@comfanion/workflow 4.39.0 ā 4.39.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/bin/cli.js +20 -110
- package/package.json +1 -1
- package/src/build-info.json +3 -4
- package/src/opencode/vectorizer.yaml +0 -45
package/bin/cli.js
CHANGED
|
@@ -54,7 +54,6 @@ program
|
|
|
54
54
|
.option('--tdd', 'Use TDD methodology')
|
|
55
55
|
.option('--stub', 'Use STUB methodology')
|
|
56
56
|
.option('--full', 'Create full repo structure')
|
|
57
|
-
.option('--vectorizer', 'Install vectorizer for semantic code search')
|
|
58
57
|
.action(async (options) => {
|
|
59
58
|
console.log(chalk.blue.bold(`\nš OpenCode Workflow v${VERSION}\n`));
|
|
60
59
|
|
|
@@ -70,9 +69,6 @@ program
|
|
|
70
69
|
jira_url: 'https://your-domain.atlassian.net',
|
|
71
70
|
jira_project: 'PROJ',
|
|
72
71
|
create_repo_structure: false,
|
|
73
|
-
vectorizer_enabled: true,
|
|
74
|
-
vectorizer_auto_index: true,
|
|
75
|
-
vectorizer_model: 'Xenova/all-MiniLM-L6-v2',
|
|
76
72
|
project_name: path.basename(process.cwd())
|
|
77
73
|
};
|
|
78
74
|
|
|
@@ -99,19 +95,6 @@ program
|
|
|
99
95
|
if (jiraUrlMatch) config.jira_url = jiraUrlMatch[1];
|
|
100
96
|
if (jiraProjMatch) config.jira_project = jiraProjMatch[1];
|
|
101
97
|
|
|
102
|
-
// Parse vectorizer settings from vectorizer.yaml if exists
|
|
103
|
-
const vecPath = path.join(targetDir, 'vectorizer.yaml');
|
|
104
|
-
if (await fs.pathExists(vecPath)) {
|
|
105
|
-
const vecContent = await fs.readFile(vecPath, 'utf8');
|
|
106
|
-
const vEnabledMatch = vecContent.match(/enabled:\s*(true|false)/);
|
|
107
|
-
const vAutoMatch = vecContent.match(/auto_index:\s*(true|false)/);
|
|
108
|
-
const vModelMatch = vecContent.match(/model:\s*["']?([^"'\n]+)["']?/);
|
|
109
|
-
|
|
110
|
-
if (vEnabledMatch) config.vectorizer_enabled = vEnabledMatch[1] === 'true';
|
|
111
|
-
if (vAutoMatch) config.vectorizer_auto_index = vAutoMatch[1] === 'true';
|
|
112
|
-
if (vModelMatch) config.vectorizer_model = vModelMatch[1].trim();
|
|
113
|
-
}
|
|
114
|
-
|
|
115
98
|
isUpdate = true;
|
|
116
99
|
} catch (e) {
|
|
117
100
|
// Could not parse, use defaults
|
|
@@ -199,40 +182,6 @@ program
|
|
|
199
182
|
message: 'Create full repository structure (README, CONTRIBUTING, .gitignore, docs/)?',
|
|
200
183
|
default: options.full || false
|
|
201
184
|
},
|
|
202
|
-
{
|
|
203
|
-
type: 'confirm',
|
|
204
|
-
name: 'vectorizer_enabled',
|
|
205
|
-
message: 'Enable semantic code search (vectorizer)?',
|
|
206
|
-
default: true
|
|
207
|
-
},
|
|
208
|
-
{
|
|
209
|
-
type: 'list',
|
|
210
|
-
name: 'vectorizer_model',
|
|
211
|
-
message: 'Embedding model for semantic search:',
|
|
212
|
-
when: (answers) => answers.vectorizer_enabled,
|
|
213
|
-
choices: [
|
|
214
|
-
{
|
|
215
|
-
name: 'MiniLM-L6 (Fast) - ~10 files/10sec, 384 dims, good quality',
|
|
216
|
-
value: 'Xenova/all-MiniLM-L6-v2'
|
|
217
|
-
},
|
|
218
|
-
{
|
|
219
|
-
name: 'BGE-small (Balanced) - ~9 files/10sec, 384 dims, better quality',
|
|
220
|
-
value: 'Xenova/bge-small-en-v1.5'
|
|
221
|
-
},
|
|
222
|
-
{
|
|
223
|
-
name: 'BGE-base (Quality) - ~3 files/10sec, 768 dims, best quality',
|
|
224
|
-
value: 'Xenova/bge-base-en-v1.5'
|
|
225
|
-
}
|
|
226
|
-
],
|
|
227
|
-
default: config.vectorizer_model
|
|
228
|
-
},
|
|
229
|
-
{
|
|
230
|
-
type: 'confirm',
|
|
231
|
-
name: 'vectorizer_auto_index',
|
|
232
|
-
message: 'Enable auto-indexing? (reindex files on save)',
|
|
233
|
-
when: (answers) => answers.vectorizer_enabled,
|
|
234
|
-
default: true
|
|
235
|
-
},
|
|
236
185
|
{
|
|
237
186
|
type: 'checkbox',
|
|
238
187
|
name: 'mcp_servers',
|
|
@@ -259,7 +208,6 @@ program
|
|
|
259
208
|
if (options.stub) config.methodology = 'stub';
|
|
260
209
|
if (options.jira) config.jira_enabled = true;
|
|
261
210
|
if (options.full) config.create_repo_structure = true;
|
|
262
|
-
if (options.vectorizer) config.install_vectorizer = true;
|
|
263
211
|
}
|
|
264
212
|
|
|
265
213
|
const spinner = ora('Initializing OpenCode Workflow...').start();
|
|
@@ -324,7 +272,6 @@ program
|
|
|
324
272
|
// Update config.yaml with user values
|
|
325
273
|
spinner.text = 'Configuring...';
|
|
326
274
|
const configPath = path.join(targetDir, 'config.yaml');
|
|
327
|
-
const vecPath = path.join(targetDir, 'vectorizer.yaml');
|
|
328
275
|
let configContent;
|
|
329
276
|
|
|
330
277
|
// If we had existing config, use it as base (preserves comments and formatting)
|
|
@@ -354,19 +301,6 @@ program
|
|
|
354
301
|
|
|
355
302
|
await fs.writeFile(configPath, configContent);
|
|
356
303
|
|
|
357
|
-
// Update vectorizer.yaml
|
|
358
|
-
if (await fs.pathExists(vecPath)) {
|
|
359
|
-
let vecContent = await fs.readFile(vecPath, 'utf8');
|
|
360
|
-
vecContent = vecContent
|
|
361
|
-
.replace(/(enabled:)\s*(true|false)/, `$1 ${config.vectorizer_enabled}`)
|
|
362
|
-
.replace(/(auto_index:)\s*(true|false)/, `$1 ${config.vectorizer_auto_index}`);
|
|
363
|
-
|
|
364
|
-
if (config.vectorizer_model) {
|
|
365
|
-
vecContent = vecContent.replace(/(model:)\s*["']?[^"'\n]+["']?/, `$1 "${config.vectorizer_model}"`);
|
|
366
|
-
}
|
|
367
|
-
await fs.writeFile(vecPath, vecContent);
|
|
368
|
-
}
|
|
369
|
-
|
|
370
304
|
// Create docs structure (always)
|
|
371
305
|
spinner.text = 'Creating docs structure...';
|
|
372
306
|
await fs.ensureDir(path.join(process.cwd(), 'docs'));
|
|
@@ -476,24 +410,10 @@ program
|
|
|
476
410
|
console.log(chalk.gray(' Run manually: cd .opencode && bun install'));
|
|
477
411
|
}
|
|
478
412
|
|
|
479
|
-
// Show what was done
|
|
480
|
-
const vectorizerInstalled = await fs.pathExists(path.join(targetDir, 'vectorizer', 'node_modules'));
|
|
481
|
-
if (vectorizerInstalled) {
|
|
482
|
-
console.log(chalk.green('ā
Vectorizer installed (fresh dependencies)'));
|
|
483
|
-
} else if (config.vectorizer_enabled) {
|
|
484
|
-
console.log(chalk.yellow('ā ļø Vectorizer: run `npx @comfanion/workflow vectorizer install`'));
|
|
485
|
-
} else {
|
|
486
|
-
console.log(chalk.gray('ā¹ļø Vectorizer disabled (enable in config.yaml to use semantic search)'));
|
|
487
|
-
}
|
|
488
413
|
if (hadVectors) {
|
|
489
414
|
console.log(chalk.green('ā
Vector indexes preserved'));
|
|
490
415
|
}
|
|
491
416
|
|
|
492
|
-
// Install vectorizer if requested and failed above
|
|
493
|
-
if (config.install_vectorizer && !vectorizerInstalled) {
|
|
494
|
-
await installVectorizer(targetDir);
|
|
495
|
-
}
|
|
496
|
-
|
|
497
417
|
// Show summary
|
|
498
418
|
console.log(chalk.yellow('\nš Created structure:'));
|
|
499
419
|
console.log(`
|
|
@@ -559,9 +479,8 @@ program
|
|
|
559
479
|
|
|
560
480
|
program
|
|
561
481
|
.command('update')
|
|
562
|
-
.description('Update .opencode/ to latest version (preserves config.yaml and
|
|
482
|
+
.description('Update .opencode/ to latest version (preserves config.yaml and vector indexes)')
|
|
563
483
|
.option('--no-backup', 'Skip creating backup')
|
|
564
|
-
.option('--vectorizer', 'Update/install vectorizer too')
|
|
565
484
|
.action(async (options) => {
|
|
566
485
|
const spinner = ora('Updating OpenCode Workflow...').start();
|
|
567
486
|
|
|
@@ -762,27 +681,25 @@ program
|
|
|
762
681
|
console.log(chalk.gray(' ā Jira credentials not set'));
|
|
763
682
|
}
|
|
764
683
|
|
|
765
|
-
// Check
|
|
766
|
-
console.log(chalk.cyan('\
|
|
767
|
-
const vectorsExist = await fs.pathExists(path.join(process.cwd(), '.opencode', 'vectors', 'code', 'hashes.json'));
|
|
768
|
-
|
|
769
|
-
// Check vectorizer config
|
|
770
|
-
let vectorizerEnabled = true;
|
|
771
|
-
let autoIndexEnabled = true;
|
|
684
|
+
// Check Semantic Search plugin
|
|
685
|
+
console.log(chalk.cyan('\nSemantic search (@comfanion/usethis_search):'));
|
|
772
686
|
try {
|
|
773
|
-
const
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
687
|
+
const opcPath = path.join(process.cwd(), 'opencode.json');
|
|
688
|
+
if (await fs.pathExists(opcPath)) {
|
|
689
|
+
const opc = JSON.parse(await fs.readFile(opcPath, 'utf8'));
|
|
690
|
+
const plugins = opc.plugin || [];
|
|
691
|
+
if (plugins.includes('@comfanion/usethis_search')) {
|
|
692
|
+
console.log(chalk.green(' ā
Plugin registered in opencode.json'));
|
|
693
|
+
} else {
|
|
694
|
+
console.log(chalk.yellow(' ā ļø Plugin not in opencode.json (add "@comfanion/usethis_search" to plugin array)'));
|
|
695
|
+
}
|
|
696
|
+
} else {
|
|
697
|
+
console.log(chalk.gray(' ā No opencode.json found'));
|
|
698
|
+
}
|
|
699
|
+
} catch {
|
|
700
|
+
console.log(chalk.gray(' ā Could not check opencode.json'));
|
|
701
|
+
}
|
|
702
|
+
const vectorsExist = await fs.pathExists(path.join(process.cwd(), '.opencode', 'vectors', 'code', 'hashes.json'));
|
|
786
703
|
if (vectorsExist) {
|
|
787
704
|
try {
|
|
788
705
|
const hashes = await fs.readJSON(path.join(process.cwd(), '.opencode', 'vectors', 'code', 'hashes.json'));
|
|
@@ -791,14 +708,7 @@ program
|
|
|
791
708
|
console.log(chalk.gray(' ā Not indexed yet'));
|
|
792
709
|
}
|
|
793
710
|
} else {
|
|
794
|
-
console.log(chalk.gray(' ā Not indexed (will index on startup)'));
|
|
795
|
-
}
|
|
796
|
-
|
|
797
|
-
// Check LSP env
|
|
798
|
-
if (process.env.OPENCODE_EXPERIMENTAL_LSP_TOOL === 'true' || process.env.OPENCODE_EXPERIMENTAL === 'true') {
|
|
799
|
-
console.log(chalk.green(' ā
LSP tool enabled'));
|
|
800
|
-
} else {
|
|
801
|
-
console.log(chalk.gray(' ā LSP tool disabled (set OPENCODE_EXPERIMENTAL_LSP_TOOL=true)'));
|
|
711
|
+
console.log(chalk.gray(' ā Not indexed (will index on first startup with plugin)'));
|
|
802
712
|
}
|
|
803
713
|
|
|
804
714
|
console.log('');
|
package/package.json
CHANGED
package/src/build-info.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "4.39.
|
|
3
|
-
"buildDate": "2026-01-
|
|
2
|
+
"version": "4.39.1",
|
|
3
|
+
"buildDate": "2026-01-29T22:52:34.568Z",
|
|
4
4
|
"files": [
|
|
5
5
|
".gitignore",
|
|
6
6
|
"config.yaml",
|
|
@@ -12,7 +12,6 @@
|
|
|
12
12
|
"commands",
|
|
13
13
|
"mcp",
|
|
14
14
|
"package.json",
|
|
15
|
-
"opencode.json"
|
|
16
|
-
"vectorizer.yaml"
|
|
15
|
+
"opencode.json"
|
|
17
16
|
]
|
|
18
17
|
}
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
vectorizer:
|
|
2
|
-
# Enable/disable vectorizer functionality
|
|
3
|
-
enabled: true
|
|
4
|
-
|
|
5
|
-
# Auto-index files when they change (requires file-indexer plugin)
|
|
6
|
-
auto_index: true
|
|
7
|
-
|
|
8
|
-
# Debounce time in ms (wait before indexing after file change)
|
|
9
|
-
debounce_ms: 1000
|
|
10
|
-
|
|
11
|
-
# Indexes to maintain - each has pattern (what to include) and ignore (what to skip)
|
|
12
|
-
indexes:
|
|
13
|
-
|
|
14
|
-
# Documentation index - markdown, text files
|
|
15
|
-
docs:
|
|
16
|
-
enabled: true
|
|
17
|
-
pattern: "docs/**/*.{md,mdx,txt,rst,adoc}"
|
|
18
|
-
ignore: []
|
|
19
|
-
|
|
20
|
-
# Configuration index - yaml, json, toml
|
|
21
|
-
config:
|
|
22
|
-
enabled: false
|
|
23
|
-
pattern: "**/*.{yaml,yml,json,toml,ini}"
|
|
24
|
-
ignore:
|
|
25
|
-
- "**/node_modules/**"
|
|
26
|
-
- "**/.git/**"
|
|
27
|
-
- "**/dist/**"
|
|
28
|
-
- "**/build/**"
|
|
29
|
-
- "**/.opencode/**"
|
|
30
|
-
- "**/docs/**"
|
|
31
|
-
- "**/vendor/**"
|
|
32
|
-
- "**/__pycache__/**"
|
|
33
|
-
- "**/*.min.js"
|
|
34
|
-
- "**/*.bundle.js"
|
|
35
|
-
- "**/package-lock.json"
|
|
36
|
-
- "**/yarn.lock"
|
|
37
|
-
|
|
38
|
-
# Global exclude patterns (applied to ALL indexes, in addition to per-index ignore)
|
|
39
|
-
exclude:
|
|
40
|
-
- node_modules
|
|
41
|
-
- vendor
|
|
42
|
-
- dist
|
|
43
|
-
- build
|
|
44
|
-
- out
|
|
45
|
-
- __pycache__
|