Skip to content

依赖注入

OpenClaw CLI 使用简洁的依赖注入模式,通过 CliDeps 接口将通道发送函数和其他基础设施能力注入到命令中。

CliDeps 接口

Source: src/cli/deps.ts

typescript
// src/cli/deps.ts (simplified)
interface CliDeps {
  sendMessageWhatsApp: SendFunction;
  sendMessageTelegram: SendFunction;
  sendMessageDiscord: SendFunction;
  sendMessageSlack: SendFunction;
  sendMessageSignal: SendFunction;
  sendMessageIMessage: SendFunction;
}

CliDeps 是一个简单的接口,包含所有通道的发送函数。

创建依赖

typescript
// src/cli/deps.ts (simplified)
function createDefaultDeps(): CliDeps {
  return {
    sendMessageWhatsApp: createWhatsAppSender(),
    sendMessageTelegram: createTelegramSender(),
    sendMessageDiscord: createDiscordSender(),
    sendMessageSlack: createSlackSender(),
    sendMessageSignal: createSignalSender(),
    sendMessageIMessage: createIMessageSender(),
  };
}

createDefaultDeps() 工厂函数创建所有通道发送器的具体实现。

桥接到基础设施层

Source: src/cli/deps.ts

typescript
// Bridging CLI deps to infra layer
function createOutboundSendDeps(deps: CliDeps): OutboundSendDeps {
  return {
    sendWhatsApp: deps.sendMessageWhatsApp,
    sendTelegram: deps.sendMessageTelegram,
    sendDiscord: deps.sendMessageDiscord,
    sendSlack: deps.sendMessageSlack,
    sendSignal: deps.sendMessageSignal,
    sendIMessage: deps.sendMessageIMessage,
  };
}

桥接函数将 CLI 层的 CliDeps 转换为基础设施层的 OutboundSendDeps,字段名可能不同但功能一致。

为什么使用依赖注入?

  1. 可测试性 — 测试中可以注入 mock 发送函数
  2. 解耦 — CLI 命令不直接依赖具体的通道 SDK
  3. 灵活性 — 可以替换实现而不修改命令代码
  4. 一致性 — 所有命令通过统一接口访问通道能力

测试示例

typescript
// In tests, inject mock dependencies
const mockDeps: CliDeps = {
  sendMessageTelegram: vi.fn().mockResolvedValue({ messageId: 1 }),
  sendMessageDiscord: vi.fn().mockResolvedValue({ messageId: 2 }),
  // ...
};

// Command uses injected deps
await sendCommand(mockDeps, { to: "123", message: "test" });

// Verify mock was called
expect(mockDeps.sendMessageTelegram).toHaveBeenCalledWith(/* ... */);

小结

  • CliDeps 接口包含所有通道的发送函数
  • createDefaultDeps() 创建具体实现
  • createOutboundSendDeps() 桥接到基础设施层
  • 依赖注入提供 可测试性解耦灵活性

下一章:媒体处理

OpenClaw 源码学习教程