@contentful/experience-design-system-cli 2.37.1-dev-build-a029dc0a.0 → 2.37.1-dev-build-f18643c3.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,370 @@ ${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
+
16245
+ // packages/experience-design-system-backend-pipeline/dist/src/orchestrators/run-generate-components-session/helpers/build-cached-component-result.js
16246
+ function buildCachedComponentResult(componentName, warnings = []) {
16247
+ return {
16248
+ componentName,
16249
+ classified: 0,
16250
+ excluded: 0,
16251
+ slots: 0,
16252
+ warnings,
16253
+ failed: false,
16254
+ cached: true,
16255
+ renamedSlotsCount: 0
16256
+ };
16257
+ }
16258
+
16259
+ // packages/experience-design-system-backend-pipeline/dist/src/orchestrators/run-generate-components-session/helpers/build-failed-component-result.js
16260
+ function buildFailedComponentResult(componentName, error, renamedSlotsCount) {
16261
+ return {
16262
+ componentName,
16263
+ classified: 0,
16264
+ excluded: 0,
16265
+ slots: 0,
16266
+ warnings: [],
16267
+ failed: true,
16268
+ error,
16269
+ cached: false,
16270
+ renamedSlotsCount
16271
+ };
16272
+ }
16273
+
16274
+ // packages/experience-design-system-backend-pipeline/dist/src/orchestrators/run-generate-components-session/helpers/run-one-generate-component.js
16275
+ var DEFAULT_TIMEOUT_MS4 = Number(process.env["EDS_AGENT_TIMEOUT_MS"] ?? 5 * 60 * 1e3);
16276
+ var RETRY_BACKOFF_MS = Number(process.env["EDS_RETRY_BACKOFF_MS"] ?? 5e3);
16277
+ async function runOneGenerateComponent(options, component, index, total) {
16278
+ const { db, sessionId, invoker, agent, model, tokensInline, tokenMapInline, verbose, noCache, skillPathOverride, skillContentOverride, promptHash, existingContentfulEntities, existingTokensInline, precomputedCachedNames, allowedComponentNames: allowedComponentNames2, onProgress } = options;
16279
+ const { renames } = renameEmptySlots(db, sessionId, component.component_id, component.name, component.slots.length);
16280
+ let effectiveSlots = component.slots;
16281
+ if (renames.length > 0) {
16282
+ const renameMap = new Map(renames.map((r) => [r.oldName, r.newName]));
16283
+ effectiveSlots = component.slots.map((s) => renameMap.has(s.name) ? { ...s, name: renameMap.get(s.name) } : s);
16284
+ for (const rename3 of renames) {
16285
+ onProgress?.({
16286
+ kind: "component:slot-renamed",
16287
+ componentName: component.name,
16288
+ oldName: rename3.oldName,
16289
+ newName: rename3.newName
16290
+ });
16291
+ }
16292
+ }
16293
+ effectiveSlots = effectiveSlots.map((slot) => slot.allowedComponents ? { ...slot, allowedComponents: slot.allowedComponents.filter((name) => allowedComponentNames2.has(name)) } : slot);
16294
+ const cacheComponent = normalizeComponentForCache(component);
16295
+ if (!noCache && precomputedCachedNames.has(component.name)) {
16296
+ onProgress?.({ kind: "component:cached", index, total, name: component.name, pinned: false });
16297
+ return buildCachedComponentResult(component.name);
16298
+ }
16299
+ if (!noCache) {
16300
+ const resolution = resolveComponentCache(db, component, promptHash, allowedComponentNames2);
16301
+ if (resolution && !resolution.humanEdited) {
16302
+ copyComponentFromCache(db, resolution.entry.sourceSessionId, sessionId, component.component_id, true, {
16303
+ allowedComponentNames: allowedComponentNames2
16304
+ });
16305
+ storeCache(db, hashComponentShape(cacheComponent), "component", component.component_id, resolution.entry.sourceSessionId, resolution.entry.humanEdited, promptHash);
16306
+ onProgress?.({ kind: "component:cached", index, total, name: component.name, pinned: false });
16307
+ return buildCachedComponentResult(component.name);
16308
+ }
16309
+ if (resolution?.humanEdited) {
16310
+ copyComponentFromCache(db, resolution.entry.sourceSessionId, sessionId, component.component_id, true, {
16311
+ allowedComponentNames: allowedComponentNames2
16312
+ });
16313
+ onProgress?.({ kind: "component:cached", index, total, name: component.name, pinned: true });
16314
+ return buildCachedComponentResult(component.name, [
16315
+ `${component.name}: source changed but human edits preserved`
16316
+ ]);
16317
+ }
16318
+ }
16319
+ const rawComponentsInline = JSON.stringify([
16320
+ {
16321
+ name: component.name,
16322
+ source: component.source,
16323
+ framework: component.framework,
16324
+ props: component.props,
16325
+ slots: effectiveSlots
16326
+ }
16327
+ ], null, 2);
16328
+ const sourceRef = await loadComponentSourceRef(component.name, component.sourcePath ?? component.source, component.props.map((p) => p.name), component.props.map((p) => p.type));
16329
+ const existingComponentsInline = existingContentfulEntities ? JSON.stringify(summarizeForGenerateAgent(existingContentfulEntities, component.name)) : void 0;
16330
+ const prompt = await buildPrompt({
16331
+ skill: "components",
16332
+ mode: "autonomous",
16333
+ rawComponentsInline,
16334
+ tokensInline,
16335
+ tokenMapInline,
16336
+ outDir: process.cwd(),
16337
+ componentName: component.name,
16338
+ componentSourceRefs: [sourceRef],
16339
+ skillPathOverride,
16340
+ skillContentOverride,
16341
+ existingComponentsInline,
16342
+ existingTokensInline,
16343
+ componentAllowlistInline: JSON.stringify([...allowedComponentNames2].sort())
16344
+ });
16345
+ const maxAttempts = 2;
16346
+ let lastError = "";
16347
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
16348
+ if (attempt > 1)
16349
+ await new Promise((res) => setTimeout(res, RETRY_BACKOFF_MS));
16350
+ onProgress?.({ kind: "component:started", index, total, name: component.name, attempt, maxAttempts });
16351
+ const { result } = await invokeAgentWithOutput(invoker, { agent, model, prompt, timeoutMs: DEFAULT_TIMEOUT_MS4 }, verbose);
16352
+ if (result.timedOut) {
16353
+ const error = `timed out after ${DEFAULT_TIMEOUT_MS4 / 6e4} minutes`;
16354
+ onProgress?.({ kind: "component:failed", index, total, name: component.name, error });
16355
+ return buildFailedComponentResult(component.name, error, renames.length);
16356
+ }
16357
+ if (result.exitCode !== 0) {
16358
+ lastError = describeAgentFailure(result);
16359
+ continue;
16360
+ }
16361
+ const { calls, warnings } = parseToolCalls(result.stdout);
16362
+ if (calls.length === 0) {
16363
+ lastError = describeAgentFailure(result);
16364
+ continue;
16365
+ }
16366
+ const applied = applyToolCalls(db, sessionId, component.component_id, component.name, calls, warnings, {
16367
+ allowedComponentNames: allowedComponentNames2
16368
+ });
16369
+ if (!noCache) {
16370
+ storeCache(db, hashComponentShape(cacheComponent), "component", component.component_id, sessionId, false, promptHash);
16371
+ }
16372
+ onProgress?.({
16373
+ kind: "component:completed",
16374
+ index,
16375
+ total,
16376
+ name: component.name,
16377
+ classified: applied.classified,
16378
+ excluded: applied.excluded,
16379
+ slots: applied.slots,
16380
+ warnings: applied.warnings
16381
+ });
16382
+ return {
16383
+ componentName: component.name,
16384
+ classified: applied.classified,
16385
+ excluded: applied.excluded,
16386
+ slots: applied.slots,
16387
+ warnings: applied.warnings,
16388
+ failed: false,
16389
+ cached: false,
16390
+ renamedSlotsCount: renames.length
16391
+ };
16392
+ }
16393
+ onProgress?.({ kind: "component:failed", index, total, name: component.name, error: lastError });
16394
+ return buildFailedComponentResult(component.name, lastError, renames.length);
16395
+ }
16396
+
16397
+ // packages/experience-design-system-backend-pipeline/dist/src/orchestrators/run-generate-components-session/helpers/run-with-pool.js
16398
+ async function runWithPool(items, concurrency, worker) {
16399
+ const results = new Array(items.length);
16400
+ let next = 0;
16401
+ async function run() {
16402
+ while (next < items.length) {
16403
+ const i = next++;
16404
+ results[i] = await worker(items[i], i);
16405
+ }
16406
+ }
16407
+ await Promise.all(Array.from({ length: concurrency }, run));
16408
+ return results;
16409
+ }
16410
+
16411
+ // packages/experience-design-system-backend-pipeline/dist/src/orchestrators/run-generate-components-session/check-generate-components-cache.js
16412
+ init_cache_keys();
16413
+
16414
+ // packages/experience-design-system-backend-pipeline/dist/src/orchestrators/run-generate-components-session/helpers/restore-cached-components.js
16415
+ function restoreCachedComponents(db, sessionId, cachedComponents, promptHash, allowedComponentNames2) {
16416
+ const restorations = [];
16417
+ const rekeyed = [];
16418
+ const componentStatus = db.prepare("SELECT status FROM raw_components WHERE session_id = ? AND component_id = ?");
16419
+ for (const { component, resolution } of cachedComponents) {
16420
+ const current = componentStatus.get(sessionId, component.component_id);
16421
+ if (current?.status === "generated")
16422
+ continue;
16423
+ renameEmptySlots(db, sessionId, component.component_id, component.name, component.slots.length);
16424
+ restorations.push({
16425
+ sourceSessionId: resolution.entry.sourceSessionId,
16426
+ targetSessionId: sessionId,
16427
+ componentId: component.component_id
16428
+ });
16429
+ rekeyed.push({ component, cached: resolution.entry });
16430
+ }
16431
+ copyComponentsFromCache(db, restorations, { allowedComponentNames: allowedComponentNames2 });
16432
+ storeCaches(db, rekeyed.map(({ component, cached }) => ({
16433
+ inputHash: hashComponentShape(normalizeComponentForCache(component)),
16434
+ entityType: "component",
16435
+ entityId: component.component_id,
16436
+ sourceSessionId: cached.sourceSessionId,
16437
+ humanEdited: cached.humanEdited,
16438
+ promptHash
16439
+ })));
16440
+ }
16441
+
16442
+ // packages/experience-design-system-backend-pipeline/dist/src/orchestrators/run-generate-components-session/check-generate-components-cache.js
16443
+ async function checkGenerateComponentsCache(request) {
16444
+ if (request.noCache) {
16445
+ return { sessionId: request.sessionId, cachedComponentNames: [], fullyCached: false, cacheDisabled: true };
16446
+ }
16447
+ const existingEntities = await readExistingEntities(request);
16448
+ const existingTokensInline = existingEntities ? JSON.stringify(summarizeForMapTokens({ entities: existingEntities })) : void 0;
16449
+ const prompt = await resolveGeneratePrompt(request.promptOverrides);
16450
+ const agent = request.agent;
16451
+ const promptHash = await hashPromptForSkill("components", agent, request.agentModel, prompt.path, existingTokensInline ? [hashContent(existingTokensInline)] : [], prompt.text);
16452
+ const db = openPipelineDb();
16453
+ try {
16454
+ const acceptedNames = await loadAcceptedNames(request.sessionId);
16455
+ const components = loadRawComponents(db, request.sessionId, acceptedNames ?? void 0);
16456
+ if (components.length === 0) {
16457
+ return { sessionId: request.sessionId, cachedComponentNames: [], fullyCached: false, cacheDisabled: false };
16458
+ }
16459
+ const allowedComponentNames2 = /* @__PURE__ */ new Set([
16460
+ ...components.map((component) => component.name),
16461
+ ...(existingEntities?.components ?? []).map((component) => component.name)
16462
+ ]);
16463
+ const cachedComponents = components.flatMap((component) => {
16464
+ const resolution = resolveComponentCache(db, component, promptHash, allowedComponentNames2);
16465
+ return resolution ? [{ component, resolution }] : [];
16466
+ });
16467
+ if (request.restoreCache) {
16468
+ restoreCachedComponents(db, request.sessionId, cachedComponents, promptHash, allowedComponentNames2);
16469
+ }
16470
+ return {
16471
+ sessionId: request.sessionId,
16472
+ cachedComponentNames: cachedComponents.map(({ component }) => component.name),
16473
+ fullyCached: cachedComponents.length === components.length,
16474
+ cacheDisabled: false
16475
+ };
16476
+ } finally {
16477
+ db.close();
16478
+ }
16479
+ }
16480
+
16481
+ // packages/experience-design-system-backend-pipeline/dist/src/orchestrators/run-generate-components-session/run-generate-components-session.js
16482
+ var DEFAULT_COMPONENT_CONCURRENCY = Number(process.env["EDS_GENERATE_CONCURRENCY"] ?? 10);
16483
+ async function runGenerateComponentsSession(request) {
16484
+ const prompt = await resolveGeneratePrompt(request.promptOverrides);
16485
+ const existingEntities = await readExistingEntities(request);
16486
+ const existingTokensInline = existingEntities ? JSON.stringify(summarizeForMapTokens({ entities: existingEntities })) : void 0;
16487
+ const existingTokensHash = existingTokensInline ? [hashContent(existingTokensInline)] : [];
16488
+ const agent = request.agent;
16489
+ const promptHash = await hashPromptForSkill("components", agent, request.agentModel, prompt.path, existingTokensHash, prompt.text);
16490
+ const db = openPipelineDb();
16491
+ try {
16492
+ const acceptedNames = await loadAcceptedNames(request.sessionId);
16493
+ const acceptedSet = acceptedNames ? new Set(acceptedNames) : void 0;
16494
+ let components = loadRawComponents(db, request.sessionId, acceptedSet ?? void 0);
16495
+ if (components.length === 0)
16496
+ return buildEmptySessionResponse(request.sessionId);
16497
+ const allowedComponentNames2 = /* @__PURE__ */ new Set([
16498
+ ...components.map((c2) => c2.name),
16499
+ ...(existingEntities?.components ?? []).map((c2) => c2.name)
16500
+ ]);
16501
+ const { components: filtered, dropped } = filterDroppedAllowedComponents(db, request.sessionId, components, allowedComponentNames2, acceptedSet);
16502
+ components = filtered;
16503
+ const duplicateNames = collectDuplicateNames(components);
16504
+ const invoker = createLocalCliAgentInvoker({});
16505
+ const concurrency = Math.max(1, Math.min(DEFAULT_COMPONENT_CONCURRENCY, components.length));
16506
+ const results = await runWithPool(components, concurrency, (component, index) => runOneGenerateComponent({
16507
+ db,
16508
+ sessionId: request.sessionId,
16509
+ invoker,
16510
+ agent,
16511
+ model: request.agentModel,
16512
+ tokensInline: request.tokensInline,
16513
+ tokenMapInline: request.tokenMapInline,
16514
+ verbose: request.verbose ?? false,
16515
+ noCache: request.noCache,
16516
+ skillPathOverride: prompt.path,
16517
+ skillContentOverride: prompt.text,
16518
+ promptHash,
16519
+ existingContentfulEntities: existingEntities,
16520
+ existingTokensInline,
16521
+ precomputedCachedNames: request.precomputedCachedNames ?? /* @__PURE__ */ new Set(),
16522
+ allowedComponentNames: allowedComponentNames2,
16523
+ onProgress: request.onProgress
16524
+ }, component, index, components.length));
16525
+ const allOk = results.every((r) => !r.failed);
16526
+ const renamedSlotsCount = results.reduce((sum, r) => sum + r.renamedSlotsCount, 0);
16527
+ return {
16528
+ sessionId: request.sessionId,
16529
+ results,
16530
+ allOk,
16531
+ renamedSlotsCount,
16532
+ duplicateNames,
16533
+ droppedAllowedComponents: dropped,
16534
+ emptySession: false
16535
+ };
16536
+ } finally {
16537
+ db.close();
16538
+ }
16539
+ }
16540
+
15092
16541
  // packages/experience-design-system-cli/src/tui/import/steps/03-path-validation/helpers/scan-files.ts
