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
|
@@ -2,278 +2,49 @@
|
|
|
2
2
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
3
|
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* lowerer in that same shared layer.
|
|
11
|
-
*
|
|
12
|
-
* Agent and SDK arms use the shared profile runners. The LLM arm deliberately
|
|
13
|
-
* requires a handler because structured callers own their parse/fallback
|
|
14
|
-
* contract. The `assertNever` arm keeps a fourth transport kind from becoming
|
|
15
|
-
* an implicit fallthrough. Symbolic LLM and SDK-fallback credentials are
|
|
16
|
-
* materialized here, at authorized operation-lease acquisition or the final
|
|
17
|
-
* single-call boundary, then scrubbed from the result.
|
|
5
|
+
* Run a built execution: the one place credentials are read. A direct LLM
|
|
6
|
+
* goes to `chatCompletion`, an agent engine to `runAgent` (the harness builder
|
|
7
|
+
* turns the request into argv), an SDK engine to `runOpencodeSdk`. Every
|
|
8
|
+
* credential and passthrough value that could reach the child is redacted
|
|
9
|
+
* from the result.
|
|
18
10
|
*/
|
|
19
11
|
import { assertNever } from "../../core/assert.js";
|
|
12
|
+
import { UsageError } from "../../core/errors.js";
|
|
20
13
|
import { collectSensitiveValues, isEnvPassthroughValueSafeToExpose, redactSensitiveText, redactSensitiveValue, } from "../../core/redaction.js";
|
|
21
|
-
import {
|
|
22
|
-
import { closeServer as disposeOpencodeSdkServers,
|
|
23
|
-
import { lookupApiKeyFileValue, lookupApiKeySecretRefValue, lookupCredentialFromEnv,
|
|
24
|
-
import { materializeLlmRunnerConnection,
|
|
14
|
+
import { chatCompletion, LlmCallError } from "../../llm/client.js";
|
|
15
|
+
import { closeServer as disposeOpencodeSdkServers, runOpencodeSdk } from "../harnesses/opencode-sdk/sdk-runner.js";
|
|
16
|
+
import { lookupApiKeyFileValue, lookupApiKeySecretRefValue, lookupCredentialFromEnv, resolveEngine, } from "./engine-resolution.js";
|
|
17
|
+
import { materializeLlmRunnerConnection, materializeSdkFallbackConnection } from "./runner.js";
|
|
25
18
|
import { runAgent } from "./spawn.js";
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
case "sdk":
|
|
42
|
-
return opencodeSdkServerEnvironmentNames(spec.profile);
|
|
43
|
-
default:
|
|
44
|
-
return assertNever(spec);
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
function snapshotDispatchEnvironment(spec, envSource) {
|
|
48
|
-
const snapshot = new Map();
|
|
49
|
-
const read = (name) => {
|
|
50
|
-
if (!snapshot.has(name))
|
|
51
|
-
snapshot.set(name, envSource[name]);
|
|
52
|
-
return snapshot.get(name);
|
|
53
|
-
};
|
|
54
|
-
const environmentSource = new Proxy(Object.create(null), {
|
|
55
|
-
get(_target, property) {
|
|
56
|
-
return typeof property === "string" ? snapshot.get(property) : undefined;
|
|
57
|
-
},
|
|
58
|
-
});
|
|
59
|
-
for (const name of dispatchEnvironmentNames(spec))
|
|
60
|
-
read(name);
|
|
61
|
-
const passthroughSensitiveValues = new Set();
|
|
62
|
-
if (spec.kind !== "llm") {
|
|
63
|
-
for (const name of new Set(spec.profile.envPassthrough)) {
|
|
64
|
-
const value = snapshot.get(name);
|
|
65
|
-
if (!isEnvPassthroughValueSafeToExpose(name, value) && value)
|
|
66
|
-
passthroughSensitiveValues.add(value);
|
|
67
|
-
}
|
|
19
|
+
const OPERATIONAL_OPTIONS = [
|
|
20
|
+
"stdio",
|
|
21
|
+
"parseOutput",
|
|
22
|
+
"signal",
|
|
23
|
+
"envSource",
|
|
24
|
+
"spawn",
|
|
25
|
+
"setTimeoutFn",
|
|
26
|
+
"clearTimeoutFn",
|
|
27
|
+
"onEvent",
|
|
28
|
+
];
|
|
29
|
+
/** Every value that can reach one dispatch and must never be echoed back: credentials and secret-looking env. */
|
|
30
|
+
export function collectDispatchSensitiveValues(runner, opts, envSource = opts.envSource ?? process.env) {
|
|
31
|
+
const values = [];
|
|
32
|
+
if (runner.kind === "llm") {
|
|
33
|
+
values.push(runner.connection.apiKey, lookupCredentialFromEnv(runner.credential, envSource), runner.apiKeyFile ? lookupApiKeyFileValue(runner.apiKeyFile) : undefined, runner.apiKeySecretRef ? lookupApiKeySecretRefValue(runner.apiKeySecretRef) : undefined);
|
|
68
34
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
function runnerLeaseBinding(spec) {
|
|
73
|
-
switch (spec.kind) {
|
|
74
|
-
case "llm":
|
|
75
|
-
return JSON.stringify({
|
|
76
|
-
kind: spec.kind,
|
|
77
|
-
engine: spec.engine ?? null,
|
|
78
|
-
endpoint: spec.connection.endpoint,
|
|
79
|
-
provider: spec.connection.provider ?? null,
|
|
80
|
-
credential: credentialBinding(spec.credential),
|
|
81
|
-
apiKeyFile: spec.apiKeyFile ?? null,
|
|
82
|
-
});
|
|
83
|
-
case "agent":
|
|
84
|
-
return JSON.stringify({
|
|
85
|
-
kind: spec.kind,
|
|
86
|
-
engine: spec.engine ?? null,
|
|
87
|
-
platform: spec.profile.platform ?? null,
|
|
88
|
-
name: spec.profile.name,
|
|
89
|
-
bin: spec.profile.bin,
|
|
90
|
-
envPassthrough: passthroughBinding(spec),
|
|
91
|
-
});
|
|
92
|
-
case "sdk":
|
|
93
|
-
return JSON.stringify({
|
|
94
|
-
kind: spec.kind,
|
|
95
|
-
engine: spec.engine ?? null,
|
|
96
|
-
platform: spec.profile.platform ?? null,
|
|
97
|
-
name: spec.profile.name,
|
|
98
|
-
bin: spec.profile.bin,
|
|
99
|
-
envPassthrough: passthroughBinding(spec),
|
|
100
|
-
fallbackEndpoint: spec.fallbackConnection?.endpoint ?? null,
|
|
101
|
-
fallbackProvider: spec.fallbackConnection?.provider ?? null,
|
|
102
|
-
fallbackCredential: credentialBinding(spec.fallbackCredential),
|
|
103
|
-
fallbackApiKeyFile: spec.fallbackApiKeyFile ?? null,
|
|
104
|
-
});
|
|
105
|
-
default:
|
|
106
|
-
return assertNever(spec);
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
function requireRunnerDispatchLease(lease, spec) {
|
|
110
|
-
if (typeof lease !== "object" || lease === null)
|
|
111
|
-
throw new TypeError("invalid dispatch lease");
|
|
112
|
-
const state = liveRunnerDispatchLeases.get(lease);
|
|
113
|
-
if (!state) {
|
|
114
|
-
if (issuedRunnerDispatchLeases.has(lease) && disposedRunnerDispatchLeases.has(lease)) {
|
|
115
|
-
throw new TypeError("dispatch lease is disposed");
|
|
35
|
+
else {
|
|
36
|
+
if (runner.kind === "sdk") {
|
|
37
|
+
values.push(runner.fallbackConnection?.apiKey, lookupCredentialFromEnv(runner.fallbackCredential, envSource), runner.fallbackApiKeyFile ? lookupApiKeyFileValue(runner.fallbackApiKeyFile) : undefined, runner.fallbackApiKeySecretRef ? lookupApiKeySecretRefValue(runner.fallbackApiKeySecretRef) : undefined);
|
|
116
38
|
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
}
|
|
122
|
-
return state;
|
|
123
|
-
}
|
|
124
|
-
/** @internal Verify provenance, liveness, and transport binding without exposing state. */
|
|
125
|
-
export function assertRunnerDispatchLease(lease, spec) {
|
|
126
|
-
requireRunnerDispatchLease(lease, spec);
|
|
127
|
-
}
|
|
128
|
-
/** @internal Acquire only through execution-lowering after authorization/provenance validation. */
|
|
129
|
-
export function acquireRunnerDispatchLease(spec, envSource = process.env) {
|
|
130
|
-
const environment = snapshotDispatchEnvironment(spec, envSource);
|
|
131
|
-
const credentialSource = new Proxy(Object.create(null), {
|
|
132
|
-
get(_target, property) {
|
|
133
|
-
return typeof property === "string" ? environment.read(property) : undefined;
|
|
134
|
-
},
|
|
135
|
-
});
|
|
136
|
-
const primaryCredential = spec.kind === "llm"
|
|
137
|
-
? resolveLlmCredentialValue(spec.engine, spec.credential, spec.apiKeyFile, spec.apiKeySecretRef, credentialSource)
|
|
138
|
-
: undefined;
|
|
139
|
-
const fallbackCredential = spec.kind === "sdk"
|
|
140
|
-
? resolveLlmCredentialValue(spec.engine, spec.fallbackCredential, spec.fallbackApiKeyFile, spec.fallbackApiKeySecretRef, credentialSource)
|
|
141
|
-
: undefined;
|
|
142
|
-
const handle = Object.create(null);
|
|
143
|
-
Object.defineProperty(handle, "toJSON", {
|
|
144
|
-
configurable: false,
|
|
145
|
-
enumerable: false,
|
|
146
|
-
writable: false,
|
|
147
|
-
value: () => {
|
|
148
|
-
throw new TypeError("dispatch lease is not serializable");
|
|
149
|
-
},
|
|
150
|
-
});
|
|
151
|
-
Object.freeze(handle);
|
|
152
|
-
const sensitiveValues = collectSensitiveValues([
|
|
153
|
-
primaryCredential,
|
|
154
|
-
fallbackCredential,
|
|
155
|
-
...environment.passthroughSensitiveValues,
|
|
156
|
-
]);
|
|
157
|
-
liveRunnerDispatchLeases.set(handle, {
|
|
158
|
-
binding: runnerLeaseBinding(spec),
|
|
159
|
-
primaryCredential,
|
|
160
|
-
fallbackCredential,
|
|
161
|
-
environmentSnapshot: environment.environmentSnapshot,
|
|
162
|
-
environmentSource: environment.environmentSource,
|
|
163
|
-
sensitiveValues,
|
|
164
|
-
});
|
|
165
|
-
issuedRunnerDispatchLeases.add(handle);
|
|
166
|
-
return handle;
|
|
167
|
-
}
|
|
168
|
-
/** @internal Scrub private material and invalidate one issued handle. */
|
|
169
|
-
export function disposeRunnerDispatchLease(lease) {
|
|
170
|
-
if (typeof lease !== "object" || lease === null || !issuedRunnerDispatchLeases.has(lease)) {
|
|
171
|
-
throw new TypeError("invalid dispatch lease");
|
|
172
|
-
}
|
|
173
|
-
const state = liveRunnerDispatchLeases.get(lease);
|
|
174
|
-
if (!state)
|
|
175
|
-
return;
|
|
176
|
-
state.primaryCredential = undefined;
|
|
177
|
-
state.fallbackCredential = undefined;
|
|
178
|
-
state.environmentSnapshot.clear();
|
|
179
|
-
state.sensitiveValues.fill("");
|
|
180
|
-
state.sensitiveValues = [];
|
|
181
|
-
liveRunnerDispatchLeases.delete(lease);
|
|
182
|
-
disposedRunnerDispatchLeases.add(lease);
|
|
183
|
-
}
|
|
184
|
-
/** @internal Redact with private credential material without exposing its values. */
|
|
185
|
-
export function redactWithRunnerDispatchLease(lease, value) {
|
|
186
|
-
return redactSensitiveText(value, requireRunnerDispatchLease(lease).sensitiveValues);
|
|
187
|
-
}
|
|
188
|
-
/**
|
|
189
|
-
* Release every long-lived resource the dispatch runners CACHE for reuse, so a
|
|
190
|
-
* one-shot process (the CLI) can exit cleanly once dispatching is done.
|
|
191
|
-
*
|
|
192
|
-
* The `sdk` runner keeps a per-material registry of `opencode serve` CHILD
|
|
193
|
-
* PROCESSES (see `opencode-sdk/sdk-runner.ts`), started lazily and reused
|
|
194
|
-
* across units within a process. Each live child is an OS handle that keeps
|
|
195
|
-
* Bun's event loop open — and the registry's own teardown is wired ONLY to
|
|
196
|
-
* `process.once('exit')`, which never fires while such a child holds the loop
|
|
197
|
-
* open. That is a deadlock: a successful `akm workflow run` that dispatched via
|
|
198
|
-
* the SDK path would hang the CLI (owner finding 4) because the process is
|
|
199
|
-
* never idle enough for the exit hook to run and close the children it is
|
|
200
|
-
* waiting on.
|
|
201
|
-
*
|
|
202
|
-
* The CLI composition root and workflow engine call this in `finally` blocks to
|
|
203
|
-
* drain the registry deterministically before relying on the event loop. Started
|
|
204
|
-
* servers close synchronously; in-flight starts are awaited and closed on
|
|
205
|
-
* arrival. When no SDK server was started this is an idempotent no-op.
|
|
206
|
-
*/
|
|
207
|
-
export async function disposeDispatchResources() {
|
|
208
|
-
await disposeOpencodeSdkServers();
|
|
209
|
-
}
|
|
210
|
-
/** Collect every materialized value that can reach one runner dispatch. */
|
|
211
|
-
export function collectDispatchSensitiveValues(spec, opts, envSource = opts.envSource ?? process.env) {
|
|
212
|
-
const values = new Set();
|
|
213
|
-
const add = (value) => {
|
|
214
|
-
if (value !== undefined && value.length > 0)
|
|
215
|
-
values.add(value);
|
|
216
|
-
};
|
|
217
|
-
const addConnection = (connection) => add(connection?.apiKey);
|
|
218
|
-
if (spec.kind === "llm")
|
|
219
|
-
addConnection(spec.connection);
|
|
220
|
-
if (spec.kind === "sdk")
|
|
221
|
-
addConnection(spec.fallbackConnection);
|
|
222
|
-
if (spec.kind === "llm")
|
|
223
|
-
add(lookupCredentialFromEnv(spec.credential, envSource));
|
|
224
|
-
if (spec.kind === "sdk")
|
|
225
|
-
add(lookupCredentialFromEnv(spec.fallbackCredential, envSource));
|
|
226
|
-
// #905: a file-backed credential is read at dispatch, so it must be in the
|
|
227
|
-
// scrub set for the same reason the env-backed one is.
|
|
228
|
-
if (spec.kind === "llm" && spec.apiKeyFile)
|
|
229
|
-
add(lookupApiKeyFileValue(spec.apiKeyFile));
|
|
230
|
-
if (spec.kind === "sdk" && spec.fallbackApiKeyFile)
|
|
231
|
-
add(lookupApiKeyFileValue(spec.fallbackApiKeyFile));
|
|
232
|
-
// #953: a secret-store-backed credential is read at dispatch too — same
|
|
233
|
-
// best-effort scrub-set inclusion rationale.
|
|
234
|
-
if (spec.kind === "llm" && spec.apiKeySecretRef)
|
|
235
|
-
add(lookupApiKeySecretRefValue(spec.apiKeySecretRef));
|
|
236
|
-
if (spec.kind === "sdk" && spec.fallbackApiKeySecretRef)
|
|
237
|
-
add(lookupApiKeySecretRefValue(spec.fallbackApiKeySecretRef));
|
|
238
|
-
if (spec.kind !== "llm") {
|
|
239
|
-
for (const value of Object.values(spec.profile.env ?? {}))
|
|
240
|
-
add(value);
|
|
241
|
-
for (const name of spec.profile.envPassthrough) {
|
|
242
|
-
const value = envSource[name];
|
|
243
|
-
if (!isEnvPassthroughValueSafeToExpose(name, value))
|
|
244
|
-
add(value);
|
|
39
|
+
values.push(...Object.values(runner.profile.env ?? {}));
|
|
40
|
+
for (const name of runner.profile.envPassthrough) {
|
|
41
|
+
if (!isEnvPassthroughValueSafeToExpose(name, envSource[name]))
|
|
42
|
+
values.push(envSource[name]);
|
|
245
43
|
}
|
|
246
44
|
}
|
|
247
45
|
for (const [name, value] of Object.entries(opts.env ?? {})) {
|
|
248
46
|
if (!isEnvPassthroughValueSafeToExpose(name, value))
|
|
249
|
-
|
|
250
|
-
}
|
|
251
|
-
return collectSensitiveValues(values);
|
|
252
|
-
}
|
|
253
|
-
function collectNonCredentialDispatchSensitiveValues(spec, opts, envSource = opts.envSource ?? process.env, includeProfilePassthrough = true) {
|
|
254
|
-
const values = new Set();
|
|
255
|
-
const add = (value) => {
|
|
256
|
-
if (value !== undefined && value.length > 0)
|
|
257
|
-
values.add(value);
|
|
258
|
-
};
|
|
259
|
-
if (spec.kind === "llm")
|
|
260
|
-
add(spec.connection.apiKey);
|
|
261
|
-
if (spec.kind === "sdk")
|
|
262
|
-
add(spec.fallbackConnection?.apiKey);
|
|
263
|
-
if (spec.kind !== "llm") {
|
|
264
|
-
for (const value of Object.values(spec.profile.env ?? {}))
|
|
265
|
-
add(value);
|
|
266
|
-
if (includeProfilePassthrough) {
|
|
267
|
-
for (const name of spec.profile.envPassthrough) {
|
|
268
|
-
const value = envSource[name];
|
|
269
|
-
if (!isEnvPassthroughValueSafeToExpose(name, value))
|
|
270
|
-
add(value);
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
for (const [name, value] of Object.entries(opts.env ?? {})) {
|
|
275
|
-
if (!isEnvPassthroughValueSafeToExpose(name, value))
|
|
276
|
-
add(value);
|
|
47
|
+
values.push(value);
|
|
277
48
|
}
|
|
278
49
|
return collectSensitiveValues(values);
|
|
279
50
|
}
|
|
@@ -286,75 +57,126 @@ function redactResult(result, sensitiveValues) {
|
|
|
286
57
|
...(result.parsed !== undefined ? { parsed: redactSensitiveValue(result.parsed, sensitiveValues) } : {}),
|
|
287
58
|
};
|
|
288
59
|
}
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
60
|
+
function llmFailureReason(error) {
|
|
61
|
+
if (!(error instanceof LlmCallError))
|
|
62
|
+
return "spawn_failed";
|
|
63
|
+
switch (error.code) {
|
|
64
|
+
case "aborted":
|
|
65
|
+
return "aborted";
|
|
66
|
+
case "timeout":
|
|
67
|
+
return "timeout";
|
|
68
|
+
case "rate_limited":
|
|
69
|
+
return "llm_rate_limit";
|
|
70
|
+
case "parse_error":
|
|
71
|
+
case "provider_html_error":
|
|
72
|
+
return "parse_error";
|
|
73
|
+
default:
|
|
74
|
+
return "spawn_failed";
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
async function dispatchRunner(runner, prompt, opts, seams, llm) {
|
|
78
|
+
const envSource = opts.envSource ?? process.env;
|
|
79
|
+
const secrets = collectDispatchSensitiveValues(runner, opts, envSource);
|
|
302
80
|
let result;
|
|
303
|
-
|
|
304
|
-
const leaseState = lease ? requireRunnerDispatchLease(lease, spec) : undefined;
|
|
305
|
-
const preDispatchSensitiveValues = leaseState
|
|
306
|
-
? collectSensitiveValues([
|
|
307
|
-
...leaseState.sensitiveValues,
|
|
308
|
-
...collectNonCredentialDispatchSensitiveValues(spec, opts, undefined, false),
|
|
309
|
-
])
|
|
310
|
-
: collectDispatchSensitiveValues(spec, opts);
|
|
311
|
-
switch (spec.kind) {
|
|
81
|
+
switch (runner.kind) {
|
|
312
82
|
case "llm": {
|
|
313
|
-
if (!
|
|
314
|
-
throw new Error("
|
|
315
|
-
|
|
316
|
-
const connection = leaseState
|
|
317
|
-
? materializeLlmRunnerConnectionWithCredential(spec, leaseState.primaryCredential)
|
|
318
|
-
: materializeLlmRunnerConnection(spec);
|
|
83
|
+
if (!llm)
|
|
84
|
+
throw new Error("an llm runner dispatches only a built execution's chat messages");
|
|
85
|
+
const connection = materializeLlmRunnerConnection(runner, envSource);
|
|
319
86
|
if (connection.apiKey)
|
|
320
|
-
|
|
321
|
-
result = await
|
|
87
|
+
secrets.push(connection.apiKey);
|
|
88
|
+
result = await llm(connection, opts);
|
|
322
89
|
break;
|
|
323
90
|
}
|
|
324
|
-
case "agent":
|
|
325
|
-
|
|
326
|
-
result = await run(spec.profile, prompt, withSpecOptions(spec.timeoutMs, spec.profile.workspace, leaseState?.environmentSource));
|
|
91
|
+
case "agent":
|
|
92
|
+
result = await (seams.runAgent ?? runAgent)(runner.profile, prompt, opts);
|
|
327
93
|
break;
|
|
328
|
-
}
|
|
329
94
|
case "sdk": {
|
|
330
|
-
const
|
|
331
|
-
const fallbackMaterial = spec.fallbackConnection
|
|
332
|
-
? {
|
|
333
|
-
engine: spec.engine ?? "unnamed-sdk-fallback",
|
|
334
|
-
connection: spec.fallbackConnection,
|
|
335
|
-
...(spec.fallbackCredential ? { credential: spec.fallbackCredential } : {}),
|
|
336
|
-
...(spec.fallbackApiKeyFile ? { apiKeyFile: spec.fallbackApiKeyFile } : {}),
|
|
337
|
-
timeoutMs: spec.fallbackTimeoutMs !== undefined
|
|
338
|
-
? spec.fallbackTimeoutMs
|
|
339
|
-
: Object.hasOwn(spec.fallbackConnection, "timeoutMs")
|
|
340
|
-
? (spec.fallbackConnection.timeoutMs ?? null)
|
|
341
|
-
: null,
|
|
342
|
-
}
|
|
343
|
-
: undefined;
|
|
344
|
-
const fallbackConnection = fallbackMaterial
|
|
345
|
-
? leaseState
|
|
346
|
-
? materializeLlmConnectionWithCredential(fallbackMaterial, leaseState.fallbackCredential)
|
|
347
|
-
: materializeLlmConnection(fallbackMaterial)
|
|
348
|
-
: undefined;
|
|
95
|
+
const fallbackConnection = materializeSdkFallbackConnection(runner, envSource);
|
|
349
96
|
if (fallbackConnection?.apiKey)
|
|
350
|
-
|
|
351
|
-
result = await
|
|
97
|
+
secrets.push(fallbackConnection.apiKey);
|
|
98
|
+
result = await (seams.runSdk ?? runOpencodeSdk)(runner.profile, prompt, opts, fallbackConnection);
|
|
352
99
|
break;
|
|
353
100
|
}
|
|
354
101
|
default:
|
|
355
|
-
|
|
356
|
-
|
|
102
|
+
return assertNever(runner);
|
|
103
|
+
}
|
|
104
|
+
return redactResult(result, collectSensitiveValues(secrets));
|
|
105
|
+
}
|
|
106
|
+
/** Run a built execution. Credentials are read here, once per call, and never returned. */
|
|
107
|
+
export async function runExecution(execution, options = {}) {
|
|
108
|
+
const opts = { ...execution.options };
|
|
109
|
+
const operational = options.runOptions ?? {};
|
|
110
|
+
for (const key of OPERATIONAL_OPTIONS) {
|
|
111
|
+
if (operational[key] !== undefined)
|
|
112
|
+
opts[key] = operational[key];
|
|
113
|
+
}
|
|
114
|
+
if (options.eventSource !== undefined) {
|
|
115
|
+
opts.env = { ...execution.options.env, AKM_EVENT_SOURCE: options.eventSource };
|
|
357
116
|
}
|
|
358
|
-
const
|
|
359
|
-
|
|
117
|
+
const chat = options.chat ?? chatCompletion;
|
|
118
|
+
const llm = async (connection, callOpts) => {
|
|
119
|
+
const started = Date.now();
|
|
120
|
+
try {
|
|
121
|
+
const stdout = await chat(connection, [...(execution.messages ?? [])], {
|
|
122
|
+
...execution.chatOptions,
|
|
123
|
+
...(Object.hasOwn(callOpts, "timeoutMs") ? { timeoutMs: callOpts.timeoutMs } : {}),
|
|
124
|
+
...(callOpts.signal ? { signal: callOpts.signal } : {}),
|
|
125
|
+
...(options.onRetryAttempt ? { onRetryAttempt: options.onRetryAttempt } : {}),
|
|
126
|
+
});
|
|
127
|
+
return { ok: true, exitCode: 0, stdout, stderr: "", durationMs: Date.now() - started };
|
|
128
|
+
}
|
|
129
|
+
catch (error) {
|
|
130
|
+
// Returned rather than thrown so the redaction below covers provider bodies.
|
|
131
|
+
return {
|
|
132
|
+
ok: false,
|
|
133
|
+
exitCode: null,
|
|
134
|
+
stdout: "",
|
|
135
|
+
stderr: "",
|
|
136
|
+
durationMs: Date.now() - started,
|
|
137
|
+
error: error instanceof Error ? error.message : String(error),
|
|
138
|
+
reason: llmFailureReason(error),
|
|
139
|
+
...(error instanceof LlmCallError ? { llmErrorCode: error.code } : {}),
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
return dispatchRunner(execution.runner, execution.prompt, opts, options, llm);
|
|
144
|
+
}
|
|
145
|
+
/** `akm agent`: launch an agent engine interactively, with no prompt of its own. */
|
|
146
|
+
export async function executeInteractiveAgentInvocation(input, seams = {}) {
|
|
147
|
+
const runner = resolveEngine(input.engine, input.config);
|
|
148
|
+
if (runner.kind === "llm") {
|
|
149
|
+
throw new UsageError(`Engine "${input.engine}" is an LLM engine; akm agent requires an agent engine.`, "INVALID_FLAG_VALUE");
|
|
150
|
+
}
|
|
151
|
+
const opts = {
|
|
152
|
+
stdio: runner.kind === "sdk" ? runner.profile.stdio : "interactive",
|
|
153
|
+
parseOutput: "text",
|
|
154
|
+
...(input.timeoutMs !== undefined
|
|
155
|
+
? { timeoutMs: input.timeoutMs }
|
|
156
|
+
: runner.timeoutMs !== undefined
|
|
157
|
+
? { timeoutMs: runner.timeoutMs }
|
|
158
|
+
: {}),
|
|
159
|
+
...(input.cwd ? { cwd: input.cwd } : runner.profile.workspace ? { cwd: runner.profile.workspace } : {}),
|
|
160
|
+
};
|
|
161
|
+
return { engine: input.engine, result: await dispatchRunner(runner, "", opts, seams) };
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Close the `opencode serve` children the SDK runner keeps for reuse. Its own
|
|
165
|
+
* teardown hangs off `process.once("exit")`, which never fires while a child
|
|
166
|
+
* holds the event loop open, so the CLI and workflow engine call this in
|
|
167
|
+
* `finally` blocks. A no-op when no SDK server was started.
|
|
168
|
+
*/
|
|
169
|
+
export async function disposeDispatchResources() {
|
|
170
|
+
await disposeOpencodeSdkServers();
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Fail fast, before an operation makes any durable change, when `runner`'s
|
|
174
|
+
* required credential is missing. Reads it and keeps nothing: every dispatch
|
|
175
|
+
* reads it again.
|
|
176
|
+
*/
|
|
177
|
+
export function assertRunnerCredentials(runner, envSource) {
|
|
178
|
+
if (runner.kind === "llm")
|
|
179
|
+
materializeLlmRunnerConnection(runner, envSource);
|
|
180
|
+
if (runner.kind === "sdk")
|
|
181
|
+
materializeSdkFallbackConnection(runner, envSource);
|
|
360
182
|
}
|
|
@@ -1,28 +1,68 @@
|
|
|
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 { materializeLlmConnection
|
|
5
|
-
/**
|
|
6
|
-
export function
|
|
7
|
-
return
|
|
4
|
+
import { materializeLlmConnection } from "./engine-resolution.js";
|
|
5
|
+
/** The symbolic LLM use behind one llm runner; nothing is read here. */
|
|
6
|
+
export function llmUseFromRunner(runner) {
|
|
7
|
+
return {
|
|
8
8
|
engine: runner.engine,
|
|
9
9
|
connection: runner.connection,
|
|
10
10
|
...(runner.credential ? { credential: runner.credential } : {}),
|
|
11
11
|
...(runner.apiKeyFile ? { apiKeyFile: runner.apiKeyFile } : {}),
|
|
12
12
|
...(runner.apiKeySecretRef ? { apiKeySecretRef: runner.apiKeySecretRef } : {}),
|
|
13
13
|
timeoutMs: runner.timeoutMs ?? null,
|
|
14
|
-
}
|
|
14
|
+
};
|
|
15
15
|
}
|
|
16
|
-
/**
|
|
17
|
-
export function
|
|
18
|
-
|
|
16
|
+
/** The symbolic LLM use behind an sdk runner's provider fallback, when it has one. */
|
|
17
|
+
export function sdkFallbackUseFromRunner(runner) {
|
|
18
|
+
if (!runner.fallbackConnection)
|
|
19
|
+
return undefined;
|
|
20
|
+
return {
|
|
19
21
|
engine: runner.engine,
|
|
20
|
-
connection: runner.
|
|
21
|
-
...(runner.
|
|
22
|
-
...(runner.
|
|
23
|
-
...(runner.
|
|
24
|
-
timeoutMs: runner.timeoutMs ?? null,
|
|
25
|
-
}
|
|
22
|
+
connection: runner.fallbackConnection,
|
|
23
|
+
...(runner.fallbackCredential ? { credential: runner.fallbackCredential } : {}),
|
|
24
|
+
...(runner.fallbackApiKeyFile ? { apiKeyFile: runner.fallbackApiKeyFile } : {}),
|
|
25
|
+
...(runner.fallbackApiKeySecretRef ? { apiKeySecretRef: runner.fallbackApiKeySecretRef } : {}),
|
|
26
|
+
timeoutMs: runner.fallbackTimeoutMs !== undefined ? runner.fallbackTimeoutMs : (runner.fallbackConnection.timeoutMs ?? null),
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
/** Read the current credential and inject it: the dispatch boundary for one llm runner. */
|
|
30
|
+
export function materializeLlmRunnerConnection(runner, envSource = process.env) {
|
|
31
|
+
return materializeLlmConnection(llmUseFromRunner(runner), envSource);
|
|
32
|
+
}
|
|
33
|
+
/** The same for an sdk runner's provider fallback, when it has one. */
|
|
34
|
+
export function materializeSdkFallbackConnection(runner, envSource = process.env) {
|
|
35
|
+
const use = sdkFallbackUseFromRunner(runner);
|
|
36
|
+
return use ? materializeLlmConnection(use, envSource) : undefined;
|
|
37
|
+
}
|
|
38
|
+
function isRecord(value) {
|
|
39
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Read a journaled runner back. Tolerant: unknown keys are kept and missing
|
|
43
|
+
* profile defaults are filled in; only a shape nothing could dispatch is refused.
|
|
44
|
+
*/
|
|
45
|
+
export function decodeFrozenRunnerSpec(value) {
|
|
46
|
+
if (!isRecord(value) || typeof value.engine !== "string") {
|
|
47
|
+
throw new TypeError("a frozen runner must be an object with an engine name");
|
|
48
|
+
}
|
|
49
|
+
if (value.kind === "llm") {
|
|
50
|
+
if (!isRecord(value.connection) || typeof value.connection.endpoint !== "string") {
|
|
51
|
+
throw new TypeError("a frozen llm runner must carry connection.endpoint");
|
|
52
|
+
}
|
|
53
|
+
return value;
|
|
54
|
+
}
|
|
55
|
+
if (value.kind !== "agent" && value.kind !== "sdk") {
|
|
56
|
+
throw new TypeError("a frozen runner's kind must be llm, agent, or sdk");
|
|
57
|
+
}
|
|
58
|
+
const profile = value.profile;
|
|
59
|
+
if (!isRecord(profile) || typeof profile.name !== "string" || typeof profile.bin !== "string") {
|
|
60
|
+
throw new TypeError("a frozen agent runner must carry profile.name and profile.bin");
|
|
61
|
+
}
|
|
62
|
+
return {
|
|
63
|
+
...value,
|
|
64
|
+
profile: { args: [], envPassthrough: [], stdio: "captured", parseOutput: "text", ...profile },
|
|
65
|
+
};
|
|
26
66
|
}
|
|
27
67
|
export function runnerIsLlm(runner) {
|
|
28
68
|
return runner.kind === "llm";
|