akm-cli 0.10.261012-beta → 0.10.261014-beta
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 +710 -3
- package/README.md +15 -0
- package/SECURITY.md +11 -10
- package/STABILITY.md +47 -51
- package/dist/assets/hints/cli-hints-full.md +21 -19
- package/dist/assets/hints/cli-hints-short.md +3 -4
- package/dist/assets/opencode/akm-plugin.js +177 -0
- package/dist/assets/stash-skeleton/README.md +1 -1
- package/dist/assets/tasks/core/improve.yml +1 -1
- package/dist/assets/tasks/improve/akm-improve-consolidate.yml +1 -1
- package/dist/assets/ui/config.js +27 -10
- package/dist/assets/workflows/workflow-template.md +2 -2
- package/dist/cli/clack.js +3 -1
- package/dist/cli/selection.js +33 -0
- package/dist/cli/shared.js +14 -1
- package/dist/cli/unknown-flags.js +6 -37
- package/dist/cli.js +69 -48
- package/dist/commands/agent/agent-dispatch.js +17 -25
- package/dist/commands/agent/contribute-cli.js +9 -8
- package/dist/commands/command/command-cli.js +4 -8
- package/dist/commands/command/command-execution.js +25 -39
- package/dist/commands/command/execution-source-loader.js +10 -14
- package/dist/commands/completions.js +1 -1
- package/dist/commands/config-cli.js +14 -5
- package/dist/commands/env/child-env.js +12 -14
- package/dist/commands/env/env-binding.js +47 -58
- package/dist/commands/env/env-cli.js +22 -24
- package/dist/commands/env/env.js +10 -58
- package/dist/commands/env/secret-cli.js +11 -29
- package/dist/commands/env/secret.js +3 -10
- package/dist/commands/health/checks.js +10 -849
- package/dist/commands/health/connections-and-harnesses-check.js +109 -0
- package/dist/commands/health/egress.js +3 -3
- package/dist/commands/health/html-report.js +9 -10
- package/dist/commands/health/plugin-staleness.js +18 -11
- package/dist/commands/health/report-view-model.js +16 -12
- package/dist/commands/health/scheduler-binary.js +1 -1
- package/dist/commands/health/semantic-search-check.js +85 -0
- package/dist/commands/health/type-directory-check.js +0 -3
- package/dist/commands/health.js +30 -42
- package/dist/commands/improve/consolidate/pair-pass.js +10 -25
- package/dist/commands/improve/consolidate.js +10 -15
- package/dist/commands/improve/distill.js +5 -17
- package/dist/commands/improve/eligibility.js +1 -3
- package/dist/commands/improve/execution.js +37 -40
- package/dist/commands/improve/extract-cli.js +6 -11
- package/dist/commands/improve/extract-prompt.js +2 -2
- package/dist/commands/improve/extract.js +67 -97
- package/dist/commands/improve/improve-cli.js +22 -128
- package/dist/commands/improve/improve-report.js +1 -1
- package/dist/commands/improve/improve-strategies.js +25 -108
- package/dist/commands/improve/improve.js +10 -14
- package/dist/commands/improve/loop-stages.js +3 -0
- package/dist/commands/improve/memory/memory-improve.js +1 -1
- package/dist/commands/improve/preparation.js +8 -13
- package/dist/commands/improve/reflect.js +203 -332
- package/dist/commands/improve/retrieval-scope.js +1 -1
- package/dist/commands/improve/session-asset.js +3 -2
- package/dist/commands/improve/stage.js +87 -115
- package/dist/commands/lint/base-linter.js +3 -3
- package/dist/commands/lint/env-key-rules.js +7 -6
- package/dist/commands/lint/index.js +3 -3
- package/dist/commands/models-cli.js +103 -63
- package/dist/commands/proposal/drain.js +26 -39
- package/dist/commands/proposal/proposal-cli.js +14 -18
- package/dist/commands/proposal/propose-cli.js +4 -2
- package/dist/commands/proposal/propose.js +37 -64
- package/dist/commands/proposal/repository.js +17 -17
- package/dist/commands/proposal/validators/proposal-validators.js +3 -6
- package/dist/commands/read/curate.js +10 -6
- package/dist/commands/read/registry-search.js +2 -48
- package/dist/commands/read/search-cli.js +1 -8
- package/dist/commands/read/search.js +5 -6
- package/dist/commands/read/show.js +6 -29
- package/dist/commands/remember.js +25 -40
- package/dist/commands/sources/add-cli.js +8 -63
- package/dist/commands/sources/bundle-cli.js +8 -9
- package/dist/commands/sources/bundle-config-ops.js +2 -2
- package/dist/commands/sources/info.js +12 -1
- package/dist/commands/sources/init.js +1 -1
- package/dist/commands/sources/installed-stashes.js +119 -63
- package/dist/commands/sources/migration-help.js +1 -1
- package/dist/commands/sources/plugin-upgrade.js +8 -15
- package/dist/commands/sources/schema-repair.js +4 -10
- package/dist/commands/sources/source-add.js +2 -2
- package/dist/commands/sources/source-clone.js +31 -7
- package/dist/commands/sources/source-manage.js +4 -4
- package/dist/commands/targets.js +175 -0
- package/dist/commands/tasks/explain.js +104 -69
- package/dist/commands/tasks/tasks-cli.js +9 -11
- package/dist/commands/tasks/tasks.js +75 -97
- package/dist/commands/ui/api.js +11 -3
- package/dist/commands/ui/redact.js +5 -31
- package/dist/commands/ui/workspace-actions.js +1 -1
- package/dist/commands/workflow/plan.js +48 -9
- package/dist/commands/workflow-cli.js +40 -45
- package/dist/core/adapter/adapters/agent-skills-adapter.js +10 -11
- package/dist/core/adapter/adapters/akm-adapter.js +36 -41
- package/dist/core/adapter/adapters/akm-lint.js +10 -12
- package/dist/core/adapter/adapters/akm-metadata.js +2 -2
- package/dist/core/adapter/adapters/akm-task-adapter.js +8 -9
- package/dist/core/adapter/adapters/akm-workflow-adapter.js +5 -5
- package/dist/core/adapter/adapters/claude-adapter.js +1 -1
- package/dist/core/adapter/adapters/dotenv-adapter.js +7 -6
- package/dist/core/adapter/adapters/generic-files-adapter.js +5 -5
- package/dist/core/adapter/adapters/index.js +3 -4
- package/dist/core/adapter/adapters/llm-wiki-adapter.js +12 -14
- package/dist/core/adapter/adapters/okf-adapter.js +8 -10
- package/dist/core/adapter/adapters/opencode-adapter.js +1 -1
- package/dist/core/adapter/adapters/shared.js +3 -3
- package/dist/core/adapter/adapters/tool-dir-shared.js +7 -25
- package/dist/core/adapter/adapters/website-snapshot-adapter.js +3 -3
- package/dist/core/adapter/detect-adapter.js +1 -1
- package/dist/core/adapter/execution-source.js +13 -35
- package/dist/core/adapter/registry.js +1 -1
- package/dist/core/adapter/validate-context.js +2 -4
- package/dist/core/asset/asset-placement.js +1 -1
- package/dist/core/asset/asset-ref.js +3 -3
- package/dist/core/asset/resolve-ref.js +5 -0
- package/dist/core/bundle-rename.js +12 -4
- package/dist/core/closest-match.js +37 -0
- package/dist/core/common.js +37 -57
- package/dist/core/config/config-io.js +26 -18
- package/dist/core/config/config-schema.js +19 -106
- package/dist/core/config/config-sources.js +3 -3
- package/dist/core/config/config-types.js +4 -4
- package/dist/core/config/config-walker.js +50 -77
- package/dist/core/config/config.js +438 -109
- package/dist/core/config/convert-engine-references.js +114 -0
- package/dist/core/config/convert-engines-shared.js +40 -0
- package/dist/core/config/convert-engines.js +300 -0
- package/dist/core/config/convert-models-overlay.js +137 -0
- package/dist/core/config/credentials.js +304 -0
- package/dist/core/config/engine-semantics.js +3 -3
- package/dist/core/config/migrate-keys.js +222 -0
- package/dist/core/config/model-aliases.js +37 -0
- package/dist/core/config/models-file.js +34 -0
- package/dist/core/config/retired-engines.js +53 -0
- package/dist/core/config/schema/connections.js +41 -0
- package/dist/core/config/schema/embedding.js +2 -2
- package/dist/core/config/schema/harnesses.js +41 -0
- package/dist/core/config/schema/improve-processes.js +9 -28
- package/dist/core/config/schema/improve.js +36 -1
- package/dist/core/config/schema/index-config.js +18 -20
- package/dist/core/config/schema/primitives.js +42 -17
- package/dist/core/config/schema/search.js +6 -11
- package/dist/core/config/schema/sources-bundles.js +9 -9
- package/dist/core/config/schema/workflow.js +2 -6
- package/dist/core/config/unusable-entries.js +66 -0
- package/dist/core/content-safety.js +3 -6
- package/dist/core/endpoint-url.js +47 -0
- package/dist/core/env-secret-ref.js +84 -73
- package/dist/core/errors.js +10 -16
- package/dist/core/extra-params.js +3 -3
- package/dist/core/improve-result.js +8 -9
- package/dist/core/json-schema.js +1 -1
- package/dist/core/lesson-lint.js +1 -1
- package/dist/core/llm-inference.js +80 -0
- package/dist/core/parse.js +2 -2
- package/dist/core/paths.js +33 -10
- package/dist/core/recognition-util.js +8 -10
- package/dist/core/redaction.js +94 -55
- package/dist/core/ref-token.js +82 -0
- package/dist/core/secret-value.js +14 -0
- package/dist/core/state/migrations.js +17 -22
- package/dist/core/structured.js +2 -68
- package/dist/core/subprocess.js +63 -22
- package/dist/core/type-presentation.js +10 -14
- package/dist/core/write-source.js +20 -4
- package/dist/execution/input-contract.js +3 -6
- package/dist/execution/notices.js +49 -0
- package/dist/execution/resolved-request.js +24 -40
- package/dist/execution/source.js +21 -45
- package/dist/execution/target-ref.js +2 -2
- package/dist/indexer/bundle-identity-guard.js +6 -5
- package/dist/indexer/ensure-index.js +1 -1
- package/dist/indexer/index-writer-lock.js +1 -1
- package/dist/indexer/indexer.js +46 -42
- package/dist/indexer/installations.js +12 -22
- package/dist/indexer/lookup/adapter-concept-owner.js +40 -14
- package/dist/indexer/materialize-embeddings.js +20 -16
- package/dist/indexer/passes/memory-inference.js +21 -50
- package/dist/indexer/passes/metadata.js +5 -5
- package/dist/indexer/scan/doc-to-entry.js +1 -1
- package/dist/indexer/scan/drain-dir.js +9 -11
- package/dist/indexer/search/db-search.js +9 -7
- package/dist/indexer/search/search-source.js +42 -22
- package/dist/indexer/usage/usage-events.js +2 -3
- package/dist/indexer/walk/index-context.js +2 -1
- package/dist/indexer/walk/matchers.js +3 -11
- package/dist/indexer/walk/path-resolver.js +13 -68
- package/dist/indexer/walk/walker.js +32 -26
- package/dist/integrations/agent/akm-read-tools.js +81 -0
- package/dist/integrations/agent/config.js +1 -1
- package/dist/integrations/agent/detect.js +32 -36
- package/dist/integrations/agent/execution.js +130 -428
- package/dist/integrations/agent/index.js +1 -1
- package/dist/integrations/agent/profiles.js +24 -28
- package/dist/integrations/agent/prompts.js +17 -30
- package/dist/integrations/agent/request-lowering.js +67 -101
- package/dist/integrations/agent/resolution.js +332 -0
- package/dist/integrations/agent/runner-dispatch.js +156 -181
- package/dist/integrations/agent/runner.js +20 -70
- package/dist/integrations/agent/runtime-port.js +4 -0
- package/dist/integrations/agent/runtime.js +10 -0
- package/dist/integrations/agent/spawn.js +65 -190
- package/dist/integrations/harnesses/aider/index.js +19 -39
- package/dist/integrations/harnesses/amazonq/index.js +17 -32
- package/dist/integrations/harnesses/claude/index.js +59 -28
- package/dist/integrations/harnesses/claude/session-log.js +7 -5
- package/dist/integrations/harnesses/codex/index.js +19 -31
- package/dist/integrations/harnesses/copilot/index.js +17 -35
- package/dist/integrations/harnesses/gemini/index.js +18 -34
- package/dist/integrations/harnesses/harness.js +36 -0
- package/dist/integrations/harnesses/index.js +20 -51
- package/dist/integrations/harnesses/opencode/agent-builder.js +132 -100
- package/dist/integrations/harnesses/opencode/index.js +11 -33
- package/dist/integrations/harnesses/opencode/roots.js +50 -0
- package/dist/integrations/harnesses/opencode/runtime/binary.js +206 -0
- package/dist/integrations/harnesses/opencode/runtime/command.js +152 -0
- package/dist/integrations/harnesses/opencode/runtime/index.js +177 -0
- package/dist/integrations/harnesses/opencode/runtime/tar.js +107 -0
- package/dist/integrations/harnesses/opencode/session-log-v1.js +15 -7
- package/dist/integrations/harnesses/opencode/session-log-v2.js +72 -48
- package/dist/integrations/harnesses/opencode/session-log.js +58 -137
- package/dist/integrations/harnesses/opencode/version.js +34 -53
- package/dist/integrations/harnesses/openhands/index.js +13 -37
- package/dist/integrations/harnesses/pi/index.js +21 -32
- package/dist/integrations/lockfile.js +1 -1
- package/dist/integrations/session-logs/index.js +11 -31
- package/dist/llm/client.js +93 -111
- package/dist/llm/embedder.js +19 -34
- package/dist/llm/embedders/connection.js +31 -0
- package/dist/llm/embedders/local-model-files.js +56 -0
- package/dist/llm/embedders/local.js +146 -115
- package/dist/llm/embedders/remote.js +26 -23
- package/dist/llm/embedders/types.js +1 -1
- package/dist/llm/index-passes.js +33 -39
- package/dist/llm/memory-infer.js +67 -77
- package/dist/llm/model-list.js +35 -0
- package/dist/llm/rerank-client.js +8 -14
- package/dist/llm/structured-call.js +45 -99
- package/dist/llm/structured.js +60 -0
- package/dist/output/renderers.js +2 -8
- package/dist/output/shapes/helpers.js +18 -44
- package/dist/output/shapes/passthrough.js +1 -0
- package/dist/output/shapes.js +1 -7
- package/dist/output/text/command-format.js +41 -39
- package/dist/output/text/health-format.js +8 -2
- package/dist/output/text/helpers.js +1 -1
- package/dist/output/text/migrate.js +12 -0
- package/dist/output/text/models.js +3 -2
- package/dist/output/text/registry-commands.js +1 -2
- package/dist/output/text/show-directives.js +16 -28
- package/dist/output/text/show-format.js +0 -2
- package/dist/output/text/targets-table.js +70 -0
- package/dist/output/text/workflow-format.js +44 -15
- package/dist/output/text.js +1 -1
- package/dist/registry/providers/skills-sh.js +1 -28
- package/dist/registry/providers/static-index.js +1 -71
- package/dist/runtime.js +6 -2
- package/dist/scripts/akm-migrate-node.js +47095 -44905
- package/dist/scripts/akm-migrate.js +46946 -44755
- package/dist/setup/detect.js +28 -273
- package/dist/setup/endpoint.js +36 -0
- package/dist/setup/semantic-assets.js +13 -19
- package/dist/setup/setup-flags.js +77 -0
- package/dist/setup/setup-plan.js +144 -0
- package/dist/setup/setup.js +134 -358
- package/dist/setup/steps/connection-shared.js +49 -101
- package/dist/setup/steps/connection.js +121 -524
- package/dist/setup/steps/embeddings.js +151 -0
- package/dist/setup/steps/harnesses.js +118 -0
- package/dist/setup/steps/platforms.js +2 -81
- package/dist/setup/steps/tasks.js +1 -2
- package/dist/setup/steps.js +10 -0
- package/dist/setup/summary.js +67 -0
- package/dist/sources/freshness.js +16 -21
- package/dist/sources/providers/git-provider.js +2 -9
- package/dist/sources/providers/provider-utils.js +13 -5
- package/dist/sources/resolve.js +12 -16
- package/dist/sources/snapshot-fetchers/robots.js +11 -12
- package/dist/sources/snapshot-fetchers/secret-seam.js +2 -4
- package/dist/sources/snapshot-fetchers/website-ingest.js +8 -15
- package/dist/sources/snapshot-fetchers/x.js +1 -1
- package/dist/standalone/onnxruntime-library.js +52 -0
- package/dist/storage/repositories/improve-ledger-repository.js +1 -1
- package/dist/storage/repositories/improve-runs-repository.js +0 -13
- package/dist/storage/repositories/index-entries-repository.js +2 -2
- package/dist/storage/repositories/proposals-repository.js +2 -2
- package/dist/storage/repositories/task-history-repository.js +2 -2
- package/dist/storage/repositories/workflow-runs-repository.js +44 -129
- package/dist/storage/sqlite-read-snapshot.js +33 -29
- package/dist/tasks/embedded.js +1 -1
- package/dist/tasks/log-redaction.js +7 -119
- package/dist/tasks/prepare/prepare-support.js +8 -7
- package/dist/tasks/prepare/prepare.js +8 -9
- package/dist/tasks/prepare/script-capture.js +9 -25
- package/dist/tasks/run/attempt-lifecycle.js +17 -35
- package/dist/tasks/run/load-task.js +54 -27
- package/dist/tasks/run/run-command-task.js +15 -10
- package/dist/tasks/run/run-native-task.js +8 -21
- package/dist/tasks/run/run-task.js +5 -8
- package/dist/tasks/run/run-workflow-task.js +14 -21
- package/dist/tasks/run/task-history.js +9 -17
- package/dist/tasks/run/task-log.js +1 -5
- package/dist/tasks/scheduler-invocation.js +13 -18
- package/dist/tasks/scheduler-sync.js +0 -1
- package/dist/tasks/source/bounded-document.js +31 -117
- package/dist/tasks/source/parse-task-source.js +0 -1
- package/dist/tasks/source/project-v4.js +5 -3
- package/dist/tasks/source/task-input-diagnostics.js +3 -4
- package/dist/tasks/source/task-source-v4.js +48 -72
- package/dist/tasks/source-v3.js +2 -5
- package/dist/tasks/task-run-reserved-flags.js +1 -2
- package/dist/workflows/authoring/authoring.js +2 -7
- package/dist/workflows/compile.js +1 -15
- package/dist/workflows/concurrency-policy.js +4 -4
- package/dist/workflows/exec/child-workflow.js +1 -4
- package/dist/workflows/exec/dispatch-redaction.js +35 -86
- package/dist/workflows/exec/environment.js +13 -77
- package/dist/workflows/exec/exec-unit.js +14 -55
- package/dist/workflows/exec/frozen-judge.js +26 -28
- package/dist/workflows/exec/native-executor.js +126 -71
- package/dist/workflows/exec/run-workflow.js +38 -42
- package/dist/workflows/exec/step-work.js +13 -17
- package/dist/workflows/exec/unit-dispatch.js +7 -21
- package/dist/workflows/freeze/environment.js +14 -119
- package/dist/workflows/freeze/freeze.js +14 -33
- package/dist/workflows/freeze/step-values.js +6 -13
- package/dist/workflows/freeze/targets/child-workflow.js +3 -5
- package/dist/workflows/freeze/targets/command.js +9 -15
- package/dist/workflows/freeze/targets/shell.js +0 -3
- package/dist/workflows/freeze/task-bindings.js +0 -1
- package/dist/workflows/parser.js +50 -59
- package/dist/workflows/plan.js +8 -2
- package/dist/workflows/renderer.js +83 -9
- package/dist/workflows/resource-limits.js +2 -2
- package/dist/workflows/runtime/run-plan.js +38 -23
- package/dist/workflows/runtime/runs.js +55 -93
- package/dist/workflows/runtime/workflow-asset-loader.js +55 -86
- package/dist/workflows/source-files.js +7 -19
- package/docs/README.md +10 -16
- package/docs/architecture/README.md +2 -37
- package/docs/architecture/adapters.md +2 -2
- package/docs/architecture/akm-core-principles.md +256 -118
- package/docs/architecture/architecture.md +283 -99
- package/docs/architecture/improvement.md +8 -2
- package/docs/architecture/internals/classification.md +1 -3
- package/docs/architecture/internals/fresh-host-rebuild-runbook.md +7 -6
- package/docs/architecture/internals/health-advisories.md +35 -74
- package/docs/architecture/internals/improve-workflow.md +27 -26
- package/docs/architecture/internals/indexing.md +3 -3
- package/docs/architecture/internals/storage-locations.md +48 -15
- package/docs/architecture/persisted-data-compat.md +10 -6
- package/docs/architecture/specs/okf-support.md +9 -11
- package/docs/architecture/specs/ref.md +7 -9
- package/docs/architecture/testing/testing-workflow.md +172 -52
- package/docs/architecture/workflow-engine.md +51 -34
- package/docs/guides/README.md +0 -1
- package/docs/guides/author-bundles.md +15 -20
- package/docs/guides/author-workflows.md +93 -71
- package/docs/guides/bundles.md +20 -16
- package/docs/guides/discover-and-load.md +1 -1
- package/docs/guides/getting-started.md +49 -3
- package/docs/guides/improve-the-library.md +10 -4
- package/docs/guides/recipes/headless-install.md +11 -16
- package/docs/guides/run-workflows.md +29 -20
- package/docs/guides/scheduling.md +2 -2
- package/docs/guides/use-with-any-agent.md +20 -22
- package/docs/integration/bundling-akm.md +19 -9
- package/docs/maintainers/README.md +2 -6
- package/docs/maintainers/release-checklist.md +73 -126
- package/docs/migration/README.md +10 -3
- package/docs/migration/release-notes/0.10.0.md +81 -16
- package/docs/migration/release-notes/0.6.0.md +1 -1
- package/docs/migration/release-notes/0.7.0.md +1 -1
- package/docs/migration/release-notes/0.9.0.md +1 -1
- package/docs/migration/release-notes/README.md +1 -1
- package/docs/migration/v0.9-to-v0.10.md +300 -60
- package/docs/migration/v0.9.1-to-v0.9.2.md +6 -5
- package/docs/posts/config-v2-lessons-16.md +1 -1
- package/docs/posts/llm-mode-reflect-13.md +1 -1
- package/docs/posts/release-0.6.0.md +11 -11
- package/docs/posts/release-0.8.0.md +4 -4
- package/docs/posts/workflows-vaults-09.md +1 -1
- package/docs/reference/README.md +1 -1
- package/docs/reference/asset-types.md +2 -2
- package/docs/reference/cli.md +477 -388
- package/docs/reference/configuration.md +569 -550
- package/docs/reference/data-and-telemetry.md +9 -6
- package/docs/reference/env-and-secrets.md +72 -15
- package/docs/reference/refs.md +3 -20
- package/docs/reference/registry.md +12 -38
- package/docs/reference/supported-formats.md +1 -1
- package/docs/reference/tasks.md +22 -11
- package/docs/reference/ui-api.md +14 -9
- package/docs/reference/workflow-schema.md +199 -154
- package/docs/reference/workflows.md +4 -6
- package/package.json +9 -11
- package/schemas/akm-config.json +1696 -2922
- package/schemas/akm-task.json +4 -4
- package/schemas/akm-workflow.json +36 -9
- package/ROADMAP.md +0 -112
- package/dist/assets/models.json +0 -35
- package/dist/commands/health/engine-usage.js +0 -45
- package/dist/commands/sources/dangerous-env-audit.js +0 -134
- package/dist/core/activation-policy.js +0 -67
- package/dist/core/config/schema/engines.js +0 -160
- package/dist/core/config/schema/execution.js +0 -23
- package/dist/core/spawn-env.js +0 -268
- package/dist/execution/directory-identity.js +0 -78
- package/dist/integrations/agent/builder-shared.js +0 -33
- package/dist/integrations/agent/builders.js +0 -43
- package/dist/integrations/agent/engine-fallback.js +0 -59
- package/dist/integrations/agent/engine-resolution.js +0 -333
- package/dist/integrations/agent/model-map.js +0 -475
- package/dist/integrations/harnesses/aider/agent-builder.js +0 -107
- package/dist/integrations/harnesses/aider/result-extractor.js +0 -53
- package/dist/integrations/harnesses/amazonq/agent-builder.js +0 -138
- package/dist/integrations/harnesses/amazonq/result-extractor.js +0 -48
- package/dist/integrations/harnesses/claude/agent-builder.js +0 -106
- package/dist/integrations/harnesses/claude/config-import.js +0 -67
- package/dist/integrations/harnesses/claude/result-extractor.js +0 -67
- package/dist/integrations/harnesses/codex/agent-builder.js +0 -150
- package/dist/integrations/harnesses/codex/result-extractor.js +0 -110
- package/dist/integrations/harnesses/copilot/agent-builder.js +0 -117
- package/dist/integrations/harnesses/copilot/result-extractor.js +0 -178
- package/dist/integrations/harnesses/gemini/agent-builder.js +0 -114
- package/dist/integrations/harnesses/gemini/result-extractor.js +0 -149
- package/dist/integrations/harnesses/opencode/config-import.js +0 -149
- package/dist/integrations/harnesses/opencode/model-config.js +0 -33
- package/dist/integrations/harnesses/opencode/model-work-agent.js +0 -115
- package/dist/integrations/harnesses/opencode/session-log-types.js +0 -12
- package/dist/integrations/harnesses/opencode-sdk/index.js +0 -44
- package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +0 -1052
- package/dist/integrations/harnesses/opencode-sdk/v1-adapter.js +0 -199
- package/dist/integrations/harnesses/opencode-sdk/v2-adapter.js +0 -254
- package/dist/integrations/harnesses/opencode-sdk/wire.js +0 -66
- package/dist/integrations/harnesses/openhands/agent-builder.js +0 -120
- package/dist/integrations/harnesses/openhands/result-extractor.js +0 -135
- package/dist/integrations/harnesses/pi/agent-builder.js +0 -89
- package/dist/integrations/harnesses/pi/result-extractor.js +0 -168
- package/dist/integrations/harnesses/shared.js +0 -18
- package/dist/integrations/harnesses/types.js +0 -55
- package/dist/llm/feature-gate.js +0 -115
- package/dist/output/shapes/models-list.js +0 -16
- package/dist/output/shapes/registry-search.js +0 -10
- package/dist/setup/detected-engines.js +0 -136
- package/dist/setup/engine-config.js +0 -97
- package/dist/setup/harness-config-import.js +0 -47
- package/dist/setup/providers.js +0 -14
- package/dist/setup/steps/semantic.js +0 -39
- package/dist/workflows/authoring/scope-key.js +0 -79
- package/dist/workflows/exec/lowering-notices.js +0 -23
- package/dist/workflows/source-semantics.js +0 -110
- package/docs/architecture/0.10-process-rules.md +0 -832
- package/docs/architecture/akm-architecture-decision-history.md +0 -2055
- package/docs/architecture/comparisons/claude-code-vs-akm-workflows-full.md +0 -550
- package/docs/architecture/decisions/0001-no-interpolation-attached-structured-context.md +0 -72
- package/docs/architecture/decisions/0002-unit-reuse-and-input-hash-scope.md +0 -142
- package/docs/architecture/decisions/0003-child-env-allowlist-and-provenance.md +0 -189
- package/docs/architecture/decisions/0004-task-input-contract-and-flag-coercion.md +0 -97
- package/docs/architecture/decisions/0005-task-result-vocabulary-and-legacy-read-mapping.md +0 -108
- package/docs/architecture/decisions/0006-task-source-version-routing.md +0 -124
- package/docs/architecture/decisions/0007-workflow-composition-bounds.md +0 -83
- package/docs/architecture/decisions/0008-task-binding-normalization.md +0 -88
- package/docs/architecture/decisions/0009-child-run-publication-column-parity.md +0 -80
- package/docs/architecture/decisions/0010-driver-protocol-cut.md +0 -36
- package/docs/architecture/decisions/0011-engine-run-loop-invariants.md +0 -125
- package/docs/architecture/decisions/README.md +0 -62
- package/docs/architecture/internals/functional-contract-patterns.md +0 -340
- package/docs/architecture/internals/registry-network-boundary.md +0 -57
- package/docs/architecture/internals/search.md +0 -248
- package/docs/architecture/reviews/env-secret-access.md +0 -319
- package/docs/architecture/runtime-boundary-design.md +0 -153
- package/docs/architecture/specs/0.9.0-close-out-plan.md +0 -361
- package/docs/architecture/specs/0.9.0-decisions.md +0 -532
- package/docs/architecture/specs/0.9.0-docs-code-drift-register.md +0 -745
- package/docs/architecture/specs/0.9.0-open-items-register.md +0 -135
- package/docs/architecture/specs/0.9.0-public-api-issue-backlog.md +0 -740
- package/docs/architecture/specs/0.9.0-release-surface-review.md +0 -636
- package/docs/architecture/specs/agent-command-engine-model-design.md +0 -513
- package/docs/architecture/specs/akm-0.9.0-bundle-adapter-spec.md +0 -501
- package/docs/architecture/specs/akm-0.9.0-ref-grammar-decision.md +0 -291
- package/docs/architecture/specs/akm-format-neutral-bundle-workspace-spec.md +0 -2059
- package/docs/architecture/specs/di-seams-plan.md +0 -539
- package/docs/architecture/specs/driver-protocol-keep-or-cut.md +0 -275
- package/docs/architecture/specs/fact-asset-type.md +0 -142
- package/docs/architecture/specs/improve-collapse-churn-detector-design.md +0 -634
- package/docs/architecture/specs/reviews/task-workflow-unification/README.md +0 -72
- package/docs/architecture/specs/reviews/task-workflow-unification/findings-consolidated.md +0 -152
- package/docs/architecture/specs/reviews/task-workflow-unification/library-eval-alternatives.md +0 -352
- package/docs/architecture/specs/reviews/task-workflow-unification/library-eval-bunqueue.md +0 -300
- package/docs/architecture/specs/reviews/task-workflow-unification/library-eval-openworkflow.md +0 -402
- package/docs/architecture/specs/reviews/task-workflow-unification/opus-review-1.md +0 -758
- package/docs/architecture/specs/reviews/task-workflow-unification/opus-review-2.md +0 -645
- package/docs/architecture/specs/reviews/task-workflow-unification/opus-review-3.md +0 -602
- package/docs/architecture/specs/reviews/task-workflow-unification/panel-r1-adversarial.md +0 -27
- package/docs/architecture/specs/reviews/task-workflow-unification/panel-r1-architecture.md +0 -27
- package/docs/architecture/specs/reviews/task-workflow-unification/panel-r1-coverage.md +0 -74
- package/docs/architecture/specs/reviews/task-workflow-unification/panel-r1-security.md +0 -15
- package/docs/architecture/specs/reviews/task-workflow-unification/panel-r2-adversarial.md +0 -132
- package/docs/architecture/specs/reviews/task-workflow-unification/panel-r2-verification.md +0 -147
- package/docs/architecture/specs/stash-conventions-code-spec.md +0 -275
- package/docs/architecture/specs/stash-organization-conventions.md +0 -377
- package/docs/architecture/specs/task-workflow-format-unification.md +0 -721
- package/docs/architecture/specs/workflow-engine-buy-vs-build.md +0 -231
- package/docs/architecture/specs/workflow-format-unification.md +0 -432
- package/docs/architecture/testing/manual-testing-checklist.md +0 -3411
- package/docs/architecture/testing/okf-v0.2-conformance-runbook.md +0 -924
- package/docs/architecture/testing/task-workflow-manual-tests.md +0 -1720
- package/docs/guides/claude-code-vs-akm-workflows.md +0 -29
- package/docs/guides/knowledge-management.md +0 -18
- package/docs/maintainers/curate-workmap.md +0 -335
- package/docs/migration/v0.5-to-v0.6.md +0 -759
- package/docs/migration/v0.7-to-v0.8.md +0 -1378
- package/docs/plans/0.9.2-agent-command-workflow-plan.md +0 -423
|
@@ -1,160 +0,0 @@
|
|
|
1
|
-
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
-
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
-
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
|
-
/**
|
|
5
|
-
* OpenAI-compatible LLM connection configs + named agent/LLM engine schemas
|
|
6
|
-
* (`engines`). Extracted verbatim from the former `config-schema.ts` monolith —
|
|
7
|
-
* no behavior change.
|
|
8
|
-
*/
|
|
9
|
-
import { z } from "zod";
|
|
10
|
-
// Harness ids come straight from the harness registry (the same source
|
|
11
|
-
// `config-types.ts` re-exports them from). Importing them here rather than via
|
|
12
|
-
// `../config-types` keeps `schema/*` free of any edge to `config-types`, which
|
|
13
|
-
// type-derives from this barrel via `typeof import("./config-schema")` —
|
|
14
|
-
// routing through config-types would mint a config-schema ↔ config-types type
|
|
15
|
-
// cycle that collapses inference.
|
|
16
|
-
import { HARNESS_AGENT_DISPATCH_IDS, HARNESS_NATIVE_AGENT_IDS, VALID_HARNESS_IDS, } from "../../../integrations/harnesses/index.js";
|
|
17
|
-
import { WORKFLOW_MAX_TIMEOUT_MS } from "../../../workflows/resource-limits.js";
|
|
18
|
-
import { chatCompletionsEndpoint, ExtraParamsSchema, engineName, nonEmptyString, positiveInt, symbolicOrWarnApiKey, } from "./primitives.js";
|
|
19
|
-
/**
|
|
20
|
-
* Engine-config timeouts share the workflow ceiling.
|
|
21
|
-
*
|
|
22
|
-
* 0.9.1 bounded workflow-authored timeouts (parser) and frozen invocations
|
|
23
|
-
* (decoder) at 2^31-1, but the third source — `engines.<name>.timeoutMs` — was
|
|
24
|
-
* validated only as a positive integer. A larger value passed config validation
|
|
25
|
-
* and then failed EVERY run of that engine with an unlocated "Invalid frozen
|
|
26
|
-
* workflow plan: invocation is invalid". Reject it where the value is written.
|
|
27
|
-
*/
|
|
28
|
-
const timeoutMsField = z.union([positiveInt.max(WORKFLOW_MAX_TIMEOUT_MS), z.null()]).optional();
|
|
29
|
-
// ── Connection configs (LLM) ────────────────────────────────────────────────
|
|
30
|
-
/**
|
|
31
|
-
* OpenAI-compatible connection fields shared by named LLM engines and bounded
|
|
32
|
-
* internal call helpers. `model` is required at schema level: current loads and
|
|
33
|
-
* CLI writes reject a partial named engine rather than normalizing it through a
|
|
34
|
-
* pre-schema compatibility transform.
|
|
35
|
-
*/
|
|
36
|
-
export const LlmConnectionConfigSchema = z
|
|
37
|
-
.object({
|
|
38
|
-
provider: z.string().optional(),
|
|
39
|
-
endpoint: z.string(),
|
|
40
|
-
model: z.string(),
|
|
41
|
-
apiKey: z.string().optional(),
|
|
42
|
-
temperature: z.number().finite().optional(),
|
|
43
|
-
maxTokens: positiveInt.optional(),
|
|
44
|
-
timeoutMs: timeoutMsField,
|
|
45
|
-
concurrency: positiveInt.optional(),
|
|
46
|
-
// User-settable override, not a cached probe verdict: attempt-then-
|
|
47
|
-
// fallback in llm/client.ts tries `response_format: json_schema` whenever
|
|
48
|
-
// a schema is supplied, degrading to plain text on an unsupported-4xx and
|
|
49
|
-
// remembering that in-memory for the rest of the process. `false` here
|
|
50
|
-
// opts a known-incompatible endpoint out of even the first attempt;
|
|
51
|
-
// `true` is advisory only.
|
|
52
|
-
supportsJsonSchema: z.boolean().optional(),
|
|
53
|
-
extraParams: ExtraParamsSchema.optional(),
|
|
54
|
-
contextLength: positiveInt.optional(),
|
|
55
|
-
enableThinking: z.boolean().optional(),
|
|
56
|
-
reasoningEffort: nonEmptyString.optional(),
|
|
57
|
-
})
|
|
58
|
-
.passthrough();
|
|
59
|
-
export const LlmProfileConfigSchema = LlmConnectionConfigSchema.passthrough();
|
|
60
|
-
// ── Agent engines ───────────────────────────────────────────────────────────
|
|
61
|
-
// Derives from the canonical VALID_HARNESS_IDS (#565) so the Zod gate cannot
|
|
62
|
-
// drift from the TS union / parse check / setup detection.
|
|
63
|
-
const AgentPlatformSchema = z.enum(VALID_HARNESS_IDS);
|
|
64
|
-
const LlmEngineSchema = z
|
|
65
|
-
.object({
|
|
66
|
-
kind: z.literal("llm"),
|
|
67
|
-
provider: z.string().optional(),
|
|
68
|
-
endpoint: chatCompletionsEndpoint,
|
|
69
|
-
model: nonEmptyString,
|
|
70
|
-
apiKey: symbolicOrWarnApiKey("engines.<name>.apiKey").optional(),
|
|
71
|
-
// #905: file-backed alternative to `apiKey` for hosts that refuse
|
|
72
|
-
// secrets in the process environment. A plain filesystem path (`~`
|
|
73
|
-
// expanded, read at dispatch) — see resolveLlmEngineUse/
|
|
74
|
-
// materializeLlmConnectionWithCredential in integrations/agent/engine-resolution.ts.
|
|
75
|
-
apiKeyFile: nonEmptyString.optional(),
|
|
76
|
-
temperature: z.number().finite().optional(),
|
|
77
|
-
maxTokens: positiveInt.optional(),
|
|
78
|
-
timeoutMs: timeoutMsField,
|
|
79
|
-
concurrency: positiveInt.optional(),
|
|
80
|
-
// Same user-settable override LlmConnectionConfigSchema declares above; a
|
|
81
|
-
// named `kind: "llm"` engine is validated by THIS object, so without the
|
|
82
|
-
// field here the unknown-key walk reported a live setting as unknown and
|
|
83
|
-
// `akm migrate apply` dropped it from config.json.
|
|
84
|
-
supportsJsonSchema: z.boolean().optional(),
|
|
85
|
-
extraParams: ExtraParamsSchema.optional(),
|
|
86
|
-
contextLength: positiveInt.optional(),
|
|
87
|
-
enableThinking: z.boolean().optional(),
|
|
88
|
-
reasoningEffort: nonEmptyString.optional(),
|
|
89
|
-
})
|
|
90
|
-
.passthrough()
|
|
91
|
-
.superRefine((value, ctx) => {
|
|
92
|
-
for (const key of ["platform", "bin", "args", "workspace", "modelAliases", "llmEngine", "agent"]) {
|
|
93
|
-
if (key in value)
|
|
94
|
-
ctx.addIssue({ code: z.ZodIssueCode.custom, path: [key], message: `${key} is not valid on an LLM engine` });
|
|
95
|
-
}
|
|
96
|
-
// #905: apiKey and apiKeyFile are two alternative ways to supply the same
|
|
97
|
-
// credential; a third (the implicit AKM_ENGINE_<NAME>_API_KEY env var) is
|
|
98
|
-
// still available when neither is set, so only the both-set case is
|
|
99
|
-
// rejected here.
|
|
100
|
-
if (value.apiKey !== undefined && value.apiKeyFile !== undefined) {
|
|
101
|
-
ctx.addIssue({
|
|
102
|
-
code: z.ZodIssueCode.custom,
|
|
103
|
-
path: ["apiKeyFile"],
|
|
104
|
-
message: "apiKey and apiKeyFile cannot both be set",
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
|
-
});
|
|
108
|
-
const AgentEngineSchema = z
|
|
109
|
-
.object({
|
|
110
|
-
kind: z.literal("agent"),
|
|
111
|
-
platform: AgentPlatformSchema.refine((platform) => HARNESS_AGENT_DISPATCH_IDS.has(platform), {
|
|
112
|
-
message: "platform does not support agent dispatch",
|
|
113
|
-
}),
|
|
114
|
-
bin: nonEmptyString.optional(),
|
|
115
|
-
args: z.array(z.string()).optional(),
|
|
116
|
-
workspace: nonEmptyString.optional(),
|
|
117
|
-
model: nonEmptyString.optional(),
|
|
118
|
-
agent: nonEmptyString.optional(),
|
|
119
|
-
timeoutMs: timeoutMsField,
|
|
120
|
-
llmEngine: engineName.optional(),
|
|
121
|
-
})
|
|
122
|
-
.passthrough()
|
|
123
|
-
.superRefine((value, ctx) => {
|
|
124
|
-
for (const key of [
|
|
125
|
-
"provider",
|
|
126
|
-
"endpoint",
|
|
127
|
-
"apiKey",
|
|
128
|
-
"apiKeyFile",
|
|
129
|
-
"temperature",
|
|
130
|
-
"maxTokens",
|
|
131
|
-
"concurrency",
|
|
132
|
-
"extraParams",
|
|
133
|
-
"contextLength",
|
|
134
|
-
"enableThinking",
|
|
135
|
-
"reasoningEffort",
|
|
136
|
-
"modelAliases",
|
|
137
|
-
]) {
|
|
138
|
-
if (key in value)
|
|
139
|
-
ctx.addIssue({ code: z.ZodIssueCode.custom, path: [key], message: `${key} is not valid on an agent engine` });
|
|
140
|
-
}
|
|
141
|
-
if (value.platform !== "opencode-sdk" && value.llmEngine !== undefined) {
|
|
142
|
-
ctx.addIssue({
|
|
143
|
-
code: z.ZodIssueCode.custom,
|
|
144
|
-
path: ["llmEngine"],
|
|
145
|
-
message: "llmEngine is only valid on opencode-sdk",
|
|
146
|
-
});
|
|
147
|
-
}
|
|
148
|
-
if (value.agent !== undefined && !HARNESS_NATIVE_AGENT_IDS.has(value.platform)) {
|
|
149
|
-
ctx.addIssue({
|
|
150
|
-
code: z.ZodIssueCode.custom,
|
|
151
|
-
path: ["agent"],
|
|
152
|
-
message: `agent is not valid on ${value.platform}: it has no native agent selector`,
|
|
153
|
-
});
|
|
154
|
-
}
|
|
155
|
-
if (value.platform === "opencode-sdk" && value.args !== undefined) {
|
|
156
|
-
ctx.addIssue({ code: z.ZodIssueCode.custom, path: ["args"], message: "args is not valid on opencode-sdk" });
|
|
157
|
-
}
|
|
158
|
-
});
|
|
159
|
-
export const EngineConfigSchema = z.union([LlmEngineSchema, AgentEngineSchema]);
|
|
160
|
-
export const EnginesSchema = z.record(engineName, EngineConfigSchema);
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
-
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
-
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
|
-
import { z } from "zod";
|
|
5
|
-
const toolName = z.string().trim().min(1, "expected a non-empty tool name");
|
|
6
|
-
/** Host-owned ceiling for capabilities requested by executable assets. */
|
|
7
|
-
export const ExecutionPolicyConfigSchema = z
|
|
8
|
-
.object({
|
|
9
|
-
/** Exact tool names an asset may request. `*` is an explicit allow-all ceiling. */
|
|
10
|
-
allowedTools: z
|
|
11
|
-
.array(toolName)
|
|
12
|
-
.default([])
|
|
13
|
-
.superRefine((tools, ctx) => {
|
|
14
|
-
const seen = new Set();
|
|
15
|
-
for (const [index, tool] of tools.entries()) {
|
|
16
|
-
if (seen.has(tool)) {
|
|
17
|
-
ctx.addIssue({ code: z.ZodIssueCode.custom, path: [index], message: "duplicates an earlier tool name" });
|
|
18
|
-
}
|
|
19
|
-
seen.add(tool);
|
|
20
|
-
}
|
|
21
|
-
}),
|
|
22
|
-
})
|
|
23
|
-
.passthrough();
|
package/dist/core/spawn-env.js
DELETED
|
@@ -1,268 +0,0 @@
|
|
|
1
|
-
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
-
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
-
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
|
-
/**
|
|
5
|
-
* The ONE allowlist-based child-environment primitive.
|
|
6
|
-
*
|
|
7
|
-
* Three akm code paths spawn a child from an explicit list of environment
|
|
8
|
-
* variable NAMES — the agent-CLI spawn wrapper
|
|
9
|
-
* (`integrations/agent/spawn.ts`, `profile.envPassthrough`), the workflow
|
|
10
|
-
* `exec` unit runner (`workflows/exec/exec-unit.ts`), and the opencode-sdk
|
|
11
|
-
* server spawn (`integrations/harnesses/opencode-sdk/sdk-runner.ts`) — and
|
|
12
|
-
* all build their allowlist from {@link COMMON_SPAWN_ENV_PASSTHROUGH} /
|
|
13
|
-
* {@link spawnEnvNamesFor}. Keeping that in one leaf module is what makes
|
|
14
|
-
* "allowlist" a single reviewable mechanism instead of independent
|
|
15
|
-
* implementations that drift apart.
|
|
16
|
-
*
|
|
17
|
-
* A LEAF: node built-ins only, so both the integrations layer and the workflow
|
|
18
|
-
* engine can import it without opening a cycle.
|
|
19
|
-
*
|
|
20
|
-
* @module core/spawn-env
|
|
21
|
-
*/
|
|
22
|
-
import fs from "node:fs";
|
|
23
|
-
import os from "node:os";
|
|
24
|
-
import path from "node:path";
|
|
25
|
-
/**
|
|
26
|
-
* The baseline env names every allowlisted akm child receives regardless of
|
|
27
|
-
* what it runs: process identity (`HOME`, `USER`), tool resolution (`PATH`),
|
|
28
|
-
* locale (`LANG`, `LC_ALL`), terminal (`TERM`), scratch space (`TMPDIR`), and
|
|
29
|
-
* akm's own event provenance (`AKM_EVENT_SOURCE` — machine traffic, never a
|
|
30
|
-
* secret). BOTH allowlists extend it — the agent-CLI profiles'
|
|
31
|
-
* `COMMON_PASSTHROUGH` (`integrations/agent/profiles.ts`) and the workflow
|
|
32
|
-
* exec unit's `EXEC_DEFAULT_ENV_PASSTHROUGH` (`workflows/exec/exec-unit.ts`)
|
|
33
|
-
* — so a baseline name cannot drift into one child-spawn path but not the
|
|
34
|
-
* other. NOTE: profile `envPassthrough` is frozen into workflow engine
|
|
35
|
-
* snapshots, so growing this list changes frozen-plan content — extend
|
|
36
|
-
* deliberately.
|
|
37
|
-
*/
|
|
38
|
-
export const COMMON_SPAWN_ENV_PASSTHROUGH = [
|
|
39
|
-
"HOME",
|
|
40
|
-
"PATH",
|
|
41
|
-
"USER",
|
|
42
|
-
"LANG",
|
|
43
|
-
"LC_ALL",
|
|
44
|
-
"TERM",
|
|
45
|
-
"TMPDIR",
|
|
46
|
-
"AKM_EVENT_SOURCE",
|
|
47
|
-
];
|
|
48
|
-
/**
|
|
49
|
-
* The XDG base-directory variables. opencode resolves its config, data, cache
|
|
50
|
-
* and state directories from them, so it must receive them: an akm that runs
|
|
51
|
-
* under a custom `XDG_CONFIG_HOME` otherwise spawns an opencode that reads
|
|
52
|
-
* `$HOME/.config/opencode` and misses the provider config its caller named.
|
|
53
|
-
*
|
|
54
|
-
* Deliberately NOT part of {@link COMMON_SPAWN_ENV_PASSTHROUGH}, which is every
|
|
55
|
-
* harness's baseline, the workflow exec unit's default allowlist (a documented
|
|
56
|
-
* list) and, through profile `envPassthrough`, frozen into workflow plans.
|
|
57
|
-
* codex, gemini and pi keep their own dotdirs under `$HOME`, and handing the
|
|
58
|
-
* names to a shell command would redirect the `git` and `gh` config it reads. A
|
|
59
|
-
* harness that reads them asks for them by name: the opencode profile's list,
|
|
60
|
-
* and the opencode-sdk server's allowlist (`opencodeSdkServerEnvironmentNames`).
|
|
61
|
-
*
|
|
62
|
-
* A name added to a profile's list changes the plans frozen after it (their
|
|
63
|
-
* bytes, so their `plan_hash`); a stored plan keeps the list it was frozen with
|
|
64
|
-
* and still resumes, because nothing gates on that hash. The SDK server's
|
|
65
|
-
* allowlist is not part of a plan, so it takes the names by code.
|
|
66
|
-
*/
|
|
67
|
-
export const XDG_BASE_DIR_ENV_PASSTHROUGH = [
|
|
68
|
-
"XDG_CONFIG_HOME",
|
|
69
|
-
"XDG_DATA_HOME",
|
|
70
|
-
"XDG_CACHE_HOME",
|
|
71
|
-
"XDG_STATE_HOME",
|
|
72
|
-
];
|
|
73
|
-
/**
|
|
74
|
-
* The names an `opencode` process reads beyond the common baseline: its API key
|
|
75
|
-
* (OpenCode Go and Zen read `OPENCODE_API_KEY`), the config file it is pointed
|
|
76
|
-
* at, and the {@link XDG_BASE_DIR_ENV_PASSTHROUGH} directories. ONE list for
|
|
77
|
-
* both ways akm starts opencode: the `opencode` CLI profile's `envPassthrough`
|
|
78
|
-
* and the `opencode-sdk` server's allowlist
|
|
79
|
-
* (`opencodeSdkServerEnvironmentNames`), so the two cannot drift.
|
|
80
|
-
*/
|
|
81
|
-
export const OPENCODE_ENV_PASSTHROUGH = [
|
|
82
|
-
"OPENCODE_API_KEY",
|
|
83
|
-
"OPENCODE_CONFIG",
|
|
84
|
-
...XDG_BASE_DIR_ENV_PASSTHROUGH,
|
|
85
|
-
];
|
|
86
|
-
/**
|
|
87
|
-
* The names Windows itself requires of ANY child, whatever the caller's
|
|
88
|
-
* allowlist says. Applied at build time rather than added to
|
|
89
|
-
* {@link COMMON_SPAWN_ENV_PASSTHROUGH} because profile `envPassthrough` is
|
|
90
|
-
* frozen into workflow engine snapshots: growing the shared list would change
|
|
91
|
-
* the bytes — and so the hashes — of every plan already on disk, to express
|
|
92
|
-
* something that is not a policy choice at all.
|
|
93
|
-
*
|
|
94
|
-
* `SystemRoot`, `SystemDrive` and `WINDIR` are what PROCESS CREATION reads;
|
|
95
|
-
* without them the loader cannot find system DLLs and the spawn fails before
|
|
96
|
-
* the command runs. Without `PATHEXT` Windows never tries `bun.exe`/`bun.cmd`,
|
|
97
|
-
* so a `bin: "bun"` profile is unresolvable, and `COMSPEC` is how `.bat`/`.cmd`
|
|
98
|
-
* targets resolve at all. The rest are the win32 analogues of baseline names
|
|
99
|
-
* the POSIX side already grants — `HOME` (`USERPROFILE`, `HOMEDRIVE`,
|
|
100
|
-
* `HOMEPATH`) and `TMPDIR` (`TEMP`, `TMP`). None is a secret.
|
|
101
|
-
*
|
|
102
|
-
* Config and install roots (`APPDATA`, `LOCALAPPDATA`, `ProgramFiles`, …) are
|
|
103
|
-
* deliberately NOT here: a child can be created and can resolve its command
|
|
104
|
-
* without them, so which allowlist wants them stays a per-caller decision.
|
|
105
|
-
*
|
|
106
|
-
* THE definition of the floor. The workflow exec allowlist
|
|
107
|
-
* (`EXEC_DEFAULT_ENV_PASSTHROUGH`) spreads this constant rather than
|
|
108
|
-
* re-spelling it, because that list is also consumed on POSIX — where
|
|
109
|
-
* {@link spawnEnvNamesFor} appends nothing — and the names still have to be
|
|
110
|
-
* requestable there for a win32 run of the same workflow.
|
|
111
|
-
*/
|
|
112
|
-
export const WIN32_SPAWN_ENV_FLOOR = [
|
|
113
|
-
"SystemRoot",
|
|
114
|
-
"SystemDrive",
|
|
115
|
-
"WINDIR",
|
|
116
|
-
"COMSPEC",
|
|
117
|
-
"PATHEXT",
|
|
118
|
-
"USERPROFILE",
|
|
119
|
-
"HOMEDRIVE",
|
|
120
|
-
"HOMEPATH",
|
|
121
|
-
"TEMP",
|
|
122
|
-
"TMP",
|
|
123
|
-
];
|
|
124
|
-
/**
|
|
125
|
-
* The effective allowlist for `platform`: the caller's names, plus any floor
|
|
126
|
-
* the operating system requires of every child regardless of allowlist.
|
|
127
|
-
* Exported for tests, which must be able to ask for a platform they are not
|
|
128
|
-
* running on.
|
|
129
|
-
*/
|
|
130
|
-
export function spawnEnvNamesFor(names, platform = process.platform) {
|
|
131
|
-
const effective = [...names];
|
|
132
|
-
if (platform !== "win32")
|
|
133
|
-
return effective;
|
|
134
|
-
// Deduped by EXACT spelling, never case-folded: {@link collectAllowlistedEnv}
|
|
135
|
-
// looks each surviving name up with exactly this case, and a `source` that is
|
|
136
|
-
// a plain object — the agent spawn's `envSource` seam — does not case-fold.
|
|
137
|
-
// Suppressing `SystemRoot` because the caller happened to write `SYSTEMROOT`
|
|
138
|
-
// would therefore drop the loader-critical variable the floor exists to
|
|
139
|
-
// guarantee. Keeping both spellings is harmless: the win32 environment is
|
|
140
|
-
// itself case-insensitive, so they resolve to the same value.
|
|
141
|
-
const present = new Set(effective);
|
|
142
|
-
for (const name of WIN32_SPAWN_ENV_FLOOR) {
|
|
143
|
-
if (!present.has(name))
|
|
144
|
-
effective.push(name);
|
|
145
|
-
}
|
|
146
|
-
return effective;
|
|
147
|
-
}
|
|
148
|
-
/**
|
|
149
|
-
* Build a child environment from an allowlist: start EMPTY and copy through
|
|
150
|
-
* exactly the named variables that exist in `source`. Names absent from the
|
|
151
|
-
* source are simply absent from the child (never an empty string, which many
|
|
152
|
-
* tools treat as "set but blank").
|
|
153
|
-
*
|
|
154
|
-
* `PATH`, when it comes through, is supplemented for scheduler contexts — see
|
|
155
|
-
* {@link supplementPathForSchedulerContext}. That happens here rather than in
|
|
156
|
-
* each caller so a child spawned from cron/launchd/Task Scheduler can find the
|
|
157
|
-
* user's toolchain no matter which spawn path reached it. On win32 the names
|
|
158
|
-
* in {@link WIN32_SPAWN_ENV_FLOOR} come through too, for the same reason: the
|
|
159
|
-
* spawn cannot succeed without them, whichever caller built the list.
|
|
160
|
-
*/
|
|
161
|
-
export function collectAllowlistedEnv(names, source = process.env) {
|
|
162
|
-
const env = {};
|
|
163
|
-
for (const name of spawnEnvNamesFor(names)) {
|
|
164
|
-
const value = source[name];
|
|
165
|
-
if (value !== undefined)
|
|
166
|
-
env[name] = value;
|
|
167
|
-
}
|
|
168
|
-
if (env.PATH !== undefined) {
|
|
169
|
-
env.PATH = supplementPathForSchedulerContext(env.PATH);
|
|
170
|
-
}
|
|
171
|
-
return env;
|
|
172
|
-
}
|
|
173
|
-
/**
|
|
174
|
-
* Answers already computed by {@link supplementPathForSchedulerContext}, keyed
|
|
175
|
-
* by the input PATH and the home directory it was computed against.
|
|
176
|
-
*
|
|
177
|
-
* Correctness envelope: the answer is a pure function of those two, the
|
|
178
|
-
* platform, and which candidate directories exist on disk. The platform cannot
|
|
179
|
-
* change under a running process, and the other two are in the key — so the one
|
|
180
|
-
* thing the memo assumes is that a candidate directory does not APPEAR while
|
|
181
|
-
* akm runs. Answering the rest of a run the way its start was answered is what
|
|
182
|
-
* a shell's own command-path caching already does, and the cost of not
|
|
183
|
-
* memoizing is paid on every child-env build: two PATH splits and up to seven
|
|
184
|
-
* SYNCHRONOUS `existsSync` probes, on the event loop a 10 000-unit fan-out
|
|
185
|
-
* shares with every other in-flight unit.
|
|
186
|
-
*
|
|
187
|
-
* Bounded so a caller that somehow varies its PATH cannot grow it without
|
|
188
|
-
* limit; a spawn path only ever sees a handful of distinct PATH strings, so
|
|
189
|
-
* the reset is effectively unreachable in practice.
|
|
190
|
-
*/
|
|
191
|
-
const supplementedPaths = new Map();
|
|
192
|
-
const SUPPLEMENTED_PATH_MEMO_MAX = 64;
|
|
193
|
-
/**
|
|
194
|
-
* Supplement `existingPath` with well-known user binary directories when
|
|
195
|
-
* running in a scheduler context (cron/launchd) where PATH is stripped.
|
|
196
|
-
*
|
|
197
|
-
* Detection heuristic: if the current PATH does not contain the user's home
|
|
198
|
-
* directory, we are likely in a stripped scheduler env. In an interactive
|
|
199
|
-
* shell the user's home almost always appears (e.g. ~/.bun/bin, ~/.cargo/bin).
|
|
200
|
-
*
|
|
201
|
-
* Only directories that actually exist on disk are prepended, and only if
|
|
202
|
-
* they are not already present, so interactive-shell PATH ordering is never
|
|
203
|
-
* disturbed.
|
|
204
|
-
*
|
|
205
|
-
* Memoized per input PATH — see {@link supplementedPaths} for what that
|
|
206
|
-
* assumes.
|
|
207
|
-
*/
|
|
208
|
-
export function supplementPathForSchedulerContext(existingPath) {
|
|
209
|
-
const home = os.homedir();
|
|
210
|
-
// NUL-joined so no pair of (home, PATH) can collide onto one key: no path
|
|
211
|
-
// component can contain a NUL.
|
|
212
|
-
const key = `${home}\u0000${existingPath}`;
|
|
213
|
-
const memoized = supplementedPaths.get(key);
|
|
214
|
-
if (memoized !== undefined)
|
|
215
|
-
return memoized;
|
|
216
|
-
const supplemented = computeSupplementedPath(existingPath, home);
|
|
217
|
-
if (supplementedPaths.size >= SUPPLEMENTED_PATH_MEMO_MAX)
|
|
218
|
-
supplementedPaths.clear();
|
|
219
|
-
supplementedPaths.set(key, supplemented);
|
|
220
|
-
return supplemented;
|
|
221
|
-
}
|
|
222
|
-
function computeSupplementedPath(existingPath, home) {
|
|
223
|
-
// A home of `/` (system crontab, launchd, service accounts) or of `""`
|
|
224
|
-
// prefixes EVERY entry, so a prefix test would read the most stripped
|
|
225
|
-
// environments there are as interactive and skip the repair they exist for.
|
|
226
|
-
const comparableHome = home === "" || home === path.sep ? undefined : home;
|
|
227
|
-
// If PATH already contains the home directory, we are in an interactive
|
|
228
|
-
// shell — skip supplementation entirely. Compared on a path boundary: a
|
|
229
|
-
// sibling home (`/home/alice` next to `/home/al`) is not this user's.
|
|
230
|
-
const isUnderHome = (dir) => comparableHome !== undefined && (dir === comparableHome || dir.startsWith(comparableHome + path.sep));
|
|
231
|
-
if (existingPath.split(path.delimiter).some(isUnderHome)) {
|
|
232
|
-
return existingPath;
|
|
233
|
-
}
|
|
234
|
-
const candidates = pathCandidatesForCurrentPlatform(home);
|
|
235
|
-
const existing = new Set(existingPath.split(path.delimiter).filter(Boolean));
|
|
236
|
-
const toAdd = candidates.filter((d) => !existing.has(d) && fs.existsSync(d));
|
|
237
|
-
if (toAdd.length === 0)
|
|
238
|
-
return existingPath;
|
|
239
|
-
return [...toAdd, existingPath].filter(Boolean).join(path.delimiter);
|
|
240
|
-
}
|
|
241
|
-
function pathCandidatesForCurrentPlatform(home) {
|
|
242
|
-
if (process.platform === "win32") {
|
|
243
|
-
// Windows: Bun + Cargo + Scoop + Chocolatey + system tools. Order favors
|
|
244
|
-
// user-local installs over machine-global so the user's chosen toolchain
|
|
245
|
-
// wins. These paths are commonly stripped from Task Scheduler / service
|
|
246
|
-
// environments, mirroring the cron/launchd problem on POSIX.
|
|
247
|
-
const localAppData = process.env.LOCALAPPDATA ?? path.join(home, "AppData", "Local");
|
|
248
|
-
const userProfile = process.env.USERPROFILE ?? home;
|
|
249
|
-
const programFiles = process.env.ProgramFiles ?? "C:\\Program Files";
|
|
250
|
-
return [
|
|
251
|
-
path.join(userProfile, ".bun", "bin"),
|
|
252
|
-
path.join(localAppData, "Programs", "bun"),
|
|
253
|
-
path.join(userProfile, ".cargo", "bin"),
|
|
254
|
-
path.join(localAppData, "Programs", "Git", "cmd"),
|
|
255
|
-
path.join(userProfile, "scoop", "shims"),
|
|
256
|
-
path.join(programFiles, "Git", "cmd"),
|
|
257
|
-
"C:\\ProgramData\\chocolatey\\bin",
|
|
258
|
-
];
|
|
259
|
-
}
|
|
260
|
-
return [
|
|
261
|
-
path.join(home, ".bun", "bin"),
|
|
262
|
-
path.join(home, ".cargo", "bin"),
|
|
263
|
-
path.join(home, ".local", "bin"),
|
|
264
|
-
"/opt/homebrew/bin",
|
|
265
|
-
"/opt/homebrew/sbin",
|
|
266
|
-
"/usr/local/bin",
|
|
267
|
-
];
|
|
268
|
-
}
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
-
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
-
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
|
-
import fs from "node:fs";
|
|
5
|
-
import path from "node:path";
|
|
6
|
-
import { UsageError } from "../core/errors.js";
|
|
7
|
-
export function captureFrozenDirectoryIdentity(rootInput, relativeCwd) {
|
|
8
|
-
const requestedRoot = path.resolve(rootInput);
|
|
9
|
-
const requestedCwd = path.resolve(requestedRoot, relativeCwd ?? ".");
|
|
10
|
-
requireContained(requestedRoot, requestedCwd);
|
|
11
|
-
const realRoot = fs.realpathSync(requestedRoot);
|
|
12
|
-
const realCwd = fs.realpathSync(requestedCwd);
|
|
13
|
-
requireContained(realRoot, realCwd);
|
|
14
|
-
const rootStat = fs.statSync(realRoot, { bigint: true });
|
|
15
|
-
const cwdStat = fs.statSync(realCwd, { bigint: true });
|
|
16
|
-
if (!rootStat.isDirectory() || !cwdStat.isDirectory()) {
|
|
17
|
-
throw new UsageError("Execution root and cwd must both be directories.", "INVALID_FLAG_VALUE");
|
|
18
|
-
}
|
|
19
|
-
return Object.freeze({
|
|
20
|
-
requestedRoot,
|
|
21
|
-
realRoot,
|
|
22
|
-
rootDevice: rootStat.dev.toString(),
|
|
23
|
-
rootInode: rootStat.ino.toString(),
|
|
24
|
-
requestedCwd,
|
|
25
|
-
realCwd,
|
|
26
|
-
cwdDevice: cwdStat.dev.toString(),
|
|
27
|
-
cwdInode: cwdStat.ino.toString(),
|
|
28
|
-
});
|
|
29
|
-
}
|
|
30
|
-
/**
|
|
31
|
-
* Re-verify, immediately before spawn, that a frozen cwd still resolves
|
|
32
|
-
* inside its execution root — path containment and resolved-path identity,
|
|
33
|
-
* NOT device/inode identity. Unlike the removed assertFrozenDirectoryIdentity,
|
|
34
|
-
* this does not compare device/inode numbers against the frozen snapshot: a
|
|
35
|
-
* remount, an rsync, or a container rebuild that leaves the same real
|
|
36
|
-
* content at the same real PATH must not abort a dispatch. What still
|
|
37
|
-
* throws is anything that changes the resolved real PATH itself — a
|
|
38
|
-
* symlink swap, an ancestor swap, a file replacing the directory, or the
|
|
39
|
-
* root itself being replaced by a symlink elsewhere (root-vs-cwd
|
|
40
|
-
* containment alone can't catch that last one, since both resolve together
|
|
41
|
-
* under the new root; comparing the root's own resolved path to its frozen
|
|
42
|
-
* value catches it).
|
|
43
|
-
*/
|
|
44
|
-
export function assertFrozenDirectoryContained(identity) {
|
|
45
|
-
let realRoot;
|
|
46
|
-
let realCwd;
|
|
47
|
-
try {
|
|
48
|
-
realRoot = fs.realpathSync(identity.requestedRoot);
|
|
49
|
-
realCwd = fs.realpathSync(identity.requestedCwd);
|
|
50
|
-
}
|
|
51
|
-
catch {
|
|
52
|
-
throw changed(identity.requestedCwd);
|
|
53
|
-
}
|
|
54
|
-
if (realRoot !== identity.realRoot)
|
|
55
|
-
throw changed(identity.requestedCwd);
|
|
56
|
-
const relative = path.relative(realRoot, realCwd);
|
|
57
|
-
if (relative.startsWith("..") || path.isAbsolute(relative)) {
|
|
58
|
-
throw changed(identity.requestedCwd);
|
|
59
|
-
}
|
|
60
|
-
let cwdStat;
|
|
61
|
-
try {
|
|
62
|
-
cwdStat = fs.statSync(realCwd, { bigint: true });
|
|
63
|
-
}
|
|
64
|
-
catch {
|
|
65
|
-
throw changed(identity.requestedCwd);
|
|
66
|
-
}
|
|
67
|
-
if (!cwdStat.isDirectory())
|
|
68
|
-
throw changed(identity.requestedCwd);
|
|
69
|
-
}
|
|
70
|
-
function changed(cwd) {
|
|
71
|
-
return new UsageError(`Frozen execution cwd ${cwd} changed and no longer resolves inside its root.`, "PATH_ESCAPE_VIOLATION");
|
|
72
|
-
}
|
|
73
|
-
function requireContained(root, candidate) {
|
|
74
|
-
const relative = path.relative(root, candidate);
|
|
75
|
-
if (relative.startsWith("..") || path.isAbsolute(relative)) {
|
|
76
|
-
throw new UsageError(`${candidate} escapes its execution root.`, "PATH_ESCAPE_VIOLATION");
|
|
77
|
-
}
|
|
78
|
-
}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
-
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
-
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
|
-
/** Models reaching a harness have already crossed the single model-map boundary. */
|
|
5
|
-
export function resolveDispatchModel(request, _profile, _platform) {
|
|
6
|
-
return request.model;
|
|
7
|
-
}
|
|
8
|
-
/**
|
|
9
|
-
* The model an engine's own `args` select, as `--model X` or `--model=X` (the
|
|
10
|
-
* last one wins), for a builder that writes its own argv in place of those args.
|
|
11
|
-
*/
|
|
12
|
-
export function modelFromArgs(args) {
|
|
13
|
-
let model;
|
|
14
|
-
for (let index = 0; index < args.length; index += 1) {
|
|
15
|
-
const arg = args[index];
|
|
16
|
-
if (arg === "--model")
|
|
17
|
-
model = args[index + 1];
|
|
18
|
-
else if (arg?.startsWith("--model="))
|
|
19
|
-
model = arg.slice("--model=".length);
|
|
20
|
-
}
|
|
21
|
-
return model;
|
|
22
|
-
}
|
|
23
|
-
/**
|
|
24
|
-
* Normalize a toolPolicy value to a comma-separated string suitable for a
|
|
25
|
-
* CLI flag. Structured policy objects are JSON-serialized.
|
|
26
|
-
*/
|
|
27
|
-
export function normalizeTools(tools) {
|
|
28
|
-
if (typeof tools === "string")
|
|
29
|
-
return tools;
|
|
30
|
-
if (Array.isArray(tools))
|
|
31
|
-
return tools.join(",");
|
|
32
|
-
return JSON.stringify(tools);
|
|
33
|
-
}
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
-
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
-
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
|
-
/**
|
|
5
|
-
* Agent command builder strategy (v1 spec §12.2).
|
|
6
|
-
*
|
|
7
|
-
* Each supported agent CLI platform has its own `AgentCommandBuilder` that
|
|
8
|
-
* translates a platform-agnostic `AgentDispatchRequest` into the exact argv
|
|
9
|
-
* the CLI expects. This keeps all per-platform arg differences out of the
|
|
10
|
-
* spawn wrapper and profiles.
|
|
11
|
-
*
|
|
12
|
-
* Adding a new platform: implement `AgentCommandBuilder`, add to
|
|
13
|
-
* `BUILTIN_BUILDERS`. Nothing else changes.
|
|
14
|
-
*/
|
|
15
|
-
import { ConfigError } from "../../core/errors.js";
|
|
16
|
-
import { HARNESS_REGISTRY } from "../harnesses/index.js";
|
|
17
|
-
// ── Registry ──────────────────────────────────────────────────────────────────
|
|
18
|
-
/**
|
|
19
|
-
* DERIVED from `HARNESS_REGISTRY` (P0.5 registry-drift fix): each harness that
|
|
20
|
-
* owns an `agentBuilder` is registered under its canonical id. Named engines
|
|
21
|
-
* are schema-validated to canonical harness ids before reaching this boundary.
|
|
22
|
-
*/
|
|
23
|
-
const BUILTIN_BUILDERS = (() => {
|
|
24
|
-
const registry = {};
|
|
25
|
-
for (const harness of HARNESS_REGISTRY) {
|
|
26
|
-
if (!harness.agentBuilder)
|
|
27
|
-
continue;
|
|
28
|
-
registry[harness.id] = harness.agentBuilder;
|
|
29
|
-
}
|
|
30
|
-
return Object.freeze(registry);
|
|
31
|
-
})();
|
|
32
|
-
/**
|
|
33
|
-
* Return the builder for the given platform name.
|
|
34
|
-
*
|
|
35
|
-
* Unknown platforms are rejected: there is no safe generic CLI flag shape.
|
|
36
|
-
* Custom builders injected by tests can be passed as `registry`.
|
|
37
|
-
*/
|
|
38
|
-
export function getCommandBuilder(platform, registry = BUILTIN_BUILDERS) {
|
|
39
|
-
const found = registry[platform];
|
|
40
|
-
if (found)
|
|
41
|
-
return found;
|
|
42
|
-
throw new ConfigError(`Agent platform "${platform}" has no registered command builder.`, "INVALID_CONFIG_FILE", "Select a canonical agent platform in engines.<name>.platform.");
|
|
43
|
-
}
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
-
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
-
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
|
-
import { defaultWhich } from "./detect.js";
|
|
5
|
-
import { OPENCODE_SDK_SERVER_BIN } from "./profiles.js";
|
|
6
|
-
/** Engine name used for the synthesized entry; matches the platform id. */
|
|
7
|
-
export const FALLBACK_ENGINE_NAME = "opencode-sdk";
|
|
8
|
-
/** Announcement text, surfaced once per run/dispatch. */
|
|
9
|
-
export const FALLBACK_ANNOUNCEMENT = `No engine is configured; falling back to \`${FALLBACK_ENGINE_NAME}\` via the ` +
|
|
10
|
-
`\`${OPENCODE_SDK_SERVER_BIN}\` binary on PATH — provider, model, and auth come ` +
|
|
11
|
-
"from opencode's own configuration. " +
|
|
12
|
-
"Run `akm setup`, or set `defaults.engine`, to choose explicitly.";
|
|
13
|
-
/** Failure suffix for every surface that needs an engine and found none. */
|
|
14
|
-
export const NO_ENGINE_MESSAGE_SUFFIX = `has no selected engine, and no usable \`${OPENCODE_SDK_SERVER_BIN}\` binary was found to fall back to.`;
|
|
15
|
-
/** Guidance used when the fallback itself is unavailable. */
|
|
16
|
-
export const NO_ENGINE_REMEDY = "Run `akm setup` to detect an installed agent, or set one explicitly: " +
|
|
17
|
-
'`akm config set engines.claude \'{"kind":"agent","platform":"claude"}\'` ' +
|
|
18
|
-
"then `akm config set defaults.engine claude`. " +
|
|
19
|
-
`Installing the \`${OPENCODE_SDK_SERVER_BIN}\` binary also works ` +
|
|
20
|
-
"(`npm i -g opencode-ai`) — akm falls back to it automatically.";
|
|
21
|
-
/**
|
|
22
|
-
* The fallback engine when its `opencode` binary is present: an
|
|
23
|
-
* operator-configured `opencode-sdk` entry (whose pinned `bin`, possibly
|
|
24
|
-
* outside PATH, is what gets probed), else a bare opencode-sdk agent engine.
|
|
25
|
-
*/
|
|
26
|
-
export function fallbackEngineConfig(config, whichFn = defaultWhich) {
|
|
27
|
-
const existing = config.engines?.[FALLBACK_ENGINE_NAME];
|
|
28
|
-
const bin = existing?.kind === "agent" ? existing.bin : undefined;
|
|
29
|
-
if (!whichFn(bin ?? OPENCODE_SDK_SERVER_BIN))
|
|
30
|
-
return undefined;
|
|
31
|
-
return existing ?? { kind: "agent", platform: "opencode-sdk" };
|
|
32
|
-
}
|
|
33
|
-
/**
|
|
34
|
-
* For diagnostics that report the effective engine: a config whose
|
|
35
|
-
* `defaults.engine` resolves, with the implicit `opencode-sdk` fallback when it
|
|
36
|
-
* does not and an opencode binary is present. Never mutates `config`; returns
|
|
37
|
-
* the same object when no fallback is needed.
|
|
38
|
-
*/
|
|
39
|
-
export function withEngineFallback(config, whichFn = defaultWhich) {
|
|
40
|
-
if (config.defaults?.engine)
|
|
41
|
-
return { config };
|
|
42
|
-
const engine = fallbackEngineConfig(config, whichFn);
|
|
43
|
-
if (!engine)
|
|
44
|
-
return { config };
|
|
45
|
-
return {
|
|
46
|
-
config: {
|
|
47
|
-
...config,
|
|
48
|
-
engines: { ...(config.engines ?? {}), [FALLBACK_ENGINE_NAME]: engine },
|
|
49
|
-
defaults: { ...(config.defaults ?? {}), engine: FALLBACK_ENGINE_NAME },
|
|
50
|
-
},
|
|
51
|
-
fallbackEngineName: FALLBACK_ENGINE_NAME,
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
/** The announcement, but only when the fallback candidate is the engine that actually won selection. */
|
|
55
|
-
export function fallbackAnnouncement(fallbackEngineName, selectedEngineName) {
|
|
56
|
-
if (!fallbackEngineName || selectedEngineName !== fallbackEngineName)
|
|
57
|
-
return undefined;
|
|
58
|
-
return FALLBACK_ANNOUNCEMENT;
|
|
59
|
-
}
|