@armadra/agent 0.5.1 → 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 (467) hide show
  1. package/CHANGELOG.md +177 -304
  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 +25928 -11144
  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.js +8 -6
  103. package/dist/cli/codemode-notice.js +2 -2
  104. package/dist/cli/compose-agents.js +2 -1
  105. package/dist/cli/compose-extensions.js +2 -0
  106. package/dist/cli/compose-memory.d.ts +53 -0
  107. package/dist/cli/compose-memory.js +127 -0
  108. package/dist/cli/compose-providers.d.ts +5 -0
  109. package/dist/cli/compose-providers.js +32 -2
  110. package/dist/cli/compose-session.d.ts +5 -0
  111. package/dist/cli/compose-session.js +27 -13
  112. package/dist/cli/compose-store.d.ts +2 -0
  113. package/dist/cli/compose-store.js +9 -5
  114. package/dist/cli/compose.d.ts +2 -0
  115. package/dist/cli/compose.js +13 -5
  116. package/dist/cli/default-model.d.ts +0 -2
  117. package/dist/cli/default-model.js +5 -8
  118. package/dist/cli/deps.d.ts +5 -1
  119. package/dist/cli/exit-codes.d.ts +1 -1
  120. package/dist/cli/exit-codes.js +7 -16
  121. package/dist/cli/from-prompt.js +3 -2
  122. package/dist/cli/help-text.d.ts +2 -1
  123. package/dist/cli/help-text.js +5 -99
  124. package/dist/cli/main.d.ts +5 -0
  125. package/dist/cli/main.js +21 -2
  126. package/dist/cli/proxy.js +14 -9
  127. package/dist/cli/runtime.d.ts +5 -0
  128. package/dist/cli/startup-screen.js +20 -27
  129. package/dist/cli/startup-steps.js +6 -8
  130. package/dist/cli/subcommands/auth.d.ts +6 -3
  131. package/dist/cli/subcommands/auth.js +52 -22
  132. package/dist/cli/subcommands/config-set.d.ts +21 -0
  133. package/dist/cli/subcommands/config-set.js +137 -0
  134. package/dist/cli/subcommands/config.d.ts +2 -1
  135. package/dist/cli/subcommands/config.js +51 -37
  136. package/dist/cli/subcommands/doctor.d.ts +2 -1
  137. package/dist/cli/subcommands/doctor.js +97 -58
  138. package/dist/cli/subcommands/init.d.ts +1 -1
  139. package/dist/cli/subcommands/init.js +8 -7
  140. package/dist/cli/subcommands/memory.d.ts +18 -0
  141. package/dist/cli/subcommands/memory.js +189 -0
  142. package/dist/cli/subcommands/model-meta.js +11 -9
  143. package/dist/cli/subcommands/models-cache-probe.js +23 -20
  144. package/dist/cli/subcommands/models-discover.d.ts +3 -0
  145. package/dist/cli/subcommands/models-discover.js +44 -21
  146. package/dist/cli/subcommands/models.d.ts +1 -1
  147. package/dist/cli/subcommands/models.js +29 -22
  148. package/dist/cli/subcommands/probe-runner.js +8 -7
  149. package/dist/cli/subcommands/providers-list.js +32 -21
  150. package/dist/cli/subcommands/providers-plan.js +24 -25
  151. package/dist/cli/subcommands/providers-probe.js +5 -6
  152. package/dist/cli/subcommands/providers.d.ts +1 -1
  153. package/dist/cli/subcommands/providers.js +45 -50
  154. package/dist/cli/subcommands/sessions-export.d.ts +1 -1
  155. package/dist/cli/subcommands/sessions-export.js +10 -9
  156. package/dist/cli/subcommands/sessions-search.d.ts +1 -1
  157. package/dist/cli/subcommands/sessions-search.js +11 -10
  158. package/dist/cli/subcommands/sessions-trace.d.ts +30 -0
  159. package/dist/cli/subcommands/sessions-trace.js +156 -0
  160. package/dist/cli/subcommands/sessions.d.ts +4 -3
  161. package/dist/cli/subcommands/sessions.js +40 -37
  162. package/dist/cli/subcommands/stats.d.ts +1 -1
  163. package/dist/cli/subcommands/stats.js +49 -30
  164. package/dist/cli/system-prompt-arg.js +3 -2
  165. package/dist/codemode/capability.js +3 -2
  166. package/dist/compaction/post-compact.d.ts +1 -0
  167. package/dist/compaction/post-compact.js +15 -1
  168. package/dist/compaction/prune-tier.d.ts +1 -1
  169. package/dist/compaction/prune-tier.js +3 -3
  170. package/dist/compaction/serialize.js +2 -1
  171. package/dist/config/auth-file.d.ts +12 -2
  172. package/dist/config/auth-file.js +32 -10
  173. package/dist/config/checker.js +12 -11
  174. package/dist/config/context-files.js +3 -2
  175. package/dist/config/edit.d.ts +106 -0
  176. package/dist/config/edit.js +350 -0
  177. package/dist/config/init.d.ts +4 -3
  178. package/dist/config/init.js +10 -18
  179. package/dist/config/json-schema.d.ts +2 -1
  180. package/dist/config/json-schema.js +101 -68
  181. package/dist/config/key-docs.d.ts +18 -7
  182. package/dist/config/key-docs.js +43 -128
  183. package/dist/config/load.js +7 -6
  184. package/dist/config/merge.d.ts +4 -1
  185. package/dist/config/merge.js +42 -22
  186. package/dist/config/paths.js +6 -5
  187. package/dist/config/profile.d.ts +5 -1
  188. package/dist/config/profile.js +7 -2
  189. package/dist/config/schema-w5.js +3 -2
  190. package/dist/config/schema-w6.d.ts +19 -0
  191. package/dist/config/schema-w6.js +115 -0
  192. package/dist/config/schema.js +34 -20
  193. package/dist/config/settings-registry.d.ts +78 -0
  194. package/dist/config/settings-registry.js +184 -0
  195. package/dist/config/types-w6.d.ts +109 -0
  196. package/dist/config/types-w6.js +19 -0
  197. package/dist/config/types.d.ts +11 -8
  198. package/dist/config/types.js +1 -0
  199. package/dist/drivers/acp/client.js +1 -1
  200. package/dist/drivers/acp/driver.js +13 -8
  201. package/dist/drivers/agents.js +4 -3
  202. package/dist/drivers/base.js +3 -2
  203. package/dist/drivers/host-runners.js +2 -1
  204. package/dist/drivers/native/claude-stream.js +12 -11
  205. package/dist/drivers/native/codex-app-server.js +17 -12
  206. package/dist/drivers/native/oneshot.js +8 -7
  207. package/dist/drivers/pool.js +1 -1
  208. package/dist/drivers/runner.d.ts +3 -1
  209. package/dist/drivers/runner.js +68 -20
  210. package/dist/drivers/turn.js +1 -1
  211. package/dist/hooks/config.js +3 -2
  212. package/dist/hooks/protocol.js +18 -12
  213. package/dist/host/api-impl.js +11 -10
  214. package/dist/host/loader.js +9 -8
  215. package/dist/host/types.d.ts +3 -0
  216. package/dist/i18n/catalog.d.ts +2169 -0
  217. package/dist/i18n/catalog.js +72 -0
  218. package/dist/i18n/format.d.ts +21 -0
  219. package/dist/i18n/format.js +58 -0
  220. package/dist/i18n/index.d.ts +58 -0
  221. package/dist/i18n/index.js +72 -0
  222. package/dist/i18n/messages/agents.d.ts +84 -0
  223. package/dist/i18n/messages/agents.js +85 -0
  224. package/dist/i18n/messages/approval.d.ts +99 -0
  225. package/dist/i18n/messages/approval.js +100 -0
  226. package/dist/i18n/messages/auth.d.ts +187 -0
  227. package/dist/i18n/messages/auth.js +189 -0
  228. package/dist/i18n/messages/cli-args.d.ts +46 -0
  229. package/dist/i18n/messages/cli-args.js +46 -0
  230. package/dist/i18n/messages/cli-help.d.ts +12 -0
  231. package/dist/i18n/messages/cli-help.js +244 -0
  232. package/dist/i18n/messages/cli.d.ts +336 -0
  233. package/dist/i18n/messages/cli.js +311 -0
  234. package/dist/i18n/messages/config-keys.d.ts +289 -0
  235. package/dist/i18n/messages/config-keys.js +292 -0
  236. package/dist/i18n/messages/config.d.ts +502 -0
  237. package/dist/i18n/messages/config.js +239 -0
  238. package/dist/i18n/messages/drivers.d.ts +123 -0
  239. package/dist/i18n/messages/drivers.js +124 -0
  240. package/dist/i18n/messages/errors.d.ts +83 -0
  241. package/dist/i18n/messages/errors.js +171 -0
  242. package/dist/i18n/messages/interactive-line.d.ts +61 -0
  243. package/dist/i18n/messages/interactive-line.js +69 -0
  244. package/dist/i18n/messages/interactive-startup.d.ts +103 -0
  245. package/dist/i18n/messages/interactive-startup.js +104 -0
  246. package/dist/i18n/messages/interactive-view.d.ts +140 -0
  247. package/dist/i18n/messages/interactive-view.js +141 -0
  248. package/dist/i18n/messages/interactive.d.ts +493 -0
  249. package/dist/i18n/messages/interactive.js +248 -0
  250. package/dist/i18n/messages/memory.d.ts +123 -0
  251. package/dist/i18n/messages/memory.js +128 -0
  252. package/dist/i18n/messages/panels.d.ts +190 -0
  253. package/dist/i18n/messages/panels.js +189 -0
  254. package/dist/i18n/messages/permissions.d.ts +126 -0
  255. package/dist/i18n/messages/permissions.js +151 -0
  256. package/dist/i18n/messages/plan.d.ts +123 -0
  257. package/dist/i18n/messages/plan.js +124 -0
  258. package/dist/i18n/messages/print.d.ts +86 -0
  259. package/dist/i18n/messages/print.js +91 -0
  260. package/dist/i18n/messages/report.d.ts +391 -0
  261. package/dist/i18n/messages/report.js +490 -0
  262. package/dist/i18n/messages/rewind.d.ts +198 -0
  263. package/dist/i18n/messages/rewind.js +217 -0
  264. package/dist/i18n/messages/session.d.ts +230 -0
  265. package/dist/i18n/messages/session.js +258 -0
  266. package/dist/i18n/messages/settings.d.ts +348 -0
  267. package/dist/i18n/messages/settings.js +336 -0
  268. package/dist/i18n/messages/subcommands-config.d.ts +111 -0
  269. package/dist/i18n/messages/subcommands-config.js +127 -0
  270. package/dist/i18n/messages/subcommands.d.ts +548 -0
  271. package/dist/i18n/messages/subcommands.js +474 -0
  272. package/dist/i18n/messages/trace.d.ts +243 -0
  273. package/dist/i18n/messages/trace.js +238 -0
  274. package/dist/i18n/types.d.ts +15 -0
  275. package/dist/i18n/types.js +7 -0
  276. package/dist/index.d.ts +6 -0
  277. package/dist/index.js +2 -0
  278. package/dist/memory/edit.d.ts +24 -0
  279. package/dist/memory/edit.js +63 -0
  280. package/dist/memory/frontmatter.d.ts +37 -0
  281. package/dist/memory/frontmatter.js +79 -0
  282. package/dist/memory/index.d.ts +28 -0
  283. package/dist/memory/index.js +126 -0
  284. package/dist/memory/lock.d.ts +17 -0
  285. package/dist/memory/lock.js +62 -0
  286. package/dist/memory/paths.d.ts +57 -0
  287. package/dist/memory/paths.js +175 -0
  288. package/dist/memory/report.d.ts +36 -0
  289. package/dist/memory/report.js +86 -0
  290. package/dist/memory/runtime.d.ts +42 -0
  291. package/dist/memory/runtime.js +36 -0
  292. package/dist/memory/secrets.d.ts +8 -0
  293. package/dist/memory/secrets.js +27 -0
  294. package/dist/memory/section.d.ts +28 -0
  295. package/dist/memory/section.js +59 -0
  296. package/dist/memory/store.d.ts +70 -0
  297. package/dist/memory/store.js +284 -0
  298. package/dist/memory/tool.d.ts +31 -0
  299. package/dist/memory/tool.js +94 -0
  300. package/dist/modes/acp/acp-events.js +2 -1
  301. package/dist/modes/acp/acp-server.js +13 -12
  302. package/dist/modes/commands-core.d.ts +11 -0
  303. package/dist/modes/commands-core.js +93 -62
  304. package/dist/modes/image-input.js +20 -6
  305. package/dist/modes/interactive/agent-bar.d.ts +95 -0
  306. package/dist/modes/interactive/agent-bar.js +248 -0
  307. package/dist/modes/interactive/agent-panels.js +27 -26
  308. package/dist/modes/interactive/agent-transcript.d.ts +47 -0
  309. package/dist/modes/interactive/agent-transcript.js +191 -0
  310. package/dist/modes/interactive/agent-ui.d.ts +36 -1
  311. package/dist/modes/interactive/agent-ui.js +180 -14
  312. package/dist/modes/interactive/agent-view.d.ts +72 -0
  313. package/dist/modes/interactive/agent-view.js +281 -0
  314. package/dist/modes/interactive/approval-dialog.js +46 -34
  315. package/dist/modes/interactive/clipboard-paste.d.ts +2 -2
  316. package/dist/modes/interactive/clipboard-paste.js +9 -4
  317. package/dist/modes/interactive/commands.d.ts +19 -1
  318. package/dist/modes/interactive/commands.js +84 -40
  319. package/dist/modes/interactive/completion.js +2 -1
  320. package/dist/modes/interactive/config-panel.d.ts +70 -0
  321. package/dist/modes/interactive/config-panel.js +319 -0
  322. package/dist/modes/interactive/config-ui.d.ts +96 -0
  323. package/dist/modes/interactive/config-ui.js +397 -0
  324. package/dist/modes/interactive/confirm-dialog.js +6 -7
  325. package/dist/modes/interactive/event-notices.js +11 -9
  326. package/dist/modes/interactive/interactive-mode.d.ts +1 -1
  327. package/dist/modes/interactive/interactive-mode.js +19 -22
  328. package/dist/modes/interactive/key-dispatch.d.ts +12 -0
  329. package/dist/modes/interactive/key-dispatch.js +24 -9
  330. package/dist/modes/interactive/line/line-editor.js +2 -1
  331. package/dist/modes/interactive/line/line-mode.js +18 -7
  332. package/dist/modes/interactive/line/line-render.js +25 -24
  333. package/dist/modes/interactive/memory-panel.d.ts +64 -0
  334. package/dist/modes/interactive/memory-panel.js +221 -0
  335. package/dist/modes/interactive/message-view.d.ts +4 -2
  336. package/dist/modes/interactive/message-view.js +42 -33
  337. package/dist/modes/interactive/panels.js +39 -31
  338. package/dist/modes/interactive/pickers.d.ts +2 -1
  339. package/dist/modes/interactive/pickers.js +10 -6
  340. package/dist/modes/interactive/plan-command.d.ts +1 -1
  341. package/dist/modes/interactive/plan-command.js +24 -27
  342. package/dist/modes/interactive/plan-dialog.js +18 -17
  343. package/dist/modes/interactive/plan-flow.js +6 -5
  344. package/dist/modes/interactive/rewind-command.d.ts +1 -1
  345. package/dist/modes/interactive/rewind-command.js +18 -16
  346. package/dist/modes/interactive/rewind-flow.d.ts +0 -1
  347. package/dist/modes/interactive/rewind-flow.js +13 -14
  348. package/dist/modes/interactive/rewind-list.js +7 -6
  349. package/dist/modes/interactive/rewind-panel.js +40 -40
  350. package/dist/modes/interactive/rewind-text.d.ts +5 -3
  351. package/dist/modes/interactive/rewind-text.js +48 -38
  352. package/dist/modes/interactive/run-indicator.js +15 -12
  353. package/dist/modes/interactive/session-events.js +3 -2
  354. package/dist/modes/interactive/startup-header.js +22 -23
  355. package/dist/modes/interactive/startup-ui.js +38 -30
  356. package/dist/modes/interactive/status-area.d.ts +2 -0
  357. package/dist/modes/interactive/status-area.js +8 -2
  358. package/dist/modes/interactive/status-bar.js +4 -3
  359. package/dist/modes/interactive/subagent-view.js +9 -7
  360. package/dist/modes/interactive/tasks-report.d.ts +6 -0
  361. package/dist/modes/interactive/tasks-report.js +28 -31
  362. package/dist/modes/interactive/terminal-setup.d.ts +9 -0
  363. package/dist/modes/interactive/terminal-setup.js +23 -0
  364. package/dist/modes/interactive/tool-summary.js +19 -17
  365. package/dist/modes/interactive/tool-view.js +7 -4
  366. package/dist/modes/interactive/trace-view.d.ts +89 -0
  367. package/dist/modes/interactive/trace-view.js +332 -0
  368. package/dist/modes/print/print-mode.js +14 -15
  369. package/dist/modes/rpc/commands.js +7 -3
  370. package/dist/modes/rpc/rpc-mode.js +9 -3
  371. package/dist/modes/session-report.d.ts +2 -0
  372. package/dist/modes/session-report.js +101 -105
  373. package/dist/modes/startup-ui-text.js +11 -6
  374. package/dist/permissions/bypass.d.ts +8 -10
  375. package/dist/permissions/bypass.js +19 -10
  376. package/dist/permissions/memory-class.d.ts +23 -0
  377. package/dist/permissions/memory-class.js +54 -0
  378. package/dist/permissions/modes.d.ts +3 -3
  379. package/dist/permissions/modes.js +21 -16
  380. package/dist/permissions/pipeline.d.ts +1 -1
  381. package/dist/permissions/pipeline.js +9 -2
  382. package/dist/permissions/preview.js +49 -42
  383. package/dist/permissions/rules.js +5 -2
  384. package/dist/permissions/types.d.ts +4 -0
  385. package/dist/plan/store.js +2 -1
  386. package/dist/rpc.d.ts +39 -1
  387. package/dist/rpc.js +3 -0
  388. package/dist/sandbox/bash.js +11 -8
  389. package/dist/sandbox/detect.js +14 -11
  390. package/dist/sdk.d.ts +17 -1
  391. package/dist/sdk.js +29 -7
  392. package/dist/session/export.js +31 -30
  393. package/dist/session/manager.d.ts +1 -1
  394. package/dist/session/manager.js +5 -3
  395. package/dist/session/reuse.js +5 -4
  396. package/dist/session/scan.js +3 -2
  397. package/dist/session/stats-aggregate.d.ts +3 -1
  398. package/dist/session/stats-aggregate.js +5 -1
  399. package/dist/session/stats-index.js +2 -1
  400. package/dist/session/stats-scan.d.ts +4 -1
  401. package/dist/session/stats-scan.js +6 -2
  402. package/dist/session/store.d.ts +11 -0
  403. package/dist/session/store.js +48 -1
  404. package/dist/session/types.d.ts +2 -0
  405. package/dist/skills/builtin.js +2 -1
  406. package/dist/tools/image-file.d.ts +26 -1
  407. package/dist/tools/image-file.js +55 -13
  408. package/dist/tools/presets.d.ts +14 -1
  409. package/dist/tools/presets.js +3 -3
  410. package/dist/tools/registry.js +1 -1
  411. package/dist/tools/truncate.d.ts +1 -1
  412. package/dist/tools/truncate.js +2 -2
  413. package/dist/tools/types.d.ts +17 -1
  414. package/dist/trace/build-index.d.ts +91 -0
  415. package/dist/trace/build-index.js +127 -0
  416. package/dist/trace/build-nodes.d.ts +24 -0
  417. package/dist/trace/build-nodes.js +279 -0
  418. package/dist/trace/build-util.d.ts +43 -0
  419. package/dist/trace/build-util.js +120 -0
  420. package/dist/trace/build.d.ts +82 -0
  421. package/dist/trace/build.js +382 -0
  422. package/dist/trace/detail.d.ts +35 -0
  423. package/dist/trace/detail.js +205 -0
  424. package/dist/trace/flatten.d.ts +69 -0
  425. package/dist/trace/flatten.js +173 -0
  426. package/dist/trace/format.d.ts +47 -0
  427. package/dist/trace/format.js +329 -0
  428. package/dist/trace/html-template.d.ts +19 -0
  429. package/dist/trace/html-template.js +150 -0
  430. package/dist/trace/html.d.ts +104 -0
  431. package/dist/trace/html.js +292 -0
  432. package/dist/trace/preview.d.ts +29 -0
  433. package/dist/trace/preview.js +59 -0
  434. package/dist/trace/query-session.d.ts +14 -0
  435. package/dist/trace/query-session.js +38 -0
  436. package/dist/trace/query.d.ts +55 -0
  437. package/dist/trace/query.js +188 -0
  438. package/dist/trace/session.d.ts +40 -0
  439. package/dist/trace/session.js +168 -0
  440. package/dist/trace/types.d.ts +243 -0
  441. package/dist/trace/types.js +13 -0
  442. package/dist/tui/components/editor-paste.d.ts +2 -0
  443. package/dist/tui/components/editor-paste.js +6 -3
  444. package/dist/tui/components/editor.js +2 -2
  445. package/dist/tui/components/loader.d.ts +3 -0
  446. package/dist/tui/components/loader.js +14 -0
  447. package/dist/tui/components/settings-list.d.ts +61 -0
  448. package/dist/tui/components/settings-list.js +135 -0
  449. package/dist/tui/keybindings.d.ts +5 -0
  450. package/dist/tui/keybindings.js +17 -5
  451. package/dist/tui.d.ts +1 -0
  452. package/dist/tui.js +2 -0
  453. package/docs/en/host-api.md +167 -0
  454. package/docs/en/permissions.md +214 -0
  455. package/docs/en/providers.md +625 -0
  456. package/docs/en/rpc.md +361 -0
  457. package/docs/en/sessions.md +219 -0
  458. package/docs/en/tui.md +527 -0
  459. package/docs/host-api.md +18 -17
  460. package/docs/memory.md +172 -0
  461. package/docs/permissions.md +2 -2
  462. package/docs/providers.md +67 -1
  463. package/docs/rpc.md +31 -3
  464. package/docs/session-format.md +8 -2
  465. package/docs/sessions.md +29 -1
  466. package/docs/tui.md +132 -3
  467. package/package.json +8 -3
