mycontext-cli 0.2.0 → 0.2.2

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 (136) hide show
  1. package/README.md +17 -16
  2. package/dist/cli.js +6 -2
  3. package/dist/cli.js.map +1 -1
  4. package/dist/commands/init.d.ts +3 -0
  5. package/dist/commands/init.d.ts.map +1 -1
  6. package/dist/commands/init.js +118 -11
  7. package/dist/commands/init.js.map +1 -1
  8. package/dist/commands/setup.d.ts.map +1 -1
  9. package/dist/commands/setup.js +8 -0
  10. package/dist/commands/setup.js.map +1 -1
  11. package/dist/config/dependencies.json +180 -0
  12. package/package.json +9 -8
  13. package/dist/cli/src/agents/implementations/CodeGenSubAgent.d.ts +0 -44
  14. package/dist/cli/src/agents/implementations/CodeGenSubAgent.d.ts.map +0 -1
  15. package/dist/cli/src/agents/implementations/CodeGenSubAgent.js +0 -1374
  16. package/dist/cli/src/agents/implementations/CodeGenSubAgent.js.map +0 -1
  17. package/dist/cli/src/agents/implementations/DocsSubAgent.d.ts +0 -35
  18. package/dist/cli/src/agents/implementations/DocsSubAgent.d.ts.map +0 -1
  19. package/dist/cli/src/agents/implementations/DocsSubAgent.js +0 -351
  20. package/dist/cli/src/agents/implementations/DocsSubAgent.js.map +0 -1
  21. package/dist/cli/src/agents/implementations/EnhancementAgent.d.ts +0 -120
  22. package/dist/cli/src/agents/implementations/EnhancementAgent.d.ts.map +0 -1
  23. package/dist/cli/src/agents/implementations/EnhancementAgent.js +0 -606
  24. package/dist/cli/src/agents/implementations/EnhancementAgent.js.map +0 -1
  25. package/dist/cli/src/agents/implementations/QASubAgent.d.ts +0 -31
  26. package/dist/cli/src/agents/implementations/QASubAgent.d.ts.map +0 -1
  27. package/dist/cli/src/agents/implementations/QASubAgent.js +0 -190
  28. package/dist/cli/src/agents/implementations/QASubAgent.js.map +0 -1
  29. package/dist/cli/src/agents/interfaces/SubAgent.d.ts +0 -287
  30. package/dist/cli/src/agents/interfaces/SubAgent.d.ts.map +0 -1
  31. package/dist/cli/src/agents/interfaces/SubAgent.js +0 -7
  32. package/dist/cli/src/agents/interfaces/SubAgent.js.map +0 -1
  33. package/dist/cli/src/agents/orchestrator/SubAgentOrchestrator.d.ts +0 -59
  34. package/dist/cli/src/agents/orchestrator/SubAgentOrchestrator.d.ts.map +0 -1
  35. package/dist/cli/src/agents/orchestrator/SubAgentOrchestrator.js +0 -305
  36. package/dist/cli/src/agents/orchestrator/SubAgentOrchestrator.js.map +0 -1
  37. package/dist/cli/src/agents/personalities/definitions.d.ts +0 -34
  38. package/dist/cli/src/agents/personalities/definitions.d.ts.map +0 -1
  39. package/dist/cli/src/agents/personalities/definitions.js +0 -389
  40. package/dist/cli/src/agents/personalities/definitions.js.map +0 -1
  41. package/dist/cli/src/cli.d.ts +0 -3
  42. package/dist/cli/src/cli.d.ts.map +0 -1
  43. package/dist/cli/src/cli.js +0 -298
  44. package/dist/cli/src/cli.js.map +0 -1
  45. package/dist/cli/src/commands/auth.d.ts +0 -23
  46. package/dist/cli/src/commands/auth.d.ts.map +0 -1
  47. package/dist/cli/src/commands/auth.js +0 -212
  48. package/dist/cli/src/commands/auth.js.map +0 -1
  49. package/dist/cli/src/commands/enhance.d.ts +0 -28
  50. package/dist/cli/src/commands/enhance.d.ts.map +0 -1
  51. package/dist/cli/src/commands/enhance.js +0 -246
  52. package/dist/cli/src/commands/enhance.js.map +0 -1
  53. package/dist/cli/src/commands/generate-components.d.ts +0 -27
  54. package/dist/cli/src/commands/generate-components.d.ts.map +0 -1
  55. package/dist/cli/src/commands/generate-components.js +0 -680
  56. package/dist/cli/src/commands/generate-components.js.map +0 -1
  57. package/dist/cli/src/commands/generate.d.ts +0 -108
  58. package/dist/cli/src/commands/generate.d.ts.map +0 -1
  59. package/dist/cli/src/commands/generate.js +0 -1970
  60. package/dist/cli/src/commands/generate.js.map +0 -1
  61. package/dist/cli/src/commands/init.d.ts +0 -13
  62. package/dist/cli/src/commands/init.d.ts.map +0 -1
  63. package/dist/cli/src/commands/init.js +0 -91
  64. package/dist/cli/src/commands/init.js.map +0 -1
  65. package/dist/cli/src/commands/list.d.ts +0 -17
  66. package/dist/cli/src/commands/list.d.ts.map +0 -1
  67. package/dist/cli/src/commands/list.js +0 -210
  68. package/dist/cli/src/commands/list.js.map +0 -1
  69. package/dist/cli/src/commands/model.d.ts +0 -25
  70. package/dist/cli/src/commands/model.d.ts.map +0 -1
  71. package/dist/cli/src/commands/model.js +0 -317
  72. package/dist/cli/src/commands/model.js.map +0 -1
  73. package/dist/cli/src/commands/preview.d.ts +0 -23
  74. package/dist/cli/src/commands/preview.d.ts.map +0 -1
  75. package/dist/cli/src/commands/preview.js +0 -1200
  76. package/dist/cli/src/commands/preview.js.map +0 -1
  77. package/dist/cli/src/commands/setup.d.ts +0 -35
  78. package/dist/cli/src/commands/setup.d.ts.map +0 -1
  79. package/dist/cli/src/commands/setup.js +0 -412
  80. package/dist/cli/src/commands/setup.js.map +0 -1
  81. package/dist/cli/src/commands/status.d.ts +0 -21
  82. package/dist/cli/src/commands/status.d.ts.map +0 -1
  83. package/dist/cli/src/commands/status.js +0 -287
  84. package/dist/cli/src/commands/status.js.map +0 -1
  85. package/dist/cli/src/commands/validate.d.ts +0 -22
  86. package/dist/cli/src/commands/validate.d.ts.map +0 -1
  87. package/dist/cli/src/commands/validate.js +0 -259
  88. package/dist/cli/src/commands/validate.js.map +0 -1
  89. package/dist/cli/src/types/index.d.ts +0 -152
  90. package/dist/cli/src/types/index.d.ts.map +0 -1
  91. package/dist/cli/src/types/index.js +0 -3
  92. package/dist/cli/src/types/index.js.map +0 -1
  93. package/dist/cli/src/utils/apiKeyManager.d.ts +0 -137
  94. package/dist/cli/src/utils/apiKeyManager.d.ts.map +0 -1
  95. package/dist/cli/src/utils/apiKeyManager.js +0 -471
  96. package/dist/cli/src/utils/apiKeyManager.js.map +0 -1
  97. package/dist/cli/src/utils/componentValidator.d.ts +0 -60
  98. package/dist/cli/src/utils/componentValidator.d.ts.map +0 -1
  99. package/dist/cli/src/utils/componentValidator.js +0 -191
  100. package/dist/cli/src/utils/componentValidator.js.map +0 -1
  101. package/dist/cli/src/utils/designTokenExtractor.d.ts +0 -94
  102. package/dist/cli/src/utils/designTokenExtractor.d.ts.map +0 -1
  103. package/dist/cli/src/utils/designTokenExtractor.js +0 -231
  104. package/dist/cli/src/utils/designTokenExtractor.js.map +0 -1
  105. package/dist/cli/src/utils/errorHandler.d.ts +0 -105
  106. package/dist/cli/src/utils/errorHandler.d.ts.map +0 -1
  107. package/dist/cli/src/utils/errorHandler.js +0 -332
  108. package/dist/cli/src/utils/errorHandler.js.map +0 -1
  109. package/dist/cli/src/utils/fileSystem.d.ts +0 -58
  110. package/dist/cli/src/utils/fileSystem.d.ts.map +0 -1
  111. package/dist/cli/src/utils/fileSystem.js +0 -230
  112. package/dist/cli/src/utils/fileSystem.js.map +0 -1
  113. package/dist/cli/src/utils/githubModels.d.ts +0 -53
  114. package/dist/cli/src/utils/githubModels.d.ts.map +0 -1
  115. package/dist/cli/src/utils/githubModels.js +0 -239
  116. package/dist/cli/src/utils/githubModels.js.map +0 -1
  117. package/dist/cli/src/utils/ollamaClient.d.ts +0 -37
  118. package/dist/cli/src/utils/ollamaClient.d.ts.map +0 -1
  119. package/dist/cli/src/utils/ollamaClient.js +0 -213
  120. package/dist/cli/src/utils/ollamaClient.js.map +0 -1
  121. package/dist/cli/src/utils/spinner.d.ts +0 -30
  122. package/dist/cli/src/utils/spinner.d.ts.map +0 -1
  123. package/dist/cli/src/utils/spinner.js +0 -119
  124. package/dist/cli/src/utils/spinner.js.map +0 -1
  125. package/dist/cli/src/utils/xaiClient.d.ts +0 -59
  126. package/dist/cli/src/utils/xaiClient.d.ts.map +0 -1
  127. package/dist/cli/src/utils/xaiClient.js +0 -244
  128. package/dist/cli/src/utils/xaiClient.js.map +0 -1
  129. package/dist/lib/analytics/usage-tracker.d.ts +0 -125
  130. package/dist/lib/analytics/usage-tracker.d.ts.map +0 -1
  131. package/dist/lib/analytics/usage-tracker.js +0 -429
  132. package/dist/lib/analytics/usage-tracker.js.map +0 -1
  133. package/dist/utils/githubModels.d.ts +0 -53
  134. package/dist/utils/githubModels.d.ts.map +0 -1
  135. package/dist/utils/githubModels.js +0 -239
  136. package/dist/utils/githubModels.js.map +0 -1
