Compare commits

..

No commits in common. "main_sync" and "main" have entirely different histories.

7 changed files with 1 additions and 29231 deletions

View File

@ -3,25 +3,6 @@
- Repo: https://github.com/openclaw/openclaw
- GitHub issues/comments/PR comments: use literal multiline strings or `-F - <<'EOF'` (or $'...') for real newlines; never embed "\\n".
## Quick Reference
**Build & Test:**
```bash
pnpm build # Type-check and build
pnpm check # Run all checks (tsgo + lint + format)
pnpm test # Run all unit tests
pnpm test:coverage # Run tests with coverage report
vitest run path/to/file.test.ts # Run single test file
vitest run -t "test name" # Run tests matching pattern
```
**Dev Commands:**
```bash
pnpm openclaw ... # Run CLI in dev mode
pnpm gateway:watch # Auto-reload gateway on changes
pnpm dev # Run node in dev mode
```
## Project Structure & Module Organization
- Source code: `src/` (CLI wiring in `src/cli`, commands in `src/commands`, web provider in `src/provider-web.ts`, infra in `src/infra`, media pipeline in `src/media`).
@ -86,50 +67,10 @@ pnpm dev # Run node in dev mode
- Language: TypeScript (ESM). Prefer strict typing; avoid `any`.
- Formatting/linting via Oxlint and Oxfmt; run `pnpm check` before commits.
- Add brief code comments for tricky or non-obvious logic.
- Keep files concise; extract helpers instead of "V2" copies. Use existing patterns for CLI options and dependency injection via `createDefaultDeps`.
- Keep files concise; extract helpers instead of “V2” copies. Use existing patterns for CLI options and dependency injection via `createDefaultDeps`.
- Aim to keep files under ~700 LOC; guideline only (not a hard guardrail). Split/refactor when it improves clarity or testability.
- Naming: use **OpenClaw** for product/app/docs headings; use `openclaw` for CLI command, package/binary, paths, and config keys.
### Import Style
- Group imports: Node.js built-ins → external packages → local modules
- Use `node:` prefix for built-in modules: `import fs from "node:fs";`
- Always use `.js` extensions for local imports: `import { foo } from "./utils.js";`
- Type-only imports: use `import type { ... }` when importing only types
### Type Definitions
- Prefer `type` over `interface` for most cases
- Use strict typing; avoid `any` - use `unknown` and narrow with type guards instead
- Export types that may be needed by other modules
- Use TypeBox (`@sinclair/typebox`) for runtime validation schemas
- Function return types: explicit when non-obvious, inferred for simple functions
### Error Handling
- Prefer explicit error handling over silent failures
- Use try/catch for async operations that may fail
- Create descriptive error messages with context
- For expected errors, throw with meaningful messages
- Log errors at appropriate levels using the tslog logger
### Naming Conventions
- **Files**: kebab-case (e.g., `agent-paths.ts`, `session-key.ts`)
- **Test files**: `*.test.ts` (colocated), `*.e2e.test.ts` (e2e tests), `*.live.test.ts` (live integration tests)
- **Functions**: camelCase (e.g., `resolveOpenClawAgentDir`, `ensureDir`)
- **Classes**: PascalCase (e.g., `SessionManager`)
- **Constants**: SCREAMING_SNAKE_CASE for true constants (e.g., `DEFAULT_AGENT_ID`)
- **Types/Interfaces**: PascalCase (e.g., `JidToE164Options`)
- **Variables**: camelCase (e.g., `tempStateDir`, `normalizedSelf`)
### Documentation & Comments
- Add JSDoc for public APIs and exported functions
- Use inline comments for complex logic or non-obvious code
- Keep comments concise and focused on "why" rather than "what"
- Document function parameters and return types when non-obvious
## Release Channels (Naming)
- stable: tagged releases only (e.g. `vYYYY.M.D`), npm dist-tag `latest`.

View File

