@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
@@ -25,6 +25,7 @@ import { PLAN_APPROVED_PROMPT, PLAN_APPROVED_TYPE, PLAN_MODE_BRIEF, PLAN_MODE_EX
25
25
  import { PLAN_CUSTOM_TYPE, PLAN_STATE_CUSTOM_TYPE, currentTodos, executionMode, latestPlan, latestPlanState, maxPlanVersion, resolvePlanDirectory, writePlanFile, } from "../plan/store.js";
26
26
  import { APPROVE_REPLY, PLAN_NOTICE_TYPE, registerPlanController, } from "../plan/controller.js";
27
27
  import { TODO_CUSTOM_TYPE } from "../tools/todo.js";
28
+ import { msg } from "../i18n/index.js";
28
29
  export function createPlanExtensionFactory(options) {
29
30
  return ({ core }) => (core.depth > 0 ? undefined : new PlanExtension(core, options));
30
31
  }
@@ -330,8 +331,7 @@ class PlanExtension {
330
331
  }
331
332
  noticeText(plan) {
332
333
  const target = permissionModeLabel(executionMode(undefined, this.pre));
333
- const where = plan.filePath === undefined ? "" : `(${plan.filePath})`;
334
- return `计划 v${plan.version} 待审批${where}:回复 1 批准并执行(${target})· 2 以 Accept edits 执行 · 3 以 Auto 执行;回复其它内容作为修改意见,留在 Plan 模式。`;
334
+ return msg().session.plan.pendingNotice(plan.version, plan.filePath, target);
335
335
  }
336
336
  // -------------------------------------------------------------------------
337
337
  // 审批与交接
@@ -11,6 +11,7 @@ import type { SessionManager } from "../session/manager.js";
11
11
  import type { SessionEntry } from "../session/types.js";
12
12
  import type { Agent } from "./agent.js";
13
13
  import type { SessionCacheStats, SessionState, SessionStats } from "./types.js";
14
+ import type { QuotaUpdateEvent } from "./types-w6.js";
14
15
  export interface StateInput {
15
16
  agent: Agent;
16
17
  manager: SessionManager;
@@ -31,6 +32,8 @@ export interface StatsInput {
31
32
  contextWindow: number | undefined;
32
33
  /** [W3-C1b] 会话层缓存控制器的统计(未接线时缺省)。 */
33
34
  cache?: SessionCacheStats;
35
+ /** [W6-O] 最近一次 `quota_update`。 */
36
+ quota?: QuotaUpdateEvent | undefined;
34
37
  }
35
38
  export declare function computeStats(input: StatsInput): SessionStats;
36
39
  /** 缓存命中率 = cacheRead /(input + cacheRead + cacheWrite);分母为 0 → undefined(设计 §9.1)。 */
@@ -37,8 +37,21 @@ function addUsage(totals, usage) {
37
37
  ? usage.totalTokens
38
38
  : usage.input + usage.output + usage.cacheRead + usage.cacheWrite;
39
39
  }
40
+ /** [W6-O] 订阅计费(`billing: "subscription"`)的请求单列,不折算美元。 */
41
+ function addSubscription(stats, provider, usage) {
42
+ if (usage.billing !== "subscription")
43
+ return;
44
+ const sub = (stats.subscription ??= { requests: 0, byProvider: {} });
45
+ sub.requests++;
46
+ const row = (sub.byProvider[provider] ??= { requests: 0, input: 0, output: 0, cacheRead: 0 });
47
+ row.requests++;
48
+ row.input += usage.input;
49
+ row.output += usage.output;
50
+ row.cacheRead += usage.cacheRead;
51
+ }
40
52
  export function computeStats(input) {
41
53
  const tokens = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 };
54
+ const sub = {};
42
55
  let userMessages = 0;
43
56
  let assistantMessages = 0;
44
57
  let toolCalls = 0;
@@ -61,11 +74,13 @@ export function computeStats(input) {
61
74
  toolCalls += message.content.filter((block) => block.type === "toolCall").length;
62
75
  addUsage(tokens, message.usage);
63
76
  addCost(message.usage);
77
+ addSubscription(sub, message.provider, message.usage);
64
78
  }
65
79
  }
66
80
  else if (entry.type === "usage") {
67
81
  addUsage(tokens, entry.usage);
68
82
  addCost(entry.usage);
83
+ addSubscription(sub, entry.provider, entry.usage);
69
84
  }
70
85
  else if ((entry.type === "compaction" || entry.type === "branch_summary") && entry.usage) {
71
86
  addUsage(tokens, entry.usage);
@@ -95,6 +110,11 @@ export function computeStats(input) {
95
110
  stats.cacheHitRate = rate;
96
111
  if (input.cache !== undefined)
97
112
  stats.cache = input.cache;
113
+ if (sub.subscription !== undefined) {
114
+ stats.subscription = sub.subscription;
115
+ if (input.quota !== undefined)
116
+ stats.subscription.quota = input.quota;
117
+ }
98
118
  return stats;
99
119
  }
100
120
  /** 缓存命中率 = cacheRead /(input + cacheRead + cacheWrite);分母为 0 → undefined(设计 §9.1)。 */
@@ -14,11 +14,14 @@
14
14
  * - 轮数耗尽且最后停在工具结果上:以 `toolChoice:"none"` 再跑一轮要最终报告,状态 `max_turns`。
15
15
  * - broker 包一层,请求带 `context{depth, parentToolCallId, taskId}`,审批事件转发到父会话;
16
16
  * [RW-B] 父的检查点钩子(worktree 里运行时不记);[W3-C1b] 子会话命中与重计费汇总进父。
17
+ * - [W6-A] 句柄外露 `observe` / `entries`(子 Agent 视图跟随)与 `message`(视图里直接发的消息,
18
+ * `origin: "direct"`:运行中 followUp,空闲开新一轮);一轮收尾时才入队、没赶上的 followUp 接着再跑一轮。
17
19
  */
18
20
  import type { CheckpointHooks } from "../checkpoints/types.js";
19
21
  import type { PermissionPipelineApi } from "../permissions/types.js";
20
22
  import { SessionManager } from "../session/manager.js";
21
23
  import type { AgentMessage } from "../session/types.js";
24
+ import type { MessageOrigin } from "../ai/types.js";
22
25
  import type { SubagentRequest, SubagentResult, SubagentRunner } from "../tools/types.js";
23
26
  import type { AgentSessionOptions } from "./session-core.js";
24
27
  import { DEFAULT_SUBAGENT_CONCURRENCY, SubagentPool, TASK_CUSTOM_TYPE, type AmaRunnerSpec, type RegistryHost } from "./subagent-registry.js";
@@ -49,7 +52,18 @@ export interface SubagentParent extends RegistryHost {
49
52
  export interface ChildSession {
50
53
  readonly manager: SessionManager;
51
54
  readonly messages: readonly AgentMessage[];
52
- prompt(text: string): Promise<unknown>;
55
+ prompt(text: string, options?: {
56
+ origin?: MessageOrigin;
57
+ }): Promise<unknown>;
58
+ /** [W6-A] 视图里直接发的消息(运行中排到回合结束)。 */
59
+ followUp?(text: string, options?: {
60
+ origin?: MessageOrigin;
61
+ }): Promise<unknown>;
62
+ /** [W6-A] 取出排队消息(一轮收尾时才入队、没被消费的)。 */
63
+ clearQueue?(): {
64
+ steering: string[];
65
+ followUp: string[];
66
+ };
53
67
  abort(): Promise<void>;
54
68
  subscribe(listener: (event: SessionEvent) => void): () => void;
55
69
  getStats(): SessionStats;
@@ -14,6 +14,8 @@
14
14
  * - 轮数耗尽且最后停在工具结果上:以 `toolChoice:"none"` 再跑一轮要最终报告,状态 `max_turns`。
15
15
  * - broker 包一层,请求带 `context{depth, parentToolCallId, taskId}`,审批事件转发到父会话;
16
16
  * [RW-B] 父的检查点钩子(worktree 里运行时不记);[W3-C1b] 子会话命中与重计费汇总进父。
17
+ * - [W6-A] 句柄外露 `observe` / `entries`(子 Agent 视图跟随)与 `message`(视图里直接发的消息,
18
+ * `origin: "direct"`:运行中 followUp,空闲开新一轮);一轮收尾时才入队、没赶上的 followUp 接着再跑一轮。
17
19
  */
18
20
  import { AmaError } from "../errors.js";
19
21
  import { PermissionPipeline } from "../permissions/pipeline.js";
@@ -183,17 +185,27 @@ async function startAmaChild(parent, spec, createChild, run) {
183
185
  const onAbort = () => void child.abort();
184
186
  run.signal.addEventListener("abort", onAbort, { once: true });
185
187
  let billed = { cacheRead: 0, prompt: 0, reBilled: 0 };
186
- const runOnce = async (prompt) => {
188
+ let active = false;
189
+ const runOnce = async (prompt, origin) => {
187
190
  const startTurns = turns;
188
191
  let error;
192
+ active = true;
189
193
  try {
190
194
  if (run.signal.aborted)
191
195
  throw new AmaError("aborted", "aborted");
192
- await child.prompt(prompt);
196
+ await child.prompt(prompt, origin === undefined ? {} : { origin });
197
+ // [W6-A] 收尾阶段才入队的 followUp(只可能来自视图)留在队列里:接着再跑一轮
198
+ for (;;) {
199
+ const left = child.clearQueue?.().followUp ?? [];
200
+ if (left.length === 0 || run.signal.aborted)
201
+ break;
202
+ await child.prompt(left.join("\n\n"), { origin: "direct" });
203
+ }
193
204
  }
194
205
  catch (caught) {
195
206
  error = caught instanceof Error ? caught.message : String(caught);
196
207
  }
208
+ active = false;
197
209
  const exhausted = error === undefined && !run.signal.aborted && turns - startTurns >= maxTurns && toolUse;
198
210
  if (exhausted) {
199
211
  finalRound = true;
@@ -216,7 +228,7 @@ async function startAmaChild(parent, spec, createChild, run) {
216
228
  result.sessionFile = file;
217
229
  return result;
218
230
  };
219
- let current = runOnce(run.prompt);
231
+ let current = runOnce(run.prompt, spec.origin);
220
232
  const handle = {
221
233
  id: manager.id,
222
234
  model: `${model.provider}/${model.id}`,
@@ -224,6 +236,17 @@ async function startAmaChild(parent, spec, createChild, run) {
224
236
  send: async (text) => {
225
237
  current = runOnce(text);
226
238
  },
239
+ observe: (listener) => child.subscribe(listener),
240
+ entries: () => child.manager.branch(),
241
+ message: async (text, when) => {
242
+ if (when === "send") {
243
+ current = runOnce(text, "direct");
244
+ return;
245
+ }
246
+ if (!active || child.followUp === undefined)
247
+ throw new AmaError("task_idle", "the sub-agent is not running");
248
+ await child.followUp(text, { origin: "direct" });
249
+ },
227
250
  wait: () => current,
228
251
  stop: () => child.abort(),
229
252
  dispose: async () => {
@@ -12,12 +12,17 @@
12
12
  * 只由增量驱动、不起计时器);
13
13
  * `ticks: false`(`ui.animation: false`)时不发,界面在 message_end 时刷新。
14
14
  *
15
+ * [W6-C0] 拆成「测量」与「发 tick」:子会话(depth > 0)也装、只测量不发 tick;每个请求结束时通知
16
+ * `onRequestEnd` 的订阅者(`session-trace-writer.ts` 据此写 `ama.trace step`);`telemetryOf(core)` 取本会话实例。
17
+ *
15
18
  * 数据从 `getStats().telemetry` 取(`contributeStats`):进行中的请求出了首 token 后 `last` 即指向它(只有
16
19
  * `requestAt / firstTokenAt / ttftMs`),结束后补齐 `doneAt / outputTokens / tps`;`sessionStartedAt` 是扩展创建(本进程打开会话)的时刻。
17
20
  */
21
+ import type { AssistantMessage } from "../ai/types.js";
22
+ import type { SessionCore } from "./session-core.js";
18
23
  import type { SessionExtension, SessionExtensionFactory } from "./session-extensions.js";
19
24
  import type { SessionEvent } from "./types.js";
20
- import type { SessionTelemetry } from "./types-w5.js";
25
+ import type { RequestTelemetry, SessionTelemetry } from "./types-w5.js";
21
26
  export declare const TELEMETRY_TICK_MS = 500;
22
27
  export declare const TELEMETRY_WINDOW_MS = 2000;
23
28
  export interface TelemetryDeps {
@@ -27,13 +32,22 @@ export interface TelemetryDeps {
27
32
  /** false:不发 tick(`ui.animation: false`)。缺省 true。 */
28
33
  ticks?: boolean;
29
34
  }
35
+ /** 一个 turn 请求结束(成功、失败或被中断)时的记录。 */
36
+ export type RequestEndListener = (record: RequestTelemetry, message: AssistantMessage | undefined) => void;
30
37
  export type TelemetryExtension = SessionExtension & {
31
38
  snapshot(): SessionTelemetry;
39
+ /** [W6-C0] 订阅请求结束;返回取消函数。 */
40
+ onRequestEnd(listener: RequestEndListener): () => void;
32
41
  };
42
+ /** [W6-C0] 本会话的遥测扩展(组装表装了才有)。 */
43
+ export declare function telemetryOf(core: SessionCore): TelemetryExtension | undefined;
33
44
  /** 一段增量文本的 token 估算(不取整,逐块累加不放大)。 */
34
45
  export declare function deltaTokens(text: string): number;
35
46
  export declare function createTelemetryExtension(deps?: TelemetryDeps): TelemetryExtension;
36
- /** 组装表用的工厂:只装主会话(depth 0);`ui.animation: false` 不发 tick。 */
47
+ /**
48
+ * 组装表用的工厂:主会话测量并发 tick(`ui.animation: false` 不发);[W6-C0] 子会话(depth > 0)也装,
49
+ * 只测量(供 `ama.trace` 与子 Agent 视图),不发 tick。
50
+ */
37
51
  export declare function telemetryFactory(ui?: {
38
52
  animation?: boolean;
39
53
  }): SessionExtensionFactory;
@@ -12,6 +12,9 @@
12
12
  * 只由增量驱动、不起计时器);
13
13
  * `ticks: false`(`ui.animation: false`)时不发,界面在 message_end 时刷新。
14
14
  *
15
+ * [W6-C0] 拆成「测量」与「发 tick」:子会话(depth > 0)也装、只测量不发 tick;每个请求结束时通知
16
+ * `onRequestEnd` 的订阅者(`session-trace-writer.ts` 据此写 `ama.trace step`);`telemetryOf(core)` 取本会话实例。
17
+ *
15
18
  * 数据从 `getStats().telemetry` 取(`contributeStats`):进行中的请求出了首 token 后 `last` 即指向它(只有
16
19
  * `requestAt / firstTokenAt / ttftMs`),结束后补齐 `doneAt / outputTokens / tps`;`sessionStartedAt` 是扩展创建(本进程打开会话)的时刻。
17
20
  */
@@ -19,6 +22,11 @@ export const TELEMETRY_TICK_MS = 500;
19
22
  export const TELEMETRY_WINDOW_MS = 2000;
20
23
  /** 不足这么长(自首 token 起)不算速率:开头几块或整块到达的回复会把速率放大到无意义。 */
21
24
  const MIN_SPAN_MS = 250;
25
+ const byCore = new WeakMap();
26
+ /** [W6-C0] 本会话的遥测扩展(组装表装了才有)。 */
27
+ export function telemetryOf(core) {
28
+ return byCore.get(core);
29
+ }
22
30
  /** 一段增量文本的 token 估算(不取整,逐块累加不放大)。 */
23
31
  export function deltaTokens(text) {
24
32
  let wide = 0;
@@ -122,6 +130,7 @@ export function createTelemetryExtension(deps = {}) {
122
130
  let sumOutput = 0;
123
131
  let sumMs = 0;
124
132
  let lastTickAt = Number.NEGATIVE_INFINITY;
133
+ const listeners = new Set();
125
134
  const finish = (tracker, message) => {
126
135
  if (tracker.finished)
127
136
  return;
@@ -130,6 +139,8 @@ export function createTelemetryExtension(deps = {}) {
130
139
  current = undefined;
131
140
  const r = tracker.record;
132
141
  last = { ...r };
142
+ for (const listener of listeners)
143
+ listener({ ...r }, message);
133
144
  const failed = message === undefined || message.stopReason === "error";
134
145
  if (!failed && r.firstTokenAt !== undefined && r.doneAt !== undefined) {
135
146
  const ms = r.doneAt - r.firstTokenAt;
@@ -218,14 +229,25 @@ export function createTelemetryExtension(deps = {}) {
218
229
  stats.telemetry = snapshot();
219
230
  },
220
231
  snapshot,
232
+ onRequestEnd(listener) {
233
+ listeners.add(listener);
234
+ return () => void listeners.delete(listener);
235
+ },
221
236
  };
222
237
  }
223
- /** 组装表用的工厂:只装主会话(depth 0);`ui.animation: false` 不发 tick。 */
238
+ /**
239
+ * 组装表用的工厂:主会话测量并发 tick(`ui.animation: false` 不发);[W6-C0] 子会话(depth > 0)也装,
240
+ * 只测量(供 `ama.trace` 与子 Agent 视图),不发 tick。
241
+ */
224
242
  export function telemetryFactory(ui) {
225
- return ({ core }) => core.depth > 0
226
- ? undefined
227
- : createTelemetryExtension({
228
- emit: (event) => core.emit(event),
229
- ticks: ui?.animation !== false,
230
- });
243
+ return ({ core }) => {
244
+ const extension = core.depth > 0
245
+ ? createTelemetryExtension({ ticks: false })
246
+ : createTelemetryExtension({
247
+ emit: (event) => core.emit(event),
248
+ ticks: ui?.animation !== false,
249
+ });
250
+ byCore.set(core, extension);
251
+ return extension;
252
+ };
231
253
  }
@@ -41,7 +41,8 @@ function requestContext(core, request) {
41
41
  taskId = data.taskId;
42
42
  }
43
43
  const origin = source?.origin;
44
- if (depth === 0 && taskId === undefined && origin === undefined)
44
+ const toolCallId = source?.toolCallId;
45
+ if (depth === 0 && taskId === undefined && origin === undefined && toolCallId === undefined)
45
46
  return undefined;
46
47
  const context = {};
47
48
  if (depth > 0)
@@ -50,6 +51,8 @@ function requestContext(core, request) {
50
51
  context.taskId = taskId;
51
52
  if (origin !== undefined)
52
53
  context.origin = origin;
54
+ if (toolCallId !== undefined)
55
+ context.toolCallId = toolCallId;
53
56
  return context;
54
57
  }
55
58
  /** 审批链:依次问每个 broker,第一个给出决定的为准;全部弃权 → deny。 */
@@ -199,7 +202,7 @@ export async function gateToolCall(core, call, ctx) {
199
202
  toolName: call.name,
200
203
  input,
201
204
  reason: approvalReason,
202
- context: { depth: core.depth, readFiles: core.readFiles },
205
+ context: { depth: core.depth, readFiles: core.readFiles, toolCallId: call.id },
203
206
  };
204
207
  if (hookReason !== undefined)
205
208
  request.hookReason = hookReason;
@@ -0,0 +1,27 @@
1
+ /**
2
+ * 轨迹写入(docs/wave6-plan.md §2.2、D5)。[W6-C0]
3
+ *
4
+ * 会话扩展:订阅事件,把计时写成 `custom{customType:"ama.trace"}` 条目(`trace/types.ts` 的 `TraceEntryData`)。
5
+ * - `step`:每个 turn 请求一条(成功、失败、被重试掉的都写),在 `turn_end` 时写——此时 assistant 与该批
6
+ * toolResult 都已落盘,所以条目在 toolResult 之后(无工具时紧跟 assistant)。请求计时来自遥测扩展
7
+ * (`telemetryOf(core).onRequestEnd`),工具起止来自 `tool_execution_start / end`,审批等待来自带
8
+ * `context.toolCallId` 的 `permission_request` → `permission_resolved`;中断而没有 `turn_end` 时由
9
+ * `agent_end` 兜底写一条 `status: "aborted"`。
10
+ * - `retry_wait`(`auto_retry_start`)、`fallback`(`model_fallback`)、`compaction`(`compaction_start / end`)、
11
+ * `aux`(`usage` 条目:保温 / 分类器请求)、`external_turn`(外部 Agent 回合骨架,由任务注册表经
12
+ * `appendTraceEntry` 写,见 `agents/task-record.ts`)。
13
+ *
14
+ * 约束:只追加、不改已落条目;`custom` 不进上下文(投影跳过),所以请求字节与缓存前缀不变;只记 id、
15
+ * 时间与计数,**不记正文**(提示、参数、结果、外部工具标题)。depth > 0 的子会话也装(只落盘,不发事件)。
16
+ */
17
+ import { type TraceEntryData } from "../trace/types.js";
18
+ import type { SessionCore } from "./session-core.js";
19
+ import type { SessionExtension, SessionExtensionFactory } from "./session-extensions.js";
20
+ export interface TraceWriterDeps {
21
+ now?(): number;
22
+ }
23
+ /** 追加一条 `ama.trace`(不发 `entry_appended` 以外的事件)。 */
24
+ export declare function appendTraceEntry(core: Pick<SessionCore, "appendEntry">, data: TraceEntryData): void;
25
+ export declare function createTraceWriter(core: SessionCore, deps?: TraceWriterDeps): SessionExtension;
26
+ /** 组装表用的工厂:主会话与子会话都装。 */
27
+ export declare function traceWriterFactory(deps?: TraceWriterDeps): SessionExtensionFactory;
@@ -0,0 +1,253 @@
1
+ /**
2
+ * 轨迹写入(docs/wave6-plan.md §2.2、D5)。[W6-C0]
3
+ *
4
+ * 会话扩展:订阅事件,把计时写成 `custom{customType:"ama.trace"}` 条目(`trace/types.ts` 的 `TraceEntryData`)。
5
+ * - `step`:每个 turn 请求一条(成功、失败、被重试掉的都写),在 `turn_end` 时写——此时 assistant 与该批
6
+ * toolResult 都已落盘,所以条目在 toolResult 之后(无工具时紧跟 assistant)。请求计时来自遥测扩展
7
+ * (`telemetryOf(core).onRequestEnd`),工具起止来自 `tool_execution_start / end`,审批等待来自带
8
+ * `context.toolCallId` 的 `permission_request` → `permission_resolved`;中断而没有 `turn_end` 时由
9
+ * `agent_end` 兜底写一条 `status: "aborted"`。
10
+ * - `retry_wait`(`auto_retry_start`)、`fallback`(`model_fallback`)、`compaction`(`compaction_start / end`)、
11
+ * `aux`(`usage` 条目:保温 / 分类器请求)、`external_turn`(外部 Agent 回合骨架,由任务注册表经
12
+ * `appendTraceEntry` 写,见 `agents/task-record.ts`)。
13
+ *
14
+ * 约束:只追加、不改已落条目;`custom` 不进上下文(投影跳过),所以请求字节与缓存前缀不变;只记 id、
15
+ * 时间与计数,**不记正文**(提示、参数、结果、外部工具标题)。depth > 0 的子会话也装(只落盘,不发事件)。
16
+ */
17
+ import { formatModelRef } from "../ai/providers/channels.js";
18
+ import { TRACE_CUSTOM_TYPE, TRACE_REASON_MAX, } from "../trace/types.js";
19
+ import { telemetryOf } from "./session-telemetry.js";
20
+ /** 追加一条 `ama.trace`(不发 `entry_appended` 以外的事件)。 */
21
+ export function appendTraceEntry(core, data) {
22
+ core.appendEntry({ type: "custom", customType: TRACE_CUSTOM_TYPE, data });
23
+ }
24
+ function clip(text) {
25
+ if (text === undefined)
26
+ return undefined;
27
+ const one = text.replace(/\s+/g, " ").trim();
28
+ return one.length > TRACE_REASON_MAX ? `${one.slice(0, TRACE_REASON_MAX - 1)}…` : one;
29
+ }
30
+ const AUX_PURPOSE = {
31
+ warm: "cache_warm",
32
+ classify: "permission_classify",
33
+ };
34
+ export function createTraceWriter(core, deps = {}) {
35
+ const now = deps.now ?? Date.now;
36
+ let request;
37
+ let assistantEntryId;
38
+ let attempt = 1;
39
+ let fallbackFrom;
40
+ /** 本次 turn 请求发出时是否处于回退(切回主模型可能早于 turn_end)。 */
41
+ let requestFallbackFrom;
42
+ const tools = new Map();
43
+ const subcalls = new Map();
44
+ /** toolCallId → 审批等待(请求可能早于 tool_execution_start)。 */
45
+ const approvals = new Map();
46
+ const pendingApprovals = new Map();
47
+ let compaction;
48
+ let compactionEntryId;
49
+ /** 非 turn 请求(保温 / 分类器)最近一次的开始时刻。 */
50
+ const auxStarted = new Map();
51
+ let unsubscribe;
52
+ const write = (data) => {
53
+ try {
54
+ appendTraceEntry(core, data);
55
+ }
56
+ catch (error) {
57
+ core.log("warn", `ama.trace append failed: ${String(error)}`);
58
+ }
59
+ };
60
+ const subscribe = () => {
61
+ if (unsubscribe !== undefined)
62
+ return;
63
+ unsubscribe = telemetryOf(core)?.onRequestEnd((record) => {
64
+ request = record;
65
+ });
66
+ };
67
+ const dirty = () => request !== undefined || tools.size > 0 || subcalls.size > 0;
68
+ const writeStep = (message, aborted) => {
69
+ const ids = new Set(message?.content.flatMap((block) => (block.type === "toolCall" ? [block.id] : [])) ?? []);
70
+ const stepTools = [];
71
+ for (const [id, timing] of tools) {
72
+ if (ids.size > 0 && !ids.has(id) && !aborted)
73
+ continue;
74
+ const approvalMs = approvals.get(id);
75
+ stepTools.push(approvalMs === undefined ? timing : { ...timing, approvalMs });
76
+ tools.delete(id);
77
+ approvals.delete(id);
78
+ }
79
+ const step = { kind: "step", attempt };
80
+ if (assistantEntryId !== undefined)
81
+ step.assistantEntryId = assistantEntryId;
82
+ const r = request;
83
+ if (r !== undefined) {
84
+ step.requestAt = r.requestAt;
85
+ if (r.firstTokenAt !== undefined)
86
+ step.firstTokenAt = r.firstTokenAt;
87
+ if (r.doneAt !== undefined)
88
+ step.doneAt = r.doneAt;
89
+ if (r.outputTokens !== undefined)
90
+ step.outputTokens = r.outputTokens;
91
+ if (r.tps !== undefined)
92
+ step.tps = Math.round(r.tps * 10) / 10;
93
+ }
94
+ if (requestFallbackFrom !== undefined)
95
+ step.fallbackFrom = requestFallbackFrom;
96
+ requestFallbackFrom = undefined;
97
+ if (aborted)
98
+ step.status = "aborted";
99
+ if (stepTools.length > 0)
100
+ step.tools = stepTools;
101
+ if (subcalls.size > 0)
102
+ step.subcalls = [...subcalls.values()];
103
+ subcalls.clear();
104
+ request = undefined;
105
+ assistantEntryId = undefined;
106
+ write(step);
107
+ // 成功的请求之后,下一次请求重新从第 1 次尝试算
108
+ if (!aborted && message !== undefined && message.stopReason !== "error")
109
+ attempt = 1;
110
+ };
111
+ const onEvent = (event) => {
112
+ subscribe();
113
+ switch (event.type) {
114
+ case "entry_appended": {
115
+ const entry = event.entry;
116
+ if (entry.type === "message" && entry.message.role === "assistant")
117
+ assistantEntryId = entry.id;
118
+ else if (entry.type === "compaction")
119
+ compactionEntryId = entry.id;
120
+ else if (entry.type === "usage") {
121
+ const startedAt = auxStarted.get(entry.kind);
122
+ auxStarted.delete(entry.kind);
123
+ write({
124
+ kind: "aux",
125
+ purpose: entry.kind,
126
+ usageEntryId: entry.id,
127
+ ...(startedAt !== undefined ? { startedAt } : {}),
128
+ endedAt: now(),
129
+ });
130
+ }
131
+ return;
132
+ }
133
+ case "tool_execution_start":
134
+ if (event.parentToolCallId !== undefined)
135
+ subcalls.set(event.toolCallId, {
136
+ id: event.toolCallId,
137
+ parentId: event.parentToolCallId,
138
+ name: event.toolName,
139
+ startedAt: now(),
140
+ });
141
+ else
142
+ tools.set(event.toolCallId, { id: event.toolCallId, startedAt: now() });
143
+ return;
144
+ case "tool_execution_end": {
145
+ const sub = subcalls.get(event.toolCallId);
146
+ if (event.parentToolCallId !== undefined && sub !== undefined) {
147
+ sub.endedAt = now();
148
+ if (event.isError)
149
+ sub.isError = true;
150
+ return;
151
+ }
152
+ const timing = tools.get(event.toolCallId) ?? { id: event.toolCallId, startedAt: now() };
153
+ timing.endedAt = now();
154
+ if (event.denied === true)
155
+ timing.denied = true;
156
+ tools.set(event.toolCallId, timing);
157
+ return;
158
+ }
159
+ case "permission_request": {
160
+ const toolCallId = event.context?.toolCallId;
161
+ if (toolCallId !== undefined)
162
+ pendingApprovals.set(event.requestId, { toolCallId, at: now() });
163
+ return;
164
+ }
165
+ case "permission_resolved": {
166
+ const pending = pendingApprovals.get(event.requestId);
167
+ if (pending === undefined)
168
+ return;
169
+ pendingApprovals.delete(event.requestId);
170
+ approvals.set(pending.toolCallId, (approvals.get(pending.toolCallId) ?? 0) + (now() - pending.at));
171
+ return;
172
+ }
173
+ case "turn_end":
174
+ writeStep(event.message, false);
175
+ return;
176
+ case "agent_end":
177
+ if (dirty())
178
+ writeStep(undefined, true);
179
+ return;
180
+ case "auto_retry_start":
181
+ attempt = event.attempt + 1;
182
+ write({
183
+ kind: "retry_wait",
184
+ attempt,
185
+ delayMs: event.delayMs,
186
+ startedAt: now(),
187
+ ...(event.errorMessage !== "" ? { reason: clip(event.errorMessage) } : {}),
188
+ });
189
+ return;
190
+ case "model_fallback": {
191
+ const from = formatModelRef(event.from);
192
+ fallbackFrom = from;
193
+ attempt += 1;
194
+ const reason = clip(event.reason);
195
+ write({
196
+ kind: "fallback",
197
+ from,
198
+ to: formatModelRef(event.to),
199
+ ...(reason !== undefined && reason !== "" ? { reason } : {}),
200
+ });
201
+ return;
202
+ }
203
+ case "model_changed":
204
+ // 回退结束切回主模型(或用户换模型):之后的请求不再算回退
205
+ if (fallbackFrom !== undefined && formatModelRef(event.model) === fallbackFrom)
206
+ fallbackFrom = undefined;
207
+ return;
208
+ case "compaction_start":
209
+ compaction = { trigger: event.trigger, at: now() };
210
+ compactionEntryId = undefined;
211
+ return;
212
+ case "compaction_end": {
213
+ const started = compaction;
214
+ compaction = undefined;
215
+ write({
216
+ kind: "compaction",
217
+ trigger: event.trigger,
218
+ startedAt: started?.at ?? now(),
219
+ endedAt: now(),
220
+ ...(compactionEntryId !== undefined ? { compactionEntryId } : {}),
221
+ ...(event.aborted ? { aborted: true } : {}),
222
+ });
223
+ compactionEntryId = undefined;
224
+ return;
225
+ }
226
+ default:
227
+ return;
228
+ }
229
+ };
230
+ return {
231
+ id: "trace-writer",
232
+ wrapStream(stream) {
233
+ return (model, context, options) => {
234
+ const kind = options.purpose ?? "turn";
235
+ if (kind === "turn")
236
+ requestFallbackFrom = fallbackFrom;
237
+ const purpose = AUX_PURPOSE[kind];
238
+ if (purpose !== undefined)
239
+ auxStarted.set(purpose, now());
240
+ return stream(model, context, options);
241
+ };
242
+ },
243
+ onEvent,
244
+ dispose() {
245
+ unsubscribe?.();
246
+ unsubscribe = undefined;
247
+ },
248
+ };
249
+ }
250
+ /** 组装表用的工厂:主会话与子会话都装。 */
251
+ export function traceWriterFactory(deps = {}) {
252
+ return ({ core }) => createTraceWriter(core, deps);
253
+ }
@@ -45,6 +45,8 @@ export declare class AgentSessionImpl implements AgentSession, SessionCore {
45
45
  private turns;
46
46
  private readonly subagentPool;
47
47
  private disposed;
48
+ /** [W6-O] 最近一次订阅配额(`quota_update`)。 */
49
+ private lastQuota;
48
50
  private classifier;
49
51
  /** 已入队、尚未投递的消息(投递时发 queue_update)。 */
50
52
  private readonly queuedMessages;
@@ -47,6 +47,8 @@ export class AgentSessionImpl {
47
47
  turns = 0;
48
48
  subagentPool;
49
49
  disposed = false;
50
+ /** [W6-O] 最近一次订阅配额(`quota_update`)。 */
51
+ lastQuota;
50
52
  classifier;
51
53
  /** 已入队、尚未投递的消息(投递时发 queue_update)。 */
52
54
  queuedMessages = new WeakSet();
@@ -97,6 +99,15 @@ export class AgentSessionImpl {
97
99
  const idle = options.idleTimeoutMs;
98
100
  return {
99
101
  sessionId: this.manager.id,
102
+ // [W6-O] ChatGPT 订阅配额 → quota_update 事件(/session 显示最近一次)
103
+ onQuota: (update) => {
104
+ this.lastQuota = {
105
+ type: "quota_update",
106
+ provider: this.settings.model.provider,
107
+ ...update,
108
+ };
109
+ this.emit(this.lastQuota);
110
+ },
100
111
  ...(apiKey === undefined ? {} : { apiKey }),
101
112
  ...(idle === undefined ? {} : { idleTimeoutMs: idle }),
102
113
  };
@@ -416,6 +427,7 @@ export class AgentSessionImpl {
416
427
  contextTokens,
417
428
  contextWindow,
418
429
  cache: this.cache.stats({ tokens: contextTokens, window: contextWindow }),
430
+ quota: this.lastQuota,
419
431
  });
420
432
  return this.extensions.contributeStats(stats);
421
433
  }