@contentful/experience-design-system-cli 2.2.1

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.
Files changed (165) hide show
  1. package/README.md +532 -0
  2. package/bin/cli.js +58 -0
  3. package/dist/package.json +56 -0
  4. package/dist/src/analyze/command.d.ts +3 -0
  5. package/dist/src/analyze/command.js +175 -0
  6. package/dist/src/analyze/extract/astro.d.ts +5 -0
  7. package/dist/src/analyze/extract/astro.js +280 -0
  8. package/dist/src/analyze/extract/pipeline.d.ts +6 -0
  9. package/dist/src/analyze/extract/pipeline.js +298 -0
  10. package/dist/src/analyze/extract/react.d.ts +2 -0
  11. package/dist/src/analyze/extract/react.js +1949 -0
  12. package/dist/src/analyze/extract/slot-detection.d.ts +35 -0
  13. package/dist/src/analyze/extract/slot-detection.js +101 -0
  14. package/dist/src/analyze/extract/stencil.d.ts +2 -0
  15. package/dist/src/analyze/extract/stencil.js +293 -0
  16. package/dist/src/analyze/extract/tsx-shared.d.ts +8 -0
  17. package/dist/src/analyze/extract/tsx-shared.js +263 -0
  18. package/dist/src/analyze/extract/vue-tsx.d.ts +2 -0
  19. package/dist/src/analyze/extract/vue-tsx.js +498 -0
  20. package/dist/src/analyze/extract/vue.d.ts +5 -0
  21. package/dist/src/analyze/extract/vue.js +647 -0
  22. package/dist/src/analyze/extract/web-components.d.ts +2 -0
  23. package/dist/src/analyze/extract/web-components.js +866 -0
  24. package/dist/src/analyze/pre-classify.d.ts +17 -0
  25. package/dist/src/analyze/pre-classify.js +144 -0
  26. package/dist/src/analyze/select/command.d.ts +2 -0
  27. package/dist/src/analyze/select/command.js +256 -0
  28. package/dist/src/analyze/select/index.d.ts +6 -0
  29. package/dist/src/analyze/select/index.js +5 -0
  30. package/dist/src/analyze/select/parser.d.ts +6 -0
  31. package/dist/src/analyze/select/parser.js +53 -0
  32. package/dist/src/analyze/select/persistence.d.ts +9 -0
  33. package/dist/src/analyze/select/persistence.js +42 -0
  34. package/dist/src/analyze/select/stdout.d.ts +7 -0
  35. package/dist/src/analyze/select/stdout.js +3 -0
  36. package/dist/src/analyze/select/tui/App.d.ts +8 -0
  37. package/dist/src/analyze/select/tui/App.js +491 -0
  38. package/dist/src/analyze/select/tui/components/ComponentDetail.d.ts +20 -0
  39. package/dist/src/analyze/select/tui/components/ComponentDetail.js +43 -0
  40. package/dist/src/analyze/select/tui/components/FieldEditor.d.ts +11 -0
  41. package/dist/src/analyze/select/tui/components/FieldEditor.js +531 -0
  42. package/dist/src/analyze/select/tui/components/FinalizeDialog.d.ts +10 -0
  43. package/dist/src/analyze/select/tui/components/FinalizeDialog.js +15 -0
  44. package/dist/src/analyze/select/tui/components/HelpOverlay.d.ts +7 -0
  45. package/dist/src/analyze/select/tui/components/HelpOverlay.js +11 -0
  46. package/dist/src/analyze/select/tui/components/JsonEditor.d.ts +11 -0
  47. package/dist/src/analyze/select/tui/components/JsonEditor.js +154 -0
  48. package/dist/src/analyze/select/tui/components/JsonPanel.d.ts +11 -0
  49. package/dist/src/analyze/select/tui/components/JsonPanel.js +62 -0
  50. package/dist/src/analyze/select/tui/components/PreviewSummaryBar.d.ts +8 -0
  51. package/dist/src/analyze/select/tui/components/PreviewSummaryBar.js +29 -0
  52. package/dist/src/analyze/select/tui/components/QuitDialog.d.ts +8 -0
  53. package/dist/src/analyze/select/tui/components/QuitDialog.js +14 -0
  54. package/dist/src/analyze/select/tui/components/Sidebar.d.ts +15 -0
  55. package/dist/src/analyze/select/tui/components/Sidebar.js +48 -0
  56. package/dist/src/analyze/select/tui/components/SourcePanel.d.ts +11 -0
  57. package/dist/src/analyze/select/tui/components/SourcePanel.js +52 -0
  58. package/dist/src/analyze/select/tui/components/StatusBar.d.ts +11 -0
  59. package/dist/src/analyze/select/tui/components/StatusBar.js +6 -0
  60. package/dist/src/analyze/select/tui/components/TopBar.d.ts +10 -0
  61. package/dist/src/analyze/select/tui/components/TopBar.js +5 -0
  62. package/dist/src/analyze/select/tui/hooks/useImmediateInput.d.ts +24 -0
  63. package/dist/src/analyze/select/tui/hooks/useImmediateInput.js +68 -0
  64. package/dist/src/analyze/select/tui/hooks/useKeymap.d.ts +24 -0
  65. package/dist/src/analyze/select/tui/hooks/useKeymap.js +67 -0
  66. package/dist/src/analyze/select/tui/hooks/useSession.d.ts +19 -0
  67. package/dist/src/analyze/select/tui/hooks/useSession.js +52 -0
  68. package/dist/src/analyze/select/tui/hooks/useUndo.d.ts +8 -0
  69. package/dist/src/analyze/select/tui/hooks/useUndo.js +26 -0
  70. package/dist/src/analyze/select/types.d.ts +46 -0
  71. package/dist/src/analyze/select/types.js +20 -0
  72. package/dist/src/analyze/select-agent/command.d.ts +2 -0
  73. package/dist/src/analyze/select-agent/command.js +208 -0
  74. package/dist/src/analyze/tui/AnalyzeView.d.ts +24 -0
  75. package/dist/src/analyze/tui/AnalyzeView.js +38 -0
  76. package/dist/src/apply/api-client.d.ts +35 -0
  77. package/dist/src/apply/api-client.js +143 -0
  78. package/dist/src/apply/command.d.ts +6 -0
  79. package/dist/src/apply/command.js +787 -0
  80. package/dist/src/apply/manifest.d.ts +1 -0
  81. package/dist/src/apply/manifest.js +1 -0
  82. package/dist/src/apply/tui/SelectView.d.ts +18 -0
  83. package/dist/src/apply/tui/SelectView.js +34 -0
  84. package/dist/src/apply/tui/ServerApplyView.d.ts +32 -0
  85. package/dist/src/apply/tui/ServerApplyView.js +42 -0
  86. package/dist/src/apply/tui/ServerPreviewView.d.ts +9 -0
  87. package/dist/src/apply/tui/ServerPreviewView.js +21 -0
  88. package/dist/src/credentials-store.d.ts +8 -0
  89. package/dist/src/credentials-store.js +30 -0
  90. package/dist/src/generate/agent-runner.d.ts +86 -0
  91. package/dist/src/generate/agent-runner.js +314 -0
  92. package/dist/src/generate/command.d.ts +2 -0
  93. package/dist/src/generate/command.js +545 -0
  94. package/dist/src/generate/edit/command.d.ts +2 -0
  95. package/dist/src/generate/edit/command.js +126 -0
  96. package/dist/src/generate/prompt-builder.d.ts +18 -0
  97. package/dist/src/generate/prompt-builder.js +202 -0
  98. package/dist/src/generate/tui/GenerateView.d.ts +12 -0
  99. package/dist/src/generate/tui/GenerateView.js +10 -0
  100. package/dist/src/import/command.d.ts +2 -0
  101. package/dist/src/import/command.js +96 -0
  102. package/dist/src/import/orchestrator.d.ts +37 -0
  103. package/dist/src/import/orchestrator.js +374 -0
  104. package/dist/src/import/path-utils.d.ts +15 -0
  105. package/dist/src/import/path-utils.js +30 -0
  106. package/dist/src/import/tui/WizardApp.d.ts +10 -0
  107. package/dist/src/import/tui/WizardApp.js +906 -0
  108. package/dist/src/import/tui/steps/CredentialsStep.d.ts +15 -0
  109. package/dist/src/import/tui/steps/CredentialsStep.js +79 -0
  110. package/dist/src/import/tui/steps/DoneStep.d.ts +20 -0
  111. package/dist/src/import/tui/steps/DoneStep.js +17 -0
  112. package/dist/src/import/tui/steps/ErrorStep.d.ts +8 -0
  113. package/dist/src/import/tui/steps/ErrorStep.js +11 -0
  114. package/dist/src/import/tui/steps/GateStep.d.ts +14 -0
  115. package/dist/src/import/tui/steps/GateStep.js +20 -0
  116. package/dist/src/import/tui/steps/GenerateReviewStep.d.ts +8 -0
  117. package/dist/src/import/tui/steps/GenerateReviewStep.js +208 -0
  118. package/dist/src/import/tui/steps/PathValidationStep.d.ts +10 -0
  119. package/dist/src/import/tui/steps/PathValidationStep.js +151 -0
  120. package/dist/src/import/tui/steps/PreviewStep.d.ts +21 -0
  121. package/dist/src/import/tui/steps/PreviewStep.js +36 -0
  122. package/dist/src/import/tui/steps/RunningStep.d.ts +10 -0
  123. package/dist/src/import/tui/steps/RunningStep.js +20 -0
  124. package/dist/src/import/tui/steps/TokenInputStep.d.ts +8 -0
  125. package/dist/src/import/tui/steps/TokenInputStep.js +70 -0
  126. package/dist/src/import/tui/steps/WelcomeStep.d.ts +7 -0
  127. package/dist/src/import/tui/steps/WelcomeStep.js +33 -0
  128. package/dist/src/import/tui/steps/WizardPreviewStep.d.ts +15 -0
  129. package/dist/src/import/tui/steps/WizardPreviewStep.js +121 -0
  130. package/dist/src/import/tui/steps/preview-diff.d.ts +10 -0
  131. package/dist/src/import/tui/steps/preview-diff.js +132 -0
  132. package/dist/src/index.d.ts +1 -0
  133. package/dist/src/index.js +2 -0
  134. package/dist/src/output/format.d.ts +23 -0
  135. package/dist/src/output/format.js +110 -0
  136. package/dist/src/print/command.d.ts +2 -0
  137. package/dist/src/print/command.js +199 -0
  138. package/dist/src/print/validate/tui/ValidateView.d.ts +15 -0
  139. package/dist/src/print/validate/tui/ValidateView.js +37 -0
  140. package/dist/src/print/validate/validators/cdf-validator.d.ts +2 -0
  141. package/dist/src/print/validate/validators/cdf-validator.js +104 -0
  142. package/dist/src/print/validate/validators/dtcg-validator.d.ts +2 -0
  143. package/dist/src/print/validate/validators/dtcg-validator.js +110 -0
  144. package/dist/src/print/validate/validators/format-errors.d.ts +12 -0
  145. package/dist/src/print/validate/validators/format-errors.js +18 -0
  146. package/dist/src/program.d.ts +2 -0
  147. package/dist/src/program.js +25 -0
  148. package/dist/src/session/command.d.ts +2 -0
  149. package/dist/src/session/command.js +261 -0
  150. package/dist/src/session/db.d.ts +111 -0
  151. package/dist/src/session/db.js +1114 -0
  152. package/dist/src/session/migration.d.ts +4 -0
  153. package/dist/src/session/migration.js +117 -0
  154. package/dist/src/session/session-id.d.ts +1 -0
  155. package/dist/src/session/session-id.js +212 -0
  156. package/dist/src/session/stats.d.ts +27 -0
  157. package/dist/src/session/stats.js +89 -0
  158. package/dist/src/setup/command.d.ts +2 -0
  159. package/dist/src/setup/command.js +765 -0
  160. package/dist/src/types.d.ts +48 -0
  161. package/dist/src/types.js +1 -0
  162. package/package.json +55 -0
  163. package/skills/generate-components.md +361 -0
  164. package/skills/generate-tokens.md +194 -0
  165. package/skills/select-components.md +180 -0
