@contentful/experience-design-system-cli 2.34.5-dev-build-d42cd1ad.0 → 2.34.5-dev-build-4985ea96.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contentful/experience-design-system-cli",
3
- "version": "2.34.5-dev-build-d42cd1ad.0",
3
+ "version": "2.34.5-dev-build-4985ea96.0",
4
4
  "description": "Contentful Experiences design system import CLI",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -1,17 +1,11 @@
1
1
  /**
2
2
  * The CLI-owned composition interchange format (spec T1).
3
3
  *
4
- * Two views of the same data:
5
- * - `InterchangeMap` — the human-authored / on-disk `{ version, groups }`
6
- * shape (parent → children), consumed by the composition-map option.
7
- * `--composition-map` consumes and the resolver can emit.
8
- * - `CompositionEdge[]` — the flat internal runtime view, one edge per
9
- * parent→child relationship, carrying optional `slot` (T7), `confidence`,
10
- * and `provenance`. Easier to merge/dedupe across sources (T2).
11
- *
12
- * This module owns both shapes and the converters between them.
4
+ * `CompositionEdge[]` is the flat internal runtime view, one edge per
5
+ * parent→child relationship, carrying optional `slot` (T7), `confidence`,
6
+ * and `provenance`. It is easier to merge and dedupe across sources (T2).
13
7
  */
