@constela/ai 1.0.2 → 2.0.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 (2) hide show
  1. package/README.md +340 -0
  2. package/package.json +2 -2
package/README.md ADDED
@@ -0,0 +1,340 @@
1
+ # @constela/ai
2
+
3
+ AI-powered DSL generation for Constela. Generate UI components and views from natural language prompts.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @constela/ai
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ Generate a component from a natural language description:
14
+
15
+ ```typescript
16
+ import { createDslGenerator } from '@constela/ai';
17
+
18
+ const generator = createDslGenerator({
19
+ provider: 'anthropic', // or 'openai'
20
+ });
21
+
22
+ const result = await generator.generate({
23
+ prompt: 'Create a card component with title, description, and action button',
24
+ output: 'component',
25
+ });
26
+
27
+ console.log(result.dsl);
28
+ // {
29
+ // "kind": "element",
30
+ // "tag": "div",
31
+ // "props": { "class": "card" },
32
+ // "children": [...]
33
+ // }
34
+ ```
35
+
36
+ ## Environment Variables
37
+
38
+ Set your API key:
39
+
40
+ ```bash
41
+ # For Anthropic (Claude)
42
+ export ANTHROPIC_API_KEY=sk-ant-...
43
+
44
+ # For OpenAI
45
+ export OPENAI_API_KEY=sk-...
46
+ ```
47
+
48
+ ## Features
49
+
50
+ ### AI Providers
51
+
52
+ Two providers are supported:
53
+
54
+ | Provider | Model | Environment Variable |
55
+ |----------|-------|---------------------|
56
+ | Anthropic | Claude Sonnet | `ANTHROPIC_API_KEY` |
57
+ | OpenAI | GPT-4o | `OPENAI_API_KEY` |
58
+
59
+ ```typescript
60
+ // Use Anthropic
61
+ const generator = createDslGenerator({ provider: 'anthropic' });
62
+
63
+ // Use OpenAI
64
+ const generator = createDslGenerator({ provider: 'openai' });
65
+ ```
66
+
67
+ ### Output Types
68
+
69
+ Generate different types of DSL:
70
+
71
+ ```typescript
72
+ // Generate a reusable component
73
+ const component = await generator.generate({
74
+ prompt: 'A notification badge with count',
75
+ output: 'component',
76
+ });
77
+
78
+ // Generate a full page/view
79
+ const view = await generator.generate({
80
+ prompt: 'A user profile page with avatar, bio, and recent posts',
81
+ output: 'view',
82
+ });
83
+ ```
84
+
85
+ ### Security Validation
86
+
87
+ All generated DSL is automatically validated:
88
+
89
+ **Forbidden Tags** (blocked by default):
90
+ - `script`, `iframe`, `object`, `embed`, `form`
91
+
92
+ **Forbidden Actions** (cannot be used even with whitelist):
93
+ - `import`, `call`, `dom`
94
+
95
+ **Restricted Actions** (require explicit whitelist):
96
+ - `fetch`
97
+
98
+ **URL Validation**:
99
+ - Blocks `javascript:`, `data:`, `vbscript:` schemes
100
+ - Supports domain whitelisting
101
+
102
+ ```typescript
103
+ const generator = createDslGenerator({
104
+ provider: 'anthropic',
105
+ security: {
106
+ allowedTags: ['a', 'button', 'input'],
107
+ allowedActions: ['set', 'update', 'navigate'],
108
+ allowedUrlPatterns: ['https://api.example.com/*'],
109
+ maxNestingDepth: 32,
110
+ },
111
+ });
112
+ ```
113
+
114
+ ### Generation Context
115
+
116
+ Provide context for more accurate generation:
117
+
118
+ ```typescript
119
+ const generator = createDslGenerator({
120
+ provider: 'anthropic',
121
+ context: {
122
+ existingComponents: ['Button', 'Card', 'Input'],
123
+ theme: { primaryColor: '#3b82f6' },
124
+ schema: { user: { name: 'string', email: 'string' } },
125
+ },
126
+ });
127
+ ```
128
+
129
+ ## CLI: Suggest Command
130
+
131
+ Analyze DSL files for improvements:
132
+
133
+ ```bash
134
+ # Analyze for accessibility issues
135
+ constela suggest app.json --aspect accessibility
136
+
137
+ # Analyze for performance
138
+ constela suggest app.json --aspect performance
139
+
140
+ # Analyze for security
141
+ constela suggest app.json --aspect security
142
+
143
+ # Analyze for UX
144
+ constela suggest app.json --aspect ux
145
+
146
+ # Use OpenAI instead of Anthropic
147
+ constela suggest app.json --aspect accessibility --provider openai
148
+
149
+ # Output as JSON
150
+ constela suggest app.json --aspect ux --json
151
+ ```
152
+
153
+ Example output:
154
+
155
+ ```
156
+ === Suggestions for app.json (accessibility) ===
157
+
158
+ [HIGH] Missing aria-label on button
159
+ Recommendation: Add aria-label="Submit form" to the button element
160
+ Location: view.children[0].props
161
+
162
+ [MED] Low color contrast in text
163
+ Recommendation: Increase contrast ratio to meet WCAG AA standards
164
+ Location: view.children[2].props.style
165
+
166
+ Total: 2 suggestion(s)
167
+ ```
168
+
169
+ ## DSL Data Source
170
+
171
+ Use AI to generate content at build time:
172
+
173
+ ```json
174
+ {
175
+ "version": "1.0",
176
+ "data": {
177
+ "hero": {
178
+ "type": "ai",
179
+ "provider": "anthropic",
180
+ "prompt": "Create a hero section with gradient background and CTA",
181
+ "output": "component"
182
+ }
183
+ },
184
+ "view": {
185
+ "kind": "component",
186
+ "name": "hero",
187
+ "props": {}
188
+ }
189
+ }
190
+ ```
191
+
192
+ ## Generate Action
193
+
194
+ Generate DSL at runtime in response to user actions:
195
+
196
+ ```json
197
+ {
198
+ "actions": [
199
+ {
200
+ "name": "generateCard",
201
+ "steps": [
202
+ {
203
+ "do": "generate",
204
+ "provider": "anthropic",
205
+ "prompt": { "expr": "state", "name": "userPrompt" },
206
+ "output": "component",
207
+ "result": "generatedCard",
208
+ "onSuccess": [
209
+ { "do": "set", "target": "card", "value": { "expr": "var", "name": "generatedCard" } }
210
+ ],
211
+ "onError": [
212
+ { "do": "set", "target": "error", "value": { "expr": "lit", "value": "Generation failed" } }
213
+ ]
214
+ }
215
+ ]
216
+ }
217
+ ]
218
+ }
219
+ ```
220
+
221
+ ## API Reference
222
+
223
+ ### createDslGenerator(options)
224
+
225
+ Creates a new DSL generator instance.
226
+
227
+ ```typescript
228
+ interface DslGeneratorOptions {
229
+ provider: 'anthropic' | 'openai';
230
+ providerInstance?: AiProvider; // Custom provider instance
231
+ security?: SecurityOptions;
232
+ context?: GenerationContext;
233
+ }
234
+ ```
235
+
236
+ ### generator.generate(options)
237
+
238
+ Generates DSL from a prompt.
239
+
240
+ ```typescript
241
+ interface GenerateOptions {
242
+ prompt: string;
243
+ output: 'component' | 'view' | 'suggestion';
244
+ context?: GenerationContext;
245
+ security?: SecurityOptions;
246
+ }
247
+
248
+ interface GenerateResult {
249
+ dsl: Record<string, unknown>;
250
+ raw: string;
251
+ validated: boolean;
252
+ errors?: string[];
253
+ }
254
+ ```
255
+
256
+ ### generator.validate(dsl, security?)
257
+
258
+ Validates DSL against security rules.
259
+
260
+ ```typescript
261
+ const result = generator.validate(dsl, {
262
+ allowedTags: ['div', 'span', 'button'],
263
+ });
264
+
265
+ if (!result.valid) {
266
+ console.error('Validation errors:', result.errors);
267
+ }
268
+ ```
269
+
270
+ ### Direct Provider Access
271
+
272
+ ```typescript
273
+ import { getProvider, AnthropicProvider, OpenAIProvider } from '@constela/ai';
274
+
275
+ // Get provider by type
276
+ const provider = getProvider('anthropic');
277
+
278
+ // Or create directly
279
+ const anthropic = new AnthropicProvider({ model: 'claude-sonnet-4-20250514' });
280
+ const openai = new OpenAIProvider({ model: 'gpt-4o' });
281
+
282
+ const response = await provider.generate('Generate a button component', {
283
+ systemPrompt: 'You are a UI component generator...',
284
+ maxTokens: 4096,
285
+ temperature: 0.7,
286
+ });
287
+ ```
288
+
289
+ ### Security Utilities
290
+
291
+ ```typescript
292
+ import {
293
+ isForbiddenTag,
294
+ isForbiddenAction,
295
+ isRestrictedAction,
296
+ validateUrl,
297
+ FORBIDDEN_TAGS,
298
+ FORBIDDEN_ACTIONS,
299
+ } from '@constela/ai';
300
+
301
+ // Check if tag is forbidden
302
+ isForbiddenTag('script'); // true
303
+ isForbiddenTag('div'); // false
304
+
305
+ // Validate URL
306
+ const result = validateUrl('https://example.com/api', {
307
+ allowedDomains: ['example.com'],
308
+ allowRelative: true,
309
+ });
310
+ ```
311
+
312
+ ## Error Handling
313
+
314
+ ```typescript
315
+ import { AiError, ValidationError, SecurityError } from '@constela/ai';
316
+
317
+ try {
318
+ const result = await generator.generate({ prompt, output: 'component' });
319
+ } catch (err) {
320
+ if (err instanceof SecurityError) {
321
+ console.error('Security violation:', err.violation);
322
+ } else if (err instanceof ValidationError) {
323
+ console.error('Validation failed:', err.violations);
324
+ } else if (err instanceof AiError) {
325
+ console.error('AI error:', err.code, err.message);
326
+ }
327
+ }
328
+ ```
329
+
330
+ Error codes:
331
+ - `PROVIDER_NOT_CONFIGURED` - API key not set
332
+ - `PROVIDER_NOT_FOUND` - Unknown provider type
333
+ - `API_ERROR` - Provider API call failed
334
+ - `VALIDATION_ERROR` - Generated DSL validation failed
335
+ - `SECURITY_VIOLATION` - Security rule violated
336
+ - `RATE_LIMIT_EXCEEDED` - API rate limit hit
337
+
338
+ ## License
339
+
340
+ MIT
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@constela/ai",
3
- "version": "1.0.2",
3
+ "version": "2.0.1",
4
4
  "description": "AI provider abstraction layer for Constela DSL",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -25,7 +25,7 @@
25
25
  "vitest": "^2.0.0"
26
26
  },
27
27
  "peerDependencies": {
28
- "@constela/core": "0.16.2"
28
+ "@constela/core": "0.17.1"
29
29
  },
30
30
  "engines": {
31
31
  "node": ">=20.0.0"