mycontext-cli 0.4.7 → 0.4.9

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 (73) hide show
  1. package/README.md +261 -67
  2. package/dist/agents/communication/AgentCommunicationManager.d.ts +27 -0
  3. package/dist/agents/communication/AgentCommunicationManager.d.ts.map +1 -0
  4. package/dist/agents/communication/AgentCommunicationManager.js +293 -0
  5. package/dist/agents/communication/AgentCommunicationManager.js.map +1 -0
  6. package/dist/agents/evolution/CodeEvolutionEngine.d.ts +92 -0
  7. package/dist/agents/evolution/CodeEvolutionEngine.d.ts.map +1 -0
  8. package/dist/agents/evolution/CodeEvolutionEngine.js +639 -0
  9. package/dist/agents/evolution/CodeEvolutionEngine.js.map +1 -0
  10. package/dist/agents/implementations/ArchitectAgent.d.ts +39 -0
  11. package/dist/agents/implementations/ArchitectAgent.d.ts.map +1 -0
  12. package/dist/agents/implementations/ArchitectAgent.js +345 -0
  13. package/dist/agents/implementations/ArchitectAgent.js.map +1 -0
  14. package/dist/agents/implementations/CodeGenSubAgent.d.ts +12 -0
  15. package/dist/agents/implementations/CodeGenSubAgent.d.ts.map +1 -1
  16. package/dist/agents/implementations/CodeGenSubAgent.js +303 -58
  17. package/dist/agents/implementations/CodeGenSubAgent.js.map +1 -1
  18. package/dist/agents/implementations/PromptConstructorAgent.d.ts +50 -0
  19. package/dist/agents/implementations/PromptConstructorAgent.d.ts.map +1 -0
  20. package/dist/agents/implementations/PromptConstructorAgent.js +481 -0
  21. package/dist/agents/implementations/PromptConstructorAgent.js.map +1 -0
  22. package/dist/agents/implementations/SecurityAgent.d.ts +31 -0
  23. package/dist/agents/implementations/SecurityAgent.d.ts.map +1 -0
  24. package/dist/agents/implementations/SecurityAgent.js +453 -0
  25. package/dist/agents/implementations/SecurityAgent.js.map +1 -0
  26. package/dist/agents/intelligence/ProjectIntelligence.d.ts +127 -0
  27. package/dist/agents/intelligence/ProjectIntelligence.d.ts.map +1 -0
  28. package/dist/agents/intelligence/ProjectIntelligence.js +456 -0
  29. package/dist/agents/intelligence/ProjectIntelligence.js.map +1 -0
  30. package/dist/agents/interfaces/AgentCommunication.d.ts +65 -0
  31. package/dist/agents/interfaces/AgentCommunication.d.ts.map +1 -0
  32. package/dist/agents/interfaces/AgentCommunication.js +13 -0
  33. package/dist/agents/interfaces/AgentCommunication.js.map +1 -0
  34. package/dist/agents/learning/CrossProjectLearning.d.ts +99 -0
  35. package/dist/agents/learning/CrossProjectLearning.d.ts.map +1 -0
  36. package/dist/agents/learning/CrossProjectLearning.js +517 -0
  37. package/dist/agents/learning/CrossProjectLearning.js.map +1 -0
  38. package/dist/cli.js +49 -0
  39. package/dist/cli.js.map +1 -1
  40. package/dist/commands/agent-flow.d.ts +21 -0
  41. package/dist/commands/agent-flow.d.ts.map +1 -0
  42. package/dist/commands/agent-flow.js +225 -0
  43. package/dist/commands/agent-flow.js.map +1 -0
  44. package/dist/commands/generate-components.d.ts +0 -13
  45. package/dist/commands/generate-components.d.ts.map +1 -1
  46. package/dist/commands/generate-components.js +42 -422
  47. package/dist/commands/generate-components.js.map +1 -1
  48. package/dist/commands/generate.d.ts +5 -1
  49. package/dist/commands/generate.d.ts.map +1 -1
  50. package/dist/commands/generate.js +381 -23
  51. package/dist/commands/generate.js.map +1 -1
  52. package/dist/commands/init.d.ts.map +1 -1
  53. package/dist/commands/init.js +12 -6
  54. package/dist/commands/init.js.map +1 -1
  55. package/dist/commands/predict.d.ts +36 -0
  56. package/dist/commands/predict.d.ts.map +1 -0
  57. package/dist/commands/predict.js +539 -0
  58. package/dist/commands/predict.js.map +1 -0
  59. package/dist/utils/clean.d.ts +6 -0
  60. package/dist/utils/clean.d.ts.map +1 -0
  61. package/dist/utils/clean.js +220 -0
  62. package/dist/utils/clean.js.map +1 -0
  63. package/dist/utils/githubModelsClient.d.ts.map +1 -1
  64. package/dist/utils/githubModelsClient.js +33 -16
  65. package/dist/utils/githubModelsClient.js.map +1 -1
  66. package/dist/utils/hybridAIClient.d.ts +1 -0
  67. package/dist/utils/hybridAIClient.d.ts.map +1 -1
  68. package/dist/utils/hybridAIClient.js +23 -9
  69. package/dist/utils/hybridAIClient.js.map +1 -1
  70. package/dist/utils/ollamaClient.d.ts.map +1 -1
  71. package/dist/utils/ollamaClient.js +6 -4
  72. package/dist/utils/ollamaClient.js.map +1 -1
  73. package/package.json +2 -1
