@armadra/agent 0.5.0 → 0.6.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 (471) hide show
  1. package/CHANGELOG.md +177 -294
  2. package/CHANGELOG.zh-CN.md +442 -0
  3. package/README.md +408 -364
  4. package/README.zh-CN.md +705 -0
  5. package/dist/agent/session-plan.js +2 -2
  6. package/dist/agent/session-state.d.ts +3 -0
  7. package/dist/agent/session-state.js +20 -0
  8. package/dist/agent/session-subagent.d.ts +15 -1
  9. package/dist/agent/session-subagent.js +26 -3
  10. package/dist/agent/session-telemetry.d.ts +16 -2
  11. package/dist/agent/session-telemetry.js +29 -7
  12. package/dist/agent/session-tools.js +5 -2
  13. package/dist/agent/session-trace-writer.d.ts +27 -0
  14. package/dist/agent/session-trace-writer.js +253 -0
  15. package/dist/agent/session.d.ts +2 -0
  16. package/dist/agent/session.js +12 -0
  17. package/dist/agent/subagent-direct.d.ts +20 -0
  18. package/dist/agent/subagent-direct.js +76 -0
  19. package/dist/agent/subagent-registry.d.ts +8 -1
  20. package/dist/agent/subagent-registry.js +28 -1
  21. package/dist/agent/system-prompt.d.ts +3 -1
  22. package/dist/agent/system-prompt.js +3 -0
  23. package/dist/agent/tool-runner.d.ts +2 -1
  24. package/dist/agent/tool-runner.js +5 -4
  25. package/dist/agent/types-w6.d.ts +39 -0
  26. package/dist/agent/types-w6.js +4 -0
  27. package/dist/agent/types.d.ts +5 -2
  28. package/dist/agents/external.js +1 -1
  29. package/dist/agents/task-record.d.ts +74 -1
  30. package/dist/agents/task-record.js +100 -0
  31. package/dist/ai/apis/cache-params.js +2 -1
  32. package/dist/ai/apis/chatgpt-backend.d.ts +52 -0
  33. package/dist/ai/apis/chatgpt-backend.js +224 -0
  34. package/dist/ai/apis/chatgpt-rate-limits.d.ts +26 -0
  35. package/dist/ai/apis/chatgpt-rate-limits.js +91 -0
  36. package/dist/ai/apis/openai-responses-request.d.ts +2 -1
  37. package/dist/ai/apis/openai-responses-request.js +8 -2
  38. package/dist/ai/apis/openai-responses.d.ts +2 -0
  39. package/dist/ai/apis/openai-responses.js +51 -16
  40. package/dist/ai/overflow.d.ts +1 -1
  41. package/dist/ai/overflow.js +10 -7
  42. package/dist/ai/providers/auth.d.ts +15 -2
  43. package/dist/ai/providers/auth.js +69 -2
  44. package/dist/ai/providers/builtin.js +27 -0
  45. package/dist/ai/providers/catalog-data.js +1 -0
  46. package/dist/ai/providers/enrich.js +2 -7
  47. package/dist/ai/providers/models-dev-cache.js +15 -19
  48. package/dist/ai/providers/models-dev-snapshot.js +8 -7
  49. package/dist/ai/providers/models-dev.js +5 -15
  50. package/dist/ai/providers/suggest.js +2 -16
  51. package/dist/ai/types.d.ts +27 -1
  52. package/dist/auth/chatgpt/backend-client.d.ts +26 -0
  53. package/dist/auth/chatgpt/backend-client.js +74 -0
  54. package/dist/auth/chatgpt/claims.d.ts +17 -0
  55. package/dist/auth/chatgpt/claims.js +46 -0
  56. package/dist/auth/chatgpt/cli.d.ts +33 -0
  57. package/dist/auth/chatgpt/cli.js +252 -0
  58. package/dist/auth/chatgpt/doctor.d.ts +17 -0
  59. package/dist/auth/chatgpt/doctor.js +36 -0
  60. package/dist/auth/chatgpt/host-id.d.ts +7 -0
  61. package/dist/auth/chatgpt/host-id.js +26 -0
  62. package/dist/auth/chatgpt/login.d.ts +30 -0
  63. package/dist/auth/chatgpt/login.js +130 -0
  64. package/dist/auth/chatgpt/presets.d.ts +66 -0
  65. package/dist/auth/chatgpt/presets.js +120 -0
  66. package/dist/auth/chatgpt/quota-text.d.ts +13 -0
  67. package/dist/auth/chatgpt/quota-text.js +36 -0
  68. package/dist/auth/oauth/browser.d.ts +12 -0
  69. package/dist/auth/oauth/browser.js +27 -0
  70. package/dist/auth/oauth/callback-server.d.ts +47 -0
  71. package/dist/auth/oauth/callback-server.js +147 -0
  72. package/dist/auth/oauth/flows.d.ts +62 -0
  73. package/dist/auth/oauth/flows.js +113 -0
  74. package/dist/auth/oauth/jwt.d.ts +24 -0
  75. package/dist/auth/oauth/jwt.js +81 -0
  76. package/dist/auth/oauth/live.d.ts +21 -0
  77. package/dist/auth/oauth/live.js +25 -0
  78. package/dist/auth/oauth/oidc.d.ts +26 -0
  79. package/dist/auth/oauth/oidc.js +72 -0
  80. package/dist/auth/oauth/pkce.d.ts +15 -0
  81. package/dist/auth/oauth/pkce.js +20 -0
  82. package/dist/auth/oauth/refresh.d.ts +35 -0
  83. package/dist/auth/oauth/refresh.js +129 -0
  84. package/dist/auth/oauth/token-client.d.ts +33 -0
  85. package/dist/auth/oauth/token-client.js +121 -0
  86. package/dist/auth/oauth/token-store.d.ts +23 -0
  87. package/dist/auth/oauth/token-store.js +125 -0
  88. package/dist/auth/testing/fake-oauth.d.ts +73 -0
  89. package/dist/auth/testing/fake-oauth.js +271 -0
  90. package/dist/auth/testing/refresh-child.d.ts +5 -0
  91. package/dist/auth/testing/refresh-child.js +16 -0
  92. package/dist/bundle/ama.cjs +28307 -13241
  93. package/dist/checkpoints/backend.js +6 -5
  94. package/dist/checkpoints/restore.js +3 -2
  95. package/dist/checkpoints/settings.js +2 -1
  96. package/dist/checkpoints/shadow-git.js +7 -6
  97. package/dist/checkpoints/shadow-restore.js +3 -2
  98. package/dist/checkpoints/tracker.js +4 -3
  99. package/dist/cli/args.d.ts +9 -2
  100. package/dist/cli/args.js +74 -27
  101. package/dist/cli/bootstrap.js +53 -31
  102. package/dist/cli/choice-prompt.d.ts +58 -0
  103. package/dist/cli/choice-prompt.js +142 -0
  104. package/dist/cli/codemode-notice.js +2 -2
  105. package/dist/cli/compose-agents.js +2 -1
  106. package/dist/cli/compose-extensions.js +2 -0
  107. package/dist/cli/compose-memory.d.ts +53 -0
  108. package/dist/cli/compose-memory.js +127 -0
  109. package/dist/cli/compose-providers.d.ts +5 -0
  110. package/dist/cli/compose-providers.js +32 -2
  111. package/dist/cli/compose-session.d.ts +5 -0
  112. package/dist/cli/compose-session.js +27 -13
  113. package/dist/cli/compose-store.d.ts +2 -0
  114. package/dist/cli/compose-store.js +9 -5
  115. package/dist/cli/compose.d.ts +2 -0
  116. package/dist/cli/compose.js +13 -5
  117. package/dist/cli/default-model.d.ts +0 -2
  118. package/dist/cli/default-model.js +5 -8
  119. package/dist/cli/deps.d.ts +5 -1
  120. package/dist/cli/exit-codes.d.ts +1 -1
  121. package/dist/cli/exit-codes.js +7 -16
  122. package/dist/cli/from-prompt.js +3 -2
  123. package/dist/cli/help-text.d.ts +2 -1
  124. package/dist/cli/help-text.js +5 -99
  125. package/dist/cli/main.d.ts +5 -0
  126. package/dist/cli/main.js +21 -2
  127. package/dist/cli/proxy.js +14 -9
  128. package/dist/cli/runtime.d.ts +5 -0
  129. package/dist/cli/startup-screen.js +20 -27
  130. package/dist/cli/startup-steps.js +6 -8
  131. package/dist/cli/subcommands/auth.d.ts +6 -3
  132. package/dist/cli/subcommands/auth.js +52 -22
  133. package/dist/cli/subcommands/config-set.d.ts +21 -0
  134. package/dist/cli/subcommands/config-set.js +137 -0
  135. package/dist/cli/subcommands/config.d.ts +2 -1
  136. package/dist/cli/subcommands/config.js +51 -37
  137. package/dist/cli/subcommands/doctor.d.ts +2 -1
  138. package/dist/cli/subcommands/doctor.js +97 -58
  139. package/dist/cli/subcommands/init.d.ts +1 -1
  140. package/dist/cli/subcommands/init.js +8 -7
  141. package/dist/cli/subcommands/memory.d.ts +18 -0
  142. package/dist/cli/subcommands/memory.js +189 -0
  143. package/dist/cli/subcommands/model-meta.js +11 -9
  144. package/dist/cli/subcommands/models-cache-probe.d.ts +1 -1
  145. package/dist/cli/subcommands/models-cache-probe.js +26 -32
  146. package/dist/cli/subcommands/models-discover.d.ts +3 -0
  147. package/dist/cli/subcommands/models-discover.js +44 -21
  148. package/dist/cli/subcommands/models.d.ts +1 -1
  149. package/dist/cli/subcommands/models.js +29 -22
  150. package/dist/cli/subcommands/probe-runner.js +8 -7
  151. package/dist/cli/subcommands/providers-list.js +32 -21
  152. package/dist/cli/subcommands/providers-plan.js +24 -25
  153. package/dist/cli/subcommands/providers-probe.js +5 -6
  154. package/dist/cli/subcommands/providers.d.ts +2 -2
  155. package/dist/cli/subcommands/providers.js +48 -59
  156. package/dist/cli/subcommands/sessions-export.d.ts +1 -1
  157. package/dist/cli/subcommands/sessions-export.js +10 -9
  158. package/dist/cli/subcommands/sessions-search.d.ts +1 -1
  159. package/dist/cli/subcommands/sessions-search.js +11 -10
  160. package/dist/cli/subcommands/sessions-trace.d.ts +30 -0
  161. package/dist/cli/subcommands/sessions-trace.js +156 -0
  162. package/dist/cli/subcommands/sessions.d.ts +4 -3
  163. package/dist/cli/subcommands/sessions.js +40 -37
  164. package/dist/cli/subcommands/stats.d.ts +1 -1
  165. package/dist/cli/subcommands/stats.js +49 -30
  166. package/dist/cli/system-prompt-arg.js +3 -2
  167. package/dist/codemode/capability.js +3 -2
  168. package/dist/compaction/post-compact.d.ts +1 -0
  169. package/dist/compaction/post-compact.js +15 -1
  170. package/dist/compaction/prune-tier.d.ts +1 -1
  171. package/dist/compaction/prune-tier.js +3 -3
  172. package/dist/compaction/serialize.js +2 -1
  173. package/dist/config/auth-file.d.ts +12 -2
  174. package/dist/config/auth-file.js +32 -10
  175. package/dist/config/checker.js +12 -11
  176. package/dist/config/context-files.js +3 -2
  177. package/dist/config/edit.d.ts +106 -0
  178. package/dist/config/edit.js +350 -0
  179. package/dist/config/init.d.ts +4 -3
  180. package/dist/config/init.js +10 -18
  181. package/dist/config/json-schema.d.ts +2 -1
  182. package/dist/config/json-schema.js +101 -68
  183. package/dist/config/key-docs.d.ts +18 -7
  184. package/dist/config/key-docs.js +43 -128
  185. package/dist/config/load.js +7 -6
  186. package/dist/config/merge.d.ts +4 -1
  187. package/dist/config/merge.js +42 -22
  188. package/dist/config/paths.js +6 -5
  189. package/dist/config/profile.d.ts +5 -1
  190. package/dist/config/profile.js +7 -2
  191. package/dist/config/schema-w5.js +3 -2
  192. package/dist/config/schema-w6.d.ts +19 -0
  193. package/dist/config/schema-w6.js +115 -0
  194. package/dist/config/schema.js +34 -20
  195. package/dist/config/settings-registry.d.ts +78 -0
  196. package/dist/config/settings-registry.js +184 -0
  197. package/dist/config/types-w6.d.ts +109 -0
  198. package/dist/config/types-w6.js +19 -0
  199. package/dist/config/types.d.ts +11 -8
  200. package/dist/config/types.js +1 -0
  201. package/dist/drivers/acp/client.js +1 -1
  202. package/dist/drivers/acp/driver.js +13 -8
  203. package/dist/drivers/agents.js +4 -3
  204. package/dist/drivers/base.js +3 -2
  205. package/dist/drivers/host-runners.js +2 -1
  206. package/dist/drivers/native/claude-stream.js +12 -11
  207. package/dist/drivers/native/codex-app-server.js +17 -12
  208. package/dist/drivers/native/oneshot.js +8 -7
  209. package/dist/drivers/pool.js +1 -1
  210. package/dist/drivers/runner.d.ts +3 -1
  211. package/dist/drivers/runner.js +68 -20
  212. package/dist/drivers/turn.js +1 -1
  213. package/dist/hooks/config.js +3 -2
  214. package/dist/hooks/protocol.js +18 -12
  215. package/dist/host/api-impl.js +11 -10
  216. package/dist/host/loader.js +9 -8
  217. package/dist/host/types.d.ts +3 -0
  218. package/dist/i18n/catalog.d.ts +2169 -0
  219. package/dist/i18n/catalog.js +72 -0
  220. package/dist/i18n/format.d.ts +21 -0
  221. package/dist/i18n/format.js +58 -0
  222. package/dist/i18n/index.d.ts +58 -0
  223. package/dist/i18n/index.js +72 -0
  224. package/dist/i18n/messages/agents.d.ts +84 -0
  225. package/dist/i18n/messages/agents.js +85 -0
  226. package/dist/i18n/messages/approval.d.ts +99 -0
  227. package/dist/i18n/messages/approval.js +100 -0
  228. package/dist/i18n/messages/auth.d.ts +187 -0
  229. package/dist/i18n/messages/auth.js +189 -0
  230. package/dist/i18n/messages/cli-args.d.ts +46 -0
  231. package/dist/i18n/messages/cli-args.js +46 -0
  232. package/dist/i18n/messages/cli-help.d.ts +12 -0
  233. package/dist/i18n/messages/cli-help.js +244 -0
  234. package/dist/i18n/messages/cli.d.ts +336 -0
  235. package/dist/i18n/messages/cli.js +311 -0
  236. package/dist/i18n/messages/config-keys.d.ts +289 -0
  237. package/dist/i18n/messages/config-keys.js +292 -0
  238. package/dist/i18n/messages/config.d.ts +502 -0
  239. package/dist/i18n/messages/config.js +239 -0
  240. package/dist/i18n/messages/drivers.d.ts +123 -0
  241. package/dist/i18n/messages/drivers.js +124 -0
  242. package/dist/i18n/messages/errors.d.ts +83 -0
  243. package/dist/i18n/messages/errors.js +171 -0
  244. package/dist/i18n/messages/interactive-line.d.ts +61 -0
  245. package/dist/i18n/messages/interactive-line.js +69 -0
  246. package/dist/i18n/messages/interactive-startup.d.ts +103 -0
  247. package/dist/i18n/messages/interactive-startup.js +104 -0
  248. package/dist/i18n/messages/interactive-view.d.ts +140 -0
  249. package/dist/i18n/messages/interactive-view.js +141 -0
  250. package/dist/i18n/messages/interactive.d.ts +493 -0
  251. package/dist/i18n/messages/interactive.js +248 -0
  252. package/dist/i18n/messages/memory.d.ts +123 -0
  253. package/dist/i18n/messages/memory.js +128 -0
  254. package/dist/i18n/messages/panels.d.ts +190 -0
  255. package/dist/i18n/messages/panels.js +189 -0
  256. package/dist/i18n/messages/permissions.d.ts +126 -0
  257. package/dist/i18n/messages/permissions.js +151 -0
  258. package/dist/i18n/messages/plan.d.ts +123 -0
  259. package/dist/i18n/messages/plan.js +124 -0
  260. package/dist/i18n/messages/print.d.ts +86 -0
  261. package/dist/i18n/messages/print.js +91 -0
  262. package/dist/i18n/messages/report.d.ts +391 -0
  263. package/dist/i18n/messages/report.js +490 -0
  264. package/dist/i18n/messages/rewind.d.ts +198 -0
  265. package/dist/i18n/messages/rewind.js +217 -0
  266. package/dist/i18n/messages/session.d.ts +230 -0
  267. package/dist/i18n/messages/session.js +258 -0
  268. package/dist/i18n/messages/settings.d.ts +348 -0
  269. package/dist/i18n/messages/settings.js +336 -0
  270. package/dist/i18n/messages/subcommands-config.d.ts +111 -0
  271. package/dist/i18n/messages/subcommands-config.js +127 -0
  272. package/dist/i18n/messages/subcommands.d.ts +548 -0
  273. package/dist/i18n/messages/subcommands.js +474 -0
  274. package/dist/i18n/messages/trace.d.ts +243 -0
  275. package/dist/i18n/messages/trace.js +238 -0
  276. package/dist/i18n/types.d.ts +15 -0
  277. package/dist/i18n/types.js +7 -0
  278. package/dist/index.d.ts +6 -0
  279. package/dist/index.js +2 -0
  280. package/dist/memory/edit.d.ts +24 -0
  281. package/dist/memory/edit.js +63 -0
  282. package/dist/memory/frontmatter.d.ts +37 -0
  283. package/dist/memory/frontmatter.js +79 -0
  284. package/dist/memory/index.d.ts +28 -0
  285. package/dist/memory/index.js +126 -0
  286. package/dist/memory/lock.d.ts +17 -0
  287. package/dist/memory/lock.js +62 -0
  288. package/dist/memory/paths.d.ts +57 -0
  289. package/dist/memory/paths.js +175 -0
  290. package/dist/memory/report.d.ts +36 -0
  291. package/dist/memory/report.js +86 -0
  292. package/dist/memory/runtime.d.ts +42 -0
  293. package/dist/memory/runtime.js +36 -0
  294. package/dist/memory/secrets.d.ts +8 -0
  295. package/dist/memory/secrets.js +27 -0
  296. package/dist/memory/section.d.ts +28 -0
  297. package/dist/memory/section.js +59 -0
  298. package/dist/memory/store.d.ts +70 -0
  299. package/dist/memory/store.js +284 -0
  300. package/dist/memory/tool.d.ts +31 -0
  301. package/dist/memory/tool.js +94 -0
  302. package/dist/modes/acp/acp-events.js +2 -1
  303. package/dist/modes/acp/acp-server.js +13 -12
  304. package/dist/modes/commands-core.d.ts +17 -0
  305. package/dist/modes/commands-core.js +101 -61
  306. package/dist/modes/image-input.js +20 -6
  307. package/dist/modes/interactive/agent-bar.d.ts +95 -0
  308. package/dist/modes/interactive/agent-bar.js +248 -0
  309. package/dist/modes/interactive/agent-panels.js +27 -26
  310. package/dist/modes/interactive/agent-transcript.d.ts +47 -0
  311. package/dist/modes/interactive/agent-transcript.js +191 -0
  312. package/dist/modes/interactive/agent-ui.d.ts +36 -1
  313. package/dist/modes/interactive/agent-ui.js +180 -14
  314. package/dist/modes/interactive/agent-view.d.ts +72 -0
  315. package/dist/modes/interactive/agent-view.js +281 -0
  316. package/dist/modes/interactive/approval-dialog.js +46 -34
  317. package/dist/modes/interactive/clipboard-paste.d.ts +2 -2
  318. package/dist/modes/interactive/clipboard-paste.js +9 -4
  319. package/dist/modes/interactive/commands.d.ts +22 -1
  320. package/dist/modes/interactive/commands.js +93 -38
  321. package/dist/modes/interactive/completion.js +2 -1
  322. package/dist/modes/interactive/config-panel.d.ts +70 -0
  323. package/dist/modes/interactive/config-panel.js +319 -0
  324. package/dist/modes/interactive/config-ui.d.ts +96 -0
  325. package/dist/modes/interactive/config-ui.js +397 -0
  326. package/dist/modes/interactive/confirm-dialog.d.ts +49 -0
  327. package/dist/modes/interactive/confirm-dialog.js +120 -0
  328. package/dist/modes/interactive/event-notices.js +11 -9
  329. package/dist/modes/interactive/interactive-mode.d.ts +1 -1
  330. package/dist/modes/interactive/interactive-mode.js +25 -22
  331. package/dist/modes/interactive/key-dispatch.d.ts +18 -0
  332. package/dist/modes/interactive/key-dispatch.js +39 -13
  333. package/dist/modes/interactive/line/line-editor.js +2 -1
  334. package/dist/modes/interactive/line/line-mode.d.ts +2 -0
  335. package/dist/modes/interactive/line/line-mode.js +24 -4
  336. package/dist/modes/interactive/line/line-render.js +25 -24
  337. package/dist/modes/interactive/memory-panel.d.ts +64 -0
  338. package/dist/modes/interactive/memory-panel.js +221 -0
  339. package/dist/modes/interactive/message-view.d.ts +4 -2
  340. package/dist/modes/interactive/message-view.js +42 -33
  341. package/dist/modes/interactive/panels.js +39 -31
  342. package/dist/modes/interactive/pickers.d.ts +2 -1
  343. package/dist/modes/interactive/pickers.js +10 -6
  344. package/dist/modes/interactive/plan-command.d.ts +1 -1
  345. package/dist/modes/interactive/plan-command.js +24 -27
  346. package/dist/modes/interactive/plan-dialog.js +18 -17
  347. package/dist/modes/interactive/plan-flow.js +6 -5
  348. package/dist/modes/interactive/rewind-command.d.ts +1 -1
  349. package/dist/modes/interactive/rewind-command.js +18 -16
  350. package/dist/modes/interactive/rewind-flow.d.ts +0 -1
  351. package/dist/modes/interactive/rewind-flow.js +13 -14
  352. package/dist/modes/interactive/rewind-list.js +7 -6
  353. package/dist/modes/interactive/rewind-panel.js +40 -40
  354. package/dist/modes/interactive/rewind-text.d.ts +5 -3
  355. package/dist/modes/interactive/rewind-text.js +48 -38
  356. package/dist/modes/interactive/run-indicator.js +15 -12
  357. package/dist/modes/interactive/session-events.js +3 -2
  358. package/dist/modes/interactive/startup-header.js +22 -23
  359. package/dist/modes/interactive/startup-ui.js +41 -29
  360. package/dist/modes/interactive/status-area.d.ts +2 -0
  361. package/dist/modes/interactive/status-area.js +8 -2
  362. package/dist/modes/interactive/status-bar.js +4 -3
  363. package/dist/modes/interactive/subagent-view.js +9 -7
  364. package/dist/modes/interactive/tasks-report.d.ts +6 -0
  365. package/dist/modes/interactive/tasks-report.js +28 -31
  366. package/dist/modes/interactive/terminal-setup.d.ts +9 -0
  367. package/dist/modes/interactive/terminal-setup.js +23 -0
  368. package/dist/modes/interactive/tool-summary.js +19 -17
  369. package/dist/modes/interactive/tool-view.js +7 -4
  370. package/dist/modes/interactive/trace-view.d.ts +89 -0
  371. package/dist/modes/interactive/trace-view.js +332 -0
  372. package/dist/modes/print/print-mode.js +14 -15
  373. package/dist/modes/rpc/commands.js +7 -3
  374. package/dist/modes/rpc/rpc-mode.js +9 -3
  375. package/dist/modes/session-report.d.ts +2 -0
  376. package/dist/modes/session-report.js +101 -105
  377. package/dist/modes/startup-ui-text.js +11 -6
  378. package/dist/permissions/bypass.d.ts +30 -0
  379. package/dist/permissions/bypass.js +45 -0
  380. package/dist/permissions/memory-class.d.ts +23 -0
  381. package/dist/permissions/memory-class.js +54 -0
  382. package/dist/permissions/modes.d.ts +3 -3
  383. package/dist/permissions/modes.js +21 -16
  384. package/dist/permissions/pipeline.d.ts +1 -1
  385. package/dist/permissions/pipeline.js +9 -2
  386. package/dist/permissions/preview.js +49 -42
  387. package/dist/permissions/rules.js +5 -2
  388. package/dist/permissions/types.d.ts +4 -0
  389. package/dist/plan/store.js +2 -1
  390. package/dist/rpc.d.ts +39 -1
  391. package/dist/rpc.js +3 -0
  392. package/dist/sandbox/bash.js +11 -8
  393. package/dist/sandbox/detect.js +14 -11
  394. package/dist/sdk.d.ts +17 -1
  395. package/dist/sdk.js +29 -7
  396. package/dist/session/export.js +31 -30
  397. package/dist/session/manager.d.ts +1 -1
  398. package/dist/session/manager.js +5 -3
  399. package/dist/session/reuse.js +5 -4
  400. package/dist/session/scan.js +3 -2
  401. package/dist/session/stats-aggregate.d.ts +3 -1
  402. package/dist/session/stats-aggregate.js +5 -1
  403. package/dist/session/stats-index.js +2 -1
  404. package/dist/session/stats-scan.d.ts +4 -1
  405. package/dist/session/stats-scan.js +6 -2
  406. package/dist/session/store.d.ts +11 -0
  407. package/dist/session/store.js +48 -1
  408. package/dist/session/types.d.ts +2 -0
  409. package/dist/skills/builtin.js +2 -1
  410. package/dist/tools/image-file.d.ts +26 -1
  411. package/dist/tools/image-file.js +55 -13
  412. package/dist/tools/presets.d.ts +14 -1
  413. package/dist/tools/presets.js +3 -3
  414. package/dist/tools/registry.js +1 -1
  415. package/dist/tools/truncate.d.ts +1 -1
  416. package/dist/tools/truncate.js +2 -2
  417. package/dist/tools/types.d.ts +17 -1
  418. package/dist/trace/build-index.d.ts +91 -0
  419. package/dist/trace/build-index.js +127 -0
  420. package/dist/trace/build-nodes.d.ts +24 -0
  421. package/dist/trace/build-nodes.js +279 -0
  422. package/dist/trace/build-util.d.ts +43 -0
  423. package/dist/trace/build-util.js +120 -0
  424. package/dist/trace/build.d.ts +82 -0
  425. package/dist/trace/build.js +382 -0
  426. package/dist/trace/detail.d.ts +35 -0
  427. package/dist/trace/detail.js +205 -0
  428. package/dist/trace/flatten.d.ts +69 -0
  429. package/dist/trace/flatten.js +173 -0
  430. package/dist/trace/format.d.ts +47 -0
  431. package/dist/trace/format.js +329 -0
  432. package/dist/trace/html-template.d.ts +19 -0
  433. package/dist/trace/html-template.js +150 -0
  434. package/dist/trace/html.d.ts +104 -0
  435. package/dist/trace/html.js +292 -0
  436. package/dist/trace/preview.d.ts +29 -0
  437. package/dist/trace/preview.js +59 -0
  438. package/dist/trace/query-session.d.ts +14 -0
  439. package/dist/trace/query-session.js +38 -0
  440. package/dist/trace/query.d.ts +55 -0
  441. package/dist/trace/query.js +188 -0
  442. package/dist/trace/session.d.ts +40 -0
  443. package/dist/trace/session.js +168 -0
  444. package/dist/trace/types.d.ts +243 -0
  445. package/dist/trace/types.js +13 -0
  446. package/dist/tui/components/editor-paste.d.ts +2 -0
  447. package/dist/tui/components/editor-paste.js +6 -3
  448. package/dist/tui/components/editor.js +2 -2
  449. package/dist/tui/components/loader.d.ts +3 -0
  450. package/dist/tui/components/loader.js +14 -0
  451. package/dist/tui/components/settings-list.d.ts +61 -0
  452. package/dist/tui/components/settings-list.js +135 -0
  453. package/dist/tui/keybindings.d.ts +6 -1
  454. package/dist/tui/keybindings.js +18 -6
  455. package/dist/tui.d.ts +1 -0
  456. package/dist/tui.js +2 -0
  457. package/docs/en/host-api.md +167 -0
  458. package/docs/en/permissions.md +214 -0
  459. package/docs/en/providers.md +625 -0
  460. package/docs/en/rpc.md +361 -0
  461. package/docs/en/sessions.md +219 -0
  462. package/docs/en/tui.md +527 -0
  463. package/docs/host-api.md +18 -17
  464. package/docs/memory.md +172 -0
  465. package/docs/permissions.md +3 -2
  466. package/docs/providers.md +67 -1
  467. package/docs/rpc.md +31 -3
  468. package/docs/session-format.md +8 -2
  469. package/docs/sessions.md +29 -1
  470. package/docs/tui.md +189 -21
  471. package/package.json +8 -3
