mycontext-cli 4.2.16 → 4.2.18
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 +62 -96
- package/dist/agents/implementations/SolverAgent.d.ts +42 -0
- package/dist/agents/implementations/SolverAgent.d.ts.map +1 -0
- package/dist/agents/implementations/SolverAgent.js +543 -0
- package/dist/agents/implementations/SolverAgent.js.map +1 -0
- package/dist/cli.js +143 -43
- package/dist/cli.js.map +1 -1
- package/dist/clients/ClaudeSDKClient.d.ts +1 -0
- package/dist/clients/ClaudeSDKClient.d.ts.map +1 -1
- package/dist/clients/ClaudeSDKClient.js +3 -0
- package/dist/clients/ClaudeSDKClient.js.map +1 -1
- package/dist/clients/MyContextAIClient.d.ts +4 -0
- package/dist/clients/MyContextAIClient.d.ts.map +1 -1
- package/dist/clients/MyContextAIClient.js +6 -0
- package/dist/clients/MyContextAIClient.js.map +1 -1
- package/dist/clients/ProviderChain.d.ts +1 -0
- package/dist/clients/ProviderChain.d.ts.map +1 -1
- package/dist/clients/ProviderChain.js +3 -0
- package/dist/clients/ProviderChain.js.map +1 -1
- package/dist/clients/XAIClient.d.ts +4 -0
- package/dist/clients/XAIClient.d.ts.map +1 -1
- package/dist/clients/XAIClient.js +6 -0
- package/dist/clients/XAIClient.js.map +1 -1
- package/dist/commands/add.d.ts +17 -0
- package/dist/commands/add.d.ts.map +1 -0
- package/dist/commands/add.js +164 -0
- package/dist/commands/add.js.map +1 -0
- package/dist/commands/build.d.ts +10 -0
- package/dist/commands/build.d.ts.map +1 -0
- package/dist/commands/build.js +37 -0
- package/dist/commands/build.js.map +1 -0
- package/dist/commands/generate-assets.d.ts +11 -0
- package/dist/commands/generate-assets.d.ts.map +1 -0
- package/dist/commands/generate-assets.js +131 -0
- package/dist/commands/generate-assets.js.map +1 -0
- package/dist/commands/generate-components.d.ts.map +1 -1
- package/dist/commands/generate-components.js +21 -18
- package/dist/commands/generate-components.js.map +1 -1
- package/dist/commands/generate-screens.d.ts +5 -0
- package/dist/commands/generate-screens.d.ts.map +1 -1
- package/dist/commands/generate-screens.js +160 -12
- package/dist/commands/generate-screens.js.map +1 -1
- package/dist/commands/generate.d.ts +3 -0
- package/dist/commands/generate.d.ts.map +1 -1
- package/dist/commands/generate.js +285 -167
- package/dist/commands/generate.js.map +1 -1
- package/dist/commands/ideate.d.ts +14 -0
- package/dist/commands/ideate.d.ts.map +1 -0
- package/dist/commands/ideate.js +153 -0
- package/dist/commands/ideate.js.map +1 -0
- package/dist/commands/init-interactive.d.ts.map +1 -1
- package/dist/commands/init-interactive.js +30 -2
- package/dist/commands/init-interactive.js.map +1 -1
- package/dist/commands/init.d.ts +2 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +220 -39
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/migrate-transform.d.ts +16 -0
- package/dist/commands/migrate-transform.d.ts.map +1 -0
- package/dist/commands/migrate-transform.js +135 -0
- package/dist/commands/migrate-transform.js.map +1 -0
- package/dist/commands/setup-complete.d.ts.map +1 -1
- package/dist/commands/setup-complete.js +4 -6
- package/dist/commands/setup-complete.js.map +1 -1
- package/dist/commands/sync-readme.d.ts +3 -1
- package/dist/commands/sync-readme.d.ts.map +1 -1
- package/dist/commands/sync-readme.js +57 -59
- package/dist/commands/sync-readme.js.map +1 -1
- package/dist/commands/vision-test.d.ts.map +1 -1
- package/dist/commands/vision-test.js +8 -0
- package/dist/commands/vision-test.js.map +1 -1
- package/dist/commands/workflow.d.ts.map +1 -1
- package/dist/commands/workflow.js +10 -58
- package/dist/commands/workflow.js.map +1 -1
- package/dist/constants/subAgentPersonalities.d.ts.map +1 -1
- package/dist/constants/subAgentPersonalities.js +29 -0
- package/dist/constants/subAgentPersonalities.js.map +1 -1
- package/dist/core/ai/AICore.d.ts +12 -0
- package/dist/core/ai/AICore.d.ts.map +1 -1
- package/dist/core/ai/AICore.js +56 -1
- package/dist/core/ai/AICore.js.map +1 -1
- package/dist/core/ai/TokenCostModel.d.ts +37 -0
- package/dist/core/ai/TokenCostModel.d.ts.map +1 -0
- package/dist/core/ai/TokenCostModel.js +132 -0
- package/dist/core/ai/TokenCostModel.js.map +1 -0
- package/dist/core/brain/BrainClient.d.ts +13 -1
- package/dist/core/brain/BrainClient.d.ts.map +1 -1
- package/dist/core/brain/BrainClient.js +49 -0
- package/dist/core/brain/BrainClient.js.map +1 -1
- package/dist/interfaces/AIClient.d.ts +4 -0
- package/dist/interfaces/AIClient.d.ts.map +1 -1
- package/dist/interfaces/AIClient.js.map +1 -1
- package/dist/services/MonorepoScanner.d.ts +18 -0
- package/dist/services/MonorepoScanner.d.ts.map +1 -0
- package/dist/services/MonorepoScanner.js +101 -0
- package/dist/services/MonorepoScanner.js.map +1 -0
- package/dist/services/ProjectScanner.d.ts.map +1 -1
- package/dist/services/ProjectScanner.js +7 -0
- package/dist/services/ProjectScanner.js.map +1 -1
- package/dist/services/ReadmeDeducer.d.ts +14 -0
- package/dist/services/ReadmeDeducer.d.ts.map +1 -0
- package/dist/services/ReadmeDeducer.js +109 -0
- package/dist/services/ReadmeDeducer.js.map +1 -0
- package/dist/tui/DashboardMode.d.ts +16 -0
- package/dist/tui/DashboardMode.d.ts.map +1 -0
- package/dist/tui/DashboardMode.js +190 -0
- package/dist/tui/DashboardMode.js.map +1 -0
- package/dist/tui/TUIClient.d.ts +9 -0
- package/dist/tui/TUIClient.d.ts.map +1 -1
- package/dist/tui/TUIClient.js +63 -0
- package/dist/tui/TUIClient.js.map +1 -1
- package/dist/types/constraint.d.ts +123 -0
- package/dist/types/constraint.d.ts.map +1 -0
- package/dist/types/constraint.js +13 -0
- package/dist/types/constraint.js.map +1 -0
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/living-context.d.ts +7 -0
- package/dist/types/living-context.d.ts.map +1 -1
- package/dist/types/tui.d.ts +3 -1
- package/dist/types/tui.d.ts.map +1 -1
- package/dist/utils/claudeAgentClient.d.ts +4 -0
- package/dist/utils/claudeAgentClient.d.ts.map +1 -1
- package/dist/utils/claudeAgentClient.js +6 -0
- package/dist/utils/claudeAgentClient.js.map +1 -1
- package/dist/utils/contextEnricher.d.ts +2 -1
- package/dist/utils/contextEnricher.d.ts.map +1 -1
- package/dist/utils/contextEnricher.js +138 -1
- package/dist/utils/contextEnricher.js.map +1 -1
- package/dist/utils/contextRenderer.d.ts +3 -0
- package/dist/utils/contextRenderer.d.ts.map +1 -1
- package/dist/utils/contextRenderer.js +101 -26
- package/dist/utils/contextRenderer.js.map +1 -1
- package/dist/utils/fileSystem.d.ts.map +1 -1
- package/dist/utils/fileSystem.js +32 -1
- package/dist/utils/fileSystem.js.map +1 -1
- package/dist/utils/geminiClient.d.ts +11 -1
- package/dist/utils/geminiClient.d.ts.map +1 -1
- package/dist/utils/geminiClient.js +109 -56
- package/dist/utils/geminiClient.js.map +1 -1
- package/dist/utils/githubModelsClient.d.ts +4 -0
- package/dist/utils/githubModelsClient.d.ts.map +1 -1
- package/dist/utils/githubModelsClient.js +10 -1
- package/dist/utils/githubModelsClient.js.map +1 -1
- package/dist/utils/openRouterClient.d.ts +1 -0
- package/dist/utils/openRouterClient.d.ts.map +1 -1
- package/dist/utils/openRouterClient.js +4 -0
- package/dist/utils/openRouterClient.js.map +1 -1
- package/dist/utils/unifiedDesignContextLoader.d.ts.map +1 -1
- package/dist/utils/unifiedDesignContextLoader.js +14 -0
- package/dist/utils/unifiedDesignContextLoader.js.map +1 -1
- package/package.json +27 -22
- package/dist/commands/assemble-features.d.ts +0 -40
- package/dist/commands/assemble-features.d.ts.map +0 -1
- package/dist/commands/assemble-features.js +0 -383
- package/dist/commands/assemble-features.js.map +0 -1
- package/dist/commands/compile-prd.d.ts +0 -18
- package/dist/commands/compile-prd.d.ts.map +0 -1
- package/dist/commands/compile-prd.js +0 -253
- package/dist/commands/compile-prd.js.map +0 -1
- package/dist/commands/generate-context-files.d.ts +0 -44
- package/dist/commands/generate-context-files.d.ts.map +0 -1
- package/dist/commands/generate-context-files.js +0 -871
- package/dist/commands/generate-context-files.js.map +0 -1
- package/dist/templates/playbooks/instantdb-integration.md +0 -851
- package/dist/templates/playbooks/mpesa-integration.md +0 -652
- package/dist/templates/ui-spec-examples.md +0 -318
|
@@ -50,6 +50,7 @@ const fs = __importStar(require("fs-extra"));
|
|
|
50
50
|
const typeTemplateGenerator_1 = require("../utils/typeTemplateGenerator");
|
|
51
51
|
const AICore_1 = require("../core/ai/AICore");
|
|
52
52
|
const contextRenderer_1 = require("../utils/contextRenderer");
|
|
53
|
+
const ProjectScanner_1 = require("../services/ProjectScanner");
|
|
53
54
|
class GenerateCommand {
|
|
54
55
|
constructor() {
|
|
55
56
|
this.fs = new fileSystem_1.FileSystemManager();
|
|
@@ -90,29 +91,16 @@ class GenerateCommand {
|
|
|
90
91
|
case "context":
|
|
91
92
|
case "prd":
|
|
92
93
|
case "requirements":
|
|
94
|
+
// Check if user wants full context generation (PRD + A/B/C/D files)
|
|
93
95
|
// Check if user wants full context generation (PRD + A/B/C/D files)
|
|
94
96
|
if (options.full) {
|
|
95
97
|
// Generate both PRD and A/B/C/D files
|
|
96
98
|
result = await this.generateFullContext(projectContext, options);
|
|
97
99
|
}
|
|
98
100
|
else {
|
|
99
|
-
// Default:
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
const { GenerateContextFilesCommand } = await Promise.resolve().then(() => __importStar(require("./generate-context-files")));
|
|
103
|
-
const contextFilesCommand = new GenerateContextFilesCommand();
|
|
104
|
-
await contextFilesCommand.execute({
|
|
105
|
-
description: projectContext.description,
|
|
106
|
-
projectPath: this.getProjectRoot(),
|
|
107
|
-
verbose: options.verbose,
|
|
108
|
-
force: options.force,
|
|
109
|
-
});
|
|
110
|
-
result = {
|
|
111
|
-
success: true,
|
|
112
|
-
content: "Context files generated successfully",
|
|
113
|
-
provider: "hybrid",
|
|
114
|
-
metadata: { model: "hybrid", tokens: 0, latency: 0 },
|
|
115
|
-
};
|
|
101
|
+
// Default: Direct to full generation as the new standard
|
|
102
|
+
console.log(chalk_1.default.blue("ℹ️ Note: 'generate context' now defaults to full brain synchronization."));
|
|
103
|
+
result = await this.generateFullContext(projectContext, options);
|
|
116
104
|
}
|
|
117
105
|
break;
|
|
118
106
|
case "types":
|
|
@@ -202,7 +190,7 @@ class GenerateCommand {
|
|
|
202
190
|
console.log(chalk_1.default.yellow(`⚠️ Project structure generation skipped or failed: ${structureRes.error || "unknown"}`));
|
|
203
191
|
}
|
|
204
192
|
this.spinner.success({
|
|
205
|
-
text: "🎉
|
|
193
|
+
text: "🎉 Context Scaffold Ready! Your Living Brain is now the perfect map for your next AI Agent.",
|
|
206
194
|
});
|
|
207
195
|
// Show next steps for the "all" workflow
|
|
208
196
|
this.printNextStepsAfterGenerate("all");
|
|
@@ -406,7 +394,40 @@ class GenerateCommand {
|
|
|
406
394
|
}
|
|
407
395
|
}
|
|
408
396
|
catch { }
|
|
409
|
-
// 5)
|
|
397
|
+
// 5) Auto-Inference fallback: Attempt to scan project if no PRD/Types found
|
|
398
|
+
try {
|
|
399
|
+
this.spinner.updateText("🔍 No context found. Inferring project structure...");
|
|
400
|
+
const scanner = new ProjectScanner_1.ProjectScanner(process.cwd());
|
|
401
|
+
const snapshot = await scanner.scan();
|
|
402
|
+
if (snapshot.stats.totalFiles > 5) {
|
|
403
|
+
const fileTree = snapshot.fileTree.filter(f => f.type === 'file').map(f => f.path).slice(0, 50).join('\n');
|
|
404
|
+
const keyFiles = snapshot.keyFiles.map(f => `--- ${f.path} ---\n${f.content}`).join('\n\n');
|
|
405
|
+
const inferenceDescription = `
|
|
406
|
+
AUTO-INFERRED PROJECT ANALYSIS:
|
|
407
|
+
The following project structure was detected. Please analyze it to build a comprehensive Living Brain.
|
|
408
|
+
|
|
409
|
+
STATS:
|
|
410
|
+
- Total Files: ${snapshot.stats.totalFiles}
|
|
411
|
+
- Route Files: ${snapshot.stats.routeFiles}
|
|
412
|
+
- Component Files: ${snapshot.stats.componentFiles}
|
|
413
|
+
- Schema Files: ${snapshot.stats.schemaFiles}
|
|
414
|
+
|
|
415
|
+
FILE TREE (Partial):
|
|
416
|
+
${fileTree}
|
|
417
|
+
|
|
418
|
+
KEY FILES CONTENT:
|
|
419
|
+
${keyFiles}
|
|
420
|
+
|
|
421
|
+
Based on this, generate a complete project context including PRD, Technical Specs, and Component Architecture.
|
|
422
|
+
`;
|
|
423
|
+
console.log(chalk_1.default.blue("\n✨ Auto-inferred project context from codebase (Self-Analysis Mode)"));
|
|
424
|
+
return { description: inferenceDescription };
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
catch (e) {
|
|
428
|
+
// Fallback to interactive prompts
|
|
429
|
+
}
|
|
430
|
+
// 6) Interactive prompt to capture description (when not in --yes)
|
|
410
431
|
if (!options.yes) {
|
|
411
432
|
this.spinner.stop();
|
|
412
433
|
console.log(chalk_1.default.yellow("\n⚠️ No context files found (.mycontext/01-prd.md or .mycontext/types/)"));
|
|
@@ -436,7 +457,7 @@ class GenerateCommand {
|
|
|
436
457
|
}
|
|
437
458
|
this.spinner.start().updateText("Continuing without description...");
|
|
438
459
|
}
|
|
439
|
-
//
|
|
460
|
+
// 7) Fallback to project config
|
|
440
461
|
return await this.getProjectContext();
|
|
441
462
|
}
|
|
442
463
|
async generateContext(projectContext, options) {
|
|
@@ -658,9 +679,11 @@ Use the business entities from the context above, not generic types.`;
|
|
|
658
679
|
const hasLocalKeys = this.hasLocalAIKeys();
|
|
659
680
|
if (hasLocalKeys) {
|
|
660
681
|
// Use local AI first (user's own keys)
|
|
661
|
-
|
|
682
|
+
// DEFAULT to gpt-4o-mini for planning tasks to avoid 8k token limits
|
|
683
|
+
const model = options.model || process.env.MYCONTEXT_MODEL || "gpt-4o-mini";
|
|
684
|
+
this.spinner.updateText(`🔧 Generating TypeScript types with ${await this.ai.getActiveProviderName()} (${model})...`);
|
|
662
685
|
const { text, provider } = await this.ai.generateText(prompt, {
|
|
663
|
-
model
|
|
686
|
+
model,
|
|
664
687
|
modelCandidates: this.getModelCandidates(options),
|
|
665
688
|
spinnerCallback: (text, resetTimer = false) => {
|
|
666
689
|
this.spinner.updateText(text);
|
|
@@ -671,6 +694,13 @@ Use the business entities from the context above, not generic types.`;
|
|
|
671
694
|
});
|
|
672
695
|
// Parse the generated content and create structured files
|
|
673
696
|
const structuredContent = this.parseAndStructureTypes(text);
|
|
697
|
+
// Update SSOT (Brain)
|
|
698
|
+
await this.updateLivingContext({
|
|
699
|
+
metadata: {
|
|
700
|
+
lastUpdatedAt: new Date().toISOString(),
|
|
701
|
+
status: "types-generated"
|
|
702
|
+
}
|
|
703
|
+
});
|
|
674
704
|
// Check if AI generated generic types (fallback detection)
|
|
675
705
|
if ((0, typeTemplateGenerator_1.isGenericTypes)(structuredContent)) {
|
|
676
706
|
console.log("⚠️ AI generated generic types, using template fallback...");
|
|
@@ -923,11 +953,27 @@ Use the business entities from the context above, not generic types.`;
|
|
|
923
953
|
}
|
|
924
954
|
return contextContent;
|
|
925
955
|
}
|
|
956
|
+
truncateContext(text, maxChars = 4000) {
|
|
957
|
+
if (!text || text.length <= maxChars)
|
|
958
|
+
return text;
|
|
959
|
+
return text.substring(0, maxChars) + "\n\n... [TRUNCATED FOR TOKENS] ...";
|
|
960
|
+
}
|
|
926
961
|
/**
|
|
927
962
|
* Unified method to load all context files for consistent discovery
|
|
928
963
|
*/
|
|
929
964
|
async loadAllContextFiles() {
|
|
930
965
|
const projectRoot = this.getProjectRoot();
|
|
966
|
+
const livingBrain = await this.loadLivingContext();
|
|
967
|
+
if (livingBrain) {
|
|
968
|
+
return {
|
|
969
|
+
prd: livingBrain.prd.title + "\n" + livingBrain.prd.problemStatement,
|
|
970
|
+
features: livingBrain.features.map(f => `${f.name}: ${f.description}`).join("\n"),
|
|
971
|
+
userFlows: livingBrain.flows.map(f => `${f.name}: ${f.steps.join(", ")}`).join("\n"),
|
|
972
|
+
edgeCases: livingBrain.edgeCases.map(e => `${e.category}: ${e.description}`).join("\n"),
|
|
973
|
+
technicalSpecs: livingBrain.specs.architecture,
|
|
974
|
+
hasContext: true,
|
|
975
|
+
};
|
|
976
|
+
}
|
|
931
977
|
const contextDir = path_1.default.join(projectRoot, ".mycontext");
|
|
932
978
|
const readOrEmpty = async (filePath) => {
|
|
933
979
|
if (await fs.pathExists(filePath)) {
|
|
@@ -1774,9 +1820,11 @@ Make the CSS immediately usable - no placeholders, actual working values!`;
|
|
|
1774
1820
|
const hasLocalKeys = this.hasLocalAIKeys();
|
|
1775
1821
|
if (hasLocalKeys) {
|
|
1776
1822
|
// Use local AI first (user's own keys)
|
|
1777
|
-
|
|
1823
|
+
// DEFAULT to gpt-4o-mini for planning tasks to avoid 8k token limits
|
|
1824
|
+
const model = options.model || process.env.MYCONTEXT_MODEL || "gpt-4o-mini";
|
|
1825
|
+
this.spinner.updateText(`🎨 Generating brand system with ${await this.ai.getActiveProviderName()} (${model})...`);
|
|
1778
1826
|
const { text, provider } = await this.ai.generateText(prompt, {
|
|
1779
|
-
model
|
|
1827
|
+
model,
|
|
1780
1828
|
modelCandidates: this.getModelCandidates(options),
|
|
1781
1829
|
spinnerCallback: (text, resetTimer = false) => {
|
|
1782
1830
|
this.spinner.updateText(text);
|
|
@@ -1787,6 +1835,13 @@ Make the CSS immediately usable - no placeholders, actual working values!`;
|
|
|
1787
1835
|
});
|
|
1788
1836
|
// Parse and create the brand system files
|
|
1789
1837
|
const brandFiles = this.parseAndCreateBrandSystem(text);
|
|
1838
|
+
// Update SSOT (Brain)
|
|
1839
|
+
await this.updateLivingContext({
|
|
1840
|
+
metadata: {
|
|
1841
|
+
lastUpdatedAt: new Date().toISOString(),
|
|
1842
|
+
status: "brand-generated"
|
|
1843
|
+
}
|
|
1844
|
+
});
|
|
1790
1845
|
return {
|
|
1791
1846
|
success: true,
|
|
1792
1847
|
content: brandFiles.guide,
|
|
@@ -1891,23 +1946,37 @@ Make the CSS immediately usable - no placeholders, actual working values!`;
|
|
|
1891
1946
|
}
|
|
1892
1947
|
}
|
|
1893
1948
|
async generateComponentList(projectContext, options) {
|
|
1949
|
+
// 1. Try to load from Living Brain first
|
|
1950
|
+
const livingContext = await this.loadLivingContext();
|
|
1951
|
+
if (livingContext && livingContext.components && livingContext.components.length > 0 && !options.force) {
|
|
1952
|
+
this.spinner.updateText("📋 Using component architecture from Living Brain...");
|
|
1953
|
+
return {
|
|
1954
|
+
success: true,
|
|
1955
|
+
content: JSON.stringify(livingContext.components, null, 2),
|
|
1956
|
+
provider: "local",
|
|
1957
|
+
metadata: {
|
|
1958
|
+
model: "static",
|
|
1959
|
+
tokens: 0,
|
|
1960
|
+
latency: 0,
|
|
1961
|
+
},
|
|
1962
|
+
};
|
|
1963
|
+
}
|
|
1964
|
+
// 2. Fallback to AI generation if brain is empty or force is used
|
|
1965
|
+
this.spinner.updateText("📋 Discovering component architecture via AI...");
|
|
1894
1966
|
// Load comprehensive context for better component generation
|
|
1895
1967
|
const allContext = await this.loadAllContextFiles();
|
|
1896
1968
|
const ctx = await this.readContextArtifacts();
|
|
1897
|
-
// Note: No core readiness check here - components-list generation should happen
|
|
1898
|
-
// before any core component is selected and refined
|
|
1899
1969
|
const coreExcerpt = await this.readCoreExcerpt();
|
|
1970
|
+
// DEFAULT to gpt-4o-mini for planning tasks to avoid 8k token limits
|
|
1971
|
+
const model = options.model || process.env.MYCONTEXT_MODEL || "gpt-4o-mini";
|
|
1900
1972
|
const prompt = [
|
|
1901
|
-
`[mycontext]
|
|
1902
|
-
`Create a detailed, business-specific component list for: ${projectContext.description || "MyContext project"}`,
|
|
1903
|
-
"",
|
|
1904
|
-
"IMPORTANT: Use the detailed business context below to create components that directly implement the specific features, user stories, and acceptance criteria described. Extract exact feature names, user roles, and business requirements to generate precise, domain-specific components.",
|
|
1973
|
+
`[mycontext] Planning: Identify and decompose components for: ${projectContext.description || "MyContext project"}`,
|
|
1905
1974
|
"",
|
|
1906
|
-
"
|
|
1975
|
+
"IMPORTANT: Use the detailed business context below to create components that directly implement the specific features described. Group components by domain (e.g., Auth, Dashboard, Billing).",
|
|
1907
1976
|
"",
|
|
1908
1977
|
...(coreExcerpt
|
|
1909
1978
|
? [
|
|
1910
|
-
"Core component
|
|
1979
|
+
"Core component style (use for reference):",
|
|
1911
1980
|
coreExcerpt,
|
|
1912
1981
|
"",
|
|
1913
1982
|
]
|
|
@@ -1915,90 +1984,38 @@ Make the CSS immediately usable - no placeholders, actual working values!`;
|
|
|
1915
1984
|
"Business Context:",
|
|
1916
1985
|
allContext.hasContext
|
|
1917
1986
|
? [
|
|
1918
|
-
allContext.prd ? `## PRD\n${allContext.prd}` : "",
|
|
1919
|
-
allContext.features ? `## Features\n${allContext.features}` : "",
|
|
1920
|
-
allContext.userFlows
|
|
1921
|
-
|
|
1922
|
-
: "",
|
|
1923
|
-
allContext.edgeCases
|
|
1924
|
-
? `## Edge Cases\n${allContext.edgeCases}`
|
|
1925
|
-
: "",
|
|
1926
|
-
allContext.technicalSpecs
|
|
1927
|
-
? `## Technical Specs\n${allContext.technicalSpecs}`
|
|
1928
|
-
: "",
|
|
1987
|
+
allContext.prd ? `## PRD\n${this.truncateContext(allContext.prd)}` : "",
|
|
1988
|
+
allContext.features ? `## Features\n${this.truncateContext(allContext.features)}` : "",
|
|
1989
|
+
allContext.userFlows ? `## User Flows\n${this.truncateContext(allContext.userFlows)}` : "",
|
|
1990
|
+
allContext.technicalSpecs ? `## Technical Specs\n${this.truncateContext(allContext.technicalSpecs)}` : "",
|
|
1929
1991
|
]
|
|
1930
1992
|
.filter(Boolean)
|
|
1931
1993
|
.join("\n\n")
|
|
1932
|
-
: ctx.prd
|
|
1994
|
+
: this.truncateContext(ctx.prd, 2000),
|
|
1933
1995
|
"",
|
|
1934
|
-
"Types
|
|
1935
|
-
ctx.types
|
|
1996
|
+
"Types Summary:",
|
|
1997
|
+
this.truncateContext(ctx.types, 3000),
|
|
1936
1998
|
"",
|
|
1937
|
-
"Branding
|
|
1938
|
-
ctx.brand
|
|
1999
|
+
"Branding Summary:",
|
|
2000
|
+
this.truncateContext(ctx.brand, 1500),
|
|
1939
2001
|
"",
|
|
1940
|
-
"Available shadcn/ui primitives
|
|
2002
|
+
"Available shadcn/ui primitives:",
|
|
1941
2003
|
(ctx.shadcn.length ? ctx.shadcn : this.getCanonicalShadcnList())
|
|
1942
2004
|
.slice(0, 60)
|
|
1943
2005
|
.join(", "),
|
|
1944
2006
|
"",
|
|
1945
|
-
"Return strictly valid JSON
|
|
2007
|
+
"Return strictly valid JSON with this structure:",
|
|
1946
2008
|
"{",
|
|
1947
|
-
' "
|
|
1948
|
-
' "description": "
|
|
1949
|
-
|
|
1950
|
-
'
|
|
1951
|
-
' "Header": {',
|
|
1952
|
-
' "description": "Application header section",',
|
|
1953
|
-
' "progress": { "completed": 0, "total": 0 },',
|
|
1954
|
-
' "children": {',
|
|
1955
|
-
' "Logo": { "description": "Company logo", "type": "display" },',
|
|
1956
|
-
' "Navigation": { "description": "Main navigation", "type": "interactive" }',
|
|
1957
|
-
" }",
|
|
1958
|
-
" },",
|
|
1959
|
-
' "Main": {',
|
|
1960
|
-
' "description": "Main content area",',
|
|
1961
|
-
' "progress": { "completed": 0, "total": 0 },',
|
|
1962
|
-
' "children": {',
|
|
1963
|
-
' "BusinessSection1": {',
|
|
1964
|
-
' "description": "First business domain section",',
|
|
1965
|
-
' "progress": { "completed": 0, "total": 0 },',
|
|
1966
|
-
' "children": {',
|
|
1967
|
-
' "SubComponent1": { "description": "Specific business component", "type": "form" },',
|
|
1968
|
-
' "SubComponent2": { "description": "Another business component", "type": "display" }',
|
|
1969
|
-
" }",
|
|
1970
|
-
" }",
|
|
1971
|
-
" }",
|
|
1972
|
-
" }",
|
|
1973
|
-
" }",
|
|
1974
|
-
" },",
|
|
1975
|
-
' "metadata": {',
|
|
1976
|
-
' "coreCandidates": [',
|
|
1977
|
-
' { "name": string, "path": string, "reason": string },',
|
|
1978
|
-
' { "name": string, "path": string, "reason": string }',
|
|
1979
|
-
" ],",
|
|
1980
|
-
' "totalComponents": 0,',
|
|
1981
|
-
' "completedComponents": 0',
|
|
1982
|
-
" }",
|
|
2009
|
+
' "components": [',
|
|
2010
|
+
' { "name": "ComponentName", "description": "Specific purpose", "type": "form|layout|display|interactive", "group": "GroupName", "status": "planned" }',
|
|
2011
|
+
" ],",
|
|
2012
|
+
' "metadata": { "totalComponents": 0 }',
|
|
1983
2013
|
"}",
|
|
1984
2014
|
"",
|
|
1985
2015
|
"Rules:",
|
|
1986
|
-
"-
|
|
1987
|
-
"-
|
|
1988
|
-
"-
|
|
1989
|
-
"- Each component should have: description, progress tracking, and children (if any)",
|
|
1990
|
-
"- Progress tracking: { completed: 0, total: 0 } - total counts all nested components",
|
|
1991
|
-
"- CRITICAL: Use the SPECIFIC business context above to generate detailed, domain-specific components",
|
|
1992
|
-
"- Extract specific feature names, user stories, and acceptance criteria from the context",
|
|
1993
|
-
"- Create components that directly implement the features described in the context",
|
|
1994
|
-
"- Use the exact terminology and business language from the context",
|
|
1995
|
-
"- Group by business domain in the hierarchy (e.g., 'OrderManagement', 'InventoryManagement')",
|
|
1996
|
-
"- Each leaf component should have a 'type' field: 'layout', 'display', 'interactive', 'form'",
|
|
1997
|
-
"- Component descriptions should reference specific business requirements from the context",
|
|
1998
|
-
"- No code fences, no comments, no trailing commas.",
|
|
1999
|
-
"- Use only the fields above.",
|
|
2000
|
-
"- Ensure arrays/objects have no extra commas.",
|
|
2001
|
-
"- Provide 2-3 'coreCandidates' with their full path in the hierarchy.",
|
|
2016
|
+
"- Logical React composition starting from root",
|
|
2017
|
+
"- Extract specific feature terminology from context",
|
|
2018
|
+
"- Return ONLY JSON - no markdown fences.",
|
|
2002
2019
|
].join("\n");
|
|
2003
2020
|
try {
|
|
2004
2021
|
// Check if user has local AI keys configured
|
|
@@ -2007,10 +2024,9 @@ Make the CSS immediately usable - no placeholders, actual working values!`;
|
|
|
2007
2024
|
let provider;
|
|
2008
2025
|
if (hasLocalKeys) {
|
|
2009
2026
|
// Use local AI first (user's own keys)
|
|
2010
|
-
this.spinner.updateText(`📋 Generating component list with ${await this.ai.getActiveProviderName()}...`);
|
|
2011
2027
|
try {
|
|
2012
2028
|
const r = await this.ai.generateText(prompt, {
|
|
2013
|
-
model
|
|
2029
|
+
model,
|
|
2014
2030
|
modelCandidates: this.getModelCandidates(options),
|
|
2015
2031
|
spinnerCallback: (text, resetTimer = false) => {
|
|
2016
2032
|
this.spinner.updateText(text);
|
|
@@ -2023,12 +2039,12 @@ Make the CSS immediately usable - no placeholders, actual working values!`;
|
|
|
2023
2039
|
provider = r.provider;
|
|
2024
2040
|
}
|
|
2025
2041
|
catch (e) {
|
|
2026
|
-
//
|
|
2042
|
+
// Retry logic (existing)
|
|
2027
2043
|
const msg = String(e?.message || e);
|
|
2028
2044
|
if (/unexpected EOF|ECONNRESET|EPIPE/i.test(msg)) {
|
|
2029
|
-
this.spinner.updateText("Retrying component list generation
|
|
2045
|
+
this.spinner.updateText("Retrying component list generation...");
|
|
2030
2046
|
const r2 = await this.ai.generateText(prompt, {
|
|
2031
|
-
model
|
|
2047
|
+
model,
|
|
2032
2048
|
modelCandidates: this.getModelCandidates(options),
|
|
2033
2049
|
spinnerCallback: (text, resetTimer = false) => {
|
|
2034
2050
|
this.spinner.updateText(text);
|
|
@@ -2047,7 +2063,6 @@ Make the CSS immediately usable - no placeholders, actual working values!`;
|
|
|
2047
2063
|
}
|
|
2048
2064
|
else {
|
|
2049
2065
|
// No local keys - use hosted API (requires authentication)
|
|
2050
|
-
this.spinner.updateText("📋 Generating component list with MyContext AI (hosted)...");
|
|
2051
2066
|
const hostedResult = await this.hostedApi.generateContext("components-list", prompt, {
|
|
2052
2067
|
model: options.model || "mycontext",
|
|
2053
2068
|
context: projectContext,
|
|
@@ -2063,6 +2078,21 @@ Make the CSS immediately usable - no placeholders, actual working values!`;
|
|
|
2063
2078
|
// Attempt to repair and extract valid JSON
|
|
2064
2079
|
const repaired = this.repairJson(text);
|
|
2065
2080
|
const cleanedContent = this.extractJson(repaired);
|
|
2081
|
+
// Update SSOT (Brain)
|
|
2082
|
+
try {
|
|
2083
|
+
const obj = JSON.parse(cleanedContent);
|
|
2084
|
+
await this.updateLivingContext({
|
|
2085
|
+
metadata: {
|
|
2086
|
+
lastUpdatedAt: new Date().toISOString(),
|
|
2087
|
+
status: "components-planned"
|
|
2088
|
+
}
|
|
2089
|
+
// Note: Full component hierarchy is heavy, keep in 04-component-list.json for now
|
|
2090
|
+
// or we could flatten and store in context.json.components
|
|
2091
|
+
});
|
|
2092
|
+
}
|
|
2093
|
+
catch (e) {
|
|
2094
|
+
// ignore parse errors for SSOT update; saveGeneratedContent will handle it later
|
|
2095
|
+
}
|
|
2066
2096
|
// Attach rich context so JSON alone is enough for component generation
|
|
2067
2097
|
try {
|
|
2068
2098
|
console.log(`[GenerateCommand] Attempting to parse cleaned content (first 200 chars): ${cleanedContent.slice(0, 200)}...`);
|
|
@@ -3529,35 +3559,128 @@ export function Typography({ variant, children, className }: TypographyProps) {
|
|
|
3529
3559
|
// 5) Fallback: wrap into minimal valid envelope
|
|
3530
3560
|
return JSON.stringify({ error: "Invalid JSON from AI", raw: raw.slice(0, 500) }, null, 2);
|
|
3531
3561
|
}
|
|
3562
|
+
async loadLivingContext() {
|
|
3563
|
+
try {
|
|
3564
|
+
const contextPath = path_1.default.join(this.getProjectRoot(), ".mycontext", "context.json");
|
|
3565
|
+
if (await fs.pathExists(contextPath)) {
|
|
3566
|
+
return await fs.readJson(contextPath);
|
|
3567
|
+
}
|
|
3568
|
+
}
|
|
3569
|
+
catch (e) {
|
|
3570
|
+
// ignore
|
|
3571
|
+
}
|
|
3572
|
+
return null;
|
|
3573
|
+
}
|
|
3574
|
+
async updateLivingContext(update) {
|
|
3575
|
+
try {
|
|
3576
|
+
const projectRoot = this.getProjectRoot();
|
|
3577
|
+
const contextPath = path_1.default.join(projectRoot, ".mycontext", "context.json");
|
|
3578
|
+
let current = await this.loadLivingContext();
|
|
3579
|
+
if (!current) {
|
|
3580
|
+
// Fallback to empty context if it doesn't exist
|
|
3581
|
+
current = {
|
|
3582
|
+
metadata: {
|
|
3583
|
+
version: "1.0.0",
|
|
3584
|
+
generatedAt: new Date().toISOString(),
|
|
3585
|
+
lastUpdatedAt: new Date().toISOString(),
|
|
3586
|
+
projectConfig: {
|
|
3587
|
+
id: require("crypto").randomUUID(),
|
|
3588
|
+
name: "MyContext Project",
|
|
3589
|
+
description: "",
|
|
3590
|
+
createdAt: new Date().toISOString(),
|
|
3591
|
+
updatedAt: new Date().toISOString(),
|
|
3592
|
+
contextPath: ".mycontext",
|
|
3593
|
+
version: "0.1.0",
|
|
3594
|
+
status: "initialized"
|
|
3595
|
+
}
|
|
3596
|
+
},
|
|
3597
|
+
prd: { title: "", problemStatement: "", goals: [], targetAudience: "", successMetrics: [] },
|
|
3598
|
+
features: [],
|
|
3599
|
+
flows: [],
|
|
3600
|
+
edgeCases: [],
|
|
3601
|
+
specs: {
|
|
3602
|
+
architecture: "",
|
|
3603
|
+
techStack: { frontend: [], backend: [], database: [], other: [] },
|
|
3604
|
+
apiEndpoints: [],
|
|
3605
|
+
databaseSchema: { tables: [] }
|
|
3606
|
+
},
|
|
3607
|
+
components: [],
|
|
3608
|
+
actions: [],
|
|
3609
|
+
routes: [],
|
|
3610
|
+
brain: { memory: {}, logs: [] }
|
|
3611
|
+
};
|
|
3612
|
+
}
|
|
3613
|
+
const { deepMerge } = await Promise.resolve().then(() => __importStar(require("../utils/deepMerge")));
|
|
3614
|
+
const merged = deepMerge(current, update);
|
|
3615
|
+
merged.metadata.lastUpdatedAt = new Date().toISOString();
|
|
3616
|
+
await fs.writeJson(contextPath, merged, { spaces: 2 });
|
|
3617
|
+
}
|
|
3618
|
+
catch (e) {
|
|
3619
|
+
console.log(chalk_1.default.yellow(`⚠️ Failed to update context.json: ${e instanceof Error ? e.message : String(e)}`));
|
|
3620
|
+
}
|
|
3621
|
+
}
|
|
3532
3622
|
async readContextArtifacts() {
|
|
3533
3623
|
try {
|
|
3534
|
-
const cwd =
|
|
3535
|
-
const
|
|
3536
|
-
? await fs.readFile(path_1.default.join(cwd, rel), "utf8")
|
|
3537
|
-
: "";
|
|
3538
|
-
// Prefer split files if present
|
|
3624
|
+
const cwd = this.getProjectRoot();
|
|
3625
|
+
const livingBrain = await this.loadLivingContext();
|
|
3539
3626
|
let prd = "";
|
|
3540
|
-
|
|
3541
|
-
|
|
3542
|
-
|
|
3543
|
-
|
|
3544
|
-
const flows = (await readOrEmpty(".mycontext/01c-flows.md")) ||
|
|
3545
|
-
(await readOrEmpty(".mycontext/03-flows.md"));
|
|
3546
|
-
if (brief || reqs || flows) {
|
|
3627
|
+
let types = "";
|
|
3628
|
+
let brand = "";
|
|
3629
|
+
if (livingBrain) {
|
|
3630
|
+
// Build PRD string from JSON
|
|
3547
3631
|
prd = [
|
|
3548
|
-
|
|
3549
|
-
|
|
3550
|
-
|
|
3551
|
-
|
|
3552
|
-
.
|
|
3553
|
-
|
|
3632
|
+
`# ${livingBrain.prd.title}`,
|
|
3633
|
+
`## Problem Statement\n${livingBrain.prd.problemStatement}`,
|
|
3634
|
+
`## Goals\n${livingBrain.prd.goals.map(g => `- ${g}`).join("\n")}`,
|
|
3635
|
+
livingBrain.features.length ? `## Features\n${livingBrain.features.map(f => `### ${f.name} (${f.priority})\n${f.description}`).join("\n\n")}` : "",
|
|
3636
|
+
livingBrain.flows.length ? `## Flows\n${livingBrain.flows.map(f => `### ${f.name}\n${f.steps.join("\n")}`).join("\n\n")}` : ""
|
|
3637
|
+
].filter(Boolean).join("\n\n");
|
|
3554
3638
|
}
|
|
3639
|
+
const readOrEmpty = async (rel) => (await fs.pathExists(path_1.default.join(cwd, rel)))
|
|
3640
|
+
? await fs.readFile(path_1.default.join(cwd, rel), "utf8")
|
|
3641
|
+
: "";
|
|
3642
|
+
// Fallback/Augment PRD from files if JSON is sparse
|
|
3555
3643
|
if (!prd) {
|
|
3556
|
-
|
|
3644
|
+
const brief = (await readOrEmpty(".mycontext/01a-brief.md")) || (await readOrEmpty(".mycontext/01-brief.md"));
|
|
3645
|
+
const reqs = (await readOrEmpty(".mycontext/01b-requirements.md")) || (await readOrEmpty(".mycontext/02-requirements.md"));
|
|
3646
|
+
const flows = (await readOrEmpty(".mycontext/01c-flows.md")) || (await readOrEmpty(".mycontext/03-flows.md"));
|
|
3647
|
+
if (brief || reqs || flows) {
|
|
3648
|
+
prd = [
|
|
3649
|
+
brief ? "## Brief\n\n" + brief : "",
|
|
3650
|
+
reqs ? "\n\n## Requirements\n\n" + reqs : "",
|
|
3651
|
+
flows ? "\n\n## Flows\n\n" + flows : "",
|
|
3652
|
+
].filter(Boolean).join("");
|
|
3653
|
+
}
|
|
3654
|
+
if (!prd) {
|
|
3655
|
+
prd = await readOrEmpty(".mycontext/01-prd.md");
|
|
3656
|
+
}
|
|
3657
|
+
}
|
|
3658
|
+
// Discover Types (Modern Multi-file)
|
|
3659
|
+
const typesDir = path_1.default.join(cwd, ".mycontext", "types");
|
|
3660
|
+
if (await fs.pathExists(typesDir)) {
|
|
3661
|
+
const files = await fs.readdir(typesDir);
|
|
3662
|
+
const typeFiles = files.filter(f => f.endsWith(".ts"));
|
|
3663
|
+
for (const file of typeFiles) {
|
|
3664
|
+
const content = await fs.readFile(path_1.default.join(typesDir, file), "utf8");
|
|
3665
|
+
types += `\n// --- ${file} ---\n${content}\n`;
|
|
3666
|
+
}
|
|
3667
|
+
}
|
|
3668
|
+
if (!types) {
|
|
3669
|
+
types = (await readOrEmpty(".mycontext/02-types.ts")) || (await readOrEmpty(".mycontext/02-types-guide.md"));
|
|
3670
|
+
}
|
|
3671
|
+
// Discover Brand (Modern Multi-file)
|
|
3672
|
+
const brandDir = path_1.default.join(cwd, ".mycontext", "brand");
|
|
3673
|
+
if (await fs.pathExists(brandDir)) {
|
|
3674
|
+
brand = await readOrEmpty(".mycontext/brand/globals.css");
|
|
3675
|
+
const brandFiles = await fs.readdir(brandDir);
|
|
3676
|
+
for (const file of brandFiles.filter(f => f.endsWith(".md"))) {
|
|
3677
|
+
const content = await fs.readFile(path_1.default.join(brandDir, file), "utf8");
|
|
3678
|
+
brand += `\n\n### ${file}\n${content}`;
|
|
3679
|
+
}
|
|
3680
|
+
}
|
|
3681
|
+
if (!brand) {
|
|
3682
|
+
brand = (await readOrEmpty(".mycontext/03-branding.md")) || (await readOrEmpty(".mycontext/03-branding-guide.md"));
|
|
3557
3683
|
}
|
|
3558
|
-
const types = await readOrEmpty(".mycontext/02-types.ts");
|
|
3559
|
-
const brand = (await readOrEmpty(".mycontext/brand/globals.css")) ||
|
|
3560
|
-
(await readOrEmpty(".mycontext/03-branding.md"));
|
|
3561
3684
|
// discover shadcn/ui primitives from components/ui
|
|
3562
3685
|
const uiDir = path_1.default.join(cwd, "components", "ui");
|
|
3563
3686
|
let shadcn = [];
|
|
@@ -3805,11 +3928,11 @@ ${isEcommerce
|
|
|
3805
3928
|
console.log(chalk_1.default.gray(" Visit /preview (dev server)"));
|
|
3806
3929
|
break;
|
|
3807
3930
|
case "all":
|
|
3808
|
-
console.log(chalk_1.default.blue("\n
|
|
3809
|
-
console.log(chalk_1.default.gray(" 1.
|
|
3810
|
-
console.log(chalk_1.default.gray(" 2.
|
|
3811
|
-
console.log(chalk_1.default.gray(" 3. Start
|
|
3812
|
-
console.log(chalk_1.default.gray(" 4. Preview: Visit /preview
|
|
3931
|
+
console.log(chalk_1.default.blue("\n🚀 Context Scaffolding Complete! Next steps:"));
|
|
3932
|
+
console.log(chalk_1.default.gray(" 1. Open .mycontext/ to see your project's new Living Brain."));
|
|
3933
|
+
console.log(chalk_1.default.gray(" 2. Recommended: Hand off .mycontext/ to your favorite AI agent (e.g. Antigravity)."));
|
|
3934
|
+
console.log(chalk_1.default.gray(" 3. Start building: npm run dev"));
|
|
3935
|
+
console.log(chalk_1.default.gray(" 4. Preview architectural alignment: Visit /preview"));
|
|
3813
3936
|
break;
|
|
3814
3937
|
default:
|
|
3815
3938
|
break;
|
|
@@ -3836,35 +3959,7 @@ ${isEcommerce
|
|
|
3836
3959
|
return aliases[type] || type;
|
|
3837
3960
|
}
|
|
3838
3961
|
hasLocalAIKeys() {
|
|
3839
|
-
|
|
3840
|
-
const keys = {
|
|
3841
|
-
github: !!process.env.MYCONTEXT_GITHUB_TOKEN,
|
|
3842
|
-
qwen: !!process.env.MYCONTEXT_QWEN_API_KEY,
|
|
3843
|
-
gemini: !!(process.env.GEMINI_API_KEY ||
|
|
3844
|
-
process.env.GOOGLE_API_KEY ||
|
|
3845
|
-
process.env.MYCONTEXT_GEMINI_API_KEY),
|
|
3846
|
-
xai: !!(process.env.MYCONTEXT_XAI_API_KEY || process.env.XAI_API_KEY),
|
|
3847
|
-
claude: !!process.env.MYCONTEXT_CLAUDE_API_KEY,
|
|
3848
|
-
openai: !!process.env.OPENAI_API_KEY,
|
|
3849
|
-
anthropic: !!process.env.ANTHROPIC_API_KEY,
|
|
3850
|
-
huggingface: !!process.env.HUGGINGFACE_API_KEY,
|
|
3851
|
-
openrouter: !!(process.env.MYCONTEXT_OPENROUTER_API_KEY ||
|
|
3852
|
-
process.env.OPENROUTER_API_KEY),
|
|
3853
|
-
};
|
|
3854
|
-
console.log(`[GenerateCommand] API Keys detected:`, keys);
|
|
3855
|
-
return !!(process.env.MYCONTEXT_GITHUB_TOKEN ||
|
|
3856
|
-
process.env.MYCONTEXT_QWEN_API_KEY ||
|
|
3857
|
-
process.env.GEMINI_API_KEY ||
|
|
3858
|
-
process.env.GOOGLE_API_KEY ||
|
|
3859
|
-
process.env.MYCONTEXT_GEMINI_API_KEY ||
|
|
3860
|
-
process.env.MYCONTEXT_XAI_API_KEY ||
|
|
3861
|
-
process.env.XAI_API_KEY ||
|
|
3862
|
-
process.env.MYCONTEXT_CLAUDE_API_KEY ||
|
|
3863
|
-
process.env.OPENAI_API_KEY ||
|
|
3864
|
-
process.env.ANTHROPIC_API_KEY ||
|
|
3865
|
-
process.env.HUGGINGFACE_API_KEY ||
|
|
3866
|
-
process.env.MYCONTEXT_OPENROUTER_API_KEY ||
|
|
3867
|
-
process.env.OPENROUTER_API_KEY);
|
|
3962
|
+
return AICore_1.AICore.getInstance().hasAnyProvider();
|
|
3868
3963
|
}
|
|
3869
3964
|
getModelCandidates(options) {
|
|
3870
3965
|
const raw = options.modelCandidates ||
|
|
@@ -3956,7 +4051,8 @@ INSTRUCTIONS:
|
|
|
3956
4051
|
1. Analyze the project details provided above (which may include file structure, tech stack, and README summary).
|
|
3957
4052
|
2. Extract functional requirements, user flows, and technical limits.
|
|
3958
4053
|
3. If the description includes a file tree, infer the project architecture from it.
|
|
3959
|
-
4.
|
|
4054
|
+
4. Identify all necessary UI components and group them logically (e.g. Auth, Sidebar, Dashboard).
|
|
4055
|
+
5. Generate a complete PRD, Technical Spec, and Component Architecture that reflects this ACTUAL existing project.
|
|
3960
4056
|
`;
|
|
3961
4057
|
}
|
|
3962
4058
|
// The schema for LivingContext (simplified version for the LLM)
|
|
@@ -3966,12 +4062,31 @@ INSTRUCTIONS:
|
|
|
3966
4062
|
"features": [{ "id": "...", "name": "...", "description": "...", "priority": "high|medium|low", "userValue": "...", "acceptanceCriteria": [], "dependencies": [] }],
|
|
3967
4063
|
"flows": [{ "id": "...", "name": "...", "description": "...", "steps": [], "actors": [] }],
|
|
3968
4064
|
"edgeCases": [{ "id": "...", "category": "...", "description": "...", "mitigation": "..." }],
|
|
4065
|
+
"brand": {
|
|
4066
|
+
"theme": "light|dark",
|
|
4067
|
+
"colors": { "primary": "#...", "background": "#...", "text": "#...", "accent": "#..." },
|
|
4068
|
+
"typography": { "fontFamily": "...", "headingScale": "..." },
|
|
4069
|
+
"designPrinciples": []
|
|
4070
|
+
},
|
|
4071
|
+
"types": {
|
|
4072
|
+
"entities": [{ "name": "...", "description": "...", "schema": "export interface ... { ... }" }],
|
|
4073
|
+
"shared": [{ "name": "...", "description": "...", "schema": "export interface ... { ... }" }]
|
|
4074
|
+
},
|
|
3969
4075
|
"specs": {
|
|
3970
4076
|
"architecture": "...",
|
|
3971
4077
|
"techStack": { "frontend": [], "backend": [], "database": [], "other": [] },
|
|
3972
4078
|
"apiEndpoints": [{ "path": "...", "method": "...", "description": "...", "authRequired": true }],
|
|
3973
4079
|
"databaseSchema": { "tables": [{ "name": "...", "columns": [{ "name": "...", "type": "...", "constraints": [] }] }] }
|
|
3974
|
-
}
|
|
4080
|
+
},
|
|
4081
|
+
"components": [
|
|
4082
|
+
{
|
|
4083
|
+
"name": "ComponentName",
|
|
4084
|
+
"description": "...",
|
|
4085
|
+
"type": "form|layout|display|interactive",
|
|
4086
|
+
"group": "Auth|Dashboard|etc",
|
|
4087
|
+
"status": "planned"
|
|
4088
|
+
}
|
|
4089
|
+
]
|
|
3975
4090
|
}
|
|
3976
4091
|
`;
|
|
3977
4092
|
const livingContextData = await aiCore.generateStructuredText(prompt, schema);
|
|
@@ -4019,6 +4134,9 @@ INSTRUCTIONS:
|
|
|
4019
4134
|
{ name: "01b-user-flows.md", content: contextRenderer_1.ContextRenderer.renderUserFlows(livingContext) },
|
|
4020
4135
|
{ name: "01c-edge-cases.md", content: contextRenderer_1.ContextRenderer.renderEdgeCases(livingContext) },
|
|
4021
4136
|
{ name: "01d-technical-specs.md", content: contextRenderer_1.ContextRenderer.renderTechnicalSpecs(livingContext) },
|
|
4137
|
+
{ name: "02-types-guide.md", content: contextRenderer_1.ContextRenderer.renderTypesGuide(livingContext) },
|
|
4138
|
+
{ name: "03-brand-guide.md", content: contextRenderer_1.ContextRenderer.renderBrandGuide(livingContext) },
|
|
4139
|
+
{ name: "04-component-list.md", content: contextRenderer_1.ContextRenderer.renderComponentList(livingContext) },
|
|
4022
4140
|
];
|
|
4023
4141
|
for (const render of renders) {
|
|
4024
4142
|
const filePath = path_1.default.join(mycontextDir, render.name);
|
|
@@ -4030,7 +4148,7 @@ INSTRUCTIONS:
|
|
|
4030
4148
|
this.spinner.success({ text: "🎉 Living Context generated and exported!" });
|
|
4031
4149
|
return {
|
|
4032
4150
|
success: true,
|
|
4033
|
-
content:
|
|
4151
|
+
content: contextRenderer_1.ContextRenderer.renderPRD(livingContext),
|
|
4034
4152
|
provider: "hybrid",
|
|
4035
4153
|
metadata: { model: "structured", tokens: 0, latency: 0 },
|
|
4036
4154
|
};
|