akm-cli 0.9.12 → 0.9.14-beta.1
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 +100 -0
- package/dist/assets/workflows/workflow-template.md +4 -0
- package/dist/commands/improve/eligibility.js +27 -15
- 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/commands/read/curate.js +3 -2
- package/dist/commands/read/show.js +26 -9
- package/dist/core/adapter/adapters/akm-adapter.js +5 -1
- package/dist/core/asset/markdown-fragments.js +146 -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/core/lexical-score.js +25 -0
- package/dist/core/type-presentation.js +36 -4
- package/dist/indexer/index-written-assets.js +4 -0
- package/dist/indexer/indexer.js +5 -2
- package/dist/indexer/passes/metadata.js +64 -1
- package/dist/indexer/scan/doc-to-entry.js +3 -0
- package/dist/indexer/scan/drain-dir.js +33 -22
- package/dist/indexer/search/db-search.js +72 -14
- package/dist/indexer/search/name-match.js +35 -0
- package/dist/indexer/search/ranking-contributors.js +15 -12
- package/dist/indexer/search/ranking.js +42 -18
- package/dist/indexer/usage/show-usage.js +14 -2
- package/dist/llm/client.js +12 -8
- package/dist/llm/embedders/remote.js +3 -2
- package/dist/llm/graph-extract.js +18 -67
- package/dist/output/shapes.js +46 -1
- package/dist/output/text/proposal-format.js +5 -0
- package/dist/scripts/akm-migrate-node.js +648 -253
- package/dist/scripts/akm-migrate.js +648 -253
- package/dist/storage/repositories/index-connection.js +23 -8
- package/dist/storage/repositories/index-entries-repository.js +3 -2
- package/dist/storage/repositories/index-entry-schema.js +43 -3
- package/dist/storage/repositories/index-fts-repository.js +160 -14
- package/dist/storage/repositories/index-schema.js +8 -18
- 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/migration/release-notes/0.9.14.md +26 -0
- package/docs/migration/release-notes/README.md +2 -0
- 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();
|
|
@@ -9454,6 +9467,53 @@ function projectMarkdownContent(body, truncationInfo) {
|
|
|
9454
9467
|
truncationInfo.truncated = text.length > MARKDOWN_CONTENT_MAX_CHARS;
|
|
9455
9468
|
return truncateUnicodeSafe(text, MARKDOWN_CONTENT_MAX_CHARS);
|
|
9456
9469
|
}
|
|
9470
|
+
function setMarkdownFragmentContent(entry, content) {
|
|
9471
|
+
markdownFragmentProjectionEntries.add(entry);
|
|
9472
|
+
if (content)
|
|
9473
|
+
markdownFragmentContentByEntry.set(entry, content);
|
|
9474
|
+
}
|
|
9475
|
+
function getMarkdownFragmentContent(entry) {
|
|
9476
|
+
return markdownFragmentContentByEntry.get(entry);
|
|
9477
|
+
}
|
|
9478
|
+
function hasMarkdownFragmentContent(entry) {
|
|
9479
|
+
return markdownFragmentProjectionEntries.has(entry);
|
|
9480
|
+
}
|
|
9481
|
+
function projectMarkdownFragmentContent(raw) {
|
|
9482
|
+
const lines = raw.split(/\r?\n/);
|
|
9483
|
+
const parsed = parseFrontmatter(raw);
|
|
9484
|
+
const start = parsed.frontmatter ? parsed.bodyStartLine - 1 : 0;
|
|
9485
|
+
const projected = lines.map(() => "");
|
|
9486
|
+
let fence;
|
|
9487
|
+
const htmlComment = { inComment: false };
|
|
9488
|
+
for (let index = start;index < lines.length; index++) {
|
|
9489
|
+
const rawLine = lines[index];
|
|
9490
|
+
if (fence) {
|
|
9491
|
+
if (isMarkdownFenceClosing(rawLine, fence))
|
|
9492
|
+
fence = undefined;
|
|
9493
|
+
continue;
|
|
9494
|
+
}
|
|
9495
|
+
if (!htmlComment.inComment) {
|
|
9496
|
+
const opening2 = parseMarkdownFenceOpening(rawLine);
|
|
9497
|
+
if (opening2) {
|
|
9498
|
+
fence = opening2;
|
|
9499
|
+
continue;
|
|
9500
|
+
}
|
|
9501
|
+
}
|
|
9502
|
+
let safe = stripMarkdownHtmlComments(rawLine, htmlComment);
|
|
9503
|
+
const opening = parseMarkdownFenceOpening(safe.trim());
|
|
9504
|
+
if (opening) {
|
|
9505
|
+
fence = opening;
|
|
9506
|
+
continue;
|
|
9507
|
+
}
|
|
9508
|
+
if (/^\s*\[[^\]]+\]:\s*\S+/.test(safe) || /^\s*<[^>]+>\s*$/.test(safe))
|
|
9509
|
+
continue;
|
|
9510
|
+
safe = stripMarkdownLinkDestinations(safe).replace(/<[^>]+>/g, " ");
|
|
9511
|
+
projected[index] = safe.replace(/[ \t]+$/g, "");
|
|
9512
|
+
}
|
|
9513
|
+
const text = projected.join(`
|
|
9514
|
+
`);
|
|
9515
|
+
return text.trim() ? text : undefined;
|
|
9516
|
+
}
|
|
9457
9517
|
function applyPreContributorFields(entry, file, ctx, pkgMeta) {
|
|
9458
9518
|
const ext = path19.extname(file).toLowerCase();
|
|
9459
9519
|
if (pkgMeta) {
|
|
@@ -9474,7 +9534,9 @@ function applyPreContributorFields(entry, file, ctx, pkgMeta) {
|
|
|
9474
9534
|
entry.parameters = fmParams;
|
|
9475
9535
|
applyWikiFrontmatter(entry, parsed.data);
|
|
9476
9536
|
applyProvenanceFrontmatter(entry, parsed.data);
|
|
9477
|
-
|
|
9537
|
+
const safeForFragments = entry.type !== "env" && entry.type !== "session" && !hasSessionMemoryMarker(parsed.data, parsed.content);
|
|
9538
|
+
setMarkdownFragmentContent(entry, safeForFragments ? projectMarkdownFragmentContent(content) : undefined);
|
|
9539
|
+
if (safeForFragments) {
|
|
9478
9540
|
const truncationInfo = { truncated: false };
|
|
9479
9541
|
const contentProjection = projectMarkdownContent(parsed.content, truncationInfo);
|
|
9480
9542
|
if (contentProjection) {
|
|
@@ -9592,7 +9654,7 @@ function extractDirTagsFromName(name) {
|
|
|
9592
9654
|
}
|
|
9593
9655
|
return Array.from(tags);
|
|
9594
9656
|
}
|
|
9595
|
-
var SCOPE_KEYS, KNOWN_QUALITY_VALUES, warnedUnknownQualityValues, MARKDOWN_CONTENT_MAX_CHARS = 1e6, MAX_MARKDOWN_LINK_NESTING = 32;
|
|
9657
|
+
var SCOPE_KEYS, KNOWN_QUALITY_VALUES, warnedUnknownQualityValues, MARKDOWN_CONTENT_MAX_CHARS = 1e6, MAX_MARKDOWN_LINK_NESTING = 32, markdownFragmentContentByEntry, markdownFragmentProjectionEntries;
|
|
9596
9658
|
var init_metadata = __esm(() => {
|
|
9597
9659
|
init_asset_ref();
|
|
9598
9660
|
init_frontmatter();
|
|
@@ -9601,6 +9663,8 @@ var init_metadata = __esm(() => {
|
|
|
9601
9663
|
SCOPE_KEYS = ["user", "agent", "run", "channel"];
|
|
9602
9664
|
KNOWN_QUALITY_VALUES = new Set(["generated", "curated", "enriched", "proposed"]);
|
|
9603
9665
|
warnedUnknownQualityValues = new Set;
|
|
9666
|
+
markdownFragmentContentByEntry = new WeakMap;
|
|
9667
|
+
markdownFragmentProjectionEntries = new WeakSet;
|
|
9604
9668
|
});
|
|
9605
9669
|
|
|
9606
9670
|
// src/execution/record.ts
|
|
@@ -12174,6 +12238,9 @@ var init_schema2 = __esm(() => {
|
|
|
12174
12238
|
});
|
|
12175
12239
|
|
|
12176
12240
|
// src/core/asset/markdown.ts
|
|
12241
|
+
function markdownHeadingSlug(heading) {
|
|
12242
|
+
return heading.trim().toLowerCase().replace(/<[^>]*>/g, "").replace(/[^\p{L}\p{N}\s_-]+/gu, "-").replace(/[\s_]+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
|
|
12243
|
+
}
|
|
12177
12244
|
function parseMarkdownToc(content) {
|
|
12178
12245
|
const lines = content.split(/\r?\n/);
|
|
12179
12246
|
const headings = [];
|
|
@@ -12415,7 +12482,7 @@ function bindStepSections(headings, lines, bodyStartLine, totalLines, path24, de
|
|
|
12415
12482
|
if (!declaredIds.has(h.text)) {
|
|
12416
12483
|
errors3.push({
|
|
12417
12484
|
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.`
|
|
12485
|
+
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
12486
|
});
|
|
12420
12487
|
continue;
|
|
12421
12488
|
}
|
|
@@ -36279,7 +36346,7 @@ var require_libvips = __commonJS((exports, module) => {
|
|
|
36279
36346
|
SPDX-License-Identifier: Apache-2.0
|
|
36280
36347
|
*/
|
|
36281
36348
|
var { spawnSync: spawnSync6 } = __require("node:child_process");
|
|
36282
|
-
var { createHash:
|
|
36349
|
+
var { createHash: createHash10 } = __require("node:crypto");
|
|
36283
36350
|
var semverCoerce = require_coerce2();
|
|
36284
36351
|
var semverGreaterThanOrEqualTo = require_gte2();
|
|
36285
36352
|
var semverSatisfies = require_satisfies2();
|
|
@@ -36367,7 +36434,7 @@ var require_libvips = __commonJS((exports, module) => {
|
|
|
36367
36434
|
}
|
|
36368
36435
|
return false;
|
|
36369
36436
|
};
|
|
36370
|
-
var sha512 = (s) =>
|
|
36437
|
+
var sha512 = (s) => createHash10("sha512").update(s).digest("hex");
|
|
36371
36438
|
var yarnLocator = () => {
|
|
36372
36439
|
try {
|
|
36373
36440
|
const identHash = sha512(`imgsharp-libvips-${buildPlatformArch()}`);
|
|
@@ -50659,10 +50726,10 @@ var import_sharp, __dirname = "/home/runner/work/akm/akm/node_modules/@huggingfa
|
|
|
50659
50726
|
if (cached) {
|
|
50660
50727
|
return cached.text();
|
|
50661
50728
|
}
|
|
50662
|
-
const
|
|
50663
|
-
if (
|
|
50664
|
-
await hashCache.put(url2, new Response(
|
|
50665
|
-
return
|
|
50729
|
+
const hash4 = await this._getLfsFileHash(url2);
|
|
50730
|
+
if (hash4) {
|
|
50731
|
+
await hashCache.put(url2, new Response(hash4));
|
|
50732
|
+
return hash4;
|
|
50666
50733
|
}
|
|
50667
50734
|
return null;
|
|
50668
50735
|
} catch {
|
|
@@ -68759,15 +68826,15 @@ ${this.boa_token}${this.audio_token.repeat(this._compute_audio_num_tokens(audio_
|
|
|
68759
68826
|
});
|
|
68760
68827
|
|
|
68761
68828
|
// src/indexer/walk/file-context.ts
|
|
68762
|
-
import
|
|
68763
|
-
import
|
|
68829
|
+
import fs47 from "node:fs";
|
|
68830
|
+
import path56 from "node:path";
|
|
68764
68831
|
function buildFileContext(stashRoot, absPath) {
|
|
68765
|
-
const relPath = toPosix(
|
|
68766
|
-
const ext =
|
|
68767
|
-
const fileName =
|
|
68768
|
-
const parentDirAbs =
|
|
68769
|
-
const parentDir =
|
|
68770
|
-
const relDir = toPosix(
|
|
68832
|
+
const relPath = toPosix(path56.relative(stashRoot, absPath));
|
|
68833
|
+
const ext = path56.extname(absPath).toLowerCase();
|
|
68834
|
+
const fileName = path56.basename(absPath);
|
|
68835
|
+
const parentDirAbs = path56.dirname(absPath);
|
|
68836
|
+
const parentDir = path56.basename(parentDirAbs);
|
|
68837
|
+
const relDir = toPosix(path56.dirname(relPath));
|
|
68771
68838
|
const ancestorDirs = relDir === "." ? [] : relDir.split("/").filter((seg) => seg.length > 0);
|
|
68772
68839
|
let cachedContent;
|
|
68773
68840
|
let cachedFrontmatter;
|
|
@@ -68784,7 +68851,7 @@ function buildFileContext(stashRoot, absPath) {
|
|
|
68784
68851
|
stashRoot,
|
|
68785
68852
|
content() {
|
|
68786
68853
|
if (cachedContent === undefined) {
|
|
68787
|
-
cachedContent =
|
|
68854
|
+
cachedContent = fs47.readFileSync(absPath, "utf8");
|
|
68788
68855
|
}
|
|
68789
68856
|
return cachedContent;
|
|
68790
68857
|
},
|
|
@@ -68799,7 +68866,7 @@ function buildFileContext(stashRoot, absPath) {
|
|
|
68799
68866
|
},
|
|
68800
68867
|
stat() {
|
|
68801
68868
|
if (cachedStat === undefined) {
|
|
68802
|
-
cachedStat =
|
|
68869
|
+
cachedStat = fs47.statSync(absPath);
|
|
68803
68870
|
}
|
|
68804
68871
|
return cachedStat;
|
|
68805
68872
|
}
|
|
@@ -70922,6 +70989,7 @@ function formatProposalDrainPlain(r) {
|
|
|
70922
70989
|
const deferred = Array.isArray(r.deferred) ? r.deferred : [];
|
|
70923
70990
|
const skippedByCap = Array.isArray(r.skippedByCap) ? r.skippedByCap : [];
|
|
70924
70991
|
const staged = Array.isArray(r.staged) ? r.staged : [];
|
|
70992
|
+
const failed = Array.isArray(r.failed) ? r.failed : [];
|
|
70925
70993
|
const prefix = r.dryRun === true ? "[dry-run] " : "";
|
|
70926
70994
|
const lines = [
|
|
70927
70995
|
`${prefix}Drained proposal queue (strategy=${String(r.strategy ?? "?")}, policy=${policy}, applyMode=${applyMode})`,
|
|
@@ -70929,11 +70997,15 @@ function formatProposalDrainPlain(r) {
|
|
|
70929
70997
|
` rejected: ${rejected.length}`,
|
|
70930
70998
|
` deferred: ${deferred.length}`,
|
|
70931
70999
|
` skippedByCap: ${skippedByCap.length}`,
|
|
70932
|
-
` staged: ${staged.length}
|
|
71000
|
+
` staged: ${staged.length}`,
|
|
71001
|
+
` failed: ${failed.length}`
|
|
70933
71002
|
];
|
|
70934
71003
|
for (const d of deferred) {
|
|
70935
71004
|
lines.push(` - ${String(d.id ?? "?")} (${String(d.reason ?? "?")})`);
|
|
70936
71005
|
}
|
|
71006
|
+
for (const f of failed) {
|
|
71007
|
+
lines.push(` ! ${String(f.id ?? "?")} (${String(f.reason ?? "?")}): ${String(f.detail ?? "?")}`);
|
|
71008
|
+
}
|
|
70937
71009
|
appendLoweringNotices(lines, r);
|
|
70938
71010
|
return lines.join(`
|
|
70939
71011
|
`).trimEnd();
|
|
@@ -76193,12 +76265,16 @@ var httpUrl = exports_external.string().refine((v) => v.startsWith("http://") ||
|
|
|
76193
76265
|
});
|
|
76194
76266
|
var ENGINE_NAME_PATTERN = new RegExp(ENGINE_NAME_PATTERN_SOURCE);
|
|
76195
76267
|
var ENV_REFERENCE_PATTERN = /^\$[A-Za-z_][A-Za-z0-9_]*$|^\$\{[A-Za-z_][A-Za-z0-9_]*\}$/;
|
|
76268
|
+
var SECRET_STORE_REFERENCE_PATTERN = /^secret:\/\/(.+)$/;
|
|
76196
76269
|
var engineName = exports_external.string().max(63).regex(ENGINE_NAME_PATTERN, "names must be lowercase kebab-case and must not begin with reserved akm-");
|
|
76270
|
+
function isApiKeyReference(value) {
|
|
76271
|
+
return ENV_REFERENCE_PATTERN.test(value) || SECRET_STORE_REFERENCE_PATTERN.test(value);
|
|
76272
|
+
}
|
|
76197
76273
|
function symbolicOrWarnApiKey(label) {
|
|
76198
76274
|
return exports_external.string().superRefine((value) => {
|
|
76199
|
-
if (
|
|
76275
|
+
if (isApiKeyReference(value))
|
|
76200
76276
|
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.`);
|
|
76277
|
+
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
76278
|
});
|
|
76203
76279
|
}
|
|
76204
76280
|
var chatCompletionsEndpoint = exports_external.string().superRefine((value, ctx) => {
|
|
@@ -77366,11 +77442,19 @@ function getSources(config) {
|
|
|
77366
77442
|
function loadConfig() {
|
|
77367
77443
|
return loadUserConfig();
|
|
77368
77444
|
}
|
|
77369
|
-
function resolveSecret(value) {
|
|
77445
|
+
function resolveSecret(value, resolveFromStore) {
|
|
77370
77446
|
if (value === undefined)
|
|
77371
77447
|
return;
|
|
77372
77448
|
if (typeof value !== "string")
|
|
77373
77449
|
return value;
|
|
77450
|
+
const storeRef = SECRET_STORE_REFERENCE_PATTERN.exec(value)?.[1];
|
|
77451
|
+
if (storeRef !== undefined) {
|
|
77452
|
+
const resolved = resolveFromStore?.(storeRef) ?? null;
|
|
77453
|
+
if (resolved === null) {
|
|
77454
|
+
throw new ConfigError(`Secret store reference "${value}" did not resolve to a stored value.`, "SECRET_REFERENCE_UNRESOLVED");
|
|
77455
|
+
}
|
|
77456
|
+
return resolved;
|
|
77457
|
+
}
|
|
77374
77458
|
if (!value.includes("$"))
|
|
77375
77459
|
return value;
|
|
77376
77460
|
return value.replace(/\$\{([A-Za-z_][A-Za-z0-9_]*)\}|\$([A-Za-z_][A-Za-z0-9_]*)/g, (_match, braced, bare) => {
|
|
@@ -79254,10 +79338,10 @@ function listTxnJournalsTolerant(predicate) {
|
|
|
79254
79338
|
}
|
|
79255
79339
|
|
|
79256
79340
|
// src/commands/proposal/repository.ts
|
|
79257
|
-
import { createHash as
|
|
79258
|
-
import
|
|
79341
|
+
import { createHash as createHash10, randomUUID as randomUUID6 } from "node:crypto";
|
|
79342
|
+
import fs49 from "node:fs";
|
|
79259
79343
|
init_dist();
|
|
79260
|
-
import
|
|
79344
|
+
import path61 from "node:path";
|
|
79261
79345
|
|
|
79262
79346
|
// src/core/adapter/adapters/agent-skills-adapter.ts
|
|
79263
79347
|
init_frontmatter();
|
|
@@ -80162,20 +80246,41 @@ function buildWorkflowAction(ref) {
|
|
|
80162
80246
|
return `Start or resume execution with \`akm workflow run ${shellQuote(ref)}\`.`;
|
|
80163
80247
|
}
|
|
80164
80248
|
var TYPE_PRESENTATION = {
|
|
80165
|
-
skill: {
|
|
80249
|
+
skill: {
|
|
80250
|
+
label: "Skill",
|
|
80251
|
+
renderer: "skill-md",
|
|
80252
|
+
action: (ref) => `akm show ${ref} -> follow the instructions`,
|
|
80253
|
+
fragmentRef: false
|
|
80254
|
+
},
|
|
80166
80255
|
command: {
|
|
80167
80256
|
label: "Command",
|
|
80168
80257
|
renderer: "command-md",
|
|
80169
|
-
action: (ref) => `akm show ${ref} -> fill placeholders and dispatch
|
|
80258
|
+
action: (ref) => `akm show ${ref} -> fill placeholders and dispatch`,
|
|
80259
|
+
fragmentRef: false
|
|
80260
|
+
},
|
|
80261
|
+
agent: {
|
|
80262
|
+
label: "Agent",
|
|
80263
|
+
renderer: "agent-md",
|
|
80264
|
+
action: (ref) => `akm show ${ref} -> dispatch with full prompt`,
|
|
80265
|
+
fragmentRef: false
|
|
80170
80266
|
},
|
|
80171
|
-
agent: { label: "Agent", renderer: "agent-md", action: (ref) => `akm show ${ref} -> dispatch with full prompt` },
|
|
80172
80267
|
knowledge: {
|
|
80173
80268
|
label: "Knowledge",
|
|
80174
80269
|
renderer: "knowledge-md",
|
|
80175
80270
|
action: (ref) => `akm show ${ref} -> read reference material`
|
|
80176
80271
|
},
|
|
80177
|
-
workflow: {
|
|
80178
|
-
|
|
80272
|
+
workflow: {
|
|
80273
|
+
label: "Workflow",
|
|
80274
|
+
renderer: "workflow-md",
|
|
80275
|
+
action: (ref) => buildWorkflowAction(ref),
|
|
80276
|
+
fragmentRef: false
|
|
80277
|
+
},
|
|
80278
|
+
script: {
|
|
80279
|
+
label: "Script",
|
|
80280
|
+
renderer: "script-source",
|
|
80281
|
+
action: (ref) => `akm show ${ref} -> execute the run command`,
|
|
80282
|
+
fragmentRef: false
|
|
80283
|
+
},
|
|
80179
80284
|
memory: { label: "Memory", renderer: "memory-md", action: (ref) => `akm show ${ref} -> recall context` },
|
|
80180
80285
|
env: {
|
|
80181
80286
|
label: "Env",
|
|
@@ -80195,7 +80300,8 @@ var TYPE_PRESENTATION = {
|
|
|
80195
80300
|
task: {
|
|
80196
80301
|
label: "Task",
|
|
80197
80302
|
renderer: "task-yaml",
|
|
80198
|
-
action: (ref) => `akm show ${ref} -> inspect; akm task run <id> -> run now; edit the file + akm task sync -> unschedule
|
|
80303
|
+
action: (ref) => `akm show ${ref} -> inspect; akm task run <id> -> run now; edit the file + akm task sync -> unschedule`,
|
|
80304
|
+
fragmentRef: false
|
|
80199
80305
|
},
|
|
80200
80306
|
session: {
|
|
80201
80307
|
label: "Session",
|
|
@@ -80210,7 +80316,8 @@ var TYPE_PRESENTATION = {
|
|
|
80210
80316
|
instruction: {
|
|
80211
80317
|
label: "Instruction",
|
|
80212
80318
|
renderer: "knowledge-md",
|
|
80213
|
-
action: (ref) => `akm show ${ref} -> read the project instructions
|
|
80319
|
+
action: (ref) => `akm show ${ref} -> read the project instructions`,
|
|
80320
|
+
fragmentRef: false
|
|
80214
80321
|
}
|
|
80215
80322
|
};
|
|
80216
80323
|
var DEFAULT_PRESENTATION = { label: "Asset" };
|
|
@@ -83136,6 +83243,8 @@ function indexDocumentFromEntry(entry, base3, rendererName) {
|
|
|
83136
83243
|
doc.lessonStrength = entry.lessonStrength;
|
|
83137
83244
|
if (entry.derivedFrom !== undefined)
|
|
83138
83245
|
doc.derivedFrom = entry.derivedFrom;
|
|
83246
|
+
if (hasMarkdownFragmentContent(entry))
|
|
83247
|
+
setMarkdownFragmentContent(doc, getMarkdownFragmentContent(entry));
|
|
83139
83248
|
return doc;
|
|
83140
83249
|
}
|
|
83141
83250
|
function conceptIdForRecognizedType(root, filePath, type) {
|
|
@@ -92674,8 +92783,8 @@ init_warn();
|
|
|
92674
92783
|
init_write_provenance();
|
|
92675
92784
|
|
|
92676
92785
|
// src/indexer/index-written-assets.ts
|
|
92677
|
-
import
|
|
92678
|
-
import
|
|
92786
|
+
import fs48 from "node:fs";
|
|
92787
|
+
import path59 from "node:path";
|
|
92679
92788
|
init_errors();
|
|
92680
92789
|
init_paths();
|
|
92681
92790
|
init_warn();
|
|
@@ -92686,7 +92795,7 @@ init_paths();
|
|
|
92686
92795
|
init_warn();
|
|
92687
92796
|
|
|
92688
92797
|
// src/storage/repositories/index-entry-schema.ts
|
|
92689
|
-
var CANONICAL_INDEX_DB_VERSION =
|
|
92798
|
+
var CANONICAL_INDEX_DB_VERSION = 23;
|
|
92690
92799
|
var CANONICAL_ENTRY_SCHEMA_FINGERPRINT = {
|
|
92691
92800
|
tableSql: "CREATE TABLE entries ( id INTEGER PRIMARY KEY AUTOINCREMENT, item_ref TEXT NOT NULL UNIQUE, bundle_id TEXT NOT NULL, component_id TEXT NOT NULL, concept_id TEXT NOT NULL, adapter_id TEXT NOT NULL, type TEXT NOT NULL, file_path TEXT NOT NULL, content_hash TEXT, document_json TEXT NOT NULL, search_text TEXT NOT NULL, derived_from TEXT )",
|
|
92692
92801
|
sqliteSequenceTable: true,
|
|
@@ -92836,7 +92945,12 @@ var CANONICAL_ENTRY_SCHEMA_FINGERPRINT = {
|
|
|
92836
92945
|
{ sequence: 1, cid: -1, name: null, descending: 0, collation: "BINARY", key: 0 }
|
|
92837
92946
|
]
|
|
92838
92947
|
}
|
|
92839
|
-
]
|
|
92948
|
+
],
|
|
92949
|
+
searchSurfaces: {
|
|
92950
|
+
entriesFtsSql: "CREATE VIRTUAL TABLE entries_fts USING fts5( entry_id UNINDEXED, name, description, tags, hints, content, tokenize='porter unicode61' )",
|
|
92951
|
+
fragmentSourceSql: "CREATE TABLE entry_fragments ( entry_id INTEGER PRIMARY KEY REFERENCES entries(id) ON DELETE CASCADE, safe_markdown TEXT NOT NULL )",
|
|
92952
|
+
fragmentsFtsSql: "CREATE VIRTUAL TABLE entry_fragments_fts USING fts5( entry_id UNINDEXED, fragment_id UNINDEXED, fragment_ordinal UNINDEXED, content, tokenize='porter unicode61' )"
|
|
92953
|
+
}
|
|
92840
92954
|
};
|
|
92841
92955
|
function sqlString(value) {
|
|
92842
92956
|
return `'${value.replaceAll("'", "''")}'`;
|
|
@@ -92846,8 +92960,11 @@ function normalizeSchemaSql(value) {
|
|
|
92846
92960
|
return null;
|
|
92847
92961
|
return value.replace(/\s+/g, " ").trim();
|
|
92848
92962
|
}
|
|
92963
|
+
function readNamedTableSql(db, name) {
|
|
92964
|
+
const row = db.prepare(`SELECT sql FROM sqlite_master WHERE type = 'table' AND name = ${sqlString(name)}`).get();
|
|
92965
|
+
return normalizeSchemaSql(row?.sql);
|
|
92966
|
+
}
|
|
92849
92967
|
function readEntrySchemaFingerprint(db) {
|
|
92850
|
-
const tableRow = db.prepare("SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'entries'").get();
|
|
92851
92968
|
const sqliteSequenceTable = db.prepare("SELECT 1 AS present FROM sqlite_master WHERE type = 'table' AND name = 'sqlite_sequence'").get() != null;
|
|
92852
92969
|
const maxId = Number(db.prepare("SELECT COALESCE(MAX(id), 0) AS maxId FROM entries").get().maxId);
|
|
92853
92970
|
const sequenceRow = sqliteSequenceTable ? db.prepare("SELECT seq FROM sqlite_sequence WHERE name = 'entries'").get() : undefined;
|
|
@@ -92876,11 +92993,16 @@ function readEntrySchemaFingerprint(db) {
|
|
|
92876
92993
|
}))
|
|
92877
92994
|
})).sort((left, right) => left.name.localeCompare(right.name));
|
|
92878
92995
|
return {
|
|
92879
|
-
tableSql:
|
|
92996
|
+
tableSql: readNamedTableSql(db, "entries"),
|
|
92880
92997
|
sqliteSequenceTable,
|
|
92881
92998
|
sqliteSequenceValid,
|
|
92882
92999
|
columns,
|
|
92883
|
-
indexes
|
|
93000
|
+
indexes,
|
|
93001
|
+
searchSurfaces: {
|
|
93002
|
+
entriesFtsSql: readNamedTableSql(db, "entries_fts"),
|
|
93003
|
+
fragmentSourceSql: readNamedTableSql(db, "entry_fragments"),
|
|
93004
|
+
fragmentsFtsSql: readNamedTableSql(db, "entry_fragments_fts")
|
|
93005
|
+
}
|
|
92884
93006
|
};
|
|
92885
93007
|
}
|
|
92886
93008
|
function hasCanonicalEntrySchema(db) {
|
|
@@ -93083,20 +93205,30 @@ function openExistingDatabase(dbPath) {
|
|
|
93083
93205
|
if (classifyPathAccess(resolvedPath).access === "absent") {
|
|
93084
93206
|
throw new Error(`Index database not found at ${resolvedPath}. Run 'akm index' to build it.`);
|
|
93085
93207
|
}
|
|
93086
|
-
|
|
93208
|
+
const db = openManagedDatabase({
|
|
93087
93209
|
path: resolvedPath,
|
|
93088
|
-
init: (
|
|
93089
|
-
loadVecExtension(
|
|
93090
|
-
warnIfNonCanonicalIndexGeneration(db, resolvedPath);
|
|
93210
|
+
init: (db2) => {
|
|
93211
|
+
loadVecExtension(db2);
|
|
93091
93212
|
},
|
|
93092
93213
|
create: false
|
|
93093
93214
|
});
|
|
93215
|
+
try {
|
|
93216
|
+
assertCanonicalIndexGeneration(db, resolvedPath);
|
|
93217
|
+
return db;
|
|
93218
|
+
} catch (error2) {
|
|
93219
|
+
db.close();
|
|
93220
|
+
throw error2;
|
|
93221
|
+
}
|
|
93094
93222
|
}
|
|
93095
|
-
function
|
|
93223
|
+
function assertCanonicalIndexGeneration(db, resolvedPath) {
|
|
93096
93224
|
if (isCanonicalIndexGeneration(db))
|
|
93097
93225
|
return;
|
|
93098
93226
|
const classification = classifyIndexGeneration(db);
|
|
93099
|
-
|
|
93227
|
+
const stored = classification.storedVersion ?? "unknown";
|
|
93228
|
+
if (classification.status === "newer") {
|
|
93229
|
+
throw new ConfigError(`Index database at ${resolvedPath} was built by a newer akm (stored generation ${stored}; ` + `this binary understands ${CANONICAL_INDEX_DB_VERSION}). Upgrade akm to use this index.`, "INDEX_SCHEMA_INCOMPATIBLE", "Upgrade akm to a version that understands this index generation.");
|
|
93230
|
+
}
|
|
93231
|
+
throw new ConfigError(`Index database at ${resolvedPath} is not usable with this akm's derived schema (stored generation ${stored}; ` + `this binary understands ${CANONICAL_INDEX_DB_VERSION}). Run 'akm index' to rebuild it.`, "INDEX_SCHEMA_INCOMPATIBLE", "Run `akm index` to rebuild the derived index from the currently materialized sources.");
|
|
93100
93232
|
}
|
|
93101
93233
|
function assertIndexPathReadable(resolvedPath) {
|
|
93102
93234
|
const { access, code } = classifyPathAccess(resolvedPath);
|
|
@@ -93113,6 +93245,7 @@ import fs40 from "node:fs";
|
|
|
93113
93245
|
init_asset_ref();
|
|
93114
93246
|
init_resolve_ref();
|
|
93115
93247
|
init_warn();
|
|
93248
|
+
init_metadata();
|
|
93116
93249
|
|
|
93117
93250
|
// src/indexer/search/search-fields.ts
|
|
93118
93251
|
function buildSearchFields(entry) {
|
|
@@ -93176,9 +93309,129 @@ function buildSearchText(entry) {
|
|
|
93176
93309
|
// src/storage/repositories/index-entry-mapper.ts
|
|
93177
93310
|
init_warn();
|
|
93178
93311
|
|
|
93312
|
+
// src/core/asset/markdown-fragments.ts
|
|
93313
|
+
init_markdown();
|
|
93314
|
+
import { createHash as createHash9 } from "node:crypto";
|
|
93315
|
+
var MARKDOWN_FRAGMENT_MAX_CHARS = 1600;
|
|
93316
|
+
var MARKDOWN_FRAGMENT_PREFIX = "akm-fragment-";
|
|
93317
|
+
function hash3(text) {
|
|
93318
|
+
return createHash9("sha256").update(text).digest("hex");
|
|
93319
|
+
}
|
|
93320
|
+
function uniqueSlugs(body) {
|
|
93321
|
+
const out = new Map;
|
|
93322
|
+
const seen = new Set;
|
|
93323
|
+
for (const heading of parseMarkdownToc(body).headings) {
|
|
93324
|
+
const base3 = markdownHeadingSlug(heading.text);
|
|
93325
|
+
if (!base3)
|
|
93326
|
+
continue;
|
|
93327
|
+
let slug = base3;
|
|
93328
|
+
for (let suffix = 1;seen.has(slug); suffix++)
|
|
93329
|
+
slug = `${base3}-${suffix}`;
|
|
93330
|
+
seen.add(slug);
|
|
93331
|
+
out.set(heading.line, slug);
|
|
93332
|
+
}
|
|
93333
|
+
return out;
|
|
93334
|
+
}
|
|
93335
|
+
function textOf(lines) {
|
|
93336
|
+
return lines.join(`
|
|
93337
|
+
`).trim();
|
|
93338
|
+
}
|
|
93339
|
+
function splitPiece(piece, maxChars) {
|
|
93340
|
+
if (textOf(piece.lines).length <= maxChars)
|
|
93341
|
+
return [piece];
|
|
93342
|
+
const pieces = [];
|
|
93343
|
+
let start = 0;
|
|
93344
|
+
while (start < piece.lines.length) {
|
|
93345
|
+
let end = start;
|
|
93346
|
+
let chars = 0;
|
|
93347
|
+
while (end < piece.lines.length) {
|
|
93348
|
+
const next = piece.lines[end];
|
|
93349
|
+
if (end === start && next.length > maxChars)
|
|
93350
|
+
break;
|
|
93351
|
+
if (end > start && chars + next.length + 1 > maxChars)
|
|
93352
|
+
break;
|
|
93353
|
+
chars += next.length + (end > start ? 1 : 0);
|
|
93354
|
+
end++;
|
|
93355
|
+
}
|
|
93356
|
+
if (end === start) {
|
|
93357
|
+
const line = piece.lines[start];
|
|
93358
|
+
let offset = 0;
|
|
93359
|
+
while (offset < line.length) {
|
|
93360
|
+
let cut = Math.min(offset + maxChars, line.length);
|
|
93361
|
+
if (cut < line.length) {
|
|
93362
|
+
const space = line.lastIndexOf(" ", cut);
|
|
93363
|
+
if (space > offset + Math.floor(maxChars * 0.55))
|
|
93364
|
+
cut = space;
|
|
93365
|
+
}
|
|
93366
|
+
pieces.push({ lines: [line.slice(offset, cut).trim()], startLine: piece.startLine + start });
|
|
93367
|
+
offset = cut;
|
|
93368
|
+
while (line[offset] === " ")
|
|
93369
|
+
offset++;
|
|
93370
|
+
}
|
|
93371
|
+
start++;
|
|
93372
|
+
continue;
|
|
93373
|
+
}
|
|
93374
|
+
let preferred = -1;
|
|
93375
|
+
for (let i = start + 1;i < end; i++)
|
|
93376
|
+
if (!piece.lines[i].trim())
|
|
93377
|
+
preferred = i;
|
|
93378
|
+
if (preferred > start)
|
|
93379
|
+
end = preferred;
|
|
93380
|
+
pieces.push({ lines: piece.lines.slice(start, end), startLine: piece.startLine + start });
|
|
93381
|
+
start = end;
|
|
93382
|
+
while (start < piece.lines.length && !piece.lines[start].trim())
|
|
93383
|
+
start++;
|
|
93384
|
+
}
|
|
93385
|
+
return pieces.filter((candidate) => textOf(candidate.lines));
|
|
93386
|
+
}
|
|
93387
|
+
function splitMarkdownFragmentStats(body, maxChars = MARKDOWN_FRAGMENT_MAX_CHARS) {
|
|
93388
|
+
const lines = body.split(/\r?\n/);
|
|
93389
|
+
const headings = parseMarkdownToc(body).headings;
|
|
93390
|
+
const boundaries = [1, ...headings.map((heading) => heading.line), lines.length + 1].filter((line, index, all) => index === 0 || line !== all[index - 1]).sort((left, right) => left - right);
|
|
93391
|
+
const slugs = uniqueSlugs(body);
|
|
93392
|
+
const pieces = [];
|
|
93393
|
+
let sectionCount = 0;
|
|
93394
|
+
for (let i = 0;i < boundaries.length - 1; i++) {
|
|
93395
|
+
const startLine = boundaries[i];
|
|
93396
|
+
const end = boundaries[i + 1] - 1;
|
|
93397
|
+
const section = { lines: lines.slice(startLine - 1, end), startLine, headingSlug: slugs.get(startLine) };
|
|
93398
|
+
if (textOf(section.lines)) {
|
|
93399
|
+
sectionCount++;
|
|
93400
|
+
pieces.push(...splitPiece(section, maxChars));
|
|
93401
|
+
}
|
|
93402
|
+
}
|
|
93403
|
+
const piecesPerHeading = new Map;
|
|
93404
|
+
for (const piece of pieces) {
|
|
93405
|
+
if (piece.headingSlug)
|
|
93406
|
+
piecesPerHeading.set(piece.headingSlug, (piecesPerHeading.get(piece.headingSlug) ?? 0) + 1);
|
|
93407
|
+
}
|
|
93408
|
+
const fragments = pieces.map((piece, ordinal) => {
|
|
93409
|
+
const text = textOf(piece.lines);
|
|
93410
|
+
const contentLines = piece.lines.map((line, index) => ({ line, index })).filter(({ line }) => line.trim());
|
|
93411
|
+
const first = contentLines[0]?.index ?? 0;
|
|
93412
|
+
const last = contentLines.at(-1)?.index ?? 0;
|
|
93413
|
+
const digest = hash3(text);
|
|
93414
|
+
const unsplitHeading = piece.headingSlug && piecesPerHeading.get(piece.headingSlug) === 1;
|
|
93415
|
+
return {
|
|
93416
|
+
fragmentId: `${MARKDOWN_FRAGMENT_PREFIX}${ordinal + 1}-${digest.slice(0, 12)}`,
|
|
93417
|
+
ordinal,
|
|
93418
|
+
startLine: piece.startLine + first,
|
|
93419
|
+
endLine: piece.startLine + last,
|
|
93420
|
+
...unsplitHeading ? { headingSlug: piece.headingSlug } : {},
|
|
93421
|
+
text,
|
|
93422
|
+
hash: digest
|
|
93423
|
+
};
|
|
93424
|
+
});
|
|
93425
|
+
return { fragments, hardSplitCount: Math.max(0, pieces.length - sectionCount) };
|
|
93426
|
+
}
|
|
93427
|
+
function splitMarkdownFragments(body, maxChars = MARKDOWN_FRAGMENT_MAX_CHARS) {
|
|
93428
|
+
return splitMarkdownFragmentStats(body, maxChars).fragments;
|
|
93429
|
+
}
|
|
93430
|
+
|
|
93179
93431
|
// src/storage/repositories/index-fts-repository.ts
|
|
93180
93432
|
init_warn();
|
|
93181
93433
|
var INSERT_FTS_SQL = "INSERT INTO entries_fts (entry_id, name, description, tags, hints, content) VALUES (?, ?, ?, ?, ?, ?)";
|
|
93434
|
+
var INSERT_FRAGMENT_SQL = "INSERT INTO entry_fragments_fts (entry_id, fragment_id, fragment_ordinal, content) VALUES (?, ?, ?, ?)";
|
|
93182
93435
|
var ftsMutationStatementsByDb = new WeakMap;
|
|
93183
93436
|
function getFtsMutationStatements(db) {
|
|
93184
93437
|
const existing = ftsMutationStatementsByDb.get(db);
|
|
@@ -93186,22 +93439,39 @@ function getFtsMutationStatements(db) {
|
|
|
93186
93439
|
return existing;
|
|
93187
93440
|
const statements = {
|
|
93188
93441
|
deleteOne: db.prepare("DELETE FROM entries_fts WHERE entry_id = ?"),
|
|
93189
|
-
insert: db.prepare(INSERT_FTS_SQL)
|
|
93442
|
+
insert: db.prepare(INSERT_FTS_SQL),
|
|
93443
|
+
deleteFragments: db.prepare("DELETE FROM entry_fragments_fts WHERE entry_id = ?"),
|
|
93444
|
+
upsertFragmentSource: db.prepare("INSERT INTO entry_fragments (entry_id, safe_markdown) VALUES (?, ?) ON CONFLICT(entry_id) DO UPDATE SET safe_markdown = excluded.safe_markdown"),
|
|
93445
|
+
deleteFragmentSource: db.prepare("DELETE FROM entry_fragments WHERE entry_id = ?"),
|
|
93446
|
+
insertFragment: db.prepare(INSERT_FRAGMENT_SQL)
|
|
93190
93447
|
};
|
|
93191
93448
|
ftsMutationStatementsByDb.set(db, statements);
|
|
93192
93449
|
return statements;
|
|
93193
93450
|
}
|
|
93194
|
-
function replaceFtsEntry(db, entryId, entry) {
|
|
93451
|
+
function replaceFtsEntry(db, entryId, entry, fragmentContent) {
|
|
93195
93452
|
const fields = buildSearchFields(entry);
|
|
93196
93453
|
const statements = getFtsMutationStatements(db);
|
|
93197
93454
|
statements.deleteOne.run(entryId);
|
|
93198
93455
|
statements.insert.run(entryId, fields.name, fields.description, fields.tags, fields.hints, fields.content);
|
|
93456
|
+
if (fragmentContent === undefined) {
|
|
93457
|
+
return;
|
|
93458
|
+
}
|
|
93459
|
+
statements.deleteFragments.run(entryId);
|
|
93460
|
+
statements.deleteFragmentSource.run(entryId);
|
|
93461
|
+
if (!fragmentContent)
|
|
93462
|
+
return;
|
|
93463
|
+
statements.upsertFragmentSource.run(entryId, fragmentContent);
|
|
93464
|
+
for (const fragment of splitMarkdownFragments(fragmentContent)) {
|
|
93465
|
+
statements.insertFragment.run(entryId, fragment.fragmentId, fragment.ordinal, fragment.text.toLowerCase());
|
|
93466
|
+
}
|
|
93199
93467
|
}
|
|
93200
93468
|
function deleteFtsEntries(db, entryIds) {
|
|
93201
93469
|
for (let i = 0;i < entryIds.length; i += SQLITE_CHUNK_SIZE) {
|
|
93202
93470
|
const chunk = entryIds.slice(i, i + SQLITE_CHUNK_SIZE);
|
|
93203
93471
|
const placeholders = chunk.map(() => "?").join(",");
|
|
93204
93472
|
db.prepare(`DELETE FROM entries_fts WHERE entry_id IN (${placeholders})`).run(...chunk);
|
|
93473
|
+
db.prepare(`DELETE FROM entry_fragments_fts WHERE entry_id IN (${placeholders})`).run(...chunk);
|
|
93474
|
+
db.prepare(`DELETE FROM entry_fragments WHERE entry_id IN (${placeholders})`).run(...chunk);
|
|
93205
93475
|
}
|
|
93206
93476
|
}
|
|
93207
93477
|
|
|
@@ -93216,7 +93486,7 @@ function upsertEntry(db, filePath, entry, searchText, provenance, contentHash) {
|
|
|
93216
93486
|
throw new Error("upsertEntry: item_ref not found after upsert");
|
|
93217
93487
|
if (previous?.id === result.id && previous.search_text !== searchText)
|
|
93218
93488
|
deleteEntryVectors(db, result.id);
|
|
93219
|
-
replaceFtsEntry(db, result.id, entry);
|
|
93489
|
+
replaceFtsEntry(db, result.id, entry, hasMarkdownFragmentContent(entry) ? getMarkdownFragmentContent(entry) ?? null : undefined);
|
|
93220
93490
|
return result.id;
|
|
93221
93491
|
};
|
|
93222
93492
|
return db.transaction(apply)();
|
|
@@ -93712,6 +93982,127 @@ function redactSensitiveText(text, sensitiveValues) {
|
|
|
93712
93982
|
|
|
93713
93983
|
// src/llm/embedders/remote.ts
|
|
93714
93984
|
init_warn();
|
|
93985
|
+
|
|
93986
|
+
// src/sources/snapshot-fetchers/secret-seam.ts
|
|
93987
|
+
import fs45 from "node:fs";
|
|
93988
|
+
|
|
93989
|
+
// src/core/env-secret-ref.ts
|
|
93990
|
+
import fs43 from "node:fs";
|
|
93991
|
+
import path54 from "node:path";
|
|
93992
|
+
|
|
93993
|
+
// src/registry/origin-resolve.ts
|
|
93994
|
+
init_asset_ref();
|
|
93995
|
+
function resolveSourcesForOrigin(origin, allSources) {
|
|
93996
|
+
if (!origin)
|
|
93997
|
+
return allSources;
|
|
93998
|
+
const installations = deriveInstallations(allSources);
|
|
93999
|
+
return allSources.filter((_, index) => installations[index]?.id === origin);
|
|
94000
|
+
}
|
|
94001
|
+
|
|
94002
|
+
// src/core/asset/asset-create.ts
|
|
94003
|
+
init_errors();
|
|
94004
|
+
function normalizeCreateSubPath(subPath) {
|
|
94005
|
+
if (subPath === undefined)
|
|
94006
|
+
return "";
|
|
94007
|
+
const trimmed = subPath.trim().replace(/\\/g, "/").replace(/^\/+|\/+$/g, "");
|
|
94008
|
+
if (!trimmed)
|
|
94009
|
+
return "";
|
|
94010
|
+
if (trimmed.split("/").some((segment) => !segment || segment === "." || segment === "..")) {
|
|
94011
|
+
throw new UsageError("--path must be a relative directory without '.' or '..' segments.");
|
|
94012
|
+
}
|
|
94013
|
+
return trimmed;
|
|
94014
|
+
}
|
|
94015
|
+
function assertFlatAssetName(name) {
|
|
94016
|
+
if (name?.replace(/\\/g, "/").replace(/\.md$/i, "").includes("/")) {
|
|
94017
|
+
throw new UsageError("Asset --name must be a flat name without '/'. Use --path to choose a subdirectory " + "(e.g. --path personal --name grocery-list).");
|
|
94018
|
+
}
|
|
94019
|
+
}
|
|
94020
|
+
function combineCreatePath(subPath, baseName) {
|
|
94021
|
+
return subPath ? `${subPath}/${baseName}` : baseName;
|
|
94022
|
+
}
|
|
94023
|
+
|
|
94024
|
+
// src/core/env-secret-ref.ts
|
|
94025
|
+
init_asset_placement();
|
|
94026
|
+
init_resolve_ref();
|
|
94027
|
+
init_common();
|
|
94028
|
+
init_errors();
|
|
94029
|
+
function assertNotRemovedVaultRef(ref) {
|
|
94030
|
+
const boundary = ref.indexOf("//");
|
|
94031
|
+
const bare = boundary >= 0 ? ref.slice(boundary + 2) : ref;
|
|
94032
|
+
if (/^vault[:/]/.test(bare.trim())) {
|
|
94033
|
+
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");
|
|
94034
|
+
}
|
|
94035
|
+
}
|
|
94036
|
+
function assertNotColonRef(ref, aliases, replacement) {
|
|
94037
|
+
const boundary = ref.indexOf("//");
|
|
94038
|
+
const bare = (boundary >= 0 ? ref.slice(boundary + 2) : ref).trim();
|
|
94039
|
+
const colon = bare.indexOf(":");
|
|
94040
|
+
if (colon <= 0)
|
|
94041
|
+
return;
|
|
94042
|
+
const head = bare.slice(0, colon).toLowerCase();
|
|
94043
|
+
if (!aliases.includes(head))
|
|
94044
|
+
return;
|
|
94045
|
+
const name = bare.slice(colon + 1);
|
|
94046
|
+
throw new UsageError(`The \`${head}:\` ref spelling was removed in 0.9.0 — use the slash form instead: \`${replacement}${name}\`.`, "INVALID_FLAG_VALUE");
|
|
94047
|
+
}
|
|
94048
|
+
function findEnvSource(origin, type, name) {
|
|
94049
|
+
const sources = resolveSourceEntries(undefined, loadConfig());
|
|
94050
|
+
if (sources.length === 0) {
|
|
94051
|
+
throw new UsageError("No bundles configured. Run `akm bundle create` to create your working bundle.");
|
|
94052
|
+
}
|
|
94053
|
+
const candidates = origin ? resolveSourcesForOrigin(origin, sources) : sources;
|
|
94054
|
+
const typeDir = type === "env" ? "env" : "secrets";
|
|
94055
|
+
const member = candidates.find((source) => fs43.existsSync(assetPathForName(type, path54.join(source.path, typeDir), name)));
|
|
94056
|
+
if (member)
|
|
94057
|
+
return member;
|
|
94058
|
+
if (!origin) {
|
|
94059
|
+
const fallback = candidates[0];
|
|
94060
|
+
if (fallback)
|
|
94061
|
+
return fallback;
|
|
94062
|
+
throw new UsageError("No bundles configured. Run `akm bundle create` to create your working bundle.");
|
|
94063
|
+
}
|
|
94064
|
+
const named = candidates[0];
|
|
94065
|
+
if (!named) {
|
|
94066
|
+
throw new NotFoundError(`Source not found for origin: ${origin}`);
|
|
94067
|
+
}
|
|
94068
|
+
return named;
|
|
94069
|
+
}
|
|
94070
|
+
function parseSecretRef(ref) {
|
|
94071
|
+
assertNotRemovedVaultRef(ref);
|
|
94072
|
+
assertNotColonRef(ref, ["secret", "secrets"], "secrets/");
|
|
94073
|
+
return parseRefInput(isFullRefInput(ref) ? ref : `secrets/${ref}`);
|
|
94074
|
+
}
|
|
94075
|
+
function resolveSecretPath(ref, create) {
|
|
94076
|
+
const parsed = parseSecretRef(ref);
|
|
94077
|
+
if (parsed.type !== "secret") {
|
|
94078
|
+
throw new UsageError(`Expected a secret ref (secrets/<name>); got "${ref}".`);
|
|
94079
|
+
}
|
|
94080
|
+
if (create) {
|
|
94081
|
+
assertFlatAssetName(parsed.name);
|
|
94082
|
+
parsed.name = combineCreatePath(normalizeCreateSubPath(create.subPath), parsed.name);
|
|
94083
|
+
}
|
|
94084
|
+
const source = findEnvSource(parsed.origin, "secret", parsed.name);
|
|
94085
|
+
const typeRoot = path54.join(source.path, "secrets");
|
|
94086
|
+
const absPath = assetPathForName("secret", typeRoot, parsed.name);
|
|
94087
|
+
if (!isWithin(absPath, typeRoot)) {
|
|
94088
|
+
throw new UsageError(`Secret name "${parsed.name}" escapes the secrets directory.`);
|
|
94089
|
+
}
|
|
94090
|
+
return { name: parsed.name, absPath, source };
|
|
94091
|
+
}
|
|
94092
|
+
|
|
94093
|
+
// src/sources/snapshot-fetchers/secret-seam.ts
|
|
94094
|
+
function resolveSecretFromStore(ref) {
|
|
94095
|
+
try {
|
|
94096
|
+
const { absPath } = resolveSecretPath(ref);
|
|
94097
|
+
if (!fs45.existsSync(absPath))
|
|
94098
|
+
return null;
|
|
94099
|
+
return fs45.readFileSync(absPath, "utf8").trim() || null;
|
|
94100
|
+
} catch {
|
|
94101
|
+
return null;
|
|
94102
|
+
}
|
|
94103
|
+
}
|
|
94104
|
+
|
|
94105
|
+
// src/llm/embedders/remote.ts
|
|
93715
94106
|
var DEFAULT_REMOTE_BATCH_SIZE = 100;
|
|
93716
94107
|
var DEFAULT_TOKEN_BUDGET = 8000;
|
|
93717
94108
|
function estimateTokenCount(text) {
|
|
@@ -93867,14 +94258,14 @@ class RemoteEmbedder {
|
|
|
93867
94258
|
}
|
|
93868
94259
|
buildHeaders() {
|
|
93869
94260
|
const headers = { "Content-Type": "application/json" };
|
|
93870
|
-
const resolvedKey = resolveSecret(this.config.apiKey);
|
|
94261
|
+
const resolvedKey = resolveSecret(this.config.apiKey, resolveSecretFromStore);
|
|
93871
94262
|
if (resolvedKey) {
|
|
93872
94263
|
headers.Authorization = `Bearer ${resolvedKey}`;
|
|
93873
94264
|
}
|
|
93874
94265
|
return headers;
|
|
93875
94266
|
}
|
|
93876
94267
|
safeErrorBody(body) {
|
|
93877
|
-
const resolvedKey = resolveSecret(this.config.apiKey);
|
|
94268
|
+
const resolvedKey = resolveSecret(this.config.apiKey, resolveSecretFromStore);
|
|
93878
94269
|
return redactSensitiveText(redactErrorBody(body), resolvedKey ? [resolvedKey] : []);
|
|
93879
94270
|
}
|
|
93880
94271
|
}
|
|
@@ -94109,8 +94500,11 @@ function publishTargetedEmbeddingMeta(db, config) {
|
|
|
94109
94500
|
setMeta(db, "hasEmbeddings", ready ? "1" : "0");
|
|
94110
94501
|
}
|
|
94111
94502
|
|
|
94503
|
+
// src/indexer/index-written-assets.ts
|
|
94504
|
+
init_metadata();
|
|
94505
|
+
|
|
94112
94506
|
// src/indexer/scan/drain-dir.ts
|
|
94113
|
-
import
|
|
94507
|
+
import path58 from "node:path";
|
|
94114
94508
|
init_common();
|
|
94115
94509
|
init_recognition_util();
|
|
94116
94510
|
|
|
@@ -94119,8 +94513,8 @@ init_common();
|
|
|
94119
94513
|
init_errors();
|
|
94120
94514
|
init_recognition_util();
|
|
94121
94515
|
init_warn();
|
|
94122
|
-
import
|
|
94123
|
-
import
|
|
94516
|
+
import fs46 from "node:fs";
|
|
94517
|
+
import path55 from "node:path";
|
|
94124
94518
|
|
|
94125
94519
|
class WorkflowSourceRejectionError extends UsageError {
|
|
94126
94520
|
sourcePaths;
|
|
@@ -94160,63 +94554,67 @@ class WorkflowSourcePathIdentityError extends WorkflowSourceRejectionError {
|
|
|
94160
94554
|
function workflowNameForSourcePath(sourceRoot, adapterId, sourcePath) {
|
|
94161
94555
|
if (adapterId !== "akm" && adapterId !== "akm-workflow")
|
|
94162
94556
|
return;
|
|
94163
|
-
const relativePath = toPosix(
|
|
94557
|
+
const relativePath = toPosix(path55.relative(path55.resolve(sourceRoot), path55.resolve(sourcePath)));
|
|
94164
94558
|
if (!isSafeRelativeName(relativePath))
|
|
94165
94559
|
return;
|
|
94166
94560
|
const ownedPath = adapterId === "akm" ? relativePath.replace(/^workflows\//, "") : relativePath;
|
|
94167
94561
|
if (adapterId === "akm" && ownedPath === relativePath)
|
|
94168
94562
|
return;
|
|
94169
|
-
const extension =
|
|
94563
|
+
const extension = path55.posix.extname(ownedPath);
|
|
94170
94564
|
if (!WORKFLOW_EXTENSIONS.includes(extension.toLowerCase()))
|
|
94171
94565
|
return;
|
|
94172
94566
|
return ownedPath;
|
|
94173
94567
|
}
|
|
94174
|
-
function
|
|
94568
|
+
function resolveWorkflowSourceDomains(sourceRoot, adapterId, sourcePaths) {
|
|
94175
94569
|
if (adapterId !== "akm" && adapterId !== "akm-workflow")
|
|
94176
94570
|
return [];
|
|
94177
|
-
const
|
|
94178
|
-
if (!isSafeRelativeName(canonicalName)) {
|
|
94179
|
-
throw new UsageError("Workflow ref resolves outside the bundle root.", "PATH_ESCAPE_VIOLATION");
|
|
94180
|
-
}
|
|
94571
|
+
const authoredRoot = path55.resolve(sourceRoot);
|
|
94181
94572
|
let realRoot;
|
|
94182
|
-
const authoredRoot = path54.resolve(sourceRoot);
|
|
94183
94573
|
try {
|
|
94184
|
-
realRoot =
|
|
94574
|
+
realRoot = fs46.realpathSync(authoredRoot);
|
|
94185
94575
|
} catch {
|
|
94186
94576
|
return [];
|
|
94187
94577
|
}
|
|
94188
|
-
const
|
|
94189
|
-
const
|
|
94190
|
-
|
|
94191
|
-
|
|
94192
|
-
|
|
94193
|
-
let entries;
|
|
94194
|
-
try {
|
|
94195
|
-
entries = fs43.readdirSync(parent, { withFileTypes: true });
|
|
94196
|
-
} catch {
|
|
94197
|
-
return [];
|
|
94198
|
-
}
|
|
94199
|
-
const basename = path54.basename(canonicalName);
|
|
94200
|
-
const candidates = [];
|
|
94201
|
-
for (const entry of entries) {
|
|
94202
|
-
if (!entry.isFile() && !entry.isSymbolicLink())
|
|
94578
|
+
const candidatesByName = new Map;
|
|
94579
|
+
const seenAuthoredPaths = new Set;
|
|
94580
|
+
for (const sourcePath of sourcePaths) {
|
|
94581
|
+
const normalizedSourcePath = path55.resolve(sourcePath);
|
|
94582
|
+
if (seenAuthoredPaths.has(normalizedSourcePath))
|
|
94203
94583
|
continue;
|
|
94204
|
-
|
|
94584
|
+
seenAuthoredPaths.add(normalizedSourcePath);
|
|
94585
|
+
const authoredName = workflowNameForSourcePath(authoredRoot, adapterId, normalizedSourcePath);
|
|
94586
|
+
if (authoredName === undefined)
|
|
94587
|
+
continue;
|
|
94588
|
+
const canonicalName = canonicalizeWorkflowName(authoredName);
|
|
94589
|
+
if (!isSafeRelativeName(canonicalName))
|
|
94590
|
+
continue;
|
|
94591
|
+
const extension = path55.extname(normalizedSourcePath);
|
|
94205
94592
|
const lowerExtension = extension.toLowerCase();
|
|
94206
94593
|
if (!WORKFLOW_EXTENSIONS.includes(lowerExtension))
|
|
94207
94594
|
continue;
|
|
94208
|
-
|
|
94209
|
-
|
|
94210
|
-
|
|
94211
|
-
candidates.push({
|
|
94212
|
-
path: candidatePath,
|
|
94213
|
-
relativePath: toPosix(path54.relative(authoredRoot, candidatePath)),
|
|
94595
|
+
const candidate = {
|
|
94596
|
+
path: normalizedSourcePath,
|
|
94597
|
+
relativePath: toPosix(path55.relative(authoredRoot, normalizedSourcePath)),
|
|
94214
94598
|
lowerExtension,
|
|
94215
|
-
extensionlessStem:
|
|
94599
|
+
extensionlessStem: path55.basename(normalizedSourcePath).slice(0, -extension.length)
|
|
94600
|
+
};
|
|
94601
|
+
const domain = candidatesByName.get(canonicalName) ?? [];
|
|
94602
|
+
domain.push(candidate);
|
|
94603
|
+
candidatesByName.set(canonicalName, domain);
|
|
94604
|
+
}
|
|
94605
|
+
const resolutions = [];
|
|
94606
|
+
for (const canonicalName of [...candidatesByName.keys()].sort(compareCodePoints)) {
|
|
94607
|
+
const candidates = candidatesByName.get(canonicalName) ?? [];
|
|
94608
|
+
candidates.sort((left, right) => compareCodePoints(left.relativePath, right.relativePath));
|
|
94609
|
+
const sources = inspectWorkflowSourceDomain(candidates, canonicalName, realRoot);
|
|
94610
|
+
const sourcePaths2 = candidates.map((candidate) => candidate.relativePath);
|
|
94611
|
+
resolutions.push({
|
|
94612
|
+
canonicalName,
|
|
94613
|
+
sourcePaths: sourcePaths2,
|
|
94614
|
+
source: pickWorkflowSource(adapterId, canonicalName, sources)
|
|
94216
94615
|
});
|
|
94217
94616
|
}
|
|
94218
|
-
|
|
94219
|
-
return inspectWorkflowSourceDomain(candidates, canonicalName, realRoot);
|
|
94617
|
+
return resolutions;
|
|
94220
94618
|
}
|
|
94221
94619
|
function inspectWorkflowSourceDomain(candidates, canonicalName, realRoot) {
|
|
94222
94620
|
const sources = [];
|
|
@@ -94245,7 +94643,7 @@ function inspectWorkflowSourceCandidate(candidate, canonicalName, realRoot) {
|
|
|
94245
94643
|
const issues = [];
|
|
94246
94644
|
let authoredStat;
|
|
94247
94645
|
try {
|
|
94248
|
-
authoredStat =
|
|
94646
|
+
authoredStat = fs46.lstatSync(candidate.path);
|
|
94249
94647
|
} catch {
|
|
94250
94648
|
issues.push(new WorkflowSourceLinkResolutionError(candidate.relativePath));
|
|
94251
94649
|
return { issues };
|
|
@@ -94257,21 +94655,21 @@ function inspectWorkflowSourceCandidate(candidate, canonicalName, realRoot) {
|
|
|
94257
94655
|
}
|
|
94258
94656
|
let realPath;
|
|
94259
94657
|
try {
|
|
94260
|
-
realPath =
|
|
94658
|
+
realPath = fs46.realpathSync(candidate.path);
|
|
94261
94659
|
} catch {
|
|
94262
94660
|
issues.push(new WorkflowSourceLinkResolutionError(candidate.relativePath));
|
|
94263
94661
|
return { issues };
|
|
94264
94662
|
}
|
|
94265
|
-
const targetPath = toPosix(
|
|
94663
|
+
const targetPath = toPosix(path55.relative(realRoot, realPath));
|
|
94266
94664
|
const contained2 = isWithinResolved(realPath, realRoot);
|
|
94267
94665
|
if (!contained2)
|
|
94268
94666
|
issues.push(new WorkflowSourcePathIdentityError(candidate.relativePath, targetPath));
|
|
94269
|
-
if (isLink &&
|
|
94667
|
+
if (isLink && path55.extname(realPath).toLowerCase() !== candidate.lowerExtension) {
|
|
94270
94668
|
issues.push(new WorkflowSourceLinkIdentityError(candidate.relativePath, targetPath));
|
|
94271
94669
|
}
|
|
94272
94670
|
if (contained2) {
|
|
94273
94671
|
try {
|
|
94274
|
-
if (!
|
|
94672
|
+
if (!fs46.statSync(realPath).isFile())
|
|
94275
94673
|
issues.push(new WorkflowSourceLinkResolutionError(candidate.relativePath));
|
|
94276
94674
|
} catch {
|
|
94277
94675
|
issues.push(new WorkflowSourceLinkResolutionError(candidate.relativePath));
|
|
@@ -94290,20 +94688,12 @@ function inspectWorkflowSourceCandidate(candidate, canonicalName, realRoot) {
|
|
|
94290
94688
|
}
|
|
94291
94689
|
};
|
|
94292
94690
|
}
|
|
94293
|
-
function resolveUniqueWorkflowSource(sourceRoot, adapterId, name) {
|
|
94294
|
-
const sources = listWorkflowSourceFiles(sourceRoot, adapterId, name);
|
|
94295
|
-
const canonicalName = sources[0]?.canonicalName ?? canonicalizeWorkflowName(normalizeName2(name));
|
|
94296
|
-
return pickWorkflowSource(adapterId, canonicalName, sources);
|
|
94297
|
-
}
|
|
94298
|
-
function normalizeName2(name) {
|
|
94299
|
-
return name.replaceAll("\\", "/");
|
|
94300
|
-
}
|
|
94301
94691
|
function isSafeRelativeName(name) {
|
|
94302
|
-
return name.length > 0 && !
|
|
94692
|
+
return name.length > 0 && !path55.posix.isAbsolute(name) && name !== ".." && !name.startsWith("../") && path55.posix.normalize(name) === name;
|
|
94303
94693
|
}
|
|
94304
94694
|
function isWithinResolved(candidate, root) {
|
|
94305
|
-
const relative =
|
|
94306
|
-
return relative === "" || !relative.startsWith("..") && !
|
|
94695
|
+
const relative = path55.relative(root, path55.resolve(candidate));
|
|
94696
|
+
return relative === "" || !relative.startsWith("..") && !path55.isAbsolute(relative);
|
|
94307
94697
|
}
|
|
94308
94698
|
|
|
94309
94699
|
// src/indexer/scan/drain-dir.ts
|
|
@@ -94312,13 +94702,14 @@ init_metadata();
|
|
|
94312
94702
|
init_file_context();
|
|
94313
94703
|
|
|
94314
94704
|
// src/indexer/scan/doc-to-entry.ts
|
|
94315
|
-
|
|
94705
|
+
init_metadata();
|
|
94706
|
+
import path57 from "node:path";
|
|
94316
94707
|
function indexDocumentToStashEntry(doc) {
|
|
94317
94708
|
const dj = doc.documentJson ?? {};
|
|
94318
94709
|
const entry = {
|
|
94319
94710
|
name: doc.name,
|
|
94320
94711
|
type: doc.type,
|
|
94321
|
-
filename:
|
|
94712
|
+
filename: path57.basename(doc.path ?? "")
|
|
94322
94713
|
};
|
|
94323
94714
|
if (doc.description !== undefined)
|
|
94324
94715
|
entry.description = doc.description;
|
|
@@ -94328,6 +94719,8 @@ function indexDocumentToStashEntry(doc) {
|
|
|
94328
94719
|
entry.content = doc.content;
|
|
94329
94720
|
if (doc.contentTruncated !== undefined)
|
|
94330
94721
|
entry.contentTruncated = doc.contentTruncated;
|
|
94722
|
+
if (hasMarkdownFragmentContent(doc))
|
|
94723
|
+
setMarkdownFragmentContent(entry, getMarkdownFragmentContent(doc));
|
|
94331
94724
|
if (doc.ownsPresentation !== undefined)
|
|
94332
94725
|
entry.ownsPresentation = doc.ownsPresentation;
|
|
94333
94726
|
if (doc.updated !== undefined)
|
|
@@ -94421,31 +94814,28 @@ function drainDirDocuments(adapter, component, fileContexts) {
|
|
|
94421
94814
|
const conceptIdByFile = new Map;
|
|
94422
94815
|
const rejectedPaths = new Set;
|
|
94423
94816
|
const rejectedConceptIds = new Set;
|
|
94424
|
-
const
|
|
94425
|
-
|
|
94817
|
+
const workflowOwnerPathByCanonicalName = new Map(resolveWorkflowSourceDomains(component.root, adapter.id, fileContexts.map((file) => file.absPath)).filter((resolution) => resolution.source !== undefined).map((resolution) => [resolution.canonicalName, path58.resolve(resolution.source.path)]));
|
|
94818
|
+
const invalidWorkflowOwnerNames = new Set;
|
|
94819
|
+
const orderedFileContexts = [...fileContexts].sort((left, right) => {
|
|
94820
|
+
const leftName = workflowNameForSourcePath(component.root, adapter.id, left.absPath);
|
|
94821
|
+
const rightName = workflowNameForSourcePath(component.root, adapter.id, right.absPath);
|
|
94822
|
+
const leftOwner = leftName !== undefined && workflowOwnerPathByCanonicalName.get(canonicalizeWorkflowName(leftName)) === path58.resolve(left.absPath);
|
|
94823
|
+
const rightOwner = rightName !== undefined && workflowOwnerPathByCanonicalName.get(canonicalizeWorkflowName(rightName)) === path58.resolve(right.absPath);
|
|
94824
|
+
if (leftOwner !== rightOwner)
|
|
94825
|
+
return leftOwner ? -1 : 1;
|
|
94826
|
+
return compareCodePoints(left.absPath, right.absPath);
|
|
94827
|
+
});
|
|
94828
|
+
for (const file of orderedFileContexts) {
|
|
94829
|
+
if (rejectedPaths.has(file.absPath))
|
|
94830
|
+
continue;
|
|
94426
94831
|
const workflowName = workflowNameForSourcePath(component.root, adapter.id, file.absPath);
|
|
94427
94832
|
if (workflowName !== undefined) {
|
|
94428
94833
|
const canonicalName = canonicalizeWorkflowName(workflowName);
|
|
94429
|
-
|
|
94430
|
-
|
|
94431
|
-
|
|
94432
|
-
}
|
|
94433
|
-
for (const [canonicalName, workflowName] of [...workflowLookups].sort(([left], [right]) => compareCodePoints(left, right))) {
|
|
94434
|
-
try {
|
|
94435
|
-
resolveUniqueWorkflowSource(component.root, adapter.id, workflowName);
|
|
94436
|
-
} catch (error2) {
|
|
94437
|
-
if (!(error2 instanceof WorkflowSourceRejectionError))
|
|
94438
|
-
throw error2;
|
|
94439
|
-
rejectedConceptIds.add(adapter.id === "akm" ? `workflows/${canonicalName}` : canonicalName);
|
|
94440
|
-
for (const relativePath of error2.sourcePaths) {
|
|
94441
|
-
rejectedPaths.add(path57.join(component.root, relativePath));
|
|
94834
|
+
const ownerPath = workflowOwnerPathByCanonicalName.get(canonicalName);
|
|
94835
|
+
if (ownerPath !== undefined && ownerPath !== path58.resolve(file.absPath) && !invalidWorkflowOwnerNames.has(canonicalName)) {
|
|
94836
|
+
continue;
|
|
94442
94837
|
}
|
|
94443
|
-
warnings.push(error2.message);
|
|
94444
94838
|
}
|
|
94445
|
-
}
|
|
94446
|
-
for (const file of fileContexts) {
|
|
94447
|
-
if (rejectedPaths.has(file.absPath))
|
|
94448
|
-
continue;
|
|
94449
94839
|
const doc = adapter.recognize(component, file);
|
|
94450
94840
|
if (doc === null)
|
|
94451
94841
|
continue;
|
|
@@ -94457,6 +94847,8 @@ function drainDirDocuments(adapter, component, fileContexts) {
|
|
|
94457
94847
|
const dropWarning = handleWorkflowDoc(doc, file, component.root);
|
|
94458
94848
|
if (dropWarning !== null) {
|
|
94459
94849
|
warnings.push(dropWarning);
|
|
94850
|
+
if (workflowName !== undefined)
|
|
94851
|
+
invalidWorkflowOwnerNames.add(canonicalizeWorkflowName(workflowName));
|
|
94460
94852
|
continue;
|
|
94461
94853
|
}
|
|
94462
94854
|
if (doc.hash !== undefined)
|
|
@@ -94500,7 +94892,7 @@ async function indexWrittenAssets(stashDir, filePaths, options = {}) {
|
|
|
94500
94892
|
if (isPathAbsent(dbPath))
|
|
94501
94893
|
return true;
|
|
94502
94894
|
const files = filePaths.filter((f) => {
|
|
94503
|
-
const rel =
|
|
94895
|
+
const rel = path59.relative(stashDir, f);
|
|
94504
94896
|
return !rel.split(/[\\/]+/).some((segment) => segment.startsWith("."));
|
|
94505
94897
|
});
|
|
94506
94898
|
if (files.length === 0)
|
|
@@ -94514,10 +94906,10 @@ async function indexWrittenAssets(stashDir, filePaths, options = {}) {
|
|
|
94514
94906
|
const unindexable = new Set;
|
|
94515
94907
|
const rejectedConceptIds = new Set;
|
|
94516
94908
|
for (const file of files) {
|
|
94517
|
-
if (!
|
|
94909
|
+
if (!fs48.existsSync(file)) {
|
|
94518
94910
|
let authoredDanglingSymlink = false;
|
|
94519
94911
|
try {
|
|
94520
|
-
authoredDanglingSymlink =
|
|
94912
|
+
authoredDanglingSymlink = fs48.lstatSync(file).isSymbolicLink();
|
|
94521
94913
|
} catch {}
|
|
94522
94914
|
if (!authoredDanglingSymlink) {
|
|
94523
94915
|
unindexable.add(file);
|
|
@@ -94568,7 +94960,10 @@ async function indexWrittenAssets(stashDir, filePaths, options = {}) {
|
|
|
94568
94960
|
for (const { file, entry, conceptId, contentHash } of pairs) {
|
|
94569
94961
|
let entryWithSize = entry;
|
|
94570
94962
|
try {
|
|
94571
|
-
entryWithSize = { ...entry, fileSize:
|
|
94963
|
+
entryWithSize = { ...entry, fileSize: fs48.statSync(file).size };
|
|
94964
|
+
if (hasMarkdownFragmentContent(entry)) {
|
|
94965
|
+
setMarkdownFragmentContent(entryWithSize, getMarkdownFragmentContent(entry));
|
|
94966
|
+
}
|
|
94572
94967
|
} catch {}
|
|
94573
94968
|
const provenance = deriveEntryProvenance({ bundleId: component.id, componentId: component.id, adapterId: component.adapter }, entry.type, entry.name, conceptId);
|
|
94574
94969
|
const supersededIds = db.prepare("SELECT id FROM entries WHERE file_path = ? AND item_ref <> ?").all(file, provenance.itemRef);
|
|
@@ -94601,7 +94996,7 @@ async function indexWrittenAssets(stashDir, filePaths, options = {}) {
|
|
|
94601
94996
|
init_asset_placement();
|
|
94602
94997
|
init_asset_ref();
|
|
94603
94998
|
init_warn();
|
|
94604
|
-
import
|
|
94999
|
+
import path60 from "node:path";
|
|
94605
95000
|
function changesToStored(changes) {
|
|
94606
95001
|
return changes.map((c, i) => ({
|
|
94607
95002
|
path: c.path,
|
|
@@ -94654,10 +95049,10 @@ function currentProposalTarget(value) {
|
|
|
94654
95049
|
if (typeof value !== "object" || value === null)
|
|
94655
95050
|
throw new Error("Proposal metadata has an invalid proposedTarget.");
|
|
94656
95051
|
const target = value;
|
|
94657
|
-
if (typeof target.source !== "string" || !isBundleSlug(target.source) || typeof target.root !== "string" || !
|
|
95052
|
+
if (typeof target.source !== "string" || !isBundleSlug(target.source) || typeof target.root !== "string" || !path60.isAbsolute(target.root)) {
|
|
94658
95053
|
throw new Error("Proposal metadata has an invalid proposedTarget.");
|
|
94659
95054
|
}
|
|
94660
|
-
return { source: target.source, root:
|
|
95055
|
+
return { source: target.source, root: path60.resolve(target.root) };
|
|
94661
95056
|
}
|
|
94662
95057
|
function invalidPresentField(name) {
|
|
94663
95058
|
throw new Error(`Proposal metadata has an invalid ${name}.`);
|
|
@@ -94697,7 +95092,7 @@ function validatePresentMetadata(meta) {
|
|
|
94697
95092
|
}
|
|
94698
95093
|
if (Object.hasOwn(meta, "acceptedTarget")) {
|
|
94699
95094
|
const target = meta.acceptedTarget;
|
|
94700
|
-
if (typeof target !== "object" || target === null || typeof target.source !== "string" || !isBundleSlug(target.source) || typeof target.root !== "string" || !
|
|
95095
|
+
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
95096
|
invalidPresentField("acceptedTarget");
|
|
94702
95097
|
}
|
|
94703
95098
|
}
|
|
@@ -95428,15 +95823,15 @@ var PROPOSAL_TXN_PHASES = [
|
|
|
95428
95823
|
"committed"
|
|
95429
95824
|
];
|
|
95430
95825
|
function proposalHash(content) {
|
|
95431
|
-
return
|
|
95826
|
+
return createHash10("sha256").update(content).digest("hex");
|
|
95432
95827
|
}
|
|
95433
95828
|
function proposalFileHash(filePath) {
|
|
95434
|
-
return proposalHash(
|
|
95829
|
+
return proposalHash(fs49.readFileSync(filePath));
|
|
95435
95830
|
}
|
|
95436
95831
|
function sameProposalFile(left, right) {
|
|
95437
95832
|
try {
|
|
95438
|
-
const leftStat =
|
|
95439
|
-
const rightStat =
|
|
95833
|
+
const leftStat = fs49.statSync(left);
|
|
95834
|
+
const rightStat = fs49.statSync(right);
|
|
95440
95835
|
return leftStat.dev === rightStat.dev && leftStat.ino === rightStat.ino;
|
|
95441
95836
|
} catch {
|
|
95442
95837
|
return false;
|
|
@@ -95445,20 +95840,20 @@ function sameProposalFile(left, right) {
|
|
|
95445
95840
|
function cleanupProposalPublication(p) {
|
|
95446
95841
|
for (const filePath of [p.publishPath, p.displacedPath]) {
|
|
95447
95842
|
try {
|
|
95448
|
-
|
|
95843
|
+
fs49.rmSync(filePath, { force: true });
|
|
95449
95844
|
} catch (error2) {
|
|
95450
95845
|
warn(`[proposals] transaction publication cleanup failed at ${filePath}: ${error2 instanceof Error ? error2.message : String(error2)}`);
|
|
95451
95846
|
}
|
|
95452
95847
|
}
|
|
95453
|
-
fsyncTxnDir(
|
|
95848
|
+
fsyncTxnDir(path61.dirname(p.assetPath));
|
|
95454
95849
|
}
|
|
95455
95850
|
function rollbackPreparedProposalTransaction(txn) {
|
|
95456
95851
|
const p = txn.journal.payload;
|
|
95457
|
-
const currentHash =
|
|
95458
|
-
if (!
|
|
95852
|
+
const currentHash = fs49.existsSync(p.assetPath) ? proposalFileHash(p.assetPath) : null;
|
|
95853
|
+
if (!fs49.existsSync(p.displacedPath)) {
|
|
95459
95854
|
if (p.originalHash === null) {
|
|
95460
95855
|
if (currentHash === p.publishedHash && sameProposalFile(p.assetPath, p.publishPath)) {
|
|
95461
|
-
|
|
95856
|
+
fs49.unlinkSync(p.assetPath);
|
|
95462
95857
|
recordWrittenPath(p.assetPath);
|
|
95463
95858
|
} else if (currentHash !== null) {
|
|
95464
95859
|
throw new Error(`Cannot roll back proposal transaction: target was created externally.`);
|
|
@@ -95470,30 +95865,30 @@ function rollbackPreparedProposalTransaction(txn) {
|
|
|
95470
95865
|
return;
|
|
95471
95866
|
}
|
|
95472
95867
|
if (currentHash === p.publishedHash) {
|
|
95473
|
-
|
|
95868
|
+
fs49.unlinkSync(p.assetPath);
|
|
95474
95869
|
recordWrittenPath(p.assetPath);
|
|
95475
95870
|
} else if (currentHash !== null && currentHash !== p.originalHash) {
|
|
95476
95871
|
throw new Error(`Cannot roll back proposal transaction: ${p.assetPath} diverged.`);
|
|
95477
95872
|
}
|
|
95478
|
-
if (
|
|
95479
|
-
if (
|
|
95873
|
+
if (fs49.existsSync(p.displacedPath)) {
|
|
95874
|
+
if (fs49.existsSync(p.assetPath)) {
|
|
95480
95875
|
throw new Error(`Cannot restore proposal backup: ${p.assetPath} is occupied.`);
|
|
95481
95876
|
}
|
|
95482
|
-
|
|
95877
|
+
fs49.linkSync(p.displacedPath, p.assetPath);
|
|
95483
95878
|
recordWrittenPath(p.assetPath);
|
|
95484
95879
|
}
|
|
95485
95880
|
cleanupProposalPublication(p);
|
|
95486
95881
|
}
|
|
95487
95882
|
function validatePublishedProposal(p) {
|
|
95488
|
-
if (!
|
|
95883
|
+
if (!fs49.existsSync(p.assetPath) || proposalFileHash(p.assetPath) !== p.publishedHash) {
|
|
95489
95884
|
throw new Error(`Cannot recover proposal ${p.proposalId}: published asset diverged.`);
|
|
95490
95885
|
}
|
|
95491
95886
|
}
|
|
95492
95887
|
function persistProposalTransactionState(txn, proposal, ctx) {
|
|
95493
95888
|
const p = txn.journal.payload;
|
|
95494
95889
|
const decidedAt = txn.journal.decidedAt;
|
|
95495
|
-
const backupContent = p.backupPath ?
|
|
95496
|
-
const publishedContent =
|
|
95890
|
+
const backupContent = p.backupPath ? fs49.readFileSync(p.backupPath, "utf8") : undefined;
|
|
95891
|
+
const publishedContent = fs49.readFileSync(p.contentPath, "utf8");
|
|
95497
95892
|
return withProposalsDb(p.stashDir, ctx, (db) => withImmediateTransaction(db, () => {
|
|
95498
95893
|
const current = requireProposal(db, p.stashDir, p.proposalId);
|
|
95499
95894
|
if (p.operation === "accept") {
|
|
@@ -95511,7 +95906,7 @@ function persistProposalTransactionState(txn, proposal, ctx) {
|
|
|
95511
95906
|
payload: { ...proposal.payload, content: publishedContent },
|
|
95512
95907
|
changes: [
|
|
95513
95908
|
{
|
|
95514
|
-
path:
|
|
95909
|
+
path: path61.relative(txn.journal.root, p.assetPath),
|
|
95515
95910
|
op: p.originalHash === null ? "create" : "update",
|
|
95516
95911
|
after: publishedContent
|
|
95517
95912
|
}
|
|
@@ -95582,7 +95977,7 @@ async function finalizeProposalTransaction(txn, target, proposal, ctx) {
|
|
|
95582
95977
|
cleanupProposalPublication(p);
|
|
95583
95978
|
if (txn.journal.phase === "asset-published") {
|
|
95584
95979
|
const commitRoot = target.source.repoPath ?? target.source.path;
|
|
95585
|
-
const commitPath =
|
|
95980
|
+
const commitPath = path61.relative(commitRoot, p.assetPath).replaceAll(path61.sep, "/");
|
|
95586
95981
|
publishWriteTargetTransaction(target, p.gitPublication, {
|
|
95587
95982
|
transactionId: txn.journal.transactionId,
|
|
95588
95983
|
message: `${p.operation === "accept" ? "Update" : "Revert"} ${p.ref}`,
|
|
@@ -95619,8 +96014,8 @@ async function finalizeProposalTransaction(txn, target, proposal, ctx) {
|
|
|
95619
96014
|
function fenceProposalTxnJournal(journal, txnDir, root) {
|
|
95620
96015
|
const p = journal.payload;
|
|
95621
96016
|
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 ${
|
|
96017
|
+
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))) {
|
|
96018
|
+
throw new Error(`Refusing unsafe proposal transaction journal at ${path61.join(txnDir, "journal.json")}.`);
|
|
95624
96019
|
}
|
|
95625
96020
|
}
|
|
95626
96021
|
function resolveProposalRecoveryTarget(config, journal) {
|
|
@@ -95720,8 +96115,8 @@ async function recoverStaleTxns(stashDir) {
|
|
|
95720
96115
|
}
|
|
95721
96116
|
|
|
95722
96117
|
// scripts/akm-migrate/migrate/writer-relocation.ts
|
|
95723
|
-
import
|
|
95724
|
-
import
|
|
96118
|
+
import fs50 from "node:fs";
|
|
96119
|
+
import path62 from "node:path";
|
|
95725
96120
|
init_paths();
|
|
95726
96121
|
function relocationSpecs(stashDir) {
|
|
95727
96122
|
return [
|
|
@@ -95741,7 +96136,7 @@ function mutexSiblingName(lockName) {
|
|
|
95741
96136
|
function fileCountIfExists(dir) {
|
|
95742
96137
|
let entries;
|
|
95743
96138
|
try {
|
|
95744
|
-
entries =
|
|
96139
|
+
entries = fs50.readdirSync(dir, { withFileTypes: true });
|
|
95745
96140
|
} catch {
|
|
95746
96141
|
return;
|
|
95747
96142
|
}
|
|
@@ -95749,7 +96144,7 @@ function fileCountIfExists(dir) {
|
|
|
95749
96144
|
}
|
|
95750
96145
|
function statFileIfExists(filePath) {
|
|
95751
96146
|
try {
|
|
95752
|
-
const stat =
|
|
96147
|
+
const stat = fs50.statSync(filePath);
|
|
95753
96148
|
return stat.isFile() ? stat : undefined;
|
|
95754
96149
|
} catch {
|
|
95755
96150
|
return;
|
|
@@ -95759,8 +96154,8 @@ function classifyLockArtifacts(akmDir) {
|
|
|
95759
96154
|
const removable = [];
|
|
95760
96155
|
const skipped = [];
|
|
95761
96156
|
for (const lockName of LOCK_NAMES) {
|
|
95762
|
-
const lockPath =
|
|
95763
|
-
const mutexPath =
|
|
96157
|
+
const lockPath = path62.join(akmDir, lockName);
|
|
96158
|
+
const mutexPath = path62.join(akmDir, mutexSiblingName(lockName));
|
|
95764
96159
|
const lockStat = statFileIfExists(lockPath);
|
|
95765
96160
|
const mutexStat = statFileIfExists(mutexPath);
|
|
95766
96161
|
if (!lockStat) {
|
|
@@ -95786,11 +96181,11 @@ function classifyLockArtifacts(akmDir) {
|
|
|
95786
96181
|
return { removable, skipped };
|
|
95787
96182
|
}
|
|
95788
96183
|
function findWriterRelocationEntries(stashDir) {
|
|
95789
|
-
const akmDir =
|
|
96184
|
+
const akmDir = path62.join(stashDir, ".akm");
|
|
95790
96185
|
const directories = [];
|
|
95791
96186
|
for (const spec of relocationSpecs(stashDir)) {
|
|
95792
96187
|
const relativeParts = Array.isArray(spec.oldRelative) ? spec.oldRelative : [spec.oldRelative];
|
|
95793
|
-
const oldPath =
|
|
96188
|
+
const oldPath = path62.join(akmDir, ...relativeParts);
|
|
95794
96189
|
const fileCount = fileCountIfExists(oldPath);
|
|
95795
96190
|
if (fileCount === undefined || fileCount === 0)
|
|
95796
96191
|
continue;
|
|
@@ -95801,36 +96196,36 @@ function findWriterRelocationEntries(stashDir) {
|
|
|
95801
96196
|
}
|
|
95802
96197
|
function moveFile(oldFilePath, newFilePath) {
|
|
95803
96198
|
try {
|
|
95804
|
-
|
|
96199
|
+
fs50.renameSync(oldFilePath, newFilePath);
|
|
95805
96200
|
} catch (error2) {
|
|
95806
96201
|
if (error2.code !== "EXDEV")
|
|
95807
96202
|
throw error2;
|
|
95808
|
-
|
|
95809
|
-
|
|
96203
|
+
fs50.copyFileSync(oldFilePath, newFilePath);
|
|
96204
|
+
fs50.rmSync(oldFilePath, { force: true });
|
|
95810
96205
|
}
|
|
95811
96206
|
}
|
|
95812
96207
|
function moveDirectoryContents(entry) {
|
|
95813
96208
|
const errors3 = [];
|
|
95814
96209
|
let moved = 0;
|
|
95815
|
-
|
|
96210
|
+
fs50.mkdirSync(entry.newPath, { recursive: true });
|
|
95816
96211
|
let names;
|
|
95817
96212
|
try {
|
|
95818
|
-
names =
|
|
96213
|
+
names = fs50.readdirSync(entry.oldPath).sort();
|
|
95819
96214
|
} catch {
|
|
95820
96215
|
return { key: entry.key, oldPath: entry.oldPath, newPath: entry.newPath, moved: 0, errors: [] };
|
|
95821
96216
|
}
|
|
95822
96217
|
for (const name of names) {
|
|
95823
|
-
const oldFilePath =
|
|
95824
|
-
const newFilePath =
|
|
96218
|
+
const oldFilePath = path62.join(entry.oldPath, name);
|
|
96219
|
+
const newFilePath = path62.join(entry.newPath, name);
|
|
95825
96220
|
let oldStat;
|
|
95826
96221
|
try {
|
|
95827
|
-
oldStat =
|
|
96222
|
+
oldStat = fs50.lstatSync(oldFilePath);
|
|
95828
96223
|
} catch {
|
|
95829
96224
|
continue;
|
|
95830
96225
|
}
|
|
95831
96226
|
if (!oldStat.isFile())
|
|
95832
96227
|
continue;
|
|
95833
|
-
if (
|
|
96228
|
+
if (fs50.existsSync(newFilePath))
|
|
95834
96229
|
continue;
|
|
95835
96230
|
try {
|
|
95836
96231
|
moveFile(oldFilePath, newFilePath);
|
|
@@ -95843,13 +96238,13 @@ function moveDirectoryContents(entry) {
|
|
|
95843
96238
|
}
|
|
95844
96239
|
function removeIfEmptyDir(dir) {
|
|
95845
96240
|
try {
|
|
95846
|
-
if (
|
|
95847
|
-
|
|
96241
|
+
if (fs50.readdirSync(dir).length === 0)
|
|
96242
|
+
fs50.rmdirSync(dir);
|
|
95848
96243
|
} catch {}
|
|
95849
96244
|
}
|
|
95850
96245
|
function removeLockArtifact(entry) {
|
|
95851
96246
|
try {
|
|
95852
|
-
|
|
96247
|
+
fs50.rmSync(entry.path, { force: true });
|
|
95853
96248
|
return { path: entry.path, removed: true };
|
|
95854
96249
|
} catch (error2) {
|
|
95855
96250
|
return { path: entry.path, removed: false, error: error2 instanceof Error ? error2.message : String(error2) };
|
|
@@ -95861,36 +96256,36 @@ function applyWriterRelocation(stashDir) {
|
|
|
95861
96256
|
const lockResults = lockArtifacts.map(removeLockArtifact);
|
|
95862
96257
|
for (const spec of relocationSpecs(stashDir)) {
|
|
95863
96258
|
const relativeParts = Array.isArray(spec.oldRelative) ? spec.oldRelative : [spec.oldRelative];
|
|
95864
|
-
removeIfEmptyDir(
|
|
96259
|
+
removeIfEmptyDir(path62.join(stashDir, ".akm", ...relativeParts));
|
|
95865
96260
|
}
|
|
95866
96261
|
return { directories: directoryResults, lockArtifacts: lockResults, skippedLocks };
|
|
95867
96262
|
}
|
|
95868
96263
|
|
|
95869
96264
|
// scripts/akm-migrate/task-migrate.ts
|
|
95870
96265
|
import { randomUUID as randomUUID7 } from "node:crypto";
|
|
95871
|
-
import
|
|
96266
|
+
import fs56 from "node:fs";
|
|
95872
96267
|
import os5 from "node:os";
|
|
95873
|
-
import
|
|
96268
|
+
import path65 from "node:path";
|
|
95874
96269
|
init_errors();
|
|
95875
96270
|
init_paths();
|
|
95876
96271
|
|
|
95877
96272
|
// scripts/akm-migrate/migrate/task-files-to-v3.ts
|
|
95878
96273
|
init_errors();
|
|
95879
96274
|
import crypto6 from "node:crypto";
|
|
95880
|
-
import
|
|
95881
|
-
import
|
|
96275
|
+
import fs53 from "node:fs";
|
|
96276
|
+
import path63 from "node:path";
|
|
95882
96277
|
|
|
95883
96278
|
// scripts/akm-migrate/migrate/durable-fs.ts
|
|
95884
|
-
import
|
|
96279
|
+
import fs51 from "node:fs";
|
|
95885
96280
|
function fsyncDirectoryPortable(directory) {
|
|
95886
96281
|
if (process.platform === "win32")
|
|
95887
96282
|
return;
|
|
95888
96283
|
try {
|
|
95889
|
-
const fd =
|
|
96284
|
+
const fd = fs51.openSync(directory, "r");
|
|
95890
96285
|
try {
|
|
95891
|
-
|
|
96286
|
+
fs51.fsyncSync(fd);
|
|
95892
96287
|
} finally {
|
|
95893
|
-
|
|
96288
|
+
fs51.closeSync(fd);
|
|
95894
96289
|
}
|
|
95895
96290
|
} catch (cause) {
|
|
95896
96291
|
const code = cause.code;
|
|
@@ -95904,25 +96299,25 @@ function migrationError(detail) {
|
|
|
95904
96299
|
return new ConfigError(`Task migration to v3 failed: ${detail}`, "INVALID_CONFIG_FILE");
|
|
95905
96300
|
}
|
|
95906
96301
|
function contained2(root, candidate) {
|
|
95907
|
-
const relative =
|
|
95908
|
-
return relative === "" || !relative.startsWith("..") && !
|
|
96302
|
+
const relative = path63.relative(root, candidate);
|
|
96303
|
+
return relative === "" || !relative.startsWith("..") && !path63.isAbsolute(relative);
|
|
95909
96304
|
}
|
|
95910
96305
|
function realDirectory(filePath) {
|
|
95911
|
-
const stat =
|
|
96306
|
+
const stat = fs53.lstatSync(filePath);
|
|
95912
96307
|
if (stat.isSymbolicLink() || !stat.isDirectory())
|
|
95913
96308
|
throw migrationError(`${filePath} must be a real directory.`);
|
|
95914
|
-
return
|
|
96309
|
+
return fs53.realpathSync(filePath);
|
|
95915
96310
|
}
|
|
95916
96311
|
function snapshot(filePath) {
|
|
95917
|
-
const stat =
|
|
96312
|
+
const stat = fs53.lstatSync(filePath);
|
|
95918
96313
|
if (stat.isSymbolicLink() || !stat.isFile())
|
|
95919
96314
|
throw migrationError(`${filePath} must be a real file.`);
|
|
95920
|
-
const bytes =
|
|
96315
|
+
const bytes = fs53.readFileSync(filePath);
|
|
95921
96316
|
return Object.freeze({ bytes, mode: stat.mode & 511 });
|
|
95922
96317
|
}
|
|
95923
96318
|
function writable(filePath) {
|
|
95924
96319
|
try {
|
|
95925
|
-
|
|
96320
|
+
fs53.accessSync(filePath, fs53.constants.W_OK);
|
|
95926
96321
|
return true;
|
|
95927
96322
|
} catch {
|
|
95928
96323
|
return false;
|
|
@@ -95935,12 +96330,12 @@ function walkTasks(root, tasksDir, out) {
|
|
|
95935
96330
|
throw migrationError(`${root.root} resolves outside bundle ${root.bundleId}.`);
|
|
95936
96331
|
}
|
|
95937
96332
|
const visit2 = (directory) => {
|
|
95938
|
-
const physicalDirectory =
|
|
96333
|
+
const physicalDirectory = fs53.realpathSync(directory);
|
|
95939
96334
|
if (!contained2(physicalRoot, physicalDirectory)) {
|
|
95940
96335
|
throw migrationError(`${directory} resolves outside bundle ${root.bundleId}.`);
|
|
95941
96336
|
}
|
|
95942
|
-
for (const entry of
|
|
95943
|
-
const candidate =
|
|
96337
|
+
for (const entry of fs53.readdirSync(directory, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
|
|
96338
|
+
const candidate = path63.join(directory, entry.name);
|
|
95944
96339
|
if (entry.isSymbolicLink())
|
|
95945
96340
|
throw migrationError(`task migration does not follow symbolic link ${candidate}.`);
|
|
95946
96341
|
if (entry.isDirectory()) {
|
|
@@ -95950,7 +96345,7 @@ function walkTasks(root, tasksDir, out) {
|
|
|
95950
96345
|
if (!entry.isFile() || !entry.name.endsWith(".yml"))
|
|
95951
96346
|
continue;
|
|
95952
96347
|
const current = snapshot(candidate);
|
|
95953
|
-
const parent =
|
|
96348
|
+
const parent = path63.dirname(candidate);
|
|
95954
96349
|
out.push({
|
|
95955
96350
|
filePath: candidate,
|
|
95956
96351
|
bytes: current.bytes,
|
|
@@ -95966,9 +96361,9 @@ function walkTasks(root, tasksDir, out) {
|
|
|
95966
96361
|
function inspectTaskToV3Files(roots) {
|
|
95967
96362
|
const files = [];
|
|
95968
96363
|
for (const root of [...roots].sort((a, b) => a.bundleId.localeCompare(b.bundleId))) {
|
|
95969
|
-
const tasksDir = root.layout === "akm-task" ? root.root :
|
|
96364
|
+
const tasksDir = root.layout === "akm-task" ? root.root : path63.join(root.root, "tasks");
|
|
95970
96365
|
try {
|
|
95971
|
-
const stat =
|
|
96366
|
+
const stat = fs53.lstatSync(tasksDir);
|
|
95972
96367
|
if (stat.isSymbolicLink())
|
|
95973
96368
|
throw migrationError(`task migration does not follow symbolic link ${tasksDir}.`);
|
|
95974
96369
|
if (!stat.isDirectory())
|
|
@@ -95983,33 +96378,33 @@ function inspectTaskToV3Files(roots) {
|
|
|
95983
96378
|
return files.sort((a, b) => a.filePath.localeCompare(b.filePath));
|
|
95984
96379
|
}
|
|
95985
96380
|
function hashPath(filePath) {
|
|
95986
|
-
return crypto6.createHash("sha256").update(
|
|
96381
|
+
return crypto6.createHash("sha256").update(path63.resolve(filePath)).digest("hex").slice(0, 16);
|
|
95987
96382
|
}
|
|
95988
96383
|
function taskMigrationBackupPath(backupRoot, filePath) {
|
|
95989
|
-
return
|
|
96384
|
+
return path63.join(backupRoot, "files", `${hashPath(filePath)}-${path63.basename(filePath)}`);
|
|
95990
96385
|
}
|
|
95991
96386
|
function writeDurable(filePath, bytes, mode, exclusive = false) {
|
|
95992
|
-
|
|
96387
|
+
fs53.mkdirSync(path63.dirname(filePath), { recursive: true });
|
|
95993
96388
|
const flags = exclusive ? "wx" : "w";
|
|
95994
|
-
const fd =
|
|
96389
|
+
const fd = fs53.openSync(filePath, flags, mode);
|
|
95995
96390
|
try {
|
|
95996
|
-
|
|
95997
|
-
|
|
96391
|
+
fs53.writeFileSync(fd, bytes);
|
|
96392
|
+
fs53.fsyncSync(fd);
|
|
95998
96393
|
} finally {
|
|
95999
|
-
|
|
96394
|
+
fs53.closeSync(fd);
|
|
96000
96395
|
}
|
|
96001
|
-
|
|
96002
|
-
fsyncDirectoryPortable(
|
|
96396
|
+
fs53.chmodSync(filePath, mode);
|
|
96397
|
+
fsyncDirectoryPortable(path63.dirname(filePath));
|
|
96003
96398
|
}
|
|
96004
96399
|
function replaceAtomically(filePath, bytes, mode) {
|
|
96005
|
-
const temporary =
|
|
96400
|
+
const temporary = path63.join(path63.dirname(filePath), `.${path63.basename(filePath)}.migrate-${crypto6.randomUUID()}`);
|
|
96006
96401
|
try {
|
|
96007
96402
|
writeDurable(temporary, bytes, mode, true);
|
|
96008
|
-
|
|
96009
|
-
fsyncDirectoryPortable(
|
|
96403
|
+
fs53.renameSync(temporary, filePath);
|
|
96404
|
+
fsyncDirectoryPortable(path63.dirname(filePath));
|
|
96010
96405
|
} finally {
|
|
96011
96406
|
try {
|
|
96012
|
-
|
|
96407
|
+
fs53.unlinkSync(temporary);
|
|
96013
96408
|
} catch (cause) {
|
|
96014
96409
|
if (cause.code !== "ENOENT")
|
|
96015
96410
|
throw cause;
|
|
@@ -96048,7 +96443,7 @@ function applyTaskToV3MigrationPlan(plan, options) {
|
|
|
96048
96443
|
const current = snapshot(change.filePath);
|
|
96049
96444
|
if (!current.bytes.equals(change.after))
|
|
96050
96445
|
continue;
|
|
96051
|
-
replaceAtomically(change.filePath,
|
|
96446
|
+
replaceAtomically(change.filePath, fs53.readFileSync(taskMigrationBackupPath(options.backupRoot, change.filePath)), change.mode);
|
|
96052
96447
|
}
|
|
96053
96448
|
throw cause;
|
|
96054
96449
|
}
|
|
@@ -96058,31 +96453,31 @@ function applyTaskToV3MigrationPlan(plan, options) {
|
|
|
96058
96453
|
// scripts/akm-migrate/migrate/task-files-to-v4.ts
|
|
96059
96454
|
init_errors();
|
|
96060
96455
|
import crypto7 from "node:crypto";
|
|
96061
|
-
import
|
|
96062
|
-
import
|
|
96456
|
+
import fs55 from "node:fs";
|
|
96457
|
+
import path64 from "node:path";
|
|
96063
96458
|
function migrationError2(detail) {
|
|
96064
96459
|
return new ConfigError(`Task migration to v4 failed: ${detail}`, "INVALID_CONFIG_FILE");
|
|
96065
96460
|
}
|
|
96066
96461
|
function contained3(root, candidate) {
|
|
96067
|
-
const relative =
|
|
96068
|
-
return relative === "" || !relative.startsWith("..") && !
|
|
96462
|
+
const relative = path64.relative(root, candidate);
|
|
96463
|
+
return relative === "" || !relative.startsWith("..") && !path64.isAbsolute(relative);
|
|
96069
96464
|
}
|
|
96070
96465
|
function realDirectory2(filePath) {
|
|
96071
|
-
const stat =
|
|
96466
|
+
const stat = fs55.lstatSync(filePath);
|
|
96072
96467
|
if (stat.isSymbolicLink() || !stat.isDirectory())
|
|
96073
96468
|
throw migrationError2(`${filePath} must be a real directory.`);
|
|
96074
|
-
return
|
|
96469
|
+
return fs55.realpathSync(filePath);
|
|
96075
96470
|
}
|
|
96076
96471
|
function snapshot2(filePath) {
|
|
96077
|
-
const stat =
|
|
96472
|
+
const stat = fs55.lstatSync(filePath);
|
|
96078
96473
|
if (stat.isSymbolicLink() || !stat.isFile())
|
|
96079
96474
|
throw migrationError2(`${filePath} must be a real file.`);
|
|
96080
|
-
const bytes =
|
|
96475
|
+
const bytes = fs55.readFileSync(filePath);
|
|
96081
96476
|
return Object.freeze({ bytes, mode: stat.mode & 511 });
|
|
96082
96477
|
}
|
|
96083
96478
|
function writable2(filePath) {
|
|
96084
96479
|
try {
|
|
96085
|
-
|
|
96480
|
+
fs55.accessSync(filePath, fs55.constants.W_OK);
|
|
96086
96481
|
return true;
|
|
96087
96482
|
} catch {
|
|
96088
96483
|
return false;
|
|
@@ -96095,12 +96490,12 @@ function walkTasks2(root, tasksDir, out) {
|
|
|
96095
96490
|
throw migrationError2(`${root.root} resolves outside bundle ${root.bundleId}.`);
|
|
96096
96491
|
}
|
|
96097
96492
|
const visit2 = (directory) => {
|
|
96098
|
-
const physicalDirectory =
|
|
96493
|
+
const physicalDirectory = fs55.realpathSync(directory);
|
|
96099
96494
|
if (!contained3(physicalRoot, physicalDirectory)) {
|
|
96100
96495
|
throw migrationError2(`${directory} resolves outside bundle ${root.bundleId}.`);
|
|
96101
96496
|
}
|
|
96102
|
-
for (const entry of
|
|
96103
|
-
const candidate =
|
|
96497
|
+
for (const entry of fs55.readdirSync(directory, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
|
|
96498
|
+
const candidate = path64.join(directory, entry.name);
|
|
96104
96499
|
if (entry.isSymbolicLink())
|
|
96105
96500
|
throw migrationError2(`task migration does not follow symbolic link ${candidate}.`);
|
|
96106
96501
|
if (entry.isDirectory()) {
|
|
@@ -96110,7 +96505,7 @@ function walkTasks2(root, tasksDir, out) {
|
|
|
96110
96505
|
if (!entry.isFile() || !entry.name.endsWith(".yml"))
|
|
96111
96506
|
continue;
|
|
96112
96507
|
const current = snapshot2(candidate);
|
|
96113
|
-
const parent =
|
|
96508
|
+
const parent = path64.dirname(candidate);
|
|
96114
96509
|
out.push({
|
|
96115
96510
|
filePath: candidate,
|
|
96116
96511
|
bytes: current.bytes,
|
|
@@ -96126,9 +96521,9 @@ function walkTasks2(root, tasksDir, out) {
|
|
|
96126
96521
|
function inspectTaskToV4Files(roots) {
|
|
96127
96522
|
const files = [];
|
|
96128
96523
|
for (const root of [...roots].sort((a, b) => a.bundleId.localeCompare(b.bundleId))) {
|
|
96129
|
-
const tasksDir = root.layout === "akm-task" ? root.root :
|
|
96524
|
+
const tasksDir = root.layout === "akm-task" ? root.root : path64.join(root.root, "tasks");
|
|
96130
96525
|
try {
|
|
96131
|
-
const stat =
|
|
96526
|
+
const stat = fs55.lstatSync(tasksDir);
|
|
96132
96527
|
if (stat.isSymbolicLink())
|
|
96133
96528
|
throw migrationError2(`task migration does not follow symbolic link ${tasksDir}.`);
|
|
96134
96529
|
if (!stat.isDirectory())
|
|
@@ -96143,33 +96538,33 @@ function inspectTaskToV4Files(roots) {
|
|
|
96143
96538
|
return files.sort((a, b) => a.filePath.localeCompare(b.filePath));
|
|
96144
96539
|
}
|
|
96145
96540
|
function hashPath2(filePath) {
|
|
96146
|
-
return crypto7.createHash("sha256").update(
|
|
96541
|
+
return crypto7.createHash("sha256").update(path64.resolve(filePath)).digest("hex").slice(0, 16);
|
|
96147
96542
|
}
|
|
96148
96543
|
function taskMigrationBackupPathV4(backupRoot, filePath) {
|
|
96149
|
-
return
|
|
96544
|
+
return path64.join(backupRoot, "files", `${hashPath2(filePath)}-${path64.basename(filePath)}`);
|
|
96150
96545
|
}
|
|
96151
96546
|
function writeDurable2(filePath, bytes, mode, exclusive = false) {
|
|
96152
|
-
|
|
96547
|
+
fs55.mkdirSync(path64.dirname(filePath), { recursive: true });
|
|
96153
96548
|
const flags = exclusive ? "wx" : "w";
|
|
96154
|
-
const fd =
|
|
96549
|
+
const fd = fs55.openSync(filePath, flags, mode);
|
|
96155
96550
|
try {
|
|
96156
|
-
|
|
96157
|
-
|
|
96551
|
+
fs55.writeFileSync(fd, bytes);
|
|
96552
|
+
fs55.fsyncSync(fd);
|
|
96158
96553
|
} finally {
|
|
96159
|
-
|
|
96554
|
+
fs55.closeSync(fd);
|
|
96160
96555
|
}
|
|
96161
|
-
|
|
96162
|
-
fsyncDirectoryPortable(
|
|
96556
|
+
fs55.chmodSync(filePath, mode);
|
|
96557
|
+
fsyncDirectoryPortable(path64.dirname(filePath));
|
|
96163
96558
|
}
|
|
96164
96559
|
function replaceAtomically2(filePath, bytes, mode) {
|
|
96165
|
-
const temporary =
|
|
96560
|
+
const temporary = path64.join(path64.dirname(filePath), `.${path64.basename(filePath)}.migrate-${crypto7.randomUUID()}`);
|
|
96166
96561
|
try {
|
|
96167
96562
|
writeDurable2(temporary, bytes, mode, true);
|
|
96168
|
-
|
|
96169
|
-
fsyncDirectoryPortable(
|
|
96563
|
+
fs55.renameSync(temporary, filePath);
|
|
96564
|
+
fsyncDirectoryPortable(path64.dirname(filePath));
|
|
96170
96565
|
} finally {
|
|
96171
96566
|
try {
|
|
96172
|
-
|
|
96567
|
+
fs55.unlinkSync(temporary);
|
|
96173
96568
|
} catch (cause) {
|
|
96174
96569
|
if (cause.code !== "ENOENT")
|
|
96175
96570
|
throw cause;
|
|
@@ -96208,7 +96603,7 @@ function applyTaskToV4MigrationPlan(plan, options) {
|
|
|
96208
96603
|
const current = snapshot2(change.filePath);
|
|
96209
96604
|
if (!current.bytes.equals(change.after))
|
|
96210
96605
|
continue;
|
|
96211
|
-
replaceAtomically2(change.filePath,
|
|
96606
|
+
replaceAtomically2(change.filePath, fs55.readFileSync(taskMigrationBackupPathV4(options.backupRoot, change.filePath)), change.mode);
|
|
96212
96607
|
}
|
|
96213
96608
|
throw cause;
|
|
96214
96609
|
}
|
|
@@ -96220,12 +96615,12 @@ function expandTilde(value) {
|
|
|
96220
96615
|
if (value === "~")
|
|
96221
96616
|
return os5.homedir();
|
|
96222
96617
|
if (value.startsWith("~/") || value.startsWith("~\\"))
|
|
96223
|
-
return
|
|
96618
|
+
return path65.join(os5.homedir(), value.slice(2));
|
|
96224
96619
|
return value;
|
|
96225
96620
|
}
|
|
96226
96621
|
function existingDirectory(target) {
|
|
96227
96622
|
try {
|
|
96228
|
-
return
|
|
96623
|
+
return fs56.statSync(target).isDirectory();
|
|
96229
96624
|
} catch (cause) {
|
|
96230
96625
|
if (cause.code === "ENOENT")
|
|
96231
96626
|
return false;
|
|
@@ -96246,21 +96641,21 @@ function taskRoots(config, resolutionBase = process.cwd()) {
|
|
|
96246
96641
|
const source = sources.get(bundleId);
|
|
96247
96642
|
if (!source)
|
|
96248
96643
|
continue;
|
|
96249
|
-
const configuredRoot = source.type === "filesystem" && source.path ?
|
|
96644
|
+
const configuredRoot = source.type === "filesystem" && source.path ? path65.resolve(resolutionBase, expandTilde(source.path)) : lockContentRootFor(bundleId, source.type);
|
|
96250
96645
|
if (!configuredRoot || !existingDirectory(configuredRoot))
|
|
96251
96646
|
continue;
|
|
96252
|
-
const bundleRoot =
|
|
96647
|
+
const bundleRoot = path65.resolve(configuredRoot);
|
|
96253
96648
|
const component = bundleComponentConfig(bundle);
|
|
96254
|
-
const componentRoot =
|
|
96255
|
-
const relative =
|
|
96256
|
-
if (relative === ".." || relative.startsWith(`..${
|
|
96649
|
+
const componentRoot = path65.resolve(bundleRoot, component?.root ?? ".");
|
|
96650
|
+
const relative = path65.relative(bundleRoot, componentRoot);
|
|
96651
|
+
if (relative === ".." || relative.startsWith(`..${path65.sep}`) || path65.isAbsolute(relative)) {
|
|
96257
96652
|
throw new ConfigError(`Task migration component root ${componentRoot} escapes bundle ${bundleId} at ${bundleRoot}.`, "INVALID_CONFIG_FILE");
|
|
96258
96653
|
}
|
|
96259
96654
|
if (!existingDirectory(componentRoot))
|
|
96260
96655
|
continue;
|
|
96261
96656
|
const adapter = component?.adapter ?? detectAdapterId(componentRoot, "");
|
|
96262
96657
|
if (!component?.adapter && adapter === "") {
|
|
96263
|
-
const flatTasks =
|
|
96658
|
+
const flatTasks = fs56.readdirSync(componentRoot, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".yml")).map((entry) => entry.name).sort();
|
|
96264
96659
|
if (flatTasks.length > 0) {
|
|
96265
96660
|
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
96661
|
}
|
|
@@ -96332,8 +96727,8 @@ function applyTaskV3Migration() {
|
|
|
96332
96727
|
const before = inspectCurrentTaskPlan();
|
|
96333
96728
|
if (before.result.taskV3Migration.changed === 0)
|
|
96334
96729
|
return before.result;
|
|
96335
|
-
const backupRoot =
|
|
96336
|
-
const backupPath =
|
|
96730
|
+
const backupRoot = path65.join(getDataDir(), "backups", "task-v3");
|
|
96731
|
+
const backupPath = path65.join(backupRoot, `${Date.now()}-${randomUUID7()}`);
|
|
96337
96732
|
const applied = applyTaskToV3MigrationPlan(before.plan, { backupRoot: backupPath });
|
|
96338
96733
|
const after = inspectCurrentTaskPlan().result;
|
|
96339
96734
|
if (after.taskV3Migration.changed > 0) {
|
|
@@ -96389,8 +96784,8 @@ function applyTaskV4Migration() {
|
|
|
96389
96784
|
const before = inspectCurrentTaskV4Plan();
|
|
96390
96785
|
if (before.result.taskV4Migration.changed === 0)
|
|
96391
96786
|
return before.result;
|
|
96392
|
-
const backupRoot =
|
|
96393
|
-
const backupPath =
|
|
96787
|
+
const backupRoot = path65.join(getDataDir(), "backups", "task-v4");
|
|
96788
|
+
const backupPath = path65.join(backupRoot, `${Date.now()}-${randomUUID7()}`);
|
|
96394
96789
|
const applied = applyTaskToV4MigrationPlan(before.plan, { backupRoot: backupPath });
|
|
96395
96790
|
const after = inspectCurrentTaskV4Plan().result;
|
|
96396
96791
|
if (after.taskV4Migration.changed > 0) {
|