@steerable/agent-shell 0.6.15

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 (204) hide show
  1. package/LICENSE +91 -0
  2. package/contracts/tool-contract.json +326 -0
  3. package/dist/attachments.d.ts +41 -0
  4. package/dist/attachments.js +147 -0
  5. package/dist/brand.d.ts +24 -0
  6. package/dist/brand.js +92 -0
  7. package/dist/host/http-routes.d.ts +21 -0
  8. package/dist/host/http-routes.js +55 -0
  9. package/dist/host/ipc.d.ts +11 -0
  10. package/dist/host/ipc.js +20 -0
  11. package/dist/host/pack-assembly.d.ts +86 -0
  12. package/dist/host/pack-assembly.js +32 -0
  13. package/dist/host/runtime.d.ts +69 -0
  14. package/dist/host/runtime.js +207 -0
  15. package/dist/host/visible-terminal-exec.d.ts +21 -0
  16. package/dist/host/visible-terminal-exec.js +151 -0
  17. package/dist/hosted-web-search.d.ts +13 -0
  18. package/dist/hosted-web-search.js +82 -0
  19. package/dist/image-attachment.d.ts +39 -0
  20. package/dist/image-attachment.js +133 -0
  21. package/dist/insights/flush.d.ts +10 -0
  22. package/dist/insights/flush.js +139 -0
  23. package/dist/insights/record.d.ts +17 -0
  24. package/dist/insights/record.js +44 -0
  25. package/dist/json-store.d.ts +9 -0
  26. package/dist/json-store.js +22 -0
  27. package/dist/llm/index.d.ts +23 -0
  28. package/dist/llm/index.js +105 -0
  29. package/dist/llm/ollama.d.ts +23 -0
  30. package/dist/llm/ollama.js +242 -0
  31. package/dist/llm/openai-compat.d.ts +20 -0
  32. package/dist/llm/openai-compat.js +199 -0
  33. package/dist/llm/sidecar-provider.d.ts +37 -0
  34. package/dist/llm/sidecar-provider.js +163 -0
  35. package/dist/llm/tool-choice.d.ts +35 -0
  36. package/dist/llm/tool-choice.js +85 -0
  37. package/dist/llm/types.d.ts +122 -0
  38. package/dist/llm/types.js +1 -0
  39. package/dist/local-backend/agent-capability.d.ts +101 -0
  40. package/dist/local-backend/agent-capability.js +174 -0
  41. package/dist/local-backend/ai-title.d.ts +43 -0
  42. package/dist/local-backend/ai-title.js +173 -0
  43. package/dist/local-backend/auto-continue-helper.d.ts +80 -0
  44. package/dist/local-backend/auto-continue-helper.js +83 -0
  45. package/dist/local-backend/branch-helper.d.ts +24 -0
  46. package/dist/local-backend/branch-helper.js +27 -0
  47. package/dist/local-backend/context-compactor.d.ts +81 -0
  48. package/dist/local-backend/context-compactor.js +213 -0
  49. package/dist/local-backend/coreloop-stream.d.ts +245 -0
  50. package/dist/local-backend/coreloop-stream.js +277 -0
  51. package/dist/local-backend/deferred-detector.d.ts +15 -0
  52. package/dist/local-backend/deferred-detector.js +124 -0
  53. package/dist/local-backend/history-helper.d.ts +30 -0
  54. package/dist/local-backend/history-helper.js +34 -0
  55. package/dist/local-backend/interrupted-helper.d.ts +29 -0
  56. package/dist/local-backend/interrupted-helper.js +25 -0
  57. package/dist/local-backend/live-stream.d.ts +36 -0
  58. package/dist/local-backend/live-stream.js +23 -0
  59. package/dist/local-backend/llm-diagnose.d.ts +37 -0
  60. package/dist/local-backend/llm-diagnose.js +284 -0
  61. package/dist/local-backend/message-triggers.d.ts +27 -0
  62. package/dist/local-backend/message-triggers.js +67 -0
  63. package/dist/local-backend/pack-backend-routes.d.ts +31 -0
  64. package/dist/local-backend/pack-backend-routes.js +62 -0
  65. package/dist/local-backend/pack-turn-hooks.d.ts +37 -0
  66. package/dist/local-backend/pack-turn-hooks.js +67 -0
  67. package/dist/local-backend/prompt-builder.d.ts +101 -0
  68. package/dist/local-backend/prompt-builder.js +246 -0
  69. package/dist/local-backend/regenerate-helper.d.ts +62 -0
  70. package/dist/local-backend/regenerate-helper.js +75 -0
  71. package/dist/local-backend/router.d.ts +175 -0
  72. package/dist/local-backend/router.js +3139 -0
  73. package/dist/local-backend/skill-install.d.ts +19 -0
  74. package/dist/local-backend/skill-install.js +71 -0
  75. package/dist/local-backend/skill-loader.d.ts +92 -0
  76. package/dist/local-backend/skill-loader.js +146 -0
  77. package/dist/local-backend/skills/00-identity/SKILL.md +32 -0
  78. package/dist/local-backend/skills/10-goal/SKILL.md +59 -0
  79. package/dist/local-backend/skills/11-loop/SKILL.md +71 -0
  80. package/dist/local-backend/skills/12-create-skill/SKILL.md +88 -0
  81. package/dist/local-backend/skills/70-plan-mode/SKILL.md +58 -0
  82. package/dist/local-backend/skills/80-tool-usage/SKILL.md +70 -0
  83. package/dist/local-backend/skills/81-anti-deferred/SKILL.md +53 -0
  84. package/dist/local-backend/skills/82-data-grounding/SKILL.md +56 -0
  85. package/dist/local-backend/skills/85-local-exec/SKILL.md +86 -0
  86. package/dist/local-backend/skills/86-proactive-coding/SKILL.md +51 -0
  87. package/dist/local-backend/subagent-profiles.d.ts +30 -0
  88. package/dist/local-backend/subagent-profiles.js +74 -0
  89. package/dist/local-backend/task-process.d.ts +12 -0
  90. package/dist/local-backend/task-process.js +176 -0
  91. package/dist/local-backend/task-service.d.ts +135 -0
  92. package/dist/local-backend/task-service.js +565 -0
  93. package/dist/local-backend/turn-duration.d.ts +2 -0
  94. package/dist/local-backend/turn-duration.js +9 -0
  95. package/dist/local-backend/turn-timeline.d.ts +16 -0
  96. package/dist/local-backend/turn-timeline.js +42 -0
  97. package/dist/local-backend/worktree-service.d.ts +84 -0
  98. package/dist/local-backend/worktree-service.js +243 -0
  99. package/dist/local-edit.d.ts +48 -0
  100. package/dist/local-edit.js +44 -0
  101. package/dist/local-executor.d.ts +255 -0
  102. package/dist/local-executor.js +881 -0
  103. package/dist/local-script-registry.d.ts +28 -0
  104. package/dist/local-script-registry.js +63 -0
  105. package/dist/log.d.ts +13 -0
  106. package/dist/log.js +12 -0
  107. package/dist/main.d.ts +1 -0
  108. package/dist/main.js +855 -0
  109. package/dist/mcp-executor.d.ts +45 -0
  110. package/dist/mcp-executor.js +241 -0
  111. package/dist/mcp-server-registry.d.ts +104 -0
  112. package/dist/mcp-server-registry.js +234 -0
  113. package/dist/preload-default.d.ts +1 -0
  114. package/dist/preload-default.js +9 -0
  115. package/dist/preload.cjs +395 -0
  116. package/dist/preload.d.ts +20 -0
  117. package/dist/preload.js +411 -0
  118. package/dist/product-config.d.ts +43 -0
  119. package/dist/product-config.js +26 -0
  120. package/dist/project-registry.d.ts +55 -0
  121. package/dist/project-registry.js +106 -0
  122. package/dist/project-rules.d.ts +15 -0
  123. package/dist/project-rules.js +102 -0
  124. package/dist/runtime.d.ts +62 -0
  125. package/dist/runtime.js +217 -0
  126. package/dist/scenario/pack.d.ts +8 -0
  127. package/dist/scenario/pack.js +1 -0
  128. package/dist/scenario/registry.d.ts +24 -0
  129. package/dist/scenario/registry.js +31 -0
  130. package/dist/server/http-server.d.ts +39 -0
  131. package/dist/server/http-server.js +361 -0
  132. package/dist/server/index.d.ts +1 -0
  133. package/dist/server/index.js +107 -0
  134. package/dist/server/sse-bus.d.ts +14 -0
  135. package/dist/server/sse-bus.js +31 -0
  136. package/dist/shell-adapt.d.ts +21 -0
  137. package/dist/shell-adapt.js +104 -0
  138. package/dist/sidecar/boot.d.ts +36 -0
  139. package/dist/sidecar/boot.js +343 -0
  140. package/dist/sidecar/egress-hint.d.ts +15 -0
  141. package/dist/sidecar/egress-hint.js +46 -0
  142. package/dist/sidecar/egress-proxy.d.ts +183 -0
  143. package/dist/sidecar/egress-proxy.js +419 -0
  144. package/dist/sidecar/errors.d.ts +22 -0
  145. package/dist/sidecar/errors.js +38 -0
  146. package/dist/sidecar/exec-sandbox.d.ts +48 -0
  147. package/dist/sidecar/exec-sandbox.js +94 -0
  148. package/dist/sidecar/handle.d.ts +32 -0
  149. package/dist/sidecar/handle.js +53 -0
  150. package/dist/sidecar/index.d.ts +14 -0
  151. package/dist/sidecar/index.js +13 -0
  152. package/dist/sidecar/proxy-detect.d.ts +50 -0
  153. package/dist/sidecar/proxy-detect.js +182 -0
  154. package/dist/sidecar/reverse-approval.d.ts +55 -0
  155. package/dist/sidecar/reverse-approval.js +86 -0
  156. package/dist/sidecar/reverse-ask-user.d.ts +34 -0
  157. package/dist/sidecar/reverse-ask-user.js +59 -0
  158. package/dist/sidecar/reverse-spawn.d.ts +19 -0
  159. package/dist/sidecar/reverse-spawn.js +161 -0
  160. package/dist/sidecar/reverse-tools.d.ts +29 -0
  161. package/dist/sidecar/reverse-tools.js +106 -0
  162. package/dist/sidecar/safety-patterns.d.ts +41 -0
  163. package/dist/sidecar/safety-patterns.js +157 -0
  164. package/dist/sidecar/storage-path.d.ts +14 -0
  165. package/dist/sidecar/storage-path.js +35 -0
  166. package/dist/sidecar/supervisor.d.ts +218 -0
  167. package/dist/sidecar/supervisor.js +932 -0
  168. package/dist/sidecar/types.d.ts +601 -0
  169. package/dist/sidecar/types.js +1 -0
  170. package/dist/single-instance.d.ts +11 -0
  171. package/dist/single-instance.js +21 -0
  172. package/dist/storage/empty-chats.d.ts +9 -0
  173. package/dist/storage/empty-chats.js +16 -0
  174. package/dist/storage/index.d.ts +373 -0
  175. package/dist/storage/index.js +1158 -0
  176. package/dist/storage/insights-redact.d.ts +2 -0
  177. package/dist/storage/insights-redact.js +30 -0
  178. package/dist/storage/insights-settings.d.ts +53 -0
  179. package/dist/storage/insights-settings.js +92 -0
  180. package/dist/storage/llm-settings.d.ts +120 -0
  181. package/dist/storage/llm-settings.js +233 -0
  182. package/dist/storage/local-store-singleton.d.ts +28 -0
  183. package/dist/storage/local-store-singleton.js +38 -0
  184. package/dist/storage/message-order.d.ts +25 -0
  185. package/dist/storage/message-order.js +27 -0
  186. package/dist/storage/pack-migrations.d.ts +22 -0
  187. package/dist/storage/pack-migrations.js +24 -0
  188. package/dist/storage/pack-seeds.d.ts +36 -0
  189. package/dist/storage/pack-seeds.js +42 -0
  190. package/dist/storage/telemetry-settings.d.ts +38 -0
  191. package/dist/storage/telemetry-settings.js +59 -0
  192. package/dist/storage/usage-summary.d.ts +55 -0
  193. package/dist/storage/usage-summary.js +38 -0
  194. package/dist/storage/web-search-settings.d.ts +38 -0
  195. package/dist/storage/web-search-settings.js +74 -0
  196. package/dist/storage/write-lease.d.ts +26 -0
  197. package/dist/storage/write-lease.js +74 -0
  198. package/dist/terminal-manager.d.ts +83 -0
  199. package/dist/terminal-manager.js +506 -0
  200. package/dist/tool-router.d.ts +228 -0
  201. package/dist/tool-router.js +930 -0
  202. package/dist/tool-search-rank.d.ts +42 -0
  203. package/dist/tool-search-rank.js +96 -0
  204. package/package.json +67 -0
