@comfanion/workflow 4.36.14 → 4.36.16
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/package.json +1 -1
- package/src/build-info.json +1 -1
- package/src/opencode/config.yaml +39 -10
- package/src/vectorizer/index.js +98 -8
package/package.json
CHANGED
package/src/build-info.json
CHANGED
package/src/opencode/config.yaml
CHANGED
|
@@ -235,28 +235,57 @@ vectorizer:
|
|
|
235
235
|
# Debounce time in ms (wait before indexing after file change)
|
|
236
236
|
debounce_ms: 1000
|
|
237
237
|
|
|
238
|
-
# Indexes to maintain
|
|
238
|
+
# Indexes to maintain - each has pattern (what to include) and ignore (what to skip)
|
|
239
239
|
indexes:
|
|
240
|
+
# Code index - source code files
|
|
240
241
|
code:
|
|
241
242
|
enabled: true
|
|
242
|
-
|
|
243
|
+
# Glob pattern for files to index
|
|
244
|
+
pattern: "**/*.{js,ts,jsx,tsx,mjs,cjs,py,go,rs,java,kt,swift,c,cpp,h,hpp,cs,rb,php,scala,clj}"
|
|
245
|
+
# Glob patterns to ignore
|
|
246
|
+
ignore:
|
|
247
|
+
- "**/node_modules/**"
|
|
248
|
+
- "**/.git/**"
|
|
249
|
+
- "**/dist/**"
|
|
250
|
+
- "**/build/**"
|
|
251
|
+
- "**/.opencode/**"
|
|
252
|
+
- "**/docs/**"
|
|
253
|
+
- "**/vendor/**"
|
|
254
|
+
- "**/__pycache__/**"
|
|
255
|
+
- "**/*.min.js"
|
|
256
|
+
- "**/*.bundle.js"
|
|
257
|
+
|
|
258
|
+
# Documentation index - markdown, text files
|
|
243
259
|
docs:
|
|
244
260
|
enabled: true
|
|
245
|
-
|
|
261
|
+
# Only docs folder by default (change to "**/*.md" for all markdown)
|
|
262
|
+
pattern: "docs/**/*.{md,mdx,txt,rst,adoc}"
|
|
263
|
+
ignore: []
|
|
264
|
+
|
|
265
|
+
# Configuration index - yaml, json, toml
|
|
246
266
|
config:
|
|
247
|
-
enabled: false
|
|
248
|
-
|
|
267
|
+
enabled: false # Disabled by default
|
|
268
|
+
pattern: "**/*.{yaml,yml,json,toml,ini}"
|
|
269
|
+
ignore:
|
|
270
|
+
- "**/node_modules/**"
|
|
271
|
+
- "**/.git/**"
|
|
272
|
+
- "**/dist/**"
|
|
273
|
+
- "**/build/**"
|
|
274
|
+
- "**/.opencode/**"
|
|
275
|
+
- "**/docs/**"
|
|
276
|
+
- "**/vendor/**"
|
|
277
|
+
- "**/__pycache__/**"
|
|
278
|
+
- "**/*.min.js"
|
|
279
|
+
- "**/*.bundle.js"
|
|
280
|
+
- "**/package-lock.json"
|
|
281
|
+
- "**/yarn.lock"
|
|
249
282
|
|
|
250
|
-
#
|
|
283
|
+
# Global exclude patterns (applied to ALL indexes, in addition to per-index ignore)
|
|
251
284
|
exclude:
|
|
252
285
|
- node_modules
|
|
253
286
|
- .git
|
|
254
|
-
- dist
|
|
255
|
-
- build
|
|
256
287
|
- .opencode/vectors
|
|
257
288
|
- .opencode/vectorizer
|
|
258
|
-
- vendor
|
|
259
|
-
- __pycache__
|
|
260
289
|
|
|
261
290
|
# =============================================================================
|
|
262
291
|
# LSP (Language Server Protocol) - Code Intelligence
|
package/src/vectorizer/index.js
CHANGED
|
@@ -17,9 +17,9 @@ if (!DEBUG) {
|
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
|
-
*
|
|
20
|
+
* Default index presets (can be overridden by config.yaml)
|
|
21
21
|
*/
|
|
22
|
-
const
|
|
22
|
+
const DEFAULT_PRESETS = {
|
|
23
23
|
code: {
|
|
24
24
|
pattern: '**/*.{js,ts,jsx,tsx,mjs,cjs,py,go,rs,java,kt,swift,c,cpp,h,hpp,cs,rb,php,scala,clj}',
|
|
25
25
|
ignore: ['**/node_modules/**', '**/.git/**', '**/dist/**', '**/build/**', '**/.opencode/**', '**/docs/**', '**/vendor/**', '**/__pycache__/**'],
|
|
@@ -42,6 +42,82 @@ const INDEX_PRESETS = {
|
|
|
42
42
|
}
|
|
43
43
|
};
|
|
44
44
|
|
|
45
|
+
// Will be populated from config.yaml if available
|
|
46
|
+
let INDEX_PRESETS = { ...DEFAULT_PRESETS };
|
|
47
|
+
let GLOBAL_IGNORE = [];
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Load index configuration from config.yaml
|
|
51
|
+
* @param {string} projectRoot - Project root directory
|
|
52
|
+
*/
|
|
53
|
+
async function loadConfig(projectRoot) {
|
|
54
|
+
try {
|
|
55
|
+
const configPath = path.join(projectRoot, '.opencode', 'config.yaml');
|
|
56
|
+
const content = await fs.readFile(configPath, 'utf8');
|
|
57
|
+
|
|
58
|
+
// Parse vectorizer section from YAML
|
|
59
|
+
const vectorizerMatch = content.match(/^vectorizer:([\s\S]*?)(?=^[a-z]|\Z)/m);
|
|
60
|
+
if (!vectorizerMatch) return;
|
|
61
|
+
|
|
62
|
+
const section = vectorizerMatch[1];
|
|
63
|
+
|
|
64
|
+
// Parse global exclude
|
|
65
|
+
const excludeMatch = section.match(/^\s{2}exclude:\s*\n((?:\s{4}-\s+.+\n?)*)/m);
|
|
66
|
+
if (excludeMatch) {
|
|
67
|
+
GLOBAL_IGNORE = excludeMatch[1]
|
|
68
|
+
.split('\n')
|
|
69
|
+
.map(line => line.replace(/^\s*-\s*/, '').trim())
|
|
70
|
+
.filter(Boolean)
|
|
71
|
+
.map(p => p.includes('*') ? p : `**/${p}/**`);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Parse indexes section
|
|
75
|
+
const indexesMatch = section.match(/^\s{2}indexes:\s*\n([\s\S]*?)(?=^\s{2}[a-z]|\s{2}exclude:|\Z)/m);
|
|
76
|
+
if (!indexesMatch) return;
|
|
77
|
+
|
|
78
|
+
const indexesSection = indexesMatch[1];
|
|
79
|
+
|
|
80
|
+
// Parse each index (code, docs, config)
|
|
81
|
+
for (const indexName of ['code', 'docs', 'config']) {
|
|
82
|
+
const indexRegex = new RegExp(`^\\s{4}${indexName}:\\s*\\n([\\s\\S]*?)(?=^\\s{4}[a-z]|\\Z)`, 'm');
|
|
83
|
+
const indexMatch = indexesSection.match(indexRegex);
|
|
84
|
+
if (!indexMatch) continue;
|
|
85
|
+
|
|
86
|
+
const indexSection = indexMatch[1];
|
|
87
|
+
|
|
88
|
+
// Parse enabled
|
|
89
|
+
const enabledMatch = indexSection.match(/^\s+enabled:\s*(true|false)/m);
|
|
90
|
+
const enabled = enabledMatch ? enabledMatch[1] === 'true' : true;
|
|
91
|
+
|
|
92
|
+
// Parse pattern
|
|
93
|
+
const patternMatch = indexSection.match(/^\s+pattern:\s*["']?([^"'\n]+)["']?/m);
|
|
94
|
+
const pattern = patternMatch ? patternMatch[1].trim() : DEFAULT_PRESETS[indexName]?.pattern;
|
|
95
|
+
|
|
96
|
+
// Parse ignore array
|
|
97
|
+
const ignoreMatch = indexSection.match(/^\s+ignore:\s*\n((?:\s+-\s+.+\n?)*)/m);
|
|
98
|
+
let ignore = [];
|
|
99
|
+
if (ignoreMatch) {
|
|
100
|
+
ignore = ignoreMatch[1]
|
|
101
|
+
.split('\n')
|
|
102
|
+
.map(line => line.replace(/^\s*-\s*/, '').replace(/["']/g, '').trim())
|
|
103
|
+
.filter(Boolean);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (enabled && pattern) {
|
|
107
|
+
INDEX_PRESETS[indexName] = {
|
|
108
|
+
pattern,
|
|
109
|
+
ignore,
|
|
110
|
+
description: `${indexName} files from config.yaml`
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (DEBUG) console.log('[vectorizer] Loaded config:', { INDEX_PRESETS, GLOBAL_IGNORE });
|
|
116
|
+
} catch (e) {
|
|
117
|
+
if (DEBUG) console.log('[vectorizer] Using default presets (no config.yaml)');
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
45
121
|
class CodebaseIndexer {
|
|
46
122
|
/**
|
|
47
123
|
* @param {string} projectRoot - Project root directory
|
|
@@ -55,9 +131,15 @@ class CodebaseIndexer {
|
|
|
55
131
|
this.model = null;
|
|
56
132
|
this.db = null;
|
|
57
133
|
this.hashes = {};
|
|
134
|
+
this.configLoaded = false;
|
|
58
135
|
}
|
|
59
136
|
|
|
60
137
|
async init() {
|
|
138
|
+
// Load config on first init
|
|
139
|
+
if (!this.configLoaded) {
|
|
140
|
+
await loadConfig(this.root);
|
|
141
|
+
this.configLoaded = true;
|
|
142
|
+
}
|
|
61
143
|
await fs.mkdir(this.cacheDir, { recursive: true });
|
|
62
144
|
this.db = await lancedb.connect(path.join(this.cacheDir, 'lancedb'));
|
|
63
145
|
await this.loadHashes();
|
|
@@ -219,10 +301,14 @@ class CodebaseIndexer {
|
|
|
219
301
|
*/
|
|
220
302
|
async checkHealth(extraIgnore = []) {
|
|
221
303
|
const { glob } = await import('glob');
|
|
222
|
-
const preset = INDEX_PRESETS[this.indexName] ||
|
|
304
|
+
const preset = INDEX_PRESETS[this.indexName] || DEFAULT_PRESETS.code;
|
|
223
305
|
|
|
224
|
-
// Combine preset ignore
|
|
225
|
-
const ignore = [
|
|
306
|
+
// Combine: preset ignore + global ignore + extra ignore
|
|
307
|
+
const ignore = [
|
|
308
|
+
...(preset.ignore || []),
|
|
309
|
+
...GLOBAL_IGNORE,
|
|
310
|
+
...extraIgnore.map(p => p.includes('*') ? p : `**/${p}/**`)
|
|
311
|
+
];
|
|
226
312
|
|
|
227
313
|
const expectedFiles = await glob(preset.pattern, {
|
|
228
314
|
cwd: this.root,
|
|
@@ -295,10 +381,14 @@ class CodebaseIndexer {
|
|
|
295
381
|
*/
|
|
296
382
|
async indexAll(onProgress = null, extraIgnore = []) {
|
|
297
383
|
const { glob } = await import('glob');
|
|
298
|
-
const preset = INDEX_PRESETS[this.indexName] ||
|
|
384
|
+
const preset = INDEX_PRESETS[this.indexName] || DEFAULT_PRESETS.code;
|
|
299
385
|
|
|
300
|
-
// Combine preset ignore
|
|
301
|
-
const ignore = [
|
|
386
|
+
// Combine: preset ignore + global ignore + extra ignore
|
|
387
|
+
const ignore = [
|
|
388
|
+
...(preset.ignore || []),
|
|
389
|
+
...GLOBAL_IGNORE,
|
|
390
|
+
...extraIgnore.map(p => p.includes('*') ? p : `**/${p}/**`)
|
|
391
|
+
];
|
|
302
392
|
|
|
303
393
|
const files = await glob(preset.pattern, {
|
|
304
394
|
cwd: this.root,
|