@comfanion/workflow 4.3.0 ā 4.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/cli.js +341 -1
- package/package.json +8 -3
- package/src/build-info.json +2 -1
- package/src/opencode/FLOW.yaml +147 -92
- package/src/opencode/agents/analyst.md +24 -20
- package/src/opencode/agents/architect.md +104 -39
- package/src/opencode/agents/change-manager.md +112 -250
- package/src/opencode/agents/coder.md +36 -19
- package/src/opencode/agents/crawler.md +180 -97
- package/src/opencode/agents/dev.md +117 -29
- package/src/opencode/agents/pm.md +25 -32
- package/src/opencode/agents/researcher.md +116 -241
- package/src/opencode/commands/dev-story.md +1 -5
- package/src/opencode/commands/unit-docs.md +170 -0
- package/src/opencode/config.yaml +29 -0
- package/src/opencode/opencode.json +5 -0
- package/src/opencode/{workflows/dev-story/instructions.md ā skills/dev-story/SKILL.md} +2 -2
- package/src/opencode/tools/codeindex.ts +255 -0
- package/src/opencode/tools/codesearch.ts +134 -0
package/bin/cli.js
CHANGED
|
@@ -7,11 +7,63 @@ import ora from 'ora';
|
|
|
7
7
|
import fs from 'fs-extra';
|
|
8
8
|
import path from 'path';
|
|
9
9
|
import { fileURLToPath } from 'url';
|
|
10
|
+
import { execSync } from 'child_process';
|
|
10
11
|
|
|
11
12
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
12
13
|
const PACKAGE_DIR = path.join(__dirname, '..');
|
|
13
14
|
const OPENCODE_SRC = path.join(PACKAGE_DIR, 'src', 'opencode');
|
|
14
15
|
const REPO_TEMPLATES_SRC = path.join(PACKAGE_DIR, 'src', 'repo-structure');
|
|
16
|
+
const VECTORIZER_SRC = path.join(PACKAGE_DIR, 'src', 'vectorizer');
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Install vectorizer module with dependencies
|
|
20
|
+
*/
|
|
21
|
+
async function installVectorizer(opencodeDir) {
|
|
22
|
+
console.log('');
|
|
23
|
+
const spinner = ora('Installing vectorizer & caching...').start();
|
|
24
|
+
|
|
25
|
+
try {
|
|
26
|
+
const vectorizerDir = path.join(opencodeDir, 'vectorizer');
|
|
27
|
+
|
|
28
|
+
// Copy vectorizer source files
|
|
29
|
+
spinner.text = 'Copying vectorizer files...';
|
|
30
|
+
await fs.ensureDir(vectorizerDir);
|
|
31
|
+
await fs.copy(VECTORIZER_SRC, vectorizerDir);
|
|
32
|
+
|
|
33
|
+
// Run npm install
|
|
34
|
+
spinner.text = 'Installing dependencies (~100MB, may take a minute)...';
|
|
35
|
+
execSync('npm install --no-audit --no-fund', {
|
|
36
|
+
cwd: vectorizerDir,
|
|
37
|
+
stdio: 'pipe',
|
|
38
|
+
timeout: 300000 // 5 min timeout
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
// Add to .gitignore
|
|
42
|
+
const gitignorePath = path.join(opencodeDir, '.gitignore');
|
|
43
|
+
let gitignore = '';
|
|
44
|
+
try { gitignore = await fs.readFile(gitignorePath, 'utf8'); } catch {}
|
|
45
|
+
if (!gitignore.includes('vectors/')) {
|
|
46
|
+
gitignore += '\n# Vectorizer cache\nvectors/\nvectorizer/node_modules/\n';
|
|
47
|
+
await fs.writeFile(gitignorePath, gitignore);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
spinner.succeed(chalk.green('Vectorizer installed!'));
|
|
51
|
+
|
|
52
|
+
console.log(chalk.cyan('\nš Vectorizer ready:'));
|
|
53
|
+
console.log(`
|
|
54
|
+
Index codebase: ${chalk.cyan('npx opencode-workflow index')}
|
|
55
|
+
Search code: ${chalk.cyan('npx opencode-workflow search "your query"')}
|
|
56
|
+
`);
|
|
57
|
+
|
|
58
|
+
return true;
|
|
59
|
+
|
|
60
|
+
} catch (error) {
|
|
61
|
+
spinner.fail(chalk.yellow('Vectorizer installation failed (optional)'));
|
|
62
|
+
console.log(chalk.gray(` Error: ${error.message}`));
|
|
63
|
+
console.log(chalk.gray(' You can install later with: npx opencode-workflow vectorizer install'));
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
15
67
|
|
|
16
68
|
const program = new Command();
|
|
17
69
|
|
|
@@ -28,6 +80,7 @@ program
|
|
|
28
80
|
.option('--tdd', 'Use TDD methodology')
|
|
29
81
|
.option('--stub', 'Use STUB methodology')
|
|
30
82
|
.option('--full', 'Create full repo structure')
|
|
83
|
+
.option('--vectorizer', 'Install vectorizer for semantic code search')
|
|
31
84
|
.action(async (options) => {
|
|
32
85
|
console.log(chalk.blue.bold('\nš OpenCode Workflow v3.7\n'));
|
|
33
86
|
|
|
@@ -43,6 +96,7 @@ program
|
|
|
43
96
|
jira_url: 'https://your-domain.atlassian.net',
|
|
44
97
|
jira_project: 'PROJ',
|
|
45
98
|
create_repo_structure: false,
|
|
99
|
+
install_vectorizer: false,
|
|
46
100
|
project_name: path.basename(process.cwd())
|
|
47
101
|
};
|
|
48
102
|
|
|
@@ -155,6 +209,12 @@ program
|
|
|
155
209
|
name: 'create_repo_structure',
|
|
156
210
|
message: 'Create full repository structure (README, CONTRIBUTING, .gitignore, docs/)?',
|
|
157
211
|
default: options.full || false
|
|
212
|
+
},
|
|
213
|
+
{
|
|
214
|
+
type: 'confirm',
|
|
215
|
+
name: 'install_vectorizer',
|
|
216
|
+
message: 'Install vectorizer & caching? (semantic code search, ~100MB)',
|
|
217
|
+
default: false
|
|
158
218
|
}
|
|
159
219
|
]);
|
|
160
220
|
|
|
@@ -165,6 +225,7 @@ program
|
|
|
165
225
|
if (options.stub) config.methodology = 'stub';
|
|
166
226
|
if (options.jira) config.jira_enabled = true;
|
|
167
227
|
if (options.full) config.create_repo_structure = true;
|
|
228
|
+
if (options.vectorizer) config.install_vectorizer = true;
|
|
168
229
|
}
|
|
169
230
|
|
|
170
231
|
const spinner = ora('Initializing OpenCode Workflow...').start();
|
|
@@ -267,6 +328,11 @@ program
|
|
|
267
328
|
|
|
268
329
|
spinner.succeed(chalk.green('OpenCode Workflow initialized!'));
|
|
269
330
|
|
|
331
|
+
// Install vectorizer if requested
|
|
332
|
+
if (config.install_vectorizer) {
|
|
333
|
+
await installVectorizer(targetDir);
|
|
334
|
+
}
|
|
335
|
+
|
|
270
336
|
// Show summary
|
|
271
337
|
console.log(chalk.yellow('\nš Created structure:'));
|
|
272
338
|
console.log(`
|
|
@@ -461,10 +527,38 @@ program
|
|
|
461
527
|
console.log(chalk.gray(' ā Jira credentials not set'));
|
|
462
528
|
}
|
|
463
529
|
|
|
530
|
+
// Check Vectorizer
|
|
531
|
+
console.log(chalk.cyan('\nVectorizer (semantic search):'));
|
|
532
|
+
const vectorizerInstalled = await fs.pathExists(path.join(process.cwd(), '.opencode', 'vectorizer', 'node_modules'));
|
|
533
|
+
const vectorsExist = await fs.pathExists(path.join(process.cwd(), '.opencode', 'vectors', 'hashes.json'));
|
|
534
|
+
|
|
535
|
+
if (vectorizerInstalled) {
|
|
536
|
+
console.log(chalk.green(' ā
Installed'));
|
|
537
|
+
if (vectorsExist) {
|
|
538
|
+
try {
|
|
539
|
+
const hashes = await fs.readJSON(path.join(process.cwd(), '.opencode', 'vectors', 'hashes.json'));
|
|
540
|
+
console.log(chalk.green(` ā
Indexed (${Object.keys(hashes).length} files)`));
|
|
541
|
+
} catch {
|
|
542
|
+
console.log(chalk.gray(' ā Not indexed yet'));
|
|
543
|
+
}
|
|
544
|
+
} else {
|
|
545
|
+
console.log(chalk.gray(' ā Not indexed (run: npx opencode-workflow index)'));
|
|
546
|
+
}
|
|
547
|
+
} else {
|
|
548
|
+
console.log(chalk.gray(' ā Not installed (run: npx opencode-workflow vectorizer install)'));
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
// Check LSP env
|
|
552
|
+
if (process.env.OPENCODE_EXPERIMENTAL_LSP_TOOL === 'true' || process.env.OPENCODE_EXPERIMENTAL === 'true') {
|
|
553
|
+
console.log(chalk.green(' ā
LSP tool enabled'));
|
|
554
|
+
} else {
|
|
555
|
+
console.log(chalk.gray(' ā LSP tool disabled (set OPENCODE_EXPERIMENTAL_LSP_TOOL=true)'));
|
|
556
|
+
}
|
|
557
|
+
|
|
464
558
|
console.log('');
|
|
465
559
|
|
|
466
560
|
if (hasErrors) {
|
|
467
|
-
console.log(chalk.yellow('š” Run `npx
|
|
561
|
+
console.log(chalk.yellow('š” Run `npx opencode-workflow init` to fix missing files.\n'));
|
|
468
562
|
} else {
|
|
469
563
|
console.log(chalk.green.bold('ā
All checks passed!\n'));
|
|
470
564
|
}
|
|
@@ -484,4 +578,250 @@ program
|
|
|
484
578
|
}
|
|
485
579
|
});
|
|
486
580
|
|
|
581
|
+
// =============================================================================
|
|
582
|
+
// VECTORIZER COMMANDS
|
|
583
|
+
// =============================================================================
|
|
584
|
+
|
|
585
|
+
program
|
|
586
|
+
.command('vectorizer')
|
|
587
|
+
.description('Manage vectorizer for semantic code search')
|
|
588
|
+
.argument('<action>', 'install | status | uninstall')
|
|
589
|
+
.action(async (action) => {
|
|
590
|
+
const opencodeDir = path.join(process.cwd(), '.opencode');
|
|
591
|
+
const vectorizerDir = path.join(opencodeDir, 'vectorizer');
|
|
592
|
+
|
|
593
|
+
if (action === 'install') {
|
|
594
|
+
if (!await fs.pathExists(opencodeDir)) {
|
|
595
|
+
console.log(chalk.red('\nā .opencode/ not found. Run `init` first.\n'));
|
|
596
|
+
process.exit(1);
|
|
597
|
+
}
|
|
598
|
+
await installVectorizer(opencodeDir);
|
|
599
|
+
|
|
600
|
+
} else if (action === 'status') {
|
|
601
|
+
const installed = await fs.pathExists(path.join(vectorizerDir, 'node_modules'));
|
|
602
|
+
const indexed = await fs.pathExists(path.join(process.cwd(), '.opencode', 'vectors', 'lancedb'));
|
|
603
|
+
|
|
604
|
+
console.log(chalk.blue.bold('\nš Vectorizer Status\n'));
|
|
605
|
+
console.log(installed
|
|
606
|
+
? chalk.green(' ā
Installed')
|
|
607
|
+
: chalk.gray(' ā Not installed (run: npx opencode-workflow vectorizer install)'));
|
|
608
|
+
console.log(indexed
|
|
609
|
+
? chalk.green(' ā
Codebase indexed')
|
|
610
|
+
: chalk.gray(' ā Not indexed (run: npx opencode-workflow index)'));
|
|
611
|
+
|
|
612
|
+
if (indexed) {
|
|
613
|
+
try {
|
|
614
|
+
const hashes = await fs.readJSON(path.join(process.cwd(), '.opencode', 'vectors', 'hashes.json'));
|
|
615
|
+
console.log(chalk.cyan(` š ${Object.keys(hashes).length} files indexed`));
|
|
616
|
+
} catch {}
|
|
617
|
+
}
|
|
618
|
+
console.log('');
|
|
619
|
+
|
|
620
|
+
} else if (action === 'uninstall') {
|
|
621
|
+
const spinner = ora('Removing vectorizer...').start();
|
|
622
|
+
await fs.remove(vectorizerDir);
|
|
623
|
+
await fs.remove(path.join(process.cwd(), '.opencode', 'vectors'));
|
|
624
|
+
spinner.succeed(chalk.green('Vectorizer removed'));
|
|
625
|
+
|
|
626
|
+
} else {
|
|
627
|
+
console.log(chalk.red(`Unknown action: ${action}`));
|
|
628
|
+
console.log('Available: install, status, uninstall');
|
|
629
|
+
}
|
|
630
|
+
});
|
|
631
|
+
|
|
632
|
+
program
|
|
633
|
+
.command('index')
|
|
634
|
+
.description('Index codebase for semantic search')
|
|
635
|
+
.option('-i, --index <name>', 'Index name: code, docs, config, all, or custom', 'code')
|
|
636
|
+
.option('-p, --pattern <glob>', 'File pattern (overrides preset)')
|
|
637
|
+
.option('--force', 'Re-index all files (ignore cache)')
|
|
638
|
+
.option('--list', 'List all indexes and their stats')
|
|
639
|
+
.action(async (options) => {
|
|
640
|
+
const vectorizerDir = path.join(process.cwd(), '.opencode', 'vectorizer');
|
|
641
|
+
|
|
642
|
+
if (!await fs.pathExists(path.join(vectorizerDir, 'node_modules'))) {
|
|
643
|
+
console.log(chalk.red('\nā Vectorizer not installed.'));
|
|
644
|
+
console.log(chalk.yellow('Run: npx opencode-workflow vectorizer install\n'));
|
|
645
|
+
process.exit(1);
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
const spinner = ora('Initializing indexer...').start();
|
|
649
|
+
|
|
650
|
+
try {
|
|
651
|
+
// Dynamic import of the vectorizer (need file:// URL for ESM)
|
|
652
|
+
const vectorizerPath = path.join(vectorizerDir, 'index.js');
|
|
653
|
+
const { CodebaseIndexer, INDEX_PRESETS } = await import(`file://${vectorizerPath}`);
|
|
654
|
+
|
|
655
|
+
// List all indexes
|
|
656
|
+
if (options.list) {
|
|
657
|
+
spinner.stop();
|
|
658
|
+
const indexer = await new CodebaseIndexer(process.cwd(), 'code').init();
|
|
659
|
+
const allStats = await indexer.getAllStats();
|
|
660
|
+
|
|
661
|
+
console.log(chalk.blue.bold('\nš Index Statistics\n'));
|
|
662
|
+
|
|
663
|
+
if (allStats.length === 0) {
|
|
664
|
+
console.log(chalk.gray(' No indexes found. Create one with:'));
|
|
665
|
+
console.log(chalk.cyan(' npx opencode-workflow index --index code'));
|
|
666
|
+
console.log(chalk.cyan(' npx opencode-workflow index --index docs\n'));
|
|
667
|
+
} else {
|
|
668
|
+
for (const stat of allStats) {
|
|
669
|
+
console.log(chalk.cyan(` š ${stat.indexName}`));
|
|
670
|
+
console.log(chalk.gray(` ${stat.description}`));
|
|
671
|
+
console.log(` Files: ${stat.fileCount}, Chunks: ${stat.chunkCount}\n`);
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
console.log(chalk.yellow('Available presets:'));
|
|
676
|
+
for (const [name, preset] of Object.entries(INDEX_PRESETS)) {
|
|
677
|
+
console.log(` ${chalk.cyan(name)}: ${preset.description}`);
|
|
678
|
+
console.log(chalk.gray(` Pattern: ${preset.pattern}\n`));
|
|
679
|
+
}
|
|
680
|
+
return;
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
const indexName = options.index;
|
|
684
|
+
const indexer = await new CodebaseIndexer(process.cwd(), indexName).init();
|
|
685
|
+
|
|
686
|
+
// Get pattern from options or preset
|
|
687
|
+
const preset = INDEX_PRESETS[indexName];
|
|
688
|
+
const pattern = options.pattern || preset?.pattern || '**/*.{js,ts,jsx,tsx,py,go,rs,java,md,yaml,yml}';
|
|
689
|
+
|
|
690
|
+
spinner.text = `Initializing index: ${indexName}...`;
|
|
691
|
+
|
|
692
|
+
if (options.force) {
|
|
693
|
+
spinner.text = `Clearing index: ${indexName}...`;
|
|
694
|
+
await indexer.clear();
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
// Find files to index
|
|
698
|
+
spinner.text = 'Finding files...';
|
|
699
|
+
const { glob } = await import('glob');
|
|
700
|
+
const { default: ignore } = await import('ignore');
|
|
701
|
+
|
|
702
|
+
// Load .gitignore
|
|
703
|
+
let ig = ignore();
|
|
704
|
+
try {
|
|
705
|
+
const gitignore = await fs.readFile(path.join(process.cwd(), '.gitignore'), 'utf8');
|
|
706
|
+
ig = ig.add(gitignore);
|
|
707
|
+
} catch {}
|
|
708
|
+
ig.add(['node_modules', '.git', 'dist', 'build', '.opencode/vectors', '.opencode/vectorizer']);
|
|
709
|
+
|
|
710
|
+
const files = await glob(pattern, { cwd: process.cwd(), nodir: true });
|
|
711
|
+
const filtered = files.filter(f => !ig.ignores(f));
|
|
712
|
+
|
|
713
|
+
spinner.succeed(`Found ${filtered.length} files for index "${indexName}"`);
|
|
714
|
+
|
|
715
|
+
let indexed = 0;
|
|
716
|
+
let skipped = 0;
|
|
717
|
+
|
|
718
|
+
for (const file of filtered) {
|
|
719
|
+
const filePath = path.join(process.cwd(), file);
|
|
720
|
+
spinner.start(`[${indexName}] Indexing: ${file}`);
|
|
721
|
+
|
|
722
|
+
try {
|
|
723
|
+
const wasIndexed = await indexer.indexFile(filePath);
|
|
724
|
+
if (wasIndexed) {
|
|
725
|
+
indexed++;
|
|
726
|
+
} else {
|
|
727
|
+
skipped++;
|
|
728
|
+
}
|
|
729
|
+
} catch (e) {
|
|
730
|
+
spinner.warn(`Skipped ${file}: ${e.message}`);
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
spinner.succeed(chalk.green(`Index "${indexName}": ${indexed} indexed, ${skipped} unchanged`));
|
|
735
|
+
|
|
736
|
+
} catch (error) {
|
|
737
|
+
spinner.fail(chalk.red('Indexing failed'));
|
|
738
|
+
console.error(error);
|
|
739
|
+
}
|
|
740
|
+
});
|
|
741
|
+
|
|
742
|
+
program
|
|
743
|
+
.command('search')
|
|
744
|
+
.description('Semantic search in codebase')
|
|
745
|
+
.argument('<query>', 'Search query')
|
|
746
|
+
.option('-i, --index <name>', 'Index to search: code, docs, config, or custom', 'code')
|
|
747
|
+
.option('-n, --limit <number>', 'Number of results', '5')
|
|
748
|
+
.option('-a, --all', 'Search all indexes')
|
|
749
|
+
.action(async (query, options) => {
|
|
750
|
+
const vectorizerDir = path.join(process.cwd(), '.opencode', 'vectorizer');
|
|
751
|
+
|
|
752
|
+
if (!await fs.pathExists(path.join(vectorizerDir, 'node_modules'))) {
|
|
753
|
+
console.log(chalk.red('\nā Vectorizer not installed.'));
|
|
754
|
+
console.log(chalk.yellow('Run: npx opencode-workflow vectorizer install\n'));
|
|
755
|
+
process.exit(1);
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
const spinner = ora('Searching...').start();
|
|
759
|
+
|
|
760
|
+
try {
|
|
761
|
+
// Dynamic import of the vectorizer (need file:// URL for ESM)
|
|
762
|
+
const vectorizerPath = path.join(vectorizerDir, 'index.js');
|
|
763
|
+
const { CodebaseIndexer } = await import(`file://${vectorizerPath}`);
|
|
764
|
+
|
|
765
|
+
let allResults = [];
|
|
766
|
+
const limit = parseInt(options.limit);
|
|
767
|
+
|
|
768
|
+
if (options.all) {
|
|
769
|
+
// Search all indexes
|
|
770
|
+
const tempIndexer = await new CodebaseIndexer(process.cwd(), 'code').init();
|
|
771
|
+
const indexes = await tempIndexer.listIndexes();
|
|
772
|
+
|
|
773
|
+
if (indexes.length === 0) {
|
|
774
|
+
spinner.stop();
|
|
775
|
+
console.log(chalk.yellow('\nNo indexes found. Run `npx opencode-workflow index` first.\n'));
|
|
776
|
+
return;
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
for (const indexName of indexes) {
|
|
780
|
+
spinner.text = `Searching index: ${indexName}...`;
|
|
781
|
+
const indexer = await new CodebaseIndexer(process.cwd(), indexName).init();
|
|
782
|
+
const results = await indexer.search(query, limit);
|
|
783
|
+
allResults.push(...results.map(r => ({ ...r, _index: indexName })));
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
// Sort by distance and take top N
|
|
787
|
+
allResults.sort((a, b) => (a._distance || 0) - (b._distance || 0));
|
|
788
|
+
allResults = allResults.slice(0, limit);
|
|
789
|
+
|
|
790
|
+
} else {
|
|
791
|
+
// Search specific index
|
|
792
|
+
const indexer = await new CodebaseIndexer(process.cwd(), options.index).init();
|
|
793
|
+
const results = await indexer.search(query, limit);
|
|
794
|
+
allResults = results.map(r => ({ ...r, _index: options.index }));
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
spinner.stop();
|
|
798
|
+
|
|
799
|
+
if (allResults.length === 0) {
|
|
800
|
+
const indexInfo = options.all ? 'any index' : `index "${options.index}"`;
|
|
801
|
+
console.log(chalk.yellow(`\nNo results found in ${indexInfo}.`));
|
|
802
|
+
console.log(chalk.gray('Try: npx opencode-workflow index --index code\n'));
|
|
803
|
+
return;
|
|
804
|
+
}
|
|
805
|
+
|
|
806
|
+
const searchScope = options.all ? 'all indexes' : `index "${options.index}"`;
|
|
807
|
+
console.log(chalk.blue.bold(`\nš Results for: "${query}" (${searchScope})\n`));
|
|
808
|
+
|
|
809
|
+
for (let i = 0; i < allResults.length; i++) {
|
|
810
|
+
const r = allResults[i];
|
|
811
|
+
const score = r._distance ? (1 - r._distance).toFixed(3) : 'N/A';
|
|
812
|
+
const indexLabel = options.all ? chalk.magenta(`[${r._index}] `) : '';
|
|
813
|
+
console.log(chalk.cyan(`${i + 1}. ${indexLabel}${r.file}`) + chalk.gray(` (score: ${score})`));
|
|
814
|
+
console.log(chalk.gray('ā'.repeat(60)));
|
|
815
|
+
// Show first 5 lines of content
|
|
816
|
+
const preview = r.content.split('\n').slice(0, 5).join('\n');
|
|
817
|
+
console.log(preview);
|
|
818
|
+
console.log('');
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
} catch (error) {
|
|
822
|
+
spinner.fail(chalk.red('Search failed'));
|
|
823
|
+
console.error(error);
|
|
824
|
+
}
|
|
825
|
+
});
|
|
826
|
+
|
|
487
827
|
program.parse();
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@comfanion/workflow",
|
|
3
|
-
"version": "4.
|
|
4
|
-
"description": "Initialize OpenCode Workflow system for AI-assisted development",
|
|
3
|
+
"version": "4.5.0",
|
|
4
|
+
"description": "Initialize OpenCode Workflow system for AI-assisted development with semantic code search",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"comfanion-workflow": "./bin/cli.js",
|
|
@@ -25,7 +25,10 @@
|
|
|
25
25
|
"prd",
|
|
26
26
|
"architecture",
|
|
27
27
|
"tdd",
|
|
28
|
-
"agile"
|
|
28
|
+
"agile",
|
|
29
|
+
"rag",
|
|
30
|
+
"vector-search",
|
|
31
|
+
"embeddings"
|
|
29
32
|
],
|
|
30
33
|
"author": "OpenCode Team",
|
|
31
34
|
"license": "MIT",
|
|
@@ -44,6 +47,8 @@
|
|
|
44
47
|
"chalk": "^5.3.0",
|
|
45
48
|
"commander": "^11.0.0",
|
|
46
49
|
"fs-extra": "^11.1.0",
|
|
50
|
+
"glob": "^10.5.0",
|
|
51
|
+
"ignore": "^5.3.0",
|
|
47
52
|
"inquirer": "^9.2.0",
|
|
48
53
|
"ora": "^7.0.0"
|
|
49
54
|
}
|
package/src/build-info.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": "3.0.0",
|
|
3
|
-
"buildDate": "2026-01-
|
|
3
|
+
"buildDate": "2026-01-24T09:15:13.601Z",
|
|
4
4
|
"files": [
|
|
5
5
|
"config.yaml",
|
|
6
6
|
"FLOW.yaml",
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
"workflows",
|
|
12
12
|
"checklists",
|
|
13
13
|
"commands",
|
|
14
|
+
"tools",
|
|
14
15
|
"opencode.json"
|
|
15
16
|
]
|
|
16
17
|
}
|