15093
16542
  function scanFiles(directory) {
15094
16543
  return toScanResult(collectFiles(directory));
@@ -15738,7 +17187,7 @@ function ExtractionScreen({
15738
17187
 
15739
17188
  // packages/experience-design-system-types/dist/src/config/index.js
15740
17189
  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";
17190
+ import { mkdir as mkdir6, readFile as readFile18, rename as rename2, writeFile as writeFile6 } from "node:fs/promises";
15742
17191
  import { homedir as homedir3 } from "node:os";
15743
17192
  import { dirname as dirname13, join as join17 } from "node:path";
15744
17193
  function configRoot2() {
@@ -15748,7 +17197,7 @@ var configFilePath2 = () => join17(configRoot2(), "config.json");
15748
17197
  var debugSessionsDir2 = () => join17(configRoot2(), "debug", "sessions");
15749
17198
  async function readSettings2() {
15750
17199
  try {
15751
- return JSON.parse(await readFile15(configFilePath2(), "utf8"));
17200
+ return JSON.parse(await readFile18(configFilePath2(), "utf8"));
15752
17201
  } catch {
15753
17202
  return {};
15754
17203
  }
@@ -15770,11 +17219,11 @@ import { useEffect as useEffect5, useRef as useRef2, useState as useState8 } fro
15770
17219
 
15771
17220
  // packages/experience-design-system-cli/src/tui/import/steps/06-extraction/run.ts
15772
17221
  import { mkdir as mkdir7 } from "node:fs/promises";
15773
- import { join as join19, resolve as resolve20 } from "node:path";
17222
+ import { join as join19, resolve as resolve22 } from "node:path";
15774
17223
 
15775
17224
  // packages/experience-design-system-cli/src/tui/import/steps/06-extraction/find-skill-path.ts
15776
17225
  import { existsSync as existsSync8 } from "node:fs";
15777
- import { dirname as dirname14, join as join18, resolve as resolve18 } from "node:path";
17226
+ import { dirname as dirname14, join as join18, resolve as resolve20 } from "node:path";
15778
17227
  import { fileURLToPath as fileURLToPath4 } from "node:url";
15779
17228
  function findSkillPath(fileName) {
15780
17229
  const thisDir = dirname14(fileURLToPath4(import.meta.url));
@@ -15782,7 +17231,7 @@ function findSkillPath(fileName) {
15782
17231
  for (; ; ) {
15783
17232
  const candidate = join18(dir, "skills", fileName);
15784
17233
  if (existsSync8(candidate)) return candidate;
15785
- const parent = resolve18(dir, "..");
17234
+ const parent = resolve20(dir, "..");
15786
17235
  if (parent === dir) {
15787
17236
  throw new Error(`skill file not found (looked for skills/${fileName} from ${thisDir})`);
15788
17237
  }
@@ -15791,11 +17240,11 @@ function findSkillPath(fileName) {
15791
17240
  }
15792
17241
 
15793
17242
  // packages/experience-design-system-cli/src/tui/import/steps/06-extraction/selection.ts
15794
- import { resolve as resolve19 } from "node:path";
17243
+ import { resolve as resolve21 } from "node:path";
15795
17244
  var SELECT_SKILL_PATH = findSkillPath("select-components.md");
15796
- var DEFAULT_TIMEOUT_MS4 = Number(process.env.EDS_AGENT_TIMEOUT_MS ?? 5 * 60 * 1e3);
17245
+ var DEFAULT_TIMEOUT_MS5 = Number(process.env.EDS_AGENT_TIMEOUT_MS ?? 5 * 60 * 1e3);
15797
17246
  async function hashSelectPrompt(options) {
15798
- const promptHash = options.promptText ? hashContent(options.promptText) : options.promptPath ? await hashFile(resolve19(options.promptPath)) : await hashFile(SELECT_SKILL_PATH);
17247
+ const promptHash = options.promptText ? hashContent(options.promptText) : options.promptPath ? await hashFile(resolve21(options.promptPath)) : await hashFile(SELECT_SKILL_PATH);
15799
17248
  return hashContent(`${promptHash}|${options.agent}|${options.model ?? ""}`);
15800
17249
  }
15801
17250
  async function runSelection(options) {
@@ -15829,7 +17278,7 @@ async function runSelection(options) {
15829
17278
  });
15830
17279
  const { result } = await invokeAgentWithOutput(
15831
17280
  invoker,
15832
- { agent: options.agent, model: options.model, prompt, timeoutMs: DEFAULT_TIMEOUT_MS4 },
17281
+ { agent: options.agent, model: options.model, prompt, timeoutMs: DEFAULT_TIMEOUT_MS5 },
15833
17282
  false
15834
17283
  );
15835
17284
  if (result.timedOut) throw new Error("selection agent timed out");
@@ -15890,7 +17339,7 @@ var realDeps = {
15890
17339
  var fail = (step, message) => ({ ok: false, step, message });
15891
17340
  var errorMessage2 = (error) => error instanceof Error ? error.message : String(error);
15892
17341
  async function runExtraction(input, onProgress, deps = realDeps) {
15893
- const outDir = join19(resolve20(input.projectPath), ".contentful");
17342
+ const outDir = join19(resolve22(input.projectPath), ".contentful");
15894
17343
  let progress = initialProgress({
15895
17344
  hasCredentials: input.credentials !== null,
15896
17345
  hasRawTokens: input.rawTokensPath !== "",
@@ -16016,7 +17465,7 @@ async function resolveSelectionPrompt(overrides) {
16016
17465
  if (select?.kind === "text") return { promptText: select.value };
16017
17466
  if (select?.kind === "path") {
16018
17467
  await resolvePromptOverride(select);
16019
- return { promptPath: resolve20(select.value) };
17468
+ return { promptPath: resolve22(select.value) };
16020
17469
  }
16021
17470
  return {};
16022
17471
  }
@@ -16920,7 +18369,7 @@ function buildVisibleRows(props) {
16920
18369
  if (visited.has(target)) continue;
16921
18370
  visited.add(target);
16922
18371
  const isCycleMember = cycleParticipants.has(target);
16923
- out.push({ name: target, depth: cur.depth + 1, isCycleMember, parent: cur.name });
18372
+ out.push({ name: target, depth: cur.depth + 1, isCycleMember });
16924
18373
  queue.push({ name: target, depth: cur.depth + 1 });
16925
18374
  }
16926
18375
  }
@@ -16967,8 +18416,7 @@ function buildVisibleRows(props) {
16967
18416
  sharedSuffix,
16968
18417
  cycleChild: child.isCycleMember || void 0,
16969
18418
  itemIdx: childRec?.idx ?? -1,
16970
- rootName: key,
16971
- parentName: child.parent
18419
+ rootName: key
16972
18420
  });
16973
18421
  });
16974
18422
  }
@@ -17051,19 +18499,13 @@ function buildVisibleRows(props) {
17051
18499
  injectedChildren.push({
17052
18500
  name: target,
17053
18501
  depth: parentDepth + 1,
17054
- isCycleChild: true,
17055
- parent: parentName
18502
+ isCycleChild: true
17056
18503
  });
17057
18504
  }
17058
18505
  };
17059
18506
  emitCycleChildrenOf(root, 0);
17060
18507
  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
- });
18508
+ injectedChildren.push({ name: c2.name, depth: c2.depth, isCycleChild: false });
17067
18509
  emitCycleChildrenOf(c2.name, c2.depth);
17068
18510
  }
17069
18511
  const isLastAtDepth = (idx) => {
@@ -17097,8 +18539,7 @@ function buildVisibleRows(props) {
17097
18539
  sharedSuffix,
17098
18540
  cycleChild: child.isCycleChild || void 0,
17099
18541
  itemIdx: childRec?.idx ?? -1,
17100
- rootName: root,
17101
- parentName: child.parent
18542
+ rootName: root
17102
18543
  });
17103
18544
  });
17104
18545
  }