@@ -79,7 +79,14 @@ class GenerateComponentsCommand {
79
79
  }
80
80
  getComponentBaseName(component) {
81
81
  const raw = typeof component === "string" ? component : component?.name;
82
- return this.generateComponentName(String(raw || "Component"));
82
+ const name = String(raw || "Component");
83
+ // Simple PascalCase conversion - no template generation
84
+ return name
85
+ .replace(/[_-]+/g, " ")
86
+ .split(/\s+/)
87
+ .map((w) => w ? w.charAt(0).toUpperCase() + w.slice(1).toLowerCase() : "")
88
+ .join("")
89
+ .replace(/[^A-Za-z0-9]/g, "");
83
90
  }
84
91
  getComponentExportName(component) {
85
92
  return this.getComponentBaseName(component);
@@ -268,6 +275,21 @@ class GenerateComponentsCommand {
268
275
  throw new Error("Component list not found. Run 'mycontext generate components-list' first.");
269
276
  }
270
277
  const componentList = JSON.parse(await this.fs.readFile(componentListPath));
278
+ // Enforce core-first gating: require core.json ready before generating all groups
279
+ if (true) {
280
+ try {
281
+ const coreStatePath = path.join(process.cwd(), ".mycontext", "core.json");
282
+ if (await fs.pathExists(coreStatePath)) {
283
+ const state = await fs.readJson(coreStatePath);
284
+ if (!state?.ready) {
285
+ throw new Error("Core not marked ready. Run 'mycontext core generate' and 'mycontext core ready' before generating all components.");
286
+ }
287
+ }
288
+ }
289
+ catch (e) {
290
+ throw e;
291
+ }
292
+ }
271
293
  const groups = componentList.groups || [];
272
294
  if (groups.length === 0) {
273
295
  throw new Error("No component groups found in component-list.json");
@@ -469,15 +491,8 @@ class GenerateComponentsCommand {
469
491
  }));
470
492
  await this.fs.writeFile(path.join(groupDir, `BrandComp.tsx`), codeResult.code);
471
493
  }
472
- catch {
473
- const code = this.generateComponentCode(brandComp, { name: "Core" }, {
474
- ...options,
475
- context: {
476
- prd: this.contextArtifacts.prd,
477
- types: this.contextArtifacts.types,
478
- },
479
- });
480
- await this.fs.writeFile(path.join(groupDir, `BrandComp.tsx`), code);
494
+ catch (e) {
495
+ throw e;
481
496
  }
482
497
  // Group index and preview
483
498
  await this.generateGroupIndex({
@@ -620,34 +635,13 @@ class GenerateComponentsCommand {
620
635
  },
621
636
  },
622
637
  }),
623
- new Promise((_, reject) => setTimeout(() => reject(new Error("Code generation timed out after 60 seconds")), 60000)),
638
+ new Promise((_, reject) => setTimeout(() => reject(new Error("Code generation timed out after 30 minutes")), 1800000)),
624
639
  ]));
625
640
  }