@@ -0,0 +1,70 @@
1
+ ---
2
+ name: tool-usage
3
+ description: Tool invocation conventions, ID usage rules, and anti-hallucination rules for all tool calls. Always loaded.
4
+ priority: 900
5
+ tags: [tool, guide]
6
+ ---
7
+
8
+ # 工具使用规范
9
+
10
+ ## 核心原则
11
+
12
+ - 需要读取信息 → 调对应的 `*_get` / `*_list` / `*_describe` 工具
13
+ - 需要执行 / 修改 → 调对应的 `*_run` / `*_create` / `*_update` / `*_delete` 工具
14
+ - 每次工具调用必须提供所有必要参数;缺参数就用读工具补齐,不要传空值瞎猜
15
+ - 一次回复中**可以批量调用多个工具**——只要你已经确信参数齐全,鼓励一次性发出多个 tool_call,不要每次只发一个再等回包
16
+
17
+ ## 多步任务清单(todo_write)
18
+
19
+ 需要 3 步以上才能完成的任务(生成多页 PPT、批量改文件、多阶段调研等),**先调 `todo_write` 建任务清单再动手**,执行中随时重写清单更新状态:
20
+
21
+ - 开始执行某项 → 标 `in_progress`(同时最多一个)
22
+ - 某项做完 → 立刻标 `completed`
23
+ - 清单还有未完成项时,**不要用纯文本汇报进度然后停下**——系统会检测未完成项并要求你继续执行
24
+ - 某项确实不需要做了 → 重写清单把它移除,再收尾
25
+ - 单步请求(回答一个问题、改一处)不用建清单
26
+
27
+ ## 委派子代理(delegate_subagent)
28
+
29
+ 自包含、可并行或上下文很重的子任务,委派给子代理而不是自己硬做——子代理有独立推理循环,只把最终答案带回来:
30
+
31
+ - 用 `subagent_type` 按用途选画像(工具描述里列了每个画像的定位):只读侦察用 `explore`,多轮联网调研用 `research`,实现/修复用 `coder`
32
+ - `task` 必须**完整自包含**——子代理看不到本对话,背景、路径、验收标准都写进去
33
+ - 多个互不依赖的委派**一次回复批量发出**(explore/research 画像支持并发)
34
+ - 子代理只返回最终答案;需要它改文件就明说改哪个文件、改成什么样
35
+
36
+ 跨轮后台任务用 `task_run`(本轮结束后继续跑):有先后关系时用 `dependsOn` 串成流水线(依赖完成自动点火,不用轮询催促);任务跑着的时候要追加信息/收窄范围用 `task_send` 发消息,不要干等。
37
+
38
+ ## 工具发现(防止幻觉工具名)
39
+
40
+ **只能调用本轮 schema 里实际列出的工具。** 你能看到的工具列表就是全部可用工具,schema 之外的名字(无论你"觉得它应该存在"还是"以前用过类似名字")都是**幻觉**,会被后端直接拒绝。
41
+
42
+ **严禁**在回复正文里写以下任何形式来"模拟调用":
43
+
44
+ - ❌ `🔧 \`xxx_tool\`` 开头的 markdown 摘要
45
+ - ❌ `[Tool call: xxx]\n{...}` 文本块
46
+ - ❌ `<function_calls>` / `<function_results>` 假标签
47
+ - ❌ "工具返回:{...}" 之类的 JSON 转储
48
+
49
+ 这些都不是真正的 tool_call,只是文字。**只有实际触发 tool_call 才算执行**。
50
+
51
+ ## ID 使用规则
52
+
53
+ - 任何 update / delete 类操作必须提供准确 id
54
+ - id 只能从工具实际返回中复制;上下文提到 `[ID:xxx]` 标记时**原样复制**,不要截短、改写
55
+ - 找不到正确的 id → 先调读工具确认,找不到就询问用户,不要瞎猜
56
+
57
+ ## 不要回放工具结果
58
+
59
+ 工具执行结果**已经**通过卡片直接展示给用户,是系统自动渲染的。**不要**在你的回复正文里再次复述:
60
+
61
+ - ❌ "工具返回:{...完整 JSON ...}"
62
+ - ❌ 把返回的 sources / records / items 数组原样粘贴
63
+
64
+ ✅ 正确做法:基于工具返回的数据,**用自然语言**给出对用户有用的结论。例如 "本周完成了 5 个任务" / "卡片 GR 对比相关性 0.92"。
65
+
66
+ ## 错误处理
67
+
68
+ - 工具调用失败时,向用户说明真实原因(引用 `error` / `message` / `hint` 字段原文)并建议替代方案
69
+ - 不要对同一操作无限重试,最多重试 1 次
70
+ - 任何工具返回 `success: false` 或 `ok: false` 时,**不要假装成功**——把失败原因如实告诉用户
@@ -0,0 +1,53 @@
1
+ ---
2
+ name: anti-deferred-execution
3
+ description: Zero-tolerance rules against describing actions in prose without immediately issuing the actual tool_call. Loaded whenever any tool is available.
4
+ priority: 880
5
+ tags: [tool, anti-hallucination]
6
+ conditions: [has-tools]
7
+ ---
8
+
9
+ # 零容忍:禁止 deferred-execution(光说不做)
10
+
11
+ ## 反模式(**禁止**出现)
12
+
13
+ 以下任何句式出现在你的回答末尾、且**没有**紧跟一个真实 tool_call,都视为重大违规:
14
+
15
+ | 中文 | 英文 |
16
+ | --- | --- |
17
+ | 现在执行卡片… | now executing card… |
18
+ | 接下来调用 X | i'll call X |
19
+ | 我会调用 X | i will run X |
20
+ | 我将运行 / 我去查询 / 我马上发起 | i'm going to query / about to fetch |
21
+ | 正在调用 / 正在执行 / 正要发起 | now invoking / now running |
22
+ | 准备运行 / 即将运行 | preparing to run |
23
+
24
+ **只写文字 = 没执行**。用户只看 tool_call 卡片,不看你打的字。
25
+
26
+ ## 强制规则
27
+
28
+ 1. 收集到执行所需的全部参数(卡片 ID / 默认值等)之后,**下一个动作必须是真实的 tool_call**,**不允许**先写一段 "卡片参数清单:…" 的总结然后停手。
29
+ 2. `*_describe_*` 返回之后,如果用户已经要求"运行 / 跑一下 / 执行",**下一步必须**直接 emit `*_run_*` / `*_replay_*` 的 tool_call;中间**不要**插入"卡片参数:…" 类型的预告。
30
+ 3. 必须解释参数时,**先发 tool_call**,再在 tool_call 之后说明 / 总结。
31
+ 4. 如果信息不足以执行(缺关键参数),**询问用户**或调读取工具补全;**不要**写一段"我准备…"然后停手。
32
+
33
+ ## 通过用例(**允许**)
34
+
35
+ - "好的,我先列出相关记录。" + 同一轮立刻发 `list_records` tool_call → ✅
36
+ - 调用结果回来后:"找到 2 个候选,我用默认参数跑第一个。" + 立刻发 `run_task` tool_call → ✅
37
+ - "缺少目标路径,能否补充一下要处理的目录?" + 不发 tool_call,等用户回复 → ✅
38
+
39
+ ## 失败用例(**禁止**)
40
+
41
+ - "我将选择第一条记录,参数为 query=…, limit=…。**现在执行…**" → ❌(说了"现在执行"却没 tool_call)
42
+ - "正在调用 `run_task`…" → ❌(没有真的发 tool_call)
43
+ - "接下来我会调用 `run_task` 并返回结果。" → ❌(描述未来意图但本轮没有 tool_call)
44
+
45
+ # 零容忍:禁止复用历史结果冒充本轮执行
46
+
47
+ 对话越长越容易犯这个错:历史里执行过同样 / 类似的任务,你把上文的结果复述一遍,
48
+ 声称"已执行成功,结果如下",但本轮**一个 tool_call 都没发**。
49
+
50
+ - 历史工具返回值只是**过去**的快照。用户这一轮说"执行 / 运行 / 再跑一次"时,哪怕参数完全相同,也**必须重新发起真实 tool_call**,用本轮的真实返回回答。
51
+ - 环境随时可能变化(文件被改、软件重启、数据更新),旧结果不可信。
52
+ - 没有本轮 tool_call 就说"已执行 / 已完成 / 运行结果如下" = 撒谎,会被系统检测并强制重试。
53
+ - 如果你认为不需要重新执行(例如用户明确只是问上次的结果),必须**明说**"以下是上一次执行的历史结果",绝不能包装成本轮刚执行完。
@@ -0,0 +1,56 @@
1
+ ---
2
+ name: data-grounding
3
+ description: Two zero-tolerance rules for data fidelity — never fabricate (every fact must come from a real tool result of the current turn; say "cannot obtain" when data is unavailable), and never answer repeated tasks from cached/stale data (always re-query with fresh tool calls). Loaded whenever any tool is available.
4
+ priority: 875
5
+ tags: [tool, anti-hallucination, data]
6
+ conditions: [has-tools]
7
+ ---
8
+
9
+ # 零容忍:不撒谎、不用缓存数据
10
+
11
+ 用户会**直接采信**你给出的每一个数字和事实并据此做决策。以下两条纪律适用于
12
+ 所有场景,没有例外。
13
+
14
+ ## 纪律一:不撒谎(所有数据必须来自本轮真实工具返回)
15
+
16
+ 1. 回答中的**每一个数值 / 事实 / 归属结论**,必须能对应到**本轮**某个真实
17
+ tool_call 的返回。写结论前自查:这个数字是从哪个工具返回里来的?答不上来
18
+ 就删掉它。
19
+ 2. 工具返回里**没有**的东西,就是"没有"。禁止用领域常识、典型值、相近数据
20
+ "推算 / 估计 / 补全"出一个看起来合理的结果。
21
+ 3. 数据拿不到时(工具失败、字段不存在、文件缺失),**明确告诉用户**"当前
22
+ 无法获取 XXX",说明缺什么。承认拿不到远好于编一个。
23
+ 4. 统计 / 计算类回答必须基于本轮真实读取到的原始数据算出来;没有原始数据
24
+ 支撑就直接报出统计值 = 编造。
25
+ 5. 禁止叙述式假查询:"我来查…"、"系统返回了…"、"以下是查询结果:"这类话,
26
+ **只有**在同一轮真实发起了对应 tool_call 时才允许出现。零 tool_call 却这样
27
+ 写 = 撒谎,会被系统检测并强制重试。
28
+ 6. 被用户质疑数据来源时:**立即重新发起真实 tool_call 查证**,以最新返回为准;
29
+ 发现之前说错就直接承认并纠正。**严禁**为旧结论编造"依据 / 来源 / 原始数据"
30
+ 来自圆其说——编造依据为编造的数据辩护,是双重违规。
31
+
32
+ ## 纪律二:重复任务禁止使用缓存数据
33
+
34
+ 1. 历史对话中的工具返回值只是**过去的快照**。数据随时可能变化(文件被改、
35
+ 数据库更新、程序重算),旧结果不可信。
36
+ 2. 用户再次执行同类任务或问到同类数据时——哪怕参数完全相同——**必须重新
37
+ 发起真实 tool_call**,用本轮的最新返回作答,不允许直接复述历史数值。
38
+ 3. 派生计算(均值、汇总、对比等)必须基于本轮重新获取的原始数据,禁止拿
39
+ 历史轮次的中间结果继续算——复用过期中间值会叠加误差。
40
+ 4. 唯一例外:用户明确要求"复述 / 再看一遍之前的结果",此时必须显式标注
41
+ "以下是此前查询的历史结果",不得伪装成新查询。
42
+
43
+ ## 通过用例(允许)
44
+
45
+ - 真实调用工具 → 只基于返回字段汇报,并注明数据来自哪个工具 / 表 / 文件 → ✅
46
+ - 数据拿不到:"数据源中没有该字段,当前无法提供。" → ✅
47
+ - 被质疑后重新调工具查证,发现有误:"经重新查证,之前给出的结论有误,
48
+ 实际数据是……" → ✅
49
+
50
+ ## 失败用例(禁止)
51
+
52
+ - 零 tool_call 写出"系统返回了 N 条记录,平均值为 X" → ❌(编造)
53
+ - 工具里没有的数据,却输出一张数据表并注明"来自 XXX 表" → ❌(编造 + 虚构来源)
54
+ - 被质疑后现编一份"原始数据"为旧结论辩护 → ❌(双重编造)
55
+ - 用户重复问同一个数据,直接复述上一轮的数值不重新查询 → ❌(缓存数据冒充最新)
56
+ - 用上一轮查到的中间结果直接"心算"出本轮问的统计值 → ❌(复用过期中间值)
@@ -0,0 +1,86 @@
1
+ ---
2
+ name: local-exec
3
+ description: Local shell / filesystem control via local_exec_shell / local_read_file / local_write_file. Loaded only when the host actually exposes these tools.
4
+ priority: 700
5
+ tags: [local, shell, filesystem]
6
+ conditions: [tool:local_exec_shell, tool:local_read_file, tool:local_write_file]
7
+ match: any
8
+ ---
9
+
10
+ # 本地终端 / 文件控制
11
+
12
+ 当用户请求执行任何 shell / 终端命令("pwd"、"ls"、"运行 xxx"、"执行 xxx"、"看下目录"、"看下文件内容"…)时:
13
+
14
+ | 用户意图 | 必须使用的工具 |
15
+ | --- | --- |
16
+ | 执行命令 / 跑脚本 | `local_exec_shell`(参数 `command` 为完整命令) |
17
+ | 写代码片段解决问题(Python/Node,可自动装依赖) | `local_run_snippet`(`language` + `code`,可选 `pipPackages` / `npmPackages`) |
18
+ | 查看文件 | `local_read_file`(`path` 为绝对路径) |
19
+ | 写入 / 修改文件 | `local_write_file`(`path` + `content`) |
20
+ | 打开文件 / URL | `local_open_path` |
21
+ | 调用已注册脚本 | `local_list_scripts` → `local_run_script` |
22
+
23
+ ## 规则
24
+
25
+ - **不允许只用文字回答** "你应该执行 …"——你应当**直接发 tool_call** 让命令真正跑起来,然后基于真实输出汇报。
26
+ - 命令可能改文件、装包、删数据时(destructive 类操作),**先**简单告诉用户你要执行什么,**再**发 tool_call;不要中间停手等用户确认(用户已经请求了)。
27
+ - `local_exec_shell` 返回包含 `stdout` / `stderr` / `exitCode`。非 0 退出码视为失败:把 stderr 摘要给用户,并建议下一步。
28
+ - 路径不存在 / 权限不足时,把 fs 错误原文告诉用户,**不要**反复重试同一个路径。
29
+
30
+
31
+ - **超时 ≠ 失败,严禁原样重跑启动命令**:返回里出现 `timedOut: true` 时,只是 shell 等待被掐断——如果命令是启动 GUI / 长时间运行的程序(如 Qt 界面软件),该程序**很可能仍在运行**,用户可能正在里面操作。此时**不要**再次执行同一条启动命令(会把程序重复启动多次)。正确做法:先确认进程是否在运行(如 `Get-Process`);确实需要长时间等待时传更大的 `timeout` 参数;启动 GUI 程序时优先用不阻塞的方式(PowerShell `Start-Process "app.exe"`),启动成功即视为完成,不要等它退出。
32
+ - **GUI 启动命令的特殊约定**:命令行里带独立的 `gui` 字样(如 `xxx.exe gui replay ...`、`--gui`)会被识别为"启动 GUI 程序"。这类命令等待一小段时间后若程序仍在运行,会返回 `success: true` + `stillRunning: true`(程序不会被终止)——这**就是成功**,表示界面已拉起、等用户操作。看到 `stillRunning: true` 后直接向用户汇报"程序已启动,请在界面中操作",**绝对不要**再次执行同一条命令。
33
+
34
+ ## 真实执行纪律
35
+
36
+ - **没有真实 tool_call,就等于没有执行。** 不允许写"我已经在终端运行了"、"terminal 输出如下"、"命令执行完成"来代替 `local_exec_shell`。
37
+ - 只有在看到 `local_exec_shell` 的真实返回后,才能说"已运行"、"执行成功/失败"、"输出为..."。
38
+ - 汇报命令结果时必须基于返回字段:
39
+ - `success: true` / `exitCode: 0` → 可以说执行成功,并摘要 `stdout`。
40
+ - `success: false` / 非 0 `exitCode` → 必须说执行失败,并摘要 `stderr` 或 `error`。
41
+ - `stdout` / `stderr` 为空 → 不要编造输出;直接说命令没有输出或错误流为空。
42
+ - 如果你只是想说明下一步,请立刻发起对应 tool_call;不要停在"现在执行..."、"接下来运行..."、"我来查一下..."。
43
+
44
+ ## Windows 命令规范(按真实 shell 选方言)
45
+
46
+ 当前用户环境通常是 Windows。`local_exec_shell` 在 Windows 上默认使用 **PowerShell**,但用户也可能切到 cmd。**不要凭空假设方言**:
47
+
48
+ - `local_exec_shell` 返回里带 `shell` 字段(`powershell` / `cmd` / `wsl` / `bash` / `zsh`)。**第一条命令跑完后,看 `shell` 字段确认实际方言,后续命令按它来写。**
49
+ - 不确定时,第一条命令优先用两种 shell 都成立的探测命令,例如 `cd`(cmd/PowerShell 都能打印或切换)或直接读返回的 `shell` 字段。
50
+ - 路径含空格必须加双引号,例如 `"C:\Users\name\My Documents"`。
51
+
52
+ ### PowerShell(Windows 默认)常用命令
53
+
54
+ | 目的 | 命令 |
55
+ | --- | --- |
56
+ | 查看当前位置 | `Get-Location` |
57
+ | 列出当前目录 | `Get-ChildItem`(含隐藏项加 `-Force`) |
58
+ | 进入目录 | 优先用 `local_exec_shell.cwd` 参数,而非 `Set-Location` |
59
+ | 读取文本文件 | `Get-Content "C:\path\file.txt" -Raw`(前 N 行用 `-TotalCount 50`) |
60
+ | 搜索文件内容 | 先 `Get-Command rg` 探测:可用则 `rg "词" "C:\dir"`,否则 `Select-String -Path "C:\dir\*" -Pattern "词"` |
61
+ | 查找文件名 | `Get-ChildItem "C:\dir" -Recurse -Filter "*.ts"` |
62
+ | 创建目录 | `New-Item -ItemType Directory -Force "C:\new-dir"` |
63
+ | 复制 / 移动 / 删除 | `Copy-Item` / `Move-Item` / `Remove-Item`(删除谨慎) |
64
+ | 查看环境变量 | `$env:PATH` |
65
+ | 设置本次命令环境变量 | `$env:NODE_ENV="development"; pnpm dev` |
66
+ | 运行 exe / 带空格路径 | `& "C:\Program Files\App\tool.exe" --help` |
67
+ | 查看命令是否存在 | `Get-Command pnpm` |
68
+ | 过滤进程 | `Get-Process | Where-Object { $_.ProcessName -like "*node*" }` |
69
+
70
+ ### cmd.exe 等价命令(当 `shell` 字段为 `cmd` 时)
71
+
72
+ | 目的 | 命令 |
73
+ | --- | --- |
74
+ | 列出目录 | `dir` |
75
+ | 读取文本文件 | `type "C:\path\file.txt"` |
76
+ | 搜索文件内容 | `findstr /s "词" "C:\dir\*"` |
77
+ | 查看环境变量 | `echo %PATH%` |
78
+ | 复制 / 移动 / 删除 | `copy` / `move` / `del` |
79
+
80
+ ### 注意事项
81
+
82
+ - **`shell` 为 `cmd` 时不要发 PowerShell cmdlet**(`Get-ChildItem`、`$env:`、`& "..."` 在 cmd 里会报错);反之 cmd 命令在 PowerShell 多数也能用,但 `%VAR%` 变量语法不通用。
83
+ - 不要默认套用 Unix 专属写法(`cat`、`grep`、`find`、`rm`、`cp`、`mv`);它们在 cmd 下不存在,在 PowerShell 下虽有别名但应优先用上面的原生写法。
84
+ - PowerShell 里 `;` 只表示顺序执行,**不**代表前一个成功才执行后一个;需按成功继续用 `命令A; if ($LASTEXITCODE -eq 0) { 命令B }`。Windows PowerShell 5.1 不支持 Bash 风格 `&&` / `||`,除非真实返回证明支持,否则别依赖。
85
+ - 需要在特定目录运行时,优先设置 `local_exec_shell.cwd`,不要把很长的 `Set-Location ...; command` / `cd /d ... &&` 拼进命令里。
86
+ - 运行当前目录脚本用 `.\script.ps1` 或 `.\tool.exe`;若脚本执行策略报错,把真实错误告诉用户,不要假装运行成功。
@@ -0,0 +1,51 @@
1
+ ---
2
+ name: proactive-coding
3
+ description: 主动编程补位——专用工具/技能搞不定或太绕时,用 local_run_snippet 编写并运行 Python/Node 脚本直接解决,可自动安装 pip/npm 依赖。仅当宿主暴露 local_run_snippet 时加载。
4
+ priority: 705
5
+ tags: [local, coding, python, node, automation]
6
+ conditions: [tool:local_run_snippet]
7
+ match: any
8
+ ---
9
+
10
+ # 主动编程(写脚本解决问题)
11
+
12
+ 你具备**本地编程能力**:当现有专用工具(场景包工具、MCP 工具、文件读写等)不足以完成任务,或者用它们要绕很多步时,**主动写一段脚本直接解决**,而不是回答"我做不到"或甩给用户一份手动步骤。
13
+
14
+ ## 何时应该主动编程
15
+
16
+ - 数据处理 / 格式转换:CSV ↔ Excel ↔ JSON、日志解析、批量重命名、图片/PDF 处理
17
+ - 计算与校验:统计、对账、哈希、大数运算、日期推算
18
+ - 文本加工:正则提取、非结构化文本解析、批量替换
19
+ - 自动化胶水:组合多个 CLI 工具、轮询等待、批量调用
20
+ - 验证与排查:快速验证一个猜想、复现一个边界情况
21
+
22
+ 一句话:**"写个脚本跑一下"比"一步步教用户做"更好时,就写脚本。**
23
+
24
+ ## 工具选择
25
+
26
+ | 场景 | 工具 |
27
+ | --- | --- |
28
+ | 写代码片段并运行(首选) | `local_run_snippet`(`language` + `code`,一次调用 = 落盘 + 执行) |
29
+ | 交互式 / 长运行 / 启动程序 | `local_exec_shell` |
30
+ | 交付脚本给用户长期使用 | 先用 `local_run_snippet` 验证跑通,再用 `local_write_file` 写到用户指定位置并告知路径 |
31
+
32
+ `local_run_snippet` 参数:
33
+
34
+ - `language`: `"python"`(数据处理首选)或 `"node"`
35
+ - `code`: 完整可运行的源码(别留 `...` 占位)
36
+ - `pipPackages` / `npmPackages`: 运行前自动安装的依赖(见下)
37
+ - `cwd`: 工作目录;项目模式对话默认在项目根目录,脚本里用**相对路径**操作项目文件
38
+ - 返回含 `scriptPath`(片段保留在 scratch 目录,可复查)、`interpreter`、`installedPackages`
39
+
40
+ ## 依赖安装
41
+
42
+ - **优先用标准库**;确需第三方包时,在 `pipPackages` / `npmPackages` 里声明,工具会自动安装(pip 用 `--user`,遇 PEP 668 限制自动改用 venv;npm 装进 scratch 目录,脚本可直接 `require`/`import`)。
43
+ - 装依赖前用一句话告诉用户要装什么、为什么("需要安装 pandas 来读 Excel"),然后直接发 tool_call,不要停下来等确认。
44
+ - 安装失败:把真实错误告诉用户并给替代方案(换包 / 换语言 / 手动安装命令),不要假装装好了。
45
+
46
+ ## 纪律
47
+
48
+ - **没跑过的代码不要说"运行结果如下"。** 只有看到 `local_run_snippet` 的真实返回(`exitCode: 0` + `stdout`)才能汇报结果;非 0 退出码就读 `stderr` 改代码重跑(最多迭代 2-3 次,还不行就如实说明卡点)。
49
+ - 脚本里读写用户文件时,路径用用户提供的真实路径或项目内相对路径;不要编造路径。
50
+ - 脚本产生的**交付物**(报表、转换后的文件)要落到用户能找到的地方(项目目录或用户指定路径),并在回复里给出完整路径——scratch 目录是临时区,不是交付位置。
51
+ - 代码保持简单直接:能 20 行解决就不要写 100 行;不要引入与任务无关的"工程化"。
@@ -0,0 +1,30 @@
1
+ /**
2
+ * 内置 subagent_type 画像集(CC `.claude/agents` parity)。
3
+ *
4
+ * 桌面不再向 sidecar 传裸 `subagent: true`——命名画像让每个委派带
5
+ * 工具域 / 轮次上限 / 并发性 / 系统提示,模型按画像 description 选择
6
+ * 委派对象(画像名与用途经工具 schema 广告给模型)。
7
+ *
8
+ * 设计约束:
9
+ * - 画像的 toolFilter 引用的是桌面模型可见工具面(tool-router)里的
10
+ * 真实工具名;收窄即权限边界(explore 够不到写工具是构造性的)。
11
+ * - per-profile model 刻意不设:跟随父模型;模型路由留给设置面。
12
+ * - 画像系统提示是种进子 loop 的第一条 system 消息(子代理看不到
13
+ * 主对话的系统提示,画像提示就是它的全部角色设定)。
14
+ */
15
+ export interface BuiltinSubagentProfile {
16
+ toolFilter?: string[];
17
+ maxRounds?: number;
18
+ concurrent?: boolean;
19
+ description: string;
20
+ systemPrompt?: string;
21
+ }
22
+ export declare const BUILTIN_SUBAGENT_PROFILES: Record<string, BuiltinSubagentProfile>;
23
+ /**
24
+ * chat.stream 的 `subagent` 参数:内置画像集。调用方(普通回合与
25
+ * task-service 后台任务)共享同一份——任务回合的子代理画像与主对话
26
+ * 一致,编排语义不随入口分叉。
27
+ */
28
+ export declare function builtinSubagentParam(): {
29
+ profiles: Record<string, BuiltinSubagentProfile>;
30
+ };
@@ -0,0 +1,74 @@
1
+ /**
2
+ * 内置 subagent_type 画像集(CC `.claude/agents` parity)。
3
+ *
4
+ * 桌面不再向 sidecar 传裸 `subagent: true`——命名画像让每个委派带
5
+ * 工具域 / 轮次上限 / 并发性 / 系统提示,模型按画像 description 选择
6
+ * 委派对象(画像名与用途经工具 schema 广告给模型)。
7
+ *
8
+ * 设计约束:
9
+ * - 画像的 toolFilter 引用的是桌面模型可见工具面(tool-router)里的
10
+ * 真实工具名;收窄即权限边界(explore 够不到写工具是构造性的)。
11
+ * - per-profile model 刻意不设:跟随父模型;模型路由留给设置面。
12
+ * - 画像系统提示是种进子 loop 的第一条 system 消息(子代理看不到
13
+ * 主对话的系统提示,画像提示就是它的全部角色设定)。
14
+ */
15
+ /** 只读工具域:探索与调研画像共享的「摸不到写操作」基线。 */
16
+ const READ_ONLY_TOOLS = [
17
+ 'local_read_file',
18
+ 'local_list_scripts',
19
+ 'local_open_path',
20
+ 'web_search',
21
+ 'web_fetch',
22
+ 'mcp_list_tools',
23
+ ];
24
+ export const BUILTIN_SUBAGENT_PROFILES = {
25
+ explore: {
26
+ toolFilter: READ_ONLY_TOOLS,
27
+ maxRounds: 12,
28
+ concurrent: true,
29
+ description: '只读代码侦察。搜索、读文件、定位「在哪里/是什么」类问题;不做任何修改,返回带路径:行号的发现。',
30
+ systemPrompt: [
31
+ '你是只读探索代理,任务是在代码库中定位信息并汇报发现。',
32
+ '纪律:',
33
+ '1) 你的工具域只有只读工具——不要尝试修改、创建、删除任何文件;',
34
+ '2) 汇报必须具体:文件路径:行号、关键片段、明确结论;',
35
+ '3) 找不到就明说找不到,并列出你查过的位置——禁止猜测。',
36
+ ].join('\n'),
37
+ },
38
+ research: {
39
+ toolFilter: [...READ_ONLY_TOOLS, 'local_write_file'],
40
+ maxRounds: 16,
41
+ concurrent: true,
42
+ description: '深度调研。多轮 web 搜索/抓取并交叉验证,给出带来源 URL 的结论;可把报告写入文件。',
43
+ systemPrompt: [
44
+ '你是调研代理,任务是对一个问题做深度调研并给出可核验的结论。',
45
+ '纪律:',
46
+ '1) 每个事实性主张都必须来自真实抓取结果,并附来源 URL;',
47
+ '2) 至少两个独立来源交叉验证关键结论,来源冲突时并列呈现;',
48
+ '3) 需要交付长报告时用 local_write_file 落盘并在汇报中给出路径;',
49
+ '4) 查不到就明说,禁止编造来源或数据。',
50
+ ].join('\n'),
51
+ },
52
+ coder: {
53
+ // 不设 toolFilter:全工具域。写操作串行(concurrent: false),避免两个
54
+ // 实现代理同时改同一批文件。
55
+ maxRounds: 16,
56
+ concurrent: false,
57
+ description: '全工具实现代理。改代码、跑命令、自验结果;适合自包含的实现/修复任务。',
58
+ systemPrompt: [
59
+ '你是实现代理,接到的是自包含的实现任务。',
60
+ '纪律:',
61
+ '1) 直接动手:真实调用工具改代码/跑命令,不要用文本描述代替执行;',
62
+ '2) 完成后必须验证:跑相关测试或构建,把真实输出作为依据;',
63
+ '3) 汇报改动清单 + 验证结果 + 遗留风险,禁止编造工具返回。',
64
+ ].join('\n'),
65
+ },
66
+ };
67
+ /**
68
+ * chat.stream 的 `subagent` 参数:内置画像集。调用方(普通回合与
69
+ * task-service 后台任务)共享同一份——任务回合的子代理画像与主对话
70
+ * 一致,编排语义不随入口分叉。
71
+ */
72
+ export function builtinSubagentParam() {
73
+ return { profiles: BUILTIN_SUBAGENT_PROFILES };
74
+ }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * 后台任务的推理时间线:和主对话同一套 TurnBlock
3
+ * (reasoning / tools / text),供右侧过程面板渲染。
4
+ *
5
+ * 来源优先级(TaskService.getProcess):
6
+ * 1. 进程内正在跑的流(live)
7
+ * 2. 任务表 process_json(流过程中回写)
8
+ * 3. sidecar durable history(task:<id> 记录)——重启后仍能回看
9
+ */
10
+ import { type PersistedTurnBlock } from './turn-timeline.js';
11
+ export declare function timelineFromHistoryEntries(entries: unknown[]): PersistedTurnBlock[];
12
+ export declare function readSidecarHistoryEntries(recordId: string): unknown[];
@@ -0,0 +1,176 @@
1
+ /**
2
+ * 后台任务的推理时间线:和主对话同一套 TurnBlock
3
+ * (reasoning / tools / text),供右侧过程面板渲染。
4
+ *
5
+ * 来源优先级(TaskService.getProcess):
6
+ * 1. 进程内正在跑的流(live)
7
+ * 2. 任务表 process_json(流过程中回写)
8
+ * 3. sidecar durable history(task:<id> 记录)——重启后仍能回看
9
+ */
10
+ import Database from 'better-sqlite3';
11
+ import { resolveSidecarStoragePath } from '../sidecar/storage-path.js';
12
+ import { appendTimelineDelta, syncTimelineTools, } from './turn-timeline.js';
13
+ export function timelineFromHistoryEntries(entries) {
14
+ const blocks = [];
15
+ const actions = [];
16
+ for (const raw of entries) {
17
+ if (!raw || typeof raw !== 'object')
18
+ continue;
19
+ const entry = raw;
20
+ const kind = typeof entry.kind === 'string' ? entry.kind : '';
21
+ if (kind === 'system' ||
22
+ kind === 'user' ||
23
+ kind === 'world_state.snapshot' ||
24
+ kind === 'world_state.patch') {
25
+ continue;
26
+ }
27
+ const message = asRecord(entry.message);
28
+ if (!message)
29
+ continue;
30
+ const role = typeof message.role === 'string' ? message.role : kind;
31
+ if (role === 'assistant' || kind === 'assistant') {
32
+ const reasoning = messageReasoning(message);
33
+ if (reasoning)
34
+ appendTimelineDelta(blocks, 'reasoning', reasoning);
35
+ const text = messageText(message).trim();
36
+ if (text)
37
+ appendTimelineDelta(blocks, 'text', text);
38
+ const calls = messageToolCalls(message);
39
+ if (calls.length > 0) {
40
+ for (const call of calls)
41
+ actions.push(call);
42
+ syncTimelineTools(blocks, actions);
43
+ }
44
+ continue;
45
+ }
46
+ if (role === 'tool' || kind === 'tool') {
47
+ const resultText = messageText(message);
48
+ const parsed = parseToolPayload(resultText);
49
+ const name = typeof message.name === 'string'
50
+ ? message.name
51
+ : typeof parsed.name === 'string'
52
+ ? parsed.name
53
+ : 'tool';
54
+ const callId = (typeof message.tool_call_id === 'string' && message.tool_call_id) ||
55
+ (typeof message.toolCallId === 'string' && message.toolCallId) ||
56
+ null;
57
+ let idx = callId ? actions.findIndex((row) => row.id === callId) : -1;
58
+ if (idx < 0) {
59
+ idx = actions.findIndex((row) => row.tool === name && row.result === undefined);
60
+ }
61
+ const row = {
62
+ ...(idx >= 0 ? actions[idx] : { tool: name }),
63
+ tool: name,
64
+ result: parsed.data ?? parsed,
65
+ success: parsed.success !== false && parsed.error == null,
66
+ error: typeof parsed.error === 'string' ? parsed.error : undefined,
67
+ threw: false,
68
+ };
69
+ if (idx >= 0)
70
+ actions[idx] = row;
71
+ else
72
+ actions.push(row);
73
+ syncTimelineTools(blocks, actions);
74
+ }
75
+ }
76
+ return blocks;
77
+ }
78
+ export function readSidecarHistoryEntries(recordId) {
79
+ const dbPath = resolveSidecarStoragePath();
80
+ let db;
81
+ try {
82
+ db = new Database(dbPath, { readonly: true, fileMustExist: true });
83
+ }
84
+ catch {
85
+ return [];
86
+ }
87
+ try {
88
+ const rows = db
89
+ .prepare('SELECT data FROM history WHERE record_id = ? ORDER BY seq ASC')
90
+ .all(recordId);
91
+ const out = [];
92
+ for (const row of rows) {
93
+ try {
94
+ out.push(JSON.parse(row.data));
95
+ }
96
+ catch {
97
+ /* 坏行跳过 */
98
+ }
99
+ }
100
+ return out;
101
+ }
102
+ catch {
103
+ return [];
104
+ }
105
+ finally {
106
+ db.close();
107
+ }
108
+ }
109
+ function asRecord(value) {
110
+ return value && typeof value === 'object' ? value : null;
111
+ }
112
+ function messageText(message) {
113
+ const content = message.content;
114
+ if (typeof content === 'string')
115
+ return content;
116
+ if (!Array.isArray(content))
117
+ return '';
118
+ let text = '';
119
+ for (const part of content) {
120
+ const rec = asRecord(part);
121
+ if (!rec)
122
+ continue;
123
+ if (typeof rec.text === 'string')
124
+ text += rec.text;
125
+ }
126
+ return text;
127
+ }
128
+ function messageReasoning(message) {
129
+ for (const key of ['reasoning', 'reasoning_content', 'reasoningContent']) {
130
+ const value = message[key];
131
+ if (typeof value === 'string' && value.trim())
132
+ return value;
133
+ const rec = asRecord(value);
134
+ if (rec && typeof rec.text === 'string' && rec.text.trim())
135
+ return rec.text;
136
+ }
137
+ return '';
138
+ }
139
+ function messageToolCalls(message) {
140
+ const raw = message.tool_calls ?? message.toolCalls;
141
+ if (!Array.isArray(raw))
142
+ return [];
143
+ const calls = [];
144
+ for (const item of raw) {
145
+ const rec = asRecord(item);
146
+ if (!rec)
147
+ continue;
148
+ const name = typeof rec.name === 'string'
149
+ ? rec.name
150
+ : typeof asRecord(rec.function)?.name === 'string'
151
+ ? String(asRecord(rec.function).name)
152
+ : 'tool';
153
+ const args = rec.arguments ??
154
+ asRecord(rec.function)?.arguments ??
155
+ {};
156
+ calls.push({
157
+ id: typeof rec.id === 'string' ? rec.id : undefined,
158
+ tool: name,
159
+ arguments: typeof args === 'string' ? tryJson(args) ?? args : args,
160
+ threw: false,
161
+ });
162
+ }
163
+ return calls;
164
+ }
165
+ function parseToolPayload(text) {
166
+ const parsed = tryJson(text);
167
+ return asRecord(parsed) ?? { data: text };
168
+ }
169
+ function tryJson(text) {
170
+ try {
171
+ return JSON.parse(text);
172
+ }
173
+ catch {
174
+ return null;
175
+ }
176
+ }