[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6CW2SRD2B079B8VSBB6WV4R":3,"skill-same:01M6CW2SRD2B079B8VSBB6WV4R":348},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":25,"publishedAt":43,"linkOnly":44,"markdownContent":45,"markdownBody":46,"frontMatter":47,"refName":49,"commitSha":50,"skillDirectory":51,"forksCount":13,"repositoryHtmlUrl":52,"repositoryHomepageUrl":6,"ownerHtmlUrl":53,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":54,"install":55,"resources":68},"01M6CW2SRD2B079B8VSBB6WV4R","agent-dispatch-use",null,"AgentDispatch 使用指南。教导 AI Agent 如何启动 Server、配置 Client Node、将各种 Agent 作为 Worker 挂载到分发集群、提交任务并监听状态。触发方式：用户提及 \"\u002Fonboard\"、\"how to use dispatch\"、\"快速上手\"、\"set up agentdispatch\"、\"挂载 Agent\"、\"mount worker\" 等关键词时激活。","blackplume233\u002FAgentDispatch","blackplume233","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F32346887?v=4","01M6CW1PP6XWA3JMVYH3T45R5P","01M6CW1PTFMF173PDVR9CQ8H31",1,"MIT","https:\u002F\u002Fgithub.com\u002Fblackplume233\u002FAgentDispatch\u002Fblob\u002Fmaster\u002F.opencode\u002Fskills\u002Fagent-dispatch-use\u002FSKILL.md",[17,22],{"categoryNo":18,"categoryName":19,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000010","后端与接口","SCENARIO","使用场景",{"categoryNo":23,"categoryName":24,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000023","Skill与智能体开发",[26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42],"agent dispatch use","dispatch","use","关键词","up","write","read","node","grep","ai agent","mount","挂载","onboard","how","shell","SET","server","2026-11-10 10:12:30",false,"---\nname: agent-dispatch-use\ndescription: 'AgentDispatch 使用指南。教导 AI Agent 如何启动 Server、配置 Client Node、将各种 Agent 作为 Worker 挂载到分发集群、提交任务并监听状态。触发方式：用户提及 \"\u002Fonboard\"、\"how to use dispatch\"、\"快速上手\"、\"set up agentdispatch\"、\"挂载 Agent\"、\"mount worker\" 等关键词时激活。'\nlicense: MIT\nallowed-tools: Shell, Read, Write, Glob, Grep\n---\n\n# AgentDispatch 使用指南\n\n## 概述\n\nAgentDispatch 是一个 AI Agent 任务分发平台。核心架构将任务**创建**与**执行**完全解耦：\n\n| 组件 | 职责 |\n|------|------|\n| **Server** | 中心化 REST API 服务，管理任务队列、客户端注册、文件持久化、SSE 推送 |\n| **Client Node** | 执行节点，轮询 Server 获取任务，调度和管理本地 Worker Agent 集群 |\n| **Worker Agent** | 通过 ACP (Agent Client Protocol) 执行具体任务的 AI Agent |\n| **Manager Agent** | 可选的 AI 调度顾问，通过 ACP 向 Client Node 提供分发建议 |\n| **CLI** | `dispatch` 命令行工具，Worker 通过它上报进度、提交产物 |\n\n```\n                            ┌────────────────────────┐\n  任务提交方                 │     Server (:9800)      │\n  (curl \u002F SDK \u002F Dashboard)─→│  REST API + FileStore   │\n                            │  SSE Stream + Auth      │\n                            └────────┬───────────────┘\n                                     │ HTTP (poll\u002Fclaim\u002Fprogress\u002Fcomplete)\n                            ┌────────▼───────────────┐\n                            │     Client Node         │\n                            │  Dispatcher (tag\u002Fmgr)   │\n                            │  AcpController          │\n                            │  WorkerManager          │\n                            │  IPC Server             │\n                            └──┬─────┬─────┬─────────┘\n                   ACP(stdio)  │     │     │  ACP(stdio)\n                     ┌─────────▼┐ ┌──▼──┐ ┌▼──────────┐\n                     │ Worker-01│ │Wk-02│ │Manager Agt │\n                     │(claude)  │ │(gpt)│ │(调度顾问)   │\n                     └──────────┘ └─────┘ └───────────┘\n```\n\n**核心设计理念**：任何支持 ACP 协议（JSON-RPC 2.0 over stdio）的 AI Agent 都可以作为 Worker 挂载到 Client Node 上。\n\n---\n\n## Part 1: 启动 Server\n\n### 1.1 前置条件\n\n- Node.js >= 20.0.0\n- pnpm >= 9.x\n\n### 1.2 安装与构建\n\n```bash\npnpm install\npnpm build\n```\n\n### 1.3 零配置启动\n\n```bash\nnode packages\u002Fserver\u002Fdist\u002Findex.js\n# Server 默认监听 0.0.0.0:9800，数据存储在 .\u002Fdata\u002F\n```\n\n### 1.4 自定义配置\n\n**环境变量方式**（推荐用于快速测试）：\n\n```bash\nDISPATCH_SERVER_PORT=8080 \\\nDISPATCH_DATA_DIR=.\u002Fmy-data \\\nDISPATCH_LOG_LEVEL=debug \\\nDISPATCH_AUTH_ENABLED=true \\\nDISPATCH_AUTH_TOKENS=\"tok_client_abc123,tok_operator_xyz:operator\" \\\nnode packages\u002Fserver\u002Fdist\u002Findex.js\n```\n\n**配置文件方式**（`server.config.json`）：\n\n```json\n{\n  \"host\": \"0.0.0.0\",\n  \"port\": 9800,\n  \"dataDir\": \".\u002Fdata\",\n  \"logLevel\": \"info\",\n  \"auth\": {\n    \"enabled\": true,\n    \"users\": [{ \"username\": \"admin\", \"password\": \"your-password\" }],\n    \"tokens\": [\n      \"tok_client_abc123\",\n      { \"token\": \"tok_operator_xyz\", \"role\": \"operator\" }\n    ]\n  }\n}\n```\n\n### 1.5 验证\n\n```bash\ncurl http:\u002F\u002Flocalhost:9800\u002Fhealth\n# {\"status\":\"ok\",\"version\":\"0.0.1\",\"authEnabled\":false}\n```\n\n### 1.6 环境变量一览\n\n| 变量 | 默认值 | 说明 |\n|------|--------|------|\n| `DISPATCH_SERVER_HOST` | `0.0.0.0` | 监听地址 |\n| `DISPATCH_SERVER_PORT` | `9800` | 监听端口 |\n| `DISPATCH_DATA_DIR` | `.\u002Fdata` | 数据目录 |\n| `DISPATCH_LOG_LEVEL` | `info` | 日志级别 (debug\u002Finfo\u002Fwarn\u002Ferror) |\n| `DISPATCH_AUTH_ENABLED` | `false` | 启用鉴权 |\n| `DISPATCH_AUTH_TOKENS` | — | 静态 Token 列表（逗号分隔，`:role` 后缀可选） |\n\n---\n\n## Part 2: 配置 Client Node\n\n### 2.1 最小可用配置\n\n在工作目录创建 `client.config.json`：\n\n```json\n{\n  \"name\": \"my-node\",\n  \"serverUrl\": \"http:\u002F\u002Flocalhost:9800\",\n  \"tags\": [\"code-review\"],\n  \"dispatchMode\": \"tag-auto\",\n  \"autoDispatch\": {\n    \"rules\": [\n      { \"taskTags\": [\"code-review\"], \"targetAgentId\": \"worker-01\", \"priority\": 10 }\n    ],\n    \"fallbackAction\": \"skip\"\n  },\n  \"agents\": [\n    {\n      \"id\": \"worker-01\",\n      \"type\": \"worker\",\n      \"command\": \"claude-agent-acp\",\n      \"workDir\": \"\u002Fpath\u002Fto\u002Fworkspace\"\n    }\n  ]\n}\n```\n\n### 2.2 完整配置结构\n\n```json\n{\n  \"name\": \"production-node\",\n  \"serverUrl\": \"http:\u002F\u002Fyour-server:9800\",\n  \"token\": \"tok_client_abc123\",\n  \"tags\": [\"code-review\", \"documentation\", \"testing\"],\n  \"dispatchMode\": \"hybrid\",\n  \"polling\": { \"interval\": 10000 },\n  \"heartbeat\": { \"interval\": 30000 },\n  \"ipc\": { \"path\": \"\" },\n  \"autoDispatch\": {\n    \"rules\": [\n      { \"taskTags\": [\"code-review\"], \"targetAgentId\": \"claude-worker\", \"priority\": 10 },\n      { \"taskTags\": [\"documentation\"], \"targetCapabilities\": [\"writing\"], \"priority\": 5 },\n      { \"taskTags\": [\"testing\"], \"targetAgentId\": \"test-worker\", \"priority\": 8 }\n    ],\n    \"fallbackAction\": \"skip\"\n  },\n  \"logging\": {\n    \"dir\": \".\u002Flogs\",\n    \"rotateDaily\": true,\n    \"retainDays\": 30,\n    \"httpLog\": true,\n    \"auditLog\": true,\n    \"agentLog\": true\n  },\n  \"agents\": []\n}\n```\n\n### 2.3 关键字段说明\n\n| 字段 | 必填 | 说明 |\n|------|------|------|\n| `name` | 是 | 节点唯一标识，Server 按此区分客户端 |\n| `serverUrl` | 是 | Server HTTP 地址 |\n| `token` | 启用 auth 时 | Server 分配的 API Token |\n| `tags` | 是 | 节点能处理的任务标签集合 |\n| `dispatchMode` | 是 | 分发策略：`tag-auto` \u002F `manager` \u002F `hybrid` |\n| `autoDispatch.rules` | tag-auto\u002Fhybrid | 按 task tag 匹配 Worker 的规则列表 |\n| `autoDispatch.fallbackAction` | 否 | 无规则匹配时行为：`skip`（默认）\u002F `queue-local` |\n\n### 2.4 分发模式\n\n| 模式 | 工作方式 | 需要 Manager |\n|------|---------|:-----------:|\n| `tag-auto` | 规则引擎按 task tag 匹配 Worker，按 priority 排序 | 否 |\n| `manager` | 每个待分配任务都咨询 Manager Agent，由 AI 决定路由 | 是 |\n| `hybrid` | Manager 在线时用 AI 调度，离线时回退到 tag-auto 规则 | 可选 |\n\n### 2.5 分发规则详解\n\n```json\n{\n  \"taskTags\": [\"backend\", \"api\"],\n  \"targetAgentId\": \"worker-backend\",\n  \"targetCapabilities\": [\"typescript\", \"node\"],\n  \"priority\": 10\n}\n```\n\n| 字段 | 说明 |\n|------|------|\n| `taskTags` | AND 逻辑 — 任务必须包含所有指定 tag 才匹配 |\n| `targetAgentId` | 精确指定 Worker ID |\n| `targetCapabilities` | 按能力匹配 — 选择拥有这些 capabilities 的空闲 Worker |\n| `priority` | 数值越大越优先（多条规则匹配时取最高优先级） |\n\n### 2.6 启动 Client Node\n\n```bash\nnode packages\u002Fclient-node\u002Fdist\u002Fmain.js\n# 或指定配置文件\nDISPATCH_NODE_CONFIG=.\u002Fmy-config.json node packages\u002Fclient-node\u002Fdist\u002Fmain.js\n```\n\nCLI 方式：\n\n```bash\ndispatch start --config .\u002Fclient.config.json\ndispatch start --config .\u002Fclient.config.json --foreground\n```\n\n---\n\n## Part 3: 将 Agent 作为 Worker 挂载（重点）\n\n这是 AgentDispatch 的核心操作——将一个 AI Agent 注册为 Worker，使其能自动接收并执行分发来的任务。\n\n### 3.1 Agent 挂载原理\n\n```\n┌──────────────────────────────────────────────────────────────┐\n│                     Client Node                               │\n│                                                               │\n│  1. Dispatcher 决定: task → worker-01                         │\n│  2. HTTP claim → Server                                       │\n│  3. AcpController.launchAgent():                              │\n│     a. 创建 AgentProcess (spawn 子进程)                        │\n│     b. 注入 DISPATCH_TOKEN + DISPATCH_IPC_PATH                │\n│     c. 通过 stdin\u002Fstdout 建立 ACP JSON-RPC 连接               │\n│     d. 发送 initialize (声明 capabilities)                     │\n│     e. TaskWorkflowRunner 发送 task prompt                    │\n│  4. Worker 执行任务，通过 dispatch CLI 上报进度                  │\n│  5. Worker 完成 → 产物打包 → dispatch worker complete          │\n│  6. AcpController 收集结果 → 上传 Server → 标记 completed      │\n│                                                               │\n│  ┌─────────────────┐  stdio (ACP)  ┌──────────────────┐      │\n│  │  AcpController   │←────────────→│  Worker Process   │      │\n│  │  DispatchAcpClient│              │  (ACP Agent 进程)  │      │\n│  └─────────────────┘               └──────────────────┘      │\n└──────────────────────────────────────────────────────────────┘\n```\n\n### 3.2 AgentConfig 完整字段\n\n每个 Worker 在 `client.config.json` 的 `agents` 数组中注册：\n\n```typescript\ninterface AgentConfig {\n  id: string;                    \u002F\u002F 唯一标识（必填）\n  type: 'manager' | 'worker';   \u002F\u002F 角色（必填）\n  command: string;               \u002F\u002F 启动命令（必填）\n  args?: string[];               \u002F\u002F 额外启动参数\n  workDir: string;               \u002F\u002F 工作目录（必填）\n  capabilities?: string[];       \u002F\u002F 能力标签（用于 dispatch 匹配）\n  autoClaimTags?: string[];      \u002F\u002F 自动认领的任务标签\n  allowMultiProcess?: boolean;   \u002F\u002F 是否允许并行多任务（默认 false）\n  promptTemplate?: string;       \u002F\u002F 自定义 prompt 模板路径\n  acpCapabilities?: {\n    fs?: {\n      readTextFile?: boolean;    \u002F\u002F 允许 Agent 读文件\n      writeTextFile?: boolean;   \u002F\u002F 允许 Agent 写文件\n    };\n    terminal?: boolean;          \u002F\u002F 允许 Agent 使用终端\n  };\n  permissionPolicy?: 'auto-allow' | 'auto-deny' | 'prompt';\n}\n```\n\n### 3.3 关键字段深度说明\n\n#### `command` — Agent 启动命令\n\n第一个 token 是可执行文件，后续 token 是默认参数。`args` 中的参数会追加到末尾。\n\n```json\n{ \"command\": \"claude-agent-acp\", \"args\": [\"--model\", \"sonnet\"] }\n\u002F\u002F 实际执行: claude-agent-acp --model sonnet\n```\n\n**要求**：`command` 启动的进程必须通过 **stdin\u002Fstdout** 进行 ACP 协议通信（JSON-RPC 2.0, newline-delimited JSON）。stderr 用于日志输出，不参与协议。\n\n> **注意**：并非所有 AI Agent CLI 都原生支持 ACP。部分 Agent（如 Claude、Codex）需要通过适配器。\n> 详见 [ACP 兼容 Agent 列表](https:\u002F\u002Fagentclientprotocol.com\u002Fget-started\u002Fagents)。\n\n#### `workDir` — Agent 工作目录\n\nAgent 进程以此目录为 `cwd` 启动。Client Node 会在其中创建：\n\n```\n{workDir}\u002F\n├── .dispatch\u002F\n│   ├── input\u002F{taskIdPrefix}\u002F    ← 下载的任务附件\n│   └── output\u002F{taskIdPrefix}\u002F   ← Agent 应将产物放在这里\n│       ├── artifact.zip         ← 产物压缩包\n│       └── result.json          ← 结构化结果\n└── ... (Agent 自身的文件)\n```\n\n#### `capabilities` — 能力标签\n\n与分发规则的 `targetCapabilities` 配合使用：\n\n```json\n\u002F\u002F 规则: 需要 [\"typescript\", \"testing\"] 能力的 Worker\n{ \"taskTags\": [\"unit-test\"], \"targetCapabilities\": [\"typescript\", \"testing\"] }\n\n\u002F\u002F Worker: 声明自己具备这些能力\n{ \"id\": \"test-bot\", \"capabilities\": [\"typescript\", \"testing\", \"jest\"] }\n\u002F\u002F ✓ 匹配成功（Worker 具备规则要求的所有能力）\n```\n\n#### `acpCapabilities` — ACP 能力声明\n\n在 ACP `initialize` 阶段向 Agent 声明 Client 提供的能力：\n\n```json\n{\n  \"acpCapabilities\": {\n    \"fs\": { \"readTextFile\": true, \"writeTextFile\": true },\n    \"terminal\": true\n  }\n}\n```\n\n| 能力 | 说明 |\n|------|------|\n| `fs.readTextFile` | Agent 可通过 ACP 请求读取 Client 端文件 |\n| `fs.writeTextFile` | Agent 可通过 ACP 请求写入 Client 端文件 |\n| `terminal` | Agent 可通过 ACP 请求执行终端命令 |\n\n#### `permissionPolicy` — 权限策略\n\n当 Agent 通过 ACP 请求使用工具（文件读写、终端）时的审批策略：\n\n| 值 | 行为 |\n|----|------|\n| `auto-allow` | 自动批准所有请求（默认，适合可信 Agent） |\n| `auto-deny` | 自动拒绝所有请求（最安全） |\n| `prompt` | 需要人工审批（当前未完整实现） |\n\n### 3.4 Worker 生命周期\n\n```\n                          Client Node 启动\n                               │\n                    Worker 注册 (config.agents)\n                               │\n                          status: idle\n                               │\n              ┌────────────────▼────────────────┐\n              │   Dispatcher 匹配到合适的任务     │\n              │   HTTP claim → Server             │\n              └────────────────┬────────────────┘\n                               │\n              ┌────────────────▼────────────────┐\n              │   AcpController.launchAgent()    │\n              │   1. spawn(command, {cwd:workDir})│\n              │   2. env += DISPATCH_TOKEN        │\n              │   3. env += DISPATCH_IPC_PATH     │\n              │   4. ACP initialize()             │\n              │   5. ACP prompt(taskContent)       │\n              └────────────────┬────────────────┘\n                               │\n                        status: busy\n                               │\n              ┌────────────────▼────────────────┐\n              │  Worker 执行任务                   │\n              │  - dispatch worker progress ...   │\n              │  - dispatch worker log ...        │\n              │  - 产出 artifact.zip + result.json │\n              │  - dispatch worker complete ...   │\n              └────────────────┬────────────────┘\n                               │\n                   ┌───────────┴───────────┐\n                   ▼                       ▼\n            完成 (completed)         失败 (failed)\n                   │                       │\n            status: idle             auto restart?\n                   │                  (指数退避)\n                   ▼                       │\n            等待下一个任务              status: idle\n```\n\n#### 进程环境变量注入\n\nWorker 进程启动时自动获得两个关键环境变量：\n\n| 变量 | 值 | 用途 |\n|------|-----|------|\n| `DISPATCH_TOKEN` | `wt_\u003Cuuid>` | 临时 Worker Token，仅在本次任务生命周期内有效，任务结束自动撤销 |\n| `DISPATCH_IPC_PATH` | Unix socket \u002F named pipe 路径 | 连接 Client Node IPC Server，用于 `dispatch` CLI 通信 |\n\n#### 自动重启机制\n\nWorker 进程异常退出时（exit code ≠ 0）：\n\n1. 状态标记为 `crashed`\n2. 如有正在执行的任务，自动释放回 `pending`\n3. 如重启次数未超限（默认 3 次），启用指数退避重启：\n   - 第 1 次: 2 秒后\n   - 第 2 次: 4 秒后\n   - 第 3 次: 8 秒后（上限 30 秒）\n4. 重启后状态回到 `idle`，可继续接收新任务\n\n### 3.5 Worker 通过 CLI 与系统交互\n\nWorker 在任务执行过程中使用 `dispatch` CLI：\n\n```bash\n# 上报进度（首次上报触发 claimed → in_progress 转换）\ndispatch worker progress \u003CtaskId> --percent 30 --message \"分析代码中...\"\n\n# 追加工作日志\ndispatch worker log \u003CtaskId> --message \"发现 3 个潜在安全问题\"\n\n# 完成任务（提交产物）\ndispatch worker complete \u003CtaskId> \\\n  --zip .\u002Foutput\u002Fartifact.zip \\\n  --result .\u002Foutput\u002Fresult.json\n\n# 报告失败\ndispatch worker fail \u003CtaskId> --reason \"无法访问代码仓库\"\n\n# 查询当前任务状态\ndispatch worker status \u003CtaskId>\n\n# 心跳（长时间无进度更新时使用）\ndispatch worker heartbeat \u003CtaskId>\n```\n\n### 3.6 ACP 任务分发流程\n\nClient Node 通过 ACP 向 Worker 发送任务时，使用 **TaskWorkflowRunner** 执行多轮对话：\n\n**Pass 1: InitialTaskPass** — 构建任务 prompt，包含：\n- 任务标题、描述、优先级、标签、元数据\n- 附件路径（如有下载）\n- 产物输出目录和格式要求\n- CLI 命令参考\n\n**Pass 2: ArtifactEnforcementPass** — 任务完成后检查产物：\n- 验证 `artifact.zip` 和 `result.json` 是否存在\n- 如产物缺失，向 Agent 发送补救 prompt，要求补充\n- 最终验证通过后才标记任务完成\n\n---\n\n## Part 4: 挂载不同类型的 Agent\n\n> **前提**：并非所有 AI Agent CLI 都原生支持 ACP 协议。部分需要通过**适配器**桥接。\n> 完整列表参见 [ACP 兼容 Agent](https:\u002F\u002Fagentclientprotocol.com\u002Fget-started\u002Fagents)。\n\n### 4.0 ACP 兼容 Agent 参考表\n\n| Agent | ACP 支持 | command | args | 安装方式 |\n|-------|---------|---------|------|---------|\n| **Claude Agent** | 适配器 | `claude-agent-acp` | — | `npm i -g @zed-industries\u002Fclaude-agent-acp` |\n| **Codex CLI** | 适配器 | `codex-acp` | — | `npm i -g @zed-industries\u002Fcodex-acp` |\n| **Gemini CLI** | 原生 | `gemini` | `[\"--experimental-acp\"]` | `npm i -g @google\u002Fgemini-cli` |\n| **Goose** | 原生 | `goose` | `[\"acp\"]` | [block.github.io\u002Fgoose](https:\u002F\u002Fblock.github.io\u002Fgoose\u002Fdocs\u002Fguides\u002Facp-clients) |\n| **OpenCode** | 原生 | `opencode` | `[\"acp\"]` | [open-code.ai](https:\u002F\u002Fopen-code.ai\u002Fdocs\u002Fen\u002Facp) |\n| **Kiro CLI** | 原生 | `kiro` | `[\"acp\"]` | [kiro.dev\u002Fcli](https:\u002F\u002Fkiro.dev\u002Fcli\u002F) |\n| **Kimi CLI** | 原生 | `kimi` | `[\"acp\"]` | [github.com\u002FMoonshotAI\u002Fkimi-cli](https:\u002F\u002Fgithub.com\u002FMoonshotAI\u002Fkimi-cli) |\n| **Augment Code** | 原生 | `auggie` | `[\"--acp\"]` | [docs.augmentcode.com\u002Fcli\u002Facp](https:\u002F\u002Fdocs.augmentcode.com\u002Fcli\u002Facp\u002Fagent) |\n| **Cline** | 原生 | `cline` | `[\"--acp\"]` | [docs.cline.bot](https:\u002F\u002Fdocs.cline.bot\u002Fcline-cli\u002Facp-editor-integrations) |\n| **Qwen Code** | 原生 | `qwen` | `[\"--acp\"]` | `npm i -g @qwen-code\u002Fqwen-code` |\n| **Mistral Vibe** | 原生 | `vibe-acp` | — | [github.com\u002Fmistralai\u002Fmistral-vibe](https:\u002F\u002Fgithub.com\u002Fmistralai\u002Fmistral-vibe\u002Fblob\u002Fmain\u002Fdocs\u002Facp-setup.md) |\n| **OpenHands** | 原生 | `openhands` | `[\"acp\"]` | [docs.openhands.dev](https:\u002F\u002Fdocs.openhands.dev\u002Fopenhands\u002Fusage\u002Frun-openhands\u002Facp) |\n| **GitHub Copilot** | 公测 | — | — | [github.com\u002Ffeatures\u002Fcopilot](https:\u002F\u002Fgithub.com\u002Ffeatures\u002Fcopilot) |\n| **Pi** | 适配器 | `pi-acp` | — | [github.com\u002Fsvkozak\u002Fpi-acp](https:\u002F\u002Fgithub.com\u002Fsvkozak\u002Fpi-acp) |\n| 自定义 Agent | 需自行实现 | `node .\u002Fagent.mjs` | — | 使用 ACP SDK（TypeScript\u002FPython\u002FRust\u002FKotlin） |\n\n> **重要**：很多 Agent CLI 的\"普通模式\"是交互式终端，不等于 ACP 模式。必须使用上表中对应的 `args` 参数才能进入 ACP stdio 通信模式。\n\nACP SDK 库：\n- TypeScript: `@anthropic-ai\u002Fagent-client-protocol` — [文档](https:\u002F\u002Fagentclientprotocol.com\u002Flibraries\u002Ftypescript)\n- Python: `agent-client-protocol` — [文档](https:\u002F\u002Fagentclientprotocol.com\u002Flibraries\u002Fpython)\n- Rust: — [文档](https:\u002F\u002Fagentclientprotocol.com\u002Flibraries\u002Frust)\n- Kotlin: — [文档](https:\u002F\u002Fagentclientprotocol.com\u002Flibraries\u002Fkotlin)\n\n### 4.1 挂载 Claude Agent\n\nClaude Code **不原生支持 ACP**，需通过 Zed 官方的 [`claude-agent-acp`](https:\u002F\u002Fgithub.com\u002Fzed-industries\u002Fclaude-agent-acp) 适配器桥接。\n\n**安装适配器**：\n\n```bash\nnpm install -g @zed-industries\u002Fclaude-agent-acp\n```\n\n**配置**：\n\n```json\n{\n  \"agents\": [\n    {\n      \"id\": \"claude-reviewer\",\n      \"type\": \"worker\",\n      \"command\": \"claude-agent-acp\",\n      \"args\": [\"--model\", \"sonnet\"],\n      \"workDir\": \"\u002Fworkspace\u002Fclaude-reviewer\",\n      \"capabilities\": [\"code-review\", \"security-audit\", \"typescript\"],\n      \"acpCapabilities\": {\n        \"fs\": { \"readTextFile\": true, \"writeTextFile\": true },\n        \"terminal\": true\n      },\n      \"permissionPolicy\": \"auto-allow\"\n    }\n  ]\n}\n```\n\n> 适配器通过 Claude Agent SDK 调用 Claude，需要设置 `ANTHROPIC_API_KEY` 环境变量。\n> 也可下载[预编译二进制](https:\u002F\u002Fgithub.com\u002Fzed-industries\u002Fclaude-agent-acp\u002Freleases)，无需 Node.js。\n\n### 4.2 挂载 Codex Agent\n\nOpenAI Codex CLI 同样需通过 [`codex-acp`](https:\u002F\u002Fgithub.com\u002Fzed-industries\u002Fcodex-acp) 适配器：\n\n```bash\nnpm install -g @zed-industries\u002Fcodex-acp\n```\n\n```json\n{\n  \"agents\": [\n    {\n      \"id\": \"codex-worker\",\n      \"type\": \"worker\",\n      \"command\": \"codex-acp\",\n      \"workDir\": \"\u002Fworkspace\u002Fcodex-worker\",\n      \"capabilities\": [\"code-generation\", \"refactor\"],\n      \"permissionPolicy\": \"auto-allow\"\n    }\n  ]\n}\n```\n\n> 需要设置 `OPENAI_API_KEY` 或 `CODEX_API_KEY` 环境变量。\n\n### 4.3 挂载原生 ACP Agent（Gemini、Goose、OpenCode 等）\n\n部分 Agent CLI 内置 ACP 协议支持，但通常需要特定的子命令或标志才能进入 ACP 模式（而非交互终端模式）。\n\n**Gemini CLI**（需 `--experimental-acp` 标志）：\n\n```json\n{\n  \"agents\": [\n    {\n      \"id\": \"gemini-worker\",\n      \"type\": \"worker\",\n      \"command\": \"gemini\",\n      \"args\": [\"--experimental-acp\"],\n      \"workDir\": \"\u002Fworkspace\u002Fgemini-worker\",\n      \"capabilities\": [\"code-generation\", \"analysis\"],\n      \"permissionPolicy\": \"auto-allow\"\n    }\n  ]\n}\n```\n\n**Goose**（需 `acp` 子命令）：\n\n```json\n{\n  \"agents\": [\n    {\n      \"id\": \"goose-worker\",\n      \"type\": \"worker\",\n      \"command\": \"goose\",\n      \"args\": [\"acp\"],\n      \"workDir\": \"\u002Fworkspace\u002Fgoose-worker\",\n      \"capabilities\": [\"general\"],\n      \"permissionPolicy\": \"auto-allow\"\n    }\n  ]\n}\n```\n\n**OpenCode**（需 `acp` 子命令）：\n\n```json\n{\n  \"agents\": [\n    {\n      \"id\": \"opencode-worker\",\n      \"type\": \"worker\",\n      \"command\": \"opencode\",\n      \"args\": [\"acp\"],\n      \"workDir\": \"\u002Fworkspace\u002Fopencode-worker\",\n      \"capabilities\": [\"code-generation\", \"refactor\"]\n    }\n  ]\n}\n```\n\n### 4.4 挂载自定义 ACP Agent\n\n任何实现了 ACP 协议的程序都可以作为 Worker。ACP 协议要求：\n\n- 通过 **stdin** 接收 JSON-RPC 2.0 消息（换行分隔 NDJSON）\n- 通过 **stdout** 发送 JSON-RPC 2.0 响应（换行分隔 NDJSON）\n- stderr 用于日志（不参与协议通信）\n\n**Python ACP Agent 示例**：\n\n```json\n{\n  \"agents\": [\n    {\n      \"id\": \"python-analyzer\",\n      \"type\": \"worker\",\n      \"command\": \"python\",\n      \"args\": [\".\u002Fmy_agent.py\"],\n      \"workDir\": \"\u002Fworkspace\u002Fpython-agent\",\n      \"capabilities\": [\"data-analysis\", \"python\"],\n      \"acpCapabilities\": {\n        \"fs\": { \"readTextFile\": true }\n      }\n    }\n  ]\n}\n```\n\n**Node.js ACP Agent**：\n\n```json\n{\n  \"agents\": [\n    {\n      \"id\": \"node-agent\",\n      \"type\": \"worker\",\n      \"command\": \"node\",\n      \"args\": [\".\u002Fagent.mjs\"],\n      \"workDir\": \"\u002Fworkspace\u002Fnode-agent\",\n      \"capabilities\": [\"web-scraping\", \"api-testing\"]\n    }\n  ]\n}\n```\n\n### 4.5 挂载 Manager Agent（调度顾问）\n\nManager Agent 不执行任务，而是为 Client Node 提供分发建议：\n\n```json\n{\n  \"dispatchMode\": \"manager\",\n  \"agents\": [\n    {\n      \"id\": \"dispatch-manager\",\n      \"type\": \"manager\",\n      \"command\": \"claude-agent-acp\",\n      \"workDir\": \"\u002Fworkspace\u002Fmanager\",\n      \"acpCapabilities\": {\n        \"fs\": { \"readTextFile\": true, \"writeTextFile\": false },\n        \"terminal\": false\n      }\n    },\n    {\n      \"id\": \"worker-backend\",\n      \"type\": \"worker\",\n      \"command\": \"claude-agent-acp\",\n      \"workDir\": \"\u002Fworkspace\u002Fbackend\",\n      \"capabilities\": [\"backend\", \"api\", \"database\"]\n    },\n    {\n      \"id\": \"worker-frontend\",\n      \"type\": \"worker\",\n      \"command\": \"gemini\",\n      \"args\": [\"--experimental-acp\"],\n      \"workDir\": \"\u002Fworkspace\u002Ffrontend\",\n      \"capabilities\": [\"frontend\", \"react\", \"css\"]\n    }\n  ]\n}\n```\n\nManager 收到的咨询 prompt 包含：任务信息 + 所有可用 Worker 的 ID、能力和状态。Manager 返回 JSON 格式的 `DispatchAdvice`：\n\n```json\n{\n  \"recommendedAgentId\": \"worker-backend\",\n  \"confidence\": 0.9,\n  \"reason\": \"This task involves API endpoint implementation, best suited for the backend worker.\"\n}\n```\n\n### 4.6 多 Worker 集群配置\n\n一个 Client Node 可以挂载多个 Worker，形成专业化分工。不同 Worker 可以使用不同的 Agent：\n\n```json\n{\n  \"name\": \"team-alpha\",\n  \"serverUrl\": \"http:\u002F\u002Fdispatch-server:9800\",\n  \"token\": \"tok_team_alpha\",\n  \"tags\": [\"code-review\", \"testing\", \"docs\", \"refactor\"],\n  \"dispatchMode\": \"hybrid\",\n  \"autoDispatch\": {\n    \"rules\": [\n      { \"taskTags\": [\"code-review\"], \"targetAgentId\": \"reviewer\", \"priority\": 10 },\n      { \"taskTags\": [\"testing\"], \"targetAgentId\": \"tester\", \"priority\": 10 },\n      { \"taskTags\": [\"docs\"], \"targetAgentId\": \"writer\", \"priority\": 5 },\n      { \"taskTags\": [\"refactor\"], \"targetCapabilities\": [\"typescript\"], \"priority\": 8 }\n    ],\n    \"fallbackAction\": \"skip\"\n  },\n  \"agents\": [\n    {\n      \"id\": \"manager\",\n      \"type\": \"manager\",\n      \"command\": \"claude-agent-acp\",\n      \"workDir\": \"\u002Fworkspace\u002Fmanager\"\n    },\n    {\n      \"id\": \"reviewer\",\n      \"type\": \"worker\",\n      \"command\": \"claude-agent-acp\",\n      \"workDir\": \"\u002Fworkspace\u002Freviewer\",\n      \"capabilities\": [\"code-review\", \"security\", \"typescript\", \"python\"]\n    },\n    {\n      \"id\": \"tester\",\n      \"type\": \"worker\",\n      \"command\": \"gemini\",\n      \"args\": [\"--experimental-acp\"],\n      \"workDir\": \"\u002Fworkspace\u002Ftester\",\n      \"capabilities\": [\"testing\", \"typescript\", \"jest\", \"playwright\"]\n    },\n    {\n      \"id\": \"writer\",\n      \"type\": \"worker\",\n      \"command\": \"goose\",\n      \"args\": [\"acp\"],\n      \"workDir\": \"\u002Fworkspace\u002Fwriter\",\n      \"capabilities\": [\"writing\", \"documentation\", \"markdown\"]\n    }\n  ]\n}\n```\n\n### 4.7 Worker 挂载检查清单\n\n挂载新 Worker 前确认以下事项：\n\n| 检查项 | 说明 |\n|--------|------|\n| Agent 支持 ACP 协议 | 原生支持或已安装适配器（参见 4.0 参考表） |\n| `command` 可直接执行 | 在 shell 中运行 `command` 能成功启动（已 `npm i -g` 或在 PATH 中） |\n| API Key 已配置 | 如 `ANTHROPIC_API_KEY`、`OPENAI_API_KEY` 等环境变量已设置 |\n| `workDir` 存在且有写权限 | Client Node 需要在其中创建 `.dispatch\u002F` 目录 |\n| `id` 全局唯一 | 同一 Client Node 下所有 Agent ID 不能重复 |\n| `capabilities` 与规则匹配 | 至少有一条 `autoDispatch.rules` 能路由到此 Worker |\n| 网络可达 | Worker 能通过 IPC 路径连接 Client Node |\n\n---\n\n## Part 5: 提交任务并监听状态\n\n### 5.1 创建任务\n\n**JSON 请求**：\n\n```bash\ncurl -X POST http:\u002F\u002Flocalhost:9800\u002Fapi\u002Fv1\u002Ftasks \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -H \"Authorization: Bearer tok_client_abc123\" \\\n  -d '{\n    \"title\": \"Review PR #42\",\n    \"description\": \"Review the pull request for security issues and code quality.\",\n    \"tags\": [\"code-review\"],\n    \"priority\": \"high\",\n    \"metadata\": { \"repo\": \"my-org\u002Fmy-repo\", \"pr\": 42 }\n  }'\n```\n\n**带附件（multipart）**：\n\n```bash\ncurl -X POST http:\u002F\u002Flocalhost:9800\u002Fapi\u002Fv1\u002Ftasks \\\n  -H \"Authorization: Bearer tok_client_abc123\" \\\n  -F 'data={\"title\":\"Analyze dataset\",\"tags\":[\"data-analysis\"],\"priority\":\"normal\"}' \\\n  -F 'files=@.\u002Fdataset.csv' \\\n  -F 'files=@.\u002Fconfig.yaml'\n```\n\n### 5.2 查询任务\n\n```bash\ncurl http:\u002F\u002Flocalhost:9800\u002Fapi\u002Fv1\u002Ftasks                  # 所有活跃任务\ncurl \"http:\u002F\u002Flocalhost:9800\u002Fapi\u002Fv1\u002Ftasks?status=pending\"  # 按状态\ncurl \"http:\u002F\u002Flocalhost:9800\u002Fapi\u002Fv1\u002Ftasks?tag=code-review\" # 按标签\ncurl \"http:\u002F\u002Flocalhost:9800\u002Fapi\u002Fv1\u002Ftasks?page=1&limit=10\" # 分页\ncurl http:\u002F\u002Flocalhost:9800\u002Fapi\u002Fv1\u002Ftasks\u002F{taskId}          # 单个任务\n```\n\n### 5.3 SSE 流式监听（推荐）\n\n```bash\ncurl -N \"http:\u002F\u002Flocalhost:9800\u002Fapi\u002Fv1\u002Ftasks\u002F{taskId}\u002Fstream?interval=1000&logs=true\"\n```\n\n| 事件 | 说明 | 数据 |\n|------|------|------|\n| `task` | 状态\u002F进度变化 | `{ id, status, progress, progressMessage, claimedBy, updatedAt }` |\n| `logs` | 新交互日志 | `InteractionLogEntry[]` |\n| `done` | 到达终态 | `{ taskId, finalStatus }` |\n| `error` | 轮询出错 | `{ message }` |\n\n**TypeScript 示例**：\n\n```typescript\nfunction watchTask(serverUrl: string, taskId: string): Promise\u003Cstring> {\n  return new Promise((resolve, reject) => {\n    const url = `${serverUrl}\u002Fapi\u002Fv1\u002Ftasks\u002F${taskId}\u002Fstream?interval=1000&logs=true`;\n    const es = new EventSource(url);\n\n    es.addEventListener('task', (e) => {\n      const data = JSON.parse(e.data);\n      console.log(`[${data.status}] ${data.progressMessage ?? ''}`);\n    });\n\n    es.addEventListener('logs', (e) => {\n      for (const entry of JSON.parse(e.data)) {\n        console.log(`  [${entry.type}] ${entry.content.slice(0, 80)}`);\n      }\n    });\n\n    es.addEventListener('done', (e) => {\n      const data = JSON.parse(e.data);\n      es.close();\n      resolve(data.finalStatus);\n    });\n\n    es.addEventListener('error', () => { es.close(); reject(new Error('SSE error')); });\n  });\n}\n```\n\n---\n\n## Part 6: 任务状态机\n\n```\npending ──→ claimed ──→ in_progress ──→ completed\n   │                        │\n   │                        └──→ failed ──→ (release) ──→ pending\n   │\n   └──→ cancelled\n```\n\n| 状态 | 触发 | 说明 |\n|------|------|------|\n| `pending` | 创建任务 \u002F release | 等待被领取 |\n| `claimed` | Worker claim | 已分配给 Worker，尚未开始 |\n| `in_progress` | 首次 progress 上报 | 正在执行中 |\n| `completed` | 产物上传成功 | 终态 |\n| `failed` | Worker 报告失败 | 可通过 release 回到 pending |\n| `cancelled` | 手动取消 | 终态 |\n\n---\n\n## Part 7: Token 鉴权\n\n| 角色 | 用途 | 权限 |\n|------|------|------|\n| `admin` | Dashboard 登录 | 完全权限 |\n| `client` | Client Node \u002F Worker | 完全权限（包括 claim\u002Fcomplete） |\n| `operator` | 外部集成 | 创建\u002F删除\u002F查看任务；**禁止** claim\u002Frelease\u002Fprogress\u002Fcomplete\u002Fcancel |\n\n```bash\n# 登录获取 session token\ncurl -X POST http:\u002F\u002Flocalhost:9800\u002Fapi\u002Fv1\u002Fauth\u002Flogin \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\"username\":\"admin\",\"password\":\"your-password\"}'\n\n# 使用 static token\ncurl -H \"Authorization: Bearer tok_client_abc123\" http:\u002F\u002Flocalhost:9800\u002Fapi\u002Fv1\u002Ftasks\n```\n\n---\n\n## Part 8: 端到端示例\n\n### 8.1 最简单的完整流程\n\n```bash\n#!\u002Fbin\u002Fbash\n# 1. 启动 Server\nDISPATCH_DATA_DIR=\u002Ftmp\u002Fdispatch-demo node packages\u002Fserver\u002Fdist\u002Findex.js &\nsleep 2\n\n# 2. 提交任务\nTASK_ID=$(curl -s -X POST http:\u002F\u002Flocalhost:9800\u002Fapi\u002Fv1\u002Ftasks \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\"title\":\"Demo\",\"tags\":[\"demo\"],\"priority\":\"normal\"}' | jq -r '.id')\necho \"Task: $TASK_ID\"\n\n# 3. 监听（后台）\ncurl -sN \"http:\u002F\u002Flocalhost:9800\u002Fapi\u002Fv1\u002Ftasks\u002F$TASK_ID\u002Fstream?interval=1000\" &\n\n# 4. 模拟 Worker: claim → progress → complete\ncurl -s -X POST \"http:\u002F\u002Flocalhost:9800\u002Fapi\u002Fv1\u002Ftasks\u002F$TASK_ID\u002Fclaim\" \\\n  -H \"Content-Type: application\u002Fjson\" -d '{\"clientId\":\"node-01\",\"agentId\":\"worker-01\"}'\n\ncurl -s -X POST \"http:\u002F\u002Flocalhost:9800\u002Fapi\u002Fv1\u002Ftasks\u002F$TASK_ID\u002Fprogress\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\"clientId\":\"node-01\",\"agentId\":\"worker-01\",\"progress\":50,\"message\":\"Working...\"}'\n\n# 5. 清理\nkill %2 2>\u002Fdev\u002Fnull; kill %1 2>\u002Fdev\u002Fnull\n```\n\n### 8.2 单 Worker 自动化完整部署\n\n```bash\n#!\u002Fbin\u002Fbash\n# 1. 启动 Server\nDISPATCH_DATA_DIR=.\u002Fdata node packages\u002Fserver\u002Fdist\u002Findex.js &\nsleep 2\n\n# 2. 安装 ACP 适配器（以 Claude 为例；若用 Gemini 等原生 ACP Agent 可跳过）\nnpm install -g @zed-industries\u002Fclaude-agent-acp\n\n# 3. 准备 Worker 工作目录\nmkdir -p \u002Fworkspace\u002Fclaude-worker\n\n# 4. 创建 client.config.json\ncat > client.config.json \u003C\u003CEOF\n{\n  \"name\": \"single-worker-node\",\n  \"serverUrl\": \"http:\u002F\u002Flocalhost:9800\",\n  \"tags\": [\"general\"],\n  \"dispatchMode\": \"tag-auto\",\n  \"autoDispatch\": {\n    \"rules\": [{ \"taskTags\": [\"general\"], \"targetAgentId\": \"claude\", \"priority\": 1 }]\n  },\n  \"agents\": [{\n    \"id\": \"claude\",\n    \"type\": \"worker\",\n    \"command\": \"claude-agent-acp\",\n    \"workDir\": \"\u002Fworkspace\u002Fclaude-worker\",\n    \"capabilities\": [\"general\"],\n    \"acpCapabilities\": { \"fs\": { \"readTextFile\": true, \"writeTextFile\": true }, \"terminal\": true },\n    \"permissionPolicy\": \"auto-allow\"\n  }]\n}\nEOF\n\n# 5. 启动 Client Node（Worker 自动就绪）\nnode packages\u002Fclient-node\u002Fdist\u002Fmain.js &\nsleep 3\n\n# 6. 提交任务 → Worker 自动领取并执行\ncurl -X POST http:\u002F\u002Flocalhost:9800\u002Fapi\u002Fv1\u002Ftasks \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\"title\":\"Write unit tests for auth module\",\"tags\":[\"general\"],\"priority\":\"normal\"}'\n\necho \"Task submitted. Worker will pick it up automatically.\"\n```\n\n---\n\n## Part 9: 生产部署注意事项\n\n部署 AgentDispatch 到远程服务器时，请注意以下关键事项。完整详情和排查步骤参见 [故障排查指南](..\u002F..\u002Fdocs\u002Fguide\u002Ftroubleshooting.md)。\n\n| 主题 | 要点 |\n|------|------|\n| **进程管理** | 使用 pm2 \u002F systemd \u002F Docker，避免 `nohup` |\n| **远程 Dashboard** | 设置 `VITE_API_URL=http:\u002F\u002F\u003Cserver-ip>:9800`；详见 [配置指南](..\u002F..\u002Fdocs\u002Fguide\u002Fconfiguration.md#dashboard-远程访问) |\n| **嵌套 Claude 会话** | 用包装脚本 `unset CLAUDECODE` 后再启动 Worker |\n| **inotify（Linux）** | 增加 `max_user_instances` 到 8192+ |\n| **CORS** | Server 已内置支持；反向代理不要重复添加 CORS 头 |\n| **部署检查清单** | 见 [troubleshooting.md — Deployment Checklist](..\u002F..\u002Fdocs\u002Fguide\u002Ftroubleshooting.md#deployment-checklist) |\n\n---\n\n## REST API 快速参考\n\n### 任务管理\n\n| 方法 | 路径 | 说明 |\n|------|------|------|\n| `POST` | `\u002Fapi\u002Fv1\u002Ftasks` | 创建任务 |\n| `GET` | `\u002Fapi\u002Fv1\u002Ftasks` | 列出活跃任务（?status=&tag=&page=&limit=） |\n| `GET` | `\u002Fapi\u002Fv1\u002Ftasks\u002F:id` | 获取单个任务 |\n| `PATCH` | `\u002Fapi\u002Fv1\u002Ftasks\u002F:id` | 更新任务 |\n| `DELETE` | `\u002Fapi\u002Fv1\u002Ftasks\u002F:id` | 删除任务 |\n| `POST` | `\u002Fapi\u002Fv1\u002Ftasks\u002F:id\u002Fclaim` | 领取任务 |\n| `POST` | `\u002Fapi\u002Fv1\u002Ftasks\u002F:id\u002Frelease` | 释放任务 |\n| `POST` | `\u002Fapi\u002Fv1\u002Ftasks\u002F:id\u002Fprogress` | 上报进度 |\n| `POST` | `\u002Fapi\u002Fv1\u002Ftasks\u002F:id\u002Fcomplete` | 完成任务（multipart） |\n| `POST` | `\u002Fapi\u002Fv1\u002Ftasks\u002F:id\u002Fcancel` | 取消任务 |\n| `GET` | `\u002Fapi\u002Fv1\u002Ftasks\u002F:id\u002Fstream` | SSE 流式监听 |\n| `GET\u002FPOST` | `\u002Fapi\u002Fv1\u002Ftasks\u002F:id\u002Flogs` | 交互日志 |\n\n### 客户端管理\n\n| 方法 | 路径 | 说明 |\n|------|------|------|\n| `POST` | `\u002Fapi\u002Fv1\u002Fclients\u002Fregister` | 注册 |\n| `GET` | `\u002Fapi\u002Fv1\u002Fclients` | 列表 |\n| `GET` | `\u002Fapi\u002Fv1\u002Fclients\u002F:id` | 详情 |\n| `DELETE` | `\u002Fapi\u002Fv1\u002Fclients\u002F:id` | 注销 |\n| `POST` | `\u002Fapi\u002Fv1\u002Fclients\u002F:id\u002Fheartbeat` | 心跳 |\n\n### 鉴权\n\n| 方法 | 路径 | 说明 |\n|------|------|------|\n| `POST` | `\u002Fapi\u002Fv1\u002Fauth\u002Flogin` | 登录 |\n| `POST` | `\u002Fapi\u002Fv1\u002Fauth\u002Flogout` | 登出 |\n| `GET` | `\u002Fapi\u002Fv1\u002Fauth\u002Fme` | 验证 Token |\n| `GET` | `\u002Fhealth` | 健康检查（无需鉴权） |\n\n---\n\n## 常见错误码\n\n| 错误码 | HTTP | 说明 |\n|--------|------|------|\n| `TASK_NOT_FOUND` | 404 | 任务不存在 |\n| `TASK_ALREADY_CLAIMED` | 409 | 任务已被其他 Worker 领取，或非 owner 操作 |\n| `TASK_INVALID_TRANSITION` | 400 | 当前状态不允许此操作 |\n| `UNAUTHORIZED` | 401 | Token 缺失或无效 |\n| `FORBIDDEN` | 403 | 角色权限不足 |\n| `VALIDATION_ERROR` | 400 | 请求参数校验失败 |\n| `ARTIFACT_MISSING_ZIP` | 400 | 完成任务时缺少 zip |\n| `ARTIFACT_MISSING_RESULT` | 400 | 完成任务时缺少 result.json |\n\n---\n\n## 数据目录结构\n\n```\n{dataDir}\u002F\n├── tasks\u002F           # 活跃任务 (.json + .md)\n├── tasks-archive\u002F   # 归档任务\n├── attachments\u002F     # 任务输入附件\n├── artifacts\u002F       # 任务产物 (zip + result.json)\n├── clients\u002F         # 客户端注册信息\n└── logs\u002F\n    ├── tasks\u002F       # 按任务 ID 的交互日志 (.jsonl)\n    ├── clients\u002F     # 按客户端 ID 的日志\n    └── server-*.jsonl  # Server 主日志\n```\n","# AgentDispatch 使用指南\n\n## 概述\n\nAgentDispatch 是一个 AI Agent 任务分发平台。核心架构将任务**创建**与**执行**完全解耦：\n\n| 组件 | 职责 |\n|------|------|\n| **Server** | 中心化 REST API 服务，管理任务队列、客户端注册、文件持久化、SSE 推送 |\n| **Client Node** | 执行节点，轮询 Server 获取任务，调度和管理本地 Worker Agent 集群 |\n| **Worker Agent** | 通过 ACP (Agent Client Protocol) 执行具体任务的 AI Agent |\n| **Manager Agent** | 可选的 AI 调度顾问，通过 ACP 向 Client Node 提供分发建议 |\n| **CLI** | `dispatch` 命令行工具，Worker 通过它上报进度、提交产物 |\n\n```\n                            ┌────────────────────────┐\n  任务提交方                 │     Server (:9800)      │\n  (curl \u002F SDK \u002F Dashboard)─→│  REST API + FileStore   │\n                            │  SSE Stream + Auth      │\n                            └────────┬───────────────┘\n                                     │ HTTP (poll\u002Fclaim\u002Fprogress\u002Fcomplete)\n                            ┌────────▼───────────────┐\n                            │     Client Node         │\n                            │  Dispatcher (tag\u002Fmgr)   │\n                            │  AcpController          │\n                            │  WorkerManager          │\n                            │  IPC Server             │\n                            └──┬─────┬─────┬─────────┘\n                   ACP(stdio)  │     │     │  ACP(stdio)\n                     ┌─────────▼┐ ┌──▼──┐ ┌▼──────────┐\n                     │ Worker-01│ │Wk-02│ │Manager Agt │\n                     │(claude)  │ │(gpt)│ │(调度顾问)   │\n                     └──────────┘ └─────┘ └───────────┘\n```\n\n**核心设计理念**：任何支持 ACP 协议（JSON-RPC 2.0 over stdio）的 AI Agent 都可以作为 Worker 挂载到 Client Node 上。\n\n---\n\n## Part 1: 启动 Server\n\n### 1.1 前置条件\n\n- Node.js >= 20.0.0\n- pnpm >= 9.x\n\n### 1.2 安装与构建\n\n```bash\npnpm install\npnpm build\n```\n\n### 1.3 零配置启动\n\n```bash\nnode packages\u002Fserver\u002Fdist\u002Findex.js\n# Server 默认监听 0.0.0.0:9800，数据存储在 .\u002Fdata\u002F\n```\n\n### 1.4 自定义配置\n\n**环境变量方式**（推荐用于快速测试）：\n\n```bash\nDISPATCH_SERVER_PORT=8080 \\\nDISPATCH_DATA_DIR=.\u002Fmy-data \\\nDISPATCH_LOG_LEVEL=debug \\\nDISPATCH_AUTH_ENABLED=true \\\nDISPATCH_AUTH_TOKENS=\"tok_client_abc123,tok_operator_xyz:operator\" \\\nnode packages\u002Fserver\u002Fdist\u002Findex.js\n```\n\n**配置文件方式**（`server.config.json`）：\n\n```json\n{\n  \"host\": \"0.0.0.0\",\n  \"port\": 9800,\n  \"dataDir\": \".\u002Fdata\",\n  \"logLevel\": \"info\",\n  \"auth\": {\n    \"enabled\": true,\n    \"users\": [{ \"username\": \"admin\", \"password\": \"your-password\" }],\n    \"tokens\": [\n      \"tok_client_abc123\",\n      { \"token\": \"tok_operator_xyz\", \"role\": \"operator\" }\n    ]\n  }\n}\n```\n\n### 1.5 验证\n\n```bash\ncurl http:\u002F\u002Flocalhost:9800\u002Fhealth\n# {\"status\":\"ok\",\"version\":\"0.0.1\",\"authEnabled\":false}\n```\n\n### 1.6 环境变量一览\n\n| 变量 | 默认值 | 说明 |\n|------|--------|------|\n| `DISPATCH_SERVER_HOST` | `0.0.0.0` | 监听地址 |\n| `DISPATCH_SERVER_PORT` | `9800` | 监听端口 |\n| `DISPATCH_DATA_DIR` | `.\u002Fdata` | 数据目录 |\n| `DISPATCH_LOG_LEVEL` | `info` | 日志级别 (debug\u002Finfo\u002Fwarn\u002Ferror) |\n| `DISPATCH_AUTH_ENABLED` | `false` | 启用鉴权 |\n| `DISPATCH_AUTH_TOKENS` | — | 静态 Token 列表（逗号分隔，`:role` 后缀可选） |\n\n---\n\n## Part 2: 配置 Client Node\n\n### 2.1 最小可用配置\n\n在工作目录创建 `client.config.json`：\n\n```json\n{\n  \"name\": \"my-node\",\n  \"serverUrl\": \"http:\u002F\u002Flocalhost:9800\",\n  \"tags\": [\"code-review\"],\n  \"dispatchMode\": \"tag-auto\",\n  \"autoDispatch\": {\n    \"rules\": [\n      { \"taskTags\": [\"code-review\"], \"targetAgentId\": \"worker-01\", \"priority\": 10 }\n    ],\n    \"fallbackAction\": \"skip\"\n  },\n  \"agents\": [\n    {\n      \"id\": \"worker-01\",\n      \"type\": \"worker\",\n      \"command\": \"claude-agent-acp\",\n      \"workDir\": \"\u002Fpath\u002Fto\u002Fworkspace\"\n    }\n  ]\n}\n```\n\n### 2.2 完整配置结构\n\n```json\n{\n  \"name\": \"production-node\",\n  \"serverUrl\": \"http:\u002F\u002Fyour-server:9800\",\n  \"token\": \"tok_client_abc123\",\n  \"tags\": [\"code-review\", \"documentation\", \"testing\"],\n  \"dispatchMode\": \"hybrid\",\n  \"polling\": { \"interval\": 10000 },\n  \"heartbeat\": { \"interval\": 30000 },\n  \"ipc\": { \"path\": \"\" },\n  \"autoDispatch\": {\n    \"rules\": [\n      { \"taskTags\": [\"code-review\"], \"targetAgentId\": \"claude-worker\", \"priority\": 10 },\n      { \"taskTags\": [\"documentation\"], \"targetCapabilities\": [\"writing\"], \"priority\": 5 },\n      { \"taskTags\": [\"testing\"], \"targetAgentId\": \"test-worker\", \"priority\": 8 }\n    ],\n    \"fallbackAction\": \"skip\"\n  },\n  \"logging\": {\n    \"dir\": \".\u002Flogs\",\n    \"rotateDaily\": true,\n    \"retainDays\": 30,\n    \"httpLog\": true,\n    \"auditLog\": true,\n    \"agentLog\": true\n  },\n  \"agents\": []\n}\n```\n\n### 2.3 关键字段说明\n\n| 字段 | 必填 | 说明 |\n|------|------|------|\n| `name` | 是 | 节点唯一标识，Server 按此区分客户端 |\n| `serverUrl` | 是 | Server HTTP 地址 |\n| `token` | 启用 auth 时 | Server 分配的 API Token |\n| `tags` | 是 | 节点能处理的任务标签集合 |\n| `dispatchMode` | 是 | 分发策略：`tag-auto` \u002F `manager` \u002F `hybrid` |\n| `autoDispatch.rules` | tag-auto\u002Fhybrid | 按 task tag 匹配 Worker 的规则列表 |\n| `autoDispatch.fallbackAction` | 否 | 无规则匹配时行为：`skip`（默认）\u002F `queue-local` |\n\n### 2.4 分发模式\n\n| 模式 | 工作方式 | 需要 Manager |\n|------|---------|:-----------:|\n| `tag-auto` | 规则引擎按 task tag 匹配 Worker，按 priority 排序 | 否 |\n| `manager` | 每个待分配任务都咨询 Manager Agent，由 AI 决定路由 | 是 |\n| `hybrid` | Manager 在线时用 AI 调度，离线时回退到 tag-auto 规则 | 可选 |\n\n### 2.5 分发规则详解\n\n```json\n{\n  \"taskTags\": [\"backend\", \"api\"],\n  \"targetAgentId\": \"worker-backend\",\n  \"targetCapabilities\": [\"typescript\", \"node\"],\n  \"priority\": 10\n}\n```\n\n| 字段 | 说明 |\n|------|------|\n| `taskTags` | AND 逻辑 — 任务必须包含所有指定 tag 才匹配 |\n| `targetAgentId` | 精确指定 Worker ID |\n| `targetCapabilities` | 按能力匹配 — 选择拥有这些 capabilities 的空闲 Worker |\n| `priority` | 数值越大越优先（多条规则匹配时取最高优先级） |\n\n### 2.6 启动 Client Node\n\n```bash\nnode packages\u002Fclient-node\u002Fdist\u002Fmain.js\n# 或指定配置文件\nDISPATCH_NODE_CONFIG=.\u002Fmy-config.json node packages\u002Fclient-node\u002Fdist\u002Fmain.js\n```\n\nCLI 方式：\n\n```bash\ndispatch start --config .\u002Fclient.config.json\ndispatch start --config .\u002Fclient.config.json --foreground\n```\n\n---\n\n## Part 3: 将 Agent 作为 Worker 挂载（重点）\n\n这是 AgentDispatch 的核心操作——将一个 AI Agent 注册为 Worker，使其能自动接收并执行分发来的任务。\n\n### 3.1 Agent 挂载原理\n\n```\n┌──────────────────────────────────────────────────────────────┐\n│                     Client Node                               │\n│                                                               │\n│  1. Dispatcher 决定: task → worker-01                         │\n│  2. HTTP claim → Server                                       │\n│  3. AcpController.launchAgent():                              │\n│     a. 创建 AgentProcess (spawn 子进程)                        │\n│     b. 注入 DISPATCH_TOKEN + DISPATCH_IPC_PATH                │\n│     c. 通过 stdin\u002Fstdout 建立 ACP JSON-RPC 连接               │\n│     d. 发送 initialize (声明 capabilities)                     │\n│     e. TaskWorkflowRunner 发送 task prompt                    │\n│  4. Worker 执行任务，通过 dispatch CLI 上报进度                  │\n│  5. Worker 完成 → 产物打包 → dispatch worker complete          │\n│  6. AcpController 收集结果 → 上传 Server → 标记 completed      │\n│                                                               │\n│  ┌─────────────────┐  stdio (ACP)  ┌──────────────────┐      │\n│  │  AcpController   │←────────────→│  Worker Process   │      │\n│  │  DispatchAcpClient│              │  (ACP Agent 进程)  │      │\n│  └─────────────────┘               └──────────────────┘      │\n└──────────────────────────────────────────────────────────────┘\n```\n\n### 3.2 AgentConfig 完整字段\n\n每个 Worker 在 `client.config.json` 的 `agents` 数组中注册：\n\n```typescript\ninterface AgentConfig {\n  id: string;                    \u002F\u002F 唯一标识（必填）\n  type: 'manager' | 'worker';   \u002F\u002F 角色（必填）\n  command: string;               \u002F\u002F 启动命令（必填）\n  args?: string[];               \u002F\u002F 额外启动参数\n  workDir: string;               \u002F\u002F 工作目录（必填）\n  capabilities?: string[];       \u002F\u002F 能力标签（用于 dispatch 匹配）\n  autoClaimTags?: string[];      \u002F\u002F 自动认领的任务标签\n  allowMultiProcess?: boolean;   \u002F\u002F 是否允许并行多任务（默认 false）\n  promptTemplate?: string;       \u002F\u002F 自定义 prompt 模板路径\n  acpCapabilities?: {\n    fs?: {\n      readTextFile?: boolean;    \u002F\u002F 允许 Agent 读文件\n      writeTextFile?: boolean;   \u002F\u002F 允许 Agent 写文件\n    };\n    terminal?: boolean;          \u002F\u002F 允许 Agent 使用终端\n  };\n  permissionPolicy?: 'auto-allow' | 'auto-deny' | 'prompt';\n}\n```\n\n### 3.3 关键字段深度说明\n\n#### `command` — Agent 启动命令\n\n第一个 token 是可执行文件，后续 token 是默认参数。`args` 中的参数会追加到末尾。\n\n```json\n{ \"command\": \"claude-agent-acp\", \"args\": [\"--model\", \"sonnet\"] }\n\u002F\u002F 实际执行: claude-agent-acp --model sonnet\n```\n\n**要求**：`command` 启动的进程必须通过 **stdin\u002Fstdout** 进行 ACP 协议通信（JSON-RPC 2.0, newline-delimited JSON）。stderr 用于日志输出，不参与协议。\n\n> **注意**：并非所有 AI Agent CLI 都原生支持 ACP。部分 Agent（如 Claude、Codex）需要通过适配器。\n> 详见 [ACP 兼容 Agent 列表](https:\u002F\u002Fagentclientprotocol.com\u002Fget-started\u002Fagents)。\n\n#### `workDir` — Agent 工作目录\n\nAgent 进程以此目录为 `cwd` 启动。Client Node 会在其中创建：\n\n```\n{workDir}\u002F\n├── .dispatch\u002F\n│   ├── input\u002F{taskIdPrefix}\u002F    ← 下载的任务附件\n│   └── output\u002F{taskIdPrefix}\u002F   ← Agent 应将产物放在这里\n│       ├── artifact.zip         ← 产物压缩包\n│       └── result.json          ← 结构化结果\n└── ... (Agent 自身的文件)\n```\n\n#### `capabilities` — 能力标签\n\n与分发规则的 `targetCapabilities` 配合使用：\n\n```json\n\u002F\u002F 规则: 需要 [\"typescript\", \"testing\"] 能力的 Worker\n{ \"taskTags\": [\"unit-test\"], \"targetCapabilities\": [\"typescript\", \"testing\"] }\n\n\u002F\u002F Worker: 声明自己具备这些能力\n{ \"id\": \"test-bot\", \"capabilities\": [\"typescript\", \"testing\", \"jest\"] }\n\u002F\u002F ✓ 匹配成功（Worker 具备规则要求的所有能力）\n```\n\n#### `acpCapabilities` — ACP 能力声明\n\n在 ACP `initialize` 阶段向 Agent 声明 Client 提供的能力：\n\n```json\n{\n  \"acpCapabilities\": {\n    \"fs\": { \"readTextFile\": true, \"writeTextFile\": true },\n    \"terminal\": true\n  }\n}\n```\n\n| 能力 | 说明 |\n|------|------|\n| `fs.readTextFile` | Agent 可通过 ACP 请求读取 Client 端文件 |\n| `fs.writeTextFile` | Agent 可通过 ACP 请求写入 Client 端文件 |\n| `terminal` | Agent 可通过 ACP 请求执行终端命令 |\n\n#### `permissionPolicy` — 权限策略\n\n当 Agent 通过 ACP 请求使用工具（文件读写、终端）时的审批策略：\n\n| 值 | 行为 |\n|----|------|\n| `auto-allow` | 自动批准所有请求（默认，适合可信 Agent） |\n| `auto-deny` | 自动拒绝所有请求（最安全） |\n| `prompt` | 需要人工审批（当前未完整实现） |\n\n### 3.4 Worker 生命周期\n\n```\n                          Client Node 启动\n                               │\n                    Worker 注册 (config.agents)\n                               │\n                          status: idle\n                               │\n              ┌────────────────▼────────────────┐\n              │   Dispatcher 匹配到合适的任务     │\n              │   HTTP claim → Server             │\n              └────────────────┬────────────────┘\n                               │\n              ┌────────────────▼────────────────┐\n              │   AcpController.launchAgent()    │\n              │   1. spawn(command, {cwd:workDir})│\n              │   2. env += DISPATCH_TOKEN        │\n              │   3. env += DISPATCH_IPC_PATH     │\n              │   4. ACP initialize()             │\n              │   5. ACP prompt(taskContent)       │\n              └────────────────┬────────────────┘\n                               │\n                        status: busy\n                               │\n              ┌────────────────▼────────────────┐\n              │  Worker 执行任务                   │\n              │  - dispatch worker progress ...   │\n              │  - dispatch worker log ...        │\n              │  - 产出 artifact.zip + result.json │\n              │  - dispatch worker complete ...   │\n              └────────────────┬────────────────┘\n                               │\n                   ┌───────────┴───────────┐\n                   ▼                       ▼\n            完成 (completed)         失败 (failed)\n                   │                       │\n            status: idle             auto restart?\n                   │                  (指数退避)\n                   ▼                       │\n            等待下一个任务              status: idle\n```\n\n#### 进程环境变量注入\n\nWorker 进程启动时自动获得两个关键环境变量：\n\n| 变量 | 值 | 用途 |\n|------|-----|------|\n| `DISPATCH_TOKEN` | `wt_\u003Cuuid>` | 临时 Worker Token，仅在本次任务生命周期内有效，任务结束自动撤销 |\n| `DISPATCH_IPC_PATH` | Unix socket \u002F named pipe 路径 | 连接 Client Node IPC Server，用于 `dispatch` CLI 通信 |\n\n#### 自动重启机制\n\nWorker 进程异常退出时（exit code ≠ 0）：\n\n1. 状态标记为 `crashed`\n2. 如有正在执行的任务，自动释放回 `pending`\n3. 如重启次数未超限（默认 3 次），启用指数退避重启：\n   - 第 1 次: 2 秒后\n   - 第 2 次: 4 秒后\n   - 第 3 次: 8 秒后（上限 30 秒）\n4. 重启后状态回到 `idle`，可继续接收新任务\n\n### 3.5 Worker 通过 CLI 与系统交互\n\nWorker 在任务执行过程中使用 `dispatch` CLI：\n\n```bash\n# 上报进度（首次上报触发 claimed → in_progress 转换）\ndispatch worker progress \u003CtaskId> --percent 30 --message \"分析代码中...\"\n\n# 追加工作日志\ndispatch worker log \u003CtaskId> --message \"发现 3 个潜在安全问题\"\n\n# 完成任务（提交产物）\ndispatch worker complete \u003CtaskId> \\\n  --zip .\u002Foutput\u002Fartifact.zip \\\n  --result .\u002Foutput\u002Fresult.json\n\n# 报告失败\ndispatch worker fail \u003CtaskId> --reason \"无法访问代码仓库\"\n\n# 查询当前任务状态\ndispatch worker status \u003CtaskId>\n\n# 心跳（长时间无进度更新时使用）\ndispatch worker heartbeat \u003CtaskId>\n```\n\n### 3.6 ACP 任务分发流程\n\nClient Node 通过 ACP 向 Worker 发送任务时，使用 **TaskWorkflowRunner** 执行多轮对话：\n\n**Pass 1: InitialTaskPass** — 构建任务 prompt，包含：\n- 任务标题、描述、优先级、标签、元数据\n- 附件路径（如有下载）\n- 产物输出目录和格式要求\n- CLI 命令参考\n\n**Pass 2: ArtifactEnforcementPass** — 任务完成后检查产物：\n- 验证 `artifact.zip` 和 `result.json` 是否存在\n- 如产物缺失，向 Agent 发送补救 prompt，要求补充\n- 最终验证通过后才标记任务完成\n\n---\n\n## Part 4: 挂载不同类型的 Agent\n\n> **前提**：并非所有 AI Agent CLI 都原生支持 ACP 协议。部分需要通过**适配器**桥接。\n> 完整列表参见 [ACP 兼容 Agent](https:\u002F\u002Fagentclientprotocol.com\u002Fget-started\u002Fagents)。\n\n### 4.0 ACP 兼容 Agent 参考表\n\n| Agent | ACP 支持 | command | args | 安装方式 |\n|-------|---------|---------|------|---------|\n| **Claude Agent** | 适配器 | `claude-agent-acp` | — | `npm i -g @zed-industries\u002Fclaude-agent-acp` |\n| **Codex CLI** | 适配器 | `codex-acp` | — | `npm i -g @zed-industries\u002Fcodex-acp` |\n| **Gemini CLI** | 原生 | `gemini` | `[\"--experimental-acp\"]` | `npm i -g @google\u002Fgemini-cli` |\n| **Goose** | 原生 | `goose` | `[\"acp\"]` | [block.github.io\u002Fgoose](https:\u002F\u002Fblock.github.io\u002Fgoose\u002Fdocs\u002Fguides\u002Facp-clients) |\n| **OpenCode** | 原生 | `opencode` | `[\"acp\"]` | [open-code.ai](https:\u002F\u002Fopen-code.ai\u002Fdocs\u002Fen\u002Facp) |\n| **Kiro CLI** | 原生 | `kiro` | `[\"acp\"]` | [kiro.dev\u002Fcli](https:\u002F\u002Fkiro.dev\u002Fcli\u002F) |\n| **Kimi CLI** | 原生 | `kimi` | `[\"acp\"]` | [github.com\u002FMoonshotAI\u002Fkimi-cli](https:\u002F\u002Fgithub.com\u002FMoonshotAI\u002Fkimi-cli) |\n| **Augment Code** | 原生 | `auggie` | `[\"--acp\"]` | [docs.augmentcode.com\u002Fcli\u002Facp](https:\u002F\u002Fdocs.augmentcode.com\u002Fcli\u002Facp\u002Fagent) |\n| **Cline** | 原生 | `cline` | `[\"--acp\"]` | [docs.cline.bot](https:\u002F\u002Fdocs.cline.bot\u002Fcline-cli\u002Facp-editor-integrations) |\n| **Qwen Code** | 原生 | `qwen` | `[\"--acp\"]` | `npm i -g @qwen-code\u002Fqwen-code` |\n| **Mistral Vibe** | 原生 | `vibe-acp` | — | [github.com\u002Fmistralai\u002Fmistral-vibe](https:\u002F\u002Fgithub.com\u002Fmistralai\u002Fmistral-vibe\u002Fblob\u002Fmain\u002Fdocs\u002Facp-setup.md) |\n| **OpenHands** | 原生 | `openhands` | `[\"acp\"]` | [docs.openhands.dev](https:\u002F\u002Fdocs.openhands.dev\u002Fopenhands\u002Fusage\u002Frun-openhands\u002Facp) |\n| **GitHub Copilot** | 公测 | — | — | [github.com\u002Ffeatures\u002Fcopilot](https:\u002F\u002Fgithub.com\u002Ffeatures\u002Fcopilot) |\n| **Pi** | 适配器 | `pi-acp` | — | [github.com\u002Fsvkozak\u002Fpi-acp](https:\u002F\u002Fgithub.com\u002Fsvkozak\u002Fpi-acp) |\n| 自定义 Agent | 需自行实现 | `node .\u002Fagent.mjs` | — | 使用 ACP SDK（TypeScript\u002FPython\u002FRust\u002FKotlin） |\n\n> **重要**：很多 Agent CLI 的\"普通模式\"是交互式终端，不等于 ACP 模式。必须使用上表中对应的 `args` 参数才能进入 ACP stdio 通信模式。\n\nACP SDK 库：\n- TypeScript: `@anthropic-ai\u002Fagent-client-protocol` — [文档](https:\u002F\u002Fagentclientprotocol.com\u002Flibraries\u002Ftypescript)\n- Python: `agent-client-protocol` — [文档](https:\u002F\u002Fagentclientprotocol.com\u002Flibraries\u002Fpython)\n- Rust: — [文档](https:\u002F\u002Fagentclientprotocol.com\u002Flibraries\u002Frust)\n- Kotlin: — [文档](https:\u002F\u002Fagentclientprotocol.com\u002Flibraries\u002Fkotlin)\n\n### 4.1 挂载 Claude Agent\n\nClaude Code **不原生支持 ACP**，需通过 Zed 官方的 [`claude-agent-acp`](https:\u002F\u002Fgithub.com\u002Fzed-industries\u002Fclaude-agent-acp) 适配器桥接。\n\n**安装适配器**：\n\n```bash\nnpm install -g @zed-industries\u002Fclaude-agent-acp\n```\n\n**配置**：\n\n```json\n{\n  \"agents\": [\n    {\n      \"id\": \"claude-reviewer\",\n      \"type\": \"worker\",\n      \"command\": \"claude-agent-acp\",\n      \"args\": [\"--model\", \"sonnet\"],\n      \"workDir\": \"\u002Fworkspace\u002Fclaude-reviewer\",\n      \"capabilities\": [\"code-review\", \"security-audit\", \"typescript\"],\n      \"acpCapabilities\": {\n        \"fs\": { \"readTextFile\": true, \"writeTextFile\": true },\n        \"terminal\": true\n      },\n      \"permissionPolicy\": \"auto-allow\"\n    }\n  ]\n}\n```\n\n> 适配器通过 Claude Agent SDK 调用 Claude，需要设置 `ANTHROPIC_API_KEY` 环境变量。\n> 也可下载[预编译二进制](https:\u002F\u002Fgithub.com\u002Fzed-industries\u002Fclaude-agent-acp\u002Freleases)，无需 Node.js。\n\n### 4.2 挂载 Codex Agent\n\nOpenAI Codex CLI 同样需通过 [`codex-acp`](https:\u002F\u002Fgithub.com\u002Fzed-industries\u002Fcodex-acp) 适配器：\n\n```bash\nnpm install -g @zed-industries\u002Fcodex-acp\n```\n\n```json\n{\n  \"agents\": [\n    {\n      \"id\": \"codex-worker\",\n      \"type\": \"worker\",\n      \"command\": \"codex-acp\",\n      \"workDir\": \"\u002Fworkspace\u002Fcodex-worker\",\n      \"capabilities\": [\"code-generation\", \"refactor\"],\n      \"permissionPolicy\": \"auto-allow\"\n    }\n  ]\n}\n```\n\n> 需要设置 `OPENAI_API_KEY` 或 `CODEX_API_KEY` 环境变量。\n\n### 4.3 挂载原生 ACP Agent（Gemini、Goose、OpenCode 等）\n\n部分 Agent CLI 内置 ACP 协议支持，但通常需要特定的子命令或标志才能进入 ACP 模式（而非交互终端模式）。\n\n**Gemini CLI**（需 `--experimental-acp` 标志）：\n\n```json\n{\n  \"agents\": [\n    {\n      \"id\": \"gemini-worker\",\n      \"type\": \"worker\",\n      \"command\": \"gemini\",\n      \"args\": [\"--experimental-acp\"],\n      \"workDir\": \"\u002Fworkspace\u002Fgemini-worker\",\n      \"capabilities\": [\"code-generation\", \"analysis\"],\n      \"permissionPolicy\": \"auto-allow\"\n    }\n  ]\n}\n```\n\n**Goose**（需 `acp` 子命令）：\n\n```json\n{\n  \"agents\": [\n    {\n      \"id\": \"goose-worker\",\n      \"type\": \"worker\",\n      \"command\": \"goose\",\n      \"args\": [\"acp\"],\n      \"workDir\": \"\u002Fworkspace\u002Fgoose-worker\",\n      \"capabilities\": [\"general\"],\n      \"permissionPolicy\": \"auto-allow\"\n    }\n  ]\n}\n```\n\n**OpenCode**（需 `acp` 子命令）：\n\n```json\n{\n  \"agents\": [\n    {\n      \"id\": \"opencode-worker\",\n      \"type\": \"worker\",\n      \"command\": \"opencode\",\n      \"args\": [\"acp\"],\n      \"workDir\": \"\u002Fworkspace\u002Fopencode-worker\",\n      \"capabilities\": [\"code-generation\", \"refactor\"]\n    }\n  ]\n}\n```\n\n### 4.4 挂载自定义 ACP Agent\n\n任何实现了 ACP 协议的程序都可以作为 Worker。ACP 协议要求：\n\n- 通过 **stdin** 接收 JSON-RPC 2.0 消息（换行分隔 NDJSON）\n- 通过 **stdout** 发送 JSON-RPC 2.0 响应（换行分隔 NDJSON）\n- stderr 用于日志（不参与协议通信）\n\n**Python ACP Agent 示例**：\n\n```json\n{\n  \"agents\": [\n    {\n      \"id\": \"python-analyzer\",\n      \"type\": \"worker\",\n      \"command\": \"python\",\n      \"args\": [\".\u002Fmy_agent.py\"],\n      \"workDir\": \"\u002Fworkspace\u002Fpython-agent\",\n      \"capabilities\": [\"data-analysis\", \"python\"],\n      \"acpCapabilities\": {\n        \"fs\": { \"readTextFile\": true }\n      }\n    }\n  ]\n}\n```\n\n**Node.js ACP Agent**：\n\n```json\n{\n  \"agents\": [\n    {\n      \"id\": \"node-agent\",\n      \"type\": \"worker\",\n      \"command\": \"node\",\n      \"args\": [\".\u002Fagent.mjs\"],\n      \"workDir\": \"\u002Fworkspace\u002Fnode-agent\",\n      \"capabilities\": [\"web-scraping\", \"api-testing\"]\n    }\n  ]\n}\n```\n\n### 4.5 挂载 Manager Agent（调度顾问）\n\nManager Agent 不执行任务，而是为 Client Node 提供分发建议：\n\n```json\n{\n  \"dispatchMode\": \"manager\",\n  \"agents\": [\n    {\n      \"id\": \"dispatch-manager\",\n      \"type\": \"manager\",\n      \"command\": \"claude-agent-acp\",\n      \"workDir\": \"\u002Fworkspace\u002Fmanager\",\n      \"acpCapabilities\": {\n        \"fs\": { \"readTextFile\": true, \"writeTextFile\": false },\n        \"terminal\": false\n      }\n    },\n    {\n      \"id\": \"worker-backend\",\n      \"type\": \"worker\",\n      \"command\": \"claude-agent-acp\",\n      \"workDir\": \"\u002Fworkspace\u002Fbackend\",\n      \"capabilities\": [\"backend\", \"api\", \"database\"]\n    },\n    {\n      \"id\": \"worker-frontend\",\n      \"type\": \"worker\",\n      \"command\": \"gemini\",\n      \"args\": [\"--experimental-acp\"],\n      \"workDir\": \"\u002Fworkspace\u002Ffrontend\",\n      \"capabilities\": [\"frontend\", \"react\", \"css\"]\n    }\n  ]\n}\n```\n\nManager 收到的咨询 prompt 包含：任务信息 + 所有可用 Worker 的 ID、能力和状态。Manager 返回 JSON 格式的 `DispatchAdvice`：\n\n```json\n{\n  \"recommendedAgentId\": \"worker-backend\",\n  \"confidence\": 0.9,\n  \"reason\": \"This task involves API endpoint implementation, best suited for the backend worker.\"\n}\n```\n\n### 4.6 多 Worker 集群配置\n\n一个 Client Node 可以挂载多个 Worker，形成专业化分工。不同 Worker 可以使用不同的 Agent：\n\n```json\n{\n  \"name\": \"team-alpha\",\n  \"serverUrl\": \"http:\u002F\u002Fdispatch-server:9800\",\n  \"token\": \"tok_team_alpha\",\n  \"tags\": [\"code-review\", \"testing\", \"docs\", \"refactor\"],\n  \"dispatchMode\": \"hybrid\",\n  \"autoDispatch\": {\n    \"rules\": [\n      { \"taskTags\": [\"code-review\"], \"targetAgentId\": \"reviewer\", \"priority\": 10 },\n      { \"taskTags\": [\"testing\"], \"targetAgentId\": \"tester\", \"priority\": 10 },\n      { \"taskTags\": [\"docs\"], \"targetAgentId\": \"writer\", \"priority\": 5 },\n      { \"taskTags\": [\"refactor\"], \"targetCapabilities\": [\"typescript\"], \"priority\": 8 }\n    ],\n    \"fallbackAction\": \"skip\"\n  },\n  \"agents\": [\n    {\n      \"id\": \"manager\",\n      \"type\": \"manager\",\n      \"command\": \"claude-agent-acp\",\n      \"workDir\": \"\u002Fworkspace\u002Fmanager\"\n    },\n    {\n      \"id\": \"reviewer\",\n      \"type\": \"worker\",\n      \"command\": \"claude-agent-acp\",\n      \"workDir\": \"\u002Fworkspace\u002Freviewer\",\n      \"capabilities\": [\"code-review\", \"security\", \"typescript\", \"python\"]\n    },\n    {\n      \"id\": \"tester\",\n      \"type\": \"worker\",\n      \"command\": \"gemini\",\n      \"args\": [\"--experimental-acp\"],\n      \"workDir\": \"\u002Fworkspace\u002Ftester\",\n      \"capabilities\": [\"testing\", \"typescript\", \"jest\", \"playwright\"]\n    },\n    {\n      \"id\": \"writer\",\n      \"type\": \"worker\",\n      \"command\": \"goose\",\n      \"args\": [\"acp\"],\n      \"workDir\": \"\u002Fworkspace\u002Fwriter\",\n      \"capabilities\": [\"writing\", \"documentation\", \"markdown\"]\n    }\n  ]\n}\n```\n\n### 4.7 Worker 挂载检查清单\n\n挂载新 Worker 前确认以下事项：\n\n| 检查项 | 说明 |\n|--------|------|\n| Agent 支持 ACP 协议 | 原生支持或已安装适配器（参见 4.0 参考表） |\n| `command` 可直接执行 | 在 shell 中运行 `command` 能成功启动（已 `npm i -g` 或在 PATH 中） |\n| API Key 已配置 | 如 `ANTHROPIC_API_KEY`、`OPENAI_API_KEY` 等环境变量已设置 |\n| `workDir` 存在且有写权限 | Client Node 需要在其中创建 `.dispatch\u002F` 目录 |\n| `id` 全局唯一 | 同一 Client Node 下所有 Agent ID 不能重复 |\n| `capabilities` 与规则匹配 | 至少有一条 `autoDispatch.rules` 能路由到此 Worker |\n| 网络可达 | Worker 能通过 IPC 路径连接 Client Node |\n\n---\n\n## Part 5: 提交任务并监听状态\n\n### 5.1 创建任务\n\n**JSON 请求**：\n\n```bash\ncurl -X POST http:\u002F\u002Flocalhost:9800\u002Fapi\u002Fv1\u002Ftasks \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -H \"Authorization: Bearer tok_client_abc123\" \\\n  -d '{\n    \"title\": \"Review PR #42\",\n    \"description\": \"Review the pull request for security issues and code quality.\",\n    \"tags\": [\"code-review\"],\n    \"priority\": \"high\",\n    \"metadata\": { \"repo\": \"my-org\u002Fmy-repo\", \"pr\": 42 }\n  }'\n```\n\n**带附件（multipart）**：\n\n```bash\ncurl -X POST http:\u002F\u002Flocalhost:9800\u002Fapi\u002Fv1\u002Ftasks \\\n  -H \"Authorization: Bearer tok_client_abc123\" \\\n  -F 'data={\"title\":\"Analyze dataset\",\"tags\":[\"data-analysis\"],\"priority\":\"normal\"}' \\\n  -F 'files=@.\u002Fdataset.csv' \\\n  -F 'files=@.\u002Fconfig.yaml'\n```\n\n### 5.2 查询任务\n\n```bash\ncurl http:\u002F\u002Flocalhost:9800\u002Fapi\u002Fv1\u002Ftasks                  # 所有活跃任务\ncurl \"http:\u002F\u002Flocalhost:9800\u002Fapi\u002Fv1\u002Ftasks?status=pending\"  # 按状态\ncurl \"http:\u002F\u002Flocalhost:9800\u002Fapi\u002Fv1\u002Ftasks?tag=code-review\" # 按标签\ncurl \"http:\u002F\u002Flocalhost:9800\u002Fapi\u002Fv1\u002Ftasks?page=1&limit=10\" # 分页\ncurl http:\u002F\u002Flocalhost:9800\u002Fapi\u002Fv1\u002Ftasks\u002F{taskId}          # 单个任务\n```\n\n### 5.3 SSE 流式监听（推荐）\n\n```bash\ncurl -N \"http:\u002F\u002Flocalhost:9800\u002Fapi\u002Fv1\u002Ftasks\u002F{taskId}\u002Fstream?interval=1000&logs=true\"\n```\n\n| 事件 | 说明 | 数据 |\n|------|------|------|\n| `task` | 状态\u002F进度变化 | `{ id, status, progress, progressMessage, claimedBy, updatedAt }` |\n| `logs` | 新交互日志 | `InteractionLogEntry[]` |\n| `done` | 到达终态 | `{ taskId, finalStatus }` |\n| `error` | 轮询出错 | `{ message }` |\n\n**TypeScript 示例**：\n\n```typescript\nfunction watchTask(serverUrl: string, taskId: string): Promise\u003Cstring> {\n  return new Promise((resolve, reject) => {\n    const url = `${serverUrl}\u002Fapi\u002Fv1\u002Ftasks\u002F${taskId}\u002Fstream?interval=1000&logs=true`;\n    const es = new EventSource(url);\n\n    es.addEventListener('task', (e) => {\n      const data = JSON.parse(e.data);\n      console.log(`[${data.status}] ${data.progressMessage ?? ''}`);\n    });\n\n    es.addEventListener('logs', (e) => {\n      for (const entry of JSON.parse(e.data)) {\n        console.log(`  [${entry.type}] ${entry.content.slice(0, 80)}`);\n      }\n    });\n\n    es.addEventListener('done', (e) => {\n      const data = JSON.parse(e.data);\n      es.close();\n      resolve(data.finalStatus);\n    });\n\n    es.addEventListener('error', () => { es.close(); reject(new Error('SSE error')); });\n  });\n}\n```\n\n---\n\n## Part 6: 任务状态机\n\n```\npending ──→ claimed ──→ in_progress ──→ completed\n   │                        │\n   │                        └──→ failed ──→ (release) ──→ pending\n   │\n   └──→ cancelled\n```\n\n| 状态 | 触发 | 说明 |\n|------|------|------|\n| `pending` | 创建任务 \u002F release | 等待被领取 |\n| `claimed` | Worker claim | 已分配给 Worker，尚未开始 |\n| `in_progress` | 首次 progress 上报 | 正在执行中 |\n| `completed` | 产物上传成功 | 终态 |\n| `failed` | Worker 报告失败 | 可通过 release 回到 pending |\n| `cancelled` | 手动取消 | 终态 |\n\n---\n\n## Part 7: Token 鉴权\n\n| 角色 | 用途 | 权限 |\n|------|------|------|\n| `admin` | Dashboard 登录 | 完全权限 |\n| `client` | Client Node \u002F Worker | 完全权限（包括 claim\u002Fcomplete） |\n| `operator` | 外部集成 | 创建\u002F删除\u002F查看任务；**禁止** claim\u002Frelease\u002Fprogress\u002Fcomplete\u002Fcancel |\n\n```bash\n# 登录获取 session token\ncurl -X POST http:\u002F\u002Flocalhost:9800\u002Fapi\u002Fv1\u002Fauth\u002Flogin \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\"username\":\"admin\",\"password\":\"your-password\"}'\n\n# 使用 static token\ncurl -H \"Authorization: Bearer tok_client_abc123\" http:\u002F\u002Flocalhost:9800\u002Fapi\u002Fv1\u002Ftasks\n```\n\n---\n\n## Part 8: 端到端示例\n\n### 8.1 最简单的完整流程\n\n```bash\n#!\u002Fbin\u002Fbash\n# 1. 启动 Server\nDISPATCH_DATA_DIR=\u002Ftmp\u002Fdispatch-demo node packages\u002Fserver\u002Fdist\u002Findex.js &\nsleep 2\n\n# 2. 提交任务\nTASK_ID=$(curl -s -X POST http:\u002F\u002Flocalhost:9800\u002Fapi\u002Fv1\u002Ftasks \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\"title\":\"Demo\",\"tags\":[\"demo\"],\"priority\":\"normal\"}' | jq -r '.id')\necho \"Task: $TASK_ID\"\n\n# 3. 监听（后台）\ncurl -sN \"http:\u002F\u002Flocalhost:9800\u002Fapi\u002Fv1\u002Ftasks\u002F$TASK_ID\u002Fstream?interval=1000\" &\n\n# 4. 模拟 Worker: claim → progress → complete\ncurl -s -X POST \"http:\u002F\u002Flocalhost:9800\u002Fapi\u002Fv1\u002Ftasks\u002F$TASK_ID\u002Fclaim\" \\\n  -H \"Content-Type: application\u002Fjson\" -d '{\"clientId\":\"node-01\",\"agentId\":\"worker-01\"}'\n\ncurl -s -X POST \"http:\u002F\u002Flocalhost:9800\u002Fapi\u002Fv1\u002Ftasks\u002F$TASK_ID\u002Fprogress\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\"clientId\":\"node-01\",\"agentId\":\"worker-01\",\"progress\":50,\"message\":\"Working...\"}'\n\n# 5. 清理\nkill %2 2>\u002Fdev\u002Fnull; kill %1 2>\u002Fdev\u002Fnull\n```\n\n### 8.2 单 Worker 自动化完整部署\n\n```bash\n#!\u002Fbin\u002Fbash\n# 1. 启动 Server\nDISPATCH_DATA_DIR=.\u002Fdata node packages\u002Fserver\u002Fdist\u002Findex.js &\nsleep 2\n\n# 2. 安装 ACP 适配器（以 Claude 为例；若用 Gemini 等原生 ACP Agent 可跳过）\nnpm install -g @zed-industries\u002Fclaude-agent-acp\n\n# 3. 准备 Worker 工作目录\nmkdir -p \u002Fworkspace\u002Fclaude-worker\n\n# 4. 创建 client.config.json\ncat > client.config.json \u003C\u003CEOF\n{\n  \"name\": \"single-worker-node\",\n  \"serverUrl\": \"http:\u002F\u002Flocalhost:9800\",\n  \"tags\": [\"general\"],\n  \"dispatchMode\": \"tag-auto\",\n  \"autoDispatch\": {\n    \"rules\": [{ \"taskTags\": [\"general\"], \"targetAgentId\": \"claude\", \"priority\": 1 }]\n  },\n  \"agents\": [{\n    \"id\": \"claude\",\n    \"type\": \"worker\",\n    \"command\": \"claude-agent-acp\",\n    \"workDir\": \"\u002Fworkspace\u002Fclaude-worker\",\n    \"capabilities\": [\"general\"],\n    \"acpCapabilities\": { \"fs\": { \"readTextFile\": true, \"writeTextFile\": true }, \"terminal\": true },\n    \"permissionPolicy\": \"auto-allow\"\n  }]\n}\nEOF\n\n# 5. 启动 Client Node（Worker 自动就绪）\nnode packages\u002Fclient-node\u002Fdist\u002Fmain.js &\nsleep 3\n\n# 6. 提交任务 → Worker 自动领取并执行\ncurl -X POST http:\u002F\u002Flocalhost:9800\u002Fapi\u002Fv1\u002Ftasks \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\"title\":\"Write unit tests for auth module\",\"tags\":[\"general\"],\"priority\":\"normal\"}'\n\necho \"Task submitted. Worker will pick it up automatically.\"\n```\n\n---\n\n## Part 9: 生产部署注意事项\n\n部署 AgentDispatch 到远程服务器时，请注意以下关键事项。完整详情和排查步骤参见 [故障排查指南](..\u002F..\u002Fdocs\u002Fguide\u002Ftroubleshooting.md)。\n\n| 主题 | 要点 |\n|------|------|\n| **进程管理** | 使用 pm2 \u002F systemd \u002F Docker，避免 `nohup` |\n| **远程 Dashboard** | 设置 `VITE_API_URL=http:\u002F\u002F\u003Cserver-ip>:9800`；详见 [配置指南](..\u002F..\u002Fdocs\u002Fguide\u002Fconfiguration.md#dashboard-远程访问) |\n| **嵌套 Claude 会话** | 用包装脚本 `unset CLAUDECODE` 后再启动 Worker |\n| **inotify（Linux）** | 增加 `max_user_instances` 到 8192+ |\n| **CORS** | Server 已内置支持；反向代理不要重复添加 CORS 头 |\n| **部署检查清单** | 见 [troubleshooting.md — Deployment Checklist](..\u002F..\u002Fdocs\u002Fguide\u002Ftroubleshooting.md#deployment-checklist) |\n\n---\n\n## REST API 快速参考\n\n### 任务管理\n\n| 方法 | 路径 | 说明 |\n|------|------|------|\n| `POST` | `\u002Fapi\u002Fv1\u002Ftasks` | 创建任务 |\n| `GET` | `\u002Fapi\u002Fv1\u002Ftasks` | 列出活跃任务（?status=&tag=&page=&limit=） |\n| `GET` | `\u002Fapi\u002Fv1\u002Ftasks\u002F:id` | 获取单个任务 |\n| `PATCH` | `\u002Fapi\u002Fv1\u002Ftasks\u002F:id` | 更新任务 |\n| `DELETE` | `\u002Fapi\u002Fv1\u002Ftasks\u002F:id` | 删除任务 |\n| `POST` | `\u002Fapi\u002Fv1\u002Ftasks\u002F:id\u002Fclaim` | 领取任务 |\n| `POST` | `\u002Fapi\u002Fv1\u002Ftasks\u002F:id\u002Frelease` | 释放任务 |\n| `POST` | `\u002Fapi\u002Fv1\u002Ftasks\u002F:id\u002Fprogress` | 上报进度 |\n| `POST` | `\u002Fapi\u002Fv1\u002Ftasks\u002F:id\u002Fcomplete` | 完成任务（multipart） |\n| `POST` | `\u002Fapi\u002Fv1\u002Ftasks\u002F:id\u002Fcancel` | 取消任务 |\n| `GET` | `\u002Fapi\u002Fv1\u002Ftasks\u002F:id\u002Fstream` | SSE 流式监听 |\n| `GET\u002FPOST` | `\u002Fapi\u002Fv1\u002Ftasks\u002F:id\u002Flogs` | 交互日志 |\n\n### 客户端管理\n\n| 方法 | 路径 | 说明 |\n|------|------|------|\n| `POST` | `\u002Fapi\u002Fv1\u002Fclients\u002Fregister` | 注册 |\n| `GET` | `\u002Fapi\u002Fv1\u002Fclients` | 列表 |\n| `GET` | `\u002Fapi\u002Fv1\u002Fclients\u002F:id` | 详情 |\n| `DELETE` | `\u002Fapi\u002Fv1\u002Fclients\u002F:id` | 注销 |\n| `POST` | `\u002Fapi\u002Fv1\u002Fclients\u002F:id\u002Fheartbeat` | 心跳 |\n\n### 鉴权\n\n| 方法 | 路径 | 说明 |\n|------|------|------|\n| `POST` | `\u002Fapi\u002Fv1\u002Fauth\u002Flogin` | 登录 |\n| `POST` | `\u002Fapi\u002Fv1\u002Fauth\u002Flogout` | 登出 |\n| `GET` | `\u002Fapi\u002Fv1\u002Fauth\u002Fme` | 验证 Token |\n| `GET` | `\u002Fhealth` | 健康检查（无需鉴权） |\n\n---\n\n## 常见错误码\n\n| 错误码 | HTTP | 说明 |\n|--------|------|------|\n| `TASK_NOT_FOUND` | 404 | 任务不存在 |\n| `TASK_ALREADY_CLAIMED` | 409 | 任务已被其他 Worker 领取，或非 owner 操作 |\n| `TASK_INVALID_TRANSITION` | 400 | 当前状态不允许此操作 |\n| `UNAUTHORIZED` | 401 | Token 缺失或无效 |\n| `FORBIDDEN` | 403 | 角色权限不足 |\n| `VALIDATION_ERROR` | 400 | 请求参数校验失败 |\n| `ARTIFACT_MISSING_ZIP` | 400 | 完成任务时缺少 zip |\n| `ARTIFACT_MISSING_RESULT` | 400 | 完成任务时缺少 result.json |\n\n---\n\n## 数据目录结构\n\n```\n{dataDir}\u002F\n├── tasks\u002F           # 活跃任务 (.json + .md)\n├── tasks-archive\u002F   # 归档任务\n├── attachments\u002F     # 任务输入附件\n├── artifacts\u002F       # 任务产物 (zip + result.json)\n├── clients\u002F         # 客户端注册信息\n└── logs\u002F\n    ├── tasks\u002F       # 按任务 ID 的交互日志 (.jsonl)\n    ├── clients\u002F     # 按客户端 ID 的日志\n    └── server-*.jsonl  # Server 主日志\n```\n",{"name":5,"license":14,"description":7,"allowed-tools":48},"Shell, Read, Write, Glob, Grep","master","3a92278a00caef2314e2008a9f50b810363a3d86",".opencode\u002Fskills\u002Fagent-dispatch-use","https:\u002F\u002Fgithub.com\u002Fblackplume233\u002FAgentDispatch","https:\u002F\u002Fgithub.com\u002Fblackplume233","2026-03-03 22:11:55",{"source":8,"skillName":5,"commands":56,"prompt":66,"zipAvailable":67},[57,60,63],{"tool":58,"command":59},"npx","npx skills add blackplume233\u002FAgentDispatch --skill agent-dispatch-use",{"tool":61,"command":62},"bunx","bunx skills add blackplume233\u002FAgentDispatch --skill agent-dispatch-use",{"tool":64,"command":65},"pnpm","pnpm dlx skills add blackplume233\u002FAgentDispatch --skill agent-dispatch-use","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fblackplume233\u002FAgentDispatch\u002Fblob\u002Fmaster\u002F.opencode\u002Fskills\u002Fagent-dispatch-use\u002FSKILL.md",true,[69,75,79,83,89,93,97,101,105,109,113,117,121,125,129,133,137,141,145,149,153,157,161,165,169,173,177,181,185,191,195,199,203,207,211,215,219,223,227,231,235,239,243,247,251,255,259,262,266,270,274,280,284,288,292,296,300,304,308,312,316,320,324,328,332,336,340,344],{"path":70,"resourceType":71,"resourceTypeDesc":72,"sizeBytes":73,"sourceHtmlUrl":74},"DashboardTemplate\u002F.env.example","OTHER","其他",36,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002FPersonal_AI_Infrastructure\u002FReleases\u002Fv4.0.2\u002F.claude\u002Fskills\u002FTelos\u002FDashboardTemplate\u002F.env.example",{"path":76,"resourceType":71,"resourceTypeDesc":72,"sizeBytes":77,"sourceHtmlUrl":78},"DashboardTemplate\u002F.gitignore",430,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002FPersonal_AI_Infrastructure\u002FReleases\u002Fv4.0.2\u002F.claude\u002Fskills\u002FTelos\u002FDashboardTemplate\u002F.gitignore",{"path":80,"resourceType":71,"resourceTypeDesc":72,"sizeBytes":81,"sourceHtmlUrl":82},"DashboardTemplate\u002FApp\u002Fadd-file\u002Fpage.tsx",9705,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002FPersonal_AI_Infrastructure\u002FReleases\u002Fv4.0.2\u002F.claude\u002Fskills\u002FTelos\u002FDashboardTemplate\u002FApp\u002Fadd-file\u002Fpage.tsx",{"path":84,"resourceType":85,"resourceTypeDesc":86,"sizeBytes":87,"sourceHtmlUrl":88},"DashboardTemplate\u002FApp\u002Fapi\u002Fchat\u002Froute.ts","SCRIPT","脚本",2406,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002FPersonal_AI_Infrastructure\u002FReleases\u002Fv4.0.2\u002F.claude\u002Fskills\u002FTelos\u002FDashboardTemplate\u002FApp\u002Fapi\u002Fchat\u002Froute.ts",{"path":90,"resourceType":85,"resourceTypeDesc":86,"sizeBytes":91,"sourceHtmlUrl":92},"DashboardTemplate\u002FApp\u002Fapi\u002Ffile\u002Fget\u002Froute.ts",1042,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002FPersonal_AI_Infrastructure\u002FReleases\u002Fv4.0.2\u002F.claude\u002Fskills\u002FTelos\u002FDashboardTemplate\u002FApp\u002Fapi\u002Ffile\u002Fget\u002Froute.ts",{"path":94,"resourceType":85,"resourceTypeDesc":86,"sizeBytes":95,"sourceHtmlUrl":96},"DashboardTemplate\u002FApp\u002Fapi\u002Ffile\u002Fsave\u002Froute.ts",1622,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002FPersonal_AI_Infrastructure\u002FReleases\u002Fv4.0.2\u002F.claude\u002Fskills\u002FTelos\u002FDashboardTemplate\u002FApp\u002Fapi\u002Ffile\u002Fsave\u002Froute.ts",{"path":98,"resourceType":85,"resourceTypeDesc":86,"sizeBytes":99,"sourceHtmlUrl":100},"DashboardTemplate\u002FApp\u002Fapi\u002Ffiles\u002Fcount\u002Froute.ts",516,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002FPersonal_AI_Infrastructure\u002FReleases\u002Fv4.0.2\u002F.claude\u002Fskills\u002FTelos\u002FDashboardTemplate\u002FApp\u002Fapi\u002Ffiles\u002Fcount\u002Froute.ts",{"path":102,"resourceType":85,"resourceTypeDesc":86,"sizeBytes":103,"sourceHtmlUrl":104},"DashboardTemplate\u002FApp\u002Fapi\u002Fupload\u002Froute.ts",2481,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002FPersonal_AI_Infrastructure\u002FReleases\u002Fv4.0.2\u002F.claude\u002Fskills\u002FTelos\u002FDashboardTemplate\u002FApp\u002Fapi\u002Fupload\u002Froute.ts",{"path":106,"resourceType":71,"resourceTypeDesc":72,"sizeBytes":107,"sourceHtmlUrl":108},"DashboardTemplate\u002FApp\u002Fask\u002Fpage.tsx",6730,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002FPersonal_AI_Infrastructure\u002FReleases\u002Fv4.0.2\u002F.claude\u002Fskills\u002FTelos\u002FDashboardTemplate\u002FApp\u002Fask\u002Fpage.tsx",{"path":110,"resourceType":71,"resourceTypeDesc":72,"sizeBytes":111,"sourceHtmlUrl":112},"DashboardTemplate\u002FApp\u002Ffile\u002F[slug]\u002Fpage.tsx",6483,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002FPersonal_AI_Infrastructure\u002FReleases\u002Fv4.0.2\u002F.claude\u002Fskills\u002FTelos\u002FDashboardTemplate\u002FApp\u002Ffile\u002F[slug]\u002Fpage.tsx",{"path":114,"resourceType":71,"resourceTypeDesc":72,"sizeBytes":115,"sourceHtmlUrl":116},"DashboardTemplate\u002FApp\u002Fglobals.css",633,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002FPersonal_AI_Infrastructure\u002FReleases\u002Fv4.0.2\u002F.claude\u002Fskills\u002FTelos\u002FDashboardTemplate\u002FApp\u002Fglobals.css",{"path":118,"resourceType":71,"resourceTypeDesc":72,"sizeBytes":119,"sourceHtmlUrl":120},"DashboardTemplate\u002FApp\u002Flayout.tsx",604,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002FPersonal_AI_Infrastructure\u002FReleases\u002Fv4.0.2\u002F.claude\u002Fskills\u002FTelos\u002FDashboardTemplate\u002FApp\u002Flayout.tsx",{"path":122,"resourceType":71,"resourceTypeDesc":72,"sizeBytes":123,"sourceHtmlUrl":124},"DashboardTemplate\u002FApp\u002Fpage.tsx",5258,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002FPersonal_AI_Infrastructure\u002FReleases\u002Fv4.0.2\u002F.claude\u002Fskills\u002FTelos\u002FDashboardTemplate\u002FApp\u002Fpage.tsx",{"path":126,"resourceType":71,"resourceTypeDesc":72,"sizeBytes":127,"sourceHtmlUrl":128},"DashboardTemplate\u002FApp\u002Fprogress\u002Fpage.tsx",3714,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002FPersonal_AI_Infrastructure\u002FReleases\u002Fv4.0.2\u002F.claude\u002Fskills\u002FTelos\u002FDashboardTemplate\u002FApp\u002Fprogress\u002Fpage.tsx",{"path":130,"resourceType":71,"resourceTypeDesc":72,"sizeBytes":131,"sourceHtmlUrl":132},"DashboardTemplate\u002FApp\u002Fteams\u002Fpage.tsx",3130,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002FPersonal_AI_Infrastructure\u002FReleases\u002Fv4.0.2\u002F.claude\u002Fskills\u002FTelos\u002FDashboardTemplate\u002FApp\u002Fteams\u002Fpage.tsx",{"path":134,"resourceType":71,"resourceTypeDesc":72,"sizeBytes":135,"sourceHtmlUrl":136},"DashboardTemplate\u002FApp\u002Fvulnerabilities\u002Fpage.tsx",4140,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002FPersonal_AI_Infrastructure\u002FReleases\u002Fv4.0.2\u002F.claude\u002Fskills\u002FTelos\u002FDashboardTemplate\u002FApp\u002Fvulnerabilities\u002Fpage.tsx",{"path":138,"resourceType":71,"resourceTypeDesc":72,"sizeBytes":139,"sourceHtmlUrl":140},"DashboardTemplate\u002Fbun.lock",28940,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002FPersonal_AI_Infrastructure\u002FReleases\u002Fv4.0.2\u002F.claude\u002Fskills\u002FTelos\u002FDashboardTemplate\u002Fbun.lock",{"path":142,"resourceType":71,"resourceTypeDesc":72,"sizeBytes":143,"sourceHtmlUrl":144},"DashboardTemplate\u002FComponents\u002Fsidebar.tsx",5131,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002FPersonal_AI_Infrastructure\u002FReleases\u002Fv4.0.2\u002F.claude\u002Fskills\u002FTelos\u002FDashboardTemplate\u002FComponents\u002Fsidebar.tsx",{"path":146,"resourceType":71,"resourceTypeDesc":72,"sizeBytes":147,"sourceHtmlUrl":148},"DashboardTemplate\u002FComponents\u002FUi\u002Fbadge.tsx",1350,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002FPersonal_AI_Infrastructure\u002FReleases\u002Fv4.0.2\u002F.claude\u002Fskills\u002FTelos\u002FDashboardTemplate\u002FComponents\u002FUi\u002Fbadge.tsx",{"path":150,"resourceType":71,"resourceTypeDesc":72,"sizeBytes":151,"sourceHtmlUrl":152},"DashboardTemplate\u002FComponents\u002FUi\u002Fbutton.tsx",1915,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002FPersonal_AI_Infrastructure\u002FReleases\u002Fv4.0.2\u002F.claude\u002Fskills\u002FTelos\u002FDashboardTemplate\u002FComponents\u002FUi\u002Fbutton.tsx",{"path":154,"resourceType":71,"resourceTypeDesc":72,"sizeBytes":155,"sourceHtmlUrl":156},"DashboardTemplate\u002FComponents\u002FUi\u002Fcard.tsx",1846,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002FPersonal_AI_Infrastructure\u002FReleases\u002Fv4.0.2\u002F.claude\u002Fskills\u002FTelos\u002FDashboardTemplate\u002FComponents\u002FUi\u002Fcard.tsx",{"path":158,"resourceType":71,"resourceTypeDesc":72,"sizeBytes":159,"sourceHtmlUrl":160},"DashboardTemplate\u002FComponents\u002FUi\u002Fprogress.tsx",812,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002FPersonal_AI_Infrastructure\u002FReleases\u002Fv4.0.2\u002F.claude\u002Fskills\u002FTelos\u002FDashboardTemplate\u002FComponents\u002FUi\u002Fprogress.tsx",{"path":162,"resourceType":71,"resourceTypeDesc":72,"sizeBytes":163,"sourceHtmlUrl":164},"DashboardTemplate\u002FComponents\u002FUi\u002Ftable.tsx",2757,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002FPersonal_AI_Infrastructure\u002FReleases\u002Fv4.0.2\u002F.claude\u002Fskills\u002FTelos\u002FDashboardTemplate\u002FComponents\u002FUi\u002Ftable.tsx",{"path":166,"resourceType":85,"resourceTypeDesc":86,"sizeBytes":167,"sourceHtmlUrl":168},"DashboardTemplate\u002FLib\u002Fdata.ts",2665,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002FPersonal_AI_Infrastructure\u002FReleases\u002Fv4.0.2\u002F.claude\u002Fskills\u002FTelos\u002FDashboardTemplate\u002FLib\u002Fdata.ts",{"path":170,"resourceType":85,"resourceTypeDesc":86,"sizeBytes":171,"sourceHtmlUrl":172},"DashboardTemplate\u002FLib\u002Ftelos-data.ts",3299,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002FPersonal_AI_Infrastructure\u002FReleases\u002Fv4.0.2\u002F.claude\u002Fskills\u002FTelos\u002FDashboardTemplate\u002FLib\u002Ftelos-data.ts",{"path":174,"resourceType":85,"resourceTypeDesc":86,"sizeBytes":175,"sourceHtmlUrl":176},"DashboardTemplate\u002FLib\u002Futils.ts",166,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002FPersonal_AI_Infrastructure\u002FReleases\u002Fv4.0.2\u002F.claude\u002Fskills\u002FTelos\u002FDashboardTemplate\u002FLib\u002Futils.ts",{"path":178,"resourceType":85,"resourceTypeDesc":86,"sizeBytes":179,"sourceHtmlUrl":180},"DashboardTemplate\u002Fnext-env.d.ts",262,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002FPersonal_AI_Infrastructure\u002FReleases\u002Fv4.0.2\u002F.claude\u002Fskills\u002FTelos\u002FDashboardTemplate\u002Fnext-env.d.ts",{"path":182,"resourceType":85,"resourceTypeDesc":86,"sizeBytes":183,"sourceHtmlUrl":184},"DashboardTemplate\u002Fnext.config.mjs",92,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002FPersonal_AI_Infrastructure\u002FReleases\u002Fv4.0.2\u002F.claude\u002Fskills\u002FTelos\u002FDashboardTemplate\u002Fnext.config.mjs",{"path":186,"resourceType":187,"resourceTypeDesc":188,"sizeBytes":189,"sourceHtmlUrl":190},"DashboardTemplate\u002Fpackage.json","REFERENCE","参考文档",759,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002FPersonal_AI_Infrastructure\u002FReleases\u002Fv4.0.2\u002F.claude\u002Fskills\u002FTelos\u002FDashboardTemplate\u002Fpackage.json",{"path":192,"resourceType":85,"resourceTypeDesc":86,"sizeBytes":193,"sourceHtmlUrl":194},"DashboardTemplate\u002Fpostcss.config.mjs",146,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002FPersonal_AI_Infrastructure\u002FReleases\u002Fv4.0.2\u002F.claude\u002Fskills\u002FTelos\u002FDashboardTemplate\u002Fpostcss.config.mjs",{"path":196,"resourceType":187,"resourceTypeDesc":188,"sizeBytes":197,"sourceHtmlUrl":198},"DashboardTemplate\u002FREADME.md",12693,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002FPersonal_AI_Infrastructure\u002FReleases\u002Fv4.0.2\u002F.claude\u002Fskills\u002FTelos\u002FDashboardTemplate\u002FREADME.md",{"path":200,"resourceType":85,"resourceTypeDesc":86,"sizeBytes":201,"sourceHtmlUrl":202},"DashboardTemplate\u002Ftailwind.config.ts",515,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002FPersonal_AI_Infrastructure\u002FReleases\u002Fv4.0.2\u002F.claude\u002Fskills\u002FTelos\u002FDashboardTemplate\u002Ftailwind.config.ts",{"path":204,"resourceType":187,"resourceTypeDesc":188,"sizeBytes":205,"sourceHtmlUrl":206},"DashboardTemplate\u002Ftsconfig.json",989,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002FPersonal_AI_Infrastructure\u002FReleases\u002Fv4.0.2\u002F.claude\u002Fskills\u002FTelos\u002FDashboardTemplate\u002Ftsconfig.json",{"path":208,"resourceType":71,"resourceTypeDesc":72,"sizeBytes":209,"sourceHtmlUrl":210},"ReportTemplate\u002FApp\u002Fglobals.css",11237,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002FPersonal_AI_Infrastructure\u002FReleases\u002Fv4.0.2\u002F.claude\u002Fskills\u002FTelos\u002FReportTemplate\u002FApp\u002Fglobals.css",{"path":212,"resourceType":71,"resourceTypeDesc":72,"sizeBytes":213,"sourceHtmlUrl":214},"ReportTemplate\u002FApp\u002Flayout.tsx",442,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002FPersonal_AI_Infrastructure\u002FReleases\u002Fv4.0.2\u002F.claude\u002Fskills\u002FTelos\u002FReportTemplate\u002FApp\u002Flayout.tsx",{"path":216,"resourceType":71,"resourceTypeDesc":72,"sizeBytes":217,"sourceHtmlUrl":218},"ReportTemplate\u002FApp\u002Fpage.tsx",10475,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002FPersonal_AI_Infrastructure\u002FReleases\u002Fv4.0.2\u002F.claude\u002Fskills\u002FTelos\u002FReportTemplate\u002FApp\u002Fpage.tsx",{"path":220,"resourceType":71,"resourceTypeDesc":72,"sizeBytes":221,"sourceHtmlUrl":222},"ReportTemplate\u002FComponents\u002Fcallout.tsx",316,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002FPersonal_AI_Infrastructure\u002FReleases\u002Fv4.0.2\u002F.claude\u002Fskills\u002FTelos\u002FReportTemplate\u002FComponents\u002Fcallout.tsx",{"path":224,"resourceType":71,"resourceTypeDesc":72,"sizeBytes":225,"sourceHtmlUrl":226},"ReportTemplate\u002FComponents\u002Fcover-page.tsx",1116,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002FPersonal_AI_Infrastructure\u002FReleases\u002Fv4.0.2\u002F.claude\u002Fskills\u002FTelos\u002FReportTemplate\u002FComponents\u002Fcover-page.tsx",{"path":228,"resourceType":71,"resourceTypeDesc":72,"sizeBytes":229,"sourceHtmlUrl":230},"ReportTemplate\u002FComponents\u002Fexhibit.tsx",594,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002FPersonal_AI_Infrastructure\u002FReleases\u002Fv4.0.2\u002F.claude\u002Fskills\u002FTelos\u002FReportTemplate\u002FComponents\u002Fexhibit.tsx",{"path":232,"resourceType":71,"resourceTypeDesc":72,"sizeBytes":233,"sourceHtmlUrl":234},"ReportTemplate\u002FComponents\u002Ffinding-card.tsx",970,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002FPersonal_AI_Infrastructure\u002FReleases\u002Fv4.0.2\u002F.claude\u002Fskills\u002FTelos\u002FReportTemplate\u002FComponents\u002Ffinding-card.tsx",{"path":236,"resourceType":71,"resourceTypeDesc":72,"sizeBytes":237,"sourceHtmlUrl":238},"ReportTemplate\u002FComponents\u002Fquote-block.tsx",407,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002FPersonal_AI_Infrastructure\u002FReleases\u002Fv4.0.2\u002F.claude\u002Fskills\u002FTelos\u002FReportTemplate\u002FComponents\u002Fquote-block.tsx",{"path":240,"resourceType":71,"resourceTypeDesc":72,"sizeBytes":241,"sourceHtmlUrl":242},"ReportTemplate\u002FComponents\u002Frecommendation-card.tsx",1507,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002FPersonal_AI_Infrastructure\u002FReleases\u002Fv4.0.2\u002F.claude\u002Fskills\u002FTelos\u002FReportTemplate\u002FComponents\u002Frecommendation-card.tsx",{"path":244,"resourceType":71,"resourceTypeDesc":72,"sizeBytes":245,"sourceHtmlUrl":246},"ReportTemplate\u002FComponents\u002Fsection.tsx",329,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002FPersonal_AI_Infrastructure\u002FReleases\u002Fv4.0.2\u002F.claude\u002Fskills\u002FTelos\u002FReportTemplate\u002FComponents\u002Fsection.tsx",{"path":248,"resourceType":71,"resourceTypeDesc":72,"sizeBytes":249,"sourceHtmlUrl":250},"ReportTemplate\u002FComponents\u002Fseverity-badge.tsx",684,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002FPersonal_AI_Infrastructure\u002FReleases\u002Fv4.0.2\u002F.claude\u002Fskills\u002FTelos\u002FReportTemplate\u002FComponents\u002Fseverity-badge.tsx",{"path":252,"resourceType":71,"resourceTypeDesc":72,"sizeBytes":253,"sourceHtmlUrl":254},"ReportTemplate\u002FComponents\u002Ftimeline.tsx",649,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002FPersonal_AI_Infrastructure\u002FReleases\u002Fv4.0.2\u002F.claude\u002Fskills\u002FTelos\u002FReportTemplate\u002FComponents\u002Ftimeline.tsx",{"path":256,"resourceType":85,"resourceTypeDesc":86,"sizeBytes":257,"sourceHtmlUrl":258},"ReportTemplate\u002FLib\u002Freport-data.ts",5427,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002FPersonal_AI_Infrastructure\u002FReleases\u002Fv4.0.2\u002F.claude\u002Fskills\u002FTelos\u002FReportTemplate\u002FLib\u002Freport-data.ts",{"path":260,"resourceType":85,"resourceTypeDesc":86,"sizeBytes":175,"sourceHtmlUrl":261},"ReportTemplate\u002FLib\u002Futils.ts","https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002FPersonal_AI_Infrastructure\u002FReleases\u002Fv4.0.2\u002F.claude\u002Fskills\u002FTelos\u002FReportTemplate\u002FLib\u002Futils.ts",{"path":263,"resourceType":85,"resourceTypeDesc":86,"sizeBytes":264,"sourceHtmlUrl":265},"ReportTemplate\u002Fnext-env.d.ts",201,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002FPersonal_AI_Infrastructure\u002FReleases\u002Fv4.0.2\u002F.claude\u002Fskills\u002FTelos\u002FReportTemplate\u002Fnext-env.d.ts",{"path":267,"resourceType":187,"resourceTypeDesc":188,"sizeBytes":268,"sourceHtmlUrl":269},"ReportTemplate\u002Fpackage.json",615,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002FPersonal_AI_Infrastructure\u002FReleases\u002Fv4.0.2\u002F.claude\u002Fskills\u002FTelos\u002FReportTemplate\u002Fpackage.json",{"path":271,"resourceType":85,"resourceTypeDesc":86,"sizeBytes":272,"sourceHtmlUrl":273},"ReportTemplate\u002Fpostcss.config.js",82,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002FPersonal_AI_Infrastructure\u002FReleases\u002Fv4.0.2\u002F.claude\u002Fskills\u002FTelos\u002FReportTemplate\u002Fpostcss.config.js",{"path":275,"resourceType":276,"resourceTypeDesc":277,"sizeBytes":278,"sourceHtmlUrl":279},"ReportTemplate\u002FPublic\u002FFonts\u002Fadvocate_34_narr_reg.woff2","ASSET","资产文件",24860,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002FPersonal_AI_Infrastructure\u002FReleases\u002Fv4.0.2\u002F.claude\u002Fskills\u002FTelos\u002FReportTemplate\u002FPublic\u002FFonts\u002Fadvocate_34_narr_reg.woff2",{"path":281,"resourceType":276,"resourceTypeDesc":277,"sizeBytes":282,"sourceHtmlUrl":283},"ReportTemplate\u002FPublic\u002FFonts\u002Fadvocate_54_wide_reg.woff2",24776,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002FPersonal_AI_Infrastructure\u002FReleases\u002Fv4.0.2\u002F.claude\u002Fskills\u002FTelos\u002FReportTemplate\u002FPublic\u002FFonts\u002Fadvocate_54_wide_reg.woff2",{"path":285,"resourceType":276,"resourceTypeDesc":277,"sizeBytes":286,"sourceHtmlUrl":287},"ReportTemplate\u002FPublic\u002FFonts\u002Fconcourse_3_bold.woff2",31004,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002FPersonal_AI_Infrastructure\u002FReleases\u002Fv4.0.2\u002F.claude\u002Fskills\u002FTelos\u002FReportTemplate\u002FPublic\u002FFonts\u002Fconcourse_3_bold.woff2",{"path":289,"resourceType":276,"resourceTypeDesc":277,"sizeBytes":290,"sourceHtmlUrl":291},"ReportTemplate\u002FPublic\u002FFonts\u002Fconcourse_3_regular.woff2",31212,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002FPersonal_AI_Infrastructure\u002FReleases\u002Fv4.0.2\u002F.claude\u002Fskills\u002FTelos\u002FReportTemplate\u002FPublic\u002FFonts\u002Fconcourse_3_regular.woff2",{"path":293,"resourceType":276,"resourceTypeDesc":277,"sizeBytes":294,"sourceHtmlUrl":295},"ReportTemplate\u002FPublic\u002FFonts\u002Fconcourse_4_bold.woff2",31060,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002FPersonal_AI_Infrastructure\u002FReleases\u002Fv4.0.2\u002F.claude\u002Fskills\u002FTelos\u002FReportTemplate\u002FPublic\u002FFonts\u002Fconcourse_4_bold.woff2",{"path":297,"resourceType":276,"resourceTypeDesc":277,"sizeBytes":298,"sourceHtmlUrl":299},"ReportTemplate\u002FPublic\u002FFonts\u002Fconcourse_4_regular.woff2",30852,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002FPersonal_AI_Infrastructure\u002FReleases\u002Fv4.0.2\u002F.claude\u002Fskills\u002FTelos\u002FReportTemplate\u002FPublic\u002FFonts\u002Fconcourse_4_regular.woff2",{"path":301,"resourceType":276,"resourceTypeDesc":277,"sizeBytes":302,"sourceHtmlUrl":303},"ReportTemplate\u002FPublic\u002FFonts\u002Fheliotrope_3_caps_regular.woff2",28180,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002FPersonal_AI_Infrastructure\u002FReleases\u002Fv4.0.2\u002F.claude\u002Fskills\u002FTelos\u002FReportTemplate\u002FPublic\u002FFonts\u002Fheliotrope_3_caps_regular.woff2",{"path":305,"resourceType":276,"resourceTypeDesc":277,"sizeBytes":306,"sourceHtmlUrl":307},"ReportTemplate\u002FPublic\u002FFonts\u002Fheliotrope_3_regular.woff2",26968,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002FPersonal_AI_Infrastructure\u002FReleases\u002Fv4.0.2\u002F.claude\u002Fskills\u002FTelos\u002FReportTemplate\u002FPublic\u002FFonts\u002Fheliotrope_3_regular.woff2",{"path":309,"resourceType":276,"resourceTypeDesc":277,"sizeBytes":310,"sourceHtmlUrl":311},"ReportTemplate\u002FPublic\u002FFonts\u002Fvalkyrie_a_bold.woff2",30012,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002FPersonal_AI_Infrastructure\u002FReleases\u002Fv4.0.2\u002F.claude\u002Fskills\u002FTelos\u002FReportTemplate\u002FPublic\u002FFonts\u002Fvalkyrie_a_bold.woff2",{"path":313,"resourceType":276,"resourceTypeDesc":277,"sizeBytes":314,"sourceHtmlUrl":315},"ReportTemplate\u002FPublic\u002FFonts\u002Fvalkyrie_a_italic.woff2",30404,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002FPersonal_AI_Infrastructure\u002FReleases\u002Fv4.0.2\u002F.claude\u002Fskills\u002FTelos\u002FReportTemplate\u002FPublic\u002FFonts\u002Fvalkyrie_a_italic.woff2",{"path":317,"resourceType":276,"resourceTypeDesc":277,"sizeBytes":318,"sourceHtmlUrl":319},"ReportTemplate\u002FPublic\u002FFonts\u002Fvalkyrie_a_regular.woff2",29896,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002FPersonal_AI_Infrastructure\u002FReleases\u002Fv4.0.2\u002F.claude\u002Fskills\u002FTelos\u002FReportTemplate\u002FPublic\u002FFonts\u002Fvalkyrie_a_regular.woff2",{"path":321,"resourceType":85,"resourceTypeDesc":86,"sizeBytes":322,"sourceHtmlUrl":323},"ReportTemplate\u002Ftailwind.config.ts",1802,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002FPersonal_AI_Infrastructure\u002FReleases\u002Fv4.0.2\u002F.claude\u002Fskills\u002FTelos\u002FReportTemplate\u002Ftailwind.config.ts",{"path":325,"resourceType":187,"resourceTypeDesc":188,"sizeBytes":326,"sourceHtmlUrl":327},"ReportTemplate\u002Ftsconfig.json",574,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002FPersonal_AI_Infrastructure\u002FReleases\u002Fv4.0.2\u002F.claude\u002Fskills\u002FTelos\u002FReportTemplate\u002Ftsconfig.json",{"path":329,"resourceType":85,"resourceTypeDesc":86,"sizeBytes":330,"sourceHtmlUrl":331},"Tools\u002FUpdateTelos.ts",6691,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002FPersonal_AI_Infrastructure\u002FReleases\u002Fv4.0.2\u002F.claude\u002Fskills\u002FTelos\u002FTools\u002FUpdateTelos.ts",{"path":333,"resourceType":187,"resourceTypeDesc":188,"sizeBytes":334,"sourceHtmlUrl":335},"Workflows\u002FCreateNarrativePoints.md",16127,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002FPersonal_AI_Infrastructure\u002FReleases\u002Fv4.0.2\u002F.claude\u002Fskills\u002FTelos\u002FWorkflows\u002FCreateNarrativePoints.md",{"path":337,"resourceType":187,"resourceTypeDesc":188,"sizeBytes":338,"sourceHtmlUrl":339},"Workflows\u002FInterviewExtraction.md",8119,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002FPersonal_AI_Infrastructure\u002FReleases\u002Fv4.0.2\u002F.claude\u002Fskills\u002FTelos\u002FWorkflows\u002FInterviewExtraction.md",{"path":341,"resourceType":187,"resourceTypeDesc":188,"sizeBytes":342,"sourceHtmlUrl":343},"Workflows\u002FUpdate.md",9450,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002FPersonal_AI_Infrastructure\u002FReleases\u002Fv4.0.2\u002F.claude\u002Fskills\u002FTelos\u002FWorkflows\u002FUpdate.md",{"path":345,"resourceType":187,"resourceTypeDesc":188,"sizeBytes":346,"sourceHtmlUrl":347},"Workflows\u002FWriteReport.md",20054,"https:\u002F\u002Fgithub.com\u002Ffadrienne\u002FMyGitHub\u002Fblob\u002Fmain\u002FPersonal_AI_Infrastructure\u002FReleases\u002Fv4.0.2\u002F.claude\u002Fskills\u002FTelos\u002FWorkflows\u002FWriteReport.md",[349,370,386,399,415,429],{"skillNo":350,"name":351,"nameZh":6,"description":352,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":353,"categories":354,"keywords":358,"publishedAt":43},"01M6CW3A862TC4XFPS14SVG8M3","qa-monitor","QA 持续监测 SubAgent。监听 git HEAD 变化，每有新 ship（commit）自动触发完整回归测试，无变化时进入可配置间隔的休眠轮询。触发方式：用户提及 \"\u002Fqa-watch\"、\"QA 监测\"、\"continuous QA\"、\"watch ship\" 等关键词时激活。","https:\u002F\u002Fgithub.com\u002Fblackplume233\u002FAgentDispatch\u002Fblob\u002Fmaster\u002F.opencode\u002Fskills\u002Fqa-monitor\u002FSKILL.md",[355],{"categoryNo":356,"categoryName":357,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000008","测试与质量",[359,360,361,362,363,364,40,365,366,29,34,32,31,367,368,369],"monitor","qa","qa monitor","testing","commit","git","ship","subagent","engineer","issue","task",{"skillNo":371,"name":372,"nameZh":6,"description":373,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":374,"categories":375,"keywords":378,"publishedAt":43},"01M6CW36KDT33XESRJE4EQZEZ3","qa-engineer","QA 测试工程师 SubAgent。模拟真实用户通过 CLI\u002FREST API 与 AgentDispatch 交互，智能判断输出和产物是否合理，黑盒为主白盒为辅，发现问题自动创建 Issue。触发方式：用户提及 \"\u002Fqa\"、\"QA run\"、\"QA test\"、\"运行测试场景\" 等关键词时激活。","https:\u002F\u002Fgithub.com\u002Fblackplume233\u002FAgentDispatch\u002Fblob\u002Fmaster\u002F.opencode\u002Fskills\u002Fqa-engineer\u002FSKILL.md",[376,377],{"categoryNo":356,"categoryName":357,"taxonomyType":20,"taxonomyTypeDesc":21},{"categoryNo":18,"categoryName":19,"taxonomyType":20,"taxonomyTypeDesc":21},[360,367,379,362,380,381,382,383,384,40,385,366,29,34,32,31,368,369],"qa engineer","cli","test","run","REST","api","qa test",{"skillNo":387,"name":388,"nameZh":6,"description":389,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":390,"categories":391,"keywords":392,"publishedAt":43},"01M6CW34K4423W6Z48RE8SP860","pr-watcher","PR 轮询守护 SubAgent。持续监控 GitHub 上的 Open PR，自动调用 pr-handler 逐一处理，连续 N 轮无新可处理 PR 后退出。触发方式：用户提及 \"\u002Fwatch-prs\"、\"轮询 PR\"、\"watch prs\" 等关键词时激活。","https:\u002F\u002Fgithub.com\u002Fblackplume233\u002FAgentDispatch\u002Fblob\u002Fmaster\u002F.opencode\u002Fskills\u002Fpr-watcher\u002FSKILL.md",[],[393,394,395,396,40,397,366,398,29,34,32,31,369],"pr","pr watcher","github","open pr","open","连续",{"skillNo":400,"name":401,"nameZh":6,"description":402,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":403,"categories":404,"keywords":405,"publishedAt":43},"01M6CW321GNCF2EKY9NQC2WJ9S","pr-handler","PR Gatekeeper SubAgent。自动化处理 Multi-Agent Pipeline 产出的 Draft PR：验证代码质量 → 本地合并 → 更新 Spec → Ship 交付。触发方式：用户提及 \"\u002Fhandle-pr\"、\"处理 PR\"、\"review pr\"、\"合并 PR\" 等关键词时激活。","https:\u002F\u002Fgithub.com\u002Fblackplume233\u002FAgentDispatch\u002Fblob\u002Fmaster\u002F.opencode\u002Fskills\u002Fpr-handler\u002FSKILL.md",[],[393,406,407,408,409,410,411,40,365,366,29,412,34,413,32,31,368,369,414],"pr handler","review","spec","review pr","pipeline","gatekeeper","multi-agent","draft pr","draft",{"skillNo":416,"name":417,"nameZh":6,"description":418,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":419,"categories":420,"keywords":421,"publishedAt":43},"01M6CW2ZQTW1TV0CMSVAKQ7B9S","issue-manager","GitHub-first Issue 管理 SubAgent。Issue 编号和内容以 GitHub Issues 为准，本地 .trellis\u002Fissues\u002F 为 Obsidian 兼容缓存。触发方式：用户提及 \"\u002Fissue\"、\"创建 issue\"、\"create issue\"、\"新建问题\"、\"提 bug\" 等关键词时激活。","https:\u002F\u002Fgithub.com\u002Fblackplume233\u002FAgentDispatch\u002Fblob\u002Fmaster\u002F.opencode\u002Fskills\u002Fissue-manager\u002FSKILL.md",[],[368,422,395,423,424,425,426,427,40,366,29,34,32,31,428],"issue manager","obsidian","create","github issues","issues","first","bug",{"skillNo":430,"name":431,"nameZh":6,"description":432,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":433,"categories":434,"keywords":435,"publishedAt":43},"01M6CW2WXEYST8AVQWP3BM0B43","git-commit","Execute git commit with conventional commit message analysis, intelligent staging, and message generation. Use when user asks to commit changes, create a git commit, or mentions \"\u002Fcommit\". Supports: (1) Auto-detecting type and scope from changes, (2) Generating conventional commit messages from diff, (3) Interactive commit with optional type\u002Fscope\u002Fdescription overrides, (4) Intelligent file staging for logical grouping","https:\u002F\u002Fgithub.com\u002Fblackplume233\u002FAgentDispatch\u002Fblob\u002Fmaster\u002F.opencode\u002Fskills\u002Fgit-commit\u002FSKILL.md",[],[363,436,364,424,437,438,439,440,441,442,443,444,445,446,28,447,448,449,450,451],"git commit","commit message","file","messages","conventional commit","analysis","Bash","commit messages","interactive","user","execute","diff","auto","commit changes","grouping","message"]