@agile-vibe-coding/avc 0.1.0 → 0.1.1
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 +2 -0
- package/cli/agents/documentation.md +302 -0
- package/cli/build-docs.js +277 -0
- package/cli/command-logger.js +208 -0
- package/cli/index.js +3 -25
- package/cli/init.js +705 -77
- package/cli/llm-claude.js +27 -0
- package/cli/llm-gemini.js +30 -0
- package/cli/llm-provider.js +63 -0
- package/cli/logger.js +32 -5
- package/cli/process-manager.js +261 -0
- package/cli/repl-ink.js +1784 -219
- package/cli/template-processor.js +274 -73
- package/cli/templates/vitepress-config.mts.template +33 -0
- package/package.json +17 -3
|
@@ -2,7 +2,7 @@ import dotenv from 'dotenv';
|
|
|
2
2
|
import fs from 'fs';
|
|
3
3
|
import path from 'path';
|
|
4
4
|
import readline from 'readline';
|
|
5
|
-
import
|
|
5
|
+
import { LLMProvider } from './llm-provider.js';
|
|
6
6
|
import { fileURLToPath } from 'url';
|
|
7
7
|
|
|
8
8
|
const __filename = fileURLToPath(import.meta.url);
|
|
@@ -20,7 +20,7 @@ const __dirname = path.dirname(__filename);
|
|
|
20
20
|
* 6. Write to .avc/project/doc.md
|
|
21
21
|
*/
|
|
22
22
|
class TemplateProcessor {
|
|
23
|
-
constructor(progressPath = null) {
|
|
23
|
+
constructor(progressPath = null, nonInteractive = false) {
|
|
24
24
|
// Load environment variables from project .env
|
|
25
25
|
dotenv.config({ path: path.join(process.cwd(), '.env') });
|
|
26
26
|
|
|
@@ -29,11 +29,13 @@ class TemplateProcessor {
|
|
|
29
29
|
this.outputPath = path.join(this.outputDir, 'doc.md');
|
|
30
30
|
this.avcConfigPath = path.join(process.cwd(), '.avc/avc.json');
|
|
31
31
|
this.progressPath = progressPath;
|
|
32
|
+
this.nonInteractive = nonInteractive;
|
|
32
33
|
|
|
33
34
|
// Read model configuration from avc.json
|
|
34
|
-
|
|
35
|
-
this.
|
|
36
|
-
this.
|
|
35
|
+
const { provider, model } = this.readModelConfig();
|
|
36
|
+
this._providerName = provider;
|
|
37
|
+
this._modelName = model;
|
|
38
|
+
this.llmProvider = null;
|
|
37
39
|
}
|
|
38
40
|
|
|
39
41
|
/**
|
|
@@ -42,10 +44,73 @@ class TemplateProcessor {
|
|
|
42
44
|
readModelConfig() {
|
|
43
45
|
try {
|
|
44
46
|
const config = JSON.parse(fs.readFileSync(this.avcConfigPath, 'utf8'));
|
|
45
|
-
|
|
47
|
+
const ceremony = config.settings?.ceremonies?.[0];
|
|
48
|
+
if (ceremony) {
|
|
49
|
+
return { provider: ceremony.provider || 'claude', model: ceremony.defaultModel || 'claude-sonnet-4-5-20250929' };
|
|
50
|
+
}
|
|
51
|
+
// Legacy fallback: settings.model without ceremonies array
|
|
52
|
+
return { provider: 'claude', model: config.settings?.model || 'claude-sonnet-4-5-20250929' };
|
|
46
53
|
} catch (error) {
|
|
47
54
|
console.warn('⚠️ Could not read model config, using default');
|
|
48
|
-
return 'claude-sonnet-4-5-20250929';
|
|
55
|
+
return { provider: 'claude', model: 'claude-sonnet-4-5-20250929' };
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Read guidelines from avc.json ceremony configuration
|
|
61
|
+
*/
|
|
62
|
+
readGuidelines() {
|
|
63
|
+
try {
|
|
64
|
+
const config = JSON.parse(fs.readFileSync(this.avcConfigPath, 'utf8'));
|
|
65
|
+
const ceremony = config.settings?.ceremonies?.[0];
|
|
66
|
+
return ceremony?.guidelines || {};
|
|
67
|
+
} catch (error) {
|
|
68
|
+
return {};
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Load agent instructions from markdown file
|
|
74
|
+
* @param {string} agentFileName - Filename in src/cli/agents/
|
|
75
|
+
* @returns {string|null} - Agent instructions content or null if not found
|
|
76
|
+
*/
|
|
77
|
+
loadAgentInstructions(agentFileName) {
|
|
78
|
+
try {
|
|
79
|
+
const agentPath = path.join(__dirname, 'agents', agentFileName);
|
|
80
|
+
if (!fs.existsSync(agentPath)) {
|
|
81
|
+
console.warn(`⚠️ Agent instruction file not found: ${agentFileName}`);
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
return fs.readFileSync(agentPath, 'utf8');
|
|
85
|
+
} catch (error) {
|
|
86
|
+
console.warn(`⚠️ Could not load agent instructions: ${error.message}`);
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Get agent instructions for a specific ceremony stage
|
|
93
|
+
* @param {string} stage - Ceremony stage (e.g., 'enhancement', 'suggestion', 'validation')
|
|
94
|
+
* @returns {string|null} - Agent instructions or null if not configured/found
|
|
95
|
+
*/
|
|
96
|
+
getAgentForStage(stage) {
|
|
97
|
+
try {
|
|
98
|
+
const config = JSON.parse(fs.readFileSync(this.avcConfigPath, 'utf8'));
|
|
99
|
+
const ceremony = config.settings?.ceremonies?.[0];
|
|
100
|
+
|
|
101
|
+
if (!ceremony?.agents || ceremony.agents.length === 0) {
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const agent = ceremony.agents.find(a => a.stage === stage);
|
|
106
|
+
if (!agent) {
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return this.loadAgentInstructions(agent.instruction);
|
|
111
|
+
} catch (error) {
|
|
112
|
+
console.warn(`⚠️ Could not get agent for stage ${stage}: ${error.message}`);
|
|
113
|
+
return null;
|
|
49
114
|
}
|
|
50
115
|
}
|
|
51
116
|
|
|
@@ -219,18 +284,17 @@ class TemplateProcessor {
|
|
|
219
284
|
}
|
|
220
285
|
|
|
221
286
|
/**
|
|
222
|
-
* Initialize
|
|
287
|
+
* Initialize LLM provider
|
|
223
288
|
*/
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
289
|
+
async initializeLLMProvider() {
|
|
290
|
+
try {
|
|
291
|
+
this.llmProvider = await LLMProvider.create(this._providerName, this._modelName);
|
|
292
|
+
return this.llmProvider;
|
|
293
|
+
} catch (error) {
|
|
294
|
+
console.log(`⚠️ Could not initialize ${this._providerName} provider - AI suggestions will be skipped`);
|
|
295
|
+
console.log(` ${error.message}`);
|
|
227
296
|
return null;
|
|
228
297
|
}
|
|
229
|
-
|
|
230
|
-
this.claudeClient = new Anthropic({
|
|
231
|
-
apiKey: process.env.ANTHROPIC_API_KEY
|
|
232
|
-
});
|
|
233
|
-
return this.claudeClient;
|
|
234
298
|
}
|
|
235
299
|
|
|
236
300
|
/**
|
|
@@ -264,11 +328,12 @@ class TemplateProcessor {
|
|
|
264
328
|
/**
|
|
265
329
|
* Parse Claude's response into structured format
|
|
266
330
|
*/
|
|
267
|
-
|
|
331
|
+
parseLLMResponse(response, isPlural) {
|
|
268
332
|
if (isPlural) {
|
|
269
333
|
return response.split('\n')
|
|
270
334
|
.map(line => line.trim())
|
|
271
|
-
.filter(line => line.length > 0
|
|
335
|
+
.filter(line => line.length > 0)
|
|
336
|
+
.map(line => line.replace(/^[0-9\-*.]+\s+/, '')); // Remove list prefixes
|
|
272
337
|
}
|
|
273
338
|
return response.trim();
|
|
274
339
|
}
|
|
@@ -277,20 +342,14 @@ class TemplateProcessor {
|
|
|
277
342
|
* Generate AI suggestions for a variable
|
|
278
343
|
*/
|
|
279
344
|
async generateSuggestions(variableName, isPlural, context) {
|
|
280
|
-
if (!this.
|
|
345
|
+
if (!this.llmProvider && !(await this.initializeLLMProvider())) {
|
|
281
346
|
return null;
|
|
282
347
|
}
|
|
283
348
|
|
|
284
349
|
try {
|
|
285
350
|
const prompt = this.buildPrompt(variableName, isPlural, context);
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
model: this.model,
|
|
289
|
-
max_tokens: isPlural ? 512 : 256,
|
|
290
|
-
messages: [{ role: "user", content: prompt }]
|
|
291
|
-
});
|
|
292
|
-
|
|
293
|
-
return this.parseClaudeResponse(response.content[0].text, isPlural);
|
|
351
|
+
const text = await this.llmProvider.generate(prompt, isPlural ? 512 : 256);
|
|
352
|
+
return this.parseLLMResponse(text, isPlural);
|
|
294
353
|
} catch (error) {
|
|
295
354
|
console.warn(`⚠️ Could not generate suggestions: ${error.message}`);
|
|
296
355
|
return null;
|
|
@@ -304,14 +363,45 @@ class TemplateProcessor {
|
|
|
304
363
|
async promptUser(variable, context) {
|
|
305
364
|
let value;
|
|
306
365
|
|
|
307
|
-
|
|
308
|
-
|
|
366
|
+
// In non-interactive mode, skip readline prompts and use guidelines/AI
|
|
367
|
+
if (this.nonInteractive) {
|
|
368
|
+
console.log(`\n📝 ${variable.displayName}`);
|
|
369
|
+
if (variable.guidance) {
|
|
370
|
+
console.log(` ${variable.guidance}`);
|
|
371
|
+
}
|
|
372
|
+
console.log(' Generating AI response...');
|
|
373
|
+
value = null; // Force AI generation
|
|
309
374
|
} else {
|
|
310
|
-
|
|
375
|
+
// Interactive mode - use readline prompts
|
|
376
|
+
if (variable.isPlural) {
|
|
377
|
+
value = await this.promptPlural(variable.displayName, variable.guidance);
|
|
378
|
+
} else {
|
|
379
|
+
value = await this.promptSingular(variable.displayName, variable.guidance);
|
|
380
|
+
}
|
|
311
381
|
}
|
|
312
382
|
|
|
313
|
-
// If user skipped, try to generate AI suggestions
|
|
383
|
+
// If user skipped (or non-interactive mode), try to use guideline or generate AI suggestions
|
|
314
384
|
if (value === null) {
|
|
385
|
+
// Check if there's a guideline for this variable
|
|
386
|
+
const guidelines = this.readGuidelines();
|
|
387
|
+
const guidelineKey = variable.name.toLowerCase().replace(/_/g, '');
|
|
388
|
+
|
|
389
|
+
if (guidelines[guidelineKey]) {
|
|
390
|
+
console.log(' 📋 Using default guideline...');
|
|
391
|
+
value = variable.isPlural
|
|
392
|
+
? [guidelines[guidelineKey]] // Wrap in array for plural variables
|
|
393
|
+
: guidelines[guidelineKey];
|
|
394
|
+
|
|
395
|
+
console.log(' ✅ Guideline applied:');
|
|
396
|
+
if (Array.isArray(value)) {
|
|
397
|
+
value.forEach((item, idx) => console.log(` ${idx + 1}. ${item}`));
|
|
398
|
+
} else {
|
|
399
|
+
console.log(` ${value}`);
|
|
400
|
+
}
|
|
401
|
+
return { variable: variable.name, value, source: 'guideline', skipped: true };
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
// No guideline available, try AI suggestions
|
|
315
405
|
console.log(' ✨ Generating AI suggestion...');
|
|
316
406
|
value = await this.generateSuggestions(variable.name, variable.isPlural, context);
|
|
317
407
|
|
|
@@ -361,20 +451,34 @@ class TemplateProcessor {
|
|
|
361
451
|
* Generate final document with LLM enhancement
|
|
362
452
|
*/
|
|
363
453
|
async generateFinalDocument(templateWithValues) {
|
|
364
|
-
if (!this.
|
|
365
|
-
// No
|
|
454
|
+
if (!this.llmProvider && !(await this.initializeLLMProvider())) {
|
|
455
|
+
// No provider available - save template as-is
|
|
456
|
+
console.log('\n⚠️ AI enhancement skipped (no LLM provider available)');
|
|
366
457
|
return templateWithValues;
|
|
367
458
|
}
|
|
368
459
|
|
|
369
460
|
console.log('\n🤖 Enhancing document with AI...');
|
|
370
461
|
|
|
371
462
|
try {
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
463
|
+
// Try to load agent instructions for enhancement stage
|
|
464
|
+
const agentInstructions = this.getAgentForStage('enhancement');
|
|
465
|
+
|
|
466
|
+
if (agentInstructions) {
|
|
467
|
+
console.log(' Using custom agent instructions for enhancement');
|
|
468
|
+
// Use agent instructions as system context
|
|
469
|
+
const userPrompt = `Here is the project information with all variables filled in:
|
|
470
|
+
|
|
471
|
+
${templateWithValues}
|
|
472
|
+
|
|
473
|
+
Please review and enhance this document according to your role.`;
|
|
474
|
+
|
|
475
|
+
const enhanced = await this.llmProvider.generate(userPrompt, 4096, agentInstructions);
|
|
476
|
+
console.log(' ✓ Document enhanced successfully');
|
|
477
|
+
return enhanced;
|
|
478
|
+
} else {
|
|
479
|
+
console.log(' Using default enhancement instructions');
|
|
480
|
+
// Fallback to legacy hardcoded prompt for backward compatibility
|
|
481
|
+
const legacyPrompt = `You are creating a project definition document for an Agile Vibe Coding (AVC) project.
|
|
378
482
|
|
|
379
483
|
Here is the project information with all variables filled in:
|
|
380
484
|
|
|
@@ -386,13 +490,15 @@ Please review and enhance this document to ensure:
|
|
|
386
490
|
3. Sections flow logically
|
|
387
491
|
4. Any incomplete sections are identified
|
|
388
492
|
|
|
389
|
-
Return the enhanced markdown document
|
|
390
|
-
}]
|
|
391
|
-
});
|
|
493
|
+
Return the enhanced markdown document.`;
|
|
392
494
|
|
|
393
|
-
|
|
495
|
+
const enhanced = await this.llmProvider.generate(legacyPrompt, 4096);
|
|
496
|
+
console.log(' ✓ Document enhanced successfully');
|
|
497
|
+
return enhanced;
|
|
498
|
+
}
|
|
394
499
|
} catch (error) {
|
|
395
|
-
console.warn(
|
|
500
|
+
console.warn(`\n⚠️ Could not enhance document: ${error.message}`);
|
|
501
|
+
console.log(' Using template without AI enhancement');
|
|
396
502
|
return templateWithValues;
|
|
397
503
|
}
|
|
398
504
|
}
|
|
@@ -406,6 +512,67 @@ Return the enhanced markdown document.`
|
|
|
406
512
|
}
|
|
407
513
|
}
|
|
408
514
|
|
|
515
|
+
/**
|
|
516
|
+
* Sync project documentation to VitePress documentation folder
|
|
517
|
+
*/
|
|
518
|
+
syncToVitePress(content) {
|
|
519
|
+
try {
|
|
520
|
+
const docsDir = path.join(process.cwd(), '.avc/documentation');
|
|
521
|
+
const indexPath = path.join(docsDir, 'index.md');
|
|
522
|
+
|
|
523
|
+
// Check if documentation folder exists
|
|
524
|
+
if (!fs.existsSync(docsDir)) {
|
|
525
|
+
console.log(' ℹ️ VitePress documentation folder not found, skipping sync');
|
|
526
|
+
return false;
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
// Write to .avc/documentation/index.md
|
|
530
|
+
fs.writeFileSync(indexPath, content, 'utf8');
|
|
531
|
+
console.log(` ✓ Synced to .avc/documentation/index.md`);
|
|
532
|
+
return true;
|
|
533
|
+
} catch (error) {
|
|
534
|
+
console.warn(` ⚠️ Could not sync to VitePress: ${error.message}`);
|
|
535
|
+
return false;
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
/**
|
|
540
|
+
* Build VitePress documentation site
|
|
541
|
+
*/
|
|
542
|
+
async buildVitePress() {
|
|
543
|
+
try {
|
|
544
|
+
const docsDir = path.join(process.cwd(), '.avc/documentation');
|
|
545
|
+
const packagePath = path.join(process.cwd(), 'package.json');
|
|
546
|
+
|
|
547
|
+
// Check if VitePress is configured
|
|
548
|
+
if (!fs.existsSync(docsDir) || !fs.existsSync(packagePath)) {
|
|
549
|
+
return false;
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
const packageJson = JSON.parse(fs.readFileSync(packagePath, 'utf8'));
|
|
553
|
+
if (!packageJson.scripts?.['docs:build']) {
|
|
554
|
+
return false;
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
console.log('\n📚 Building VitePress documentation...');
|
|
558
|
+
|
|
559
|
+
// Import execSync for running build command
|
|
560
|
+
const { execSync } = await import('child_process');
|
|
561
|
+
|
|
562
|
+
// Run VitePress build
|
|
563
|
+
execSync('npm run docs:build', {
|
|
564
|
+
cwd: process.cwd(),
|
|
565
|
+
stdio: 'inherit'
|
|
566
|
+
});
|
|
567
|
+
|
|
568
|
+
console.log('✓ VitePress build completed');
|
|
569
|
+
return true;
|
|
570
|
+
} catch (error) {
|
|
571
|
+
console.warn(`⚠️ VitePress build failed: ${error.message}`);
|
|
572
|
+
return false;
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
|
|
409
576
|
/**
|
|
410
577
|
* Write document to file
|
|
411
578
|
*/
|
|
@@ -420,6 +587,14 @@ Return the enhanced markdown document.`
|
|
|
420
587
|
|
|
421
588
|
console.log(`\n✅ Project document generated!`);
|
|
422
589
|
console.log(` Location: ${this.outputPath}`);
|
|
590
|
+
|
|
591
|
+
// Sync to VitePress if configured
|
|
592
|
+
const synced = this.syncToVitePress(content);
|
|
593
|
+
|
|
594
|
+
// Optionally build VitePress (commented out by default to avoid slow builds during dev)
|
|
595
|
+
// if (synced) {
|
|
596
|
+
// await this.buildVitePress();
|
|
597
|
+
// }
|
|
423
598
|
}
|
|
424
599
|
|
|
425
600
|
/**
|
|
@@ -441,38 +616,64 @@ Return the enhanced markdown document.`
|
|
|
441
616
|
if (initialProgress && initialProgress.collectedValues) {
|
|
442
617
|
collectedValues = { ...initialProgress.collectedValues };
|
|
443
618
|
answeredCount = Object.keys(collectedValues).length;
|
|
444
|
-
console.log(`Resuming with ${answeredCount}/${variables.length} questions already answered.\n`);
|
|
445
|
-
} else {
|
|
446
|
-
console.log(`Found ${variables.length} sections to complete.\n`);
|
|
447
|
-
}
|
|
448
619
|
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
620
|
+
// Check if ALL answers are pre-filled (from REPL questionnaire)
|
|
621
|
+
if (answeredCount === variables.length) {
|
|
622
|
+
console.log(`✅ Using ${answeredCount} pre-filled answers from questionnaire.\n`);
|
|
623
|
+
|
|
624
|
+
// Use pre-filled answers, but still allow AI enhancement for skipped (null) answers
|
|
625
|
+
for (const variable of variables) {
|
|
626
|
+
if (collectedValues[variable.name] === null) {
|
|
627
|
+
console.log(`\n📝 ${variable.displayName}`);
|
|
628
|
+
console.log(' Generating AI suggestion...');
|
|
629
|
+
const aiValue = await this.generateSuggestions(variable.name, variable.isPlural, collectedValues);
|
|
630
|
+
collectedValues[variable.name] = aiValue || '';
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
} else {
|
|
634
|
+
console.log(`Resuming with ${answeredCount}/${variables.length} questions already answered.\n`);
|
|
635
|
+
|
|
636
|
+
// Continue with normal interactive flow for remaining questions
|
|
637
|
+
for (const variable of variables) {
|
|
638
|
+
if (collectedValues[variable.name] === undefined) {
|
|
639
|
+
const result = await this.promptUser(variable, collectedValues);
|
|
640
|
+
collectedValues[result.variable] = result.value;
|
|
641
|
+
answeredCount++;
|
|
642
|
+
|
|
643
|
+
// Save progress after each question
|
|
644
|
+
if (this.progressPath) {
|
|
645
|
+
const progress = {
|
|
646
|
+
stage: 'questionnaire',
|
|
647
|
+
totalQuestions: variables.length,
|
|
648
|
+
answeredQuestions: answeredCount,
|
|
649
|
+
collectedValues: collectedValues,
|
|
650
|
+
lastUpdate: new Date().toISOString()
|
|
651
|
+
};
|
|
652
|
+
this.saveProgress(progress);
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
}
|
|
460
656
|
}
|
|
657
|
+
} else {
|
|
658
|
+
console.log(`Found ${variables.length} sections to complete.\n`);
|
|
461
659
|
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
660
|
+
// 4. Collect values with context accumulation
|
|
661
|
+
for (const variable of variables) {
|
|
662
|
+
const result = await this.promptUser(variable, collectedValues);
|
|
663
|
+
collectedValues[result.variable] = result.value;
|
|
664
|
+
answeredCount++;
|
|
665
|
+
|
|
666
|
+
// Save progress after each question
|
|
667
|
+
if (this.progressPath) {
|
|
668
|
+
const progress = {
|
|
669
|
+
stage: 'questionnaire',
|
|
670
|
+
totalQuestions: variables.length,
|
|
671
|
+
answeredQuestions: answeredCount,
|
|
672
|
+
collectedValues: collectedValues,
|
|
673
|
+
lastUpdate: new Date().toISOString()
|
|
674
|
+
};
|
|
675
|
+
this.saveProgress(progress);
|
|
676
|
+
}
|
|
476
677
|
}
|
|
477
678
|
}
|
|
478
679
|
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { defineConfig } from 'vitepress'
|
|
2
|
+
|
|
3
|
+
export default defineConfig({
|
|
4
|
+
title: '{{PROJECT_NAME}}',
|
|
5
|
+
description: 'Project documentation powered by Agile Vibe Coding',
|
|
6
|
+
base: '/',
|
|
7
|
+
|
|
8
|
+
// Custom head tags for AVC documentation identification
|
|
9
|
+
head: [
|
|
10
|
+
['meta', { name: 'avc-documentation', content: 'true' }],
|
|
11
|
+
['meta', { name: 'generator', content: 'Agile Vibe Coding' }]
|
|
12
|
+
],
|
|
13
|
+
|
|
14
|
+
themeConfig: {
|
|
15
|
+
nav: [
|
|
16
|
+
{ text: 'Home', link: '/' },
|
|
17
|
+
{ text: 'Epics', link: '/epics' }
|
|
18
|
+
],
|
|
19
|
+
|
|
20
|
+
sidebar: [
|
|
21
|
+
{
|
|
22
|
+
text: 'Project',
|
|
23
|
+
items: [
|
|
24
|
+
{ text: 'Overview', link: '/' }
|
|
25
|
+
]
|
|
26
|
+
}
|
|
27
|
+
],
|
|
28
|
+
|
|
29
|
+
socialLinks: [
|
|
30
|
+
{ icon: 'github', link: 'https://github.com/yourusername/yourproject' }
|
|
31
|
+
]
|
|
32
|
+
}
|
|
33
|
+
})
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agile-vibe-coding/avc",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Agile Vibe Coding (AVC) - Framework for managing AI agent-based software development projects",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "cli/index.js",
|
|
@@ -16,7 +16,12 @@
|
|
|
16
16
|
"access": "public"
|
|
17
17
|
},
|
|
18
18
|
"scripts": {
|
|
19
|
-
"test": "
|
|
19
|
+
"test": "vitest run",
|
|
20
|
+
"test:unit": "vitest run tests/unit",
|
|
21
|
+
"test:integration": "vitest run tests/integration",
|
|
22
|
+
"test:watch": "vitest watch",
|
|
23
|
+
"test:coverage": "vitest run --coverage",
|
|
24
|
+
"test:ui": "vitest --ui",
|
|
20
25
|
"prepublishOnly": "echo \"Running pre-publish checks...\" && npm test"
|
|
21
26
|
},
|
|
22
27
|
"keywords": [
|
|
@@ -49,10 +54,19 @@
|
|
|
49
54
|
},
|
|
50
55
|
"dependencies": {
|
|
51
56
|
"@anthropic-ai/sdk": "^0.20.0",
|
|
57
|
+
"@google/genai": "^1.37.0",
|
|
52
58
|
"dotenv": "^16.4.0",
|
|
53
59
|
"ink": "^5.0.1",
|
|
54
60
|
"ink-select-input": "^6.0.0",
|
|
55
61
|
"ink-spinner": "^5.0.0",
|
|
56
62
|
"react": "^18.3.1"
|
|
63
|
+
},
|
|
64
|
+
"devDependencies": {
|
|
65
|
+
"@sinonjs/fake-timers": "^12.0.0",
|
|
66
|
+
"@vitest/coverage-v8": "^2.1.9",
|
|
67
|
+
"@vitest/ui": "^2.1.9",
|
|
68
|
+
"memfs": "^4.56.10",
|
|
69
|
+
"sinon": "^19.0.5",
|
|
70
|
+
"vitest": "^2.1.9"
|
|
57
71
|
}
|
|
58
|
-
}
|
|
72
|
+
}
|