mycontext-cli 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +440 -0
- package/dist/cli/src/agents/implementations/CodeGenSubAgent.d.ts +43 -0
- package/dist/cli/src/agents/implementations/CodeGenSubAgent.d.ts.map +1 -0
- package/dist/cli/src/agents/implementations/CodeGenSubAgent.js +1440 -0
- package/dist/cli/src/agents/implementations/CodeGenSubAgent.js.map +1 -0
- package/dist/cli/src/agents/implementations/DocsSubAgent.d.ts +35 -0
- package/dist/cli/src/agents/implementations/DocsSubAgent.d.ts.map +1 -0
- package/dist/cli/src/agents/implementations/DocsSubAgent.js +351 -0
- package/dist/cli/src/agents/implementations/DocsSubAgent.js.map +1 -0
- package/dist/cli/src/agents/implementations/QASubAgent.d.ts +31 -0
- package/dist/cli/src/agents/implementations/QASubAgent.d.ts.map +1 -0
- package/dist/cli/src/agents/implementations/QASubAgent.js +190 -0
- package/dist/cli/src/agents/implementations/QASubAgent.js.map +1 -0
- package/dist/cli/src/agents/interfaces/SubAgent.d.ts +157 -0
- package/dist/cli/src/agents/interfaces/SubAgent.d.ts.map +1 -0
- package/dist/cli/src/agents/interfaces/SubAgent.js +7 -0
- package/dist/cli/src/agents/interfaces/SubAgent.js.map +1 -0
- package/dist/cli/src/agents/orchestrator/SubAgentOrchestrator.d.ts +59 -0
- package/dist/cli/src/agents/orchestrator/SubAgentOrchestrator.d.ts.map +1 -0
- package/dist/cli/src/agents/orchestrator/SubAgentOrchestrator.js +305 -0
- package/dist/cli/src/agents/orchestrator/SubAgentOrchestrator.js.map +1 -0
- package/dist/cli/src/agents/personalities/definitions.d.ts +34 -0
- package/dist/cli/src/agents/personalities/definitions.d.ts.map +1 -0
- package/dist/cli/src/agents/personalities/definitions.js +360 -0
- package/dist/cli/src/agents/personalities/definitions.js.map +1 -0
- package/dist/cli/src/cli.d.ts +3 -0
- package/dist/cli/src/cli.d.ts.map +1 -0
- package/dist/cli/src/cli.js +286 -0
- package/dist/cli/src/cli.js.map +1 -0
- package/dist/cli/src/commands/auth.d.ts +23 -0
- package/dist/cli/src/commands/auth.d.ts.map +1 -0
- package/dist/cli/src/commands/auth.js +212 -0
- package/dist/cli/src/commands/auth.js.map +1 -0
- package/dist/cli/src/commands/generate-components.d.ts +28 -0
- package/dist/cli/src/commands/generate-components.d.ts.map +1 -0
- package/dist/cli/src/commands/generate-components.js +680 -0
- package/dist/cli/src/commands/generate-components.js.map +1 -0
- package/dist/cli/src/commands/generate.d.ts +108 -0
- package/dist/cli/src/commands/generate.d.ts.map +1 -0
- package/dist/cli/src/commands/generate.js +1984 -0
- package/dist/cli/src/commands/generate.js.map +1 -0
- package/dist/cli/src/commands/init.d.ts +13 -0
- package/dist/cli/src/commands/init.d.ts.map +1 -0
- package/dist/cli/src/commands/init.js +91 -0
- package/dist/cli/src/commands/init.js.map +1 -0
- package/dist/cli/src/commands/list.d.ts +17 -0
- package/dist/cli/src/commands/list.d.ts.map +1 -0
- package/dist/cli/src/commands/list.js +209 -0
- package/dist/cli/src/commands/list.js.map +1 -0
- package/dist/cli/src/commands/preview.d.ts +23 -0
- package/dist/cli/src/commands/preview.d.ts.map +1 -0
- package/dist/cli/src/commands/preview.js +1200 -0
- package/dist/cli/src/commands/preview.js.map +1 -0
- package/dist/cli/src/commands/status.d.ts +21 -0
- package/dist/cli/src/commands/status.d.ts.map +1 -0
- package/dist/cli/src/commands/status.js +287 -0
- package/dist/cli/src/commands/status.js.map +1 -0
- package/dist/cli/src/commands/validate.d.ts +22 -0
- package/dist/cli/src/commands/validate.d.ts.map +1 -0
- package/dist/cli/src/commands/validate.js +259 -0
- package/dist/cli/src/commands/validate.js.map +1 -0
- package/dist/cli/src/types/index.d.ts +152 -0
- package/dist/cli/src/types/index.d.ts.map +1 -0
- package/dist/cli/src/types/index.js +3 -0
- package/dist/cli/src/types/index.js.map +1 -0
- package/dist/cli/src/utils/apiKeyManager.d.ts +137 -0
- package/dist/cli/src/utils/apiKeyManager.d.ts.map +1 -0
- package/dist/cli/src/utils/apiKeyManager.js +471 -0
- package/dist/cli/src/utils/apiKeyManager.js.map +1 -0
- package/dist/cli/src/utils/errorHandler.d.ts +105 -0
- package/dist/cli/src/utils/errorHandler.d.ts.map +1 -0
- package/dist/cli/src/utils/errorHandler.js +332 -0
- package/dist/cli/src/utils/errorHandler.js.map +1 -0
- package/dist/cli/src/utils/fileSystem.d.ts +58 -0
- package/dist/cli/src/utils/fileSystem.d.ts.map +1 -0
- package/dist/cli/src/utils/fileSystem.js +230 -0
- package/dist/cli/src/utils/fileSystem.js.map +1 -0
- package/dist/cli/src/utils/githubModels.d.ts +53 -0
- package/dist/cli/src/utils/githubModels.d.ts.map +1 -0
- package/dist/cli/src/utils/githubModels.js +239 -0
- package/dist/cli/src/utils/githubModels.js.map +1 -0
- package/dist/cli/src/utils/spinner.d.ts +28 -0
- package/dist/cli/src/utils/spinner.d.ts.map +1 -0
- package/dist/cli/src/utils/spinner.js +112 -0
- package/dist/cli/src/utils/spinner.js.map +1 -0
- package/dist/cli/src/utils/xaiClient.d.ts +59 -0
- package/dist/cli/src/utils/xaiClient.d.ts.map +1 -0
- package/dist/cli/src/utils/xaiClient.js +244 -0
- package/dist/cli/src/utils/xaiClient.js.map +1 -0
- package/dist/lib/analytics/usage-tracker.d.ts +125 -0
- package/dist/lib/analytics/usage-tracker.d.ts.map +1 -0
- package/dist/lib/analytics/usage-tracker.js +429 -0
- package/dist/lib/analytics/usage-tracker.js.map +1 -0
- package/package.json +64 -0
|
@@ -0,0 +1,1984 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.GenerateCommand = void 0;
|
|
40
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
41
|
+
const prompts_1 = __importDefault(require("prompts"));
|
|
42
|
+
const path_1 = __importDefault(require("path"));
|
|
43
|
+
const spinner_1 = require("../utils/spinner");
|
|
44
|
+
const fileSystem_1 = require("../utils/fileSystem");
|
|
45
|
+
class GenerateCommand {
|
|
46
|
+
constructor() {
|
|
47
|
+
this.fs = new fileSystem_1.FileSystemManager();
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Sanitizes a group name for use as a directory or route segment.
|
|
51
|
+
* - Lowercase
|
|
52
|
+
* - Replace spaces and & with dashes
|
|
53
|
+
* - Remove all other special characters
|
|
54
|
+
* - Collapse multiple dashes
|
|
55
|
+
* - Trim leading/trailing dashes
|
|
56
|
+
*/
|
|
57
|
+
sanitizeGroupName(name) {
|
|
58
|
+
return name
|
|
59
|
+
.toLowerCase()
|
|
60
|
+
.replace(/\s+/g, "-") // Replace spaces with dash
|
|
61
|
+
.replace(/\s*&\s*/g, "-") // Replace spaces and & with dash
|
|
62
|
+
.replace(/[^a-z0-9-]/g, "") // Remove all non-alphanumeric/dash
|
|
63
|
+
.replace(/-+/g, "-") // Collapse multiple dashes
|
|
64
|
+
.replace(/^-+|-+$/g, ""); // Trim leading/trailing dashes
|
|
65
|
+
}
|
|
66
|
+
async execute(target, options) {
|
|
67
|
+
const spinner = new spinner_1.EnhancedSpinner("Generating content...");
|
|
68
|
+
const startTime = Date.now();
|
|
69
|
+
let success = false;
|
|
70
|
+
let error;
|
|
71
|
+
try {
|
|
72
|
+
console.log(chalk_1.default.blue.bold("🚀 MyContext Generation\n"));
|
|
73
|
+
// Determine generation type
|
|
74
|
+
const generationType = options.type || target;
|
|
75
|
+
switch (generationType) {
|
|
76
|
+
case "context":
|
|
77
|
+
await this.generateContext(options, spinner);
|
|
78
|
+
break;
|
|
79
|
+
case "types":
|
|
80
|
+
await this.generateTypes(options, spinner);
|
|
81
|
+
break;
|
|
82
|
+
case "brand":
|
|
83
|
+
await this.generateBrand(options, spinner);
|
|
84
|
+
break;
|
|
85
|
+
case "components-list":
|
|
86
|
+
await this.generateComponentsList(options, spinner);
|
|
87
|
+
break;
|
|
88
|
+
case "components":
|
|
89
|
+
await this.generateComponents(options, spinner);
|
|
90
|
+
break;
|
|
91
|
+
case "app-structure":
|
|
92
|
+
await this.generateAppStructure(options, spinner);
|
|
93
|
+
break;
|
|
94
|
+
default:
|
|
95
|
+
throw new Error(`Unknown generation type: ${generationType}`);
|
|
96
|
+
}
|
|
97
|
+
success = true;
|
|
98
|
+
}
|
|
99
|
+
catch (err) {
|
|
100
|
+
error = err instanceof Error ? err.message : "Unknown error";
|
|
101
|
+
spinner.error({ text: "Generation failed" });
|
|
102
|
+
throw err;
|
|
103
|
+
}
|
|
104
|
+
finally {
|
|
105
|
+
// Track CLI generation event
|
|
106
|
+
const executionTime = Date.now() - startTime;
|
|
107
|
+
const userId = process.env.DEFAULT_USER_ID || "cli-user";
|
|
108
|
+
try {
|
|
109
|
+
// Import usage tracker dynamically to avoid CLI dependency issues
|
|
110
|
+
const { usageTracker } = await Promise.resolve().then(() => __importStar(require("../../../lib/analytics/usage-tracker")));
|
|
111
|
+
await usageTracker.trackCLIGeneration(userId, target, "cli", success, executionTime, error);
|
|
112
|
+
}
|
|
113
|
+
catch (trackingError) {
|
|
114
|
+
console.log(chalk_1.default.yellow("⚠️ Analytics tracking failed:", trackingError));
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
async generateContext(options, spinner) {
|
|
119
|
+
spinner.updateText("Generating project context...");
|
|
120
|
+
// Get project description
|
|
121
|
+
let description = "";
|
|
122
|
+
if (!options.yes) {
|
|
123
|
+
const response = await (0, prompts_1.default)({
|
|
124
|
+
type: "text",
|
|
125
|
+
name: "description",
|
|
126
|
+
message: "Project description:",
|
|
127
|
+
validate: (value) => value.length > 10 || "Description must be at least 10 characters",
|
|
128
|
+
});
|
|
129
|
+
description = response.description;
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
// For non-interactive mode, use a default description or read from project config
|
|
133
|
+
try {
|
|
134
|
+
// Try to read from project config first
|
|
135
|
+
const configPath = ".mycontext/config.json";
|
|
136
|
+
const configContent = await this.fs.readFile(configPath);
|
|
137
|
+
const config = JSON.parse(configContent);
|
|
138
|
+
description =
|
|
139
|
+
config.description ||
|
|
140
|
+
"A simple application for testing AI generation flow";
|
|
141
|
+
}
|
|
142
|
+
catch {
|
|
143
|
+
// Fallback to a generic description
|
|
144
|
+
description = "A simple application for testing AI generation flow";
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
// Generate context files using API
|
|
148
|
+
const contextFiles = await this.callGenerationAPI("context", description, options);
|
|
149
|
+
// Write files to filesystem
|
|
150
|
+
await this.writeContextFiles(contextFiles);
|
|
151
|
+
spinner.success({ text: "Context files generated successfully!" });
|
|
152
|
+
console.log(chalk_1.default.green("\n✅ Generated Files:"));
|
|
153
|
+
Object.keys(contextFiles).forEach((filename) => {
|
|
154
|
+
console.log(chalk_1.default.gray(` • ${filename}`));
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
async generateTypes(options, spinner) {
|
|
158
|
+
spinner.updateText("Generating TypeScript types...");
|
|
159
|
+
// Read PRD for context
|
|
160
|
+
const prdPath = await this.findPRDFile();
|
|
161
|
+
if (!prdPath) {
|
|
162
|
+
throw new Error('No PRD found. Run "mycontext generate context" first.');
|
|
163
|
+
}
|
|
164
|
+
const prdContent = await this.fs.readFile(prdPath);
|
|
165
|
+
// Generate types using API
|
|
166
|
+
const typesContent = await this.callGenerationAPI("types", prdContent, options);
|
|
167
|
+
// Write types file
|
|
168
|
+
await this.fs.writeFile("context/types.ts", typesContent);
|
|
169
|
+
spinner.success({ text: "TypeScript types generated successfully!" });
|
|
170
|
+
}
|
|
171
|
+
async generateBrand(options, spinner) {
|
|
172
|
+
spinner.updateText("Generating branding guidelines...");
|
|
173
|
+
// Read PRD for context
|
|
174
|
+
const prdPath = await this.findPRDFile();
|
|
175
|
+
if (!prdPath) {
|
|
176
|
+
throw new Error('No PRD found. Run "mycontext generate context" first.');
|
|
177
|
+
}
|
|
178
|
+
const prdContent = await this.fs.readFile(prdPath);
|
|
179
|
+
// Generate branding using API (returns { markdown, json })
|
|
180
|
+
const branding = await this.callGenerationAPI("brand", prdContent, options);
|
|
181
|
+
// Write branding files
|
|
182
|
+
await this.fs.writeFile("context/branding.md", branding.markdown);
|
|
183
|
+
await this.fs.writeFile("context/branding.json", JSON.stringify(branding.json, null, 2));
|
|
184
|
+
spinner.success({ text: "Branding guidelines generated successfully!" });
|
|
185
|
+
console.log(chalk_1.default.green("\n✅ Generated Files:"));
|
|
186
|
+
console.log(chalk_1.default.gray(" • branding.md"));
|
|
187
|
+
console.log(chalk_1.default.gray(" • branding.json"));
|
|
188
|
+
}
|
|
189
|
+
async generateComponentsList(options, spinner) {
|
|
190
|
+
spinner.updateText("Generating comprehensive component list...");
|
|
191
|
+
// Read context files for comprehensive analysis
|
|
192
|
+
const contextFiles = await this.readContextFiles();
|
|
193
|
+
const prdContent = contextFiles["context/01_PRD.md"] || "";
|
|
194
|
+
const userStoriesContent = contextFiles["context/02_user_stories.md"] || "";
|
|
195
|
+
const typesContent = contextFiles["context/types.ts"] || "";
|
|
196
|
+
// Combine context for analysis
|
|
197
|
+
const fullContext = `
|
|
198
|
+
PRD: ${prdContent}
|
|
199
|
+
User Stories: ${userStoriesContent}
|
|
200
|
+
Types: ${typesContent}
|
|
201
|
+
`.trim();
|
|
202
|
+
// Use local generation for component list (more reliable than API workflow)
|
|
203
|
+
const componentListData = await this.generateLocalComponentsList(fullContext);
|
|
204
|
+
// Write both JSON and Markdown versions
|
|
205
|
+
await this.fs.writeFile("context/component-list.json", JSON.stringify(componentListData, null, 2));
|
|
206
|
+
// Generate Markdown version for human review
|
|
207
|
+
const markdownContent = this.generateComponentListMarkdown(componentListData);
|
|
208
|
+
await this.fs.writeFile("context/component-list.md", markdownContent);
|
|
209
|
+
spinner.success({ text: "Component list generated successfully!" });
|
|
210
|
+
console.log(chalk_1.default.green("\n✅ Generated Files:"));
|
|
211
|
+
console.log(chalk_1.default.gray(" • component-list.json"));
|
|
212
|
+
console.log(chalk_1.default.gray(" • component-list.md"));
|
|
213
|
+
// Show summary
|
|
214
|
+
if (componentListData.groups) {
|
|
215
|
+
console.log(chalk_1.default.blue("\n📋 Component Groups:"));
|
|
216
|
+
componentListData.groups.forEach((group) => {
|
|
217
|
+
console.log(chalk_1.default.gray(` • ${group.name} (${group.components?.length || 0} components)`));
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
async generateComponents(options, spinner) {
|
|
222
|
+
spinner.updateText("Generating components...");
|
|
223
|
+
// Read component list for context
|
|
224
|
+
const componentListPath = "context/component-list.json";
|
|
225
|
+
let componentList;
|
|
226
|
+
try {
|
|
227
|
+
const componentListContent = await this.fs.readFile(componentListPath);
|
|
228
|
+
componentList = JSON.parse(componentListContent);
|
|
229
|
+
}
|
|
230
|
+
catch {
|
|
231
|
+
throw new Error('No component list found. Run "mycontext generate components-list" first.');
|
|
232
|
+
}
|
|
233
|
+
// Create components directory
|
|
234
|
+
const componentsDir = "components/generated";
|
|
235
|
+
await this.fs.ensureDir(componentsDir);
|
|
236
|
+
// Generate each component using the sub-agent system
|
|
237
|
+
const generatedComponents = [];
|
|
238
|
+
for (const group of componentList.groups || []) {
|
|
239
|
+
const groupDir = path_1.default.join(componentsDir, this.sanitizeGroupName(group.name));
|
|
240
|
+
await this.fs.ensureDir(groupDir);
|
|
241
|
+
for (const component of group.components || []) {
|
|
242
|
+
try {
|
|
243
|
+
// Generate component using CodeGenSubAgent
|
|
244
|
+
const componentResult = await this.callGenerationAPI("component", JSON.stringify({ component, group, options }), options);
|
|
245
|
+
// Extract the component code from the result
|
|
246
|
+
let componentCode;
|
|
247
|
+
if (Array.isArray(componentResult) && componentResult.length > 0) {
|
|
248
|
+
// Result is an array from generateLocalComponents
|
|
249
|
+
componentCode = componentResult[0].code || componentResult[0];
|
|
250
|
+
}
|
|
251
|
+
else if (typeof componentResult === "object" &&
|
|
252
|
+
componentResult.code) {
|
|
253
|
+
// Result is an object with code property
|
|
254
|
+
componentCode = componentResult.code;
|
|
255
|
+
}
|
|
256
|
+
else if (typeof componentResult === "string") {
|
|
257
|
+
// Result is a string
|
|
258
|
+
componentCode = componentResult;
|
|
259
|
+
}
|
|
260
|
+
else {
|
|
261
|
+
throw new Error(`Invalid component result format for ${component.name}`);
|
|
262
|
+
}
|
|
263
|
+
// Write component file
|
|
264
|
+
const componentPath = path_1.default.join(groupDir, `${component.name}.tsx`);
|
|
265
|
+
await this.fs.writeFile(componentPath, componentCode);
|
|
266
|
+
generatedComponents.push({
|
|
267
|
+
name: component.name,
|
|
268
|
+
type: component.type,
|
|
269
|
+
path: componentPath,
|
|
270
|
+
});
|
|
271
|
+
console.log(chalk_1.default.gray(` • ${component.name} (${component.type})`));
|
|
272
|
+
}
|
|
273
|
+
catch (error) {
|
|
274
|
+
console.log(chalk_1.default.red(` ❌ Failed to generate ${component.name}: ${error}`));
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
// Generate group index file
|
|
278
|
+
const indexContent = this.generateGroupIndex(group);
|
|
279
|
+
const indexPath = path_1.default.join(groupDir, "index.ts");
|
|
280
|
+
await this.fs.writeFile(indexPath, indexContent);
|
|
281
|
+
}
|
|
282
|
+
spinner.success({ text: "Components generated successfully!" });
|
|
283
|
+
console.log(chalk_1.default.green("\n✅ Generated Components:"));
|
|
284
|
+
generatedComponents.forEach((component) => {
|
|
285
|
+
console.log(chalk_1.default.gray(` • ${component.name} (${component.type})`));
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
generateGroupIndex(group) {
|
|
289
|
+
const components = group.components || [];
|
|
290
|
+
const imports = components
|
|
291
|
+
.map((comp) => `export { ${comp.name} } from './${comp.name}';`)
|
|
292
|
+
.join("\n");
|
|
293
|
+
return `// ${group.name} Components
|
|
294
|
+
${imports}
|
|
295
|
+
|
|
296
|
+
// Group metadata
|
|
297
|
+
export const groupMetadata = {
|
|
298
|
+
name: "${group.name}",
|
|
299
|
+
description: "${group.description || ""}",
|
|
300
|
+
priority: "${group.priority || "medium"}",
|
|
301
|
+
componentCount: ${components.length},
|
|
302
|
+
};
|
|
303
|
+
`;
|
|
304
|
+
}
|
|
305
|
+
async generateAppStructure(options, spinner) {
|
|
306
|
+
spinner.updateText("Generating app structure...");
|
|
307
|
+
// Read context files
|
|
308
|
+
const contextFiles = await this.readContextFiles();
|
|
309
|
+
// Generate app structure using API
|
|
310
|
+
const appStructure = await this.callGenerationAPI("app-structure", JSON.stringify(contextFiles), options);
|
|
311
|
+
// Write app structure file
|
|
312
|
+
await this.fs.writeFile("context/app-structure.json", JSON.stringify(appStructure, null, 2));
|
|
313
|
+
spinner.success({ text: "App structure generated successfully!" });
|
|
314
|
+
}
|
|
315
|
+
async callGenerationAPI(type, context, options) {
|
|
316
|
+
// Try X.AI first if specified, then GitHub Models, then fallback to local API
|
|
317
|
+
const xaiApiKey = process.env.XAI_API_KEY;
|
|
318
|
+
const githubToken = process.env.GITHUB_TOKEN;
|
|
319
|
+
// X.AI Priority (if explicitly requested or available)
|
|
320
|
+
if (options.useXAI && xaiApiKey) {
|
|
321
|
+
try {
|
|
322
|
+
const { XAIClient } = await Promise.resolve().then(() => __importStar(require("../utils/xaiClient")));
|
|
323
|
+
const xaiClient = new XAIClient({
|
|
324
|
+
apiKey: xaiApiKey,
|
|
325
|
+
temperature: options.temperature || 0.7,
|
|
326
|
+
maxTokens: options.maxTokens || 4000,
|
|
327
|
+
});
|
|
328
|
+
// Test connection first
|
|
329
|
+
const isConnected = await xaiClient.testConnection();
|
|
330
|
+
if (!isConnected) {
|
|
331
|
+
throw new Error("X.AI connection failed");
|
|
332
|
+
}
|
|
333
|
+
console.log(chalk_1.default.blue("🤖 Using X.AI (Grok) for generation..."));
|
|
334
|
+
switch (type) {
|
|
335
|
+
case "context":
|
|
336
|
+
return await xaiClient.generateContext(context);
|
|
337
|
+
case "components-list":
|
|
338
|
+
return await xaiClient.generateComponentList(context);
|
|
339
|
+
case "component":
|
|
340
|
+
// For component generation, we need to parse the context
|
|
341
|
+
try {
|
|
342
|
+
const componentData = JSON.parse(context);
|
|
343
|
+
return await xaiClient.generateComponent(componentData.component, componentData.group?.name || "general");
|
|
344
|
+
}
|
|
345
|
+
catch {
|
|
346
|
+
// If context is not JSON, treat it as a simple component name
|
|
347
|
+
return await xaiClient.generateComponent({ name: context, description: context }, "general");
|
|
348
|
+
}
|
|
349
|
+
default:
|
|
350
|
+
// For other types, use the general generate method
|
|
351
|
+
return await xaiClient.generate({
|
|
352
|
+
prompt: context,
|
|
353
|
+
temperature: options.temperature || 0.7,
|
|
354
|
+
maxTokens: options.maxTokens || 4000,
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
catch (error) {
|
|
359
|
+
console.log(chalk_1.default.yellow("X.AI unavailable, trying GitHub Models..."));
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
// GitHub Models fallback
|
|
363
|
+
if (githubToken) {
|
|
364
|
+
try {
|
|
365
|
+
const { GitHubModelsClient } = await Promise.resolve().then(() => __importStar(require("../utils/githubModels")));
|
|
366
|
+
const githubClient = new GitHubModelsClient({
|
|
367
|
+
token: githubToken,
|
|
368
|
+
temperature: options.temperature || 0.7,
|
|
369
|
+
maxTokens: options.maxTokens || 4000,
|
|
370
|
+
});
|
|
371
|
+
// Test connection first
|
|
372
|
+
const isConnected = await githubClient.testConnection();
|
|
373
|
+
if (!isConnected) {
|
|
374
|
+
throw new Error("GitHub Models connection failed");
|
|
375
|
+
}
|
|
376
|
+
console.log(chalk_1.default.blue("🤖 Using GitHub Models for generation..."));
|
|
377
|
+
switch (type) {
|
|
378
|
+
case "component":
|
|
379
|
+
// For component generation, we need to parse the context
|
|
380
|
+
try {
|
|
381
|
+
const componentData = JSON.parse(context);
|
|
382
|
+
return await githubClient.generateComponent(componentData.component, componentData.group?.name || "general");
|
|
383
|
+
}
|
|
384
|
+
catch {
|
|
385
|
+
// If context is not JSON, treat it as a simple component name
|
|
386
|
+
return await githubClient.generateComponent({ name: context, description: context }, "general");
|
|
387
|
+
}
|
|
388
|
+
case "context":
|
|
389
|
+
return await githubClient.generateComponentList(context);
|
|
390
|
+
default:
|
|
391
|
+
// For other types, use the general generate method
|
|
392
|
+
return await githubClient.generate({
|
|
393
|
+
prompt: context,
|
|
394
|
+
temperature: options.temperature || 0.7,
|
|
395
|
+
maxTokens: options.maxTokens || 4000,
|
|
396
|
+
});
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
catch (error) {
|
|
400
|
+
console.log(chalk_1.default.yellow("GitHub Models unavailable, trying local API..."));
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
// Fallback to local API
|
|
404
|
+
const apiUrl = process.env.MYCONTEXT_API_URL || "http://localhost:3000/api/generate";
|
|
405
|
+
try {
|
|
406
|
+
const response = await fetch(apiUrl, {
|
|
407
|
+
method: "POST",
|
|
408
|
+
headers: {
|
|
409
|
+
"Content-Type": "application/json",
|
|
410
|
+
...(process.env.MYCONTEXT_API_KEY && {
|
|
411
|
+
Authorization: `Bearer ${process.env.MYCONTEXT_API_KEY}`,
|
|
412
|
+
}),
|
|
413
|
+
},
|
|
414
|
+
body: JSON.stringify({
|
|
415
|
+
type,
|
|
416
|
+
context,
|
|
417
|
+
options: {
|
|
418
|
+
useClaudeCodeSDK: options.useClaudeCodeSDK,
|
|
419
|
+
useGemini: options.useGemini,
|
|
420
|
+
temperature: options.temperature || 0.7,
|
|
421
|
+
maxTokens: options.maxTokens || 4000,
|
|
422
|
+
},
|
|
423
|
+
}),
|
|
424
|
+
});
|
|
425
|
+
if (!response.ok) {
|
|
426
|
+
throw new Error(`API request failed: ${response.status} ${response.statusText}`);
|
|
427
|
+
}
|
|
428
|
+
const result = (await response.json());
|
|
429
|
+
// Handle API response structure
|
|
430
|
+
if (result.success && result.result) {
|
|
431
|
+
// Check if result has a data property (nested structure)
|
|
432
|
+
if (result.result.data) {
|
|
433
|
+
return result.result.data;
|
|
434
|
+
}
|
|
435
|
+
return result.result;
|
|
436
|
+
}
|
|
437
|
+
else if (result.content) {
|
|
438
|
+
return result.content;
|
|
439
|
+
}
|
|
440
|
+
else {
|
|
441
|
+
return result;
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
catch (error) {
|
|
445
|
+
// Fallback to local generation if API fails
|
|
446
|
+
console.log(chalk_1.default.yellow("API unavailable, using local generation..."));
|
|
447
|
+
return this.generateLocally(type, context, options);
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
async generateLocally(type, context, options) {
|
|
451
|
+
// Local generation fallback
|
|
452
|
+
switch (type) {
|
|
453
|
+
case "context":
|
|
454
|
+
return this.generateLocalContext(context);
|
|
455
|
+
case "types":
|
|
456
|
+
return this.generateLocalTypes(context);
|
|
457
|
+
case "brand":
|
|
458
|
+
return this.generateLocalBrand(context);
|
|
459
|
+
case "components-list":
|
|
460
|
+
case "workflow":
|
|
461
|
+
return this.generateLocalComponentsList(context);
|
|
462
|
+
case "components":
|
|
463
|
+
return this.generateLocalComponents(context);
|
|
464
|
+
case "app-structure":
|
|
465
|
+
return this.generateLocalAppStructure(context);
|
|
466
|
+
default:
|
|
467
|
+
throw new Error(`Unknown generation type: ${type}`);
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
async generateLocalContext(description) {
|
|
471
|
+
// Detect app type based on description
|
|
472
|
+
const isTodoApp = description.toLowerCase().includes("todo") ||
|
|
473
|
+
description.toLowerCase().includes("task") ||
|
|
474
|
+
description.toLowerCase().includes("checklist");
|
|
475
|
+
const isEcommerceApp = description.toLowerCase().includes("ecommerce") ||
|
|
476
|
+
description.toLowerCase().includes("shop") ||
|
|
477
|
+
description.toLowerCase().includes("store") ||
|
|
478
|
+
description.toLowerCase().includes("cart") ||
|
|
479
|
+
description.toLowerCase().includes("checkout") ||
|
|
480
|
+
description.toLowerCase().includes("payment");
|
|
481
|
+
if (isTodoApp) {
|
|
482
|
+
return {
|
|
483
|
+
"01_PRD.md": `# Product Requirements Document
|
|
484
|
+
|
|
485
|
+
## Project Overview
|
|
486
|
+
**Project Name:** Todo Application
|
|
487
|
+
**Description:** ${description}
|
|
488
|
+
|
|
489
|
+
## Core Features
|
|
490
|
+
- **Task Management**: Create, read, update, and delete todo items
|
|
491
|
+
- **Task Status**: Mark tasks as complete/incomplete with visual indicators
|
|
492
|
+
- **Task Categories**: Organize tasks by categories or priorities
|
|
493
|
+
- **Search & Filter**: Find specific tasks quickly
|
|
494
|
+
- **Responsive Design**: Works seamlessly on desktop and mobile devices
|
|
495
|
+
|
|
496
|
+
## User Stories
|
|
497
|
+
- As a user, I want to create new todo items so that I can track my tasks
|
|
498
|
+
- As a user, I want to mark tasks as complete so that I can track my progress
|
|
499
|
+
- As a user, I want to edit existing tasks so that I can update details
|
|
500
|
+
- As a user, I want to delete tasks so that I can remove completed or irrelevant items
|
|
501
|
+
- As a user, I want to filter tasks by status so that I can focus on pending work
|
|
502
|
+
- As a user, I want to search for specific tasks so that I can find them quickly
|
|
503
|
+
|
|
504
|
+
## Technical Requirements
|
|
505
|
+
- **Frontend**: Next.js 14 with App Router, TypeScript, Tailwind CSS
|
|
506
|
+
- **UI Components**: shadcn/ui component library
|
|
507
|
+
- **State Management**: React hooks with local storage persistence
|
|
508
|
+
- **Styling**: Responsive design with mobile-first approach
|
|
509
|
+
- **Accessibility**: WCAG 2.1 AA compliance
|
|
510
|
+
|
|
511
|
+
## Acceptance Criteria
|
|
512
|
+
- [ ] Users can create new todo items with title and optional description
|
|
513
|
+
- [ ] Users can mark tasks as complete/incomplete with visual feedback
|
|
514
|
+
- [ ] Users can edit task details inline
|
|
515
|
+
- [ ] Users can delete tasks with confirmation
|
|
516
|
+
- [ ] Users can filter tasks by status (all, active, completed)
|
|
517
|
+
- [ ] Users can search tasks by title or description
|
|
518
|
+
- [ ] Tasks persist across browser sessions using local storage
|
|
519
|
+
- [ ] Interface is fully responsive and accessible`,
|
|
520
|
+
"02_user_stories.md": `# User Stories
|
|
521
|
+
|
|
522
|
+
## Primary User Stories
|
|
523
|
+
|
|
524
|
+
### 1. Task Creation
|
|
525
|
+
**As a** user
|
|
526
|
+
**I want to** create new todo items
|
|
527
|
+
**So that** I can track my tasks and responsibilities
|
|
528
|
+
|
|
529
|
+
**Acceptance Criteria:**
|
|
530
|
+
- [ ] I can click an "Add Task" button or press Enter in an input field
|
|
531
|
+
- [ ] I can enter a task title (required)
|
|
532
|
+
- [ ] I can optionally add a description
|
|
533
|
+
- [ ] The task appears in my todo list immediately
|
|
534
|
+
- [ ] The input field clears after adding a task
|
|
535
|
+
|
|
536
|
+
### 2. Task Completion
|
|
537
|
+
**As a** user
|
|
538
|
+
**I want to** mark tasks as complete
|
|
539
|
+
**So that** I can track my progress and focus on remaining work
|
|
540
|
+
|
|
541
|
+
**Acceptance Criteria:**
|
|
542
|
+
- [ ] I can click a checkbox next to each task
|
|
543
|
+
- [ ] Completed tasks show visual indicators (strikethrough, different color)
|
|
544
|
+
- [ ] I can uncheck completed tasks to mark them as incomplete
|
|
545
|
+
- [ ] The completion status persists across sessions
|
|
546
|
+
|
|
547
|
+
### 3. Task Editing
|
|
548
|
+
**As a** user
|
|
549
|
+
**I want to** edit existing tasks
|
|
550
|
+
**So that** I can update details or correct mistakes
|
|
551
|
+
|
|
552
|
+
**Acceptance Criteria:**
|
|
553
|
+
- [ ] I can click on a task title to edit it inline
|
|
554
|
+
- [ ] I can also edit the task description
|
|
555
|
+
- [ ] Changes are saved automatically or with a save button
|
|
556
|
+
- [ ] I can cancel editing by pressing Escape
|
|
557
|
+
|
|
558
|
+
### 4. Task Deletion
|
|
559
|
+
**As a** user
|
|
560
|
+
**I want to** delete tasks
|
|
561
|
+
**So that** I can remove completed or irrelevant items
|
|
562
|
+
|
|
563
|
+
**Acceptance Criteria:**
|
|
564
|
+
- [ ] I can click a delete button (trash icon) next to each task
|
|
565
|
+
- [ ] A confirmation dialog appears before deletion
|
|
566
|
+
- [ ] Deleted tasks are removed from the list permanently
|
|
567
|
+
- [ ] I can undo deletion within a short time window
|
|
568
|
+
|
|
569
|
+
### 5. Task Filtering
|
|
570
|
+
**As a** user
|
|
571
|
+
**I want to** filter tasks by status
|
|
572
|
+
**So that** I can focus on specific types of tasks
|
|
573
|
+
|
|
574
|
+
**Acceptance Criteria:**
|
|
575
|
+
- [ ] I can filter by "All", "Active", or "Completed" tasks
|
|
576
|
+
- [ ] The filter selection is visually indicated
|
|
577
|
+
- [ ] The task count updates based on the current filter
|
|
578
|
+
- [ ] I can clear filters to show all tasks
|
|
579
|
+
|
|
580
|
+
### 6. Task Search
|
|
581
|
+
**As a** user
|
|
582
|
+
**I want to** search for specific tasks
|
|
583
|
+
**So that** I can find them quickly in a long list
|
|
584
|
+
|
|
585
|
+
**Acceptance Criteria:**
|
|
586
|
+
- [ ] I can type in a search box to filter tasks
|
|
587
|
+
- [ ] Search works on both task titles and descriptions
|
|
588
|
+
- [ ] Search results update in real-time as I type
|
|
589
|
+
- [ ] No results message appears when no matches are found`,
|
|
590
|
+
"03_technical_specs.md": `# Technical Specifications
|
|
591
|
+
|
|
592
|
+
## Architecture Overview
|
|
593
|
+
- **Frontend Framework**: Next.js 14 with App Router
|
|
594
|
+
- **Language**: TypeScript for type safety
|
|
595
|
+
- **Styling**: Tailwind CSS with shadcn/ui components
|
|
596
|
+
- **State Management**: React hooks with localStorage persistence
|
|
597
|
+
- **Build Tool**: Vite for fast development and building
|
|
598
|
+
|
|
599
|
+
## Component Architecture
|
|
600
|
+
|
|
601
|
+
### Core Components
|
|
602
|
+
1. **TodoApp** - Main application container
|
|
603
|
+
2. **TodoList** - Displays the list of todo items
|
|
604
|
+
3. **TodoItem** - Individual todo item with actions
|
|
605
|
+
4. **TodoForm** - Form for creating new todos
|
|
606
|
+
5. **TodoFilter** - Filter and search controls
|
|
607
|
+
6. **TodoStats** - Shows completion statistics
|
|
608
|
+
|
|
609
|
+
### Layout Components
|
|
610
|
+
- **Header** - App title and navigation
|
|
611
|
+
- **Main** - Primary content area
|
|
612
|
+
- **Footer** - Additional information and links
|
|
613
|
+
|
|
614
|
+
## Data Model
|
|
615
|
+
|
|
616
|
+
### Todo Item Structure
|
|
617
|
+
\`\`\`typescript
|
|
618
|
+
interface Todo {
|
|
619
|
+
id: string;
|
|
620
|
+
title: string;
|
|
621
|
+
description?: string;
|
|
622
|
+
completed: boolean;
|
|
623
|
+
createdAt: Date;
|
|
624
|
+
updatedAt: Date;
|
|
625
|
+
priority?: 'low' | 'medium' | 'high';
|
|
626
|
+
category?: string;
|
|
627
|
+
}
|
|
628
|
+
\`\`\`
|
|
629
|
+
|
|
630
|
+
### Local Storage Schema
|
|
631
|
+
\`\`\`json
|
|
632
|
+
{
|
|
633
|
+
"todos": [
|
|
634
|
+
{
|
|
635
|
+
"id": "uuid",
|
|
636
|
+
"title": "Task title",
|
|
637
|
+
"description": "Optional description",
|
|
638
|
+
"completed": false,
|
|
639
|
+
"createdAt": "2024-01-01T00:00:00.000Z",
|
|
640
|
+
"updatedAt": "2024-01-01T00:00:00.000Z"
|
|
641
|
+
}
|
|
642
|
+
],
|
|
643
|
+
"filters": {
|
|
644
|
+
"status": "all",
|
|
645
|
+
"search": ""
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
\`\`\`
|
|
649
|
+
|
|
650
|
+
## UI/UX Design
|
|
651
|
+
|
|
652
|
+
### Design System
|
|
653
|
+
- **Color Palette**: Tailwind CSS default with custom accent colors
|
|
654
|
+
- **Typography**: Inter font family for readability
|
|
655
|
+
- **Spacing**: Consistent 4px grid system
|
|
656
|
+
- **Components**: shadcn/ui primitives for consistency
|
|
657
|
+
|
|
658
|
+
### Responsive Design
|
|
659
|
+
- **Mobile First**: Design for mobile devices first
|
|
660
|
+
- **Breakpoints**: sm (640px), md (768px), lg (1024px), xl (1280px)
|
|
661
|
+
- **Touch Targets**: Minimum 44px for interactive elements
|
|
662
|
+
|
|
663
|
+
### Accessibility
|
|
664
|
+
- **WCAG 2.1 AA**: Full compliance with accessibility standards
|
|
665
|
+
- **Keyboard Navigation**: All features accessible via keyboard
|
|
666
|
+
- **Screen Readers**: Proper ARIA labels and semantic HTML
|
|
667
|
+
- **Color Contrast**: Minimum 4.5:1 ratio for text
|
|
668
|
+
|
|
669
|
+
## Performance Considerations
|
|
670
|
+
- **Lazy Loading**: Components load only when needed
|
|
671
|
+
- **Debounced Search**: Search input debounced to prevent excessive filtering
|
|
672
|
+
- **Optimistic Updates**: UI updates immediately, then syncs with storage
|
|
673
|
+
- **Virtual Scrolling**: For large lists (future enhancement)
|
|
674
|
+
|
|
675
|
+
## Security & Data
|
|
676
|
+
- **Client-Side Only**: No server-side storage required
|
|
677
|
+
- **Input Sanitization**: All user inputs are sanitized
|
|
678
|
+
- **XSS Prevention**: React's built-in XSS protection
|
|
679
|
+
- **Local Storage**: Data persists in browser localStorage`,
|
|
680
|
+
};
|
|
681
|
+
}
|
|
682
|
+
else if (isEcommerceApp) {
|
|
683
|
+
return {
|
|
684
|
+
"01_PRD.md": `# Product Requirements Document
|
|
685
|
+
|
|
686
|
+
## Project Overview
|
|
687
|
+
**Project Name:** Ecommerce Platform
|
|
688
|
+
**Description:** ${description}
|
|
689
|
+
|
|
690
|
+
## Core Features
|
|
691
|
+
- **Product Catalog**: Browse and search products with filtering and sorting
|
|
692
|
+
- **Shopping Cart**: Add, remove, and manage items in cart
|
|
693
|
+
- **Checkout Process**: Multi-step checkout with payment processing
|
|
694
|
+
- **User Accounts**: Registration, login, and order history
|
|
695
|
+
- **Payment Integration**: Secure payment processing with multiple options
|
|
696
|
+
- **Order Management**: Track orders and receive notifications
|
|
697
|
+
|
|
698
|
+
## User Stories
|
|
699
|
+
- As a customer, I want to browse products so that I can find items to purchase
|
|
700
|
+
- As a customer, I want to add items to cart so that I can purchase multiple items
|
|
701
|
+
- As a customer, I want to complete checkout so that I can receive my order
|
|
702
|
+
- As a customer, I want to track my orders so that I know when they'll arrive
|
|
703
|
+
- As a customer, I want to save payment methods so that checkout is faster
|
|
704
|
+
- As an admin, I want to manage products so that inventory is accurate
|
|
705
|
+
|
|
706
|
+
## Technical Requirements
|
|
707
|
+
- **Frontend**: Next.js 14 with App Router, TypeScript, Tailwind CSS
|
|
708
|
+
- **UI Components**: shadcn/ui component library
|
|
709
|
+
- **State Management**: React hooks with cart persistence
|
|
710
|
+
- **Payment**: Stripe integration for secure payments
|
|
711
|
+
- **Authentication**: NextAuth.js for user management
|
|
712
|
+
- **Database**: PostgreSQL for product and order data
|
|
713
|
+
|
|
714
|
+
## Acceptance Criteria
|
|
715
|
+
- [ ] Users can browse products with search and filtering
|
|
716
|
+
- [ ] Users can add/remove items from shopping cart
|
|
717
|
+
- [ ] Users can complete checkout with payment processing
|
|
718
|
+
- [ ] Users can track order status and history
|
|
719
|
+
- [ ] Admin can manage product inventory
|
|
720
|
+
- [ ] Payment processing is secure and reliable`,
|
|
721
|
+
"02_user_stories.md": `# User Stories
|
|
722
|
+
|
|
723
|
+
## Primary User Stories
|
|
724
|
+
|
|
725
|
+
### 1. Product Browsing
|
|
726
|
+
**As a** customer
|
|
727
|
+
**I want to** browse products
|
|
728
|
+
**So that** I can find items to purchase
|
|
729
|
+
|
|
730
|
+
**Acceptance Criteria:**
|
|
731
|
+
- [ ] I can view a grid/list of products with images and prices
|
|
732
|
+
- [ ] I can search for specific products by name or category
|
|
733
|
+
- [ ] I can filter products by price, category, or rating
|
|
734
|
+
- [ ] I can sort products by price, popularity, or newest
|
|
735
|
+
- [ ] I can view detailed product information
|
|
736
|
+
|
|
737
|
+
### 2. Shopping Cart Management
|
|
738
|
+
**As a** customer
|
|
739
|
+
**I want to** manage my shopping cart
|
|
740
|
+
**So that** I can purchase multiple items efficiently
|
|
741
|
+
|
|
742
|
+
**Acceptance Criteria:**
|
|
743
|
+
- [ ] I can add products to my cart from product pages
|
|
744
|
+
- [ ] I can view my cart contents and total
|
|
745
|
+
- [ ] I can update quantities or remove items
|
|
746
|
+
- [ ] My cart persists across browser sessions
|
|
747
|
+
- [ ] I can save items for later purchase
|
|
748
|
+
|
|
749
|
+
### 3. Checkout Process
|
|
750
|
+
**As a** customer
|
|
751
|
+
**I want to** complete my purchase
|
|
752
|
+
**So that** I can receive my order
|
|
753
|
+
|
|
754
|
+
**Acceptance Criteria:**
|
|
755
|
+
- [ ] I can enter shipping and billing information
|
|
756
|
+
- [ ] I can select from multiple payment options
|
|
757
|
+
- [ ] I can review my order before confirmation
|
|
758
|
+
- [ ] I receive confirmation of my purchase
|
|
759
|
+
- [ ] I can track my order status
|
|
760
|
+
|
|
761
|
+
### 4. Order Tracking
|
|
762
|
+
**As a** customer
|
|
763
|
+
**I want to** track my orders
|
|
764
|
+
**So that** I know when they'll arrive
|
|
765
|
+
|
|
766
|
+
**Acceptance Criteria:**
|
|
767
|
+
- [ ] I can view my order history
|
|
768
|
+
- [ ] I can see current order status
|
|
769
|
+
- [ ] I receive email notifications for updates
|
|
770
|
+
- [ ] I can cancel orders within allowed timeframe
|
|
771
|
+
- [ ] I can request refunds or returns`,
|
|
772
|
+
"03_technical_specs.md": `# Technical Specifications
|
|
773
|
+
|
|
774
|
+
## Architecture Overview
|
|
775
|
+
- **Frontend Framework**: Next.js 14 with App Router
|
|
776
|
+
- **Language**: TypeScript for type safety
|
|
777
|
+
- **Styling**: Tailwind CSS with shadcn/ui components
|
|
778
|
+
- **State Management**: React hooks with cart persistence
|
|
779
|
+
- **Payment Processing**: Stripe integration
|
|
780
|
+
- **Authentication**: NextAuth.js
|
|
781
|
+
- **Database**: PostgreSQL with Prisma ORM
|
|
782
|
+
|
|
783
|
+
## Component Architecture
|
|
784
|
+
|
|
785
|
+
### Core Components
|
|
786
|
+
1. **ProductCatalog** - Product browsing and search
|
|
787
|
+
2. **ProductCard** - Individual product display
|
|
788
|
+
3. **ShoppingCart** - Cart management and display
|
|
789
|
+
4. **CheckoutForm** - Multi-step checkout process
|
|
790
|
+
5. **PaymentForm** - Payment method selection
|
|
791
|
+
6. **OrderTracking** - Order status and history
|
|
792
|
+
|
|
793
|
+
### Layout Components
|
|
794
|
+
- **Header** - Navigation and cart icon
|
|
795
|
+
- **ProductGrid** - Product listing layout
|
|
796
|
+
- **CheckoutWizard** - Multi-step checkout flow
|
|
797
|
+
- **Footer** - Additional information and links
|
|
798
|
+
|
|
799
|
+
## Data Model
|
|
800
|
+
|
|
801
|
+
### Product Structure
|
|
802
|
+
\`\`\`typescript
|
|
803
|
+
interface Product {
|
|
804
|
+
id: string;
|
|
805
|
+
name: string;
|
|
806
|
+
description: string;
|
|
807
|
+
price: number;
|
|
808
|
+
images: string[];
|
|
809
|
+
category: string;
|
|
810
|
+
inventory: number;
|
|
811
|
+
rating: number;
|
|
812
|
+
reviews: Review[];
|
|
813
|
+
}
|
|
814
|
+
\`\`\`
|
|
815
|
+
|
|
816
|
+
### Cart Structure
|
|
817
|
+
\`\`\`typescript
|
|
818
|
+
interface CartItem {
|
|
819
|
+
productId: string;
|
|
820
|
+
quantity: number;
|
|
821
|
+
price: number;
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
interface Cart {
|
|
825
|
+
items: CartItem[];
|
|
826
|
+
total: number;
|
|
827
|
+
itemCount: number;
|
|
828
|
+
}
|
|
829
|
+
\`\`\`
|
|
830
|
+
|
|
831
|
+
## UI/UX Design
|
|
832
|
+
|
|
833
|
+
### Design System
|
|
834
|
+
- **Color Palette**: Professional ecommerce colors
|
|
835
|
+
- **Typography**: Clear, readable fonts for product information
|
|
836
|
+
- **Spacing**: Consistent spacing for product grids
|
|
837
|
+
- **Components**: shadcn/ui primitives with ecommerce patterns
|
|
838
|
+
|
|
839
|
+
### Responsive Design
|
|
840
|
+
- **Mobile First**: Optimized for mobile shopping
|
|
841
|
+
- **Product Grid**: Responsive grid layout
|
|
842
|
+
- **Checkout**: Mobile-friendly form design
|
|
843
|
+
- **Touch Targets**: Large enough for mobile interaction
|
|
844
|
+
|
|
845
|
+
### Accessibility
|
|
846
|
+
- **WCAG 2.1 AA**: Full compliance for all users
|
|
847
|
+
- **Screen Readers**: Proper product descriptions
|
|
848
|
+
- **Keyboard Navigation**: Full keyboard accessibility
|
|
849
|
+
- **Color Contrast**: High contrast for product information
|
|
850
|
+
|
|
851
|
+
## Performance Considerations
|
|
852
|
+
- **Image Optimization**: Lazy loading and WebP format
|
|
853
|
+
- **Product Search**: Fast search with debouncing
|
|
854
|
+
- **Cart Updates**: Optimistic updates for better UX
|
|
855
|
+
- **Payment Processing**: Secure and fast payment flow
|
|
856
|
+
|
|
857
|
+
## Security & Data
|
|
858
|
+
- **Payment Security**: PCI compliance with Stripe
|
|
859
|
+
- **User Data**: Secure storage and transmission
|
|
860
|
+
- **Input Validation**: All user inputs validated
|
|
861
|
+
- **CSRF Protection**: Protection against cross-site attacks`,
|
|
862
|
+
};
|
|
863
|
+
}
|
|
864
|
+
else {
|
|
865
|
+
// Fallback: generic context with instructions
|
|
866
|
+
const instructions = `<!--\nThis is a generic context file.\nTo regenerate with your project details, run:\n\n mycontext generate context --yes\n\nEdit your PRD or provide a detailed description for better results.\n-->\n`;
|
|
867
|
+
return {
|
|
868
|
+
"01_PRD.md": `${instructions}
|
|
869
|
+
# Product Requirements Document
|
|
870
|
+
|
|
871
|
+
## Project Overview
|
|
872
|
+
Describe your project here.
|
|
873
|
+
|
|
874
|
+
## Core Features
|
|
875
|
+
- Feature 1: Description
|
|
876
|
+
- Feature 2: Description
|
|
877
|
+
- Feature 3: Description
|
|
878
|
+
|
|
879
|
+
## Technical Requirements
|
|
880
|
+
- Technology Stack: [List technologies]
|
|
881
|
+
- Database: [Database choice]
|
|
882
|
+
- Authentication: [Auth method]
|
|
883
|
+
|
|
884
|
+
## User Stories
|
|
885
|
+
- As a user, I want to [action] so that [benefit]
|
|
886
|
+
- As an admin, I need to [action] so that [benefit]
|
|
887
|
+
|
|
888
|
+
## Acceptance Criteria
|
|
889
|
+
- [ ] Feature 1 works correctly
|
|
890
|
+
- [ ] Feature 2 is responsive
|
|
891
|
+
- [ ] Feature 3 is accessible
|
|
892
|
+
`,
|
|
893
|
+
"02_user_stories.md": `${instructions}
|
|
894
|
+
# User Stories
|
|
895
|
+
|
|
896
|
+
Add user stories for your project here.
|
|
897
|
+
|
|
898
|
+
## Example User Stories
|
|
899
|
+
- As a user, I want to [do something] so that [benefit].
|
|
900
|
+
- As an admin, I want to [manage something] so that [benefit].
|
|
901
|
+
|
|
902
|
+
## Acceptance Criteria
|
|
903
|
+
- [ ] User can complete the primary action
|
|
904
|
+
- [ ] System provides appropriate feedback
|
|
905
|
+
- [ ] Error handling is implemented
|
|
906
|
+
`,
|
|
907
|
+
"03_technical_specs.md": `${instructions}
|
|
908
|
+
# Technical Specifications
|
|
909
|
+
|
|
910
|
+
## Architecture
|
|
911
|
+
- Frontend: [Framework, e.g., Next.js, React]
|
|
912
|
+
- Styling: [CSS framework, e.g., Tailwind CSS]
|
|
913
|
+
- State Management: [e.g., Zustand, Redux]
|
|
914
|
+
- Database: [e.g., PostgreSQL, MongoDB]
|
|
915
|
+
- Authentication: [e.g., NextAuth.js, Auth0]
|
|
916
|
+
|
|
917
|
+
## Component Structure
|
|
918
|
+
- Layout components
|
|
919
|
+
- Form components
|
|
920
|
+
- Display components
|
|
921
|
+
- Interactive components
|
|
922
|
+
|
|
923
|
+
## API Design
|
|
924
|
+
- RESTful endpoints
|
|
925
|
+
- TypeScript interfaces
|
|
926
|
+
- Error handling
|
|
927
|
+
- Rate limiting
|
|
928
|
+
`,
|
|
929
|
+
};
|
|
930
|
+
}
|
|
931
|
+
}
|
|
932
|
+
async generateLocalTypes(context) {
|
|
933
|
+
return `// Generated TypeScript types based on: ${context}
|
|
934
|
+
|
|
935
|
+
export interface User {
|
|
936
|
+
id: string;
|
|
937
|
+
email: string;
|
|
938
|
+
name: string;
|
|
939
|
+
role: 'user' | 'admin';
|
|
940
|
+
createdAt: Date;
|
|
941
|
+
updatedAt: Date;
|
|
942
|
+
}
|
|
943
|
+
|
|
944
|
+
export interface Project {
|
|
945
|
+
id: string;
|
|
946
|
+
name: string;
|
|
947
|
+
description: string;
|
|
948
|
+
userId: string;
|
|
949
|
+
status: 'active' | 'inactive' | 'archived';
|
|
950
|
+
createdAt: Date;
|
|
951
|
+
updatedAt: Date;
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
export interface ApiResponse<T = any> {
|
|
955
|
+
success: boolean;
|
|
956
|
+
data?: T;
|
|
957
|
+
error?: string;
|
|
958
|
+
message?: string;
|
|
959
|
+
}
|
|
960
|
+
|
|
961
|
+
// Add more types based on your project requirements
|
|
962
|
+
`;
|
|
963
|
+
}
|
|
964
|
+
// Update local brand generation to return both markdown and JSON
|
|
965
|
+
async generateLocalBrand(context) {
|
|
966
|
+
// Extract project name from context
|
|
967
|
+
const projectName = context.includes("Project Name:")
|
|
968
|
+
? context.split("Project Name:")[1]?.split("\n")[0]?.trim() ||
|
|
969
|
+
"MyContext Project"
|
|
970
|
+
: "MyContext Project";
|
|
971
|
+
const theme = "rose";
|
|
972
|
+
const colors = {
|
|
973
|
+
primary: "oklch(0.645 0.246 16.439)",
|
|
974
|
+
secondary: "oklch(0.967 0.001 286.375)",
|
|
975
|
+
accent: "oklch(0.967 0.001 286.375)",
|
|
976
|
+
background: "oklch(1 0 0)",
|
|
977
|
+
foreground: "oklch(0.141 0.005 285.823)",
|
|
978
|
+
border: "oklch(0.92 0.004 286.32)",
|
|
979
|
+
card: "oklch(1 0 0)",
|
|
980
|
+
cardForeground: "oklch(0.141 0.005 285.823)",
|
|
981
|
+
// ... add more as needed
|
|
982
|
+
};
|
|
983
|
+
const cssVariables = {
|
|
984
|
+
"--radius": "0.65rem",
|
|
985
|
+
"--background": colors.background,
|
|
986
|
+
"--foreground": colors.foreground,
|
|
987
|
+
"--primary": colors.primary,
|
|
988
|
+
"--secondary": colors.secondary,
|
|
989
|
+
"--accent": colors.accent,
|
|
990
|
+
"--border": colors.border,
|
|
991
|
+
"--card": colors.card,
|
|
992
|
+
"--card-foreground": colors.cardForeground,
|
|
993
|
+
// ... add more as needed
|
|
994
|
+
};
|
|
995
|
+
const typography = {
|
|
996
|
+
fontFamily: "Inter, system-ui, sans-serif",
|
|
997
|
+
fontSizes: {
|
|
998
|
+
xs: "0.75rem",
|
|
999
|
+
sm: "0.875rem",
|
|
1000
|
+
base: "1rem",
|
|
1001
|
+
lg: "1.125rem",
|
|
1002
|
+
xl: "1.25rem",
|
|
1003
|
+
"2xl": "1.5rem",
|
|
1004
|
+
"3xl": "1.875rem",
|
|
1005
|
+
"4xl": "2.25rem",
|
|
1006
|
+
"5xl": "3rem",
|
|
1007
|
+
},
|
|
1008
|
+
fontWeights: {
|
|
1009
|
+
light: 300,
|
|
1010
|
+
regular: 400,
|
|
1011
|
+
medium: 500,
|
|
1012
|
+
semibold: 600,
|
|
1013
|
+
bold: 700,
|
|
1014
|
+
extrabold: 800,
|
|
1015
|
+
},
|
|
1016
|
+
lineHeights: {
|
|
1017
|
+
tight: 1.25,
|
|
1018
|
+
normal: 1.5,
|
|
1019
|
+
relaxed: 1.75,
|
|
1020
|
+
},
|
|
1021
|
+
};
|
|
1022
|
+
const spacing = {
|
|
1023
|
+
base: "4px",
|
|
1024
|
+
scale: [0, 4, 8, 12, 16, 20, 24, 32, 40, 48, 64, 80, 96],
|
|
1025
|
+
};
|
|
1026
|
+
const markdown = `# Branding Guidelines
|
|
1027
|
+
|
|
1028
|
+
## Project Overview
|
|
1029
|
+
**Project Name:** ${projectName}
|
|
1030
|
+
**Theme:** ${theme} (shadcn/ui)
|
|
1031
|
+
**Generated:** ${new Date().toISOString().split("T")[0]}
|
|
1032
|
+
|
|
1033
|
+
### Color Palette
|
|
1034
|
+
- Primary: ${colors.primary}
|
|
1035
|
+
- Secondary: ${colors.secondary}
|
|
1036
|
+
- Accent: ${colors.accent}
|
|
1037
|
+
- Background: ${colors.background}
|
|
1038
|
+
- Foreground: ${colors.foreground}
|
|
1039
|
+
- Border: ${colors.border}
|
|
1040
|
+
|
|
1041
|
+
### CSS Variables
|
|
1042
|
+
\`\`\`css
|
|
1043
|
+
:root {
|
|
1044
|
+
${Object.entries(cssVariables)
|
|
1045
|
+
.map(([k, v]) => ` ${k}: ${v};`)
|
|
1046
|
+
.join("\n")}
|
|
1047
|
+
}
|
|
1048
|
+
\`\`\`
|
|
1049
|
+
|
|
1050
|
+
### Typography
|
|
1051
|
+
- Font Family: ${typography.fontFamily}
|
|
1052
|
+
- Font Sizes: ${Object.entries(typography.fontSizes)
|
|
1053
|
+
.map(([k, v]) => `${k}: ${v}`)
|
|
1054
|
+
.join(", ")}
|
|
1055
|
+
- Font Weights: ${Object.entries(typography.fontWeights)
|
|
1056
|
+
.map(([k, v]) => `${k}: ${v}`)
|
|
1057
|
+
.join(", ")}
|
|
1058
|
+
- Line Heights: ${Object.entries(typography.lineHeights)
|
|
1059
|
+
.map(([k, v]) => `${k}: ${v}`)
|
|
1060
|
+
.join(", ")}
|
|
1061
|
+
|
|
1062
|
+
### Spacing System
|
|
1063
|
+
- Base: ${spacing.base}
|
|
1064
|
+
- Scale: ${spacing.scale.join(", ")}
|
|
1065
|
+
|
|
1066
|
+
---
|
|
1067
|
+
|
|
1068
|
+
*This branding guide ensures consistency across all components and maintains the professional, accessible, and user-friendly design principles of the ${projectName} project.*
|
|
1069
|
+
`;
|
|
1070
|
+
const json = {
|
|
1071
|
+
projectName,
|
|
1072
|
+
theme,
|
|
1073
|
+
colors,
|
|
1074
|
+
cssVariables,
|
|
1075
|
+
typography,
|
|
1076
|
+
spacing,
|
|
1077
|
+
generated: new Date().toISOString(),
|
|
1078
|
+
};
|
|
1079
|
+
return { markdown, json };
|
|
1080
|
+
}
|
|
1081
|
+
async generateLocalComponents(context) {
|
|
1082
|
+
// Parse the context to extract component information
|
|
1083
|
+
let componentData;
|
|
1084
|
+
try {
|
|
1085
|
+
componentData = JSON.parse(context);
|
|
1086
|
+
}
|
|
1087
|
+
catch {
|
|
1088
|
+
// If context is not JSON, return empty array
|
|
1089
|
+
return [];
|
|
1090
|
+
}
|
|
1091
|
+
const { component, group, options } = componentData;
|
|
1092
|
+
// Use the CodeGenSubAgent to generate actual component code
|
|
1093
|
+
const { CodeGenSubAgent } = await Promise.resolve().then(() => __importStar(require("../agents/implementations/CodeGenSubAgent")));
|
|
1094
|
+
const codeGenAgent = new CodeGenSubAgent();
|
|
1095
|
+
const result = await codeGenAgent.run({
|
|
1096
|
+
component,
|
|
1097
|
+
group,
|
|
1098
|
+
options,
|
|
1099
|
+
context,
|
|
1100
|
+
});
|
|
1101
|
+
return [result];
|
|
1102
|
+
}
|
|
1103
|
+
async generateLocalComponentsList(context) {
|
|
1104
|
+
// Dynamic AI-driven component list generation
|
|
1105
|
+
// Instead of hardcoded patterns, we use intelligent analysis
|
|
1106
|
+
// Step 1: Analyze the context to determine app type and intent
|
|
1107
|
+
const appAnalysis = this.analyzeAppContext(context);
|
|
1108
|
+
// Step 2: Generate component list based on analysis
|
|
1109
|
+
return this.generateComponentListFromAnalysis(appAnalysis, context);
|
|
1110
|
+
}
|
|
1111
|
+
/**
|
|
1112
|
+
* Analyzes app context to determine type, intent, and requirements
|
|
1113
|
+
*/
|
|
1114
|
+
analyzeAppContext(context) {
|
|
1115
|
+
const analysis = {
|
|
1116
|
+
appType: this.detectAppType(context),
|
|
1117
|
+
primaryIntent: this.detectPrimaryIntent(context),
|
|
1118
|
+
complexity: this.assessComplexity(context),
|
|
1119
|
+
keyFeatures: this.extractKeyFeatures(context),
|
|
1120
|
+
userTypes: this.identifyUserTypes(context),
|
|
1121
|
+
dataEntities: this.identifyDataEntities(context),
|
|
1122
|
+
technicalRequirements: this.extractTechnicalRequirements(context),
|
|
1123
|
+
uiPatterns: this.suggestUIPatterns(context),
|
|
1124
|
+
componentGroups: [],
|
|
1125
|
+
priorityMatrix: this.createPriorityMatrix(context),
|
|
1126
|
+
};
|
|
1127
|
+
// Generate component groups based on analysis
|
|
1128
|
+
analysis.componentGroups = this.suggestComponentGroups(analysis);
|
|
1129
|
+
return analysis;
|
|
1130
|
+
}
|
|
1131
|
+
/**
|
|
1132
|
+
* Detects the type of application based on context
|
|
1133
|
+
*/
|
|
1134
|
+
detectAppType(context) {
|
|
1135
|
+
const lowerContext = context.toLowerCase();
|
|
1136
|
+
// Define app type patterns with confidence scores
|
|
1137
|
+
const typePatterns = [
|
|
1138
|
+
{
|
|
1139
|
+
type: "ecommerce",
|
|
1140
|
+
patterns: [
|
|
1141
|
+
"shop",
|
|
1142
|
+
"store",
|
|
1143
|
+
"cart",
|
|
1144
|
+
"checkout",
|
|
1145
|
+
"product",
|
|
1146
|
+
"order",
|
|
1147
|
+
"payment",
|
|
1148
|
+
],
|
|
1149
|
+
score: 0.9,
|
|
1150
|
+
},
|
|
1151
|
+
{
|
|
1152
|
+
type: "dashboard",
|
|
1153
|
+
patterns: [
|
|
1154
|
+
"dashboard",
|
|
1155
|
+
"analytics",
|
|
1156
|
+
"metrics",
|
|
1157
|
+
"report",
|
|
1158
|
+
"chart",
|
|
1159
|
+
"graph",
|
|
1160
|
+
],
|
|
1161
|
+
score: 0.85,
|
|
1162
|
+
},
|
|
1163
|
+
{
|
|
1164
|
+
type: "social",
|
|
1165
|
+
patterns: [
|
|
1166
|
+
"social",
|
|
1167
|
+
"network",
|
|
1168
|
+
"profile",
|
|
1169
|
+
"friend",
|
|
1170
|
+
"post",
|
|
1171
|
+
"comment",
|
|
1172
|
+
"share",
|
|
1173
|
+
],
|
|
1174
|
+
score: 0.8,
|
|
1175
|
+
},
|
|
1176
|
+
{
|
|
1177
|
+
type: "productivity",
|
|
1178
|
+
patterns: ["todo", "task", "project", "calendar", "note", "document"],
|
|
1179
|
+
score: 0.85,
|
|
1180
|
+
},
|
|
1181
|
+
{
|
|
1182
|
+
type: "communication",
|
|
1183
|
+
patterns: ["chat", "message", "email", "notification", "contact"],
|
|
1184
|
+
score: 0.8,
|
|
1185
|
+
},
|
|
1186
|
+
{
|
|
1187
|
+
type: "content",
|
|
1188
|
+
patterns: ["blog", "article", "news", "media", "gallery", "video"],
|
|
1189
|
+
score: 0.75,
|
|
1190
|
+
},
|
|
1191
|
+
{
|
|
1192
|
+
type: "utility",
|
|
1193
|
+
patterns: ["tool", "calculator", "converter", "generator", "utility"],
|
|
1194
|
+
score: 0.7,
|
|
1195
|
+
},
|
|
1196
|
+
{
|
|
1197
|
+
type: "game",
|
|
1198
|
+
patterns: ["game", "play", "score", "level", "player", "board"],
|
|
1199
|
+
score: 0.9,
|
|
1200
|
+
},
|
|
1201
|
+
{
|
|
1202
|
+
type: "weather",
|
|
1203
|
+
patterns: ["weather", "forecast", "temperature", "climate"],
|
|
1204
|
+
score: 0.85,
|
|
1205
|
+
},
|
|
1206
|
+
{
|
|
1207
|
+
type: "finance",
|
|
1208
|
+
patterns: ["finance", "banking", "budget", "expense", "investment"],
|
|
1209
|
+
score: 0.8,
|
|
1210
|
+
},
|
|
1211
|
+
];
|
|
1212
|
+
let bestMatch = "general";
|
|
1213
|
+
let highestScore = 0;
|
|
1214
|
+
for (const pattern of typePatterns) {
|
|
1215
|
+
const matchCount = pattern.patterns.filter((p) => lowerContext.includes(p)).length;
|
|
1216
|
+
const score = (matchCount / pattern.patterns.length) * pattern.score;
|
|
1217
|
+
if (score > highestScore) {
|
|
1218
|
+
highestScore = score;
|
|
1219
|
+
bestMatch = pattern.type;
|
|
1220
|
+
}
|
|
1221
|
+
}
|
|
1222
|
+
return bestMatch;
|
|
1223
|
+
}
|
|
1224
|
+
/**
|
|
1225
|
+
* Detects the primary intent of the application
|
|
1226
|
+
*/
|
|
1227
|
+
detectPrimaryIntent(context) {
|
|
1228
|
+
const lowerContext = context.toLowerCase();
|
|
1229
|
+
const intentPatterns = [
|
|
1230
|
+
{
|
|
1231
|
+
intent: "create",
|
|
1232
|
+
patterns: ["create", "add", "new", "generate", "build"],
|
|
1233
|
+
score: 0.8,
|
|
1234
|
+
},
|
|
1235
|
+
{
|
|
1236
|
+
intent: "view",
|
|
1237
|
+
patterns: ["view", "display", "show", "browse", "list"],
|
|
1238
|
+
score: 0.8,
|
|
1239
|
+
},
|
|
1240
|
+
{
|
|
1241
|
+
intent: "manage",
|
|
1242
|
+
patterns: ["manage", "organize", "control", "admin", "dashboard"],
|
|
1243
|
+
score: 0.8,
|
|
1244
|
+
},
|
|
1245
|
+
{
|
|
1246
|
+
intent: "connect",
|
|
1247
|
+
patterns: ["connect", "social", "network", "share", "collaborate"],
|
|
1248
|
+
score: 0.8,
|
|
1249
|
+
},
|
|
1250
|
+
{
|
|
1251
|
+
intent: "analyze",
|
|
1252
|
+
patterns: ["analyze", "track", "monitor", "report", "insights"],
|
|
1253
|
+
score: 0.8,
|
|
1254
|
+
},
|
|
1255
|
+
{
|
|
1256
|
+
intent: "entertain",
|
|
1257
|
+
patterns: ["game", "play", "entertain", "fun", "leisure"],
|
|
1258
|
+
score: 0.8,
|
|
1259
|
+
},
|
|
1260
|
+
];
|
|
1261
|
+
let bestIntent = "view";
|
|
1262
|
+
let highestScore = 0;
|
|
1263
|
+
for (const pattern of intentPatterns) {
|
|
1264
|
+
const matchCount = pattern.patterns.filter((p) => lowerContext.includes(p)).length;
|
|
1265
|
+
const score = (matchCount / pattern.patterns.length) * pattern.score;
|
|
1266
|
+
if (score > highestScore) {
|
|
1267
|
+
highestScore = score;
|
|
1268
|
+
bestIntent = pattern.intent;
|
|
1269
|
+
}
|
|
1270
|
+
}
|
|
1271
|
+
return bestIntent;
|
|
1272
|
+
}
|
|
1273
|
+
/**
|
|
1274
|
+
* Assesses the complexity of the application
|
|
1275
|
+
*/
|
|
1276
|
+
assessComplexity(context) {
|
|
1277
|
+
const wordCount = context.split(" ").length;
|
|
1278
|
+
const featureKeywords = [
|
|
1279
|
+
"authentication",
|
|
1280
|
+
"payment",
|
|
1281
|
+
"real-time",
|
|
1282
|
+
"api",
|
|
1283
|
+
"database",
|
|
1284
|
+
"search",
|
|
1285
|
+
"filter",
|
|
1286
|
+
"chart",
|
|
1287
|
+
"notification",
|
|
1288
|
+
];
|
|
1289
|
+
const featureCount = featureKeywords.filter((keyword) => context.toLowerCase().includes(keyword)).length;
|
|
1290
|
+
if (wordCount > 100 || featureCount > 5)
|
|
1291
|
+
return "high";
|
|
1292
|
+
if (wordCount > 50 || featureCount > 3)
|
|
1293
|
+
return "medium";
|
|
1294
|
+
return "low";
|
|
1295
|
+
}
|
|
1296
|
+
/**
|
|
1297
|
+
* Extracts key features from the context
|
|
1298
|
+
*/
|
|
1299
|
+
extractKeyFeatures(context) {
|
|
1300
|
+
const featurePatterns = [
|
|
1301
|
+
/authentication|login|signup|auth/gi,
|
|
1302
|
+
/payment|checkout|billing|subscription/gi,
|
|
1303
|
+
/search|filter|sort/gi,
|
|
1304
|
+
/real.?time|live|instant/gi,
|
|
1305
|
+
/notification|alert|reminder/gi,
|
|
1306
|
+
/chart|graph|analytics|metrics/gi,
|
|
1307
|
+
/upload|file|media/gi,
|
|
1308
|
+
/location|map|geolocation/gi,
|
|
1309
|
+
/chat|message|communication/gi,
|
|
1310
|
+
/calendar|schedule|booking/gi,
|
|
1311
|
+
];
|
|
1312
|
+
const features = [];
|
|
1313
|
+
featurePatterns.forEach((pattern) => {
|
|
1314
|
+
const matches = context.match(pattern);
|
|
1315
|
+
if (matches) {
|
|
1316
|
+
features.push(...matches.map((m) => m.toLowerCase()));
|
|
1317
|
+
}
|
|
1318
|
+
});
|
|
1319
|
+
return [...new Set(features)]; // Remove duplicates
|
|
1320
|
+
}
|
|
1321
|
+
/**
|
|
1322
|
+
* Identifies user types from context
|
|
1323
|
+
*/
|
|
1324
|
+
identifyUserTypes(context) {
|
|
1325
|
+
const userTypes = [];
|
|
1326
|
+
const lowerContext = context.toLowerCase();
|
|
1327
|
+
if (lowerContext.includes("admin") || lowerContext.includes("management"))
|
|
1328
|
+
userTypes.push("admin");
|
|
1329
|
+
if (lowerContext.includes("user") || lowerContext.includes("customer"))
|
|
1330
|
+
userTypes.push("user");
|
|
1331
|
+
if (lowerContext.includes("guest") || lowerContext.includes("public"))
|
|
1332
|
+
userTypes.push("guest");
|
|
1333
|
+
if (lowerContext.includes("moderator") || lowerContext.includes("editor"))
|
|
1334
|
+
userTypes.push("moderator");
|
|
1335
|
+
return userTypes.length > 0 ? userTypes : ["user"];
|
|
1336
|
+
}
|
|
1337
|
+
/**
|
|
1338
|
+
* Identifies data entities from context
|
|
1339
|
+
*/
|
|
1340
|
+
identifyDataEntities(context) {
|
|
1341
|
+
const entityPatterns = [
|
|
1342
|
+
/user|profile|account/gi,
|
|
1343
|
+
/product|item|goods/gi,
|
|
1344
|
+
/order|transaction|purchase/gi,
|
|
1345
|
+
/post|article|content/gi,
|
|
1346
|
+
/comment|review|feedback/gi,
|
|
1347
|
+
/category|tag|label/gi,
|
|
1348
|
+
/file|document|media/gi,
|
|
1349
|
+
/event|activity|log/gi,
|
|
1350
|
+
];
|
|
1351
|
+
const entities = [];
|
|
1352
|
+
entityPatterns.forEach((pattern) => {
|
|
1353
|
+
const matches = context.match(pattern);
|
|
1354
|
+
if (matches) {
|
|
1355
|
+
entities.push(...matches.map((m) => m.toLowerCase()));
|
|
1356
|
+
}
|
|
1357
|
+
});
|
|
1358
|
+
return [...new Set(entities)];
|
|
1359
|
+
}
|
|
1360
|
+
/**
|
|
1361
|
+
* Extracts technical requirements
|
|
1362
|
+
*/
|
|
1363
|
+
extractTechnicalRequirements(context) {
|
|
1364
|
+
const requirements = [];
|
|
1365
|
+
const lowerContext = context.toLowerCase();
|
|
1366
|
+
if (lowerContext.includes("mobile") || lowerContext.includes("responsive"))
|
|
1367
|
+
requirements.push("responsive");
|
|
1368
|
+
if (lowerContext.includes("real-time") || lowerContext.includes("live"))
|
|
1369
|
+
requirements.push("realtime");
|
|
1370
|
+
if (lowerContext.includes("offline") || lowerContext.includes("pwa"))
|
|
1371
|
+
requirements.push("offline");
|
|
1372
|
+
if (lowerContext.includes("accessibility") || lowerContext.includes("a11y"))
|
|
1373
|
+
requirements.push("accessible");
|
|
1374
|
+
if (lowerContext.includes("performance") || lowerContext.includes("fast"))
|
|
1375
|
+
requirements.push("performant");
|
|
1376
|
+
return requirements;
|
|
1377
|
+
}
|
|
1378
|
+
/**
|
|
1379
|
+
* Suggests UI patterns based on app type and intent
|
|
1380
|
+
*/
|
|
1381
|
+
suggestUIPatterns(context) {
|
|
1382
|
+
const appType = this.detectAppType(context);
|
|
1383
|
+
const patterns = [];
|
|
1384
|
+
switch (appType) {
|
|
1385
|
+
case "ecommerce":
|
|
1386
|
+
patterns.push("product-grid", "shopping-cart", "checkout-flow", "product-detail");
|
|
1387
|
+
break;
|
|
1388
|
+
case "dashboard":
|
|
1389
|
+
patterns.push("data-table", "chart-dashboard", "metric-cards", "sidebar-navigation");
|
|
1390
|
+
break;
|
|
1391
|
+
case "social":
|
|
1392
|
+
patterns.push("feed", "profile-card", "comment-thread", "social-actions");
|
|
1393
|
+
break;
|
|
1394
|
+
case "productivity":
|
|
1395
|
+
patterns.push("list-view", "form-wizard", "calendar-view", "kanban-board");
|
|
1396
|
+
break;
|
|
1397
|
+
case "weather":
|
|
1398
|
+
patterns.push("dashboard", "card-layout", "metric-cards", "chart-dashboard");
|
|
1399
|
+
break;
|
|
1400
|
+
default:
|
|
1401
|
+
patterns.push("list-view", "form", "card-layout", "navigation");
|
|
1402
|
+
}
|
|
1403
|
+
return patterns;
|
|
1404
|
+
}
|
|
1405
|
+
/**
|
|
1406
|
+
* Suggests component groups based on analysis
|
|
1407
|
+
*/
|
|
1408
|
+
suggestComponentGroups(analysis) {
|
|
1409
|
+
const groups = [];
|
|
1410
|
+
// Core functionality group
|
|
1411
|
+
groups.push({
|
|
1412
|
+
name: "Core Functionality",
|
|
1413
|
+
description: "Primary application features and main user workflows",
|
|
1414
|
+
priority: "high",
|
|
1415
|
+
components: this.generateCoreComponents(analysis),
|
|
1416
|
+
});
|
|
1417
|
+
// Data management group
|
|
1418
|
+
if (analysis.complexity !== "low") {
|
|
1419
|
+
groups.push({
|
|
1420
|
+
name: "Data Management",
|
|
1421
|
+
description: "Data input, display, and manipulation components",
|
|
1422
|
+
priority: "high",
|
|
1423
|
+
components: this.generateDataComponents(analysis),
|
|
1424
|
+
});
|
|
1425
|
+
}
|
|
1426
|
+
// Navigation and layout group
|
|
1427
|
+
groups.push({
|
|
1428
|
+
name: "Navigation & Layout",
|
|
1429
|
+
description: "Layout components and navigation elements",
|
|
1430
|
+
priority: "medium",
|
|
1431
|
+
components: this.generateLayoutComponents(analysis),
|
|
1432
|
+
});
|
|
1433
|
+
// User interaction group
|
|
1434
|
+
if (analysis.primaryIntent === "create" ||
|
|
1435
|
+
analysis.primaryIntent === "manage") {
|
|
1436
|
+
groups.push({
|
|
1437
|
+
name: "User Interaction",
|
|
1438
|
+
description: "Forms, controls, and interactive elements",
|
|
1439
|
+
priority: "medium",
|
|
1440
|
+
components: this.generateInteractionComponents(analysis),
|
|
1441
|
+
});
|
|
1442
|
+
}
|
|
1443
|
+
// Analytics and feedback group
|
|
1444
|
+
if (analysis.appType === "dashboard" ||
|
|
1445
|
+
analysis.primaryIntent === "analyze") {
|
|
1446
|
+
groups.push({
|
|
1447
|
+
name: "Analytics & Feedback",
|
|
1448
|
+
description: "Charts, metrics, and user feedback components",
|
|
1449
|
+
priority: "medium",
|
|
1450
|
+
components: this.generateAnalyticsComponents(analysis),
|
|
1451
|
+
});
|
|
1452
|
+
}
|
|
1453
|
+
return groups;
|
|
1454
|
+
}
|
|
1455
|
+
/**
|
|
1456
|
+
* Creates a priority matrix for components
|
|
1457
|
+
*/
|
|
1458
|
+
createPriorityMatrix(context) {
|
|
1459
|
+
const complexity = this.assessComplexity(context);
|
|
1460
|
+
return {
|
|
1461
|
+
critical: complexity === "high" ? 0.3 : 0.2,
|
|
1462
|
+
high: 0.4,
|
|
1463
|
+
medium: 0.2,
|
|
1464
|
+
low: 0.1,
|
|
1465
|
+
};
|
|
1466
|
+
}
|
|
1467
|
+
/**
|
|
1468
|
+
* Generates component list from analysis
|
|
1469
|
+
*/
|
|
1470
|
+
generateComponentListFromAnalysis(analysis, context) {
|
|
1471
|
+
const projectName = this.extractProjectName(context);
|
|
1472
|
+
return {
|
|
1473
|
+
project: {
|
|
1474
|
+
name: projectName,
|
|
1475
|
+
description: context,
|
|
1476
|
+
version: "0.1.0",
|
|
1477
|
+
generated: new Date().toISOString(),
|
|
1478
|
+
analysis: {
|
|
1479
|
+
appType: analysis.appType,
|
|
1480
|
+
primaryIntent: analysis.primaryIntent,
|
|
1481
|
+
complexity: analysis.complexity,
|
|
1482
|
+
keyFeatures: analysis.keyFeatures,
|
|
1483
|
+
userTypes: analysis.userTypes,
|
|
1484
|
+
dataEntities: analysis.dataEntities,
|
|
1485
|
+
technicalRequirements: analysis.technicalRequirements,
|
|
1486
|
+
uiPatterns: analysis.uiPatterns,
|
|
1487
|
+
},
|
|
1488
|
+
},
|
|
1489
|
+
groups: analysis.componentGroups,
|
|
1490
|
+
metadata: {
|
|
1491
|
+
totalComponents: analysis.componentGroups.reduce((acc, group) => acc + group.components.length, 0),
|
|
1492
|
+
totalGroups: analysis.componentGroups.length,
|
|
1493
|
+
generatedAt: new Date().toISOString(),
|
|
1494
|
+
version: "1.0.0",
|
|
1495
|
+
analysisScore: this.calculateAnalysisScore(analysis),
|
|
1496
|
+
},
|
|
1497
|
+
};
|
|
1498
|
+
}
|
|
1499
|
+
/**
|
|
1500
|
+
* Extracts project description from context
|
|
1501
|
+
*/
|
|
1502
|
+
extractProjectDescription(context) {
|
|
1503
|
+
// Try to extract from PRD content
|
|
1504
|
+
const prdMatch = context.match(/## Project Overview[\s\S]*?\*\*Description:\*\*\s*([^\n]+)/i);
|
|
1505
|
+
if (prdMatch && prdMatch[1]) {
|
|
1506
|
+
return prdMatch[1].trim();
|
|
1507
|
+
}
|
|
1508
|
+
// Try to extract from common patterns
|
|
1509
|
+
const patterns = [
|
|
1510
|
+
/(?:project|app|application)\s+(?:name|called|titled?)\s+["']?([^"'\n]+)["']?/i,
|
|
1511
|
+
/(?:create|build|develop)\s+(?:a|an)\s+([a-z\s]+?)\s+(?:app|application)/i,
|
|
1512
|
+
/^([A-Z][a-z\s]+?)\s+(?:app|application|platform|system)/i,
|
|
1513
|
+
];
|
|
1514
|
+
for (const pattern of patterns) {
|
|
1515
|
+
const match = context.match(pattern);
|
|
1516
|
+
if (match && match[1]) {
|
|
1517
|
+
return match[1].trim();
|
|
1518
|
+
}
|
|
1519
|
+
}
|
|
1520
|
+
// Fallback: use first meaningful phrase
|
|
1521
|
+
const words = context.split(" ").slice(0, 3);
|
|
1522
|
+
return (words
|
|
1523
|
+
.join(" ")
|
|
1524
|
+
.replace(/[^\w\s]/g, "")
|
|
1525
|
+
.trim() || "MyContext Project");
|
|
1526
|
+
}
|
|
1527
|
+
/**
|
|
1528
|
+
* Extracts project name from context
|
|
1529
|
+
*/
|
|
1530
|
+
extractProjectName(context) {
|
|
1531
|
+
// First try to get from the config file
|
|
1532
|
+
try {
|
|
1533
|
+
const configPath = ".mycontext/config.json";
|
|
1534
|
+
// Note: This is a synchronous context, so we'll use a fallback approach
|
|
1535
|
+
// The config reading will be handled in the calling method
|
|
1536
|
+
}
|
|
1537
|
+
catch {
|
|
1538
|
+
// Config file doesn't exist or can't be read, continue with other methods
|
|
1539
|
+
}
|
|
1540
|
+
// Try to extract from PRD content
|
|
1541
|
+
const prdMatch = context.match(/## Project Overview[\s\S]*?\*\*Project Name:\*\*\s*([^\n]+)/i);
|
|
1542
|
+
if (prdMatch && prdMatch[1]) {
|
|
1543
|
+
return prdMatch[1].trim();
|
|
1544
|
+
}
|
|
1545
|
+
// Try to extract from common patterns
|
|
1546
|
+
const patterns = [
|
|
1547
|
+
/(?:project|app|application)\s+(?:name|called|titled?)\s+["']?([^"'\n]+)["']?/i,
|
|
1548
|
+
/(?:create|build|develop)\s+(?:a|an)\s+([a-z\s]+?)\s+(?:app|application)/i,
|
|
1549
|
+
/^([A-Z][a-z\s]+?)\s+(?:app|application|platform|system)/i,
|
|
1550
|
+
];
|
|
1551
|
+
for (const pattern of patterns) {
|
|
1552
|
+
const match = context.match(pattern);
|
|
1553
|
+
if (match && match[1]) {
|
|
1554
|
+
return match[1].trim();
|
|
1555
|
+
}
|
|
1556
|
+
}
|
|
1557
|
+
// Fallback: use first meaningful phrase
|
|
1558
|
+
const words = context.split(" ").slice(0, 3);
|
|
1559
|
+
return (words
|
|
1560
|
+
.join(" ")
|
|
1561
|
+
.replace(/[^\w\s]/g, "")
|
|
1562
|
+
.trim() || "MyContext Project");
|
|
1563
|
+
}
|
|
1564
|
+
/**
|
|
1565
|
+
* Calculates analysis confidence score
|
|
1566
|
+
*/
|
|
1567
|
+
calculateAnalysisScore(analysis) {
|
|
1568
|
+
let score = 0;
|
|
1569
|
+
// App type detection score
|
|
1570
|
+
score += analysis.appType !== "general" ? 20 : 10;
|
|
1571
|
+
// Intent detection score
|
|
1572
|
+
score += analysis.primaryIntent !== "view" ? 15 : 10;
|
|
1573
|
+
// Feature extraction score
|
|
1574
|
+
score += Math.min(analysis.keyFeatures.length * 5, 25);
|
|
1575
|
+
// User types score
|
|
1576
|
+
score += analysis.userTypes.length * 5;
|
|
1577
|
+
// Data entities score
|
|
1578
|
+
score += Math.min(analysis.dataEntities.length * 3, 15);
|
|
1579
|
+
// Technical requirements score
|
|
1580
|
+
score += analysis.technicalRequirements.length * 5;
|
|
1581
|
+
return Math.min(score, 100);
|
|
1582
|
+
}
|
|
1583
|
+
// Helper methods for generating specific component types
|
|
1584
|
+
generateCoreComponents(analysis) {
|
|
1585
|
+
// This would generate components based on app type and intent
|
|
1586
|
+
// For now, return a basic set
|
|
1587
|
+
return [
|
|
1588
|
+
{
|
|
1589
|
+
name: `${analysis.appType.charAt(0).toUpperCase() + analysis.appType.slice(1)}App`,
|
|
1590
|
+
description: `Main application container for ${analysis.appType} functionality`,
|
|
1591
|
+
type: "layout",
|
|
1592
|
+
priority: "high",
|
|
1593
|
+
userStories: [
|
|
1594
|
+
`As a user, I want to access ${analysis.appType} features in a single application`,
|
|
1595
|
+
],
|
|
1596
|
+
actionFunctions: ["initializeApp", "handleNavigation", "manageState"],
|
|
1597
|
+
dependencies: ["layout", "state", "navigation"],
|
|
1598
|
+
tags: [analysis.appType, "app", "container"],
|
|
1599
|
+
},
|
|
1600
|
+
];
|
|
1601
|
+
}
|
|
1602
|
+
generateDataComponents(analysis) {
|
|
1603
|
+
const appType = analysis.appType;
|
|
1604
|
+
const dataEntities = analysis.dataEntities;
|
|
1605
|
+
const components = [];
|
|
1606
|
+
if (appType === "ecommerce") {
|
|
1607
|
+
components.push({
|
|
1608
|
+
name: "ProductList",
|
|
1609
|
+
description: "Display and manage product catalog",
|
|
1610
|
+
type: "display",
|
|
1611
|
+
priority: "high",
|
|
1612
|
+
userStories: [
|
|
1613
|
+
"As a user, I want to browse products to find items to purchase",
|
|
1614
|
+
],
|
|
1615
|
+
actionFunctions: ["loadProducts", "filterProducts", "sortProducts"],
|
|
1616
|
+
dependencies: ["list", "card", "button"],
|
|
1617
|
+
tags: ["product", "list", "catalog"],
|
|
1618
|
+
});
|
|
1619
|
+
components.push({
|
|
1620
|
+
name: "ProductDetail",
|
|
1621
|
+
description: "Show detailed information about a specific product",
|
|
1622
|
+
type: "display",
|
|
1623
|
+
priority: "medium",
|
|
1624
|
+
userStories: ["As a user, I want to view detailed product information"],
|
|
1625
|
+
actionFunctions: ["loadProductDetails", "addToCart"],
|
|
1626
|
+
dependencies: ["card", "button", "image"],
|
|
1627
|
+
tags: ["product", "detail", "information"],
|
|
1628
|
+
});
|
|
1629
|
+
components.push({
|
|
1630
|
+
name: "ShoppingCart",
|
|
1631
|
+
description: "Manage items added to the shopping cart",
|
|
1632
|
+
type: "interactive",
|
|
1633
|
+
priority: "high",
|
|
1634
|
+
userStories: [
|
|
1635
|
+
"As a user, I want to add items to my cart so that I can purchase multiple items",
|
|
1636
|
+
],
|
|
1637
|
+
actionFunctions: [
|
|
1638
|
+
"addItemToCart",
|
|
1639
|
+
"removeItemFromCart",
|
|
1640
|
+
"updateQuantity",
|
|
1641
|
+
],
|
|
1642
|
+
dependencies: ["cart", "button", "input"],
|
|
1643
|
+
tags: ["cart", "shopping", "checkout"],
|
|
1644
|
+
});
|
|
1645
|
+
components.push({
|
|
1646
|
+
name: "CheckoutForm",
|
|
1647
|
+
description: "Multi-step checkout process with payment",
|
|
1648
|
+
type: "form",
|
|
1649
|
+
priority: "high",
|
|
1650
|
+
userStories: ["As a user, I want to complete my purchase securely"],
|
|
1651
|
+
actionFunctions: ["validateCheckout", "processPayment", "confirmOrder"],
|
|
1652
|
+
dependencies: ["form", "payment-gateway", "validation"],
|
|
1653
|
+
tags: ["checkout", "payment", "form"],
|
|
1654
|
+
});
|
|
1655
|
+
components.push({
|
|
1656
|
+
name: "OrderHistory",
|
|
1657
|
+
description: "Display user's order history and status",
|
|
1658
|
+
type: "display",
|
|
1659
|
+
priority: "medium",
|
|
1660
|
+
userStories: [
|
|
1661
|
+
"As a user, I want to view my order history and track orders",
|
|
1662
|
+
],
|
|
1663
|
+
actionFunctions: ["loadOrderHistory", "trackOrder", "cancelOrder"],
|
|
1664
|
+
dependencies: ["list", "order-item", "status-indicator"],
|
|
1665
|
+
tags: ["order", "history", "tracking"],
|
|
1666
|
+
});
|
|
1667
|
+
components.push({
|
|
1668
|
+
name: "UserProfile",
|
|
1669
|
+
description: "Manage user account and preferences",
|
|
1670
|
+
type: "form",
|
|
1671
|
+
priority: "medium",
|
|
1672
|
+
userStories: ["As a user, I want to manage my account and preferences"],
|
|
1673
|
+
actionFunctions: ["loadUserProfile", "updateProfile", "changePassword"],
|
|
1674
|
+
dependencies: ["form", "avatar", "settings"],
|
|
1675
|
+
tags: ["user", "profile", "account"],
|
|
1676
|
+
});
|
|
1677
|
+
}
|
|
1678
|
+
else if (appType === "dashboard") {
|
|
1679
|
+
components.push({
|
|
1680
|
+
name: "DashboardOverview",
|
|
1681
|
+
description: "Display key metrics and quick actions",
|
|
1682
|
+
type: "display",
|
|
1683
|
+
priority: "high",
|
|
1684
|
+
userStories: [
|
|
1685
|
+
"As a user, I want to see analytics and performance metrics",
|
|
1686
|
+
],
|
|
1687
|
+
actionFunctions: ["loadOverviewData", "updateCharts"],
|
|
1688
|
+
dependencies: ["card", "chart", "metric-cards"],
|
|
1689
|
+
tags: ["dashboard", "overview", "metrics"],
|
|
1690
|
+
});
|
|
1691
|
+
components.push({
|
|
1692
|
+
name: "DataGrid",
|
|
1693
|
+
description: "Display and manage tabular data",
|
|
1694
|
+
type: "display",
|
|
1695
|
+
priority: "medium",
|
|
1696
|
+
userStories: [
|
|
1697
|
+
"As a user, I want to view and manage data in a table format",
|
|
1698
|
+
],
|
|
1699
|
+
actionFunctions: ["loadData", "filterData", "sortData"],
|
|
1700
|
+
dependencies: ["table", "input", "button"],
|
|
1701
|
+
tags: ["data", "grid", "table"],
|
|
1702
|
+
});
|
|
1703
|
+
}
|
|
1704
|
+
else if (appType === "productivity") {
|
|
1705
|
+
components.push({
|
|
1706
|
+
name: "TodoList",
|
|
1707
|
+
description: "Display and manage todo items",
|
|
1708
|
+
type: "display",
|
|
1709
|
+
priority: "high",
|
|
1710
|
+
userStories: ["As a user, I want to view and manage todo items"],
|
|
1711
|
+
actionFunctions: ["loadTodos", "addTodo", "completeTodo", "deleteTodo"],
|
|
1712
|
+
dependencies: ["list", "item", "button"],
|
|
1713
|
+
tags: ["todo", "list", "task"],
|
|
1714
|
+
});
|
|
1715
|
+
components.push({
|
|
1716
|
+
name: "TaskDetail",
|
|
1717
|
+
description: "Show detailed information about a specific task",
|
|
1718
|
+
type: "display",
|
|
1719
|
+
priority: "medium",
|
|
1720
|
+
userStories: ["As a user, I want to view detailed task information"],
|
|
1721
|
+
actionFunctions: ["loadTaskDetails", "updateTaskStatus"],
|
|
1722
|
+
dependencies: ["card", "button", "checkbox"],
|
|
1723
|
+
tags: ["task", "detail", "information"],
|
|
1724
|
+
});
|
|
1725
|
+
}
|
|
1726
|
+
else if (appType === "weather") {
|
|
1727
|
+
components.push({
|
|
1728
|
+
name: "WeatherForecast",
|
|
1729
|
+
description: "Display weather forecast for a specific location",
|
|
1730
|
+
type: "display",
|
|
1731
|
+
priority: "high",
|
|
1732
|
+
userStories: ["As a user, I want to see weather forecast"],
|
|
1733
|
+
actionFunctions: ["loadWeatherForecast", "changeLocation"],
|
|
1734
|
+
dependencies: ["card", "chart", "location-picker"],
|
|
1735
|
+
tags: ["weather", "forecast", "temperature"],
|
|
1736
|
+
});
|
|
1737
|
+
components.push({
|
|
1738
|
+
name: "WeatherHistory",
|
|
1739
|
+
description: "Display historical weather data",
|
|
1740
|
+
type: "display",
|
|
1741
|
+
priority: "medium",
|
|
1742
|
+
userStories: ["As a user, I want to view historical weather data"],
|
|
1743
|
+
actionFunctions: ["loadWeatherHistory", "selectDateRange"],
|
|
1744
|
+
dependencies: ["chart", "date-picker"],
|
|
1745
|
+
tags: ["weather", "history", "temperature"],
|
|
1746
|
+
});
|
|
1747
|
+
}
|
|
1748
|
+
else if (appType === "finance") {
|
|
1749
|
+
components.push({
|
|
1750
|
+
name: "TransactionList",
|
|
1751
|
+
description: "Display and manage financial transactions",
|
|
1752
|
+
type: "display",
|
|
1753
|
+
priority: "high",
|
|
1754
|
+
userStories: [
|
|
1755
|
+
"As a user, I want to view and manage financial transactions",
|
|
1756
|
+
],
|
|
1757
|
+
actionFunctions: [
|
|
1758
|
+
"loadTransactions",
|
|
1759
|
+
"filterTransactions",
|
|
1760
|
+
"sortTransactions",
|
|
1761
|
+
],
|
|
1762
|
+
dependencies: ["list", "transaction-item", "button"],
|
|
1763
|
+
tags: ["transaction", "list", "finance"],
|
|
1764
|
+
});
|
|
1765
|
+
components.push({
|
|
1766
|
+
name: "BudgetOverview",
|
|
1767
|
+
description: "Display budget overview and spending trends",
|
|
1768
|
+
type: "display",
|
|
1769
|
+
priority: "medium",
|
|
1770
|
+
userStories: [
|
|
1771
|
+
"As a user, I want to see budget overview and spending trends",
|
|
1772
|
+
],
|
|
1773
|
+
actionFunctions: ["loadBudgetOverview", "updateBudget"],
|
|
1774
|
+
dependencies: ["card", "chart", "budget-form"],
|
|
1775
|
+
tags: ["budget", "overview", "spending"],
|
|
1776
|
+
});
|
|
1777
|
+
}
|
|
1778
|
+
// Add more specific components for other app types if needed
|
|
1779
|
+
return components;
|
|
1780
|
+
}
|
|
1781
|
+
generateLayoutComponents(analysis) {
|
|
1782
|
+
return [
|
|
1783
|
+
{
|
|
1784
|
+
name: "AppLayout",
|
|
1785
|
+
description: "Main application layout with navigation",
|
|
1786
|
+
type: "layout",
|
|
1787
|
+
priority: "high",
|
|
1788
|
+
userStories: [
|
|
1789
|
+
"As a user, I want to navigate between different sections easily",
|
|
1790
|
+
],
|
|
1791
|
+
actionFunctions: [
|
|
1792
|
+
"handleNavigation",
|
|
1793
|
+
"toggleSidebar",
|
|
1794
|
+
"updateBreadcrumbs",
|
|
1795
|
+
],
|
|
1796
|
+
dependencies: ["header", "sidebar", "main"],
|
|
1797
|
+
tags: ["layout", "navigation", "structure"],
|
|
1798
|
+
},
|
|
1799
|
+
];
|
|
1800
|
+
}
|
|
1801
|
+
generateInteractionComponents(analysis) {
|
|
1802
|
+
return [
|
|
1803
|
+
{
|
|
1804
|
+
name: "ActionForm",
|
|
1805
|
+
description: "Form for user interactions and data input",
|
|
1806
|
+
type: "form",
|
|
1807
|
+
priority: "medium",
|
|
1808
|
+
userStories: ["As a user, I want to input data and perform actions"],
|
|
1809
|
+
actionFunctions: ["handleSubmit", "validateInput", "clearForm"],
|
|
1810
|
+
dependencies: ["input", "button", "form"],
|
|
1811
|
+
tags: ["form", "interaction", "input"],
|
|
1812
|
+
},
|
|
1813
|
+
];
|
|
1814
|
+
}
|
|
1815
|
+
generateAnalyticsComponents(analysis) {
|
|
1816
|
+
return [
|
|
1817
|
+
{
|
|
1818
|
+
name: "AnalyticsDashboard",
|
|
1819
|
+
description: "Display analytics and metrics",
|
|
1820
|
+
type: "display",
|
|
1821
|
+
priority: "medium",
|
|
1822
|
+
userStories: [
|
|
1823
|
+
"As a user, I want to see analytics and performance metrics",
|
|
1824
|
+
],
|
|
1825
|
+
actionFunctions: ["loadMetrics", "updateCharts", "exportData"],
|
|
1826
|
+
dependencies: ["chart", "card", "table"],
|
|
1827
|
+
tags: ["analytics", "metrics", "dashboard"],
|
|
1828
|
+
},
|
|
1829
|
+
];
|
|
1830
|
+
}
|
|
1831
|
+
generateComponentListMarkdown(data) {
|
|
1832
|
+
const { project, groups, metadata } = data;
|
|
1833
|
+
let markdown = `# Component List
|
|
1834
|
+
|
|
1835
|
+
## Project Overview
|
|
1836
|
+
**Project Name:** ${project?.name || "MyContext Project"}
|
|
1837
|
+
**Description:** ${project?.description || "AI-powered component generation platform"}
|
|
1838
|
+
**Generated:** ${project?.generated || new Date().toISOString().split("T")[0]}
|
|
1839
|
+
|
|
1840
|
+
## Summary
|
|
1841
|
+
- **Total Components:** ${metadata?.totalComponents ||
|
|
1842
|
+
groups?.reduce((acc, g) => acc + (g.components?.length || 0), 0) ||
|
|
1843
|
+
0}
|
|
1844
|
+
- **Total Groups:** ${metadata?.totalGroups || groups?.length || 0}
|
|
1845
|
+
- **Version:** ${metadata?.version || "1.0.0"}
|
|
1846
|
+
|
|
1847
|
+
---
|
|
1848
|
+
|
|
1849
|
+
`;
|
|
1850
|
+
if (groups && Array.isArray(groups)) {
|
|
1851
|
+
groups.forEach((group) => {
|
|
1852
|
+
markdown += `## ${group.name}
|
|
1853
|
+
|
|
1854
|
+
**Description:** ${group.description}
|
|
1855
|
+
**Priority:** ${group.priority}
|
|
1856
|
+
**Components:** ${group.components?.length || 0}
|
|
1857
|
+
|
|
1858
|
+
`;
|
|
1859
|
+
if (group.components && Array.isArray(group.components)) {
|
|
1860
|
+
group.components.forEach((component) => {
|
|
1861
|
+
markdown += `### ${component.name}
|
|
1862
|
+
|
|
1863
|
+
**Type:** ${component.type}
|
|
1864
|
+
**Priority:** ${component.priority}
|
|
1865
|
+
**Description:** ${component.description}
|
|
1866
|
+
|
|
1867
|
+
**User Stories:**
|
|
1868
|
+
${component.userStories?.map((story) => `- ${story}`).join("\n") ||
|
|
1869
|
+
"- No user stories defined"}
|
|
1870
|
+
|
|
1871
|
+
**Action Functions:**
|
|
1872
|
+
${component.actionFunctions
|
|
1873
|
+
?.map((func) => `- \`${func}\``)
|
|
1874
|
+
.join("\n") || "- No action functions defined"}
|
|
1875
|
+
|
|
1876
|
+
**Dependencies:** ${component.dependencies?.join(", ") || "None"}
|
|
1877
|
+
**Tags:** ${component.tags?.join(", ") || "None"}
|
|
1878
|
+
|
|
1879
|
+
---
|
|
1880
|
+
`;
|
|
1881
|
+
});
|
|
1882
|
+
}
|
|
1883
|
+
});
|
|
1884
|
+
}
|
|
1885
|
+
markdown += `
|
|
1886
|
+
## Implementation Notes
|
|
1887
|
+
|
|
1888
|
+
### Building Blocks Philosophy
|
|
1889
|
+
Each component is designed as a reusable building block that can:
|
|
1890
|
+
- Work across different projects
|
|
1891
|
+
- Include specific action functions for user workflows
|
|
1892
|
+
- Be easily customized and extended
|
|
1893
|
+
- Follow consistent design patterns
|
|
1894
|
+
|
|
1895
|
+
### User Story Integration
|
|
1896
|
+
Components are mapped to specific user stories to ensure they serve real user needs and provide actionable functionality.
|
|
1897
|
+
|
|
1898
|
+
### Action Functions
|
|
1899
|
+
Every component includes action functions that handle the business logic and user interactions, making them truly useful rather than just visual elements.
|
|
1900
|
+
|
|
1901
|
+
---
|
|
1902
|
+
|
|
1903
|
+
*This component list serves as the blueprint for generating production-ready UI components that fulfill specific user workflows and can be reused across projects.*
|
|
1904
|
+
`;
|
|
1905
|
+
return markdown;
|
|
1906
|
+
}
|
|
1907
|
+
async generateLocalAppStructure(context) {
|
|
1908
|
+
return {
|
|
1909
|
+
directoryStructure: `
|
|
1910
|
+
app/
|
|
1911
|
+
├── layout.tsx
|
|
1912
|
+
├── page.tsx
|
|
1913
|
+
├── globals.css
|
|
1914
|
+
├── (auth)/
|
|
1915
|
+
│ ├── login/
|
|
1916
|
+
│ └── register/
|
|
1917
|
+
├── (dashboard)/
|
|
1918
|
+
│ ├── projects/
|
|
1919
|
+
│ └── settings/
|
|
1920
|
+
components/
|
|
1921
|
+
├── ui/
|
|
1922
|
+
└── custom/
|
|
1923
|
+
lib/
|
|
1924
|
+
├── utils.ts
|
|
1925
|
+
└── types.ts
|
|
1926
|
+
`,
|
|
1927
|
+
fileTemplates: {
|
|
1928
|
+
"app/layout.tsx": "// Root layout component",
|
|
1929
|
+
"app/page.tsx": "// Home page component",
|
|
1930
|
+
"components/ui/button.tsx": "// Button component",
|
|
1931
|
+
},
|
|
1932
|
+
componentUsage: {
|
|
1933
|
+
UserProfile: "Display user information with avatar and settings",
|
|
1934
|
+
ProjectCard: "Show project details in a card format",
|
|
1935
|
+
},
|
|
1936
|
+
};
|
|
1937
|
+
}
|
|
1938
|
+
async writeContextFiles(files) {
|
|
1939
|
+
for (const [filename, content] of Object.entries(files)) {
|
|
1940
|
+
await this.fs.writeFile(`context/${filename}`, content);
|
|
1941
|
+
}
|
|
1942
|
+
}
|
|
1943
|
+
async findPRDFile() {
|
|
1944
|
+
const possiblePaths = [
|
|
1945
|
+
"context/prd.md",
|
|
1946
|
+
"context/PRD.md",
|
|
1947
|
+
"context/01_PRD.md",
|
|
1948
|
+
".mycontext/context/prd.md",
|
|
1949
|
+
"prd.md",
|
|
1950
|
+
"PRD.md",
|
|
1951
|
+
];
|
|
1952
|
+
for (const path of possiblePaths) {
|
|
1953
|
+
try {
|
|
1954
|
+
await this.fs.readFile(path);
|
|
1955
|
+
return path;
|
|
1956
|
+
}
|
|
1957
|
+
catch {
|
|
1958
|
+
continue;
|
|
1959
|
+
}
|
|
1960
|
+
}
|
|
1961
|
+
return null;
|
|
1962
|
+
}
|
|
1963
|
+
async readContextFiles() {
|
|
1964
|
+
const files = {};
|
|
1965
|
+
const filePaths = [
|
|
1966
|
+
"context/01_PRD.md",
|
|
1967
|
+
"context/02_user_stories.md",
|
|
1968
|
+
"context/03_technical_specs.md",
|
|
1969
|
+
"context/types.ts",
|
|
1970
|
+
"context/branding.md",
|
|
1971
|
+
];
|
|
1972
|
+
for (const filePath of filePaths) {
|
|
1973
|
+
try {
|
|
1974
|
+
files[filePath] = await this.fs.readFile(filePath);
|
|
1975
|
+
}
|
|
1976
|
+
catch {
|
|
1977
|
+
// File doesn't exist, skip
|
|
1978
|
+
}
|
|
1979
|
+
}
|
|
1980
|
+
return files;
|
|
1981
|
+
}
|
|
1982
|
+
}
|
|
1983
|
+
exports.GenerateCommand = GenerateCommand;
|
|
1984
|
+
//# sourceMappingURL=generate.js.map
|