626
641
  catch (error) {
627
- if (error.message.includes("timed out")) {
628
- console.log(chalk_1.default.yellow(`⚠️ Code generation timed out for ${component.name}`));
629
- console.log(chalk_1.default.gray("Using fallback generation method..."));
630
- const code = this.generateComponentCode(component, group, options);
631
- const fileBase = this.getComponentBaseName(component);
632
- const componentPath = path.join(groupDir, `${fileBase}.tsx`);
633
- await this.fs.writeFile(componentPath, code);
634
- // Store component with fallback data
635
- await this.storeComponent({
636
- userId,
637
- name: component.name,
638
- code,
639
- metadata: {
640
- prompt: component.description || "",
641
- model: "fallback-timeout",
642
- executionTime: Date.now(),
643
- qualityScore: null,
644
- group: group.name,
645
- },
646
- group: group.name,
647
- qualityScore: null,
648
- });
649
- return;
650
- }
642
+ // No fallbacks - propagate the error for clean failure
643
+ console.log(chalk_1.default.red(`❌ AI generation failed for ${component.name}: ${error.message}`));
644
+ console.log(chalk_1.default.yellow(`💡 No generic templates - retry when AI is available!`));
651
645
  throw error;
652
646
  }
653
647
  const fileBase = this.getComponentBaseName(component);
@@ -713,34 +707,8 @@ class GenerateComponentsCommand {
713
707
  });
714
708
  }
715
709
  catch (error) {
716
- // Fallback to original method if sub-agent system fails
717
- console.log(chalk_1.default.yellow(`⚠️ Sub-agent system failed for ${component.name}, using fallback method`));
718
- const enrichedOptions = {
719
- ...options,
720
- context: {
721
- prd: this.contextArtifacts.prd,
722
- types: this.contextArtifacts.types,
723
- },
724
- };
725
- const code = this.generateComponentCode(component, group, enrichedOptions);
726
- const fileBase = this.getComponentBaseName(component);
727
- const componentPath = path.join(groupDir, `${fileBase}.tsx`);
728
- await this.fs.writeFile(componentPath, code);
729
- // Store component with fallback data
730
- await this.storeComponent({
731
- userId,
732
- name: component.name,
733
- code,
734
- metadata: {
735
- prompt: component.description || "",
736
- model: "fallback",
737
- executionTime: Date.now(),
738
- qualityScore: null,
739
- group: group.name,
740
- },
741
- group: group.name,
742
- qualityScore: null,
743
- });
710
+ // Fail hard: no local/template fallback
711
+ throw error;
744
712
  }
745
713
  }
