@contentful/experience-design-system-cli 2.37.1-dev-build-7652d7c0.0 → 2.37.1-dev-build-6fb2b08b.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/index.js CHANGED
@@ -1500,7 +1500,7 @@ async function runAgent(options) {
1500
1500
  promptLen: prompt.length,
1501
1501
  promptHead: prompt.slice(0, 500)
1502
1502
  });
1503
- return new Promise((resolve25) => {
1503
+ return new Promise((resolve27) => {
1504
1504
  const bedrockEnv = bedrock ? BEDROCK_ENV_BY_AGENT[agent] : void 0;
1505
1505
  const child = spawn(binary, args, {
1506
1506
  stdio: ["pipe", "pipe", "pipe"],
@@ -1549,7 +1549,7 @@ async function runAgent(options) {
1549
1549
  stderrLen: stderr.length,
1550
1550
  stderrTail: stderr.slice(-1e3)
1551
1551
  });
1552
- resolve25(result);
1552
+ resolve27(result);
1553
1553
  });
1554
1554
  });
1555
1555
  }
@@ -1571,7 +1571,7 @@ async function checkAgentAuth(agent) {
1571
1571
  return "not-found";
1572
1572
  if (agent !== "claude")
1573
1573
  return "ok";
1574
- return new Promise((resolve25) => {
1574
+ return new Promise((resolve27) => {
1575
1575
  const child = spawn2(binary, ["auth", "status", "--json"], { stdio: ["ignore", "pipe", "pipe"] });
1576
1576
  let stdout = "";
1577
1577
  let done = false;
@@ -1580,7 +1580,7 @@ async function checkAgentAuth(agent) {
1580
1580
  return;
1581
1581
  done = true;
1582
1582
  child.kill("SIGTERM");
1583
- resolve25("unauthenticated");
1583
+ resolve27("unauthenticated");
1584
1584
  }, 5e3);
1585
1585
  child.stdout?.on("data", (chunk) => {
1586
1586
  stdout += chunk.toString();
@@ -1591,14 +1591,14 @@ async function checkAgentAuth(agent) {
1591
1591
  done = true;
1592
1592
  clearTimeout(timer);
1593
1593
  if (code !== 0) {
1594
- resolve25("unauthenticated");
1594
+ resolve27("unauthenticated");
1595
1595
  return;
1596
1596
  }
1597
1597
  try {
1598
1598
  const status = JSON.parse(stdout);
1599
- resolve25(status.loggedIn ? "ok" : "unauthenticated");
1599
+ resolve27(status.loggedIn ? "ok" : "unauthenticated");
1600
1600
  } catch {
1601
- resolve25("unauthenticated");
1601
+ resolve27("unauthenticated");
1602
1602
  }
1603
1603
  });
1604
1604
  });
@@ -1608,9 +1608,9 @@ async function binaryIsOnPath(binary) {
1608
1608
  const fs = await import("node:fs/promises");
1609
1609
  return fs.access(binary).then(() => true, () => false);
1610
1610
  }
1611
- return new Promise((resolve25) => {
1611
+ return new Promise((resolve27) => {
1612
1612
  const child = spawn2(process.platform === "win32" ? "where" : "which", [binary], { stdio: "ignore" });
1613
- child.on("close", (code) => resolve25(code === 0));
1613
+ child.on("close", (code) => resolve27(code === 0));
1614
1614
  });
1615
1615
  }
1616
1616
  var init_check_agent_auth = __esm({
@@ -12523,11 +12523,11 @@ var init_load_and_validate_for_review = __esm({
12523
12523
  // packages/experience-design-system-backend-pipeline/dist/src/persistence/src/review-session/repositories/review-session-paths.js
12524
12524
  import { resolve as resolve14 } from "node:path";
12525
12525
  async function getRefineSessionPaths(sessionId, artifactsRoot) {
12526
- const sessionDir = resolve14(artifactsRoot, sessionId);
12526
+ const sessionDir2 = resolve14(artifactsRoot, sessionId);
12527
12527
  return {
12528
- sessionDir,
12529
- eventsPath: resolve14(sessionDir, "events.jsonl"),
12530
- statePath: resolve14(sessionDir, "current-review-state.json")
12528
+ sessionDir: sessionDir2,
12529
+ eventsPath: resolve14(sessionDir2, "events.jsonl"),
12530
+ statePath: resolve14(sessionDir2, "current-review-state.json")
12531
12531
  };
12532
12532
  }
12533
12533
  var init_review_session_paths = __esm({
@@ -14333,7 +14333,7 @@ function errorMessage(error) {
14333
14333
  return error instanceof Error && error.message ? error.message : String(error);
14334
14334
  }
14335
14335
  function defaultSleep(delayMs) {
14336
- return new Promise((resolve25) => setTimeout(resolve25, delayMs));
14336
+ return new Promise((resolve27) => setTimeout(resolve27, delayMs));
14337
14337
  }
14338
14338
  var MAX_RETRY_AFTER_MS;
14339
14339
  var init_http_utils = __esm({
@@ -14609,7 +14609,7 @@ var init_api_client = __esm({
14609
14609
  const progress = maxAttempts > 1 ? attempt / (maxAttempts - 1) : 0;
14610
14610
  const baseDelay = intervalMs + (maxIntervalMs - intervalMs) * progress;
14611
14611
  const jitter = Math.random() * baseDelay * 0.15;
14612
- await new Promise((resolve25) => setTimeout(resolve25, baseDelay + jitter));
14612
+ await new Promise((resolve27) => setTimeout(resolve27, baseDelay + jitter));
14613
14613
  }
14614
14614
  }
14615
14615
  throw new Error(`Operation ${operationId} timed out after ${maxAttempts} attempts`);
@@ -16302,31 +16302,21 @@ async function runMapTokens(request) {
16302
16302
  await bindAnalyticsSessionId(sessionId);
16303
16303
  const tokenLeaves = loadTokenLeaves(db, sessionId);
16304
16304
  const knownTokenPaths = new Set(tokenLeaves.map((t) => t.path));
16305
- const diagnostics = [];
16306
16305
  if (request.tokenMapInline) {
16307
16306
  const validMappings = {};
16308
16307
  for (const [rawName, path5] of Object.entries(request.tokenMapInline)) {
16309
- if (knownTokenPaths.has(path5)) {
16308
+ if (knownTokenPaths.has(path5))
16310
16309
  validMappings[rawName] = path5;
16311
- } else {
16312
- diagnostics.push(`Token map '${rawName}' -> '${path5}': path not found in session tokens \u2014 skipped.`);
16313
- }
16314
16310
  }
16315
16311
  replaceRawTokenNamePaths(db, sessionId, validMappings, "manual");
16316
16312
  }
16317
16313
  const rawDefaults = loadRawDefaults(db, sessionId);
16318
16314
  const defaultResolution = resolveTokenDefaults(rawDefaults.map((row) => ({ rawDefault: row.default_reference, tokenKind: row.cdf_token_kind })), tokenLeaves);
16319
- for (const diagnostic of defaultResolution.diagnostics)
16320
- diagnostics.push(diagnostic.message);
16321
16315
  const manualMappings = new Map(getRawTokenNamePathRows(db, sessionId).filter((row) => row.source === "manual").map((row) => [row.rawName, row.path]));
16322
16316
  const automaticMappings = {};
16323
16317
  for (const [rawName, path5] of Object.entries(defaultResolution.mappings)) {
16324
- const manualPath = manualMappings.get(rawName);
16325
- if (manualPath === void 0) {
16318
+ if (manualMappings.get(rawName) === void 0)
16326
16319
  automaticMappings[rawName] = path5;
16327
- } else if (manualPath !== path5) {
16328
- diagnostics.push(`Token default '${rawName}' automatically resolves to '${path5}', but manual mapping '${manualPath}' is retained.`);
16329
- }
16330
16320
  }
16331
16321
  replaceRawTokenNamePaths(db, sessionId, automaticMappings, "automatic");
16332
16322
  const cdfEntries = loadCDFComponents(db, sessionId);
@@ -16337,7 +16327,7 @@ async function runMapTokens(request) {
16337
16327
  const { groups, tokens } = getDtcgTokensForSession(db, sessionId);
16338
16328
  const tokenCount = tokens.length;
16339
16329
  if (mappablePropCount === 0 || tokenCount === 0) {
16340
- return { type: "nothing-to-map", sessionId, mappablePropCount, tokenCount, diagnostics };
16330
+ return { type: "nothing-to-map", sessionId, mappablePropCount, tokenCount };
16341
16331
  }
16342
16332
  const generatedCdf = Object.fromEntries(cdfEntries.map((c2) => [c2.key, c2.entry]));
16343
16333
  const tokenTree = rebuildDTCGTree(groups, tokens);
@@ -16355,7 +16345,7 @@ async function runMapTokens(request) {
16355
16345
  });
16356
16346
  if (request.printPrompt) {
16357
16347
  const prompt2 = await buildMapPrompt();
16358
- return { type: "printed-prompt", sessionId, prompt: prompt2, diagnostics };
16348
+ return { type: "printed-prompt", sessionId, prompt: prompt2 };
16359
16349
  }
16360
16350
  if (request.skipAgent) {
16361
16351
  const stepId2 = createStep(db, sessionId, "map tokens", {
@@ -16364,7 +16354,7 @@ async function runMapTokens(request) {
16364
16354
  skipAgent: "true"
16365
16355
  });
16366
16356
  updateStep(db, stepId2, "complete", { applied: "0", skipAgent: "true" });
16367
- return { type: "skipped", sessionId, stepId: stepId2, diagnostics };
16357
+ return { type: "skipped", sessionId, stepId: stepId2 };
16368
16358
  }
16369
16359
  const agent = request.agent;
16370
16360
  const noCache = request.cache === false || process.env["EDS_NO_CACHE"] === "1";
@@ -16376,7 +16366,7 @@ async function runMapTokens(request) {
16376
16366
  const applied2 = copyMapTokensFromCache(db, cached.sourceSessionId, sessionId);
16377
16367
  const stepId2 = createStep(db, sessionId, "map tokens", { agent, model: request.model ?? "" });
16378
16368
  updateStep(db, stepId2, "complete", { cached: "true", applied: String(applied2) });
16379
- return { type: "cached", sessionId, applied: applied2, stepId: stepId2, diagnostics };
16369
+ return { type: "cached", sessionId, applied: applied2, stepId: stepId2 };
16380
16370
  }
16381
16371
  }
16382
16372
  const binary = resolveBinary(agent);
@@ -16403,7 +16393,7 @@ async function runMapTokens(request) {
16403
16393
  storeCache(db, inputHash, "token_mapping", "__map_tokens__", sessionId, false, promptHash);
16404
16394
  }
16405
16395
  updateStep(db, stepId, "complete", { applied: String(applied), warnings: String(warnings.length) });
16406
- return { type: "applied", sessionId, applied, warnings, stepId, diagnostics };
16396
+ return { type: "applied", sessionId, applied, warnings, stepId };
16407
16397
  } finally {
16408
16398
  db.close();
16409
16399
  }
@@ -18510,7 +18500,7 @@ async function retryDatabaseWrite(operation, attempts = 8) {
18510
18500
  const message = error instanceof Error ? error.message : String(error);
18511
18501
  if (!/database is locked|database is busy/i.test(message) || attempt >= attempts)
18512
18502
  throw error;
18513
- await new Promise((resolve25) => setTimeout(resolve25, Math.min(250 * attempt, 2e3)));
18503
+ await new Promise((resolve27) => setTimeout(resolve27, Math.min(250 * attempt, 2e3)));
18514
18504
  }
18515
18505
  }
18516
18506
  }
@@ -19527,13 +19517,12 @@ async function writeSettings2(settings) {
19527
19517
  async function updateSettings2(patch) {
19528
19518
  await writeSettings2({ ...await readSettings2(), ...patch });
19529
19519
  }
19530
- var configFilePath2, runsFilePath2, debugSessionsDir2, oldConfigDir2;
19520
+ var configFilePath2, runsFilePath2, oldConfigDir2;
19531
19521
  var init_config = __esm({
19532
19522
  "packages/experience-design-system-types/dist/src/config/index.js"() {
19533
19523
  "use strict";
19534
19524
  configFilePath2 = () => join17(configRoot2(), "config.json");
19535
19525
  runsFilePath2 = () => join17(configRoot2(), "state", "runs.json");
19536
- debugSessionsDir2 = () => join17(configRoot2(), "debug", "sessions");
19537
19526
  oldConfigDir2 = () => join17(homedir2(), ".config", "experiences");
19538
19527
  }
19539
19528
  });
@@ -20777,11 +20766,34 @@ var init_shared2 = __esm({
20777
20766
  });
20778
20767
 
20779
20768
  // packages/experience-design-system-cli/src/tui/import/steps/05-token-reuse/logic.ts
20780
- import { access as access5, stat as stat4 } from "node:fs/promises";
20769
+ import { access as access5, readdir as readdir2, stat as stat4 } from "node:fs/promises";
20781
20770
  import { join as join19 } from "node:path";
20782
- async function inspectTokens({ rawTokensPath, outDir, cache }) {
20771
+ async function findLatestTokens(contentfulDir) {
20772
+ const candidates = [join19(contentfulDir, "tokens.json")];
20773
+ try {
20774
+ for (const session of await readdir2(contentfulDir, { withFileTypes: true })) {
20775
+ if (!session.isDirectory()) continue;
20776
+ for (const run of await readdir2(join19(contentfulDir, session.name), { withFileTypes: true }).catch(() => [])) {
20777
+ if (run.isDirectory() && /^dsi-import-\d+$/.test(run.name)) {
20778
+ candidates.push(join19(contentfulDir, session.name, run.name, "tokens.json"));
20779
+ }
20780
+ }
20781
+ }
20782
+ } catch {
20783
+ }
20784
+ const found = [];
20785
+ for (const path5 of candidates) {
20786
+ try {
20787
+ found.push({ path: path5, mtimeMs: (await stat4(path5)).mtimeMs });
20788
+ } catch {
20789
+ }
20790
+ }
20791
+ return found.sort((a, b) => b.mtimeMs - a.mtimeMs)[0]?.path ?? null;
20792
+ }
20793
+ async function inspectTokens({ rawTokensPath, contentfulDir, cache }) {
20783
20794
  if (!cache) return { kind: "none" };
20784
- const tokensPath = join19(outDir, "tokens.json");
20795
+ const tokensPath = await findLatestTokens(contentfulDir);
20796
+ if (!tokensPath) return { kind: "none" };
20785
20797
  try {
20786
20798
  await access5(tokensPath);
20787
20799
  } catch {
@@ -21093,7 +21105,7 @@ var init_selection2 = __esm({
21093
21105
  import { mkdir as mkdir7 } from "node:fs/promises";
21094
21106
  import { join as join21, resolve as resolve22 } from "node:path";
21095
21107
  async function runExtraction(input, onProgress, deps = realDeps) {
21096
- const outDir = join21(resolve22(input.projectPath), ".contentful");
21108
+ const outDir = input.outDir ?? join21(resolve22(input.projectPath), ".contentful");
21097
21109
  let progress = initialProgress({
21098
21110
  hasCredentials: input.credentials !== null,
21099
21111
  hasRawTokens: input.rawTokensPath !== "",
@@ -24535,7 +24547,7 @@ async function runGeneration(input, onProgress, deps = realDeps3) {
24535
24547
  update({ mapTokens: "running" });
24536
24548
  try {
24537
24549
  const mapTokensOptions = await buildMapTokensOptions(input);
24538
- const mapResult = await deps.runMapTokens({
24550
+ await deps.runMapTokens({
24539
24551
  sessionId: input.sessionId,
24540
24552
  agent: input.agent,
24541
24553
  ...input.agentModel ? { model: input.agentModel } : {},
@@ -24543,11 +24555,6 @@ async function runGeneration(input, onProgress, deps = realDeps3) {
24543
24555
  skillPathOverride: MAP_TOKENS_SKILL_PATH,
24544
24556
  ...mapTokensOptions
24545
24557
  });
24546
- if (mapResult.diagnostics.length > 0) {
24547
- process.stderr.write(`Unresolved token defaults:
24548
- ${mapResult.diagnostics.map((d) => ` ${d}`).join("\n")}
24549
- `);
24550
- }
24551
24558
  } catch (error) {
24552
24559
  const message = error instanceof MapTokensRunFailure ? error.message : error instanceof Error ? error.message : String(error);
24553
24560
  return fail2("map tokens", message);
@@ -32218,7 +32225,7 @@ var init_save = __esm({
32218
32225
  writeFile: (path5, contents) => writeFile7(path5, contents),
32219
32226
  appendRun,
32220
32227
  buildSourceFingerprint,
32221
- sleep: (ms) => new Promise((resolve25) => setTimeout(resolve25, ms)),
32228
+ sleep: (ms) => new Promise((resolve27) => setTimeout(resolve27, ms)),
32222
32229
  warn: (message) => process.stderr.write(message)
32223
32230
  });
32224
32231
  }
@@ -32240,7 +32247,7 @@ var init_types9 = __esm({
32240
32247
  import { appendFileSync, writeFileSync } from "node:fs";
32241
32248
  import { mkdir as mkdir8 } from "node:fs/promises";
32242
32249
  import { tmpdir } from "node:os";
32243
- import { join as join25 } from "node:path";
32250
+ import { join as join25, resolve as resolve25 } from "node:path";
32244
32251
  function appendWizardLog(entry) {
32245
32252
  appendFileSync(WIZARD_LOG, JSON.stringify({ ts: (/* @__PURE__ */ new Date()).toISOString(), ...entry }) + "\n");
32246
32253
  }
@@ -32488,7 +32495,7 @@ function createFlowController(start, deps) {
32488
32495
  },
32489
32496
  async submitPath(submitted) {
32490
32497
  await deps.mkdir(submitted);
32491
- if (await deps.detectSaveConflict(submitted)) {
32498
+ if (resolve25(submitted) !== resolve25(state2.outDir) && await deps.detectSaveConflict(submitted)) {
32492
32499
  const subdir = deps.buildTimestampedSubdir(submitted);
32493
32500
  await deps.mkdir(subdir);
32494
32501
  await proceedToWrite(subdir);
@@ -32576,9 +32583,18 @@ var init_debug_mode_store = __esm({
32576
32583
  });
32577
32584
 
32578
32585
  // packages/experience-design-system-cli/src/tui/debug-store.ts
32586
+ var debug_store_exports = {};
32587
+ __export(debug_store_exports, {
32588
+ currentDebugSessionDir: () => currentDebugSessionDir,
32589
+ currentSessionDir: () => currentSessionDir,
32590
+ finishDebugRun: () => finishDebugRun,
32591
+ startDebugRun: () => startDebugRun,
32592
+ startDebugSessionIn: () => startDebugSessionIn,
32593
+ startImportRun: () => startImportRun
32594
+ });
32579
32595
  import { mkdir as mkdir9, writeFile as writeFile8 } from "node:fs/promises";
32580
32596
  import { existsSync as existsSync11, readdirSync as readdirSync4 } from "node:fs";
32581
- import { join as join26 } from "node:path";
32597
+ import { join as join26, resolve as resolve26 } from "node:path";
32582
32598
  function generateRunId() {
32583
32599
  const now = /* @__PURE__ */ new Date();
32584
32600
  const pad = (n) => String(n).padStart(2, "0");
@@ -32591,10 +32607,17 @@ function datePrefix(now = /* @__PURE__ */ new Date()) {
32591
32607
  function slugify(value) {
32592
32608
  return value.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
32593
32609
  }
32594
- function generateSessionId3() {
32610
+ async function readBaseDir() {
32611
+ try {
32612
+ const dir = (await readSettings2())["contentfulBaseDir"];
32613
+ return typeof dir === "string" && dir !== "" ? resolve26(dir) : void 0;
32614
+ } catch {
32615
+ return void 0;
32616
+ }
32617
+ }
32618
+ function nextSessionId(contentfulDir) {
32595
32619
  const today = datePrefix();
32596
- const root = debugSessionsDir2();
32597
- const existing = existsSync11(root) ? readdirSync4(root) : [];
32620
+ const existing = existsSync11(contentfulDir) ? readdirSync4(contentfulDir) : [];
32598
32621
  const seqPattern = new RegExp(`^${today}-session-(\\d+)$`);
32599
32622
  const maxSeq = existing.reduce((max, entry) => {
32600
32623
  const match2 = seqPattern.exec(entry);
@@ -32602,11 +32625,38 @@ function generateSessionId3() {
32602
32625
  }, 0);
32603
32626
  return `${today}-session-${maxSeq + 1}`;
32604
32627
  }
32605
- function sessionDebugDir() {
32606
- return join26(debugSessionsDir2(), SESSION_ID);
32628
+ function startSession(base, { replace }) {
32629
+ const contentfulDir = join26(base, ".contentful");
32630
+ if (replace || !sessionDir) sessionDir = join26(contentfulDir, nextSessionId(contentfulDir));
32631
+ return sessionDir;
32607
32632
  }
32608
32633
  function currentDebugSessionDir() {
32609
- return sessionDebugDir();
32634
+ return sessionDir && join26(sessionDir, "debug");
32635
+ }
32636
+ function currentSessionDir() {
32637
+ return sessionDir;
32638
+ }
32639
+ async function startDebugSessionIn(base, { replace = false } = {}) {
32640
+ try {
32641
+ if (!await isDebugModeEnabled()) return;
32642
+ await mkdir9(join26(startSession(resolve26(base), { replace }), "debug"), { recursive: true });
32643
+ } catch {
32644
+ }
32645
+ }
32646
+ function nextImportRunDir(session) {
32647
+ const existing = existsSync11(session) ? readdirSync4(session) : [];
32648
+ const maxRun = existing.reduce((max, entry) => {
32649
+ const match2 = /^dsi-import-(\d+)$/.exec(entry);
32650
+ return match2 ? Math.max(max, Number(match2[1])) : max;
32651
+ }, 0);
32652
+ return join26(session, `dsi-import-${maxRun + 1}`);
32653
+ }
32654
+ async function startImportRun(projectPath) {
32655
+ await startDebugSessionIn(projectPath);
32656
+ if (!sessionDir) return join26(resolve26(projectPath), ".contentful");
32657
+ const dir = nextImportRunDir(sessionDir);
32658
+ await mkdir9(dir, { recursive: true });
32659
+ return dir;
32610
32660
  }
32611
32661
  async function isDebugModeEnabled() {
32612
32662
  try {
@@ -32647,8 +32697,10 @@ async function finishDebugRun({
32647
32697
  pendingRun = void 0;
32648
32698
  const durationMs = Date.now() - run.startedAt;
32649
32699
  const content = renderMarkdown(run, { outputs: redact(outputs), status, exitMethod, durationMs });
32700
+ const root = currentDebugSessionDir();
32701
+ if (!root) return;
32650
32702
  const flowSegments = run.flow.split("/");
32651
- const dir = join26(sessionDebugDir(), ...flowSegments);
32703
+ const dir = join26(root, ...flowSegments);
32652
32704
  await mkdir9(dir, { recursive: true });
32653
32705
  const filename = nextAttemptFilename(dir, run.menuOption);
32654
32706
  await writeFile8(join26(dir, filename), content, { mode: 384 });
@@ -32695,17 +32747,16 @@ ${JSON.stringify(finish.outputs, null, 2)}
32695
32747
  function handleCrash() {
32696
32748
  return finishDebugRun({ outputs: {}, status: "error", exitMethod: "crashed" });
32697
32749
  }
32698
- var pendingRun, SESSION_ID;
32750
+ var pendingRun, sessionDir;
32699
32751
  var init_debug_store = __esm({
32700
32752
  "packages/experience-design-system-cli/src/tui/debug-store.ts"() {
32701
32753
  "use strict";
32702
32754
  init_config();
32703
32755
  init_version();
32704
32756
  init_debug_mode_store();
32705
- SESSION_ID = generateSessionId3();
32706
- void isDebugModeEnabled().then((enabled) => {
32707
- if (!enabled) return void 0;
32708
- return mkdir9(sessionDebugDir(), { recursive: true });
32757
+ void Promise.all([isDebugModeEnabled(), readBaseDir()]).then(([enabled, base]) => {
32758
+ if (!enabled || !base) return void 0;
32759
+ return mkdir9(join26(startSession(base, { replace: false }), "debug"), { recursive: true });
32709
32760
  });
32710
32761
  process.once("uncaughtException", (err) => {
32711
32762
  void handleCrash().finally(() => {
@@ -32731,8 +32782,7 @@ async function readHelpInfo() {
32731
32782
  return {
32732
32783
  storage: [
32733
32784
  { label: "Config folder", value: configRoot2() },
32734
- { label: "Settings file", value: configFilePath2() },
32735
- { label: "Debug logs", value: debugSessionsDir2() }
32785
+ { label: "Settings file", value: configFilePath2() }
32736
32786
  ],
32737
32787
  troubleshooting: [
32738
32788
  { label: "CLI version", value: readPackageVersion() },
@@ -32741,7 +32791,7 @@ async function readHelpInfo() {
32741
32791
  { label: "Debug Mode", value: debugMode.enabled ? "on" : "off" },
32742
32792
  {
32743
32793
  label: "This session",
32744
- value: debugMode.enabled ? currentDebugSessionDir() : "no logs written while Debug Mode is off"
32794
+ value: !debugMode.enabled ? "no logs written while Debug Mode is off" : currentDebugSessionDir() ?? "not started: set the Root Project Directory in Settings, or start an import"
32745
32795
  }
32746
32796
  ]
32747
32797
  };
@@ -32887,7 +32937,8 @@ async function readCredentials() {
32887
32937
  cmaToken: store.cmaToken || "",
32888
32938
  host: store.host || "",
32889
32939
  defaultComponentDir: store.defaultComponentDir || "",
32890
- defaultTokenFile: store.defaultTokenFile || ""
32940
+ defaultTokenFile: store.defaultTokenFile || "",
32941
+ contentfulBaseDir: store.contentfulBaseDir || ""
32891
32942
  };
32892
32943
  }
32893
32944
  async function writeCredentials(config) {
@@ -32920,7 +32971,8 @@ function debugFields(config) {
32920
32971
  cma_token: config?.cmaToken ?? "",
32921
32972
  host: config?.host ?? "",
32922
32973
  default_component_dir: config?.defaultComponentDir ?? "",
32923
- default_token_file: config?.defaultTokenFile ?? ""
32974
+ default_token_file: config?.defaultTokenFile ?? "",
32975
+ contentful_base_dir: config?.contentfulBaseDir ?? ""
32924
32976
  };
32925
32977
  }
32926
32978
  function ConfigurationScreen({ onDone }) {
@@ -32958,6 +33010,7 @@ function ConfigurationScreen({ onDone }) {
32958
33010
  setNotice(null);
32959
33011
  writeCredentials(config).then(() => {
32960
33012
  setLastSaved(config);
33013
+ if (config.contentfulBaseDir) void startDebugSessionIn(config.contentfulBaseDir, { replace: true });
32961
33014
  setNotice({ kind: "success", text: "Configuration saved" });
32962
33015
  setStage("form");
32963
33016
  }).catch((err) => {
@@ -33023,10 +33076,7 @@ function ConfigurationScreen({ onDone }) {
33023
33076
  const display = field === "cmaToken" ? "\u2022".repeat(value.length) : value;
33024
33077
  return /* @__PURE__ */ jsxs45(Box44, { gap: 1, children: [
33025
33078
  /* @__PURE__ */ jsx55(Text46, { color: isActive ? PALETTE.accent : void 0, children: isActive ? "\u276F" : " " }),
33026
- /* @__PURE__ */ jsxs45(Text46, { bold: isActive, children: [
33027
- FIELD_LABELS[field],
33028
- ":"
33029
- ] }),
33079
+ /* @__PURE__ */ jsx55(Box44, { width: LABEL_WIDTH, flexShrink: 0, children: /* @__PURE__ */ jsx55(Text46, { bold: isActive, color: isActive ? PALETTE.accent : PALETTE.muted, children: FIELD_LABELS[field] }) }),
33030
33080
  isActive && editing ? /* @__PURE__ */ jsx55(
33031
33081
  TextInput4,
33032
33082
  {
@@ -33035,7 +33085,8 @@ function ConfigurationScreen({ onDone }) {
33035
33085
  onSubmit: () => setEditing(false),
33036
33086
  mask: field === "cmaToken" ? "\u2022" : void 0
33037
33087
  }
33038
- ) : /* @__PURE__ */ jsx55(Text46, { children: display || /* @__PURE__ */ jsx55(Text46, { color: PALETTE.muted, children: "(empty)" }) })
33088
+ ) : /* @__PURE__ */ jsx55(Text46, { bold: !!display, children: display || (FIELD_HINTS[field] ? "" : /* @__PURE__ */ jsx55(Text46, { color: PALETTE.muted, children: "(empty)" })) }),
33089
+ FIELD_HINTS[field] && /* @__PURE__ */ jsx55(Text46, { color: PALETTE.muted, children: FIELD_HINTS[field] })
33039
33090
  ] }, field);
33040
33091
  }) }),
33041
33092
  notice && /* @__PURE__ */ jsxs45(Fragment17, { children: [
@@ -33066,7 +33117,7 @@ function ConfigurationScreen({ onDone }) {
33066
33117
  )
33067
33118
  ] });
33068
33119
  }
33069
- var FIELD_ORDER, FIELD_LABELS;
33120
+ var FIELD_ORDER, FIELD_LABELS, FIELD_HINTS, LABEL_WIDTH;
33070
33121
  var init_ContentfulConfigScreen = __esm({
33071
33122
  "packages/experience-design-system-cli/src/tui/settings/contentful-configuration/ContentfulConfigScreen.tsx"() {
33072
33123
  "use strict";
@@ -33080,16 +33131,22 @@ var init_ContentfulConfigScreen = __esm({
33080
33131
  "cmaToken",
33081
33132
  "host",
33082
33133
  "defaultComponentDir",
33083
- "defaultTokenFile"
33134
+ "defaultTokenFile",
33135
+ "contentfulBaseDir"
33084
33136
  ];
33085
33137
  FIELD_LABELS = {
33086
33138
  spaceId: "Space ID",
33087
33139
  environmentId: "Environment ID",
33088
33140
  cmaToken: "CMA Token",
33089
- host: "API Host (optional)",
33090
- defaultComponentDir: "Default component directory (optional)",
33091
- defaultTokenFile: "Default token file (optional)"
33141
+ host: "API Host",
33142
+ defaultComponentDir: "Default component directory",
33143
+ defaultTokenFile: "Default token file",
33144
+ contentfulBaseDir: "Root Project Directory"
33145
+ };
33146
+ FIELD_HINTS = {
33147
+ contentfulBaseDir: "(where .contentful goes)"
33092
33148
  };
33149
+ LABEL_WIDTH = Math.max(...Object.values(FIELD_LABELS).map((label) => label.length));
33093
33150
  }
33094
33151
  });
33095
33152
 
@@ -33362,7 +33419,7 @@ function App({ importOptions, inkClear }) {
33362
33419
  const launch = { projectPath: projectPath2, tokens, filePaths, ...importOptions };
33363
33420
  const state2 = await inspectTokens({
33364
33421
  rawTokensPath: tokens,
33365
- outDir: join27(resolveUserPath(projectPath2), ".contentful"),
33422
+ contentfulDir: join27(resolveUserPath(projectPath2), ".contentful"),
33366
33423
  cache: importOptions.cache
33367
33424
  });
33368
33425
  if (state2.kind === "cached") {
@@ -33383,6 +33440,7 @@ function App({ importOptions, inkClear }) {
33383
33440
  const settings = await readSettings2();
33384
33441
  const { agent, agentModel } = resolveAgentChoice(launch.agent, settings);
33385
33442
  const generatePromptPath = typeof settings.generatePromptPath === "string" ? settings.generatePromptPath : void 0;
33443
+ const outDir = await (await Promise.resolve().then(() => (init_debug_store(), debug_store_exports))).startImportRun(resolveUserPath(launch.projectPath ?? ""));
33386
33444
  setExtractionRun({
33387
33445
  ...generatePromptPath ? { generatePromptPath } : {},
33388
33446
  // the later steps get the same agent, so they use what the stage used
@@ -33391,6 +33449,7 @@ function App({ importOptions, inkClear }) {
33391
33449
  tokenStrategy,
33392
33450
  input: {
33393
33451
  projectPath: resolveUserPath(launch.projectPath ?? ""),
33452
+ outDir,
33394
33453
  filePaths: launch.filePaths ?? [],
33395
33454
  rawTokensPath: launch.tokens ?? "",
33396
33455
  tokenStrategy,
@@ -33738,14 +33797,14 @@ function runDevWatch(args) {
33738
33797
  process.stderr.write("--watch only works from a checkout of the repo (scripts/dev.mjs is not in the package).\n");
33739
33798
  return Promise.resolve(1);
33740
33799
  }
33741
- return new Promise((resolve25) => {
33800
+ return new Promise((resolve27) => {
33742
33801
  const child = spawn4(process.execPath, [script, ...args], { stdio: "inherit" });
33743
33802
  process.on("SIGINT", () => void 0);
33744
- child.on("exit", (code) => resolve25(code ?? 0));
33803
+ child.on("exit", (code) => resolve27(code ?? 0));
33745
33804
  child.on("error", (err) => {
33746
33805
  process.stderr.write(`${err.message}
33747
33806
  `);
33748
- resolve25(1);
33807
+ resolve27(1);
33749
33808
  });
33750
33809
  });
33751
33810
  }
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-7652d7c0.0",
3
+ "version": "2.37.1-dev-build-6fb2b08b.0",
4
4
  "description": "Contentful Experiences design system import CLI",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -1,6 +1,23 @@
1
1
  type Status = 'success' | 'error';
2
2
  type ExitMethod = 'saved' | 'discarded' | 'crashed';
3
- export declare function currentDebugSessionDir(): string;
3
+ export declare function currentDebugSessionDir(): string | undefined;
4
+ /** This terminal session's folder, `<base>/.contentful/<session>/`, or undefined until it is known. */
5
+ export declare function currentSessionDir(): string | undefined;
6
+ /**
7
+ * Starts this terminal session's folder in `base`. The base directory setting being saved passes `replace` so the new
8
+ * location wins; the import passes nothing and only starts a session when none exists yet. Fail-open like the rest of
9
+ * the logger.
10
+ */
11
+ export declare function startDebugSessionIn(base: string, { replace }?: {
12
+ replace?: boolean | undefined;
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>;
4
21
  export declare function startDebugRun({ flow, step, menuOption, inputs, }: {
5
22
  flow: string;
6
23
  step: string;
@@ -8,10 +8,11 @@ export type TokensState = {
8
8
  };
9
9
  interface InspectInput {
10
10
  rawTokensPath: string;
11
- outDir: 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;
12
13
  cache: boolean;
13
14
  }
14
- export declare function inspectTokens({ rawTokensPath, outDir, cache }: InspectInput): Promise<TokensState>;
15
+ export declare function inspectTokens({ rawTokensPath, contentfulDir, cache }: InspectInput): Promise<TokensState>;
15
16
  export declare function gateText({ tokensPath, sourceChanged }: {
16
17
  tokensPath: string;
17
18
  sourceChanged: boolean;
@@ -2,6 +2,8 @@ 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;
5
7
  /** Absolute source files from the path-validation step (collectFiles output). */
6
8
  filePaths: string[];
7
9
  /** Raw tokens file the user pointed at (always set: v2 asks for one). */
@@ -5,6 +5,7 @@ export type V1Credentials = {
5
5
  host?: string;
6
6
  defaultComponentDir?: string;
7
7
  defaultTokenFile?: string;
8
+ contentfulBaseDir?: string;
8
9
  [key: string]: string | undefined;
9
10
  };
10
11
  export declare function readCredentials(): Promise<V1Credentials>;
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contentful/experience-design-system-cli",
3
- "version": "2.37.1-dev-build-7652d7c0.0",
3
+ "version": "2.37.1-dev-build-6fb2b08b.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-7652d7c0.0",
3
+ "version": "2.37.1-dev-build-6fb2b08b.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-7652d7c0.0",
49
- "@contentful/experience-design-system-types": "2.37.1-dev-build-7652d7c0.0"
48
+ "@contentful/experience-design-system-backend-pipeline": "2.37.1-dev-build-6fb2b08b.0",
49
+ "@contentful/experience-design-system-types": "2.37.1-dev-build-6fb2b08b.0"
50
50
  },
51
51
  "devDependencies": {
52
52
  "@tsconfig/node24": "^24.0.4",