@contentful/experience-design-system-cli 2.32.1-dev-build-b78fe18.0 → 2.32.1-dev-build-71db090.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/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((resolve27) => {
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
- resolve27(result);
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((resolve27) => {
393
+ const binaryExists2 = await new Promise((resolve28) => {
394
394
  if (binary.startsWith("/")) {
395
- import("node:fs/promises").then((fs2) => fs2.access(binary).then(() => resolve27(true), () => resolve27(false)));
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) => resolve27(code === 0));
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((resolve27) => {
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
- resolve27("unauthenticated");
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
- resolve27("unauthenticated");
427
+ resolve28("unauthenticated");
428
428
  return;
429
429
  }
430
430
  try {
431
431
  const status = JSON.parse(stdout);
432
- resolve27(status.loggedIn ? "ok" : "unauthenticated");
432
+ resolve28(status.loggedIn ? "ok" : "unauthenticated");
433
433
  } catch {
434
- resolve27("unauthenticated");
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
- return hashContent(`${promptHash}|${agent}|${model ?? ""}`);
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((resolve27) => setTimeout(resolve27, delayMs));
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((resolve27) => setTimeout(resolve27, baseDelay + jitter));
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 resolve20 } from "node:path";
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 resolve20(p);
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"() {
@@ -16587,9 +16600,74 @@ var init_path_utils = __esm({
16587
16600
  }
16588
16601
  });
16589
16602
 
16603
+ // packages/experience-design-system-cli/src/helpers/build-contentful-management-client.ts
16604
+ import { createClient as createClient2 } from "contentful-management";
16605
+ function buildContentfulManagementClient(opts) {
16606
+ return createClient2(
16607
+ {
16608
+ accessToken: opts.cmaToken,
16609
+ ...opts.host ? { host: toConfiguredHost(opts.host) } : {}
16610
+ },
16611
+ { type: "plain" }
16612
+ );
16613
+ }
16614
+ var init_build_contentful_management_client = __esm({
16615
+ "packages/experience-design-system-cli/src/helpers/build-contentful-management-client.ts"() {
16616
+ "use strict";
16617
+ init_host_utils();
16618
+ }
16619
+ });
16620
+
16621
+ // packages/experience-design-system-cli/src/helpers/fetch-existing-contentful-entities.ts
16622
+ import { fetchAll } from "contentful-management";
16623
+ async function fetchExistingContentfulEntitiesFromContentful(client2, params) {
16624
+ const scope = { spaceId: params.spaceId, environmentId: params.environmentId, query: {} };
16625
+ const components = await fetchAll(client2.component.getMany, scope);
16626
+ const tokens = await fetchAll(client2.designToken.getMany, scope);
16627
+ return { components, tokens };
16628
+ }
16629
+ var init_fetch_existing_contentful_entities = __esm({
16630
+ "packages/experience-design-system-cli/src/helpers/fetch-existing-contentful-entities.ts"() {
16631
+ "use strict";
16632
+ }
16633
+ });
16634
+
16635
+ // packages/experience-design-system-cli/src/helpers/fetch-and-persist-existing-contentful-entities.ts
16636
+ import { writeFile as writeFile5 } from "node:fs/promises";
16637
+ import { join as join18 } from "node:path";
16638
+ async function fetchAndPersistExistingContentfulEntities(params) {
16639
+ const t0 = Date.now();
16640
+ try {
16641
+ const client2 = buildContentfulManagementClient({
16642
+ cmaToken: params.cmaToken,
16643
+ ...params.host ? { host: params.host } : {}
16644
+ });
16645
+ const entities = await fetchExistingContentfulEntitiesFromContentful(client2, {
16646
+ spaceId: params.spaceId,
16647
+ environmentId: params.environmentId
16648
+ });
16649
+ const path = join18(params.outDir, ".existing-entities.json");
16650
+ await writeFile5(path, JSON.stringify(entities, null, 2), "utf8");
16651
+ return { ok: true, path, durationMs: Date.now() - t0, entities };
16652
+ } catch (error) {
16653
+ return {
16654
+ ok: false,
16655
+ durationMs: Date.now() - t0,
16656
+ error: error instanceof Error ? error.message : String(error)
16657
+ };
16658
+ }
16659
+ }
16660
+ var init_fetch_and_persist_existing_contentful_entities = __esm({
16661
+ "packages/experience-design-system-cli/src/helpers/fetch-and-persist-existing-contentful-entities.ts"() {
16662
+ "use strict";
16663
+ init_build_contentful_management_client();
16664
+ init_fetch_existing_contentful_entities();
16665
+ }
16666
+ });
16667
+
16590
16668
  // packages/experience-design-system-cli/src/runs/save-path-resolver.ts
16591
16669
  import { access as access8 } from "node:fs/promises";
16592
- import { join as join19 } from "node:path";
16670
+ import { join as join20 } from "node:path";
16593
16671
  function isConflictMode(value) {
16594
16672
  return CONFLICT_MODES.includes(value);
16595
16673
  }
@@ -16597,7 +16675,7 @@ async function listConflictingFiles(path) {
16597
16675
  const conflicts = [];
16598
16676
  for (const name of SAVE_FILES) {
16599
16677
  try {
16600
- await access8(join19(path, name));
16678
+ await access8(join20(path, name));
16601
16679
  conflicts.push(name);
16602
16680
  } catch {
16603
16681
  }
@@ -16617,7 +16695,7 @@ function buildTimestampedSubdir(base, now = /* @__PURE__ */ new Date()) {
16617
16695
  const hh = pad2(now.getHours());
16618
16696
  const mm = pad2(now.getMinutes());
16619
16697
  const ss = pad2(now.getSeconds());
16620
- return join19(base, `dsi-${y}${m}${d}-${hh}${mm}${ss}`);
16698
+ return join20(base, `dsi-${y}${m}${d}-${hh}${mm}${ss}`);
16621
16699
  }
16622
16700
  async function resolveSavePath(path, options = {}) {
16623
16701
  const conflicts = await listConflictingFiles(path);
@@ -16647,8 +16725,8 @@ var init_save_path_resolver = __esm({
16647
16725
  });
16648
16726
 
16649
16727
  // packages/experience-design-system-cli/src/runs/store.ts
16650
- import { readFile as readFile22, writeFile as writeFile6, mkdir as mkdir6, rename } from "node:fs/promises";
16651
- import { join as join20 } from "node:path";
16728
+ import { readFile as readFile23, writeFile as writeFile6, mkdir as mkdir6, rename } from "node:fs/promises";
16729
+ import { join as join21 } from "node:path";
16652
16730
  import { homedir as homedir7 } from "node:os";
16653
16731
  import { randomBytes as randomBytes2 } from "node:crypto";
16654
16732
  function runsFilePath() {
@@ -16691,7 +16769,7 @@ function migrateRecord(rec) {
16691
16769
  }
16692
16770
  async function readFileMaybe() {
16693
16771
  try {
16694
- const raw = await readFile22(RUNS_PATH, "utf8");
16772
+ const raw = await readFile23(RUNS_PATH, "utf8");
16695
16773
  const parsed = JSON.parse(raw);
16696
16774
  if (!READABLE_VERSIONS.has(parsed.version)) {
16697
16775
  throw new Error(
@@ -16769,8 +16847,8 @@ var init_store = __esm({
16769
16847
  RUNS_FILE_VERSION = 3;
16770
16848
  RUNS_FILE_CAP = 200;
16771
16849
  READABLE_VERSIONS = /* @__PURE__ */ new Set([1, 2, 3]);
16772
- RUNS_DIR = join20(homedir7(), ".config", "experiences");
16773
- RUNS_PATH = join20(RUNS_DIR, "runs.json");
16850
+ RUNS_DIR = join21(homedir7(), ".config", "experiences");
16851
+ RUNS_PATH = join21(RUNS_DIR, "runs.json");
16774
16852
  CROCKFORD = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";
16775
16853
  }
16776
16854
  });
@@ -16834,7 +16912,7 @@ var init_run_teaser = __esm({
16834
16912
  import { useState as useState9, useEffect as useEffect3 } from "react";
16835
16913
  import { Box as Box20, Text as Text20 } from "ink";
16836
16914
  import { readdirSync as readdirSync3 } from "node:fs";
16837
- import { dirname as dirname13, basename as basename6, join as join21 } from "node:path";
16915
+ import { dirname as dirname13, basename as basename6, join as join22 } from "node:path";
16838
16916
  import { jsx as jsx20, jsxs as jsxs20 } from "react/jsx-runtime";
16839
16917
  function autocomplete(partial) {
16840
16918
  if (!partial) return null;
@@ -16849,13 +16927,13 @@ function autocomplete(partial) {
16849
16927
  }
16850
16928
  const matches = entries.filter((e) => e.startsWith(base));
16851
16929
  if (matches.length === 0) return null;
16852
- if (matches.length === 1) return join21(dir, matches[0]);
16930
+ if (matches.length === 1) return join22(dir, matches[0]);
16853
16931
  let prefix = matches[0];
16854
16932
  for (const m of matches) {
16855
16933
  while (!m.startsWith(prefix)) prefix = prefix.slice(0, -1);
16856
16934
  if (!prefix) break;
16857
16935
  }
16858
- return prefix.length > base.length ? join21(dir, prefix) : null;
16936
+ return prefix.length > base.length ? join22(dir, prefix) : null;
16859
16937
  }
16860
16938
  function PathPrompt({
16861
16939
  defaultPath,
@@ -17287,8 +17365,8 @@ var init_save_conflict = __esm({
17287
17365
 
17288
17366
  // packages/experience-design-system-cli/src/runs/fingerprint.ts
17289
17367
  import { createHash as createHash4 } from "node:crypto";
17290
- import { readFile as readFile23, stat as stat5 } from "node:fs/promises";
17291
- import { resolve as resolve22 } from "node:path";
17368
+ import { readFile as readFile24, stat as stat5 } from "node:fs/promises";
17369
+ import { resolve as resolve23 } from "node:path";
17292
17370
  function rowField(row, key) {
17293
17371
  const v = row[key];
17294
17372
  return typeof v === "string" ? v : null;
@@ -17304,7 +17382,7 @@ async function buildSourceFingerprint(opts) {
17304
17382
  const sourcePath = rowField(row, "source_path");
17305
17383
  const name = rowField(row, "name");
17306
17384
  if (!sourcePath) continue;
17307
- const abs = resolve22(sourcePath);
17385
+ const abs = resolve23(sourcePath);
17308
17386
  if (seen.has(abs)) continue;
17309
17387
  seen.add(abs);
17310
17388
  try {
@@ -17319,10 +17397,10 @@ async function buildSourceFingerprint(opts) {
17319
17397
  let rawTokensMtime = null;
17320
17398
  let rawTokensContentHash = null;
17321
17399
  if (opts.rawTokensPath) {
17322
- const abs = resolve22(opts.rawTokensPath);
17400
+ const abs = resolve23(opts.rawTokensPath);
17323
17401
  rawTokensPath = abs;
17324
17402
  try {
17325
- const [st, buf] = await Promise.all([stat5(abs), readFile23(abs)]);
17403
+ const [st, buf] = await Promise.all([stat5(abs), readFile24(abs)]);
17326
17404
  rawTokensMtime = st.mtime.toISOString();
17327
17405
  rawTokensContentHash = sha256Hex(buf);
17328
17406
  } catch {
@@ -17453,7 +17531,7 @@ var init_WelcomeStep = __esm({
17453
17531
  import { useState as useState13, useEffect as useEffect5 } from "react";
17454
17532
  import { Box as Box25, Text as Text25 } from "ink";
17455
17533
  import { promises as fs } from "node:fs";
17456
- import { join as join22 } from "node:path";
17534
+ import { join as join23 } from "node:path";
17457
17535
  import { jsx as jsx25, jsxs as jsxs25 } from "react/jsx-runtime";
17458
17536
  async function countFiles(dir) {
17459
17537
  const counts = {
@@ -17477,7 +17555,7 @@ async function countFiles(dir) {
17477
17555
  await Promise.all(
17478
17556
  entries.map(async (entry) => {
17479
17557
  if (IGNORE_DIRS.has(entry)) return;
17480
- const full = join22(current, entry);
17558
+ const full = join23(current, entry);
17481
17559
  let stat8;
17482
17560
  try {
17483
17561
  stat8 = await fs.stat(full);
@@ -17821,7 +17899,7 @@ __export(CredentialsStep_exports, {
17821
17899
  });
17822
17900
  import { useState as useState15, useEffect as useEffect7, useRef as useRef3 } from "react";
17823
17901
  import { Box as Box28, Text as Text28 } from "ink";
17824
- import { jsx as jsx28, jsxs as jsxs28 } from "react/jsx-runtime";
17902
+ import { Fragment as Fragment9, jsx as jsx28, jsxs as jsxs28 } from "react/jsx-runtime";
17825
17903
  function CredentialsStep({
17826
17904
  summary,
17827
17905
  error: externalError,
@@ -17935,8 +18013,13 @@ function CredentialsStep({
17935
18013
  "\u2713 ",
17936
18014
  summary
17937
18015
  ] }),
17938
- /* @__PURE__ */ jsx28(Box28, { marginTop: 1, children: /* @__PURE__ */ jsx28(Text28, { children: initialSpaceId && initialCmaToken ? "Credentials pre-filled from experiences setup. Press Enter to continue or edit any field to update." : "Enter your Contentful credentials to continue." }) }),
17939
- !(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." }),
18016
+ /* @__PURE__ */ jsxs28(Box28, { flexDirection: "column", marginTop: 1, gap: 0, children: [
18017
+ /* @__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." }),
18018
+ !(initialSpaceId && initialCmaToken) && /* @__PURE__ */ jsxs28(Fragment9, { children: [
18019
+ /* @__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)." }),
18020
+ /* @__PURE__ */ jsx28(Text28, { dimColor: true, children: "Tip: run experiences setup to save these to ~/.config/experiences/credentials.json so they pre-fill here automatically." })
18021
+ ] })
18022
+ ] }),
17940
18023
  /* @__PURE__ */ jsxs28(Box28, { flexDirection: "column", gap: 0, marginTop: 1, children: [
17941
18024
  renderField("Space ID", spaceId, "spaceId"),
17942
18025
  renderField("Environment", environmentId, "environmentId"),
@@ -18134,7 +18217,7 @@ var init_preview_diff = __esm({
18134
18217
  // packages/experience-design-system-cli/src/import/tui/steps/WizardPreviewStep.tsx
18135
18218
  import { useState as useState16, useMemo as useMemo3 } from "react";
18136
18219
  import { Box as Box29, Text as Text29, useStdout as useStdout3 } from "ink";
18137
- import { Fragment as Fragment9, jsx as jsx29, jsxs as jsxs29 } from "react/jsx-runtime";
18220
+ import { Fragment as Fragment10, jsx as jsx29, jsxs as jsxs29 } from "react/jsx-runtime";
18138
18221
  function buildPreviewDiffLines(preview) {
18139
18222
  const lines = [];
18140
18223
  const { components, tokens } = preview;
@@ -18311,7 +18394,7 @@ function WizardPreviewStep({
18311
18394
  ] }),
18312
18395
  /* @__PURE__ */ jsx29(Text29, { dimColor: true, children: "\u2500".repeat(40) })
18313
18396
  ] }),
18314
- hasAnything ? /* @__PURE__ */ jsxs29(Fragment9, { children: [
18397
+ hasAnything ? /* @__PURE__ */ jsxs29(Fragment10, { children: [
18315
18398
  /* @__PURE__ */ jsx29(Text29, { children: "Here's what will happen in your space:" }),
18316
18399
  hasComponents && /* @__PURE__ */ jsxs29(Box29, { flexDirection: "column", gap: 0, children: [
18317
18400
  /* @__PURE__ */ jsx29(Box29, { gap: 1, marginTop: 1, children: /* @__PURE__ */ jsx29(Text29, { bold: true, dimColor: true, children: "ComponentTypes" }) }),
@@ -18477,7 +18560,7 @@ var init_WizardPreviewStep = __esm({
18477
18560
 
18478
18561
  // packages/experience-design-system-cli/src/import/tui/steps/DoneStep.tsx
18479
18562
  import { Box as Box30, Text as Text30 } from "ink";
18480
- import { Fragment as Fragment10, jsx as jsx30, jsxs as jsxs30 } from "react/jsx-runtime";
18563
+ import { Fragment as Fragment11, jsx as jsx30, jsxs as jsxs30 } from "react/jsx-runtime";
18481
18564
  function DoneStep({
18482
18565
  componentTypes,
18483
18566
  designTokens,
@@ -18498,7 +18581,7 @@ function DoneStep({
18498
18581
  const totalPushed = componentTypes.created + componentTypes.updated + componentTypes.removed + designTokens.created + designTokens.updated + designTokens.removed;
18499
18582
  const success = totalFailed === 0;
18500
18583
  function EntityRows({ entity, label }) {
18501
- return /* @__PURE__ */ jsxs30(Fragment10, { children: [
18584
+ return /* @__PURE__ */ jsxs30(Fragment11, { children: [
18502
18585
  entity.created > 0 && /* @__PURE__ */ jsxs30(Box30, { gap: 1, children: [
18503
18586
  /* @__PURE__ */ jsx30(Text30, { color: PALETTE.success, children: "\u2713" }),
18504
18587
  /* @__PURE__ */ jsxs30(Text30, { children: [
@@ -19103,9 +19186,9 @@ function spawnGenerateChild(opts) {
19103
19186
  stderr += chunk;
19104
19187
  opts.onStderr?.(chunk);
19105
19188
  });
19106
- const donePromise = new Promise((resolve27) => {
19189
+ const donePromise = new Promise((resolve28) => {
19107
19190
  child.on("close", (code, signal) => {
19108
- resolve27({
19191
+ resolve28({
19109
19192
  exitCode: code ?? 0,
19110
19193
  signal: signal ?? null,
19111
19194
  stdout,
@@ -19113,7 +19196,7 @@ function spawnGenerateChild(opts) {
19113
19196
  });
19114
19197
  });
19115
19198
  child.on("error", (err) => {
19116
- resolve27({
19199
+ resolve28({
19117
19200
  exitCode: 1,
19118
19201
  signal: null,
19119
19202
  stdout,
@@ -20670,7 +20753,7 @@ var init_scope_gate_columns = __esm({
20670
20753
  // packages/experience-design-system-cli/src/import/tui/steps/ScopeGateStep.tsx
20671
20754
  import { Box as Box39, Text as Text41, useStdout as useStdout4 } from "ink";
20672
20755
  import React21, { useEffect as useEffect10, useMemo as useMemo5, useRef as useRef4, useState as useState21 } from "react";
20673
- import { Fragment as Fragment11, jsx as jsx42, jsxs as jsxs41 } from "react/jsx-runtime";
20756
+ import { Fragment as Fragment12, jsx as jsx42, jsxs as jsxs41 } from "react/jsx-runtime";
20674
20757
  function capReasonForFocusedRow(reason, width) {
20675
20758
  const safeWidth = Math.max(20, width);
20676
20759
  const budget = safeWidth * FOCUSED_REASON_MAX_LINES;
@@ -21419,7 +21502,7 @@ function ScopeGateStep({
21419
21502
  graph
21420
21503
  }
21421
21504
  ),
21422
- columnPlan.layout === "three-column" && /* @__PURE__ */ jsxs41(Fragment11, { children: [
21505
+ columnPlan.layout === "three-column" && /* @__PURE__ */ jsxs41(Fragment12, { children: [
21423
21506
  /* @__PURE__ */ jsx42(Box39, { width: 2, flexShrink: 0 }),
21424
21507
  /* @__PURE__ */ jsx42(
21425
21508
  AddedComponentsColumn,
@@ -21594,7 +21677,7 @@ function AddedComponentsColumn(props) {
21594
21677
  borderColor: focused ? PALETTE.inverse : void 0,
21595
21678
  children: [
21596
21679
  /* @__PURE__ */ jsx42(ColumnHeader, { title: "Added components", width, focused }),
21597
- entries.length === 0 ? /* @__PURE__ */ jsx42(Text41, { dimColor: true, children: "(none)" }) : /* @__PURE__ */ jsxs41(Fragment11, { children: [
21680
+ entries.length === 0 ? /* @__PURE__ */ jsx42(Text41, { dimColor: true, children: "(none)" }) : /* @__PURE__ */ jsxs41(Fragment12, { children: [
21598
21681
  window.above > 0 && /* @__PURE__ */ jsx42(Text41, { dimColor: true, children: `\u2191 ${window.above} more` }),
21599
21682
  entries.slice(window.start, window.end).map((entry, vi) => {
21600
21683
  const i = window.start + vi;
@@ -21657,7 +21740,7 @@ function AddedGroupsColumn(props) {
21657
21740
  borderColor: focused ? PALETTE.inverse : void 0,
21658
21741
  children: [
21659
21742
  /* @__PURE__ */ jsx42(ColumnHeader, { title: "Added groups", width, focused }),
21660
- entries.length === 0 ? /* @__PURE__ */ jsx42(Text41, { dimColor: true, children: "(none)" }) : /* @__PURE__ */ jsxs41(Fragment11, { children: [
21743
+ entries.length === 0 ? /* @__PURE__ */ jsx42(Text41, { dimColor: true, children: "(none)" }) : /* @__PURE__ */ jsxs41(Fragment12, { children: [
21661
21744
  window.above > 0 && /* @__PURE__ */ jsx42(Text41, { dimColor: true, children: `\u2191 ${window.above} more` }),
21662
21745
  entries.slice(window.start, window.end).map((g, vi) => {
21663
21746
  const i = window.start + vi;
@@ -22363,7 +22446,7 @@ import {
22363
22446
  CDF_PROPERTY_CATEGORIES,
22364
22447
  DESIGN_TOKEN_TYPES as DESIGN_TOKEN_TYPES2
22365
22448
  } from "@contentful/experience-design-system-types";
22366
- import { Fragment as Fragment12, jsx as jsx45, jsxs as jsxs44 } from "react/jsx-runtime";
22449
+ import { Fragment as Fragment13, jsx as jsx45, jsxs as jsxs44 } from "react/jsx-runtime";
22367
22450
  function parseToState(json) {
22368
22451
  let parsed;
22369
22452
  try {
@@ -22565,7 +22648,7 @@ function PropRow({
22565
22648
  activeField === "category" && /* @__PURE__ */ jsx45(Picker, { value: prop.category, active: true }),
22566
22649
  /* @__PURE__ */ jsx45(Text44, { dimColor: !selected, children: "req:" }),
22567
22650
  activeField === "required" ? /* @__PURE__ */ jsx45(Toggle, { value: prop.required, active: true }) : /* @__PURE__ */ jsx45(Toggle, { value: prop.required, active: false }),
22568
- prop.type === "enum" && /* @__PURE__ */ jsxs44(Fragment12, { children: [
22651
+ prop.type === "enum" && /* @__PURE__ */ jsxs44(Fragment13, { children: [
22569
22652
  /* @__PURE__ */ jsx45(Text44, { dimColor: !selected, children: "values:" }),
22570
22653
  /* @__PURE__ */ jsxs44(Text44, { color: selected ? PALETTE.warning : PALETTE.inverse, children: [
22571
22654
  "[",
@@ -22573,7 +22656,7 @@ function PropRow({
22573
22656
  "]"
22574
22657
  ] })
22575
22658
  ] }),
22576
- prop.type === "token" && /* @__PURE__ */ jsxs44(Fragment12, { children: [
22659
+ prop.type === "token" && /* @__PURE__ */ jsxs44(Fragment13, { children: [
22577
22660
  /* @__PURE__ */ jsx45(Text44, { dimColor: !selected, children: "kind:" }),
22578
22661
  activeField === "tokenKind" ? /* @__PURE__ */ jsx45(Picker, { value: prop.tokenKind || DESIGN_TOKEN_TYPES2[0], active: true }) : /* @__PURE__ */ jsx45(Text44, { color: selected ? PALETTE.success : PALETTE.inverse, children: prop.tokenKind || "\u2014" })
22579
22662
  ] })
@@ -23778,7 +23861,7 @@ var init_cycle_panel_scroll = __esm({
23778
23861
 
23779
23862
  // packages/experience-design-system-cli/src/analyze/select/tui/components/RationalePanel.tsx
23780
23863
  import { Box as Box43, Text as Text45 } from "ink";
23781
- import { Fragment as Fragment13, jsx as jsx46, jsxs as jsxs45 } from "react/jsx-runtime";
23864
+ import { Fragment as Fragment14, jsx as jsx46, jsxs as jsxs45 } from "react/jsx-runtime";
23782
23865
  function wrapText(text, innerWidth) {
23783
23866
  if (!text) return [""];
23784
23867
  const width = Math.max(1, innerWidth);
@@ -23858,7 +23941,7 @@ function RationalePanel({
23858
23941
  children: [
23859
23942
  /* @__PURE__ */ jsxs45(Box43, { children: [
23860
23943
  /* @__PURE__ */ jsx46(Text45, { bold: true, dimColor: !active, children: `RATIONALE \u2014 ${componentName}` }),
23861
- overflowed && /* @__PURE__ */ jsxs45(Fragment13, { children: [
23944
+ overflowed && /* @__PURE__ */ jsxs45(Fragment14, { children: [
23862
23945
  /* @__PURE__ */ jsx46(Box43, { flexGrow: 1 }),
23863
23946
  /* @__PURE__ */ jsx46(Text45, { dimColor: !active, children: `\u2195 ${visibleStart}-${visibleEnd}/${totalLines}` })
23864
23947
  ] })
@@ -24582,7 +24665,7 @@ var init_history = __esm({
24582
24665
  // packages/experience-design-system-cli/src/import/tui/steps/GenerateReviewStep.tsx
24583
24666
  import { useEffect as useEffect13, useMemo as useMemo7, useRef as useRef7, useState as useState26 } from "react";
24584
24667
  import { Box as Box46, Text as Text48, useStdout as useStdout6 } from "ink";
24585
- import { Fragment as Fragment14, jsx as jsx49, jsxs as jsxs48 } from "react/jsx-runtime";
24668
+ import { Fragment as Fragment15, jsx as jsx49, jsxs as jsxs48 } from "react/jsx-runtime";
24586
24669
  function sortComponentsForSidebar2(components, cycleParticipants) {
24587
24670
  const isEmpty2 = (entry) => Object.keys(entry.$properties ?? {}).length === 0 && Object.keys(entry.$slots ?? {}).length === 0;
24588
24671
  const tier = (c2) => {
@@ -25976,7 +26059,7 @@ function GenerateReviewStep({
25976
26059
  const isCursor = idx === breakCursor;
25977
26060
  return /* @__PURE__ */ jsx49(Text48, { inverse: isCursor, children: `${isCursor ? "\u25B6" : " "} remove '${edge.toComponent}' from ${edge.fromComponent}.$slots.${edge.slotName}.$allowedComponents` }, `break-${idx}`);
25978
26061
  }),
25979
- breakConfirm ? /* @__PURE__ */ jsxs48(Fragment14, { children: [
26062
+ breakConfirm ? /* @__PURE__ */ jsxs48(Fragment15, { children: [
25980
26063
  /* @__PURE__ */ jsx49(Text48, { children: " " }),
25981
26064
  /* @__PURE__ */ jsx49(Text48, { bold: true, color: PALETTE.warning, children: "Delete this slot edge? [y] confirm [n] cancel" })
25982
26065
  ] }) : /* @__PURE__ */ jsx49(Text48, { dimColor: true, children: "[\u2191\u2193/j/k] move [Enter] delete [x/Esc] close" })
@@ -26058,7 +26141,7 @@ function GenerateReviewStep({
26058
26141
  ] }),
26059
26142
  removedComponents.length > 0 && !dialogOpen && /* @__PURE__ */ jsxs48(Box46, { flexDirection: "column", borderStyle: "round", borderColor: PALETTE.error, paddingX: 1, children: [
26060
26143
  /* @__PURE__ */ jsx49(Text48, { bold: true, color: PALETTE.error, children: removedComponentsHeader(removedComponents.length, true) }),
26061
- !removedBannerCollapsed && /* @__PURE__ */ jsxs48(Fragment14, { children: [
26144
+ !removedBannerCollapsed && /* @__PURE__ */ jsxs48(Fragment15, { children: [
26062
26145
  /* @__PURE__ */ jsx49(Text48, { children: " " }),
26063
26146
  removedComponents.map((rc) => /* @__PURE__ */ jsx49(Text48, { children: removedComponentLine(rc) }, rc.id))
26064
26147
  ] })
@@ -26235,7 +26318,7 @@ function GenerateReviewStep({
26235
26318
  graph: sidebarGraph
26236
26319
  }
26237
26320
  ),
26238
- /* @__PURE__ */ jsx49(Box46, { flexGrow: 1, paddingLeft: 1, flexDirection: "column", children: selected ? /* @__PURE__ */ jsxs48(Fragment14, { children: [
26321
+ /* @__PURE__ */ jsx49(Box46, { flexGrow: 1, paddingLeft: 1, flexDirection: "column", children: selected ? /* @__PURE__ */ jsxs48(Fragment15, { children: [
26239
26322
  /* @__PURE__ */ jsxs48(Box46, { children: [
26240
26323
  /* @__PURE__ */ jsx49(Text48, { bold: true, children: selected.key }),
26241
26324
  /* @__PURE__ */ jsx49(Box46, { flexGrow: 1 }),
@@ -26404,11 +26487,11 @@ function GenerateReviewStep({
26404
26487
  autocompleteCandidates.length > 1 && /* @__PURE__ */ jsx49(Text48, { dimColor: true, children: ` possibilities: ${autocompleteCandidates.join(" \xB7 ").slice(0, 120)}` })
26405
26488
  ] }),
26406
26489
  !dialogOpen && !searchOpen && searchQuery && /* @__PURE__ */ jsx49(Box46, { children: /* @__PURE__ */ jsx49(Text48, { dimColor: true, children: `/${searchQuery} (${searchMatchCount}/${components.length} matches) \xB7 [Esc] clear` }) }),
26407
- !dialogOpen && sidebarFocused && /* @__PURE__ */ jsx49(Box46, { columnGap: 2, flexWrap: "wrap", children: panelOpen === "token-review" ? /* @__PURE__ */ jsxs48(Fragment14, { children: [
26490
+ !dialogOpen && sidebarFocused && /* @__PURE__ */ jsx49(Box46, { columnGap: 2, flexWrap: "wrap", children: panelOpen === "token-review" ? /* @__PURE__ */ jsxs48(Fragment15, { children: [
26408
26491
  legendEntry("[\u2191/\u2193]", "move"),
26409
26492
  legendEntry("[Enter]", "edit allowed"),
26410
26493
  legendEntry("[Esc]", "close")
26411
- ] }) : /* @__PURE__ */ jsxs48(Fragment14, { children: [
26494
+ ] }) : /* @__PURE__ */ jsxs48(Fragment15, { children: [
26412
26495
  legendEntry("[j/k]", "move"),
26413
26496
  legendEntry("[a]", "accept"),
26414
26497
  legendEntry("[r]", "reject"),
@@ -26576,7 +26659,7 @@ var init_GenerateReviewStep = __esm({
26576
26659
  // packages/experience-design-system-cli/src/import/tui/steps/AtomicGenerateReviewStep.tsx
26577
26660
  import { useEffect as useEffect14, useRef as useRef8, useState as useState27 } from "react";
26578
26661
  import { Box as Box47, Text as Text49, useStdout as useStdout7 } from "ink";
26579
- import { Fragment as Fragment15, jsx as jsx50, jsxs as jsxs49 } from "react/jsx-runtime";
26662
+ import { Fragment as Fragment16, jsx as jsx50, jsxs as jsxs49 } from "react/jsx-runtime";
26580
26663
  function sortComponentsForSidebar3(components) {
26581
26664
  return [...components].sort((a, b) => {
26582
26665
  const aEmpty = Object.keys(a.entry.$properties ?? {}).length === 0;
@@ -27301,7 +27384,7 @@ function AtomicGenerateReviewStep({
27301
27384
  width: sidebarWidth
27302
27385
  }
27303
27386
  ),
27304
- /* @__PURE__ */ jsx50(Box47, { flexGrow: 1, paddingLeft: 1, flexDirection: "column", children: selected ? /* @__PURE__ */ jsxs49(Fragment15, { children: [
27387
+ /* @__PURE__ */ jsx50(Box47, { flexGrow: 1, paddingLeft: 1, flexDirection: "column", children: selected ? /* @__PURE__ */ jsxs49(Fragment16, { children: [
27305
27388
  /* @__PURE__ */ jsxs49(Box47, { children: [
27306
27389
  /* @__PURE__ */ jsx50(Text49, { bold: true, children: selected.key }),
27307
27390
  /* @__PURE__ */ jsx50(Box47, { flexGrow: 1 }),
@@ -27656,9 +27739,9 @@ __export(WizardApp_exports, {
27656
27739
  });
27657
27740
  import { useEffect as useEffect15, useRef as useRef9, useState as useState28 } from "react";
27658
27741
  import { Box as Box49, Text as Text51, useStdout as useStdout8 } from "ink";
27659
- import { join as join23, resolve as resolve23 } from "node:path";
27742
+ import { join as join24, resolve as resolve24 } from "node:path";
27660
27743
  import { appendFileSync as appendFileSync2, writeFileSync } from "node:fs";
27661
- import { access as access9, readFile as readFile24, stat as stat6 } from "node:fs/promises";
27744
+ import { access as access9, readFile as readFile25, stat as stat6 } from "node:fs/promises";
27662
27745
  import { tmpdir } from "node:os";
27663
27746
  import { execFile as execFile4, spawn as spawn4 } from "node:child_process";
27664
27747
  import { mkdir as mkdir7 } from "node:fs/promises";
@@ -27670,6 +27753,7 @@ function buildSelectAgentArgs(opts) {
27670
27753
  if (opts.bedrock) args.push("--bedrock");
27671
27754
  if (opts.selectPromptPath) args.push("--select-prompt-path", opts.selectPromptPath);
27672
27755
  if (opts.noCache) args.push("--no-cache");
27756
+ if (opts.existingEntitiesPath) args.push("--existing-entities-path", opts.existingEntitiesPath);
27673
27757
  return args;
27674
27758
  }
27675
27759
  function parseAutoFilterProgressLine(line) {
@@ -27706,6 +27790,7 @@ function buildGenerateComponentsArgs(opts) {
27706
27790
  if (opts.bedrock) args.push("--bedrock");
27707
27791
  if (opts.noCache) args.push("--no-cache");
27708
27792
  if (opts.generatePromptPath) args.push("--generate-prompt-path", opts.generatePromptPath);
27793
+ if (opts.existingEntitiesPath) args.push("--existing-entities-path", opts.existingEntitiesPath);
27709
27794
  return args;
27710
27795
  }
27711
27796
  function buildMapTokensArgs(opts) {
@@ -27713,6 +27798,7 @@ function buildMapTokensArgs(opts) {
27713
27798
  if (opts.model) args.push("--model", opts.model);
27714
27799
  if (opts.noCache) args.push("--no-cache");
27715
27800
  if (opts.skipAgent) args.push("--skip-agent");
27801
+ if (opts.existingEntitiesPath) args.push("--existing-entities-path", opts.existingEntitiesPath);
27716
27802
  return args;
27717
27803
  }
27718
27804
  function shouldRunMapTokens(opts) {
@@ -27802,8 +27888,8 @@ function WizardApp({
27802
27888
  const rawTokensEntryReady = !modifyEntryReady && !pushFromPickerReady && !!initialRawTokensPath;
27803
27889
  const effectiveNoCache = resolveNoCacheForGenerate({ cliNoCache: noCache });
27804
27890
  const initialStepResolved = modifyEntryReady ? "final-review" : pushFromPickerReady ? "push-from-picker" : rawTokensEntryReady ? "generating-tokens" : initialProjectPath ? "token-input" : "welcome";
27805
- const initialOutDir = initialProjectPath ? join23(resolve23(initialProjectPath), ".contentful") : "";
27806
- const initialTokensPath = (modifyEntryReady || pushFromPickerReady) && initialOutDir && seedTokenSessionId ? join23(initialOutDir, "tokens.json") : "";
27891
+ const initialOutDir = initialProjectPath ? join24(resolve24(initialProjectPath), ".contentful") : "";
27892
+ const initialTokensPath = (modifyEntryReady || pushFromPickerReady) && initialOutDir && seedTokenSessionId ? join24(initialOutDir, "tokens.json") : "";
27807
27893
  const [state, setState] = useState28({
27808
27894
  step: modifyEntryReady || rawTokensEntryReady || pushFromPickerReady ? initialStepResolved : initialRuns && initialRuns.length > 0 ? "run-picker" : initialStepResolved,
27809
27895
  agent: initialAgent ?? "claude",
@@ -27856,6 +27942,7 @@ function WizardApp({
27856
27942
  generatePrefetchError: null,
27857
27943
  mapTokensEligible: null,
27858
27944
  credentialsSkipped: false,
27945
+ existingEntitiesPath: null,
27859
27946
  lastRunId: null,
27860
27947
  finalizeErrorBanner: null,
27861
27948
  finalReviewPassed: modifyEntryReady || pushFromPickerReady,
@@ -27970,7 +28057,7 @@ If you are using AWS Bedrock, run:
27970
28057
  }
27971
28058
  const sessionMatch = /^session=(.+)$/m.exec(result.stdout);
27972
28059
  const tokenSessionId = sessionMatch ? sessionMatch[1].trim() : null;
27973
- const tokensPath = join23(outDir, "tokens.json");
28060
+ const tokensPath = join24(outDir, "tokens.json");
27974
28061
  const printArgs = ["print", "tokens", "--out", tokensPath];
27975
28062
  if (tokenSessionId) printArgs.push("--session", tokenSessionId);
27976
28063
  const r = await runCli2(printArgs);
@@ -27990,7 +28077,7 @@ If you are using AWS Bedrock, run:
27990
28077
  tokenCount,
27991
28078
  skipComponents: true,
27992
28079
  acceptedCount: 0,
27993
- outDir: state.outDir || join23(process.cwd(), ".contentful")
28080
+ outDir: state.outDir || join24(process.cwd(), ".contentful")
27994
28081
  });
27995
28082
  if (noPush) {
27996
28083
  void startSaveFlow();
@@ -28042,7 +28129,8 @@ If you are using AWS Bedrock, run:
28042
28129
  agent: state.agent,
28043
28130
  ...state.agentModel ? { model: state.agentModel } : {},
28044
28131
  noCache: effectiveNoCache,
28045
- skipAgent: skipMapTokens
28132
+ skipAgent: skipMapTokens,
28133
+ ...state.existingEntitiesPath ? { existingEntitiesPath: state.existingEntitiesPath } : {}
28046
28134
  });
28047
28135
  const result = await runCli2(args);
28048
28136
  if (result.exitCode !== 0) {
@@ -28056,7 +28144,7 @@ If you are using AWS Bedrock, run:
28056
28144
  return true;
28057
28145
  };
28058
28146
  const runExtract = async (projectPath) => {
28059
- const outDir = join23(resolve23(projectPath), ".contentful");
28147
+ const outDir = join24(resolve24(projectPath), ".contentful");
28060
28148
  update({ step: "extracting", outDir, extractProgress: null, compositionPhase: null });
28061
28149
  const r = await new Promise((res) => {
28062
28150
  const extractArgs = [findCliPath(), "analyze", "extract", "--project", projectPath];
@@ -28163,7 +28251,8 @@ Make sure this path contains TypeScript/React/Vue component files (.tsx, .ts, .v
28163
28251
  ...state.agentModel ? { model: state.agentModel } : {},
28164
28252
  ...state.bedrock ? { bedrock: true } : {},
28165
28253
  selectPromptPath,
28166
- noCache
28254
+ noCache,
28255
+ ...state.existingEntitiesPath ? { existingEntitiesPath: state.existingEntitiesPath } : {}
28167
28256
  });
28168
28257
  const child = spawn4("node", [findCliPath(), ...args]);
28169
28258
  autoFilterChildRef.current = child;
@@ -28261,7 +28350,8 @@ Make sure this path contains TypeScript/React/Vue component files (.tsx, .ts, .v
28261
28350
  agent: state.agent,
28262
28351
  ...state.agentModel ? { model: state.agentModel } : {},
28263
28352
  ...state.bedrock ? { bedrock: true } : {},
28264
- noCache: effectiveNoCache
28353
+ noCache: effectiveNoCache,
28354
+ ...state.existingEntitiesPath ? { existingEntitiesPath: state.existingEntitiesPath } : {}
28265
28355
  })
28266
28356
  ];
28267
28357
  let progressCursor = null;
@@ -28332,7 +28422,8 @@ Make sure this path contains TypeScript/React/Vue component files (.tsx, .ts, .v
28332
28422
  ...state.agentModel ? { model: state.agentModel } : {},
28333
28423
  ...state.bedrock ? { bedrock: true } : {},
28334
28424
  noCache: effectiveNoCache,
28335
- generatePromptPath
28425
+ generatePromptPath,
28426
+ ...state.existingEntitiesPath ? { existingEntitiesPath: state.existingEntitiesPath } : {}
28336
28427
  })
28337
28428
  ];
28338
28429
  let progressCursor = state.generateProgress;
@@ -28372,7 +28463,7 @@ Make sure this path contains TypeScript/React/Vue component files (.tsx, .ts, .v
28372
28463
  if (await runMapTokens2(mappedSessionId)) update({ step: "final-review" });
28373
28464
  };
28374
28465
  const advanceToPushFlow = (generatedAcceptedCount) => {
28375
- update({ generatedAcceptedCount, step: "credentials" });
28466
+ update({ generatedAcceptedCount, step: "push-decision-gate" });
28376
28467
  };
28377
28468
  const runEditFromPreview = async () => {
28378
28469
  update({ step: "final-review" });
@@ -28443,6 +28534,24 @@ Make sure this path contains TypeScript/React/Vue component files (.tsx, .ts, .v
28443
28534
  }
28444
28535
  };
28445
28536
  const advanceAfterCredentialsValidated = async () => {
28537
+ if (!state.credentialsSkipped && state.spaceId && state.environmentId && state.cmaToken && state.projectPath) {
28538
+ const outDir = join24(resolve24(state.projectPath), ".contentful");
28539
+ await mkdir7(outDir, { recursive: true });
28540
+ const result = await fetchAndPersistExistingContentfulEntities({
28541
+ spaceId: state.spaceId,
28542
+ environmentId: state.environmentId,
28543
+ cmaToken: state.cmaToken,
28544
+ ...state.host ? { host: state.host } : {},
28545
+ outDir
28546
+ });
28547
+ if (result.ok) {
28548
+ update({ existingEntitiesPath: result.path });
28549
+ }
28550
+ }
28551
+ if (!sessionRef.current.extractSessionId && state.projectPath) {
28552
+ void runExtract(state.projectPath);
28553
+ return;
28554
+ }
28446
28555
  if (shouldSkipFinalReviewAfterCredentials(state)) {
28447
28556
  update({ step: "push-decision-gate" });
28448
28557
  return;
@@ -28798,7 +28907,7 @@ If using a custom --host, make sure the space exists on that host.`
28798
28907
  };
28799
28908
  const runPrintFiles = async (extractSessionId, outDir, opts = {}) => {
28800
28909
  update({ step: "printing" });
28801
- const componentsPath = join23(outDir, "components.json");
28910
+ const componentsPath = join24(outDir, "components.json");
28802
28911
  const printArgs = ["print", "components", "--out", componentsPath];
28803
28912
  if (extractSessionId) printArgs.push("--session", extractSessionId);
28804
28913
  if (opts.allowEmpty) printArgs.push("--allow-empty");
@@ -28814,7 +28923,7 @@ If using a custom --host, make sure the space exists on that host.`
28814
28923
  let emittedTokensPath;
28815
28924
  let emittedTokenCount;
28816
28925
  if (opts.tokenSessionId) {
28817
- const tokensOut = join23(outDir, "tokens.json");
28926
+ const tokensOut = join24(outDir, "tokens.json");
28818
28927
  const tokenArgs = ["print", "tokens", "--out", tokensOut, "--session", opts.tokenSessionId];
28819
28928
  const tr = await runCli2(tokenArgs);
28820
28929
  if (tr.exitCode !== 0) {
@@ -28901,8 +29010,8 @@ If using a custom --host, make sure the space exists on that host.`
28901
29010
  );
28902
29011
  }
28903
29012
  try {
28904
- const componentsBuf = await readFile24(join23(path, "components.json")).catch(() => null);
28905
- const tokensBuf = recordedTokensPath ? await readFile24(recordedTokensPath).catch(() => null) : null;
29013
+ const componentsBuf = await readFile25(join24(path, "components.json")).catch(() => null);
29014
+ const tokensBuf = recordedTokensPath ? await readFile25(recordedTokensPath).catch(() => null) : null;
28906
29015
  savedFingerprint = buildSavedFingerprint({
28907
29016
  componentsJson: componentsBuf,
28908
29017
  tokensJson: tokensBuf
@@ -28943,7 +29052,7 @@ If using a custom --host, make sure the space exists on that host.`
28943
29052
  if (state.step === "generating-tokens") {
28944
29053
  if (tokenReuseChecked.current) return;
28945
29054
  tokenReuseChecked.current = true;
28946
- const existingTokensPath = join23(state.outDir, "tokens.json");
29055
+ const existingTokensPath = join24(state.outDir, "tokens.json");
28947
29056
  (async () => {
28948
29057
  try {
28949
29058
  await access9(existingTokensPath);
@@ -29019,7 +29128,7 @@ If using a custom --host, make sure the space exists on that host.`
29019
29128
  {
29020
29129
  onContinue: (path) => {
29021
29130
  const projectPath = normalizePath(path);
29022
- const outDir = join23(projectPath, ".contentful");
29131
+ const outDir = join24(projectPath, ".contentful");
29023
29132
  update({ step: "token-input", projectPath, outDir });
29024
29133
  },
29025
29134
  onQuit: () => process.exit(0)
@@ -29084,7 +29193,7 @@ If using a custom --host, make sure the space exists on that host.`
29084
29193
  {
29085
29194
  projectPath: state.projectPath,
29086
29195
  onConfirm: (path) => {
29087
- void runExtract(path);
29196
+ update({ projectPath: path, step: "credentials" });
29088
29197
  },
29089
29198
  onSkipComponents: () => {
29090
29199
  if (noPush) {
@@ -29168,12 +29277,7 @@ If using a custom --host, make sure the space exists on that host.`
29168
29277
  }
29169
29278
  return;
29170
29279
  }
29171
- if (acceptedCount > 0 && !noPush) {
29172
- if (await runAgentAuthCheck("credentials")) {
29173
- startGeneratePrefetch(sid, state.tokensPath);
29174
- }
29175
- }
29176
- update({ step: "credentials" });
29280
+ update({ step: "push-decision-gate" });
29177
29281
  },
29178
29282
  onAdvanceToPushFlow: (count) => {
29179
29283
  update({ acceptedCount: count, autoRejectedCount: 0 });
@@ -29644,10 +29748,11 @@ var init_WizardApp = __esm({
29644
29748
  init_path_utils();
29645
29749
  init_host_utils();
29646
29750
  init_credentials_store();
29751
+ init_fetch_and_persist_existing_contentful_entities();
29647
29752
  init_wizard_state_transitions();
29648
29753
  init_cycle_auto_reject();
29649
29754
  init_cli_path();
29650
- WIZARD_LOG = join23(tmpdir(), "experiences-import-wizard.log");
29755
+ WIZARD_LOG = join24(tmpdir(), "experiences-import-wizard.log");
29651
29756
  }
29652
29757
  });
29653
29758
 
@@ -29658,8 +29763,8 @@ __export(staleness_exports, {
29658
29763
  formatStalenessDetail: () => formatStalenessDetail,
29659
29764
  shortStalenessSummary: () => shortStalenessSummary
29660
29765
  });
29661
- import { readFile as readFile25, stat as stat7 } from "node:fs/promises";
29662
- import { join as join24 } from "node:path";
29766
+ import { readFile as readFile26, stat as stat7 } from "node:fs/promises";
29767
+ import { join as join25 } from "node:path";
29663
29768
  async function checkRunStaleness(run) {
29664
29769
  if (!run.sourceFingerprint) return { ...UNKNOWN };
29665
29770
  const result = {
@@ -29685,7 +29790,7 @@ async function checkRunStaleness(run) {
29685
29790
  if (run.sourceFingerprint.rawTokensPath) {
29686
29791
  const absPath = run.sourceFingerprint.rawTokensPath;
29687
29792
  try {
29688
- const [st, buf] = await Promise.all([stat7(absPath), readFile25(absPath)]);
29793
+ const [st, buf] = await Promise.all([stat7(absPath), readFile26(absPath)]);
29689
29794
  const mtime = st.mtime.toISOString();
29690
29795
  const hash = sha256Hex(buf);
29691
29796
  const mtimeChanged = run.sourceFingerprint.rawTokensMtime !== null && mtime !== run.sourceFingerprint.rawTokensMtime;
@@ -29701,9 +29806,9 @@ async function checkRunStaleness(run) {
29701
29806
  }
29702
29807
  if (run.savedFingerprint) {
29703
29808
  if (run.savedFingerprint.componentsJsonHash !== null) {
29704
- const compPath = join24(run.savePath, "components.json");
29809
+ const compPath = join25(run.savePath, "components.json");
29705
29810
  try {
29706
- const buf = await readFile25(compPath);
29811
+ const buf = await readFile26(compPath);
29707
29812
  if (sha256Hex(buf) !== run.savedFingerprint.componentsJsonHash) {
29708
29813
  result.savedComponentsEdited = true;
29709
29814
  result.stale = true;
@@ -29714,9 +29819,9 @@ async function checkRunStaleness(run) {
29714
29819
  }
29715
29820
  }
29716
29821
  if (run.savedFingerprint.tokensJsonHash !== null) {
29717
- const tokensPath = run.tokensPath ?? join24(run.savePath, "tokens.json");
29822
+ const tokensPath = run.tokensPath ?? join25(run.savePath, "tokens.json");
29718
29823
  try {
29719
- const buf = await readFile25(tokensPath);
29824
+ const buf = await readFile26(tokensPath);
29720
29825
  if (sha256Hex(buf) !== run.savedFingerprint.tokensJsonHash) {
29721
29826
  result.savedTokensEdited = true;
29722
29827
  result.stale = true;
@@ -29783,7 +29888,7 @@ async function promptForPushCredentials(opts = {}) {
29783
29888
  const { render: render7, Box: Box50, Text: Text52 } = await import("ink");
29784
29889
  const { useState: useState29 } = await import("react");
29785
29890
  const { CredentialsStep: CredentialsStep2 } = await Promise.resolve().then(() => (init_CredentialsStep(), CredentialsStep_exports));
29786
- return new Promise((resolve27, reject) => {
29891
+ return new Promise((resolve28, reject) => {
29787
29892
  let app = null;
29788
29893
  function App2() {
29789
29894
  const [done, setDone] = useState29(false);
@@ -29792,7 +29897,7 @@ async function promptForPushCredentials(opts = {}) {
29792
29897
  setDone(true);
29793
29898
  queueMicrotask(() => {
29794
29899
  app?.unmount();
29795
- resolve27({ spaceId, environmentId, cmaToken, host });
29900
+ resolve28({ spaceId, environmentId, cmaToken, host });
29796
29901
  });
29797
29902
  };
29798
29903
  if (done) {
@@ -29824,14 +29929,14 @@ var init_push_creds_prompt = __esm({
29824
29929
  // packages/experience-design-system-cli/src/program.ts
29825
29930
  import { spawn as spawn6 } from "node:child_process";
29826
29931
  import { fileURLToPath as fileURLToPath5 } from "node:url";
29827
- import { dirname as dirname14, join as join27, resolve as resolve26 } from "node:path";
29932
+ import { dirname as dirname14, join as join28, resolve as resolve27 } from "node:path";
29828
29933
  import { readFileSync as readFileSync10 } from "node:fs";
29829
29934
  import { Command } from "commander";
29830
29935
 
29831
29936
  // packages/experience-design-system-cli/src/analyze/command.ts
29832
29937
  import { createElement as createElement3 } from "react";
29833
29938
  import { render as render3 } from "ink";
29834
- import { mkdir as mkdir3, readdir as readdir2, readFile as readFile16, stat as stat2, writeFile as writeFile3 } from "node:fs/promises";
29939
+ import { mkdir as mkdir3, readdir as readdir2, readFile as readFile17, stat as stat2, writeFile as writeFile3 } from "node:fs/promises";
29835
29940
  import { isAbsolute as isAbsolute4, join as join15, relative as relative3, resolve as resolve15 } from "node:path";
29836
29941
 
29837
29942
  // packages/experience-design-system-cli/src/lib/agent-model-options.ts
@@ -29958,6 +30063,104 @@ init_command2();
29958
30063
  // packages/experience-design-system-cli/src/analyze/select-agent/command.ts
29959
30064
  init_db();
29960
30065
  init_cache_keys();
30066
+
30067
+ // packages/experience-design-system-cli/src/helpers/read-existing-contentful-entities-from-session.ts
30068
+ import { readFile as readFile13 } from "node:fs/promises";
30069
+ async function readExistingContentfulEntitiesFromSession(path) {
30070
+ if (!path) return void 0;
30071
+ try {
30072
+ const raw = await readFile13(path, "utf8");
30073
+ const parsed = JSON.parse(raw);
30074
+ if (!Array.isArray(parsed.components) || !Array.isArray(parsed.tokens)) return void 0;
30075
+ return parsed;
30076
+ } catch {
30077
+ return void 0;
30078
+ }
30079
+ }
30080
+
30081
+ // packages/experience-design-system-cli/src/helpers/find-nearly-matching-component.ts
30082
+ var MAX_CHARACTER_EDITS_FOR_LIKELY_MATCH = 2;
30083
+ function findNearlyMatchingComponent(components, codebaseName) {
30084
+ const target = simplifyNameForComparison(codebaseName);
30085
+ if (!target) return void 0;
30086
+ let best;
30087
+ for (const c2 of components) {
30088
+ const edits = countCharacterEdits(target, simplifyNameForComparison(c2.name));
30089
+ if (edits > MAX_CHARACTER_EDITS_FOR_LIKELY_MATCH) continue;
30090
+ if (!best || edits < best.edits) best = { component: c2, edits };
30091
+ if (edits === 0) break;
30092
+ }
30093
+ return best?.component;
30094
+ }
30095
+ function simplifyNameForComparison(name) {
30096
+ const stripped = name.toLowerCase().replace(/[^a-z0-9]/g, "");
30097
+ return stripped.endsWith("s") && stripped.length > 1 ? stripped.slice(0, -1) : stripped;
30098
+ }
30099
+ function countCharacterEdits(a, b) {
30100
+ if (a === b) return 0;
30101
+ if (a.length === 0) return b.length;
30102
+ if (b.length === 0) return a.length;
30103
+ if (a.length > b.length) [a, b] = [b, a];
30104
+ let prev = new Array(a.length + 1);
30105
+ let curr = new Array(a.length + 1);
30106
+ for (let i = 0; i <= a.length; i++) prev[i] = i;
30107
+ for (let j = 1; j <= b.length; j++) {
30108
+ curr[0] = j;
30109
+ for (let i = 1; i <= a.length; i++) {
30110
+ const cost = a[i - 1] === b[j - 1] ? 0 : 1;
30111
+ curr[i] = Math.min(curr[i - 1] + 1, prev[i] + 1, prev[i - 1] + cost);
30112
+ }
30113
+ [prev, curr] = [curr, prev];
30114
+ }
30115
+ return prev[a.length];
30116
+ }
30117
+
30118
+ // packages/experience-design-system-cli/src/helpers/summarize-existing-contentful-entities.ts
30119
+ function summarizeForSelectAgent(entities) {
30120
+ return {
30121
+ components: entities.components.map((c2) => ({
30122
+ id: c2.sys.id,
30123
+ name: c2.name,
30124
+ description: c2.description
30125
+ })),
30126
+ tokens: summarizeTokens(entities.tokens)
30127
+ };
30128
+ }
30129
+ function summarizeForGenerateAgent(entities, codebaseComponentName) {
30130
+ const match2 = findNearlyMatchingComponent(entities.components, codebaseComponentName);
30131
+ const otherComponents = entities.components.filter((c2) => c2.sys.id !== match2?.sys.id).map((c2) => ({ id: c2.sys.id, name: c2.name }));
30132
+ return {
30133
+ likelyMatch: match2 ? {
30134
+ id: match2.sys.id,
30135
+ name: match2.name,
30136
+ designProperties: match2.designProperties.map((p) => ({
30137
+ id: p.id,
30138
+ name: p.name,
30139
+ type: p.type
30140
+ })),
30141
+ contentProperties: match2.contentProperties.map((p) => ({
30142
+ id: p.id,
30143
+ name: p.name,
30144
+ type: p.type
30145
+ })),
30146
+ slots: (match2.slots ?? []).map((s) => ({ id: s.id, name: s.name }))
30147
+ } : void 0,
30148
+ otherComponents,
30149
+ tokens: summarizeTokens(entities.tokens)
30150
+ };
30151
+ }
30152
+ function summarizeForMapTokens(entities) {
30153
+ return {
30154
+ tokens: entities.tokens.map((t) => ({ id: t.sys.id, name: t.name, type: t.type }))
30155
+ };
30156
+ }
30157
+ function summarizeTokens(tokens) {
30158
+ const kinds = /* @__PURE__ */ new Set();
30159
+ for (const t of tokens) kinds.add(t.type);
30160
+ return { count: tokens.length, kinds: [...kinds].sort() };
30161
+ }
30162
+
30163
+ // packages/experience-design-system-cli/src/analyze/select-agent/command.ts
29961
30164
  init_persistence();
29962
30165
  init_parser();
29963
30166
  init_src();
@@ -30059,7 +30262,7 @@ var OutputFormatter = class {
30059
30262
  };
30060
30263
 
30061
30264
  // packages/experience-design-system-cli/src/analyze/select-agent/context-builder.ts
30062
- import { readFile as readFile13 } from "node:fs/promises";
30265
+ import { readFile as readFile14 } from "node:fs/promises";
30063
30266
  import { dirname as dirname10, isAbsolute as isAbsolute2, join as join13, relative as relative2, resolve as resolve11, sep } from "node:path";
30064
30267
  var SCANNED_FILE_EXTENSIONS = /* @__PURE__ */ new Set([".astro", ".js", ".jsx", ".svelte", ".ts", ".tsx", ".vue"]);
30065
30268
  var IMPORT_PATTERN2 = /import\s+(?:type\s+)?(.+?)\s+from\s+['"]([^'"]+)['"]/g;
@@ -30188,7 +30391,7 @@ async function buildRepoContextIndex(root, filePaths) {
30188
30391
  absolutePath,
30189
30392
  relativePath: toPosixPath(relative2(resolvedRoot, absolutePath)),
30190
30393
  directory: dirname10(absolutePath),
30191
- text: await readFile13(absolutePath, "utf8").catch(() => "")
30394
+ text: await readFile14(absolutePath, "utf8").catch(() => "")
30192
30395
  })
30193
30396
  )
30194
30397
  );
@@ -30401,7 +30604,7 @@ function resolveProjectRoot(sessionId2, projectRootFlag) {
30401
30604
  db.close();
30402
30605
  }
30403
30606
  }
30404
- async function selectBatch(agent, model, batch, total, verbose, skillPathOverride) {
30607
+ async function selectBatch(agent, model, batch, total, verbose, skillPathOverride, existingComponentsInline) {
30405
30608
  const prompt2 = await buildPrompt({
30406
30609
  skill: "select",
30407
30610
  mode: "autonomous",
@@ -30411,7 +30614,8 @@ async function selectBatch(agent, model, batch, total, verbose, skillPathOverrid
30411
30614
  2
30412
30615
  ),
30413
30616
  outDir: process.cwd(),
30414
- skillPathOverride
30617
+ skillPathOverride,
30618
+ existingComponentsInline
30415
30619
  });
30416
30620
  let outputBuf = "";
30417
30621
  const formatter = new OutputFormatter(verbose, (s) => {
@@ -30506,7 +30710,7 @@ ${outputBuf}`);
30506
30710
  }
30507
30711
  return results;
30508
30712
  }
30509
- async function selectAllComponents(agent, model, components, verbose, skillPathOverride, cacheConfig = { noCache: true }) {
30713
+ async function selectAllComponents(agent, model, components, verbose, skillPathOverride, existingComponentsInline, cacheConfig = { noCache: true }) {
30510
30714
  const concurrency = Number(process.env.EDS_GENERATE_CONCURRENCY ?? DEFAULT_CONCURRENCY);
30511
30715
  const batchSize = resolveBatchSize();
30512
30716
  const total = components.length;
@@ -30515,7 +30719,13 @@ async function selectAllComponents(agent, model, components, verbose, skillPathO
30515
30719
  let cliVersion2 = "";
30516
30720
  if (!cacheConfig.noCache) {
30517
30721
  try {
30518
- promptHash = await hashPromptForSkill("select", agent, model, skillPathOverride);
30722
+ promptHash = await hashPromptForSkill(
30723
+ "select",
30724
+ agent,
30725
+ model,
30726
+ skillPathOverride,
30727
+ existingComponentsInline ? [hashContent(existingComponentsInline)] : []
30728
+ );
30519
30729
  cliVersion2 = await getCliCacheVersion();
30520
30730
  const db = openPipelineDb(cacheConfig.dbPath);
30521
30731
  try {
@@ -30571,7 +30781,15 @@ async function selectAllComponents(agent, model, components, verbose, skillPathO
30571
30781
  while (nextBatch < batches.length) {
30572
30782
  const b = nextBatch++;
30573
30783
  const batch = batches[b];
30574
- const batchResults = await selectBatch(agent, model, batch, total, verbose, skillPathOverride);
30784
+ const batchResults = await selectBatch(
30785
+ agent,
30786
+ model,
30787
+ batch,
30788
+ total,
30789
+ verbose,
30790
+ skillPathOverride,
30791
+ existingComponentsInline
30792
+ );
30575
30793
  for (let k = 0; k < batch.length; k++) {
30576
30794
  results[batch[k].index] = batchResults[k];
30577
30795
  }
@@ -30607,6 +30825,9 @@ function registerAnalyzeSelectAgentCommand(program) {
30607
30825
  "--select-prompt-path <path>",
30608
30826
  "Path to a custom .md skill prompt for select-agent (bypasses bundled prompt invariants)"
30609
30827
  ).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(
30828
+ "--existing-entities-path <path>",
30829
+ "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."
30830
+ ).option(
30610
30831
  "--show-rationale",
30611
30832
  "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
30833
  ).option("--json", "When used with --show-rationale, emit a JSON array instead of a human-readable table").action(
@@ -30715,6 +30936,20 @@ function registerAnalyzeSelectAgentCommand(program) {
30715
30936
  }));
30716
30937
  }
30717
30938
  }
30939
+ let existingComponentsInline;
30940
+ if (opts.existingEntitiesPath) {
30941
+ const existingContentfulEntities = await readExistingContentfulEntitiesFromSession(
30942
+ resolve12(opts.existingEntitiesPath)
30943
+ );
30944
+ if (existingContentfulEntities) {
30945
+ existingComponentsInline = JSON.stringify(summarizeForSelectAgent(existingContentfulEntities));
30946
+ } else {
30947
+ process.stderr.write(
30948
+ `warn: --existing-entities-path ${opts.existingEntitiesPath} could not be read as JSON \u2014 proceeding without space-context enrichment
30949
+ `
30950
+ );
30951
+ }
30952
+ }
30718
30953
  if (opts.dryRun) {
30719
30954
  if (selectionCandidates.length === 0) {
30720
30955
  process.stderr.write(
@@ -30729,7 +30964,8 @@ function registerAnalyzeSelectAgentCommand(program) {
30729
30964
  mode: "autonomous",
30730
30965
  rawComponentsInline: JSON.stringify([buildComponentData(first)], null, 2),
30731
30966
  outDir: process.cwd(),
30732
- skillPathOverride: selectPromptPath ? resolve12(selectPromptPath) : void 0
30967
+ skillPathOverride: selectPromptPath ? resolve12(selectPromptPath) : void 0,
30968
+ existingComponentsInline
30733
30969
  });
30734
30970
  process.stdout.write(prompt2 + "\n");
30735
30971
  await exitWithAnalytics(0);
@@ -30742,6 +30978,7 @@ function registerAnalyzeSelectAgentCommand(program) {
30742
30978
  selectionCandidates,
30743
30979
  opts.verbose ?? false,
30744
30980
  selectPromptPath ? resolve12(selectPromptPath) : void 0,
30981
+ existingComponentsInline,
30745
30982
  { noCache }
30746
30983
  );
30747
30984
  const decisions = /* @__PURE__ */ new Map();
@@ -31129,11 +31366,11 @@ ${f.content}`).join("\n\n");
31129
31366
  }
31130
31367
 
31131
31368
  // packages/experience-design-system-cli/src/analyze/composition/resolve-mapping-cli.ts
31132
- import { readFile as readFile14 } from "node:fs/promises";
31369
+ import { readFile as readFile15 } from "node:fs/promises";
31133
31370
  async function loadUserMap(path) {
31134
31371
  let text;
31135
31372
  try {
31136
- text = await readFile14(path, "utf8");
31373
+ text = await readFile15(path, "utf8");
31137
31374
  } catch {
31138
31375
  return { ok: false, error: `--composition-map: file not found: ${path}` };
31139
31376
  }
@@ -31369,16 +31606,16 @@ var HEAP_CAP_MB = 128;
31369
31606
  var MAX_INPUT_BYTES = 8 * 1024 * 1024;
31370
31607
  function runParserInSandbox(source, ctx, opts = {}) {
31371
31608
  const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS2;
31372
- return new Promise((resolve27) => {
31609
+ return new Promise((resolve28) => {
31373
31610
  let input;
31374
31611
  try {
31375
31612
  input = JSON.stringify({ source, ctx, timeoutMs });
31376
31613
  } catch {
31377
- resolve27({ edges: [], error: "ctx is not serializable" });
31614
+ resolve28({ edges: [], error: "ctx is not serializable" });
31378
31615
  return;
31379
31616
  }
31380
31617
  if (input.length > MAX_INPUT_BYTES) {
31381
- resolve27({ edges: [], error: "parser input exceeds size limit" });
31618
+ resolve28({ edges: [], error: "parser input exceeds size limit" });
31382
31619
  return;
31383
31620
  }
31384
31621
  let settled = false;
@@ -31410,7 +31647,7 @@ function runParserInSandbox(source, ctx, opts = {}) {
31410
31647
  child.kill("SIGKILL");
31411
31648
  } catch {
31412
31649
  }
31413
- resolve27(r);
31650
+ resolve28(r);
31414
31651
  };
31415
31652
  const timer = setTimeout(
31416
31653
  () => done({ edges: [], error: `parser timed out after ${timeoutMs}ms` }),
@@ -31622,7 +31859,7 @@ ${loadPrompt("composition-parser-repair-error.md").trim().replace("{{error}}", f
31622
31859
  }
31623
31860
 
31624
31861
  // packages/experience-design-system-cli/src/lib/prompt-overrides.ts
31625
- import { readFile as readFile15 } from "node:fs/promises";
31862
+ import { readFile as readFile16 } from "node:fs/promises";
31626
31863
  import { resolve as resolve14 } from "node:path";
31627
31864
  var PROMPT_FILE_EXTENSIONS = [".md", ".txt", ".prompt"];
31628
31865
  function looksLikePath(value) {
@@ -31658,7 +31895,7 @@ async function resolvePromptOverride(override) {
31658
31895
  if (override.kind === "text") return override.value;
31659
31896
  const abs = resolve14(override.value);
31660
31897
  try {
31661
- return await readFile15(abs, "utf8");
31898
+ return await readFile16(abs, "utf8");
31662
31899
  } catch {
31663
31900
  throw new Error(`--prompt: could not read prompt file: ${abs}`);
31664
31901
  }
@@ -31841,7 +32078,7 @@ async function readCandidateFiles(components, extraFiles = []) {
31841
32078
  await Promise.all(
31842
32079
  [...paths].map(async (p) => {
31843
32080
  try {
31844
- const content = await readFile16(p, "utf8");
32081
+ const content = await readFile17(p, "utf8");
31845
32082
  out.push({ path: p, content });
31846
32083
  } catch {
31847
32084
  }
@@ -32245,7 +32482,7 @@ function registerAnalyzeCommand(program) {
32245
32482
  init_src();
32246
32483
  import { createElement as createElement4 } from "react";
32247
32484
  import { render as render4 } from "ink";
32248
- import { access as access6, readFile as readFile18, readdir as readdir3, stat as stat3 } from "node:fs/promises";
32485
+ import { access as access6, readFile as readFile19, readdir as readdir3, stat as stat3 } from "node:fs/promises";
32249
32486
  import { join as join16, resolve as resolve17 } from "node:path";
32250
32487
  init_debug_logger();
32251
32488
 
@@ -32286,7 +32523,7 @@ function GenerateView({ result, onExit }) {
32286
32523
  }
32287
32524
 
32288
32525
  // packages/experience-design-system-cli/src/generate/edit/command.ts
32289
- import { readFile as readFile17 } from "node:fs/promises";
32526
+ import { readFile as readFile18 } from "node:fs/promises";
32290
32527
  import { resolve as resolve16 } from "node:path";
32291
32528
  var SAFE_PATH_RE2 = /^[a-zA-Z0-9_.$[\]=]+$/;
32292
32529
  var PROTO_KEYS2 = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
@@ -32369,7 +32606,7 @@ async function runNonInteractive2(opts, skill) {
32369
32606
  if (opts.patch) {
32370
32607
  let patchOps;
32371
32608
  try {
32372
- const raw = await readFile17(resolve16(opts.patch), "utf8");
32609
+ const raw = await readFile18(resolve16(opts.patch), "utf8");
32373
32610
  patchOps = JSON.parse(raw);
32374
32611
  } catch {
32375
32612
  process.stderr.write(`Error: cannot read or parse --patch file: ${opts.patch}
@@ -32463,7 +32700,7 @@ async function readFileInline(path) {
32463
32700
  } catch {
32464
32701
  return void 0;
32465
32702
  }
32466
- if (!s.isDirectory()) return readFile18(resolved, "utf8");
32703
+ if (!s.isDirectory()) return readFile19(resolved, "utf8");
32467
32704
  const files = [];
32468
32705
  async function walk(dir) {
32469
32706
  let entries;
@@ -32489,7 +32726,7 @@ async function readFileInline(path) {
32489
32726
  }
32490
32727
  await walk(resolved);
32491
32728
  if (files.length === 0) return void 0;
32492
- const parts = await Promise.all(files.map((f) => readFile18(f, "utf8").catch(() => "")));
32729
+ const parts = await Promise.all(files.map((f) => readFile19(f, "utf8").catch(() => "")));
32493
32730
  return parts.filter(Boolean).join("\n\n");
32494
32731
  }
32495
32732
  function printFallbackInstructions(options) {
@@ -32511,7 +32748,7 @@ function printFallbackInstructions(options) {
32511
32748
  lines.push(` Re-run the generate command with the agent available, or use --dry-run to inspect the prompt.`);
32512
32749
  process.stderr.write(lines.join("\n") + "\n");
32513
32750
  }
32514
- async function runOneComponent(agent, model, db, sessionId2, component, tokensInline, tokenMapInline, index, total, verbose, noCache, skillPathOverride, promptHash) {
32751
+ async function runOneComponent(agent, model, db, sessionId2, component, tokensInline, tokenMapInline, index, total, verbose, noCache, skillPathOverride, promptHash, existingContentfulEntities, existingTokensInline) {
32515
32752
  const pos = c.dim(`[${index + 1}/${total}]`);
32516
32753
  if (!noCache) {
32517
32754
  const inputHash = computeComponentInputHash(component);
@@ -32581,6 +32818,7 @@ async function runOneComponent(agent, model, db, sessionId2, component, tokensIn
32581
32818
  component.props.map((p) => p.name),
32582
32819
  component.props.map((p) => p.type)
32583
32820
  );
32821
+ const existingComponentsInline = existingContentfulEntities ? JSON.stringify(summarizeForGenerateAgent(existingContentfulEntities, component.name)) : void 0;
32584
32822
  const prompt2 = await buildPrompt({
32585
32823
  skill: "components",
32586
32824
  mode: "autonomous",
@@ -32590,7 +32828,9 @@ async function runOneComponent(agent, model, db, sessionId2, component, tokensIn
32590
32828
  outDir: process.cwd(),
32591
32829
  componentName: component.name,
32592
32830
  componentSourceRefs: [sourceRef],
32593
- skillPathOverride
32831
+ skillPathOverride,
32832
+ existingComponentsInline,
32833
+ existingTokensInline
32594
32834
  });
32595
32835
  const maxAttempts = 2;
32596
32836
  let lastError = "";
@@ -32658,7 +32898,7 @@ ${outputBuf}`);
32658
32898
  renamedSlotsCount: renames.length
32659
32899
  };
32660
32900
  }
32661
- async function runAllComponents(agent, model, db, sessionId2, components, tokensInline, tokenMapInline, verbose, noCache, skillPathOverride, promptHash) {
32901
+ async function runAllComponents(agent, model, db, sessionId2, components, tokensInline, tokenMapInline, verbose, noCache, skillPathOverride, promptHash, existingContentfulEntities, existingTokensInline) {
32662
32902
  const concurrency = Number(process.env.EDS_GENERATE_CONCURRENCY ?? DEFAULT_COMPONENT_CONCURRENCY);
32663
32903
  process.stderr.write(
32664
32904
  `Categorizing ${c.bold(String(components.length))} component${components.length === 1 ? "" : "s"}` + c.dim(` (concurrency: ${concurrency})`) + "\n"
@@ -32682,7 +32922,9 @@ async function runAllComponents(agent, model, db, sessionId2, components, tokens
32682
32922
  verbose,
32683
32923
  noCache,
32684
32924
  skillPathOverride,
32685
- promptHash
32925
+ promptHash,
32926
+ existingContentfulEntities,
32927
+ existingTokensInline
32686
32928
  );
32687
32929
  completed += 1;
32688
32930
  process.stderr.write(`${formatGenerateProgressLine(completed, components.length, results[i].componentName)}
@@ -32720,7 +32962,7 @@ async function loadAcceptedNames(sessionId2) {
32720
32962
  try {
32721
32963
  const artifactsRoot = getRefineArtifactsRoot();
32722
32964
  const paths = await getRefineSessionPaths(sessionId2, artifactsRoot);
32723
- const raw = await readFile18(paths.statePath, "utf8");
32965
+ const raw = await readFile19(paths.statePath, "utf8");
32724
32966
  const snapshot = JSON.parse(raw);
32725
32967
  const accepted = snapshot.components.filter((c2) => c2.status === "accepted").map((c2) => c2.name);
32726
32968
  if (accepted.length === 0) return null;
@@ -32766,6 +33008,19 @@ async function runGenerateSkill(skill, opts, verbose = false) {
32766
33008
  readFileInline(opts.tokens),
32767
33009
  readFileInline(opts.tokenMap)
32768
33010
  ]);
33011
+ let existingContentfulEntities;
33012
+ let existingTokensInline;
33013
+ if (opts.existingEntitiesPath) {
33014
+ existingContentfulEntities = await readExistingContentfulEntitiesFromSession(resolve17(opts.existingEntitiesPath));
33015
+ if (existingContentfulEntities) {
33016
+ existingTokensInline = JSON.stringify(summarizeForMapTokens(existingContentfulEntities));
33017
+ } else {
33018
+ process.stderr.write(
33019
+ `warn: --existing-entities-path ${opts.existingEntitiesPath} could not be read as JSON \u2014 proceeding without space-context enrichment
33020
+ `
33021
+ );
33022
+ }
33023
+ }
32769
33024
  let sessionId2;
32770
33025
  let allComponents;
32771
33026
  if (skill === "components") {
@@ -32826,6 +33081,7 @@ async function runGenerateSkill(skill, opts, verbose = false) {
32826
33081
  sampleComponent.props.map((p) => p.name),
32827
33082
  sampleComponent.props.map((p) => p.type)
32828
33083
  ) : void 0;
33084
+ const dryRunExistingComponentsInline = skill === "components" && existingContentfulEntities && sampleComponent ? JSON.stringify(summarizeForGenerateAgent(existingContentfulEntities, sampleComponent.name)) : void 0;
32829
33085
  const prompt2 = await buildPrompt({
32830
33086
  skill,
32831
33087
  mode: "autonomous",
@@ -32836,7 +33092,9 @@ async function runGenerateSkill(skill, opts, verbose = false) {
32836
33092
  tokenMapInline,
32837
33093
  outDir: process.cwd(),
32838
33094
  componentSourceRefs: sampleSourceRef ? [sampleSourceRef] : void 0,
32839
- skillPathOverride: generatePromptPath
33095
+ skillPathOverride: generatePromptPath,
33096
+ existingComponentsInline: dryRunExistingComponentsInline,
33097
+ existingTokensInline: skill === "components" ? existingTokensInline : void 0
32840
33098
  });
32841
33099
  process.stdout.write(prompt2 + "\n");
32842
33100
  await exitWithAnalytics(0);
@@ -32854,7 +33112,15 @@ async function runGenerateSkill(skill, opts, verbose = false) {
32854
33112
  const db = openPipelineDb();
32855
33113
  let componentResults;
32856
33114
  try {
32857
- const promptHash = await hashPromptForSkill("components", agent, model, generatePromptPath);
33115
+ const existingContentfulEntitiesHashInputs = [];
33116
+ if (existingTokensInline) existingContentfulEntitiesHashInputs.push(hashContent(existingTokensInline));
33117
+ const promptHash = await hashPromptForSkill(
33118
+ "components",
33119
+ agent,
33120
+ model,
33121
+ generatePromptPath,
33122
+ existingContentfulEntitiesHashInputs
33123
+ );
32858
33124
  componentResults = await runAllComponents(
32859
33125
  agent,
32860
33126
  model,
@@ -32866,7 +33132,9 @@ async function runGenerateSkill(skill, opts, verbose = false) {
32866
33132
  verbose,
32867
33133
  opts.cache === false || process.env.EDS_NO_CACHE === "1",
32868
33134
  generatePromptPath,
32869
- promptHash
33135
+ promptHash,
33136
+ existingContentfulEntities,
33137
+ existingTokensInline
32870
33138
  );
32871
33139
  } finally {
32872
33140
  db.close();
@@ -33043,6 +33311,9 @@ function registerGenerateCommand(program) {
33043
33311
  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
33312
  "--generate-prompt-path <path>",
33045
33313
  "Path to a custom .md skill prompt for components generation (bypasses bundled prompt invariants)"
33314
+ ).option(
33315
+ "--existing-entities-path <path>",
33316
+ "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
33317
  );
33047
33318
  addAgentFlags(componentsCmd).action(async (opts) => {
33048
33319
  await runGenerateSkill("components", opts, opts.verbose ?? false);
@@ -33489,9 +33760,9 @@ ${"\u2500".repeat(60)}
33489
33760
  `);
33490
33761
  }
33491
33762
  process.stdout.write("\nDelete these sessions? (y/N) ");
33492
- const answer = await new Promise((resolve27) => {
33763
+ const answer = await new Promise((resolve28) => {
33493
33764
  process.stdin.setEncoding("utf8");
33494
- process.stdin.once("data", (chunk) => resolve27(String(chunk).trim().toLowerCase()));
33765
+ process.stdin.once("data", (chunk) => resolve28(String(chunk).trim().toLowerCase()));
33495
33766
  });
33496
33767
  if (answer !== "y") {
33497
33768
  db.close();
@@ -33526,7 +33797,7 @@ import { access as access7, mkdir as mkdir4, stat as stat4, writeFile as writeFi
33526
33797
  import { basename as basename5, resolve as resolve19 } from "node:path";
33527
33798
 
33528
33799
  // packages/experience-design-system-cli/src/print/validate/validators/cdf-validator.ts
33529
- import { readFile as readFile19 } from "node:fs/promises";
33800
+ import { readFile as readFile20 } from "node:fs/promises";
33530
33801
  import { validateCDF as validateCDF2 } from "@contentful/experience-design-system-types";
33531
33802
  function extractValue(input, path) {
33532
33803
  if (path === "/") return void 0;
@@ -33585,7 +33856,7 @@ function rewriteDiagnostic(error, input) {
33585
33856
  async function validateCDFFile(filePath) {
33586
33857
  let content;
33587
33858
  try {
33588
- content = await readFile19(filePath, "utf-8");
33859
+ content = await readFile20(filePath, "utf-8");
33589
33860
  } catch (err) {
33590
33861
  return {
33591
33862
  valid: false,
@@ -33620,7 +33891,7 @@ async function validateCDFFile(filePath) {
33620
33891
  }
33621
33892
 
33622
33893
  // packages/experience-design-system-cli/src/print/validate/validators/dtcg-validator.ts
33623
- import { readFile as readFile20 } from "node:fs/promises";
33894
+ import { readFile as readFile21 } from "node:fs/promises";
33624
33895
  import { DESIGN_TOKEN_TYPES } from "@contentful/experience-design-system-types";
33625
33896
  function walkDTCG(obj, path, diagnostics, counts) {
33626
33897
  for (const [key, value] of Object.entries(obj)) {
@@ -33665,7 +33936,7 @@ function walkDTCG(obj, path, diagnostics, counts) {
33665
33936
  async function validateDTCGTokenFile(filePath) {
33666
33937
  let content;
33667
33938
  try {
33668
- content = await readFile20(filePath, "utf-8");
33939
+ content = await readFile21(filePath, "utf-8");
33669
33940
  } catch (err) {
33670
33941
  return {
33671
33942
  valid: false,
@@ -33998,7 +34269,8 @@ init_db();
33998
34269
  init_cache_keys();
33999
34270
  import { createElement as createElement6 } from "react";
34000
34271
  import { render as render6 } from "ink";
34001
- import { readFile as readFile21 } from "node:fs/promises";
34272
+ import { readFile as readFile22 } from "node:fs/promises";
34273
+ import { resolve as resolve20 } from "node:path";
34002
34274
 
34003
34275
  // packages/experience-design-system-cli/src/map-tokens/apply.ts
34004
34276
  init_db();
@@ -34246,7 +34518,7 @@ async function runMapTokens(opts) {
34246
34518
  const knownTokenPaths = new Set(tokenLeaves.map((t) => t.path));
34247
34519
  const tokenMapDiagnostics = [];
34248
34520
  if (opts.tokenMap) {
34249
- const fileMappings = JSON.parse(await readFile21(opts.tokenMap, "utf8"));
34521
+ const fileMappings = JSON.parse(await readFile22(opts.tokenMap, "utf8"));
34250
34522
  const validMappings = {};
34251
34523
  for (const [rawName, path] of Object.entries(fileMappings)) {
34252
34524
  if (knownTokenPaths.has(path)) {
@@ -34321,6 +34593,20 @@ ${defaultDiagnostics.map((diagnostic) => ` ${diagnostic}`).join("\n")}
34321
34593
  const generatedCdf = Object.fromEntries(cdfEntries.map((c2) => [c2.key, c2.entry]));
34322
34594
  const tokenTree = rebuildDTCGTree(groups, tokens);
34323
34595
  const componentSourceRefs = await loadComponentSourceRefs(db, sessionId2);
34596
+ let existingTokensInline;
34597
+ if (opts.existingEntitiesPath) {
34598
+ const existingContentfulEntities = await readExistingContentfulEntitiesFromSession(
34599
+ resolve20(opts.existingEntitiesPath)
34600
+ );
34601
+ if (existingContentfulEntities) {
34602
+ existingTokensInline = JSON.stringify(summarizeForMapTokens(existingContentfulEntities));
34603
+ } else {
34604
+ process.stderr.write(
34605
+ `warn: --existing-entities-path ${opts.existingEntitiesPath} could not be read as JSON \u2014 proceeding without space-context enrichment
34606
+ `
34607
+ );
34608
+ }
34609
+ }
34324
34610
  if (opts.printPrompt) {
34325
34611
  const prompt3 = await buildPrompt({
34326
34612
  skill: "map-tokens",
@@ -34328,7 +34614,8 @@ ${defaultDiagnostics.map((diagnostic) => ` ${diagnostic}`).join("\n")}
34328
34614
  generatedCdf,
34329
34615
  tokenTree,
34330
34616
  componentSourceRefs,
34331
- outDir: process.cwd()
34617
+ outDir: process.cwd(),
34618
+ existingTokensInline
34332
34619
  });
34333
34620
  process.stdout.write(prompt3 + "\n");
34334
34621
  await exitWithAnalytics(0);
@@ -34346,7 +34633,13 @@ ${defaultDiagnostics.map((diagnostic) => ` ${diagnostic}`).join("\n")}
34346
34633
  }
34347
34634
  const agent = configuredAgent;
34348
34635
  const noCache = opts.cache === false || process.env.EDS_NO_CACHE === "1";
34349
- const promptHash = await hashPromptForSkill("map-tokens", agent, model);
34636
+ const promptHash = await hashPromptForSkill(
34637
+ "map-tokens",
34638
+ agent,
34639
+ model,
34640
+ void 0,
34641
+ existingTokensInline ? [hashContent(existingTokensInline)] : []
34642
+ );
34350
34643
  const inputHash = computeMapTokensInputHash(db, sessionId2, componentSourceRefs);
34351
34644
  if (!noCache) {
34352
34645
  const cached = lookupCache(db, inputHash, "token_mapping", "__map_tokens__", promptHash);
@@ -34373,7 +34666,8 @@ Install it, choose another agent with --agent, or use --print-prompt to run the
34373
34666
  generatedCdf,
34374
34667
  tokenTree,
34375
34668
  componentSourceRefs,
34376
- outDir: process.cwd()
34669
+ outDir: process.cwd(),
34670
+ existingTokensInline
34377
34671
  });
34378
34672
  const invoker3 = createLocalCliAgentInvoker();
34379
34673
  const result = await invoker3.invoke({ agent, model, prompt: prompt2, timeoutMs: DEFAULT_TIMEOUT_MS4 });
@@ -34400,7 +34694,10 @@ ${warnings.map((w) => ` ${w}`).join("\n")}
34400
34694
  }
34401
34695
  function registerMapTokensCommand(program) {
34402
34696
  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");
34697
+ 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(
34698
+ "--existing-entities-path <path>",
34699
+ "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."
34700
+ );
34404
34701
  addAgentModelOptions(tokensCmd).action(async (opts) => {
34405
34702
  await runMapTokens(opts);
34406
34703
  });
@@ -34409,45 +34706,22 @@ function registerMapTokensCommand(program) {
34409
34706
  // packages/experience-design-system-cli/src/import/command.ts
34410
34707
  init_src();
34411
34708
  init_path_utils();
34412
- import { resolve as resolve25, join as join25 } from "node:path";
34709
+ import { resolve as resolve26, join as join26 } from "node:path";
34413
34710
 
34414
34711
  // packages/experience-design-system-cli/src/import/orchestrator.ts
34415
34712
  init_db();
34416
34713
  init_command();
34417
34714
  init_manifest();
34418
34715
  init_api_client();
34419
- import { mkdir as mkdir5, writeFile as writeFile5 } from "node:fs/promises";
34420
- import { join as join18, resolve as resolve21 } from "node:path";
34421
- import { execFile as execFile2 } from "node:child_process";
34422
-
34423
- // packages/experience-design-system-cli/src/helpers/fetch-existing-entities.ts
34424
- import { fetchAll } from "contentful-management";
34425
- async function fetchExistingEntities(client2, params) {
34426
- const scope = { spaceId: params.spaceId, environmentId: params.environmentId, query: {} };
34427
- const components = await fetchAll(client2.component.getMany, scope);
34428
- const tokens = await fetchAll(client2.designToken.getMany, scope);
34429
- return { components, tokens };
34430
- }
34431
-
34432
- // packages/experience-design-system-cli/src/helpers/cma-client.ts
34433
- init_host_utils();
34434
- import { createClient as createClient2 } from "contentful-management";
34435
- function createCmaClient(opts) {
34436
- return createClient2(
34437
- {
34438
- accessToken: opts.cmaToken,
34439
- ...opts.host ? { host: toConfiguredHost(opts.host) } : {}
34440
- },
34441
- { type: "plain" }
34442
- );
34443
- }
34444
-
34445
- // packages/experience-design-system-cli/src/import/orchestrator.ts
34716
+ init_fetch_and_persist_existing_contentful_entities();
34446
34717
  init_contentful_urls();
34447
34718
  init_debug_logger();
34448
34719
  init_analytics();
34449
34720
  init_env();
34450
34721
  init_cli_path();
34722
+ import { mkdir as mkdir5 } from "node:fs/promises";
34723
+ import { join as join19, resolve as resolve22 } from "node:path";
34724
+ import { execFile as execFile2 } from "node:child_process";
34451
34725
  async function runStep(args, cliPath, analyticsSessionId, env = {}, streamStderr = false) {
34452
34726
  const debug = getDebugLogger();
34453
34727
  const startedAt = Date.now();
@@ -34532,9 +34806,9 @@ function buildPushStepResult(args) {
34532
34806
  };
34533
34807
  }
34534
34808
  async function runPipeline(opts, progressWriter, cliPathOverride) {
34535
- const projectRoot = resolve21(opts.project);
34536
- const outDir = resolve21(opts.out);
34537
- const componentsPath = join18(outDir, "components.json");
34809
+ const projectRoot = resolve22(opts.project);
34810
+ const outDir = resolve22(opts.out);
34811
+ const componentsPath = join19(outDir, "components.json");
34538
34812
  const cliPath = cliPathOverride ?? findCliPath();
34539
34813
  const db = openPipelineDb();
34540
34814
  const { sessionId: sessionId2 } = getOrCreateSession(db, void 0, void 0, {
@@ -34555,67 +34829,56 @@ async function runPipeline(opts, progressWriter, cliPathOverride) {
34555
34829
  await mkdir5(outDir, { recursive: true });
34556
34830
  const steps = [];
34557
34831
  let stepNum = 0;
34558
- const wantsSpaceContext = opts.withSpaceContext === true;
34559
- const canFetchSpaceContext = wantsSpaceContext && !!opts.spaceId && !!opts.environmentId && !!opts.cmaToken;
34560
- const totalSteps = 5 + (opts.print ? 1 : 0) + (canFetchSpaceContext ? 1 : 0);
34832
+ const canFetchExistingContentfulEntities = !!opts.spaceId && !!opts.environmentId && !!opts.cmaToken;
34833
+ const totalSteps = 5 + (opts.print ? 1 : 0) + (canFetchExistingContentfulEntities ? 1 : 0);
34561
34834
  function stepLabel(name) {
34562
34835
  stepNum++;
34563
34836
  return ` Step ${stepNum}/${totalSteps} ${name} `;
34564
34837
  }
34565
- if (wantsSpaceContext && !canFetchSpaceContext) {
34566
- progressWriter(
34567
- " Note: --with-space-context requires --space-id, --environment-id, and --cma-token; skipping context fetch."
34568
- );
34569
- }
34570
- if (canFetchSpaceContext) {
34838
+ let existingEntitiesPath;
34839
+ if (canFetchExistingContentfulEntities) {
34571
34840
  const fetchLabel = stepLabel("Fetching existing components + design tokens");
34572
34841
  const fetchStepId = createStep(db, sessionId2, "fetch existing entities", {
34573
34842
  spaceId: opts.spaceId,
34574
34843
  environmentId: opts.environmentId
34575
34844
  });
34576
- const t0 = Date.now();
34577
- try {
34578
- const cmaClient = createCmaClient({
34579
- cmaToken: opts.cmaToken,
34580
- ...opts.host ? { host: opts.host } : {}
34581
- });
34582
- const existingComponentsAndTokens = await fetchExistingEntities(cmaClient, {
34583
- spaceId: opts.spaceId,
34584
- environmentId: opts.environmentId
34585
- });
34586
- const fetchDurationMs = Date.now() - t0;
34587
- const existingEntitiesPath = join18(outDir, ".existing-entities.json");
34588
- await writeFile5(existingEntitiesPath, JSON.stringify(existingComponentsAndTokens, null, 2), "utf8");
34845
+ const result = await fetchAndPersistExistingContentfulEntities({
34846
+ spaceId: opts.spaceId,
34847
+ environmentId: opts.environmentId,
34848
+ cmaToken: opts.cmaToken,
34849
+ ...opts.host ? { host: opts.host } : {},
34850
+ outDir
34851
+ });
34852
+ if (result.ok) {
34853
+ existingEntitiesPath = result.path;
34589
34854
  updateStep(db, fetchStepId, "complete", {
34590
- components: String(existingComponentsAndTokens.components.length),
34591
- tokens: String(existingComponentsAndTokens.tokens.length),
34592
- path: existingEntitiesPath
34855
+ components: String(result.entities.components.length),
34856
+ tokens: String(result.entities.tokens.length),
34857
+ path: result.path
34593
34858
  });
34594
34859
  progressWriter(
34595
- `${fetchLabel}\u2713 ${existingComponentsAndTokens.components.length} component${existingComponentsAndTokens.components.length === 1 ? "" : "s"}, ${existingComponentsAndTokens.tokens.length} token${existingComponentsAndTokens.tokens.length === 1 ? "" : "s"} (${(fetchDurationMs / 1e3).toFixed(1)}s)`
34860
+ `${fetchLabel}\u2713 ${result.entities.components.length} component${result.entities.components.length === 1 ? "" : "s"}, ${result.entities.tokens.length} token${result.entities.tokens.length === 1 ? "" : "s"} (${(result.durationMs / 1e3).toFixed(1)}s)`
34596
34861
  );
34597
34862
  steps.push({
34598
34863
  step: "fetch existing entities",
34599
34864
  status: "complete",
34600
- durationMs: fetchDurationMs,
34865
+ durationMs: result.durationMs,
34601
34866
  detail: {
34602
- components: existingComponentsAndTokens.components.length,
34603
- tokens: existingComponentsAndTokens.tokens.length
34867
+ components: result.entities.components.length,
34868
+ tokens: result.entities.tokens.length
34604
34869
  }
34605
34870
  });
34606
- } catch (error) {
34607
- const fetchDurationMs = Date.now() - t0;
34608
- const message = error instanceof Error ? error.message : String(error);
34609
- updateStep(db, fetchStepId, "complete", {}, message);
34871
+ } else {
34872
+ updateStep(db, fetchStepId, "complete", {}, result.error);
34610
34873
  progressWriter(
34611
- `${fetchLabel}\u26A0 fetch failed, continuing without space context (${(fetchDurationMs / 1e3).toFixed(1)}s)`
34874
+ `${fetchLabel}\u26A0 fetch failed, continuing without space context (${(result.durationMs / 1e3).toFixed(1)}s)`
34612
34875
  );
34613
- progressWriter(` ${message.split("\n")[0]}`);
34876
+ progressWriter(` ${result.error.split("\n")[0]}`);
34614
34877
  steps.push({
34615
34878
  step: "fetch existing entities",
34616
34879
  status: "skipped",
34617
- durationMs: fetchDurationMs,
34618
- reason: `fetch failed: ${message.split("\n")[0]}`
34880
+ durationMs: result.durationMs,
34881
+ reason: `fetch failed: ${result.error.split("\n")[0]}`
34619
34882
  });
34620
34883
  }
34621
34884
  }
@@ -34701,6 +34964,7 @@ async function runPipeline(opts, progressWriter, cliPathOverride) {
34701
34964
  if (opts.excludeInvalid) editArgs.push("--exclude-invalid");
34702
34965
  if (opts.noCache) editArgs.push("--no-cache");
34703
34966
  if (opts.selectPromptPath) editArgs.push("--select-prompt-path", opts.selectPromptPath);
34967
+ if (existingEntitiesPath) editArgs.push("--existing-entities-path", existingEntitiesPath);
34704
34968
  } else {
34705
34969
  editArgs = ["analyze", "select", "--session", extractSessionId];
34706
34970
  if (opts.select && opts.select.length > 0) {
@@ -34763,6 +35027,7 @@ async function runPipeline(opts, progressWriter, cliPathOverride) {
34763
35027
  if (extractSessionId) generateArgs.push("--session", extractSessionId);
34764
35028
  if (opts.dryRun) generateArgs.push("--dry-run");
34765
35029
  if (opts.verbose) generateArgs.push("--verbose");
35030
+ if (existingEntitiesPath) generateArgs.push("--existing-entities-path", existingEntitiesPath);
34766
35031
  const stepId = createStep(db, sessionId2, "generate components", {
34767
35032
  extractSession: extractSessionId ?? ""
34768
35033
  });
@@ -34817,6 +35082,7 @@ async function runPipeline(opts, progressWriter, cliPathOverride) {
34817
35082
  if (opts.model) mapTokensArgs.push("--model", opts.model);
34818
35083
  if (opts.noCache) mapTokensArgs.push("--no-cache");
34819
35084
  if (opts.skipMapTokens) mapTokensArgs.push("--skip-agent");
35085
+ if (existingEntitiesPath) mapTokensArgs.push("--existing-entities-path", existingEntitiesPath);
34820
35086
  const mapTokensStepId = createStep(db, sessionId2, "map tokens", {
34821
35087
  extractSession: extractSessionId,
34822
35088
  skipAgent: String(opts.skipMapTokens === true)
@@ -35178,7 +35444,7 @@ init_host_utils();
35178
35444
  // packages/experience-design-system-cli/src/runs/replay-helpers.ts
35179
35445
  init_resolve_run_target();
35180
35446
  init_store();
35181
- import { resolve as resolve24 } from "node:path";
35447
+ import { resolve as resolve25 } from "node:path";
35182
35448
 
35183
35449
  // packages/experience-design-system-cli/src/runs/push-helpers.ts
35184
35450
  init_cli_path();
@@ -35368,7 +35634,7 @@ async function modifyRun(opts) {
35368
35634
  entryStep: "final-review",
35369
35635
  saveMode,
35370
35636
  ...run.compositionMode ? { compositionMode: run.compositionMode } : {},
35371
- ...opts.outDir ? { outDirOverride: resolve24(opts.outDir) } : {},
35637
+ ...opts.outDir ? { outDirOverride: resolve25(opts.outDir) } : {},
35372
35638
  ...mergedSpaceId ? { initialSpaceId: mergedSpaceId } : {},
35373
35639
  ...mergedEnvironmentId ? { initialEnvironmentId: mergedEnvironmentId } : {},
35374
35640
  ...mergedHost ? { initialHost: mergedHost } : {},
@@ -35445,7 +35711,7 @@ function resolvePromptFlags(flags) {
35445
35711
 
35446
35712
  // packages/experience-design-system-cli/src/runs/run-picker-mount.ts
35447
35713
  init_store();
35448
- import { readFile as readFile26 } from "node:fs/promises";
35714
+ import { readFile as readFile27 } from "node:fs/promises";
35449
35715
  function migrateRecord2(rec) {
35450
35716
  return {
35451
35717
  ...rec,
@@ -35468,7 +35734,7 @@ async function shouldShowRunPicker(input) {
35468
35734
  const path = input.runsJsonPath ?? runsFilePath();
35469
35735
  let raw;
35470
35736
  try {
35471
- raw = await readFile26(path, "utf8");
35737
+ raw = await readFile27(path, "utf8");
35472
35738
  } catch {
35473
35739
  return { shouldShow: false, runs: [] };
35474
35740
  }
@@ -35573,10 +35839,7 @@ function registerImportCommand(program) {
35573
35839
  "Override a stage prompt (repeatable). value is a file path or literal text, e.g. --prompt composition=./p.md",
35574
35840
  (v, acc) => [...acc, v],
35575
35841
  []
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(
35842
+ ).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
35843
  "--no-auto-filter",
35581
35844
  "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
35845
  ).option(
@@ -35844,7 +36107,7 @@ function registerImportCommand(program) {
35844
36107
  livePreview: opts.livePreview !== false,
35845
36108
  noPush: noPushRequested,
35846
36109
  noSave: opts.save === false,
35847
- ...opts.outDir ? { outDirOverride: resolve25(opts.outDir) } : {},
36110
+ ...opts.outDir ? { outDirOverride: resolve26(opts.outDir) } : {},
35848
36111
  ...opts.onConflict ? { onConflictMode: opts.onConflict } : {},
35849
36112
  selectPromptPath: opts.selectPromptPath ?? creds.selectPromptPath,
35850
36113
  generatePromptPath: opts.generatePromptPath ?? creds.generatePromptPath,
@@ -35885,7 +36148,7 @@ function registerImportCommand(program) {
35885
36148
  return;
35886
36149
  }
35887
36150
  const projectRoot = normalizePath(opts.project);
35888
- const outDir = opts.out ? resolve25(opts.out) : join25(projectRoot, ".contentful");
36151
+ const outDir = opts.out ? resolve26(opts.out) : join26(projectRoot, ".contentful");
35889
36152
  const headlessCreds = await readExperiencesCredentials();
35890
36153
  const headlessAgent = resolveAgent(opts.agent, headlessCreds.agent);
35891
36154
  const headlessModel = resolveModel(opts.model, headlessCreds.agentModel);
@@ -35923,7 +36186,6 @@ function registerImportCommand(program) {
35923
36186
  dryRun: dryRunForward,
35924
36187
  selectPromptPath: opts.selectPromptPath,
35925
36188
  autoRejectCycles: opts.autoRejectCycles ?? false,
35926
- withSpaceContext: opts.withSpaceContext ?? false,
35927
36189
  allowDeletions: opts.allowDeletions ?? false,
35928
36190
  compositionMode: headlessCompositionMode,
35929
36191
  ...opts.compositionMap ? { compositionMap: opts.compositionMap } : {},
@@ -35948,8 +36210,8 @@ function registerImportCommand(program) {
35948
36210
  // packages/experience-design-system-cli/src/setup/command.ts
35949
36211
  init_credentials_store();
35950
36212
  import { execFile as execFile5, spawn as spawn5 } from "node:child_process";
35951
- import { appendFile as appendFile2, readFile as readFile27, access as access10 } from "node:fs/promises";
35952
- import { join as join26 } from "node:path";
36213
+ import { appendFile as appendFile2, readFile as readFile28, access as access10 } from "node:fs/promises";
36214
+ import { join as join27 } from "node:path";
35953
36215
  import { homedir as homedir9 } from "node:os";
35954
36216
  import { fileURLToPath as fileURLToPath4 } from "node:url";
35955
36217
  import { createInterface } from "node:readline";
@@ -36027,10 +36289,10 @@ function prompt(question) {
36027
36289
  return Promise.resolve("");
36028
36290
  }
36029
36291
  const rl = createInterface({ input: process.stdin, output: process.stdout });
36030
- return new Promise((resolve27) => {
36292
+ return new Promise((resolve28) => {
36031
36293
  rl.question(question, (answer) => {
36032
36294
  rl.close();
36033
- resolve27(answer.trim());
36295
+ resolve28(answer.trim());
36034
36296
  });
36035
36297
  });
36036
36298
  }
@@ -36038,7 +36300,7 @@ function promptSecret(question) {
36038
36300
  if (!isInteractivePromptSession()) {
36039
36301
  return Promise.resolve("");
36040
36302
  }
36041
- return new Promise((resolve27) => {
36303
+ return new Promise((resolve28) => {
36042
36304
  const rl = createInterface({
36043
36305
  input: process.stdin,
36044
36306
  output: process.stdout,
@@ -36065,7 +36327,7 @@ function promptSecret(question) {
36065
36327
  }
36066
36328
  if (!process.stdin.isTTY) process.stdout.write("\n");
36067
36329
  process.stdin.resume();
36068
- resolve27(value);
36330
+ resolve28(value);
36069
36331
  });
36070
36332
  });
36071
36333
  }
@@ -36087,7 +36349,7 @@ async function binaryExists(name) {
36087
36349
  }
36088
36350
  }
36089
36351
  function runSpawn(cmd, args, opts = {}) {
36090
- return new Promise((resolve27) => {
36352
+ return new Promise((resolve28) => {
36091
36353
  const child = spawn5(cmd, args, {
36092
36354
  cwd: opts.cwd,
36093
36355
  env: opts.env ?? process.env,
@@ -36099,7 +36361,7 @@ function runSpawn(cmd, args, opts = {}) {
36099
36361
  child.on("error", (err) => {
36100
36362
  if (!settled) {
36101
36363
  settled = true;
36102
- resolve27({ exitCode: 1, stdout: "", stderr: err.message });
36364
+ resolve28({ exitCode: 1, stdout: "", stderr: err.message });
36103
36365
  }
36104
36366
  });
36105
36367
  child.stdout.on("data", (d) => {
@@ -36111,7 +36373,7 @@ function runSpawn(cmd, args, opts = {}) {
36111
36373
  child.on("exit", (code) => {
36112
36374
  if (!settled) {
36113
36375
  settled = true;
36114
- resolve27({ exitCode: code ?? 1, stdout, stderr });
36376
+ resolve28({ exitCode: code ?? 1, stdout, stderr });
36115
36377
  }
36116
36378
  });
36117
36379
  });
@@ -36120,21 +36382,21 @@ async function detectShellProfile() {
36120
36382
  const shell = process.env["SHELL"] ?? "";
36121
36383
  const home = homedir9();
36122
36384
  if (shell.includes("zsh")) {
36123
- return join26(home, ".zshrc");
36385
+ return join27(home, ".zshrc");
36124
36386
  }
36125
36387
  if (shell.includes("bash")) {
36126
- const bashProfile = join26(home, ".bash_profile");
36388
+ const bashProfile = join27(home, ".bash_profile");
36127
36389
  const exists = await access10(bashProfile).then(() => true).catch(() => false);
36128
- return exists ? bashProfile : join26(home, ".bashrc");
36390
+ return exists ? bashProfile : join27(home, ".bashrc");
36129
36391
  }
36130
36392
  if (shell.includes("fish")) {
36131
- return join26(home, ".config", "fish", "config.fish");
36393
+ return join27(home, ".config", "fish", "config.fish");
36132
36394
  }
36133
- return join26(home, ".profile");
36395
+ return join27(home, ".profile");
36134
36396
  }
36135
36397
  async function profileContains(profilePath, str) {
36136
36398
  try {
36137
- const content = await readFile27(profilePath, "utf8");
36399
+ const content = await readFile28(profilePath, "utf8");
36138
36400
  return content.includes(str);
36139
36401
  } catch {
36140
36402
  return false;
@@ -36155,7 +36417,7 @@ async function setupNode() {
36155
36417
  }
36156
36418
  fail(`Node.js v${current} \u2014 need v${REQUIRED_NODE_MAJOR}+`);
36157
36419
  info("");
36158
- const hasNvm = await binaryExists("nvm") || await access10(join26(homedir9(), ".nvm", "nvm.sh")).then(() => true).catch(() => false);
36420
+ const hasNvm = await binaryExists("nvm") || await access10(join27(homedir9(), ".nvm", "nvm.sh")).then(() => true).catch(() => false);
36159
36421
  const hasFnm = await binaryExists("fnm");
36160
36422
  if (hasNvm) {
36161
36423
  info(`nvm detected. Will run: nvm install ${REQUIRED_NODE_MAJOR} && nvm use ${REQUIRED_NODE_MAJOR}`);
@@ -36164,7 +36426,7 @@ async function setupNode() {
36164
36426
  warn(`Skipped. Re-run experiences setup after switching to Node ${REQUIRED_NODE_MAJOR}.`);
36165
36427
  return false;
36166
36428
  }
36167
- const nvmScript = join26(homedir9(), ".nvm", "nvm.sh");
36429
+ const nvmScript = join27(homedir9(), ".nvm", "nvm.sh");
36168
36430
  const result = await runSpawn("bash", [
36169
36431
  "-c",
36170
36432
  `source "${nvmScript}" && nvm install ${REQUIRED_NODE_MAJOR} && nvm alias default ${REQUIRED_NODE_MAJOR}`
@@ -36631,13 +36893,13 @@ async function checkPnpm(pkgRoot) {
36631
36893
  }
36632
36894
  async function checkDependencies(pkgRoot) {
36633
36895
  section("Checking dependencies (pnpm install)");
36634
- const nodeModulesExists = await access10(join26(pkgRoot, "node_modules")).then(() => true).catch(() => false);
36896
+ const nodeModulesExists = await access10(join27(pkgRoot, "node_modules")).then(() => true).catch(() => false);
36635
36897
  if (!nodeModulesExists) {
36636
36898
  info("node_modules not found \u2014 running pnpm install...");
36637
36899
  } else {
36638
36900
  info("Running pnpm install to ensure dependencies are up to date...");
36639
36901
  }
36640
- const repoRoot = join26(pkgRoot, "..", "..");
36902
+ const repoRoot = join27(pkgRoot, "..", "..");
36641
36903
  const result = await runSpawn("pnpm", ["install", "--frozen-lockfile"], { cwd: repoRoot });
36642
36904
  if (result.exitCode !== 0) {
36643
36905
  fail("pnpm install failed");
@@ -36656,7 +36918,7 @@ async function checkDependencies(pkgRoot) {
36656
36918
  async function checkBuild(pkgRoot) {
36657
36919
  section("Building CLI");
36658
36920
  info("Running pnpm build...");
36659
- const repoRoot = join26(pkgRoot, "..", "..");
36921
+ const repoRoot = join27(pkgRoot, "..", "..");
36660
36922
  const result = await runSpawn("pnpm", ["--filter", "@contentful/experience-design-system-cli", "run", "build"], {
36661
36923
  cwd: repoRoot
36662
36924
  });
@@ -36772,7 +37034,7 @@ function registerSetupCommand(program) {
36772
37034
  process.stdout.write("\n\x1B[1mexperiences setup\x1B[0m \u2014 interactive setup wizard\n");
36773
37035
  process.stdout.write("Sets up everything you need to run \x1B[1mexperiences import\x1B[0m.\n");
36774
37036
  const pkgRoot = findPkgRoot();
36775
- const repoRoot = join26(pkgRoot, "..", "..");
37037
+ const repoRoot = join27(pkgRoot, "..", "..");
36776
37038
  const profilePath = await detectShellProfile();
36777
37039
  const results = [];
36778
37040
  const nodeOk = await setupNode();
@@ -37012,7 +37274,7 @@ async function beginCommand(command, opts) {
37012
37274
  init_analytics();
37013
37275
  init_credentials_store();
37014
37276
  init_cli_path();
37015
- var pkg3 = JSON.parse(readFileSync10(join27(findPkgRoot(), "package.json"), "utf8"));
37277
+ var pkg3 = JSON.parse(readFileSync10(join28(findPkgRoot(), "package.json"), "utf8"));
37016
37278
  async function runBuild(opts) {
37017
37279
  return new Promise((resolvePromise) => {
37018
37280
  const child = opts.spawnFn();
@@ -37049,7 +37311,7 @@ function registerImportV2Command(program) {
37049
37311
  }
37050
37312
  function registerBuildCommand(program) {
37051
37313
  program.command("build").description("Rebuild from source and re-link exo/experiences binaries to this build").action(async () => {
37052
- const pkgRoot = resolve26(dirname14(fileURLToPath5(import.meta.url)), "..", "..");
37314
+ const pkgRoot = resolve27(dirname14(fileURLToPath5(import.meta.url)), "..", "..");
37053
37315
  process.stderr.write("\u2699 Building from source...\n");
37054
37316
  const { exitCode } = await runBuild({
37055
37317
  spawnFn: () => spawn6("pnpm", ["build"], { cwd: pkgRoot, stdio: "inherit" }),