akm-cli 0.9.1 → 0.9.2-alpha.2

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 (350) hide show
  1. package/CHANGELOG.md +103 -28
  2. package/README.md +3 -1
  3. package/SECURITY.md +1 -1
  4. package/STABILITY.md +1 -1
  5. package/dist/akm +2 -2
  6. package/dist/akm-migrate +2 -2
  7. package/dist/assets/hints/cli-hints-full.md +14 -9
  8. package/dist/assets/improve-strategies/proactive-maintenance.json +1 -1
  9. package/dist/assets/improve-strategies/reflect-distill.json +1 -1
  10. package/dist/assets/models.json +35 -0
  11. package/dist/assets/stash-skeleton/facts/conventions/backlinks.md +3 -4
  12. package/dist/assets/stash-skeleton/facts/conventions/organization.md +1 -3
  13. package/dist/assets/tasks/core/extract.yml +6 -5
  14. package/dist/assets/tasks/core/improve.yml +6 -5
  15. package/dist/assets/tasks/core/index-refresh.yml +6 -5
  16. package/dist/assets/tasks/core/sync.yml +6 -5
  17. package/dist/assets/tasks/core/version-check.yml +6 -5
  18. package/dist/assets/tasks/improve/akm-graph-refresh-weekly.yml +6 -5
  19. package/dist/assets/tasks/improve/akm-improve-catchup.yml +6 -5
  20. package/dist/assets/tasks/improve/akm-improve-consolidate.yml +6 -5
  21. package/dist/assets/tasks/improve/akm-improve-frequent.yml +6 -5
  22. package/dist/assets/tasks/improve/akm-improve-nightly.yml +6 -5
  23. package/dist/cli/confirm.js +2 -2
  24. package/dist/cli/parse-args.js +3 -24
  25. package/dist/cli/retired-commands.js +1 -1
  26. package/dist/cli/shared.js +2 -2
  27. package/dist/cli.js +11 -9
  28. package/dist/commands/agent/agent-dispatch.js +55 -89
  29. package/dist/commands/agent/contribute-cli.js +12 -45
  30. package/dist/commands/command/builtin-action.js +32 -0
  31. package/dist/commands/command/command-cli.js +99 -0
  32. package/dist/commands/command/command-execution.js +308 -0
  33. package/dist/commands/command/execution-source-loader.js +176 -0
  34. package/dist/commands/command/portable-template.js +60 -0
  35. package/dist/commands/config-cli.js +10 -4
  36. package/dist/commands/env/env.js +4 -2
  37. package/dist/commands/feedback-cli.js +1 -1
  38. package/dist/commands/health/checks.js +241 -29
  39. package/dist/commands/health/html-report.js +0 -14
  40. package/dist/commands/health/report-view-model.js +0 -1
  41. package/dist/commands/health/surfaces.js +6 -7
  42. package/dist/commands/health/types.js +0 -2
  43. package/dist/commands/health.js +63 -18
  44. package/dist/commands/improve/collapse-detector.js +5 -6
  45. package/dist/commands/improve/consolidate.js +251 -214
  46. package/dist/commands/improve/distill/promote-memory.js +71 -34
  47. package/dist/commands/improve/distill/quality-gate.js +17 -5
  48. package/dist/commands/improve/distill.js +232 -155
  49. package/dist/commands/improve/eligibility.js +112 -79
  50. package/dist/commands/improve/execution.js +57 -0
  51. package/dist/commands/improve/extract-cli.js +5 -5
  52. package/dist/commands/improve/extract-prompt.js +64 -22
  53. package/dist/commands/improve/extract.js +608 -360
  54. package/dist/commands/improve/improve-strategies.js +43 -14
  55. package/dist/commands/improve/improve.js +249 -29
  56. package/dist/commands/improve/loop-stages.js +11 -17
  57. package/dist/commands/improve/memory/memory-contradiction-detect.js +90 -66
  58. package/dist/commands/improve/outcome-loop.js +22 -38
  59. package/dist/commands/improve/planner.js +134 -0
  60. package/dist/commands/improve/preparation.js +730 -409
  61. package/dist/commands/improve/reflect.js +386 -223
  62. package/dist/commands/improve/run-context.js +3 -4
  63. package/dist/commands/improve/salience.js +6 -58
  64. package/dist/commands/improve/session-asset.js +12 -12
  65. package/dist/commands/lint/index.js +101 -29
  66. package/dist/commands/migrate-cli.js +11 -69
  67. package/dist/commands/migration-tool.js +6 -9
  68. package/dist/commands/models-cli.js +27 -0
  69. package/dist/commands/proposal/drain.js +258 -186
  70. package/dist/commands/proposal/proposal-cli.js +32 -10
  71. package/dist/commands/proposal/proposal.js +2 -5
  72. package/dist/commands/proposal/propose.js +192 -172
  73. package/dist/commands/proposal/repository.js +54 -91
  74. package/dist/commands/proposal/validators/proposal-validators.js +9 -7
  75. package/dist/commands/read/curate.js +53 -22
  76. package/dist/commands/read/registry-search.js +25 -9
  77. package/dist/commands/read/remember-cli.js +14 -2
  78. package/dist/commands/read/search.js +10 -4
  79. package/dist/commands/read/show.js +139 -153
  80. package/dist/commands/registry-cli.js +16 -7
  81. package/dist/commands/remember.js +33 -18
  82. package/dist/commands/sources/add-cli.js +19 -178
  83. package/dist/commands/sources/bundle-cli.js +15 -3
  84. package/dist/commands/sources/dangerous-env-audit.js +135 -0
  85. package/dist/commands/sources/info.js +2 -1
  86. package/dist/commands/sources/installed-stashes.js +901 -177
  87. package/dist/commands/sources/schema-repair.js +174 -95
  88. package/dist/commands/sources/self-update.js +30 -74
  89. package/dist/commands/sources/source-add.js +3 -5
  90. package/dist/commands/sources/sources-cli.js +2 -15
  91. package/dist/commands/sources/update-transaction.js +220 -0
  92. package/dist/commands/tasks/tasks-cli.js +3 -3
  93. package/dist/commands/tasks/tasks.js +736 -317
  94. package/dist/commands/workflow-cli.js +2 -2
  95. package/dist/core/adapter/adapters/agent-skills-adapter.js +3 -0
  96. package/dist/core/adapter/adapters/akm-adapter.js +85 -35
  97. package/dist/core/adapter/adapters/akm-lint.js +54 -39
  98. package/dist/core/adapter/adapters/akm-metadata.js +45 -45
  99. package/dist/core/adapter/adapters/akm-task-adapter.js +32 -49
  100. package/dist/core/adapter/adapters/akm-workflow-adapter.js +38 -23
  101. package/dist/core/adapter/adapters/dotenv-adapter.js +30 -1
  102. package/dist/core/adapter/adapters/generic-files-adapter.js +11 -0
  103. package/dist/core/adapter/adapters/index.js +0 -9
  104. package/dist/core/adapter/adapters/llm-wiki-adapter.js +4 -0
  105. package/dist/core/adapter/adapters/okf-adapter.js +4 -0
  106. package/dist/core/adapter/adapters/opencode-adapter.js +5 -8
  107. package/dist/core/adapter/adapters/tool-dir-shared.js +63 -6
  108. package/dist/core/adapter/adapters/website-snapshot-adapter.js +4 -0
  109. package/dist/core/adapter/execution-source.js +308 -0
  110. package/dist/core/adapter/recognize-match.js +36 -13
  111. package/dist/core/adapter/registry.js +0 -9
  112. package/dist/core/asset/stash-meta.js +94 -4
  113. package/dist/core/common.js +6 -11
  114. package/dist/core/config/config-io.js +3 -3
  115. package/dist/core/config/config-schema.js +18 -40
  116. package/dist/core/config/config-sources.js +11 -21
  117. package/dist/core/config/config-walker.js +31 -13
  118. package/dist/core/config/config.js +23 -26
  119. package/dist/core/config/schema/engines.js +8 -7
  120. package/dist/core/config/schema/improve-processes.js +29 -5
  121. package/dist/core/config/schema/index-config.js +0 -27
  122. package/dist/core/config/schema/primitives.js +1 -23
  123. package/dist/core/config/schema/sources-bundles.js +13 -16
  124. package/dist/core/errors.js +2 -0
  125. package/dist/core/events.js +68 -32
  126. package/dist/core/extra-params.js +1 -0
  127. package/dist/core/improve-result.js +315 -0
  128. package/dist/core/lesson-lint.js +0 -6
  129. package/dist/core/maintenance-barrier.js +4 -4
  130. package/dist/core/network-policy.js +152 -0
  131. package/dist/core/paths.js +1 -1
  132. package/dist/core/recognition-util.js +4 -4
  133. package/dist/core/registry-url.js +456 -0
  134. package/dist/core/state/migrations.js +161 -47
  135. package/dist/core/state-db.js +453 -80
  136. package/dist/core/system-error.js +32 -0
  137. package/dist/core/time.js +2 -12
  138. package/dist/core/write-source.js +0 -18
  139. package/dist/execution/directory-identity.js +52 -0
  140. package/dist/execution/executable-identity.js +107 -0
  141. package/dist/execution/guarded-source.js +398 -0
  142. package/dist/execution/json.js +95 -0
  143. package/dist/{commands/health/types-session-log.js → execution/limits.js} +2 -1
  144. package/dist/execution/record.js +55 -0
  145. package/dist/execution/resolved-request.js +730 -0
  146. package/dist/execution/source.js +320 -0
  147. package/dist/indexer/bundle-identity-guard.js +5 -4
  148. package/dist/indexer/db/graph-db.js +33 -0
  149. package/dist/indexer/graph/graph-boost.js +3 -4
  150. package/dist/indexer/graph/graph-extraction.js +562 -373
  151. package/dist/indexer/index-written-assets.js +78 -39
  152. package/dist/indexer/indexer.js +471 -432
  153. package/dist/indexer/installations.js +6 -0
  154. package/dist/indexer/lookup/adapter-concept-owner.js +283 -0
  155. package/dist/indexer/materialize-embeddings.js +155 -0
  156. package/dist/indexer/passes/memory-inference.js +227 -174
  157. package/dist/indexer/passes/metadata.js +263 -118
  158. package/dist/indexer/scan/doc-to-entry.js +7 -10
  159. package/dist/indexer/scan/drain-dir.js +51 -23
  160. package/dist/indexer/search/db-search.js +156 -50
  161. package/dist/indexer/search/fts-query.js +40 -40
  162. package/dist/indexer/search/ranking.js +36 -1
  163. package/dist/indexer/search/search-attribution.js +3 -1
  164. package/dist/indexer/search/search-fields.js +23 -14
  165. package/dist/indexer/search/search-hit-enrichers.js +1 -1
  166. package/dist/indexer/search/search-source.js +7 -16
  167. package/dist/indexer/search/semantic-status.js +10 -1
  168. package/dist/indexer/usage/show-usage.js +105 -0
  169. package/dist/indexer/usage/usage-events.js +7 -2
  170. package/dist/indexer/walk/matchers.js +40 -10
  171. package/dist/indexer/walk/path-resolver.js +5 -2
  172. package/dist/indexer/walk/walker.js +20 -2
  173. package/dist/integrations/agent/builder-shared.js +3 -6
  174. package/dist/integrations/agent/conversation-fallback.js +16 -0
  175. package/dist/integrations/agent/engine-resolution.js +87 -87
  176. package/dist/integrations/agent/execution-cascade.js +566 -0
  177. package/dist/integrations/agent/execution-definitions.js +211 -0
  178. package/dist/integrations/agent/execution-lowering.js +811 -0
  179. package/dist/integrations/agent/execution-preparation.js +67 -0
  180. package/dist/integrations/agent/index.js +0 -2
  181. package/dist/integrations/agent/inline-execution.js +74 -0
  182. package/dist/integrations/agent/model-map.js +515 -0
  183. package/dist/integrations/agent/persona-fallback.js +30 -0
  184. package/dist/integrations/agent/request-lowering.js +186 -0
  185. package/dist/integrations/agent/runner-dispatch.js +230 -37
  186. package/dist/integrations/agent/runner.js +12 -83
  187. package/dist/integrations/harnesses/aider/agent-builder.js +8 -0
  188. package/dist/integrations/harnesses/aider/index.js +0 -1
  189. package/dist/integrations/harnesses/amazonq/agent-builder.js +8 -0
  190. package/dist/integrations/harnesses/amazonq/index.js +0 -1
  191. package/dist/integrations/harnesses/claude/agent-builder.js +14 -1
  192. package/dist/integrations/harnesses/claude/index.js +1 -5
  193. package/dist/integrations/harnesses/claude/session-log.js +3 -33
  194. package/dist/integrations/harnesses/codex/agent-builder.js +8 -0
  195. package/dist/integrations/harnesses/codex/index.js +0 -1
  196. package/dist/integrations/harnesses/copilot/agent-builder.js +8 -0
  197. package/dist/integrations/harnesses/copilot/index.js +0 -1
  198. package/dist/integrations/harnesses/gemini/agent-builder.js +8 -0
  199. package/dist/integrations/harnesses/gemini/index.js +0 -1
  200. package/dist/integrations/harnesses/index.js +4 -44
  201. package/dist/integrations/harnesses/opencode/agent-builder.js +16 -9
  202. package/dist/integrations/harnesses/opencode/index.js +0 -2
  203. package/dist/integrations/harnesses/opencode/session-log.js +14 -204
  204. package/dist/integrations/harnesses/opencode-sdk/harness.js +12 -1
  205. package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +40 -42
  206. package/dist/integrations/harnesses/openhands/agent-builder.js +8 -0
  207. package/dist/integrations/harnesses/openhands/index.js +0 -1
  208. package/dist/integrations/harnesses/pi/agent-builder.js +8 -0
  209. package/dist/integrations/harnesses/pi/index.js +0 -1
  210. package/dist/integrations/harnesses/shared.js +0 -1
  211. package/dist/integrations/harnesses/types.js +1 -3
  212. package/dist/integrations/lockfile.js +82 -79
  213. package/dist/integrations/session-logs/index.js +6 -17
  214. package/dist/integrations/session-logs/provider-base.js +1 -29
  215. package/dist/llm/client.js +10 -5
  216. package/dist/llm/embedder.js +6 -7
  217. package/dist/llm/embedders/local.js +37 -88
  218. package/dist/llm/embedders/types.js +1 -1
  219. package/dist/llm/graph-extract.js +75 -50
  220. package/dist/llm/index-passes.js +43 -5
  221. package/dist/llm/memory-infer.js +8 -6
  222. package/dist/llm/metadata-enhance.js +5 -3
  223. package/dist/llm/structured-call.js +122 -25
  224. package/dist/output/format-exempt.js +1 -1
  225. package/dist/output/render-registry.js +0 -16
  226. package/dist/output/renderers.js +12 -7
  227. package/dist/output/shapes/curate.js +1 -0
  228. package/dist/output/shapes/helpers.js +10 -2
  229. package/dist/output/shapes/passthrough.js +2 -0
  230. package/dist/output/text/command-format.js +31 -33
  231. package/dist/output/text/health-format.js +1 -29
  232. package/dist/output/text/migrate.js +6 -56
  233. package/dist/output/text/proposal-format.js +16 -1
  234. package/dist/output/text/workflow-format.js +16 -0
  235. package/dist/registry/network.js +279 -0
  236. package/dist/registry/pinned-request-helper.js +247 -0
  237. package/dist/registry/pinned-transport.js +717 -0
  238. package/dist/registry/providers/skills-sh.js +18 -6
  239. package/dist/registry/providers/static-index.js +20 -7
  240. package/dist/registry/resolve.js +53 -28
  241. package/dist/scripts/akm-migrate-node.js +19334 -52269
  242. package/dist/scripts/akm-migrate.js +19270 -51612
  243. package/dist/setup/registry-stash-loader.js +64 -20
  244. package/dist/setup/semantic-assets.js +9 -34
  245. package/dist/setup/setup.js +12 -30
  246. package/dist/setup/source-identity.js +17 -0
  247. package/dist/setup/steps/sources.js +36 -15
  248. package/dist/setup/steps/tasks.js +39 -11
  249. package/dist/sources/providers/git-provider.js +3 -3
  250. package/dist/sources/providers/npm.js +2 -2
  251. package/dist/sources/providers/provider-utils.js +4 -3
  252. package/dist/sources/providers/website.js +11 -7
  253. package/dist/sources/snapshot-fetchers/host-guard.js +9 -136
  254. package/dist/sources/snapshot-fetchers/website-ingest.js +25 -109
  255. package/dist/sources/website-url.js +73 -0
  256. package/dist/storage/engines/sqlite-migrations.js +81 -26
  257. package/dist/storage/managed-db.js +27 -24
  258. package/dist/storage/repositories/events-repository.js +3 -0
  259. package/dist/storage/repositories/index-connection.js +42 -10
  260. package/dist/storage/repositories/index-entries-repository.js +203 -229
  261. package/dist/storage/repositories/index-entry-mapper.js +8 -12
  262. package/dist/storage/repositories/index-entry-schema.js +255 -0
  263. package/dist/storage/repositories/index-fts-repository.js +64 -71
  264. package/dist/storage/repositories/index-llm-cache-repository.js +8 -13
  265. package/dist/storage/repositories/index-meta-repository.js +0 -11
  266. package/dist/storage/repositories/index-schema.js +74 -350
  267. package/dist/storage/repositories/index-utility-repository.js +12 -17
  268. package/dist/storage/repositories/index-vec-repository.js +56 -7
  269. package/dist/storage/repositories/proposals-repository.js +4 -127
  270. package/dist/storage/repositories/registry-cache.js +2 -1
  271. package/dist/storage/repositories/task-history-repository.js +20 -40
  272. package/dist/storage/repositories/workflow-runs-repository.js +228 -129
  273. package/dist/storage/sqlite-read-snapshot.js +148 -0
  274. package/dist/tasks/backends/cron.js +170 -42
  275. package/dist/tasks/backends/index.js +1 -1
  276. package/dist/tasks/backends/launchd.js +787 -202
  277. package/dist/tasks/backends/schtasks.js +282 -83
  278. package/dist/tasks/embedded.js +7 -7
  279. package/dist/tasks/frozen-script.js +50 -0
  280. package/dist/tasks/resolve-akm-bin.js +5 -1
  281. package/dist/tasks/runner.js +239 -251
  282. package/dist/tasks/runtime-v3.js +281 -0
  283. package/dist/tasks/scheduler-binding.js +272 -0
  284. package/dist/tasks/scheduler-invocation.js +57 -43
  285. package/dist/tasks/scheduler-sync.js +654 -0
  286. package/dist/tasks/source-v3.js +752 -0
  287. package/dist/tasks/standalone-script-entry.js +5 -0
  288. package/dist/tasks/task-id.js +29 -0
  289. package/dist/workflows/authoring/authoring.js +15 -32
  290. package/dist/workflows/exec/dispatch-redaction.js +14 -8
  291. package/dist/workflows/exec/exec-unit.js +7 -28
  292. package/dist/workflows/exec/frozen-judge.js +57 -89
  293. package/dist/workflows/exec/lowering-notices.js +23 -0
  294. package/dist/workflows/exec/native-executor.js +301 -458
  295. package/dist/workflows/exec/param-secrets.js +4 -3
  296. package/dist/workflows/exec/run-workflow.js +26 -32
  297. package/dist/workflows/exec/step-work.js +105 -109
  298. package/dist/workflows/exec/unit-dispatch.js +103 -27
  299. package/dist/workflows/exec/unit-writer.js +3 -3
  300. package/dist/workflows/exec/worktree.js +2 -2
  301. package/dist/workflows/ir/compile.js +86 -72
  302. package/dist/workflows/ir/environment-v4.js +328 -0
  303. package/dist/workflows/ir/freeze-v4.js +122 -0
  304. package/dist/workflows/ir/plan-hash.js +13 -7
  305. package/dist/workflows/ir/schema-v4.js +525 -0
  306. package/dist/workflows/ir/schema.js +25 -284
  307. package/dist/workflows/ir/source-freeze-v4.js +506 -0
  308. package/dist/workflows/parser.js +27 -24
  309. package/dist/workflows/program/schema.js +1 -2
  310. package/dist/workflows/renderer.js +42 -29
  311. package/dist/workflows/resource-limits.js +4 -5
  312. package/dist/workflows/runtime/agent-identity.js +11 -13
  313. package/dist/workflows/runtime/plan-classifier.js +8 -8
  314. package/dist/workflows/runtime/runs.js +27 -43
  315. package/dist/workflows/runtime/workflow-asset-loader.js +45 -205
  316. package/dist/workflows/source-files.js +373 -0
  317. package/dist/workflows/source-ir/compile.js +196 -0
  318. package/dist/workflows/source-ir/github-yaml.js +577 -0
  319. package/dist/workflows/source-ir/ordering.js +38 -0
  320. package/dist/workflows/source-ir/program.js +50 -0
  321. package/dist/workflows/source-ir/result.js +26 -0
  322. package/dist/workflows/source-ir/schema.js +772 -0
  323. package/dist/workflows/source-ir/semantics.js +242 -0
  324. package/dist/workflows/source-ir/uses.js +14 -0
  325. package/docs/README.md +2 -0
  326. package/docs/migration/README.md +3 -1
  327. package/docs/migration/release-notes/0.9.2.md +55 -0
  328. package/docs/migration/release-notes/README.md +5 -0
  329. package/docs/migration/v0.8-to-v0.9.md +76 -1077
  330. package/docs/migration/v0.9.0-troubleshooting.md +104 -516
  331. package/docs/migration/v0.9.1-to-v0.9.2.md +150 -0
  332. package/docs/reference/README.md +1 -0
  333. package/docs/reference/cli.md +230 -98
  334. package/docs/reference/configuration.md +159 -36
  335. package/docs/reference/data-and-telemetry.md +19 -1
  336. package/docs/reference/supported-formats.md +23 -3
  337. package/docs/reference/tasks.md +182 -0
  338. package/docs/reference/workflow-schema.md +91 -40
  339. package/docs/reference/workflows.md +33 -6
  340. package/package.json +10 -6
  341. package/schemas/akm-config.json +372 -224
  342. package/schemas/akm-task.json +324 -80
  343. package/schemas/akm-workflow.json +6 -9
  344. package/dist/core/migration-operation.js +0 -75
  345. package/dist/integrations/agent/model-aliases.js +0 -74
  346. package/dist/tasks/parser.js +0 -380
  347. package/dist/tasks/schema.js +0 -123
  348. package/dist/tasks/validator.js +0 -80
  349. package/dist/workflows/ir/freeze.js +0 -320
  350. package/dist/workflows/runtime/document-cache.js +0 -13
