@contentful/experience-design-system-cli 2.37.1-dev-build-2eb3abd8.0 → 2.37.1-dev-build-9d1e87d0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/app.js CHANGED
@@ -837,7 +837,7 @@ async function runAgent(options) {
837
837
  promptLen: prompt.length,
838
838
  promptHead: prompt.slice(0, 500)
839
839
  });
840
- return new Promise((resolve27) => {
840
+ return new Promise((resolve28) => {
841
841
  const bedrockEnv = bedrock ? BEDROCK_ENV_BY_AGENT[agent] : void 0;
842
842
  const child = spawn(binary, args, {
843
843
  stdio: ["pipe", "pipe", "pipe"],
@@ -886,7 +886,7 @@ async function runAgent(options) {
886
886
  stderrLen: stderr.length,
887
887
  stderrTail: stderr.slice(-1e3)
888
888
  });
889
- resolve27(result);
889
+ resolve28(result);
890
890
  });
891
891
  });
892
892
  }
@@ -908,7 +908,7 @@ async function checkAgentAuth(agent) {
908
908
  return "not-found";
909
909
  if (agent !== "claude")
910
910
  return "ok";
911
- return new Promise((resolve27) => {
911
+ return new Promise((resolve28) => {
912
912
  const child = spawn2(binary, ["auth", "status", "--json"], { stdio: ["ignore", "pipe", "pipe"] });
913
913
  let stdout = "";
914
914
  let done = false;
@@ -917,7 +917,7 @@ async function checkAgentAuth(agent) {
917
917
  return;
918
918
  done = true;
919
919
  child.kill("SIGTERM");
920
- resolve27("unauthenticated");
920
+ resolve28("unauthenticated");
921
921
  }, 5e3);
922
922
  child.stdout?.on("data", (chunk) => {
923
923
  stdout += chunk.toString();
@@ -928,14 +928,14 @@ async function checkAgentAuth(agent) {
928
928
  done = true;
929
929
  clearTimeout(timer);
930
930
  if (code !== 0) {
931
- resolve27("unauthenticated");
931
+ resolve28("unauthenticated");
932
932
  return;
933
933
  }
934
934
  try {
935
935
  const status = JSON.parse(stdout);
936
- resolve27(status.loggedIn ? "ok" : "unauthenticated");
936
+ resolve28(status.loggedIn ? "ok" : "unauthenticated");
937
937
  } catch {
938
- resolve27("unauthenticated");
938
+ resolve28("unauthenticated");
939
939
  }
940
940
  });
941
941
  });
@@ -945,9 +945,9 @@ async function binaryIsOnPath(binary) {
945
945
  const fs = await import("node:fs/promises");
946
946
  return fs.access(binary).then(() => true, () => false);
947
947
  }
948
- return new Promise((resolve27) => {
948
+ return new Promise((resolve28) => {
949
949
  const child = spawn2(process.platform === "win32" ? "where" : "which", [binary], { stdio: "ignore" });
950
- child.on("close", (code) => resolve27(code === 0));
950
+ child.on("close", (code) => resolve28(code === 0));
951
951
  });
952
952
  }
953
953
  var init_check_agent_auth = __esm({
@@ -2329,8 +2329,8 @@ var init_debug_store = __esm({
2329
2329
  });
2330
2330
 
2331
2331
  // packages/experience-design-system-cli/app.tsx
2332
- import { join as join25 } from "node:path";
2333
- import { useEffect as useEffect25, useState as useState32 } from "react";
2332
+ import { join as join26 } from "node:path";
2333
+ import { useEffect as useEffect28, useState as useState37 } from "react";
2334
2334
 
2335
2335
  // packages/experience-design-system-cli/src/tui/home/home.tsx
2336
2336
  import { useEffect as useEffect2, useState as useState2 } from "react";
@@ -2431,17 +2431,18 @@ var SUBTITLE = "Let's import your design system into Contentful";
2431
2431
  var MIN_TERMINAL_WIDTH = 164;
2432
2432
  var START_ITEMS = [
2433
2433
  { label: "Import", screen: "import" },
2434
+ { label: "Upgrade Version", screen: "upgrade" },
2434
2435
  { label: "Settings", screen: "settings" },
2435
2436
  { label: "Help", screen: "help" }
2436
2437
  ];
2437
- function versionStatus(upgradeCheck) {
2438
+ function upgradeItemDisplay(upgradeCheck) {
2438
2439
  if (upgradeCheck?.status === "update-available") {
2439
- return { text: ` (upgrade available v${upgradeCheck.latest})`, color: PALETTE.warning };
2440
+ return { label: `Upgrade Version (v${upgradeCheck.latest} available)`, color: PALETTE.warning };
2440
2441
  }
2441
2442
  if (upgradeCheck?.status === "up-to-date") {
2442
- return { text: " (up to date)", color: PALETTE.muted };
2443
+ return { label: "Upgrade Version (up to date)", color: PALETTE.muted };
2443
2444
  }
2444
- return void 0;
2445
+ return { label: "Upgrade Version" };
2445
2446
  }
2446
2447
  function HomeScreen({ onNavigate }) {
2447
2448
  const [focusIdx, setFocusIdx] = useState2(0);
@@ -2449,7 +2450,7 @@ function HomeScreen({ onNavigate }) {
2449
2450
  const { exit } = useApp();
2450
2451
  const terminalWidth = useTerminalWidth();
2451
2452
  const tooNarrow = terminalWidth < MIN_TERMINAL_WIDTH;
2452
- const status = versionStatus(upgradeCheck);
2453
+ const upgradeDisabled = upgradeCheck?.status === "up-to-date";
2453
2454
  useEffect2(() => {
2454
2455
  checkForUpgrade().then(setUpgradeCheck).catch(() => setUpgradeCheck({ status: "error" }));
2455
2456
  }, []);
@@ -2469,6 +2470,7 @@ function HomeScreen({ onNavigate }) {
2469
2470
  }
2470
2471
  if (key.return) {
2471
2472
  const item = START_ITEMS[focusIdx];
2473
+ if (item.screen === "upgrade" && upgradeDisabled) return;
2472
2474
  onNavigate(item.screen);
2473
2475
  return;
2474
2476
  }
@@ -2486,16 +2488,26 @@ function HomeScreen({ onNavigate }) {
2486
2488
  /* @__PURE__ */ jsx2(Text2, { color: PALETTE.muted, children: SUBTITLE }),
2487
2489
  /* @__PURE__ */ jsxs(Text2, { color: PALETTE.muted, children: [
2488
2490
  "v",
2489
- VERSION,
2490
- status && /* @__PURE__ */ jsx2(Text2, { color: status.color, children: status.text })
2491
+ VERSION
2491
2492
  ] })
2492
2493
  ] }),
2493
2494
  /* @__PURE__ */ jsx2(Box, { marginTop: 1, justifyContent: "center", children: /* @__PURE__ */ jsx2(Box, { flexDirection: "column", children: START_ITEMS.map((item, i) => {
2494
2495
  const focused = i === focusIdx;
2495
- return /* @__PURE__ */ jsxs(Text2, { bold: focused, color: focused ? PALETTE.accent : void 0, children: [
2496
- focused ? `${FOCUS_MARKER} ` : " ",
2496
+ const isUpgradeItem = item.screen === "upgrade";
2497
+ const display = isUpgradeItem ? upgradeItemDisplay(upgradeCheck) : { label: item.label };
2498
+ const dimmed = isUpgradeItem && upgradeDisabled;
2499
+ return /* @__PURE__ */ jsxs(
2500
+ Text2,
2501
+ {
2502
+ bold: focused && !dimmed,
2503
+ color: dimmed ? PALETTE.muted : focused ? PALETTE.accent : display.color,
2504
+ children: [
2505
+ focused ? `${FOCUS_MARKER} ` : " ",
2506
+ display.label
2507
+ ]
2508
+ },
2497
2509
  item.label
2498
- ] }, item.label);
2510
+ );
2499
2511
  }) }) }),
2500
2512
  /* @__PURE__ */ jsx2(Box, { marginTop: 1, justifyContent: "center", children: /* @__PURE__ */ jsx2(
2501
2513
  ControlHints,
@@ -8441,10 +8453,10 @@ function extractVueSlotsFromSetup(options) {
8441
8453
  if (!body)
8442
8454
  return [];
8443
8455
  const slotsByName = /* @__PURE__ */ new Map();
8444
- for (const access6 of body.getDescendantsOfKind(SyntaxKind5.PropertyAccessExpression)) {
8445
- if (access6.getExpression().getText() !== slotsName)
8456
+ for (const access7 of body.getDescendantsOfKind(SyntaxKind5.PropertyAccessExpression)) {
8457
+ if (access7.getExpression().getText() !== slotsName)
8446
8458
  continue;
8447
- const slotName = access6.getName();
8459
+ const slotName = access7.getName();
8448
8460
  if (!slotsByName.has(slotName)) {
8449
8461
  slotsByName.set(slotName, {
8450
8462
  name: slotName,
@@ -13834,7 +13846,7 @@ function errorMessage(error) {
13834
13846
  return error instanceof Error && error.message ? error.message : String(error);
13835
13847
  }
13836
13848
  function defaultSleep(delayMs) {
13837
- return new Promise((resolve27) => setTimeout(resolve27, delayMs));
13849
+ return new Promise((resolve28) => setTimeout(resolve28, delayMs));
13838
13850
  }
13839
13851
 
13840
13852
  // packages/experience-design-system-backend-pipeline/dist/src/steps/apply/src/helpers/sanitize-preview.js
@@ -14075,7 +14087,7 @@ var ApiClient = class {
14075
14087
  const progress = maxAttempts > 1 ? attempt / (maxAttempts - 1) : 0;
14076
14088
  const baseDelay = intervalMs + (maxIntervalMs - intervalMs) * progress;
14077
14089
  const jitter = Math.random() * baseDelay * 0.15;
14078
- await new Promise((resolve27) => setTimeout(resolve27, baseDelay + jitter));
14090
+ await new Promise((resolve28) => setTimeout(resolve28, baseDelay + jitter));
14079
14091
  }
14080
14092
  }
14081
14093
  throw new Error(`Operation ${operationId} timed out after ${maxAttempts} attempts`);
@@ -14560,6 +14572,7 @@ function readTokensFromPath2(request) {
14560
14572
  init_agents();
14561
14573
  init_agent_name();
14562
14574
  init_models();
14575
+ init_binaries();
14563
14576
  init_is_agent_name();
14564
14577
  init_agent_supports_bedrock();
14565
14578
  init_check_agent_auth();
@@ -15118,11 +15131,11 @@ function setCommandContext(context) {
15118
15131
  mergeContext(state.pending.context, context);
15119
15132
  mergeContext(state.pending.completion, context);
15120
15133
  }
15121
- function enrichCommandResult(fields) {
15134
+ function enrichCommandResult(fields2) {
15122
15135
  if (!state.pending)
15123
15136
  return;
15124
- Object.assign(state.pending.completion, fields);
15125
- mergeContext(state.pending.context, fields);
15137
+ Object.assign(state.pending.completion, fields2);
15138
+ mergeContext(state.pending.context, fields2);
15126
15139
  }
15127
15140
 
15128
15141
  // packages/experience-design-system-backend-pipeline/dist/src/analytics/os.js
@@ -16384,7 +16397,7 @@ async function retryDatabaseWrite(operation, attempts = 8) {
16384
16397
  const message = error instanceof Error ? error.message : String(error);
16385
16398
  if (!/database is locked|database is busy/i.test(message) || attempt >= attempts)
16386
16399
  throw error;
16387
- await new Promise((resolve27) => setTimeout(resolve27, Math.min(250 * attempt, 2e3)));
16400
+ await new Promise((resolve28) => setTimeout(resolve28, Math.min(250 * attempt, 2e3)));
16388
16401
  }
16389
16402
  }
16390
16403
  }
@@ -22331,16 +22344,16 @@ function SlotRow({
22331
22344
  ] });
22332
22345
  }
22333
22346
  function propFields(prop) {
22334
- const fields = ["description", "required", "type"];
22347
+ const fields2 = ["description", "required", "type"];
22335
22348
  if (prop.type === "token") {
22336
- fields.push("tokenKind");
22349
+ fields2.push("tokenKind");
22337
22350
  }
22338
- if (prop.type === "enum") fields.push("values");
22351
+ if (prop.type === "enum") fields2.push("values");
22339
22352
  if (prop.type !== "richtext" && prop.type !== "media" && prop.type !== "link") {
22340
- fields.push("default");
22353
+ fields2.push("default");
22341
22354
  }
22342
- if (prop.type === "token" && prop.category === "design") fields.push("allowed");
22343
- return fields;
22355
+ if (prop.type === "token" && prop.category === "design") fields2.push("allowed");
22356
+ return fields2;
22344
22357
  }
22345
22358
  var SLOT_FIELDS = ["description", "required", "allowedComponents"];
22346
22359
  function simulateGraphWithCandidate(projectSlotGraph, selfName, currentSlots, targetSlotName, candidate) {
@@ -22879,8 +22892,8 @@ function FieldEditor({
22879
22892
  return;
22880
22893
  }
22881
22894
  if (focusLevel === "field") {
22882
- const fields = inSlots ? SLOT_FIELDS : currentProp ? propFields(currentProp) : [];
22883
- const currentFieldIdx = fields.indexOf(activeField);
22895
+ const fields2 = inSlots ? SLOT_FIELDS : currentProp ? propFields(currentProp) : [];
22896
+ const currentFieldIdx = fields2.indexOf(activeField);
22884
22897
  const isValuesNav = activeField === "values" || activeField === "allowedComponents";
22885
22898
  const arrowUp = key.upArrow;
22886
22899
  const arrowDown = key.downArrow;
@@ -22894,10 +22907,10 @@ function FieldEditor({
22894
22907
  const navPrevious = arrowUp || arrowLeft;
22895
22908
  const navNext = arrowDown || arrowRight || input === "j";
22896
22909
  const navBack = navPrevious || input === "k";
22897
- if ((navBack || navNext) && fields.length > 0) {
22898
- const lastIdx = fields.length - 1;
22910
+ if ((navBack || navNext) && fields2.length > 0) {
22911
+ const lastIdx = fields2.length - 1;
22899
22912
  const targetIdx = navNext ? currentFieldIdx >= lastIdx ? 0 : currentFieldIdx + 1 : currentFieldIdx <= 0 ? lastIdx : currentFieldIdx - 1;
22900
- const next = fields[targetIdx];
22913
+ const next = fields2[targetIdx];
22901
22914
  setActiveField(next);
22902
22915
  if (next === "description") {
22903
22916
  const desc = inSlots ? currentSlot?.description ?? "" : currentProp?.description ?? "";
@@ -28018,7 +28031,7 @@ var realSaveDeps = () => ({
28018
28031
  writeFile: (path5, contents) => writeFile7(path5, contents),
28019
28032
  appendRun,
28020
28033
  buildSourceFingerprint,
28021
- sleep: (ms) => new Promise((resolve27) => setTimeout(resolve27, ms)),
28034
+ sleep: (ms) => new Promise((resolve28) => setTimeout(resolve28, ms)),
28022
28035
  warn: (message) => process.stderr.write(message)
28023
28036
  });
28024
28037
  async function runPrintFiles(input, deps, onPatch) {
@@ -28408,12 +28421,44 @@ init_config();
28408
28421
  init_debug_store();
28409
28422
  init_debug_mode_store();
28410
28423
  init_version();
28424
+
28425
+ // packages/experience-design-system-cli/src/tui/help/file-locations.ts
28426
+ import { join as join25, resolve as resolve27 } from "node:path";
28427
+ function describeFileLocations({
28428
+ contentfulBaseDir,
28429
+ debugModeEnabled,
28430
+ currentSessionDir: currentSessionDir2
28431
+ }) {
28432
+ if (!debugModeEnabled) {
28433
+ return {
28434
+ debugLogs: "none while Debug Mode is off",
28435
+ importFiles: `${join25("<project>", ".contentful")}/ (tokens.json, components.json)`
28436
+ };
28437
+ }
28438
+ const base = contentfulBaseDir ? resolve27(contentfulBaseDir) : "<project>";
28439
+ const session = currentSessionDir2 ?? join25(base, ".contentful", "<date>-session-<n>");
28440
+ return {
28441
+ debugLogs: join25(session, "debug"),
28442
+ importFiles: `${join25(session, "dsi-import-<n>")}/ (tokens.json, components.json)`
28443
+ };
28444
+ }
28445
+
28446
+ // packages/experience-design-system-cli/src/tui/help/help-info.ts
28411
28447
  async function readHelpInfo() {
28412
- const debugMode = await readDebugModeSetting();
28448
+ const [debugMode, settings] = await Promise.all([readDebugModeSetting(), readSettings2()]);
28449
+ const base = settings["contentfulBaseDir"];
28450
+ const locations = describeFileLocations({
28451
+ contentfulBaseDir: typeof base === "string" ? base : "",
28452
+ debugModeEnabled: debugMode.enabled,
28453
+ currentSessionDir: currentSessionDir()
28454
+ });
28413
28455
  return {
28414
28456
  storage: [
28415
28457
  { label: "Config folder", value: configRoot2() },
28416
- { label: "Settings file", value: configFilePath2() }
28458
+ { label: "Settings file", value: configFilePath2() },
28459
+ { label: "Agent settings", value: `${configFilePath2()} (keys: agent, agentModel, agents)` },
28460
+ { label: "Debug logs", value: locations.debugLogs },
28461
+ { label: "Import files", value: locations.importFiles }
28417
28462
  ],
28418
28463
  troubleshooting: [
28419
28464
  { label: "CLI version", value: readPackageVersion() },
@@ -28434,7 +28479,7 @@ function Section({ title, rows }) {
28434
28479
  return /* @__PURE__ */ jsxs43(Box42, { flexDirection: "column", children: [
28435
28480
  /* @__PURE__ */ jsx53(Text44, { bold: true, color: PALETTE.accent, children: title }),
28436
28481
  rows.map((row) => /* @__PURE__ */ jsxs43(Box42, { gap: 1, children: [
28437
- /* @__PURE__ */ jsx53(Box42, { width: 14, flexShrink: 0, children: /* @__PURE__ */ jsx53(Text44, { color: PALETTE.muted, children: row.label }) }),
28482
+ /* @__PURE__ */ jsx53(Box42, { width: 16, flexShrink: 0, children: /* @__PURE__ */ jsx53(Text44, { color: PALETTE.muted, children: row.label }) }),
28438
28483
  /* @__PURE__ */ jsx53(Text44, { children: row.value })
28439
28484
  ] }, row.label))
28440
28485
  ] });
@@ -28534,15 +28579,694 @@ function SettingsScreen({
28534
28579
  }
28535
28580
 
28536
28581
  // packages/experience-design-system-cli/src/tui/settings/contentful-configuration/ContentfulConfigScreen.tsx
28537
- import { useEffect as useEffect22, useState as useState29 } from "react";
28538
- import { Box as Box44, Text as Text46, useInput as useInput11 } from "ink";
28539
- import TextInput4 from "ink-text-input";
28582
+ import { useState as useState33 } from "react";
28583
+ import { Box as Box48, Text as Text51, useInput as useInput13 } from "ink";
28584
+
28585
+ // packages/experience-design-system-cli/src/tui/settings/agents/AgentsScreen.tsx
28586
+ import { useEffect as useEffect23, useState as useState31 } from "react";
28587
+ import { Box as Box46, Text as Text49, useInput as useInput12 } from "ink";
28588
+ init_debug_store();
28540
28589
 
28541
28590
  // packages/experience-design-system-cli/src/tui/settings/utils/v1-store.ts
28542
28591
  init_config();
28543
28592
  var readV1Store = readSettings2;
28544
28593
  var writeV1Store = writeSettings2;
28545
28594
 
28595
+ // packages/experience-design-system-cli/src/tui/settings/agents/agent-store.ts
28596
+ var DEFAULT_AGENT3 = "claude";
28597
+ var AGENT_LABELS = {
28598
+ claude: "Claude Code",
28599
+ codex: "OpenAI Codex",
28600
+ opencode: "OpenCode",
28601
+ cursor: "Cursor",
28602
+ copilot: "GitHub Copilot"
28603
+ };
28604
+ var asString = (value) => typeof value === "string" ? value : "";
28605
+ function emptyAgents() {
28606
+ return Object.fromEntries(AGENT_NAMES.map((name) => [name, { model: "", binary: "" }]));
28607
+ }
28608
+ async function readAgentConfig() {
28609
+ const store = await readV1Store();
28610
+ const stored = asString(store["agent"]);
28611
+ const defaultAgent = isAgentName(stored) ? stored : DEFAULT_AGENT3;
28612
+ const agents = emptyAgents();
28613
+ const saved = store["agents"];
28614
+ if (saved && typeof saved === "object") {
28615
+ for (const name of AGENT_NAMES) {
28616
+ const entry = saved[name];
28617
+ if (entry && typeof entry === "object") {
28618
+ const fields2 = entry;
28619
+ agents[name] = { model: asString(fields2["model"]), binary: asString(fields2["binary"]) };
28620
+ }
28621
+ }
28622
+ }
28623
+ const legacyModel = asString(store["agentModel"]);
28624
+ if (legacyModel && !agents[defaultAgent].model)
28625
+ agents[defaultAgent] = { ...agents[defaultAgent], model: legacyModel };
28626
+ return { defaultAgent, agents };
28627
+ }
28628
+ async function writeAgentConfig(config) {
28629
+ const existing = await readV1Store();
28630
+ const merged = { ...existing };
28631
+ const agents = {};
28632
+ for (const name of AGENT_NAMES) {
28633
+ const model = config.agents[name].model.trim();
28634
+ const binary = config.agents[name].binary.trim();
28635
+ if (model || binary) agents[name] = { ...model ? { model } : {}, ...binary ? { binary } : {} };
28636
+ }
28637
+ merged["agent"] = config.defaultAgent;
28638
+ const defaultModel = agents[config.defaultAgent]?.model;
28639
+ if (defaultModel) merged["agentModel"] = defaultModel;
28640
+ else delete merged["agentModel"];
28641
+ if (Object.keys(agents).length > 0) merged["agents"] = agents;
28642
+ else delete merged["agents"];
28643
+ await writeV1Store(merged);
28644
+ }
28645
+
28646
+ // packages/experience-design-system-cli/src/tui/settings/agents/agent-status.ts
28647
+ import { execFile as execFile2 } from "node:child_process";
28648
+ import { access as access6, constants } from "node:fs/promises";
28649
+ var VERSION_TIMEOUT_MS = 5e3;
28650
+ var PROMPT_TIMEOUT_MS = 6e4;
28651
+ var TEST_PROMPT = "Reply with the single word: ok";
28652
+ var INSTALL_HINTS = {
28653
+ claude: "npm install -g @anthropic-ai/claude-code",
28654
+ codex: "npm install -g @openai/codex",
28655
+ opencode: "npm install -g opencode-ai",
28656
+ cursor: "install Cursor\u2019s `cursor-agent` command",
28657
+ copilot: "npm install -g @github/copilot"
28658
+ };
28659
+ var LOGIN_HINTS = {
28660
+ claude: "run `claude login`",
28661
+ codex: "set OPENAI_API_KEY, or sign in with a ChatGPT account",
28662
+ opencode: "run `opencode auth`",
28663
+ cursor: "sign in from Cursor",
28664
+ copilot: "run `copilot` and sign in"
28665
+ };
28666
+ function effectiveBinary(name, savedBinary) {
28667
+ return savedBinary.trim() || AGENT_BINARIES[name];
28668
+ }
28669
+ function defaultModelLabel(name) {
28670
+ const model = DEFAULT_MODELS[name];
28671
+ return model && model !== "Auto" ? model : "chosen by the agent";
28672
+ }
28673
+ var fail3 = (step, detail) => ({ step, ok: false, detail });
28674
+ var pass = (step, detail) => ({ step, ok: true, detail });
28675
+ function resolveOnPath(binary) {
28676
+ if (binary.includes("/")) {
28677
+ return access6(binary, constants.X_OK).then(
28678
+ () => binary,
28679
+ () => null
28680
+ );
28681
+ }
28682
+ return new Promise((resolve28) => {
28683
+ execFile2(
28684
+ process.platform === "win32" ? "where" : "which",
28685
+ [binary],
28686
+ (error, stdout) => resolve28(error ? null : stdout.split("\n")[0]?.trim() ?? null)
28687
+ );
28688
+ });
28689
+ }
28690
+ function readVersion(binary) {
28691
+ return new Promise((resolve28) => {
28692
+ execFile2(binary, ["--version"], { timeout: VERSION_TIMEOUT_MS }, (error, stdout) => {
28693
+ const line = stdout.split("\n")[0]?.trim() ?? "";
28694
+ if (!error && line) resolve28(pass("version", line));
28695
+ else resolve28(fail3("version", "runs, but did not report a version"));
28696
+ });
28697
+ });
28698
+ }
28699
+ async function inspect(name, binary) {
28700
+ const target = effectiveBinary(name, binary);
28701
+ const found = await resolveOnPath(target);
28702
+ if (!found) return { checks: [fail3("path", `\`${target}\` was not found or is not executable`)], found: null };
28703
+ const checks = [pass("path", found)];
28704
+ checks.push(await readVersion(found));
28705
+ if (name === "claude") {
28706
+ const auth = await withBinaryEnv(name, found, () => checkAgentAuth(name));
28707
+ checks.push(
28708
+ auth === "ok" ? pass("login", "logged in") : fail3("login", auth === "not-found" ? "binary not found" : `not logged in: ${LOGIN_HINTS.claude}`)
28709
+ );
28710
+ }
28711
+ return { checks, found };
28712
+ }
28713
+ async function inspectAgent(name, binary) {
28714
+ return (await inspect(name, binary)).checks;
28715
+ }
28716
+ async function testAgent(name, binary, model) {
28717
+ const { checks, found } = await inspect(name, binary);
28718
+ if (!found || !checks.every((check) => check.step === "version" || check.ok)) return checks;
28719
+ const started = Date.now();
28720
+ const result = await withBinaryEnv(
28721
+ name,
28722
+ found,
28723
+ () => createLocalCliAgentInvoker().invoke({
28724
+ agent: name,
28725
+ ...model.trim() ? { model: model.trim() } : {},
28726
+ prompt: TEST_PROMPT,
28727
+ timeoutMs: PROMPT_TIMEOUT_MS
28728
+ })
28729
+ );
28730
+ const seconds = ((Date.now() - started) / 1e3).toFixed(1);
28731
+ if (result.timedOut) {
28732
+ return [...checks, { ...fail3("prompt", `no answer within ${PROMPT_TIMEOUT_MS / 1e3}s`), timedOut: true }];
28733
+ }
28734
+ if (result.exitCode !== 0) {
28735
+ const reason = result.stderr.trim().split("\n").pop()?.slice(0, 160) || `exited with code ${result.exitCode}`;
28736
+ return [...checks, fail3("prompt", reason)];
28737
+ }
28738
+ return [...checks, pass("prompt", `answered in ${seconds}s`)];
28739
+ }
28740
+ function statusFromChecks(name, checks, savedBinary) {
28741
+ if (checks.length === 0) return "checking";
28742
+ if (checks.some((check) => check.step === "path" && !check.ok)) {
28743
+ return savedBinary.trim() ? "not-found" : "not-configured";
28744
+ }
28745
+ const prompt = checks.find((check) => check.step === "prompt");
28746
+ if (prompt) {
28747
+ if (prompt.ok) return "ready";
28748
+ return prompt.timedOut ? "timed-out" : "test-failed";
28749
+ }
28750
+ const login = checks.find((check) => check.step === "login");
28751
+ if (login) return login.ok ? "ready" : "not-logged-in";
28752
+ return name === "claude" ? "ready" : "unknown";
28753
+ }
28754
+ function setupHint(name, status) {
28755
+ if (status === "not-configured") return `${INSTALL_HINTS[name]}, or set its command path in settings`;
28756
+ if (status === "not-found") return `${INSTALL_HINTS[name]}, or correct the command path in settings`;
28757
+ if (status === "not-logged-in") return LOGIN_HINTS[name];
28758
+ if (status === "test-failed") return `read the test message; if it is a login problem, ${LOGIN_HINTS[name]}`;
28759
+ if (status === "timed-out") return "it may be slow or waiting for input; run the test again, or try it in a terminal";
28760
+ if (status === "unknown") return "run a full test to confirm it is logged in";
28761
+ return "";
28762
+ }
28763
+ function testOutcome(checks) {
28764
+ const prompt = checks?.find((check) => check.step === "prompt");
28765
+ if (!prompt) return void 0;
28766
+ if (prompt.ok) return { ok: true, text: `Test passed: ${prompt.detail}` };
28767
+ if (prompt.timedOut) return { ok: false, text: `Test timed out: ${prompt.detail}` };
28768
+ return { ok: false, text: `Test failed: ${prompt.detail}` };
28769
+ }
28770
+ var LIST_STATUS = {
28771
+ checking: { symbol: "\u2026", text: "checking", tone: "muted" },
28772
+ ready: { symbol: "\u25CF", text: "ready", tone: "ok" },
28773
+ "not-configured": { symbol: "\u25CB", text: "not installed", tone: "muted" },
28774
+ "not-found": { symbol: "\u25CB", text: "not installed", tone: "bad" },
28775
+ "not-logged-in": { symbol: "\u25D0", text: "not logged in", tone: "bad" },
28776
+ "test-failed": { symbol: "\u2717", text: "test failed", tone: "bad" },
28777
+ "timed-out": { symbol: "\u2717", text: "test timed out", tone: "bad" },
28778
+ unknown: { symbol: "\u25D0", text: "installed, login unknown", tone: "muted" }
28779
+ };
28780
+ function modelLine(name, savedModel) {
28781
+ const model = savedModel.trim();
28782
+ return model ? model : `${defaultModelLabel(name)} (built-in default)`;
28783
+ }
28784
+ function baseRows(name, checks, savedBinary) {
28785
+ const path5 = checks.find((check) => check.step === "path");
28786
+ const version = checks.find((check) => check.step === "version");
28787
+ const hint = setupHint(name, statusFromChecks(name, checks, savedBinary));
28788
+ const setup = hint ? { label: "Setup", value: hint, tone: "muted" } : void 0;
28789
+ if (!path5?.ok) {
28790
+ const saved = savedBinary.trim() !== "";
28791
+ const command = {
28792
+ label: "Command",
28793
+ value: saved ? path5?.detail ?? "not found" : "not configured (not on the PATH)",
28794
+ tone: saved ? "bad" : "muted"
28795
+ };
28796
+ return { command, version: void 0, setup, found: false };
28797
+ }
28798
+ return {
28799
+ command: { label: "Command", value: path5.detail, tone: "ok" },
28800
+ version: {
28801
+ label: "Version",
28802
+ value: version?.ok ? version.detail : "could not be read",
28803
+ tone: version?.ok ? "ok" : "muted"
28804
+ },
28805
+ setup,
28806
+ found: true
28807
+ };
28808
+ }
28809
+ var checking = [{ label: "Command", value: "checking...", tone: "muted" }];
28810
+ function panelRows(name, checks, settings) {
28811
+ if (!checks) return checking;
28812
+ const { command, version, setup, found } = baseRows(name, checks, settings.binary);
28813
+ const model = { label: "Model", value: modelLine(name, settings.model), tone: "muted" };
28814
+ return [command, ...found ? [...version?.tone === "ok" ? [version] : [], model] : [], ...setup ? [setup] : []];
28815
+ }
28816
+ function statusRows(name, checks, savedBinary) {
28817
+ if (!checks) return checking;
28818
+ const { command, version, setup, found } = baseRows(name, checks, savedBinary);
28819
+ if (!found) return [command];
28820
+ const login = checks.find((check) => check.step === "login");
28821
+ const prompt = checks.find((check) => check.step === "prompt");
28822
+ let loginRow;
28823
+ if (login) {
28824
+ loginRow = { label: "Login", value: login.detail, tone: login.ok ? "ok" : "bad" };
28825
+ } else if (prompt) {
28826
+ loginRow = {
28827
+ label: "Login",
28828
+ value: prompt.ok ? "confirmed by the test" : prompt.timedOut ? "unknown (the test timed out)" : "see the test result",
28829
+ tone: prompt.ok ? "ok" : prompt.timedOut ? "muted" : "bad"
28830
+ };
28831
+ } else {
28832
+ loginRow = { label: "Login", value: "not checked (use Run test)", tone: "muted" };
28833
+ }
28834
+ const testRow = prompt ? [{ label: "Test", value: prompt.detail, tone: prompt.ok ? "ok" : "bad" }] : [];
28835
+ return [command, ...version ? [version] : [], loginRow, ...testRow, ...setup ? [setup] : []];
28836
+ }
28837
+ async function withBinaryEnv(name, binary, run) {
28838
+ const key = `EDS_AGENT_BINARY_${name.toUpperCase()}`;
28839
+ const previous = process.env[key];
28840
+ process.env[key] = binary;
28841
+ try {
28842
+ return await run();
28843
+ } finally {
28844
+ if (previous === void 0) delete process.env[key];
28845
+ else process.env[key] = previous;
28846
+ }
28847
+ }
28848
+
28849
+ // packages/experience-design-system-cli/src/tui/settings/agents/AgentDetail.tsx
28850
+ import { useEffect as useEffect22, useState as useState30 } from "react";
28851
+ import { Box as Box45, Text as Text48 } from "ink";
28852
+
28853
+ // packages/experience-design-system-cli/src/tui/settings/shared/FieldForm.tsx
28854
+ import { useState as useState29 } from "react";
28855
+ import { Box as Box44, Text as Text46, useInput as useInput11 } from "ink";
28856
+ import TextInput4 from "ink-text-input";
28857
+ import { Fragment as Fragment17, jsx as jsx55, jsxs as jsxs45 } from "react/jsx-runtime";
28858
+ function FieldForm({
28859
+ title,
28860
+ subtitle,
28861
+ fields: fields2,
28862
+ values,
28863
+ onChange,
28864
+ onSave,
28865
+ onQuit,
28866
+ actions = [],
28867
+ notice,
28868
+ busy = false,
28869
+ children
28870
+ }) {
28871
+ const [active, setActive] = useState29(0);
28872
+ const [editing, setEditing] = useState29(false);
28873
+ const [valueBeforeEdit, setValueBeforeEdit] = useState29("");
28874
+ const rowCount = fields2.length + actions.length;
28875
+ const labelWidth = Math.max(
28876
+ ...fields2.map((field) => field.label.length),
28877
+ ...actions.map((action) => action.label.length)
28878
+ );
28879
+ const currentField = active < fields2.length ? fields2[active] : void 0;
28880
+ const currentAction = currentField ? void 0 : actions[active - fields2.length];
28881
+ useInput11((input, key) => {
28882
+ if (busy) return;
28883
+ if (editing) {
28884
+ if (key.escape && currentField) {
28885
+ onChange(currentField.key, valueBeforeEdit);
28886
+ setEditing(false);
28887
+ }
28888
+ return;
28889
+ }
28890
+ if (key.escape || input === "q") {
28891
+ onQuit();
28892
+ return;
28893
+ }
28894
+ if (input === "s") {
28895
+ onSave();
28896
+ return;
28897
+ }
28898
+ if (input === "c" && currentField) {
28899
+ onChange(currentField.key, "");
28900
+ return;
28901
+ }
28902
+ if (key.tab || key.downArrow) {
28903
+ setActive((i) => (i + 1) % rowCount);
28904
+ return;
28905
+ }
28906
+ if (key.upArrow) {
28907
+ setActive((i) => (i - 1 + rowCount) % rowCount);
28908
+ return;
28909
+ }
28910
+ if (key.return) {
28911
+ if (currentField) {
28912
+ setValueBeforeEdit(values[currentField.key]);
28913
+ setEditing(true);
28914
+ } else {
28915
+ currentAction?.onRun();
28916
+ }
28917
+ }
28918
+ });
28919
+ const pointer = (isActive) => /* @__PURE__ */ jsx55(Text46, { color: isActive ? PALETTE.accent : void 0, children: isActive ? "\u276F" : " " });
28920
+ return /* @__PURE__ */ jsxs45(Box44, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
28921
+ /* @__PURE__ */ jsx55(Text46, { bold: true, children: title }),
28922
+ subtitle && /* @__PURE__ */ jsx55(Text46, { color: PALETTE.muted, children: subtitle }),
28923
+ /* @__PURE__ */ jsx55(Text46, { children: " " }),
28924
+ /* @__PURE__ */ jsxs45(Box44, { flexDirection: "column", children: [
28925
+ fields2.map((field, index) => {
28926
+ const isActive = index === active;
28927
+ const value = values[field.key];
28928
+ const display = field.masked ? "\u2022".repeat(value.length) : value;
28929
+ return /* @__PURE__ */ jsxs45(Box44, { gap: 1, children: [
28930
+ pointer(isActive),
28931
+ /* @__PURE__ */ jsx55(Box44, { width: labelWidth, flexShrink: 0, children: /* @__PURE__ */ jsx55(Text46, { bold: isActive, color: isActive ? PALETTE.accent : PALETTE.muted, children: field.label }) }),
28932
+ isActive && editing ? /* @__PURE__ */ jsx55(
28933
+ TextInput4,
28934
+ {
28935
+ value,
28936
+ onChange: (next) => onChange(field.key, next),
28937
+ onSubmit: () => setEditing(false),
28938
+ mask: field.masked ? "\u2022" : void 0
28939
+ }
28940
+ ) : /* @__PURE__ */ jsx55(Text46, { bold: !!display, children: display || (field.hint ? "" : /* @__PURE__ */ jsx55(Text46, { color: PALETTE.muted, children: "(empty)" })) }),
28941
+ field.hint && /* @__PURE__ */ jsx55(Text46, { color: PALETTE.muted, children: field.hint })
28942
+ ] }, field.key);
28943
+ }),
28944
+ actions.map((action, index) => {
28945
+ const isActive = fields2.length + index === active;
28946
+ return /* @__PURE__ */ jsxs45(Box44, { gap: 1, children: [
28947
+ pointer(isActive),
28948
+ /* @__PURE__ */ jsx55(Box44, { width: labelWidth, flexShrink: 0, children: /* @__PURE__ */ jsx55(Text46, { bold: isActive, color: isActive ? PALETTE.accent : PALETTE.muted, children: action.label }) }),
28949
+ /* @__PURE__ */ jsx55(Text46, { color: action.running ? PALETTE.accent : PALETTE.muted, children: action.running ? action.runningText ?? "running..." : action.description })
28950
+ ] }, action.label);
28951
+ })
28952
+ ] }),
28953
+ notice && /* @__PURE__ */ jsxs45(Fragment17, { children: [
28954
+ /* @__PURE__ */ jsx55(Text46, { children: " " }),
28955
+ /* @__PURE__ */ jsxs45(Text46, { color: notice.kind === "success" ? PALETTE.success : PALETTE.error, children: [
28956
+ notice.kind === "success" ? "\u2713" : "\u2717",
28957
+ " ",
28958
+ notice.text
28959
+ ] })
28960
+ ] }),
28961
+ children,
28962
+ /* @__PURE__ */ jsx55(Text46, { children: " " }),
28963
+ /* @__PURE__ */ jsx55(
28964
+ ControlHints,
28965
+ {
28966
+ hints: editing ? [
28967
+ { keys: "type", label: "edit" },
28968
+ { keys: "\u2190/\u2192", label: "move cursor" },
28969
+ { keys: "\u23CE", label: "done" },
28970
+ { keys: "Esc", label: "cancel edit" }
28971
+ ] : [
28972
+ { keys: "\u2191/\u2193", label: "move" },
28973
+ { keys: "\u23CE", label: currentAction ? currentAction.hint : "edit" },
28974
+ ...currentField ? [{ keys: "c", label: "clear" }] : [],
28975
+ { keys: "s", label: "save" },
28976
+ { keys: "Esc/q", label: "back without saving" }
28977
+ ]
28978
+ }
28979
+ )
28980
+ ] });
28981
+ }
28982
+
28983
+ // packages/experience-design-system-cli/src/tui/settings/agents/AgentStatusBadge.tsx
28984
+ import { Text as Text47 } from "ink";
28985
+ import { jsx as jsx56 } from "react/jsx-runtime";
28986
+ var TONE_COLOR = {
28987
+ ok: PALETTE.success,
28988
+ bad: PALETTE.error,
28989
+ muted: PALETTE.muted
28990
+ };
28991
+ function AgentStatusBadge({
28992
+ name,
28993
+ checks,
28994
+ binary
28995
+ }) {
28996
+ const { symbol, text, tone } = LIST_STATUS[checks ? statusFromChecks(name, checks, binary) : "checking"];
28997
+ return /* @__PURE__ */ jsx56(Text47, { color: TONE_COLOR[tone], children: `${symbol} ${text}` });
28998
+ }
28999
+
29000
+ // packages/experience-design-system-cli/src/tui/settings/agents/apply-binary-overrides.ts
29001
+ var shellValues = /* @__PURE__ */ new Map();
29002
+ function applyBinaryOverrides(config) {
29003
+ for (const name of AGENT_NAMES) {
29004
+ const key = `EDS_AGENT_BINARY_${name.toUpperCase()}`;
29005
+ const binary = config.agents[name].binary.trim();
29006
+ if (binary) {
29007
+ if (!shellValues.has(key)) shellValues.set(key, process.env[key]);
29008
+ process.env[key] = binary;
29009
+ } else if (shellValues.has(key)) {
29010
+ const shellValue = shellValues.get(key);
29011
+ if (shellValue === void 0) delete process.env[key];
29012
+ else process.env[key] = shellValue;
29013
+ shellValues.delete(key);
29014
+ }
29015
+ }
29016
+ }
29017
+
29018
+ // packages/experience-design-system-cli/src/tui/settings/agents/AgentDetail.tsx
29019
+ import { jsx as jsx57, jsxs as jsxs46 } from "react/jsx-runtime";
29020
+ var fields = (name) => [
29021
+ { key: "binary", label: "Command path", hint: `(empty: \`${AGENT_BINARIES[name]}\` from the PATH)` },
29022
+ { key: "model", label: "Model", hint: `(empty: ${defaultModelLabel(name)})` }
29023
+ ];
29024
+ var LABEL_WIDTH = "Command path".length;
29025
+ var LABEL_GAP = 2;
29026
+ var POINTER_WIDTH = 2;
29027
+ function Row2({ label, children }) {
29028
+ return /* @__PURE__ */ jsxs46(Box45, { children: [
29029
+ /* @__PURE__ */ jsx57(Box45, { width: POINTER_WIDTH + LABEL_WIDTH + LABEL_GAP, flexShrink: 0, children: /* @__PURE__ */ jsx57(Text48, { color: PALETTE.muted, children: label }) }),
29030
+ children
29031
+ ] });
29032
+ }
29033
+ function StatusHeading() {
29034
+ return /* @__PURE__ */ jsxs46(Box45, { gap: 1, children: [
29035
+ /* @__PURE__ */ jsx57(Text48, { bold: true, color: PALETTE.muted, children: "STATUS" }),
29036
+ /* @__PURE__ */ jsx57(Text48, { color: PALETTE.muted, children: "\xB7 read only" })
29037
+ ] });
29038
+ }
29039
+ function AgentDetail({
29040
+ name,
29041
+ config,
29042
+ setConfig,
29043
+ onBack
29044
+ }) {
29045
+ const settings = config.agents[name];
29046
+ const [saving, setSaving] = useState30(false);
29047
+ const [testing, setTesting] = useState30(false);
29048
+ const [notice, setNotice] = useState30(null);
29049
+ const [checks, setChecks] = useState30(void 0);
29050
+ useEffect22(() => {
29051
+ let active = true;
29052
+ setChecks(void 0);
29053
+ void inspectAgent(name, settings.binary).then((result) => active && setChecks(result));
29054
+ return () => {
29055
+ active = false;
29056
+ };
29057
+ }, [name, settings.binary]);
29058
+ const save = () => {
29059
+ setSaving(true);
29060
+ setNotice(null);
29061
+ writeAgentConfig(config).then(() => {
29062
+ applyBinaryOverrides(config);
29063
+ setNotice({ kind: "success", text: `Saved: ${AGENT_LABELS[name]} settings are written to config.json` });
29064
+ }).catch(
29065
+ (err) => setNotice({ kind: "error", text: `Not saved: ${err instanceof Error ? err.message : String(err)}` })
29066
+ ).finally(() => setSaving(false));
29067
+ };
29068
+ const runTest = () => {
29069
+ setTesting(true);
29070
+ setNotice(null);
29071
+ testAgent(name, settings.binary, settings.model).then((result) => {
29072
+ setChecks(result);
29073
+ const outcome = testOutcome(result);
29074
+ setNotice(
29075
+ outcome ? { kind: outcome.ok ? "success" : "error", text: outcome.text } : { kind: "error", text: "Test not run: the agent could not be started (see Status)" }
29076
+ );
29077
+ }).catch(
29078
+ (err) => setNotice({ kind: "error", text: `Test could not run: ${err instanceof Error ? err.message : String(err)}` })
29079
+ ).finally(() => setTesting(false));
29080
+ };
29081
+ const action = {
29082
+ label: "Run test",
29083
+ description: "sends one small prompt (uses a few tokens)",
29084
+ running: testing,
29085
+ hint: "run test",
29086
+ onRun: runTest
29087
+ };
29088
+ return /* @__PURE__ */ jsx57(
29089
+ FieldForm,
29090
+ {
29091
+ title: AGENT_LABELS[name],
29092
+ subtitle: config.defaultAgent === name ? "This is the default agent." : `Runs the \`${AGENT_BINARIES[name]}\` command.`,
29093
+ fields: fields(name),
29094
+ values: { binary: settings.binary, model: settings.model },
29095
+ onChange: (key, value) => {
29096
+ setConfig({ ...config, agents: { ...config.agents, [name]: { ...settings, [key]: value } } });
29097
+ setNotice(null);
29098
+ },
29099
+ onSave: save,
29100
+ onQuit: onBack,
29101
+ actions: [action],
29102
+ notice: testing ? null : notice,
29103
+ busy: saving || testing,
29104
+ children: /* @__PURE__ */ jsxs46(Box45, { flexDirection: "column", marginTop: 1, children: [
29105
+ /* @__PURE__ */ jsx57(StatusHeading, {}),
29106
+ statusRows(name, checks, settings.binary).map((row) => /* @__PURE__ */ jsx57(Row2, { label: row.label, children: /* @__PURE__ */ jsx57(Text48, { color: TONE_COLOR[row.tone], children: row.value }) }, row.label))
29107
+ ] })
29108
+ }
29109
+ );
29110
+ }
29111
+
29112
+ // packages/experience-design-system-cli/src/tui/settings/agents/AgentsScreen.tsx
29113
+ import { Fragment as Fragment18, jsx as jsx58, jsxs as jsxs47 } from "react/jsx-runtime";
29114
+ var NAME_WIDTH = 16;
29115
+ var PANEL_LABEL_WIDTH = "Command".length;
29116
+ function AgentsScreen({ onDone }) {
29117
+ const [config, setConfig] = useState31(null);
29118
+ const [focus, setFocus] = useState31(0);
29119
+ const [open, setOpen] = useState31(null);
29120
+ const [notice, setNotice] = useState31(null);
29121
+ const [saving, setSaving] = useState31(false);
29122
+ const [checks, setChecks] = useState31({});
29123
+ const inspectAll = (loaded) => {
29124
+ for (const name of AGENT_NAMES) {
29125
+ void inspectAgent(name, loaded.agents[name].binary).then(
29126
+ (result) => setChecks((previous) => ({ ...previous, [name]: result }))
29127
+ );
29128
+ }
29129
+ };
29130
+ useEffect23(() => {
29131
+ void readAgentConfig().then((loaded) => {
29132
+ setConfig(loaded);
29133
+ inspectAll(loaded);
29134
+ startDebugRun({
29135
+ flow: "settings/agents",
29136
+ step: "01-agents",
29137
+ menuOption: "Configuration > Agents",
29138
+ inputs: { default_agent: loaded.defaultAgent }
29139
+ });
29140
+ });
29141
+ }, []);
29142
+ const makeDefault = (name) => {
29143
+ if (!config || saving) return;
29144
+ if (name === config.defaultAgent) {
29145
+ setNotice({ kind: "success", text: `${AGENT_LABELS[name]} is already the default agent` });
29146
+ return;
29147
+ }
29148
+ setSaving(true);
29149
+ setNotice(null);
29150
+ writeAgentConfig({ ...config, defaultAgent: name }).then(() => {
29151
+ setConfig((current) => current ? { ...current, defaultAgent: name } : current);
29152
+ setNotice({ kind: "success", text: `Default agent is now ${AGENT_LABELS[name]}` });
29153
+ }).catch(
29154
+ (err) => setNotice({
29155
+ kind: "error",
29156
+ text: `Default agent not changed: ${err instanceof Error ? err.message : String(err)}`
29157
+ })
29158
+ ).finally(() => setSaving(false));
29159
+ };
29160
+ useInput12((input, key) => {
29161
+ if (!config || open || saving) return;
29162
+ const focused = AGENT_NAMES[focus];
29163
+ if (key.upArrow || key.downArrow || key.tab) setNotice(null);
29164
+ if (key.upArrow) {
29165
+ setFocus((i) => (i - 1 + AGENT_NAMES.length) % AGENT_NAMES.length);
29166
+ return;
29167
+ }
29168
+ if (key.downArrow || key.tab) {
29169
+ setFocus((i) => (i + 1) % AGENT_NAMES.length);
29170
+ return;
29171
+ }
29172
+ if (key.return) {
29173
+ makeDefault(focused);
29174
+ return;
29175
+ }
29176
+ if (key.rightArrow) {
29177
+ setNotice(null);
29178
+ setOpen(focused);
29179
+ return;
29180
+ }
29181
+ if (key.escape || input === "q") {
29182
+ void finishDebugRun({ outputs: { default_agent: config.defaultAgent }, status: "success", exitMethod: "saved" });
29183
+ onDone();
29184
+ }
29185
+ });
29186
+ if (!config) {
29187
+ return /* @__PURE__ */ jsxs47(Box46, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
29188
+ /* @__PURE__ */ jsx58(Text49, { bold: true, children: "Agents" }),
29189
+ /* @__PURE__ */ jsx58(Text49, { children: " " }),
29190
+ /* @__PURE__ */ jsx58(Text49, { color: PALETTE.accent, children: "Loading..." })
29191
+ ] });
29192
+ }
29193
+ if (open) {
29194
+ return /* @__PURE__ */ jsx58(
29195
+ AgentDetail,
29196
+ {
29197
+ name: open,
29198
+ config,
29199
+ setConfig,
29200
+ onBack: () => {
29201
+ setOpen(null);
29202
+ void readAgentConfig().then((saved) => {
29203
+ setConfig(saved);
29204
+ inspectAll(saved);
29205
+ });
29206
+ }
29207
+ }
29208
+ );
29209
+ }
29210
+ const focusedAgent = AGENT_NAMES[focus];
29211
+ return /* @__PURE__ */ jsxs47(Box46, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
29212
+ /* @__PURE__ */ jsx58(Text49, { bold: true, children: "Agents" }),
29213
+ /* @__PURE__ */ jsx58(Text49, { color: PALETTE.muted, children: "The coding agent the CLI runs, and what was found for each one." }),
29214
+ /* @__PURE__ */ jsx58(Text49, { children: " " }),
29215
+ /* @__PURE__ */ jsxs47(Box46, { gap: 1, children: [
29216
+ /* @__PURE__ */ jsx58(Text49, { color: PALETTE.muted, children: "Default agent" }),
29217
+ /* @__PURE__ */ jsx58(Text49, { bold: true, children: AGENT_LABELS[config.defaultAgent] }),
29218
+ saving && /* @__PURE__ */ jsx58(Text49, { color: PALETTE.accent, children: "\u2026 saving" })
29219
+ ] }),
29220
+ /* @__PURE__ */ jsxs47(Box46, { marginTop: 1, gap: 1, children: [
29221
+ /* @__PURE__ */ jsx58(Text49, { children: " " }),
29222
+ /* @__PURE__ */ jsx58(Text49, { children: " " }),
29223
+ /* @__PURE__ */ jsx58(Box46, { width: NAME_WIDTH, flexShrink: 0, children: /* @__PURE__ */ jsx58(Text49, { color: PALETTE.muted, children: "AGENT" }) }),
29224
+ /* @__PURE__ */ jsx58(Text49, { color: PALETTE.muted, children: "STATUS" })
29225
+ ] }),
29226
+ AGENT_NAMES.map((name) => {
29227
+ const isFocused = focusedAgent === name;
29228
+ return /* @__PURE__ */ jsxs47(Box46, { gap: 1, children: [
29229
+ /* @__PURE__ */ jsx58(Text49, { color: isFocused ? PALETTE.accent : void 0, children: isFocused ? "\u276F" : " " }),
29230
+ /* @__PURE__ */ jsx58(Text49, { color: PALETTE.success, children: name === config.defaultAgent ? "\u2605" : " " }),
29231
+ /* @__PURE__ */ jsx58(Box46, { width: NAME_WIDTH, flexShrink: 0, children: /* @__PURE__ */ jsx58(Text49, { bold: isFocused, color: isFocused ? PALETTE.accent : void 0, children: AGENT_LABELS[name] }) }),
29232
+ /* @__PURE__ */ jsx58(AgentStatusBadge, { name, checks: checks[name], binary: config.agents[name].binary })
29233
+ ] }, name);
29234
+ }),
29235
+ /* @__PURE__ */ jsxs47(Box46, { flexDirection: "column", marginTop: 1, children: [
29236
+ /* @__PURE__ */ jsx58(Text49, { color: PALETTE.muted, children: `\u2500 ${AGENT_LABELS[focusedAgent]} ${"\u2500".repeat(30)}` }),
29237
+ panelRows(focusedAgent, checks[focusedAgent], config.agents[focusedAgent]).map((row) => /* @__PURE__ */ jsxs47(Box46, { gap: 1, paddingLeft: 1, children: [
29238
+ /* @__PURE__ */ jsx58(Box46, { width: PANEL_LABEL_WIDTH, flexShrink: 0, children: /* @__PURE__ */ jsx58(Text49, { color: PALETTE.muted, children: row.label }) }),
29239
+ /* @__PURE__ */ jsx58(Text49, { color: TONE_COLOR[row.tone], children: row.value })
29240
+ ] }, row.label))
29241
+ ] }),
29242
+ notice && /* @__PURE__ */ jsxs47(Fragment18, { children: [
29243
+ /* @__PURE__ */ jsx58(Text49, { children: " " }),
29244
+ /* @__PURE__ */ jsxs47(Text49, { bold: true, color: notice.kind === "success" ? PALETTE.success : PALETTE.error, children: [
29245
+ notice.kind === "success" ? "\u2713" : "\u2717",
29246
+ " ",
29247
+ notice.text
29248
+ ] })
29249
+ ] }),
29250
+ /* @__PURE__ */ jsx58(Text49, { children: " " }),
29251
+ /* @__PURE__ */ jsx58(
29252
+ ControlHints,
29253
+ {
29254
+ hints: [
29255
+ { keys: "\u2191/\u2193", label: "move" },
29256
+ { keys: "\u23CE", label: "make default" },
29257
+ { keys: "\u2192", label: "settings and test" },
29258
+ { keys: "Esc/q", label: "back" }
29259
+ ]
29260
+ }
29261
+ )
29262
+ ] });
29263
+ }
29264
+
29265
+ // packages/experience-design-system-cli/src/tui/settings/contentful-configuration/ProjectConfigScreen.tsx
29266
+ import { useEffect as useEffect24, useState as useState32 } from "react";
29267
+ import { Box as Box47, Text as Text50 } from "ink";
29268
+ init_debug_store();
29269
+
28546
29270
  // packages/experience-design-system-cli/src/tui/settings/contentful-configuration/config-store.ts
28547
29271
  async function readCredentials() {
28548
29272
  const store = await readV1Store();
@@ -28568,17 +29292,16 @@ async function writeCredentials(config) {
28568
29292
  await writeV1Store(merged);
28569
29293
  }
28570
29294
 
28571
- // packages/experience-design-system-cli/src/tui/settings/contentful-configuration/ContentfulConfigScreen.tsx
28572
- init_debug_store();
28573
- import { Fragment as Fragment17, jsx as jsx55, jsxs as jsxs45 } from "react/jsx-runtime";
28574
- var FIELD_ORDER = [
28575
- "spaceId",
28576
- "environmentId",
28577
- "cmaToken",
28578
- "host",
28579
- "defaultComponentDir",
28580
- "defaultTokenFile",
28581
- "contentfulBaseDir"
29295
+ // packages/experience-design-system-cli/src/tui/settings/contentful-configuration/ProjectConfigScreen.tsx
29296
+ import { jsx as jsx59, jsxs as jsxs48 } from "react/jsx-runtime";
29297
+ var FIELDS2 = [
29298
+ { key: "spaceId", label: "Space ID" },
29299
+ { key: "environmentId", label: "Environment ID" },
29300
+ { key: "cmaToken", label: "CMA Token", masked: true },
29301
+ { key: "host", label: "API Host" },
29302
+ { key: "defaultComponentDir", label: "Default component directory" },
29303
+ { key: "defaultTokenFile", label: "Default token file" },
29304
+ { key: "contentfulBaseDir", label: "Root Project Directory", hint: "(where .contentful goes)" }
28582
29305
  ];
28583
29306
  function debugFields(config) {
28584
29307
  return {
@@ -28591,156 +29314,114 @@ function debugFields(config) {
28591
29314
  contentful_base_dir: config?.contentfulBaseDir ?? ""
28592
29315
  };
28593
29316
  }
28594
- var FIELD_LABELS = {
28595
- spaceId: "Space ID",
28596
- environmentId: "Environment ID",
28597
- cmaToken: "CMA Token",
28598
- host: "API Host",
28599
- defaultComponentDir: "Default component directory",
28600
- defaultTokenFile: "Default token file",
28601
- contentfulBaseDir: "Root Project Directory"
28602
- };
28603
- var FIELD_HINTS = {
28604
- contentfulBaseDir: "(where .contentful goes)"
28605
- };
28606
- var LABEL_WIDTH = Math.max(...Object.values(FIELD_LABELS).map((label) => label.length));
28607
- function ConfigurationScreen({ onDone }) {
28608
- const [stage, setStage] = useState29("loading");
28609
- const [config, setConfig] = useState29(null);
28610
- const [activeField, setActiveField] = useState29("spaceId");
28611
- const [notice, setNotice] = useState29(null);
28612
- const [lastSaved, setLastSaved] = useState29(null);
28613
- const [editing, setEditing] = useState29(false);
28614
- const [valueBeforeEdit, setValueBeforeEdit] = useState29("");
28615
- useEffect22(() => {
28616
- readCredentials().then((cfg) => {
29317
+ var valuesOf = (config) => Object.fromEntries(FIELDS2.map(({ key }) => [key, config[key] || ""]));
29318
+ function ProjectConfigScreen({ onDone }) {
29319
+ const [config, setConfig] = useState32(null);
29320
+ const [saving, setSaving] = useState32(false);
29321
+ const [notice, setNotice] = useState32(null);
29322
+ const [lastSaved, setLastSaved] = useState32(null);
29323
+ useEffect24(() => {
29324
+ void readCredentials().then((cfg) => {
28617
29325
  setConfig(cfg);
28618
- setStage("form");
28619
29326
  startDebugRun({
28620
29327
  flow: "settings/contentful-configuration",
28621
29328
  step: "01-configuration",
28622
- menuOption: "Configuration",
29329
+ menuOption: "Configuration > Project",
28623
29330
  inputs: debugFields(cfg)
28624
29331
  });
28625
29332
  });
28626
29333
  }, []);
28627
- function fieldValue(field) {
28628
- if (!config) return "";
28629
- return config[field] || "";
28630
- }
28631
- function setFieldValue(field, value) {
28632
- if (!config) return;
28633
- setConfig({ ...config, [field]: value });
28634
- setNotice(null);
29334
+ if (!config) {
29335
+ return /* @__PURE__ */ jsxs48(Box47, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
29336
+ /* @__PURE__ */ jsx59(Text50, { bold: true, children: "Project" }),
29337
+ /* @__PURE__ */ jsx59(Text50, { children: " " }),
29338
+ /* @__PURE__ */ jsx59(Text50, { color: PALETTE.accent, children: "Loading..." })
29339
+ ] });
28635
29340
  }
28636
- function handleSave() {
28637
- if (!config) return;
28638
- setStage("saving");
29341
+ const save = () => {
29342
+ setSaving(true);
28639
29343
  setNotice(null);
28640
29344
  writeCredentials(config).then(() => {
28641
29345
  setLastSaved(config);
28642
29346
  if (config.contentfulBaseDir) void startDebugSessionIn(config.contentfulBaseDir, { replace: true });
28643
- setNotice({ kind: "success", text: "Configuration saved" });
28644
- setStage("form");
29347
+ setNotice({ kind: "success", text: "Project settings saved" });
28645
29348
  }).catch((err) => {
28646
29349
  setNotice({ kind: "error", text: err instanceof Error ? err.message : "Failed to save" });
28647
- setStage("form");
28648
- });
28649
- }
28650
- function quit() {
29350
+ }).finally(() => setSaving(false));
29351
+ };
29352
+ const quit = () => {
28651
29353
  void finishDebugRun(
28652
29354
  lastSaved ? { outputs: debugFields(lastSaved), status: "success", exitMethod: "saved" } : { outputs: {}, status: "success", exitMethod: "discarded" }
28653
29355
  );
28654
29356
  onDone();
28655
- }
28656
- useInput11((input, key) => {
28657
- if (stage === "loading" || stage === "saving") return;
28658
- if (editing) {
28659
- if (key.escape) {
28660
- setFieldValue(activeField, valueBeforeEdit);
28661
- setEditing(false);
28662
- }
28663
- return;
28664
- }
28665
- if (key.escape || input === "q") {
28666
- quit();
28667
- return;
28668
- }
28669
- if (input === "s") {
28670
- handleSave();
28671
- return;
28672
- }
28673
- if (input === "c") {
28674
- setFieldValue(activeField, "");
28675
- return;
29357
+ };
29358
+ return /* @__PURE__ */ jsx59(
29359
+ FieldForm,
29360
+ {
29361
+ title: "Project",
29362
+ subtitle: "The Contentful space and where the CLI keeps its files.",
29363
+ fields: FIELDS2,
29364
+ values: valuesOf(config),
29365
+ onChange: (key, value) => {
29366
+ setConfig({ ...config, [key]: value });
29367
+ setNotice(null);
29368
+ },
29369
+ onSave: save,
29370
+ onQuit: quit,
29371
+ notice,
29372
+ busy: saving
28676
29373
  }
28677
- if (key.tab || key.downArrow) {
28678
- const idx = FIELD_ORDER.indexOf(activeField);
28679
- setActiveField(FIELD_ORDER[(idx + 1) % FIELD_ORDER.length]);
29374
+ );
29375
+ }
29376
+
29377
+ // packages/experience-design-system-cli/src/tui/settings/contentful-configuration/ContentfulConfigScreen.tsx
29378
+ import { jsx as jsx60, jsxs as jsxs49 } from "react/jsx-runtime";
29379
+ var SECTIONS = [
29380
+ {
29381
+ id: "project",
29382
+ label: "Project",
29383
+ description: "Contentful space, credentials, defaults and where .contentful goes"
29384
+ },
29385
+ { id: "agents", label: "Agents", description: "Which coding agent the CLI uses, and each agent\u2019s settings" }
29386
+ ];
29387
+ function ConfigurationScreen({ onDone }) {
29388
+ const [focus, setFocus] = useState33(0);
29389
+ const [open, setOpen] = useState33(null);
29390
+ const close = () => setOpen(null);
29391
+ useInput13((input, key) => {
29392
+ if (open) return;
29393
+ if (key.upArrow) {
29394
+ setFocus((i) => (i - 1 + SECTIONS.length) % SECTIONS.length);
28680
29395
  return;
28681
29396
  }
28682
- if (key.upArrow) {
28683
- const idx = FIELD_ORDER.indexOf(activeField);
28684
- setActiveField(FIELD_ORDER[(idx - 1 + FIELD_ORDER.length) % FIELD_ORDER.length]);
29397
+ if (key.downArrow || key.tab) {
29398
+ setFocus((i) => (i + 1) % SECTIONS.length);
28685
29399
  return;
28686
29400
  }
28687
29401
  if (key.return) {
28688
- setValueBeforeEdit(fieldValue(activeField));
28689
- setEditing(true);
29402
+ setOpen(SECTIONS[focus].id);
29403
+ return;
28690
29404
  }
29405
+ if (key.escape || input === "q") onDone();
28691
29406
  });
28692
- if (stage === "loading") {
28693
- return /* @__PURE__ */ jsxs45(Box44, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
28694
- /* @__PURE__ */ jsx55(Text46, { bold: true, children: "Configuration" }),
28695
- /* @__PURE__ */ jsx55(Text46, { children: " " }),
28696
- /* @__PURE__ */ jsx55(Text46, { color: PALETTE.accent, children: "Loading..." })
28697
- ] });
28698
- }
28699
- return /* @__PURE__ */ jsxs45(Box44, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
28700
- /* @__PURE__ */ jsx55(Text46, { bold: true, children: "Configuration" }),
28701
- /* @__PURE__ */ jsx55(Text46, { children: " " }),
28702
- /* @__PURE__ */ jsx55(Box44, { flexDirection: "column", children: FIELD_ORDER.map((field) => {
28703
- const isActive = activeField === field;
28704
- const value = fieldValue(field);
28705
- const display = field === "cmaToken" ? "\u2022".repeat(value.length) : value;
28706
- return /* @__PURE__ */ jsxs45(Box44, { gap: 1, children: [
28707
- /* @__PURE__ */ jsx55(Text46, { color: isActive ? PALETTE.accent : void 0, children: isActive ? "\u276F" : " " }),
28708
- /* @__PURE__ */ jsx55(Box44, { width: LABEL_WIDTH, flexShrink: 0, children: /* @__PURE__ */ jsx55(Text46, { bold: isActive, color: isActive ? PALETTE.accent : PALETTE.muted, children: FIELD_LABELS[field] }) }),
28709
- isActive && editing ? /* @__PURE__ */ jsx55(
28710
- TextInput4,
28711
- {
28712
- value,
28713
- onChange: (next) => setFieldValue(field, next),
28714
- onSubmit: () => setEditing(false),
28715
- mask: field === "cmaToken" ? "\u2022" : void 0
28716
- }
28717
- ) : /* @__PURE__ */ jsx55(Text46, { bold: !!display, children: display || (FIELD_HINTS[field] ? "" : /* @__PURE__ */ jsx55(Text46, { color: PALETTE.muted, children: "(empty)" })) }),
28718
- FIELD_HINTS[field] && /* @__PURE__ */ jsx55(Text46, { color: PALETTE.muted, children: FIELD_HINTS[field] })
28719
- ] }, field);
28720
- }) }),
28721
- notice && /* @__PURE__ */ jsxs45(Fragment17, { children: [
28722
- /* @__PURE__ */ jsx55(Text46, { children: " " }),
28723
- /* @__PURE__ */ jsxs45(Text46, { color: notice.kind === "success" ? PALETTE.success : PALETTE.error, children: [
28724
- notice.kind === "success" ? "\u2713" : "\u2717",
28725
- " ",
28726
- notice.text
28727
- ] })
28728
- ] }),
28729
- /* @__PURE__ */ jsx55(Text46, { children: " " }),
28730
- /* @__PURE__ */ jsx55(
29407
+ if (open === "project") return /* @__PURE__ */ jsx60(ProjectConfigScreen, { onDone: close });
29408
+ if (open === "agents") return /* @__PURE__ */ jsx60(AgentsScreen, { onDone: close });
29409
+ return /* @__PURE__ */ jsxs49(Box48, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
29410
+ /* @__PURE__ */ jsx60(Text51, { bold: true, children: "Configuration" }),
29411
+ /* @__PURE__ */ jsx60(Text51, { children: " " }),
29412
+ SECTIONS.map((section, index) => /* @__PURE__ */ jsxs49(Box48, { gap: 1, children: [
29413
+ /* @__PURE__ */ jsx60(Text51, { color: index === focus ? PALETTE.accent : void 0, children: index === focus ? "\u276F" : " " }),
29414
+ /* @__PURE__ */ jsx60(Box48, { width: 9, flexShrink: 0, children: /* @__PURE__ */ jsx60(Text51, { bold: index === focus, color: index === focus ? PALETTE.accent : void 0, children: section.label }) }),
29415
+ /* @__PURE__ */ jsx60(Text51, { color: PALETTE.muted, children: section.description })
29416
+ ] }, section.id)),
29417
+ /* @__PURE__ */ jsx60(Text51, { children: " " }),
29418
+ /* @__PURE__ */ jsx60(
28731
29419
  ControlHints,
28732
29420
  {
28733
- hints: editing ? [
28734
- { keys: "type", label: "edit" },
28735
- { keys: "\u2190/\u2192", label: "move cursor" },
28736
- { keys: "\u23CE", label: "done" },
28737
- { keys: "Esc", label: "cancel edit" }
28738
- ] : [
29421
+ hints: [
28739
29422
  { keys: "\u2191/\u2193", label: "move" },
28740
- { keys: "\u23CE", label: "edit" },
28741
- { keys: "c", label: "clear" },
28742
- { keys: "s", label: "save" },
28743
- { keys: "Esc/q", label: "quit without saving" }
29423
+ { keys: "\u23CE", label: "open" },
29424
+ { keys: "Esc/q", label: "back" }
28744
29425
  ]
28745
29426
  }
28746
29427
  )
@@ -28748,8 +29429,8 @@ function ConfigurationScreen({ onDone }) {
28748
29429
  }
28749
29430
 
28750
29431
  // packages/experience-design-system-cli/src/tui/settings/opt-in-analytics/screen.tsx
28751
- import { useEffect as useEffect23, useState as useState30 } from "react";
28752
- import { Box as Box45, Text as Text47, useInput as useInput12 } from "ink";
29432
+ import { useEffect as useEffect25, useState as useState34 } from "react";
29433
+ import { Box as Box49, Text as Text52, useInput as useInput14 } from "ink";
28753
29434
 
28754
29435
  // packages/experience-design-system-cli/src/tui/settings/opt-in-analytics/analytics-store.ts
28755
29436
  async function readAnalyticsSetting() {
@@ -28768,11 +29449,11 @@ async function writeAnalyticsSetting(setting) {
28768
29449
 
28769
29450
  // packages/experience-design-system-cli/src/tui/settings/opt-in-analytics/screen.tsx
28770
29451
  init_debug_store();
28771
- import { Fragment as Fragment18, jsx as jsx56, jsxs as jsxs46 } from "react/jsx-runtime";
29452
+ import { Fragment as Fragment19, jsx as jsx61, jsxs as jsxs50 } from "react/jsx-runtime";
28772
29453
  function OptInAnalyticsScreen({ onDone }) {
28773
- const [loading, setLoading] = useState30(true);
28774
- const [enabled, setEnabled] = useState30(true);
28775
- useEffect23(() => {
29454
+ const [loading, setLoading] = useState34(true);
29455
+ const [enabled, setEnabled] = useState34(true);
29456
+ useEffect25(() => {
28776
29457
  readAnalyticsSetting().then((setting) => {
28777
29458
  setEnabled(setting.enabled);
28778
29459
  setLoading(false);
@@ -28784,7 +29465,7 @@ function OptInAnalyticsScreen({ onDone }) {
28784
29465
  });
28785
29466
  });
28786
29467
  }, []);
28787
- useInput12((input, key) => {
29468
+ useInput14((input, key) => {
28788
29469
  if (loading) return;
28789
29470
  if (key.return || input === " ") {
28790
29471
  setEnabled((current) => {
@@ -28799,21 +29480,21 @@ function OptInAnalyticsScreen({ onDone }) {
28799
29480
  onDone();
28800
29481
  }
28801
29482
  });
28802
- return /* @__PURE__ */ jsxs46(Box45, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
28803
- /* @__PURE__ */ jsx56(Text47, { bold: true, children: "Settings \u203A Opt-in Analytics" }),
28804
- /* @__PURE__ */ jsx56(Text47, { children: " " }),
28805
- loading ? /* @__PURE__ */ jsx56(Text47, { color: PALETTE.muted, children: "Loading\u2026" }) : /* @__PURE__ */ jsxs46(Fragment18, { children: [
28806
- /* @__PURE__ */ jsxs46(Text47, { children: [
29483
+ return /* @__PURE__ */ jsxs50(Box49, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
29484
+ /* @__PURE__ */ jsx61(Text52, { bold: true, children: "Settings \u203A Opt-in Analytics" }),
29485
+ /* @__PURE__ */ jsx61(Text52, { children: " " }),
29486
+ loading ? /* @__PURE__ */ jsx61(Text52, { color: PALETTE.muted, children: "Loading\u2026" }) : /* @__PURE__ */ jsxs50(Fragment19, { children: [
29487
+ /* @__PURE__ */ jsxs50(Text52, { children: [
28807
29488
  "Share anonymous usage data:",
28808
29489
  " ",
28809
- /* @__PURE__ */ jsx56(Text47, { bold: true, color: enabled ? PALETTE.success : PALETTE.muted, children: enabled ? "On" : "Off" })
29490
+ /* @__PURE__ */ jsx61(Text52, { bold: true, color: enabled ? PALETTE.success : PALETTE.muted, children: enabled ? "On" : "Off" })
28810
29491
  ] }),
28811
- /* @__PURE__ */ jsx56(Text47, { children: " " }),
28812
- /* @__PURE__ */ jsx56(Text47, { color: PALETTE.muted, children: "Shares which CLI commands are used and where imports succeed or fail." }),
28813
- /* @__PURE__ */ jsx56(Text47, { color: PALETTE.muted, children: "Never includes source code, file paths, credentials, or authored content." })
29492
+ /* @__PURE__ */ jsx61(Text52, { children: " " }),
29493
+ /* @__PURE__ */ jsx61(Text52, { color: PALETTE.muted, children: "Shares which CLI commands are used and where imports succeed or fail." }),
29494
+ /* @__PURE__ */ jsx61(Text52, { color: PALETTE.muted, children: "Never includes source code, file paths, credentials, or authored content." })
28814
29495
  ] }),
28815
- /* @__PURE__ */ jsx56(Text47, { children: " " }),
28816
- /* @__PURE__ */ jsx56(
29496
+ /* @__PURE__ */ jsx61(Text52, { children: " " }),
29497
+ /* @__PURE__ */ jsx61(
28817
29498
  ControlHints,
28818
29499
  {
28819
29500
  hints: [
@@ -28825,16 +29506,89 @@ function OptInAnalyticsScreen({ onDone }) {
28825
29506
  ] });
28826
29507
  }
28827
29508
 
29509
+ // packages/experience-design-system-cli/src/tui/upgrade/PageContainer.tsx
29510
+ import { useEffect as useEffect26, useState as useState35 } from "react";
29511
+ import { Box as Box50, Text as Text53, useInput as useInput15 } from "ink";
29512
+ init_version();
29513
+ init_debug_store();
29514
+ import { jsx as jsx62, jsxs as jsxs51 } from "react/jsx-runtime";
29515
+ var UPGRADE_COMMANDS = ["git pull", "pnpm install", "pnpm build"];
29516
+ function UpgradeScreen({ onDone }) {
29517
+ const [upgradeCheck, setUpgradeCheck] = useState35();
29518
+ useEffect26(() => {
29519
+ startDebugRun({
29520
+ flow: "upgrade",
29521
+ step: "01-upgrade",
29522
+ menuOption: "Upgrade",
29523
+ inputs: { currentVersion: readPackageVersion() }
29524
+ });
29525
+ checkForUpgrade().then(setUpgradeCheck).catch(() => setUpgradeCheck({ status: "error" }));
29526
+ }, []);
29527
+ useInput15((_input, key) => {
29528
+ if (key.return) {
29529
+ void finishDebugRun({
29530
+ outputs: upgradeCheck ?? {},
29531
+ status: upgradeCheck?.status === "error" ? "error" : "success",
29532
+ exitMethod: "saved"
29533
+ });
29534
+ onDone();
29535
+ return;
29536
+ }
29537
+ });
29538
+ return /* @__PURE__ */ jsxs51(Box50, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
29539
+ /* @__PURE__ */ jsx62(Text53, { bold: true, children: "Upgrade" }),
29540
+ /* @__PURE__ */ jsx62(Text53, { children: " " }),
29541
+ renderBody(upgradeCheck),
29542
+ /* @__PURE__ */ jsx62(Text53, { children: " " }),
29543
+ /* @__PURE__ */ jsxs51(Text53, { bold: true, color: PALETTE.accent, children: [
29544
+ FOCUS_MARKER,
29545
+ " Go Back"
29546
+ ] })
29547
+ ] });
29548
+ }
29549
+ function renderBody(upgradeCheck) {
29550
+ if (!upgradeCheck) {
29551
+ return /* @__PURE__ */ jsx62(Text53, { color: PALETTE.muted, children: "Checking for updates\u2026" });
29552
+ }
29553
+ if (upgradeCheck.status === "error") {
29554
+ return /* @__PURE__ */ jsx62(Text53, { color: PALETTE.warning, children: "Couldn't check for updates \u2014 check your network connection and try again." });
29555
+ }
29556
+ if (upgradeCheck.status === "up-to-date") {
29557
+ return /* @__PURE__ */ jsxs51(Text53, { color: PALETTE.success, children: [
29558
+ "You're already on the latest version (v",
29559
+ upgradeCheck.current,
29560
+ ")."
29561
+ ] });
29562
+ }
29563
+ return /* @__PURE__ */ jsxs51(Box50, { flexDirection: "column", children: [
29564
+ /* @__PURE__ */ jsxs51(Text53, { color: PALETTE.muted, children: [
29565
+ /* @__PURE__ */ jsxs51(Text53, { bold: true, color: PALETTE.success, children: [
29566
+ "v",
29567
+ upgradeCheck.latest
29568
+ ] }),
29569
+ " ",
29570
+ "is available (you're on ",
29571
+ /* @__PURE__ */ jsxs51(Text53, { bold: true, children: [
29572
+ "v",
29573
+ upgradeCheck.current
29574
+ ] }),
29575
+ "). Exit this program, cd into the root of your local clone of contentful/experience-design-system-sdk-public, then run:"
29576
+ ] }),
29577
+ /* @__PURE__ */ jsx62(Text53, { children: " " }),
29578
+ /* @__PURE__ */ jsx62(Box50, { flexDirection: "column", borderStyle: "round", borderColor: PALETTE.border, paddingX: 1, children: UPGRADE_COMMANDS.map((cmd) => /* @__PURE__ */ jsx62(Text53, { bold: true, children: cmd }, cmd)) })
29579
+ ] });
29580
+ }
29581
+
28828
29582
  // packages/experience-design-system-cli/src/tui/settings/debug-mode/screen.tsx
28829
- import { useEffect as useEffect24, useState as useState31 } from "react";
28830
- import { Box as Box46, Text as Text48, useInput as useInput13 } from "ink";
29583
+ import { useEffect as useEffect27, useState as useState36 } from "react";
29584
+ import { Box as Box51, Text as Text54, useInput as useInput16 } from "ink";
28831
29585
  init_debug_mode_store();
28832
29586
  init_debug_store();
28833
- import { jsx as jsx57, jsxs as jsxs47 } from "react/jsx-runtime";
29587
+ import { jsx as jsx63, jsxs as jsxs52 } from "react/jsx-runtime";
28834
29588
  function DebugModeScreen({ onDone }) {
28835
- const [loading, setLoading] = useState31(true);
28836
- const [enabled, setEnabled] = useState31(true);
28837
- useEffect24(() => {
29589
+ const [loading, setLoading] = useState36(true);
29590
+ const [enabled, setEnabled] = useState36(true);
29591
+ useEffect27(() => {
28838
29592
  readDebugModeSetting().then((setting) => {
28839
29593
  setEnabled(setting.enabled);
28840
29594
  setLoading(false);
@@ -28846,7 +29600,7 @@ function DebugModeScreen({ onDone }) {
28846
29600
  });
28847
29601
  });
28848
29602
  }, []);
28849
- useInput13((input, key) => {
29603
+ useInput16((input, key) => {
28850
29604
  if (loading) return;
28851
29605
  if (key.return || input === " ") {
28852
29606
  setEnabled((current) => {
@@ -28861,16 +29615,16 @@ function DebugModeScreen({ onDone }) {
28861
29615
  onDone();
28862
29616
  }
28863
29617
  });
28864
- return /* @__PURE__ */ jsxs47(Box46, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
28865
- /* @__PURE__ */ jsx57(Text48, { bold: true, children: "Settings \u203A Debug Mode" }),
28866
- /* @__PURE__ */ jsx57(Text48, { children: " " }),
28867
- loading ? /* @__PURE__ */ jsx57(Text48, { color: PALETTE.muted, children: "Loading\u2026" }) : /* @__PURE__ */ jsxs47(Text48, { children: [
29618
+ return /* @__PURE__ */ jsxs52(Box51, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
29619
+ /* @__PURE__ */ jsx63(Text54, { bold: true, children: "Settings \u203A Debug Mode" }),
29620
+ /* @__PURE__ */ jsx63(Text54, { children: " " }),
29621
+ loading ? /* @__PURE__ */ jsx63(Text54, { color: PALETTE.muted, children: "Loading\u2026" }) : /* @__PURE__ */ jsxs52(Text54, { children: [
28868
29622
  "Debug logging:",
28869
29623
  " ",
28870
- /* @__PURE__ */ jsx57(Text48, { bold: true, color: enabled ? PALETTE.success : PALETTE.muted, children: enabled ? "On" : "Off" })
29624
+ /* @__PURE__ */ jsx63(Text54, { bold: true, color: enabled ? PALETTE.success : PALETTE.muted, children: enabled ? "On" : "Off" })
28871
29625
  ] }),
28872
- /* @__PURE__ */ jsx57(Text48, { children: " " }),
28873
- /* @__PURE__ */ jsx57(
29626
+ /* @__PURE__ */ jsx63(Text54, { children: " " }),
29627
+ /* @__PURE__ */ jsx63(
28874
29628
  ControlHints,
28875
29629
  {
28876
29630
  hints: [
@@ -28883,18 +29637,18 @@ function DebugModeScreen({ onDone }) {
28883
29637
  }
28884
29638
 
28885
29639
  // packages/experience-design-system-cli/app.tsx
28886
- import { Fragment as Fragment19, jsx as jsx58 } from "react/jsx-runtime";
29640
+ import { Fragment as Fragment20, jsx as jsx64 } from "react/jsx-runtime";
28887
29641
  function App({ importOptions, inkClear }) {
28888
- const [screen, setScreen] = useState32("start");
28889
- const [importExitCode, setImportExitCode] = useState32();
29642
+ const [screen, setScreen] = useState37("start");
29643
+ const [importExitCode, setImportExitCode] = useState37();
28890
29644
  const showImportResult = importExitCode !== void 0;
28891
- const [projectPath, setProjectPath] = useState32();
28892
- const [tokensPath, setTokensPath] = useState32();
28893
- const [scannedFiles, setScannedFiles] = useState32();
28894
- const [pendingLaunch, setPendingLaunch] = useState32();
28895
- const [extractionRun, setExtractionRun] = useState32();
29645
+ const [projectPath, setProjectPath] = useState37();
29646
+ const [tokensPath, setTokensPath] = useState37();
29647
+ const [scannedFiles, setScannedFiles] = useState37();
29648
+ const [pendingLaunch, setPendingLaunch] = useState37();
29649
+ const [extractionRun, setExtractionRun] = useState37();
28896
29650
  const extraction = useExtraction(extractionRun?.input);
28897
- const [scopeRun, setScopeRun] = useState32();
29651
+ const [scopeRun, setScopeRun] = useState37();
28898
29652
  const scopeFlow = useScopeGateFlow(
28899
29653
  scopeRun && {
28900
29654
  sessionId: scopeRun.extraction.sessionId,
@@ -28909,12 +29663,12 @@ function App({ importOptions, inkClear }) {
28909
29663
  }
28910
29664
  }
28911
29665
  );
28912
- const [generationInput, setGenerationInput] = useState32();
29666
+ const [generationInput, setGenerationInput] = useState37();
28913
29667
  const generation = useGeneration(generationInput);
28914
- const [flowStart, setFlowStart] = useState32();
29668
+ const [flowStart, setFlowStart] = useState37();
28915
29669
  const flow = useFlow(flowStart, { beforeStepChange: inkClear });
28916
- const [importDefaults, setImportDefaults] = useState32();
28917
- useEffect25(() => {
29670
+ const [importDefaults, setImportDefaults] = useState37();
29671
+ useEffect28(() => {
28918
29672
  if (screen !== "import") {
28919
29673
  setImportDefaults(void 0);
28920
29674
  return;
@@ -28932,7 +29686,7 @@ function App({ importOptions, inkClear }) {
28932
29686
  const launch = { projectPath: projectPath2, tokens, filePaths, ...importOptions };
28933
29687
  const state2 = await inspectTokens({
28934
29688
  rawTokensPath: tokens,
28935
- contentfulDir: join25(resolveUserPath(projectPath2), ".contentful"),
29689
+ contentfulDir: join26(resolveUserPath(projectPath2), ".contentful"),
28936
29690
  cache: importOptions.cache
28937
29691
  });
28938
29692
  if (state2.kind === "cached") {
@@ -28974,12 +29728,12 @@ function App({ importOptions, inkClear }) {
28974
29728
  }
28975
29729
  });
28976
29730
  };
28977
- useEffect25(() => {
29731
+ useEffect28(() => {
28978
29732
  if (!extractionRun || extraction?.status !== "done" || !extraction.result.ok) return;
28979
29733
  setExtractionRun(void 0);
28980
29734
  setScopeRun({ ...extractionRun, extraction: extraction.result.extraction });
28981
29735
  }, [extraction, extractionRun]);
28982
- useEffect25(() => {
29736
+ useEffect28(() => {
28983
29737
  if (!scopeRun || scopeFlow?.status !== "confirmed" || generationInput) return;
28984
29738
  const { extraction: produced, input, generatePromptPath } = scopeRun;
28985
29739
  setGenerationInput({
@@ -28997,7 +29751,7 @@ function App({ importOptions, inkClear }) {
28997
29751
  ...generatePromptPath ? { generatePromptPath } : {}
28998
29752
  });
28999
29753
  }, [scopeFlow, scopeRun, generationInput]);
29000
- useEffect25(() => {
29754
+ useEffect28(() => {
29001
29755
  if (!scopeRun || generation?.status !== "done" || !generation.result.ok) return;
29002
29756
  const { credentialsSkipped, tokenStrategy, extraction: produced, input, generatePromptPath } = scopeRun;
29003
29757
  inkClear();
@@ -29040,9 +29794,9 @@ function App({ importOptions, inkClear }) {
29040
29794
  };
29041
29795
  switch (screen) {
29042
29796
  case "import":
29043
- if (showImportResult) return /* @__PURE__ */ jsx58(ImportScreen, { exitCode: importExitCode, onDone: finishImportResult });
29797
+ if (showImportResult) return /* @__PURE__ */ jsx64(ImportScreen, { exitCode: importExitCode, onDone: finishImportResult });
29044
29798
  if (flow && flowStart) {
29045
- return /* @__PURE__ */ jsx58(
29799
+ return /* @__PURE__ */ jsx64(
29046
29800
  FlowScreen,
29047
29801
  {
29048
29802
  state: flow.state,
@@ -29052,12 +29806,12 @@ function App({ importOptions, inkClear }) {
29052
29806
  }
29053
29807
  );
29054
29808
  }
29055
- if (importDefaults === void 0) return /* @__PURE__ */ jsx58(Fragment19, {});
29809
+ if (importDefaults === void 0) return /* @__PURE__ */ jsx64(Fragment20, {});
29056
29810
  if (projectPath === void 0) {
29057
- return /* @__PURE__ */ jsx58(WelcomeScreen, { onContinue: setProjectPath, onQuit: leaveImport, initialPath: importDefaults.componentDir });
29811
+ return /* @__PURE__ */ jsx64(WelcomeScreen, { onContinue: setProjectPath, onQuit: leaveImport, initialPath: importDefaults.componentDir });
29058
29812
  }
29059
29813
  if (tokensPath === void 0) {
29060
- return /* @__PURE__ */ jsx58(
29814
+ return /* @__PURE__ */ jsx64(
29061
29815
  TokenInputScreen,
29062
29816
  {
29063
29817
  initialPath: importDefaults.tokenFile,
@@ -29067,7 +29821,7 @@ function App({ importOptions, inkClear }) {
29067
29821
  );
29068
29822
  }
29069
29823
  if (scannedFiles === void 0) {
29070
- return /* @__PURE__ */ jsx58(
29824
+ return /* @__PURE__ */ jsx64(
29071
29825
  PathValidationScreen,
29072
29826
  {
29073
29827
  projectPath,
@@ -29079,10 +29833,10 @@ function App({ importOptions, inkClear }) {
29079
29833
  }
29080
29834
  if (extractionRun) {
29081
29835
  if (extraction?.status === "done" && !extraction.result.ok) {
29082
- return /* @__PURE__ */ jsx58(ErrorStep, { stepName: extraction.result.step, message: extraction.result.message, onExit: leaveImport });
29836
+ return /* @__PURE__ */ jsx64(ErrorStep, { stepName: extraction.result.step, message: extraction.result.message, onExit: leaveImport });
29083
29837
  }
29084
29838
  if (extraction?.status === "running") {
29085
- return /* @__PURE__ */ jsx58(
29839
+ return /* @__PURE__ */ jsx64(
29086
29840
  ExtractionScreen,
29087
29841
  {
29088
29842
  progress: extraction.progress,
@@ -29091,14 +29845,14 @@ function App({ importOptions, inkClear }) {
29091
29845
  }
29092
29846
  );
29093
29847
  }
29094
- return /* @__PURE__ */ jsx58(Fragment19, {});
29848
+ return /* @__PURE__ */ jsx64(Fragment20, {});
29095
29849
  }
29096
29850
  if (scopeRun && scopeFlow) {
29097
29851
  if (scopeFlow.status === "failed") {
29098
- return /* @__PURE__ */ jsx58(ErrorStep, { stepName: "scope gate", message: scopeFlow.message, onExit: leaveImport });
29852
+ return /* @__PURE__ */ jsx64(ErrorStep, { stepName: "scope gate", message: scopeFlow.message, onExit: leaveImport });
29099
29853
  }
29100
29854
  if (scopeFlow.status === "deciding") {
29101
- return /* @__PURE__ */ jsx58(
29855
+ return /* @__PURE__ */ jsx64(
29102
29856
  ScopeGateScreen,
29103
29857
  {
29104
29858
  components: scopeFlow.load.components,
@@ -29108,7 +29862,7 @@ function App({ importOptions, inkClear }) {
29108
29862
  );
29109
29863
  }
29110
29864
  if (generation?.status === "done" && !generation.result.ok) {
29111
- return /* @__PURE__ */ jsx58(ErrorStep, { stepName: generation.result.step, message: generation.result.message, onExit: leaveImport });
29865
+ return /* @__PURE__ */ jsx64(ErrorStep, { stepName: generation.result.step, message: generation.result.message, onExit: leaveImport });
29112
29866
  }
29113
29867
  if (generation?.status === "running") {
29114
29868
  const hasRawTokens = scopeRun.input.rawTokensPath !== "";
@@ -29116,7 +29870,7 @@ function App({ importOptions, inkClear }) {
29116
29870
  hasRawTokens,
29117
29871
  mapTokensEligible: generation.progress.mapTokensEligible
29118
29872
  });
29119
- return /* @__PURE__ */ jsx58(
29873
+ return /* @__PURE__ */ jsx64(
29120
29874
  GenerationScreen,
29121
29875
  {
29122
29876
  progress: generation.progress,
@@ -29128,10 +29882,10 @@ function App({ importOptions, inkClear }) {
29128
29882
  }
29129
29883
  );
29130
29884
  }
29131
- return /* @__PURE__ */ jsx58(Fragment19, {});
29885
+ return /* @__PURE__ */ jsx64(Fragment20, {});
29132
29886
  }
29133
29887
  if (pendingLaunch?.cached) {
29134
- return /* @__PURE__ */ jsx58(
29888
+ return /* @__PURE__ */ jsx64(
29135
29889
  TokenReuseScreen,
29136
29890
  {
29137
29891
  tokensPath: pendingLaunch.cached.tokensPath,
@@ -29142,7 +29896,7 @@ function App({ importOptions, inkClear }) {
29142
29896
  }
29143
29897
  );
29144
29898
  }
29145
- return /* @__PURE__ */ jsx58(
29899
+ return /* @__PURE__ */ jsx64(
29146
29900
  CredentialsScreen,
29147
29901
  {
29148
29902
  initial: importDefaults.credentials,
@@ -29151,17 +29905,19 @@ function App({ importOptions, inkClear }) {
29151
29905
  }
29152
29906
  );
29153
29907
  case "help":
29154
- return /* @__PURE__ */ jsx58(HelpScreen, { onDone: goToStart });
29908
+ return /* @__PURE__ */ jsx64(HelpScreen, { onDone: goToStart });
29909
+ case "upgrade":
29910
+ return /* @__PURE__ */ jsx64(UpgradeScreen, { onDone: goToStart });
29155
29911
  case "settings":
29156
- return /* @__PURE__ */ jsx58(SettingsScreen, { onNavigate: setScreen, onBack: goToStart });
29912
+ return /* @__PURE__ */ jsx64(SettingsScreen, { onNavigate: setScreen, onBack: goToStart });
29157
29913
  case "settings-configuration":
29158
- return /* @__PURE__ */ jsx58(ConfigurationScreen, { onDone: goToSettings });
29914
+ return /* @__PURE__ */ jsx64(ConfigurationScreen, { onDone: goToSettings });
29159
29915
  case "settings-opt-in-analytics":
29160
- return /* @__PURE__ */ jsx58(OptInAnalyticsScreen, { onDone: goToSettings });
29916
+ return /* @__PURE__ */ jsx64(OptInAnalyticsScreen, { onDone: goToSettings });
29161
29917
  case "settings-debug-mode":
29162
- return /* @__PURE__ */ jsx58(DebugModeScreen, { onDone: goToSettings });
29918
+ return /* @__PURE__ */ jsx64(DebugModeScreen, { onDone: goToSettings });
29163
29919
  case "start":
29164
- return /* @__PURE__ */ jsx58(HomeScreen, { onNavigate: setScreen });
29920
+ return /* @__PURE__ */ jsx64(HomeScreen, { onNavigate: setScreen });
29165
29921
  }
29166
29922
  }
29167
29923
  async function runApp(renderApp, importOptions) {
@@ -29169,7 +29925,7 @@ async function runApp(renderApp, importOptions) {
29169
29925
  instance.clear?.();
29170
29926
  process.stdout.write("\x1B[H\x1B[0J");
29171
29927
  };
29172
- const instance = renderApp(/* @__PURE__ */ jsx58(App, { importOptions, inkClear }));
29928
+ const instance = renderApp(/* @__PURE__ */ jsx64(App, { importOptions, inkClear }));
29173
29929
  await instance.waitUntilExit();
29174
29930
  }
29175
29931
  export {