14
- export type EdgeProvenance = 'user' | 'typed-slot' | 'structural' | 'manifest' | 'doc' | `adapter:${string}` | 'agent';
8
+ export type EdgeProvenance = 'typed-slot' | 'structural' | 'manifest' | 'doc' | `adapter:${string}` | 'agent';
15
9
  export type CompositionEdge = {
16
10
  parent: string;
17
11
  child: string;
@@ -21,17 +15,3 @@ export type CompositionEdge = {
21
15
  confidence?: number;
22
16
  provenance: EdgeProvenance;
23
17
  };
24
- export type InterchangeMap = {
25
- version: 1;
26
- groups: Record<string, string[]>;
27
- };
28
- export type ValidateResult = {
29
- valid: true;
30
- map: InterchangeMap;
31
- } | {
32
- valid: false;
33
- errors: string[];
34
- };
35
- export declare function validateInterchangeMap(input: unknown): ValidateResult;
36
- export declare function groupsToEdges(map: InterchangeMap, provenance: EdgeProvenance): CompositionEdge[];
37
- export declare function edgesToGroups(edges: CompositionEdge[]): InterchangeMap;
@@ -1,18 +1,7 @@
1
- import { type InterchangeMap } from './interchange-schema.js';
2
1
  export type CompositionCliOptions = {
3
- /** `--composition-map <path>` — hand-authored interchange file. */
4
- compositionMap?: string;
5
2
  /** `--composition-refresh` — force edge emission to run even over resolved residue. */
6
3
  compositionRefresh?: boolean;
7
4
  };
8
- export type LoadUserMapResult = {
9
- ok: true;
10
- map: InterchangeMap;
11
- } | {
12
- ok: false;
13
- error: string;
14
- };
15
- export declare function loadUserMap(path: string): Promise<LoadUserMapResult>;
16
5
  export type ResolvedCompositionSources = {
17
6
  forceAgent: boolean;
18
7
  };
@@ -1,9 +1,8 @@
1
1
  import type { RawComponentDefinition } from '../../types.js';
2
- import { type CompositionEdge, type InterchangeMap } from './interchange-schema.js';
2
+ import type { CompositionEdge } from './interchange-schema.js';
3
3
  import { type EdgeConflict } from './merge-edges.js';
4
4
  export type ResolveMappingResult = {
5
5
  components: RawComponentDefinition[];
6
- userMap?: InterchangeMap;
7
6
  edges: CompositionEdge[];
8
7
  conflicts: EdgeConflict[];
9
8
  warnings: string[];
@@ -11,9 +10,9 @@ export type ResolveMappingResult = {
11
10
  /**
12
11
  * Orchestrate composition-edge acquisition and enrichment.
13
12
  *
14
- * Sources by rank: user map (1) > typed-slot / "code slots" (2) > structural
15
- * usage evidence (3) > manifest (4) > doc (5) > adapter-resolved / extraEdges
16
- * (6) > edge-emitting agent (7). Manifest/doc edges are computed deterministically outside
13
+ * Sources by rank: typed-slot / "code slots" (2) > structural usage evidence
14
+ * (3) > manifest (4) > doc (5) > adapter-resolved / extraEdges (6) >
15
+ * edge-emitting agent (7). Manifest/doc edges are computed deterministically outside
17
16
  * this function (see manifest-doc-evidence.ts) and joined via `extraEdges`.
18
17
  * ALL sources — including the code slots already on the incoming components —
19
18
  * are fed into one ranked merge and unioned; non-conflicting edges from every
@@ -28,7 +27,6 @@ export type ResolveMappingResult = {
28
27
  */
29
28
  export declare function resolveMapping(input: {
30
29
  components: RawComponentDefinition[];
31
- userMap?: InterchangeMap;
32
30
  forceAgent?: boolean;
33
31
  files: Array<{
34
32
  path: string;
@@ -55,7 +53,7 @@ export declare function resolveMapping(input: {
55
53
  /**
56
54
  * Pre-resolved edges from an external source (e.g. manifest or documentation)
57
55
  * path). They join the ranked merge at their own provenance rank alongside
58
- * code slots and the user map.
56
+ * code slots and other automatic mapping sources.
59
57
  */
60
58
  extraEdges?: CompositionEdge[];
61
59
  }): Promise<ResolveMappingResult>;
@@ -7,7 +7,7 @@ export type ExperiencesCredentials = {
7
7
  agentModel?: string;
8
8
  /** Feature 8: persisted custom prompt path for `generate components`. */
9
9
  generatePromptPath?: string;
10
- /** Write JSONL trace of every command decision to ~/.contentful/experience-design-system-cli/debug/. */
10
+ /** Feature: default debug-mode (writes JSONL trace of every decision) for all commands. */
11
11
  debug?: boolean;
12
12
  /** Print plain text with no color; an exported NO_COLOR still wins. */
13
13
  noColor?: boolean;
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Resolution chain for the combined `--agent` override on `experiences import`.
3
+ *
4
+ * The wizard path previously hard-defaulted `--agent` to `'claude'` at the
5
+ * commander layer, which (a) shadowed the stored `credentials.json` value when
6
+ * the user passed no flag, and (b) made it impossible to distinguish "user
7
+ * explicitly passed --agent claude" from "user passed nothing". The combined
8
+ * flag accepts either `agent:model` or `agent model`.
9
+ *
10
+ * These helpers produce the resolved values to feed into `WizardApp` /
11
+ * the import wizard:
12
+ *
13
+ * 1. CLI flag wins when provided.
14
+ * 2. Otherwise, the value persisted in `credentials.json` (written by
15
+ * `experiences setup`) is used.
16
+ * 3. Otherwise, the built-in default (currently `'claude'`) is used for
17
+ * the agent. Model has no default — agents pick a small/fast model
18
+ * themselves when no model is included in `--agent`.
19
+ */
20
+ /** Built-in fallback agent when neither a flag nor a stored preference is set. */
21
+ export declare const DEFAULT_AGENT = "claude";
22
+ export declare function parseAgentModel(value: string | undefined): {
23
+ agent?: string;
24
+ model?: string;
25
+ };
26
+ export declare function resolveAgent(flagValue: string | undefined, storedValue: string | undefined): string;
27
+ export declare function resolveModel(flagValue: string | undefined, storedValue: string | undefined): string | undefined;
@@ -1,9 +1,7 @@
1
1
  export type CompositionOptionInput = {
2
- compositionMap?: string;
3
2
  prompt?: string[];
4
3
  };
5
4
  export type CompositionForwardingOptions = {
6
- compositionMap?: string;
7
5
  promptOverrides?: string[];
8
6
  };
9
7
  export declare function buildCompositionForwardingOptions(options: CompositionOptionInput): CompositionForwardingOptions;
@@ -17,6 +17,7 @@ export declare function buildGenerateTokensArgs(opts: {
17
17
  model?: string;
18
18
  bedrock?: boolean;
19
19
  noCache?: boolean;
20
+ promptOverrides?: string[];
20
21
  }): string[];
21
22
  export declare function buildMapTokensArgs(opts: {
22
23
  sessionId: string;
@@ -24,6 +25,7 @@ export declare function buildMapTokensArgs(opts: {
24
25
  model?: string;
25
26
  noCache?: boolean;
26
27
  skipAgent?: boolean;
28
+ promptOverrides?: string[];
27
29
  existingEntitiesPath?: string;
28
30
  }): string[];
29
31
  export declare function shouldRunMapTokens(opts: {
@@ -51,7 +53,6 @@ export type WizardAppProps = {
51
53
  bedrock?: boolean;
52
54
  initialProjectPath?: string;
53
55
  host?: string;
54
- compositionMap?: string;
55
56
  promptOverrides?: string[];
56
57
  noCache?: boolean;
57
58
  livePreview?: boolean;
@@ -59,4 +60,4 @@ export type WizardAppProps = {
59
60
  skipMapTokens?: boolean;
60
61
  initialRawTokensPath?: string;
61
62
  };
62
- export declare function WizardApp({ initialSpaceId, initialEnvironmentId, initialCmaToken, initialHost, initialAgent, initialModel, bedrock, initialProjectPath, host, compositionMap, promptOverrides, noCache, livePreview, generatePromptPath, skipMapTokens, initialRawTokensPath, }?: WizardAppProps): React.ReactElement;
63
+ export declare function WizardApp({ initialSpaceId, initialEnvironmentId, initialCmaToken, initialHost, initialAgent, initialModel, bedrock, initialProjectPath, host, promptOverrides, noCache, livePreview, generatePromptPath, skipMapTokens, initialRawTokensPath, }?: WizardAppProps): React.ReactElement;
@@ -0,0 +1,8 @@
1
+ import { type AgentName } from '@contentful/experience-design-system-generation';
2
+ export declare function runSelectionAgent(options: {
3
+ sessionId: string;
4
+ agent: AgentName;
5
+ model?: string;
6
+ promptText?: string;
7
+ promptPath?: string;
8
+ }): Promise<void>;
package/dist/src/index.js CHANGED
@@ -1184,6 +1184,17 @@ function initDebugLogger(opts) {
1184
1184
  function getDebugLogger() {
1185
1185
  return singleton ?? new NoopDebugLogger();
1186
1186
  }
1187
+ function resolveDebugMode(opts, configDebug) {
1188
+ if (opts.debug !== void 0) return opts.debug;
1189
+ const env = process.env["EDSI_DEBUG"];
1190
+ if (env !== void 0 && env !== "") {
1191
+ const v = env.toLowerCase();
1192
+ if (v === "1" || v === "true" || v === "yes" || v === "on") return true;
1193
+ if (v === "0" || v === "false" || v === "no" || v === "off") return false;
1194
+ }
1195
+ if (configDebug !== void 0) return configDebug;
1196
+ return false;
1197
+ }
1187
1198
  function printDebugBanner(logger, phase) {
1188
1199
  if (!logger.enabled || !logger.path) return;
1189
1200
  const prefix = phase === "start" ? "\x1B[92m[debug]\x1B[0m " : "\x1B[92m[debug]\x1B[0m ";
@@ -4135,12 +4146,17 @@ var init_persistence = __esm({
4135
4146
 
4136
4147
  // packages/experience-design-system-cli/src/lib/agent-model-options.ts
4137
4148
  function addAgentModelOptions(cmd, config = {}) {
4138
- const { agentDescription = AGENT_DESCRIPTION, includeModel = true, modelDescription = MODEL_DESCRIPTION } = config;
4149
+ const {
4150
+ agentDescription = AGENT_DESCRIPTION,
4151
+ includeModel = true,
4152
+ includeBedrock = true,
4153
+ modelDescription = MODEL_DESCRIPTION
4154
+ } = config;
4139
4155
  cmd.option("--agent <name>", agentDescription);
4140
4156
  if (includeModel) {
4141
4157
  cmd.option("--model <name>", modelDescription);
4142
4158
  }
4143
- cmd.option("--bedrock", BEDROCK_DESCRIPTION);
4159
+ if (includeBedrock) cmd.option("--bedrock", BEDROCK_DESCRIPTION);
4144
4160
  return cmd;
4145
4161
  }
4146
4162
  var AGENT_DESCRIPTION, MODEL_DESCRIPTION, BEDROCK_AGENTS, BEDROCK_DESCRIPTION;
@@ -4899,7 +4915,8 @@ async function runGenerateSkill(skill, opts, verbose = false) {
4899
4915
  const { overrides: promptOverrides, errors: promptErrors } = parsePromptOverrides(opts.prompt ?? []);
4900
4916
  if (promptErrors.length > 0) die(`Error: ${promptErrors.join("; ")}`);
4901
4917
  let generatePrompt;
4902
- const generateOverride = promptOverrides.get("generate");
4918
+ const promptStage = skill === "tokens" ? "tokens" : "generate";
4919
+ const generateOverride = promptOverrides.get(promptStage);
4903
4920
  if (generateOverride) {
4904
4921
  try {
4905
4922
  generatePrompt = await resolvePromptOverride(generateOverride);
@@ -5249,7 +5266,12 @@ function registerInternalGenerateCommand(program) {
5249
5266
  addAgentFlags(componentsCmd).action(async (opts) => {
5250
5267
  await runGenerateSkill("components", opts, opts.verbose ?? false);
5251
5268
  });
5252
- const tokensCmd = generate.command("tokens").description("Invoke a coding agent to produce tokens.json from raw token data").option("--raw-tokens <path>", "Path to raw token input file");
5269
+ const tokensCmd = generate.command("tokens").description("Invoke a coding agent to produce tokens.json from raw token data").option("--raw-tokens <path>", "Path to raw token input file").option(
5270
+ "--prompt <stage=value>",
5271
+ "Override a stage prompt (repeatable). Used here for the tokens stage.",
5272
+ (v, acc) => [...acc, v],
5273
+ []
5274
+ );
5253
5275
  addAgentFlags(tokensCmd).action(async (opts) => {
5254
5276
  await runGenerateSkill("tokens", opts, opts.verbose ?? false);
5255
5277
  });
@@ -7521,7 +7543,7 @@ function buildApplyOutput(operation, spaceId, environmentId, host) {
7521
7543
  };
7522
7544
  }
7523
7545
  function registerApplyCommand(program) {
7524
- const applyCmd = program.command("apply").description("Write component types and design tokens to Contentful ExO").argument("<file>", "CDF file containing all component and design token definitions");
7546
+ const applyCmd = program.command("apply").description("Write component types and design tokens to Contentful ExO").helpOption(false).argument("<file>", "CDF file containing all component and design token definitions");
7525
7547
  applyCmd.action(async (file) => {
7526
7548
  const isTTY = getInteractiveTerminalSupport().supported;
7527
7549
  const inputs = await resolveSharedInputsOrDie(file);
@@ -8469,6 +8491,20 @@ async function runMapTokens(opts) {
8469
8491
  );
8470
8492
  }
8471
8493
  const resultAgent = configuredAgent ?? "skipped";
8494
+ const { overrides: promptOverrides, errors: promptErrors } = parsePromptOverrides(opts.prompt ?? []);
8495
+ if (promptErrors.length > 0) die(`Error: ${promptErrors.join("; ")}`);
8496
+ const mapPromptOverride = promptOverrides.get("map-tokens");
8497
+ let mapPromptText;
8498
+ let mapPromptPath;
8499
+ if (mapPromptOverride?.kind === "text") mapPromptText = mapPromptOverride.value;
8500
+ if (mapPromptOverride?.kind === "path") {
8501
+ mapPromptPath = resolve8(mapPromptOverride.value);
8502
+ try {
8503
+ await resolvePromptOverride(mapPromptOverride);
8504
+ } catch (error) {
8505
+ die(`Error: ${error instanceof Error ? error.message : String(error)}`);
8506
+ }
8507
+ }
8472
8508
  const db = openPipelineDb();
8473
8509
  try {
8474
8510
  const sessionId2 = opts.session ?? findLatestSessionForCommand(db, "generate components");
@@ -8571,16 +8607,19 @@ ${defaultDiagnostics.map((diagnostic) => ` ${diagnostic}`).join("\n")}
8571
8607
  );
8572
8608
  }
8573
8609
  }
8610
+ const buildMapPrompt = () => buildPrompt({
8611
+ skill: "map-tokens",
8612
+ mode: "autonomous",
8613
+ generatedCdf,
8614
+ tokenTree,
8615
+ componentSourceRefs,
8616
+ outDir: process.cwd(),
8617
+ existingTokensInline,
8618
+ ...mapPromptText !== void 0 ? { skillContentOverride: mapPromptText } : {},
8619
+ ...mapPromptText === void 0 && mapPromptPath ? { skillPathOverride: mapPromptPath } : {}
8620
+ });
8574
8621
  if (opts.printPrompt) {
8575
- const prompt2 = await buildPrompt({
8576
- skill: "map-tokens",
8577
- mode: "autonomous",
8578
- generatedCdf,
8579
- tokenTree,
8580
- componentSourceRefs,
8581
- outDir: process.cwd(),
8582
- existingTokensInline
8583
- });
8622
+ const prompt2 = await buildMapPrompt();
8584
8623
  process.stdout.write(prompt2 + "\n");
8585
8624
  await exitWithAnalytics(0);
8586
8625
  return;
@@ -8602,7 +8641,8 @@ ${defaultDiagnostics.map((diagnostic) => ` ${diagnostic}`).join("\n")}
8602
8641
  agent,
8603
8642
  model,
8604
8643
  void 0,
8605
- existingTokensInline ? [hashContent(existingTokensInline)] : []
8644
+ existingTokensInline ? [hashContent(existingTokensInline)] : [],
8645
+ mapPromptText
8606
8646
  );
8607
8647
  const inputHash = computeMapTokensInputHash(db, sessionId2, componentSourceRefs);
8608
8648
  if (!noCache) {
@@ -8624,15 +8664,7 @@ Install it, choose another agent with --agent, or use --print-prompt to run the
8624
8664
  );
8625
8665
  }
8626
8666
  const stepId = createStep(db, sessionId2, "map tokens", { agent, model: model ?? "" });
8627
- const prompt = await buildPrompt({
8628
- skill: "map-tokens",
8629
- mode: "autonomous",
8630
- generatedCdf,
8631
- tokenTree,
8632
- componentSourceRefs,
8633
- outDir: process.cwd(),
8634
- existingTokensInline
8635
- });
8667
+ const prompt = await buildMapPrompt();
8636
8668
  const invoker2 = createLocalCliAgentInvoker();
8637
8669
  const result = await invoker2.invoke({ agent, model, prompt, timeoutMs: DEFAULT_TIMEOUT_MS2 });
8638
8670
  if (result.timedOut || result.exitCode !== 0) {
@@ -8658,7 +8690,12 @@ ${warnings.map((w) => ` ${w}`).join("\n")}
8658
8690
  }
8659
8691
  function registerMapTokensCommand(program) {
8660
8692
  const map = program.command("map", { hidden: true }).description("Suggest token restrictions for generated design-token props");
8661
- const tokensCmd = map.command("tokens").description("Invoke a coding agent to suggest $token.allowed for design-category token props").option("--session <id>", "Session ID from generate components (defaults to most recent)").option("--print-prompt", "Print the prompt without invoking the agent").option("--skip-agent", "Resolve token defaults without agentic $token.allowed inference").option("--no-cache", "Bypass the map-tokens cache and force a re-run").option("--token-map <path>", "Path to token-name-map.json sidecar").option(
8693
+ const tokensCmd = map.command("tokens").description("Invoke a coding agent to suggest $token.allowed for design-category token props").option("--session <id>", "Session ID from generate components (defaults to most recent)").option("--print-prompt", "Print the prompt without invoking the agent").option("--skip-agent", "Resolve token defaults without agentic $token.allowed inference").option("--no-cache", "Bypass the map-tokens cache and force a re-run").option(
8694
+ "--prompt <stage=value>",
8695
+ "Override a stage prompt (repeatable). Used here for the map-tokens stage.",
8696
+ (v, acc) => [...acc, v],
8697
+ []
8698
+ ).option("--token-map <path>", "Path to token-name-map.json sidecar").option(
8662
8699
  "--existing-entities-path <path>",
8663
8700
  "Path to the .existing-entities.json file written after CMA credentials are supplied. When present, the agent gets a list of the space's existing design tokens so it can prefer binding to them. Missing/malformed files are treated as no-op."
8664
8701
  );
@@ -8683,6 +8720,7 @@ var init_command4 = __esm({
8683
8720
  init_MapTokensView();
8684
8721
  init_resolve_defaults();
8685
8722
  init_cli_errors();
8723
+ init_prompt_overrides();
8686
8724
  DEFAULT_TIMEOUT_MS2 = Number(process.env.EDS_AGENT_TIMEOUT_MS ?? 5 * 60 * 1e3);
8687
8725
  }
8688
8726
  });
@@ -8710,10 +8748,41 @@ var init_path_utils = __esm({
8710
8748
  }
8711
8749
  });
8712
8750
 
8751
+ // packages/experience-design-system-cli/src/import/agent-model-resolve.ts
8752
+ function parseAgentModel(value) {
8753
+ if (!value?.trim()) return {};
8754
+ const trimmed = value.trim();
8755
+ const separator = trimmed.indexOf(":");
8756
+ if (separator >= 0) {
8757
+ return {
8758
+ agent: trimmed.slice(0, separator).trim() || void 0,
8759
+ model: trimmed.slice(separator + 1).trim() || void 0
8760
+ };
8761
+ }
8762
+ const [agent, ...modelParts] = trimmed.split(/\s+/);
8763
+ return { agent, ...modelParts.length > 0 ? { model: modelParts.join(" ") } : {} };
8764
+ }
8765
+ function resolveAgent(flagValue, storedValue) {
8766
+ if (flagValue && flagValue.length > 0) return flagValue;
8767
+ if (storedValue && storedValue.length > 0) return storedValue;
8768
+ return DEFAULT_AGENT;
8769
+ }
8770
+ function resolveModel(flagValue, storedValue) {
8771
+ if (flagValue && flagValue.length > 0) return flagValue;
8772
+ if (storedValue && storedValue.length > 0) return storedValue;
8773
+ return void 0;
8774
+ }
8775
+ var DEFAULT_AGENT;
8776
+ var init_agent_model_resolve = __esm({
8777
+ "packages/experience-design-system-cli/src/import/agent-model-resolve.ts"() {
8778
+ "use strict";
8779
+ DEFAULT_AGENT = "claude";
8780
+ }
8781
+ });
8782
+
8713
8783
  // packages/experience-design-system-cli/src/import/composition-options.ts
8714
8784
  function buildCompositionForwardingOptions(options) {
8715
8785
  return {
8716
- ...options.compositionMap ? { compositionMap: options.compositionMap } : {},
8717
8786
  ...options.prompt && options.prompt.length > 0 ? { promptOverrides: options.prompt } : {}
8718
8787
  };
8719
8788
  }
@@ -26568,6 +26637,70 @@ var init_wizard_state_transitions = __esm({
26568
26637
  }
26569
26638
  });
26570
26639
 
26640
+ // packages/experience-design-system-cli/src/import/tui/run-selection-agent.ts
26641
+ async function runSelectionAgent(options) {
26642
+ const db = openPipelineDb();
26643
+ let components;
26644
+ try {
26645
+ components = loadRawComponents(db, options.sessionId);
26646
+ } finally {
26647
+ db.close();
26648
+ }
26649
+ if (components.length === 0) return;
26650
+ const invoker2 = createLocalCliAgentInvoker({
26651
+ onDebugEvent: (name, payload) => getDebugLogger().event("agent", name, payload)
26652
+ });
26653
+ const prompt = await buildPrompt({
26654
+ skill: "select",
26655
+ mode: "autonomous",
26656
+ rawComponentsInline: JSON.stringify(components, null, 2),
26657
+ outDir: process.cwd(),
26658
+ ...options.promptText !== void 0 ? { skillContentOverride: options.promptText } : {},
26659
+ ...options.promptText === void 0 && options.promptPath ? { skillPathOverride: options.promptPath } : {}
26660
+ });
26661
+ const { result } = await invokeAgentWithOutput(
26662
+ invoker2,
26663
+ { agent: options.agent, model: options.model, prompt, timeoutMs: DEFAULT_TIMEOUT_MS4 },
26664
+ false
26665
+ );
26666
+ if (result.timedOut) throw new Error("selection agent timed out");
26667
+ if (result.exitCode !== 0) throw new Error(`selection agent exited with code ${result.exitCode}`);
26668
+ const { calls, warnings } = parseSelectToolCallLines(result.stdout);
26669
+ for (const warning of warnings) process.stderr.write(`Warning: selection agent: ${warning}
26670
+ `);
26671
+ const byName = new Map(calls.map((call) => [call.name, call]));
26672
+ const writeDb = openPipelineDb();
26673
+ try {
26674
+ const update = writeDb.prepare(
26675
+ `UPDATE raw_components SET status = ?, reject_reason = ? WHERE session_id = ? AND component_id = ?`
26676
+ );
26677
+ for (const component of components) {
26678
+ const call = byName.get(component.name);
26679
+ if (!call) continue;
26680
+ const rejected = call.tool === "reject_component";
26681
+ update.run(
26682
+ rejected ? "rejected" : "accepted",
26683
+ rejected ? call.reason ?? null : null,
26684
+ options.sessionId,
26685
+ component.component_id
26686
+ );
26687
+ }
26688
+ } finally {
26689
+ writeDb.close();
26690
+ }
26691
+ }
26692
+ var DEFAULT_TIMEOUT_MS4;
26693
+ var init_run_selection_agent = __esm({
26694
+ "packages/experience-design-system-cli/src/import/tui/run-selection-agent.ts"() {
26695
+ "use strict";
26696
+ init_src();
26697
+ init_debug_logger();
26698
+ init_agent_output();
26699
+ init_db();
26700
+ DEFAULT_TIMEOUT_MS4 = Number(process.env.EDS_AGENT_TIMEOUT_MS ?? 5 * 60 * 1e3);
26701
+ }
26702
+ });
26703
+
26571
26704
  // packages/experience-design-system-cli/src/import/tui/WizardApp.tsx
26572
26705
  var WizardApp_exports = {};
26573
26706
  __export(WizardApp_exports, {
@@ -26606,6 +26739,7 @@ function buildGenerateTokensArgs(opts) {
26606
26739
  if (opts.model) args.push("--model", opts.model);
26607
26740
  if (opts.bedrock) args.push("--bedrock");
26608
26741
  if (opts.noCache) args.push("--no-cache");
26742
+ for (const prompt of opts.promptOverrides ?? []) args.push("--prompt", prompt);
26609
26743
  return args;
26610
26744
  }
26611
26745
  function buildMapTokensArgs(opts) {
@@ -26613,6 +26747,7 @@ function buildMapTokensArgs(opts) {
26613
26747
  if (opts.model) args.push("--model", opts.model);
26614
26748
  if (opts.noCache) args.push("--no-cache");
26615
26749
  if (opts.skipAgent) args.push("--skip-agent");
26750
+ for (const prompt of opts.promptOverrides ?? []) args.push("--prompt", prompt);
26616
26751
  if (opts.existingEntitiesPath) args.push("--existing-entities-path", opts.existingEntitiesPath);
26617
26752
  return args;
26618
26753
  }
@@ -26688,7 +26823,6 @@ function WizardApp({
26688
26823
  bedrock = false,
26689
26824
  initialProjectPath,
26690
26825
  host,
26691
- compositionMap,
26692
26826
  promptOverrides,
26693
26827
  noCache = false,
26694
26828
  livePreview = true,
@@ -26858,7 +26992,8 @@ If you are using AWS Bedrock, run:
26858
26992
  agent: state.agent,
26859
26993
  ...state.agentModel ? { model: state.agentModel } : {},
26860
26994
  ...state.bedrock ? { bedrock: true } : {},
26861
- noCache: effectiveNoCache
26995
+ noCache: effectiveNoCache,
26996
+ promptOverrides
26862
26997
  });
26863
26998
  const result = await runSpawnedCli(tokenArgs);
26864
26999
  if (result.exitCode !== 0) {
@@ -26938,6 +27073,7 @@ If you are using AWS Bedrock, run:
26938
27073
  ...state.agentModel ? { model: state.agentModel } : {},
26939
27074
  noCache: effectiveNoCache,
26940
27075
  skipAgent: skipMapTokens,
27076
+ promptOverrides,
26941
27077
  ...state.existingEntitiesPath ? { existingEntitiesPath: state.existingEntitiesPath } : {}
26942
27078
  });
26943
27079
  const result = await runCli(args);
@@ -26956,7 +27092,6 @@ If you are using AWS Bedrock, run:
26956
27092
  update({ step: "extracting", outDir, extractProgress: null, compositionPhase: null });
26957
27093
  const extractArgs = [findCliPath(), "__extract", "--project", projectPath];
26958
27094
  if (noCache) extractArgs.push("--composition-refresh");
26959
- if (compositionMap) extractArgs.push("--composition-map", compositionMap);
26960
27095
  for (const p of promptOverrides ?? []) extractArgs.push("--prompt", p);
26961
27096
  if (state.agent) extractArgs.push("--agent", state.agent);
26962
27097
  if (state.bedrock) extractArgs.push("--bedrock");
@@ -27021,6 +27156,34 @@ Make sure this path contains TypeScript/React/Vue component files (.tsx, .ts, .v
27021
27156
  });
27022
27157
  return;
27023
27158
  }
27159
+ try {
27160
+ const { overrides, errors } = parsePromptOverrides(promptOverrides ?? []);
27161
+ if (errors.length > 0) throw new Error(errors.join("; "));
27162
+ const selectOverride = overrides.get("select");
27163
+ let promptText;
27164
+ let promptPath;
27165
+ if (selectOverride?.kind === "text") promptText = selectOverride.value;
27166
+ if (selectOverride?.kind === "path") {
27167
+ promptPath = resolve17(selectOverride.value);
27168
+ await resolvePromptOverride(selectOverride);
27169
+ }
27170
+ if (state.agent) {
27171
+ await runSelectionAgent({
27172
+ sessionId: extractSessionId ?? "",
27173
+ agent: state.agent,
27174
+ ...state.agentModel ? { model: state.agentModel } : {},
27175
+ ...promptText !== void 0 ? { promptText } : {},
27176
+ ...promptPath ? { promptPath } : {}
27177
+ });
27178
+ }
27179
+ } catch (error) {
27180
+ update({
27181
+ step: "error",
27182
+ errorStep: "selection agent",
27183
+ errorMessage: error instanceof Error ? error.message : String(error)
27184
+ });
27185
+ return;
27186
+ }
27024
27187
  update({
27025
27188
  step: "scope-gate",
27026
27189
  extractSessionId
@@ -28267,6 +28430,8 @@ var init_WizardApp = __esm({
28267
28430
  init_fetch_and_persist_existing_contentful_entities();
28268
28431
  init_wizard_state_transitions();
28269
28432
  init_cli_path();
28433
+ init_prompt_overrides();
28434
+ init_run_selection_agent();
28270
28435
  WIZARD_LOG = join20(tmpdir(), "experiences-import-wizard.log");
28271
28436
  }
28272
28437
  });
@@ -28274,81 +28439,73 @@ var init_WizardApp = __esm({
28274
28439
  // packages/experience-design-system-cli/src/import/command.ts
28275
28440
  function registerImportCommand(program) {
28276
28441
  const cmd = program.command("import").description("Run the full pipeline: analyze \u2192 select \u2192 generate \u2192 push").option("--project <path>", "Path to the project root to analyze", ".");
28277
- addAgentModelOptions(cmd, {
28278
- agentDescription: 'Agent to use for generate components (overrides credentials.json; falls back to "claude")',
28279
- modelDescription: "Model to use for generate components (defaults to a lightweight per-agent model; override with EDS_AGENT_MODEL_<AGENT>)"
28280
- }).option(
28281
- "--raw-tokens <path>",
28442
+ cmd.option(
28443
+ "--tokens <path>",
28282
28444
  "Path to a raw token source file (SCSS, CSS variables, JS/TS, Style Dictionary, etc.) to classify and import alongside components. Bypasses the interactive token prompt."
28283
- ).option(
28284
- "--skip-map-tokens",
28285
- "Skip agentic token restrictions while still resolving deterministic token-default paths"
28286
- ).option("--no-cache", "Re-run all steps even if output already exists");
28287
- cmd.option("--composition-map <path>", "Consume a hand-authored parent\u2192children interchange map").option(
28445
+ );
28446
+ addAgentModelOptions(cmd, {
28447
+ agentDescription: 'Agent and optional model as agent:model or "agent model" (overrides credentials.json; falls back to "claude")',
28448
+ includeModel: false,
28449
+ includeBedrock: false
28450
+ });
28451
+ cmd.option(
28288
28452
  "--prompt <stage=value>",
28289
- "Override a stage prompt (repeatable). value is a file path or literal text, e.g. --prompt composition=./p.md",
28453
+ "Override a composition, selection, token, generation, or token-mapping prompt (repeatable). value is a file path or literal text, e.g. --prompt select=./p.md",
28290
28454
  (v, acc) => [...acc, v],
28291
28455
  []
28292
- ).action(
28293
- async (opts) => {
28294
- const interactiveTerminalSupported = getInteractiveTerminalSupport().supported;
28295
- if (opts.rawTokens !== void 0) {
28296
- const { access: access9 } = await import("node:fs/promises");
28297
- try {
28298
- await access9(normalizePath(opts.rawTokens));
28299
- } catch {
28300
- process.stderr.write(`Error: --raw-tokens: file not found: ${opts.rawTokens}
28301
- `);
28302
- process.exit(1);
28303
- return;
28304
- }
28305
- }
28306
- if (!interactiveTerminalSupported) {
28307
- requireInteractiveTerminal({
28308
- alternative: "run experiences import in an interactive terminal"
28309
- });
28310
- }
28311
- {
28312
- const { render: render5 } = await import("ink");
28313
- const { createElement: createElement6 } = await import("react");
28314
- const { WizardApp: WizardApp2 } = await Promise.resolve().then(() => (init_WizardApp(), WizardApp_exports));
28315
- const creds = await readExperiencesCredentials();
28316
- const resolvedAgent = opts.agent || creds.agent || "claude";
28317
- const resolvedModel = opts.model || creds.agentModel || void 0;
28318
- if (opts.bedrock && !(isAgentName(resolvedAgent) && agentSupportsBedrock(resolvedAgent))) {
28319
- process.stderr.write(`Error: --bedrock is not supported for --agent ${resolvedAgent}
28456
+ ).option("--no-cache", "Re-run all steps even if output already exists").action(async (opts) => {
28457
+ const interactiveTerminalSupported = getInteractiveTerminalSupport().supported;
28458
+ if (opts.tokens !== void 0) {
28459
+ const { access: access9 } = await import("node:fs/promises");
28460
+ try {
28461
+ await access9(normalizePath(opts.tokens));
28462
+ } catch {
28463
+ process.stderr.write(`Error: --tokens: file not found: ${opts.tokens}
28320
28464
  `);
28321
- process.exit(1);
28322
- }
28323
- const { waitUntilExit } = render5(
28324
- createElement6(WizardApp2, {
28325
- initialSpaceId: creds.spaceId,
28326
- initialEnvironmentId: creds.environmentId || "master",
28327
- initialCmaToken: creds.cmaToken,
28328
- initialHost: toConfiguredHost(creds.host) ?? DEFAULT_CONFIGURED_HOST,
28329
- initialAgent: resolvedAgent,
28330
- ...resolvedModel ? { initialModel: resolvedModel } : {},
28331
- ...opts.bedrock ? { bedrock: true } : {},
28332
- initialProjectPath: opts.project !== "." ? normalizePath(opts.project) : void 0,
28333
- ...buildCompositionForwardingOptions(opts),
28334
- noCache: opts.cache === false,
28335
- skipMapTokens: opts.skipMapTokens ?? false,
28336
- livePreview: true,
28337
- generatePromptPath: creds.generatePromptPath,
28338
- ...opts.rawTokens ? { initialRawTokensPath: normalizePath(opts.rawTokens) } : {}
28339
- })
28340
- );
28341
- await waitUntilExit();
28465
+ process.exit(1);
28342
28466
  return;
28343
28467
  }
28344
28468
  }
28345
- );
28469
+ if (!interactiveTerminalSupported) {
28470
+ requireInteractiveTerminal({
28471
+ alternative: "run experiences import in an interactive terminal"
28472
+ });
28473
+ }
28474
+ {
28475
+ const { render: render5 } = await import("ink");
28476
+ const { createElement: createElement6 } = await import("react");
28477
+ const { WizardApp: WizardApp2 } = await Promise.resolve().then(() => (init_WizardApp(), WizardApp_exports));
28478
+ const creds = await readExperiencesCredentials();
28479
+ const parsedAgentModel = parseAgentModel(opts.agent);
28480
+ const resolvedAgent = resolveAgent(parsedAgentModel.agent, creds.agent);
28481
+ const resolvedModel = resolveModel(parsedAgentModel.model, creds.agentModel);
28482
+ const { waitUntilExit } = render5(
28483
+ createElement6(WizardApp2, {
28484
+ initialSpaceId: creds.spaceId,
28485
+ initialEnvironmentId: creds.environmentId || "master",
28486
+ initialCmaToken: creds.cmaToken,
28487
+ initialHost: toConfiguredHost(creds.host) ?? DEFAULT_CONFIGURED_HOST,
28488
+ initialAgent: resolvedAgent,
28489
+ ...resolvedModel ? { initialModel: resolvedModel } : {},
28490
+ initialProjectPath: opts.project !== "." ? normalizePath(opts.project) : void 0,
28491
+ ...buildCompositionForwardingOptions(opts),
28492
+ noCache: opts.cache === false,
28493
+ skipMapTokens: false,
28494
+ livePreview: true,
28495
+ generatePromptPath: creds.generatePromptPath,
28496
+ ...opts.tokens ? { initialRawTokensPath: normalizePath(opts.tokens) } : {}
28497
+ })
28498
+ );
28499
+ await waitUntilExit();
28500
+ return;
28501
+ }
28502
+ });
28346
28503
  }
28347
28504
  var init_command6 = __esm({
28348
28505
  "packages/experience-design-system-cli/src/import/command.ts"() {
28349
28506
  "use strict";
28350
- init_src();
28351
28507
  init_path_utils();
28508
+ init_agent_model_resolve();
28352
28509
  init_agent_model_options();
28353
28510
  init_credentials_store();
28354
28511
  init_host_utils();
@@ -28659,7 +28816,7 @@ var init_checks2 = __esm({
28659
28816
  });
28660
28817
 
28661
28818
  // packages/experience-design-system-cli/src/doctor/command.ts
28662
- async function runChecks(opts) {
28819
+ async function runChecks() {
28663
28820
  const pkgRoot = findPkgRoot();
28664
28821
  const results = [];
28665
28822
  const record = (name, passed, required = true) => {
@@ -28668,13 +28825,11 @@ async function runChecks(opts) {
28668
28825
  };
28669
28826
  if (record("Node.js version", await reportNode())) {
28670
28827
  const pnpmOk = record("pnpm", await reportPnpm(pkgRoot));
28671
- if (opts.skipBuild) {
28672
- info("\nSkipping install + build (--skip-build)");
28673
- } else if (pnpmOk && record("dependencies", await reportDependencies(pkgRoot))) {
28828
+ if (pnpmOk && record("dependencies", await reportDependencies(pkgRoot))) {
28674
28829
  record("build", await reportBuild(pkgRoot));
28675
28830
  }
28676
28831
  }
28677
- if (!opts.skipAgent) record("coding agent", await reportAgent(), false);
28832
+ record("coding agent", await reportAgent(), false);
28678
28833
  return results;
28679
28834
  }
28680
28835
  function printSummary(results) {
@@ -28714,13 +28869,13 @@ ${c.red(c.bold(`\u2717 ${requiredFailed} required check${requiredFailed === 1 ?
28714
28869
  `);
28715
28870
  return 1;
28716
28871
  }
28717
- async function runDoctor(opts) {
28872
+ async function runDoctor() {
28718
28873
  process.stderr.write(`${c.bold("experiences doctor")} \u2014 checking your environment
28719
28874
  `);
28720
- process.exitCode = printSummary(await runChecks(opts));
28875
+ process.exitCode = printSummary(await runChecks());
28721
28876
  }
28722
28877
  function registerDoctorCommand(program) {
28723
- program.command("doctor").description("Check prerequisites so experiences import runs without errors").option("--skip-build", "Skip the pnpm install + build step (useful if already built)").option("--skip-agent", "Skip the coding agent check").action((opts) => runDoctor(opts));
28878
+ program.command("doctor").description("Check prerequisites so experiences import runs without errors").helpOption(false).action(() => runDoctor());
28724
28879
  }
28725
28880
  var init_command7 = __esm({
28726
28881
  "packages/experience-design-system-cli/src/doctor/command.ts"() {
@@ -29860,7 +30015,7 @@ async function runSetup(opts) {
29860
30015
  process.exit(finished.exitCode);
29861
30016
  }
29862
30017
  function registerSetupCommand(program) {
29863
- program.command("setup").description("Interactive setup: installs prerequisites and configures credentials for experiences import").option("--skip-build", "Skip the pnpm install + build step").option("--skip-agent", "Skip the coding agent check").option("--skip-credentials", "Skip the Contentful credentials step").option("--skip-optional", "Skip optional quality-of-life extras").action((opts) => runSetup(opts));
30018
+ program.command("setup").description("Interactive setup: installs prerequisites and configures credentials for experiences import").helpOption(false).action(() => runSetup({}));
29864
30019
  }
29865
30020
  var SETUP_REQUIRES_TTY_MESSAGE;
29866
30021
  var init_command8 = __esm({
@@ -29872,57 +30027,14 @@ var init_command8 = __esm({
29872
30027
  }
29873
30028
  });
29874
30029
 
29875
- // packages/experience-design-system-cli/src/analyze/composition/interchange-schema.ts
29876
- function validateInterchangeMap(input) {
29877
- const errors = [];
29878
- if (typeof input !== "object" || input === null || Array.isArray(input)) {
29879
- return { valid: false, errors: ["interchange map must be a JSON object"] };
29880
- }
29881
- const obj = input;
29882
- if (obj.version !== 1) {
29883
- errors.push(`unsupported interchange version: expected 1, got ${JSON.stringify(obj.version)}`);
29884
- }
29885
- if (typeof obj.groups !== "object" || obj.groups === null || Array.isArray(obj.groups)) {
29886
- errors.push("interchange map must have a `groups` object");
29887
- return { valid: false, errors };
29888
- }
29889
- const groups = obj.groups;
29890
- for (const [parent, children] of Object.entries(groups)) {
29891
- if (!Array.isArray(children) || !children.every((c2) => typeof c2 === "string")) {
29892
- errors.push(`groups["${parent}"] must be an array of strings`);
29893
- }
29894
- }
29895
- if (errors.length > 0) return { valid: false, errors };
29896
- return { valid: true, map: { version: 1, groups } };
29897
- }
29898
- function groupsToEdges(map, provenance) {
29899
- const seen = /* @__PURE__ */ new Set();
29900
- const edges = [];
29901
- for (const [parent, children] of Object.entries(map.groups)) {
29902
- for (const child of children) {
29903
- const key = `${parent}::${child}`;
29904
- if (seen.has(key)) continue;
29905
- seen.add(key);
29906
- edges.push({ parent, child, provenance });
29907
- }
29908
- }
29909
- return edges;
29910
- }
29911
- var init_interchange_schema = __esm({
29912
- "packages/experience-design-system-cli/src/analyze/composition/interchange-schema.ts"() {
29913
- "use strict";
29914
- }
29915
- });
29916
-
29917
30030
  // packages/experience-design-system-cli/src/analyze/composition/merge-edges.ts
29918
30031
  function rank(p) {
29919
- if (p === "user") return 1;
29920
- if (p === "typed-slot") return 2;
29921
- if (p === "structural") return 3;
29922
- if (p === "manifest") return 4;
29923
- if (p === "doc") return 5;
29924
- if (p.startsWith("adapter:")) return 6;
29925
- return 7;
30032
+ if (p === "typed-slot") return 1;
30033
+ if (p === "structural") return 2;
30034
+ if (p === "manifest") return 3;
30035
+ if (p === "doc") return 4;
30036
+ if (p.startsWith("adapter:")) return 5;
30037
+ return 6;
29926
30038
  }
29927
30039
  function mergeEdges(all) {
29928
30040
  const byKey = /* @__PURE__ */ new Map();
@@ -30028,7 +30140,7 @@ function applyMapping(components, edges) {
30028
30140
  }))
30029
30141
  }));
30030
30142
  const byName = new Map(cloned.map((c2) => [c2.name, c2]));
30031
- const isHighTrust = (p) => p === "user" || p === "typed-slot" || p.startsWith("adapter:");
30143
+ const isHighTrust = (p) => p === "typed-slot" || p.startsWith("adapter:");
30032
30144
  const addAllowed = (slot, child) => {
30033
30145
  const set = new Set(slot.allowedComponents ?? []);
30034
30146
  set.add(child);
@@ -30127,7 +30239,6 @@ async function resolveMapping(input) {
30127
30239
  }
30128
30240
  }
30129
30241
  }
30130
- if (input.userMap) collected.push(...groupsToEdges(input.userMap, "user"));
30131
30242
  if (input.extraEdges) {
30132
30243
  collected.push(...input.extraEdges);
30133
30244
  }
@@ -30175,7 +30286,6 @@ ${f.content}`).join("\n\n");
30175
30286
  var init_resolve_mapping = __esm({
30176
30287
  "packages/experience-design-system-cli/src/analyze/composition/resolve-mapping.ts"() {
30177
30288
  "use strict";
30178
- init_interchange_schema();
30179
30289
  init_merge_edges();
30180
30290
  init_parse_map_edges();
30181
30291
  init_apply_mapping();
@@ -30184,24 +30294,6 @@ var init_resolve_mapping = __esm({
30184
30294
  });
30185
30295
 
30186
30296
  // packages/experience-design-system-cli/src/analyze/composition/resolve-mapping-cli.ts
30187
- import { readFile as readFile18 } from "node:fs/promises";
30188
- async function loadUserMap(path) {
30189
- let text;
30190
- try {
30191
- text = await readFile18(path, "utf8");
30192
- } catch {
30193
- return { ok: false, error: `--composition-map: file not found: ${path}` };
30194
- }
30195
- let parsed;
30196
- try {
30197
- parsed = JSON.parse(text);
30198
- } catch {
30199
- return { ok: false, error: `--composition-map: not valid JSON: ${path}` };
30200
- }
30201
- const result = validateInterchangeMap(parsed);
30202
- if (!result.valid) return { ok: false, error: `--composition-map: ${result.errors.join("; ")}` };
30203
- return { ok: true, map: result.map };
30204
- }
30205
30297
  function resolveCompositionSources(opts) {
30206
30298
  return {
30207
30299
  forceAgent: !!opts.compositionRefresh
@@ -30210,7 +30302,6 @@ function resolveCompositionSources(opts) {
30210
30302
  var init_resolve_mapping_cli = __esm({
30211
30303
  "packages/experience-design-system-cli/src/analyze/composition/resolve-mapping-cli.ts"() {
30212
30304
  "use strict";
30213
- init_interchange_schema();
30214
30305
  }
30215
30306
  });
30216
30307
 
@@ -30372,7 +30463,7 @@ var init_manifest_doc_evidence = __esm({
30372
30463
  });
30373
30464
 
30374
30465
  // packages/experience-design-system-cli/src/analyze/extract-command.ts
30375
- import { mkdir as mkdir6, readdir as readdir3, readFile as readFile19, stat as stat6 } from "node:fs/promises";
30466
+ import { mkdir as mkdir6, readdir as readdir3, readFile as readFile18, stat as stat6 } from "node:fs/promises";
30376
30467
  import { isAbsolute as isAbsolute2, join as join25, relative as relative2, resolve as resolve19 } from "node:path";
30377
30468
  function isDenylistedNoiseFile(name) {
30378
30469
  return DENYLISTED_EXACT_FILE_NAMES.has(name) || DENYLISTED_FILE_NAME_PATTERNS.some((pattern) => pattern.test(name));
@@ -30439,7 +30530,7 @@ async function readCandidateFiles(components, extraFiles = []) {
30439
30530
  await Promise.all(
30440
30531
  [...paths].map(async (p) => {
30441
30532
  try {
30442
- const content = await readFile19(p, "utf8");
30533
+ const content = await readFile18(p, "utf8");
30443
30534
  out.push({ path: p, content });
30444
30535
  } catch {
30445
30536
  }
@@ -30452,7 +30543,7 @@ function registerInternalExtractCommand(program) {
30452
30543
  "--resolve-unreachable <mode>",
30453
30544
  "Retry pass for unresolved Svelte Props types: 'auto' (default), 'always', or 'never'",
30454
30545
  "auto"
30455
- ).option("--composition-refresh", "Force the mapping agent to run even where deterministic sources answered").option("--composition-map <path>", "Consume a hand-authored parent\u2192children interchange map").option(
30546
+ ).option("--composition-refresh", "Force the mapping agent to run even where deterministic sources answered").option(
30456
30547
  "--prompt <stage=value>",
30457
30548
  "Override a stage prompt (repeatable). value is a file path or literal text, e.g. --prompt composition=./p.md",
30458
30549
  (v, acc) => [...acc, v],
@@ -30568,16 +30659,6 @@ function registerInternalExtractCommand(program) {
30568
30659
  let validatedComponents = validateExtractedComponents(filteredComponents);
30569
30660
  {
30570
30661
  const sources = resolveCompositionSources(opts);
30571
- let userMap;
30572
- if (opts.compositionMap) {
30573
- const loaded = await loadUserMap(opts.compositionMap);
30574
- if (!loaded.ok) {
30575
- process.stderr.write(`Error: ${loaded.error}
30576
- `);
30577
- process.exit(1);
30578
- }
30579
- userMap = loaded.map;
30580
- }
30581
30662
  const { overrides: promptOverrides, errors: promptErrors } = parsePromptOverrides(opts.prompt ?? []);
30582
30663
  for (const err of promptErrors) {
30583
30664
  process.stderr.write(`Error: ${err}
@@ -30639,7 +30720,6 @@ function registerInternalExtractCommand(program) {
30639
30720
  });
30640
30721
  const result = await resolveMapping({
30641
30722
  components: validatedComponents,
30642
- ...userMap ? { userMap } : {},
30643
30723
  ...extraEdges.length > 0 ? { extraEdges } : {},
30644
30724
  forceAgent: sources.forceAgent,
30645
30725
  files: promptFiles,
@@ -30780,14 +30860,14 @@ var init_extract_command = __esm({
30780
30860
  });
30781
30861
 
30782
30862
  // packages/experience-design-system-cli/src/lib/debug-preamble.ts
30783
- async function beginCommand(command) {
30863
+ async function beginCommand(command, opts) {
30784
30864
  let configDebug;
30785
30865
  try {
30786
30866
  const creds = await readExperiencesCredentials();
30787
30867
  configDebug = creds.debug;
30788
30868
  } catch {
30789
30869
  }
30790
- const enabled = configDebug ?? false;
30870
+ const enabled = resolveDebugMode(opts, configDebug);
30791
30871
  const logger = initDebugLogger({ enabled, command });
30792
30872
  if (logger.enabled) {
30793
30873
  printDebugBanner(logger, "start");
@@ -30846,7 +30926,7 @@ function resolveBedrockFromAncestors(actionCommand) {
30846
30926
  return false;
30847
30927
  }
30848
30928
  function registerImportV2Command(program) {
30849
- program.command("importv2").description("Launch the v2 import").action(async () => {
30929
+ program.command("importv2").description("Launch the v2 import TUI (experience-design-system-cli-v2)").helpOption(false).action(async () => {
30850
30930
  const v2Path = join26(
30851
30931
  dirname13(fileURLToPath4(import.meta.url)),
30852
30932
  "..",
@@ -30864,7 +30944,7 @@ function registerImportV2Command(program) {
30864
30944
  });
30865
30945
  }
30866
30946
  function registerBuildCommand(program) {
30867
- program.command("build").description("Rebuild from source and re-link exo/experiences binaries to this build").action(async () => {
30947
+ program.command("build").description("Rebuild from source and re-link exo/experiences binaries to this build").helpOption(false).action(async () => {
30868
30948
  const pkgRoot = resolve20(dirname13(fileURLToPath4(import.meta.url)), "..", "..");
30869
30949
  process.stderr.write("\u2699 Building from source...\n");
30870
30950
  const { exitCode } = await runBuild({
@@ -30874,18 +30954,34 @@ function registerBuildCommand(program) {
30874
30954
  process.exit(exitCode);
30875
30955
  });
30876
30956
  }
30957
+ function configureRootHelpOrder(program) {
30958
+ const order = ["build", "help", "import", "apply", "importv2", "setup", "doctor"];
30959
+ const rank2 = new Map(order.map((name, index) => [name, index]));
30960
+ program.configureHelp({
30961
+ visibleCommands(command) {
30962
+ const internals = command;
30963
+ const visible = command.commands.filter((entry) => !entry._hidden);
30964
+ const helpCommand = internals._getHelpCommand?.();
30965
+ if (helpCommand && !helpCommand._hidden) visible.push(helpCommand);
30966
+ if (command !== program) return visible;
30967
+ return visible.sort((a, b) => (rank2.get(a.name()) ?? order.length) - (rank2.get(b.name()) ?? order.length));
30968
+ }
30969
+ });
30970
+ }
30877
30971
  function createProgram() {
30878
30972
  const program = new Command().name("experience-design-system-cli").description("Static analysis, validation, generation, and import of Contentful design system artifacts").version(pkg3.version, "--version", "Print version number");
30879
30973
  registerInternalGenerateCommand(program);
30880
30974
  registerInternalExtractCommand(program);
30881
30975
  registerPrintCommand(program);
30882
30976
  registerMapTokensCommand(program);
30883
- registerApplyCommand(program);
30977
+ registerBuildCommand(program);
30978
+ program.helpCommand("help [command]", "display help for command");
30884
30979
  registerImportCommand(program);
30980
+ registerApplyCommand(program);
30885
30981
  registerImportV2Command(program);
30886
- registerDoctorCommand(program);
30887
30982
  registerSetupCommand(program);
30888
- registerBuildCommand(program);
30983
+ registerDoctorCommand(program);
30984
+ configureRootHelpOrder(program);
30889
30985
  program.hook("preAction", async (_thisCommand, actionCommand) => {
30890
30986
  if (resolveBedrockFromAncestors(actionCommand)) {
30891
30987
  process.env.EDS_BEDROCK = "1";
@@ -30896,7 +30992,7 @@ function createProgram() {
30896
30992
  const { analyticsDisabled } = await readExperiencesCredentials();
30897
30993
  setPersistedAnalyticsDisabled(analyticsDisabled ?? false);
30898
30994
  noteCommandStart(commandChain);
30899
- await beginCommand(commandChain);
30995
+ await beginCommand(commandChain, {});
30900
30996
  });
30901
30997
  program.hook("postAction", async () => {
30902
30998
  await completeActiveCommand();
@@ -4,12 +4,12 @@ export declare const MODEL_DESCRIPTION = "Model to use (defaults to a lightweigh
4
4
  export interface AgentModelOptionsConfig {
5
5
  agentDescription?: string;
6
6
  includeModel?: boolean;
7
+ includeBedrock?: boolean;
7
8
  modelDescription?: string;
8
9
  }
9
10
  /**
10
- * Register --agent, --bedrock, and optional --model flags with a Commander
11
- * command. Pass includeModel: false to omit --model only — --bedrock is
12
- * independent of model selection (it's a routing switch, not a model choice)
13
- * and is always registered alongside --agent.
11
+ * Register --agent plus optional --model and --bedrock flags with a Commander
12
+ * command. The optional flags can be omitted for commands with a narrower
13
+ * public surface.
14
14
  */
15
15
  export declare function addAgentModelOptions(cmd: Command, config?: AgentModelOptionsConfig): Command;
@@ -25,6 +25,17 @@ export declare function initDebugLogger(opts: InitDebugLoggerOptions): DebugLogg
25
25
  export declare function getDebugLogger(): DebugLogger;
26
26
  /** Test-only: reset the singleton. */
27
27
  export declare function __resetDebugLoggerForTest(): void;
28
+ /**
29
+ * Resolve effective debug-mode setting from three sources.
30
+ *
31
+ * Precedence (highest first):
32
+ * 1. `EDSI_DEBUG` env var (truthy: 1, true, yes, on)
33
+ * 2. Persisted `debug` field in credentials.json
34
+ * 4. Default: OFF
35
+ */
36
+ export declare function resolveDebugMode(opts: {
37
+ debug?: boolean;
38
+ }, configDebug?: boolean): boolean;
28
39
  /**
29
40
  * Emit the bright-green "debug logs at <path>" banner to stderr.
30
41
  * No-op when debug is disabled or stderr is not a TTY-friendly stream.
@@ -1,6 +1,14 @@
1
1
  import { type DebugLogger } from './debug-logger.js';
2
2
  /**
3
- * Initialize the debug logger from persisted credentials.
4
- * Debug mode can only be configured via setup preferences;
3
+ * Preamble every top-level command action should call before doing work.
4
+ *
5
+ * Resolves the effective debug decision (flag > env > persisted config),
6
+ * initializes the singleton, and prints the bright-green start banner.
7
+ * Registers a process-exit handler that prints the end banner once.
8
+ *
9
+ * Returns the logger so the caller can emit events without a second import.
10
+ * When debug is disabled, the returned logger is a no-op.
5
11
  */
6
- export declare function beginCommand(command: string): Promise<DebugLogger>;
12
+ export declare function beginCommand(command: string, opts: {
13
+ debug?: boolean;
14
+ }): Promise<DebugLogger>;
@@ -16,9 +16,9 @@ export declare function runBuild(opts: {
16
16
  exitCode: number;
17
17
  }>;
18
18
  /**
19
- * Walks `actionCommand` and its ancestors for a truthy `--bedrock`.
20
- * --bedrock is registered per-subcommand, so a root-level or
21
- * subcommand-level setting can each carry it.
19
+ * Walks `actionCommand` and its ancestors for a truthy `--bedrock`. --bedrock
20
+ * is registered per-subcommand, so a
21
+ * root-level or subcommand-level setting can each carry it.
22
22
  */
23
23
  export declare function resolveBedrockFromAncestors(actionCommand: Command): boolean;
24
24
  export declare function createProgram(): Command;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contentful/experience-design-system-cli",
3
- "version": "2.34.5-dev-build-d42cd1ad.0",
3
+ "version": "2.34.5-dev-build-4985ea96.0",
4
4
  "description": "Contentful Experiences design system import CLI",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -41,8 +41,8 @@
41
41
  "svelte": "^5.56.4",
42
42
  "ts-morph": "^27.0.2",
43
43
  "typescript": "^5.9.3",
44
- "@contentful/experience-design-system-cli-v2": "2.34.5-dev-build-d42cd1ad.0",
45
- "@contentful/experience-design-system-types": "2.34.5-dev-build-d42cd1ad.0"
44
+ "@contentful/experience-design-system-types": "2.34.5-dev-build-4985ea96.0",
45
+ "@contentful/experience-design-system-cli-v2": "2.34.5-dev-build-4985ea96.0"
46
46
  },
47
47
  "devDependencies": {
48
48
  "@tsconfig/node24": "^24.0.4",
@@ -54,9 +54,9 @@
54
54
  "ink-testing-library": "^4.0.0",
55
55
  "typescript-eslint": "^8.67.0",
56
56
  "vitest": "^4.0.16",
57
- "@contentful/experience-design-system-client": "2.34.5-dev-build-d42cd1ad.0",
58
- "@contentful/experience-design-system-generation": "2.34.5-dev-build-d42cd1ad.0",
59
- "@contentful/experience-design-system-extraction": "2.34.5-dev-build-d42cd1ad.0"
57
+ "@contentful/experience-design-system-client": "2.34.5-dev-build-4985ea96.0",
58
+ "@contentful/experience-design-system-extraction": "2.34.5-dev-build-4985ea96.0",
59
+ "@contentful/experience-design-system-generation": "2.34.5-dev-build-4985ea96.0"
60
60
  },
61
61
  "repository": {
62
62
  "type": "git",