@armadra/agent 0.3.0 → 0.5.0

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 (527) hide show
  1. package/CHANGELOG.md +257 -0
  2. package/README.md +263 -95
  3. package/THIRD_PARTY_NOTICES.md +34 -0
  4. package/dist/acp.d.ts +18 -0
  5. package/dist/acp.js +19 -0
  6. package/dist/agent/limits.d.ts +38 -0
  7. package/dist/agent/limits.js +127 -0
  8. package/dist/agent/loop-guard.d.ts +38 -0
  9. package/dist/agent/loop-guard.js +95 -0
  10. package/dist/agent/loop.d.ts +4 -0
  11. package/dist/agent/loop.js +7 -0
  12. package/dist/agent/prompt-rules.d.ts +12 -0
  13. package/dist/agent/prompt-rules.js +18 -0
  14. package/dist/agent/reminders.d.ts +59 -0
  15. package/dist/agent/reminders.js +327 -0
  16. package/dist/agent/retry.d.ts +1 -1
  17. package/dist/agent/retry.js +2 -1
  18. package/dist/agent/session-cache.d.ts +5 -0
  19. package/dist/agent/session-cache.js +18 -2
  20. package/dist/agent/session-classifier.d.ts +18 -0
  21. package/dist/agent/session-classifier.js +105 -0
  22. package/dist/agent/session-compaction.d.ts +35 -6
  23. package/dist/agent/session-compaction.js +157 -31
  24. package/dist/agent/session-core.d.ts +40 -1
  25. package/dist/agent/session-extensions.d.ts +61 -0
  26. package/dist/agent/session-extensions.js +129 -0
  27. package/dist/agent/session-images.d.ts +23 -0
  28. package/dist/agent/session-images.js +97 -0
  29. package/dist/agent/session-plan.d.ts +21 -0
  30. package/dist/agent/session-plan.js +524 -0
  31. package/dist/agent/session-rewind.d.ts +81 -0
  32. package/dist/agent/session-rewind.js +354 -0
  33. package/dist/agent/session-run.d.ts +28 -1
  34. package/dist/agent/session-run.js +157 -6
  35. package/dist/agent/session-settings.d.ts +49 -0
  36. package/dist/agent/session-settings.js +95 -0
  37. package/dist/agent/session-subagent.d.ts +36 -24
  38. package/dist/agent/session-subagent.js +259 -129
  39. package/dist/agent/session-sync.d.ts +10 -3
  40. package/dist/agent/session-sync.js +37 -8
  41. package/dist/agent/session-telemetry.d.ts +39 -0
  42. package/dist/agent/session-telemetry.js +231 -0
  43. package/dist/agent/session-tools.js +63 -3
  44. package/dist/agent/session.d.ts +33 -29
  45. package/dist/agent/session.js +91 -126
  46. package/dist/agent/subagent-registry.d.ts +91 -0
  47. package/dist/agent/subagent-registry.js +494 -0
  48. package/dist/agent/system-prompt.d.ts +6 -3
  49. package/dist/agent/system-prompt.js +7 -2
  50. package/dist/agent/tool-runner.d.ts +8 -1
  51. package/dist/agent/tool-runner.js +72 -6
  52. package/dist/agent/types-w5.d.ts +192 -0
  53. package/dist/agent/types-w5.js +10 -0
  54. package/dist/agent/types.d.ts +55 -4
  55. package/dist/agent/types.js +2 -0
  56. package/dist/agent/worktree.d.ts +36 -0
  57. package/dist/agent/worktree.js +86 -0
  58. package/dist/agents/builtin.d.ts +14 -0
  59. package/dist/agents/builtin.js +39 -0
  60. package/dist/agents/catalog.d.ts +43 -0
  61. package/dist/agents/catalog.js +82 -0
  62. package/dist/agents/discover.d.ts +35 -0
  63. package/dist/agents/discover.js +83 -0
  64. package/dist/agents/external.d.ts +82 -0
  65. package/dist/agents/external.js +326 -0
  66. package/dist/agents/parse.d.ts +18 -0
  67. package/dist/agents/parse.js +116 -0
  68. package/dist/agents/result.d.ts +32 -0
  69. package/dist/agents/result.js +67 -0
  70. package/dist/agents/task-control.d.ts +17 -0
  71. package/dist/agents/task-control.js +17 -0
  72. package/dist/agents/task-record.d.ts +78 -0
  73. package/dist/agents/task-record.js +141 -0
  74. package/dist/agents/types.d.ts +46 -0
  75. package/dist/agents/types.js +8 -0
  76. package/dist/ai/apis/anthropic-compat.d.ts +36 -0
  77. package/dist/ai/apis/anthropic-compat.js +92 -0
  78. package/dist/ai/apis/anthropic-messages.js +3 -2
  79. package/dist/ai/apis/anthropic-request.d.ts +7 -6
  80. package/dist/ai/apis/anthropic-request.js +10 -28
  81. package/dist/ai/apis/cache-params.d.ts +11 -2
  82. package/dist/ai/apis/cache-params.js +25 -6
  83. package/dist/ai/apis/google-generative-ai.js +3 -2
  84. package/dist/ai/apis/openai-compat.d.ts +4 -1
  85. package/dist/ai/apis/openai-compat.js +8 -1
  86. package/dist/ai/apis/openai-completions.js +3 -2
  87. package/dist/ai/apis/openai-responses.js +3 -2
  88. package/dist/ai/http.d.ts +28 -6
  89. package/dist/ai/http.js +41 -8
  90. package/dist/ai/image-limits.d.ts +45 -0
  91. package/dist/ai/image-limits.js +68 -0
  92. package/dist/ai/providers/builtin.d.ts +18 -6
  93. package/dist/ai/providers/builtin.js +135 -6
  94. package/dist/ai/providers/catalog-data.js +17 -13
  95. package/dist/ai/providers/catalog.d.ts +60 -7
  96. package/dist/ai/providers/catalog.js +197 -38
  97. package/dist/ai/providers/channels.d.ts +33 -3
  98. package/dist/ai/providers/channels.js +108 -7
  99. package/dist/ai/providers/enrich.d.ts +6 -3
  100. package/dist/ai/providers/enrich.js +19 -4
  101. package/dist/ai/providers/models-dev-cache.d.ts +28 -24
  102. package/dist/ai/providers/models-dev-cache.js +92 -78
  103. package/dist/ai/providers/models-dev-data.d.ts +7 -0
  104. package/dist/ai/providers/models-dev-data.js +32 -0
  105. package/dist/ai/providers/models-dev-snapshot.d.ts +50 -0
  106. package/dist/ai/providers/models-dev-snapshot.js +137 -0
  107. package/dist/ai/providers/models-dev.d.ts +51 -10
  108. package/dist/ai/providers/models-dev.js +132 -39
  109. package/dist/ai/providers/registry.d.ts +28 -11
  110. package/dist/ai/providers/registry.js +112 -65
  111. package/dist/ai/providers/suggest.d.ts +18 -0
  112. package/dist/ai/providers/suggest.js +72 -0
  113. package/dist/ai/sse.d.ts +6 -2
  114. package/dist/ai/sse.js +22 -2
  115. package/dist/ai/types.d.ts +37 -4
  116. package/dist/ai/types.js +5 -0
  117. package/dist/bundle/ama.cjs +41979 -21147
  118. package/dist/checkpoints/backend.d.ts +61 -0
  119. package/dist/checkpoints/backend.js +135 -0
  120. package/dist/checkpoints/blobs.d.ts +60 -0
  121. package/dist/checkpoints/blobs.js +203 -0
  122. package/dist/checkpoints/gc.d.ts +47 -0
  123. package/dist/checkpoints/gc.js +144 -0
  124. package/dist/checkpoints/git-head.d.ts +15 -0
  125. package/dist/checkpoints/git-head.js +89 -0
  126. package/dist/checkpoints/index.d.ts +17 -0
  127. package/dist/checkpoints/index.js +17 -0
  128. package/dist/checkpoints/replay.d.ts +48 -0
  129. package/dist/checkpoints/replay.js +154 -0
  130. package/dist/checkpoints/restore.d.ts +86 -0
  131. package/dist/checkpoints/restore.js +263 -0
  132. package/dist/checkpoints/settings.d.ts +14 -0
  133. package/dist/checkpoints/settings.js +23 -0
  134. package/dist/checkpoints/shadow-git.d.ts +108 -0
  135. package/dist/checkpoints/shadow-git.js +491 -0
  136. package/dist/checkpoints/shadow-restore.d.ts +25 -0
  137. package/dist/checkpoints/shadow-restore.js +128 -0
  138. package/dist/checkpoints/tracker.d.ts +64 -0
  139. package/dist/checkpoints/tracker.js +192 -0
  140. package/dist/checkpoints/types.d.ts +99 -0
  141. package/dist/checkpoints/types.js +12 -0
  142. package/dist/cli/args.d.ts +26 -7
  143. package/dist/cli/args.js +75 -82
  144. package/dist/cli/bootstrap.js +40 -4
  145. package/dist/cli/codemode-notice.d.ts +21 -0
  146. package/dist/cli/codemode-notice.js +56 -0
  147. package/dist/cli/compose-agents.d.ts +27 -0
  148. package/dist/cli/compose-agents.js +111 -0
  149. package/dist/cli/compose-extensions.d.ts +29 -0
  150. package/dist/cli/compose-extensions.js +44 -0
  151. package/dist/cli/compose-session.d.ts +8 -0
  152. package/dist/cli/compose-session.js +76 -2
  153. package/dist/cli/compose-store.d.ts +1 -1
  154. package/dist/cli/compose-store.js +3 -1
  155. package/dist/cli/compose.d.ts +17 -4
  156. package/dist/cli/compose.js +60 -14
  157. package/dist/cli/default-model.d.ts +38 -1
  158. package/dist/cli/default-model.js +96 -9
  159. package/dist/cli/deps.d.ts +42 -0
  160. package/dist/cli/exit-codes.d.ts +12 -0
  161. package/dist/cli/exit-codes.js +15 -0
  162. package/dist/cli/fake-visibility.d.ts +13 -0
  163. package/dist/cli/fake-visibility.js +26 -0
  164. package/dist/cli/from-prompt.d.ts +18 -0
  165. package/dist/cli/from-prompt.js +49 -0
  166. package/dist/cli/help-text.d.ts +4 -0
  167. package/dist/cli/help-text.js +102 -0
  168. package/dist/cli/main.d.ts +9 -2
  169. package/dist/cli/main.js +77 -3
  170. package/dist/cli/proxy.d.ts +51 -0
  171. package/dist/cli/proxy.js +135 -0
  172. package/dist/cli/startup-screen.d.ts +29 -0
  173. package/dist/cli/startup-screen.js +51 -2
  174. package/dist/cli/startup-steps.d.ts +1 -1
  175. package/dist/cli/startup-steps.js +21 -13
  176. package/dist/cli/subcommands/config.d.ts +22 -3
  177. package/dist/cli/subcommands/config.js +119 -21
  178. package/dist/cli/subcommands/context.js +4 -1
  179. package/dist/cli/subcommands/doctor.js +33 -1
  180. package/dist/cli/subcommands/init.js +2 -1
  181. package/dist/cli/subcommands/models-discover.d.ts +15 -9
  182. package/dist/cli/subcommands/models-discover.js +58 -52
  183. package/dist/cli/subcommands/models.d.ts +2 -0
  184. package/dist/cli/subcommands/models.js +33 -14
  185. package/dist/cli/subcommands/probe-runner.d.ts +96 -0
  186. package/dist/cli/subcommands/probe-runner.js +264 -0
  187. package/dist/cli/subcommands/providers-probe.d.ts +34 -0
  188. package/dist/cli/subcommands/providers-probe.js +87 -0
  189. package/dist/cli/subcommands/providers.d.ts +3 -2
  190. package/dist/cli/subcommands/providers.js +53 -51
  191. package/dist/cli/subcommands/sessions-export.d.ts +10 -0
  192. package/dist/cli/subcommands/sessions-export.js +59 -0
  193. package/dist/cli/subcommands/sessions-search.d.ts +13 -0
  194. package/dist/cli/subcommands/sessions-search.js +103 -0
  195. package/dist/cli/subcommands/sessions.d.ts +6 -3
  196. package/dist/cli/subcommands/sessions.js +58 -3
  197. package/dist/cli/subcommands/stats.d.ts +17 -0
  198. package/dist/cli/subcommands/stats.js +198 -0
  199. package/dist/cli/system-prompt-arg.d.ts +11 -0
  200. package/dist/cli/system-prompt-arg.js +34 -0
  201. package/dist/codemode/capability.d.ts +24 -7
  202. package/dist/codemode/capability.js +38 -10
  203. package/dist/codemode/host-side.d.ts +14 -0
  204. package/dist/codemode/host-side.js +24 -1
  205. package/dist/codemode/modes.d.ts +4 -11
  206. package/dist/codemode/modes.js +5 -27
  207. package/dist/codemode/tool.d.ts +18 -14
  208. package/dist/codemode/tool.js +76 -31
  209. package/dist/compaction/breaker.d.ts +25 -9
  210. package/dist/compaction/breaker.js +47 -17
  211. package/dist/compaction/estimate.d.ts +11 -3
  212. package/dist/compaction/estimate.js +64 -22
  213. package/dist/compaction/image-budget.d.ts +45 -0
  214. package/dist/compaction/image-budget.js +115 -0
  215. package/dist/compaction/post-compact.d.ts +38 -0
  216. package/dist/compaction/post-compact.js +152 -0
  217. package/dist/compaction/protect.d.ts +27 -0
  218. package/dist/compaction/protect.js +56 -0
  219. package/dist/compaction/prune-tier.d.ts +58 -12
  220. package/dist/compaction/prune-tier.js +120 -54
  221. package/dist/compaction/summarize-tier.d.ts +23 -4
  222. package/dist/compaction/summarize-tier.js +100 -29
  223. package/dist/config/checker.d.ts +28 -0
  224. package/dist/config/checker.js +97 -0
  225. package/dist/config/init.d.ts +6 -2
  226. package/dist/config/init.js +12 -5
  227. package/dist/config/json-schema.d.ts +1 -0
  228. package/dist/config/json-schema.js +98 -4
  229. package/dist/config/key-docs.d.ts +22 -0
  230. package/dist/config/key-docs.js +174 -0
  231. package/dist/config/merge.d.ts +12 -9
  232. package/dist/config/merge.js +102 -13
  233. package/dist/config/profile.d.ts +2 -0
  234. package/dist/config/profile.js +2 -0
  235. package/dist/config/schema-w5.d.ts +18 -0
  236. package/dist/config/schema-w5.js +109 -0
  237. package/dist/config/schema.d.ts +5 -9
  238. package/dist/config/schema.js +91 -118
  239. package/dist/config/types-w5.d.ts +118 -0
  240. package/dist/config/types-w5.js +20 -0
  241. package/dist/config/types.d.ts +84 -7
  242. package/dist/config/types.js +29 -1
  243. package/dist/drivers/acp/client.d.ts +57 -0
  244. package/dist/drivers/acp/client.js +160 -0
  245. package/dist/drivers/acp/driver.d.ts +31 -0
  246. package/dist/drivers/acp/driver.js +274 -0
  247. package/dist/drivers/acp/testing/fake-agent-main.d.ts +5 -0
  248. package/dist/drivers/acp/testing/fake-agent-main.js +7 -0
  249. package/dist/drivers/acp/testing/fake-agent.d.ts +27 -0
  250. package/dist/drivers/acp/testing/fake-agent.js +211 -0
  251. package/dist/drivers/acp/types.d.ts +285 -0
  252. package/dist/drivers/acp/types.js +36 -0
  253. package/dist/drivers/agents.d.ts +58 -0
  254. package/dist/drivers/agents.js +142 -0
  255. package/dist/drivers/base.d.ts +35 -0
  256. package/dist/drivers/base.js +59 -0
  257. package/dist/drivers/catalog.d.ts +46 -0
  258. package/dist/drivers/catalog.js +167 -0
  259. package/dist/drivers/env.d.ts +20 -0
  260. package/dist/drivers/env.js +46 -0
  261. package/dist/drivers/host-runners.d.ts +18 -0
  262. package/dist/drivers/host-runners.js +45 -0
  263. package/dist/drivers/jsonrpc.d.ts +58 -0
  264. package/dist/drivers/jsonrpc.js +180 -0
  265. package/dist/drivers/native/claude-normalize.d.ts +46 -0
  266. package/dist/drivers/native/claude-normalize.js +106 -0
  267. package/dist/drivers/native/claude-stream.d.ts +29 -0
  268. package/dist/drivers/native/claude-stream.js +456 -0
  269. package/dist/drivers/native/codex-app-server.d.ts +26 -0
  270. package/dist/drivers/native/codex-app-server.js +407 -0
  271. package/dist/drivers/native/codex-normalize.d.ts +38 -0
  272. package/dist/drivers/native/codex-normalize.js +124 -0
  273. package/dist/drivers/native/oneshot.d.ts +28 -0
  274. package/dist/drivers/native/oneshot.js +312 -0
  275. package/dist/drivers/permissions.d.ts +40 -0
  276. package/dist/drivers/permissions.js +92 -0
  277. package/dist/drivers/pids.d.ts +32 -0
  278. package/dist/drivers/pids.js +93 -0
  279. package/dist/drivers/pool.d.ts +28 -0
  280. package/dist/drivers/pool.js +96 -0
  281. package/dist/drivers/probe.d.ts +47 -0
  282. package/dist/drivers/probe.js +172 -0
  283. package/dist/drivers/process.d.ts +48 -0
  284. package/dist/drivers/process.js +100 -0
  285. package/dist/drivers/runner.d.ts +61 -0
  286. package/dist/drivers/runner.js +388 -0
  287. package/dist/drivers/store.d.ts +49 -0
  288. package/dist/drivers/store.js +91 -0
  289. package/dist/drivers/turn.d.ts +41 -0
  290. package/dist/drivers/turn.js +99 -0
  291. package/dist/drivers/types.d.ts +122 -0
  292. package/dist/drivers/types.js +11 -0
  293. package/dist/git/info.d.ts +75 -0
  294. package/dist/git/info.js +191 -0
  295. package/dist/hooks/protocol.js +6 -1
  296. package/dist/hooks/types.d.ts +10 -1
  297. package/dist/hooks/types.js +2 -0
  298. package/dist/host/api-impl.d.ts +7 -0
  299. package/dist/host/api-impl.js +15 -0
  300. package/dist/host/types.d.ts +24 -2
  301. package/dist/host/types.js +4 -0
  302. package/dist/index.d.ts +3 -0
  303. package/dist/index.js +1 -0
  304. package/dist/modes/acp/acp-events.d.ts +46 -0
  305. package/dist/modes/acp/acp-events.js +233 -0
  306. package/dist/modes/acp/acp-mode.d.ts +17 -0
  307. package/dist/modes/acp/acp-mode.js +47 -0
  308. package/dist/modes/acp/acp-server.d.ts +79 -0
  309. package/dist/modes/acp/acp-server.js +315 -0
  310. package/dist/modes/commands-core.d.ts +7 -1
  311. package/dist/modes/commands-core.js +61 -5
  312. package/dist/modes/image-input.d.ts +12 -4
  313. package/dist/modes/image-input.js +22 -5
  314. package/dist/modes/interactive/agent-panels.d.ts +14 -0
  315. package/dist/modes/interactive/agent-panels.js +103 -0
  316. package/dist/modes/interactive/agent-ui.d.ts +73 -0
  317. package/dist/modes/interactive/agent-ui.js +234 -0
  318. package/dist/modes/interactive/approval-dialog.d.ts +40 -7
  319. package/dist/modes/interactive/approval-dialog.js +192 -35
  320. package/dist/modes/interactive/approval-merge.d.ts +41 -0
  321. package/dist/modes/interactive/approval-merge.js +89 -0
  322. package/dist/modes/interactive/clipboard-paste.d.ts +18 -0
  323. package/dist/modes/interactive/clipboard-paste.js +28 -0
  324. package/dist/modes/interactive/commands.d.ts +20 -3
  325. package/dist/modes/interactive/commands.js +75 -16
  326. package/dist/modes/interactive/double-esc.d.ts +20 -0
  327. package/dist/modes/interactive/double-esc.js +34 -0
  328. package/dist/modes/interactive/event-notices.d.ts +32 -0
  329. package/dist/modes/interactive/event-notices.js +79 -0
  330. package/dist/modes/interactive/external-editor.d.ts +16 -0
  331. package/dist/modes/interactive/external-editor.js +39 -0
  332. package/dist/modes/interactive/interactive-mode.d.ts +16 -2
  333. package/dist/modes/interactive/interactive-mode.js +184 -202
  334. package/dist/modes/interactive/key-dispatch.d.ts +18 -2
  335. package/dist/modes/interactive/key-dispatch.js +53 -6
  336. package/dist/modes/interactive/line/line-mode.d.ts +3 -1
  337. package/dist/modes/interactive/line/line-mode.js +28 -9
  338. package/dist/modes/interactive/line/line-render.d.ts +6 -1
  339. package/dist/modes/interactive/line/line-render.js +66 -8
  340. package/dist/modes/interactive/message-view.d.ts +49 -10
  341. package/dist/modes/interactive/message-view.js +262 -46
  342. package/dist/modes/interactive/panels.d.ts +35 -0
  343. package/dist/modes/interactive/panels.js +157 -0
  344. package/dist/modes/interactive/pickers.d.ts +23 -2
  345. package/dist/modes/interactive/pickers.js +48 -15
  346. package/dist/modes/interactive/plan-command.d.ts +40 -0
  347. package/dist/modes/interactive/plan-command.js +129 -0
  348. package/dist/modes/interactive/plan-dialog.d.ts +98 -0
  349. package/dist/modes/interactive/plan-dialog.js +290 -0
  350. package/dist/modes/interactive/plan-flow.d.ts +34 -0
  351. package/dist/modes/interactive/plan-flow.js +98 -0
  352. package/dist/modes/interactive/rewind-command.d.ts +31 -0
  353. package/dist/modes/interactive/rewind-command.js +106 -0
  354. package/dist/modes/interactive/rewind-flow.d.ts +37 -0
  355. package/dist/modes/interactive/rewind-flow.js +151 -0
  356. package/dist/modes/interactive/rewind-list.d.ts +36 -0
  357. package/dist/modes/interactive/rewind-list.js +123 -0
  358. package/dist/modes/interactive/rewind-panel.d.ts +77 -0
  359. package/dist/modes/interactive/rewind-panel.js +309 -0
  360. package/dist/modes/interactive/rewind-text.d.ts +40 -0
  361. package/dist/modes/interactive/rewind-text.js +139 -0
  362. package/dist/modes/interactive/run-indicator.d.ts +51 -0
  363. package/dist/modes/interactive/run-indicator.js +189 -0
  364. package/dist/modes/interactive/session-events.d.ts +24 -0
  365. package/dist/modes/interactive/session-events.js +96 -0
  366. package/dist/modes/interactive/startup-header.d.ts +40 -0
  367. package/dist/modes/interactive/startup-header.js +169 -0
  368. package/dist/modes/interactive/status-area.d.ts +73 -0
  369. package/dist/modes/interactive/status-area.js +190 -0
  370. package/dist/modes/interactive/status-bar.d.ts +107 -16
  371. package/dist/modes/interactive/status-bar.js +306 -81
  372. package/dist/modes/interactive/status-line.d.ts +33 -0
  373. package/dist/modes/interactive/status-line.js +113 -0
  374. package/dist/modes/interactive/subagent-view.d.ts +56 -0
  375. package/dist/modes/interactive/subagent-view.js +154 -0
  376. package/dist/modes/interactive/tasks-report.d.ts +27 -0
  377. package/dist/modes/interactive/tasks-report.js +114 -0
  378. package/dist/modes/interactive/tool-summary.d.ts +46 -0
  379. package/dist/modes/interactive/tool-summary.js +218 -0
  380. package/dist/modes/interactive/tool-view.d.ts +58 -15
  381. package/dist/modes/interactive/tool-view.js +233 -145
  382. package/dist/modes/print/print-mode.d.ts +40 -4
  383. package/dist/modes/print/print-mode.js +161 -8
  384. package/dist/modes/rpc/commands.d.ts +9 -0
  385. package/dist/modes/rpc/commands.js +49 -0
  386. package/dist/modes/rpc/rpc-mode.js +7 -1
  387. package/dist/modes/session-report.d.ts +11 -0
  388. package/dist/modes/session-report.js +48 -1
  389. package/dist/permissions/auto-safe.d.ts +65 -0
  390. package/dist/permissions/auto-safe.js +547 -0
  391. package/dist/permissions/classifier.d.ts +68 -0
  392. package/dist/permissions/classifier.js +186 -0
  393. package/dist/permissions/dangerous.d.ts +5 -0
  394. package/dist/permissions/dangerous.js +1 -1
  395. package/dist/permissions/modes.d.ts +30 -0
  396. package/dist/permissions/modes.js +78 -0
  397. package/dist/permissions/pipeline.d.ts +72 -6
  398. package/dist/permissions/pipeline.js +306 -11
  399. package/dist/permissions/protected.d.ts +19 -0
  400. package/dist/permissions/protected.js +74 -0
  401. package/dist/permissions/readonly-bash.d.ts +30 -0
  402. package/dist/permissions/readonly-bash.js +118 -0
  403. package/dist/permissions/rules.js +3 -0
  404. package/dist/permissions/types.d.ts +92 -3
  405. package/dist/permissions/types.js +3 -0
  406. package/dist/plan/compose.d.ts +9 -0
  407. package/dist/plan/compose.js +19 -0
  408. package/dist/plan/controller.d.ts +71 -0
  409. package/dist/plan/controller.js +27 -0
  410. package/dist/plan/done-markers.d.ts +17 -0
  411. package/dist/plan/done-markers.js +51 -0
  412. package/dist/plan/extract.d.ts +29 -0
  413. package/dist/plan/extract.js +160 -0
  414. package/dist/plan/prompts.d.ts +36 -0
  415. package/dist/plan/prompts.js +89 -0
  416. package/dist/plan/store.d.ts +37 -0
  417. package/dist/plan/store.js +90 -0
  418. package/dist/rpc.d.ts +58 -2
  419. package/dist/rpc.js +7 -0
  420. package/dist/sandbox/bash.d.ts +74 -0
  421. package/dist/sandbox/bash.js +126 -0
  422. package/dist/sandbox/detect.d.ts +48 -0
  423. package/dist/sandbox/detect.js +149 -0
  424. package/dist/sandbox/index.d.ts +5 -0
  425. package/dist/sandbox/index.js +5 -0
  426. package/dist/sandbox/profile.d.ts +33 -0
  427. package/dist/sandbox/profile.js +76 -0
  428. package/dist/sandbox/wrap.d.ts +29 -0
  429. package/dist/sandbox/wrap.js +117 -0
  430. package/dist/sdk.d.ts +42 -5
  431. package/dist/sdk.js +34 -4
  432. package/dist/session/export.d.ts +32 -0
  433. package/dist/session/export.js +187 -0
  434. package/dist/session/redact.d.ts +15 -0
  435. package/dist/session/redact.js +55 -0
  436. package/dist/session/reuse.d.ts +33 -0
  437. package/dist/session/reuse.js +86 -0
  438. package/dist/session/scan.d.ts +34 -0
  439. package/dist/session/scan.js +140 -0
  440. package/dist/session/search.d.ts +52 -0
  441. package/dist/session/search.js +211 -0
  442. package/dist/session/stats-aggregate.d.ts +63 -0
  443. package/dist/session/stats-aggregate.js +163 -0
  444. package/dist/session/stats-index.d.ts +26 -0
  445. package/dist/session/stats-index.js +91 -0
  446. package/dist/session/stats-scan.d.ts +54 -0
  447. package/dist/session/stats-scan.js +236 -0
  448. package/dist/session/types.d.ts +3 -1
  449. package/dist/session/types.js +1 -0
  450. package/dist/skills/builtin.d.ts +31 -0
  451. package/dist/skills/builtin.js +109 -0
  452. package/dist/skills/discover.d.ts +2 -1
  453. package/dist/skills/index-prompt.js +5 -8
  454. package/dist/tools/background-jobs.d.ts +71 -0
  455. package/dist/tools/background-jobs.js +198 -0
  456. package/dist/tools/bash.d.ts +53 -1
  457. package/dist/tools/bash.js +158 -7
  458. package/dist/tools/clipboard-image.d.ts +44 -0
  459. package/dist/tools/clipboard-image.js +148 -0
  460. package/dist/tools/edit.d.ts +2 -0
  461. package/dist/tools/edit.js +18 -3
  462. package/dist/tools/image-file.d.ts +38 -3
  463. package/dist/tools/image-file.js +81 -10
  464. package/dist/tools/image-resize.d.ts +58 -0
  465. package/dist/tools/image-resize.js +97 -0
  466. package/dist/tools/presets.d.ts +40 -8
  467. package/dist/tools/presets.js +65 -19
  468. package/dist/tools/read.d.ts +5 -2
  469. package/dist/tools/read.js +13 -10
  470. package/dist/tools/registry.d.ts +7 -1
  471. package/dist/tools/registry.js +27 -4
  472. package/dist/tools/task-ctl.d.ts +22 -0
  473. package/dist/tools/task-ctl.js +116 -0
  474. package/dist/tools/task.d.ts +22 -10
  475. package/dist/tools/task.js +66 -26
  476. package/dist/tools/todo.d.ts +22 -2
  477. package/dist/tools/todo.js +58 -14
  478. package/dist/tools/truncate.d.ts +15 -0
  479. package/dist/tools/truncate.js +25 -0
  480. package/dist/tools/types.d.ts +113 -0
  481. package/dist/tools/types.js +5 -0
  482. package/dist/tools/write.js +3 -0
  483. package/dist/tui/component.d.ts +8 -2
  484. package/dist/tui/component.js +3 -1
  485. package/dist/tui/components/box.d.ts +6 -1
  486. package/dist/tui/components/box.js +16 -6
  487. package/dist/tui/components/card.d.ts +23 -0
  488. package/dist/tui/components/card.js +37 -0
  489. package/dist/tui/components/editor-history.d.ts +6 -0
  490. package/dist/tui/components/editor-history.js +45 -0
  491. package/dist/tui/components/editor-paste.d.ts +1 -1
  492. package/dist/tui/components/editor-paste.js +4 -4
  493. package/dist/tui/components/editor.d.ts +11 -5
  494. package/dist/tui/components/editor.js +52 -58
  495. package/dist/tui/components/key-value.d.ts +3 -0
  496. package/dist/tui/components/key-value.js +16 -6
  497. package/dist/tui/components/loader.d.ts +37 -7
  498. package/dist/tui/components/loader.js +84 -21
  499. package/dist/tui/components/markdown.d.ts +5 -1
  500. package/dist/tui/components/markdown.js +45 -21
  501. package/dist/tui/components/meter.d.ts +3 -3
  502. package/dist/tui/components/meter.js +13 -11
  503. package/dist/tui/components/select-list.d.ts +23 -1
  504. package/dist/tui/components/select-list.js +76 -13
  505. package/dist/tui/glyphs.d.ts +72 -0
  506. package/dist/tui/glyphs.js +118 -0
  507. package/dist/tui/keybindings.d.ts +5 -0
  508. package/dist/tui/keybindings.js +5 -0
  509. package/dist/tui/theme.d.ts +30 -6
  510. package/dist/tui/theme.js +103 -17
  511. package/dist/tui.d.ts +4 -2
  512. package/dist/tui.js +3 -1
  513. package/docs/acp.md +78 -0
  514. package/docs/agents.md +250 -0
  515. package/docs/codemode.md +28 -10
  516. package/docs/hooks.md +36 -32
  517. package/docs/permissions.md +212 -0
  518. package/docs/plan.md +107 -0
  519. package/docs/providers.md +261 -62
  520. package/docs/rewind-plan.md +181 -0
  521. package/docs/rpc.md +127 -40
  522. package/docs/sandbox.md +215 -0
  523. package/docs/session-format.md +43 -22
  524. package/docs/sessions.md +174 -0
  525. package/docs/tui-design.md +751 -0
  526. package/docs/tui.md +260 -64
  527. package/package.json +15 -2