@@ -0,0 +1,30 @@
1
+ // This Source Code Form is subject to the terms of the Mozilla Public
2
+ // License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
+ export const PERSONA_FALLBACK_NOTICE_CODE = "persona-prompt-composed";
5
+ export const PERSONA_FALLBACK_BEGIN = "<AKM_PERSONA>";
6
+ export const PERSONA_FALLBACK_END = "</AKM_PERSONA>";
7
+ function withTrailingNewline(value) {
8
+ return value.endsWith("\n") ? value : `${value}\n`;
9
+ }
10
+ /** Preserve a persona when a target has no native system/persona channel. */
11
+ export function composePersonaFallbackPrompt(persona, command, adapter) {
12
+ if (typeof persona !== "string" || typeof command !== "string") {
13
+ throw new TypeError("persona fallback content must be strings");
14
+ }
15
+ if (typeof adapter !== "string" || adapter.length === 0) {
16
+ throw new TypeError("persona fallback adapter must be a non-empty string");
17
+ }
18
+ const notice = Object.freeze({
19
+ code: PERSONA_FALLBACK_NOTICE_CODE,
20
+ severity: "info",
21
+ adapter,
22
+ field: "persona",
23
+ message: "The selected engine has no native persona channel; AKM composed the persona into the prompt.",
24
+ });
25
+ const notices = Object.freeze([notice]);
26
+ return Object.freeze({
27
+ prompt: `${PERSONA_FALLBACK_BEGIN}\n${withTrailingNewline(persona)}${PERSONA_FALLBACK_END}\n\n${command}`,
28
+ notices,
29
+ });
30
+ }
@@ -0,0 +1,186 @@
1
+ // This Source Code Form is subject to the terms of the Mozilla Public
2
+ // License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
+ import { ConfigError } from "../../core/errors.js";
5
+ import { composeConversationFallbackPrompt } from "./conversation-fallback.js";
6
+ import { composePersonaFallbackPrompt } from "./persona-fallback.js";
7
+ function own(value, key) {
8
+ return Object.hasOwn(value, key);
9
+ }
10
+ function hasToolSelection(value) {
11
+ if (value === null)
12
+ return false;
13
+ if (typeof value === "string")
14
+ return value.length > 0;
15
+ if (Array.isArray(value))
16
+ return value.length > 0;
17
+ return Object.keys(value).length > 0;
18
+ }
19
+ function translatesTools(mode, value) {
20
+ if (!hasToolSelection(value))
21
+ return true;
22
+ if (mode === "all")
23
+ return true;
24
+ if (mode === "flat")
25
+ return typeof value === "string" || Array.isArray(value);
26
+ if (mode === "sdk") {
27
+ return (typeof value === "string" ||
28
+ Array.isArray(value) ||
29
+ (value !== null && Object.values(value).every((entry) => typeof entry === "boolean")));
30
+ }
31
+ return false;
32
+ }
33
+ function notice(adapter, field) {
34
+ return Object.freeze({
35
+ code: "untranslated-field",
36
+ severity: "warning",
37
+ adapter,
38
+ field,
39
+ message: `The ${adapter} lowerer does not translate resolved field ${field}; dispatch will continue optimistically.`,
40
+ });
41
+ }
42
+ function conversationFallbackNotice(adapter) {
43
+ return Object.freeze({
44
+ code: "conversation-prompt-composed",
45
+ severity: "warning",
46
+ adapter,
47
+ field: "conversation",
48
+ message: `The ${adapter} transport has no native multi-message channel; AKM composed the conversation prefix into one deterministic JSON prompt block.`,
49
+ });
50
+ }
51
+ function selectedExtensionPaths(request) {
52
+ const out = [];
53
+ if (own(request, "extensions"))
54
+ out.push("extensions");
55
+ if (own(request.command, "extensions"))
56
+ out.push("command.extensions");
57
+ const persona = own(request, "persona") ? request.persona : undefined;
58
+ if (persona && own(persona, "extensions"))
59
+ out.push("persona.extensions");
60
+ if (own(request.engine, "extensions"))
61
+ out.push("engine.extensions");
62
+ if (own(request.runtime, "extensions"))
63
+ out.push("runtime.extensions");
64
+ return out;
65
+ }
66
+ function sortedUnique(values) {
67
+ return Object.freeze([...new Set(values)].sort());
68
+ }
69
+ /**
70
+ * Build one harness-owned structural lowerer. Each harness registers the
71
+ * function it gets back beside its argv builder; no global model/provider
72
+ * capability table participates in dispatch.
73
+ */
74
+ export function createAgentRequestLowerer(options) {
75
+ const supportedInference = new Set(options.inference ?? []);
76
+ return (_profile, request) => {
77
+ const translated = new Set(["command.content", "engine"]);
78
+ for (const field of ["timeoutMs", "workspace", "environment"]) {
79
+ if (own(request.runtime, field))
80
+ translated.add(`runtime.${field}`);
81
+ }
82
+ const untranslated = new Set();
83
+ const notices = [];
84
+ const reject = (field) => {
85
+ untranslated.add(field);
86
+ notices.push(notice(options.adapter, field));
87
+ };
88
+ let prompt = request.command.content;
89
+ if (own(request, "conversation")) {
90
+ translated.add("conversation");
91
+ if (request.conversation && request.conversation.length > 0) {
92
+ prompt = composeConversationFallbackPrompt(request.conversation, prompt);
93
+ notices.push(conversationFallbackNotice(options.adapter));
94
+ }
95
+ }
96
+ let systemPrompt;
97
+ const persona = own(request, "persona") ? request.persona : undefined;
98
+ const agent = own(request, "agent") ? request.agent : undefined;
99
+ let nativeAgent;
100
+ if (persona) {
101
+ if (options.personaChannel === "native") {
102
+ systemPrompt = persona.content;
103
+ translated.add("persona");
104
+ }
105
+ else {
106
+ const composed = composePersonaFallbackPrompt(persona.content, prompt, options.adapter);
107
+ prompt = composed.prompt;
108
+ notices.push(...composed.notices);
109
+ translated.add("persona");
110
+ }
111
+ if (typeof agent === "string")
112
+ translated.add("agent");
113
+ }
114
+ else if (typeof agent === "string") {
115
+ if (!options.nativeAgentSelector) {
116
+ throw new ConfigError(`The ${options.adapter} transport cannot consume native agent selector ${JSON.stringify(agent)}.`, "INVALID_CONFIG_FILE");
117
+ }
118
+ nativeAgent = agent;
119
+ translated.add("agent");
120
+ }
121
+ else if (own(request, "agent")) {
122
+ translated.add("agent");
123
+ }
124
+ const dispatch = { prompt };
125
+ if (nativeAgent !== undefined)
126
+ dispatch.agent = nativeAgent;
127
+ if (systemPrompt !== undefined)
128
+ dispatch.systemPrompt = systemPrompt;
129
+ if (own(request, "model")) {
130
+ translated.add("model");
131
+ if (request.model) {
132
+ dispatch.model = request.model.resolved;
133
+ }
134
+ }
135
+ if (own(request, "inference")) {
136
+ dispatch.inference = request.inference;
137
+ const inference = request.inference;
138
+ if (inference && Object.keys(inference).length > 0) {
139
+ for (const key of Object.keys(inference).sort()) {
140
+ const field = `inference.${key}`;
141
+ if (supportedInference.has(key))
142
+ translated.add(field);
143
+ else
144
+ reject(field);
145
+ }
146
+ if (typeof inference.effort === "string")
147
+ dispatch.effort = inference.effort;
148
+ }
149
+ else {
150
+ translated.add("inference");
151
+ }
152
+ }
153
+ if (own(request, "outputSchema")) {
154
+ if (request.outputSchema === null || options.outputSchema)
155
+ translated.add("outputSchema");
156
+ else
157
+ reject("outputSchema");
158
+ if (request.outputSchema)
159
+ dispatch.schema = request.outputSchema;
160
+ }
161
+ if (own(request, "tools")) {
162
+ const tools = request.tools;
163
+ if (translatesTools(options.tools, tools))
164
+ translated.add("tools");
165
+ else
166
+ reject("tools");
167
+ dispatch.tools = tools;
168
+ }
169
+ if (own(request.runtime, "settings")) {
170
+ const settings = request.runtime.settings;
171
+ if (settings === null || Object.keys(settings).length === 0)
172
+ translated.add("runtime.settings");
173
+ else
174
+ reject("runtime.settings");
175
+ }
176
+ for (const field of selectedExtensionPaths(request))
177
+ reject(field);
178
+ return Object.freeze({
179
+ prompt,
180
+ dispatch: Object.freeze(dispatch),
181
+ translatedFields: sortedUnique(translated),
182
+ untranslatedFields: sortedUnique(untranslated),
183
+ notices: Object.freeze(notices),
184
+ });
185
+ };
186
+ }
@@ -2,37 +2,183 @@
2
2
  // License, v. 2.0. If a copy of the MPL was not distributed with this
