@contentful/experience-design-system-cli 2.32.1-dev-build-dc74ac7.0 → 2.32.1-dev-build-e667d41.0
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/dist/package.json +1 -1
- package/dist/src/helpers/build-contentful-management-client.d.ts +7 -0
- package/dist/src/helpers/fetch-existing-contentful-entities.d.ts +11 -0
- package/dist/src/helpers/find-nearly-matching-component.d.ts +7 -0
- package/dist/src/helpers/read-existing-contentful-entities-from-session.d.ts +7 -0
- package/dist/src/helpers/summarize-existing-contentful-entities.d.ts +50 -0
- package/dist/src/import/orchestrator.d.ts +0 -1
- package/dist/src/index.js +341 -137
- package/dist/src/session/cache-keys.d.ts +1 -1
- package/package.json +6 -6
- package/skills/generate-components.md +27 -0
- package/skills/map-tokens.md +12 -0
- package/skills/select-components.md +11 -0
- package/dist/src/helpers/cma-client.d.ts +0 -17
- package/dist/src/helpers/fetch-existing-entities.d.ts +0 -16
package/dist/src/index.js
CHANGED
|
@@ -335,7 +335,7 @@ async function runAgent(options) {
|
|
|
335
335
|
promptLen: prompt2.length,
|
|
336
336
|
promptHead: prompt2.slice(0, 500)
|
|
337
337
|
});
|
|
338
|
-
return new Promise((
|
|
338
|
+
return new Promise((resolve28) => {
|
|
339
339
|
const bedrockEnv = bedrock ? BEDROCK_ENV_BY_AGENT[agent] : void 0;
|
|
340
340
|
const child = spawn(binary, args, {
|
|
341
341
|
stdio: ["pipe", "pipe", "pipe"],
|
|
@@ -384,25 +384,25 @@ async function runAgent(options) {
|
|
|
384
384
|
stderrLen: stderr.length,
|
|
385
385
|
stderrTail: stderr.slice(-1e3)
|
|
386
386
|
});
|
|
387
|
-
|
|
387
|
+
resolve28(result);
|
|
388
388
|
});
|
|
389
389
|
});
|
|
390
390
|
}
|
|
391
391
|
async function checkAgentAuth(agent) {
|
|
392
392
|
const binary = resolveBinary(agent);
|
|
393
|
-
const binaryExists2 = await new Promise((
|
|
393
|
+
const binaryExists2 = await new Promise((resolve28) => {
|
|
394
394
|
if (binary.startsWith("/")) {
|
|
395
|
-
import("node:fs/promises").then((fs2) => fs2.access(binary).then(() =>
|
|
395
|
+
import("node:fs/promises").then((fs2) => fs2.access(binary).then(() => resolve28(true), () => resolve28(false)));
|
|
396
396
|
return;
|
|
397
397
|
}
|
|
398
398
|
const child = spawn("which", [binary], { stdio: "ignore" });
|
|
399
|
-
child.on("close", (code) =>
|
|
399
|
+
child.on("close", (code) => resolve28(code === 0));
|
|
400
400
|
});
|
|
401
401
|
if (!binaryExists2)
|
|
402
402
|
return "not-found";
|
|
403
403
|
if (agent !== "claude")
|
|
404
404
|
return "ok";
|
|
405
|
-
return new Promise((
|
|
405
|
+
return new Promise((resolve28) => {
|
|
406
406
|
const child = spawn(binary, ["auth", "status", "--json"], {
|
|
407
407
|
stdio: ["ignore", "pipe", "pipe"]
|
|
408
408
|
});
|
|
@@ -412,7 +412,7 @@ async function checkAgentAuth(agent) {
|
|
|
412
412
|
if (!done) {
|
|
413
413
|
done = true;
|
|
414
414
|
child.kill("SIGTERM");
|
|
415
|
-
|
|
415
|
+
resolve28("unauthenticated");
|
|
416
416
|
}
|
|
417
417
|
}, 5e3);
|
|
418
418
|
child.stdout?.on("data", (chunk) => {
|
|
@@ -424,14 +424,14 @@ async function checkAgentAuth(agent) {
|
|
|
424
424
|
done = true;
|
|
425
425
|
clearTimeout(timer);
|
|
426
426
|
if (code !== 0) {
|
|
427
|
-
|
|
427
|
+
resolve28("unauthenticated");
|
|
428
428
|
return;
|
|
429
429
|
}
|
|
430
430
|
try {
|
|
431
431
|
const status = JSON.parse(stdout);
|
|
432
|
-
|
|
432
|
+
resolve28(status.loggedIn ? "ok" : "unauthenticated");
|
|
433
433
|
} catch {
|
|
434
|
-
|
|
434
|
+
resolve28("unauthenticated");
|
|
435
435
|
}
|
|
436
436
|
});
|
|
437
437
|
});
|
|
@@ -624,8 +624,20 @@ function renderTokenCandidateSection(kind, entries) {
|
|
|
624
624
|
${formatTokenCandidateLines(entries)}`;
|
|
625
625
|
}
|
|
626
626
|
function buildPreamble(options) {
|
|
627
|
-
const { skill, rawComponentsInline, rawTokensInline, rawTokensFilename, tokensInline, tokenMapInline, generatedCdf, tokenTree, componentSourceRefs } = options;
|
|
627
|
+
const { skill, rawComponentsInline, rawTokensInline, rawTokensFilename, tokensInline, tokenMapInline, generatedCdf, tokenTree, componentSourceRefs, existingComponentsInline, existingTokensInline } = options;
|
|
628
628
|
const sections = [];
|
|
629
|
+
if (existingComponentsInline) {
|
|
630
|
+
sections.push(`Existing components in the target Contentful space (JSON) \u2014 use for alignment, not as a hard filter:
|
|
631
|
+
\`\`\`json
|
|
632
|
+
${existingComponentsInline}
|
|
633
|
+
\`\`\``);
|
|
634
|
+
}
|
|
635
|
+
if (existingTokensInline) {
|
|
636
|
+
sections.push(`Existing design tokens in the target Contentful space (JSON) \u2014 prefer binding to these paths over inventing new ones:
|
|
637
|
+
\`\`\`json
|
|
638
|
+
${existingTokensInline}
|
|
639
|
+
\`\`\``);
|
|
640
|
+
}
|
|
629
641
|
if (rawComponentsInline) {
|
|
630
642
|
sections.push(`Raw component data (JSON):
|
|
631
643
|
\`\`\`json
|
|
@@ -8775,9 +8787,10 @@ async function hashFile(filePath) {
|
|
|
8775
8787
|
const content = await readFile6(filePath, "utf8");
|
|
8776
8788
|
return hashContent(content);
|
|
8777
8789
|
}
|
|
8778
|
-
async function hashPromptForSkill(skill, agent, model, skillPathOverride) {
|
|
8790
|
+
async function hashPromptForSkill(skill, agent, model, skillPathOverride, extraInputs = []) {
|
|
8779
8791
|
const promptHash = skillPathOverride ? await hashFile(resolve6(skillPathOverride)) : await hashFile(resolveSkillPath(skill));
|
|
8780
|
-
|
|
8792
|
+
const extraSegment = extraInputs.length > 0 ? `|${extraInputs.join("|")}` : "";
|
|
8793
|
+
return hashContent(`${promptHash}|${agent}|${model ?? ""}${extraSegment}`);
|
|
8781
8794
|
}
|
|
8782
8795
|
var init_cache_keys = __esm({
|
|
8783
8796
|
"packages/experience-design-system-cli/src/session/cache-keys.ts"() {
|
|
@@ -12885,7 +12898,7 @@ var init_user_agent = __esm({
|
|
|
12885
12898
|
|
|
12886
12899
|
// packages/experience-design-system-cli/src/apply/api-client.ts
|
|
12887
12900
|
function defaultSleep(delayMs) {
|
|
12888
|
-
return new Promise((
|
|
12901
|
+
return new Promise((resolve28) => setTimeout(resolve28, delayMs));
|
|
12889
12902
|
}
|
|
12890
12903
|
function isTransientStatus(status) {
|
|
12891
12904
|
return status >= 500 && status <= 599;
|
|
@@ -13273,7 +13286,7 @@ ${trimmed}`;
|
|
|
13273
13286
|
const progress = maxAttempts > 1 ? attempt / (maxAttempts - 1) : 0;
|
|
13274
13287
|
const baseDelay = intervalMs + (maxIntervalMs - intervalMs) * progress;
|
|
13275
13288
|
const jitter = Math.random() * baseDelay * 0.15;
|
|
13276
|
-
await new Promise((
|
|
13289
|
+
await new Promise((resolve28) => setTimeout(resolve28, baseDelay + jitter));
|
|
13277
13290
|
}
|
|
13278
13291
|
}
|
|
13279
13292
|
throw new Error(`Operation ${operationId} timed out after ${maxAttempts} attempts`);
|
|
@@ -16565,7 +16578,7 @@ var init_command2 = __esm({
|
|
|
16565
16578
|
});
|
|
16566
16579
|
|
|
16567
16580
|
// packages/experience-design-system-cli/src/import/path-utils.ts
|
|
16568
|
-
import { resolve as
|
|
16581
|
+
import { resolve as resolve21 } from "node:path";
|
|
16569
16582
|
import { homedir as homedir6 } from "node:os";
|
|
16570
16583
|
function expandTilde(input) {
|
|
16571
16584
|
if (input === "~" || input.startsWith("~/") || input.startsWith("~\\")) {
|
|
@@ -16579,7 +16592,7 @@ function normalizePath(input) {
|
|
|
16579
16592
|
p = p.slice(1, -1);
|
|
16580
16593
|
}
|
|
16581
16594
|
p = expandTilde(p);
|
|
16582
|
-
return
|
|
16595
|
+
return resolve21(p);
|
|
16583
16596
|
}
|
|
16584
16597
|
var init_path_utils = __esm({
|
|
16585
16598
|
"packages/experience-design-system-cli/src/import/path-utils.ts"() {
|
|
@@ -16647,7 +16660,7 @@ var init_save_path_resolver = __esm({
|
|
|
16647
16660
|
});
|
|
16648
16661
|
|
|
16649
16662
|
// packages/experience-design-system-cli/src/runs/store.ts
|
|
16650
|
-
import { readFile as
|
|
16663
|
+
import { readFile as readFile23, writeFile as writeFile6, mkdir as mkdir6, rename } from "node:fs/promises";
|
|
16651
16664
|
import { join as join20 } from "node:path";
|
|
16652
16665
|
import { homedir as homedir7 } from "node:os";
|
|
16653
16666
|
import { randomBytes as randomBytes2 } from "node:crypto";
|
|
@@ -16691,7 +16704,7 @@ function migrateRecord(rec) {
|
|
|
16691
16704
|
}
|
|
16692
16705
|
async function readFileMaybe() {
|
|
16693
16706
|
try {
|
|
16694
|
-
const raw = await
|
|
16707
|
+
const raw = await readFile23(RUNS_PATH, "utf8");
|
|
16695
16708
|
const parsed = JSON.parse(raw);
|
|
16696
16709
|
if (!READABLE_VERSIONS.has(parsed.version)) {
|
|
16697
16710
|
throw new Error(
|
|
@@ -17287,8 +17300,8 @@ var init_save_conflict = __esm({
|
|
|
17287
17300
|
|
|
17288
17301
|
// packages/experience-design-system-cli/src/runs/fingerprint.ts
|
|
17289
17302
|
import { createHash as createHash4 } from "node:crypto";
|
|
17290
|
-
import { readFile as
|
|
17291
|
-
import { resolve as
|
|
17303
|
+
import { readFile as readFile24, stat as stat5 } from "node:fs/promises";
|
|
17304
|
+
import { resolve as resolve23 } from "node:path";
|
|
17292
17305
|
function rowField(row, key) {
|
|
17293
17306
|
const v = row[key];
|
|
17294
17307
|
return typeof v === "string" ? v : null;
|
|
@@ -17304,7 +17317,7 @@ async function buildSourceFingerprint(opts) {
|
|
|
17304
17317
|
const sourcePath = rowField(row, "source_path");
|
|
17305
17318
|
const name = rowField(row, "name");
|
|
17306
17319
|
if (!sourcePath) continue;
|
|
17307
|
-
const abs =
|
|
17320
|
+
const abs = resolve23(sourcePath);
|
|
17308
17321
|
if (seen.has(abs)) continue;
|
|
17309
17322
|
seen.add(abs);
|
|
17310
17323
|
try {
|
|
@@ -17319,10 +17332,10 @@ async function buildSourceFingerprint(opts) {
|
|
|
17319
17332
|
let rawTokensMtime = null;
|
|
17320
17333
|
let rawTokensContentHash = null;
|
|
17321
17334
|
if (opts.rawTokensPath) {
|
|
17322
|
-
const abs =
|
|
17335
|
+
const abs = resolve23(opts.rawTokensPath);
|
|
17323
17336
|
rawTokensPath = abs;
|
|
17324
17337
|
try {
|
|
17325
|
-
const [st, buf] = await Promise.all([stat5(abs),
|
|
17338
|
+
const [st, buf] = await Promise.all([stat5(abs), readFile24(abs)]);
|
|
17326
17339
|
rawTokensMtime = st.mtime.toISOString();
|
|
17327
17340
|
rawTokensContentHash = sha256Hex(buf);
|
|
17328
17341
|
} catch {
|
|
@@ -17935,8 +17948,11 @@ function CredentialsStep({
|
|
|
17935
17948
|
"\u2713 ",
|
|
17936
17949
|
summary
|
|
17937
17950
|
] }),
|
|
17938
|
-
/* @__PURE__ */
|
|
17939
|
-
|
|
17951
|
+
/* @__PURE__ */ jsxs28(Box28, { flexDirection: "column", marginTop: 1, gap: 0, children: [
|
|
17952
|
+
/* @__PURE__ */ jsx28(Text28, { children: initialSpaceId && initialCmaToken ? "Credentials pre-filled from experiences setup. Press Enter to continue or edit any field to update." : "Enter the Contentful space you want to import into." }),
|
|
17953
|
+
!(initialSpaceId && initialCmaToken) && /* @__PURE__ */ jsx28(Text28, { dimColor: true, children: "These credentials are used both to align agent suggestions with what already exists in the space and to push your import at the end. Press S to skip and run without space context (push will be disabled)." }),
|
|
17954
|
+
!(initialSpaceId && initialCmaToken) && /* @__PURE__ */ jsx28(Text28, { dimColor: true, children: "Tip: run experiences setup to save these to ~/.config/experiences/credentials.json so they pre-fill here automatically." })
|
|
17955
|
+
] }),
|
|
17940
17956
|
/* @__PURE__ */ jsxs28(Box28, { flexDirection: "column", gap: 0, marginTop: 1, children: [
|
|
17941
17957
|
renderField("Space ID", spaceId, "spaceId"),
|
|
17942
17958
|
renderField("Environment", environmentId, "environmentId"),
|
|
@@ -19103,9 +19119,9 @@ function spawnGenerateChild(opts) {
|
|
|
19103
19119
|
stderr += chunk;
|
|
19104
19120
|
opts.onStderr?.(chunk);
|
|
19105
19121
|
});
|
|
19106
|
-
const donePromise = new Promise((
|
|
19122
|
+
const donePromise = new Promise((resolve28) => {
|
|
19107
19123
|
child.on("close", (code, signal) => {
|
|
19108
|
-
|
|
19124
|
+
resolve28({
|
|
19109
19125
|
exitCode: code ?? 0,
|
|
19110
19126
|
signal: signal ?? null,
|
|
19111
19127
|
stdout,
|
|
@@ -19113,7 +19129,7 @@ function spawnGenerateChild(opts) {
|
|
|
19113
19129
|
});
|
|
19114
19130
|
});
|
|
19115
19131
|
child.on("error", (err) => {
|
|
19116
|
-
|
|
19132
|
+
resolve28({
|
|
19117
19133
|
exitCode: 1,
|
|
19118
19134
|
signal: null,
|
|
19119
19135
|
stdout,
|
|
@@ -27656,9 +27672,9 @@ __export(WizardApp_exports, {
|
|
|
27656
27672
|
});
|
|
27657
27673
|
import { useEffect as useEffect15, useRef as useRef9, useState as useState28 } from "react";
|
|
27658
27674
|
import { Box as Box49, Text as Text51, useStdout as useStdout8 } from "ink";
|
|
27659
|
-
import { join as join23, resolve as
|
|
27675
|
+
import { join as join23, resolve as resolve24 } from "node:path";
|
|
27660
27676
|
import { appendFileSync as appendFileSync2, writeFileSync } from "node:fs";
|
|
27661
|
-
import { access as access9, readFile as
|
|
27677
|
+
import { access as access9, readFile as readFile25, stat as stat6 } from "node:fs/promises";
|
|
27662
27678
|
import { tmpdir } from "node:os";
|
|
27663
27679
|
import { execFile as execFile4, spawn as spawn4 } from "node:child_process";
|
|
27664
27680
|
import { mkdir as mkdir7 } from "node:fs/promises";
|
|
@@ -27802,7 +27818,7 @@ function WizardApp({
|
|
|
27802
27818
|
const rawTokensEntryReady = !modifyEntryReady && !pushFromPickerReady && !!initialRawTokensPath;
|
|
27803
27819
|
const effectiveNoCache = resolveNoCacheForGenerate({ cliNoCache: noCache });
|
|
27804
27820
|
const initialStepResolved = modifyEntryReady ? "final-review" : pushFromPickerReady ? "push-from-picker" : rawTokensEntryReady ? "generating-tokens" : initialProjectPath ? "token-input" : "welcome";
|
|
27805
|
-
const initialOutDir = initialProjectPath ? join23(
|
|
27821
|
+
const initialOutDir = initialProjectPath ? join23(resolve24(initialProjectPath), ".contentful") : "";
|
|
27806
27822
|
const initialTokensPath = (modifyEntryReady || pushFromPickerReady) && initialOutDir && seedTokenSessionId ? join23(initialOutDir, "tokens.json") : "";
|
|
27807
27823
|
const [state, setState] = useState28({
|
|
27808
27824
|
step: modifyEntryReady || rawTokensEntryReady || pushFromPickerReady ? initialStepResolved : initialRuns && initialRuns.length > 0 ? "run-picker" : initialStepResolved,
|
|
@@ -28056,7 +28072,7 @@ If you are using AWS Bedrock, run:
|
|
|
28056
28072
|
return true;
|
|
28057
28073
|
};
|
|
28058
28074
|
const runExtract = async (projectPath) => {
|
|
28059
|
-
const outDir = join23(
|
|
28075
|
+
const outDir = join23(resolve24(projectPath), ".contentful");
|
|
28060
28076
|
update({ step: "extracting", outDir, extractProgress: null, compositionPhase: null });
|
|
28061
28077
|
const r = await new Promise((res) => {
|
|
28062
28078
|
const extractArgs = [findCliPath(), "analyze", "extract", "--project", projectPath];
|
|
@@ -28372,7 +28388,7 @@ Make sure this path contains TypeScript/React/Vue component files (.tsx, .ts, .v
|
|
|
28372
28388
|
if (await runMapTokens2(mappedSessionId)) update({ step: "final-review" });
|
|
28373
28389
|
};
|
|
28374
28390
|
const advanceToPushFlow = (generatedAcceptedCount) => {
|
|
28375
|
-
update({ generatedAcceptedCount, step: "
|
|
28391
|
+
update({ generatedAcceptedCount, step: "push-decision-gate" });
|
|
28376
28392
|
};
|
|
28377
28393
|
const runEditFromPreview = async () => {
|
|
28378
28394
|
update({ step: "final-review" });
|
|
@@ -28443,6 +28459,10 @@ Make sure this path contains TypeScript/React/Vue component files (.tsx, .ts, .v
|
|
|
28443
28459
|
}
|
|
28444
28460
|
};
|
|
28445
28461
|
const advanceAfterCredentialsValidated = async () => {
|
|
28462
|
+
if (!sessionRef.current.extractSessionId && state.projectPath) {
|
|
28463
|
+
void runExtract(state.projectPath);
|
|
28464
|
+
return;
|
|
28465
|
+
}
|
|
28446
28466
|
if (shouldSkipFinalReviewAfterCredentials(state)) {
|
|
28447
28467
|
update({ step: "push-decision-gate" });
|
|
28448
28468
|
return;
|
|
@@ -28901,8 +28921,8 @@ If using a custom --host, make sure the space exists on that host.`
|
|
|
28901
28921
|
);
|
|
28902
28922
|
}
|
|
28903
28923
|
try {
|
|
28904
|
-
const componentsBuf = await
|
|
28905
|
-
const tokensBuf = recordedTokensPath ? await
|
|
28924
|
+
const componentsBuf = await readFile25(join23(path, "components.json")).catch(() => null);
|
|
28925
|
+
const tokensBuf = recordedTokensPath ? await readFile25(recordedTokensPath).catch(() => null) : null;
|
|
28906
28926
|
savedFingerprint = buildSavedFingerprint({
|
|
28907
28927
|
componentsJson: componentsBuf,
|
|
28908
28928
|
tokensJson: tokensBuf
|
|
@@ -29084,7 +29104,7 @@ If using a custom --host, make sure the space exists on that host.`
|
|
|
29084
29104
|
{
|
|
29085
29105
|
projectPath: state.projectPath,
|
|
29086
29106
|
onConfirm: (path) => {
|
|
29087
|
-
|
|
29107
|
+
update({ projectPath: path, step: "credentials" });
|
|
29088
29108
|
},
|
|
29089
29109
|
onSkipComponents: () => {
|
|
29090
29110
|
if (noPush) {
|
|
@@ -29168,12 +29188,7 @@ If using a custom --host, make sure the space exists on that host.`
|
|
|
29168
29188
|
}
|
|
29169
29189
|
return;
|
|
29170
29190
|
}
|
|
29171
|
-
|
|
29172
|
-
if (await runAgentAuthCheck("credentials")) {
|
|
29173
|
-
startGeneratePrefetch(sid, state.tokensPath);
|
|
29174
|
-
}
|
|
29175
|
-
}
|
|
29176
|
-
update({ step: "credentials" });
|
|
29191
|
+
update({ step: "push-decision-gate" });
|
|
29177
29192
|
},
|
|
29178
29193
|
onAdvanceToPushFlow: (count) => {
|
|
29179
29194
|
update({ acceptedCount: count, autoRejectedCount: 0 });
|
|
@@ -29658,7 +29673,7 @@ __export(staleness_exports, {
|
|
|
29658
29673
|
formatStalenessDetail: () => formatStalenessDetail,
|
|
29659
29674
|
shortStalenessSummary: () => shortStalenessSummary
|
|
29660
29675
|
});
|
|
29661
|
-
import { readFile as
|
|
29676
|
+
import { readFile as readFile26, stat as stat7 } from "node:fs/promises";
|
|
29662
29677
|
import { join as join24 } from "node:path";
|
|
29663
29678
|
async function checkRunStaleness(run) {
|
|
29664
29679
|
if (!run.sourceFingerprint) return { ...UNKNOWN };
|
|
@@ -29685,7 +29700,7 @@ async function checkRunStaleness(run) {
|
|
|
29685
29700
|
if (run.sourceFingerprint.rawTokensPath) {
|
|
29686
29701
|
const absPath = run.sourceFingerprint.rawTokensPath;
|
|
29687
29702
|
try {
|
|
29688
|
-
const [st, buf] = await Promise.all([stat7(absPath),
|
|
29703
|
+
const [st, buf] = await Promise.all([stat7(absPath), readFile26(absPath)]);
|
|
29689
29704
|
const mtime = st.mtime.toISOString();
|
|
29690
29705
|
const hash = sha256Hex(buf);
|
|
29691
29706
|
const mtimeChanged = run.sourceFingerprint.rawTokensMtime !== null && mtime !== run.sourceFingerprint.rawTokensMtime;
|
|
@@ -29703,7 +29718,7 @@ async function checkRunStaleness(run) {
|
|
|
29703
29718
|
if (run.savedFingerprint.componentsJsonHash !== null) {
|
|
29704
29719
|
const compPath = join24(run.savePath, "components.json");
|
|
29705
29720
|
try {
|
|
29706
|
-
const buf = await
|
|
29721
|
+
const buf = await readFile26(compPath);
|
|
29707
29722
|
if (sha256Hex(buf) !== run.savedFingerprint.componentsJsonHash) {
|
|
29708
29723
|
result.savedComponentsEdited = true;
|
|
29709
29724
|
result.stale = true;
|
|
@@ -29716,7 +29731,7 @@ async function checkRunStaleness(run) {
|
|
|
29716
29731
|
if (run.savedFingerprint.tokensJsonHash !== null) {
|
|
29717
29732
|
const tokensPath = run.tokensPath ?? join24(run.savePath, "tokens.json");
|
|
29718
29733
|
try {
|
|
29719
|
-
const buf = await
|
|
29734
|
+
const buf = await readFile26(tokensPath);
|
|
29720
29735
|
if (sha256Hex(buf) !== run.savedFingerprint.tokensJsonHash) {
|
|
29721
29736
|
result.savedTokensEdited = true;
|
|
29722
29737
|
result.stale = true;
|
|
@@ -29783,7 +29798,7 @@ async function promptForPushCredentials(opts = {}) {
|
|
|
29783
29798
|
const { render: render7, Box: Box50, Text: Text52 } = await import("ink");
|
|
29784
29799
|
const { useState: useState29 } = await import("react");
|
|
29785
29800
|
const { CredentialsStep: CredentialsStep2 } = await Promise.resolve().then(() => (init_CredentialsStep(), CredentialsStep_exports));
|
|
29786
|
-
return new Promise((
|
|
29801
|
+
return new Promise((resolve28, reject) => {
|
|
29787
29802
|
let app = null;
|
|
29788
29803
|
function App2() {
|
|
29789
29804
|
const [done, setDone] = useState29(false);
|
|
@@ -29792,7 +29807,7 @@ async function promptForPushCredentials(opts = {}) {
|
|
|
29792
29807
|
setDone(true);
|
|
29793
29808
|
queueMicrotask(() => {
|
|
29794
29809
|
app?.unmount();
|
|
29795
|
-
|
|
29810
|
+
resolve28({ spaceId, environmentId, cmaToken, host });
|
|
29796
29811
|
});
|
|
29797
29812
|
};
|
|
29798
29813
|
if (done) {
|
|
@@ -29824,14 +29839,14 @@ var init_push_creds_prompt = __esm({
|
|
|
29824
29839
|
// packages/experience-design-system-cli/src/program.ts
|
|
29825
29840
|
import { spawn as spawn6 } from "node:child_process";
|
|
29826
29841
|
import { fileURLToPath as fileURLToPath5 } from "node:url";
|
|
29827
|
-
import { dirname as dirname14, join as join27, resolve as
|
|
29842
|
+
import { dirname as dirname14, join as join27, resolve as resolve27 } from "node:path";
|
|
29828
29843
|
import { readFileSync as readFileSync10 } from "node:fs";
|
|
29829
29844
|
import { Command } from "commander";
|
|
29830
29845
|
|
|
29831
29846
|
// packages/experience-design-system-cli/src/analyze/command.ts
|
|
29832
29847
|
import { createElement as createElement3 } from "react";
|
|
29833
29848
|
import { render as render3 } from "ink";
|
|
29834
|
-
import { mkdir as mkdir3, readdir as readdir2, readFile as
|
|
29849
|
+
import { mkdir as mkdir3, readdir as readdir2, readFile as readFile17, stat as stat2, writeFile as writeFile3 } from "node:fs/promises";
|
|
29835
29850
|
import { isAbsolute as isAbsolute4, join as join15, relative as relative3, resolve as resolve15 } from "node:path";
|
|
29836
29851
|
|
|
29837
29852
|
// packages/experience-design-system-cli/src/lib/agent-model-options.ts
|
|
@@ -29958,6 +29973,104 @@ init_command2();
|
|
|
29958
29973
|
// packages/experience-design-system-cli/src/analyze/select-agent/command.ts
|
|
29959
29974
|
init_db();
|
|
29960
29975
|
init_cache_keys();
|
|
29976
|
+
|
|
29977
|
+
// packages/experience-design-system-cli/src/helpers/read-existing-contentful-entities-from-session.ts
|
|
29978
|
+
import { readFile as readFile13 } from "node:fs/promises";
|
|
29979
|
+
async function readExistingContentfulEntitiesFromSession(path) {
|
|
29980
|
+
if (!path) return void 0;
|
|
29981
|
+
try {
|
|
29982
|
+
const raw = await readFile13(path, "utf8");
|
|
29983
|
+
const parsed = JSON.parse(raw);
|
|
29984
|
+
if (!Array.isArray(parsed.components) || !Array.isArray(parsed.tokens)) return void 0;
|
|
29985
|
+
return parsed;
|
|
29986
|
+
} catch {
|
|
29987
|
+
return void 0;
|
|
29988
|
+
}
|
|
29989
|
+
}
|
|
29990
|
+
|
|
29991
|
+
// packages/experience-design-system-cli/src/helpers/find-nearly-matching-component.ts
|
|
29992
|
+
var MAX_CHARACTER_EDITS_FOR_LIKELY_MATCH = 2;
|
|
29993
|
+
function findNearlyMatchingComponent(components, codebaseName) {
|
|
29994
|
+
const target = simplifyNameForComparison(codebaseName);
|
|
29995
|
+
if (!target) return void 0;
|
|
29996
|
+
let best;
|
|
29997
|
+
for (const c2 of components) {
|
|
29998
|
+
const edits = countCharacterEdits(target, simplifyNameForComparison(c2.name));
|
|
29999
|
+
if (edits > MAX_CHARACTER_EDITS_FOR_LIKELY_MATCH) continue;
|
|
30000
|
+
if (!best || edits < best.edits) best = { component: c2, edits };
|
|
30001
|
+
if (edits === 0) break;
|
|
30002
|
+
}
|
|
30003
|
+
return best?.component;
|
|
30004
|
+
}
|
|
30005
|
+
function simplifyNameForComparison(name) {
|
|
30006
|
+
const stripped = name.toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
30007
|
+
return stripped.endsWith("s") && stripped.length > 1 ? stripped.slice(0, -1) : stripped;
|
|
30008
|
+
}
|
|
30009
|
+
function countCharacterEdits(a, b) {
|
|
30010
|
+
if (a === b) return 0;
|
|
30011
|
+
if (a.length === 0) return b.length;
|
|
30012
|
+
if (b.length === 0) return a.length;
|
|
30013
|
+
if (a.length > b.length) [a, b] = [b, a];
|
|
30014
|
+
let prev = new Array(a.length + 1);
|
|
30015
|
+
let curr = new Array(a.length + 1);
|
|
30016
|
+
for (let i = 0; i <= a.length; i++) prev[i] = i;
|
|
30017
|
+
for (let j = 1; j <= b.length; j++) {
|
|
30018
|
+
curr[0] = j;
|
|
30019
|
+
for (let i = 1; i <= a.length; i++) {
|
|
30020
|
+
const cost = a[i - 1] === b[j - 1] ? 0 : 1;
|
|
30021
|
+
curr[i] = Math.min(curr[i - 1] + 1, prev[i] + 1, prev[i - 1] + cost);
|
|
30022
|
+
}
|
|
30023
|
+
[prev, curr] = [curr, prev];
|
|
30024
|
+
}
|
|
30025
|
+
return prev[a.length];
|
|
30026
|
+
}
|
|
30027
|
+
|
|
30028
|
+
// packages/experience-design-system-cli/src/helpers/summarize-existing-contentful-entities.ts
|
|
30029
|
+
function summarizeForSelectAgent(entities) {
|
|
30030
|
+
return {
|
|
30031
|
+
components: entities.components.map((c2) => ({
|
|
30032
|
+
id: c2.sys.id,
|
|
30033
|
+
name: c2.name,
|
|
30034
|
+
description: c2.description
|
|
30035
|
+
})),
|
|
30036
|
+
tokens: summarizeTokens(entities.tokens)
|
|
30037
|
+
};
|
|
30038
|
+
}
|
|
30039
|
+
function summarizeForGenerateAgent(entities, codebaseComponentName) {
|
|
30040
|
+
const match2 = findNearlyMatchingComponent(entities.components, codebaseComponentName);
|
|
30041
|
+
const otherComponents = entities.components.filter((c2) => c2.sys.id !== match2?.sys.id).map((c2) => ({ id: c2.sys.id, name: c2.name }));
|
|
30042
|
+
return {
|
|
30043
|
+
likelyMatch: match2 ? {
|
|
30044
|
+
id: match2.sys.id,
|
|
30045
|
+
name: match2.name,
|
|
30046
|
+
designProperties: match2.designProperties.map((p) => ({
|
|
30047
|
+
id: p.id,
|
|
30048
|
+
name: p.name,
|
|
30049
|
+
type: p.type
|
|
30050
|
+
})),
|
|
30051
|
+
contentProperties: match2.contentProperties.map((p) => ({
|
|
30052
|
+
id: p.id,
|
|
30053
|
+
name: p.name,
|
|
30054
|
+
type: p.type
|
|
30055
|
+
})),
|
|
30056
|
+
slots: (match2.slots ?? []).map((s) => ({ id: s.id, name: s.name }))
|
|
30057
|
+
} : void 0,
|
|
30058
|
+
otherComponents,
|
|
30059
|
+
tokens: summarizeTokens(entities.tokens)
|
|
30060
|
+
};
|
|
30061
|
+
}
|
|
30062
|
+
function summarizeForMapTokens(entities) {
|
|
30063
|
+
return {
|
|
30064
|
+
tokens: entities.tokens.map((t) => ({ id: t.sys.id, name: t.name, type: t.type }))
|
|
30065
|
+
};
|
|
30066
|
+
}
|
|
30067
|
+
function summarizeTokens(tokens) {
|
|
30068
|
+
const kinds = /* @__PURE__ */ new Set();
|
|
30069
|
+
for (const t of tokens) kinds.add(t.type);
|
|
30070
|
+
return { count: tokens.length, kinds: [...kinds].sort() };
|
|
30071
|
+
}
|
|
30072
|
+
|
|
30073
|
+
// packages/experience-design-system-cli/src/analyze/select-agent/command.ts
|
|
29961
30074
|
init_persistence();
|
|
29962
30075
|
init_parser();
|
|
29963
30076
|
init_src();
|
|
@@ -30059,7 +30172,7 @@ var OutputFormatter = class {
|
|
|
30059
30172
|
};
|
|
30060
30173
|
|
|
30061
30174
|
// packages/experience-design-system-cli/src/analyze/select-agent/context-builder.ts
|
|
30062
|
-
import { readFile as
|
|
30175
|
+
import { readFile as readFile14 } from "node:fs/promises";
|
|
30063
30176
|
import { dirname as dirname10, isAbsolute as isAbsolute2, join as join13, relative as relative2, resolve as resolve11, sep } from "node:path";
|
|
30064
30177
|
var SCANNED_FILE_EXTENSIONS = /* @__PURE__ */ new Set([".astro", ".js", ".jsx", ".svelte", ".ts", ".tsx", ".vue"]);
|
|
30065
30178
|
var IMPORT_PATTERN2 = /import\s+(?:type\s+)?(.+?)\s+from\s+['"]([^'"]+)['"]/g;
|
|
@@ -30188,7 +30301,7 @@ async function buildRepoContextIndex(root, filePaths) {
|
|
|
30188
30301
|
absolutePath,
|
|
30189
30302
|
relativePath: toPosixPath(relative2(resolvedRoot, absolutePath)),
|
|
30190
30303
|
directory: dirname10(absolutePath),
|
|
30191
|
-
text: await
|
|
30304
|
+
text: await readFile14(absolutePath, "utf8").catch(() => "")
|
|
30192
30305
|
})
|
|
30193
30306
|
)
|
|
30194
30307
|
);
|
|
@@ -30401,7 +30514,7 @@ function resolveProjectRoot(sessionId2, projectRootFlag) {
|
|
|
30401
30514
|
db.close();
|
|
30402
30515
|
}
|
|
30403
30516
|
}
|
|
30404
|
-
async function selectBatch(agent, model, batch, total, verbose, skillPathOverride) {
|
|
30517
|
+
async function selectBatch(agent, model, batch, total, verbose, skillPathOverride, existingComponentsInline) {
|
|
30405
30518
|
const prompt2 = await buildPrompt({
|
|
30406
30519
|
skill: "select",
|
|
30407
30520
|
mode: "autonomous",
|
|
@@ -30411,7 +30524,8 @@ async function selectBatch(agent, model, batch, total, verbose, skillPathOverrid
|
|
|
30411
30524
|
2
|
|
30412
30525
|
),
|
|
30413
30526
|
outDir: process.cwd(),
|
|
30414
|
-
skillPathOverride
|
|
30527
|
+
skillPathOverride,
|
|
30528
|
+
existingComponentsInline
|
|
30415
30529
|
});
|
|
30416
30530
|
let outputBuf = "";
|
|
30417
30531
|
const formatter = new OutputFormatter(verbose, (s) => {
|
|
@@ -30506,7 +30620,7 @@ ${outputBuf}`);
|
|
|
30506
30620
|
}
|
|
30507
30621
|
return results;
|
|
30508
30622
|
}
|
|
30509
|
-
async function selectAllComponents(agent, model, components, verbose, skillPathOverride, cacheConfig = { noCache: true }) {
|
|
30623
|
+
async function selectAllComponents(agent, model, components, verbose, skillPathOverride, existingComponentsInline, cacheConfig = { noCache: true }) {
|
|
30510
30624
|
const concurrency = Number(process.env.EDS_GENERATE_CONCURRENCY ?? DEFAULT_CONCURRENCY);
|
|
30511
30625
|
const batchSize = resolveBatchSize();
|
|
30512
30626
|
const total = components.length;
|
|
@@ -30515,7 +30629,13 @@ async function selectAllComponents(agent, model, components, verbose, skillPathO
|
|
|
30515
30629
|
let cliVersion2 = "";
|
|
30516
30630
|
if (!cacheConfig.noCache) {
|
|
30517
30631
|
try {
|
|
30518
|
-
promptHash = await hashPromptForSkill(
|
|
30632
|
+
promptHash = await hashPromptForSkill(
|
|
30633
|
+
"select",
|
|
30634
|
+
agent,
|
|
30635
|
+
model,
|
|
30636
|
+
skillPathOverride,
|
|
30637
|
+
existingComponentsInline ? [hashContent(existingComponentsInline)] : []
|
|
30638
|
+
);
|
|
30519
30639
|
cliVersion2 = await getCliCacheVersion();
|
|
30520
30640
|
const db = openPipelineDb(cacheConfig.dbPath);
|
|
30521
30641
|
try {
|
|
@@ -30571,7 +30691,15 @@ async function selectAllComponents(agent, model, components, verbose, skillPathO
|
|
|
30571
30691
|
while (nextBatch < batches.length) {
|
|
30572
30692
|
const b = nextBatch++;
|
|
30573
30693
|
const batch = batches[b];
|
|
30574
|
-
const batchResults = await selectBatch(
|
|
30694
|
+
const batchResults = await selectBatch(
|
|
30695
|
+
agent,
|
|
30696
|
+
model,
|
|
30697
|
+
batch,
|
|
30698
|
+
total,
|
|
30699
|
+
verbose,
|
|
30700
|
+
skillPathOverride,
|
|
30701
|
+
existingComponentsInline
|
|
30702
|
+
);
|
|
30575
30703
|
for (let k = 0; k < batch.length; k++) {
|
|
30576
30704
|
results[batch[k].index] = batchResults[k];
|
|
30577
30705
|
}
|
|
@@ -30607,6 +30735,9 @@ function registerAnalyzeSelectAgentCommand(program) {
|
|
|
30607
30735
|
"--select-prompt-path <path>",
|
|
30608
30736
|
"Path to a custom .md skill prompt for select-agent (bypasses bundled prompt invariants)"
|
|
30609
30737
|
).option("--no-select-cache", "Skip the per-component select cache and re-LLM every component").option("--no-cache", "Skip ALL fine-grained caches (extract, select, generate)").option(
|
|
30738
|
+
"--existing-entities-path <path>",
|
|
30739
|
+
"Path to the .existing-entities.json file written by the orchestrator when CMA credentials are supplied. When present, the agent gets an existing-components summary to align rejection/acceptance reasoning with the target space. Missing/malformed files are treated as no-op."
|
|
30740
|
+
).option(
|
|
30610
30741
|
"--show-rationale",
|
|
30611
30742
|
"Read-only: print the AI rejection rationale persisted by a prior select-agent run and exit. No LLM call. Combine with --json for machine-readable output."
|
|
30612
30743
|
).option("--json", "When used with --show-rationale, emit a JSON array instead of a human-readable table").action(
|
|
@@ -30715,6 +30846,20 @@ function registerAnalyzeSelectAgentCommand(program) {
|
|
|
30715
30846
|
}));
|
|
30716
30847
|
}
|
|
30717
30848
|
}
|
|
30849
|
+
let existingComponentsInline;
|
|
30850
|
+
if (opts.existingEntitiesPath) {
|
|
30851
|
+
const existingContentfulEntities = await readExistingContentfulEntitiesFromSession(
|
|
30852
|
+
resolve12(opts.existingEntitiesPath)
|
|
30853
|
+
);
|
|
30854
|
+
if (existingContentfulEntities) {
|
|
30855
|
+
existingComponentsInline = JSON.stringify(summarizeForSelectAgent(existingContentfulEntities));
|
|
30856
|
+
} else {
|
|
30857
|
+
process.stderr.write(
|
|
30858
|
+
`warn: --existing-entities-path ${opts.existingEntitiesPath} could not be read as JSON \u2014 proceeding without space-context enrichment
|
|
30859
|
+
`
|
|
30860
|
+
);
|
|
30861
|
+
}
|
|
30862
|
+
}
|
|
30718
30863
|
if (opts.dryRun) {
|
|
30719
30864
|
if (selectionCandidates.length === 0) {
|
|
30720
30865
|
process.stderr.write(
|
|
@@ -30729,7 +30874,8 @@ function registerAnalyzeSelectAgentCommand(program) {
|
|
|
30729
30874
|
mode: "autonomous",
|
|
30730
30875
|
rawComponentsInline: JSON.stringify([buildComponentData(first)], null, 2),
|
|
30731
30876
|
outDir: process.cwd(),
|
|
30732
|
-
skillPathOverride: selectPromptPath ? resolve12(selectPromptPath) : void 0
|
|
30877
|
+
skillPathOverride: selectPromptPath ? resolve12(selectPromptPath) : void 0,
|
|
30878
|
+
existingComponentsInline
|
|
30733
30879
|
});
|
|
30734
30880
|
process.stdout.write(prompt2 + "\n");
|
|
30735
30881
|
await exitWithAnalytics(0);
|
|
@@ -30742,6 +30888,7 @@ function registerAnalyzeSelectAgentCommand(program) {
|
|
|
30742
30888
|
selectionCandidates,
|
|
30743
30889
|
opts.verbose ?? false,
|
|
30744
30890
|
selectPromptPath ? resolve12(selectPromptPath) : void 0,
|
|
30891
|
+
existingComponentsInline,
|
|
30745
30892
|
{ noCache }
|
|
30746
30893
|
);
|
|
30747
30894
|
const decisions = /* @__PURE__ */ new Map();
|
|
@@ -31129,11 +31276,11 @@ ${f.content}`).join("\n\n");
|
|
|
31129
31276
|
}
|
|
31130
31277
|
|
|
31131
31278
|
// packages/experience-design-system-cli/src/analyze/composition/resolve-mapping-cli.ts
|
|
31132
|
-
import { readFile as
|
|
31279
|
+
import { readFile as readFile15 } from "node:fs/promises";
|
|
31133
31280
|
async function loadUserMap(path) {
|
|
31134
31281
|
let text;
|
|
31135
31282
|
try {
|
|
31136
|
-
text = await
|
|
31283
|
+
text = await readFile15(path, "utf8");
|
|
31137
31284
|
} catch {
|
|
31138
31285
|
return { ok: false, error: `--composition-map: file not found: ${path}` };
|
|
31139
31286
|
}
|
|
@@ -31369,16 +31516,16 @@ var HEAP_CAP_MB = 128;
|
|
|
31369
31516
|
var MAX_INPUT_BYTES = 8 * 1024 * 1024;
|
|
31370
31517
|
function runParserInSandbox(source, ctx, opts = {}) {
|
|
31371
31518
|
const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS2;
|
|
31372
|
-
return new Promise((
|
|
31519
|
+
return new Promise((resolve28) => {
|
|
31373
31520
|
let input;
|
|
31374
31521
|
try {
|
|
31375
31522
|
input = JSON.stringify({ source, ctx, timeoutMs });
|
|
31376
31523
|
} catch {
|
|
31377
|
-
|
|
31524
|
+
resolve28({ edges: [], error: "ctx is not serializable" });
|
|
31378
31525
|
return;
|
|
31379
31526
|
}
|
|
31380
31527
|
if (input.length > MAX_INPUT_BYTES) {
|
|
31381
|
-
|
|
31528
|
+
resolve28({ edges: [], error: "parser input exceeds size limit" });
|
|
31382
31529
|
return;
|
|
31383
31530
|
}
|
|
31384
31531
|
let settled = false;
|
|
@@ -31410,7 +31557,7 @@ function runParserInSandbox(source, ctx, opts = {}) {
|
|
|
31410
31557
|
child.kill("SIGKILL");
|
|
31411
31558
|
} catch {
|
|
31412
31559
|
}
|
|
31413
|
-
|
|
31560
|
+
resolve28(r);
|
|
31414
31561
|
};
|
|
31415
31562
|
const timer = setTimeout(
|
|
31416
31563
|
() => done({ edges: [], error: `parser timed out after ${timeoutMs}ms` }),
|
|
@@ -31622,7 +31769,7 @@ ${loadPrompt("composition-parser-repair-error.md").trim().replace("{{error}}", f
|
|
|
31622
31769
|
}
|
|
31623
31770
|
|
|
31624
31771
|
// packages/experience-design-system-cli/src/lib/prompt-overrides.ts
|
|
31625
|
-
import { readFile as
|
|
31772
|
+
import { readFile as readFile16 } from "node:fs/promises";
|
|
31626
31773
|
import { resolve as resolve14 } from "node:path";
|
|
31627
31774
|
var PROMPT_FILE_EXTENSIONS = [".md", ".txt", ".prompt"];
|
|
31628
31775
|
function looksLikePath(value) {
|
|
@@ -31658,7 +31805,7 @@ async function resolvePromptOverride(override) {
|
|
|
31658
31805
|
if (override.kind === "text") return override.value;
|
|
31659
31806
|
const abs = resolve14(override.value);
|
|
31660
31807
|
try {
|
|
31661
|
-
return await
|
|
31808
|
+
return await readFile16(abs, "utf8");
|
|
31662
31809
|
} catch {
|
|
31663
31810
|
throw new Error(`--prompt: could not read prompt file: ${abs}`);
|
|
31664
31811
|
}
|
|
@@ -31841,7 +31988,7 @@ async function readCandidateFiles(components, extraFiles = []) {
|
|
|
31841
31988
|
await Promise.all(
|
|
31842
31989
|
[...paths].map(async (p) => {
|
|
31843
31990
|
try {
|
|
31844
|
-
const content = await
|
|
31991
|
+
const content = await readFile17(p, "utf8");
|
|
31845
31992
|
out.push({ path: p, content });
|
|
31846
31993
|
} catch {
|
|
31847
31994
|
}
|
|
@@ -32245,7 +32392,7 @@ function registerAnalyzeCommand(program) {
|
|
|
32245
32392
|
init_src();
|
|
32246
32393
|
import { createElement as createElement4 } from "react";
|
|
32247
32394
|
import { render as render4 } from "ink";
|
|
32248
|
-
import { access as access6, readFile as
|
|
32395
|
+
import { access as access6, readFile as readFile19, readdir as readdir3, stat as stat3 } from "node:fs/promises";
|
|
32249
32396
|
import { join as join16, resolve as resolve17 } from "node:path";
|
|
32250
32397
|
init_debug_logger();
|
|
32251
32398
|
|
|
@@ -32286,7 +32433,7 @@ function GenerateView({ result, onExit }) {
|
|
|
32286
32433
|
}
|
|
32287
32434
|
|
|
32288
32435
|
// packages/experience-design-system-cli/src/generate/edit/command.ts
|
|
32289
|
-
import { readFile as
|
|
32436
|
+
import { readFile as readFile18 } from "node:fs/promises";
|
|
32290
32437
|
import { resolve as resolve16 } from "node:path";
|
|
32291
32438
|
var SAFE_PATH_RE2 = /^[a-zA-Z0-9_.$[\]=]+$/;
|
|
32292
32439
|
var PROTO_KEYS2 = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
|
|
@@ -32369,7 +32516,7 @@ async function runNonInteractive2(opts, skill) {
|
|
|
32369
32516
|
if (opts.patch) {
|
|
32370
32517
|
let patchOps;
|
|
32371
32518
|
try {
|
|
32372
|
-
const raw = await
|
|
32519
|
+
const raw = await readFile18(resolve16(opts.patch), "utf8");
|
|
32373
32520
|
patchOps = JSON.parse(raw);
|
|
32374
32521
|
} catch {
|
|
32375
32522
|
process.stderr.write(`Error: cannot read or parse --patch file: ${opts.patch}
|
|
@@ -32463,7 +32610,7 @@ async function readFileInline(path) {
|
|
|
32463
32610
|
} catch {
|
|
32464
32611
|
return void 0;
|
|
32465
32612
|
}
|
|
32466
|
-
if (!s.isDirectory()) return
|
|
32613
|
+
if (!s.isDirectory()) return readFile19(resolved, "utf8");
|
|
32467
32614
|
const files = [];
|
|
32468
32615
|
async function walk(dir) {
|
|
32469
32616
|
let entries;
|
|
@@ -32489,7 +32636,7 @@ async function readFileInline(path) {
|
|
|
32489
32636
|
}
|
|
32490
32637
|
await walk(resolved);
|
|
32491
32638
|
if (files.length === 0) return void 0;
|
|
32492
|
-
const parts = await Promise.all(files.map((f) =>
|
|
32639
|
+
const parts = await Promise.all(files.map((f) => readFile19(f, "utf8").catch(() => "")));
|
|
32493
32640
|
return parts.filter(Boolean).join("\n\n");
|
|
32494
32641
|
}
|
|
32495
32642
|
function printFallbackInstructions(options) {
|
|
@@ -32511,7 +32658,7 @@ function printFallbackInstructions(options) {
|
|
|
32511
32658
|
lines.push(` Re-run the generate command with the agent available, or use --dry-run to inspect the prompt.`);
|
|
32512
32659
|
process.stderr.write(lines.join("\n") + "\n");
|
|
32513
32660
|
}
|
|
32514
|
-
async function runOneComponent(agent, model, db, sessionId2, component, tokensInline, tokenMapInline, index, total, verbose, noCache, skillPathOverride, promptHash) {
|
|
32661
|
+
async function runOneComponent(agent, model, db, sessionId2, component, tokensInline, tokenMapInline, index, total, verbose, noCache, skillPathOverride, promptHash, existingContentfulEntities, existingTokensInline) {
|
|
32515
32662
|
const pos = c.dim(`[${index + 1}/${total}]`);
|
|
32516
32663
|
if (!noCache) {
|
|
32517
32664
|
const inputHash = computeComponentInputHash(component);
|
|
@@ -32581,6 +32728,7 @@ async function runOneComponent(agent, model, db, sessionId2, component, tokensIn
|
|
|
32581
32728
|
component.props.map((p) => p.name),
|
|
32582
32729
|
component.props.map((p) => p.type)
|
|
32583
32730
|
);
|
|
32731
|
+
const existingComponentsInline = existingContentfulEntities ? JSON.stringify(summarizeForGenerateAgent(existingContentfulEntities, component.name)) : void 0;
|
|
32584
32732
|
const prompt2 = await buildPrompt({
|
|
32585
32733
|
skill: "components",
|
|
32586
32734
|
mode: "autonomous",
|
|
@@ -32590,7 +32738,9 @@ async function runOneComponent(agent, model, db, sessionId2, component, tokensIn
|
|
|
32590
32738
|
outDir: process.cwd(),
|
|
32591
32739
|
componentName: component.name,
|
|
32592
32740
|
componentSourceRefs: [sourceRef],
|
|
32593
|
-
skillPathOverride
|
|
32741
|
+
skillPathOverride,
|
|
32742
|
+
existingComponentsInline,
|
|
32743
|
+
existingTokensInline
|
|
32594
32744
|
});
|
|
32595
32745
|
const maxAttempts = 2;
|
|
32596
32746
|
let lastError = "";
|
|
@@ -32658,7 +32808,7 @@ ${outputBuf}`);
|
|
|
32658
32808
|
renamedSlotsCount: renames.length
|
|
32659
32809
|
};
|
|
32660
32810
|
}
|
|
32661
|
-
async function runAllComponents(agent, model, db, sessionId2, components, tokensInline, tokenMapInline, verbose, noCache, skillPathOverride, promptHash) {
|
|
32811
|
+
async function runAllComponents(agent, model, db, sessionId2, components, tokensInline, tokenMapInline, verbose, noCache, skillPathOverride, promptHash, existingContentfulEntities, existingTokensInline) {
|
|
32662
32812
|
const concurrency = Number(process.env.EDS_GENERATE_CONCURRENCY ?? DEFAULT_COMPONENT_CONCURRENCY);
|
|
32663
32813
|
process.stderr.write(
|
|
32664
32814
|
`Categorizing ${c.bold(String(components.length))} component${components.length === 1 ? "" : "s"}` + c.dim(` (concurrency: ${concurrency})`) + "\n"
|
|
@@ -32682,7 +32832,9 @@ async function runAllComponents(agent, model, db, sessionId2, components, tokens
|
|
|
32682
32832
|
verbose,
|
|
32683
32833
|
noCache,
|
|
32684
32834
|
skillPathOverride,
|
|
32685
|
-
promptHash
|
|
32835
|
+
promptHash,
|
|
32836
|
+
existingContentfulEntities,
|
|
32837
|
+
existingTokensInline
|
|
32686
32838
|
);
|
|
32687
32839
|
completed += 1;
|
|
32688
32840
|
process.stderr.write(`${formatGenerateProgressLine(completed, components.length, results[i].componentName)}
|
|
@@ -32720,7 +32872,7 @@ async function loadAcceptedNames(sessionId2) {
|
|
|
32720
32872
|
try {
|
|
32721
32873
|
const artifactsRoot = getRefineArtifactsRoot();
|
|
32722
32874
|
const paths = await getRefineSessionPaths(sessionId2, artifactsRoot);
|
|
32723
|
-
const raw = await
|
|
32875
|
+
const raw = await readFile19(paths.statePath, "utf8");
|
|
32724
32876
|
const snapshot = JSON.parse(raw);
|
|
32725
32877
|
const accepted = snapshot.components.filter((c2) => c2.status === "accepted").map((c2) => c2.name);
|
|
32726
32878
|
if (accepted.length === 0) return null;
|
|
@@ -32766,6 +32918,19 @@ async function runGenerateSkill(skill, opts, verbose = false) {
|
|
|
32766
32918
|
readFileInline(opts.tokens),
|
|
32767
32919
|
readFileInline(opts.tokenMap)
|
|
32768
32920
|
]);
|
|
32921
|
+
let existingContentfulEntities;
|
|
32922
|
+
let existingTokensInline;
|
|
32923
|
+
if (opts.existingEntitiesPath) {
|
|
32924
|
+
existingContentfulEntities = await readExistingContentfulEntitiesFromSession(resolve17(opts.existingEntitiesPath));
|
|
32925
|
+
if (existingContentfulEntities) {
|
|
32926
|
+
existingTokensInline = JSON.stringify(summarizeForMapTokens(existingContentfulEntities));
|
|
32927
|
+
} else {
|
|
32928
|
+
process.stderr.write(
|
|
32929
|
+
`warn: --existing-entities-path ${opts.existingEntitiesPath} could not be read as JSON \u2014 proceeding without space-context enrichment
|
|
32930
|
+
`
|
|
32931
|
+
);
|
|
32932
|
+
}
|
|
32933
|
+
}
|
|
32769
32934
|
let sessionId2;
|
|
32770
32935
|
let allComponents;
|
|
32771
32936
|
if (skill === "components") {
|
|
@@ -32826,6 +32991,7 @@ async function runGenerateSkill(skill, opts, verbose = false) {
|
|
|
32826
32991
|
sampleComponent.props.map((p) => p.name),
|
|
32827
32992
|
sampleComponent.props.map((p) => p.type)
|
|
32828
32993
|
) : void 0;
|
|
32994
|
+
const dryRunExistingComponentsInline = skill === "components" && existingContentfulEntities && sampleComponent ? JSON.stringify(summarizeForGenerateAgent(existingContentfulEntities, sampleComponent.name)) : void 0;
|
|
32829
32995
|
const prompt2 = await buildPrompt({
|
|
32830
32996
|
skill,
|
|
32831
32997
|
mode: "autonomous",
|
|
@@ -32836,7 +33002,9 @@ async function runGenerateSkill(skill, opts, verbose = false) {
|
|
|
32836
33002
|
tokenMapInline,
|
|
32837
33003
|
outDir: process.cwd(),
|
|
32838
33004
|
componentSourceRefs: sampleSourceRef ? [sampleSourceRef] : void 0,
|
|
32839
|
-
skillPathOverride: generatePromptPath
|
|
33005
|
+
skillPathOverride: generatePromptPath,
|
|
33006
|
+
existingComponentsInline: dryRunExistingComponentsInline,
|
|
33007
|
+
existingTokensInline: skill === "components" ? existingTokensInline : void 0
|
|
32840
33008
|
});
|
|
32841
33009
|
process.stdout.write(prompt2 + "\n");
|
|
32842
33010
|
await exitWithAnalytics(0);
|
|
@@ -32854,7 +33022,15 @@ async function runGenerateSkill(skill, opts, verbose = false) {
|
|
|
32854
33022
|
const db = openPipelineDb();
|
|
32855
33023
|
let componentResults;
|
|
32856
33024
|
try {
|
|
32857
|
-
const
|
|
33025
|
+
const existingContentfulEntitiesHashInputs = [];
|
|
33026
|
+
if (existingTokensInline) existingContentfulEntitiesHashInputs.push(hashContent(existingTokensInline));
|
|
33027
|
+
const promptHash = await hashPromptForSkill(
|
|
33028
|
+
"components",
|
|
33029
|
+
agent,
|
|
33030
|
+
model,
|
|
33031
|
+
generatePromptPath,
|
|
33032
|
+
existingContentfulEntitiesHashInputs
|
|
33033
|
+
);
|
|
32858
33034
|
componentResults = await runAllComponents(
|
|
32859
33035
|
agent,
|
|
32860
33036
|
model,
|
|
@@ -32866,7 +33042,9 @@ async function runGenerateSkill(skill, opts, verbose = false) {
|
|
|
32866
33042
|
verbose,
|
|
32867
33043
|
opts.cache === false || process.env.EDS_NO_CACHE === "1",
|
|
32868
33044
|
generatePromptPath,
|
|
32869
|
-
promptHash
|
|
33045
|
+
promptHash,
|
|
33046
|
+
existingContentfulEntities,
|
|
33047
|
+
existingTokensInline
|
|
32870
33048
|
);
|
|
32871
33049
|
} finally {
|
|
32872
33050
|
db.close();
|
|
@@ -33043,6 +33221,9 @@ function registerGenerateCommand(program) {
|
|
|
33043
33221
|
const componentsCmd = generate.command("components").description("Invoke a coding agent to produce components.json from raw analysis output").option("--session <id>", "Session ID from analyze extract (defaults to most recent)").option("--tokens <path>", "Path to tokens.json for token-linked prop resolution").option("--token-map <path>", "Path to token-name-map.json sidecar").option(
|
|
33044
33222
|
"--generate-prompt-path <path>",
|
|
33045
33223
|
"Path to a custom .md skill prompt for components generation (bypasses bundled prompt invariants)"
|
|
33224
|
+
).option(
|
|
33225
|
+
"--existing-entities-path <path>",
|
|
33226
|
+
"Path to the .existing-entities.json file written by the orchestrator when CMA credentials are supplied. When present, per-component prompts include a summary of the target space so classifications can align to existing prop names/tokens. Missing/malformed files are treated as no-op."
|
|
33046
33227
|
);
|
|
33047
33228
|
addAgentFlags(componentsCmd).action(async (opts) => {
|
|
33048
33229
|
await runGenerateSkill("components", opts, opts.verbose ?? false);
|
|
@@ -33489,9 +33670,9 @@ ${"\u2500".repeat(60)}
|
|
|
33489
33670
|
`);
|
|
33490
33671
|
}
|
|
33491
33672
|
process.stdout.write("\nDelete these sessions? (y/N) ");
|
|
33492
|
-
const answer = await new Promise((
|
|
33673
|
+
const answer = await new Promise((resolve28) => {
|
|
33493
33674
|
process.stdin.setEncoding("utf8");
|
|
33494
|
-
process.stdin.once("data", (chunk) =>
|
|
33675
|
+
process.stdin.once("data", (chunk) => resolve28(String(chunk).trim().toLowerCase()));
|
|
33495
33676
|
});
|
|
33496
33677
|
if (answer !== "y") {
|
|
33497
33678
|
db.close();
|
|
@@ -33526,7 +33707,7 @@ import { access as access7, mkdir as mkdir4, stat as stat4, writeFile as writeFi
|
|
|
33526
33707
|
import { basename as basename5, resolve as resolve19 } from "node:path";
|
|
33527
33708
|
|
|
33528
33709
|
// packages/experience-design-system-cli/src/print/validate/validators/cdf-validator.ts
|
|
33529
|
-
import { readFile as
|
|
33710
|
+
import { readFile as readFile20 } from "node:fs/promises";
|
|
33530
33711
|
import { validateCDF as validateCDF2 } from "@contentful/experience-design-system-types";
|
|
33531
33712
|
function extractValue(input, path) {
|
|
33532
33713
|
if (path === "/") return void 0;
|
|
@@ -33585,7 +33766,7 @@ function rewriteDiagnostic(error, input) {
|
|
|
33585
33766
|
async function validateCDFFile(filePath) {
|
|
33586
33767
|
let content;
|
|
33587
33768
|
try {
|
|
33588
|
-
content = await
|
|
33769
|
+
content = await readFile20(filePath, "utf-8");
|
|
33589
33770
|
} catch (err) {
|
|
33590
33771
|
return {
|
|
33591
33772
|
valid: false,
|
|
@@ -33620,7 +33801,7 @@ async function validateCDFFile(filePath) {
|
|
|
33620
33801
|
}
|
|
33621
33802
|
|
|
33622
33803
|
// packages/experience-design-system-cli/src/print/validate/validators/dtcg-validator.ts
|
|
33623
|
-
import { readFile as
|
|
33804
|
+
import { readFile as readFile21 } from "node:fs/promises";
|
|
33624
33805
|
import { DESIGN_TOKEN_TYPES } from "@contentful/experience-design-system-types";
|
|
33625
33806
|
function walkDTCG(obj, path, diagnostics, counts) {
|
|
33626
33807
|
for (const [key, value] of Object.entries(obj)) {
|
|
@@ -33665,7 +33846,7 @@ function walkDTCG(obj, path, diagnostics, counts) {
|
|
|
33665
33846
|
async function validateDTCGTokenFile(filePath) {
|
|
33666
33847
|
let content;
|
|
33667
33848
|
try {
|
|
33668
|
-
content = await
|
|
33849
|
+
content = await readFile21(filePath, "utf-8");
|
|
33669
33850
|
} catch (err) {
|
|
33670
33851
|
return {
|
|
33671
33852
|
valid: false,
|
|
@@ -33998,7 +34179,8 @@ init_db();
|
|
|
33998
34179
|
init_cache_keys();
|
|
33999
34180
|
import { createElement as createElement6 } from "react";
|
|
34000
34181
|
import { render as render6 } from "ink";
|
|
34001
|
-
import { readFile as
|
|
34182
|
+
import { readFile as readFile22 } from "node:fs/promises";
|
|
34183
|
+
import { resolve as resolve20 } from "node:path";
|
|
34002
34184
|
|
|
34003
34185
|
// packages/experience-design-system-cli/src/map-tokens/apply.ts
|
|
34004
34186
|
init_db();
|
|
@@ -34246,7 +34428,7 @@ async function runMapTokens(opts) {
|
|
|
34246
34428
|
const knownTokenPaths = new Set(tokenLeaves.map((t) => t.path));
|
|
34247
34429
|
const tokenMapDiagnostics = [];
|
|
34248
34430
|
if (opts.tokenMap) {
|
|
34249
|
-
const fileMappings = JSON.parse(await
|
|
34431
|
+
const fileMappings = JSON.parse(await readFile22(opts.tokenMap, "utf8"));
|
|
34250
34432
|
const validMappings = {};
|
|
34251
34433
|
for (const [rawName, path] of Object.entries(fileMappings)) {
|
|
34252
34434
|
if (knownTokenPaths.has(path)) {
|
|
@@ -34321,6 +34503,20 @@ ${defaultDiagnostics.map((diagnostic) => ` ${diagnostic}`).join("\n")}
|
|
|
34321
34503
|
const generatedCdf = Object.fromEntries(cdfEntries.map((c2) => [c2.key, c2.entry]));
|
|
34322
34504
|
const tokenTree = rebuildDTCGTree(groups, tokens);
|
|
34323
34505
|
const componentSourceRefs = await loadComponentSourceRefs(db, sessionId2);
|
|
34506
|
+
let existingTokensInline;
|
|
34507
|
+
if (opts.existingEntitiesPath) {
|
|
34508
|
+
const existingContentfulEntities = await readExistingContentfulEntitiesFromSession(
|
|
34509
|
+
resolve20(opts.existingEntitiesPath)
|
|
34510
|
+
);
|
|
34511
|
+
if (existingContentfulEntities) {
|
|
34512
|
+
existingTokensInline = JSON.stringify(summarizeForMapTokens(existingContentfulEntities));
|
|
34513
|
+
} else {
|
|
34514
|
+
process.stderr.write(
|
|
34515
|
+
`warn: --existing-entities-path ${opts.existingEntitiesPath} could not be read as JSON \u2014 proceeding without space-context enrichment
|
|
34516
|
+
`
|
|
34517
|
+
);
|
|
34518
|
+
}
|
|
34519
|
+
}
|
|
34324
34520
|
if (opts.printPrompt) {
|
|
34325
34521
|
const prompt3 = await buildPrompt({
|
|
34326
34522
|
skill: "map-tokens",
|
|
@@ -34328,7 +34524,8 @@ ${defaultDiagnostics.map((diagnostic) => ` ${diagnostic}`).join("\n")}
|
|
|
34328
34524
|
generatedCdf,
|
|
34329
34525
|
tokenTree,
|
|
34330
34526
|
componentSourceRefs,
|
|
34331
|
-
outDir: process.cwd()
|
|
34527
|
+
outDir: process.cwd(),
|
|
34528
|
+
existingTokensInline
|
|
34332
34529
|
});
|
|
34333
34530
|
process.stdout.write(prompt3 + "\n");
|
|
34334
34531
|
await exitWithAnalytics(0);
|
|
@@ -34346,7 +34543,13 @@ ${defaultDiagnostics.map((diagnostic) => ` ${diagnostic}`).join("\n")}
|
|
|
34346
34543
|
}
|
|
34347
34544
|
const agent = configuredAgent;
|
|
34348
34545
|
const noCache = opts.cache === false || process.env.EDS_NO_CACHE === "1";
|
|
34349
|
-
const promptHash = await hashPromptForSkill(
|
|
34546
|
+
const promptHash = await hashPromptForSkill(
|
|
34547
|
+
"map-tokens",
|
|
34548
|
+
agent,
|
|
34549
|
+
model,
|
|
34550
|
+
void 0,
|
|
34551
|
+
existingTokensInline ? [hashContent(existingTokensInline)] : []
|
|
34552
|
+
);
|
|
34350
34553
|
const inputHash = computeMapTokensInputHash(db, sessionId2, componentSourceRefs);
|
|
34351
34554
|
if (!noCache) {
|
|
34352
34555
|
const cached = lookupCache(db, inputHash, "token_mapping", "__map_tokens__", promptHash);
|
|
@@ -34373,7 +34576,8 @@ Install it, choose another agent with --agent, or use --print-prompt to run the
|
|
|
34373
34576
|
generatedCdf,
|
|
34374
34577
|
tokenTree,
|
|
34375
34578
|
componentSourceRefs,
|
|
34376
|
-
outDir: process.cwd()
|
|
34579
|
+
outDir: process.cwd(),
|
|
34580
|
+
existingTokensInline
|
|
34377
34581
|
});
|
|
34378
34582
|
const invoker3 = createLocalCliAgentInvoker();
|
|
34379
34583
|
const result = await invoker3.invoke({ agent, model, prompt: prompt2, timeoutMs: DEFAULT_TIMEOUT_MS4 });
|
|
@@ -34400,7 +34604,10 @@ ${warnings.map((w) => ` ${w}`).join("\n")}
|
|
|
34400
34604
|
}
|
|
34401
34605
|
function registerMapTokensCommand(program) {
|
|
34402
34606
|
const map = program.command("map").description("Suggest token restrictions for generated design-token props");
|
|
34403
|
-
const tokensCmd = map.command("tokens").description("Invoke a coding agent to suggest $token.allowed for design-category token props").option("--session <id>", "Session ID from generate components (defaults to most recent)").option("--print-prompt", "Print the prompt without invoking the agent").option("--skip-agent", "Resolve token defaults without agentic $token.allowed inference").option("--no-cache", "Bypass the map-tokens cache and force a re-run").option("--token-map <path>", "Path to token-name-map.json sidecar")
|
|
34607
|
+
const tokensCmd = map.command("tokens").description("Invoke a coding agent to suggest $token.allowed for design-category token props").option("--session <id>", "Session ID from generate components (defaults to most recent)").option("--print-prompt", "Print the prompt without invoking the agent").option("--skip-agent", "Resolve token defaults without agentic $token.allowed inference").option("--no-cache", "Bypass the map-tokens cache and force a re-run").option("--token-map <path>", "Path to token-name-map.json sidecar").option(
|
|
34608
|
+
"--existing-entities-path <path>",
|
|
34609
|
+
"Path to the .existing-entities.json file written by the orchestrator when CMA credentials are supplied. When present, the agent gets a list of the space's existing design tokens so it can prefer binding to them. Missing/malformed files are treated as no-op."
|
|
34610
|
+
);
|
|
34404
34611
|
addAgentModelOptions(tokensCmd).action(async (opts) => {
|
|
34405
34612
|
await runMapTokens(opts);
|
|
34406
34613
|
});
|
|
@@ -34409,7 +34616,7 @@ function registerMapTokensCommand(program) {
|
|
|
34409
34616
|
// packages/experience-design-system-cli/src/import/command.ts
|
|
34410
34617
|
init_src();
|
|
34411
34618
|
init_path_utils();
|
|
34412
|
-
import { resolve as
|
|
34619
|
+
import { resolve as resolve26, join as join25 } from "node:path";
|
|
34413
34620
|
|
|
34414
34621
|
// packages/experience-design-system-cli/src/import/orchestrator.ts
|
|
34415
34622
|
init_db();
|
|
@@ -34417,22 +34624,22 @@ init_command();
|
|
|
34417
34624
|
init_manifest();
|
|
34418
34625
|
init_api_client();
|
|
34419
34626
|
import { mkdir as mkdir5, writeFile as writeFile5 } from "node:fs/promises";
|
|
34420
|
-
import { join as join18, resolve as
|
|
34627
|
+
import { join as join18, resolve as resolve22 } from "node:path";
|
|
34421
34628
|
import { execFile as execFile2 } from "node:child_process";
|
|
34422
34629
|
|
|
34423
|
-
// packages/experience-design-system-cli/src/helpers/fetch-existing-entities.ts
|
|
34630
|
+
// packages/experience-design-system-cli/src/helpers/fetch-existing-contentful-entities.ts
|
|
34424
34631
|
import { fetchAll } from "contentful-management";
|
|
34425
|
-
async function
|
|
34632
|
+
async function fetchExistingContentfulEntitiesFromContentful(client2, params) {
|
|
34426
34633
|
const scope = { spaceId: params.spaceId, environmentId: params.environmentId, query: {} };
|
|
34427
34634
|
const components = await fetchAll(client2.component.getMany, scope);
|
|
34428
34635
|
const tokens = await fetchAll(client2.designToken.getMany, scope);
|
|
34429
34636
|
return { components, tokens };
|
|
34430
34637
|
}
|
|
34431
34638
|
|
|
34432
|
-
// packages/experience-design-system-cli/src/helpers/
|
|
34639
|
+
// packages/experience-design-system-cli/src/helpers/build-contentful-management-client.ts
|
|
34433
34640
|
init_host_utils();
|
|
34434
34641
|
import { createClient as createClient2 } from "contentful-management";
|
|
34435
|
-
function
|
|
34642
|
+
function buildContentfulManagementClient(opts) {
|
|
34436
34643
|
return createClient2(
|
|
34437
34644
|
{
|
|
34438
34645
|
accessToken: opts.cmaToken,
|
|
@@ -34532,8 +34739,8 @@ function buildPushStepResult(args) {
|
|
|
34532
34739
|
};
|
|
34533
34740
|
}
|
|
34534
34741
|
async function runPipeline(opts, progressWriter, cliPathOverride) {
|
|
34535
|
-
const projectRoot =
|
|
34536
|
-
const outDir =
|
|
34742
|
+
const projectRoot = resolve22(opts.project);
|
|
34743
|
+
const outDir = resolve22(opts.out);
|
|
34537
34744
|
const componentsPath = join18(outDir, "components.json");
|
|
34538
34745
|
const cliPath = cliPathOverride ?? findCliPath();
|
|
34539
34746
|
const db = openPipelineDb();
|
|
@@ -34555,19 +34762,14 @@ async function runPipeline(opts, progressWriter, cliPathOverride) {
|
|
|
34555
34762
|
await mkdir5(outDir, { recursive: true });
|
|
34556
34763
|
const steps = [];
|
|
34557
34764
|
let stepNum = 0;
|
|
34558
|
-
const
|
|
34559
|
-
const
|
|
34560
|
-
const totalSteps = 5 + (opts.print ? 1 : 0) + (canFetchSpaceContext ? 1 : 0);
|
|
34765
|
+
const canFetchExistingContentfulEntities = !!opts.spaceId && !!opts.environmentId && !!opts.cmaToken;
|
|
34766
|
+
const totalSteps = 5 + (opts.print ? 1 : 0) + (canFetchExistingContentfulEntities ? 1 : 0);
|
|
34561
34767
|
function stepLabel(name) {
|
|
34562
34768
|
stepNum++;
|
|
34563
34769
|
return ` Step ${stepNum}/${totalSteps} ${name} `;
|
|
34564
34770
|
}
|
|
34565
|
-
|
|
34566
|
-
|
|
34567
|
-
" Note: --with-space-context requires --space-id, --environment-id, and --cma-token; skipping context fetch."
|
|
34568
|
-
);
|
|
34569
|
-
}
|
|
34570
|
-
if (canFetchSpaceContext) {
|
|
34771
|
+
let existingEntitiesPath;
|
|
34772
|
+
if (canFetchExistingContentfulEntities) {
|
|
34571
34773
|
const fetchLabel = stepLabel("Fetching existing components + design tokens");
|
|
34572
34774
|
const fetchStepId = createStep(db, sessionId2, "fetch existing entities", {
|
|
34573
34775
|
spaceId: opts.spaceId,
|
|
@@ -34575,16 +34777,19 @@ async function runPipeline(opts, progressWriter, cliPathOverride) {
|
|
|
34575
34777
|
});
|
|
34576
34778
|
const t0 = Date.now();
|
|
34577
34779
|
try {
|
|
34578
|
-
const
|
|
34780
|
+
const contentfulManagementClient = buildContentfulManagementClient({
|
|
34579
34781
|
cmaToken: opts.cmaToken,
|
|
34580
34782
|
...opts.host ? { host: opts.host } : {}
|
|
34581
34783
|
});
|
|
34582
|
-
const existingComponentsAndTokens = await
|
|
34583
|
-
|
|
34584
|
-
|
|
34585
|
-
|
|
34784
|
+
const existingComponentsAndTokens = await fetchExistingContentfulEntitiesFromContentful(
|
|
34785
|
+
contentfulManagementClient,
|
|
34786
|
+
{
|
|
34787
|
+
spaceId: opts.spaceId,
|
|
34788
|
+
environmentId: opts.environmentId
|
|
34789
|
+
}
|
|
34790
|
+
);
|
|
34586
34791
|
const fetchDurationMs = Date.now() - t0;
|
|
34587
|
-
|
|
34792
|
+
existingEntitiesPath = join18(outDir, ".existing-entities.json");
|
|
34588
34793
|
await writeFile5(existingEntitiesPath, JSON.stringify(existingComponentsAndTokens, null, 2), "utf8");
|
|
34589
34794
|
updateStep(db, fetchStepId, "complete", {
|
|
34590
34795
|
components: String(existingComponentsAndTokens.components.length),
|
|
@@ -34701,6 +34906,7 @@ async function runPipeline(opts, progressWriter, cliPathOverride) {
|
|
|
34701
34906
|
if (opts.excludeInvalid) editArgs.push("--exclude-invalid");
|
|
34702
34907
|
if (opts.noCache) editArgs.push("--no-cache");
|
|
34703
34908
|
if (opts.selectPromptPath) editArgs.push("--select-prompt-path", opts.selectPromptPath);
|
|
34909
|
+
if (existingEntitiesPath) editArgs.push("--existing-entities-path", existingEntitiesPath);
|
|
34704
34910
|
} else {
|
|
34705
34911
|
editArgs = ["analyze", "select", "--session", extractSessionId];
|
|
34706
34912
|
if (opts.select && opts.select.length > 0) {
|
|
@@ -34763,6 +34969,7 @@ async function runPipeline(opts, progressWriter, cliPathOverride) {
|
|
|
34763
34969
|
if (extractSessionId) generateArgs.push("--session", extractSessionId);
|
|
34764
34970
|
if (opts.dryRun) generateArgs.push("--dry-run");
|
|
34765
34971
|
if (opts.verbose) generateArgs.push("--verbose");
|
|
34972
|
+
if (existingEntitiesPath) generateArgs.push("--existing-entities-path", existingEntitiesPath);
|
|
34766
34973
|
const stepId = createStep(db, sessionId2, "generate components", {
|
|
34767
34974
|
extractSession: extractSessionId ?? ""
|
|
34768
34975
|
});
|
|
@@ -34817,6 +35024,7 @@ async function runPipeline(opts, progressWriter, cliPathOverride) {
|
|
|
34817
35024
|
if (opts.model) mapTokensArgs.push("--model", opts.model);
|
|
34818
35025
|
if (opts.noCache) mapTokensArgs.push("--no-cache");
|
|
34819
35026
|
if (opts.skipMapTokens) mapTokensArgs.push("--skip-agent");
|
|
35027
|
+
if (existingEntitiesPath) mapTokensArgs.push("--existing-entities-path", existingEntitiesPath);
|
|
34820
35028
|
const mapTokensStepId = createStep(db, sessionId2, "map tokens", {
|
|
34821
35029
|
extractSession: extractSessionId,
|
|
34822
35030
|
skipAgent: String(opts.skipMapTokens === true)
|
|
@@ -35178,7 +35386,7 @@ init_host_utils();
|
|
|
35178
35386
|
// packages/experience-design-system-cli/src/runs/replay-helpers.ts
|
|
35179
35387
|
init_resolve_run_target();
|
|
35180
35388
|
init_store();
|
|
35181
|
-
import { resolve as
|
|
35389
|
+
import { resolve as resolve25 } from "node:path";
|
|
35182
35390
|
|
|
35183
35391
|
// packages/experience-design-system-cli/src/runs/push-helpers.ts
|
|
35184
35392
|
init_cli_path();
|
|
@@ -35368,7 +35576,7 @@ async function modifyRun(opts) {
|
|
|
35368
35576
|
entryStep: "final-review",
|
|
35369
35577
|
saveMode,
|
|
35370
35578
|
...run.compositionMode ? { compositionMode: run.compositionMode } : {},
|
|
35371
|
-
...opts.outDir ? { outDirOverride:
|
|
35579
|
+
...opts.outDir ? { outDirOverride: resolve25(opts.outDir) } : {},
|
|
35372
35580
|
...mergedSpaceId ? { initialSpaceId: mergedSpaceId } : {},
|
|
35373
35581
|
...mergedEnvironmentId ? { initialEnvironmentId: mergedEnvironmentId } : {},
|
|
35374
35582
|
...mergedHost ? { initialHost: mergedHost } : {},
|
|
@@ -35445,7 +35653,7 @@ function resolvePromptFlags(flags) {
|
|
|
35445
35653
|
|
|
35446
35654
|
// packages/experience-design-system-cli/src/runs/run-picker-mount.ts
|
|
35447
35655
|
init_store();
|
|
35448
|
-
import { readFile as
|
|
35656
|
+
import { readFile as readFile27 } from "node:fs/promises";
|
|
35449
35657
|
function migrateRecord2(rec) {
|
|
35450
35658
|
return {
|
|
35451
35659
|
...rec,
|
|
@@ -35468,7 +35676,7 @@ async function shouldShowRunPicker(input) {
|
|
|
35468
35676
|
const path = input.runsJsonPath ?? runsFilePath();
|
|
35469
35677
|
let raw;
|
|
35470
35678
|
try {
|
|
35471
|
-
raw = await
|
|
35679
|
+
raw = await readFile27(path, "utf8");
|
|
35472
35680
|
} catch {
|
|
35473
35681
|
return { shouldShow: false, runs: [] };
|
|
35474
35682
|
}
|
|
@@ -35573,10 +35781,7 @@ function registerImportCommand(program) {
|
|
|
35573
35781
|
"Override a stage prompt (repeatable). value is a file path or literal text, e.g. --prompt composition=./p.md",
|
|
35574
35782
|
(v, acc) => [...acc, v],
|
|
35575
35783
|
[]
|
|
35576
|
-
).option("--auto-reject-cycles", "Automatically reject components involved in slot cycles and retry").option(
|
|
35577
|
-
"--with-space-context",
|
|
35578
|
-
"Fetch existing Components + DesignTokens from the target space+env and persist them under <out>/.existing-entities.json for future agent-context enrichment. Requires --space-id, --environment-id, and --cma-token."
|
|
35579
|
-
).option("--auto-filter", "Force the AI auto-filter ON (overrides the credentials.json autoFilter preference)").option(
|
|
35784
|
+
).option("--auto-reject-cycles", "Automatically reject components involved in slot cycles and retry").option("--auto-filter", "Force the AI auto-filter ON (overrides the credentials.json autoFilter preference)").option(
|
|
35580
35785
|
"--no-auto-filter",
|
|
35581
35786
|
"Skip the automatic AI pre-filter; jump straight to manual scope-gate (overrides the credentials.json autoFilter preference; no-op when paired with --auto-accept-scope)"
|
|
35582
35787
|
).option(
|
|
@@ -35844,7 +36049,7 @@ function registerImportCommand(program) {
|
|
|
35844
36049
|
livePreview: opts.livePreview !== false,
|
|
35845
36050
|
noPush: noPushRequested,
|
|
35846
36051
|
noSave: opts.save === false,
|
|
35847
|
-
...opts.outDir ? { outDirOverride:
|
|
36052
|
+
...opts.outDir ? { outDirOverride: resolve26(opts.outDir) } : {},
|
|
35848
36053
|
...opts.onConflict ? { onConflictMode: opts.onConflict } : {},
|
|
35849
36054
|
selectPromptPath: opts.selectPromptPath ?? creds.selectPromptPath,
|
|
35850
36055
|
generatePromptPath: opts.generatePromptPath ?? creds.generatePromptPath,
|
|
@@ -35885,7 +36090,7 @@ function registerImportCommand(program) {
|
|
|
35885
36090
|
return;
|
|
35886
36091
|
}
|
|
35887
36092
|
const projectRoot = normalizePath(opts.project);
|
|
35888
|
-
const outDir = opts.out ?
|
|
36093
|
+
const outDir = opts.out ? resolve26(opts.out) : join25(projectRoot, ".contentful");
|
|
35889
36094
|
const headlessCreds = await readExperiencesCredentials();
|
|
35890
36095
|
const headlessAgent = resolveAgent(opts.agent, headlessCreds.agent);
|
|
35891
36096
|
const headlessModel = resolveModel(opts.model, headlessCreds.agentModel);
|
|
@@ -35923,7 +36128,6 @@ function registerImportCommand(program) {
|
|
|
35923
36128
|
dryRun: dryRunForward,
|
|
35924
36129
|
selectPromptPath: opts.selectPromptPath,
|
|
35925
36130
|
autoRejectCycles: opts.autoRejectCycles ?? false,
|
|
35926
|
-
withSpaceContext: opts.withSpaceContext ?? false,
|
|
35927
36131
|
allowDeletions: opts.allowDeletions ?? false,
|
|
35928
36132
|
compositionMode: headlessCompositionMode,
|
|
35929
36133
|
...opts.compositionMap ? { compositionMap: opts.compositionMap } : {},
|
|
@@ -35948,7 +36152,7 @@ function registerImportCommand(program) {
|
|
|
35948
36152
|
// packages/experience-design-system-cli/src/setup/command.ts
|
|
35949
36153
|
init_credentials_store();
|
|
35950
36154
|
import { execFile as execFile5, spawn as spawn5 } from "node:child_process";
|
|
35951
|
-
import { appendFile as appendFile2, readFile as
|
|
36155
|
+
import { appendFile as appendFile2, readFile as readFile28, access as access10 } from "node:fs/promises";
|
|
35952
36156
|
import { join as join26 } from "node:path";
|
|
35953
36157
|
import { homedir as homedir9 } from "node:os";
|
|
35954
36158
|
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
@@ -36027,10 +36231,10 @@ function prompt(question) {
|
|
|
36027
36231
|
return Promise.resolve("");
|
|
36028
36232
|
}
|
|
36029
36233
|
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
36030
|
-
return new Promise((
|
|
36234
|
+
return new Promise((resolve28) => {
|
|
36031
36235
|
rl.question(question, (answer) => {
|
|
36032
36236
|
rl.close();
|
|
36033
|
-
|
|
36237
|
+
resolve28(answer.trim());
|
|
36034
36238
|
});
|
|
36035
36239
|
});
|
|
36036
36240
|
}
|
|
@@ -36038,7 +36242,7 @@ function promptSecret(question) {
|
|
|
36038
36242
|
if (!isInteractivePromptSession()) {
|
|
36039
36243
|
return Promise.resolve("");
|
|
36040
36244
|
}
|
|
36041
|
-
return new Promise((
|
|
36245
|
+
return new Promise((resolve28) => {
|
|
36042
36246
|
const rl = createInterface({
|
|
36043
36247
|
input: process.stdin,
|
|
36044
36248
|
output: process.stdout,
|
|
@@ -36065,7 +36269,7 @@ function promptSecret(question) {
|
|
|
36065
36269
|
}
|
|
36066
36270
|
if (!process.stdin.isTTY) process.stdout.write("\n");
|
|
36067
36271
|
process.stdin.resume();
|
|
36068
|
-
|
|
36272
|
+
resolve28(value);
|
|
36069
36273
|
});
|
|
36070
36274
|
});
|
|
36071
36275
|
}
|
|
@@ -36087,7 +36291,7 @@ async function binaryExists(name) {
|
|
|
36087
36291
|
}
|
|
36088
36292
|
}
|
|
36089
36293
|
function runSpawn(cmd, args, opts = {}) {
|
|
36090
|
-
return new Promise((
|
|
36294
|
+
return new Promise((resolve28) => {
|
|
36091
36295
|
const child = spawn5(cmd, args, {
|
|
36092
36296
|
cwd: opts.cwd,
|
|
36093
36297
|
env: opts.env ?? process.env,
|
|
@@ -36099,7 +36303,7 @@ function runSpawn(cmd, args, opts = {}) {
|
|
|
36099
36303
|
child.on("error", (err) => {
|
|
36100
36304
|
if (!settled) {
|
|
36101
36305
|
settled = true;
|
|
36102
|
-
|
|
36306
|
+
resolve28({ exitCode: 1, stdout: "", stderr: err.message });
|
|
36103
36307
|
}
|
|
36104
36308
|
});
|
|
36105
36309
|
child.stdout.on("data", (d) => {
|
|
@@ -36111,7 +36315,7 @@ function runSpawn(cmd, args, opts = {}) {
|
|
|
36111
36315
|
child.on("exit", (code) => {
|
|
36112
36316
|
if (!settled) {
|
|
36113
36317
|
settled = true;
|
|
36114
|
-
|
|
36318
|
+
resolve28({ exitCode: code ?? 1, stdout, stderr });
|
|
36115
36319
|
}
|
|
36116
36320
|
});
|
|
36117
36321
|
});
|
|
@@ -36134,7 +36338,7 @@ async function detectShellProfile() {
|
|
|
36134
36338
|
}
|
|
36135
36339
|
async function profileContains(profilePath, str) {
|
|
36136
36340
|
try {
|
|
36137
|
-
const content = await
|
|
36341
|
+
const content = await readFile28(profilePath, "utf8");
|
|
36138
36342
|
return content.includes(str);
|
|
36139
36343
|
} catch {
|
|
36140
36344
|
return false;
|
|
@@ -37049,7 +37253,7 @@ function registerImportV2Command(program) {
|
|
|
37049
37253
|
}
|
|
37050
37254
|
function registerBuildCommand(program) {
|
|
37051
37255
|
program.command("build").description("Rebuild from source and re-link exo/experiences binaries to this build").action(async () => {
|
|
37052
|
-
const pkgRoot =
|
|
37256
|
+
const pkgRoot = resolve27(dirname14(fileURLToPath5(import.meta.url)), "..", "..");
|
|
37053
37257
|
process.stderr.write("\u2699 Building from source...\n");
|
|
37054
37258
|
const { exitCode } = await runBuild({
|
|
37055
37259
|
spawnFn: () => spawn6("pnpm", ["build"], { cwd: pkgRoot, stdio: "inherit" }),
|