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
|
@@ -7042,7 +7042,8 @@ var init_errors = __esm(() => {
|
|
|
7042
7042
|
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.",
|
|
7043
7043
|
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.",
|
|
7044
7044
|
UNKNOWN_IMPROVE_STRATEGY: "Pass one of the listed strategy names to `--strategy`, or define it under `improve.strategies`. Names are case-sensitive.",
|
|
7045
|
-
EXECUTION_NOT_AUTHORIZED: "Change the selected tools or update the machine/user execution policy, then retry."
|
|
7045
|
+
EXECUTION_NOT_AUTHORIZED: "Change the selected tools or update the machine/user execution policy, then retry.",
|
|
7046
|
+
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."
|
|
7046
7047
|
};
|
|
7047
7048
|
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.";
|
|
7048
7049
|
USAGE_HINTS = {
|
|
@@ -7064,7 +7065,8 @@ var init_errors = __esm(() => {
|
|
|
7064
7065
|
INPUT_BINDING_INVALID: "Check the step's with: keys against the target's declared inputs.",
|
|
7065
7066
|
TASK_TARGET_UNSUPPORTED: "Task definitions support command, script, workflow, and shell (run:) targets; akm/command is layered by callers.",
|
|
7066
7067
|
WORKFLOW_IR_VERSION_UNSUPPORTED: "Abandon the run with `akm workflow abandon <id>`, then start it again from the workflow source \u2014 a frozen plan this akm cannot execute is not re-executable in place.",
|
|
7067
|
-
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."
|
|
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
|
+
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."
|
|
7068
7070
|
};
|
|
7069
7071
|
NOT_FOUND_HINTS = {
|
|
7070
7072
|
ASSET_NOT_FOUND: "Run `akm search <query>` or `akm index` to refresh the index.",
|
|
@@ -8388,6 +8390,17 @@ function parseRefInput(raw) {
|
|
|
8388
8390
|
}
|
|
8389
8391
|
return { type: parts.type, name: parts.name, origin: ref.bundle };
|
|
8390
8392
|
}
|
|
8393
|
+
function isFullRefInput(raw) {
|
|
8394
|
+
const trimmed = raw.trim();
|
|
8395
|
+
if (!trimmed)
|
|
8396
|
+
return false;
|
|
8397
|
+
try {
|
|
8398
|
+
const parsed = parseBundleRef(trimmed);
|
|
8399
|
+
return parsed.bundle !== undefined || typeNameFromConceptId(parsed.conceptId) !== undefined;
|
|
8400
|
+
} catch {
|
|
8401
|
+
return false;
|
|
8402
|
+
}
|
|
8403
|
+
}
|
|
8391
8404
|
var init_resolve_ref = __esm(() => {
|
|
8392
8405
|
init_errors();
|
|
8393
8406
|
init_asset_placement();
|
|
@@ -12414,7 +12427,7 @@ function bindStepSections(headings, lines, bodyStartLine, totalLines, path24, de
|
|
|
12414
12427
|
if (!declaredIds.has(h.text)) {
|
|
12415
12428
|
errors3.push({
|
|
12416
12429
|
line: h.line,
|
|
12417
|
-
message: `Unexpected level-2 heading "## ${h.text}" on line ${h.line} \u2014 no step "${h.text}" is declared in frontmatter "steps:". Level-2 headings must exactly match a declared step id.`
|
|
12430
|
+
message: `Unexpected level-2 heading "## ${h.text}" on line ${h.line} \u2014 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.`
|
|
12418
12431
|
});
|
|
12419
12432
|
continue;
|
|
12420
12433
|
}
|
|
@@ -68087,15 +68100,15 @@ ${this.boa_token}${this.audio_token.repeat(this._compute_audio_num_tokens(audio_
|
|
|
68087
68100
|
});
|
|
68088
68101
|
|
|
68089
68102
|
// src/indexer/walk/file-context.ts
|
|
68090
|
-
import
|
|
68091
|
-
import
|
|
68103
|
+
import fs47 from "fs";
|
|
68104
|
+
import path56 from "path";
|
|
68092
68105
|
function buildFileContext(stashRoot, absPath) {
|
|
68093
|
-
const relPath = toPosix(
|
|
68094
|
-
const ext =
|
|
68095
|
-
const fileName =
|
|
68096
|
-
const parentDirAbs =
|
|
68097
|
-
const parentDir =
|
|
68098
|
-
const relDir = toPosix(
|
|
68106
|
+
const relPath = toPosix(path56.relative(stashRoot, absPath));
|
|
68107
|
+
const ext = path56.extname(absPath).toLowerCase();
|
|
68108
|
+
const fileName = path56.basename(absPath);
|
|
68109
|
+
const parentDirAbs = path56.dirname(absPath);
|
|
68110
|
+
const parentDir = path56.basename(parentDirAbs);
|
|
68111
|
+
const relDir = toPosix(path56.dirname(relPath));
|
|
68099
68112
|
const ancestorDirs = relDir === "." ? [] : relDir.split("/").filter((seg) => seg.length > 0);
|
|
68100
68113
|
let cachedContent;
|
|
68101
68114
|
let cachedFrontmatter;
|
|
@@ -68112,7 +68125,7 @@ function buildFileContext(stashRoot, absPath) {
|
|
|
68112
68125
|
stashRoot,
|
|
68113
68126
|
content() {
|
|
68114
68127
|
if (cachedContent === undefined) {
|
|
68115
|
-
cachedContent =
|
|
68128
|
+
cachedContent = fs47.readFileSync(absPath, "utf8");
|
|
68116
68129
|
}
|
|
68117
68130
|
return cachedContent;
|
|
68118
68131
|
},
|
|
@@ -68127,7 +68140,7 @@ function buildFileContext(stashRoot, absPath) {
|
|
|
68127
68140
|
},
|
|
68128
68141
|
stat() {
|
|
68129
68142
|
if (cachedStat === undefined) {
|
|
68130
|
-
cachedStat =
|
|
68143
|
+
cachedStat = fs47.statSync(absPath);
|
|
68131
68144
|
}
|
|
68132
68145
|
return cachedStat;
|
|
68133
68146
|
}
|
|
@@ -70250,6 +70263,7 @@ function formatProposalDrainPlain(r) {
|
|
|
70250
70263
|
const deferred = Array.isArray(r.deferred) ? r.deferred : [];
|
|
70251
70264
|
const skippedByCap = Array.isArray(r.skippedByCap) ? r.skippedByCap : [];
|
|
70252
70265
|
const staged = Array.isArray(r.staged) ? r.staged : [];
|
|
70266
|
+
const failed = Array.isArray(r.failed) ? r.failed : [];
|
|
70253
70267
|
const prefix = r.dryRun === true ? "[dry-run] " : "";
|
|
70254
70268
|
const lines = [
|
|
70255
70269
|
`${prefix}Drained proposal queue (strategy=${String(r.strategy ?? "?")}, policy=${policy}, applyMode=${applyMode})`,
|
|
@@ -70257,11 +70271,15 @@ function formatProposalDrainPlain(r) {
|
|
|
70257
70271
|
` rejected: ${rejected.length}`,
|
|
70258
70272
|
` deferred: ${deferred.length}`,
|
|
70259
70273
|
` skippedByCap: ${skippedByCap.length}`,
|
|
70260
|
-
` staged: ${staged.length}
|
|
70274
|
+
` staged: ${staged.length}`,
|
|
70275
|
+
` failed: ${failed.length}`
|
|
70261
70276
|
];
|
|
70262
70277
|
for (const d of deferred) {
|
|
70263
70278
|
lines.push(` - ${String(d.id ?? "?")} (${String(d.reason ?? "?")})`);
|
|
70264
70279
|
}
|
|
70280
|
+
for (const f of failed) {
|
|
70281
|
+
lines.push(` ! ${String(f.id ?? "?")} (${String(f.reason ?? "?")}): ${String(f.detail ?? "?")}`);
|
|
70282
|
+
}
|
|
70265
70283
|
appendLoweringNotices(lines, r);
|
|
70266
70284
|
return lines.join(`
|
|
70267
70285
|
`).trimEnd();
|
|
@@ -75483,12 +75501,16 @@ var httpUrl = exports_external.string().refine((v) => v.startsWith("http://") ||
|
|
|
75483
75501
|
});
|
|
75484
75502
|
var ENGINE_NAME_PATTERN = new RegExp(ENGINE_NAME_PATTERN_SOURCE);
|
|
75485
75503
|
var ENV_REFERENCE_PATTERN = /^\$[A-Za-z_][A-Za-z0-9_]*$|^\$\{[A-Za-z_][A-Za-z0-9_]*\}$/;
|
|
75504
|
+
var SECRET_STORE_REFERENCE_PATTERN = /^secret:\/\/(.+)$/;
|
|
75486
75505
|
var engineName = exports_external.string().max(63).regex(ENGINE_NAME_PATTERN, "names must be lowercase kebab-case and must not begin with reserved akm-");
|
|
75506
|
+
function isApiKeyReference(value) {
|
|
75507
|
+
return ENV_REFERENCE_PATTERN.test(value) || SECRET_STORE_REFERENCE_PATTERN.test(value);
|
|
75508
|
+
}
|
|
75487
75509
|
function symbolicOrWarnApiKey(label) {
|
|
75488
75510
|
return exports_external.string().superRefine((value) => {
|
|
75489
|
-
if (
|
|
75511
|
+
if (isApiKeyReference(value))
|
|
75490
75512
|
return;
|
|
75491
|
-
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) \u2014 see docs/reference/data-and-telemetry.md.`);
|
|
75513
|
+
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> ...\`) \u2014 see docs/reference/data-and-telemetry.md.`);
|
|
75492
75514
|
});
|
|
75493
75515
|
}
|
|
75494
75516
|
var chatCompletionsEndpoint = exports_external.string().superRefine((value, ctx) => {
|
|
@@ -76656,11 +76678,19 @@ function getSources(config) {
|
|
|
76656
76678
|
function loadConfig() {
|
|
76657
76679
|
return loadUserConfig();
|
|
76658
76680
|
}
|
|
76659
|
-
function resolveSecret(value) {
|
|
76681
|
+
function resolveSecret(value, resolveFromStore) {
|
|
76660
76682
|
if (value === undefined)
|
|
76661
76683
|
return;
|
|
76662
76684
|
if (typeof value !== "string")
|
|
76663
76685
|
return value;
|
|
76686
|
+
const storeRef = SECRET_STORE_REFERENCE_PATTERN.exec(value)?.[1];
|
|
76687
|
+
if (storeRef !== undefined) {
|
|
76688
|
+
const resolved = resolveFromStore?.(storeRef) ?? null;
|
|
76689
|
+
if (resolved === null) {
|
|
76690
|
+
throw new ConfigError(`Secret store reference "${value}" did not resolve to a stored value.`, "SECRET_REFERENCE_UNRESOLVED");
|
|
76691
|
+
}
|
|
76692
|
+
return resolved;
|
|
76693
|
+
}
|
|
76664
76694
|
if (!value.includes("$"))
|
|
76665
76695
|
return value;
|
|
76666
76696
|
return value.replace(/\$\{([A-Za-z_][A-Za-z0-9_]*)\}|\$([A-Za-z_][A-Za-z0-9_]*)/g, (_match, braced, bare) => {
|
|
@@ -78545,9 +78575,9 @@ function listTxnJournalsTolerant(predicate) {
|
|
|
78545
78575
|
|
|
78546
78576
|
// src/commands/proposal/repository.ts
|
|
78547
78577
|
import { createHash as createHash9, randomUUID as randomUUID6 } from "crypto";
|
|
78548
|
-
import
|
|
78578
|
+
import fs49 from "fs";
|
|
78549
78579
|
init_dist();
|
|
78550
|
-
import
|
|
78580
|
+
import path61 from "path";
|
|
78551
78581
|
|
|
78552
78582
|
// src/core/adapter/adapters/agent-skills-adapter.ts
|
|
78553
78583
|
init_frontmatter();
|
|
@@ -92631,8 +92661,8 @@ init_warn();
|
|
|
92631
92661
|
init_write_provenance();
|
|
92632
92662
|
|
|
92633
92663
|
// src/indexer/index-written-assets.ts
|
|
92634
|
-
import
|
|
92635
|
-
import
|
|
92664
|
+
import fs48 from "fs";
|
|
92665
|
+
import path59 from "path";
|
|
92636
92666
|
init_errors();
|
|
92637
92667
|
init_paths();
|
|
92638
92668
|
init_warn();
|
|
@@ -93669,6 +93699,127 @@ function redactSensitiveText(text, sensitiveValues) {
|
|
|
93669
93699
|
|
|
93670
93700
|
// src/llm/embedders/remote.ts
|
|
93671
93701
|
init_warn();
|
|
93702
|
+
|
|
93703
|
+
// src/sources/snapshot-fetchers/secret-seam.ts
|
|
93704
|
+
import fs45 from "fs";
|
|
93705
|
+
|
|
93706
|
+
// src/core/env-secret-ref.ts
|
|
93707
|
+
import fs43 from "fs";
|
|
93708
|
+
import path54 from "path";
|
|
93709
|
+
|
|
93710
|
+
// src/registry/origin-resolve.ts
|
|
93711
|
+
init_asset_ref();
|
|
93712
|
+
function resolveSourcesForOrigin(origin, allSources) {
|
|
93713
|
+
if (!origin)
|
|
93714
|
+
return allSources;
|
|
93715
|
+
const installations = deriveInstallations(allSources);
|
|
93716
|
+
return allSources.filter((_, index) => installations[index]?.id === origin);
|
|
93717
|
+
}
|
|
93718
|
+
|
|
93719
|
+
// src/core/asset/asset-create.ts
|
|
93720
|
+
init_errors();
|
|
93721
|
+
function normalizeCreateSubPath(subPath) {
|
|
93722
|
+
if (subPath === undefined)
|
|
93723
|
+
return "";
|
|
93724
|
+
const trimmed = subPath.trim().replace(/\\/g, "/").replace(/^\/+|\/+$/g, "");
|
|
93725
|
+
if (!trimmed)
|
|
93726
|
+
return "";
|
|
93727
|
+
if (trimmed.split("/").some((segment) => !segment || segment === "." || segment === "..")) {
|
|
93728
|
+
throw new UsageError("--path must be a relative directory without '.' or '..' segments.");
|
|
93729
|
+
}
|
|
93730
|
+
return trimmed;
|
|
93731
|
+
}
|
|
93732
|
+
function assertFlatAssetName(name) {
|
|
93733
|
+
if (name?.replace(/\\/g, "/").replace(/\.md$/i, "").includes("/")) {
|
|
93734
|
+
throw new UsageError("Asset --name must be a flat name without '/'. Use --path to choose a subdirectory " + "(e.g. --path personal --name grocery-list).");
|
|
93735
|
+
}
|
|
93736
|
+
}
|
|
93737
|
+
function combineCreatePath(subPath, baseName) {
|
|
93738
|
+
return subPath ? `${subPath}/${baseName}` : baseName;
|
|
93739
|
+
}
|
|
93740
|
+
|
|
93741
|
+
// src/core/env-secret-ref.ts
|
|
93742
|
+
init_asset_placement();
|
|
93743
|
+
init_resolve_ref();
|
|
93744
|
+
init_common();
|
|
93745
|
+
init_errors();
|
|
93746
|
+
function assertNotRemovedVaultRef(ref) {
|
|
93747
|
+
const boundary = ref.indexOf("//");
|
|
93748
|
+
const bare = boundary >= 0 ? ref.slice(boundary + 2) : ref;
|
|
93749
|
+
if (/^vault[:/]/.test(bare.trim())) {
|
|
93750
|
+
throw new UsageError("The `vault` asset type was removed in 0.9.0 \u2014 use `env/` (whole .env config) or `secrets/` (a single value).", "INVALID_FLAG_VALUE");
|
|
93751
|
+
}
|
|
93752
|
+
}
|
|
93753
|
+
function assertNotColonRef(ref, aliases, replacement) {
|
|
93754
|
+
const boundary = ref.indexOf("//");
|
|
93755
|
+
const bare = (boundary >= 0 ? ref.slice(boundary + 2) : ref).trim();
|
|
93756
|
+
const colon = bare.indexOf(":");
|
|
93757
|
+
if (colon <= 0)
|
|
93758
|
+
return;
|
|
93759
|
+
const head = bare.slice(0, colon).toLowerCase();
|
|
93760
|
+
if (!aliases.includes(head))
|
|
93761
|
+
return;
|
|
93762
|
+
const name = bare.slice(colon + 1);
|
|
93763
|
+
throw new UsageError(`The \`${head}:\` ref spelling was removed in 0.9.0 \u2014 use the slash form instead: \`${replacement}${name}\`.`, "INVALID_FLAG_VALUE");
|
|
93764
|
+
}
|
|
93765
|
+
function findEnvSource(origin, type, name) {
|
|
93766
|
+
const sources = resolveSourceEntries(undefined, loadConfig());
|
|
93767
|
+
if (sources.length === 0) {
|
|
93768
|
+
throw new UsageError("No bundles configured. Run `akm bundle create` to create your working bundle.");
|
|
93769
|
+
}
|
|
93770
|
+
const candidates = origin ? resolveSourcesForOrigin(origin, sources) : sources;
|
|
93771
|
+
const typeDir = type === "env" ? "env" : "secrets";
|
|
93772
|
+
const member = candidates.find((source) => fs43.existsSync(assetPathForName(type, path54.join(source.path, typeDir), name)));
|
|
93773
|
+
if (member)
|
|
93774
|
+
return member;
|
|
93775
|
+
if (!origin) {
|
|
93776
|
+
const fallback = candidates[0];
|
|
93777
|
+
if (fallback)
|
|
93778
|
+
return fallback;
|
|
93779
|
+
throw new UsageError("No bundles configured. Run `akm bundle create` to create your working bundle.");
|
|
93780
|
+
}
|
|
93781
|
+
const named = candidates[0];
|
|
93782
|
+
if (!named) {
|
|
93783
|
+
throw new NotFoundError(`Source not found for origin: ${origin}`);
|
|
93784
|
+
}
|
|
93785
|
+
return named;
|
|
93786
|
+
}
|
|
93787
|
+
function parseSecretRef(ref) {
|
|
93788
|
+
assertNotRemovedVaultRef(ref);
|
|
93789
|
+
assertNotColonRef(ref, ["secret", "secrets"], "secrets/");
|
|
93790
|
+
return parseRefInput(isFullRefInput(ref) ? ref : `secrets/${ref}`);
|
|
93791
|
+
}
|
|
93792
|
+
function resolveSecretPath(ref, create) {
|
|
93793
|
+
const parsed = parseSecretRef(ref);
|
|
93794
|
+
if (parsed.type !== "secret") {
|
|
93795
|
+
throw new UsageError(`Expected a secret ref (secrets/<name>); got "${ref}".`);
|
|
93796
|
+
}
|
|
93797
|
+
if (create) {
|
|
93798
|
+
assertFlatAssetName(parsed.name);
|
|
93799
|
+
parsed.name = combineCreatePath(normalizeCreateSubPath(create.subPath), parsed.name);
|
|
93800
|
+
}
|
|
93801
|
+
const source = findEnvSource(parsed.origin, "secret", parsed.name);
|
|
93802
|
+
const typeRoot = path54.join(source.path, "secrets");
|
|
93803
|
+
const absPath = assetPathForName("secret", typeRoot, parsed.name);
|
|
93804
|
+
if (!isWithin(absPath, typeRoot)) {
|
|
93805
|
+
throw new UsageError(`Secret name "${parsed.name}" escapes the secrets directory.`);
|
|
93806
|
+
}
|
|
93807
|
+
return { name: parsed.name, absPath, source };
|
|
93808
|
+
}
|
|
93809
|
+
|
|
93810
|
+
// src/sources/snapshot-fetchers/secret-seam.ts
|
|
93811
|
+
function resolveSecretFromStore(ref) {
|
|
93812
|
+
try {
|
|
93813
|
+
const { absPath } = resolveSecretPath(ref);
|
|
93814
|
+
if (!fs45.existsSync(absPath))
|
|
93815
|
+
return null;
|
|
93816
|
+
return fs45.readFileSync(absPath, "utf8").trim() || null;
|
|
93817
|
+
} catch {
|
|
93818
|
+
return null;
|
|
93819
|
+
}
|
|
93820
|
+
}
|
|
93821
|
+
|
|
93822
|
+
// src/llm/embedders/remote.ts
|
|
93672
93823
|
var DEFAULT_REMOTE_BATCH_SIZE = 100;
|
|
93673
93824
|
var DEFAULT_TOKEN_BUDGET = 8000;
|
|
93674
93825
|
function estimateTokenCount(text) {
|
|
@@ -93824,14 +93975,14 @@ class RemoteEmbedder {
|
|
|
93824
93975
|
}
|
|
93825
93976
|
buildHeaders() {
|
|
93826
93977
|
const headers = { "Content-Type": "application/json" };
|
|
93827
|
-
const resolvedKey = resolveSecret(this.config.apiKey);
|
|
93978
|
+
const resolvedKey = resolveSecret(this.config.apiKey, resolveSecretFromStore);
|
|
93828
93979
|
if (resolvedKey) {
|
|
93829
93980
|
headers.Authorization = `Bearer ${resolvedKey}`;
|
|
93830
93981
|
}
|
|
93831
93982
|
return headers;
|
|
93832
93983
|
}
|
|
93833
93984
|
safeErrorBody(body) {
|
|
93834
|
-
const resolvedKey = resolveSecret(this.config.apiKey);
|
|
93985
|
+
const resolvedKey = resolveSecret(this.config.apiKey, resolveSecretFromStore);
|
|
93835
93986
|
return redactSensitiveText(redactErrorBody(body), resolvedKey ? [resolvedKey] : []);
|
|
93836
93987
|
}
|
|
93837
93988
|
}
|
|
@@ -94067,7 +94218,7 @@ function publishTargetedEmbeddingMeta(db, config) {
|
|
|
94067
94218
|
}
|
|
94068
94219
|
|
|
94069
94220
|
// src/indexer/scan/drain-dir.ts
|
|
94070
|
-
import
|
|
94221
|
+
import path58 from "path";
|
|
94071
94222
|
init_common();
|
|
94072
94223
|
init_recognition_util();
|
|
94073
94224
|
|
|
@@ -94076,8 +94227,8 @@ init_common();
|
|
|
94076
94227
|
init_errors();
|
|
94077
94228
|
init_recognition_util();
|
|
94078
94229
|
init_warn();
|
|
94079
|
-
import
|
|
94080
|
-
import
|
|
94230
|
+
import fs46 from "fs";
|
|
94231
|
+
import path55 from "path";
|
|
94081
94232
|
|
|
94082
94233
|
class WorkflowSourceRejectionError extends UsageError {
|
|
94083
94234
|
sourcePaths;
|
|
@@ -94117,13 +94268,13 @@ class WorkflowSourcePathIdentityError extends WorkflowSourceRejectionError {
|
|
|
94117
94268
|
function workflowNameForSourcePath(sourceRoot, adapterId, sourcePath) {
|
|
94118
94269
|
if (adapterId !== "akm" && adapterId !== "akm-workflow")
|
|
94119
94270
|
return;
|
|
94120
|
-
const relativePath = toPosix(
|
|
94271
|
+
const relativePath = toPosix(path55.relative(path55.resolve(sourceRoot), path55.resolve(sourcePath)));
|
|
94121
94272
|
if (!isSafeRelativeName(relativePath))
|
|
94122
94273
|
return;
|
|
94123
94274
|
const ownedPath = adapterId === "akm" ? relativePath.replace(/^workflows\//, "") : relativePath;
|
|
94124
94275
|
if (adapterId === "akm" && ownedPath === relativePath)
|
|
94125
94276
|
return;
|
|
94126
|
-
const extension =
|
|
94277
|
+
const extension = path55.posix.extname(ownedPath);
|
|
94127
94278
|
if (!WORKFLOW_EXTENSIONS.includes(extension.toLowerCase()))
|
|
94128
94279
|
return;
|
|
94129
94280
|
return ownedPath;
|
|
@@ -94136,38 +94287,38 @@ function listWorkflowSourceFiles(sourceRoot, adapterId, name) {
|
|
|
94136
94287
|
throw new UsageError("Workflow ref resolves outside the bundle root.", "PATH_ESCAPE_VIOLATION");
|
|
94137
94288
|
}
|
|
94138
94289
|
let realRoot;
|
|
94139
|
-
const authoredRoot =
|
|
94290
|
+
const authoredRoot = path55.resolve(sourceRoot);
|
|
94140
94291
|
try {
|
|
94141
|
-
realRoot =
|
|
94292
|
+
realRoot = fs46.realpathSync(authoredRoot);
|
|
94142
94293
|
} catch {
|
|
94143
94294
|
return [];
|
|
94144
94295
|
}
|
|
94145
|
-
const ownershipRoot = adapterId === "akm" ?
|
|
94146
|
-
const parent =
|
|
94296
|
+
const ownershipRoot = adapterId === "akm" ? path55.join(authoredRoot, "workflows") : authoredRoot;
|
|
94297
|
+
const parent = path55.join(ownershipRoot, path55.dirname(canonicalName));
|
|
94147
94298
|
if (!isWithinResolved(parent, authoredRoot)) {
|
|
94148
94299
|
throw new UsageError("Workflow ref resolves outside the bundle root.", "PATH_ESCAPE_VIOLATION");
|
|
94149
94300
|
}
|
|
94150
94301
|
let entries;
|
|
94151
94302
|
try {
|
|
94152
|
-
entries =
|
|
94303
|
+
entries = fs46.readdirSync(parent, { withFileTypes: true });
|
|
94153
94304
|
} catch {
|
|
94154
94305
|
return [];
|
|
94155
94306
|
}
|
|
94156
|
-
const basename =
|
|
94307
|
+
const basename = path55.basename(canonicalName);
|
|
94157
94308
|
const candidates = [];
|
|
94158
94309
|
for (const entry of entries) {
|
|
94159
94310
|
if (!entry.isFile() && !entry.isSymbolicLink())
|
|
94160
94311
|
continue;
|
|
94161
|
-
const extension =
|
|
94312
|
+
const extension = path55.extname(entry.name);
|
|
94162
94313
|
const lowerExtension = extension.toLowerCase();
|
|
94163
94314
|
if (!WORKFLOW_EXTENSIONS.includes(lowerExtension))
|
|
94164
94315
|
continue;
|
|
94165
94316
|
if (entry.name.slice(0, -extension.length) !== basename)
|
|
94166
94317
|
continue;
|
|
94167
|
-
const candidatePath =
|
|
94318
|
+
const candidatePath = path55.join(parent, entry.name);
|
|
94168
94319
|
candidates.push({
|
|
94169
94320
|
path: candidatePath,
|
|
94170
|
-
relativePath: toPosix(
|
|
94321
|
+
relativePath: toPosix(path55.relative(authoredRoot, candidatePath)),
|
|
94171
94322
|
lowerExtension,
|
|
94172
94323
|
extensionlessStem: entry.name.slice(0, -extension.length)
|
|
94173
94324
|
});
|
|
@@ -94202,7 +94353,7 @@ function inspectWorkflowSourceCandidate(candidate, canonicalName, realRoot) {
|
|
|
94202
94353
|
const issues = [];
|
|
94203
94354
|
let authoredStat;
|
|
94204
94355
|
try {
|
|
94205
|
-
authoredStat =
|
|
94356
|
+
authoredStat = fs46.lstatSync(candidate.path);
|
|
94206
94357
|
} catch {
|
|
94207
94358
|
issues.push(new WorkflowSourceLinkResolutionError(candidate.relativePath));
|
|
94208
94359
|
return { issues };
|
|
@@ -94214,21 +94365,21 @@ function inspectWorkflowSourceCandidate(candidate, canonicalName, realRoot) {
|
|
|
94214
94365
|
}
|
|
94215
94366
|
let realPath;
|
|
94216
94367
|
try {
|
|
94217
|
-
realPath =
|
|
94368
|
+
realPath = fs46.realpathSync(candidate.path);
|
|
94218
94369
|
} catch {
|
|
94219
94370
|
issues.push(new WorkflowSourceLinkResolutionError(candidate.relativePath));
|
|
94220
94371
|
return { issues };
|
|
94221
94372
|
}
|
|
94222
|
-
const targetPath = toPosix(
|
|
94373
|
+
const targetPath = toPosix(path55.relative(realRoot, realPath));
|
|
94223
94374
|
const contained2 = isWithinResolved(realPath, realRoot);
|
|
94224
94375
|
if (!contained2)
|
|
94225
94376
|
issues.push(new WorkflowSourcePathIdentityError(candidate.relativePath, targetPath));
|
|
94226
|
-
if (isLink &&
|
|
94377
|
+
if (isLink && path55.extname(realPath).toLowerCase() !== candidate.lowerExtension) {
|
|
94227
94378
|
issues.push(new WorkflowSourceLinkIdentityError(candidate.relativePath, targetPath));
|
|
94228
94379
|
}
|
|
94229
94380
|
if (contained2) {
|
|
94230
94381
|
try {
|
|
94231
|
-
if (!
|
|
94382
|
+
if (!fs46.statSync(realPath).isFile())
|
|
94232
94383
|
issues.push(new WorkflowSourceLinkResolutionError(candidate.relativePath));
|
|
94233
94384
|
} catch {
|
|
94234
94385
|
issues.push(new WorkflowSourceLinkResolutionError(candidate.relativePath));
|
|
@@ -94256,11 +94407,11 @@ function normalizeName2(name) {
|
|
|
94256
94407
|
return name.replaceAll("\\", "/");
|
|
94257
94408
|
}
|
|
94258
94409
|
function isSafeRelativeName(name) {
|
|
94259
|
-
return name.length > 0 && !
|
|
94410
|
+
return name.length > 0 && !path55.posix.isAbsolute(name) && name !== ".." && !name.startsWith("../") && path55.posix.normalize(name) === name;
|
|
94260
94411
|
}
|
|
94261
94412
|
function isWithinResolved(candidate, root2) {
|
|
94262
|
-
const relative =
|
|
94263
|
-
return relative === "" || !relative.startsWith("..") && !
|
|
94413
|
+
const relative = path55.relative(root2, path55.resolve(candidate));
|
|
94414
|
+
return relative === "" || !relative.startsWith("..") && !path55.isAbsolute(relative);
|
|
94264
94415
|
}
|
|
94265
94416
|
|
|
94266
94417
|
// src/indexer/scan/drain-dir.ts
|
|
@@ -94269,13 +94420,13 @@ init_metadata();
|
|
|
94269
94420
|
init_file_context();
|
|
94270
94421
|
|
|
94271
94422
|
// src/indexer/scan/doc-to-entry.ts
|
|
94272
|
-
import
|
|
94423
|
+
import path57 from "path";
|
|
94273
94424
|
function indexDocumentToStashEntry(doc) {
|
|
94274
94425
|
const dj = doc.documentJson ?? {};
|
|
94275
94426
|
const entry = {
|
|
94276
94427
|
name: doc.name,
|
|
94277
94428
|
type: doc.type,
|
|
94278
|
-
filename:
|
|
94429
|
+
filename: path57.basename(doc.path ?? "")
|
|
94279
94430
|
};
|
|
94280
94431
|
if (doc.description !== undefined)
|
|
94281
94432
|
entry.description = doc.description;
|
|
@@ -94395,7 +94546,7 @@ function drainDirDocuments(adapter, component, fileContexts) {
|
|
|
94395
94546
|
throw error2;
|
|
94396
94547
|
rejectedConceptIds.add(adapter.id === "akm" ? `workflows/${canonicalName}` : canonicalName);
|
|
94397
94548
|
for (const relativePath of error2.sourcePaths) {
|
|
94398
|
-
rejectedPaths.add(
|
|
94549
|
+
rejectedPaths.add(path58.join(component.root, relativePath));
|
|
94399
94550
|
}
|
|
94400
94551
|
warnings.push(error2.message);
|
|
94401
94552
|
}
|
|
@@ -94457,7 +94608,7 @@ async function indexWrittenAssets(stashDir, filePaths, options = {}) {
|
|
|
94457
94608
|
if (isPathAbsent(dbPath))
|
|
94458
94609
|
return true;
|
|
94459
94610
|
const files = filePaths.filter((f) => {
|
|
94460
|
-
const rel =
|
|
94611
|
+
const rel = path59.relative(stashDir, f);
|
|
94461
94612
|
return !rel.split(/[\\/]+/).some((segment) => segment.startsWith("."));
|
|
94462
94613
|
});
|
|
94463
94614
|
if (files.length === 0)
|
|
@@ -94471,10 +94622,10 @@ async function indexWrittenAssets(stashDir, filePaths, options = {}) {
|
|
|
94471
94622
|
const unindexable = new Set;
|
|
94472
94623
|
const rejectedConceptIds = new Set;
|
|
94473
94624
|
for (const file of files) {
|
|
94474
|
-
if (!
|
|
94625
|
+
if (!fs48.existsSync(file)) {
|
|
94475
94626
|
let authoredDanglingSymlink = false;
|
|
94476
94627
|
try {
|
|
94477
|
-
authoredDanglingSymlink =
|
|
94628
|
+
authoredDanglingSymlink = fs48.lstatSync(file).isSymbolicLink();
|
|
94478
94629
|
} catch {}
|
|
94479
94630
|
if (!authoredDanglingSymlink) {
|
|
94480
94631
|
unindexable.add(file);
|
|
@@ -94525,7 +94676,7 @@ async function indexWrittenAssets(stashDir, filePaths, options = {}) {
|
|
|
94525
94676
|
for (const { file, entry, conceptId, contentHash } of pairs) {
|
|
94526
94677
|
let entryWithSize = entry;
|
|
94527
94678
|
try {
|
|
94528
|
-
entryWithSize = { ...entry, fileSize:
|
|
94679
|
+
entryWithSize = { ...entry, fileSize: fs48.statSync(file).size };
|
|
94529
94680
|
} catch {}
|
|
94530
94681
|
const provenance = deriveEntryProvenance({ bundleId: component.id, componentId: component.id, adapterId: component.adapter }, entry.type, entry.name, conceptId);
|
|
94531
94682
|
const supersededIds = db.prepare("SELECT id FROM entries WHERE file_path = ? AND item_ref <> ?").all(file, provenance.itemRef);
|
|
@@ -94558,7 +94709,7 @@ async function indexWrittenAssets(stashDir, filePaths, options = {}) {
|
|
|
94558
94709
|
init_asset_placement();
|
|
94559
94710
|
init_asset_ref();
|
|
94560
94711
|
init_warn();
|
|
94561
|
-
import
|
|
94712
|
+
import path60 from "path";
|
|
94562
94713
|
function changesToStored(changes) {
|
|
94563
94714
|
return changes.map((c, i) => ({
|
|
94564
94715
|
path: c.path,
|
|
@@ -94611,10 +94762,10 @@ function currentProposalTarget(value) {
|
|
|
94611
94762
|
if (typeof value !== "object" || value === null)
|
|
94612
94763
|
throw new Error("Proposal metadata has an invalid proposedTarget.");
|
|
94613
94764
|
const target = value;
|
|
94614
|
-
if (typeof target.source !== "string" || !isBundleSlug(target.source) || typeof target.root !== "string" || !
|
|
94765
|
+
if (typeof target.source !== "string" || !isBundleSlug(target.source) || typeof target.root !== "string" || !path60.isAbsolute(target.root)) {
|
|
94615
94766
|
throw new Error("Proposal metadata has an invalid proposedTarget.");
|
|
94616
94767
|
}
|
|
94617
|
-
return { source: target.source, root:
|
|
94768
|
+
return { source: target.source, root: path60.resolve(target.root) };
|
|
94618
94769
|
}
|
|
94619
94770
|
function invalidPresentField(name) {
|
|
94620
94771
|
throw new Error(`Proposal metadata has an invalid ${name}.`);
|
|
@@ -94654,7 +94805,7 @@ function validatePresentMetadata(meta) {
|
|
|
94654
94805
|
}
|
|
94655
94806
|
if (Object.hasOwn(meta, "acceptedTarget")) {
|
|
94656
94807
|
const target = meta.acceptedTarget;
|
|
94657
|
-
if (typeof target !== "object" || target === null || typeof target.source !== "string" || !isBundleSlug(target.source) || typeof target.root !== "string" || !
|
|
94808
|
+
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") {
|
|
94658
94809
|
invalidPresentField("acceptedTarget");
|
|
94659
94810
|
}
|
|
94660
94811
|
}
|
|
@@ -95388,12 +95539,12 @@ function proposalHash(content) {
|
|
|
95388
95539
|
return createHash9("sha256").update(content).digest("hex");
|
|
95389
95540
|
}
|
|
95390
95541
|
function proposalFileHash(filePath) {
|
|
95391
|
-
return proposalHash(
|
|
95542
|
+
return proposalHash(fs49.readFileSync(filePath));
|
|
95392
95543
|
}
|
|
95393
95544
|
function sameProposalFile(left, right) {
|
|
95394
95545
|
try {
|
|
95395
|
-
const leftStat =
|
|
95396
|
-
const rightStat =
|
|
95546
|
+
const leftStat = fs49.statSync(left);
|
|
95547
|
+
const rightStat = fs49.statSync(right);
|
|
95397
95548
|
return leftStat.dev === rightStat.dev && leftStat.ino === rightStat.ino;
|
|
95398
95549
|
} catch {
|
|
95399
95550
|
return false;
|
|
@@ -95402,20 +95553,20 @@ function sameProposalFile(left, right) {
|
|
|
95402
95553
|
function cleanupProposalPublication(p) {
|
|
95403
95554
|
for (const filePath of [p.publishPath, p.displacedPath]) {
|
|
95404
95555
|
try {
|
|
95405
|
-
|
|
95556
|
+
fs49.rmSync(filePath, { force: true });
|
|
95406
95557
|
} catch (error2) {
|
|
95407
95558
|
warn(`[proposals] transaction publication cleanup failed at ${filePath}: ${error2 instanceof Error ? error2.message : String(error2)}`);
|
|
95408
95559
|
}
|
|
95409
95560
|
}
|
|
95410
|
-
fsyncTxnDir(
|
|
95561
|
+
fsyncTxnDir(path61.dirname(p.assetPath));
|
|
95411
95562
|
}
|
|
95412
95563
|
function rollbackPreparedProposalTransaction(txn) {
|
|
95413
95564
|
const p = txn.journal.payload;
|
|
95414
|
-
const currentHash =
|
|
95415
|
-
if (!
|
|
95565
|
+
const currentHash = fs49.existsSync(p.assetPath) ? proposalFileHash(p.assetPath) : null;
|
|
95566
|
+
if (!fs49.existsSync(p.displacedPath)) {
|
|
95416
95567
|
if (p.originalHash === null) {
|
|
95417
95568
|
if (currentHash === p.publishedHash && sameProposalFile(p.assetPath, p.publishPath)) {
|
|
95418
|
-
|
|
95569
|
+
fs49.unlinkSync(p.assetPath);
|
|
95419
95570
|
recordWrittenPath(p.assetPath);
|
|
95420
95571
|
} else if (currentHash !== null) {
|
|
95421
95572
|
throw new Error(`Cannot roll back proposal transaction: target was created externally.`);
|
|
@@ -95427,30 +95578,30 @@ function rollbackPreparedProposalTransaction(txn) {
|
|
|
95427
95578
|
return;
|
|
95428
95579
|
}
|
|
95429
95580
|
if (currentHash === p.publishedHash) {
|
|
95430
|
-
|
|
95581
|
+
fs49.unlinkSync(p.assetPath);
|
|
95431
95582
|
recordWrittenPath(p.assetPath);
|
|
95432
95583
|
} else if (currentHash !== null && currentHash !== p.originalHash) {
|
|
95433
95584
|
throw new Error(`Cannot roll back proposal transaction: ${p.assetPath} diverged.`);
|
|
95434
95585
|
}
|
|
95435
|
-
if (
|
|
95436
|
-
if (
|
|
95586
|
+
if (fs49.existsSync(p.displacedPath)) {
|
|
95587
|
+
if (fs49.existsSync(p.assetPath)) {
|
|
95437
95588
|
throw new Error(`Cannot restore proposal backup: ${p.assetPath} is occupied.`);
|
|
95438
95589
|
}
|
|
95439
|
-
|
|
95590
|
+
fs49.linkSync(p.displacedPath, p.assetPath);
|
|
95440
95591
|
recordWrittenPath(p.assetPath);
|
|
95441
95592
|
}
|
|
95442
95593
|
cleanupProposalPublication(p);
|
|
95443
95594
|
}
|
|
95444
95595
|
function validatePublishedProposal(p) {
|
|
95445
|
-
if (!
|
|
95596
|
+
if (!fs49.existsSync(p.assetPath) || proposalFileHash(p.assetPath) !== p.publishedHash) {
|
|
95446
95597
|
throw new Error(`Cannot recover proposal ${p.proposalId}: published asset diverged.`);
|
|
95447
95598
|
}
|
|
95448
95599
|
}
|
|
95449
95600
|
function persistProposalTransactionState(txn, proposal, ctx) {
|
|
95450
95601
|
const p = txn.journal.payload;
|
|
95451
95602
|
const decidedAt = txn.journal.decidedAt;
|
|
95452
|
-
const backupContent = p.backupPath ?
|
|
95453
|
-
const publishedContent =
|
|
95603
|
+
const backupContent = p.backupPath ? fs49.readFileSync(p.backupPath, "utf8") : undefined;
|
|
95604
|
+
const publishedContent = fs49.readFileSync(p.contentPath, "utf8");
|
|
95454
95605
|
return withProposalsDb(p.stashDir, ctx, (db) => withImmediateTransaction(db, () => {
|
|
95455
95606
|
const current = requireProposal(db, p.stashDir, p.proposalId);
|
|
95456
95607
|
if (p.operation === "accept") {
|
|
@@ -95468,7 +95619,7 @@ function persistProposalTransactionState(txn, proposal, ctx) {
|
|
|
95468
95619
|
payload: { ...proposal.payload, content: publishedContent },
|
|
95469
95620
|
changes: [
|
|
95470
95621
|
{
|
|
95471
|
-
path:
|
|
95622
|
+
path: path61.relative(txn.journal.root, p.assetPath),
|
|
95472
95623
|
op: p.originalHash === null ? "create" : "update",
|
|
95473
95624
|
after: publishedContent
|
|
95474
95625
|
}
|
|
@@ -95539,7 +95690,7 @@ async function finalizeProposalTransaction(txn, target, proposal, ctx) {
|
|
|
95539
95690
|
cleanupProposalPublication(p);
|
|
95540
95691
|
if (txn.journal.phase === "asset-published") {
|
|
95541
95692
|
const commitRoot = target.source.repoPath ?? target.source.path;
|
|
95542
|
-
const commitPath =
|
|
95693
|
+
const commitPath = path61.relative(commitRoot, p.assetPath).replaceAll(path61.sep, "/");
|
|
95543
95694
|
publishWriteTargetTransaction(target, p.gitPublication, {
|
|
95544
95695
|
transactionId: txn.journal.transactionId,
|
|
95545
95696
|
message: `${p.operation === "accept" ? "Update" : "Revert"} ${p.ref}`,
|
|
@@ -95576,8 +95727,8 @@ async function finalizeProposalTransaction(txn, target, proposal, ctx) {
|
|
|
95576
95727
|
function fenceProposalTxnJournal(journal, txnDir, root2) {
|
|
95577
95728
|
const p = journal.payload;
|
|
95578
95729
|
const refIdentity = proposalRefIdentity(p.ref);
|
|
95579
|
-
if (!["accept", "revert"].includes(p.operation) || !p.targetSource || !p.targetKind || refIdentity?.bundle === undefined || !isWithin(p.assetPath, root2) || ![p.contentPath, p.backupPath].filter((candidate) => candidate !== null).every((candidate) => isWithin(candidate, txnDir)) || ![p.publishPath, p.displacedPath].every((candidate) => isWithin(candidate, root2) &&
|
|
95580
|
-
throw new Error(`Refusing unsafe proposal transaction journal at ${
|
|
95730
|
+
if (!["accept", "revert"].includes(p.operation) || !p.targetSource || !p.targetKind || refIdentity?.bundle === undefined || !isWithin(p.assetPath, root2) || ![p.contentPath, p.backupPath].filter((candidate) => candidate !== null).every((candidate) => isWithin(candidate, txnDir)) || ![p.publishPath, p.displacedPath].every((candidate) => isWithin(candidate, root2) && path61.dirname(candidate) === path61.dirname(p.assetPath))) {
|
|
95731
|
+
throw new Error(`Refusing unsafe proposal transaction journal at ${path61.join(txnDir, "journal.json")}.`);
|
|
95581
95732
|
}
|
|
95582
95733
|
}
|
|
95583
95734
|
function resolveProposalRecoveryTarget(config, journal) {
|
|
@@ -95677,8 +95828,8 @@ async function recoverStaleTxns(stashDir) {
|
|
|
95677
95828
|
}
|
|
95678
95829
|
|
|
95679
95830
|
// scripts/akm-migrate/migrate/writer-relocation.ts
|
|
95680
|
-
import
|
|
95681
|
-
import
|
|
95831
|
+
import fs50 from "fs";
|
|
95832
|
+
import path62 from "path";
|
|
95682
95833
|
init_paths();
|
|
95683
95834
|
function relocationSpecs(stashDir) {
|
|
95684
95835
|
return [
|
|
@@ -95698,7 +95849,7 @@ function mutexSiblingName(lockName) {
|
|
|
95698
95849
|
function fileCountIfExists(dir) {
|
|
95699
95850
|
let entries;
|
|
95700
95851
|
try {
|
|
95701
|
-
entries =
|
|
95852
|
+
entries = fs50.readdirSync(dir, { withFileTypes: true });
|
|
95702
95853
|
} catch {
|
|
95703
95854
|
return;
|
|
95704
95855
|
}
|
|
@@ -95706,7 +95857,7 @@ function fileCountIfExists(dir) {
|
|
|
95706
95857
|
}
|
|
95707
95858
|
function statFileIfExists(filePath) {
|
|
95708
95859
|
try {
|
|
95709
|
-
const stat =
|
|
95860
|
+
const stat = fs50.statSync(filePath);
|
|
95710
95861
|
return stat.isFile() ? stat : undefined;
|
|
95711
95862
|
} catch {
|
|
95712
95863
|
return;
|
|
@@ -95716,8 +95867,8 @@ function classifyLockArtifacts(akmDir) {
|
|
|
95716
95867
|
const removable = [];
|
|
95717
95868
|
const skipped = [];
|
|
95718
95869
|
for (const lockName of LOCK_NAMES) {
|
|
95719
|
-
const lockPath =
|
|
95720
|
-
const mutexPath =
|
|
95870
|
+
const lockPath = path62.join(akmDir, lockName);
|
|
95871
|
+
const mutexPath = path62.join(akmDir, mutexSiblingName(lockName));
|
|
95721
95872
|
const lockStat = statFileIfExists(lockPath);
|
|
95722
95873
|
const mutexStat = statFileIfExists(mutexPath);
|
|
95723
95874
|
if (!lockStat) {
|
|
@@ -95743,11 +95894,11 @@ function classifyLockArtifacts(akmDir) {
|
|
|
95743
95894
|
return { removable, skipped };
|
|
95744
95895
|
}
|
|
95745
95896
|
function findWriterRelocationEntries(stashDir) {
|
|
95746
|
-
const akmDir =
|
|
95897
|
+
const akmDir = path62.join(stashDir, ".akm");
|
|
95747
95898
|
const directories = [];
|
|
95748
95899
|
for (const spec of relocationSpecs(stashDir)) {
|
|
95749
95900
|
const relativeParts = Array.isArray(spec.oldRelative) ? spec.oldRelative : [spec.oldRelative];
|
|
95750
|
-
const oldPath =
|
|
95901
|
+
const oldPath = path62.join(akmDir, ...relativeParts);
|
|
95751
95902
|
const fileCount = fileCountIfExists(oldPath);
|
|
95752
95903
|
if (fileCount === undefined || fileCount === 0)
|
|
95753
95904
|
continue;
|
|
@@ -95758,36 +95909,36 @@ function findWriterRelocationEntries(stashDir) {
|
|
|
95758
95909
|
}
|
|
95759
95910
|
function moveFile(oldFilePath, newFilePath) {
|
|
95760
95911
|
try {
|
|
95761
|
-
|
|
95912
|
+
fs50.renameSync(oldFilePath, newFilePath);
|
|
95762
95913
|
} catch (error2) {
|
|
95763
95914
|
if (error2.code !== "EXDEV")
|
|
95764
95915
|
throw error2;
|
|
95765
|
-
|
|
95766
|
-
|
|
95916
|
+
fs50.copyFileSync(oldFilePath, newFilePath);
|
|
95917
|
+
fs50.rmSync(oldFilePath, { force: true });
|
|
95767
95918
|
}
|
|
95768
95919
|
}
|
|
95769
95920
|
function moveDirectoryContents(entry) {
|
|
95770
95921
|
const errors3 = [];
|
|
95771
95922
|
let moved = 0;
|
|
95772
|
-
|
|
95923
|
+
fs50.mkdirSync(entry.newPath, { recursive: true });
|
|
95773
95924
|
let names;
|
|
95774
95925
|
try {
|
|
95775
|
-
names =
|
|
95926
|
+
names = fs50.readdirSync(entry.oldPath).sort();
|
|
95776
95927
|
} catch {
|
|
95777
95928
|
return { key: entry.key, oldPath: entry.oldPath, newPath: entry.newPath, moved: 0, errors: [] };
|
|
95778
95929
|
}
|
|
95779
95930
|
for (const name of names) {
|
|
95780
|
-
const oldFilePath =
|
|
95781
|
-
const newFilePath =
|
|
95931
|
+
const oldFilePath = path62.join(entry.oldPath, name);
|
|
95932
|
+
const newFilePath = path62.join(entry.newPath, name);
|
|
95782
95933
|
let oldStat;
|
|
95783
95934
|
try {
|
|
95784
|
-
oldStat =
|
|
95935
|
+
oldStat = fs50.lstatSync(oldFilePath);
|
|
95785
95936
|
} catch {
|
|
95786
95937
|
continue;
|
|
95787
95938
|
}
|
|
95788
95939
|
if (!oldStat.isFile())
|
|
95789
95940
|
continue;
|
|
95790
|
-
if (
|
|
95941
|
+
if (fs50.existsSync(newFilePath))
|
|
95791
95942
|
continue;
|
|
95792
95943
|
try {
|
|
95793
95944
|
moveFile(oldFilePath, newFilePath);
|
|
@@ -95800,13 +95951,13 @@ function moveDirectoryContents(entry) {
|
|
|
95800
95951
|
}
|
|
95801
95952
|
function removeIfEmptyDir(dir) {
|
|
95802
95953
|
try {
|
|
95803
|
-
if (
|
|
95804
|
-
|
|
95954
|
+
if (fs50.readdirSync(dir).length === 0)
|
|
95955
|
+
fs50.rmdirSync(dir);
|
|
95805
95956
|
} catch {}
|
|
95806
95957
|
}
|
|
95807
95958
|
function removeLockArtifact(entry) {
|
|
95808
95959
|
try {
|
|
95809
|
-
|
|
95960
|
+
fs50.rmSync(entry.path, { force: true });
|
|
95810
95961
|
return { path: entry.path, removed: true };
|
|
95811
95962
|
} catch (error2) {
|
|
95812
95963
|
return { path: entry.path, removed: false, error: error2 instanceof Error ? error2.message : String(error2) };
|
|
@@ -95818,36 +95969,36 @@ function applyWriterRelocation(stashDir) {
|
|
|
95818
95969
|
const lockResults = lockArtifacts.map(removeLockArtifact);
|
|
95819
95970
|
for (const spec of relocationSpecs(stashDir)) {
|
|
95820
95971
|
const relativeParts = Array.isArray(spec.oldRelative) ? spec.oldRelative : [spec.oldRelative];
|
|
95821
|
-
removeIfEmptyDir(
|
|
95972
|
+
removeIfEmptyDir(path62.join(stashDir, ".akm", ...relativeParts));
|
|
95822
95973
|
}
|
|
95823
95974
|
return { directories: directoryResults, lockArtifacts: lockResults, skippedLocks };
|
|
95824
95975
|
}
|
|
95825
95976
|
|
|
95826
95977
|
// scripts/akm-migrate/task-migrate.ts
|
|
95827
95978
|
import { randomUUID as randomUUID7 } from "crypto";
|
|
95828
|
-
import
|
|
95979
|
+
import fs56 from "fs";
|
|
95829
95980
|
import os5 from "os";
|
|
95830
|
-
import
|
|
95981
|
+
import path65 from "path";
|
|
95831
95982
|
init_errors();
|
|
95832
95983
|
init_paths();
|
|
95833
95984
|
|
|
95834
95985
|
// scripts/akm-migrate/migrate/task-files-to-v3.ts
|
|
95835
95986
|
init_errors();
|
|
95836
95987
|
import crypto6 from "crypto";
|
|
95837
|
-
import
|
|
95838
|
-
import
|
|
95988
|
+
import fs53 from "fs";
|
|
95989
|
+
import path63 from "path";
|
|
95839
95990
|
|
|
95840
95991
|
// scripts/akm-migrate/migrate/durable-fs.ts
|
|
95841
|
-
import
|
|
95992
|
+
import fs51 from "fs";
|
|
95842
95993
|
function fsyncDirectoryPortable(directory) {
|
|
95843
95994
|
if (process.platform === "win32")
|
|
95844
95995
|
return;
|
|
95845
95996
|
try {
|
|
95846
|
-
const fd =
|
|
95997
|
+
const fd = fs51.openSync(directory, "r");
|
|
95847
95998
|
try {
|
|
95848
|
-
|
|
95999
|
+
fs51.fsyncSync(fd);
|
|
95849
96000
|
} finally {
|
|
95850
|
-
|
|
96001
|
+
fs51.closeSync(fd);
|
|
95851
96002
|
}
|
|
95852
96003
|
} catch (cause) {
|
|
95853
96004
|
const code = cause.code;
|
|
@@ -95861,25 +96012,25 @@ function migrationError(detail) {
|
|
|
95861
96012
|
return new ConfigError(`Task migration to v3 failed: ${detail}`, "INVALID_CONFIG_FILE");
|
|
95862
96013
|
}
|
|
95863
96014
|
function contained2(root2, candidate) {
|
|
95864
|
-
const relative =
|
|
95865
|
-
return relative === "" || !relative.startsWith("..") && !
|
|
96015
|
+
const relative = path63.relative(root2, candidate);
|
|
96016
|
+
return relative === "" || !relative.startsWith("..") && !path63.isAbsolute(relative);
|
|
95866
96017
|
}
|
|
95867
96018
|
function realDirectory(filePath) {
|
|
95868
|
-
const stat =
|
|
96019
|
+
const stat = fs53.lstatSync(filePath);
|
|
95869
96020
|
if (stat.isSymbolicLink() || !stat.isDirectory())
|
|
95870
96021
|
throw migrationError(`${filePath} must be a real directory.`);
|
|
95871
|
-
return
|
|
96022
|
+
return fs53.realpathSync(filePath);
|
|
95872
96023
|
}
|
|
95873
96024
|
function snapshot(filePath) {
|
|
95874
|
-
const stat =
|
|
96025
|
+
const stat = fs53.lstatSync(filePath);
|
|
95875
96026
|
if (stat.isSymbolicLink() || !stat.isFile())
|
|
95876
96027
|
throw migrationError(`${filePath} must be a real file.`);
|
|
95877
|
-
const bytes =
|
|
96028
|
+
const bytes = fs53.readFileSync(filePath);
|
|
95878
96029
|
return Object.freeze({ bytes, mode: stat.mode & 511 });
|
|
95879
96030
|
}
|
|
95880
96031
|
function writable(filePath) {
|
|
95881
96032
|
try {
|
|
95882
|
-
|
|
96033
|
+
fs53.accessSync(filePath, fs53.constants.W_OK);
|
|
95883
96034
|
return true;
|
|
95884
96035
|
} catch {
|
|
95885
96036
|
return false;
|
|
@@ -95892,12 +96043,12 @@ function walkTasks(root2, tasksDir, out) {
|
|
|
95892
96043
|
throw migrationError(`${root2.root} resolves outside bundle ${root2.bundleId}.`);
|
|
95893
96044
|
}
|
|
95894
96045
|
const visit2 = (directory) => {
|
|
95895
|
-
const physicalDirectory =
|
|
96046
|
+
const physicalDirectory = fs53.realpathSync(directory);
|
|
95896
96047
|
if (!contained2(physicalRoot, physicalDirectory)) {
|
|
95897
96048
|
throw migrationError(`${directory} resolves outside bundle ${root2.bundleId}.`);
|
|
95898
96049
|
}
|
|
95899
|
-
for (const entry of
|
|
95900
|
-
const candidate =
|
|
96050
|
+
for (const entry of fs53.readdirSync(directory, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
|
|
96051
|
+
const candidate = path63.join(directory, entry.name);
|
|
95901
96052
|
if (entry.isSymbolicLink())
|
|
95902
96053
|
throw migrationError(`task migration does not follow symbolic link ${candidate}.`);
|
|
95903
96054
|
if (entry.isDirectory()) {
|
|
@@ -95907,7 +96058,7 @@ function walkTasks(root2, tasksDir, out) {
|
|
|
95907
96058
|
if (!entry.isFile() || !entry.name.endsWith(".yml"))
|
|
95908
96059
|
continue;
|
|
95909
96060
|
const current = snapshot(candidate);
|
|
95910
|
-
const parent =
|
|
96061
|
+
const parent = path63.dirname(candidate);
|
|
95911
96062
|
out.push({
|
|
95912
96063
|
filePath: candidate,
|
|
95913
96064
|
bytes: current.bytes,
|
|
@@ -95923,9 +96074,9 @@ function walkTasks(root2, tasksDir, out) {
|
|
|
95923
96074
|
function inspectTaskToV3Files(roots) {
|
|
95924
96075
|
const files = [];
|
|
95925
96076
|
for (const root2 of [...roots].sort((a, b) => a.bundleId.localeCompare(b.bundleId))) {
|
|
95926
|
-
const tasksDir = root2.layout === "akm-task" ? root2.root :
|
|
96077
|
+
const tasksDir = root2.layout === "akm-task" ? root2.root : path63.join(root2.root, "tasks");
|
|
95927
96078
|
try {
|
|
95928
|
-
const stat =
|
|
96079
|
+
const stat = fs53.lstatSync(tasksDir);
|
|
95929
96080
|
if (stat.isSymbolicLink())
|
|
95930
96081
|
throw migrationError(`task migration does not follow symbolic link ${tasksDir}.`);
|
|
95931
96082
|
if (!stat.isDirectory())
|
|
@@ -95940,33 +96091,33 @@ function inspectTaskToV3Files(roots) {
|
|
|
95940
96091
|
return files.sort((a, b) => a.filePath.localeCompare(b.filePath));
|
|
95941
96092
|
}
|
|
95942
96093
|
function hashPath(filePath) {
|
|
95943
|
-
return crypto6.createHash("sha256").update(
|
|
96094
|
+
return crypto6.createHash("sha256").update(path63.resolve(filePath)).digest("hex").slice(0, 16);
|
|
95944
96095
|
}
|
|
95945
96096
|
function taskMigrationBackupPath(backupRoot, filePath) {
|
|
95946
|
-
return
|
|
96097
|
+
return path63.join(backupRoot, "files", `${hashPath(filePath)}-${path63.basename(filePath)}`);
|
|
95947
96098
|
}
|
|
95948
96099
|
function writeDurable(filePath, bytes, mode, exclusive = false) {
|
|
95949
|
-
|
|
96100
|
+
fs53.mkdirSync(path63.dirname(filePath), { recursive: true });
|
|
95950
96101
|
const flags = exclusive ? "wx" : "w";
|
|
95951
|
-
const fd =
|
|
96102
|
+
const fd = fs53.openSync(filePath, flags, mode);
|
|
95952
96103
|
try {
|
|
95953
|
-
|
|
95954
|
-
|
|
96104
|
+
fs53.writeFileSync(fd, bytes);
|
|
96105
|
+
fs53.fsyncSync(fd);
|
|
95955
96106
|
} finally {
|
|
95956
|
-
|
|
96107
|
+
fs53.closeSync(fd);
|
|
95957
96108
|
}
|
|
95958
|
-
|
|
95959
|
-
fsyncDirectoryPortable(
|
|
96109
|
+
fs53.chmodSync(filePath, mode);
|
|
96110
|
+
fsyncDirectoryPortable(path63.dirname(filePath));
|
|
95960
96111
|
}
|
|
95961
96112
|
function replaceAtomically(filePath, bytes, mode) {
|
|
95962
|
-
const temporary =
|
|
96113
|
+
const temporary = path63.join(path63.dirname(filePath), `.${path63.basename(filePath)}.migrate-${crypto6.randomUUID()}`);
|
|
95963
96114
|
try {
|
|
95964
96115
|
writeDurable(temporary, bytes, mode, true);
|
|
95965
|
-
|
|
95966
|
-
fsyncDirectoryPortable(
|
|
96116
|
+
fs53.renameSync(temporary, filePath);
|
|
96117
|
+
fsyncDirectoryPortable(path63.dirname(filePath));
|
|
95967
96118
|
} finally {
|
|
95968
96119
|
try {
|
|
95969
|
-
|
|
96120
|
+
fs53.unlinkSync(temporary);
|
|
95970
96121
|
} catch (cause) {
|
|
95971
96122
|
if (cause.code !== "ENOENT")
|
|
95972
96123
|
throw cause;
|
|
@@ -96005,7 +96156,7 @@ function applyTaskToV3MigrationPlan(plan, options) {
|
|
|
96005
96156
|
const current = snapshot(change.filePath);
|
|
96006
96157
|
if (!current.bytes.equals(change.after))
|
|
96007
96158
|
continue;
|
|
96008
|
-
replaceAtomically(change.filePath,
|
|
96159
|
+
replaceAtomically(change.filePath, fs53.readFileSync(taskMigrationBackupPath(options.backupRoot, change.filePath)), change.mode);
|
|
96009
96160
|
}
|
|
96010
96161
|
throw cause;
|
|
96011
96162
|
}
|
|
@@ -96015,31 +96166,31 @@ function applyTaskToV3MigrationPlan(plan, options) {
|
|
|
96015
96166
|
// scripts/akm-migrate/migrate/task-files-to-v4.ts
|
|
96016
96167
|
init_errors();
|
|
96017
96168
|
import crypto7 from "crypto";
|
|
96018
|
-
import
|
|
96019
|
-
import
|
|
96169
|
+
import fs55 from "fs";
|
|
96170
|
+
import path64 from "path";
|
|
96020
96171
|
function migrationError2(detail) {
|
|
96021
96172
|
return new ConfigError(`Task migration to v4 failed: ${detail}`, "INVALID_CONFIG_FILE");
|
|
96022
96173
|
}
|
|
96023
96174
|
function contained3(root2, candidate) {
|
|
96024
|
-
const relative =
|
|
96025
|
-
return relative === "" || !relative.startsWith("..") && !
|
|
96175
|
+
const relative = path64.relative(root2, candidate);
|
|
96176
|
+
return relative === "" || !relative.startsWith("..") && !path64.isAbsolute(relative);
|
|
96026
96177
|
}
|
|
96027
96178
|
function realDirectory2(filePath) {
|
|
96028
|
-
const stat =
|
|
96179
|
+
const stat = fs55.lstatSync(filePath);
|
|
96029
96180
|
if (stat.isSymbolicLink() || !stat.isDirectory())
|
|
96030
96181
|
throw migrationError2(`${filePath} must be a real directory.`);
|
|
96031
|
-
return
|
|
96182
|
+
return fs55.realpathSync(filePath);
|
|
96032
96183
|
}
|
|
96033
96184
|
function snapshot2(filePath) {
|
|
96034
|
-
const stat =
|
|
96185
|
+
const stat = fs55.lstatSync(filePath);
|
|
96035
96186
|
if (stat.isSymbolicLink() || !stat.isFile())
|
|
96036
96187
|
throw migrationError2(`${filePath} must be a real file.`);
|
|
96037
|
-
const bytes =
|
|
96188
|
+
const bytes = fs55.readFileSync(filePath);
|
|
96038
96189
|
return Object.freeze({ bytes, mode: stat.mode & 511 });
|
|
96039
96190
|
}
|
|
96040
96191
|
function writable2(filePath) {
|
|
96041
96192
|
try {
|
|
96042
|
-
|
|
96193
|
+
fs55.accessSync(filePath, fs55.constants.W_OK);
|
|
96043
96194
|
return true;
|
|
96044
96195
|
} catch {
|
|
96045
96196
|
return false;
|
|
@@ -96052,12 +96203,12 @@ function walkTasks2(root2, tasksDir, out) {
|
|
|
96052
96203
|
throw migrationError2(`${root2.root} resolves outside bundle ${root2.bundleId}.`);
|
|
96053
96204
|
}
|
|
96054
96205
|
const visit2 = (directory) => {
|
|
96055
|
-
const physicalDirectory =
|
|
96206
|
+
const physicalDirectory = fs55.realpathSync(directory);
|
|
96056
96207
|
if (!contained3(physicalRoot, physicalDirectory)) {
|
|
96057
96208
|
throw migrationError2(`${directory} resolves outside bundle ${root2.bundleId}.`);
|
|
96058
96209
|
}
|
|
96059
|
-
for (const entry of
|
|
96060
|
-
const candidate =
|
|
96210
|
+
for (const entry of fs55.readdirSync(directory, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
|
|
96211
|
+
const candidate = path64.join(directory, entry.name);
|
|
96061
96212
|
if (entry.isSymbolicLink())
|
|
96062
96213
|
throw migrationError2(`task migration does not follow symbolic link ${candidate}.`);
|
|
96063
96214
|
if (entry.isDirectory()) {
|
|
@@ -96067,7 +96218,7 @@ function walkTasks2(root2, tasksDir, out) {
|
|
|
96067
96218
|
if (!entry.isFile() || !entry.name.endsWith(".yml"))
|
|
96068
96219
|
continue;
|
|
96069
96220
|
const current = snapshot2(candidate);
|
|
96070
|
-
const parent =
|
|
96221
|
+
const parent = path64.dirname(candidate);
|
|
96071
96222
|
out.push({
|
|
96072
96223
|
filePath: candidate,
|
|
96073
96224
|
bytes: current.bytes,
|
|
@@ -96083,9 +96234,9 @@ function walkTasks2(root2, tasksDir, out) {
|
|
|
96083
96234
|
function inspectTaskToV4Files(roots) {
|
|
96084
96235
|
const files = [];
|
|
96085
96236
|
for (const root2 of [...roots].sort((a, b) => a.bundleId.localeCompare(b.bundleId))) {
|
|
96086
|
-
const tasksDir = root2.layout === "akm-task" ? root2.root :
|
|
96237
|
+
const tasksDir = root2.layout === "akm-task" ? root2.root : path64.join(root2.root, "tasks");
|
|
96087
96238
|
try {
|
|
96088
|
-
const stat =
|
|
96239
|
+
const stat = fs55.lstatSync(tasksDir);
|
|
96089
96240
|
if (stat.isSymbolicLink())
|
|
96090
96241
|
throw migrationError2(`task migration does not follow symbolic link ${tasksDir}.`);
|
|
96091
96242
|
if (!stat.isDirectory())
|
|
@@ -96100,33 +96251,33 @@ function inspectTaskToV4Files(roots) {
|
|
|
96100
96251
|
return files.sort((a, b) => a.filePath.localeCompare(b.filePath));
|
|
96101
96252
|
}
|
|
96102
96253
|
function hashPath2(filePath) {
|
|
96103
|
-
return crypto7.createHash("sha256").update(
|
|
96254
|
+
return crypto7.createHash("sha256").update(path64.resolve(filePath)).digest("hex").slice(0, 16);
|
|
96104
96255
|
}
|
|
96105
96256
|
function taskMigrationBackupPathV4(backupRoot, filePath) {
|
|
96106
|
-
return
|
|
96257
|
+
return path64.join(backupRoot, "files", `${hashPath2(filePath)}-${path64.basename(filePath)}`);
|
|
96107
96258
|
}
|
|
96108
96259
|
function writeDurable2(filePath, bytes, mode, exclusive = false) {
|
|
96109
|
-
|
|
96260
|
+
fs55.mkdirSync(path64.dirname(filePath), { recursive: true });
|
|
96110
96261
|
const flags = exclusive ? "wx" : "w";
|
|
96111
|
-
const fd =
|
|
96262
|
+
const fd = fs55.openSync(filePath, flags, mode);
|
|
96112
96263
|
try {
|
|
96113
|
-
|
|
96114
|
-
|
|
96264
|
+
fs55.writeFileSync(fd, bytes);
|
|
96265
|
+
fs55.fsyncSync(fd);
|
|
96115
96266
|
} finally {
|
|
96116
|
-
|
|
96267
|
+
fs55.closeSync(fd);
|
|
96117
96268
|
}
|
|
96118
|
-
|
|
96119
|
-
fsyncDirectoryPortable(
|
|
96269
|
+
fs55.chmodSync(filePath, mode);
|
|
96270
|
+
fsyncDirectoryPortable(path64.dirname(filePath));
|
|
96120
96271
|
}
|
|
96121
96272
|
function replaceAtomically2(filePath, bytes, mode) {
|
|
96122
|
-
const temporary =
|
|
96273
|
+
const temporary = path64.join(path64.dirname(filePath), `.${path64.basename(filePath)}.migrate-${crypto7.randomUUID()}`);
|
|
96123
96274
|
try {
|
|
96124
96275
|
writeDurable2(temporary, bytes, mode, true);
|
|
96125
|
-
|
|
96126
|
-
fsyncDirectoryPortable(
|
|
96276
|
+
fs55.renameSync(temporary, filePath);
|
|
96277
|
+
fsyncDirectoryPortable(path64.dirname(filePath));
|
|
96127
96278
|
} finally {
|
|
96128
96279
|
try {
|
|
96129
|
-
|
|
96280
|
+
fs55.unlinkSync(temporary);
|
|
96130
96281
|
} catch (cause) {
|
|
96131
96282
|
if (cause.code !== "ENOENT")
|
|
96132
96283
|
throw cause;
|
|
@@ -96165,7 +96316,7 @@ function applyTaskToV4MigrationPlan(plan, options) {
|
|
|
96165
96316
|
const current = snapshot2(change.filePath);
|
|
96166
96317
|
if (!current.bytes.equals(change.after))
|
|
96167
96318
|
continue;
|
|
96168
|
-
replaceAtomically2(change.filePath,
|
|
96319
|
+
replaceAtomically2(change.filePath, fs55.readFileSync(taskMigrationBackupPathV4(options.backupRoot, change.filePath)), change.mode);
|
|
96169
96320
|
}
|
|
96170
96321
|
throw cause;
|
|
96171
96322
|
}
|
|
@@ -96177,12 +96328,12 @@ function expandTilde(value) {
|
|
|
96177
96328
|
if (value === "~")
|
|
96178
96329
|
return os5.homedir();
|
|
96179
96330
|
if (value.startsWith("~/") || value.startsWith("~\\"))
|
|
96180
|
-
return
|
|
96331
|
+
return path65.join(os5.homedir(), value.slice(2));
|
|
96181
96332
|
return value;
|
|
96182
96333
|
}
|
|
96183
96334
|
function existingDirectory(target) {
|
|
96184
96335
|
try {
|
|
96185
|
-
return
|
|
96336
|
+
return fs56.statSync(target).isDirectory();
|
|
96186
96337
|
} catch (cause) {
|
|
96187
96338
|
if (cause.code === "ENOENT")
|
|
96188
96339
|
return false;
|
|
@@ -96203,21 +96354,21 @@ function taskRoots(config, resolutionBase = process.cwd()) {
|
|
|
96203
96354
|
const source = sources.get(bundleId);
|
|
96204
96355
|
if (!source)
|
|
96205
96356
|
continue;
|
|
96206
|
-
const configuredRoot = source.type === "filesystem" && source.path ?
|
|
96357
|
+
const configuredRoot = source.type === "filesystem" && source.path ? path65.resolve(resolutionBase, expandTilde(source.path)) : lockContentRootFor(bundleId, source.type);
|
|
96207
96358
|
if (!configuredRoot || !existingDirectory(configuredRoot))
|
|
96208
96359
|
continue;
|
|
96209
|
-
const bundleRoot =
|
|
96360
|
+
const bundleRoot = path65.resolve(configuredRoot);
|
|
96210
96361
|
const component = bundleComponentConfig(bundle);
|
|
96211
|
-
const componentRoot =
|
|
96212
|
-
const relative =
|
|
96213
|
-
if (relative === ".." || relative.startsWith(`..${
|
|
96362
|
+
const componentRoot = path65.resolve(bundleRoot, component?.root ?? ".");
|
|
96363
|
+
const relative = path65.relative(bundleRoot, componentRoot);
|
|
96364
|
+
if (relative === ".." || relative.startsWith(`..${path65.sep}`) || path65.isAbsolute(relative)) {
|
|
96214
96365
|
throw new ConfigError(`Task migration component root ${componentRoot} escapes bundle ${bundleId} at ${bundleRoot}.`, "INVALID_CONFIG_FILE");
|
|
96215
96366
|
}
|
|
96216
96367
|
if (!existingDirectory(componentRoot))
|
|
96217
96368
|
continue;
|
|
96218
96369
|
const adapter = component?.adapter ?? detectAdapterId(componentRoot, "");
|
|
96219
96370
|
if (!component?.adapter && adapter === "") {
|
|
96220
|
-
const flatTasks =
|
|
96371
|
+
const flatTasks = fs56.readdirSync(componentRoot, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".yml")).map((entry) => entry.name).sort();
|
|
96221
96372
|
if (flatTasks.length > 0) {
|
|
96222
96373
|
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");
|
|
96223
96374
|
}
|
|
@@ -96289,8 +96440,8 @@ function applyTaskV3Migration() {
|
|
|
96289
96440
|
const before = inspectCurrentTaskPlan();
|
|
96290
96441
|
if (before.result.taskV3Migration.changed === 0)
|
|
96291
96442
|
return before.result;
|
|
96292
|
-
const backupRoot =
|
|
96293
|
-
const backupPath =
|
|
96443
|
+
const backupRoot = path65.join(getDataDir(), "backups", "task-v3");
|
|
96444
|
+
const backupPath = path65.join(backupRoot, `${Date.now()}-${randomUUID7()}`);
|
|
96294
96445
|
const applied = applyTaskToV3MigrationPlan(before.plan, { backupRoot: backupPath });
|
|
96295
96446
|
const after = inspectCurrentTaskPlan().result;
|
|
96296
96447
|
if (after.taskV3Migration.changed > 0) {
|
|
@@ -96346,8 +96497,8 @@ function applyTaskV4Migration() {
|
|
|
96346
96497
|
const before = inspectCurrentTaskV4Plan();
|
|
96347
96498
|
if (before.result.taskV4Migration.changed === 0)
|
|
96348
96499
|
return before.result;
|
|
96349
|
-
const backupRoot =
|
|
96350
|
-
const backupPath =
|
|
96500
|
+
const backupRoot = path65.join(getDataDir(), "backups", "task-v4");
|
|
96501
|
+
const backupPath = path65.join(backupRoot, `${Date.now()}-${randomUUID7()}`);
|
|
96351
96502
|
const applied = applyTaskToV4MigrationPlan(before.plan, { backupRoot: backupPath });
|
|
96352
96503
|
const after = inspectCurrentTaskV4Plan().result;
|
|
96353
96504
|
if (after.taskV4Migration.changed > 0) {
|