3
3
  // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
4
  /**
5
- * X3 the ONE dispatch seam for the {@link RunnerSpec} tagged union.
5
+ * The low-level exhaustive dispatch seam for the {@link RunnerSpec} transport
6
+ * union (`llm | agent | sdk`). User/model work reaches this function only
7
+ * after `ResolvedExecutionRequestV1` preparation and engine-owned lowering;
8
+ * `dispatchLoweredExecutionRequest` supplies the direct-LLM handler. A
9
+ * prompt-free native launch crosses the explicit payload-free interactive
10
+ * lowerer in that same shared layer.
6
11
  *
7
- * The improve slice dispatches a `RunnerSpec` (`llm | agent | sdk`) in several
8
- * places (`reflect.ts`, `proposal/drain.ts`, …). Before this module each site
9
- * re-rolled the identical 3-arm switch and re-declared its own per-kind test
10
- * seams (`chat`, `runAgentFn`, `runSdkFn`). `executeRunner` collapses that into
11
- * one switch + one {@link RunnerSeams} object.
12
- *
13
- * Scoping (behavior-preserving):
14
- * - The `agent` and `sdk` arms are byte-identical across call sites: invoke
15
- * the profile runner (`runAgent` / `runOpencodeSdk`) with the per-call
16
- * `RunAgentOptions` the caller passes. Those default runners live here so
17
- * callers stop importing `runAgent` / `runOpencodeSdk` for dispatch. The
18
- * `opts` (incl. any `timeoutMs`) is constructed by the caller and passed
19
- * through unchanged, so each site keeps its exact option set.
20
- * - The `llm` arm is irreducibly caller-specific (reflect wraps
21
- * `runReflectViaLlm`, which returns reflect's iteration shape; drain wraps a
22
- * plain `chatCompletion`). It is therefore a REQUIRED seam — there is no
23
- * default `llm` handler — so neither caller's bespoke behavior is changed.
24
- * - The `assertNever` exhaustiveness arm is kept so a 4th `RunnerSpec` kind is
25
- * a compile error here instead of a silent runtime fall-through.
26
- *
27
- * The return type is {@link AgentRunResult} so a later `callStructured` layer
28
- * (X2) can wrap `executeRunner` without changing this contract.
12
+ * Agent and SDK arms use the shared profile runners. The LLM arm deliberately
13
+ * requires a handler because structured callers own their parse/fallback
14
+ * contract. The `assertNever` arm keeps a fourth transport kind from becoming
15
+ * an implicit fallthrough. Symbolic LLM and SDK-fallback credentials are
16
+ * materialized here, at authorized operation-lease acquisition or the final
17
+ * single-call boundary, then scrubbed from the result.
29
18
  */