@@ -1,1374 +0,0 @@
1
- "use strict";
2
- /**
3
- * CodeGenSubAgent Implementation
4
- *
5
- * Specialized sub-agent for generating production-ready React components and TypeScript code.
6
- * Uses Claude Code for optimal code generation capabilities.
7
- * Enhanced with shadcn/ui primitives and modern React patterns for Next.js 14+.
8
- */
9
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- var desc = Object.getOwnPropertyDescriptor(m, k);
12
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
13
- desc = { enumerable: true, get: function() { return m[k]; } };
14
- }
15
- Object.defineProperty(o, k2, desc);
16
- }) : (function(o, m, k, k2) {
17
- if (k2 === undefined) k2 = k;
18
- o[k2] = m[k];
19
- }));
20
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
21
- Object.defineProperty(o, "default", { enumerable: true, value: v });
22
- }) : function(o, v) {
23
- o["default"] = v;
24
- });
25
- var __importStar = (this && this.__importStar) || (function () {
26
- var ownKeys = function(o) {
27
- ownKeys = Object.getOwnPropertyNames || function (o) {
28
- var ar = [];
29
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
30
- return ar;
31
- };
32
- return ownKeys(o);
33
- };
34
- return function (mod) {
35
- if (mod && mod.__esModule) return mod;
36
- var result = {};
37
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
38
- __setModuleDefault(result, mod);
39
- return result;
40
- };
41
- })();
42
- Object.defineProperty(exports, "__esModule", { value: true });
43
- exports.CodeGenSubAgent = void 0;
44
- const definitions_1 = require("../personalities/definitions");
45
- const generate_components_1 = require("../../commands/generate-components");
46
- // shadcn/ui component mapping for intelligent imports
47
- const SHADCN_COMPONENTS = {
48
- // Layout & Structure
49
- layout: ["Card", "Separator", "AspectRatio"],
50
- form: [
51
- "Button",
52
- "Input",
53
- "Label",
54
- "Form",
55
- "Select",
56
- "Checkbox",
57
- "RadioGroup",
58
- "Textarea",
59
- "Switch",
60
- ],
61
- navigation: ["NavigationMenu", "Breadcrumb", "Pagination", "Tabs"],
62
- feedback: ["Alert", "AlertDialog", "Dialog", "Toast", "Progress", "Skeleton"],
63
- data: ["Table", "DataTable", "Command", "Combobox"],
64
- overlay: ["Popover", "HoverCard", "Tooltip", "Sheet", "Drawer"],
65
- media: ["Avatar", "Badge", "Calendar", "Carousel"],
66
- utility: [
67
- "ScrollArea",
68
- "Resizable",
69
- "Collapsible",
70
- "Accordion",
71
- "ContextMenu",
72
- "Menubar",
73
- "DropdownMenu",
74
- "Toggle",
75
- "ToggleGroup",
76
- "Slider",
77
- "Sonner",
78
- ],
79
- };
80
- class CodeGenSubAgent {
81
- constructor() {
82
- this.name = "CodeGenSubAgent";
83
- this.description = "Expert React/TypeScript developer specializing in production-ready Next.js 14+ components with shadcn/ui";
84
- const personality = (0, definitions_1.getSubAgentPersonality)(this.name);
85
- if (!personality) {
86
- throw new Error(`Personality not found for ${this.name}`);
87
- }
88
- this.personality = personality.personality;
89
- this.llmProvider = personality.llmProvider;
90
- this.expertise = personality.expertise;
91
- }
92
- async run(input) {
93
- const { component, group, options, context } = input;
94
- // Use the existing GenerateComponentsCommand logic
95
- const generateCommand = new generate_components_1.GenerateComponentsCommand();
96
- // Handle both string and object inputs
97
- let componentName;
98
- if (typeof component === "string") {
99
- componentName = component;
100
- }
101
- else {
102
- componentName = component.name;
103
- }
104
- // Generate the component code using the enhanced method
105
- const code = await this.generateProductionReadyComponent(component, group, options);
106
- // Calculate metadata
107
- const estimatedLines = code.split("\n").length;
108
- const dependencies = this.extractDependencies(code);
109
- const shadcnComponents = this.extractShadcnComponents(code);
110
- return {
111
- code,
112
- metadata: {
113
- componentName,
114
- group,
115
- dependencies,
116
- estimatedLines,
117
- shadcnComponents,
118
- qualityScore: this.calculateQualityScore(code),
119
- },
120
- };
121
- }
122
- async validate(input) {
123
- // Handle both structured component objects and simple string descriptions
124
- if (typeof input.component === "string") {
125
- // Simple string input - just need the string and group
126
- return !!(input.component && input.group);
127
- }
128
- else {
129
- // Structured component object - validate all required fields
130
- if (!input.component || !input.component.name) {
131
- return false;
132
- }
133
- if (!input.group) {
134
- return false;
135
- }
136
- // For structured input, require type and userStories
137
- if (!input.component.type || !input.component.userStories) {
138
- return false;
139
- }
140
- }
141
- return true;
142
- }
143
- async getStatus() {
144
- return {
145
- name: this.name,
146
- status: "idle",
147
- errorCount: 0,
148
- successCount: 0,
149
- };
150
- }
151
- async generateProductionReadyComponent(component, group, options) {
152
- // Ollama is the only generation method for local AI
153
- return await this.generateWithOllama(component, group, options);
154
- }
155
- getReactImportsForType(type) {
156
- const imports = [];
157
- switch (type) {
158
- case "form":
159
- imports.push("useState", "useCallback", "useMemo");
160
- break;
161
- case "layout":
162
- imports.push("ReactNode", "FC");
163
- break;
164
- case "data":
165
- imports.push("useState", "useEffect", "useMemo");
166
- break;
167
- case "navigation":
168
- imports.push("useState", "useEffect");
169
- break;
170
- case "feedback":
171
- imports.push("useState", "useEffect");
172
- break;
173
- default:
174
- imports.push("useState");
175
- }
176
- return [...new Set(imports)];
177
- }
178
- getShadcnImportsForType(type) {
179
- const imports = [];
180
- switch (type) {
181
- case "form":
182
- imports.push("Button", "Input", "Label", "Form", "FormControl", "FormField", "FormItem", "FormLabel", "FormMessage", "Select", "SelectContent", "SelectItem", "SelectTrigger", "SelectValue", "Checkbox", "Alert", "AlertDescription");
183
- break;
184
- case "layout":
185
- imports.push("Card", "CardContent", "CardDescription", "CardHeader", "CardTitle", "Separator");
186
- break;
187
- case "card":
188
- imports.push("Card", "CardContent", "CardDescription", "CardHeader", "CardTitle", "CardFooter", "Button");
189
- break;
190
- case "button":
191
- imports.push("Button");
192
- break;
193
- case "navigation":
194
- imports.push("NavigationMenu", "NavigationMenuContent", "NavigationMenuItem", "NavigationMenuLink", "NavigationMenuList", "NavigationMenuTrigger", "Breadcrumb", "BreadcrumbItem", "BreadcrumbLink", "BreadcrumbList", "BreadcrumbSeparator", "Tabs", "TabsContent", "TabsList", "TabsTrigger");
195
- break;
196
- case "feedback":
197
- imports.push("Alert", "AlertDescription", "AlertTitle", "Dialog", "DialogContent", "DialogDescription", "DialogHeader", "DialogTitle", "DialogTrigger", "Toast", "Progress");
198
- break;
199
- case "data":
200
- imports.push("Table", "TableBody", "TableCell", "TableHead", "TableHeader", "TableRow", "Command", "CommandEmpty", "CommandGroup", "CommandInput", "CommandItem", "CommandList");
201
- break;
202
- case "overlay":
203
- imports.push("Popover", "PopoverContent", "PopoverTrigger", "Tooltip", "TooltipContent", "TooltipProvider", "TooltipTrigger", "Sheet", "SheetContent", "SheetDescription", "SheetHeader", "SheetTitle", "SheetTrigger");
204
- break;
205
- case "media":
206
- imports.push("Avatar", "AvatarFallback", "AvatarImage", "Badge");
207
- break;
208
- default:
209
- imports.push("Card", "CardContent", "CardHeader", "CardTitle", "Button");
210
- }
211
- return [...new Set(imports)];
212
- }
213
- getCustomImportsForType(type) {
214
- const imports = [];
215
- if (type === "form") {
216
- imports.push('import { useForm } from "react-hook-form";');
217
- imports.push('import { zodResolver } from "@hookform/resolvers/zod";');
218
- imports.push('import * as z from "zod";');
219
- }
220
- if (type === "navigation") {
221
- imports.push('import Link from "next/link";');
222
- imports.push('import { usePathname } from "next/navigation";');
223
- }
224
- if (type === "data") {
225
- imports.push('import { useMemo } from "react";');
226
- }
227
- return imports;
228
- }
229
- generateTypeDefinitions(type, name) {
230
- switch (type) {
231
- case "form":
232
- return `
233
- /** Form data schema */
234
- export const ${name.toLowerCase()}Schema = z.object({
235
- email: z.string().email("Please enter a valid email address"),
236
- password: z.string().min(8, "Password must be at least 8 characters long"),
237
- confirmPassword: z.string().optional(),
238
- }).refine((data) => {
239
- if (data.confirmPassword !== undefined) {
240
- return data.password === data.confirmPassword;
241
- }
242
- return true;
243
- }, {
244
- message: "Passwords don't match",
245
- path: ["confirmPassword"],
246
- });
247
-
248
- /** Inferred form data type */
249
- export type ${name}FormData = z.infer<typeof ${name.toLowerCase()}Schema>;
250
-
251
- /** Form submission result */
252
- export interface ${name}SubmissionResult {
253
- success: boolean;
254
- message?: string;
255
- errors?: Record<string, string>;
256
- }`;
257
- case "navigation":
258
- return `
259
- /** Navigation item interface */
260
- export interface NavigationItem {
261
- /** Display label */
262
- label: string;
263
- /** Route path */
264
- href: string;
265
- /** Optional icon component */
266
- icon?: React.ComponentType<{ className?: string }>;
267
- /** Whether the item is disabled */
268
- disabled?: boolean;
269
- /** Nested items for dropdowns */
270
- children?: NavigationItem[];
271
- }`;
272
- case "data":
273
- return `
274
- /** Generic data row interface */
275
- export interface DataRow {
276
- id: string | number;
277
- [key: string]: any;
278
- }
279
-
280
- /** Column definition */
281
- export interface ColumnDef<T = DataRow> {
282
- /** Column key */
283
- key: keyof T;
284
- /** Display label */
285
- label: string;
286
- /** Custom render function */
287
- render?: (value: any, row: T) => React.ReactNode;
288
- /** Whether column is sortable */
289
- sortable?: boolean;
290
- /** Column width */
291
- width?: string;
292
- }
293
-
294
- /** Sort configuration */
295
- export interface SortConfig {
296
- key: keyof DataRow;
297
- direction: "asc" | "desc";
298
- }`;
299
- default:
300
- return "";
301
- }
302
- }
303
- generateDetailedPropsForType(type) {
304
- switch (type) {
305
- case "form":
306
- return `
307
- /** Form submission handler */
308
- onSubmit?: (data: ${type}FormData) => Promise<${type}SubmissionResult> | ${type}SubmissionResult;
309
- /** Loading state */
310
- loading?: boolean;
311
- /** Error message */
312
- error?: string;
313
- /** Form variant */
314
- variant?: "default" | "login" | "signup" | "contact";
315
- /** Initial form values */
316
- defaultValues?: Partial<${type}FormData>;
317
- /** Whether to show password confirmation field */
318
- showConfirmPassword?: boolean;
319
- /** Custom validation rules */
320
- validationRules?: Partial<Record<keyof ${type}FormData, z.ZodSchema>>;`;
321
- case "layout":
322
- return `
323
- /** Main content */
324
- children: React.ReactNode;
325
- /** Sidebar content */
326
- sidebar?: React.ReactNode;
327
- /** Header content */
328
- header?: React.ReactNode;
329
- /** Footer content */
330
- footer?: React.ReactNode;
331
- /** Layout variant */
332
- variant?: "default" | "sidebar" | "centered" | "fullscreen";
333
- /** Whether sidebar is collapsible */
334
- collapsibleSidebar?: boolean;
335
- /** Sidebar initial state */
336
- sidebarDefaultOpen?: boolean;`;
337
- case "card":
338
- return `
339
- /** Card title */
340
- title?: string;
341
- /** Card description */
342
- description?: string;
343
- /** Card content */
344
- content?: React.ReactNode;
345
- /** Card footer actions */
346
- actions?: React.ReactNode;
347
- /** Card variant */
348
- variant?: "default" | "elevated" | "outlined" | "ghost";
349
- /** Whether card is interactive */
350
- interactive?: boolean;
351
- /** Click handler for interactive cards */
352
- onClick?: () => void;
353
- /** Card size */
354
- size?: "sm" | "default" | "lg";`;
355
- case "button":
356
- return `
357
- /** Button variant */
358
- variant?: "default" | "destructive" | "outline" | "secondary" | "ghost" | "link";
359
- /** Button size */
360
- size?: "default" | "sm" | "lg" | "icon";
361
- /** Whether button is disabled */
362
- disabled?: boolean;
363
- /** Loading state */
364
- loading?: boolean;
365
- /** Click handler */
366
- onClick?: (event: React.MouseEvent<HTMLButtonElement>) => void;
367
- /** Button content */
368
- children: React.ReactNode;
369
- /** Button type */
370
- type?: "button" | "submit" | "reset";
371
- /** ARIA label for accessibility */
372
- "aria-label"?: string;`;
373
- case "navigation":
374
- return `
375
- /** Navigation items */
376
- items: NavigationItem[];
377
- /** Currently active item path */
378
- activeItem?: string;
379
- /** Navigation orientation */
380
- orientation?: "horizontal" | "vertical";
381
- /** Whether to show icons */
382
- showIcons?: boolean;
383
- /** Custom item renderer */
384
- renderItem?: (item: NavigationItem, isActive: boolean) => React.ReactNode;
385
- /** Navigation variant */
386
- variant?: "default" | "pills" | "underline";`;
387
- case "feedback":
388
- return `
389
- /** Alert title */
390
- title?: string;
391
- /** Alert message */
392
- message?: string;
393
- /** Alert variant */
394
- variant?: "default" | "destructive" | "success" | "warning";
395
- /** Close handler */
396
- onClose?: () => void;
397
- /** Whether alert is dismissible */
398
- dismissible?: boolean;
399
- /** Auto-dismiss timeout in milliseconds */
400
- autoDissmissAfter?: number;
401
- /** Custom icon */
402
- icon?: React.ReactNode;`;
403
- case "data":
404
- return `
405
- /** Table data */
406
- data: DataRow[];
407
- /** Column definitions */
408
- columns: ColumnDef[];
409
- /** Whether table is loading */
410
- loading?: boolean;
411
- /** Whether to show pagination */
412
- pagination?: boolean;
413
- /** Items per page */
414
- pageSize?: number;
415
- /** Sort configuration */
416
- sortable?: boolean;
417
- /** Initial sort */
418
- defaultSort?: SortConfig;
419
- /** Row selection handler */
420
- onRowSelect?: (selectedRows: DataRow[]) => void;
421
- /** Empty state message */
422
- emptyMessage?: string;
423
- /** Custom row renderer */
424
- renderRow?: (row: DataRow, index: number) => React.ReactNode;`;
425
- default:
426
- return `
427
- /** Component children */
428
- children?: React.ReactNode;
429
- /** Component variant */
430
- variant?: "default";`;
431
- }
432
- }
433
- generateExampleProps(type) {
434
- switch (type) {
435
- case "form":
436
- return `onSubmit={handleSubmit}\n * loading={false}\n * variant="default"`;
437
- case "layout":
438
- return `variant="sidebar"\n * header={<Header />}\n * sidebar={<Sidebar />}`;
439
- case "card":
440
- return `title="Card Title"\n * variant="elevated"\n * interactive`;
441
- case "button":
442
- return `variant="default"\n * size="lg"\n * onClick={handleClick}`;
443
- case "navigation":
444
- return `items={navigationItems}\n * variant="pills"\n * orientation="horizontal"`;
445
- case "feedback":
446
- return `variant="success"\n * title="Success"\n * dismissible`;
447
- case "data":
448
- return `data={tableData}\n * columns={columns}\n * pagination`;
449
- default:
450
- return `variant="default"`;
451
- }
452
- }
453
- generateEnhancedPropsDestructuring(type) {
454
- switch (type) {
455
- case "form":
456
- return `
457
- onSubmit,
458
- loading = false,
459
- error,
460
- variant = "default",
461
- defaultValues,
462
- showConfirmPassword = false,
463
- validationRules,`;
464
- case "layout":
465
- return `
466
- children,
467
- sidebar,
468
- header,
469
- footer,
470
- variant = "default",
471
- collapsibleSidebar = false,
472
- sidebarDefaultOpen = true,`;
473
- case "card":
474
- return `
475
- title,
476
- description,
477
- content,
478
- actions,
479
- variant = "default",
480
- interactive = false,
481
- onClick,
482
- size = "default",`;
483
- case "button":
484
- return `
485
- variant = "default",
486
- size = "default",
487
- disabled = false,
488
- loading = false,
489
- onClick,
490
- children,
491
- type = "button",
492
- "aria-label": ariaLabel,`;
493
- case "navigation":
494
- return `
495
- items,
496
- activeItem,
497
- orientation = "horizontal",
498
- showIcons = true,
499
- renderItem,
500
- variant = "default",`;
501
- case "feedback":
502
- return `
503
- title,
504
- message,
505
- variant = "default",
506
- onClose,
507
- dismissible = false,
508
- autoDissmissAfter,
509
- icon,`;
510
- case "data":
511
- return `
512
- data,
513
- columns,
514
- loading = false,
515
- pagination = false,
516
- pageSize = 10,
517
- sortable = false,
518
- defaultSort,
519
- onRowSelect,
520
- emptyMessage = "No data available",
521
- renderRow,`;
522
- default:
523
- return `
524
- children,
525
- variant = "default",`;
526
- }
527
- }
528
- generateProductionComponentLogic(type, actionFunctions, componentName) {
529
- const logic = [];
530
- if (type === "form") {
531
- logic.push(`
532
- const [isSubmitting, setIsSubmitting] = useState(false);
533
-
534
- const form = useForm<${componentName}FormData>({
535
- resolver: zodResolver(${componentName.toLowerCase()}Schema),
536
- defaultValues: defaultValues || {
537
- email: "",
538
- password: "",
539
- ...(showConfirmPassword && { confirmPassword: "" }),
540
- },
541
- });
542
-
543
- const handleFormSubmit = useCallback(async (values: ${componentName}FormData) => {
544
- if (!onSubmit) return;
545
-
546
- setIsSubmitting(true);
547
- try {
548
- const result = await onSubmit(values);
549
- if (result.success) {
550
- form.reset();
551
- } else if (result.errors) {
552
- Object.entries(result.errors).forEach(([field, message]) => {
553
- form.setError(field as keyof ${componentName}FormData, { message });
554
- });
555
- }
556
- } catch (error) {
557
- console.error("Form submission error:", error);
558
- form.setError("root", { message: "An unexpected error occurred" });
559
- } finally {
560
- setIsSubmitting(false);
561
- }
562
- }, [onSubmit, form]);`);
563
- }
564
- if (type === "navigation") {
565
- logic.push(`
566
- const pathname = usePathname();
567
- const [openDropdowns, setOpenDropdowns] = useState<Set<string>>(new Set());
568
-
569
- const currentActiveItem = useMemo(() => {
570
- return activeItem || pathname;
571
- }, [activeItem, pathname]);
572
-
573
- const toggleDropdown = useCallback((itemLabel: string) => {
574
- setOpenDropdowns(prev => {
575
- const newSet = new Set(prev);
576
- if (newSet.has(itemLabel)) {
577
- newSet.delete(itemLabel);
578
- } else {
579
- newSet.add(itemLabel);
580
- }
581
- return newSet;
582
- });
583
- }, []);`);
584
- }
585
- if (type === "data") {
586
- logic.push(`
587
- const [currentPage, setCurrentPage] = useState(1);
588
- const [sortConfig, setSortConfig] = useState<SortConfig | null>(defaultSort || null);
589
- const [selectedRows, setSelectedRows] = useState<Set<string | number>>(new Set());
590
-
591
- const sortedData = useMemo(() => {
592
- if (!sortConfig) return data;
593
-
594
- return [...data].sort((a, b) => {
595
- const aValue = a[sortConfig.key];
596
- const bValue = b[sortConfig.key];
597
-
598
- if (aValue < bValue) return sortConfig.direction === "asc" ? -1 : 1;
599
- if (aValue > bValue) return sortConfig.direction === "asc" ? 1 : -1;
600
- return 0;
601
- });
602
- }, [data, sortConfig]);
603
-
604
- const paginatedData = useMemo(() => {
605
- if (!pagination) return sortedData;
606
-
607
- const startIndex = (currentPage - 1) * pageSize;
608
- return sortedData.slice(startIndex, startIndex + pageSize);
609
- }, [sortedData, pagination, currentPage, pageSize]);
610
-
611
- const handleSort = useCallback((key: keyof DataRow) => {
612
- if (!sortable) return;
613
-
614
- setSortConfig(prevSort => {
615
- if (prevSort?.key === key) {
616
- return {
617
- key,
618
- direction: prevSort.direction === "asc" ? "desc" : "asc"
619
- };
620
- }
621
- return { key, direction: "asc" };
622
- });
623
- }, [sortable]);
624
-
625
- const handleRowSelection = useCallback((rowId: string | number) => {
626
- setSelectedRows(prev => {
627
- const newSet = new Set(prev);
628
- if (newSet.has(rowId)) {
629
- newSet.delete(rowId);
630
- } else {
631
- newSet.add(rowId);
632
- }
633
-
634
- if (onRowSelect) {
635
- const selectedData = data.filter(row => newSet.has(row.id));
636
- onRowSelect(selectedData);
637
- }
638
-
639
- return newSet;
640
- });
641
- }, [data, onRowSelect]);`);
642
- }
643
- if (type === "feedback" && logic.length === 0) {
644
- logic.push(`
645
- useEffect(() => {
646
- if (autoDissmissAfter && onClose) {
647
- const timer = setTimeout(onClose, autoDissmissAfter);
648
- return () => clearTimeout(timer);
649
- }
650
- }, [autoDissmissAfter, onClose]);`);
651
- }
652
- return logic.join("\n");
653
- }
654
- generateAccessibleComponentJSX(type, name, shadcnImports) {
655
- switch (type) {
656
- case "form":
657
- return `<Form {...form}>
658
- <form
659
- onSubmit={form.handleSubmit(handleFormSubmit)}
660
- className={cn("space-y-6", className)}
661
- noValidate
662
- {...props}
663
- >
664
- <FormField
665
- control={form.control}
666
- name="email"
667
- render={({ field }) => (
668
- <FormItem>
669
- <FormLabel>Email Address</FormLabel>
670
- <FormControl>
671
- <Input
672
- type="email"
673
- placeholder="Enter your email address"
674
- autoComplete="email"
675
- aria-describedby="email-error"
676
- {...field}
677
- />
678
- </FormControl>
679
- <FormMessage id="email-error" />
680
- </FormItem>
681
- )}
682
- />
683
-
684
- <FormField
685
- control={form.control}
686
- name="password"
687
- render={({ field }) => (
688
- <FormItem>
689
- <FormLabel>Password</FormLabel>
690
- <FormControl>
691
- <Input
692
- type="password"
693
- placeholder="Enter your password"
694
- autoComplete="current-password"
695
- aria-describedby="password-error"
696
- {...field}
697
- />
698
- </FormControl>
699
- <FormMessage id="password-error" />
700
- </FormItem>
701
- )}
702
- />
703
-
704
- {showConfirmPassword && (
705
- <FormField
706
- control={form.control}
707
- name="confirmPassword"
708
- render={({ field }) => (
709
- <FormItem>
710
- <FormLabel>Confirm Password</FormLabel>
711
- <FormControl>
712
- <Input
713
- type="password"
714
- placeholder="Confirm your password"
715
- autoComplete="new-password"
716
- aria-describedby="confirm-password-error"
717
- {...field}
718
- />
719
- </FormControl>
720
- <FormMessage id="confirm-password-error" />
721
- </FormItem>
722
- )}
723
- />
724
- )}
725
-
726
- {error && (
727
- <Alert variant="destructive">
728
- <AlertDescription>{error}</AlertDescription>
729
- </Alert>
730
- )}
731
-
732
- {form.formState.errors.root && (
733
- <Alert variant="destructive">
734
- <AlertDescription>{form.formState.errors.root.message}</AlertDescription>
735
- </Alert>
736
- )}
737
-
738
- <Button
739
- type="submit"
740
- disabled={loading || isSubmitting}
741
- className="w-full"
742
- aria-describedby={loading || isSubmitting ? "submit-loading" : undefined}
743
- >
744
- {loading || isSubmitting ? (
745
- <>
746
- <span className="sr-only" id="submit-loading">Loading...</span>
747
- <div className="animate-spin rounded-full h-4 w-4 border-b-2 border-white mr-2" />
748
- Submitting...
749
- </>
750
- ) : (
751
- "Submit"
752
- )}
753
- </Button>
754
- </form>
755
- </Form>`;
756
- case "layout":
757
- return `<div className={cn("min-h-screen flex flex-col", className)} {...props}>
758
- {header && (
759
- <header
760
- className="border-b bg-background sticky top-0 z-40"
761
- role="banner"
762
- >
763
- <div className="container mx-auto px-4 py-4">
764
- {header}
765
- </div>
766
- </header>
767
- )}
768
-
769
- <div className="flex-1 flex">
770
- {sidebar && (
771
- <aside
772
- className={cn(
773
- "border-r bg-background",
774
- variant === "sidebar" ? "w-64" : "w-auto"
775
- )}
776
- role="complementary"
777
- aria-label="Sidebar navigation"
778
- >
779
- <div className="p-4">
780
- {sidebar}
781
- </div>
782
- </aside>
783
- )}
784
-
785
- <main
786
- className="flex-1 focus:outline-none"
787
- role="main"
788
- tabIndex={-1}
789
- >
790
- <div className={cn(
791
- "container mx-auto px-4 py-8",
792
- variant === "centered" && "max-w-4xl",
793
- variant === "fullscreen" && "max-w-none px-0 py-0"
794
- )}>
795
- {children}
796
- </div>
797
- </main>
798
- </div>
799
-
800
- {footer && (
801
- <footer
802
- className="border-t bg-background"
803
- role="contentinfo"
804
- >
805
- <div className="container mx-auto px-4 py-4 text-center text-sm text-muted-foreground">
806
- {footer}
807
- </div>
808
- </footer>
809
- )}
810
- </div>`;
811
- case "card":
812
- return `<Card
813
- className={cn(
814
- "transition-all duration-200",
815
- variant === "elevated" && "shadow-lg hover:shadow-xl",
816
- variant === "outlined" && "border-2",
817
- variant === "ghost" && "border-none shadow-none",
818
- interactive && "cursor-pointer hover:bg-accent/50",
819
- size === "sm" && "p-4",
820
- size === "lg" && "p-8",
821
- className
822
- )}
823
- onClick={interactive ? onClick : undefined}
824
- role={interactive ? "button" : undefined}
825
- tabIndex={interactive ? 0 : undefined}
826
- onKeyDown={interactive ? (e) => {
827
- if (e.key === "Enter" || e.key === " ") {
828
- e.preventDefault();
829
- onClick?.();
830
- }
831
- } : undefined}
832
- {...props}
833
- >
834
- {(title || description) && (
835
- <CardHeader className={size === "sm" ? "pb-3" : undefined}>
836
- {title && (
837
- <CardTitle className={size === "sm" ? "text-base" : "text-lg"}>
838
- {title}
839
- </CardTitle>
840
- )}
841
- {description && (
842
- <CardDescription>{description}</CardDescription>
843
- )}
844
- </CardHeader>
845
- )}
846
-
847
- {content && (
848
- <CardContent className={cn(
849
- size === "sm" && "pt-0 pb-3",
850
- !title && !description && "pt-6"
851
- )}>
852
- {content}
853
- </CardContent>
854
- )}
855
-
856
- {actions && (
857
- <CardFooter className={cn(
858
- "flex justify-end space-x-2",
859
- size === "sm" && "pt-0"
860
- )}>
861
- {actions}
862
- </CardFooter>
863
- )}
864
- </Card>`;
865
- case "button":
866
- return `<Button
867
- variant={variant}
868
- size={size}
869
- disabled={disabled || loading}
870
- onClick={onClick}
871
- type={type}
872
- className={cn(loading && "cursor-wait", className)}
873
- aria-label={ariaLabel}
874
- aria-disabled={disabled || loading}
875
- {...props}
876
- >
877
- {loading ? (
878
- <>
879
- <div className="animate-spin rounded-full h-4 w-4 border-b-2 border-current mr-2" />
880
- <span className="sr-only">Loading...</span>
881
- Loading...
882
- </>
883
- ) : (
884
- children
885
- )}
886
- </Button>`;
887
- case "navigation":
888
- return `<NavigationMenu
889
- className={cn("", className)}
890
- orientation={orientation}
891
- {...props}
892
- >
893
- <NavigationMenuList className={cn(
894
- orientation === "vertical" && "flex-col space-x-0 space-y-1"
895
- )}>
896
- {items.map((item, index) => (
897
- <NavigationMenuItem key={item.href || index}>
898
- {item.children ? (
899
- <>
900
- <NavigationMenuTrigger
901
- className={cn(
902
- variant === "pills" && "rounded-full",
903
- variant === "underline" && "border-b-2 border-transparent data-[state=open]:border-primary"
904
- )}
905
- onClick={() => toggleDropdown(item.label)}
906
- aria-expanded={openDropdowns.has(item.label)}
907
- >
908
- {showIcons && item.icon && (
909
- <item.icon className="w-4 h-4 mr-2" />
910
- )}
911
- {item.label}
912
- </NavigationMenuTrigger>
913
- <NavigationMenuContent>
914
- <div className="grid gap-3 p-4 w-[400px]">
915
- {item.children.map((child, childIndex) => (
916
- <NavigationMenuLink
917
- key={child.href || childIndex}
918
- asChild
919
- >
920
- <Link
921
- href={child.href}
922
- className={cn(
923
- "block select-none space-y-1 rounded-md p-3 leading-none no-underline outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground",
924
- child.disabled && "pointer-events-none opacity-50"
925
- )}
926
- >
927
- <div className="text-sm font-medium leading-none">
928
- {child.label}
929
- </div>
930
- </Link>
931
- </NavigationMenuLink>
932
- ))}
933
- </div>
934
- </NavigationMenuContent>
935
- </>
936
- ) : (
937
- <NavigationMenuLink
938
- asChild
939
- className={cn(
940
- currentActiveItem === item.href && "bg-accent text-accent-foreground",
941
- variant === "pills" && "rounded-full",
942
- variant === "underline" && currentActiveItem === item.href && "border-b-2 border-primary"
943
- )}
944
- >
945
- <Link
946
- href={item.href}
947
- className={cn(
948
- "block select-none space-y-1 rounded-md p-3 leading-none no-underline outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground",
949
- item.disabled && "pointer-events-none opacity-50"
950
- )}
951
- >
952
- {showIcons && item.icon && (
953
- <item.icon className="w-4 h-4 mr-2 inline-block" />
954
- )}
955
- {item.label}
956
- </Link>
957
- </NavigationMenuLink>
958
- )}
959
- </NavigationMenuItem>
960
- ))}
961
- </NavigationMenuList>
962
- </NavigationMenu>`;
963
- case "feedback":
964
- return `<Alert
965
- variant={variant}
966
- className={cn("relative", className)}
967
- role={variant === "destructive" ? "alert" : "status"}
968
- aria-live={variant === "destructive" ? "assertive" : "polite"}
969
- {...props}
970
- >
971
- {icon || (
972
- <div className="w-4 h-4">
973
- {variant === "success" && "✓"}
974
- {variant === "destructive" && "⚠"}
975
- {variant === "warning" && "⚠"}
976
- </div>
977
- )}
978
-
979
- <div className="flex-1">
980
- {title && <AlertTitle>{title}</AlertTitle>}
981
- {message && <AlertDescription>{message}</AlertDescription>}
982
- </div>
983
-
984
- {dismissible && onClose && (
985
- <Button
986
- variant="ghost"
987
- size="sm"
988
- onClick={onClose}
989
- className="absolute top-2 right-2 h-6 w-6 p-0"
990
- aria-label="Close alert"
991
- >
992
- ×
993
- </Button>
994
- )}
995
- </Alert>`;
996
- case "data":
997
- return `<div className={cn("space-y-4", className)} {...props}>
998
- {loading ? (
999
- <div className="flex items-center justify-center p-8">
1000
- <div className="animate-spin rounded-full h-8 w-8 border-b-2 border-primary" />
1001
- <span className="sr-only">Loading data...</span>
1002
- </div>
1003
- ) : (
1004
- <>
1005
- <div className="rounded-md border overflow-hidden">
1006
- <Table>
1007
- <TableHeader>
1008
- <TableRow>
1009
- {onRowSelect && (
1010
- <TableHead className="w-12">
1011
- <span className="sr-only">Select row</span>
1012
- </TableHead>
1013
- )}
1014
- {columns.map((column) => (
1015
- <TableHead
1016
- key={String(column.key)}
1017
- className={cn(
1018
- sortable && column.sortable && "cursor-pointer hover:bg-muted",
1019
- column.width && \`w-[\${column.width}]\`
1020
- )}
1021
- onClick={() => column.sortable && handleSort(column.key)}
1022
- role={column.sortable ? "button" : undefined}
1023
- tabIndex={column.sortable ? 0 : undefined}
1024
- onKeyDown={column.sortable ? (e) => {
1025
- if (e.key === "Enter" || e.key === " ") {
1026
- e.preventDefault();
1027
- handleSort(column.key);
1028
- }
1029
- } : undefined}
1030
- >
1031
- <div className="flex items-center space-x-2">
1032
- <span>{column.label}</span>
1033
- {sortable && column.sortable && sortConfig?.key === column.key && (
1034
- <span className="text-xs">
1035
- {sortConfig.direction === "asc" ? "↑" : "↓"}
1036
- </span>
1037
- )}
1038
- </div>
1039
- </TableHead>
1040
- ))}
1041
- </TableRow>
1042
- </TableHeader>
1043
- <TableBody>
1044
- {paginatedData.length === 0 ? (
1045
- <TableRow>
1046
- <TableCell
1047
- colSpan={columns.length + (onRowSelect ? 1 : 0)}
1048
- className="text-center py-8 text-muted-foreground"
1049
- >
1050
- {emptyMessage}
1051
- </TableCell>
1052
- </TableRow>
1053
- ) : (
1054
- paginatedData.map((row, index) => (
1055
- renderRow ? renderRow(row, index) : (
1056
- <TableRow
1057
- key={row.id}
1058
- className={cn(
1059
- onRowSelect && selectedRows.has(row.id) && "bg-muted"
1060
- )}
1061
- >
1062
- {onRowSelect && (
1063
- <TableCell>
1064
- <Checkbox
1065
- checked={selectedRows.has(row.id)}
1066
- onCheckedChange={() => handleRowSelection(row.id)}
1067
- aria-label={\`Select row \${index + 1}\`}
1068
- />
1069
- </TableCell>
1070
- )}
1071
- {columns.map((column) => (
1072
- <TableCell key={String(column.key)}>
1073
- {column.render
1074
- ? column.render(row[column.key], row)
1075
- : String(row[column.key] || "")
1076
- }
1077
- </TableCell>
1078
- ))}
1079
- </TableRow>
1080
- )
1081
- ))
1082
- )}
1083
- </TableBody>
1084
- </Table>
1085
- </div>
1086
-
1087
- {pagination && data.length > pageSize && (
1088
- <div className="flex items-center justify-between">
1089
- <p className="text-sm text-muted-foreground">
1090
- Showing {((currentPage - 1) * pageSize) + 1} to {Math.min(currentPage * pageSize, data.length)} of {data.length} results
1091
- </p>
1092
- <div className="flex items-center space-x-2">
1093
- <Button
1094
- variant="outline"
1095
- size="sm"
1096
- onClick={() => setCurrentPage(prev => Math.max(1, prev - 1))}
1097
- disabled={currentPage === 1}
1098
- aria-label="Previous page"
1099
- >
1100
- Previous
1101
- </Button>
1102
- <Button
1103
- variant="outline"
1104
- size="sm"
1105
- onClick={() => setCurrentPage(prev => prev + 1)}
1106
- disabled={currentPage * pageSize >= data.length}
1107
- aria-label="Next page"
1108
- >
1109
- Next
1110
- </Button>
1111
- </div>
1112
- </div>
1113
- )}
1114
- </>
1115
- )}
1116
- </div>`;
1117
- default:
1118
- return `<Card className={cn("p-4", className)} {...props}>
1119
- <CardHeader>
1120
- <CardTitle>${name}</CardTitle>
1121
- </CardHeader>
1122
- <CardContent>
1123
- <p className="text-sm text-muted-foreground">
1124
- This is a production-ready ${type} component with accessibility features and TypeScript support.
1125
- </p>
1126
- {children}
1127
- </CardContent>
1128
- </Card>`;
1129
- }
1130
- }
1131
- generateProductionActionFunctions(actionFunctions, componentName, type) {
1132
- if (actionFunctions.length === 0)
1133
- return "";
1134
- const functions = actionFunctions.map((func) => {
1135
- switch (func) {
1136
- case "handleSubmit":
1137
- return type === "form"
1138
- ? `// Form submission is handled within the component`
1139
- : `
1140
- /**
1141
- * Handles form submission with validation and error handling
1142
- * @param data - Form data to submit
1143
- * @returns Promise with submission result
1144
- */
1145
- export async function handleSubmit(data: Record<string, any>): Promise<{ success: boolean; message?: string }> {
1146
- try {
1147
- // TODO: Implement actual submission logic
1148
- console.log("Submitting data:", data);
1149
-
1150
- // Simulate API call
1151
- await new Promise(resolve => setTimeout(resolve, 1000));
1152
-
1153
- return { success: true, message: "Data submitted successfully" };
1154
- } catch (error) {
1155
- console.error("Submission error:", error);
1156
- return { success: false, message: "Failed to submit data" };
1157
- }
1158
- }`;
1159
- case "handleLogin":
1160
- return `
1161
- /**
1162
- * Handles user authentication with proper validation
1163
- * @param email - User email address
1164
- * @param password - User password
1165
- * @returns Promise with authentication result
1166
- */
1167
- export async function handleLogin(email: string, password: string): Promise<{
1168
- success: boolean;
1169
- user?: { id: string; email: string; name: string };
1170
- error?: string
1171
- }> {
1172
- try {
1173
- // TODO: Implement actual authentication logic
1174
- const response = await fetch("/api/auth/login", {
1175
- method: "POST",
1176
- headers: { "Content-Type": "application/json" },
1177
- body: JSON.stringify({ email, password }),
1178
- });
1179
-
1180
- if (!response.ok) {
1181
- throw new Error("Authentication failed");
1182
- }
1183
-
1184
- const result = await response.json();
1185
- return { success: true, user: result.user };
1186
- } catch (error) {
1187
- console.error("Login error:", error);
1188
- return { success: false, error: "Invalid credentials" };
1189
- }
1190
- }`;
1191
- case "validateEmail":
1192
- return `
1193
- /**
1194
- * Validates email address format and availability
1195
- * @param email - Email address to validate
1196
- * @returns Validation result with detailed feedback
1197
- */
1198
- export async function validateEmail(email: string): Promise<{
1199
- isValid: boolean;
1200
- isAvailable?: boolean;
1201
- message?: string;
1202
- }> {
1203
- const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;
1204
-
1205
- if (!emailRegex.test(email)) {
1206
- return { isValid: false, message: "Please enter a valid email address" };
1207
- }
1208
-
1209
- try {
1210
- // TODO: Check email availability
1211
- const response = await fetch(\`/api/auth/check-email?email=\${encodeURIComponent(email)}\`);
1212
- const { available } = await response.json();
1213
-
1214
- return {
1215
- isValid: true,
1216
- isAvailable: available,
1217
- message: available ? "Email is available" : "Email is already registered"
1218
- };
1219
- } catch (error) {
1220
- console.error("Email validation error:", error);
1221
- return { isValid: true, message: "Unable to verify email availability" };
1222
- }
1223
- }`;
1224
- default:
1225
- return `
1226
- /**
1227
- * ${func} - Custom action function
1228
- * TODO: Implement ${func} logic with proper TypeScript types and error handling
1229
- */
1230
- export async function ${func}(...args: any[]): Promise<{ success: boolean; data?: any; error?: string }> {
1231
- try {
1232
- console.log("${func} called with args:", args);
1233
-
1234
- // TODO: Implement actual logic
1235
- await new Promise(resolve => setTimeout(resolve, 100));
1236
-
1237
- return { success: true };
1238
- } catch (error) {
1239
- console.error("${func} error:", error);
1240
- return { success: false, error: "Operation failed" };
1241
- }
1242
- }`;
1243
- }
1244
- });
1245
- return functions.join("\n");
1246
- }
1247
- extractDependencies(code) {
1248
- const dependencies = [];
1249
- // Extract import statements
1250
- const importRegex = /import\s+.*?\s+from\s+['"]([^'"]+)['"]/g;
1251
- let match;
1252
- while ((match = importRegex.exec(code)) !== null) {
1253
- const importPath = match[1];
1254
- if (importPath.startsWith("@/") ||
1255
- importPath.startsWith("./") ||
1256
- importPath.startsWith("../")) {
1257
- dependencies.push(importPath);
1258
- }
1259
- }
1260
- // Extract shadcn/ui component dependencies
1261
- const shadcnComponents = this.extractShadcnComponents(code);
1262
- shadcnComponents.forEach((comp) => {
1263
- dependencies.push(`@/components/ui/${comp.toLowerCase()}`);
1264
- });
1265
- // Remove duplicates
1266
- return [...new Set(dependencies)];
1267
- }
1268
- extractShadcnComponents(code) {
1269
- const components = [];
1270
- // Check for shadcn/ui component usage
1271
- Object.values(SHADCN_COMPONENTS)
1272
- .flat()
1273
- .forEach((comp) => {
1274
- if (code.includes(comp)) {
1275
- components.push(comp);
1276
- }
1277
- });
1278
- return [...new Set(components)];
1279
- }
1280
- calculateQualityScore(code) {
1281
- let score = 70; // Base score
1282
- // Bonus for using shadcn/ui components
1283
- const shadcnComponents = this.extractShadcnComponents(code);
1284
- score += Math.min(shadcnComponents.length * 3, 15);
1285
- // Bonus for proper TypeScript usage
1286
- if (code.includes("interface") && code.includes("Props"))
1287
- score += 10;
1288
- if (code.includes("export type") || code.includes("export interface"))
1289
- score += 5;
1290
- // Bonus for React patterns and hooks
1291
- if (code.includes("useState") || code.includes("useEffect"))
1292
- score += 5;
1293
- if (code.includes("useCallback") || code.includes("useMemo"))
1294
- score += 5;
1295
- // Bonus for accessibility features
1296
- if (code.includes("aria-") || code.includes("role="))
1297
- score += 10;
1298
- if (code.includes("tabIndex") || code.includes("onKeyDown"))
1299
- score += 5;
1300
- // Bonus for error handling and validation
1301
- if (code.includes("try") && code.includes("catch"))
1302
- score += 5;
1303
- if (code.includes("zodResolver") || code.includes("z.object"))
1304
- score += 5;
1305
- // Bonus for semantic HTML and proper structure
1306
- if (code.includes("role=") && code.includes("aria-"))
1307
- score += 5;
1308
- if (code.includes("sr-only"))
1309
- score += 3;
1310
- // Bonus for production patterns
1311
- if (code.includes("useCallback") && code.includes("useMemo"))
1312
- score += 5;
1313
- if (code.includes("React.memo") || code.includes("forwardRef"))
1314
- score += 3;
1315
- // Cap at 100
1316
- return Math.min(score, 100);
1317
- }
1318
- generateComponentName(description) {
1319
- // Convert description to PascalCase component name
1320
- return description
1321
- .split(" ")
1322
- .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
1323
- .join("")
1324
- .replace(/[^a-zA-Z0-9]/g, "");
1325
- }
1326
- async generateWithOllama(component, group, options) {
1327
- try {
1328
- const { OllamaClient } = await Promise.resolve().then(() => __importStar(require("../../utils/ollamaClient")));
1329
- const ollamaClient = new OllamaClient(process.env.OLLAMA_BASE_URL || "http://127.0.0.1:11434");
1330
- // Test connection first
1331
- const isConnected = await ollamaClient.testConnection();
1332
- if (!isConnected) {
1333
- throw new Error("Ollama service is not running. Please run 'mycontext setup' to install and start Ollama.");
1334
- }
1335
- // Check if the model exists
1336
- const hasModel = await ollamaClient.hasModel("mycontext-react");
1337
- if (!hasModel) {
1338
- throw new Error("MyContext React model not found. Please run 'mycontext setup' to create the specialized model.");
1339
- }
1340
- return await ollamaClient.generateComponent(JSON.stringify(component), "mycontext-react");
1341
- }
1342
- catch (error) {
1343
- // No fallback - Ollama is required for local AI generation
1344
- throw new Error(`Ollama generation failed: ${error instanceof Error ? error.message : 'Unknown error'}. ` +
1345
- `Please ensure Ollama is running and the 'mycontext-react' model is installed. ` +
1346
- `Run 'mycontext setup' to configure your local AI environment.`);
1347
- }
1348
- }
1349
- async generateWithXAI(component, group, options) {
1350
- try {
1351
- const xaiApiKey = process.env.XAI_API_KEY;
1352
- if (!xaiApiKey) {
1353
- throw new Error("X.AI API key not found");
1354
- }
1355
- const { XAIClient } = await Promise.resolve().then(() => __importStar(require("../../utils/xaiClient")));
1356
- const xaiClient = new XAIClient({
1357
- apiKey: xaiApiKey,
1358
- temperature: options.temperature || 0.6,
1359
- maxTokens: options.maxTokens || 8000,
1360
- });
1361
- return await xaiClient.generateComponent(component, group?.name || "general");
1362
- }
1363
- catch (error) {
1364
- console.warn("X.AI generation failed, falling back to local generation:", error);
1365
- // Fallback to local generation
1366
- return this.generateProductionReadyComponent(component, group, {
1367
- ...options,
1368
- useXAI: false,
1369
- });
1370
- }
1371
- }
1372
- }
1373
- exports.CodeGenSubAgent = CodeGenSubAgent;
1374
- //# sourceMappingURL=CodeGenSubAgent.js.map