@@ -17251,7 +18692,7 @@ function GroupedSidebar(props) {
17251
18692
  const rs = itemName ? renderStatusByKey?.get(itemName) : void 0;
17252
18693
  const badge = itemName ? previewBadge(previewAnnotationByKey?.get(itemName)) : null;
17253
18694
  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");
18695
+ 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
18696
  const selState = supportsSelectionGlyph ? selectionStateByKey.get(itemName) ?? "undecided" : void 0;
17256
18697
  const isCycleRow = row.kind === "cycle";
17257
18698
  const selStyle = selectionGlyphStyleFor(selState, isCycleRow);
@@ -17281,7 +18722,7 @@ function GroupedSidebar(props) {
17281
18722
  color: isSelected ? PALETTE2.info : labelStyle.dim ? PALETTE2.muted : labelStyle.color,
17282
18723
  bold: isSelected || labelStyle.bold,
17283
18724
  inverse: false,
17284
- underline: isSelected && focused,
18725
+ underline: isSelected && !focused,
17285
18726
  wrap: wrapLabels ? "wrap" : "truncate",
17286
18727
  children: [
17287
18728
  " ",
@@ -17940,7 +19381,6 @@ function resolveKey(mode, key, ctx) {
17940
19381
  function resolveMain(key, ctx) {
17941
19382
  const { input } = key;
17942
19383
  const inMain = ctx.focusedColumn === "main";
17943
- if (key.ctrl && input === "z") return { type: "undo" };
17944
19384
  if (input === "q" || key.escape) {
17945
19385
  if (key.escape && ctx.jumpFilterActive) return { type: "clear-jump-filter" };
17946
19386
  if (key.escape && ctx.searchActive) return { type: "clear-search" };
@@ -18199,42 +19639,21 @@ function rejectNeedsConfirmation(graph, name, state) {
18199
19639
  const ancestors = toReject.filter((n) => n !== name);
18200
19640
  return ancestors.length + toDeselect.length >= 2;
18201
19641
  }
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) {
19642
+ function partitionDecisions(components, state) {
18217
19643
  const accepted = [];
18218
19644
  const rejected = [];
18219
19645
  for (const c2 of components) {
18220
19646
  if (state.get(c2.name) === "accepted") accepted.push(c2.name);
18221
19647
  else rejected.push(c2.name);
18222
19648
  }
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 };
19649
+ return { accepted, rejected };
18226
19650
  }
18227
19651
 
18228
19652
  // packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/use-scope-gate.ts
18229
- function useScopeGate({ components: loadedComponents, onConfirm, onQuit }) {
19653
+ function useScopeGate({ components, onConfirm, onQuit }) {
18230
19654
  const { columns: totalWidth, rows: terminalRows } = useTerminalSize();
18231
19655
  const columnPlan = useMemo2(() => computeColumnWidths(totalWidth), [totalWidth]);
18232
19656
  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
19657
  const [nav, setNav] = useState12({ cursor: 0, scrollOffset: 0 });
18239
19658
  const [focusedColumn, setFocusedColumn] = useState12("main");
18240
19659
  const [addedComponentsCursor, setAddedComponentsCursor] = useState12(0);
@@ -18406,14 +19825,6 @@ function useScopeGate({ components: loadedComponents, onConfirm, onQuit }) {
18406
19825
  return void 0;
18407
19826
  }
18408
19827
  };
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
19828
  const jumpCursorTo = (name) => {
18418
19829
  let idx = -1;
18419
19830
  for (let i = 0; i < visibleRows.length; i++) {
@@ -18513,7 +19924,7 @@ function useScopeGate({ components: loadedComponents, onConfirm, onQuit }) {
18513
19924
  onQuit();
18514
19925
  return;
18515
19926
  case "confirm":
18516
- onConfirm(partitionDecisions(components, decisions, removedEdges));
19927
+ onConfirm(partitionDecisions(components, decisions));
18517
19928
  return;
18518
19929
  case "close-help":
18519
19930
  setShowHelp(false);
@@ -18566,11 +19977,6 @@ function useScopeGate({ components: loadedComponents, onConfirm, onQuit }) {
18566
19977
  return;
18567
19978
  }
18568
19979
  case "reject": {
18569
- const edge = focusedColumn === "main" ? focusedNestedEdge() : void 0;
18570
- if (edge) {
18571
- removeFromParentSlot(edge);
18572
- return;
18573
- }
18574
19980
  const key = focusedColumn === "added-components" ? addedComponents[safeAddedComponentsCursor]?.name : focusedRowKey();
18575
19981
  if (key) requestReject(key);
18576
19982
  return;
@@ -18578,9 +19984,6 @@ function useScopeGate({ components: loadedComponents, onConfirm, onQuit }) {
18578
19984
  case "toggle-all":
18579
19985
  decide({ type: "toggle-all" });
18580
19986
  return;
18581
- case "undo":
18582
- undoSlotRemoval();
18583
- return;
18584
19987
  case "accept-unflagged":
18585
19988
  decide({ type: "accept-unflagged" });
18586
19989
  return;
@@ -18851,58 +20254,19 @@ function ScopeGateView({ components, onConfirm, onQuit }) {
18851
20254
  import { useEffect as useEffect8, useMemo as useMemo3, useRef as useRef5, useState as useState13 } from "react";
18852
20255
 
18853
20256
  // 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) {
20257
+ async function checkGenerationCache(input) {
18901
20258
  if (input.noCache) return [];
18902
20259
  try {
18903
- const result = await run(buildCacheCheckArgs(input));
18904
- if (result.exitCode !== 0) return [];
18905
- return parseCacheComponents(result.stdout);
20260
+ const result = await checkGenerateComponentsCache({
20261
+ sessionId: input.sessionId,
20262
+ agent: input.agent,
20263
+ ...input.agentModel ? { agentModel: input.agentModel } : {},
20264
+ promptOverrides: input.promptOverrides,
20265
+ existingEntitiesPath: input.existingEntitiesPath,
20266
+ noCache: input.noCache,
20267
+ restoreCache: true
20268
+ });
20269
+ return result.cachedComponentNames;
18906
20270
  } catch {
18907
20271
  return [];
18908
20272
  }
@@ -18951,33 +20315,6 @@ function useScopeGateFlow(input, deps = realDeps2) {
18951
20315
  function initialProgress2() {
18952
20316
  return { components: null, mapTokens: "idle", mapTokensEligible: null };
18953
20317
  }
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
20318
  function shouldRunMapTokens(counts) {
18982
20319
  return counts.mappablePropCount > 0 && counts.rawTokenCount > 0;
18983
20320
  }
@@ -19033,17 +20370,215 @@ function GenerationScreen({
19033
20370
  );
19034
20371
  }
19035
20372
 
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
- };
20373
+ // packages/experience-design-system-cli/src/tui/import/steps/08-generation/use-generation.ts
20374
+ import { useEffect as useEffect9, useRef as useRef6, useState as useState14 } from "react";
20375
+
20376
+ // packages/experience-design-system-cli/src/tui/import/steps/08-generation/run.ts
20377
+ import { resolve as resolve23 } from "node:path";
20378
+
20379
+ // packages/experience-design-system-cli/src/tui/import/steps/08-generation/map-tokens.ts
20380
+ async function prepareMapTokens(input, generatedSessionId) {
20381
+ const db = openPipelineDb();
20382
+ try {
20383
+ if (input.tokenSessionId && input.tokenSessionId !== generatedSessionId) {
20384
+ copyTokensFromCache(db, input.tokenSessionId, generatedSessionId);
20385
+ } else if (!input.tokenSessionId && input.tokensPath) {
20386
+ const tokens = await readTokensFromPath2({ flag: "tokens", path: input.tokensPath });
20387
+ storeDtcgTokens(db, generatedSessionId, [], tokens);
20388
+ }
20389
+ const mappablePropCount = loadCDFComponents(db, generatedSessionId).reduce(
20390
+ (count, { entry }) => count + Object.values(entry.$properties).filter((prop) => prop.$type === "token" && prop.$category === "design").length,
20391
+ 0
20392
+ );
20393
+ const rawTokenCount = getDtcgTokensForSession(db, generatedSessionId).tokens.length;
20394
+ return {
20395
+ eligible: shouldRunMapTokens({ mappablePropCount, rawTokenCount }),
20396
+ mappablePropCount,
20397
+ rawTokenCount
20398
+ };
20399
+ } finally {
20400
+ db.close();
20401
+ }
20402
+ }
20403
+
20404
+ // packages/experience-design-system-cli/src/tui/import/steps/08-generation/save-decisions.ts
20405
+ async function saveDecisions(input) {
20406
+ const db = openPipelineDb();
20407
+ try {
20408
+ applyScopeDecisions(db, input.sessionId, input.decisions);
20409
+ await writeScopeDecisionsSnapshot(db, input.sessionId, input.decisions);
20410
+ } finally {
20411
+ db.close();
20412
+ }
20413
+ }
20414
+
20415
+ // packages/experience-design-system-cli/src/tui/import/steps/08-generation/run.ts
20416
+ var realDeps3 = {
20417
+ checkAgentAuth,
20418
+ saveDecisions,
20419
+ runGenerate: runGenerateComponentsSession,
20420
+ runMapTokens,
20421
+ prepareMapTokens
20422
+ };
20423
+ var fail2 = (step, message) => ({ ok: false, step, message });
20424
+ var errorMessage3 = (error) => error instanceof Error ? error.message : String(error);
20425
+ async function runGeneration(input, onProgress, deps = realDeps3) {
20426
+ let progress = { components: null, mapTokens: "idle", mapTokensEligible: null };
20427
+ const update = (change) => {
20428
+ progress = { ...progress, ...change };
20429
+ onProgress(progress);
20430
+ };
20431
+ const accepted = input.decisions.accepted;
20432
+ const handedOverNames = await input.cachedNames.catch(() => []);
20433
+ try {
20434
+ await deps.saveDecisions({ sessionId: input.sessionId, decisions: input.decisions });
20435
+ } catch (error) {
20436
+ return fail2("save decisions", errorMessage3(error));
20437
+ }
20438
+ if (accepted.length === 0) return { ok: true, generation: { route: "push", acceptedCount: 0 } };
20439
+ const auth = await deps.checkAgentAuth(input.agent);
20440
+ if (auth === "not-found" || auth === "unauthenticated") {
20441
+ return fail2(`${input.agent} auth check`, agentAuthMessage(input.agent, auth));
20442
+ }
20443
+ let generated;
20444
+ try {
20445
+ generated = await deps.runGenerate({
20446
+ sessionId: input.sessionId,
20447
+ agent: input.agent,
20448
+ ...input.agentModel ? { agentModel: input.agentModel } : {},
20449
+ promptOverrides: appendGeneratePromptOverride(input),
20450
+ noCache: input.noCache,
20451
+ existingEntitiesPath: input.existingEntitiesPath,
20452
+ precomputedCachedNames: new Set(handedOverNames),
20453
+ onProgress: (event) => update({ components: applyProgressEvent2(event, progress.components, accepted.length) })
20454
+ });
20455
+ } catch (error) {
20456
+ return fail2("generate components", errorMessage3(error));
20457
+ }
20458
+ if (generated.emptySession) return fail2("generate components", "no raw components in session");
20459
+ if (!generated.allOk) {
20460
+ const firstFailure = generated.results.find((r) => r.failed);
20461
+ return fail2("generate components", firstFailure?.error ?? "unknown error");
20462
+ }
20463
+ let plan;
20464
+ try {
20465
+ plan = await deps.prepareMapTokens(input, input.sessionId);
20466
+ } catch (error) {
20467
+ return fail2("map tokens", errorMessage3(error));
20468
+ }
20469
+ update({ mapTokensEligible: plan.eligible });
20470
+ if (plan.eligible) {
20471
+ update({ mapTokens: "running" });
20472
+ try {
20473
+ const mapTokensOptions = await buildMapTokensOptions(input);
20474
+ await deps.runMapTokens({
20475
+ sessionId: input.sessionId,
20476
+ agent: input.agent,
20477
+ ...input.agentModel ? { model: input.agentModel } : {},
20478
+ cache: !input.noCache,
20479
+ ...mapTokensOptions
20480
+ });
20481
+ } catch (error) {
20482
+ const message = error instanceof MapTokensRunFailure ? error.message : error instanceof Error ? error.message : String(error);
20483
+ return fail2("map tokens", message);
20484
+ }
20485
+ }
20486
+ update({ mapTokens: "complete" });
20487
+ const generatedCount = generated.results.filter((r) => !r.failed).length;
20488
+ return {
20489
+ ok: true,
20490
+ generation: {
20491
+ route: "review",
20492
+ sessionId: input.sessionId,
20493
+ acceptedCount: accepted.length,
20494
+ generatedCount,
20495
+ mapTokensEligible: plan.eligible
20496
+ }
20497
+ };
20498
+ }
20499
+ async function buildMapTokensOptions(input) {
20500
+ const { overrides: parsed, errors } = parsePromptOverrides(input.promptOverrides);
20501
+ if (errors.length > 0) throw new Error(errors.join("; "));
20502
+ const mapOverride = parsed.get("map-tokens");
20503
+ const prompt = {};
20504
+ if (mapOverride?.kind === "text") prompt.skillContentOverride = mapOverride.value;
20505
+ if (mapOverride?.kind === "path") {
20506
+ await resolvePromptOverride(mapOverride);
20507
+ prompt.skillPathOverride = resolve23(mapOverride.value);
20508
+ }
20509
+ if (input.existingEntitiesPath) {
20510
+ const entities = await readExistingContentfulEntitiesFromSession({ path: input.existingEntitiesPath });
20511
+ if (entities) return { ...prompt, existingEntitiesInline: JSON.stringify(summarizeForMapTokens({ entities })) };
20512
+ }
20513
+ return prompt;
20514
+ }
20515
+ function appendGeneratePromptOverride(input) {
20516
+ if (!input.generatePromptPath) return input.promptOverrides;
20517
+ const already = input.promptOverrides.some((override) => override.startsWith("generate="));
20518
+ if (already) return input.promptOverrides;
20519
+ return [...input.promptOverrides, `generate=${input.generatePromptPath}`];
20520
+ }
20521
+ function applyProgressEvent2(event, previous, total) {
20522
+ if (event.kind === "component:started") {
20523
+ return { done: previous?.done ?? 0, total: event.total || total, current: event.name };
20524
+ }
20525
+ if (event.kind === "component:completed" || event.kind === "component:failed" || event.kind === "component:cached") {
20526
+ return { done: (previous?.done ?? 0) + 1, total: event.total || total, current: event.name };
20527
+ }
20528
+ return previous;
20529
+ }
20530
+
20531
+ // packages/experience-design-system-cli/src/tui/import/steps/08-generation/use-generation.ts
20532
+ function useGeneration(input) {
20533
+ const [state, setState] = useState14();
20534
+ const current = useRef6();
20535
+ useEffect9(() => {
20536
+ current.current = input;
20537
+ if (!input) {
20538
+ setState(void 0);
20539
+ return;
20540
+ }
20541
+ setState({ status: "running", progress: initialProgress2() });
20542
+ void runGeneration(input, (progress) => {
20543
+ if (current.current === input) setState({ status: "running", progress });
20544
+ }).then((result) => {
20545
+ if (current.current === input) setState({ status: "done", result });
20546
+ });
20547
+ return () => {
20548
+ if (current.current === input) current.current = void 0;
20549
+ };
20550
+ }, [input]);
20551
+ return state;
20552
+ }
20553
+
20554
+ // packages/experience-design-system-cli/src/tui/import/steps/10-flow/flow/build-flow-start.ts
20555
+ import { join as join20 } from "node:path";
20556
+ function buildFlowStart(input) {
20557
+ const { extraction, handoff, saved, generatePromptPath } = input;
20558
+ const credentials = extraction.credentials ?? {
20559
+ spaceId: saved?.spaceId ?? "",
20560
+ environmentId: saved?.environmentId ?? "",
20561
+ cmaToken: saved?.cmaToken ?? "",
20562
+ host: saved?.host ?? ""
20563
+ };
20564
+ return {
20565
+ handoff,
20566
+ agent: extraction.agent,
20567
+ projectPath: extraction.projectPath,
20568
+ outDir: extraction.projectPath ? join20(extraction.projectPath, ".contentful") : "",
20569
+ rawTokensPath: extraction.rawTokensPath,
20570
+ credentials: {
20571
+ spaceId: credentials.spaceId,
20572
+ environmentId: credentials.environmentId || "master",
20573
+ cmaToken: credentials.cmaToken,
20574
+ host: toConfiguredHost2(credentials.host) ?? DEFAULT_CONFIGURED_HOST
20575
+ },
20576
+ ...generatePromptPath ? { generatePromptPath } : {}
20577
+ };
20578
+ }
20579
+
20580
+ // packages/experience-design-system-cli/src/tui/import/steps/10-flow/flow/screen.tsx
20581
+ import { Box as Box41 } from "ink";
19047
20582
 
19048
20583
  // packages/experience-design-system-types/dist/src/cdf/validate.js
19049
20584
  import { Ajv as Ajv2 } from "ajv";
@@ -19328,315 +20863,6 @@ var DTCGTokenSchema2 = z4.strictObject({
19328
20863
  // packages/experience-design-system-types/dist/src/dtcg/validate.js
19329
20864
  var TOKEN_TYPE_SET4 = new Set(DESIGN_TOKEN_TYPES2);
19330
20865
 
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
20866
  // packages/experience-design-system-cli/src/tui/import/steps/preview-validation-error/logic.ts
19641
20867
  function failedComponentNames(errors) {
19642
20868
  return [...new Set(errors.map((error) => error.componentName))];
@@ -21394,8 +22620,8 @@ function FieldEditor({
21394
22620
  return /* @__PURE__ */ jsxs22(Box21, { flexDirection: "column", width, borderStyle: "single", borderColor: PALETTE3.warning, children: [
21395
22621
  /* @__PURE__ */ jsx27(Text23, { bold: true, color: PALETTE3.warning, children: "FIELD EDITOR \u2014 no fields" }),
21396
22622
  /* @__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" })
22623
+ /* @__PURE__ */ jsx27(Text23, { color: PALETTE3.muted, children: "You can add fields manually below or reject this component." }),
22624
+ /* @__PURE__ */ jsx27(Text23, { color: PALETTE3.muted, children: "Enter to save \xB7 Esc to discard" })
21399
22625
  ] });
21400
22626
  }
21401
22627
  const hasEmptyProperties = props.length === 0 && slots.length === 0;
@@ -21610,7 +22836,7 @@ function FieldEditor({
21610
22836
  children: [
21611
22837
  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
22838
  header,
21613
- /* @__PURE__ */ jsx27(Box21, { flexDirection: "column", width: innerWidth, flexShrink: 0, children: focusLevel === "field" && !inComponentDesc && !inSlots && currentProp ? /* @__PURE__ */ jsx27(
22839
+ /* @__PURE__ */ jsx27(Box21, { flexDirection: "column", width: innerWidth, flexShrink: 0, children: focusLevel === "field" && !inComponentDesc && currentProp ? /* @__PURE__ */ jsx27(
21614
22840
  PropRow,
21615
22841
  {
21616
22842
  prop: currentProp,
@@ -22519,7 +23745,6 @@ function finalizeReviewSession(extractSessionId, components) {
22519
23745
  db.exec("ROLLBACK");
22520
23746
  throw error;
22521
23747
  }
22522
- removeSlotAllowedComponents(db, extractSessionId, [], toReject);
22523
23748
  } finally {
22524
23749
  db.close();
22525
23750
  }
@@ -22597,10 +23822,10 @@ var TimeoutError = class extends Error {
22597
23822
  this.name = "TimeoutError";
22598
23823
  }
22599
23824
  };
22600
- var DEFAULT_TIMEOUT_MS5 = 15e3;
23825
+ var DEFAULT_TIMEOUT_MS6 = 15e3;
22601
23826
  async function runLivePreview(opts) {
22602
23827
  const { sessionId, tokensPath, spaceId, environmentId, cmaToken, host, generation } = opts;
22603
- const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS5;
23828
+ const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS6;
22604
23829
  if (!spaceId || !environmentId || !cmaToken) {
22605
23830
  return { generation, response: null };
22606
23831
  }
@@ -24251,50 +25476,33 @@ function GenerateReviewStepView({
24251
25476
  const cycle = cycleRows[cyclesCursor];
24252
25477
  return cycle ? enumerateCycleBreaks(cycle, components) : [];
24253
25478
  }, [cycleRows, cyclesCursor, components]);
24254
- const saveSlotChange = (parentKey, nextEntry, historyLabel) => {
25479
+ const handleBreakEdge = (edge) => {
25480
+ const target = components.find((component) => component.key === edge.fromComponent);
25481
+ const slot = target?.entry.$slots?.[edge.slotName];
25482
+ if (!target || !slot || !Array.isArray(slot.$allowedComponents)) return;
25483
+ const nextEntry = {
25484
+ ...target.entry,
25485
+ $slots: {
25486
+ ...target.entry.$slots,
25487
+ [edge.slotName]: {
25488
+ ...slot,
25489
+ $allowedComponents: slot.$allowedComponents.filter((value) => value !== edge.toComponent)
25490
+ }
25491
+ }
25492
+ };
24255
25493
  const next = components.map(
24256
- (component) => component.key === parentKey ? { ...component, entry: nextEntry } : component
25494
+ (component) => component.key === target.key ? { ...component, entry: nextEntry } : component
24257
25495
  );
24258
25496
  setComponents(next);
24259
25497
  const db = openPipelineDb();
24260
25498
  try {
24261
- storeCDFComponents(db, extractSessionId, [{ key: parentKey, entry: nextEntry }]);
25499
+ storeCDFComponents(db, extractSessionId, [{ key: target.key, entry: nextEntry }]);
24262
25500
  } finally {
24263
25501
  db.close();
24264
25502
  }
24265
25503
  recomputeCycles(next);
24266
25504
  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");
25505
+ pushHistorySnapshot(next, "break-cycle-edge");
24298
25506
  };
24299
25507
  const handleRejectComponent = (key) => {
24300
25508
  const rejectCascade2 = computeRejectCascade(key, componentGraph);
@@ -24624,11 +25832,6 @@ function GenerateReviewStepView({
24624
25832
  if (input === "r") {
24625
25833
  const current = components[selectedIdx];
24626
25834
  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
25835
  handleRejectComponent(current.key);
24633
25836
  return;
24634
25837
  }
@@ -25105,10 +26308,10 @@ function DoneStep({
25105
26308
  import { useState as useState24 } from "react";
25106
26309
  import { Box as Box37, Text as Text40 } from "ink";
25107
26310
  import { readdirSync as readdirSync3 } from "node:fs";
25108
- import { dirname as dirname15, basename as basename6, join as join22 } from "node:path";
26311
+ import { dirname as dirname15, basename as basename6, join as join21 } from "node:path";
25109
26312
 
25110
26313
  // packages/experience-design-system-cli/src/tui/import/steps/10-flow/support/path-utils.ts
25111
- import { resolve as resolve21 } from "node:path";
26314
+ import { resolve as resolve24 } from "node:path";
25112
26315
  import { homedir as homedir4 } from "node:os";
25113
26316
  function expandTilde(input) {
25114
26317
  if (input === "~" || input.startsWith("~/") || input.startsWith("~\\")) {
@@ -25122,7 +26325,7 @@ function normalizePath(input) {
25122
26325
  p = p.slice(1, -1);
25123
26326
  }
25124
26327
  p = expandTilde(p);
25125
- return resolve21(p);
26328
+ return resolve24(p);
25126
26329
  }
25127
26330
 
25128
26331
  // packages/experience-design-system-cli/src/tui/import/steps/10-flow/support/use-blinking-cursor.ts
@@ -25151,13 +26354,13 @@ function autocomplete(partial) {
25151
26354
  }
25152
26355
  const matches = entries.filter((e) => e.startsWith(base));
25153
26356
  if (matches.length === 0) return null;
25154
- if (matches.length === 1) return join22(dir, matches[0]);
26357
+ if (matches.length === 1) return join21(dir, matches[0]);
25155
26358
  let prefix = matches[0];
25156
26359
  for (const m of matches) {
25157
26360
  while (!m.startsWith(prefix)) prefix = prefix.slice(0, -1);
25158
26361
  if (!prefix) break;
25159
26362
  }
25160
- return prefix.length > base.length ? join22(dir, prefix) : null;
26363
+ return prefix.length > base.length ? join21(dir, prefix) : null;
25161
26364
  }
25162
26365
  function PathPrompt({
25163
26366
  defaultPath,
@@ -25910,7 +27113,7 @@ import { useEffect as useEffect20, useRef as useRef12, useSyncExternalStore } fr
25910
27113
  import { appendFileSync, writeFileSync } from "node:fs";
25911
27114
  import { mkdir as mkdir8 } from "node:fs/promises";
25912
27115
  import { tmpdir } from "node:os";
25913
- import { join as join24 } from "node:path";
27116
+ import { join as join23 } from "node:path";
25914
27117
 
25915
27118
  // packages/experience-design-system-cli/src/tui/import/steps/10-flow/support/wizard-state-transitions.ts
25916
27119
  function shouldBypassPreview(state) {
@@ -26255,7 +27458,7 @@ function pushFailure(e, deps) {
26255
27458
 
26256
27459
  // packages/experience-design-system-cli/src/tui/import/steps/10-flow/flow/save.ts
26257
27460
  import { writeFile as writeFile7 } from "node:fs/promises";
26258
- import { join as join23 } from "node:path";
27461
+ import { join as join22 } from "node:path";
26259
27462
 
26260
27463
  // packages/experience-design-system-cli/src/tui/import/steps/10-flow/support/run-print-files-helpers.ts
26261
27464
  function nextStateAfterPrint(opts) {
@@ -26281,12 +27484,12 @@ var realSaveDeps = () => ({
26281
27484
  writeFile: (path5, contents) => writeFile7(path5, contents),
26282
27485
  appendRun,
26283
27486
  buildSourceFingerprint,
26284
- sleep: (ms) => new Promise((resolve22) => setTimeout(resolve22, ms)),
27487
+ sleep: (ms) => new Promise((resolve25) => setTimeout(resolve25, ms)),
26285
27488
  warn: (message) => process.stderr.write(message)
26286
27489
  });
26287
27490
  async function runPrintFiles(input, deps, onPatch) {
26288
27491
  onPatch({ step: "printing" });
26289
- const componentsPath = join23(input.outDir, "components.json");
27492
+ const componentsPath = join22(input.outDir, "components.json");
26290
27493
  try {
26291
27494
  const db = deps.openDb();
26292
27495
  let components = [];
@@ -26367,7 +27570,7 @@ var EMPTY_PUSH_RESULT = {
26367
27570
  };
26368
27571
 
26369
27572
  // packages/experience-design-system-cli/src/tui/import/steps/10-flow/flow/controller.ts
26370
- var WIZARD_LOG = join24(tmpdir(), "experiences-import-wizard.log");
27573
+ var WIZARD_LOG = join23(tmpdir(), "experiences-import-wizard.log");
26371
27574
  function appendWizardLog(entry) {
26372
27575
  appendFileSync(WIZARD_LOG, JSON.stringify({ ts: (/* @__PURE__ */ new Date()).toISOString(), ...entry }) + "\n");
26373
27576
  }
@@ -26657,8 +27860,8 @@ import { Box as Box42, Text as Text44, useInput as useInput9 } from "ink";
26657
27860
 
26658
27861
  // packages/experience-design-system-cli/src/tui/debug-store.ts
26659
27862
  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";
27863
+ import { existsSync as existsSync9, readdirSync as readdirSync4 } from "node:fs";
27864
+ import { join as join24 } from "node:path";
26662
27865
 
26663
27866
  // packages/experience-design-system-cli/src/tui/settings/debug-mode/debug-mode-store.ts
26664
27867
  var DEFAULT_DEBUG_MODE_SETTING = {
@@ -26689,7 +27892,7 @@ function slugify(value) {
26689
27892
  function generateSessionId3() {
26690
27893
  const today = datePrefix();
26691
27894
  const root = debugSessionsDir2();
26692
- const existing = existsSync10(root) ? readdirSync4(root) : [];
27895
+ const existing = existsSync9(root) ? readdirSync4(root) : [];
26693
27896
  const seqPattern = new RegExp(`^${today}-session-(\\d+)$`);
26694
27897
  const maxSeq = existing.reduce((max, entry) => {
26695
27898
  const match2 = seqPattern.exec(entry);
@@ -26699,7 +27902,7 @@ function generateSessionId3() {
26699
27902
  }
26700
27903
  var SESSION_ID = generateSessionId3();
26701
27904
  function sessionDebugDir() {
26702
- return join25(debugSessionsDir2(), SESSION_ID);
27905
+ return join24(debugSessionsDir2(), SESSION_ID);
26703
27906
  }
26704
27907
  function currentDebugSessionDir() {
26705
27908
  return sessionDebugDir();
@@ -26748,15 +27951,15 @@ async function finishDebugRun({
26748
27951
  const durationMs = Date.now() - run.startedAt;
26749
27952
  const content = renderMarkdown(run, { outputs: redact(outputs), status, exitMethod, durationMs });
26750
27953
  const flowSegments = run.flow.split("/");
26751
- const dir = join25(sessionDebugDir(), ...flowSegments);
27954
+ const dir = join24(sessionDebugDir(), ...flowSegments);
26752
27955
  await mkdir9(dir, { recursive: true });
26753
27956
  const filename = nextAttemptFilename(dir, run.menuOption);
26754
- await writeFile8(join25(dir, filename), content, { mode: 384 });
27957
+ await writeFile8(join24(dir, filename), content, { mode: 384 });
26755
27958
  }
26756
27959
  function nextAttemptFilename(dir, menuOption) {
26757
27960
  const today = datePrefix();
26758
27961
  const optionSlug = slugify(menuOption);
26759
- const existing = existsSync10(dir) ? readdirSync4(dir) : [];
27962
+ const existing = existsSync9(dir) ? readdirSync4(dir) : [];
26760
27963
  const attemptPattern = new RegExp(`^${today}-${optionSlug}-attempt-(\\d+)\\.md$`);
26761
27964
  const maxAttempt = existing.reduce((max, entry) => {
26762
27965
  const match2 = attemptPattern.exec(entry);
@@ -27396,7 +28599,7 @@ function App({ importOptions }) {
27396
28599
  const launch = { projectPath: projectPath2, tokens, filePaths, ...importOptions };
27397
28600
  const state = await inspectTokens({
27398
28601
  rawTokensPath: tokens,
27399
- outDir: join26(resolveUserPath(projectPath2), ".contentful"),
28602
+ outDir: join25(resolveUserPath(projectPath2), ".contentful"),
27400
28603
  cache: importOptions.cache
27401
28604
  });
27402
28605
  if (state.kind === "cached") {