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
|
@@ -12,9 +12,8 @@
|
|
|
12
12
|
* target below so a configured registry cannot preselect a different source
|
|
13
13
|
* merely by reusing a trusted display ID.
|
|
14
14
|
*/
|
|
15
|
-
import { jsonWithByteCap } from "../core/common.js";
|
|
16
15
|
import { hasRegistryUrlCredentials } from "../core/registry-url.js";
|
|
17
|
-
import {
|
|
16
|
+
import { fetchRegistryJson } from "../registry/network.js";
|
|
18
17
|
import { parseRegistryRef } from "../registry/resolve.js";
|
|
19
18
|
// ── Default selections ──────────────────────────────────────────────────────
|
|
20
19
|
const AUTHENTICATED_DEFAULT_TARGETS = {
|
|
@@ -74,20 +73,12 @@ export async function loadSetupStashes(registryUrl, timeoutMs = 4000) {
|
|
|
74
73
|
}
|
|
75
74
|
async function loadSetupStashesReal(registryUrl, timeoutMs = 4000) {
|
|
76
75
|
try {
|
|
77
|
-
const
|
|
78
|
-
|
|
76
|
+
const raw = await fetchRegistryJson(registryUrl, {
|
|
77
|
+
headers: { Accept: "application/json" },
|
|
79
78
|
timeoutMs,
|
|
80
79
|
retries: 0,
|
|
81
|
-
allowPrivateHostsForTesting: allowPrivateRegistryFixtureForTests(registryUrl),
|
|
82
80
|
});
|
|
83
|
-
if (!
|
|
84
|
-
await cancelRegistryResponse(response);
|
|
85
|
-
return FALLBACK_STASHES;
|
|
86
|
-
}
|
|
87
|
-
const raw = await jsonWithByteCap(response, 10 * 1024 * 1024, {
|
|
88
|
-
bodyTimeoutMs: timeoutMs,
|
|
89
|
-
});
|
|
90
|
-
if (!Array.isArray(raw.stashes) || raw.stashes.length === 0)
|
|
81
|
+
if (!Array.isArray(raw?.stashes) || raw.stashes.length === 0)
|
|
91
82
|
return FALLBACK_STASHES;
|
|
92
83
|
const entries = raw.stashes.flatMap((item) => {
|
|
93
84
|
if (!item || typeof item !== "object")
|
|
@@ -4,21 +4,13 @@
|
|
|
4
4
|
/**
|
|
5
5
|
* Semantic-search asset preparation for the setup wizard. Transformers.js is
|
|
6
6
|
* a normal external package dependency; setup never mutates the installed CLI.
|
|
7
|
-
* This module only prepares the model
|
|
7
|
+
* This module only prepares the model.
|
|
8
8
|
*/
|
|
9
|
-
import fs from "node:fs";
|
|
10
|
-
import os from "node:os";
|
|
11
|
-
import path from "node:path";
|
|
12
9
|
import * as p from "../cli/clack.js";
|
|
13
10
|
import { isHttpUrl } from "../core/common.js";
|
|
14
11
|
import { checkEmbeddingAvailability, DEFAULT_LOCAL_MODEL, isTransformersAvailable } from "../llm/embedder.js";
|
|
15
|
-
|
|
16
|
-
import { isVecAvailable } from "../storage/repositories/index-vec-repository.js";
|
|
17
|
-
// Approximate first-download sizes used in the setup note.
|
|
18
|
-
// LOCAL_MODEL_APPROX_SIZE_MB tracks the default local model (DEFAULT_LOCAL_MODEL).
|
|
12
|
+
// Approximate first-download size of the default local model (DEFAULT_LOCAL_MODEL), used in the setup note.
|
|
19
13
|
const LOCAL_MODEL_APPROX_SIZE_MB = 130;
|
|
20
|
-
// SQLITE_VEC_APPROX_SIZE_MB reflects the optional sqlite-vec install footprint.
|
|
21
|
-
const SQLITE_VEC_APPROX_SIZE_MB = 5;
|
|
22
14
|
export function isRemoteEmbeddingConfig(embedding) {
|
|
23
15
|
return isHttpUrl(embedding?.endpoint);
|
|
24
16
|
}
|
|
@@ -27,14 +19,10 @@ export function isRemoteEmbeddingConfig(embedding) {
|
|
|
27
19
|
*/
|
|
28
20
|
export function describeSemanticSearchAssets(embedding) {
|
|
29
21
|
if (isRemoteEmbeddingConfig(embedding)) {
|
|
30
|
-
return [
|
|
31
|
-
`• Embedding endpoint: ${embedding?.provider ?? "custom"} / ${embedding?.model} (no local model download)`,
|
|
32
|
-
`• sqlite-vec acceleration: optional native extension (~${SQLITE_VEC_APPROX_SIZE_MB} MB when installed separately)`,
|
|
33
|
-
];
|
|
22
|
+
return [`• Embedding endpoint: ${embedding?.provider ?? "custom"} / ${embedding?.model} (no local model download)`];
|
|
34
23
|
}
|
|
35
24
|
return [
|
|
36
25
|
`• Local embedding model: ${embedding?.localModel ?? DEFAULT_LOCAL_MODEL} (~${LOCAL_MODEL_APPROX_SIZE_MB} MB download on first use)`,
|
|
37
|
-
`• sqlite-vec acceleration: optional native extension (~${SQLITE_VEC_APPROX_SIZE_MB} MB when installed separately)`,
|
|
38
26
|
];
|
|
39
27
|
}
|
|
40
28
|
export async function prepareSemanticSearchAssets(config) {
|
|
@@ -69,34 +57,5 @@ export async function prepareSemanticSearchAssets(config) {
|
|
|
69
57
|
}
|
|
70
58
|
}
|
|
71
59
|
spin.stop(remote ? "Remote embedding endpoint is ready." : "Local embedding model downloaded and ready.");
|
|
72
|
-
let db;
|
|
73
|
-
let probeDir;
|
|
74
|
-
try {
|
|
75
|
-
probeDir = fs.mkdtempSync(path.join(os.tmpdir(), "akm-setup-vec-probe-"));
|
|
76
|
-
db = openIndexDatabase(path.join(probeDir, "probe.db"), config.embedding?.dimension ? { embeddingDim: config.embedding.dimension } : undefined);
|
|
77
|
-
if (isVecAvailable(db)) {
|
|
78
|
-
p.log.info("sqlite-vec is available for fast vector search.");
|
|
79
|
-
}
|
|
80
|
-
else {
|
|
81
|
-
p.log.info("sqlite-vec is not available. Semantic search will use the JS fallback until the optional extension is installed.");
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
catch (error) {
|
|
85
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
86
|
-
p.log.warn(`Could not open the local database or check for sqlite-vec. Semantic search will use the JS fallback. (${message})\n` +
|
|
87
|
-
"Check file permissions and available disk space in the cache directory, or run `akm index --full --verbose` to diagnose.");
|
|
88
|
-
}
|
|
89
|
-
finally {
|
|
90
|
-
if (db)
|
|
91
|
-
closeDatabase(db);
|
|
92
|
-
if (probeDir) {
|
|
93
|
-
try {
|
|
94
|
-
fs.rmSync(probeDir, { recursive: true, force: true });
|
|
95
|
-
}
|
|
96
|
-
catch {
|
|
97
|
-
/* ignore cleanup failure */
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
60
|
return { ok: true };
|
|
102
61
|
}
|
package/dist/setup/setup.js
CHANGED
|
@@ -117,7 +117,7 @@ export function assertSetupConfigPreflight() {
|
|
|
117
117
|
catch (error) {
|
|
118
118
|
if (!(error instanceof ConfigError))
|
|
119
119
|
throw error;
|
|
120
|
-
if (error.code !== "
|
|
120
|
+
if (error.code !== "INVALID_CONFIG_FILE")
|
|
121
121
|
throw error;
|
|
122
122
|
throw new ConfigError(`\`akm setup\` cannot run: the config at ${configPath} did not load (${error.message}). ` +
|
|
123
123
|
"It was left untouched — setup never writes over a config it cannot first read cleanly.", error.code, "Rewrite the file using the current config schema, or move it aside to start fresh " +
|
|
@@ -122,7 +122,8 @@ const LLM_PRESETS = [
|
|
|
122
122
|
},
|
|
123
123
|
];
|
|
124
124
|
/**
|
|
125
|
-
* Step 3a: pick an LLM provider. Used for
|
|
125
|
+
* Step 3a: pick an LLM provider. Used for LLM-gated background features
|
|
126
|
+
* (e.g. memory inference).
|
|
126
127
|
*
|
|
127
128
|
* @internal Exported for testing only.
|
|
128
129
|
*/
|
|
@@ -151,14 +152,14 @@ export async function stepLlm(current, ollamaEndpoint, ollamaChatModels, lmStudi
|
|
|
151
152
|
}
|
|
152
153
|
options.push({ value: "lmstudio", label: "LM Studio / local server", hint: lmStudioOptionHint(lmStudio) });
|
|
153
154
|
options.push({ value: "custom", label: "Custom OpenAI-compatible endpoint" });
|
|
154
|
-
options.push({ value: "none", label: "Skip LLM", hint: "
|
|
155
|
+
options.push({ value: "none", label: "Skip LLM", hint: "LLM-gated background features stay disabled" });
|
|
155
156
|
const currentLlm = readCurrentLlmEngine(current);
|
|
156
157
|
if (currentLlm) {
|
|
157
158
|
options.push(keepCurrentOption(currentLlm));
|
|
158
159
|
}
|
|
159
160
|
const initialValue = currentLlm ? "keep" : ollamaAvailable ? "ollama" : (LLM_PRESETS[0]?.value ?? "none");
|
|
160
161
|
const choice = await prompt(() => p.select({
|
|
161
|
-
message: "Configure an LLM for
|
|
162
|
+
message: "Configure an LLM for background features:",
|
|
162
163
|
options,
|
|
163
164
|
initialValue,
|
|
164
165
|
}));
|
|
@@ -251,7 +252,7 @@ export async function stepLlm(current, ollamaEndpoint, ollamaChatModels, lmStudi
|
|
|
251
252
|
return llm;
|
|
252
253
|
}
|
|
253
254
|
/**
|
|
254
|
-
* Step 1/2: Configure the small model connection used for
|
|
255
|
+
* Step 1/2: Configure the small model connection used for bounded LLM features.
|
|
255
256
|
*
|
|
256
257
|
* Detects Ollama automatically and pre-selects it. The user may also choose
|
|
257
258
|
* OpenAI, LM Studio, a custom endpoint, or skip the step entirely.
|
|
@@ -260,7 +261,6 @@ export async function stepSmallModelConnection(current) {
|
|
|
260
261
|
p.log.step("Step 1/2: Configure your small model connection");
|
|
261
262
|
p.note([
|
|
262
263
|
"This connection is used for background processing:",
|
|
263
|
-
" • akm index (metadata enhancement)",
|
|
264
264
|
" • akm improve (lesson distillation)",
|
|
265
265
|
" • akm remember --enrich (memory compression)",
|
|
266
266
|
].join("\n"));
|
|
@@ -301,7 +301,6 @@ export async function stepSmallModelConnection(current) {
|
|
|
301
301
|
if (providerChoice === "skip") {
|
|
302
302
|
p.note([
|
|
303
303
|
"Enrichment features disabled:",
|
|
304
|
-
" • akm index — metadata enhancement disabled",
|
|
305
304
|
" • akm improve — lesson generation",
|
|
306
305
|
" • akm remember --enrich",
|
|
307
306
|
"",
|
|
@@ -53,10 +53,10 @@ export function printCapabilitySummary(smallModelSkipped, agentConfigured) {
|
|
|
53
53
|
const lines = ["Setup complete. Here's what's enabled:", ""];
|
|
54
54
|
lines.push(" ✓ akm search, akm curate, akm show, akm index, akm remember — always available");
|
|
55
55
|
if (!smallModelSkipped) {
|
|
56
|
-
lines.push(" ✓
|
|
56
|
+
lines.push(" ✓ akm improve, akm remember --enrich — small model configured");
|
|
57
57
|
}
|
|
58
58
|
else {
|
|
59
|
-
lines.push(" ✗
|
|
59
|
+
lines.push(" ✗ akm improve, akm remember --enrich — run `akm setup` to enable");
|
|
60
60
|
}
|
|
61
61
|
if (agentConfigured) {
|
|
62
62
|
lines.push(" ✓ akm proposal new, akm improve, akm task — agent configured");
|
|
@@ -9,11 +9,11 @@ import { parse as yamlParse, stringify as yamlStringify } from "yaml";
|
|
|
9
9
|
import * as p from "../../cli/clack.js";
|
|
10
10
|
import { akmTasksSync } from "../../commands/tasks/tasks.js";
|
|
11
11
|
import { makeBundleRef } from "../../core/asset/asset-ref.js";
|
|
12
|
-
import { loadConfig, mutateConfig } from "../../core/config/config.js";
|
|
12
|
+
import { loadConfig, mutateConfig, resetConfigCache } from "../../core/config/config.js";
|
|
13
13
|
import { UsageError } from "../../core/errors.js";
|
|
14
14
|
import { commitWriteTargetBoundary, deleteAssetFromSource, prepareWriteTargetForMutation, resolveWriteTarget, writeAssetToSource, } from "../../core/write-source.js";
|
|
15
|
-
import {
|
|
16
|
-
import { backendNameForPlatform } from "../../tasks/backends/index.js";
|
|
15
|
+
import { enabledRefsFromInstalled, isSchedulerBundleActive, schedulerEnabledRefs } from "../../tasks/activation-config.js";
|
|
16
|
+
import { backendNameForPlatform, selectBackend } from "../../tasks/backends/index.js";
|
|
17
17
|
import { listEmbeddedTasks } from "../../tasks/embedded.js";
|
|
18
18
|
import { parseSchedule } from "../../tasks/schedule.js";
|
|
19
19
|
import { parseTaskSource } from "../../tasks/source/parse-task-source.js";
|
|
@@ -77,9 +77,7 @@ export function listSetupTaskDefinitions() {
|
|
|
77
77
|
const config = loadConfig();
|
|
78
78
|
const target = resolveWriteTarget(config, config.defaultBundle, { requireWritable: false });
|
|
79
79
|
const taskDir = path.join(target.source.path, "tasks");
|
|
80
|
-
const enabledRefs = new Set(
|
|
81
|
-
.filter((activation) => activation.kind === "task")
|
|
82
|
-
.map((activation) => activation.ref));
|
|
80
|
+
const enabledRefs = new Set(schedulerEnabledRefs(config) ?? []);
|
|
83
81
|
if (!fs.existsSync(taskDir))
|
|
84
82
|
return [];
|
|
85
83
|
const tasks = [];
|
|
@@ -178,17 +176,14 @@ export async function prepareSetupTaskDefinitions(tasks, deps = {}) {
|
|
|
178
176
|
const selected = new Set(tasks.filter((plan) => plan.enabled).map((plan) => makeBundleRef(target.source.name, `tasks/${plan.task.id}`)));
|
|
179
177
|
const managed = new Set(tasks.map((plan) => makeBundleRef(target.source.name, `tasks/${plan.task.id}`)));
|
|
180
178
|
mutateConfig((current) => {
|
|
181
|
-
const existing =
|
|
182
|
-
const next = existing.filter((
|
|
183
|
-
|
|
184
|
-
if (selected.size > 0 && !sourceId) {
|
|
179
|
+
const existing = schedulerEnabledRefs(current) ?? [];
|
|
180
|
+
const next = existing.filter((ref) => !managed.has(ref));
|
|
181
|
+
if (selected.size > 0 && !isSchedulerBundleActive(current, target.source.name)) {
|
|
185
182
|
throw new UsageError(`Cannot activate setup tasks from disabled bundle ${JSON.stringify(target.source.name)}.`);
|
|
186
183
|
}
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
next.sort((left, right) => left.ref.localeCompare(right.ref) || left.kind.localeCompare(right.kind));
|
|
191
|
-
if (JSON.stringify(existing) === JSON.stringify(next))
|
|
184
|
+
next.push(...selected);
|
|
185
|
+
next.sort((left, right) => left.localeCompare(right));
|
|
186
|
+
if (current.scheduler?.enabled !== undefined && JSON.stringify([...existing]) === JSON.stringify(next))
|
|
192
187
|
return current;
|
|
193
188
|
return { ...current, scheduler: { ...current.scheduler, enabled: next } };
|
|
194
189
|
});
|
|
@@ -198,6 +193,7 @@ const DEFAULT_SCHEDULED_TASKS_DEPS = {
|
|
|
198
193
|
list: listSetupTaskDefinitions,
|
|
199
194
|
prepare: prepareSetupTaskDefinitions,
|
|
200
195
|
sync: akmTasksSync,
|
|
196
|
+
inspectInstalled: async () => ({ installed: await selectBackend().list() }),
|
|
201
197
|
};
|
|
202
198
|
export async function stepScheduledTasks(deps = DEFAULT_SCHEDULED_TASKS_DEPS, options = {}) {
|
|
203
199
|
if (options.nonInteractive || isCiEnvironment()) {
|
|
@@ -212,6 +208,20 @@ export async function stepScheduledTasks(deps = DEFAULT_SCHEDULED_TASKS_DEPS, op
|
|
|
212
208
|
const embedded = listEmbeddedTasks();
|
|
213
209
|
if (embedded.length === 0)
|
|
214
210
|
return;
|
|
211
|
+
// A config that predates `scheduler.enabled` means "keep what is installed":
|
|
212
|
+
// make that explicit before the review below reads and edits the list.
|
|
213
|
+
if (schedulerEnabledRefs(loadConfig()) === undefined) {
|
|
214
|
+
try {
|
|
215
|
+
const inspection = await deps.inspectInstalled();
|
|
216
|
+
const refs = enabledRefsFromInstalled(inspection.installed, loadConfig());
|
|
217
|
+
mutateConfig((current) => ({ ...current, scheduler: { ...current.scheduler, enabled: [...refs] } }));
|
|
218
|
+
resetConfigCache();
|
|
219
|
+
}
|
|
220
|
+
catch (cause) {
|
|
221
|
+
const message = cause instanceof Error ? cause.message : String(cause);
|
|
222
|
+
p.log.warn(`Native scheduler bindings could not be inspected: ${message}`);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
215
225
|
const installed = await deps.list();
|
|
216
226
|
const byId = new Map();
|
|
217
227
|
for (const task of installed)
|
|
@@ -1,23 +1,22 @@
|
|
|
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
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
* {@link SourceConfigEntry}.
|
|
10
|
-
*
|
|
11
|
-
* Distinct from the registry-discovery factory (`registry/factory.ts`).
|
|
12
|
-
* Both share `create-provider-registry.ts` for the underlying string→factory
|
|
13
|
-
* map.
|
|
14
|
-
*/
|
|
15
|
-
import { createProviderRegistry } from "../registry/create-provider-registry.js";
|
|
16
|
-
// ── Factory map ─────────────────────────────────────────────────────────────
|
|
17
|
-
const registry = createProviderRegistry();
|
|
18
|
-
export function registerSourceProvider(type, factory) {
|
|
19
|
-
registry.register(type, factory);
|
|
20
|
-
}
|
|
4
|
+
import { createFilesystemProvider } from "./providers/filesystem.js";
|
|
5
|
+
import { GitSourceProvider } from "./providers/git-provider.js";
|
|
6
|
+
import { NpmSourceProvider } from "./providers/npm.js";
|
|
7
|
+
import { createWebsiteProvider } from "./providers/website.js";
|
|
8
|
+
/** The factory for a configured source kind, or null for a kind akm does not support. */
|
|
21
9
|
export function resolveSourceProviderFactory(type) {
|
|
22
|
-
|
|
10
|
+
switch (type) {
|
|
11
|
+
case "filesystem":
|
|
12
|
+
return createFilesystemProvider;
|
|
13
|
+
case "git":
|
|
14
|
+
return (config) => new GitSourceProvider(config);
|
|
15
|
+
case "npm":
|
|
16
|
+
return (config) => new NpmSourceProvider(config);
|
|
17
|
+
case "website":
|
|
18
|
+
return createWebsiteProvider;
|
|
19
|
+
default:
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
23
22
|
}
|
|
@@ -3,14 +3,13 @@
|
|
|
3
3
|
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
4
|
import { resolveStashDir } from "../../core/common.js";
|
|
5
5
|
import { ConfigError } from "../../core/errors.js";
|
|
6
|
-
import { registerSourceProvider } from "../provider-factory.js";
|
|
7
6
|
/**
|
|
8
7
|
* Filesystem source — points at a directory the user already manages.
|
|
9
8
|
*
|
|
10
9
|
* Implements {@link SourceProvider} with `{ name, kind, path }`. No `sync()`:
|
|
11
10
|
* content is the user's own directory, never refreshed by akm.
|
|
12
11
|
*/
|
|
13
|
-
|
|
12
|
+
export function createFilesystemProvider(entry) {
|
|
14
13
|
if (entry.type !== "filesystem") {
|
|
15
14
|
throw new ConfigError(`filesystem source invoked with type="${entry.type}"`);
|
|
16
15
|
}
|
|
@@ -26,4 +25,4 @@ registerSourceProvider("filesystem", (entry) => {
|
|
|
26
25
|
return stashDir;
|
|
27
26
|
},
|
|
28
27
|
};
|
|
29
|
-
}
|
|
28
|
+
}
|
|
@@ -114,8 +114,14 @@ function normalizeRemoteUrl(value) {
|
|
|
114
114
|
.replace(/\/+$/, "")
|
|
115
115
|
.replace(/\.git$/i, "");
|
|
116
116
|
}
|
|
117
|
-
|
|
117
|
+
/**
|
|
118
|
+
* Move a fully materialized directory into place. POSIX cannot rename over a
|
|
119
|
+
* non-empty directory, so the old one is renamed aside first and restored if
|
|
120
|
+
* the second rename fails; the destination is missing for one syscall at most.
|
|
121
|
+
*/
|
|
122
|
+
export function replaceDirectory(stagedDir, destination) {
|
|
118
123
|
const backup = `${destination}.backup-${randomBytes(4).toString("hex")}`;
|
|
124
|
+
fs.mkdirSync(path.dirname(destination), { recursive: true });
|
|
119
125
|
const hadDestination = fs.existsSync(destination);
|
|
120
126
|
if (hadDestination)
|
|
121
127
|
fs.renameSync(destination, backup);
|
|
@@ -11,7 +11,6 @@ import { ConfigError, UsageError } from "../../core/errors.js";
|
|
|
11
11
|
import { getRegistryIndexCacheDir } from "../../core/paths.js";
|
|
12
12
|
import { validateGitUrl } from "../../registry/resolve.js";
|
|
13
13
|
import { withFreshnessCache } from "../freshness.js";
|
|
14
|
-
import { registerSourceProvider } from "../provider-factory.js";
|
|
15
14
|
import { assertNoIgnoredPathOverwrite, cloneRepo, inspectGitUpstream, runGit } from "./git-install.js";
|
|
16
15
|
import { sanitizeString } from "./provider-utils.js";
|
|
17
16
|
/** Cache TTL before refreshing the mirrored repo (12 hours). */
|
|
@@ -60,8 +59,6 @@ function resolveGitContentDir(config) {
|
|
|
60
59
|
}
|
|
61
60
|
throw new ConfigError("git source entry must have either `path` or `url`");
|
|
62
61
|
}
|
|
63
|
-
// ── Self-register ───────────────────────────────────────────────────────────
|
|
64
|
-
registerSourceProvider("git", (config) => new GitSourceProvider(config));
|
|
65
62
|
// ── Cache management ────────────────────────────────────────────────────────
|
|
66
63
|
export function getCachePaths(repoUrl, cacheRootOverride) {
|
|
67
64
|
const key = createHash("sha256").update(repoUrl).digest("hex").slice(0, 16);
|
|
@@ -25,11 +25,18 @@ import { getCachePaths, parseGitRepoUrl } from "./git-provider.js";
|
|
|
25
25
|
export function isGitBackedStash(stashDir) {
|
|
26
26
|
return fs.existsSync(path.join(stashDir, ".git"));
|
|
27
27
|
}
|
|
28
|
-
/**
|
|
29
|
-
|
|
28
|
+
/**
|
|
29
|
+
* Return repo-relative dirty/staged paths without changing the index, and
|
|
30
|
+
* whether `git status` itself succeeded. A broken submodule, a detached
|
|
31
|
+
* `GIT_DIR`, or git simply not being on `PATH` all exit nonzero here — a
|
|
32
|
+
* caller that would otherwise read the empty `paths` as "nothing is dirty"
|
|
33
|
+
* must check `ok` first (see {@link listGitChangedPaths}'s callers that
|
|
34
|
+
* cannot, and the archive purge sweep, which can and does).
|
|
35
|
+
*/
|
|
36
|
+
export function tryListGitChangedPaths(repoDir) {
|
|
30
37
|
const result = runGit(["-C", repoDir, "status", "--porcelain", "-z", "--untracked-files=all"]);
|
|
31
38
|
if (result.status !== 0)
|
|
32
|
-
return [];
|
|
39
|
+
return { paths: [], ok: false };
|
|
33
40
|
const records = result.stdout.split("\0");
|
|
34
41
|
const paths = [];
|
|
35
42
|
for (let i = 0; i < records.length; i++) {
|
|
@@ -44,7 +51,79 @@ export function listGitChangedPaths(repoDir) {
|
|
|
44
51
|
paths.push(previousPath);
|
|
45
52
|
}
|
|
46
53
|
}
|
|
47
|
-
return paths;
|
|
54
|
+
return { paths, ok: true };
|
|
55
|
+
}
|
|
56
|
+
/** Return repo-relative dirty/staged paths without changing the index. `[]` on any git failure — see {@link tryListGitChangedPaths} for a caller that must tell that apart from "nothing is dirty". */
|
|
57
|
+
export function listGitChangedPaths(repoDir) {
|
|
58
|
+
return tryListGitChangedPaths(repoDir).paths;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Return repo-relative paths git tracks at HEAD/index under `pathspec` (or
|
|
62
|
+
* the whole repo when omitted), and whether `git ls-files` itself
|
|
63
|
+
* succeeded — see {@link tryListGitChangedPaths}, the same contract.
|
|
64
|
+
*/
|
|
65
|
+
export function tryListGitTrackedPaths(repoDir, pathspec) {
|
|
66
|
+
const args = ["-C", repoDir, "ls-files", "-z"];
|
|
67
|
+
if (pathspec)
|
|
68
|
+
args.push("--", pathspec);
|
|
69
|
+
const result = runGit(args);
|
|
70
|
+
if (result.status !== 0)
|
|
71
|
+
return { paths: [], ok: false };
|
|
72
|
+
return { paths: result.stdout.split("\0").filter((record) => record.length > 0), ok: true };
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Return repo-relative paths under `pathspec` that `git ls-files -v` tags as
|
|
76
|
+
* NOT verifiable against the worktree: `assume-unchanged` (a lowercase tag —
|
|
77
|
+
* `ls-files -v` lowercases a file's normal tag letter when that bit is set)
|
|
78
|
+
* or `skip-worktree` (the literal `S`). `git status` silently omits an edit
|
|
79
|
+
* to either kind of file — the index is telling git not to compare it — so a
|
|
80
|
+
* caller that trusts {@link tryListGitChangedPaths} alone would read a
|
|
81
|
+
* genuinely modified file as clean.
|
|
82
|
+
*/
|
|
83
|
+
export function tryListGitUnverifiablePaths(repoDir, pathspec) {
|
|
84
|
+
const args = ["-C", repoDir, "ls-files", "-v", "-z"];
|
|
85
|
+
if (pathspec)
|
|
86
|
+
args.push("--", pathspec);
|
|
87
|
+
const result = runGit(args);
|
|
88
|
+
if (result.status !== 0)
|
|
89
|
+
return { paths: [], ok: false };
|
|
90
|
+
const paths = [];
|
|
91
|
+
for (const record of result.stdout.split("\0")) {
|
|
92
|
+
if (!record)
|
|
93
|
+
continue;
|
|
94
|
+
const tag = record.slice(0, 1);
|
|
95
|
+
if (tag === "S" || (tag >= "a" && tag <= "z"))
|
|
96
|
+
paths.push(record.slice(2));
|
|
97
|
+
}
|
|
98
|
+
return { paths, ok: true };
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* The three-part git cleanliness check shared by the archive purge sweep
|
|
102
|
+
* (`purgeGracedArchive` in `commands/improve/memory/memory-improve.ts`) and
|
|
103
|
+
* the `memory-cleanup-archive` health advisory (`collectArchiveUsageAdvisory`
|
|
104
|
+
* in `commands/health/archive-usage.ts`): a path is safe to treat as
|
|
105
|
+
* committed only if it is tracked ({@link tryListGitTrackedPaths}), not dirty
|
|
106
|
+
* ({@link tryListGitChangedPaths}), and not assume-unchanged/skip-worktree
|
|
107
|
+
* ({@link tryListGitUnverifiablePaths} — those hide their own edits from
|
|
108
|
+
* `git status`, so an unverifiable file is never trusted as clean either).
|
|
109
|
+
*
|
|
110
|
+
* Each of the three git calls can fail independently (a broken submodule, or
|
|
111
|
+
* git missing from `PATH`); `ok` is `false` if any one does, and `isSafe`
|
|
112
|
+
* then returns `false` for every path rather than guessing — callers that
|
|
113
|
+
* need to short-circuit before doing other work still check `ok` themselves.
|
|
114
|
+
*/
|
|
115
|
+
export function checkGitPathSafety(repoDir, pathspec) {
|
|
116
|
+
const dirtyQuery = tryListGitChangedPaths(repoDir);
|
|
117
|
+
const trackedQuery = tryListGitTrackedPaths(repoDir, pathspec);
|
|
118
|
+
const unverifiableQuery = tryListGitUnverifiablePaths(repoDir, pathspec);
|
|
119
|
+
const ok = dirtyQuery.ok && trackedQuery.ok && unverifiableQuery.ok;
|
|
120
|
+
const dirty = new Set(dirtyQuery.paths);
|
|
121
|
+
const tracked = new Set(trackedQuery.paths);
|
|
122
|
+
const unverifiable = new Set(unverifiableQuery.paths);
|
|
123
|
+
return {
|
|
124
|
+
ok,
|
|
125
|
+
isSafe: (repoRelativePath) => ok && tracked.has(repoRelativePath) && !dirty.has(repoRelativePath) && !unverifiable.has(repoRelativePath),
|
|
126
|
+
};
|
|
48
127
|
}
|
|
49
128
|
export class GitStashPushError extends Error {
|
|
50
129
|
commit;
|
|
@@ -204,9 +283,6 @@ export function saveGitStash(name, message, writableOverride, options) {
|
|
|
204
283
|
}
|
|
205
284
|
assertNoIgnoredExactPaths(repoDir, requestedPaths);
|
|
206
285
|
const baseHead = readOptionalHead(repoDir);
|
|
207
|
-
if (options?.expectedBaseHead !== undefined && (baseHead ?? null) !== options.expectedBaseHead) {
|
|
208
|
-
throw new Error(`Git target advanced before its exact-path commit could be created.`);
|
|
209
|
-
}
|
|
210
286
|
const remoteResult = runGit(["-C", repoDir, "remote"]);
|
|
211
287
|
if (remoteResult.status !== 0) {
|
|
212
288
|
throw new Error(`git remote failed: ${remoteResult.stderr?.trim() || "unknown error"}`);
|
|
@@ -300,20 +376,6 @@ export function assertNoIgnoredExactPaths(repoDir, paths) {
|
|
|
300
376
|
throw new UsageError(`Exact Git publication path is ignored: ${ignored[0]}. Update .gitignore or choose a tracked destination before writing.`);
|
|
301
377
|
}
|
|
302
378
|
}
|
|
303
|
-
/** Reject exact staged/unstaged paths before an AKM filesystem mutation. */
|
|
304
|
-
export function assertGitExactPathsClean(repoDir, paths) {
|
|
305
|
-
const normalized = normalizeExactPaths(repoDir, paths);
|
|
306
|
-
assertNoIgnoredExactPaths(repoDir, normalized);
|
|
307
|
-
for (const result of runExactPathChunks(repoDir, ["status", "--porcelain=v1", "-z", "--untracked-files=all"], normalized)) {
|
|
308
|
-
if (result.status !== 0) {
|
|
309
|
-
throw new Error(`git status failed: ${result.stderr.trim() || "unknown error"}`);
|
|
310
|
-
}
|
|
311
|
-
if (result.stdout.length > 0) {
|
|
312
|
-
const record = result.stdout.split("\0").find(Boolean) ?? "";
|
|
313
|
-
throw new UsageError(`Exact Git operation path has staged or unstaged work: ${record.slice(3)}. Commit, stash, or discard that path before retrying.`);
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
379
|
function readOptionalHead(repoDir) {
|
|
318
380
|
const result = runGit(["-C", repoDir, "rev-parse", "--verify", "HEAD"]);
|
|
319
381
|
return result.status === 0 && result.stdout.trim() ? result.stdout.trim() : undefined;
|
|
@@ -13,8 +13,7 @@ import fs from "node:fs";
|
|
|
13
13
|
import path from "node:path";
|
|
14
14
|
import { ConfigError, UsageError } from "../../core/errors.js";
|
|
15
15
|
import { getRegistryCacheDir } from "../../core/paths.js";
|
|
16
|
-
import {
|
|
17
|
-
import { registerSourceProvider } from "../provider-factory.js";
|
|
16
|
+
import { parseRegistryRef, resolveRegistryArtifact } from "../../registry/resolve.js";
|
|
18
17
|
import { applyAkmIncludeConfig, buildInstallCacheDir, computeFileHash, detectStashRoot, downloadArchive, isDirectory, } from "./provider-utils.js";
|
|
19
18
|
import { extractTarGzSecure, verifyArchiveIntegrity } from "./tar-utils.js";
|
|
20
19
|
/**
|
|
@@ -45,7 +44,6 @@ class NpmSourceProvider {
|
|
|
45
44
|
await syncNpmRef(ref, { force: options?.force });
|
|
46
45
|
}
|
|
47
46
|
}
|
|
48
|
-
registerSourceProvider("npm", (config) => new NpmSourceProvider(config));
|
|
49
47
|
function npmRefFromConfig(config) {
|
|
50
48
|
const candidate = config.path;
|
|
51
49
|
if (typeof candidate !== "string" || !candidate) {
|
|
@@ -108,7 +106,7 @@ async function doSyncNpm(parsed, options) {
|
|
|
108
106
|
let installRoot;
|
|
109
107
|
let stashRoot;
|
|
110
108
|
try {
|
|
111
|
-
await downloadArchive(resolved.artifactUrl, archivePath
|
|
109
|
+
await downloadArchive(resolved.artifactUrl, archivePath);
|
|
112
110
|
verifyArchiveIntegrity(archivePath, resolved.resolvedRevision, resolved.source);
|
|
113
111
|
integrity = await computeFileHash(archivePath);
|
|
114
112
|
extractTarGzSecure(archivePath, extractedDir);
|
|
@@ -6,7 +6,7 @@ import fs from "node:fs";
|
|
|
6
6
|
import path from "node:path";
|
|
7
7
|
import { getAdapters } from "../../core/adapter/registry.js";
|
|
8
8
|
import { stashDirNames } from "../../core/asset/asset-placement.js";
|
|
9
|
-
import {
|
|
9
|
+
import { fetchRegistry } from "../../registry/network.js";
|
|
10
10
|
import { writeResponseToFileCapped } from "../../runtime.js";
|
|
11
11
|
import { copyIncludedPaths, findNearestIncludeConfig } from "../include.js";
|
|
12
12
|
const REGISTRY_STASH_DIR_NAMES = new Set(stashDirNames());
|
|
@@ -99,15 +99,10 @@ export function applyAkmIncludeConfig(sourceRoot, cacheDir, searchRoot = sourceR
|
|
|
99
99
|
return selectedDir;
|
|
100
100
|
}
|
|
101
101
|
/** Stream a remote archive to disk via the runtime boundary's response writer. */
|
|
102
|
-
export async function downloadArchive(url, destination
|
|
103
|
-
const response = await
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
throw new Error(`Failed to download archive (${response.status}) from ${url}`);
|
|
107
|
-
}
|
|
108
|
-
// Stream to disk with an explicit byte cap + body-read deadline: the fetch
|
|
109
|
-
// timeout above bounds only the connection/header phase, so an unbounded or
|
|
110
|
-
// dribbling body could otherwise fill the disk or hang the install forever.
|
|
102
|
+
export async function downloadArchive(url, destination) {
|
|
103
|
+
const response = await fetchRegistry(url, { timeoutMs: 120_000 });
|
|
104
|
+
// Stream to disk with an explicit byte cap + body-read deadline so an
|
|
105
|
+
// unbounded or dribbling body cannot fill the disk or hang the install.
|
|
111
106
|
await writeResponseToFileCapped(destination, response);
|
|
112
107
|
}
|
|
113
108
|
/** SHA-256 of a file, returned as `sha256:<hex>`. */
|
|
@@ -2,7 +2,6 @@
|
|
|
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 { registerSourceProvider } from "../provider-factory.js";
|
|
6
5
|
import { getWebsiteCachePaths, shouldAllowPrivateWebsiteUrlForTests, validateWebsiteUrl } from "../website-url.js";
|
|
7
6
|
/** Website source provider — URL-derived path plus an injected mirror refresh. */
|
|
8
7
|
export function createWebsiteProvider(config) {
|
|
@@ -33,4 +32,3 @@ export function createWebsiteProvider(config) {
|
|
|
33
32
|
},
|
|
34
33
|
};
|
|
35
34
|
}
|
|
36
|
-
registerSourceProvider("website", createWebsiteProvider);
|
|
@@ -76,7 +76,7 @@ function resolveFetcherStashDir(explicitStashDir) {
|
|
|
76
76
|
export async function ensureWebsiteMirror(config, options) {
|
|
77
77
|
const rawUrl = config.url ?? "";
|
|
78
78
|
const normalizedUrl = validateWebsiteUrl(rawUrl, { allowPrivateHosts: options?.allowPrivateHosts });
|
|
79
|
-
const cachePaths = getWebsiteCachePaths(normalizedUrl
|
|
79
|
+
const cachePaths = getWebsiteCachePaths(normalizedUrl);
|
|
80
80
|
const requireStashDir = options?.requireStashDir === true;
|
|
81
81
|
await withFreshnessCache({
|
|
82
82
|
markerPath: cachePaths.manifestPath,
|
|
@@ -35,9 +35,9 @@ export function shouldAllowPrivateWebsiteUrlForTests(rawUrl) {
|
|
|
35
35
|
}
|
|
36
36
|
return true;
|
|
37
37
|
}
|
|
38
|
-
export function getWebsiteCachePaths(siteUrl
|
|
38
|
+
export function getWebsiteCachePaths(siteUrl) {
|
|
39
39
|
const key = createHash("sha256").update(normalizeSiteUrl(siteUrl)).digest("hex").slice(0, 16);
|
|
40
|
-
const rootDir = path.join(
|
|
40
|
+
const rootDir = path.join(getRegistryIndexCacheDir(), `website-${key}`);
|
|
41
41
|
return {
|
|
42
42
|
rootDir,
|
|
43
43
|
stashDir: path.join(rootDir, "stash"),
|