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,730 +1,176 @@
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 { cloneExecutionJson, cloneExecutionJsonObject, sortExecutionJson } from "./json.js";
5
- import { EXECUTION_MAX_TIMEOUT_MS } from "./limits.js";
6
- import { assertSnapshotKeys, requireSnapshotField, snapshotStrictRecord } from "./record.js";
7
- import { cloneAdapterExtensions, cloneToolSelection, decodeExecutionSourceIdentity, executionPersonaMatchesSelector, isAdapterRenderedCommandSource, isAdapterRenderedPersonaSource, isPortableExecutionAgentSelector, requireStableExecutionSelector, } from "./source.js";
4
+ import { sortExecutionJson } from "./json.js";
5
+ import { decodeExecutionSourceIdentity, } from "./source.js";
8
6
  export const RESOLVED_EXECUTION_SCHEMA_VERSION = 1;
9
- const resolvedCommandBrand = Symbol("akm.resolved-command");
10
- const resolvedPersonaBrand = Symbol("akm.resolved-persona");
11
- const resolvedCommandInstances = new WeakSet();
12
- const resolvedPersonaInstances = new WeakSet();
13
- const resolvedRequestInstances = new WeakSet();
14
- function defineBrand(value, brand, instances) {
15
- Object.defineProperty(value, brand, { value: true, enumerable: false });
16
- const frozen = Object.freeze(value);
17
- instances.add(frozen);
18
- return frozen;
19
- }
20
- function cloneIdentity(value) {
21
- return decodeExecutionSourceIdentity(value);
7
+ const COMMAND_KEYS = ["template", "argumentInput", "content", "source", "extensions"];
8
+ const PERSONA_KEYS = ["content", "source", "extensions"];
9
+ const ENGINE_KEYS = ["name", "kind", "platform", "settings", "extensions"];
10
+ const MODEL_KEYS = ["input", "interpretation", "resolved", "extensions"];
11
+ const AUTHORIZATION_KEYS = ["status", "reason", "policy"];
12
+ const RUNTIME_KEYS = ["timeoutMs", "workspace", "environment", "settings", "extensions"];
13
+ const NOTICE_KEYS = ["code", "severity", "adapter", "field", "message", "details"];
14
+ const IDENTITY_KEYS = ["ref", "bundle", "adapter", "file", "hash"];
15
+ const OPTIONAL_REQUEST_KEYS = [
16
+ "conversation",
17
+ "agent",
18
+ "persona",
19
+ "model",
20
+ "inference",
21
+ "outputSchema",
22
+ "tools",
23
+ "extensions",
24
+ ];
25
+ /** Copy the own, defined fields named by `keys`; omitted stays omitted, `null` stays `null`. */
26
+ function pick(value, keys) {
27
+ const record = value;
28
+ const out = {};
29
+ for (const key of keys) {
30
+ if (Object.hasOwn(record, key) && record[key] !== undefined)
31
+ out[key] = record[key];
32
+ }
33
+ return out;
22
34
  }
23
- function copyArgumentInput(input, output) {
24
- if (!Object.hasOwn(input, "argumentInput"))
25
- return;
26
- if (typeof input.argumentInput !== "string") {
27
- throw new TypeError("command argumentInput must be omitted or a string");
35
+ function requireRecord(value, path) {
36
+ if (value === null || typeof value !== "object" || Array.isArray(value)) {
37
+ throw new TypeError(`${path} must be an object`);
28
38
  }
29
- output.argumentInput = input.argumentInput;
39
+ return value;
30
40
  }
31
41
  export function createResolvedCommand(input) {
32
- const record = requireObject(input, "resolved command input");
33
- assertOnlyKeys(record, ["source", "argumentInput", "content"], "resolved command input");
34
- const source = requireOwn(record, "source", "resolved command input");
35
- const content = requireOwn(record, "content", "resolved command input");
36
- if (!isAdapterRenderedCommandSource(source)) {
37
- throw new TypeError("source must be an adapter-rendered command source");
38
- }
39
- if (typeof content !== "string")
42
+ if (typeof input.content !== "string")
40
43
  throw new TypeError("resolved command content must be a string");
41
- const out = {
42
- template: source.content,
43
- content,
44
- source: cloneIdentity(source.identity),
45
- ...(source.extensions
46
- ? { extensions: cloneAdapterExtensions(source.extensions, "resolved command extensions") }
47
- : {}),
48
- };
49
- copyArgumentInput(record, out);
50
- return defineBrand(out, resolvedCommandBrand, resolvedCommandInstances);
44
+ return Object.freeze({
45
+ template: input.source.content,
46
+ ...(input.argumentInput !== undefined ? { argumentInput: input.argumentInput } : {}),
47
+ content: input.content,
48
+ source: decodeExecutionSourceIdentity(input.source.identity),
49
+ ...(input.source.extensions ? { extensions: input.source.extensions } : {}),
50
+ });
51
51
  }
52
52
  export function createInlineResolvedCommand(input) {
53
- const record = requireObject(input, "inline resolved command input");
54
- assertOnlyKeys(record, ["template", "argumentInput", "content"], "inline resolved command input");
55
- const template = requireOwn(record, "template", "inline resolved command input");
56
- const content = requireOwn(record, "content", "inline resolved command input");
57
- if (typeof template !== "string" || typeof content !== "string") {
53
+ if (typeof input.template !== "string" || typeof input.content !== "string") {
58
54
  throw new TypeError("inline command template and content must be strings");
59
55
  }
60
- const out = { template, content, source: null };
61
- copyArgumentInput(record, out);
62
- return defineBrand(out, resolvedCommandBrand, resolvedCommandInstances);
56
+ return Object.freeze({
57
+ template: input.template,
58
+ ...(input.argumentInput !== undefined ? { argumentInput: input.argumentInput } : {}),
59
+ content: input.content,
60
+ source: null,
61
+ });
63
62
  }
64
63
  export function createResolvedPersona(source) {
65
- if (!isAdapterRenderedPersonaSource(source)) {
66
- throw new TypeError("source must be an adapter-rendered persona source");
67
- }
68
- const out = {
64
+ return Object.freeze({
69
65
  content: source.content,
70
- source: cloneIdentity(source.identity),
71
- ...(source.extensions
72
- ? { extensions: cloneAdapterExtensions(source.extensions, "resolved persona extensions") }
73
- : {}),
74
- };
75
- return defineBrand(out, resolvedPersonaBrand, resolvedPersonaInstances);
76
- }
77
- function hasOwnFrozenBrand(value, brand, instances) {
78
- if (typeof value !== "object" ||
79
- value === null ||
80
- !instances.has(value) ||
81
- Object.getPrototypeOf(value) !== Object.prototype ||
82
- !Object.isFrozen(value) ||
83
- !Object.hasOwn(value, brand)) {
84
- return false;
85
- }
86
- const descriptor = Object.getOwnPropertyDescriptor(value, brand);
87
- return (descriptor?.value === true &&
88
- descriptor.enumerable === false &&
89
- descriptor.configurable === false &&
90
- descriptor.writable === false);
91
- }
92
- function isResolvedCommand(value) {
93
- if (!hasOwnFrozenBrand(value, resolvedCommandBrand, resolvedCommandInstances))
94
- return false;
95
- try {
96
- const allowedSymbols = new Set([resolvedCommandBrand]);
97
- const record = requireObject(value, "command", allowedSymbols);
98
- assertOnlyKeys(record, ["template", "argumentInput", "content", "source", "extensions"], "command", allowedSymbols);
99
- const template = requireOwn(record, "template", "command");
100
- const content = requireOwn(record, "content", "command");
101
- const source = requireOwn(record, "source", "command");
102
- if (typeof template !== "string" || typeof content !== "string")
103
- return false;
104
- if (Object.hasOwn(record, "argumentInput") && typeof record.argumentInput !== "string")
105
- return false;
106
- if (source !== null)
107
- decodeExecutionSourceIdentity(source, "command.source");
108
- if (Object.hasOwn(record, "extensions"))
109
- cloneAdapterExtensions(record.extensions, "command.extensions");
110
- return true;
111
- }
112
- catch {
113
- return false;
114
- }
115
- }
116
- function isResolvedPersona(value) {
117
- if (!hasOwnFrozenBrand(value, resolvedPersonaBrand, resolvedPersonaInstances))
118
- return false;
119
- try {
120
- const allowedSymbols = new Set([resolvedPersonaBrand]);
121
- const record = requireObject(value, "persona", allowedSymbols);
122
- assertOnlyKeys(record, ["content", "source", "extensions"], "persona", allowedSymbols);
123
- if (typeof requireOwn(record, "content", "persona") !== "string")
124
- return false;
125
- decodeExecutionSourceIdentity(requireOwn(record, "source", "persona"), "persona.source");
126
- if (Object.hasOwn(record, "extensions"))
127
- cloneAdapterExtensions(record.extensions, "persona.extensions");
128
- return true;
129
- }
130
- catch {
131
- return false;
132
- }
133
- }
134
- function requireString(value, path) {
135
- if (typeof value !== "string" || value.length === 0)
136
- throw new TypeError(`${path} must be a non-empty string`);
137
- return value;
138
- }
139
- function cloneEngine(input) {
140
- const record = requireObject(input, "engine");
141
- assertOnlyKeys(record, ["name", "kind", "platform", "settings", "extensions"], "engine");
142
- const name = requireString(requireOwn(record, "name", "engine"), "engine.name");
143
- const kind = requireOwn(record, "kind", "engine");
144
- if (!(kind === "agent" || kind === "sdk" || kind === "llm"))
145
- throw new TypeError("engine.kind is invalid");
146
- const out = { name, kind };
147
- for (const key of ["platform", "settings", "extensions"]) {
148
- if (!Object.hasOwn(record, key))
149
- continue;
150
- const value = record[key];
151
- if (value === undefined)
152
- throw new TypeError(`engine.${key} must be omitted rather than undefined`);
153
- if (key === "platform") {
154
- if (value !== null && typeof value !== "string")
155
- throw new TypeError("engine.platform must be a string or null");
156
- out.platform = value;
157
- }
158
- else if (key === "settings") {
159
- out.settings = value === null ? null : cloneExecutionJsonObject(value, "engine.settings");
160
- }
161
- else {
162
- out.extensions = cloneAdapterExtensions(value, "engine.extensions");
163
- }
164
- }
165
- return Object.freeze(out);
166
- }
167
- function cloneModel(input) {
168
- const record = requireObject(input, "model");
169
- assertOnlyKeys(record, ["input", "interpretation", "resolved", "extensions"], "model");
170
- const modelInput = requireString(requireOwn(record, "input", "model"), "model.input");
171
- const interpretation = requireOwn(record, "interpretation", "model");
172
- const resolved = requireString(requireOwn(record, "resolved", "model"), "model.resolved");
173
- if (interpretation !== "alias" && interpretation !== "exact") {
174
- throw new TypeError("model.interpretation is invalid");
175
- }
176
- if (interpretation === "exact" && modelInput !== resolved) {
177
- throw new TypeError("model.input must match model.resolved when interpretation is exact");
178
- }
179
- const out = {
180
- input: modelInput,
181
- interpretation,
182
- resolved,
183
- };
184
- if (Object.hasOwn(record, "extensions")) {
185
- if (record.extensions === null || record.extensions === undefined) {
186
- throw new TypeError("model.extensions must be omitted or an adapter-owned extension object");
187
- }
188
- out.extensions = cloneAdapterExtensions(record.extensions, "model.extensions");
189
- }
190
- return Object.freeze(out);
191
- }
192
- function cloneAuthorization(input) {
193
- const record = requireObject(input, "authorization");
194
- assertOnlyKeys(record, ["status", "reason", "policy"], "authorization");
195
- const status = requireOwn(record, "status", "authorization");
196
- if (!(status === "allowed" || status === "denied" || status === "not-required")) {
197
- throw new TypeError("authorization.status is invalid");
198
- }
199
- const out = { status };
200
- if (Object.hasOwn(record, "reason")) {
201
- if (record.reason !== null && typeof record.reason !== "string") {
202
- throw new TypeError("authorization.reason must be a string or null");
203
- }
204
- out.reason = record.reason;
205
- }
206
- if (Object.hasOwn(record, "policy")) {
207
- out.policy = record.policy === null ? null : cloneExecutionJsonObject(record.policy, "authorization.policy");
208
- }
209
- return Object.freeze(out);
210
- }
211
- function cloneRuntime(input) {
212
- const record = requireObject(input, "runtime");
213
- assertOnlyKeys(record, ["timeoutMs", "workspace", "environment", "settings", "extensions"], "runtime");
214
- const out = {};
215
- if (Object.hasOwn(record, "timeoutMs")) {
216
- const timeoutMs = record.timeoutMs;
217
- if (timeoutMs !== null &&
218
- (typeof timeoutMs !== "number" ||
219
- !Number.isInteger(timeoutMs) ||
220
- timeoutMs < 0 ||
221
- timeoutMs > EXECUTION_MAX_TIMEOUT_MS)) {
222
- throw new TypeError(`runtime.timeoutMs must be null or an integer from 0 through ${EXECUTION_MAX_TIMEOUT_MS}`);
223
- }
224
- out.timeoutMs = timeoutMs;
225
- }
226
- if (Object.hasOwn(record, "workspace")) {
227
- if (record.workspace !== null && typeof record.workspace !== "string") {
228
- throw new TypeError("runtime.workspace must be a string or null");
229
- }
230
- out.workspace = record.workspace;
231
- }
232
- if (Object.hasOwn(record, "environment")) {
233
- if (record.environment === null)
234
- out.environment = null;
235
- else {
236
- const environment = cloneExecutionJsonObject(record.environment, "runtime.environment");
237
- if (Object.values(environment).some((value) => typeof value !== "string")) {
238
- throw new TypeError("runtime.environment values must be strings");
239
- }
240
- out.environment = environment;
241
- }
242
- }
243
- if (Object.hasOwn(record, "settings")) {
244
- out.settings = record.settings === null ? null : cloneExecutionJsonObject(record.settings, "runtime.settings");
245
- }
246
- if (Object.hasOwn(record, "extensions")) {
247
- out.extensions = cloneAdapterExtensions(record.extensions, "runtime.extensions");
248
- }
249
- return Object.freeze(out);
250
- }
251
- function cloneNotice(input, index) {
252
- const path = `notices[${index}]`;
253
- const record = requireObject(input, path);
254
- assertOnlyKeys(record, ["code", "severity", "adapter", "field", "message", "details"], path);
255
- const code = requireString(requireOwn(record, "code", path), `${path}.code`);
256
- const severity = requireOwn(record, "severity", path);
257
- const adapter = requireString(requireOwn(record, "adapter", path), `${path}.adapter`);
258
- const message = requireString(requireOwn(record, "message", path), `${path}.message`);
259
- if (severity !== "info" && severity !== "warning") {
260
- throw new TypeError(`notices[${index}].severity is invalid`);
261
- }
262
- const out = {
263
- code,
264
- severity,
265
- adapter,
266
- message,
267
- };
268
- if (Object.hasOwn(record, "field")) {
269
- if (record.field !== null && typeof record.field !== "string") {
270
- throw new TypeError(`notices[${index}].field must be a string or null`);
271
- }
272
- out.field = record.field;
273
- }
274
- if (Object.hasOwn(record, "details")) {
275
- out.details = record.details === null ? null : cloneExecutionJsonObject(record.details, `${path}.details`);
276
- }
277
- return Object.freeze(out);
278
- }
279
- function cloneConversation(input, path = "conversation") {
280
- const cloned = cloneExecutionJson(input, path);
281
- if (!Array.isArray(cloned))
282
- throw new TypeError(`${path} must be an array`);
283
- return Object.freeze(cloned.map((message, index) => {
284
- const messagePath = `${path}[${index}]`;
285
- const record = requireObject(message, messagePath);
286
- assertOnlyKeys(record, ["role", "content"], messagePath);
287
- const role = requireOwn(record, "role", messagePath);
288
- const content = requireOwn(record, "content", messagePath);
289
- if (role !== "system" && role !== "user" && role !== "assistant") {
290
- throw new TypeError(`${messagePath}.role must be system, user, or assistant`);
291
- }
292
- if (typeof content !== "string")
293
- throw new TypeError(`${messagePath}.content must be a string`);
294
- return Object.freeze({ role, content });
295
- }));
296
- }
297
- function cloneResolvedCommandLeaf(input) {
298
- if (!isResolvedCommand(input))
299
- throw new TypeError("command must be constructed by the execution boundary");
300
- const allowedSymbols = new Set([resolvedCommandBrand]);
301
- const record = requireObject(input, "command", allowedSymbols);
302
- assertOnlyKeys(record, ["template", "argumentInput", "content", "source", "extensions"], "command", allowedSymbols);
303
- const template = requireOwn(record, "template", "command");
304
- const content = requireOwn(record, "content", "command");
305
- const source = requireOwn(record, "source", "command");
306
- if (typeof template !== "string" || typeof content !== "string") {
307
- throw new TypeError("command template and content must be strings");
308
- }
309
- const out = {
310
- template,
311
- content,
312
- source: source === null ? null : decodeExecutionSourceIdentity(source, "command.source"),
313
- };
314
- copyArgumentInput(record, out);
315
- if (Object.hasOwn(record, "extensions")) {
316
- out.extensions = cloneAdapterExtensions(record.extensions, "command.extensions");
317
- }
318
- return defineBrand(out, resolvedCommandBrand, resolvedCommandInstances);
319
- }
320
- function cloneResolvedPersonaLeaf(input) {
321
- if (!isResolvedPersona(input))
322
- throw new TypeError("persona must be constructed by the execution boundary");
323
- const allowedSymbols = new Set([resolvedPersonaBrand]);
324
- const record = requireObject(input, "persona", allowedSymbols);
325
- assertOnlyKeys(record, ["content", "source", "extensions"], "persona", allowedSymbols);
326
- const content = requireOwn(record, "content", "persona");
327
- if (typeof content !== "string")
328
- throw new TypeError("persona.content must be a string");
329
- const out = {
330
- content,
331
- source: decodeExecutionSourceIdentity(requireOwn(record, "source", "persona"), "persona.source"),
332
- };
333
- if (Object.hasOwn(record, "extensions")) {
334
- out.extensions = cloneAdapterExtensions(record.extensions, "persona.extensions");
335
- }
336
- return defineBrand(out, resolvedPersonaBrand, resolvedPersonaInstances);
337
- }
338
- /** Revalidate and detach one command leaf before any caller dereferences it. */
339
- export function cloneResolvedCommandContent(input) {
340
- return cloneResolvedCommandLeaf(input);
341
- }
342
- /** Revalidate and detach one persona leaf before any caller dereferences it. */
343
- export function cloneResolvedPersonaContent(input) {
344
- return cloneResolvedPersonaLeaf(input);
345
- }
346
- function cloneAgentSelector(input, path) {
347
- if (input === null)
348
- return null;
349
- return requireStableExecutionSelector(input, path);
350
- }
351
- function assertAgentPersonaInvariant(request, path) {
352
- if (!Object.hasOwn(request, "agent"))
353
- return;
354
- if (!Object.hasOwn(request, "persona")) {
355
- throw new TypeError(`${path}.persona must be present when ${path}.agent is selected or explicitly null`);
356
- }
357
- const agent = request.agent;
358
- const persona = request.persona;
359
- if (agent === null) {
360
- if (persona !== null)
361
- throw new TypeError(`${path}.agent null requires ${path}.persona null`);
362
- return;
363
- }
364
- if (isPortableExecutionAgentSelector(agent)) {
365
- if (persona === null || !executionPersonaMatchesSelector(agent, persona.source.ref)) {
366
- throw new TypeError(`${path}.agent portable selector must match the non-null persona source`);
367
- }
368
- return;
369
- }
370
- if (persona !== null) {
371
- throw new TypeError(`${path}.agent native selector requires ${path}.persona null`);
372
- }
66
+ source: decodeExecutionSourceIdentity(source.identity),
67
+ ...(source.extensions ? { extensions: source.extensions } : {}),
68
+ });
373
69
  }
374
- /** Validate and freeze one request without normalizing away optional-field presence. */
70
+ /** Freeze one request without normalizing away optional-field presence. */
375
71
  export function createResolvedExecutionRequest(input) {
376
- const record = requireObject(input, "resolved execution request input");
377
- assertOnlyKeys(record, [
378
- "command",
379
- "conversation",
380
- "agent",
381
- "persona",
382
- "engine",
383
- "model",
384
- "inference",
385
- "outputSchema",
386
- "tools",
387
- "authorization",
388
- "runtime",
389
- "notices",
390
- "extensions",
391
- ], "resolved execution request input");
392
- const command = requireOwn(record, "command", "resolved execution request input");
393
- const engine = requireOwn(record, "engine", "resolved execution request input");
394
- const authorization = requireOwn(record, "authorization", "resolved execution request input");
395
- const runtime = requireOwn(record, "runtime", "resolved execution request input");
396
- const notices = requireOwn(record, "notices", "resolved execution request input");
397
- if (!isResolvedCommand(command))
398
- throw new TypeError("command must be constructed by the execution boundary");
399
- const clonedNotices = cloneExecutionJson(notices, "notices");
400
- if (!Array.isArray(clonedNotices))
401
- throw new TypeError("notices must be an array");
402
- const out = {
403
- schemaVersion: RESOLVED_EXECUTION_SCHEMA_VERSION,
404
- command: cloneResolvedCommandLeaf(command),
405
- engine: cloneEngine(engine),
406
- authorization: cloneAuthorization(authorization),
407
- runtime: cloneRuntime(runtime),
408
- notices: Object.freeze(clonedNotices.map((notice, index) => cloneNotice(notice, index))),
409
- };
410
- if (Object.hasOwn(record, "conversation"))
411
- out.conversation = cloneConversation(record.conversation);
412
- if (Object.hasOwn(record, "agent")) {
413
- if (record.agent === undefined)
414
- throw new TypeError("agent must be omitted, null, or a selected agent string");
415
- out.agent = cloneAgentSelector(record.agent, "agent");
416
- }
417
- if (Object.hasOwn(record, "persona")) {
418
- if (record.persona !== null && !isResolvedPersona(record.persona)) {
419
- throw new TypeError("persona must be null or constructed by the execution boundary");
420
- }
421
- out.persona = record.persona === null ? null : cloneResolvedPersonaLeaf(record.persona);
422
- }
423
- assertAgentPersonaInvariant(out, "resolved execution request");
424
- if (Object.hasOwn(record, "model")) {
425
- if (record.model === undefined)
426
- throw new TypeError("model must be omitted, null, or a model selection");
427
- out.model = record.model === null ? null : cloneModel(record.model);
428
- }
429
- if (Object.hasOwn(record, "inference")) {
430
- out.inference = record.inference === null ? null : cloneExecutionJsonObject(record.inference, "inference");
431
- }
432
- if (Object.hasOwn(record, "outputSchema")) {
433
- out.outputSchema =
434
- record.outputSchema === null ? null : cloneExecutionJsonObject(record.outputSchema, "outputSchema");
435
- }
436
- if (Object.hasOwn(record, "tools"))
437
- out.tools = cloneToolSelection(record.tools, "tools");
438
- const toolsRequireAuthorization = toolSelectionRequiresAuthorization(out.tools, Object.hasOwn(out, "tools"));
439
- const authorizationStatus = out.authorization.status;
440
- if (toolsRequireAuthorization && authorizationStatus === "not-required") {
441
- throw new TypeError("authorization.status not-required is valid only when no tools are selected");
442
- }
443
- if (!toolsRequireAuthorization && authorizationStatus !== "not-required") {
444
- throw new TypeError("empty or omitted tool selection requires authorization.status not-required");
445
- }
446
- if (Object.hasOwn(record, "extensions")) {
447
- out.extensions = cloneAdapterExtensions(record.extensions, "request.extensions");
448
- }
449
- const frozen = Object.freeze(out);
450
- resolvedRequestInstances.add(frozen);
451
- return frozen;
452
- }
453
- function toolSelectionRequiresAuthorization(value, present) {
454
- // WP1's transport-level invariant is intentionally syntax based: omitted,
455
- // null, "", [], and {} are the only empty spellings. Adapters/resolvers own
456
- // any format-specific normalization before they construct this request.
457
- if (!present || value === null)
458
- return false;
459
- if (typeof value === "string")
460
- return value.length > 0;
461
- if (Array.isArray(value))
462
- return value.length > 0;
463
- return typeof value === "object" && value !== null && Object.keys(value).length > 0;
464
- }
465
- function requireObject(value, path, allowedSymbols = new Set()) {
466
- return snapshotStrictRecord(value, path, { allowedSymbols });
467
- }
468
- function assertOnlyKeys(value, allowed, path, allowedSymbols = new Set()) {
469
- assertSnapshotKeys(value, allowed, path, allowedSymbols);
470
- }
471
- function requireOwn(value, key, path) {
472
- return requireSnapshotField(value, key, path);
473
- }
474
- function decodeExtensions(value, path) {
475
- return cloneAdapterExtensions(requireObject(value, path), path);
476
- }
477
- function decodeResolvedCommand(value) {
478
- const input = requireObject(value, "command");
479
- assertOnlyKeys(input, ["template", "argumentInput", "content", "source", "extensions"], "command");
480
- const template = requireOwn(input, "template", "command");
481
- const content = requireOwn(input, "content", "command");
482
- const source = requireOwn(input, "source", "command");
483
- if (typeof template !== "string" || typeof content !== "string") {
484
- throw new TypeError("command template and content must be strings");
72
+ if (!input.command || !input.engine || !input.authorization || !input.runtime || !input.notices) {
73
+ throw new TypeError("resolved execution request requires command, engine, authorization, runtime, and notices");
485
74
  }
486
75
  const out = {
487
- template,
488
- content,
489
- source: source === null ? null : decodeExecutionSourceIdentity(source, "command.source"),
76
+ schemaVersion: RESOLVED_EXECUTION_SCHEMA_VERSION,
77
+ command: input.command,
78
+ engine: input.engine,
79
+ authorization: input.authorization,
80
+ runtime: input.runtime,
81
+ notices: input.notices,
82
+ ...pick(input, OPTIONAL_REQUEST_KEYS),
490
83
  };
491
- if (Object.hasOwn(input, "argumentInput")) {
492
- if (typeof input.argumentInput !== "string")
493
- throw new TypeError("command.argumentInput must be a string");
494
- out.argumentInput = input.argumentInput;
495
- }
496
- if (Object.hasOwn(input, "extensions"))
497
- out.extensions = decodeExtensions(input.extensions, "command.extensions");
498
- return defineBrand(out, resolvedCommandBrand, resolvedCommandInstances);
499
- }
500
- function decodeResolvedPersona(value) {
501
- const input = requireObject(value, "persona");
502
- assertOnlyKeys(input, ["content", "source", "extensions"], "persona");
503
- const content = requireOwn(input, "content", "persona");
504
- if (typeof content !== "string")
505
- throw new TypeError("persona.content must be a string");
506
- const source = decodeExecutionSourceIdentity(requireOwn(input, "source", "persona"), "persona.source");
507
- const out = { content, source };
508
- if (Object.hasOwn(input, "extensions"))
509
- out.extensions = decodeExtensions(input.extensions, "persona.extensions");
510
- return defineBrand(out, resolvedPersonaBrand, resolvedPersonaInstances);
511
- }
512
- function decodeEngine(value) {
513
- const input = requireObject(value, "engine");
514
- assertOnlyKeys(input, ["name", "kind", "platform", "settings", "extensions"], "engine");
515
- requireOwn(input, "name", "engine");
516
- requireOwn(input, "kind", "engine");
517
- return cloneEngine(input);
518
- }
519
- function decodeModel(value) {
520
- const input = requireObject(value, "model");
521
- assertOnlyKeys(input, ["input", "interpretation", "resolved", "extensions"], "model");
522
- for (const key of ["input", "interpretation", "resolved"])
523
- requireOwn(input, key, "model");
524
- return cloneModel(input);
525
- }
526
- function decodeAuthorization(value) {
527
- const input = requireObject(value, "authorization");
528
- assertOnlyKeys(input, ["status", "reason", "policy"], "authorization");
529
- requireOwn(input, "status", "authorization");
530
- return cloneAuthorization(input);
531
- }
532
- function decodeRuntime(value) {
533
- const input = requireObject(value, "runtime");
534
- assertOnlyKeys(input, ["timeoutMs", "workspace", "environment", "settings", "extensions"], "runtime");
535
- return cloneRuntime(input);
536
- }
537
- function decodeNotice(value, index) {
538
- const input = requireObject(value, `notices[${index}]`);
539
- assertOnlyKeys(input, ["code", "severity", "adapter", "field", "message", "details"], `notices[${index}]`);
540
- for (const key of ["code", "severity", "adapter", "message"])
541
- requireOwn(input, key, `notices[${index}]`);
542
- return cloneNotice(input, index);
84
+ return Object.freeze(out);
543
85
  }
544
86
  /**
545
- * Strictly rehydrate a frozen JSON request after workflow resume/replay.
546
- * Symbol construction brands are restored only after every wire field has
547
- * been validated; raw/frontmatter lookalike fields are rejected as unknown.
87
+ * Rehydrate a frozen JSON request after workflow resume/replay. Tolerant of
88
+ * unknown keys; refuses only a request written by a newer schema.
548
89
  */
549
90
  export function decodeResolvedExecutionRequest(value) {
550
- const input = requireObject(value, "resolved execution request");
551
- assertOnlyKeys(input, [
552
- "schemaVersion",
553
- "command",
554
- "conversation",
555
- "agent",
556
- "persona",
557
- "engine",
558
- "model",
559
- "inference",
560
- "outputSchema",
561
- "tools",
562
- "authorization",
563
- "runtime",
564
- "notices",
565
- "extensions",
566
- ], "resolved execution request");
567
- if (requireOwn(input, "schemaVersion", "resolved execution request") !== RESOLVED_EXECUTION_SCHEMA_VERSION) {
568
- throw new TypeError(`unsupported resolved execution schemaVersion: ${String(input.schemaVersion)}`);
91
+ const input = requireRecord(value, "resolved execution request");
92
+ const version = input.schemaVersion;
93
+ if (version !== RESOLVED_EXECUTION_SCHEMA_VERSION) {
94
+ throw new TypeError(typeof version === "number" && version > RESOLVED_EXECUTION_SCHEMA_VERSION
95
+ ? `resolved execution request schemaVersion ${version} was written by a newer akm; upgrade akm to run it`
96
+ : `unsupported resolved execution schemaVersion: ${String(version)}`);
97
+ }
98
+ const command = requireRecord(input.command, "command");
99
+ if (typeof command.template !== "string" || typeof command.content !== "string") {
100
+ throw new TypeError("command template and content must be strings");
101
+ }
102
+ const engine = requireRecord(input.engine, "engine");
103
+ if (typeof engine.name !== "string" || (engine.kind !== "agent" && engine.kind !== "sdk" && engine.kind !== "llm")) {
104
+ throw new TypeError("engine.name must be a string and engine.kind must be agent, sdk, or llm");
569
105
  }
570
- const notices = requireOwn(input, "notices", "resolved execution request");
571
- const clonedNotices = cloneExecutionJson(notices, "resolved execution request.notices");
572
- if (!Array.isArray(clonedNotices))
573
- throw new TypeError("resolved execution request.notices must be an array");
106
+ const notices = input.notices;
107
+ if (!Array.isArray(notices))
108
+ throw new TypeError("notices must be an array");
574
109
  const request = {
575
- command: decodeResolvedCommand(requireOwn(input, "command", "resolved execution request")),
576
- engine: decodeEngine(requireOwn(input, "engine", "resolved execution request")),
577
- authorization: decodeAuthorization(requireOwn(input, "authorization", "resolved execution request")),
578
- runtime: decodeRuntime(requireOwn(input, "runtime", "resolved execution request")),
579
- notices: clonedNotices.map(decodeNotice),
110
+ command: Object.freeze({
111
+ ...pick(command, COMMAND_KEYS),
112
+ source: command.source === null ? null : decodeExecutionSourceIdentity(command.source, "command.source"),
113
+ }),
114
+ engine: Object.freeze(pick(engine, ENGINE_KEYS)),
115
+ authorization: Object.freeze(pick(requireRecord(input.authorization, "authorization"), AUTHORIZATION_KEYS)),
116
+ runtime: Object.freeze(pick(requireRecord(input.runtime, "runtime"), RUNTIME_KEYS)),
117
+ notices: Object.freeze(notices.map((notice, index) => Object.freeze(pick(requireRecord(notice, `notices[${index}]`), NOTICE_KEYS)))),
580
118
  };
581
- if (Object.hasOwn(input, "conversation")) {
582
- request.conversation = cloneConversation(input.conversation, "resolved execution request.conversation");
119
+ if (Array.isArray(input.conversation)) {
120
+ request.conversation = Object.freeze(input.conversation.map((message, index) => Object.freeze(pick(requireRecord(message, `conversation[${index}]`), ["role", "content"]))));
121
+ }
122
+ if (Object.hasOwn(input, "agent") && input.agent !== undefined)
123
+ request.agent = input.agent;
124
+ if (Object.hasOwn(input, "persona") && input.persona !== undefined) {
125
+ if (input.persona === null)
126
+ request.persona = null;
127
+ else {
128
+ const persona = requireRecord(input.persona, "persona");
129
+ request.persona = Object.freeze({
130
+ ...pick(persona, PERSONA_KEYS),
131
+ source: decodeExecutionSourceIdentity(persona.source, "persona.source"),
132
+ });
133
+ }
583
134
  }
584
- if (Object.hasOwn(input, "agent")) {
585
- request.agent = cloneAgentSelector(input.agent, "resolved execution request.agent");
135
+ if (Object.hasOwn(input, "model") && input.model !== undefined) {
136
+ request.model = input.model === null ? null : Object.freeze(pick(requireRecord(input.model, "model"), MODEL_KEYS));
586
137
  }
587
- if (Object.hasOwn(input, "persona")) {
588
- request.persona = input.persona === null ? null : decodeResolvedPersona(input.persona);
138
+ for (const key of ["inference", "outputSchema", "tools", "extensions"]) {
139
+ if (Object.hasOwn(input, key) && input[key] !== undefined)
140
+ request[key] = input[key];
589
141
  }
590
- if (Object.hasOwn(input, "model"))
591
- request.model = input.model === null ? null : decodeModel(input.model);
592
- if (Object.hasOwn(input, "inference"))
593
- request.inference = input.inference;
594
- if (Object.hasOwn(input, "outputSchema"))
595
- request.outputSchema = input.outputSchema;
596
- if (Object.hasOwn(input, "tools"))
597
- request.tools = input.tools;
598
- if (Object.hasOwn(input, "extensions"))
599
- request.extensions = decodeExtensions(input.extensions, "request.extensions");
600
142
  return createResolvedExecutionRequest(request);
601
143
  }
602
- function projectIdentity(identity) {
603
- return {
604
- ref: identity.ref,
605
- bundle: identity.bundle,
606
- adapter: identity.adapter,
607
- file: identity.file,
608
- hash: identity.hash,
609
- };
610
- }
611
- function projectCommand(command) {
612
- const out = {
613
- template: command.template,
614
- content: command.content,
615
- source: command.source === null ? null : projectIdentity(command.source),
616
- };
617
- if (Object.hasOwn(command, "argumentInput"))
618
- out.argumentInput = command.argumentInput;
619
- if (Object.hasOwn(command, "extensions"))
620
- out.extensions = command.extensions;
621
- return out;
622
- }
623
- function projectPersona(persona) {
624
- const out = { content: persona.content, source: projectIdentity(persona.source) };
625
- if (Object.hasOwn(persona, "extensions"))
626
- out.extensions = persona.extensions;
627
- return out;
628
- }
629
- function projectEngine(engine) {
630
- const out = { name: engine.name, kind: engine.kind };
631
- for (const key of ["platform", "settings", "extensions"]) {
632
- if (Object.hasOwn(engine, key))
633
- out[key] = engine[key];
634
- }
635
- return out;
636
- }
637
- function projectModel(model) {
638
- const out = {
639
- input: model.input,
640
- interpretation: model.interpretation,
641
- resolved: model.resolved,
642
- };
643
- if (Object.hasOwn(model, "extensions"))
644
- out.extensions = model.extensions;
645
- return out;
646
- }
647
- function projectAuthorization(authorization) {
648
- const out = { status: authorization.status };
649
- for (const key of ["reason", "policy"]) {
650
- if (Object.hasOwn(authorization, key))
651
- out[key] = authorization[key];
652
- }
653
- return out;
654
- }
655
- function projectRuntime(runtime) {
656
- const out = {};
657
- for (const key of ["timeoutMs", "workspace", "environment", "settings", "extensions"]) {
658
- if (Object.hasOwn(runtime, key))
659
- out[key] = runtime[key];
660
- }
661
- return out;
662
- }
663
- function projectNotice(notice) {
664
- const out = {
665
- code: notice.code,
666
- severity: notice.severity,
667
- adapter: notice.adapter,
668
- message: notice.message,
669
- };
670
- for (const key of ["field", "details"]) {
671
- if (Object.hasOwn(notice, key))
672
- out[key] = notice[key];
673
- }
674
- return out;
675
- }
676
- function projectConversationMessage(message) {
677
- return { role: message.role, content: message.content };
678
- }
679
- function projectResolvedExecutionWire(request) {
680
- const out = {
144
+ /** Stable bytes for freeze hashes and entrypoint-equivalence projections. */
145
+ export function canonicalResolvedExecutionRequest(request) {
146
+ const wire = {
681
147
  schemaVersion: RESOLVED_EXECUTION_SCHEMA_VERSION,
682
- command: projectCommand(request.command),
683
- engine: projectEngine(request.engine),
684
- authorization: projectAuthorization(request.authorization),
685
- runtime: projectRuntime(request.runtime),
686
- notices: request.notices.map(projectNotice),
148
+ command: {
149
+ ...pick(request.command, COMMAND_KEYS),
150
+ source: request.command.source === null ? null : pick(request.command.source, IDENTITY_KEYS),
151
+ },
152
+ engine: pick(request.engine, ENGINE_KEYS),
153
+ authorization: pick(request.authorization, AUTHORIZATION_KEYS),
154
+ runtime: pick(request.runtime, RUNTIME_KEYS),
155
+ notices: request.notices.map((notice) => pick(notice, NOTICE_KEYS)),
687
156
  };
688
- if (Object.hasOwn(request, "conversation")) {
689
- if (request.conversation === undefined) {
690
- throw new TypeError("constructed request conversation cannot be undefined");
691
- }
692
- out.conversation = request.conversation.map(projectConversationMessage);
693
- }
694
- if (Object.hasOwn(request, "agent")) {
695
- if (request.agent === undefined)
696
- throw new TypeError("constructed request agent cannot be undefined");
697
- out.agent = request.agent;
157
+ if (request.conversation !== undefined) {
158
+ wire.conversation = request.conversation.map((message) => ({ role: message.role, content: message.content }));
698
159
  }
699
- if (Object.hasOwn(request, "persona")) {
700
- if (request.persona === undefined)
701
- throw new TypeError("constructed request persona cannot be undefined");
702
- out.persona = request.persona === null ? null : projectPersona(request.persona);
160
+ if (Object.hasOwn(request, "agent") && request.agent !== undefined)
161
+ wire.agent = request.agent;
162
+ if (Object.hasOwn(request, "persona") && request.persona !== undefined) {
163
+ wire.persona =
164
+ request.persona === null
165
+ ? null
166
+ : { ...pick(request.persona, PERSONA_KEYS), source: pick(request.persona.source, IDENTITY_KEYS) };
703
167
  }
704
- if (Object.hasOwn(request, "model")) {
705
- if (request.model === undefined)
706
- throw new TypeError("constructed request model cannot be undefined");
707
- out.model = request.model === null ? null : projectModel(request.model);
168
+ if (Object.hasOwn(request, "model") && request.model !== undefined) {
169
+ wire.model = request.model === null ? null : pick(request.model, MODEL_KEYS);
708
170
  }
709
171
  for (const key of ["inference", "outputSchema", "tools", "extensions"]) {
710
- if (Object.hasOwn(request, key))
711
- out[key] = request[key];
712
- }
713
- return out;
714
- }
715
- function encodeResolvedExecutionWire(request) {
716
- const json = cloneExecutionJson(projectResolvedExecutionWire(request), "resolved execution request wire DTO");
717
- return `${JSON.stringify(sortExecutionJson(json))}\n`;
718
- }
719
- /** Stable bytes for freeze hashes and entrypoint-equivalence projections. */
720
- export function canonicalResolvedExecutionRequest(request) {
721
- if (typeof request !== "object" || request === null || !resolvedRequestInstances.has(request)) {
722
- throw new TypeError("resolved execution request must be constructed by the execution boundary");
723
- }
724
- const canonical = encodeResolvedExecutionWire(request);
725
- const decoded = decodeResolvedExecutionRequest(JSON.parse(canonical));
726
- if (encodeResolvedExecutionWire(decoded) !== canonical) {
727
- throw new TypeError("resolved execution request failed canonical decode/re-encode validation");
172
+ if (Object.hasOwn(request, key) && request[key] !== undefined)
173
+ wire[key] = request[key];
728
174
  }
729
- return canonical;
175
+ return `${JSON.stringify(sortExecutionJson(wire))}\n`;
730
176
  }