@contentful/experience-design-system-cli 2.37.1-dev-build-f57f8147.0 → 2.37.1-dev-build-3c845a01.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/app.js CHANGED
@@ -837,7 +837,7 @@ async function runAgent(options) {
837
837
  promptLen: prompt.length,
838
838
  promptHead: prompt.slice(0, 500)
839
839
  });
840
- return new Promise((resolve27) => {
840
+ return new Promise((resolve26) => {
841
841
  const bedrockEnv = bedrock ? BEDROCK_ENV_BY_AGENT[agent] : void 0;
842
842
  const child = spawn(binary, args, {
843
843
  stdio: ["pipe", "pipe", "pipe"],
@@ -886,7 +886,7 @@ async function runAgent(options) {
886
886
  stderrLen: stderr.length,
887
887
  stderrTail: stderr.slice(-1e3)
888
888
  });
889
- resolve27(result);
889
+ resolve26(result);
890
890
  });
891
891
  });
892
892
  }
@@ -908,7 +908,7 @@ async function checkAgentAuth(agent) {
908
908
  return "not-found";
909
909
  if (agent !== "claude")
910
910
  return "ok";
911
- return new Promise((resolve27) => {
911
+ return new Promise((resolve26) => {
912
912
  const child = spawn2(binary, ["auth", "status", "--json"], { stdio: ["ignore", "pipe", "pipe"] });
913
913
  let stdout = "";
914
914
  let done = false;
@@ -917,7 +917,7 @@ async function checkAgentAuth(agent) {
917
917
  return;
918
918
  done = true;
919
919
  child.kill("SIGTERM");
920
- resolve27("unauthenticated");
920
+ resolve26("unauthenticated");
921
921
  }, 5e3);
922
922
  child.stdout?.on("data", (chunk) => {
923
923
  stdout += chunk.toString();
@@ -928,14 +928,14 @@ async function checkAgentAuth(agent) {
928
928
  done = true;
929
929
  clearTimeout(timer);
930
930
  if (code !== 0) {
931
- resolve27("unauthenticated");
931
+ resolve26("unauthenticated");
932
932
  return;
933
933
  }
934
934
  try {
935
935
  const status = JSON.parse(stdout);
936
- resolve27(status.loggedIn ? "ok" : "unauthenticated");
936
+ resolve26(status.loggedIn ? "ok" : "unauthenticated");
937
937
  } catch {
938
- resolve27("unauthenticated");
938
+ resolve26("unauthenticated");
939
939
  }
940
940
  });
941
941
  });
@@ -945,9 +945,9 @@ async function binaryIsOnPath(binary) {
945
945
  const fs = await import("node:fs/promises");
946
946
  return fs.access(binary).then(() => true, () => false);
947
947
  }
948
- return new Promise((resolve27) => {
948
+ return new Promise((resolve26) => {
949
949
  const child = spawn2(process.platform === "win32" ? "where" : "which", [binary], { stdio: "ignore" });
950
- child.on("close", (code) => resolve27(code === 0));
950
+ child.on("close", (code) => resolve26(code === 0));
951
951
  });
952
952
  }
953
953
  var init_check_agent_auth = __esm({
@@ -2141,12 +2141,11 @@ __export(debug_store_exports, {
2141
2141
  currentSessionDir: () => currentSessionDir,
2142
2142
  finishDebugRun: () => finishDebugRun,
2143
2143
  startDebugRun: () => startDebugRun,
2144
- startDebugSessionIn: () => startDebugSessionIn,
2145
- startImportRun: () => startImportRun
2144
+ startDebugSessionIn: () => startDebugSessionIn
2146
2145
  });
2147
- import { mkdir as mkdir9, writeFile as writeFile8 } from "node:fs/promises";
2148
- import { existsSync as existsSync9, readdirSync as readdirSync4 } from "node:fs";
2149
- import { join as join24, resolve as resolve26 } from "node:path";
2146
+ import { mkdir as mkdir8, writeFile as writeFile7 } from "node:fs/promises";
2147
+ import { existsSync as existsSync9, readdirSync as readdirSync3 } from "node:fs";
2148
+ import { join as join20, resolve as resolve23 } from "node:path";
2150
2149
  function generateRunId() {
2151
2150
  const now = /* @__PURE__ */ new Date();
2152
2151
  const pad = (n) => String(n).padStart(2, "0");
@@ -2162,14 +2161,14 @@ function slugify(value) {
2162
2161
  async function readBaseDir() {
2163
2162
  try {
2164
2163
  const dir = (await readSettings2())["contentfulBaseDir"];
2165
- return typeof dir === "string" && dir !== "" ? resolve26(dir) : void 0;
2164
+ return typeof dir === "string" && dir !== "" ? resolve23(dir) : void 0;
2166
2165
  } catch {
2167
2166
  return void 0;
2168
2167
  }
2169
2168
  }
2170
2169
  function nextSessionId(contentfulDir) {
2171
2170
  const today = datePrefix();
2172
- const existing = existsSync9(contentfulDir) ? readdirSync4(contentfulDir) : [];
2171
+ const existing = existsSync9(contentfulDir) ? readdirSync3(contentfulDir) : [];
2173
2172
  const seqPattern = new RegExp(`^${today}-session-(\\d+)$`);
2174
2173
  const maxSeq = existing.reduce((max, entry) => {
2175
2174
  const match2 = seqPattern.exec(entry);
@@ -2178,12 +2177,12 @@ function nextSessionId(contentfulDir) {
2178
2177
  return `${today}-session-${maxSeq + 1}`;
2179
2178
  }
2180
2179
  function startSession(base, { replace }) {
2181
- const contentfulDir = join24(base, ".contentful");
2182
- if (replace || !sessionDir) sessionDir = join24(contentfulDir, nextSessionId(contentfulDir));
2180
+ const contentfulDir = join20(base, ".contentful");
2181
+ if (replace || !sessionDir) sessionDir = join20(contentfulDir, nextSessionId(contentfulDir));
2183
2182
  return sessionDir;
2184
2183
  }
2185
2184
  function currentDebugSessionDir() {
2186
- return sessionDir && join24(sessionDir, "debug");
2185
+ return sessionDir && join20(sessionDir, "debug");
2187
2186
  }
2188
2187
  function currentSessionDir() {
2189
2188
  return sessionDir;
@@ -2191,25 +2190,10 @@ function currentSessionDir() {
2191
2190
  async function startDebugSessionIn(base, { replace = false } = {}) {
2192
2191
  try {
2193
2192
  if (!await isDebugModeEnabled()) return;
2194
- await mkdir9(join24(startSession(resolve26(base), { replace }), "debug"), { recursive: true });
2193
+ await mkdir8(join20(startSession(resolve23(base), { replace }), "debug"), { recursive: true });
2195
2194
  } catch {
2196
2195
  }
2197
2196
  }
2198
- function nextImportRunDir(session) {
2199
- const existing = existsSync9(session) ? readdirSync4(session) : [];
2200
- const maxRun = existing.reduce((max, entry) => {
2201
- const match2 = /^dsi-import-(\d+)$/.exec(entry);
2202
- return match2 ? Math.max(max, Number(match2[1])) : max;
2203
- }, 0);
2204
- return join24(session, `dsi-import-${maxRun + 1}`);
2205
- }
2206
- async function startImportRun(projectPath) {
2207
- await startDebugSessionIn(projectPath);
2208
- if (!sessionDir) return join24(resolve26(projectPath), ".contentful");
2209
- const dir = nextImportRunDir(sessionDir);
2210
- await mkdir9(dir, { recursive: true });
2211
- return dir;
2212
- }
2213
2197
  async function isDebugModeEnabled() {
2214
2198
  try {
2215
2199
  return (await readDebugModeSetting()).enabled;
@@ -2252,15 +2236,15 @@ async function finishDebugRun({
2252
2236
  const root = currentDebugSessionDir();
2253
2237
  if (!root) return;
2254
2238
  const flowSegments = run.flow.split("/");
2255
- const dir = join24(root, ...flowSegments);
2256
- await mkdir9(dir, { recursive: true });
2239
+ const dir = join20(root, ...flowSegments);
2240
+ await mkdir8(dir, { recursive: true });
2257
2241
  const filename = nextAttemptFilename(dir, run.menuOption);
2258
- await writeFile8(join24(dir, filename), content, { mode: 384 });
2242
+ await writeFile7(join20(dir, filename), content, { mode: 384 });
2259
2243
  }
2260
2244
  function nextAttemptFilename(dir, menuOption) {
2261
2245
  const today = datePrefix();
2262
2246
  const optionSlug = slugify(menuOption);
2263
- const existing = existsSync9(dir) ? readdirSync4(dir) : [];
2247
+ const existing = existsSync9(dir) ? readdirSync3(dir) : [];
2264
2248
  const attemptPattern = new RegExp(`^${today}-${optionSlug}-attempt-(\\d+)\\.md$`);
2265
2249
  const maxAttempt = existing.reduce((max, entry) => {
2266
2250
  const match2 = attemptPattern.exec(entry);
@@ -2308,7 +2292,7 @@ var init_debug_store = __esm({
2308
2292
  init_debug_mode_store();
2309
2293
  void Promise.all([isDebugModeEnabled(), readBaseDir()]).then(([enabled, base]) => {
2310
2294
  if (!enabled || !base) return void 0;
2311
- return mkdir9(join24(startSession(base, { replace: false }), "debug"), { recursive: true });
2295
+ return mkdir8(join20(startSession(base, { replace: false }), "debug"), { recursive: true });
2312
2296
  });
2313
2297
  process.once("uncaughtException", (err) => {
2314
2298
  void handleCrash().finally(() => {
@@ -13770,7 +13754,7 @@ function errorMessage(error) {
13770
13754
  return error instanceof Error && error.message ? error.message : String(error);
13771
13755
  }
13772
13756
  function defaultSleep(delayMs) {
13773
- return new Promise((resolve27) => setTimeout(resolve27, delayMs));
13757
+ return new Promise((resolve26) => setTimeout(resolve26, delayMs));
13774
13758
  }
13775
13759
 
13776
13760
  // packages/experience-design-system-backend-pipeline/dist/src/steps/apply/src/helpers/sanitize-preview.js
@@ -14011,7 +13995,7 @@ var ApiClient = class {
14011
13995
  const progress = maxAttempts > 1 ? attempt / (maxAttempts - 1) : 0;
14012
13996
  const baseDelay = intervalMs + (maxIntervalMs - intervalMs) * progress;
14013
13997
  const jitter = Math.random() * baseDelay * 0.15;
14014
- await new Promise((resolve27) => setTimeout(resolve27, baseDelay + jitter));
13998
+ await new Promise((resolve26) => setTimeout(resolve26, baseDelay + jitter));
14015
13999
  }
14016
14000
  }
14017
14001
  throw new Error(`Operation ${operationId} timed out after ${maxAttempts} attempts`);
@@ -16124,7 +16108,7 @@ async function retryDatabaseWrite(operation, attempts = 8) {
16124
16108
  const message = error instanceof Error ? error.message : String(error);
16125
16109
  if (!/database is locked|database is busy/i.test(message) || attempt >= attempts)
16126
16110
  throw error;
16127
- await new Promise((resolve27) => setTimeout(resolve27, Math.min(250 * attempt, 2e3)));
16111
+ await new Promise((resolve26) => setTimeout(resolve26, Math.min(250 * attempt, 2e3)));
16128
16112
  }
16129
16113
  }
16130
16114
  }
@@ -17296,34 +17280,11 @@ function RunningStep({
17296
17280
  }
17297
17281
 
17298
17282
  // packages/experience-design-system-cli/src/tui/import/steps/05-token-reuse/logic.ts
17299
- import { access as access5, readdir as readdir2, stat as stat4 } from "node:fs/promises";
17283
+ import { access as access5, stat as stat4 } from "node:fs/promises";
17300
17284
  import { join as join16 } from "node:path";
17301
- async function findLatestTokens(contentfulDir) {
17302
- const candidates = [join16(contentfulDir, "tokens.json")];
17303
- try {
17304
- for (const session of await readdir2(contentfulDir, { withFileTypes: true })) {
17305
- if (!session.isDirectory()) continue;
17306
- for (const run of await readdir2(join16(contentfulDir, session.name), { withFileTypes: true }).catch(() => [])) {
17307
- if (run.isDirectory() && /^dsi-import-\d+$/.test(run.name)) {
17308
- candidates.push(join16(contentfulDir, session.name, run.name, "tokens.json"));
17309
- }
17310
- }
17311
- }
17312
- } catch {
17313
- }
17314
- const found = [];
17315
- for (const path5 of candidates) {
17316
- try {
17317
- found.push({ path: path5, mtimeMs: (await stat4(path5)).mtimeMs });
17318
- } catch {
17319
- }
17320
- }
17321
- return found.sort((a, b) => b.mtimeMs - a.mtimeMs)[0]?.path ?? null;
17322
- }
17323
- async function inspectTokens({ rawTokensPath, contentfulDir, cache }) {
17285
+ async function inspectTokens({ rawTokensPath, outDir, cache }) {
17324
17286
  if (!cache) return { kind: "none" };
17325
- const tokensPath = await findLatestTokens(contentfulDir);
17326
- if (!tokensPath) return { kind: "none" };
17287
+ const tokensPath = join16(outDir, "tokens.json");
17327
17288
  try {
17328
17289
  await access5(tokensPath);
17329
17290
  } catch {
@@ -17602,7 +17563,7 @@ var realDeps = {
17602
17563
  var fail = (step, message) => ({ ok: false, step, message });
17603
17564
  var errorMessage2 = (error) => error instanceof Error ? error.message : String(error);
17604
17565
  async function runExtraction(input, onProgress, deps = realDeps) {
17605
- const outDir = input.outDir ?? join19(resolve22(input.projectPath), ".contentful");
17566
+ const outDir = join19(resolve22(input.projectPath), ".contentful");
17606
17567
  let progress = initialProgress({
17607
17568
  hasCredentials: input.credentials !== null,
17608
17569
  hasRawTokens: input.rawTokensPath !== "",
@@ -17751,6 +17712,7 @@ function useExtraction(input) {
17751
17712
  reuseTokens: input.tokenStrategy === "reuse"
17752
17713
  })
17753
17714
  });
17715
+ void Promise.resolve().then(() => (init_debug_store(), debug_store_exports)).then((store) => store.startDebugSessionIn(input.projectPath));
17754
17716
  void runExtraction(input, (progress) => {
17755
17717
  if (current.current === input) setState({ status: "running", progress });
17756
17718
  }).then((result) => {
@@ -20637,7 +20599,7 @@ function GenerationScreen({
20637
20599
  import { useEffect as useEffect9, useRef as useRef6, useState as useState14 } from "react";
20638
20600
 
20639
20601
  // packages/experience-design-system-cli/src/tui/import/steps/08-generation/run.ts
20640
- import { resolve as resolve23 } from "node:path";
20602
+ import { resolve as resolve24 } from "node:path";
20641
20603
 
20642
20604
  // packages/experience-design-system-cli/src/tui/import/steps/08-generation/map-tokens.ts
20643
20605
  async function prepareMapTokens(input, generatedSessionId) {
@@ -20772,7 +20734,7 @@ async function buildMapTokensOptions(input) {
20772
20734
  if (mapOverride?.kind === "text") prompt.skillContentOverride = mapOverride.value;
20773
20735
  if (mapOverride?.kind === "path") {
20774
20736
  await resolvePromptOverride(mapOverride);
20775
- prompt.skillPathOverride = resolve23(mapOverride.value);
20737
+ prompt.skillPathOverride = resolve24(mapOverride.value);
20776
20738
  }
20777
20739
  if (input.existingEntitiesPath) {
20778
20740
  const entities = await readExistingContentfulEntitiesFromSession({ path: input.existingEntitiesPath });
@@ -20820,7 +20782,7 @@ function useGeneration(input) {
20820
20782
  }
20821
20783
 
20822
20784
  // packages/experience-design-system-cli/src/tui/import/steps/10-flow/flow/build-flow-start.ts
20823
- import { join as join20 } from "node:path";
20785
+ import { join as join21 } from "node:path";
20824
20786
  function buildFlowStart(input) {
20825
20787
  const { extraction, handoff, saved, generatePromptPath } = input;
20826
20788
  const credentials = extraction.credentials ?? {
@@ -20833,7 +20795,7 @@ function buildFlowStart(input) {
20833
20795
  handoff,
20834
20796
  agent: extraction.agent,
20835
20797
  projectPath: extraction.projectPath,
20836
- outDir: extraction.projectPath ? join20(extraction.projectPath, ".contentful") : "",
20798
+ outDir: extraction.projectPath ? join21(extraction.projectPath, ".contentful") : "",
20837
20799
  rawTokensPath: extraction.rawTokensPath,
20838
20800
  credentials: {
20839
20801
  spaceId: credentials.spaceId,
@@ -26576,11 +26538,11 @@ function DoneStep({
26576
26538
  // packages/experience-design-system-cli/src/tui/import/steps/10-flow/screens/PathPrompt.tsx
26577
26539
  import { useState as useState24 } from "react";
26578
26540
  import { Box as Box37, Text as Text40 } from "ink";
26579
- import { readdirSync as readdirSync3 } from "node:fs";
26580
- import { dirname as dirname15, basename as basename6, join as join21 } from "node:path";
26541
+ import { readdirSync as readdirSync4 } from "node:fs";
26542
+ import { dirname as dirname15, basename as basename6, join as join22 } from "node:path";
26581
26543
 
26582
26544
  // packages/experience-design-system-cli/src/tui/import/steps/10-flow/support/path-utils.ts
26583
- import { resolve as resolve24 } from "node:path";
26545
+ import { resolve as resolve25 } from "node:path";
26584
26546
  import { homedir as homedir4 } from "node:os";
26585
26547
  function expandTilde(input) {
26586
26548
  if (input === "~" || input.startsWith("~/") || input.startsWith("~\\")) {
@@ -26594,7 +26556,7 @@ function normalizePath(input) {
26594
26556
  p = p.slice(1, -1);
26595
26557
  }
26596
26558
  p = expandTilde(p);
26597
- return resolve24(p);
26559
+ return resolve25(p);
26598
26560
  }
26599
26561
 
26600
26562
  // packages/experience-design-system-cli/src/tui/import/steps/10-flow/support/use-blinking-cursor.ts
@@ -26617,19 +26579,19 @@ function autocomplete(partial) {
26617
26579
  const base = basename6(normalized);
26618
26580
  let entries;
26619
26581
  try {
26620
- entries = readdirSync3(dir);
26582
+ entries = readdirSync4(dir);
26621
26583
  } catch {
26622
26584
  return null;
26623
26585
  }
26624
26586
  const matches = entries.filter((e) => e.startsWith(base));
26625
26587
  if (matches.length === 0) return null;
26626
- if (matches.length === 1) return join21(dir, matches[0]);
26588
+ if (matches.length === 1) return join22(dir, matches[0]);
26627
26589
  let prefix = matches[0];
26628
26590
  for (const m of matches) {
26629
26591
  while (!m.startsWith(prefix)) prefix = prefix.slice(0, -1);
26630
26592
  if (!prefix) break;
26631
26593
  }
26632
- return prefix.length > base.length ? join21(dir, prefix) : null;
26594
+ return prefix.length > base.length ? join22(dir, prefix) : null;
26633
26595
  }
26634
26596
  function PathPrompt({
26635
26597
  defaultPath,
@@ -27388,9 +27350,9 @@ import { useEffect as useEffect21, useRef as useRef13, useSyncExternalStore } fr
27388
27350
 
27389
27351
  // packages/experience-design-system-cli/src/tui/import/steps/10-flow/flow/controller.ts
27390
27352
  import { appendFileSync, writeFileSync } from "node:fs";
27391
- import { mkdir as mkdir8 } from "node:fs/promises";
27353
+ import { mkdir as mkdir9 } from "node:fs/promises";
27392
27354
  import { tmpdir } from "node:os";
27393
- import { join as join23, resolve as resolve25 } from "node:path";
27355
+ import { join as join24 } from "node:path";
27394
27356
 
27395
27357
  // packages/experience-design-system-cli/src/tui/import/steps/10-flow/support/wizard-state-transitions.ts
27396
27358
  function shouldBypassPreview(state) {
@@ -27734,8 +27696,8 @@ function pushFailure(e, deps) {
27734
27696
  }
27735
27697
 
27736
27698
  // packages/experience-design-system-cli/src/tui/import/steps/10-flow/flow/save.ts
27737
- import { writeFile as writeFile7 } from "node:fs/promises";
27738
- import { join as join22 } from "node:path";
27699
+ import { writeFile as writeFile8 } from "node:fs/promises";
27700
+ import { join as join23 } from "node:path";
27739
27701
 
27740
27702
  // packages/experience-design-system-cli/src/tui/import/steps/10-flow/support/run-print-files-helpers.ts
27741
27703
  function nextStateAfterPrint(opts) {
@@ -27758,15 +27720,15 @@ function buildSavedCDF(components, tokens, opts = {}) {
27758
27720
  var realSaveDeps = () => ({
27759
27721
  openDb: openPipelineDb,
27760
27722
  readTokens: (path5) => readTokensFromPath2({ flag: "tokens", path: path5 }),
27761
- writeFile: (path5, contents) => writeFile7(path5, contents),
27723
+ writeFile: (path5, contents) => writeFile8(path5, contents),
27762
27724
  appendRun,
27763
27725
  buildSourceFingerprint,
27764
- sleep: (ms) => new Promise((resolve27) => setTimeout(resolve27, ms)),
27726
+ sleep: (ms) => new Promise((resolve26) => setTimeout(resolve26, ms)),
27765
27727
  warn: (message) => process.stderr.write(message)
27766
27728
  });
27767
27729
  async function runPrintFiles(input, deps, onPatch) {
27768
27730
  onPatch({ step: "printing" });
27769
- const componentsPath = join22(input.outDir, "components.json");
27731
+ const componentsPath = join23(input.outDir, "components.json");
27770
27732
  try {
27771
27733
  const db = deps.openDb();
27772
27734
  let components = [];
@@ -27847,7 +27809,7 @@ var EMPTY_PUSH_RESULT = {
27847
27809
  };
27848
27810
 
27849
27811
  // packages/experience-design-system-cli/src/tui/import/steps/10-flow/flow/controller.ts
27850
- var WIZARD_LOG = join23(tmpdir(), "experiences-import-wizard.log");
27812
+ var WIZARD_LOG = join24(tmpdir(), "experiences-import-wizard.log");
27851
27813
  function appendWizardLog(entry) {
27852
27814
  appendFileSync(WIZARD_LOG, JSON.stringify({ ts: (/* @__PURE__ */ new Date()).toISOString(), ...entry }) + "\n");
27853
27815
  }
@@ -27855,6 +27817,9 @@ function startWizardLog() {
27855
27817
  writeFileSync(WIZARD_LOG, `--- experiences import session ${(/* @__PURE__ */ new Date()).toISOString()} ---
27856
27818
  `);
27857
27819
  }
27820
+ async function realSessionDir() {
27821
+ return (await Promise.resolve().then(() => (init_debug_store(), debug_store_exports))).currentSessionDir();
27822
+ }
27858
27823
  function realFlowDeps() {
27859
27824
  const log = (entry) => appendWizardLog(entry);
27860
27825
  return {
@@ -27870,13 +27835,14 @@ function realFlowDeps() {
27870
27835
  }
27871
27836
  },
27872
27837
  mkdir: async (path5) => {
27873
- await mkdir8(path5, { recursive: true });
27838
+ await mkdir9(path5, { recursive: true });
27874
27839
  },
27875
27840
  detectSaveConflict,
27876
27841
  buildTimestampedSubdir,
27877
27842
  rejectComponentsByName,
27878
27843
  log,
27879
- stderr: (text) => process.stderr.write(text)
27844
+ stderr: (text) => process.stderr.write(text),
27845
+ sessionDir: realSessionDir
27880
27846
  };
27881
27847
  }
27882
27848
  function initialFlowState(start) {
@@ -28017,6 +27983,9 @@ function createFlowController(start, deps) {
28017
27983
  const startSave = (opts, patch = {}) => {
28018
27984
  pendingSave = opts;
28019
27985
  update({ ...patch, step: "path-prompt" });
27986
+ void deps.sessionDir?.().then((session) => {
27987
+ if (session && state.step === "path-prompt") update({ outDir: join24(session, "dsi-import") });
27988
+ });
28020
27989
  };
28021
27990
  const proceedToWrite = async (path5) => {
28022
27991
  update({ outDir: path5 });
@@ -28089,7 +28058,7 @@ function createFlowController(start, deps) {
28089
28058
  },
28090
28059
  async submitPath(submitted) {
28091
28060
  await deps.mkdir(submitted);
28092
- if (resolve25(submitted) !== resolve25(state.outDir) && await deps.detectSaveConflict(submitted)) {
28061
+ if (await deps.detectSaveConflict(submitted)) {
28093
28062
  const subdir = deps.buildTimestampedSubdir(submitted);
28094
28063
  await deps.mkdir(subdir);
28095
28064
  await proceedToWrite(subdir);
@@ -28738,7 +28707,7 @@ function App({ importOptions, inkClear }) {
28738
28707
  const launch = { projectPath: projectPath2, tokens, filePaths, ...importOptions };
28739
28708
  const state = await inspectTokens({
28740
28709
  rawTokensPath: tokens,
28741
- contentfulDir: join25(resolveUserPath(projectPath2), ".contentful"),
28710
+ outDir: join25(resolveUserPath(projectPath2), ".contentful"),
28742
28711
  cache: importOptions.cache
28743
28712
  });
28744
28713
  if (state.kind === "cached") {
@@ -28759,7 +28728,6 @@ function App({ importOptions, inkClear }) {
28759
28728
  const settings = await readSettings2();
28760
28729
  const { agent, agentModel } = resolveAgentChoice(launch.agent, settings);
28761
28730
  const generatePromptPath = typeof settings.generatePromptPath === "string" ? settings.generatePromptPath : void 0;
28762
- const outDir = await (await Promise.resolve().then(() => (init_debug_store(), debug_store_exports))).startImportRun(resolveUserPath(launch.projectPath ?? ""));
28763
28731
  setExtractionRun({
28764
28732
  ...generatePromptPath ? { generatePromptPath } : {},
28765
28733
  // the later steps get the same agent, so they use what the stage used
@@ -28768,7 +28736,6 @@ function App({ importOptions, inkClear }) {
28768
28736
  tokenStrategy,
28769
28737
  input: {
28770
28738
  projectPath: resolveUserPath(launch.projectPath ?? ""),
28771
- outDir,
28772
28739
  filePaths: launch.filePaths ?? [],
28773
28740
  rawTokensPath: launch.tokens ?? "",
28774
28741
  tokenStrategy,
package/dist/index.js CHANGED
@@ -2121,7 +2121,7 @@ async function runAgent(options) {
2121
2121
  promptLen: prompt.length,
2122
2122
  promptHead: prompt.slice(0, 500)
2123
2123
  });
2124
- return new Promise((resolve27) => {
2124
+ return new Promise((resolve26) => {
2125
2125
  const bedrockEnv = bedrock ? BEDROCK_ENV_BY_AGENT[agent] : void 0;
2126
2126
  const child = spawn3(binary, args, {
2127
2127
  stdio: ["pipe", "pipe", "pipe"],
@@ -2170,7 +2170,7 @@ async function runAgent(options) {
2170
2170
  stderrLen: stderr.length,
2171
2171
  stderrTail: stderr.slice(-1e3)
2172
2172
  });
2173
- resolve27(result);
2173
+ resolve26(result);
2174
2174
  });
2175
2175
  });
2176
2176
  }
@@ -2192,7 +2192,7 @@ async function checkAgentAuth(agent) {
2192
2192
  return "not-found";
2193
2193
  if (agent !== "claude")
2194
2194
  return "ok";
2195
- return new Promise((resolve27) => {
2195
+ return new Promise((resolve26) => {
2196
2196
  const child = spawn4(binary, ["auth", "status", "--json"], { stdio: ["ignore", "pipe", "pipe"] });
2197
2197
  let stdout = "";
2198
2198
  let done = false;
@@ -2201,7 +2201,7 @@ async function checkAgentAuth(agent) {
2201
2201
  return;
2202
2202
  done = true;
2203
2203
  child.kill("SIGTERM");
2204
- resolve27("unauthenticated");
2204
+ resolve26("unauthenticated");
2205
2205
  }, 5e3);
2206
2206
  child.stdout?.on("data", (chunk) => {
2207
2207
  stdout += chunk.toString();
@@ -2212,14 +2212,14 @@ async function checkAgentAuth(agent) {
2212
2212
  done = true;
2213
2213
  clearTimeout(timer);
2214
2214
  if (code !== 0) {
2215
- resolve27("unauthenticated");
2215
+ resolve26("unauthenticated");
2216
2216
  return;
2217
2217
  }
2218
2218
  try {
2219
2219
  const status = JSON.parse(stdout);
2220
- resolve27(status.loggedIn ? "ok" : "unauthenticated");
2220
+ resolve26(status.loggedIn ? "ok" : "unauthenticated");
2221
2221
  } catch {
2222
- resolve27("unauthenticated");
2222
+ resolve26("unauthenticated");
2223
2223
  }
2224
2224
  });
2225
2225
  });
@@ -2229,9 +2229,9 @@ async function binaryIsOnPath(binary) {
2229
2229
  const fs = await import("node:fs/promises");
2230
2230
  return fs.access(binary).then(() => true, () => false);
2231
2231
  }
2232
- return new Promise((resolve27) => {
2232
+ return new Promise((resolve26) => {
2233
2233
  const child = spawn4(process.platform === "win32" ? "where" : "which", [binary], { stdio: "ignore" });
2234
- child.on("close", (code) => resolve27(code === 0));
2234
+ child.on("close", (code) => resolve26(code === 0));
2235
2235
  });
2236
2236
  }
2237
2237
  var init_check_agent_auth = __esm({
@@ -14901,7 +14901,7 @@ function errorMessage(error) {
14901
14901
  return error instanceof Error && error.message ? error.message : String(error);
14902
14902
  }
14903
14903
  function defaultSleep(delayMs) {
14904
- return new Promise((resolve27) => setTimeout(resolve27, delayMs));
14904
+ return new Promise((resolve26) => setTimeout(resolve26, delayMs));
14905
14905
  }
14906
14906
  var MAX_RETRY_AFTER_MS;
14907
14907
  var init_http_utils = __esm({
@@ -15177,7 +15177,7 @@ var init_api_client = __esm({
15177
15177
  const progress = maxAttempts > 1 ? attempt / (maxAttempts - 1) : 0;
15178
15178
  const baseDelay = intervalMs + (maxIntervalMs - intervalMs) * progress;
15179
15179
  const jitter = Math.random() * baseDelay * 0.15;
15180
- await new Promise((resolve27) => setTimeout(resolve27, baseDelay + jitter));
15180
+ await new Promise((resolve26) => setTimeout(resolve26, baseDelay + jitter));
15181
15181
  }
15182
15182
  }
15183
15183
  throw new Error(`Operation ${operationId} timed out after ${maxAttempts} attempts`);
@@ -18734,7 +18734,7 @@ async function retryDatabaseWrite(operation, attempts = 8) {
18734
18734
  const message = error instanceof Error ? error.message : String(error);
18735
18735
  if (!/database is locked|database is busy/i.test(message) || attempt >= attempts)
18736
18736
  throw error;
18737
- await new Promise((resolve27) => setTimeout(resolve27, Math.min(250 * attempt, 2e3)));
18737
+ await new Promise((resolve26) => setTimeout(resolve26, Math.min(250 * attempt, 2e3)));
18738
18738
  }
18739
18739
  }
18740
18740
  }
@@ -20301,34 +20301,11 @@ var init_shared2 = __esm({
20301
20301
  });
20302
20302
 
20303
20303
  // packages/experience-design-system-cli/src/tui/import/steps/05-token-reuse/logic.ts
20304
- import { access as access5, readdir as readdir2, stat as stat4 } from "node:fs/promises";
20304
+ import { access as access5, stat as stat4 } from "node:fs/promises";
20305
20305
  import { join as join18 } from "node:path";
20306
- async function findLatestTokens(contentfulDir) {
20307
- const candidates = [join18(contentfulDir, "tokens.json")];
20308
- try {
20309
- for (const session of await readdir2(contentfulDir, { withFileTypes: true })) {
20310
- if (!session.isDirectory()) continue;
20311
- for (const run of await readdir2(join18(contentfulDir, session.name), { withFileTypes: true }).catch(() => [])) {
20312
- if (run.isDirectory() && /^dsi-import-\d+$/.test(run.name)) {
20313
- candidates.push(join18(contentfulDir, session.name, run.name, "tokens.json"));
20314
- }
20315
- }
20316
- }
20317
- } catch {
20318
- }
20319
- const found = [];
20320
- for (const path5 of candidates) {
20321
- try {
20322
- found.push({ path: path5, mtimeMs: (await stat4(path5)).mtimeMs });
20323
- } catch {
20324
- }
20325
- }
20326
- return found.sort((a, b) => b.mtimeMs - a.mtimeMs)[0]?.path ?? null;
20327
- }
20328
- async function inspectTokens({ rawTokensPath, contentfulDir, cache }) {
20306
+ async function inspectTokens({ rawTokensPath, outDir, cache }) {
20329
20307
  if (!cache) return { kind: "none" };
20330
- const tokensPath = await findLatestTokens(contentfulDir);
20331
- if (!tokensPath) return { kind: "none" };
20308
+ const tokensPath = join18(outDir, "tokens.json");
20332
20309
  try {
20333
20310
  await access5(tokensPath);
20334
20311
  } catch {
@@ -20676,7 +20653,7 @@ var init_selection2 = __esm({
20676
20653
  import { mkdir as mkdir7 } from "node:fs/promises";
20677
20654
  import { join as join21, resolve as resolve22 } from "node:path";
20678
20655
  async function runExtraction(input, onProgress, deps = realDeps) {
20679
- const outDir = input.outDir ?? join21(resolve22(input.projectPath), ".contentful");
20656
+ const outDir = join21(resolve22(input.projectPath), ".contentful");
20680
20657
  let progress = initialProgress({
20681
20658
  hasCredentials: input.credentials !== null,
20682
20659
  hasRawTokens: input.rawTokensPath !== "",
@@ -20827,6 +20804,203 @@ var init_run = __esm({
20827
20804
  }
20828
20805
  });
20829
20806
 
20807
+ // packages/experience-design-system-cli/src/tui/settings/debug-mode/debug-mode-store.ts
20808
+ async function readDebugModeSetting() {
20809
+ const { debugMode } = await readSettings2();
20810
+ return { ...DEFAULT_DEBUG_MODE_SETTING, ...debugMode };
20811
+ }
20812
+ async function writeDebugModeSetting(setting) {
20813
+ await updateSettings2({ debugMode: setting });
20814
+ }
20815
+ var DEFAULT_DEBUG_MODE_SETTING;
20816
+ var init_debug_mode_store = __esm({
20817
+ "packages/experience-design-system-cli/src/tui/settings/debug-mode/debug-mode-store.ts"() {
20818
+ "use strict";
20819
+ init_config();
20820
+ DEFAULT_DEBUG_MODE_SETTING = {
20821
+ enabled: true
20822
+ };
20823
+ }
20824
+ });
20825
+
20826
+ // packages/experience-design-system-cli/src/tui/debug-store.ts
20827
+ var debug_store_exports = {};
20828
+ __export(debug_store_exports, {
20829
+ currentDebugSessionDir: () => currentDebugSessionDir,
20830
+ currentSessionDir: () => currentSessionDir,
20831
+ finishDebugRun: () => finishDebugRun,
20832
+ startDebugRun: () => startDebugRun,
20833
+ startDebugSessionIn: () => startDebugSessionIn
20834
+ });
20835
+ import { mkdir as mkdir8, writeFile as writeFile7 } from "node:fs/promises";
20836
+ import { existsSync as existsSync11, readdirSync as readdirSync3 } from "node:fs";
20837
+ import { join as join22, resolve as resolve23 } from "node:path";
20838
+ function generateRunId() {
20839
+ const now = /* @__PURE__ */ new Date();
20840
+ const pad = (n) => String(n).padStart(2, "0");
20841
+ return `${now.getFullYear()}${pad(now.getMonth() + 1)}${pad(now.getDate())}-${pad(now.getHours())}${pad(now.getMinutes())}${pad(now.getSeconds())}`;
20842
+ }
20843
+ function datePrefix(now = /* @__PURE__ */ new Date()) {
20844
+ const pad = (n) => String(n).padStart(2, "0");
20845
+ return `${pad(now.getMonth() + 1)}-${pad(now.getDate())}-${now.getFullYear()}`;
20846
+ }
20847
+ function slugify(value) {
20848
+ return value.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
20849
+ }
20850
+ async function readBaseDir() {
20851
+ try {
20852
+ const dir = (await readSettings2())["contentfulBaseDir"];
20853
+ return typeof dir === "string" && dir !== "" ? resolve23(dir) : void 0;
20854
+ } catch {
20855
+ return void 0;
20856
+ }
20857
+ }
20858
+ function nextSessionId(contentfulDir) {
20859
+ const today = datePrefix();
20860
+ const existing = existsSync11(contentfulDir) ? readdirSync3(contentfulDir) : [];
20861
+ const seqPattern = new RegExp(`^${today}-session-(\\d+)$`);
20862
+ const maxSeq = existing.reduce((max, entry) => {
20863
+ const match2 = seqPattern.exec(entry);
20864
+ return match2 ? Math.max(max, Number(match2[1])) : max;
20865
+ }, 0);
20866
+ return `${today}-session-${maxSeq + 1}`;
20867
+ }
20868
+ function startSession(base, { replace }) {
20869
+ const contentfulDir = join22(base, ".contentful");
20870
+ if (replace || !sessionDir) sessionDir = join22(contentfulDir, nextSessionId(contentfulDir));
20871
+ return sessionDir;
20872
+ }
20873
+ function currentDebugSessionDir() {
20874
+ return sessionDir && join22(sessionDir, "debug");
20875
+ }
20876
+ function currentSessionDir() {
20877
+ return sessionDir;
20878
+ }
20879
+ async function startDebugSessionIn(base, { replace = false } = {}) {
20880
+ try {
20881
+ if (!await isDebugModeEnabled()) return;
20882
+ await mkdir8(join22(startSession(resolve23(base), { replace }), "debug"), { recursive: true });
20883
+ } catch {
20884
+ }
20885
+ }
20886
+ async function isDebugModeEnabled() {
20887
+ try {
20888
+ return (await readDebugModeSetting()).enabled;
20889
+ } catch {
20890
+ return true;
20891
+ }
20892
+ }
20893
+ function redact(value) {
20894
+ const clone = { ...value };
20895
+ if ("cma_token" in clone) {
20896
+ const raw = clone.cma_token;
20897
+ clone.cma_token = typeof raw === "string" && raw.length > 0 ? `[present, ${raw.length} chars]` : "[not set]";
20898
+ }
20899
+ return clone;
20900
+ }
20901
+ function startDebugRun({
20902
+ flow,
20903
+ step,
20904
+ menuOption,
20905
+ inputs
20906
+ }) {
20907
+ const runId = generateRunId();
20908
+ const startedAt = Date.now();
20909
+ const redactedInputs = redact(inputs);
20910
+ isDebugModeEnabled().then((enabled) => {
20911
+ if (!enabled) return;
20912
+ pendingRun = { flow, step, runId, menuOption, inputs: redactedInputs, startedAt };
20913
+ });
20914
+ }
20915
+ async function finishDebugRun({
20916
+ outputs,
20917
+ status,
20918
+ exitMethod
20919
+ }) {
20920
+ const run = pendingRun;
20921
+ if (!run) return;
20922
+ pendingRun = void 0;
20923
+ const durationMs = Date.now() - run.startedAt;
20924
+ const content = renderMarkdown(run, { outputs: redact(outputs), status, exitMethod, durationMs });
20925
+ const root = currentDebugSessionDir();
20926
+ if (!root) return;
20927
+ const flowSegments = run.flow.split("/");
20928
+ const dir = join22(root, ...flowSegments);
20929
+ await mkdir8(dir, { recursive: true });
20930
+ const filename = nextAttemptFilename(dir, run.menuOption);
20931
+ await writeFile7(join22(dir, filename), content, { mode: 384 });
20932
+ }
20933
+ function nextAttemptFilename(dir, menuOption) {
20934
+ const today = datePrefix();
20935
+ const optionSlug = slugify(menuOption);
20936
+ const existing = existsSync11(dir) ? readdirSync3(dir) : [];
20937
+ const attemptPattern = new RegExp(`^${today}-${optionSlug}-attempt-(\\d+)\\.md$`);
20938
+ const maxAttempt = existing.reduce((max, entry) => {
20939
+ const match2 = attemptPattern.exec(entry);
20940
+ return match2 ? Math.max(max, Number(match2[1])) : max;
20941
+ }, 0);
20942
+ return `${today}-${optionSlug}-attempt-${maxAttempt + 1}.md`;
20943
+ }
20944
+ function renderMarkdown(run, finish) {
20945
+ const stepMatch = /^(\d+)-(.+)$/.exec(run.step);
20946
+ const stepLabel2 = stepMatch ? `${stepMatch[1]} - ${stepMatch[2]}` : run.step;
20947
+ const flowSlug = run.flow.split("/").join("-");
20948
+ return `# Debug Log
20949
+
20950
+ - Run ID: ${run.runId}
20951
+ - Flow: ${flowSlug}
20952
+ - Step: ${stepLabel2}
20953
+ - Menu option: ${run.menuOption}
20954
+ - Date: ${(/* @__PURE__ */ new Date()).toISOString()}
20955
+ - CLI version: ${readPackageVersion()}
20956
+ - Platform: ${process.platform} / Node ${process.version}
20957
+ - Duration on screen: ${finish.durationMs}ms
20958
+ - Status: ${finish.status}
20959
+ - Exit method: ${finish.exitMethod}
20960
+
20961
+ ## Inputs
20962
+ \`\`\`json
20963
+ ${JSON.stringify(run.inputs, null, 2)}
20964
+ \`\`\`
20965
+
20966
+ ## Outputs
20967
+ \`\`\`json
20968
+ ${JSON.stringify(finish.outputs, null, 2)}
20969
+ \`\`\`
20970
+ `;
20971
+ }
20972
+ function handleCrash() {
20973
+ return finishDebugRun({ outputs: {}, status: "error", exitMethod: "crashed" });
20974
+ }
20975
+ var pendingRun, sessionDir;
20976
+ var init_debug_store = __esm({
20977
+ "packages/experience-design-system-cli/src/tui/debug-store.ts"() {
20978
+ "use strict";
20979
+ init_config();
20980
+ init_version();
20981
+ init_debug_mode_store();
20982
+ void Promise.all([isDebugModeEnabled(), readBaseDir()]).then(([enabled, base]) => {
20983
+ if (!enabled || !base) return void 0;
20984
+ return mkdir8(join22(startSession(base, { replace: false }), "debug"), { recursive: true });
20985
+ });
20986
+ process.once("uncaughtException", (err) => {
20987
+ void handleCrash().finally(() => {
20988
+ throw err;
20989
+ });
20990
+ });
20991
+ process.once("unhandledRejection", (reason) => {
20992
+ void handleCrash().finally(() => {
20993
+ throw reason;
20994
+ });
20995
+ });
20996
+ process.once("SIGINT", () => {
20997
+ void handleCrash().finally(() => {
20998
+ process.exit(130);
20999
+ });
21000
+ });
21001
+ }
21002
+ });
21003
+
20830
21004
  // packages/experience-design-system-cli/src/tui/import/steps/06-extraction/use-extraction.ts
20831
21005
  import { useEffect as useEffect5, useRef as useRef2, useState as useState8 } from "react";
20832
21006
  function useExtraction(input) {
@@ -20846,6 +21020,7 @@ function useExtraction(input) {
20846
21020
  reuseTokens: input.tokenStrategy === "reuse"
20847
21021
  })
20848
21022
  });
21023
+ void Promise.resolve().then(() => (init_debug_store(), debug_store_exports)).then((store) => store.startDebugSessionIn(input.projectPath));
20849
21024
  void runExtraction(input, (progress) => {
20850
21025
  if (current.current === input) setState({ status: "running", progress });
20851
21026
  }).then((result) => {
@@ -24067,7 +24242,7 @@ var init_save_decisions = __esm({
24067
24242
  });
24068
24243
 
24069
24244
  // packages/experience-design-system-cli/src/tui/import/steps/08-generation/run.ts
24070
- import { resolve as resolve23 } from "node:path";
24245
+ import { resolve as resolve24 } from "node:path";
24071
24246
  async function runGeneration(input, onProgress, deps = realDeps3) {
24072
24247
  let progress = { components: null, mapTokens: "idle", mapTokensEligible: null };
24073
24248
  const update = (change) => {
@@ -24153,7 +24328,7 @@ async function buildMapTokensOptions(input) {
24153
24328
  if (mapOverride?.kind === "text") prompt.skillContentOverride = mapOverride.value;
24154
24329
  if (mapOverride?.kind === "path") {
24155
24330
  await resolvePromptOverride(mapOverride);
24156
- prompt.skillPathOverride = resolve23(mapOverride.value);
24331
+ prompt.skillPathOverride = resolve24(mapOverride.value);
24157
24332
  }
24158
24333
  if (input.existingEntitiesPath) {
24159
24334
  const entities = await readExistingContentfulEntitiesFromSession({ path: input.existingEntitiesPath });
@@ -24231,7 +24406,7 @@ var init_use_generation = __esm({
24231
24406
  });
24232
24407
 
24233
24408
  // packages/experience-design-system-cli/src/tui/import/steps/10-flow/flow/build-flow-start.ts
24234
- import { join as join22 } from "node:path";
24409
+ import { join as join23 } from "node:path";
24235
24410
  function buildFlowStart(input) {
24236
24411
  const { extraction, handoff, saved, generatePromptPath } = input;
24237
24412
  const credentials = extraction.credentials ?? {
@@ -24244,7 +24419,7 @@ function buildFlowStart(input) {
24244
24419
  handoff,
24245
24420
  agent: extraction.agent,
24246
24421
  projectPath: extraction.projectPath,
24247
- outDir: extraction.projectPath ? join22(extraction.projectPath, ".contentful") : "",
24422
+ outDir: extraction.projectPath ? join23(extraction.projectPath, ".contentful") : "",
24248
24423
  rawTokensPath: extraction.rawTokensPath,
24249
24424
  credentials: {
24250
24425
  spaceId: credentials.spaceId,
@@ -30440,7 +30615,7 @@ var init_DoneStep = __esm({
30440
30615
  });
30441
30616
 
30442
30617
  // packages/experience-design-system-cli/src/tui/import/steps/10-flow/support/path-utils.ts
30443
- import { resolve as resolve24 } from "node:path";
30618
+ import { resolve as resolve25 } from "node:path";
30444
30619
  import { homedir as homedir4 } from "node:os";
30445
30620
  function expandTilde(input) {
30446
30621
  if (input === "~" || input.startsWith("~/") || input.startsWith("~\\")) {
@@ -30454,7 +30629,7 @@ function normalizePath(input) {
30454
30629
  p = p.slice(1, -1);
30455
30630
  }
30456
30631
  p = expandTilde(p);
30457
- return resolve24(p);
30632
+ return resolve25(p);
30458
30633
  }
30459
30634
  var init_path_utils = __esm({
30460
30635
  "packages/experience-design-system-cli/src/tui/import/steps/10-flow/support/path-utils.ts"() {
@@ -30481,8 +30656,8 @@ var init_use_blinking_cursor = __esm({
30481
30656
  // packages/experience-design-system-cli/src/tui/import/steps/10-flow/screens/PathPrompt.tsx
30482
30657
  import { useState as useState24 } from "react";
30483
30658
  import { Box as Box37, Text as Text40 } from "ink";
30484
- import { readdirSync as readdirSync3 } from "node:fs";
30485
- import { dirname as dirname15, basename as basename6, join as join23 } from "node:path";
30659
+ import { readdirSync as readdirSync4 } from "node:fs";
30660
+ import { dirname as dirname15, basename as basename6, join as join24 } from "node:path";
30486
30661
  import { jsx as jsx47, jsxs as jsxs38 } from "react/jsx-runtime";
30487
30662
  function autocomplete(partial) {
30488
30663
  if (!partial) return null;
@@ -30491,19 +30666,19 @@ function autocomplete(partial) {
30491
30666
  const base = basename6(normalized);
30492
30667
  let entries;
30493
30668
  try {
30494
- entries = readdirSync3(dir);
30669
+ entries = readdirSync4(dir);
30495
30670
  } catch {
30496
30671
  return null;
30497
30672
  }
30498
30673
  const matches = entries.filter((e) => e.startsWith(base));
30499
30674
  if (matches.length === 0) return null;
30500
- if (matches.length === 1) return join23(dir, matches[0]);
30675
+ if (matches.length === 1) return join24(dir, matches[0]);
30501
30676
  let prefix = matches[0];
30502
30677
  for (const m of matches) {
30503
30678
  while (!m.startsWith(prefix)) prefix = prefix.slice(0, -1);
30504
30679
  if (!prefix) break;
30505
30680
  }
30506
- return prefix.length > base.length ? join23(dir, prefix) : null;
30681
+ return prefix.length > base.length ? join24(dir, prefix) : null;
30507
30682
  }
30508
30683
  function PathPrompt({
30509
30684
  defaultPath,
@@ -31706,8 +31881,8 @@ var init_run_print_files_helpers = __esm({
31706
31881
  });
31707
31882
 
31708
31883
  // packages/experience-design-system-cli/src/tui/import/steps/10-flow/flow/save.ts
31709
- import { writeFile as writeFile7 } from "node:fs/promises";
31710
- import { join as join24 } from "node:path";
31884
+ import { writeFile as writeFile8 } from "node:fs/promises";
31885
+ import { join as join25 } from "node:path";
31711
31886
  function buildSavedCDF(components, tokens, opts = {}) {
31712
31887
  const cdf = buildCDF2(components, toCdfTokens(tokens), opts);
31713
31888
  if (!cdf) throw new Error("nothing to save \u2014 no components or tokens resolved");
@@ -31719,7 +31894,7 @@ function buildSavedCDF(components, tokens, opts = {}) {
31719
31894
  }
31720
31895
  async function runPrintFiles(input, deps, onPatch) {
31721
31896
  onPatch({ step: "printing" });
31722
- const componentsPath = join24(input.outDir, "components.json");
31897
+ const componentsPath = join25(input.outDir, "components.json");
31723
31898
  try {
31724
31899
  const db = deps.openDb();
31725
31900
  let components = [];
@@ -31803,10 +31978,10 @@ var init_save = __esm({
31803
31978
  realSaveDeps = () => ({
31804
31979
  openDb: openPipelineDb,
31805
31980
  readTokens: (path5) => readTokensFromPath2({ flag: "tokens", path: path5 }),
31806
- writeFile: (path5, contents) => writeFile7(path5, contents),
31981
+ writeFile: (path5, contents) => writeFile8(path5, contents),
31807
31982
  appendRun,
31808
31983
  buildSourceFingerprint,
31809
- sleep: (ms) => new Promise((resolve27) => setTimeout(resolve27, ms)),
31984
+ sleep: (ms) => new Promise((resolve26) => setTimeout(resolve26, ms)),
31810
31985
  warn: (message) => process.stderr.write(message)
31811
31986
  });
31812
31987
  }
@@ -31826,9 +32001,9 @@ var init_types9 = __esm({
31826
32001
 
31827
32002
  // packages/experience-design-system-cli/src/tui/import/steps/10-flow/flow/controller.ts
31828
32003
  import { appendFileSync, writeFileSync } from "node:fs";
31829
- import { mkdir as mkdir8 } from "node:fs/promises";
32004
+ import { mkdir as mkdir9 } from "node:fs/promises";
31830
32005
  import { tmpdir } from "node:os";
31831
- import { join as join25, resolve as resolve25 } from "node:path";
32006
+ import { join as join26 } from "node:path";
31832
32007
  function appendWizardLog(entry) {
31833
32008
  appendFileSync(WIZARD_LOG, JSON.stringify({ ts: (/* @__PURE__ */ new Date()).toISOString(), ...entry }) + "\n");
31834
32009
  }
@@ -31836,6 +32011,9 @@ function startWizardLog() {
31836
32011
  writeFileSync(WIZARD_LOG, `--- experiences import session ${(/* @__PURE__ */ new Date()).toISOString()} ---
31837
32012
  `);
31838
32013
  }
32014
+ async function realSessionDir() {
32015
+ return (await Promise.resolve().then(() => (init_debug_store(), debug_store_exports))).currentSessionDir();
32016
+ }
31839
32017
  function realFlowDeps() {
31840
32018
  const log = (entry) => appendWizardLog(entry);
31841
32019
  return {
@@ -31851,13 +32029,14 @@ function realFlowDeps() {
31851
32029
  }
31852
32030
  },
31853
32031
  mkdir: async (path5) => {
31854
- await mkdir8(path5, { recursive: true });
32032
+ await mkdir9(path5, { recursive: true });
31855
32033
  },
31856
32034
  detectSaveConflict,
31857
32035
  buildTimestampedSubdir,
31858
32036
  rejectComponentsByName,
31859
32037
  log,
31860
- stderr: (text) => process.stderr.write(text)
32038
+ stderr: (text) => process.stderr.write(text),
32039
+ sessionDir: realSessionDir
31861
32040
  };
31862
32041
  }
31863
32042
  function initialFlowState(start) {
@@ -31998,6 +32177,9 @@ function createFlowController(start, deps) {
31998
32177
  const startSave = (opts, patch = {}) => {
31999
32178
  pendingSave = opts;
32000
32179
  update({ ...patch, step: "path-prompt" });
32180
+ void deps.sessionDir?.().then((session) => {
32181
+ if (session && state.step === "path-prompt") update({ outDir: join26(session, "dsi-import") });
32182
+ });
32001
32183
  };
32002
32184
  const proceedToWrite = async (path5) => {
32003
32185
  update({ outDir: path5 });
@@ -32070,7 +32252,7 @@ function createFlowController(start, deps) {
32070
32252
  },
32071
32253
  async submitPath(submitted) {
32072
32254
  await deps.mkdir(submitted);
32073
- if (resolve25(submitted) !== resolve25(state.outDir) && await deps.detectSaveConflict(submitted)) {
32255
+ if (await deps.detectSaveConflict(submitted)) {
32074
32256
  const subdir = deps.buildTimestampedSubdir(submitted);
32075
32257
  await deps.mkdir(subdir);
32076
32258
  await proceedToWrite(subdir);
@@ -32102,7 +32284,7 @@ var init_controller = __esm({
32102
32284
  init_push();
32103
32285
  init_save();
32104
32286
  init_types9();
32105
- WIZARD_LOG = join25(tmpdir(), "experiences-import-wizard.log");
32287
+ WIZARD_LOG = join26(tmpdir(), "experiences-import-wizard.log");
32106
32288
  }
32107
32289
  });
32108
32290
 
@@ -32134,219 +32316,6 @@ var init_use_flow = __esm({
32134
32316
  }
32135
32317
  });
32136
32318
 
32137
- // packages/experience-design-system-cli/src/tui/settings/debug-mode/debug-mode-store.ts
32138
- async function readDebugModeSetting() {
32139
- const { debugMode } = await readSettings2();
32140
- return { ...DEFAULT_DEBUG_MODE_SETTING, ...debugMode };
32141
- }
32142
- async function writeDebugModeSetting(setting) {
32143
- await updateSettings2({ debugMode: setting });
32144
- }
32145
- var DEFAULT_DEBUG_MODE_SETTING;
32146
- var init_debug_mode_store = __esm({
32147
- "packages/experience-design-system-cli/src/tui/settings/debug-mode/debug-mode-store.ts"() {
32148
- "use strict";
32149
- init_config();
32150
- DEFAULT_DEBUG_MODE_SETTING = {
32151
- enabled: true
32152
- };
32153
- }
32154
- });
32155
-
32156
- // packages/experience-design-system-cli/src/tui/debug-store.ts
32157
- var debug_store_exports = {};
32158
- __export(debug_store_exports, {
32159
- currentDebugSessionDir: () => currentDebugSessionDir,
32160
- currentSessionDir: () => currentSessionDir,
32161
- finishDebugRun: () => finishDebugRun,
32162
- startDebugRun: () => startDebugRun,
32163
- startDebugSessionIn: () => startDebugSessionIn,
32164
- startImportRun: () => startImportRun
32165
- });
32166
- import { mkdir as mkdir9, writeFile as writeFile8 } from "node:fs/promises";
32167
- import { existsSync as existsSync11, readdirSync as readdirSync4 } from "node:fs";
32168
- import { join as join26, resolve as resolve26 } from "node:path";
32169
- function generateRunId() {
32170
- const now = /* @__PURE__ */ new Date();
32171
- const pad = (n) => String(n).padStart(2, "0");
32172
- return `${now.getFullYear()}${pad(now.getMonth() + 1)}${pad(now.getDate())}-${pad(now.getHours())}${pad(now.getMinutes())}${pad(now.getSeconds())}`;
32173
- }
32174
- function datePrefix(now = /* @__PURE__ */ new Date()) {
32175
- const pad = (n) => String(n).padStart(2, "0");
32176
- return `${pad(now.getMonth() + 1)}-${pad(now.getDate())}-${now.getFullYear()}`;
32177
- }
32178
- function slugify(value) {
32179
- return value.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
32180
- }
32181
- async function readBaseDir() {
32182
- try {
32183
- const dir = (await readSettings2())["contentfulBaseDir"];
32184
- return typeof dir === "string" && dir !== "" ? resolve26(dir) : void 0;
32185
- } catch {
32186
- return void 0;
32187
- }
32188
- }
32189
- function nextSessionId(contentfulDir) {
32190
- const today = datePrefix();
32191
- const existing = existsSync11(contentfulDir) ? readdirSync4(contentfulDir) : [];
32192
- const seqPattern = new RegExp(`^${today}-session-(\\d+)$`);
32193
- const maxSeq = existing.reduce((max, entry) => {
32194
- const match2 = seqPattern.exec(entry);
32195
- return match2 ? Math.max(max, Number(match2[1])) : max;
32196
- }, 0);
32197
- return `${today}-session-${maxSeq + 1}`;
32198
- }
32199
- function startSession(base, { replace }) {
32200
- const contentfulDir = join26(base, ".contentful");
32201
- if (replace || !sessionDir) sessionDir = join26(contentfulDir, nextSessionId(contentfulDir));
32202
- return sessionDir;
32203
- }
32204
- function currentDebugSessionDir() {
32205
- return sessionDir && join26(sessionDir, "debug");
32206
- }
32207
- function currentSessionDir() {
32208
- return sessionDir;
32209
- }
32210
- async function startDebugSessionIn(base, { replace = false } = {}) {
32211
- try {
32212
- if (!await isDebugModeEnabled()) return;
32213
- await mkdir9(join26(startSession(resolve26(base), { replace }), "debug"), { recursive: true });
32214
- } catch {
32215
- }
32216
- }
32217
- function nextImportRunDir(session) {
32218
- const existing = existsSync11(session) ? readdirSync4(session) : [];
32219
- const maxRun = existing.reduce((max, entry) => {
32220
- const match2 = /^dsi-import-(\d+)$/.exec(entry);
32221
- return match2 ? Math.max(max, Number(match2[1])) : max;
32222
- }, 0);
32223
- return join26(session, `dsi-import-${maxRun + 1}`);
32224
- }
32225
- async function startImportRun(projectPath) {
32226
- await startDebugSessionIn(projectPath);
32227
- if (!sessionDir) return join26(resolve26(projectPath), ".contentful");
32228
- const dir = nextImportRunDir(sessionDir);
32229
- await mkdir9(dir, { recursive: true });
32230
- return dir;
32231
- }
32232
- async function isDebugModeEnabled() {
32233
- try {
32234
- return (await readDebugModeSetting()).enabled;
32235
- } catch {
32236
- return true;
32237
- }
32238
- }
32239
- function redact(value) {
32240
- const clone = { ...value };
32241
- if ("cma_token" in clone) {
32242
- const raw = clone.cma_token;
32243
- clone.cma_token = typeof raw === "string" && raw.length > 0 ? `[present, ${raw.length} chars]` : "[not set]";
32244
- }
32245
- return clone;
32246
- }
32247
- function startDebugRun({
32248
- flow,
32249
- step,
32250
- menuOption,
32251
- inputs
32252
- }) {
32253
- const runId = generateRunId();
32254
- const startedAt = Date.now();
32255
- const redactedInputs = redact(inputs);
32256
- isDebugModeEnabled().then((enabled) => {
32257
- if (!enabled) return;
32258
- pendingRun = { flow, step, runId, menuOption, inputs: redactedInputs, startedAt };
32259
- });
32260
- }
32261
- async function finishDebugRun({
32262
- outputs,
32263
- status,
32264
- exitMethod
32265
- }) {
32266
- const run = pendingRun;
32267
- if (!run) return;
32268
- pendingRun = void 0;
32269
- const durationMs = Date.now() - run.startedAt;
32270
- const content = renderMarkdown(run, { outputs: redact(outputs), status, exitMethod, durationMs });
32271
- const root = currentDebugSessionDir();
32272
- if (!root) return;
32273
- const flowSegments = run.flow.split("/");
32274
- const dir = join26(root, ...flowSegments);
32275
- await mkdir9(dir, { recursive: true });
32276
- const filename = nextAttemptFilename(dir, run.menuOption);
32277
- await writeFile8(join26(dir, filename), content, { mode: 384 });
32278
- }
32279
- function nextAttemptFilename(dir, menuOption) {
32280
- const today = datePrefix();
32281
- const optionSlug = slugify(menuOption);
32282
- const existing = existsSync11(dir) ? readdirSync4(dir) : [];
32283
- const attemptPattern = new RegExp(`^${today}-${optionSlug}-attempt-(\\d+)\\.md$`);
32284
- const maxAttempt = existing.reduce((max, entry) => {
32285
- const match2 = attemptPattern.exec(entry);
32286
- return match2 ? Math.max(max, Number(match2[1])) : max;
32287
- }, 0);
32288
- return `${today}-${optionSlug}-attempt-${maxAttempt + 1}.md`;
32289
- }
32290
- function renderMarkdown(run, finish) {
32291
- const stepMatch = /^(\d+)-(.+)$/.exec(run.step);
32292
- const stepLabel2 = stepMatch ? `${stepMatch[1]} - ${stepMatch[2]}` : run.step;
32293
- const flowSlug = run.flow.split("/").join("-");
32294
- return `# Debug Log
32295
-
32296
- - Run ID: ${run.runId}
32297
- - Flow: ${flowSlug}
32298
- - Step: ${stepLabel2}
32299
- - Menu option: ${run.menuOption}
32300
- - Date: ${(/* @__PURE__ */ new Date()).toISOString()}
32301
- - CLI version: ${readPackageVersion()}
32302
- - Platform: ${process.platform} / Node ${process.version}
32303
- - Duration on screen: ${finish.durationMs}ms
32304
- - Status: ${finish.status}
32305
- - Exit method: ${finish.exitMethod}
32306
-
32307
- ## Inputs
32308
- \`\`\`json
32309
- ${JSON.stringify(run.inputs, null, 2)}
32310
- \`\`\`
32311
-
32312
- ## Outputs
32313
- \`\`\`json
32314
- ${JSON.stringify(finish.outputs, null, 2)}
32315
- \`\`\`
32316
- `;
32317
- }
32318
- function handleCrash() {
32319
- return finishDebugRun({ outputs: {}, status: "error", exitMethod: "crashed" });
32320
- }
32321
- var pendingRun, sessionDir;
32322
- var init_debug_store = __esm({
32323
- "packages/experience-design-system-cli/src/tui/debug-store.ts"() {
32324
- "use strict";
32325
- init_config();
32326
- init_version();
32327
- init_debug_mode_store();
32328
- void Promise.all([isDebugModeEnabled(), readBaseDir()]).then(([enabled, base]) => {
32329
- if (!enabled || !base) return void 0;
32330
- return mkdir9(join26(startSession(base, { replace: false }), "debug"), { recursive: true });
32331
- });
32332
- process.once("uncaughtException", (err) => {
32333
- void handleCrash().finally(() => {
32334
- throw err;
32335
- });
32336
- });
32337
- process.once("unhandledRejection", (reason) => {
32338
- void handleCrash().finally(() => {
32339
- throw reason;
32340
- });
32341
- });
32342
- process.once("SIGINT", () => {
32343
- void handleCrash().finally(() => {
32344
- process.exit(130);
32345
- });
32346
- });
32347
- }
32348
- });
32349
-
32350
32319
  // packages/experience-design-system-cli/src/tui/help/help-info.ts
32351
32320
  async function readHelpInfo() {
32352
32321
  const debugMode = await readDebugModeSetting();
@@ -33022,7 +32991,7 @@ function App({ importOptions, inkClear }) {
33022
32991
  const launch = { projectPath: projectPath2, tokens, filePaths, ...importOptions };
33023
32992
  const state = await inspectTokens({
33024
32993
  rawTokensPath: tokens,
33025
- contentfulDir: join27(resolveUserPath(projectPath2), ".contentful"),
32994
+ outDir: join27(resolveUserPath(projectPath2), ".contentful"),
33026
32995
  cache: importOptions.cache
33027
32996
  });
33028
32997
  if (state.kind === "cached") {
@@ -33043,7 +33012,6 @@ function App({ importOptions, inkClear }) {
33043
33012
  const settings = await readSettings2();
33044
33013
  const { agent, agentModel } = resolveAgentChoice(launch.agent, settings);
33045
33014
  const generatePromptPath = typeof settings.generatePromptPath === "string" ? settings.generatePromptPath : void 0;
33046
- const outDir = await (await Promise.resolve().then(() => (init_debug_store(), debug_store_exports))).startImportRun(resolveUserPath(launch.projectPath ?? ""));
33047
33015
  setExtractionRun({
33048
33016
  ...generatePromptPath ? { generatePromptPath } : {},
33049
33017
  // the later steps get the same agent, so they use what the stage used
@@ -33052,7 +33020,6 @@ function App({ importOptions, inkClear }) {
33052
33020
  tokenStrategy,
33053
33021
  input: {
33054
33022
  projectPath: resolveUserPath(launch.projectPath ?? ""),
33055
- outDir,
33056
33023
  filePaths: launch.filePaths ?? [],
33057
33024
  rawTokensPath: launch.tokens ?? "",
33058
33025
  tokenStrategy,
@@ -33400,14 +33367,14 @@ function runDevWatch(args) {
33400
33367
  process.stderr.write("--watch only works from a checkout of the repo (scripts/dev.mjs is not in the package).\n");
33401
33368
  return Promise.resolve(1);
33402
33369
  }
33403
- return new Promise((resolve27) => {
33370
+ return new Promise((resolve26) => {
33404
33371
  const child = spawn2(process.execPath, [script, ...args], { stdio: "inherit" });
33405
33372
  process.on("SIGINT", () => void 0);
33406
- child.on("exit", (code) => resolve27(code ?? 0));
33373
+ child.on("exit", (code) => resolve26(code ?? 0));
33407
33374
  child.on("error", (err) => {
33408
33375
  process.stderr.write(`${err.message}
33409
33376
  `);
33410
- resolve27(1);
33377
+ resolve26(1);
33411
33378
  });
33412
33379
  });
33413
33380
  }
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contentful/experience-design-system-cli",
3
- "version": "2.37.1-dev-build-f57f8147.0",
3
+ "version": "2.37.1-dev-build-3c845a01.0",
4
4
  "description": "Contentful Experiences design system import CLI",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -11,13 +11,6 @@ export declare function currentSessionDir(): string | undefined;
11
11
  export declare function startDebugSessionIn(base: string, { replace }?: {
12
12
  replace?: boolean | undefined;
13
13
  }): Promise<void>;
14
- /**
15
- * Where this import run writes everything it produces (tokens.json, .existing-entities.json, components.json): a new
16
- * `dsi-import-N` folder in this session's folder, next to the debug logs. The session is started here, and waited for,
17
- * so the answer does not depend on how quickly the boot-time start finished. Without a session (Debug Mode off, or a
18
- * folder that cannot be created) the files stay in `<project>/.contentful`, as before.
19
- */
20
- export declare function startImportRun(projectPath: string): Promise<string>;
21
14
  export declare function startDebugRun({ flow, step, menuOption, inputs, }: {
22
15
  flow: string;
23
16
  step: string;
@@ -8,11 +8,10 @@ export type TokensState = {
8
8
  };
9
9
  interface InspectInput {
10
10
  rawTokensPath: string;
11
- /** The `.contentful` folder: the sessions' `dsi-import` folders sit inside it, and an older `tokens.json` may sit in it. */
12
- contentfulDir: string;
11
+ outDir: string;
13
12
  cache: boolean;
14
13
  }
15
- export declare function inspectTokens({ rawTokensPath, contentfulDir, cache }: InspectInput): Promise<TokensState>;
14
+ export declare function inspectTokens({ rawTokensPath, outDir, cache }: InspectInput): Promise<TokensState>;
16
15
  export declare function gateText({ tokensPath, sourceChanged }: {
17
16
  tokensPath: string;
18
17
  sourceChanged: boolean;
@@ -2,8 +2,6 @@ import type { ExtractionHandoff, ImportHandoff } from '@contentful/experience-de
2
2
  export type TokenStrategy = ImportHandoff['tokens']['strategy'];
3
3
  export interface ExtractionInput {
4
4
  projectPath: string;
5
- /** Where the stage writes tokens.json and the other files. Defaults to `<projectPath>/.contentful`. */
6
- outDir?: string;
7
5
  /** Absolute source files from the path-validation step (collectFiles output). */
8
6
  filePaths: string[];
9
7
  /** Raw tokens file the user pointed at (always set: v2 asks for one). */
@@ -38,6 +38,8 @@ export interface FlowDeps {
38
38
  /** Writes one line of the wizard's step log. */
39
39
  log: (entry: Record<string, unknown>) => void;
40
40
  stderr: (text: string) => void;
41
+ /** This terminal session's folder, when there is one; the saved files default to a `dsi-import` folder inside it. */
42
+ sessionDir?: () => Promise<string | undefined>;
41
43
  }
42
44
  export declare function startWizardLog(): void;
43
45
  export declare function realFlowDeps(): FlowDeps;
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contentful/experience-design-system-cli",
3
- "version": "2.37.1-dev-build-f57f8147.0",
3
+ "version": "2.37.1-dev-build-3c845a01.0",
4
4
  "description": "Contentful Experiences design system import CLI",
5
5
  "license": "MIT",
6
6
  "type": "module",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contentful/experience-design-system-cli",
3
- "version": "2.37.1-dev-build-f57f8147.0",
3
+ "version": "2.37.1-dev-build-3c845a01.0",
4
4
  "description": "Contentful Experiences design system import CLI",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -45,8 +45,8 @@
45
45
  "ts-morph": "^27.0.2",
46
46
  "typescript": "^5.9.3",
47
47
  "zod": "^4.6.5",
48
- "@contentful/experience-design-system-backend-pipeline": "2.37.1-dev-build-f57f8147.0",
49
- "@contentful/experience-design-system-types": "2.37.1-dev-build-f57f8147.0"
48
+ "@contentful/experience-design-system-backend-pipeline": "2.37.1-dev-build-3c845a01.0",
49
+ "@contentful/experience-design-system-types": "2.37.1-dev-build-3c845a01.0"
50
50
  },
51
51
  "devDependencies": {
52
52
  "@tsconfig/node24": "^24.0.4",