akm-cli 0.9.12 → 0.9.13
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 +61 -0
- package/dist/assets/workflows/workflow-template.md +4 -0
- package/dist/commands/improve/improve.js +1 -0
- package/dist/commands/lint/base-linter.js +10 -0
- package/dist/commands/proposal/drain.js +48 -6
- package/dist/commands/proposal/proposal-cli.js +1 -0
- package/dist/core/config/config-walker.js +7 -3
- package/dist/core/config/config.js +21 -12
- package/dist/core/config/schema/primitives.js +8 -2
- package/dist/core/errors.js +2 -0
- package/dist/llm/client.js +12 -8
- package/dist/llm/embedders/remote.js +3 -2
- package/dist/output/shapes.js +46 -1
- package/dist/output/text/proposal-format.js +5 -0
- package/dist/scripts/akm-migrate-node.js +323 -172
- package/dist/scripts/akm-migrate.js +323 -172
- package/dist/storage/repositories/workflow-runs-repository.js +118 -10
- package/dist/workflows/exec/run-workflow.js +1 -1
- package/dist/workflows/exec/step-work.js +41 -0
- package/dist/workflows/parser.js +1 -1
- package/dist/workflows/runtime/runs.js +29 -5
- package/docs/reference/cli.md +18 -0
- package/package.json +1 -1
|
@@ -7043,7 +7043,8 @@ var init_errors = __esm(() => {
|
|
|
7043
7043
|
TEST_ISOLATION_MISSING: "Under bun test, when AKM_BUNDLE_DIR is set you MUST also set XDG_DATA_HOME (or AKM_DATA_DIR) and XDG_STATE_HOME (or AKM_STATE_DIR) to temp directories so the test does not touch the developer's real ~/.local/share/akm or ~/.local/state/akm.",
|
|
7044
7044
|
UNSAFE_STASH_DIR: "Choose a path inside your home directory (e.g. ~/akm) or another empty workspace. The bundle directory cannot be the filesystem root, your home directory itself, or a sensitive system path like /etc, /var, ~/.config, or ~/.ssh.",
|
|
7045
7045
|
UNKNOWN_IMPROVE_STRATEGY: "Pass one of the listed strategy names to `--strategy`, or define it under `improve.strategies`. Names are case-sensitive.",
|
|
7046
|
-
EXECUTION_NOT_AUTHORIZED: "Change the selected tools or update the machine/user execution policy, then retry."
|
|
7046
|
+
EXECUTION_NOT_AUTHORIZED: "Change the selected tools or update the machine/user execution policy, then retry.",
|
|
7047
|
+
SECRET_REFERENCE_UNRESOLVED: "Check the secret exists (`akm secret list`) and the name after `secret://` matches, or run `akm secret set <name> <value>` to store it."
|
|
7047
7048
|
};
|
|
7048
7049
|
COMPOSITION_INVALID_MULTI_JOB_HINT = "AKM workflows support exactly one job per source, with no needs: between jobs. Split the extra job(s) into " + "their own workflow file, and compose them with uses: workflows/<ref> instead.";
|
|
7049
7050
|
USAGE_HINTS = {
|
|
@@ -7065,7 +7066,8 @@ var init_errors = __esm(() => {
|
|
|
7065
7066
|
INPUT_BINDING_INVALID: "Check the step's with: keys against the target's declared inputs.",
|
|
7066
7067
|
TASK_TARGET_UNSUPPORTED: "Task definitions support command, script, workflow, and shell (run:) targets; akm/command is layered by callers.",
|
|
7067
7068
|
WORKFLOW_IR_VERSION_UNSUPPORTED: "Abandon the run with `akm workflow abandon <id>`, then start it again from the workflow source — a frozen plan this akm cannot execute is not re-executable in place.",
|
|
7068
|
-
WORKFLOW_OUTPUT_INVALID: "Check each `outputs:` entry's `from:` against the step artifact it names, and its `schema:` against the value that step actually promotes."
|
|
7069
|
+
WORKFLOW_OUTPUT_INVALID: "Check each `outputs:` entry's `from:` against the step artifact it names, and its `schema:` against the value that step actually promotes.",
|
|
7070
|
+
RUN_LEASE_HELD: "Wait for the named engine invocation to finish or for the lease to expire, then retry. `akm workflow status <id>` shows the current lease."
|
|
7069
7071
|
};
|
|
7070
7072
|
NOT_FOUND_HINTS = {
|
|
7071
7073
|
ASSET_NOT_FOUND: "Run `akm search <query>` or `akm index` to refresh the index.",
|
|
@@ -8389,6 +8391,17 @@ function parseRefInput(raw) {
|
|
|
8389
8391
|
}
|
|
8390
8392
|
return { type: parts.type, name: parts.name, origin: ref.bundle };
|
|
8391
8393
|
}
|
|
8394
|
+
function isFullRefInput(raw) {
|
|
8395
|
+
const trimmed = raw.trim();
|
|
8396
|
+
if (!trimmed)
|
|
8397
|
+
return false;
|
|
8398
|
+
try {
|
|
8399
|
+
const parsed = parseBundleRef(trimmed);
|
|
8400
|
+
return parsed.bundle !== undefined || typeNameFromConceptId(parsed.conceptId) !== undefined;
|
|
8401
|
+
} catch {
|
|
8402
|
+
return false;
|
|
8403
|
+
}
|
|
8404
|
+
}
|
|
8392
8405
|
var init_resolve_ref = __esm(() => {
|
|
8393
8406
|
init_errors();
|
|
8394
8407
|
init_asset_placement();
|
|
@@ -12415,7 +12428,7 @@ function bindStepSections(headings, lines, bodyStartLine, totalLines, path24, de
|
|
|
12415
12428
|
if (!declaredIds.has(h.text)) {
|
|
12416
12429
|
errors3.push({
|
|
12417
12430
|
line: h.line,
|
|
12418
|
-
message: `Unexpected level-2 heading "## ${h.text}" on line ${h.line} — no step "${h.text}" is declared in frontmatter "steps:". Level-2 headings must exactly match a declared step id.`
|
|
12431
|
+
message: `Unexpected level-2 heading "## ${h.text}" on line ${h.line} — no step "${h.text}" is declared in frontmatter "steps:". Level-2 headings must exactly match a declared step id. To document something that is not a step, use a level-3 heading.`
|
|
12419
12432
|
});
|
|
12420
12433
|
continue;
|
|
12421
12434
|
}
|
|
@@ -68759,15 +68772,15 @@ ${this.boa_token}${this.audio_token.repeat(this._compute_audio_num_tokens(audio_
|
|
|
68759
68772
|
});
|
|
68760
68773
|
|
|
68761
68774
|
// src/indexer/walk/file-context.ts
|
|
68762
|
-
import
|
|
68763
|
-
import
|
|
68775
|
+
import fs47 from "node:fs";
|
|
68776
|
+
import path56 from "node:path";
|
|
68764
68777
|
function buildFileContext(stashRoot, absPath) {
|
|
68765
|
-
const relPath = toPosix(
|
|
68766
|
-
const ext =
|
|
68767
|
-
const fileName =
|
|
68768
|
-
const parentDirAbs =
|
|
68769
|
-
const parentDir =
|
|
68770
|
-
const relDir = toPosix(
|
|
68778
|
+
const relPath = toPosix(path56.relative(stashRoot, absPath));
|
|
68779
|
+
const ext = path56.extname(absPath).toLowerCase();
|
|
68780
|
+
const fileName = path56.basename(absPath);
|
|
68781
|
+
const parentDirAbs = path56.dirname(absPath);
|
|
68782
|
+
const parentDir = path56.basename(parentDirAbs);
|
|
68783
|
+
const relDir = toPosix(path56.dirname(relPath));
|
|
68771
68784
|
const ancestorDirs = relDir === "." ? [] : relDir.split("/").filter((seg) => seg.length > 0);
|
|
68772
68785
|
let cachedContent;
|
|
68773
68786
|
let cachedFrontmatter;
|
|
@@ -68784,7 +68797,7 @@ function buildFileContext(stashRoot, absPath) {
|
|
|
68784
68797
|
stashRoot,
|
|
68785
68798
|
content() {
|
|
68786
68799
|
if (cachedContent === undefined) {
|
|
68787
|
-
cachedContent =
|
|
68800
|
+
cachedContent = fs47.readFileSync(absPath, "utf8");
|
|
68788
68801
|
}
|
|
68789
68802
|
return cachedContent;
|
|
68790
68803
|
},
|
|
@@ -68799,7 +68812,7 @@ function buildFileContext(stashRoot, absPath) {
|
|
|
68799
68812
|
},
|
|
68800
68813
|
stat() {
|
|
68801
68814
|
if (cachedStat === undefined) {
|
|
68802
|
-
cachedStat =
|
|
68815
|
+
cachedStat = fs47.statSync(absPath);
|
|
68803
68816
|
}
|
|
68804
68817
|
return cachedStat;
|
|
68805
68818
|
}
|
|
@@ -70922,6 +70935,7 @@ function formatProposalDrainPlain(r) {
|
|
|
70922
70935
|
const deferred = Array.isArray(r.deferred) ? r.deferred : [];
|
|
70923
70936
|
const skippedByCap = Array.isArray(r.skippedByCap) ? r.skippedByCap : [];
|
|
70924
70937
|
const staged = Array.isArray(r.staged) ? r.staged : [];
|
|
70938
|
+
const failed = Array.isArray(r.failed) ? r.failed : [];
|
|
70925
70939
|
const prefix = r.dryRun === true ? "[dry-run] " : "";
|
|
70926
70940
|
const lines = [
|
|
70927
70941
|
`${prefix}Drained proposal queue (strategy=${String(r.strategy ?? "?")}, policy=${policy}, applyMode=${applyMode})`,
|
|
@@ -70929,11 +70943,15 @@ function formatProposalDrainPlain(r) {
|
|
|
70929
70943
|
` rejected: ${rejected.length}`,
|
|
70930
70944
|
` deferred: ${deferred.length}`,
|
|
70931
70945
|
` skippedByCap: ${skippedByCap.length}`,
|
|
70932
|
-
` staged: ${staged.length}
|
|
70946
|
+
` staged: ${staged.length}`,
|
|
70947
|
+
` failed: ${failed.length}`
|
|
70933
70948
|
];
|
|
70934
70949
|
for (const d of deferred) {
|
|
70935
70950
|
lines.push(` - ${String(d.id ?? "?")} (${String(d.reason ?? "?")})`);
|
|
70936
70951
|
}
|
|
70952
|
+
for (const f of failed) {
|
|
70953
|
+
lines.push(` ! ${String(f.id ?? "?")} (${String(f.reason ?? "?")}): ${String(f.detail ?? "?")}`);
|
|
70954
|
+
}
|
|
70937
70955
|
appendLoweringNotices(lines, r);
|
|
70938
70956
|
return lines.join(`
|
|
70939
70957
|
`).trimEnd();
|
|
@@ -76193,12 +76211,16 @@ var httpUrl = exports_external.string().refine((v) => v.startsWith("http://") ||
|
|
|
76193
76211
|
});
|
|
76194
76212
|
var ENGINE_NAME_PATTERN = new RegExp(ENGINE_NAME_PATTERN_SOURCE);
|
|
76195
76213
|
var ENV_REFERENCE_PATTERN = /^\$[A-Za-z_][A-Za-z0-9_]*$|^\$\{[A-Za-z_][A-Za-z0-9_]*\}$/;
|
|
76214
|
+
var SECRET_STORE_REFERENCE_PATTERN = /^secret:\/\/(.+)$/;
|
|
76196
76215
|
var engineName = exports_external.string().max(63).regex(ENGINE_NAME_PATTERN, "names must be lowercase kebab-case and must not begin with reserved akm-");
|
|
76216
|
+
function isApiKeyReference(value) {
|
|
76217
|
+
return ENV_REFERENCE_PATTERN.test(value) || SECRET_STORE_REFERENCE_PATTERN.test(value);
|
|
76218
|
+
}
|
|
76197
76219
|
function symbolicOrWarnApiKey(label) {
|
|
76198
76220
|
return exports_external.string().superRefine((value) => {
|
|
76199
|
-
if (
|
|
76221
|
+
if (isApiKeyReference(value))
|
|
76200
76222
|
return;
|
|
76201
|
-
warnOnce(`config:literal-api-key:${label}`, `A ${label} in config.json is a literal API key, not a $VAR/\${VAR} reference; using it as configured. Prefer \`akm config set ...apiKey '$VAR'\` (with the corresponding env var set) — see docs/reference/data-and-telemetry.md.`);
|
|
76223
|
+
warnOnce(`config:literal-api-key:${label}`, `A ${label} in config.json is a literal API key, not a $VAR/\${VAR}/secret:// reference; using it as configured. Prefer \`akm config set ...apiKey '$VAR'\` (with the corresponding env var set) or \`secret://<name>\` (with \`akm secret set <name> ...\`) — see docs/reference/data-and-telemetry.md.`);
|
|
76202
76224
|
});
|
|
76203
76225
|
}
|
|
76204
76226
|
var chatCompletionsEndpoint = exports_external.string().superRefine((value, ctx) => {
|
|
@@ -77366,11 +77388,19 @@ function getSources(config) {
|
|
|
77366
77388
|
function loadConfig() {
|
|
77367
77389
|
return loadUserConfig();
|
|
77368
77390
|
}
|
|
77369
|
-
function resolveSecret(value) {
|
|
77391
|
+
function resolveSecret(value, resolveFromStore) {
|
|
77370
77392
|
if (value === undefined)
|
|
77371
77393
|
return;
|
|
77372
77394
|
if (typeof value !== "string")
|
|
77373
77395
|
return value;
|
|
77396
|
+
const storeRef = SECRET_STORE_REFERENCE_PATTERN.exec(value)?.[1];
|
|
77397
|
+
if (storeRef !== undefined) {
|
|
77398
|
+
const resolved = resolveFromStore?.(storeRef) ?? null;
|
|
77399
|
+
if (resolved === null) {
|
|
77400
|
+
throw new ConfigError(`Secret store reference "${value}" did not resolve to a stored value.`, "SECRET_REFERENCE_UNRESOLVED");
|
|
77401
|
+
}
|
|
77402
|
+
return resolved;
|
|
77403
|
+
}
|
|
77374
77404
|
if (!value.includes("$"))
|
|
77375
77405
|
return value;
|
|
77376
77406
|
return value.replace(/\$\{([A-Za-z_][A-Za-z0-9_]*)\}|\$([A-Za-z_][A-Za-z0-9_]*)/g, (_match, braced, bare) => {
|
|
@@ -79255,9 +79285,9 @@ function listTxnJournalsTolerant(predicate) {
|
|
|
79255
79285
|
|
|
79256
79286
|
// src/commands/proposal/repository.ts
|
|
79257
79287
|
import { createHash as createHash9, randomUUID as randomUUID6 } from "node:crypto";
|
|
79258
|
-
import
|
|
79288
|
+
import fs49 from "node:fs";
|
|
79259
79289
|
init_dist();
|
|
79260
|
-
import
|
|
79290
|
+
import path61 from "node:path";
|
|
79261
79291
|
|
|
79262
79292
|
// src/core/adapter/adapters/agent-skills-adapter.ts
|
|
79263
79293
|
init_frontmatter();
|
|
@@ -92674,8 +92704,8 @@ init_warn();
|
|
|
92674
92704
|
init_write_provenance();
|
|
92675
92705
|
|
|
92676
92706
|
// src/indexer/index-written-assets.ts
|
|
92677
|
-
import
|
|
92678
|
-
import
|
|
92707
|
+
import fs48 from "node:fs";
|
|
92708
|
+
import path59 from "node:path";
|
|
92679
92709
|
init_errors();
|
|
92680
92710
|
init_paths();
|
|
92681
92711
|
init_warn();
|
|
@@ -93712,6 +93742,127 @@ function redactSensitiveText(text, sensitiveValues) {
|
|
|
93712
93742
|
|
|
93713
93743
|
// src/llm/embedders/remote.ts
|
|
93714
93744
|
init_warn();
|
|
93745
|
+
|
|
93746
|
+
// src/sources/snapshot-fetchers/secret-seam.ts
|
|
93747
|
+
import fs45 from "node:fs";
|
|
93748
|
+
|
|
93749
|
+
// src/core/env-secret-ref.ts
|
|
93750
|
+
import fs43 from "node:fs";
|
|
93751
|
+
import path54 from "node:path";
|
|
93752
|
+
|
|
93753
|
+
// src/registry/origin-resolve.ts
|
|
93754
|
+
init_asset_ref();
|
|
93755
|
+
function resolveSourcesForOrigin(origin, allSources) {
|
|
93756
|
+
if (!origin)
|
|
93757
|
+
return allSources;
|
|
93758
|
+
const installations = deriveInstallations(allSources);
|
|
93759
|
+
return allSources.filter((_, index) => installations[index]?.id === origin);
|
|
93760
|
+
}
|
|
93761
|
+
|
|
93762
|
+
// src/core/asset/asset-create.ts
|
|
93763
|
+
init_errors();
|
|
93764
|
+
function normalizeCreateSubPath(subPath) {
|
|
93765
|
+
if (subPath === undefined)
|
|
93766
|
+
return "";
|
|
93767
|
+
const trimmed = subPath.trim().replace(/\\/g, "/").replace(/^\/+|\/+$/g, "");
|
|
93768
|
+
if (!trimmed)
|
|
93769
|
+
return "";
|
|
93770
|
+
if (trimmed.split("/").some((segment) => !segment || segment === "." || segment === "..")) {
|
|
93771
|
+
throw new UsageError("--path must be a relative directory without '.' or '..' segments.");
|
|
93772
|
+
}
|
|
93773
|
+
return trimmed;
|
|
93774
|
+
}
|
|
93775
|
+
function assertFlatAssetName(name) {
|
|
93776
|
+
if (name?.replace(/\\/g, "/").replace(/\.md$/i, "").includes("/")) {
|
|
93777
|
+
throw new UsageError("Asset --name must be a flat name without '/'. Use --path to choose a subdirectory " + "(e.g. --path personal --name grocery-list).");
|
|
93778
|
+
}
|
|
93779
|
+
}
|
|
93780
|
+
function combineCreatePath(subPath, baseName) {
|
|
93781
|
+
return subPath ? `${subPath}/${baseName}` : baseName;
|
|
93782
|
+
}
|
|
93783
|
+
|
|
93784
|
+
// src/core/env-secret-ref.ts
|
|
93785
|
+
init_asset_placement();
|
|
93786
|
+
init_resolve_ref();
|
|
93787
|
+
init_common();
|
|
93788
|
+
init_errors();
|
|
93789
|
+
function assertNotRemovedVaultRef(ref) {
|
|
93790
|
+
const boundary = ref.indexOf("//");
|
|
93791
|
+
const bare = boundary >= 0 ? ref.slice(boundary + 2) : ref;
|
|
93792
|
+
if (/^vault[:/]/.test(bare.trim())) {
|
|
93793
|
+
throw new UsageError("The `vault` asset type was removed in 0.9.0 — use `env/` (whole .env config) or `secrets/` (a single value).", "INVALID_FLAG_VALUE");
|
|
93794
|
+
}
|
|
93795
|
+
}
|
|
93796
|
+
function assertNotColonRef(ref, aliases, replacement) {
|
|
93797
|
+
const boundary = ref.indexOf("//");
|
|
93798
|
+
const bare = (boundary >= 0 ? ref.slice(boundary + 2) : ref).trim();
|
|
93799
|
+
const colon = bare.indexOf(":");
|
|
93800
|
+
if (colon <= 0)
|
|
93801
|
+
return;
|
|
93802
|
+
const head = bare.slice(0, colon).toLowerCase();
|
|
93803
|
+
if (!aliases.includes(head))
|
|
93804
|
+
return;
|
|
93805
|
+
const name = bare.slice(colon + 1);
|
|
93806
|
+
throw new UsageError(`The \`${head}:\` ref spelling was removed in 0.9.0 — use the slash form instead: \`${replacement}${name}\`.`, "INVALID_FLAG_VALUE");
|
|
93807
|
+
}
|
|
93808
|
+
function findEnvSource(origin, type, name) {
|
|
93809
|
+
const sources = resolveSourceEntries(undefined, loadConfig());
|
|
93810
|
+
if (sources.length === 0) {
|
|
93811
|
+
throw new UsageError("No bundles configured. Run `akm bundle create` to create your working bundle.");
|
|
93812
|
+
}
|
|
93813
|
+
const candidates = origin ? resolveSourcesForOrigin(origin, sources) : sources;
|
|
93814
|
+
const typeDir = type === "env" ? "env" : "secrets";
|
|
93815
|
+
const member = candidates.find((source) => fs43.existsSync(assetPathForName(type, path54.join(source.path, typeDir), name)));
|
|
93816
|
+
if (member)
|
|
93817
|
+
return member;
|
|
93818
|
+
if (!origin) {
|
|
93819
|
+
const fallback = candidates[0];
|
|
93820
|
+
if (fallback)
|
|
93821
|
+
return fallback;
|
|
93822
|
+
throw new UsageError("No bundles configured. Run `akm bundle create` to create your working bundle.");
|
|
93823
|
+
}
|
|
93824
|
+
const named = candidates[0];
|
|
93825
|
+
if (!named) {
|
|
93826
|
+
throw new NotFoundError(`Source not found for origin: ${origin}`);
|
|
93827
|
+
}
|
|
93828
|
+
return named;
|
|
93829
|
+
}
|
|
93830
|
+
function parseSecretRef(ref) {
|
|
93831
|
+
assertNotRemovedVaultRef(ref);
|
|
93832
|
+
assertNotColonRef(ref, ["secret", "secrets"], "secrets/");
|
|
93833
|
+
return parseRefInput(isFullRefInput(ref) ? ref : `secrets/${ref}`);
|
|
93834
|
+
}
|
|
93835
|
+
function resolveSecretPath(ref, create) {
|
|
93836
|
+
const parsed = parseSecretRef(ref);
|
|
93837
|
+
if (parsed.type !== "secret") {
|
|
93838
|
+
throw new UsageError(`Expected a secret ref (secrets/<name>); got "${ref}".`);
|
|
93839
|
+
}
|
|
93840
|
+
if (create) {
|
|
93841
|
+
assertFlatAssetName(parsed.name);
|
|
93842
|
+
parsed.name = combineCreatePath(normalizeCreateSubPath(create.subPath), parsed.name);
|
|
93843
|
+
}
|
|
93844
|
+
const source = findEnvSource(parsed.origin, "secret", parsed.name);
|
|
93845
|
+
const typeRoot = path54.join(source.path, "secrets");
|
|
93846
|
+
const absPath = assetPathForName("secret", typeRoot, parsed.name);
|
|
93847
|
+
if (!isWithin(absPath, typeRoot)) {
|
|
93848
|
+
throw new UsageError(`Secret name "${parsed.name}" escapes the secrets directory.`);
|
|
93849
|
+
}
|
|
93850
|
+
return { name: parsed.name, absPath, source };
|
|
93851
|
+
}
|
|
93852
|
+
|
|
93853
|
+
// src/sources/snapshot-fetchers/secret-seam.ts
|
|
93854
|
+
function resolveSecretFromStore(ref) {
|
|
93855
|
+
try {
|
|
93856
|
+
const { absPath } = resolveSecretPath(ref);
|
|
93857
|
+
if (!fs45.existsSync(absPath))
|
|
93858
|
+
return null;
|
|
93859
|
+
return fs45.readFileSync(absPath, "utf8").trim() || null;
|
|
93860
|
+
} catch {
|
|
93861
|
+
return null;
|
|
93862
|
+
}
|
|
93863
|
+
}
|
|
93864
|
+
|
|
93865
|
+
// src/llm/embedders/remote.ts
|
|
93715
93866
|
var DEFAULT_REMOTE_BATCH_SIZE = 100;
|
|
93716
93867
|
var DEFAULT_TOKEN_BUDGET = 8000;
|
|
93717
93868
|
function estimateTokenCount(text) {
|
|
@@ -93867,14 +94018,14 @@ class RemoteEmbedder {
|
|
|
93867
94018
|
}
|
|
93868
94019
|
buildHeaders() {
|
|
93869
94020
|
const headers = { "Content-Type": "application/json" };
|
|
93870
|
-
const resolvedKey = resolveSecret(this.config.apiKey);
|
|
94021
|
+
const resolvedKey = resolveSecret(this.config.apiKey, resolveSecretFromStore);
|
|
93871
94022
|
if (resolvedKey) {
|
|
93872
94023
|
headers.Authorization = `Bearer ${resolvedKey}`;
|
|
93873
94024
|
}
|
|
93874
94025
|
return headers;
|
|
93875
94026
|
}
|
|
93876
94027
|
safeErrorBody(body) {
|
|
93877
|
-
const resolvedKey = resolveSecret(this.config.apiKey);
|
|
94028
|
+
const resolvedKey = resolveSecret(this.config.apiKey, resolveSecretFromStore);
|
|
93878
94029
|
return redactSensitiveText(redactErrorBody(body), resolvedKey ? [resolvedKey] : []);
|
|
93879
94030
|
}
|
|
93880
94031
|
}
|
|
@@ -94110,7 +94261,7 @@ function publishTargetedEmbeddingMeta(db, config) {
|
|
|
94110
94261
|
}
|
|
94111
94262
|
|
|
94112
94263
|
// src/indexer/scan/drain-dir.ts
|
|
94113
|
-
import
|
|
94264
|
+
import path58 from "node:path";
|
|
94114
94265
|
init_common();
|
|
94115
94266
|
init_recognition_util();
|
|
94116
94267
|
|
|
@@ -94119,8 +94270,8 @@ init_common();
|
|
|
94119
94270
|
init_errors();
|
|
94120
94271
|
init_recognition_util();
|
|
94121
94272
|
init_warn();
|
|
94122
|
-
import
|
|
94123
|
-
import
|
|
94273
|
+
import fs46 from "node:fs";
|
|
94274
|
+
import path55 from "node:path";
|
|
94124
94275
|
|
|
94125
94276
|
class WorkflowSourceRejectionError extends UsageError {
|
|
94126
94277
|
sourcePaths;
|
|
@@ -94160,13 +94311,13 @@ class WorkflowSourcePathIdentityError extends WorkflowSourceRejectionError {
|
|
|
94160
94311
|
function workflowNameForSourcePath(sourceRoot, adapterId, sourcePath) {
|
|
94161
94312
|
if (adapterId !== "akm" && adapterId !== "akm-workflow")
|
|
94162
94313
|
return;
|
|
94163
|
-
const relativePath = toPosix(
|
|
94314
|
+
const relativePath = toPosix(path55.relative(path55.resolve(sourceRoot), path55.resolve(sourcePath)));
|
|
94164
94315
|
if (!isSafeRelativeName(relativePath))
|
|
94165
94316
|
return;
|
|
94166
94317
|
const ownedPath = adapterId === "akm" ? relativePath.replace(/^workflows\//, "") : relativePath;
|
|
94167
94318
|
if (adapterId === "akm" && ownedPath === relativePath)
|
|
94168
94319
|
return;
|
|
94169
|
-
const extension =
|
|
94320
|
+
const extension = path55.posix.extname(ownedPath);
|
|
94170
94321
|
if (!WORKFLOW_EXTENSIONS.includes(extension.toLowerCase()))
|
|
94171
94322
|
return;
|
|
94172
94323
|
return ownedPath;
|
|
@@ -94179,38 +94330,38 @@ function listWorkflowSourceFiles(sourceRoot, adapterId, name) {
|
|
|
94179
94330
|
throw new UsageError("Workflow ref resolves outside the bundle root.", "PATH_ESCAPE_VIOLATION");
|
|
94180
94331
|
}
|
|
94181
94332
|
let realRoot;
|
|
94182
|
-
const authoredRoot =
|
|
94333
|
+
const authoredRoot = path55.resolve(sourceRoot);
|
|
94183
94334
|
try {
|
|
94184
|
-
realRoot =
|
|
94335
|
+
realRoot = fs46.realpathSync(authoredRoot);
|
|
94185
94336
|
} catch {
|
|
94186
94337
|
return [];
|
|
94187
94338
|
}
|
|
94188
|
-
const ownershipRoot = adapterId === "akm" ?
|
|
94189
|
-
const parent =
|
|
94339
|
+
const ownershipRoot = adapterId === "akm" ? path55.join(authoredRoot, "workflows") : authoredRoot;
|
|
94340
|
+
const parent = path55.join(ownershipRoot, path55.dirname(canonicalName));
|
|
94190
94341
|
if (!isWithinResolved(parent, authoredRoot)) {
|
|
94191
94342
|
throw new UsageError("Workflow ref resolves outside the bundle root.", "PATH_ESCAPE_VIOLATION");
|
|
94192
94343
|
}
|
|
94193
94344
|
let entries;
|
|
94194
94345
|
try {
|
|
94195
|
-
entries =
|
|
94346
|
+
entries = fs46.readdirSync(parent, { withFileTypes: true });
|
|
94196
94347
|
} catch {
|
|
94197
94348
|
return [];
|
|
94198
94349
|
}
|
|
94199
|
-
const basename =
|
|
94350
|
+
const basename = path55.basename(canonicalName);
|
|
94200
94351
|
const candidates = [];
|
|
94201
94352
|
for (const entry of entries) {
|
|
94202
94353
|
if (!entry.isFile() && !entry.isSymbolicLink())
|
|
94203
94354
|
continue;
|
|
94204
|
-
const extension =
|
|
94355
|
+
const extension = path55.extname(entry.name);
|
|
94205
94356
|
const lowerExtension = extension.toLowerCase();
|
|
94206
94357
|
if (!WORKFLOW_EXTENSIONS.includes(lowerExtension))
|
|
94207
94358
|
continue;
|
|
94208
94359
|
if (entry.name.slice(0, -extension.length) !== basename)
|
|
94209
94360
|
continue;
|
|
94210
|
-
const candidatePath =
|
|
94361
|
+
const candidatePath = path55.join(parent, entry.name);
|
|
94211
94362
|
candidates.push({
|
|
94212
94363
|
path: candidatePath,
|
|
94213
|
-
relativePath: toPosix(
|
|
94364
|
+
relativePath: toPosix(path55.relative(authoredRoot, candidatePath)),
|
|
94214
94365
|
lowerExtension,
|
|
94215
94366
|
extensionlessStem: entry.name.slice(0, -extension.length)
|
|
94216
94367
|
});
|
|
@@ -94245,7 +94396,7 @@ function inspectWorkflowSourceCandidate(candidate, canonicalName, realRoot) {
|
|
|
94245
94396
|
const issues = [];
|
|
94246
94397
|
let authoredStat;
|
|
94247
94398
|
try {
|
|
94248
|
-
authoredStat =
|
|
94399
|
+
authoredStat = fs46.lstatSync(candidate.path);
|
|
94249
94400
|
} catch {
|
|
94250
94401
|
issues.push(new WorkflowSourceLinkResolutionError(candidate.relativePath));
|
|
94251
94402
|
return { issues };
|
|
@@ -94257,21 +94408,21 @@ function inspectWorkflowSourceCandidate(candidate, canonicalName, realRoot) {
|
|
|
94257
94408
|
}
|
|
94258
94409
|
let realPath;
|
|
94259
94410
|
try {
|
|
94260
|
-
realPath =
|
|
94411
|
+
realPath = fs46.realpathSync(candidate.path);
|
|
94261
94412
|
} catch {
|
|
94262
94413
|
issues.push(new WorkflowSourceLinkResolutionError(candidate.relativePath));
|
|
94263
94414
|
return { issues };
|
|
94264
94415
|
}
|
|
94265
|
-
const targetPath = toPosix(
|
|
94416
|
+
const targetPath = toPosix(path55.relative(realRoot, realPath));
|
|
94266
94417
|
const contained2 = isWithinResolved(realPath, realRoot);
|
|
94267
94418
|
if (!contained2)
|
|
94268
94419
|
issues.push(new WorkflowSourcePathIdentityError(candidate.relativePath, targetPath));
|
|
94269
|
-
if (isLink &&
|
|
94420
|
+
if (isLink && path55.extname(realPath).toLowerCase() !== candidate.lowerExtension) {
|
|
94270
94421
|
issues.push(new WorkflowSourceLinkIdentityError(candidate.relativePath, targetPath));
|
|
94271
94422
|
}
|
|
94272
94423
|
if (contained2) {
|
|
94273
94424
|
try {
|
|
94274
|
-
if (!
|
|
94425
|
+
if (!fs46.statSync(realPath).isFile())
|
|
94275
94426
|
issues.push(new WorkflowSourceLinkResolutionError(candidate.relativePath));
|
|
94276
94427
|
} catch {
|
|
94277
94428
|
issues.push(new WorkflowSourceLinkResolutionError(candidate.relativePath));
|
|
@@ -94299,11 +94450,11 @@ function normalizeName2(name) {
|
|
|
94299
94450
|
return name.replaceAll("\\", "/");
|
|
94300
94451
|
}
|
|
94301
94452
|
function isSafeRelativeName(name) {
|
|
94302
|
-
return name.length > 0 && !
|
|
94453
|
+
return name.length > 0 && !path55.posix.isAbsolute(name) && name !== ".." && !name.startsWith("../") && path55.posix.normalize(name) === name;
|
|
94303
94454
|
}
|
|
94304
94455
|
function isWithinResolved(candidate, root) {
|
|
94305
|
-
const relative =
|
|
94306
|
-
return relative === "" || !relative.startsWith("..") && !
|
|
94456
|
+
const relative = path55.relative(root, path55.resolve(candidate));
|
|
94457
|
+
return relative === "" || !relative.startsWith("..") && !path55.isAbsolute(relative);
|
|
94307
94458
|
}
|
|
94308
94459
|
|
|
94309
94460
|
// src/indexer/scan/drain-dir.ts
|
|
@@ -94312,13 +94463,13 @@ init_metadata();
|
|
|
94312
94463
|
init_file_context();
|
|
94313
94464
|
|
|
94314
94465
|
// src/indexer/scan/doc-to-entry.ts
|
|
94315
|
-
import
|
|
94466
|
+
import path57 from "node:path";
|
|
94316
94467
|
function indexDocumentToStashEntry(doc) {
|
|
94317
94468
|
const dj = doc.documentJson ?? {};
|
|
94318
94469
|
const entry = {
|
|
94319
94470
|
name: doc.name,
|
|
94320
94471
|
type: doc.type,
|
|
94321
|
-
filename:
|
|
94472
|
+
filename: path57.basename(doc.path ?? "")
|
|
94322
94473
|
};
|
|
94323
94474
|
if (doc.description !== undefined)
|
|
94324
94475
|
entry.description = doc.description;
|
|
@@ -94438,7 +94589,7 @@ function drainDirDocuments(adapter, component, fileContexts) {
|
|
|
94438
94589
|
throw error2;
|
|
94439
94590
|
rejectedConceptIds.add(adapter.id === "akm" ? `workflows/${canonicalName}` : canonicalName);
|
|
94440
94591
|
for (const relativePath of error2.sourcePaths) {
|
|
94441
|
-
rejectedPaths.add(
|
|
94592
|
+
rejectedPaths.add(path58.join(component.root, relativePath));
|
|
94442
94593
|
}
|
|
94443
94594
|
warnings.push(error2.message);
|
|
94444
94595
|
}
|
|
@@ -94500,7 +94651,7 @@ async function indexWrittenAssets(stashDir, filePaths, options = {}) {
|
|
|
94500
94651
|
if (isPathAbsent(dbPath))
|
|
94501
94652
|
return true;
|
|
94502
94653
|
const files = filePaths.filter((f) => {
|
|
94503
|
-
const rel =
|
|
94654
|
+
const rel = path59.relative(stashDir, f);
|
|
94504
94655
|
return !rel.split(/[\\/]+/).some((segment) => segment.startsWith("."));
|
|
94505
94656
|
});
|
|
94506
94657
|
if (files.length === 0)
|
|
@@ -94514,10 +94665,10 @@ async function indexWrittenAssets(stashDir, filePaths, options = {}) {
|
|
|
94514
94665
|
const unindexable = new Set;
|
|
94515
94666
|
const rejectedConceptIds = new Set;
|
|
94516
94667
|
for (const file of files) {
|
|
94517
|
-
if (!
|
|
94668
|
+
if (!fs48.existsSync(file)) {
|
|
94518
94669
|
let authoredDanglingSymlink = false;
|
|
94519
94670
|
try {
|
|
94520
|
-
authoredDanglingSymlink =
|
|
94671
|
+
authoredDanglingSymlink = fs48.lstatSync(file).isSymbolicLink();
|
|
94521
94672
|
} catch {}
|
|
94522
94673
|
if (!authoredDanglingSymlink) {
|
|
94523
94674
|
unindexable.add(file);
|
|
@@ -94568,7 +94719,7 @@ async function indexWrittenAssets(stashDir, filePaths, options = {}) {
|
|
|
94568
94719
|
for (const { file, entry, conceptId, contentHash } of pairs) {
|
|
94569
94720
|
let entryWithSize = entry;
|
|
94570
94721
|
try {
|
|
94571
|
-
entryWithSize = { ...entry, fileSize:
|
|
94722
|
+
entryWithSize = { ...entry, fileSize: fs48.statSync(file).size };
|
|
94572
94723
|
} catch {}
|
|
94573
94724
|
const provenance = deriveEntryProvenance({ bundleId: component.id, componentId: component.id, adapterId: component.adapter }, entry.type, entry.name, conceptId);
|
|
94574
94725
|
const supersededIds = db.prepare("SELECT id FROM entries WHERE file_path = ? AND item_ref <> ?").all(file, provenance.itemRef);
|
|
@@ -94601,7 +94752,7 @@ async function indexWrittenAssets(stashDir, filePaths, options = {}) {
|
|
|
94601
94752
|
init_asset_placement();
|
|
94602
94753
|
init_asset_ref();
|
|
94603
94754
|
init_warn();
|
|
94604
|
-
import
|
|
94755
|
+
import path60 from "node:path";
|
|
94605
94756
|
function changesToStored(changes) {
|
|
94606
94757
|
return changes.map((c, i) => ({
|
|
94607
94758
|
path: c.path,
|
|
@@ -94654,10 +94805,10 @@ function currentProposalTarget(value) {
|
|
|
94654
94805
|
if (typeof value !== "object" || value === null)
|
|
94655
94806
|
throw new Error("Proposal metadata has an invalid proposedTarget.");
|
|
94656
94807
|
const target = value;
|
|
94657
|
-
if (typeof target.source !== "string" || !isBundleSlug(target.source) || typeof target.root !== "string" || !
|
|
94808
|
+
if (typeof target.source !== "string" || !isBundleSlug(target.source) || typeof target.root !== "string" || !path60.isAbsolute(target.root)) {
|
|
94658
94809
|
throw new Error("Proposal metadata has an invalid proposedTarget.");
|
|
94659
94810
|
}
|
|
94660
|
-
return { source: target.source, root:
|
|
94811
|
+
return { source: target.source, root: path60.resolve(target.root) };
|
|
94661
94812
|
}
|
|
94662
94813
|
function invalidPresentField(name) {
|
|
94663
94814
|
throw new Error(`Proposal metadata has an invalid ${name}.`);
|
|
@@ -94697,7 +94848,7 @@ function validatePresentMetadata(meta) {
|
|
|
94697
94848
|
}
|
|
94698
94849
|
if (Object.hasOwn(meta, "acceptedTarget")) {
|
|
94699
94850
|
const target = meta.acceptedTarget;
|
|
94700
|
-
if (typeof target !== "object" || target === null || typeof target.source !== "string" || !isBundleSlug(target.source) || typeof target.root !== "string" || !
|
|
94851
|
+
if (typeof target !== "object" || target === null || typeof target.source !== "string" || !isBundleSlug(target.source) || typeof target.root !== "string" || !path60.isAbsolute(target.root) || typeof target.path !== "string" || !path60.isAbsolute(target.path) || typeof target.contentHash !== "string") {
|
|
94701
94852
|
invalidPresentField("acceptedTarget");
|
|
94702
94853
|
}
|
|
94703
94854
|
}
|
|
@@ -95431,12 +95582,12 @@ function proposalHash(content) {
|
|
|
95431
95582
|
return createHash9("sha256").update(content).digest("hex");
|
|
95432
95583
|
}
|
|
95433
95584
|
function proposalFileHash(filePath) {
|
|
95434
|
-
return proposalHash(
|
|
95585
|
+
return proposalHash(fs49.readFileSync(filePath));
|
|
95435
95586
|
}
|
|
95436
95587
|
function sameProposalFile(left, right) {
|
|
95437
95588
|
try {
|
|
95438
|
-
const leftStat =
|
|
95439
|
-
const rightStat =
|
|
95589
|
+
const leftStat = fs49.statSync(left);
|
|
95590
|
+
const rightStat = fs49.statSync(right);
|
|
95440
95591
|
return leftStat.dev === rightStat.dev && leftStat.ino === rightStat.ino;
|
|
95441
95592
|
} catch {
|
|
95442
95593
|
return false;
|
|
@@ -95445,20 +95596,20 @@ function sameProposalFile(left, right) {
|
|
|
95445
95596
|
function cleanupProposalPublication(p) {
|
|
95446
95597
|
for (const filePath of [p.publishPath, p.displacedPath]) {
|
|
95447
95598
|
try {
|
|
95448
|
-
|
|
95599
|
+
fs49.rmSync(filePath, { force: true });
|
|
95449
95600
|
} catch (error2) {
|
|
95450
95601
|
warn(`[proposals] transaction publication cleanup failed at ${filePath}: ${error2 instanceof Error ? error2.message : String(error2)}`);
|
|
95451
95602
|
}
|
|
95452
95603
|
}
|
|
95453
|
-
fsyncTxnDir(
|
|
95604
|
+
fsyncTxnDir(path61.dirname(p.assetPath));
|
|
95454
95605
|
}
|
|
95455
95606
|
function rollbackPreparedProposalTransaction(txn) {
|
|
95456
95607
|
const p = txn.journal.payload;
|
|
95457
|
-
const currentHash =
|
|
95458
|
-
if (!
|
|
95608
|
+
const currentHash = fs49.existsSync(p.assetPath) ? proposalFileHash(p.assetPath) : null;
|
|
95609
|
+
if (!fs49.existsSync(p.displacedPath)) {
|
|
95459
95610
|
if (p.originalHash === null) {
|
|
95460
95611
|
if (currentHash === p.publishedHash && sameProposalFile(p.assetPath, p.publishPath)) {
|
|
95461
|
-
|
|
95612
|
+
fs49.unlinkSync(p.assetPath);
|
|
95462
95613
|
recordWrittenPath(p.assetPath);
|
|
95463
95614
|
} else if (currentHash !== null) {
|
|
95464
95615
|
throw new Error(`Cannot roll back proposal transaction: target was created externally.`);
|
|
@@ -95470,30 +95621,30 @@ function rollbackPreparedProposalTransaction(txn) {
|
|
|
95470
95621
|
return;
|
|
95471
95622
|
}
|
|
95472
95623
|
if (currentHash === p.publishedHash) {
|
|
95473
|
-
|
|
95624
|
+
fs49.unlinkSync(p.assetPath);
|
|
95474
95625
|
recordWrittenPath(p.assetPath);
|
|
95475
95626
|
} else if (currentHash !== null && currentHash !== p.originalHash) {
|
|
95476
95627
|
throw new Error(`Cannot roll back proposal transaction: ${p.assetPath} diverged.`);
|
|
95477
95628
|
}
|
|
95478
|
-
if (
|
|
95479
|
-
if (
|
|
95629
|
+
if (fs49.existsSync(p.displacedPath)) {
|
|
95630
|
+
if (fs49.existsSync(p.assetPath)) {
|
|
95480
95631
|
throw new Error(`Cannot restore proposal backup: ${p.assetPath} is occupied.`);
|
|
95481
95632
|
}
|
|
95482
|
-
|
|
95633
|
+
fs49.linkSync(p.displacedPath, p.assetPath);
|
|
95483
95634
|
recordWrittenPath(p.assetPath);
|
|
95484
95635
|
}
|
|
95485
95636
|
cleanupProposalPublication(p);
|
|
95486
95637
|
}
|
|
95487
95638
|
function validatePublishedProposal(p) {
|
|
95488
|
-
if (!
|
|
95639
|
+
if (!fs49.existsSync(p.assetPath) || proposalFileHash(p.assetPath) !== p.publishedHash) {
|
|
95489
95640
|
throw new Error(`Cannot recover proposal ${p.proposalId}: published asset diverged.`);
|
|
95490
95641
|
}
|
|
95491
95642
|
}
|
|
95492
95643
|
function persistProposalTransactionState(txn, proposal, ctx) {
|
|
95493
95644
|
const p = txn.journal.payload;
|
|
95494
95645
|
const decidedAt = txn.journal.decidedAt;
|
|
95495
|
-
const backupContent = p.backupPath ?
|
|
95496
|
-
const publishedContent =
|
|
95646
|
+
const backupContent = p.backupPath ? fs49.readFileSync(p.backupPath, "utf8") : undefined;
|
|
95647
|
+
const publishedContent = fs49.readFileSync(p.contentPath, "utf8");
|
|
95497
95648
|
return withProposalsDb(p.stashDir, ctx, (db) => withImmediateTransaction(db, () => {
|
|
95498
95649
|
const current = requireProposal(db, p.stashDir, p.proposalId);
|
|
95499
95650
|
if (p.operation === "accept") {
|
|
@@ -95511,7 +95662,7 @@ function persistProposalTransactionState(txn, proposal, ctx) {
|
|
|
95511
95662
|
payload: { ...proposal.payload, content: publishedContent },
|
|
95512
95663
|
changes: [
|
|
95513
95664
|
{
|
|
95514
|
-
path:
|
|
95665
|
+
path: path61.relative(txn.journal.root, p.assetPath),
|
|
95515
95666
|
op: p.originalHash === null ? "create" : "update",
|
|
95516
95667
|
after: publishedContent
|
|
95517
95668
|
}
|
|
@@ -95582,7 +95733,7 @@ async function finalizeProposalTransaction(txn, target, proposal, ctx) {
|
|
|
95582
95733
|
cleanupProposalPublication(p);
|
|
95583
95734
|
if (txn.journal.phase === "asset-published") {
|
|
95584
95735
|
const commitRoot = target.source.repoPath ?? target.source.path;
|
|
95585
|
-
const commitPath =
|
|
95736
|
+
const commitPath = path61.relative(commitRoot, p.assetPath).replaceAll(path61.sep, "/");
|
|
95586
95737
|
publishWriteTargetTransaction(target, p.gitPublication, {
|
|
95587
95738
|
transactionId: txn.journal.transactionId,
|
|
95588
95739
|
message: `${p.operation === "accept" ? "Update" : "Revert"} ${p.ref}`,
|
|
@@ -95619,8 +95770,8 @@ async function finalizeProposalTransaction(txn, target, proposal, ctx) {
|
|
|
95619
95770
|
function fenceProposalTxnJournal(journal, txnDir, root) {
|
|
95620
95771
|
const p = journal.payload;
|
|
95621
95772
|
const refIdentity = proposalRefIdentity(p.ref);
|
|
95622
|
-
if (!["accept", "revert"].includes(p.operation) || !p.targetSource || !p.targetKind || refIdentity?.bundle === undefined || !isWithin(p.assetPath, root) || ![p.contentPath, p.backupPath].filter((candidate) => candidate !== null).every((candidate) => isWithin(candidate, txnDir)) || ![p.publishPath, p.displacedPath].every((candidate) => isWithin(candidate, root) &&
|
|
95623
|
-
throw new Error(`Refusing unsafe proposal transaction journal at ${
|
|
95773
|
+
if (!["accept", "revert"].includes(p.operation) || !p.targetSource || !p.targetKind || refIdentity?.bundle === undefined || !isWithin(p.assetPath, root) || ![p.contentPath, p.backupPath].filter((candidate) => candidate !== null).every((candidate) => isWithin(candidate, txnDir)) || ![p.publishPath, p.displacedPath].every((candidate) => isWithin(candidate, root) && path61.dirname(candidate) === path61.dirname(p.assetPath))) {
|
|
95774
|
+
throw new Error(`Refusing unsafe proposal transaction journal at ${path61.join(txnDir, "journal.json")}.`);
|
|
95624
95775
|
}
|
|
95625
95776
|
}
|
|
95626
95777
|
function resolveProposalRecoveryTarget(config, journal) {
|
|
@@ -95720,8 +95871,8 @@ async function recoverStaleTxns(stashDir) {
|
|
|
95720
95871
|
}
|
|
95721
95872
|
|
|
95722
95873
|
// scripts/akm-migrate/migrate/writer-relocation.ts
|
|
95723
|
-
import
|
|
95724
|
-
import
|
|
95874
|
+
import fs50 from "node:fs";
|
|
95875
|
+
import path62 from "node:path";
|
|
95725
95876
|
init_paths();
|
|
95726
95877
|
function relocationSpecs(stashDir) {
|
|
95727
95878
|
return [
|
|
@@ -95741,7 +95892,7 @@ function mutexSiblingName(lockName) {
|
|
|
95741
95892
|
function fileCountIfExists(dir) {
|
|
95742
95893
|
let entries;
|
|
95743
95894
|
try {
|
|
95744
|
-
entries =
|
|
95895
|
+
entries = fs50.readdirSync(dir, { withFileTypes: true });
|
|
95745
95896
|
} catch {
|
|
95746
95897
|
return;
|
|
95747
95898
|
}
|
|
@@ -95749,7 +95900,7 @@ function fileCountIfExists(dir) {
|
|
|
95749
95900
|
}
|
|
95750
95901
|
function statFileIfExists(filePath) {
|
|
95751
95902
|
try {
|
|
95752
|
-
const stat =
|
|
95903
|
+
const stat = fs50.statSync(filePath);
|
|
95753
95904
|
return stat.isFile() ? stat : undefined;
|
|
95754
95905
|
} catch {
|
|
95755
95906
|
return;
|
|
@@ -95759,8 +95910,8 @@ function classifyLockArtifacts(akmDir) {
|
|
|
95759
95910
|
const removable = [];
|
|
95760
95911
|
const skipped = [];
|
|
95761
95912
|
for (const lockName of LOCK_NAMES) {
|
|
95762
|
-
const lockPath =
|
|
95763
|
-
const mutexPath =
|
|
95913
|
+
const lockPath = path62.join(akmDir, lockName);
|
|
95914
|
+
const mutexPath = path62.join(akmDir, mutexSiblingName(lockName));
|
|
95764
95915
|
const lockStat = statFileIfExists(lockPath);
|
|
95765
95916
|
const mutexStat = statFileIfExists(mutexPath);
|
|
95766
95917
|
if (!lockStat) {
|
|
@@ -95786,11 +95937,11 @@ function classifyLockArtifacts(akmDir) {
|
|
|
95786
95937
|
return { removable, skipped };
|
|
95787
95938
|
}
|
|
95788
95939
|
function findWriterRelocationEntries(stashDir) {
|
|
95789
|
-
const akmDir =
|
|
95940
|
+
const akmDir = path62.join(stashDir, ".akm");
|
|
95790
95941
|
const directories = [];
|
|
95791
95942
|
for (const spec of relocationSpecs(stashDir)) {
|
|
95792
95943
|
const relativeParts = Array.isArray(spec.oldRelative) ? spec.oldRelative : [spec.oldRelative];
|
|
95793
|
-
const oldPath =
|
|
95944
|
+
const oldPath = path62.join(akmDir, ...relativeParts);
|
|
95794
95945
|
const fileCount = fileCountIfExists(oldPath);
|
|
95795
95946
|
if (fileCount === undefined || fileCount === 0)
|
|
95796
95947
|
continue;
|
|
@@ -95801,36 +95952,36 @@ function findWriterRelocationEntries(stashDir) {
|
|
|
95801
95952
|
}
|
|
95802
95953
|
function moveFile(oldFilePath, newFilePath) {
|
|
95803
95954
|
try {
|
|
95804
|
-
|
|
95955
|
+
fs50.renameSync(oldFilePath, newFilePath);
|
|
95805
95956
|
} catch (error2) {
|
|
95806
95957
|
if (error2.code !== "EXDEV")
|
|
95807
95958
|
throw error2;
|
|
95808
|
-
|
|
95809
|
-
|
|
95959
|
+
fs50.copyFileSync(oldFilePath, newFilePath);
|
|
95960
|
+
fs50.rmSync(oldFilePath, { force: true });
|
|
95810
95961
|
}
|
|
95811
95962
|
}
|
|
95812
95963
|
function moveDirectoryContents(entry) {
|
|
95813
95964
|
const errors3 = [];
|
|
95814
95965
|
let moved = 0;
|
|
95815
|
-
|
|
95966
|
+
fs50.mkdirSync(entry.newPath, { recursive: true });
|
|
95816
95967
|
let names;
|
|
95817
95968
|
try {
|
|
95818
|
-
names =
|
|
95969
|
+
names = fs50.readdirSync(entry.oldPath).sort();
|
|
95819
95970
|
} catch {
|
|
95820
95971
|
return { key: entry.key, oldPath: entry.oldPath, newPath: entry.newPath, moved: 0, errors: [] };
|
|
95821
95972
|
}
|
|
95822
95973
|
for (const name of names) {
|
|
95823
|
-
const oldFilePath =
|
|
95824
|
-
const newFilePath =
|
|
95974
|
+
const oldFilePath = path62.join(entry.oldPath, name);
|
|
95975
|
+
const newFilePath = path62.join(entry.newPath, name);
|
|
95825
95976
|
let oldStat;
|
|
95826
95977
|
try {
|
|
95827
|
-
oldStat =
|
|
95978
|
+
oldStat = fs50.lstatSync(oldFilePath);
|
|
95828
95979
|
} catch {
|
|
95829
95980
|
continue;
|
|
95830
95981
|
}
|
|
95831
95982
|
if (!oldStat.isFile())
|
|
95832
95983
|
continue;
|
|
95833
|
-
if (
|
|
95984
|
+
if (fs50.existsSync(newFilePath))
|
|
95834
95985
|
continue;
|
|
95835
95986
|
try {
|
|
95836
95987
|
moveFile(oldFilePath, newFilePath);
|
|
@@ -95843,13 +95994,13 @@ function moveDirectoryContents(entry) {
|
|
|
95843
95994
|
}
|
|
95844
95995
|
function removeIfEmptyDir(dir) {
|
|
95845
95996
|
try {
|
|
95846
|
-
if (
|
|
95847
|
-
|
|
95997
|
+
if (fs50.readdirSync(dir).length === 0)
|
|
95998
|
+
fs50.rmdirSync(dir);
|
|
95848
95999
|
} catch {}
|
|
95849
96000
|
}
|
|
95850
96001
|
function removeLockArtifact(entry) {
|
|
95851
96002
|
try {
|
|
95852
|
-
|
|
96003
|
+
fs50.rmSync(entry.path, { force: true });
|
|
95853
96004
|
return { path: entry.path, removed: true };
|
|
95854
96005
|
} catch (error2) {
|
|
95855
96006
|
return { path: entry.path, removed: false, error: error2 instanceof Error ? error2.message : String(error2) };
|
|
@@ -95861,36 +96012,36 @@ function applyWriterRelocation(stashDir) {
|
|
|
95861
96012
|
const lockResults = lockArtifacts.map(removeLockArtifact);
|
|
95862
96013
|
for (const spec of relocationSpecs(stashDir)) {
|
|
95863
96014
|
const relativeParts = Array.isArray(spec.oldRelative) ? spec.oldRelative : [spec.oldRelative];
|
|
95864
|
-
removeIfEmptyDir(
|
|
96015
|
+
removeIfEmptyDir(path62.join(stashDir, ".akm", ...relativeParts));
|
|
95865
96016
|
}
|
|
95866
96017
|
return { directories: directoryResults, lockArtifacts: lockResults, skippedLocks };
|
|
95867
96018
|
}
|
|
95868
96019
|
|
|
95869
96020
|
// scripts/akm-migrate/task-migrate.ts
|
|
95870
96021
|
import { randomUUID as randomUUID7 } from "node:crypto";
|
|
95871
|
-
import
|
|
96022
|
+
import fs56 from "node:fs";
|
|
95872
96023
|
import os5 from "node:os";
|
|
95873
|
-
import
|
|
96024
|
+
import path65 from "node:path";
|
|
95874
96025
|
init_errors();
|
|
95875
96026
|
init_paths();
|
|
95876
96027
|
|
|
95877
96028
|
// scripts/akm-migrate/migrate/task-files-to-v3.ts
|
|
95878
96029
|
init_errors();
|
|
95879
96030
|
import crypto6 from "node:crypto";
|
|
95880
|
-
import
|
|
95881
|
-
import
|
|
96031
|
+
import fs53 from "node:fs";
|
|
96032
|
+
import path63 from "node:path";
|
|
95882
96033
|
|
|
95883
96034
|
// scripts/akm-migrate/migrate/durable-fs.ts
|
|
95884
|
-
import
|
|
96035
|
+
import fs51 from "node:fs";
|
|
95885
96036
|
function fsyncDirectoryPortable(directory) {
|
|
95886
96037
|
if (process.platform === "win32")
|
|
95887
96038
|
return;
|
|
95888
96039
|
try {
|
|
95889
|
-
const fd =
|
|
96040
|
+
const fd = fs51.openSync(directory, "r");
|
|
95890
96041
|
try {
|
|
95891
|
-
|
|
96042
|
+
fs51.fsyncSync(fd);
|
|
95892
96043
|
} finally {
|
|
95893
|
-
|
|
96044
|
+
fs51.closeSync(fd);
|
|
95894
96045
|
}
|
|
95895
96046
|
} catch (cause) {
|
|
95896
96047
|
const code = cause.code;
|
|
@@ -95904,25 +96055,25 @@ function migrationError(detail) {
|
|
|
95904
96055
|
return new ConfigError(`Task migration to v3 failed: ${detail}`, "INVALID_CONFIG_FILE");
|
|
95905
96056
|
}
|
|
95906
96057
|
function contained2(root, candidate) {
|
|
95907
|
-
const relative =
|
|
95908
|
-
return relative === "" || !relative.startsWith("..") && !
|
|
96058
|
+
const relative = path63.relative(root, candidate);
|
|
96059
|
+
return relative === "" || !relative.startsWith("..") && !path63.isAbsolute(relative);
|
|
95909
96060
|
}
|
|
95910
96061
|
function realDirectory(filePath) {
|
|
95911
|
-
const stat =
|
|
96062
|
+
const stat = fs53.lstatSync(filePath);
|
|
95912
96063
|
if (stat.isSymbolicLink() || !stat.isDirectory())
|
|
95913
96064
|
throw migrationError(`${filePath} must be a real directory.`);
|
|
95914
|
-
return
|
|
96065
|
+
return fs53.realpathSync(filePath);
|
|
95915
96066
|
}
|
|
95916
96067
|
function snapshot(filePath) {
|
|
95917
|
-
const stat =
|
|
96068
|
+
const stat = fs53.lstatSync(filePath);
|
|
95918
96069
|
if (stat.isSymbolicLink() || !stat.isFile())
|
|
95919
96070
|
throw migrationError(`${filePath} must be a real file.`);
|
|
95920
|
-
const bytes =
|
|
96071
|
+
const bytes = fs53.readFileSync(filePath);
|
|
95921
96072
|
return Object.freeze({ bytes, mode: stat.mode & 511 });
|
|
95922
96073
|
}
|
|
95923
96074
|
function writable(filePath) {
|
|
95924
96075
|
try {
|
|
95925
|
-
|
|
96076
|
+
fs53.accessSync(filePath, fs53.constants.W_OK);
|
|
95926
96077
|
return true;
|
|
95927
96078
|
} catch {
|
|
95928
96079
|
return false;
|
|
@@ -95935,12 +96086,12 @@ function walkTasks(root, tasksDir, out) {
|
|
|
95935
96086
|
throw migrationError(`${root.root} resolves outside bundle ${root.bundleId}.`);
|
|
95936
96087
|
}
|
|
95937
96088
|
const visit2 = (directory) => {
|
|
95938
|
-
const physicalDirectory =
|
|
96089
|
+
const physicalDirectory = fs53.realpathSync(directory);
|
|
95939
96090
|
if (!contained2(physicalRoot, physicalDirectory)) {
|
|
95940
96091
|
throw migrationError(`${directory} resolves outside bundle ${root.bundleId}.`);
|
|
95941
96092
|
}
|
|
95942
|
-
for (const entry of
|
|
95943
|
-
const candidate =
|
|
96093
|
+
for (const entry of fs53.readdirSync(directory, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
|
|
96094
|
+
const candidate = path63.join(directory, entry.name);
|
|
95944
96095
|
if (entry.isSymbolicLink())
|
|
95945
96096
|
throw migrationError(`task migration does not follow symbolic link ${candidate}.`);
|
|
95946
96097
|
if (entry.isDirectory()) {
|
|
@@ -95950,7 +96101,7 @@ function walkTasks(root, tasksDir, out) {
|
|
|
95950
96101
|
if (!entry.isFile() || !entry.name.endsWith(".yml"))
|
|
95951
96102
|
continue;
|
|
95952
96103
|
const current = snapshot(candidate);
|
|
95953
|
-
const parent =
|
|
96104
|
+
const parent = path63.dirname(candidate);
|
|
95954
96105
|
out.push({
|
|
95955
96106
|
filePath: candidate,
|
|
95956
96107
|
bytes: current.bytes,
|
|
@@ -95966,9 +96117,9 @@ function walkTasks(root, tasksDir, out) {
|
|
|
95966
96117
|
function inspectTaskToV3Files(roots) {
|
|
95967
96118
|
const files = [];
|
|
95968
96119
|
for (const root of [...roots].sort((a, b) => a.bundleId.localeCompare(b.bundleId))) {
|
|
95969
|
-
const tasksDir = root.layout === "akm-task" ? root.root :
|
|
96120
|
+
const tasksDir = root.layout === "akm-task" ? root.root : path63.join(root.root, "tasks");
|
|
95970
96121
|
try {
|
|
95971
|
-
const stat =
|
|
96122
|
+
const stat = fs53.lstatSync(tasksDir);
|
|
95972
96123
|
if (stat.isSymbolicLink())
|
|
95973
96124
|
throw migrationError(`task migration does not follow symbolic link ${tasksDir}.`);
|
|
95974
96125
|
if (!stat.isDirectory())
|
|
@@ -95983,33 +96134,33 @@ function inspectTaskToV3Files(roots) {
|
|
|
95983
96134
|
return files.sort((a, b) => a.filePath.localeCompare(b.filePath));
|
|
95984
96135
|
}
|
|
95985
96136
|
function hashPath(filePath) {
|
|
95986
|
-
return crypto6.createHash("sha256").update(
|
|
96137
|
+
return crypto6.createHash("sha256").update(path63.resolve(filePath)).digest("hex").slice(0, 16);
|
|
95987
96138
|
}
|
|
95988
96139
|
function taskMigrationBackupPath(backupRoot, filePath) {
|
|
95989
|
-
return
|
|
96140
|
+
return path63.join(backupRoot, "files", `${hashPath(filePath)}-${path63.basename(filePath)}`);
|
|
95990
96141
|
}
|
|
95991
96142
|
function writeDurable(filePath, bytes, mode, exclusive = false) {
|
|
95992
|
-
|
|
96143
|
+
fs53.mkdirSync(path63.dirname(filePath), { recursive: true });
|
|
95993
96144
|
const flags = exclusive ? "wx" : "w";
|
|
95994
|
-
const fd =
|
|
96145
|
+
const fd = fs53.openSync(filePath, flags, mode);
|
|
95995
96146
|
try {
|
|
95996
|
-
|
|
95997
|
-
|
|
96147
|
+
fs53.writeFileSync(fd, bytes);
|
|
96148
|
+
fs53.fsyncSync(fd);
|
|
95998
96149
|
} finally {
|
|
95999
|
-
|
|
96150
|
+
fs53.closeSync(fd);
|
|
96000
96151
|
}
|
|
96001
|
-
|
|
96002
|
-
fsyncDirectoryPortable(
|
|
96152
|
+
fs53.chmodSync(filePath, mode);
|
|
96153
|
+
fsyncDirectoryPortable(path63.dirname(filePath));
|
|
96003
96154
|
}
|
|
96004
96155
|
function replaceAtomically(filePath, bytes, mode) {
|
|
96005
|
-
const temporary =
|
|
96156
|
+
const temporary = path63.join(path63.dirname(filePath), `.${path63.basename(filePath)}.migrate-${crypto6.randomUUID()}`);
|
|
96006
96157
|
try {
|
|
96007
96158
|
writeDurable(temporary, bytes, mode, true);
|
|
96008
|
-
|
|
96009
|
-
fsyncDirectoryPortable(
|
|
96159
|
+
fs53.renameSync(temporary, filePath);
|
|
96160
|
+
fsyncDirectoryPortable(path63.dirname(filePath));
|
|
96010
96161
|
} finally {
|
|
96011
96162
|
try {
|
|
96012
|
-
|
|
96163
|
+
fs53.unlinkSync(temporary);
|
|
96013
96164
|
} catch (cause) {
|
|
96014
96165
|
if (cause.code !== "ENOENT")
|
|
96015
96166
|
throw cause;
|
|
@@ -96048,7 +96199,7 @@ function applyTaskToV3MigrationPlan(plan, options) {
|
|
|
96048
96199
|
const current = snapshot(change.filePath);
|
|
96049
96200
|
if (!current.bytes.equals(change.after))
|
|
96050
96201
|
continue;
|
|
96051
|
-
replaceAtomically(change.filePath,
|
|
96202
|
+
replaceAtomically(change.filePath, fs53.readFileSync(taskMigrationBackupPath(options.backupRoot, change.filePath)), change.mode);
|
|
96052
96203
|
}
|
|
96053
96204
|
throw cause;
|
|
96054
96205
|
}
|
|
@@ -96058,31 +96209,31 @@ function applyTaskToV3MigrationPlan(plan, options) {
|
|
|
96058
96209
|
// scripts/akm-migrate/migrate/task-files-to-v4.ts
|
|
96059
96210
|
init_errors();
|
|
96060
96211
|
import crypto7 from "node:crypto";
|
|
96061
|
-
import
|
|
96062
|
-
import
|
|
96212
|
+
import fs55 from "node:fs";
|
|
96213
|
+
import path64 from "node:path";
|
|
96063
96214
|
function migrationError2(detail) {
|
|
96064
96215
|
return new ConfigError(`Task migration to v4 failed: ${detail}`, "INVALID_CONFIG_FILE");
|
|
96065
96216
|
}
|
|
96066
96217
|
function contained3(root, candidate) {
|
|
96067
|
-
const relative =
|
|
96068
|
-
return relative === "" || !relative.startsWith("..") && !
|
|
96218
|
+
const relative = path64.relative(root, candidate);
|
|
96219
|
+
return relative === "" || !relative.startsWith("..") && !path64.isAbsolute(relative);
|
|
96069
96220
|
}
|
|
96070
96221
|
function realDirectory2(filePath) {
|
|
96071
|
-
const stat =
|
|
96222
|
+
const stat = fs55.lstatSync(filePath);
|
|
96072
96223
|
if (stat.isSymbolicLink() || !stat.isDirectory())
|
|
96073
96224
|
throw migrationError2(`${filePath} must be a real directory.`);
|
|
96074
|
-
return
|
|
96225
|
+
return fs55.realpathSync(filePath);
|
|
96075
96226
|
}
|
|
96076
96227
|
function snapshot2(filePath) {
|
|
96077
|
-
const stat =
|
|
96228
|
+
const stat = fs55.lstatSync(filePath);
|
|
96078
96229
|
if (stat.isSymbolicLink() || !stat.isFile())
|
|
96079
96230
|
throw migrationError2(`${filePath} must be a real file.`);
|
|
96080
|
-
const bytes =
|
|
96231
|
+
const bytes = fs55.readFileSync(filePath);
|
|
96081
96232
|
return Object.freeze({ bytes, mode: stat.mode & 511 });
|
|
96082
96233
|
}
|
|
96083
96234
|
function writable2(filePath) {
|
|
96084
96235
|
try {
|
|
96085
|
-
|
|
96236
|
+
fs55.accessSync(filePath, fs55.constants.W_OK);
|
|
96086
96237
|
return true;
|
|
96087
96238
|
} catch {
|
|
96088
96239
|
return false;
|
|
@@ -96095,12 +96246,12 @@ function walkTasks2(root, tasksDir, out) {
|
|
|
96095
96246
|
throw migrationError2(`${root.root} resolves outside bundle ${root.bundleId}.`);
|
|
96096
96247
|
}
|
|
96097
96248
|
const visit2 = (directory) => {
|
|
96098
|
-
const physicalDirectory =
|
|
96249
|
+
const physicalDirectory = fs55.realpathSync(directory);
|
|
96099
96250
|
if (!contained3(physicalRoot, physicalDirectory)) {
|
|
96100
96251
|
throw migrationError2(`${directory} resolves outside bundle ${root.bundleId}.`);
|
|
96101
96252
|
}
|
|
96102
|
-
for (const entry of
|
|
96103
|
-
const candidate =
|
|
96253
|
+
for (const entry of fs55.readdirSync(directory, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
|
|
96254
|
+
const candidate = path64.join(directory, entry.name);
|
|
96104
96255
|
if (entry.isSymbolicLink())
|
|
96105
96256
|
throw migrationError2(`task migration does not follow symbolic link ${candidate}.`);
|
|
96106
96257
|
if (entry.isDirectory()) {
|
|
@@ -96110,7 +96261,7 @@ function walkTasks2(root, tasksDir, out) {
|
|
|
96110
96261
|
if (!entry.isFile() || !entry.name.endsWith(".yml"))
|
|
96111
96262
|
continue;
|
|
96112
96263
|
const current = snapshot2(candidate);
|
|
96113
|
-
const parent =
|
|
96264
|
+
const parent = path64.dirname(candidate);
|
|
96114
96265
|
out.push({
|
|
96115
96266
|
filePath: candidate,
|
|
96116
96267
|
bytes: current.bytes,
|
|
@@ -96126,9 +96277,9 @@ function walkTasks2(root, tasksDir, out) {
|
|
|
96126
96277
|
function inspectTaskToV4Files(roots) {
|
|
96127
96278
|
const files = [];
|
|
96128
96279
|
for (const root of [...roots].sort((a, b) => a.bundleId.localeCompare(b.bundleId))) {
|
|
96129
|
-
const tasksDir = root.layout === "akm-task" ? root.root :
|
|
96280
|
+
const tasksDir = root.layout === "akm-task" ? root.root : path64.join(root.root, "tasks");
|
|
96130
96281
|
try {
|
|
96131
|
-
const stat =
|
|
96282
|
+
const stat = fs55.lstatSync(tasksDir);
|
|
96132
96283
|
if (stat.isSymbolicLink())
|
|
96133
96284
|
throw migrationError2(`task migration does not follow symbolic link ${tasksDir}.`);
|
|
96134
96285
|
if (!stat.isDirectory())
|
|
@@ -96143,33 +96294,33 @@ function inspectTaskToV4Files(roots) {
|
|
|
96143
96294
|
return files.sort((a, b) => a.filePath.localeCompare(b.filePath));
|
|
96144
96295
|
}
|
|
96145
96296
|
function hashPath2(filePath) {
|
|
96146
|
-
return crypto7.createHash("sha256").update(
|
|
96297
|
+
return crypto7.createHash("sha256").update(path64.resolve(filePath)).digest("hex").slice(0, 16);
|
|
96147
96298
|
}
|
|
96148
96299
|
function taskMigrationBackupPathV4(backupRoot, filePath) {
|
|
96149
|
-
return
|
|
96300
|
+
return path64.join(backupRoot, "files", `${hashPath2(filePath)}-${path64.basename(filePath)}`);
|
|
96150
96301
|
}
|
|
96151
96302
|
function writeDurable2(filePath, bytes, mode, exclusive = false) {
|
|
96152
|
-
|
|
96303
|
+
fs55.mkdirSync(path64.dirname(filePath), { recursive: true });
|
|
96153
96304
|
const flags = exclusive ? "wx" : "w";
|
|
96154
|
-
const fd =
|
|
96305
|
+
const fd = fs55.openSync(filePath, flags, mode);
|
|
96155
96306
|
try {
|
|
96156
|
-
|
|
96157
|
-
|
|
96307
|
+
fs55.writeFileSync(fd, bytes);
|
|
96308
|
+
fs55.fsyncSync(fd);
|
|
96158
96309
|
} finally {
|
|
96159
|
-
|
|
96310
|
+
fs55.closeSync(fd);
|
|
96160
96311
|
}
|
|
96161
|
-
|
|
96162
|
-
fsyncDirectoryPortable(
|
|
96312
|
+
fs55.chmodSync(filePath, mode);
|
|
96313
|
+
fsyncDirectoryPortable(path64.dirname(filePath));
|
|
96163
96314
|
}
|
|
96164
96315
|
function replaceAtomically2(filePath, bytes, mode) {
|
|
96165
|
-
const temporary =
|
|
96316
|
+
const temporary = path64.join(path64.dirname(filePath), `.${path64.basename(filePath)}.migrate-${crypto7.randomUUID()}`);
|
|
96166
96317
|
try {
|
|
96167
96318
|
writeDurable2(temporary, bytes, mode, true);
|
|
96168
|
-
|
|
96169
|
-
fsyncDirectoryPortable(
|
|
96319
|
+
fs55.renameSync(temporary, filePath);
|
|
96320
|
+
fsyncDirectoryPortable(path64.dirname(filePath));
|
|
96170
96321
|
} finally {
|
|
96171
96322
|
try {
|
|
96172
|
-
|
|
96323
|
+
fs55.unlinkSync(temporary);
|
|
96173
96324
|
} catch (cause) {
|
|
96174
96325
|
if (cause.code !== "ENOENT")
|
|
96175
96326
|
throw cause;
|
|
@@ -96208,7 +96359,7 @@ function applyTaskToV4MigrationPlan(plan, options) {
|
|
|
96208
96359
|
const current = snapshot2(change.filePath);
|
|
96209
96360
|
if (!current.bytes.equals(change.after))
|
|
96210
96361
|
continue;
|
|
96211
|
-
replaceAtomically2(change.filePath,
|
|
96362
|
+
replaceAtomically2(change.filePath, fs55.readFileSync(taskMigrationBackupPathV4(options.backupRoot, change.filePath)), change.mode);
|
|
96212
96363
|
}
|
|
96213
96364
|
throw cause;
|
|
96214
96365
|
}
|
|
@@ -96220,12 +96371,12 @@ function expandTilde(value) {
|
|
|
96220
96371
|
if (value === "~")
|
|
96221
96372
|
return os5.homedir();
|
|
96222
96373
|
if (value.startsWith("~/") || value.startsWith("~\\"))
|
|
96223
|
-
return
|
|
96374
|
+
return path65.join(os5.homedir(), value.slice(2));
|
|
96224
96375
|
return value;
|
|
96225
96376
|
}
|
|
96226
96377
|
function existingDirectory(target) {
|
|
96227
96378
|
try {
|
|
96228
|
-
return
|
|
96379
|
+
return fs56.statSync(target).isDirectory();
|
|
96229
96380
|
} catch (cause) {
|
|
96230
96381
|
if (cause.code === "ENOENT")
|
|
96231
96382
|
return false;
|
|
@@ -96246,21 +96397,21 @@ function taskRoots(config, resolutionBase = process.cwd()) {
|
|
|
96246
96397
|
const source = sources.get(bundleId);
|
|
96247
96398
|
if (!source)
|
|
96248
96399
|
continue;
|
|
96249
|
-
const configuredRoot = source.type === "filesystem" && source.path ?
|
|
96400
|
+
const configuredRoot = source.type === "filesystem" && source.path ? path65.resolve(resolutionBase, expandTilde(source.path)) : lockContentRootFor(bundleId, source.type);
|
|
96250
96401
|
if (!configuredRoot || !existingDirectory(configuredRoot))
|
|
96251
96402
|
continue;
|
|
96252
|
-
const bundleRoot =
|
|
96403
|
+
const bundleRoot = path65.resolve(configuredRoot);
|
|
96253
96404
|
const component = bundleComponentConfig(bundle);
|
|
96254
|
-
const componentRoot =
|
|
96255
|
-
const relative =
|
|
96256
|
-
if (relative === ".." || relative.startsWith(`..${
|
|
96405
|
+
const componentRoot = path65.resolve(bundleRoot, component?.root ?? ".");
|
|
96406
|
+
const relative = path65.relative(bundleRoot, componentRoot);
|
|
96407
|
+
if (relative === ".." || relative.startsWith(`..${path65.sep}`) || path65.isAbsolute(relative)) {
|
|
96257
96408
|
throw new ConfigError(`Task migration component root ${componentRoot} escapes bundle ${bundleId} at ${bundleRoot}.`, "INVALID_CONFIG_FILE");
|
|
96258
96409
|
}
|
|
96259
96410
|
if (!existingDirectory(componentRoot))
|
|
96260
96411
|
continue;
|
|
96261
96412
|
const adapter = component?.adapter ?? detectAdapterId(componentRoot, "");
|
|
96262
96413
|
if (!component?.adapter && adapter === "") {
|
|
96263
|
-
const flatTasks =
|
|
96414
|
+
const flatTasks = fs56.readdirSync(componentRoot, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".yml")).map((entry) => entry.name).sort();
|
|
96264
96415
|
if (flatTasks.length > 0) {
|
|
96265
96416
|
throw new ConfigError(`Task migration cannot classify top-level task file(s) ${flatTasks.join(", ")} in bundle ${bundleId}; configure adapter "akm-task" or move them under tasks/.`, "INVALID_CONFIG_FILE");
|
|
96266
96417
|
}
|
|
@@ -96332,8 +96483,8 @@ function applyTaskV3Migration() {
|
|
|
96332
96483
|
const before = inspectCurrentTaskPlan();
|
|
96333
96484
|
if (before.result.taskV3Migration.changed === 0)
|
|
96334
96485
|
return before.result;
|
|
96335
|
-
const backupRoot =
|
|
96336
|
-
const backupPath =
|
|
96486
|
+
const backupRoot = path65.join(getDataDir(), "backups", "task-v3");
|
|
96487
|
+
const backupPath = path65.join(backupRoot, `${Date.now()}-${randomUUID7()}`);
|
|
96337
96488
|
const applied = applyTaskToV3MigrationPlan(before.plan, { backupRoot: backupPath });
|
|
96338
96489
|
const after = inspectCurrentTaskPlan().result;
|
|
96339
96490
|
if (after.taskV3Migration.changed > 0) {
|
|
@@ -96389,8 +96540,8 @@ function applyTaskV4Migration() {
|
|
|
96389
96540
|
const before = inspectCurrentTaskV4Plan();
|
|
96390
96541
|
if (before.result.taskV4Migration.changed === 0)
|
|
96391
96542
|
return before.result;
|
|
96392
|
-
const backupRoot =
|
|
96393
|
-
const backupPath =
|
|
96543
|
+
const backupRoot = path65.join(getDataDir(), "backups", "task-v4");
|
|
96544
|
+
const backupPath = path65.join(backupRoot, `${Date.now()}-${randomUUID7()}`);
|
|
96394
96545
|
const applied = applyTaskToV4MigrationPlan(before.plan, { backupRoot: backupPath });
|
|
96395
96546
|
const after = inspectCurrentTaskV4Plan().result;
|
|
96396
96547
|
if (after.taskV4Migration.changed > 0) {
|