@@ -0,0 +1,154 @@
1
+ /**
2
+ * 消息区的子 Agent 折叠视图(docs/wave5-plan.md §7.5)。[W5-U]
3
+ *
4
+ * 消费 `subagent_start / update / end`,按 taskId 记下类型、状态、轮数、最近 3 个工具与用量;task 工具行
5
+ * (tool-view.ts)据 `parentToolCallId` 取来显示一行:
6
+ *
7
+ * ```
8
+ * ⏺ task 检查 src/tui 的测试覆盖缺口
9
+ * ⎿ ⠋ explore · 运行中 1m05s · 3 轮 · read grep bash · ↑12k ↓3.4k
10
+ * ```
11
+ *
12
+ * 后台任务的工具调用立即返回,工具行下面多一行跟随状态(`↳ t2 explore · 完成 · 7 轮 …`,运行中每秒刷新);
13
+ * 完成后父会话收到的 `<task-notification>` 只显示一行(`notificationSummary`),失败 / 停止另有一行提示。
14
+ * 外部 runner(claude / codex)同一组事件,用量可能缺。
15
+ */
16
+ import { formatElapsed } from "../../tui.js";
17
+ import { formatTokenCount } from "../session-report.js";
18
+ import { taskStatusText } from "./tasks-report.js";
19
+ export const RECENT_TOOLS = 3;
20
+ export class SubagentTracker {
21
+ now;
22
+ tasks = new Map();
23
+ byCall = new Map();
24
+ constructor(now = Date.now) {
25
+ this.now = now;
26
+ }
27
+ /** 子 Agent 事件:更新状态并返回它;其它事件返回 undefined。 */
28
+ onEvent(event) {
29
+ switch (event.type) {
30
+ case "subagent_start": {
31
+ const previous = this.tasks.get(event.taskId);
32
+ const state = {
33
+ taskId: event.taskId,
34
+ parentToolCallId: event.parentToolCallId,
35
+ agent: event.agent,
36
+ runner: event.runner,
37
+ background: event.background,
38
+ status: "running",
39
+ // 续聊(同一 taskId 再次 start)沿用轮数与工具
40
+ turns: previous?.turns ?? 0,
41
+ tools: previous?.tools ?? [],
42
+ startedAt: this.now(),
43
+ };
44
+ this.tasks.set(event.taskId, state);
45
+ this.byCall.set(event.parentToolCallId, event.taskId);
46
+ return state;
47
+ }
48
+ case "subagent_update": {
49
+ const state = this.tasks.get(event.taskId);
50
+ if (state === undefined)
51
+ return undefined;
52
+ if (event.turn > state.turns)
53
+ state.turns = event.turn;
54
+ if (event.usage !== undefined)
55
+ state.usage = event.usage;
56
+ if (event.kind === "tool" && event.toolName !== undefined) {
57
+ state.tools.push(event.toolName);
58
+ if (state.tools.length > RECENT_TOOLS)
59
+ state.tools.splice(0, state.tools.length - RECENT_TOOLS);
60
+ }
61
+ return state;
62
+ }
63
+ case "subagent_end": {
64
+ const state = this.tasks.get(event.taskId);
65
+ if (state === undefined)
66
+ return undefined;
67
+ state.status = event.status;
68
+ state.endedAt = this.now();
69
+ if (event.usage !== undefined)
70
+ state.usage = event.usage;
71
+ return state;
72
+ }
73
+ default:
74
+ return undefined;
75
+ }
76
+ }
77
+ /** 运行中的任务。 */
78
+ running() {
79
+ return [...this.tasks.values()].filter((state) => state.status === "running");
80
+ }
81
+ get(taskId) {
82
+ return this.tasks.get(taskId);
83
+ }
84
+ /** task 工具调用对应的子 Agent(续聊时是同一 taskId)。 */
85
+ forToolCall(toolCallId) {
86
+ const taskId = this.byCall.get(toolCallId);
87
+ return taskId === undefined ? undefined : this.tasks.get(taskId);
88
+ }
89
+ clear() {
90
+ this.tasks.clear();
91
+ this.byCall.clear();
92
+ }
93
+ }
94
+ /** `explore · 运行中 1m05s · 3 轮 · read grep bash · ↑12k ↓3.4k`(已着色:类型 tool 色,其余 muted)。 */
95
+ export function subagentLine(state, theme, now) {
96
+ const g = theme.glyphs;
97
+ const end = state.endedAt ?? now;
98
+ const elapsed = formatElapsed(end - state.startedAt);
99
+ const status = state.status === "running" ? `运行中 ${elapsed}` : `${taskStatusText(state.status)} ${elapsed}`;
100
+ const facts = [status];
101
+ if (state.turns > 0)
102
+ facts.push(`${state.turns} 轮`);
103
+ if (state.tools.length > 0)
104
+ facts.push(state.tools.join(" "));
105
+ const usage = state.usage;
106
+ if (usage !== undefined && usage.input + usage.output + usage.cacheRead > 0) {
107
+ const input = usage.input + usage.cacheRead + usage.cacheWrite;
108
+ facts.push(`${g.arrowUp}${formatTokenCount(input)} ${g.arrowDown}${formatTokenCount(usage.output)}`);
109
+ }
110
+ const color = state.status === "running" || state.status === "completed"
111
+ ? "muted"
112
+ : state.status === "failed"
113
+ ? "error"
114
+ : "warning";
115
+ const agent = state.runner !== "ama" && state.runner !== state.agent
116
+ ? `${state.agent}(${state.runner})`
117
+ : state.agent;
118
+ return theme.fg("tool", agent) + theme.fg("dim", " · ") + theme.fg(color, facts.join(" · "));
119
+ }
120
+ /** 后台任务结束的一行提示。 */
121
+ export function backgroundEndText(state) {
122
+ const turns = state.turns > 0 ? ` · ${state.turns} 轮` : "";
123
+ return `后台任务 ${state.taskId}(${state.agent})${taskStatusText(state.status)}${turns} · /tasks 查看输出`;
124
+ }
125
+ /**
126
+ * 父会话收到的 `<task-notification …>`(origin `task` 的用户消息)在消息区只显示一行:
127
+ * `t1 explore 完成 · 7 轮 · /tasks 查看输出`;不是通知格式返回 undefined。
128
+ */
129
+ export function notificationSummary(text) {
130
+ const head = /^<task-notification\s+([^>]*)>/.exec(text.trimStart());
131
+ if (head === null)
132
+ return undefined;
133
+ const attrs = new Map();
134
+ for (const m of (head[1] ?? "").matchAll(/(\w+)="([^"]*)"/g))
135
+ attrs.set(m[1], m[2]);
136
+ const taskId = attrs.get("taskId") ?? "?";
137
+ const status = attrs.get("status");
138
+ const parts = [
139
+ `${taskId} ${attrs.get("agent") ?? ""}`.trim() +
140
+ ` ${status !== undefined && status in STATUS_KEYS ? taskStatusText(status) : (status ?? "")}`,
141
+ ];
142
+ const turns = attrs.get("turns");
143
+ if (turns !== undefined)
144
+ parts.push(`${turns} 轮`);
145
+ parts.push("/tasks 查看输出");
146
+ return parts.join(" · ");
147
+ }
148
+ const STATUS_KEYS = {
149
+ completed: true,
150
+ failed: true,
151
+ aborted: true,
152
+ max_turns: true,
153
+ interrupted: true,
154
+ };
@@ -0,0 +1,27 @@
1
+ /**
2
+ * `/tasks`、`/agents` 的数据与文本(line 模式与交互模式共用)。[W5-U]
3
+ *
4
+ * - 任务:`taskRegistryView(sessionId).list()`(子 Agent 注册表,W5-G);全文 `registryOf(sessionId).output()`;
5
+ * 停止 `registryOf(sessionId).stop()`。
6
+ * - 类型:`cachedAgentInfos(sessionId) ?? sessionAgents(sessionId)`(外部 Agent 带安装状态与版本,W5-EG)。
7
+ */
8
+ import type { AgentInfo } from "../../agents/types.js";
9
+ import type { SubagentStatus, TaskInfo } from "../../tools/types.js";
10
+ export declare function taskStatusText(status: SubagentStatus | "running"): string;
11
+ export declare function listTasks(sessionId: string): readonly TaskInfo[];
12
+ export declare function listAgents(sessionId: string): AgentInfo[];
13
+ /** 运行中是已有输出,结束后是最终文本。 */
14
+ export declare function taskOutput(sessionId: string, taskId: string): string | undefined;
15
+ export declare function stopTask(sessionId: string, taskId: string): Promise<void>;
16
+ /** 任务一行的各字段(状态、耗时、轮数、用量、费用)。 */
17
+ export declare function taskFacts(task: TaskInfo, now: number): string[];
18
+ /** `t1 explore · 运行中 · 1m05s · 7 轮 · 描述` */
19
+ export declare function taskLine(task: TaskInfo, now: number): string;
20
+ /** `/tasks` 的纯文本(line 模式)。 */
21
+ export declare function describeTasks(sessionId: string, now: number): string;
22
+ /** 一个任务的输出全文(line 模式 `/tasks <id>`)。 */
23
+ export declare function describeTaskOutput(sessionId: string, taskId: string, now: number): string;
24
+ /** 类型一行的状态:外部 Agent 写安装与版本。 */
25
+ export declare function agentFacts(agent: AgentInfo): string[];
26
+ /** `/agents` 的纯文本(line 模式)。 */
27
+ export declare function describeAgents(sessionId: string): string;
@@ -0,0 +1,114 @@
1
+ /**
2
+ * `/tasks`、`/agents` 的数据与文本(line 模式与交互模式共用)。[W5-U]
3
+ *
4
+ * - 任务:`taskRegistryView(sessionId).list()`(子 Agent 注册表,W5-G);全文 `registryOf(sessionId).output()`;
5
+ * 停止 `registryOf(sessionId).stop()`。
6
+ * - 类型:`cachedAgentInfos(sessionId) ?? sessionAgents(sessionId)`(外部 Agent 带安装状态与版本,W5-EG)。
7
+ */
8
+ import { cachedAgentInfos } from "../../agents/external.js";
9
+ import { registryOf, sessionAgents, taskRegistryView } from "../../agent/subagent-registry.js";
10
+ import { formatTokenCount, formatUsd } from "../session-report.js";
11
+ import { formatDuration } from "./tool-summary.js";
12
+ const STATUS = {
13
+ running: "运行中",
14
+ completed: "完成",
15
+ failed: "失败",
16
+ aborted: "已停止",
17
+ max_turns: "轮数耗尽",
18
+ interrupted: "已中断",
19
+ };
20
+ export function taskStatusText(status) {
21
+ return STATUS[status];
22
+ }
23
+ export function listTasks(sessionId) {
24
+ return taskRegistryView(sessionId)?.list() ?? [];
25
+ }
26
+ export function listAgents(sessionId) {
27
+ return cachedAgentInfos(sessionId) ?? sessionAgents(sessionId);
28
+ }
29
+ /** 运行中是已有输出,结束后是最终文本。 */
30
+ export function taskOutput(sessionId, taskId) {
31
+ return registryOf(sessionId)?.output(taskId);
32
+ }
33
+ export async function stopTask(sessionId, taskId) {
34
+ const registry = registryOf(sessionId);
35
+ if (registry === undefined)
36
+ return;
37
+ await registry.stop(taskId);
38
+ }
39
+ /** 任务一行的各字段(状态、耗时、轮数、用量、费用)。 */
40
+ export function taskFacts(task, now) {
41
+ const end = task.endedAt ?? now;
42
+ const facts = [taskStatusText(task.status), formatDuration(end - task.startedAt)];
43
+ if (task.turns !== undefined && task.turns > 0)
44
+ facts.push(`${task.turns} 轮`);
45
+ const usage = task.usage;
46
+ if (usage !== undefined && usage.input + usage.output + usage.cacheRead > 0)
47
+ facts.push(`↑${formatTokenCount(usage.input + usage.cacheRead + usage.cacheWrite)} ↓${formatTokenCount(usage.output)}`);
48
+ if (task.costUsd !== undefined && task.costUsd > 0)
49
+ facts.push(formatUsd(task.costUsd));
50
+ return facts;
51
+ }
52
+ function oneLine(text, max = 60) {
53
+ const flat = text.replace(/\s+/g, " ").trim();
54
+ return flat.length > max ? `${flat.slice(0, max - 1)}…` : flat;
55
+ }
56
+ /** `t1 explore · 运行中 · 1m05s · 7 轮 · 描述` */
57
+ export function taskLine(task, now) {
58
+ const agent = task.runner !== "ama" && task.runner !== task.agent
59
+ ? `${task.agent}(${task.runner})`
60
+ : task.agent;
61
+ const parts = [agent, ...taskFacts(task, now)];
62
+ if (task.background)
63
+ parts.push("后台");
64
+ const description = oneLine(task.description);
65
+ return `${task.taskId} ${parts.join(" · ")}${description !== "" ? ` ${description}` : ""}`;
66
+ }
67
+ /** `/tasks` 的纯文本(line 模式)。 */
68
+ export function describeTasks(sessionId, now) {
69
+ const tasks = listTasks(sessionId);
70
+ if (tasks.length === 0)
71
+ return "还没有子 Agent 任务";
72
+ return [
73
+ `子 Agent 任务(${tasks.length}):`,
74
+ ...tasks.map((task) => ` ${taskLine(task, now)}`),
75
+ "/tasks <id> 查看输出 · /tasks stop <id> 停止",
76
+ ].join("\n");
77
+ }
78
+ /** 一个任务的输出全文(line 模式 `/tasks <id>`)。 */
79
+ export function describeTaskOutput(sessionId, taskId, now) {
80
+ const task = taskRegistryView(sessionId)?.get(taskId);
81
+ if (task === undefined)
82
+ return `没有任务 ${taskId}`;
83
+ const output = taskOutput(sessionId, taskId) ?? "";
84
+ const file = task.outputFile !== undefined ? `\n全文:${task.outputFile}` : "";
85
+ return `${taskLine(task, now)}${file}\n${output.trim() === "" ? "(还没有输出)" : output.trimEnd()}`;
86
+ }
87
+ const SOURCE = {
88
+ builtin: "内置",
89
+ cli: "命令行",
90
+ profile: "profile",
91
+ user: "用户",
92
+ project: "项目",
93
+ host: "宿主",
94
+ };
95
+ /** 类型一行的状态:外部 Agent 写安装与版本。 */
96
+ export function agentFacts(agent) {
97
+ const facts = [agent.runner, SOURCE[agent.source] ?? agent.source];
98
+ if (agent.installed === false)
99
+ facts.push("未安装");
100
+ else if (agent.installed === true)
101
+ facts.push(agent.version !== undefined ? `已安装 ${agent.version}` : "已安装");
102
+ return facts;
103
+ }
104
+ /** `/agents` 的纯文本(line 模式)。 */
105
+ export function describeAgents(sessionId) {
106
+ const agents = listAgents(sessionId);
107
+ if (agents.length === 0)
108
+ return "当前会话没有子 Agent(task 工具未启用)";
109
+ const width = Math.max(...agents.map((a) => a.name.length));
110
+ return [
111
+ `子 Agent 类型(${agents.length}):`,
112
+ ...agents.map((a) => ` ${a.name.padEnd(width)} ${agentFacts(a).join(" · ")} ${oneLine(a.description)}`),
113
+ ].join("\n");
114
+ }
@@ -0,0 +1,46 @@
1
+ /**
2
+ * 工具调用的文字摘要(终端界面视觉设计 v1 §3.5):标题行的参数摘要、`⎿` 后的一行结果摘要、
3
+ * 统一 diff 解析与输出清洗。纯函数,ToolView 负责排版与着色之外的状态。
4
+ *
5
+ * 结果摘要(完成后):
6
+ * - read `读取 N 行`(图片 `图片 mime`、空文件 `空文件`);edit `N 处修改 · +a −b`;write `新建 / 覆盖 · N 行`;
7
+ * - bash `退出 c · 耗时 · N 行`(超时 `超时 · 耗时`、中断 `已中断 · 耗时`);
8
+ * - grep `N 处匹配 · M 个文件`;glob `N 个文件`;codemode `N 个内层调用 · 脚本输出 M 行`;
9
+ * - task `完成 · 耗时 · ↑in ↓out`;其它 `N 行输出`;失败(非 bash)取错误首行。
10
+ */
11
+ import type { ToolResult } from "../../tools/types.js";
12
+ import { type Theme } from "../../tui.js";
13
+ /** 工具输出 → 可安全显示的行。 */
14
+ export declare function cleanLines(text: string): string[];
15
+ export declare function flat(text: string, max?: number): string;
16
+ export declare function displayPath(path: string, cwd: string | undefined): string;
17
+ /** 标题行里的参数摘要。 */
18
+ export declare function toolSummary(name: string, args: unknown, cwd?: string): string;
19
+ /** 完成耗时:< 10s 一位小数(`2.1s`),< 60s 整秒,再长 `1m05s`。 */
20
+ export declare function formatDuration(ms: number): string;
21
+ export interface DiffRow {
22
+ kind: "hunk" | "add" | "del" | "ctx";
23
+ /** 原行(含 `+` / `-` / ` ` 前缀)。 */
24
+ text: string;
25
+ /** 行号:删除行取旧号,其余取新号;hunk 行没有。 */
26
+ num?: number;
27
+ }
28
+ /** 统一 diff → 行(去掉 `---` / `+++` 文件头),带行号。 */
29
+ export declare function parseDiff(diff: string): DiffRow[];
30
+ export declare function diffOf(result: ToolResult | undefined): string | undefined;
31
+ /** bash 完成后的正文:优先 `details.output`(不含退出码等附注)。 */
32
+ export declare function bashOutput(result: ToolResult): string | undefined;
33
+ export interface SummaryInput {
34
+ name: string;
35
+ args: unknown;
36
+ result: ToolResult;
37
+ isError: boolean;
38
+ /** 结果正文(已清洗)。 */
39
+ lines: readonly string[];
40
+ /** 完成耗时(ms);重放的历史调用没有,bash 取 `details.wall_time_seconds`。 */
41
+ elapsedMs: number | undefined;
42
+ /** 已显示的内层调用数(codemode 没有 details 时用)。 */
43
+ nestedCount?: number;
44
+ }
45
+ /** 完成后的一行结果摘要(已着色,不含 `⎿`)。 */
46
+ export declare function resultSummary(input: SummaryInput, theme: Theme): string;
@@ -0,0 +1,218 @@
1
+ /**
2
+ * 工具调用的文字摘要(终端界面视觉设计 v1 §3.5):标题行的参数摘要、`⎿` 后的一行结果摘要、
3
+ * 统一 diff 解析与输出清洗。纯函数,ToolView 负责排版与着色之外的状态。
4
+ *
5
+ * 结果摘要(完成后):
6
+ * - read `读取 N 行`(图片 `图片 mime`、空文件 `空文件`);edit `N 处修改 · +a −b`;write `新建 / 覆盖 · N 行`;
7
+ * - bash `退出 c · 耗时 · N 行`(超时 `超时 · 耗时`、中断 `已中断 · 耗时`);
8
+ * - grep `N 处匹配 · M 个文件`;glob `N 个文件`;codemode `N 个内层调用 · 脚本输出 M 行`;
9
+ * - task `完成 · 耗时 · ↑in ↓out`;其它 `N 行输出`;失败(非 bash)取错误首行。
10
+ */
11
+ import { isAbsolute, relative } from "node:path";
12
+ import { stripAnsi } from "../../tui.js";
13
+ import { formatTokens } from "./status-bar.js";
14
+ /** 工具输出 → 可安全显示的行。 */
15
+ export function cleanLines(text) {
16
+ const clean = stripAnsi(text)
17
+ .replace(/\r\n?/g, "\n")
18
+ .replace(/\t/g, " ")
19
+ .replace(/[\x00-\x08\x0b-\x1f\x7f]/g, "");
20
+ const lines = clean.split("\n");
21
+ while (lines.length > 0 && lines[lines.length - 1].trim() === "")
22
+ lines.pop();
23
+ return lines;
24
+ }
25
+ export function flat(text, max = 120) {
26
+ const one = text.replace(/\s*\n\s*/g, " ⏎ ").trim();
27
+ return one.length > max ? `${one.slice(0, max - 1)}…` : one;
28
+ }
29
+ export function displayPath(path, cwd) {
30
+ if (cwd === undefined || !isAbsolute(path))
31
+ return path;
32
+ const rel = relative(cwd, path);
33
+ return rel === "" ? "." : rel.startsWith("..") || isAbsolute(rel) ? path : rel;
34
+ }
35
+ /** 标题行里的参数摘要。 */
36
+ export function toolSummary(name, args, cwd) {
37
+ if (typeof args !== "object" || args === null)
38
+ return "";
39
+ const a = args;
40
+ const str = (key) => typeof a[key] === "string" && a[key] !== "" ? a[key] : undefined;
41
+ const path = str("path") ?? str("file_path");
42
+ switch (name) {
43
+ case "bash":
44
+ return flat(str("command") ?? "");
45
+ case "read": {
46
+ if (path === undefined)
47
+ return "";
48
+ const offset = typeof a["offset"] === "number" ? a["offset"] : undefined;
49
+ const limit = typeof a["limit"] === "number" ? a["limit"] : undefined;
50
+ const range = offset !== undefined || limit !== undefined
51
+ ? `:${offset ?? 1}${limit !== undefined ? `+${limit}` : ""}`
52
+ : "";
53
+ return displayPath(path, cwd) + range;
54
+ }
55
+ case "grep":
56
+ case "glob": {
57
+ const pattern = str("pattern") ?? "";
58
+ return path !== undefined ? `${flat(pattern)} in ${displayPath(path, cwd)}` : flat(pattern);
59
+ }
60
+ case "task":
61
+ return flat(str("description") ?? str("prompt") ?? "");
62
+ default:
63
+ if (path !== undefined)
64
+ return displayPath(path, cwd);
65
+ for (const key of [
66
+ "command",
67
+ "pattern",
68
+ "description",
69
+ "query",
70
+ "url",
71
+ "name",
72
+ "code",
73
+ "script",
74
+ ]) {
75
+ const value = str(key);
76
+ if (value !== undefined)
77
+ return flat(value);
78
+ }
79
+ return "";
80
+ }
81
+ }
82
+ /** 完成耗时:< 10s 一位小数(`2.1s`),< 60s 整秒,再长 `1m05s`。 */
83
+ export function formatDuration(ms) {
84
+ const s = Math.max(0, ms) / 1000;
85
+ if (s < 10)
86
+ return `${s.toFixed(1)}s`;
87
+ if (s < 60)
88
+ return `${Math.floor(s)}s`;
89
+ const total = Math.floor(s);
90
+ return `${Math.floor(total / 60)}m${String(total % 60).padStart(2, "0")}s`;
91
+ }
92
+ /** 统一 diff → 行(去掉 `---` / `+++` 文件头),带行号。 */
93
+ export function parseDiff(diff) {
94
+ const rows = [];
95
+ let oldNo = 0;
96
+ let newNo = 0;
97
+ for (const line of cleanLines(diff)) {
98
+ if (line.startsWith("---") || line.startsWith("+++"))
99
+ continue;
100
+ const hunk = /^@@ -(\d+)(?:,\d+)? \+(\d+)(?:,\d+)? @@/.exec(line);
101
+ if (hunk) {
102
+ oldNo = Number(hunk[1]);
103
+ newNo = Number(hunk[2]);
104
+ rows.push({ kind: "hunk", text: line });
105
+ }
106
+ else if (line.startsWith("+"))
107
+ rows.push({ kind: "add", text: line, num: newNo++ });
108
+ else if (line.startsWith("-"))
109
+ rows.push({ kind: "del", text: line, num: oldNo++ });
110
+ else if (line.startsWith("@@"))
111
+ rows.push({ kind: "hunk", text: line });
112
+ else {
113
+ rows.push({ kind: "ctx", text: line, num: newNo });
114
+ oldNo++;
115
+ newNo++;
116
+ }
117
+ }
118
+ return rows;
119
+ }
120
+ function record(value) {
121
+ return typeof value === "object" && value !== null ? value : {};
122
+ }
123
+ function num(value) {
124
+ return typeof value === "number" && Number.isFinite(value) ? value : undefined;
125
+ }
126
+ export function diffOf(result) {
127
+ const diff = record(result?.details)["diff"];
128
+ return typeof diff === "string" && diff !== "" ? diff : undefined;
129
+ }
130
+ /** bash 完成后的正文:优先 `details.output`(不含退出码等附注)。 */
131
+ export function bashOutput(result) {
132
+ const output = record(result.details)["output"];
133
+ return typeof output === "string" ? output : undefined;
134
+ }
135
+ /** 完成后的一行结果摘要(已着色,不含 `⎿`)。 */
136
+ export function resultSummary(input, theme) {
137
+ const { name, result, isError, lines } = input;
138
+ const details = record(result.details);
139
+ const muted = (s) => theme.fg("muted", s);
140
+ const sep = theme.fg("dim", " · ");
141
+ const wall = num(details["wall_time_seconds"]);
142
+ const elapsed = input.elapsedMs ?? (wall !== undefined ? wall * 1000 : 0);
143
+ const duration = formatDuration(elapsed);
144
+ const count = lines.length;
145
+ if (name === "bash") {
146
+ const code = num(details["exit_code"]) ?? (isError ? 1 : 0);
147
+ const total = num(details["totalLines"]) ?? count;
148
+ const head = details["aborted"] === true
149
+ ? "已中断"
150
+ : details["timedOut"] === true
151
+ ? "超时"
152
+ : `退出 ${code}`;
153
+ const parts = [head, duration, ...(total > 0 ? [`${total} 行`] : [])];
154
+ const text = parts.join(" · ");
155
+ return isError || code !== 0 ? theme.fg("error", text) : parts.map(muted).join(sep);
156
+ }
157
+ if (isError)
158
+ return theme.fg("error", `${theme.glyphs.fail} ${lines[0] ?? "失败"}`);
159
+ switch (name) {
160
+ case "read": {
161
+ const mime = details["mimeType"];
162
+ if (typeof mime === "string")
163
+ return muted(`图片 ${mime}`);
164
+ const first = num(details["firstLine"]);
165
+ const last = num(details["lastLine"]);
166
+ if (num(details["totalLines"]) === 0)
167
+ return muted("空文件");
168
+ const n = first !== undefined && last !== undefined ? last - first + 1 : count;
169
+ return muted(`读取 ${n} 行`);
170
+ }
171
+ case "edit": {
172
+ const rows = parseDiff(diffOf(result) ?? "");
173
+ const add = rows.filter((r) => r.kind === "add").length;
174
+ const del = rows.filter((r) => r.kind === "del").length;
175
+ const edits = record(input.args)["edits"];
176
+ const n = num(details["replacements"]) ?? (Array.isArray(edits) ? edits.length : 1);
177
+ return (muted(`${n} 处修改`) +
178
+ sep +
179
+ theme.fg("success", `+${add}`) +
180
+ " " +
181
+ theme.fg("error", `−${del}`));
182
+ }
183
+ case "write": {
184
+ const content = record(input.args)["content"];
185
+ const n = typeof content === "string" ? cleanLines(content).length : 0;
186
+ return muted(`${details["created"] === true ? "新建" : "覆盖"} · ${n} 行`);
187
+ }
188
+ case "grep": {
189
+ const matches = num(details["matches"]);
190
+ if (matches === 0)
191
+ return muted("无匹配");
192
+ if (matches === undefined)
193
+ return muted(`${count} 行`);
194
+ return muted(`${matches} 处匹配 · ${num(details["files"]) ?? "?"} 个文件`);
195
+ }
196
+ case "glob": {
197
+ const n = num(details["count"]);
198
+ return muted(n === 0 ? "无匹配" : `${n ?? count} 个文件`);
199
+ }
200
+ case "codemode": {
201
+ const calls = num(details["toolCalls"]) ?? input.nestedCount ?? 0;
202
+ return muted(`${calls} 个内层调用 · 脚本输出 ${count} 行`);
203
+ }
204
+ case "task": {
205
+ const usage = record(details["usage"]);
206
+ const input_ = num(usage["input"]);
207
+ const output = num(usage["output"]);
208
+ const tokens = input_ !== undefined && output !== undefined
209
+ ? [
210
+ `${theme.glyphs.arrowUp}${formatTokens(input_)} ${theme.glyphs.arrowDown}${formatTokens(output)}`,
211
+ ]
212
+ : [];
213
+ return muted(["完成", duration, ...tokens].join(" · "));
214
+ }
215
+ default:
216
+ return muted(count === 0 ? "完成" : `${count} 行输出`);
217
+ }
218
+ }