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
|
@@ -4,9 +4,8 @@
|
|
|
4
4
|
import fs from "node:fs";
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import { writeFileAtomic } from "../core/common.js";
|
|
7
|
-
import { ConfigError, rethrowIfTestIsolationError } from "../core/errors.js";
|
|
7
|
+
import { ConfigError, rethrowIfTestIsolationError, TransientError } from "../core/errors.js";
|
|
8
8
|
import { createLockPayload, probeLock, reclaimStaleLock, releaseLock, tryAcquireLockSync } from "../core/file-lock.js";
|
|
9
|
-
import { acquireMaintenanceBarrier } from "../core/maintenance-barrier.js";
|
|
10
9
|
import { classifyPathAccess, describeInaccessiblePath } from "../core/path-access.js";
|
|
11
10
|
import { getDataDir, getLockfileLockPath, getLockfilePath } from "../core/paths.js";
|
|
12
11
|
import { warn } from "../core/warn.js";
|
|
@@ -27,23 +26,18 @@ async function acquireLockSentinel() {
|
|
|
27
26
|
let delayMs = LOCK_RETRY_INITIAL_DELAY_MS;
|
|
28
27
|
let announced = false;
|
|
29
28
|
for (;;) {
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
if (ownership) {
|
|
34
|
-
return () => releaseLock(ownership);
|
|
35
|
-
}
|
|
36
|
-
const probe = probeLock(sentinelPath);
|
|
37
|
-
if (probe.state === "stale" && reclaimStaleLock(sentinelPath, probe)) {
|
|
38
|
-
continue; // Reclaimed — retry immediately.
|
|
39
|
-
}
|
|
29
|
+
const ownership = tryAcquireLockSync(sentinelPath, createLockPayload());
|
|
30
|
+
if (ownership) {
|
|
31
|
+
return () => releaseLock(ownership);
|
|
40
32
|
}
|
|
41
|
-
|
|
42
|
-
|
|
33
|
+
const probe = probeLock(sentinelPath);
|
|
34
|
+
if (probe.state === "stale" && reclaimStaleLock(sentinelPath, probe)) {
|
|
35
|
+
continue; // Reclaimed — retry immediately.
|
|
43
36
|
}
|
|
44
|
-
// Another process holds the lock
|
|
37
|
+
// Another process holds the lock: ordinary contention, exit 75, not a
|
|
38
|
+
// config error a supervisor should stop retrying on.
|
|
45
39
|
if (Date.now() >= deadline) {
|
|
46
|
-
throw new
|
|
40
|
+
throw new TransientError(`Could not acquire lockfile sentinel at ${sentinelPath} after ${(timeoutMs / 1000).toFixed(1)}s; refusing to write without exclusive ownership.`, "LOCKFILE_CONTENDED");
|
|
47
41
|
}
|
|
48
42
|
if (!announced) {
|
|
49
43
|
announced = true;
|
|
@@ -93,37 +87,33 @@ function assertLockfilePathReadable(target) {
|
|
|
93
87
|
"records, and writing over them would destroy every bundle they track. Fix the ownership or mode of that " +
|
|
94
88
|
"path (or point AKM_DATA_DIR / XDG_DATA_HOME somewhere this user owns) and retry.", "DATA_DIR_UNREADABLE");
|
|
95
89
|
}
|
|
96
|
-
|
|
90
|
+
/**
|
|
91
|
+
* Like {@link readLockfile}, but THROWS instead of silently degrading to `[]`
|
|
92
|
+
* when the on-disk lockfile exists yet cannot be read or parsed (R-012, #791).
|
|
93
|
+
*
|
|
94
|
+
* `readLockfile`'s fail-open contract is intentional for READ paths — a
|
|
95
|
+
* corrupt lock degrades a managed bundle to "unmanaged" rather than erroring
|
|
96
|
+
* every read-only command. But every writer below reads the current entries
|
|
97
|
+
* and writes the whole array back; if that read silently returned `[]` for a
|
|
98
|
+
* corrupt or unreadable file, the write would replace it with only the one
|
|
99
|
+
* entry being changed — permanently destroying every other lock record (a
|
|
100
|
+
* corrupt lockfile once wiped every entry this way). A missing file is NOT
|
|
101
|
+
* corruption: there is nothing to preserve, so that case returns `[]`.
|
|
102
|
+
*/
|
|
103
|
+
function readLockfileOrThrow() {
|
|
97
104
|
const lockfilePath = getLockfilePath();
|
|
98
|
-
let fd;
|
|
99
105
|
let raw;
|
|
100
|
-
let mode;
|
|
101
106
|
try {
|
|
102
|
-
|
|
103
|
-
// chmod between separate path-based calls cannot synthesize a generation
|
|
104
|
-
// that never existed on disk.
|
|
105
|
-
fd = fs.openSync(lockfilePath, "r");
|
|
106
|
-
raw = fs.readFileSync(fd, "utf8");
|
|
107
|
-
mode = fs.fstatSync(fd).mode & 0o777;
|
|
107
|
+
raw = fs.readFileSync(lockfilePath, "utf8");
|
|
108
108
|
}
|
|
109
109
|
catch (err) {
|
|
110
110
|
rethrowIfTestIsolationError(err);
|
|
111
|
-
if (err.code === "ENOENT")
|
|
112
|
-
return
|
|
113
|
-
|
|
114
|
-
//
|
|
115
|
-
// UNREADABLE lockfile has everything to preserve and we cannot see it —
|
|
116
|
-
// degrading it to `[]` here is precisely the destructive overwrite this
|
|
117
|
-
// function was written to prevent, only triggered by a permission fault
|
|
118
|
-
// instead of a corrupt file (#791). Classify AFTER the failed read so the
|
|
119
|
-
// happy path costs no extra syscall and the answer describes the failure
|
|
120
|
-
// we actually got.
|
|
111
|
+
if (err.code === "ENOENT")
|
|
112
|
+
return [];
|
|
113
|
+
// An UNREADABLE lockfile has everything to preserve and we cannot see it.
|
|
114
|
+
// Classify AFTER the failed read so the happy path costs no extra syscall.
|
|
121
115
|
assertLockfilePathReadable(lockfilePath);
|
|
122
|
-
return
|
|
123
|
-
}
|
|
124
|
-
finally {
|
|
125
|
-
if (fd !== undefined)
|
|
126
|
-
fs.closeSync(fd);
|
|
116
|
+
return [];
|
|
127
117
|
}
|
|
128
118
|
let parsed;
|
|
129
119
|
try {
|
|
@@ -145,23 +135,7 @@ function readLockfileSnapshotOrThrow() {
|
|
|
145
135
|
throw new ConfigError(`Refusing to modify lockfile ${lockfilePath}: ${invalid.length} existing entr${invalid.length === 1 ? "y is" : "ies are"} malformed. ` +
|
|
146
136
|
"Fix or remove the file by hand before retrying — those entries would otherwise be lost.", "INVALID_CONFIG_FILE");
|
|
147
137
|
}
|
|
148
|
-
return
|
|
149
|
-
entries: parsed.filter(isValidLockfileEntry),
|
|
150
|
-
raw,
|
|
151
|
-
mode,
|
|
152
|
-
};
|
|
153
|
-
}
|
|
154
|
-
function readLockfileOrThrow() {
|
|
155
|
-
return readLockfileSnapshotOrThrow().entries;
|
|
156
|
-
}
|
|
157
|
-
/**
|
|
158
|
-
* Read the exact lock generation that a source-lifecycle transaction may
|
|
159
|
-
* replace. Unlike {@link readLockfile}, this refuses corrupt, malformed, or
|
|
160
|
-
* unreadable state so an update can never treat state it could not snapshot as
|
|
161
|
-
* an empty generation.
|
|
162
|
-
*/
|
|
163
|
-
export function readLockfileForUpdate() {
|
|
164
|
-
return readLockfileSnapshotOrThrow();
|
|
138
|
+
return parsed;
|
|
165
139
|
}
|
|
166
140
|
/**
|
|
167
141
|
* The materialized content root recorded in the lock for a managed (git/npm)
|
|
@@ -201,66 +175,44 @@ export async function writeLockfile(entries) {
|
|
|
201
175
|
release();
|
|
202
176
|
}
|
|
203
177
|
}
|
|
204
|
-
|
|
205
|
-
* Publish an update from one exact raw + parsed lockfile generation and return
|
|
206
|
-
* the exact bytes that were written. Formatting-only concurrent edits are a
|
|
207
|
-
* generation change here: rollback must never overwrite bytes it did not
|
|
208
|
-
* publish merely because they parse to an equivalent array.
|
|
209
|
-
*/
|
|
210
|
-
export async function publishLockfileUpdate(expected, desired) {
|
|
178
|
+
export async function upsertLockEntry(entry) {
|
|
211
179
|
const release = await acquireLockSentinel();
|
|
212
180
|
try {
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
writeLockfileUnlocked(desired);
|
|
220
|
-
return readLockfileSnapshotOrThrow();
|
|
181
|
+
// R-012: readLockfileOrThrow (not readLockfile) — a corrupt/malformed
|
|
182
|
+
// lockfile must abort the upsert loudly rather than read as `[]` and get
|
|
183
|
+
// silently overwritten with just this one entry.
|
|
184
|
+
const entries = readLockfileOrThrow();
|
|
185
|
+
const withoutExisting = entries.filter((e) => e.id !== entry.id);
|
|
186
|
+
writeLockfileUnlocked([...withoutExisting, entry]);
|
|
221
187
|
}
|
|
222
188
|
finally {
|
|
223
189
|
release();
|
|
224
190
|
}
|
|
225
191
|
}
|
|
226
|
-
/**
|
|
227
|
-
|
|
192
|
+
/**
|
|
193
|
+
* Rename a lock entry's id in place (D6 — `akm bundle rename`), keeping every
|
|
194
|
+
* other resolved field (`localRoot`, `resolvedVersion`, …) unchanged. Returns
|
|
195
|
+
* `true` when an entry for `oldId` existed and was renamed, `false` when
|
|
196
|
+
* there was nothing to rename (e.g. a filesystem bundle, which has no lock
|
|
197
|
+
* entry).
|
|
198
|
+
*/
|
|
199
|
+
export async function renameLockEntry(oldId, newId) {
|
|
228
200
|
const release = await acquireLockSentinel();
|
|
229
201
|
try {
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
202
|
+
// R-012: see upsertLockEntry — a corrupt lockfile must abort loudly
|
|
203
|
+
// rather than read as `[]` and get silently overwritten.
|
|
204
|
+
const entries = readLockfileOrThrow();
|
|
205
|
+
const existing = entries.find((e) => e.id === oldId);
|
|
206
|
+
if (!existing)
|
|
234
207
|
return false;
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
if (desired.raw === null) {
|
|
238
|
-
fs.rmSync(lockfilePath, { force: true });
|
|
239
|
-
}
|
|
240
|
-
else {
|
|
241
|
-
fs.mkdirSync(path.dirname(lockfilePath), { recursive: true });
|
|
242
|
-
writeFileAtomic(lockfilePath, desired.raw, desired.mode);
|
|
243
|
-
}
|
|
208
|
+
const renamed = entries.map((e) => (e.id === oldId ? { ...e, id: newId } : e));
|
|
209
|
+
writeLockfileUnlocked(renamed);
|
|
244
210
|
return true;
|
|
245
211
|
}
|
|
246
212
|
finally {
|
|
247
213
|
release();
|
|
248
214
|
}
|
|
249
215
|
}
|
|
250
|
-
export async function upsertLockEntry(entry) {
|
|
251
|
-
const release = await acquireLockSentinel();
|
|
252
|
-
try {
|
|
253
|
-
// R-012: readLockfileOrThrow (not readLockfile) — a corrupt/malformed
|
|
254
|
-
// lockfile must abort the upsert loudly rather than read as `[]` and get
|
|
255
|
-
// silently overwritten with just this one entry.
|
|
256
|
-
const entries = readLockfileOrThrow();
|
|
257
|
-
const withoutExisting = entries.filter((e) => e.id !== entry.id);
|
|
258
|
-
writeLockfileUnlocked([...withoutExisting, entry]);
|
|
259
|
-
}
|
|
260
|
-
finally {
|
|
261
|
-
release();
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
216
|
export async function removeLockEntry(id) {
|
|
265
217
|
// Returning early says "there is no lock record to remove", and the uninstall
|
|
266
218
|
// that called us reports success on that basis. Only an absent data dir earns
|
package/dist/llm/client.js
CHANGED
|
@@ -101,10 +101,9 @@ function retryBackoffMs() {
|
|
|
101
101
|
* narrating about a document) does not get misclassified as a provider
|
|
102
102
|
* context-limit error (#496).
|
|
103
103
|
*
|
|
104
|
-
* Canonical home: `
|
|
105
|
-
*
|
|
106
|
-
*
|
|
107
|
-
* must never be retried.
|
|
104
|
+
* Canonical home: `structured-call.ts`'s failure classifier and the retry
|
|
105
|
+
* classifier (`isRetryable`) here share one definition — retrying a context
|
|
106
|
+
* overflow cannot shrink the input, so it must never be retried.
|
|
108
107
|
*/
|
|
109
108
|
export function isContextSizeError(message) {
|
|
110
109
|
const lower = message.toLowerCase();
|
|
@@ -117,12 +116,23 @@ export function isContextSizeError(message) {
|
|
|
117
116
|
/exceeded|over.*limit|too.*long/.test(lower);
|
|
118
117
|
return evidence;
|
|
119
118
|
}
|
|
119
|
+
/**
|
|
120
|
+
* Codes describing a failure to reach or get a usable response from the
|
|
121
|
+
* provider transport itself, as opposed to a malformed-but-received response
|
|
122
|
+
* (`parse_error`) or a request-shape rejection (`rate_limited`). Used by
|
|
123
|
+
* {@link isRetryable}, which additionally requires evidence the failure is
|
|
124
|
+
* transient. Not exported — its one external caller (batched LLM
|
|
125
|
+
* entity-graph extraction) was retired in 0.9.17-alpha.9.
|
|
126
|
+
*/
|
|
127
|
+
function isTransportFailure(err) {
|
|
128
|
+
return err.code === "provider_error" || err.code === "network_error" || err.code === "provider_html_error";
|
|
129
|
+
}
|
|
120
130
|
/**
|
|
121
131
|
* Decide whether a first-attempt {@link LlmCallError} is eligible for a single
|
|
122
132
|
* retry. Retryable: HTTP 5xx (`provider_error` with statusCode >= 500) and
|
|
123
133
|
* `network_error` whose message looks like a transient connection drop.
|
|
124
|
-
* NOT retryable: 4xx, `rate_limited` (429), `timeout`, `parse_error`,
|
|
125
|
-
* context-overflow-classified errors.
|
|
134
|
+
* NOT retryable: 4xx, `rate_limited` (429), `timeout`, `parse_error`,
|
|
135
|
+
* `provider_html_error`, and context-overflow-classified errors.
|
|
126
136
|
*
|
|
127
137
|
* The connection-drop heuristic covers the substrings emitted across runtimes
|
|
128
138
|
* for a mid-flight socket close:
|
|
@@ -141,6 +151,8 @@ export function isContextSizeError(message) {
|
|
|
141
151
|
function isRetryable(err) {
|
|
142
152
|
if (isContextSizeError(err.message))
|
|
143
153
|
return false;
|
|
154
|
+
if (!isTransportFailure(err))
|
|
155
|
+
return false;
|
|
144
156
|
if (err.code === "provider_error") {
|
|
145
157
|
return typeof err.statusCode === "number" && err.statusCode >= 500;
|
|
146
158
|
}
|
|
@@ -4,9 +4,8 @@
|
|
|
4
4
|
/** Env var that switches the whole embedding facade into deterministic mode. */
|
|
5
5
|
export const DETERMINISTIC_EMBED_ENV = "AKM_EMBED_DETERMINISTIC";
|
|
6
6
|
/**
|
|
7
|
-
* Vector width. Matches the default local model (`bge-small`, 384 dims) so
|
|
8
|
-
* index
|
|
9
|
-
* any extra config.
|
|
7
|
+
* Vector width. Matches the default local model (`bge-small`, 384 dims), so a
|
|
8
|
+
* deterministic index is the same shape as a default local one.
|
|
10
9
|
*/
|
|
11
10
|
export const DETERMINISTIC_EMBED_DIM = 384;
|
|
12
11
|
/**
|
|
@@ -0,0 +1,71 @@
|
|
|
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
|
+
* Embedding profile: the text an embedding model expects around a query and
|
|
6
|
+
* around a document. Retrieval models are trained with these prompts, and
|
|
7
|
+
* sending raw text costs recall — Qwen3-Embedding without its query
|
|
8
|
+
* instruction lost 0.096 nDCG@10 on the retrieval suite.
|
|
9
|
+
*
|
|
10
|
+
* Presets are matched on the model name; `embedding.queryTemplate` and
|
|
11
|
+
* `embedding.documentTemplate` override them (an empty string means none).
|
|
12
|
+
* `{text}` marks where the text goes; a template without it is a prefix.
|
|
13
|
+
*/
|
|
14
|
+
import { createHash } from "node:crypto";
|
|
15
|
+
import { isDeterministicEmbedEnabled } from "./deterministic.js";
|
|
16
|
+
import { DEFAULT_LOCAL_MODEL } from "./local.js";
|
|
17
|
+
const RETRIEVAL_QUERY_PREFIX = "Represent this sentence for searching relevant passages: {text}";
|
|
18
|
+
const PRESETS = [
|
|
19
|
+
{
|
|
20
|
+
model: /qwen3-embedding/i,
|
|
21
|
+
profile: {
|
|
22
|
+
queryTemplate: "Instruct: Given a question or task, retrieve the knowledge asset that helps with it\nQuery:{text}",
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
model: /nomic-embed/i,
|
|
27
|
+
profile: { queryTemplate: "search_query: {text}", documentTemplate: "search_document: {text}" },
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
model: /bge-(?:small|base|large)-en|mxbai-embed|arctic-embed/i,
|
|
31
|
+
profile: { queryTemplate: RETRIEVAL_QUERY_PREFIX },
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
model: /(?:^|[^a-z0-9])e5-(?:small|base|large)(?!.*instruct)/i,
|
|
35
|
+
profile: { queryTemplate: "query: {text}", documentTemplate: "passage: {text}" },
|
|
36
|
+
},
|
|
37
|
+
];
|
|
38
|
+
/** The model a config embeds with, as the presets match it. */
|
|
39
|
+
function embeddingModelName(config) {
|
|
40
|
+
if (config?.endpoint)
|
|
41
|
+
return config.model ?? "";
|
|
42
|
+
return config?.localModel ?? DEFAULT_LOCAL_MODEL;
|
|
43
|
+
}
|
|
44
|
+
/** The configured model's templates: its preset, with each side replaced by an explicit config value. */
|
|
45
|
+
export function resolveEmbeddingProfile(config) {
|
|
46
|
+
const model = embeddingModelName(config);
|
|
47
|
+
const preset = isDeterministicEmbedEnabled() ? {} : (PRESETS.find((entry) => entry.model.test(model))?.profile ?? {});
|
|
48
|
+
const queryTemplate = config?.queryTemplate ?? preset.queryTemplate;
|
|
49
|
+
const documentTemplate = config?.documentTemplate ?? preset.documentTemplate;
|
|
50
|
+
return {
|
|
51
|
+
...(queryTemplate ? { queryTemplate } : {}),
|
|
52
|
+
...(documentTemplate ? { documentTemplate } : {}),
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
/** Put `text` into `template`; no template returns the text unchanged. */
|
|
56
|
+
export function applyEmbeddingTemplate(template, text) {
|
|
57
|
+
if (!template)
|
|
58
|
+
return text;
|
|
59
|
+
// A replacer function keeps `$&`-style sequences in the text literal.
|
|
60
|
+
return template.includes("{text}") ? template.replaceAll("{text}", () => text) : `${template}${text}`;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* The document template's part of the embedding fingerprint: empty without a
|
|
64
|
+
* template, so vectors embedded without one stay current.
|
|
65
|
+
*/
|
|
66
|
+
export function documentTemplateFingerprint(config) {
|
|
67
|
+
const template = resolveEmbeddingProfile(config).documentTemplate;
|
|
68
|
+
if (!template)
|
|
69
|
+
return "";
|
|
70
|
+
return `|doc:${createHash("sha256").update(template).digest("hex").slice(0, 12)}`;
|
|
71
|
+
}
|
|
@@ -187,8 +187,7 @@ export function isContextExceededResponse(status, body) {
|
|
|
187
187
|
* Resolve the effective in-flight request window for `RemoteEmbedder.embedBatch`.
|
|
188
188
|
* Default (unset `embedding.concurrency`): 1 for a loopback endpoint, 2 for a
|
|
189
189
|
* remote one, via the shared `defaultConcurrencyForEndpoint`
|
|
190
|
-
* (`src/core/loopback.ts`)
|
|
191
|
-
* `getDefaultLlmConcurrency` (`src/indexer/indexer.ts`) uses.
|
|
190
|
+
* (`src/core/loopback.ts`).
|
|
192
191
|
*
|
|
193
192
|
* `embedding.concurrency` (#954) overrides this default in
|
|
194
193
|
* either direction, bounded 1-16 at the config schema — added after field
|
|
@@ -428,7 +427,7 @@ export class RemoteEmbedder {
|
|
|
428
427
|
textBatches.splice(dispatchedBatchCount, textBatches.length - dispatchedBatchCount, ...replanned);
|
|
429
428
|
}
|
|
430
429
|
warnVerbose(`[embed] provider rejected a ${rejectedRequestTokens}-token request as over its context; request budget lowered to ${effectiveTokenBudget.toLocaleString()} for the rest of this run`);
|
|
431
|
-
commitBatch(rejectedIndices, rejectedIndices.map(() => undefined),
|
|
430
|
+
commitBatch(rejectedIndices, rejectedIndices.map(() => undefined), {
|
|
432
431
|
batchIndex: rejectedBatchIndex,
|
|
433
432
|
batchCount: textBatches.length,
|
|
434
433
|
docCount: rejectedIndices.length,
|
|
@@ -471,7 +470,7 @@ export class RemoteEmbedder {
|
|
|
471
470
|
// fabricated "batch-request-failed" skip (#954). Checked (and rethrown)
|
|
472
471
|
// once the pool drains, the same way `signal?.aborted` is today.
|
|
473
472
|
let firstOnBatchError;
|
|
474
|
-
const commitBatch = (indices, embeddings,
|
|
473
|
+
const commitBatch = (indices, embeddings, outcome) => {
|
|
475
474
|
if (!onBatch)
|
|
476
475
|
return;
|
|
477
476
|
// Once persistence has failed once, an already in-flight batch that
|
|
@@ -481,7 +480,7 @@ export class RemoteEmbedder {
|
|
|
481
480
|
if (firstOnBatchError !== undefined)
|
|
482
481
|
return;
|
|
483
482
|
try {
|
|
484
|
-
onBatch(indices, embeddings,
|
|
483
|
+
onBatch(indices, embeddings, outcome);
|
|
485
484
|
}
|
|
486
485
|
catch (err) {
|
|
487
486
|
firstOnBatchError = err;
|
|
@@ -523,16 +522,14 @@ export class RemoteEmbedder {
|
|
|
523
522
|
const requestTimeoutMs = scaleEmbeddingTimeoutMs(configuredTimeoutMs, requestTokens, effectiveTokenBudget);
|
|
524
523
|
const requestStart = Date.now();
|
|
525
524
|
let batchEmbeddings;
|
|
526
|
-
let responseModel;
|
|
527
525
|
let outcome;
|
|
528
526
|
let failureReason;
|
|
529
527
|
try {
|
|
530
|
-
const
|
|
528
|
+
const vectors = await this.requestBatch(batch, headers, ollamaOpts, requestTimeoutMs, signal);
|
|
531
529
|
for (let k = 0; k < indices.length; k++) {
|
|
532
530
|
results[indices[k]] = vectors[k];
|
|
533
531
|
}
|
|
534
532
|
batchEmbeddings = indices.map((i) => results[i]);
|
|
535
|
-
responseModel = model;
|
|
536
533
|
outcome = "stored";
|
|
537
534
|
}
|
|
538
535
|
catch (err) {
|
|
@@ -571,7 +568,7 @@ export class RemoteEmbedder {
|
|
|
571
568
|
// failed or succeeded yet, so there is nothing to persist:
|
|
572
569
|
// `embeddings` are all `undefined` and the materializer's onBatch
|
|
573
570
|
// must not touch storage for this event.
|
|
574
|
-
commitBatch(indices, indices.map(() => undefined),
|
|
571
|
+
commitBatch(indices, indices.map(() => undefined), {
|
|
575
572
|
batchIndex,
|
|
576
573
|
batchCount: textBatches.length,
|
|
577
574
|
docCount: indices.length,
|
|
@@ -635,7 +632,7 @@ export class RemoteEmbedder {
|
|
|
635
632
|
outcome = "failed";
|
|
636
633
|
failureReason = message;
|
|
637
634
|
}
|
|
638
|
-
commitBatch(indices, batchEmbeddings,
|
|
635
|
+
commitBatch(indices, batchEmbeddings, {
|
|
639
636
|
batchIndex,
|
|
640
637
|
batchCount: textBatches.length,
|
|
641
638
|
docCount: indices.length,
|
|
@@ -665,7 +662,7 @@ export class RemoteEmbedder {
|
|
|
665
662
|
// Never made a request — excluded from the default-level per-batch
|
|
666
663
|
// line (there is no request outcome to report), but still counted
|
|
667
664
|
// in the run's oversized-skip total via `onSkip` above.
|
|
668
|
-
commitBatch([idx], [undefined],
|
|
665
|
+
commitBatch([idx], [undefined], {
|
|
669
666
|
batchIndex,
|
|
670
667
|
batchCount: textBatches.length,
|
|
671
668
|
docCount: 1,
|
|
@@ -701,11 +698,8 @@ export class RemoteEmbedder {
|
|
|
701
698
|
return results;
|
|
702
699
|
}
|
|
703
700
|
/**
|
|
704
|
-
* Send one batch request and return its embeddings in input order
|
|
705
|
-
*
|
|
706
|
-
* used by the embedding-fingerprint canary to verify a config-string
|
|
707
|
-
* rename against what the endpoint actually served, not just re-assert the
|
|
708
|
-
* configured string. Throws on any failure.
|
|
701
|
+
* Send one batch request and return its embeddings in input order. Throws
|
|
702
|
+
* on any failure.
|
|
709
703
|
*
|
|
710
704
|
* `timeoutMs` is the caller's ALREADY-SCALED per-request timeout (#954
|
|
711
705
|
* — see {@link scaleEmbeddingTimeoutMs}), not re-resolved here:
|
|
@@ -756,7 +750,7 @@ export class RemoteEmbedder {
|
|
|
756
750
|
}
|
|
757
751
|
results.push(l2Normalize(d.embedding));
|
|
758
752
|
}
|
|
759
|
-
return
|
|
753
|
+
return results;
|
|
760
754
|
}
|
|
761
755
|
buildHeaders() {
|
|
762
756
|
const headers = { "Content-Type": "application/json" };
|
package/dist/llm/feature-gate.js
CHANGED
|
@@ -7,8 +7,6 @@
|
|
|
7
7
|
*/
|
|
8
8
|
const FEATURE_LOCATION = {
|
|
9
9
|
memory_inference: (cfg) => cfg.index?.memory?.enabled ?? true,
|
|
10
|
-
graph_extraction: (cfg) => cfg.index?.graph?.enabled ?? true,
|
|
11
|
-
metadata_enhance: (cfg) => cfg.index?.metadataEnhance?.enabled ?? false,
|
|
12
10
|
// #951: a real implementation of the dead `curate_rerank` key removed in
|
|
13
11
|
// 0.8.0. Off by default — it requires a `search.curateRerank.endpoint` a
|
|
14
12
|
// caller must explicitly configure.
|
|
@@ -79,15 +77,9 @@ export function isProcessEnabled(section, processName, config) {
|
|
|
79
77
|
return false;
|
|
80
78
|
// Index passes are first-class 0.9 entries.
|
|
81
79
|
if (section === "index") {
|
|
82
|
-
if (processName === "metadata_enhance" || processName === "metadataEnhance") {
|
|
83
|
-
return config.index?.metadataEnhance?.enabled ?? true;
|
|
84
|
-
}
|
|
85
80
|
if (processName === "memory_inference" || processName === "memoryInference") {
|
|
86
81
|
return isLlmFeatureEnabled(config, "memory_inference");
|
|
87
82
|
}
|
|
88
|
-
if (processName === "graph_extraction" || processName === "graphExtraction") {
|
|
89
|
-
return isLlmFeatureEnabled(config, "graph_extraction");
|
|
90
|
-
}
|
|
91
83
|
}
|
|
92
84
|
return false;
|
|
93
85
|
}
|
package/dist/llm/index-passes.js
CHANGED
|
@@ -3,8 +3,7 @@
|
|
|
3
3
|
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
4
|
import { warn } from "../core/warn.js";
|
|
5
5
|
import { cloneExecutionJsonObject } from "../execution/json.js";
|
|
6
|
-
import {
|
|
7
|
-
import { prepareInlineExecution } from "../integrations/agent/inline-execution.js";
|
|
6
|
+
import { buildExecution, resolveExecution } from "../integrations/agent/execution.js";
|
|
8
7
|
const NO_LOWERING_NOTICES = Object.freeze([]);
|
|
9
8
|
function own(value, key) {
|
|
10
9
|
return value !== undefined && Object.hasOwn(value, key);
|
|
@@ -39,14 +38,13 @@ export function resolveIndexPassExecution(passName, config) {
|
|
|
39
38
|
...indexExecutionDefaults(defaults),
|
|
40
39
|
...(!own(defaults, "engine") && fallbackLlmEngine ? { engine: fallbackLlmEngine } : {}),
|
|
41
40
|
};
|
|
42
|
-
const prepared =
|
|
41
|
+
const prepared = resolveExecution({
|
|
43
42
|
content: "",
|
|
44
43
|
config,
|
|
45
|
-
invocationKind: "direct",
|
|
46
44
|
invocationDefaults,
|
|
47
45
|
current: indexExecutionDefaults(pass),
|
|
48
46
|
});
|
|
49
|
-
const lowered =
|
|
47
|
+
const lowered = buildExecution(prepared.request, prepared.runner);
|
|
50
48
|
if (lowered.runner.kind !== "llm") {
|
|
51
49
|
warn("[akm] Index pass %s requires an LLM engine; %s is not one. Skipping this pass.", passName, selectedEngine);
|
|
52
50
|
return Object.freeze({ runner: undefined, notices: NO_LOWERING_NOTICES });
|
package/dist/llm/memory-infer.js
CHANGED
|
@@ -68,7 +68,7 @@ const DERIVED_MEMORY_JSON_SCHEMA = {
|
|
|
68
68
|
* feature gate, error classification, and onFallback hook are honoured uniformly
|
|
69
69
|
* (Fix C5).
|
|
70
70
|
*/
|
|
71
|
-
export async function compressMemoryToDerivedMemory(llmRunner, body, signal, akmConfig, onFallback, telemetry, onRetryAttempt, onNotices
|
|
71
|
+
export async function compressMemoryToDerivedMemory(llmRunner, body, signal, akmConfig, onFallback, telemetry, onRetryAttempt, onNotices) {
|
|
72
72
|
const trimmedBody = body.trim();
|
|
73
73
|
if (!trimmedBody)
|
|
74
74
|
return undefined;
|
|
@@ -83,7 +83,6 @@ export async function compressMemoryToDerivedMemory(llmRunner, body, signal, akm
|
|
|
83
83
|
feature: "memory_inference",
|
|
84
84
|
akmConfig,
|
|
85
85
|
runner: llmRunner,
|
|
86
|
-
...(lease ? { lease } : {}),
|
|
87
86
|
messages: [
|
|
88
87
|
{ role: "system", content: SYSTEM_PROMPT },
|
|
89
88
|
{ role: "user", content: userPrompt },
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
3
|
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
4
|
import { ConfigError } from "../core/errors.js";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
5
|
+
import { buildExecution, resolveExecution } from "../integrations/agent/execution.js";
|
|
6
|
+
import { runExecution } from "../integrations/agent/runner-dispatch.js";
|
|
7
7
|
import { isContextSizeError, LlmCallError } from "./client.js";
|
|
8
8
|
import { isLlmFeatureEnabled, tryLlmFeature, } from "./feature-gate.js";
|
|
9
9
|
/**
|
|
@@ -62,22 +62,6 @@ function dispatchFailure(result) {
|
|
|
62
62
|
const message = result.error ?? result.stderr ?? result.reason ?? "LLM dispatch failed";
|
|
63
63
|
return result.llmErrorCode ? new LlmCallError(message, result.llmErrorCode) : new Error(message);
|
|
64
64
|
}
|
|
65
|
-
/**
|
|
66
|
-
* Validate one already-selected symbolic LLM runner before an operation makes
|
|
67
|
-
* any durable mutation. Callers must apply their feature/authorization gates
|
|
68
|
-
* first. Acquisition crosses the canonical prepare -> lower -> lease boundary,
|
|
69
|
-
* so required credentials are snapshotted by the same central authority as a
|
|
70
|
-
* real call without contacting the provider.
|
|
71
|
-
*/
|
|
72
|
-
export async function preflightStructuredLlmRunner(runner) {
|
|
73
|
-
const prepared = prepareInlineExecutionWithRunner({
|
|
74
|
-
content: "Validate the selected LLM runner before operation dispatch.",
|
|
75
|
-
runner,
|
|
76
|
-
invocationKind: "direct",
|
|
77
|
-
});
|
|
78
|
-
const lowered = lowerResolvedExecutionRequestWithRunner(prepared.request, prepared.runner);
|
|
79
|
-
return acquireLoweredExecutionDispatchLease(lowered);
|
|
80
|
-
}
|
|
81
65
|
export async function callStructured(opts) {
|
|
82
66
|
const { feature, akmConfig, enabled, messages, request, parse, onError, fallback, onFallback } = opts;
|
|
83
67
|
// A disabled feature owns a true no-work path: it does not need a runner,
|
|
@@ -97,19 +81,16 @@ export async function callStructured(opts) {
|
|
|
97
81
|
const terminal = requireTerminalUserMessage(messages);
|
|
98
82
|
const prepareInvocation = () => {
|
|
99
83
|
const current = resolveStructuredCurrent(opts.current, request);
|
|
100
|
-
const prepared =
|
|
84
|
+
const prepared = resolveExecution({
|
|
101
85
|
content: terminal.content,
|
|
102
86
|
conversation: terminal.conversation,
|
|
103
87
|
runner,
|
|
104
|
-
invocationKind: "direct",
|
|
105
88
|
...(current ? { current } : {}),
|
|
106
|
-
...(opts.authorizeTools ? { authorizeTools: opts.authorizeTools } : {}),
|
|
107
89
|
});
|
|
108
|
-
const lowered =
|
|
90
|
+
const lowered = buildExecution(prepared.request, prepared.runner);
|
|
109
91
|
opts.onNotices?.(lowered.notices);
|
|
110
92
|
return async () => {
|
|
111
|
-
const result = await
|
|
112
|
-
...(opts.lease ? { lease: opts.lease } : {}),
|
|
93
|
+
const result = await runExecution(lowered, {
|
|
113
94
|
...(request?.chat ? { chat: request.chat } : {}),
|
|
114
95
|
...(request?.onRetryAttempt ? { onRetryAttempt: request.onRetryAttempt } : {}),
|
|
115
96
|
...(own(request, "signal") ? { runOptions: { signal: request?.signal } } : {}),
|
|
@@ -1,6 +1,29 @@
|
|
|
1
1
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
2
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
3
|
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
|
+
/**
|
|
5
|
+
* Generic `md` / `html` / `text` rendering of a shaped output envelope (D7).
|
|
6
|
+
*
|
|
7
|
+
* Every command gets `json`, `jsonl`, and `yaml` for free because those are
|
|
8
|
+
* serializations of the envelope rather than renderings of it. `md`, `html`,
|
|
9
|
+
* and `text` are renderings, and before D7 only `akm health` had `md`/`html`:
|
|
10
|
+
* `md` silently emitted the JSON envelope everywhere else and `html` threw.
|
|
11
|
+
* `text` had the same silent-JSON gap for any command with no registered
|
|
12
|
+
* text formatter, closed later than `md`/`html` — see `renderGenericText`
|
|
13
|
+
* below for why it is its own function rather than a reuse of
|
|
14
|
+
* `renderGenericMarkdown`.
|
|
15
|
+
*
|
|
16
|
+
* These functions close that gap structurally rather than per command. A
|
|
17
|
+
* command that registers a bespoke renderer (`akm health`) still wins; every
|
|
18
|
+
* other command falls back to a real rendering derived from whatever its
|
|
19
|
+
* envelope happens to contain. The shape is discovered, not declared, so a new
|
|
20
|
+
* command is covered the day it is added.
|
|
21
|
+
*
|
|
22
|
+
* Deliberately dependency-free apart from the shared detail types and
|
|
23
|
+
* `escapeHtml`: this module sits underneath the per-command renderer
|
|
24
|
+
* registries and must not import them.
|
|
25
|
+
*/
|
|
26
|
+
import { escapeHtml } from "./html-render.js";
|
|
4
27
|
/**
|
|
5
28
|
* True when `value` is a non-empty array of plain objects — the shape worth
|
|
6
29
|
* rendering as a table rather than as a nested list. Uniformity is judged on
|
|
@@ -106,17 +129,6 @@ export function renderGenericMarkdown(command, value) {
|
|
|
106
129
|
return `${rendered}\n`;
|
|
107
130
|
}
|
|
108
131
|
// ── HTML ─────────────────────────────────────────────────────────────────────
|
|
109
|
-
const HTML_ESCAPES = {
|
|
110
|
-
"&": "&",
|
|
111
|
-
"<": "<",
|
|
112
|
-
">": ">",
|
|
113
|
-
'"': """,
|
|
114
|
-
"'": "'",
|
|
115
|
-
};
|
|
116
|
-
/** Escape every value that reaches the document — this is untrusted content. */
|
|
117
|
-
function escapeHtml(text) {
|
|
118
|
-
return text.replace(/[&<>"']/g, (char) => HTML_ESCAPES[char] ?? char);
|
|
119
|
-
}
|
|
120
132
|
function htmlTable(rows) {
|
|
121
133
|
const columns = tableColumns(rows);
|
|
122
134
|
if (columns.length === 0)
|