mycontext-cli 4.2.25 → 4.2.26
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/dist/commands/analyze.d.ts.map +1 -1
- package/dist/commands/analyze.js +8 -24
- package/dist/commands/analyze.js.map +1 -1
- package/dist/commands/generate-design-prompt.d.ts +2 -0
- package/dist/commands/generate-design-prompt.d.ts.map +1 -1
- package/dist/commands/generate-design-prompt.js +29 -2
- package/dist/commands/generate-design-prompt.js.map +1 -1
- package/dist/commands/generate.d.ts +0 -49
- package/dist/commands/generate.d.ts.map +1 -1
- package/dist/commands/generate.js +19 -746
- package/dist/commands/generate.js.map +1 -1
- package/dist/commands/review-context.d.ts.map +1 -1
- package/dist/commands/review-context.js +3 -27
- package/dist/commands/review-context.js.map +1 -1
- package/dist/commands/setup-database.d.ts.map +1 -1
- package/dist/commands/setup-database.js +2 -2
- package/dist/commands/setup-database.js.map +1 -1
- package/dist/commands/setup-instantdb.d.ts.map +1 -1
- package/dist/commands/setup-instantdb.js +3 -3
- package/dist/commands/setup-instantdb.js.map +1 -1
- package/dist/utils/contextExportsImporter.d.ts +3 -0
- package/dist/utils/contextExportsImporter.d.ts.map +1 -0
- package/dist/utils/contextExportsImporter.js +203 -0
- package/dist/utils/contextExportsImporter.js.map +1 -0
- package/package.json +1 -1
|
@@ -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 contextExportsImporter_1 = require("../utils/contextExportsImporter");
|
|
53
54
|
const ProjectScanner_1 = require("../services/ProjectScanner");
|
|
54
55
|
class GenerateCommand {
|
|
55
56
|
constructor() {
|
|
@@ -461,7 +462,8 @@ Based on this, generate a complete project context including PRD, Technical Spec
|
|
|
461
462
|
return await this.getProjectContext();
|
|
462
463
|
}
|
|
463
464
|
async generateContext(projectContext, options) {
|
|
464
|
-
//
|
|
465
|
+
// Canonical behavior: sync Living Brain (context.json) and export markdown views.
|
|
466
|
+
// If user provided --prd-file, treat it as description context for brain generation.
|
|
465
467
|
try {
|
|
466
468
|
const prdFile = options.prdFile ||
|
|
467
469
|
options.prdfile ||
|
|
@@ -472,190 +474,12 @@ Based on this, generate a complete project context including PRD, Technical Spec
|
|
|
472
474
|
: path_1.default.join(process.cwd(), prdFile);
|
|
473
475
|
if (await fs.pathExists(abs)) {
|
|
474
476
|
const content = await fs.readFile(abs, "utf8");
|
|
475
|
-
|
|
476
|
-
success: true,
|
|
477
|
-
content,
|
|
478
|
-
provider: "hybrid",
|
|
479
|
-
metadata: { imported: true },
|
|
480
|
-
};
|
|
477
|
+
projectContext = { ...(projectContext || {}), description: content };
|
|
481
478
|
}
|
|
482
479
|
}
|
|
483
480
|
}
|
|
484
481
|
catch { }
|
|
485
|
-
|
|
486
|
-
const projectRoot = this.getProjectRoot();
|
|
487
|
-
const prdPath = path_1.default.join(projectRoot, ".mycontext", "01-prd.md");
|
|
488
|
-
const existingPRD = await this.checkExistingPRD(prdPath, options);
|
|
489
|
-
if (existingPRD.shouldSkip) {
|
|
490
|
-
return {
|
|
491
|
-
success: true,
|
|
492
|
-
content: existingPRD.content || "",
|
|
493
|
-
provider: "hybrid",
|
|
494
|
-
metadata: { skipped: true, reason: existingPRD.reason },
|
|
495
|
-
};
|
|
496
|
-
}
|
|
497
|
-
// Get active playbook for additional context
|
|
498
|
-
const activePlaybook = await this.getActivePlaybook();
|
|
499
|
-
// Load existing context files for better PRD generation
|
|
500
|
-
const contextContent = await this.loadContextForPRDGeneration();
|
|
501
|
-
// Check if we're merging with existing PRD
|
|
502
|
-
const isMerging = options.merge && existingPRD.content;
|
|
503
|
-
const prompt = [
|
|
504
|
-
`[mycontext] Plan: plan → generate → QA → docs → preview (→ checks)`,
|
|
505
|
-
isMerging
|
|
506
|
-
? `Refine and enhance the existing PRD based on the following project context:`
|
|
507
|
-
: `Create a production-grade PRD based on the following project context:`,
|
|
508
|
-
``,
|
|
509
|
-
contextContent,
|
|
510
|
-
``,
|
|
511
|
-
...(isMerging
|
|
512
|
-
? [
|
|
513
|
-
`## Existing PRD to Refine:`,
|
|
514
|
-
``,
|
|
515
|
-
existingPRD.content,
|
|
516
|
-
``,
|
|
517
|
-
`IMPORTANT: You are refining the above existing PRD. Enhance it with the context above while preserving valuable existing content. Merge new insights with existing structure.`,
|
|
518
|
-
]
|
|
519
|
-
: [
|
|
520
|
-
`IMPORTANT: Generate a PRD that is 100% accurate to the business context provided above. Extract specific requirements, features, and business logic from the context files. Do NOT generate generic fallback content.`,
|
|
521
|
-
]),
|
|
522
|
-
"",
|
|
523
|
-
// Include playbook context if available
|
|
524
|
-
...(activePlaybook
|
|
525
|
-
? [
|
|
526
|
-
"",
|
|
527
|
-
"## Proven Process Reference",
|
|
528
|
-
`**Active Playbook: ${activePlaybook.title}**`,
|
|
529
|
-
`Category: ${activePlaybook.category || "N/A"}`,
|
|
530
|
-
`Difficulty: ${activePlaybook.metadata?.difficulty || "N/A"}`,
|
|
531
|
-
`Estimated Time: ${activePlaybook.metadata?.estimatedTime || "N/A"}`,
|
|
532
|
-
"",
|
|
533
|
-
"**Process Guidelines:**",
|
|
534
|
-
activePlaybook.content,
|
|
535
|
-
"",
|
|
536
|
-
"**Important:** Follow the proven patterns and best practices outlined in the playbook above. This will ensure your implementation follows industry standards and proven approaches.",
|
|
537
|
-
"",
|
|
538
|
-
]
|
|
539
|
-
: []),
|
|
540
|
-
"Assume default stack unless user specifies otherwise:",
|
|
541
|
-
"- Frontend: Next.js (App Router) with Shadcn UI",
|
|
542
|
-
"- Auth/DB/File storage: InstantDB (auth, data, file persistence)",
|
|
543
|
-
"- Accessibility: Radix UI principles (keyboard nav, ARIA, focus mgmt)",
|
|
544
|
-
"- Testing: Jest + React Testing Library",
|
|
545
|
-
"",
|
|
546
|
-
"Follow this step-by-step process first, then structure the PRD (avoid generic statements):",
|
|
547
|
-
"",
|
|
548
|
-
"Process:",
|
|
549
|
-
"1) Problem Statement: restate the project description from the user's perspective (who is impacted, what problem exists today, why now)",
|
|
550
|
-
"2) Desired Outcomes & Success Metrics: what users want to eliminate/improve/create; define measurable outcomes",
|
|
551
|
-
"3) Primary Users & Roles: identify roles and their responsibilities/permissions",
|
|
552
|
-
"4) Current State & Pain Points: briefly describe how it works today (or assumptions) and pain points",
|
|
553
|
-
"5) Improvement Opportunities: what to eliminate/automate/simplify; list key constraints/assumptions",
|
|
554
|
-
"6) Solution Approach & Scope: MVP vs later; boundaries and tradeoffs",
|
|
555
|
-
"7) User Journeys & Flows: derive end-to-end flows per role (happy path + alternatives + edge cases)",
|
|
556
|
-
"8) Detailed User Stories: action-oriented stories with context and goals",
|
|
557
|
-
"9) Acceptance Criteria: Given/When/Then per critical story",
|
|
558
|
-
"10) Entity Model & Relationships: core entities and associations",
|
|
559
|
-
"11) Information Architecture: pages/routes and the shadcn/ui primitives likely used",
|
|
560
|
-
"12) Technical Requirements: SSR/ISR, server actions, data fetching, security, telemetry",
|
|
561
|
-
"13) Non-Functional Requirements: performance budgets, accessibility, i18n, reliability",
|
|
562
|
-
"14) Risks & Open Questions: what could derail the plan and what needs decisions",
|
|
563
|
-
"",
|
|
564
|
-
"Then, produce the PRD with the following sections (use exact headers for splitting):",
|
|
565
|
-
"Structure the PRD with depth (avoid generic statements):",
|
|
566
|
-
"## Requirements",
|
|
567
|
-
"1) Overview: goal, non-goals, success metrics",
|
|
568
|
-
"2) User Roles & Responsibilities: distinct roles with responsibilities and permissions",
|
|
569
|
-
"3) Personas (optional): brief traits that influence UX",
|
|
570
|
-
"4) Detailed User Stories: action-oriented; include negative flows and edge cases",
|
|
571
|
-
"5) Entity Model & Relationships: main entities and associations",
|
|
572
|
-
"",
|
|
573
|
-
"## Flows",
|
|
574
|
-
"6) User Journeys & Flows: end-to-end scenarios per role (step-by-step)",
|
|
575
|
-
"7) Information Architecture: pages/routes, key UI patterns (shadcn components)",
|
|
576
|
-
"8) Technical Requirements: SSR/ISR, data fetching, server actions, security, telemetry",
|
|
577
|
-
"9) Non-Functional Requirements: performance budgets, accessibility, internationalization",
|
|
578
|
-
"10) Acceptance Criteria: Gherkin-style Given/When/Then per critical story",
|
|
579
|
-
"11) Risks & Open Questions",
|
|
580
|
-
"",
|
|
581
|
-
"Include two diagrams in fenced code blocks:",
|
|
582
|
-
"- Sequence diagram of a critical flow (e.g., auth → gameplay → result)",
|
|
583
|
-
"- (Optional) Flowchart for a user journey",
|
|
584
|
-
"",
|
|
585
|
-
"```mermaid",
|
|
586
|
-
"sequenceDiagram",
|
|
587
|
-
" autonumber",
|
|
588
|
-
" participant User",
|
|
589
|
-
" participant App as Next.js App",
|
|
590
|
-
" participant DB as InstantDB",
|
|
591
|
-
" User->>App: Perform primary action",
|
|
592
|
-
" App->>DB: Persist/fetch data",
|
|
593
|
-
" DB-->>App: Data OK",
|
|
594
|
-
" App-->>User: Updated UI",
|
|
595
|
-
"```",
|
|
596
|
-
"",
|
|
597
|
-
"Write concretely. Ground content in the provided description. No placeholders.",
|
|
598
|
-
].join("\n");
|
|
599
|
-
try {
|
|
600
|
-
// Check if user has local AI keys configured
|
|
601
|
-
const hasLocalKeys = this.hasLocalAIKeys();
|
|
602
|
-
if (hasLocalKeys) {
|
|
603
|
-
// Use local AI first (user's own keys)
|
|
604
|
-
this.spinner.updateText(`🤖 Generating PRD with ${await this.ai.getActiveProviderName()}...`);
|
|
605
|
-
const { text, provider } = await this.ai.generateText(prompt, {
|
|
606
|
-
model: options.model || process.env.MYCONTEXT_MODEL,
|
|
607
|
-
modelCandidates: this.getModelCandidates(options),
|
|
608
|
-
spinnerCallback: (text, resetTimer = false) => {
|
|
609
|
-
this.spinner.updateText(text);
|
|
610
|
-
if (resetTimer) {
|
|
611
|
-
this.spinner.reset();
|
|
612
|
-
}
|
|
613
|
-
},
|
|
614
|
-
});
|
|
615
|
-
const cleaned = this.sanitizeMarkdownOutput(text);
|
|
616
|
-
return {
|
|
617
|
-
success: true,
|
|
618
|
-
content: cleaned,
|
|
619
|
-
provider: provider,
|
|
620
|
-
metadata: {
|
|
621
|
-
model: "local",
|
|
622
|
-
tokens: cleaned.length / 4,
|
|
623
|
-
latency: 1000,
|
|
624
|
-
},
|
|
625
|
-
};
|
|
626
|
-
}
|
|
627
|
-
else {
|
|
628
|
-
// No local keys - use hosted API (requires authentication)
|
|
629
|
-
this.spinner.updateText("🤖 Generating PRD with MyContext AI (hosted)...");
|
|
630
|
-
const hostedResult = await this.hostedApi.generateContext("context", prompt, {
|
|
631
|
-
model: options.model || "mycontext",
|
|
632
|
-
context: projectContext,
|
|
633
|
-
});
|
|
634
|
-
if (hostedResult.success && hostedResult.data) {
|
|
635
|
-
const cleaned = this.sanitizeMarkdownOutput(hostedResult.data);
|
|
636
|
-
return {
|
|
637
|
-
success: true,
|
|
638
|
-
content: cleaned,
|
|
639
|
-
provider: "hosted",
|
|
640
|
-
metadata: {
|
|
641
|
-
model: "mycontext",
|
|
642
|
-
tokens: cleaned.length / 4,
|
|
643
|
-
latency: 1000,
|
|
644
|
-
},
|
|
645
|
-
};
|
|
646
|
-
}
|
|
647
|
-
else {
|
|
648
|
-
throw new Error(hostedResult.error || "Hosted API failed");
|
|
649
|
-
}
|
|
650
|
-
}
|
|
651
|
-
}
|
|
652
|
-
catch (error) {
|
|
653
|
-
return {
|
|
654
|
-
success: false,
|
|
655
|
-
error: `AI generation failed: ${error instanceof Error ? error.message : "Unknown error"}`,
|
|
656
|
-
provider: "hybrid",
|
|
657
|
-
};
|
|
658
|
-
}
|
|
482
|
+
return await this.generateFullContext(projectContext, options);
|
|
659
483
|
}
|
|
660
484
|
async generateTypes(projectContext, options) {
|
|
661
485
|
// Check if --from-schema flag is used
|
|
@@ -839,7 +663,7 @@ Use the business entities from the context above, not generic types.`;
|
|
|
839
663
|
}
|
|
840
664
|
let contextContent = "";
|
|
841
665
|
// Load PRD (01-prd.md)
|
|
842
|
-
if (context.prd
|
|
666
|
+
if (context.prd) {
|
|
843
667
|
contextContent += `## Project Requirements Document (PRD)\n\n${context.prd}\n\n`;
|
|
844
668
|
}
|
|
845
669
|
// Load features (01a-features.md)
|
|
@@ -870,7 +694,7 @@ Use the business entities from the context above, not generic types.`;
|
|
|
870
694
|
}
|
|
871
695
|
let contextContent = "";
|
|
872
696
|
// Load PRD (01-prd.md)
|
|
873
|
-
if (context.prd
|
|
697
|
+
if (context.prd) {
|
|
874
698
|
contextContent += `## Project Requirements Document (PRD)\n\n${context.prd}\n\n`;
|
|
875
699
|
}
|
|
876
700
|
// Load features (01a-features.md)
|
|
@@ -900,10 +724,7 @@ Use the business entities from the context above, not generic types.`;
|
|
|
900
724
|
}
|
|
901
725
|
const existingContent = await fs.readFile(prdPath, "utf8");
|
|
902
726
|
// Check if it's just a template/placeholder
|
|
903
|
-
|
|
904
|
-
console.log(chalk_1.default.yellow("⚠️ Existing PRD appears to be a template, will generate new one"));
|
|
905
|
-
return { shouldSkip: false };
|
|
906
|
-
}
|
|
727
|
+
// Templates are no longer supported: PRD is an export of context.json.
|
|
907
728
|
// Check for force flag
|
|
908
729
|
if (options.force) {
|
|
909
730
|
console.log(chalk_1.default.yellow("🔄 Force flag detected, will overwrite existing PRD"));
|
|
@@ -932,7 +753,7 @@ Use the business entities from the context above, not generic types.`;
|
|
|
932
753
|
}
|
|
933
754
|
let contextContent = "";
|
|
934
755
|
// Load existing PRD if it exists (for refinement)
|
|
935
|
-
if (context.prd
|
|
756
|
+
if (context.prd) {
|
|
936
757
|
contextContent += `## Existing Project Requirements Document (PRD)\n\n${context.prd}\n\n`;
|
|
937
758
|
}
|
|
938
759
|
// Load features (01a-features.md)
|
|
@@ -4023,6 +3844,16 @@ ${isEcommerce
|
|
|
4023
3844
|
catch (e) {
|
|
4024
3845
|
// ignore
|
|
4025
3846
|
}
|
|
3847
|
+
// Optional: import manual edits from exported markdown back into the brain
|
|
3848
|
+
// (best-effort, only when explicitly requested)
|
|
3849
|
+
if (existingContext && options.importExports) {
|
|
3850
|
+
try {
|
|
3851
|
+
existingContext = await (0, contextExportsImporter_1.importContextExports)(path_1.default.join(projectRoot, ".mycontext"), existingContext);
|
|
3852
|
+
}
|
|
3853
|
+
catch {
|
|
3854
|
+
// ignore import failures
|
|
3855
|
+
}
|
|
3856
|
+
}
|
|
4026
3857
|
let prompt = "";
|
|
4027
3858
|
if (existingContext && existingContext.prd && Object.keys(existingContext.prd).length > 0) {
|
|
4028
3859
|
prompt = `
|
|
@@ -4203,564 +4034,6 @@ INSTRUCTIONS:
|
|
|
4203
4034
|
// Default to current working directory
|
|
4204
4035
|
return cwd;
|
|
4205
4036
|
}
|
|
4206
|
-
/**
|
|
4207
|
-
* Generate A/B/C/D context files (Features, User Flows, Edge Cases, Technical Specs)
|
|
4208
|
-
*/
|
|
4209
|
-
async generateContextFiles(projectContext, options) {
|
|
4210
|
-
// Ensure we're using the project root, not a nested .mycontext directory
|
|
4211
|
-
const projectRoot = this.getProjectRoot();
|
|
4212
|
-
const contextDir = path_1.default.join(projectRoot, ".mycontext");
|
|
4213
|
-
// Ensure .mycontext directory exists
|
|
4214
|
-
await fs.ensureDir(contextDir);
|
|
4215
|
-
// Check if context files already exist
|
|
4216
|
-
const existingFiles = await this.checkExistingContextFiles(contextDir);
|
|
4217
|
-
if (existingFiles.length > 0 && !options.force) {
|
|
4218
|
-
return {
|
|
4219
|
-
success: false,
|
|
4220
|
-
error: `Context files already exist: ${existingFiles.join(", ")}. Use --force to overwrite.`,
|
|
4221
|
-
provider: "system",
|
|
4222
|
-
metadata: { model: "system", tokens: 0, latency: 0 },
|
|
4223
|
-
};
|
|
4224
|
-
}
|
|
4225
|
-
// Get context from PRD if it exists, otherwise use description
|
|
4226
|
-
const contextContent = await this.getContextForGeneration(contextDir, projectContext.description);
|
|
4227
|
-
try {
|
|
4228
|
-
// Generate each context file using the PRD content as context
|
|
4229
|
-
console.log("[GenerateCommand] Generating features file...");
|
|
4230
|
-
await this.generateFeaturesFile(contextDir, contextContent);
|
|
4231
|
-
console.log("[GenerateCommand] Generating user flows file...");
|
|
4232
|
-
await this.generateUserFlowsFile(contextDir, contextContent);
|
|
4233
|
-
console.log("[GenerateCommand] Generating edge cases file...");
|
|
4234
|
-
await this.generateEdgeCasesFile(contextDir, contextContent);
|
|
4235
|
-
console.log("[GenerateCommand] Generating technical specs file...");
|
|
4236
|
-
await this.generateTechnicalSpecsFile(contextDir, contextContent);
|
|
4237
|
-
return {
|
|
4238
|
-
success: true,
|
|
4239
|
-
content: "Context files generated successfully",
|
|
4240
|
-
provider: "hybrid",
|
|
4241
|
-
metadata: { model: "hybrid", tokens: 0, latency: 0 },
|
|
4242
|
-
};
|
|
4243
|
-
}
|
|
4244
|
-
catch (error) {
|
|
4245
|
-
return {
|
|
4246
|
-
success: false,
|
|
4247
|
-
error: `Context file generation failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
4248
|
-
provider: "system",
|
|
4249
|
-
metadata: { model: "system", tokens: 0, latency: 0 },
|
|
4250
|
-
};
|
|
4251
|
-
}
|
|
4252
|
-
}
|
|
4253
|
-
async checkExistingContextFiles(contextDir) {
|
|
4254
|
-
const files = [
|
|
4255
|
-
"01a-features.md",
|
|
4256
|
-
"01b-user-flows.md",
|
|
4257
|
-
"01c-edge-cases.md",
|
|
4258
|
-
"01d-technical-specs.md",
|
|
4259
|
-
];
|
|
4260
|
-
const existingFiles = [];
|
|
4261
|
-
for (const file of files) {
|
|
4262
|
-
if (await fs.pathExists(path_1.default.join(contextDir, file))) {
|
|
4263
|
-
existingFiles.push(file);
|
|
4264
|
-
}
|
|
4265
|
-
}
|
|
4266
|
-
return existingFiles;
|
|
4267
|
-
}
|
|
4268
|
-
async generateFeaturesFile(contextDir, contextContent) {
|
|
4269
|
-
const prompt = this.buildFeaturesPrompt(contextContent);
|
|
4270
|
-
try {
|
|
4271
|
-
// Add timeout to prevent infinite loops
|
|
4272
|
-
const timeoutPromise = new Promise((_, reject) => setTimeout(() => reject(new Error("AI generation timeout")), 30000) // 30 second timeout
|
|
4273
|
-
);
|
|
4274
|
-
const responsePromise = this.ai.generateText(prompt, {
|
|
4275
|
-
temperature: 0.7,
|
|
4276
|
-
maxTokens: 2000,
|
|
4277
|
-
});
|
|
4278
|
-
const response = (await Promise.race([
|
|
4279
|
-
responsePromise,
|
|
4280
|
-
timeoutPromise,
|
|
4281
|
-
]));
|
|
4282
|
-
// Check if response is valid
|
|
4283
|
-
if (!response || !response.text || response.text.trim().length < 50) {
|
|
4284
|
-
throw new Error("AI response too short or invalid");
|
|
4285
|
-
}
|
|
4286
|
-
const content = this.formatFeaturesContent(response.text);
|
|
4287
|
-
await fs.writeFile(path_1.default.join(contextDir, "01a-features.md"), content);
|
|
4288
|
-
}
|
|
4289
|
-
catch (error) {
|
|
4290
|
-
console.log(chalk_1.default.red("❌ AI generation failed for features"));
|
|
4291
|
-
console.log(chalk_1.default.yellow("💡 MyContext requires 100% accuracy - no fallbacks"));
|
|
4292
|
-
console.log(chalk_1.default.blue("🔄 Retry options:"));
|
|
4293
|
-
console.log(chalk_1.default.gray(" 1. Wait for rate limits to reset"));
|
|
4294
|
-
console.log(chalk_1.default.gray(" 2. Use a different AI provider"));
|
|
4295
|
-
console.log(chalk_1.default.gray(" 3. Check your API key configuration"));
|
|
4296
|
-
console.log(chalk_1.default.gray(" 4. Try again later with: mycontext generate context --full"));
|
|
4297
|
-
throw new Error("AI generation failed - retry when conditions improve");
|
|
4298
|
-
}
|
|
4299
|
-
}
|
|
4300
|
-
async generateUserFlowsFile(contextDir, contextContent) {
|
|
4301
|
-
const prompt = this.buildUserFlowsPrompt(contextContent);
|
|
4302
|
-
try {
|
|
4303
|
-
const response = await this.ai.generateText(prompt, {
|
|
4304
|
-
temperature: 0.7,
|
|
4305
|
-
maxTokens: 2000,
|
|
4306
|
-
});
|
|
4307
|
-
const content = this.formatUserFlowsContent(response.text);
|
|
4308
|
-
await fs.writeFile(path_1.default.join(contextDir, "01b-user-flows.md"), content);
|
|
4309
|
-
}
|
|
4310
|
-
catch (error) {
|
|
4311
|
-
console.log(chalk_1.default.red("❌ AI generation failed for user flows"));
|
|
4312
|
-
console.log(chalk_1.default.yellow("💡 MyContext requires 100% accuracy - no fallbacks"));
|
|
4313
|
-
console.log(chalk_1.default.blue("🔄 Retry options:"));
|
|
4314
|
-
console.log(chalk_1.default.gray(" 1. Wait for rate limits to reset"));
|
|
4315
|
-
console.log(chalk_1.default.gray(" 2. Use a different AI provider"));
|
|
4316
|
-
console.log(chalk_1.default.gray(" 3. Check your API key configuration"));
|
|
4317
|
-
console.log(chalk_1.default.gray(" 4. Try again later with: mycontext generate context --full"));
|
|
4318
|
-
throw new Error("AI generation failed - retry when conditions improve");
|
|
4319
|
-
}
|
|
4320
|
-
}
|
|
4321
|
-
async generateEdgeCasesFile(contextDir, contextContent) {
|
|
4322
|
-
const prompt = this.buildEdgeCasesPrompt(contextContent);
|
|
4323
|
-
try {
|
|
4324
|
-
const response = await this.ai.generateText(prompt, {
|
|
4325
|
-
temperature: 0.7,
|
|
4326
|
-
maxTokens: 2000,
|
|
4327
|
-
});
|
|
4328
|
-
const content = this.formatEdgeCasesContent(response.text);
|
|
4329
|
-
await fs.writeFile(path_1.default.join(contextDir, "01c-edge-cases.md"), content);
|
|
4330
|
-
}
|
|
4331
|
-
catch (error) {
|
|
4332
|
-
console.log(chalk_1.default.red("❌ AI generation failed for edge cases"));
|
|
4333
|
-
console.log(chalk_1.default.yellow("💡 MyContext requires 100% accuracy - no fallbacks"));
|
|
4334
|
-
console.log(chalk_1.default.blue("🔄 Retry options:"));
|
|
4335
|
-
console.log(chalk_1.default.gray(" 1. Wait for rate limits to reset"));
|
|
4336
|
-
console.log(chalk_1.default.gray(" 2. Use a different AI provider"));
|
|
4337
|
-
console.log(chalk_1.default.gray(" 3. Check your API key configuration"));
|
|
4338
|
-
console.log(chalk_1.default.gray(" 4. Try again later with: mycontext generate context --full"));
|
|
4339
|
-
throw new Error("AI generation failed - retry when conditions improve");
|
|
4340
|
-
}
|
|
4341
|
-
}
|
|
4342
|
-
async generateTechnicalSpecsFile(contextDir, contextContent) {
|
|
4343
|
-
const prompt = this.buildTechnicalSpecsPrompt(contextContent);
|
|
4344
|
-
try {
|
|
4345
|
-
const response = await this.ai.generateText(prompt, {
|
|
4346
|
-
temperature: 0.7,
|
|
4347
|
-
maxTokens: 2000,
|
|
4348
|
-
});
|
|
4349
|
-
const content = this.formatTechnicalSpecsContent(response.text);
|
|
4350
|
-
await fs.writeFile(path_1.default.join(contextDir, "01d-technical-specs.md"), content);
|
|
4351
|
-
}
|
|
4352
|
-
catch (error) {
|
|
4353
|
-
console.log(chalk_1.default.red("❌ AI generation failed for technical specs"));
|
|
4354
|
-
console.log(chalk_1.default.yellow("💡 MyContext requires 100% accuracy - no fallbacks"));
|
|
4355
|
-
console.log(chalk_1.default.blue("🔄 Retry options:"));
|
|
4356
|
-
console.log(chalk_1.default.gray(" 1. Wait for rate limits to reset"));
|
|
4357
|
-
console.log(chalk_1.default.gray(" 2. Use a different AI provider"));
|
|
4358
|
-
console.log(chalk_1.default.gray(" 3. Check your API key configuration"));
|
|
4359
|
-
console.log(chalk_1.default.gray(" 4. Try again later with: mycontext generate context --full"));
|
|
4360
|
-
throw new Error("AI generation failed - retry when conditions improve");
|
|
4361
|
-
}
|
|
4362
|
-
}
|
|
4363
|
-
buildFeaturesPrompt(contextContent) {
|
|
4364
|
-
return `You are a product manager creating a comprehensive features document for a web application.
|
|
4365
|
-
|
|
4366
|
-
${contextContent
|
|
4367
|
-
? `Project Context (from PRD): ${contextContent}`
|
|
4368
|
-
: "Generate features for a modern web application."}
|
|
4369
|
-
|
|
4370
|
-
Create a detailed features document that includes:
|
|
4371
|
-
|
|
4372
|
-
1. **Core Features** - Primary functionality that defines the product
|
|
4373
|
-
2. **User Features** - Features that directly benefit end users
|
|
4374
|
-
3. **Admin Features** - Administrative and management capabilities
|
|
4375
|
-
4. **Technical Features** - Backend, API, and infrastructure features
|
|
4376
|
-
5. **Integration Features** - Third-party integrations and APIs
|
|
4377
|
-
6. **Security Features** - Authentication, authorization, and data protection
|
|
4378
|
-
7. **Performance Features** - Optimization and scalability features
|
|
4379
|
-
8. **Accessibility Features** - WCAG compliance and inclusive design
|
|
4380
|
-
|
|
4381
|
-
For each feature, include:
|
|
4382
|
-
- Feature name and description
|
|
4383
|
-
- User value proposition
|
|
4384
|
-
- Acceptance criteria
|
|
4385
|
-
- Priority level (High/Medium/Low)
|
|
4386
|
-
- Dependencies on other features
|
|
4387
|
-
|
|
4388
|
-
Format the output as a well-structured markdown document with clear sections and bullet points.`;
|
|
4389
|
-
}
|
|
4390
|
-
buildUserFlowsPrompt(contextContent) {
|
|
4391
|
-
return `You are a UX designer creating comprehensive user flow documentation for a web application.
|
|
4392
|
-
|
|
4393
|
-
${contextContent
|
|
4394
|
-
? `Project Context (from PRD): ${contextContent}`
|
|
4395
|
-
: "Generate user flows for a modern web application."}
|
|
4396
|
-
|
|
4397
|
-
Create detailed user flow documentation that includes:
|
|
4398
|
-
|
|
4399
|
-
1. **Primary User Journeys** - Main user paths through the application
|
|
4400
|
-
2. **Authentication Flows** - Login, signup, password reset, etc.
|
|
4401
|
-
3. **Core Feature Flows** - How users interact with main features
|
|
4402
|
-
4. **Error Handling Flows** - What happens when things go wrong
|
|
4403
|
-
5. **Admin/Management Flows** - Administrative user journeys
|
|
4404
|
-
6. **Mobile vs Desktop Flows** - Responsive design considerations
|
|
4405
|
-
7. **Accessibility Flows** - Screen reader and keyboard navigation paths
|
|
4406
|
-
|
|
4407
|
-
For each flow, include:
|
|
4408
|
-
- Flow name and description
|
|
4409
|
-
- Step-by-step user actions
|
|
4410
|
-
- System responses and feedback
|
|
4411
|
-
- Decision points and branches
|
|
4412
|
-
- Error states and recovery
|
|
4413
|
-
- Success criteria
|
|
4414
|
-
|
|
4415
|
-
Format the output as a well-structured markdown document with clear sections, numbered steps, and flow diagrams in text format.`;
|
|
4416
|
-
}
|
|
4417
|
-
buildEdgeCasesPrompt(contextContent) {
|
|
4418
|
-
return `You are a QA engineer creating comprehensive edge cases and error scenarios documentation for a web application.
|
|
4419
|
-
|
|
4420
|
-
${contextContent
|
|
4421
|
-
? `Project Context (from PRD): ${contextContent}`
|
|
4422
|
-
: "Generate edge cases for a modern web application."}
|
|
4423
|
-
|
|
4424
|
-
Create detailed edge cases documentation that includes:
|
|
4425
|
-
|
|
4426
|
-
1. **Input Validation Edge Cases** - Invalid, malformed, or extreme input scenarios
|
|
4427
|
-
2. **Network Edge Cases** - Offline, slow connections, timeouts, API failures
|
|
4428
|
-
3. **Browser Edge Cases** - Different browsers, versions, disabled features
|
|
4429
|
-
4. **Device Edge Cases** - Mobile, tablet, desktop, different screen sizes
|
|
4430
|
-
5. **Data Edge Cases** - Empty data, large datasets, concurrent modifications
|
|
4431
|
-
6. **Security Edge Cases** - Injection attacks, XSS, CSRF, unauthorized access
|
|
4432
|
-
7. **Performance Edge Cases** - High load, memory constraints, slow operations
|
|
4433
|
-
8. **Accessibility Edge Cases** - Screen readers, keyboard-only navigation, high contrast
|
|
4434
|
-
9. **Integration Edge Cases** - Third-party service failures, API changes
|
|
4435
|
-
10. **Business Logic Edge Cases** - Boundary conditions, race conditions
|
|
4436
|
-
|
|
4437
|
-
For each edge case, include:
|
|
4438
|
-
- Scenario description
|
|
4439
|
-
- Expected behavior
|
|
4440
|
-
- Potential impact
|
|
4441
|
-
- Mitigation strategies
|
|
4442
|
-
- Testing approach
|
|
4443
|
-
|
|
4444
|
-
Format the output as a well-structured markdown document with clear sections and detailed scenarios.`;
|
|
4445
|
-
}
|
|
4446
|
-
buildTechnicalSpecsPrompt(contextContent) {
|
|
4447
|
-
return `You are a technical architect creating comprehensive technical specifications for a web application.
|
|
4448
|
-
|
|
4449
|
-
${contextContent
|
|
4450
|
-
? `Project Context (from PRD): ${contextContent}`
|
|
4451
|
-
: "Generate technical specs for a modern web application."}
|
|
4452
|
-
|
|
4453
|
-
Create detailed technical specifications that include:
|
|
4454
|
-
|
|
4455
|
-
1. **Architecture Overview** - System design, components, and relationships
|
|
4456
|
-
2. **Technology Stack** - Frontend, backend, database, deployment technologies
|
|
4457
|
-
3. **API Specifications** - Endpoints, request/response formats, authentication
|
|
4458
|
-
4. **Database Design** - Schema, relationships, indexing, data flow
|
|
4459
|
-
5. **Security Requirements** - Authentication, authorization, data protection
|
|
4460
|
-
6. **Performance Requirements** - Response times, throughput, scalability
|
|
4461
|
-
7. **Deployment Architecture** - Infrastructure, CI/CD, monitoring
|
|
4462
|
-
8. **Integration Requirements** - Third-party services, APIs, webhooks
|
|
4463
|
-
9. **Development Standards** - Code style, testing, documentation
|
|
4464
|
-
10. **Monitoring and Logging** - Error tracking, analytics, performance monitoring
|
|
4465
|
-
|
|
4466
|
-
For each specification, include:
|
|
4467
|
-
- Requirement description
|
|
4468
|
-
- Technical approach
|
|
4469
|
-
- Implementation details
|
|
4470
|
-
- Dependencies
|
|
4471
|
-
- Success criteria
|
|
4472
|
-
|
|
4473
|
-
Format the output as a well-structured markdown document with clear sections and technical details.`;
|
|
4474
|
-
}
|
|
4475
|
-
formatFeaturesContent(response) {
|
|
4476
|
-
return `# Product Features
|
|
4477
|
-
|
|
4478
|
-
${response}
|
|
4479
|
-
|
|
4480
|
-
---
|
|
4481
|
-
*Generated by MyContext CLI - AI-powered component generation platform*
|
|
4482
|
-
*Last updated: ${new Date().toISOString()}*
|
|
4483
|
-
`;
|
|
4484
|
-
}
|
|
4485
|
-
formatUserFlowsContent(response) {
|
|
4486
|
-
return `# User Flows
|
|
4487
|
-
|
|
4488
|
-
${response}
|
|
4489
|
-
|
|
4490
|
-
---
|
|
4491
|
-
*Generated by MyContext CLI - AI-powered component generation platform*
|
|
4492
|
-
*Last updated: ${new Date().toISOString()}*
|
|
4493
|
-
`;
|
|
4494
|
-
}
|
|
4495
|
-
formatEdgeCasesContent(response) {
|
|
4496
|
-
return `# Edge Cases and Error Scenarios
|
|
4497
|
-
|
|
4498
|
-
${response}
|
|
4499
|
-
|
|
4500
|
-
---
|
|
4501
|
-
*Generated by MyContext CLI - AI-powered component generation platform*
|
|
4502
|
-
*Last updated: ${new Date().toISOString()}*
|
|
4503
|
-
`;
|
|
4504
|
-
}
|
|
4505
|
-
formatTechnicalSpecsContent(response) {
|
|
4506
|
-
return `# Technical Specifications
|
|
4507
|
-
|
|
4508
|
-
${response}
|
|
4509
|
-
|
|
4510
|
-
---
|
|
4511
|
-
*Generated by MyContext CLI - AI-powered component generation platform*
|
|
4512
|
-
*Last updated: ${new Date().toISOString()}*
|
|
4513
|
-
`;
|
|
4514
|
-
}
|
|
4515
|
-
/**
|
|
4516
|
-
* Get context content for generation - prefer PRD over description
|
|
4517
|
-
*/
|
|
4518
|
-
async getContextForGeneration(contextDir, fallbackDescription) {
|
|
4519
|
-
// First, try to read from 01-prd.md
|
|
4520
|
-
const prdPath = path_1.default.join(contextDir, "01-prd.md");
|
|
4521
|
-
if (await fs.pathExists(prdPath)) {
|
|
4522
|
-
try {
|
|
4523
|
-
const prdContent = await fs.readFile(prdPath, "utf8");
|
|
4524
|
-
// Check if PRD is just a template/starter sample
|
|
4525
|
-
if (this.isTemplatePRD(prdContent)) {
|
|
4526
|
-
console.log(chalk_1.default.yellow("⚠️ PRD appears to be a template, not using as context"));
|
|
4527
|
-
}
|
|
4528
|
-
else {
|
|
4529
|
-
console.log(chalk_1.default.blue("📖 Using existing PRD as context for context files generation"));
|
|
4530
|
-
return prdContent;
|
|
4531
|
-
}
|
|
4532
|
-
}
|
|
4533
|
-
catch (error) {
|
|
4534
|
-
console.log(chalk_1.default.yellow("⚠️ Could not read PRD file, falling back to description"));
|
|
4535
|
-
}
|
|
4536
|
-
}
|
|
4537
|
-
// Fallback to description if no PRD exists
|
|
4538
|
-
if (fallbackDescription) {
|
|
4539
|
-
console.log(chalk_1.default.blue("📝 Using project description as context"));
|
|
4540
|
-
return fallbackDescription;
|
|
4541
|
-
}
|
|
4542
|
-
// No context available - ask user
|
|
4543
|
-
console.log(chalk_1.default.red("❌ No PRD or description found!"));
|
|
4544
|
-
console.log(chalk_1.default.yellow("Please provide context by either:"));
|
|
4545
|
-
console.log(chalk_1.default.gray(" 1. Run 'mycontext generate context' first to create a PRD"));
|
|
4546
|
-
console.log(chalk_1.default.gray(" 2. Use --description flag: mycontext generate-context-files --description 'Your project'"));
|
|
4547
|
-
console.log(chalk_1.default.gray(" 3. Create a PRD file manually at .mycontext/01-prd.md"));
|
|
4548
|
-
throw new Error("No context available for generation. Please provide a PRD or description.");
|
|
4549
|
-
}
|
|
4550
|
-
/**
|
|
4551
|
-
* Check if PRD content is just a template/starter sample
|
|
4552
|
-
*/
|
|
4553
|
-
isTemplatePRD(content) {
|
|
4554
|
-
const templateIndicators = [
|
|
4555
|
-
"MyContext project",
|
|
4556
|
-
"Replace this with your actual project description",
|
|
4557
|
-
"TODO: Add your project details",
|
|
4558
|
-
"This is a template",
|
|
4559
|
-
"Sample project",
|
|
4560
|
-
"Example project",
|
|
4561
|
-
"Your project description here",
|
|
4562
|
-
"Project Name: [Your Project Name]",
|
|
4563
|
-
"Description: [Your project description]",
|
|
4564
|
-
"## Project Overview\n\n[Add your project overview here]",
|
|
4565
|
-
"## Requirements\n\n[Add your requirements here]",
|
|
4566
|
-
"## Features\n\n[Add your features here]",
|
|
4567
|
-
"## Technical Specifications\n\n[Add your technical specs here]",
|
|
4568
|
-
];
|
|
4569
|
-
// Check if content contains multiple template indicators
|
|
4570
|
-
const templateMatches = templateIndicators.filter((indicator) => content.toLowerCase().includes(indicator.toLowerCase()));
|
|
4571
|
-
// If more than 2 template indicators are found, it's likely a template
|
|
4572
|
-
if (templateMatches.length >= 2) {
|
|
4573
|
-
return true;
|
|
4574
|
-
}
|
|
4575
|
-
// Check if content is very short (likely a template)
|
|
4576
|
-
// BUT NOT if it's just a success message from context generation
|
|
4577
|
-
if (content.includes("Full context generated successfully") ||
|
|
4578
|
-
content.includes("context generated successfully")) {
|
|
4579
|
-
return false; // This is not a template, it's a success message
|
|
4580
|
-
}
|
|
4581
|
-
if (content.trim().length < 200) {
|
|
4582
|
-
return true;
|
|
4583
|
-
}
|
|
4584
|
-
// Check if content is mostly placeholder text
|
|
4585
|
-
const placeholderRatio = (content.match(/\[.*?\]/g) || []).length /
|
|
4586
|
-
(content.split(" ").length || 1);
|
|
4587
|
-
if (placeholderRatio > 0.1) {
|
|
4588
|
-
// More than 10% placeholders
|
|
4589
|
-
return true;
|
|
4590
|
-
}
|
|
4591
|
-
return false;
|
|
4592
|
-
}
|
|
4593
|
-
/**
|
|
4594
|
-
* REMOVED: Dangerous fallback method that compromises accuracy
|
|
4595
|
-
* MyContext requires 100% accuracy - no fallbacks allowed
|
|
4596
|
-
*/
|
|
4597
|
-
extractFeaturesFromPRD_DISABLED(prdContent) {
|
|
4598
|
-
if (!prdContent) {
|
|
4599
|
-
return `# Product Features
|
|
4600
|
-
|
|
4601
|
-
## Core Features
|
|
4602
|
-
|
|
4603
|
-
*No features available - PRD content not found*
|
|
4604
|
-
|
|
4605
|
-
---
|
|
4606
|
-
*Generated by MyContext CLI - AI-powered component generation platform*
|
|
4607
|
-
*Last updated: ${new Date().toISOString()}*
|
|
4608
|
-
`;
|
|
4609
|
-
}
|
|
4610
|
-
// Extract features from PRD content
|
|
4611
|
-
const features = this.extractSectionFromPRD(prdContent, [
|
|
4612
|
-
"Core Features",
|
|
4613
|
-
"Features",
|
|
4614
|
-
"Key Features",
|
|
4615
|
-
"Main Features",
|
|
4616
|
-
]);
|
|
4617
|
-
return `# Product Features
|
|
4618
|
-
|
|
4619
|
-
${features ||
|
|
4620
|
-
"## Core Features\n\n*Features will be extracted from PRD content*"}
|
|
4621
|
-
|
|
4622
|
-
---
|
|
4623
|
-
*Generated by MyContext CLI - AI-powered component generation platform*
|
|
4624
|
-
*Last updated: ${new Date().toISOString()}*
|
|
4625
|
-
`;
|
|
4626
|
-
}
|
|
4627
|
-
/**
|
|
4628
|
-
* REMOVED: Dangerous fallback method that compromises accuracy
|
|
4629
|
-
* MyContext requires 100% accuracy - no fallbacks allowed
|
|
4630
|
-
*/
|
|
4631
|
-
extractUserFlowsFromPRD_DISABLED(prdContent) {
|
|
4632
|
-
if (!prdContent) {
|
|
4633
|
-
return `# User Flows
|
|
4634
|
-
|
|
4635
|
-
## User Journey
|
|
4636
|
-
|
|
4637
|
-
*No user flows available - PRD content not found*
|
|
4638
|
-
|
|
4639
|
-
---
|
|
4640
|
-
*Generated by MyContext CLI - AI-powered component generation platform*
|
|
4641
|
-
*Last updated: ${new Date().toISOString()}*
|
|
4642
|
-
`;
|
|
4643
|
-
}
|
|
4644
|
-
// Extract user flows from PRD content
|
|
4645
|
-
const userFlows = this.extractSectionFromPRD(prdContent, [
|
|
4646
|
-
"User Roles",
|
|
4647
|
-
"User Journey",
|
|
4648
|
-
"User Flows",
|
|
4649
|
-
"Workflow",
|
|
4650
|
-
]);
|
|
4651
|
-
return `# User Flows
|
|
4652
|
-
|
|
4653
|
-
${userFlows ||
|
|
4654
|
-
"## User Journey\n\n*User flows will be extracted from PRD content*"}
|
|
4655
|
-
|
|
4656
|
-
---
|
|
4657
|
-
*Generated by MyContext CLI - AI-powered component generation platform*
|
|
4658
|
-
*Last updated: ${new Date().toISOString()}*
|
|
4659
|
-
`;
|
|
4660
|
-
}
|
|
4661
|
-
/**
|
|
4662
|
-
* REMOVED: Dangerous fallback method that compromises accuracy
|
|
4663
|
-
* MyContext requires 100% accuracy - no fallbacks allowed
|
|
4664
|
-
*/
|
|
4665
|
-
extractEdgeCasesFromPRD_DISABLED(prdContent) {
|
|
4666
|
-
if (!prdContent) {
|
|
4667
|
-
return `# Edge Cases and Error Scenarios
|
|
4668
|
-
|
|
4669
|
-
## Error Handling
|
|
4670
|
-
|
|
4671
|
-
*No edge cases available - PRD content not found*
|
|
4672
|
-
|
|
4673
|
-
---
|
|
4674
|
-
*Generated by MyContext CLI - AI-powered component generation platform*
|
|
4675
|
-
*Last updated: ${new Date().toISOString()}*
|
|
4676
|
-
`;
|
|
4677
|
-
}
|
|
4678
|
-
// Extract edge cases from PRD content
|
|
4679
|
-
const edgeCases = this.extractSectionFromPRD(prdContent, [
|
|
4680
|
-
"Risk Mitigation",
|
|
4681
|
-
"Edge Cases",
|
|
4682
|
-
"Error Scenarios",
|
|
4683
|
-
"Troubleshooting",
|
|
4684
|
-
]);
|
|
4685
|
-
return `# Edge Cases and Error Scenarios
|
|
4686
|
-
|
|
4687
|
-
${edgeCases ||
|
|
4688
|
-
"## Error Handling\n\n*Edge cases will be extracted from PRD content*"}
|
|
4689
|
-
|
|
4690
|
-
---
|
|
4691
|
-
*Generated by MyContext CLI - AI-powered component generation platform*
|
|
4692
|
-
*Last updated: ${new Date().toISOString()}*
|
|
4693
|
-
`;
|
|
4694
|
-
}
|
|
4695
|
-
/**
|
|
4696
|
-
* REMOVED: Dangerous fallback method that compromises accuracy
|
|
4697
|
-
* MyContext requires 100% accuracy - no fallbacks allowed
|
|
4698
|
-
*/
|
|
4699
|
-
extractTechnicalSpecsFromPRD_DISABLED(prdContent) {
|
|
4700
|
-
if (!prdContent) {
|
|
4701
|
-
return `# Technical Specifications
|
|
4702
|
-
|
|
4703
|
-
## Architecture
|
|
4704
|
-
|
|
4705
|
-
*No technical specs available - PRD content not found*
|
|
4706
|
-
|
|
4707
|
-
---
|
|
4708
|
-
*Generated by MyContext CLI - AI-powered component generation platform*
|
|
4709
|
-
*Last updated: ${new Date().toISOString()}*
|
|
4710
|
-
`;
|
|
4711
|
-
}
|
|
4712
|
-
// Extract technical specs from PRD content
|
|
4713
|
-
const techSpecs = this.extractSectionFromPRD(prdContent, [
|
|
4714
|
-
"Technical Architecture",
|
|
4715
|
-
"Technical Specifications",
|
|
4716
|
-
"Architecture",
|
|
4717
|
-
"Technology Stack",
|
|
4718
|
-
]);
|
|
4719
|
-
return `# Technical Specifications
|
|
4720
|
-
|
|
4721
|
-
${techSpecs ||
|
|
4722
|
-
"## Architecture\n\n*Technical specifications will be extracted from PRD content*"}
|
|
4723
|
-
|
|
4724
|
-
---
|
|
4725
|
-
*Generated by MyContext CLI - AI-powered component generation platform*
|
|
4726
|
-
*Last updated: ${new Date().toISOString()}*
|
|
4727
|
-
`;
|
|
4728
|
-
}
|
|
4729
|
-
/**
|
|
4730
|
-
* Extract a section from PRD content by looking for common section headers
|
|
4731
|
-
*/
|
|
4732
|
-
extractSectionFromPRD(prdContent, sectionHeaders) {
|
|
4733
|
-
const lines = prdContent.split("\n");
|
|
4734
|
-
let inSection = false;
|
|
4735
|
-
let sectionContent = [];
|
|
4736
|
-
let currentSection = "";
|
|
4737
|
-
for (const line of lines) {
|
|
4738
|
-
const trimmedLine = line.trim();
|
|
4739
|
-
// Check if this line starts a section we're looking for
|
|
4740
|
-
if (sectionHeaders.some((header) => trimmedLine.toLowerCase().includes(header.toLowerCase()) &&
|
|
4741
|
-
(trimmedLine.startsWith("#") ||
|
|
4742
|
-
trimmedLine.startsWith("##") ||
|
|
4743
|
-
trimmedLine.startsWith("###")))) {
|
|
4744
|
-
if (inSection) {
|
|
4745
|
-
// We found a new section, stop collecting the previous one
|
|
4746
|
-
break;
|
|
4747
|
-
}
|
|
4748
|
-
inSection = true;
|
|
4749
|
-
currentSection = trimmedLine;
|
|
4750
|
-
sectionContent.push(line);
|
|
4751
|
-
continue;
|
|
4752
|
-
}
|
|
4753
|
-
if (inSection) {
|
|
4754
|
-
// Check if we hit another major section (starts with # or ##)
|
|
4755
|
-
if (trimmedLine.startsWith("#") &&
|
|
4756
|
-
!trimmedLine.includes(currentSection)) {
|
|
4757
|
-
break;
|
|
4758
|
-
}
|
|
4759
|
-
sectionContent.push(line);
|
|
4760
|
-
}
|
|
4761
|
-
}
|
|
4762
|
-
return sectionContent.join("\n").trim();
|
|
4763
|
-
}
|
|
4764
4037
|
}
|
|
4765
4038
|
exports.GenerateCommand = GenerateCommand;
|
|
4766
4039
|
//# sourceMappingURL=generate.js.map
|