@ -1,812 +0,0 @@
# OpenClaw 架构蓝图
> 完整的系统架构可视化
---
## 1. 整体系统架构
```mermaid
graph TB
subgraph "客户端层 Clients"
APP1[macOS App]
APP2[iOS App]
APP3[Android App]
UI[Web UI]
CLI[CLI Tool]
NODES[Nodes<br/>macOS/iOS/Android]
end
subgraph "网关层 Gateway (18789)"
WS[WebSocket Server]
HTTP[HTTP Server]
PROTO[Protocol Validator<br/>AJV]
CHANNELS[Channel Manager]
EVENTS[Event Dispatcher]
METHODS[Method Handlers]
CRON[Cron Service]
CANVAS["Canvas Host<br/>a2ui (18793)"]
end
subgraph "通道层 Channels"
WA[WhatsApp Web<br/>Baileys]
TG[Telegram<br/>grammY]
DC[Discord]
SL[Slack]
SG[Signal]
IM[iMessage]
LN[LINE]
GO[Google Chat]
MS[MS Teams]
EXT[Extensions<br/>Matrix/Zalo/etc]
end
subgraph "Agent 层"
ROUTER[Message Router<br/>Bindings]
SESSION[Session Manager]
AGENT[Agent Runtime]
TOOLS[Tool Execution]
MEMORY[Memory Store]
PROVIDERS[Model Providers<br/>OpenAI/Anthropic/etc]
end
subgraph "基础设施层Infrastructure"
MEDIA[Media Pipeline<br/>Store/Fetch/Process]
CONFIG[Config System<br/>JSON5/Zod]
PAIRING[Device Pairing]
AUTH[Authentication]
LOGS[Logging System]
DIAG[Diagnostic Events]
end
subgraph "扩展层Plugins"
PLUGINSDK[Plugin SDK]
CHANNEL_PLG[Channel Plugins]
MEMORY_PLG[Memory Plugins]
PROVIDER_PLG[Provider Plugins]
HOOKS[Lifecycle Hooks]
end
%% 连接关系
APP1 -->|WebSocket| WS
APP2 -->|WebSocket| WS
APP3 -->|WebSocket| WS
UI -->|WebSocket| WS
CLI -->|WebSocket| WS
NODES -->|WebSocket| WS
WS --> PROTO
PROTO --> METHODS
PROTO --> EVENTS
HTTP --> METHODS
METHODS --> CHANNELS
METHODS --> ROUTER
METHODS --> CONFIG
METHODS --> MEDIA
CHANNELS --> WA
CHANNELS --> TG
CHANNELS --> DC
CHANNELS --> SL
CHANNELS --> SG
CHANNELS --> IM
CHANNELS --> LN
CHANNELS --> GO
CHANNELS --> MS
CHANNELS --> EXT
CHANNELS -.->|事件| EVENTS
EVENTS -.->|广播| WS
CRON -.->|触发| EVENTS
WA -->|入站| CHANNELS
TG -->|入站| CHANNELS
DC -->|入站| CHANNELS
SL -->|入站| CHANNELS
SG -->|入站| CHANNELS
IM -->|入站| CHANNELS
LN -->|入站| CHANNELS
GO -->|入站| CHANNELS
MS -->|入站| CHANNELS
EXT -->|入站| CHANNELS
CHANNELS -->|路由| ROUTER
ROUTER --> AGENT
AGENT --> TOOLS
AGENT --> MEMORY
AGENT --> PROVIDERS
AGENT -->|出站| CHANNELS
AGENT -.->|事件| EVENTS
SESSION -->|持久化| ROUTER
METHODS --> MEDIA
CONFIG -->|加载| CHANNELS
CONFIG -->|加载| ROUTER
WS --> AUTH
PAIRING --> AUTH
LOGS -->| everywhere | *
DIAG -->| everywhere | *
PLUGINSDK --> CHANNEL_PLG
PLUGINSDK --> MEMORY_PLG
PLUGINSDK --> PROVIDER_PLG
CHANNEL_PLG --> CHANNELS
MEMORY_PLG --> MEMORY
PROVIDER_PLG --> PROVIDERS
HOOKS --> AGENT
HOOKS --> CHANNELS
HOOKS --> EVENTS
style Gateway fill:#e1f5fe
style Clients fill:#f3e5f5
style Channels fill:#fff3e0
style Agent fill:#e8f5e9
style Infrastructure fill:#fce4ec
style Plugins fill:#fff9c4
```
---
## 2. Gateway 详细架构
```mermaid
graph TB
subgraph "Gateway Server端口 18789"
ENTER[客户端连接] --> WS_CONN
subgraph "WebSocket 层"
WS_CONN[WebSocket Server]
WS_HANDLER[WS Handler]
FRAME_PARSER[Frame Parser]
FRAME_VALIDATOR[Frame Validator<br/>JSON Schema]
end
subgraph "连接管理 Connect Management"
HELLO[req:connect]
AUTH_CHECK[Auth Check<br/>Token Check]
PAIRING_CHECK[Pairing Check<br/>Device Approval]
CLIENT_REGISTRY[Client Registry]
end
subgraph "方法层 Method Layer"
METHOD_DISPATCH[Method Dispatcher]
CORE_HANDLERS[Core Handlers<br/>health/status/send/agent]
GATEWAY_METHODS[Gateway Methods<br/>channels.* / media.*]
PLUGIN_METHODS[Plugin Methods]
end
subgraph "状态层 State Layer"
RUNTIME_STATE[Runtime State<br/>健康查看 / 缓冲]
CHANNEL_STATE[Channel State<br/>运行时实例]
NODE_REGISTRY[Node Registry]
end
subgraph "事件层 Event Layer"
EVENT_EMITTER[Event Emitter]
AGENT_EVENTS[agent Events]
CHAT_EVENTS[chat Events]
PRESENCE_EVENTS[presence Events]
HEARTBEAT[heartbeat Events]
DIAGNOSTICS[diagnostic Events]
end
subgraph "资源层 Resource Layer"
CONFIG_RELOAD[Config Reloader]
CHANNEL_MANAGER[Channel Manager]
CANVAS_HOST[Canvas Host<br/>a2ui:18793]
MEDIA_SERVER[Media Server]
CRON_SCHEDULER[Cron Scheduler]
end
end
%% 连接关系
WS_CONN --> WS_HANDLER
WS_HANDLER --> FRAME_PARSER
FRAME_PARSER --> FRAME_VALIDATOR
FRAME_VALIDATOR --> HELLO
FRAME_VALIDATOR --> METHOD_DISPATCH
HELLO --> AUTH_CHECK
AUTH_CHECK --> PAIRING_CHECK
PAIRING_CHECK --> CLIENT_REGISTRY
CLIENT_REGISTRY --> RUNTIME_STATE
METHOD_DISPATCH --> CORE_HANDLERS
METHOD_DISPATCH --> GATEWAY_METHODS
METHOD_DISPATCH --> PLUGIN_METHODS
CORE_HANDLERS -->|使用| RUNTIME_STATE
CORE_HANDLERS -->|使用| CHANNEL_STATE
CORE_HANDLERS -->|使用| CHANNEL_MANAGER
GATEWAY_METHODS --> CHANNEL_MANAGER
GATEWAY_METHODS --> MEDIA_SERVER
GATEWAY_METHODS --> NODE_REGISTRY
CHANNEL_MANAGER --> CHANNEL_STATE
CHANNEL_MANAGER -->|启动/停止| WA_SVC
CHANNEL_MANAGER -->|启动/停止| TG_SVC
CHANNEL_MANAGER -->|启动/停止| DC_SVC
RLGA_EVENTS -.->|广播| WS_HANDLER
HEARTBEAT -.->|广播| WS_HANDLER
DIAGNOSTICS -.->|广播| WS_HANDLER
CONFIG_RELOAD -.->|通知| CORE_HANDLERS
CONFIG_RELOAD -.->|通知| CHANNEL_MANAGER
CRON_SCHEDULER -.->|触发| EVENT_EMITTER
CRON_SCHEDULER -.->|触发| CANVAS_HOST
subgraph "外部服务 External Services"
WA_SVC[WhatsApp Service]
TG_SVC[Telegram Service]
DC_SVC[Discord Service]
end
style GatewayServer fill:#e1f5fe
style WebSocket层 fill:#e3f2fd
style MethodLayer fill:#bbdefb
style StateLayer fill:#90caf9
style EventLayer fill:#64b5f6
style ResourceLayer fill:#42a5f5
style ExternalServices fill:#ffecb3
```
---
## 3. 消息流转图 Message Flow
```mermaid
sequenceDiagram
participant USER as 用户
participant CH as 通道通道<br/>WhatsApp/Telegram/etc
participant GATEWAY as Gateway
participant ROUTER as Message Router
participant AGENT as Agent Runtime
participant PROVIDER as AI Provider
participant TOOLS as Tools
%% 入站消息流
USER->>CH: 发送消息
CH->>GATEWAY: 接入事件
GATEWAY->>ROUTER: 解析路由<br/>(channel/account/peer)
ROUTER-->>GATEWAY: 返回匹配结果<br/>(agentId, sessionKey)
GATEWAY->>AGENT: 调用 agent.execute
AGENT->>AGENT: 加载会话历史
AGENT->>AGENT: 构建系统提示
AGENT->>PROVIDER: 发起 LLM 调用
alt 需要工具调用
PROVIDER-->>AGENT: 返回 tool_calls
AGENT->>TOOLS: 执行工具
TOOLS-->>AGENT: 返回工具结果
AGENT->>PROVIDER: 继续调用 (with tool results)
end
PROVIDER-->>AGENT: 返回完整响应
AGENT->>AGENT: 更新会话历史
AGENT-->>GATEWAY: 返回响应 (events: agent)
GATEWAY->>CH: 发送消息 (channel.message.send)
CH->>USER: 接收回复
%% 出站消息流 (CLI/Web/App 触发)
rect rgb(255, 255, 200)
Note over GATEWAY,USER: 出站消息流 (从客户端触发)
USER->>GATEWAY: 调用 gateway.send
GATEWAY->>ROUTER: 解析路由
ROUTER-->>GATEWAY: 返回匹配结果
GATEWAY->>CH: 发送消息
CH->>USER: 接收消息
end
```
---
## 4. 插件系统架构 Plugin System
```mermaid
graph TB
subgraph "插件 API Plugin SDK"
API[OpenClawPluginApi]
end
subgraph "插件运行时 Plugin Runtime"
RUNTIME[Plugin Runtime]
CONFIG_API[Config API<br/>loadConfig/writeConfigFile]
SYSTEM_API[System API<br/>enqueueSystemEvent]
MEDIA_API[Media API<br/>loadWebMedia/detectMime]
TTS_API[TTS API<br/>textToSpeechTelephony]
TOOLS_API[Tools API<br/>createMemoryGetTool]
CHANNEL_API[Channel API<br/>routing/network/session]
LOGGING_API[Logging API<br/>getChildLogger]
end
subgraph "注册接口 Registrations"
REG_TOOL[registerTool]
REG_HOOK[registerHook]
REG_HTTP[registerHttpRoute/registerHttpHandler]
REG_CHANNEL[registerChannel]
REG_GW_METHOD[registerGatewayMethod]
REG_CLI[registerCli]
REG_SERVICE[registerService]
REG_PROVIDER[registerProvider]
REG_CMD[registerCommand]
end
subgraph "钩子系统 Hook System"
H_BEFORE_AGENT[before_agent_start]
H_AFTER_AGENT[after_agent_start]
H_BEFORE_SEND[before_message_send]
H_AFTER_SEND[after_message_send]
H_RECEIVED[message_received]
H_TOOL[tool_called]
H_CONFIG[config_changed]
end
subgraph "插件类型 Plugin Types"
P_CHANNEL[Channel Plugin<br/>must implement ChannelPlugin]
P_MEMORY[Memory Plugin<br/>LanceDB/etc]
P_PROVIDER[Provider Plugin<br/>Custom AI API]
end
subgraph "插件生命周期 Plugin Lifecycle"
LOAD[loadPlugin]
VALIDATE[validateConfig]
REGISTER[register]
ACTIVATE[activate]
DISPOSE[dispose]
end
%% 连接关系
API --> RUNTIME
RUNTIME --> CONFIG_API
RUNTIME --> SYSTEM_API
RUNTIME --> MEDIA_API
RUNTIME --> TTS_API
RUNTIME --> TOOLS_API
RUNTIME --> CHANNEL_API
RUNTIME --> LOGGING_API
API --> REG_TOOL
API --> REG_HOOK
API --> REG_HTTP
API --> REG_CHANNEL
API --> REG_GW_METHOD
API --> REG_CLI
API --> REG_SERVICE
API --> REG_PROVIDER
API --> REG_CMD
REG_HOOK --> H_BEFORE_AGENT
REG_HOOK --> H_AFTER_AGENT
REG_HOOK --> H_BEFORE_SEND
REG_HOOK --> H_AFTER_SEND
REG_HOOK --> H_RECEIVED
REG_HOOK --> H_TOOL
REG_HOOK --> H_CONFIG
REG_CHANNEL --> P_CHANNEL
LOAD --> VALIDATE
VALIDATE --> REGISTER
REGISTER --> ACTIVATE
ACTIVATE --> DISPOSE
P_CHANNEL -.->|loose coupling| H_RECEIVED
P_CHANNEL -.->|loose coupling| H_BEFORE_SEND
style PluginSDK fill:#fff9c4
style PluginRuntime fill:#fff59d
style Registrations fill:#ffee58
style HookSystem fill:#fdd835
style PluginTypes fill:#fbc02d
style PluginLifecycle fill:#f9a825
```
---
## 5. 路与绑定系统 Routing & Bindings
```mermaid
graph TD
subgraph "路由输入 Route Input"
CFG[User Config<br/>bindings 数组]
IN_CHANNEL[channel<br/>消息来源]
IN_ACCOUNT[accountId<br/>账户 ID]
IN_PEER[peer<br/>用户/组 ID]
IN_GUILD[guildId<br/>Discord 服务器]
IN_TEAM[teamId<br/>Slack/Teams]
end
subgraph "路由匹配优先级 Matching Priority"
P1[1. peer<br/>具体用户/组]
P2[2. peer.parent<br/>线程继承]
P3[3. guildId<br/>Discord 服务器]
P4[4. teamId<br/>Slack/Teams]
P5[5. account<br/>非通配符账户]
P6[6. account<br/>通配符账户]
P7[7. default<br/>默认绑定]
end
subgraph "路由输出 Route Output"
AGENT_ID[agentId<br/>目标 Agent]
SESSION_KEY[sessionKey<br/>会话唯一标识]
MAIN_KEY[mainSessionKey<br/>主会话]
MATCHED_BY[matchedBy<br/>匹配方式]
end
subgraph "会话管理 Session Management"
SESSION_STORE[Session Store<br/>~/.openclaw/sessions/]
SESSION_FILE[.jsonl 文件<br/>role/content/timestamp]
HISTORY[上下文历史<br/>消息 turnover]
end
%% 连接关系
CFG -->|解析| P1
IN_CHANNEL -->|输入| P1
IN_ACCOUNT -->|输入| P1
IN_PEER -->|输入| P1
IN_GUILD -->|输入| P1
IN_TEAM -->|输入| P1
P1 -->|无匹配| P2
P2 -->|无匹配| P3
P3 -->|无匹配| P4
P4 -->|无匹配| P5
P5 -->|无匹配| P6
P6 -->|无匹配| P7
P1 -->|匹配| AGENT_ID
P2 -->|匹配| AGENT_ID
P3 -->|匹配| AGENT_ID
P4 -->|匹配| AGENT_ID
P5 -->|匹配| AGENT_ID
P6 -->|匹配| AGENT_ID
P7 -->|匹配| AGENT_ID
AGENT_ID -->|构建| SESSION_KEY
AGENT_ID -->|构建| MAIN_KEY
P1 -->|设置| MATCHED_BY
P2 -->|设置| MATCHED_BY
P3 -->|设置| MATCHED_BY
P4 -->|设置| MATCHED_BY
P5 -->|设置| MATCHED_BY
P6 -->|设置| MATCHED_BY
P7 -->|设置| MATCHED_BY
SESSION_KEY -->|读写| SESSION_STORE
MAIN_KEY -->|读写| SESSION_STORE
SESSION_STORE -->|包含| SESSION_FILE
SESSION_FILE -->|构建| HISTORY
style RouteInput fill:#e8f5e9
style MatchingPriority fill:#c8e6c9
style RouteOutput fill:#a5d6a7
style SessionManagement fill:#81c784
```
---
## 6. 媒体管道架构 Media Pipeline
```mermaid
graph LR
subgraph "入站 Inbound"
A[收到媒体] --> B[parse<br/>提取媒体]
B --> C[mime.ts<br/>检测 MIME]
C -->|magic number<br/>+ content type| MIME_TYPE{MIME 类型?}
MIME_TYPE -->|image| D[store.ts<br/>保存到磁盘]
MIME_TYPE -->|audio| D
MIME_TYPE -->|video| D
MIME_TYPE -->|unknown| DROP[丢弃/警告]
end
subgraph "存储 Storage"
D --> STORAGE[~/.openclaw/media/inbound/]
STORAGE --> FILES["{original}---{uuid}.ext"]
end
subgraph "处理 Processing (可选)"
FILES --> E[image_ops.ts<br/>image/image-ops.ts]
E -->|resizeToJpeg| RESIZED[调整大小的 JPEG]
end
subgraph "出站 Outbound"
OUT_REQ[出站请求] --> OUT_MIME[mime.ts<br/>检测 MIME]
OUT_MIME -->|需要处理?| OUT_PROC[image_ops/audio.ts]
OUT_MIME -->|不需要处理| OUT_STORE[store.ts<br/>保存到磁盘]
OUT_PROC --> OUT_STORE
OUT_STORE --> OUT_STORAGE[~/.openclaw/media/outbound/]
end
subgraph "服务服务 & Fetch"
STORAGE --> HOST[host.ts<br/>HTTP 服务]
OUT_STORAGE --> HOST
HOST -->|GET /media/*| CLIENT[客户端]
FETCH[fetch.ts<br/>远程获取] --> STORAGE
end
style Inbound fill:#e3f2fd
style Storage fill:#bbdefb
style Processing fill:#90caf9
style Outbound fill:#64b5f6
style ServeFetch fill:#42a5f5
```
---
## 7. Gateway 通信协议 Gateway Protocol
```mermaid
stateDiagram-v2
direction LR
%% 定义带有复杂描述的状态名规避连线上的解析Bug
state "Authenticated (已认证)" as Authenticated
state "Connected (已就绪)" as Connected
state "Requesting (请求中)" as Requesting
state "Streaming (流式传输中)" as Streaming
state "Waiting (异步等待中)" as Waiting
state "Error (发生错误)" as Error
state "Closed (连接关闭)" as Closed
[*] --> Disconnected
note right of Disconnected
未连接状态
end note
Disconnected --> Connecting: 客户端发起WS连接
%% 连线描述尽量保持简洁,避开特殊字符
Connecting --> Authenticated: req_connect_auth_ok
Connecting --> Closed: 认证失败
Connecting --> Closed: 非首帧为connect
Authenticated --> Connected: res_hello_ok
Connected --> Requesting: req_method
Connected --> Streaming: event_stream
Requesting --> Connected: res_ok_sync
Requesting --> Waiting: method_processing
Waiting --> Connected: res_ok
Waiting --> Error: res_error
Streaming --> Connected: stream_end
Streaming --> Streaming: stream_continue
Connected --> Closed: 客户端断开
Error --> Connected: error_recovery
Authenticated --> Closed: connection_close
Closed --> [*]
note right of Streaming
agent 事件流示例:
{
"type": "event",
"event": "agent",
"payload": {
"agentId": "xxx",
"runId": "yyy",
"status": "running"
}
}
end note
note right of Requesting
request 示例:
{
"type": "req",
"id": 1,
"method": "send",
"params": {
"channel": "whatsapp",
"target": "...",
"text": "..."
}
}
end note
```
---
## 8. 认证与配对流程 Authentication & Pairing
```mermaid
sequenceDiagram
participant DEV as 设备(Device)<br/>CLI/App/Node
participant WS as Gateway<br/>WebSocket Server
participant AUTH as Auth Module
participant PAIRING as Pairing Store
participant USER as 操作员
%% 首次连接 - 本地
rect rgb(200, 255, 200)
Note over DEV,USER: 场景:首次本地连接 (自动批准)
DEV->>WS: WS connect
WS->>AUTH: 生成 deviceIdentity
AUTH-->>WS: deviceIdentity (含 deviceID)
WS-->>DEV: res:connect + deviceIdentity
DEV->>WS: req:connect (带 deviceID)
WS->>AUTH: 验证 deviceID 是否本地
AUTH->>PAIRING: 检查 pairing 状态
PAIRING-->>AUTH: 新设备 (需要批准)
AUTH->>AUTH: 本地地址 -> 自动批准
AUTH->>PAIRING: 生成 deviceToken
AUTH-->>WS: 设备已批准
WS-->>DEV: res:hello-ok (带 deviceToken)
end
%% 首次连接 - 远程
rect rgb(255, 200, 200)
Note over DEV,USER: 场景:首次远程连接 (需要批准)
DEV->>WS: WS connect (via Tailscale/VPN)
WS->>AUTH: 生成 deviceIdentity (带 challenge)
AUTH-->>WS: deviceIdentity + challenge
WS-->>DEV: res:connect + deviceIdentity + challenge
DEV->>DEV: 签名 challenge
DEV->>WS: req:connect (带 deviceID + signature)
WS->>AUTH: 验证签名
AUTH->>PAIRING: 检查 pairing 状态
PAIRING-->>AUTH: 新设备,非本地
AUTH-->>USER: 通知等待批准
USER-->>AUTH: 批准设备
AUTH->>PAIRING: 生成并保存 deviceToken
AUTH-->>WS: 设备已批准
WS-->>DEV: res:hello-ok (带 deviceToken)
end
%% 后续连接
rect rgb(200, 200, 255)
Note over DEV,USER: 场景:后续连接
DEV->>WS: WS connect
DEV->>WS: req:connect (带 deviceID + deviceToken)
WS->>PAIRING: 验证 deviceToken
PAIRING-->>WS: Token 有效
WS-->>DEV: res:hello-ok
end
```
---
## 9. 完整组件关系图 Component Relationships
```mermaid
graph TB
%% CLI 层
CLI[openclaw CLI<br/>openclaw.mjs]
PROG[src/index.ts<br/>buildProgram]
CMDS[src/commands/]
CLI --> PROG
PROG --> CMD_DEPS[createDefaultDeps]
%% Gateway 层
GW_SERVER[src/gateway/server.impl.ts<br/>startGatewayServer]
GW_PROT[src/gateway/protocol/]
GW_METHODS[src/gateway/server-methods/]
GW_CHAN[src/gateway/server-channels.ts]
GW_SERVER --> GW_PROT
GW_SERVER --> GW_METHODS
GW_SERVER --> GW_CHAN
%% 通道层
CHAN_SYS[src/channels/]
PLUG_TYPES[src/channels/plugins/types.plugin.ts]
PLUG_ADAPTER[src/channels/plugins/types.adapters.ts]
WHAST[whatsapp.ts]
TELEG[telegram.ts]
DISC[discord.ts]
SLACK[slack.ts]
SIGNL[signal.ts]
IMMSG[imessage.ts]
CHAN_SYS --> PLUG_TYPES
CHAN_SYS --> PLUG_ADAPTER
CHAN_SYS --> WA
CHAN_SYS --> TG
CHAN_SYS --> DC
CHAN_SYS --> SL
CHAN_SYS --> SI
CHAN_SYS --> IM
GW_CHAN --> CHAN_SYS
%% Agent 层
AGENT_RT[src/agents/runtime.ts]
AGENT_TOOLS[src/agents/tools/]
ROUTER[src/routing/resolve-route.ts]
ROUTER --> AGENT_RT
AGENT_RT --> AGENT_TOOLS
GW_METHODS --> ROUTER
%% 配置层
CONFIG[src/config/]
ZOD_TYPES[src/config/zod-schema.*.ts]
CONFIG --> ZOD_TYPES
GW_SERVER --> CONFIG
ROUTER --> CONFIG
%% 媒体层
MEDIA[src/media/]
MIME[mime.ts]
STORE[store.ts]
FETCH[fetch.ts]
MEDIA --> MIME
MEDIA --> STORE
MEDIA --> FETCH
GW_METHODS --> MEDIA
%% 插件层
PLUG_SYS[src/plugins/]
PLUG_SDK[src/plugin-sdk/]
PLUG_SYS --> PLUG_SDK
GW_SERVER --> PLUG_SYS
%% 钩子
HOOKS[src/hooks/types.ts]
HOOKS --> AGENT_RT
PLUG_SDK --> HOOKS
%% 基础设施
INFRA[src/infra/]
PORTS[ports.ts]
LOGG[logging/]
INFRA --> PORTS
INFRA --> LOGG
GW_SERVER --> INFRA
style CLI fill:#e1f5fe
style GatewayServer fill:#bbdefb
style ChannelLayer fill:#90caf9
style AgentLayer fill:#64b5f6
style ConfigLayer fill:#42a5f5
style MediaLayer fill:#1e88e5
style PluginLayer fill:#0d47a1
```
---
## 附录:组件职责
| 组件 | 职责 |
| ------------------ | ---------------------------------------------- |
| **CLI** | 命令行界面,启动 gateway、发送消息、配置管理等 |
| **Gateway** | WebSocket 服务器,协议验证,事件广播,通道管理 |
| **Channels** | 消息平台适配器,入站/出站消息,状态管理 |
| **Routing** | 消息路由解析,绑定匹配,会话键构建 |
| **Agent Runtime** | AI Agent 执行,工具调用,会话管理 |
| **Media Pipeline** | 媒体上传、存储、处理、服务 |
| **Config System** | 配置加载、验证、迁移、监听 |
| **Plugin SDK** | 插件开发接口,运行时 API |
| **Hooks** | 生命周期钩子,插件扩展点 |
| **Infrastructure** | 端口管理、日志、诊断事件、SSRF 防护 |
---
**文档结束**