package/dist/sdk.js CHANGED
@@ -13,12 +13,14 @@
13
13
  * - [W5-F] 计划(docs/plan.md):`CreateSessionOptions.plan`(plan.* 配置 + `onProposed` 审批回调);
14
14
  * 返回的会话带 `plan.current() / respond() / todos()`。没有 `onProposed` 时按 `plan.unattended`
15
15
  * (缺省 stop:计划落盘后停下,不替人批准)。
16
+ * - [W6-C0] `language`(两个入口都有):界面语言,跟随宿主界面(docs/i18n.md);进程级,`AMA_LANG` 仍优先。
16
17
  */
17
18
  import { resolve } from "node:path";
18
19
  import { ProviderRegistry } from "./ai/providers/registry.js";
19
20
  import { planController, } from "./agent/session-plan.js";
20
21
  import { parseArgs } from "./cli/args.js";
21
22
  import { bootstrap } from "./cli/bootstrap.js";
23
+ import { resolveMemory } from "./cli/compose-memory.js";
22
24
  import { withExtraProviders } from "./cli/compose-providers.js";
23
25
  import { composeSession, emptyComposeState } from "./cli/compose-session.js";
24
26
  import { buildRules, createRuntimeDeps, createTools } from "./cli/compose.js";
@@ -26,8 +28,10 @@ import { pickDefaultModel } from "./cli/default-model.js";
26
28
  import { findContextFiles } from "./config/context-files.js";
