@contentful/experience-design-system-cli 2.37.1-dev-build-a029dc0a.0 → 2.37.1-dev-build-1c5cd11a.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
@@ -772,7 +772,7 @@ async function runAgent(options) {
772
772
  promptLen: prompt.length,
773
773
  promptHead: prompt.slice(0, 500)
774
774
  });
775
- return new Promise((resolve22) => {
775
+ return new Promise((resolve25) => {
776
776
  const bedrockEnv = bedrock ? BEDROCK_ENV_BY_AGENT[agent] : void 0;
777
777
  const child = spawn(binary, args, {
778
778
  stdio: ["pipe", "pipe", "pipe"],
@@ -821,7 +821,7 @@ async function runAgent(options) {
821
821
  stderrLen: stderr.length,
822
822
  stderrTail: stderr.slice(-1e3)
823
823
  });
824
- resolve22(result);
824
+ resolve25(result);
825
825
  });
826
826
  });
827
827
  }
@@ -843,7 +843,7 @@ async function checkAgentAuth(agent) {
843
843
  return "not-found";
844
844
  if (agent !== "claude")
845
845
  return "ok";
846
- return new Promise((resolve22) => {
846
+ return new Promise((resolve25) => {
847
847
  const child = spawn2(binary, ["auth", "status", "--json"], { stdio: ["ignore", "pipe", "pipe"] });
848
848
  let stdout = "";
849
849
  let done = false;
@@ -852,7 +852,7 @@ async function checkAgentAuth(agent) {
852
852
  return;
853
853
  done = true;
854
854
  child.kill("SIGTERM");
855
- resolve22("unauthenticated");
855
+ resolve25("unauthenticated");
856
856
  }, 5e3);
857
857
  child.stdout?.on("data", (chunk) => {
858
858
  stdout += chunk.toString();
@@ -863,14 +863,14 @@ async function checkAgentAuth(agent) {
863
863
  done = true;
864
864
  clearTimeout(timer);
865
865
  if (code !== 0) {
866
- resolve22("unauthenticated");
866
+ resolve25("unauthenticated");
867
867
  return;
868
868
  }
869
869
  try {
870
870
  const status = JSON.parse(stdout);
871
- resolve22(status.loggedIn ? "ok" : "unauthenticated");
871
+ resolve25(status.loggedIn ? "ok" : "unauthenticated");
872
872
  } catch {
873
- resolve22("unauthenticated");
873
+ resolve25("unauthenticated");
874
874
  }
875
875
  });
876
876
  });
@@ -880,9 +880,9 @@ async function binaryIsOnPath(binary) {
880
880
  const fs = await import("node:fs/promises");
881
881
  return fs.access(binary).then(() => true, () => false);
882
882
  }
883
- return new Promise((resolve22) => {
883
+ return new Promise((resolve25) => {
884
884
  const child = spawn2(process.platform === "win32" ? "where" : "which", [binary], { stdio: "ignore" });
885
- child.on("close", (code) => resolve22(code === 0));
885
+ child.on("close", (code) => resolve25(code === 0));
886
886
  });
887
887
  }
888
888
  var init_check_agent_auth = __esm({
@@ -2017,7 +2017,7 @@ var init_cache_keys = __esm({
2017
2017
  });
2018
2018
 
2019
2019
  // packages/experience-design-system-cli/app.tsx
2020
- import { join as join26 } from "node:path";
2020
+ import { join as join25 } from "node:path";
2021
2021
  import { useEffect as useEffect26, useState as useState33 } from "react";
2022
2022
 
2023
2023
  // packages/experience-design-system-cli/src/tui/home/home.tsx
@@ -2553,6 +2553,8 @@ function usePathValidationControls(phase, handlers) {
2553
2553
  // packages/experience-design-system-backend-pipeline/dist/src/persistence/src/session/repositories/db.js
2554
2554
  import { DatabaseSync } from "node:sqlite";
2555
2555
  import { mkdirSync, readFileSync as readFileSync3 } from "node:fs";
2556
+ import { readFile as readFile4 } from "node:fs/promises";
2557
+ import { createHash as createHash5 } from "node:crypto";
2556
2558
 
2557
2559
  // packages/experience-design-system-backend-pipeline/dist/src/persistence/src/session/helpers/config-root.js
2558
2560
  import { homedir as homedir2 } from "node:os";
@@ -2565,6 +2567,81 @@ var runsFilePath = () => join3(configRoot(), "state", "runs.json");
2565
2567
  // packages/experience-design-system-backend-pipeline/dist/src/persistence/src/session/repositories/db.js
2566
2568
  import { dirname as dirname4, resolve as resolve6 } from "node:path";
2567
2569
 
2570
+ // packages/experience-design-system-backend-pipeline/dist/src/persistence/src/session/helpers/source-excerpt.js
2571
+ var ELLIPSIS_MARKER = "/* \u2026 */";
2572
+ var TRUNCATED_MARKER = "/* truncated */";
2573
+ function escapeForRegExp(value) {
2574
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
2575
+ }
2576
+ function identifierPattern(name) {
2577
+ return new RegExp(`(?<![A-Za-z0-9_$])${escapeForRegExp(name)}(?![A-Za-z0-9_$])`);
2578
+ }
2579
+ function excerptAroundNames(text, names, maxChars, contextLines = 6) {
2580
+ if (text.length <= maxChars)
2581
+ return { content: text, usesNotShown: [] };
2582
+ const patterns = names.filter((name) => name.length > 0).map((name) => ({ name, pattern: identifierPattern(name) }));
2583
+ const lines = text.split("\n");
2584
+ const windows = [];
2585
+ lines.forEach((line, index) => {
2586
+ const mentioned = patterns.filter(({ pattern }) => pattern.test(line)).map(({ name }) => name);
2587
+ if (mentioned.length === 0)
2588
+ return;
2589
+ const start = Math.max(0, index - contextLines);
2590
+ const end = Math.min(lines.length - 1, index + contextLines);
2591
+ const last = windows[windows.length - 1];
2592
+ if (last && start <= last.end + 1) {
2593
+ last.end = Math.max(last.end, end);
2594
+ for (const name of mentioned)
2595
+ last.names.add(name);
2596
+ } else {
2597
+ windows.push({ start, end, names: new Set(mentioned) });
2598
+ }
2599
+ });
2600
+ if (windows.length === 0) {
2601
+ return { content: `${text.slice(0, maxChars)}
2602
+ ${TRUNCATED_MARKER}`, usesNotShown: [] };
2603
+ }
2604
+ const lastWindowFor = /* @__PURE__ */ new Map();
2605
+ for (const window of windows)
2606
+ for (const name of window.names)
2607
+ lastWindowFor.set(name, window);
2608
+ const kept = [];
2609
+ const cut = /* @__PURE__ */ new Set();
2610
+ let used = 0;
2611
+ for (const window of [...windows].reverse()) {
2612
+ const chunk = lines.slice(window.start, window.end + 1).join("\n");
2613
+ const separator = kept.length > 0 ? `
2614
+ ${ELLIPSIS_MARKER}
2615
+ ` : "";
2616
+ if (used + separator.length + chunk.length > maxChars) {
2617
+ if (kept.length === 0) {
2618
+ const head = chunk.slice(0, maxChars);
2619
+ kept.push({ window, text: head });
2620
+ used += head.length;
2621
+ for (const name of window.names) {
2622
+ if (lastWindowFor.get(name) === window && !identifierPattern(name).test(head))
2623
+ cut.add(name);
2624
+ }
2625
+ continue;
2626
+ }
2627
+ for (const name of window.names) {
2628
+ if (lastWindowFor.get(name) === window)
2629
+ cut.add(name);
2630
+ }
2631
+ continue;
2632
+ }
2633
+ kept.push({ window, text: chunk });
2634
+ used += separator.length + chunk.length;
2635
+ }
2636
+ kept.sort((a, b) => a.window.start - b.window.start);
2637
+ const parts = kept.map((entry, index) => (index > 0 ? `
2638
+ ${ELLIPSIS_MARKER}
2639
+ ` : "") + entry.text);
2640
+ const usesNotShown = names.filter((name, index) => cut.has(name) && names.indexOf(name) === index);
2641
+ return { content: `${parts.join("")}
2642
+ ${TRUNCATED_MARKER}`, usesNotShown };
2643
+ }
2644
+
2568
2645
  // packages/experience-design-system-backend-pipeline/dist/src/persistence/src/session/helpers/components/derive-component-id.js
2569
2646
  import { createHash } from "node:crypto";
2570
2647
  function deriveComponentId(name, source) {
@@ -2626,6 +2703,14 @@ function getSessionById(db, sessionId) {
2626
2703
  const row = db.prepare("SELECT id FROM sessions WHERE id = ?").get(sessionId);
2627
2704
  return row ?? null;
2628
2705
  }
2706
+ function getLatestCompletedSessionForCommand(db, command) {
2707
+ const row = db.prepare(`SELECT s.id FROM sessions s
2708
+ JOIN steps st ON st.session_id = s.id
2709
+ WHERE st.command = ? AND st.status = 'complete'
2710
+ ORDER BY st.started_at DESC, st.id DESC
2711
+ LIMIT 1`).get(command);
2712
+ return row?.id ?? null;
2713
+ }
2629
2714
 
2630
2715
  // packages/experience-design-system-backend-pipeline/dist/src/persistence/src/session/repositories/sessions/write.js
2631
2716
  function createSession(db, id, name, timestamp) {
@@ -2930,6 +3015,13 @@ function getRawTokenNamePaths(db, sessionId) {
2930
3015
  const rows = db.prepare("SELECT raw_name, path FROM raw_token_name_paths WHERE session_id = ? ORDER BY raw_name").all(sessionId);
2931
3016
  return Object.fromEntries(rows.map((row) => [String(row.raw_name), String(row.path)]));
2932
3017
  }
3018
+ function getRawTokenNamePathRows(db, sessionId) {
3019
+ return db.prepare("SELECT raw_name, path, source FROM raw_token_name_paths WHERE session_id = ? ORDER BY raw_name").all(sessionId).map((row) => ({
3020
+ rawName: String(row.raw_name),
3021
+ path: String(row.path),
3022
+ source: String(row.source)
3023
+ }));
3024
+ }
2933
3025
 
2934
3026
  // packages/experience-design-system-backend-pipeline/dist/src/persistence/src/session/helpers/components/hash-component-shape.js
2935
3027
  import { createHash as createHash2 } from "node:crypto";
@@ -2981,6 +3073,27 @@ function upsertRawTokenGroup(db, sessionId, call) {
2981
3073
  db.prepare(`INSERT INTO raw_token_groups (session_id, path, description) VALUES (?, ?, ?)
2982
3074
  ON CONFLICT(session_id, path) DO UPDATE SET description = excluded.description`).run(sessionId, call.path, call.description ?? null);
2983
3075
  }
3076
+ function updateRawTokenNamePaths(db, sessionId, tokenNamePaths, source) {
3077
+ const entries = Object.entries(tokenNamePaths);
3078
+ const deletePaths = db.prepare("DELETE FROM raw_token_name_paths WHERE session_id = ? AND source = ?");
3079
+ const insertPath = db.prepare("INSERT OR IGNORE INTO raw_token_name_paths (session_id, raw_name, path, source) VALUES (?, ?, ?, ?)");
3080
+ const deleteAutomaticByName = db.prepare("DELETE FROM raw_token_name_paths WHERE session_id = ? AND raw_name = ? AND source = 'automatic'");
3081
+ deletePaths.run(sessionId, source);
3082
+ for (const [rawName, path5] of entries) {
3083
+ if (source === "manual")
3084
+ deleteAutomaticByName.run(sessionId, rawName);
3085
+ insertPath.run(sessionId, rawName, path5, source);
3086
+ }
3087
+ }
3088
+ function updateRawPropTokenPaths(db, sessionId, componentId, propName, paths, source) {
3089
+ db.prepare(`DELETE FROM raw_prop_token_paths
3090
+ WHERE session_id = ? AND component_id = ? AND prop_name = ?`).run(sessionId, componentId, propName);
3091
+ const insertPath = db.prepare(`INSERT INTO raw_prop_token_paths (session_id, component_id, prop_name, source, position, path)
3092
+ VALUES (?, ?, ?, ?, ?, ?)`);
3093
+ paths.forEach((path5, position) => {
3094
+ insertPath.run(sessionId, componentId, propName, source, position, path5);
3095
+ });
3096
+ }
2984
3097
 
2985
3098
  // packages/experience-design-system-backend-pipeline/dist/src/persistence/src/session/repositories/shared/with-transaction.js
2986
3099
  function withTransaction(db, fn) {
@@ -3027,6 +3140,22 @@ function applyTokenToolCalls(db, sessionId, calls, incomingWarnings) {
3027
3140
  return { tokens, groups, warnings };
3028
3141
  }
3029
3142
 
3143
+ // packages/experience-design-system-backend-pipeline/dist/src/persistence/src/session/services/tokens/replace-raw-token-name-paths.js
3144
+ function replaceRawTokenNamePaths(db, sessionId, tokenNamePaths, source = "automatic") {
3145
+ withTransaction(db, () => {
3146
+ updateRawTokenNamePaths(db, sessionId, tokenNamePaths, source);
3147
+ updateSessionTimestamp(db, sessionId, (/* @__PURE__ */ new Date()).toISOString());
3148
+ });
3149
+ }
3150
+
3151
+ // packages/experience-design-system-backend-pipeline/dist/src/persistence/src/session/services/tokens/replace-raw-prop-token-paths.js
3152
+ function replaceRawPropTokenPaths(db, sessionId, componentId, propName, paths, source) {
3153
+ withTransaction(db, () => {
3154
+ updateRawPropTokenPaths(db, sessionId, componentId, propName, paths, source);
3155
+ updateSessionTimestamp(db, sessionId, (/* @__PURE__ */ new Date()).toISOString());
3156
+ });
3157
+ }
3158
+
3030
3159
  // packages/experience-design-system-backend-pipeline/dist/src/persistence/src/session/repositories/db.js
3031
3160
  var SCHEMA = `
3032
3161
  PRAGMA journal_mode = WAL;
@@ -3521,6 +3650,109 @@ function loadComponentRationale(db, sessionId, componentName) {
3521
3650
  }))
3522
3651
  };
3523
3652
  }
3653
+ function applyToolCalls(db, sessionId, componentId, componentName, calls, incomingWarnings, options = {}) {
3654
+ const now = (/* @__PURE__ */ new Date()).toISOString();
3655
+ const warnings = [...incomingWarnings];
3656
+ let classified = 0;
3657
+ let excluded = 0;
3658
+ let slots = 0;
3659
+ const updateProp = db.prepare(`UPDATE raw_props SET cdf_type = ?, cdf_category = ?, cdf_token_kind = ?, required = ?, description = ?, rationale = ?
3660
+ WHERE session_id = ? AND component_id = ? AND name = ?`);
3661
+ const clearProp = db.prepare(`UPDATE raw_props
3662
+ SET cdf_type = CASE WHEN type = 'boolean' THEN 'boolean' ELSE 'string' END,
3663
+ cdf_category = 'unattached',
3664
+ cdf_token_kind = NULL,
3665
+ required = 0,
3666
+ rationale = ?
3667
+ WHERE session_id = ? AND component_id = ? AND name = ?`);
3668
+ const deleteAllowedValues = db.prepare(`DELETE FROM raw_prop_allowed_values WHERE session_id = ? AND component_id = ? AND prop_name = ?`);
3669
+ const deleteTokenPaths = db.prepare(`DELETE FROM raw_prop_token_paths WHERE session_id = ? AND component_id = ? AND prop_name = ?`);
3670
+ const insertAllowedValue = db.prepare(`INSERT OR IGNORE INTO raw_prop_allowed_values (session_id, component_id, prop_name, value, position)
3671
+ VALUES (?, ?, ?, ?, ?)`);
3672
+ const deleteAllowedComponents = db.prepare(`DELETE FROM raw_slot_allowed_components WHERE session_id = ? AND component_id = ? AND slot_name = ?`);
3673
+ const insertAllowedComponent = db.prepare(`INSERT OR IGNORE INTO raw_slot_allowed_components (session_id, component_id, slot_name, allowed_component, position)
3674
+ VALUES (?, ?, ?, ?, ?)`);
3675
+ const updateSlot = db.prepare(`UPDATE raw_slots SET required = ?, description = ? WHERE session_id = ? AND component_id = ? AND name = ?`);
3676
+ db.exec("BEGIN");
3677
+ try {
3678
+ for (const call of calls) {
3679
+ if (call.tool === "classify_component") {
3680
+ if (call.description !== void 0) {
3681
+ db.prepare("UPDATE raw_components SET description = ? WHERE session_id = ? AND component_id = ?").run(call.description, sessionId, componentId);
3682
+ }
3683
+ if (call.rationale) {
3684
+ if (call.rationale.description !== void 0) {
3685
+ db.prepare("UPDATE raw_components SET component_description_rationale = ? WHERE session_id = ? AND component_id = ?").run(call.rationale.description, sessionId, componentId);
3686
+ }
3687
+ if (call.rationale.props !== void 0) {
3688
+ db.prepare("UPDATE raw_components SET props_rationale = ? WHERE session_id = ? AND component_id = ?").run(call.rationale.props, sessionId, componentId);
3689
+ }
3690
+ if (call.rationale.slots !== void 0) {
3691
+ db.prepare("UPDATE raw_components SET slots_rationale = ? WHERE session_id = ? AND component_id = ?").run(call.rationale.slots, sessionId, componentId);
3692
+ }
3693
+ }
3694
+ } else if (call.tool === "classify_prop") {
3695
+ const changes = updateProp.run(call.cdf_type, call.cdf_category, call.token_kind ?? null, call.required !== void 0 ? call.required ? 1 : 0 : 0, call.description ?? null, call.reason ?? null, sessionId, componentId, call.prop);
3696
+ if (changes.changes === 0) {
3697
+ warnings.push(`${componentName}: classify_prop '${call.prop}' \u2014 prop not found, skipped`);
3698
+ continue;
3699
+ }
3700
+ if (call.cdf_type === "token") {
3701
+ deleteAllowedValues.run(sessionId, componentId, call.prop);
3702
+ if (call.values && call.values.length > 0) {
3703
+ const count = call.values.length;
3704
+ warnings.push(`${componentName}: classify_prop '${call.prop}' \u2014 dropped ${count} value${count === 1 ? "" : "s"} on a token property; its options list is $token.allowed, not $values`);
3705
+ }
3706
+ } else {
3707
+ deleteTokenPaths.run(sessionId, componentId, call.prop);
3708
+ if (call.values && call.values.length > 0) {
3709
+ deleteAllowedValues.run(sessionId, componentId, call.prop);
3710
+ call.values.forEach((v, i) => insertAllowedValue.run(sessionId, componentId, call.prop, v, i));
3711
+ }
3712
+ }
3713
+ if (call.default !== void 0) {
3714
+ const storedDefault = typeof call.default === "boolean" ? String(call.default) : call.default;
3715
+ db.prepare(`UPDATE raw_props SET default_value = ? WHERE session_id = ? AND component_id = ? AND name = ?`).run(storedDefault, sessionId, componentId, call.prop);
3716
+ }
3717
+ classified++;
3718
+ } else if (call.tool === "exclude_prop") {
3719
+ clearProp.run(call.reason || null, sessionId, componentId, call.prop);
3720
+ excluded++;
3721
+ } else if (call.tool === "classify_slot") {
3722
+ const slotRequired = call.required !== void 0 ? call.required ? 1 : 0 : 1;
3723
+ const slotChanges = updateSlot.run(slotRequired, call.description ?? null, sessionId, componentId, call.slot);
3724
+ if (slotChanges.changes === 0) {
3725
+ warnings.push(`${componentName}: classify_slot '${call.slot}' \u2014 slot not found, skipped`);
3726
+ continue;
3727
+ }
3728
+ if (call.rationale !== void 0) {
3729
+ db.prepare("UPDATE raw_slots SET rationale = ? WHERE session_id = ? AND component_id = ? AND name = ?").run(call.rationale, sessionId, componentId, call.slot);
3730
+ }
3731
+ if (call.allowed_components !== void 0) {
3732
+ deleteAllowedComponents.run(sessionId, componentId, call.slot);
3733
+ const allowedComponents = options.allowedComponentNames ? call.allowed_components.filter((allowedComponent) => options.allowedComponentNames.has(allowedComponent)) : call.allowed_components;
3734
+ if (options.allowedComponentNames) {
3735
+ const dropped = [
3736
+ ...new Set(call.allowed_components.filter((ac) => !options.allowedComponentNames.has(ac)))
3737
+ ];
3738
+ for (const allowedComponent of dropped) {
3739
+ warnings.push(`${componentName}: classify_slot '${call.slot}' \u2014 dropped unknown allowed component '${allowedComponent}'`);
3740
+ }
3741
+ }
3742
+ allowedComponents.forEach((ac, i) => insertAllowedComponent.run(sessionId, componentId, call.slot, ac, i));
3743
+ }
3744
+ slots++;
3745
+ }
3746
+ }
3747
+ db.prepare(`UPDATE raw_components SET status = 'generated', extracted_at = ? WHERE session_id = ? AND component_id = ?`).run(now, sessionId, componentId);
3748
+ db.prepare("UPDATE sessions SET updated_at = ? WHERE id = ?").run(now, sessionId);
3749
+ db.exec("COMMIT");
3750
+ } catch (e) {
3751
+ db.exec("ROLLBACK");
3752
+ throw e;
3753
+ }
3754
+ return { classified, excluded, slots, warnings };
3755
+ }
3524
3756
  function getOrCreateSession(db, sessionFlag, sessionName, hints) {
3525
3757
  return getOrCreateSessionForCommand(db, sessionFlag, sessionName, hints);
3526
3758
  }
@@ -3730,6 +3962,192 @@ function loadRawComponents(db, sessionId, allowedNames) {
3730
3962
  })
3731
3963
  }));
3732
3964
  }
3965
+ var MAX_COMPONENT_SOURCE_CHARS = 8e3;
3966
+ var MAX_SIBLING_FILES = 5;
3967
+ var MAX_SIBLING_SNIPPET_CHARS = 1200;
3968
+ var MAX_TYPE_DECLARING_SIBLING_CHARS = 4e3;
3969
+ var MAX_ENLARGED_SIBLINGS = 2;
3970
+ var MAX_SIBLING_DEPTH = 2;
3971
+ var MAX_SIBLING_CANDIDATES_EXPLORED = 25;
3972
+ var RELATIVE_IMPORT_PATTERN = /from\s+['"](\.[^'"]+)['"]/g;
3973
+ var SIBLING_FILE_EXTENSIONS = [".ts", ".tsx", ".js", ".jsx"];
3974
+ var TS_ESM_EXTENSION_REWRITES = [
3975
+ [".js", [".ts", ".tsx", ".js", ".jsx"]],
3976
+ [".jsx", [".tsx", ".jsx"]],
3977
+ [".mjs", [".mts", ".mjs"]],
3978
+ [".cjs", [".cts", ".cjs"]]
3979
+ ];
3980
+ function rewrittenSourcePaths(basePath) {
3981
+ for (const [emitted, sources] of TS_ESM_EXTENSION_REWRITES) {
3982
+ if (!basePath.endsWith(emitted))
3983
+ continue;
3984
+ const stem = basePath.slice(0, -emitted.length);
3985
+ return sources.map((ext) => `${stem}${ext}`);
3986
+ }
3987
+ return [];
3988
+ }
3989
+ var IDENTIFIER_PATTERN = /[A-Za-z_$][A-Za-z0-9_$]*/g;
3990
+ function identifiersIn(propTypes) {
3991
+ const names = /* @__PURE__ */ new Set();
3992
+ for (const propType of propTypes) {
3993
+ for (const match2 of propType.matchAll(IDENTIFIER_PATTERN))
3994
+ names.add(match2[0]);
3995
+ }
3996
+ return [...names];
3997
+ }
3998
+ function declaresAnyType(text, typeNames) {
3999
+ return typeNames.some((name) => new RegExp(`\\b(?:type|interface|enum|const|class)\\s+${escapeForRegExp(name)}\\b`).test(text));
4000
+ }
4001
+ function extractRelativeImportPaths(sourceText) {
4002
+ const specifiers = /* @__PURE__ */ new Set();
4003
+ for (const match2 of sourceText.matchAll(RELATIVE_IMPORT_PATTERN)) {
4004
+ if (match2[1])
4005
+ specifiers.add(match2[1]);
4006
+ }
4007
+ return [...specifiers];
4008
+ }
4009
+ async function resolveRelativeImport(specifier, fromDir) {
4010
+ const basePath = resolve6(fromDir, specifier);
4011
+ const candidates = [
4012
+ basePath,
4013
+ ...rewrittenSourcePaths(basePath),
4014
+ ...SIBLING_FILE_EXTENSIONS.map((ext) => `${basePath}${ext}`),
4015
+ ...SIBLING_FILE_EXTENSIONS.map((ext) => resolve6(basePath, `index${ext}`))
4016
+ ];
4017
+ for (const candidate of candidates) {
4018
+ try {
4019
+ await readFile4(candidate, "utf8");
4020
+ return candidate;
4021
+ } catch {
4022
+ }
4023
+ }
4024
+ return void 0;
4025
+ }
4026
+ async function resolveImportSpecifiers(sourceText, fromDir) {
4027
+ const resolvedPaths = [];
4028
+ for (const specifier of extractRelativeImportPaths(sourceText)) {
4029
+ const resolvedPath = await resolveRelativeImport(specifier, fromDir);
4030
+ if (resolvedPath)
4031
+ resolvedPaths.push(resolvedPath);
4032
+ }
4033
+ return resolvedPaths;
4034
+ }
4035
+ async function loadSiblingFiles(sourceText, sourcePath, propNames, candidateTypeNames = []) {
4036
+ const visited = /* @__PURE__ */ new Set([resolve6(sourcePath)]);
4037
+ const discovered = [];
4038
+ let frontier = [{ text: sourceText, dir: dirname4(sourcePath) }];
4039
+ for (let hop = 0; hop < MAX_SIBLING_DEPTH && discovered.length < MAX_SIBLING_CANDIDATES_EXPLORED; hop++) {
4040
+ const nextFrontier = [];
4041
+ for (const node of frontier) {
4042
+ if (discovered.length >= MAX_SIBLING_CANDIDATES_EXPLORED)
4043
+ break;
4044
+ const resolvedPaths = await resolveImportSpecifiers(node.text, node.dir);
4045
+ for (const resolvedPath of resolvedPaths) {
4046
+ if (visited.has(resolvedPath))
4047
+ continue;
4048
+ visited.add(resolvedPath);
4049
+ if (discovered.length >= MAX_SIBLING_CANDIDATES_EXPLORED)
4050
+ break;
4051
+ let content;
4052
+ try {
4053
+ content = await readFile4(resolvedPath, "utf8");
4054
+ } catch {
4055
+ continue;
4056
+ }
4057
+ discovered.push({ path: resolvedPath, content });
4058
+ nextFrontier.push({ text: content, dir: dirname4(resolvedPath) });
4059
+ }
4060
+ }
4061
+ frontier = nextFrontier;
4062
+ }
4063
+ const inHand = [sourceText, ...discovered.map((d) => d.content)];
4064
+ const declaredTypeNames = candidateTypeNames.filter((name) => inHand.some((text) => declaresAnyType(text, [name])));
4065
+ const usesNotShown = /* @__PURE__ */ new Set();
4066
+ const searchNames = [.../* @__PURE__ */ new Set([...propNames, ...declaredTypeNames])];
4067
+ let enlarged = 0;
4068
+ const siblings = discovered.slice(0, MAX_SIBLING_FILES).map((d) => {
4069
+ const enlarge = enlarged < MAX_ENLARGED_SIBLINGS && declaresAnyType(d.content, declaredTypeNames);
4070
+ if (enlarge)
4071
+ enlarged++;
4072
+ const budget = enlarge ? MAX_TYPE_DECLARING_SIBLING_CHARS : MAX_SIBLING_SNIPPET_CHARS;
4073
+ const excerpt = excerptAroundNames(d.content, searchNames, budget);
4074
+ for (const name of excerpt.usesNotShown)
4075
+ usesNotShown.add(name);
4076
+ return { path: d.path, content: excerpt.content };
4077
+ });
4078
+ const truncatedCount = Math.max(0, discovered.length - MAX_SIBLING_FILES);
4079
+ return {
4080
+ siblings,
4081
+ truncatedCount,
4082
+ usesNotShown: propNames.filter((name) => usesNotShown.has(name)),
4083
+ declaredTypeNames
4084
+ };
4085
+ }
4086
+ async function loadComponentSourceRef(name, sourcePath, propNames = [], propTypes = []) {
4087
+ let content = null;
4088
+ let siblingFiles = [];
4089
+ let truncatedSiblingCount = 0;
4090
+ const usesNotShown = /* @__PURE__ */ new Set();
4091
+ try {
4092
+ const rawText = await readFile4(sourcePath, "utf8");
4093
+ let siblingUsesNotShown;
4094
+ let declaredTypeNames;
4095
+ ({
4096
+ siblings: siblingFiles,
4097
+ truncatedCount: truncatedSiblingCount,
4098
+ usesNotShown: siblingUsesNotShown,
4099
+ declaredTypeNames
4100
+ } = await loadSiblingFiles(rawText, sourcePath, propNames, identifiersIn(propTypes)));
4101
+ const mainExcerpt = excerptAroundNames(rawText, [.../* @__PURE__ */ new Set([...propNames, ...declaredTypeNames])], MAX_COMPONENT_SOURCE_CHARS);
4102
+ content = mainExcerpt.content;
4103
+ for (const name2 of mainExcerpt.usesNotShown)
4104
+ usesNotShown.add(name2);
4105
+ for (const name2 of siblingUsesNotShown)
4106
+ usesNotShown.add(name2);
4107
+ } catch {
4108
+ }
4109
+ const ref = { component: name, sourcePath, content };
4110
+ if (siblingFiles.length > 0)
4111
+ ref.siblingFiles = siblingFiles;
4112
+ if (truncatedSiblingCount > 0)
4113
+ ref.truncatedSiblingCount = truncatedSiblingCount;
4114
+ const notShown = propNames.filter((name2) => usesNotShown.has(name2));
4115
+ if (notShown.length > 0)
4116
+ ref.usesNotShown = notShown;
4117
+ return ref;
4118
+ }
4119
+ async function loadComponentSourceRefs(db, sessionId) {
4120
+ const rows = db.prepare(`SELECT component_id, name, source, source_path FROM raw_components WHERE session_id = ? AND status = 'generated' ORDER BY rowid`).all(sessionId);
4121
+ const propsFor = db.prepare(`SELECT name, type FROM raw_props WHERE session_id = ? AND component_id = ? ORDER BY position`);
4122
+ return Promise.all(rows.map((r) => {
4123
+ const props = propsFor.all(sessionId, r.component_id);
4124
+ return loadComponentSourceRef(r.name, r.source_path ?? r.source, props.map((p) => p.name), props.map((p) => p.type));
4125
+ }));
4126
+ }
4127
+ function renameEmptySlots(db, sessionId, componentId, componentName, slotCount) {
4128
+ const emptySlots = db.prepare(`SELECT name, position FROM raw_slots
4129
+ WHERE session_id = ? AND component_id = ? AND trim(name) = ''
4130
+ ORDER BY position`).all(sessionId, componentId);
4131
+ if (emptySlots.length === 0)
4132
+ return { renames: [], warnings: [] };
4133
+ const renames = [];
4134
+ const warnings = [];
4135
+ const rename3 = db.prepare(`UPDATE raw_slots SET name = ? WHERE session_id = ? AND component_id = ? AND name = ? AND position = ?`);
4136
+ db.exec("BEGIN");
4137
+ try {
4138
+ for (const slot of emptySlots) {
4139
+ const newName = slotCount === 1 ? "children" : `slot_${slot.position}`;
4140
+ rename3.run(newName, sessionId, componentId, slot.name, slot.position);
4141
+ renames.push({ oldName: slot.name, newName });
4142
+ warnings.push(`${componentName}: slot at position ${slot.position} had empty name \u2014 renamed to "${newName}" for classification`);
4143
+ }
4144
+ db.exec("COMMIT");
4145
+ } catch (e) {
4146
+ db.exec("ROLLBACK");
4147
+ throw e;
4148
+ }
4149
+ return { renames, warnings };
4150
+ }
3733
4151
  function parseReviewReasons(raw) {
3734
4152
  try {
3735
4153
  const parsed = JSON.parse(raw ?? "[]");
@@ -3947,29 +4365,10 @@ function applyScopeDecisions(db, sessionId, decisions) {
3947
4365
  const placeholders = accepted.map(() => "?").join(",");
3948
4366
  db.prepare(`UPDATE raw_components SET status = 'generated' WHERE session_id = ? AND name IN (${placeholders})`).run(sessionId, ...accepted);
3949
4367
  }
3950
- removeSlotAllowedComponents(db, sessionId, decisions.excludedSlotEdges ?? [], rejected);
3951
4368
  db.prepare("UPDATE sessions SET updated_at = ? WHERE id = ?").run(now, sessionId);
3952
4369
  }
3953
- function removeSlotAllowedComponents(db, sessionId, edges, rejectedNames) {
3954
- if (edges.length === 0 && rejectedNames.length === 0)
3955
- return;
3956
- const componentId = db.prepare("SELECT component_id FROM raw_components WHERE session_id = ? AND name = ?");
3957
- const removeEdge = db.prepare("DELETE FROM raw_slot_allowed_components WHERE session_id = ? AND component_id = ? AND allowed_component = ?");
3958
- const removeEverywhere = db.prepare("DELETE FROM raw_slot_allowed_components WHERE session_id = ? AND allowed_component = ?");
3959
- db.exec("BEGIN");
3960
- try {
3961
- for (const edge of edges) {
3962
- const row = componentId.get(sessionId, edge.parent);
3963
- if (row)
3964
- removeEdge.run(sessionId, row.component_id, edge.child);
3965
- }
3966
- for (const name of rejectedNames)
3967
- removeEverywhere.run(sessionId, name);
3968
- db.exec("COMMIT");
3969
- } catch (e) {
3970
- db.exec("ROLLBACK");
3971
- throw e;
3972
- }
4370
+ function findLatestSessionForCommand(db, command) {
4371
+ return getLatestCompletedSessionForCommand(db, command);
3973
4372
  }
3974
4373
  function seedCDFFromPreviewResponse(db, sessionId, removedItems) {
3975
4374
  if (removedItems.length === 0)
@@ -4038,6 +4437,35 @@ function backfillUnclassifiedProps(db, sessionId) {
4038
4437
  )`).run(sessionId, sessionId);
4039
4438
  return Number(withCategory.changes) + Number(withoutCategory.changes);
4040
4439
  }
4440
+ function computeMapTokensInputHash(db, sessionId, componentSourceRefs = []) {
4441
+ const props = db.prepare(`SELECT rc.name AS component_name, rp.name AS prop_name, rp.cdf_token_kind, rp.default_value
4442
+ FROM raw_props rp
4443
+ JOIN raw_components rc ON rc.session_id = rp.session_id AND rc.component_id = rp.component_id
4444
+ WHERE rp.session_id = ? AND rp.cdf_type = 'token' AND rp.cdf_category = 'design'
4445
+ ORDER BY rc.name, rp.name`).all(sessionId);
4446
+ const tokens = db.prepare(`SELECT path, type FROM raw_tokens WHERE session_id = ? ORDER BY path`).all(sessionId);
4447
+ const defaultMappings = db.prepare("SELECT raw_name, path, source FROM raw_token_name_paths WHERE session_id = ? ORDER BY raw_name").all(sessionId);
4448
+ const payload = {
4449
+ props: props.map((p) => ({
4450
+ component: p.component_name,
4451
+ prop: p.prop_name,
4452
+ tokenKind: p.cdf_token_kind,
4453
+ rawDefault: p.default_value
4454
+ })),
4455
+ tokens,
4456
+ defaultMappings,
4457
+ // The agent's evidence, not just its inputs: a comment or allowlist edit
4458
+ // in a source file (or a sibling it reads) changes the correct answer
4459
+ // without touching props or tokens, so it must invalidate the cache too.
4460
+ sourceRefs: [...componentSourceRefs].sort((a, b) => a.component.localeCompare(b.component)).map((ref) => ({
4461
+ component: ref.component,
4462
+ content: ref.content,
4463
+ siblingFiles: (ref.siblingFiles ?? []).map((s) => ({ path: s.path, content: s.content })).sort((a, b) => a.path.localeCompare(b.path)),
4464
+ usesNotShown: [...ref.usesNotShown ?? []].sort()
4465
+ }))
4466
+ };
4467
+ return createHash5("sha256").update(JSON.stringify(payload)).digest("hex");
4468
+ }
4041
4469
  function lookupCache(db, inputHash, entityType, entityId, promptHash = "") {
4042
4470
  const row = db.prepare(`SELECT input_hash, entity_type, entity_id, source_session_id, human_edited, created_at, updated_at, prompt_hash
4043
4471
  FROM generation_cache
@@ -4055,6 +4483,24 @@ function lookupCache(db, inputHash, entityType, entityId, promptHash = "") {
4055
4483
  updatedAt: row.updated_at
4056
4484
  };
4057
4485
  }
4486
+ function lookupCacheByEntity(db, entityType, entityId) {
4487
+ const row = db.prepare(`SELECT input_hash, entity_type, entity_id, source_session_id, human_edited, created_at, updated_at, prompt_hash
4488
+ FROM generation_cache
4489
+ WHERE entity_type = ? AND entity_id = ?
4490
+ ORDER BY updated_at DESC LIMIT 1`).get(entityType, entityId);
4491
+ if (!row)
4492
+ return null;
4493
+ return {
4494
+ inputHash: row.input_hash,
4495
+ entityType: row.entity_type,
4496
+ entityId: row.entity_id,
4497
+ sourceSessionId: row.source_session_id,
4498
+ humanEdited: row.human_edited === 1,
4499
+ promptHash: row.prompt_hash,
4500
+ createdAt: row.created_at,
4501
+ updatedAt: row.updated_at
4502
+ };
4503
+ }
4058
4504
  function storeCache(db, inputHash, entityType, entityId, sourceSessionId, humanEdited, promptHash = "") {
4059
4505
  storeCaches(db, [{ inputHash, entityType, entityId, sourceSessionId, humanEdited, promptHash }]);
4060
4506
  }
@@ -4117,6 +4563,95 @@ function loadSlotCycles(db, sessionId) {
4117
4563
  suggestedBreak: r.suggested_break_json ? JSON.parse(r.suggested_break_json) : null
4118
4564
  }));
4119
4565
  }
4566
+ function findUnknownSlotAllowedComponents(db, sessionId, allowedComponentNames2, componentId) {
4567
+ const rows = db.prepare(`SELECT a.component_id, c.name AS component_name, a.slot_name, a.allowed_component
4568
+ FROM raw_slot_allowed_components a
4569
+ JOIN raw_components c ON c.session_id = a.session_id AND c.component_id = a.component_id
4570
+ WHERE a.session_id = ? AND (? IS NULL OR a.component_id = ?)
4571
+ ORDER BY a.component_id, a.slot_name, a.position`).all(sessionId, componentId ?? null, componentId ?? null);
4572
+ return rows.filter((row) => !allowedComponentNames2.has(row.allowed_component)).map((row) => ({
4573
+ componentId: row.component_id,
4574
+ componentName: row.component_name,
4575
+ slotName: row.slot_name,
4576
+ allowedComponent: row.allowed_component
4577
+ }));
4578
+ }
4579
+ function filterUnknownSlotAllowedComponents(db, sessionId, allowedComponentNames2) {
4580
+ const unknown5 = findUnknownSlotAllowedComponents(db, sessionId, allowedComponentNames2);
4581
+ if (unknown5.length === 0)
4582
+ return unknown5;
4583
+ db.exec("BEGIN");
4584
+ try {
4585
+ const remove = db.prepare(`DELETE FROM raw_slot_allowed_components
4586
+ WHERE session_id = ? AND component_id = ? AND slot_name = ? AND allowed_component = ?`);
4587
+ for (const row of unknown5) {
4588
+ remove.run(sessionId, row.componentId, row.slotName, row.allowedComponent);
4589
+ }
4590
+ db.exec("COMMIT");
4591
+ } catch (e) {
4592
+ db.exec("ROLLBACK");
4593
+ throw e;
4594
+ }
4595
+ return unknown5;
4596
+ }
4597
+ function copyComponentFromCache(db, sourceSessionId, targetSessionId, componentId, manageTransaction = true, options = {}) {
4598
+ const now = (/* @__PURE__ */ new Date()).toISOString();
4599
+ if (manageTransaction)
4600
+ db.exec("BEGIN");
4601
+ try {
4602
+ const srcComp = db.prepare(`SELECT description, status, component_description_rationale, props_rationale, slots_rationale
4603
+ FROM raw_components WHERE session_id = ? AND component_id = ?`).get(sourceSessionId, componentId);
4604
+ if (srcComp) {
4605
+ db.prepare(`UPDATE raw_components
4606
+ SET description = ?, status = ?, component_description_rationale = ?, props_rationale = ?, slots_rationale = ?, extracted_at = ?
4607
+ WHERE session_id = ? AND component_id = ?`).run(srcComp.description, srcComp.status, srcComp.component_description_rationale, srcComp.props_rationale, srcComp.slots_rationale, now, targetSessionId, componentId);
4608
+ }
4609
+ const srcProps = db.prepare(`SELECT name, cdf_type, cdf_category, cdf_token_kind, required, description, default_value, rationale
4610
+ FROM raw_props WHERE session_id = ? AND component_id = ?`).all(sourceSessionId, componentId);
4611
+ for (const p of srcProps) {
4612
+ db.prepare(`UPDATE raw_props SET cdf_type = ?, cdf_category = ?, cdf_token_kind = ?, required = ?, description = ?, default_value = ?, rationale = ?
4613
+ WHERE session_id = ? AND component_id = ? AND name = ?`).run(p.cdf_type, p.cdf_category, p.cdf_token_kind, p.required, p.description, p.default_value, p.rationale, targetSessionId, componentId, p.name);
4614
+ }
4615
+ db.prepare(`DELETE FROM raw_prop_allowed_values WHERE session_id = ? AND component_id = ?`).run(targetSessionId, componentId);
4616
+ const srcAV = db.prepare(`SELECT prop_name, position, value FROM raw_prop_allowed_values WHERE session_id = ? AND component_id = ?`).all(sourceSessionId, componentId);
4617
+ const insertAV = db.prepare(`INSERT INTO raw_prop_allowed_values (session_id, component_id, prop_name, position, value) VALUES (?, ?, ?, ?, ?)`);
4618
+ for (const av of srcAV) {
4619
+ insertAV.run(targetSessionId, componentId, av.prop_name, av.position, av.value);
4620
+ }
4621
+ const srcSlots = db.prepare(`SELECT name, required, description, rationale FROM raw_slots WHERE session_id = ? AND component_id = ?`).all(sourceSessionId, componentId);
4622
+ for (const s of srcSlots) {
4623
+ db.prepare(`UPDATE raw_slots SET required = ?, description = ?, rationale = ? WHERE session_id = ? AND component_id = ? AND name = ?`).run(s.required, s.description, s.rationale, targetSessionId, componentId, s.name);
4624
+ }
4625
+ db.prepare(`DELETE FROM raw_slot_allowed_components WHERE session_id = ? AND component_id = ?`).run(targetSessionId, componentId);
4626
+ const srcSAC = db.prepare(`SELECT slot_name, position, allowed_component FROM raw_slot_allowed_components WHERE session_id = ? AND component_id = ?`).all(sourceSessionId, componentId);
4627
+ const insertSAC = db.prepare(`INSERT INTO raw_slot_allowed_components (session_id, component_id, slot_name, allowed_component, position) VALUES (?, ?, ?, ?, ?)`);
4628
+ const allowedSAC = options.allowedComponentNames ? srcSAC.filter((sac) => options.allowedComponentNames.has(sac.allowed_component)) : srcSAC;
4629
+ for (const sac of allowedSAC) {
4630
+ insertSAC.run(targetSessionId, componentId, sac.slot_name, sac.allowed_component, sac.position);
4631
+ }
4632
+ db.prepare("UPDATE sessions SET updated_at = ? WHERE id = ?").run(now, targetSessionId);
4633
+ if (manageTransaction)
4634
+ db.exec("COMMIT");
4635
+ } catch (e) {
4636
+ if (manageTransaction)
4637
+ db.exec("ROLLBACK");
4638
+ throw e;
4639
+ }
4640
+ }
4641
+ function copyComponentsFromCache(db, entries, options = {}) {
4642
+ if (entries.length === 0)
4643
+ return;
4644
+ db.exec("BEGIN");
4645
+ try {
4646
+ for (const entry of entries) {
4647
+ copyComponentFromCache(db, entry.sourceSessionId, entry.targetSessionId, entry.componentId, false, options);
4648
+ }
4649
+ db.exec("COMMIT");
4650
+ } catch (e) {
4651
+ db.exec("ROLLBACK");
4652
+ throw e;
4653
+ }
4654
+ }
4120
4655
  function copyTokensFromCache(db, sourceSessionId, targetSessionId) {
4121
4656
  const now = (/* @__PURE__ */ new Date()).toISOString();
4122
4657
  db.exec("BEGIN");
@@ -4134,18 +4669,58 @@ function copyTokensFromCache(db, sourceSessionId, targetSessionId) {
4134
4669
  throw e;
4135
4670
  }
4136
4671
  }
4672
+ function copyMapTokensFromCache(db, sourceSessionId, targetSessionId) {
4673
+ const now = (/* @__PURE__ */ new Date()).toISOString();
4674
+ let copiedCount = 0;
4675
+ db.exec("BEGIN");
4676
+ try {
4677
+ const sourceRows = db.prepare(`SELECT rc.name AS component_name, rptp.prop_name, rptp.source, rptp.position, rptp.path
4678
+ FROM raw_prop_token_paths rptp
4679
+ JOIN raw_components rc ON rc.session_id = rptp.session_id AND rc.component_id = rptp.component_id
4680
+ WHERE rptp.session_id = ?
4681
+ ORDER BY rc.name, rptp.prop_name, rptp.position`).all(sourceSessionId);
4682
+ const targetComponents = db.prepare(`SELECT component_id, name FROM raw_components WHERE session_id = ?`).all(targetSessionId);
4683
+ const targetIdByName = new Map(targetComponents.map((c2) => [c2.name, c2.component_id]));
4684
+ const targetProps = new Set(db.prepare(`SELECT component_id, name FROM raw_props WHERE session_id = ?`).all(targetSessionId).map((p) => `${p.component_id}::${p.name}`));
4685
+ const insertPath = db.prepare(`INSERT INTO raw_prop_token_paths (session_id, component_id, prop_name, source, position, path)
4686
+ VALUES (?, ?, ?, ?, ?, ?)`);
4687
+ const clearedProps = /* @__PURE__ */ new Set();
4688
+ const copiedProps = /* @__PURE__ */ new Set();
4689
+ for (const row of sourceRows) {
4690
+ const targetComponentId = targetIdByName.get(row.component_name);
4691
+ if (!targetComponentId)
4692
+ continue;
4693
+ if (!targetProps.has(`${targetComponentId}::${row.prop_name}`))
4694
+ continue;
4695
+ const propKey = `${targetComponentId}::${row.prop_name}`;
4696
+ if (!clearedProps.has(propKey)) {
4697
+ clearedProps.add(propKey);
4698
+ db.prepare(`DELETE FROM raw_prop_token_paths WHERE session_id = ? AND component_id = ? AND prop_name = ?`).run(targetSessionId, targetComponentId, row.prop_name);
4699
+ }
4700
+ insertPath.run(targetSessionId, targetComponentId, row.prop_name, row.source, row.position, row.path);
4701
+ copiedProps.add(propKey);
4702
+ }
4703
+ copiedCount = copiedProps.size;
4704
+ db.prepare("UPDATE sessions SET updated_at = ? WHERE id = ?").run(now, targetSessionId);
4705
+ db.exec("COMMIT");
4706
+ } catch (e) {
4707
+ db.exec("ROLLBACK");
4708
+ throw e;
4709
+ }
4710
+ return copiedCount;
4711
+ }
4137
4712
  var _cliCacheVersionCache = null;
4138
4713
  async function getCliCacheVersion() {
4139
4714
  if (_cliCacheVersionCache)
4140
4715
  return _cliCacheVersionCache;
4141
4716
  try {
4142
4717
  const { hashContent: hashContent3 } = await Promise.resolve().then(() => (init_cache_keys(), cache_keys_exports));
4143
- const { resolveSkillPath: resolveSkillPath3 } = await Promise.resolve().then(() => (init_agents(), agents_exports));
4718
+ const { resolveSkillPath: resolveSkillPath2 } = await Promise.resolve().then(() => (init_agents(), agents_exports));
4144
4719
  const skills = ["components", "tokens", "select"];
4145
4720
  const parts = [];
4146
4721
  for (const s of skills) {
4147
4722
  try {
4148
- const p = resolveSkillPath3(s);
4723
+ const p = resolveSkillPath2(s);
4149
4724
  parts.push(readFileSync3(p, "utf8"));
4150
4725
  } catch {
4151
4726
  parts.push(`<missing:${s}>`);
@@ -4625,7 +5200,7 @@ function findNearestPackageRootDir(filePath) {
4625
5200
  }
4626
5201
 
4627
5202
  // packages/experience-design-system-backend-pipeline/dist/src/steps/extraction/src/framework-adapters/shared/file-extraction-workers.js
4628
- import { readFile as readFile4 } from "node:fs/promises";
5203
+ import { readFile as readFile5 } from "node:fs/promises";
4629
5204
  async function runFileExtractionWorkers(filePaths, concurrency, extractFile, formatError, onProgress, onResult) {
4630
5205
  const warnings = [];
4631
5206
  const items = [];
@@ -4637,7 +5212,7 @@ async function runFileExtractionWorkers(filePaths, concurrency, extractFile, for
4637
5212
  if (!filePath)
4638
5213
  break;
4639
5214
  try {
4640
- const source = await readFile4(filePath, "utf-8");
5215
+ const source = await readFile5(filePath, "utf-8");
4641
5216
  const outcome = await extractFile(filePath, source);
4642
5217
  warnings.push(...outcome.warnings ?? []);
4643
5218
  if (outcome.item)
@@ -7613,7 +8188,7 @@ function extractVueSlotsFromSetup(options) {
7613
8188
  // packages/experience-design-system-backend-pipeline/dist/src/steps/extraction/src/framework-adapters/vue/extract-vue-components.js
7614
8189
  import os from "node:os";
7615
8190
  import { basename, dirname as dirname7, resolve as resolve9, join as join7 } from "node:path";
7616
- import { readFile as readFile5 } from "node:fs/promises";
8191
+ import { readFile as readFile6 } from "node:fs/promises";
7617
8192
  import { existsSync as existsSync5, readFileSync as readFileSync5, readdirSync, statSync as statSync3 } from "node:fs";
7618
8193
  import { parse as parseSFC } from "@vue/compiler-sfc";
7619
8194
  import { Project as Project3, Node as Node6 } from "ts-morph";
@@ -7855,7 +8430,7 @@ async function extractNamedObjectExportProps(importedRef, visitedImports) {
7855
8430
  if (visitedImports.has(visitKey))
7856
8431
  return [];
7857
8432
  visitedImports.add(visitKey);
7858
- const source = await readFile5(importedRef.filePath, "utf-8");
8433
+ const source = await readFile6(importedRef.filePath, "utf-8");
7859
8434
  const project = new Project3({
7860
8435
  compilerOptions: {
7861
8436
  strict: false,
@@ -8086,7 +8661,7 @@ async function extractOptionsProps(filePath, scriptContent, visited = /* @__PURE
8086
8661
  return [];
8087
8662
  }
8088
8663
  async function extractInheritedVueProps(filePath, visited) {
8089
- const source = await readFile5(filePath, "utf-8");
8664
+ const source = await readFile6(filePath, "utf-8");
8090
8665
  const { descriptor } = parseSFC(source);
8091
8666
  if (!descriptor.script) {
8092
8667
  return [];
@@ -11252,9 +11827,9 @@ function capCandidatesToPromptBudget(files, budget = PROMPT_CANDIDATE_TOKEN_BUDG
11252
11827
  }
11253
11828
 
11254
11829
  // packages/experience-design-system-backend-pipeline/dist/src/steps/composition/src/helpers/candidates/composition-cache-key.js
11255
- import { createHash as createHash5 } from "node:crypto";
11830
+ import { createHash as createHash6 } from "node:crypto";
11256
11831
  function hashContent2(content) {
11257
- return createHash5("sha256").update(content).digest("hex");
11832
+ return createHash6("sha256").update(content).digest("hex");
11258
11833
  }
11259
11834
  function buildCompositionInputHash(input) {
11260
11835
  const fileDigest = input.files.map((f) => `${f.path} ${hashContent2(f.content)}`).sort().join("");
@@ -11656,9 +12231,9 @@ function validateExtractedComponents(components) {
11656
12231
  import { resolve as resolve14 } from "node:path";
11657
12232
 
11658
12233
  // packages/experience-design-system-backend-pipeline/dist/src/persistence/src/review-session/helpers/create-component-id.js
11659
- import { createHash as createHash6 } from "node:crypto";
12234
+ import { createHash as createHash7 } from "node:crypto";
11660
12235
  function createComponentId(name, resolvedSourcePath) {
11661
- const sourceHash = createHash6("sha256").update(`${name}:${resolvedSourcePath}`).digest("hex").slice(0, 12);
12236
+ const sourceHash = createHash7("sha256").update(`${name}:${resolvedSourcePath}`).digest("hex").slice(0, 12);
11662
12237
  return `${name}-${sourceHash}`;
11663
12238
  }
11664
12239
 
@@ -11724,10 +12299,10 @@ async function loadAndValidateForReview(sessionId, projectRoot) {
11724
12299
  }
11725
12300
 
11726
12301
  // packages/experience-design-system-backend-pipeline/dist/src/steps/selection/src/controller/review/merge-preview-validation-errors-into-review-session.js
11727
- import { access as access3, readFile as readFile7 } from "node:fs/promises";
12302
+ import { access as access3, readFile as readFile8 } from "node:fs/promises";
11728
12303
 
11729
12304
  // packages/experience-design-system-backend-pipeline/dist/src/persistence/src/review-session/repositories/ensure-review-session.js
11730
- import { access as access2, mkdir, readFile as readFile6, writeFile } from "node:fs/promises";
12305
+ import { access as access2, mkdir, readFile as readFile7, writeFile } from "node:fs/promises";
11731
12306
 
11732
12307
  // packages/experience-design-system-backend-pipeline/dist/src/persistence/src/review-session/repositories/review-session-paths.js
11733
12308
  import { resolve as resolve15 } from "node:path";
@@ -11746,7 +12321,7 @@ async function ensureRefineSession(sessionId, artifactsRoot, initialSnapshot) {
11746
12321
  await mkdir(paths.sessionDir, { recursive: true });
11747
12322
  try {
11748
12323
  await access2(paths.statePath);
11749
- const savedState = await readFile6(paths.statePath, "utf8");
12324
+ const savedState = await readFile7(paths.statePath, "utf8");
11750
12325
  return JSON.parse(savedState);
11751
12326
  } catch {
11752
12327
  await writeFile(paths.statePath, JSON.stringify(initialSnapshot, null, 2), "utf8");
@@ -11777,7 +12352,7 @@ async function mergePreviewValidationErrorsIntoReviewSession(sessionId, errors,
11777
12352
  let snapshot;
11778
12353
  try {
11779
12354
  await access3(paths.statePath);
11780
- snapshot = JSON.parse(await readFile7(paths.statePath, "utf8"));
12355
+ snapshot = JSON.parse(await readFile8(paths.statePath, "utf8"));
11781
12356
  } catch {
11782
12357
  snapshot = await loadAndValidateForReview(sessionId, void 0);
11783
12358
  snapshot = await ensureRefineSession(sessionId, artifactsRoot, snapshot);
@@ -11815,7 +12390,7 @@ async function mergePreviewValidationErrorsIntoReviewSession(sessionId, errors,
11815
12390
  }
11816
12391
 
11817
12392
  // packages/experience-design-system-backend-pipeline/dist/src/steps/selection/src/controller/review/reject-components-by-name.js
11818
- import { readFile as readFile8 } from "node:fs/promises";
12393
+ import { readFile as readFile9 } from "node:fs/promises";
11819
12394
  async function rejectComponentsByName(sessionId, names, opts = {}) {
11820
12395
  if (names.length === 0)
11821
12396
  return;
@@ -11831,7 +12406,7 @@ async function rejectComponentsByName(sessionId, names, opts = {}) {
11831
12406
  const nameSet = new Set(names);
11832
12407
  let snapshot;
11833
12408
  try {
11834
- snapshot = JSON.parse(await readFile8(paths.statePath, "utf8"));
12409
+ snapshot = JSON.parse(await readFile9(paths.statePath, "utf8"));
11835
12410
  } catch {
11836
12411
  return;
11837
12412
  }
@@ -12083,7 +12658,7 @@ function generateUlid(now = Date.now()) {
12083
12658
  }
12084
12659
 
12085
12660
  // packages/experience-design-system-backend-pipeline/dist/src/persistence/src/runs/repositories/read-runs-file.js
12086
- import { readFile as readFile9 } from "node:fs/promises";
12661
+ import { readFile as readFile10 } from "node:fs/promises";
12087
12662
 
12088
12663
  // packages/experience-design-system-backend-pipeline/dist/src/persistence/src/runs/helpers/migrate-record.js
12089
12664
  function migrateRecord(rec) {
@@ -12102,7 +12677,7 @@ var READABLE_VERSIONS = /* @__PURE__ */ new Set([1, 2, 3]);
12102
12677
  // packages/experience-design-system-backend-pipeline/dist/src/persistence/src/runs/repositories/read-runs-file.js
12103
12678
  async function readRunsFileMaybe() {
12104
12679
  try {
12105
- const raw = await readFile9(runsFilePath(), "utf8");
12680
+ const raw = await readFile10(runsFilePath(), "utf8");
12106
12681
  const parsed = JSON.parse(raw);
12107
12682
  if (!READABLE_VERSIONS.has(parsed.version)) {
12108
12683
  throw new Error(`runs.json version mismatch: file is v${parsed.version}, this CLI expects v${RUNS_FILE_VERSION} (also reads: ${[...READABLE_VERSIONS].join(", ")}). Back up and remove the file to start fresh.`);
@@ -12161,13 +12736,13 @@ async function updateRun(id, patch) {
12161
12736
  }
12162
12737
 
12163
12738
  // packages/experience-design-system-backend-pipeline/dist/src/persistence/src/runs/services/build-source-fingerprint.js
12164
- import { readFile as readFile10, stat } from "node:fs/promises";
12739
+ import { readFile as readFile11, stat } from "node:fs/promises";
12165
12740
  import { resolve as resolve17 } from "node:path";
12166
12741
 
12167
12742
  // packages/experience-design-system-backend-pipeline/dist/src/persistence/src/runs/helpers/sha256-hex.js
12168
- import { createHash as createHash7 } from "node:crypto";
12743
+ import { createHash as createHash8 } from "node:crypto";
12169
12744
  function sha256Hex(buf) {
12170
- return createHash7("sha256").update(buf).digest("hex");
12745
+ return createHash8("sha256").update(buf).digest("hex");
12171
12746
  }
12172
12747
 
12173
12748
  // packages/experience-design-system-backend-pipeline/dist/src/persistence/src/runs/services/build-source-fingerprint.js
@@ -12204,7 +12779,7 @@ async function buildSourceFingerprint(opts) {
12204
12779
  const abs = resolve17(opts.rawTokensPath);
12205
12780
  rawTokensPath = abs;
12206
12781
  try {
12207
- const [st, buf] = await Promise.all([stat(abs), readFile10(abs)]);
12782
+ const [st, buf] = await Promise.all([stat(abs), readFile11(abs)]);
12208
12783
  rawTokensMtime = st.mtime.toISOString();
12209
12784
  rawTokensContentHash = sha256Hex(buf);
12210
12785
  } catch {
@@ -12285,6 +12860,23 @@ async function writeScopeDecisionsSnapshot(db, sessionId, decisions) {
12285
12860
  await saveReviewState(paths.statePath, { components: records });
12286
12861
  }
12287
12862
 
12863
+ // packages/experience-design-system-backend-pipeline/dist/src/persistence/src/review-session/repositories/load-accepted-names.js
12864
+ import { readFile as readFile12 } from "node:fs/promises";
12865
+ async function loadAcceptedNames(sessionId) {
12866
+ try {
12867
+ const artifactsRoot = getRefineArtifactsRoot();
12868
+ const paths = await getRefineSessionPaths(sessionId, artifactsRoot);
12869
+ const raw = await readFile12(paths.statePath, "utf8");
12870
+ const snapshot = JSON.parse(raw);
12871
+ const accepted = snapshot.components.filter((c2) => c2.status === "accepted").map((c2) => c2.name);
12872
+ if (accepted.length === 0)
12873
+ return null;
12874
+ return new Set(accepted);
12875
+ } catch {
12876
+ return null;
12877
+ }
12878
+ }
12879
+
12288
12880
  // packages/experience-design-system-backend-pipeline/dist/src/persistence/src/session/index.js
12289
12881
  import { DatabaseSync as DatabaseSync2 } from "node:sqlite";
12290
12882
 
@@ -12918,7 +13510,7 @@ function errorMessage(error) {
12918
13510
  return error instanceof Error && error.message ? error.message : String(error);
12919
13511
  }
12920
13512
  function defaultSleep(delayMs) {
12921
- return new Promise((resolve22) => setTimeout(resolve22, delayMs));
13513
+ return new Promise((resolve25) => setTimeout(resolve25, delayMs));
12922
13514
  }
12923
13515
 
12924
13516
  // packages/experience-design-system-backend-pipeline/dist/src/steps/apply/src/helpers/sanitize-preview.js
@@ -13159,7 +13751,7 @@ var ApiClient = class {
13159
13751
  const progress = maxAttempts > 1 ? attempt / (maxAttempts - 1) : 0;
13160
13752
  const baseDelay = intervalMs + (maxIntervalMs - intervalMs) * progress;
13161
13753
  const jitter = Math.random() * baseDelay * 0.15;
13162
- await new Promise((resolve22) => setTimeout(resolve22, baseDelay + jitter));
13754
+ await new Promise((resolve25) => setTimeout(resolve25, baseDelay + jitter));
13163
13755
  }
13164
13756
  }
13165
13757
  throw new Error(`Operation ${operationId} timed out after ${maxAttempts} attempts`);
@@ -13546,7 +14138,7 @@ function formatApiError2(request) {
13546
14138
 
13547
14139
  // packages/experience-design-system-backend-pipeline/dist/src/steps/apply/src/helpers/tokens/read-tokens-from-path.js
13548
14140
  init_shared();
13549
- import { readFile as readFile11, stat as stat3 } from "node:fs/promises";
14141
+ import { readFile as readFile13, stat as stat3 } from "node:fs/promises";
13550
14142
 
13551
14143
  // packages/experience-design-system-backend-pipeline/dist/src/steps/apply/src/helpers/tokens/collect-json-files.js
13552
14144
  import { readdir, stat as stat2 } from "node:fs/promises";
@@ -13605,7 +14197,7 @@ async function readMergedFromDir(flag, dir) {
13605
14197
  const merged = {};
13606
14198
  for (const file of files.sort()) {
13607
14199
  try {
13608
- const text = await readFile11(file, "utf8");
14200
+ const text = await readFile13(file, "utf8");
13609
14201
  const parsed = JSON.parse(text);
13610
14202
  if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
13611
14203
  Object.assign(merged, parsed);
@@ -13619,7 +14211,7 @@ async function readMergedFromDir(flag, dir) {
13619
14211
  async function readSingleFile(flag, p) {
13620
14212
  let text;
13621
14213
  try {
13622
- text = await readFile11(p, "utf8");
14214
+ text = await readFile13(p, "utf8");
13623
14215
  } catch {
13624
14216
  throw new Error(`file not found: ${p} (from ${flag})`);
13625
14217
  }
@@ -13708,29 +14300,522 @@ async function fetchAndPersistExistingContentfulEntities(request) {
13708
14300
  }
13709
14301
  }
13710
14302
 
13711
- // packages/experience-design-system-backend-pipeline/dist/src/steps/apply/src/controller/endpoint/resolve-shared-inputs.js
13712
- init_validate();
13713
-
13714
- // packages/experience-design-system-backend-pipeline/dist/src/steps/generation/src/controller/map-tokens/run-map-tokens.js
13715
- init_build_prompt();
13716
- init_create_local_cli_agent_invoker();
13717
- init_describe_agent_failure();
13718
- init_resolve_binary();
13719
- init_resolve_skill_path();
13720
- init_parse_map_token_prop_tool_calls();
13721
- init_cache_keys();
13722
-
13723
- // packages/experience-design-system-backend-pipeline/dist/src/agents/helpers/resolution/binary-exists.js
13724
- import { execFile } from "node:child_process";
13725
- import { promisify } from "node:util";
13726
- var execFileAsync = promisify(execFile);
14303
+ // packages/experience-design-system-backend-pipeline/dist/src/steps/generation/src/controller/existing-entities/read-from-session.js
14304
+ import { readFile as readFile14 } from "node:fs/promises";
14305
+ async function readExistingContentfulEntitiesFromSession(request) {
14306
+ if (!request.path)
14307
+ return void 0;
14308
+ try {
14309
+ const raw = await readFile14(request.path, "utf8");
14310
+ const parsed = JSON.parse(raw);
14311
+ if (!Array.isArray(parsed.components) || !Array.isArray(parsed.tokens))
14312
+ return void 0;
14313
+ return parsed;
14314
+ } catch {
14315
+ return void 0;
14316
+ }
14317
+ }
13727
14318
 
13728
- // packages/experience-design-system-backend-pipeline/dist/src/steps/generation/src/controller/map-tokens/run-map-tokens.js
13729
- var DEFAULT_TIMEOUT_MS2 = 5 * 60 * 1e3;
14319
+ // packages/experience-design-system-backend-pipeline/dist/src/steps/generation/src/helpers/summarizers/summarize-tokens.js
14320
+ function summarizeTokens(tokens) {
14321
+ const kinds = /* @__PURE__ */ new Set();
14322
+ for (const t of tokens)
14323
+ kinds.add(t.type);
14324
+ return { count: tokens.length, kinds: [...kinds].sort() };
14325
+ }
13730
14326
 
13731
- // packages/experience-design-system-backend-pipeline/dist/src/orchestrators/run-extract-and-compose-session/run-extract-and-compose-session.js
13732
- import { mkdir as mkdir4 } from "node:fs/promises";
13733
- import { relative as relative2 } from "node:path";
14327
+ // packages/experience-design-system-backend-pipeline/dist/src/steps/generation/src/helpers/existing-entities/count-character-edits.js
14328
+ function countCharacterEdits(a, b) {
14329
+ if (a === b)
14330
+ return 0;
14331
+ if (a.length === 0)
14332
+ return b.length;
14333
+ if (b.length === 0)
14334
+ return a.length;
14335
+ if (a.length > b.length)
14336
+ [a, b] = [b, a];
14337
+ let prev = new Array(a.length + 1);
14338
+ let curr = new Array(a.length + 1);
14339
+ for (let i = 0; i <= a.length; i++)
14340
+ prev[i] = i;
14341
+ for (let j = 1; j <= b.length; j++) {
14342
+ curr[0] = j;
14343
+ for (let i = 1; i <= a.length; i++) {
14344
+ const cost = a[i - 1] === b[j - 1] ? 0 : 1;
14345
+ curr[i] = Math.min(curr[i - 1] + 1, prev[i] + 1, prev[i - 1] + cost);
14346
+ }
14347
+ [prev, curr] = [curr, prev];
14348
+ }
14349
+ return prev[a.length];
14350
+ }
14351
+
14352
+ // packages/experience-design-system-backend-pipeline/dist/src/steps/generation/src/helpers/existing-entities/simplify-name-for-comparison.js
14353
+ function simplifyNameForComparison(name) {
14354
+ const stripped = name.toLowerCase().replace(/[^a-z0-9]/g, "");
14355
+ return stripped.endsWith("s") && stripped.length > 1 ? stripped.slice(0, -1) : stripped;
14356
+ }
14357
+
14358
+ // packages/experience-design-system-backend-pipeline/dist/src/steps/generation/src/helpers/existing-entities/find-nearly-matching-component.js
14359
+ var MAX_CHARACTER_EDITS_FOR_LIKELY_MATCH = 2;
14360
+ function findNearlyMatchingComponent(components, codebaseName) {
14361
+ const target = simplifyNameForComparison(codebaseName);
14362
+ if (!target)
14363
+ return void 0;
14364
+ let best;
14365
+ for (const c2 of components) {
14366
+ const edits = countCharacterEdits(target, simplifyNameForComparison(c2.name));
14367
+ if (edits > MAX_CHARACTER_EDITS_FOR_LIKELY_MATCH)
14368
+ continue;
14369
+ if (!best || edits < best.edits)
14370
+ best = { component: c2, edits };
14371
+ if (edits === 0)
14372
+ break;
14373
+ }
14374
+ return best?.component;
14375
+ }
14376
+
14377
+ // packages/experience-design-system-backend-pipeline/dist/src/steps/generation/src/controller/existing-entities/summarize-for-generate.js
14378
+ function summarizeForGenerateAgent(entities, codebaseComponentName) {
14379
+ const match2 = findNearlyMatchingComponent(entities.components, codebaseComponentName);
14380
+ const otherComponents = entities.components.filter((c2) => c2.sys.id !== match2?.sys.id).map((c2) => ({ id: c2.sys.id, name: c2.name }));
14381
+ return {
14382
+ likelyMatch: match2 ? {
14383
+ id: match2.sys.id,
14384
+ name: match2.name,
14385
+ designProperties: match2.designProperties.map((p) => ({
14386
+ id: p.id,
14387
+ name: p.name,
14388
+ type: p.type
14389
+ })),
14390
+ contentProperties: match2.contentProperties.map((p) => ({
14391
+ id: p.id,
14392
+ name: p.name,
14393
+ type: p.type
14394
+ })),
14395
+ slots: (match2.slots ?? []).map((s) => ({ id: s.id, name: s.name }))
14396
+ } : void 0,
14397
+ otherComponents,
14398
+ tokens: summarizeTokens(entities.tokens)
14399
+ };
14400
+ }
14401
+
14402
+ // packages/experience-design-system-backend-pipeline/dist/src/steps/generation/src/controller/existing-entities/summarize-for-map-tokens.js
14403
+ function summarizeForMapTokens(request) {
14404
+ return {
14405
+ tokens: request.entities.tokens.map((t) => ({ id: t.sys.id, name: t.name, type: t.type }))
14406
+ };
14407
+ }
14408
+
14409
+ // packages/experience-design-system-backend-pipeline/dist/src/steps/generation/src/helpers/token-defaults/normalize-token-key.js
14410
+ function normalizeTokenKey(key) {
14411
+ return key.replace(/([a-z0-9])([A-Z])/g, "$1-$2").replace(/([A-Z])([A-Z][a-z])/g, "$1-$2").replace(/[ _]+/g, "-").toLowerCase();
14412
+ }
14413
+
14414
+ // packages/experience-design-system-backend-pipeline/dist/src/steps/generation/src/helpers/token-defaults/terminal-member.js
14415
+ function terminalMember(reference) {
14416
+ if (!/^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)+$/.test(reference))
14417
+ return void 0;
14418
+ return reference.slice(reference.lastIndexOf(".") + 1);
14419
+ }
14420
+
14421
+ // packages/experience-design-system-backend-pipeline/dist/src/steps/generation/src/helpers/token-defaults/resolve-token-defaults.js
14422
+ function describeType(tokenKind) {
14423
+ return tokenKind === null ? "the property type" : `a ${tokenKind} token`;
14424
+ }
14425
+ function resolveTokenDefaults(defaults, leaves) {
14426
+ const leavesByPath = new Map(leaves.map((leaf) => [leaf.path, leaf]));
14427
+ const leavesByNormalizedKey = buildNormalizedIndex(leaves);
14428
+ const outcomesByRawDefault = /* @__PURE__ */ new Map();
14429
+ const diagnostics = [];
14430
+ const outcomesFor = (rawDefault) => {
14431
+ const outcomes = outcomesByRawDefault.get(rawDefault) ?? { resolvedPaths: [], diagnostics: [] };
14432
+ outcomesByRawDefault.set(rawDefault, outcomes);
14433
+ return outcomes;
14434
+ };
14435
+ const recordResolvedPath = (rawDefault, path5) => {
14436
+ outcomesFor(rawDefault).resolvedPaths.push(path5);
14437
+ };
14438
+ const recordDiagnostic = (d) => {
14439
+ outcomesFor(d.rawDefault).diagnostics.push(d);
14440
+ diagnostics.push(d);
14441
+ };
14442
+ for (const input of defaults) {
14443
+ classifyOneDefault(input, leavesByPath, leavesByNormalizedKey, recordResolvedPath, recordDiagnostic, describeType);
14444
+ }
14445
+ const mappings = finalizeMappings(outcomesByRawDefault, recordDiagnostic);
14446
+ return { mappings, diagnostics };
14447
+ }
14448
+ function buildNormalizedIndex(leaves) {
14449
+ const out = /* @__PURE__ */ new Map();
14450
+ for (const leaf of leaves) {
14451
+ const key = leaf.path.slice(leaf.path.lastIndexOf(".") + 1);
14452
+ const normalizedKey = normalizeTokenKey(key);
14453
+ const matches = out.get(normalizedKey) ?? [];
14454
+ matches.push(leaf);
14455
+ out.set(normalizedKey, matches);
14456
+ }
14457
+ return out;
14458
+ }
14459
+ function classifyOneDefault(input, leavesByPath, leavesByNormalizedKey, recordResolvedPath, recordDiagnostic, describeType2) {
14460
+ const exact = leavesByPath.get(input.rawDefault);
14461
+ if (exact !== void 0) {
14462
+ if (input.tokenKind === null || exact.type === input.tokenKind) {
14463
+ recordResolvedPath(input.rawDefault, exact.path);
14464
+ } else {
14465
+ recordDiagnostic({
14466
+ rawDefault: input.rawDefault,
14467
+ tokenKind: input.tokenKind,
14468
+ reason: "type_mismatch",
14469
+ candidatePaths: [exact.path],
14470
+ message: `Token default '${input.rawDefault}' is a ${exact.type} token, not ${describeType2(input.tokenKind)}.`
14471
+ });
14472
+ }
14473
+ return;
14474
+ }
14475
+ const member = terminalMember(input.rawDefault);
14476
+ const candidates = member === void 0 ? [] : leavesByNormalizedKey.get(normalizeTokenKey(member)) ?? [];
14477
+ const compatible = input.tokenKind === null ? candidates : candidates.filter((c2) => c2.type === input.tokenKind);
14478
+ if (compatible.length === 1) {
14479
+ recordResolvedPath(input.rawDefault, compatible[0].path);
14480
+ return;
14481
+ }
14482
+ if (compatible.length > 1) {
14483
+ recordDiagnostic({
14484
+ rawDefault: input.rawDefault,
14485
+ tokenKind: input.tokenKind,
14486
+ reason: "ambiguous",
14487
+ candidatePaths: compatible.map((c2) => c2.path).sort(),
14488
+ message: `Token default '${input.rawDefault}' matches multiple compatible DTCG leaves: ${compatible.map((c2) => c2.path).sort().join(", ")}.`
14489
+ });
14490
+ return;
14491
+ }
14492
+ if (candidates.length > 0 && input.tokenKind !== null) {
14493
+ recordDiagnostic({
14494
+ rawDefault: input.rawDefault,
14495
+ tokenKind: input.tokenKind,
14496
+ reason: "type_mismatch",
14497
+ candidatePaths: candidates.map((c2) => c2.path).sort(),
14498
+ message: `Token default '${input.rawDefault}' has matching DTCG leaf names, but none is ${describeType2(input.tokenKind)}.`
14499
+ });
14500
+ return;
14501
+ }
14502
+ recordDiagnostic({
14503
+ rawDefault: input.rawDefault,
14504
+ tokenKind: input.tokenKind,
14505
+ reason: "no_match",
14506
+ candidatePaths: [],
14507
+ message: `Token default '${input.rawDefault}' does not match a DTCG token leaf.`
14508
+ });
14509
+ }
14510
+ function finalizeMappings(outcomesByRawDefault, recordDiagnostic) {
14511
+ const mappings = {};
14512
+ for (const [rawDefault, outcomes] of outcomesByRawDefault) {
14513
+ if (outcomes.diagnostics.length > 0)
14514
+ continue;
14515
+ const uniquePaths = [...new Set(outcomes.resolvedPaths)];
14516
+ if (uniquePaths.length === 1) {
14517
+ mappings[rawDefault] = uniquePaths[0];
14518
+ continue;
14519
+ }
14520
+ recordDiagnostic({
14521
+ rawDefault,
14522
+ tokenKind: null,
14523
+ reason: "ambiguous",
14524
+ candidatePaths: uniquePaths.sort(),
14525
+ message: `Token default '${rawDefault}' resolves to different compatible DTCG leaves across properties: ${uniquePaths.sort().join(", ")}.`
14526
+ });
14527
+ }
14528
+ return mappings;
14529
+ }
14530
+
14531
+ // packages/experience-design-system-backend-pipeline/dist/src/steps/generation/src/helpers/components/normalize-component-for-cache.js
14532
+ function normalizeComponentForCache(component) {
14533
+ const slots = component.slots.map((slot, index, allSlots) => ({
14534
+ ...slot,
14535
+ name: slot.name.trim() || (allSlots.length === 1 ? "children" : `slot_${index}`)
14536
+ }));
14537
+ return { ...component, slots };
14538
+ }
14539
+
14540
+ // packages/experience-design-system-backend-pipeline/dist/src/steps/generation/src/helpers/components/lookup-component-cache.js
14541
+ function lookupComponentCache(db, component, promptHash) {
14542
+ const normalized = normalizeComponentForCache(component);
14543
+ const inputHash = hashComponentShape(normalized);
14544
+ const cached = lookupCache(db, inputHash, "component", component.component_id, promptHash);
14545
+ if (cached)
14546
+ return cached;
14547
+ const legacyInputHash = hashComponentShape(component);
14548
+ return legacyInputHash === inputHash ? null : lookupCache(db, legacyInputHash, "component", component.component_id, promptHash);
14549
+ }
14550
+
14551
+ // packages/experience-design-system-backend-pipeline/dist/src/steps/generation/src/helpers/components/resolve-component-cache.js
14552
+ function resolveComponentCache(db, component, promptHash, allowedComponentNames2) {
14553
+ const cached = lookupComponentCache(db, component, promptHash);
14554
+ if (cached && findUnknownSlotAllowedComponents(db, cached.sourceSessionId, allowedComponentNames2, component.component_id).length === 0) {
14555
+ return { entry: cached, humanEdited: cached.humanEdited };
14556
+ }
14557
+ const pinned = lookupCacheByEntity(db, "component", component.component_id);
14558
+ if (pinned?.humanEdited && findUnknownSlotAllowedComponents(db, pinned.sourceSessionId, allowedComponentNames2, component.component_id).length === 0) {
14559
+ return { entry: pinned, humanEdited: true };
14560
+ }
14561
+ return null;
14562
+ }
14563
+
14564
+ // packages/experience-design-system-backend-pipeline/dist/src/steps/apply/src/controller/endpoint/resolve-shared-inputs.js
14565
+ init_validate();
14566
+
14567
+ // packages/experience-design-system-backend-pipeline/dist/src/steps/generation/src/helpers/map-tokens/filter-allowed-paths.js
14568
+ function filterAllowedPaths(args) {
14569
+ const { component, prop, tokenAllowed, tokenTypeByPath, propTokenKind, warnings } = args;
14570
+ const kept = [];
14571
+ for (const path5 of tokenAllowed) {
14572
+ const tokenType = tokenTypeByPath.get(path5);
14573
+ if (tokenType === void 0) {
14574
+ warnings.push(`map_token_prop '${component}.${prop}': dropped unknown token path '${path5}'`);
14575
+ } else if (propTokenKind !== null && tokenType !== propTokenKind) {
14576
+ warnings.push(`map_token_prop '${component}.${prop}': dropped '${path5}' \u2014 it is a ${tokenType} token, but the property's $token.kind is ${propTokenKind}`);
14577
+ } else {
14578
+ kept.push(path5);
14579
+ }
14580
+ }
14581
+ return kept;
14582
+ }
14583
+
14584
+ // packages/experience-design-system-backend-pipeline/dist/src/steps/generation/src/helpers/map-tokens/is-prop-reviewed.js
14585
+ function isPropReviewed(db, sessionId, componentId, propName) {
14586
+ const row = db.prepare(`SELECT COUNT(*) AS count FROM raw_prop_token_paths
14587
+ WHERE session_id = ? AND component_id = ? AND prop_name = ?
14588
+ AND source = 'review'`).get(sessionId, componentId, propName);
14589
+ return row.count > 0;
14590
+ }
14591
+
14592
+ // packages/experience-design-system-backend-pipeline/dist/src/steps/generation/src/helpers/map-tokens/load-token-type-by-path.js
14593
+ function loadTokenTypeByPath(db, sessionId) {
14594
+ const rows = db.prepare("SELECT path, type FROM raw_tokens WHERE session_id = ?").all(sessionId);
14595
+ return new Map(rows.map((r) => [r.path, r.type]));
14596
+ }
14597
+
14598
+ // packages/experience-design-system-backend-pipeline/dist/src/steps/generation/src/controller/map-tokens/apply-map-token-prop-calls.js
14599
+ function applyMapTokenPropCalls(db, sessionId, calls, incomingWarnings) {
14600
+ const warnings = [...incomingWarnings];
14601
+ let applied = 0;
14602
+ const tokenTypeByPath = loadTokenTypeByPath(db, sessionId);
14603
+ const findComponent = db.prepare("SELECT component_id FROM raw_components WHERE session_id = ? AND name = ?");
14604
+ const findProp = db.prepare("SELECT cdf_type, cdf_category, cdf_token_kind FROM raw_props WHERE session_id = ? AND component_id = ? AND name = ?");
14605
+ for (const call of calls) {
14606
+ const component = findComponent.get(sessionId, call.component);
14607
+ if (!component) {
14608
+ warnings.push(`map_token_prop: unknown component '${call.component}' \u2014 skipped`);
14609
+ continue;
14610
+ }
14611
+ const prop = findProp.get(sessionId, component.component_id, call.prop);
14612
+ if (!prop) {
14613
+ warnings.push(`map_token_prop '${call.component}.${call.prop}': unknown prop \u2014 skipped`);
14614
+ continue;
14615
+ }
14616
+ if (prop.cdf_type !== "token" || prop.cdf_category !== "design") {
14617
+ warnings.push(`map_token_prop '${call.component}.${call.prop}': target is not a design-category token prop \u2014 skipped`);
14618
+ continue;
14619
+ }
14620
+ if (isPropReviewed(db, sessionId, component.component_id, call.prop)) {
14621
+ warnings.push(`map_token_prop '${call.component}.${call.prop}': a reviewer already set this restriction \u2014 skipped`);
14622
+ continue;
14623
+ }
14624
+ const filteredAllowed = filterAllowedPaths({
14625
+ component: call.component,
14626
+ prop: call.prop,
14627
+ tokenAllowed: call.token_allowed,
14628
+ tokenTypeByPath,
14629
+ propTokenKind: prop.cdf_token_kind,
14630
+ warnings
14631
+ });
14632
+ if (filteredAllowed.length === 0) {
14633
+ warnings.push(`map_token_prop '${call.component}.${call.prop}': no valid token_allowed remain \u2014 skipped`);
14634
+ continue;
14635
+ }
14636
+ replaceRawPropTokenPaths(db, sessionId, component.component_id, call.prop, filteredAllowed, "agent");
14637
+ applied++;
14638
+ }
14639
+ return { applied, warnings };
14640
+ }
14641
+
14642
+ // packages/experience-design-system-backend-pipeline/dist/src/steps/generation/src/controller/map-tokens/run-map-tokens.js
14643
+ init_build_prompt();
14644
+ init_create_local_cli_agent_invoker();
14645
+ init_describe_agent_failure();
14646
+ init_resolve_binary();
14647
+ init_resolve_skill_path();
14648
+ init_parse_map_token_prop_tool_calls();
14649
+ import { resolve as resolve18 } from "node:path";
14650
+ init_cache_keys();
14651
+
14652
+ // packages/experience-design-system-backend-pipeline/dist/src/agents/helpers/resolution/binary-exists.js
14653
+ import { execFile } from "node:child_process";
14654
+ import { promisify } from "node:util";
14655
+ var execFileAsync = promisify(execFile);
14656
+ async function binaryExists(name) {
14657
+ try {
14658
+ await execFileAsync(process.platform === "win32" ? "where" : "which", [name]);
14659
+ return true;
14660
+ } catch {
14661
+ return false;
14662
+ }
14663
+ }
14664
+
14665
+ // packages/experience-design-system-backend-pipeline/dist/src/steps/generation/src/helpers/map-tokens/count-mappable-props.js
14666
+ function countMappableProps(cdfEntries) {
14667
+ return cdfEntries.reduce((count, { entry }) => {
14668
+ const props = entry.$properties ?? {};
14669
+ return count + Object.values(props).filter((prop) => prop.$type === "token" && prop.$category === "design").length;
14670
+ }, 0);
14671
+ }
14672
+
14673
+ // packages/experience-design-system-backend-pipeline/dist/src/steps/generation/src/helpers/map-tokens/load-raw-defaults.js
14674
+ function loadRawDefaults(db, sessionId) {
14675
+ return db.prepare(`SELECT rp.default_value AS default_reference, rp.cdf_token_kind
14676
+ FROM raw_props rp
14677
+ JOIN raw_components rc ON rc.session_id = rp.session_id AND rc.component_id = rp.component_id
14678
+ WHERE rp.session_id = ? AND rc.status = 'generated'
14679
+ AND rp.cdf_type = 'token' AND rp.cdf_category = 'design'
14680
+ AND rp.default_value IS NOT NULL`).all(sessionId);
14681
+ }
14682
+
14683
+ // packages/experience-design-system-backend-pipeline/dist/src/steps/generation/src/helpers/map-tokens/load-token-leaves.js
14684
+ function loadTokenLeaves(db, sessionId) {
14685
+ return db.prepare("SELECT path, type FROM raw_tokens WHERE session_id = ? ORDER BY path").all(sessionId);
14686
+ }
14687
+
14688
+ // packages/experience-design-system-backend-pipeline/dist/src/steps/generation/src/controller/map-tokens/run-map-tokens.js
14689
+ var DEFAULT_TIMEOUT_MS2 = 5 * 60 * 1e3;
14690
+ var MapTokensRunFailure = class _MapTokensRunFailure extends Error {
14691
+ reason;
14692
+ constructor(reason) {
14693
+ super(_MapTokensRunFailure.format(reason));
14694
+ this.reason = reason;
14695
+ }
14696
+ static format(r) {
14697
+ switch (r.type) {
14698
+ case "no-session":
14699
+ return "no completed generate components session found. Run generate components first, or pass sessionId.";
14700
+ case "no-components":
14701
+ return `no generated components in session '${r.sessionId}'. Run generate components first.`;
14702
+ case "binary-not-found":
14703
+ return `agent '${r.agent}' not found in $PATH (looked for binary: ${r.binary}). Install it, choose another agent, or run the mapping manually via: ${r.skillPath}`;
14704
+ case "agent-failed":
14705
+ return `map tokens agent failed \u2014 ${r.error}`;
14706
+ }
14707
+ }
14708
+ };
14709
+ async function runMapTokens(request) {
14710
+ const timeoutMs = request.agentTimeoutMs ?? DEFAULT_TIMEOUT_MS2;
14711
+ const db = openPipelineDb();
14712
+ try {
14713
+ const sessionId = request.sessionId ?? findLatestSessionForCommand(db, "generate components");
14714
+ if (!sessionId) {
14715
+ throw new MapTokensRunFailure({ type: "no-session" });
14716
+ }
14717
+ const tokenLeaves = loadTokenLeaves(db, sessionId);
14718
+ const knownTokenPaths = new Set(tokenLeaves.map((t) => t.path));
14719
+ if (request.tokenMapInline) {
14720
+ const validMappings = {};
14721
+ for (const [rawName, path5] of Object.entries(request.tokenMapInline)) {
14722
+ if (knownTokenPaths.has(path5))
14723
+ validMappings[rawName] = path5;
14724
+ }
14725
+ replaceRawTokenNamePaths(db, sessionId, validMappings, "manual");
14726
+ }
14727
+ const rawDefaults = loadRawDefaults(db, sessionId);
14728
+ const defaultResolution = resolveTokenDefaults(rawDefaults.map((row) => ({ rawDefault: row.default_reference, tokenKind: row.cdf_token_kind })), tokenLeaves);
14729
+ const manualMappings = new Map(getRawTokenNamePathRows(db, sessionId).filter((row) => row.source === "manual").map((row) => [row.rawName, row.path]));
14730
+ const automaticMappings = {};
14731
+ for (const [rawName, path5] of Object.entries(defaultResolution.mappings)) {
14732
+ if (manualMappings.get(rawName) === void 0)
14733
+ automaticMappings[rawName] = path5;
14734
+ }
14735
+ replaceRawTokenNamePaths(db, sessionId, automaticMappings, "automatic");
14736
+ const cdfEntries = loadCDFComponents(db, sessionId);
14737
+ if (cdfEntries.length === 0) {
14738
+ throw new MapTokensRunFailure({ type: "no-components", sessionId });
14739
+ }
14740
+ const mappablePropCount = countMappableProps(cdfEntries);
14741
+ const { groups, tokens } = getDtcgTokensForSession(db, sessionId);
14742
+ const tokenCount = tokens.length;
14743
+ if (mappablePropCount === 0 || tokenCount === 0) {
14744
+ return { type: "nothing-to-map", sessionId, mappablePropCount, tokenCount };
14745
+ }
14746
+ const generatedCdf = Object.fromEntries(cdfEntries.map((c2) => [c2.key, c2.entry]));
14747
+ const tokenTree = rebuildDTCGTree(groups, tokens);
14748
+ const componentSourceRefs = await loadComponentSourceRefs(db, sessionId);
14749
+ const buildMapPrompt = () => buildPrompt({
14750
+ skill: "map-tokens",
14751
+ mode: "autonomous",
14752
+ generatedCdf,
14753
+ tokenTree,
14754
+ componentSourceRefs,
14755
+ outDir: process.cwd(),
14756
+ existingTokensInline: request.existingEntitiesInline,
14757
+ ...request.skillContentOverride !== void 0 ? { skillContentOverride: request.skillContentOverride } : {},
14758
+ ...request.skillContentOverride === void 0 && request.skillPathOverride ? { skillPathOverride: resolve18(request.skillPathOverride) } : {}
14759
+ });
14760
+ if (request.printPrompt) {
14761
+ const prompt2 = await buildMapPrompt();
14762
+ return { type: "printed-prompt", sessionId, prompt: prompt2 };
14763
+ }
14764
+ if (request.skipAgent) {
14765
+ const stepId2 = createStep(db, sessionId, "map tokens", {
14766
+ agent: request.agent,
14767
+ model: request.model ?? "",
14768
+ skipAgent: "true"
14769
+ });
14770
+ updateStep(db, stepId2, "complete", { applied: "0", skipAgent: "true" });
14771
+ return { type: "skipped", sessionId, stepId: stepId2 };
14772
+ }
14773
+ const agent = request.agent;
14774
+ const noCache = request.cache === false || process.env["EDS_NO_CACHE"] === "1";
14775
+ const promptHash = await hashPromptForSkill("map-tokens", agent, request.model, void 0, request.existingEntitiesInline ? [hashContent(request.existingEntitiesInline)] : [], request.skillContentOverride);
14776
+ const inputHash = computeMapTokensInputHash(db, sessionId, componentSourceRefs);
14777
+ if (!noCache) {
14778
+ const cached = lookupCache(db, inputHash, "token_mapping", "__map_tokens__", promptHash);
14779
+ if (cached) {
14780
+ const applied2 = copyMapTokensFromCache(db, cached.sourceSessionId, sessionId);
14781
+ const stepId2 = createStep(db, sessionId, "map tokens", { agent, model: request.model ?? "" });
14782
+ updateStep(db, stepId2, "complete", { cached: "true", applied: String(applied2) });
14783
+ return { type: "cached", sessionId, applied: applied2, stepId: stepId2 };
14784
+ }
14785
+ }
14786
+ const binary = resolveBinary(agent);
14787
+ if (!await binaryExists(binary)) {
14788
+ throw new MapTokensRunFailure({
14789
+ type: "binary-not-found",
14790
+ agent,
14791
+ binary,
14792
+ skillPath: resolveSkillPath("map-tokens")
14793
+ });
14794
+ }
14795
+ const stepId = createStep(db, sessionId, "map tokens", { agent, model: request.model ?? "" });
14796
+ const prompt = await buildMapPrompt();
14797
+ const invoker = createLocalCliAgentInvoker();
14798
+ const result = await invoker.invoke({ agent, model: request.model, prompt, timeoutMs });
14799
+ if (result.timedOut || result.exitCode !== 0) {
14800
+ const error = result.timedOut ? `timed out after ${timeoutMs / 6e4} minutes` : describeAgentFailure(result);
14801
+ updateStep(db, stepId, "failed", {}, error);
14802
+ throw new MapTokensRunFailure({ type: "agent-failed", sessionId, stepId, error });
14803
+ }
14804
+ const { calls, warnings: parseWarnings } = parseMapTokenPropToolCalls(result.stdout);
14805
+ const { applied, warnings } = applyMapTokenPropCalls(db, sessionId, calls, parseWarnings);
14806
+ if (!noCache) {
14807
+ storeCache(db, inputHash, "token_mapping", "__map_tokens__", sessionId, false, promptHash);
14808
+ }
14809
+ updateStep(db, stepId, "complete", { applied: String(applied), warnings: String(warnings.length) });
14810
+ return { type: "applied", sessionId, applied, warnings, stepId };
14811
+ } finally {
14812
+ db.close();
14813
+ }
14814
+ }
14815
+
14816
+ // packages/experience-design-system-backend-pipeline/dist/src/orchestrators/run-extract-and-compose-session/run-extract-and-compose-session.js
14817
+ import { mkdir as mkdir4 } from "node:fs/promises";
14818
+ import { relative as relative2 } from "node:path";
13734
14819
 
13735
14820
  // packages/experience-design-system-extraction/dist/src/extract/framework-adapters/astro/helpers/collect-astro-props-bindings.js
13736
14821
  import { Node as Node10, Project as Project7 } from "ts-morph";
@@ -14389,7 +15474,7 @@ function hasNoAuthoringSurface(component) {
14389
15474
  }
14390
15475
 
14391
15476
  // packages/experience-design-system-extraction/dist/src/extract/services/quality/helpers/inspection/inspect-component-source.js
14392
- import { readFile as readFile12 } from "node:fs/promises";
15477
+ import { readFile as readFile15 } from "node:fs/promises";
14393
15478
 
14394
15479
  // packages/experience-design-system-extraction/dist/src/extract/helpers/evidence/parse-source-imports.js
14395
15480
  function parseImportedNames(importClause) {
@@ -14484,7 +15569,7 @@ var ZERO_SURFACE_RENDERED_UI_REASON = "zero-surface:rendered-ui";
14484
15569
  async function inspectComponentSource(component) {
14485
15570
  let sourceText = "";
14486
15571
  try {
14487
- sourceText = await readFile12(component.source, "utf8");
15572
+ sourceText = await readFile15(component.source, "utf8");
14488
15573
  } catch {
14489
15574
  return {
14490
15575
  wrapperConfidence: 0,
@@ -14779,7 +15864,7 @@ async function retryDatabaseWrite(operation, attempts = 8) {
14779
15864
  const message = error instanceof Error ? error.message : String(error);
14780
15865
  if (!/database is locked|database is busy/i.test(message) || attempt >= attempts)
14781
15866
  throw error;
14782
- await new Promise((resolve22) => setTimeout(resolve22, Math.min(250 * attempt, 2e3)));
15867
+ await new Promise((resolve25) => setTimeout(resolve25, Math.min(250 * attempt, 2e3)));
14783
15868
  }
14784
15869
  }
14785
15870
  }
@@ -14811,7 +15896,7 @@ function resolveCompositionAgentName(flagValue) {
14811
15896
  }
14812
15897
 
14813
15898
  // packages/experience-design-system-backend-pipeline/dist/src/orchestrators/run-extract-and-compose-session/helpers/read-candidate-files.js
14814
- import { readFile as readFile13 } from "node:fs/promises";
15899
+ import { readFile as readFile16 } from "node:fs/promises";
14815
15900
  async function readCandidateFiles(components, extraFiles = []) {
14816
15901
  const paths = new Set(extraFiles);
14817
15902
  for (const c2 of components) {
@@ -14821,7 +15906,7 @@ async function readCandidateFiles(components, extraFiles = []) {
14821
15906
  const out = [];
14822
15907
  await Promise.all([...paths].map(async (p) => {
14823
15908
  try {
14824
- const content = await readFile13(p, "utf8");
15909
+ const content = await readFile16(p, "utf8");
14825
15910
  out.push({ path: p, content });
14826
15911
  } catch {
14827
15912
  }
@@ -14988,7 +16073,7 @@ init_build_prompt();
14988
16073
  init_create_local_cli_agent_invoker();
14989
16074
  init_invoke_agent_with_output();
14990
16075
  init_parse_token_tool_calls();
14991
- import { readFile as readFile14 } from "node:fs/promises";
16076
+ import { readFile as readFile17 } from "node:fs/promises";
14992
16077
  import { basename as basename5, resolve as pathResolve } from "node:path";
14993
16078
  init_cache_keys();
14994
16079
  init_parse_prompt_overrides();
@@ -15021,7 +16106,7 @@ async function runGenerateTokensSession(request) {
15021
16106
  throw new Error(`Prompt override error(s): ${promptErrors.join("; ")}`);
15022
16107
  const tokensOverride = overridesMap.get("tokens");
15023
16108
  const skillContentOverride = tokensOverride ? await resolvePromptOverride(tokensOverride) : void 0;
15024
- const rawTokensInline = await readFile14(pathResolve(rawTokensPath), "utf8");
16109
+ const rawTokensInline = await readFile17(pathResolve(rawTokensPath), "utf8");
15025
16110
  const tokenInputHash = hashTokenContent(rawTokensInline);
15026
16111
  const db = openPipelineDb();
15027
16112
  try {
@@ -15089,6 +16174,357 @@ ${result.stdout}`);
15089
16174
  }
15090
16175
  }
15091
16176
 
16177
+ // packages/experience-design-system-backend-pipeline/dist/src/orchestrators/run-generate-components-session/run-generate-components-session.js
16178
+ init_create_local_cli_agent_invoker();
16179
+ init_cache_keys();
16180
+
16181
+ // packages/experience-design-system-backend-pipeline/dist/src/orchestrators/run-generate-components-session/helpers/build-empty-session-response.js
16182
+ function buildEmptySessionResponse(sessionId) {
16183
+ return {
16184
+ sessionId,
16185
+ results: [],
16186
+ allOk: true,
16187
+ renamedSlotsCount: 0,
16188
+ duplicateNames: [],
16189
+ droppedAllowedComponents: [],
16190
+ emptySession: true
16191
+ };
16192
+ }
16193
+
16194
+ // packages/experience-design-system-backend-pipeline/dist/src/orchestrators/run-generate-components-session/helpers/collect-duplicate-names.js
16195
+ function collectDuplicateNames(components) {
16196
+ const nameCounts = /* @__PURE__ */ new Map();
16197
+ for (const c2 of components) {
16198
+ const sources = nameCounts.get(c2.name) ?? [];
16199
+ sources.push(c2.source);
16200
+ nameCounts.set(c2.name, sources);
16201
+ }
16202
+ return [...nameCounts.entries()].filter(([, srcs]) => srcs.length > 1).map(([name, sources]) => ({ name, sources }));
16203
+ }
16204
+
16205
+ // packages/experience-design-system-backend-pipeline/dist/src/orchestrators/run-generate-components-session/helpers/filter-dropped-allowed-components.js
16206
+ function filterDroppedAllowedComponents(db, sessionId, components, allowedComponentNames2, acceptedNames) {
16207
+ const dropped = filterUnknownSlotAllowedComponents(db, sessionId, allowedComponentNames2);
16208
+ if (dropped.length === 0)
16209
+ return { components, dropped: [] };
16210
+ return { components: loadRawComponents(db, sessionId, acceptedNames), dropped };
16211
+ }
16212
+
16213
+ // packages/experience-design-system-backend-pipeline/dist/src/orchestrators/run-generate-components-session/helpers/read-existing-entities.js
16214
+ async function readExistingEntities(request) {
16215
+ if (request.existingContentfulEntities !== void 0)
16216
+ return request.existingContentfulEntities;
16217
+ if (!request.existingEntitiesPath)
16218
+ return void 0;
16219
+ return readExistingContentfulEntitiesFromSession({ path: request.existingEntitiesPath });
16220
+ }
16221
+
16222
+ // packages/experience-design-system-backend-pipeline/dist/src/orchestrators/run-generate-components-session/helpers/resolve-generate-prompt.js
16223
+ init_parse_prompt_overrides();
16224
+ init_resolve_prompt_override();
16225
+ import { resolve as resolve19 } from "node:path";
16226
+ async function resolveGeneratePrompt(overrides) {
16227
+ const { overrides: parsed, errors } = parsePromptOverrides(overrides);
16228
+ if (errors.length > 0)
16229
+ throw new Error(errors.join("; "));
16230
+ const entry = parsed.get("generate");
16231
+ if (!entry)
16232
+ return {};
16233
+ const text = await resolvePromptOverride(entry);
16234
+ if (entry.kind === "text")
16235
+ return { text };
16236
+ return { path: resolve19(entry.value), text };
16237
+ }
16238
+
16239
+ // packages/experience-design-system-backend-pipeline/dist/src/orchestrators/run-generate-components-session/helpers/run-one-generate-component.js
16240
+ init_build_prompt();
16241
+ init_describe_agent_failure();
16242
+ init_invoke_agent_with_output();
16243
+ init_parse_tool_calls();
16244
+ var DEFAULT_TIMEOUT_MS4 = Number(process.env["EDS_AGENT_TIMEOUT_MS"] ?? 5 * 60 * 1e3);
16245
+ var RETRY_BACKOFF_MS = Number(process.env["EDS_RETRY_BACKOFF_MS"] ?? 5e3);
16246
+ async function runOneGenerateComponent(options, component, index, total) {
16247
+ const { db, sessionId, invoker, agent, model, tokensInline, tokenMapInline, verbose, noCache, skillPathOverride, skillContentOverride, promptHash, existingContentfulEntities, existingTokensInline, precomputedCachedNames, allowedComponentNames: allowedComponentNames2, onProgress } = options;
16248
+ const { renames } = renameEmptySlots(db, sessionId, component.component_id, component.name, component.slots.length);
16249
+ let effectiveSlots = component.slots;
16250
+ if (renames.length > 0) {
16251
+ const renameMap = new Map(renames.map((r) => [r.oldName, r.newName]));
16252
+ effectiveSlots = component.slots.map((s) => renameMap.has(s.name) ? { ...s, name: renameMap.get(s.name) } : s);
16253
+ for (const rename3 of renames) {
16254
+ onProgress?.({
16255
+ kind: "component:slot-renamed",
16256
+ componentName: component.name,
16257
+ oldName: rename3.oldName,
16258
+ newName: rename3.newName
16259
+ });
16260
+ }
16261
+ }
16262
+ effectiveSlots = effectiveSlots.map((slot) => slot.allowedComponents ? { ...slot, allowedComponents: slot.allowedComponents.filter((name) => allowedComponentNames2.has(name)) } : slot);
16263
+ const cacheComponent = normalizeComponentForCache(component);
16264
+ if (!noCache && precomputedCachedNames.has(component.name)) {
16265
+ onProgress?.({ kind: "component:cached", index, total, name: component.name, pinned: false });
16266
+ return cachedResult(component.name);
16267
+ }
16268
+ if (!noCache) {
16269
+ const resolution = resolveComponentCache(db, component, promptHash, allowedComponentNames2);
16270
+ if (resolution && !resolution.humanEdited) {
16271
+ copyComponentFromCache(db, resolution.entry.sourceSessionId, sessionId, component.component_id, true, {
16272
+ allowedComponentNames: allowedComponentNames2
16273
+ });
16274
+ storeCache(db, hashComponentShape(cacheComponent), "component", component.component_id, resolution.entry.sourceSessionId, resolution.entry.humanEdited, promptHash);
16275
+ onProgress?.({ kind: "component:cached", index, total, name: component.name, pinned: false });
16276
+ return cachedResult(component.name);
16277
+ }
16278
+ if (resolution?.humanEdited) {
16279
+ copyComponentFromCache(db, resolution.entry.sourceSessionId, sessionId, component.component_id, true, {
16280
+ allowedComponentNames: allowedComponentNames2
16281
+ });
16282
+ onProgress?.({ kind: "component:cached", index, total, name: component.name, pinned: true });
16283
+ return cachedResult(component.name, [`${component.name}: source changed but human edits preserved`]);
16284
+ }
16285
+ }
16286
+ const rawComponentsInline = JSON.stringify([
16287
+ {
16288
+ name: component.name,
16289
+ source: component.source,
16290
+ framework: component.framework,
16291
+ props: component.props,
16292
+ slots: effectiveSlots
16293
+ }
16294
+ ], null, 2);
16295
+ const sourceRef = await loadComponentSourceRef(component.name, component.sourcePath ?? component.source, component.props.map((p) => p.name), component.props.map((p) => p.type));
16296
+ const existingComponentsInline = existingContentfulEntities ? JSON.stringify(summarizeForGenerateAgent(existingContentfulEntities, component.name)) : void 0;
16297
+ const prompt = await buildPrompt({
16298
+ skill: "components",
16299
+ mode: "autonomous",
16300
+ rawComponentsInline,
16301
+ tokensInline,
16302
+ tokenMapInline,
16303
+ outDir: process.cwd(),
16304
+ componentName: component.name,
16305
+ componentSourceRefs: [sourceRef],
16306
+ skillPathOverride,
16307
+ skillContentOverride,
16308
+ existingComponentsInline,
16309
+ existingTokensInline,
16310
+ componentAllowlistInline: JSON.stringify([...allowedComponentNames2].sort())
16311
+ });
16312
+ const maxAttempts = 2;
16313
+ let lastError = "";
16314
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
16315
+ if (attempt > 1)
16316
+ await new Promise((res) => setTimeout(res, RETRY_BACKOFF_MS));
16317
+ onProgress?.({ kind: "component:started", index, total, name: component.name, attempt, maxAttempts });
16318
+ const { result } = await invokeAgentWithOutput(invoker, { agent, model, prompt, timeoutMs: DEFAULT_TIMEOUT_MS4 }, verbose);
16319
+ if (result.timedOut) {
16320
+ const error = `timed out after ${DEFAULT_TIMEOUT_MS4 / 6e4} minutes`;
16321
+ onProgress?.({ kind: "component:failed", index, total, name: component.name, error });
16322
+ return failed(component.name, error, renames.length);
16323
+ }
16324
+ if (result.exitCode !== 0) {
16325
+ lastError = describeAgentFailure(result);
16326
+ continue;
16327
+ }
16328
+ const { calls, warnings } = parseToolCalls(result.stdout);
16329
+ if (calls.length === 0) {
16330
+ lastError = describeAgentFailure(result);
16331
+ continue;
16332
+ }
16333
+ const applied = applyToolCalls(db, sessionId, component.component_id, component.name, calls, warnings, {
16334
+ allowedComponentNames: allowedComponentNames2
16335
+ });
16336
+ if (!noCache) {
16337
+ storeCache(db, hashComponentShape(cacheComponent), "component", component.component_id, sessionId, false, promptHash);
16338
+ }
16339
+ onProgress?.({
16340
+ kind: "component:completed",
16341
+ index,
16342
+ total,
16343
+ name: component.name,
16344
+ classified: applied.classified,
16345
+ excluded: applied.excluded,
16346
+ slots: applied.slots,
16347
+ warnings: applied.warnings
16348
+ });
16349
+ return {
16350
+ componentName: component.name,
16351
+ classified: applied.classified,
16352
+ excluded: applied.excluded,
16353
+ slots: applied.slots,
16354
+ warnings: applied.warnings,
16355
+ failed: false,
16356
+ cached: false,
16357
+ renamedSlotsCount: renames.length
16358
+ };
16359
+ }
16360
+ onProgress?.({ kind: "component:failed", index, total, name: component.name, error: lastError });
16361
+ return failed(component.name, lastError, renames.length);
16362
+ }
16363
+ function cachedResult(componentName, warnings = []) {
16364
+ return {
16365
+ componentName,
16366
+ classified: 0,
16367
+ excluded: 0,
16368
+ slots: 0,
16369
+ warnings,
16370
+ failed: false,
16371
+ cached: true,
16372
+ renamedSlotsCount: 0
16373
+ };
16374
+ }
16375
+ function failed(componentName, error, renamedSlotsCount) {
16376
+ return {
16377
+ componentName,
16378
+ classified: 0,
16379
+ excluded: 0,
16380
+ slots: 0,
16381
+ warnings: [],
16382
+ failed: true,
16383
+ error,
16384
+ cached: false,
16385
+ renamedSlotsCount
16386
+ };
16387
+ }
16388
+
16389
+ // packages/experience-design-system-backend-pipeline/dist/src/orchestrators/run-generate-components-session/helpers/run-with-pool.js
16390
+ async function runWithPool(items, concurrency, worker) {
16391
+ const results = new Array(items.length);
16392
+ let next = 0;
16393
+ async function run() {
16394
+ while (next < items.length) {
16395
+ const i = next++;
16396
+ results[i] = await worker(items[i], i);
16397
+ }
16398
+ }
16399
+ await Promise.all(Array.from({ length: concurrency }, run));
16400
+ return results;
16401
+ }
16402
+
16403
+ // packages/experience-design-system-backend-pipeline/dist/src/orchestrators/run-generate-components-session/check-generate-components-cache.js
16404
+ init_cache_keys();
16405
+ async function checkGenerateComponentsCache(request) {
16406
+ if (request.noCache) {
16407
+ return { sessionId: request.sessionId, cachedComponentNames: [], fullyCached: false, cacheDisabled: true };
16408
+ }
16409
+ const existingEntities = await readExistingEntities(request);
16410
+ const existingTokensInline = existingEntities ? JSON.stringify(summarizeForMapTokens({ entities: existingEntities })) : void 0;
16411
+ const prompt = await resolveGeneratePrompt(request.promptOverrides);
16412
+ const agent = request.agent;
16413
+ const promptHash = await hashPromptForSkill("components", agent, request.agentModel, prompt.path, existingTokensInline ? [hashContent(existingTokensInline)] : [], prompt.text);
16414
+ const db = openPipelineDb();
16415
+ try {
16416
+ const acceptedNames = await loadAcceptedNames(request.sessionId);
16417
+ const components = loadRawComponents(db, request.sessionId, acceptedNames ?? void 0);
16418
+ if (components.length === 0) {
16419
+ return { sessionId: request.sessionId, cachedComponentNames: [], fullyCached: false, cacheDisabled: false };
16420
+ }
16421
+ const allowedComponentNames2 = /* @__PURE__ */ new Set([
16422
+ ...components.map((component) => component.name),
16423
+ ...(existingEntities?.components ?? []).map((component) => component.name)
16424
+ ]);
16425
+ const cachedComponents = components.flatMap((component) => {
16426
+ const resolution = resolveComponentCache(db, component, promptHash, allowedComponentNames2);
16427
+ return resolution ? [{ component, resolution }] : [];
16428
+ });
16429
+ if (request.restoreCache)
16430
+ restoreCached(db, request.sessionId, cachedComponents, promptHash, allowedComponentNames2);
16431
+ return {
16432
+ sessionId: request.sessionId,
16433
+ cachedComponentNames: cachedComponents.map(({ component }) => component.name),
16434
+ fullyCached: cachedComponents.length === components.length,
16435
+ cacheDisabled: false
16436
+ };
16437
+ } finally {
16438
+ db.close();
16439
+ }
16440
+ }
16441
+ function restoreCached(db, sessionId, cachedComponents, promptHash, allowedComponentNames2) {
16442
+ const restorations = [];
16443
+ const rekeyed = [];
16444
+ const componentStatus = db.prepare("SELECT status FROM raw_components WHERE session_id = ? AND component_id = ?");
16445
+ for (const { component, resolution } of cachedComponents) {
16446
+ const current = componentStatus.get(sessionId, component.component_id);
16447
+ if (current?.status === "generated")
16448
+ continue;
16449
+ renameEmptySlots(db, sessionId, component.component_id, component.name, component.slots.length);
16450
+ restorations.push({
16451
+ sourceSessionId: resolution.entry.sourceSessionId,
16452
+ targetSessionId: sessionId,
16453
+ componentId: component.component_id
16454
+ });
16455
+ rekeyed.push({ component, cached: resolution.entry });
16456
+ }
16457
+ copyComponentsFromCache(db, restorations, { allowedComponentNames: allowedComponentNames2 });
16458
+ storeCaches(db, rekeyed.map(({ component, cached }) => ({
16459
+ inputHash: hashComponentShape(normalizeComponentForCache(component)),
16460
+ entityType: "component",
16461
+ entityId: component.component_id,
16462
+ sourceSessionId: cached.sourceSessionId,
16463
+ humanEdited: cached.humanEdited,
16464
+ promptHash
16465
+ })));
16466
+ }
16467
+
16468
+ // packages/experience-design-system-backend-pipeline/dist/src/orchestrators/run-generate-components-session/run-generate-components-session.js
16469
+ var DEFAULT_COMPONENT_CONCURRENCY = Number(process.env["EDS_GENERATE_CONCURRENCY"] ?? 10);
16470
+ async function runGenerateComponentsSession(request) {
16471
+ const prompt = await resolveGeneratePrompt(request.promptOverrides);
16472
+ const existingEntities = await readExistingEntities(request);
16473
+ const existingTokensInline = existingEntities ? JSON.stringify(summarizeForMapTokens({ entities: existingEntities })) : void 0;
16474
+ const existingTokensHash = existingTokensInline ? [hashContent(existingTokensInline)] : [];
16475
+ const agent = request.agent;
16476
+ const promptHash = await hashPromptForSkill("components", agent, request.agentModel, prompt.path, existingTokensHash, prompt.text);
16477
+ const db = openPipelineDb();
16478
+ try {
16479
+ const acceptedNames = await loadAcceptedNames(request.sessionId);
16480
+ const acceptedSet = acceptedNames ? new Set(acceptedNames) : void 0;
16481
+ let components = loadRawComponents(db, request.sessionId, acceptedSet ?? void 0);
16482
+ if (components.length === 0)
16483
+ return buildEmptySessionResponse(request.sessionId);
16484
+ const allowedComponentNames2 = /* @__PURE__ */ new Set([
16485
+ ...components.map((c2) => c2.name),
16486
+ ...(existingEntities?.components ?? []).map((c2) => c2.name)
16487
+ ]);
16488
+ const { components: filtered, dropped } = filterDroppedAllowedComponents(db, request.sessionId, components, allowedComponentNames2, acceptedSet);
16489
+ components = filtered;
16490
+ const duplicateNames = collectDuplicateNames(components);
16491
+ const invoker = createLocalCliAgentInvoker({});
16492
+ const concurrency = Math.max(1, Math.min(DEFAULT_COMPONENT_CONCURRENCY, components.length));
16493
+ const results = await runWithPool(components, concurrency, (component, index) => runOneGenerateComponent({
16494
+ db,
16495
+ sessionId: request.sessionId,
16496
+ invoker,
16497
+ agent,
16498
+ model: request.agentModel,
16499
+ tokensInline: request.tokensInline,
16500
+ tokenMapInline: request.tokenMapInline,
16501
+ verbose: request.verbose ?? false,
16502
+ noCache: request.noCache,
16503
+ skillPathOverride: prompt.path,
16504
+ skillContentOverride: prompt.text,
16505
+ promptHash,
16506
+ existingContentfulEntities: existingEntities,
16507
+ existingTokensInline,
16508
+ precomputedCachedNames: request.precomputedCachedNames ?? /* @__PURE__ */ new Set(),
16509
+ allowedComponentNames: allowedComponentNames2,
16510
+ onProgress: request.onProgress
16511
+ }, component, index, components.length));
16512
+ const allOk = results.every((r) => !r.failed);
16513
+ const renamedSlotsCount = results.reduce((sum, r) => sum + r.renamedSlotsCount, 0);
16514
+ return {
16515
+ sessionId: request.sessionId,
16516
+ results,
16517
+ allOk,
16518
+ renamedSlotsCount,
16519
+ duplicateNames,
16520
+ droppedAllowedComponents: dropped,
16521
+ emptySession: false
16522
+ };
16523
+ } finally {
16524
+ db.close();
16525
+ }
16526
+ }
16527
+
15092
16528
  // packages/experience-design-system-cli/src/tui/import/steps/03-path-validation/helpers/scan-files.ts
15093
16529
  function scanFiles(directory) {
15094
16530
  return toScanResult(collectFiles(directory));
@@ -15738,7 +17174,7 @@ function ExtractionScreen({
15738
17174
 
15739
17175
  // packages/experience-design-system-types/dist/src/config/index.js
15740
17176
  import { randomBytes as randomBytes3 } from "node:crypto";
15741
- import { mkdir as mkdir6, readFile as readFile15, rename as rename2, writeFile as writeFile6 } from "node:fs/promises";
17177
+ import { mkdir as mkdir6, readFile as readFile18, rename as rename2, writeFile as writeFile6 } from "node:fs/promises";
15742
17178
  import { homedir as homedir3 } from "node:os";
15743
17179
  import { dirname as dirname13, join as join17 } from "node:path";
15744
17180
  function configRoot2() {
@@ -15748,7 +17184,7 @@ var configFilePath2 = () => join17(configRoot2(), "config.json");
15748
17184
  var debugSessionsDir2 = () => join17(configRoot2(), "debug", "sessions");
15749
17185
  async function readSettings2() {
15750
17186
  try {
15751
- return JSON.parse(await readFile15(configFilePath2(), "utf8"));
17187
+ return JSON.parse(await readFile18(configFilePath2(), "utf8"));
15752
17188
  } catch {
15753
17189
  return {};
15754
17190
  }
@@ -15770,11 +17206,11 @@ import { useEffect as useEffect5, useRef as useRef2, useState as useState8 } fro
15770
17206
 
15771
17207
  // packages/experience-design-system-cli/src/tui/import/steps/06-extraction/run.ts
15772
17208
  import { mkdir as mkdir7 } from "node:fs/promises";
15773
- import { join as join19, resolve as resolve20 } from "node:path";
17209
+ import { join as join19, resolve as resolve22 } from "node:path";
15774
17210
 
15775
17211
  // packages/experience-design-system-cli/src/tui/import/steps/06-extraction/find-skill-path.ts
15776
17212
  import { existsSync as existsSync8 } from "node:fs";
15777
- import { dirname as dirname14, join as join18, resolve as resolve18 } from "node:path";
17213
+ import { dirname as dirname14, join as join18, resolve as resolve20 } from "node:path";
15778
17214
  import { fileURLToPath as fileURLToPath4 } from "node:url";
15779
17215
  function findSkillPath(fileName) {
15780
17216
  const thisDir = dirname14(fileURLToPath4(import.meta.url));
@@ -15782,7 +17218,7 @@ function findSkillPath(fileName) {
15782
17218
  for (; ; ) {
15783
17219
  const candidate = join18(dir, "skills", fileName);
15784
17220
  if (existsSync8(candidate)) return candidate;
15785
- const parent = resolve18(dir, "..");
17221
+ const parent = resolve20(dir, "..");
15786
17222
  if (parent === dir) {
15787
17223
  throw new Error(`skill file not found (looked for skills/${fileName} from ${thisDir})`);
15788
17224
  }
@@ -15791,11 +17227,11 @@ function findSkillPath(fileName) {
15791
17227
  }
15792
17228
 
15793
17229
  // packages/experience-design-system-cli/src/tui/import/steps/06-extraction/selection.ts
15794
- import { resolve as resolve19 } from "node:path";
17230
+ import { resolve as resolve21 } from "node:path";
15795
17231
  var SELECT_SKILL_PATH = findSkillPath("select-components.md");
15796
- var DEFAULT_TIMEOUT_MS4 = Number(process.env.EDS_AGENT_TIMEOUT_MS ?? 5 * 60 * 1e3);
17232
+ var DEFAULT_TIMEOUT_MS5 = Number(process.env.EDS_AGENT_TIMEOUT_MS ?? 5 * 60 * 1e3);
15797
17233
  async function hashSelectPrompt(options) {
15798
- const promptHash = options.promptText ? hashContent(options.promptText) : options.promptPath ? await hashFile(resolve19(options.promptPath)) : await hashFile(SELECT_SKILL_PATH);
17234
+ const promptHash = options.promptText ? hashContent(options.promptText) : options.promptPath ? await hashFile(resolve21(options.promptPath)) : await hashFile(SELECT_SKILL_PATH);
15799
17235
  return hashContent(`${promptHash}|${options.agent}|${options.model ?? ""}`);
15800
17236
  }
15801
17237
  async function runSelection(options) {
@@ -15829,7 +17265,7 @@ async function runSelection(options) {
15829
17265
  });
15830
17266
  const { result } = await invokeAgentWithOutput(
15831
17267
  invoker,
15832
- { agent: options.agent, model: options.model, prompt, timeoutMs: DEFAULT_TIMEOUT_MS4 },
17268
+ { agent: options.agent, model: options.model, prompt, timeoutMs: DEFAULT_TIMEOUT_MS5 },
15833
17269
  false
15834
17270
  );
15835
17271
  if (result.timedOut) throw new Error("selection agent timed out");
@@ -15890,7 +17326,7 @@ var realDeps = {
15890
17326
  var fail = (step, message) => ({ ok: false, step, message });
15891
17327
  var errorMessage2 = (error) => error instanceof Error ? error.message : String(error);
15892
17328
  async function runExtraction(input, onProgress, deps = realDeps) {
15893
- const outDir = join19(resolve20(input.projectPath), ".contentful");
17329
+ const outDir = join19(resolve22(input.projectPath), ".contentful");
15894
17330
  let progress = initialProgress({
15895
17331
  hasCredentials: input.credentials !== null,
15896
17332
  hasRawTokens: input.rawTokensPath !== "",
@@ -16016,7 +17452,7 @@ async function resolveSelectionPrompt(overrides) {
16016
17452
  if (select?.kind === "text") return { promptText: select.value };
16017
17453
  if (select?.kind === "path") {
16018
17454
  await resolvePromptOverride(select);
16019
- return { promptPath: resolve20(select.value) };
17455
+ return { promptPath: resolve22(select.value) };
16020
17456
  }
16021
17457
  return {};
16022
17458
  }
@@ -16920,7 +18356,7 @@ function buildVisibleRows(props) {
16920
18356
  if (visited.has(target)) continue;
16921
18357
  visited.add(target);
16922
18358
  const isCycleMember = cycleParticipants.has(target);
16923
- out.push({ name: target, depth: cur.depth + 1, isCycleMember, parent: cur.name });
18359
+ out.push({ name: target, depth: cur.depth + 1, isCycleMember });
16924
18360
  queue.push({ name: target, depth: cur.depth + 1 });
16925
18361
  }
16926
18362
  }
@@ -16967,8 +18403,7 @@ function buildVisibleRows(props) {
16967
18403
  sharedSuffix,
16968
18404
  cycleChild: child.isCycleMember || void 0,
16969
18405
  itemIdx: childRec?.idx ?? -1,
16970
- rootName: key,
16971
- parentName: child.parent
18406
+ rootName: key
16972
18407
  });
16973
18408
  });
16974
18409
  }
@@ -17051,19 +18486,13 @@ function buildVisibleRows(props) {
17051
18486
  injectedChildren.push({
17052
18487
  name: target,
17053
18488
  depth: parentDepth + 1,
17054
- isCycleChild: true,
17055
- parent: parentName
18489
+ isCycleChild: true
17056
18490
  });
17057
18491
  }
17058
18492
  };
17059
18493
  emitCycleChildrenOf(root, 0);
17060
18494
  for (const c2 of closureChildren) {
17061
- injectedChildren.push({
17062
- name: c2.name,
17063
- depth: c2.depth,
17064
- isCycleChild: false,
17065
- parent: c2.path[c2.path.length - 2] ?? root
17066
- });
18495
+ injectedChildren.push({ name: c2.name, depth: c2.depth, isCycleChild: false });
17067
18496
  emitCycleChildrenOf(c2.name, c2.depth);
17068
18497
  }
17069
18498
  const isLastAtDepth = (idx) => {
@@ -17097,8 +18526,7 @@ function buildVisibleRows(props) {
17097
18526
  sharedSuffix,
17098
18527
  cycleChild: child.isCycleChild || void 0,
17099
18528
  itemIdx: childRec?.idx ?? -1,
17100
- rootName: root,
17101
- parentName: child.parent
18529
+ rootName: root
17102
18530
  });
17103
18531
  });
17104
18532
  }
@@ -17251,7 +18679,7 @@ function GroupedSidebar(props) {
17251
18679
  const rs = itemName ? renderStatusByKey?.get(itemName) : void 0;
17252
18680
  const badge = itemName ? previewBadge(previewAnnotationByKey?.get(itemName)) : null;
17253
18681
  const showInheritance = rs !== void 0 && row.kind !== "cycle" && row.kind !== "empty" && row.kind !== "group-root";
17254
- const supportsSelectionGlyph = selectionStateByKey !== void 0 && itemName !== void 0 && (row.kind === "standalone" || row.kind === "group-root" || row.kind === "group-child" || row.kind === "flat" || row.kind === "empty" || row.kind === "cycle");
18682
+ const supportsSelectionGlyph = selectionStateByKey !== void 0 && itemName !== void 0 && (row.kind === "standalone" || row.kind === "group-root" || row.kind === "group-child" || row.kind === "flat" || row.kind === "cycle");
17255
18683
  const selState = supportsSelectionGlyph ? selectionStateByKey.get(itemName) ?? "undecided" : void 0;
17256
18684
  const isCycleRow = row.kind === "cycle";
17257
18685
  const selStyle = selectionGlyphStyleFor(selState, isCycleRow);
@@ -17281,7 +18709,7 @@ function GroupedSidebar(props) {
17281
18709
  color: isSelected ? PALETTE2.info : labelStyle.dim ? PALETTE2.muted : labelStyle.color,
17282
18710
  bold: isSelected || labelStyle.bold,
17283
18711
  inverse: false,
17284
- underline: isSelected && focused,
18712
+ underline: isSelected && !focused,
17285
18713
  wrap: wrapLabels ? "wrap" : "truncate",
17286
18714
  children: [
17287
18715
  " ",
@@ -17940,7 +19368,6 @@ function resolveKey(mode, key, ctx) {
17940
19368
  function resolveMain(key, ctx) {
17941
19369
  const { input } = key;
17942
19370
  const inMain = ctx.focusedColumn === "main";
17943
- if (key.ctrl && input === "z") return { type: "undo" };
17944
19371
  if (input === "q" || key.escape) {
17945
19372
  if (key.escape && ctx.jumpFilterActive) return { type: "clear-jump-filter" };
17946
19373
  if (key.escape && ctx.searchActive) return { type: "clear-search" };
@@ -18199,42 +19626,21 @@ function rejectNeedsConfirmation(graph, name, state) {
18199
19626
  const ancestors = toReject.filter((n) => n !== name);
18200
19627
  return ancestors.length + toDeselect.length >= 2;
18201
19628
  }
18202
- function removeSlotChild(components, edge) {
18203
- return components.map(
18204
- (component) => component.name === edge.parent ? {
18205
- ...component,
18206
- slots: component.slots?.map((slot) => ({
18207
- ...slot,
18208
- allowedComponents: slot.allowedComponents.filter((name) => name !== edge.child)
18209
- }))
18210
- } : component
18211
- );
18212
- }
18213
- function withoutSlotChildren(components, removedEdges) {
18214
- return removedEdges.reduce(removeSlotChild, components);
18215
- }
18216
- function partitionDecisions(components, state, removedEdges) {
19629
+ function partitionDecisions(components, state) {
18217
19630
  const accepted = [];
18218
19631
  const rejected = [];
18219
19632
  for (const c2 of components) {
18220
19633
  if (state.get(c2.name) === "accepted") accepted.push(c2.name);
18221
19634
  else rejected.push(c2.name);
18222
19635
  }
18223
- const rejectedNames = new Set(rejected);
18224
- const excludedSlotEdges = removedEdges.filter((e) => !rejectedNames.has(e.parent) && !rejectedNames.has(e.child));
18225
- return { accepted, rejected, excludedSlotEdges };
19636
+ return { accepted, rejected };
18226
19637
  }
18227
19638
 
18228
19639
  // packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/use-scope-gate.ts
18229
- function useScopeGate({ components: loadedComponents, onConfirm, onQuit }) {
19640
+ function useScopeGate({ components, onConfirm, onQuit }) {
18230
19641
  const { columns: totalWidth, rows: terminalRows } = useTerminalSize();
18231
19642
  const columnPlan = useMemo2(() => computeColumnWidths(totalWidth), [totalWidth]);
18232
19643
  const [decisions, setDecisions] = useState12(/* @__PURE__ */ new Map());
18233
- const [removedEdges, setRemovedEdges] = useState12([]);
18234
- const components = useMemo2(
18235
- () => withoutSlotChildren(loadedComponents, removedEdges),
18236
- [loadedComponents, removedEdges]
18237
- );
18238
19644
  const [nav, setNav] = useState12({ cursor: 0, scrollOffset: 0 });
18239
19645
  const [focusedColumn, setFocusedColumn] = useState12("main");
18240
19646
  const [addedComponentsCursor, setAddedComponentsCursor] = useState12(0);
@@ -18406,14 +19812,6 @@ function useScopeGate({ components: loadedComponents, onConfirm, onQuit }) {
18406
19812
  return void 0;
18407
19813
  }
18408
19814
  };
18409
- const focusedNestedEdge = () => {
18410
- const row = visibleRows[safeCursor];
18411
- if (row?.kind !== "group-child" || !row.parentName || row.itemIdx < 0) return void 0;
18412
- const child = groupedItems[row.itemIdx]?.key;
18413
- return child ? { parent: row.parentName, child } : void 0;
18414
- };
18415
- const removeFromParentSlot = (edge) => setRemovedEdges((edges) => [...edges, edge]);
18416
- const undoSlotRemoval = () => setRemovedEdges((edges) => edges.slice(0, -1));
18417
19815
  const jumpCursorTo = (name) => {
18418
19816
  let idx = -1;
18419
19817
  for (let i = 0; i < visibleRows.length; i++) {
@@ -18513,7 +19911,7 @@ function useScopeGate({ components: loadedComponents, onConfirm, onQuit }) {
18513
19911
  onQuit();
18514
19912
  return;
18515
19913
  case "confirm":
18516
- onConfirm(partitionDecisions(components, decisions, removedEdges));
19914
+ onConfirm(partitionDecisions(components, decisions));
18517
19915
  return;
18518
19916
  case "close-help":
18519
19917
  setShowHelp(false);
@@ -18566,11 +19964,6 @@ function useScopeGate({ components: loadedComponents, onConfirm, onQuit }) {
18566
19964
  return;
18567
19965
  }
18568
19966
  case "reject": {
18569
- const edge = focusedColumn === "main" ? focusedNestedEdge() : void 0;
18570
- if (edge) {
18571
- removeFromParentSlot(edge);
18572
- return;
18573
- }
18574
19967
  const key = focusedColumn === "added-components" ? addedComponents[safeAddedComponentsCursor]?.name : focusedRowKey();
18575
19968
  if (key) requestReject(key);
18576
19969
  return;
@@ -18578,9 +19971,6 @@ function useScopeGate({ components: loadedComponents, onConfirm, onQuit }) {
18578
19971
  case "toggle-all":
18579
19972
  decide({ type: "toggle-all" });
18580
19973
  return;
18581
- case "undo":
18582
- undoSlotRemoval();
18583
- return;
18584
19974
  case "accept-unflagged":
18585
19975
  decide({ type: "accept-unflagged" });
18586
19976
  return;
@@ -18851,58 +20241,19 @@ function ScopeGateView({ components, onConfirm, onQuit }) {
18851
20241
  import { useEffect as useEffect8, useMemo as useMemo3, useRef as useRef5, useState as useState13 } from "react";
18852
20242
 
18853
20243
  // packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/cache-check.ts
18854
- import { execFile as execFile2 } from "node:child_process";
18855
-
18856
- // packages/experience-design-system-cli/src/legacy/legacy-cli-path.ts
18857
- import { existsSync as existsSync9 } from "node:fs";
18858
- import { join as join20 } from "node:path";
18859
- var PACKAGE_NAME2 = "@contentful/experience-design-system-cli";
18860
- function findLegacyCliPath() {
18861
- const root = findPackageRoot(import.meta.url, PACKAGE_NAME2);
18862
- const candidates = [
18863
- join20(root, "legacy", "bin", "cli.js"),
18864
- join20(root, "..", "experience-design-system-cli-legacy", "bin", "cli.js")
18865
- ];
18866
- const found = candidates.find((candidate) => existsSync9(candidate));
18867
- if (!found) {
18868
- throw new Error(`Legacy CLI not found. Looked in:
18869
- ${candidates.join("\n")}`);
18870
- }
18871
- return found;
18872
- }
18873
-
18874
- // packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/cache-check.ts
18875
- function buildCacheCheckArgs(input) {
18876
- const args = ["__generate", "components", "--agent", input.agent, "--session", input.sessionId];
18877
- if (input.tokensPath) args.push("--tokens", input.tokensPath);
18878
- if (input.agentModel) args.push("--model", input.agentModel);
18879
- if (input.noCache) args.push("--no-cache");
18880
- for (const prompt of input.promptOverrides) args.push("--prompt", prompt);
18881
- if (input.existingEntitiesPath) args.push("--existing-entities-path", input.existingEntitiesPath);
18882
- args.push("--cache-status", "--restore-cache");
18883
- return args;
18884
- }
18885
- function parseCacheComponents(stdout) {
18886
- const line = /^cache-components=(.+)$/m.exec(stdout)?.[1];
18887
- if (!line) return [];
18888
- try {
18889
- const names = JSON.parse(line);
18890
- return Array.isArray(names) ? names.filter((name) => typeof name === "string") : [];
18891
- } catch {
18892
- return [];
18893
- }
18894
- }
18895
- var runLegacyCli = (args) => new Promise((resolve22) => {
18896
- execFile2("node", [findLegacyCliPath(), ...args], (error, stdout, stderr) => {
18897
- resolve22({ exitCode: error?.code ? Number(error.code) : 0, stdout, stderr });
18898
- });
18899
- });
18900
- async function checkGenerationCache(input, run = runLegacyCli) {
20244
+ async function checkGenerationCache(input) {
18901
20245
  if (input.noCache) return [];
18902
20246
  try {
18903
- const result = await run(buildCacheCheckArgs(input));
18904
- if (result.exitCode !== 0) return [];
18905
- return parseCacheComponents(result.stdout);
20247
+ const result = await checkGenerateComponentsCache({
20248
+ sessionId: input.sessionId,
20249
+ agent: input.agent,
20250
+ ...input.agentModel ? { agentModel: input.agentModel } : {},
20251
+ promptOverrides: input.promptOverrides,
20252
+ existingEntitiesPath: input.existingEntitiesPath,
20253
+ noCache: input.noCache,
20254
+ restoreCache: true
20255
+ });
20256
+ return result.cachedComponentNames;
18906
20257
  } catch {
18907
20258
  return [];
18908
20259
  }
@@ -18951,33 +20302,6 @@ function useScopeGateFlow(input, deps = realDeps2) {
18951
20302
  function initialProgress2() {
18952
20303
  return { components: null, mapTokens: "idle", mapTokensEligible: null };
18953
20304
  }
18954
- var PROGRESS_LINE = /^progress=generate:(\d+)\/(\d+):(.+)$/;
18955
- var STARTED_LINE = /\[(\d+)\/(\d+)\]\s+(.+)/;
18956
- function applyGenerateStderr(chunk, previous) {
18957
- let state = previous;
18958
- for (const line of chunk.split("\n")) {
18959
- const finished = PROGRESS_LINE.exec(line);
18960
- if (finished) {
18961
- state = { done: Number(finished[1]), total: Number(finished[2]), current: finished[3].trim() };
18962
- continue;
18963
- }
18964
- const started = STARTED_LINE.exec(line);
18965
- if (started) {
18966
- state = { done: state?.done ?? 0, total: Number(started[2]), current: started[3].trim() };
18967
- }
18968
- }
18969
- return state;
18970
- }
18971
- function parseGenerateResult(output, fallbackCount) {
18972
- const session = /^session=(.+)$/m.exec(output.stdout);
18973
- const count = /(\d+) components?/.exec(output.stderr);
18974
- const renamed = /^renamed-slots:\s*(\d+)$/m.exec(output.stdout);
18975
- return {
18976
- generateSessionId: session ? session[1].trim() : null,
18977
- generatedCount: count ? Number(count[1]) : fallbackCount,
18978
- renamedSlotsCount: renamed ? Number(renamed[1]) : 0
18979
- };
18980
- }
18981
20305
  function shouldRunMapTokens(counts) {
18982
20306
  return counts.mappablePropCount > 0 && counts.rawTokenCount > 0;
18983
20307
  }
@@ -19033,17 +20357,215 @@ function GenerationScreen({
19033
20357
  );
19034
20358
  }
19035
20359
 
19036
- // packages/experience-design-system-cli/src/tui/import/steps/08-generation/use-generation.ts
19037
- import { useEffect as useEffect9, useRef as useRef6, useState as useState14 } from "react";
19038
-
19039
- // packages/experience-design-system-generation/dist/src/agent-names.js
19040
- var AGENT_BINARIES2 = {
19041
- claude: "claude",
19042
- codex: "codex",
19043
- opencode: "opencode",
19044
- cursor: "cursor-agent",
19045
- copilot: "copilot"
19046
- };
20360
+ // packages/experience-design-system-cli/src/tui/import/steps/08-generation/use-generation.ts
20361
+ import { useEffect as useEffect9, useRef as useRef6, useState as useState14 } from "react";
20362
+
20363
+ // packages/experience-design-system-cli/src/tui/import/steps/08-generation/run.ts
20364
+ import { resolve as resolve23 } from "node:path";
20365
+
20366
+ // packages/experience-design-system-cli/src/tui/import/steps/08-generation/map-tokens.ts
20367
+ async function prepareMapTokens(input, generatedSessionId) {
20368
+ const db = openPipelineDb();
20369
+ try {
20370
+ if (input.tokenSessionId && input.tokenSessionId !== generatedSessionId) {
20371
+ copyTokensFromCache(db, input.tokenSessionId, generatedSessionId);
20372
+ } else if (!input.tokenSessionId && input.tokensPath) {
20373
+ const tokens = await readTokensFromPath2({ flag: "tokens", path: input.tokensPath });
20374
+ storeDtcgTokens(db, generatedSessionId, [], tokens);
20375
+ }
20376
+ const mappablePropCount = loadCDFComponents(db, generatedSessionId).reduce(
20377
+ (count, { entry }) => count + Object.values(entry.$properties).filter((prop) => prop.$type === "token" && prop.$category === "design").length,
20378
+ 0
20379
+ );
20380
+ const rawTokenCount = getDtcgTokensForSession(db, generatedSessionId).tokens.length;
20381
+ return {
20382
+ eligible: shouldRunMapTokens({ mappablePropCount, rawTokenCount }),
20383
+ mappablePropCount,
20384
+ rawTokenCount
20385
+ };
20386
+ } finally {
20387
+ db.close();
20388
+ }
20389
+ }
20390
+
20391
+ // packages/experience-design-system-cli/src/tui/import/steps/08-generation/save-decisions.ts
20392
+ async function saveDecisions(input) {
20393
+ const db = openPipelineDb();
20394
+ try {
20395
+ applyScopeDecisions(db, input.sessionId, input.decisions);
20396
+ await writeScopeDecisionsSnapshot(db, input.sessionId, input.decisions);
20397
+ } finally {
20398
+ db.close();
20399
+ }
20400
+ }
20401
+
20402
+ // packages/experience-design-system-cli/src/tui/import/steps/08-generation/run.ts
20403
+ var realDeps3 = {
20404
+ checkAgentAuth,
20405
+ saveDecisions,
20406
+ runGenerate: runGenerateComponentsSession,
20407
+ runMapTokens,
20408
+ prepareMapTokens
20409
+ };
20410
+ var fail2 = (step, message) => ({ ok: false, step, message });
20411
+ var errorMessage3 = (error) => error instanceof Error ? error.message : String(error);
20412
+ async function runGeneration(input, onProgress, deps = realDeps3) {
20413
+ let progress = { components: null, mapTokens: "idle", mapTokensEligible: null };
20414
+ const update = (change) => {
20415
+ progress = { ...progress, ...change };
20416
+ onProgress(progress);
20417
+ };
20418
+ const accepted = input.decisions.accepted;
20419
+ const handedOverNames = await input.cachedNames.catch(() => []);
20420
+ try {
20421
+ await deps.saveDecisions({ sessionId: input.sessionId, decisions: input.decisions });
20422
+ } catch (error) {
20423
+ return fail2("save decisions", errorMessage3(error));
20424
+ }
20425
+ if (accepted.length === 0) return { ok: true, generation: { route: "push", acceptedCount: 0 } };
20426
+ const auth = await deps.checkAgentAuth(input.agent);
20427
+ if (auth === "not-found" || auth === "unauthenticated") {
20428
+ return fail2(`${input.agent} auth check`, agentAuthMessage(input.agent, auth));
20429
+ }
20430
+ let generated;
20431
+ try {
20432
+ generated = await deps.runGenerate({
20433
+ sessionId: input.sessionId,
20434
+ agent: input.agent,
20435
+ ...input.agentModel ? { agentModel: input.agentModel } : {},
20436
+ promptOverrides: appendGeneratePromptOverride(input),
20437
+ noCache: input.noCache,
20438
+ existingEntitiesPath: input.existingEntitiesPath,
20439
+ precomputedCachedNames: new Set(handedOverNames),
20440
+ onProgress: (event) => update({ components: applyProgressEvent2(event, progress.components, accepted.length) })
20441
+ });
20442
+ } catch (error) {
20443
+ return fail2("generate components", errorMessage3(error));
20444
+ }
20445
+ if (generated.emptySession) return fail2("generate components", "no raw components in session");
20446
+ if (!generated.allOk) {
20447
+ const firstFailure = generated.results.find((r) => r.failed);
20448
+ return fail2("generate components", firstFailure?.error ?? "unknown error");
20449
+ }
20450
+ let plan;
20451
+ try {
20452
+ plan = await deps.prepareMapTokens(input, input.sessionId);
20453
+ } catch (error) {
20454
+ return fail2("map tokens", errorMessage3(error));
20455
+ }
20456
+ update({ mapTokensEligible: plan.eligible });
20457
+ if (plan.eligible) {
20458
+ update({ mapTokens: "running" });
20459
+ try {
20460
+ const mapTokensOptions = await buildMapTokensOptions(input);
20461
+ await deps.runMapTokens({
20462
+ sessionId: input.sessionId,
20463
+ agent: input.agent,
20464
+ ...input.agentModel ? { model: input.agentModel } : {},
20465
+ cache: !input.noCache,
20466
+ ...mapTokensOptions
20467
+ });
20468
+ } catch (error) {
20469
+ const message = error instanceof MapTokensRunFailure ? error.message : error instanceof Error ? error.message : String(error);
20470
+ return fail2("map tokens", message);
20471
+ }
20472
+ }
20473
+ update({ mapTokens: "complete" });
20474
+ const generatedCount = generated.results.filter((r) => !r.failed).length;
20475
+ return {
20476
+ ok: true,
20477
+ generation: {
20478
+ route: "review",
20479
+ sessionId: input.sessionId,
20480
+ acceptedCount: accepted.length,
20481
+ generatedCount,
20482
+ mapTokensEligible: plan.eligible
20483
+ }
20484
+ };
20485
+ }
20486
+ async function buildMapTokensOptions(input) {
20487
+ const { overrides: parsed, errors } = parsePromptOverrides(input.promptOverrides);
20488
+ if (errors.length > 0) throw new Error(errors.join("; "));
20489
+ const mapOverride = parsed.get("map-tokens");
20490
+ const prompt = {};
20491
+ if (mapOverride?.kind === "text") prompt.skillContentOverride = mapOverride.value;
20492
+ if (mapOverride?.kind === "path") {
20493
+ await resolvePromptOverride(mapOverride);
20494
+ prompt.skillPathOverride = resolve23(mapOverride.value);
20495
+ }
20496
+ if (input.existingEntitiesPath) {
20497
+ const entities = await readExistingContentfulEntitiesFromSession({ path: input.existingEntitiesPath });
20498
+ if (entities) return { ...prompt, existingEntitiesInline: JSON.stringify(summarizeForMapTokens({ entities })) };
20499
+ }
20500
+ return prompt;
20501
+ }
20502
+ function appendGeneratePromptOverride(input) {
20503
+ if (!input.generatePromptPath) return input.promptOverrides;
20504
+ const already = input.promptOverrides.some((override) => override.startsWith("generate="));
20505
+ if (already) return input.promptOverrides;
20506
+ return [...input.promptOverrides, `generate=${input.generatePromptPath}`];
20507
+ }
20508
+ function applyProgressEvent2(event, previous, total) {
20509
+ if (event.kind === "component:started") {
20510
+ return { done: previous?.done ?? 0, total: event.total || total, current: event.name };
20511
+ }
20512
+ if (event.kind === "component:completed" || event.kind === "component:failed" || event.kind === "component:cached") {
20513
+ return { done: (previous?.done ?? 0) + 1, total: event.total || total, current: event.name };
20514
+ }
20515
+ return previous;
20516
+ }
20517
+
20518
+ // packages/experience-design-system-cli/src/tui/import/steps/08-generation/use-generation.ts
20519
+ function useGeneration(input) {
20520
+ const [state, setState] = useState14();
20521
+ const current = useRef6();
20522
+ useEffect9(() => {
20523
+ current.current = input;
20524
+ if (!input) {
20525
+ setState(void 0);
20526
+ return;
20527
+ }
20528
+ setState({ status: "running", progress: initialProgress2() });
20529
+ void runGeneration(input, (progress) => {
20530
+ if (current.current === input) setState({ status: "running", progress });
20531
+ }).then((result) => {
20532
+ if (current.current === input) setState({ status: "done", result });
20533
+ });
20534
+ return () => {
20535
+ if (current.current === input) current.current = void 0;
20536
+ };
20537
+ }, [input]);
20538
+ return state;
20539
+ }
20540
+
20541
+ // packages/experience-design-system-cli/src/tui/import/steps/10-flow/flow/build-flow-start.ts
20542
+ import { join as join20 } from "node:path";
20543
+ function buildFlowStart(input) {
20544
+ const { extraction, handoff, saved, generatePromptPath } = input;
20545
+ const credentials = extraction.credentials ?? {
20546
+ spaceId: saved?.spaceId ?? "",
20547
+ environmentId: saved?.environmentId ?? "",
20548
+ cmaToken: saved?.cmaToken ?? "",
20549
+ host: saved?.host ?? ""
20550
+ };
20551
+ return {
20552
+ handoff,
20553
+ agent: extraction.agent,
20554
+ projectPath: extraction.projectPath,
20555
+ outDir: extraction.projectPath ? join20(extraction.projectPath, ".contentful") : "",
20556
+ rawTokensPath: extraction.rawTokensPath,
20557
+ credentials: {
20558
+ spaceId: credentials.spaceId,
20559
+ environmentId: credentials.environmentId || "master",
20560
+ cmaToken: credentials.cmaToken,
20561
+ host: toConfiguredHost2(credentials.host) ?? DEFAULT_CONFIGURED_HOST
20562
+ },
20563
+ ...generatePromptPath ? { generatePromptPath } : {}
20564
+ };
20565
+ }
20566
+
20567
+ // packages/experience-design-system-cli/src/tui/import/steps/10-flow/flow/screen.tsx
20568
+ import { Box as Box41 } from "ink";
19047
20569
 
19048
20570
  // packages/experience-design-system-types/dist/src/cdf/validate.js
19049
20571
  import { Ajv as Ajv2 } from "ajv";
@@ -19328,315 +20850,6 @@ var DTCGTokenSchema2 = z4.strictObject({
19328
20850
  // packages/experience-design-system-types/dist/src/dtcg/validate.js
19329
20851
  var TOKEN_TYPE_SET4 = new Set(DESIGN_TOKEN_TYPES2);
19330
20852
 
19331
- // packages/experience-design-system-generation/dist/src/services/agent/helpers/resolve-agent-binary.js
19332
- function resolveAgentBinary(agent) {
19333
- const envKey = `EDS_AGENT_BINARY_${agent.toUpperCase()}`;
19334
- const override = process.env[envKey];
19335
- if (override && override.trim())
19336
- return override.trim();
19337
- return AGENT_BINARIES2[agent];
19338
- }
19339
-
19340
- // packages/experience-design-system-generation/dist/src/services/agent/helpers/check-agent-auth.js
19341
- import { spawn as spawn4 } from "node:child_process";
19342
-
19343
- // packages/experience-design-system-generation/dist/src/services/agent/helpers/check-claude-auth.js
19344
- import { spawn as spawn3 } from "node:child_process";
19345
- function checkClaudeAuth(binary) {
19346
- return new Promise((resolve22) => {
19347
- const child = spawn3(binary, ["auth", "status", "--json"], {
19348
- stdio: ["ignore", "pipe", "pipe"]
19349
- });
19350
- let stdout = "";
19351
- let done = false;
19352
- const timer = setTimeout(() => {
19353
- if (!done) {
19354
- done = true;
19355
- child.kill("SIGTERM");
19356
- resolve22("unauthenticated");
19357
- }
19358
- }, 5e3);
19359
- child.stdout?.on("data", (chunk) => {
19360
- stdout += chunk.toString();
19361
- });
19362
- child.on("close", (code) => {
19363
- if (done)
19364
- return;
19365
- done = true;
19366
- clearTimeout(timer);
19367
- if (code !== 0) {
19368
- resolve22("unauthenticated");
19369
- return;
19370
- }
19371
- try {
19372
- const status = JSON.parse(stdout);
19373
- resolve22(status.loggedIn ? "ok" : "unauthenticated");
19374
- } catch {
19375
- resolve22("unauthenticated");
19376
- }
19377
- });
19378
- });
19379
- }
19380
-
19381
- // packages/experience-design-system-generation/dist/src/services/agent/helpers/check-agent-auth.js
19382
- async function checkAgentAuth2(agent) {
19383
- const binary = resolveAgentBinary(agent);
19384
- const binaryExists2 = await new Promise((resolve22) => {
19385
- if (binary.startsWith("/")) {
19386
- import("node:fs/promises").then((fs) => fs.access(binary).then(() => resolve22(true), () => resolve22(false)));
19387
- return;
19388
- }
19389
- const child = spawn4(process.platform === "win32" ? "where" : "which", [binary], { stdio: "ignore" });
19390
- child.on("close", (code) => resolve22(code === 0));
19391
- });
19392
- if (!binaryExists2)
19393
- return "not-found";
19394
- if (agent !== "claude")
19395
- return "ok";
19396
- return checkClaudeAuth(binary);
19397
- }
19398
-
19399
- // packages/experience-design-system-cli/src/tui/import/steps/08-generation/map-tokens.ts
19400
- async function prepareMapTokens(input, generatedSessionId) {
19401
- const db = openPipelineDb();
19402
- try {
19403
- if (input.tokenSessionId && input.tokenSessionId !== generatedSessionId) {
19404
- copyTokensFromCache(db, input.tokenSessionId, generatedSessionId);
19405
- } else if (!input.tokenSessionId && input.tokensPath) {
19406
- const tokens = await readTokensFromPath2({ flag: "tokens", path: input.tokensPath });
19407
- storeDtcgTokens(db, generatedSessionId, [], tokens);
19408
- }
19409
- const mappablePropCount = loadCDFComponents(db, generatedSessionId).reduce(
19410
- (count, { entry }) => count + Object.values(entry.$properties).filter((prop) => prop.$type === "token" && prop.$category === "design").length,
19411
- 0
19412
- );
19413
- const rawTokenCount = getDtcgTokensForSession(db, generatedSessionId).tokens.length;
19414
- return {
19415
- eligible: shouldRunMapTokens({ mappablePropCount, rawTokenCount }),
19416
- mappablePropCount,
19417
- rawTokenCount
19418
- };
19419
- } finally {
19420
- db.close();
19421
- }
19422
- }
19423
-
19424
- // packages/experience-design-system-cli/src/tui/import/steps/08-generation/processes.ts
19425
- import { execFile as execFile3, spawn as spawn5 } from "node:child_process";
19426
- function buildGenerateArgs(cliPath, command) {
19427
- const args = [cliPath, "__generate", "components", "--agent", command.agent, "--session", command.sessionId];
19428
- if (command.tokensPath) args.push("--tokens", command.tokensPath);
19429
- if (command.agentModel) args.push("--model", command.agentModel);
19430
- if (command.noCache) args.push("--no-cache");
19431
- if (command.generatePromptPath) args.push("--generate-prompt-path", command.generatePromptPath);
19432
- for (const prompt of command.promptOverrides) args.push("--prompt", prompt);
19433
- if (command.existingEntitiesPath) args.push("--existing-entities-path", command.existingEntitiesPath);
19434
- if (command.cachedComponents.length > 0) args.push("--cached-components", JSON.stringify(command.cachedComponents));
19435
- return args;
19436
- }
19437
- function buildMapTokensArgs(command) {
19438
- const args = ["map", "tokens", "--session", command.sessionId, "--agent", command.agent];
19439
- if (command.agentModel) args.push("--model", command.agentModel);
19440
- if (command.noCache) args.push("--no-cache");
19441
- for (const prompt of command.promptOverrides) args.push("--prompt", prompt);
19442
- if (command.existingEntitiesPath) args.push("--existing-entities-path", command.existingEntitiesPath);
19443
- return args;
19444
- }
19445
- function spawnGenerate(command, handlers) {
19446
- return new Promise((resolve22) => {
19447
- const child = spawn5("node", buildGenerateArgs(findLegacyCliPath(), command));
19448
- let stdout = "";
19449
- let stderr = "";
19450
- child.stdout.on("data", (data) => {
19451
- stdout += String(data);
19452
- });
19453
- child.stderr.on("data", (data) => {
19454
- const chunk = String(data);
19455
- stderr += chunk;
19456
- handlers.onStderr(chunk);
19457
- });
19458
- child.on("error", (error) => resolve22({ exitCode: 1, stdout, stderr: stderr + error.message }));
19459
- child.on("close", (code) => resolve22({ exitCode: code ?? 0, stdout, stderr }));
19460
- });
19461
- }
19462
- function runMapTokens2(command) {
19463
- return new Promise((resolve22) => {
19464
- execFile3("node", [findLegacyCliPath(), ...buildMapTokensArgs(command)], (error, stdout, stderr) => {
19465
- resolve22({ exitCode: error?.code ? Number(error.code) : 0, stdout, stderr });
19466
- });
19467
- });
19468
- }
19469
-
19470
- // packages/experience-design-system-cli/src/tui/import/steps/08-generation/save-decisions.ts
19471
- async function saveDecisions(input) {
19472
- const db = openPipelineDb();
19473
- try {
19474
- applyScopeDecisions(db, input.sessionId, input.decisions);
19475
- await writeScopeDecisionsSnapshot(db, input.sessionId, input.decisions);
19476
- } finally {
19477
- db.close();
19478
- }
19479
- }
19480
-
19481
- // packages/experience-design-system-cli/src/tui/import/steps/08-generation/run.ts
19482
- var realDeps3 = {
19483
- checkAgentAuth: checkAgentAuth2,
19484
- saveDecisions,
19485
- checkCache: checkGenerationCache,
19486
- spawnGenerate,
19487
- prepareMapTokens,
19488
- runMapTokens: runMapTokens2
19489
- };
19490
- var fail2 = (step, message) => ({ ok: false, step, message });
19491
- var errorMessage3 = (error) => error instanceof Error ? error.message : String(error);
19492
- async function runGeneration(input, onProgress, deps = realDeps3) {
19493
- let progress = initialProgress2();
19494
- const update = (change) => {
19495
- progress = { ...progress, ...change };
19496
- onProgress(progress);
19497
- };
19498
- const accepted = input.decisions.accepted;
19499
- const handedOverNames = await input.cachedNames.catch(() => []);
19500
- try {
19501
- await deps.saveDecisions({ sessionId: input.sessionId, decisions: input.decisions });
19502
- } catch (error) {
19503
- return fail2("save decisions", errorMessage3(error));
19504
- }
19505
- if (accepted.length === 0) return { ok: true, generation: { route: "push", acceptedCount: 0 } };
19506
- const auth = await deps.checkAgentAuth(input.agent);
19507
- if (auth === "not-found" || auth === "unauthenticated") {
19508
- return fail2(`${input.agent} auth check`, agentAuthMessage(input.agent, auth));
19509
- }
19510
- const acceptedSet = new Set(accepted);
19511
- let cachedNames = handedOverNames;
19512
- let cacheHit = !input.noCache && accepted.length > 0 && accepted.every((name) => cachedNames.includes(name));
19513
- if (!cacheHit && !input.noCache && accepted.length > 0) {
19514
- const fresh = await deps.checkCache(cacheCheckFor(input));
19515
- cachedNames = fresh.filter((name) => acceptedSet.has(name));
19516
- cacheHit = accepted.every((name) => cachedNames.includes(name));
19517
- }
19518
- let generatedSessionId = input.sessionId;
19519
- let generatedCount = accepted.length;
19520
- if (!cacheHit) {
19521
- const result = await deps.spawnGenerate(
19522
- {
19523
- sessionId: input.sessionId,
19524
- tokensPath: input.tokensPath,
19525
- agent: input.agent,
19526
- ...input.agentModel ? { agentModel: input.agentModel } : {},
19527
- promptOverrides: input.promptOverrides,
19528
- ...input.generatePromptPath ? { generatePromptPath: input.generatePromptPath } : {},
19529
- noCache: input.noCache,
19530
- existingEntitiesPath: input.existingEntitiesPath,
19531
- cachedComponents: cachedNames
19532
- },
19533
- {
19534
- onStderr: (chunk) => {
19535
- const components = applyGenerateStderr(chunk, progress.components);
19536
- if (components !== progress.components) update({ components });
19537
- }
19538
- }
19539
- );
19540
- if (result.exitCode !== 0) return fail2("generate components", result.stderr.trim() || "Unknown error");
19541
- const parsed = parseGenerateResult(result, accepted.length);
19542
- generatedSessionId = parsed.generateSessionId ?? input.sessionId;
19543
- generatedCount = parsed.generatedCount;
19544
- }
19545
- let plan;
19546
- try {
19547
- plan = await deps.prepareMapTokens(input, generatedSessionId);
19548
- } catch (error) {
19549
- return fail2("map tokens", errorMessage3(error));
19550
- }
19551
- update({ mapTokensEligible: plan.eligible });
19552
- if (plan.eligible) {
19553
- update({ mapTokens: "running" });
19554
- const mapped = await deps.runMapTokens({
19555
- sessionId: generatedSessionId,
19556
- agent: input.agent,
19557
- ...input.agentModel ? { agentModel: input.agentModel } : {},
19558
- promptOverrides: input.promptOverrides,
19559
- noCache: input.noCache,
19560
- existingEntitiesPath: input.existingEntitiesPath
19561
- });
19562
- if (mapped.exitCode !== 0) return fail2("map tokens", mapped.stderr.trim() || "Unknown error");
19563
- }
19564
- update({ mapTokens: "complete" });
19565
- return {
19566
- ok: true,
19567
- generation: {
19568
- route: "review",
19569
- sessionId: generatedSessionId,
19570
- acceptedCount: accepted.length,
19571
- generatedCount,
19572
- mapTokensEligible: plan.eligible
19573
- }
19574
- };
19575
- }
19576
- function cacheCheckFor(input) {
19577
- return {
19578
- sessionId: input.sessionId,
19579
- tokensPath: input.tokensPath,
19580
- agent: input.agent,
19581
- ...input.agentModel ? { agentModel: input.agentModel } : {},
19582
- promptOverrides: input.promptOverrides,
19583
- existingEntitiesPath: input.existingEntitiesPath,
19584
- noCache: input.noCache
19585
- };
19586
- }
19587
-
19588
- // packages/experience-design-system-cli/src/tui/import/steps/08-generation/use-generation.ts
19589
- function useGeneration(input) {
19590
- const [state, setState] = useState14();
19591
- const current = useRef6();
19592
- useEffect9(() => {
19593
- current.current = input;
19594
- if (!input) {
19595
- setState(void 0);
19596
- return;
19597
- }
19598
- setState({ status: "running", progress: initialProgress2() });
19599
- void runGeneration(input, (progress) => {
19600
- if (current.current === input) setState({ status: "running", progress });
19601
- }).then((result) => {
19602
- if (current.current === input) setState({ status: "done", result });
19603
- });
19604
- return () => {
19605
- if (current.current === input) current.current = void 0;
19606
- };
19607
- }, [input]);
19608
- return state;
19609
- }
19610
-
19611
- // packages/experience-design-system-cli/src/tui/import/steps/10-flow/flow/build-flow-start.ts
19612
- import { join as join21 } from "node:path";
19613
- function buildFlowStart(input) {
19614
- const { extraction, handoff, saved, generatePromptPath } = input;
19615
- const credentials = extraction.credentials ?? {
19616
- spaceId: saved?.spaceId ?? "",
19617
- environmentId: saved?.environmentId ?? "",
19618
- cmaToken: saved?.cmaToken ?? "",
19619
- host: saved?.host ?? ""
19620
- };
19621
- return {
19622
- handoff,
19623
- agent: extraction.agent,
19624
- projectPath: extraction.projectPath,
19625
- outDir: extraction.projectPath ? join21(extraction.projectPath, ".contentful") : "",
19626
- rawTokensPath: extraction.rawTokensPath,
19627
- credentials: {
19628
- spaceId: credentials.spaceId,
19629
- environmentId: credentials.environmentId || "master",
19630
- cmaToken: credentials.cmaToken,
19631
- host: toConfiguredHost2(credentials.host) ?? DEFAULT_CONFIGURED_HOST
19632
- },
19633
- ...generatePromptPath ? { generatePromptPath } : {}
19634
- };
19635
- }
19636
-
19637
- // packages/experience-design-system-cli/src/tui/import/steps/10-flow/flow/screen.tsx
19638
- import { Box as Box41 } from "ink";
19639
-
19640
20853
  // packages/experience-design-system-cli/src/tui/import/steps/preview-validation-error/logic.ts
19641
20854
  function failedComponentNames(errors) {
19642
20855
  return [...new Set(errors.map((error) => error.componentName))];
@@ -19662,8 +20875,8 @@ function missingNote(missingNames) {
19662
20875
  Note: ${plural2(missingNames.length, "component name")} from the server (${missingNames.join(", ")}) ${verb} not match anything in this session \u2014 they cannot be edited or skipped from here.`;
19663
20876
  }
19664
20877
  function contextText(errors, missingNames) {
19665
- const failed = failedComponentNames(errors);
19666
- return `${plural2(failed.length, "component")} failed server validation. Edit their definitions in the review TUI, or skip them and retry preview without them.${missingNote(missingNames)}`;
20878
+ const failed2 = failedComponentNames(errors);
20879
+ return `${plural2(failed2.length, "component")} failed server validation. Edit their definitions in the review TUI, or skip them and retry preview without them.${missingNote(missingNames)}`;
19667
20880
  }
19668
20881
  function skipLabel(matchedNames) {
19669
20882
  if (matchedNames.length === 0) return "No matching components to skip";
@@ -21394,8 +22607,8 @@ function FieldEditor({
21394
22607
  return /* @__PURE__ */ jsxs22(Box21, { flexDirection: "column", width, borderStyle: "single", borderColor: PALETTE3.warning, children: [
21395
22608
  /* @__PURE__ */ jsx27(Text23, { bold: true, color: PALETTE3.warning, children: "FIELD EDITOR \u2014 no fields" }),
21396
22609
  /* @__PURE__ */ jsx27(Text23, { color: PALETTE3.warning, children: "\u26A0 No properties classified for this component. The LLM didn't find anything to classify." }),
21397
- /* @__PURE__ */ jsx27(Text23, { color: PALETTE3.muted, children: "There is nothing to edit here." }),
21398
- /* @__PURE__ */ jsx27(Text23, { color: PALETTE3.muted, children: active ? "[Esc] go back to the list" : "In the list: [r] reject this component \xB7 [a] accept it" })
22610
+ /* @__PURE__ */ jsx27(Text23, { color: PALETTE3.muted, children: "You can add fields manually below or reject this component." }),
22611
+ /* @__PURE__ */ jsx27(Text23, { color: PALETTE3.muted, children: "Enter to save \xB7 Esc to discard" })
21399
22612
  ] });
21400
22613
  }
21401
22614
  const hasEmptyProperties = props.length === 0 && slots.length === 0;
@@ -21610,7 +22823,7 @@ function FieldEditor({
21610
22823
  children: [
21611
22824
  hasEmptyProperties && /* @__PURE__ */ jsx27(Text23, { color: PALETTE3.warning, children: "\u26A0 No properties classified for this component. The LLM didn't find anything to classify. Reject this component or add fields manually." }),
21612
22825
  header,
21613
- /* @__PURE__ */ jsx27(Box21, { flexDirection: "column", width: innerWidth, flexShrink: 0, children: focusLevel === "field" && !inComponentDesc && !inSlots && currentProp ? /* @__PURE__ */ jsx27(
22826
+ /* @__PURE__ */ jsx27(Box21, { flexDirection: "column", width: innerWidth, flexShrink: 0, children: focusLevel === "field" && !inComponentDesc && currentProp ? /* @__PURE__ */ jsx27(
21614
22827
  PropRow,
21615
22828
  {
21616
22829
  prop: currentProp,
@@ -22519,7 +23732,6 @@ function finalizeReviewSession(extractSessionId, components) {
22519
23732
  db.exec("ROLLBACK");
22520
23733
  throw error;
22521
23734
  }
22522
- removeSlotAllowedComponents(db, extractSessionId, [], toReject);
22523
23735
  } finally {
22524
23736
  db.close();
22525
23737
  }
@@ -22597,10 +23809,10 @@ var TimeoutError = class extends Error {
22597
23809
  this.name = "TimeoutError";
22598
23810
  }
22599
23811
  };
22600
- var DEFAULT_TIMEOUT_MS5 = 15e3;
23812
+ var DEFAULT_TIMEOUT_MS6 = 15e3;
22601
23813
  async function runLivePreview(opts) {
22602
23814
  const { sessionId, tokensPath, spaceId, environmentId, cmaToken, host, generation } = opts;
22603
- const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS5;
23815
+ const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS6;
22604
23816
  if (!spaceId || !environmentId || !cmaToken) {
22605
23817
  return { generation, response: null };
22606
23818
  }
@@ -24251,50 +25463,33 @@ function GenerateReviewStepView({
24251
25463
  const cycle = cycleRows[cyclesCursor];
24252
25464
  return cycle ? enumerateCycleBreaks(cycle, components) : [];
24253
25465
  }, [cycleRows, cyclesCursor, components]);
24254
- const saveSlotChange = (parentKey, nextEntry, historyLabel) => {
25466
+ const handleBreakEdge = (edge) => {
25467
+ const target = components.find((component) => component.key === edge.fromComponent);
25468
+ const slot = target?.entry.$slots?.[edge.slotName];
25469
+ if (!target || !slot || !Array.isArray(slot.$allowedComponents)) return;
25470
+ const nextEntry = {
25471
+ ...target.entry,
25472
+ $slots: {
25473
+ ...target.entry.$slots,
25474
+ [edge.slotName]: {
25475
+ ...slot,
25476
+ $allowedComponents: slot.$allowedComponents.filter((value) => value !== edge.toComponent)
25477
+ }
25478
+ }
25479
+ };
24255
25480
  const next = components.map(
24256
- (component) => component.key === parentKey ? { ...component, entry: nextEntry } : component
25481
+ (component) => component.key === target.key ? { ...component, entry: nextEntry } : component
24257
25482
  );
24258
25483
  setComponents(next);
24259
25484
  const db = openPipelineDb();
24260
25485
  try {
24261
- storeCDFComponents(db, extractSessionId, [{ key: parentKey, entry: nextEntry }]);
25486
+ storeCDFComponents(db, extractSessionId, [{ key: target.key, entry: nextEntry }]);
24262
25487
  } finally {
24263
25488
  db.close();
24264
25489
  }
24265
25490
  recomputeCycles(next);
24266
25491
  livePreviewHook.trigger();
24267
- pushHistorySnapshot(next, historyLabel);
24268
- };
24269
- const handleBreakEdge = (edge) => {
24270
- const target = components.find((component) => component.key === edge.fromComponent);
24271
- const slot = target?.entry.$slots?.[edge.slotName];
24272
- if (!target || !slot || !Array.isArray(slot.$allowedComponents)) return;
24273
- saveSlotChange(
24274
- target.key,
24275
- {
24276
- ...target.entry,
24277
- $slots: {
24278
- ...target.entry.$slots,
24279
- [edge.slotName]: {
24280
- ...slot,
24281
- $allowedComponents: slot.$allowedComponents.filter((value) => value !== edge.toComponent)
24282
- }
24283
- }
24284
- },
24285
- "break-cycle-edge"
24286
- );
24287
- };
24288
- const handleRemoveSlotChild = (parentKey, childKey) => {
24289
- const parent = components.find((component) => component.key === parentKey);
24290
- if (!parent?.entry.$slots) return;
24291
- const slots = Object.fromEntries(
24292
- Object.entries(parent.entry.$slots).map(([slotName, slot]) => [
24293
- slotName,
24294
- Array.isArray(slot.$allowedComponents) ? { ...slot, $allowedComponents: slot.$allowedComponents.filter((value) => value !== childKey) } : slot
24295
- ])
24296
- );
24297
- saveSlotChange(parentKey, { ...parent.entry, $slots: slots }, "remove-slot-child");
25492
+ pushHistorySnapshot(next, "break-cycle-edge");
24298
25493
  };
24299
25494
  const handleRejectComponent = (key) => {
24300
25495
  const rejectCascade2 = computeRejectCascade(key, componentGraph);
@@ -24624,11 +25819,6 @@ function GenerateReviewStepView({
24624
25819
  if (input === "r") {
24625
25820
  const current = components[selectedIdx];
24626
25821
  if (!current) return;
24627
- const row = visibleRowsMemo[cursorRowIdx];
24628
- if (row?.kind === "group-child" && row.parentName) {
24629
- handleRemoveSlotChild(row.parentName, current.key);
24630
- return;
24631
- }
24632
25822
  handleRejectComponent(current.key);
24633
25823
  return;
24634
25824
  }
@@ -25105,10 +26295,10 @@ function DoneStep({
25105
26295
  import { useState as useState24 } from "react";
25106
26296
  import { Box as Box37, Text as Text40 } from "ink";
25107
26297
  import { readdirSync as readdirSync3 } from "node:fs";
25108
- import { dirname as dirname15, basename as basename6, join as join22 } from "node:path";
26298
+ import { dirname as dirname15, basename as basename6, join as join21 } from "node:path";
25109
26299
 
25110
26300
  // packages/experience-design-system-cli/src/tui/import/steps/10-flow/support/path-utils.ts
25111
- import { resolve as resolve21 } from "node:path";
26301
+ import { resolve as resolve24 } from "node:path";
25112
26302
  import { homedir as homedir4 } from "node:os";
25113
26303
  function expandTilde(input) {
25114
26304
  if (input === "~" || input.startsWith("~/") || input.startsWith("~\\")) {
@@ -25122,7 +26312,7 @@ function normalizePath(input) {
25122
26312
  p = p.slice(1, -1);
25123
26313
  }
25124
26314
  p = expandTilde(p);
25125
- return resolve21(p);
26315
+ return resolve24(p);
25126
26316
  }
25127
26317
 
25128
26318
  // packages/experience-design-system-cli/src/tui/import/steps/10-flow/support/use-blinking-cursor.ts
@@ -25151,13 +26341,13 @@ function autocomplete(partial) {
25151
26341
  }
25152
26342
  const matches = entries.filter((e) => e.startsWith(base));
25153
26343
  if (matches.length === 0) return null;
25154
- if (matches.length === 1) return join22(dir, matches[0]);
26344
+ if (matches.length === 1) return join21(dir, matches[0]);
25155
26345
  let prefix = matches[0];
25156
26346
  for (const m of matches) {
25157
26347
  while (!m.startsWith(prefix)) prefix = prefix.slice(0, -1);
25158
26348
  if (!prefix) break;
25159
26349
  }
25160
- return prefix.length > base.length ? join22(dir, prefix) : null;
26350
+ return prefix.length > base.length ? join21(dir, prefix) : null;
25161
26351
  }
25162
26352
  function PathPrompt({
25163
26353
  defaultPath,
@@ -25910,7 +27100,7 @@ import { useEffect as useEffect20, useRef as useRef12, useSyncExternalStore } fr
25910
27100
  import { appendFileSync, writeFileSync } from "node:fs";
25911
27101
  import { mkdir as mkdir8 } from "node:fs/promises";
25912
27102
  import { tmpdir } from "node:os";
25913
- import { join as join24 } from "node:path";
27103
+ import { join as join23 } from "node:path";
25914
27104
 
25915
27105
  // packages/experience-design-system-cli/src/tui/import/steps/10-flow/support/wizard-state-transitions.ts
25916
27106
  function shouldBypassPreview(state) {
@@ -26198,19 +27388,19 @@ function resultOf(operation, preview) {
26198
27388
  const items = operation.items ?? [];
26199
27389
  if (items.length > 0) {
26200
27390
  const count = (entityType, action) => items.filter((i) => i.entityType === entityType && i.action === action && i.status === "succeeded").length;
26201
- const failed = (entityType) => items.filter((i) => i.entityType === entityType && i.status === "failed").length;
27391
+ const failed2 = (entityType) => items.filter((i) => i.entityType === entityType && i.status === "failed").length;
26202
27392
  return {
26203
27393
  componentTypes: {
26204
27394
  created: count("ComponentType", "create"),
26205
27395
  updated: count("ComponentType", "update"),
26206
27396
  removed: count("ComponentType", "delete"),
26207
- failed: failed("ComponentType")
27397
+ failed: failed2("ComponentType")
26208
27398
  },
26209
27399
  designTokens: {
26210
27400
  created: count("DesignToken", "create"),
26211
27401
  updated: count("DesignToken", "update"),
26212
27402
  removed: count("DesignToken", "delete"),
26213
- failed: failed("DesignToken")
27403
+ failed: failed2("DesignToken")
26214
27404
  },
26215
27405
  summary: operation.summary,
26216
27406
  failures: items.filter((item) => item.status === "failed").map((item) => ({
@@ -26255,7 +27445,7 @@ function pushFailure(e, deps) {
26255
27445
 
26256
27446
  // packages/experience-design-system-cli/src/tui/import/steps/10-flow/flow/save.ts
26257
27447
  import { writeFile as writeFile7 } from "node:fs/promises";
26258
- import { join as join23 } from "node:path";
27448
+ import { join as join22 } from "node:path";
26259
27449
 
26260
27450
  // packages/experience-design-system-cli/src/tui/import/steps/10-flow/support/run-print-files-helpers.ts
26261
27451
  function nextStateAfterPrint(opts) {
@@ -26281,12 +27471,12 @@ var realSaveDeps = () => ({
26281
27471
  writeFile: (path5, contents) => writeFile7(path5, contents),
26282
27472
  appendRun,
26283
27473
  buildSourceFingerprint,
26284
- sleep: (ms) => new Promise((resolve22) => setTimeout(resolve22, ms)),
27474
+ sleep: (ms) => new Promise((resolve25) => setTimeout(resolve25, ms)),
26285
27475
  warn: (message) => process.stderr.write(message)
26286
27476
  });
26287
27477
  async function runPrintFiles(input, deps, onPatch) {
26288
27478
  onPatch({ step: "printing" });
26289
- const componentsPath = join23(input.outDir, "components.json");
27479
+ const componentsPath = join22(input.outDir, "components.json");
26290
27480
  try {
26291
27481
  const db = deps.openDb();
26292
27482
  let components = [];
@@ -26367,7 +27557,7 @@ var EMPTY_PUSH_RESULT = {
26367
27557
  };
26368
27558
 
26369
27559
  // packages/experience-design-system-cli/src/tui/import/steps/10-flow/flow/controller.ts
26370
- var WIZARD_LOG = join24(tmpdir(), "experiences-import-wizard.log");
27560
+ var WIZARD_LOG = join23(tmpdir(), "experiences-import-wizard.log");
26371
27561
  function appendWizardLog(entry) {
26372
27562
  appendFileSync(WIZARD_LOG, JSON.stringify({ ts: (/* @__PURE__ */ new Date()).toISOString(), ...entry }) + "\n");
26373
27563
  }
@@ -26657,8 +27847,8 @@ import { Box as Box42, Text as Text44, useInput as useInput9 } from "ink";
26657
27847
 
26658
27848
  // packages/experience-design-system-cli/src/tui/debug-store.ts
26659
27849
  import { mkdir as mkdir9, writeFile as writeFile8 } from "node:fs/promises";
26660
- import { existsSync as existsSync10, readdirSync as readdirSync4 } from "node:fs";
26661
- import { join as join25 } from "node:path";
27850
+ import { existsSync as existsSync9, readdirSync as readdirSync4 } from "node:fs";
27851
+ import { join as join24 } from "node:path";
26662
27852
 
26663
27853
  // packages/experience-design-system-cli/src/tui/settings/debug-mode/debug-mode-store.ts
26664
27854
  var DEFAULT_DEBUG_MODE_SETTING = {
@@ -26689,7 +27879,7 @@ function slugify(value) {
26689
27879
  function generateSessionId3() {
26690
27880
  const today = datePrefix();
26691
27881
  const root = debugSessionsDir2();
26692
- const existing = existsSync10(root) ? readdirSync4(root) : [];
27882
+ const existing = existsSync9(root) ? readdirSync4(root) : [];
26693
27883
  const seqPattern = new RegExp(`^${today}-session-(\\d+)$`);
26694
27884
  const maxSeq = existing.reduce((max, entry) => {
26695
27885
  const match2 = seqPattern.exec(entry);
@@ -26699,7 +27889,7 @@ function generateSessionId3() {
26699
27889
  }
26700
27890
  var SESSION_ID = generateSessionId3();
26701
27891
  function sessionDebugDir() {
26702
- return join25(debugSessionsDir2(), SESSION_ID);
27892
+ return join24(debugSessionsDir2(), SESSION_ID);
26703
27893
  }
26704
27894
  function currentDebugSessionDir() {
26705
27895
  return sessionDebugDir();
@@ -26748,15 +27938,15 @@ async function finishDebugRun({
26748
27938
  const durationMs = Date.now() - run.startedAt;
26749
27939
  const content = renderMarkdown(run, { outputs: redact(outputs), status, exitMethod, durationMs });
26750
27940
  const flowSegments = run.flow.split("/");
26751
- const dir = join25(sessionDebugDir(), ...flowSegments);
27941
+ const dir = join24(sessionDebugDir(), ...flowSegments);
26752
27942
  await mkdir9(dir, { recursive: true });
26753
27943
  const filename = nextAttemptFilename(dir, run.menuOption);
26754
- await writeFile8(join25(dir, filename), content, { mode: 384 });
27944
+ await writeFile8(join24(dir, filename), content, { mode: 384 });
26755
27945
  }
26756
27946
  function nextAttemptFilename(dir, menuOption) {
26757
27947
  const today = datePrefix();
26758
27948
  const optionSlug = slugify(menuOption);
26759
- const existing = existsSync10(dir) ? readdirSync4(dir) : [];
27949
+ const existing = existsSync9(dir) ? readdirSync4(dir) : [];
26760
27950
  const attemptPattern = new RegExp(`^${today}-${optionSlug}-attempt-(\\d+)\\.md$`);
26761
27951
  const maxAttempt = existing.reduce((max, entry) => {
26762
27952
  const match2 = attemptPattern.exec(entry);
@@ -27396,7 +28586,7 @@ function App({ importOptions }) {
27396
28586
  const launch = { projectPath: projectPath2, tokens, filePaths, ...importOptions };
27397
28587
  const state = await inspectTokens({
27398
28588
  rawTokensPath: tokens,
27399
- outDir: join26(resolveUserPath(projectPath2), ".contentful"),
28589
+ outDir: join25(resolveUserPath(projectPath2), ".contentful"),
27400
28590
  cache: importOptions.cache
27401
28591
  });
27402
28592
  if (state.kind === "cached") {