akm-cli 0.9.16 → 0.9.17-alpha.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +2101 -0
- package/STABILITY.md +11 -10
- package/dist/akm +124 -193
- package/dist/akm-migrate +38 -19
- package/dist/assets/hints/cli-hints-full.md +6 -7
- package/dist/assets/improve-strategies/catchup.json +0 -3
- package/dist/assets/improve-strategies/consolidate.json +0 -1
- package/dist/assets/improve-strategies/default.json +1 -2
- package/dist/assets/improve-strategies/proactive-maintenance.json +1 -2
- package/dist/assets/improve-strategies/quick.json +1 -2
- package/dist/assets/improve-strategies/reflect-distill.json +1 -2
- package/dist/assets/improve-strategies/thorough.json +0 -3
- package/dist/assets/prompts/consolidate-pair.md +20 -0
- package/dist/assets/prompts/consolidate-system.md +4 -11
- package/dist/assets/prompts/retrieval-relevance-judge.md +6 -0
- package/dist/assets/stash-skeleton/facts/conventions/backlinks.md +20 -20
- package/dist/assets/stash-skeleton/facts/conventions/domains.md +2 -2
- package/dist/assets/templates/html/health.html +3 -5
- package/dist/cli/retired-commands.js +1 -1
- package/dist/cli/shared.js +6 -2
- package/dist/cli/unknown-flags.js +24 -1
- package/dist/cli.js +68 -10
- package/dist/commands/agent/agent-dispatch.js +1 -1
- package/dist/commands/command/command-execution.js +24 -62
- package/dist/commands/feedback-cli.js +0 -1
- package/dist/commands/health/accept-rate.js +6 -0
- package/dist/commands/health/archive-usage.js +92 -0
- package/dist/commands/health/checks.js +83 -74
- package/dist/commands/health/config-skew.js +38 -0
- package/dist/commands/health/data-dir-usage.js +25 -13
- package/dist/commands/health/egress.js +54 -0
- package/dist/commands/health/html-report.js +1 -42
- package/dist/commands/health/improve-metrics.js +136 -591
- package/dist/commands/health/md-report.js +1 -6
- package/dist/commands/health/plugin-staleness.js +53 -3
- package/dist/commands/health/renderers.js +12 -4
- package/dist/commands/health/report-view-model.js +14 -120
- package/dist/commands/health/types-improve.js +4 -19
- package/dist/commands/health/windows.js +64 -74
- package/dist/commands/health.js +145 -143
- package/dist/commands/improve/consolidate/chunking.js +26 -117
- package/dist/commands/improve/consolidate/continuity-check.js +137 -0
- package/dist/commands/improve/consolidate/pair-pass.js +791 -0
- package/dist/commands/improve/consolidate/sanitize.js +54 -149
- package/dist/commands/improve/consolidate.js +589 -1127
- package/dist/commands/improve/content-hash.js +16 -24
- package/dist/commands/improve/distill/content-repair.js +18 -100
- package/dist/commands/improve/distill-guards.js +20 -81
- package/dist/commands/improve/distill-promotion-policy.js +23 -243
- package/dist/commands/improve/distill.js +608 -1041
- package/dist/commands/improve/eligibility.js +126 -390
- package/dist/commands/improve/execution.js +8 -10
- package/dist/commands/improve/extract-prompt.js +1 -2
- package/dist/commands/improve/extract.js +487 -1046
- package/dist/commands/improve/feedback-valence.js +0 -25
- package/dist/commands/improve/improve-cli.js +75 -169
- package/dist/commands/improve/improve-result-file.js +10 -66
- package/dist/commands/improve/improve-strategies.js +52 -4
- package/dist/commands/improve/improve-usage-report.js +18 -64
- package/dist/commands/improve/improve.js +480 -1074
- package/dist/commands/improve/ledger.js +119 -0
- package/dist/commands/improve/locks.js +2 -8
- package/dist/commands/improve/loop-stages.js +415 -1073
- package/dist/commands/improve/memory/derived-ref.js +12 -77
- package/dist/commands/improve/memory/memory-belief.js +16 -118
- package/dist/commands/improve/memory/memory-improve.js +266 -14
- package/dist/commands/improve/outcome-loop.js +28 -156
- package/dist/commands/improve/planner.js +5 -15
- package/dist/commands/improve/preparation.js +779 -2319
- package/dist/commands/improve/proactive-maintenance.js +34 -101
- package/dist/commands/improve/reflect-noise.js +104 -280
- package/dist/commands/improve/reflect.js +642 -1353
- package/dist/commands/improve/retrieval-gate.js +127 -0
- package/dist/commands/improve/retrieval-scope.js +92 -0
- package/dist/commands/improve/salience.js +41 -240
- package/dist/commands/improve/session-asset.js +19 -100
- package/dist/commands/improve/stage.js +322 -0
- package/dist/commands/lint/base-linter.js +37 -15
- package/dist/commands/proposal/drain.js +261 -578
- package/dist/commands/proposal/proposal-cli.js +19 -20
- package/dist/commands/proposal/proposal-types.js +31 -24
- package/dist/commands/proposal/proposal.js +38 -8
- package/dist/commands/proposal/propose.js +134 -160
- package/dist/commands/proposal/repository.js +1097 -1394
- package/dist/commands/proposal/validators/proposal-quality-validators.js +71 -174
- package/dist/commands/proposal/validators/proposal-validators.js +1 -1
- package/dist/commands/proposal/validators/proposals.js +22 -89
- package/dist/commands/read/curate.js +105 -462
- package/dist/commands/read/knowledge.js +3 -2
- package/dist/commands/read/search-cli.js +16 -33
- package/dist/commands/read/search.js +17 -23
- package/dist/commands/read/show.js +57 -108
- package/dist/commands/sources/bundle-cli.js +25 -2
- package/dist/commands/sources/bundle-config-ops.js +4 -0
- package/dist/commands/sources/dangerous-env-audit.js +1 -2
- package/dist/commands/sources/info.js +127 -29
- package/dist/commands/sources/installed-stashes.js +197 -746
- package/dist/commands/sources/schema-repair.js +98 -129
- package/dist/commands/sources/source-add.js +62 -12
- package/dist/commands/sources/source-manage.js +9 -2
- package/dist/commands/sources/stash-cli.js +24 -4
- package/dist/commands/tasks/explain.js +10 -13
- package/dist/commands/tasks/tasks-cli.js +12 -13
- package/dist/commands/tasks/tasks.js +350 -936
- package/dist/commands/tasks/validate.js +26 -24
- package/dist/commands/workflow/plan.js +22 -29
- package/dist/commands/workflow-cli.js +4 -4
- package/dist/core/adapter/adapters/akm-adapter.js +2 -1
- package/dist/core/adapter/adapters/akm-lint.js +2 -3
- package/dist/core/adapter/adapters/akm-metadata.js +42 -12
- package/dist/core/adapter/adapters/akm-task-adapter.js +29 -8
- package/dist/core/adapter/adapters/akm-workflow-adapter.js +1 -1
- package/dist/core/adapter/execution-source.js +17 -29
- package/dist/core/asset/asset-placement.js +4 -13
- package/dist/core/asset/frontmatter.js +106 -1
- package/dist/core/asset/resolve-ref.js +1 -1
- package/dist/core/bundle-id.js +42 -5
- package/dist/core/bundle-rename.js +285 -0
- package/dist/core/config/config-io.js +1 -2
- package/dist/core/config/config-schema.js +9 -34
- package/dist/core/config/config-walker.js +1 -1
- package/dist/core/config/config.js +184 -111
- package/dist/core/config/engine-semantics.js +0 -2
- package/dist/core/config/legacy-source-shape-shim.js +38 -9
- package/dist/core/config/schema/embedding.js +20 -5
- package/dist/core/config/schema/engines.js +5 -0
- package/dist/core/config/schema/execution.js +1 -1
- package/dist/core/config/schema/experimental.js +1 -1
- package/dist/core/config/schema/improve-processes.js +54 -125
- package/dist/core/config/schema/improve.js +4 -42
- package/dist/core/config/schema/index-config.js +9 -48
- package/dist/core/config/schema/scheduler.js +12 -12
- package/dist/core/config/schema/search.js +6 -22
- package/dist/core/env-secret-ref.js +0 -1
- package/dist/core/errors.js +8 -9
- package/dist/core/file-change.js +13 -5
- package/dist/core/file-lock.js +76 -173
- package/dist/core/improve-result.js +35 -7
- package/dist/core/improve-types.js +0 -1
- package/dist/core/logs-db.js +2 -2
- package/dist/core/loopback.js +7 -12
- package/dist/core/non-task-input.js +20 -0
- package/dist/core/parse.js +13 -16
- package/dist/core/paths.js +0 -24
- package/dist/core/redaction.js +109 -2
- package/dist/core/run-lock.js +2 -5
- package/dist/core/spawn-env.js +1 -1
- package/dist/core/state/migrations.js +123 -61
- package/dist/core/state-db-scope.js +2 -4
- package/dist/core/state-db.js +126 -692
- package/dist/core/time.js +0 -20
- package/dist/core/type-presentation.js +1 -9
- package/dist/core/write-source.js +294 -1005
- package/dist/execution/input-contract.js +1 -1
- package/dist/execution/resolved-request.js +135 -689
- package/dist/execution/source.js +63 -257
- package/dist/execution/target-ref.js +1 -1
- package/dist/indexer/bundle-identity-guard.js +2 -2
- package/dist/indexer/db/llm-cache.js +2 -2
- package/dist/indexer/ensure-index.js +77 -73
- package/dist/indexer/index-rebuild-lock.js +3 -11
- package/dist/indexer/index-writer-lock.js +8 -17
- package/dist/indexer/index-written-assets.js +141 -154
- package/dist/indexer/indexer.js +400 -1124
- package/dist/indexer/links/declared-links.js +90 -0
- package/dist/indexer/materialize-embeddings.js +60 -397
- package/dist/indexer/passes/memory-inference.js +96 -90
- package/dist/indexer/passes/metadata.js +132 -219
- package/dist/indexer/read-preflight.js +0 -7
- package/dist/indexer/scan/doc-to-entry.js +2 -3
- package/dist/indexer/scan/drain-dir.js +1 -1
- package/dist/indexer/search/db-search.js +190 -590
- package/dist/indexer/search/fts-query.js +30 -41
- package/dist/indexer/search/ranking.js +28 -154
- package/dist/indexer/search/search-attribution.js +12 -32
- package/dist/indexer/search/search-fields.js +11 -15
- package/dist/indexer/search/search-hit-enrichers.js +54 -85
- package/dist/indexer/search/search-source.js +1 -4
- package/dist/indexer/usage/usage-events.js +36 -7
- package/dist/indexer/walk/walker.js +3 -4
- package/dist/integrations/agent/engine-fallback.js +23 -40
- package/dist/integrations/agent/engine-resolution.js +93 -183
- package/dist/integrations/agent/execution.js +507 -0
- package/dist/integrations/agent/model-map.js +28 -156
- package/dist/integrations/agent/request-lowering.js +66 -141
- package/dist/integrations/agent/runner-dispatch.js +143 -321
- package/dist/integrations/agent/runner.js +54 -14
- package/dist/integrations/lockfile.js +53 -101
- package/dist/llm/client.js +18 -6
- package/dist/llm/embedders/deterministic.js +2 -3
- package/dist/llm/embedders/profile.js +71 -0
- package/dist/llm/embedders/remote.js +11 -17
- package/dist/llm/feature-gate.js +0 -8
- package/dist/llm/index-passes.js +3 -5
- package/dist/llm/memory-infer.js +1 -2
- package/dist/llm/structured-call.js +5 -24
- package/dist/output/generic-render.js +23 -11
- package/dist/output/html-render.js +13 -10
- package/dist/output/render-registry.js +3 -32
- package/dist/output/shapes/helpers.js +25 -38
- package/dist/output/shapes/passthrough.js +1 -9
- package/dist/{indexer/graph/graph-types.js → output/text/bundle-rename.js} +4 -1
- package/dist/output/text/command-format.js +69 -31
- package/dist/output/text/helpers.js +1 -1
- package/dist/output/text/migrate.js +5 -14
- package/dist/output/text/proposal-format.js +48 -3
- package/dist/output/text/show-format.js +13 -17
- package/dist/output/text/workflow-format.js +0 -32
- package/dist/output/text.js +2 -0
- package/dist/registry/factory.js +4 -19
- package/dist/registry/network.js +66 -220
- package/dist/registry/providers/index.js +0 -2
- package/dist/registry/providers/skills-sh.js +3 -14
- package/dist/registry/providers/static-index.js +24 -26
- package/dist/registry/resolve.js +55 -131
- package/dist/scripts/akm-migrate-node.js +42948 -92369
- package/dist/scripts/akm-migrate.js +42935 -92354
- package/dist/setup/registry-stash-loader.js +4 -13
- package/dist/setup/semantic-assets.js +3 -44
- package/dist/setup/setup.js +1 -1
- package/dist/setup/steps/connection.js +5 -6
- package/dist/setup/steps/platforms.js +2 -2
- package/dist/setup/steps/tasks.js +25 -15
- package/dist/sources/provider-factory.js +17 -18
- package/dist/sources/providers/filesystem.js +2 -3
- package/dist/sources/providers/git-install.js +7 -1
- package/dist/sources/providers/git-provider.js +0 -3
- package/dist/sources/providers/git-stash.js +83 -21
- package/dist/sources/providers/npm.js +2 -4
- package/dist/sources/providers/provider-utils.js +5 -10
- package/dist/sources/providers/website.js +0 -2
- package/dist/sources/snapshot-fetchers/website-ingest.js +1 -1
- package/dist/sources/website-url.js +2 -2
- package/dist/storage/database.js +9 -35
- package/dist/storage/repositories/improve-ledger-repository.js +209 -0
- package/dist/storage/repositories/index-connection.js +39 -72
- package/dist/storage/repositories/index-entries-repository.js +131 -129
- package/dist/storage/repositories/index-entry-mapper.js +1 -2
- package/dist/storage/repositories/index-entry-schema.js +101 -268
- package/dist/storage/repositories/index-fts-repository.js +86 -256
- package/dist/storage/repositories/index-links-repository.js +143 -0
- package/dist/storage/repositories/index-llm-cache-repository.js +7 -9
- package/dist/storage/repositories/index-meta-repository.js +6 -4
- package/dist/storage/repositories/index-schema.js +257 -325
- package/dist/storage/repositories/index-utility-repository.js +8 -29
- package/dist/storage/repositories/index-vec-repository.js +133 -414
- package/dist/storage/repositories/outcome-repository.js +2 -1
- package/dist/storage/repositories/proposals-repository.js +104 -1
- package/dist/storage/repositories/registry-index-cache-repository.js +100 -0
- package/dist/storage/repositories/salience-repository.js +1 -19
- package/dist/storage/repositories/task-history-repository.js +26 -4
- package/dist/storage/repositories/workflow-runs-repository.js +53 -244
- package/dist/storage/sqlite-migrations.js +136 -0
- package/dist/storage/sqlite-pragmas.js +11 -9
- package/dist/storage/sqlite-transaction.js +170 -0
- package/dist/storage/state-db-integrity.js +130 -0
- package/dist/tasks/activation-config.js +134 -62
- package/dist/tasks/backends/cron.js +191 -302
- package/dist/tasks/backends/exec-utils.js +2 -5
- package/dist/tasks/backends/launchd.js +141 -748
- package/dist/tasks/backends/schtasks.js +119 -623
- package/dist/tasks/prepare/prepare-support.js +5 -15
- package/dist/tasks/prepare/prepare.js +0 -2
- package/dist/tasks/resolve-akm-bin.js +20 -79
- package/dist/tasks/run/attempt-lifecycle.js +0 -1
- package/dist/tasks/run/load-task.js +1 -1
- package/dist/tasks/scheduler-binding.js +20 -238
- package/dist/tasks/scheduler-invocation.js +136 -244
- package/dist/tasks/scheduler-lock.js +53 -0
- package/dist/tasks/scheduler-sync.js +368 -679
- package/dist/tasks/source/parse-task-source.js +55 -9
- package/dist/tasks/source/task-source-v3-frozen.js +3 -4
- package/dist/tasks/source/task-to-v4.js +464 -88
- package/dist/workflows/authoring/authoring.js +3 -12
- package/dist/workflows/compile.js +211 -0
- package/dist/workflows/concurrency-policy.js +13 -74
- package/dist/workflows/exec/child-invocation.js +3 -17
- package/dist/workflows/exec/child-workflow.js +32 -141
- package/dist/workflows/exec/dispatch-redaction.js +13 -53
- package/dist/workflows/exec/environment.js +98 -0
- package/dist/workflows/exec/exec-unit.js +33 -140
- package/dist/workflows/exec/frozen-judge.js +7 -59
- package/dist/workflows/exec/native-executor.js +82 -341
- package/dist/workflows/exec/param-secrets.js +29 -47
- package/dist/workflows/exec/run-workflow.js +154 -387
- package/dist/workflows/exec/scheduler.js +9 -36
- package/dist/workflows/exec/step-work.js +127 -430
- package/dist/workflows/exec/unit-dispatch.js +11 -63
- package/dist/workflows/exec/unit-writer.js +8 -52
- package/dist/workflows/exec/worktree.js +39 -273
- package/dist/workflows/freeze/child-output-references.js +4 -15
- package/dist/workflows/freeze/environment.js +99 -92
- package/dist/workflows/freeze/freeze.js +172 -0
- package/dist/workflows/freeze/step-values.js +19 -21
- package/dist/workflows/freeze/targets/child-workflow.js +23 -92
- package/dist/workflows/freeze/targets/command.js +10 -33
- package/dist/workflows/freeze/targets/script.js +5 -12
- package/dist/workflows/freeze/targets/shell.js +3 -6
- package/dist/workflows/freeze/targets/task.js +25 -80
- package/dist/workflows/freeze/task-bindings.js +20 -67
- package/dist/workflows/{source-ir/github-yaml.js → github-yaml.js} +88 -206
- package/dist/workflows/ir/params.js +6 -51
- package/dist/workflows/ir/plan-hash.js +2 -34
- package/dist/workflows/parser.js +140 -43
- package/dist/{commands/improve/consolidate/types.js → workflows/plan.js} +2 -1
- package/dist/workflows/renderer.js +36 -69
- package/dist/workflows/resource-limits.js +12 -120
- package/dist/workflows/runtime/agent-identity.js +8 -40
- package/dist/workflows/runtime/run-outputs.js +3 -6
- package/dist/workflows/runtime/run-plan.js +316 -0
- package/dist/workflows/runtime/runs.js +48 -200
- package/dist/workflows/runtime/workflow-asset-loader.js +24 -57
- package/dist/workflows/{source-ir/semantics.js → source-semantics.js} +16 -20
- package/dist/workflows/validate-summary.js +2 -7
- package/docs/integration/bundling-akm.md +49 -42
- package/docs/migration/README.md +1 -0
- package/docs/migration/release-notes/0.9.17.md +43 -0
- package/docs/migration/v0.9.1-to-v0.9.2.md +23 -7
- package/docs/reference/cli.md +232 -135
- package/docs/reference/configuration.md +71 -57
- package/docs/reference/data-and-telemetry.md +20 -21
- package/docs/reference/tasks.md +105 -39
- package/docs/reference/workflow-schema.md +14 -18
- package/docs/reference/workflows.md +6 -9
- package/package.json +1 -1
- package/schemas/akm-config.json +115 -738
- package/schemas/akm-workflow.json +1 -0
- package/dist/assets/improve-strategies/graph-refresh.json +0 -15
- package/dist/assets/prompts/contradiction-judge.md +0 -33
- package/dist/assets/prompts/graph-extract-system.md +0 -1
- package/dist/assets/prompts/graph-extract-user-prompt.md +0 -35
- package/dist/assets/prompts/metadata-enhance-system.md +0 -1
- package/dist/assets/tasks/improve/akm-graph-refresh-weekly.yml +0 -4
- package/dist/commands/health/advisories.js +0 -150
- package/dist/commands/health/metrics.js +0 -329
- package/dist/commands/health/surfaces.js +0 -102
- package/dist/commands/improve/anti-collapse.js +0 -83
- package/dist/commands/improve/collapse-detector.js +0 -432
- package/dist/commands/improve/consolidate/eligibility.js +0 -48
- package/dist/commands/improve/consolidate/merge.js +0 -149
- package/dist/commands/improve/distill/promote-memory.js +0 -291
- package/dist/commands/improve/distill/quality-gate.js +0 -337
- package/dist/commands/improve/eval-cases.js +0 -52
- package/dist/commands/improve/memory/memory-contradiction-detect.js +0 -291
- package/dist/commands/improve/proposal-envelope.js +0 -31
- package/dist/commands/improve/run-context.js +0 -123
- package/dist/commands/improve/shared.js +0 -31
- package/dist/commands/improve/source-identity.js +0 -28
- package/dist/commands/improve/triage.js +0 -96
- package/dist/commands/proposal/drain-policies.js +0 -151
- package/dist/commands/sources/update-transaction.js +0 -220
- package/dist/core/action-contributors.js +0 -28
- package/dist/core/config/config-version-shim.js +0 -101
- package/dist/core/fs-txn.js +0 -405
- package/dist/core/lexical-score.js +0 -25
- package/dist/core/maintenance-barrier.js +0 -167
- package/dist/execution/executable-identity.js +0 -105
- package/dist/execution/guarded-source.js +0 -427
- package/dist/indexer/db/graph-db.js +0 -444
- package/dist/indexer/graph/graph-boost.js +0 -427
- package/dist/indexer/graph/graph-dedup.js +0 -95
- package/dist/indexer/graph/graph-extraction.js +0 -1108
- package/dist/indexer/search/name-match.js +0 -35
- package/dist/indexer/search/ranking-contributors.js +0 -515
- package/dist/indexer/search/ranking-types.js +0 -4
- package/dist/indexer/walk/project-context.js +0 -192
- package/dist/integrations/agent/execution-cascade.js +0 -566
- package/dist/integrations/agent/execution-definitions.js +0 -202
- package/dist/integrations/agent/execution-lowering.js +0 -841
- package/dist/integrations/agent/execution-preparation.js +0 -98
- package/dist/integrations/agent/inline-execution.js +0 -74
- package/dist/llm/graph-extract.js +0 -728
- package/dist/llm/metadata-enhance.js +0 -96
- package/dist/registry/create-provider-registry.js +0 -29
- package/dist/registry/pinned-request-helper.js +0 -247
- package/dist/registry/pinned-transport.js +0 -717
- package/dist/sources/providers/index.js +0 -14
- package/dist/storage/engines/sqlite-migrations.js +0 -271
- package/dist/storage/repositories/canaries-repository.js +0 -107
- package/dist/storage/repositories/embedding-salvage-repository.js +0 -184
- package/dist/storage/repositories/registry-cache.js +0 -113
- package/dist/tasks/scheduler-sync-preview.js +0 -52
- package/dist/tasks/source/task-to-v3.js +0 -507
- package/dist/workflows/freeze/resolve-steps.js +0 -86
- package/dist/workflows/freeze/source-freeze.js +0 -64
- package/dist/workflows/ir/compile.js +0 -321
- package/dist/workflows/ir/environment-v4.js +0 -330
- package/dist/workflows/ir/freeze-v4.js +0 -153
- package/dist/workflows/ir/schema-v4.js +0 -745
- package/dist/workflows/ir/schema.js +0 -354
- package/dist/workflows/program/schema.js +0 -77
- package/dist/workflows/runtime/checkin.js +0 -57
- package/dist/workflows/runtime/plan-classifier.js +0 -196
- package/dist/workflows/runtime/unit-checkin.js +0 -45
- package/dist/workflows/runtime/unit-phases.js +0 -20
- package/dist/workflows/schema.js +0 -4
- package/dist/workflows/source-ir/compile.js +0 -200
- package/dist/workflows/source-ir/program.js +0 -50
- package/dist/workflows/source-ir/result.js +0 -26
- package/dist/workflows/source-ir/schema.js +0 -786
- package/dist/workflows/source-ir/triggers.js +0 -79
- package/dist/workflows/source-ir/uses.js +0 -40
- package/dist/workflows/validator.js +0 -60
|
@@ -5,15 +5,16 @@ import fs from "node:fs";
|
|
|
5
5
|
import os from "node:os";
|
|
6
6
|
import path from "node:path";
|
|
7
7
|
import { isDeepStrictEqual } from "node:util";
|
|
8
|
-
import { isBundleSlug } from "../asset/asset-ref.js";
|
|
9
|
-
import {
|
|
8
|
+
import { isBundleSlug, parseBundleRef } from "../asset/asset-ref.js";
|
|
9
|
+
import { deriveBundleId } from "../bundle-id.js";
|
|
10
|
+
import { isRecord, resolveStashDir } from "../common.js";
|
|
10
11
|
import { ConfigError } from "../errors.js";
|
|
11
12
|
import { liftLegacyEngineExtraParams } from "../extra-params.js";
|
|
12
13
|
import { formatRegistryLabel, hasRegistryUrlCredentials } from "../registry-url.js";
|
|
13
14
|
import { acquireConfigLock, backupExistingConfig, parseConfigText, readConfigText, withConfigLock, writeConfigAtomic, } from "./config-io.js";
|
|
14
|
-
import { AkmConfigSchema, CURRENT_CONFIG_VERSION
|
|
15
|
-
import { bundleComponentConfig, bundleContentRoot, bundleContentRoots, bundlesToSourceEntries } from "./config-sources.js";
|
|
16
|
-
import {
|
|
15
|
+
import { AkmConfigSchema, CURRENT_CONFIG_VERSION } from "./config-schema.js";
|
|
16
|
+
import { bundleComponentConfig, bundleContentRoot, bundleContentRoots, bundleSourceId, bundlesToSourceEntries, filesystemBundleSourceId, isBundleEnabled, } from "./config-sources.js";
|
|
17
|
+
import { resolveSchemaAt } from "./config-walker.js";
|
|
17
18
|
import { deepMergeConfig, isPlainObject } from "./deep-merge.js";
|
|
18
19
|
import { migrateLegacySourceShape } from "./legacy-source-shape-shim.js";
|
|
19
20
|
import { isApiKeyReference, SECRET_STORE_REFERENCE_PATTERN } from "./schema/primitives.js";
|
|
@@ -26,36 +27,6 @@ export { VALID_HARNESS_IDS } from "./config-types.js";
|
|
|
26
27
|
// Canonical taxonomy lives in the schema/validator layer; re-exported here so
|
|
27
28
|
// existing `../core/config/config` import sites keep working.
|
|
28
29
|
export { FEEDBACK_FAILURE_MODES } from "./config-schema.js";
|
|
29
|
-
/**
|
|
30
|
-
* Default value for {@link IndexPassConfig.graphExtractionBatchSize}. Chosen
|
|
31
|
-
* empirically: 4 amortises the per-call HTTP overhead 4× while keeping the
|
|
32
|
-
* combined prompt size well under common 8K/16K context windows (each body is
|
|
33
|
-
* sliced to ~500 chars in the graph-extract prompt builder).
|
|
34
|
-
*/
|
|
35
|
-
export const DEFAULT_GRAPH_EXTRACTION_BATCH_SIZE = 4;
|
|
36
|
-
/**
|
|
37
|
-
* Approximate character budget per asset body inside a batched
|
|
38
|
-
* graph-extraction prompt — used by {@link resolveBatchSize} to derive a
|
|
39
|
-
* context-window ceiling when `llm.contextLength` is configured. This accounts
|
|
40
|
-
* for the actual `MAX_BODY_CHARS` (500) in graph-extract.ts plus the system
|
|
41
|
-
* prompt, user prompt wrapper, and expected JSON response overhead.
|
|
42
|
-
*/
|
|
43
|
-
const GRAPH_EXTRACTION_CHARS_PER_BODY = 1500;
|
|
44
|
-
/**
|
|
45
|
-
* Clamp a configured batch size against the model's known context window.
|
|
46
|
-
*
|
|
47
|
-
* `configured` defaults to {@link DEFAULT_GRAPH_EXTRACTION_BATCH_SIZE} when
|
|
48
|
-
* `undefined`. When `contextLength` is provided, the result is the smaller of
|
|
49
|
-
* `configured` and `floor(contextLength / GRAPH_EXTRACTION_CHARS_PER_BODY)`,
|
|
50
|
-
* with a floor of 1 so the batched path always processes at least one body.
|
|
51
|
-
*/
|
|
52
|
-
export function resolveBatchSize(configured, contextLength) {
|
|
53
|
-
const base = configured && configured > 0 ? configured : DEFAULT_GRAPH_EXTRACTION_BATCH_SIZE;
|
|
54
|
-
if (!contextLength || contextLength <= 0)
|
|
55
|
-
return base;
|
|
56
|
-
const ceiling = Math.max(1, Math.floor(contextLength / GRAPH_EXTRACTION_CHARS_PER_BODY));
|
|
57
|
-
return Math.max(1, Math.min(base, ceiling));
|
|
58
|
-
}
|
|
59
30
|
// ── Defaults ────────────────────────────────────────────────────────────────
|
|
60
31
|
export const DEFAULT_CONFIG = {
|
|
61
32
|
configVersion: "0.9.0",
|
|
@@ -124,39 +95,39 @@ export function loadUserConfig() {
|
|
|
124
95
|
};
|
|
125
96
|
return finalConfig;
|
|
126
97
|
}
|
|
127
|
-
/**
|
|
128
|
-
* Acquire the existing config-write sentinel and read a fresh validated
|
|
129
|
-
* generation while keeping the sentinel held. Source update uses this to
|
|
130
|
-
* fence an audited bundle descriptor through publication: a cooperating
|
|
131
|
-
* config writer can commit either before this snapshot or after the update,
|
|
132
|
-
* never between the final generation check and index commit.
|
|
133
|
-
*/
|
|
134
|
-
export function acquireConfigReadFence() {
|
|
135
|
-
const release = acquireConfigLock();
|
|
136
|
-
try {
|
|
137
|
-
cachedConfig = undefined;
|
|
138
|
-
return { config: loadUserConfig(), release };
|
|
139
|
-
}
|
|
140
|
-
catch (error) {
|
|
141
|
-
release();
|
|
142
|
-
throw error;
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
98
|
/**
|
|
146
99
|
* Run the per-file config pipeline every raw config object goes through
|
|
147
100
|
* before it is either validated (the local/top-level file) or merged in as
|
|
148
|
-
* an `extends` base: JSONC parse already done by the caller, then
|
|
149
|
-
*
|
|
150
|
-
*
|
|
151
|
-
* (
|
|
152
|
-
*
|
|
153
|
-
*
|
|
101
|
+
* an `extends` base: JSONC parse already done by the caller, then the
|
|
102
|
+
* `configVersion` read ({@link readConfigVersion}), then the legacy
|
|
103
|
+
* `stashDir`/`sources[]`/`installed[]` shim, then the legacy `extraParams`
|
|
104
|
+
* lift (#852). Unknown keys are not an error: the schema drops them in
|
|
105
|
+
* memory. Shared by {@link parseAndValidateConfigText} (the local file) and
|
|
106
|
+
* {@link resolveExtendsChain} (each base in the chain) so a fleet-shared base
|
|
107
|
+
* config can carry its own `configVersion` / legacy shape independently of
|
|
108
|
+
* the file that extends it.
|
|
154
109
|
*/
|
|
155
110
|
function runConfigFilePipeline(text, sourcePath) {
|
|
156
|
-
const versioned =
|
|
111
|
+
const versioned = readConfigVersion(parseConfigText(text, sourcePath), sourcePath);
|
|
157
112
|
const parsedRaw = migrateLegacySourceShape(versioned, sourcePath);
|
|
158
113
|
return liftExtraParamsOrThrow(parsedRaw, sourcePath);
|
|
159
114
|
}
|
|
115
|
+
/**
|
|
116
|
+
* `configVersion` is read, never gated on. `"0.9.0"` is the only value akm
|
|
117
|
+
* has ever shipped, and a document without the field is that same document.
|
|
118
|
+
* Any other value is named once and the file is read as the current shape
|
|
119
|
+
* anyway; every ordinary config write and `akm migrate apply`'s `configFile`
|
|
120
|
+
* step then persist `"0.9.0"`.
|
|
121
|
+
*/
|
|
122
|
+
function readConfigVersion(raw, sourcePath) {
|
|
123
|
+
const version = raw.configVersion;
|
|
124
|
+
if (version === CURRENT_CONFIG_VERSION)
|
|
125
|
+
return raw;
|
|
126
|
+
if (version !== undefined) {
|
|
127
|
+
warnOnce(`config:config-version${sourcePath ? `:${sourcePath}` : ""}`, `${sourcePath ?? "config.json"} declares configVersion ${JSON.stringify(version)}; this release reads it as ${CURRENT_CONFIG_VERSION}.`);
|
|
128
|
+
}
|
|
129
|
+
return { ...raw, configVersion: CURRENT_CONFIG_VERSION };
|
|
130
|
+
}
|
|
160
131
|
/**
|
|
161
132
|
* #852 (following #815): a config still using legacy `extraParams` keys —
|
|
162
133
|
* e.g. `reasoning_effort`, a documented 0.9.1 workaround — needs to be
|
|
@@ -192,49 +163,74 @@ function liftExtraParamsOrThrow(parsedRaw, sourcePath) {
|
|
|
192
163
|
* keeps around, instead of only getting the final merged `AkmConfig` back.
|
|
193
164
|
*/
|
|
194
165
|
function buildEffectiveConfig(liftedLocalRaw, sourcePath) {
|
|
195
|
-
warnUnknownTopLevelConfigKeys(liftedLocalRaw, sourcePath);
|
|
196
166
|
const withExtends = resolveExtendsChain(liftedLocalRaw, sourcePath);
|
|
197
167
|
const where = sourcePath ? ` at ${sourcePath}` : "";
|
|
168
|
+
warnUnknownConfigKeys(liftedLocalRaw, sourcePath);
|
|
198
169
|
const parsed = AkmConfigSchema.safeParse(withExtends);
|
|
199
170
|
if (!parsed.success) {
|
|
200
171
|
const lines = parsed.error.issues.map((i) => ` - ${i.path.join(".") || "(root)"}: ${i.message}`).join("\n");
|
|
201
|
-
|
|
202
|
-
throw new ConfigError(`Invalid config${where}:\n${lines}`, "INVALID_CONFIG_FILE", needsSchedulerMigration
|
|
203
|
-
? "Run `akm migrate apply` to bind existing scheduler grants to their source."
|
|
204
|
-
: undefined);
|
|
172
|
+
throw new ConfigError(`Invalid config${where}:\n${lines}`, "INVALID_CONFIG_FILE");
|
|
205
173
|
}
|
|
206
174
|
const merged = deepMergeConfig(DEFAULT_CONFIG, parsed.data);
|
|
207
175
|
const finalResult = AkmConfigSchema.safeParse(merged);
|
|
208
176
|
if (!finalResult.success) {
|
|
209
177
|
const lines = finalResult.error.issues.map((i) => ` - ${i.path.join(".") || "(root)"}: ${i.message}`).join("\n");
|
|
210
|
-
|
|
211
|
-
throw new ConfigError(`Invalid merged config${sourcePath ? ` at ${sourcePath}` : ""}:\n${lines}`, "INVALID_CONFIG_FILE", needsSchedulerMigration
|
|
212
|
-
? "Run `akm migrate apply` to bind existing scheduler grants to their source."
|
|
213
|
-
: undefined);
|
|
178
|
+
throw new ConfigError(`Invalid merged config${sourcePath ? ` at ${sourcePath}` : ""}:\n${lines}`, "INVALID_CONFIG_FILE");
|
|
214
179
|
}
|
|
215
180
|
assertUniquePhysicalBundleRoots(finalResult.data, sourcePath);
|
|
216
181
|
return finalResult.data;
|
|
217
182
|
}
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
183
|
+
/**
|
|
184
|
+
* Retired `index.<passName>` keys that still validate against the generic
|
|
185
|
+
* per-pass catchall schema (`IndexPassConfigSchema`), so `resolveSchemaAt`
|
|
186
|
+
* below never returns `undefined` for them and the walk would otherwise
|
|
187
|
+
* treat them as a live, ordinary pass. Named here so the same three
|
|
188
|
+
* guarantees apply as any other retired config key (AGENTS.md "Reading
|
|
189
|
+
* persisted data"): a config setting one keeps loading, is named once by
|
|
190
|
+
* the unknown-key warning, and is dropped only by `akm migrate apply`.
|
|
191
|
+
* Both were retired in 0.9.17-alpha.9: `index.graph` (the LLM entity-graph
|
|
192
|
+
* extraction pass) and `index.metadataEnhance` (LLM metadata enrichment).
|
|
193
|
+
*/
|
|
194
|
+
const RETIRED_CATCHALL_KEY_PATHS = new Set(["index.graph", "index.metadataEnhance"]);
|
|
195
|
+
/**
|
|
196
|
+
* Every dotted key in `raw` the schema does not know, at any depth (arrays
|
|
197
|
+
* are not descended). Unknown keys are never an error: they are a typo, or a
|
|
198
|
+
* key another release used. Reads keep them (they round-trip through
|
|
199
|
+
* ordinary writes, so a newer release's settings survive a downgrade);
|
|
200
|
+
* `akm migrate apply` drops them.
|
|
201
|
+
*/
|
|
202
|
+
export function unknownConfigKeyPaths(root, node = root, prefix = []) {
|
|
203
|
+
const found = [];
|
|
204
|
+
for (const key of Object.keys(node).sort()) {
|
|
205
|
+
const keyPath = [...prefix, key];
|
|
206
|
+
if (RETIRED_CATCHALL_KEY_PATHS.has(keyPath.join(".")) || resolveSchemaAt(keyPath, root) === undefined) {
|
|
207
|
+
found.push(keyPath);
|
|
235
208
|
continue;
|
|
236
|
-
|
|
209
|
+
}
|
|
210
|
+
const value = node[key];
|
|
211
|
+
if (isPlainConfigObject(value))
|
|
212
|
+
found.push(...unknownConfigKeyPaths(root, value, keyPath));
|
|
213
|
+
}
|
|
214
|
+
return found;
|
|
215
|
+
}
|
|
216
|
+
function warnUnknownConfigKeys(raw, sourcePath) {
|
|
217
|
+
for (const keyPath of unknownConfigKeyPaths(raw)) {
|
|
218
|
+
const dotted = keyPath.join(".");
|
|
219
|
+
warnOnce(`config:unknown-key:${sourcePath ?? "inline"}:${dotted}`, `Unknown config key ${JSON.stringify(dotted)}${sourcePath ? ` at ${sourcePath}` : ""} has no defined akm behavior and is ignored. Check the spelling; a key retired by this release or added by a newer one is dropped by \`akm migrate apply\`.`);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
function deleteConfigPath(node, keyPath) {
|
|
223
|
+
let cursor = node;
|
|
224
|
+
for (const segment of keyPath.slice(0, -1)) {
|
|
225
|
+
if (!isPlainConfigObject(cursor))
|
|
226
|
+
return;
|
|
227
|
+
cursor = cursor[segment];
|
|
237
228
|
}
|
|
229
|
+
if (isPlainConfigObject(cursor))
|
|
230
|
+
delete cursor[keyPath[keyPath.length - 1]];
|
|
231
|
+
}
|
|
232
|
+
function isPlainConfigObject(value) {
|
|
233
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
238
234
|
}
|
|
239
235
|
function assertUniquePhysicalBundleRoots(config, sourcePath) {
|
|
240
236
|
const owners = new Map();
|
|
@@ -250,11 +246,10 @@ function assertUniquePhysicalBundleRoots(config, sourcePath) {
|
|
|
250
246
|
* Parse raw config text and validate via Zod.
|
|
251
247
|
* ({@link AkmConfigSchema}). Returns the merged-with-defaults AkmConfig.
|
|
252
248
|
*
|
|
253
|
-
*
|
|
254
|
-
*
|
|
255
|
-
*
|
|
256
|
-
*
|
|
257
|
-
* deep-merged underneath before validation — see {@link resolveExtendsChain}.
|
|
249
|
+
* `configVersion` is read as the current version whatever it says (see
|
|
250
|
+
* {@link readConfigVersion}). When the config sets `extends` (#945), its
|
|
251
|
+
* resolved chain is deep-merged underneath before validation — see
|
|
252
|
+
* {@link resolveExtendsChain}.
|
|
258
253
|
*/
|
|
259
254
|
export function parseAndValidateConfigText(text, sourcePath) {
|
|
260
255
|
const liftedConfig = runConfigFilePipeline(text, sourcePath);
|
|
@@ -287,7 +282,7 @@ function collectExtendsLayers(localRaw, configPath) {
|
|
|
287
282
|
}
|
|
288
283
|
visited.add(resolvedPath);
|
|
289
284
|
const baseRaw = runConfigFilePipeline(text, resolvedPath);
|
|
290
|
-
|
|
285
|
+
warnUnknownConfigKeys(baseRaw, resolvedPath);
|
|
291
286
|
layers.push({ ref, raw: baseRaw });
|
|
292
287
|
current = baseRaw;
|
|
293
288
|
currentPath = resolvedPath;
|
|
@@ -663,6 +658,46 @@ function configWriteBody(localRaw, current, next, persistTopLevelKeys = []) {
|
|
|
663
658
|
}
|
|
664
659
|
return ordered;
|
|
665
660
|
}
|
|
661
|
+
/**
|
|
662
|
+
* The migrator's one config step. The reader already tolerates every shape
|
|
663
|
+
* akm has written (`configVersion` read as current, legacy source layout,
|
|
664
|
+
* `extraParams` lift, unknown keys dropped); this writes that current shape back to
|
|
665
|
+
* `config.json` — the same body `mutateConfig` writes — so the tolerance
|
|
666
|
+
* becomes durable. Reports without writing unless `apply` is set.
|
|
667
|
+
*/
|
|
668
|
+
export function normalizeConfigFile(configPath, options) {
|
|
669
|
+
return withConfigLock(() => {
|
|
670
|
+
const text = readConfigText(configPath);
|
|
671
|
+
if (text === undefined)
|
|
672
|
+
return { keys: [], changed: false, applied: false };
|
|
673
|
+
const raw = parseConfigText(text, configPath);
|
|
674
|
+
const localRaw = runConfigFilePipeline(text, configPath);
|
|
675
|
+
const current = buildEffectiveConfig(localRaw, configPath);
|
|
676
|
+
const next = validateCompleteConfig({ ...current, configVersion: CURRENT_CONFIG_VERSION });
|
|
677
|
+
const body = withSchedulerOnDisk(configWriteBody(localRaw, current, next), next);
|
|
678
|
+
for (const keyPath of unknownConfigKeyPaths(body))
|
|
679
|
+
deleteConfigPath(body, keyPath);
|
|
680
|
+
// `improve.strategies["graph-refresh"]` is schema-valid (any name is a
|
|
681
|
+
// legal custom-strategy key), so it never reaches the unknown-key sweep
|
|
682
|
+
// above. It can only be a leftover override of the deleted graph-refresh
|
|
683
|
+
// built-in (0.9.17-alpha.9) — resolveImproveStrategy now refuses that
|
|
684
|
+
// name unconditionally, so the override can never apply again. Drop it
|
|
685
|
+
// the same way any other retired key is dropped: only by `akm migrate
|
|
686
|
+
// apply`, never by an ordinary write.
|
|
687
|
+
const strategies = body.improve?.strategies;
|
|
688
|
+
if (strategies && Object.hasOwn(strategies, "graph-refresh"))
|
|
689
|
+
delete strategies["graph-refresh"];
|
|
690
|
+
const keys = [...new Set([...Object.keys(raw), ...Object.keys(body)])]
|
|
691
|
+
.filter((key) => JSON.stringify(raw[key]) !== JSON.stringify(body[key]))
|
|
692
|
+
.sort();
|
|
693
|
+
if (keys.length === 0 || !options.apply)
|
|
694
|
+
return { keys, changed: keys.length > 0, applied: false };
|
|
695
|
+
const backup = backupExistingConfig(configPath);
|
|
696
|
+
writeConfigAtomic(configPath, body);
|
|
697
|
+
cachedConfig = undefined;
|
|
698
|
+
return { keys, changed: true, applied: true, ...(backup ? { backupPath: backup.timestamped } : {}) };
|
|
699
|
+
});
|
|
700
|
+
}
|
|
666
701
|
/**
|
|
667
702
|
* Mutate config under one fail-closed lock spanning read, merge, validation,
|
|
668
703
|
* ordinary backup, and atomic write.
|
|
@@ -716,6 +751,61 @@ export async function mutateConfigWithPrecommit(mutate, precommit, options) {
|
|
|
716
751
|
release();
|
|
717
752
|
}
|
|
718
753
|
}
|
|
754
|
+
const UNBOUND_SCHEDULER_SOURCE_ID = `sha256:${"0".repeat(64)}`;
|
|
755
|
+
/**
|
|
756
|
+
* The source identity 0.9.16 bound a scheduler grant to: the configured
|
|
757
|
+
* bundle's source id, or the implicit `AKM_BUNDLE_DIR` stash's. `undefined`
|
|
758
|
+
* when the bundle is not active on this host.
|
|
759
|
+
*/
|
|
760
|
+
export function schedulerSourceIdFor(config, bundleId) {
|
|
761
|
+
if (isBundleEnabled(config, bundleId))
|
|
762
|
+
return bundleSourceId(config, bundleId);
|
|
763
|
+
if (config.bundles?.[bundleId] !== undefined || !process.env.AKM_BUNDLE_DIR?.trim())
|
|
764
|
+
return undefined;
|
|
765
|
+
try {
|
|
766
|
+
const root = resolveStashDir();
|
|
767
|
+
const implicitId = deriveBundleId(undefined, root, new Set(Object.keys(config.bundles ?? {})));
|
|
768
|
+
return implicitId === bundleId ? filesystemBundleSourceId(root) : undefined;
|
|
769
|
+
}
|
|
770
|
+
catch {
|
|
771
|
+
return undefined;
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
/**
|
|
775
|
+
* `scheduler.enabled` is a list of refs in memory but is written in the
|
|
776
|
+
* `{kind, ref, sourceId}` shape 0.9.16 reads, so that release still runs
|
|
777
|
+
* against a config this one wrote (the upgrade rehearsal's read-back). This
|
|
778
|
+
* release reads either shape; the object form can go once no supported
|
|
779
|
+
* release is strict about it.
|
|
780
|
+
*/
|
|
781
|
+
function schedulerEnabledOnDisk(config) {
|
|
782
|
+
const enabled = config.scheduler?.enabled;
|
|
783
|
+
if (enabled === undefined)
|
|
784
|
+
return undefined;
|
|
785
|
+
return enabled.map((ref) => {
|
|
786
|
+
let bundle;
|
|
787
|
+
let conceptId = "";
|
|
788
|
+
try {
|
|
789
|
+
const parsed = parseBundleRef(ref);
|
|
790
|
+
bundle = parsed.bundle;
|
|
791
|
+
conceptId = parsed.conceptId;
|
|
792
|
+
}
|
|
793
|
+
catch {
|
|
794
|
+
return ref;
|
|
795
|
+
}
|
|
796
|
+
return {
|
|
797
|
+
kind: conceptId.startsWith("workflows/") ? "workflow" : "task",
|
|
798
|
+
ref,
|
|
799
|
+
sourceId: (bundle !== undefined ? schedulerSourceIdFor(config, bundle) : undefined) ?? UNBOUND_SCHEDULER_SOURCE_ID,
|
|
800
|
+
};
|
|
801
|
+
});
|
|
802
|
+
}
|
|
803
|
+
function withSchedulerOnDisk(body, config) {
|
|
804
|
+
const onDisk = schedulerEnabledOnDisk(config);
|
|
805
|
+
if (onDisk === undefined || !isPlainConfigObject(body.scheduler))
|
|
806
|
+
return body;
|
|
807
|
+
return { ...body, scheduler: { ...body.scheduler, enabled: onDisk } };
|
|
808
|
+
}
|
|
719
809
|
/**
|
|
720
810
|
* Strip literal apiKey fields before writing config to disk.
|
|
721
811
|
* API keys are expected to come from environment variables
|
|
@@ -780,7 +870,7 @@ export function sanitizeConfigForWrite(config) {
|
|
|
780
870
|
warn(`Config sanitizer dropped registry entr${droppedRegistries.length === 1 ? "y" : "ies"} with URL credentials before writing to disk:\n - ${droppedRegistries.join("\n - ")}\n\nRegistry URLs must be credential-free; configure a credential-free HTTPS endpoint.`);
|
|
781
871
|
}
|
|
782
872
|
}
|
|
783
|
-
return sanitized;
|
|
873
|
+
return withSchedulerOnDisk(sanitized, config);
|
|
784
874
|
}
|
|
785
875
|
export function updateConfig(partial) {
|
|
786
876
|
return mutateConfig((current) => deepMergeConfig(current, partial)).config;
|
|
@@ -830,23 +920,6 @@ export function resolveSecret(value, resolveFromStore) {
|
|
|
830
920
|
return resolved ?? "";
|
|
831
921
|
});
|
|
832
922
|
}
|
|
833
|
-
/**
|
|
834
|
-
* Read a per-pass {@link IndexPassConfig} entry from {@link IndexConfig},
|
|
835
|
-
* filtering out the reserved feature-section keys so callers don't mistake
|
|
836
|
-
* `metadataEnhance` for a pass.
|
|
837
|
-
*/
|
|
838
|
-
/** Reserved well-known keys on IndexConfig that are NOT per-pass entries. */
|
|
839
|
-
const INDEX_RESERVED_KEYS = new Set(["metadataEnhance"]);
|
|
840
|
-
export function getIndexPassConfig(config, passName) {
|
|
841
|
-
if (!config)
|
|
842
|
-
return undefined;
|
|
843
|
-
if (INDEX_RESERVED_KEYS.has(passName))
|
|
844
|
-
return undefined;
|
|
845
|
-
const entry = config[passName];
|
|
846
|
-
if (!entry || typeof entry !== "object")
|
|
847
|
-
return undefined;
|
|
848
|
-
return entry;
|
|
849
|
-
}
|
|
850
923
|
// Re-export source runtime helpers — implementation lives in config-sources.ts.
|
|
851
924
|
export { bundleComponentConfig, bundleContentRoot, bundleContentRoots, bundleEntryToSourceEntry, bundleKeyForContentRoot, bundlePhysicalContentRoot, bundleSourceId, bundlesToSourceEntries, installedSourceDescriptor, isBundleEnabled, parseSourceSpec, primaryBundlePath, resolveActiveConfiguredSources, resolveConfiguredSources, } from "./config-sources.js";
|
|
852
925
|
/**
|
|
@@ -6,7 +6,6 @@ export const BUILTIN_IMPROVE_STRATEGY_NAMES = [
|
|
|
6
6
|
"default",
|
|
7
7
|
"quick",
|
|
8
8
|
"thorough",
|
|
9
|
-
"graph-refresh",
|
|
10
9
|
"consolidate",
|
|
11
10
|
"catchup",
|
|
12
11
|
"reflect-distill",
|
|
@@ -18,7 +17,6 @@ export const IMPROVE_PROCESS_ENGINE_CAPABILITIES = {
|
|
|
18
17
|
distill: "llm",
|
|
19
18
|
consolidate: "llm",
|
|
20
19
|
memoryInference: "llm",
|
|
21
|
-
graphExtraction: "llm",
|
|
22
20
|
extract: "llm",
|
|
23
21
|
validation: "llm",
|
|
24
22
|
triage: "runner",
|
|
@@ -55,20 +55,29 @@ function filesystemLocator(bundle) {
|
|
|
55
55
|
return undefined;
|
|
56
56
|
return path.resolve(bundle.path);
|
|
57
57
|
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
58
|
+
/**
|
|
59
|
+
* Pure legacy `stashDir`/`sources[]`/`installed` -> `bundles`/`defaultBundle`
|
|
60
|
+
* conversion. Triggers on key *presence* (not on the value being usable), so
|
|
61
|
+
* an unusable value — `stashDir: ""`, `sources: []` — is still removed along
|
|
62
|
+
* with the rest of the legacy shape; only a usable `stashDir` or `sources[]`
|
|
63
|
+
* entry is actually folded into `bundles`. Never warns — see
|
|
64
|
+
* {@link migrateLegacySourceShape} for the warn-once wrapper callers use.
|
|
65
|
+
*/
|
|
66
|
+
export function convertLegacySourceShape(raw) {
|
|
67
|
+
const hasStashDir = "stashDir" in raw;
|
|
68
|
+
const hasSources = "sources" in raw;
|
|
61
69
|
const hasInstalled = "installed" in raw && raw.installed !== undefined;
|
|
62
70
|
if (!hasStashDir && !hasSources && !hasInstalled)
|
|
63
|
-
return raw;
|
|
71
|
+
return { config: raw, converted: [] };
|
|
64
72
|
const { stashDir: _stashDir, sources: _sources, installed: _installed, ...rest } = raw;
|
|
65
73
|
const bundles = isPlainRecord(rest.bundles) ? { ...rest.bundles } : {};
|
|
66
74
|
let defaultBundle = typeof rest.defaultBundle === "string" ? rest.defaultBundle : undefined;
|
|
67
|
-
|
|
75
|
+
const usableStashDir = typeof raw.stashDir === "string" && raw.stashDir.trim().length > 0;
|
|
76
|
+
if (usableStashDir) {
|
|
68
77
|
bundles.stash = { path: raw.stashDir, writable: true };
|
|
69
78
|
defaultBundle ??= "stash";
|
|
70
79
|
}
|
|
71
|
-
if (
|
|
80
|
+
if (Array.isArray(raw.sources)) {
|
|
72
81
|
raw.sources.forEach((entry, index) => {
|
|
73
82
|
const converted = bundleFromLegacySource(entry, index);
|
|
74
83
|
if (!converted)
|
|
@@ -81,8 +90,28 @@ export function migrateLegacySourceShape(raw, sourcePath) {
|
|
|
81
90
|
defaultBundle ??= key;
|
|
82
91
|
});
|
|
83
92
|
}
|
|
84
|
-
const
|
|
93
|
+
const converted = [hasStashDir && "stashDir", hasSources && "sources", hasInstalled && "installed"].filter((key) => typeof key === "string");
|
|
94
|
+
// Only add a `bundles` key when there is something to say: either a
|
|
95
|
+
// legacy entry actually converted into one, or the config already had a
|
|
96
|
+
// `bundles` map (preserved as-is). An unusable `stashDir: ""` / `sources: []`
|
|
97
|
+
// with no pre-existing `bundles` should just disappear, not leave behind
|
|
98
|
+
// an empty `bundles: {}`.
|
|
99
|
+
const hasBundles = Object.keys(bundles).length > 0 || isPlainRecord(rest.bundles);
|
|
100
|
+
return {
|
|
101
|
+
config: { ...rest, ...(hasBundles ? { bundles } : {}), ...(defaultBundle !== undefined ? { defaultBundle } : {}) },
|
|
102
|
+
converted,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Warn-once wrapper around {@link convertLegacySourceShape} for the
|
|
107
|
+
* in-memory read path: converts the legacy shape and, when it removed
|
|
108
|
+
* anything, warns once that `akm migrate apply` will persist the rewrite.
|
|
109
|
+
*/
|
|
110
|
+
export function migrateLegacySourceShape(raw, sourcePath) {
|
|
111
|
+
const { config, converted } = convertLegacySourceShape(raw);
|
|
112
|
+
if (converted.length === 0)
|
|
113
|
+
return config;
|
|
85
114
|
const where = sourcePath ? ` at ${sourcePath}` : "";
|
|
86
|
-
warnOnce(`legacy-source-shape${sourcePath ? `:${sourcePath}` : ""}`, `Config${where} uses the retired ${
|
|
87
|
-
return
|
|
115
|
+
warnOnce(`legacy-source-shape${sourcePath ? `:${sourcePath}` : ""}`, `Config${where} uses the retired ${converted.join("/")} shape — auto-migrated in memory to \`bundles\`/\`defaultBundle\`. Run \`akm migrate apply\` to rewrite the config file and silence this warning.`);
|
|
116
|
+
return config;
|
|
88
117
|
}
|
|
@@ -27,11 +27,7 @@ export const EmbeddingConnectionConfigSchema = z
|
|
|
27
27
|
endpoint: z.string().optional(),
|
|
28
28
|
model: z.string().optional(),
|
|
29
29
|
apiKey: symbolicOrWarnApiKey("embedding.apiKey").optional(),
|
|
30
|
-
|
|
31
|
-
// storage/repositories/index-schema.ts) so an out-of-range dimension
|
|
32
|
-
// fails at config validation with a clear message instead of crashing
|
|
33
|
-
// `akm index` when ensureSchema rejects it (§24.2 "Semantic" gate).
|
|
34
|
-
dimension: positiveInt.max(4096).optional(),
|
|
30
|
+
dimension: positiveInt.optional(),
|
|
35
31
|
localModel: z.string().min(1).optional(),
|
|
36
32
|
/**
|
|
37
33
|
* Per-document token cap applied BEFORE batching (default 512,
|
|
@@ -68,6 +64,25 @@ export const EmbeddingConnectionConfigSchema = z
|
|
|
68
64
|
* no retry — every batch that hit it was silently dropped (#954).
|
|
69
65
|
*/
|
|
70
66
|
timeoutMs: positiveInt.optional(),
|
|
67
|
+
/**
|
|
68
|
+
* How long search waits for the query embedding (default 3000,
|
|
69
|
+
* `DEFAULT_QUERY_EMBED_TIMEOUT_MS` in `src/indexer/search/db-search.ts`).
|
|
70
|
+
* On expiry the search is served by keyword ranking alone, with a warning.
|
|
71
|
+
*/
|
|
72
|
+
queryTimeoutMs: positiveInt.optional(),
|
|
73
|
+
/**
|
|
74
|
+
* Text sent to the model around a search query, `{text}` marking the
|
|
75
|
+
* query (a template without it is a prefix). Overrides the preset matched
|
|
76
|
+
* on the model name (`src/llm/embedders/profile.ts`); `""` sends the query
|
|
77
|
+
* as is.
|
|
78
|
+
*/
|
|
79
|
+
queryTemplate: z.string().optional(),
|
|
80
|
+
/**
|
|
81
|
+
* Text sent to the model around each document at index time, as
|
|
82
|
+
* `queryTemplate`. Part of the embedding fingerprint: changing it
|
|
83
|
+
* re-embeds the index.
|
|
84
|
+
*/
|
|
85
|
+
documentTemplate: z.string().optional(),
|
|
71
86
|
/**
|
|
72
87
|
* Overrides the fixed in-flight request window (#954, added after field
|
|
73
88
|
* evidence from multi-slot local servers). Bounded 1-16. Unset keeps
|
|
@@ -77,6 +77,11 @@ const LlmEngineSchema = z
|
|
|
77
77
|
maxTokens: positiveInt.optional(),
|
|
78
78
|
timeoutMs: timeoutMsField,
|
|
79
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(),
|
|
80
85
|
extraParams: ExtraParamsSchema.optional(),
|
|
81
86
|
contextLength: positiveInt.optional(),
|
|
82
87
|
enableThinking: z.boolean().optional(),
|