27
29
  import { DEFAULT_CONFIG, mergeConfig } from "./config/merge.js";
28
30
  import { resolveConfigDir, resolveDataDir } from "./config/paths.js";
29
- import { canonicalPreset } from "./config/types.js";
31
+ import { canonicalPreset, } from "./config/types.js";
32
+ import { sdkSessionTrace } from "./trace/query-session.js";
30
33
  import { AmaError } from "./errors.js";
34
+ import { msg, resolveLocale, setLocale } from "./i18n/index.js";
31
35
  import { hooksFromConfig } from "./hooks/config.js";
32
36
  import { HookDispatcher } from "./hooks/dispatcher.js";
33
37
  import { AgentEventBus } from "./host/api-impl.js";
@@ -38,7 +42,7 @@ import { PresetToolRegistry } from "./tools/presets.js";
38
42
  export async function createRuntime(options = {}) {
39
43
  const parsed = parseArgs(options.argv ?? []);
40
44
  if (parsed.kind !== "run")
41
- throw new AmaError("invalid_arguments", "createRuntime 不接受子命令");
45
+ throw new AmaError("invalid_arguments", msg().errors.sdk.noSubcommand);
42
46
  const args = parsed.args;
43
47
  if (options.model !== undefined)
44
48
  args.model = options.model;
@@ -56,7 +60,13 @@ export async function createRuntime(options = {}) {
56
60
  args.profile = options.profile;
57
61
  if (options.unattended === true)
58
62
  args.print = true;
63
+ if (options.language !== undefined)
64
+ args.lang = options.language;
65
+ if (options.memory !== undefined)
66
+ args.memory = options.memory;
59
67
  const env = options.env ?? process.env;
68
+ if (args.lang !== undefined)
69
+ setLocale(resolveLocale(env, undefined, args.lang));
60
70
  const io = {
61
71
  stdout: () => undefined,
62
72
  stderr: options.stderr ?? ((text) => void process.stderr.write(text)),
@@ -85,6 +95,8 @@ function keyOptions(auth) {
85
95
  export async function createAgentSession(options = {}) {
86
96
  const cwd = resolve(options.cwd ?? process.cwd());
87
97
  const warn = options.onWarning ?? (() => undefined);
98
+ if (options.language !== undefined)
99
+ setLocale(resolveLocale(process.env, undefined, options.language));
88
100
  let config = mergeConfig(DEFAULT_CONFIG, options.config);
89
101
  const { onProposed, ...planConfig } = options.plan ?? {};
90
102
  if (options.plan !== undefined)
@@ -105,18 +117,28 @@ export async function createAgentSession(options = {}) {
105
117
  if (ref !== undefined) {
106
118
  const found = providers.findModel(ref);
107
119
  if (!found.ok)
108
- throw new AmaError("model_not_found", `模型不存在:${ref}`, { detail: found.candidates });
120
+ throw new AmaError("model_not_found", msg().errors.sdk.modelNotFound(ref), {
121
+ detail: found.candidates,
122
+ });
109
123
  choice = found;
110
124
  }
111
125
  else {
112
126
  choice = await pickDefaultModel(providers);
113
127
  if (choice === undefined)
114
- throw new AmaError("no_api_key", "没有可用模型:传 model,或配置任一供应商的 key");
128
+ throw new AmaError("no_api_key", msg().errors.sdk.noModel);
115
129
  }
116
130
  const state = emptyComposeState();
117
131
  let tools;
118
132
  if (options.tools === undefined || options.tools === "default") {
119
- tools = createTools({ config, cwd, mode: "line" }, { extraTools: options.extraTools ?? [] }, state);
133
+ // [W6-M] SDK 同嵌入宿主:只有 `options.memory = { enabled, dir }` 开启(workspace 作用域)
134
+ const memory = resolveMemory({
135
+ config,
136
+ cwd,
137
+ dataDir: resolveDataDir(),
138
+ trusted: true,
139
+ embedded: { memory: options.memory },
140
+ });
141
+ tools = createTools({ config, cwd, mode: "line", memory }, { extraTools: options.extraTools ?? [] }, state);
120
142
  }
121
143
  else {
122
144
  tools = new PresetToolRegistry();
@@ -214,12 +236,12 @@ function withPlanApi(session, onProposed) {
214
236
  const controller = planController(session);
215
237
  controller?.setAttendance(onProposed === undefined ? "unattended" : "callback", onProposed);
216
238
  const missing = () => {
217
- throw new AmaError("not_implemented", "该会话没有装配 plan 扩展");
239
+ throw new AmaError("not_implemented", msg().errors.sdk.noPlan);
218
240
  };
219
241
  const plan = {
220
242
  current: () => controller?.current() ?? null,
221
243
  respond: (response) => (controller ?? missing()).respond(response),
222
244
  todos: () => controller?.todos() ?? [],
223
245
  };
224
- return Object.assign(session, { plan });
246
+ return Object.assign(session, { plan, trace: (o) => sdkSessionTrace(session, o) }); // [W6-T2]
225
247
  }
@@ -10,6 +10,7 @@
10
10
  import { contentImages, contentText, numberUserMessages } from "./reuse.js";
11
11
  import { redactSecrets, redactValue } from "./redact.js";
12
12
  import { indexEntries, pathToRoot } from "./tree.js";
13
+ import { msg } from "../i18n/index.js";
13
14
  export function selectEntries(input, branch) {
14
15
  return branch === "all"
15
16
  ? [...input.entries]
@@ -52,7 +53,9 @@ function sessionName(entries) {
52
53
  return name;
53
54
  }
54
55
  function truncate(text, max) {
55
- return text.length > max ? `${text.slice(0, max)}\n…(截断,原长 ${text.length} 字符)` : text;
56
+ return text.length > max
57
+ ? `${text.slice(0, max)}\n${msg().session.export.truncated(text.length)}`
58
+ : text;
56
59
  }
57
60
  function fence(text, lang = "") {
58
61
  let ticks = "```";
@@ -65,66 +68,64 @@ function time(iso) {
65
68
  }
66
69
  function imagesNote(content) {
67
70
  return contentImages(content)
68
- .map((image) => `[图片 ${image.mimeType}]`)
71
+ .map((image) => msg().session.export.image(image.mimeType))
69
72
  .join(" ");
70
73
  }
71
74
  export function renderMarkdown(input, branch) {
72
75
  const entries = selectEntries(input, branch);
73
76
  const numbers = new Map(numberUserMessages(input.entries).map((u) => [u.entryId, u.n]));
74
77
  const name = sessionName(input.entries);
78
+ const m = msg().session.export;
75
79
  const out = [
76
- `# ${name ?? `会话 ${input.header.id.slice(0, 8)}`}`,
80
+ `# ${name ?? m.title(input.header.id.slice(0, 8))}`,
77
81
  "",
78
- `- id:${input.header.id}`,
79
- `- 目录:${input.header.cwd}`,
80
- `- 创建:${time(input.header.timestamp)}`,
81
- `- 范围:${branch === "all" ? "全部条目" : "当前分支"}(${entries.length} 条条目)`,
82
- ...(input.header.parentSession !== undefined
83
- ? [`- 来源会话:${input.header.parentSession}`]
84
- : []),
82
+ m.id(input.header.id),
83
+ m.cwd(input.header.cwd),
84
+ m.created(time(input.header.timestamp)),
85
+ m.scope(branch === "all", entries.length),
86
+ ...(input.header.parentSession !== undefined ? [m.parent(input.header.parentSession)] : []),
85
87
  "",
86
88
  ];
87
89
  for (const entry of entries) {
88
90
  switch (entry.type) {
89
91
  case "message": {
90
- const m = entry.message;
91
- if (m.role === "user") {
92
+ const message = entry.message;
93
+ if (message.role === "user") {
92
94
  const n = numbers.get(entry.id);
93
- const origin = m.origin;
94
- out.push(`## 用户${n !== undefined ? ` #${n}` : ""}${origin !== undefined ? `(${origin})` : ""} · ${time(entry.timestamp)}`, "");
95
- const text = contentText(m.content);
95
+ const origin = message.origin;
96
+ out.push(m.user(n, origin, time(entry.timestamp)), "");
97
+ const text = contentText(message.content);
96
98
  if (text !== "")
97
99
  out.push(text, "");
98
- const images = imagesNote(m.content);
100
+ const images = imagesNote(message.content);
99
101
  if (images !== "")
100
102
  out.push(images, "");
101
103
  }
102
- else if (m.role === "assistant") {
103
- out.push(`## 助手 · ${m.provider}/${m.model} · ${time(entry.timestamp)}`, "");
104
- for (const block of m.content) {
104
+ else if (message.role === "assistant") {
105
+ out.push(m.assistant(`${message.provider}/${message.model}`, time(entry.timestamp)), "");
106
+ for (const block of message.content) {
105
107
  if (block.type === "text" && block.text.trim() !== "")
106
108
  out.push(block.text, "");
107
109
  if (block.type === "toolCall") {
108
- out.push(`**工具调用** \`${block.name}\``, "", fence(truncate(JSON.stringify(block.arguments, null, 2), 500), "json"), "");
110
+ out.push(m.toolCall(block.name), "", fence(truncate(JSON.stringify(block.arguments, null, 2), 500), "json"), "");
109
111
  }
110
112
  }
111
- if (m.stopReason === "error" || m.stopReason === "aborted") {
112
- out.push(`> 停止:${m.stopReason}${m.errorMessage !== undefined ? ` · ${m.errorMessage}` : ""}`, "");
113
- }
113
+ if (message.stopReason === "error" || message.stopReason === "aborted")
114
+ out.push(m.stopped(message.stopReason, message.errorMessage), "");
114
115
  }
115
- else if (m.role === "toolResult") {
116
- out.push(`**结果** \`${m.toolName}\`${m.isError ? "(出错)" : ""}`, "", fence(truncate(contentText(m.content), 2000)), "");
117
- const images = imagesNote(m.content);
116
+ else if (message.role === "toolResult") {
117
+ out.push(m.toolResult(message.toolName, message.isError), "", fence(truncate(contentText(message.content), 2000)), "");
118
+ const images = imagesNote(message.content);
118
119
  if (images !== "")
119
120
  out.push(images, "");
120
121
  }
121
122
  break;
122
123
  }
123
124
  case "compaction":
124
- out.push(`## 压缩摘要 · ${time(entry.timestamp)}`, "", entry.summary, "");
125
+ out.push(m.compaction(time(entry.timestamp)), "", entry.summary, "");
125
126
  break;
126
127
  case "branch_summary":
127
- out.push(`## 分支摘要 · ${time(entry.timestamp)}`, "", entry.summary, "");
128
+ out.push(m.branchSummary(time(entry.timestamp)), "", entry.summary, "");
128
129
  break;
129
130
  case "custom_message":
130
131
  if (entry.display) {
@@ -133,14 +134,14 @@ export function renderMarkdown(input, branch) {
133
134
  }
134
135
  break;
135
136
  case "model_change":
136
- out.push(`_切换模型:${entry.provider}/${entry.modelId}${entry.channel !== undefined ? `@${entry.channel}` : ""}_`, "");
137
+ out.push(m.modelChange(`${entry.provider}/${entry.modelId}${entry.channel !== undefined ? `@${entry.channel}` : ""}`), "");
137
138
  break;
138
139
  default:
139
140
  break;
140
141
  }
141
142
  }
142
143
  const usage = usageTotals(entries);
143
- out.push("## 用量", "", "| 请求 | 输入 | 输出 | 缓存读 | 缓存写 | 费用 |", "| ---: | ---: | ---: | ---: | ---: | ---: |", `| ${usage.requests} | ${usage.input} | ${usage.output} | ${usage.cacheRead} | ${usage.cacheWrite} | ${usage.cost !== undefined ? `$${usage.cost.toFixed(4)}` : "—"} |`, "");
144
+ out.push(m.usage, "", m.usageHeader, "| ---: | ---: | ---: | ---: | ---: | ---: |", `| ${usage.requests} | ${usage.input} | ${usage.output} | ${usage.cacheRead} | ${usage.cacheWrite} | ${usage.cost !== undefined ? `$${usage.cost.toFixed(4)}` : "—"} |`, "");
144
145
  return redactSecrets(out.join("\n"));
145
146
  }
146
147
  export function renderJson(input, branch) {
@@ -39,7 +39,7 @@ export declare class SessionManager implements SessionManagerApi {
39
39
  static open(file: string, options?: {
40
40
  now?: () => Date;
41
41
  }): SessionManager;
42
- /** `--continue`:本目录最近一条;没有则新建(延迟落盘)。 */
42
+ /** `--continue`:本目录最近一条(跳过子 Agent 会话,只读文件头两行);没有则新建(延迟落盘)。 */
43
43
  static continueRecent(dir: string, cwd: string): SessionManager;
44
44
  /** 只读列出目录下的会话(最新在前);损坏的文件跳过。 */
45
45
  static list(dir: string): SessionListItem[];
@@ -17,7 +17,7 @@ import { dirname, join } from "node:path";
17
17
  import { AmaError } from "../errors.js";
18
18
  import { AMA_VERSION } from "../version.js";
19
19
  import { migrateSessionLines } from "./migrate.js";
20
- import { acquireLock, appendLines, listSessionFiles, readSessionLines, sessionDirForCwd, sessionFileName, writeNewSessionFile, } from "./store.js";
20
+ import { acquireLock, appendLines, isSubagentSession, isSubagentSessionFile, listSessionFiles, readSessionLines, sessionDirForCwd, sessionFileName, writeNewSessionFile, } from "./store.js";
21
21
  import { buildTree, indexEntries, pathToRoot } from "./tree.js";
22
22
  import { SESSION_FORMAT_VERSION } from "./types.js";
23
23
  function newEntryId(taken) {
@@ -86,9 +86,9 @@ export class SessionManager {
86
86
  throw error;
87
87
  }
88
88
  }
89
- /** `--continue`:本目录最近一条;没有则新建(延迟落盘)。 */
89
+ /** `--continue`:本目录最近一条(跳过子 Agent 会话,只读文件头两行);没有则新建(延迟落盘)。 */
90
90
  static continueRecent(dir, cwd) {
91
- const [latest] = listSessionFiles(dir);
91
+ const latest = listSessionFiles(dir).find((file) => !isSubagentSessionFile(file));
92
92
  return latest === undefined ? this.create(dir, cwd) : this.open(latest);
93
93
  }
94
94
  /** 只读列出目录下的会话(最新在前);损坏的文件跳过。 */
@@ -124,6 +124,8 @@ export class SessionManager {
124
124
  };
125
125
  if (name !== undefined)
126
126
  item.name = name;
127
+ if (isSubagentSession(header, entries[0]))
128
+ item.subagent = true;
127
129
  if (firstPrompt !== undefined)
128
130
  item.firstPrompt = firstPrompt.slice(0, 200);
129
131
  items.push(item);
@@ -8,6 +8,7 @@
8
8
  */
9
9
  import { AmaError } from "../errors.js";
10
10
  import { findSessionFileReadOnly, readSessionReadOnly } from "./scan.js";
11
+ import { msg } from "../i18n/index.js";
11
12
  /** 内容 → 纯文本(文本块用空行连接;不含图片)。 */
12
13
  export function contentText(content) {
13
14
  if (typeof content === "string")
@@ -54,14 +55,14 @@ export function parseFromSpec(spec) {
54
55
  const at = spec.lastIndexOf("#");
55
56
  if (at < 0) {
56
57
  if (spec.trim() === "")
57
- throw new AmaError("invalid_arguments", "--from 需要会话 id", { exitCode: 2 });
58
+ throw new AmaError("invalid_arguments", msg().session.lookup.fromNeedsId, { exitCode: 2 });
58
59
  return { id: spec };
59
60
  }
60
61
  const id = spec.slice(0, at);
61
62
  const raw = spec.slice(at + 1);
62
63
  const n = Number(raw);
63
64
  if (id === "" || !/^\d+$/.test(raw) || n < 1) {
64
- throw new AmaError("invalid_arguments", `--from 应为 <会话 id> 或 <会话 id>#<编号>(收到 ${spec})`, {
65
+ throw new AmaError("invalid_arguments", msg().session.lookup.fromInvalid(spec), {
65
66
  exitCode: 2,
66
67
  });
67
68
  }
@@ -74,13 +75,13 @@ export function resolveFromMessage(root, spec, cwd) {
74
75
  const session = readSessionReadOnly(file);
75
76
  const messages = numberUserMessages(session.entries);
76
77
  if (messages.length === 0) {
77
- throw new AmaError("invalid_arguments", `会话 ${session.header.id} 没有用户消息`, {
78
+ throw new AmaError("invalid_arguments", msg().session.lookup.noUserMessages(session.header.id), {
78
79
  exitCode: 2,
79
80
  });
80
81
  }
81
82
  const picked = n === undefined ? messages.at(-1) : messages[n - 1];
82
83
  if (picked === undefined) {
83
- throw new AmaError("invalid_arguments", `会话 ${session.header.id} 只有 ${messages.length} 条用户消息(收到 #${n})`, { exitCode: 2 });
84
+ throw new AmaError("invalid_arguments", msg().session.lookup.tooFewMessages(session.header.id, messages.length, n), { exitCode: 2 });
84
85
  }
85
86
  return { ...picked, sessionId: session.header.id, file };
86
87
  }
@@ -13,6 +13,7 @@ import { basename, join } from "node:path";
13
13
  import { AmaError } from "../errors.js";
14
14
  import { migrateSessionLines } from "./migrate.js";
15
15
  import { SESSION_FILE_SUFFIX, TRASH_DIR_NAME, listSessionFiles, sessionDirForCwd, sessionIdFromFileName, } from "./store.js";
16
+ import { msg } from "../i18n/index.js";
16
17
  /** 根目录下全部 cwd 子目录(不含 trash)。 */
17
18
  export function sessionSubdirs(root) {
18
19
  if (!existsSync(root))
@@ -56,13 +57,13 @@ export function findSessionFileReadOnly(root, id, cwd) {
56
57
  }
57
58
  if (prefix.length > 1) {
58
59
  const ids = prefix.map((f) => sessionIdFromFileName(f) ?? f).slice(0, 10);
59
- throw new AmaError("invalid_arguments", `会话 id 前缀 ${id} 不唯一,候选:${ids.join(", ")}`, {
60
+ throw new AmaError("invalid_arguments", msg().session.lookup.ambiguousPrefix(id, ids.join(", ")), {
60
61
  exitCode: 5,
61
62
  });
62
63
  }
63
64
  const [file] = prefix;
64
65
  if (file === undefined)
65
- throw new AmaError("session_not_found", `会话不存在:${id}`, { exitCode: 5 });
66
+ throw new AmaError("session_not_found", msg().session.lookup.notFound(id), { exitCode: 5 });
66
67
  return file;
67
68
  }
68
69
  /**
@@ -19,8 +19,10 @@ export interface StatsTotals {
19
19
  cacheWrite: number;
20
20
  /** 有价请求的费用;没有任何有价请求时缺省。 */
21
21
  cost?: number;
22
- /** 无价请求数。 */
22
+ /** 无价请求数(不含订阅计费的)。 */
23
23
  unpriced: number;
24
+ /** [W6-I5] 订阅计费的请求数(ChatGPT 登录;不折算美元);没有时缺省。 */
25
+ subscription?: number;
24
26
  /** 0–1;报告缓存的端点没有输入时缺省。 */
25
27
  hitRate?: number;
26
28
  errors: number;
@@ -25,6 +25,7 @@ const newAcc = () => ({
25
25
  cacheWrite: 0,
26
26
  cost: 0,
27
27
  costed: 0,
28
+ subscription: 0,
28
29
  hitRead: 0,
29
30
  hitPrompt: 0,
30
31
  errors: 0,
@@ -45,6 +46,7 @@ function add(acc, b, reported, session) {
45
46
  acc.cacheWrite += b.cacheWrite;
46
47
  acc.cost += b.cost;
47
48
  acc.costed += b.costed;
49
+ acc.subscription += b.subscription;
48
50
  if (reported) {
49
51
  acc.hitRead += b.cacheRead;
50
52
  acc.hitPrompt += b.input + b.cacheRead + b.cacheWrite;
@@ -63,12 +65,14 @@ function totals(acc) {
63
65
  output: acc.output,
64
66
  cacheRead: acc.cacheRead,
65
67
  cacheWrite: acc.cacheWrite,
66
- unpriced: acc.requests - acc.costed,
68
+ unpriced: acc.requests - acc.costed - acc.subscription,
67
69
  errors: acc.errors,
68
70
  retries: acc.retries,
69
71
  };
70
72
  if (acc.costed > 0)
71
73
  out.cost = acc.cost;
74
+ if (acc.subscription > 0)
75
+ out.subscription = acc.subscription;
72
76
  if (acc.hitPrompt > 0)
73
77
  out.hitRate = acc.hitRead / acc.hitPrompt;
74
78
  if (acc.timedTurns > 0)
@@ -10,7 +10,8 @@ import { mkdirSync, readFileSync, renameSync, statSync, writeFileSync } from "no
10
10
  import { dirname } from "node:path";
11
11
  import { summarizeSessionFile } from "./stats-scan.js";
12
12
  export const STATS_INDEX_FILE = "stats-index.json";
13
- const INDEX_VERSION = 1;
13
+ // 2:桶加 subscription([W6-I5]),旧索引里订阅请求被算成 $0 有价,整体重扫
14
+ const INDEX_VERSION = 2;
14
15
  export function timeZoneKey(now = new Date()) {
15
16
  let zone = "";
16
17
  try {
@@ -5,7 +5,8 @@
5
5
  * - 请求来源:assistant 消息 = `turn`;`usage` 条目用自己的 `kind`(cache_warm、permission_classify…);
6
6
  * `compaction` / `branch_summary` 带的 usage 记为同名 kind(模型取最近一条 assistant 的)。
7
7
  * - token:input(不含缓存)/ output / cacheRead / cacheWrite;费用只累加有 `usage.cost` 的请求,
8
- * `costed` 记有价请求数,展示层据此区分「有价」「部分无价」「全无价」。
8
+ * `costed` 记有价请求数,展示层据此区分「有价」「部分无价」「全无价」。订阅计费
9
+ * (`usage.billing: "subscription"`,ChatGPT 登录)单列 `subscription`,不进费用也不算无价。
9
10
  * - 缓存三态:桶记下是否出现过 cacheRead > 0 或 cacheWrite > 0(`cacheSeen`);汇总时同一端点
10
11
  * (provider/model@channel)任一桶出现过即算报告缓存,其余端点不进命中率分母(同会话层三态)。
11
12
  * - 回合:非 `steer` 的用户消息开始一个回合,到下一个回合开始为止;回合计入首条 assistant 的桶,
@@ -31,6 +32,8 @@ export interface StatsBucket {
31
32
  cost: number;
32
33
  /** 有价请求数。 */
33
34
  costed: number;
35
+ /** [W6-I5] 订阅计费的请求数(不折算美元)。 */
36
+ subscription: number;
34
37
  /** 出现过 cacheRead > 0 或 cacheWrite > 0。 */
35
38
  cacheSeen: boolean;
36
39
  errors: number;
@@ -5,7 +5,8 @@
5
5
  * - 请求来源:assistant 消息 = `turn`;`usage` 条目用自己的 `kind`(cache_warm、permission_classify…);
6
6
  * `compaction` / `branch_summary` 带的 usage 记为同名 kind(模型取最近一条 assistant 的)。
7
7
  * - token:input(不含缓存)/ output / cacheRead / cacheWrite;费用只累加有 `usage.cost` 的请求,
8
- * `costed` 记有价请求数,展示层据此区分「有价」「部分无价」「全无价」。
8
+ * `costed` 记有价请求数,展示层据此区分「有价」「部分无价」「全无价」。订阅计费
9
+ * (`usage.billing: "subscription"`,ChatGPT 登录)单列 `subscription`,不进费用也不算无价。
9
10
  * - 缓存三态:桶记下是否出现过 cacheRead > 0 或 cacheWrite > 0(`cacheSeen`);汇总时同一端点
10
11
  * (provider/model@channel)任一桶出现过即算报告缓存,其余端点不进命中率分母(同会话层三态)。
11
12
  * - 回合:非 `steer` 的用户消息开始一个回合,到下一个回合开始为止;回合计入首条 assistant 的桶,
@@ -64,6 +65,7 @@ export function summarizeSessionFile(file) {
64
65
  cacheWrite: 0,
65
66
  cost: 0,
66
67
  costed: 0,
68
+ subscription: 0,
67
69
  cacheSeen: false,
68
70
  errors: 0,
69
71
  retries: 0,
@@ -88,7 +90,9 @@ export function summarizeSessionFile(file) {
88
90
  bucket.cacheWrite += num(u.cacheWrite);
89
91
  if (num(u.cacheRead) > 0 || num(u.cacheWrite) > 0)
90
92
  bucket.cacheSeen = true;
91
- if (isRec(u.cost) && typeof u.cost["total"] === "number") {
93
+ if (u.billing === "subscription")
94
+ bucket.subscription++;
95
+ else if (isRec(u.cost) && typeof u.cost["total"] === "number") {
92
96
  bucket.cost += num(u.cost["total"]);
93
97
  bucket.costed++;
94
98
  }
@@ -41,6 +41,17 @@ export interface SessionLock {
41
41
  export declare function acquireLock(file: string): SessionLock;
42
42
  /** 目录下的会话文件(按文件名倒序 = 最新在前)。 */
43
43
  export declare function listSessionFiles(dir: string): string[];
44
+ /** 子 Agent(task)会话第一条条目的 customType(与 agents/task-record.ts 同值)。 */
45
+ export declare const TASK_SESSION_CUSTOM_TYPE = "ama.task";
46
+ /**
47
+ * 子 Agent 会话:头有 `parentSession`,且第一条条目是 `custom{ama.task}`(fork / clone 也带
48
+ * `parentSession`,但第一条不是任务记录,不算)。
49
+ */
50
+ export declare function isSubagentSession(header: {
51
+ parentSession?: string;
52
+ } | undefined, first: unknown): boolean;
53
+ /** 只读文件开头的前两行(头 + 第一条条目)判断是否子 Agent 会话;读不了 / 解析不了 → false。 */
54
+ export declare function isSubagentSessionFile(file: string): boolean;
44
55
  /** 移到 `<sessionsRoot>/.trash/<删除时间毫秒>__<编码目录>__<文件名>`,返回新路径。 */
45
56
  export declare function trashSession(file: string, sessionsRoot: string, now?: number): string;
46
57
  /** 删除 trash 中超过保留期的文件,返回删除的路径。 */
@@ -7,7 +7,7 @@
7
7
  * - 锁:`<file>.lock`(O_EXCL 创建,内容为 pid);持锁进程已不在 → 视为陈旧锁并接管。
8
8
  * - prune:移到 `<sessionsRoot>/.trash/`,文件名前缀删除时间;`purgeTrash` 清理超过 7 天的。
9
9
  */
10
- import { closeSync, existsSync, mkdirSync, openSync, readFileSync, readdirSync, renameSync, rmSync, statSync, truncateSync, writeFileSync, writeSync, } from "node:fs";
10
+ import { closeSync, existsSync, mkdirSync, openSync, readFileSync, readdirSync, renameSync, readSync, rmSync, statSync, truncateSync, writeFileSync, writeSync, } from "node:fs";
11
11
  import { basename, dirname, join } from "node:path";
12
12
  import { AmaError } from "../errors.js";
13
13
  export const SESSION_FILE_SUFFIX = ".jsonl";
@@ -182,6 +182,53 @@ export function listSessionFiles(dir) {
182
182
  .reverse()
183
183
  .map((name) => join(dir, name));
184
184
  }
185
+ /** 子 Agent(task)会话第一条条目的 customType(与 agents/task-record.ts 同值)。 */
186
+ export const TASK_SESSION_CUSTOM_TYPE = "ama.task";
187
+ /**
188
+ * 子 Agent 会话:头有 `parentSession`,且第一条条目是 `custom{ama.task}`(fork / clone 也带
189
+ * `parentSession`,但第一条不是任务记录,不算)。
190
+ */
191
+ export function isSubagentSession(header, first) {
192
+ if (header?.parentSession === undefined)
193
+ return false;
194
+ const entry = first;
195
+ return entry?.type === "custom" && entry.customType === TASK_SESSION_CUSTOM_TYPE;
196
+ }
197
+ const HEAD_CHUNK = 16 * 1024;
198
+ const HEAD_LIMIT = 1024 * 1024;
199
+ /** 只读文件开头的前两行(头 + 第一条条目)判断是否子 Agent 会话;读不了 / 解析不了 → false。 */
200
+ export function isSubagentSessionFile(file) {
201
+ let fd;
202
+ try {
203
+ fd = openSync(file, "r");
204
+ const chunks = [];
205
+ let size = 0;
206
+ let newlines = 0;
207
+ while (newlines < 2 && size < HEAD_LIMIT) {
208
+ const buffer = Buffer.alloc(HEAD_CHUNK);
209
+ const read = readSync(fd, buffer, 0, HEAD_CHUNK, size);
210
+ if (read === 0)
211
+ break;
212
+ const chunk = buffer.subarray(0, read);
213
+ for (const byte of chunk)
214
+ if (byte === 0x0a)
215
+ newlines++;
216
+ chunks.push(chunk);
217
+ size += read;
218
+ }
219
+ const [header, first] = Buffer.concat(chunks).toString("utf8").split("\n", 2);
220
+ if (header === undefined || first === undefined || first.trim() === "")
221
+ return false;
222
+ return isSubagentSession(JSON.parse(header), JSON.parse(first));
223
+ }
224
+ catch {
225
+ return false;
226
+ }
227
+ finally {
228
+ if (fd !== undefined)
229
+ closeSync(fd);
230
+ }
231
+ }
185
232
  /** 移到 `<sessionsRoot>/.trash/<删除时间毫秒>__<编码目录>__<文件名>`,返回新路径。 */
186
233
  export function trashSession(file, sessionsRoot, now = Date.now()) {
187
234
  const trash = join(sessionsRoot, TRASH_DIR_NAME);
@@ -172,6 +172,8 @@ export interface SessionListItem {
172
172
  modifiedAt: string;
173
173
  firstPrompt?: string;
174
174
  messageCount: number;
175
+ /** 子 Agent(task)会话:继续 / 恢复选择器缺省跳过。 */
176
+ subagent?: true;
175
177
  }
176
178
  export interface SessionManagerApi {
177
179
  readonly id: string;
@@ -93,7 +93,8 @@ export async function withBuiltinSkills(skills, dataDir, builtins = BUILTIN_SKIL
93
93
  await ensureFile(location, builtinSkillText(builtin));
94
94
  }
95
95
  catch (error) {
96
- warnings.push(`内置 Skill ${builtin.name} 写入失败:${error.message}`);
96
+ // 与 skills/ 其它加载告警一样固定英文(模型侧模块不 import i18n,见 docs/i18n.md)
97
+ warnings.push(`built-in skill ${builtin.name} could not be written: ${error.message}`);
97
98
  continue;
98
99
  }
99
100
  out.push({
@@ -61,6 +61,31 @@ export type ImageFit = {
61
61
  */
62
62
  export declare function fitImage(buf: Buffer, mimeType: string, options?: ImageFitOptions, path?: string): Promise<ImageFit>;
63
63
  /**
64
- * 读一张图片作为附件。文件不存在、不是图片、超过上限 → AmaError(`invalid_arguments`),文案给用户看。
64
+ * [W6-C0] 读图失败的结构化说明:`AmaError.detail`。本模块属模型侧(不 import i18n),`message` 固定英文;
65
+ * 界面层(`modes/image-input.ts`)按 `reason` 渲染本地化文案。
66
+ */
67
+ export type ImageFileErrorDetail = {
68
+ reason: "missing" | "not_file" | "unsupported";
69
+ path: string;
70
+ } | {
71
+ reason: "too_large";
72
+ path: string;
73
+ limitMb: string;
74
+ sizeMb: string;
75
+ hint?: ImageFitHint;
76
+ } | {
77
+ reason: "too_wide";
78
+ path: string;
79
+ maxEdge: number;
80
+ size?: ImageSize;
81
+ hint?: ImageFitHint;
82
+ };
83
+ /** 超限时为什么没缩放:配置关闭 / 没有缩放工具 / 缩放后仍超限。 */
84
+ export type ImageFitHint = "resize_off" | "no_tool" | "still_too_large";
85
+ /** `AmaError.detail` 是否是读图失败的说明。 */
86
+ export declare function isImageFileErrorDetail(detail: unknown): detail is ImageFileErrorDetail;
87
+ /**
88
+ * 读一张图片作为附件。文件不存在、不是图片、超过上限 → AmaError(`invalid_arguments`,英文 message,
89
+ * `detail` 为 `ImageFileErrorDetail`,界面层据此本地化)。
65
90
  */
66
91
  export declare function loadImageFile(path: string, options?: ImageFitOptions): Promise<LoadedImage>;