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