@contentful/experience-design-system-cli 2.37.1-dev-build-eed963c1.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/app.js CHANGED
@@ -8,6 +8,71 @@ var __export = (target, all) => {
8
8
  __defProp(target, name, { get: all[name], enumerable: true });
9
9
  };
10
10
 
11
+ // packages/experience-design-system-cli/src/tui/package-root.ts
12
+ import { existsSync, readFileSync } from "node:fs";
13
+ import { dirname, join } from "node:path";
14
+ import { fileURLToPath } from "node:url";
15
+ function findPackageRoot(startUrl, packageName) {
16
+ let dir = dirname(fileURLToPath(startUrl));
17
+ let found;
18
+ while (true) {
19
+ const manifestPath = join(dir, "package.json");
20
+ if (existsSync(manifestPath)) {
21
+ const pkg = JSON.parse(readFileSync(manifestPath, "utf8"));
22
+ if (pkg.name === packageName) found = dir;
23
+ }
24
+ const parent = dirname(dir);
25
+ if (parent === dir) return found ?? dir;
26
+ dir = parent;
27
+ }
28
+ }
29
+ var init_package_root = __esm({
30
+ "packages/experience-design-system-cli/src/tui/package-root.ts"() {
31
+ "use strict";
32
+ }
33
+ });
34
+
35
+ // packages/experience-design-system-cli/src/tui/upgrade/version.ts
36
+ import { readFileSync as readFileSync2 } from "node:fs";
37
+ import { join as join2 } from "node:path";
38
+ import semver from "semver";
39
+ function readPackageVersion() {
40
+ const root = findPackageRoot(import.meta.url, PACKAGE_NAME);
41
+ const pkg = JSON.parse(readFileSync2(join2(root, "package.json"), "utf8"));
42
+ return pkg.version ?? "unknown";
43
+ }
44
+ function parseVersionTag(tag) {
45
+ const match2 = /^v(\d+\.\d+\.\d+)$/.exec(tag);
46
+ return match2 ? match2[1] : void 0;
47
+ }
48
+ async function checkForUpgrade() {
49
+ const current = readPackageVersion();
50
+ try {
51
+ const response = await fetch(TAGS_URL);
52
+ if (!response.ok) return { status: "error" };
53
+ const tags = await response.json();
54
+ const versions = tags.map((tag) => tag.name ? parseVersionTag(tag.name) : void 0).filter((v) => v !== void 0);
55
+ if (versions.length === 0) return { status: "error" };
56
+ const latest = versions.reduce((best, v) => semver.gt(v, best) ? v : best);
57
+ if (!semver.valid(current)) return { status: "error" };
58
+ if (semver.gt(latest, current)) {
59
+ return { status: "update-available", current, latest };
60
+ }
61
+ return { status: "up-to-date", current };
62
+ } catch {
63
+ return { status: "error" };
64
+ }
65
+ }
66
+ var PACKAGE_NAME, TAGS_URL;
67
+ var init_version = __esm({
68
+ "packages/experience-design-system-cli/src/tui/upgrade/version.ts"() {
69
+ "use strict";
70
+ init_package_root();
71
+ PACKAGE_NAME = "@contentful/experience-design-system-cli";
72
+ TAGS_URL = "https://api.github.com/repos/contentful/experience-design-system-sdk-public/tags?per_page=10";
73
+ }
74
+ });
75
+
11
76
  // packages/experience-design-system-backend-pipeline/dist/src/agents/types/agent-name.js
12
77
  var AGENT_NAMES;