@@ -0,0 +1,202 @@
1
+ import { existsSync } from 'node:fs';
2
+ import { readFile } from 'node:fs/promises';
3
+ import { dirname, join, resolve } from 'node:path';
4
+ import { fileURLToPath } from 'node:url';
5
+ const SKILL_FILES = {
6
+ components: 'generate-components.md',
7
+ tokens: 'generate-tokens.md',
8
+ select: 'select-components.md',
9
+ };
10
+ const OUTPUT_FILES = {
11
+ components: 'components.json',
12
+ tokens: 'tokens.json',
13
+ select: 'select.json',
14
+ };
15
+ export async function buildPrompt(options) {
16
+ const skillContent = await readSkillFile(options.skill);
17
+ const preamble = buildPreamble(options);
18
+ return `${preamble}\n\nSkill instructions follow:\n---\n${skillContent}`;
19
+ }
20
+ export function resolveSkillPath(skill) {
21
+ if (!(skill in SKILL_FILES))
22
+ throw new Error(`Invalid skill: ${skill}`);
23
+ // Walk up until we find the skills/ directory (works from both src/ and dist/src/ contexts)
24
+ const thisDir = dirname(fileURLToPath(import.meta.url));
25
+ let dir = thisDir;
26
+ for (;;) {
27
+ const candidate = join(dir, 'skills');
28
+ if (existsSync(candidate))
29
+ return join(candidate, SKILL_FILES[skill]);
30
+ const parent = resolve(dir, '..');
31
+ if (parent === dir) {
32
+ throw new Error(`skill file missing from CLI installation (could not locate skills/ directory from: ${thisDir})`);
33
+ }
34
+ dir = parent;
35
+ }
36
+ }
37
+ async function readSkillFile(skill) {
38
+ const skillPath = resolveSkillPath(skill);
39
+ try {
40
+ return await readFile(skillPath, 'utf8');
41
+ }
42
+ catch {
43
+ throw new Error(`skill file missing from CLI installation — try reinstalling the CLI (looked for: ${skillPath})`);
44
+ }
45
+ }
46
+ function inferFenceLang(filename) {
47
+ if (!filename)
48
+ return 'json';
49
+ const ext = filename.split('.').pop()?.toLowerCase() ?? '';
50
+ const map = {
51
+ js: 'js',
52
+ mjs: 'js',
53
+ cjs: 'js',
54
+ ts: 'ts',
55
+ mts: 'ts',
56
+ cts: 'ts',
57
+ scss: 'scss',
58
+ sass: 'scss',
59
+ css: 'css',
60
+ json: 'json',
61
+ json5: 'json',
62
+ };
63
+ return map[ext] ?? 'text';
64
+ }
65
+ function buildPreamble(options) {
66
+ const { skill, mode, rawComponentsInline, rawTokensInline, rawTokensFilename, tokensInline, tokenMapInline, outDir } = options;
67
+ const outputFile = OUTPUT_FILES[skill];
68
+ const outputPath = join(resolve(outDir), outputFile);
69
+ const sections = [];
70
+ if (rawComponentsInline) {
71
+ sections.push(`Raw component data (JSON):\n\`\`\`json\n${rawComponentsInline}\n\`\`\``);
72
+ }
73
+ if (rawTokensInline) {
74
+ const lang = inferFenceLang(rawTokensFilename);
75
+ const label = rawTokensFilename ? `Raw token source (${rawTokensFilename})` : 'Raw token source';
76
+ sections.push(`${label}:\n\`\`\`${lang}\n${rawTokensInline}\n\`\`\``);
77
+ }
78
+ if (tokensInline) {
79
+ sections.push(`DTCG token data (for token kind lookups):\n\`\`\`json\n${tokensInline}\n\`\`\``);
80
+ }
81
+ if (tokenMapInline) {
82
+ sections.push(`Token-name sidecar (raw name → DTCG path):\n\`\`\`json\n${tokenMapInline}\n\`\`\``);
83
+ }
84
+ const inputBlock = sections.length > 0 ? `\n\n${sections.join('\n\n')}` : '';
85
+ if (mode === 'autonomous') {
86
+ if (skill === 'components') {
87
+ return buildComponentsAutonomousPreamble(inputBlock);
88
+ }
89
+ if (skill === 'select') {
90
+ return buildSelectAutonomousPreamble(inputBlock);
91
+ }
92
+ return buildTokensAutonomousPreamble(inputBlock);
93
+ }
94
+ else {
95
+ return `You are running as part of the experience-design-system-cli generate pipeline in INTERACTIVE mode. The developer is present and will answer your questions.
96
+
97
+ Your task: follow the skill instructions below, working collaboratively with the developer. Ask for confirmation on category corrections, prop exclusions, and grouping choices as the skill instructs.
98
+
99
+ All input data is provided inline below — do not read any additional files.${inputBlock}
100
+
101
+ Output:
102
+ Write the final ${outputFile} directly to: ${outputPath}`;
103
+ }
104
+ }
105
+ function buildComponentsAutonomousPreamble(inputBlock) {
106
+ return `You are running as part of the experience-design-system-cli generate pipeline in AUTONOMOUS mode. The developer is not present to answer questions.
107
+
108
+ Context: You are classifying a React component for **Contentful Experience Orchestration**. The result is a Component Type — a schema that tells Contentful what a marketer can configure. Properties fall into three categories:
109
+ - **design**: controls how the component looks (variant, size, color, layout toggles)
110
+ - **content**: the data a content editor fills in (text, images, URLs, rich text)
111
+ - **state**: runtime behavioral flags (disabled, loading, expanded, identifiers)
112
+
113
+ For props with complex TypeScript types (named types, enums): reason from the prop name and type name to classify them. Do not automatically exclude a prop just because its type is a named reference — infer the likely values and classify it as enum if it controls appearance.
114
+
115
+ Your task: classify every prop and slot in the component below. Apply all judgment calls yourself — do not pause to ask for confirmation. Include a "description" field on each tool call to document your reasoning so the developer can review it afterward.
116
+
117
+ All input data is provided inline below — do not read any additional files.${inputBlock}
118
+
119
+ ## Output protocol
120
+
121
+ Do NOT write any files or emit any JSON blobs. Instead, emit one JSON object per line to stdout for each classification decision. The CLI reads your stdout line by line and writes each decision directly to the pipeline database.
122
+
123
+ The four tool calls you may emit are:
124
+
125
+ \`\`\`
126
+ {"tool":"classify_component","description":"<optional component-level description>"}
127
+
128
+ {"tool":"classify_prop","prop":"<propName>","cdf_type":"<type>","cdf_category":"<category>","required":<bool>,"description":"<reason>","values":["a","b"],"token_kind":"color","default":"<value>"}
129
+
130
+ {"tool":"exclude_prop","prop":"<propName>","reason":"<why excluded>"}
131
+
132
+ {"tool":"classify_slot","slot":"<slotName>","required":<bool>,"allowed_components":["ComponentName"],"description":"<reason>"}
133
+ \`\`\`
134
+
135
+ Rules:
136
+ - Emit exactly one JSON object per line. No multi-line JSON. No markdown fences around the lines.
137
+ - Every prop in the input must have exactly one call: either classify_prop or exclude_prop.
138
+ - Every slot in the input must have exactly one classify_slot call.
139
+ - Valid cdf_type values: string, richtext, media, enum, token, boolean
140
+ - Valid cdf_category values: content, design, state
141
+ - For enum type, always include "values" (non-empty string array).
142
+ - For token type, always include "token_kind" (DTCG \$type, e.g. "color").
143
+ - href and URL props → cdf_type "string", cdf_category "content". Do NOT use cdf_type "link" — it is not valid.
144
+ - Framework internals (ref, event handlers, test IDs) → exclude_prop.
145
+ - CSS design props (className, style, styles, positional/geometric props: top, bottom, left, right, rotation, offset, etc.) → classify_prop, cdf_type: "string", cdf_category: "design".
146
+ - You may emit prose lines (not starting with {) anywhere — they are ignored by the parser and serve as your reasoning log.`;
147
+ }
148
+ function buildSelectAutonomousPreamble(inputBlock) {
149
+ return `You are running as part of the experience-design-system-cli import pipeline in AUTONOMOUS mode. The developer is not present to answer questions.
150
+
151
+ Your task: review the single component provided below and decide whether it belongs in Contentful Experience Orchestration as a Component Type. Apply all judgment calls yourself — do not pause to ask for confirmation. Include a brief "reason" to document your reasoning.
152
+
153
+ Key rule: accept any component that renders visible UI — atoms, molecules, and organisms are all valid Component Types in Contentful Experience Orchestration. Reject only components that produce zero visual output: React hooks, pure context providers, A/B testing or variant-routing wrappers, analytics trackers, and security utilities. Do NOT reject a component because it has few props, is low-level, or has some A/B testing or personalization-related props mixed in — those props are handled in the generate step.
154
+
155
+ All input data is provided inline below — do not read any additional files.${inputBlock}
156
+
157
+ ## Output protocol
158
+
159
+ Do NOT write any files or emit any JSON blobs. Instead, emit one JSON object on a single line to stdout. The CLI reads your stdout line by line.
160
+
161
+ The two tool calls — emit exactly one:
162
+
163
+ \`\`\`
164
+ {"tool":"select_component","name":"<ComponentName>","reason":"<brief reason>"}
165
+
166
+ {"tool":"reject_component","name":"<ComponentName>","reason":"<brief reason>"}
167
+ \`\`\`
168
+
169
+ Rules:
170
+ - Emit exactly one JSON object, on one line. No multi-line JSON. No markdown fences.
171
+ - The name must match the component name in the input exactly.
172
+ - You may emit prose lines (not starting with {) to reason before the final tool call — they are ignored by the parser.`;
173
+ }
174
+ function buildTokensAutonomousPreamble(inputBlock) {
175
+ return `You are running as part of the experience-design-system-cli generate pipeline in AUTONOMOUS mode. The developer is not present to answer questions.
176
+
177
+ Your task: classify every raw token from the input below into a DTCG token tree. Apply all judgment calls yourself — do not pause to ask for confirmation. Include a "description" field on each set_token call to document your reasoning.
178
+
179
+ All input data is provided inline below — do not read any additional files.${inputBlock}
180
+
181
+ ## Output protocol
182
+
183
+ Do NOT write any files or emit any JSON blobs. Instead, emit one JSON object per line to stdout for each token or group. The CLI reads your stdout line by line and writes each entry directly to the pipeline database.
184
+
185
+ The two tool calls you may emit are:
186
+
187
+ \`\`\`
188
+ {"tool":"set_group","path":"<dot.notation.path>","description":"<optional group description>"}
189
+
190
+ {"tool":"set_token","path":"<dot.notation.path>","type":"<DTCG type>","value":<value>,"description":"<reason>"}
191
+ \`\`\`
192
+
193
+ Rules:
194
+ - Emit exactly one JSON object per line. No multi-line JSON. No markdown fences.
195
+ - Emit a set_group call for every intermediate group node in the tree.
196
+ - Emit a set_token call for every leaf token.
197
+ - "path" is dot-notation, e.g. "colors.brand.primary" — no leading dots or slashes.
198
+ - "type" must be one of the 13 valid DTCG types: color, dimension, fontFamily, fontWeight, duration, cubicBezier, number, strokeStyle, border, transition, shadow, gradient, typography.
199
+ - "value" must be valid JSON (string, number, array, or object depending on the type). Do NOT wrap it in quotes if it is a complex type.
200
+ - Emit set_group calls before the set_token calls that fall under them.
201
+ - You may emit prose lines (not starting with {) anywhere — they are ignored by the parser and serve as your reasoning log.`;
202
+ }
@@ -0,0 +1,12 @@
1
+ import React from 'react';
2
+ export interface GenerateViewResult {
3
+ skill: string;
4
+ agent: string;
5
+ sessionId: string;
6
+ }
7
+ interface GenerateViewProps {
8
+ result: GenerateViewResult;
9
+ onExit: () => void;
10
+ }
11
+ export declare function GenerateView({ result, onExit }: GenerateViewProps): React.ReactElement;
12
+ export {};
@@ -0,0 +1,10 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import React from 'react';
3
+ import { Box, Text } from 'ink';
4
+ export function GenerateView({ result, onExit }) {
5
+ React.useEffect(() => {
6
+ const timer = setTimeout(onExit, 100);
7
+ return () => clearTimeout(timer);
8
+ }, [onExit]);
9
+ return (_jsxs(Box, { flexDirection: "column", padding: 1, children: [_jsx(Text, { color: "green", children: "\u2713 generate complete" }), _jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsxs(Text, { children: [_jsx(Text, { dimColor: true, children: "skill " }), _jsx(Text, { children: result.skill })] }), _jsxs(Text, { children: [_jsx(Text, { dimColor: true, children: "agent " }), _jsx(Text, { children: result.agent })] }), _jsxs(Text, { children: [_jsx(Text, { dimColor: true, children: "session " }), _jsx(Text, { children: result.sessionId })] })] }), _jsxs(Box, { marginTop: 1, children: [_jsx(Text, { dimColor: true, children: "Run " }), _jsxs(Text, { children: ["experience-design-system-cli print ", result.skill] }), _jsx(Text, { dimColor: true, children: " to write the output file." })] })] }));
10
+ }
@@ -0,0 +1,2 @@
1
+ import type { Command } from 'commander';
2
+ export declare function registerImportCommand(program: Command): void;
@@ -0,0 +1,96 @@
1
+ import { resolve, join } from 'node:path';
2
+ import { runPipeline } from './orchestrator.js';
3
+ import { readExoCredentials } from '../credentials-store.js';
4
+ export function registerImportCommand(program) {
5
+ program
6
+ .command('import')
7
+ .description('Run the full pipeline: analyze → select → generate → push')
8
+ .option('--space-id <id>', 'Contentful space ID (required unless --skip-apply)')
9
+ .option('--environment-id <id>', 'Contentful environment ID (required unless --skip-apply)')
10
+ .option('--cma-token <token>', 'CMA personal access token (or set CONTENTFUL_MANAGEMENT_TOKEN)')
11
+ .option('--project <path>', 'Path to the project root to analyze', '.')
12
+ .option('--out <path>', 'Output directory for pipeline artifacts')
13
+ .option('--agent <name>', 'Agent to use for generate components', 'claude')
14
+ .option('--model <name>', 'Model to use for generate components (defaults to a small/fast model per agent)')
15
+ .option('--tokens <path>', 'Path to a DTCG tokens.json file to push alongside generated components')
16
+ .option('--select-all', 'Select all extracted components for generation (default)')
17
+ .option('--select <pattern>', 'Select components matching pattern (repeatable)', (v, a) => [...a, v], [])
18
+ .option('--deselect <pattern>', 'Deselect components matching pattern (repeatable)', (v, a) => [...a, v], [])
19
+ .option('--skip-analyze', 'Skip the analyze step (uses most recent extract session)')
20
+ .option('--skip-generate', 'Skip the generate step (uses most recent generate session)')
21
+ .option('--print', 'Write components.json to --out after generation')
22
+ .option('--skip-apply', 'Skip pushing to Contentful (stops after generate)')
23
+ .option('--no-cache', 'Re-run all steps even if output already exists')
24
+ .option('--yes', 'Skip interactive confirmation in apply push')
25
+ .option('--verbose', 'Show full agent output and all entity progress')
26
+ .option('--viewports <path>', 'JSON file with viewport array (passed to apply push)')
27
+ .option('--host <url>', 'Override API base URL (passed to apply push)')
28
+ .option('--dry-run', 'Print generate components prompt without invoking the agent')
29
+ .action(async (opts) => {
30
+ const isHeadless = opts.skipAnalyze ||
31
+ opts.skipGenerate ||
32
+ opts.skipApply ||
33
+ !!opts.spaceId ||
34
+ !!opts.environmentId ||
35
+ !!opts.cmaToken ||
36
+ opts.yes ||
37
+ opts.dryRun ||
38
+ false;
39
+ if (process.stdout.isTTY && !isHeadless) {
40
+ const { render } = await import('ink');
41
+ const { createElement } = await import('react');
42
+ const { WizardApp } = await import('./tui/WizardApp.js');
43
+ const creds = await readExoCredentials();
44
+ const { waitUntilExit } = render(createElement(WizardApp, {
45
+ initialSpaceId: creds.spaceId,
46
+ initialEnvironmentId: creds.environmentId || 'master',
47
+ initialCmaToken: creds.cmaToken,
48
+ initialAgent: opts.agent !== 'claude' ? opts.agent : undefined,
49
+ initialProjectPath: opts.project !== '.' ? resolve(opts.project) : undefined,
50
+ host: opts.host,
51
+ }));
52
+ await waitUntilExit();
53
+ return;
54
+ }
55
+ const skipApply = opts.skipApply ?? false;
56
+ const spaceId = opts.spaceId ?? process.env['CONTENTFUL_SPACE_ID'];
57
+ const environmentId = opts.environmentId ?? process.env['CONTENTFUL_ENVIRONMENT_ID'];
58
+ const cmaToken = opts.cmaToken ?? process.env['CONTENTFUL_MANAGEMENT_TOKEN'];
59
+ if (!skipApply && (!spaceId || !environmentId || !cmaToken)) {
60
+ process.stderr.write('Error: --space-id (or CONTENTFUL_SPACE_ID), --environment-id (or CONTENTFUL_ENVIRONMENT_ID), and --cma-token (or CONTENTFUL_MANAGEMENT_TOKEN) are required unless --skip-apply is set.\n');
61
+ process.exit(1);
62
+ return;
63
+ }
64
+ const projectRoot = resolve(opts.project);
65
+ const outDir = opts.out ? resolve(opts.out) : join(projectRoot, '.contentful');
66
+ const result = await runPipeline({
67
+ project: projectRoot,
68
+ out: outDir,
69
+ spaceId,
70
+ environmentId,
71
+ cmaToken,
72
+ agent: opts.agent,
73
+ model: opts.model,
74
+ tokens: opts.tokens,
75
+ selectAll: opts.selectAll,
76
+ select: opts.select.length > 0 ? opts.select : undefined,
77
+ deselect: opts.deselect.length > 0 ? opts.deselect : undefined,
78
+ skipAnalyze: opts.skipAnalyze ?? false,
79
+ skipGenerate: opts.skipGenerate ?? false,
80
+ print: opts.print ?? false,
81
+ skipApply,
82
+ noCache: opts.cache === false,
83
+ yes: opts.yes ?? false,
84
+ verbose: opts.verbose ?? false,
85
+ viewports: opts.viewports,
86
+ host: opts.host,
87
+ dryRun: opts.dryRun,
88
+ }, (line) => process.stderr.write(line + '\n'));
89
+ const hasFailed = result.steps.some((s) => s.status === 'failed');
90
+ if (!process.stdout.isTTY) {
91
+ const json = JSON.stringify(result, null, 2) + '\n';
92
+ await new Promise((res) => process.stdout.write(json, () => res()));
93
+ }
94
+ process.exit(hasFailed ? 1 : 0);
95
+ });
96
+ }
@@ -0,0 +1,37 @@
1
+ export interface PipelineOptions {
2
+ project: string;
3
+ out: string;
4
+ spaceId?: string;
5
+ environmentId?: string;
6
+ cmaToken?: string;
7
+ agent: string;
8
+ model?: string;
9
+ skipAnalyze: boolean;
10
+ skipGenerate: boolean;
11
+ print: boolean;
12
+ skipApply: boolean;
13
+ noCache: boolean;
14
+ yes: boolean;
15
+ verbose: boolean;
16
+ tokens?: string;
17
+ viewports?: string;
18
+ host?: string;
19
+ dryRun?: boolean;
20
+ selectAll?: boolean;
21
+ select?: string[];
22
+ deselect?: string[];
23
+ }
24
+ export interface StepResult {
25
+ step: string;
26
+ status: 'complete' | 'failed' | 'skipped';
27
+ durationMs?: number;
28
+ reason?: string;
29
+ detail?: Record<string, unknown>;
30
+ error?: string;
31
+ }
32
+ export interface PipelineResult {
33
+ session: string;
34
+ project: string;
35
+ steps: StepResult[];
36
+ }
37
+ export declare function runPipeline(opts: PipelineOptions, progressWriter: (line: string) => void, cliPathOverride?: string): Promise<PipelineResult>;