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.
- package/README.md +261 -67
- package/dist/agents/communication/AgentCommunicationManager.d.ts +27 -0
- package/dist/agents/communication/AgentCommunicationManager.d.ts.map +1 -0
- package/dist/agents/communication/AgentCommunicationManager.js +293 -0
- package/dist/agents/communication/AgentCommunicationManager.js.map +1 -0
- package/dist/agents/evolution/CodeEvolutionEngine.d.ts +92 -0
- package/dist/agents/evolution/CodeEvolutionEngine.d.ts.map +1 -0
- package/dist/agents/evolution/CodeEvolutionEngine.js +639 -0
- package/dist/agents/evolution/CodeEvolutionEngine.js.map +1 -0
- package/dist/agents/implementations/ArchitectAgent.d.ts +39 -0
- package/dist/agents/implementations/ArchitectAgent.d.ts.map +1 -0
- package/dist/agents/implementations/ArchitectAgent.js +345 -0
- package/dist/agents/implementations/ArchitectAgent.js.map +1 -0
- package/dist/agents/implementations/CodeGenSubAgent.d.ts +12 -0
- package/dist/agents/implementations/CodeGenSubAgent.d.ts.map +1 -1
- package/dist/agents/implementations/CodeGenSubAgent.js +303 -58
- package/dist/agents/implementations/CodeGenSubAgent.js.map +1 -1
- package/dist/agents/implementations/PromptConstructorAgent.d.ts +50 -0
- package/dist/agents/implementations/PromptConstructorAgent.d.ts.map +1 -0
- package/dist/agents/implementations/PromptConstructorAgent.js +481 -0
- package/dist/agents/implementations/PromptConstructorAgent.js.map +1 -0
- package/dist/agents/implementations/SecurityAgent.d.ts +31 -0
- package/dist/agents/implementations/SecurityAgent.d.ts.map +1 -0
- package/dist/agents/implementations/SecurityAgent.js +453 -0
- package/dist/agents/implementations/SecurityAgent.js.map +1 -0
- package/dist/agents/intelligence/ProjectIntelligence.d.ts +127 -0
- package/dist/agents/intelligence/ProjectIntelligence.d.ts.map +1 -0
- package/dist/agents/intelligence/ProjectIntelligence.js +456 -0
- package/dist/agents/intelligence/ProjectIntelligence.js.map +1 -0
- package/dist/agents/interfaces/AgentCommunication.d.ts +65 -0
- package/dist/agents/interfaces/AgentCommunication.d.ts.map +1 -0
- package/dist/agents/interfaces/AgentCommunication.js +13 -0
- package/dist/agents/interfaces/AgentCommunication.js.map +1 -0
- package/dist/agents/learning/CrossProjectLearning.d.ts +99 -0
- package/dist/agents/learning/CrossProjectLearning.d.ts.map +1 -0
- package/dist/agents/learning/CrossProjectLearning.js +517 -0
- package/dist/agents/learning/CrossProjectLearning.js.map +1 -0
- package/dist/cli.js +49 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/agent-flow.d.ts +21 -0
- package/dist/commands/agent-flow.d.ts.map +1 -0
- package/dist/commands/agent-flow.js +225 -0
- package/dist/commands/agent-flow.js.map +1 -0
- package/dist/commands/generate-components.d.ts +0 -13
- package/dist/commands/generate-components.d.ts.map +1 -1
- package/dist/commands/generate-components.js +42 -422
- package/dist/commands/generate-components.js.map +1 -1
- package/dist/commands/generate.d.ts +5 -1
- package/dist/commands/generate.d.ts.map +1 -1
- package/dist/commands/generate.js +381 -23
- package/dist/commands/generate.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +12 -6
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/predict.d.ts +36 -0
- package/dist/commands/predict.d.ts.map +1 -0
- package/dist/commands/predict.js +539 -0
- package/dist/commands/predict.js.map +1 -0
- package/dist/utils/clean.d.ts +6 -0
- package/dist/utils/clean.d.ts.map +1 -0
- package/dist/utils/clean.js +220 -0
- package/dist/utils/clean.js.map +1 -0
- package/dist/utils/githubModelsClient.d.ts.map +1 -1
- package/dist/utils/githubModelsClient.js +33 -16
- package/dist/utils/githubModelsClient.js.map +1 -1
- package/dist/utils/hybridAIClient.d.ts +1 -0
- package/dist/utils/hybridAIClient.d.ts.map +1 -1
- package/dist/utils/hybridAIClient.js +23 -9
- package/dist/utils/hybridAIClient.js.map +1 -1
- package/dist/utils/ollamaClient.d.ts.map +1 -1
- package/dist/utils/ollamaClient.js +6 -4
- package/dist/utils/ollamaClient.js.map +1 -1
- 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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
628
|
-
|
|
629
|
-
|
|
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
|
-
//
|
|
717
|
-
|
|
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
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
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 ${
|
|
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
|
};
|