@c4a/context-cli 0.7.29 → 0.7.34
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/README.md +12 -0
- package/README.zh-CN.md +8 -0
- package/cli.js +380 -259
- package/indexers/contracts/profile-contract.json +245 -245
- package/indexers/release-manifest.json +1 -1
- package/package.json +12 -12
- package/plugins/VERSION +1 -1
- package/plugins/claude/.claude-plugin/plugin.json +1 -1
- package/plugins/claude/commands/context-inspect-search.md +77 -21
- package/plugins/claude/skills/context-inspect-search/SKILL.md +77 -21
- package/plugins/codex/.codex-plugin/plugin.json +2 -2
- package/plugins/codex/skills/context-inspect-search/SKILL.md +77 -21
- package/plugins/cursor/.cursor-plugin/plugin.json +1 -1
- package/plugins/cursor/commands/c4a-context-inspect-search.md +77 -21
- package/plugins/cursor/skills/context-inspect-search/SKILL.md +77 -21
- package/plugins/skills/context-inspect-search/SKILL.md +77 -21
- package/providers/context/manifest.json +11 -11
- package/providers/context/provider.yaml +1 -1
- package/providers/context/resources/dialogue/document-capture.md +8 -0
- package/providers/context/resources/manuals/guides/lark-resources.md +39 -11
- package/providers/context/resources/procedures/document-capture.md +95 -14
- package/providers/context/resources/procedures/source-capture-detailed.md +6 -0
package/cli.js
CHANGED
|
@@ -42637,7 +42637,7 @@ function parseDocumentResourceMaterialization(value, field) {
|
|
|
42637
42637
|
...reason !== undefined ? { reason } : {}
|
|
42638
42638
|
};
|
|
42639
42639
|
});
|
|
42640
|
-
const expectedStatus = items.some((item) => item.status === "failed" && item.required && !isNonBlockingDocumentResourceFailureReasonCode(item.reason_code)) ? "error" : items.some((item) => item.status === "failed") || items.some((item) => item.status === "reference-only" && item.kind === "poll" && item.reason?.includes("absent") === true) ? "warning" : "complete";
|
|
42640
|
+
const expectedStatus = items.some((item) => item.status === "failed" && item.required && !isNonBlockingDocumentResourceFailureReasonCode(item.reason_code)) ? "error" : items.some((item) => item.status === "failed" || item.reason_code === "document.resource.preview") || items.some((item) => item.status === "reference-only" && item.kind === "poll" && item.reason?.includes("absent") === true) ? "warning" : "complete";
|
|
42641
42641
|
if (value.status !== expectedStatus)
|
|
42642
42642
|
throw new TypeError(`${field}.status must be ${expectedStatus} for its items`);
|
|
42643
42643
|
const expected = (status) => {
|
|
@@ -90705,7 +90705,7 @@ function documentSnapshotFidelityState(manifest, captureReport) {
|
|
|
90705
90705
|
],
|
|
90706
90706
|
warnings: [
|
|
90707
90707
|
...report === undefined ? [] : render((issue) => issue.impact === "projection" || issue.severity === "warning"),
|
|
90708
|
-
...(resources?.items ?? []).filter((item) => item.status === "failed" && (!item.required || isNonBlockingDocumentResourceFailureReasonCode(item.reason_code))).map((item) => `${item.reason_code ?? "lark.capture.resource-materialization-warning"}: ${item.kind}: ${item.reason ?? item.locator}`)
|
|
90708
|
+
...(resources?.items ?? []).filter((item) => item.reason_code === "document.resource.preview" || item.status === "failed" && (!item.required || isNonBlockingDocumentResourceFailureReasonCode(item.reason_code))).map((item) => `${item.reason_code ?? "lark.capture.resource-materialization-warning"}: ${item.kind}: ${item.reason ?? item.locator}`)
|
|
90709
90709
|
]
|
|
90710
90710
|
};
|
|
90711
90711
|
}
|
|
@@ -97826,32 +97826,6 @@ var init_larkDocxXml = __esm(() => {
|
|
|
97826
97826
|
]);
|
|
97827
97827
|
});
|
|
97828
97828
|
|
|
97829
|
-
// src/lib/larkImagePolicy.ts
|
|
97830
|
-
function omitLarkImage(resource, policy, items, replacements, mediaType, failure2) {
|
|
97831
|
-
if (resource.kind !== "image" && !mediaType?.startsWith("image/"))
|
|
97832
|
-
return false;
|
|
97833
|
-
const gif = mediaType === "image/gif" || /\.gif$/iu.test(resource.title ?? "") || Object.entries(resource.attributes).some(([key, value]) => ["mime_type", "content_type"].includes(key) && value === "image/gif");
|
|
97834
|
-
if (!failure2 && policy.images !== "reference-only" && !(gif && policy.gifs === "reference-only"))
|
|
97835
|
-
return false;
|
|
97836
|
-
const title2 = (resource.title ?? "image").replace(/[\r\n<>]/gu, " ");
|
|
97837
|
-
replacements.set(resource.locator, `> Image omitted: ${title2}. ${failure2 ? "Resource size limit exceeded." : "Excluded by selected policy."} See the source document. <!-- ${resource.locator} -->`);
|
|
97838
|
-
items.push({
|
|
97839
|
-
kind: resource.kind,
|
|
97840
|
-
locator: resource.locator,
|
|
97841
|
-
status: "reference-only",
|
|
97842
|
-
required: false,
|
|
97843
|
-
asset_paths: [],
|
|
97844
|
-
reason_code: failure2 ? "image-budget-exceeded" : "image-excluded-by-policy",
|
|
97845
|
-
reason: failure2 ?? "Image bytes were not retained; the selected image policy preserves a placeholder and source reference"
|
|
97846
|
-
});
|
|
97847
|
-
return true;
|
|
97848
|
-
}
|
|
97849
|
-
var LarkResourceBudgetError;
|
|
97850
|
-
var init_larkImagePolicy = __esm(() => {
|
|
97851
|
-
LarkResourceBudgetError = class LarkResourceBudgetError extends Error {
|
|
97852
|
-
};
|
|
97853
|
-
});
|
|
97854
|
-
|
|
97855
97829
|
// src/lib/larkResourceCommand.ts
|
|
97856
97830
|
function stableJson(value) {
|
|
97857
97831
|
if (value === undefined)
|
|
@@ -97880,13 +97854,13 @@ function commandError(fallback, detail) {
|
|
|
97880
97854
|
if (detail === undefined)
|
|
97881
97855
|
return new LarkResourceCommandError(fallback);
|
|
97882
97856
|
const message = [detail.message, detail.hint, detail.code].filter((value) => typeof value === "string" || typeof value === "number").map(String).join("; ");
|
|
97883
|
-
return new LarkResourceCommandError(message.length > 0 ? message : stableJson(detail), typeof detail.type === "string" ? detail.type : undefined, typeof detail.subtype === "string" ? detail.subtype : undefined);
|
|
97857
|
+
return new LarkResourceCommandError(message.length > 0 ? message : stableJson(detail), typeof detail.type === "string" ? detail.type : undefined, typeof detail.subtype === "string" ? detail.subtype : undefined, typeof detail.code === "string" || typeof detail.code === "number" ? detail.code : undefined, typeof detail.log_id === "string" ? detail.log_id : undefined);
|
|
97884
97858
|
}
|
|
97885
97859
|
async function runLarkResourceCommand(runner2, args, options) {
|
|
97886
97860
|
const result = await runner2(args, options);
|
|
97887
97861
|
if (result.exitCode !== 0) {
|
|
97888
97862
|
const fallback = result.stderr.trim() || `lark-cli ${args.slice(0, 2).join(" ")} failed with exit code ${result.exitCode ?? "unknown"}`;
|
|
97889
|
-
throw commandError(fallback, errorDetail(result.stderr));
|
|
97863
|
+
throw commandError(fallback, errorDetail(result.stderr) ?? errorDetail(result.stdout));
|
|
97890
97864
|
}
|
|
97891
97865
|
const trimmed = result.stdout.trim();
|
|
97892
97866
|
if (!trimmed.startsWith("{"))
|
|
@@ -97906,24 +97880,78 @@ async function runLarkResourceCommand(runner2, args, options) {
|
|
|
97906
97880
|
}
|
|
97907
97881
|
return result.stdout;
|
|
97908
97882
|
}
|
|
97883
|
+
function isLarkResourcePermissionDenied(error) {
|
|
97884
|
+
return error instanceof LarkResourceCommandError && (String(error.code) === "403" || error.errorType === "authorization" && ["permission_denied", "access_denied", "missing_scope"].includes(error.errorSubtype ?? ""));
|
|
97885
|
+
}
|
|
97909
97886
|
var LarkResourceCommandError;
|
|
97910
97887
|
var init_larkResourceCommand = __esm(() => {
|
|
97911
97888
|
LarkResourceCommandError = class LarkResourceCommandError extends Error {
|
|
97912
97889
|
errorType;
|
|
97913
97890
|
errorSubtype;
|
|
97914
|
-
|
|
97891
|
+
code;
|
|
97892
|
+
logId;
|
|
97893
|
+
constructor(message, errorType, errorSubtype, code3, logId) {
|
|
97915
97894
|
super(message);
|
|
97916
97895
|
this.errorType = errorType;
|
|
97917
97896
|
this.errorSubtype = errorSubtype;
|
|
97897
|
+
this.code = code3;
|
|
97898
|
+
this.logId = logId;
|
|
97918
97899
|
this.name = "LarkResourceCommandError";
|
|
97919
97900
|
}
|
|
97920
97901
|
};
|
|
97921
97902
|
});
|
|
97922
97903
|
|
|
97904
|
+
// src/lib/larkMediaDownload.ts
|
|
97905
|
+
import { readdir as readdir21, rm as rm20 } from "node:fs/promises";
|
|
97906
|
+
import { join as join94 } from "node:path";
|
|
97907
|
+
async function downloadLarkMedia(input) {
|
|
97908
|
+
const shared = ["--as", input.identity, "--token", input.token, "--output", "./resource", "--format", "json"];
|
|
97909
|
+
try {
|
|
97910
|
+
await runLarkResourceCommand(input.runner, ["docs", "+media-download", ...shared, "--type", input.type, "--overwrite"], { cwd: input.cwd });
|
|
97911
|
+
return "original";
|
|
97912
|
+
} catch (error) {
|
|
97913
|
+
if (!input.allowPreview || !isLarkResourcePermissionDenied(error))
|
|
97914
|
+
throw error;
|
|
97915
|
+
for (const entry of await readdir21(input.cwd))
|
|
97916
|
+
await rm20(join94(input.cwd, entry), { recursive: true, force: true });
|
|
97917
|
+
await runLarkResourceCommand(input.runner, ["docs", "+media-preview", ...shared], { cwd: input.cwd });
|
|
97918
|
+
return "preview";
|
|
97919
|
+
}
|
|
97920
|
+
}
|
|
97921
|
+
var init_larkMediaDownload = __esm(() => {
|
|
97922
|
+
init_larkResourceCommand();
|
|
97923
|
+
});
|
|
97924
|
+
|
|
97925
|
+
// src/lib/larkImagePolicy.ts
|
|
97926
|
+
function omitLarkImage(resource, policy, items, replacements, mediaType, failure2) {
|
|
97927
|
+
if (resource.kind !== "image" && !mediaType?.startsWith("image/"))
|
|
97928
|
+
return false;
|
|
97929
|
+
const gif = mediaType === "image/gif" || /\.gif$/iu.test(resource.title ?? "") || Object.entries(resource.attributes).some(([key, value]) => ["mime_type", "content_type"].includes(key) && value === "image/gif");
|
|
97930
|
+
if (!failure2 && policy.images !== "reference-only" && !(gif && policy.gifs === "reference-only"))
|
|
97931
|
+
return false;
|
|
97932
|
+
const title2 = (resource.title ?? "image").replace(/[\r\n<>]/gu, " ");
|
|
97933
|
+
replacements.set(resource.locator, `> Image omitted: ${title2}. ${failure2 ? "Resource size limit exceeded." : "Excluded by selected policy."} See the source document. <!-- ${resource.locator} -->`);
|
|
97934
|
+
items.push({
|
|
97935
|
+
kind: resource.kind,
|
|
97936
|
+
locator: resource.locator,
|
|
97937
|
+
status: "reference-only",
|
|
97938
|
+
required: false,
|
|
97939
|
+
asset_paths: [],
|
|
97940
|
+
reason_code: failure2 ? "image-budget-exceeded" : "image-excluded-by-policy",
|
|
97941
|
+
reason: failure2 ?? "Image bytes were not retained; the selected image policy preserves a placeholder and source reference"
|
|
97942
|
+
});
|
|
97943
|
+
return true;
|
|
97944
|
+
}
|
|
97945
|
+
var LarkResourceBudgetError;
|
|
97946
|
+
var init_larkImagePolicy = __esm(() => {
|
|
97947
|
+
LarkResourceBudgetError = class LarkResourceBudgetError extends Error {
|
|
97948
|
+
};
|
|
97949
|
+
});
|
|
97950
|
+
|
|
97923
97951
|
// src/lib/larkResourceMaterialization.ts
|
|
97924
97952
|
import { createHash as createHash28 } from "node:crypto";
|
|
97925
|
-
import { mkdtemp as mkdtemp4, readFile as readFile74, readdir as
|
|
97926
|
-
import { extname as extname13, join as
|
|
97953
|
+
import { mkdtemp as mkdtemp4, readFile as readFile74, readdir as readdir22, rm as rm21 } from "node:fs/promises";
|
|
97954
|
+
import { extname as extname13, join as join95 } from "node:path";
|
|
97927
97955
|
import { tmpdir } from "node:os";
|
|
97928
97956
|
function countByKind(items, status) {
|
|
97929
97957
|
const counts2 = new Map;
|
|
@@ -98029,33 +98057,19 @@ function findBooleanField(value, name3) {
|
|
|
98029
98057
|
async function downloadedFile(input) {
|
|
98030
98058
|
if (input.localPath !== undefined) {
|
|
98031
98059
|
const bytes = await readFile74(input.localPath);
|
|
98032
|
-
return { path: input.localPath, bytes, mediaType: mediaTypeFor(input.localPath, bytes) };
|
|
98060
|
+
return { path: input.localPath, bytes, mediaType: mediaTypeFor(input.localPath, bytes), representation: "original" };
|
|
98033
98061
|
}
|
|
98034
|
-
const tempRoot = await mkdtemp4(
|
|
98062
|
+
const tempRoot = await mkdtemp4(join95(tmpdir(), "context-lark-resource-"));
|
|
98035
98063
|
try {
|
|
98036
|
-
await
|
|
98037
|
-
|
|
98038
|
-
"+media-download",
|
|
98039
|
-
"--as",
|
|
98040
|
-
input.identity,
|
|
98041
|
-
"--token",
|
|
98042
|
-
input.token,
|
|
98043
|
-
"--type",
|
|
98044
|
-
input.type,
|
|
98045
|
-
"--output",
|
|
98046
|
-
"./resource",
|
|
98047
|
-
"--overwrite",
|
|
98048
|
-
"--format",
|
|
98049
|
-
"json"
|
|
98050
|
-
], { cwd: tempRoot });
|
|
98051
|
-
const entries2 = (await readdir21(tempRoot, { withFileTypes: true })).filter((entry) => entry.isFile());
|
|
98064
|
+
const representation = await downloadLarkMedia({ ...input, cwd: tempRoot });
|
|
98065
|
+
const entries2 = (await readdir22(tempRoot, { withFileTypes: true })).filter((entry) => entry.isFile());
|
|
98052
98066
|
if (entries2.length !== 1)
|
|
98053
98067
|
throw new Error(`media download produced ${entries2.length} files, expected exactly one`);
|
|
98054
98068
|
const path3 = entries2[0]?.name ?? "resource.bin";
|
|
98055
|
-
const bytes = await readFile74(
|
|
98056
|
-
return { path: path3, bytes, mediaType: mediaTypeFor(path3, bytes) };
|
|
98069
|
+
const bytes = await readFile74(join95(tempRoot, path3));
|
|
98070
|
+
return { path: path3, bytes, mediaType: mediaTypeFor(path3, bytes), representation };
|
|
98057
98071
|
} finally {
|
|
98058
|
-
await
|
|
98072
|
+
await rm21(tempRoot, { recursive: true, force: true });
|
|
98059
98073
|
}
|
|
98060
98074
|
}
|
|
98061
98075
|
function parseCsv(value) {
|
|
@@ -98143,9 +98157,9 @@ async function sheetMaterialization(resource, runner2, identity2) {
|
|
|
98143
98157
|
const sheetId = resource.attributes["sheet-id"];
|
|
98144
98158
|
if (token === undefined || sheetId === undefined)
|
|
98145
98159
|
throw new Error("embedded Sheet requires token and sheet-id");
|
|
98146
|
-
const tempRoot = await mkdtemp4(
|
|
98160
|
+
const tempRoot = await mkdtemp4(join95(tmpdir(), "context-lark-sheet-"));
|
|
98147
98161
|
try {
|
|
98148
|
-
const outputPath =
|
|
98162
|
+
const outputPath = join95(tempRoot, "sheet.json");
|
|
98149
98163
|
const stdout = await runLarkResourceCommand(runner2, [
|
|
98150
98164
|
"sheets",
|
|
98151
98165
|
"+csv-get",
|
|
@@ -98187,7 +98201,7 @@ ${markdownTable2(parseCsv(csv))}
|
|
|
98187
98201
|
[CSV snapshot](${sourceAssetTarget(path3)}) <!-- ${resource.locator} -->`
|
|
98188
98202
|
};
|
|
98189
98203
|
} finally {
|
|
98190
|
-
await
|
|
98204
|
+
await rm21(tempRoot, { recursive: true, force: true });
|
|
98191
98205
|
}
|
|
98192
98206
|
}
|
|
98193
98207
|
function basePageRecords(value) {
|
|
@@ -98301,7 +98315,7 @@ async function whiteboardMaterialization(resource, runner2, identity2) {
|
|
|
98301
98315
|
if (token === undefined)
|
|
98302
98316
|
throw new Error(`${resource.kind} has no whiteboard token`);
|
|
98303
98317
|
const preview = await downloadedFile({ runner: runner2, identity: identity2, token, type: "whiteboard" });
|
|
98304
|
-
const tempRoot = await mkdtemp4(
|
|
98318
|
+
const tempRoot = await mkdtemp4(join95(tmpdir(), "context-lark-whiteboard-"));
|
|
98305
98319
|
let rawPayload;
|
|
98306
98320
|
try {
|
|
98307
98321
|
await runLarkResourceCommand(runner2, [
|
|
@@ -98319,9 +98333,9 @@ async function whiteboardMaterialization(resource, runner2, identity2) {
|
|
|
98319
98333
|
"--format",
|
|
98320
98334
|
"json"
|
|
98321
98335
|
], { cwd: tempRoot });
|
|
98322
|
-
rawPayload = JSON.parse(await readFile74(
|
|
98336
|
+
rawPayload = JSON.parse(await readFile74(join95(tempRoot, "raw.json"), "utf8"));
|
|
98323
98337
|
} finally {
|
|
98324
|
-
await
|
|
98338
|
+
await rm21(tempRoot, { recursive: true, force: true });
|
|
98325
98339
|
}
|
|
98326
98340
|
const digest6 = resourceDigest(resource);
|
|
98327
98341
|
const previewPath = `materialized/${resource.kind}/${digest6}${extensionFor2(preview.mediaType, preview.path)}`;
|
|
@@ -98380,7 +98394,7 @@ function referenceOnlyReason(resource) {
|
|
|
98380
98394
|
}
|
|
98381
98395
|
function materializationReport(items) {
|
|
98382
98396
|
const hasRequiredFailure = items.some((item) => item.status === "failed" && item.required && !isNonBlockingDocumentResourceFailureReasonCode(item.reason_code));
|
|
98383
|
-
const hasOptionalFailure = items.some((item) => item.status === "failed" || item.reason_code === "image-budget-exceeded") || items.some((item) => item.status === "reference-only" && item.kind === "poll" && item.reason?.includes("absent") === true);
|
|
98397
|
+
const hasOptionalFailure = items.some((item) => item.status === "failed" || item.reason_code === "image-budget-exceeded" || item.reason_code === "document.resource.preview") || items.some((item) => item.status === "reference-only" && item.kind === "poll" && item.reason?.includes("absent") === true);
|
|
98384
98398
|
return {
|
|
98385
98399
|
status: hasRequiredFailure ? "error" : hasOptionalFailure ? "warning" : "complete",
|
|
98386
98400
|
discovered: countByKind(items),
|
|
@@ -98391,7 +98405,7 @@ function materializationReport(items) {
|
|
|
98391
98405
|
};
|
|
98392
98406
|
}
|
|
98393
98407
|
function resourceFailureReasonCode(resource, error) {
|
|
98394
|
-
if (error
|
|
98408
|
+
if (isLarkResourcePermissionDenied(error)) {
|
|
98395
98409
|
return DOCUMENT_RESOURCE_PERMISSION_DENIED_REASON_CODE;
|
|
98396
98410
|
}
|
|
98397
98411
|
if (resource.kind !== "diagram" && resource.kind !== "whiteboard")
|
|
@@ -98511,6 +98525,7 @@ async function materializeLarkResources(input) {
|
|
|
98511
98525
|
identity: identity2,
|
|
98512
98526
|
token,
|
|
98513
98527
|
type: "media",
|
|
98528
|
+
allowPreview: resource.kind === "image",
|
|
98514
98529
|
...input.mediaFiles?.[token] === undefined ? {} : { localPath: input.mediaFiles[token] }
|
|
98515
98530
|
});
|
|
98516
98531
|
if (omitLarkImage(resource, input.policy, items, replacements, downloaded.mediaType))
|
|
@@ -98522,7 +98537,7 @@ async function materializeLarkResources(input) {
|
|
|
98522
98537
|
bytes: downloaded.bytes,
|
|
98523
98538
|
mediaType: downloaded.mediaType,
|
|
98524
98539
|
role: "evidence",
|
|
98525
|
-
source: { kind: resource.kind, locator: resource.locator }
|
|
98540
|
+
source: { kind: resource.kind, locator: resource.locator, identity: identity2, representation: downloaded.representation }
|
|
98526
98541
|
};
|
|
98527
98542
|
assertBudget(asset, input.policy, totalBytes);
|
|
98528
98543
|
totalBytes += asset.bytes.byteLength;
|
|
@@ -98530,8 +98545,17 @@ async function materializeLarkResources(input) {
|
|
|
98530
98545
|
const title2 = markdownLabel(safeLabel(resource.title, resource.kind));
|
|
98531
98546
|
const target = sourceAssetTarget(asset.path);
|
|
98532
98547
|
const replacement = downloaded.mediaType.startsWith("image/") ? ` <!-- ${resource.locator} -->` : `[${title2}](${target}) <!-- ${resource.locator} -->`;
|
|
98533
|
-
replacements.set(resource.locator, replacement
|
|
98534
|
-
|
|
98548
|
+
replacements.set(resource.locator, downloaded.representation === "preview" ? `${replacement}
|
|
98549
|
+
|
|
98550
|
+
> Image preview captured; the original could not be downloaded.` : replacement);
|
|
98551
|
+
items.push({
|
|
98552
|
+
kind: resource.kind,
|
|
98553
|
+
locator: resource.locator,
|
|
98554
|
+
status: "materialized",
|
|
98555
|
+
required,
|
|
98556
|
+
asset_paths: [asset.path],
|
|
98557
|
+
...downloaded.representation === "preview" ? { reason_code: "document.resource.preview", reason: "Same-identity preview captured; original download permission denied" } : {}
|
|
98558
|
+
});
|
|
98535
98559
|
} catch (error) {
|
|
98536
98560
|
if (error instanceof LarkResourceBudgetError && omitLarkImage(resource, input.policy, items, replacements, undefined, error.message))
|
|
98537
98561
|
return;
|
|
@@ -98579,6 +98603,7 @@ function applyLarkResourceReplacements(markdown, resources, replacements) {
|
|
|
98579
98603
|
}
|
|
98580
98604
|
var REQUIRED_KINDS, MEDIA_TYPES_BY_EXTENSION;
|
|
98581
98605
|
var init_larkResourceMaterialization = __esm(() => {
|
|
98606
|
+
init_larkMediaDownload();
|
|
98582
98607
|
init_larkImagePolicy();
|
|
98583
98608
|
init_src3();
|
|
98584
98609
|
init_larkResourceCommand();
|
|
@@ -98654,6 +98679,89 @@ var init_larkMarkdownImages = __esm(() => {
|
|
|
98654
98679
|
init_markdownLinks();
|
|
98655
98680
|
});
|
|
98656
98681
|
|
|
98682
|
+
// src/lib/larkReadIdentity.ts
|
|
98683
|
+
function resolveLarkReadIdentity() {
|
|
98684
|
+
const value = process.env.CONTEXT_LARK_IDENTITY?.trim() || "user";
|
|
98685
|
+
if (value === "user" || value === "bot")
|
|
98686
|
+
return value;
|
|
98687
|
+
throw new ContextError(ExitCode.UserError, "CONTEXT_LARK_IDENTITY must be user or bot", {
|
|
98688
|
+
reason_code: "lark.invalid-read-identity",
|
|
98689
|
+
valid_values: ["user", "bot"],
|
|
98690
|
+
next: "Set CONTEXT_LARK_IDENTITY to user or bot and rerun the same command"
|
|
98691
|
+
});
|
|
98692
|
+
}
|
|
98693
|
+
function credentialFailure(result) {
|
|
98694
|
+
for (const output of [result.stdout, result.stderr]) {
|
|
98695
|
+
const start2 = output.indexOf("{");
|
|
98696
|
+
if (start2 < 0)
|
|
98697
|
+
continue;
|
|
98698
|
+
try {
|
|
98699
|
+
const parsed = JSON.parse(output.slice(start2));
|
|
98700
|
+
if (!parsed || typeof parsed !== "object" || !("error" in parsed))
|
|
98701
|
+
continue;
|
|
98702
|
+
if (result.exitCode === 0 && (!("ok" in parsed) || parsed.ok !== false))
|
|
98703
|
+
continue;
|
|
98704
|
+
const error = parsed.error;
|
|
98705
|
+
if (!error || typeof error !== "object")
|
|
98706
|
+
continue;
|
|
98707
|
+
const type = "type" in error ? error.type : undefined;
|
|
98708
|
+
const subtype = "subtype" in error ? error.subtype : undefined;
|
|
98709
|
+
if (type === "authorization" || type === "authentication" || ["missing_scope", "permission_denied", "access_denied", "need_user_authorization"].includes(String(subtype))) {
|
|
98710
|
+
return true;
|
|
98711
|
+
}
|
|
98712
|
+
} catch {}
|
|
98713
|
+
}
|
|
98714
|
+
return result.exitCode !== 0 && /reason=(?:bot_unavailable|not_authorized)\b|\b(?:missing_scope|permission_denied|access_denied)\b/iu.test(result.stderr);
|
|
98715
|
+
}
|
|
98716
|
+
function createLarkReadSession(runner2, initial, fallback = initial === "bot") {
|
|
98717
|
+
let identity2 = initial;
|
|
98718
|
+
let usedFallback = false;
|
|
98719
|
+
let readingDocument = false;
|
|
98720
|
+
let locked = false;
|
|
98721
|
+
const restart = new Error("Restart document with user identity");
|
|
98722
|
+
const run = async (args, options) => {
|
|
98723
|
+
const explicit = args.indexOf("--as");
|
|
98724
|
+
const requested = explicit >= 0 ? args[explicit + 1] : identity2;
|
|
98725
|
+
const selected = locked || usedFallback ? identity2 : requested === "bot" ? "bot" : "user";
|
|
98726
|
+
const withIdentity = [...args];
|
|
98727
|
+
if (explicit >= 0)
|
|
98728
|
+
withIdentity[explicit + 1] = selected;
|
|
98729
|
+
else
|
|
98730
|
+
withIdentity.push("--as", selected);
|
|
98731
|
+
const result = await runner2(withIdentity, options);
|
|
98732
|
+
identity2 = selected;
|
|
98733
|
+
if (readingDocument && identity2 === "bot" && fallback && !usedFallback && !args.includes("--help") && credentialFailure(result))
|
|
98734
|
+
throw restart;
|
|
98735
|
+
return result;
|
|
98736
|
+
};
|
|
98737
|
+
async function readDocument(read) {
|
|
98738
|
+
readingDocument = true;
|
|
98739
|
+
try {
|
|
98740
|
+
try {
|
|
98741
|
+
return await read();
|
|
98742
|
+
} catch (error) {
|
|
98743
|
+
if (error !== restart)
|
|
98744
|
+
throw error;
|
|
98745
|
+
usedFallback = true;
|
|
98746
|
+
identity2 = "user";
|
|
98747
|
+
return await read();
|
|
98748
|
+
}
|
|
98749
|
+
} finally {
|
|
98750
|
+
readingDocument = false;
|
|
98751
|
+
locked = true;
|
|
98752
|
+
}
|
|
98753
|
+
}
|
|
98754
|
+
return { run, readDocument, get identity() {
|
|
98755
|
+
return identity2;
|
|
98756
|
+
}, get usedFallback() {
|
|
98757
|
+
return usedFallback;
|
|
98758
|
+
} };
|
|
98759
|
+
}
|
|
98760
|
+
var init_larkReadIdentity = __esm(() => {
|
|
98761
|
+
init_errors3();
|
|
98762
|
+
init_exitCode();
|
|
98763
|
+
});
|
|
98764
|
+
|
|
98657
98765
|
// src/lib/feishu.ts
|
|
98658
98766
|
import { spawn as spawn4 } from "node:child_process";
|
|
98659
98767
|
async function detectDocsFetchCapabilities(runner2) {
|
|
@@ -98670,14 +98778,19 @@ ${result.stderr}`;
|
|
|
98670
98778
|
supportsDocFormat: result.exitCode === 0 && /\s--doc-format\b/u.test(help)
|
|
98671
98779
|
};
|
|
98672
98780
|
}
|
|
98673
|
-
function resolveDocsFetchPlan(requested, runner2) {
|
|
98781
|
+
function resolveDocsFetchPlan(requested, runner2, cacheKey = runner2, identity2 = "user") {
|
|
98674
98782
|
if (requested === "v1" || requested === "v2") {
|
|
98675
98783
|
return Promise.resolve({ apiVersion: requested, docFormat: "xml" });
|
|
98676
98784
|
}
|
|
98677
|
-
let
|
|
98785
|
+
let cached = docsFetchCapabilitiesCache.get(cacheKey);
|
|
98786
|
+
if (!cached) {
|
|
98787
|
+
cached = new Map;
|
|
98788
|
+
docsFetchCapabilitiesCache.set(cacheKey, cached);
|
|
98789
|
+
}
|
|
98790
|
+
let capabilitiesPromise = cached.get(identity2);
|
|
98678
98791
|
if (capabilitiesPromise === undefined) {
|
|
98679
98792
|
capabilitiesPromise = detectDocsFetchCapabilities(runner2);
|
|
98680
|
-
|
|
98793
|
+
cached.set(identity2, capabilitiesPromise);
|
|
98681
98794
|
}
|
|
98682
98795
|
return capabilitiesPromise.then((capabilities) => {
|
|
98683
98796
|
if (!capabilities.supportsDocFormat) {
|
|
@@ -98974,20 +99087,25 @@ function hasEmptySubPageList(projection) {
|
|
|
98974
99087
|
return projection.fidelity.issues.some((issue) => issue.code === LARK_EMPTY_SUB_PAGE_LIST_CODE);
|
|
98975
99088
|
}
|
|
98976
99089
|
async function fetchFeishuDocSnapshot(input, runner2 = defaultRunner) {
|
|
98977
|
-
const
|
|
99090
|
+
const preference = input.prefetched?.identity ?? input.identity ?? resolveLarkReadIdentity();
|
|
99091
|
+
const cacheKey = runner2;
|
|
99092
|
+
const session = createLarkReadSession(runner2, input.prefetched?.identity ?? (preference === "bot" ? "bot" : "user"), !input.prefetched && preference === "bot");
|
|
99093
|
+
runner2 = session.run;
|
|
99094
|
+
const docsFetchPlan = input.prefetched ? { apiVersion: "v2", docFormat: "xml" } : await resolveDocsFetchPlan(input.docsApiVersion ?? "auto", runner2, cacheKey, preference);
|
|
98978
99095
|
const identityFetch = input.prefetched ? {
|
|
98979
99096
|
fetched: await fetchDocsResponse(input, docsFetchPlan, runner2, input.prefetched.identity),
|
|
98980
99097
|
identity: input.prefetched.identity,
|
|
98981
99098
|
fallback: false
|
|
98982
|
-
} : await fetchWithIdentity(input, docsFetchPlan, runner2);
|
|
99099
|
+
} : await session.readDocument(() => fetchWithIdentity({ ...input, identity: preference }, docsFetchPlan, runner2));
|
|
98983
99100
|
let fetched = identityFetch.fetched;
|
|
98984
|
-
|
|
99101
|
+
let accessIdentity = input.prefetched?.identity ?? session.identity;
|
|
98985
99102
|
let projection;
|
|
98986
99103
|
for (let attempt = 0;attempt < MAX_STRUCTURAL_FETCH_ATTEMPTS && fetched.contentFormat === "xml"; attempt++) {
|
|
98987
99104
|
projection = projectLarkDocxXml({ xml: fetched.body, sourceUrl: input.url });
|
|
98988
99105
|
if (input.prefetched || !hasEmptySubPageList(projection) || attempt === MAX_STRUCTURAL_FETCH_ATTEMPTS - 1)
|
|
98989
99106
|
break;
|
|
98990
99107
|
fetched = await fetchDocsResponse(input, docsFetchPlan, runner2, accessIdentity);
|
|
99108
|
+
accessIdentity = session.identity;
|
|
98991
99109
|
}
|
|
98992
99110
|
let body2 = fetched.body;
|
|
98993
99111
|
let title2 = fetched.title;
|
|
@@ -99073,7 +99191,7 @@ ${body2}`,
|
|
|
99073
99191
|
fidelity,
|
|
99074
99192
|
resourceMaterialization,
|
|
99075
99193
|
accessIdentity,
|
|
99076
|
-
identityFallback: identityFetch.fallback
|
|
99194
|
+
identityFallback: identityFetch.fallback || session.usedFallback
|
|
99077
99195
|
};
|
|
99078
99196
|
}
|
|
99079
99197
|
return {
|
|
@@ -99084,7 +99202,7 @@ ${body2}`,
|
|
|
99084
99202
|
fidelity,
|
|
99085
99203
|
resourceMaterialization,
|
|
99086
99204
|
accessIdentity,
|
|
99087
|
-
identityFallback: identityFetch.fallback
|
|
99205
|
+
identityFallback: identityFetch.fallback || session.usedFallback
|
|
99088
99206
|
};
|
|
99089
99207
|
}
|
|
99090
99208
|
var LARK_BIN = "lark-cli", MAX_FETCH_PAGES = 50, MAX_STRUCTURAL_FETCH_ATTEMPTS = 2, LarkCliNotInstalledError, LarkCliError, defaultRunner = (args, options) => new Promise((resolve8, reject) => {
|
|
@@ -99116,6 +99234,7 @@ var init_feishu = __esm(() => {
|
|
|
99116
99234
|
init_larkResourceMaterialization();
|
|
99117
99235
|
init_larkCaptureReport();
|
|
99118
99236
|
init_larkMarkdownImages();
|
|
99237
|
+
init_larkReadIdentity();
|
|
99119
99238
|
LarkCliNotInstalledError = class LarkCliNotInstalledError extends Error {
|
|
99120
99239
|
constructor() {
|
|
99121
99240
|
super(`${LARK_BIN} not installed — see https://github.com/larksuite/cli for install instructions`);
|
|
@@ -99168,8 +99287,8 @@ var init_sensitiveSourceLiteral = __esm(() => {
|
|
|
99168
99287
|
});
|
|
99169
99288
|
|
|
99170
99289
|
// src/project/documentCaptureLark.ts
|
|
99171
|
-
import { readdir as
|
|
99172
|
-
import { basename as basename10, extname as extname14, join as
|
|
99290
|
+
import { readdir as readdir23, readFile as readFile75 } from "node:fs/promises";
|
|
99291
|
+
import { basename as basename10, extname as extname14, join as join96 } from "node:path";
|
|
99173
99292
|
function titleFromMarkdown2(markdown, fallbackPath) {
|
|
99174
99293
|
const heading2 = markdown.split(`
|
|
99175
99294
|
`).find((line) => /^#\s+\S/u.test(line));
|
|
@@ -99196,7 +99315,7 @@ async function fileContentMatches(path3, content3) {
|
|
|
99196
99315
|
}
|
|
99197
99316
|
}
|
|
99198
99317
|
function sourceManifestPath2(entry) {
|
|
99199
|
-
return entry.snapshot?.manifest ??
|
|
99318
|
+
return entry.snapshot?.manifest ?? join96(entry.materializedAt, "manifest.json");
|
|
99200
99319
|
}
|
|
99201
99320
|
function larkRuntimeError(message, detail) {
|
|
99202
99321
|
return new ContextError(ExitCode.ExternalToolError, message, {
|
|
@@ -99276,7 +99395,7 @@ function larkErrorRecovery(error, sourceName) {
|
|
|
99276
99395
|
if (/auth|login|permission|forbidden|unauthori[sz]ed|scope/iu.test(message)) {
|
|
99277
99396
|
return {
|
|
99278
99397
|
reasonCode: "external.authorization-required",
|
|
99279
|
-
next: "
|
|
99398
|
+
next: "Check the selected Lark identity and document access. For host-managed credentials use the host authorization flow; use lark-cli auth login only for a locally managed user login, then rerun capture"
|
|
99280
99399
|
};
|
|
99281
99400
|
}
|
|
99282
99401
|
return {
|
|
@@ -99323,12 +99442,12 @@ function assetManifestEntry(asset, assetRoot) {
|
|
|
99323
99442
|
};
|
|
99324
99443
|
}
|
|
99325
99444
|
async function listSnapshotAssetFiles(root2, assetRoot) {
|
|
99326
|
-
const assetsRoot =
|
|
99445
|
+
const assetsRoot = join96(root2, assetRoot);
|
|
99327
99446
|
const files = [];
|
|
99328
99447
|
const visit4 = async (dir, prefix = assetRoot) => {
|
|
99329
99448
|
let entries2;
|
|
99330
99449
|
try {
|
|
99331
|
-
entries2 = await
|
|
99450
|
+
entries2 = await readdir23(dir, { withFileTypes: true });
|
|
99332
99451
|
} catch (error) {
|
|
99333
99452
|
if (error instanceof Error && "code" in error && error.code === "ENOENT")
|
|
99334
99453
|
return;
|
|
@@ -99336,7 +99455,7 @@ async function listSnapshotAssetFiles(root2, assetRoot) {
|
|
|
99336
99455
|
}
|
|
99337
99456
|
for (const entry of entries2) {
|
|
99338
99457
|
const relPath = `${prefix}/${entry.name}`;
|
|
99339
|
-
const absolutePath =
|
|
99458
|
+
const absolutePath = join96(dir, entry.name);
|
|
99340
99459
|
if (entry.isDirectory()) {
|
|
99341
99460
|
await visit4(absolutePath, relPath);
|
|
99342
99461
|
continue;
|
|
@@ -99351,7 +99470,7 @@ async function listSnapshotAssetFiles(root2, assetRoot) {
|
|
|
99351
99470
|
}
|
|
99352
99471
|
async function staleSnapshotAssetPaths(input) {
|
|
99353
99472
|
const existingPaths = await listSnapshotAssetFiles(input.materializedAtAbsPath, input.assetRoot);
|
|
99354
|
-
return existingPaths.filter((path3) => !input.currentPaths.has(path3)).map((path3) =>
|
|
99473
|
+
return existingPaths.filter((path3) => !input.currentPaths.has(path3)).map((path3) => join96(input.materializedAtAbsPath, path3));
|
|
99355
99474
|
}
|
|
99356
99475
|
function normalizeLarkError(error, sourceName) {
|
|
99357
99476
|
if (error instanceof ContextError)
|
|
@@ -99421,6 +99540,8 @@ async function runCaptureLarkPhaseUnlocked(input) {
|
|
|
99421
99540
|
...input.prefetched === undefined ? {} : { prefetched: input.prefetched }
|
|
99422
99541
|
}, input.larkRunner);
|
|
99423
99542
|
} catch (error) {
|
|
99543
|
+
if (error instanceof ContextError)
|
|
99544
|
+
throw error;
|
|
99424
99545
|
const failure2 = normalizeLarkError(error, resolved.sourceName);
|
|
99425
99546
|
if (failure2.detail?.reason_code === "external.authorization-required" || failure2.detail?.reason_code === "external.tool-failed" && error instanceof LarkCliError && error.exitCode !== 0) {
|
|
99426
99547
|
throw new ContextError(failure2.code, failure2.message, { ...failure2.detail, reason_code: DOCUMENT_ACQUISITION_UNAVAILABLE, acquisition_cause: failure2.detail?.reason_code });
|
|
@@ -99463,9 +99584,9 @@ async function runCaptureLarkPhaseUnlocked(input) {
|
|
|
99463
99584
|
locator
|
|
99464
99585
|
}];
|
|
99465
99586
|
const manifestPath = sourceManifestPath2(entry);
|
|
99466
|
-
const manifestAbsPath =
|
|
99587
|
+
const manifestAbsPath = join96(input.projectRoot, manifestPath);
|
|
99467
99588
|
const materializedAt = entry.materializedAt;
|
|
99468
|
-
const materializedAtAbsPath =
|
|
99589
|
+
const materializedAtAbsPath = join96(input.projectRoot, materializedAt);
|
|
99469
99590
|
const manifest = createDocumentSnapshotManifest({
|
|
99470
99591
|
sourceType: "lark",
|
|
99471
99592
|
sourceName: resolved.sourceName,
|
|
@@ -99499,13 +99620,13 @@ async function runCaptureLarkPhaseUnlocked(input) {
|
|
|
99499
99620
|
}));
|
|
99500
99621
|
try {
|
|
99501
99622
|
const requestedWrites = [{
|
|
99502
|
-
path:
|
|
99623
|
+
path: join96(materializedAtAbsPath, documentPath),
|
|
99503
99624
|
bytes: normalized
|
|
99504
99625
|
}];
|
|
99505
99626
|
for (const asset of assets) {
|
|
99506
99627
|
if (asset.bytes !== undefined) {
|
|
99507
99628
|
requestedWrites.push({
|
|
99508
|
-
path:
|
|
99629
|
+
path: join96(materializedAtAbsPath, asset.entry.path),
|
|
99509
99630
|
bytes: asset.bytes
|
|
99510
99631
|
});
|
|
99511
99632
|
}
|
|
@@ -99522,7 +99643,7 @@ async function runCaptureLarkPhaseUnlocked(input) {
|
|
|
99522
99643
|
currentPaths: new Set(assets.filter((asset) => asset.bytes !== undefined).map((asset) => asset.entry.path))
|
|
99523
99644
|
});
|
|
99524
99645
|
await applyAtomicFileBatch({
|
|
99525
|
-
transactionRoot:
|
|
99646
|
+
transactionRoot: join96(input.projectRoot, ".tmp", "context-runtime", "capture-transactions"),
|
|
99526
99647
|
writes,
|
|
99527
99648
|
removals
|
|
99528
99649
|
});
|
|
@@ -99594,7 +99715,7 @@ async function runCaptureLarkPhaseUnlocked(input) {
|
|
|
99594
99715
|
resource_materialization: fetched.resourceMaterialization,
|
|
99595
99716
|
diagnostics: [
|
|
99596
99717
|
...recovery === undefined ? [] : [recovery.diagnostic],
|
|
99597
|
-
...fetched.identityFallback ? [`info: lark.capture.identity-fallback:
|
|
99718
|
+
...fetched.identityFallback ? [`info: lark.capture.identity-fallback: capture used an identity fallback; document identity: ${fetched.accessIdentity}; embedded reads may use the fallback identity`] : [],
|
|
99598
99719
|
...fetched.fidelity.issues.map((issue) => `${issue.severity}: ${issue.code}: ${issue.block_type} × ${issue.count}: ${issue.reason}`),
|
|
99599
99720
|
...fetched.resourceMaterialization.items.filter((item) => item.status === "failed" || item.kind === "poll" && item.reason?.includes("absent") === true).map((item) => `${item.status}: lark.capture.resource-${item.status}: ${item.kind}: ${item.reason ?? item.locator}`)
|
|
99600
99721
|
],
|
|
@@ -99668,7 +99789,7 @@ __export(exports_articleRetirement, {
|
|
|
99668
99789
|
retireArticles: () => retireArticles,
|
|
99669
99790
|
articleRetirementSchema: () => articleRetirementSchema
|
|
99670
99791
|
});
|
|
99671
|
-
import { readFile as readFile81, readdir as
|
|
99792
|
+
import { readFile as readFile81, readdir as readdir24 } from "node:fs/promises";
|
|
99672
99793
|
import { posix as posix10 } from "node:path";
|
|
99673
99794
|
function rebuildInput(revision) {
|
|
99674
99795
|
return JSON.stringify({ id: `retirement-${revision.slice(7)}`, operation: "rebuild", timing: "priority", targets: [] });
|
|
@@ -99801,7 +99922,7 @@ async function retireArticles(input) {
|
|
|
99801
99922
|
}
|
|
99802
99923
|
async function inspectTemplates(directory2) {
|
|
99803
99924
|
const absolute = await safeProjectTarget(input.projectRoot, directory2);
|
|
99804
|
-
const entries2 = await
|
|
99925
|
+
const entries2 = await readdir24(absolute, { withFileTypes: true }).catch((error) => {
|
|
99805
99926
|
if (error.code === "ENOENT")
|
|
99806
99927
|
return [];
|
|
99807
99928
|
throw error;
|
|
@@ -99951,8 +100072,8 @@ __export(exports_writeLockRecovery, {
|
|
|
99951
100072
|
recoverWriterLock: () => recoverWriterLock,
|
|
99952
100073
|
inspectWriterLock: () => inspectWriterLock
|
|
99953
100074
|
});
|
|
99954
|
-
import { lstat as lstat10, mkdir as mkdir34, readFile as readFile82, readdir as
|
|
99955
|
-
import { join as
|
|
100075
|
+
import { lstat as lstat10, mkdir as mkdir34, readFile as readFile82, readdir as readdir25, rename as rename8, rmdir as rmdir2 } from "node:fs/promises";
|
|
100076
|
+
import { join as join101 } from "node:path";
|
|
99956
100077
|
import { createHash as createHash30, randomUUID as randomUUID7 } from "node:crypto";
|
|
99957
100078
|
async function inspectWriterLock(root2) {
|
|
99958
100079
|
const path3 = await safeProjectTarget(root2, lockRelative);
|
|
@@ -99999,19 +100120,19 @@ async function recoverWriterLock(input) {
|
|
|
99999
100120
|
};
|
|
100000
100121
|
if (input.plan_digest !== before.digest)
|
|
100001
100122
|
throw new Error("Writer lock changed; preview recovery again.");
|
|
100002
|
-
const path3 =
|
|
100003
|
-
const guard =
|
|
100123
|
+
const path3 = join101(input.projectRoot, lockRelative);
|
|
100124
|
+
const guard = join101(path3, ".recovery");
|
|
100004
100125
|
await mkdir34(guard);
|
|
100005
100126
|
let archived = false;
|
|
100006
100127
|
try {
|
|
100007
100128
|
const current2 = await inspectWriterLock(input.projectRoot);
|
|
100008
100129
|
if (current2?.digest !== before.digest || current2.process_state !== "not-running")
|
|
100009
100130
|
throw new Error("Writer lock changed or owner resumed; keep the lock.");
|
|
100010
|
-
const names = await
|
|
100131
|
+
const names = await readdir25(path3);
|
|
100011
100132
|
if (names.some((name3) => name3 !== "owner.json" && name3 !== ".recovery"))
|
|
100012
100133
|
throw new Error("Unexpected lock contents; preserve for diagnosis.");
|
|
100013
100134
|
const archive = `.tmp/context-runtime/locks/recovered-write-${randomUUID7()}.lock`;
|
|
100014
|
-
await rename8(path3,
|
|
100135
|
+
await rename8(path3, join101(input.projectRoot, archive));
|
|
100015
100136
|
archived = true;
|
|
100016
100137
|
return { action: "writer-lock-recovered", archived_lock: archive, next: "context task recover --format json" };
|
|
100017
100138
|
} finally {
|
|
@@ -100035,8 +100156,8 @@ __export(exports_taskRecovery, {
|
|
|
100035
100156
|
RECOVERY_COMMAND: () => RECOVERY_COMMAND
|
|
100036
100157
|
});
|
|
100037
100158
|
import { existsSync as existsSync26 } from "node:fs";
|
|
100038
|
-
import { dirname as dirname41, join as
|
|
100039
|
-
import { lstat as lstat11, readdir as
|
|
100159
|
+
import { dirname as dirname41, join as join102 } from "node:path";
|
|
100160
|
+
import { lstat as lstat11, readdir as readdir26, readFile as readFile83 } from "node:fs/promises";
|
|
100040
100161
|
async function recoveryText(root2, path3) {
|
|
100041
100162
|
const target = await safeProjectTarget(root2, path3);
|
|
100042
100163
|
try {
|
|
@@ -100053,7 +100174,7 @@ async function recoveryJournals(root2) {
|
|
|
100053
100174
|
await safeProjectTarget(root2, path3);
|
|
100054
100175
|
let stat11;
|
|
100055
100176
|
try {
|
|
100056
|
-
stat11 = await lstat11(
|
|
100177
|
+
stat11 = await lstat11(join102(root2, path3));
|
|
100057
100178
|
} catch (error) {
|
|
100058
100179
|
if (error.code === "ENOENT")
|
|
100059
100180
|
return;
|
|
@@ -100064,7 +100185,7 @@ async function recoveryJournals(root2) {
|
|
|
100064
100185
|
if (stat11.isDirectory()) {
|
|
100065
100186
|
if (depth > 3)
|
|
100066
100187
|
throw new TypeError("Unexpected transaction directory depth; preserve it for diagnosis.");
|
|
100067
|
-
for (const name3 of (await
|
|
100188
|
+
for (const name3 of (await readdir26(join102(root2, path3))).sort())
|
|
100068
100189
|
await visit4(`${path3}/${name3}`, depth + 1);
|
|
100069
100190
|
} else if (stat11.isFile())
|
|
100070
100191
|
entries2.push({ path: path3, digest: indexerProtocolDigest(await recoveryText(root2, path3)) });
|
|
@@ -100076,8 +100197,8 @@ function recoveryResources() {
|
|
|
100076
100197
|
try {
|
|
100077
100198
|
const root2 = dirname41(contextWorkflowProviderPath());
|
|
100078
100199
|
const resources = {
|
|
100079
|
-
skill:
|
|
100080
|
-
issue_template:
|
|
100200
|
+
skill: join102(root2, "skills/recover-workspace/SKILL.md"),
|
|
100201
|
+
issue_template: join102(root2, "resources/templates/recovery-issue.md")
|
|
100081
100202
|
};
|
|
100082
100203
|
if (!Object.values(resources).every((path3) => existsSync26(path3)))
|
|
100083
100204
|
throw new Error("Recovery resources are absent from this Provider.");
|
|
@@ -100163,7 +100284,7 @@ __export(exports_taskLocalSourceAdjustment, {
|
|
|
100163
100284
|
adjustLocalRevisionSources: () => adjustLocalRevisionSources
|
|
100164
100285
|
});
|
|
100165
100286
|
import { readFile as readFile84 } from "node:fs/promises";
|
|
100166
|
-
import { join as
|
|
100287
|
+
import { join as join103 } from "node:path";
|
|
100167
100288
|
async function adjustLocalRevisionSources(root2, input) {
|
|
100168
100289
|
const { readMaintenance: readMaintenance2 } = await Promise.resolve().then(() => (init_maintenanceStorage(), exports_maintenanceStorage));
|
|
100169
100290
|
if ((await readMaintenance2(root2)).active && await readProductionStage(root2))
|
|
@@ -100206,7 +100327,7 @@ async function adjustLocalRevisionSources(root2, input) {
|
|
|
100206
100327
|
if (input.refresh && (!current2.refresh_sources || indexerProtocolDigest([...current2.refresh_sources].sort()) !== indexerProtocolDigest([...selected].sort()))) {
|
|
100207
100328
|
throw new TypeError("No matching acquisition adjustment exists. Run task adjust without refresh first.");
|
|
100208
100329
|
}
|
|
100209
|
-
const raw = await readFile84(
|
|
100330
|
+
const raw = await readFile84(join103(root2, await revisionStoragePath(root2)), "utf8");
|
|
100210
100331
|
let next2;
|
|
100211
100332
|
const discardIds = new Set;
|
|
100212
100333
|
if (!input.refresh) {
|
|
@@ -100309,7 +100430,7 @@ ${input.instruction}` : revision.instruction
|
|
|
100309
100430
|
content: content3
|
|
100310
100431
|
}];
|
|
100311
100432
|
if (discardIds.size > 0) {
|
|
100312
|
-
const ledger = await readFile84(
|
|
100433
|
+
const ledger = await readFile84(join103(root2, CANDIDATE_LEDGER_FILE), "utf8").catch((error) => {
|
|
100313
100434
|
if (error.code === "ENOENT")
|
|
100314
100435
|
return;
|
|
100315
100436
|
throw error;
|
|
@@ -100566,7 +100687,7 @@ __export(exports_managedDocumentRename, {
|
|
|
100566
100687
|
renameManagedDocument: () => renameManagedDocument
|
|
100567
100688
|
});
|
|
100568
100689
|
import { readFile as readFile92 } from "node:fs/promises";
|
|
100569
|
-
import { join as
|
|
100690
|
+
import { join as join111, posix as posix11 } from "node:path";
|
|
100570
100691
|
async function optionalText2(path3) {
|
|
100571
100692
|
try {
|
|
100572
100693
|
return await readFile92(path3, "utf8");
|
|
@@ -100653,7 +100774,7 @@ async function renameManagedDocument(input) {
|
|
|
100653
100774
|
if (path3.split("/").includes("..") || path3.startsWith("/"))
|
|
100654
100775
|
throw new TypeError("Source references contain an unsafe knowledge path; repair it before renaming.");
|
|
100655
100776
|
await safeProjectTarget(input.projectRoot, path3);
|
|
100656
|
-
const before = await optionalText2(
|
|
100777
|
+
const before = await optionalText2(join111(input.projectRoot, path3));
|
|
100657
100778
|
if (before === undefined)
|
|
100658
100779
|
continue;
|
|
100659
100780
|
let after;
|
|
@@ -100742,7 +100863,7 @@ var init_managedDocumentRename = __esm(() => {
|
|
|
100742
100863
|
|
|
100743
100864
|
// src/cli.ts
|
|
100744
100865
|
import { existsSync as existsSync36, realpathSync as realpathSync3 } from "node:fs";
|
|
100745
|
-
import { dirname as dirname49, join as
|
|
100866
|
+
import { dirname as dirname49, join as join117 } from "node:path";
|
|
100746
100867
|
import { fileURLToPath as fileURLToPath11, pathToFileURL as pathToFileURL3 } from "node:url";
|
|
100747
100868
|
|
|
100748
100869
|
// ../../node_modules/.bun/commander@11.1.0/node_modules/commander/esm.mjs
|
|
@@ -106025,14 +106146,14 @@ function compactJsonResult(result, verbose) {
|
|
|
106025
106146
|
// src/project/runLog.ts
|
|
106026
106147
|
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
106027
106148
|
import { mkdir as mkdir33, writeFile as writeFile26 } from "node:fs/promises";
|
|
106028
|
-
import { dirname as dirname39, join as
|
|
106149
|
+
import { dirname as dirname39, join as join97 } from "node:path";
|
|
106029
106150
|
var createPhaseRunId = () => {
|
|
106030
106151
|
const timestamp = new Date().toISOString().replace(/[-:.TZ]/gu, "");
|
|
106031
106152
|
return `run_${timestamp}_${randomUUID5().slice(0, 8)}`;
|
|
106032
106153
|
};
|
|
106033
106154
|
async function writePhaseRunLog(input) {
|
|
106034
|
-
const relPath =
|
|
106035
|
-
const absPath =
|
|
106155
|
+
const relPath = join97(".tmp", "context-runtime", "runs", `${input.runId}.json`);
|
|
106156
|
+
const absPath = join97(input.projectRoot, relPath);
|
|
106036
106157
|
await mkdir33(dirname39(absPath), { recursive: true });
|
|
106037
106158
|
await writeFile26(absPath, `${JSON.stringify({
|
|
106038
106159
|
run_id: input.runId,
|
|
@@ -107132,7 +107253,7 @@ init_reviewApplyIndexer();
|
|
|
107132
107253
|
init_approvedKnowledgeSnapshots();
|
|
107133
107254
|
import { existsSync as existsSync25 } from "node:fs";
|
|
107134
107255
|
import { readFile as readFile76 } from "node:fs/promises";
|
|
107135
|
-
import { join as
|
|
107256
|
+
import { join as join98 } from "node:path";
|
|
107136
107257
|
|
|
107137
107258
|
// src/project/reviewCandidateAuthority.ts
|
|
107138
107259
|
init_src2();
|
|
@@ -107195,7 +107316,7 @@ async function prepareApprovedPage(input) {
|
|
|
107195
107316
|
next: "Refresh the current production or article revision, then reopen Review before approval."
|
|
107196
107317
|
});
|
|
107197
107318
|
}
|
|
107198
|
-
const relPath =
|
|
107319
|
+
const relPath = join98("knowledge", input.record.path);
|
|
107199
107320
|
const existingView = findApprovedPageForArticleId(input.record.indexer_candidate.artifact_ref, input.approvedPageIndex);
|
|
107200
107321
|
const previousPath = input.record.approved_revision?.previous_path;
|
|
107201
107322
|
if (previousPath !== undefined && (!isSafeKnowledgeTargetPath(previousPath.split("/")[0], previousPath) || previousPath.includes("\\")))
|
|
@@ -107210,13 +107331,13 @@ async function prepareApprovedPage(input) {
|
|
|
107210
107331
|
next: "Resolve the approved page path migration explicitly before approving this candidate."
|
|
107211
107332
|
});
|
|
107212
107333
|
}
|
|
107213
|
-
const absPath =
|
|
107334
|
+
const absPath = join98(input.projectRoot, relPath);
|
|
107214
107335
|
const existing = existsSync25(absPath) ? await readFile76(absPath, "utf8") : undefined;
|
|
107215
107336
|
let previous3;
|
|
107216
107337
|
if (previousPath !== undefined) {
|
|
107217
107338
|
if (existing !== undefined || existingView?.relPath !== `knowledge/${previousPath}`)
|
|
107218
107339
|
throw new TypeError("Page move destination or original identity changed; refresh its revision.");
|
|
107219
|
-
previous3 = { path: `knowledge/${previousPath}`, content: await readFile76(
|
|
107340
|
+
previous3 = { path: `knowledge/${previousPath}`, content: await readFile76(join98(input.projectRoot, "knowledge", previousPath), "utf8") };
|
|
107220
107341
|
}
|
|
107221
107342
|
if (input.record.approved_revision !== undefined) {
|
|
107222
107343
|
const base = previous3?.content ?? existing;
|
|
@@ -107263,7 +107384,7 @@ async function prepareApprovedPage(input) {
|
|
|
107263
107384
|
}
|
|
107264
107385
|
async function readProjectFileMaybe(projectRoot, relPath) {
|
|
107265
107386
|
try {
|
|
107266
|
-
return await readFile76(
|
|
107387
|
+
return await readFile76(join98(projectRoot, relPath), "utf8");
|
|
107267
107388
|
} catch (error) {
|
|
107268
107389
|
if (error !== null && typeof error === "object" && "code" in error && error.code === "ENOENT") {
|
|
107269
107390
|
return;
|
|
@@ -107486,7 +107607,7 @@ async function applyReviewDecisions(input) {
|
|
|
107486
107607
|
});
|
|
107487
107608
|
}
|
|
107488
107609
|
seenApprovedIds.set(approvedRef, row.candidate_id);
|
|
107489
|
-
const approvedPath =
|
|
107610
|
+
const approvedPath = join98("knowledge", row.path);
|
|
107490
107611
|
const previousPathCandidate = seenApprovedPaths.get(knowledgeTargetPathKey(approvedPath));
|
|
107491
107612
|
if (previousPathCandidate !== undefined) {
|
|
107492
107613
|
throw new ContextError(ExitCode.UserError, `multiple approved review decisions target the same knowledge path: ${approvedPath}`, {
|
|
@@ -107536,7 +107657,7 @@ async function applyReviewDecisions(input) {
|
|
|
107536
107657
|
for (const path3 of approvedPageIndex.byRelPath.keys()) {
|
|
107537
107658
|
if (pagesToWrite.some((page) => page.relPath === path3 || page.previous?.path === path3))
|
|
107538
107659
|
continue;
|
|
107539
|
-
const before = await readFile76(
|
|
107660
|
+
const before = await readFile76(join98(input.projectRoot, path3), "utf8");
|
|
107540
107661
|
const local = path3.replace(/^knowledge\//u, "");
|
|
107541
107662
|
const after = moveKnowledgeLinkTargets2(before, local, local, moved);
|
|
107542
107663
|
navigationTargets.push(reviewFileTarget({ path: path3, baseContent: before, targetContent: after }));
|
|
@@ -107620,12 +107741,12 @@ init_candidateLedger();
|
|
|
107620
107741
|
|
|
107621
107742
|
// src/project/localHtmlReport.ts
|
|
107622
107743
|
import { execFile as execFile11 } from "node:child_process";
|
|
107623
|
-
import { isAbsolute as isAbsolute17, join as
|
|
107744
|
+
import { isAbsolute as isAbsolute17, join as join99 } from "node:path";
|
|
107624
107745
|
import { pathToFileURL as pathToFileURL2 } from "node:url";
|
|
107625
107746
|
import { promisify as promisify11 } from "node:util";
|
|
107626
107747
|
var execFileAsync5 = promisify11(execFile11);
|
|
107627
107748
|
function htmlReportReference(input) {
|
|
107628
|
-
const absolutePath = isAbsolute17(input.path) ? input.path :
|
|
107749
|
+
const absolutePath = isAbsolute17(input.path) ? input.path : join99(input.projectRoot, input.path);
|
|
107629
107750
|
return {
|
|
107630
107751
|
format: "html",
|
|
107631
107752
|
path: input.path,
|
|
@@ -108649,7 +108770,7 @@ init_maintenanceStorage();
|
|
|
108649
108770
|
init_productionFeedback();
|
|
108650
108771
|
import { randomUUID as randomUUID6 } from "node:crypto";
|
|
108651
108772
|
import { readFile as readFile79 } from "node:fs/promises";
|
|
108652
|
-
import { join as
|
|
108773
|
+
import { join as join100 } from "node:path";
|
|
108653
108774
|
async function beginProductionRevision(input) {
|
|
108654
108775
|
return withProductionFeedback({ operation: "revision" }, () => withProjectWriteLock(input.projectRoot, "production-revision", async () => {
|
|
108655
108776
|
await recoverDurableMultiFileTransactions(input.projectRoot);
|
|
@@ -108688,7 +108809,7 @@ async function beginProductionRevision(input) {
|
|
|
108688
108809
|
const formal = approved.byPath.get(path3);
|
|
108689
108810
|
if (!prior && !formal)
|
|
108690
108811
|
throw invalid2("Write the current task first; there is no article draft to revise yet.");
|
|
108691
|
-
const markdown = prior?.body ?? await readFile79(await safeProjectTarget(input.projectRoot,
|
|
108812
|
+
const markdown = prior?.body ?? await readFile79(await safeProjectTarget(input.projectRoot, join100("knowledge", path3)), "utf8");
|
|
108692
108813
|
const sections = prior?.indexer_candidate.sections.map((section) => ({ id: section.section_key, references: section.references })) ?? formal?.sections;
|
|
108693
108814
|
const sources = [];
|
|
108694
108815
|
for (const source2 of owner.sources) {
|
|
@@ -109328,7 +109449,7 @@ init_atomicWrite();
|
|
|
109328
109449
|
var import_yaml44 = __toESM(require_dist(), 1);
|
|
109329
109450
|
import { Buffer as Buffer4 } from "node:buffer";
|
|
109330
109451
|
import { createHash as createHash31 } from "node:crypto";
|
|
109331
|
-
import { join as
|
|
109452
|
+
import { join as join104 } from "node:path";
|
|
109332
109453
|
var INLINE_LIMIT = 16 * 1024;
|
|
109333
109454
|
function record4(value) {
|
|
109334
109455
|
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : undefined;
|
|
@@ -109354,8 +109475,8 @@ async function prepareActionCompletionOutput(input) {
|
|
|
109354
109475
|
if (production && Buffer4.byteLength(full) <= INLINE_LIMIT)
|
|
109355
109476
|
return input.result;
|
|
109356
109477
|
const digest6 = createHash31("sha256").update(full).digest("hex");
|
|
109357
|
-
const root2 =
|
|
109358
|
-
const resultFile =
|
|
109478
|
+
const root2 = join104(input.projectRoot, ".tmp/context-runtime/action-results");
|
|
109479
|
+
const resultFile = join104(root2, `${digest6}.json`);
|
|
109359
109480
|
await atomicWriteFile(resultFile, full);
|
|
109360
109481
|
if (production)
|
|
109361
109482
|
return {
|
|
@@ -109366,7 +109487,7 @@ async function prepareActionCompletionOutput(input) {
|
|
|
109366
109487
|
...pick(result, ["next", "next_preparation"])
|
|
109367
109488
|
};
|
|
109368
109489
|
const next2 = record4(result.next) ?? record4(record4(result.workflow)?.current) ?? record4(record4(result.continuation)?.next);
|
|
109369
|
-
const nextFile = next2 === undefined ? undefined :
|
|
109490
|
+
const nextFile = next2 === undefined ? undefined : join104(root2, `${digest6}.next.json`);
|
|
109370
109491
|
if (nextFile !== undefined)
|
|
109371
109492
|
await atomicWriteFile(nextFile, serializeActionCompletion(next2, "json"));
|
|
109372
109493
|
const outcomes = (Array.isArray(result.outcomes) ? result.outcomes : []).map(record4).filter((item) => item !== undefined);
|
|
@@ -109771,9 +109892,9 @@ function registerProjectActionCommands(program2) {
|
|
|
109771
109892
|
// src/commands/cleanClaudePluginCache.ts
|
|
109772
109893
|
init_cliFeedback();
|
|
109773
109894
|
import { existsSync as existsSync27 } from "node:fs";
|
|
109774
|
-
import { readdir as
|
|
109895
|
+
import { readdir as readdir27, rm as rm22 } from "node:fs/promises";
|
|
109775
109896
|
import { homedir } from "node:os";
|
|
109776
|
-
import { join as
|
|
109897
|
+
import { join as join105 } from "node:path";
|
|
109777
109898
|
var ORPHAN_MARKER = ".orphaned_at";
|
|
109778
109899
|
var CLAUDE_PLUGIN_CACHE_ROOT_ENV = "C4A_CLAUDE_PLUGIN_CACHE_ROOT";
|
|
109779
109900
|
var CLAUDE_PLUGIN_CACHE_HOME_ENV = "C4A_CLAUDE_PLUGIN_CACHE_HOME";
|
|
@@ -109786,40 +109907,40 @@ async function cleanClaudePluginCache(opts = {}) {
|
|
|
109786
109907
|
lines.push("· claude plugin cache: missing — nothing to clean");
|
|
109787
109908
|
return { lines, removed, scanned };
|
|
109788
109909
|
}
|
|
109789
|
-
const marketplaces = await
|
|
109910
|
+
const marketplaces = await readdir27(cacheRoot, { withFileTypes: true });
|
|
109790
109911
|
for (const mp of marketplaces) {
|
|
109791
109912
|
if (!mp.isDirectory())
|
|
109792
109913
|
continue;
|
|
109793
|
-
const mpDir =
|
|
109794
|
-
const plugins = await
|
|
109914
|
+
const mpDir = join105(cacheRoot, mp.name);
|
|
109915
|
+
const plugins = await readdir27(mpDir, { withFileTypes: true });
|
|
109795
109916
|
for (const pl of plugins) {
|
|
109796
109917
|
if (!pl.isDirectory())
|
|
109797
109918
|
continue;
|
|
109798
|
-
const plDir =
|
|
109799
|
-
const versions = await
|
|
109919
|
+
const plDir = join105(mpDir, pl.name);
|
|
109920
|
+
const versions = await readdir27(plDir, { withFileTypes: true });
|
|
109800
109921
|
for (const ver of versions) {
|
|
109801
109922
|
if (!ver.isDirectory())
|
|
109802
109923
|
continue;
|
|
109803
109924
|
scanned += 1;
|
|
109804
|
-
const verDir =
|
|
109805
|
-
const markerPath =
|
|
109925
|
+
const verDir = join105(plDir, ver.name);
|
|
109926
|
+
const markerPath = join105(verDir, ORPHAN_MARKER);
|
|
109806
109927
|
if (!existsSync27(markerPath))
|
|
109807
109928
|
continue;
|
|
109808
109929
|
const label2 = `${mp.name}/${pl.name}/${ver.name}`;
|
|
109809
109930
|
if (opts.dryRun) {
|
|
109810
109931
|
lines.push(` - would remove: ${label2}`);
|
|
109811
109932
|
} else {
|
|
109812
|
-
await
|
|
109933
|
+
await rm22(verDir, { recursive: true, force: true });
|
|
109813
109934
|
removed += 1;
|
|
109814
109935
|
lines.push(` ✓ removed: ${label2}`);
|
|
109815
109936
|
}
|
|
109816
109937
|
}
|
|
109817
109938
|
if (!opts.dryRun && await isEmptyDir(plDir)) {
|
|
109818
|
-
await
|
|
109939
|
+
await rm22(plDir, { recursive: true, force: true });
|
|
109819
109940
|
}
|
|
109820
109941
|
}
|
|
109821
109942
|
if (!opts.dryRun && await isEmptyDir(mpDir)) {
|
|
109822
|
-
await
|
|
109943
|
+
await rm22(mpDir, { recursive: true, force: true });
|
|
109823
109944
|
}
|
|
109824
109945
|
}
|
|
109825
109946
|
if (scanned === 0) {
|
|
@@ -109834,11 +109955,11 @@ function resolveClaudePluginCacheRoot(opts) {
|
|
|
109834
109955
|
if (explicitRoot)
|
|
109835
109956
|
return explicitRoot;
|
|
109836
109957
|
const home = opts.home ?? process.env[CLAUDE_PLUGIN_CACHE_HOME_ENV] ?? homedir();
|
|
109837
|
-
return
|
|
109958
|
+
return join105(home, ".claude", "plugins", "cache");
|
|
109838
109959
|
}
|
|
109839
109960
|
async function isEmptyDir(dir) {
|
|
109840
109961
|
try {
|
|
109841
|
-
const entries2 = await
|
|
109962
|
+
const entries2 = await readdir27(dir);
|
|
109842
109963
|
return entries2.length === 0;
|
|
109843
109964
|
} catch {
|
|
109844
109965
|
return false;
|
|
@@ -109866,13 +109987,13 @@ init_exitCode();
|
|
|
109866
109987
|
|
|
109867
109988
|
// src/lib/packageVersion.ts
|
|
109868
109989
|
import { existsSync as existsSync28, readFileSync as readFileSync9 } from "node:fs";
|
|
109869
|
-
import { dirname as dirname42, join as
|
|
109990
|
+
import { dirname as dirname42, join as join106 } from "node:path";
|
|
109870
109991
|
import { fileURLToPath as fileURLToPath8 } from "node:url";
|
|
109871
109992
|
function readPackageVersion() {
|
|
109872
109993
|
try {
|
|
109873
109994
|
let dir = dirname42(fileURLToPath8(import.meta.url));
|
|
109874
109995
|
for (let depth = 0;depth < 8; depth += 1) {
|
|
109875
|
-
const packagePath =
|
|
109996
|
+
const packagePath = join106(dir, "package.json");
|
|
109876
109997
|
if (existsSync28(packagePath)) {
|
|
109877
109998
|
const parsed = JSON.parse(readFileSync9(packagePath, "utf8"));
|
|
109878
109999
|
if (typeof parsed.version === "string" && parsed.version.length > 0) {
|
|
@@ -109912,7 +110033,7 @@ init_repoSourceRegistry();
|
|
|
109912
110033
|
init_writeLock();
|
|
109913
110034
|
import { execFile as execFile12 } from "node:child_process";
|
|
109914
110035
|
import { existsSync as existsSync29 } from "node:fs";
|
|
109915
|
-
import { lstat as lstat12, mkdir as mkdir35, readlink as readlink2, realpath as realpath10, rm as
|
|
110036
|
+
import { lstat as lstat12, mkdir as mkdir35, readlink as readlink2, realpath as realpath10, rm as rm23, symlink as symlink4 } from "node:fs/promises";
|
|
109916
110037
|
import { basename as basename11, dirname as dirname43, isAbsolute as isAbsolute19, relative as relative26, resolve as resolve34 } from "node:path";
|
|
109917
110038
|
import { promisify as promisify12 } from "node:util";
|
|
109918
110039
|
var execFileAsync6 = promisify12(execFile12);
|
|
@@ -110102,14 +110223,14 @@ async function cloneCheckout(input) {
|
|
|
110102
110223
|
try {
|
|
110103
110224
|
await execFileAsync6("git", cloneArgs, { encoding: "utf8", maxBuffer: 4 * 1024 * 1024 });
|
|
110104
110225
|
} catch {
|
|
110105
|
-
await
|
|
110226
|
+
await rm23(target, { recursive: true, force: true });
|
|
110106
110227
|
try {
|
|
110107
110228
|
await execFileAsync6("git", ["clone", "--no-checkout", "--depth=1", input.remote, target], {
|
|
110108
110229
|
encoding: "utf8",
|
|
110109
110230
|
maxBuffer: 4 * 1024 * 1024
|
|
110110
110231
|
});
|
|
110111
110232
|
} catch (error) {
|
|
110112
|
-
await
|
|
110233
|
+
await rm23(target, { recursive: true, force: true });
|
|
110113
110234
|
const detail = error !== null && typeof error === "object" && "stderr" in error ? String(error.stderr ?? "").trim() : error instanceof Error ? error.message : String(error);
|
|
110114
110235
|
throw new ContextError(ExitCode.ExternalToolError, `cannot clone registered repository: ${input.remote}`, {
|
|
110115
110236
|
category: ErrorCategory.ExternalToolFailed,
|
|
@@ -110134,7 +110255,7 @@ async function cloneCheckout(input) {
|
|
|
110134
110255
|
await verifyCheckout({ checkout: target, remote: input.remote, ref: input.ref, subpaths: input.subpaths });
|
|
110135
110256
|
return target;
|
|
110136
110257
|
} catch (error) {
|
|
110137
|
-
await
|
|
110258
|
+
await rm23(target, { recursive: true, force: true });
|
|
110138
110259
|
throw error;
|
|
110139
110260
|
}
|
|
110140
110261
|
}
|
|
@@ -110150,7 +110271,7 @@ async function bindLocalAlias(input) {
|
|
|
110150
110271
|
const actualReal = await realpath10(actual).catch(() => null);
|
|
110151
110272
|
if (actualReal !== null && actualReal === await realpath10(input.checkout))
|
|
110152
110273
|
return;
|
|
110153
|
-
await
|
|
110274
|
+
await rm23(alias);
|
|
110154
110275
|
} else {
|
|
110155
110276
|
const actual = await realpath10(alias);
|
|
110156
110277
|
if (actual === await realpath10(input.checkout))
|
|
@@ -110259,14 +110380,14 @@ init_src2();
|
|
|
110259
110380
|
init_documentCapture();
|
|
110260
110381
|
import { existsSync as existsSync30 } from "node:fs";
|
|
110261
110382
|
import { readFile as readFile86 } from "node:fs/promises";
|
|
110262
|
-
import { join as
|
|
110383
|
+
import { join as join108 } from "node:path";
|
|
110263
110384
|
|
|
110264
110385
|
// src/project/sourceCommandViews.ts
|
|
110265
110386
|
init_documentSiteDetection();
|
|
110266
110387
|
init_workspace();
|
|
110267
110388
|
init_documentBatchManifest();
|
|
110268
110389
|
import { readFile as readFile85 } from "node:fs/promises";
|
|
110269
|
-
import { join as
|
|
110390
|
+
import { join as join107 } from "node:path";
|
|
110270
110391
|
function repoSourceAgentView(source2) {
|
|
110271
110392
|
return {
|
|
110272
110393
|
id: source2.id ?? source2.name,
|
|
@@ -110327,7 +110448,7 @@ async function fileSourceAgentViewWithNextAction(input) {
|
|
|
110327
110448
|
};
|
|
110328
110449
|
}
|
|
110329
110450
|
function documentSourceManifestPath(source2) {
|
|
110330
|
-
return source2.snapshot?.manifest ??
|
|
110451
|
+
return source2.snapshot?.manifest ?? join107(source2.materializedAt, "manifest.json");
|
|
110331
110452
|
}
|
|
110332
110453
|
async function fileSourceDocumentSiteHint(input) {
|
|
110333
110454
|
const detection = await detectDocumentSiteFiles({
|
|
@@ -110337,7 +110458,7 @@ async function fileSourceDocumentSiteHint(input) {
|
|
|
110337
110458
|
let snapshotConfigured = false;
|
|
110338
110459
|
const manifest = documentSourceManifestPath(input.source);
|
|
110339
110460
|
try {
|
|
110340
|
-
const parsed = parseDocumentSnapshotForSource(JSON.parse(await readFile85(
|
|
110461
|
+
const parsed = parseDocumentSnapshotForSource(JSON.parse(await readFile85(join107(input.projectRoot, manifest), "utf8")), input.source.name);
|
|
110341
110462
|
snapshotConfigured = manifestUsesMdxJsonDocs(parsed);
|
|
110342
110463
|
} catch {
|
|
110343
110464
|
snapshotConfigured = false;
|
|
@@ -110370,11 +110491,11 @@ async function larkSourceAgentViewWithNextAction(input) {
|
|
|
110370
110491
|
init_documentBatchManifest();
|
|
110371
110492
|
init_documentSnapshotFidelity();
|
|
110372
110493
|
function documentSourceManifestPath2(source2) {
|
|
110373
|
-
return source2.snapshot?.manifest ??
|
|
110494
|
+
return source2.snapshot?.manifest ?? join108(source2.materializedAt, "manifest.json");
|
|
110374
110495
|
}
|
|
110375
110496
|
async function documentSnapshotState(input) {
|
|
110376
110497
|
const manifest = documentSourceManifestPath2(input.source);
|
|
110377
|
-
const manifestPath =
|
|
110498
|
+
const manifestPath = join108(input.projectRoot, manifest);
|
|
110378
110499
|
if (!existsSync30(manifestPath)) {
|
|
110379
110500
|
return {
|
|
110380
110501
|
snapshotReady: false,
|
|
@@ -110453,7 +110574,7 @@ async function documentSnapshotState(input) {
|
|
|
110453
110574
|
const missing = [
|
|
110454
110575
|
...parsed.files.map((file) => file.path),
|
|
110455
110576
|
...(parsed.assets ?? []).filter((asset) => asset.content_hash !== undefined).map((asset) => asset.path)
|
|
110456
|
-
].find((path3) => !existsSync30(
|
|
110577
|
+
].find((path3) => !existsSync30(join108(input.projectRoot, input.source.materializedAt, path3)));
|
|
110457
110578
|
if (missing !== undefined) {
|
|
110458
110579
|
return {
|
|
110459
110580
|
snapshotReady: false,
|
|
@@ -110555,7 +110676,7 @@ init_exitCode();
|
|
|
110555
110676
|
var import_yaml47 = __toESM(require_dist(), 1);
|
|
110556
110677
|
import { createHash as createHash32 } from "node:crypto";
|
|
110557
110678
|
import { readFile as readFile87, realpath as realpath11 } from "node:fs/promises";
|
|
110558
|
-
import { basename as basename12, extname as extname15, isAbsolute as isAbsolute20, join as
|
|
110679
|
+
import { basename as basename12, extname as extname15, isAbsolute as isAbsolute20, join as join109, relative as relative27, resolve as resolve35 } from "node:path";
|
|
110559
110680
|
init_writeLock();
|
|
110560
110681
|
var SOURCE_NAME_PATTERN3 = /^[a-z0-9][a-z0-9._-]*$/u;
|
|
110561
110682
|
function isDateSourceNamespace(value) {
|
|
@@ -110651,7 +110772,7 @@ function assertSafeFileInclude(value) {
|
|
|
110651
110772
|
}
|
|
110652
110773
|
async function readRegistryDocument(projectRoot, registryPath2) {
|
|
110653
110774
|
try {
|
|
110654
|
-
const content3 = await readFile87(
|
|
110775
|
+
const content3 = await readFile87(join109(projectRoot, registryPath2), "utf8");
|
|
110655
110776
|
return content3.trim().length === 0 ? { sources: [] } : import_yaml47.default.parse(content3);
|
|
110656
110777
|
} catch (error) {
|
|
110657
110778
|
if (error instanceof Error && "code" in error && error.code === "ENOENT")
|
|
@@ -110769,7 +110890,7 @@ async function addFileSourceUnlocked(input) {
|
|
|
110769
110890
|
const record6 = entry2;
|
|
110770
110891
|
return record6.name !== input.name && record6.id !== input.name;
|
|
110771
110892
|
}), nextEntry];
|
|
110772
|
-
await atomicWriteFile(
|
|
110893
|
+
await atomicWriteFile(join109(input.projectRoot, DEFAULT_FILE_SOURCES_REGISTRY_PATH), import_yaml47.default.stringify({ sources: nextSources }));
|
|
110773
110894
|
const updated = await loadSourcesRegistry({ rootDir: input.projectRoot });
|
|
110774
110895
|
const entry = updated.files.find((source2) => source2.name === input.name || source2.id === input.name);
|
|
110775
110896
|
if (entry === undefined) {
|
|
@@ -110825,7 +110946,7 @@ async function addLarkSourceUnlocked(input) {
|
|
|
110825
110946
|
const record6 = entry2;
|
|
110826
110947
|
return record6.name !== input.name && record6.id !== input.name;
|
|
110827
110948
|
}), nextEntry];
|
|
110828
|
-
await atomicWriteFile(
|
|
110949
|
+
await atomicWriteFile(join109(input.projectRoot, DEFAULT_LARK_SOURCES_REGISTRY_PATH), import_yaml47.default.stringify({ sources: nextSources }));
|
|
110829
110950
|
const updated = await loadSourcesRegistry({ rootDir: input.projectRoot });
|
|
110830
110951
|
const entry = updated.larks.find((source2) => source2.name === input.name || source2.id === input.name);
|
|
110831
110952
|
if (entry === undefined) {
|
|
@@ -111029,8 +111150,8 @@ init_writeLock();
|
|
|
111029
111150
|
var import_yaml48 = __toESM(require_dist(), 1);
|
|
111030
111151
|
import { existsSync as existsSync31 } from "node:fs";
|
|
111031
111152
|
import { createHash as createHash33 } from "node:crypto";
|
|
111032
|
-
import { readFile as readFile88, readdir as
|
|
111033
|
-
import { isAbsolute as isAbsolute21, join as
|
|
111153
|
+
import { readFile as readFile88, readdir as readdir28, rm as rm24 } from "node:fs/promises";
|
|
111154
|
+
import { isAbsolute as isAbsolute21, join as join110, relative as relative28, resolve as resolve36, sep as sep8 } from "node:path";
|
|
111034
111155
|
function sourceIdentity(source2) {
|
|
111035
111156
|
if (source2.kind === "source.collection")
|
|
111036
111157
|
return;
|
|
@@ -111062,7 +111183,7 @@ function collectStrings(value, output) {
|
|
|
111062
111183
|
}
|
|
111063
111184
|
}
|
|
111064
111185
|
async function yamlReferences(input) {
|
|
111065
|
-
const absolutePath =
|
|
111186
|
+
const absolutePath = join110(input.projectRoot, input.path);
|
|
111066
111187
|
if (!existsSync31(absolutePath))
|
|
111067
111188
|
return false;
|
|
111068
111189
|
const parsed = import_yaml48.default.parse(await readFile88(absolutePath, "utf8"));
|
|
@@ -111191,7 +111312,7 @@ async function registryRemovalWrite(projectRoot, source2) {
|
|
|
111191
111312
|
const path3 = registryPath2(source2.type);
|
|
111192
111313
|
if (path3 === null)
|
|
111193
111314
|
return;
|
|
111194
|
-
const absolutePath =
|
|
111315
|
+
const absolutePath = join110(projectRoot, path3);
|
|
111195
111316
|
const document4 = existsSync31(absolutePath) ? import_yaml48.default.parse(await readFile88(absolutePath, "utf8")) : { sources: [] };
|
|
111196
111317
|
return {
|
|
111197
111318
|
path: absolutePath,
|
|
@@ -111210,7 +111331,7 @@ function safeManagedMaterializedPath(projectRoot, source2) {
|
|
|
111210
111331
|
return absolute;
|
|
111211
111332
|
}
|
|
111212
111333
|
function safeManagedManifestPath(projectRoot, source2) {
|
|
111213
|
-
const manifest = source2.manifest ??
|
|
111334
|
+
const manifest = source2.manifest ?? join110(source2.materializedAt, "manifest.json");
|
|
111214
111335
|
if (isAbsolute21(manifest))
|
|
111215
111336
|
throw unsafeOwnership(source2, manifest);
|
|
111216
111337
|
const absolute = resolve36(projectRoot, manifest);
|
|
@@ -111372,7 +111493,7 @@ function publicRemovalResult(plan, action) {
|
|
|
111372
111493
|
};
|
|
111373
111494
|
}
|
|
111374
111495
|
async function pruneExtractRuntime(projectRoot, source2) {
|
|
111375
|
-
const fingerprintPath =
|
|
111496
|
+
const fingerprintPath = join110(projectRoot, ".tmp/context-runtime/extract/source-fingerprints.json");
|
|
111376
111497
|
const removedPhaseIds = new Set;
|
|
111377
111498
|
if (existsSync31(fingerprintPath)) {
|
|
111378
111499
|
const parsed = JSON.parse(await readFile88(fingerprintPath, "utf8"));
|
|
@@ -111389,14 +111510,14 @@ async function pruneExtractRuntime(projectRoot, source2) {
|
|
|
111389
111510
|
await atomicWriteFile(fingerprintPath, `${JSON.stringify({ ...parsed, phases: next2 }, null, 2)}
|
|
111390
111511
|
`);
|
|
111391
111512
|
}
|
|
111392
|
-
const phaseOwnershipPath =
|
|
111513
|
+
const phaseOwnershipPath = join110(projectRoot, ".tmp/context-runtime/extract/custom-phase-candidates.json");
|
|
111393
111514
|
if (existsSync31(phaseOwnershipPath) && removedPhaseIds.size > 0) {
|
|
111394
111515
|
const parsed = JSON.parse(await readFile88(phaseOwnershipPath, "utf8"));
|
|
111395
111516
|
const phases = Object.fromEntries(Object.entries(parsed.phases ?? {}).filter(([phaseId]) => !removedPhaseIds.has(phaseId)));
|
|
111396
111517
|
await atomicWriteFile(phaseOwnershipPath, `${JSON.stringify({ ...parsed, phases }, null, 2)}
|
|
111397
111518
|
`);
|
|
111398
111519
|
}
|
|
111399
|
-
const symbolPath =
|
|
111520
|
+
const symbolPath = join110(projectRoot, ".tmp/context-runtime/extract/source-symbols.json");
|
|
111400
111521
|
if (existsSync31(symbolPath)) {
|
|
111401
111522
|
const parsed = JSON.parse(await readFile88(symbolPath, "utf8"));
|
|
111402
111523
|
const symbols = Array.isArray(parsed.symbols) ? parsed.symbols.filter((entry) => entry === null || typeof entry !== "object" || Array.isArray(entry) || entry.source !== source2.name) : [];
|
|
@@ -111404,12 +111525,12 @@ async function pruneExtractRuntime(projectRoot, source2) {
|
|
|
111404
111525
|
await atomicWriteFile(symbolPath, `${JSON.stringify({ ...parsed, phaseFingerprints, symbols }, null, 2)}
|
|
111405
111526
|
`);
|
|
111406
111527
|
}
|
|
111407
|
-
const snapshotRoot =
|
|
111528
|
+
const snapshotRoot = join110(projectRoot, ".tmp/context-runtime/extract/candidates");
|
|
111408
111529
|
const visit4 = async (directory) => {
|
|
111409
111530
|
if (!existsSync31(directory))
|
|
111410
111531
|
return;
|
|
111411
|
-
for (const entry of await
|
|
111412
|
-
const path3 =
|
|
111532
|
+
for (const entry of await readdir28(directory, { withFileTypes: true })) {
|
|
111533
|
+
const path3 = join110(directory, entry.name);
|
|
111413
111534
|
if (entry.isDirectory()) {
|
|
111414
111535
|
await visit4(path3);
|
|
111415
111536
|
continue;
|
|
@@ -111420,7 +111541,7 @@ async function pruneExtractRuntime(projectRoot, source2) {
|
|
|
111420
111541
|
const parsed = JSON.parse(await readFile88(path3, "utf8"));
|
|
111421
111542
|
const refs = Array.isArray(parsed.source_refs) ? parsed.source_refs : [];
|
|
111422
111543
|
if (parsed.source === source2.name || refs.some((ref2) => typeof ref2 === "string" && stringReferencesSource(ref2, source2))) {
|
|
111423
|
-
await
|
|
111544
|
+
await rm24(path3, { force: true });
|
|
111424
111545
|
}
|
|
111425
111546
|
} catch {}
|
|
111426
111547
|
}
|
|
@@ -111459,7 +111580,7 @@ async function removeProjectSource(input) {
|
|
|
111459
111580
|
});
|
|
111460
111581
|
}
|
|
111461
111582
|
await applyAtomicFileBatch({
|
|
111462
|
-
transactionRoot:
|
|
111583
|
+
transactionRoot: join110(input.projectRoot, ".tmp", "context-runtime", "source-remove-transactions"),
|
|
111463
111584
|
writes: [...plan.registryWrite === undefined ? [] : [plan.registryWrite], ...plan.manifestWrite !== undefined ? [plan.manifestWrite] : []],
|
|
111464
111585
|
removals: plan.absoluteRemovals
|
|
111465
111586
|
});
|
|
@@ -112101,8 +112222,8 @@ init_cliFeedback();
|
|
|
112101
112222
|
init_exitCode();
|
|
112102
112223
|
var import_yaml51 = __toESM(require_dist(), 1);
|
|
112103
112224
|
import { constants as constants6, existsSync as existsSync32 } from "node:fs";
|
|
112104
|
-
import { lstat as lstat13, open as open5, readdir as
|
|
112105
|
-
import { dirname as dirname44, join as
|
|
112225
|
+
import { lstat as lstat13, open as open5, readdir as readdir29 } from "node:fs/promises";
|
|
112226
|
+
import { dirname as dirname44, join as join112, resolve as resolve38 } from "node:path";
|
|
112106
112227
|
import { fileURLToPath as fileURLToPath9 } from "node:url";
|
|
112107
112228
|
function bundledSkillRoot() {
|
|
112108
112229
|
const directory = dirname44(fileURLToPath9(import.meta.url));
|
|
@@ -112129,10 +112250,10 @@ async function listProductionSkills(root2) {
|
|
|
112129
112250
|
}
|
|
112130
112251
|
}
|
|
112131
112252
|
async function readProductionSkills(root2) {
|
|
112132
|
-
const entries2 = (await
|
|
112253
|
+
const entries2 = (await readdir29(root2, { withFileTypes: true })).filter((entry) => entry.isDirectory()).sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0);
|
|
112133
112254
|
const skills = [];
|
|
112134
112255
|
for (const directory of entries2) {
|
|
112135
|
-
const entry =
|
|
112256
|
+
const entry = join112(root2, directory.name, "SKILL.md");
|
|
112136
112257
|
if (!(await lstat13(entry)).isFile())
|
|
112137
112258
|
throw new TypeError(`Skill entry must be a regular file: ${entry}`);
|
|
112138
112259
|
const handle2 = await open5(entry, constants6.O_RDONLY | constants6.O_NOFOLLOW | constants6.O_NONBLOCK);
|
|
@@ -112540,8 +112661,8 @@ init_cliFeedback();
|
|
|
112540
112661
|
init_errors3();
|
|
112541
112662
|
init_exitCode();
|
|
112542
112663
|
import { createHash as createHash34 } from "node:crypto";
|
|
112543
|
-
import { cp as cp2, lstat as lstat14, mkdir as mkdir36, mkdtemp as mkdtemp5, readFile as readFile94, readdir as
|
|
112544
|
-
import { dirname as dirname46, join as
|
|
112664
|
+
import { cp as cp2, lstat as lstat14, mkdir as mkdir36, mkdtemp as mkdtemp5, readFile as readFile94, readdir as readdir30, rename as rename9, rm as rm25, writeFile as writeFile28 } from "node:fs/promises";
|
|
112665
|
+
import { dirname as dirname46, join as join113, resolve as resolve40 } from "node:path";
|
|
112545
112666
|
var MARKER = ".context-skill-install.json";
|
|
112546
112667
|
function conflict(path3) {
|
|
112547
112668
|
throw new ContextError(ExitCode.UserError, `Local skill install conflict: ${path3}`, {
|
|
@@ -112569,10 +112690,10 @@ async function checkParents(path3) {
|
|
|
112569
112690
|
async function digest7(root2) {
|
|
112570
112691
|
const hash4 = createHash34("sha256");
|
|
112571
112692
|
async function visit4(dir, prefix) {
|
|
112572
|
-
for (const name3 of (await
|
|
112693
|
+
for (const name3 of (await readdir30(dir)).sort()) {
|
|
112573
112694
|
if (!prefix && name3 === MARKER)
|
|
112574
112695
|
continue;
|
|
112575
|
-
const path3 =
|
|
112696
|
+
const path3 = join113(dir, name3);
|
|
112576
112697
|
const entry = await lstat14(path3);
|
|
112577
112698
|
if (entry.isSymbolicLink())
|
|
112578
112699
|
conflict(path3);
|
|
@@ -112592,31 +112713,31 @@ async function installLocalSkills(root2, path3, dryRun, agent) {
|
|
|
112592
112713
|
if (!path3.trim())
|
|
112593
112714
|
conflict("--local requires a non-empty path");
|
|
112594
112715
|
const targetRoot = resolve40(path3);
|
|
112595
|
-
const skillsRoot =
|
|
112716
|
+
const skillsRoot = join113(targetRoot, "skills");
|
|
112596
112717
|
await checkParents(skillsRoot);
|
|
112597
|
-
const sourceRoot2 =
|
|
112718
|
+
const sourceRoot2 = join113(root2, "skills");
|
|
112598
112719
|
const commandPlans = [];
|
|
112599
112720
|
const commandEntries = new Set;
|
|
112600
112721
|
if (agent === "claude" || agent === "cursor") {
|
|
112601
|
-
for (const name3 of await
|
|
112722
|
+
for (const name3 of await readdir30(join113(root2, "claude", "commands"))) {
|
|
112602
112723
|
if (name3.endsWith(".md"))
|
|
112603
112724
|
commandEntries.add(name3.slice(0, -3));
|
|
112604
112725
|
}
|
|
112605
|
-
const commandsRoot =
|
|
112726
|
+
const commandsRoot = join113(targetRoot, "commands");
|
|
112606
112727
|
await checkParents(commandsRoot);
|
|
112607
|
-
for (const entry of await
|
|
112728
|
+
for (const entry of await readdir30(join113(root2, agent, "commands"), { withFileTypes: true })) {
|
|
112608
112729
|
if (!entry.isFile() || !entry.name.endsWith(".md"))
|
|
112609
112730
|
continue;
|
|
112610
|
-
let content3 = await readFile94(
|
|
112731
|
+
let content3 = await readFile94(join113(root2, agent, "commands", entry.name), "utf8");
|
|
112611
112732
|
if (agent === "claude") {
|
|
112612
112733
|
const frontmatter2 = /^(---\r?\n)([\s\S]*?)(\r?\n---(?:\r?\n|$))/.exec(content3);
|
|
112613
112734
|
if (!frontmatter2)
|
|
112614
|
-
conflict(
|
|
112735
|
+
conflict(join113(root2, agent, "commands", entry.name));
|
|
112615
112736
|
content3 = `${frontmatter2[1]}disable-model-invocation: true
|
|
112616
112737
|
${frontmatter2[2].replace(/^disable-model-invocation:.*\r?\n?/mu, "")}${frontmatter2[3]}${content3.slice(frontmatter2[0].length)}`;
|
|
112617
112738
|
}
|
|
112618
|
-
const target =
|
|
112619
|
-
const marker =
|
|
112739
|
+
const target = join113(commandsRoot, entry.name);
|
|
112740
|
+
const marker = join113(commandsRoot, `.context-${entry.name}.json`);
|
|
112620
112741
|
for (const file of [target, marker]) {
|
|
112621
112742
|
const existing = await stat11(file);
|
|
112622
112743
|
if (existing && (!existing.isFile() || existing.isSymbolicLink()))
|
|
@@ -112637,14 +112758,14 @@ ${frontmatter2[2].replace(/^disable-model-invocation:.*\r?\n?/mu, "")}${frontmat
|
|
|
112637
112758
|
commandPlans.push({ name: entry.name, target, marker, content: content3, hash: createHash34("sha256").update(content3).digest("hex") });
|
|
112638
112759
|
}
|
|
112639
112760
|
if (!commandPlans.length)
|
|
112640
|
-
conflict(
|
|
112761
|
+
conflict(join113(root2, agent, "commands"));
|
|
112641
112762
|
}
|
|
112642
112763
|
const plans = [];
|
|
112643
|
-
for (const entry of (await
|
|
112644
|
-
if (!entry.isDirectory() || !await stat11(
|
|
112764
|
+
for (const entry of (await readdir30(sourceRoot2, { withFileTypes: true })).sort((a, b) => a.name.localeCompare(b.name))) {
|
|
112765
|
+
if (!entry.isDirectory() || !await stat11(join113(sourceRoot2, entry.name, "SKILL.md")))
|
|
112645
112766
|
continue;
|
|
112646
|
-
const source2 =
|
|
112647
|
-
const target =
|
|
112767
|
+
const source2 = join113(sourceRoot2, entry.name);
|
|
112768
|
+
const target = join113(skillsRoot, entry.name);
|
|
112648
112769
|
if (commandEntries.has(entry.name)) {
|
|
112649
112770
|
if (await stat11(target))
|
|
112650
112771
|
conflict(`${target} (use a fresh host directory to avoid duplicate command/skill entries)`);
|
|
@@ -112654,7 +112775,7 @@ ${frontmatter2[2].replace(/^disable-model-invocation:.*\r?\n?/mu, "")}${frontmat
|
|
|
112654
112775
|
if (existing) {
|
|
112655
112776
|
if (!existing.isDirectory() || existing.isSymbolicLink())
|
|
112656
112777
|
conflict(target);
|
|
112657
|
-
const markerPath =
|
|
112778
|
+
const markerPath = join113(target, MARKER);
|
|
112658
112779
|
if (!(await stat11(markerPath))?.isFile())
|
|
112659
112780
|
conflict(target);
|
|
112660
112781
|
let marker;
|
|
@@ -112673,14 +112794,14 @@ ${frontmatter2[2].replace(/^disable-model-invocation:.*\r?\n?/mu, "")}${frontmat
|
|
|
112673
112794
|
if (!dryRun) {
|
|
112674
112795
|
await mkdir36(skillsRoot, { recursive: true });
|
|
112675
112796
|
for (const plan of plans) {
|
|
112676
|
-
const staging = await mkdtemp5(
|
|
112677
|
-
const candidate =
|
|
112678
|
-
const previous3 =
|
|
112797
|
+
const staging = await mkdtemp5(join113(skillsRoot, ".context-install-"));
|
|
112798
|
+
const candidate = join113(staging, "candidate");
|
|
112799
|
+
const previous3 = join113(staging, "previous");
|
|
112679
112800
|
let moved = false;
|
|
112680
112801
|
try {
|
|
112681
112802
|
await cp2(plan.source, candidate, { recursive: true });
|
|
112682
112803
|
if (agent === "claude") {
|
|
112683
|
-
const skillFile =
|
|
112804
|
+
const skillFile = join113(candidate, "SKILL.md");
|
|
112684
112805
|
const content3 = await readFile94(skillFile, "utf8");
|
|
112685
112806
|
const parts = /^(---\r?\n)([\s\S]*?)(\r?\n---(?:\r?\n|$))/.exec(content3);
|
|
112686
112807
|
if (parts && /^\s*context-public-entry:\s*["']?false["']?\s*$/mu.test(parts[2])) {
|
|
@@ -112689,7 +112810,7 @@ ${frontmatter2[2].replace(/^disable-model-invocation:.*\r?\n?/mu, "")}${frontmat
|
|
|
112689
112810
|
${frontmatter2}${parts[3]}${content3.slice(parts[0].length)}`);
|
|
112690
112811
|
}
|
|
112691
112812
|
}
|
|
112692
|
-
await writeFile28(
|
|
112813
|
+
await writeFile28(join113(candidate, MARKER), JSON.stringify({ owner: "context-plugin-local", digest: await digest7(candidate) }) + `
|
|
112693
112814
|
`);
|
|
112694
112815
|
if (plan.exists) {
|
|
112695
112816
|
await rename9(plan.target, previous3);
|
|
@@ -112702,7 +112823,7 @@ ${frontmatter2}${parts[3]}${content3.slice(parts[0].length)}`);
|
|
|
112702
112823
|
await rename9(previous3, plan.target);
|
|
112703
112824
|
throw error;
|
|
112704
112825
|
}
|
|
112705
|
-
await
|
|
112826
|
+
await rm25(staging, { recursive: true, force: true });
|
|
112706
112827
|
} catch (error) {
|
|
112707
112828
|
throw new ContextError(ExitCode.WorkspaceStateError, `Local skill installation failed: ${plan.target}`, {
|
|
112708
112829
|
category: ErrorCategory.WorkspaceStateInvalid,
|
|
@@ -112713,13 +112834,13 @@ ${frontmatter2}${parts[3]}${content3.slice(parts[0].length)}`);
|
|
|
112713
112834
|
}
|
|
112714
112835
|
for (const command3 of commandPlans) {
|
|
112715
112836
|
await mkdir36(dirname46(command3.target), { recursive: true });
|
|
112716
|
-
const staging = await mkdtemp5(
|
|
112717
|
-
await writeFile28(
|
|
112718
|
-
await writeFile28(
|
|
112837
|
+
const staging = await mkdtemp5(join113(dirname46(command3.target), ".context-install-"));
|
|
112838
|
+
await writeFile28(join113(staging, "command"), command3.content);
|
|
112839
|
+
await writeFile28(join113(staging, "marker"), JSON.stringify({ owner: "context-plugin-local", digest: command3.hash }) + `
|
|
112719
112840
|
`);
|
|
112720
|
-
await rename9(
|
|
112721
|
-
await rename9(
|
|
112722
|
-
await
|
|
112841
|
+
await rename9(join113(staging, "command"), command3.target);
|
|
112842
|
+
await rename9(join113(staging, "marker"), command3.marker);
|
|
112843
|
+
await rm25(staging, { recursive: true, force: true });
|
|
112723
112844
|
}
|
|
112724
112845
|
}
|
|
112725
112846
|
return formatFeedback({
|
|
@@ -112742,10 +112863,10 @@ init_cliFeedback();
|
|
|
112742
112863
|
init_errors3();
|
|
112743
112864
|
init_exitCode();
|
|
112744
112865
|
import { lstat as lstat15 } from "node:fs/promises";
|
|
112745
|
-
import { join as
|
|
112866
|
+
import { join as join114, resolve as resolve41 } from "node:path";
|
|
112746
112867
|
var HOST_DIRS = { claude: ".claude", cursor: ".cursor", codex: ".agents" };
|
|
112747
112868
|
async function detectLocalAgent(agent, repo) {
|
|
112748
|
-
const path3 =
|
|
112869
|
+
const path3 = join114(repo, HOST_DIRS[agent]);
|
|
112749
112870
|
try {
|
|
112750
112871
|
const entry = await lstat15(path3);
|
|
112751
112872
|
if (!entry.isDirectory() || entry.isSymbolicLink()) {
|
|
@@ -112770,7 +112891,7 @@ async function installAutoLocalSkills(root2, path3, dryRun, detect = detectLocal
|
|
|
112770
112891
|
if (selectedAgent ? selectedAgent === "all" || agent === selectedAgent : await detect(agent, repo))
|
|
112771
112892
|
agents.push(agent);
|
|
112772
112893
|
}
|
|
112773
|
-
const targets = agents.length ? agents.map((agent) => ({ agent, path:
|
|
112894
|
+
const targets = agents.length ? agents.map((agent) => ({ agent, path: join114(repo, HOST_DIRS[agent]) })) : [{ path: join114(repo, ".agents") }];
|
|
112774
112895
|
const previews = [];
|
|
112775
112896
|
for (const target of targets)
|
|
112776
112897
|
previews.push(await installLocalSkills(root2, target.path, true, target.agent));
|
|
@@ -112803,7 +112924,7 @@ init_cliFeedback();
|
|
|
112803
112924
|
init_errors3();
|
|
112804
112925
|
init_exitCode();
|
|
112805
112926
|
import { existsSync as existsSync35 } from "node:fs";
|
|
112806
|
-
import { dirname as dirname48, join as
|
|
112927
|
+
import { dirname as dirname48, join as join116, resolve as resolve42 } from "node:path";
|
|
112807
112928
|
import { fileURLToPath as fileURLToPath10 } from "node:url";
|
|
112808
112929
|
|
|
112809
112930
|
// src/project/pluginInstallTargets.ts
|
|
@@ -112812,9 +112933,9 @@ init_errors3();
|
|
|
112812
112933
|
init_exitCode();
|
|
112813
112934
|
import { execFile as execFile13 } from "node:child_process";
|
|
112814
112935
|
import { existsSync as existsSync34 } from "node:fs";
|
|
112815
|
-
import { cp as cp3, mkdir as mkdir37, readdir as
|
|
112936
|
+
import { cp as cp3, mkdir as mkdir37, readdir as readdir31, readFile as readFile95, rename as rename10, rm as rm26, writeFile as writeFile29 } from "node:fs/promises";
|
|
112816
112937
|
import { homedir as homedir2 } from "node:os";
|
|
112817
|
-
import { dirname as dirname47, join as
|
|
112938
|
+
import { dirname as dirname47, join as join115 } from "node:path";
|
|
112818
112939
|
import { promisify as promisify13 } from "node:util";
|
|
112819
112940
|
var execFileAsync7 = promisify13(execFile13);
|
|
112820
112941
|
var MARKETPLACE_NAME = "c4a";
|
|
@@ -112868,23 +112989,23 @@ async function claudePluginInstalled(pluginId) {
|
|
|
112868
112989
|
}
|
|
112869
112990
|
}
|
|
112870
112991
|
function codexHome() {
|
|
112871
|
-
return process.env.CODEX_HOME?.trim() ||
|
|
112992
|
+
return process.env.CODEX_HOME?.trim() || join115(homedir2(), ".codex");
|
|
112872
112993
|
}
|
|
112873
112994
|
function claudePluginCacheRoot() {
|
|
112874
112995
|
const explicitRoot = process.env[CLAUDE_PLUGIN_CACHE_ROOT_ENV2]?.trim();
|
|
112875
112996
|
if (explicitRoot)
|
|
112876
112997
|
return explicitRoot;
|
|
112877
112998
|
const home = process.env[CLAUDE_PLUGIN_CACHE_HOME_ENV2]?.trim() || homedir2();
|
|
112878
|
-
return
|
|
112999
|
+
return join115(home, ".claude", "plugins", "cache");
|
|
112879
113000
|
}
|
|
112880
113001
|
function sharedSkillsRoot() {
|
|
112881
|
-
return process.env[SHARED_SKILLS_ROOT_ENV]?.trim() ||
|
|
113002
|
+
return process.env[SHARED_SKILLS_ROOT_ENV]?.trim() || join115(homedir2(), ".agents", "skills");
|
|
112882
113003
|
}
|
|
112883
113004
|
function claudeSkillsRoot() {
|
|
112884
|
-
return process.env[CLAUDE_SKILLS_ROOT_ENV]?.trim() ||
|
|
113005
|
+
return process.env[CLAUDE_SKILLS_ROOT_ENV]?.trim() || join115(homedir2(), ".claude", "skills");
|
|
112885
113006
|
}
|
|
112886
113007
|
function cursorPluginRoot() {
|
|
112887
|
-
return process.env[CURSOR_PLUGIN_ROOT_ENV]?.trim() ||
|
|
113008
|
+
return process.env[CURSOR_PLUGIN_ROOT_ENV]?.trim() || join115(homedir2(), ".cursor", "plugins", "local", PLUGIN_NAME);
|
|
112888
113009
|
}
|
|
112889
113010
|
function blockHeader(line) {
|
|
112890
113011
|
const match = line.match(/^\s*\[([^\]]+)\]\s*$/u);
|
|
@@ -112935,7 +113056,7 @@ function pruneLegacyCodexConfigContent(content3) {
|
|
|
112935
113056
|
`), removed };
|
|
112936
113057
|
}
|
|
112937
113058
|
async function pruneLegacyCodexConfig(dryRun, steps) {
|
|
112938
|
-
const configPath =
|
|
113059
|
+
const configPath = join115(codexHome(), "config.toml");
|
|
112939
113060
|
const current2 = await readFile95(configPath, "utf8").catch(() => "");
|
|
112940
113061
|
if (!current2)
|
|
112941
113062
|
return;
|
|
@@ -112952,10 +113073,10 @@ async function pruneLegacyCodexConfig(dryRun, steps) {
|
|
|
112952
113073
|
}
|
|
112953
113074
|
}
|
|
112954
113075
|
async function pruneCodexPluginCacheForName(pluginName, keepVersion, dryRun, steps) {
|
|
112955
|
-
const cacheRoot =
|
|
113076
|
+
const cacheRoot = join115(codexHome(), "plugins", "cache", MARKETPLACE_NAME, pluginName);
|
|
112956
113077
|
if (!existsSync34(cacheRoot))
|
|
112957
113078
|
return;
|
|
112958
|
-
const versions = (await
|
|
113079
|
+
const versions = (await readdir31(cacheRoot, { withFileTypes: true }).catch(() => [])).filter((entry) => entry.isDirectory() && entry.name !== keepVersion).map((entry) => entry.name).sort();
|
|
112959
113080
|
if (versions.length === 0)
|
|
112960
113081
|
return;
|
|
112961
113082
|
steps.push({
|
|
@@ -112964,7 +113085,7 @@ async function pruneCodexPluginCacheForName(pluginName, keepVersion, dryRun, ste
|
|
|
112964
113085
|
status: dryRun ? "planned" : "ran"
|
|
112965
113086
|
});
|
|
112966
113087
|
if (!dryRun)
|
|
112967
|
-
await Promise.all(versions.map((version3) =>
|
|
113088
|
+
await Promise.all(versions.map((version3) => rm26(join115(cacheRoot, version3), { recursive: true, force: true })));
|
|
112968
113089
|
}
|
|
112969
113090
|
async function pruneCodexPluginCache(currentVersion, dryRun, steps) {
|
|
112970
113091
|
await pruneCodexPluginCacheForName(PLUGIN_NAME, currentVersion, dryRun, steps);
|
|
@@ -112974,7 +113095,7 @@ async function pruneCodexPluginCache(currentVersion, dryRun, steps) {
|
|
|
112974
113095
|
}
|
|
112975
113096
|
async function isEmptyDir2(dir) {
|
|
112976
113097
|
try {
|
|
112977
|
-
return (await
|
|
113098
|
+
return (await readdir31(dir)).length === 0;
|
|
112978
113099
|
} catch {
|
|
112979
113100
|
return false;
|
|
112980
113101
|
}
|
|
@@ -112984,31 +113105,31 @@ async function pruneClaudeOrphanContextCache(dryRun, steps) {
|
|
|
112984
113105
|
if (!existsSync34(cacheRoot))
|
|
112985
113106
|
return;
|
|
112986
113107
|
const removed = [];
|
|
112987
|
-
const marketplaces = await
|
|
113108
|
+
const marketplaces = await readdir31(cacheRoot, { withFileTypes: true }).catch(() => []);
|
|
112988
113109
|
for (const marketplace of marketplaces) {
|
|
112989
113110
|
if (!marketplace.isDirectory())
|
|
112990
113111
|
continue;
|
|
112991
|
-
const pluginDir =
|
|
113112
|
+
const pluginDir = join115(cacheRoot, marketplace.name, PLUGIN_NAME);
|
|
112992
113113
|
if (!existsSync34(pluginDir))
|
|
112993
113114
|
continue;
|
|
112994
|
-
const versions = await
|
|
113115
|
+
const versions = await readdir31(pluginDir, { withFileTypes: true }).catch(() => []);
|
|
112995
113116
|
for (const version3 of versions) {
|
|
112996
113117
|
if (!version3.isDirectory())
|
|
112997
113118
|
continue;
|
|
112998
|
-
const versionDir =
|
|
112999
|
-
if (!existsSync34(
|
|
113119
|
+
const versionDir = join115(pluginDir, version3.name);
|
|
113120
|
+
if (!existsSync34(join115(versionDir, ORPHAN_MARKER2)))
|
|
113000
113121
|
continue;
|
|
113001
113122
|
removed.push(`${marketplace.name}/${PLUGIN_NAME}/${version3.name}`);
|
|
113002
113123
|
if (!dryRun) {
|
|
113003
|
-
await
|
|
113124
|
+
await rm26(versionDir, { recursive: true, force: true });
|
|
113004
113125
|
}
|
|
113005
113126
|
}
|
|
113006
113127
|
if (!dryRun && await isEmptyDir2(pluginDir)) {
|
|
113007
|
-
await
|
|
113128
|
+
await rm26(pluginDir, { recursive: true, force: true });
|
|
113008
113129
|
}
|
|
113009
|
-
const marketplaceDir =
|
|
113130
|
+
const marketplaceDir = join115(cacheRoot, marketplace.name);
|
|
113010
113131
|
if (!dryRun && await isEmptyDir2(marketplaceDir)) {
|
|
113011
|
-
await
|
|
113132
|
+
await rm26(marketplaceDir, { recursive: true, force: true });
|
|
113012
113133
|
}
|
|
113013
113134
|
}
|
|
113014
113135
|
if (removed.length > 0) {
|
|
@@ -113027,12 +113148,12 @@ async function pruneClaudeLegacyPluginCache(dryRun, steps) {
|
|
|
113027
113148
|
return;
|
|
113028
113149
|
const removed = [];
|
|
113029
113150
|
for (const pluginName of LEGACY_PLUGIN_NAMES) {
|
|
113030
|
-
const pluginDir =
|
|
113151
|
+
const pluginDir = join115(cacheRoot, MARKETPLACE_NAME, pluginName);
|
|
113031
113152
|
if (!existsSync34(pluginDir))
|
|
113032
113153
|
continue;
|
|
113033
113154
|
removed.push(`${MARKETPLACE_NAME}/${pluginName}`);
|
|
113034
113155
|
if (!dryRun) {
|
|
113035
|
-
await
|
|
113156
|
+
await rm26(pluginDir, { recursive: true, force: true });
|
|
113036
113157
|
}
|
|
113037
113158
|
}
|
|
113038
113159
|
if (removed.length > 0) {
|
|
@@ -113044,12 +113165,12 @@ async function pruneClaudeLegacyPluginCache(dryRun, steps) {
|
|
|
113044
113165
|
}
|
|
113045
113166
|
}
|
|
113046
113167
|
async function pruneClaudeSupersededContextCache(root2, dryRun, steps) {
|
|
113047
|
-
const manifest = await readFile95(
|
|
113168
|
+
const manifest = await readFile95(join115(root2, "claude", ".claude-plugin", "plugin.json"), "utf8").then((content3) => JSON.parse(content3)).catch(() => null);
|
|
113048
113169
|
const currentVersion = typeof manifest?.version === "string" ? manifest.version : null;
|
|
113049
113170
|
if (!currentVersion)
|
|
113050
113171
|
return;
|
|
113051
|
-
const pluginDir =
|
|
113052
|
-
const staleVersions = (await
|
|
113172
|
+
const pluginDir = join115(claudePluginCacheRoot(), MARKETPLACE_NAME, PLUGIN_NAME);
|
|
113173
|
+
const staleVersions = (await readdir31(pluginDir, { withFileTypes: true }).catch(() => [])).filter((entry) => entry.isDirectory() && entry.name !== currentVersion).map((entry) => entry.name);
|
|
113053
113174
|
if (staleVersions.length === 0)
|
|
113054
113175
|
return;
|
|
113055
113176
|
steps.push({
|
|
@@ -113058,7 +113179,7 @@ async function pruneClaudeSupersededContextCache(root2, dryRun, steps) {
|
|
|
113058
113179
|
status: dryRun ? "planned" : "ran"
|
|
113059
113180
|
});
|
|
113060
113181
|
if (!dryRun) {
|
|
113061
|
-
await Promise.all(staleVersions.map((version3) =>
|
|
113182
|
+
await Promise.all(staleVersions.map((version3) => rm26(join115(pluginDir, version3), { recursive: true, force: true })));
|
|
113062
113183
|
}
|
|
113063
113184
|
}
|
|
113064
113185
|
function enableCodexPluginConfig(content3) {
|
|
@@ -113122,7 +113243,7 @@ source = ${JSON.stringify(root2)}
|
|
|
113122
113243
|
`;
|
|
113123
113244
|
}
|
|
113124
113245
|
async function ensureCodexPluginEnabled() {
|
|
113125
|
-
const configPath =
|
|
113246
|
+
const configPath = join115(codexHome(), "config.toml");
|
|
113126
113247
|
await mkdir37(dirname47(configPath), { recursive: true });
|
|
113127
113248
|
const current2 = await readFile95(configPath, "utf8").catch(() => "");
|
|
113128
113249
|
const next2 = enableCodexPluginConfig(current2);
|
|
@@ -113131,7 +113252,7 @@ async function ensureCodexPluginEnabled() {
|
|
|
113131
113252
|
}
|
|
113132
113253
|
}
|
|
113133
113254
|
async function ensureCodexLocalMarketplace(root2) {
|
|
113134
|
-
const configPath =
|
|
113255
|
+
const configPath = join115(codexHome(), "config.toml");
|
|
113135
113256
|
await mkdir37(dirname47(configPath), { recursive: true });
|
|
113136
113257
|
const current2 = await readFile95(configPath, "utf8").catch(() => "");
|
|
113137
113258
|
const next2 = upsertCodexLocalMarketplaceConfig(current2, root2);
|
|
@@ -113140,7 +113261,7 @@ async function ensureCodexLocalMarketplace(root2) {
|
|
|
113140
113261
|
}
|
|
113141
113262
|
}
|
|
113142
113263
|
async function codexPluginVersion(root2) {
|
|
113143
|
-
const manifestPath =
|
|
113264
|
+
const manifestPath = join115(root2, "codex", ".codex-plugin", "plugin.json");
|
|
113144
113265
|
const manifest = JSON.parse(await readFile95(manifestPath, "utf8"));
|
|
113145
113266
|
if (typeof manifest.version !== "string" || !/^[A-Za-z0-9][A-Za-z0-9._-]*$/u.test(manifest.version)) {
|
|
113146
113267
|
throw new Error(`Codex plugin manifest has an invalid version: ${manifestPath}`);
|
|
@@ -113148,13 +113269,13 @@ async function codexPluginVersion(root2) {
|
|
|
113148
113269
|
return manifest.version;
|
|
113149
113270
|
}
|
|
113150
113271
|
function codexPluginCacheDir(version3) {
|
|
113151
|
-
return
|
|
113272
|
+
return join115(codexHome(), "plugins", "cache", MARKETPLACE_NAME, PLUGIN_NAME, version3);
|
|
113152
113273
|
}
|
|
113153
113274
|
async function replaceDirectoryFromSource(source2, target) {
|
|
113154
113275
|
await mkdir37(dirname47(target), { recursive: true });
|
|
113155
113276
|
const temporary = `${target}.tmp-${process.pid}-${Date.now()}`;
|
|
113156
113277
|
const previous3 = `${target}.previous-${process.pid}-${Date.now()}`;
|
|
113157
|
-
await
|
|
113278
|
+
await rm26(temporary, { recursive: true, force: true });
|
|
113158
113279
|
await cp3(source2, temporary, { recursive: true, force: true });
|
|
113159
113280
|
const hadPrevious = existsSync34(target);
|
|
113160
113281
|
try {
|
|
@@ -113162,16 +113283,16 @@ async function replaceDirectoryFromSource(source2, target) {
|
|
|
113162
113283
|
await rename10(target, previous3);
|
|
113163
113284
|
await rename10(temporary, target);
|
|
113164
113285
|
if (hadPrevious)
|
|
113165
|
-
await
|
|
113286
|
+
await rm26(previous3, { recursive: true, force: true });
|
|
113166
113287
|
} catch (error) {
|
|
113167
|
-
await
|
|
113288
|
+
await rm26(temporary, { recursive: true, force: true });
|
|
113168
113289
|
if (hadPrevious && !existsSync34(target) && existsSync34(previous3))
|
|
113169
113290
|
await rename10(previous3, target);
|
|
113170
113291
|
throw error;
|
|
113171
113292
|
}
|
|
113172
113293
|
}
|
|
113173
113294
|
async function materializeCodexPluginCache(root2, version3, dryRun, steps) {
|
|
113174
|
-
const source2 =
|
|
113295
|
+
const source2 = join115(root2, "codex");
|
|
113175
113296
|
const target = codexPluginCacheDir(version3);
|
|
113176
113297
|
steps.push({
|
|
113177
113298
|
agent: "codex",
|
|
@@ -113183,13 +113304,13 @@ async function materializeCodexPluginCache(root2, version3, dryRun, steps) {
|
|
|
113183
113304
|
await replaceDirectoryFromSource(source2, target);
|
|
113184
113305
|
}
|
|
113185
113306
|
async function bundledProviderSkillNames(root2) {
|
|
113186
|
-
const skillsRoot =
|
|
113187
|
-
const entries2 = await
|
|
113307
|
+
const skillsRoot = join115(root2, "skills");
|
|
113308
|
+
const entries2 = await readdir31(skillsRoot, { withFileTypes: true });
|
|
113188
113309
|
const names = [];
|
|
113189
113310
|
for (const entry of entries2) {
|
|
113190
113311
|
if (!entry.isDirectory() || entry.name === "context")
|
|
113191
113312
|
continue;
|
|
113192
|
-
const skillPath =
|
|
113313
|
+
const skillPath = join115(skillsRoot, entry.name, "SKILL.md");
|
|
113193
113314
|
if (!existsSync34(skillPath))
|
|
113194
113315
|
continue;
|
|
113195
113316
|
const skill = await readFile95(skillPath, "utf8");
|
|
@@ -113204,10 +113325,10 @@ async function bundledProviderSkillNames(root2) {
|
|
|
113204
113325
|
return names;
|
|
113205
113326
|
}
|
|
113206
113327
|
async function materializeProviderSkills(root2, targetRoot, agent, dryRun, steps) {
|
|
113207
|
-
const sourceRoot2 =
|
|
113328
|
+
const sourceRoot2 = join115(root2, "skills");
|
|
113208
113329
|
for (const name3 of await bundledProviderSkillNames(root2)) {
|
|
113209
|
-
const source2 =
|
|
113210
|
-
const target =
|
|
113330
|
+
const source2 = join115(sourceRoot2, name3);
|
|
113331
|
+
const target = join115(targetRoot, name3);
|
|
113211
113332
|
steps.push({
|
|
113212
113333
|
agent,
|
|
113213
113334
|
command: `materialize lifecycle Provider skill: ${shellQuote8(source2)} -> ${shellQuote8(target)}`,
|
|
@@ -113218,7 +113339,7 @@ async function materializeProviderSkills(root2, targetRoot, agent, dryRun, steps
|
|
|
113218
113339
|
}
|
|
113219
113340
|
}
|
|
113220
113341
|
async function installCursor(root2, dryRun, steps) {
|
|
113221
|
-
const source2 =
|
|
113342
|
+
const source2 = join115(root2, "cursor");
|
|
113222
113343
|
const target = cursorPluginRoot();
|
|
113223
113344
|
steps.push({
|
|
113224
113345
|
agent: "cursor",
|
|
@@ -113273,12 +113394,12 @@ async function installCodex(root2, dryRun, steps) {
|
|
|
113273
113394
|
steps.push({ agent: "codex", command: commandLine("codex", addArgs), status: dryRun ? "planned" : "ran" });
|
|
113274
113395
|
steps.push({
|
|
113275
113396
|
agent: "codex",
|
|
113276
|
-
command: `ensure ${shellQuote8(
|
|
113397
|
+
command: `ensure ${shellQuote8(join115(codexHome(), "config.toml"))} registers local marketplace ${shellQuote8(MARKETPLACE_NAME)}`,
|
|
113277
113398
|
status: dryRun ? "planned" : "ran"
|
|
113278
113399
|
});
|
|
113279
113400
|
steps.push({
|
|
113280
113401
|
agent: "codex",
|
|
113281
|
-
command: `ensure ${shellQuote8(
|
|
113402
|
+
command: `ensure ${shellQuote8(join115(codexHome(), "config.toml"))} enables ${shellQuote8(PLUGIN_ID)}`,
|
|
113282
113403
|
status: dryRun ? "planned" : "ran"
|
|
113283
113404
|
});
|
|
113284
113405
|
if (dryRun) {
|
|
@@ -113333,13 +113454,13 @@ function pluginRootCandidates() {
|
|
|
113333
113454
|
return [resolve42(envRoot)];
|
|
113334
113455
|
const candidates = [];
|
|
113335
113456
|
for (const dir of packageCandidateDirs()) {
|
|
113336
|
-
candidates.push(
|
|
113337
|
-
candidates.push(
|
|
113457
|
+
candidates.push(join116(dir, "plugins"));
|
|
113458
|
+
candidates.push(join116(dir, "dist", "plugins"));
|
|
113338
113459
|
}
|
|
113339
113460
|
return [...new Set(candidates)];
|
|
113340
113461
|
}
|
|
113341
113462
|
function isInstallablePluginRoot(root2) {
|
|
113342
|
-
return existsSync35(
|
|
113463
|
+
return existsSync35(join116(root2, ".claude-plugin", "marketplace.json")) && existsSync35(join116(root2, ".agents", "plugins", "marketplace.json")) && existsSync35(join116(root2, "claude", ".claude-plugin", "plugin.json")) && existsSync35(join116(root2, "codex", ".codex-plugin", "plugin.json")) && existsSync35(join116(root2, "cursor", ".cursor-plugin", "plugin.json")) && existsSync35(join116(root2, "skills"));
|
|
113343
113464
|
}
|
|
113344
113465
|
function resolveBundledPluginsRoot() {
|
|
113345
113466
|
const candidates = pluginRootCandidates();
|
|
@@ -113586,10 +113707,10 @@ function readQuickstartPath() {
|
|
|
113586
113707
|
try {
|
|
113587
113708
|
let dir = dirname49(fileURLToPath11(import.meta.url));
|
|
113588
113709
|
for (let i2 = 0;i2 < 8; i2++) {
|
|
113589
|
-
const candidate =
|
|
113710
|
+
const candidate = join117(dir, "docs", "quickstart.md");
|
|
113590
113711
|
if (existsSync36(candidate))
|
|
113591
113712
|
return candidate;
|
|
113592
|
-
const pkg =
|
|
113713
|
+
const pkg = join117(dir, "package.json");
|
|
113593
113714
|
if (existsSync36(pkg))
|
|
113594
113715
|
return candidate;
|
|
113595
113716
|
const parent = dirname49(dir);
|
|
@@ -113598,7 +113719,7 @@ function readQuickstartPath() {
|
|
|
113598
113719
|
dir = parent;
|
|
113599
113720
|
}
|
|
113600
113721
|
} catch {}
|
|
113601
|
-
return
|
|
113722
|
+
return join117(dirname49(fileURLToPath11(import.meta.url)), "docs", "quickstart.md");
|
|
113602
113723
|
}
|
|
113603
113724
|
var GREEN = "\x1B[32m";
|
|
113604
113725
|
var RESET = "\x1B[0m";
|