@armadra/agent 0.0.0-stage → 0.2.1

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 (407) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/LICENSE +21 -0
  3. package/README.md +426 -2
  4. package/dist/agent/agent.d.ts +56 -0
  5. package/dist/agent/agent.js +129 -0
  6. package/dist/agent/loop.d.ts +51 -0
  7. package/dist/agent/loop.js +158 -0
  8. package/dist/agent/queue.d.ts +25 -0
  9. package/dist/agent/queue.js +55 -0
  10. package/dist/agent/retry.d.ts +22 -0
  11. package/dist/agent/retry.js +92 -0
  12. package/dist/agent/schema.d.ts +27 -0
  13. package/dist/agent/schema.js +186 -0
  14. package/dist/agent/session-cache.d.ts +100 -0
  15. package/dist/agent/session-cache.js +511 -0
  16. package/dist/agent/session-compaction.d.ts +49 -0
  17. package/dist/agent/session-compaction.js +251 -0
  18. package/dist/agent/session-core.d.ts +103 -0
  19. package/dist/agent/session-core.js +7 -0
  20. package/dist/agent/session-run.d.ts +55 -0
  21. package/dist/agent/session-run.js +246 -0
  22. package/dist/agent/session-state.d.ts +39 -0
  23. package/dist/agent/session-state.js +118 -0
  24. package/dist/agent/session-subagent.d.ts +54 -0
  25. package/dist/agent/session-subagent.js +157 -0
  26. package/dist/agent/session-sync.d.ts +20 -0
  27. package/dist/agent/session-sync.js +104 -0
  28. package/dist/agent/session-tools.d.ts +24 -0
  29. package/dist/agent/session-tools.js +277 -0
  30. package/dist/agent/session.d.ts +117 -0
  31. package/dist/agent/session.js +484 -0
  32. package/dist/agent/system-prompt.d.ts +49 -0
  33. package/dist/agent/system-prompt.js +121 -0
  34. package/dist/agent/tool-runner.d.ts +64 -0
  35. package/dist/agent/tool-runner.js +309 -0
  36. package/dist/agent/transform.d.ts +26 -0
  37. package/dist/agent/transform.js +171 -0
  38. package/dist/agent/types.d.ts +378 -0
  39. package/dist/agent/types.js +21 -0
  40. package/dist/ai/apis/anthropic-messages.d.ts +26 -0
  41. package/dist/ai/apis/anthropic-messages.js +214 -0
  42. package/dist/ai/apis/anthropic-request.d.ts +42 -0
  43. package/dist/ai/apis/anthropic-request.js +282 -0
  44. package/dist/ai/apis/api.d.ts +28 -0
  45. package/dist/ai/apis/api.js +102 -0
  46. package/dist/ai/apis/cache-params.d.ts +48 -0
  47. package/dist/ai/apis/cache-params.js +163 -0
  48. package/dist/ai/apis/google-generative-ai.d.ts +32 -0
  49. package/dist/ai/apis/google-generative-ai.js +249 -0
  50. package/dist/ai/apis/google-request.d.ts +40 -0
  51. package/dist/ai/apis/google-request.js +255 -0
  52. package/dist/ai/apis/openai-compat.d.ts +35 -0
  53. package/dist/ai/apis/openai-compat.js +142 -0
  54. package/dist/ai/apis/openai-completions.d.ts +28 -0
  55. package/dist/ai/apis/openai-completions.js +246 -0
  56. package/dist/ai/apis/openai-request.d.ts +35 -0
  57. package/dist/ai/apis/openai-request.js +303 -0
  58. package/dist/ai/apis/openai-responses-request.d.ts +52 -0
  59. package/dist/ai/apis/openai-responses-request.js +266 -0
  60. package/dist/ai/apis/openai-responses.d.ts +28 -0
  61. package/dist/ai/apis/openai-responses.js +303 -0
  62. package/dist/ai/apis/shared.d.ts +56 -0
  63. package/dist/ai/apis/shared.js +179 -0
  64. package/dist/ai/cache/economics.d.ts +24 -0
  65. package/dist/ai/cache/economics.js +69 -0
  66. package/dist/ai/cache/fingerprint.d.ts +17 -0
  67. package/dist/ai/cache/fingerprint.js +39 -0
  68. package/dist/ai/cache/miss.d.ts +49 -0
  69. package/dist/ai/cache/miss.js +96 -0
  70. package/dist/ai/cache/reporting.d.ts +39 -0
  71. package/dist/ai/cache/reporting.js +102 -0
  72. package/dist/ai/cache/types.d.ts +94 -0
  73. package/dist/ai/cache/types.js +19 -0
  74. package/dist/ai/cache/warmer.d.ts +94 -0
  75. package/dist/ai/cache/warmer.js +224 -0
  76. package/dist/ai/context.d.ts +35 -0
  77. package/dist/ai/context.js +114 -0
  78. package/dist/ai/cost.d.ts +21 -0
  79. package/dist/ai/cost.js +60 -0
  80. package/dist/ai/event-stream.d.ts +33 -0
  81. package/dist/ai/event-stream.js +101 -0
  82. package/dist/ai/fake/fake-provider.d.ts +68 -0
  83. package/dist/ai/fake/fake-provider.js +278 -0
  84. package/dist/ai/fake/fake-script.d.ts +69 -0
  85. package/dist/ai/fake/fake-script.js +142 -0
  86. package/dist/ai/http.d.ts +54 -0
  87. package/dist/ai/http.js +212 -0
  88. package/dist/ai/json-partial.d.ts +17 -0
  89. package/dist/ai/json-partial.js +243 -0
  90. package/dist/ai/overflow.d.ts +22 -0
  91. package/dist/ai/overflow.js +61 -0
  92. package/dist/ai/providers/auth.d.ts +71 -0
  93. package/dist/ai/providers/auth.js +202 -0
  94. package/dist/ai/providers/builtin.d.ts +23 -0
  95. package/dist/ai/providers/builtin.js +148 -0
  96. package/dist/ai/providers/catalog-data.d.ts +5 -0
  97. package/dist/ai/providers/catalog-data.js +19 -0
  98. package/dist/ai/providers/catalog.d.ts +28 -0
  99. package/dist/ai/providers/catalog.js +166 -0
  100. package/dist/ai/providers/registry.d.ts +83 -0
  101. package/dist/ai/providers/registry.js +305 -0
  102. package/dist/ai/sse.d.ts +32 -0
  103. package/dist/ai/sse.js +140 -0
  104. package/dist/ai/thinking.d.ts +42 -0
  105. package/dist/ai/thinking.js +101 -0
  106. package/dist/ai/types.d.ts +428 -0
  107. package/dist/ai/types.js +19 -0
  108. package/dist/bundle/ama-sandbox.cjs +324 -0
  109. package/dist/bundle/ama.cjs +25770 -0
  110. package/dist/bundle.d.ts +9 -0
  111. package/dist/bundle.js +15 -0
  112. package/dist/cli/args.d.ts +82 -0
  113. package/dist/cli/args.js +381 -0
  114. package/dist/cli/bootstrap.d.ts +18 -0
  115. package/dist/cli/bootstrap.js +398 -0
  116. package/dist/cli/compose-providers.d.ts +37 -0
  117. package/dist/cli/compose-providers.js +104 -0
  118. package/dist/cli/compose-session.d.ts +69 -0
  119. package/dist/cli/compose-session.js +370 -0
  120. package/dist/cli/compose-store.d.ts +24 -0
  121. package/dist/cli/compose-store.js +125 -0
  122. package/dist/cli/compose.d.ts +106 -0
  123. package/dist/cli/compose.js +206 -0
  124. package/dist/cli/default-model.d.ts +16 -0
  125. package/dist/cli/default-model.js +24 -0
  126. package/dist/cli/deps.d.ts +205 -0
  127. package/dist/cli/deps.js +12 -0
  128. package/dist/cli/exit-codes.d.ts +29 -0
  129. package/dist/cli/exit-codes.js +40 -0
  130. package/dist/cli/main.d.ts +26 -0
  131. package/dist/cli/main.js +165 -0
  132. package/dist/cli/runtime.d.ts +90 -0
  133. package/dist/cli/runtime.js +8 -0
  134. package/dist/cli/startup-screen.d.ts +15 -0
  135. package/dist/cli/startup-screen.js +56 -0
  136. package/dist/cli/startup-steps.d.ts +35 -0
  137. package/dist/cli/startup-steps.js +197 -0
  138. package/dist/cli/subcommands/auth.d.ts +12 -0
  139. package/dist/cli/subcommands/auth.js +91 -0
  140. package/dist/cli/subcommands/config.d.ts +44 -0
  141. package/dist/cli/subcommands/config.js +201 -0
  142. package/dist/cli/subcommands/context.d.ts +21 -0
  143. package/dist/cli/subcommands/context.js +41 -0
  144. package/dist/cli/subcommands/doctor.d.ts +11 -0
  145. package/dist/cli/subcommands/doctor.js +246 -0
  146. package/dist/cli/subcommands/models-cache-probe.d.ts +34 -0
  147. package/dist/cli/subcommands/models-cache-probe.js +190 -0
  148. package/dist/cli/subcommands/models-discover.d.ts +40 -0
  149. package/dist/cli/subcommands/models-discover.js +204 -0
  150. package/dist/cli/subcommands/models.d.ts +40 -0
  151. package/dist/cli/subcommands/models.js +144 -0
  152. package/dist/cli/subcommands/sessions.d.ts +11 -0
  153. package/dist/cli/subcommands/sessions.js +100 -0
  154. package/dist/codemode/capability.d.ts +37 -0
  155. package/dist/codemode/capability.js +55 -0
  156. package/dist/codemode/declarations.d.ts +44 -0
  157. package/dist/codemode/declarations.js +111 -0
  158. package/dist/codemode/host-side.d.ts +59 -0
  159. package/dist/codemode/host-side.js +253 -0
  160. package/dist/codemode/modes.d.ts +23 -0
  161. package/dist/codemode/modes.js +40 -0
  162. package/dist/codemode/protocol.d.ts +91 -0
  163. package/dist/codemode/protocol.js +114 -0
  164. package/dist/codemode/sandbox-entry.d.ts +25 -0
  165. package/dist/codemode/sandbox-entry.js +323 -0
  166. package/dist/codemode/store.d.ts +26 -0
  167. package/dist/codemode/store.js +53 -0
  168. package/dist/codemode/tool.d.ts +105 -0
  169. package/dist/codemode/tool.js +283 -0
  170. package/dist/compaction/branch-summary.d.ts +30 -0
  171. package/dist/compaction/branch-summary.js +79 -0
  172. package/dist/compaction/breaker.d.ts +32 -0
  173. package/dist/compaction/breaker.js +65 -0
  174. package/dist/compaction/cut-point.d.ts +23 -0
  175. package/dist/compaction/cut-point.js +70 -0
  176. package/dist/compaction/estimate.d.ts +30 -0
  177. package/dist/compaction/estimate.js +114 -0
  178. package/dist/compaction/prune-tier.d.ts +31 -0
  179. package/dist/compaction/prune-tier.js +83 -0
  180. package/dist/compaction/serialize.d.ts +20 -0
  181. package/dist/compaction/serialize.js +115 -0
  182. package/dist/compaction/summarize-tier.d.ts +111 -0
  183. package/dist/compaction/summarize-tier.js +305 -0
  184. package/dist/config/auth-file.d.ts +39 -0
  185. package/dist/config/auth-file.js +92 -0
  186. package/dist/config/context-files.d.ts +30 -0
  187. package/dist/config/context-files.js +77 -0
  188. package/dist/config/load.d.ts +45 -0
  189. package/dist/config/load.js +97 -0
  190. package/dist/config/merge.d.ts +73 -0
  191. package/dist/config/merge.js +248 -0
  192. package/dist/config/paths.d.ts +38 -0
  193. package/dist/config/paths.js +108 -0
  194. package/dist/config/profile.d.ts +27 -0
  195. package/dist/config/profile.js +65 -0
  196. package/dist/config/schema.d.ts +34 -0
  197. package/dist/config/schema.js +413 -0
  198. package/dist/config/trust.d.ts +42 -0
  199. package/dist/config/trust.js +122 -0
  200. package/dist/config/types.d.ts +172 -0
  201. package/dist/config/types.js +27 -0
  202. package/dist/config/write.d.ts +10 -0
  203. package/dist/config/write.js +25 -0
  204. package/dist/errors.d.ts +28 -0
  205. package/dist/errors.js +30 -0
  206. package/dist/hooks/config.d.ts +49 -0
  207. package/dist/hooks/config.js +102 -0
  208. package/dist/hooks/dispatcher.d.ts +41 -0
  209. package/dist/hooks/dispatcher.js +104 -0
  210. package/dist/hooks/matcher.d.ts +22 -0
  211. package/dist/hooks/matcher.js +108 -0
  212. package/dist/hooks/protocol.d.ts +33 -0
  213. package/dist/hooks/protocol.js +240 -0
  214. package/dist/hooks/runner.d.ts +30 -0
  215. package/dist/hooks/runner.js +143 -0
  216. package/dist/hooks/types.d.ts +147 -0
  217. package/dist/hooks/types.js +20 -0
  218. package/dist/host/api-impl.d.ts +75 -0
  219. package/dist/host/api-impl.js +173 -0
  220. package/dist/host/loader.d.ts +31 -0
  221. package/dist/host/loader.js +147 -0
  222. package/dist/host/types.d.ts +169 -0
  223. package/dist/host/types.js +14 -0
  224. package/dist/host.d.ts +5 -0
  225. package/dist/host.js +4 -0
  226. package/dist/index.d.ts +41 -0
  227. package/dist/index.js +28 -0
  228. package/dist/modes/commands-core.d.ts +44 -0
  229. package/dist/modes/commands-core.js +171 -0
  230. package/dist/modes/interactive/approval-dialog.d.ts +48 -0
  231. package/dist/modes/interactive/approval-dialog.js +202 -0
  232. package/dist/modes/interactive/commands.d.ts +41 -0
  233. package/dist/modes/interactive/commands.js +202 -0
  234. package/dist/modes/interactive/completion.d.ts +53 -0
  235. package/dist/modes/interactive/completion.js +157 -0
  236. package/dist/modes/interactive/interactive-mode.d.ts +46 -0
  237. package/dist/modes/interactive/interactive-mode.js +487 -0
  238. package/dist/modes/interactive/key-dispatch.d.ts +29 -0
  239. package/dist/modes/interactive/key-dispatch.js +107 -0
  240. package/dist/modes/interactive/line/line-editor.d.ts +50 -0
  241. package/dist/modes/interactive/line/line-editor.js +232 -0
  242. package/dist/modes/interactive/line/line-mode.d.ts +20 -0
  243. package/dist/modes/interactive/line/line-mode.js +216 -0
  244. package/dist/modes/interactive/line/line-render.d.ts +35 -0
  245. package/dist/modes/interactive/line/line-render.js +171 -0
  246. package/dist/modes/interactive/line/paste-state.d.ts +26 -0
  247. package/dist/modes/interactive/line/paste-state.js +72 -0
  248. package/dist/modes/interactive/message-view.d.ts +77 -0
  249. package/dist/modes/interactive/message-view.js +269 -0
  250. package/dist/modes/interactive/pickers.d.ts +42 -0
  251. package/dist/modes/interactive/pickers.js +115 -0
  252. package/dist/modes/interactive/startup-ui.d.ts +28 -0
  253. package/dist/modes/interactive/startup-ui.js +238 -0
  254. package/dist/modes/interactive/status-bar.d.ts +48 -0
  255. package/dist/modes/interactive/status-bar.js +139 -0
  256. package/dist/modes/interactive/tool-view.d.ts +95 -0
  257. package/dist/modes/interactive/tool-view.js +344 -0
  258. package/dist/modes/print/json-event.d.ts +15 -0
  259. package/dist/modes/print/json-event.js +39 -0
  260. package/dist/modes/print/print-mode.d.ts +15 -0
  261. package/dist/modes/print/print-mode.js +96 -0
  262. package/dist/modes/rpc/commands.d.ts +40 -0
  263. package/dist/modes/rpc/commands.js +258 -0
  264. package/dist/modes/rpc/jsonl.d.ts +16 -0
  265. package/dist/modes/rpc/jsonl.js +55 -0
  266. package/dist/modes/rpc/rpc-mode.d.ts +22 -0
  267. package/dist/modes/rpc/rpc-mode.js +153 -0
  268. package/dist/modes/session-report.d.ts +55 -0
  269. package/dist/modes/session-report.js +278 -0
  270. package/dist/modes/shared.d.ts +13 -0
  271. package/dist/modes/shared.js +52 -0
  272. package/dist/modes/startup-ui-text.d.ts +16 -0
  273. package/dist/modes/startup-ui-text.js +103 -0
  274. package/dist/permissions/broker.d.ts +47 -0
  275. package/dist/permissions/broker.js +107 -0
  276. package/dist/permissions/dangerous.d.ts +47 -0
  277. package/dist/permissions/dangerous.js +370 -0
  278. package/dist/permissions/pipeline.d.ts +51 -0
  279. package/dist/permissions/pipeline.js +181 -0
  280. package/dist/permissions/preview.d.ts +43 -0
  281. package/dist/permissions/preview.js +463 -0
  282. package/dist/permissions/rules.d.ts +58 -0
  283. package/dist/permissions/rules.js +249 -0
  284. package/dist/permissions/types.d.ts +100 -0
  285. package/dist/permissions/types.js +18 -0
  286. package/dist/rpc.d.ts +171 -0
  287. package/dist/rpc.js +13 -0
  288. package/dist/sdk.d.ts +98 -0
  289. package/dist/sdk.js +195 -0
  290. package/dist/session/manager.d.ts +70 -0
  291. package/dist/session/manager.js +278 -0
  292. package/dist/session/migrate.d.ts +19 -0
  293. package/dist/session/migrate.js +53 -0
  294. package/dist/session/projection.d.ts +50 -0
  295. package/dist/session/projection.js +180 -0
  296. package/dist/session/store.d.ts +47 -0
  297. package/dist/session/store.js +210 -0
  298. package/dist/session/tree.d.ts +21 -0
  299. package/dist/session/tree.js +88 -0
  300. package/dist/session/types.d.ts +199 -0
  301. package/dist/session/types.js +18 -0
  302. package/dist/skills/discover.d.ts +60 -0
  303. package/dist/skills/discover.js +160 -0
  304. package/dist/skills/expand.d.ts +35 -0
  305. package/dist/skills/expand.js +46 -0
  306. package/dist/skills/frontmatter.d.ts +27 -0
  307. package/dist/skills/frontmatter.js +157 -0
  308. package/dist/skills/index-prompt.d.ts +13 -0
  309. package/dist/skills/index-prompt.js +42 -0
  310. package/dist/skills/templates.d.ts +52 -0
  311. package/dist/skills/templates.js +177 -0
  312. package/dist/tools/bash.d.ts +49 -0
  313. package/dist/tools/bash.js +222 -0
  314. package/dist/tools/edit-fuzzy.d.ts +36 -0
  315. package/dist/tools/edit-fuzzy.js +129 -0
  316. package/dist/tools/edit.d.ts +38 -0
  317. package/dist/tools/edit.js +241 -0
  318. package/dist/tools/file-mutex.d.ts +8 -0
  319. package/dist/tools/file-mutex.js +29 -0
  320. package/dist/tools/glob.d.ts +44 -0
  321. package/dist/tools/glob.js +217 -0
  322. package/dist/tools/grep.d.ts +39 -0
  323. package/dist/tools/grep.js +179 -0
  324. package/dist/tools/ignore.d.ts +40 -0
  325. package/dist/tools/ignore.js +174 -0
  326. package/dist/tools/ls.d.ts +21 -0
  327. package/dist/tools/ls.js +96 -0
  328. package/dist/tools/output-accumulator.d.ts +48 -0
  329. package/dist/tools/output-accumulator.js +106 -0
  330. package/dist/tools/paths.d.ts +20 -0
  331. package/dist/tools/paths.js +58 -0
  332. package/dist/tools/presets.d.ts +71 -0
  333. package/dist/tools/presets.js +128 -0
  334. package/dist/tools/process-tree.d.ts +35 -0
  335. package/dist/tools/process-tree.js +125 -0
  336. package/dist/tools/read.d.ts +28 -0
  337. package/dist/tools/read.js +181 -0
  338. package/dist/tools/registry.d.ts +43 -0
  339. package/dist/tools/registry.js +106 -0
  340. package/dist/tools/shell.d.ts +38 -0
  341. package/dist/tools/shell.js +91 -0
  342. package/dist/tools/task.d.ts +29 -0
  343. package/dist/tools/task.js +107 -0
  344. package/dist/tools/todo.d.ts +28 -0
  345. package/dist/tools/todo.js +107 -0
  346. package/dist/tools/truncate.d.ts +44 -0
  347. package/dist/tools/truncate.js +175 -0
  348. package/dist/tools/types.d.ts +135 -0
  349. package/dist/tools/types.js +19 -0
  350. package/dist/tools/write.d.ts +20 -0
  351. package/dist/tools/write.js +84 -0
  352. package/dist/tui/ansi.d.ts +29 -0
  353. package/dist/tui/ansi.js +420 -0
  354. package/dist/tui/component.d.ts +38 -0
  355. package/dist/tui/component.js +13 -0
  356. package/dist/tui/components/box.d.ts +26 -0
  357. package/dist/tui/components/box.js +65 -0
  358. package/dist/tui/components/container.d.ts +14 -0
  359. package/dist/tui/components/container.js +39 -0
  360. package/dist/tui/components/editor-buffer.d.ts +67 -0
  361. package/dist/tui/components/editor-buffer.js +300 -0
  362. package/dist/tui/components/editor-paste.d.ts +29 -0
  363. package/dist/tui/components/editor-paste.js +64 -0
  364. package/dist/tui/components/editor.d.ts +114 -0
  365. package/dist/tui/components/editor.js +530 -0
  366. package/dist/tui/components/key-value.d.ts +29 -0
  367. package/dist/tui/components/key-value.js +48 -0
  368. package/dist/tui/components/loader.d.ts +35 -0
  369. package/dist/tui/components/loader.js +71 -0
  370. package/dist/tui/components/markdown.d.ts +90 -0
  371. package/dist/tui/components/markdown.js +462 -0
  372. package/dist/tui/components/meter.d.ts +29 -0
  373. package/dist/tui/components/meter.js +47 -0
  374. package/dist/tui/components/overlay.d.ts +24 -0
  375. package/dist/tui/components/overlay.js +52 -0
  376. package/dist/tui/components/select-list.d.ts +57 -0
  377. package/dist/tui/components/select-list.js +179 -0
  378. package/dist/tui/components/spacer.d.ts +11 -0
  379. package/dist/tui/components/spacer.js +16 -0
  380. package/dist/tui/components/text.d.ts +30 -0
  381. package/dist/tui/components/text.js +65 -0
  382. package/dist/tui/keybindings.d.ts +66 -0
  383. package/dist/tui/keybindings.js +120 -0
  384. package/dist/tui/keys.d.ts +38 -0
  385. package/dist/tui/keys.js +275 -0
  386. package/dist/tui/stdin-buffer.d.ts +41 -0
  387. package/dist/tui/stdin-buffer.js +206 -0
  388. package/dist/tui/terminal.d.ts +79 -0
  389. package/dist/tui/terminal.js +153 -0
  390. package/dist/tui/theme.d.ts +31 -0
  391. package/dist/tui/theme.js +199 -0
  392. package/dist/tui/tui.d.ts +103 -0
  393. package/dist/tui/tui.js +363 -0
  394. package/dist/tui/vt-screen.d.ts +46 -0
  395. package/dist/tui/vt-screen.js +251 -0
  396. package/dist/tui.d.ts +30 -0
  397. package/dist/tui.js +31 -0
  398. package/dist/version.d.ts +8 -0
  399. package/dist/version.js +24 -0
  400. package/docs/codemode.md +102 -0
  401. package/docs/hooks.md +196 -0
  402. package/docs/host-api.md +161 -0
  403. package/docs/providers.md +316 -0
  404. package/docs/rpc.md +253 -0
  405. package/docs/session-format.md +119 -0
  406. package/docs/tui.md +168 -0
  407. package/package.json +101 -4
