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
|
@@ -0,0 +1,114 @@
|
|
|
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
|
+
* Where the engines of improve strategies, index passes and workflow gates went: the
|
|
6
|
+
* `connection` / `harness` they name now, or the process they moved to. See `convert-engines.ts`.
|
|
7
|
+
*/
|
|
8
|
+
import { isDeepStrictEqual } from "node:util";
|
|
9
|
+
import { isRecord } from "../common.js";
|
|
10
|
+
import { objectAt, str } from "./convert-engines-shared.js";
|
|
11
|
+
/** What a strategy's process, quality gate or judgment once said about where it runs and how. */
|
|
12
|
+
const EXECUTION_KEYS = ["connection", "harness", "model", "llm", "timeoutMs"];
|
|
13
|
+
/** Rewrite the `engine` of `holder` as the `connection` or `harness` it names now, unless the holder already says. */
|
|
14
|
+
export function retargeter(conversion, target) {
|
|
15
|
+
return (holder, where, harnessOk = true) => {
|
|
16
|
+
if (!isRecord(holder) || !("engine" in holder))
|
|
17
|
+
return;
|
|
18
|
+
conversion.changed = true;
|
|
19
|
+
const engine = str(holder.engine);
|
|
20
|
+
delete holder.engine;
|
|
21
|
+
const found = engine === undefined ? undefined : target(engine);
|
|
22
|
+
if (found === undefined)
|
|
23
|
+
conversion.notes.push(`${where}: engine ${JSON.stringify(engine)} is not carried over.`);
|
|
24
|
+
else if ("harness" in found && !harnessOk)
|
|
25
|
+
conversion.notes.push(`${where}: index passes run on connections only; engine "${engine}" is not carried over.`);
|
|
26
|
+
else
|
|
27
|
+
for (const [key, value] of Object.entries(found))
|
|
28
|
+
holder[key] ??= value;
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* A strategy's `engine`, `model`, `llm` and `timeoutMs` are dropped (it says which processes run, not where), and
|
|
33
|
+
* where its processes, quality gates and triage judgment said a process runs moves to `improve.processes.<name>` /
|
|
34
|
+
* `improve.qualityGate`; the first strategy to say it wins.
|
|
35
|
+
*/
|
|
36
|
+
export function moveStrategyExecution(improve, conversion, retarget) {
|
|
37
|
+
if (!isRecord(improve.strategies))
|
|
38
|
+
return;
|
|
39
|
+
const hoist = (holder, from, place, destination) => {
|
|
40
|
+
if (!isRecord(holder))
|
|
41
|
+
return;
|
|
42
|
+
retarget(holder, `${from}.engine`);
|
|
43
|
+
const found = EXECUTION_KEYS.filter((key) => key in holder);
|
|
44
|
+
if (found.length === 0)
|
|
45
|
+
return;
|
|
46
|
+
conversion.changed = true;
|
|
47
|
+
const into = destination();
|
|
48
|
+
for (const key of found) {
|
|
49
|
+
const value = holder[key];
|
|
50
|
+
delete holder[key];
|
|
51
|
+
const names = key === "connection" || key === "harness";
|
|
52
|
+
const taken = names ? "connection" in into || "harness" in into : key in into;
|
|
53
|
+
if (!taken)
|
|
54
|
+
into[key] = value;
|
|
55
|
+
else if (!isDeepStrictEqual(into[key], value))
|
|
56
|
+
conversion.notes.push(`${from}.${key}: ${place} already says where this runs; the first choice is kept.`);
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
const processEntry = (name) => () => objectAt(objectAt(improve, "processes"), name);
|
|
60
|
+
for (const [strategyName, strategy] of Object.entries(improve.strategies)) {
|
|
61
|
+
if (!isRecord(strategy))
|
|
62
|
+
continue;
|
|
63
|
+
for (const key of ["engine", "model", "llm", "timeoutMs"]) {
|
|
64
|
+
if (key in strategy) {
|
|
65
|
+
delete strategy[key];
|
|
66
|
+
conversion.changed = true;
|
|
67
|
+
conversion.notes.push(`improve.strategies.${strategyName}.${key}: a strategy says which processes run, not where; it is dropped.`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
for (const [processName, process] of Object.entries(isRecord(strategy.processes) ? strategy.processes : {})) {
|
|
71
|
+
const where = `improve.strategies.${strategyName}.processes.${processName}`;
|
|
72
|
+
if (!isRecord(process))
|
|
73
|
+
continue;
|
|
74
|
+
// Triage's judgment is the model call; in 0.9 its setting was the nearer one, so it is hoisted first and wins.
|
|
75
|
+
hoist(process.judgment, `${where}.judgment`, "improve.processes.triage", processEntry("triage"));
|
|
76
|
+
hoist(process, where, `improve.processes.${processName}`, processEntry(processName));
|
|
77
|
+
hoist(process.qualityGate, `${where}.qualityGate`, "improve.qualityGate", () => objectAt(improve, "qualityGate"));
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/** `defaults.improveStrategy`: `improve.strategy`. */
|
|
82
|
+
export function improveStrategyDefault(out, defaults, improve) {
|
|
83
|
+
if (defaults.improveStrategy === undefined)
|
|
84
|
+
return;
|
|
85
|
+
out.improve = { ...(isRecord(improve) ? improve : {}) };
|
|
86
|
+
out.improve.strategy ??= defaults.improveStrategy;
|
|
87
|
+
}
|
|
88
|
+
/** `workflow.judgeEngine`: a gate's judge is the default connection or harness now. */
|
|
89
|
+
export function dropJudgeEngine(out, conversion) {
|
|
90
|
+
const workflow = out.workflow;
|
|
91
|
+
if (!isRecord(workflow) || !("judgeEngine" in workflow))
|
|
92
|
+
return;
|
|
93
|
+
delete workflow.judgeEngine;
|
|
94
|
+
conversion.changed = true;
|
|
95
|
+
conversion.notes.push("workflow.judgeEngine: a gate's judge is the default connection or harness now; it is dropped.");
|
|
96
|
+
}
|
|
97
|
+
/** `index.defaults.*` and `index.<pass>.engine`: `index.*` and `connection`; a harness cannot run an index pass. */
|
|
98
|
+
export function convertIndexEngines(out, conversion, retarget) {
|
|
99
|
+
const index = out.index;
|
|
100
|
+
if (!isRecord(index))
|
|
101
|
+
return;
|
|
102
|
+
const indexDefaults = index.defaults;
|
|
103
|
+
delete index.defaults;
|
|
104
|
+
if (isRecord(indexDefaults)) {
|
|
105
|
+
conversion.changed = true;
|
|
106
|
+
retarget(indexDefaults, "index.defaults.engine", false);
|
|
107
|
+
for (const key of ["connection", "model", "timeoutMs", "llm"])
|
|
108
|
+
if (indexDefaults[key] !== undefined)
|
|
109
|
+
index[key] ??= indexDefaults[key];
|
|
110
|
+
}
|
|
111
|
+
for (const [pass, value] of Object.entries(index))
|
|
112
|
+
if (pass !== "connection")
|
|
113
|
+
retarget(value, `index.${pass}.engine`, false);
|
|
114
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
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
|
+
* What the pieces of the engines conversion share: the shapes they pass around and the
|
|
6
|
+
* few helpers more than one of them needs. See `convert-engines.ts`.
|
|
7
|
+
*/
|
|
8
|
+
import { isRecord } from "../common.js";
|
|
9
|
+
import { normalizeExtraParamKey } from "../extra-params.js";
|
|
10
|
+
import { inferenceWireFields } from "../llm-inference.js";
|
|
11
|
+
export const str = (value) => (typeof value === "string" && value ? value : undefined);
|
|
12
|
+
export const asDict = (value) => (isRecord(value) ? value : {});
|
|
13
|
+
/**
|
|
14
|
+
* The request fields an old engine's (or a `models.json` entry's) inference
|
|
15
|
+
* becomes. The first-class settings win over `extraParams`: an `extraParams` key
|
|
16
|
+
* that names the same field as one of them (`temperature`, `maxTokens`/`max_tokens`,
|
|
17
|
+
* `enableThinking`, `reasoningEffort`, `chat_template_kwargs`) is dropped, with a
|
|
18
|
+
* note that names the key and not its value.
|
|
19
|
+
*/
|
|
20
|
+
export function wireFieldsOf(inference, where, notes) {
|
|
21
|
+
const { extraParams, ...settings } = inference;
|
|
22
|
+
const firstClass = inferenceWireFields(settings);
|
|
23
|
+
const taken = new Set(Object.keys(firstClass).map(normalizeExtraParamKey));
|
|
24
|
+
const extras = {};
|
|
25
|
+
for (const [key, value] of Object.entries(isRecord(extraParams) ? extraParams : {})) {
|
|
26
|
+
if (taken.has(normalizeExtraParamKey(key))) {
|
|
27
|
+
notes.push(`${where}: extraParams.${key} is dropped, because the setting it shadows takes precedence.`);
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
extras[key] = value;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return { ...extras, ...firstClass };
|
|
34
|
+
}
|
|
35
|
+
/** `holder[key]` as an object, made on `holder` when it is not one yet. */
|
|
36
|
+
export function objectAt(holder, key) {
|
|
37
|
+
if (!isRecord(holder[key]))
|
|
38
|
+
holder[key] = {};
|
|
39
|
+
return holder[key];
|
|
40
|
+
}
|
|
@@ -0,0 +1,300 @@
|
|
|
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 pre-0.10 `engines` / `defaults` config read as `connections` / `harnesses`.
|
|
6
|
+
*
|
|
7
|
+
* One pure function, two call sites: the loader runs it in memory on every read
|
|
8
|
+
* (`runConfigFilePipeline`) and `akm migrate apply` writes its result back.
|
|
9
|
+
* Whatever it cannot carry over is named in `notes` and dropped. One step per row of
|
|
10
|
+
* the migration table in `docs/reference/configuration.md`; `models.json` and the
|
|
11
|
+
* references in strategies, index passes and gates are folded in by their own modules.
|
|
12
|
+
*/
|
|
13
|
+
import { isRecord } from "../common.js";
|
|
14
|
+
import { convertIndexEngines, dropJudgeEngine, improveStrategyDefault, moveStrategyExecution, retargeter, } from "./convert-engine-references.js";
|
|
15
|
+
import { asDict, str, wireFieldsOf, } from "./convert-engines-shared.js";
|
|
16
|
+
import { foldEngineModels, foldModelsOverlay } from "./convert-models-overlay.js";
|
|
17
|
+
import { deepMergeConfig } from "./deep-merge.js";
|
|
18
|
+
import { isEnvReference } from "./schema/primitives.js";
|
|
19
|
+
const LLM_ENGINE_KEYS = new Set([
|
|
20
|
+
"kind",
|
|
21
|
+
"provider",
|
|
22
|
+
"endpoint",
|
|
23
|
+
"model",
|
|
24
|
+
"apiKey",
|
|
25
|
+
"apiKeyFile",
|
|
26
|
+
"temperature",
|
|
27
|
+
"maxTokens",
|
|
28
|
+
"timeoutMs",
|
|
29
|
+
"concurrency",
|
|
30
|
+
"supportsJsonSchema",
|
|
31
|
+
"extraParams",
|
|
32
|
+
"contextLength",
|
|
33
|
+
"enableThinking",
|
|
34
|
+
"reasoningEffort",
|
|
35
|
+
]);
|
|
36
|
+
const AGENT_ENGINE_KEYS = new Set([
|
|
37
|
+
"kind",
|
|
38
|
+
"platform",
|
|
39
|
+
"bin",
|
|
40
|
+
"args",
|
|
41
|
+
"workspace",
|
|
42
|
+
"model",
|
|
43
|
+
"agent",
|
|
44
|
+
"timeoutMs",
|
|
45
|
+
"llmEngine",
|
|
46
|
+
]);
|
|
47
|
+
const CARRIED = ["endpoint", "contextLength", "timeoutMs", "concurrency"];
|
|
48
|
+
/**
|
|
49
|
+
* The environment variables an engine's key used to be read from without being
|
|
50
|
+
* named in config: `AKM_ENGINE_<NAME>_API_KEY` for any engine, and
|
|
51
|
+
* `AKM_LLM_API_KEY` for the engine `defaults.llmEngine` named.
|
|
52
|
+
*/
|
|
53
|
+
function implicitKeyVariables(name, defaults) {
|
|
54
|
+
const own = `AKM_ENGINE_${name.toUpperCase().replaceAll("-", "_")}_API_KEY`;
|
|
55
|
+
return name === str(defaults.llmEngine) ? [own, "AKM_LLM_API_KEY"] : [own];
|
|
56
|
+
}
|
|
57
|
+
// ── engines → connections / harnesses ────────────────────────────────────────
|
|
58
|
+
/** `engines.<name>` with `kind: "agent"` and `platform: "opencode-sdk"`: akm's own runtime has no entry of its own. */
|
|
59
|
+
function runtimeEngine(name, engine, converted, conversion) {
|
|
60
|
+
converted.runtimes.set(name, str(engine.llmEngine));
|
|
61
|
+
conversion.notes.push(`engines.${name}: opencode-sdk is akm's own runtime now, with no entry of its own; its model, timeout and workspace are dropped.`);
|
|
62
|
+
}
|
|
63
|
+
/** `engines.<name>` with `kind: "agent"`, any other platform: `harnesses.<name>`. */
|
|
64
|
+
function agentEngineToHarness(name, engine, converted) {
|
|
65
|
+
const harness = { platform: engine.platform };
|
|
66
|
+
for (const key of ["bin", "args", "workspace", "agent", "timeoutMs"])
|
|
67
|
+
if (engine[key] !== undefined)
|
|
68
|
+
harness[key] = engine[key];
|
|
69
|
+
const model = str(engine.model);
|
|
70
|
+
if (model !== undefined)
|
|
71
|
+
converted.ownModelOf.push({ kind: "harnesses", engine: name, model });
|
|
72
|
+
converted.harnesses[name] = harness;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* The key of an engine, on its connection: a `$VAR` is kept; a file, a literal or a secret reference cannot be
|
|
76
|
+
* (the key belongs in `credentials.json`); and with none written, the variable it used to be read from implicitly,
|
|
77
|
+
* when that one is set. When none is, the connection has no key, and a note says which variables 0.9 read.
|
|
78
|
+
*/
|
|
79
|
+
function carryEngineKey(name, engine, connection, defaults, env, converted, conversion) {
|
|
80
|
+
const apiKey = str(engine.apiKey);
|
|
81
|
+
if (apiKey !== undefined && isEnvReference(apiKey))
|
|
82
|
+
connection.apiKey = apiKey;
|
|
83
|
+
else if (apiKey !== undefined || engine.apiKeyFile !== undefined) {
|
|
84
|
+
converted.keyHolders.push({ engine: name, field: engine.apiKeyFile !== undefined ? "apiKeyFile" : "apiKey" });
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
const variables = implicitKeyVariables(name, defaults);
|
|
88
|
+
const variable = variables.find((candidate) => env?.[candidate]?.trim());
|
|
89
|
+
if (variable !== undefined)
|
|
90
|
+
connection.apiKey = `$${variable}`;
|
|
91
|
+
else {
|
|
92
|
+
conversion.notes.push(`engines.${name}: it names no key, and ${variables.join(" or ")}, which it used to read when set, is not set here, so the connection has no key. If the endpoint needs one, set the variable and run \`akm setup --api-key-env <VARIABLE>\`, or store the key with \`akm setup\`.`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
/** `engines.<name>` with `kind: "llm"`: `connections.<name>`. */
|
|
97
|
+
function llmEngineToConnection(name, engine, defaults, env, converted, conversion) {
|
|
98
|
+
const connection = {};
|
|
99
|
+
for (const key of CARRIED)
|
|
100
|
+
if (engine[key] !== undefined)
|
|
101
|
+
connection[key] = engine[key];
|
|
102
|
+
carryEngineKey(name, engine, connection, defaults, env, converted, conversion);
|
|
103
|
+
const model = str(engine.model);
|
|
104
|
+
if (model !== undefined)
|
|
105
|
+
converted.ownModelOf.push({ kind: "connections", engine: name, model });
|
|
106
|
+
if (engine.provider !== undefined) {
|
|
107
|
+
conversion.notes.push(`engines.${name}: provider is not a setting any more (akm does not branch on it); it is dropped.`);
|
|
108
|
+
}
|
|
109
|
+
if (engine.supportsJsonSchema === false) {
|
|
110
|
+
conversion.notes.push(`engines.${name}: supportsJsonSchema is not a setting any more; akm retries without a schema when the endpoint rejects one.`);
|
|
111
|
+
}
|
|
112
|
+
Object.assign(connection, wireFieldsOf({
|
|
113
|
+
temperature: engine.temperature,
|
|
114
|
+
maxTokens: engine.maxTokens,
|
|
115
|
+
extraParams: engine.extraParams,
|
|
116
|
+
enableThinking: engine.enableThinking,
|
|
117
|
+
reasoningEffort: engine.reasoningEffort,
|
|
118
|
+
}, `engines.${name}`, conversion.notes));
|
|
119
|
+
converted.connections[name] = connection;
|
|
120
|
+
}
|
|
121
|
+
function convertEngines(engines, defaults, env, conversion) {
|
|
122
|
+
const converted = {
|
|
123
|
+
connections: {},
|
|
124
|
+
harnesses: {},
|
|
125
|
+
runtimes: new Map(),
|
|
126
|
+
keyHolders: [],
|
|
127
|
+
ownModelOf: [],
|
|
128
|
+
};
|
|
129
|
+
for (const [name, engine] of Object.entries(engines)) {
|
|
130
|
+
if (!isRecord(engine))
|
|
131
|
+
continue;
|
|
132
|
+
const unknown = Object.keys(engine).filter((k) => !(engine.kind === "agent" ? AGENT_ENGINE_KEYS : LLM_ENGINE_KEYS).has(k));
|
|
133
|
+
if (unknown.length > 0)
|
|
134
|
+
conversion.notes.push(`engines.${name}: dropped ${unknown.join(", ")}, which akm does not read.`);
|
|
135
|
+
if (engine.kind !== "agent")
|
|
136
|
+
llmEngineToConnection(name, engine, defaults, env, converted, conversion);
|
|
137
|
+
else if (engine.platform === "opencode-sdk")
|
|
138
|
+
runtimeEngine(name, engine, converted, conversion);
|
|
139
|
+
else
|
|
140
|
+
agentEngineToHarness(name, engine, converted);
|
|
141
|
+
}
|
|
142
|
+
return converted;
|
|
143
|
+
}
|
|
144
|
+
// ── the defaults are the entries named `default` ─────────────────────────────
|
|
145
|
+
/**
|
|
146
|
+
* The name each of `names` has once `from` is called `default`. An existing `default` moves aside to
|
|
147
|
+
* `legacy-default`, or the first `legacy-default-<n>` that nothing else (an engine, or an entry the file writes
|
|
148
|
+
* itself under `taken`) already has, so no two entries ever share a name and none is lost.
|
|
149
|
+
*/
|
|
150
|
+
function renameMap(names, taken, from) {
|
|
151
|
+
const moved = new Map();
|
|
152
|
+
if (from !== undefined && from !== "default") {
|
|
153
|
+
moved.set(from, "default");
|
|
154
|
+
if (names.includes("default")) {
|
|
155
|
+
const used = new Set([...names, ...taken]);
|
|
156
|
+
let aside = "legacy-default";
|
|
157
|
+
for (let n = 2; used.has(aside); n += 1)
|
|
158
|
+
aside = `legacy-default-${n}`;
|
|
159
|
+
moved.set("default", aside);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
return (name) => moved.get(name) ?? name;
|
|
163
|
+
}
|
|
164
|
+
/** `defaults.llmEngine`, else `defaults.engine`: that connection is `default`; `defaults.engine` naming one of several harnesses: that harness is. */
|
|
165
|
+
function nameDefaults(defaults, converted, conversion, written) {
|
|
166
|
+
const { connections, harnesses, runtimes, keyHolders } = converted;
|
|
167
|
+
const defaultEngine = str(defaults.engine);
|
|
168
|
+
const runtimeLlm = defaultEngine === undefined ? undefined : runtimes.get(defaultEngine);
|
|
169
|
+
const defaultConnection = [str(defaults.llmEngine), defaultEngine, runtimeLlm].find((n) => n !== undefined && n in connections);
|
|
170
|
+
const defaultHarness = defaultEngine !== undefined && defaultEngine in harnesses && Object.keys(harnesses).length > 1
|
|
171
|
+
? defaultEngine
|
|
172
|
+
: undefined;
|
|
173
|
+
const connectionName = renameMap(Object.keys(connections), Object.keys(written.connections), defaultConnection);
|
|
174
|
+
const harnessName = renameMap(Object.keys(harnesses), Object.keys(written.harnesses), defaultHarness);
|
|
175
|
+
const renamed = (entries, name) => Object.fromEntries(Object.entries(entries).map(([engine, entry]) => [name(engine), entry]));
|
|
176
|
+
const named = {
|
|
177
|
+
connections: renamed(connections, connectionName),
|
|
178
|
+
harnesses: renamed(harnesses, harnessName),
|
|
179
|
+
};
|
|
180
|
+
const defaultHarnessName = "default" in named.harnesses
|
|
181
|
+
? "default"
|
|
182
|
+
: Object.keys(named.harnesses).length === 1
|
|
183
|
+
? Object.keys(named.harnesses)[0]
|
|
184
|
+
: undefined;
|
|
185
|
+
if (defaultHarnessName !== undefined && (defaultEngine === undefined || runtimes.has(defaultEngine))) {
|
|
186
|
+
conversion.notes.push(`Agent work ran on akm's own runtime${defaultEngine === undefined ? "" : ` (engines.${defaultEngine})`}; with the harness "${defaultHarnessName}" configured it now runs there. Remove that harness to keep agent work on akm's runtime.`);
|
|
187
|
+
}
|
|
188
|
+
for (const [kind, rename] of [
|
|
189
|
+
["connections", connectionName],
|
|
190
|
+
["harnesses", harnessName],
|
|
191
|
+
]) {
|
|
192
|
+
const aside = rename("default");
|
|
193
|
+
if (aside === "default")
|
|
194
|
+
continue;
|
|
195
|
+
conversion.notes.push(`engines.default is now ${kind}.${aside}, and "default" names another engine: an engine: default key is rewritten by \`akm migrate apply\` where it can be, but a script or scheduled command that passes --engine default now reaches the new "default"; change it to the name ${aside}.`);
|
|
196
|
+
}
|
|
197
|
+
const target = (engine) => {
|
|
198
|
+
if (runtimes.has(engine)) {
|
|
199
|
+
const runtime = runtimes.get(engine);
|
|
200
|
+
return runtime !== undefined && runtime in connections ? { connection: connectionName(runtime) } : undefined;
|
|
201
|
+
}
|
|
202
|
+
if (engine in harnesses)
|
|
203
|
+
return { harness: harnessName(engine) };
|
|
204
|
+
if (engine in connections)
|
|
205
|
+
return { connection: connectionName(engine) };
|
|
206
|
+
return { connection: engine };
|
|
207
|
+
};
|
|
208
|
+
const keys = keyHolders.map(({ engine, field }) => ({
|
|
209
|
+
engine,
|
|
210
|
+
connection: connectionName(engine),
|
|
211
|
+
field,
|
|
212
|
+
}));
|
|
213
|
+
return { defaultConnection, defaultHarness, connectionName, harnessName, ...named, keys, target };
|
|
214
|
+
}
|
|
215
|
+
/** What the file writes under `connections` / `harnesses` itself, read with the converted entries: the written entry wins field by field. */
|
|
216
|
+
function mergeWritten(out, naming) {
|
|
217
|
+
for (const [name, harness] of Object.entries(naming.harnesses)) {
|
|
218
|
+
if (harness.platform === name)
|
|
219
|
+
delete harness.platform;
|
|
220
|
+
}
|
|
221
|
+
return {
|
|
222
|
+
connections: deepMergeConfig(naming.connections, asDict(out.connections)),
|
|
223
|
+
harnesses: deepMergeConfig(naming.harnesses, asDict(out.harnesses)),
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
function ownModelsOf(converted, naming) {
|
|
227
|
+
const ownModels = { connections: new Map(), harnesses: new Map() };
|
|
228
|
+
for (const { kind, engine, model } of converted.ownModelOf) {
|
|
229
|
+
ownModels[kind].set(kind === "connections" ? naming.connectionName(engine) : naming.harnessName(engine), model);
|
|
230
|
+
}
|
|
231
|
+
return ownModels;
|
|
232
|
+
}
|
|
233
|
+
// ── the whole conversion ─────────────────────────────────────────────────────
|
|
234
|
+
export function convertEngineConfig(raw, options = {}) {
|
|
235
|
+
const out = structuredClone(raw);
|
|
236
|
+
const engines = asDict(out.engines);
|
|
237
|
+
const defaults = asDict(out.defaults);
|
|
238
|
+
const conversion = {
|
|
239
|
+
notes: [],
|
|
240
|
+
changed: out.engines !== undefined || out.defaults !== undefined,
|
|
241
|
+
};
|
|
242
|
+
const converted = convertEngines(engines, defaults, options.env, conversion);
|
|
243
|
+
const naming = nameDefaults(defaults, converted, conversion, {
|
|
244
|
+
connections: asDict(out.connections),
|
|
245
|
+
harnesses: asDict(out.harnesses),
|
|
246
|
+
});
|
|
247
|
+
const merged = mergeWritten(out, naming);
|
|
248
|
+
const ownModels = ownModelsOf(converted, naming);
|
|
249
|
+
foldModelsOverlay(options.modelsOverlay, {
|
|
250
|
+
conversion,
|
|
251
|
+
merged,
|
|
252
|
+
ownModels,
|
|
253
|
+
written: { connections: asDict(out.connections), harnesses: asDict(out.harnesses) },
|
|
254
|
+
inherited: { connections: options.inherited?.connections ?? {}, harnesses: options.inherited?.harnesses ?? {} },
|
|
255
|
+
renamed: {
|
|
256
|
+
runtime: [...converted.runtimes.values()]
|
|
257
|
+
.filter((name) => name !== undefined && name in converted.connections)
|
|
258
|
+
.map((name) => naming.connectionName(name)),
|
|
259
|
+
connection: (engine) => (engine in converted.connections ? naming.connectionName(engine) : undefined),
|
|
260
|
+
},
|
|
261
|
+
});
|
|
262
|
+
foldEngineModels(merged, ownModels);
|
|
263
|
+
const retarget = retargeter(conversion, naming.target);
|
|
264
|
+
const improve = out.improve;
|
|
265
|
+
if (isRecord(improve))
|
|
266
|
+
moveStrategyExecution(improve, conversion, retarget);
|
|
267
|
+
improveStrategyDefault(out, defaults, improve);
|
|
268
|
+
dropJudgeEngine(out, conversion);
|
|
269
|
+
convertIndexEngines(out, conversion, retarget);
|
|
270
|
+
// Assemble, keeping the file's key order.
|
|
271
|
+
const config = {};
|
|
272
|
+
let placed = false;
|
|
273
|
+
for (const [key, value] of Object.entries(out)) {
|
|
274
|
+
if (key === "defaults")
|
|
275
|
+
continue;
|
|
276
|
+
if (key !== "engines" && key !== "connections" && key !== "harnesses") {
|
|
277
|
+
config[key] = value;
|
|
278
|
+
}
|
|
279
|
+
else if (!placed) {
|
|
280
|
+
placed = true;
|
|
281
|
+
if (Object.keys(merged.connections).length > 0)
|
|
282
|
+
config.connections = merged.connections;
|
|
283
|
+
if (Object.keys(merged.harnesses).length > 0)
|
|
284
|
+
config.harnesses = merged.harnesses;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
const targets = {};
|
|
288
|
+
for (const name of Object.keys(engines).filter((engine) => isRecord(engines[engine]))) {
|
|
289
|
+
const became = naming.target(name);
|
|
290
|
+
if (became !== undefined)
|
|
291
|
+
targets[name] = became;
|
|
292
|
+
}
|
|
293
|
+
return {
|
|
294
|
+
config: conversion.changed ? config : raw,
|
|
295
|
+
notes: conversion.notes,
|
|
296
|
+
changed: conversion.changed,
|
|
297
|
+
keys: naming.keys,
|
|
298
|
+
targets,
|
|
299
|
+
};
|
|
300
|
+
}
|
|
@@ -0,0 +1,137 @@
|
|
|
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
|
+
* `models.json`, and an engine's own `model`, folded into the `models` of the connections
|
|
6
|
+
* and harnesses the engines became. See `convert-engines.ts`.
|
|
7
|
+
*/
|
|
8
|
+
import { getHarness } from "../../integrations/harnesses/index.js";
|
|
9
|
+
import { isRecord } from "../common.js";
|
|
10
|
+
import { str, wireFieldsOf } from "./convert-engines-shared.js";
|
|
11
|
+
import { modelForEveryAlias } from "./model-aliases.js";
|
|
12
|
+
const allAliases = (model) => model === undefined ? undefined : modelForEveryAlias(model);
|
|
13
|
+
/** An overlay entry as a model entry: the bare name, or `{ model, ...fields }` when it sets more. */
|
|
14
|
+
function modelEntry(model, fields) {
|
|
15
|
+
return Object.keys(fields).length > 0 ? { model, ...fields } : model;
|
|
16
|
+
}
|
|
17
|
+
// ── models.json folds into the models of what it named ───────────────────────
|
|
18
|
+
/** The models of `entry`, made on it when it has none yet. */
|
|
19
|
+
function modelsOf(entry) {
|
|
20
|
+
entry.models ??= {};
|
|
21
|
+
return entry.models;
|
|
22
|
+
}
|
|
23
|
+
const hasModel = (entry, alias) => isRecord(entry) && isRecord(entry.models) && alias in entry.models;
|
|
24
|
+
/**
|
|
25
|
+
* The overlay's rows: one per alias and column, the runtime's column first (it is the weakest, naming OpenCode's own
|
|
26
|
+
* models), then a connection's own, then `*`, which fills what is left. The flat shorthand is the `*` column.
|
|
27
|
+
*/
|
|
28
|
+
function overlayRows(modelsOverlay) {
|
|
29
|
+
const overlay = isRecord(modelsOverlay) && isRecord(modelsOverlay.aliases) ? modelsOverlay.aliases : {};
|
|
30
|
+
const rows = Object.entries(overlay).flatMap(([alias, columns]) => {
|
|
31
|
+
if (!isRecord(columns))
|
|
32
|
+
return [];
|
|
33
|
+
const flat = Object.fromEntries(Object.entries(columns).filter(([k]) => k === "model" || k === "inference" || k === "engine"));
|
|
34
|
+
const perColumn = Object.entries(columns).filter(([k]) => !(k in flat));
|
|
35
|
+
return [...perColumn, ...(Object.keys(flat).length > 0 ? [["*", flat]] : [])].map(([column, profile]) => ({
|
|
36
|
+
alias,
|
|
37
|
+
column,
|
|
38
|
+
profile,
|
|
39
|
+
}));
|
|
40
|
+
});
|
|
41
|
+
const rank = (column) => (column === "opencode-sdk" ? 0 : column === "*" ? 2 : 1);
|
|
42
|
+
return rows.sort((a, b) => rank(a.column) - rank(b.column));
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* `models.json`: an alias is set by, nearest first, the config's own `models`, models.json's column for that
|
|
46
|
+
* connection or harness, models.json's `*` column (and the flat shorthand, which is that), the engine's own model.
|
|
47
|
+
*/
|
|
48
|
+
export function foldModelsOverlay(modelsOverlay, fold) {
|
|
49
|
+
const { conversion, merged, written, inherited, ownModels, renamed } = fold;
|
|
50
|
+
const { notes } = conversion;
|
|
51
|
+
const mergedConnections = merged.connections;
|
|
52
|
+
const mergedHarnesses = merged.harnesses;
|
|
53
|
+
const inheritedConnections = inherited.connections;
|
|
54
|
+
const inheritedHarnesses = inherited.harnesses;
|
|
55
|
+
const writtenConnections = written.connections;
|
|
56
|
+
const writtenHarnesses = written.harnesses;
|
|
57
|
+
/** Whether the config itself, the file or its base, already names a model for the alias. */
|
|
58
|
+
const configNames = (own, base, name, alias) => hasModel(own[name], alias) || hasModel(base[name], alias);
|
|
59
|
+
const platformOf = (name) => String((mergedHarnesses[name] ?? inheritedHarnesses[name])?.platform ?? name);
|
|
60
|
+
let folded = false;
|
|
61
|
+
for (const { alias, column, profile } of overlayRows(modelsOverlay)) {
|
|
62
|
+
const p = typeof profile === "string" ? { model: profile } : isRecord(profile) ? profile : {};
|
|
63
|
+
const { effort, ...portable } = (isRecord(p.inference) ? p.inference : {});
|
|
64
|
+
const where = `models.json ${alias}.${column === "*" ? "(all)" : column}`;
|
|
65
|
+
const wire = wireFieldsOf({ ...portable, reasoningEffort: portable.reasoningEffort ?? effort }, where, notes);
|
|
66
|
+
if (p.engine !== undefined) {
|
|
67
|
+
notes.push(`${where}: an engine indirection is not carried over.`);
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
const candidates = column === "*"
|
|
71
|
+
? [...new Set([...Object.keys(mergedConnections), ...Object.keys(inheritedConnections)])]
|
|
72
|
+
: column === "opencode-sdk"
|
|
73
|
+
? [...renamed.runtime]
|
|
74
|
+
: renamed.connection(column) !== undefined
|
|
75
|
+
? [renamed.connection(column)]
|
|
76
|
+
: column in writtenConnections || column in inheritedConnections
|
|
77
|
+
? [column]
|
|
78
|
+
: [];
|
|
79
|
+
const harnessNamed = [...new Set([...Object.keys(mergedHarnesses), ...Object.keys(inheritedHarnesses)])].filter((name) => platformOf(name) === column);
|
|
80
|
+
if (candidates.length === 0 && harnessNamed.length === 0) {
|
|
81
|
+
notes.push(`${where}: names no configured connection or harness, so it is not carried over.`);
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
// The config's own choice stands, and `*` leaves what an explicit column already set.
|
|
85
|
+
const connectionNames = candidates.filter((name) => !configNames(writtenConnections, inheritedConnections, name, alias) &&
|
|
86
|
+
!(column === "*" && hasModel(mergedConnections[name], alias)));
|
|
87
|
+
const harnessNames = harnessNamed.filter((name) => !configNames(writtenHarnesses, inheritedHarnesses, name, alias));
|
|
88
|
+
if (connectionNames.length === 0 && harnessNames.length === 0) {
|
|
89
|
+
// Only the config's own choice is worth a note; an explicit column that came first is the overlay's own.
|
|
90
|
+
const keptByConfig = candidates.some((name) => configNames(writtenConnections, inheritedConnections, name, alias)) ||
|
|
91
|
+
harnessNamed.some((name) => configNames(writtenHarnesses, inheritedHarnesses, name, alias));
|
|
92
|
+
if (keptByConfig)
|
|
93
|
+
notes.push(`${where}: the config already names a model for it, so it is not carried over.`);
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
for (const name of connectionNames) {
|
|
97
|
+
const current = mergedConnections[name]?.models;
|
|
98
|
+
const existing = current?.[alias];
|
|
99
|
+
const model = str(p.model) ?? str(isRecord(existing) ? existing.model : existing) ?? ownModels.connections.get(name);
|
|
100
|
+
if (model === undefined)
|
|
101
|
+
continue;
|
|
102
|
+
// A connection only the base defines gets a partial entry here; the base completes it.
|
|
103
|
+
mergedConnections[name] ??= {};
|
|
104
|
+
modelsOf(mergedConnections[name])[alias] = modelEntry(model, wire);
|
|
105
|
+
folded = true;
|
|
106
|
+
}
|
|
107
|
+
for (const name of harnessNames) {
|
|
108
|
+
const model = str(p.model) ?? str(getHarness(platformOf(name))?.models?.[alias]);
|
|
109
|
+
if (model === undefined)
|
|
110
|
+
continue;
|
|
111
|
+
mergedHarnesses[name] ??= {};
|
|
112
|
+
modelsOf(mergedHarnesses[name])[alias] = model;
|
|
113
|
+
folded = true;
|
|
114
|
+
if (Object.keys(wire).length > 0)
|
|
115
|
+
notes.push(`${where}: a harness takes the model only; the inference settings are not carried over.`);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
if (folded)
|
|
119
|
+
conversion.changed = true;
|
|
120
|
+
}
|
|
121
|
+
/** An engine's `model`: every alias nothing else named is that model, on the entry the engine became. */
|
|
122
|
+
export function foldEngineModels(merged, ownModels) {
|
|
123
|
+
for (const [kind, entries] of [
|
|
124
|
+
["connections", merged.connections],
|
|
125
|
+
["harnesses", merged.harnesses],
|
|
126
|
+
]) {
|
|
127
|
+
for (const [name, model] of ownModels[kind]) {
|
|
128
|
+
const entry = entries[name];
|
|
129
|
+
if (!isRecord(entry))
|
|
130
|
+
continue;
|
|
131
|
+
for (const [alias, value] of Object.entries(allAliases(model) ?? {})) {
|
|
132
|
+
if (!hasModel(entry, alias))
|
|
133
|
+
modelsOf(entry)[alias] = value;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|