@axhub/genie 0.2.7 → 0.2.8

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.
Files changed (117) hide show
  1. package/dist/api-docs.html +2 -2
  2. package/dist/assets/App-CTKZtqB1.js +460 -0
  3. package/dist/assets/App-qxJ8_QYu.css +32 -0
  4. package/dist/assets/ReviewApp-DM6BNAzR.js +1 -0
  5. package/dist/assets/{_basePickBy-C19AekOu.js → _basePickBy-CqJbRZ9y.js} +1 -1
  6. package/dist/assets/{_baseUniq-JsnevLw_.js → _baseUniq-BS8YH8jO.js} +1 -1
  7. package/dist/assets/{arc-BLpcuBlf.js → arc-BBmKEN-S.js} +1 -1
  8. package/dist/assets/architectureDiagram-2XIMDMQ5-N5lcb82R.js +36 -0
  9. package/dist/assets/{blockDiagram-WCTKOSBZ-DQBLwsUS.js → blockDiagram-WCTKOSBZ-DTMwHuLn.js} +3 -3
  10. package/dist/assets/c4Diagram-IC4MRINW-BTKlkXI9.js +10 -0
  11. package/dist/assets/channel-1oJBvF-0.js +1 -0
  12. package/dist/assets/{chunk-4BX2VUAB-De63kbgc.js → chunk-4BX2VUAB-DUdoTxAc.js} +1 -1
  13. package/dist/assets/{chunk-55IACEB6-DtTDDdM9.js → chunk-55IACEB6-Bm_92xe4.js} +1 -1
  14. package/dist/assets/{chunk-FMBD7UC4-DHuwd8tw.js → chunk-FMBD7UC4-CGW0g62g.js} +1 -1
  15. package/dist/assets/{chunk-JSJVCQXG-BgytFtmO.js → chunk-JSJVCQXG-DYkTH3w1.js} +1 -1
  16. package/dist/assets/{chunk-KX2RTZJC-nZdp86aN.js → chunk-KX2RTZJC-C9oTlISU.js} +1 -1
  17. package/dist/assets/chunk-NQ4KR5QH-CM50ygWP.js +220 -0
  18. package/dist/assets/{chunk-QZHKN3VN-DvUQ3mnO.js → chunk-QZHKN3VN-7dzpYeNJ.js} +1 -1
  19. package/dist/assets/chunk-WL4C6EOR-Cm9nQrsr.js +189 -0
  20. package/dist/assets/classDiagram-VBA2DB6C-d5TeKFM4.js +1 -0
  21. package/dist/assets/classDiagram-v2-RAHNMMFH-d5TeKFM4.js +1 -0
  22. package/dist/assets/clone-CinxIlEu.js +1 -0
  23. package/dist/assets/cose-bilkent-S5V4N54A-Ccp_p0JZ.js +1 -0
  24. package/dist/assets/cytoscape.esm-2ZfV8NB5.js +331 -0
  25. package/dist/assets/{dagre-KLK3FWXG-CHYIvW47.js → dagre-KLK3FWXG-fBwTLUp9.js} +1 -1
  26. package/dist/assets/diagram-E7M64L7V-CeNVmFUp.js +24 -0
  27. package/dist/assets/{diagram-IFDJBPK2-Dzsiln_C.js → diagram-IFDJBPK2-CtavyLGa.js} +1 -1
  28. package/dist/assets/{diagram-P4PSJMXO-DKnGbUpE.js → diagram-P4PSJMXO-CpQTjQwc.js} +1 -1
  29. package/dist/assets/erDiagram-INFDFZHY-B8R5vwhd.js +70 -0
  30. package/dist/assets/{flowDiagram-PKNHOUZH-BAZ2-jKp.js → flowDiagram-PKNHOUZH-BvkVVwIQ.js} +4 -4
  31. package/dist/assets/ganttDiagram-A5KZAMGK-DOu3hSNa.js +292 -0
  32. package/dist/assets/{gitGraphDiagram-K3NZZRJ6-BflpyjGy.js → gitGraphDiagram-K3NZZRJ6-C7zT67YE.js} +1 -1
  33. package/dist/assets/{graph-suelaXFh.js → graph-D11wiwHo.js} +1 -1
  34. package/dist/assets/highlighted-body-TPN3WLV5-Babpthg-.js +1 -0
  35. package/dist/assets/index-DFxzgWoO.js +2 -0
  36. package/dist/assets/index-YCFGDVKw.css +1 -0
  37. package/dist/assets/{infoDiagram-LFFYTUFH-pfD1FA3p.js → infoDiagram-LFFYTUFH-BmA7IpQG.js} +1 -1
  38. package/dist/assets/ishikawaDiagram-PHBUUO56-BEquZd3E.js +70 -0
  39. package/dist/assets/journeyDiagram-4ABVD52K-BfemGz7f.js +139 -0
  40. package/dist/assets/{kanban-definition-K7BYSVSG-FWinmur1.js → kanban-definition-K7BYSVSG-CWja3mln.js} +5 -5
  41. package/dist/assets/{layout-vcz43XvZ.js → layout-BLUNf-PJ.js} +1 -1
  42. package/dist/assets/{linear-le4gc0vx.js → linear-DukIV_Xv.js} +1 -1
  43. package/dist/assets/mermaid-O7DHMXV3-SgtM28qI.js +1038 -0
  44. package/dist/assets/mindmap-definition-YRQLILUH-4UjqXITU.js +68 -0
  45. package/dist/assets/{pieDiagram-SKSYHLDU-C7PKDh3b.js → pieDiagram-SKSYHLDU-8AxqJd0M.js} +2 -2
  46. package/dist/assets/quadrantDiagram-337W2JSQ-D60m8V8r.js +7 -0
  47. package/dist/assets/requirementDiagram-Z7DCOOCP-zqh9jBVf.js +73 -0
  48. package/dist/assets/{sankeyDiagram-WA2Y5GQK-4gulcOP4.js → sankeyDiagram-WA2Y5GQK-CDZILTLI.js} +3 -3
  49. package/dist/assets/sequenceDiagram-2WXFIKYE-7BReFd0L.js +145 -0
  50. package/dist/assets/{stateDiagram-RAJIS63D-CB4Vl7qM.js → stateDiagram-RAJIS63D-HPTVdIG4.js} +1 -1
  51. package/dist/assets/stateDiagram-v2-FVOUBMTO-DTUf5_gC.js +1 -0
  52. package/dist/assets/timeline-definition-YZTLITO2-CTVllFgr.js +61 -0
  53. package/dist/assets/{treemap-KZPCXAKY-DZSEE6Hz.js → treemap-KZPCXAKY-BtyxboJZ.js} +58 -58
  54. package/dist/assets/vendor-codemirror-Dz7_EqNA.js +39 -0
  55. package/dist/assets/vendor-react-Cpt6D04s.js +59 -0
  56. package/dist/assets/vendor-xterm-DfaPXD3y.js +66 -0
  57. package/dist/assets/{vennDiagram-LZ73GAT5-8E_G06fI.js → vennDiagram-LZ73GAT5-D96ZI6Mg.js} +4 -4
  58. package/dist/assets/xychartDiagram-JWTSCODW-eRk-39YO.js +7 -0
  59. package/dist/index.html +4 -4
  60. package/package.json +34 -33
  61. package/server/acp-runtime/client.js +82 -15
  62. package/server/acp-runtime/index.js +5 -16
  63. package/server/channels/runtime/AgentRuntimeAdapter.js +1 -10
  64. package/server/claude-sdk.js +1 -3
  65. package/server/cli.js +136 -0
  66. package/server/gemini-cli.js +1 -3
  67. package/server/index.js +86 -14
  68. package/server/openai-codex.js +1 -3
  69. package/server/opencode-cli.js +1 -3
  70. package/server/projects.js +128 -85
  71. package/server/routes/cc-connect.js +1131 -0
  72. package/server/routes/cli-auth.js +1 -73
  73. package/server/routes/commands.js +4 -9
  74. package/server/routes/projects.js +45 -24
  75. package/server/session-core/providerDiscovery.js +8 -3
  76. package/server/utils/ccConnectManager.js +390 -0
  77. package/server/utils/ccConnectState.js +575 -0
  78. package/server/utils/resolveCommandPath.js +71 -0
  79. package/server/utils/workspaceRoots.js +154 -0
  80. package/dist/assets/App-BWSqiXAT.js +0 -220
  81. package/dist/assets/App-DrlLKa8f.css +0 -1
  82. package/dist/assets/ReviewApp-nz3mbArg.js +0 -1
  83. package/dist/assets/architectureDiagram-2XIMDMQ5-CarjBOOv.js +0 -36
  84. package/dist/assets/c4Diagram-IC4MRINW-CGobwBIj.js +0 -10
  85. package/dist/assets/channel-DkFNxV_H.js +0 -1
  86. package/dist/assets/chunk-NQ4KR5QH-CMH6EDP2.js +0 -220
  87. package/dist/assets/chunk-WL4C6EOR-Dn7db_6t.js +0 -189
  88. package/dist/assets/classDiagram-VBA2DB6C-DtwCEe8S.js +0 -1
  89. package/dist/assets/classDiagram-v2-RAHNMMFH-DtwCEe8S.js +0 -1
  90. package/dist/assets/clone-C0lCEIEO.js +0 -1
  91. package/dist/assets/cose-bilkent-S5V4N54A-DD_nzqsz.js +0 -1
  92. package/dist/assets/cytoscape.esm-5J0xJHOV.js +0 -321
  93. package/dist/assets/diagram-E7M64L7V-TVdvHtGc.js +0 -24
  94. package/dist/assets/erDiagram-INFDFZHY-5Kw0bByo.js +0 -70
  95. package/dist/assets/ganttDiagram-A5KZAMGK-CsADFkcq.js +0 -292
  96. package/dist/assets/highlighted-body-OFNGDK62-CZrBMazC.js +0 -1
  97. package/dist/assets/index-B01NxbUv.css +0 -1
  98. package/dist/assets/index-DW5pGgQ_.js +0 -2
  99. package/dist/assets/ishikawaDiagram-PHBUUO56-ndm9snwO.js +0 -70
  100. package/dist/assets/journeyDiagram-4ABVD52K-HgF2t7z5.js +0 -139
  101. package/dist/assets/mermaid-GHXKKRXX-CK8m3lad.js +0 -870
  102. package/dist/assets/mindmap-definition-YRQLILUH-CNq9SKj4.js +0 -68
  103. package/dist/assets/quadrantDiagram-337W2JSQ-B7FnztNO.js +0 -7
  104. package/dist/assets/requirementDiagram-Z7DCOOCP-Bl_BM2Th.js +0 -73
  105. package/dist/assets/sequenceDiagram-2WXFIKYE-VEuJDwyJ.js +0 -145
  106. package/dist/assets/stateDiagram-v2-FVOUBMTO-C85ucl39.js +0 -1
  107. package/dist/assets/timeline-definition-YZTLITO2-BPGKhi7f.js +0 -61
  108. package/dist/assets/vendor-codemirror-CyOKkaQZ.js +0 -31
  109. package/dist/assets/vendor-react-CP4yFTs7.js +0 -8
  110. package/dist/assets/vendor-xterm-DfcmCpbH.js +0 -66
  111. package/dist/assets/xychartDiagram-JWTSCODW-CbBk50-O.js +0 -7
  112. package/server/acp-runtime/client.test.js +0 -688
  113. package/server/acp-runtime/session-store.test.js +0 -89
  114. package/server/cli.test.js +0 -76
  115. package/server/external-agent/service.test.js +0 -53
  116. package/server/external-agent/ws.test.js +0 -289
  117. package/shared/conversationEvents.test.js +0 -403