30
19
  import { assertNever } from "../../core/assert.js";
31
20
  import { collectSensitiveValues, isEnvPassthroughValueSafeToExpose, redactSensitiveText, redactSensitiveValue, } from "../../core/redaction.js";
32
- import { closeServer as disposeOpencodeSdkServers, runOpencodeSdk } from "../harnesses/opencode-sdk/sdk-runner.js";
33
- import { materializeLlmConnection } from "./engine-resolution.js";
34
- import { materializeLlmRunnerConnection } from "./runner.js";
21
+ import { spawnEnvNamesFor } from "../../core/spawn-env.js";
22
+ import { closeServer as disposeOpencodeSdkServers, opencodeSdkServerEnvironmentNames, runOpencodeSdk, } from "../harnesses/opencode-sdk/sdk-runner.js";
23
+ import { lookupCredentialFromEnv, materializeLlmConnection, materializeLlmConnectionWithCredential, resolveCredentialFromEnv, } from "./engine-resolution.js";
24
+ import { materializeLlmRunnerConnection, materializeLlmRunnerConnectionWithCredential, } from "./runner.js";
35
25
  import { runAgent } from "./spawn.js";
26
+ const liveRunnerDispatchLeases = new WeakMap();
27
+ const issuedRunnerDispatchLeases = new WeakSet();
28
+ const disposedRunnerDispatchLeases = new WeakSet();
29
+ function credentialBinding(credential) {
30
+ return credential ? { names: [...credential.names], required: credential.required } : null;
31
+ }
32
+ function passthroughBinding(spec) {
33
+ return [...new Set(spec.profile.envPassthrough)].sort();
34
+ }
35
+ function dispatchEnvironmentNames(spec) {
36
+ switch (spec.kind) {
37
+ case "llm":
38
+ return [];
39
+ case "agent":
40
+ return spawnEnvNamesFor(spec.profile.envPassthrough);
41
+ case "sdk":
42
+ return opencodeSdkServerEnvironmentNames(spec.profile);
43
+ default:
44
+ return assertNever(spec);
45
+ }
46
+ }
47
+ function snapshotDispatchEnvironment(spec, envSource) {
48
+ const snapshot = new Map();
49
+ const read = (name) => {
50
+ if (!snapshot.has(name))
51
+ snapshot.set(name, envSource[name]);
52
+ return snapshot.get(name);
53
+ };
54
+ const environmentSource = new Proxy(Object.create(null), {
55
+ get(_target, property) {
56
+ return typeof property === "string" ? snapshot.get(property) : undefined;
57
+ },
58
+ });
59
+ for (const name of dispatchEnvironmentNames(spec))
60
+ read(name);
61
+ const passthroughSensitiveValues = new Set();
62
+ if (spec.kind !== "llm") {
63
+ for (const name of new Set(spec.profile.envPassthrough)) {
64
+ const value = snapshot.get(name);
65
+ if (!isEnvPassthroughValueSafeToExpose(name, value) && value)
66
+ passthroughSensitiveValues.add(value);
67
+ }
68
+ }
69
+ return { environmentSnapshot: snapshot, environmentSource, passthroughSensitiveValues, read };
70
+ }
71
+ /** Bind only transport identity; request model/inference/schema/timeout remain per-call. */
72
+ function runnerLeaseBinding(spec) {
73
+ switch (spec.kind) {
74
+ case "llm":
75
+ return JSON.stringify({
76
+ kind: spec.kind,
77
+ engine: spec.engine ?? null,
78
+ endpoint: spec.connection.endpoint,
79
+ provider: spec.connection.provider ?? null,
80
+ credential: credentialBinding(spec.credential),
81
+ });
82
+ case "agent":
83
+ return JSON.stringify({
84
+ kind: spec.kind,
85
+ engine: spec.engine ?? null,
86
+ platform: spec.profile.platform ?? null,
87
+ name: spec.profile.name,
88
+ bin: spec.profile.bin,
89
+ envPassthrough: passthroughBinding(spec),
90
+ });
91
+ case "sdk":
92
+ return JSON.stringify({
93
+ kind: spec.kind,
94
+ engine: spec.engine ?? null,
95
+ platform: spec.profile.platform ?? null,
96
+ name: spec.profile.name,
97
+ bin: spec.profile.bin,
98
+ envPassthrough: passthroughBinding(spec),
99
+ fallbackEndpoint: spec.fallbackConnection?.endpoint ?? null,
100
+ fallbackProvider: spec.fallbackConnection?.provider ?? null,
101
+ fallbackCredential: credentialBinding(spec.fallbackCredential),
102
+ });
103
+ default:
104
+ return assertNever(spec);
105
+ }
106
+ }
107
+ function requireRunnerDispatchLease(lease, spec) {
108
+ if (typeof lease !== "object" || lease === null)
109
+ throw new TypeError("invalid dispatch lease");
110
+ const state = liveRunnerDispatchLeases.get(lease);
111
+ if (!state) {
112
+ if (issuedRunnerDispatchLeases.has(lease) && disposedRunnerDispatchLeases.has(lease)) {
113
+ throw new TypeError("dispatch lease is disposed");
114
+ }
115
+ throw new TypeError("invalid dispatch lease");
116
+ }
117
+ if (spec && state.binding !== runnerLeaseBinding(spec)) {
118
+ throw new TypeError("dispatch lease does not match the lowered runner transport");
119
+ }
120
+ return state;
121
+ }
122
+ /** @internal Verify provenance, liveness, and transport binding without exposing state. */
123
+ export function assertRunnerDispatchLease(lease, spec) {
124
+ requireRunnerDispatchLease(lease, spec);
125
+ }
126
+ /** @internal Acquire only through execution-lowering after authorization/provenance validation. */
127
+ export function acquireRunnerDispatchLease(spec, envSource = process.env) {
128
+ const environment = snapshotDispatchEnvironment(spec, envSource);
129
+ const credentialSource = new Proxy(Object.create(null), {
130
+ get(_target, property) {
131
+ return typeof property === "string" ? environment.read(property) : undefined;
132
+ },
133
+ });
134
+ const primaryCredential = spec.kind === "llm" ? resolveCredentialFromEnv(spec.credential, credentialSource) : undefined;
135
+ const fallbackCredential = spec.kind === "sdk" ? resolveCredentialFromEnv(spec.fallbackCredential, credentialSource) : undefined;
136
+ const handle = Object.create(null);
137
+ Object.defineProperty(handle, "toJSON", {
138
+ configurable: false,
139
+ enumerable: false,
140
+ writable: false,
141
+ value: () => {
142
+ throw new TypeError("dispatch lease is not serializable");
143
+ },
144
+ });
145
+ Object.freeze(handle);
146
+ const sensitiveValues = collectSensitiveValues([
147
+ primaryCredential,
148
+ fallbackCredential,
149
+ ...environment.passthroughSensitiveValues,
150
+ ]);
151
+ liveRunnerDispatchLeases.set(handle, {
152
+ binding: runnerLeaseBinding(spec),
153
+ primaryCredential,
154
+ fallbackCredential,
155
+ environmentSnapshot: environment.environmentSnapshot,
156
+ environmentSource: environment.environmentSource,
157
+ sensitiveValues,
158
+ });
159
+ issuedRunnerDispatchLeases.add(handle);
160
+ return handle;
161
+ }
162
+ /** @internal Scrub private material and invalidate one issued handle. */
163
+ export function disposeRunnerDispatchLease(lease) {
164
+ if (typeof lease !== "object" || lease === null || !issuedRunnerDispatchLeases.has(lease)) {
165
+ throw new TypeError("invalid dispatch lease");
166
+ }
167
+ const state = liveRunnerDispatchLeases.get(lease);
168
+ if (!state)
169
+ return;
170
+ state.primaryCredential = undefined;
171
+ state.fallbackCredential = undefined;
172
+ state.environmentSnapshot.clear();
173
+ state.sensitiveValues.fill("");
174
+ state.sensitiveValues = [];
175
+ liveRunnerDispatchLeases.delete(lease);
176
+ disposedRunnerDispatchLeases.add(lease);
177
+ }
178
+ /** @internal Redact with private credential material without exposing its values. */
179
+ export function redactWithRunnerDispatchLease(lease, value) {
180
+ return redactSensitiveText(value, requireRunnerDispatchLease(lease).sensitiveValues);
181
+ }
36
182
  /**
37
183
  * Release every long-lived resource the dispatch runners CACHE for reuse, so a
38
184
  * one-shot process (the CLI) can exit cleanly once dispatching is done.
@@ -67,6 +213,10 @@ export function collectDispatchSensitiveValues(spec, opts, envSource = opts.envS
67
213
  addConnection(spec.connection);
68
214
  if (spec.kind === "sdk")
69
215
  addConnection(spec.fallbackConnection);
216
+ if (spec.kind === "llm")
217
+ add(lookupCredentialFromEnv(spec.credential, envSource));
218
+ if (spec.kind === "sdk")
219
+ add(lookupCredentialFromEnv(spec.fallbackCredential, envSource));
70
220
  if (spec.kind !== "llm") {
71
221
  for (const value of Object.values(spec.profile.env ?? {}))
72
222
  add(value);
@@ -82,6 +232,33 @@ export function collectDispatchSensitiveValues(spec, opts, envSource = opts.envS
82
232
  }
83
233
  return collectSensitiveValues(values);
84
234
  }
235
+ function collectNonCredentialDispatchSensitiveValues(spec, opts, envSource = opts.envSource ?? process.env, includeProfilePassthrough = true) {
236
+ const values = new Set();
237
+ const add = (value) => {
238
+ if (value !== undefined && value.length > 0)
239
+ values.add(value);
240
+ };
241
+ if (spec.kind === "llm")
242
+ add(spec.connection.apiKey);
243
+ if (spec.kind === "sdk")
244
+ add(spec.fallbackConnection?.apiKey);
245
+ if (spec.kind !== "llm") {
246
+ for (const value of Object.values(spec.profile.env ?? {}))
247
+ add(value);
248
+ if (includeProfilePassthrough) {
249
+ for (const name of spec.profile.envPassthrough) {
250
+ const value = envSource[name];
251
+ if (!isEnvPassthroughValueSafeToExpose(name, value))
252
+ add(value);
253
+ }
254
+ }
255
+ }
256
+ for (const [name, value] of Object.entries(opts.env ?? {})) {
257
+ if (!isEnvPassthroughValueSafeToExpose(name, value))
258
+ add(value);
259
+ }
260
+ return collectSensitiveValues(values);
261
+ }
85
262
  function redactResult(result, sensitiveValues) {
86
263
  return {
87
264
  ...result,
@@ -94,23 +271,33 @@ function redactResult(result, sensitiveValues) {
94
271
  /**
95
272
  * Dispatch a {@link RunnerSpec} to its runner and return the raw
96
273
  * {@link AgentRunResult}. `opts` is the {@link RunAgentOptions} for the profile
97
- * (`agent` / `sdk`) arms; it is passed through unchanged so each caller keeps
98
- * its exact option set (incl. any `timeoutMs` the caller chose to apply).
274
+ * (`agent` / `sdk`) arms. Callers keep their per-call options; a bound lease
275
+ * replaces only `envSource` with its private immutable environment snapshot.
99
276
  */
