@calibrate-ds/cli 0.1.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.
Files changed (201) hide show
  1. package/dist/__tests__/component-slug.test.d.ts +2 -0
  2. package/dist/__tests__/component-slug.test.d.ts.map +1 -0
  3. package/dist/__tests__/component-slug.test.js +54 -0
  4. package/dist/__tests__/component-slug.test.js.map +1 -0
  5. package/dist/__tests__/lock-changes.test.d.ts +2 -0
  6. package/dist/__tests__/lock-changes.test.d.ts.map +1 -0
  7. package/dist/__tests__/lock-changes.test.js +81 -0
  8. package/dist/__tests__/lock-changes.test.js.map +1 -0
  9. package/dist/__tests__/permissions.test.d.ts +2 -0
  10. package/dist/__tests__/permissions.test.d.ts.map +1 -0
  11. package/dist/__tests__/permissions.test.js +67 -0
  12. package/dist/__tests__/permissions.test.js.map +1 -0
  13. package/dist/__tests__/stamp-in-lock.test.d.ts +2 -0
  14. package/dist/__tests__/stamp-in-lock.test.d.ts.map +1 -0
  15. package/dist/__tests__/stamp-in-lock.test.js +102 -0
  16. package/dist/__tests__/stamp-in-lock.test.js.map +1 -0
  17. package/dist/__tests__/status-logic.test.d.ts +2 -0
  18. package/dist/__tests__/status-logic.test.d.ts.map +1 -0
  19. package/dist/__tests__/status-logic.test.js +74 -0
  20. package/dist/__tests__/status-logic.test.js.map +1 -0
  21. package/dist/__tests__/team-roster.test.d.ts +2 -0
  22. package/dist/__tests__/team-roster.test.d.ts.map +1 -0
  23. package/dist/__tests__/team-roster.test.js +97 -0
  24. package/dist/__tests__/team-roster.test.js.map +1 -0
  25. package/dist/ai/claude-provider.d.ts +13 -0
  26. package/dist/ai/claude-provider.d.ts.map +1 -0
  27. package/dist/ai/claude-provider.js +335 -0
  28. package/dist/ai/claude-provider.js.map +1 -0
  29. package/dist/ai/enhance-doc.d.ts +24 -0
  30. package/dist/ai/enhance-doc.d.ts.map +1 -0
  31. package/dist/ai/enhance-doc.js +272 -0
  32. package/dist/ai/enhance-doc.js.map +1 -0
  33. package/dist/ai/openai-provider.d.ts +13 -0
  34. package/dist/ai/openai-provider.d.ts.map +1 -0
  35. package/dist/ai/openai-provider.js +345 -0
  36. package/dist/ai/openai-provider.js.map +1 -0
  37. package/dist/ai/prompt-utils.d.ts +23 -0
  38. package/dist/ai/prompt-utils.d.ts.map +1 -0
  39. package/dist/ai/prompt-utils.js +67 -0
  40. package/dist/ai/prompt-utils.js.map +1 -0
  41. package/dist/commands/ai.d.ts +8 -0
  42. package/dist/commands/ai.d.ts.map +1 -0
  43. package/dist/commands/ai.js +576 -0
  44. package/dist/commands/ai.js.map +1 -0
  45. package/dist/commands/apply.d.ts +4 -0
  46. package/dist/commands/apply.d.ts.map +1 -0
  47. package/dist/commands/apply.js +98 -0
  48. package/dist/commands/apply.js.map +1 -0
  49. package/dist/commands/assign.d.ts +5 -0
  50. package/dist/commands/assign.d.ts.map +1 -0
  51. package/dist/commands/assign.js +180 -0
  52. package/dist/commands/assign.js.map +1 -0
  53. package/dist/commands/ci.d.ts +4 -0
  54. package/dist/commands/ci.d.ts.map +1 -0
  55. package/dist/commands/ci.js +84 -0
  56. package/dist/commands/ci.js.map +1 -0
  57. package/dist/commands/context.d.ts +19 -0
  58. package/dist/commands/context.d.ts.map +1 -0
  59. package/dist/commands/context.js +297 -0
  60. package/dist/commands/context.js.map +1 -0
  61. package/dist/commands/diff.d.ts +2 -0
  62. package/dist/commands/diff.d.ts.map +1 -0
  63. package/dist/commands/diff.js +119 -0
  64. package/dist/commands/diff.js.map +1 -0
  65. package/dist/commands/doctor.d.ts +5 -0
  66. package/dist/commands/doctor.d.ts.map +1 -0
  67. package/dist/commands/doctor.js +348 -0
  68. package/dist/commands/doctor.js.map +1 -0
  69. package/dist/commands/document-system.d.ts +5 -0
  70. package/dist/commands/document-system.d.ts.map +1 -0
  71. package/dist/commands/document-system.js +84 -0
  72. package/dist/commands/document-system.js.map +1 -0
  73. package/dist/commands/document.d.ts +6 -0
  74. package/dist/commands/document.d.ts.map +1 -0
  75. package/dist/commands/document.js +276 -0
  76. package/dist/commands/document.js.map +1 -0
  77. package/dist/commands/export.d.ts +11 -0
  78. package/dist/commands/export.d.ts.map +1 -0
  79. package/dist/commands/export.js +74 -0
  80. package/dist/commands/export.js.map +1 -0
  81. package/dist/commands/generate-components.d.ts +4 -0
  82. package/dist/commands/generate-components.d.ts.map +1 -0
  83. package/dist/commands/generate-components.js +62 -0
  84. package/dist/commands/generate-components.js.map +1 -0
  85. package/dist/commands/generate-composites.d.ts +2 -0
  86. package/dist/commands/generate-composites.d.ts.map +1 -0
  87. package/dist/commands/generate-composites.js +31 -0
  88. package/dist/commands/generate-composites.js.map +1 -0
  89. package/dist/commands/generate-tokens.d.ts +2 -0
  90. package/dist/commands/generate-tokens.d.ts.map +1 -0
  91. package/dist/commands/generate-tokens.js +48 -0
  92. package/dist/commands/generate-tokens.js.map +1 -0
  93. package/dist/commands/help-topics.d.ts +2 -0
  94. package/dist/commands/help-topics.d.ts.map +1 -0
  95. package/dist/commands/help-topics.js +324 -0
  96. package/dist/commands/help-topics.js.map +1 -0
  97. package/dist/commands/implement.d.ts +5 -0
  98. package/dist/commands/implement.d.ts.map +1 -0
  99. package/dist/commands/implement.js +595 -0
  100. package/dist/commands/implement.js.map +1 -0
  101. package/dist/commands/import-tokens.d.ts +2 -0
  102. package/dist/commands/import-tokens.d.ts.map +1 -0
  103. package/dist/commands/import-tokens.js +42 -0
  104. package/dist/commands/import-tokens.js.map +1 -0
  105. package/dist/commands/init.d.ts +6 -0
  106. package/dist/commands/init.d.ts.map +1 -0
  107. package/dist/commands/init.js +410 -0
  108. package/dist/commands/init.js.map +1 -0
  109. package/dist/commands/inspect-component.d.ts +2 -0
  110. package/dist/commands/inspect-component.d.ts.map +1 -0
  111. package/dist/commands/inspect-component.js +146 -0
  112. package/dist/commands/inspect-component.js.map +1 -0
  113. package/dist/commands/log.d.ts +4 -0
  114. package/dist/commands/log.d.ts.map +1 -0
  115. package/dist/commands/log.js +109 -0
  116. package/dist/commands/log.js.map +1 -0
  117. package/dist/commands/onboarding.d.ts +9 -0
  118. package/dist/commands/onboarding.d.ts.map +1 -0
  119. package/dist/commands/onboarding.js +63 -0
  120. package/dist/commands/onboarding.js.map +1 -0
  121. package/dist/commands/plan.d.ts +3 -0
  122. package/dist/commands/plan.d.ts.map +1 -0
  123. package/dist/commands/plan.js +108 -0
  124. package/dist/commands/plan.js.map +1 -0
  125. package/dist/commands/prompt.d.ts +5 -0
  126. package/dist/commands/prompt.d.ts.map +1 -0
  127. package/dist/commands/prompt.js +77 -0
  128. package/dist/commands/prompt.js.map +1 -0
  129. package/dist/commands/prune.d.ts +2 -0
  130. package/dist/commands/prune.d.ts.map +1 -0
  131. package/dist/commands/prune.js +95 -0
  132. package/dist/commands/prune.js.map +1 -0
  133. package/dist/commands/remove.d.ts +2 -0
  134. package/dist/commands/remove.d.ts.map +1 -0
  135. package/dist/commands/remove.js +76 -0
  136. package/dist/commands/remove.js.map +1 -0
  137. package/dist/commands/scaffold.d.ts +2 -0
  138. package/dist/commands/scaffold.d.ts.map +1 -0
  139. package/dist/commands/scaffold.js +47 -0
  140. package/dist/commands/scaffold.js.map +1 -0
  141. package/dist/commands/scan.d.ts +2 -0
  142. package/dist/commands/scan.d.ts.map +1 -0
  143. package/dist/commands/scan.js +91 -0
  144. package/dist/commands/scan.js.map +1 -0
  145. package/dist/commands/stamp.d.ts +11 -0
  146. package/dist/commands/stamp.d.ts.map +1 -0
  147. package/dist/commands/stamp.js +147 -0
  148. package/dist/commands/stamp.js.map +1 -0
  149. package/dist/commands/status.d.ts +7 -0
  150. package/dist/commands/status.d.ts.map +1 -0
  151. package/dist/commands/status.js +219 -0
  152. package/dist/commands/status.js.map +1 -0
  153. package/dist/commands/team.d.ts +7 -0
  154. package/dist/commands/team.d.ts.map +1 -0
  155. package/dist/commands/team.js +173 -0
  156. package/dist/commands/team.js.map +1 -0
  157. package/dist/index.d.ts +3 -0
  158. package/dist/index.d.ts.map +1 -0
  159. package/dist/index.js +303 -0
  160. package/dist/index.js.map +1 -0
  161. package/dist/onboarding/content.d.ts +39 -0
  162. package/dist/onboarding/content.d.ts.map +1 -0
  163. package/dist/onboarding/content.js +82 -0
  164. package/dist/onboarding/content.js.map +1 -0
  165. package/dist/utils/component-slug.d.ts +10 -0
  166. package/dist/utils/component-slug.d.ts.map +1 -0
  167. package/dist/utils/component-slug.js +13 -0
  168. package/dist/utils/component-slug.js.map +1 -0
  169. package/dist/utils/framework-registry.d.ts +41 -0
  170. package/dist/utils/framework-registry.d.ts.map +1 -0
  171. package/dist/utils/framework-registry.js +82 -0
  172. package/dist/utils/framework-registry.js.map +1 -0
  173. package/dist/utils/gitignore.d.ts +4 -0
  174. package/dist/utils/gitignore.d.ts.map +1 -0
  175. package/dist/utils/gitignore.js +67 -0
  176. package/dist/utils/gitignore.js.map +1 -0
  177. package/dist/utils/lock-changes.d.ts +14 -0
  178. package/dist/utils/lock-changes.d.ts.map +1 -0
  179. package/dist/utils/lock-changes.js +26 -0
  180. package/dist/utils/lock-changes.js.map +1 -0
  181. package/dist/utils/logger.d.ts +9 -0
  182. package/dist/utils/logger.d.ts.map +1 -0
  183. package/dist/utils/logger.js +32 -0
  184. package/dist/utils/logger.js.map +1 -0
  185. package/dist/utils/permissions.d.ts +17 -0
  186. package/dist/utils/permissions.d.ts.map +1 -0
  187. package/dist/utils/permissions.js +37 -0
  188. package/dist/utils/permissions.js.map +1 -0
  189. package/dist/utils/status-logic.d.ts +16 -0
  190. package/dist/utils/status-logic.d.ts.map +1 -0
  191. package/dist/utils/status-logic.js +32 -0
  192. package/dist/utils/status-logic.js.map +1 -0
  193. package/dist/utils/storybook-setup.d.ts +5 -0
  194. package/dist/utils/storybook-setup.d.ts.map +1 -0
  195. package/dist/utils/storybook-setup.js +104 -0
  196. package/dist/utils/storybook-setup.js.map +1 -0
  197. package/dist/utils/team-roster.d.ts +35 -0
  198. package/dist/utils/team-roster.d.ts.map +1 -0
  199. package/dist/utils/team-roster.js +99 -0
  200. package/dist/utils/team-roster.js.map +1 -0
  201. package/package.json +44 -0
