@axhub/genie 0.2.9 → 0.2.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api-docs.html +2 -2
- package/dist/assets/App-CYCCsgwf.js +264 -0
- package/dist/assets/{ReviewApp-C9K--AQE.js → ReviewApp-0srHIXwb.js} +1 -1
- package/dist/assets/{_basePickBy-DR_8uFCo.js → _basePickBy-DVVb07UV.js} +1 -1
- package/dist/assets/{_baseUniq-D0njlQ_7.js → _baseUniq-BtbziL5G.js} +1 -1
- package/dist/assets/{arc-CKlr_Rec.js → arc-BsCC8yBD.js} +1 -1
- package/dist/assets/{architectureDiagram-2XIMDMQ5-BmO_uLUH.js → architectureDiagram-2XIMDMQ5-woFp6eNI.js} +1 -1
- package/dist/assets/{blockDiagram-WCTKOSBZ-DhAeO-56.js → blockDiagram-WCTKOSBZ-ya8VAc2k.js} +1 -1
- package/dist/assets/{c4Diagram-IC4MRINW-C67kFoXx.js → c4Diagram-IC4MRINW-CY1dZmIZ.js} +1 -1
- package/dist/assets/channel-BMhScXFe.js +1 -0
- package/dist/assets/{chunk-4BX2VUAB-mLLagvJi.js → chunk-4BX2VUAB-CR1lAd74.js} +1 -1
- package/dist/assets/{chunk-55IACEB6-Lx-hOjlM.js → chunk-55IACEB6-CP98WcFC.js} +1 -1
- package/dist/assets/{chunk-FMBD7UC4-Bt-XmVUV.js → chunk-FMBD7UC4-D9c7ijAB.js} +1 -1
- package/dist/assets/{chunk-JSJVCQXG-Cya6gaDV.js → chunk-JSJVCQXG-DQAGYOn-.js} +1 -1
- package/dist/assets/{chunk-KX2RTZJC-Bd7Ig6tF.js → chunk-KX2RTZJC-BbTXiDq7.js} +1 -1
- package/dist/assets/{chunk-NQ4KR5QH-5UAE0Vg-.js → chunk-NQ4KR5QH-BI6AX0dr.js} +1 -1
- package/dist/assets/{chunk-QZHKN3VN-BAxZ8m7w.js → chunk-QZHKN3VN-DB3V2Ifo.js} +1 -1
- package/dist/assets/{chunk-WL4C6EOR-DjDPvUUP.js → chunk-WL4C6EOR-DhzTthv6.js} +1 -1
- package/dist/assets/classDiagram-VBA2DB6C-CMIxlWcT.js +1 -0
- package/dist/assets/classDiagram-v2-RAHNMMFH-CMIxlWcT.js +1 -0
- package/dist/assets/clone-BPqOt4r3.js +1 -0
- package/dist/assets/{cose-bilkent-S5V4N54A-D-60XrkJ.js → cose-bilkent-S5V4N54A-BQ09ZE2j.js} +1 -1
- package/dist/assets/{dagre-KLK3FWXG-bqu3ZS4K.js → dagre-KLK3FWXG-Dc2ueD_R.js} +1 -1
- package/dist/assets/{diagram-E7M64L7V-BueeqoYm.js → diagram-E7M64L7V-DP-LsQoL.js} +1 -1
- package/dist/assets/{diagram-IFDJBPK2-D4fDv2E7.js → diagram-IFDJBPK2-Cg6r42cB.js} +1 -1
- package/dist/assets/{diagram-P4PSJMXO-WqipY3fN.js → diagram-P4PSJMXO-aHsfoUZE.js} +1 -1
- package/dist/assets/{erDiagram-INFDFZHY-D0oVnO-x.js → erDiagram-INFDFZHY-qBXJ4aAz.js} +1 -1
- package/dist/assets/{flowDiagram-PKNHOUZH-DzbGyxrr.js → flowDiagram-PKNHOUZH-D_13emJM.js} +1 -1
- package/dist/assets/{ganttDiagram-A5KZAMGK-BwhbbgCP.js → ganttDiagram-A5KZAMGK-BvIcOLwz.js} +1 -1
- package/dist/assets/{gitGraphDiagram-K3NZZRJ6-DZgAh_KM.js → gitGraphDiagram-K3NZZRJ6-ad0vvNcU.js} +1 -1
- package/dist/assets/{graph-DzKos-N0.js → graph-CeJCMjan.js} +1 -1
- package/dist/assets/{highlighted-body-TPN3WLV5-CKDMgz3X.js → highlighted-body-TPN3WLV5-B_novwSz.js} +1 -1
- package/dist/assets/index-C514cLyb.js +2 -0
- package/dist/assets/index-h1DBl_g3.css +1 -0
- package/dist/assets/{infoDiagram-LFFYTUFH-BFicZbTf.js → infoDiagram-LFFYTUFH-lOxAqb3m.js} +1 -1
- package/dist/assets/{ishikawaDiagram-PHBUUO56-CtihxDxl.js → ishikawaDiagram-PHBUUO56-DIr-51gj.js} +1 -1
- package/dist/assets/{journeyDiagram-4ABVD52K-Du00J8_d.js → journeyDiagram-4ABVD52K-CYcIW0ZU.js} +1 -1
- package/dist/assets/{kanban-definition-K7BYSVSG-BJi9S0iQ.js → kanban-definition-K7BYSVSG-C1ZK616a.js} +1 -1
- package/dist/assets/{layout-B80Sityu.js → layout-CI2RM-v6.js} +1 -1
- package/dist/assets/{linear-sRQLOf5H.js → linear-DE7bISck.js} +1 -1
- package/dist/assets/{mermaid-O7DHMXV3-CBuVs4eJ.js → mermaid-O7DHMXV3-XxAJo8EK.js} +6 -6
- package/dist/assets/{mindmap-definition-YRQLILUH-C5IL_xi-.js → mindmap-definition-YRQLILUH-Dz6EFjmn.js} +1 -1
- package/dist/assets/{pieDiagram-SKSYHLDU-CeTwlJ8z.js → pieDiagram-SKSYHLDU-DPpEzUed.js} +1 -1
- package/dist/assets/{quadrantDiagram-337W2JSQ-COfUcLWt.js → quadrantDiagram-337W2JSQ-xdoXNet7.js} +1 -1
- package/dist/assets/{requirementDiagram-Z7DCOOCP-DSb-CJ5B.js → requirementDiagram-Z7DCOOCP-DUq8H3CL.js} +1 -1
- package/dist/assets/{sankeyDiagram-WA2Y5GQK-8jtuVb45.js → sankeyDiagram-WA2Y5GQK-CmqEUxRu.js} +1 -1
- package/dist/assets/{sequenceDiagram-2WXFIKYE-C2VpkMwA.js → sequenceDiagram-2WXFIKYE-DhtXRNiH.js} +1 -1
- package/dist/assets/{stateDiagram-RAJIS63D-fmwMqxxc.js → stateDiagram-RAJIS63D-Dj0HOlbN.js} +1 -1
- package/dist/assets/stateDiagram-v2-FVOUBMTO-C9utf5gv.js +1 -0
- package/dist/assets/{timeline-definition-YZTLITO2-Dx1hP5lg.js → timeline-definition-YZTLITO2-DUuJzZB5.js} +1 -1
- package/dist/assets/{treemap-KZPCXAKY-CkLOdYCZ.js → treemap-KZPCXAKY-DpYBQ0qr.js} +1 -1
- package/dist/assets/vendor-codemirror-CMHSJ_9p.js +9 -0
- package/dist/assets/{vennDiagram-LZ73GAT5-D6KWcnln.js → vennDiagram-LZ73GAT5-DpePUyOd.js} +1 -1
- package/dist/assets/{xychartDiagram-JWTSCODW-6fh6qmzN.js → xychartDiagram-JWTSCODW-Cfp1I4_U.js} +1 -1
- package/dist/index.html +3 -3
- package/package.json +6 -5
- package/server/acp-runtime/client.js +120 -14
- package/server/acp-runtime/index.js +54 -0
- package/server/acp-runtime/registry.js +2 -2
- package/server/acp-runtime/session-store.js +75 -1
- package/server/cli.js +32 -8
- package/server/database/db.js +20 -0
- package/server/external-agent/ws.js +477 -24
- package/server/index.js +78 -146
- package/server/lan-access/core.js +79 -0
- package/server/lan-access/state.js +102 -0
- package/server/middleware/auth.js +57 -14
- package/server/projects.js +423 -535
- package/server/routes/auth.js +24 -4
- package/server/routes/cli-auth.js +21 -25
- package/server/routes/codex.js +84 -298
- package/server/routes/commands.js +322 -407
- package/server/routes/lan-access.js +231 -0
- package/server/routes/projects.js +154 -158
- package/server/routes/session-core.js +13 -7
- package/server/routes/settings.js +113 -99
- package/server/session-core/eventStore.js +15 -2
- package/server/session-core/providerAdapters.js +28 -28
- package/server/session-core/sessionListMerge.js +47 -0
- package/shared/conversationEvents.js +96 -1
- package/shared/modelConstants.js +79 -99
- package/dist/assets/App-GBcTeeUS.js +0 -460
- package/dist/assets/channel-V3MBjKys.js +0 -1
- package/dist/assets/classDiagram-VBA2DB6C-C790yYiY.js +0 -1
- package/dist/assets/classDiagram-v2-RAHNMMFH-C790yYiY.js +0 -1
- package/dist/assets/clone-BbMGfZwt.js +0 -1
- package/dist/assets/index-DiQlHzGj.js +0 -2
- package/dist/assets/index-Drat2nB9.css +0 -1
- package/dist/assets/stateDiagram-v2-FVOUBMTO-9GGXVWrR.js +0 -1
- package/dist/assets/vendor-codemirror-BxPY6emf.js +0 -39
- package/server/routes/git.js +0 -1110
- package/server/routes/mcp-utils.js +0 -48
- package/server/routes/mcp.js +0 -536
- package/server/routes/taskmaster.js +0 -1963
- package/server/utils/mcp-detector.js +0 -198
- package/server/utils/taskmaster-websocket.js +0 -129
package/dist/api-docs.html
CHANGED
|
@@ -303,14 +303,14 @@
|
|
|
303
303
|
This page is auto-generated. Do not edit <code>public/api-docs.html</code> directly.
|
|
304
304
|
</div>
|
|
305
305
|
<article id="markdown-root" class="markdown-body"></article>
|
|
306
|
-
<footer>Generated at: 2026-04-
|
|
306
|
+
<footer>Generated at: 2026-04-12T10:12:04.262Z</footer>
|
|
307
307
|
</div>
|
|
308
308
|
</section>
|
|
309
309
|
</main>
|
|
310
310
|
|
|
311
311
|
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
|
|
312
312
|
<script>
|
|
313
|
-
const markdownSource = "# 开放接口使用文档(MVP)\n\n> Source Set:`docs/open-api/*.zh-CN.md` \n> 聚合产物:`docs/open-api-mvp.zh-CN.md` \n> 页面入口:`/api-docs.html`\n\n<a id=\"overview\"></a>\n\n适用场景:外部系统、本地服务、AI Agent 以及带网页编辑器的宿主应用,通过 Axhub Genie 的开放接口完成会话创建、续聊、中断、运行态观察,以及对在线网页编辑器实例做定向查询与控制。\n\n## Quick English Summary\n\n- HTTP: `GET /health`, `POST /api/agent`, `POST /api/agent/abort`\n- WebSocket: `WS /api/agent/ws`\n- CLI: `axhub-genie status`, `axhub-genie cc-connect ...`, `axhub-genie editor ...`\n- Editor integration model: enumerate online frontend clients first, then send editor requests to a specific `channel + targetClientId`\n\n## 1. 文档地图\n\n| 子文档 | 说明 |\n|---|---|\n| [`docs/open-api/http.zh-CN.md`](./http.zh-CN.md) | HTTP 接口、请求体、返回体、cURL 示例 |\n| [`docs/open-api/ws.zh-CN.md`](./ws.zh-CN.md) | `/api/agent/ws` 协议、集成 WS、editor 指令 |\n| [`docs/open-api/cli.zh-CN.md`](./cli.zh-CN.md) | `axhub-genie` CLI、editor 子命令、JSON 输出约定 |\n\n## 2. 基本信息\n\n- Assistant 前端地址示例:`http://localhost:5173`\n- Assistant 后端地址示例:`http://localhost:32123`\n- API Base 示例:`http://localhost:32123/api`\n- 会话页面路由格式:`/session/{sessionId}`\n- 健康检查:`GET /health`\n\n### 2.1 地址发现\n\n在开发、测试、生产环境中,地址可能不同。推荐始终先执行:\n\n```bash\naxhub-genie status --json\n```\n\n典型返回:\n\n```json\n{\n \"running\": true,\n \"pid\": 12345,\n \"port\": 32123,\n \"startedAt\": \"2026-02-08T03:12:45.321Z\",\n \"statusFile\": \"/Users/you/.axhub-genie/runtime-status.json\",\n \"endpoint\": {\n \"environment\": \"development\",\n \"frontendUrl\": \"http://localhost:5173\",\n \"apiBaseUrl\": \"http://localhost:32123/api\"\n }\n}\n```\n\n使用建议:\n\n- 统一把 `endpoint.apiBaseUrl` 当作 `<CURRENT_API_BASE>`\n- editor CLI / WS 默认也以这里发现到的 API Base 为准\n\n### 2.2 服务身份识别\n\n为了避免误连到其他本地服务,建议对 `/health` 额外校验:\n\n- `service.id`\n- 响应头 `X-App-Identifier`\n\n推荐成功条件:\n\n- HTTP `200`\n- `status = ok`\n- `service.id = @axhub/genie`\n\n### 2.3 前端 URL 参数\n\n前端支持通过 URL 预选项目、provider 与动态上下文:\n\n| 参数 | 示例 | 说明 |\n|---|---|---|\n| `project` / `projectName` | `?project=my-project` | 按项目名/显示名/路径匹配 |\n| `cwd` / `workdir` | `?cwd=/Users/you/my-project` | 按工作目录匹配 |\n| `provider` / `tool` / `cli` | `?provider=codex` | 预设默认工具 |\n| `context` | `?context=...` | 动态上下文(`contextV1`) |\n| `prompt` | `?prompt=...` | 预填输入框内容 |\n| `integrationWs=1` | `?integrationWs=1` | 让页面额外连接 `/api/agent/ws` |\n| `integrationClientId` | `?integrationClientId=figma-123` | 当前前端页面实例标识 |\n| `integrationChannel` | `?integrationChannel=project-a` | 当前业务通道标识 |\n\n说明:\n\n- editor 相关的所有外部操作都应先锁定 `channel + targetClientId`\n- 当同时存在多个网页编辑器客户端时,必须先列出客户端,再定向操作\n\n<a id=\"authentication\"></a>\n\n## 3. 鉴权策略(MVP)\n\n- `/api/agent` 与 `/api/agent/ws` 默认允许本地匿名访问\n- 若设置 `AGENT_API_KEY_REQUIRED=true`,则:\n - HTTP 通过 `X-API-Key`\n - WebSocket 通过查询参数 `apiKey`\n- editor CLI 与外部系统连接 `/api/agent/ws` 时,复用相同的鉴权规则\n\n### 3.1 对外 WebSocket 与内部 UI WebSocket 的边界\n\n- `/ws`:前端应用内部协议,承载 UI 与 provider 的私有消息,不属于开放接口\n- `/api/agent/ws`:开放接口,承载 Agent 请求流、运行态查询/订阅、集成 WS,以及 editor 集成协议\n\n## 4. 能力总览\n\n### 4.1 HTTP\n\n- 创建会话 / 续聊:`POST /api/agent`\n- 打开既有会话:`POST /api/agent` + `openOnly=true`\n- 中断运行:`POST /api/agent/abort`\n\n详情见 [`docs/open-api/http.zh-CN.md`](./http.zh-CN.md)。\n\n### 4.2 WebSocket\n\n- `agent.run`\n- `agent.abort`\n- `agent.state.query`\n- `agent.state.subscribe`\n- `integration.connect`\n- `integration.ping`\n- `integration.context.update`\n- `integration.prompt.update`\n- `integration.editor.clients.list`\n- `integration.editor.snapshot.get`\n- `integration.editor.nodes.list`\n- `integration.editor.node.screenshot.get`\n- `integration.editor.context-images.get`\n- `integration.editor.editing.set`\n\n详情见 [`docs/open-api/ws.zh-CN.md`](./ws.zh-CN.md)。\n\n### 4.3 CLI\n\n- `axhub-genie status`\n- `axhub-genie cc-connect status`\n- `axhub-genie cc-connect set`\n- `axhub-genie editor clients list`\n- `axhub-genie editor snapshot`\n- `axhub-genie editor nodes list`\n- `axhub-genie editor node screenshot`\n- `axhub-genie editor context-images export`\n- `axhub-genie editor editing set`\n\n详情见 [`docs/open-api/cli.zh-CN.md`](./cli.zh-CN.md)。\n\n## 5. 推荐集成顺序\n\n1. 用 `axhub-genie status --json` 或 `/health` 发现服务地址并确认身份。\n2. 如果要操作网页编辑器,先通过 CLI 或 `integration.editor.clients.list` 枚举在线客户端,并关注返回的 `source` 字段以识别 Chrome 扩展等来源。\n3. 保存 `channel + clientId`,后续请求都显式命中这个客户端。\n4. 对会话调用 HTTP 或 `agent.run`。\n5. 对网页编辑器调用 editor CLI 或 editor WS 指令。\n\n<a id=\"faq\"></a>\n\n## 6. FAQ\n\n### Q1:为什么 editor 命令必须指定客户端?\n\n因为同一时间可能存在多个在线网页编辑器页面,服务端不会默认广播 editor 读写请求。调用方应先拿到客户端列表,再定向到一个 `targetClientId`。\n\n### Q2:客户端还没升级 editor capability 时会怎样?\n\n服务端会返回:\n\n```json\n{\n \"type\": \"integration.error\",\n \"payload\": {\n \"code\": \"UNSUPPORTED_FRONTEND_CAPABILITY\",\n \"message\": \"Target frontend page does not advertise capability editor.snapshot\"\n }\n}\n```\n\n### Q3:为什么要保留 `docs/open-api-mvp.zh-CN.md`?\n\n为了保持历史入口与 `/api-docs.html` 不变。维护时请编辑 `docs/open-api/*.zh-CN.md`,不要手改聚合产物。\n\n## 7. 版本说明\n\n- 文档版本:MVP v1.7\n- 更新日期:2026-04-03\n- 维护入口:`docs/open-api/*.zh-CN.md`\n- 聚合产物:`docs/open-api-mvp.zh-CN.md`\n\n---\n\n## HTTP API\n\n<a id=\"http-api\"></a>\n\n### 1. 健康检查\n\n#### `GET /health`\n\n请求示例:\n\n```bash\ncurl -i http://localhost:32123/health\n```\n\n响应示例:\n\n```json\n{\n \"status\": \"ok\",\n \"timestamp\": \"2026-02-09T12:00:00.000Z\",\n \"service\": {\n \"id\": \"@axhub/genie\",\n \"name\": \"Axhub Genie\",\n \"version\": \"1.16.3\"\n },\n \"runtime\": {\n \"environment\": \"development\",\n \"port\": 32123\n }\n}\n```\n\n关键响应头:\n\n- `X-App-Identifier`\n- `X-App-Name`\n- `X-App-Version`\n- `X-App-Environment`\n\n### 2. 创建或续聊会话\n\n#### `POST /api/agent`\n\n典型用途:\n\n- 新建会话并发送第一条消息\n- 带 `sessionId` 续聊既有会话\n- 带 `openOnly=true` 仅打开会话,不触发模型运行\n\n#### 2.1 请求体\n\n```json\n{\n \"projectPath\": \"/Users/you/your-project\",\n \"provider\": \"codex\",\n \"message\": \"请先梳理当前项目结构并给出重构计划\",\n \"stream\": false\n}\n```\n\n常用字段:\n\n| 字段 | 说明 |\n|---|---|\n| `projectPath` | 本地项目路径,可选;未传时按“服务启动配置目录 > 服务进程启动目录”回退 |\n| `provider` | `claude` / `codex` / `gemini` / `opencode` |\n| `model` | 可选模型名 |\n| `message` | 用户输入 |\n| `sessionId` | 既有会话 ID |\n| `openOnly` | 仅打开会话 |\n| `stream` | 是否流式返回 |\n| `images[]` | 附加图片 |\n| `createBranch` | 是否自动创建分支 |\n| `branchName` | 自定义分支名 |\n| `createPR` | 是否自动发起 PR |\n| `callback` | 终态回调配置 |\n\n#### 2.2 关键校验规则\n\n- `message` 在 `openOnly !== true` 时必填\n- `provider` 必须是受支持的 provider\n- `sessionId` 续聊时由调用方保证正确\n- `projectPath` 可省略;服务端会按“默认工作目录配置 > 进程当前目录”解析\n- `images[].data` 使用 data URL\n\n#### 2.3 返回(`stream: false`)\n\n```json\n{\n \"success\": true,\n \"sessionId\": \"019c3263-967f-7ba2-84fe-fc5c694f6316\",\n \"sessionPath\": \"/session/019c3263-967f-7ba2-84fe-fc5c694f6316\",\n \"sessionUrl\": \"https://assistant.example.com/session/019c3263-967f-7ba2-84fe-fc5c694f6316\",\n \"isResumed\": false,\n \"messages\": [],\n \"tokens\": {\n \"inputTokens\": 0,\n \"outputTokens\": 0,\n \"cacheReadTokens\": 0,\n \"cacheCreationTokens\": 0,\n \"totalTokens\": 0\n },\n \"projectPath\": \"/Users/you/your-project\"\n}\n```\n\n### 3. 只打开会话页面\n\n当你只想进入某个既有会话,而不想立刻发消息时:\n\n```json\n{\n \"sessionId\": \"019c3263-967f-7ba2-84fe-fc5c694f6316\",\n \"openOnly\": true,\n \"stream\": false\n}\n```\n\n### 4. 中断运行中的会话\n\n#### `POST /api/agent/abort`\n\n请求示例:\n\n```json\n{\n \"sessionId\": \"019c3263-967f-7ba2-84fe-fc5c694f6316\",\n \"provider\": \"codex\"\n}\n```\n\n成功响应:\n\n```json\n{\n \"success\": true,\n \"aborted\": true,\n \"sessionId\": \"019c3263-967f-7ba2-84fe-fc5c694f6316\",\n \"provider\": \"codex\",\n \"message\": \"Session aborted\"\n}\n```\n\n未找到活跃会话时,HTTP 仍可能返回 `200`,但 `success=false`。\n\n### 5. cURL 示例\n\n#### 5.1 创建新会话\n\n```bash\ncurl -X POST <CURRENT_API_BASE>/agent \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"projectPath\": \"/Users/you/your-project\",\n \"provider\": \"codex\",\n \"message\": \"请先梳理当前项目结构并给出重构计划\",\n \"stream\": false\n }'\n```\n\n#### 5.2 创建会话并附带图片\n\n```bash\ncurl -X POST <CURRENT_API_BASE>/agent \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"projectPath\": \"/Users/you/your-project\",\n \"provider\": \"codex\",\n \"message\": \"请描述这张截图并指出 UI 问题\",\n \"images\": [\n {\n \"name\": \"ui.png\",\n \"data\": \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...\",\n \"mimeType\": \"image/png\"\n }\n ],\n \"stream\": false\n }'\n```\n\n#### 5.3 续聊指定会话\n\n```bash\ncurl -X POST <CURRENT_API_BASE>/agent \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"projectPath\": \"/Users/you/your-project\",\n \"provider\": \"codex\",\n \"sessionId\": \"019c3263-967f-7ba2-84fe-fc5c694f6316\",\n \"message\": \"继续上一轮,把第 1、2 点先落代码\",\n \"stream\": false\n }'\n```\n\n#### 5.4 只打开会话\n\n```bash\ncurl -X POST <CURRENT_API_BASE>/agent \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"sessionId\": \"019c3263-967f-7ba2-84fe-fc5c694f6316\",\n \"openOnly\": true,\n \"stream\": false\n }'\n```\n\n#### 5.5 中断运行中的会话\n\n```bash\ncurl -X POST <CURRENT_API_BASE>/agent/abort \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"sessionId\": \"019c3263-967f-7ba2-84fe-fc5c694f6316\",\n \"provider\": \"codex\"\n }'\n```\n\n### 6. 会话映射建议\n\n建议外部系统保存:\n\n- `external_conversation_key -> sessionId`\n\n这样可以稳定支持:\n\n- 可重入\n- 可续聊\n- 可跳转\n- 可中断\n\n---\n\n## WebSocket API\n\n<a id=\"ws-api\"></a>\n\n### 1. 连接地址\n\n```text\nWS /api/agent/ws\n```\n\n鉴权方式:\n\n- 默认本地匿名允许\n- 若开启 API Key,使用查询参数 `apiKey`\n\n### 2. 使用模式\n\n`/api/agent/ws` 同时承载三类开放能力:\n\n- Agent 请求流:`agent.run` / `agent.abort`\n- Agent 运行态:`agent.state.query` / `agent.state.subscribe`\n- 集成流:`integration.*`\n\n其中 editor 相关能力也属于 `integration.*` 协议的一部分。\n\n### 3. Agent 请求流\n\n#### 3.1 入站:`agent.run`\n\n```json\n{\n \"type\": \"agent.run\",\n \"requestId\": \"req_001\",\n \"payload\": {\n \"projectPath\": \"/Users/you/your-project\",\n \"provider\": \"codex\",\n \"message\": \"请继续处理当前任务\"\n }\n}\n```\n\n说明:\n\n- `payload.projectPath` 可选\n- 若未传,服务端按“默认工作目录配置 > 进程当前目录”回退\n\n#### 3.2 入站:`agent.abort`\n\n```json\n{\n \"type\": \"agent.abort\",\n \"requestId\": \"req_002\",\n \"payload\": {\n \"sessionId\": \"019c3263-967f-7ba2-84fe-fc5c694f6316\",\n \"provider\": \"codex\"\n }\n}\n```\n\n#### 3.3 出站:典型序列\n\n1. `agent.accepted`\n2. `agent.session.created`\n3. 多个 `agent.event`\n4. `agent.completed`\n\n中断时终态为 `agent.aborted`;失败时终态为 `agent.error`。\n\n### 4. Agent 运行态查询/订阅\n\n#### 4.1 查询\n\n```json\n{\n \"type\": \"agent.state.query\",\n \"requestId\": \"state_001\",\n \"payload\": {\n \"sessionId\": \"019c3263-967f-7ba2-84fe-fc5c694f6316\",\n \"provider\": \"codex\"\n }\n}\n```\n\n响应:\n\n```json\n{\n \"type\": \"agent.state.snapshot\",\n \"requestId\": \"state_001\",\n \"payload\": {\n \"sessionId\": \"019c3263-967f-7ba2-84fe-fc5c694f6316\",\n \"provider\": \"codex\",\n \"phase\": \"streaming\",\n \"isLoading\": true,\n \"canAbortSession\": true,\n \"hasPendingApproval\": false,\n \"updatedAt\": \"2026-03-20T10:00:01.000Z\"\n }\n}\n```\n\n#### 4.2 订阅\n\n```json\n{\n \"type\": \"agent.state.subscribe\",\n \"requestId\": \"state_002\",\n \"payload\": {\n \"sessionId\": \"019c3263-967f-7ba2-84fe-fc5c694f6316\",\n \"provider\": \"codex\"\n }\n}\n```\n\n确认:\n\n```json\n{\n \"type\": \"agent.state.subscribed\",\n \"requestId\": \"state_002\",\n \"payload\": {\n \"sessionId\": \"019c3263-967f-7ba2-84fe-fc5c694f6316\",\n \"provider\": \"codex\",\n \"subscriptionKey\": \"codex:019c3263-967f-7ba2-84fe-fc5c694f6316\"\n }\n}\n```\n\n变化通知:\n\n```json\n{\n \"type\": \"agent.state.changed\",\n \"payload\": {\n \"subscriptionKey\": \"codex:019c3263-967f-7ba2-84fe-fc5c694f6316\",\n \"sessionId\": \"019c3263-967f-7ba2-84fe-fc5c694f6316\",\n \"provider\": \"codex\",\n \"phase\": \"completed\",\n \"isLoading\": false,\n \"canAbortSession\": false,\n \"hasPendingApproval\": false,\n \"updatedAt\": \"2026-03-20T10:00:08.000Z\"\n }\n}\n```\n\n### 5. 集成流基础协议\n\n#### 5.1 页面注册:`integration.connect`\n\n前端页面示例:\n\n```json\n{\n \"type\": \"integration.connect\",\n \"requestId\": \"conn_001\",\n \"payload\": {\n \"role\": \"frontend-page\",\n \"channel\": \"project-a\",\n \"clientId\": \"figma-123\",\n \"source\": \"chrome-extension\",\n \"pageUrl\": \"http://localhost:5173/session/019c...?...\",\n \"sessionId\": \"019c3263-967f-7ba2-84fe-fc5c694f6316\",\n \"capabilities\": [\n \"context.update\",\n \"prompt.update\",\n \"presence.report\"\n ]\n }\n}\n```\n\n说明:\n\n- `source` 为可选字段,用于标记客户端来源,例如 `chrome-extension`\n\n外部系统示例:\n\n```json\n{\n \"type\": \"integration.connect\",\n \"requestId\": \"conn_002\",\n \"payload\": {\n \"role\": \"external-client\",\n \"channel\": \"project-a\",\n \"clientId\": \"host-app-01\",\n \"capabilities\": [\n \"presence.query\",\n \"context.push\",\n \"prompt.push\",\n \"editor.query\"\n ]\n }\n}\n```\n\n#### 5.2 探活:`integration.ping`\n\n```json\n{\n \"type\": \"integration.ping\",\n \"requestId\": \"ping_001\",\n \"payload\": {\n \"channel\": \"project-a\",\n \"targetClientId\": \"figma-123\"\n }\n}\n```\n\n响应:\n\n```json\n{\n \"type\": \"integration.pong\",\n \"requestId\": \"ping_001\",\n \"payload\": {\n \"server\": {\n \"status\": \"ok\",\n \"started\": true\n },\n \"frontend\": {\n \"connected\": true,\n \"count\": 1,\n \"clients\": [\n {\n \"clientId\": \"figma-123\",\n \"lastSeenAt\": \"2026-03-19T10:00:03.000Z\",\n \"pageUrl\": \"http://localhost:5173/session/019c...?integrationWs=1...\",\n \"sessionId\": \"019c3263-967f-7ba2-84fe-fc5c694f6316\"\n }\n ]\n }\n }\n}\n```\n\n#### 5.3 运行期上下文/提示词写入\n\n- `integration.context.update`\n- `integration.prompt.update`\n\n它们沿用既有协议,行为保持不变。\n\n### 6. Editor 集成协议\n\n#### 6.1 设计原则\n\n- 统一复用 `/api/agent/ws`\n- 统一带 `requestId`\n- 除 `clients.list` 外,统一要求 `channel + targetClientId`\n- 读操作终态为 `integration.editor.*.result`\n- 参数错误、目标页离线、超时、能力不支持统一走 `integration.error`\n- 写操作可以先回 `integration.ack`,但终态仍以 `integration.editor.*.result` 或 `integration.error` 为准\n\n#### 6.2 先列出客户端\n\n##### 入站:`integration.editor.clients.list`\n\n```json\n{\n \"type\": \"integration.editor.clients.list\",\n \"requestId\": \"editor_clients_001\",\n \"payload\": {\n \"channel\": \"project-a\"\n }\n}\n```\n\n##### 出站:`integration.editor.clients.result`\n\n```json\n{\n \"type\": \"integration.editor.clients.result\",\n \"requestId\": \"editor_clients_001\",\n \"payload\": {\n \"items\": [\n {\n \"channel\": \"project-a\",\n \"clientId\": \"figma-123\",\n \"source\": \"chrome-extension\",\n \"sessionId\": \"019c3263-967f-7ba2-84fe-fc5c694f6316\",\n \"pageUrl\": \"http://localhost:5173/session/019c...?integrationWs=1...\",\n \"lastSeenAt\": \"2026-03-21T09:00:00.000Z\",\n \"connectedAt\": \"2026-03-21T08:58:00.000Z\",\n \"connectionId\": \"conn_001\",\n \"capabilities\": [\n \"context.update\",\n \"prompt.update\",\n \"editor.snapshot\",\n \"editor.nodes.list\",\n \"editor.node.screenshot\",\n \"editor.context-images\",\n \"editor.editing.set\"\n ]\n }\n ],\n \"total\": 1,\n \"filters\": {\n \"channel\": \"project-a\",\n \"clientId\": null\n }\n }\n}\n```\n\n说明:\n\n- `source` 用于区分客户端来源,AI Agent 可据此识别是否来自 Chrome 扩展\n\n#### 6.3 编辑器快照\n\n##### 入站:`integration.editor.snapshot.get`\n\n```json\n{\n \"type\": \"integration.editor.snapshot.get\",\n \"requestId\": \"editor_snapshot_001\",\n \"payload\": {\n \"channel\": \"project-a\",\n \"targetClientId\": \"figma-123\"\n }\n}\n```\n\n##### 出站:`integration.editor.snapshot.result`\n\n```json\n{\n \"type\": \"integration.editor.snapshot.result\",\n \"requestId\": \"editor_snapshot_001\",\n \"payload\": {\n \"resource\": null,\n \"selectedElement\": null,\n \"modifiedElements\": [],\n \"textChanges\": [],\n \"styleChanges\": {\n \"cssText\": \"\"\n },\n \"statusSummary\": {\n \"active\": true,\n \"modifiedCount\": 0,\n \"nodeStateCounts\": {\n \"clean\": 0,\n \"dirty\": 0,\n \"handled\": 0,\n \"editing\": 0,\n \"completed\": 0,\n \"error\": 0\n }\n }\n }\n}\n```\n\n#### 6.4 节点列表\n\n##### 入站:`integration.editor.nodes.list`\n\n```json\n{\n \"type\": \"integration.editor.nodes.list\",\n \"requestId\": \"editor_nodes_001\",\n \"payload\": {\n \"channel\": \"project-a\",\n \"targetClientId\": \"figma-123\",\n \"status\": [\"pending-dispatch\", \"dirty\"],\n \"elementKey\": null,\n \"limit\": 100\n }\n}\n```\n\n##### 出站:`integration.editor.nodes.result`\n\n```json\n{\n \"type\": \"integration.editor.nodes.result\",\n \"requestId\": \"editor_nodes_001\",\n \"payload\": {\n \"items\": [\n {\n \"elementKey\": \"hero-card\",\n \"label\": \"body > main > section.hero-card\",\n \"changeState\": \"dirty\",\n \"taskState\": \"idle\",\n \"hasNote\": true,\n \"hasImages\": false,\n \"changeKinds\": [\"text\"],\n \"dirtySince\": 1742547600000,\n \"lastHandledAt\": null\n }\n ],\n \"total\": 1,\n \"filters\": {\n \"status\": [\"pending-dispatch\", \"dirty\"],\n \"elementKey\": null,\n \"limit\": 100\n }\n }\n}\n```\n\n推荐状态字段:\n\n- `changeState`: `clean` / `dirty` / `handled`\n- `taskState`: `idle` / `editing` / `completed` / `error`\n- `hasNote`\n- `hasImages`\n- `changeKinds`\n- `dirtySince`\n- `lastHandledAt`\n\n推荐状态别名:\n\n- `dirty`\n- `handled`\n- `editing`\n- `completed`\n- `error`\n- `pending-dispatch`\n 定义为 `changeState=dirty && taskState=idle && changeState!=handled`\n\n#### 6.5 节点截图\n\n##### 入站:`integration.editor.node.screenshot.get`\n\n```json\n{\n \"type\": \"integration.editor.node.screenshot.get\",\n \"requestId\": \"editor_shot_001\",\n \"payload\": {\n \"channel\": \"project-a\",\n \"targetClientId\": \"figma-123\",\n \"elementKey\": \"hero-card\",\n \"downloadPath\": \"/Users/you/tmp\"\n }\n}\n```\n\n说明:\n\n- `downloadPath` 是服务端本地落盘目录,不是前端页面自己的文件路径\n- 前端页面收到指令后,应将截图内容以 `data:<mime>;base64,...` 的形式回传给服务端\n- 服务端收到 base64/data URL 后负责写入本地文件,再把 `absolutePath` 返回给 CLI / 外部调用方\n\n##### 前端页面回包:`integration.editor.node.screenshot.result`\n\n```json\n{\n \"type\": \"integration.editor.node.screenshot.result\",\n \"requestId\": \"editor_shot_001\",\n \"payload\": {\n \"elementKey\": \"hero-card\",\n \"image\": {\n \"name\": \"hero-card.png\",\n \"data\": \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...\",\n \"width\": 1440,\n \"height\": 640\n },\n \"mimeType\": \"image/png\",\n \"width\": 1440,\n \"height\": 640\n }\n}\n```\n\n兼容说明:\n\n- 前端可以把 `data` 放在 `payload.image.data`\n- 也可以直接放在 `payload.data`\n- 如果前端未来已经具备本地文件访问代理能力,服务端当前也兼容直接回传 `absolutePath`,但推荐协议仍然是回传 data URL,由服务端统一落盘\n\n##### 服务端对外回包:`integration.editor.node.screenshot.result`\n\n```json\n{\n \"type\": \"integration.editor.node.screenshot.result\",\n \"requestId\": \"editor_shot_001\",\n \"payload\": {\n \"elementKey\": \"hero-card\",\n \"absolutePath\": \"/Users/you/tmp/hero-card.png\",\n \"mimeType\": \"image/png\",\n \"width\": 1440,\n \"height\": 640,\n \"size\": 482113\n }\n}\n```\n\n#### 6.6 上下文图片导出\n\n##### 入站:`integration.editor.context-images.get`\n\n```json\n{\n \"type\": \"integration.editor.context-images.get\",\n \"requestId\": \"editor_ctximg_001\",\n \"payload\": {\n \"channel\": \"project-a\",\n \"targetClientId\": \"figma-123\",\n \"downloadPath\": \"/Users/you/tmp\"\n }\n}\n```\n\n说明:\n\n- `downloadPath` 同样是服务端本地目录\n- 前端页面应把上下文图片逐项回传为 data URL / base64\n- 服务端负责逐张写入本地,并返回每张图片的 `absolutePath`\n\n##### 前端页面回包:`integration.editor.context-images.result`\n\n```json\n{\n \"type\": \"integration.editor.context-images.result\",\n \"requestId\": \"editor_ctximg_001\",\n \"payload\": {\n \"items\": [\n {\n \"id\": \"img_001\",\n \"name\": \"clipboard-image-1.png\",\n \"data\": \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...\",\n \"mimeType\": \"image/png\",\n \"createdAt\": 1742547600000,\n \"source\": \"prompt-context\"\n }\n ]\n }\n}\n```\n\n##### 服务端对外回包:`integration.editor.context-images.result`\n\n```json\n{\n \"type\": \"integration.editor.context-images.result\",\n \"requestId\": \"editor_ctximg_001\",\n \"payload\": {\n \"items\": [\n {\n \"id\": \"img_001\",\n \"name\": \"clipboard-image-1.png\",\n \"absolutePath\": \"/Users/you/tmp/clipboard-image-1.png\",\n \"mimeType\": \"image/png\",\n \"size\": 90312,\n \"createdAt\": 1742547600000,\n \"source\": \"prompt-context\"\n }\n ]\n }\n}\n```\n\n#### 6.7 编辑态设置\n\n##### 入站:`integration.editor.editing.set`\n\n```json\n{\n \"type\": \"integration.editor.editing.set\",\n \"requestId\": \"editor_editing_001\",\n \"payload\": {\n \"channel\": \"project-a\",\n \"targetClientId\": \"figma-123\",\n \"elementKey\": \"hero-card\",\n \"state\": \"editing\",\n \"taskRef\": {\n \"provider\": \"codex\",\n \"sessionId\": \"019c3263-967f-7ba2-84fe-fc5c694f6316\",\n \"requestId\": \"req_001\"\n }\n }\n}\n```\n\n##### 出站:`integration.editor.editing.result`\n\n```json\n{\n \"type\": \"integration.editor.editing.result\",\n \"requestId\": \"editor_editing_001\",\n \"payload\": {\n \"elementKey\": \"hero-card\",\n \"state\": \"editing\",\n \"applied\": true,\n \"taskRef\": {\n \"provider\": \"codex\",\n \"sessionId\": \"019c3263-967f-7ba2-84fe-fc5c694f6316\",\n \"requestId\": \"req_001\"\n }\n }\n}\n```\n\n说明:\n\n- `state` 支持 `editing`、`idle`、`completed`、`error`\n\n#### 6.8 能力声明\n\n服务端会在转发 editor 指令前检查目标前端页面是否声明以下 capability:\n\n| 消息类型 | capability |\n|---|---|\n| `integration.editor.snapshot.get` | `editor.snapshot` |\n| `integration.editor.nodes.list` | `editor.nodes.list` |\n| `integration.editor.node.screenshot.get` | `editor.node.screenshot` |\n| `integration.editor.context-images.get` | `editor.context-images` |\n| `integration.editor.editing.set` | `editor.editing.set` |\n\n若目标页未声明对应 capability,服务端返回:\n\n```json\n{\n \"type\": \"integration.error\",\n \"requestId\": \"editor_snapshot_001\",\n \"payload\": {\n \"code\": \"UNSUPPORTED_FRONTEND_CAPABILITY\",\n \"message\": \"Target frontend page does not advertise capability editor.snapshot\"\n }\n}\n```\n\n#### 6.9 常见错误码\n\n- `FRONTEND_NOT_ONLINE`\n- `INVALID_TARGET`\n- `INVALID_PAYLOAD`\n- `UNSUPPORTED_MESSAGE_TYPE`\n- `UNSUPPORTED_FRONTEND_CAPABILITY`\n- `REQUEST_TIMEOUT`\n\n---\n\n## CLI API\n\n<a id=\"cli-api\"></a>\n\n### 1. 地址发现与状态检查\n\n#### `axhub-genie status`\n\n用于查看:\n\n- 当前服务是否运行\n- PID / 端口\n- `endpoint.frontendUrl`\n- `endpoint.apiBaseUrl`\n\n示例:\n\n```bash\naxhub-genie status --json\n```\n\n返回示例:\n\n```json\n{\n \"running\": true,\n \"pid\": 12345,\n \"port\": 32123,\n \"startedAt\": \"2026-02-08T03:12:45.321Z\",\n \"statusFile\": \"/Users/you/.axhub-genie/runtime-status.json\",\n \"defaultProjectPath\": \"/Users/you/your-project\",\n \"endpoint\": {\n \"environment\": \"development\",\n \"frontendUrl\": \"http://localhost:5173\",\n \"apiBaseUrl\": \"http://localhost:32123/api\"\n }\n}\n```\n\n说明:\n\n- 启动服务时可通过 `axhub-genie --cwd /path/to/project` 配置默认工作目录\n- 当开放 API 未显式传 `projectPath` 时,服务端按“默认工作目录配置 > 服务进程启动目录”回退\n\n### 2. cc-connect 子命令\n\n所有 `cc-connect` 子命令都默认输出 JSON,用于读取或更新本机 `cc-connect` 平台绑定配置。\n\n#### 2.1 通用参数\n\n| 参数 | 说明 |\n|---|---|\n| `--platform <id>` | 目标平台,当前支持 `weixin` / `feishu` |\n| `--provider <id>` | 切换到的 AI 供应商:`claude` / `codex` / `gemini` / `opencode` |\n| `--project-path <path>` | 切换到的新项目目录 |\n| `--json` | 显式声明 JSON 输出(默认已是 JSON) |\n\n统一成功包型:\n\n```json\n{\n \"ok\": true,\n \"command\": \"cc-connect set\",\n \"platform\": \"feishu\",\n \"data\": {}\n}\n```\n\n统一失败包型:\n\n```json\n{\n \"ok\": false,\n \"command\": \"cc-connect set\",\n \"platform\": \"feishu\",\n \"error\": {\n \"code\": \"PLATFORM_NOT_CONNECTED\",\n \"message\": \"Feishu is not connected.\"\n }\n}\n```\n\n失败时 CLI 以非 0 退出码结束。\n\n#### 2.2 `axhub-genie cc-connect status`\n\n作用:查看当前 `cc-connect` 安装状态、已检测到的供应商,以及平台绑定信息。\n\n示例:\n\n```bash\naxhub-genie cc-connect status\n```\n\n指定单个平台:\n\n```bash\naxhub-genie cc-connect status --platform feishu\n```\n\n返回示例:\n\n```json\n{\n \"ok\": true,\n \"command\": \"cc-connect status\",\n \"platform\": \"feishu\",\n \"data\": {\n \"ccConnect\": {\n \"installed\": true,\n \"version\": \"0.6.0-beta.4\",\n \"isBeta\": true,\n \"resolvedPath\": \"/opt/homebrew/bin/cc-connect\"\n },\n \"providers\": [\n {\n \"id\": \"claude\",\n \"label\": \"Claude\",\n \"installed\": true\n },\n {\n \"id\": \"codex\",\n \"label\": \"Codex\",\n \"installed\": true\n }\n ],\n \"platform\": {\n \"id\": \"feishu\",\n \"label\": \"Feishu\",\n \"connected\": true,\n \"activeProvider\": \"codex\",\n \"configuredProviders\": [\"claude\", \"codex\", \"gemini\", \"opencode\"],\n \"projectPath\": \"/Users/you/your-project\"\n }\n }\n}\n```\n\n#### 2.3 `axhub-genie cc-connect set`\n\n作用:切换指定平台当前绑定的 AI 供应商,或者切换该平台消息最终路由到的项目目录。两者可以一次命令同时更新,并只触发一次 `cc-connect` 配置写入与 daemon 重载。\n\n示例 1:切换飞书当前供应商到 `codex`\n\n```bash\naxhub-genie cc-connect set --platform feishu --provider codex\n```\n\n示例 2:切换微信默认工作项目\n\n```bash\naxhub-genie cc-connect set --platform weixin --project-path /Users/you/workspace/app\n```\n\n示例 3:同时切换供应商与项目目录\n\n```bash\naxhub-genie cc-connect set \\\n --platform feishu \\\n --provider claude \\\n --project-path /Users/you/workspace/assistant\n```\n\n返回示例:\n\n```json\n{\n \"ok\": true,\n \"command\": \"cc-connect set\",\n \"platform\": \"feishu\",\n \"data\": {\n \"platform\": \"feishu\",\n \"label\": \"Feishu\",\n \"provider\": \"claude\",\n \"projectPath\": \"/Users/you/workspace/assistant\",\n \"configuredProviders\": [\"claude\", \"codex\", \"gemini\", \"opencode\"],\n \"changed\": true,\n \"changedFields\": [\"provider\", \"projectPath\"],\n \"message\": \"cc-connect daemon restarted with the latest configuration.\"\n }\n}\n```\n\n约束:\n\n- `--platform` 必填\n- `--provider` 与 `--project-path` 至少传一个\n- `--project-path` 必须是本机存在的目录\n- 命令会直接更新 `~/.cc-connect/config.toml` 以及 `~/.cc-connect/ai-web-ui-connect-state.json`\n\n### 3. Editor 子命令\n\n所有 editor 子命令都默认输出 JSON,并通过 `/api/agent/ws` 与在线 frontend-page 通信。\n\n#### 3.1 通用参数\n\n| 参数 | 说明 |\n|---|---|\n| `--api-base <url>` | 显式指定 API Base,默认自动发现 |\n| `--api-key <key>` | 连接 `/api/agent/ws` 时的 API Key |\n| `--channel <name>` | 目标业务通道 |\n| `--target-client-id <id>` | 目标前端页面实例 |\n| `--timeout-ms <ms>` | 请求超时 |\n| `--json` | 显式声明 JSON 输出 |\n| `--output-dir <path>` | 截图/图片导出目录,默认当前目录 |\n\n### 4. 推荐顺序:先列客户端\n\n#### `axhub-genie editor clients list`\n\n作用:列出当前在线的网页编辑器客户端,避免把 editor 请求广播给错误页面。\n\n示例:\n\n```bash\naxhub-genie editor clients list --channel project-a\n```\n\n返回示例:\n\n```json\n{\n \"ok\": true,\n \"requestId\": \"editor_xxx\",\n \"channel\": null,\n \"targetClientId\": null,\n \"data\": {\n \"items\": [\n {\n \"channel\": \"project-a\",\n \"clientId\": \"figma-123\",\n \"sessionId\": \"019c3263-967f-7ba2-84fe-fc5c694f6316\",\n \"pageUrl\": \"http://localhost:5173/session/019c...?integrationWs=1...\",\n \"lastSeenAt\": \"2026-03-21T09:00:00.000Z\",\n \"connectedAt\": \"2026-03-21T08:58:00.000Z\",\n \"connectionId\": \"conn_001\",\n \"capabilities\": [\n \"editor.snapshot\",\n \"editor.nodes.list\"\n ]\n }\n ],\n \"total\": 1,\n \"filters\": {\n \"channel\": \"project-a\",\n \"clientId\": null\n }\n }\n}\n```\n\n### 5. Editor 快照与节点\n\n#### `axhub-genie editor snapshot`\n\n```bash\naxhub-genie editor snapshot \\\n --channel project-a \\\n --target-client-id figma-123\n```\n\n返回字段覆盖:\n\n- `resource`\n- `selectedElement`\n- `modifiedElements`\n- `textChanges`\n- `styleChanges`\n- `statusSummary`\n\n#### `axhub-genie editor nodes list`\n\n```bash\naxhub-genie editor nodes list \\\n --channel project-a \\\n --target-client-id figma-123 \\\n --status pending-dispatch,dirty \\\n --limit 100\n```\n\n推荐状态字段:\n\n- `changeState`\n - `clean`\n - `dirty`\n - `handled`\n- `taskState`\n - `idle`\n - `editing`\n - `completed`\n - `error`\n- `hasNote`\n- `hasImages`\n- `changeKinds`\n- `dirtySince`\n- `lastHandledAt`\n\n推荐状态别名:\n\n- `dirty`\n- `handled`\n- `editing`\n- `completed`\n- `error`\n- `pending-dispatch`\n 定义为 `changeState=dirty && taskState=idle && changeState!=handled`\n\n### 6. 截图与上下文图片\n\n约定:\n\n- 前端页面通过 WS 把截图/图片内容以 data URL / base64 回传给服务端\n- 服务端再把文件写入 `--output-dir` 指向的本地目录\n- CLI 最终返回的是服务端已经落好的绝对路径,而不是前端页面自己的临时路径\n\n#### `axhub-genie editor node screenshot`\n\n```bash\naxhub-genie editor node screenshot \\\n --channel project-a \\\n --target-client-id figma-123 \\\n --element-key hero-card \\\n --output-dir .\n```\n\n返回:\n\n- `absolutePath`\n- `mimeType`\n- `width`\n- `height`\n- `size`\n\n#### `axhub-genie editor context-images export`\n\n```bash\naxhub-genie editor context-images export \\\n --channel project-a \\\n --target-client-id figma-123 \\\n --output-dir .\n```\n\n返回每张图片的:\n\n- `id`\n- `name`\n- `absolutePath`\n- `mimeType`\n- `size`\n- `createdAt`\n- `source`\n\n### 7. 编辑态设置\n\n#### `axhub-genie editor editing set`\n\n```bash\naxhub-genie editor editing set \\\n --channel project-a \\\n --target-client-id figma-123 \\\n --element-key hero-card \\\n --state editing \\\n --provider codex \\\n --session-id 019c3263-967f-7ba2-84fe-fc5c694f6316 \\\n --task-request-id req_001\n```\n\n说明:\n\n- `--state` 允许 `editing`、`idle`、`completed`、`error`\n- 可选通过 `--provider` / `--session-id` / `--task-request-id` 传递任务追踪信息\n\n### 8. 常见失败原因\n\n#### 8.1 `FRONTEND_NOT_ONLINE`\n\n表示目标 `channel + targetClientId` 当前没有在线页面。\n\n#### 7.2 `UNSUPPORTED_FRONTEND_CAPABILITY`\n\n表示目标页面已经在线,但还没有升级到支持该 editor 指令的客户端版本。\n\n#### 7.3 `REQUEST_TIMEOUT`\n\n表示服务端已转发请求,但在超时时间内没有收到目标前端的最终 `*.result`。\n";
|
|
313
|
+
const markdownSource = "# 开放接口使用文档(MVP)\n\n> Source Set:`docs/open-api/*.zh-CN.md` \n> 聚合产物:`docs/open-api-mvp.zh-CN.md` \n> 页面入口:`/api-docs.html`\n\n<a id=\"overview\"></a>\n\n适用场景:外部系统、本地服务、AI Agent 以及带网页编辑器的宿主应用,通过 Axhub Genie 的开放接口完成会话创建、续聊、中断、运行态观察,以及对在线网页编辑器实例做定向查询与控制。\n\n## Quick English Summary\n\n- HTTP: `GET /health`, `POST /api/agent`, `POST /api/agent/abort`\n- WebSocket: `WS /api/agent/ws`\n- CLI: `axhub-genie status`, `axhub-genie cc-connect ...`, `axhub-genie editor ...`\n- Editor integration model: open the page, let it auto-register, then send editor requests with `channel`; only specify `targetClientId` when multiple online pages are ambiguous\n\n## 1. 文档地图\n\n| 子文档 | 说明 |\n|---|---|\n| [`docs/open-api/http.zh-CN.md`](./http.zh-CN.md) | HTTP 接口、请求体、返回体、cURL 示例 |\n| [`docs/open-api/ws.zh-CN.md`](./ws.zh-CN.md) | `/api/agent/ws` 协议、集成 WS、editor 指令 |\n| [`docs/open-api/cli.zh-CN.md`](./cli.zh-CN.md) | `axhub-genie` CLI、editor 子命令、JSON 输出约定 |\n\n## 2. 基本信息\n\n- Assistant 前端地址示例:`http://localhost:5173`\n- Assistant 后端地址示例:`http://localhost:32123`\n- API Base 示例:`http://localhost:32123/api`\n- 会话页面路由格式:`/session/{provider}/{sessionId}`\n- 健康检查:`GET /health`\n\n### 2.1 地址发现\n\n在开发、测试、生产环境中,地址可能不同。推荐始终先执行:\n\n```bash\naxhub-genie status --json\n```\n\n典型返回:\n\n```json\n{\n \"running\": true,\n \"pid\": 12345,\n \"port\": 32123,\n \"startedAt\": \"2026-02-08T03:12:45.321Z\",\n \"statusFile\": \"/Users/you/.axhub-genie/runtime-status.json\",\n \"endpoint\": {\n \"environment\": \"development\",\n \"frontendUrl\": \"http://localhost:5173\",\n \"apiBaseUrl\": \"http://localhost:32123/api\"\n }\n}\n```\n\n使用建议:\n\n- 统一把 `endpoint.apiBaseUrl` 当作 `<CURRENT_API_BASE>`\n- editor CLI / WS 默认也以这里发现到的 API Base 为准\n\n### 2.2 服务身份识别\n\n为了避免误连到其他本地服务,建议对 `/health` 额外校验:\n\n- `service.id`\n- 响应头 `X-App-Identifier`\n\n推荐成功条件:\n\n- HTTP `200`\n- `status = ok`\n- `service.id = @axhub/genie`\n\n### 2.3 前端 URL 参数\n\n前端支持通过 URL 预选项目、provider 与动态上下文:\n\n| 参数 | 示例 | 说明 |\n|---|---|---|\n| `project` / `projectName` | `?project=my-project` | 按项目名/显示名/路径匹配 |\n| `cwd` / `workdir` | `?cwd=/Users/you/my-project` | 按工作目录匹配 |\n| `provider` / `tool` / `cli` | `?provider=codex` | 预设默认工具 |\n| `context` | `?context=...` | 动态上下文(`contextV1`) |\n| `prompt` | `?prompt=...` | 预填输入框内容 |\n| `integrationWs=1` | `?integrationWs=1` | 让页面额外连接 `/api/agent/ws` |\n\n说明:\n\n- 页面带 `integrationWs=1` 打开后,会自动通过 `integration.connect` 注册为 `frontend-page`\n- `frontend-page` 的 `clientId` 由前端在本地会话内自动生成并复用,不需要通过 URL 传入\n- `frontend-page` 的 `channel` 默认取 `cwd` / `workdir`;若未提供,则回退到 `axhub`\n- editor 相关请求通常只需要传 `channel`\n- 只有当同一 `channel` 下存在多个在线页面且服务端无法唯一推断目标时,才需要显式传 `targetClientId`\n\n<a id=\"authentication\"></a>\n\n## 3. 鉴权策略(MVP)\n\n- `/api/agent` 与 `/api/agent/ws` 默认允许匿名访问,并绑定到服务端默认用户\n- 若设置 `AGENT_API_KEY_REQUIRED=true`,则:\n - HTTP 通过 `X-API-Key`\n - WebSocket 通过查询参数 `apiKey`\n- editor CLI 与外部系统连接 `/api/agent/ws` 时,复用相同的鉴权规则\n\n说明:\n\n- 当前匿名模式不区分“本机请求”与“远程请求”,是否只对本机可见取决于你的部署方式与网络暴露范围\n- 非浏览器 WebSocket 客户端也兼容通过 `X-API-Key` 或 `Authorization: Bearer <token>` 传递凭证,但查询参数 `apiKey` 仍是推荐方式\n\n### 3.1 对外 WebSocket 与内部 UI WebSocket 的边界\n\n- `/ws`:前端应用内部协议,承载 UI 与 provider 的私有消息,不属于开放接口\n- `/api/agent/ws`:开放接口,承载 Agent 请求流、运行态查询/订阅、集成 WS,以及 editor 集成协议\n\n## 4. 能力总览\n\n### 4.1 HTTP\n\n- 创建会话 / 续聊:`POST /api/agent`\n- 打开既有会话:`POST /api/agent` + `openOnly=true`\n- 中断运行:`POST /api/agent/abort`\n\n详情见 [`docs/open-api/http.zh-CN.md`](./http.zh-CN.md)。\n\n### 4.2 WebSocket\n\n- `agent.run`\n- `agent.abort`\n- `agent.state.query`\n- `agent.state.subscribe`\n- `session.activity.subscribe`\n- `session.activity.unsubscribe`\n- `integration.connect`\n- `integration.ping`\n- `integration.context.update`\n- `integration.prompt.update`\n- `integration.editor.clients.list`\n- `integration.editor.snapshot.get`\n- `integration.editor.nodes.list`\n- `integration.editor.node.screenshot.get`\n- `integration.editor.context-images.get`\n- `integration.editor.editing.set`\n\n详情见 [`docs/open-api/ws.zh-CN.md`](./ws.zh-CN.md)。\n\n### 4.3 CLI\n\n- `axhub-genie status`\n- `axhub-genie cc-connect status`\n- `axhub-genie cc-connect set`\n- `axhub-genie editor clients list`\n- `axhub-genie editor snapshot`\n- `axhub-genie editor nodes list`\n- `axhub-genie editor node screenshot`\n- `axhub-genie editor context-images export`\n- `axhub-genie editor editing set`\n\n详情见 [`docs/open-api/cli.zh-CN.md`](./cli.zh-CN.md)。\n\n## 5. 推荐集成顺序\n\n1. 用 `axhub-genie status --json` 或 `/health` 发现服务地址并确认身份。\n2. 打开目标网页编辑器页面,并确保它已通过 `integration.connect` 自动注册到目标 `channel`。\n3. 优先直接发送 editor 请求,只传 `channel`;若服务端返回多页冲突,再通过 CLI 或 `integration.editor.clients.list` 枚举在线客户端并补传 `targetClientId`。\n4. 对会话调用 HTTP 或 `agent.run`。\n5. 对网页编辑器调用 editor CLI 或 editor WS 指令。\n\n<a id=\"faq\"></a>\n\n## 6. FAQ\n\n### Q1:为什么现在大多数 editor 命令不必再指定客户端?\n\n因为服务端现在会先尝试自动解析目标页面:显式 `targetClientId` 优先;否则命中该 `channel` 下唯一在线页;若发送方也注册了 `external-client`,还会尝试按同 `sessionId` 或同 `pageUrl` 继续收敛。只有仍然存在多个候选页时,才返回 `AMBIGUOUS_TARGET` 并要求补传 `targetClientId`。\n\n### Q2:客户端还没升级 editor capability 时会怎样?\n\n服务端会返回:\n\n```json\n{\n \"type\": \"integration.error\",\n \"payload\": {\n \"code\": \"UNSUPPORTED_FRONTEND_CAPABILITY\",\n \"message\": \"Target frontend page does not advertise capability editor.snapshot\"\n }\n}\n```\n\n### Q3:为什么要保留 `docs/open-api-mvp.zh-CN.md`?\n\n为了保持历史入口与 `/api-docs.html` 不变。维护时请编辑 `docs/open-api/*.zh-CN.md`,不要手改聚合产物。\n\n### Q4:Genie Editor 追加上下文时,会不会把已有文件路径清掉?\n\n不会。`integration.context.update` 在 `mode=append` 下,如果新增上下文里的 `currentFile.path` 为空,发送方会省略该字段,前端合并时也会保留已有文件路径,不会用空值覆盖。\n\n## 7. 版本说明\n\n- 文档版本:MVP v1.8\n- 更新日期:2026-04-10\n- 维护入口:`docs/open-api/*.zh-CN.md`\n- 聚合产物:`docs/open-api-mvp.zh-CN.md`\n\n---\n\n## HTTP API\n\n<a id=\"http-api\"></a>\n\n### 1. 健康检查\n\n#### `GET /health`\n\n请求示例:\n\n```bash\ncurl -i http://localhost:32123/health\n```\n\n响应示例:\n\n```json\n{\n \"status\": \"ok\",\n \"timestamp\": \"2026-02-09T12:00:00.000Z\",\n \"service\": {\n \"id\": \"@axhub/genie\",\n \"name\": \"Axhub Genie\",\n \"version\": \"1.16.3\"\n },\n \"runtime\": {\n \"environment\": \"development\",\n \"port\": 32123\n }\n}\n```\n\n关键响应头:\n\n- `X-App-Identifier`\n- `X-App-Name`\n- `X-App-Version`\n- `X-App-Environment`\n\n### 2. 创建或续聊会话\n\n#### `POST /api/agent`\n\n典型用途:\n\n- 新建会话并发送第一条消息\n- 带 `sessionId` 续聊既有会话\n- 带 `openOnly=true` 仅打开会话,不触发模型运行\n\n#### 2.1 请求体\n\n```json\n{\n \"projectPath\": \"/Users/you/your-project\",\n \"provider\": \"codex\",\n \"message\": \"请先梳理当前项目结构并给出重构计划\",\n \"stream\": false\n}\n```\n\n常用字段:\n\n| 字段 | 说明 |\n|---|---|\n| `projectPath` | 本地项目路径,可选;未传时按“服务启动配置目录 > 服务进程启动目录”回退 |\n| `provider` | `claude` / `codex` / `gemini` / `opencode` |\n| `model` | 可选模型名 |\n| `message` | 用户输入 |\n| `sessionId` | 既有会话 ID |\n| `openOnly` | 仅打开会话 |\n| `stream` | 是否流式返回 |\n| `images[]` | 附加图片;当前仅 `claude` / `codex` 支持 |\n| `callback` | 终态回调配置 |\n\n#### 2.2 关键校验规则\n\n- `message` 在 `openOnly !== true` 时必填\n- `provider` 必须是受支持的 provider\n- `sessionId` 续聊或 `openOnly=true` 时由调用方保证与 `provider` 配对正确;若省略 `provider`,服务端会默认按 `claude` 解析\n- `projectPath` 可省略;服务端会按“默认工作目录配置 > 进程当前目录”解析\n- `images[].data` 使用 data URL\n- `images` 不支持 `openOnly=true`\n- `images` 当前不支持 `gemini` / `opencode`\n- `githubUrl`、`githubToken`、`createBranch`、`branchName`、`createPR` 已从开放 API 移除,传入会返回 `400`\n\n#### 2.3 返回(`stream: false`)\n\n```json\n{\n \"success\": true,\n \"sessionId\": \"019c3263-967f-7ba2-84fe-fc5c694f6316\",\n \"sessionPath\": \"/session/codex/019c3263-967f-7ba2-84fe-fc5c694f6316\",\n \"sessionUrl\": \"https://assistant.example.com/session/codex/019c3263-967f-7ba2-84fe-fc5c694f6316\",\n \"isResumed\": false,\n \"messages\": [],\n \"tokens\": {\n \"inputTokens\": 0,\n \"outputTokens\": 0,\n \"cacheReadTokens\": 0,\n \"cacheCreationTokens\": 0,\n \"totalTokens\": 0\n },\n \"projectPath\": \"/Users/you/your-project\"\n}\n```\n\n### 3. 只打开会话页面\n\n当你只想进入某个既有会话,而不想立刻发消息时:\n\n```json\n{\n \"provider\": \"codex\",\n \"sessionId\": \"019c3263-967f-7ba2-84fe-fc5c694f6316\",\n \"openOnly\": true,\n \"stream\": false\n}\n```\n\n### 4. 中断运行中的会话\n\n#### `POST /api/agent/abort`\n\n请求示例:\n\n```json\n{\n \"sessionId\": \"019c3263-967f-7ba2-84fe-fc5c694f6316\",\n \"provider\": \"codex\"\n}\n```\n\n成功响应:\n\n```json\n{\n \"success\": true,\n \"aborted\": true,\n \"sessionId\": \"019c3263-967f-7ba2-84fe-fc5c694f6316\",\n \"provider\": \"codex\",\n \"message\": \"Session aborted\"\n}\n```\n\n未找到活跃会话时,HTTP 仍可能返回 `200`,但 `success=false`。\n\n### 5. cURL 示例\n\n#### 5.1 创建新会话\n\n```bash\ncurl -X POST <CURRENT_API_BASE>/agent \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"projectPath\": \"/Users/you/your-project\",\n \"provider\": \"codex\",\n \"message\": \"请先梳理当前项目结构并给出重构计划\",\n \"stream\": false\n }'\n```\n\n#### 5.2 创建会话并附带图片\n\n```bash\ncurl -X POST <CURRENT_API_BASE>/agent \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"projectPath\": \"/Users/you/your-project\",\n \"provider\": \"codex\",\n \"message\": \"请描述这张截图并指出 UI 问题\",\n \"images\": [\n {\n \"name\": \"ui.png\",\n \"data\": \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...\",\n \"mimeType\": \"image/png\"\n }\n ],\n \"stream\": false\n }'\n```\n\n#### 5.3 续聊指定会话\n\n```bash\ncurl -X POST <CURRENT_API_BASE>/agent \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"projectPath\": \"/Users/you/your-project\",\n \"provider\": \"codex\",\n \"sessionId\": \"019c3263-967f-7ba2-84fe-fc5c694f6316\",\n \"message\": \"继续上一轮,把第 1、2 点先落代码\",\n \"stream\": false\n }'\n```\n\n#### 5.4 只打开会话\n\n```bash\ncurl -X POST <CURRENT_API_BASE>/agent \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"provider\": \"codex\",\n \"sessionId\": \"019c3263-967f-7ba2-84fe-fc5c694f6316\",\n \"openOnly\": true,\n \"stream\": false\n }'\n```\n\n#### 5.5 中断运行中的会话\n\n```bash\ncurl -X POST <CURRENT_API_BASE>/agent/abort \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"sessionId\": \"019c3263-967f-7ba2-84fe-fc5c694f6316\",\n \"provider\": \"codex\"\n }'\n```\n\n### 6. 会话映射建议\n\n建议外部系统保存:\n\n- `external_conversation_key -> { provider, sessionId }`\n\n这样可以稳定支持:\n\n- 可重入\n- 可续聊\n- 可跳转\n- 可中断\n\n---\n\n## WebSocket API\n\n<a id=\"ws-api\"></a>\n\n### 1. 连接地址\n\n```text\nWS /api/agent/ws\n```\n\n鉴权方式:\n\n- 默认允许匿名访问,并绑定到服务端默认用户\n- 若开启 API Key,优先使用查询参数 `apiKey`\n\n说明:\n\n- 当前匿名模式不区分“本机请求”与“远程请求”,是否只对本机可见取决于你的部署方式与网络暴露范围\n- 非浏览器 WebSocket 客户端也兼容通过 `X-API-Key` 或 `Authorization: Bearer <token>` 传递凭证,但查询参数 `apiKey` 仍是推荐方式\n\n### 2. 使用模式\n\n`/api/agent/ws` 同时承载三类开放能力:\n\n- Agent 请求流:`agent.run` / `agent.abort`\n- Agent 运行态:`agent.state.query` / `agent.state.subscribe`\n- 会话活动流:`session.activity.subscribe` / `session.activity.unsubscribe`\n- 集成流:`integration.*`\n\n其中 editor 相关能力也属于 `integration.*` 协议的一部分。\n\n### 3. Agent 请求流\n\n#### 3.1 入站:`agent.run`\n\n```json\n{\n \"type\": \"agent.run\",\n \"requestId\": \"req_001\",\n \"payload\": {\n \"projectPath\": \"/Users/you/your-project\",\n \"provider\": \"codex\",\n \"message\": \"请继续处理当前任务\"\n }\n}\n```\n\n说明:\n\n- `payload.projectPath` 可选\n- 若未传,服务端按“默认工作目录配置 > 进程当前目录”回退\n\n#### 3.2 入站:`agent.abort`\n\n```json\n{\n \"type\": \"agent.abort\",\n \"requestId\": \"req_002\",\n \"payload\": {\n \"sessionId\": \"019c3263-967f-7ba2-84fe-fc5c694f6316\",\n \"provider\": \"codex\"\n }\n}\n```\n\n#### 3.3 出站:典型序列\n\n1. `agent.accepted`\n2. `agent.session.created`\n3. 多个 `agent.event`\n4. `agent.completed`\n\n中断时终态为 `agent.aborted`;失败时终态为 `agent.error`。\n\n### 4. Agent 运行态查询/订阅\n\n#### 4.1 查询\n\n```json\n{\n \"type\": \"agent.state.query\",\n \"requestId\": \"state_001\",\n \"payload\": {\n \"sessionId\": \"019c3263-967f-7ba2-84fe-fc5c694f6316\",\n \"provider\": \"codex\"\n }\n}\n```\n\n响应:\n\n```json\n{\n \"type\": \"agent.state.snapshot\",\n \"requestId\": \"state_001\",\n \"payload\": {\n \"sessionId\": \"019c3263-967f-7ba2-84fe-fc5c694f6316\",\n \"provider\": \"codex\",\n \"phase\": \"streaming\",\n \"isLoading\": true,\n \"canAbortSession\": true,\n \"hasPendingApproval\": false,\n \"updatedAt\": \"2026-03-20T10:00:01.000Z\"\n }\n}\n```\n\n#### 4.2 订阅\n\n```json\n{\n \"type\": \"agent.state.subscribe\",\n \"requestId\": \"state_002\",\n \"payload\": {\n \"sessionId\": \"019c3263-967f-7ba2-84fe-fc5c694f6316\",\n \"provider\": \"codex\"\n }\n}\n```\n\n确认:\n\n```json\n{\n \"type\": \"agent.state.subscribed\",\n \"requestId\": \"state_002\",\n \"payload\": {\n \"sessionId\": \"019c3263-967f-7ba2-84fe-fc5c694f6316\",\n \"provider\": \"codex\",\n \"subscriptionKey\": \"codex:019c3263-967f-7ba2-84fe-fc5c694f6316\"\n }\n}\n```\n\n变化通知:\n\n```json\n{\n \"type\": \"agent.state.changed\",\n \"payload\": {\n \"subscriptionKey\": \"codex:019c3263-967f-7ba2-84fe-fc5c694f6316\",\n \"sessionId\": \"019c3263-967f-7ba2-84fe-fc5c694f6316\",\n \"provider\": \"codex\",\n \"phase\": \"completed\",\n \"isLoading\": false,\n \"canAbortSession\": false,\n \"hasPendingApproval\": false,\n \"updatedAt\": \"2026-03-20T10:00:08.000Z\"\n }\n}\n```\n\n#### 4.3 会话活动订阅\n\n按 `provider + sessionId` 订阅:\n\n```json\n{\n \"type\": \"session.activity.subscribe\",\n \"requestId\": \"activity_001\",\n \"payload\": {\n \"provider\": \"codex\",\n \"sessionId\": \"019c3263-967f-7ba2-84fe-fc5c694f6316\"\n }\n}\n```\n\n确认:\n\n```json\n{\n \"type\": \"session.activity.subscribed\",\n \"requestId\": \"activity_001\",\n \"payload\": {\n \"provider\": \"codex\",\n \"sessionId\": \"019c3263-967f-7ba2-84fe-fc5c694f6316\"\n }\n}\n```\n\n活动事件:\n\n```json\n{\n \"type\": \"session.activity.event\",\n \"payload\": {\n \"provider\": \"codex\",\n \"sessionId\": \"019c3263-967f-7ba2-84fe-fc5c694f6316\",\n \"kind\": \"assistant.message.completed\",\n \"messageId\": \"msg_001\",\n \"requestId\": \"req_001\",\n \"text\": \"已完成本次更新。\"\n }\n}\n```\n\n取消订阅:\n\n```json\n{\n \"type\": \"session.activity.unsubscribe\",\n \"requestId\": \"activity_002\",\n \"payload\": {\n \"provider\": \"codex\",\n \"sessionId\": \"019c3263-967f-7ba2-84fe-fc5c694f6316\"\n }\n}\n```\n\n说明:\n\n- 也支持按单次请求 `requestId` 订阅;此时 `payload` 可只传 `requestId`\n- 服务端确认取消时会返回 `session.activity.unsubscribed`\n\n### 5. 集成流基础协议\n\n#### 5.1 页面注册:`integration.connect`\n\n前端页面示例:\n\n```json\n{\n \"type\": \"integration.connect\",\n \"requestId\": \"conn_001\",\n \"payload\": {\n \"role\": \"frontend-page\",\n \"channel\": \"project-a\",\n \"clientId\": \"figma-123\",\n \"source\": \"chrome-extension\",\n \"pageUrl\": \"http://localhost:5173/session/019c...?...\",\n \"sessionId\": \"019c3263-967f-7ba2-84fe-fc5c694f6316\",\n \"capabilities\": [\n \"context.update\",\n \"prompt.update\",\n \"presence.report\"\n ]\n }\n}\n```\n\n说明:\n\n- `source` 为可选字段,用于标记客户端来源,例如 `chrome-extension`\n- Assistant 前端页面通常会用打开页面时的 `cwd` / `workdir` 作为 `channel`;若未提供则回退到 `axhub`\n- 页面应在打开后尽早发送 `integration.connect` 完成自动注册;只要连接存活,服务端就会把它视为可路由的 `frontend-page`\n\n外部系统示例:\n\n```json\n{\n \"type\": \"integration.connect\",\n \"requestId\": \"conn_002\",\n \"payload\": {\n \"role\": \"external-client\",\n \"channel\": \"project-a\",\n \"clientId\": \"host-app-01\",\n \"pageUrl\": \"http://localhost:5173/session/019c...?...\",\n \"sessionId\": \"019c3263-967f-7ba2-84fe-fc5c694f6316\",\n \"capabilities\": [\n \"presence.query\",\n \"context.push\",\n \"prompt.push\",\n \"editor.query\"\n ]\n }\n}\n```\n\n说明:\n\n- `external-client` 的 `pageUrl` / `sessionId` 为可选字段\n- 当 editor 请求未显式传 `targetClientId` 时,服务端会优先利用这些字段做同页归因\n\n#### 5.2 探活:`integration.ping`\n\n```json\n{\n \"type\": \"integration.ping\",\n \"requestId\": \"ping_001\",\n \"payload\": {\n \"channel\": \"project-a\",\n \"targetClientId\": \"figma-123\"\n }\n}\n```\n\n响应:\n\n```json\n{\n \"type\": \"integration.pong\",\n \"requestId\": \"ping_001\",\n \"payload\": {\n \"server\": {\n \"status\": \"ok\",\n \"started\": true\n },\n \"frontend\": {\n \"connected\": true,\n \"count\": 1,\n \"clients\": [\n {\n \"clientId\": \"figma-123\",\n \"lastSeenAt\": \"2026-03-19T10:00:03.000Z\",\n \"pageUrl\": \"http://localhost:5173/session/019c...?integrationWs=1...\",\n \"sessionId\": \"019c3263-967f-7ba2-84fe-fc5c694f6316\"\n }\n ]\n }\n }\n}\n```\n\n#### 5.3 运行期上下文/提示词写入\n\n- `integration.context.update`\n- `integration.prompt.update`\n\n典型的上下文追加请求:\n\n```json\n{\n \"type\": \"integration.context.update\",\n \"requestId\": \"ctx_001\",\n \"payload\": {\n \"channel\": \"project-a\",\n \"mode\": \"append\",\n \"context\": {\n \"version\": \"1\",\n \"systemContext\": \"\",\n \"selectedElements\": [\n {\n \"tag\": \"button\",\n \"selector\": \"body > main > button.primary\",\n \"label\": \"主按钮\"\n }\n ]\n }\n }\n}\n```\n\n典型的提示词更新请求:\n\n```json\n{\n \"type\": \"integration.prompt.update\",\n \"requestId\": \"prompt_001\",\n \"payload\": {\n \"channel\": \"project-a\",\n \"mode\": \"append\",\n \"prompt\": \"请先处理刚刚选中的主按钮。\"\n }\n}\n```\n\n约定说明:\n\n- `targetClientId` 在常见场景下可省略\n- 服务端解析顺序为:显式 `targetClientId` > `channel` 下唯一在线页 > 与发送方同 `sessionId` 的页 > 与发送方同 `pageUrl` 的页 > 返回 `AMBIGUOUS_TARGET`\n- `integration.context.update` 在 `mode=append` 下,若追加上下文里的 `currentFile.path` 为空,不会覆盖会话中已存在的文件路径\n\n### 6. Editor 集成协议\n\n#### 6.1 设计原则\n\n- 统一复用 `/api/agent/ws`\n- 统一带 `requestId`\n- 除 `clients.list` 外,统一要求 `channel`;`targetClientId` 仅在显式定向或多页冲突兜底时需要\n- 读操作终态为 `integration.editor.*.result`\n- 参数错误、目标页离线、超时、能力不支持统一走 `integration.error`\n- 写操作可以先回 `integration.ack`,但终态仍以 `integration.editor.*.result` 或 `integration.error` 为准\n\n#### 6.2 自动路由与冲突兜底\n\n服务端在转发 editor 请求时,按如下顺序选择目标页:\n\n1. 若请求显式传了 `targetClientId`,精确命中该页面\n2. 若该 `channel` 下只有一个在线 `frontend-page`,自动命中它\n3. 若发送方也已注册为 `external-client` 且带了 `sessionId`,尝试命中同 `sessionId` 页面\n4. 若仍未命中且发送方带了 `pageUrl`,尝试命中同 `pageUrl` 页面\n5. 若依然有多个候选页,返回 `AMBIGUOUS_TARGET`\n\n因此,推荐流程是“页面自动注册,调用方默认只传 `channel`,冲突时再补选页”。\n\n#### 6.3 先列出客户端\n\n##### 入站:`integration.editor.clients.list`\n\n```json\n{\n \"type\": \"integration.editor.clients.list\",\n \"requestId\": \"editor_clients_001\",\n \"payload\": {\n \"channel\": \"project-a\"\n }\n}\n```\n\n##### 出站:`integration.editor.clients.result`\n\n```json\n{\n \"type\": \"integration.editor.clients.result\",\n \"requestId\": \"editor_clients_001\",\n \"payload\": {\n \"items\": [\n {\n \"channel\": \"project-a\",\n \"clientId\": \"figma-123\",\n \"source\": \"chrome-extension\",\n \"sessionId\": \"019c3263-967f-7ba2-84fe-fc5c694f6316\",\n \"pageUrl\": \"http://localhost:5173/session/019c...?integrationWs=1...\",\n \"lastSeenAt\": \"2026-03-21T09:00:00.000Z\",\n \"connectedAt\": \"2026-03-21T08:58:00.000Z\",\n \"connectionId\": \"conn_001\",\n \"capabilities\": [\n \"context.update\",\n \"prompt.update\",\n \"editor.snapshot\",\n \"editor.nodes.list\",\n \"editor.node.screenshot\",\n \"editor.context-images\",\n \"editor.editing.set\"\n ]\n }\n ],\n \"total\": 1,\n \"filters\": {\n \"channel\": \"project-a\",\n \"clientId\": null\n }\n }\n}\n```\n\n说明:\n\n- `source` 用于区分客户端来源,AI Agent 可据此识别是否来自 Chrome 扩展\n\n#### 6.4 编辑器快照\n\n##### 入站:`integration.editor.snapshot.get`\n\n```json\n{\n \"type\": \"integration.editor.snapshot.get\",\n \"requestId\": \"editor_snapshot_001\",\n \"payload\": {\n \"channel\": \"project-a\"\n }\n}\n```\n\n说明:\n\n- `targetClientId` 可选;仅在调用方需要显式指定目标页面时传入\n\n##### 出站:`integration.editor.snapshot.result`\n\n```json\n{\n \"type\": \"integration.editor.snapshot.result\",\n \"requestId\": \"editor_snapshot_001\",\n \"payload\": {\n \"resource\": null,\n \"selectedElement\": null,\n \"modifiedElements\": [],\n \"textChanges\": [],\n \"styleChanges\": {\n \"cssText\": \"\"\n },\n \"statusSummary\": {\n \"active\": true,\n \"modifiedCount\": 0,\n \"nodeStateCounts\": {\n \"clean\": 0,\n \"dirty\": 0,\n \"handled\": 0,\n \"editing\": 0,\n \"completed\": 0,\n \"error\": 0\n }\n }\n }\n}\n```\n\n#### 6.5 节点列表\n\n##### 入站:`integration.editor.nodes.list`\n\n```json\n{\n \"type\": \"integration.editor.nodes.list\",\n \"requestId\": \"editor_nodes_001\",\n \"payload\": {\n \"channel\": \"project-a\",\n \"status\": [\"pending-dispatch\", \"dirty\"],\n \"elementKey\": null,\n \"limit\": 100\n }\n}\n```\n\n##### 出站:`integration.editor.nodes.result`\n\n```json\n{\n \"type\": \"integration.editor.nodes.result\",\n \"requestId\": \"editor_nodes_001\",\n \"payload\": {\n \"items\": [\n {\n \"elementKey\": \"hero-card\",\n \"label\": \"body > main > section.hero-card\",\n \"changeState\": \"dirty\",\n \"taskState\": \"idle\",\n \"hasNote\": true,\n \"hasImages\": false,\n \"changeKinds\": [\"text\"],\n \"dirtySince\": 1742547600000,\n \"lastHandledAt\": null\n }\n ],\n \"total\": 1,\n \"filters\": {\n \"status\": [\"pending-dispatch\", \"dirty\"],\n \"elementKey\": null,\n \"limit\": 100\n }\n }\n}\n```\n\n推荐状态字段:\n\n- `changeState`: `clean` / `dirty` / `handled`\n- `taskState`: `idle` / `editing` / `completed` / `error`\n- `hasNote`\n- `hasImages`\n- `changeKinds`\n- `dirtySince`\n- `lastHandledAt`\n\n推荐状态别名:\n\n- `dirty`\n- `handled`\n- `editing`\n- `completed`\n- `error`\n- `pending-dispatch`\n 定义为 `changeState=dirty && taskState=idle && changeState!=handled`\n\n#### 6.6 节点截图\n\n##### 入站:`integration.editor.node.screenshot.get`\n\n```json\n{\n \"type\": \"integration.editor.node.screenshot.get\",\n \"requestId\": \"editor_shot_001\",\n \"payload\": {\n \"channel\": \"project-a\",\n \"elementKey\": \"hero-card\",\n \"downloadPath\": \"/Users/you/tmp\"\n }\n}\n```\n\n说明:\n\n- `downloadPath` 是服务端本地落盘目录,不是前端页面自己的文件路径\n- 前端页面收到指令后,应将截图内容以 `data:<mime>;base64,...` 的形式回传给服务端\n- 服务端收到 base64/data URL 后负责写入本地文件,再把 `absolutePath` 返回给 CLI / 外部调用方\n\n##### 前端页面回包:`integration.editor.node.screenshot.result`\n\n```json\n{\n \"type\": \"integration.editor.node.screenshot.result\",\n \"requestId\": \"editor_shot_001\",\n \"payload\": {\n \"elementKey\": \"hero-card\",\n \"image\": {\n \"name\": \"hero-card.png\",\n \"data\": \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...\",\n \"width\": 1440,\n \"height\": 640\n },\n \"mimeType\": \"image/png\",\n \"width\": 1440,\n \"height\": 640\n }\n}\n```\n\n兼容说明:\n\n- 前端可以把 `data` 放在 `payload.image.data`\n- 也可以直接放在 `payload.data`\n- 如果前端未来已经具备本地文件访问代理能力,服务端当前也兼容直接回传 `absolutePath`,但推荐协议仍然是回传 data URL,由服务端统一落盘\n\n##### 服务端对外回包:`integration.editor.node.screenshot.result`\n\n```json\n{\n \"type\": \"integration.editor.node.screenshot.result\",\n \"requestId\": \"editor_shot_001\",\n \"payload\": {\n \"elementKey\": \"hero-card\",\n \"absolutePath\": \"/Users/you/tmp/hero-card.png\",\n \"mimeType\": \"image/png\",\n \"width\": 1440,\n \"height\": 640,\n \"size\": 482113\n }\n}\n```\n\n#### 6.7 上下文图片导出\n\n##### 入站:`integration.editor.context-images.get`\n\n```json\n{\n \"type\": \"integration.editor.context-images.get\",\n \"requestId\": \"editor_ctximg_001\",\n \"payload\": {\n \"channel\": \"project-a\",\n \"downloadPath\": \"/Users/you/tmp\"\n }\n}\n```\n\n说明:\n\n- `downloadPath` 同样是服务端本地目录\n- 前端页面应把上下文图片逐项回传为 data URL / base64\n- 服务端负责逐张写入本地,并返回每张图片的 `absolutePath`\n\n##### 前端页面回包:`integration.editor.context-images.result`\n\n```json\n{\n \"type\": \"integration.editor.context-images.result\",\n \"requestId\": \"editor_ctximg_001\",\n \"payload\": {\n \"items\": [\n {\n \"id\": \"img_001\",\n \"name\": \"clipboard-image-1.png\",\n \"data\": \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...\",\n \"mimeType\": \"image/png\",\n \"createdAt\": 1742547600000,\n \"source\": \"prompt-context\"\n }\n ]\n }\n}\n```\n\n##### 服务端对外回包:`integration.editor.context-images.result`\n\n```json\n{\n \"type\": \"integration.editor.context-images.result\",\n \"requestId\": \"editor_ctximg_001\",\n \"payload\": {\n \"items\": [\n {\n \"id\": \"img_001\",\n \"name\": \"clipboard-image-1.png\",\n \"absolutePath\": \"/Users/you/tmp/clipboard-image-1.png\",\n \"mimeType\": \"image/png\",\n \"size\": 90312,\n \"createdAt\": 1742547600000,\n \"source\": \"prompt-context\"\n }\n ]\n }\n}\n```\n\n#### 6.8 编辑态设置\n\n##### 入站:`integration.editor.editing.set`\n\n```json\n{\n \"type\": \"integration.editor.editing.set\",\n \"requestId\": \"editor_editing_001\",\n \"payload\": {\n \"channel\": \"project-a\",\n \"elementKey\": \"hero-card\",\n \"state\": \"editing\",\n \"taskRef\": {\n \"provider\": \"codex\",\n \"sessionId\": \"019c3263-967f-7ba2-84fe-fc5c694f6316\",\n \"requestId\": \"req_001\"\n }\n }\n}\n```\n\n##### 出站:`integration.editor.editing.result`\n\n```json\n{\n \"type\": \"integration.editor.editing.result\",\n \"requestId\": \"editor_editing_001\",\n \"payload\": {\n \"elementKey\": \"hero-card\",\n \"state\": \"editing\",\n \"applied\": true,\n \"taskRef\": {\n \"provider\": \"codex\",\n \"sessionId\": \"019c3263-967f-7ba2-84fe-fc5c694f6316\",\n \"requestId\": \"req_001\"\n }\n }\n}\n```\n\n说明:\n\n- `state` 支持 `editing`、`idle`、`completed`、`error`\n\n#### 6.9 能力声明\n\n服务端会在转发 editor 指令前检查目标前端页面是否声明以下 capability:\n\n| 消息类型 | capability |\n|---|---|\n| `integration.editor.snapshot.get` | `editor.snapshot` |\n| `integration.editor.nodes.list` | `editor.nodes.list` |\n| `integration.editor.node.screenshot.get` | `editor.node.screenshot` |\n| `integration.editor.context-images.get` | `editor.context-images` |\n| `integration.editor.editing.set` | `editor.editing.set` |\n\n若目标页未声明对应 capability,服务端返回:\n\n```json\n{\n \"type\": \"integration.error\",\n \"requestId\": \"editor_snapshot_001\",\n \"payload\": {\n \"code\": \"UNSUPPORTED_FRONTEND_CAPABILITY\",\n \"message\": \"Target frontend page does not advertise capability editor.snapshot\"\n }\n}\n```\n\n#### 6.10 常见错误码\n\n- `FRONTEND_NOT_ONLINE`\n- `AMBIGUOUS_TARGET`\n- `INVALID_TARGET`\n- `INVALID_PAYLOAD`\n- `UNSUPPORTED_MESSAGE_TYPE`\n- `UNSUPPORTED_FRONTEND_CAPABILITY`\n- `REQUEST_TIMEOUT`\n\n---\n\n## CLI API\n\n<a id=\"cli-api\"></a>\n\n### 1. 地址发现与状态检查\n\n#### `axhub-genie status`\n\n用于查看:\n\n- 当前服务是否运行\n- PID / 端口\n- `endpoint.frontendUrl`\n- `endpoint.apiBaseUrl`\n\n示例:\n\n```bash\naxhub-genie status --json\n```\n\n返回示例:\n\n```json\n{\n \"running\": true,\n \"pid\": 12345,\n \"port\": 32123,\n \"startedAt\": \"2026-02-08T03:12:45.321Z\",\n \"statusFile\": \"/Users/you/.axhub-genie/runtime-status.json\",\n \"defaultProjectPath\": \"/Users/you/your-project\",\n \"endpoint\": {\n \"environment\": \"development\",\n \"frontendUrl\": \"http://localhost:5173\",\n \"apiBaseUrl\": \"http://localhost:32123/api\"\n }\n}\n```\n\n说明:\n\n- 启动服务时可通过 `axhub-genie --cwd /path/to/project` 配置默认工作目录\n- 当开放 API 未显式传 `projectPath` 时,服务端按“默认工作目录配置 > 服务进程启动目录”回退\n\n### 2. cc-connect 子命令\n\n所有 `cc-connect` 子命令都默认输出 JSON,用于读取或更新本机 `cc-connect` 平台绑定配置。\n\n#### 2.1 通用参数\n\n| 参数 | 说明 |\n|---|---|\n| `--platform <id>` | 目标平台,当前支持 `weixin` / `feishu` |\n| `--provider <id>` | 切换到的 AI 供应商:`claude` / `codex` / `gemini` / `opencode` |\n| `--project-path <path>` | 切换到的新项目目录 |\n| `--json` | 显式声明 JSON 输出(默认已是 JSON) |\n\n统一成功包型:\n\n```json\n{\n \"ok\": true,\n \"command\": \"cc-connect set\",\n \"platform\": \"feishu\",\n \"data\": {}\n}\n```\n\n统一失败包型:\n\n```json\n{\n \"ok\": false,\n \"command\": \"cc-connect set\",\n \"platform\": \"feishu\",\n \"error\": {\n \"code\": \"PLATFORM_NOT_CONNECTED\",\n \"message\": \"Feishu is not connected.\"\n }\n}\n```\n\n失败时 CLI 以非 0 退出码结束。\n\n#### 2.2 `axhub-genie cc-connect status`\n\n作用:查看当前 `cc-connect` 安装状态、已检测到的供应商,以及平台绑定信息。\n\n示例:\n\n```bash\naxhub-genie cc-connect status\n```\n\n指定单个平台:\n\n```bash\naxhub-genie cc-connect status --platform feishu\n```\n\n返回示例:\n\n```json\n{\n \"ok\": true,\n \"command\": \"cc-connect status\",\n \"platform\": \"feishu\",\n \"data\": {\n \"ccConnect\": {\n \"installed\": true,\n \"version\": \"0.6.0-beta.4\",\n \"isBeta\": true,\n \"resolvedPath\": \"/opt/homebrew/bin/cc-connect\"\n },\n \"providers\": [\n {\n \"id\": \"claude\",\n \"label\": \"Claude\",\n \"installed\": true\n },\n {\n \"id\": \"codex\",\n \"label\": \"Codex\",\n \"installed\": true\n }\n ],\n \"platform\": {\n \"id\": \"feishu\",\n \"label\": \"Feishu\",\n \"connected\": true,\n \"activeProvider\": \"codex\",\n \"configuredProviders\": [\"claude\", \"codex\", \"gemini\", \"opencode\"],\n \"projectPath\": \"/Users/you/your-project\"\n }\n }\n}\n```\n\n#### 2.3 `axhub-genie cc-connect set`\n\n作用:切换指定平台当前绑定的 AI 供应商,或者切换该平台消息最终路由到的项目目录。两者可以一次命令同时更新,并只触发一次 `cc-connect` 配置写入与 daemon 重载。\n\n示例 1:切换飞书当前供应商到 `codex`\n\n```bash\naxhub-genie cc-connect set --platform feishu --provider codex\n```\n\n示例 2:切换微信默认工作项目\n\n```bash\naxhub-genie cc-connect set --platform weixin --project-path /Users/you/workspace/app\n```\n\n示例 3:同时切换供应商与项目目录\n\n```bash\naxhub-genie cc-connect set \\\n --platform feishu \\\n --provider claude \\\n --project-path /Users/you/workspace/assistant\n```\n\n返回示例:\n\n```json\n{\n \"ok\": true,\n \"command\": \"cc-connect set\",\n \"platform\": \"feishu\",\n \"data\": {\n \"platform\": \"feishu\",\n \"label\": \"Feishu\",\n \"provider\": \"claude\",\n \"projectPath\": \"/Users/you/workspace/assistant\",\n \"configuredProviders\": [\"claude\", \"codex\", \"gemini\", \"opencode\"],\n \"changed\": true,\n \"changedFields\": [\"provider\", \"projectPath\"],\n \"message\": \"cc-connect daemon restarted with the latest configuration.\"\n }\n}\n```\n\n约束:\n\n- `--platform` 必填\n- `--provider` 与 `--project-path` 至少传一个\n- `--project-path` 必须是本机存在的目录\n- 命令会直接更新 `~/.cc-connect/config.toml` 以及 `~/.cc-connect/ai-web-ui-connect-state.json`\n\n### 3. Editor 子命令\n\n所有 editor 子命令都默认输出 JSON,并通过 `/api/agent/ws` 与在线 frontend-page 通信。\n\n#### 3.1 通用参数\n\n| 参数 | 说明 |\n|---|---|\n| `--api-base <url>` | 显式指定 API Base,默认自动发现 |\n| `--api-key <key>` | 连接 `/api/agent/ws` 时的 API Key |\n| `--channel <name>` | 目标业务通道 |\n| `--target-client-id <id>` | 目标前端页面实例;可选,只有多页面冲突或需要强制定向时才传 |\n| `--timeout-ms <ms>` | 请求超时 |\n| `--json` | 显式声明 JSON 输出 |\n| `--output-dir <path>` | 截图/图片导出目录,默认当前目录 |\n\n默认路由约定:\n\n- 先打开目标页面,让它自动注册到对应 `channel`\n- CLI 在大多数场景下只需要传 `--channel`\n- 只有同一 `channel` 下存在多个在线页面并返回 `AMBIGUOUS_TARGET` 时,才需要先列客户端再补传 `--target-client-id`\n\n### 4. 推荐顺序:先打开页面,冲突时再列客户端\n\n#### `axhub-genie editor clients list`\n\n作用:列出当前在线的网页编辑器客户端。通常只在多页面冲突、排查连接状态、或需要显式定向到某个页面时使用。\n\n示例:\n\n```bash\naxhub-genie editor clients list --channel project-a\n```\n\n返回示例:\n\n```json\n{\n \"ok\": true,\n \"requestId\": \"editor_xxx\",\n \"channel\": null,\n \"targetClientId\": null,\n \"data\": {\n \"items\": [\n {\n \"channel\": \"project-a\",\n \"clientId\": \"figma-123\",\n \"sessionId\": \"019c3263-967f-7ba2-84fe-fc5c694f6316\",\n \"pageUrl\": \"http://localhost:5173/session/019c...?integrationWs=1...\",\n \"lastSeenAt\": \"2026-03-21T09:00:00.000Z\",\n \"connectedAt\": \"2026-03-21T08:58:00.000Z\",\n \"connectionId\": \"conn_001\",\n \"capabilities\": [\n \"editor.snapshot\",\n \"editor.nodes.list\"\n ]\n }\n ],\n \"total\": 1,\n \"filters\": {\n \"channel\": \"project-a\",\n \"clientId\": null\n }\n }\n}\n```\n\n### 5. Editor 快照与节点\n\n#### `axhub-genie editor snapshot`\n\n```bash\naxhub-genie editor snapshot \\\n --channel project-a\n```\n\n返回字段覆盖:\n\n- `resource`\n- `selectedElement`\n- `modifiedElements`\n- `textChanges`\n- `styleChanges`\n- `statusSummary`\n\n#### `axhub-genie editor nodes list`\n\n```bash\naxhub-genie editor nodes list \\\n --channel project-a \\\n --status pending-dispatch,dirty \\\n --limit 100\n```\n\n推荐状态字段:\n\n- `changeState`\n - `clean`\n - `dirty`\n - `handled`\n- `taskState`\n - `idle`\n - `editing`\n - `completed`\n - `error`\n- `hasNote`\n- `hasImages`\n- `changeKinds`\n- `dirtySince`\n- `lastHandledAt`\n\n推荐状态别名:\n\n- `dirty`\n- `handled`\n- `editing`\n- `completed`\n- `error`\n- `pending-dispatch`\n 定义为 `changeState=dirty && taskState=idle && changeState!=handled`\n\n### 6. 截图与上下文图片\n\n约定:\n\n- 前端页面通过 WS 把截图/图片内容以 data URL / base64 回传给服务端\n- 服务端再把文件写入 `--output-dir` 指向的本地目录\n- CLI 最终返回的是服务端已经落好的绝对路径,而不是前端页面自己的临时路径\n\n#### `axhub-genie editor node screenshot`\n\n```bash\naxhub-genie editor node screenshot \\\n --channel project-a \\\n --element-key hero-card \\\n --output-dir .\n```\n\n返回:\n\n- `absolutePath`\n- `mimeType`\n- `width`\n- `height`\n- `size`\n\n#### `axhub-genie editor context-images export`\n\n```bash\naxhub-genie editor context-images export \\\n --channel project-a \\\n --output-dir .\n```\n\n返回每张图片的:\n\n- `id`\n- `name`\n- `absolutePath`\n- `mimeType`\n- `size`\n- `createdAt`\n- `source`\n\n### 7. 编辑态设置\n\n#### `axhub-genie editor editing set`\n\n```bash\naxhub-genie editor editing set \\\n --channel project-a \\\n --element-key hero-card \\\n --state editing \\\n --provider codex \\\n --session-id 019c3263-967f-7ba2-84fe-fc5c694f6316 \\\n --task-request-id req_001\n```\n\n说明:\n\n- `--state` 允许 `editing`、`idle`、`completed`、`error`\n- 可选通过 `--provider` / `--session-id` / `--task-request-id` 传递任务追踪信息\n\n### 8. 常见失败原因\n\n#### 8.1 `FRONTEND_NOT_ONLINE`\n\n表示目标 `channel` 当前没有在线页面;如果同时显式传了 `--target-client-id`,也可能表示该页面实例当前不在线。\n\n#### 8.2 `AMBIGUOUS_TARGET`\n\n表示同一 `channel` 下存在多个在线页面,CLI 无法自动判断应该命中哪一个。此时请先执行 `axhub-genie editor clients list --channel <name>`,再补传 `--target-client-id`。\n\n#### 8.3 `UNSUPPORTED_FRONTEND_CAPABILITY`\n\n表示目标页面已经在线,但还没有升级到支持该 editor 指令的客户端版本。\n\n#### 8.4 `REQUEST_TIMEOUT`\n\n表示服务端已转发请求,但在超时时间内没有收到目标前端的最终 `*.result`。\n";
|
|
314
314
|
const root = document.getElementById('markdown-root');
|
|
315
315
|
|
|
316
316
|
function scrollToHashAnchor() {
|