746
714
  /**
@@ -1086,363 +1054,10 @@ class GenerateComponentsCommand {
1086
1054
  }
1087
1055
  }
1088
1056
  }
1089
- generateComponentCode(component, group, options) {
1090
- // Handle both string and object inputs
1091
- let name, description, type, userStories, actionFunctions, dependencies, tags;
1092
- if (typeof component === "string") {
1093
- // Simple string input - create a basic component structure
1094
- name = this.generateComponentName(component);
1095
- description = component;
1096
- type = "form"; // Default type
1097
- userStories = [
1098
- `As a user, I want to use ${name} to ${component.toLowerCase()}`,
1099
- ];
1100
- actionFunctions = ["handleSubmit", "handleChange"];
1101
- dependencies = ["react", "tailwindcss"];
1102
- tags = ["ui", "component"];
1103
- }
1104
- else {
1105
- // Structured component object
1106
- const rawName = String(component?.name || "Component");
1107
- name = this.generateComponentName(rawName);
1108
- description = String(component?.description || "");
1109
- type = String(component?.type || "form");
1110
- userStories = Array.isArray(component?.userStories)
1111
- ? component.userStories
1112
- : [];
1113
- actionFunctions = Array.isArray(component?.actionFunctions)
1114
- ? component.actionFunctions
1115
- : [];
1116
- dependencies = Array.isArray(component?.dependencies)
1117
- ? component.dependencies
1118
- : [];
1119
- tags = Array.isArray(component?.tags) ? component.tags : [];
1120
- }
1121
- // Ensure robust defaults for template rendering
1122
- if (!Array.isArray(userStories))
1123
- userStories = [];
1124
- if (!Array.isArray(actionFunctions))
1125
- actionFunctions = [];
1126
- if (!Array.isArray(dependencies))
1127
- dependencies = [];
1128
- if (!Array.isArray(tags))
1129
- tags = [];
1130
- type = String(type || "form");
1131
- // Read branding for styling
1132
- const brandingPath = "context/branding.json";
1133
- let branding = {};
1134
- try {
1135
- if (fs.existsSync(brandingPath)) {
1136
- branding = JSON.parse(fs.readFileSync(brandingPath, "utf8"));
1137
- }
1138
- }
1139
- catch (error) {
1140
- // Use default branding if file doesn't exist
1141
- }
1142
- const planned = this.findComponentPlan(group?.name || "", name) || {};
1143
- const plannedContext = Array.isArray(planned?.acceptanceCriteria)
1144
- ? planned.acceptanceCriteria
1145
- .slice(0, 5)
1146
- .map((s) => ` * - ${String(s)}`)
1147
- .join("\n")
1148
- : "";
1149
- const prdContext = options?.context?.prd || "";
1150
- const typesContext = options?.context?.types || "";
1151
- return `"use client";
1152
-
1153
- import React from "react";
1154
- import { cn } from "@/lib/utils";
1155
- import { Card, CardHeader, CardTitle, CardContent } from "@/components/ui/card";
1156
- import { Button } from "@/components/ui/button";
1157
-
1158
- /**
1159
- * ${name} Component
1160
- *
1161
- * ${description}
1162
- *
1163
- * User Stories:
1164
- ${userStories.map((story) => ` * - ${story}`).join("\n")}
1165
- *
1166
- * Action Functions:
1167
- ${actionFunctions.map((func) => ` * - ${func}`).join("\n")}
1168
- *
1169
- * Dependencies: ${dependencies.join(", ")}
1170
- * Tags: ${tags.join(", ")}
1171
- *
1172
- * Context Snapshot (PRD excerpt):
1173
- * ${prdContext
1174
- .split("\n")
1175
- .slice(0, 5)
1176
- .map((l) => ` * ${l}`)
1177
- .join("\n")}
1178
- *
1179
- * Types Snapshot (excerpt):
1180
- * ${typesContext
1181
- .split("\n")
1182
- .slice(0, 5)
1183
- .map((l) => ` * ${l}`)
1184
- .join("\n")}
1185
- *
1186
- * Planned Acceptance Criteria:
1187
- ${plannedContext || " * - (none)"}
1188
- */
1189
-
1190
- interface ${name}Props {
1191
- className?: string;
1192
- // Add specific props based on component type
1193
- ${this.generatePropsForType(type)}
1194
- }
1195
-
1196
- export function ${name}({
1197
- className,
1198
- ${this.generatePropsDestructuring(type)}
1199
- ...props
1200
- }: ${name}Props) {
1201
- ${this.generateComponentLogic(type, actionFunctions)}
1202
-
1203
- return (
1204
- <Card className={cn("${this.generateBaseClasses(type, branding)}", className)} {...props}>
1205
- <CardHeader>
1206
- <CardTitle>${name}</CardTitle>
1207
- </CardHeader>
1208
- <CardContent>
1209
- ${this.generateComponentJSX(type, name)}
1210
- </CardContent>
1211
- </Card>
1212
- );
1213
- }
1214
-
1215
- ${this.generateActionFunctions(actionFunctions, name)}
1216
-
1217
- export default ${name};
1218
- `;
1219
- }
1220
- generateComponentName(description) {
1221
- // Preserve existing PascalCase names; otherwise convert to PascalCase
1222
- const trimmed = description.trim();
1223
- if (/^[A-Z][A-Za-z0-9]*$/.test(trimmed))
1224
- return trimmed;
1225
- return trimmed
1226
- .replace(/[_-]+/g, " ")
1227
- .split(/\s+/)
1228
- .map((w) => w ? w.charAt(0).toUpperCase() + w.slice(1).toLowerCase() : "")
1229
- .join("")
1230
- .replace(/[^A-Za-z0-9]/g, "");
1231
- }
1232
- generatePropsForType(type) {
1233
- switch (type) {
1234
- case "form":
1235
- return `
1236
- onSubmit?: (data: any) => void;
1237
- loading?: boolean;
1238
- error?: string;`;
1239
- case "layout":
1240
- return `
1241
- children: React.ReactNode;
1242
- sidebar?: React.ReactNode;`;
1243
- case "card":
1244
- return `
1245
- title?: string;
1246
- content?: React.ReactNode;
1247
- actions?: React.ReactNode;`;
1248
- case "button":
1249
- return `
1250
- variant?: "default" | "destructive" | "outline" | "secondary" | "ghost" | "link";
1251
- size?: "default" | "sm" | "lg" | "icon";
1252
- disabled?: boolean;
1253
- onClick?: () => void;`;
1254
- default:
1255
- return `
1256
- // Add component-specific props here`;
1257
- }
1258
- }
1259
- generatePropsDestructuring(type) {
1260
- switch (type) {
1261
- case "form":
1262
- return `
1263
- onSubmit,
1264
- loading = false,
1265
- error,`;
1266
- case "layout":
1267
- return `
1268
- children,
1269
- sidebar,`;
1270
- case "card":
1271
- return `
1272
- title,
1273
- content,
1274
- actions,`;
1275
- case "button":
1276
- return `
1277
- variant = "default",
1278
- size = "default",
1279
- disabled = false,
1280
- onClick,`;
1281
- default:
1282
- return "";
1283
- }
1284
- }
1285
- generateComponentLogic(type, actionFunctions) {
1286
- const logic = [];
1287
- if (type === "form") {
1288
- logic.push(`
1289
- const [formData, setFormData] = React.useState({});
1290
- const [isSubmitting, setIsSubmitting] = React.useState(false);`);
1291
- }
1292
- if (type === "form") {
1293
- logic.push(`
1294
- const handleSubmit = async (e: React.FormEvent) => {
1295
- e.preventDefault();
1296
- setIsSubmitting(true);
1297
- try {
1298
- onSubmit?.(formData);
1299
- } catch (error) {
1300
- console.error("Form submission error:", error);
1301
- } finally {
1302
- setIsSubmitting(false);
1303
- }
1304
- };`);
1305
- }
1306
- return logic.join("\n");
1307
- }
1308
- generateBaseClasses(type, branding) {
1309
- const baseClasses = [];
1310
- // Normalize and sanitize type
1311
- const normalizedType = String(type || "")
1312
- .toLowerCase()
1313
- .replace(/\s+/g, "-");
1314
- switch (normalizedType) {
1315
- case "form":
1316
- baseClasses.push("space-y-4", "w-full", "max-w-md");
1317
- break;
1318
- case "layout":
1319
- baseClasses.push("min-h-screen", "flex", "flex-col");
1320
- break;
1321
- case "card":
1322
- baseClasses.push("rounded-lg", "border", "bg-card", "p-6", "shadow-sm");
1323
- break;
1324
- case "button":
1325
- baseClasses.push("inline-flex", "items-center", "justify-center", "rounded-md", "text-sm", "font-medium", "transition-colors", "focus-visible:outline-none", "focus-visible:ring-2", "focus-visible:ring-ring", "focus-visible:ring-offset-2", "disabled:opacity-50", "disabled:pointer-events-none");
1326
- break;
1327
- default:
1328
- baseClasses.push("w-full");
1329
- }
1330
- return baseClasses.join(" ");
1331
- }
1332
- generateComponentJSX(type, name) {
1333
- const normalizedType = String(type || "")
1334
- .toLowerCase()
1335
- .replace(/\s+/g, "-");
1336
- switch (normalizedType) {
1337
- case "form":
1338
- return `
1339
- {/* Example domain-agnostic form scaffold. Replace fields per component plan. */}
1340
- <form onSubmit={handleSubmit} className="space-y-4">
1341
- <div className="space-y-2">
1342
- <label htmlFor="field1" className="text-sm font-medium">Field 1</label>
1343
- <input id="field1" className="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50" placeholder="Type here" />
1344
- </div>
1345
- {error ? <div className="text-sm text-destructive">{error}</div> : null}
1346
- <button
1347
- type="submit"
1348
- disabled={loading || isSubmitting}
1349
- className="inline-flex h-10 items-center justify-center rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground ring-offset-background transition-colors hover:bg-primary/90 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50"
1350
- >
1351
- {loading || isSubmitting ? "Submitting..." : "Submit"}
1352
- </button>
1353
- </form>`;
1354
- case "layout":
1355
- return `
1356
- <header className="border-b bg-background">
1357
- <div className="container mx-auto px-4 py-4">
1358
- <h1 className="text-2xl font-bold">${name}</h1>
1359
- </div>
1360
- </header>
1361
- <main className="flex-1">
1362
- <div className="container mx-auto px-4 py-8">
1363
- {children}
1364
- </div>
1365
- </main>
1366
- <footer className="border-t bg-background">
1367
- <div className="container mx-auto px-4 py-4 text-center text-sm text-muted-foreground">
1368
- © 2024 MyContext. All rights reserved.
1369
- </div>
1370
- </footer>`;
1371
- case "card":
1372
- return `
1373
- {title && (
1374
- <h3 className="text-lg font-semibold leading-none tracking-tight">
1375
- {title}
1376
- </h3>
1377
- )}
1378
- {content && (
1379
- <div className="mt-4">
1380
- {content}
1381
- </div>
1382
- )}
1383
- {actions && (
1384
- <div className="mt-4 flex justify-end space-x-2">
1385
- {actions}
1386
- </div>
1387
- )}`;
1388
- case "button":
1389
- return `
1390
- <span className="sr-only">${name}</span>
1391
- <span>${name}</span>`;
1392
- default:
1393
- return `
1394
- <div className="p-4">
1395
- <h3 className="text-lg font-semibold">${name}</h3>
1396
- <p className="text-sm text-muted-foreground">
1397
- This is a ${type} component. Customize it based on your needs.
1398
- </p>
1399
- </div>`;
1400
- }
1401
- }
1402
- generateActionFunctions(actionFunctions, componentName) {
1403
- if (actionFunctions.length === 0)
1404
- return "";
1405
- const functions = actionFunctions.map((func) => {
1406
- switch (func) {
1407
- case "handleSubmit":
1408
- return `// Already implemented in component logic`;
1409
- case "handleLogin":
1410
- return `
1411
- export async function handleLogin(email: string, password: string) {
1412
- // Implement login logic in application layer
1413
- console.log("Logging in with:", { email, password });
1414
- return { success: true };
1415
- }`;
1416
- case "handleSignup":
1417
- return `
1418
- export async function handleSignup(email: string, password: string, name: string) {
1419
- // Implement signup logic in application layer
1420
- console.log("Signing up with:", { email, password, name });
1421
- return { success: true };
1422
- }`;
1423
- case "validateEmail":
1424
- return `
1425
- export function validateEmail(email: string): boolean {
1426
- const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;
1427
- return emailRegex.test(email);
1428
- }`;
1429
- case "checkUsername":
1430
- return `
1431
- export async function checkUsername(username: string): Promise<boolean> {
1432
- // Implement username availability check in application layer
1433
- console.log("Checking username:", username);
1434
- return true;
1435
- }`;
1436
- default:
1437
- return `
1438
- export function ${func}() {
1439
- // Implement ${func} logic in application layer
1440
- console.log("${func} called");
1441
- }`;
1442
- }
1443
- });
1444
- return functions.join("\n");
1445
- }
1057
+ // REMOVED: All generic template generation
1058
+ // Components are now 100% generated by AI using context files and sub-agents
1059
+ // REMOVED: Template generation methods
1060
+ // All components now generated by AI with context analysis
1446
1061
  async generateGroupIndex(group, groupDir) {
1447
1062
  const components = group.components || [];
1448
1063
  const exports = components.map((comp) => {
@@ -1479,7 +1094,12 @@ ${components
1479
1094
  })
1480
1095
  .join("\n")}
1481
1096
 
1482
- export default function ${this.generateComponentName(String(group.name || "Group"))}Preview() {
1097
+ export default function ${String(group.name || "Group")
1098
+ .replace(/[_-]+/g, " ")
1099
+ .split(/\s+/)
1100
+ .map((w) => w ? w.charAt(0).toUpperCase() + w.slice(1).toLowerCase() : "")
1101
+ .join("")
1102
+ .replace(/[^A-Za-z0-9]/g, "")}Preview() {
1483
1103
  return (
1484
1104
  <div className="container mx-auto p-8 space-y-8">
1485
1105
  <div className="text-center">
@@ -1545,7 +1165,7 @@ import { previewProps } from './preview-props';
1545
1165
 
1546
1166
  export type PreviewRegistryItem = {
1547
1167
  group: string;
1548
- name: string;
1168
+ name: string;
1549
1169
  path: string;
1550
1170
  loader: () => Promise<any>;
1551
1171
  };