@@ -0,0 +1,398 @@
1
+ /**
2
+ * 启动序列编排(设计 §11.1 第 3–16 步、§11.2)。[B5]
3
+ *
4
+ * `bootstrap(args, deps, io)` 跑第 3–14 步并返回 Runtime(SDK `createRuntime()` 复用);
5
+ * `runCli(argv, deps, io)` 在其前后加上第 2 步(参数)与第 15–16 步(模式分派),返回退出码。
6
+ * 每步失败抛 `StartupError{exitCode}`;具体实现经 RuntimeDeps 注入(见 cli/deps.ts)。
7
+ */
8
+ import { existsSync } from "node:fs";
9
+ import { resolve } from "node:path";
10
+ import { defaultAuthFilePath } from "../config/auth-file.js";
11
+ import { findContextFiles } from "../config/context-files.js";
12
+ import { loadConfigFile } from "../config/load.js";
13
+ import { mergeBaseLayers, mergeProjectAndCli } from "../config/merge.js";
14
+ import { CONFIG_FILE, ensurePaths, projectFile, resolvePaths, userFile } from "../config/paths.js";
15
+ import { loadProfile } from "../config/profile.js";
16
+ import { decideTrust } from "../config/trust.js";
17
+ import { AmaError, StartupError, isAmaError } from "../errors.js";
18
+ import { loadHookConfigs } from "../hooks/config.js";
19
+ import { HookDispatcher } from "../hooks/dispatcher.js";
20
+ import { AgentEventBus, createHostApi } from "../host/api-impl.js";
21
+ import { activateHost, disposeHost } from "../host/loader.js";
22
+ import { HELP_TEXT, parseArgs, UsageError } from "./args.js";
23
+ import { ExitCode } from "./exit-codes.js";
24
+ import { applyProfile, applyToolFilters, decideMode, defaultSendUser, instructionSources, resolveModel, sessionRequestOf, sourceOf, step, thinkingOf, toStartupError, } from "./startup-steps.js";
25
+ /** §11.1 第 3–14 步。 */
26
+ export async function bootstrap(argsIn, deps, io) {
27
+ const warnings = [];
28
+ const warn = (message) => {
29
+ warnings.push(message);
30
+ };
31
+ // 3. profile
32
+ let args = argsIn;
33
+ let profile;
34
+ if (args.profile !== undefined) {
35
+ const profilePath = args.profile;
36
+ profile = await step(ExitCode.Config, "profile", () => loadProfile(profilePath, io.cwd));
37
+ warnings.push(...profile.warnings);
38
+ args = applyProfile(args, profile);
39
+ }
40
+ // 4. 模式
41
+ const mode = decideMode(args, io);
42
+ const interactive = mode === "interactive" || mode === "line";
43
+ // 5. 目录
44
+ const paths = await step(ExitCode.Config, "目录", () => {
45
+ const resolved = resolvePaths({ env: io.env, cwd: io.cwd, sessionDirFlag: args.sessionDir });
46
+ ensurePaths(resolved);
47
+ return resolved;
48
+ });
49
+ // 6. 用户级 + profile.config
50
+ const base = await step(ExitCode.Config, "配置", () => {
51
+ const user = loadConfigFile("config", userFile(paths, CONFIG_FILE));
52
+ if (user !== undefined)
53
+ warnings.push(...user.warnings);
54
+ return mergeBaseLayers({
55
+ user: user?.value,
56
+ profile: profile?.config,
57
+ hasProfile: profile !== undefined,
58
+ });
59
+ });
60
+ // 7. 会话
61
+ let request = sessionRequestOf(args);
62
+ if (request === "pick") {
63
+ if (!interactive || deps.ui?.pickSession === undefined || deps.sessions.list === undefined) {
64
+ throw new UsageError("--resume 在非交互模式下需要会话 id");
65
+ }
66
+ const items = await step(ExitCode.Session, "会话列表", () => deps.sessions.list?.({ sessionDir: paths.sessionDir, cwd: paths.cwd }) ?? []);
67
+ const id = await deps.ui.pickSession(items);
68
+ if (id === undefined)
69
+ throw new StartupError("session_not_found", "未选择会话", ExitCode.Session);
70
+ request = { kind: "resume", id };
71
+ }
72
+ const sessionRequest = request;
73
+ const sessionManager = await step(ExitCode.Session, "会话", () => deps.sessions.open(sessionRequest, { sessionDir: paths.sessionDir, cwd: paths.cwd }));
74
+ let sessionCwd = sessionManager.cwd;
75
+ if (!existsSync(sessionCwd)) {
76
+ const replacement = interactive ? await deps.ui?.askCwd?.(sessionCwd) : undefined;
77
+ if (replacement === undefined) {
78
+ throw new StartupError("session_corrupt", `会话的工作目录不存在:${sessionCwd}`, ExitCode.Session);
79
+ }
80
+ sessionCwd = resolve(replacement);
81
+ }
82
+ const runtimePaths = { ...paths, cwd: sessionCwd };
83
+ // 8. 信任(以会话 cwd 为准)
84
+ const trust = await step(ExitCode.Config, "信任", () => decideTrust({
85
+ cwd: sessionCwd,
86
+ configDir: paths.configDir,
87
+ flag: args.trust,
88
+ profileTrust: profile?.trustProject,
89
+ interactive,
90
+ prompt: deps.ui?.promptTrust,
91
+ }));
92
+ // 9. 项目级配置(只能收紧)+ 命令行
93
+ const merged = await step(ExitCode.Config, "项目配置", () => {
94
+ const project = loadConfigFile("config", projectFile(sessionCwd, CONFIG_FILE));
95
+ if (project !== undefined)
96
+ warnings.push(...project.warnings);
97
+ return mergeProjectAndCli(base, project?.value, {
98
+ thinkingLevel: args.thinking,
99
+ permissionMode: args.permissionMode,
100
+ allow: args.allow,
101
+ deny: args.deny,
102
+ quietStartup: args.quietStartup,
103
+ tuiMode: args.tuiMode,
104
+ toolsPreset: args.toolsPreset,
105
+ codemode: args.codemode,
106
+ });
107
+ });
108
+ warnings.push(...merged.warnings);
109
+ const config = merged.config;
110
+ // 10. 资源发现
111
+ const context = findContextFiles({ cwd: sessionCwd, configDir: paths.configDir });
112
+ warnings.push(...context.warnings);
113
+ const discovered = deps.resources === undefined
114
+ ? { skills: [], prompts: [], warnings: [] }
115
+ : await step(ExitCode.Config, "Skill 发现", () => deps.resources?.discover({
116
+ cwd: sessionCwd,
117
+ configDir: paths.configDir,
118
+ trusted: trust.trusted,
119
+ extraSkillDirs: [...args.skillDirs, ...(config.skills?.dirs ?? [])],
120
+ promptDirs: profile?.promptDirs ?? [],
121
+ }) ?? { skills: [], prompts: [], warnings: [] });
122
+ warnings.push(...discovered.warnings);
123
+ const hookConfig = await step(ExitCode.Config, "hooks.json", () => loadHookConfigs({
124
+ configDir: paths.configDir,
125
+ cwd: sessionCwd,
126
+ profileHooksFile: profile?.hooksFile,
127
+ trusted: trust.trusted,
128
+ defaultTimeoutMs: config.hooks?.timeoutMs,
129
+ }));
130
+ warnings.push(...hookConfig.warnings);
131
+ const instructions = instructionSources(args.instructions, io.cwd);
132
+ const resources = {
133
+ contextFiles: context.files.map((f) => ({ path: f.path, content: f.content })),
134
+ skills: discovered.skills,
135
+ prompts: discovered.prompts,
136
+ instructions,
137
+ };
138
+ // 11. 供应商与模型
139
+ const providers = await step(ExitCode.Config, "供应商", () => deps.providers.create({
140
+ config,
141
+ cwd: sessionCwd,
142
+ authFile: args.authFile !== undefined
143
+ ? resolve(io.cwd, args.authFile)
144
+ : defaultAuthFilePath(paths.configDir),
145
+ authEnv: profile?.authEnv ?? true,
146
+ ...(args.apiKey !== undefined && args.model !== undefined
147
+ ? {
148
+ cliApiKey: {
149
+ apiKey: args.apiKey,
150
+ modelRef: args.model,
151
+ ...(args.provider !== undefined ? { provider: args.provider } : {}),
152
+ },
153
+ }
154
+ : {}),
155
+ }));
156
+ const { model, provider } = await step(ExitCode.NoModel, "模型", () => resolveModel(args, providers, sessionManager, config.defaultModel, deps, interactive));
157
+ const thinkingLevel = thinkingOf(args, sessionManager, config.thinkingLevel);
158
+ // 12. 工具注册表
159
+ const tools = await step(ExitCode.RuntimeError, "工具", () => deps.tools.create({ config, cwd: sessionCwd, mode }));
160
+ for (const name of config.tools?.disabled ?? []) {
161
+ if (tools.get(name) === undefined)
162
+ warn(`config tools.disabled:未知工具 ${name},已忽略`);
163
+ else
164
+ tools.disable(name);
165
+ }
166
+ // 13. 宿主适配器
167
+ let session;
168
+ const events = new AgentEventBus((level, message, detail) => {
169
+ if (level === "warn" || level === "error")
170
+ warn(`${message}${detail instanceof Error ? `:${detail.message}` : ""}`);
171
+ });
172
+ const binding = createHostApi({
173
+ mode,
174
+ env: io.env,
175
+ session: {
176
+ id: () => session?.state.sessionId ?? sessionManager.id,
177
+ file: () => (session !== undefined ? session.state.sessionFile : sessionManager.file()),
178
+ cwd: () => session?.state.cwd ?? sessionCwd,
179
+ model: () => session?.state.model ?? { provider: model.provider, id: model.id },
180
+ },
181
+ tools,
182
+ bus: events,
183
+ sendUser: (text, origin) => {
184
+ if (session === undefined)
185
+ return Promise.reject(new AmaError("busy", "会话尚未就绪"));
186
+ return (deps.sendUser ?? defaultSendUser)(session, text, origin);
187
+ },
188
+ stderr: io.stderr,
189
+ });
190
+ let uiBroker;
191
+ const hostSpec = args.host;
192
+ let host;
193
+ if (hostSpec !== undefined) {
194
+ host = await step(ExitCode.HostOrHook, "宿主适配器", () => activateHost({ module: hostSpec, binding, cwd: io.cwd }));
195
+ }
196
+ let shutdown;
197
+ try {
198
+ applyToolFilters(args, tools);
199
+ // 14. 组装 AgentSession、session_start、SessionStart Hook
200
+ const unattended = mode === "print";
201
+ const builtinDeny = config.permission?.builtinDeny;
202
+ const permission = await step(ExitCode.Config, "权限", () => deps.permissions.create({
203
+ mode: config.permission?.mode ?? "default",
204
+ rules: merged.ruleSpecs,
205
+ unattended,
206
+ cwd: sessionCwd,
207
+ ...(builtinDeny !== undefined ? { builtinDeny } : {}),
208
+ }));
209
+ const hooks = new HookDispatcher({
210
+ hooks: hookConfig.hooks,
211
+ context: () => ({
212
+ sessionId: session?.state.sessionId ?? sessionManager.id,
213
+ ...((session?.state.sessionFile ?? sessionManager.file()) !== undefined
214
+ ? { sessionFile: (session?.state.sessionFile ?? sessionManager.file()) }
215
+ : {}),
216
+ cwd: session?.state.cwd ?? sessionCwd,
217
+ model: session?.state.model ?? { provider: model.provider, id: model.id },
218
+ permissionMode: session?.state.permissionMode ?? permission.mode,
219
+ depth: 0,
220
+ ...(host !== undefined ? { host: host.adapter.id } : {}),
221
+ }),
222
+ onExecuted: (r) => void events.emit("hook_executed", {
223
+ event: r.event,
224
+ command: r.command,
225
+ exitCode: r.exitCode,
226
+ durationMs: r.durationMs,
227
+ }),
228
+ onWarning: warn,
229
+ });
230
+ let sessionStartContext;
231
+ const source = sourceOf(sessionRequest, sessionManager);
232
+ const assembly = {
233
+ mode,
234
+ paths: runtimePaths,
235
+ config,
236
+ trust,
237
+ resources,
238
+ providers,
239
+ model,
240
+ provider,
241
+ thinkingLevel,
242
+ sessionManager,
243
+ source,
244
+ hooks,
245
+ permission,
246
+ tools,
247
+ events,
248
+ host: {
249
+ handle: host,
250
+ broker: binding.broker,
251
+ instructions: binding.instructions,
252
+ warmingDecider: binding.warmingDecider,
253
+ },
254
+ uiBroker: () => uiBroker,
255
+ onSessionReplaced: (next) => {
256
+ session = next;
257
+ },
258
+ sessionStartContext: () => sessionStartContext,
259
+ unattended,
260
+ warn,
261
+ };
262
+ session = await step(ExitCode.RuntimeError, "会话组装", () => deps.session.create(assembly));
263
+ const active = session;
264
+ let disposed;
265
+ shutdown = (reason) => {
266
+ disposed ??= (async () => {
267
+ await events.emit("session_shutdown", {});
268
+ await hooks.run("SessionEnd", { reason }).catch(() => undefined);
269
+ await disposeHost(host, (e) => warn(`宿主适配器 dispose 失败:${String(e)}`));
270
+ // 会话被替换过时 dispose 当前那个(旧会话由替换方负责)
271
+ await (session ?? active).dispose();
272
+ })();
273
+ return disposed;
274
+ };
275
+ await events.emit("session_start", {
276
+ sessionId: active.state.sessionId,
277
+ ...(active.state.sessionFile !== undefined ? { sessionFile: active.state.sessionFile } : {}),
278
+ cwd: active.state.cwd,
279
+ reason: source,
280
+ });
281
+ const outcome = await hooks.run("SessionStart", { source });
282
+ if (outcome.decision === "block") {
283
+ throw new StartupError("hook_failed", `SessionStart Hook 阻止启动:${outcome.reason ?? "(无原因)"}`, ExitCode.HostOrHook);
284
+ }
285
+ sessionStartContext = outcome.additionalContext;
286
+ const finalShutdown = shutdown;
287
+ return {
288
+ mode,
289
+ paths: runtimePaths,
290
+ config,
291
+ trust,
292
+ resources,
293
+ providers,
294
+ model,
295
+ thinkingLevel,
296
+ sessionManager,
297
+ session: active,
298
+ hooks,
299
+ host,
300
+ permission,
301
+ tools,
302
+ approvals: {
303
+ setUiBroker: (broker) => {
304
+ uiBroker = broker;
305
+ },
306
+ },
307
+ notifier: { set: (fn) => binding.setNotify(fn) },
308
+ warnings,
309
+ dispose: (reason = "exit") => finalShutdown(reason),
310
+ };
311
+ }
312
+ catch (error) {
313
+ if (shutdown !== undefined)
314
+ await shutdown("exit").catch(() => undefined);
315
+ else
316
+ await disposeHost(host);
317
+ throw toStartupError(error, ExitCode.RuntimeError, "启动");
318
+ }
319
+ }
320
+ /** 非交互模式接管 stdout:console.log / info / debug 改写到 stderr;返回还原函数。 */
321
+ export function takeOverStdout() {
322
+ const saved = { log: console.log, info: console.info, debug: console.debug };
323
+ console.log = console.info = console.debug = (...items) => console.error(...items);
324
+ return () => {
325
+ console.log = saved.log;
326
+ console.info = saved.info;
327
+ console.debug = saved.debug;
328
+ };
329
+ }
330
+ export function isTerminalInitError(error) {
331
+ return isAmaError(error) && error.code === "terminal_init_failed";
332
+ }
333
+ /** 第 2–16 步:参数 → bootstrap → 模式;返回退出码(不含子命令)。 */
334
+ export async function runCli(argv, deps, io) {
335
+ let args;
336
+ try {
337
+ const parsed = parseArgs(argv);
338
+ if (parsed.kind !== "run")
339
+ throw new UsageError("子命令应由 main 分派");
340
+ args = parsed.args;
341
+ }
342
+ catch (error) {
343
+ return reportError(error, io);
344
+ }
345
+ if (args.help) {
346
+ io.stdout(HELP_TEXT);
347
+ return ExitCode.Ok;
348
+ }
349
+ if (deps === undefined) {
350
+ io.stderr("ama: 运行时尚未装配(集成批次通过 registerRuntimeDeps 注入实现)\n");
351
+ return ExitCode.RuntimeError;
352
+ }
353
+ let runtime;
354
+ try {
355
+ runtime = await bootstrap(args, deps, io);
356
+ }
357
+ catch (error) {
358
+ return reportError(error, io);
359
+ }
360
+ const restore = runtime.mode === "print" || runtime.mode === "rpc" ? takeOverStdout() : () => undefined;
361
+ try {
362
+ if (runtime.mode !== "interactive")
363
+ for (const w of runtime.warnings)
364
+ io.stderr(`ama: 警告:${w}\n`);
365
+ const context = { args, prompt: args.prompt, io };
366
+ const runner = deps.modes[runtime.mode];
367
+ if (runner === undefined)
368
+ throw new AmaError("not_implemented", `模式 ${runtime.mode} 尚未装配`, { exitCode: 1 });
369
+ try {
370
+ return await runner(runtime, context);
371
+ }
372
+ catch (error) {
373
+ const line = deps.modes.line;
374
+ if (runtime.mode !== "interactive" || !isTerminalInitError(error) || line === undefined)
375
+ throw error;
376
+ io.stderr(`ama: 警告:终端初始化失败,降级为行式界面(${error.message})\n`);
377
+ return await line(runtime, context);
378
+ }
379
+ }
380
+ catch (error) {
381
+ return reportError(error, io, ExitCode.RuntimeError);
382
+ }
383
+ finally {
384
+ await runtime.dispose("exit").catch(() => undefined);
385
+ restore();
386
+ }
387
+ }
388
+ export function reportError(error, io, fallback = ExitCode.RuntimeError) {
389
+ if (error instanceof UsageError) {
390
+ io.stderr(`ama: ${error.message}\n(ama --help 查看用法)\n`);
391
+ return ExitCode.Usage;
392
+ }
393
+ const message = error instanceof Error ? error.message : String(error);
394
+ io.stderr(`ama: ${message}\n`);
395
+ if (isAmaError(error) && error.exitCode !== undefined)
396
+ return error.exitCode;
397
+ return fallback;
398
+ }
@@ -0,0 +1,37 @@
1
+ /**
2
+ * 组装根:供应商注册表(实施计划 §1.1 `providers.create`)。[B6]
3
+ *
4
+ * - `ProviderBuildInput` → `ProviderRegistry`:auth.json(`--auth-file` 或用户级缺省,已由 bootstrap
5
+ * 解析成一个路径,所以 `userAuthFile: null`)、环境变量开关、`--api-key` 只作用于 `--model` 所属的
6
+ * 供应商(无斜杠的模型名先用一个不带 cli key 的注册表解析出供应商)。
7
+ * - `OPENAI_BASE_URL` / `ANTHROPIC_BASE_URL`(第三波 §2.3):与 key 同一份 `env`、同一个 `authEnv`
8
+ * 开关进注册表,内置 openai / anthropic 指向中转站;profile.authEnv=false 时一并不读。
9
+ * - SDK 追加的供应商(`ProviderData[]`)折成 `config.providers` 条目,走同一条合并路径。
10
+ * - 零配置(设计 §10.0):没有 `defaultModel`、也没有任何需要 key 的供应商配了 key 时,探测本地
11
+ * ollama / lmstudio(短超时),把枚举到的模型加进注册表,供 `pickDefaultModel` 选用。
12
+ */
13
+ import type { ApiRegistry } from "../ai/apis/api.js";
14
+ import { ProviderRegistry } from "../ai/providers/registry.js";
15
+ import type { ProviderData } from "../ai/types.js";
16
+ import type { AmaConfig, ProviderConfig } from "../config/types.js";
17
+ import type { ProviderBuildInput } from "./deps.js";
18
+ export declare const LOCAL_PROBE_TIMEOUT_MS = 300;
19
+ export declare const NO_LOCAL_PROBE_ENV = "AMA_NO_LOCAL_PROBE";
20
+ export interface ProviderComposeOptions {
21
+ /** 追加 / 覆盖的供应商(SDK)。 */
22
+ providers?: readonly ProviderData[] | undefined;
23
+ apis?: ApiRegistry | undefined;
24
+ /** key 发现用的环境(缺省 process.env)。 */
25
+ env?: NodeJS.ProcessEnv | undefined;
26
+ /** 注册 fake 供应商(缺省 true:测试与 `--model fake/echo` 依赖)。 */
27
+ includeFake?: boolean | undefined;
28
+ /** 零配置时探测本地服务(缺省 true;`AMA_NO_LOCAL_PROBE=1` 关闭)。 */
29
+ probeLocal?: boolean | undefined;
30
+ probeTimeoutMs?: number | undefined;
31
+ warn?: ((message: string) => void) | undefined;
32
+ }
33
+ export declare function providerConfigOf(provider: ProviderData): ProviderConfig;
34
+ export declare function withExtraProviders(config: AmaConfig, providers: readonly ProviderData[] | undefined): AmaConfig;
35
+ export declare function buildProviderRegistry(input: ProviderBuildInput, options?: ProviderComposeOptions): Promise<ProviderRegistry>;
36
+ /** 本地服务(无需 key、模型表为空)的模型枚举;连不上静默跳过。 */
37
+ export declare function probeLocalProviders(registry: ProviderRegistry, timeoutMs?: number): Promise<string[]>;
@@ -0,0 +1,104 @@
1
+ /**
2
+ * 组装根:供应商注册表(实施计划 §1.1 `providers.create`)。[B6]
3
+ *
4
+ * - `ProviderBuildInput` → `ProviderRegistry`:auth.json(`--auth-file` 或用户级缺省,已由 bootstrap
5
+ * 解析成一个路径,所以 `userAuthFile: null`)、环境变量开关、`--api-key` 只作用于 `--model` 所属的
6
+ * 供应商(无斜杠的模型名先用一个不带 cli key 的注册表解析出供应商)。
7
+ * - `OPENAI_BASE_URL` / `ANTHROPIC_BASE_URL`(第三波 §2.3):与 key 同一份 `env`、同一个 `authEnv`
8
+ * 开关进注册表,内置 openai / anthropic 指向中转站;profile.authEnv=false 时一并不读。
9
+ * - SDK 追加的供应商(`ProviderData[]`)折成 `config.providers` 条目,走同一条合并路径。
10
+ * - 零配置(设计 §10.0):没有 `defaultModel`、也没有任何需要 key 的供应商配了 key 时,探测本地
11
+ * ollama / lmstudio(短超时),把枚举到的模型加进注册表,供 `pickDefaultModel` 选用。
12
+ */
13
+ import { ProviderRegistry, discoverLocalModels } from "../ai/providers/registry.js";
14
+ export const LOCAL_PROBE_TIMEOUT_MS = 300;
15
+ export const NO_LOCAL_PROBE_ENV = "AMA_NO_LOCAL_PROBE";
16
+ /** 模型协议与供应商不同时保留模型级 `api`(同一中转下的模型可走不同协议)。 */
17
+ function modelConfigOf(model, providerApi) {
18
+ const { provider: _p, api, ...rest } = model;
19
+ return api !== providerApi ? { ...rest, api } : rest;
20
+ }
21
+ export function providerConfigOf(provider) {
22
+ const config = {
23
+ name: provider.name,
24
+ api: provider.api,
25
+ baseUrl: provider.baseUrl,
26
+ envKeys: [...provider.envKeys],
27
+ requiresApiKey: provider.requiresApiKey,
28
+ models: provider.models.map((model) => modelConfigOf(model, provider.api)),
29
+ };
30
+ if (provider.authHeader !== undefined)
31
+ config.authHeader = provider.authHeader;
32
+ if (provider.headers !== undefined)
33
+ config.headers = { ...provider.headers };
34
+ if (provider.compat !== undefined)
35
+ config.compat = { ...provider.compat };
36
+ return config;
37
+ }
38
+ export function withExtraProviders(config, providers) {
39
+ if (providers === undefined || providers.length === 0)
40
+ return config;
41
+ const merged = { ...(config.providers ?? {}) };
42
+ for (const provider of providers)
43
+ merged[provider.id] = providerConfigOf(provider);
44
+ return { ...config, providers: merged };
45
+ }
46
+ export async function buildProviderRegistry(input, options = {}) {
47
+ const config = withExtraProviders(input.config, options.providers);
48
+ const make = (cliApiKey) => new ProviderRegistry({
49
+ config,
50
+ apis: options.apis,
51
+ includeFake: options.includeFake ?? true,
52
+ keys: {
53
+ cliApiKey,
54
+ authFile: input.authFile,
55
+ userAuthFile: null,
56
+ useEnv: input.authEnv,
57
+ env: options.env,
58
+ },
59
+ onWarning: options.warn,
60
+ });
61
+ let registry = make();
62
+ const cli = input.cliApiKey;
63
+ if (cli !== undefined) {
64
+ let provider = cli.provider;
65
+ if (provider === undefined) {
66
+ const found = registry.findModel(cli.modelRef);
67
+ if (found.ok)
68
+ provider = found.provider.id;
69
+ }
70
+ if (provider !== undefined)
71
+ registry = make({ provider, apiKey: cli.apiKey });
72
+ }
73
+ const env = options.env ?? process.env;
74
+ const probe = options.probeLocal ?? env[NO_LOCAL_PROBE_ENV] !== "1";
75
+ if (probe && config.defaultModel === undefined && !anyKeyConfigured(registry)) {
76
+ await probeLocalProviders(registry, options.probeTimeoutMs ?? LOCAL_PROBE_TIMEOUT_MS);
77
+ }
78
+ return registry;
79
+ }
80
+ function anyKeyConfigured(registry) {
81
+ return registry
82
+ .list()
83
+ .some((provider) => provider.requiresApiKey && registry.hasConfiguredKey(provider.id));
84
+ }
85
+ /** 本地服务(无需 key、模型表为空)的模型枚举;连不上静默跳过。 */
86
+ export async function probeLocalProviders(registry, timeoutMs = LOCAL_PROBE_TIMEOUT_MS) {
87
+ const local = registry
88
+ .list()
89
+ .filter((p) => !p.requiresApiKey && p.id !== "fake" && p.models.length === 0);
90
+ const found = [];
91
+ await Promise.all(local.map(async (provider) => {
92
+ try {
93
+ const models = await discoverLocalModels(provider, { timeoutMs });
94
+ if (models.length === 0)
95
+ return;
96
+ registry.addModels(provider.id, models);
97
+ found.push(provider.id);
98
+ }
99
+ catch {
100
+ // 本地服务未运行:不是错误
101
+ }
102
+ }));
103
+ return found;
104
+ }
@@ -0,0 +1,69 @@
1
+ /**
2
+ * 组装根:`SessionAssembly` → `AgentSessionImpl`(实施计划 §1.2、§1.4)。[B6]
3
+ *
4
+ * - 审批:一个 `ApprovalBrokerChain`(串行队列)作 B2 `brokers` 的唯一元素;链首代理宿主 broker
5
+ * (`assembly.host.broker()` 每次现取,宿主可在任意时刻 `setBroker`),链尾代理模式层经
6
+ * `Runtime.approvals.setUiBroker` 晚绑定的 UI broker。子 Agent 的请求由 B2 包上 `context.depth`
7
+ * 后进同一条链,排在父对话框之后。
8
+ * - 系统提示:AGENTS.md + `--instructions` 文件(project_context 节)、Skill 索引(read 读取)、
9
+ * 宿主 instructions(host 节,读成文本)。SessionStart Hook 的 additionalContext 与宿主后加的
10
+ * 指令在每次提示展开前 `updateSystem`——值不变时不产生补丁,前缀保持逐字节稳定(§9.1)。
11
+ * - 事件:`SessionEvent` 桥接到宿主 `AgentEventBus`(§1.4 表;hook_executed、session_start /
12
+ * session_shutdown 由 bootstrap 发,不桥接);第三波加 `cache_miss` / `context_pressure`。
13
+ * - 缓存(第三波 §1.12):config `cache` 段(项目级已在合并时忽略)+ `AMA_CACHE_WARMING` /
14
+ * `AMA_CACHE_RETENTION` 覆盖 → 会话的 `cache` 设置;宿主 `cache.onWarmingDecision` 每次现取。
15
+ * - 会话切换:`switchSession()` 复用同一份装配材料建新会话,`assembly.onSessionReplaced(next)`
16
+ * 让宿主访问、Hook 公共字段与退出 dispose 跟随新会话。
17
+ */
18
+ import { AgentSessionImpl } from "../agent/session.js";
19
+ import type { AgentSession, CacheSettings, SessionEvent } from "../agent/types.js";
20
+ import { type AmaConfig } from "../config/types.js";
21
+ import type { AgentEventBus } from "../host/api-impl.js";
22
+ import type { Skill } from "../skills/discover.js";
23
+ import { type PromptTemplate } from "../skills/templates.js";
24
+ import type { SessionAssembly } from "./deps.js";
25
+ import type { Runtime } from "./runtime.js";
26
+ /** createRuntimeDeps 闭包里跨步骤共享的状态。 */
27
+ export interface ComposeState {
28
+ /** 第 10 步发现的完整 Skill(`/skill:` 展开与索引用)。 */
29
+ skills: Skill[];
30
+ templates: PromptTemplate[];
31
+ /** 没有 warn 通道的步骤(tools.create 等)留下的 warning,组装会话时交给 assembly.warn。 */
32
+ warnings: string[];
33
+ /** 当前会话(工具工厂的 `session()`)。 */
34
+ session: AgentSession | undefined;
35
+ }
36
+ export declare function emptyComposeState(): ComposeState;
37
+ export type LogFn = (level: "debug" | "info" | "warn" | "error", message: string) => void;
38
+ export interface SessionComposeOptions {
39
+ /** 审批超时(缺省 10 分钟);`AMA_APPROVAL_TIMEOUT_MS` 覆盖。 */
40
+ approvalTimeoutMs?: number | undefined;
41
+ log?: LogFn | undefined;
42
+ }
43
+ /** `AMA_LOG=debug|info|warn|error`(缺省 warn)过滤后写 stderr。 */
44
+ export declare function stderrLog(env?: NodeJS.ProcessEnv): LogFn;
45
+ /** config `cache` 段 + 环境变量 → 会话缓存设置;非法的环境变量值忽略并 warning。 */
46
+ export declare function cacheSettingsFrom(config: Pick<AmaConfig, "cache">, env?: NodeJS.ProcessEnv, warn?: (message: string) => void): Partial<CacheSettings>;
47
+ /** §1.4:SessionEvent → AgentEvents。 */
48
+ export declare function bridgeEvent(event: SessionEvent, bus: AgentEventBus): void;
49
+ /** 第 14 步:组装主会话。 */
50
+ export declare function composeSession(assembly: SessionAssembly, state?: ComposeState, options?: SessionComposeOptions): AgentSessionImpl;
51
+ /** 模式层当前应操作的会话(`switchSession` 之后不再是 `Runtime.session`)。 */
52
+ export declare function currentSession(target: Runtime | AgentSession): AgentSession;
53
+ export type SwitchRequest = {
54
+ kind: "new";
55
+ } | {
56
+ kind: "open";
57
+ file: string;
58
+ } | {
59
+ kind: "resume";
60
+ id: string;
61
+ } | {
62
+ kind: "fork";
63
+ entryId: string;
64
+ };
65
+ /**
66
+ * `/new`、`/resume`、`/fork`、RPC `new_session / switch_session / fork`:旧会话发 SessionEnd 后
67
+ * dispose,新会话复用装配材料,宿主总线发 session_start,再跑 SessionStart Hook。
68
+ */
69
+ export declare function switchSession(target: Runtime | AgentSession, request: SwitchRequest): Promise<AgentSessionImpl>;