100
- export async function executeRunner(spec, prompt, opts, seams = {}) {
101
- const withSpecOptions = (timeoutMs, workspace) => ({
277
+ export async function executeRunner(spec, prompt, opts, seams = {}, lease) {
278
+ const withSpecOptions = (timeoutMs, workspace, environmentSource) => ({
102
279
  ...opts,
103
280
  ...(Object.hasOwn(opts, "timeoutMs") ? {} : timeoutMs !== undefined ? { timeoutMs } : {}),
104
281
  ...(opts.cwd === undefined && workspace ? { cwd: workspace } : {}),
282
+ ...(environmentSource ? { envSource: environmentSource } : {}),
105
283
  });
106
284
  let result;
107
285
  const dispatchSensitiveValues = [];
286
+ const leaseState = lease ? requireRunnerDispatchLease(lease, spec) : undefined;
287
+ const preDispatchSensitiveValues = leaseState
288
+ ? collectSensitiveValues([
289
+ ...leaseState.sensitiveValues,
290
+ ...collectNonCredentialDispatchSensitiveValues(spec, opts, undefined, false),
291
+ ])
292
+ : collectDispatchSensitiveValues(spec, opts);
108
293
  switch (spec.kind) {
109
294
  case "llm": {
110
295
  if (!seams.llm) {
111
296
  throw new Error("executeRunner: an `llm` runner requires a `seams.llm` handler (no default LLM dispatch).");
112
297
  }
113
- const connection = materializeLlmRunnerConnection(spec);
298
+ const connection = leaseState
299
+ ? materializeLlmRunnerConnectionWithCredential(spec, leaseState.primaryCredential)
300
+ : materializeLlmRunnerConnection(spec);
114
301
  if (connection.apiKey)
115
302
  dispatchSensitiveValues.push(connection.apiKey);
116
303
  result = await seams.llm({ ...spec, connection }, prompt, withSpecOptions(spec.timeoutMs));
@@ -118,13 +305,13 @@ export async function executeRunner(spec, prompt, opts, seams = {}) {
118
305
  }
119
306
  case "agent": {
120
307
  const run = seams.runAgent ?? runAgent;
121
- result = await run(spec.profile, prompt, withSpecOptions(spec.timeoutMs, spec.profile.workspace));
308
+ result = await run(spec.profile, prompt, withSpecOptions(spec.timeoutMs, spec.profile.workspace, leaseState?.environmentSource));
122
309
  break;
123
310
  }
124
311
  case "sdk": {
125
312
  const run = seams.runSdk ?? runOpencodeSdk;
126
- const fallbackConnection = spec.fallbackConnection
127
- ? materializeLlmConnection({
313
+ const fallbackMaterial = spec.fallbackConnection
314
+ ? {
128
315
  engine: spec.engine ?? "unnamed-sdk-fallback",
129
316
  connection: spec.fallbackConnection,
130
317
  ...(spec.fallbackCredential ? { credential: spec.fallbackCredential } : {}),
@@ -133,16 +320,22 @@ export async function executeRunner(spec, prompt, opts, seams = {}) {
133
320
  : Object.hasOwn(spec.fallbackConnection, "timeoutMs")
134
321
  ? (spec.fallbackConnection.timeoutMs ?? null)
135
322
  : null,
136
- })
323
+ }
324
+ : undefined;
325
+ const fallbackConnection = fallbackMaterial
326
+ ? leaseState
327
+ ? materializeLlmConnectionWithCredential(fallbackMaterial, leaseState.fallbackCredential)
328
+ : materializeLlmConnection(fallbackMaterial)
137
329
  : undefined;
138
330
  if (fallbackConnection?.apiKey)
139
331
  dispatchSensitiveValues.push(fallbackConnection.apiKey);
140
- result = await run(spec.profile, prompt, withSpecOptions(spec.timeoutMs, spec.profile.workspace), fallbackConnection);
332
+ result = await run(spec.profile, prompt, withSpecOptions(spec.timeoutMs, spec.profile.workspace, leaseState?.environmentSource), fallbackConnection);
141
333
  break;
142
334
  }
143
335
  default:
144
336
  // Exhaustiveness arm: a 4th RunnerSpec kind becomes a compile error here.
145
337
  return assertNever(spec);
146
338
  }
147
- return redactResult(result, [...collectDispatchSensitiveValues(spec, opts), ...dispatchSensitiveValues]);
339
+ const sensitiveValues = collectSensitiveValues([...preDispatchSensitiveValues, ...dispatchSensitiveValues]);
340
+ return redactResult(result, sensitiveValues);
148
341
  }
@@ -1,99 +1,28 @@
1
1
  // This Source Code Form is subject to the terms of the Mozilla Public
2
2
  // License, v. 2.0. If a copy of the MPL was not distributed with this
3
3
  // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
- import { ConfigError } from "../../core/errors.js";
5
- import { materializeLlmConnection, resolveEngine, resolveLlmEngineUse, } from "./engine-resolution.js";
6
- import { resolveModel } from "./model-aliases.js";
4
+ import { materializeLlmConnection, materializeLlmConnectionWithCredential, } from "./engine-resolution.js";
7
5
  /** Resolve the current credential value for one frozen LLM runner at dispatch. */
8
6
  export function materializeLlmRunnerConnection(runner) {
9
- const connectionWithLegacyTimeout = runner.connection;
10
- const timeoutMs = runner.timeoutMs !== undefined
11
- ? runner.timeoutMs
12
- : Object.hasOwn(connectionWithLegacyTimeout, "timeoutMs")
13
- ? (connectionWithLegacyTimeout.timeoutMs ?? null)
14
- : null;
15
7
  return materializeLlmConnection({
16
- engine: runner.engine ?? "unnamed",
8
+ engine: runner.engine,
17
9
  connection: runner.connection,
18
10
  ...(runner.credential ? { credential: runner.credential } : {}),
19
- timeoutMs,
11
+ timeoutMs: runner.timeoutMs ?? null,
20
12
  });
21
13
  }
14
+ /** Inject an already-snapshotted credential without consulting live process state. */
15
+ export function materializeLlmRunnerConnectionWithCredential(runner, credentialValue) {
16
+ return materializeLlmConnectionWithCredential({
17
+ engine: runner.engine,
18
+ connection: runner.connection,
19
+ ...(runner.credential ? { credential: runner.credential } : {}),
20
+ timeoutMs: runner.timeoutMs ?? null,
21
+ }, credentialValue);
22
+ }
22
23
  export function runnerIsLlm(runner) {
23
24
  return runner.kind === "llm";
24
25
  }
25
26
  export function runnerSupportsFileWrite(runner) {
26
27
  return runner.kind !== "llm";
27
28
  }
28
- /** Resolve the configured LLM default without ever consulting retired profiles. */
29
- export function resolveDefaultLlmRunner(config, timeoutMs) {
30
- const resolved = resolveLlmEngineUse(config, [], { optional: true });
31
- if (!resolved)
32
- return null;
33
- return {
34
- kind: "llm",
35
- engine: resolved.engine,
36
- connection: resolved.connection,
37
- ...(resolved.credential ? { credential: resolved.credential } : {}),
38
- ...(timeoutMs !== undefined ? { timeoutMs } : { timeoutMs: resolved.timeoutMs }),
39
- };
40
- }
41
- /** Resolve a triage judgment using judgment -> triage -> strategy -> defaults.llmEngine precedence. */
42
- export function resolveTriageJudgmentRunner(judgment, config, triage, strategy) {
43
- const layers = [strategy ?? {}, triage ?? {}, judgment ?? {}];
44
- const selectedEngine = judgment?.engine ?? triage?.engine ?? strategy?.engine ?? config.defaults?.llmEngine;
45
- if (selectedEngine) {
46
- const runner = resolveEngine(selectedEngine, config);
47
- if (runner.kind === "llm") {
48
- const resolved = resolveLlmEngineUse(config, layers);
49
- return {
50
- kind: "llm",
51
- engine: resolved.engine,
52
- connection: resolved.connection,
53
- ...(resolved.credential ? { credential: resolved.credential } : {}),
54
- timeoutMs: resolved.timeoutMs,
55
- };
56
- }
57
- const effectiveLlmOverrides = [...layers].reverse().find((layer) => layer.llm !== undefined)?.llm;
58
- if (effectiveLlmOverrides) {
59
- throw new ConfigError(`Triage judgment engine "${selectedEngine}" is an agent engine and cannot receive llm overrides.`, "INVALID_CONFIG_FILE");
60
- }
61
- const model = [...layers].reverse().find((layer) => layer.model !== undefined)?.model;
62
- const profile = model
63
- ? {
64
- ...runner.profile,
65
- model: resolveModel(model, runner.profile.platform ?? runner.profile.name, runner.profile.modelAliases, runner.profile.globalModelAliases),
66
- modelIsExact: true,
67
- }
68
- : runner.profile;
69
- const timeoutLayer = [...layers].reverse().find((layer) => Object.hasOwn(layer, "timeoutMs"));
70
- return {
71
- ...runner,
72
- profile,
73
- ...(timeoutLayer ? { timeoutMs: timeoutLayer.timeoutMs ?? null } : {}),
74
- };
75
- }
76
- return null;
77
- }
78
- export function resolveImproveProcessLlmUse(config, strategy, processName, options = {}) {
79
- const process = strategy?.processes?.[processName];
80
- const layers = strategy ? [strategy, process ?? {}] : [];
81
- return options.optional
82
- ? resolveLlmEngineUse(config, layers, { optional: true })
83
- : resolveLlmEngineUse(config, layers);
84
- }
85
- /** Resolve the LLM runner selected by an improve strategy and process without reading credentials. */
86
- export function resolveImproveProcessRunner(strategy, processName, config) {
87
- if (!strategy)
88
- return null;
89
- const resolved = resolveImproveProcessLlmUse(config, strategy, processName, { optional: true });
90
- if (!resolved)
91
- return null;
92
- return {
93
- kind: "llm",
94
- engine: resolved.engine,
95
- connection: resolved.connection,
96
- ...(resolved.credential ? { credential: resolved.credential } : {}),
97
- timeoutMs: resolved.timeoutMs,
98
- };
99
- }