@@ -0,0 +1,335 @@
1
+ import Anthropic from "@anthropic-ai/sdk";
2
+ import { calcMaxTokens, buildUserMessage, formatTokenUsage } from "./prompt-utils.js";
3
+ const SYSTEM_PROMPT = `You are a design system component implementation assistant working inside PTB (Calibrate).
4
+
5
+ You receive a structured design context document describing a component extracted directly from Figma. Your job is to implement the component files that bring this design to life in code.
6
+
7
+ The examples below use React/JSX syntax. If the context specifies a different framework, apply the same principles using that framework's equivalent patterns.
8
+
9
+ ## Rules
10
+
11
+ 1. Use the write_file tool for EVERY file you generate. Do not output prose or fenced code blocks — tool calls only.
12
+ 2. You MUST generate ALL FOUR of these files, no exceptions:
13
+ - <ComponentName>.<ext> — the component implementation
14
+ - <ComponentName>.types.ts — TypeScript prop types
15
+ - <ComponentName>.module.css — CSS module styles (generate an empty file if the component truly has no styles)
16
+ - index.ts — barrel export (always required, even if it is a single re-export line)
17
+ Before writing the last file, verify:
18
+ - [ ] The component file imports the Props type: \`import type { ComponentNameProps } from './ComponentName.types';\`
19
+ - [ ] Every \`[Class: X]\` annotation in the render structure is applied as a plain utility string (never a CSS module key)
20
+ - [ ] No \`display: none\` in CSS for elements already handled by a JS conditional in the template
21
+ - [ ] No fixed \`height: Npx\` on any element that wraps text content
22
+ - [ ] Dependency props match the \`Accepted props\` list in the context — no invented prop names, defaults match \`/* default: X */\` annotations
23
+ - [ ] Conditional rendering wraps ONLY the node at the specified path, not all instances of that component type
24
+ - [ ] Every prop in the Props Interface Skeleton is destructured in the function signature — no props silently dropped
25
+ 3. Implement ONLY what the design context specifies:
26
+ - Variant axes → prop union types (these are PROPS, not useState)
27
+ - Token bindings → CSS custom properties (use the resolved variable names from the context)
28
+ - State contract → conditional class logic driven by a prop or controlled state
29
+ - Interaction contract → event handler stubs
30
+ - Layout → flex/grid CSS matching direction, gap, padding from context
31
+ - Size → CSS classes, never inline style={{ width, height }}
32
+ 4. Do NOT invent business logic, API calls, or application state.
33
+ 5. Do NOT add features absent from the design context.
34
+ 6. Follow the framework and naming conventions specified in the prompt.
35
+ 7. Never reference hardcoded colour values — always use the CSS custom properties from the token bindings.
36
+
37
+ ## Anti-patterns — never do these
38
+
39
+ **1. Variant axes are props, not state:**
40
+ \`\`\`tsx
41
+ // WRONG — variant axes from the design context are never local state
42
+ const [variant, setVariant] = useState<'primary' | 'secondary'>('primary');
43
+ // RIGHT — receive as a prop with the Figma default as the default value
44
+ function Component({ variant = 'primary' }: ComponentProps) { ... }
45
+ \`\`\`
46
+
47
+ **2. CSS modules must be imported as an object, not as a side-effect:**
48
+ \`\`\`tsx
49
+ // WRONG — side-effect import; className string has no scoping
50
+ import './Component.module.css';
51
+ className="root"
52
+ // RIGHT — named import gives you the scoped class map
53
+ import styles from './Component.module.css';
54
+ className={styles.root}
55
+ \`\`\`
56
+
57
+ **3. Import every component you render — never use an undeclared identifier:**
58
+ \`\`\`tsx
59
+ // WRONG — renders <SubComponent /> without importing it; runtime error
60
+ // RIGHT
61
+ import { SubComponent } from '../sub-component/index.js';
62
+ \`\`\`
63
+
64
+ **4. Never inline pixel dimensions from the context — put them in CSS:**
65
+ \`\`\`tsx
66
+ // WRONG — inline styles bypass the CSS module and are hard to override
67
+ <div style={{ width: 320, height: 48 }}>
68
+ // RIGHT — dimensions belong in the CSS module
69
+ .root { width: 320px; height: 48px; }
70
+ \`\`\`
71
+
72
+ **5. Never pass a Figma metadata object as a prop:**
73
+ \`\`\`tsx
74
+ // WRONG — slot values in the context are design descriptions, not runtime values
75
+ <Component iconSlot={{ kind: 'unknown', componentId: '123:456' }} />
76
+ // RIGHT — render the actual resolved component in JSX
77
+ <IconComponent />
78
+ \`\`\`
79
+
80
+ **6. Pass sub-component dependencies as named slot props, not as children:**
81
+ \`\`\`tsx
82
+ // WRONG — passing as children only works if the component explicitly renders {children}
83
+ <ParentComponent><IconComponent /></ParentComponent>
84
+ // RIGHT — use the named slot prop defined in the Slot Contract
85
+ <ParentComponent icon={<IconComponent />} />
86
+ \`\`\`
87
+
88
+ **7. Never use heading tags (h1–h6) for non-heading content:**
89
+ \`\`\`tsx
90
+ // WRONG — labels, captions, and timestamps are not document headings
91
+ <h1>{label}</h1>
92
+ // RIGHT — use the semantically appropriate inline or block element
93
+ <span className={styles.label}>{label}</span>
94
+ <time className={styles.timestamp}>{timestamp}</time>
95
+ \`\`\`
96
+
97
+ **8. All props that have a Figma default must have a default value in code:**
98
+ \`\`\`tsx
99
+ // WRONG — prop with no default silently breaks the component when omitted
100
+ function Component({ label, value }: ComponentProps) { ... }
101
+ // RIGHT — mirror the Figma default so the component renders correctly in isolation
102
+ function Component({ label = 'Default label', value = '' }: ComponentProps) { ... }
103
+ \`\`\`
104
+
105
+ **9. Never use local state for anything driven by the design context:**
106
+ \`\`\`tsx
107
+ // WRONG — design-system variant axes are never local state
108
+ const [variant, setVariant] = useState('primary');
109
+ // WRONG — inventing a boolean flag for a slot that should be a ReactNode
110
+ function Component({ showIcon = false }: ComponentProps) { ... }
111
+ // RIGHT — receive variant axes and slot props directly; derive everything from props
112
+ function Component({ variant = 'primary', icon }: ComponentProps) { ... }
113
+ \`\`\`
114
+ Slot props (icons, sub-components) are ALWAYS \`ReactNode\` — never \`boolean\`.
115
+
116
+ **10. Never set a fixed height on a text or content container:**
117
+ \`\`\`css
118
+ /* WRONG — clips content when text reflows on the web */
119
+ .content { height: 80px; }
120
+ /* RIGHT — let the container grow with its content */
121
+ .content { min-height: 1.5em; } /* or omit height entirely */
122
+ \`\`\`
123
+ Figma fixes containers to their current content height. On the web, text reflows freely.
124
+ Use \`min-height\` or no height for any element that wraps text. Only apply a fixed \`height\`
125
+ to elements with a truly fixed visual footprint (icons, avatars, dividers, separators).
126
+
127
+ **11. A slot prop IS the element to render — never use its presence to select a hardcoded fallback:**
128
+ \`\`\`tsx
129
+ // WRONG — prop holds a ReactNode; treating it as a boolean selects a hardcoded component
130
+ const rendered = icon ? <DefaultIcon /> : null;
131
+ // RIGHT — render whatever was passed in
132
+ {icon}
133
+ // RIGHT — use the design default only as a fallback when nothing is passed
134
+ {icon ?? <DefaultIcon />}
135
+ \`\`\`
136
+ A slot prop named \`icon?: React.ReactNode\` is the element itself. The named component in the
137
+ context is the design tool's placeholder — use it as the \`??\` fallback, not the primary render.
138
+
139
+ **12. Never concatenate className with template literals — use a filtered join:**
140
+ \`\`\`tsx
141
+ // WRONG — produces "root undefined" when the optional className prop is not passed
142
+ className={\`\${styles.root} \${className}\`}
143
+ // RIGHT — filter removes falsy values before joining
144
+ className={[styles.root, className].filter(Boolean).join(' ')}
145
+ \`\`\`
146
+
147
+ **13. Never build dynamic class names from variant values — use data attributes:**
148
+ \`\`\`tsx
149
+ // WRONG — generates class names like "size-sm-status-active" that don't exist in the CSS module
150
+ const cls = \`size-\${size}-status-\${status}\`;
151
+ <div className={styles[cls]}>
152
+ // RIGHT — the CSS skeleton uses [data-*] attribute selectors; wire props to data attributes
153
+ <div
154
+ className={styles.root}
155
+ data-size={size}
156
+ data-status={status}
157
+ >
158
+ \`\`\`
159
+ The CSS skeleton already has \`.root[data-size="sm"] { ... }\` — connect props via \`data-*\`, never via dynamic class names.
160
+
161
+ **14. Always import the component's Props type from its .types file:**
162
+ \`\`\`tsx
163
+ // WRONG — type identifier is used but not imported → TypeScript error
164
+ const MyComponent: React.FC<MyComponentProps> = ...
165
+ // RIGHT
166
+ import type { MyComponentProps } from './MyComponent.types';
167
+ const MyComponent: React.FC<MyComponentProps> = ...
168
+ \`\`\`
169
+ Every component has a \`<ComponentName>.types.ts\` file. Always import the Props type from it.
170
+
171
+ **15. A CSS module key lookup must contain exactly one key — never two class names in one string:**
172
+ \`\`\`tsx
173
+ // WRONG — looks up a single key with a space in it; always resolves to undefined
174
+ className={styles['element-name utility-class']}
175
+ // RIGHT — look up the module key, then join utility classes separately as plain strings
176
+ className={[styles['element-name'], 'utility-class'].filter(Boolean).join(' ')}
177
+ \`\`\`
178
+ \`styles[key]\` is a single object property lookup. A space-separated string is one key, not two classes.
179
+
180
+ **16. CSS module keys containing a hyphen MUST use bracket notation — dot notation is a syntax error:**
181
+ \`\`\`tsx
182
+ // WRONG — "list-item" parses as "styles.list" minus "item" — JavaScript subtraction syntax error
183
+ className={styles.list-item}
184
+ // RIGHT — any key that is not a valid JS identifier requires bracket notation
185
+ className={styles['list-item']}
186
+ \`\`\`
187
+ Any CSS module key with a \`-\`, digit start, or reserved word must use \`styles['key']\`.
188
+
189
+ **17. A ReactNode slot prop is already an element — render it directly, never invoke it as a component:**
190
+ \`\`\`tsx
191
+ // WRONG — variable name in lowercase JSX is treated as a DOM element tag, not a component
192
+ {icon && <icon />}
193
+ // WRONG — the variable holds a ReactNode, not a constructor; calling it as a component is an error
194
+ {icon && <Icon />}
195
+ // RIGHT — a ReactNode renders as-is; undefined or null renders nothing
196
+ {icon}
197
+ \`\`\`
198
+ If the slot is optional, \`{prop}\` is the complete render expression — no boolean guard, no JSX invocation.
199
+ Never invent a paired \`showX: boolean\` alongside \`x: ReactNode\`. The presence or absence of the node IS the visibility control.
200
+
201
+ **18. Render structure \`[Class: X]\` tags are global utility classes — apply them as plain strings alongside the module class:**
202
+ \`\`\`tsx
203
+ // Context render structure: "Label node [Class: type-body-sm]"
204
+ // WRONG — drops the typography utility class entirely
205
+ <span className={styles['label']}>{text}</span>
206
+ // WRONG — tries to look up the utility class as a module key; always undefined
207
+ <span className={styles['label type-body-sm']}>{text}</span>
208
+ // RIGHT — module class handles component-specific styles; utility class handles typography
209
+ <span className={[styles['label'], 'type-body-sm'].filter(Boolean).join(' ')}>{text}</span>
210
+ \`\`\`
211
+ \`[Class: X]\` in the render structure is a global utility class (e.g. from \`typography.css\`). It is NOT a CSS module key. Always apply it as a plain string entry in the class array.
212
+
213
+ **19. Nodes marked \`visible: false\` in a variant diff must be conditionally removed from the DOM:**
214
+ \`\`\`tsx
215
+ // Context variant diff: "sidebar node — visible: true → false in state=collapsed"
216
+ // WRONG — CSS display:none hides visually but the node is still in the DOM and still runs
217
+ <div className={styles.layout}>
218
+ <Sidebar />
219
+ </div>
220
+ // RIGHT — use a JS conditional so the node does not render at all in that state
221
+ <div className={styles.layout}>
222
+ {status !== 'collapsed' && <Sidebar />}
223
+ </div>
224
+ \`\`\`
225
+ When the variant diff shows \`visible: true → false\` for a node in a given state, use \`&&\` or a ternary to remove it entirely — do not rely only on CSS.
226
+
227
+ **20. When one of several instances of the same dependency is conditionally hidden, wrap ONLY that instance:**
228
+ \`\`\`tsx
229
+ // Context: two SubComponent instances — one always visible, one hidden in state=secondary
230
+ // WRONG — wraps both; nothing renders in 'secondary' state
231
+ {variant !== 'secondary' && <SubComponent type="icon" />}
232
+ {variant !== 'secondary' && <SubComponent label="Open" />}
233
+ // RIGHT — the Conditional Rendering Guide names the hidden SLOT (e.g. "cta");
234
+ // cross-reference the Slot Render Guide to find which specific instance it maps to
235
+ <SubComponent type="icon" /> {/* always rendered */}
236
+ {variant !== 'secondary' && <SubComponent label="Open" />} {/* 'cta' slot — hidden in secondary */}
237
+ \`\`\`
238
+ The Conditional Rendering Guide names SLOTS (e.g. \`/* hide slot: cta */\`), not component types.
239
+ Look up that slot in the Slot Render Guide to identify exactly which instance to wrap.
240
+ All other instances of the same component that are NOT named remain always-rendered.
241
+
242
+ **21. Always use named exports — never default exports:**
243
+ \`\`\`tsx
244
+ // WRONG — default exports break named imports used by every consumer of this component
245
+ export default function Component({ ... }: ComponentProps) { ... }
246
+ export default Component;
247
+
248
+ // RIGHT — named export so every import can use { Component }
249
+ export function Component({ ... }: ComponentProps) { ... }
250
+ // OR
251
+ export const Component: React.FC<ComponentProps> = ({ ... }) => { ... };
252
+ \`\`\`
253
+ The \`index.ts\` barrel must also re-export named:
254
+ \`\`\`ts
255
+ // WRONG
256
+ export { default } from './Component.js';
257
+ // RIGHT
258
+ export { Component } from './Component.js';
259
+ \`\`\`
260
+
261
+ **22. \`data-state\` only exists on the root container — child overrides must use descendant selectors:**
262
+ \`\`\`css
263
+ /* WRONG — data-state is not on .sidebar; this selector never matches */
264
+ .sidebar[data-state="collapsed"] { width: 0; }
265
+
266
+ /* RIGHT — data-state lives on .container; use descendant selector */
267
+ .container[data-state="collapsed"] .sidebar { width: 0; }
268
+ \`\`\`
269
+ Every state/variant attribute is set on the root element only. Any CSS overrides for child elements
270
+ in a given state must be written as \`.container[data-X="Y"] .child\`, never \`.child[data-X="Y"]\`.
271
+ The CSS skeleton already shows the correct descendant-selector form — follow it exactly.`;
272
+ const WRITE_FILE_TOOL = {
273
+ name: "write_file",
274
+ description: "Write a generated implementation file for the component. Call this once per file.",
275
+ input_schema: {
276
+ type: "object",
277
+ properties: {
278
+ path: {
279
+ type: "string",
280
+ description: "File path relative to the component folder, e.g. Button.tsx or Button.module.css"
281
+ },
282
+ content: {
283
+ type: "string",
284
+ description: "Full file content — no PTB_METADATA header needed, PTB adds that automatically"
285
+ }
286
+ },
287
+ required: ["path", "content"]
288
+ }
289
+ };
290
+ export class ClaudeProvider {
291
+ name = "Claude (Anthropic)";
292
+ client;
293
+ model;
294
+ constructor(apiKey, model = "claude-sonnet-4-6") {
295
+ this.client = new Anthropic({ apiKey });
296
+ this.model = model;
297
+ }
298
+ async implementComponent(params) {
299
+ const { componentName, framework, promptPackage } = params;
300
+ const response = await this.client.messages.create({
301
+ model: this.model,
302
+ max_tokens: calcMaxTokens(promptPackage),
303
+ // System prompt passed as a content block so Anthropic can cache it.
304
+ // The prompt never changes between calls — cached after the first use.
305
+ system: [{
306
+ type: "text",
307
+ text: SYSTEM_PROMPT,
308
+ cache_control: { type: "ephemeral" }
309
+ }],
310
+ tools: [WRITE_FILE_TOOL],
311
+ tool_choice: { type: "auto" },
312
+ messages: [{
313
+ role: "user",
314
+ content: buildUserMessage(promptPackage, componentName, framework)
315
+ }]
316
+ });
317
+ const usage = response.usage;
318
+ console.log(formatTokenUsage(usage.input_tokens, usage.output_tokens, usage.cache_read_input_tokens ?? 0));
319
+ const files = [];
320
+ for (const block of response.content) {
321
+ if (block.type === "tool_use" && block.name === "write_file") {
322
+ const input = block.input;
323
+ if (input.path && input.content !== undefined) {
324
+ files.push({ path: input.path, content: input.content });
325
+ }
326
+ }
327
+ }
328
+ if (files.length === 0) {
329
+ throw new Error(`Claude returned no files for "${componentName}". ` +
330
+ `Stop reason: ${response.stop_reason}. Check your API key and model access.`);
331
+ }
332
+ return { files };
333
+ }
334
+ }
335
+ //# sourceMappingURL=claude-provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-provider.js","sourceRoot":"","sources":["../../src/ai/claude-provider.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ import { z } from "zod";
2
+ import type { PTBConfig } from "@calibrate-ds/shared-types";
3
+ import type { ComponentDocPackage } from "@calibrate-ds/core";
4
+ export type DocEnhancement = {
5
+ filledMdx: string;
6
+ };
7
+ export declare function enhanceDocWithAI(config: PTBConfig, docPackage: ComponentDocPackage): Promise<DocEnhancement>;
8
+ declare const IntentEntrySchema: z.ZodObject<{
9
+ intent: z.ZodString;
10
+ component: z.ZodString;
11
+ note: z.ZodOptional<z.ZodString>;
12
+ }, z.core.$strip>;
13
+ export type IntentEntry = z.infer<typeof IntentEntrySchema>;
14
+ export declare function generateIntentMapWithAI(config: PTBConfig, componentNames: string[]): Promise<IntentEntry[]>;
15
+ declare const ExampleStorySchema: z.ZodObject<{
16
+ name: z.ZodString;
17
+ title: z.ZodString;
18
+ args: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
19
+ description: z.ZodDefault<z.ZodString>;
20
+ }, z.core.$strip>;
21
+ export type ExampleStory = z.infer<typeof ExampleStorySchema>;
22
+ export declare function generateExampleStoriesWithAI(config: PTBConfig, docPackage: ComponentDocPackage): Promise<ExampleStory[]>;
23
+ export {};
24
+ //# sourceMappingURL=enhance-doc.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"enhance-doc.d.ts","sourceRoot":"","sources":["../../src/ai/enhance-doc.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAgJ9D,MAAM,MAAM,cAAc,GAAG;IAAE,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC;AAEnD,wBAAsB,gBAAgB,CAClC,MAAM,EAAE,SAAS,EACjB,UAAU,EAAE,mBAAmB,GAChC,OAAO,CAAC,cAAc,CAAC,CAsBzB;AAkBD,QAAA,MAAM,iBAAiB;;;;iBAIrB,CAAC;AACH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAE5D,wBAAsB,uBAAuB,CACzC,MAAM,EAAE,SAAS,EACjB,cAAc,EAAE,MAAM,EAAE,GACzB,OAAO,CAAC,WAAW,EAAE,CAAC,CAgBxB;AAyBD,QAAA,MAAM,kBAAkB;;;;;iBAKtB,CAAC;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AA2B9D,wBAAsB,4BAA4B,CAC9C,MAAM,EAAE,SAAS,EACjB,UAAU,EAAE,mBAAmB,GAChC,OAAO,CAAC,YAAY,EAAE,CAAC,CA2CzB"}
@@ -0,0 +1,272 @@
1
+ import { z } from "zod";
2
+ function resolveClient(config) {
3
+ const rawAI = config.ai;
4
+ if (!rawAI)
5
+ return null;
6
+ const providerName = rawAI.active?.toLowerCase();
7
+ const providerEntry = rawAI.providers?.[providerName] ?? {};
8
+ if (!providerName || !providerEntry.accessTokenEnv)
9
+ return null;
10
+ const apiKey = process.env[providerEntry.accessTokenEnv];
11
+ if (!apiKey)
12
+ return null;
13
+ if (providerName === "claude") {
14
+ return {
15
+ complete: async (system, user, maxTokens) => {
16
+ const Anthropic = (await import("@anthropic-ai/sdk")).default;
17
+ const client = new Anthropic({ apiKey });
18
+ const response = await client.messages.create({
19
+ model: providerEntry.model ?? "claude-haiku-4-5-20251001",
20
+ max_tokens: maxTokens,
21
+ system,
22
+ messages: [{ role: "user", content: user }],
23
+ });
24
+ const block = response.content.find((b) => b.type === "text");
25
+ return block?.text ?? "";
26
+ },
27
+ };
28
+ }
29
+ if (providerName === "openai") {
30
+ return {
31
+ complete: async (system, user, maxTokens) => {
32
+ const OpenAI = (await import("openai")).default;
33
+ const client = new OpenAI({ apiKey });
34
+ const model = providerEntry.model ?? "gpt-4o-mini";
35
+ const tokenParam = /^(gpt-5|o1|o3|o4)/.test(model)
36
+ ? { max_completion_tokens: maxTokens }
37
+ : { max_tokens: maxTokens };
38
+ const response = await client.chat.completions.create({
39
+ model,
40
+ ...tokenParam,
41
+ messages: [
42
+ { role: "system", content: system },
43
+ { role: "user", content: user },
44
+ ],
45
+ });
46
+ return response.choices[0]?.message?.content ?? "";
47
+ },
48
+ };
49
+ }
50
+ return null;
51
+ }
52
+ // ── Prose enhancement ─────────────────────────────────────────────────────────
53
+ const PROSE_SYSTEM = `You are a design system documentation writer. You receive a structured summary of a UI component extracted from Figma and return ONLY a JSON object with prose documentation — nothing else.
54
+
55
+ Return this exact JSON shape:
56
+ {
57
+ "description": "1-2 sentence description of what this component is and when to use it",
58
+ "usageExample": "a realistic TSX code snippet as a plain string (no markdown fences)",
59
+ "guidelines": {
60
+ "do": ["short imperative bullet", "..."],
61
+ "dont": ["short imperative bullet", "..."]
62
+ },
63
+ "accessibility": ["ARIA role or keyboard note", "..."]
64
+ }
65
+
66
+ Rules:
67
+ - Use only prop names, variant values, and states from the summary — never invent new ones
68
+ - usageExample must be valid TSX (no imports, just the JSX)
69
+ - Do NOT wrap the component in native HTML elements (button, div, span, label) — use it directly as <ComponentName props... />
70
+ - 2-3 items in do/dont, 2-4 items in accessibility
71
+ - Language is concise and technical — audience is developers`;
72
+ const ProseResultSchema = z.object({
73
+ description: z.string().default(""),
74
+ usageExample: z.string().default(""),
75
+ guidelines: z.object({
76
+ do: z.array(z.string()).default([]),
77
+ dont: z.array(z.string()).default([]),
78
+ }).default({ do: [], dont: [] }),
79
+ accessibility: z.array(z.string()).default([]),
80
+ });
81
+ function buildProseUserMessage(pkg) {
82
+ const s = pkg.contextSummary;
83
+ const parts = [`Component: ${pkg.componentName}`];
84
+ if (s.kind)
85
+ parts.push(`Kind: ${s.kind}`);
86
+ if (s.description)
87
+ parts.push(`Figma description: ${s.description}`);
88
+ if (s.props.length) {
89
+ parts.push(`Props:\n${s.props.map(p => p.options ? ` - ${p.name}: ${p.options.join(" | ")}` : ` - ${p.name}: ${p.type}`).join("\n")}`);
90
+ }
91
+ if (s.states?.length)
92
+ parts.push(`States: ${s.states.join(", ")}`);
93
+ if (s.slots?.length)
94
+ parts.push(`Slot toggles (boolean props): ${s.slots.join(", ")}`);
95
+ if (s.dependencies?.length)
96
+ parts.push(`Uses: ${s.dependencies.join(", ")}`);
97
+ if (s.hasInteractions)
98
+ parts.push(`Has prototype interactions.`);
99
+ return parts.join("\n");
100
+ }
101
+ function injectProse(mdx, prose) {
102
+ let result = mdx;
103
+ if (prose.description) {
104
+ result = result.replace("<!-- AI_DESCRIPTION -->", prose.description);
105
+ }
106
+ if (prose.usageExample) {
107
+ const usageBlock = ["```tsx", prose.usageExample.trim(), "```"].join("\n");
108
+ result = result.replace("<!-- AI_USAGE_EXAMPLE -->", usageBlock);
109
+ }
110
+ const doItems = prose.guidelines?.do ?? [];
111
+ const dontItems = prose.guidelines?.dont ?? [];
112
+ if (doItems.length > 0 || dontItems.length > 0) {
113
+ const guidelinesBlock = [
114
+ "**Do**",
115
+ ...doItems.map(g => `- ${g}`),
116
+ "",
117
+ "**Don't**",
118
+ ...dontItems.map(g => `- ${g}`),
119
+ ].join("\n");
120
+ result = result.replace("<!-- AI_GUIDELINES -->", guidelinesBlock);
121
+ }
122
+ const a11yItems = prose.accessibility ?? [];
123
+ if (a11yItems.length > 0) {
124
+ result = result.replace("<!-- AI_ACCESSIBILITY -->", a11yItems.map(a => `- ${a}`).join("\n"));
125
+ }
126
+ return result;
127
+ }
128
+ export async function enhanceDocWithAI(config, docPackage) {
129
+ const client = resolveClient(config);
130
+ if (!client)
131
+ return { filledMdx: docPackage.deterministicMdx };
132
+ try {
133
+ const raw = await client.complete(PROSE_SYSTEM, buildProseUserMessage(docPackage), 2048);
134
+ const jsonStart = raw.indexOf("{");
135
+ const jsonEnd = raw.lastIndexOf("}");
136
+ if (jsonStart === -1 || jsonEnd === -1)
137
+ throw new Error("No JSON in response");
138
+ const prose = ProseResultSchema.parse(JSON.parse(raw.slice(jsonStart, jsonEnd + 1)));
139
+ return { filledMdx: injectProse(docPackage.deterministicMdx, prose) };
140
+ }
141
+ catch (err) {
142
+ console.warn(` \x1b[33m⚠\x1b[0m AI doc enhancement failed: ${err.message ?? err}`);
143
+ return { filledMdx: docPackage.deterministicMdx };
144
+ }
145
+ }
146
+ // ── Intent map enhancement ────────────────────────────────────────────────────
147
+ const INTENT_SYSTEM = `You are a design system documentation writer. You receive a list of UI components and return ONLY a JSON array mapping user intents to components — nothing else.
148
+
149
+ Return this exact JSON shape:
150
+ [
151
+ { "intent": "user needs to submit a form", "component": "Button", "note": "use variant=primary" },
152
+ ...
153
+ ]
154
+
155
+ Rules:
156
+ - Cover 15-25 common UI intents
157
+ - Be specific about props/variants where helpful
158
+ - Intents should read naturally: "user needs to X" or "display a Y"
159
+ - Only use component names from the provided list`;
160
+ const IntentEntrySchema = z.object({
161
+ intent: z.string(),
162
+ component: z.string(),
163
+ note: z.string().optional(),
164
+ });
165
+ export async function generateIntentMapWithAI(config, componentNames) {
166
+ const client = resolveClient(config);
167
+ if (!client)
168
+ return [];
169
+ const user = `Component list:\n${componentNames.map(n => `- ${n}`).join("\n")}`;
170
+ try {
171
+ const raw = await client.complete(INTENT_SYSTEM, user, 1500);
172
+ const arrStart = raw.indexOf("[");
173
+ const arrEnd = raw.lastIndexOf("]");
174
+ if (arrStart === -1 || arrEnd === -1)
175
+ throw new Error("No JSON array in response");
176
+ return z.array(IntentEntrySchema).parse(JSON.parse(raw.slice(arrStart, arrEnd + 1)));
177
+ }
178
+ catch (err) {
179
+ console.warn(` \x1b[33m⚠\x1b[0m AI intent map failed: ${err.message ?? err}`);
180
+ return [];
181
+ }
182
+ }
183
+ // ── Example stories generation ────────────────────────────────────────────────
184
+ const STORIES_SYSTEM = `You are a React component developer writing Storybook stories for a design system. You receive a component summary and return ONLY a JSON array of story scenarios — nothing else.
185
+
186
+ Return this exact JSON shape:
187
+ [
188
+ {
189
+ "name": "StoryExportName",
190
+ "title": "Human readable label",
191
+ "args": { "propName": "value" },
192
+ "description": "one sentence explaining this scenario"
193
+ }
194
+ ]
195
+
196
+ Rules:
197
+ - 3-5 scenarios that represent real-world usage (not just variant permutations)
198
+ - name must be valid PascalCase JavaScript identifier
199
+ - CRITICAL: args keys MUST be copied character-for-character from the "Valid prop names" list in the summary. Every character matters — do NOT invent, abbreviate, prefix, or expand any prop name. If "showIcon" is not in the list, you cannot use it.
200
+ - For enum props, only use values listed for that prop. For boolean props, use true/false.
201
+ - Focus on: realistic content, common compositions, edge cases (long text, empty state, error state)
202
+ - Do NOT generate stories for every variant — those are already generated
203
+ - If the component has no props, return an empty array []`;
204
+ const ExampleStorySchema = z.object({
205
+ name: z.string(),
206
+ title: z.string(),
207
+ args: z.record(z.string(), z.unknown()).default({}),
208
+ description: z.string().default(""),
209
+ });
210
+ function buildStoriesUserMessage(pkg) {
211
+ const s = pkg.contextSummary;
212
+ const parts = [`Component: ${pkg.componentName}`];
213
+ if (s.props.length > 0) {
214
+ const validNames = s.props.map(p => `"${p.name}"`).join(", ");
215
+ parts.push(`Valid prop names (ONLY these may appear as args keys): ${validNames}`);
216
+ parts.push(`Props detail:`);
217
+ for (const p of s.props) {
218
+ if (p.options) {
219
+ parts.push(` - ${p.name}: enum — valid values: ${p.options.join(" | ")}`);
220
+ }
221
+ else {
222
+ parts.push(` - ${p.name}: ${p.type}`);
223
+ }
224
+ }
225
+ }
226
+ else {
227
+ parts.push(`Valid prop names: none — return empty array []`);
228
+ }
229
+ if (s.states?.length)
230
+ parts.push(`States: ${s.states.join(", ")}`);
231
+ if (s.description)
232
+ parts.push(`Figma description: ${s.description}`);
233
+ if (s.dependencies?.length)
234
+ parts.push(`Uses: ${s.dependencies.join(", ")}`);
235
+ return parts.join("\n");
236
+ }
237
+ export async function generateExampleStoriesWithAI(config, docPackage) {
238
+ const meaningfulProps = docPackage.contextSummary.props.filter(p => p.type !== "instance");
239
+ if (meaningfulProps.length === 0) {
240
+ console.warn(` \x1b[33m⚠\x1b[0m AI stories skipped: ${docPackage.componentName} has no non-instance props — nothing to generate stories for`);
241
+ return [];
242
+ }
243
+ const client = resolveClient(config);
244
+ if (!client) {
245
+ const providerName = config.ai?.active ?? "unknown";
246
+ const envVar = config.ai?.providers?.[providerName]?.accessTokenEnv;
247
+ const reason = !config.ai
248
+ ? "no ai config in ptb.config.json"
249
+ : !envVar
250
+ ? `provider '${providerName}' has no accessTokenEnv set`
251
+ : `env var '${envVar}' is not set`;
252
+ console.warn(` \x1b[33m⚠\x1b[0m AI stories skipped: ${reason}`);
253
+ return [];
254
+ }
255
+ try {
256
+ const raw = await client.complete(STORIES_SYSTEM, buildStoriesUserMessage(docPackage), 1024);
257
+ const arrStart = raw.indexOf("[");
258
+ const arrEnd = raw.lastIndexOf("]");
259
+ if (arrStart === -1 || arrEnd === -1)
260
+ throw new Error("No JSON array in response");
261
+ const stories = z.array(ExampleStorySchema).parse(JSON.parse(raw.slice(arrStart, arrEnd + 1)));
262
+ if (stories.length === 0) {
263
+ console.warn(` \x1b[33m⚠\x1b[0m AI stories skipped: model returned empty array for ${docPackage.componentName}`);
264
+ }
265
+ return stories;
266
+ }
267
+ catch (err) {
268
+ console.warn(` \x1b[33m⚠\x1b[0m AI stories generation failed: ${err.message ?? err}`);
269
+ return [];
270
+ }
271
+ }
272
+ //# sourceMappingURL=enhance-doc.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"enhance-doc.js","sourceRoot":"","sources":["../../src/ai/enhance-doc.ts"],"names":[],"mappings":"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"}