openclaw/OPENCLAW_SYSTEM_ARCHITECTUR...

1033 lines
27 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# OpenClaw 系统架构设计文档
> 项目https://github.com/openclaw/openclaw
> 文档版本1.0
> 创建日期2026-02-06
---
## 目录
- [1. 概述](#1-概述)
- [2. 项目整体结构](#2-项目整体结构)
- [3. 核心架构设计](#3-核心架构设计)
- [3.1 CLI 命令系统](#31-cli-命令系统)
- [3.2 网关架构](#32-网关架构)
- [3.3 消息通道系统](#33-消息通道系统)
- [3.4 媒体管道](#34-媒体管道)
- [3.5 基础设施层](#35-基础设施层)
- [4. 关键设计模式](#4-关键设计模式)
- [4.1 依赖注入](#41-依赖注入)
- [4.2 状态管理](#42-状态管理)
- [4.3 消息路由机制](#43-消息路由机制)
- [4.4 配置系统](#44-配置系统)
- [4.5 钩子系统](#45-钩子系统)
- [5. 插件扩展机制](#5-插件扩展机制)
- [5.1 插件类型](#51-插件类型)
- [5.2 插件 API](#52-插件-api)
- [5.3 通道插件](#53-通道插件)
- [5.4 插件运行时](#54-插件运行时)
- [6. 路与会话管理](#6-路由与会话管理)
- [6.1 路由解析](#61-路由解析)
- [6.2 会话管理](#62-会话管理)
- [6.3 会话持久化](#63-会话持久化)
- [7. 模块间关系](#7-模块间关系)
- [8. 通信协议](#8-通信协议)
- [8.1 Gateway Protocol](#81-gateway-protocol)
- [8.2 ACP (Agent Client Protocol)](#82-acp-agent-client-protocol)
- [9. 认证与安全](#9-认证与安全)
- [9.1 设备配对](#91-设备配对)
- [9.2 Gateway 认证](#92-gateway-认证)
- [9.3 SSRF 防护](#93-ssrf-防护)
- [10. 测试策略](#10-测试策略)
- [11. 构建与部署](#11-构建与部署)
- [12. 编码规范](#12-编码规范)
- [13. 附录:代码示例](#13-附录代码示例)
---
## 1. 概述
OpenClaw 是一个多平台消息聚合与 AI Agent 平台,支持 WhatsApp、Telegram、Discord、Slack、Signal、iMessage 等多个消息通道,以及多种 AI 模型提供者。
### 1.1 核心特性
- **多通道支持**:通过插件化架构支持十多种消息平台
- **Gateway 架构**:集中式的 WebSocket 网关服务所有客户端
- **插件系统**:可扩展的插件机制(通道、模型提供者、内存等)
- **灵活路由**:基于绑定的智能消息路由
- **会话管理**:持久化的会话存储和历史记录
- **媒体处理**:完整的媒体上传、存储和处理管道
### 1.2 技术栈
- **语言**TypeScript (ESM)
- **运行时**Node 22+,支持 Bun
- **包管理**pnpm保持 npm 兼容性)
- **测试**Vitest + V8 覆盖率
- **Lint/Format**Oxlint + Oxfmt
- **协议**WebSocket (JSON)HTTP (REST + OpenAI 兼容)
---
## 2. 项目整体结构
### 2.1 主要目录
```
openclaw/
├── src/
│ ├── cli/ # CLI 入口和命令系统
│ ├── commands/ # 命令实现
│ ├── gateway/ # Gateway 服务器
│ ├── channels/ # 通道系统
│ ├── providers/ # AI 模型提供者
│ ├── agents/ # Agent 运行时
│ ├── media/ # 媒体管道
│ ├── infra/ # 基础设施
│ ├── config/ # 配置系统
│ ├── plugins/ # 插件系统
│ ├── plugin-sdk/ # 插件开发 SDK
│ ├── routing/ # 路由系统
│ ├── acp/ # Agent Client Protocol
│ ├── pairing/ # 设备配对
│ ├── hooks/ # 生命周期钩子
│ ├── terminal/ # 终端输出工具
│ ├── logging/ # 日志系统
│ └── ...
├── extensions/ # 扩展插件(工作区包)
├── apps/ # 移动应用和 macOS 应用
├── ui/ # Web UI (dien)
├── docs/ # 文档
├── skills/ # 内置技能
└── openclaw.mjs # CLI 入口点
```
### 2.2 程序入口
```
openclaw.mjs (编译缓存入口)
└─> src/index.ts
└─> buildProgram()
├─> createProgramContext()
└─> registerProgramCommands()
```
### 2.3 包导出
```json
{
"exports": {
".": "./dist/index.js",
"./plugin-sdk": "./dist/plugin-sdk/index.js",
"./cli-entry": "./openclaw.mjs"
}
}
```
---
## 3. 核心架构设计
### 3.1 CLI 命令系统
#### 3.1.1 命令注册表模式
CLI 基于 `commander`,采用注册表模式进行命令注册:
```typescript
// src/cli/program/command-registry.ts
export const commandRegistry: CommandRegistration[] = [
{ id: "setup", register: ({ program }) => registerSetupCommand(program) },
{ id: "onboard", register: ({ program }) => registerOnboardCommand(program) },
{ id: "config", register: ({ program }) => registerConfigCli(program) },
{ id: "memory", register: ({ program }) => registerMemoryCli(program) },
{ id: "agent", register: ({ program, ctx }) => registerAgentCommands(program, ctx) },
// ... 更多命令
];
```
#### 3.1.2 命令分类
| 类别 | 模块 | 示例命令 |
| -------- | --------------- | ------------------------------ |
| 核心命令 | `src/commands/` | `agent`, `send`, `message` |
| 配置命令 | `src/config/` | `config set/get/apply` |
| 通道命令 | Sub CLI | `channels status/login/logout` |
| Gateway | Sub CLI | `gateway run/stop` |
| Daemon | Sub CLI | `daemon start/stop` |
| 节点 | Sub CLI | `nodes list/status` |
#### 3.1.3 路由机制
```typescript
// src/cli/program/routing.ts
export type RouteSpec = {
match: (path: string[]) => boolean;
loadPlugins?: boolean; // 是否加载插件以解析命令
run: (argv: string[]) => Promise<boolean>;
};
```
路由机制允许快速解析某些命令路径,例如网关模式下直接启动而无需加载所有插件。
---
### 3.2 网关架构
#### 3.2.1 网关启动入口
```
src/gateway/server.impl.ts
└─> startGatewayServer(port, opts): Promise<GatewayServer>
```
#### 3.2.2 核心子系统
| 子系统 | 实现路径 | 职责 |
| ---------- | ------------------------------------- | --------------------- |
| 协议验证 | `src/gateway/protocol/` | Ajv 验证所有 JSON 帧 |
| 方法处理器 | `src/gateway/server-methods/` | 各个 gateway 方法实现 |
| 运行时状态 | `src/gateway/server-runtime-state.ts` | 服务器状态、缓冲区 |
| 通道管理 | `src/gateway/server-channels.ts` | 通道启停 |
| 事件处理 | `src/gateway/server-chat.ts` | Agent 事件和广播 |
| WebSocket | `src/gateway/server-ws-runtime.ts` | WS 连接和帧分发 |
| 配置重载 | `src/gateway/config-reload.ts` | 监听配置变更 |
| 启动/停止 | `src/gateway/server-close.ts` | 优雅关闭 |
| 协议定义 | `src/gateway/protocol/` | 请求/事件帧模式 |
#### 3.2.3 网关启动流程
```
startGatewayServer()
├─> 加载配置 (loadConfig)
├─> 加载插件 (loadGatewayPlugins)
│ ├─> 注册插件钩子
│ ├─> 注册通道插件
│ └─> 注册自定义 Gateway 方法
├─> 创建运行时状态 (createGatewayRuntimeState)
│ ├─> HTTP 服务器
│ ├─> WebSocket 服务器
│ ├─> Canvas Host (a2ui, 端口 18793)
│ └─> 协议验证 (AJV)
├─> 注册状态恢复
├─> 注册方法处理器 (coreGatewayHandlers + plugin 处理器)
├─> 启动通道 (startChannels)
├─> 启动 Cron 服务 (buildGatewayCronService)
├─> 配置重载监听 (startGatewayConfigReloader)
└─> 返回 GatewayServer 实例
```
#### 3.2.4 HTTP 端点
默认端口:`18789`
| 端点 | 方法 | 用途 |
| ---------------------- | --------- | ------------------ |
| `/ws` | WebSocket | 控制和事件流 |
| `/v1/gateway/*` | POST | 增量 API 方法 |
| `/v1/chat/completions` | POST | OpenAI 兼容 |
| `/v1/responses` | POST | OpenResponses 兼容 |
| `/media/*` | GET/PUT | 媒体服务 |
---
### 3.3 消息通道系统
#### 3.3.1 通道插件化
所有通道必须实现 `ChannelPlugin` 接口:
```typescript
export type ChannelPlugin<ResolvedAccount, Probe, Audit> = {
id: ChannelId;
meta: ChannelMeta;
capabilities: ChannelCapabilities;
config: ChannelConfigAdapter<ResolvedAccount>;
configSchema?: ChannelConfigSchema;
setup?: ChannelSetupAdapter;
pairing?: ChannelPairingAdapter;
security?: ChannelSecurityAdapter<ResolvedAccount>;
groups?: ChannelGroupAdapter;
mentions?: ChannelMentionAdapter;
outbound?: ChannelOutboundAdapter;
status?: ChannelStatusAdapter<ResolvedAccount, Probe, Audit>;
gatewayMethods?: string[];
gateway?: ChannelGatewayAdapter<ResolvedAccount>;
auth?: ChannelAuthAdapter;
elevated?: ChannelElevatedAdapter;
commands?: ChannelCommandAdapter;
streaming?: ChannelStreamingAdapter;
threading?: ChannelThreadingAdapter;
messaging?: ChannelMessagingAdapter;
agentPrompt?: ChannelAgentPromptAdapter;
directory?: ChannelDirectoryAdapter;
resolver?: ChannelResolverAdapter;
actions?: ChannelMessageActionAdapter;
heartbeat?: ChannelHeartbeatAdapter;
agentTools?: ChannelAgentToolFactory | ChannelAgentTool[];
};
```
#### 3.3.2 核心适配器
| 适配器 | 接口 | 职责 |
| ------------------------- | ---------------------------------- | ---------- |
| `ChannelConfigAdapter` | `listAccountIds`, `resolveAccount` | 配置解析 |
| `ChannelOutboundAdapter` | `sendText`, `sendMedia` | 消息发送 |
| `ChannelGatewayAdapter` | `startAccount`, `stopAccount` | 网关启停 |
| `ChannelStatusAdapter` | `snapshots`, `probe`, `audit` | 状态探查 |
| `ChannelGroupAdapter` | `resolveGroup` | 群组上下文 |
| `ChannelSecurityAdapter` | `resolveDMPolicy` | 安全策略 |
| `ChannelDirectoryAdapter` | `listGroups`, `listPeers` | 用户目录 |
| `ChannelAuthAdapter` | `login` | 登录流程 |
#### 3.3.3 内置通道
| 通道 | 实现目录 |
| ------------ | --------------------------- |
| WhatsApp Web | `src/web/`, `src/whatsapp/` |
| Telegram | `src/telegram/` |
| Discord | `src/discord/` |
| Slack | `src/slack/` |
| Signal | `src/signal/` |
| iMessage | `src/imessage/` |
| LINE | `src/line/` |
| Google Chat | `src/googlechat/` |
| MS Teams | `src/msteams/` |
#### 3.3.4 扩展通道
位于 `extensions/*/`
- `bluebubbles` / `matrix` / `msteams` (extension)
- `tton` / `zalo` / `zalouser`
- `nostr` / `mattermost`
- `nextcloud-talk` / `feishu`
---
### 3.4 媒体管道
#### 3.4.1 核心组件
| 文件 | 职责 |
| -------------- | -------------------------------------------- |
| `mime.ts` | MIME 类型检测magic number + content type |
| `parse.ts` | 消息媒介提取(文本、图片、音频等) |
| `store.ts` | 磁盘存储,文件命名 `{original}---{uuid}.ext` |
| `fetch.ts` | HTTP/HTTPS 远程获取 |
| `host.ts` | HTTP 服务,鉴权和 Headers |
| `image-ops.ts` | 图片调整大小 (JPEG) |
| `audio.ts` | 音频转换、兼容性检查 |
| `server.ts` | HTTP 服务配置 |
#### 3.4.2 存储结构
```
~/.openclaw/media/
├── inbound/ # 接收的媒体
└── outbound/ # 发送的媒体
```
#### 3.4.3 媒体处理流程
```
入站:
消息媒介提取
MIME 检测 (magic number)
保存到磁盘 (store.ts)
生成内部 URL
出站:
媒体上传/处理
MIME 检测
压缩/转换 (可选)
保存到磁盘
通过 HTTP 端点服务
```
---
### 3.5 基础设施层
#### 3.5.1 端口管理
`src/infra/ports.ts`
| 功能 | 说明 |
| -------------------------- | ------------------ |
| `checkPortAvailability` | 检查端口是否可用 |
| `killPortOccupyingProcess` | 杀死占用端口的进程 |
| `autoDetectAvailablePort` | 自动检测可用端口 |
| `DEFAULT_PORT` | 默认端口 18789 |
#### 3.5.2 SSRF 防护
`src/infra/net/ssrf.ts`
解析主机名并验证是否为安全的内部地址。
#### 3.5.3 事件系统
| 表件 | 事件类型 |
| ---------------------- | ------------ |
| `diagnostic-events.ts` | 诊断事件 |
| `heartbeat-events.ts` | 心跳事件 |
| `system-events.ts` | 系统事件队列 |
| `channel-activity.ts` | 通道活动跟踪 |
#### 3.5.4 出站传送
`src/infra/outbound/deliver.ts`
支持三种传送模式:
- `single` - 单通道
- `gateway` - 通过网关
- `mixed` - 混合模式
---
## 4. 关键设计模式
### 4.1 依赖注入
#### 4.1.1 CLI 依赖
```typescript
// src/cli/deps.ts
export type CliDeps = {
sendMessageWhatsApp: typeof sendMessageWhatsApp;
sendMessageTelegram: typeof sendMessageTelegram;
sendMessageDiscord: typeof sendMessageDiscord;
sendMessageSlack: typeof sendMessageSlack;
sendMessageSignal: typeof sendMessageSignal;
sendMessageIMessage: typeof sendMessageIMessage;
};
export function createDefaultDeps(): CliDeps {
return {
sendMessageWhatsApp,
sendMessageTelegram,
sendMessageDiscord,
sendMessageSlack,
sendMessageSignal,
sendMessageIMessage,
};
}
```
#### 4.1.2 插件运行时依赖
```typescript
// src/plugins/runtime/types.ts
export type PluginRuntime = {
version: string;
config: { loadConfig, writeConfigFile };
system: { enqueueSystemEvent, runCommandWithTimeout };
media: { loadWebMedia, detectMime, mediaKindFromMime, ... };
tts: { textToSpeechTelephony };
tools: { createMemoryGetTool, createMemorySearchTool, ... };
channel: {
text: { chunkByNewline, chunkMarkdownText, ... };
reply: { dispatchReplyWithBufferedBlockDispatcher, ... };
routing: { resolveAgentRoute };
pairing: { buildPairingReply, ... };
network: { fetchRemoteMedia, saveMediaBuffer };
activity: { record, get };
session: { resolveStorePath, ... };
// 各通道特定函数...
};
logging: { shouldLogVerbose, getChildLogger };
state: { resolveStateDir };
};
```
---
### 4.2 状态管理
#### 4.2.1 配置状态
```typescript
// 配置加载流程
loadConfig() parseConfigJson5() validateConfigObject() migrateLegacyConfig()
```
配置文件位置:`~/.openclaw/config.json5`
#### 4.2.2 配置监听和重载
`src/gateway/config-reload.ts`
监听配置文件变更,触发网关状态更新。
#### 4.2.3 通道状态
```typescript
// src/gateway/server-channels.ts
type ChannelRuntime = {
id: string;
accountId: string;
status: Snapshot;
stop?: () => Promise<void>;
// ...
};
```
#### 4.2.4 会话状态
会话存储位置:`~/.openclaw/sessions/{channel}/{accountId}/{session}.jsonl`
会话键格式:`session/{agentId}/{channel}/{accountId}/{peer}`
---
### 4.3 消息路由机制
#### 4.3.1 路由解析
```typescript
// src/routing/resolve-route.ts
export type ResolveAgentRouteInput = {
cfg: OpenClawConfig;
channel: string;
accountId?: string | null;
peer?: RoutePeer | null;
parentPeer?: RoutePeer | null;
guildId?: string | null;
teamId?: string | null;
};
export type ResolvedAgentRoute = {
agentId: string;
channel: string;
accountId: string;
sessionKey: string;
mainSessionKey: string;
matchedBy:
| "binding.peer"
| "binding.peer.parent"
| "binding.guild"
| "binding.team"
| "binding.account"
| "binding.channel"
| "default";
};
```
#### 4.3.2 路由匹配优先级
```
1. peer (具体用户/组)
2. thread parent peer (继承)
3. guildId (Discord 服务器)
4. teamId (Slack/Teams)
5. account (非通配符)
6. account (通配符)
7. default (默认代理)
```
#### 4.3.3 会话键构建
```typescript
// src/routing/session-key.ts
export function buildAgentSessionKey(params: {
agentId: string;
channel: string;
accountId?: string | null;
peer?: RoutePeer | null;
dmScope?: "main" | "per-peer" | "per-channel-peer" | "per-account-channel-peer";
identityLinks?: Record<string, string[]>;
}): string;
```
---
### 4.4 配置系统
#### 4.4.1 配置模块
```
src/config/
├── types.agent-defaults.ts
├── types.agents.ts
├── types.auth.ts
├── types.base.ts
├── types.browser.ts
├── types.channels.ts
├── types.openclaw.ts
├── types.cron.ts
├── types.sandbox.ts
├── types.memory.ts
├── types.models.ts
├── types.node-host.ts
├── types.tts.ts
├── types.tools.ts
├── types.whatsapp.ts
├── types.imessage.ts
├── types.slack.ts
├── ... (更多通道配置)
├── config.ts (主导出)
└── ...
```
#### 4.4.2 验证机制
使用 Zod 进行模式验证:
```typescript
validateConfigObject(config): ValidationResult
validateConfigObjectWithPlugins(config, plugins): ValidationResult
```
#### 4.4.3 配置迁移
`migrateLegacyConfig()` - 处理旧配置版本的自动迁移。
---
### 4.5 钩子系统
#### 4.5.1 钩子类型
```typescript
// src/hooks/types.ts
export type HookEntry = {
name: string;
handler: HookHandler;
priority?: number;
};
export type HookEvent =
| "before_agent_start"
| "after_agent_start"
| "before_message_send"
| "after_message_send"
| "message_received"
| "tool_called"
| "config_changed"
// ... 更多钩子
};
```
#### 4.5.2 钩子注册方式
- 插件通过 `api.registerHook()` 注册
- 优先级按 `priority` 数值排序
---
## 5. 插件扩展机制
### 5.1 插件类型
| 类型 | 说明 | 示例 |
| ---------- | ----------------- | ---------------------- |
| `memory` | 内存/向量存储插件 | LanceDB |
| `channel` | 通道插件 | Matrix, Zalo |
| `provider` | 模型提供者插件 | 自定义 OpenAI 兼容 API |
### 5.2 插件 API
```typescript
// src/plugins/types.ts
export type OpenClawPluginDefinition = {
id?: string;
name?: string;
description?: string;
version?: string;
kind?: PluginKind; // "channel" | "memory" | "provider" | ...
configSchema?: OpenClawPluginConfigSchema;
register?: (api: OpenClawPluginApi) => void | Promise<void>;
activate?: (api: OpenClawPluginApi) => void | Promise<void>;
};
```
### 5.3 通道插件
参见 [3.3.1 节](#331-通道插件化)。
### 5.4 插件运行时
插件通过 `OpenClawPluginApi.runtime` 访问运行时 API参见 [4.1.2 节](#412-插件运行时依赖)。
---
## 6. 路由与会话管理
### 6.1 路由解析
详见 [4.3.1 节](#431-路由解析)。
### 6.2 会话结构
```
~/.openclaw/sessions/
└── {channel}/
└── {accountId}/
└── {session}.jsonl (JSONL 格式)
```
每行包含:
- `role`: "user" | "assistant"
- `content`: 消息内容
- `timestamp`: 时间戳
- `meta`: 元数据
### 6.3 会话 API
```typescript
loadSessionStore(sessionPath): Promise<Session>
saveSessionStore(sessionPath, session): Promise<void>
updateLastRoute(channel, accountId, route): Promise<void>
```
---
## 7. 模块间关系
### 7.1 CLI 层
```
openclaw.mjs
└─> src/index.ts
├─> createDefaultDeps()
├─> buildProgram()
│ ├─> createProgramContext()
│ └─> registerProgramCommands()
│ ├─> registerSetupCommand()
│ ├─> registerOnboardCommand()
│ ├─> registerConfigCli()
│ ├─> registerAgentCommands()
│ ├─> registerSubCliCommands()
│ └─> ...
└─> 程序解析 → 各命令处理器
```
### 7.2 Gateway 层
```
startGatewayServer()
├─> 配置加载 (loadConfig)
├─> 插件加载 (loadGatewayPlugins)
│ ├─> 插件注册表
│ └─> 通道插件 (listChannelPlugins)
├─> 运行时状态 (createGatewayRuntimeState)
│ ├─> HTTP 服务器
│ ├─> WebSocket 服务器
│ ├─> Canvas Host (a2ui)
│ └─> 协议验证 (AJV)
├─> 方法处理器
├─> 事件广播
├─> 通道管理器
├─> Cron 服务
├─> 节点注册
└─> 配置重载
```
### 7.3 消息流转
```
入站:
平台消息 → 通道适配器 → Gateway 事件 → 路由解析 → Agent 执行 → 出站
出站:
CLI/Web/App → Gateway 方法 → 根据路由分发 → 通道适配器 → 平台
```
---
## 8. 通信协议
### 8.1 Gateway Protocol
详见 `docs/concepts/architecture.md``docs/gateway/protocol.md`
核心帧类型:
```typescript
export type GatewayFrame =
| RequestFrame // {type:"req", id, method, params}
| ResponseFrame // {type:"res", id, ok, payload|error}
| EventFrame; // {type:"event", event, payload, seq?, stateVersion?}
```
#### 事件类型
- `agent` - Agent 执行事件
- `chat` - 聊天更新
- `presence` - 在线状态
- `health` - 健康状态
- `heartbeat` - 心跳
- `cron` - Cron 任务
- `tick` - 定时脉冲
#### 常用 Gateway 方法
| 方法 | 功能 |
| ----------------- | ------------ |
| `health` | 健康检查 |
| `status` | 状态查询 |
| `send` | 发送消息 |
| `agent` | 启动 Agent |
| `channels.list` | 列出通道账户 |
| `channels.status` | 通道状态 |
| `channels.login` | 通道登录 |
### 8.2 ACP (Agent Client Protocol)
位于 `src/acp/`,用于 Agent 与客户端的通信。
---
## 9. 认证与安全
### 9.1 设备配对
新建设备 ID 需要配对批准:
- 本地连接:自动批准
- 远程连接:需要显式批准
- 挑战签名:防止劫持
设备令牌存储在 `~/.openclaw/device-tokens.json`
### 9.2 Gateway 认证
```typescript
// src/config/auth.ts
export type GatewayAuth = {
token?: string; // Bearer Token 检查
allowed?: string[]; // 允许的设备 ID
};
```
### 9.3 SSRF 防护
`src/infra/net/ssrf.ts` - 防止服务器端请求伪造。
---
## 10. 测试策略
### 10.1 测试框架
- **框架**Vitest
- **覆盖率**V8
- **阈值**70% (线/分/函数/语句)
### 10.2 测试类型
| 类型 | 后缀 | 说明 |
| -------- | --------------- | ------------ |
| 单元测试 | `*.test.ts` | 功能单元测试 |
| E2E 测试 | `*.e2e.test.ts` | 端到端测试 |
### 10.3 测试命令
```bash
pnpm test # 运行所有测试
pnpm test:coverage # 运行测试并生成覆盖率报告
pnpm test:live # 运行 Live 测试 (需要真实凭证)
```
---
## 11. 构建与部署
### 11.1 构建命令
```bash
pnpm build # 完整构建
pnpm tsgo # TypeScript 类型检查
pnpm check # Lint + Format
```
### 11.2 macOS 应用打包
```bash
scripts/package-mac-app.sh
```
### 11.3 发布流程
详解见 `docs/platforms/mac/release.md``docs/reference/RELEASING.md`
发布通道:
- **stable**: 版本标签 (v2026.2.4) + npm tag `latest`
- **beta**: 预发布标签 (v2026.2.4-beta.N) + npm tag `beta`
- **dev**: main 分支头部 (无标签)
---
## 12. 编码规范
### 12.1 语言与风格
- **语言**TypeScript (ESM)
- **严格类型**:避免 `any`
- **格式化**Oxlint + Oxfmt
- **文件大小**:目标 < ~700 LOC
### 12.2 命名规范
- **产品/文档标题**OpenClaw (大写)
- **CLI 命令**openclaw (小写)
- **包/二进制名**openclaw (小写)
- **配置键**openclaw (小写)
### 12.3 代码注释
为复杂或非显而易见的逻辑添加简短注释。
### 12.4 终端输出
- **进度条**`src/cli/progress.ts` (osc-progress + @clack/prompts)
- **表格**`src/terminal/table.ts` (ANSI 安全换行)
### 12.5 多 Agent 安全
- 不创建/应用/删除 git stash 除非明确要求
- 不删除/修改 git worktree 除非明确要求
- 尊重其他 Agent 的工作
---
## 13. 附录:代码示例
### 13.1 注册插件钩子
```typescript
export default function register(api: OpenClawPluginApi) {
api.on("before_agent_start", async (event, ctx) => {
console.log("Agent starting:", ctx.agentId);
return {
systemPrompt: "Custom system prompt...",
prependContext: "Extended context...\n",
};
});
api.on("message_received", async (event, ctx) => {
console.log("Received:", event.content);
});
}
```
### 13.2 注册自定义命令
```typescript
api.registerCommand({
name: "tts",
description: "Text to speech",
acceptsArgs: true,
requireAuth: true,
handler: async (ctx) => {
const text = ctx.args || "";
// ... 处理 tts 并回复
return { text: `Speaking: ${text}` };
},
});
```
### 13.3 注册通道
```typescript
api.registerChannel({
id: "mychannel" as ChannelId,
meta: {
id: "mychannel" as ChannelId,
label: "My Channel",
selectionLabel: "My Channel",
docsPath: "/channels/mychannel",
blurb: "My custom channel implementation",
},
capabilities: {
chatTypes: ["dm", "group"],
media: true,
reactions: true,
reply: true,
},
config: {
listAccountIds: (cfg) => Object.keys(cfg.mychannel?.accounts ?? {}),
resolveAccount: (cfg, accountId) => cfg.mychannel?.accounts?.[accountId] ?? {},
defaultAccountId: (cfg) => "default",
},
outbound: {
deliveryMode: "gateway",
sendText: async (ctx) => {
// 发送文本到平台
return { ok: true };
},
},
gatewayMethods: ["mychannel.send"],
gateway: {
startAccount: async (ctx) => {
// 启动通道监听器
},
stopAccount: async (ctx) => {
// 停止通道监听器
},
},
});
```
### 13.4 使用插件 SDK
```typescript
import {
registerTool,
resolveAgentRoute,
loadConfig,
dispatchReplyWithBufferedBlockDispatcher,
} from 'openclaw/plugin-sdk';
export default function register(api: OpenClawPluginApi) {
const tool = {
type: 'function',
name: 'mytool',
description: 'My custom tool',
parameters: {
type: 'object',
properties: {},
additionalProperties: false,
},
handler: async ({ accountId, messageChannel, agentId, ... }) => {
// 处理工具
return {
success: true,
content: [],
data: undefined,
};
},
};
api.registerTool(tool);
}
```
---
## 参考资料
- [Gateway Architecture](/docs/concepts/architecture.md)
- [Gateway Protocol](/docs/gateway/protocol.md)
- [提交 PR 指南](/docs/help/submitting-a-pr.md)
- [提交 Issue 指南](/docs/help/submitting-an-issue.md)
- [测试文档](/docs/testing.md)
- [发布文档](/docs/reference/RELEASING.md)
- [macOS 发布](/docs/platforms/mac/release.md)
---
**文档结束**