@armadra/agent 0.0.0-stage → 0.3.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 (433) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/LICENSE +21 -0
  3. package/README.md +470 -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 +514 -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 +119 -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 +111 -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 +485 -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 +304 -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 +103 -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/channels.d.ts +51 -0
  101. package/dist/ai/providers/channels.js +96 -0
  102. package/dist/ai/providers/enrich.d.ts +34 -0
  103. package/dist/ai/providers/enrich.js +86 -0
  104. package/dist/ai/providers/models-dev-cache.d.ts +53 -0
  105. package/dist/ai/providers/models-dev-cache.js +147 -0
  106. package/dist/ai/providers/models-dev.d.ts +99 -0
  107. package/dist/ai/providers/models-dev.js +315 -0
  108. package/dist/ai/providers/registry.d.ts +114 -0
  109. package/dist/ai/providers/registry.js +458 -0
  110. package/dist/ai/sse.d.ts +32 -0
  111. package/dist/ai/sse.js +140 -0
  112. package/dist/ai/thinking.d.ts +42 -0
  113. package/dist/ai/thinking.js +101 -0
  114. package/dist/ai/types.d.ts +448 -0
  115. package/dist/ai/types.js +19 -0
  116. package/dist/bundle/ama-sandbox.cjs +324 -0
  117. package/dist/bundle/ama.cjs +27837 -0
  118. package/dist/bundle.d.ts +9 -0
  119. package/dist/bundle.js +15 -0
  120. package/dist/cli/args.d.ts +85 -0
  121. package/dist/cli/args.js +408 -0
  122. package/dist/cli/bootstrap.d.ts +18 -0
  123. package/dist/cli/bootstrap.js +399 -0
  124. package/dist/cli/compose-providers.d.ts +37 -0
  125. package/dist/cli/compose-providers.js +107 -0
  126. package/dist/cli/compose-session.d.ts +72 -0
  127. package/dist/cli/compose-session.js +370 -0
  128. package/dist/cli/compose-store.d.ts +24 -0
  129. package/dist/cli/compose-store.js +125 -0
  130. package/dist/cli/compose.d.ts +108 -0
  131. package/dist/cli/compose.js +221 -0
  132. package/dist/cli/default-model.d.ts +16 -0
  133. package/dist/cli/default-model.js +24 -0
  134. package/dist/cli/deps.d.ts +207 -0
  135. package/dist/cli/deps.js +12 -0
  136. package/dist/cli/exit-codes.d.ts +29 -0
  137. package/dist/cli/exit-codes.js +40 -0
  138. package/dist/cli/main.d.ts +27 -0
  139. package/dist/cli/main.js +177 -0
  140. package/dist/cli/runtime.d.ts +90 -0
  141. package/dist/cli/runtime.js +8 -0
  142. package/dist/cli/startup-screen.d.ts +15 -0
  143. package/dist/cli/startup-screen.js +56 -0
  144. package/dist/cli/startup-steps.d.ts +35 -0
  145. package/dist/cli/startup-steps.js +202 -0
  146. package/dist/cli/subcommands/auth.d.ts +12 -0
  147. package/dist/cli/subcommands/auth.js +91 -0
  148. package/dist/cli/subcommands/config.d.ts +53 -0
  149. package/dist/cli/subcommands/config.js +277 -0
  150. package/dist/cli/subcommands/context.d.ts +21 -0
  151. package/dist/cli/subcommands/context.js +42 -0
  152. package/dist/cli/subcommands/doctor.d.ts +11 -0
  153. package/dist/cli/subcommands/doctor.js +246 -0
  154. package/dist/cli/subcommands/init.d.ts +6 -0
  155. package/dist/cli/subcommands/init.js +22 -0
  156. package/dist/cli/subcommands/model-meta.d.ts +16 -0
  157. package/dist/cli/subcommands/model-meta.js +54 -0
  158. package/dist/cli/subcommands/models-cache-probe.d.ts +34 -0
  159. package/dist/cli/subcommands/models-cache-probe.js +190 -0
  160. package/dist/cli/subcommands/models-discover.d.ts +46 -0
  161. package/dist/cli/subcommands/models-discover.js +232 -0
  162. package/dist/cli/subcommands/models.d.ts +40 -0
  163. package/dist/cli/subcommands/models.js +152 -0
  164. package/dist/cli/subcommands/providers-list.d.ts +8 -0
  165. package/dist/cli/subcommands/providers-list.js +97 -0
  166. package/dist/cli/subcommands/providers-plan.d.ts +79 -0
  167. package/dist/cli/subcommands/providers-plan.js +215 -0
  168. package/dist/cli/subcommands/providers.d.ts +27 -0
  169. package/dist/cli/subcommands/providers.js +433 -0
  170. package/dist/cli/subcommands/sessions.d.ts +11 -0
  171. package/dist/cli/subcommands/sessions.js +100 -0
  172. package/dist/codemode/capability.d.ts +37 -0
  173. package/dist/codemode/capability.js +55 -0
  174. package/dist/codemode/declarations.d.ts +44 -0
  175. package/dist/codemode/declarations.js +111 -0
  176. package/dist/codemode/host-side.d.ts +59 -0
  177. package/dist/codemode/host-side.js +253 -0
  178. package/dist/codemode/modes.d.ts +23 -0
  179. package/dist/codemode/modes.js +40 -0
  180. package/dist/codemode/protocol.d.ts +91 -0
  181. package/dist/codemode/protocol.js +114 -0
  182. package/dist/codemode/sandbox-entry.d.ts +25 -0
  183. package/dist/codemode/sandbox-entry.js +323 -0
  184. package/dist/codemode/store.d.ts +26 -0
  185. package/dist/codemode/store.js +53 -0
  186. package/dist/codemode/tool.d.ts +105 -0
  187. package/dist/codemode/tool.js +283 -0
  188. package/dist/compaction/branch-summary.d.ts +30 -0
  189. package/dist/compaction/branch-summary.js +79 -0
  190. package/dist/compaction/breaker.d.ts +32 -0
  191. package/dist/compaction/breaker.js +65 -0
  192. package/dist/compaction/cut-point.d.ts +23 -0
  193. package/dist/compaction/cut-point.js +70 -0
  194. package/dist/compaction/estimate.d.ts +30 -0
  195. package/dist/compaction/estimate.js +114 -0
  196. package/dist/compaction/prune-tier.d.ts +31 -0
  197. package/dist/compaction/prune-tier.js +83 -0
  198. package/dist/compaction/serialize.d.ts +20 -0
  199. package/dist/compaction/serialize.js +115 -0
  200. package/dist/compaction/summarize-tier.d.ts +111 -0
  201. package/dist/compaction/summarize-tier.js +305 -0
  202. package/dist/config/auth-file.d.ts +39 -0
  203. package/dist/config/auth-file.js +92 -0
  204. package/dist/config/context-files.d.ts +30 -0
  205. package/dist/config/context-files.js +77 -0
  206. package/dist/config/init.d.ts +30 -0
  207. package/dist/config/init.js +92 -0
  208. package/dist/config/json-schema.d.ts +14 -0
  209. package/dist/config/json-schema.js +182 -0
  210. package/dist/config/load.d.ts +45 -0
  211. package/dist/config/load.js +97 -0
  212. package/dist/config/merge.d.ts +73 -0
  213. package/dist/config/merge.js +248 -0
  214. package/dist/config/paths.d.ts +38 -0
  215. package/dist/config/paths.js +108 -0
  216. package/dist/config/profile.d.ts +27 -0
  217. package/dist/config/profile.js +65 -0
  218. package/dist/config/schema.d.ts +34 -0
  219. package/dist/config/schema.js +476 -0
  220. package/dist/config/trust.d.ts +42 -0
  221. package/dist/config/trust.js +122 -0
  222. package/dist/config/types.d.ts +190 -0
  223. package/dist/config/types.js +29 -0
  224. package/dist/config/write.d.ts +10 -0
  225. package/dist/config/write.js +25 -0
  226. package/dist/errors.d.ts +28 -0
  227. package/dist/errors.js +30 -0
  228. package/dist/hooks/config.d.ts +49 -0
  229. package/dist/hooks/config.js +102 -0
  230. package/dist/hooks/dispatcher.d.ts +41 -0
  231. package/dist/hooks/dispatcher.js +104 -0
  232. package/dist/hooks/matcher.d.ts +22 -0
  233. package/dist/hooks/matcher.js +108 -0
  234. package/dist/hooks/protocol.d.ts +33 -0
  235. package/dist/hooks/protocol.js +240 -0
  236. package/dist/hooks/runner.d.ts +30 -0
  237. package/dist/hooks/runner.js +143 -0
  238. package/dist/hooks/types.d.ts +147 -0
  239. package/dist/hooks/types.js +20 -0
  240. package/dist/host/api-impl.d.ts +75 -0
  241. package/dist/host/api-impl.js +173 -0
  242. package/dist/host/loader.d.ts +31 -0
  243. package/dist/host/loader.js +147 -0
  244. package/dist/host/types.d.ts +169 -0
  245. package/dist/host/types.js +14 -0
  246. package/dist/host.d.ts +5 -0
  247. package/dist/host.js +4 -0
  248. package/dist/index.d.ts +41 -0
  249. package/dist/index.js +28 -0
  250. package/dist/modes/commands-core.d.ts +44 -0
  251. package/dist/modes/commands-core.js +171 -0
  252. package/dist/modes/image-input.d.ts +27 -0
  253. package/dist/modes/image-input.js +78 -0
  254. package/dist/modes/interactive/approval-dialog.d.ts +48 -0
  255. package/dist/modes/interactive/approval-dialog.js +202 -0
  256. package/dist/modes/interactive/commands.d.ts +41 -0
  257. package/dist/modes/interactive/commands.js +201 -0
  258. package/dist/modes/interactive/completion.d.ts +53 -0
  259. package/dist/modes/interactive/completion.js +157 -0
  260. package/dist/modes/interactive/interactive-mode.d.ts +46 -0
  261. package/dist/modes/interactive/interactive-mode.js +491 -0
  262. package/dist/modes/interactive/key-dispatch.d.ts +29 -0
  263. package/dist/modes/interactive/key-dispatch.js +107 -0
  264. package/dist/modes/interactive/line/line-editor.d.ts +50 -0
  265. package/dist/modes/interactive/line/line-editor.js +232 -0
  266. package/dist/modes/interactive/line/line-mode.d.ts +20 -0
  267. package/dist/modes/interactive/line/line-mode.js +218 -0
  268. package/dist/modes/interactive/line/line-render.d.ts +35 -0
  269. package/dist/modes/interactive/line/line-render.js +171 -0
  270. package/dist/modes/interactive/line/paste-state.d.ts +26 -0
  271. package/dist/modes/interactive/line/paste-state.js +72 -0
  272. package/dist/modes/interactive/message-view.d.ts +77 -0
  273. package/dist/modes/interactive/message-view.js +269 -0
  274. package/dist/modes/interactive/pickers.d.ts +42 -0
  275. package/dist/modes/interactive/pickers.js +115 -0
  276. package/dist/modes/interactive/startup-ui.d.ts +33 -0
  277. package/dist/modes/interactive/startup-ui.js +268 -0
  278. package/dist/modes/interactive/status-bar.d.ts +48 -0
  279. package/dist/modes/interactive/status-bar.js +139 -0
  280. package/dist/modes/interactive/tool-view.d.ts +95 -0
  281. package/dist/modes/interactive/tool-view.js +344 -0
  282. package/dist/modes/print/json-event.d.ts +15 -0
  283. package/dist/modes/print/json-event.js +39 -0
  284. package/dist/modes/print/print-mode.d.ts +17 -0
  285. package/dist/modes/print/print-mode.js +107 -0
  286. package/dist/modes/rpc/commands.d.ts +40 -0
  287. package/dist/modes/rpc/commands.js +263 -0
  288. package/dist/modes/rpc/jsonl.d.ts +16 -0
  289. package/dist/modes/rpc/jsonl.js +55 -0
  290. package/dist/modes/rpc/rpc-mode.d.ts +22 -0
  291. package/dist/modes/rpc/rpc-mode.js +153 -0
  292. package/dist/modes/session-report.d.ts +55 -0
  293. package/dist/modes/session-report.js +278 -0
  294. package/dist/modes/shared.d.ts +13 -0
  295. package/dist/modes/shared.js +52 -0
  296. package/dist/modes/startup-ui-text.d.ts +16 -0
  297. package/dist/modes/startup-ui-text.js +103 -0
  298. package/dist/permissions/broker.d.ts +47 -0
  299. package/dist/permissions/broker.js +107 -0
  300. package/dist/permissions/dangerous.d.ts +47 -0
  301. package/dist/permissions/dangerous.js +370 -0
  302. package/dist/permissions/pipeline.d.ts +51 -0
  303. package/dist/permissions/pipeline.js +181 -0
  304. package/dist/permissions/preview.d.ts +43 -0
  305. package/dist/permissions/preview.js +463 -0
  306. package/dist/permissions/rules.d.ts +58 -0
  307. package/dist/permissions/rules.js +249 -0
  308. package/dist/permissions/types.d.ts +100 -0
  309. package/dist/permissions/types.js +18 -0
  310. package/dist/rpc.d.ts +173 -0
  311. package/dist/rpc.js +13 -0
  312. package/dist/sdk.d.ts +98 -0
  313. package/dist/sdk.js +195 -0
  314. package/dist/session/manager.d.ts +70 -0
  315. package/dist/session/manager.js +278 -0
  316. package/dist/session/migrate.d.ts +19 -0
  317. package/dist/session/migrate.js +53 -0
  318. package/dist/session/projection.d.ts +50 -0
  319. package/dist/session/projection.js +184 -0
  320. package/dist/session/store.d.ts +47 -0
  321. package/dist/session/store.js +210 -0
  322. package/dist/session/tree.d.ts +21 -0
  323. package/dist/session/tree.js +88 -0
  324. package/dist/session/types.d.ts +201 -0
  325. package/dist/session/types.js +18 -0
  326. package/dist/skills/discover.d.ts +60 -0
  327. package/dist/skills/discover.js +160 -0
  328. package/dist/skills/expand.d.ts +35 -0
  329. package/dist/skills/expand.js +46 -0
  330. package/dist/skills/frontmatter.d.ts +27 -0
  331. package/dist/skills/frontmatter.js +157 -0
  332. package/dist/skills/index-prompt.d.ts +13 -0
  333. package/dist/skills/index-prompt.js +42 -0
  334. package/dist/skills/templates.d.ts +52 -0
  335. package/dist/skills/templates.js +177 -0
  336. package/dist/tools/bash.d.ts +49 -0
  337. package/dist/tools/bash.js +222 -0
  338. package/dist/tools/edit-fuzzy.d.ts +36 -0
  339. package/dist/tools/edit-fuzzy.js +129 -0
  340. package/dist/tools/edit.d.ts +38 -0
  341. package/dist/tools/edit.js +241 -0
  342. package/dist/tools/file-mutex.d.ts +8 -0
  343. package/dist/tools/file-mutex.js +29 -0
  344. package/dist/tools/glob.d.ts +44 -0
  345. package/dist/tools/glob.js +217 -0
  346. package/dist/tools/grep.d.ts +39 -0
  347. package/dist/tools/grep.js +179 -0
  348. package/dist/tools/ignore.d.ts +40 -0
  349. package/dist/tools/ignore.js +174 -0
  350. package/dist/tools/image-file.d.ts +31 -0
  351. package/dist/tools/image-file.js +114 -0
  352. package/dist/tools/ls.d.ts +21 -0
  353. package/dist/tools/ls.js +96 -0
  354. package/dist/tools/output-accumulator.d.ts +48 -0
  355. package/dist/tools/output-accumulator.js +106 -0
  356. package/dist/tools/paths.d.ts +20 -0
  357. package/dist/tools/paths.js +58 -0
  358. package/dist/tools/presets.d.ts +71 -0
  359. package/dist/tools/presets.js +128 -0
  360. package/dist/tools/process-tree.d.ts +35 -0
  361. package/dist/tools/process-tree.js +125 -0
  362. package/dist/tools/read.d.ts +24 -0
  363. package/dist/tools/read.js +132 -0
  364. package/dist/tools/registry.d.ts +43 -0
  365. package/dist/tools/registry.js +106 -0
  366. package/dist/tools/shell.d.ts +38 -0
  367. package/dist/tools/shell.js +91 -0
  368. package/dist/tools/task.d.ts +29 -0
  369. package/dist/tools/task.js +107 -0
  370. package/dist/tools/todo.d.ts +28 -0
  371. package/dist/tools/todo.js +107 -0
  372. package/dist/tools/truncate.d.ts +44 -0
  373. package/dist/tools/truncate.js +175 -0
  374. package/dist/tools/types.d.ts +135 -0
  375. package/dist/tools/types.js +19 -0
  376. package/dist/tools/write.d.ts +20 -0
  377. package/dist/tools/write.js +84 -0
  378. package/dist/tui/ansi.d.ts +29 -0
  379. package/dist/tui/ansi.js +420 -0
  380. package/dist/tui/component.d.ts +38 -0
  381. package/dist/tui/component.js +13 -0
  382. package/dist/tui/components/box.d.ts +26 -0
  383. package/dist/tui/components/box.js +65 -0
  384. package/dist/tui/components/container.d.ts +14 -0
  385. package/dist/tui/components/container.js +39 -0
  386. package/dist/tui/components/editor-buffer.d.ts +67 -0
  387. package/dist/tui/components/editor-buffer.js +300 -0
  388. package/dist/tui/components/editor-paste.d.ts +29 -0
  389. package/dist/tui/components/editor-paste.js +64 -0
  390. package/dist/tui/components/editor.d.ts +114 -0
  391. package/dist/tui/components/editor.js +530 -0
  392. package/dist/tui/components/key-value.d.ts +29 -0
  393. package/dist/tui/components/key-value.js +48 -0
  394. package/dist/tui/components/loader.d.ts +35 -0
  395. package/dist/tui/components/loader.js +71 -0
  396. package/dist/tui/components/markdown.d.ts +90 -0
  397. package/dist/tui/components/markdown.js +462 -0
  398. package/dist/tui/components/meter.d.ts +29 -0
  399. package/dist/tui/components/meter.js +47 -0
  400. package/dist/tui/components/overlay.d.ts +24 -0
  401. package/dist/tui/components/overlay.js +52 -0
  402. package/dist/tui/components/select-list.d.ts +57 -0
  403. package/dist/tui/components/select-list.js +179 -0
  404. package/dist/tui/components/spacer.d.ts +11 -0
  405. package/dist/tui/components/spacer.js +16 -0
  406. package/dist/tui/components/text.d.ts +30 -0
  407. package/dist/tui/components/text.js +65 -0
  408. package/dist/tui/keybindings.d.ts +66 -0
  409. package/dist/tui/keybindings.js +120 -0
  410. package/dist/tui/keys.d.ts +38 -0
  411. package/dist/tui/keys.js +275 -0
  412. package/dist/tui/stdin-buffer.d.ts +41 -0
  413. package/dist/tui/stdin-buffer.js +206 -0
  414. package/dist/tui/terminal.d.ts +79 -0
  415. package/dist/tui/terminal.js +153 -0
  416. package/dist/tui/theme.d.ts +31 -0
  417. package/dist/tui/theme.js +199 -0
  418. package/dist/tui/tui.d.ts +103 -0
  419. package/dist/tui/tui.js +363 -0
  420. package/dist/tui/vt-screen.d.ts +46 -0
  421. package/dist/tui/vt-screen.js +251 -0
  422. package/dist/tui.d.ts +30 -0
  423. package/dist/tui.js +31 -0
  424. package/dist/version.d.ts +8 -0
  425. package/dist/version.js +24 -0
  426. package/docs/codemode.md +102 -0
  427. package/docs/hooks.md +196 -0
  428. package/docs/host-api.md +161 -0
  429. package/docs/providers.md +531 -0
  430. package/docs/rpc.md +253 -0
  431. package/docs/session-format.md +119 -0
  432. package/docs/tui.md +170 -0
  433. package/package.json +101 -4