@@ -0,0 +1,382 @@
1
+ /**
2
+ * 轨迹构建器(docs/wave6-plan.md §2.3、D6)。[W6-T1]
3
+ *
4
+ * `buildTrace(input, opts)` 把会话条目重建成 `Trace`(Turn → Step → Tool → Subcall / Subagent):
5
+ * TUI `/trace`、`ama sessions trace`、RPC `get_trace` 三方共用同一棵树。
6
+ *
7
+ * 性质:
8
+ * - **纯函数**:不读时钟、不做 I/O;子会话经 `opts.loadChild` 回调读取(深度 ≤ 1:子轨迹里不再展开孙任务)。
9
+ * - **确定性**:同样的输入(含 `opts.now` / `opts.live`)得到逐字节相同的 JSON;节点顺序 = 条目顺序。
10
+ * - **不改历史**:老会话没有 `ama.trace` 时按条目时间回退推算并标 `approx`;推算出的时间不写回文件。
11
+ * - **容忍**:未知条目、未知 customType、损坏的 data 一律跳过;子会话缺失或读取抛错标 `childMissing`。
12
+ * - **不含正文**:只有 id、时间、计数与用量;提示 / 参数 / 结果的预览由调用方按 `entryIds` 回条目取。
13
+ *
14
+ * 算法:选分支(leaf = 根 → 叶子;all = 文件顺序)→ 预建索引(`ama.trace` 按 assistant / toolCall /
15
+ * compaction / usage 条目 id,`ama.task` 按父 toolCallId,`external_turn` 按 taskId,`context_edit` 的
16
+ * retry / overflow 目标)→ 顺序扫描建节点 → 叠加 `live` → 汇总。推算规则:`requestAt = assistant.timestamp`、
17
+ * `doneAt = 条目时间`、工具 `startedAt = assistant 条目时间`、`endedAt = toolResult.timestamp`;ttft 分位与
18
+ * 平均吞吐只用精确(非 approx)的 step。
19
+ *
20
+ * 汇总口径:`requests` 与 token / 费用和 `usageTotals`(session/export.ts)一致(assistant + 压缩 / 分支摘要 +
21
+ * `usage` 条目;进行中的请求不计);`durationMs` = 各回合耗时之和(不含回合之间的空闲);回合的 `endedAt`
22
+ * 不被后台子 Agent 拉长;文件里 `status: "running"` 的任务在没有 `live` 时视为 `interrupted`。
23
+ */
24
+ import { indexEntries, pathToRoot } from "../session/tree.js";
25
+ import { buildIndex, entryTime, num, splitRef, traceData, zeroUsage, } from "./build-index.js";
26
+ import { abortedRequest, assistantStep, compactionAsAux, compactionNode, externalNodes, pushUsage, retryNode, subagentNode, } from "./build-nodes.js";
27
+ import { accumulate, emptyTotals, finishTotals, maxDefined, mergeTotals } from "./build-util.js";
28
+ import {} from "./types.js";
29
+ /** 所选分支的条目。 */
30
+ export function selectTraceEntries(input, branch = "leaf") {
31
+ if (branch === "all")
32
+ return [...input.entries];
33
+ const leaf = input.leaf === undefined ? (input.entries.at(-1)?.id ?? null) : input.leaf;
34
+ return pathToRoot(indexEntries(input.entries), leaf);
35
+ }
36
+ /**
37
+ * 从会话条目构建轨迹树。见文件头的性质与算法;选项见 `BuildTraceOptions`。
38
+ */
39
+ export function buildTrace(input, opts = {}) {
40
+ const entries = selectTraceEntries(input, opts.branch ?? "leaf");
41
+ const index = buildIndex(entries);
42
+ const state = {
43
+ turns: [],
44
+ aux: [],
45
+ turn: undefined,
46
+ turnModel: undefined,
47
+ model: undefined,
48
+ tools: new Map(),
49
+ resolved: new Set(),
50
+ extraUsage: new Map(),
51
+ };
52
+ const openTurn = (id, startedAt, origin) => {
53
+ const turn = {
54
+ id,
55
+ kind: "turn",
56
+ status: "ok",
57
+ entryIds: [id],
58
+ steps: [],
59
+ usage: emptyTotals(),
60
+ };
61
+ if (startedAt !== undefined)
62
+ turn.startedAt = startedAt;
63
+ if (origin !== undefined)
64
+ turn.origin = origin;
65
+ state.turns.push(turn);
66
+ state.turn = turn;
67
+ state.turnModel = state.model;
68
+ return turn;
69
+ };
70
+ const currentTurn = (entry, at) => state.turn ?? openTurn(entry.id, at);
71
+ for (const entry of entries) {
72
+ const at = entryTime(entry);
73
+ switch (entry.type) {
74
+ case "model_change":
75
+ state.model = `${entry.provider}/${entry.modelId}`;
76
+ break;
77
+ case "message": {
78
+ const m = entry.message;
79
+ if (m.role === "user") {
80
+ if (m.origin === "steer" && state.turn !== undefined)
81
+ state.turn.entryIds.push(entry.id);
82
+ else
83
+ openTurn(entry.id, num(m.timestamp) ?? at, m.origin);
84
+ }
85
+ else if (m.role === "assistant") {
86
+ const turn = currentTurn(entry, num(m.timestamp) ?? at);
87
+ turn.steps.push(assistantStep(entry.id, m, at, turn, state, index));
88
+ }
89
+ else if (m.role === "toolResult") {
90
+ const tool = state.tools.get(m.toolCallId);
91
+ if (tool === undefined)
92
+ break;
93
+ state.resolved.add(tool.id);
94
+ tool.entryIds.push(entry.id);
95
+ tool.isError = m.isError === true;
96
+ if (tool.status !== "denied")
97
+ tool.status = tool.isError ? "error" : "ok";
98
+ if (tool.approx === true) {
99
+ const end = num(m.timestamp) ?? at;
100
+ if (end !== undefined)
101
+ tool.endedAt = end;
102
+ }
103
+ }
104
+ break;
105
+ }
106
+ case "compaction": {
107
+ const turn = state.turn;
108
+ const node = compactionNode(entry.id, at, index.compactionByEntry.get(entry.id));
109
+ node.tokensBefore = entry.tokensBefore;
110
+ if (turn === undefined)
111
+ state.aux.push(compactionAsAux(node, entry.usage));
112
+ else {
113
+ turn.steps.push(node);
114
+ if (entry.usage !== undefined)
115
+ pushUsage(state, turn.id, entry.usage);
116
+ }
117
+ break;
118
+ }
119
+ case "branch_summary":
120
+ if (state.turn !== undefined && entry.usage !== undefined)
121
+ pushUsage(state, state.turn.id, entry.usage);
122
+ break;
123
+ case "usage": {
124
+ const trace = index.auxByUsage.get(entry.id);
125
+ const node = {
126
+ id: entry.id,
127
+ kind: "aux",
128
+ purpose: trace?.data.purpose ?? entry.kind,
129
+ status: "ok",
130
+ entryIds: trace === undefined ? [entry.id] : [entry.id, trace.entryId],
131
+ usage: entry.usage,
132
+ };
133
+ const started = num(trace?.data.startedAt);
134
+ const ended = num(trace?.data.endedAt) ?? at;
135
+ if (started !== undefined)
136
+ node.startedAt = started;
137
+ if (ended !== undefined)
138
+ node.endedAt = ended;
139
+ if (started === undefined)
140
+ node.approx = true;
141
+ state.aux.push(node);
142
+ break;
143
+ }
144
+ case "custom": {
145
+ const data = traceData(entry);
146
+ if (data === undefined || state.turn === undefined)
147
+ break;
148
+ if (data.kind === "retry_wait")
149
+ state.turn.steps.push(retryNode(entry.id, data));
150
+ else if (data.kind === "compaction" && typeof data.compactionEntryId !== "string") {
151
+ // 中断的压缩没有 compaction 条目,只有这一条
152
+ state.turn.steps.push(compactionNode(entry.id, at, { data, entryId: entry.id }));
153
+ }
154
+ else if (data.kind === "step" && typeof data.assistantEntryId !== "string")
155
+ abortedRequest(entry.id, data, state);
156
+ break;
157
+ }
158
+ default:
159
+ break;
160
+ }
161
+ }
162
+ attachTasks(state, index, opts);
163
+ applyLive(state, opts.live);
164
+ return finish(input, state, opts);
165
+ }
166
+ function attachTasks(state, index, opts) {
167
+ for (const tool of state.tools.values()) {
168
+ const tasks = index.tasks.get(tool.id);
169
+ if (tasks === undefined)
170
+ continue;
171
+ for (const { data, entryId } of tasks.values()) {
172
+ const node = subagentNode(data, entryId, opts.live !== undefined);
173
+ const external = index.external.get(data.taskId);
174
+ if (external !== undefined)
175
+ node.external = externalNodes(data.taskId, external);
176
+ const file = node.childRef?.sessionFile;
177
+ if (opts.loadChild !== undefined && file !== undefined && node.runner === "ama")
178
+ loadSubagentTrace(node, opts.loadChild, opts.now);
179
+ tool.children.push(node);
180
+ }
181
+ }
182
+ }
183
+ /**
184
+ * 懒加载 ama 子 Agent 的子轨迹(就地写 `node.child` / `node.childMissing`,返回子轨迹)。深度 ≤ 1:
185
+ * 子轨迹里的任务不再展开。外部 runner 或没有会话文件时返回 undefined 且不标缺失。
186
+ */
187
+ export function loadSubagentTrace(node, loadChild, now) {
188
+ if (node.child !== undefined)
189
+ return node.child;
190
+ const file = node.childRef?.sessionFile;
191
+ if (file === undefined || node.runner !== "ama")
192
+ return undefined;
193
+ let input;
194
+ try {
195
+ input = loadChild(file);
196
+ }
197
+ catch {
198
+ input = undefined;
199
+ }
200
+ if (input === undefined) {
201
+ node.childMissing = true;
202
+ return undefined;
203
+ }
204
+ try {
205
+ const child = buildTrace({ ...input, sessionFile: input.sessionFile ?? file }, now === undefined ? {} : { now });
206
+ node.child = child;
207
+ delete node.childMissing;
208
+ return child;
209
+ }
210
+ catch {
211
+ node.childMissing = true;
212
+ return undefined;
213
+ }
214
+ }
215
+ function applyLive(state, live) {
216
+ for (const tool of state.tools.values()) {
217
+ if (state.resolved.has(tool.id) || tool.status === "denied")
218
+ continue;
219
+ tool.status = live?.running === true ? "running" : "interrupted";
220
+ }
221
+ if (live === undefined)
222
+ return;
223
+ for (const lt of live.tools ?? []) {
224
+ if (lt.parentId !== undefined) {
225
+ const parent = state.tools.get(lt.parentId);
226
+ if (parent === undefined)
227
+ continue;
228
+ const existing = parent.children.find((c) => c.kind === "subcall" && c.id === lt.id);
229
+ if (existing !== undefined) {
230
+ existing.status = "running";
231
+ delete existing.endedAt;
232
+ continue;
233
+ }
234
+ parent.children.push({
235
+ id: lt.id,
236
+ kind: "subcall",
237
+ name: lt.name,
238
+ parentToolCallId: lt.parentId,
239
+ isError: false,
240
+ status: "running",
241
+ startedAt: lt.startedAt,
242
+ entryIds: [],
243
+ });
244
+ continue;
245
+ }
246
+ const tool = state.tools.get(lt.id);
247
+ if (tool === undefined || state.resolved.has(tool.id))
248
+ continue;
249
+ tool.status = "running";
250
+ tool.startedAt = lt.startedAt;
251
+ delete tool.endedAt;
252
+ delete tool.approx;
253
+ }
254
+ const turn = state.turn;
255
+ const request = live.request;
256
+ if (request !== undefined && turn !== undefined) {
257
+ const ref = splitRef(state.model);
258
+ const step = {
259
+ id: `live:${request.requestAt}`,
260
+ kind: "step",
261
+ status: "running",
262
+ entryIds: [],
263
+ provider: request.provider ?? ref.provider,
264
+ model: request.model ?? ref.model,
265
+ attempt: 1,
266
+ usage: { ...zeroUsage(), output: request.outputTokens ?? 0 },
267
+ stopReason: "",
268
+ requestAt: request.requestAt,
269
+ startedAt: request.requestAt,
270
+ tools: [],
271
+ };
272
+ if (request.firstTokenAt !== undefined) {
273
+ step.firstTokenAt = request.firstTokenAt;
274
+ step.ttftMs = Math.max(0, request.firstTokenAt - request.requestAt);
275
+ }
276
+ turn.steps.push(step);
277
+ }
278
+ if (live.running && turn !== undefined)
279
+ turn.status = "running";
280
+ }
281
+ function finish(input, state, opts) {
282
+ const all = emptyTotals();
283
+ let partial = false;
284
+ let endedAt;
285
+ let duration = 0;
286
+ let timed = false;
287
+ for (const turn of state.turns) {
288
+ const totals = emptyTotals();
289
+ let end;
290
+ let running = turn.status === "running";
291
+ let interrupted = false;
292
+ for (const node of turn.steps) {
293
+ if (node.approx === true)
294
+ turn.approx = true;
295
+ end = maxDefined(end, node.endedAt);
296
+ if (node.status === "running")
297
+ running = true;
298
+ if (node.kind !== "step")
299
+ continue;
300
+ accumulate(totals, node);
301
+ for (const tool of node.tools) {
302
+ totals.toolCalls++;
303
+ if (tool.approx === true)
304
+ turn.approx = true;
305
+ if (tool.status === "running")
306
+ running = true;
307
+ if (tool.status === "interrupted")
308
+ interrupted = true;
309
+ end = maxDefined(end, tool.endedAt);
310
+ for (const child of tool.children) {
311
+ if (child.status === "running")
312
+ running = running || child.kind === "subcall";
313
+ // 后台任务可能在回合结束后很久才结束,不拉长回合
314
+ if (child.kind === "subcall" || !child.background)
315
+ end = maxDefined(end, child.endedAt);
316
+ }
317
+ }
318
+ }
319
+ for (const usage of state.extraUsage.get(turn.id) ?? [])
320
+ accumulate(totals, { usage });
321
+ const last = [...turn.steps].reverse().find((s) => s.kind === "step");
322
+ if (running) {
323
+ turn.status = "running";
324
+ partial = true;
325
+ }
326
+ else if (interrupted)
327
+ turn.status = "interrupted";
328
+ else if (last?.status === "aborted")
329
+ turn.status = "aborted";
330
+ else if (last?.status === "error")
331
+ turn.status = "error";
332
+ if (!running && end !== undefined)
333
+ turn.endedAt = Math.max(end, turn.startedAt ?? end);
334
+ if (turn.startedAt !== undefined && turn.endedAt !== undefined) {
335
+ totals.durationMs = turn.endedAt - turn.startedAt;
336
+ duration += totals.durationMs;
337
+ timed = true;
338
+ }
339
+ turn.usage = finishTotals(totals);
340
+ mergeTotals(all, totals);
341
+ endedAt = maxDefined(endedAt, turn.endedAt);
342
+ }
343
+ for (const aux of state.aux) {
344
+ if (aux.usage !== undefined)
345
+ accumulate(all, { usage: aux.usage });
346
+ endedAt = maxDefined(endedAt, aux.endedAt);
347
+ }
348
+ if (timed)
349
+ all.durationMs = duration;
350
+ const startedAt = entryTime(input.header) ??
351
+ (input.entries[0] !== undefined ? entryTime(input.entries[0]) : undefined) ??
352
+ opts.now ??
353
+ 0;
354
+ const trace = {
355
+ version: 1,
356
+ sessionId: input.header.id,
357
+ cwd: input.header.cwd,
358
+ startedAt,
359
+ totals: finishTotals(all),
360
+ turns: state.turns,
361
+ aux: state.aux,
362
+ partial,
363
+ };
364
+ if (input.sessionFile !== undefined)
365
+ trace.sessionFile = input.sessionFile;
366
+ if (!partial && endedAt !== undefined)
367
+ trace.endedAt = endedAt;
368
+ return trace;
369
+ }
370
+ /** 在轨迹里找任务(子 Agent 节点);深度优先,先找到的为准。 */
371
+ export function findSubagent(trace, taskId) {
372
+ for (const turn of trace.turns)
373
+ for (const step of turn.steps) {
374
+ if (step.kind !== "step")
375
+ continue;
376
+ for (const tool of step.tools)
377
+ for (const child of tool.children)
378
+ if (child.kind === "subagent" && child.taskId === taskId)
379
+ return child;
380
+ }
381
+ return undefined;
382
+ }
@@ -0,0 +1,35 @@
1
+ /**
2
+ * 轨迹节点的正文预览与详情卡片(docs/wave6-plan.md §2.4:Enter 详情——概要 / 用量与缓存 / 参数与结果预览)。
3
+ * [W6-T1]
4
+ *
5
+ * 轨迹树不含正文;这里按节点的 `entryIds` 回会话条目取:回合 → 用户提示,请求 → 助手文字,工具 → 参数
6
+ * (JSON,截到 500 字符)与结果(截到 2000 字符),与 `sessions export --format md` 同一截断口径。
7
+ * 只给本机界面用(TUI 详情、line 模式标签);HTML / RPC 的预览由 W6-T2 另行脱敏。
8
+ */
9
+ import type { SessionEntry } from "../session/types.js";
10
+ import type { Theme } from "../tui/component.js";
11
+ import type { TraceRowNode } from "./flatten.js";
12
+ /** 参数预览上限(字符)。 */
13
+ export declare const ARGS_PREVIEW_MAX = 500;
14
+ /** 结果 / 提示 / 输出预览上限(字符)。 */
15
+ export declare const RESULT_PREVIEW_MAX = 2000;
16
+ export interface TraceEntryLookup {
17
+ entry(id: string): SessionEntry | undefined;
18
+ /** 工具参数里的路径相对它显示。 */
19
+ cwd?: string;
20
+ }
21
+ /** 由条目数组建查找表。 */
22
+ export declare function entryLookup(entries: readonly SessionEntry[], cwd?: string): TraceEntryLookup;
23
+ /** 行标签里来自正文的部分:回合 → 提示预览,工具 → 参数摘要。 */
24
+ export declare function describeNode(node: TraceRowNode, lookup: TraceEntryLookup): string | undefined;
25
+ /** 详情里的两段预览(标题 → 正文)。 */
26
+ export declare function nodePreviews(node: TraceRowNode, lookup: TraceEntryLookup): {
27
+ title: string;
28
+ text: string;
29
+ }[];
30
+ type Row = [label: string, value: string];
31
+ /** 概要与用量两组键值行。 */
32
+ export declare function summaryRows(node: TraceRowNode, theme: Theme, traceStart: number): Row[];
33
+ /** 详情卡片的行(不含标题与边框;宽度内折行)。 */
34
+ export declare function detailLines(node: TraceRowNode, lookup: TraceEntryLookup, width: number, theme: Theme, traceStart: number): string[];
35
+ export {};
@@ -0,0 +1,205 @@
1
+ /**
2
+ * 轨迹节点的正文预览与详情卡片(docs/wave6-plan.md §2.4:Enter 详情——概要 / 用量与缓存 / 参数与结果预览)。
3
+ * [W6-T1]
4
+ *
5
+ * 轨迹树不含正文;这里按节点的 `entryIds` 回会话条目取:回合 → 用户提示,请求 → 助手文字,工具 → 参数
6
+ * (JSON,截到 500 字符)与结果(截到 2000 字符),与 `sessions export --format md` 同一截断口径。
7
+ * 只给本机界面用(TUI 详情、line 模式标签);HTML / RPC 的预览由 W6-T2 另行脱敏。
8
+ */
9
+ import { formatDuration, msg } from "../i18n/index.js";
10
+ import { formatPercent, formatTokenCount, formatUsd } from "../modes/session-report.js";
11
+ import { toolSummary } from "../modes/interactive/tool-summary.js";
12
+ import { contentText } from "../session/reuse.js";
13
+ import { padToWidth, visibleWidth, wrapTextWithAnsi } from "../tui/ansi.js";
14
+ import { durationText } from "./format.js";
15
+ /** 参数预览上限(字符)。 */
16
+ export const ARGS_PREVIEW_MAX = 500;
17
+ /** 结果 / 提示 / 输出预览上限(字符)。 */
18
+ export const RESULT_PREVIEW_MAX = 2000;
19
+ /** 行内标签里的提示预览上限(字符)。 */
20
+ const LABEL_PREVIEW_MAX = 80;
21
+ /** 由条目数组建查找表。 */
22
+ export function entryLookup(entries, cwd) {
23
+ const map = new Map();
24
+ for (const entry of entries)
25
+ map.set(entry.id, entry);
26
+ return { entry: (id) => map.get(id), ...(cwd !== undefined ? { cwd } : {}) };
27
+ }
28
+ function oneLine(text, max) {
29
+ const flat = text.replace(/\s+/g, " ").trim();
30
+ return flat.length > max ? `${flat.slice(0, max - 1)}…` : flat;
31
+ }
32
+ function truncate(text, max) {
33
+ return text.length > max
34
+ ? `${text.slice(0, max)}\n${msg().trace.detail.truncated(text.length)}`
35
+ : text;
36
+ }
37
+ function messageOf(lookup, id) {
38
+ const entry = id === undefined ? undefined : lookup.entry(id);
39
+ return entry?.type === "message" ? entry.message : undefined;
40
+ }
41
+ function toolArgs(lookup, node) {
42
+ if (node.kind !== "tool")
43
+ return undefined;
44
+ const m = messageOf(lookup, node.entryIds[0]);
45
+ if (m?.role !== "assistant")
46
+ return undefined;
47
+ for (const block of m.content)
48
+ if (block.type === "toolCall" && block.id === node.id)
49
+ return block.arguments;
50
+ return undefined;
51
+ }
52
+ /** 行标签里来自正文的部分:回合 → 提示预览,工具 → 参数摘要。 */
53
+ export function describeNode(node, lookup) {
54
+ if (node.kind === "turn") {
55
+ const m = messageOf(lookup, node.id);
56
+ return m?.role === "user" ? oneLine(contentText(m.content), LABEL_PREVIEW_MAX) : undefined;
57
+ }
58
+ if (node.kind === "tool") {
59
+ const summary = toolSummary(node.name, toolArgs(lookup, node), lookup.cwd);
60
+ return summary === "" ? undefined : oneLine(summary, LABEL_PREVIEW_MAX);
61
+ }
62
+ return undefined;
63
+ }
64
+ /** 详情里的两段预览(标题 → 正文)。 */
65
+ export function nodePreviews(node, lookup) {
66
+ const d = msg().trace.detail;
67
+ const out = [];
68
+ if (node.kind === "turn") {
69
+ const m = messageOf(lookup, node.id);
70
+ if (m?.role === "user")
71
+ out.push({ title: d.input, text: truncate(contentText(m.content), RESULT_PREVIEW_MAX) });
72
+ }
73
+ else if (node.kind === "step") {
74
+ const m = messageOf(lookup, node.id);
75
+ if (m?.role === "assistant") {
76
+ const text = m.content
77
+ .flatMap((b) => (b.type === "text" && b.text.trim() !== "" ? [b.text] : []))
78
+ .join("\n");
79
+ if (text !== "")
80
+ out.push({ title: d.output, text: truncate(text, RESULT_PREVIEW_MAX) });
81
+ }
82
+ }
83
+ else if (node.kind === "tool") {
84
+ const args = toolArgs(lookup, node);
85
+ if (args !== undefined)
86
+ out.push({ title: d.args, text: truncate(JSON.stringify(args, null, 2), ARGS_PREVIEW_MAX) });
87
+ const r = messageOf(lookup, node.entryIds[1]);
88
+ if (r?.role === "toolResult")
89
+ out.push({ title: d.result, text: truncate(contentText(r.content), RESULT_PREVIEW_MAX) });
90
+ }
91
+ return out;
92
+ }
93
+ function usageRows(usage, cost) {
94
+ const d = msg().trace.detail;
95
+ if (usage === undefined)
96
+ return [];
97
+ const t = formatTokenCount;
98
+ const rows = [
99
+ [
100
+ d.usage,
101
+ d.usageValue(t(usage.input), t(usage.output), t(usage.cacheRead), t(usage.cacheWrite)),
102
+ ],
103
+ ];
104
+ const prompt = usage.input + usage.cacheRead + usage.cacheWrite;
105
+ if (prompt > 0)
106
+ rows.push([d.cacheHit, formatPercent(usage.cacheRead / prompt)]);
107
+ if (cost !== undefined)
108
+ rows.push([d.cost, formatUsd(cost)]);
109
+ return rows;
110
+ }
111
+ /** 概要与用量两组键值行。 */
112
+ export function summaryRows(node, theme, traceStart) {
113
+ const d = msg().trace.detail;
114
+ if (node.kind === "more" || node.kind === "aux_group")
115
+ return [];
116
+ const rows = [
117
+ [d.kind, node.kind],
118
+ [d.status, msg().trace.status[node.status]],
119
+ ];
120
+ if (node.startedAt !== undefined)
121
+ rows.push([d.start, `+${formatDuration(Math.max(0, node.startedAt - traceStart), "precise")}`]);
122
+ const duration = durationText(node, theme);
123
+ if (duration !== "")
124
+ rows.push([d.duration, duration]);
125
+ if (node.approx === true)
126
+ rows.push([d.approx, d.approxValue]);
127
+ switch (node.kind) {
128
+ case "turn":
129
+ if (node.origin !== undefined)
130
+ rows.push([d.origin, node.origin]);
131
+ rows.push(...usageRows(node.usage, node.usage.cost));
132
+ break;
133
+ case "step":
134
+ rows.push([d.model, `${node.provider}/${node.model}`], [d.attempt, String(node.attempt)]);
135
+ if (node.fallbackFrom !== undefined)
136
+ rows.push([d.fallbackFrom, node.fallbackFrom]);
137
+ if (node.ttftMs !== undefined)
138
+ rows.push([d.ttft, formatDuration(node.ttftMs, "precise")]);
139
+ if (node.tps !== undefined)
140
+ rows.push([d.tps, `${node.tps} tok/s`]);
141
+ if (node.thinkingLevel !== undefined)
142
+ rows.push([d.thinking, node.thinkingLevel]);
143
+ if (node.stopReason !== "")
144
+ rows.push([d.stopReason, node.stopReason]);
145
+ if (node.errorMessage !== undefined)
146
+ rows.push([d.error, node.errorMessage]);
147
+ rows.push(...usageRows(node.usage, node.usage.cost?.total));
148
+ break;
149
+ case "tool":
150
+ if (node.approvalMs !== undefined)
151
+ rows.push([d.approval, formatDuration(node.approvalMs, "precise")]);
152
+ if (node.denied === true)
153
+ rows.push([d.denied, d.yes]);
154
+ break;
155
+ case "subagent":
156
+ rows.push([d.task, `${node.taskId} ${node.agent}`], [d.runner, node.runner]);
157
+ if (node.background)
158
+ rows.push([d.background, d.yes]);
159
+ if (node.turns !== undefined)
160
+ rows.push([d.turns, String(node.turns)]);
161
+ rows.push(...usageRows(node.usage, node.costUsd));
162
+ if (node.childRef?.sessionFile !== undefined)
163
+ rows.push([d.childFile, node.childRef.sessionFile]);
164
+ if (node.childMissing === true)
165
+ rows.push([d.childFile, d.childMissing]);
166
+ break;
167
+ case "external_turn":
168
+ rows.push([d.stopReason, node.stopReason], [d.files, String(node.filesTouched)]);
169
+ if (node.tools.length > 0)
170
+ rows.push([d.tools, node.tools.map((t) => `${t.kind}:${t.status}`).join(" ")]);
171
+ break;
172
+ case "retry_wait":
173
+ if (node.reason !== undefined)
174
+ rows.push([d.reason, node.reason]);
175
+ break;
176
+ case "compaction":
177
+ if (node.tokensBefore !== undefined)
178
+ rows.push([d.usage, formatTokenCount(node.tokensBefore)]);
179
+ break;
180
+ case "aux":
181
+ rows.push(...usageRows(node.usage, node.usage?.cost?.total));
182
+ break;
183
+ default:
184
+ break;
185
+ }
186
+ return rows;
187
+ }
188
+ /** 详情卡片的行(不含标题与边框;宽度内折行)。 */
189
+ export function detailLines(node, lookup, width, theme, traceStart) {
190
+ const rows = summaryRows(node, theme, traceStart);
191
+ // 键列宽取最长的键(en 的 Waiting for approval 比 16 列宽,封顶会让这一行错位)
192
+ const labelWidth = Math.max(0, ...rows.map(([label]) => visibleWidth(label)));
193
+ const out = [];
194
+ const valueWidth = Math.max(8, width - labelWidth - 2);
195
+ for (const [label, value] of rows) {
196
+ const wrapped = wrapTextWithAnsi(value, valueWidth);
197
+ wrapped.forEach((line, i) => out.push(`${i === 0 ? theme.fg("muted", padToWidth(label, labelWidth)) : " ".repeat(labelWidth)} ${line}`));
198
+ }
199
+ for (const preview of nodePreviews(node, lookup)) {
200
+ out.push("", theme.bold(preview.title));
201
+ for (const line of preview.text.split("\n"))
202
+ out.push(...wrapTextWithAnsi(line, Math.max(8, width)));
203
+ }
204
+ return out;
205
+ }