akm-cli 0.9.17-alpha.2 → 0.9.17-alpha.4

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 (343) hide show
  1. package/CHANGELOG.md +756 -0
  2. package/dist/akm +94 -196
  3. package/dist/cli/shared.js +6 -2
  4. package/dist/cli.js +22 -9
  5. package/dist/commands/agent/agent-dispatch.js +1 -1
  6. package/dist/commands/command/command-execution.js +24 -62
  7. package/dist/commands/feedback-cli.js +0 -1
  8. package/dist/commands/health/accept-rate.js +2 -2
  9. package/dist/commands/health/checks.js +30 -75
  10. package/dist/commands/health/config-skew.js +38 -0
  11. package/dist/commands/health/egress.js +54 -0
  12. package/dist/commands/health/html-report.js +0 -38
  13. package/dist/commands/health/improve-metrics.js +123 -562
  14. package/dist/commands/health/plugin-staleness.js +53 -3
  15. package/dist/commands/health/renderers.js +12 -4
  16. package/dist/commands/health/report-view-model.js +11 -106
  17. package/dist/commands/health/types-improve.js +4 -19
  18. package/dist/commands/health/windows.js +64 -73
  19. package/dist/commands/health.js +122 -143
  20. package/dist/commands/improve/consolidate/chunking.js +25 -100
  21. package/dist/commands/improve/consolidate/sanitize.js +54 -149
  22. package/dist/commands/improve/consolidate.js +538 -1075
  23. package/dist/commands/improve/content-hash.js +16 -24
  24. package/dist/commands/improve/distill/content-repair.js +18 -100
  25. package/dist/commands/improve/distill-guards.js +20 -81
  26. package/dist/commands/improve/distill-promotion-policy.js +23 -243
  27. package/dist/commands/improve/distill.js +608 -1075
  28. package/dist/commands/improve/eligibility.js +126 -400
  29. package/dist/commands/improve/execution.js +3 -5
  30. package/dist/commands/improve/extract.js +487 -1046
  31. package/dist/commands/improve/feedback-valence.js +0 -25
  32. package/dist/commands/improve/improve-cli.js +29 -166
  33. package/dist/commands/improve/improve-result-file.js +10 -66
  34. package/dist/commands/improve/improve-strategies.js +12 -7
  35. package/dist/commands/improve/improve-usage-report.js +18 -64
  36. package/dist/commands/improve/improve.js +443 -1063
  37. package/dist/commands/improve/ledger.js +114 -0
  38. package/dist/commands/improve/locks.js +2 -8
  39. package/dist/commands/improve/loop-stages.js +459 -1172
  40. package/dist/commands/improve/memory/derived-ref.js +12 -77
  41. package/dist/commands/improve/memory/memory-belief.js +14 -118
  42. package/dist/commands/improve/memory/memory-improve.js +4 -3
  43. package/dist/commands/improve/outcome-loop.js +28 -156
  44. package/dist/commands/improve/planner.js +5 -10
  45. package/dist/commands/improve/preparation.js +851 -2339
  46. package/dist/commands/improve/proactive-maintenance.js +34 -101
  47. package/dist/commands/improve/reflect-noise.js +104 -280
  48. package/dist/commands/improve/reflect.js +621 -1367
  49. package/dist/commands/improve/salience.js +46 -232
  50. package/dist/commands/improve/session-asset.js +19 -100
  51. package/dist/commands/improve/stage.js +323 -0
  52. package/dist/commands/proposal/drain.js +251 -644
  53. package/dist/commands/proposal/proposal-cli.js +3 -18
  54. package/dist/commands/proposal/proposal-types.js +20 -41
  55. package/dist/commands/proposal/proposal.js +1 -2
  56. package/dist/commands/proposal/propose.js +134 -160
  57. package/dist/commands/proposal/repository.js +502 -1487
  58. package/dist/commands/proposal/validators/proposal-quality-validators.js +71 -174
  59. package/dist/commands/proposal/validators/proposal-validators.js +1 -1
  60. package/dist/commands/proposal/validators/proposals.js +13 -89
  61. package/dist/commands/read/curate.js +63 -413
  62. package/dist/commands/read/search-cli.js +16 -33
  63. package/dist/commands/read/search.js +17 -23
  64. package/dist/commands/read/show.js +2 -13
  65. package/dist/commands/sources/bundle-cli.js +25 -2
  66. package/dist/commands/sources/bundle-config-ops.js +7 -0
  67. package/dist/commands/sources/dangerous-env-audit.js +1 -2
  68. package/dist/commands/sources/info.js +2 -11
  69. package/dist/commands/sources/installed-stashes.js +197 -746
  70. package/dist/commands/sources/schema-repair.js +98 -129
  71. package/dist/commands/sources/source-add.js +62 -12
  72. package/dist/commands/sources/stash-cli.js +1 -1
  73. package/dist/commands/tasks/explain.js +10 -13
  74. package/dist/commands/tasks/tasks-cli.js +9 -8
  75. package/dist/commands/tasks/tasks.js +326 -930
  76. package/dist/commands/tasks/validate.js +42 -21
  77. package/dist/commands/workflow/plan.js +22 -29
  78. package/dist/commands/workflow-cli.js +4 -4
  79. package/dist/core/adapter/adapters/akm-adapter.js +0 -1
  80. package/dist/core/adapter/adapters/akm-lint.js +2 -3
  81. package/dist/core/adapter/adapters/akm-metadata.js +11 -12
  82. package/dist/core/adapter/adapters/akm-workflow-adapter.js +1 -1
  83. package/dist/core/adapter/execution-source.js +17 -29
  84. package/dist/core/asset/resolve-ref.js +1 -1
  85. package/dist/core/bundle-id.js +42 -5
  86. package/dist/core/bundle-rename.js +291 -0
  87. package/dist/core/config/config-io.js +1 -2
  88. package/dist/core/config/config-schema.js +1 -33
  89. package/dist/core/config/config-walker.js +1 -1
  90. package/dist/core/config/config.js +163 -68
  91. package/dist/core/config/legacy-source-shape-shim.js +38 -9
  92. package/dist/core/config/schema/embedding.js +20 -5
  93. package/dist/core/config/schema/engines.js +5 -0
  94. package/dist/core/config/schema/execution.js +1 -1
  95. package/dist/core/config/schema/experimental.js +1 -1
  96. package/dist/core/config/schema/improve-processes.js +21 -95
  97. package/dist/core/config/schema/improve.js +4 -42
  98. package/dist/core/config/schema/scheduler.js +12 -12
  99. package/dist/core/config/schema/search.js +6 -22
  100. package/dist/core/env-secret-ref.js +0 -1
  101. package/dist/core/errors.js +8 -9
  102. package/dist/core/file-lock.js +76 -173
  103. package/dist/core/logs-db.js +2 -2
  104. package/dist/core/paths.js +0 -27
  105. package/dist/core/redaction.js +109 -2
  106. package/dist/core/run-lock.js +2 -5
  107. package/dist/core/spawn-env.js +1 -1
  108. package/dist/core/state/migrations.js +108 -61
  109. package/dist/core/state-db-scope.js +2 -4
  110. package/dist/core/state-db.js +126 -692
  111. package/dist/core/type-presentation.js +1 -9
  112. package/dist/core/write-source.js +293 -1012
  113. package/dist/execution/input-contract.js +1 -1
  114. package/dist/execution/resolved-request.js +135 -689
  115. package/dist/execution/source.js +63 -257
  116. package/dist/execution/target-ref.js +1 -1
  117. package/dist/indexer/bundle-identity-guard.js +2 -2
  118. package/dist/indexer/db/graph-db.js +106 -46
  119. package/dist/indexer/ensure-index.js +44 -85
  120. package/dist/indexer/graph/graph-extraction.js +340 -562
  121. package/dist/indexer/graph/graph-related.js +130 -0
  122. package/dist/indexer/index-rebuild-lock.js +3 -11
  123. package/dist/indexer/index-writer-lock.js +8 -17
  124. package/dist/indexer/index-written-assets.js +139 -151
  125. package/dist/indexer/indexer.js +524 -846
  126. package/dist/indexer/materialize-embeddings.js +60 -397
  127. package/dist/indexer/passes/memory-inference.js +81 -90
  128. package/dist/indexer/passes/metadata.js +132 -200
  129. package/dist/indexer/read-preflight.js +0 -7
  130. package/dist/indexer/scan/doc-to-entry.js +1 -3
  131. package/dist/indexer/scan/drain-dir.js +1 -1
  132. package/dist/indexer/search/db-search.js +181 -590
  133. package/dist/indexer/search/fts-query.js +30 -41
  134. package/dist/indexer/search/ranking.js +28 -154
  135. package/dist/indexer/search/search-attribution.js +12 -32
  136. package/dist/indexer/search/search-fields.js +11 -15
  137. package/dist/indexer/search/search-hit-enrichers.js +54 -85
  138. package/dist/indexer/search/search-source.js +1 -4
  139. package/dist/indexer/usage/usage-events.js +2 -7
  140. package/dist/integrations/agent/engine-fallback.js +23 -40
  141. package/dist/integrations/agent/engine-resolution.js +93 -183
  142. package/dist/integrations/agent/execution.js +507 -0
  143. package/dist/integrations/agent/model-map.js +28 -156
  144. package/dist/integrations/agent/request-lowering.js +66 -141
  145. package/dist/integrations/agent/runner-dispatch.js +143 -321
  146. package/dist/integrations/agent/runner.js +54 -14
  147. package/dist/integrations/lockfile.js +53 -101
  148. package/dist/llm/embedders/deterministic.js +2 -3
  149. package/dist/llm/embedders/profile.js +71 -0
  150. package/dist/llm/embedders/remote.js +10 -15
  151. package/dist/llm/graph-extract.js +3 -12
  152. package/dist/llm/index-passes.js +3 -5
  153. package/dist/llm/memory-infer.js +1 -2
  154. package/dist/llm/metadata-enhance.js +1 -2
  155. package/dist/llm/structured-call.js +5 -24
  156. package/dist/output/generic-render.js +23 -11
  157. package/dist/output/html-render.js +13 -10
  158. package/dist/output/render-registry.js +3 -32
  159. package/dist/output/shapes/helpers.js +2 -34
  160. package/dist/output/shapes/passthrough.js +1 -9
  161. package/dist/{indexer/search/ranking-types.js → output/text/bundle-rename.js} +4 -1
  162. package/dist/output/text/command-format.js +60 -23
  163. package/dist/output/text/helpers.js +1 -1
  164. package/dist/output/text/migrate.js +5 -14
  165. package/dist/output/text/proposal-format.js +1 -2
  166. package/dist/output/text/workflow-format.js +0 -32
  167. package/dist/output/text.js +2 -0
  168. package/dist/registry/factory.js +4 -19
  169. package/dist/registry/network.js +66 -220
  170. package/dist/registry/providers/index.js +0 -2
  171. package/dist/registry/providers/skills-sh.js +3 -14
  172. package/dist/registry/providers/static-index.js +24 -26
  173. package/dist/registry/resolve.js +55 -131
  174. package/dist/scripts/akm-migrate-node.js +43937 -93313
  175. package/dist/scripts/akm-migrate.js +43697 -93071
  176. package/dist/setup/registry-stash-loader.js +4 -13
  177. package/dist/setup/semantic-assets.js +3 -44
  178. package/dist/setup/setup.js +1 -1
  179. package/dist/setup/steps/tasks.js +25 -15
  180. package/dist/sources/provider-factory.js +17 -18
  181. package/dist/sources/providers/filesystem.js +2 -3
  182. package/dist/sources/providers/git-install.js +7 -1
  183. package/dist/sources/providers/git-provider.js +0 -3
  184. package/dist/sources/providers/git-stash.js +0 -17
  185. package/dist/sources/providers/npm.js +2 -4
  186. package/dist/sources/providers/provider-utils.js +5 -10
  187. package/dist/sources/providers/website.js +0 -2
  188. package/dist/sources/snapshot-fetchers/website-ingest.js +1 -1
  189. package/dist/sources/website-url.js +2 -2
  190. package/dist/storage/database.js +9 -35
  191. package/dist/storage/repositories/improve-ledger-repository.js +168 -0
  192. package/dist/storage/repositories/index-connection.js +34 -70
  193. package/dist/storage/repositories/index-entries-repository.js +69 -111
  194. package/dist/storage/repositories/index-entry-mapper.js +1 -2
  195. package/dist/storage/repositories/index-entry-schema.js +83 -269
  196. package/dist/storage/repositories/index-fts-repository.js +86 -256
  197. package/dist/storage/repositories/index-llm-cache-repository.js +17 -0
  198. package/dist/storage/repositories/index-meta-repository.js +6 -4
  199. package/dist/storage/repositories/index-schema.js +192 -220
  200. package/dist/storage/repositories/index-utility-repository.js +8 -29
  201. package/dist/storage/repositories/index-vec-repository.js +133 -414
  202. package/dist/storage/repositories/outcome-repository.js +2 -1
  203. package/dist/storage/repositories/proposals-repository.js +35 -0
  204. package/dist/storage/repositories/registry-index-cache-repository.js +100 -0
  205. package/dist/storage/repositories/task-history-repository.js +26 -4
  206. package/dist/storage/repositories/workflow-runs-repository.js +53 -244
  207. package/dist/storage/sqlite-migrations.js +136 -0
  208. package/dist/storage/sqlite-pragmas.js +11 -9
  209. package/dist/storage/sqlite-transaction.js +170 -0
  210. package/dist/storage/state-db-integrity.js +34 -27
  211. package/dist/tasks/activation-config.js +134 -62
  212. package/dist/tasks/backends/cron.js +129 -277
  213. package/dist/tasks/backends/exec-utils.js +2 -5
  214. package/dist/tasks/backends/launchd.js +125 -745
  215. package/dist/tasks/backends/schtasks.js +101 -620
  216. package/dist/tasks/prepare/prepare-support.js +5 -15
  217. package/dist/tasks/prepare/prepare.js +0 -2
  218. package/dist/tasks/resolve-akm-bin.js +20 -79
  219. package/dist/tasks/run/attempt-lifecycle.js +0 -1
  220. package/dist/tasks/scheduler-binding.js +18 -238
  221. package/dist/tasks/scheduler-invocation.js +52 -52
  222. package/dist/tasks/scheduler-lock.js +53 -0
  223. package/dist/tasks/scheduler-sync.js +363 -679
  224. package/dist/tasks/source/parse-task-source.js +160 -10
  225. package/dist/tasks/source/task-source-v3-frozen.js +3 -4
  226. package/dist/tasks/source/task-to-v4.js +2 -2
  227. package/dist/workflows/authoring/authoring.js +3 -12
  228. package/dist/workflows/compile.js +211 -0
  229. package/dist/workflows/concurrency-policy.js +13 -74
  230. package/dist/workflows/exec/child-invocation.js +3 -17
  231. package/dist/workflows/exec/child-workflow.js +32 -141
  232. package/dist/workflows/exec/dispatch-redaction.js +13 -53
  233. package/dist/workflows/exec/environment.js +98 -0
  234. package/dist/workflows/exec/exec-unit.js +33 -140
  235. package/dist/workflows/exec/frozen-judge.js +7 -59
  236. package/dist/workflows/exec/native-executor.js +82 -341
  237. package/dist/workflows/exec/param-secrets.js +29 -47
  238. package/dist/workflows/exec/run-workflow.js +154 -387
  239. package/dist/workflows/exec/scheduler.js +9 -36
  240. package/dist/workflows/exec/step-work.js +127 -430
  241. package/dist/workflows/exec/unit-dispatch.js +11 -63
  242. package/dist/workflows/exec/unit-writer.js +8 -52
  243. package/dist/workflows/exec/worktree.js +39 -273
  244. package/dist/workflows/freeze/child-output-references.js +4 -15
  245. package/dist/workflows/freeze/environment.js +99 -92
  246. package/dist/workflows/freeze/freeze.js +172 -0
  247. package/dist/workflows/freeze/step-values.js +19 -21
  248. package/dist/workflows/freeze/targets/child-workflow.js +23 -92
  249. package/dist/workflows/freeze/targets/command.js +10 -33
  250. package/dist/workflows/freeze/targets/script.js +5 -12
  251. package/dist/workflows/freeze/targets/shell.js +3 -6
  252. package/dist/workflows/freeze/targets/task.js +25 -80
  253. package/dist/workflows/freeze/task-bindings.js +20 -67
  254. package/dist/workflows/{source-ir/github-yaml.js → github-yaml.js} +88 -206
  255. package/dist/workflows/ir/params.js +6 -51
  256. package/dist/workflows/ir/plan-hash.js +2 -34
  257. package/dist/workflows/parser.js +140 -43
  258. package/dist/{commands/improve/consolidate/types.js → workflows/plan.js} +2 -1
  259. package/dist/workflows/renderer.js +36 -69
  260. package/dist/workflows/resource-limits.js +12 -120
  261. package/dist/workflows/runtime/agent-identity.js +8 -40
  262. package/dist/workflows/runtime/run-outputs.js +3 -6
  263. package/dist/workflows/runtime/run-plan.js +316 -0
  264. package/dist/workflows/runtime/runs.js +48 -200
  265. package/dist/workflows/runtime/workflow-asset-loader.js +24 -57
  266. package/dist/workflows/{source-ir/semantics.js → source-semantics.js} +16 -20
  267. package/dist/workflows/validate-summary.js +2 -7
  268. package/docs/integration/bundling-akm.md +49 -42
  269. package/docs/migration/README.md +1 -0
  270. package/docs/migration/release-notes/0.9.17.md +41 -0
  271. package/docs/migration/v0.9.1-to-v0.9.2.md +19 -7
  272. package/docs/reference/cli.md +182 -125
  273. package/docs/reference/configuration.md +49 -56
  274. package/docs/reference/data-and-telemetry.md +19 -20
  275. package/docs/reference/tasks.md +86 -38
  276. package/docs/reference/workflow-schema.md +14 -18
  277. package/docs/reference/workflows.md +6 -9
  278. package/package.json +1 -1
  279. package/schemas/akm-config.json +87 -406
  280. package/dist/commands/health/advisories.js +0 -150
  281. package/dist/commands/health/metrics.js +0 -329
  282. package/dist/commands/health/surfaces.js +0 -102
  283. package/dist/commands/improve/anti-collapse.js +0 -83
  284. package/dist/commands/improve/collapse-detector.js +0 -432
  285. package/dist/commands/improve/consolidate/eligibility.js +0 -48
  286. package/dist/commands/improve/consolidate/merge.js +0 -146
  287. package/dist/commands/improve/distill/promote-memory.js +0 -329
  288. package/dist/commands/improve/distill/quality-gate.js +0 -500
  289. package/dist/commands/improve/memory/memory-contradiction-detect.js +0 -291
  290. package/dist/commands/improve/proposal-envelope.js +0 -31
  291. package/dist/commands/improve/run-context.js +0 -123
  292. package/dist/commands/improve/shared.js +0 -21
  293. package/dist/commands/improve/source-identity.js +0 -28
  294. package/dist/commands/improve/triage.js +0 -96
  295. package/dist/commands/proposal/drain-policies.js +0 -151
  296. package/dist/commands/sources/update-transaction.js +0 -220
  297. package/dist/core/action-contributors.js +0 -28
  298. package/dist/core/config/config-version-shim.js +0 -101
  299. package/dist/core/config/retired-experimental-keys-shim.js +0 -62
  300. package/dist/core/fs-txn.js +0 -405
  301. package/dist/core/lexical-score.js +0 -25
  302. package/dist/core/maintenance-barrier.js +0 -167
  303. package/dist/execution/executable-identity.js +0 -105
  304. package/dist/execution/guarded-source.js +0 -427
  305. package/dist/indexer/graph/graph-boost.js +0 -427
  306. package/dist/indexer/graph/graph-dedup.js +0 -95
  307. package/dist/indexer/search/name-match.js +0 -35
  308. package/dist/indexer/search/ranking-contributors.js +0 -515
  309. package/dist/indexer/walk/project-context.js +0 -192
  310. package/dist/integrations/agent/execution-cascade.js +0 -566
  311. package/dist/integrations/agent/execution-definitions.js +0 -202
  312. package/dist/integrations/agent/execution-lowering.js +0 -841
  313. package/dist/integrations/agent/execution-preparation.js +0 -98
  314. package/dist/integrations/agent/inline-execution.js +0 -74
  315. package/dist/registry/create-provider-registry.js +0 -29
  316. package/dist/registry/pinned-request-helper.js +0 -247
  317. package/dist/registry/pinned-transport.js +0 -717
  318. package/dist/sources/providers/index.js +0 -14
  319. package/dist/storage/engines/sqlite-migrations.js +0 -271
  320. package/dist/storage/repositories/canaries-repository.js +0 -107
  321. package/dist/storage/repositories/embedding-salvage-repository.js +0 -184
  322. package/dist/storage/repositories/registry-cache.js +0 -113
  323. package/dist/tasks/scheduler-sync-preview.js +0 -52
  324. package/dist/workflows/freeze/resolve-steps.js +0 -86
  325. package/dist/workflows/freeze/source-freeze.js +0 -64
  326. package/dist/workflows/ir/compile.js +0 -321
  327. package/dist/workflows/ir/environment-v4.js +0 -330
  328. package/dist/workflows/ir/freeze-v4.js +0 -153
  329. package/dist/workflows/ir/schema-v4.js +0 -745
  330. package/dist/workflows/ir/schema.js +0 -354
  331. package/dist/workflows/program/schema.js +0 -78
  332. package/dist/workflows/runtime/checkin.js +0 -57
  333. package/dist/workflows/runtime/plan-classifier.js +0 -196
  334. package/dist/workflows/runtime/unit-checkin.js +0 -45
  335. package/dist/workflows/runtime/unit-phases.js +0 -20
  336. package/dist/workflows/schema.js +0 -4
  337. package/dist/workflows/source-ir/compile.js +0 -200
  338. package/dist/workflows/source-ir/program.js +0 -50
  339. package/dist/workflows/source-ir/result.js +0 -26
  340. package/dist/workflows/source-ir/schema.js +0 -786
  341. package/dist/workflows/source-ir/triggers.js +0 -79
  342. package/dist/workflows/source-ir/uses.js +0 -40
  343. package/dist/workflows/validator.js +0 -60
