cli-claw-kit 0.0.1

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 (295) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +245 -0
  3. package/config/default-groups.json +1 -0
  4. package/config/global-agents-md.template.md +37 -0
  5. package/config/mount-allowlist.json +11 -0
  6. package/container/Dockerfile +160 -0
  7. package/container/agent-runner/dist/.tsbuildinfo +1 -0
  8. package/container/agent-runner/dist/agent-definitions.js +22 -0
  9. package/container/agent-runner/dist/channel-prefixes.js +16 -0
  10. package/container/agent-runner/dist/codex-config.js +29 -0
  11. package/container/agent-runner/dist/image-detector.js +96 -0
  12. package/container/agent-runner/dist/index.js +2587 -0
  13. package/container/agent-runner/dist/mcp-tools.js +1076 -0
  14. package/container/agent-runner/dist/stream-event.types.js +5 -0
  15. package/container/agent-runner/dist/stream-processor.js +867 -0
  16. package/container/agent-runner/dist/types.js +6 -0
  17. package/container/agent-runner/dist/utils.js +115 -0
  18. package/container/agent-runner/package.json +36 -0
  19. package/container/agent-runner/prompts/security-rules.md +31 -0
  20. package/container/agent-runner/src/agent-definitions.ts +27 -0
  21. package/container/agent-runner/src/channel-prefixes.ts +16 -0
  22. package/container/agent-runner/src/codex-config.ts +40 -0
  23. package/container/agent-runner/src/image-detector.ts +116 -0
  24. package/container/agent-runner/src/index.ts +3107 -0
  25. package/container/agent-runner/src/mcp-tools.ts +1295 -0
  26. package/container/agent-runner/src/stream-event.types.ts +10 -0
  27. package/container/agent-runner/src/stream-processor.ts +932 -0
  28. package/container/agent-runner/src/types.ts +75 -0
  29. package/container/agent-runner/src/utils.ts +114 -0
  30. package/container/agent-runner/tsconfig.json +17 -0
  31. package/container/build.sh +28 -0
  32. package/container/entrypoint.sh +64 -0
  33. package/container/skills/agent-browser/SKILL.md +159 -0
  34. package/container/skills/install-skill/SKILL.md +64 -0
  35. package/container/skills/post-test-cleanup/SKILL.md +121 -0
  36. package/dist/.tsbuildinfo +1 -0
  37. package/dist/agent-output-parser.js +459 -0
  38. package/dist/app-root.js +52 -0
  39. package/dist/assistant-meta-footer.js +1 -0
  40. package/dist/auth.js +91 -0
  41. package/dist/billing.js +694 -0
  42. package/dist/channel-prefixes.js +16 -0
  43. package/dist/cli.js +86 -0
  44. package/dist/commands.js +79 -0
  45. package/dist/config.js +120 -0
  46. package/dist/container-runner.js +981 -0
  47. package/dist/daily-summary.js +210 -0
  48. package/dist/db.js +3683 -0
  49. package/dist/dingtalk.js +1347 -0
  50. package/dist/feishu-markdown-style.js +97 -0
  51. package/dist/feishu-streaming-card.js +1875 -0
  52. package/dist/feishu.js +1628 -0
  53. package/dist/file-manager.js +270 -0
  54. package/dist/group-queue.js +1070 -0
  55. package/dist/group-runtime.js +35 -0
  56. package/dist/host-workspace-cwd.js +85 -0
  57. package/dist/im-channel.js +384 -0
  58. package/dist/im-command-utils.js +142 -0
  59. package/dist/im-downloader.js +45 -0
  60. package/dist/im-manager.js +527 -0
  61. package/dist/im-utils.js +53 -0
  62. package/dist/image-detector.js +96 -0
  63. package/dist/index.js +5828 -0
  64. package/dist/logger.js +22 -0
  65. package/dist/mcp-utils.js +66 -0
  66. package/dist/message-attachments.js +69 -0
  67. package/dist/message-notifier.js +36 -0
  68. package/dist/middleware/auth.js +85 -0
  69. package/dist/mount-security.js +315 -0
  70. package/dist/permissions.js +67 -0
  71. package/dist/project-memory.js +6 -0
  72. package/dist/provider-pool.js +189 -0
  73. package/dist/qq.js +826 -0
  74. package/dist/reset-admin.js +42 -0
  75. package/dist/routes/admin.js +543 -0
  76. package/dist/routes/agent-definitions.js +241 -0
  77. package/dist/routes/agents.js +533 -0
  78. package/dist/routes/auth.js +675 -0
  79. package/dist/routes/billing.js +490 -0
  80. package/dist/routes/browse.js +210 -0
  81. package/dist/routes/bug-report.js +387 -0
  82. package/dist/routes/config.js +1868 -0
  83. package/dist/routes/files.js +671 -0
  84. package/dist/routes/groups.js +1367 -0
  85. package/dist/routes/mcp-servers.js +320 -0
  86. package/dist/routes/memory.js +523 -0
  87. package/dist/routes/monitor.js +307 -0
  88. package/dist/routes/skills.js +777 -0
  89. package/dist/routes/tasks.js +509 -0
  90. package/dist/routes/usage.js +64 -0
  91. package/dist/routes/workspace-config.js +458 -0
  92. package/dist/runtime-build.js +112 -0
  93. package/dist/runtime-command-handler.js +189 -0
  94. package/dist/runtime-command-registry.js +1 -0
  95. package/dist/runtime-config.js +1777 -0
  96. package/dist/runtime-identity.js +52 -0
  97. package/dist/schemas.js +590 -0
  98. package/dist/script-runner.js +64 -0
  99. package/dist/sdk-query.js +82 -0
  100. package/dist/skill-utils.js +145 -0
  101. package/dist/sqlite-compat.js +19 -0
  102. package/dist/stream-event.types.js +5 -0
  103. package/dist/streaming-runtime-meta.js +29 -0
  104. package/dist/task-scheduler.js +695 -0
  105. package/dist/task-utils.js +13 -0
  106. package/dist/telegram-pairing.js +59 -0
  107. package/dist/telegram.js +897 -0
  108. package/dist/terminal-manager.js +307 -0
  109. package/dist/tool-step-display.js +1 -0
  110. package/dist/types.js +1 -0
  111. package/dist/utils.js +85 -0
  112. package/dist/web-context.js +161 -0
  113. package/dist/web.js +1377 -0
  114. package/dist/wechat-crypto.js +182 -0
  115. package/dist/wechat.js +589 -0
  116. package/dist/workspace-runtime-reset.js +35 -0
  117. package/package.json +107 -0
  118. package/shared/assistant-meta-footer.ts +127 -0
  119. package/shared/channel-prefixes.ts +16 -0
  120. package/shared/dist/assistant-meta-footer.d.ts +29 -0
  121. package/shared/dist/assistant-meta-footer.js +85 -0
  122. package/shared/dist/channel-prefixes.d.ts +4 -0
  123. package/shared/dist/channel-prefixes.js +16 -0
  124. package/shared/dist/image-detector.d.ts +20 -0
  125. package/shared/dist/image-detector.js +96 -0
  126. package/shared/dist/runtime-command-registry.d.ts +38 -0
  127. package/shared/dist/runtime-command-registry.js +185 -0
  128. package/shared/dist/stream-event.d.ts +65 -0
  129. package/shared/dist/stream-event.js +8 -0
  130. package/shared/dist/tool-step-display.d.ts +4 -0
  131. package/shared/dist/tool-step-display.js +11 -0
  132. package/shared/image-detector.ts +116 -0
  133. package/shared/runtime-command-registry.ts +252 -0
  134. package/shared/stream-event.ts +67 -0
  135. package/shared/tool-step-display.ts +21 -0
  136. package/shared/tsconfig.json +24 -0
  137. package/web/dist/assets/BillingPage-B1wBR_o-.js +52 -0
  138. package/web/dist/assets/ChatPage-6GBZ9nXN.css +32 -0
  139. package/web/dist/assets/ChatPage-BOJcXtaj.js +161 -0
  140. package/web/dist/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
  141. package/web/dist/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
  142. package/web/dist/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
  143. package/web/dist/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
  144. package/web/dist/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
  145. package/web/dist/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
  146. package/web/dist/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
  147. package/web/dist/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
  148. package/web/dist/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
  149. package/web/dist/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
  150. package/web/dist/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
  151. package/web/dist/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
  152. package/web/dist/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
  153. package/web/dist/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
  154. package/web/dist/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
  155. package/web/dist/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
  156. package/web/dist/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
  157. package/web/dist/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
  158. package/web/dist/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
  159. package/web/dist/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
  160. package/web/dist/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
  161. package/web/dist/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
  162. package/web/dist/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
  163. package/web/dist/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
  164. package/web/dist/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
  165. package/web/dist/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
  166. package/web/dist/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
  167. package/web/dist/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
  168. package/web/dist/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
  169. package/web/dist/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
  170. package/web/dist/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
  171. package/web/dist/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
  172. package/web/dist/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
  173. package/web/dist/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
  174. package/web/dist/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
  175. package/web/dist/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
  176. package/web/dist/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
  177. package/web/dist/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
  178. package/web/dist/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
  179. package/web/dist/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
  180. package/web/dist/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
  181. package/web/dist/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
  182. package/web/dist/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
  183. package/web/dist/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
  184. package/web/dist/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
  185. package/web/dist/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
  186. package/web/dist/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
  187. package/web/dist/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
  188. package/web/dist/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
  189. package/web/dist/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
  190. package/web/dist/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
  191. package/web/dist/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
  192. package/web/dist/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
  193. package/web/dist/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
  194. package/web/dist/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
  195. package/web/dist/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
  196. package/web/dist/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
  197. package/web/dist/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
  198. package/web/dist/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
  199. package/web/dist/assets/SettingsPage-DoY7FoZ_.js +153 -0
  200. package/web/dist/assets/ShareImageDialog-C1ga8b7l.js +22 -0
  201. package/web/dist/assets/TasksPage-CRivnNsx.js +14 -0
  202. package/web/dist/assets/_basePickBy-Bf-bSoS9.js +1 -0
  203. package/web/dist/assets/_baseUniq-zAOaCuKw.js +1 -0
  204. package/web/dist/assets/arc-Dm9mVQ9U.js +1 -0
  205. package/web/dist/assets/architectureDiagram-2XIMDMQ5-BLmzX1wr.js +36 -0
  206. package/web/dist/assets/band-CquvqAHh.js +1 -0
  207. package/web/dist/assets/blockDiagram-WCTKOSBZ-B9pcqm3j.js +132 -0
  208. package/web/dist/assets/c4Diagram-IC4MRINW-Cytx1q3b.js +10 -0
  209. package/web/dist/assets/channel-BOVj73LR.js +1 -0
  210. package/web/dist/assets/channel-meta-CQD0Pei-.js +41 -0
  211. package/web/dist/assets/chunk-4BX2VUAB-0ToDr6RE.js +1 -0
  212. package/web/dist/assets/chunk-55IACEB6-DQDjnXfS.js +1 -0
  213. package/web/dist/assets/chunk-FMBD7UC4-Di8ABm6c.js +15 -0
  214. package/web/dist/assets/chunk-JSJVCQXG-BZQN6rnX.js +1 -0
  215. package/web/dist/assets/chunk-KX2RTZJC-zBbcpaN_.js +1 -0
  216. package/web/dist/assets/chunk-NQ4KR5QH-BCrLoU88.js +220 -0
  217. package/web/dist/assets/chunk-QZHKN3VN-Bqk8juan.js +1 -0
  218. package/web/dist/assets/chunk-WL4C6EOR-D2YX-MHY.js +189 -0
  219. package/web/dist/assets/classDiagram-VBA2DB6C-DUUoMyaK.js +1 -0
  220. package/web/dist/assets/classDiagram-v2-RAHNMMFH-DUUoMyaK.js +1 -0
  221. package/web/dist/assets/clone-BmaCesfa.js +1 -0
  222. package/web/dist/assets/cose-bilkent-S5V4N54A-CTsv6qQA.js +1 -0
  223. package/web/dist/assets/cytoscape.esm-BQaXIfA_.js +331 -0
  224. package/web/dist/assets/dagre-KLK3FWXG-Ci4Jh9nu.js +4 -0
  225. package/web/dist/assets/defaultLocale-DX6XiGOO.js +1 -0
  226. package/web/dist/assets/diagram-E7M64L7V-BFRnfTI2.js +24 -0
  227. package/web/dist/assets/diagram-IFDJBPK2-B7Zhnp0b.js +43 -0
  228. package/web/dist/assets/diagram-P4PSJMXO-BVyP7nwq.js +24 -0
  229. package/web/dist/assets/erDiagram-INFDFZHY-NorKdTOF.js +70 -0
  230. package/web/dist/assets/error-CGD5mp5f.js +1 -0
  231. package/web/dist/assets/flowDiagram-PKNHOUZH-Ch97nABF.js +162 -0
  232. package/web/dist/assets/ganttDiagram-A5KZAMGK-BQ2pLWsy.js +292 -0
  233. package/web/dist/assets/gitGraphDiagram-K3NZZRJ6-bcvnBsD2.js +65 -0
  234. package/web/dist/assets/graph-CeAEckur.js +1 -0
  235. package/web/dist/assets/index-CPnL1_qC.js +768 -0
  236. package/web/dist/assets/index-DVevCbcO.css +10 -0
  237. package/web/dist/assets/infoDiagram-LFFYTUFH-CcsrFdj-.js +2 -0
  238. package/web/dist/assets/init-Dmth1JHB.js +1 -0
  239. package/web/dist/assets/ishikawaDiagram-PHBUUO56-1upyMfHN.js +70 -0
  240. package/web/dist/assets/journeyDiagram-4ABVD52K-CKUi-V0c.js +139 -0
  241. package/web/dist/assets/kanban-definition-K7BYSVSG-DOnQwXfL.js +89 -0
  242. package/web/dist/assets/layout-BmMMqTnJ.js +1 -0
  243. package/web/dist/assets/linear-DiaJloY5.js +1 -0
  244. package/web/dist/assets/mermaid.core-BWLV1B2v.js +254 -0
  245. package/web/dist/assets/mindmap-definition-YRQLILUH-BeAKHVWP.js +68 -0
  246. package/web/dist/assets/ordinal-DILIJJjt.js +1 -0
  247. package/web/dist/assets/pieDiagram-SKSYHLDU-DfiMSfWo.js +30 -0
  248. package/web/dist/assets/quadrantDiagram-337W2JSQ-wZxZOJxd.js +7 -0
  249. package/web/dist/assets/requirementDiagram-Z7DCOOCP-BK4HHm17.js +73 -0
  250. package/web/dist/assets/sankeyDiagram-WA2Y5GQK-BX6t2avX.js +10 -0
  251. package/web/dist/assets/sequenceDiagram-2WXFIKYE-BPQlkbAa.js +145 -0
  252. package/web/dist/assets/sheet-rI0FfB1g.js +6 -0
  253. package/web/dist/assets/sliders-horizontal-CuijWFNK.js +6 -0
  254. package/web/dist/assets/sparkles-BsMYXJoT.js +11 -0
  255. package/web/dist/assets/square-0CqMX1Q3.js +11 -0
  256. package/web/dist/assets/stateDiagram-RAJIS63D-DxkV0Vwd.js +1 -0
  257. package/web/dist/assets/stateDiagram-v2-FVOUBMTO-qLYoiOPe.js +1 -0
  258. package/web/dist/assets/step-D51IIHGA.js +1 -0
  259. package/web/dist/assets/tasks-D8JjBTwx.js +1 -0
  260. package/web/dist/assets/time-O8zIGux3.js +1 -0
  261. package/web/dist/assets/timeline-definition-YZTLITO2-kNp1DyFc.js +61 -0
  262. package/web/dist/assets/treemap-KZPCXAKY-CkrClVhk.js +162 -0
  263. package/web/dist/assets/utils-KGAn0XTg.js +11 -0
  264. package/web/dist/assets/vennDiagram-LZ73GAT5-CgdzEZz4.js +34 -0
  265. package/web/dist/assets/xychartDiagram-JWTSCODW-DfYGPfNB.js +7 -0
  266. package/web/dist/assets/zap-_hKJYy7J.js +6 -0
  267. package/web/dist/favicon.svg +332 -0
  268. package/web/dist/fonts/AlibabaPuHuiTi-3-55-Regular.woff2 +0 -0
  269. package/web/dist/fonts/AlibabaPuHuiTi-3-65-Medium.woff2 +0 -0
  270. package/web/dist/fonts/AlibabaPuHuiTi-3-75-SemiBold.woff2 +0 -0
  271. package/web/dist/fonts/DMSans-latin-ext.woff2 +0 -0
  272. package/web/dist/fonts/DMSans-latin.woff2 +0 -0
  273. package/web/dist/icons/README.md +20 -0
  274. package/web/dist/icons/apple-touch-icon-180.png +0 -0
  275. package/web/dist/icons/icon-128.png +0 -0
  276. package/web/dist/icons/icon-144.png +0 -0
  277. package/web/dist/icons/icon-152.png +0 -0
  278. package/web/dist/icons/icon-192.png +0 -0
  279. package/web/dist/icons/icon-192.svg +332 -0
  280. package/web/dist/icons/icon-384.png +0 -0
  281. package/web/dist/icons/icon-48.png +0 -0
  282. package/web/dist/icons/icon-512-maskable.png +0 -0
  283. package/web/dist/icons/icon-512.png +0 -0
  284. package/web/dist/icons/icon-512.svg +332 -0
  285. package/web/dist/icons/icon-72.png +0 -0
  286. package/web/dist/icons/icon-96.png +0 -0
  287. package/web/dist/icons/loading-logo.svg +332 -0
  288. package/web/dist/icons/logo-1024.png +0 -0
  289. package/web/dist/icons/logo-icon.svg +332 -0
  290. package/web/dist/icons/logo-text.svg +332 -0
  291. package/web/dist/index.html +30 -0
  292. package/web/dist/manifest.webmanifest +1 -0
  293. package/web/dist/registerSW.js +1 -0
  294. package/web/dist/sw.js +1 -0
  295. package/web/dist/workbox-08d6266a.js +1 -0
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Shared types for cli-claw Agent Runner.
3
+ *
4
+ * These types are used across index.ts, stream-processor.ts, and mcp-tools.ts.
5
+ */
6
+
7
+ // Streaming event types (canonical source: shared/stream-event.ts)
8
+ export type { StreamEventType, StreamEvent } from './stream-event.types.js';
9
+ import type { StreamEvent, StreamRuntimeIdentity } from './stream-event.types.js';
10
+
11
+ export interface ContainerInput {
12
+ prompt: string;
13
+ sessionId?: string;
14
+ turnId?: string;
15
+ groupFolder: string;
16
+ chatJid: string;
17
+ agentType?: 'claude' | 'codex';
18
+ model?: string | null;
19
+ reasoningEffort?: string | null;
20
+ /** @deprecated Use isHome + isAdminHome instead. Kept for backward compatibility with older host processes. */
21
+ isMain?: boolean;
22
+ /** Whether this is the user's home container (admin or member). */
23
+ isHome?: boolean;
24
+ /** Whether this is the admin's home container (full privileges). */
25
+ isAdminHome?: boolean;
26
+ isScheduledTask?: boolean;
27
+ images?: Array<{ data: string; mimeType?: string }>;
28
+ agentId?: string;
29
+ agentName?: string;
30
+ }
31
+
32
+ export interface ContainerOutput {
33
+ status: 'success' | 'error' | 'stream' | 'closed';
34
+ result: string | null;
35
+ newSessionId?: string;
36
+ error?: string;
37
+ alreadyStreamedError?: boolean;
38
+ runtimeIdentity?: StreamRuntimeIdentity | null;
39
+ streamEvent?: StreamEvent;
40
+ turnId?: string;
41
+ sessionId?: string;
42
+ sdkMessageUuid?: string;
43
+ sourceKind?: 'sdk_final' | 'sdk_send_message' | 'interrupt_partial' | 'overflow_partial' | 'compact_partial' | 'legacy' | 'auto_continue';
44
+ finalizationReason?: 'completed' | 'interrupted' | 'error';
45
+ }
46
+
47
+ export interface SessionEntry {
48
+ sessionId: string;
49
+ fullPath: string;
50
+ summary: string;
51
+ firstPrompt: string;
52
+ }
53
+
54
+ export interface SessionsIndex {
55
+ entries: SessionEntry[];
56
+ }
57
+
58
+ export type ImageMediaType = 'image/jpeg' | 'image/png' | 'image/gif' | 'image/webp';
59
+
60
+ export interface SDKUserMessage {
61
+ type: 'user';
62
+ message: {
63
+ role: 'user';
64
+ content:
65
+ | string
66
+ | Array<{ type: 'text'; text: string } | { type: 'image'; source: { type: 'base64'; media_type: ImageMediaType; data: string } }>;
67
+ };
68
+ parent_tool_use_id: null;
69
+ session_id: string;
70
+ }
71
+
72
+ export interface ParsedMessage {
73
+ role: 'user' | 'assistant';
74
+ content: string;
75
+ }
@@ -0,0 +1,114 @@
1
+ /**
2
+ * Utility functions for cli-claw Agent Runner.
3
+ *
4
+ * Pure utility functions with no side effects or state dependencies.
5
+ */
6
+
7
+ /**
8
+ * Shorten a string to maxLen, appending "..." if truncated.
9
+ */
10
+ export function shorten(input: string, maxLen = 180): string {
11
+ if (input.length <= maxLen) return input;
12
+ return `${input.slice(0, maxLen)}...`;
13
+ }
14
+
15
+ /**
16
+ * Recursively redact sensitive fields (tokens, passwords, API keys, etc.)
17
+ * from an object. Limits recursion depth to 3 levels.
18
+ */
19
+ export function redactSensitive(input: unknown, depth = 0): unknown {
20
+ if (depth > 3) return '[truncated]';
21
+ if (input == null) return input;
22
+ if (typeof input === 'string' || typeof input === 'number' || typeof input === 'boolean') {
23
+ return input;
24
+ }
25
+ if (Array.isArray(input)) {
26
+ return input.slice(0, 10).map((item) => redactSensitive(item, depth + 1));
27
+ }
28
+ if (typeof input === 'object') {
29
+ const obj = input as Record<string, unknown>;
30
+ const out: Record<string, unknown> = {};
31
+ for (const [k, v] of Object.entries(obj)) {
32
+ if (/(token|password|secret|api[_-]?key|authorization|cookie)/iu.test(k)) {
33
+ out[k] = '[REDACTED]';
34
+ } else {
35
+ out[k] = redactSensitive(v, depth + 1);
36
+ }
37
+ }
38
+ return out;
39
+ }
40
+ return '[unsupported]';
41
+ }
42
+
43
+ /**
44
+ * Summarize tool input for display in stream events.
45
+ * Extracts key fields (command, query, path, etc.) or serializes the object.
46
+ */
47
+ export function summarizeToolInput(input: unknown): string | undefined {
48
+ if (input == null) return undefined;
49
+
50
+ if (typeof input === 'string') {
51
+ return shorten(input.trim());
52
+ }
53
+
54
+ if (typeof input === 'object') {
55
+ const obj = input as Record<string, unknown>;
56
+ const keyCandidates = ['command', 'query', 'path', 'pattern', 'prompt', 'url', 'name'];
57
+ for (const key of keyCandidates) {
58
+ const value = obj[key];
59
+ if (typeof value === 'string' && value.trim()) {
60
+ return `${key}: ${shorten(value.trim())}`;
61
+ }
62
+ }
63
+ try {
64
+ const json = JSON.stringify(redactSensitive(obj));
65
+ // Skip empty or trivial objects (e.g. {} at content_block_start)
66
+ if (!json || json === '{}' || json === '[]') return undefined;
67
+ return shorten(json);
68
+ } catch {
69
+ return undefined;
70
+ }
71
+ }
72
+
73
+ return undefined;
74
+ }
75
+
76
+ /**
77
+ * Extract a skill name from Skill tool input.
78
+ * Tries skillName, skill, name, command fields, then regex-matches leading slashes.
79
+ */
80
+ export function extractSkillName(toolName: unknown, input: unknown): string | undefined {
81
+ if (toolName !== 'Skill') return undefined;
82
+ if (!input || typeof input !== 'object') return undefined;
83
+ const obj = input as Record<string, unknown>;
84
+ const raw =
85
+ (typeof obj.skillName === 'string' && obj.skillName) ||
86
+ (typeof obj.skill === 'string' && obj.skill) ||
87
+ (typeof obj.name === 'string' && obj.name) ||
88
+ (typeof obj.command === 'string' && obj.command) ||
89
+ '';
90
+ if (!raw) return undefined;
91
+ const matched = raw.match(/\/([A-Za-z0-9._-]+)/);
92
+ if (matched && matched[1]) return matched[1];
93
+ return raw.replace(/^\/+/, '').trim() || undefined;
94
+ }
95
+
96
+ /**
97
+ * Sanitize a string for use as a filename.
98
+ * Lowercases, replaces non-alphanumeric characters with hyphens, trims, and limits length.
99
+ */
100
+ export function sanitizeFilename(summary: string): string {
101
+ return summary
102
+ .toLowerCase()
103
+ .replace(/[^\p{L}\p{N}]+/gu, '-')
104
+ .replace(/^-+|-+$/g, '')
105
+ .slice(0, 50);
106
+ }
107
+
108
+ /**
109
+ * Generate a fallback conversation archive filename based on current time.
110
+ */
111
+ export function generateFallbackName(): string {
112
+ const time = new Date();
113
+ return `conversation-${time.getHours().toString().padStart(2, '0')}${time.getMinutes().toString().padStart(2, '0')}`;
114
+ }
@@ -0,0 +1,17 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "lib": ["ES2022"],
5
+ "module": "NodeNext",
6
+ "moduleResolution": "NodeNext",
7
+ "outDir": "./dist",
8
+ "rootDir": "./src",
9
+ "strict": true,
10
+ "esModuleInterop": true,
11
+ "skipLibCheck": true,
12
+ "incremental": true,
13
+ "tsBuildInfoFile": "./dist/.tsbuildinfo"
14
+ },
15
+ "include": ["src/**/*"],
16
+ "exclude": ["node_modules", "dist"]
17
+ }
@@ -0,0 +1,28 @@
1
+ #!/bin/bash
2
+ # Build the cli-claw agent container image
3
+
4
+ set -e
5
+
6
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
7
+ ROOT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
8
+
9
+ IMAGE_NAME="cli-claw-agent"
10
+ TAG="${1:-latest}"
11
+
12
+ echo "Building cli-claw agent container image..."
13
+ echo "Image: ${IMAGE_NAME}:${TAG}"
14
+
15
+ # Build with Docker (CACHEBUST ensures claude-code is always latest)
16
+ # --progress=plain ensures clean line-based output for piped log capture (WebSocket streaming)
17
+ docker build --progress=plain --build-arg CACHEBUST="$(date +%s)" -f "$SCRIPT_DIR/Dockerfile" -t "${IMAGE_NAME}:${TAG}" "$ROOT_DIR"
18
+
19
+ echo ""
20
+ echo "Build complete!"
21
+ echo "Image: ${IMAGE_NAME}:${TAG}"
22
+
23
+ # Touch sentinel so Makefile can detect stale image
24
+ touch "$ROOT_DIR/.docker-build-sentinel"
25
+
26
+ echo ""
27
+ echo "Test with:"
28
+ echo " printf '%s' '{\"prompt\":\"What is 2+2?\",\"groupFolder\":\"test\",\"chatJid\":\"test@g.us\",\"isMain\":false}' | docker run -i ${IMAGE_NAME}:${TAG}"
@@ -0,0 +1,64 @@
1
+ #!/bin/bash
2
+ set -e
3
+
4
+ # Set permissive umask so files created by the container (node user, uid 1000)
5
+ # are writable by the host backend (agent user, uid 1002).
6
+ # Without this, the host cannot delete/modify files created by the container.
7
+ umask 0000
8
+
9
+ # Fix ownership on mounted volumes.
10
+ # Host uid may differ from container node user (uid 1000), especially in
11
+ # rootless podman where uid remapping causes EACCES on bind mounts.
12
+ # Running as root here so chown works regardless of host uid.
13
+ chown -R node:node /home/node/.claude 2>/dev/null || true
14
+ chown -R node:node /workspace/group /workspace/global /workspace/memory /workspace/ipc 2>/dev/null || true
15
+
16
+ # Source environment variables from mounted env file
17
+ if [ -f /workspace/env-dir/env ]; then
18
+ set -a
19
+ source /workspace/env-dir/env
20
+ set +a
21
+ fi
22
+
23
+ # Discover and link skills (builtin → project → user, higher priority overwrites)
24
+ # Only remove entries that conflict with mounted skills (non-symlink with same name),
25
+ # preserving any skills the agent created directly in .claude/skills/.
26
+ mkdir -p /home/node/.claude/skills
27
+ for dir in /opt/builtin-skills /workspace/project-skills /workspace/user-skills; do
28
+ if [ -d "$dir" ]; then
29
+ for skill in "$dir"/*/; do
30
+ if [ -d "$skill" ]; then
31
+ name=$(basename "$skill")
32
+ target="/home/node/.claude/skills/$name"
33
+ # Remove conflicting non-symlink entry (e.g. real directory from a failed agent edit)
34
+ if [ -e "$target" ] && [ ! -L "$target" ]; then
35
+ rm -rf "$target" 2>/dev/null || true
36
+ fi
37
+ ln -sfn "$skill" "$target" 2>/dev/null || true
38
+ fi
39
+ done
40
+ fi
41
+ done
42
+ chown -R node:node /home/node/.claude/skills 2>/dev/null || true
43
+
44
+ # Compile TypeScript (agent-runner source may be hot-mounted from host)
45
+ cd /app && npx tsc --outDir /tmp/dist 2>&1 >&2
46
+ ln -s /app/node_modules /tmp/dist/node_modules
47
+ ln -s /app/prompts /tmp/prompts
48
+ chmod -R a-w /tmp/dist
49
+
50
+ # Buffer stdin to file (container requires EOF to flush stdin pipe)
51
+ cat > /tmp/input.json
52
+ chmod 644 /tmp/input.json
53
+
54
+ # Fix permissions on exit: Claude Code creates some files with mode 0600
55
+ # (e.g. settings.json), which the host backend (agent user) cannot read.
56
+ # The trap runs as root after the node process exits.
57
+ cleanup() {
58
+ chmod -R a+rwX /home/node/.claude 2>/dev/null || true
59
+ chmod -R a+rwX /workspace/group 2>/dev/null || true
60
+ }
61
+ trap cleanup EXIT
62
+
63
+ # Drop privileges and execute agent-runner as node user
64
+ runuser -u node -- node /tmp/dist/index.js < /tmp/input.json
@@ -0,0 +1,159 @@
1
+ ---
2
+ name: agent-browser
3
+ description: Browse the web for any task — research topics, read articles, interact with web apps, fill forms, take screenshots, extract data, and test web pages. Use whenever a browser would be useful, not just when the user explicitly asks.
4
+ allowed-tools: Bash(agent-browser:*)
5
+ ---
6
+
7
+ # Browser Automation with agent-browser
8
+
9
+ ## Quick start
10
+
11
+ ```bash
12
+ agent-browser open <url> # Navigate to page
13
+ agent-browser snapshot -i # Get interactive elements with refs
14
+ agent-browser click @e1 # Click element by ref
15
+ agent-browser fill @e2 "text" # Fill input by ref
16
+ agent-browser close # Close browser
17
+ ```
18
+
19
+ ## Core workflow
20
+
21
+ 1. Navigate: `agent-browser open <url>`
22
+ 2. Snapshot: `agent-browser snapshot -i` (returns elements with refs like `@e1`, `@e2`)
23
+ 3. Interact using refs from the snapshot
24
+ 4. Re-snapshot after navigation or significant DOM changes
25
+
26
+ ## Commands
27
+
28
+ ### Navigation
29
+
30
+ ```bash
31
+ agent-browser open <url> # Navigate to URL
32
+ agent-browser back # Go back
33
+ agent-browser forward # Go forward
34
+ agent-browser reload # Reload page
35
+ agent-browser close # Close browser
36
+ ```
37
+
38
+ ### Snapshot (page analysis)
39
+
40
+ ```bash
41
+ agent-browser snapshot # Full accessibility tree
42
+ agent-browser snapshot -i # Interactive elements only (recommended)
43
+ agent-browser snapshot -c # Compact output
44
+ agent-browser snapshot -d 3 # Limit depth to 3
45
+ agent-browser snapshot -s "#main" # Scope to CSS selector
46
+ ```
47
+
48
+ ### Interactions (use @refs from snapshot)
49
+
50
+ ```bash
51
+ agent-browser click @e1 # Click
52
+ agent-browser dblclick @e1 # Double-click
53
+ agent-browser fill @e2 "text" # Clear and type
54
+ agent-browser type @e2 "text" # Type without clearing
55
+ agent-browser press Enter # Press key
56
+ agent-browser hover @e1 # Hover
57
+ agent-browser check @e1 # Check checkbox
58
+ agent-browser uncheck @e1 # Uncheck checkbox
59
+ agent-browser select @e1 "value" # Select dropdown option
60
+ agent-browser scroll down 500 # Scroll page
61
+ agent-browser upload @e1 file.pdf # Upload files
62
+ ```
63
+
64
+ ### Get information
65
+
66
+ ```bash
67
+ agent-browser get text @e1 # Get element text
68
+ agent-browser get html @e1 # Get innerHTML
69
+ agent-browser get value @e1 # Get input value
70
+ agent-browser get attr @e1 href # Get attribute
71
+ agent-browser get title # Get page title
72
+ agent-browser get url # Get current URL
73
+ agent-browser get count ".item" # Count matching elements
74
+ ```
75
+
76
+ ### Screenshots & PDF
77
+
78
+ ```bash
79
+ agent-browser screenshot # Save to temp directory
80
+ agent-browser screenshot path.png # Save to specific path
81
+ agent-browser screenshot --full # Full page
82
+ agent-browser pdf output.pdf # Save as PDF
83
+ ```
84
+
85
+ ### Wait
86
+
87
+ ```bash
88
+ agent-browser wait @e1 # Wait for element
89
+ agent-browser wait 2000 # Wait milliseconds
90
+ agent-browser wait --text "Success" # Wait for text
91
+ agent-browser wait --url "**/dashboard" # Wait for URL pattern
92
+ agent-browser wait --load networkidle # Wait for network idle
93
+ ```
94
+
95
+ ### Semantic locators (alternative to refs)
96
+
97
+ ```bash
98
+ agent-browser find role button click --name "Submit"
99
+ agent-browser find text "Sign In" click
100
+ agent-browser find label "Email" fill "user@test.com"
101
+ agent-browser find placeholder "Search" type "query"
102
+ ```
103
+
104
+ ### Authentication with saved state
105
+
106
+ ```bash
107
+ # Login once
108
+ agent-browser open https://app.example.com/login
109
+ agent-browser snapshot -i
110
+ agent-browser fill @e1 "username"
111
+ agent-browser fill @e2 "password"
112
+ agent-browser click @e3
113
+ agent-browser wait --url "**/dashboard"
114
+ agent-browser state save auth.json
115
+
116
+ # Later: load saved state
117
+ agent-browser state load auth.json
118
+ agent-browser open https://app.example.com/dashboard
119
+ ```
120
+
121
+ ### Cookies & Storage
122
+
123
+ ```bash
124
+ agent-browser cookies # Get all cookies
125
+ agent-browser cookies set name value # Set cookie
126
+ agent-browser cookies clear # Clear cookies
127
+ agent-browser storage local # Get localStorage
128
+ agent-browser storage local set k v # Set value
129
+ ```
130
+
131
+ ### JavaScript
132
+
133
+ ```bash
134
+ agent-browser eval "document.title" # Run JavaScript
135
+ ```
136
+
137
+ ## Example: Form submission
138
+
139
+ ```bash
140
+ agent-browser open https://example.com/form
141
+ agent-browser snapshot -i
142
+ # Output shows: textbox "Email" [ref=e1], textbox "Password" [ref=e2], button "Submit" [ref=e3]
143
+
144
+ agent-browser fill @e1 "user@example.com"
145
+ agent-browser fill @e2 "password123"
146
+ agent-browser click @e3
147
+ agent-browser wait --load networkidle
148
+ agent-browser snapshot -i # Check result
149
+ ```
150
+
151
+ ## Example: Data extraction
152
+
153
+ ```bash
154
+ agent-browser open https://example.com/products
155
+ agent-browser snapshot -i
156
+ agent-browser get text @e1 # Get product title
157
+ agent-browser get attr @e2 href # Get link URL
158
+ agent-browser screenshot products.png
159
+ ```
@@ -0,0 +1,64 @@
1
+ ---
2
+ name: install-skill
3
+ description: >
4
+ When a user requests to install a new skill, this skill guides you to identify
5
+ the package name from various input formats and use the install_skill MCP tool.
6
+ Supports skills.sh URLs, GitHub URLs, owner/repo, and owner/repo@skill formats.
7
+ user-invocable: false
8
+ ---
9
+
10
+ # Skill Installation Guide
11
+
12
+ When a user asks to install a skill (e.g., sends a link, mentions a skill name, or says "install xxx skill"), follow this process:
13
+
14
+ ## 1. Identify the Package Name
15
+
16
+ Parse the user's input to extract the `owner/repo` or `owner/repo@skill` format:
17
+
18
+ | Input Format | Example | Extract As |
19
+ |---|---|---|
20
+ | skills.sh URL | `https://skills.sh/s/owner/repo` | `owner/repo` |
21
+ | skills.sh skill URL | `https://skills.sh/s/owner/repo/skill-name` | `owner/repo@skill-name` |
22
+ | GitHub URL | `https://github.com/owner/repo` | `owner/repo` |
23
+ | GitHub tree URL | `https://github.com/owner/repo/tree/main/skills/name` | `owner/repo@name` |
24
+ | Direct package | `owner/repo` | `owner/repo` |
25
+ | Package with skill | `owner/repo@skill` | `owner/repo@skill` |
26
+
27
+ ## 2. Install the Skill
28
+
29
+ Call the `install_skill` MCP tool with the extracted package name:
30
+
31
+ ```
32
+ install_skill({ "package": "owner/repo" })
33
+ ```
34
+
35
+ Or with a specific skill from the repo:
36
+
37
+ ```
38
+ install_skill({ "package": "owner/repo@skill-name" })
39
+ ```
40
+
41
+ ## 3. Handle Results
42
+
43
+ **On success:**
44
+ - Tell the user which skill(s) were installed (use the `installed` array from the response)
45
+ - Briefly describe what the skill does (if you know from context)
46
+ - Mention they can manage it in the Skills page
47
+
48
+ **On failure:**
49
+ - Check if the package name format is correct
50
+ - Suggest the user verify the URL or package name
51
+ - Common issues:
52
+ - Package not found: double-check the owner/repo spelling
53
+ - Network error: ask user to retry
54
+ - Invalid format: must be `owner/repo` or `owner/repo@skill`
55
+
56
+ ## 4. Uninstalling
57
+
58
+ If the user wants to uninstall a skill, use the `uninstall_skill` MCP tool:
59
+
60
+ ```
61
+ uninstall_skill({ "skill_id": "skill-name" })
62
+ ```
63
+
64
+ The `skill_id` is the directory name of the installed skill.
@@ -0,0 +1,121 @@
1
+ ---
2
+ name: post-test-cleanup
3
+ description: 测试完成后的扫尾清理流程。在向某个工作区发送测试指令(如长篇文章生成、耗时任务)后,用此流程彻底清除测试痕迹,防止测试消息残留在会话上下文中持续消耗 token 额度。
4
+ ---
5
+
6
+ # 测试后扫尾清理流程
7
+
8
+ ## 何时使用
9
+
10
+ - 向某个工作区发送了耗时测试指令(如"写一篇5000字综述")后
11
+ - 测试完成或中断后,需要清除测试痕迹
12
+ - 发现某工作区残留测试消息影响 AI 上下文时
13
+
14
+ ## 完整清理步骤
15
+
16
+ ### 第一步:停止残留容器
17
+
18
+ ```bash
19
+ # 查看当前运行的容器
20
+ docker ps --format "table {{.Names}}\t{{.Status}}\t{{.RunningFor}}"
21
+
22
+ # 确认目标容器的 folder(容器名格式:cli-claw-{folder}-{timestamp})
23
+ ls ~/.cli-claw/ipc/
24
+
25
+ # 发送中断信号(优雅停止)
26
+ touch ~/.cli-claw/ipc/{folder}/input/_interrupt
27
+ sleep 5
28
+
29
+ # 若容器仍在运行,发送关闭信号
30
+ touch ~/.cli-claw/ipc/{folder}/input/_close
31
+ sleep 10
32
+
33
+ # 确认容器已停止
34
+ docker ps --format "{{.Names}}" | grep {folder关键字}
35
+ ```
36
+
37
+ ### 第二步:查找测试消息
38
+
39
+ ```python3
40
+ python3 -c "
41
+ import os, sqlite3
42
+ conn = sqlite3.connect(os.path.expanduser('~/.cli-claw/db/messages.db'))
43
+ cur = conn.cursor()
44
+
45
+ # 先找到 folder 对应的 JID
46
+ cur.execute(\"SELECT jid, folder, name FROM registered_groups WHERE folder = '{folder}'\")
47
+ print('Group:', cur.fetchall())
48
+
49
+ # 查看最近消息,定位测试消息范围
50
+ cur.execute(\"\"\"
51
+ SELECT id, content, is_from_me, timestamp
52
+ FROM messages
53
+ WHERE chat_jid = '{jid}'
54
+ ORDER BY timestamp DESC LIMIT 20
55
+ \"\"\")
56
+ for r in cur.fetchall():
57
+ print(f'id={r[0]} from_me={r[2]} | {str(r[1])[:80]}')
58
+ conn.close()
59
+ "
60
+ ```
61
+
62
+ ### 第三步:删除测试消息
63
+
64
+ ```python3
65
+ python3 -c "
66
+ import os, sqlite3
67
+ conn = sqlite3.connect(os.path.expanduser('~/.cli-claw/db/messages.db'))
68
+ cur = conn.cursor()
69
+
70
+ # 将需要删除的消息 ID 填入列表
71
+ test_ids = [
72
+ 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx',
73
+ # ...
74
+ ]
75
+
76
+ placeholders = ','.join(['?' for _ in test_ids])
77
+ cur.execute(f'DELETE FROM messages WHERE id IN ({placeholders})', test_ids)
78
+ print(f'Deleted {cur.rowcount} messages')
79
+ conn.commit()
80
+ conn.close()
81
+ "
82
+ ```
83
+
84
+ ### 第四步:重置 Claude 会话(关键:清除 token 上下文)
85
+
86
+ ```python3
87
+ python3 -c "
88
+ import os, sqlite3, uuid
89
+ conn = sqlite3.connect(os.path.expanduser('~/.cli-claw/db/messages.db'))
90
+ cur = conn.cursor()
91
+
92
+ # 生成新 session ID,下次启动时以空上下文开始
93
+ new_id = str(uuid.uuid4())
94
+ cur.execute(\"UPDATE sessions SET session_id = ? WHERE group_folder = '{folder}'\", (new_id,))
95
+ print(f'Session reset: {cur.rowcount} rows, new ID: {new_id}')
96
+ conn.commit()
97
+ conn.close()
98
+ "
99
+ ```
100
+
101
+ ### 第五步:确认代码无意外修改
102
+
103
+ ```bash
104
+ git status
105
+ git diff --stat
106
+ # 应显示 "nothing to commit, working tree clean"
107
+ ```
108
+
109
+ ## 注意事项
110
+
111
+ - **必须重置 session**:仅删除 DB 消息不够,Claude session 文件中仍保存着历史上下文,下次激活时依然消耗 token
112
+ - **容器名与 folder 的对应关系**:容器名格式为 `cli-claw-{folder}-{timestamp}`,可通过 `ls ~/.cli-claw/ipc/` 查看所有 folder
113
+ - **删除消息前仔细核对**:通过 `is_from_me` 和内容确认,避免误删正常业务消息
114
+ - **全局运行时目录的修改不影响 git**:SQLite 和 IPC 文件均在 `~/.cli-claw/` 下,不纳入版本控制
115
+
116
+ ## 快速检查清单
117
+
118
+ - [ ] 无残留测试容器在运行(`docker ps`)
119
+ - [ ] 测试消息已从 DB 删除
120
+ - [ ] Claude session ID 已重置为新 UUID
121
+ - [ ] `git status` 显示工作区干净