@sdsrs/code-graph 0.73.0 → 0.73.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.
|
@@ -330,6 +330,32 @@ function relicRepairGuard({ log = console.log, relic = undefined } = {}) {
|
|
|
330
330
|
return true;
|
|
331
331
|
}
|
|
332
332
|
|
|
333
|
+
// A dev-mode rebuild must PRESERVE the existing binary's feature set. This repair
|
|
334
|
+
// used to hardcode `--no-default-features`, which silently downgraded a hybrid
|
|
335
|
+
// (embed-model) dev binary to FTS5-only and ping-ponged against a manual
|
|
336
|
+
// `cargo build --release --features embed-model`. Probe the binary's COMPILED
|
|
337
|
+
// feature via `health-check --json` → `model_available` (= cfg!(feature =
|
|
338
|
+
// "embed-model"), reported even with no index) and rebuild to match. Returns
|
|
339
|
+
// true/false, or null when the binary can't be probed (missing/broken) — the
|
|
340
|
+
// caller then defaults to FTS5 + an explicit note, never a silent downgrade.
|
|
341
|
+
// End users never reach this path (binary-stale → auto-update; binary-missing
|
|
342
|
+
// non-dev → install instructions); it is purely the source-repo dev convenience.
|
|
343
|
+
function detectEmbedModel(binary, run = execFileSync) {
|
|
344
|
+
if (!binary) return null;
|
|
345
|
+
try {
|
|
346
|
+
const out = run(binary, ['health-check', '--json'], {
|
|
347
|
+
timeout: 10000, encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'],
|
|
348
|
+
});
|
|
349
|
+
return JSON.parse(out).model_available === true;
|
|
350
|
+
} catch { return null; }
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
function devBuildCommand(embed) {
|
|
354
|
+
return embed
|
|
355
|
+
? 'cargo build --release --features embed-model'
|
|
356
|
+
: 'cargo build --release --no-default-features';
|
|
357
|
+
}
|
|
358
|
+
|
|
333
359
|
function runRepairs(results) {
|
|
334
360
|
const fixable = results.filter(r => r.fixId);
|
|
335
361
|
if (fixable.length === 0) return 0;
|
|
@@ -353,14 +379,23 @@ function runRepairs(results) {
|
|
|
353
379
|
}
|
|
354
380
|
break;
|
|
355
381
|
}
|
|
382
|
+
// Preserve the current binary's feature set \u2014 never silently downgrade
|
|
383
|
+
// a hybrid (embed-model) dev binary to FTS5-only (which also ping-pongs
|
|
384
|
+
// against a manual `--features embed-model` build).
|
|
385
|
+
const embed = detectEmbedModel(findBinary());
|
|
386
|
+
const buildCmd = devBuildCommand(embed === true);
|
|
356
387
|
console.log('\n Building binary...');
|
|
357
|
-
|
|
388
|
+
if (embed === null) {
|
|
389
|
+
console.log(' (could not detect current feature set \u2014 building FTS5-only;');
|
|
390
|
+
console.log(' for semantic search rebuild with `cargo build --release --features embed-model`)');
|
|
391
|
+
}
|
|
392
|
+
console.log(` \u2192 ${buildCmd}`);
|
|
358
393
|
try {
|
|
359
394
|
const projectRoot = path.resolve(__dirname, '..', '..');
|
|
360
|
-
execSync(
|
|
395
|
+
execSync(buildCmd, {
|
|
361
396
|
cwd: projectRoot,
|
|
362
397
|
stdio: 'inherit',
|
|
363
|
-
timeout:
|
|
398
|
+
timeout: 600000, // embed-model (Candle) builds exceed the old 5min
|
|
364
399
|
});
|
|
365
400
|
clearBinaryCache();
|
|
366
401
|
console.log(' \u2705 Build complete');
|
|
@@ -374,13 +409,16 @@ function runRepairs(results) {
|
|
|
374
409
|
case 'binary-missing': {
|
|
375
410
|
console.log('\n Installing binary...');
|
|
376
411
|
if (isDevMode()) {
|
|
412
|
+
// No binary to probe \u2014 build the fast FTS5 binary, but point at the
|
|
413
|
+
// hybrid option so FTS5 isn't silently presented as the only choice.
|
|
377
414
|
console.log(' \u2192 cargo build --release --no-default-features');
|
|
415
|
+
console.log(' (for semantic search: cargo build --release --features embed-model)');
|
|
378
416
|
try {
|
|
379
417
|
const projectRoot = path.resolve(__dirname, '..', '..');
|
|
380
418
|
execSync('cargo build --release --no-default-features', {
|
|
381
419
|
cwd: projectRoot,
|
|
382
420
|
stdio: 'inherit',
|
|
383
|
-
timeout:
|
|
421
|
+
timeout: 600000,
|
|
384
422
|
});
|
|
385
423
|
clearBinaryCache();
|
|
386
424
|
console.log(' \u2705 Build complete');
|
|
@@ -500,7 +538,7 @@ function runDoctor(opts = {}) {
|
|
|
500
538
|
return { results, issueCount: issues.length };
|
|
501
539
|
}
|
|
502
540
|
|
|
503
|
-
module.exports = { runDiagnostics, formatReport, runRepairs, runDoctor, surveyHookCoverage, relicRepairGuard, classifyEmbeddings };
|
|
541
|
+
module.exports = { runDiagnostics, formatReport, runRepairs, runDoctor, surveyHookCoverage, relicRepairGuard, classifyEmbeddings, detectEmbedModel, devBuildCommand };
|
|
504
542
|
|
|
505
543
|
if (require.main === module) {
|
|
506
544
|
const args = process.argv.slice(2);
|
|
@@ -122,3 +122,30 @@ test('classifyEmbeddings OK for hybrid (partial + complete) and no-embeddable',
|
|
|
122
122
|
assert.equal(none.status, 'ok');
|
|
123
123
|
assert.match(none.detail, /no embeddable nodes/);
|
|
124
124
|
});
|
|
125
|
+
|
|
126
|
+
// ── dev-rebuild feature preservation (no silent hybrid→FTS5 downgrade / ping-pong) ──
|
|
127
|
+
test('devBuildCommand preserves feature set: hybrid → --features embed-model, fts → --no-default-features', () => {
|
|
128
|
+
const { devBuildCommand } = require('./doctor');
|
|
129
|
+
assert.match(devBuildCommand(true), /--features embed-model/);
|
|
130
|
+
assert.doesNotMatch(devBuildCommand(true), /--no-default-features/);
|
|
131
|
+
assert.match(devBuildCommand(false), /--no-default-features/);
|
|
132
|
+
assert.doesNotMatch(devBuildCommand(false), /--features embed-model/);
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
test('detectEmbedModel reads model_available from `health-check --json`; probe failure → null (never a false downgrade signal)', () => {
|
|
136
|
+
const { detectEmbedModel } = require('./doctor');
|
|
137
|
+
// hybrid binary
|
|
138
|
+
const hybridStub = (_bin, args) => {
|
|
139
|
+
assert.deepEqual(args, ['health-check', '--json']);
|
|
140
|
+
return JSON.stringify({ model_available: true });
|
|
141
|
+
};
|
|
142
|
+
assert.equal(detectEmbedModel('/bin/cg', hybridStub), true);
|
|
143
|
+
// FTS5-only binary
|
|
144
|
+
assert.equal(detectEmbedModel('/bin/cg', () => JSON.stringify({ model_available: false })), false);
|
|
145
|
+
// probe throws (binary broken) → null (caller defaults to FTS5 + note, not a downgrade claim)
|
|
146
|
+
assert.equal(detectEmbedModel('/bin/cg', () => { throw new Error('boom'); }), null);
|
|
147
|
+
// unparseable output → null
|
|
148
|
+
assert.equal(detectEmbedModel('/bin/cg', () => 'not json'), null);
|
|
149
|
+
// no binary → null
|
|
150
|
+
assert.equal(detectEmbedModel(null), null);
|
|
151
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sdsrs/code-graph",
|
|
3
|
-
"version": "0.73.
|
|
3
|
+
"version": "0.73.1",
|
|
4
4
|
"description": "MCP server that indexes codebases into an AST knowledge graph with semantic search, call graph traversal, and HTTP route tracing",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -35,10 +35,10 @@
|
|
|
35
35
|
"node": ">=16"
|
|
36
36
|
},
|
|
37
37
|
"optionalDependencies": {
|
|
38
|
-
"@sdsrs/code-graph-linux-x64": "0.73.
|
|
39
|
-
"@sdsrs/code-graph-linux-arm64": "0.73.
|
|
40
|
-
"@sdsrs/code-graph-darwin-x64": "0.73.
|
|
41
|
-
"@sdsrs/code-graph-darwin-arm64": "0.73.
|
|
42
|
-
"@sdsrs/code-graph-win32-x64": "0.73.
|
|
38
|
+
"@sdsrs/code-graph-linux-x64": "0.73.1",
|
|
39
|
+
"@sdsrs/code-graph-linux-arm64": "0.73.1",
|
|
40
|
+
"@sdsrs/code-graph-darwin-x64": "0.73.1",
|
|
41
|
+
"@sdsrs/code-graph-darwin-arm64": "0.73.1",
|
|
42
|
+
"@sdsrs/code-graph-win32-x64": "0.73.1"
|
|
43
43
|
}
|
|
44
44
|
}
|