bluera-knowledge 0.11.9 → 0.11.11
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/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +32 -0
- package/dist/{chunk-AHS2EILR.js → chunk-5NUI6JL6.js} +2 -2
- package/dist/{chunk-TTV7P7HG.js → chunk-ZDEO4WJT.js} +2 -2
- package/dist/{chunk-UB3L33JF.js → chunk-ZZNABJMQ.js} +6 -19
- package/dist/chunk-ZZNABJMQ.js.map +1 -0
- package/dist/index.js +129 -113
- package/dist/index.js.map +1 -1
- package/dist/mcp/server.js +2 -2
- package/dist/workers/background-worker-cli.js +2 -2
- package/package.json +1 -1
- package/scripts/validate-npm-release.sh +24 -3
- package/src/plugin/commands.test.ts +2 -1
- package/src/plugin/commands.ts +194 -164
- package/src/scripts/validate-npm-release.test.ts +15 -0
- package/src/services/search.service.test.ts +12 -43
- package/src/services/search.service.ts +5 -18
- package/dist/chunk-UB3L33JF.js.map +0 -1
- /package/dist/{chunk-AHS2EILR.js.map → chunk-5NUI6JL6.js.map} +0 -0
- /package/dist/{chunk-TTV7P7HG.js.map → chunk-ZDEO4WJT.js.map} +0 -0
package/dist/mcp/server.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
IntelligentCrawler
|
|
4
|
-
} from "../chunk-
|
|
4
|
+
} from "../chunk-ZDEO4WJT.js";
|
|
5
5
|
import {
|
|
6
6
|
JobService,
|
|
7
7
|
createDocumentId,
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
createServices,
|
|
10
10
|
createStoreId,
|
|
11
11
|
shutdownLogger
|
|
12
|
-
} from "../chunk-
|
|
12
|
+
} from "../chunk-ZZNABJMQ.js";
|
|
13
13
|
import "../chunk-6FHWC36B.js";
|
|
14
14
|
|
|
15
15
|
// src/workers/background-worker.ts
|
package/package.json
CHANGED
|
@@ -130,6 +130,10 @@ log "Test store: $TEST_STORE"
|
|
|
130
130
|
log "Test folder: $TEST_FOLDER"
|
|
131
131
|
log "Data directory: $DATA_DIR"
|
|
132
132
|
|
|
133
|
+
# Get expected version from package.json
|
|
134
|
+
EXPECTED_VERSION=$(node -p "require('$REPO_ROOT/package.json').version")
|
|
135
|
+
log "Expected version: $EXPECTED_VERSION"
|
|
136
|
+
|
|
133
137
|
# Install latest from npm
|
|
134
138
|
log_header "Installing Latest from npm"
|
|
135
139
|
log "Installing bluera-knowledge@latest globally..."
|
|
@@ -144,7 +148,24 @@ fi
|
|
|
144
148
|
# Verify installation
|
|
145
149
|
log_header "Verifying Installation"
|
|
146
150
|
|
|
147
|
-
|
|
151
|
+
# Capture and display the installed version
|
|
152
|
+
INSTALLED_VERSION=$(bluera-knowledge --version 2>&1 | head -1)
|
|
153
|
+
log "Installed version: $INSTALLED_VERSION"
|
|
154
|
+
VERSION_TEXT="Installed: bluera-knowledge@$INSTALLED_VERSION"
|
|
155
|
+
VERSION_LEN=${#VERSION_TEXT}
|
|
156
|
+
PADDING=$((VERSION_LEN + 4))
|
|
157
|
+
echo ""
|
|
158
|
+
printf " ╔"; printf '═%.0s' $(seq 1 $PADDING); printf "╗\n"
|
|
159
|
+
printf " ║ %s ║\n" "$VERSION_TEXT"
|
|
160
|
+
printf " ╚"; printf '═%.0s' $(seq 1 $PADDING); printf "╝\n"
|
|
161
|
+
echo ""
|
|
162
|
+
|
|
163
|
+
if [ "$INSTALLED_VERSION" != "$EXPECTED_VERSION" ]; then
|
|
164
|
+
log "WARNING: Version mismatch! Expected $EXPECTED_VERSION but got $INSTALLED_VERSION"
|
|
165
|
+
log "This may indicate npm cache issues. Try: npm cache clean --force"
|
|
166
|
+
fi
|
|
167
|
+
|
|
168
|
+
run_test_contains "bluera-knowledge --version" "$INSTALLED_VERSION" "bluera-knowledge --version"
|
|
148
169
|
|
|
149
170
|
run_test_contains "bluera-knowledge --help" "CLI tool for managing knowledge stores" "bluera-knowledge --help"
|
|
150
171
|
|
|
@@ -169,7 +190,7 @@ run_test_contains "bluera-knowledge store info" "$TEST_STORE" "bluera-knowledge
|
|
|
169
190
|
# Test search (may return no results, but should not error)
|
|
170
191
|
log_header "Testing search"
|
|
171
192
|
|
|
172
|
-
run_test "bluera-knowledge search" "bluera-knowledge search 'test content' --
|
|
193
|
+
run_test "bluera-knowledge search" "bluera-knowledge search 'test content' --stores '$TEST_STORE' -d '$DATA_DIR' -f json"
|
|
173
194
|
|
|
174
195
|
# Test index command (re-index)
|
|
175
196
|
log_header "Testing index"
|
|
@@ -177,7 +198,7 @@ log_header "Testing index"
|
|
|
177
198
|
run_test "bluera-knowledge index" "bluera-knowledge index '$TEST_STORE' -d '$DATA_DIR'"
|
|
178
199
|
|
|
179
200
|
# Test search again after re-indexing
|
|
180
|
-
run_test "bluera-knowledge search (after reindex)" "bluera-knowledge search 'validation' --
|
|
201
|
+
run_test "bluera-knowledge search (after reindex)" "bluera-knowledge search 'validation' --stores '$TEST_STORE' -d '$DATA_DIR' -f json"
|
|
181
202
|
|
|
182
203
|
# Test store delete
|
|
183
204
|
log_header "Testing store delete"
|
|
@@ -9,9 +9,10 @@ import {
|
|
|
9
9
|
} from './commands.js';
|
|
10
10
|
import type { ServiceContainer } from '../services/index.js';
|
|
11
11
|
|
|
12
|
-
// Mock the createServices
|
|
12
|
+
// Mock the createServices and destroyServices functions
|
|
13
13
|
vi.mock('../services/index.js', () => ({
|
|
14
14
|
createServices: vi.fn(),
|
|
15
|
+
destroyServices: vi.fn().mockResolvedValue(undefined),
|
|
15
16
|
}));
|
|
16
17
|
|
|
17
18
|
// Mock extractRepoName
|
package/src/plugin/commands.ts
CHANGED
|
@@ -2,7 +2,7 @@ import ora from 'ora';
|
|
|
2
2
|
import { extractRepoName } from './git-clone.js';
|
|
3
3
|
import { DependencyUsageAnalyzer } from '../analysis/dependency-usage-analyzer.js';
|
|
4
4
|
import { RepoUrlResolver } from '../analysis/repo-url-resolver.js';
|
|
5
|
-
import { createServices } from '../services/index.js';
|
|
5
|
+
import { createServices, destroyServices } from '../services/index.js';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Options passed from CLI global options to plugin command handlers.
|
|
@@ -22,37 +22,42 @@ export async function handleSearch(args: {
|
|
|
22
22
|
}): Promise<void> {
|
|
23
23
|
// PWD is set by Claude Code to user's project directory
|
|
24
24
|
const services = await createServices(undefined, undefined, process.env['PWD']);
|
|
25
|
-
const storeNames = args.stores?.split(',').map((s: string) => s.trim());
|
|
26
25
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
storeNames !== undefined ? allStores.filter((s) => storeNames.includes(s.name)) : allStores;
|
|
26
|
+
try {
|
|
27
|
+
const storeNames = args.stores?.split(',').map((s: string) => s.trim());
|
|
30
28
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
}
|
|
29
|
+
const allStores = await services.store.list();
|
|
30
|
+
const targetStores =
|
|
31
|
+
storeNames !== undefined ? allStores.filter((s) => storeNames.includes(s.name)) : allStores;
|
|
35
32
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
33
|
+
if (targetStores.length === 0) {
|
|
34
|
+
console.error('No stores found to search');
|
|
35
|
+
process.exit(1);
|
|
36
|
+
}
|
|
40
37
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
mode: 'hybrid',
|
|
45
|
-
limit: parseInt(args.limit ?? '10', 10),
|
|
46
|
-
detail: 'contextual',
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
console.log(`Found ${String(results.totalResults)} results:\n`);
|
|
50
|
-
for (const r of results.results) {
|
|
51
|
-
if (r.summary !== undefined) {
|
|
52
|
-
console.log(`Score: ${r.score.toFixed(2)} - ${r.summary.location}`);
|
|
53
|
-
console.log(r.summary.purpose);
|
|
38
|
+
// Initialize stores
|
|
39
|
+
for (const store of targetStores) {
|
|
40
|
+
await services.lance.initialize(store.id);
|
|
54
41
|
}
|
|
55
|
-
|
|
42
|
+
|
|
43
|
+
const results = await services.search.search({
|
|
44
|
+
query: args.query,
|
|
45
|
+
stores: targetStores.map((s) => s.id),
|
|
46
|
+
mode: 'hybrid',
|
|
47
|
+
limit: parseInt(args.limit ?? '10', 10),
|
|
48
|
+
detail: 'contextual',
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
console.log(`Found ${String(results.totalResults)} results:\n`);
|
|
52
|
+
for (const r of results.results) {
|
|
53
|
+
if (r.summary !== undefined) {
|
|
54
|
+
console.log(`Score: ${r.score.toFixed(2)} - ${r.summary.location}`);
|
|
55
|
+
console.log(r.summary.purpose);
|
|
56
|
+
}
|
|
57
|
+
console.log('---');
|
|
58
|
+
}
|
|
59
|
+
} finally {
|
|
60
|
+
await destroyServices(services);
|
|
56
61
|
}
|
|
57
62
|
}
|
|
58
63
|
|
|
@@ -69,35 +74,40 @@ export async function handleAddRepo(
|
|
|
69
74
|
options.dataDir,
|
|
70
75
|
options.projectRoot ?? process.env['PWD']
|
|
71
76
|
);
|
|
72
|
-
const storeName = args.name ?? extractRepoName(args.url);
|
|
73
77
|
|
|
74
|
-
|
|
78
|
+
try {
|
|
79
|
+
const storeName = args.name ?? extractRepoName(args.url);
|
|
75
80
|
|
|
76
|
-
|
|
77
|
-
name: storeName,
|
|
78
|
-
type: 'repo',
|
|
79
|
-
url: args.url,
|
|
80
|
-
...(args.branch !== undefined ? { branch: args.branch } : {}),
|
|
81
|
-
});
|
|
81
|
+
console.log(`Cloning ${args.url}...`);
|
|
82
82
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
83
|
+
const result = await services.store.create({
|
|
84
|
+
name: storeName,
|
|
85
|
+
type: 'repo',
|
|
86
|
+
url: args.url,
|
|
87
|
+
...(args.branch !== undefined ? { branch: args.branch } : {}),
|
|
88
|
+
});
|
|
87
89
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
90
|
+
if (!result.success) {
|
|
91
|
+
console.error(`Error: ${result.error.message}`);
|
|
92
|
+
process.exit(1);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
console.log(`Created store: ${storeName} (${result.data.id})`);
|
|
96
|
+
if ('path' in result.data) {
|
|
97
|
+
console.log(`Location: ${result.data.path}`);
|
|
98
|
+
}
|
|
92
99
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
100
|
+
// Auto-index
|
|
101
|
+
console.log('\nIndexing...');
|
|
102
|
+
const indexResult = await services.index.indexStore(result.data);
|
|
96
103
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
104
|
+
if (indexResult.success) {
|
|
105
|
+
console.log(`Indexed ${String(indexResult.data.documentsIndexed)} files`);
|
|
106
|
+
} else {
|
|
107
|
+
console.error(`Indexing failed: ${indexResult.error.message}`);
|
|
108
|
+
}
|
|
109
|
+
} finally {
|
|
110
|
+
await destroyServices(services);
|
|
101
111
|
}
|
|
102
112
|
}
|
|
103
113
|
|
|
@@ -110,58 +120,68 @@ export async function handleAddFolder(
|
|
|
110
120
|
options.dataDir,
|
|
111
121
|
options.projectRoot ?? process.env['PWD']
|
|
112
122
|
);
|
|
113
|
-
const { basename } = await import('node:path');
|
|
114
|
-
const storeName = args.name ?? basename(args.path);
|
|
115
123
|
|
|
116
|
-
|
|
124
|
+
try {
|
|
125
|
+
const { basename } = await import('node:path');
|
|
126
|
+
const storeName = args.name ?? basename(args.path);
|
|
117
127
|
|
|
118
|
-
|
|
119
|
-
name: storeName,
|
|
120
|
-
type: 'file',
|
|
121
|
-
path: args.path,
|
|
122
|
-
});
|
|
128
|
+
console.log(`Adding folder: ${args.path}...`);
|
|
123
129
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
130
|
+
const result = await services.store.create({
|
|
131
|
+
name: storeName,
|
|
132
|
+
type: 'file',
|
|
133
|
+
path: args.path,
|
|
134
|
+
});
|
|
128
135
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
136
|
+
if (!result.success) {
|
|
137
|
+
console.error(`Error: ${result.error.message}`);
|
|
138
|
+
process.exit(1);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
console.log(`Created store: ${storeName} (${result.data.id})`);
|
|
142
|
+
if ('path' in result.data) {
|
|
143
|
+
console.log(`Location: ${result.data.path}`);
|
|
144
|
+
}
|
|
133
145
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
146
|
+
// Auto-index
|
|
147
|
+
console.log('\nIndexing...');
|
|
148
|
+
const indexResult = await services.index.indexStore(result.data);
|
|
137
149
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
150
|
+
if (indexResult.success) {
|
|
151
|
+
console.log(`Indexed ${String(indexResult.data.documentsIndexed)} files`);
|
|
152
|
+
} else {
|
|
153
|
+
console.error(`Indexing failed: ${indexResult.error.message}`);
|
|
154
|
+
}
|
|
155
|
+
} finally {
|
|
156
|
+
await destroyServices(services);
|
|
142
157
|
}
|
|
143
158
|
}
|
|
144
159
|
|
|
145
160
|
export async function handleIndex(args: { store: string }): Promise<void> {
|
|
146
161
|
// PWD is set by Claude Code to user's project directory
|
|
147
162
|
const services = await createServices(undefined, undefined, process.env['PWD']);
|
|
148
|
-
const store = await services.store.getByIdOrName(args.store);
|
|
149
163
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
process.exit(1);
|
|
153
|
-
}
|
|
164
|
+
try {
|
|
165
|
+
const store = await services.store.getByIdOrName(args.store);
|
|
154
166
|
|
|
155
|
-
|
|
156
|
-
|
|
167
|
+
if (store === undefined) {
|
|
168
|
+
console.error(`Store not found: ${args.store}`);
|
|
169
|
+
process.exit(1);
|
|
170
|
+
}
|
|
157
171
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
)
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
172
|
+
console.log(`Indexing ${store.name}...`);
|
|
173
|
+
const result = await services.index.indexStore(store);
|
|
174
|
+
|
|
175
|
+
if (result.success) {
|
|
176
|
+
console.log(
|
|
177
|
+
`Indexed ${String(result.data.documentsIndexed)} documents in ${String(result.data.timeMs)}ms`
|
|
178
|
+
);
|
|
179
|
+
} else {
|
|
180
|
+
console.error(`Error: ${result.error.message}`);
|
|
181
|
+
process.exit(1);
|
|
182
|
+
}
|
|
183
|
+
} finally {
|
|
184
|
+
await destroyServices(services);
|
|
165
185
|
}
|
|
166
186
|
}
|
|
167
187
|
|
|
@@ -171,34 +191,39 @@ export async function handleStores(options: CommandOptions = {}): Promise<void>
|
|
|
171
191
|
options.dataDir,
|
|
172
192
|
options.projectRoot ?? process.env['PWD']
|
|
173
193
|
);
|
|
174
|
-
const stores = await services.store.list();
|
|
175
|
-
|
|
176
|
-
if (stores.length === 0) {
|
|
177
|
-
console.log('No stores found.');
|
|
178
|
-
console.log('\nCreate a store with:');
|
|
179
|
-
console.log(' /bluera-knowledge:add-repo <url> --name=<name>');
|
|
180
|
-
console.log(' /bluera-knowledge:add-folder <path> --name=<name>');
|
|
181
|
-
return;
|
|
182
|
-
}
|
|
183
194
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
let source = '';
|
|
194
|
-
|
|
195
|
-
if ('url' in store && store.url !== undefined) {
|
|
196
|
-
source = store.url;
|
|
197
|
-
} else if ('path' in store) {
|
|
198
|
-
source = store.path;
|
|
195
|
+
try {
|
|
196
|
+
const stores = await services.store.list();
|
|
197
|
+
|
|
198
|
+
if (stores.length === 0) {
|
|
199
|
+
console.log('No stores found.');
|
|
200
|
+
console.log('\nCreate a store with:');
|
|
201
|
+
console.log(' /bluera-knowledge:add-repo <url> --name=<name>');
|
|
202
|
+
console.log(' /bluera-knowledge:add-folder <path> --name=<name>');
|
|
203
|
+
return;
|
|
199
204
|
}
|
|
200
205
|
|
|
201
|
-
|
|
206
|
+
// Table header
|
|
207
|
+
console.log('| Name | Type | ID | Source |');
|
|
208
|
+
console.log('|------|------|----|--------------------|');
|
|
209
|
+
|
|
210
|
+
// Table rows
|
|
211
|
+
for (const store of stores) {
|
|
212
|
+
const name = store.name;
|
|
213
|
+
const type = store.type;
|
|
214
|
+
const id = store.id;
|
|
215
|
+
let source = '';
|
|
216
|
+
|
|
217
|
+
if ('url' in store && store.url !== undefined) {
|
|
218
|
+
source = store.url;
|
|
219
|
+
} else if ('path' in store) {
|
|
220
|
+
source = store.path;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
console.log(`| ${name} | ${type} | ${id.substring(0, 8)}... | ${source} |`);
|
|
224
|
+
}
|
|
225
|
+
} finally {
|
|
226
|
+
await destroyServices(services);
|
|
202
227
|
}
|
|
203
228
|
}
|
|
204
229
|
|
|
@@ -209,73 +234,78 @@ export async function handleSuggest(options: CommandOptions = {}): Promise<void>
|
|
|
209
234
|
|
|
210
235
|
// Create analyzer instance
|
|
211
236
|
const services = await createServices(options.config, options.dataDir, projectRoot);
|
|
212
|
-
const analyzer = new DependencyUsageAnalyzer();
|
|
213
|
-
const resolver = new RepoUrlResolver();
|
|
214
|
-
|
|
215
|
-
// Analyze with progress indicator
|
|
216
|
-
const spinner = ora('Scanning source files...').start();
|
|
217
237
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
238
|
+
try {
|
|
239
|
+
const analyzer = new DependencyUsageAnalyzer();
|
|
240
|
+
const resolver = new RepoUrlResolver();
|
|
221
241
|
|
|
222
|
-
|
|
242
|
+
// Analyze with progress indicator
|
|
243
|
+
const spinner = ora('Scanning source files...').start();
|
|
223
244
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
const { usages, totalFilesScanned, skippedFiles } = result.data;
|
|
245
|
+
const result = await analyzer.analyze(projectRoot, (current, total, message) => {
|
|
246
|
+
spinner.text = `${message} (${String(current)}/${String(total)})`;
|
|
247
|
+
});
|
|
230
248
|
|
|
231
|
-
|
|
232
|
-
`✔ Scanned ${String(totalFilesScanned)} files${skippedFiles > 0 ? ` (skipped ${String(skippedFiles)})` : ''}\n`
|
|
233
|
-
);
|
|
249
|
+
spinner.stop();
|
|
234
250
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
}
|
|
251
|
+
if (!result.success) {
|
|
252
|
+
console.error(`Error: ${result.error.message}`);
|
|
253
|
+
process.exit(1);
|
|
254
|
+
}
|
|
240
255
|
|
|
241
|
-
|
|
242
|
-
const existingStores = await services.store.list();
|
|
243
|
-
const existingRepoNames = new Set(existingStores.map((s) => s.name));
|
|
256
|
+
const { usages, totalFilesScanned, skippedFiles } = result.data;
|
|
244
257
|
|
|
245
|
-
|
|
258
|
+
console.log(
|
|
259
|
+
`✔ Scanned ${String(totalFilesScanned)} files${skippedFiles > 0 ? ` (skipped ${String(skippedFiles)})` : ''}\n`
|
|
260
|
+
);
|
|
246
261
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
262
|
+
if (usages.length === 0) {
|
|
263
|
+
console.log('No external dependencies found in this project.');
|
|
264
|
+
console.log('\nMake sure you have a package.json or requirements.txt file.');
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
251
267
|
|
|
252
|
-
|
|
253
|
-
|
|
268
|
+
// Filter out packages already in stores
|
|
269
|
+
const existingStores = await services.store.list();
|
|
270
|
+
const existingRepoNames = new Set(existingStores.map((s) => s.name));
|
|
254
271
|
|
|
255
|
-
|
|
256
|
-
topSuggestions.forEach((usage, i) => {
|
|
257
|
-
console.log(`${String(i + 1)}. ${usage.packageName}`);
|
|
258
|
-
console.log(
|
|
259
|
-
` ${String(usage.importCount)} imports across ${String(usage.fileCount)} files\n`
|
|
260
|
-
);
|
|
261
|
-
});
|
|
272
|
+
const newUsages = usages.filter((u) => !existingRepoNames.has(u.packageName));
|
|
262
273
|
|
|
263
|
-
|
|
274
|
+
if (newUsages.length === 0) {
|
|
275
|
+
console.log('✔ All dependencies are already in knowledge stores!');
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
264
278
|
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
const repoResult = await resolver.findRepoUrl(usage.packageName, usage.language);
|
|
279
|
+
// Show top 5 suggestions
|
|
280
|
+
const topSuggestions = newUsages.slice(0, 5);
|
|
268
281
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
console.log(
|
|
272
|
-
} else {
|
|
273
|
-
console.log(`✗ ${usage.packageName}: Could not find repository URL`);
|
|
282
|
+
console.log('Top dependencies by usage in this project:\n');
|
|
283
|
+
topSuggestions.forEach((usage, i) => {
|
|
284
|
+
console.log(`${String(i + 1)}. ${usage.packageName}`);
|
|
274
285
|
console.log(
|
|
275
|
-
`
|
|
286
|
+
` ${String(usage.importCount)} imports across ${String(usage.fileCount)} files\n`
|
|
276
287
|
);
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
console.log('Searching for repository URLs...\n');
|
|
291
|
+
|
|
292
|
+
// For each package, find repo URL
|
|
293
|
+
for (const usage of topSuggestions) {
|
|
294
|
+
const repoResult = await resolver.findRepoUrl(usage.packageName, usage.language);
|
|
295
|
+
|
|
296
|
+
if (repoResult.url !== null) {
|
|
297
|
+
console.log(`✔ ${usage.packageName}: ${repoResult.url}`);
|
|
298
|
+
console.log(` /bluera-knowledge:add-repo ${repoResult.url} --name=${usage.packageName}\n`);
|
|
299
|
+
} else {
|
|
300
|
+
console.log(`✗ ${usage.packageName}: Could not find repository URL`);
|
|
301
|
+
console.log(
|
|
302
|
+
` You can manually add it: /bluera-knowledge:add-repo <url> --name=${usage.packageName}\n`
|
|
303
|
+
);
|
|
304
|
+
}
|
|
277
305
|
}
|
|
278
|
-
}
|
|
279
306
|
|
|
280
|
-
|
|
307
|
+
console.log('Use the commands above to add repositories to your knowledge stores.');
|
|
308
|
+
} finally {
|
|
309
|
+
await destroyServices(services);
|
|
310
|
+
}
|
|
281
311
|
}
|
|
@@ -52,4 +52,19 @@ describe('validate-npm-release.sh', () => {
|
|
|
52
52
|
|
|
53
53
|
expect(hasSilentRedirect).toBe(false);
|
|
54
54
|
});
|
|
55
|
+
|
|
56
|
+
it('logs expected and installed versions for debugging', () => {
|
|
57
|
+
// Script should log both expected (from package.json) and installed versions
|
|
58
|
+
// This helps diagnose version mismatch issues from npm cache
|
|
59
|
+
expect(scriptContent).toContain('EXPECTED_VERSION');
|
|
60
|
+
expect(scriptContent).toContain('INSTALLED_VERSION');
|
|
61
|
+
expect(scriptContent).toContain('Expected version:');
|
|
62
|
+
expect(scriptContent).toContain('Installed version:');
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it('warns on version mismatch', () => {
|
|
66
|
+
// Script should warn if installed version differs from expected
|
|
67
|
+
expect(scriptContent).toContain('Version mismatch');
|
|
68
|
+
expect(scriptContent).toContain('npm cache');
|
|
69
|
+
});
|
|
55
70
|
});
|
|
@@ -2186,43 +2186,11 @@ describe('SearchService Environment Variables', () => {
|
|
|
2186
2186
|
vi.unstubAllEnvs();
|
|
2187
2187
|
});
|
|
2188
2188
|
|
|
2189
|
-
it('
|
|
2189
|
+
it('uses default values when env vars are not set', async () => {
|
|
2190
|
+
// Clear env vars to test defaults
|
|
2190
2191
|
vi.stubEnv('SEARCH_CONFIDENCE_HIGH', undefined as unknown as string);
|
|
2191
|
-
vi.stubEnv('SEARCH_CONFIDENCE_MEDIUM', '0.3');
|
|
2192
|
-
vi.stubEnv('SEARCH_TEST_FILE_BOOST', '0.5');
|
|
2193
|
-
|
|
2194
|
-
const tempDir = await mkdtemp(join(tmpdir(), 'search-env-test-'));
|
|
2195
|
-
const lanceStore = new LanceStore(tempDir);
|
|
2196
|
-
const embeddingEngine = new EmbeddingEngine();
|
|
2197
|
-
await embeddingEngine.initialize();
|
|
2198
|
-
|
|
2199
|
-
const storeId = createStoreId('env-test-store');
|
|
2200
|
-
await lanceStore.initialize(storeId);
|
|
2201
|
-
|
|
2202
|
-
const text = 'test document';
|
|
2203
|
-
const vector = await embeddingEngine.embed(text);
|
|
2204
|
-
await lanceStore.addDocuments(storeId, [
|
|
2205
|
-
{
|
|
2206
|
-
id: createDocumentId('doc-1'),
|
|
2207
|
-
content: text,
|
|
2208
|
-
vector,
|
|
2209
|
-
metadata: { type: 'file', storeId, indexedAt: new Date() },
|
|
2210
|
-
},
|
|
2211
|
-
]);
|
|
2212
|
-
|
|
2213
|
-
const searchService = new SearchService(lanceStore, embeddingEngine);
|
|
2214
|
-
|
|
2215
|
-
await expect(searchService.search({ query: 'test', stores: [storeId] })).rejects.toThrow(
|
|
2216
|
-
'SEARCH_CONFIDENCE_HIGH environment variable is required'
|
|
2217
|
-
);
|
|
2218
|
-
|
|
2219
|
-
await rm(tempDir, { recursive: true });
|
|
2220
|
-
});
|
|
2221
|
-
|
|
2222
|
-
it('throws if SEARCH_CONFIDENCE_MEDIUM is not set', async () => {
|
|
2223
|
-
vi.stubEnv('SEARCH_CONFIDENCE_HIGH', '0.5');
|
|
2224
2192
|
vi.stubEnv('SEARCH_CONFIDENCE_MEDIUM', undefined as unknown as string);
|
|
2225
|
-
vi.stubEnv('SEARCH_TEST_FILE_BOOST',
|
|
2193
|
+
vi.stubEnv('SEARCH_TEST_FILE_BOOST', undefined as unknown as string);
|
|
2226
2194
|
|
|
2227
2195
|
const tempDir = await mkdtemp(join(tmpdir(), 'search-env-test-'));
|
|
2228
2196
|
const lanceStore = new LanceStore(tempDir);
|
|
@@ -2245,14 +2213,15 @@ describe('SearchService Environment Variables', () => {
|
|
|
2245
2213
|
|
|
2246
2214
|
const searchService = new SearchService(lanceStore, embeddingEngine);
|
|
2247
2215
|
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
);
|
|
2216
|
+
// Should work with defaults (0.5 for high, 0.3 for medium)
|
|
2217
|
+
const results = await searchService.search({ query: 'test', stores: [storeId] });
|
|
2218
|
+
expect(results.results.length).toBeGreaterThan(0);
|
|
2219
|
+
expect(results.confidence).toBeDefined();
|
|
2251
2220
|
|
|
2252
2221
|
await rm(tempDir, { recursive: true });
|
|
2253
2222
|
});
|
|
2254
2223
|
|
|
2255
|
-
it('
|
|
2224
|
+
it('uses default test file boost when env var is not set', async () => {
|
|
2256
2225
|
vi.stubEnv('SEARCH_CONFIDENCE_HIGH', '0.5');
|
|
2257
2226
|
vi.stubEnv('SEARCH_CONFIDENCE_MEDIUM', '0.3');
|
|
2258
2227
|
vi.stubEnv('SEARCH_TEST_FILE_BOOST', undefined as unknown as string);
|
|
@@ -2278,16 +2247,16 @@ describe('SearchService Environment Variables', () => {
|
|
|
2278
2247
|
storeId,
|
|
2279
2248
|
indexedAt: new Date(),
|
|
2280
2249
|
filePath: 'tests/example.test.ts',
|
|
2281
|
-
fileType: 'test', //
|
|
2250
|
+
fileType: 'test', // Uses default SEARCH_TEST_FILE_BOOST (0.5)
|
|
2282
2251
|
},
|
|
2283
2252
|
},
|
|
2284
2253
|
]);
|
|
2285
2254
|
|
|
2286
2255
|
const searchService = new SearchService(lanceStore, embeddingEngine);
|
|
2287
2256
|
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
);
|
|
2257
|
+
// Should work with default test file boost
|
|
2258
|
+
const results = await searchService.search({ query: 'test', stores: [storeId] });
|
|
2259
|
+
expect(results.results.length).toBeGreaterThan(0);
|
|
2291
2260
|
|
|
2292
2261
|
await rm(tempDir, { recursive: true });
|
|
2293
2262
|
});
|