File diff suppressed because one or more lines are too long

View File

@ -1,126 +0,0 @@
# OpenClaw Mac 节点配置与云端控制完全指南
本文档汇总了关于将 Mac 注册为 OpenClaw Gateway 节点的操作指南,以及在云端部署 Gateway 控制本地 Mac 的场景可行性分析。
---
## 1. 核心概念Gateway 与 Node
在 OpenClaw 架构中:
- **Gateway (网关)**: 系统的"大脑"与控制中心。负责运行 AI 智能体、管理会话、连接消息平台(如 WhatsApp/Telegram。它可以部署在任何地方本地 Manjaro、云端 Ubuntu 服务器等)。
- **Node (节点)**: 系统的"手脚"与执行单元。它连接到 Gateway暴露本地设备的能力如屏幕显示、摄像头、执行系统命令。Mac 可以作为一个高权限节点加入网络。
---
## 2. 实操指南:将 Mac 注册到 Gateway
无论 Gateway 运行在本地局域网Manjaro还是云端Ubuntu连接 Mac 的步骤基本一致。
### 方案选择
| 方案 | 适用场景 | 优势 | 劣势 |
| :--- | :--- | :--- | :--- |
| **A. macOS App (Remote 模式)** | **推荐** | ✅ 支持 Canvas (网页显示)<br>✅ 支持摄像头/录屏<br>✅ 完整的权限管理 (TCC)<br>✅ 系统通知 | 需要安装 App |
| **B. 纯 CLI (无头模式)** | 服务器/轻量级 | ✅ 无需 GUI<br>✅ 部署简单 | ❌ 无 Canvas/摄像头/录屏支持 |
### 详细配置步骤
#### 第一步:环境准备
1. **Gateway 端 (Manjaro/Ubuntu)**:
- 确保 Gateway 已启动。
- 获取连接 Token
```bash
openclaw config get gateway.auth.token
# 记录下输出的 Token
```
- 确保网络可达(云端需开放端口或使用 Tailscale/SSH 隧道)。
2. **Mac 端 (节点)**:
- 安装 OpenClaw CLI: `npm install -g openclaw`
- (推荐) 下载并安装 **OpenClaw.app**
#### 第二步:连接 Gateway
**方式 A: 使用 macOS App (推荐)**
1. 打开 OpenClaw.app进入 **Settings** -> **General**
2. **Mode**: 选择 **Remote**
3. **Gateway Host**: 输入 Gateway 的 IP 或域名(如 `1.2.3.4``myserver.tailscale.net`)。
4. **Gateway Port**: 默认为 `18789`
5. **Gateway Token**: 填入第一步获取的 Token。
6. 应用会自动启动本地节点服务并尝试连接。
**方式 B: 使用 CLI**
在 Mac 终端运行:
```bash
# 前台运行测试
openclaw node run --host <gateway-ip> --port 18789 --token <token> --display-name "MyMac"
# 或安装为后台服务
openclaw node install --host <gateway-ip> --port 18789 --token <token> --display-name "MyMac"
openclaw node start
```
#### 第三步:批准连接 (在 Gateway 端)
出于安全考虑,新节点连接需要批准。
```bash
# 在 Gateway 机器上运行
openclaw devices list # 查看待批准请求
openclaw devices approve <request-id>
```
#### 第四步:验证
```bash
# 在 Gateway 机器上运行
openclaw nodes status # 应显示 Mac 节点在线
openclaw nodes describe --node "MyMac"
```
---
## 3. 功能手册Gateway 可控制 Mac 做什么
连接成功后Gateway 上的 AI Agent 可以通过 `node.invoke` 调用 Mac 的能力:
### 基础能力
- **执行命令**: `system.run` (如 `uname -a`, `ls -la`)
- *安全提示*: 需在 Mac 的 `~/.openclaw/exec-approvals.json` 中配置允许列表。
- **系统通知**: `system.notify` (发送弹窗通知到 Mac 桌面)
- **获取位置**: `location.get`
### 多媒体与 UI (需 macOS App)
- **浏览器控制 (Canvas)**:
- 打开网页: `canvas.present --target https://google.com`
- 执行 JS: `canvas.eval --js "document.title"`
- 截图: `canvas.snapshot`
- **摄像头**: `camera.snap` (拍照), `camera.clip` (录短视频)
- **屏幕录制**: `screen.record`
---
## 4. 场景深度分析:云端 Gateway + Mac Node
**问题**: 如果 Gateway 在云端 UbuntuMac 作为节点OpenClaw 能否"像人一样"使用 Mac如写代码、做 PPT
**结论**: **可以做到,但更像是"远程脚本专家",而非"人类操作员"。**
由于网络延迟和架构限制AI 的操作模式与人类不同:
### 场景 A: 修改代码 (Code Modification)
* **人类模式 (不推荐)**: 打开 VS Code GUI点击光标输入字符。
* *AI 限制*: 视觉识别+模拟点击在云端到本地的高延迟下体验极差。
* **OpenClaw 模式 (推荐)**:
1. **Git流**: AI 在云端修改代码 -> Push 到仓库 -> 指挥 Mac 节点 `git pull` -> 指挥 Mac 运行 `npm run dev` 预览。
2. **命令行流**: AI 通过 `system.run` 发送 `sed`/`echo` 命令直接修改 Mac 文件(风险较高,容易改错)。
### 场景 B: 制作 PPT (Presentation)
* **人类模式 (不推荐)**: 打开 Keynote鼠标拖拽文本框调整字体。
* *AI 限制*: 无法精准控制鼠标拖拽,且无法实时"看"到效果。
* **OpenClaw 模式 (推荐 - AppleScript)**:
* Mac 节点支持执行 AppleScript。AI 可以编写脚本直接控制 Keynote/PowerPoint。
* *指令示例*: `tell application "Keynote" to make new slide with title "AI Report"`
* *优势*: 速度极快,精确,无需视觉反馈。
### 关键限制与建议
1. **网络延迟**: 云端控制本地 UI 会有显著延迟。如果需要频繁的"看屏幕-点击"交互,建议将 Gateway 部署在本地。
2. **文件访问**: Gateway 默认无法直接读取 Mac 文件系统(除非通过 `cat` 命令回传)。建议通过 Git 或云同步文件夹共享工作区。
3. **最佳实践**: 让 AI 充当**指挥官**(在云端思考、规划、写脚本),让 Mac 充当**执行器**(运行脚本、渲染 UI、跑测试而不是让 AI 模拟鼠标键盘。

File diff suppressed because it is too large Load Diff

View File

@ -1,42 +0,0 @@
Q: 现在我们需要基于openclaw做二开提供企业级的办公助手。希望这个应用能够提供端云协同的能力我们可以脑暴下端云协同指的什么能力。 我的理解: 端云协同的一个理解:我可以在工作电脑上使用这个助手,通过助手工作台,比如让他帮我写代码、给他提数据分析的需求,这些需求会被分配到云端执行,执行过程中可能会需要询问用户,当前遇到的问题,让用户补充一些信息之类的。 用户也可以看到当前执行的任务,任务执行过程等。 用户离开电脑,可以通过手机办公软件,如钉钉,通过对话的方式继续协同助手办公
关于端云协同,你有什么好的想法吗
A:
基于 OpenClaw 进行企业级二次开发是一个非常务实的路径。你提到的“任务云端执行、移动端交互协同”已经抓住了端云协同的核心——“算力在云,交互在端,状态同步”。
为了让这个“办公助手”真正达到企业级深度,我们可以从环境感知、隐私边界、异步执行这几个维度进一步拓展“端云协同”的内涵:
1. 环境与上下文的“无缝接力” (Seamless Context Handoff)
端云协同不应只是消息同步,更应该是**“执行环境”**的同步。
端侧快照: 当你在电脑上给助手发指令(如“分析这段代码的 Bug”端侧插件可以自动抓取当前的 IDE 状态、打开的文件列表、甚至是报错日志,打包发送到云端。
移动端“数字孪生”: 当你切换到手机钉钉时,助手不仅是回复文字,它能通过一张“状态卡片”让你看到云端容器里正在运行的终端界面或代码 Demo。你可以在手机上点一下“继续运行”或“终止”。
2. 隐私与安全的“离岸闸口” (Privacy Gatekeeper)
企业级应用中,数据安全是第一生命线。端侧可以作为一个**“脱敏层”**。
本地脱敏: 在需求发送到云端大模型之前端侧助手先在本地扫描是否含有代码秘钥API Key、客户手机号、内部服务器 IP。
端侧替换/云端还原: 端侧将敏感信息替换为占位符,云端执行完后再传回端侧,由端侧助手在本地环境将信息“填补”回来。这样核心数据从未真正离开过用户的内网环境。
3. 异步任务的“长跑协同” (Asynchronous Long-running Tasks)
很多企业需求(如:生成一份 50 页的行业调研报告、跑一个大型自动化测试)不是秒回的。
云端常驻 Agent 云端助手是一个长驻进程。你在下班路上通过手机问一句:“下午交代的那个数据清洗任务跑完没?”
主动推送到端: 任务执行到关键节点(如:发现数据源格式错误),云端助手主动通过钉钉向你发送一条“紧急弹窗”,询问:“我发现有 10% 的数据缺失,是跳过还是取平均值填充?”
4. 资源调度协同 (Resource Orchestration)
根据任务的性质动态分配“在哪里干活”: | 任务类型 | 执行位置 | 协同逻辑 | | :--- | :--- | :--- | | UI 操作/本地文件改写 | 端侧 (Local) | 云端下达指令(类似 MCP 协议),端侧助手操控本地 Playwright 或文件系统执行。 | | 大规模计算/复杂逻辑推理 | 云端 (Cloud) | 端侧提供上下文,云端利用高性能算力进行深度思考。 | | 即时通讯/审批提醒 | 移动端 (Mobile) | 作为指令入口和结果反馈的轻量化界面。 |
5. 多模态的交互分工
端侧PC 强于“输入”,适合处理复杂的代码编写、多文档对比、窗口拖拽。
移动端: 强于“反馈”,利用语音、拍照、快捷卡片。
例子: 你在云端跑了一个数据分析,助手在手机上给你推了一张可视化图表,你对着手机说:“把那两个异常点剔除掉重新跑一下”,这比在手机上敲代码快得多。
核心价值总结
这种端云协同的本质是:把 PC 端作为“作业车间”,把云端作为“超级大脑”,把移动端作为“遥控器”和“对讲机”。

File diff suppressed because one or more lines are too long