@@ -0,0 +1,14 @@
1
+ /**
2
+ * config.json 的 JSON Schema(draft-07 子集),写到配置目录的 `config.schema.json` 给编辑器补全与校验
3
+ * (docs/providers.md「配置目录」)。规则与 schema.ts 的 `validateConfig` 一一对应:未知字段在那里是
4
+ * warning、这里是 `additionalProperties: false`;渠道引用(模型 `channels` 指向已定义的渠道)这类跨字段
5
+ * 规则 JSON Schema 表达不了,只在 `validateConfig` 里查。一致性由 json-schema.test.ts 的正反例守住。
6
+ */
7
+ type Schema = Record<string, unknown>;
8
+ export declare const CONFIG_SCHEMA_FILE = "config.schema.json";
9
+ export declare const CONFIG_SCHEMA_ID = "https://github.com/Owlbay/armadra-agent/config.schema.json";
10
+ /** 生成 config.json 的 JSON Schema。 */
11
+ export declare function buildConfigJsonSchema(): Schema;
12
+ /** 写进文件的文本(2 空格缩进 + 换行结尾)。 */
13
+ export declare function configSchemaText(): string;
14
+ export {};
@@ -0,0 +1,182 @@
1
+ /**
2
+ * config.json 的 JSON Schema(draft-07 子集),写到配置目录的 `config.schema.json` 给编辑器补全与校验
3
+ * (docs/providers.md「配置目录」)。规则与 schema.ts 的 `validateConfig` 一一对应:未知字段在那里是
4
+ * warning、这里是 `additionalProperties: false`;渠道引用(模型 `channels` 指向已定义的渠道)这类跨字段
5
+ * 规则 JSON Schema 表达不了,只在 `validateConfig` 里查。一致性由 json-schema.test.ts 的正反例守住。
6
+ */
7
+ import { WARMING_MODES } from "../ai/cache/types.js";
8
+ import { PERMISSION_MODES_STRICT_FIRST } from "../permissions/types.js";
9
+ import { HOOK_TIMEOUT_MAX_MS, THINKING_LEVELS } from "./schema.js";
10
+ import { CACHE_RETENTIONS, CHANNEL_NAME_PATTERN, CODEMODE_MODES, TOOLS_PRESETS_STRICT_FIRST, } from "./types.js";
11
+ export const CONFIG_SCHEMA_FILE = "config.schema.json";
12
+ export const CONFIG_SCHEMA_ID = "https://github.com/Owlbay/armadra-agent/config.schema.json";
13
+ const KNOWN_APIS = [
14
+ "openai-completions",
15
+ "openai-responses",
16
+ "anthropic-messages",
17
+ "google-generative-ai",
18
+ ];
19
+ function object(properties, extra = {}) {
20
+ return { type: "object", properties, additionalProperties: false, ...extra };
21
+ }
22
+ const str = (description) => ({
23
+ type: "string",
24
+ ...(description ? { description } : {}),
25
+ });
26
+ const bool = (description) => ({
27
+ type: "boolean",
28
+ ...(description ? { description } : {}),
29
+ });
30
+ const num = (minimum, maximum, description) => ({
31
+ type: "number",
32
+ ...(minimum !== undefined ? { minimum } : {}),
33
+ ...(maximum !== undefined ? { maximum } : {}),
34
+ ...(description ? { description } : {}),
35
+ });
36
+ const strings = { type: "array", items: { type: "string" } };
37
+ const stringRecord = { type: "object", additionalProperties: { type: "string" } };
38
+ const oneOf = (values, description) => ({
39
+ type: "string",
40
+ enum: [...values],
41
+ ...(description ? { description } : {}),
42
+ });
43
+ /** api 只查是字符串(与 validateConfig 一致),enum 给编辑器补全。 */
44
+ const api = {
45
+ type: "string",
46
+ description: "协议",
47
+ examples: KNOWN_APIS,
48
+ anyOf: [{ enum: KNOWN_APIS }, { type: "string" }],
49
+ };
50
+ const compat = {
51
+ type: "object",
52
+ description: "协议兼容开关(docs/providers.md「compat」)",
53
+ properties: {
54
+ sendPromptCacheKey: bool(),
55
+ sendSessionAffinityHeaders: bool(),
56
+ supportsLongCacheRetention: bool(),
57
+ supportsExplicitPromptCacheMode: bool(),
58
+ cacheReporting: oneOf(["auto", "silent", "reported"]),
59
+ },
60
+ };
61
+ function model(description) {
62
+ return {
63
+ type: "object",
64
+ description,
65
+ required: ["id"],
66
+ properties: {
67
+ id: str("模型 id(发给上游的名字)"),
68
+ name: str(),
69
+ api,
70
+ baseUrl: str("覆盖渠道 / 供应商的地址"),
71
+ contextWindow: num(1, undefined, "上下文 token;缺省从 models.dev 补,匹配不到不猜"),
72
+ maxTokens: num(1, undefined, "单次输出上限;缺省 min(models.dev, 64k) 或 8192"),
73
+ reasoning: bool(),
74
+ input: {
75
+ type: "array",
76
+ items: { enum: ["text", "image"] },
77
+ description: '["text"] 或 ["text", "image"](收图片)',
78
+ },
79
+ channels: { ...strings, description: "挂载的渠道,第一个是首选" },
80
+ modelsDev: {
81
+ description: 'models.dev 条目 "provider/model";false 关闭补全',
82
+ anyOf: [{ type: "string", pattern: "^[^/]+/.+$" }, { const: false }],
83
+ },
84
+ headers: stringRecord,
85
+ compat,
86
+ promptCache: object({ short: num(), long: num(), minTokens: num() }),
87
+ cost: { type: "object", description: "$/M token" },
88
+ thinkingLevelMap: { type: "object" },
89
+ samplingParams: { type: "object" },
90
+ },
91
+ };
92
+ }
93
+ const channel = object({
94
+ api,
95
+ baseUrl: str("接口地址"),
96
+ apiKey: str("$ENV / ${ENV} / !command / 字面量;缺省用供应商的 key"),
97
+ authHeader: { type: "object" },
98
+ headers: stringRecord,
99
+ compat,
100
+ }, { required: ["api", "baseUrl"] });
101
+ const provider = object({
102
+ name: str(),
103
+ api,
104
+ baseUrl: str(),
105
+ apiKey: str("$ENV / ${ENV} / !command / 字面量"),
106
+ envKeys: strings,
107
+ authHeader: { type: "object" },
108
+ headers: stringRecord,
109
+ compat,
110
+ requiresApiKey: bool(),
111
+ channels: {
112
+ type: "object",
113
+ description: "渠道:一个供应商下的多种接口",
114
+ minProperties: 1,
115
+ propertyNames: { pattern: CHANNEL_NAME_PATTERN.source },
116
+ additionalProperties: channel,
117
+ },
118
+ defaultChannel: str("首选渠道;缺省 channels 的第一个"),
119
+ models: { type: "array", items: model("自定义模型(同 id 整条替换)") },
120
+ modelOverrides: { type: "array", items: model("只改已有模型的元数据") },
121
+ });
122
+ /** 生成 config.json 的 JSON Schema。 */
123
+ export function buildConfigJsonSchema() {
124
+ return {
125
+ $schema: "http://json-schema.org/draft-07/schema#",
126
+ $id: CONFIG_SCHEMA_ID,
127
+ title: "ama config.json",
128
+ ...object({
129
+ $schema: str(),
130
+ version: { const: 1 },
131
+ defaultModel: str("provider/model 或 provider/model@channel"),
132
+ thinkingLevel: oneOf(THINKING_LEVELS),
133
+ providers: { type: "object", additionalProperties: provider },
134
+ permission: object({
135
+ mode: oneOf(PERMISSION_MODES_STRICT_FIRST),
136
+ allow: strings,
137
+ deny: strings,
138
+ builtinDeny: { anyOf: [{ type: "boolean" }, strings] },
139
+ }),
140
+ compaction: object({ enabled: bool(), reserveTokens: num(0), keepRecentTokens: num(0) }),
141
+ retry: object({
142
+ enabled: bool(),
143
+ maxRetries: num(0, 100),
144
+ baseDelayMs: num(0),
145
+ maxDelayMs: num(0),
146
+ }),
147
+ tools: object({
148
+ preset: oneOf(TOOLS_PRESETS_STRICT_FIRST),
149
+ default: strings,
150
+ maxToolResultChars: num(1),
151
+ bashTimeoutMs: num(1),
152
+ disabled: strings,
153
+ }),
154
+ codemode: object({
155
+ mode: oneOf(CODEMODE_MODES),
156
+ inlineBudget: num(0),
157
+ requireStrict: bool(),
158
+ }),
159
+ hooks: object({ timeoutMs: num(1, HOOK_TIMEOUT_MAX_MS) }),
160
+ ui: object({
161
+ theme: oneOf(["dark", "light"]),
162
+ markdown: bool(),
163
+ showThinking: oneOf(["full", "collapsed", "hidden"]),
164
+ tuiMode: oneOf(["regular"]),
165
+ quietStartup: oneOf(["normal", "header", "silent"]),
166
+ }),
167
+ skills: object({ dirs: strings }),
168
+ cache: object({
169
+ warming: oneOf(WARMING_MODES),
170
+ retention: oneOf(CACHE_RETENTIONS),
171
+ minSavingsUsd: num(0),
172
+ missNotices: bool(),
173
+ warmSubagents: bool(),
174
+ }),
175
+ }),
176
+ required: ["version"],
177
+ };
178
+ }
179
+ /** 写进文件的文本(2 空格缩进 + 换行结尾)。 */
180
+ export function configSchemaText() {
181
+ return `${JSON.stringify(buildConfigJsonSchema(), null, 2)}\n`;
182
+ }
@@ -0,0 +1,45 @@
1
+ /**
2
+ * 读配置文件 + 校验 + 诊断(设计 §11.1 第 6 / 9 / 10 步)。[B5]
3
+ *
4
+ * JSON 语法错误给出行列号;字段错误给出字段路径。任何 error 级诊断都抛
5
+ * `StartupError{exitCode: 3}`(code 依文件种类为 config_invalid / profile_invalid),
6
+ * warning 级诊断(未知字段)原样返回给调用方汇入 Runtime.warnings。
7
+ */
8
+ import { type Diagnostic } from "./schema.js";
9
+ import type { AmaConfig, AuthFile, ProfileFile, TrustFile } from "./types.js";
10
+ import type { HookConfig } from "../hooks/types.js";
11
+ export type ConfigFileKind = "config" | "auth" | "profile" | "hooks" | "trust";
12
+ interface KindMap {
13
+ config: AmaConfig;
14
+ auth: AuthFile;
15
+ profile: ProfileFile;
16
+ hooks: HookConfig;
17
+ trust: TrustFile;
18
+ }
19
+ export interface LoadedFile<T> {
20
+ path: string;
21
+ value: T;
22
+ /** 已格式化的 warning(`<path>: <field>: <message>`)。 */
23
+ warnings: string[];
24
+ }
25
+ /** 字符偏移 → 1 起的行列。 */
26
+ export declare function lineColumnAt(text: string, offset: number): {
27
+ line: number;
28
+ column: number;
29
+ };
30
+ /** 解析 JSON;语法错误抛带行列号的 Error。容忍 UTF-8 BOM。 */
31
+ export declare function parseJsonText(text: string): unknown;
32
+ export declare function formatDiagnostic(path: string, d: Diagnostic): string;
33
+ export interface ReadOptions {
34
+ /** 文件不存在时报错(缺省 false:返回 undefined)。 */
35
+ required?: boolean;
36
+ }
37
+ /** 读并校验一个配置文件;不存在且非必需时返回 undefined。 */
38
+ export declare function loadConfigFile<K extends ConfigFileKind>(kind: K, path: string, options?: ReadOptions): LoadedFile<KindMap[K]> | undefined;
39
+ /** 读失败不抛:返回诊断(doctor 用)。 */
40
+ export declare function probeConfigFile(kind: ConfigFileKind, path: string): {
41
+ exists: boolean;
42
+ ok: boolean;
43
+ messages: string[];
44
+ };
45
+ export {};
@@ -0,0 +1,97 @@
1
+ /**
2
+ * 读配置文件 + 校验 + 诊断(设计 §11.1 第 6 / 9 / 10 步)。[B5]
3
+ *
4
+ * JSON 语法错误给出行列号;字段错误给出字段路径。任何 error 级诊断都抛
5
+ * `StartupError{exitCode: 3}`(code 依文件种类为 config_invalid / profile_invalid),
6
+ * warning 级诊断(未知字段)原样返回给调用方汇入 Runtime.warnings。
7
+ */
8
+ import { readFileSync } from "node:fs";
9
+ import { StartupError } from "../errors.js";
10
+ import { hasErrors, validateAuthFile, validateConfig, validateHookConfig, validateProfile, validateTrustFile, } from "./schema.js";
11
+ const EXIT_CONFIG = 3;
12
+ const VALIDATORS = {
13
+ config: validateConfig,
14
+ auth: validateAuthFile,
15
+ profile: validateProfile,
16
+ hooks: validateHookConfig,
17
+ trust: validateTrustFile,
18
+ };
19
+ /** 字符偏移 → 1 起的行列。 */
20
+ export function lineColumnAt(text, offset) {
21
+ const before = text.slice(0, Math.max(0, Math.min(offset, text.length)));
22
+ const lines = before.split("\n");
23
+ return { line: lines.length, column: (lines[lines.length - 1]?.length ?? 0) + 1 };
24
+ }
25
+ /** 解析 JSON;语法错误抛带行列号的 Error。容忍 UTF-8 BOM。 */
26
+ export function parseJsonText(text) {
27
+ const source = text.charCodeAt(0) === 0xfeff ? text.slice(1) : text;
28
+ try {
29
+ return JSON.parse(source);
30
+ }
31
+ catch (error) {
32
+ const message = error instanceof Error ? error.message : String(error);
33
+ const lineCol = /line (\d+) column (\d+)/.exec(message);
34
+ if (lineCol !== null)
35
+ throw new Error(`JSON 语法错误(第 ${lineCol[1]} 行第 ${lineCol[2]} 列):${message}`);
36
+ const position = /position (\d+)/.exec(message);
37
+ if (position?.[1] !== undefined) {
38
+ const { line, column } = lineColumnAt(source, Number(position[1]));
39
+ throw new Error(`JSON 语法错误(第 ${line} 行第 ${column} 列):${message}`);
40
+ }
41
+ if (source.trim() === "")
42
+ throw new Error("JSON 语法错误:文件为空");
43
+ const end = lineColumnAt(source, source.length);
44
+ throw new Error(`JSON 语法错误(第 ${end.line} 行第 ${end.column} 列附近):${message}`);
45
+ }
46
+ }
47
+ export function formatDiagnostic(path, d) {
48
+ return `${path}: ${d.path === "" ? "" : `${d.path}: `}${d.message}`;
49
+ }
50
+ function failure(kind, message, detail) {
51
+ return new StartupError(kind === "profile" ? "profile_invalid" : "config_invalid", message, EXIT_CONFIG, detail === undefined ? {} : { detail });
52
+ }
53
+ /** 读并校验一个配置文件;不存在且非必需时返回 undefined。 */
54
+ export function loadConfigFile(kind, path, options = {}) {
55
+ let text;
56
+ try {
57
+ text = readFileSync(path, "utf8");
58
+ }
59
+ catch (error) {
60
+ const code = error.code;
61
+ if (code === "ENOENT" && options.required !== true)
62
+ return undefined;
63
+ const reason = code === "ENOENT" ? "文件不存在" : error.message;
64
+ throw failure(kind, `${path}: ${reason}`, { path });
65
+ }
66
+ let value;
67
+ try {
68
+ value = parseJsonText(text);
69
+ }
70
+ catch (error) {
71
+ throw failure(kind, `${path}: ${error.message}`, { path });
72
+ }
73
+ const diagnostics = VALIDATORS[kind](value);
74
+ if (hasErrors(diagnostics)) {
75
+ const lines = diagnostics
76
+ .filter((d) => d.severity === "error")
77
+ .map((d) => formatDiagnostic(path, d));
78
+ throw failure(kind, `配置文件无效:\n ${lines.join("\n ")}`, { path, diagnostics });
79
+ }
80
+ return {
81
+ path,
82
+ value: value,
83
+ warnings: diagnostics.map((d) => formatDiagnostic(path, d)),
84
+ };
85
+ }
86
+ /** 读失败不抛:返回诊断(doctor 用)。 */
87
+ export function probeConfigFile(kind, path) {
88
+ try {
89
+ const loaded = loadConfigFile(kind, path);
90
+ if (loaded === undefined)
91
+ return { exists: false, ok: true, messages: [] };
92
+ return { exists: true, ok: true, messages: loaded.warnings };
93
+ }
94
+ catch (error) {
95
+ return { exists: true, ok: false, messages: [error.message] };
96
+ }
97
+ }
@@ -0,0 +1,73 @@
1
+ /**
2
+ * 配置层级合并(设计 §7.2、§10.2)。[B5]
3
+ *
4
+ * 顺序:内置缺省 ← 用户级 ← profile.config ← 项目级(受限字段,只能收紧)← 命令行。
5
+ * - 对象深合并;数组整体替换,例外是「累加型」列表:`permission.allow / deny`、
6
+ * `tools.disabled`、`skills.dirs` 跨层拼接去重。
7
+ * - 项目级 `.ama/config.json` 只接受:`permission.deny`(追加)、`permission.mode`(只能更严)、
8
+ * `compaction`、`tools.disabled`、`tools.preset`(只能更严)、`codemode.mode: "off"`、`ui`;
9
+ * 其它字段与放宽项(含 `permission.builtinDeny`)被忽略并记 warning。
10
+ * - 同时产出带来源的权限规则清单(`ruleSpecs`),交给权限管线(B3 的 rules.ts 解析)。
11
+ */
12
+ import type { AmaConfig, CodemodeMode, ToolsPreset } from "./types.js";
13
+ import type { PermissionMode, RuleSource } from "../permissions/types.js";
14
+ import type { ModelThinkingLevel } from "../ai/types.js";
15
+ export declare const DEFAULT_CONFIG: Readonly<AmaConfig>;
16
+ /** 嵌入宿主(有 profile)时的缺省覆盖(§12.10)。 */
17
+ export declare const PROFILE_DEFAULTS: Readonly<Partial<AmaConfig>>;
18
+ export type ConfigLayerName = "default" | "user" | "profile" | "project" | "cli";
19
+ export interface PermissionRuleSpec {
20
+ effect: "allow" | "deny";
21
+ raw: string;
22
+ source: RuleSource;
23
+ }
24
+ /** 深合并两层配置(不改入参)。 */
25
+ export declare function mergeConfig(base: AmaConfig, over: Partial<AmaConfig> | undefined): AmaConfig;
26
+ export interface RestrictResult {
27
+ /** 只含被接受的字段。 */
28
+ accepted: Partial<AmaConfig>;
29
+ warnings: string[];
30
+ }
31
+ /** 预设 a 是否比 b 更严或相同(coordinator 最严,codemode 最宽)。 */
32
+ export declare function isPresetStricterOrEqual(a: ToolsPreset, b: ToolsPreset): boolean;
33
+ /**
34
+ * 把项目级配置裁剪为受限字段(§7.2);`currentMode` / `currentPreset` 是合并到此为止的
35
+ * 权限模式与工具预设。
36
+ */
37
+ export declare function restrictProjectConfig(project: AmaConfig, currentMode: PermissionMode, label?: string, currentPreset?: ToolsPreset): RestrictResult;
38
+ /** 命令行对配置的覆盖(只含与 config 同名的那部分参数)。 */
39
+ export interface CliConfigOverrides {
40
+ thinkingLevel?: ModelThinkingLevel | undefined;
41
+ permissionMode?: PermissionMode | undefined;
42
+ allow?: readonly string[] | undefined;
43
+ deny?: readonly string[] | undefined;
44
+ quietStartup?: "normal" | "header" | "silent" | undefined;
45
+ tuiMode?: "regular" | undefined;
46
+ skillDirs?: readonly string[] | undefined;
47
+ /** `--tools-preset`。 */
48
+ toolsPreset?: ToolsPreset | undefined;
49
+ /** `--codemode`。 */
50
+ codemode?: CodemodeMode | undefined;
51
+ }
52
+ export declare function cliOverridesToConfig(cli: CliConfigOverrides): Partial<AmaConfig>;
53
+ export interface ConfigLayers {
54
+ user?: AmaConfig | undefined;
55
+ /** profile.config 指向的文件内容;`hasProfile` 为 true 时还会叠加 PROFILE_DEFAULTS。 */
56
+ profile?: AmaConfig | undefined;
57
+ hasProfile?: boolean;
58
+ project?: AmaConfig | undefined;
59
+ cli?: CliConfigOverrides | undefined;
60
+ }
61
+ export interface MergeResult {
62
+ config: AmaConfig;
63
+ warnings: string[];
64
+ ruleSpecs: PermissionRuleSpec[];
65
+ /** 各层是否存在(doctor 显示)。 */
66
+ layers: ConfigLayerName[];
67
+ }
68
+ /** 第 6 步:缺省 ← 用户级 ← profile。 */
69
+ export declare function mergeBaseLayers(layers: Pick<ConfigLayers, "user" | "profile" | "hasProfile">): MergeResult;
70
+ /** 第 9 步:叠加项目级(受限)与命令行。 */
71
+ export declare function mergeProjectAndCli(base: MergeResult, project: AmaConfig | undefined, cli: CliConfigOverrides | undefined, projectLabel?: string): MergeResult;
72
+ /** 一次合并全部层(SDK / 测试用)。 */
73
+ export declare function mergeConfigLayers(layers: ConfigLayers): MergeResult;
@@ -0,0 +1,248 @@
1
+ /**
2
+ * 配置层级合并(设计 §7.2、§10.2)。[B5]
3
+ *
4
+ * 顺序:内置缺省 ← 用户级 ← profile.config ← 项目级(受限字段,只能收紧)← 命令行。
5
+ * - 对象深合并;数组整体替换,例外是「累加型」列表:`permission.allow / deny`、
6
+ * `tools.disabled`、`skills.dirs` 跨层拼接去重。
7
+ * - 项目级 `.ama/config.json` 只接受:`permission.deny`(追加)、`permission.mode`(只能更严)、
8
+ * `compaction`、`tools.disabled`、`tools.preset`(只能更严)、`codemode.mode: "off"`、`ui`;
9
+ * 其它字段与放宽项(含 `permission.builtinDeny`)被忽略并记 warning。
10
+ * - 同时产出带来源的权限规则清单(`ruleSpecs`),交给权限管线(B3 的 rules.ts 解析)。
11
+ */
12
+ import { CONFIG_FILE_VERSION, TOOLS_PRESETS_STRICT_FIRST } from "./types.js";
13
+ import { isAtLeastAsStrict } from "../permissions/rules.js";
14
+ export const DEFAULT_CONFIG = Object.freeze({
15
+ version: CONFIG_FILE_VERSION,
16
+ thinkingLevel: "medium",
17
+ permission: { mode: "default", allow: [], deny: [] },
18
+ compaction: { enabled: true, reserveTokens: 16_384, keepRecentTokens: 20_000 },
19
+ retry: { enabled: true, maxRetries: 3, baseDelayMs: 2_000, maxDelayMs: 60_000 },
20
+ tools: { preset: "default", maxToolResultChars: 30_000, bashTimeoutMs: 120_000, disabled: [] },
21
+ hooks: { timeoutMs: 60_000 },
22
+ ui: {
23
+ theme: "dark",
24
+ markdown: true,
25
+ showThinking: "collapsed",
26
+ tuiMode: "regular",
27
+ quietStartup: "normal",
28
+ },
29
+ skills: { dirs: [] },
30
+ });
31
+ /** 嵌入宿主(有 profile)时的缺省覆盖(§12.10)。 */
32
+ export const PROFILE_DEFAULTS = Object.freeze({
33
+ ui: { quietStartup: "header" },
34
+ });
35
+ /** 层名 → 规则来源(RuleSource)。 */
36
+ const RULE_SOURCE = {
37
+ default: "builtin",
38
+ user: "user",
39
+ profile: "profile",
40
+ project: "project",
41
+ cli: "cli",
42
+ };
43
+ const ACCUMULATING = new Set([
44
+ "permission.allow",
45
+ "permission.deny",
46
+ "tools.disabled",
47
+ "skills.dirs",
48
+ ]);
49
+ function isPlainObject(value) {
50
+ return typeof value === "object" && value !== null && !Array.isArray(value);
51
+ }
52
+ function unique(values) {
53
+ return [...new Set(values)];
54
+ }
55
+ function mergeValue(base, over, path) {
56
+ if (over === undefined)
57
+ return structuredCloneSafe(base);
58
+ if (Array.isArray(over)) {
59
+ if (ACCUMULATING.has(path) && Array.isArray(base))
60
+ return unique([...base, ...over]);
61
+ return [...over];
62
+ }
63
+ if (isPlainObject(over)) {
64
+ const result = isPlainObject(base) ? { ...structuredCloneSafe(base) } : {};
65
+ for (const [key, value] of Object.entries(over)) {
66
+ result[key] = mergeValue(result[key], value, path === "" ? key : `${path}.${key}`);
67
+ }
68
+ return result;
69
+ }
70
+ return over;
71
+ }
72
+ function structuredCloneSafe(value) {
73
+ return value === undefined ? value : structuredClone(value);
74
+ }
75
+ /** 深合并两层配置(不改入参)。 */
76
+ export function mergeConfig(base, over) {
77
+ if (over === undefined)
78
+ return structuredCloneSafe(base);
79
+ const merged = mergeValue(base, over, "");
80
+ merged.version = CONFIG_FILE_VERSION;
81
+ return merged;
82
+ }
83
+ /** 预设 a 是否比 b 更严或相同(coordinator 最严,codemode 最宽)。 */
84
+ export function isPresetStricterOrEqual(a, b) {
85
+ return TOOLS_PRESETS_STRICT_FIRST.indexOf(a) <= TOOLS_PRESETS_STRICT_FIRST.indexOf(b);
86
+ }
87
+ /**
88
+ * 把项目级配置裁剪为受限字段(§7.2);`currentMode` / `currentPreset` 是合并到此为止的
89
+ * 权限模式与工具预设。
90
+ */
91
+ export function restrictProjectConfig(project, currentMode, label = ".ama/config.json", currentPreset = "default") {
92
+ const warnings = [];
93
+ const accepted = {};
94
+ for (const [key, value] of Object.entries(project)) {
95
+ if (key === "version" || key === "$schema" || value === undefined)
96
+ continue;
97
+ switch (key) {
98
+ case "compaction":
99
+ if (project.compaction !== undefined)
100
+ accepted.compaction = structuredClone(project.compaction);
101
+ break;
102
+ case "ui":
103
+ if (project.ui !== undefined)
104
+ accepted.ui = structuredClone(project.ui);
105
+ break;
106
+ case "tools": {
107
+ const tools = project.tools ?? {};
108
+ const result = {};
109
+ for (const sub of Object.keys(tools)) {
110
+ if (sub !== "disabled" && sub !== "preset")
111
+ warnings.push(`${label}: 项目级只能设 tools.disabled / tools.preset,忽略 tools.${sub}`);
112
+ }
113
+ if (tools.disabled !== undefined)
114
+ result.disabled = [...tools.disabled];
115
+ if (tools.preset !== undefined) {
116
+ if (isPresetStricterOrEqual(tools.preset, currentPreset))
117
+ result.preset = tools.preset;
118
+ else
119
+ warnings.push(`${label}: 项目级不能放宽工具预设,忽略 tools.preset ${tools.preset}(当前 ${currentPreset})`);
120
+ }
121
+ if (Object.keys(result).length > 0)
122
+ accepted.tools = result;
123
+ break;
124
+ }
125
+ case "codemode": {
126
+ const codemode = project.codemode ?? {};
127
+ for (const [sub, v] of Object.entries(codemode)) {
128
+ if (sub === "mode" && v === "off")
129
+ continue;
130
+ warnings.push(`${label}: 项目级只接受 codemode.mode "off",忽略 codemode.${sub}${sub === "mode" ? ` ${String(v)}` : ""}`);
131
+ }
132
+ if (codemode.mode === "off")
133
+ accepted.codemode = { mode: "off" };
134
+ break;
135
+ }
136
+ case "permission": {
137
+ const permission = restrictPermission(project.permission ?? {}, currentMode, label, warnings);
138
+ if (permission !== undefined)
139
+ accepted.permission = permission;
140
+ break;
141
+ }
142
+ default:
143
+ warnings.push(`${label}: 项目级不能设 ${key},已忽略`);
144
+ }
145
+ }
146
+ return { accepted, warnings };
147
+ }
148
+ function restrictPermission(permission, currentMode, label, warnings) {
149
+ const result = {};
150
+ if (permission.allow !== undefined && permission.allow.length > 0) {
151
+ warnings.push(`${label}: 项目级不能加 allow 规则,忽略 ${permission.allow.join(", ")}`);
152
+ }
153
+ if (permission.deny !== undefined && permission.deny.length > 0)
154
+ result.deny = [...permission.deny];
155
+ if (permission.builtinDeny !== undefined) {
156
+ warnings.push(`${label}: 项目级不能改内置 deny 表,忽略 permission.builtinDeny`);
157
+ }
158
+ if (permission.mode !== undefined) {
159
+ if (isAtLeastAsStrict(permission.mode, currentMode)) {
160
+ result.mode = permission.mode;
161
+ }
162
+ else {
163
+ warnings.push(`${label}: 项目级只能收紧权限模式,忽略 ${permission.mode}(当前 ${currentMode})`);
164
+ }
165
+ }
166
+ return Object.keys(result).length > 0 ? result : undefined;
167
+ }
168
+ export function cliOverridesToConfig(cli) {
169
+ const out = {};
170
+ if (cli.thinkingLevel !== undefined)
171
+ out.thinkingLevel = cli.thinkingLevel;
172
+ const permission = {};
173
+ if (cli.permissionMode !== undefined)
174
+ permission.mode = cli.permissionMode;
175
+ if (cli.allow !== undefined && cli.allow.length > 0)
176
+ permission.allow = [...cli.allow];
177
+ if (cli.deny !== undefined && cli.deny.length > 0)
178
+ permission.deny = [...cli.deny];
179
+ if (Object.keys(permission).length > 0)
180
+ out.permission = permission;
181
+ const ui = {};
182
+ if (cli.quietStartup !== undefined)
183
+ ui.quietStartup = cli.quietStartup;
184
+ if (cli.tuiMode !== undefined)
185
+ ui.tuiMode = cli.tuiMode;
186
+ if (Object.keys(ui).length > 0)
187
+ out.ui = ui;
188
+ if (cli.toolsPreset !== undefined)
189
+ out.tools = { preset: cli.toolsPreset };
190
+ if (cli.codemode !== undefined)
191
+ out.codemode = { mode: cli.codemode };
192
+ return out;
193
+ }
194
+ function collectRules(layer, permission) {
195
+ const source = RULE_SOURCE[layer];
196
+ const specs = [];
197
+ for (const raw of permission?.allow ?? [])
198
+ specs.push({ effect: "allow", raw, source });
199
+ for (const raw of permission?.deny ?? [])
200
+ specs.push({ effect: "deny", raw, source });
201
+ return specs;
202
+ }
203
+ /** 第 6 步:缺省 ← 用户级 ← profile。 */
204
+ export function mergeBaseLayers(layers) {
205
+ let config = mergeConfig(DEFAULT_CONFIG, undefined);
206
+ const present = ["default"];
207
+ const ruleSpecs = [];
208
+ if (layers.user !== undefined) {
209
+ config = mergeConfig(config, layers.user);
210
+ present.push("user");
211
+ ruleSpecs.push(...collectRules("user", layers.user.permission));
212
+ }
213
+ if (layers.hasProfile === true)
214
+ config = mergeConfig(config, PROFILE_DEFAULTS);
215
+ if (layers.profile !== undefined) {
216
+ config = mergeConfig(config, layers.profile);
217
+ present.push("profile");
218
+ ruleSpecs.push(...collectRules("profile", layers.profile.permission));
219
+ }
220
+ return { config, warnings: [], ruleSpecs, layers: present };
221
+ }
222
+ /** 第 9 步:叠加项目级(受限)与命令行。 */
223
+ export function mergeProjectAndCli(base, project, cli, projectLabel) {
224
+ let config = base.config;
225
+ const warnings = [...base.warnings];
226
+ const ruleSpecs = [...base.ruleSpecs];
227
+ const present = [...base.layers];
228
+ if (project !== undefined) {
229
+ const baseline = config.permission?.mode ?? "default";
230
+ const restricted = restrictProjectConfig(project, baseline, projectLabel, config.tools?.preset ?? "default");
231
+ warnings.push(...restricted.warnings);
232
+ config = mergeConfig(config, restricted.accepted);
233
+ present.push("project");
234
+ ruleSpecs.push(...collectRules("project", restricted.accepted.permission));
235
+ }
236
+ // 命令行是用户的显式选择,最后叠加(可以放宽项目级收紧过的 mode,§7.2「放宽只认用户级 / 命令行 / profile」)。
237
+ const cliConfig = cli === undefined ? undefined : cliOverridesToConfig(cli);
238
+ if (cliConfig !== undefined && Object.keys(cliConfig).length > 0) {
239
+ config = mergeConfig(config, cliConfig);
240
+ present.push("cli");
241
+ ruleSpecs.push(...collectRules("cli", cliConfig.permission));
242
+ }
243
+ return { config, warnings, ruleSpecs, layers: present };
244
+ }
245
+ /** 一次合并全部层(SDK / 测试用)。 */
246
+ export function mergeConfigLayers(layers) {
247
+ return mergeProjectAndCli(mergeBaseLayers(layers), layers.project, layers.cli);
248
+ }