13
78
  var init_agent_name = __esm({
@@ -772,7 +837,7 @@ async function runAgent(options) {
772
837
  promptLen: prompt.length,
773
838
  promptHead: prompt.slice(0, 500)
774
839
  });
775
- return new Promise((resolve25) => {
840
+ return new Promise((resolve27) => {
776
841
  const bedrockEnv = bedrock ? BEDROCK_ENV_BY_AGENT[agent] : void 0;
777
842
  const child = spawn(binary, args, {
778
843
  stdio: ["pipe", "pipe", "pipe"],
@@ -821,7 +886,7 @@ async function runAgent(options) {
821
886
  stderrLen: stderr.length,
822
887
  stderrTail: stderr.slice(-1e3)
823
888
  });
824
- resolve25(result);
889
+ resolve27(result);
825
890
  });
826
891
  });
827
892
  }
@@ -843,7 +908,7 @@ async function checkAgentAuth(agent) {
843
908
  return "not-found";
844
909
  if (agent !== "claude")
845
910
  return "ok";
846
- return new Promise((resolve25) => {
911
+ return new Promise((resolve27) => {
847
912
  const child = spawn2(binary, ["auth", "status", "--json"], { stdio: ["ignore", "pipe", "pipe"] });
848
913
  let stdout = "";
849
914
  let done = false;
@@ -852,7 +917,7 @@ async function checkAgentAuth(agent) {
852
917
  return;
853
918
  done = true;
854
919
  child.kill("SIGTERM");
855
- resolve25("unauthenticated");
920
+ resolve27("unauthenticated");
856
921
  }, 5e3);
857
922
  child.stdout?.on("data", (chunk) => {
858
923
  stdout += chunk.toString();
@@ -863,14 +928,14 @@ async function checkAgentAuth(agent) {
863
928
  done = true;
864
929
  clearTimeout(timer);
865
930
  if (code !== 0) {
866
- resolve25("unauthenticated");
931
+ resolve27("unauthenticated");
867
932
  return;
868
933
  }
869
934
  try {
870
935
  const status = JSON.parse(stdout);
871
- resolve25(status.loggedIn ? "ok" : "unauthenticated");
936
+ resolve27(status.loggedIn ? "ok" : "unauthenticated");
872
937
  } catch {
873
- resolve25("unauthenticated");
938
+ resolve27("unauthenticated");
874
939
  }
875
940
  });
876
941
  });
@@ -880,9 +945,9 @@ async function binaryIsOnPath(binary) {
880
945
  const fs = await import("node:fs/promises");
881
946
  return fs.access(binary).then(() => true, () => false);
882
947
  }
883
- return new Promise((resolve25) => {
948
+ return new Promise((resolve27) => {
884
949
  const child = spawn2(process.platform === "win32" ? "where" : "which", [binary], { stdio: "ignore" });
885
- child.on("close", (code) => resolve25(code === 0));
950
+ child.on("close", (code) => resolve27(code === 0));
886
951
  });
887
952
  }
888
953
  var init_check_agent_auth = __esm({
@@ -2016,6 +2081,253 @@ var init_cache_keys = __esm({
2016
2081
  }
2017
2082
  });
2018
2083
 
2084
+ // packages/experience-design-system-types/dist/src/config/index.js
2085
+ import { randomBytes as randomBytes4 } from "node:crypto";
2086
+ import { mkdir as mkdir6, readFile as readFile18, rename as rename2, writeFile as writeFile6 } from "node:fs/promises";
2087
+ import { homedir as homedir3 } from "node:os";
2088
+ import { dirname as dirname13, join as join17 } from "node:path";
2089
+ function configRoot2() {
2090
+ return process.env["EDS_HOME"] || join17(homedir3(), ".contentful", "experience-design-system-cli");
2091
+ }
2092
+ async function readSettings2() {
2093
+ try {
2094
+ return JSON.parse(await readFile18(configFilePath2(), "utf8"));
2095
+ } catch {
2096
+ return {};
2097
+ }
2098
+ }
2099
+ async function writeSettings2(settings) {
2100
+ const path5 = configFilePath2();
2101
+ await mkdir6(dirname13(path5), { recursive: true });
2102
+ const tmp = `${path5}.${process.pid}.${randomBytes4(4).toString("hex")}.tmp`;
2103
+ await writeFile6(tmp, `${JSON.stringify(settings, null, 2)}
2104
+ `, { mode: 384 });
2105
+ await rename2(tmp, path5);
2106
+ }
2107
+ async function updateSettings2(patch) {
2108
+ await writeSettings2({ ...await readSettings2(), ...patch });
2109
+ }
2110
+ var configFilePath2;
2111
+ var init_config = __esm({
2112
+ "packages/experience-design-system-types/dist/src/config/index.js"() {
2113
+ "use strict";
2114
+ configFilePath2 = () => join17(configRoot2(), "config.json");
2115
+ }
2116
+ });
2117
+
2118
+ // packages/experience-design-system-cli/src/tui/settings/debug-mode/debug-mode-store.ts
2119
+ async function readDebugModeSetting() {
2120
+ const { debugMode } = await readSettings2();
2121
+ return { ...DEFAULT_DEBUG_MODE_SETTING, ...debugMode };
2122
+ }
2123
+ async function writeDebugModeSetting(setting) {
2124
+ await updateSettings2({ debugMode: setting });
2125
+ }
2126
+ var DEFAULT_DEBUG_MODE_SETTING;
2127
+ var init_debug_mode_store = __esm({
2128
+ "packages/experience-design-system-cli/src/tui/settings/debug-mode/debug-mode-store.ts"() {
2129
+ "use strict";
2130
+ init_config();
2131
+ DEFAULT_DEBUG_MODE_SETTING = {
2132
+ enabled: true
2133
+ };
2134
+ }
2135
+ });
2136
+
2137
+ // packages/experience-design-system-cli/src/tui/debug-store.ts
2138
+ var debug_store_exports = {};
2139
+ __export(debug_store_exports, {
2140
+ currentDebugSessionDir: () => currentDebugSessionDir,
2141
+ currentSessionDir: () => currentSessionDir,
2142
+ finishDebugRun: () => finishDebugRun,
2143
+ startDebugRun: () => startDebugRun,
2144
+ startDebugSessionIn: () => startDebugSessionIn,
2145
+ startImportRun: () => startImportRun
2146
+ });
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";
2150
+ function generateRunId() {
2151
+ const now = /* @__PURE__ */ new Date();
2152
+ const pad = (n) => String(n).padStart(2, "0");
2153
+ return `${now.getFullYear()}${pad(now.getMonth() + 1)}${pad(now.getDate())}-${pad(now.getHours())}${pad(now.getMinutes())}${pad(now.getSeconds())}`;
2154
+ }
2155
+ function datePrefix(now = /* @__PURE__ */ new Date()) {
2156
+ const pad = (n) => String(n).padStart(2, "0");
2157
+ return `${pad(now.getMonth() + 1)}-${pad(now.getDate())}-${now.getFullYear()}`;
2158
+ }
2159
+ function slugify(value) {
2160
+ return value.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
2161
+ }
2162
+ async function readBaseDir() {
2163
+ try {
2164
+ const dir = (await readSettings2())["contentfulBaseDir"];
2165
+ return typeof dir === "string" && dir !== "" ? resolve26(dir) : void 0;
2166
+ } catch {
2167
+ return void 0;
2168
+ }
2169
+ }
2170
+ function nextSessionId(contentfulDir) {
2171
+ const today = datePrefix();
2172
+ const existing = existsSync9(contentfulDir) ? readdirSync4(contentfulDir) : [];
2173
+ const seqPattern = new RegExp(`^${today}-session-(\\d+)$`);
2174
+ const maxSeq = existing.reduce((max, entry) => {
2175
+ const match2 = seqPattern.exec(entry);
2176
+ return match2 ? Math.max(max, Number(match2[1])) : max;
2177
+ }, 0);
2178
+ return `${today}-session-${maxSeq + 1}`;
2179
+ }
2180
+ function startSession(base, { replace }) {
2181
+ const contentfulDir = join24(base, ".contentful");
2182
+ if (replace || !sessionDir) sessionDir = join24(contentfulDir, nextSessionId(contentfulDir));
2183
+ return sessionDir;
2184
+ }
2185
+ function currentDebugSessionDir() {
2186
+ return sessionDir && join24(sessionDir, "debug");
2187
+ }
2188
+ function currentSessionDir() {
2189
+ return sessionDir;
2190
+ }
2191
+ async function startDebugSessionIn(base, { replace = false } = {}) {
2192
+ try {
2193
+ if (!await isDebugModeEnabled()) return;
2194
+ await mkdir9(join24(startSession(resolve26(base), { replace }), "debug"), { recursive: true });
2195
+ } catch {
2196
+ }
2197
+ }
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
+ async function isDebugModeEnabled() {
2214
+ try {
2215
+ return (await readDebugModeSetting()).enabled;
2216
+ } catch {
2217
+ return true;
2218
+ }
2219
+ }
2220
+ function redact(value) {
2221
+ const clone = { ...value };
2222
+ if ("cma_token" in clone) {
2223
+ const raw = clone.cma_token;
2224
+ clone.cma_token = typeof raw === "string" && raw.length > 0 ? `[present, ${raw.length} chars]` : "[not set]";
2225
+ }
2226
+ return clone;
2227
+ }
2228
+ function startDebugRun({
2229
+ flow,
2230
+ step,
2231
+ menuOption,
2232
+ inputs
2233
+ }) {
2234
+ const runId = generateRunId();
2235
+ const startedAt = Date.now();
2236
+ const redactedInputs = redact(inputs);
2237
+ isDebugModeEnabled().then((enabled) => {
2238
+ if (!enabled) return;
2239
+ pendingRun = { flow, step, runId, menuOption, inputs: redactedInputs, startedAt };
2240
+ });
2241
+ }
2242
+ async function finishDebugRun({
2243
+ outputs,
2244
+ status,
2245
+ exitMethod
2246
+ }) {
2247
+ const run = pendingRun;
2248
+ if (!run) return;
2249
+ pendingRun = void 0;
2250
+ const durationMs = Date.now() - run.startedAt;
2251
+ const content = renderMarkdown(run, { outputs: redact(outputs), status, exitMethod, durationMs });
2252
+ const root = currentDebugSessionDir();
2253
+ if (!root) return;
2254
+ const flowSegments = run.flow.split("/");
2255
+ const dir = join24(root, ...flowSegments);
2256
+ await mkdir9(dir, { recursive: true });
2257
+ const filename = nextAttemptFilename(dir, run.menuOption);
2258
+ await writeFile8(join24(dir, filename), content, { mode: 384 });
2259
+ }
2260
+ function nextAttemptFilename(dir, menuOption) {
2261
+ const today = datePrefix();
2262
+ const optionSlug = slugify(menuOption);
2263
+ const existing = existsSync9(dir) ? readdirSync4(dir) : [];
2264
+ const attemptPattern = new RegExp(`^${today}-${optionSlug}-attempt-(\\d+)\\.md$`);
2265
+ const maxAttempt = existing.reduce((max, entry) => {
2266
+ const match2 = attemptPattern.exec(entry);
2267
+ return match2 ? Math.max(max, Number(match2[1])) : max;
2268
+ }, 0);
2269
+ return `${today}-${optionSlug}-attempt-${maxAttempt + 1}.md`;
2270
+ }
2271
+ function renderMarkdown(run, finish) {
2272
+ const stepMatch = /^(\d+)-(.+)$/.exec(run.step);
2273
+ const stepLabel2 = stepMatch ? `${stepMatch[1]} - ${stepMatch[2]}` : run.step;
2274
+ const flowSlug = run.flow.split("/").join("-");
2275
+ return `# Debug Log
2276
+
2277
+ - Run ID: ${run.runId}
2278
+ - Flow: ${flowSlug}
2279
+ - Step: ${stepLabel2}
2280
+ - Menu option: ${run.menuOption}
2281
+ - Date: ${(/* @__PURE__ */ new Date()).toISOString()}
2282
+ - CLI version: ${readPackageVersion()}
2283
+ - Platform: ${process.platform} / Node ${process.version}
2284
+ - Duration on screen: ${finish.durationMs}ms
2285
+ - Status: ${finish.status}
2286
+ - Exit method: ${finish.exitMethod}
2287
+
2288
+ ## Inputs
2289
+ \`\`\`json
2290
+ ${JSON.stringify(run.inputs, null, 2)}
2291
+ \`\`\`
2292
+
2293
+ ## Outputs
2294
+ \`\`\`json
2295
+ ${JSON.stringify(finish.outputs, null, 2)}
2296
+ \`\`\`
2297
+ `;
2298
+ }
2299
+ function handleCrash() {
2300
+ return finishDebugRun({ outputs: {}, status: "error", exitMethod: "crashed" });
2301
+ }
2302
+ var pendingRun, sessionDir;
2303
+ var init_debug_store = __esm({
2304
+ "packages/experience-design-system-cli/src/tui/debug-store.ts"() {
2305
+ "use strict";
2306
+ init_config();
2307
+ init_version();
2308
+ init_debug_mode_store();
2309
+ void Promise.all([isDebugModeEnabled(), readBaseDir()]).then(([enabled, base]) => {
2310
+ if (!enabled || !base) return void 0;
2311
+ return mkdir9(join24(startSession(base, { replace: false }), "debug"), { recursive: true });
2312
+ });
2313
+ process.once("uncaughtException", (err) => {
2314
+ void handleCrash().finally(() => {
2315
+ throw err;
2316
+ });
2317
+ });
2318
+ process.once("unhandledRejection", (reason) => {
2319
+ void handleCrash().finally(() => {
2320
+ throw reason;
2321
+ });
2322
+ });
2323
+ process.once("SIGINT", () => {
2324
+ void handleCrash().finally(() => {
2325
+ process.exit(130);
2326
+ });
2327
+ });
2328
+ }
2329
+ });
2330
+
2019
2331
  // packages/experience-design-system-cli/app.tsx
2020
2332
  import { join as join25 } from "node:path";
2021
2333
  import { useEffect as useEffect26, useState as useState33 } from "react";
@@ -2055,60 +2367,8 @@ function brandBar(width, ramp = BRAND_RAMP) {
2055
2367
  }
2056
2368
  var FOCUS_MARKER = "\u276F";
2057
2369
 
2058
- // packages/experience-design-system-cli/src/tui/upgrade/version.ts
2059
- import { readFileSync as readFileSync2 } from "node:fs";
2060
- import { join as join2 } from "node:path";
2061
- import semver from "semver";
2062
-
2063
- // packages/experience-design-system-cli/src/tui/package-root.ts
2064
- import { existsSync, readFileSync } from "node:fs";
2065
- import { dirname, join } from "node:path";
2066
- import { fileURLToPath } from "node:url";
2067
- function findPackageRoot(startUrl, packageName) {
2068
- let dir = dirname(fileURLToPath(startUrl));
2069
- let found;
2070
- while (true) {
2071
- const manifestPath = join(dir, "package.json");
2072
- if (existsSync(manifestPath)) {
2073
- const pkg = JSON.parse(readFileSync(manifestPath, "utf8"));
2074
- if (pkg.name === packageName) found = dir;
2075
- }
2076
- const parent = dirname(dir);
2077
- if (parent === dir) return found ?? dir;
2078
- dir = parent;
2079
- }
2080
- }
2081
-
2082
- // packages/experience-design-system-cli/src/tui/upgrade/version.ts
2083
- var PACKAGE_NAME = "@contentful/experience-design-system-cli";
2084
- var TAGS_URL = "https://api.github.com/repos/contentful/experience-design-system-sdk-public/tags?per_page=10";
2085
- function readPackageVersion() {
2086
- const root = findPackageRoot(import.meta.url, PACKAGE_NAME);
2087
- const pkg = JSON.parse(readFileSync2(join2(root, "package.json"), "utf8"));
2088
- return pkg.version ?? "unknown";
2089
- }
2090
- function parseVersionTag(tag) {
2091
- const match2 = /^v(\d+\.\d+\.\d+)$/.exec(tag);
2092
- return match2 ? match2[1] : void 0;
2093
- }
2094
- async function checkForUpgrade() {
2095
- const current = readPackageVersion();
2096
- try {
2097
- const response = await fetch(TAGS_URL);
2098
- if (!response.ok) return { status: "error" };
2099
- const tags = await response.json();
2100
- const versions = tags.map((tag) => tag.name ? parseVersionTag(tag.name) : void 0).filter((v) => v !== void 0);
2101
- if (versions.length === 0) return { status: "error" };
2102
- const latest = versions.reduce((best, v) => semver.gt(v, best) ? v : best);
2103
- if (!semver.valid(current)) return { status: "error" };
2104
- if (semver.gt(latest, current)) {
2105
- return { status: "update-available", current, latest };
2106
- }
2107
- return { status: "up-to-date", current };
2108
- } catch {
2109
- return { status: "error" };
2110
- }
2111
- }
2370
+ // packages/experience-design-system-cli/src/tui/home/home.tsx
2371
+ init_version();
2112
2372
 
2113
2373
  // packages/experience-design-system-cli/src/tui/use-terminal-width.ts
2114
2374
  import { useEffect, useState } from "react";
@@ -4733,7 +4993,7 @@ async function getCliCacheVersion() {
4733
4993
  return _cliCacheVersionCache;
4734
4994
  }
4735
4995
  }
4736
- function storeExtractCache(db, filePath, fileHash, cliVersion, components) {
4996
+ function storeExtractCache(db, filePath, fileHash, cliVersion2, components) {
4737
4997
  const now = (/* @__PURE__ */ new Date()).toISOString();
4738
4998
  const componentsJson = JSON.stringify(components);
4739
4999
  db.prepare(`INSERT INTO extract_cache (file_path, file_hash, cli_version, created_at, updated_at, components_json)
@@ -4741,12 +5001,12 @@ function storeExtractCache(db, filePath, fileHash, cliVersion, components) {
4741
5001
  ON CONFLICT(file_hash, cli_version) DO UPDATE SET
4742
5002
  file_path = excluded.file_path,
4743
5003
  updated_at = excluded.updated_at,
4744
- components_json = excluded.components_json`).run(filePath, fileHash, cliVersion, now, now, componentsJson);
5004
+ components_json = excluded.components_json`).run(filePath, fileHash, cliVersion2, now, now, componentsJson);
4745
5005
  }
4746
- function lookupExtractCache(db, fileHash, cliVersion) {
5006
+ function lookupExtractCache(db, fileHash, cliVersion2) {
4747
5007
  const row = db.prepare(`SELECT file_path, file_hash, cli_version, created_at, updated_at, components_json
4748
5008
  FROM extract_cache
4749
- WHERE file_hash = ? AND cli_version = ?`).get(fileHash, cliVersion);
5009
+ WHERE file_hash = ? AND cli_version = ?`).get(fileHash, cliVersion2);
4750
5010
  if (!row)
4751
5011
  return null;
4752
5012
  let components = [];
@@ -4764,31 +5024,31 @@ function lookupExtractCache(db, fileHash, cliVersion) {
4764
5024
  components
4765
5025
  };
4766
5026
  }
4767
- function storeCompositionCache(db, inputHash, cliVersion, agentOutput) {
5027
+ function storeCompositionCache(db, inputHash, cliVersion2, agentOutput) {
4768
5028
  const now = (/* @__PURE__ */ new Date()).toISOString();
4769
5029
  db.prepare(`INSERT INTO composition_cache (input_hash, cli_version, agent_output, created_at, updated_at)
4770
5030
  VALUES (?, ?, ?, ?, ?)
4771
5031
  ON CONFLICT(input_hash, cli_version) DO UPDATE SET
4772
5032
  agent_output = excluded.agent_output,
4773
- updated_at = excluded.updated_at`).run(inputHash, cliVersion, agentOutput, now, now);
5033
+ updated_at = excluded.updated_at`).run(inputHash, cliVersion2, agentOutput, now, now);
4774
5034
  }
4775
- function lookupCompositionCache(db, inputHash, cliVersion) {
4776
- const row = db.prepare(`SELECT agent_output FROM composition_cache WHERE input_hash = ? AND cli_version = ?`).get(inputHash, cliVersion);
5035
+ function lookupCompositionCache(db, inputHash, cliVersion2) {
5036
+ const row = db.prepare(`SELECT agent_output FROM composition_cache WHERE input_hash = ? AND cli_version = ?`).get(inputHash, cliVersion2);
4777
5037
  return row ? row.agent_output : null;
4778
5038
  }
4779
- function storeSelectCache(db, componentHash, promptHash, cliVersion, decision, reason) {
5039
+ function storeSelectCache(db, componentHash, promptHash, cliVersion2, decision, reason) {
4780
5040
  const now = (/* @__PURE__ */ new Date()).toISOString();
4781
5041
  db.prepare(`INSERT INTO select_cache (component_hash, prompt_hash, cli_version, decision, reason, created_at, updated_at)
4782
5042
  VALUES (?, ?, ?, ?, ?, ?, ?)
4783
5043
  ON CONFLICT(component_hash, prompt_hash, cli_version) DO UPDATE SET
4784
5044
  decision = excluded.decision,
4785
5045
  reason = excluded.reason,
4786
- updated_at = excluded.updated_at`).run(componentHash, promptHash, cliVersion, decision, reason, now, now);
5046
+ updated_at = excluded.updated_at`).run(componentHash, promptHash, cliVersion2, decision, reason, now, now);
4787
5047
  }
4788
- function lookupSelectCache(db, componentHash, promptHash, cliVersion) {
5048
+ function lookupSelectCache(db, componentHash, promptHash, cliVersion2) {
4789
5049
  const row = db.prepare(`SELECT component_hash, prompt_hash, cli_version, decision, reason, created_at, updated_at
4790
5050
  FROM select_cache
4791
- WHERE component_hash = ? AND prompt_hash = ? AND cli_version = ?`).get(componentHash, promptHash, cliVersion);
5051
+ WHERE component_hash = ? AND prompt_hash = ? AND cli_version = ?`).get(componentHash, promptHash, cliVersion2);
4792
5052
  if (!row)
4793
5053
  return null;
4794
5054
  return {
@@ -12307,11 +12567,11 @@ import { access as access2, mkdir, readFile as readFile7, writeFile } from "node
12307
12567
  // packages/experience-design-system-backend-pipeline/dist/src/persistence/src/review-session/repositories/review-session-paths.js
12308
12568
  import { resolve as resolve15 } from "node:path";
12309
12569
  async function getRefineSessionPaths(sessionId, artifactsRoot) {
12310
- const sessionDir = resolve15(artifactsRoot, sessionId);
12570
+ const sessionDir2 = resolve15(artifactsRoot, sessionId);
12311
12571
  return {
12312
- sessionDir,
12313
- eventsPath: resolve15(sessionDir, "events.jsonl"),
12314
- statePath: resolve15(sessionDir, "current-review-state.json")
12572
+ sessionDir: sessionDir2,
12573
+ eventsPath: resolve15(sessionDir2, "events.jsonl"),
12574
+ statePath: resolve15(sessionDir2, "current-review-state.json")
12315
12575
  };
12316
12576
  }
12317
12577
 
@@ -12877,9 +13137,63 @@ async function loadAcceptedNames(sessionId) {
12877
13137
  }
12878
13138
  }
12879
13139
 
12880
- // packages/experience-design-system-backend-pipeline/dist/src/persistence/src/session/index.js
12881
- import { DatabaseSync as DatabaseSync2 } from "node:sqlite";
12882
-
13140
+ // packages/experience-design-system-backend-pipeline/dist/src/persistence/src/session/index.js
13141
+ import { DatabaseSync as DatabaseSync2 } from "node:sqlite";
13142
+
13143
+ // packages/experience-design-system-backend-pipeline/dist/src/persistence/src/session/helpers/generate-session-id.js
13144
+ import { randomBytes as randomBytes3 } from "node:crypto";
13145
+ var ADJECTIVES2 = [
13146
+ "bright",
13147
+ "calm",
13148
+ "dark",
13149
+ "fast",
13150
+ "green",
13151
+ "happy",
13152
+ "keen",
13153
+ "light",
13154
+ "long",
13155
+ "loud",
13156
+ "pale",
13157
+ "quick",
13158
+ "sharp",
13159
+ "slow",
13160
+ "soft",
13161
+ "warm",
13162
+ "wild",
13163
+ "wise"
13164
+ ];
13165
+ var NOUNS2 = [
13166
+ "cloud",
13167
+ "creek",
13168
+ "dawn",
13169
+ "dusk",
13170
+ "field",
13171
+ "flame",
13172
+ "frost",
13173
+ "grove",
13174
+ "hill",
13175
+ "lake",
13176
+ "leaf",
13177
+ "moon",
13178
+ "peak",
13179
+ "rain",
13180
+ "river",
13181
+ "rock",
13182
+ "snow",
13183
+ "star",
13184
+ "storm",
13185
+ "tide",
13186
+ "tree",
13187
+ "wave",
13188
+ "wind"
13189
+ ];
13190
+ function generateSessionId2() {
13191
+ const adj = ADJECTIVES2[Math.floor(Math.random() * ADJECTIVES2.length)];
13192
+ const noun = NOUNS2[Math.floor(Math.random() * NOUNS2.length)];
13193
+ const hex = randomBytes3(2).toString("hex");
13194
+ return `${adj}-${noun}-${hex}`;
13195
+ }
13196
+
12883
13197
  // packages/experience-design-system-backend-pipeline/dist/src/persistence/src/session/repositories/migration.js
12884
13198
  import { DatabaseSync as DatabaseSync3 } from "node:sqlite";
12885
13199
 
@@ -13510,7 +13824,7 @@ function errorMessage(error) {
13510
13824
  return error instanceof Error && error.message ? error.message : String(error);
13511
13825
  }
13512
13826
  function defaultSleep(delayMs) {
13513
- return new Promise((resolve25) => setTimeout(resolve25, delayMs));
13827
+ return new Promise((resolve27) => setTimeout(resolve27, delayMs));
13514
13828
  }
13515
13829
 
13516
13830
  // packages/experience-design-system-backend-pipeline/dist/src/steps/apply/src/helpers/sanitize-preview.js
@@ -13751,7 +14065,7 @@ var ApiClient = class {
13751
14065
  const progress = maxAttempts > 1 ? attempt / (maxAttempts - 1) : 0;
13752
14066
  const baseDelay = intervalMs + (maxIntervalMs - intervalMs) * progress;
13753
14067
  const jitter = Math.random() * baseDelay * 0.15;
13754
- await new Promise((resolve25) => setTimeout(resolve25, baseDelay + jitter));
14068
+ await new Promise((resolve27) => setTimeout(resolve27, baseDelay + jitter));
13755
14069
  }
13756
14070
  }
13757
14071
  throw new Error(`Operation ${operationId} timed out after ${maxAttempts} attempts`);
@@ -14685,6 +14999,172 @@ function loadTokenLeaves(db, sessionId) {
14685
14999
  return db.prepare("SELECT path, type FROM raw_tokens WHERE session_id = ? ORDER BY path").all(sessionId);
14686
15000
  }
14687
15001
 
15002
+ // packages/experience-design-system-backend-pipeline/dist/src/analytics/client/cli-info.js
15003
+ var cliVersionString = "0.0.0-unknown";
15004
+ function cliVersion() {
15005
+ return cliVersionString;
15006
+ }
15007
+
15008
+ // packages/experience-design-system-backend-pipeline/dist/src/analytics/client/opt-out.js
15009
+ var persistedDisabled = false;
15010
+ function analyticsEnabled() {
15011
+ return !persistedDisabled && !process.env["DISABLE_ANALYTICS"];
15012
+ }
15013
+
15014
+ // packages/experience-design-system-backend-pipeline/dist/src/analytics/client/segment-client.js
15015
+ import { Analytics } from "@segment/analytics-node";
15016
+ var DEFAULT_WRITE_KEY = "6DmxiEPN3SV1vbRTTMcNqDzCvkfwT06N";
15017
+ var analyticsClient = null;
15018
+ function resolveWriteKey() {
15019
+ const key = (process.env["SEGMENT_WRITE_KEY"] ?? "").trim();
15020
+ return key.length > 0 ? key : DEFAULT_WRITE_KEY;
15021
+ }
15022
+ function getClient() {
15023
+ if (!analyticsEnabled())
15024
+ return null;
15025
+ const writeKey = resolveWriteKey();
15026
+ if (!writeKey)
15027
+ return null;
15028
+ if (!analyticsClient) {
15029
+ analyticsClient = new Analytics({ writeKey });
15030
+ analyticsClient.on("error", () => {
15031
+ });
15032
+ }
15033
+ return analyticsClient;
15034
+ }
15035
+ async function trackEvent(event, properties, anonymousId, options) {
15036
+ const client2 = getClient();
15037
+ if (!client2)
15038
+ return;
15039
+ try {
15040
+ client2.track({
15041
+ event,
15042
+ properties,
15043
+ anonymousId,
15044
+ timestamp: /* @__PURE__ */ new Date()
15045
+ });
15046
+ if (options?.flush)
15047
+ await flushAnalytics();
15048
+ } catch {
15049
+ }
15050
+ }
15051
+ async function flushAnalytics() {
15052
+ if (!analyticsClient)
15053
+ return;
15054
+ try {
15055
+ await analyticsClient.closeAndFlush();
15056
+ } catch {
15057
+ } finally {
15058
+ analyticsClient = null;
15059
+ }
15060
+ }
15061
+
15062
+ // packages/experience-design-system-backend-pipeline/dist/src/analytics/constants.js
15063
+ var ANALYTICS_SESSION_ENV = "EDS_ANALYTICS_SESSION_ID";
15064
+ var IMPORT_PIPELINE_ENV = "EDS_IMPORT_PIPELINE";
15065
+
15066
+ // packages/experience-design-system-backend-pipeline/dist/src/analytics/session.js
15067
+ function resolveAnalyticsSessionId(explicit) {
15068
+ const inherited = process.env[ANALYTICS_SESSION_ENV]?.trim();
15069
+ if (inherited)
15070
+ return inherited;
15071
+ const passed = explicit?.trim();
15072
+ if (passed)
15073
+ return passed;
15074
+ return generateSessionId2();
15075
+ }
15076
+ function isPipelineAnalyticsChild() {
15077
+ return Boolean(process.env[ANALYTICS_SESSION_ENV]?.trim());
15078
+ }
15079
+
15080
+ // packages/experience-design-system-backend-pipeline/dist/src/analytics/tracker/pending-command.js
15081
+ var state = {
15082
+ pending: null,
15083
+ sessionId: void 0,
15084
+ sessionStartedEmitted: false
15085
+ };
15086
+ function isPipelineStep() {
15087
+ return process.env[IMPORT_PIPELINE_ENV] === "1";
15088
+ }
15089
+ function buildBaseProps(command) {
15090
+ return {
15091
+ dsi_session_id: state.sessionId,
15092
+ command,
15093
+ ...isPipelineStep() ? { is_pipeline_step: true } : {}
15094
+ };
15095
+ }
15096
+ function mergeContext(target, source) {
15097
+ if (source.space_key !== void 0)
15098
+ target.space_key = source.space_key;
15099
+ if (source.environment_key !== void 0)
15100
+ target.environment_key = source.environment_key;
15101
+ if (source.x_contentful_request_id !== void 0) {
15102
+ target.x_contentful_request_id = source.x_contentful_request_id;
15103
+ }
15104
+ }
15105
+ function setCommandContext(context) {
15106
+ if (!state.pending)
15107
+ return;
15108
+ mergeContext(state.pending.context, context);
15109
+ mergeContext(state.pending.completion, context);
15110
+ }
15111
+ function enrichCommandResult(fields) {
15112
+ if (!state.pending)
15113
+ return;
15114
+ Object.assign(state.pending.completion, fields);
15115
+ mergeContext(state.pending.context, fields);
15116
+ }
15117
+
15118
+ // packages/experience-design-system-backend-pipeline/dist/src/analytics/os.js
15119
+ var OS_NAMES2 = {
15120
+ android: "Android",
15121
+ aix: "Linux",
15122
+ darwin: "macOS",
15123
+ freebsd: "Linux",
15124
+ linux: "Linux",
15125
+ openbsd: "Linux",
15126
+ sunos: "Linux",
15127
+ win32: "Windows"
15128
+ };
15129
+ function getOsName() {
15130
+ return OS_NAMES2[process.platform] ?? "other";
15131
+ }
15132
+
15133
+ // packages/experience-design-system-backend-pipeline/dist/src/analytics/tracker/emit-events.js
15134
+ async function bindAnalyticsSessionId(explicit, context) {
15135
+ const id = resolveAnalyticsSessionId(explicit);
15136
+ await bindAnalyticsSession(id, context);
15137
+ return id;
15138
+ }
15139
+ async function bindAnalyticsSession(id, context) {
15140
+ state.sessionId = id;
15141
+ if (context)
15142
+ setCommandContext(context);
15143
+ await emitInvokedIfReady();
15144
+ }
15145
+ async function emitSessionStarted(entryCommand) {
15146
+ if (!state.sessionId || state.sessionStartedEmitted)
15147
+ return;
15148
+ state.sessionStartedEmitted = true;
15149
+ await trackEvent("dsi_cli_session_started", {
15150
+ dsi_session_id: state.sessionId,
15151
+ entry_command: entryCommand,
15152
+ cli_version: cliVersion(),
15153
+ node_version: process.version,
15154
+ os_name: getOsName()
15155
+ }, state.sessionId, { flush: true });
15156
+ await emitInvokedIfReady();
15157
+ }
15158
+ async function emitInvokedIfReady() {
15159
+ if (!state.pending || state.pending.invoked || !state.sessionId)
15160
+ return;
15161
+ state.pending.invoked = true;
15162
+ await trackEvent("dsi_cli_command_invoked", {
15163
+ ...buildBaseProps(state.pending.command),
15164
+ ...state.pending.context
15165
+ }, state.sessionId, { flush: true });
15166
+ }
15167
+
14688
15168
  // packages/experience-design-system-backend-pipeline/dist/src/steps/generation/src/controller/map-tokens/run-map-tokens.js
14689
15169
  var DEFAULT_TIMEOUT_MS2 = 5 * 60 * 1e3;
14690
15170
  var MapTokensRunFailure = class _MapTokensRunFailure extends Error {
@@ -14714,6 +15194,7 @@ async function runMapTokens(request) {
14714
15194
  if (!sessionId) {
14715
15195
  throw new MapTokensRunFailure({ type: "no-session" });
14716
15196
  }
15197
+ await bindAnalyticsSessionId(sessionId);
14717
15198
  const tokenLeaves = loadTokenLeaves(db, sessionId);
14718
15199
  const knownTokenPaths = new Set(tokenLeaves.map((t) => t.path));
14719
15200
  if (request.tokenMapInline) {
@@ -15864,7 +16345,7 @@ async function retryDatabaseWrite(operation, attempts = 8) {
15864
16345
  const message = error instanceof Error ? error.message : String(error);
15865
16346
  if (!/database is locked|database is busy/i.test(message) || attempt >= attempts)
15866
16347
  throw error;
15867
- await new Promise((resolve25) => setTimeout(resolve25, Math.min(250 * attempt, 2e3)));
16348
+ await new Promise((resolve27) => setTimeout(resolve27, Math.min(250 * attempt, 2e3)));
15868
16349
  }
15869
16350
  }
15870
16351
  }
@@ -16027,6 +16508,9 @@ async function runExtractAndComposeSession(request) {
16027
16508
  outDir
16028
16509
  });
16029
16510
  await onSessionCreated?.(sessionId);
16511
+ await bindAnalyticsSessionId(sessionId);
16512
+ if (!isPipelineAnalyticsChild())
16513
+ await emitSessionStarted("analyze_extract");
16030
16514
  const stepId = createStep(db, sessionId, "analyze extract", { project: projectPath });
16031
16515
  if (cacheHits === 0 && !noCache) {
16032
16516
  await persistExtractCache(db, sourceFiles, extraction.components, cacheVersion);
@@ -16054,6 +16538,7 @@ async function runExtractAndComposeSession(request) {
16054
16538
  await persistSlotCycles(db, sessionId, composition.components);
16055
16539
  storeScannedFiles(db, sessionId, sourceFiles.map((f) => relative2(projectPath, f)));
16056
16540
  await retryDatabaseWrite(() => updateStep(db, stepId, "complete", { sessionId }));
16541
+ enrichCommandResult({ extracted_component_count: composition.components.length });
16057
16542
  return {
16058
16543
  sessionId,
16059
16544
  compositionPhase: composition.phase,
@@ -16116,6 +16601,7 @@ async function runGenerateTokensSession(request) {
16116
16601
  outDir
16117
16602
  });
16118
16603
  await onSessionCreated?.(tokenSessionId);
16604
+ await bindAnalyticsSessionId(tokenSessionId);
16119
16605
  const tokenPromptHash = await hashPromptForSkill("tokens", agent, agentModel, skillPath);
16120
16606
  const warnings = [];
16121
16607
  onProgress?.({ kind: "resolving" });
@@ -16492,6 +16978,7 @@ async function runGenerateComponentsSession(request) {
16492
16978
  const existingTokensHash = existingTokensInline ? [hashContent(existingTokensInline)] : [];
16493
16979
  const agent = request.agent;
16494
16980
  const promptHash = await hashPromptForSkill("components", agent, request.agentModel, effectiveSkillPath, existingTokensHash, prompt.text);
16981
+ await bindAnalyticsSessionId(request.sessionId);
16495
16982
  const db = openPipelineDb();
16496
16983
  try {
16497
16984
  const acceptedNames = await loadAcceptedNames(request.sessionId);
@@ -16691,6 +17178,7 @@ function useCredentialsControls(handlers) {
16691
17178
  }
16692
17179
 
16693
17180
  // packages/experience-design-system-cli/src/tui/user-agent.ts
17181
+ init_version();
16694
17182
  function cliUserAgent() {
16695
17183
  return buildUserAgent(readPackageVersion());
16696
17184
  }
@@ -17035,11 +17523,34 @@ function RunningStep({
17035
17523
  }
17036
17524
 
17037
17525
  // packages/experience-design-system-cli/src/tui/import/steps/05-token-reuse/logic.ts
17038
- import { access as access5, stat as stat4 } from "node:fs/promises";
17526
+ import { access as access5, readdir as readdir2, stat as stat4 } from "node:fs/promises";
17039
17527
  import { join as join16 } from "node:path";
17040
- async function inspectTokens({ rawTokensPath, outDir, cache }) {
17528
+ async function findLatestTokens(contentfulDir) {
17529
+ const candidates = [join16(contentfulDir, "tokens.json")];
17530
+ try {
17531
+ for (const session of await readdir2(contentfulDir, { withFileTypes: true })) {
17532
+ if (!session.isDirectory()) continue;
17533
+ for (const run of await readdir2(join16(contentfulDir, session.name), { withFileTypes: true }).catch(() => [])) {
17534
+ if (run.isDirectory() && /^dsi-import-\d+$/.test(run.name)) {
17535
+ candidates.push(join16(contentfulDir, session.name, run.name, "tokens.json"));
17536
+ }
17537
+ }
17538
+ }
17539
+ } catch {
17540
+ }
17541
+ const found = [];
17542
+ for (const path5 of candidates) {
17543
+ try {
17544
+ found.push({ path: path5, mtimeMs: (await stat4(path5)).mtimeMs });
17545
+ } catch {
17546
+ }
17547
+ }
17548
+ return found.sort((a, b) => b.mtimeMs - a.mtimeMs)[0]?.path ?? null;
17549
+ }
17550
+ async function inspectTokens({ rawTokensPath, contentfulDir, cache }) {
17041
17551
  if (!cache) return { kind: "none" };
17042
- const tokensPath = join16(outDir, "tokens.json");
17552
+ const tokensPath = await findLatestTokens(contentfulDir);
17553
+ if (!tokensPath) return { kind: "none" };
17043
17554
  try {
17044
17555
  await access5(tokensPath);
17045
17556
  } catch {
@@ -17190,34 +17701,8 @@ function ExtractionScreen({
17190
17701
  );
17191
17702
  }
17192
17703
 
17193
- // packages/experience-design-system-types/dist/src/config/index.js
17194
- import { randomBytes as randomBytes3 } from "node:crypto";
17195
- import { mkdir as mkdir6, readFile as readFile18, rename as rename2, writeFile as writeFile6 } from "node:fs/promises";
17196
- import { homedir as homedir3 } from "node:os";
17197
- import { dirname as dirname13, join as join17 } from "node:path";
17198
- function configRoot2() {
17199
- return process.env["EDS_HOME"] || join17(homedir3(), ".contentful", "experience-design-system-cli");
17200
- }
17201
- var configFilePath2 = () => join17(configRoot2(), "config.json");
17202
- var debugSessionsDir2 = () => join17(configRoot2(), "debug", "sessions");
17203
- async function readSettings2() {
17204
- try {
17205
- return JSON.parse(await readFile18(configFilePath2(), "utf8"));
17206
- } catch {
17207
- return {};
17208
- }
17209
- }
17210
- async function writeSettings2(settings) {
17211
- const path5 = configFilePath2();
17212
- await mkdir6(dirname13(path5), { recursive: true });
17213
- const tmp = `${path5}.${process.pid}.${randomBytes3(4).toString("hex")}.tmp`;
17214
- await writeFile6(tmp, `${JSON.stringify(settings, null, 2)}
17215
- `, { mode: 384 });
17216
- await rename2(tmp, path5);
17217
- }
17218
- async function updateSettings2(patch) {
17219
- await writeSettings2({ ...await readSettings2(), ...patch });
17220
- }
17704
+ // packages/experience-design-system-cli/app.tsx
17705
+ init_config();
17221
17706
 
17222
17707
  // packages/experience-design-system-cli/src/tui/import/steps/06-extraction/use-extraction.ts
17223
17708
  import { useEffect as useEffect5, useRef as useRef2, useState as useState8 } from "react";
@@ -17256,13 +17741,13 @@ async function runSelection(options) {
17256
17741
  const db = openPipelineDb();
17257
17742
  let components;
17258
17743
  const cachedDecisions = /* @__PURE__ */ new Map();
17259
- const cliVersion = await getCliCacheVersion();
17744
+ const cliVersion2 = await getCliCacheVersion();
17260
17745
  const promptHash = await hashSelectPrompt(options);
17261
17746
  try {
17262
17747
  components = loadRawComponents(db, options.sessionId);
17263
17748
  if (!options.noCache) {
17264
17749
  for (const component of components) {
17265
- const cached = lookupSelectCache(db, hashComponentShape(component), promptHash, cliVersion);
17750
+ const cached = lookupSelectCache(db, hashComponentShape(component), promptHash, cliVersion2);
17266
17751
  if (cached) cachedDecisions.set(component.name, { decision: cached.decision, reason: cached.reason });
17267
17752
  }
17268
17753
  }
@@ -17317,7 +17802,7 @@ async function runSelection(options) {
17317
17802
  writeDb,
17318
17803
  hashComponentShape(component),
17319
17804
  promptHash,
17320
- cliVersion,
17805
+ cliVersion2,
17321
17806
  rejected ? "rejected" : "accepted",
17322
17807
  rejected ? reason : null
17323
17808
  );
@@ -17344,7 +17829,7 @@ var realDeps = {
17344
17829
  var fail = (step, message) => ({ ok: false, step, message });
17345
17830
  var errorMessage2 = (error) => error instanceof Error ? error.message : String(error);
17346
17831
  async function runExtraction(input, onProgress, deps = realDeps) {
17347
- const outDir = join19(resolve22(input.projectPath), ".contentful");
17832
+ const outDir = input.outDir ?? join19(resolve22(input.projectPath), ".contentful");
17348
17833
  let progress = initialProgress({
17349
17834
  hasCredentials: input.credentials !== null,
17350
17835
  hasRawTokens: input.rawTokensPath !== "",
@@ -17477,7 +17962,7 @@ async function resolveSelectionPrompt(overrides) {
17477
17962
 
17478
17963
  // packages/experience-design-system-cli/src/tui/import/steps/06-extraction/use-extraction.ts
17479
17964
  function useExtraction(input) {
17480
- const [state, setState] = useState8();
17965
+ const [state2, setState] = useState8();
17481
17966
  const current = useRef2();
17482
17967
  useEffect5(() => {
17483
17968
  current.current = input;
@@ -17502,7 +17987,7 @@ function useExtraction(input) {
17502
17987
  if (current.current === input) current.current = void 0;
17503
17988
  };
17504
17989
  }, [input]);
17505
- return state;
17990
+ return state2;
17506
17991
  }
17507
17992
 
17508
17993
  // packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/screen.tsx
@@ -18672,8 +19157,7 @@ function GroupedSidebar(props) {
18672
19157
  dimPredicate,
18673
19158
  visibleRows: providedRows,
18674
19159
  graph,
18675
- filterVisibleKeys,
18676
- emptyMessage
19160
+ filterVisibleKeys
18677
19161
  } = props;
18678
19162
  const allRows = providedRows ?? buildVisibleRows({
18679
19163
  items,
@@ -18690,10 +19174,6 @@ function GroupedSidebar(props) {
18690
19174
  const end = windowed ? start + (visibleCount ?? allRows.length) : allRows.length;
18691
19175
  const rows = windowed ? allRows.slice(start, end) : allRows;
18692
19176
  return /* @__PURE__ */ jsxs18(WindowedPanel, { width, height: props.height, title, focused, children: [
18693
- allRows.length === 0 && emptyMessage !== void 0 && /* @__PURE__ */ jsxs18(Text19, { color: PALETTE2.warning, children: [
18694
- " ",
18695
- emptyMessage
18696
- ] }),
18697
19177
  windowed && /* @__PURE__ */ jsx21(WindowIndicator, { direction: "up", count: start }),
18698
19178
  rows.map((row, i) => {
18699
19179
  const absoluteRowIdx = start + i;
@@ -19009,9 +19489,9 @@ function createSidebarViewsHelpSection(includeBreaking) {
19009
19489
  { keys: "L", label: "Flat view" },
19010
19490
  { keys: "i", label: "Focus lineage" }
19011
19491
  ];
19012
- if (includeBreaking) entries.push({ keys: "w", label: "Show only components with breaking changes" });
19492
+ if (includeBreaking) entries.push({ keys: "w", label: "Only breaking" });
19013
19493
  entries.push(
19014
- { keys: "o", label: "Show only components in slot cycles" },
19494
+ { keys: "o", label: "Only cycles" },
19015
19495
  { keys: "space", label: "Expand/collapse group" },
19016
19496
  { keys: "E / C", label: "Expand/collapse all" }
19017
19497
  );
@@ -19578,17 +20058,6 @@ function computeFilterKeys(input) {
19578
20058
  if (active.has("deleted")) for (const k of input.data.deleted ?? []) out.add(k);
19579
20059
  return out;
19580
20060
  }
19581
- var FILTER_LABELS = {
19582
- broken: "components with breaking changes",
19583
- cycles: "slot cycles",
19584
- deleted: "removed components"
19585
- };
19586
- function describeEmptyFilter(input) {
19587
- const names = [...input.filters].map((f) => FILTER_LABELS[f]);
19588
- if (input.slotDependencies) names.push("slot dependencies");
19589
- if (names.length === 0) return void 0;
19590
- return `Nothing to show: no ${names.join(" or ")} in this import.`;
19591
- }
19592
20061
  function intersectFilterKeys(a, b) {
19593
20062
  if (a === void 0) return b;
19594
20063
  if (b === void 0) return a;
@@ -19609,62 +20078,62 @@ function buildFlatDimPredicate(input) {
19609
20078
  }
19610
20079
 
19611
20080
  // packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/state.ts
19612
- function apply(state, entries) {
19613
- const next = new Map(state);
20081
+ function apply(state2, entries) {
20082
+ const next = new Map(state2);
19614
20083
  for (const [name, decision] of entries) next.set(name, decision);
19615
20084
  return next;
19616
20085
  }
19617
- function reduceDecisions(state, action, components, graph) {
20086
+ function reduceDecisions(state2, action, components, graph) {
19618
20087
  switch (action.type) {
19619
20088
  case "accept": {
19620
- if (state.get(action.name) === "accepted") return state;
20089
+ if (state2.get(action.name) === "accepted") return state2;
19621
20090
  return apply(
19622
- state,
20091
+ state2,
19623
20092
  acceptCascade(graph, action.name).map((name) => [name, "accepted"])
19624
20093
  );
19625
20094
  }
19626
20095
  case "reject": {
19627
- if (state.get(action.name) === "rejected") return state;
20096
+ if (state2.get(action.name) === "rejected") return state2;
19628
20097
  const { toReject, toDeselect } = rejectCascade(graph, action.name);
19629
- return apply(state, [
20098
+ return apply(state2, [
19630
20099
  ...toReject.map((name) => [name, "rejected"]),
19631
20100
  ...toDeselect.map((name) => [name, "undecided"])
19632
20101
  ]);
19633
20102
  }
19634
20103
  case "toggle-all": {
19635
20104
  const nonCycle = components.filter((c2) => !graph.cycleParticipants.has(c2.name)).map((c2) => c2.name);
19636
- const anyNotAccepted = nonCycle.some((name) => state.get(name) !== "accepted");
20105
+ const anyNotAccepted = nonCycle.some((name) => state2.get(name) !== "accepted");
19637
20106
  if (anyNotAccepted) {
19638
- return apply(state, [
20107
+ return apply(state2, [
19639
20108
  ...nonCycle.map((name) => [name, "accepted"]),
19640
20109
  ...reachableCycleMembers(graph, nonCycle).map((name) => [name, "accepted"])
19641
20110
  ]);
19642
20111
  }
19643
- return apply(state, [
20112
+ return apply(state2, [
19644
20113
  ...nonCycle.map((name) => [name, "rejected"]),
19645
- ...components.filter((c2) => graph.cycleParticipants.has(c2.name) && state.get(c2.name) === "accepted").map((c2) => [c2.name, "undecided"])
20114
+ ...components.filter((c2) => graph.cycleParticipants.has(c2.name) && state2.get(c2.name) === "accepted").map((c2) => [c2.name, "undecided"])
19646
20115
  ]);
19647
20116
  }
19648
20117
  case "accept-unflagged": {
19649
20118
  const seeds = components.filter((c2) => !graph.cycleParticipants.has(c2.name) && !isAiFlagged(c2)).map((c2) => c2.name);
19650
- return apply(state, [
20119
+ return apply(state2, [
19651
20120
  ...seeds.map((name) => [name, "accepted"]),
19652
20121
  ...reachableCycleMembers(graph, seeds).map((name) => [name, "accepted"])
19653
20122
  ]);
19654
20123
  }
19655
20124
  }
19656
20125
  }
19657
- function rejectNeedsConfirmation(graph, name, state) {
19658
- if (state.get(name) === "rejected") return false;
20126
+ function rejectNeedsConfirmation(graph, name, state2) {
20127
+ if (state2.get(name) === "rejected") return false;
19659
20128
  const { toReject, toDeselect } = rejectCascade(graph, name);
19660
20129
  const ancestors = toReject.filter((n) => n !== name);
19661
20130
  return ancestors.length + toDeselect.length >= 2;
19662
20131
  }
19663
- function partitionDecisions(components, state) {
20132
+ function partitionDecisions(components, state2) {
19664
20133
  const accepted = [];
19665
20134
  const rejected = [];
19666
20135
  for (const c2 of components) {
19667
- if (state.get(c2.name) === "accepted") accepted.push(c2.name);
20136
+ if (state2.get(c2.name) === "accepted") accepted.push(c2.name);
19668
20137
  else rejected.push(c2.name);
19669
20138
  }
19670
20139
  return { accepted, rejected };
@@ -19784,7 +20253,6 @@ function useScopeGate({ components, onConfirm, onQuit }) {
19784
20253
  }),
19785
20254
  [groupedItems, cycleParticipants, expandedGroups, columnOneView, graph, filterVisibleKeys]
19786
20255
  );
19787
- const emptyMessage = visibleRows.length === 0 && filterVisibleKeys !== void 0 && !jumpFilterTarget ? describeEmptyFilter({ filters: activeFilters, slotDependencies: showDependencies }) : void 0;
19788
20256
  const total = visibleRows.length;
19789
20257
  const safeCursor = Math.min(nav.cursor, Math.max(0, total - 1));
19790
20258
  const currentRow = visibleRows[safeCursor];
@@ -20106,7 +20574,6 @@ function useScopeGate({ components, onConfirm, onQuit }) {
20106
20574
  expandedGroups,
20107
20575
  toggleExpanded,
20108
20576
  visibleRows,
20109
- emptyMessage,
20110
20577
  safeCursor,
20111
20578
  scrollOffset: nav.scrollOffset,
20112
20579
  selectionStateByKey,
@@ -20160,7 +20627,7 @@ var HELP_SECTIONS = [
20160
20627
  title: "Panels",
20161
20628
  entries: [
20162
20629
  { keys: "c", label: "Cycle list" },
20163
- { keys: "d", label: "Show slot dependenciess" },
20630
+ { keys: "d", label: "Show slot dependencies in main list" },
20164
20631
  { keys: "x", label: "Review flags" }
20165
20632
  ]
20166
20633
  },
@@ -20229,7 +20696,6 @@ function ScopeGateView({ components, onConfirm, onQuit }) {
20229
20696
  aiFlaggedByKey: gate.aiFlaggedByKey,
20230
20697
  dimPredicate: gate.dimPredicate,
20231
20698
  visibleRows: gate.visibleRows,
20232
- emptyMessage: gate.emptyMessage,
20233
20699
  viewMode: gate.columnOneView,
20234
20700
  graph: graph.nodes
20235
20701
  }
@@ -20559,7 +21025,7 @@ function applyProgressEvent2(event, previous, total) {
20559
21025
 
20560
21026
  // packages/experience-design-system-cli/src/tui/import/steps/08-generation/use-generation.ts
20561
21027
  function useGeneration(input) {
20562
- const [state, setState] = useState14();
21028
+ const [state2, setState] = useState14();
20563
21029
  const current = useRef6();
20564
21030
  useEffect9(() => {
20565
21031
  current.current = input;
@@ -20577,7 +21043,7 @@ function useGeneration(input) {
20577
21043
  if (current.current === input) current.current = void 0;
20578
21044
  };
20579
21045
  }, [input]);
20580
- return state;
21046
+ return state2;
20581
21047
  }
20582
21048
 
20583
21049
  // packages/experience-design-system-cli/src/tui/import/steps/10-flow/flow/build-flow-start.ts
@@ -21342,7 +21808,7 @@ function parseToState(json) {
21342
21808
  });
21343
21809
  return { state: { componentDescription, props, slots }, error: null };
21344
21810
  }
21345
- function serializeState(state, originalJson) {
21811
+ function serializeState(state2, originalJson) {
21346
21812
  let wrapperKey = null;
21347
21813
  try {
21348
21814
  const orig = JSON.parse(originalJson);
@@ -21356,7 +21822,7 @@ function serializeState(state, originalJson) {
21356
21822
  } catch {
21357
21823
  }
21358
21824
  const $properties = {};
21359
- for (const p of state.props) {
21825
+ for (const p of state2.props) {
21360
21826
  const def = {
21361
21827
  $type: p.type,
21362
21828
  $category: p.category
@@ -21379,10 +21845,10 @@ function serializeState(state, originalJson) {
21379
21845
  $type: "component",
21380
21846
  $properties
21381
21847
  };
21382
- if (state.componentDescription) entry.$description = state.componentDescription;
21383
- if (state.slots.length > 0) {
21848
+ if (state2.componentDescription) entry.$description = state2.componentDescription;
21849
+ if (state2.slots.length > 0) {
21384
21850
  entry.$slots = {};
21385
- for (const s of state.slots) {
21851
+ for (const s of state2.slots) {
21386
21852
  const slotDef = {};
21387
21853
  if (s.description) slotDef.$description = s.description;
21388
21854
  if (s.required) slotDef.$required = true;
@@ -24472,71 +24938,71 @@ function ReviewReloadDialog({ open }) {
24472
24938
 
24473
24939
  // packages/experience-design-system-cli/src/tui/import/steps/09-review/review-input.ts
24474
24940
  var PANEL_CONTENT_HEIGHT = 12;
24475
- function handleReviewOverlayInput(input, key, state) {
24476
- if (state.loading) return true;
24477
- if (state.loadError) {
24478
- if (input === "q" || key.escape || key.return) state.onQuit();
24941
+ function handleReviewOverlayInput(input, key, state2) {
24942
+ if (state2.loading) return true;
24943
+ if (state2.loadError) {
24944
+ if (input === "q" || key.escape || key.return) state2.onQuit();
24479
24945
  return true;
24480
24946
  }
24481
- if (state.showFinalize) {
24947
+ if (state2.showFinalize) {
24482
24948
  if (key.downArrow) {
24483
- state.finalizePreview.scrollBy(1);
24949
+ state2.finalizePreview.scrollBy(1);
24484
24950
  return true;
24485
24951
  }
24486
24952
  if (key.upArrow) {
24487
- state.finalizePreview.scrollBy(-1);
24953
+ state2.finalizePreview.scrollBy(-1);
24488
24954
  return true;
24489
24955
  }
24490
24956
  return true;
24491
24957
  }
24492
- if (state.dialogOpen || state.showHelp) return true;
24493
- if (state.showReloadDialog) {
24958
+ if (state2.dialogOpen || state2.showHelp) return true;
24959
+ if (state2.showReloadDialog) {
24494
24960
  if (key.return) {
24495
- state.reloadFromSave();
24496
- state.setShowReloadDialog(false);
24961
+ state2.reloadFromSave();
24962
+ state2.setShowReloadDialog(false);
24497
24963
  return true;
24498
24964
  }
24499
24965
  if (key.escape) {
24500
- state.setShowReloadDialog(false);
24966
+ state2.setShowReloadDialog(false);
24501
24967
  return true;
24502
24968
  }
24503
24969
  return true;
24504
24970
  }
24505
24971
  if (key.ctrl && input === "z") {
24506
- state.handleUndo();
24972
+ state2.handleUndo();
24507
24973
  return true;
24508
24974
  }
24509
24975
  if (key.ctrl && input === "y") {
24510
- state.handleRedo();
24976
+ state2.handleRedo();
24511
24977
  return true;
24512
24978
  }
24513
24979
  if (key.ctrl && input === "r") {
24514
- state.setShowReloadDialog(true);
24980
+ state2.setShowReloadDialog(true);
24515
24981
  return true;
24516
24982
  }
24517
24983
  return false;
24518
24984
  }
24519
- function handleTokenReviewInput(input, key, state) {
24520
- if (state.panelOpen !== "token-review") return false;
24521
- const suggestions = state.currentTokenSuggestions();
24522
- const row = suggestions[state.tokenReviewRow];
24523
- if (state.tokenReviewEditing) {
24985
+ function handleTokenReviewInput(input, key, state2) {
24986
+ if (state2.panelOpen !== "token-review") return false;
24987
+ const suggestions = state2.currentTokenSuggestions();
24988
+ const row = suggestions[state2.tokenReviewRow];
24989
+ if (state2.tokenReviewEditing) {
24524
24990
  if (key.ctrl && input === "s" && row) {
24525
- state.handleTokenEditSave(row);
24991
+ state2.handleTokenEditSave(row);
24526
24992
  return true;
24527
24993
  }
24528
24994
  if (row && row.paths.length > 0) {
24529
24995
  if (key.upArrow || input === "k") {
24530
- state.setTokenReviewEditCursor((cursor) => Math.max(0, cursor - 1));
24996
+ state2.setTokenReviewEditCursor((cursor) => Math.max(0, cursor - 1));
24531
24997
  return true;
24532
24998
  }
24533
24999
  if (key.downArrow || input === "j") {
24534
- state.setTokenReviewEditCursor((cursor) => Math.min(row.paths.length - 1, cursor + 1));
25000
+ state2.setTokenReviewEditCursor((cursor) => Math.min(row.paths.length - 1, cursor + 1));
24535
25001
  return true;
24536
25002
  }
24537
25003
  if (input === " " || key.return) {
24538
- const path5 = row.paths[state.tokenReviewEditCursor];
24539
- state.setTokenReviewEditSelection((previous) => {
25004
+ const path5 = row.paths[state2.tokenReviewEditCursor];
25005
+ state2.setTokenReviewEditSelection((previous) => {
24540
25006
  const next = new Set(previous);
24541
25007
  if (next.has(path5) && next.size === 1) return next;
24542
25008
  if (next.has(path5)) next.delete(path5);
@@ -24547,34 +25013,34 @@ function handleTokenReviewInput(input, key, state) {
24547
25013
  }
24548
25014
  }
24549
25015
  if (key.escape) {
24550
- state.setTokenReviewEditing(false);
25016
+ state2.setTokenReviewEditing(false);
24551
25017
  return true;
24552
25018
  }
24553
25019
  return true;
24554
25020
  }
24555
25021
  if (key.upArrow || input === "k") {
24556
- state.setTokenReviewRow((rowIndex) => Math.max(0, rowIndex - 1));
25022
+ state2.setTokenReviewRow((rowIndex) => Math.max(0, rowIndex - 1));
24557
25023
  return true;
24558
25024
  }
24559
25025
  if (key.downArrow || input === "j") {
24560
- state.setTokenReviewRow((rowIndex) => Math.min(Math.max(0, suggestions.length - 1), rowIndex + 1));
25026
+ state2.setTokenReviewRow((rowIndex) => Math.min(Math.max(0, suggestions.length - 1), rowIndex + 1));
24561
25027
  return true;
24562
25028
  }
24563
25029
  if (key.return && row) {
24564
- state.setTokenReviewEditCursor(0);
24565
- state.setTokenReviewEditSelection(new Set(row.allowed));
24566
- state.setTokenReviewEditing(true);
25030
+ state2.setTokenReviewEditCursor(0);
25031
+ state2.setTokenReviewEditSelection(new Set(row.allowed));
25032
+ state2.setTokenReviewEditing(true);
24567
25033
  return true;
24568
25034
  }
24569
25035
  if (key.escape || input === "t") {
24570
- state.setPanelOpen("none");
25036
+ state2.setPanelOpen("none");
24571
25037
  return true;
24572
25038
  }
24573
25039
  return true;
24574
25040
  }
24575
- function setReviewPanel(state, panel) {
24576
- state.setPanelOpen(panel);
24577
- state.setPanelScrollOffset(() => 0);
25041
+ function setReviewPanel(state2, panel) {
25042
+ state2.setPanelOpen(panel);
25043
+ state2.setPanelScrollOffset(() => 0);
24578
25044
  }
24579
25045
  function rationalePanelForInput(input, propKey, componentKey) {
24580
25046
  if (input === propKey) return "prop-rationale";
@@ -24582,70 +25048,70 @@ function rationalePanelForInput(input, propKey, componentKey) {
24582
25048
  if (input === "s") return "source";
24583
25049
  return null;
24584
25050
  }
24585
- function handleRationalePanelInput(input, key, state) {
24586
- if (state.panelOpen === "none" || state.panelOpen === "token-review") return false;
24587
- const next = computeNextScrollOffset(state.panelScrollOffset, input, key, 9999, PANEL_CONTENT_HEIGHT);
25051
+ function handleRationalePanelInput(input, key, state2) {
25052
+ if (state2.panelOpen === "none" || state2.panelOpen === "token-review") return false;
25053
+ const next = computeNextScrollOffset(state2.panelScrollOffset, input, key, 9999, PANEL_CONTENT_HEIGHT);
24588
25054
  if (next !== null) {
24589
- state.setPanelScrollOffset(() => next);
25055
+ state2.setPanelScrollOffset(() => next);
24590
25056
  return true;
24591
25057
  }
24592
25058
  if (key.escape) {
24593
- setReviewPanel(state, "none");
25059
+ setReviewPanel(state2, "none");
24594
25060
  return true;
24595
25061
  }
24596
25062
  const togglable = !key.ctrl && !key.tab && !key.meta && !key.return;
24597
25063
  if (!togglable) return true;
24598
- const panel = rationalePanelForInput(input, state.propKey, state.componentKey);
24599
- if (panel) setReviewPanel(state, state.panelOpen === panel ? "none" : panel);
25064
+ const panel = rationalePanelForInput(input, state2.propKey, state2.componentKey);
25065
+ if (panel) setReviewPanel(state2, state2.panelOpen === panel ? "none" : panel);
24600
25066
  return true;
24601
25067
  }
24602
- function handleReviewPanelShortcuts(input, key, state) {
24603
- if (handleTokenReviewInput(input, key, state)) return true;
24604
- if (handleRationalePanelInput(input, key, state)) return true;
24605
- const rationaleKeyOk = !state.textEntryActive && !state.showJson && !key.ctrl && !key.tab && !key.meta && !key.return;
25068
+ function handleReviewPanelShortcuts(input, key, state2) {
25069
+ if (handleTokenReviewInput(input, key, state2)) return true;
25070
+ if (handleRationalePanelInput(input, key, state2)) return true;
25071
+ const rationaleKeyOk = !state2.textEntryActive && !state2.showJson && !key.ctrl && !key.tab && !key.meta && !key.return;
24606
25072
  if (!rationaleKeyOk) return false;
24607
- const panel = rationalePanelForInput(input, state.propKey, state.componentKey);
25073
+ const panel = rationalePanelForInput(input, state2.propKey, state2.componentKey);
24608
25074
  if (panel) {
24609
- setReviewPanel(state, panel);
25075
+ setReviewPanel(state2, panel);
24610
25076
  return true;
24611
25077
  }
24612
- if (input === "t" && state.currentTokenSuggestions().length > 0) {
24613
- state.setPanelOpen("token-review");
24614
- state.setTokenReviewRow(0);
25078
+ if (input === "t" && state2.currentTokenSuggestions().length > 0) {
25079
+ state2.setPanelOpen("token-review");
25080
+ state2.setTokenReviewRow(0);
24615
25081
  return true;
24616
25082
  }
24617
25083
  return false;
24618
25084
  }
24619
- function handleReviewViewToggleInput(input, state) {
25085
+ function handleReviewViewToggleInput(input, state2) {
24620
25086
  if (input === "J") {
24621
- state.setShowJson((previous) => !previous);
24622
- state.setJsonScrollOffset(0);
24623
- state.pendingGRef.current = false;
25087
+ state2.setShowJson((previous) => !previous);
25088
+ state2.setJsonScrollOffset(0);
25089
+ state2.pendingGRef.current = false;
24624
25090
  return true;
24625
25091
  }
24626
25092
  return false;
24627
25093
  }
24628
- function handleJsonPanelInput(input, key, state) {
24629
- if (state.sidebarFocused || !state.showJson) return false;
24630
- const totalLines = state.jsonValue.split("\n").length;
24631
- const maxOffset = Math.max(0, totalLines - state.height);
25094
+ function handleJsonPanelInput(input, key, state2) {
25095
+ if (state2.sidebarFocused || !state2.showJson) return false;
25096
+ const totalLines = state2.jsonValue.split("\n").length;
25097
+ const maxOffset = Math.max(0, totalLines - state2.height);
24632
25098
  if (input === "g" && !key.ctrl) {
24633
- if (state.pendingGRef.current) {
24634
- state.pendingGRef.current = false;
24635
- state.setJsonScrollOffset(() => 0);
25099
+ if (state2.pendingGRef.current) {
25100
+ state2.pendingGRef.current = false;
25101
+ state2.setJsonScrollOffset(() => 0);
24636
25102
  return true;
24637
25103
  }
24638
- state.pendingGRef.current = true;
25104
+ state2.pendingGRef.current = true;
24639
25105
  return true;
24640
25106
  }
24641
- const next = computeNextScrollOffset(state.jsonScrollOffset, input, key, totalLines, state.height);
25107
+ const next = computeNextScrollOffset(state2.jsonScrollOffset, input, key, totalLines, state2.height);
24642
25108
  if (next !== null) {
24643
- state.pendingGRef.current = false;
25109
+ state2.pendingGRef.current = false;
24644
25110
  const clamped = Math.min(maxOffset, Math.max(0, next));
24645
- state.setJsonScrollOffset(() => clamped);
25111
+ state2.setJsonScrollOffset(() => clamped);
24646
25112
  return true;
24647
25113
  }
24648
- state.pendingGRef.current = false;
25114
+ state2.pendingGRef.current = false;
24649
25115
  return true;
24650
25116
  }
24651
25117
 
@@ -24989,12 +25455,12 @@ var HELP_SECTIONS2 = [
24989
25455
  title: "Panels",
24990
25456
  entries: [
24991
25457
  { keys: "c", label: "Cycle list" },
24992
- { keys: "b", label: "Show breaking changes" },
24993
- { keys: "w", label: "Filter components with breaking changes" },
24994
- { keys: "o", label: "Filter components in slot cycles" },
25458
+ { keys: "b", label: "Breaking changes" },
25459
+ { keys: "w", label: "Only breaking" },
25460
+ { keys: "o", label: "Only cycles" },
24995
25461
  { keys: "p", label: "Prop rationale" },
24996
25462
  { keys: "P", label: "Component rationale" },
24997
- { keys: "s", label: "Source code snippet" },
25463
+ { keys: "s", label: "Source" },
24998
25464
  { keys: "J", label: "Toggle JSON" },
24999
25465
  { keys: "t", label: "Token review" }
25000
25466
  ]
@@ -25713,18 +26179,18 @@ function GenerateReviewStepView({
25713
26179
  }
25714
26180
  return;
25715
26181
  }
25716
- if (input === "c" && !reviewEditor.textEntryActive && !key.ctrl && !key.meta && cycleRows.length > 0) {
26182
+ if (input === "c" && !key.ctrl && !key.meta && cycleRows.length > 0) {
25717
26183
  cyclePanel.open();
25718
26184
  setCyclePanelScroll(0);
25719
26185
  setCyclesCursor(0);
25720
26186
  return;
25721
26187
  }
25722
- if (input === "b" && !reviewEditor.textEntryActive && sidebarFocused && breakingChanges.length > 0) {
26188
+ if (input === "b" && sidebarFocused && breakingChanges.length > 0) {
25723
26189
  breakingPanel.open();
25724
26190
  setBreakingCursor(0);
25725
26191
  return;
25726
26192
  }
25727
- if (!reviewEditor.textEntryActive && (input === "o" || input === "w")) {
26193
+ if (input === "o" || input === "w") {
25728
26194
  const category = input === "o" ? "cycles" : "broken";
25729
26195
  setActiveFilters((prev) => {
25730
26196
  const next = new Set(prev);
@@ -26110,7 +26576,6 @@ function GenerateReviewStepView({
26110
26576
  visibleCount,
26111
26577
  dimPredicate,
26112
26578
  visibleRows: visibleRowsMemo,
26113
- emptyMessage: visibleRowsMemo.length === 0 && filterVisibleKeys !== void 0 && !jumpFilterTarget ? describeEmptyFilter({ filters: activeFilters }) : void 0,
26114
26579
  viewMode: columnOneView,
26115
26580
  graph: sidebarGraph
26116
26581
  }
@@ -26995,38 +27460,38 @@ function buildRunTeaserLine(runId) {
26995
27460
 
26996
27461
  // packages/experience-design-system-cli/src/tui/import/steps/10-flow/flow/screen.tsx
26997
27462
  import { jsx as jsx52, jsxs as jsxs42 } from "react/jsx-runtime";
26998
- function totalStepsFor(state) {
26999
- const hasTokenStage = !!state.tokensPath || !!state.rawTokensPath;
27000
- return 3 + (hasTokenStage ? 1 : 0) + 2 + (state.mapTokensEligible === true ? 1 : 0);
27463
+ function totalStepsFor(state2) {
27464
+ const hasTokenStage = !!state2.tokensPath || !!state2.rawTokensPath;
27465
+ return 3 + (hasTokenStage ? 1 : 0) + 2 + (state2.mapTokensEligible === true ? 1 : 0);
27001
27466
  }
27002
27467
  function canEditFromPreview(cdf) {
27003
27468
  if (!cdf) return false;
27004
27469
  return parseCDFComponents(cdf).components.length > 0;
27005
27470
  }
27006
27471
  function FlowScreen({
27007
- state,
27472
+ state: state2,
27008
27473
  controller,
27009
27474
  livePreview = true,
27010
27475
  generatePromptPath,
27011
27476
  onExit
27012
27477
  }) {
27013
- const totalSteps = totalStepsFor(state);
27478
+ const totalSteps = totalStepsFor(state2);
27014
27479
  const quit = () => onExit(0);
27015
27480
  const content = (() => {
27016
- switch (state.step) {
27481
+ switch (state2.step) {
27017
27482
  case "final-review":
27018
27483
  return /* @__PURE__ */ jsx52(
27019
27484
  GenerateReviewStep,
27020
27485
  {
27021
- extractSessionId: state.extractSessionId,
27022
- tokenSessionId: state.tokenSessionId,
27486
+ extractSessionId: state2.extractSessionId,
27487
+ tokenSessionId: state2.tokenSessionId,
27023
27488
  livePreview,
27024
- spaceId: state.spaceId,
27025
- environmentId: state.environmentId,
27026
- cmaToken: state.cmaToken,
27027
- host: state.host,
27028
- tokensPath: state.tokensPath,
27029
- initialFinalizeError: state.finalizeErrorBanner,
27489
+ spaceId: state2.spaceId,
27490
+ environmentId: state2.environmentId,
27491
+ cmaToken: state2.cmaToken,
27492
+ host: state2.host,
27493
+ tokensPath: state2.tokensPath,
27494
+ initialFinalizeError: state2.finalizeErrorBanner,
27030
27495
  onFinalize: controller.finalize,
27031
27496
  onQuit: quit
27032
27497
  }
@@ -27042,27 +27507,27 @@ function FlowScreen({
27042
27507
  }
27043
27508
  );
27044
27509
  case "preview-gate":
27045
- if (!state.serverPreview) return null;
27510
+ if (!state2.serverPreview) return null;
27046
27511
  return /* @__PURE__ */ jsx52(
27047
27512
  WizardPreviewStep,
27048
27513
  {
27049
- preview: state.serverPreview,
27050
- spaceId: state.spaceId,
27051
- environmentId: state.environmentId,
27514
+ preview: state2.serverPreview,
27515
+ spaceId: state2.spaceId,
27516
+ environmentId: state2.environmentId,
27052
27517
  stepNumber: totalSteps,
27053
27518
  totalSteps,
27054
27519
  onConfirm: controller.confirmPreview,
27055
- ...canEditFromPreview(state.cdf) ? { onEdit: controller.editDefinitions } : {},
27520
+ ...canEditFromPreview(state2.cdf) ? { onEdit: controller.editDefinitions } : {},
27056
27521
  onQuit: quit
27057
27522
  }
27058
27523
  );
27059
27524
  case "pushing":
27060
- return /* @__PURE__ */ jsx52(PushingStep, { stepNumber: totalSteps, totalSteps, progress: state.pushProgress });
27525
+ return /* @__PURE__ */ jsx52(PushingStep, { stepNumber: totalSteps, totalSteps, progress: state2.pushProgress });
27061
27526
  case "path-prompt":
27062
27527
  return /* @__PURE__ */ jsx52(
27063
27528
  PathPrompt,
27064
27529
  {
27065
- defaultPath: state.outDir,
27530
+ defaultPath: state2.outDir,
27066
27531
  onSubmit: (submitted) => void controller.submitPath(submitted),
27067
27532
  onCancel: quit
27068
27533
  }
@@ -27078,12 +27543,12 @@ function FlowScreen({
27078
27543
  }
27079
27544
  );
27080
27545
  case "print-gate": {
27081
- const teaser = buildRunTeaserLine(state.lastRunId);
27546
+ const teaser = buildRunTeaserLine(state2.lastRunId);
27082
27547
  return /* @__PURE__ */ jsx52(
27083
27548
  GateStep,
27084
27549
  {
27085
27550
  message: "Files saved",
27086
- summary: state.componentsPath ? `components.json \u2192 ${state.componentsPath}` : void 0,
27551
+ summary: state2.componentsPath ? `components.json \u2192 ${state2.componentsPath}` : void 0,
27087
27552
  context: teaser ? `Your files are saved to disk. ${teaser}` : "Your files are saved to disk. Run `experiences import` again when you're ready to push to Contentful.",
27088
27553
  continueLabel: "Exit",
27089
27554
  onContinue: quit,
@@ -27092,17 +27557,17 @@ function FlowScreen({
27092
27557
  );
27093
27558
  }
27094
27559
  case "done": {
27095
- const totalFailed = state.pushResult.componentTypes.failed + state.pushResult.designTokens.failed;
27560
+ const totalFailed = state2.pushResult.componentTypes.failed + state2.pushResult.designTokens.failed;
27096
27561
  return /* @__PURE__ */ jsx52(
27097
27562
  DoneStep,
27098
27563
  {
27099
- componentTypes: state.pushResult.componentTypes,
27100
- designTokens: state.pushResult.designTokens,
27101
- summary: state.pushResult.summary,
27102
- failures: state.pushResult.failures,
27103
- spaceId: state.spaceId,
27104
- environmentId: state.environmentId,
27105
- host: state.host,
27564
+ componentTypes: state2.pushResult.componentTypes,
27565
+ designTokens: state2.pushResult.designTokens,
27566
+ summary: state2.pushResult.summary,
27567
+ failures: state2.pushResult.failures,
27568
+ spaceId: state2.spaceId,
27569
+ environmentId: state2.environmentId,
27570
+ host: state2.host,
27106
27571
  onExit: () => onExit(totalFailed > 0 ? 1 : 0)
27107
27572
  }
27108
27573
  );
@@ -27111,8 +27576,8 @@ function FlowScreen({
27111
27576
  return /* @__PURE__ */ jsx52(
27112
27577
  PreviewValidationErrorScreen,
27113
27578
  {
27114
- errors: state.previewValidationErrors,
27115
- missingNames: state.previewValidationMissingNames,
27579
+ errors: state2.previewValidationErrors,
27580
+ missingNames: state2.previewValidationMissingNames,
27116
27581
  onEdit: controller.editDefinitions,
27117
27582
  onSkip: () => void controller.skipValidationErrors(),
27118
27583
  onQuit: quit
@@ -27122,10 +27587,10 @@ function FlowScreen({
27122
27587
  return /* @__PURE__ */ jsx52(
27123
27588
  ErrorStep,
27124
27589
  {
27125
- stepName: state.errorStep,
27126
- message: state.errorMessage,
27590
+ stepName: state2.errorStep,
27591
+ message: state2.errorMessage,
27127
27592
  onExit: () => onExit(1),
27128
- onAcknowledgeBreakingChanges: state.errorAllowBreakingChangeAcknowledgment && state.cdf ? controller.acknowledgeBreakingChanges : void 0
27593
+ onAcknowledgeBreakingChanges: state2.errorAllowBreakingChangeAcknowledgment && state2.cdf ? controller.acknowledgeBreakingChanges : void 0
27129
27594
  }
27130
27595
  );
27131
27596
  }
@@ -27143,11 +27608,11 @@ import { useEffect as useEffect20, useRef as useRef12, useSyncExternalStore } fr
27143
27608
  import { appendFileSync, writeFileSync } from "node:fs";
27144
27609
  import { mkdir as mkdir8 } from "node:fs/promises";
27145
27610
  import { tmpdir } from "node:os";
27146
- import { join as join23 } from "node:path";
27611
+ import { join as join23, resolve as resolve25 } from "node:path";
27147
27612
 
27148
27613
  // packages/experience-design-system-cli/src/tui/import/steps/10-flow/support/wizard-state-transitions.ts
27149
- function shouldBypassPreview(state) {
27150
- return state.credentialsSkipped === true;
27614
+ function shouldBypassPreview(state2) {
27615
+ return state2.credentialsSkipped === true;
27151
27616
  }
27152
27617
  function buildSkippedPreviewTransition() {
27153
27618
  return { step: "done", serverPreview: null };
@@ -27156,8 +27621,8 @@ function resolveCycleGateAction(opts) {
27156
27621
  if (!opts.hasCycles) return "proceed";
27157
27622
  return "block";
27158
27623
  }
27159
- function shouldRefusePush(state) {
27160
- return state.credentialsSkipped === true;
27624
+ function shouldRefusePush(state2) {
27625
+ return state2.credentialsSkipped === true;
27161
27626
  }
27162
27627
  function buildSkippedPushTransition() {
27163
27628
  return { step: "print-gate" };
@@ -27514,7 +27979,7 @@ var realSaveDeps = () => ({
27514
27979
  writeFile: (path5, contents) => writeFile7(path5, contents),
27515
27980
  appendRun,
27516
27981
  buildSourceFingerprint,
27517
- sleep: (ms) => new Promise((resolve25) => setTimeout(resolve25, ms)),
27982
+ sleep: (ms) => new Promise((resolve27) => setTimeout(resolve27, ms)),
27518
27983
  warn: (message) => process.stderr.write(message)
27519
27984
  });
27520
27985
  async function runPrintFiles(input, deps, onPatch) {
@@ -27552,17 +28017,17 @@ async function runPrintFiles(input, deps, onPatch) {
27552
28017
  return { ok: true, patch: nextStateAfterPrint({ skipGate: input.skipGate, componentsPath }) };
27553
28018
  }
27554
28019
  async function recordRun(input, deps) {
27555
- const { state } = input;
28020
+ const { state: state2 } = input;
27556
28021
  try {
27557
28022
  let sourceFingerprint = null;
27558
28023
  try {
27559
- if (state.extractSessionId) {
28024
+ if (state2.extractSessionId) {
27560
28025
  const db = deps.openDb();
27561
28026
  try {
27562
28027
  sourceFingerprint = await deps.buildSourceFingerprint({
27563
28028
  db,
27564
- extractSessionId: state.extractSessionId,
27565
- rawTokensPath: state.rawTokensPath || null
28029
+ extractSessionId: state2.extractSessionId,
28030
+ rawTokensPath: state2.rawTokensPath || null
27566
28031
  });
27567
28032
  } finally {
27568
28033
  db.close();
@@ -27573,16 +28038,16 @@ async function recordRun(input, deps) {
27573
28038
  `);
27574
28039
  }
27575
28040
  const record3 = await deps.appendRun({
27576
- projectPath: state.projectPath,
28041
+ projectPath: state2.projectPath,
27577
28042
  savePath: input.savePath,
27578
- componentCount: state.generatedAcceptedCount || state.generatedCount,
27579
- tokenCount: state.tokenCount,
27580
- tokensPath: (state.tokenSessionId ? state.tokensPath || null : null) || null,
27581
- tokenSessionId: state.tokenSessionId,
27582
- agent: state.agent,
28043
+ componentCount: state2.generatedAcceptedCount || state2.generatedCount,
28044
+ tokenCount: state2.tokenCount,
28045
+ tokensPath: (state2.tokenSessionId ? state2.tokensPath || null : null) || null,
28046
+ tokenSessionId: state2.tokenSessionId,
28047
+ agent: state2.agent,
27583
28048
  pushedTo: null,
27584
- extractSessionId: state.extractSessionId ?? "",
27585
- generateSessionId: state.generateSessionId,
28049
+ extractSessionId: state2.extractSessionId ?? "",
28050
+ generateSessionId: state2.generateSessionId,
27586
28051
  sourceFingerprint
27587
28052
  });
27588
28053
  return record3.id;
@@ -27718,7 +28183,7 @@ function namesToSkip(errors) {
27718
28183
  return [...new Set(errors.map((e) => e.componentName))];
27719
28184
  }
27720
28185
  function createFlowController(start, deps) {
27721
- let state = initialFlowState(start);
28186
+ let state2 = initialFlowState(start);
27722
28187
  const listeners = /* @__PURE__ */ new Set();
27723
28188
  let allowEmptyDeleteAll = false;
27724
28189
  let pendingSave = {};
@@ -27727,27 +28192,27 @@ function createFlowController(start, deps) {
27727
28192
  deps.log({ update: sanitizeForLog(patch) });
27728
28193
  } catch {
27729
28194
  }
27730
- if (patch.step !== void 0 && patch.step !== state.step) {
28195
+ if (patch.step !== void 0 && patch.step !== state2.step) {
27731
28196
  try {
27732
28197
  deps.beforeStepChange?.();
27733
28198
  } catch {
27734
28199
  }
27735
28200
  }
27736
- state = { ...state, ...patch };
28201
+ state2 = { ...state2, ...patch };
27737
28202
  for (const listener of listeners) listener();
27738
28203
  };
27739
28204
  const preview = async () => {
27740
- if (!state.credentialsSkipped) update({ step: "previewing" });
28205
+ if (!state2.credentialsSkipped) update({ step: "previewing" });
27741
28206
  update(
27742
28207
  await runPreview(
27743
28208
  {
27744
- state,
27745
- extractSessionId: state.extractSessionId,
27746
- tokensPath: state.tokensPath,
27747
- spaceId: state.spaceId,
27748
- environmentId: state.environmentId,
27749
- cmaToken: state.cmaToken,
27750
- host: state.host,
28209
+ state: state2,
28210
+ extractSessionId: state2.extractSessionId,
28211
+ tokensPath: state2.tokensPath,
28212
+ spaceId: state2.spaceId,
28213
+ environmentId: state2.environmentId,
28214
+ cmaToken: state2.cmaToken,
28215
+ host: state2.host,
27751
28216
  deleteAll: allowEmptyDeleteAll
27752
28217
  },
27753
28218
  deps.preview
@@ -27755,18 +28220,18 @@ function createFlowController(start, deps) {
27755
28220
  );
27756
28221
  };
27757
28222
  const push = async (acknowledgeBreakingChanges) => {
27758
- if (!state.cdf) return;
28223
+ if (!state2.cdf) return;
27759
28224
  update(
27760
28225
  await runPush(
27761
28226
  {
27762
- state,
27763
- cdf: state.cdf,
27764
- spaceId: state.spaceId,
27765
- environmentId: state.environmentId,
27766
- cmaToken: state.cmaToken,
27767
- host: state.host,
28227
+ state: state2,
28228
+ cdf: state2.cdf,
28229
+ spaceId: state2.spaceId,
28230
+ environmentId: state2.environmentId,
28231
+ cmaToken: state2.cmaToken,
28232
+ host: state2.host,
27768
28233
  acknowledgeBreakingChanges,
27769
- preview: state.serverPreview
28234
+ preview: state2.serverPreview
27770
28235
  },
27771
28236
  deps.push,
27772
28237
  update
@@ -27782,11 +28247,11 @@ function createFlowController(start, deps) {
27782
28247
  const { skipGate, andPush } = pendingSave;
27783
28248
  const written = await runPrintFiles(
27784
28249
  {
27785
- extractSessionId: state.extractSessionId,
28250
+ extractSessionId: state2.extractSessionId,
27786
28251
  outDir: path5,
27787
28252
  ...skipGate ? { skipGate: true } : {},
27788
- ...state.tokenSessionId ? { tokenSessionId: state.tokenSessionId } : {},
27789
- ...state.tokensPath ? { tokensPath: state.tokensPath } : {},
28253
+ ...state2.tokenSessionId ? { tokenSessionId: state2.tokenSessionId } : {},
28254
+ ...state2.tokensPath ? { tokensPath: state2.tokensPath } : {},
27790
28255
  ...allowEmptyDeleteAll ? { allowEmpty: true } : {}
27791
28256
  },
27792
28257
  deps.save,
@@ -27794,21 +28259,21 @@ function createFlowController(start, deps) {
27794
28259
  );
27795
28260
  update(written.patch);
27796
28261
  if (!written.ok) return;
27797
- const runId = await recordRun({ state, savePath: path5 }, deps.save);
28262
+ const runId = await recordRun({ state: state2, savePath: path5 }, deps.save);
27798
28263
  if (runId) update({ lastRunId: runId });
27799
28264
  if (andPush) await preview();
27800
28265
  };
27801
28266
  const detectAcceptedCycles = () => {
27802
- if (!state.extractSessionId) return [];
28267
+ if (!state2.extractSessionId) return [];
27803
28268
  try {
27804
- const accepted = deps.loadAcceptedComponents(state.extractSessionId);
28269
+ const accepted = deps.loadAcceptedComponents(state2.extractSessionId);
27805
28270
  return findSlotCycles3(buildComponentGraph3(accepted));
27806
28271
  } catch {
27807
28272
  return [];
27808
28273
  }
27809
28274
  };
27810
28275
  const begin = () => {
27811
- if (!state.extractSessionId || !start.handoff.generation) {
28276
+ if (!state2.extractSessionId || !start.handoff.generation) {
27812
28277
  update({
27813
28278
  step: "error",
27814
28279
  errorStep: "start import",
@@ -27825,7 +28290,7 @@ function createFlowController(start, deps) {
27825
28290
  };
27826
28291
  begin();
27827
28292
  return {
27828
- getState: () => state,
28293
+ getState: () => state2,
27829
28294
  subscribe: (listener) => {
27830
28295
  listeners.add(listener);
27831
28296
  return () => listeners.delete(listener);
@@ -27848,7 +28313,7 @@ function createFlowController(start, deps) {
27848
28313
  },
27849
28314
  async submitPath(submitted) {
27850
28315
  await deps.mkdir(submitted);
27851
- if (await deps.detectSaveConflict(submitted)) {
28316
+ if (resolve25(submitted) !== resolve25(state2.outDir) && await deps.detectSaveConflict(submitted)) {
27852
28317
  const subdir = deps.buildTimestampedSubdir(submitted);
27853
28318
  await deps.mkdir(subdir);
27854
28319
  await proceedToWrite(subdir);
@@ -27860,9 +28325,9 @@ function createFlowController(start, deps) {
27860
28325
  acknowledgeBreakingChanges: () => void push(true),
27861
28326
  editDefinitions: () => update({ step: "final-review" }),
27862
28327
  async skipValidationErrors() {
27863
- if (state.extractSessionId) {
27864
- const names = namesToSkip(state.previewValidationErrors);
27865
- if (names.length > 0) await deps.rejectComponentsByName(state.extractSessionId, names);
28328
+ if (state2.extractSessionId) {
28329
+ const names = namesToSkip(state2.previewValidationErrors);
28330
+ if (names.length > 0) await deps.rejectComponentsByName(state2.extractSessionId, names);
27866
28331
  }
27867
28332
  await preview();
27868
28333
  }
@@ -27884,184 +28349,32 @@ function useFlow(start, options = {}) {
27884
28349
  });
27885
28350
  }
27886
28351
  const current = controller.current;
27887
- const state = useSyncExternalStore(
28352
+ const state2 = useSyncExternalStore(
27888
28353
  (listener) => current?.subscribe(listener) ?? (() => void 0),
27889
28354
  () => current?.getState()
27890
28355
  );
27891
28356
  useEffect20(() => {
27892
28357
  if (!start) controller.current = void 0;
27893
28358
  }, [start]);
27894
- return current && state ? { controller: current, state } : void 0;
28359
+ return current && state2 ? { controller: current, state: state2 } : void 0;
27895
28360
  }
27896
28361
 
27897
28362
  // packages/experience-design-system-cli/src/tui/help/PageContainer.tsx
27898
28363
  import { useEffect as useEffect21, useState as useState27 } from "react";
27899
28364
  import { Box as Box42, Text as Text44, useInput as useInput9 } from "ink";
27900
-
27901
- // packages/experience-design-system-cli/src/tui/debug-store.ts
27902
- import { mkdir as mkdir9, writeFile as writeFile8 } from "node:fs/promises";
27903
- import { existsSync as existsSync9, readdirSync as readdirSync4 } from "node:fs";
27904
- import { join as join24 } from "node:path";
27905
-
27906
- // packages/experience-design-system-cli/src/tui/settings/debug-mode/debug-mode-store.ts
27907
- var DEFAULT_DEBUG_MODE_SETTING = {
27908
- enabled: true
27909
- };
27910
- async function readDebugModeSetting() {
27911
- const { debugMode } = await readSettings2();
27912
- return { ...DEFAULT_DEBUG_MODE_SETTING, ...debugMode };
27913
- }
27914
- async function writeDebugModeSetting(setting) {
27915
- await updateSettings2({ debugMode: setting });
27916
- }
27917
-
27918
- // packages/experience-design-system-cli/src/tui/debug-store.ts
27919
- var pendingRun;
27920
- function generateRunId() {
27921
- const now = /* @__PURE__ */ new Date();
27922
- const pad = (n) => String(n).padStart(2, "0");
27923
- return `${now.getFullYear()}${pad(now.getMonth() + 1)}${pad(now.getDate())}-${pad(now.getHours())}${pad(now.getMinutes())}${pad(now.getSeconds())}`;
27924
- }
27925
- function datePrefix(now = /* @__PURE__ */ new Date()) {
27926
- const pad = (n) => String(n).padStart(2, "0");
27927
- return `${pad(now.getMonth() + 1)}-${pad(now.getDate())}-${now.getFullYear()}`;
27928
- }
27929
- function slugify(value) {
27930
- return value.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
27931
- }
27932
- function generateSessionId3() {
27933
- const today = datePrefix();
27934
- const root = debugSessionsDir2();
27935
- const existing = existsSync9(root) ? readdirSync4(root) : [];
27936
- const seqPattern = new RegExp(`^${today}-session-(\\d+)$`);
27937
- const maxSeq = existing.reduce((max, entry) => {
27938
- const match2 = seqPattern.exec(entry);
27939
- return match2 ? Math.max(max, Number(match2[1])) : max;
27940
- }, 0);
27941
- return `${today}-session-${maxSeq + 1}`;
27942
- }
27943
- var SESSION_ID = generateSessionId3();
27944
- function sessionDebugDir() {
27945
- return join24(debugSessionsDir2(), SESSION_ID);
27946
- }
27947
- function currentDebugSessionDir() {
27948
- return sessionDebugDir();
27949
- }
27950
- void isDebugModeEnabled().then((enabled) => {
27951
- if (!enabled) return void 0;
27952
- return mkdir9(sessionDebugDir(), { recursive: true });
27953
- });
27954
- async function isDebugModeEnabled() {
27955
- try {
27956
- return (await readDebugModeSetting()).enabled;
27957
- } catch {
27958
- return true;
27959
- }
27960
- }
27961
- function redact(value) {
27962
- const clone = { ...value };
27963
- if ("cma_token" in clone) {
27964
- const raw = clone.cma_token;
27965
- clone.cma_token = typeof raw === "string" && raw.length > 0 ? `[present, ${raw.length} chars]` : "[not set]";
27966
- }
27967
- return clone;
27968
- }
27969
- function startDebugRun({
27970
- flow,
27971
- step,
27972
- menuOption,
27973
- inputs
27974
- }) {
27975
- const runId = generateRunId();
27976
- const startedAt = Date.now();
27977
- const redactedInputs = redact(inputs);
27978
- isDebugModeEnabled().then((enabled) => {
27979
- if (!enabled) return;
27980
- pendingRun = { flow, step, runId, menuOption, inputs: redactedInputs, startedAt };
27981
- });
27982
- }
27983
- async function finishDebugRun({
27984
- outputs,
27985
- status,
27986
- exitMethod
27987
- }) {
27988
- const run = pendingRun;
27989
- if (!run) return;
27990
- pendingRun = void 0;
27991
- const durationMs = Date.now() - run.startedAt;
27992
- const content = renderMarkdown(run, { outputs: redact(outputs), status, exitMethod, durationMs });
27993
- const flowSegments = run.flow.split("/");
27994
- const dir = join24(sessionDebugDir(), ...flowSegments);
27995
- await mkdir9(dir, { recursive: true });
27996
- const filename = nextAttemptFilename(dir, run.menuOption);
27997
- await writeFile8(join24(dir, filename), content, { mode: 384 });
27998
- }
27999
- function nextAttemptFilename(dir, menuOption) {
28000
- const today = datePrefix();
28001
- const optionSlug = slugify(menuOption);
28002
- const existing = existsSync9(dir) ? readdirSync4(dir) : [];
28003
- const attemptPattern = new RegExp(`^${today}-${optionSlug}-attempt-(\\d+)\\.md$`);
28004
- const maxAttempt = existing.reduce((max, entry) => {
28005
- const match2 = attemptPattern.exec(entry);
28006
- return match2 ? Math.max(max, Number(match2[1])) : max;
28007
- }, 0);
28008
- return `${today}-${optionSlug}-attempt-${maxAttempt + 1}.md`;
28009
- }
28010
- function renderMarkdown(run, finish) {
28011
- const stepMatch = /^(\d+)-(.+)$/.exec(run.step);
28012
- const stepLabel2 = stepMatch ? `${stepMatch[1]} - ${stepMatch[2]}` : run.step;
28013
- const flowSlug = run.flow.split("/").join("-");
28014
- return `# Debug Log
28015
-
28016
- - Run ID: ${run.runId}
28017
- - Flow: ${flowSlug}
28018
- - Step: ${stepLabel2}
28019
- - Menu option: ${run.menuOption}
28020
- - Date: ${(/* @__PURE__ */ new Date()).toISOString()}
28021
- - CLI version: ${readPackageVersion()}
28022
- - Platform: ${process.platform} / Node ${process.version}
28023
- - Duration on screen: ${finish.durationMs}ms
28024
- - Status: ${finish.status}
28025
- - Exit method: ${finish.exitMethod}
28026
-
28027
- ## Inputs
28028
- \`\`\`json
28029
- ${JSON.stringify(run.inputs, null, 2)}
28030
- \`\`\`
28031
-
28032
- ## Outputs
28033
- \`\`\`json
28034
- ${JSON.stringify(finish.outputs, null, 2)}
28035
- \`\`\`
28036
- `;
28037
- }
28038
- function handleCrash() {
28039
- return finishDebugRun({ outputs: {}, status: "error", exitMethod: "crashed" });
28040
- }
28041
- process.once("uncaughtException", (err) => {
28042
- void handleCrash().finally(() => {
28043
- throw err;
28044
- });
28045
- });
28046
- process.once("unhandledRejection", (reason) => {
28047
- void handleCrash().finally(() => {
28048
- throw reason;
28049
- });
28050
- });
28051
- process.once("SIGINT", () => {
28052
- void handleCrash().finally(() => {
28053
- process.exit(130);
28054
- });
28055
- });
28365
+ init_debug_store();
28056
28366
 
28057
28367
  // packages/experience-design-system-cli/src/tui/help/help-info.ts
28368
+ init_config();
28369
+ init_debug_store();
28370
+ init_debug_mode_store();
28371
+ init_version();
28058
28372
  async function readHelpInfo() {
28059
28373
  const debugMode = await readDebugModeSetting();
28060
28374
  return {
28061
28375
  storage: [
28062
28376
  { label: "Config folder", value: configRoot2() },
28063
- { label: "Settings file", value: configFilePath2() },
28064
- { label: "Debug logs", value: debugSessionsDir2() }
28377
+ { label: "Settings file", value: configFilePath2() }
28065
28378
  ],
28066
28379
  troubleshooting: [
28067
28380
  { label: "CLI version", value: readPackageVersion() },
@@ -28070,7 +28383,7 @@ async function readHelpInfo() {
28070
28383
  { label: "Debug Mode", value: debugMode.enabled ? "on" : "off" },
28071
28384
  {
28072
28385
  label: "This session",
28073
- value: debugMode.enabled ? currentDebugSessionDir() : "no logs written while Debug Mode is off"
28386
+ 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"
28074
28387
  }
28075
28388
  ]
28076
28389
  };
@@ -28187,6 +28500,7 @@ import { Box as Box44, Text as Text46, useInput as useInput11 } from "ink";
28187
28500
  import TextInput4 from "ink-text-input";
28188
28501
 
28189
28502
  // packages/experience-design-system-cli/src/tui/settings/utils/v1-store.ts
28503
+ init_config();
28190
28504
  var readV1Store = readSettings2;
28191
28505
  var writeV1Store = writeSettings2;
28192
28506
 
@@ -28199,7 +28513,8 @@ async function readCredentials() {
28199
28513
  cmaToken: store.cmaToken || "",
28200
28514
  host: store.host || "",
28201
28515
  defaultComponentDir: store.defaultComponentDir || "",
28202
- defaultTokenFile: store.defaultTokenFile || ""
28516
+ defaultTokenFile: store.defaultTokenFile || "",
28517
+ contentfulBaseDir: store.contentfulBaseDir || ""
28203
28518
  };
28204
28519
  }
28205
28520
  async function writeCredentials(config) {
@@ -28215,6 +28530,7 @@ async function writeCredentials(config) {
28215
28530
  }
28216
28531
 
28217
28532
  // packages/experience-design-system-cli/src/tui/settings/contentful-configuration/ContentfulConfigScreen.tsx
28533
+ init_debug_store();
28218
28534
  import { Fragment as Fragment17, jsx as jsx55, jsxs as jsxs45 } from "react/jsx-runtime";
28219
28535
  var FIELD_ORDER = [
28220
28536
  "spaceId",
@@ -28222,7 +28538,8 @@ var FIELD_ORDER = [
28222
28538
  "cmaToken",
28223
28539
  "host",
28224
28540
  "defaultComponentDir",
28225
- "defaultTokenFile"
28541
+ "defaultTokenFile",
28542
+ "contentfulBaseDir"
28226
28543
  ];
28227
28544
  function debugFields(config) {
28228
28545
  return {
@@ -28231,17 +28548,23 @@ function debugFields(config) {
28231
28548
  cma_token: config?.cmaToken ?? "",
28232
28549
  host: config?.host ?? "",
28233
28550
  default_component_dir: config?.defaultComponentDir ?? "",
28234
- default_token_file: config?.defaultTokenFile ?? ""
28551
+ default_token_file: config?.defaultTokenFile ?? "",
28552
+ contentful_base_dir: config?.contentfulBaseDir ?? ""
28235
28553
  };
28236
28554
  }
28237
28555
  var FIELD_LABELS = {
28238
28556
  spaceId: "Space ID",
28239
28557
  environmentId: "Environment ID",
28240
28558
  cmaToken: "CMA Token",
28241
- host: "API Host (optional)",
28242
- defaultComponentDir: "Default component directory (optional)",
28243
- defaultTokenFile: "Default token file (optional)"
28559
+ host: "API Host",
28560
+ defaultComponentDir: "Default component directory",
28561
+ defaultTokenFile: "Default token file",
28562
+ contentfulBaseDir: "Root Project Directory"
28244
28563
  };
28564
+ var FIELD_HINTS = {
28565
+ contentfulBaseDir: "(where .contentful goes)"
28566
+ };
28567
+ var LABEL_WIDTH = Math.max(...Object.values(FIELD_LABELS).map((label) => label.length));
28245
28568
  function ConfigurationScreen({ onDone }) {
28246
28569
  const [stage, setStage] = useState29("loading");
28247
28570
  const [config, setConfig] = useState29(null);
@@ -28277,6 +28600,7 @@ function ConfigurationScreen({ onDone }) {
28277
28600
  setNotice(null);
28278
28601
  writeCredentials(config).then(() => {
28279
28602
  setLastSaved(config);
28603
+ if (config.contentfulBaseDir) void startDebugSessionIn(config.contentfulBaseDir, { replace: true });
28280
28604
  setNotice({ kind: "success", text: "Configuration saved" });
28281
28605
  setStage("form");
28282
28606
  }).catch((err) => {
@@ -28342,10 +28666,7 @@ function ConfigurationScreen({ onDone }) {
28342
28666
  const display = field === "cmaToken" ? "\u2022".repeat(value.length) : value;
28343
28667
  return /* @__PURE__ */ jsxs45(Box44, { gap: 1, children: [
28344
28668
  /* @__PURE__ */ jsx55(Text46, { color: isActive ? PALETTE.accent : void 0, children: isActive ? "\u276F" : " " }),
28345
- /* @__PURE__ */ jsxs45(Text46, { bold: isActive, children: [
28346
- FIELD_LABELS[field],
28347
- ":"
28348
- ] }),
28669
+ /* @__PURE__ */ jsx55(Box44, { width: LABEL_WIDTH, flexShrink: 0, children: /* @__PURE__ */ jsx55(Text46, { bold: isActive, color: isActive ? PALETTE.accent : PALETTE.muted, children: FIELD_LABELS[field] }) }),
28349
28670
  isActive && editing ? /* @__PURE__ */ jsx55(
28350
28671
  TextInput4,
28351
28672
  {
@@ -28354,7 +28675,8 @@ function ConfigurationScreen({ onDone }) {
28354
28675
  onSubmit: () => setEditing(false),
28355
28676
  mask: field === "cmaToken" ? "\u2022" : void 0
28356
28677
  }
28357
- ) : /* @__PURE__ */ jsx55(Text46, { children: display || /* @__PURE__ */ jsx55(Text46, { color: PALETTE.muted, children: "(empty)" }) })
28678
+ ) : /* @__PURE__ */ jsx55(Text46, { bold: !!display, children: display || (FIELD_HINTS[field] ? "" : /* @__PURE__ */ jsx55(Text46, { color: PALETTE.muted, children: "(empty)" })) }),
28679
+ FIELD_HINTS[field] && /* @__PURE__ */ jsx55(Text46, { color: PALETTE.muted, children: FIELD_HINTS[field] })
28358
28680
  ] }, field);
28359
28681
  }) }),
28360
28682
  notice && /* @__PURE__ */ jsxs45(Fragment17, { children: [
@@ -28406,6 +28728,7 @@ async function writeAnalyticsSetting(setting) {
28406
28728
  }
28407
28729
 
28408
28730
  // packages/experience-design-system-cli/src/tui/settings/opt-in-analytics/screen.tsx
28731
+ init_debug_store();
28409
28732
  import { Fragment as Fragment18, jsx as jsx56, jsxs as jsxs46 } from "react/jsx-runtime";
28410
28733
  function OptInAnalyticsScreen({ onDone }) {
28411
28734
  const [loading, setLoading] = useState30(true);
@@ -28466,6 +28789,8 @@ function OptInAnalyticsScreen({ onDone }) {
28466
28789
  // packages/experience-design-system-cli/src/tui/upgrade/PageContainer.tsx
28467
28790
  import { useEffect as useEffect24, useState as useState31 } from "react";
28468
28791
  import { Box as Box46, Text as Text48, useInput as useInput13 } from "ink";
28792
+ init_version();
28793
+ init_debug_store();
28469
28794
  import { jsx as jsx57, jsxs as jsxs47 } from "react/jsx-runtime";
28470
28795
  var UPGRADE_COMMANDS = ["git pull", "pnpm install", "pnpm build"];
28471
28796
  function UpgradeScreen({ onDone }) {
@@ -28537,6 +28862,8 @@ function renderBody(upgradeCheck) {
28537
28862
  // packages/experience-design-system-cli/src/tui/settings/debug-mode/screen.tsx
28538
28863
  import { useEffect as useEffect25, useState as useState32 } from "react";
28539
28864
  import { Box as Box47, Text as Text49, useInput as useInput14 } from "ink";
28865
+ init_debug_mode_store();
28866
+ init_debug_store();
28540
28867
  import { jsx as jsx58, jsxs as jsxs48 } from "react/jsx-runtime";
28541
28868
  function DebugModeScreen({ onDone }) {
28542
28869
  const [loading, setLoading] = useState32(true);
@@ -28637,16 +28964,16 @@ function App({ importOptions, inkClear }) {
28637
28964
  const finishCredentials = async (result, projectPath2, tokens, filePaths) => {
28638
28965
  if (!result.skipped) await writeCredentials({ ...result.credentials });
28639
28966
  const launch = { projectPath: projectPath2, tokens, filePaths, ...importOptions };
28640
- const state = await inspectTokens({
28967
+ const state2 = await inspectTokens({
28641
28968
  rawTokensPath: tokens,
28642
- outDir: join25(resolveUserPath(projectPath2), ".contentful"),
28969
+ contentfulDir: join25(resolveUserPath(projectPath2), ".contentful"),
28643
28970
  cache: importOptions.cache
28644
28971
  });
28645
- if (state.kind === "cached") {
28972
+ if (state2.kind === "cached") {
28646
28973
  setPendingLaunch({
28647
28974
  launch,
28648
28975
  credentials: result,
28649
- cached: { tokensPath: state.tokensPath, sourceChanged: state.sourceChanged }
28976
+ cached: { tokensPath: state2.tokensPath, sourceChanged: state2.sourceChanged }
28650
28977
  });
28651
28978
  return;
28652
28979
  }
@@ -28660,6 +28987,7 @@ function App({ importOptions, inkClear }) {
28660
28987
  const settings = await readSettings2();
28661
28988
  const { agent, agentModel } = resolveAgentChoice(launch.agent, settings);
28662
28989
  const generatePromptPath = typeof settings.generatePromptPath === "string" ? settings.generatePromptPath : void 0;
28990
+ const outDir = await (await Promise.resolve().then(() => (init_debug_store(), debug_store_exports))).startImportRun(resolveUserPath(launch.projectPath ?? ""));
28663
28991
  setExtractionRun({
28664
28992
  ...generatePromptPath ? { generatePromptPath } : {},
28665
28993
  // the later steps get the same agent, so they use what the stage used
@@ -28668,6 +28996,7 @@ function App({ importOptions, inkClear }) {
28668
28996
  tokenStrategy,
28669
28997
  input: {
28670
28998
  projectPath: resolveUserPath(launch.projectPath ?? ""),
28999
+ outDir,
28671
29000
  filePaths: launch.filePaths ?? [],
28672
29001
  rawTokensPath: launch.tokens ?? "",
28673
29002
  tokenStrategy,