@@ -1,841 +0,0 @@
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, UsageError } from "../../core/errors.js";
5
- import { cloneExecutionJsonObject } from "../../execution/json.js";
6
- import { EXECUTION_MAX_TIMEOUT_MS } from "../../execution/limits.js";
7
- import { assertSnapshotKeys, snapshotStrictRecord } from "../../execution/record.js";
8
- import { canonicalResolvedExecutionRequest, } from "../../execution/resolved-request.js";
9
- import { chatCompletion, LlmCallError, } from "../../llm/client.js";
10
- import { HARNESS_REGISTRY } from "../harnesses/index.js";
11
- import { resolveEngine } from "./engine-resolution.js";
12
- import { SDK_FALLBACK_MODEL_FROM_REQUEST_SETTING } from "./execution-definitions.js";
13
- import { acquireRunnerDispatchLease, assertRunnerDispatchLease, disposeRunnerDispatchLease, executeRunner, redactWithRunnerDispatchLease, } from "./runner-dispatch.js";
14
- export const EXECUTION_LOWERING_SCHEMA_VERSION = 1;
15
- const loweredExecutionInstances = new WeakSet();
16
- function registerLoweredExecution(value) {
17
- const frozen = Object.freeze(value);
18
- loweredExecutionInstances.add(frozen);
19
- return frozen;
20
- }
21
- function own(value, key) {
22
- return Object.hasOwn(value, key);
23
- }
24
- function sterileRecord(value) {
25
- return Object.assign(Object.create(null), value);
26
- }
27
- function sortedUnique(values) {
28
- return Object.freeze([...new Set(values)].sort());
29
- }
30
- function freezeNotices(values) {
31
- return Object.freeze([...values]);
32
- }
33
- const SAFE_ENGINE_FALLBACK_NOTICE = Object.freeze({
34
- code: "engine-fallback",
35
- severity: "info",
36
- adapter: "akm",
37
- field: "engine",
38
- message: "No engine was selected; using the fixed opencode-sdk fallback.",
39
- });
40
- const UNRECOGNIZED_REQUEST_NOTICE = Object.freeze({
41
- code: "unrecognized-request-notice",
42
- severity: "warning",
43
- adapter: "akm",
44
- message: "An unrecognized durable execution notice was omitted at the engine lowering boundary.",
45
- });
46
- /** Reconstruct durable/untrusted notices without forwarding message/details bytes. */
47
- function safeRequestNotices(request) {
48
- let fallback = false;
49
- let unknown = false;
50
- for (const notice of request.notices) {
51
- if (notice.code === "engine-fallback")
52
- fallback = true;
53
- else
54
- unknown = true;
55
- }
56
- return Object.freeze([
57
- ...(fallback ? [SAFE_ENGINE_FALLBACK_NOTICE] : []),
58
- ...(unknown ? [UNRECOGNIZED_REQUEST_NOTICE] : []),
59
- ]);
60
- }
61
- function untranslatedNotice(adapter, field) {
62
- return Object.freeze({
63
- code: "untranslated-field",
64
- severity: "warning",
65
- adapter,
66
- field,
67
- message: `The ${adapter} lowerer does not translate resolved field ${field}; dispatch will continue optimistically.`,
68
- });
69
- }
70
- function requireAuthorizedRequest(request) {
71
- // The canonical round trip is the public brand/prototype/accessor guard. It
72
- // deliberately happens before config or registry access.
73
- canonicalResolvedExecutionRequest(request);
74
- if (request.authorization.status === "denied") {
75
- throw new ConfigError(request.authorization.reason ?? "Resolved execution is not authorized by operator policy.", "EXECUTION_NOT_AUTHORIZED");
76
- }
77
- return request;
78
- }
79
- function snapshotConfig(config) {
80
- return cloneExecutionJsonObject(config, "execution lowering config");
81
- }
82
- function assertKeys(value, allowed, path) {
83
- const allowedKeys = new Set(allowed);
84
- for (const key of Object.keys(value)) {
85
- if (!allowedKeys.has(key))
86
- throw new TypeError(`${path} contains unsupported field: ${key}`);
87
- }
88
- }
89
- function requireStringField(value, key, path) {
90
- const field = value[key];
91
- if (typeof field !== "string")
92
- throw new TypeError(`${path}.${key} must be a string`);
93
- return field;
94
- }
95
- function validateOptionalString(value, key, path) {
96
- if (own(value, key) && typeof value[key] !== "string")
97
- throw new TypeError(`${path}.${key} must be a string`);
98
- }
99
- function validateTimeout(value, path) {
100
- if (value !== null &&
101
- (typeof value !== "number" || !Number.isInteger(value) || value < 0 || value > EXECUTION_MAX_TIMEOUT_MS)) {
102
- throw new TypeError(`${path} must be null or an integer from 0 through ${EXECUTION_MAX_TIMEOUT_MS}`);
103
- }
104
- }
105
- function validateStringArray(value, path, allowEmpty = true) {
106
- if (!Array.isArray(value) ||
107
- (!allowEmpty && value.length === 0) ||
108
- value.some((entry) => typeof entry !== "string")) {
109
- throw new TypeError(`${path} must be ${allowEmpty ? "an" : "a non-empty"} array of strings`);
110
- }
111
- }
112
- function validateCredential(value, path) {
113
- if (value === null || typeof value !== "object" || Array.isArray(value))
114
- throw new TypeError(`${path} must be an object`);
115
- const record = value;
116
- assertKeys(record, ["names", "required"], path);
117
- validateStringArray(record.names, `${path}.names`, false);
118
- if (typeof record.required !== "boolean")
119
- throw new TypeError(`${path}.required must be a boolean`);
120
- }
121
- function validateConnection(value, path, requireModel = true) {
122
- if (value === null || typeof value !== "object" || Array.isArray(value))
123
- throw new TypeError(`${path} must be an object`);
124
- const record = value;
125
- requireStringField(record, "endpoint", path);
126
- if (requireModel || own(record, "model"))
127
- requireStringField(record, "model", path);
128
- if (own(record, "apiKey")) {
129
- throw new TypeError(`${path}.apiKey must remain a symbolic credential and cannot be frozen as secret material`);
130
- }
131
- }
132
- function validateProfile(value, path) {
133
- if (value === null || typeof value !== "object" || Array.isArray(value))
134
- throw new TypeError(`${path} must be an object`);
135
- const record = value;
136
- assertKeys(record, [
137
- "name",
138
- "platform",
139
- "personaChannel",
140
- "workspace",
141
- "bin",
142
- "args",
143
- "stdio",
144
- "env",
145
- "envPassthrough",
146
- "parseOutput",
147
- "model",
148
- ], path);
149
- requireStringField(record, "name", path);
150
- requireStringField(record, "bin", path);
151
- validateOptionalString(record, "platform", path);
152
- validateOptionalString(record, "workspace", path);
153
- validateOptionalString(record, "model", path);
154
- validateStringArray(record.args, `${path}.args`);
155
- validateStringArray(record.envPassthrough, `${path}.envPassthrough`);
156
- if (record.stdio !== "captured" && record.stdio !== "interactive") {
157
- throw new TypeError(`${path}.stdio is invalid`);
158
- }
159
- if (record.parseOutput !== "text" && record.parseOutput !== "json") {
160
- throw new TypeError(`${path}.parseOutput is invalid`);
161
- }
162
- if (own(record, "personaChannel") && record.personaChannel !== "native" && record.personaChannel !== "prompt") {
163
- throw new TypeError(`${path}.personaChannel is invalid`);
164
- }
165
- if (own(record, "env")) {
166
- const env = record.env;
167
- if (env === null ||
168
- typeof env !== "object" ||
169
- Array.isArray(env) ||
170
- Object.values(env).some((entry) => typeof entry !== "string")) {
171
- throw new TypeError(`${path}.env must be an object of strings`);
172
- }
173
- }
174
- }
175
- /** Durable runner material may contain ordinary literals, never credential-shaped bytes. */
176
- function runnerEnvironmentValueLooksSecret(name, value) {
177
- const key = name.toLowerCase();
178
- if ([
179
- "secret",
180
- "token",
181
- "password",
182
- "passwd",
183
- "apikey",
184
- "api_key",
185
- "api-key",
186
- "accesskey",
187
- "access_key",
188
- "privatekey",
189
- "private_key",
190
- "credential",
191
- "bearer",
192
- "client_secret",
193
- ].some((hint) => key.includes(hint))) {
194
- return true;
195
- }
196
- const candidate = value.trim();
197
- if (candidate.length < 20 || /\s/.test(candidate))
198
- return false;
199
- if (/^(?:sk-|rk-|ghp_|gho_|ghu_|ghs_|ghr_|github_pat_|xox[baprs]-|AKIA|ASIA|AIza|ya29\.|-----BEGIN)/.test(candidate)) {
200
- return true;
201
- }
202
- const classes = [/[a-z]/, /[A-Z]/, /[0-9]/, /[^A-Za-z0-9]/].filter((pattern) => pattern.test(candidate)).length;
203
- return (candidate.length >= 24 && classes >= 3) || (candidate.length >= 32 && /^[A-Za-z0-9+/=_-]+$/.test(candidate));
204
- }
205
- /** Strictly detach and deep-freeze non-secret runner material before lowering. */
206
- function snapshotRunnerSpec(input, options = {}) {
207
- const cloned = cloneExecutionJsonObject(input, "execution runner material");
208
- const kind = cloned.kind;
209
- validateOptionalString(cloned, "engine", "execution runner material");
210
- if (own(cloned, "timeoutMs"))
211
- validateTimeout(cloned.timeoutMs, "execution runner material.timeoutMs");
212
- if (kind === "llm") {
213
- assertKeys(cloned, ["kind", "engine", "connection", "credential", "apiKeyFile", "apiKeySecretRef", "timeoutMs"], "execution runner material");
214
- validateConnection(cloned.connection, "execution runner material.connection", !options.allowMissingLlmModel);
215
- if (own(cloned, "credential"))
216
- validateCredential(cloned.credential, "execution runner material.credential");
217
- // #905: a path, not the secret itself — as safe to freeze as `credential`'s
218
- // env-var name.
219
- validateOptionalString(cloned, "apiKeyFile", "execution runner material");
220
- // #953: a `secret://<name>` reference, not the secret itself — same
221
- // freeze-safety rationale as apiKeyFile above.
222
- validateOptionalString(cloned, "apiKeySecretRef", "execution runner material");
223
- }
224
- else if (kind === "agent") {
225
- assertKeys(cloned, ["kind", "engine", "profile", "timeoutMs"], "execution runner material");
226
- validateProfile(cloned.profile, "execution runner material.profile");
227
- }
228
- else if (kind === "sdk") {
229
- assertKeys(cloned, [
230
- "kind",
231
- "engine",
232
- "profile",
233
- "fallbackConnection",
234
- "fallbackCredential",
235
- "fallbackApiKeyFile",
236
- "fallbackApiKeySecretRef",
237
- "fallbackTimeoutMs",
238
- "timeoutMs",
239
- ], "execution runner material");
240
- validateProfile(cloned.profile, "execution runner material.profile");
241
- if (own(cloned, "fallbackConnection")) {
242
- validateConnection(cloned.fallbackConnection, "execution runner material.fallbackConnection", !options.allowMissingSdkFallbackModel);
243
- }
244
- if (own(cloned, "fallbackCredential")) {
245
- validateCredential(cloned.fallbackCredential, "execution runner material.fallbackCredential");
246
- }
247
- validateOptionalString(cloned, "fallbackApiKeyFile", "execution runner material");
248
- validateOptionalString(cloned, "fallbackApiKeySecretRef", "execution runner material");
249
- if (own(cloned, "fallbackTimeoutMs")) {
250
- validateTimeout(cloned.fallbackTimeoutMs, "execution runner material.fallbackTimeoutMs");
251
- }
252
- }
253
- else {
254
- throw new TypeError("execution runner material.kind must be llm, agent, or sdk");
255
- }
256
- return cloned;
257
- }
258
- /** Strict public decoder for persisted, non-secret runner/transport material. */
259
- export function decodeFrozenRunnerSpec(input) {
260
- const runner = snapshotRunnerSpec(input);
261
- if (runner.kind !== "llm") {
262
- for (const [name, value] of Object.entries(runner.profile.env ?? {})) {
263
- if (runnerEnvironmentValueLooksSecret(name, value)) {
264
- throw new TypeError("execution runner material.profile.env contains a secret-shaped literal; freeze only symbolic environment names");
265
- }
266
- }
267
- }
268
- return runner;
269
- }
270
- function lowererEntries() {
271
- return HARNESS_REGISTRY.map((harness) => {
272
- const lowerer = harness.agentBuilder?.lower !== undefined
273
- ? {
274
- platform: harness.agentBuilder.platform,
275
- personaChannel: harness.agentBuilder.personaChannel,
276
- lower: harness.agentBuilder.lower,
277
- }
278
- : harness.executionLowerer;
279
- if (!lowerer) {
280
- throw new Error(`dispatch harness ${harness.id} has no registered resolved-request lowerer`);
281
- }
282
- if (lowerer.platform !== harness.id) {
283
- throw new Error(`dispatch harness ${harness.id} registered mismatched lowerer ${lowerer.platform}`);
284
- }
285
- return [harness.id, lowerer];
286
- });
287
- }
288
- const AGENT_LOWERERS = new Map(lowererEntries());
289
- function requireRunnerShape(request, runner) {
290
- if (!own(runner, "engine") || runner.engine !== request.engine.name) {
291
- throw new ConfigError(`Resolved engine ${JSON.stringify(request.engine.name)} changed engine identity before lowering.`, "INVALID_CONFIG_FILE");
292
- }
293
- if (request.engine.kind !== runner.kind) {
294
- throw new ConfigError(`Resolved engine ${JSON.stringify(request.engine.name)} changed transport kind before lowering.`, "INVALID_CONFIG_FILE");
295
- }
296
- const platform = own(request.engine, "platform") ? request.engine.platform : undefined;
297
- const runnerPlatform = runner.kind === "llm"
298
- ? (runner.connection.provider ?? runner.engine)
299
- : (runner.profile.platform ?? runner.profile.name);
300
- // A selected platform is an identity binding rather than a capability hint.
301
- if (typeof platform === "string" && platform !== runnerPlatform) {
302
- throw new ConfigError(`Resolved engine ${JSON.stringify(request.engine.name)} changed provider/harness platform before lowering.`, "INVALID_CONFIG_FILE");
303
- }
304
- }
305
- const LLM_CALL_ERROR_CODES = new Set([
306
- "aborted",
307
- "timeout",
308
- "rate_limited",
309
- "parse_error",
310
- "provider_html_error",
311
- "network_error",
312
- "provider_error",
313
- ]);
314
- function safeLlmCallErrorCode(error) {
315
- if (!(error instanceof LlmCallError))
316
- return undefined;
317
- const descriptor = Reflect.getOwnPropertyDescriptor(error, "code");
318
- if (!descriptor || !("value" in descriptor) || !LLM_CALL_ERROR_CODES.has(descriptor.value)) {
319
- return undefined;
320
- }
321
- return descriptor.value;
322
- }
323
- function directLlmFailure(error) {
324
- const code = safeLlmCallErrorCode(error);
325
- if (!code)
326
- return { reason: "spawn_failed" };
327
- switch (code) {
328
- case "aborted":
329
- return { reason: "aborted", code };
330
- case "timeout":
331
- return { reason: "timeout", code };
332
- case "rate_limited":
333
- return { reason: "llm_rate_limit", code };
334
- case "parse_error":
335
- case "provider_html_error":
336
- return { reason: "parse_error", code };
337
- case "network_error":
338
- case "provider_error":
339
- return { reason: "spawn_failed", code };
340
- }
341
- }
342
- function safeCaughtErrorMessage(error) {
343
- if (typeof error === "string")
344
- return error;
345
- if (error instanceof Error) {
346
- const descriptor = Reflect.getOwnPropertyDescriptor(error, "message");
347
- if (descriptor && "value" in descriptor && typeof descriptor.value === "string")
348
- return descriptor.value;
349
- }
350
- if (error === null || error === undefined || typeof error === "number" || typeof error === "boolean") {
351
- return String(error);
352
- }
353
- return "LLM transport failed.";
354
- }
355
- function requestRuntimeOptions(request) {
356
- const options = sterileRecord({ stdio: "captured", parseOutput: "text" });
357
- if (own(request.runtime, "timeoutMs"))
358
- options.timeoutMs = request.runtime.timeoutMs;
359
- if (own(request.runtime, "workspace") && typeof request.runtime.workspace === "string") {
360
- options.cwd = request.runtime.workspace;
361
- }
362
- if (own(request.runtime, "environment") && request.runtime.environment !== null) {
363
- options.env = request.runtime.environment;
364
- }
365
- return Object.freeze(options);
366
- }
367
- function projectAgentRunner(base, request) {
368
- const settings = own(request.engine, "settings") ? request.engine.settings : undefined;
369
- const profile = sterileRecord({ ...base.profile });
370
- delete profile.model;
371
- delete profile.workspace;
372
- if (own(request, "model") && request.model) {
373
- profile.model = request.model.resolved;
374
- }
375
- if (own(request.runtime, "workspace") && typeof request.runtime.workspace === "string") {
376
- profile.workspace = request.runtime.workspace;
377
- }
378
- if (settings) {
379
- if (own(settings, "bin") && typeof settings.bin === "string")
380
- profile.bin = settings.bin;
381
- if (own(settings, "args") &&
382
- Array.isArray(settings.args) &&
383
- settings.args.every((entry) => typeof entry === "string")) {
384
- profile.args = Object.freeze([...settings.args]);
385
- }
386
- }
387
- const common = {
388
- ...base,
389
- profile: Object.freeze(profile),
390
- };
391
- const sdkFallbackModelFromRequest = base.kind === "sdk" &&
392
- settings !== null &&
393
- settings !== undefined &&
394
- own(settings, SDK_FALLBACK_MODEL_FROM_REQUEST_SETTING);
395
- const clearsSdkFallbackModel = base.kind === "sdk" && base.fallbackConnection !== undefined && request.model === null;
396
- if (sdkFallbackModelFromRequest && settings?.[SDK_FALLBACK_MODEL_FROM_REQUEST_SETTING] !== true) {
397
- throw new ConfigError("Resolved SDK fallback model marker is invalid.", "INVALID_CONFIG_FILE");
398
- }
399
- if (sdkFallbackModelFromRequest && (!base.fallbackConnection || !own(request, "model"))) {
400
- throw new ConfigError("Resolved SDK fallback model material is incomplete.", "INVALID_CONFIG_FILE");
401
- }
402
- if (base.kind === "sdk" && base.fallbackConnection) {
403
- const fallbackConnection = sterileRecord({ ...base.fallbackConnection });
404
- if (sdkFallbackModelFromRequest || clearsSdkFallbackModel) {
405
- delete fallbackConnection.model;
406
- if (sdkFallbackModelFromRequest && request.model)
407
- fallbackConnection.model = request.model.resolved;
408
- }
409
- if (own(request, "inference")) {
410
- for (const key of LLM_INFERENCE_CONNECTION_FIELDS)
411
- delete fallbackConnection[key];
412
- if (request.inference) {
413
- for (const key of LLM_INFERENCE_CONNECTION_FIELDS) {
414
- if (own(request.inference, key))
415
- fallbackConnection[key] = request.inference[key];
416
- }
417
- }
418
- }
419
- common.fallbackConnection = Object.freeze(fallbackConnection);
420
- }
421
- delete common.timeoutMs;
422
- if (own(request.runtime, "timeoutMs"))
423
- common.timeoutMs = request.runtime.timeoutMs;
424
- else if (own(base, "timeoutMs"))
425
- common.timeoutMs = base.timeoutMs;
426
- return snapshotRunnerSpec(common, {
427
- allowMissingSdkFallbackModel: clearsSdkFallbackModel,
428
- });
429
- }
430
- function selectedExtensionPaths(request) {
431
- const out = [];
432
- if (own(request, "extensions"))
433
- out.push("extensions");
434
- if (own(request.command, "extensions"))
435
- out.push("command.extensions");
436
- const persona = own(request, "persona") ? request.persona : undefined;
437
- if (persona && own(persona, "extensions"))
438
- out.push("persona.extensions");
439
- if (own(request.engine, "extensions"))
440
- out.push("engine.extensions");
441
- if (own(request.runtime, "extensions"))
442
- out.push("runtime.extensions");
443
- return out;
444
- }
445
- const LLM_INFERENCE_CONNECTION_FIELDS = new Set([
446
- "temperature",
447
- "maxTokens",
448
- "supportsJsonSchema",
449
- "extraParams",
450
- "contextLength",
451
- "enableThinking",
452
- "reasoningEffort",
453
- ]);
454
- function projectLlmRunner(base, request) {
455
- const connection = sterileRecord({ ...base.connection });
456
- for (const key of [
457
- "model",
458
- "temperature",
459
- "maxTokens",
460
- "supportsJsonSchema",
461
- "extraParams",
462
- "contextLength",
463
- "enableThinking",
464
- "reasoningEffort",
465
- ]) {
466
- delete connection[key];
467
- }
468
- const settings = own(request.engine, "settings") ? request.engine.settings : undefined;
469
- if (settings) {
470
- if (own(settings, "endpoint") && typeof settings.endpoint === "string")
471
- connection.endpoint = settings.endpoint;
472
- if (own(settings, "provider") && typeof settings.provider === "string")
473
- connection.provider = settings.provider;
474
- }
475
- if (own(request, "model") && request.model)
476
- connection.model = request.model.resolved;
477
- const inference = own(request, "inference") ? request.inference : undefined;
478
- if (inference) {
479
- for (const key of LLM_INFERENCE_CONNECTION_FIELDS) {
480
- if (own(inference, key))
481
- connection[key] = inference[key];
482
- }
483
- }
484
- const projected = {
485
- ...base,
486
- connection: Object.freeze(connection),
487
- };
488
- delete projected.timeoutMs;
489
- if (own(request.runtime, "timeoutMs"))
490
- projected.timeoutMs = request.runtime.timeoutMs;
491
- else if (own(base, "timeoutMs"))
492
- projected.timeoutMs = base.timeoutMs;
493
- return snapshotRunnerSpec(projected, { allowMissingLlmModel: true });
494
- }
495
- function lowerAgent(request, base) {
496
- const platform = own(request.engine, "platform") ? request.engine.platform : undefined;
497
- if (typeof platform !== "string") {
498
- throw new ConfigError(`Resolved agent engine ${JSON.stringify(request.engine.name)} has no platform.`, "INVALID_CONFIG_FILE");
499
- }
500
- const lowerer = AGENT_LOWERERS.get(platform);
501
- if (!lowerer) {
502
- throw new ConfigError(`Agent platform ${JSON.stringify(platform)} has no registered lowerer.`, "INVALID_CONFIG_FILE");
503
- }
504
- const runner = projectAgentRunner(base, request);
505
- const lowered = lowerer.lower(runner.profile, request);
506
- const options = Object.freeze(sterileRecord({ ...requestRuntimeOptions(request), dispatch: lowered.dispatch }));
507
- return registerLoweredExecution({
508
- schemaVersion: EXECUTION_LOWERING_SCHEMA_VERSION,
509
- request,
510
- adapter: platform,
511
- runner,
512
- prompt: lowered.prompt,
513
- dispatch: lowered.dispatch,
514
- options,
515
- translatedFields: sortedUnique([
516
- ...lowered.translatedFields,
517
- ...(own(request.engine, "settings") ? ["engine.settings"] : []),
518
- ]),
519
- untranslatedFields: lowered.untranslatedFields,
520
- notices: freezeNotices([...safeRequestNotices(request), ...lowered.notices]),
521
- });
522
- }
523
- function lowerLlm(request, base) {
524
- const runner = projectLlmRunner(base, request);
525
- const translated = new Set(["command.content", "engine"]);
526
- const untranslated = new Set();
527
- const notices = [...safeRequestNotices(request)];
528
- const reject = (field) => {
529
- untranslated.add(field);
530
- notices.push(untranslatedNotice("llm", field));
531
- };
532
- if (own(request.engine, "settings"))
533
- translated.add("engine.settings");
534
- if (own(request, "model"))
535
- translated.add("model");
536
- if (own(request, "persona"))
537
- translated.add("persona");
538
- if (own(request, "agent")) {
539
- if (typeof request.agent === "string" && request.persona === null) {
540
- throw new ConfigError(`The direct LLM transport cannot consume native agent selector ${JSON.stringify(request.agent)}.`, "INVALID_CONFIG_FILE");
541
- }
542
- translated.add("agent");
543
- }
544
- if (own(request, "conversation"))
545
- translated.add("conversation");
546
- if (own(request, "inference")) {
547
- const inference = request.inference;
548
- if (inference && Object.keys(inference).length > 0) {
549
- for (const key of Object.keys(inference).sort()) {
550
- const field = `inference.${key}`;
551
- if (LLM_INFERENCE_CONNECTION_FIELDS.has(key))
552
- translated.add(field);
553
- else
554
- reject(field);
555
- }
556
- }
557
- else {
558
- translated.add("inference");
559
- }
560
- }
561
- const chatOptions = sterileRecord({});
562
- if (own(request.runtime, "timeoutMs")) {
563
- translated.add("runtime.timeoutMs");
564
- chatOptions.timeoutMs = request.runtime.timeoutMs;
565
- }
566
- if (own(request, "outputSchema")) {
567
- if (request.outputSchema === null)
568
- translated.add("outputSchema");
569
- else if (runner.connection.supportsJsonSchema === true) {
570
- translated.add("outputSchema");
571
- chatOptions.responseSchema = request.outputSchema;
572
- }
573
- else
574
- reject("outputSchema");
575
- }
576
- if (own(request, "tools")) {
577
- const tools = request.tools;
578
- const empty = tools === null ||
579
- tools === "" ||
580
- (Array.isArray(tools) && tools.length === 0) ||
581
- (typeof tools === "object" && tools !== null && !Array.isArray(tools) && Object.keys(tools).length === 0);
582
- if (empty)
583
- translated.add("tools");
584
- else {
585
- throw new ConfigError("The direct LLM transport cannot enforce the resolved tool policy.", "INVALID_CONFIG_FILE");
586
- }
587
- }
588
- if (own(request.runtime, "workspace")) {
589
- if (request.runtime.workspace === null || request.runtime.workspace === "")
590
- translated.add("runtime.workspace");
591
- else
592
- reject("runtime.workspace");
593
- }
594
- if (own(request.runtime, "environment")) {
595
- const environment = request.runtime.environment;
596
- if (environment === null || environment === undefined || Object.keys(environment).length === 0) {
597
- translated.add("runtime.environment");
598
- }
599
- else
600
- reject("runtime.environment");
601
- }
602
- if (own(request.runtime, "settings")) {
603
- const settings = request.runtime.settings;
604
- if (settings === null || settings === undefined || Object.keys(settings).length === 0) {
605
- translated.add("runtime.settings");
606
- }
607
- else
608
- reject("runtime.settings");
609
- }
610
- for (const field of selectedExtensionPaths(request))
611
- reject(field);
612
- const messages = Object.freeze([
613
- ...(own(request, "persona") && request.persona
614
- ? [{ role: "system", content: request.persona.content }]
615
- : []),
616
- ...(request.conversation ?? []),
617
- { role: "user", content: request.command.content },
618
- ].map((message) => Object.freeze({ role: message.role, content: message.content })));
619
- return registerLoweredExecution({
620
- schemaVersion: EXECUTION_LOWERING_SCHEMA_VERSION,
621
- request,
622
- adapter: "llm",
623
- runner,
624
- prompt: request.command.content,
625
- messages,
626
- chatOptions: Object.freeze(chatOptions),
627
- options: requestRuntimeOptions(request),
628
- translatedFields: sortedUnique(translated),
629
- untranslatedFields: sortedUnique(untranslated),
630
- notices: freezeNotices(notices),
631
- });
632
- }
633
- /** The sole live-config engine resolver used by every current execution mode. */
634
- function resolveSnapshotRunner(engine, config) {
635
- return snapshotRunnerSpec(resolveEngine(engine, config));
636
- }
637
- /**
638
- * Lower one payload-free interactive launch. The input vocabulary is closed:
639
- * there is deliberately no command, prompt, model, tool, or arbitrary env.
640
- */
641
- function lowerInteractiveAgentExecution(input) {
642
- if (typeof input.engine !== "string" || input.engine.length === 0) {
643
- throw new TypeError("interactive agent execution input.engine must be a non-empty string");
644
- }
645
- if (input.timeoutMs !== undefined) {
646
- validateTimeout(input.timeoutMs, "interactive agent execution input.timeoutMs");
647
- }
648
- if (input.cwd !== undefined && typeof input.cwd !== "string") {
649
- throw new TypeError("interactive agent execution input.cwd must be a string");
650
- }
651
- const runner = resolveSnapshotRunner(input.engine, snapshotConfig(input.config));
652
- if (runner.kind === "llm") {
653
- throw new UsageError(`Engine "${input.engine}" is an LLM engine; akm agent requires an agent engine.`, "INVALID_FLAG_VALUE");
654
- }
655
- const options = Object.freeze(sterileRecord({
656
- stdio: runner.kind === "sdk" ? runner.profile.stdio : "interactive",
657
- parseOutput: "text",
658
- ...(input.timeoutMs !== undefined ? { timeoutMs: input.timeoutMs } : {}),
659
- ...(input.cwd ? { cwd: input.cwd } : {}),
660
- }));
661
- return Object.freeze({
662
- engine: input.engine,
663
- runner,
664
- options,
665
- });
666
- }
667
- /**
668
- * The one optimistic lowering boundary. Authorization and request-brand
669
- * validation precede config, registry, credential, and transport work.
670
- */
671
- export function lowerResolvedExecutionRequest(input, config) {
672
- const request = requireAuthorizedRequest(input);
673
- const frozenConfig = snapshotConfig(config);
674
- const base = resolveSnapshotRunner(request.engine.name, frozenConfig);
675
- requireRunnerShape(request, base);
676
- return base.kind === "llm" ? lowerLlm(request, base) : lowerAgent(request, base);
677
- }
678
- /**
679
- * Lower from already-frozen, symbolic runner material. Workflow resume uses
680
- * this entry point so no live config, alias, environment, or credential lookup
681
- * can alter a journaled request before dispatch.
682
- */
683
- export function lowerResolvedExecutionRequestWithRunner(input, runner) {
684
- const request = requireAuthorizedRequest(input);
685
- const base = snapshotRunnerSpec(runner);
686
- requireRunnerShape(request, base);
687
- return base.kind === "llm" ? lowerLlm(request, base) : lowerAgent(request, base);
688
- }
689
- function requireLoweredExecutionProvenance(lowered) {
690
- if (typeof lowered !== "object" ||
691
- lowered === null ||
692
- !loweredExecutionInstances.has(lowered) ||
693
- !Object.isFrozen(lowered)) {
694
- throw new TypeError("lowered execution request must be produced by the engine lowerer registry");
695
- }
696
- canonicalResolvedExecutionRequest(lowered.request);
697
- }
698
- /**
699
- * Acquire an opaque operation capability only after genuine lowered-request
700
- * provenance and canonical authorization have been revalidated.
701
- */
702
- export function acquireLoweredExecutionDispatchLease(lowered, options = {}) {
703
- requireLoweredExecutionProvenance(lowered);
704
- const optionSnapshot = snapshotStrictRecord(options, "dispatch lease acquisition options");
705
- assertSnapshotKeys(optionSnapshot, ["envSource"], "dispatch lease acquisition options");
706
- const strictOptions = optionSnapshot;
707
- return acquireRunnerDispatchLease(lowered.runner, strictOptions.envSource ?? process.env);
708
- }
709
- /** Idempotently scrub and invalidate a genuine operation dispatch lease. */
710
- export function disposeLoweredExecutionDispatchLease(lease) {
711
- disposeRunnerDispatchLease(lease);
712
- }
713
- /** Redact text with a lease's private credential inventory without exposing it. */
714
- export function redactWithLoweredExecutionDispatchLease(lease, value) {
715
- return redactWithRunnerDispatchLease(lease, value);
716
- }
717
- /** One raw runner symbol reference for every shared execution dispatch mode. */
718
- function runnerDispatcher(candidate) {
719
- return candidate ?? executeRunner;
720
- }
721
- async function dispatchLoweredInteractiveAgentExecution(lowered, seams) {
722
- const lease = acquireRunnerDispatchLease(lowered.runner, process.env);
723
- try {
724
- return await runnerDispatcher()(lowered.runner, "", lowered.options, {
725
- ...(seams.runAgent ? { runAgent: seams.runAgent } : {}),
726
- ...(seams.runSdk ? { runSdk: seams.runSdk } : {}),
727
- }, lease);
728
- }
729
- finally {
730
- disposeRunnerDispatchLease(lease);
731
- }
732
- }
733
- /** Resolve, lower, and dispatch one native interactive agent invocation. */
734
- export async function executeInteractiveAgentInvocation(input, seams = {}) {
735
- const lowered = lowerInteractiveAgentExecution(input);
736
- return {
737
- engine: lowered.engine,
738
- result: await dispatchLoweredInteractiveAgentExecution(lowered, seams),
739
- };
740
- }
741
- /** Dispatch a previously lowered request without re-resolving any model, ref, or persona. */
742
- export async function dispatchLoweredExecutionRequest(lowered, options = {}) {
743
- requireLoweredExecutionProvenance(lowered);
744
- const optionSnapshot = snapshotStrictRecord(options, "lowered execution dispatch options");
745
- assertSnapshotKeys(optionSnapshot, ["executeRunner", "chat", "onRetryAttempt", "runAgent", "runSdk", "lease", "runOptions", "eventSource"], "lowered execution dispatch options");
746
- const strictOptions = optionSnapshot;
747
- if (strictOptions.onRetryAttempt !== undefined && typeof strictOptions.onRetryAttempt !== "function") {
748
- throw new TypeError("lowered execution dispatch options.onRetryAttempt must be a function");
749
- }
750
- if (strictOptions.eventSource !== undefined && typeof strictOptions.eventSource !== "string") {
751
- throw new TypeError("lowered execution dispatch options.eventSource must be a string");
752
- }
753
- const usesDefaultRunner = strictOptions.executeRunner === undefined;
754
- const run = runnerDispatcher(strictOptions.executeRunner);
755
- const operationalSnapshot = snapshotStrictRecord(strictOptions.runOptions ?? {}, "lowered execution operational options");
756
- assertSnapshotKeys(operationalSnapshot, [
757
- "stdio",
758
- "timeoutMs",
759
- "parseOutput",
760
- "env",
761
- "cwd",
762
- "args",
763
- "stdin",
764
- "signal",
765
- "envSource",
766
- "spawn",
767
- "setTimeoutFn",
768
- "clearTimeoutFn",
769
- "onEvent",
770
- "dispatch",
771
- "builderRegistry",
772
- ], "lowered execution operational options");
773
- const operational = operationalSnapshot;
774
- const runOptions = sterileRecord({
775
- ...lowered.options,
776
- ...(operational.stdio !== undefined ? { stdio: operational.stdio } : {}),
777
- ...(operational.parseOutput !== undefined ? { parseOutput: operational.parseOutput } : {}),
778
- ...(operational.signal !== undefined ? { signal: operational.signal } : {}),
779
- ...(operational.envSource !== undefined ? { envSource: operational.envSource } : {}),
780
- ...(operational.spawn !== undefined ? { spawn: operational.spawn } : {}),
781
- ...(operational.setTimeoutFn !== undefined ? { setTimeoutFn: operational.setTimeoutFn } : {}),
782
- ...(operational.clearTimeoutFn !== undefined ? { clearTimeoutFn: operational.clearTimeoutFn } : {}),
783
- ...(operational.onEvent !== undefined ? { onEvent: operational.onEvent } : {}),
784
- // F-1 (spec docs/plans/specs/p1b-model-extraction.md §5.2 point 3): the
785
- // ONE narrowly-scoped exception to "resolved content cannot be
786
- // overridden" — sets exactly the one named key, never a caller-supplied
787
- // env bag (runOptions.env stays unhonored, same as before P1b; see
788
- // DispatchLoweredExecutionOptions.eventSource's doc).
789
- ...(strictOptions.eventSource !== undefined
790
- ? { env: { ...lowered.options.env, AKM_EVENT_SOURCE: strictOptions.eventSource } }
791
- : {}),
792
- });
793
- const ownedLease = strictOptions.lease === undefined && usesDefaultRunner;
794
- const lease = strictOptions.lease ??
795
- (ownedLease ? acquireRunnerDispatchLease(lowered.runner, runOptions.envSource ?? process.env) : undefined);
796
- if (lease)
797
- assertRunnerDispatchLease(lease, lowered.runner);
798
- try {
799
- return await run(lowered.runner, lowered.prompt, runOptions, {
800
- ...(strictOptions.runAgent ? { runAgent: strictOptions.runAgent } : {}),
801
- ...(strictOptions.runSdk ? { runSdk: strictOptions.runSdk } : {}),
802
- ...("messages" in lowered
803
- ? {
804
- llm: async (spec, _prompt, runOptions) => {
805
- const started = Date.now();
806
- try {
807
- const stdout = await (strictOptions.chat ?? chatCompletion)(spec.connection, [...lowered.messages], {
808
- ...lowered.chatOptions,
809
- ...(!own(lowered.chatOptions, "timeoutMs") && own(runOptions, "timeoutMs")
810
- ? { timeoutMs: runOptions.timeoutMs }
811
- : {}),
812
- ...(runOptions.signal ? { signal: runOptions.signal } : {}),
813
- ...(strictOptions.onRetryAttempt ? { onRetryAttempt: strictOptions.onRetryAttempt } : {}),
814
- });
815
- return { ok: true, exitCode: 0, stdout, stderr: "", durationMs: Date.now() - started };
816
- }
817
- catch (error) {
818
- // Return through executeRunner so its credential-aware redactor
819
- // handles provider bodies before any caller can persist them.
820
- const failure = directLlmFailure(error);
821
- return {
822
- ok: false,
823
- exitCode: null,
824
- stdout: "",
825
- stderr: "",
826
- durationMs: Date.now() - started,
827
- error: safeCaughtErrorMessage(error),
828
- reason: failure.reason,
829
- ...(failure.code ? { llmErrorCode: failure.code } : {}),
830
- };
831
- }
832
- },
833
- }
834
- : {}),
835
- }, lease);
836
- }
837
- finally {
838
- if (ownedLease && lease)
839
- disposeRunnerDispatchLease(lease);
840
- }
841
- }