akm-cli 0.9.16 → 0.9.17-alpha.10
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.
- package/CHANGELOG.md +2101 -0
- package/STABILITY.md +11 -10
- package/dist/akm +124 -193
- package/dist/akm-migrate +38 -19
- package/dist/assets/hints/cli-hints-full.md +6 -7
- package/dist/assets/improve-strategies/catchup.json +0 -3
- package/dist/assets/improve-strategies/consolidate.json +0 -1
- package/dist/assets/improve-strategies/default.json +1 -2
- package/dist/assets/improve-strategies/proactive-maintenance.json +1 -2
- package/dist/assets/improve-strategies/quick.json +1 -2
- package/dist/assets/improve-strategies/reflect-distill.json +1 -2
- package/dist/assets/improve-strategies/thorough.json +0 -3
- package/dist/assets/prompts/consolidate-pair.md +20 -0
- package/dist/assets/prompts/consolidate-system.md +4 -11
- package/dist/assets/prompts/retrieval-relevance-judge.md +6 -0
- package/dist/assets/stash-skeleton/facts/conventions/backlinks.md +20 -20
- package/dist/assets/stash-skeleton/facts/conventions/domains.md +2 -2
- package/dist/assets/templates/html/health.html +3 -5
- package/dist/cli/retired-commands.js +1 -1
- package/dist/cli/shared.js +6 -2
- package/dist/cli/unknown-flags.js +24 -1
- package/dist/cli.js +68 -10
- package/dist/commands/agent/agent-dispatch.js +1 -1
- package/dist/commands/command/command-execution.js +24 -62
- package/dist/commands/feedback-cli.js +0 -1
- package/dist/commands/health/accept-rate.js +6 -0
- package/dist/commands/health/archive-usage.js +92 -0
- package/dist/commands/health/checks.js +83 -74
- package/dist/commands/health/config-skew.js +38 -0
- package/dist/commands/health/data-dir-usage.js +25 -13
- package/dist/commands/health/egress.js +54 -0
- package/dist/commands/health/html-report.js +1 -42
- package/dist/commands/health/improve-metrics.js +136 -591
- package/dist/commands/health/md-report.js +1 -6
- package/dist/commands/health/plugin-staleness.js +53 -3
- package/dist/commands/health/renderers.js +12 -4
- package/dist/commands/health/report-view-model.js +14 -120
- package/dist/commands/health/types-improve.js +4 -19
- package/dist/commands/health/windows.js +64 -74
- package/dist/commands/health.js +145 -143
- package/dist/commands/improve/consolidate/chunking.js +26 -117
- package/dist/commands/improve/consolidate/continuity-check.js +137 -0
- package/dist/commands/improve/consolidate/pair-pass.js +791 -0
- package/dist/commands/improve/consolidate/sanitize.js +54 -149
- package/dist/commands/improve/consolidate.js +589 -1127
- package/dist/commands/improve/content-hash.js +16 -24
- package/dist/commands/improve/distill/content-repair.js +18 -100
- package/dist/commands/improve/distill-guards.js +20 -81
- package/dist/commands/improve/distill-promotion-policy.js +23 -243
- package/dist/commands/improve/distill.js +608 -1041
- package/dist/commands/improve/eligibility.js +126 -390
- package/dist/commands/improve/execution.js +8 -10
- package/dist/commands/improve/extract-prompt.js +1 -2
- package/dist/commands/improve/extract.js +487 -1046
- package/dist/commands/improve/feedback-valence.js +0 -25
- package/dist/commands/improve/improve-cli.js +75 -169
- package/dist/commands/improve/improve-result-file.js +10 -66
- package/dist/commands/improve/improve-strategies.js +52 -4
- package/dist/commands/improve/improve-usage-report.js +18 -64
- package/dist/commands/improve/improve.js +480 -1074
- package/dist/commands/improve/ledger.js +119 -0
- package/dist/commands/improve/locks.js +2 -8
- package/dist/commands/improve/loop-stages.js +415 -1073
- package/dist/commands/improve/memory/derived-ref.js +12 -77
- package/dist/commands/improve/memory/memory-belief.js +16 -118
- package/dist/commands/improve/memory/memory-improve.js +266 -14
- package/dist/commands/improve/outcome-loop.js +28 -156
- package/dist/commands/improve/planner.js +5 -15
- package/dist/commands/improve/preparation.js +779 -2319
- package/dist/commands/improve/proactive-maintenance.js +34 -101
- package/dist/commands/improve/reflect-noise.js +104 -280
- package/dist/commands/improve/reflect.js +642 -1353
- package/dist/commands/improve/retrieval-gate.js +127 -0
- package/dist/commands/improve/retrieval-scope.js +92 -0
- package/dist/commands/improve/salience.js +41 -240
- package/dist/commands/improve/session-asset.js +19 -100
- package/dist/commands/improve/stage.js +322 -0
- package/dist/commands/lint/base-linter.js +37 -15
- package/dist/commands/proposal/drain.js +261 -578
- package/dist/commands/proposal/proposal-cli.js +19 -20
- package/dist/commands/proposal/proposal-types.js +31 -24
- package/dist/commands/proposal/proposal.js +38 -8
- package/dist/commands/proposal/propose.js +134 -160
- package/dist/commands/proposal/repository.js +1097 -1394
- package/dist/commands/proposal/validators/proposal-quality-validators.js +71 -174
- package/dist/commands/proposal/validators/proposal-validators.js +1 -1
- package/dist/commands/proposal/validators/proposals.js +22 -89
- package/dist/commands/read/curate.js +105 -462
- package/dist/commands/read/knowledge.js +3 -2
- package/dist/commands/read/search-cli.js +16 -33
- package/dist/commands/read/search.js +17 -23
- package/dist/commands/read/show.js +57 -108
- package/dist/commands/sources/bundle-cli.js +25 -2
- package/dist/commands/sources/bundle-config-ops.js +4 -0
- package/dist/commands/sources/dangerous-env-audit.js +1 -2
- package/dist/commands/sources/info.js +127 -29
- package/dist/commands/sources/installed-stashes.js +197 -746
- package/dist/commands/sources/schema-repair.js +98 -129
- package/dist/commands/sources/source-add.js +62 -12
- package/dist/commands/sources/source-manage.js +9 -2
- package/dist/commands/sources/stash-cli.js +24 -4
- package/dist/commands/tasks/explain.js +10 -13
- package/dist/commands/tasks/tasks-cli.js +12 -13
- package/dist/commands/tasks/tasks.js +350 -936
- package/dist/commands/tasks/validate.js +26 -24
- package/dist/commands/workflow/plan.js +22 -29
- package/dist/commands/workflow-cli.js +4 -4
- package/dist/core/adapter/adapters/akm-adapter.js +2 -1
- package/dist/core/adapter/adapters/akm-lint.js +2 -3
- package/dist/core/adapter/adapters/akm-metadata.js +42 -12
- package/dist/core/adapter/adapters/akm-task-adapter.js +29 -8
- package/dist/core/adapter/adapters/akm-workflow-adapter.js +1 -1
- package/dist/core/adapter/execution-source.js +17 -29
- package/dist/core/asset/asset-placement.js +4 -13
- package/dist/core/asset/frontmatter.js +106 -1
- package/dist/core/asset/resolve-ref.js +1 -1
- package/dist/core/bundle-id.js +42 -5
- package/dist/core/bundle-rename.js +285 -0
- package/dist/core/config/config-io.js +1 -2
- package/dist/core/config/config-schema.js +9 -34
- package/dist/core/config/config-walker.js +1 -1
- package/dist/core/config/config.js +184 -111
- package/dist/core/config/engine-semantics.js +0 -2
- package/dist/core/config/legacy-source-shape-shim.js +38 -9
- package/dist/core/config/schema/embedding.js +20 -5
- package/dist/core/config/schema/engines.js +5 -0
- package/dist/core/config/schema/execution.js +1 -1
- package/dist/core/config/schema/experimental.js +1 -1
- package/dist/core/config/schema/improve-processes.js +54 -125
- package/dist/core/config/schema/improve.js +4 -42
- package/dist/core/config/schema/index-config.js +9 -48
- package/dist/core/config/schema/scheduler.js +12 -12
- package/dist/core/config/schema/search.js +6 -22
- package/dist/core/env-secret-ref.js +0 -1
- package/dist/core/errors.js +8 -9
- package/dist/core/file-change.js +13 -5
- package/dist/core/file-lock.js +76 -173
- package/dist/core/improve-result.js +35 -7
- package/dist/core/improve-types.js +0 -1
- package/dist/core/logs-db.js +2 -2
- package/dist/core/loopback.js +7 -12
- package/dist/core/non-task-input.js +20 -0
- package/dist/core/parse.js +13 -16
- package/dist/core/paths.js +0 -24
- package/dist/core/redaction.js +109 -2
- package/dist/core/run-lock.js +2 -5
- package/dist/core/spawn-env.js +1 -1
- package/dist/core/state/migrations.js +123 -61
- package/dist/core/state-db-scope.js +2 -4
- package/dist/core/state-db.js +126 -692
- package/dist/core/time.js +0 -20
- package/dist/core/type-presentation.js +1 -9
- package/dist/core/write-source.js +294 -1005
- package/dist/execution/input-contract.js +1 -1
- package/dist/execution/resolved-request.js +135 -689
- package/dist/execution/source.js +63 -257
- package/dist/execution/target-ref.js +1 -1
- package/dist/indexer/bundle-identity-guard.js +2 -2
- package/dist/indexer/db/llm-cache.js +2 -2
- package/dist/indexer/ensure-index.js +77 -73
- package/dist/indexer/index-rebuild-lock.js +3 -11
- package/dist/indexer/index-writer-lock.js +8 -17
- package/dist/indexer/index-written-assets.js +141 -154
- package/dist/indexer/indexer.js +400 -1124
- package/dist/indexer/links/declared-links.js +90 -0
- package/dist/indexer/materialize-embeddings.js +60 -397
- package/dist/indexer/passes/memory-inference.js +96 -90
- package/dist/indexer/passes/metadata.js +132 -219
- package/dist/indexer/read-preflight.js +0 -7
- package/dist/indexer/scan/doc-to-entry.js +2 -3
- package/dist/indexer/scan/drain-dir.js +1 -1
- package/dist/indexer/search/db-search.js +190 -590
- package/dist/indexer/search/fts-query.js +30 -41
- package/dist/indexer/search/ranking.js +28 -154
- package/dist/indexer/search/search-attribution.js +12 -32
- package/dist/indexer/search/search-fields.js +11 -15
- package/dist/indexer/search/search-hit-enrichers.js +54 -85
- package/dist/indexer/search/search-source.js +1 -4
- package/dist/indexer/usage/usage-events.js +36 -7
- package/dist/indexer/walk/walker.js +3 -4
- package/dist/integrations/agent/engine-fallback.js +23 -40
- package/dist/integrations/agent/engine-resolution.js +93 -183
- package/dist/integrations/agent/execution.js +507 -0
- package/dist/integrations/agent/model-map.js +28 -156
- package/dist/integrations/agent/request-lowering.js +66 -141
- package/dist/integrations/agent/runner-dispatch.js +143 -321
- package/dist/integrations/agent/runner.js +54 -14
- package/dist/integrations/lockfile.js +53 -101
- package/dist/llm/client.js +18 -6
- package/dist/llm/embedders/deterministic.js +2 -3
- package/dist/llm/embedders/profile.js +71 -0
- package/dist/llm/embedders/remote.js +11 -17
- package/dist/llm/feature-gate.js +0 -8
- package/dist/llm/index-passes.js +3 -5
- package/dist/llm/memory-infer.js +1 -2
- package/dist/llm/structured-call.js +5 -24
- package/dist/output/generic-render.js +23 -11
- package/dist/output/html-render.js +13 -10
- package/dist/output/render-registry.js +3 -32
- package/dist/output/shapes/helpers.js +25 -38
- package/dist/output/shapes/passthrough.js +1 -9
- package/dist/{indexer/graph/graph-types.js → output/text/bundle-rename.js} +4 -1
- package/dist/output/text/command-format.js +69 -31
- package/dist/output/text/helpers.js +1 -1
- package/dist/output/text/migrate.js +5 -14
- package/dist/output/text/proposal-format.js +48 -3
- package/dist/output/text/show-format.js +13 -17
- package/dist/output/text/workflow-format.js +0 -32
- package/dist/output/text.js +2 -0
- package/dist/registry/factory.js +4 -19
- package/dist/registry/network.js +66 -220
- package/dist/registry/providers/index.js +0 -2
- package/dist/registry/providers/skills-sh.js +3 -14
- package/dist/registry/providers/static-index.js +24 -26
- package/dist/registry/resolve.js +55 -131
- package/dist/scripts/akm-migrate-node.js +42948 -92369
- package/dist/scripts/akm-migrate.js +42935 -92354
- package/dist/setup/registry-stash-loader.js +4 -13
- package/dist/setup/semantic-assets.js +3 -44
- package/dist/setup/setup.js +1 -1
- package/dist/setup/steps/connection.js +5 -6
- package/dist/setup/steps/platforms.js +2 -2
- package/dist/setup/steps/tasks.js +25 -15
- package/dist/sources/provider-factory.js +17 -18
- package/dist/sources/providers/filesystem.js +2 -3
- package/dist/sources/providers/git-install.js +7 -1
- package/dist/sources/providers/git-provider.js +0 -3
- package/dist/sources/providers/git-stash.js +83 -21
- package/dist/sources/providers/npm.js +2 -4
- package/dist/sources/providers/provider-utils.js +5 -10
- package/dist/sources/providers/website.js +0 -2
- package/dist/sources/snapshot-fetchers/website-ingest.js +1 -1
- package/dist/sources/website-url.js +2 -2
- package/dist/storage/database.js +9 -35
- package/dist/storage/repositories/improve-ledger-repository.js +209 -0
- package/dist/storage/repositories/index-connection.js +39 -72
- package/dist/storage/repositories/index-entries-repository.js +131 -129
- package/dist/storage/repositories/index-entry-mapper.js +1 -2
- package/dist/storage/repositories/index-entry-schema.js +101 -268
- package/dist/storage/repositories/index-fts-repository.js +86 -256
- package/dist/storage/repositories/index-links-repository.js +143 -0
- package/dist/storage/repositories/index-llm-cache-repository.js +7 -9
- package/dist/storage/repositories/index-meta-repository.js +6 -4
- package/dist/storage/repositories/index-schema.js +257 -325
- package/dist/storage/repositories/index-utility-repository.js +8 -29
- package/dist/storage/repositories/index-vec-repository.js +133 -414
- package/dist/storage/repositories/outcome-repository.js +2 -1
- package/dist/storage/repositories/proposals-repository.js +104 -1
- package/dist/storage/repositories/registry-index-cache-repository.js +100 -0
- package/dist/storage/repositories/salience-repository.js +1 -19
- package/dist/storage/repositories/task-history-repository.js +26 -4
- package/dist/storage/repositories/workflow-runs-repository.js +53 -244
- package/dist/storage/sqlite-migrations.js +136 -0
- package/dist/storage/sqlite-pragmas.js +11 -9
- package/dist/storage/sqlite-transaction.js +170 -0
- package/dist/storage/state-db-integrity.js +130 -0
- package/dist/tasks/activation-config.js +134 -62
- package/dist/tasks/backends/cron.js +191 -302
- package/dist/tasks/backends/exec-utils.js +2 -5
- package/dist/tasks/backends/launchd.js +141 -748
- package/dist/tasks/backends/schtasks.js +119 -623
- package/dist/tasks/prepare/prepare-support.js +5 -15
- package/dist/tasks/prepare/prepare.js +0 -2
- package/dist/tasks/resolve-akm-bin.js +20 -79
- package/dist/tasks/run/attempt-lifecycle.js +0 -1
- package/dist/tasks/run/load-task.js +1 -1
- package/dist/tasks/scheduler-binding.js +20 -238
- package/dist/tasks/scheduler-invocation.js +136 -244
- package/dist/tasks/scheduler-lock.js +53 -0
- package/dist/tasks/scheduler-sync.js +368 -679
- package/dist/tasks/source/parse-task-source.js +55 -9
- package/dist/tasks/source/task-source-v3-frozen.js +3 -4
- package/dist/tasks/source/task-to-v4.js +464 -88
- package/dist/workflows/authoring/authoring.js +3 -12
- package/dist/workflows/compile.js +211 -0
- package/dist/workflows/concurrency-policy.js +13 -74
- package/dist/workflows/exec/child-invocation.js +3 -17
- package/dist/workflows/exec/child-workflow.js +32 -141
- package/dist/workflows/exec/dispatch-redaction.js +13 -53
- package/dist/workflows/exec/environment.js +98 -0
- package/dist/workflows/exec/exec-unit.js +33 -140
- package/dist/workflows/exec/frozen-judge.js +7 -59
- package/dist/workflows/exec/native-executor.js +82 -341
- package/dist/workflows/exec/param-secrets.js +29 -47
- package/dist/workflows/exec/run-workflow.js +154 -387
- package/dist/workflows/exec/scheduler.js +9 -36
- package/dist/workflows/exec/step-work.js +127 -430
- package/dist/workflows/exec/unit-dispatch.js +11 -63
- package/dist/workflows/exec/unit-writer.js +8 -52
- package/dist/workflows/exec/worktree.js +39 -273
- package/dist/workflows/freeze/child-output-references.js +4 -15
- package/dist/workflows/freeze/environment.js +99 -92
- package/dist/workflows/freeze/freeze.js +172 -0
- package/dist/workflows/freeze/step-values.js +19 -21
- package/dist/workflows/freeze/targets/child-workflow.js +23 -92
- package/dist/workflows/freeze/targets/command.js +10 -33
- package/dist/workflows/freeze/targets/script.js +5 -12
- package/dist/workflows/freeze/targets/shell.js +3 -6
- package/dist/workflows/freeze/targets/task.js +25 -80
- package/dist/workflows/freeze/task-bindings.js +20 -67
- package/dist/workflows/{source-ir/github-yaml.js → github-yaml.js} +88 -206
- package/dist/workflows/ir/params.js +6 -51
- package/dist/workflows/ir/plan-hash.js +2 -34
- package/dist/workflows/parser.js +140 -43
- package/dist/{commands/improve/consolidate/types.js → workflows/plan.js} +2 -1
- package/dist/workflows/renderer.js +36 -69
- package/dist/workflows/resource-limits.js +12 -120
- package/dist/workflows/runtime/agent-identity.js +8 -40
- package/dist/workflows/runtime/run-outputs.js +3 -6
- package/dist/workflows/runtime/run-plan.js +316 -0
- package/dist/workflows/runtime/runs.js +48 -200
- package/dist/workflows/runtime/workflow-asset-loader.js +24 -57
- package/dist/workflows/{source-ir/semantics.js → source-semantics.js} +16 -20
- package/dist/workflows/validate-summary.js +2 -7
- package/docs/integration/bundling-akm.md +49 -42
- package/docs/migration/README.md +1 -0
- package/docs/migration/release-notes/0.9.17.md +43 -0
- package/docs/migration/v0.9.1-to-v0.9.2.md +23 -7
- package/docs/reference/cli.md +232 -135
- package/docs/reference/configuration.md +71 -57
- package/docs/reference/data-and-telemetry.md +20 -21
- package/docs/reference/tasks.md +105 -39
- package/docs/reference/workflow-schema.md +14 -18
- package/docs/reference/workflows.md +6 -9
- package/package.json +1 -1
- package/schemas/akm-config.json +115 -738
- package/schemas/akm-workflow.json +1 -0
- package/dist/assets/improve-strategies/graph-refresh.json +0 -15
- package/dist/assets/prompts/contradiction-judge.md +0 -33
- package/dist/assets/prompts/graph-extract-system.md +0 -1
- package/dist/assets/prompts/graph-extract-user-prompt.md +0 -35
- package/dist/assets/prompts/metadata-enhance-system.md +0 -1
- package/dist/assets/tasks/improve/akm-graph-refresh-weekly.yml +0 -4
- package/dist/commands/health/advisories.js +0 -150
- package/dist/commands/health/metrics.js +0 -329
- package/dist/commands/health/surfaces.js +0 -102
- package/dist/commands/improve/anti-collapse.js +0 -83
- package/dist/commands/improve/collapse-detector.js +0 -432
- package/dist/commands/improve/consolidate/eligibility.js +0 -48
- package/dist/commands/improve/consolidate/merge.js +0 -149
- package/dist/commands/improve/distill/promote-memory.js +0 -291
- package/dist/commands/improve/distill/quality-gate.js +0 -337
- package/dist/commands/improve/eval-cases.js +0 -52
- package/dist/commands/improve/memory/memory-contradiction-detect.js +0 -291
- package/dist/commands/improve/proposal-envelope.js +0 -31
- package/dist/commands/improve/run-context.js +0 -123
- package/dist/commands/improve/shared.js +0 -31
- package/dist/commands/improve/source-identity.js +0 -28
- package/dist/commands/improve/triage.js +0 -96
- package/dist/commands/proposal/drain-policies.js +0 -151
- package/dist/commands/sources/update-transaction.js +0 -220
- package/dist/core/action-contributors.js +0 -28
- package/dist/core/config/config-version-shim.js +0 -101
- package/dist/core/fs-txn.js +0 -405
- package/dist/core/lexical-score.js +0 -25
- package/dist/core/maintenance-barrier.js +0 -167
- package/dist/execution/executable-identity.js +0 -105
- package/dist/execution/guarded-source.js +0 -427
- package/dist/indexer/db/graph-db.js +0 -444
- package/dist/indexer/graph/graph-boost.js +0 -427
- package/dist/indexer/graph/graph-dedup.js +0 -95
- package/dist/indexer/graph/graph-extraction.js +0 -1108
- package/dist/indexer/search/name-match.js +0 -35
- package/dist/indexer/search/ranking-contributors.js +0 -515
- package/dist/indexer/search/ranking-types.js +0 -4
- package/dist/indexer/walk/project-context.js +0 -192
- package/dist/integrations/agent/execution-cascade.js +0 -566
- package/dist/integrations/agent/execution-definitions.js +0 -202
- package/dist/integrations/agent/execution-lowering.js +0 -841
- package/dist/integrations/agent/execution-preparation.js +0 -98
- package/dist/integrations/agent/inline-execution.js +0 -74
- package/dist/llm/graph-extract.js +0 -728
- package/dist/llm/metadata-enhance.js +0 -96
- package/dist/registry/create-provider-registry.js +0 -29
- package/dist/registry/pinned-request-helper.js +0 -247
- package/dist/registry/pinned-transport.js +0 -717
- package/dist/sources/providers/index.js +0 -14
- package/dist/storage/engines/sqlite-migrations.js +0 -271
- package/dist/storage/repositories/canaries-repository.js +0 -107
- package/dist/storage/repositories/embedding-salvage-repository.js +0 -184
- package/dist/storage/repositories/registry-cache.js +0 -113
- package/dist/tasks/scheduler-sync-preview.js +0 -52
- package/dist/tasks/source/task-to-v3.js +0 -507
- package/dist/workflows/freeze/resolve-steps.js +0 -86
- package/dist/workflows/freeze/source-freeze.js +0 -64
- package/dist/workflows/ir/compile.js +0 -321
- package/dist/workflows/ir/environment-v4.js +0 -330
- package/dist/workflows/ir/freeze-v4.js +0 -153
- package/dist/workflows/ir/schema-v4.js +0 -745
- package/dist/workflows/ir/schema.js +0 -354
- package/dist/workflows/program/schema.js +0 -77
- package/dist/workflows/runtime/checkin.js +0 -57
- package/dist/workflows/runtime/plan-classifier.js +0 -196
- package/dist/workflows/runtime/unit-checkin.js +0 -45
- package/dist/workflows/runtime/unit-phases.js +0 -20
- package/dist/workflows/schema.js +0 -4
- package/dist/workflows/source-ir/compile.js +0 -200
- package/dist/workflows/source-ir/program.js +0 -50
- package/dist/workflows/source-ir/result.js +0 -26
- package/dist/workflows/source-ir/schema.js +0 -786
- package/dist/workflows/source-ir/triggers.js +0 -79
- package/dist/workflows/source-ir/uses.js +0 -40
- package/dist/workflows/validator.js +0 -60
|
@@ -0,0 +1,507 @@
|
|
|
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 { deepMergeConfig } from "../../core/config/deep-merge.js";
|
|
5
|
+
import { ConfigError } from "../../core/errors.js";
|
|
6
|
+
import { DURATION_UNITS, parseDuration } from "../../core/time.js";
|
|
7
|
+
import { EXECUTION_MAX_TIMEOUT_MS } from "../../execution/limits.js";
|
|
8
|
+
import { createInlineResolvedCommand, createResolvedExecutionRequest, decodeResolvedExecutionRequest, } from "../../execution/resolved-request.js";
|
|
9
|
+
import { cloneToolSelection, isPortableExecutionAgentSelector, } from "../../execution/source.js";
|
|
10
|
+
import { getHarness } from "../harnesses/index.js";
|
|
11
|
+
import { DEFAULT_AGENT_TIMEOUT_MS, DEFAULT_LLM_TIMEOUT_MS } from "./config.js";
|
|
12
|
+
import { FALLBACK_ENGINE_NAME, fallbackEngineConfig, NO_ENGINE_MESSAGE_SUFFIX, NO_ENGINE_REMEDY, } from "./engine-fallback.js";
|
|
13
|
+
import { configuredEngine, resolveEngine } from "./engine-resolution.js";
|
|
14
|
+
import { engineModelAndInference, loadModelMap, resolveModelMapAlias } from "./model-map.js";
|
|
15
|
+
import { extensionFields, hasToolSelection, untranslated } from "./request-lowering.js";
|
|
16
|
+
import { decodeFrozenRunnerSpec } from "./runner.js";
|
|
17
|
+
const LLM_INFERENCE_FIELDS = [
|
|
18
|
+
"temperature",
|
|
19
|
+
"maxTokens",
|
|
20
|
+
"supportsJsonSchema",
|
|
21
|
+
"extraParams",
|
|
22
|
+
"contextLength",
|
|
23
|
+
"enableThinking",
|
|
24
|
+
"reasoningEffort",
|
|
25
|
+
];
|
|
26
|
+
function has(values, key) {
|
|
27
|
+
return (values !== null &&
|
|
28
|
+
values !== undefined &&
|
|
29
|
+
Object.hasOwn(values, key) &&
|
|
30
|
+
values[key] !== undefined);
|
|
31
|
+
}
|
|
32
|
+
function nearest(layers, key) {
|
|
33
|
+
for (let index = layers.length - 1; index >= 0; index -= 1) {
|
|
34
|
+
const layer = layers[index];
|
|
35
|
+
if (layer && has(layer.values, key))
|
|
36
|
+
return layer;
|
|
37
|
+
}
|
|
38
|
+
return undefined;
|
|
39
|
+
}
|
|
40
|
+
function explicit(layer, via = "explicit") {
|
|
41
|
+
return { layer: layer.id, kind: layer.kind, via };
|
|
42
|
+
}
|
|
43
|
+
function inferenceOf(source) {
|
|
44
|
+
const out = {};
|
|
45
|
+
for (const key of LLM_INFERENCE_FIELDS)
|
|
46
|
+
if (source[key] !== undefined)
|
|
47
|
+
out[key] = source[key];
|
|
48
|
+
return Object.keys(out).length > 0 ? out : undefined;
|
|
49
|
+
}
|
|
50
|
+
/** A configured engine's model, inference, timeout and workspace, and where its aliases resolve. */
|
|
51
|
+
function engineDefaults(name, engine, config) {
|
|
52
|
+
const own = engineModelAndInference(engine);
|
|
53
|
+
const values = {
|
|
54
|
+
...(own.model !== undefined ? { model: own.model } : {}),
|
|
55
|
+
...(own.inference !== undefined ? { inference: own.inference } : {}),
|
|
56
|
+
...(Object.hasOwn(engine, "timeoutMs") ? { timeout: engine.timeoutMs ?? null } : {}),
|
|
57
|
+
};
|
|
58
|
+
if (engine.kind === "llm")
|
|
59
|
+
return { kind: "llm", platform: engine.provider ?? name, modelMapKey: name, values };
|
|
60
|
+
if (engine.workspace !== undefined)
|
|
61
|
+
values.workspace = engine.workspace;
|
|
62
|
+
if (engine.platform !== "opencode-sdk") {
|
|
63
|
+
return { kind: "agent", platform: engine.platform, modelMapKey: engine.platform, values };
|
|
64
|
+
}
|
|
65
|
+
// An SDK engine runs its LLM fallback's model/inference/timeout unless it sets its own.
|
|
66
|
+
const fallbackName = engine.llmEngine ?? config.defaults?.llmEngine;
|
|
67
|
+
const fallback = fallbackName && config.engines && Object.hasOwn(config.engines, fallbackName)
|
|
68
|
+
? config.engines[fallbackName]
|
|
69
|
+
: undefined;
|
|
70
|
+
if (fallback?.kind !== "llm" || !fallbackName) {
|
|
71
|
+
return {
|
|
72
|
+
kind: "sdk",
|
|
73
|
+
platform: "opencode-sdk",
|
|
74
|
+
modelMapKey: "opencode-sdk",
|
|
75
|
+
values: {
|
|
76
|
+
...values,
|
|
77
|
+
timeout: has(values, "timeout") ? values.timeout : DEFAULT_AGENT_TIMEOUT_MS,
|
|
78
|
+
},
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
const inherited = engineModelAndInference(fallback);
|
|
82
|
+
return {
|
|
83
|
+
kind: "sdk",
|
|
84
|
+
platform: "opencode-sdk",
|
|
85
|
+
modelMapKey: own.model === undefined ? fallbackName : "opencode-sdk",
|
|
86
|
+
values: {
|
|
87
|
+
...(inherited.model !== undefined ? { model: inherited.model } : {}),
|
|
88
|
+
...(inherited.inference !== undefined ? { inference: inherited.inference } : {}),
|
|
89
|
+
...values,
|
|
90
|
+
timeout: Object.hasOwn(engine, "timeoutMs")
|
|
91
|
+
? (engine.timeoutMs ?? null)
|
|
92
|
+
: Object.hasOwn(fallback, "timeoutMs")
|
|
93
|
+
? (fallback.timeoutMs ?? null)
|
|
94
|
+
: DEFAULT_LLM_TIMEOUT_MS,
|
|
95
|
+
},
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
/** The same defaults read back from an already-resolved runner. */
|
|
99
|
+
function runnerDefaults(runner) {
|
|
100
|
+
const timeout = Object.hasOwn(runner, "timeoutMs") ? { timeout: runner.timeoutMs ?? null } : {};
|
|
101
|
+
if (runner.kind === "llm") {
|
|
102
|
+
const inference = inferenceOf(runner.connection);
|
|
103
|
+
return {
|
|
104
|
+
kind: "llm",
|
|
105
|
+
platform: runner.connection.provider ?? runner.engine,
|
|
106
|
+
modelMapKey: runner.engine,
|
|
107
|
+
values: {
|
|
108
|
+
...(runner.connection.model !== undefined ? { model: runner.connection.model } : {}),
|
|
109
|
+
...(inference ? { inference } : {}),
|
|
110
|
+
...timeout,
|
|
111
|
+
},
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
const platform = runner.profile.platform ?? runner.profile.name;
|
|
115
|
+
const fallback = runner.kind === "sdk" ? runner.fallbackConnection : undefined;
|
|
116
|
+
const model = runner.profile.model ?? fallback?.model;
|
|
117
|
+
const inference = fallback ? inferenceOf(fallback) : undefined;
|
|
118
|
+
return {
|
|
119
|
+
kind: runner.kind,
|
|
120
|
+
platform,
|
|
121
|
+
modelMapKey: platform,
|
|
122
|
+
values: {
|
|
123
|
+
...(model !== undefined ? { model } : {}),
|
|
124
|
+
...(inference ? { inference } : {}),
|
|
125
|
+
...timeout,
|
|
126
|
+
...(runner.profile.workspace !== undefined ? { workspace: runner.profile.workspace } : {}),
|
|
127
|
+
},
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* The engine, from an ordered list: the nearest layer that names one, then
|
|
132
|
+
* `defaults.engine`, then the implicit opencode-sdk fallback when its binary
|
|
133
|
+
* is present. A named engine that is not configured is an error, never rescued.
|
|
134
|
+
*/
|
|
135
|
+
function selectEngine(config, layers) {
|
|
136
|
+
for (let index = layers.length - 1; index >= 0; index -= 1) {
|
|
137
|
+
const layer = layers[index];
|
|
138
|
+
const name = layer?.values.engine;
|
|
139
|
+
if (layer && typeof name === "string" && name.length > 0) {
|
|
140
|
+
return { name, engine: configuredEngine(name, config), provenance: explicit(layer), fallback: false };
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
const installed = config.defaults?.engine;
|
|
144
|
+
if (installed) {
|
|
145
|
+
return {
|
|
146
|
+
name: installed,
|
|
147
|
+
engine: configuredEngine(installed, config),
|
|
148
|
+
provenance: { layer: "installation-defaults", kind: "installation", via: "explicit" },
|
|
149
|
+
fallback: false,
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
const fallback = fallbackEngineConfig(config);
|
|
153
|
+
if (fallback) {
|
|
154
|
+
return {
|
|
155
|
+
name: FALLBACK_ENGINE_NAME,
|
|
156
|
+
engine: fallback,
|
|
157
|
+
provenance: { layer: FALLBACK_ENGINE_NAME, kind: "fallback", via: "fallback" },
|
|
158
|
+
fallback: true,
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
throw new ConfigError(`Execution ${NO_ENGINE_MESSAGE_SUFFIX}`, "INVALID_CONFIG_FILE", NO_ENGINE_REMEDY);
|
|
162
|
+
}
|
|
163
|
+
function parseTimeout(value) {
|
|
164
|
+
if (value === null)
|
|
165
|
+
return null;
|
|
166
|
+
const milliseconds = typeof value === "string" ? parseDuration(value, DURATION_UNITS) : value;
|
|
167
|
+
if (typeof milliseconds !== "number" ||
|
|
168
|
+
!Number.isInteger(milliseconds) ||
|
|
169
|
+
milliseconds < 0 ||
|
|
170
|
+
milliseconds > EXECUTION_MAX_TIMEOUT_MS) {
|
|
171
|
+
throw new ConfigError("Execution timeout must be null, a whole number of milliseconds, or a duration such as 20m.", "INVALID_CONFIG_FILE");
|
|
172
|
+
}
|
|
173
|
+
return milliseconds;
|
|
174
|
+
}
|
|
175
|
+
/** Tool names a selection asks for; `undefined` when a structured policy cannot be reduced to names. */
|
|
176
|
+
function requestedToolNames(tools) {
|
|
177
|
+
if (typeof tools === "string") {
|
|
178
|
+
return tools
|
|
179
|
+
.split(",")
|
|
180
|
+
.map((tool) => tool.trim())
|
|
181
|
+
.filter(Boolean);
|
|
182
|
+
}
|
|
183
|
+
if (Array.isArray(tools))
|
|
184
|
+
return tools.map((tool) => tool.trim()).filter(Boolean);
|
|
185
|
+
const policy = tools;
|
|
186
|
+
if (Object.values(policy).some((value) => typeof value !== "boolean"))
|
|
187
|
+
return undefined;
|
|
188
|
+
return Object.keys(policy).filter((tool) => policy[tool] === true);
|
|
189
|
+
}
|
|
190
|
+
/** Assets may only narrow the host's `execution.allowedTools`; without a config nothing is allowed. */
|
|
191
|
+
function authorizeTools(tools, config) {
|
|
192
|
+
if (!hasToolSelection(tools))
|
|
193
|
+
return { status: "not-required" };
|
|
194
|
+
if (!config) {
|
|
195
|
+
return {
|
|
196
|
+
status: "denied",
|
|
197
|
+
reason: "Selected tools require an explicit machine/user authorization policy.",
|
|
198
|
+
policy: { id: "unconfigured" },
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
const allowed = new Set(config.execution?.allowedTools ?? []);
|
|
202
|
+
const names = requestedToolNames(tools);
|
|
203
|
+
const permitted = allowed.has("*") || names?.every((tool) => allowed.has(tool)) === true;
|
|
204
|
+
return permitted
|
|
205
|
+
? {
|
|
206
|
+
status: "allowed",
|
|
207
|
+
reason: "Selected tools were authorized by operator policy.",
|
|
208
|
+
policy: { id: "config-execution-allowed-tools" },
|
|
209
|
+
}
|
|
210
|
+
: {
|
|
211
|
+
status: "denied",
|
|
212
|
+
reason: "Selected tools are not authorized by operator policy.",
|
|
213
|
+
policy: { id: "config-execution-allowed-tools" },
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
function withInference(connection, inference) {
|
|
217
|
+
const out = { ...connection };
|
|
218
|
+
for (const key of LLM_INFERENCE_FIELDS)
|
|
219
|
+
delete out[key];
|
|
220
|
+
if (inference)
|
|
221
|
+
for (const key of LLM_INFERENCE_FIELDS)
|
|
222
|
+
if (inference[key] !== undefined)
|
|
223
|
+
out[key] = inference[key];
|
|
224
|
+
return out;
|
|
225
|
+
}
|
|
226
|
+
/** Apply a request's model, inference, timeout and workspace to its runner. Idempotent. */
|
|
227
|
+
function applyRequest(base, request) {
|
|
228
|
+
const timeout = Object.hasOwn(request.runtime, "timeoutMs")
|
|
229
|
+
? { timeoutMs: request.runtime.timeoutMs ?? null }
|
|
230
|
+
: Object.hasOwn(base, "timeoutMs")
|
|
231
|
+
? { timeoutMs: base.timeoutMs }
|
|
232
|
+
: {};
|
|
233
|
+
const model = request.model?.resolved;
|
|
234
|
+
if (base.kind === "llm") {
|
|
235
|
+
const { model: _model, ...connection } = base.connection;
|
|
236
|
+
return {
|
|
237
|
+
...base,
|
|
238
|
+
connection: withInference({ ...connection, ...(model !== undefined ? { model } : {}) }, request.inference),
|
|
239
|
+
...timeout,
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
const { model: _model, workspace: _workspace, ...profile } = base.profile;
|
|
243
|
+
const workspace = request.runtime.workspace;
|
|
244
|
+
const next = {
|
|
245
|
+
...base,
|
|
246
|
+
profile: {
|
|
247
|
+
...profile,
|
|
248
|
+
...(model !== undefined ? { model } : {}),
|
|
249
|
+
...(typeof workspace === "string" ? { workspace } : {}),
|
|
250
|
+
},
|
|
251
|
+
...timeout,
|
|
252
|
+
};
|
|
253
|
+
if (next.kind === "sdk" && next.fallbackConnection) {
|
|
254
|
+
let fallback = { ...next.fallbackConnection };
|
|
255
|
+
if (request.model === null)
|
|
256
|
+
delete fallback.model;
|
|
257
|
+
if (Object.hasOwn(request, "inference"))
|
|
258
|
+
fallback = withInference(fallback, request.inference);
|
|
259
|
+
next.fallbackConnection = fallback;
|
|
260
|
+
}
|
|
261
|
+
return next;
|
|
262
|
+
}
|
|
263
|
+
function mergeInference(current, next, source, provenance) {
|
|
264
|
+
provenance["/inference"] = source;
|
|
265
|
+
if (next === null) {
|
|
266
|
+
for (const key of Object.keys(provenance))
|
|
267
|
+
if (key.startsWith("/inference/"))
|
|
268
|
+
delete provenance[key];
|
|
269
|
+
return null;
|
|
270
|
+
}
|
|
271
|
+
for (const key of Object.keys(next)) {
|
|
272
|
+
provenance[`/inference/${key.replaceAll("~", "~0").replaceAll("/", "~1")}`] = source;
|
|
273
|
+
}
|
|
274
|
+
return deepMergeConfig(current ?? {}, next);
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Resolve one execution: select the engine, merge its defaults with the
|
|
278
|
+
* caller's layers (nearest wins), expand a model alias, authorize tools, and
|
|
279
|
+
* apply the result to the engine's runner.
|
|
280
|
+
*/
|
|
281
|
+
export function resolveExecution(input) {
|
|
282
|
+
const command = input.command ??
|
|
283
|
+
createInlineResolvedCommand({
|
|
284
|
+
template: input.content ?? "",
|
|
285
|
+
...(input.argumentInput !== undefined ? { argumentInput: input.argumentInput } : {}),
|
|
286
|
+
content: input.content ?? "",
|
|
287
|
+
});
|
|
288
|
+
const callerLayers = [
|
|
289
|
+
...(input.agentLayer ? [{ ...input.agentLayer, kind: "agent" }] : []),
|
|
290
|
+
{
|
|
291
|
+
id: input.commandLayer?.id ?? "inline-command",
|
|
292
|
+
kind: "command",
|
|
293
|
+
values: input.commandLayer?.values ?? {},
|
|
294
|
+
},
|
|
295
|
+
...(input.invocationDefaults
|
|
296
|
+
? [{ id: "invocation-defaults", kind: "invocation-defaults", values: input.invocationDefaults }]
|
|
297
|
+
: []),
|
|
298
|
+
...(input.current ? [{ id: "current-invocation", kind: "current", values: input.current }] : []),
|
|
299
|
+
];
|
|
300
|
+
const provenance = {};
|
|
301
|
+
let name;
|
|
302
|
+
let defaults;
|
|
303
|
+
let base;
|
|
304
|
+
let fallback = false;
|
|
305
|
+
if (input.runner) {
|
|
306
|
+
name = input.runner.engine;
|
|
307
|
+
defaults = runnerDefaults(input.runner);
|
|
308
|
+
base = input.runner;
|
|
309
|
+
provenance.engine = { layer: "installation-defaults", kind: "installation", via: "explicit" };
|
|
310
|
+
}
|
|
311
|
+
else {
|
|
312
|
+
if (!input.config)
|
|
313
|
+
throw new TypeError("resolveExecution needs a config or a runner");
|
|
314
|
+
const selected = selectEngine(input.config, callerLayers);
|
|
315
|
+
name = selected.name;
|
|
316
|
+
fallback = selected.fallback;
|
|
317
|
+
defaults = engineDefaults(name, selected.engine, input.config);
|
|
318
|
+
base = resolveEngine(name, input.config, selected.engine);
|
|
319
|
+
provenance.engine = selected.provenance;
|
|
320
|
+
}
|
|
321
|
+
const layers = [{ id: name, kind: "engine", values: defaults.values }, ...callerLayers];
|
|
322
|
+
provenance.command = { layer: command.source?.ref ?? "inline", kind: "command", via: "source" };
|
|
323
|
+
let persona = input.persona;
|
|
324
|
+
const agentLayer = nearest(layers, "agent");
|
|
325
|
+
const agent = agentLayer?.values.agent;
|
|
326
|
+
if (agentLayer) {
|
|
327
|
+
provenance.agent = explicit(agentLayer);
|
|
328
|
+
// A native selector (or an explicit null) replaces any persona.
|
|
329
|
+
if (typeof agent !== "string" || !isPortableExecutionAgentSelector(agent))
|
|
330
|
+
persona = null;
|
|
331
|
+
}
|
|
332
|
+
if (persona)
|
|
333
|
+
provenance.persona = { layer: persona.source.ref, kind: "agent", via: "source" };
|
|
334
|
+
const modelLayer = nearest(layers, "model");
|
|
335
|
+
let model;
|
|
336
|
+
let aliasInference;
|
|
337
|
+
if (modelLayer) {
|
|
338
|
+
provenance.model = explicit(modelLayer);
|
|
339
|
+
const value = modelLayer.values.model;
|
|
340
|
+
if (value === null)
|
|
341
|
+
model = null;
|
|
342
|
+
else if (typeof value === "string" && value.length > 0) {
|
|
343
|
+
const map = input.modelMap ?? (input.config ? loadModelMap({ engines: input.config.engines }).map : undefined);
|
|
344
|
+
const selection = map
|
|
345
|
+
? resolveModelMapAlias(value, defaults.modelMapKey, map)
|
|
346
|
+
: { input: value, interpretation: "exact", model: value };
|
|
347
|
+
model = { input: selection.input, interpretation: selection.interpretation, resolved: selection.model };
|
|
348
|
+
if ("inference" in selection && selection.inference !== undefined)
|
|
349
|
+
aliasInference = selection.inference;
|
|
350
|
+
}
|
|
351
|
+
else {
|
|
352
|
+
throw new ConfigError("Resolved model must be null or a non-empty string.", "INVALID_CONFIG_FILE");
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
// An alias's inference applies at the layer that chose the alias, under that layer's own inference.
|
|
356
|
+
let inference;
|
|
357
|
+
for (const layer of layers) {
|
|
358
|
+
if (layer === modelLayer && aliasInference !== undefined) {
|
|
359
|
+
inference = mergeInference(inference, aliasInference, explicit(layer, "model-alias"), provenance);
|
|
360
|
+
}
|
|
361
|
+
if (has(layer.values, "inference")) {
|
|
362
|
+
inference = mergeInference(inference, layer.values.inference ?? null, explicit(layer), provenance);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
const select = (key, field) => {
|
|
366
|
+
const layer = nearest(layers, key);
|
|
367
|
+
if (layer)
|
|
368
|
+
provenance[field] = explicit(layer);
|
|
369
|
+
return layer;
|
|
370
|
+
};
|
|
371
|
+
const schemaLayer = select("outputSchema", "outputSchema");
|
|
372
|
+
const toolsLayer = select("tools", "tools");
|
|
373
|
+
const timeoutLayer = select("timeout", "runtime.timeoutMs");
|
|
374
|
+
const workspaceLayer = select("workspace", "runtime.workspace");
|
|
375
|
+
const environmentLayer = select("environment", "runtime.environment");
|
|
376
|
+
const settingsLayer = select("runtime", "runtime.settings");
|
|
377
|
+
const tools = toolsLayer ? cloneToolSelection(toolsLayer.values.tools ?? null, "tools") : undefined;
|
|
378
|
+
const authorization = authorizeTools(tools, input.runner ? undefined : input.config);
|
|
379
|
+
provenance.authorization = {
|
|
380
|
+
layer: typeof authorization.policy?.id === "string" ? authorization.policy.id : "not-required",
|
|
381
|
+
kind: "authorization",
|
|
382
|
+
via: "policy",
|
|
383
|
+
};
|
|
384
|
+
const request = createResolvedExecutionRequest({
|
|
385
|
+
command,
|
|
386
|
+
...(input.conversation !== undefined ? { conversation: input.conversation } : {}),
|
|
387
|
+
...(agentLayer ? { agent: agent } : {}),
|
|
388
|
+
...(persona !== undefined ? { persona } : {}),
|
|
389
|
+
engine: { name, kind: defaults.kind, platform: defaults.platform },
|
|
390
|
+
...(modelLayer ? { model: model ?? null } : {}),
|
|
391
|
+
...(inference !== undefined ? { inference } : {}),
|
|
392
|
+
...(schemaLayer ? { outputSchema: schemaLayer.values.outputSchema ?? null } : {}),
|
|
393
|
+
...(toolsLayer ? { tools } : {}),
|
|
394
|
+
authorization,
|
|
395
|
+
runtime: {
|
|
396
|
+
...(timeoutLayer ? { timeoutMs: parseTimeout(timeoutLayer.values.timeout ?? null) } : {}),
|
|
397
|
+
...(workspaceLayer ? { workspace: workspaceLayer.values.workspace ?? null } : {}),
|
|
398
|
+
...(environmentLayer ? { environment: environmentLayer.values.environment ?? null } : {}),
|
|
399
|
+
...(settingsLayer ? { settings: settingsLayer.values.runtime ?? null } : {}),
|
|
400
|
+
},
|
|
401
|
+
notices: [],
|
|
402
|
+
});
|
|
403
|
+
const sorted = Object.fromEntries(Object.entries(provenance).sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0)));
|
|
404
|
+
return {
|
|
405
|
+
request,
|
|
406
|
+
runner: applyRequest(base, request),
|
|
407
|
+
provenance: sorted,
|
|
408
|
+
...(fallback ? { fallbackEngineName: name } : {}),
|
|
409
|
+
};
|
|
410
|
+
}
|
|
411
|
+
function nonEmpty(value) {
|
|
412
|
+
return value !== null && value !== undefined && Object.keys(value).length > 0;
|
|
413
|
+
}
|
|
414
|
+
function buildLlm(request, runner, options) {
|
|
415
|
+
if (typeof request.agent === "string" && request.persona === null) {
|
|
416
|
+
throw new ConfigError(`The direct LLM transport cannot consume native agent selector ${JSON.stringify(request.agent)}.`, "INVALID_CONFIG_FILE");
|
|
417
|
+
}
|
|
418
|
+
if (hasToolSelection(request.tools)) {
|
|
419
|
+
throw new ConfigError("The direct LLM transport cannot enforce the resolved tool policy.", "INVALID_CONFIG_FILE");
|
|
420
|
+
}
|
|
421
|
+
const notices = [...request.notices];
|
|
422
|
+
const skip = (field) => {
|
|
423
|
+
notices.push(untranslated("llm", field));
|
|
424
|
+
};
|
|
425
|
+
for (const key of Object.keys(request.inference ?? {}).sort()) {
|
|
426
|
+
if (!LLM_INFERENCE_FIELDS.includes(key))
|
|
427
|
+
skip(`inference.${key}`);
|
|
428
|
+
}
|
|
429
|
+
const chatOptions = {};
|
|
430
|
+
if (request.outputSchema) {
|
|
431
|
+
if (runner.connection.supportsJsonSchema === true)
|
|
432
|
+
chatOptions.responseSchema = request.outputSchema;
|
|
433
|
+
else
|
|
434
|
+
skip("outputSchema");
|
|
435
|
+
}
|
|
436
|
+
if (request.runtime.workspace)
|
|
437
|
+
skip("runtime.workspace");
|
|
438
|
+
if (nonEmpty(request.runtime.environment))
|
|
439
|
+
skip("runtime.environment");
|
|
440
|
+
if (nonEmpty(request.runtime.settings))
|
|
441
|
+
skip("runtime.settings");
|
|
442
|
+
for (const field of extensionFields(request))
|
|
443
|
+
skip(field);
|
|
444
|
+
const messages = [
|
|
445
|
+
...(request.persona ? [{ role: "system", content: request.persona.content }] : []),
|
|
446
|
+
...(request.conversation ?? []).map((message) => ({ role: message.role, content: message.content })),
|
|
447
|
+
{ role: "user", content: request.command.content },
|
|
448
|
+
];
|
|
449
|
+
return { request, runner, prompt: request.command.content, options, messages, chatOptions, notices };
|
|
450
|
+
}
|
|
451
|
+
/**
|
|
452
|
+
* Build a request for its runner's transport: the harness's own builder for
|
|
453
|
+
* agent/SDK engines, chat messages for a direct LLM. A request whose tools
|
|
454
|
+
* were denied by `execution.allowedTools` stops here.
|
|
455
|
+
*/
|
|
456
|
+
export function buildExecution(request, runner) {
|
|
457
|
+
if (request.authorization.status === "denied") {
|
|
458
|
+
throw new ConfigError(request.authorization.reason ?? "Resolved execution is not authorized by operator policy.", "EXECUTION_NOT_AUTHORIZED");
|
|
459
|
+
}
|
|
460
|
+
const applied = applyRequest(runner, request);
|
|
461
|
+
const environment = request.runtime.environment;
|
|
462
|
+
const options = {
|
|
463
|
+
stdio: "captured",
|
|
464
|
+
parseOutput: "text",
|
|
465
|
+
...(applied.timeoutMs !== undefined ? { timeoutMs: applied.timeoutMs } : {}),
|
|
466
|
+
...(applied.kind !== "llm" && applied.profile.workspace ? { cwd: applied.profile.workspace } : {}),
|
|
467
|
+
...(environment ? { env: { ...environment } } : {}),
|
|
468
|
+
};
|
|
469
|
+
if (applied.kind === "llm")
|
|
470
|
+
return buildLlm(request, applied, options);
|
|
471
|
+
const platform = applied.profile.platform ?? applied.profile.name;
|
|
472
|
+
const harness = getHarness(platform);
|
|
473
|
+
const lower = harness?.agentBuilder?.lower ?? harness?.executionLowerer?.lower;
|
|
474
|
+
if (!lower) {
|
|
475
|
+
throw new ConfigError(`Agent platform ${JSON.stringify(platform)} has no registered request builder.`, "INVALID_CONFIG_FILE");
|
|
476
|
+
}
|
|
477
|
+
const built = lower(applied.profile, request);
|
|
478
|
+
return {
|
|
479
|
+
request,
|
|
480
|
+
runner: applied,
|
|
481
|
+
prompt: built.prompt,
|
|
482
|
+
options: { ...options, dispatch: built.dispatch },
|
|
483
|
+
notices: [...request.notices, ...built.notices],
|
|
484
|
+
};
|
|
485
|
+
}
|
|
486
|
+
/**
|
|
487
|
+
* Resume: build a journaled `{ request, runner }` exactly as frozen. Never
|
|
488
|
+
* reads config, models.json or credentials, so a config edit after the freeze
|
|
489
|
+
* cannot change what a resumed unit runs.
|
|
490
|
+
*/
|
|
491
|
+
export function buildExecutionFromWire(wire) {
|
|
492
|
+
return buildExecution(decodeResolvedExecutionRequest(wire.request), decodeFrozenRunnerSpec(wire.runner));
|
|
493
|
+
}
|
|
494
|
+
/** Each configured engine's own model selection and models.json column, for `akm health`. */
|
|
495
|
+
export function executionEngineDefinitionsFromConfig(config) {
|
|
496
|
+
return Object.fromEntries(Object.entries(config.engines ?? {}).map(([name, engine]) => {
|
|
497
|
+
const defaults = engineDefaults(name, engine, config);
|
|
498
|
+
return [
|
|
499
|
+
name,
|
|
500
|
+
{
|
|
501
|
+
selection: { name, kind: defaults.kind, platform: defaults.platform },
|
|
502
|
+
defaults: defaults.values,
|
|
503
|
+
modelMapKey: defaults.modelMapKey,
|
|
504
|
+
},
|
|
505
|
+
];
|
|
506
|
+
}));
|
|
507
|
+
}
|