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
package/dist/registry/resolve.js
CHANGED
|
@@ -6,10 +6,9 @@ import fs from "node:fs";
|
|
|
6
6
|
import os from "node:os";
|
|
7
7
|
import path from "node:path";
|
|
8
8
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
9
|
-
import {
|
|
10
|
-
import { NotFoundError, UsageError } from "../core/errors.js";
|
|
9
|
+
import { ConfigError, NotFoundError, UsageError } from "../core/errors.js";
|
|
11
10
|
import { asRecord, asString, GITHUB_API_BASE, githubHeaders } from "../integrations/github.js";
|
|
12
|
-
import {
|
|
11
|
+
import { fetchRegistryJson } from "./network.js";
|
|
13
12
|
import { isExactSemver, isSemverRange, maxSatisfying } from "./semver.js";
|
|
14
13
|
/**
|
|
15
14
|
* Pass an HTTPS bearer credential to Git without placing it in the remote URL
|
|
@@ -64,12 +63,12 @@ export function validateGitRef(ref) {
|
|
|
64
63
|
export function parseRegistryRef(rawRef) {
|
|
65
64
|
const ref = rawRef.trim();
|
|
66
65
|
if (!ref)
|
|
67
|
-
throw new
|
|
66
|
+
throw new UsageError("Registry ref is required.", "MISSING_REQUIRED_ARGUMENT");
|
|
68
67
|
// Detect registry search result IDs (e.g. "skills-sh:org/skills/name")
|
|
69
68
|
// that are not installable refs. Known installable prefixes are handled below.
|
|
70
69
|
const registryIdHint = detectRegistrySearchId(ref);
|
|
71
70
|
if (registryIdHint) {
|
|
72
|
-
throw new
|
|
71
|
+
throw new UsageError(registryIdHint);
|
|
73
72
|
}
|
|
74
73
|
if (ref.startsWith("npm:")) {
|
|
75
74
|
return parseNpmRef(ref.slice(4), ref);
|
|
@@ -160,7 +159,7 @@ export async function resolveRegistryArtifact(parsed, options) {
|
|
|
160
159
|
function parseNpmRef(input, originalRef) {
|
|
161
160
|
const trimmed = input.trim();
|
|
162
161
|
if (!trimmed)
|
|
163
|
-
throw new
|
|
162
|
+
throw new UsageError("Invalid npm ref.");
|
|
164
163
|
const parsed = splitNpmNameAndVersion(trimmed);
|
|
165
164
|
validateNpmPackageName(parsed.packageName);
|
|
166
165
|
return {
|
|
@@ -175,12 +174,12 @@ function parseGithubShorthand(input, originalRef) {
|
|
|
175
174
|
const [repoPart, requestedRef] = splitRefSuffix(input.trim());
|
|
176
175
|
const segments = repoPart.split("/").filter(Boolean);
|
|
177
176
|
if (segments.length !== 2) {
|
|
178
|
-
throw new
|
|
177
|
+
throw new UsageError("Invalid GitHub ref. Expected owner/repo or owner/repo#ref.");
|
|
179
178
|
}
|
|
180
179
|
const owner = segments[0];
|
|
181
180
|
const repo = segments[1].replace(/\.git$/i, "");
|
|
182
181
|
if (!owner || !repo) {
|
|
183
|
-
throw new
|
|
182
|
+
throw new UsageError("Invalid GitHub ref. Expected owner/repo.");
|
|
184
183
|
}
|
|
185
184
|
return {
|
|
186
185
|
source: "github",
|
|
@@ -197,7 +196,7 @@ function parseRemoteUrl(rawUrl) {
|
|
|
197
196
|
url = new URL(rawUrl);
|
|
198
197
|
}
|
|
199
198
|
catch {
|
|
200
|
-
throw new
|
|
199
|
+
throw new UsageError("Invalid registry URL.");
|
|
201
200
|
}
|
|
202
201
|
if (url.hostname === "github.com") {
|
|
203
202
|
return parseGithubUrl(url, rawUrl);
|
|
@@ -207,7 +206,7 @@ function parseRemoteUrl(rawUrl) {
|
|
|
207
206
|
function parseGithubUrl(url, rawUrl) {
|
|
208
207
|
const segments = url.pathname.split("/").filter(Boolean);
|
|
209
208
|
if (segments.length < 2) {
|
|
210
|
-
throw new
|
|
209
|
+
throw new UsageError("Invalid GitHub URL. Expected https://github.com/owner/repo.");
|
|
211
210
|
}
|
|
212
211
|
const owner = segments[0];
|
|
213
212
|
const repo = segments[1].replace(/\.git$/i, "");
|
|
@@ -224,7 +223,7 @@ function parseGithubUrl(url, rawUrl) {
|
|
|
224
223
|
function parseGitUrl(input, originalRef) {
|
|
225
224
|
const [urlPart, requestedRef] = splitRefSuffix(input.trim());
|
|
226
225
|
if (!urlPart)
|
|
227
|
-
throw new
|
|
226
|
+
throw new UsageError("Invalid git ref. A URL is required.");
|
|
228
227
|
// Normalize the URL for the id (strip .git suffix, fragment)
|
|
229
228
|
const normalized = urlPart.replace(/\.git$/i, "");
|
|
230
229
|
return {
|
|
@@ -251,7 +250,7 @@ function tryParseLocalRef(rawRef, explicitPath) {
|
|
|
251
250
|
}
|
|
252
251
|
if (!stat.isDirectory()) {
|
|
253
252
|
if (explicitPath) {
|
|
254
|
-
throw new
|
|
253
|
+
throw new UsageError("Local add path must be a directory, but the provided path is not one.");
|
|
255
254
|
}
|
|
256
255
|
// Bare name exists but isn't a directory — not a local ref
|
|
257
256
|
return undefined;
|
|
@@ -292,55 +291,11 @@ function isPathLikeRef(ref) {
|
|
|
292
291
|
}
|
|
293
292
|
/** Default public npm registry host. */
|
|
294
293
|
const DEFAULT_NPM_REGISTRY_HOST = "registry.npmjs.org";
|
|
295
|
-
|
|
296
|
-
* Typed error raised when the npm registry returns a tarball URL on a host
|
|
297
|
-
* that is not the public registry or the operator-configured mirror. Carries
|
|
298
|
-
* a stable `.code` so callers (and JSON envelope output) can branch on it
|
|
299
|
-
* without parsing the message string.
|
|
300
|
-
*/
|
|
301
|
-
export class UntrustedNpmTarballError extends Error {
|
|
302
|
-
code = "UNTRUSTED_NPM_TARBALL";
|
|
303
|
-
_hint;
|
|
304
|
-
constructor(msg, hint) {
|
|
305
|
-
super(msg);
|
|
306
|
-
this.name = "UntrustedNpmTarballError";
|
|
307
|
-
this._hint = hint;
|
|
308
|
-
Object.setPrototypeOf(this, new.target.prototype);
|
|
309
|
-
}
|
|
310
|
-
hint() {
|
|
311
|
-
return (this._hint ??
|
|
312
|
-
"Set AKM_NPM_REGISTRY to your private npm mirror's base URL if you install from a non-default registry.");
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
/**
|
|
316
|
-
* Resolve the set of npm registry hosts whose tarballs are considered trusted.
|
|
317
|
-
* Always includes the public npm registry, plus the host of an operator-set
|
|
318
|
-
* `AKM_NPM_REGISTRY` environment variable (if it parses to a valid URL).
|
|
319
|
-
*/
|
|
320
|
-
export function trustedNpmTarballHosts() {
|
|
321
|
-
const hosts = new Set([DEFAULT_NPM_REGISTRY_HOST]);
|
|
322
|
-
const override = process.env.AKM_NPM_REGISTRY?.trim();
|
|
323
|
-
if (override) {
|
|
324
|
-
// A malformed override must not be silently ignored (falling back to the
|
|
325
|
-
// public registry as though nothing was configured) — that would install
|
|
326
|
-
// from the wrong registry without telling the operator (R-035).
|
|
327
|
-
let overrideHost;
|
|
328
|
-
try {
|
|
329
|
-
overrideHost = new URL(override).hostname.toLowerCase();
|
|
330
|
-
}
|
|
331
|
-
catch {
|
|
332
|
-
throw new UsageError(`AKM_NPM_REGISTRY is set to an invalid URL: ${override}`);
|
|
333
|
-
}
|
|
334
|
-
if (overrideHost)
|
|
335
|
-
hosts.add(overrideHost);
|
|
336
|
-
}
|
|
337
|
-
return hosts;
|
|
338
|
-
}
|
|
294
|
+
const UNTRUSTED_TARBALL_HINT = "Set AKM_NPM_REGISTRY to your private npm mirror's base URL if you install from a non-default registry.";
|
|
339
295
|
/**
|
|
340
296
|
* Validate that an npm tarball URL starts at the exact metadata registry
|
|
341
|
-
* origin
|
|
342
|
-
*
|
|
343
|
-
* the outbound boundary's hop-by-hop policy.
|
|
297
|
+
* origin: a mirror must not change scheme or port, or nominate a different
|
|
298
|
+
* host, in `dist.tarball`.
|
|
344
299
|
*/
|
|
345
300
|
export function validateNpmTarballUrl(tarballUrl, packageRef, registryOrigin) {
|
|
346
301
|
let url;
|
|
@@ -348,39 +303,20 @@ export function validateNpmTarballUrl(tarballUrl, packageRef, registryOrigin) {
|
|
|
348
303
|
url = new URL(tarballUrl);
|
|
349
304
|
}
|
|
350
305
|
catch {
|
|
351
|
-
throw new
|
|
306
|
+
throw new NotFoundError(`npm package ${packageRef} returned an invalid tarball URL: ${tarballUrl}`, "REGISTRY_RESPONSE_INVALID", UNTRUSTED_TARBALL_HINT);
|
|
352
307
|
}
|
|
353
308
|
if (url.protocol !== "https:" && url.protocol !== "http:") {
|
|
354
|
-
throw new
|
|
309
|
+
throw new NotFoundError(`npm package ${packageRef} returned a tarball with disallowed scheme "${url.protocol}".`, "REGISTRY_RESPONSE_INVALID", UNTRUSTED_TARBALL_HINT);
|
|
355
310
|
}
|
|
356
|
-
const expectedOrigin = registryOrigin ?? new URL(npmMetadataRegistry()
|
|
311
|
+
const expectedOrigin = registryOrigin ?? new URL(npmMetadataRegistry()).origin;
|
|
357
312
|
if (url.origin !== expectedOrigin) {
|
|
358
|
-
throw new
|
|
313
|
+
throw new NotFoundError(`npm package ${packageRef} returned a tarball URL on untrusted origin "${url.origin}" (expected: ${expectedOrigin}).`, "REGISTRY_RESPONSE_INVALID", UNTRUSTED_TARBALL_HINT);
|
|
359
314
|
}
|
|
360
315
|
}
|
|
361
|
-
/** Network policy for a tarball URL that already passed {@link validateNpmTarballUrl}. */
|
|
362
|
-
export function npmArtifactNetworkPolicy(artifact) {
|
|
363
|
-
if (!artifact.registryOrigin) {
|
|
364
|
-
throw new UsageError("npm artifact network policy requires the registry origin that authorized its metadata.");
|
|
365
|
-
}
|
|
366
|
-
return {
|
|
367
|
-
kind: "npm-api",
|
|
368
|
-
registryOrigin: new URL(artifact.registryOrigin).origin,
|
|
369
|
-
allowPrivateRegistryOrigin: artifact.allowPrivateRegistryOrigin === true,
|
|
370
|
-
};
|
|
371
|
-
}
|
|
372
316
|
/**
|
|
373
|
-
*
|
|
374
|
-
*
|
|
375
|
-
*
|
|
376
|
-
* allowlist (see {@link trustedNpmTarballHosts}) while the metadata endpoint
|
|
377
|
-
* stayed hardcoded to the public registry — so an operator-configured mirror
|
|
378
|
-
* was never actually consulted, making the `UntrustedNpmTarballError.hint()`
|
|
379
|
-
* text below false. Honoring the override here for metadata too makes the
|
|
380
|
-
* hint true: installs really do resolve entirely against the configured
|
|
381
|
-
* mirror when it is set, mirroring how a private npm registry replaces the
|
|
382
|
-
* default wholesale (like npm's own `--registry` flag) rather than being
|
|
383
|
-
* merged with it.
|
|
317
|
+
* The npm registry base URL for package METADATA: `AKM_NPM_REGISTRY` when set
|
|
318
|
+
* (a private mirror replaces the default wholesale, like npm's own
|
|
319
|
+
* `--registry`), else the public registry.
|
|
384
320
|
*/
|
|
385
321
|
function npmMetadataRegistry() {
|
|
386
322
|
const override = process.env.AKM_NPM_REGISTRY?.trim();
|
|
@@ -393,22 +329,16 @@ function npmMetadataRegistry() {
|
|
|
393
329
|
url = new URL(override);
|
|
394
330
|
}
|
|
395
331
|
catch {
|
|
396
|
-
throw new
|
|
332
|
+
throw new ConfigError(`AKM_NPM_REGISTRY is set to an invalid URL: ${override}`, "REGISTRY_URL_INVALID");
|
|
397
333
|
}
|
|
398
|
-
|
|
399
|
-
return { baseUrl: base.replace(/\/+$/, ""), allowPrivateRegistryOrigin: true };
|
|
334
|
+
return `${url.origin}${url.pathname === "/" ? "" : url.pathname}`.replace(/\/+$/, "");
|
|
400
335
|
}
|
|
401
|
-
return
|
|
336
|
+
return `https://${DEFAULT_NPM_REGISTRY_HOST}`;
|
|
402
337
|
}
|
|
403
338
|
async function resolveNpmArtifact(parsed) {
|
|
404
339
|
const encodedName = encodeURIComponent(parsed.packageName);
|
|
405
|
-
const
|
|
406
|
-
const
|
|
407
|
-
kind: "npm-api",
|
|
408
|
-
registryOrigin: new URL(npmRegistry.baseUrl).origin,
|
|
409
|
-
allowPrivateRegistryOrigin: npmRegistry.allowPrivateRegistryOrigin,
|
|
410
|
-
};
|
|
411
|
-
const metadata = await fetchJson(`${npmRegistry.baseUrl}/${encodedName}`, undefined, npmPolicy);
|
|
340
|
+
const registryBase = npmMetadataRegistry();
|
|
341
|
+
const metadata = await fetchJson(`${registryBase}/${encodedName}`, undefined);
|
|
412
342
|
const versions = asRecord(metadata.versions);
|
|
413
343
|
const distTags = asRecord(metadata["dist-tags"]);
|
|
414
344
|
const requested = parsed.requestedVersionOrTag;
|
|
@@ -429,15 +359,15 @@ async function resolveNpmArtifact(parsed) {
|
|
|
429
359
|
}
|
|
430
360
|
}
|
|
431
361
|
if (!resolvedVersion || !(resolvedVersion in versions)) {
|
|
432
|
-
throw new
|
|
362
|
+
throw new NotFoundError(`Unable to resolve npm ref "${parsed.ref}".`, "REGISTRY_NOT_FOUND");
|
|
433
363
|
}
|
|
434
364
|
const versionMeta = asRecord(versions[resolvedVersion]);
|
|
435
365
|
const dist = asRecord(versionMeta.dist);
|
|
436
366
|
const tarballUrl = asString(dist.tarball);
|
|
437
367
|
if (!tarballUrl) {
|
|
438
|
-
throw new
|
|
368
|
+
throw new NotFoundError(`npm package ${parsed.packageName}@${resolvedVersion} does not expose a tarball URL.`, "REGISTRY_RESPONSE_INVALID");
|
|
439
369
|
}
|
|
440
|
-
validateNpmTarballUrl(tarballUrl, `${parsed.packageName}@${resolvedVersion}`,
|
|
370
|
+
validateNpmTarballUrl(tarballUrl, `${parsed.packageName}@${resolvedVersion}`, new URL(registryBase).origin);
|
|
441
371
|
const resolvedRevision = asString(dist.shasum) ?? asString(dist.integrity);
|
|
442
372
|
return {
|
|
443
373
|
id: parsed.id,
|
|
@@ -446,8 +376,6 @@ async function resolveNpmArtifact(parsed) {
|
|
|
446
376
|
artifactUrl: tarballUrl,
|
|
447
377
|
resolvedVersion,
|
|
448
378
|
resolvedRevision,
|
|
449
|
-
registryOrigin: npmPolicy.registryOrigin,
|
|
450
|
-
allowPrivateRegistryOrigin: npmPolicy.allowPrivateRegistryOrigin,
|
|
451
379
|
};
|
|
452
380
|
}
|
|
453
381
|
async function resolveGithubArtifact(parsed, credential) {
|
|
@@ -468,7 +396,7 @@ async function resolveGithubArtifact(parsed, credential) {
|
|
|
468
396
|
}
|
|
469
397
|
const headers = { ...githubHeaders(), ...(credential ? { Authorization: `Bearer ${credential}` } : {}) };
|
|
470
398
|
if (parsed.requestedRef) {
|
|
471
|
-
const commit = await tryFetchJson(`${repoBase}/commits/${encodeURIComponent(parsed.requestedRef)}`, headers
|
|
399
|
+
const commit = await tryFetchJson(`${repoBase}/commits/${encodeURIComponent(parsed.requestedRef)}`, headers);
|
|
472
400
|
const resolvedRevision = asString(commit?.sha) ?? parsed.requestedRef;
|
|
473
401
|
return {
|
|
474
402
|
id: parsed.id,
|
|
@@ -479,7 +407,7 @@ async function resolveGithubArtifact(parsed, credential) {
|
|
|
479
407
|
resolvedVersion: parsed.requestedRef,
|
|
480
408
|
};
|
|
481
409
|
}
|
|
482
|
-
const latestRelease = await tryFetchJson(`${repoBase}/releases/latest`, headers
|
|
410
|
+
const latestRelease = await tryFetchJson(`${repoBase}/releases/latest`, headers);
|
|
483
411
|
if (latestRelease) {
|
|
484
412
|
const tarballUrl = asString(latestRelease.tarball_url);
|
|
485
413
|
if (tarballUrl) {
|
|
@@ -493,12 +421,12 @@ async function resolveGithubArtifact(parsed, credential) {
|
|
|
493
421
|
};
|
|
494
422
|
}
|
|
495
423
|
}
|
|
496
|
-
const repoMeta = await fetchJson(repoBase, headers
|
|
424
|
+
const repoMeta = await fetchJson(repoBase, headers);
|
|
497
425
|
const defaultBranch = asString(repoMeta.default_branch);
|
|
498
426
|
if (!defaultBranch) {
|
|
499
|
-
throw new
|
|
427
|
+
throw new NotFoundError(`Unable to resolve default branch for ${parsed.owner}/${parsed.repo}.`, "REGISTRY_RESPONSE_INVALID");
|
|
500
428
|
}
|
|
501
|
-
const commit = await tryFetchJson(`${repoBase}/commits/${encodeURIComponent(defaultBranch)}`, headers
|
|
429
|
+
const commit = await tryFetchJson(`${repoBase}/commits/${encodeURIComponent(defaultBranch)}`, headers);
|
|
502
430
|
return {
|
|
503
431
|
id: parsed.id,
|
|
504
432
|
source: parsed.source,
|
|
@@ -530,7 +458,7 @@ async function resolveGitArtifact(parsed, credential) {
|
|
|
530
458
|
// `git ls-remote`), a plain git source has no fallback resolver — an
|
|
531
459
|
// unresolved revision here would silently disable the post-clone
|
|
532
460
|
// revision-integrity check in `verifyClonedRevision` (R-011).
|
|
533
|
-
throw new
|
|
461
|
+
throw new NotFoundError(`Unable to resolve ${parsed.requestedRef ?? "HEAD"} for ${parsed.url} via 'git ls-remote'; refusing to install without a verifiable revision.`, "REGISTRY_NOT_FOUND");
|
|
534
462
|
}
|
|
535
463
|
return {
|
|
536
464
|
id: parsed.id,
|
|
@@ -573,21 +501,21 @@ function splitNpmNameAndVersion(input) {
|
|
|
573
501
|
}
|
|
574
502
|
function validateNpmPackageName(name) {
|
|
575
503
|
if (!name)
|
|
576
|
-
throw new
|
|
504
|
+
throw new UsageError("Invalid npm package name: name is required.");
|
|
577
505
|
if (name.length > 214)
|
|
578
|
-
throw new
|
|
506
|
+
throw new UsageError(`Invalid npm package name: "${name}" exceeds 214 characters.`);
|
|
579
507
|
if (name !== name.toLowerCase() && !name.startsWith("@")) {
|
|
580
|
-
throw new
|
|
508
|
+
throw new UsageError(`Invalid npm package name: "${name}" must be lowercase.`);
|
|
581
509
|
}
|
|
582
510
|
if (name.startsWith(".") || name.startsWith("_")) {
|
|
583
|
-
throw new
|
|
511
|
+
throw new UsageError(`Invalid npm package name: "${name}" cannot start with . or _.`);
|
|
584
512
|
}
|
|
585
513
|
if (/[~'!()*]/.test(name) ||
|
|
586
514
|
name.includes(" ") ||
|
|
587
515
|
encodeURIComponent(name)
|
|
588
516
|
.replace(/%40/g, "@")
|
|
589
517
|
.replace(/%2[Ff]/g, "/") !== name) {
|
|
590
|
-
throw new
|
|
518
|
+
throw new UsageError(`Invalid npm package name: "${name}" contains invalid characters.`);
|
|
591
519
|
}
|
|
592
520
|
}
|
|
593
521
|
function looksLikeGithubOwnerRepo(ref) {
|
|
@@ -662,24 +590,20 @@ function readGitValue(repoRoot, ...args) {
|
|
|
662
590
|
const value = result.stdout.trim();
|
|
663
591
|
return value || undefined;
|
|
664
592
|
}
|
|
665
|
-
//
|
|
666
|
-
//
|
|
667
|
-
// tens of MB of JSON is a DoS surface, not a feature.
|
|
593
|
+
// npm package manifests and GitHub API responses are typically a few KB; 10 MB
|
|
594
|
+
// is the cap on what one is allowed to send.
|
|
668
595
|
const REGISTRY_JSON_BYTE_CAP = 10 * 1024 * 1024;
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
return null;
|
|
683
|
-
}
|
|
684
|
-
return jsonWithByteCap(response, REGISTRY_JSON_BYTE_CAP, { bodyTimeoutMs: 30_000 });
|
|
596
|
+
async function fetchJson(url, headers) {
|
|
597
|
+
return fetchRegistryJson(url, { headers, timeoutMs: 30_000, maxBytes: REGISTRY_JSON_BYTE_CAP });
|
|
598
|
+
}
|
|
599
|
+
/** `fetchJson` for optional GitHub lookups: a not-found / unusable answer is `null`, a transient failure still throws. */
|
|
600
|
+
async function tryFetchJson(url, headers) {
|
|
601
|
+
try {
|
|
602
|
+
return await fetchJson(url, headers);
|
|
603
|
+
}
|
|
604
|
+
catch (error) {
|
|
605
|
+
if (error instanceof NotFoundError)
|
|
606
|
+
return null;
|
|
607
|
+
throw error;
|
|
608
|
+
}
|
|
685
609
|
}
|