akm-cli 0.9.1 → 0.9.2-alpha.2
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 +103 -28
- package/README.md +3 -1
- package/SECURITY.md +1 -1
- package/STABILITY.md +1 -1
- package/dist/akm +2 -2
- package/dist/akm-migrate +2 -2
- package/dist/assets/hints/cli-hints-full.md +14 -9
- package/dist/assets/improve-strategies/proactive-maintenance.json +1 -1
- package/dist/assets/improve-strategies/reflect-distill.json +1 -1
- package/dist/assets/models.json +35 -0
- package/dist/assets/stash-skeleton/facts/conventions/backlinks.md +3 -4
- package/dist/assets/stash-skeleton/facts/conventions/organization.md +1 -3
- package/dist/assets/tasks/core/extract.yml +6 -5
- package/dist/assets/tasks/core/improve.yml +6 -5
- package/dist/assets/tasks/core/index-refresh.yml +6 -5
- package/dist/assets/tasks/core/sync.yml +6 -5
- package/dist/assets/tasks/core/version-check.yml +6 -5
- package/dist/assets/tasks/improve/akm-graph-refresh-weekly.yml +6 -5
- package/dist/assets/tasks/improve/akm-improve-catchup.yml +6 -5
- package/dist/assets/tasks/improve/akm-improve-consolidate.yml +6 -5
- package/dist/assets/tasks/improve/akm-improve-frequent.yml +6 -5
- package/dist/assets/tasks/improve/akm-improve-nightly.yml +6 -5
- package/dist/cli/confirm.js +2 -2
- package/dist/cli/parse-args.js +3 -24
- package/dist/cli/retired-commands.js +1 -1
- package/dist/cli/shared.js +2 -2
- package/dist/cli.js +11 -9
- package/dist/commands/agent/agent-dispatch.js +55 -89
- package/dist/commands/agent/contribute-cli.js +12 -45
- package/dist/commands/command/builtin-action.js +32 -0
- package/dist/commands/command/command-cli.js +99 -0
- package/dist/commands/command/command-execution.js +308 -0
- package/dist/commands/command/execution-source-loader.js +176 -0
- package/dist/commands/command/portable-template.js +60 -0
- package/dist/commands/config-cli.js +10 -4
- package/dist/commands/env/env.js +4 -2
- package/dist/commands/feedback-cli.js +1 -1
- package/dist/commands/health/checks.js +241 -29
- package/dist/commands/health/html-report.js +0 -14
- package/dist/commands/health/report-view-model.js +0 -1
- package/dist/commands/health/surfaces.js +6 -7
- package/dist/commands/health/types.js +0 -2
- package/dist/commands/health.js +63 -18
- package/dist/commands/improve/collapse-detector.js +5 -6
- package/dist/commands/improve/consolidate.js +251 -214
- package/dist/commands/improve/distill/promote-memory.js +71 -34
- package/dist/commands/improve/distill/quality-gate.js +17 -5
- package/dist/commands/improve/distill.js +232 -155
- package/dist/commands/improve/eligibility.js +112 -79
- package/dist/commands/improve/execution.js +57 -0
- package/dist/commands/improve/extract-cli.js +5 -5
- package/dist/commands/improve/extract-prompt.js +64 -22
- package/dist/commands/improve/extract.js +608 -360
- package/dist/commands/improve/improve-strategies.js +43 -14
- package/dist/commands/improve/improve.js +249 -29
- package/dist/commands/improve/loop-stages.js +11 -17
- package/dist/commands/improve/memory/memory-contradiction-detect.js +90 -66
- package/dist/commands/improve/outcome-loop.js +22 -38
- package/dist/commands/improve/planner.js +134 -0
- package/dist/commands/improve/preparation.js +730 -409
- package/dist/commands/improve/reflect.js +386 -223
- package/dist/commands/improve/run-context.js +3 -4
- package/dist/commands/improve/salience.js +6 -58
- package/dist/commands/improve/session-asset.js +12 -12
- package/dist/commands/lint/index.js +101 -29
- package/dist/commands/migrate-cli.js +11 -69
- package/dist/commands/migration-tool.js +6 -9
- package/dist/commands/models-cli.js +27 -0
- package/dist/commands/proposal/drain.js +258 -186
- package/dist/commands/proposal/proposal-cli.js +32 -10
- package/dist/commands/proposal/proposal.js +2 -5
- package/dist/commands/proposal/propose.js +192 -172
- package/dist/commands/proposal/repository.js +54 -91
- package/dist/commands/proposal/validators/proposal-validators.js +9 -7
- package/dist/commands/read/curate.js +53 -22
- package/dist/commands/read/registry-search.js +25 -9
- package/dist/commands/read/remember-cli.js +14 -2
- package/dist/commands/read/search.js +10 -4
- package/dist/commands/read/show.js +139 -153
- package/dist/commands/registry-cli.js +16 -7
- package/dist/commands/remember.js +33 -18
- package/dist/commands/sources/add-cli.js +19 -178
- package/dist/commands/sources/bundle-cli.js +15 -3
- package/dist/commands/sources/dangerous-env-audit.js +135 -0
- package/dist/commands/sources/info.js +2 -1
- package/dist/commands/sources/installed-stashes.js +901 -177
- package/dist/commands/sources/schema-repair.js +174 -95
- package/dist/commands/sources/self-update.js +30 -74
- package/dist/commands/sources/source-add.js +3 -5
- package/dist/commands/sources/sources-cli.js +2 -15
- package/dist/commands/sources/update-transaction.js +220 -0
- package/dist/commands/tasks/tasks-cli.js +3 -3
- package/dist/commands/tasks/tasks.js +736 -317
- package/dist/commands/workflow-cli.js +2 -2
- package/dist/core/adapter/adapters/agent-skills-adapter.js +3 -0
- package/dist/core/adapter/adapters/akm-adapter.js +85 -35
- package/dist/core/adapter/adapters/akm-lint.js +54 -39
- package/dist/core/adapter/adapters/akm-metadata.js +45 -45
- package/dist/core/adapter/adapters/akm-task-adapter.js +32 -49
- package/dist/core/adapter/adapters/akm-workflow-adapter.js +38 -23
- package/dist/core/adapter/adapters/dotenv-adapter.js +30 -1
- package/dist/core/adapter/adapters/generic-files-adapter.js +11 -0
- package/dist/core/adapter/adapters/index.js +0 -9
- package/dist/core/adapter/adapters/llm-wiki-adapter.js +4 -0
- package/dist/core/adapter/adapters/okf-adapter.js +4 -0
- package/dist/core/adapter/adapters/opencode-adapter.js +5 -8
- package/dist/core/adapter/adapters/tool-dir-shared.js +63 -6
- package/dist/core/adapter/adapters/website-snapshot-adapter.js +4 -0
- package/dist/core/adapter/execution-source.js +308 -0
- package/dist/core/adapter/recognize-match.js +36 -13
- package/dist/core/adapter/registry.js +0 -9
- package/dist/core/asset/stash-meta.js +94 -4
- package/dist/core/common.js +6 -11
- package/dist/core/config/config-io.js +3 -3
- package/dist/core/config/config-schema.js +18 -40
- package/dist/core/config/config-sources.js +11 -21
- package/dist/core/config/config-walker.js +31 -13
- package/dist/core/config/config.js +23 -26
- package/dist/core/config/schema/engines.js +8 -7
- package/dist/core/config/schema/improve-processes.js +29 -5
- package/dist/core/config/schema/index-config.js +0 -27
- package/dist/core/config/schema/primitives.js +1 -23
- package/dist/core/config/schema/sources-bundles.js +13 -16
- package/dist/core/errors.js +2 -0
- package/dist/core/events.js +68 -32
- package/dist/core/extra-params.js +1 -0
- package/dist/core/improve-result.js +315 -0
- package/dist/core/lesson-lint.js +0 -6
- package/dist/core/maintenance-barrier.js +4 -4
- package/dist/core/network-policy.js +152 -0
- package/dist/core/paths.js +1 -1
- package/dist/core/recognition-util.js +4 -4
- package/dist/core/registry-url.js +456 -0
- package/dist/core/state/migrations.js +161 -47
- package/dist/core/state-db.js +453 -80
- package/dist/core/system-error.js +32 -0
- package/dist/core/time.js +2 -12
- package/dist/core/write-source.js +0 -18
- package/dist/execution/directory-identity.js +52 -0
- package/dist/execution/executable-identity.js +107 -0
- package/dist/execution/guarded-source.js +398 -0
- package/dist/execution/json.js +95 -0
- package/dist/{commands/health/types-session-log.js → execution/limits.js} +2 -1
- package/dist/execution/record.js +55 -0
- package/dist/execution/resolved-request.js +730 -0
- package/dist/execution/source.js +320 -0
- package/dist/indexer/bundle-identity-guard.js +5 -4
- package/dist/indexer/db/graph-db.js +33 -0
- package/dist/indexer/graph/graph-boost.js +3 -4
- package/dist/indexer/graph/graph-extraction.js +562 -373
- package/dist/indexer/index-written-assets.js +78 -39
- package/dist/indexer/indexer.js +471 -432
- package/dist/indexer/installations.js +6 -0
- package/dist/indexer/lookup/adapter-concept-owner.js +283 -0
- package/dist/indexer/materialize-embeddings.js +155 -0
- package/dist/indexer/passes/memory-inference.js +227 -174
- package/dist/indexer/passes/metadata.js +263 -118
- package/dist/indexer/scan/doc-to-entry.js +7 -10
- package/dist/indexer/scan/drain-dir.js +51 -23
- package/dist/indexer/search/db-search.js +156 -50
- package/dist/indexer/search/fts-query.js +40 -40
- package/dist/indexer/search/ranking.js +36 -1
- package/dist/indexer/search/search-attribution.js +3 -1
- package/dist/indexer/search/search-fields.js +23 -14
- package/dist/indexer/search/search-hit-enrichers.js +1 -1
- package/dist/indexer/search/search-source.js +7 -16
- package/dist/indexer/search/semantic-status.js +10 -1
- package/dist/indexer/usage/show-usage.js +105 -0
- package/dist/indexer/usage/usage-events.js +7 -2
- package/dist/indexer/walk/matchers.js +40 -10
- package/dist/indexer/walk/path-resolver.js +5 -2
- package/dist/indexer/walk/walker.js +20 -2
- package/dist/integrations/agent/builder-shared.js +3 -6
- package/dist/integrations/agent/conversation-fallback.js +16 -0
- package/dist/integrations/agent/engine-resolution.js +87 -87
- package/dist/integrations/agent/execution-cascade.js +566 -0
- package/dist/integrations/agent/execution-definitions.js +211 -0
- package/dist/integrations/agent/execution-lowering.js +811 -0
- package/dist/integrations/agent/execution-preparation.js +67 -0
- package/dist/integrations/agent/index.js +0 -2
- package/dist/integrations/agent/inline-execution.js +74 -0
- package/dist/integrations/agent/model-map.js +515 -0
- package/dist/integrations/agent/persona-fallback.js +30 -0
- package/dist/integrations/agent/request-lowering.js +186 -0
- package/dist/integrations/agent/runner-dispatch.js +230 -37
- package/dist/integrations/agent/runner.js +12 -83
- package/dist/integrations/harnesses/aider/agent-builder.js +8 -0
- package/dist/integrations/harnesses/aider/index.js +0 -1
- package/dist/integrations/harnesses/amazonq/agent-builder.js +8 -0
- package/dist/integrations/harnesses/amazonq/index.js +0 -1
- package/dist/integrations/harnesses/claude/agent-builder.js +14 -1
- package/dist/integrations/harnesses/claude/index.js +1 -5
- package/dist/integrations/harnesses/claude/session-log.js +3 -33
- package/dist/integrations/harnesses/codex/agent-builder.js +8 -0
- package/dist/integrations/harnesses/codex/index.js +0 -1
- package/dist/integrations/harnesses/copilot/agent-builder.js +8 -0
- package/dist/integrations/harnesses/copilot/index.js +0 -1
- package/dist/integrations/harnesses/gemini/agent-builder.js +8 -0
- package/dist/integrations/harnesses/gemini/index.js +0 -1
- package/dist/integrations/harnesses/index.js +4 -44
- package/dist/integrations/harnesses/opencode/agent-builder.js +16 -9
- package/dist/integrations/harnesses/opencode/index.js +0 -2
- package/dist/integrations/harnesses/opencode/session-log.js +14 -204
- package/dist/integrations/harnesses/opencode-sdk/harness.js +12 -1
- package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +40 -42
- package/dist/integrations/harnesses/openhands/agent-builder.js +8 -0
- package/dist/integrations/harnesses/openhands/index.js +0 -1
- package/dist/integrations/harnesses/pi/agent-builder.js +8 -0
- package/dist/integrations/harnesses/pi/index.js +0 -1
- package/dist/integrations/harnesses/shared.js +0 -1
- package/dist/integrations/harnesses/types.js +1 -3
- package/dist/integrations/lockfile.js +82 -79
- package/dist/integrations/session-logs/index.js +6 -17
- package/dist/integrations/session-logs/provider-base.js +1 -29
- package/dist/llm/client.js +10 -5
- package/dist/llm/embedder.js +6 -7
- package/dist/llm/embedders/local.js +37 -88
- package/dist/llm/embedders/types.js +1 -1
- package/dist/llm/graph-extract.js +75 -50
- package/dist/llm/index-passes.js +43 -5
- package/dist/llm/memory-infer.js +8 -6
- package/dist/llm/metadata-enhance.js +5 -3
- package/dist/llm/structured-call.js +122 -25
- package/dist/output/format-exempt.js +1 -1
- package/dist/output/render-registry.js +0 -16
- package/dist/output/renderers.js +12 -7
- package/dist/output/shapes/curate.js +1 -0
- package/dist/output/shapes/helpers.js +10 -2
- package/dist/output/shapes/passthrough.js +2 -0
- package/dist/output/text/command-format.js +31 -33
- package/dist/output/text/health-format.js +1 -29
- package/dist/output/text/migrate.js +6 -56
- package/dist/output/text/proposal-format.js +16 -1
- package/dist/output/text/workflow-format.js +16 -0
- package/dist/registry/network.js +279 -0
- package/dist/registry/pinned-request-helper.js +247 -0
- package/dist/registry/pinned-transport.js +717 -0
- package/dist/registry/providers/skills-sh.js +18 -6
- package/dist/registry/providers/static-index.js +20 -7
- package/dist/registry/resolve.js +53 -28
- package/dist/scripts/akm-migrate-node.js +19334 -52269
- package/dist/scripts/akm-migrate.js +19270 -51612
- package/dist/setup/registry-stash-loader.js +64 -20
- package/dist/setup/semantic-assets.js +9 -34
- package/dist/setup/setup.js +12 -30
- package/dist/setup/source-identity.js +17 -0
- package/dist/setup/steps/sources.js +36 -15
- package/dist/setup/steps/tasks.js +39 -11
- package/dist/sources/providers/git-provider.js +3 -3
- package/dist/sources/providers/npm.js +2 -2
- package/dist/sources/providers/provider-utils.js +4 -3
- package/dist/sources/providers/website.js +11 -7
- package/dist/sources/snapshot-fetchers/host-guard.js +9 -136
- package/dist/sources/snapshot-fetchers/website-ingest.js +25 -109
- package/dist/sources/website-url.js +73 -0
- package/dist/storage/engines/sqlite-migrations.js +81 -26
- package/dist/storage/managed-db.js +27 -24
- package/dist/storage/repositories/events-repository.js +3 -0
- package/dist/storage/repositories/index-connection.js +42 -10
- package/dist/storage/repositories/index-entries-repository.js +203 -229
- package/dist/storage/repositories/index-entry-mapper.js +8 -12
- package/dist/storage/repositories/index-entry-schema.js +255 -0
- package/dist/storage/repositories/index-fts-repository.js +64 -71
- package/dist/storage/repositories/index-llm-cache-repository.js +8 -13
- package/dist/storage/repositories/index-meta-repository.js +0 -11
- package/dist/storage/repositories/index-schema.js +74 -350
- package/dist/storage/repositories/index-utility-repository.js +12 -17
- package/dist/storage/repositories/index-vec-repository.js +56 -7
- package/dist/storage/repositories/proposals-repository.js +4 -127
- package/dist/storage/repositories/registry-cache.js +2 -1
- package/dist/storage/repositories/task-history-repository.js +20 -40
- package/dist/storage/repositories/workflow-runs-repository.js +228 -129
- package/dist/storage/sqlite-read-snapshot.js +148 -0
- package/dist/tasks/backends/cron.js +170 -42
- package/dist/tasks/backends/index.js +1 -1
- package/dist/tasks/backends/launchd.js +787 -202
- package/dist/tasks/backends/schtasks.js +282 -83
- package/dist/tasks/embedded.js +7 -7
- package/dist/tasks/frozen-script.js +50 -0
- package/dist/tasks/resolve-akm-bin.js +5 -1
- package/dist/tasks/runner.js +239 -251
- package/dist/tasks/runtime-v3.js +281 -0
- package/dist/tasks/scheduler-binding.js +272 -0
- package/dist/tasks/scheduler-invocation.js +57 -43
- package/dist/tasks/scheduler-sync.js +654 -0
- package/dist/tasks/source-v3.js +752 -0
- package/dist/tasks/standalone-script-entry.js +5 -0
- package/dist/tasks/task-id.js +29 -0
- package/dist/workflows/authoring/authoring.js +15 -32
- package/dist/workflows/exec/dispatch-redaction.js +14 -8
- package/dist/workflows/exec/exec-unit.js +7 -28
- package/dist/workflows/exec/frozen-judge.js +57 -89
- package/dist/workflows/exec/lowering-notices.js +23 -0
- package/dist/workflows/exec/native-executor.js +301 -458
- package/dist/workflows/exec/param-secrets.js +4 -3
- package/dist/workflows/exec/run-workflow.js +26 -32
- package/dist/workflows/exec/step-work.js +105 -109
- package/dist/workflows/exec/unit-dispatch.js +103 -27
- package/dist/workflows/exec/unit-writer.js +3 -3
- package/dist/workflows/exec/worktree.js +2 -2
- package/dist/workflows/ir/compile.js +86 -72
- package/dist/workflows/ir/environment-v4.js +328 -0
- package/dist/workflows/ir/freeze-v4.js +122 -0
- package/dist/workflows/ir/plan-hash.js +13 -7
- package/dist/workflows/ir/schema-v4.js +525 -0
- package/dist/workflows/ir/schema.js +25 -284
- package/dist/workflows/ir/source-freeze-v4.js +506 -0
- package/dist/workflows/parser.js +27 -24
- package/dist/workflows/program/schema.js +1 -2
- package/dist/workflows/renderer.js +42 -29
- package/dist/workflows/resource-limits.js +4 -5
- package/dist/workflows/runtime/agent-identity.js +11 -13
- package/dist/workflows/runtime/plan-classifier.js +8 -8
- package/dist/workflows/runtime/runs.js +27 -43
- package/dist/workflows/runtime/workflow-asset-loader.js +45 -205
- package/dist/workflows/source-files.js +373 -0
- package/dist/workflows/source-ir/compile.js +196 -0
- package/dist/workflows/source-ir/github-yaml.js +577 -0
- package/dist/workflows/source-ir/ordering.js +38 -0
- package/dist/workflows/source-ir/program.js +50 -0
- package/dist/workflows/source-ir/result.js +26 -0
- package/dist/workflows/source-ir/schema.js +772 -0
- package/dist/workflows/source-ir/semantics.js +242 -0
- package/dist/workflows/source-ir/uses.js +14 -0
- package/docs/README.md +2 -0
- package/docs/migration/README.md +3 -1
- package/docs/migration/release-notes/0.9.2.md +55 -0
- package/docs/migration/release-notes/README.md +5 -0
- package/docs/migration/v0.8-to-v0.9.md +76 -1077
- package/docs/migration/v0.9.0-troubleshooting.md +104 -516
- package/docs/migration/v0.9.1-to-v0.9.2.md +150 -0
- package/docs/reference/README.md +1 -0
- package/docs/reference/cli.md +230 -98
- package/docs/reference/configuration.md +159 -36
- package/docs/reference/data-and-telemetry.md +19 -1
- package/docs/reference/supported-formats.md +23 -3
- package/docs/reference/tasks.md +182 -0
- package/docs/reference/workflow-schema.md +91 -40
- package/docs/reference/workflows.md +33 -6
- package/package.json +10 -6
- package/schemas/akm-config.json +372 -224
- package/schemas/akm-task.json +324 -80
- package/schemas/akm-workflow.json +6 -9
- package/dist/core/migration-operation.js +0 -75
- package/dist/integrations/agent/model-aliases.js +0 -74
- package/dist/tasks/parser.js +0 -380
- package/dist/tasks/schema.js +0 -123
- package/dist/tasks/validator.js +0 -80
- package/dist/workflows/ir/freeze.js +0 -320
- package/dist/workflows/runtime/document-cache.js +0 -13
|
@@ -8,19 +8,29 @@
|
|
|
8
8
|
* using a cached result when available. Falls back to FALLBACK_STASHES
|
|
9
9
|
* when the registry is unreachable or returns no results.
|
|
10
10
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
11
|
+
* Default-selected registry IDs are also bound to an authenticated install
|
|
12
|
+
* target below so a configured registry cannot preselect a different source
|
|
13
|
+
* merely by reusing a trusted display ID.
|
|
13
14
|
*/
|
|
15
|
+
import { jsonWithByteCap } from "../core/common.js";
|
|
16
|
+
import { hasRegistryUrlCredentials } from "../core/registry-url.js";
|
|
17
|
+
import { allowPrivateRegistryFixtureForTests, cancelRegistryResponse, fetchRegistryResponse, } from "../registry/network.js";
|
|
18
|
+
import { parseRegistryRef } from "../registry/resolve.js";
|
|
14
19
|
// ── Default selections ──────────────────────────────────────────────────────
|
|
15
20
|
/**
|
|
16
21
|
* Registry stash IDs that are pre-selected by default during setup.
|
|
17
|
-
*
|
|
18
|
-
*
|
|
22
|
+
* IDs must match the `id` field in the official registry index and have a
|
|
23
|
+
* matching target in AUTHENTICATED_DEFAULT_TARGETS.
|
|
19
24
|
*
|
|
20
|
-
*
|
|
21
|
-
* in the setup wizard. No other change is required to adjust defaults.
|
|
25
|
+
* The target binding is intentionally separate from display metadata.
|
|
22
26
|
*/
|
|
23
27
|
export const DEFAULT_SELECTED_STASH_IDS = ["itlackey/akm-stash"];
|
|
28
|
+
const AUTHENTICATED_DEFAULT_TARGETS = {
|
|
29
|
+
"itlackey/akm-stash": {
|
|
30
|
+
installType: "git",
|
|
31
|
+
url: "https://github.com/itlackey/akm-stash",
|
|
32
|
+
},
|
|
33
|
+
};
|
|
24
34
|
// ── Fallback list ───────────────────────────────────────────────────────────
|
|
25
35
|
/**
|
|
26
36
|
* Hardcoded stash list used when the registry is unreachable.
|
|
@@ -32,6 +42,7 @@ const FALLBACK_STASHES = [
|
|
|
32
42
|
name: "itlackey/akm-stash",
|
|
33
43
|
description: "Official AKM onboarding bundle",
|
|
34
44
|
url: "https://github.com/itlackey/akm-stash",
|
|
45
|
+
installType: "git",
|
|
35
46
|
source: "fallback",
|
|
36
47
|
defaultSelected: true,
|
|
37
48
|
},
|
|
@@ -40,6 +51,7 @@ const FALLBACK_STASHES = [
|
|
|
40
51
|
name: "andrewyng/context-hub",
|
|
41
52
|
description: "Optional community prompt and context bundle",
|
|
42
53
|
url: "https://github.com/andrewyng/context-hub",
|
|
54
|
+
installType: "git",
|
|
43
55
|
source: "fallback",
|
|
44
56
|
defaultSelected: false,
|
|
45
57
|
},
|
|
@@ -62,19 +74,27 @@ export function _setLoadSetupStashesForTests(fake) {
|
|
|
62
74
|
* @param timeoutMs Fetch timeout in ms (default: 4000).
|
|
63
75
|
*/
|
|
64
76
|
export async function loadSetupStashes(registryUrl, timeoutMs = 4000) {
|
|
77
|
+
if (hasRegistryUrlCredentials(registryUrl))
|
|
78
|
+
return FALLBACK_STASHES;
|
|
65
79
|
if (loadSetupStashesOverride)
|
|
66
80
|
return loadSetupStashesOverride(registryUrl, timeoutMs);
|
|
67
81
|
return loadSetupStashesReal(registryUrl, timeoutMs);
|
|
68
82
|
}
|
|
69
83
|
async function loadSetupStashesReal(registryUrl, timeoutMs = 4000) {
|
|
70
84
|
try {
|
|
71
|
-
const response = await
|
|
72
|
-
|
|
73
|
-
|
|
85
|
+
const response = await fetchRegistryResponse(registryUrl, { headers: { Accept: "application/json" } }, {
|
|
86
|
+
policy: { kind: "public-registry" },
|
|
87
|
+
timeoutMs,
|
|
88
|
+
retries: 0,
|
|
89
|
+
allowPrivateHostsForTesting: allowPrivateRegistryFixtureForTests(registryUrl),
|
|
74
90
|
});
|
|
75
|
-
if (!response.ok)
|
|
91
|
+
if (!response.ok) {
|
|
92
|
+
await cancelRegistryResponse(response);
|
|
76
93
|
return FALLBACK_STASHES;
|
|
77
|
-
|
|
94
|
+
}
|
|
95
|
+
const raw = await jsonWithByteCap(response, 10 * 1024 * 1024, {
|
|
96
|
+
bodyTimeoutMs: timeoutMs,
|
|
97
|
+
});
|
|
78
98
|
if (!Array.isArray(raw.stashes) || raw.stashes.length === 0)
|
|
79
99
|
return FALLBACK_STASHES;
|
|
80
100
|
const entries = raw.stashes.flatMap((item) => {
|
|
@@ -84,22 +104,17 @@ async function loadSetupStashesReal(registryUrl, timeoutMs = 4000) {
|
|
|
84
104
|
const id = typeof s.id === "string" ? s.id : "";
|
|
85
105
|
const name = typeof s.name === "string" ? s.name : id;
|
|
86
106
|
const description = typeof s.description === "string" ? s.description : "";
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
? `https://github.com/${s.ref.replace(/^github:/, "")}`
|
|
90
|
-
: typeof s.homepage === "string"
|
|
91
|
-
? s.homepage
|
|
92
|
-
: "";
|
|
93
|
-
if (!id || !url)
|
|
107
|
+
const target = setupInstallTarget(s.source, s.ref);
|
|
108
|
+
if (!id || !target)
|
|
94
109
|
return [];
|
|
95
110
|
return [
|
|
96
111
|
{
|
|
97
112
|
id,
|
|
98
113
|
name,
|
|
99
114
|
description,
|
|
100
|
-
|
|
115
|
+
...target,
|
|
101
116
|
source: "registry",
|
|
102
|
-
defaultSelected:
|
|
117
|
+
defaultSelected: authenticatedDefaultTarget(id, target),
|
|
103
118
|
},
|
|
104
119
|
];
|
|
105
120
|
});
|
|
@@ -109,3 +124,32 @@ async function loadSetupStashesReal(registryUrl, timeoutMs = 4000) {
|
|
|
109
124
|
return FALLBACK_STASHES;
|
|
110
125
|
}
|
|
111
126
|
}
|
|
127
|
+
function authenticatedDefaultTarget(id, target) {
|
|
128
|
+
const expected = AUTHENTICATED_DEFAULT_TARGETS[id];
|
|
129
|
+
return expected?.installType === target.installType && expected.url === target.url;
|
|
130
|
+
}
|
|
131
|
+
function setupInstallTarget(source, ref) {
|
|
132
|
+
if (typeof ref !== "string")
|
|
133
|
+
return undefined;
|
|
134
|
+
try {
|
|
135
|
+
if (source === "npm") {
|
|
136
|
+
const candidate = ref.startsWith("npm:") ? ref : `npm:${ref}`;
|
|
137
|
+
const parsed = parseRegistryRef(candidate);
|
|
138
|
+
return parsed.source === "npm" ? { installType: "npm", url: candidate } : undefined;
|
|
139
|
+
}
|
|
140
|
+
if (source === "github") {
|
|
141
|
+
const candidate = ref.startsWith("github:") ? ref : `github:${ref}`;
|
|
142
|
+
const parsed = parseRegistryRef(candidate);
|
|
143
|
+
if (parsed.source !== "github")
|
|
144
|
+
return undefined;
|
|
145
|
+
return {
|
|
146
|
+
installType: "git",
|
|
147
|
+
url: `https://github.com/${encodeURIComponent(parsed.owner)}/${encodeURIComponent(parsed.repo)}`,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
catch {
|
|
152
|
+
// Malformed registry install refs are omitted without breaking setup.
|
|
153
|
+
}
|
|
154
|
+
return undefined;
|
|
155
|
+
}
|
|
@@ -2,18 +2,16 @@
|
|
|
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
|
/**
|
|
5
|
-
* Semantic-search asset preparation for the setup wizard.
|
|
6
|
-
*
|
|
7
|
-
*
|
|
5
|
+
* Semantic-search asset preparation for the setup wizard. Transformers.js is
|
|
6
|
+
* a normal external package dependency; setup never mutates the installed CLI.
|
|
7
|
+
* This module only prepares the model and probes sqlite-vec.
|
|
8
8
|
*/
|
|
9
9
|
import fs from "node:fs";
|
|
10
10
|
import os from "node:os";
|
|
11
11
|
import path from "node:path";
|
|
12
12
|
import * as p from "../cli/clack.js";
|
|
13
13
|
import { isHttpUrl } from "../core/common.js";
|
|
14
|
-
import { runManagedSubprocess } from "../core/subprocess.js";
|
|
15
14
|
import { checkEmbeddingAvailability, DEFAULT_LOCAL_MODEL, isTransformersAvailable } from "../llm/embedder.js";
|
|
16
|
-
import { getDirname } from "../runtime.js";
|
|
17
15
|
import { closeDatabase, openIndexDatabase } from "../storage/repositories/index-connection.js";
|
|
18
16
|
import { isVecAvailable } from "../storage/repositories/index-vec-repository.js";
|
|
19
17
|
// Approximate first-download sizes used in the setup note.
|
|
@@ -41,34 +39,12 @@ export function describeSemanticSearchAssets(embedding) {
|
|
|
41
39
|
}
|
|
42
40
|
export async function prepareSemanticSearchAssets(config) {
|
|
43
41
|
const remote = isRemoteEmbeddingConfig(config.embedding);
|
|
44
|
-
//
|
|
42
|
+
// Local embeddings require the declared Transformers dependency.
|
|
45
43
|
if (!remote) {
|
|
46
44
|
if (!isTransformersAvailable()) {
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
const pkgRoot = path.resolve(getDirname(import.meta.url), "../..");
|
|
51
|
-
// Bounded (10 min) so a stalled `bun add` can't hang setup forever.
|
|
52
|
-
const result = await runManagedSubprocess(["bun", "add", "@huggingface/transformers"], {
|
|
53
|
-
capture: true,
|
|
54
|
-
cwd: pkgRoot,
|
|
55
|
-
timeoutMs: 10 * 60_000,
|
|
56
|
-
});
|
|
57
|
-
if (result.spawnError)
|
|
58
|
-
throw result.spawnError;
|
|
59
|
-
if (result.exitCode !== 0) {
|
|
60
|
-
throw new Error(result.stderr || `exit code ${result.exitCode}`);
|
|
61
|
-
}
|
|
62
|
-
spin.stop("@huggingface/transformers installed.");
|
|
63
|
-
}
|
|
64
|
-
catch (err) {
|
|
65
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
66
|
-
spin.stop("Could not install @huggingface/transformers.");
|
|
67
|
-
p.log.warn(`Automatic install failed: ${msg}\n` +
|
|
68
|
-
"Install it manually with: bun add @huggingface/transformers\n" +
|
|
69
|
-
"Then re-run `akm setup` or `akm index --full --verbose`.");
|
|
70
|
-
return { ok: false, reason: "missing-package", message: `Automatic install failed: ${msg}` };
|
|
71
|
-
}
|
|
45
|
+
const message = "The @huggingface/transformers dependency is unavailable. Reinstall akm-cli, then re-run `akm setup` or `akm index --full --verbose`.";
|
|
46
|
+
p.log.warn(message);
|
|
47
|
+
return { ok: false, reason: "missing-package", message };
|
|
72
48
|
}
|
|
73
49
|
}
|
|
74
50
|
const spin = p.spinner();
|
|
@@ -83,9 +59,8 @@ export async function prepareSemanticSearchAssets(config) {
|
|
|
83
59
|
return { ok: false, reason: "remote-network", message: "The remote embedding endpoint is not reachable." };
|
|
84
60
|
}
|
|
85
61
|
else if (result.reason === "missing-package") {
|
|
86
|
-
p.log.warn("@huggingface/transformers is
|
|
87
|
-
|
|
88
|
-
return { ok: false, reason: "missing-package", message: "@huggingface/transformers is not installed." };
|
|
62
|
+
p.log.warn("The @huggingface/transformers dependency is unavailable. Reinstall akm-cli, then re-run `akm setup` or `akm index --full --verbose`.");
|
|
63
|
+
return { ok: false, reason: "missing-package", message: "The local embedding runtime is unavailable." };
|
|
89
64
|
}
|
|
90
65
|
else {
|
|
91
66
|
p.log.warn(`The local embedding model could not be downloaded: ${result.message}\n` +
|
package/dist/setup/setup.js
CHANGED
|
@@ -41,6 +41,7 @@ import { detectHarnessConfigs } from "./harness-config-import.js";
|
|
|
41
41
|
import { bail, prompt } from "./prompt.js";
|
|
42
42
|
import { PROVIDER_DEFAULTS } from "./providers.js";
|
|
43
43
|
import { prepareSemanticSearchAssets } from "./semantic-assets.js";
|
|
44
|
+
import { canonicalSetupGitUrl } from "./source-identity.js";
|
|
44
45
|
import { createSetupContext, runSetupSteps } from "./steps.js";
|
|
45
46
|
import { stepAgentConnection, stepLlm, stepOllama, stepSmallModelConnection } from "./steps/connection.js";
|
|
46
47
|
import { stepOutputConfig } from "./steps/output.js";
|
|
@@ -66,7 +67,7 @@ import { stepScheduledTasks } from "./steps/tasks.js";
|
|
|
66
67
|
* rules fire and config + cache writes route into `$stashDir/.akm/`
|
|
67
68
|
* instead of the user's host `~/.config/akm`.
|
|
68
69
|
*/
|
|
69
|
-
function assertSetupSandbox(stashDir, dirExplicitlyProvided) {
|
|
70
|
+
export function assertSetupSandbox(stashDir, dirExplicitlyProvided) {
|
|
70
71
|
if (!dirExplicitlyProvided)
|
|
71
72
|
return;
|
|
72
73
|
if (process.env.AKM_FORCE_SETUP_TMP_STASH === "1")
|
|
@@ -102,28 +103,10 @@ function applyStashIsolationToEnv(stashDir, dirExplicitlyProvided) {
|
|
|
102
103
|
/**
|
|
103
104
|
* Raw preflight used before setup performs prompts, initialization, or writes.
|
|
104
105
|
*
|
|
105
|
-
*
|
|
106
|
-
*
|
|
107
|
-
*
|
|
108
|
-
*
|
|
109
|
-
* this is the first thing each one calls. When the on-disk config predates
|
|
110
|
-
* 0.9 (or is otherwise unparseable/invalid), `parseAndValidateConfigText`
|
|
111
|
-
* throws `ConfigError`; deliberately let that propagate rather than falling
|
|
112
|
-
* back to a fresh default config here.
|
|
113
|
-
*
|
|
114
|
-
* That fallback was considered and rejected: `mutateConfigWithPrecommit`
|
|
115
|
-
* (src/core/config/config.ts) re-reads and re-validates this SAME file
|
|
116
|
-
* inside its write lock before saving, so a wizard that "survived" this
|
|
117
|
-
* preflight by substituting `DEFAULT_CONFIG` would still crash with the
|
|
118
|
-
* identical error at the final save — after prompting the user through the
|
|
119
|
-
* entire wizard. Worse, making the save path itself tolerate an old config
|
|
120
|
-
* would mean writing a freshly-generated 0.9 config over the live 0.8 file
|
|
121
|
-
* `akm migrate apply` needs to read as ITS OWN input — replacing the user's
|
|
122
|
-
* real engine/source settings with the wizard's placeholder ones, silently,
|
|
123
|
-
* on the one path (`akm migrate ...`) the upgrade docs tell users to run
|
|
124
|
-
* first. Refusing here — before any prompt, detection, or write — is strictly
|
|
125
|
-
* safer: the file is left byte-for-byte untouched and the error message
|
|
126
|
-
* below points straight at the real recovery command.
|
|
106
|
+
* Setup merges into a current config, so it rejects an unreadable or obsolete
|
|
107
|
+
* file before prompting or writing. There is no runtime config translator: an
|
|
108
|
+
* operator who wants a fresh setup moves the old file aside, while an operator
|
|
109
|
+
* who wants to preserve its values rewrites them into the current schema.
|
|
127
110
|
*/
|
|
128
111
|
export function assertSetupConfigPreflight() {
|
|
129
112
|
const configPath = getConfigPath();
|
|
@@ -145,8 +128,7 @@ export function assertSetupConfigPreflight() {
|
|
|
145
128
|
if (error.code !== "UNSUPPORTED_CONFIG_VERSION" && error.code !== "INVALID_CONFIG_FILE")
|
|
146
129
|
throw error;
|
|
147
130
|
throw new ConfigError(`\`akm setup\` cannot run: the config at ${configPath} did not load (${error.message}). ` +
|
|
148
|
-
"It was left untouched — setup never writes over a config it cannot first read cleanly.", error.code, "
|
|
149
|
-
"for the full upgrade checklist. To abandon it and start fresh instead, move it aside " +
|
|
131
|
+
"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 " +
|
|
150
132
|
`(e.g. \`mv ${configPath} ${configPath}.bak\`) and re-run \`akm setup\`.`);
|
|
151
133
|
}
|
|
152
134
|
}
|
|
@@ -261,10 +243,10 @@ function setupSourceDescriptor(source) {
|
|
|
261
243
|
}
|
|
262
244
|
function selectsExistingBundle(source, id, bundle) {
|
|
263
245
|
const configured = bundleEntryToSourceEntry(id, bundle);
|
|
264
|
-
|
|
265
|
-
configured.
|
|
266
|
-
configured
|
|
267
|
-
|
|
246
|
+
const sameUrl = configured?.type === "git" && source.type === "git" && configured.url && source.url
|
|
247
|
+
? canonicalSetupGitUrl(configured.url) === canonicalSetupGitUrl(source.url)
|
|
248
|
+
: configured?.url === source.url;
|
|
249
|
+
return configured !== undefined && configured.type === source.type && configured.path === source.path && sameUrl;
|
|
268
250
|
}
|
|
269
251
|
/** Convert only the wizard's private drafts, leaving current bundle entries intact. */
|
|
270
252
|
function finalizeSetupDraft(draft) {
|
|
@@ -914,7 +896,7 @@ export async function runSetupFromConfig(opts) {
|
|
|
914
896
|
// Phase 2: Validate — only allow safe top-level keys
|
|
915
897
|
for (const key of ["stashDir", "sources", "installed"]) {
|
|
916
898
|
if (key in incoming) {
|
|
917
|
-
throw new ConfigError(`${key} is not supported by the current config schema;
|
|
899
|
+
throw new ConfigError(`${key} is not supported by the current config schema; configure bundles/defaultBundle instead.`, "INVALID_CONFIG_FILE");
|
|
918
900
|
}
|
|
919
901
|
}
|
|
920
902
|
// Derived from AkmConfigShape (via `listTopLevelConfigKeys`) rather than a
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
|
+
/**
|
|
5
|
+
* Canonical identity for Git sources selected by setup.
|
|
6
|
+
*
|
|
7
|
+
* Git accepts a terminal `.git` suffix as an optional spelling of the same
|
|
8
|
+
* remote. Registry, fallback, and historical setup entries have used both
|
|
9
|
+
* forms, so comparisons must not turn that spelling difference into a second
|
|
10
|
+
* configured bundle.
|
|
11
|
+
*/
|
|
12
|
+
export function canonicalSetupGitUrl(value) {
|
|
13
|
+
return value
|
|
14
|
+
.trim()
|
|
15
|
+
.replace(/\/+$/, "")
|
|
16
|
+
.replace(/\.git$/i, "");
|
|
17
|
+
}
|
|
@@ -11,9 +11,20 @@ import { DEFAULT_CONFIG, getEffectiveRegistries, getSources } from "../../core/c
|
|
|
11
11
|
import { readLockfile } from "../../integrations/lockfile.js";
|
|
12
12
|
import { prompt, promptOrBack } from "../prompt.js";
|
|
13
13
|
import { loadSetupStashes } from "../registry-stash-loader.js";
|
|
14
|
+
import { canonicalSetupGitUrl } from "../source-identity.js";
|
|
14
15
|
function configuredSourceKey(source) {
|
|
15
16
|
return `${source.type}:${source.path ?? source.url ?? source.name ?? "unknown"}`;
|
|
16
17
|
}
|
|
18
|
+
function configuredSourceTarget(source) {
|
|
19
|
+
return source.type === "npm" ? source.path : source.url;
|
|
20
|
+
}
|
|
21
|
+
function configuredSourceIdentity(source) {
|
|
22
|
+
const target = configuredSourceTarget(source);
|
|
23
|
+
return source.type === "git" && target ? canonicalSetupGitUrl(target) : target;
|
|
24
|
+
}
|
|
25
|
+
function recommendedSourceIdentity(entry) {
|
|
26
|
+
return entry.installType === "git" ? canonicalSetupGitUrl(entry.url) : entry.url;
|
|
27
|
+
}
|
|
17
28
|
function describeConfiguredSource(source) {
|
|
18
29
|
const target = source.path ?? source.url ?? "(unknown target)";
|
|
19
30
|
const typeLabel = source.type === "git" ? "Git" : source.type === "filesystem" ? "Filesystem" : source.type;
|
|
@@ -68,10 +79,13 @@ export async function stepAdditionalSources(currentSources) {
|
|
|
68
79
|
}));
|
|
69
80
|
if (name === null)
|
|
70
81
|
continue;
|
|
71
|
-
const
|
|
82
|
+
const entryUrl = url.trim();
|
|
83
|
+
const entry = { type: "git", url: entryUrl };
|
|
72
84
|
if (name.trim())
|
|
73
85
|
entry.name = name.trim();
|
|
74
|
-
if (!sources.some((
|
|
86
|
+
if (!sources.some((source) => source.type === "git" &&
|
|
87
|
+
source.url !== undefined &&
|
|
88
|
+
canonicalSetupGitUrl(source.url) === canonicalSetupGitUrl(entryUrl))) {
|
|
75
89
|
sources.push(entry);
|
|
76
90
|
}
|
|
77
91
|
else {
|
|
@@ -183,16 +197,18 @@ export async function stepAddSources(current, options) {
|
|
|
183
197
|
"https://raw.githubusercontent.com/itlackey/akm-registry/main/index.json";
|
|
184
198
|
const availableStashes = await loadSetupStashes(registryUrl);
|
|
185
199
|
if (availableStashes.length > 0) {
|
|
186
|
-
const
|
|
200
|
+
const existingTargets = new Set(sources.map(configuredSourceIdentity).filter((value) => !!value));
|
|
187
201
|
const stashOptions = availableStashes.map((s) => ({
|
|
188
|
-
value: s
|
|
202
|
+
value: recommendedSourceIdentity(s),
|
|
189
203
|
label: s.name,
|
|
190
|
-
hint:
|
|
204
|
+
hint: existingTargets.has(recommendedSourceIdentity(s))
|
|
205
|
+
? `${s.description} (already added)`
|
|
206
|
+
: s.description || s.source,
|
|
191
207
|
}));
|
|
192
208
|
// Pre-check: already-installed stashes OR default-selected on fresh install
|
|
193
209
|
const initialValues = sources.length > 0
|
|
194
|
-
? stashOptions.filter((o) =>
|
|
195
|
-
: availableStashes.filter((s) => s.defaultSelected).map(
|
|
210
|
+
? stashOptions.filter((o) => existingTargets.has(o.value)).map((o) => o.value)
|
|
211
|
+
: availableStashes.filter((s) => s.defaultSelected).map(recommendedSourceIdentity);
|
|
196
212
|
const selectedUrls = await prompt(() => p.multiselect({
|
|
197
213
|
message: availableStashes[0]?.source === "registry"
|
|
198
214
|
? "Available bundles from the AKM registry — toggle to add or remove:"
|
|
@@ -202,20 +218,25 @@ export async function stepAddSources(current, options) {
|
|
|
202
218
|
required: false,
|
|
203
219
|
}));
|
|
204
220
|
// Add newly selected stashes
|
|
205
|
-
for (const
|
|
206
|
-
if (!
|
|
207
|
-
const entry = availableStashes.find((s) => s
|
|
208
|
-
|
|
209
|
-
|
|
221
|
+
for (const target of selectedUrls) {
|
|
222
|
+
if (!existingTargets.has(target)) {
|
|
223
|
+
const entry = availableStashes.find((s) => recommendedSourceIdentity(s) === target);
|
|
224
|
+
if (!entry)
|
|
225
|
+
continue;
|
|
226
|
+
sources.push(entry.installType === "npm"
|
|
227
|
+
? { type: "npm", path: target, name: entry.name }
|
|
228
|
+
: { type: "git", url: target, name: entry.name });
|
|
229
|
+
existingTargets.add(target);
|
|
210
230
|
}
|
|
211
231
|
}
|
|
212
232
|
// Remove deselected stashes that were previously configured
|
|
213
233
|
for (const entry of availableStashes) {
|
|
214
|
-
|
|
215
|
-
|
|
234
|
+
const target = recommendedSourceIdentity(entry);
|
|
235
|
+
if (existingTargets.has(target) && !selectedUrls.includes(target)) {
|
|
236
|
+
const idx = sources.findIndex((source) => configuredSourceIdentity(source) === target);
|
|
216
237
|
if (idx !== -1) {
|
|
217
238
|
sources.splice(idx, 1);
|
|
218
|
-
|
|
239
|
+
existingTargets.delete(target);
|
|
219
240
|
p.log.info(`Removed ${entry.name}.`);
|
|
220
241
|
}
|
|
221
242
|
}
|
|
@@ -7,14 +7,14 @@ import os from "node:os";
|
|
|
7
7
|
import path from "node:path";
|
|
8
8
|
import { parse as yamlParse, stringify as yamlStringify } from "yaml";
|
|
9
9
|
import * as p from "../../cli/clack.js";
|
|
10
|
-
import { akmTasksSync
|
|
10
|
+
import { akmTasksSync } from "../../commands/tasks/tasks.js";
|
|
11
11
|
import { loadConfig } from "../../core/config/config.js";
|
|
12
12
|
import { UsageError } from "../../core/errors.js";
|
|
13
13
|
import { commitWriteTargetBoundary, deleteAssetFromSource, prepareWriteTargetForMutation, resolveWriteTarget, writeAssetToSource, } from "../../core/write-source.js";
|
|
14
14
|
import { backendNameForPlatform } from "../../tasks/backends/index.js";
|
|
15
15
|
import { listEmbeddedTasks } from "../../tasks/embedded.js";
|
|
16
|
-
import { parseTaskDocument } from "../../tasks/parser.js";
|
|
17
16
|
import { parseSchedule } from "../../tasks/schedule.js";
|
|
17
|
+
import { parseTaskV3Yaml } from "../../tasks/source-v3.js";
|
|
18
18
|
import { prompt } from "../prompt.js";
|
|
19
19
|
/**
|
|
20
20
|
* A scheduled server-only nightly full sweep exists among the embedded
|
|
@@ -71,6 +71,15 @@ export function detectServerDefault() {
|
|
|
71
71
|
function normaliseTaskIdForMatch(raw) {
|
|
72
72
|
return raw.trim().replace(/\.(yml|md)$/, "");
|
|
73
73
|
}
|
|
74
|
+
function setTaskV3EnabledInYaml(yaml, enabled) {
|
|
75
|
+
const document = yamlParse(yaml);
|
|
76
|
+
const akm = document.akm;
|
|
77
|
+
if (!akm || typeof akm !== "object" || Array.isArray(akm)) {
|
|
78
|
+
throw new UsageError("Task v3 source must declare an akm mapping before setup can change enabled state.");
|
|
79
|
+
}
|
|
80
|
+
akm.enabled = enabled;
|
|
81
|
+
return yamlStringify(document);
|
|
82
|
+
}
|
|
74
83
|
export function listSetupTaskDefinitions() {
|
|
75
84
|
const config = loadConfig();
|
|
76
85
|
const target = resolveWriteTarget(config, config.defaultBundle, { requireWritable: false });
|
|
@@ -84,8 +93,21 @@ export function listSetupTaskDefinitions() {
|
|
|
84
93
|
const id = file.slice(0, -4);
|
|
85
94
|
const filePath = path.join(taskDir, file);
|
|
86
95
|
try {
|
|
87
|
-
const task =
|
|
88
|
-
|
|
96
|
+
const task = parseTaskV3Yaml({
|
|
97
|
+
yaml: fs.readFileSync(filePath, "utf8"),
|
|
98
|
+
filePath,
|
|
99
|
+
workspaceRoot: target.source.path,
|
|
100
|
+
});
|
|
101
|
+
if (task.triggers.schedules.length === 0)
|
|
102
|
+
continue;
|
|
103
|
+
const schedules = task.triggers.schedules.map((schedule) => schedule.cron);
|
|
104
|
+
tasks.push({
|
|
105
|
+
id,
|
|
106
|
+
schedule: schedules[0],
|
|
107
|
+
schedules: Object.freeze(schedules),
|
|
108
|
+
enabled: task.akm?.enabled !== false,
|
|
109
|
+
...(task.akm?.description !== undefined ? { description: task.akm.description } : {}),
|
|
110
|
+
});
|
|
89
111
|
}
|
|
90
112
|
catch (error) {
|
|
91
113
|
throw new UsageError(`Cannot review task definition ${filePath}: ${error instanceof Error ? error.message : String(error)} ` +
|
|
@@ -106,16 +128,19 @@ export async function prepareSetupTaskDefinitions(tasks, deps = {}) {
|
|
|
106
128
|
const original = fs.existsSync(filePath) ? fs.readFileSync(filePath, "utf8") : undefined;
|
|
107
129
|
let yaml;
|
|
108
130
|
if (original !== undefined) {
|
|
109
|
-
yaml =
|
|
131
|
+
yaml = setTaskV3EnabledInYaml(original, plan.enabled);
|
|
110
132
|
}
|
|
111
133
|
else {
|
|
112
134
|
const document = yamlParse(plan.task.yaml);
|
|
113
|
-
|
|
114
|
-
|
|
135
|
+
const akm = document.akm;
|
|
136
|
+
akm.schedule = plan.schedule;
|
|
137
|
+
akm.enabled = plan.enabled;
|
|
115
138
|
yaml = yamlStringify(document);
|
|
116
139
|
}
|
|
117
|
-
|
|
118
|
-
|
|
140
|
+
const parsed = parseTaskV3Yaml({ yaml, filePath, workspaceRoot: target.source.path });
|
|
141
|
+
for (const schedule of parsed.triggers.schedules) {
|
|
142
|
+
parseSchedule(schedule.cron, backendNameForPlatform());
|
|
143
|
+
}
|
|
119
144
|
return { filePath, original, yaml, ref: { type: "task", name: plan.task.id } };
|
|
120
145
|
});
|
|
121
146
|
const changed = prepared.filter((entry) => entry.original !== entry.yaml);
|
|
@@ -198,7 +223,7 @@ export async function stepScheduledTasks(deps = DEFAULT_SCHEDULED_TASKS_DEPS, op
|
|
|
198
223
|
initialValues: preChecked,
|
|
199
224
|
options: embedded.map((task) => {
|
|
200
225
|
const current = byId.get(task.id);
|
|
201
|
-
const schedule = current
|
|
226
|
+
const schedule = current ? displayTaskSchedules(current) : task.schedule;
|
|
202
227
|
const state = current ? (current.enabled ? "enabled" : "disabled") : "not prepared";
|
|
203
228
|
return {
|
|
204
229
|
value: task.id,
|
|
@@ -241,7 +266,7 @@ export async function stepScheduledTasks(deps = DEFAULT_SCHEDULED_TASKS_DEPS, op
|
|
|
241
266
|
const custom = installed.filter((task) => !embeddedIds.has(normaliseTaskIdForMatch(task.id)));
|
|
242
267
|
p.note([
|
|
243
268
|
...plans.map((plan) => `${plan.task.label}: ${plan.enabled ? "enabled" : "disabled"} | ${plan.schedule} | ${plan.task.description}`),
|
|
244
|
-
...custom.map((task) => `${task.id}: ${task.enabled ? "enabled" : "disabled"} | ${task
|
|
269
|
+
...custom.map((task) => `${task.id}: ${task.enabled ? "enabled" : "disabled"} | ${displayTaskSchedules(task)}${task.description ? ` | ${task.description}` : ""}`),
|
|
245
270
|
].join("\n"), "Task Schedule Review");
|
|
246
271
|
const activate = await prompt(() => p.confirm({
|
|
247
272
|
message: `Activate these schedules now? This will update task files and sync them to the ${backendNameForPlatform()} scheduler.`,
|
|
@@ -267,3 +292,6 @@ export async function stepScheduledTasks(deps = DEFAULT_SCHEDULED_TASKS_DEPS, op
|
|
|
267
292
|
}
|
|
268
293
|
p.log.success("Task schedules activated. Verify them with `akm task doctor`.");
|
|
269
294
|
}
|
|
295
|
+
function displayTaskSchedules(task) {
|
|
296
|
+
return task.schedules && task.schedules.length > 0 ? task.schedules.join(", ") : task.schedule;
|
|
297
|
+
}
|
|
@@ -57,9 +57,9 @@ function resolveGitContentDir(config) {
|
|
|
57
57
|
// ── Self-register ───────────────────────────────────────────────────────────
|
|
58
58
|
registerSourceProvider("git", (config) => new GitSourceProvider(config));
|
|
59
59
|
// ── Cache management ────────────────────────────────────────────────────────
|
|
60
|
-
export function getCachePaths(repoUrl) {
|
|
60
|
+
export function getCachePaths(repoUrl, cacheRootOverride) {
|
|
61
61
|
const key = createHash("sha256").update(repoUrl).digest("hex").slice(0, 16);
|
|
62
|
-
const cacheRoot = getRegistryIndexCacheDir();
|
|
62
|
+
const cacheRoot = cacheRootOverride ?? getRegistryIndexCacheDir();
|
|
63
63
|
const rootDir = path.join(cacheRoot, `git-${key}`);
|
|
64
64
|
return {
|
|
65
65
|
rootDir,
|
|
@@ -101,7 +101,7 @@ export async function syncMirroredRepo(config, options) {
|
|
|
101
101
|
throw new ConfigError("git stash entry requires a URL when no install ref is supplied");
|
|
102
102
|
}
|
|
103
103
|
const repo = parseGitRepoUrl(config.url);
|
|
104
|
-
const cachePaths = getCachePaths(repo.canonicalUrl);
|
|
104
|
+
const cachePaths = getCachePaths(repo.canonicalUrl, options?.cacheRootDir);
|
|
105
105
|
await ensureGitMirror(repo, cachePaths, {
|
|
106
106
|
requireRepoDir: true,
|
|
107
107
|
writable: options?.writable ?? config.writable === true,
|
|
@@ -13,7 +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 { parseRegistryRef, resolveRegistryArtifact } from "../../registry/resolve.js";
|
|
16
|
+
import { npmArtifactNetworkPolicy, parseRegistryRef, resolveRegistryArtifact } from "../../registry/resolve.js";
|
|
17
17
|
import { registerSourceProvider } from "../provider-factory.js";
|
|
18
18
|
import { applyAkmIncludeConfig, buildInstallCacheDir, computeFileHash, detectStashRoot, downloadArchive, isDirectory, } from "./provider-utils.js";
|
|
19
19
|
import { extractTarGzSecure, verifyArchiveIntegrity } from "./tar-utils.js";
|
|
@@ -108,7 +108,7 @@ async function doSyncNpm(parsed, options) {
|
|
|
108
108
|
let installRoot;
|
|
109
109
|
let stashRoot;
|
|
110
110
|
try {
|
|
111
|
-
await downloadArchive(resolved.artifactUrl, archivePath);
|
|
111
|
+
await downloadArchive(resolved.artifactUrl, archivePath, npmArtifactNetworkPolicy(resolved));
|
|
112
112
|
verifyArchiveIntegrity(archivePath, resolved.resolvedRevision, resolved.source);
|
|
113
113
|
integrity = await computeFileHash(archivePath);
|
|
114
114
|
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 { cancelRegistryResponse, fetchRegistryResponse } 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,9 +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
|
|
102
|
+
export async function downloadArchive(url, destination, networkPolicy) {
|
|
103
|
+
const response = await fetchRegistryResponse(url, undefined, { policy: networkPolicy, timeoutMs: 120_000 });
|
|
104
104
|
if (!response.ok) {
|
|
105
|
+
await cancelRegistryResponse(response);
|
|
105
106
|
throw new Error(`Failed to download archive (${response.status}) from ${url}`);
|
|
106
107
|
}
|
|
107
108
|
// Stream to disk with an explicit byte cap + body-read deadline: the fetch
|
|
@@ -1,12 +1,11 @@
|
|
|
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
|
+
import { ConfigError } from "../../core/errors.js";
|
|
4
5
|
import { registerSourceProvider } from "../provider-factory.js";
|
|
5
|
-
import {
|
|
6
|
-
/**
|
|
7
|
-
|
|
8
|
-
*/
|
|
9
|
-
registerSourceProvider("website", (config) => {
|
|
6
|
+
import { getWebsiteCachePaths, shouldAllowPrivateWebsiteUrlForTests, validateWebsiteUrl } from "../website-url.js";
|
|
7
|
+
/** Website source provider — URL-derived path plus an injected mirror refresh. */
|
|
8
|
+
export function createWebsiteProvider(config) {
|
|
10
9
|
const allowPrivateHosts = shouldAllowPrivateWebsiteUrlForTests(config.url ?? "");
|
|
11
10
|
const url = validateWebsiteUrl(config.url ?? "", { allowPrivateHosts });
|
|
12
11
|
const name = config.name ?? "website";
|
|
@@ -17,10 +16,14 @@ registerSourceProvider("website", (config) => {
|
|
|
17
16
|
return getWebsiteCachePaths(url).rootDir;
|
|
18
17
|
},
|
|
19
18
|
async sync(options) {
|
|
19
|
+
const ensureWebsiteMirror = options?.ensureWebsiteMirror;
|
|
20
|
+
if (!ensureWebsiteMirror) {
|
|
21
|
+
throw new ConfigError("Website provider sync requires an injected ensureWebsiteMirror capability");
|
|
22
|
+
}
|
|
20
23
|
await ensureWebsiteMirror(config, {
|
|
21
24
|
requireStashDir: true,
|
|
22
25
|
force: options?.force,
|
|
23
|
-
// Feed the resolver into the
|
|
26
|
+
// Feed the resolver into the injected mirror plumbing that
|
|
24
27
|
// already threads `resolveSecret` down to `FetcherContext`. This is the
|
|
25
28
|
// line that closes the bundle-update / sync() gap: previously the X
|
|
26
29
|
// fetcher on this path saw only `X_BEARER_TOKEN`, never the store.
|
|
@@ -29,4 +32,5 @@ registerSourceProvider("website", (config) => {
|
|
|
29
32
|
});
|
|
30
33
|
},
|
|
31
34
|
};
|
|
32
|
-
}
|
|
35
|
+
}
|
|
36
|
+
registerSourceProvider("website", createWebsiteProvider);
|