@@ -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-03-22T04:01:13.470Z</footer>
306
+ <footer>Generated at: 2026-04-03T03:46:20.166Z</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 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 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` 枚举在线客户端。\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.6\n- 更新日期:2026-03-21\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 \"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```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 \"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#### 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#### 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. Editor 子命令\n\n所有 editor 子命令都默认输出 JSON,并通过 `/api/agent/ws` 与在线 frontend-page 通信。\n\n#### 2.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```json\n{\n \"ok\": true,\n \"requestId\": \"editor_001\",\n \"channel\": \"project-a\",\n \"targetClientId\": \"figma-123\",\n \"data\": {}\n}\n```\n\n统一失败包型:\n\n```json\n{\n \"ok\": false,\n \"requestId\": \"editor_001\",\n \"channel\": \"project-a\",\n \"targetClientId\": \"figma-123\",\n \"error\": {\n \"code\": \"FRONTEND_NOT_ONLINE\",\n \"message\": \"Target frontend page is not connected\"\n }\n}\n```\n\n失败时 CLI 以非 0 退出码结束。\n\n### 3. 推荐顺序:先列客户端\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### 4. 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### 5. 截图与上下文图片\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### 6. 编辑态设置\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`\n- 可选通过 `--provider` / `--session-id` / `--task-request-id` 传递任务追踪信息\n\n### 7. 常见失败原因\n\n#### 7.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: 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` 枚举在线客户端。\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 \"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```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 \"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#### 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#### 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`\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";
314
314
  const root = document.getElementById('markdown-root');
315
315
 
316
316
  function scrollToHashAnchor() {