@sdsrs/code-graph 0.25.0 → 0.26.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/claude-plugin/.claude-plugin/plugin.json +1 -1
- package/claude-plugin/scripts/find-binary.js +24 -4
- package/claude-plugin/scripts/find-binary.test.js +75 -1
- package/claude-plugin/scripts/pre-edit-guide.js +7 -2
- package/claude-plugin/scripts/user-prompt-context.js +18 -11
- package/claude-plugin/scripts/user-prompt-context.test.js +24 -38
- package/claude-plugin/templates/plugin_code_graph_mcp.md +12 -7
- package/package.json +6 -6
|
@@ -87,13 +87,33 @@ function isNativeBinary(candidate) {
|
|
|
87
87
|
}
|
|
88
88
|
}
|
|
89
89
|
|
|
90
|
+
/**
|
|
91
|
+
* Decide whether a cached binary path is fresh enough to skip the full
|
|
92
|
+
* discovery walk. Matches the auto-update cache logic at ~:185-188 —
|
|
93
|
+
* cache wins only when its binary's version >= pkg version. Without this
|
|
94
|
+
* check, a stale cache entry (e.g. dev checkout's `bin/code-graph-mcp`
|
|
95
|
+
* recorded once, then never refreshed) shadows newer auto-update or
|
|
96
|
+
* platform-pkg binaries forever (see mem #8454).
|
|
97
|
+
*
|
|
98
|
+
* Permissive on unknown values: missing pkg version or unreadable binary
|
|
99
|
+
* version → trust cache (don't refuse the only path we know about).
|
|
100
|
+
*/
|
|
101
|
+
function isCachedBinaryFresh(cachedPath, pkgVersion) {
|
|
102
|
+
if (!isNativeBinary(cachedPath)) return false;
|
|
103
|
+
if (!pkgVersion) return true;
|
|
104
|
+
const cacheVer = readBinaryVersion(cachedPath);
|
|
105
|
+
if (!cacheVer) return true;
|
|
106
|
+
return compareVersions(cacheVer, pkgVersion) >= 0;
|
|
107
|
+
}
|
|
108
|
+
|
|
90
109
|
/**
|
|
91
110
|
* Locate the code-graph-mcp binary using multiple strategies.
|
|
92
111
|
* Results are cached to disk so repeated calls (e.g. per-hook) are fast.
|
|
93
112
|
*
|
|
94
113
|
* Priority:
|
|
95
|
-
* cache (if valid) → dev-mode (target/release) →
|
|
96
|
-
* → platform npm pkg → bundled (bin/) →
|
|
114
|
+
* cache (if valid + version >= pkg) → dev-mode (target/release) →
|
|
115
|
+
* auto-update cache → platform npm pkg → bundled (bin/) →
|
|
116
|
+
* cargo install → PATH → npx cache
|
|
97
117
|
*
|
|
98
118
|
* Returns the absolute path or null if not found.
|
|
99
119
|
*/
|
|
@@ -101,7 +121,7 @@ function findBinary() {
|
|
|
101
121
|
// Try disk cache first (avoids spawning `which` on hot paths)
|
|
102
122
|
try {
|
|
103
123
|
const cached = fs.readFileSync(CACHE_FILE, 'utf8').trim();
|
|
104
|
-
if (
|
|
124
|
+
if (isCachedBinaryFresh(cached, getPackageVersion())) return cached;
|
|
105
125
|
if (cached) clearCache();
|
|
106
126
|
} catch { /* no cache or stale */ }
|
|
107
127
|
|
|
@@ -242,7 +262,7 @@ function clearCache() {
|
|
|
242
262
|
module.exports = {
|
|
243
263
|
findBinary, findBinaryUncached, clearCache,
|
|
244
264
|
globalNodeModulesCandidates, findPlatformBinary,
|
|
245
|
-
getPackageVersion, compareVersions,
|
|
265
|
+
getPackageVersion, compareVersions, isCachedBinaryFresh,
|
|
246
266
|
CACHE_FILE, BINARY_NAME, PLATFORM_PKG,
|
|
247
267
|
};
|
|
248
268
|
|
|
@@ -6,7 +6,7 @@ const os = require('os');
|
|
|
6
6
|
const path = require('path');
|
|
7
7
|
|
|
8
8
|
const { globalNodeModulesCandidates, findPlatformBinary, BINARY_NAME,
|
|
9
|
-
compareVersions, getPackageVersion } = require('./find-binary');
|
|
9
|
+
compareVersions, getPackageVersion, isCachedBinaryFresh } = require('./find-binary');
|
|
10
10
|
|
|
11
11
|
function mkDir(t, prefix) {
|
|
12
12
|
const dir = fs.mkdtempSync(path.join(os.tmpdir(), prefix));
|
|
@@ -145,3 +145,77 @@ test('getPackageVersion reads root package.json', () => {
|
|
|
145
145
|
const v = getPackageVersion();
|
|
146
146
|
assert.match(v, /^\d+\.\d+\.\d+$/, `expected semver-ish, got: ${v}`);
|
|
147
147
|
});
|
|
148
|
+
|
|
149
|
+
// ─── isCachedBinaryFresh: disk cache version-check (mem #8454) ────────────
|
|
150
|
+
//
|
|
151
|
+
// Builds a fake binary that responds to `--version` with a controllable
|
|
152
|
+
// string. process.execPath (node itself) won't do — we need a binary
|
|
153
|
+
// whose --version line we control. Smallest approach: shell wrapper.
|
|
154
|
+
|
|
155
|
+
function buildFakeBinary(t, versionLine) {
|
|
156
|
+
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'cgmcp-fake-bin-'));
|
|
157
|
+
t.after(() => fs.rmSync(dir, { recursive: true, force: true }));
|
|
158
|
+
const binPath = path.join(dir, BINARY_NAME);
|
|
159
|
+
// readBinaryVersion parses "code-graph-mcp X.Y.Z" via the binary's first
|
|
160
|
+
// stdout line on `--version`. Shell wrapper is simpler than compiling.
|
|
161
|
+
const script = process.platform === 'win32'
|
|
162
|
+
? `@echo off\r\necho ${versionLine}\r\n`
|
|
163
|
+
: `#!/bin/sh\necho '${versionLine}'\n`;
|
|
164
|
+
fs.writeFileSync(binPath, script);
|
|
165
|
+
if (process.platform !== 'win32') fs.chmodSync(binPath, 0o755);
|
|
166
|
+
return binPath;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
test('isCachedBinaryFresh: cache binary version >= pkg → fresh', (t) => {
|
|
170
|
+
const bin = buildFakeBinary(t, 'code-graph-mcp 9.9.9');
|
|
171
|
+
assert.equal(isCachedBinaryFresh(bin, '0.25.0'), true);
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
test('isCachedBinaryFresh: cache binary version equals pkg → fresh', (t) => {
|
|
175
|
+
const bin = buildFakeBinary(t, 'code-graph-mcp 0.25.0');
|
|
176
|
+
assert.equal(isCachedBinaryFresh(bin, '0.25.0'), true);
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
test('isCachedBinaryFresh: cache binary version < pkg → stale (THE BUG)', (t) => {
|
|
180
|
+
// Reproduces mem #8454: cache pointed at bin/code-graph-mcp v0.5.28
|
|
181
|
+
// while pkg was v0.25.0 → cache was returned silently with no
|
|
182
|
+
// version-check, shadowing the installed 0.25.0 platform binary.
|
|
183
|
+
// After this fix, returns false → caller clears cache + falls through.
|
|
184
|
+
const bin = buildFakeBinary(t, 'code-graph-mcp 0.5.28');
|
|
185
|
+
assert.equal(isCachedBinaryFresh(bin, '0.25.0'), false);
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
test('isCachedBinaryFresh: missing pkg version → permissive (trust cache)', (t) => {
|
|
189
|
+
// Caller couldn't read package.json; refusing the cache would leave us
|
|
190
|
+
// with nothing. Better to trust the one path we have.
|
|
191
|
+
const bin = buildFakeBinary(t, 'code-graph-mcp 0.5.28');
|
|
192
|
+
assert.equal(isCachedBinaryFresh(bin, null), true);
|
|
193
|
+
assert.equal(isCachedBinaryFresh(bin, ''), true);
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
test('isCachedBinaryFresh: unreadable cache binary version → permissive', (t) => {
|
|
197
|
+
// Old binary that doesn't support `--version`, or output we can't
|
|
198
|
+
// parse. Same permissive path as missing pkg version.
|
|
199
|
+
const bin = buildFakeBinary(t, 'whatever garbage no semver here');
|
|
200
|
+
assert.equal(isCachedBinaryFresh(bin, '0.25.0'), true);
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
test('isCachedBinaryFresh: cache path does not exist → not fresh', () => {
|
|
204
|
+
assert.equal(isCachedBinaryFresh('/nonexistent/path/code-graph-mcp', '0.25.0'), false);
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
test('isCachedBinaryFresh: empty/null cache path → not fresh', () => {
|
|
208
|
+
assert.equal(isCachedBinaryFresh('', '0.25.0'), false);
|
|
209
|
+
assert.equal(isCachedBinaryFresh(null, '0.25.0'), false);
|
|
210
|
+
assert.equal(isCachedBinaryFresh(undefined, '0.25.0'), false);
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
test('isCachedBinaryFresh: file basename mismatch → not fresh', (t) => {
|
|
214
|
+
// realpathSync.basename check inside isNativeBinary — wrong name = not ours.
|
|
215
|
+
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'cgmcp-wrongname-'));
|
|
216
|
+
t.after(() => fs.rmSync(dir, { recursive: true, force: true }));
|
|
217
|
+
const wrongName = path.join(dir, 'other-tool');
|
|
218
|
+
fs.writeFileSync(wrongName, '#!/bin/sh\necho wrong\n');
|
|
219
|
+
if (process.platform !== 'win32') fs.chmodSync(wrongName, 0o755);
|
|
220
|
+
assert.equal(isCachedBinaryFresh(wrongName, '0.25.0'), false);
|
|
221
|
+
});
|
|
@@ -118,13 +118,18 @@ try {
|
|
|
118
118
|
process.exit(0);
|
|
119
119
|
}
|
|
120
120
|
|
|
121
|
-
// ---
|
|
121
|
+
// --- Inject when the symbol has any caller (1+) ---
|
|
122
|
+
// Earlier gate was 2+ direct callers; reality is that editing a function with
|
|
123
|
+
// even one production caller benefits from a one-line impact summary, and the
|
|
124
|
+
// per-symbol 2-minute cooldown caps frequency. The 2+ floor was a remnant of
|
|
125
|
+
// the v0.21 "agent picks tools without push" assumption — same bias mem #8234
|
|
126
|
+
// records as bounded leverage at the bench level.
|
|
122
127
|
const directCallers = jsonResult.direct_callers || 0;
|
|
123
128
|
const totalCallers = jsonResult.total_callers || 0;
|
|
124
129
|
const affectedFiles = jsonResult.affected_files || 0;
|
|
125
130
|
const risk = jsonResult.risk || 'low';
|
|
126
131
|
|
|
127
|
-
if (directCallers <
|
|
132
|
+
if (directCallers < 1) process.exit(0);
|
|
128
133
|
|
|
129
134
|
// Mark cooldown
|
|
130
135
|
try { fs.writeFileSync(cooldownFile, ''); } catch { /* ok */ }
|
|
@@ -33,23 +33,30 @@ function markCooldown(type) {
|
|
|
33
33
|
} catch { /* ok */ }
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
// v0.21
|
|
37
|
-
//
|
|
38
|
-
//
|
|
39
|
-
// agent
|
|
40
|
-
//
|
|
36
|
+
// Default ON. The v0.21 opt-in flip relied on routing-bench P@1=100% to argue
|
|
37
|
+
// "Sonnet 4.5 picks tools without push injection." That bench measures *triage
|
|
38
|
+
// accuracy once the agent has decided to query a tool*; it does not measure
|
|
39
|
+
// the prior question — *whether the agent reaches for a tool at all*.
|
|
40
|
+
// pre-grep-guide.js sees the real-world counter-evidence: a 15-day baseline of
|
|
41
|
+
// 429 raw `grep` vs 191 functional CLI calls on the same indexed source tree
|
|
42
|
+
// — a 13× pre-training bias toward grep. Push injection on the relevant turns
|
|
43
|
+
// is the corrective; cooldowns (impact 30s / overview 5min / callgraph 60s /
|
|
44
|
+
// search 60s) already cap per-type frequency. SessionStart `project_map` stays
|
|
45
|
+
// default OFF (lifecycle.js / session-init.js) — that one is a static dump
|
|
46
|
+
// duplicated by MEMORY.md; this hook is reactive and trigger-shaped, so the
|
|
47
|
+
// two defaults diverge intentionally.
|
|
41
48
|
//
|
|
42
49
|
// Priority (high → low):
|
|
43
|
-
// 1. CODE_GRAPH_QUIET_HOOKS=
|
|
44
|
-
// 2. CODE_GRAPH_QUIET_HOOKS=
|
|
45
|
-
// 3. CODE_GRAPH_VERBOSE_HOOKS=1 →
|
|
46
|
-
// 4. default →
|
|
50
|
+
// 1. CODE_GRAPH_QUIET_HOOKS=1 → forced quiet (escape hatch)
|
|
51
|
+
// 2. CODE_GRAPH_QUIET_HOOKS=0 → forced noisy (legacy back-compat, redundant with default)
|
|
52
|
+
// 3. CODE_GRAPH_VERBOSE_HOOKS=1 → noisy (legacy back-compat, redundant with default)
|
|
53
|
+
// 4. default → noisy
|
|
47
54
|
function computeQuietHooks(env = process.env) {
|
|
48
55
|
const envQuiet = env.CODE_GRAPH_QUIET_HOOKS;
|
|
49
|
-
if (envQuiet === '0') return false;
|
|
50
56
|
if (envQuiet === '1') return true;
|
|
57
|
+
if (envQuiet === '0') return false;
|
|
51
58
|
if (env.CODE_GRAPH_VERBOSE_HOOKS === '1') return false;
|
|
52
|
-
return
|
|
59
|
+
return false;
|
|
53
60
|
}
|
|
54
61
|
|
|
55
62
|
// --- Pure logic (exported for testing) ---
|
|
@@ -511,62 +511,48 @@ test('skills: only expected skills exist', () => {
|
|
|
511
511
|
assert.deepEqual(files, ['explore.md', 'index.md']);
|
|
512
512
|
});
|
|
513
513
|
|
|
514
|
-
|
|
515
|
-
const { spawnSync } = require('node:child_process');
|
|
516
|
-
const script = path.join(__dirname, 'user-prompt-context.js');
|
|
517
|
-
const proc = spawnSync(process.execPath, [script], {
|
|
518
|
-
input: JSON.stringify({ message: 'impact analysis for fn_that_would_trigger_search' }),
|
|
519
|
-
env: { ...process.env, CODE_GRAPH_QUIET_HOOKS: '1' },
|
|
520
|
-
encoding: 'utf8',
|
|
521
|
-
timeout: 2000,
|
|
522
|
-
});
|
|
523
|
-
// Quiet mode must be fully silent — any stderr leaks into Claude's display.
|
|
524
|
-
assert.equal(proc.stdout, '', 'stdout must be empty');
|
|
525
|
-
assert.equal(proc.stderr, '', 'stderr must be empty');
|
|
526
|
-
assert.equal(proc.status, 0, 'must exit 0');
|
|
527
|
-
});
|
|
514
|
+
// ── computeQuietHooks priority chain (default-noisy flip) ────────
|
|
528
515
|
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
//
|
|
533
|
-
//
|
|
534
|
-
assert.equal(computeQuietHooks({}),
|
|
516
|
+
test('computeQuietHooks: default (no env) is NOISY', () => {
|
|
517
|
+
// Default flipped back to push-on. The v0.21 opt-in default relied on
|
|
518
|
+
// routing-bench P@1=100% but that measures triage accuracy, not whether
|
|
519
|
+
// the agent reaches for a tool at all. pre-grep-guide.js sees 13× raw-grep
|
|
520
|
+
// bias on the same source tree — push is the corrective.
|
|
521
|
+
assert.equal(computeQuietHooks({}), false);
|
|
535
522
|
});
|
|
536
523
|
|
|
537
|
-
test('computeQuietHooks:
|
|
538
|
-
assert.equal(computeQuietHooks({
|
|
524
|
+
test('computeQuietHooks: CODE_GRAPH_QUIET_HOOKS=1 forces quiet (escape hatch)', () => {
|
|
525
|
+
assert.equal(computeQuietHooks({ CODE_GRAPH_QUIET_HOOKS: '1' }), true);
|
|
539
526
|
});
|
|
540
527
|
|
|
541
|
-
test('computeQuietHooks:
|
|
528
|
+
test('computeQuietHooks: CODE_GRAPH_QUIET_HOOKS=0 stays noisy (back-compat, same as default)', () => {
|
|
542
529
|
assert.equal(computeQuietHooks({ CODE_GRAPH_QUIET_HOOKS: '0' }), false);
|
|
543
530
|
});
|
|
544
531
|
|
|
545
|
-
test('computeQuietHooks:
|
|
546
|
-
assert.equal(computeQuietHooks({
|
|
532
|
+
test('computeQuietHooks: CODE_GRAPH_VERBOSE_HOOKS=1 stays noisy (back-compat, same as default)', () => {
|
|
533
|
+
assert.equal(computeQuietHooks({ CODE_GRAPH_VERBOSE_HOOKS: '1' }), false);
|
|
547
534
|
});
|
|
548
535
|
|
|
549
|
-
test('computeQuietHooks:
|
|
550
|
-
// Priority
|
|
551
|
-
assert.equal(computeQuietHooks({ CODE_GRAPH_QUIET_HOOKS: '0', CODE_GRAPH_VERBOSE_HOOKS: '0' }), false);
|
|
536
|
+
test('computeQuietHooks: QUIET_HOOKS=1 wins over VERBOSE_HOOKS=1 (priority chain)', () => {
|
|
537
|
+
// Priority: CODE_GRAPH_QUIET_HOOKS=1 (escape) > QUIET_HOOKS=0 / VERBOSE_HOOKS=1 > default.
|
|
552
538
|
assert.equal(computeQuietHooks({ CODE_GRAPH_QUIET_HOOKS: '1', CODE_GRAPH_VERBOSE_HOOKS: '1' }), true);
|
|
539
|
+
assert.equal(computeQuietHooks({ CODE_GRAPH_QUIET_HOOKS: '0', CODE_GRAPH_VERBOSE_HOOKS: '0' }), false);
|
|
553
540
|
});
|
|
554
541
|
|
|
555
|
-
test('
|
|
556
|
-
// End-to-end
|
|
557
|
-
//
|
|
542
|
+
test('CODE_GRAPH_QUIET_HOOKS=1 short-circuits silently on stdout, stderr, exit 0 (escape hatch verified end-to-end)', () => {
|
|
543
|
+
// End-to-end: the escape hatch must produce zero stdout/stderr noise
|
|
544
|
+
// (any leak would land in Claude's display). Was the only e2e check before
|
|
545
|
+
// the default-noisy flip — kept under the new default to guarantee that
|
|
546
|
+
// setting the env still fully silences the hook.
|
|
558
547
|
const { spawnSync } = require('node:child_process');
|
|
559
548
|
const script = path.join(__dirname, 'user-prompt-context.js');
|
|
560
|
-
const cleanEnv = { ...process.env };
|
|
561
|
-
delete cleanEnv.CODE_GRAPH_QUIET_HOOKS;
|
|
562
|
-
delete cleanEnv.CODE_GRAPH_VERBOSE_HOOKS;
|
|
563
549
|
const proc = spawnSync(process.execPath, [script], {
|
|
564
550
|
input: JSON.stringify({ message: 'impact of refactoring parse_code function' }),
|
|
565
|
-
env:
|
|
551
|
+
env: { ...process.env, CODE_GRAPH_QUIET_HOOKS: '1' },
|
|
566
552
|
encoding: 'utf8',
|
|
567
553
|
timeout: 2000,
|
|
568
554
|
});
|
|
569
|
-
assert.equal(proc.stdout, '', '
|
|
570
|
-
assert.equal(proc.stderr, '', '
|
|
571
|
-
assert.equal(proc.status, 0, '
|
|
555
|
+
assert.equal(proc.stdout, '', 'quiet must be silent on stdout');
|
|
556
|
+
assert.equal(proc.stderr, '', 'quiet must be silent on stderr');
|
|
557
|
+
assert.equal(proc.status, 0, 'quiet must exit 0');
|
|
572
558
|
});
|
|
@@ -15,12 +15,16 @@ type: reference
|
|
|
15
15
|
> 的最新决策表(本文件 SHA 与 template 差异时覆盖)。手动编辑会被覆盖——
|
|
16
16
|
> 要锁定自己的版本,设 `CODE_GRAPH_NO_TEMPLATE_REFRESH=1`(不影响首次 adopt)。
|
|
17
17
|
>
|
|
18
|
-
> **
|
|
19
|
-
>
|
|
20
|
-
> dump ≈2.3 KB
|
|
21
|
-
>
|
|
22
|
-
>
|
|
23
|
-
>
|
|
18
|
+
> **Hook 默认值(两个 hook,默认不同 —— 故意的)**:
|
|
19
|
+
> - **SessionStart `project_map` 注入:默认 OFF**(v0.17.0 起)。本文件 + 7 个
|
|
20
|
+
> 工具描述已经覆盖路由所需决策信息,每次会话再 dump ≈2.3 KB 项目地图是冗余的
|
|
21
|
+
> 常驻上下文。显式启用:`CODE_GRAPH_VERBOSE_HOOKS=1`;或按需 `code-graph-mcp map --compact`。
|
|
22
|
+
> - **UserPromptSubmit context push:默认 ON**。基于用户消息 intent 推 impact /
|
|
23
|
+
> overview / callgraph / search 结果(per-type cooldown 30s–5min)。routing-bench
|
|
24
|
+
> P@1=100% 测的是分诊准确率(已决定查工具时选哪个),不等于触发率(是否
|
|
25
|
+
> 决定查工具)—— 真实 baseline 是 raw-grep ≈13× 偏向于内置 Grep。Push 是
|
|
26
|
+
> pre-training bias 的矫正。Escape hatch:`CODE_GRAPH_QUIET_HOOKS=1`。
|
|
27
|
+
> - 优先级:`CODE_GRAPH_QUIET_HOOKS=1` (escape) > 其他 env > 默认。
|
|
24
28
|
>
|
|
25
29
|
> **v0.18.4 起**:原"进阶 5"(impact / similar / deps / dead-code / trace)已折叠
|
|
26
30
|
> 进核心 7 的 flag —— Claude Code 现在能直接通过 MCP 调用,不必落到 CLI:
|
|
@@ -122,4 +126,5 @@ code-graph-mcp health-check # 索引健康
|
|
|
122
126
|
- `CODE_GRAPH_NO_AUTO_ADOPT=1`(`~/.claude/settings.json` env) — 阻止未来自动 adopt,不影响已 adopted 状态。
|
|
123
127
|
- `CODE_GRAPH_NO_TEMPLATE_REFRESH=1`(v0.11.0+) — 锁定本文件不随插件升级刷新;允许手动编辑长久保留。
|
|
124
128
|
- `CODE_GRAPH_VERBOSE_HOOKS=1`(v0.17.0+) — opt in 到 SessionStart `project_map` 注入(默认 OFF)。
|
|
125
|
-
- `CODE_GRAPH_QUIET_HOOKS=
|
|
129
|
+
- `CODE_GRAPH_QUIET_HOOKS=1` — UserPromptSubmit context push 的 escape hatch(默认 ON);同时强制 SessionStart `project_map` quiet。
|
|
130
|
+
- `CODE_GRAPH_QUIET_HOOKS=0` — 强制恢复 SessionStart `project_map` 注入(向后兼容路径)。
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sdsrs/code-graph",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.26.0",
|
|
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.
|
|
39
|
-
"@sdsrs/code-graph-linux-arm64": "0.
|
|
40
|
-
"@sdsrs/code-graph-darwin-x64": "0.
|
|
41
|
-
"@sdsrs/code-graph-darwin-arm64": "0.
|
|
42
|
-
"@sdsrs/code-graph-win32-x64": "0.
|
|
38
|
+
"@sdsrs/code-graph-linux-x64": "0.26.0",
|
|
39
|
+
"@sdsrs/code-graph-linux-arm64": "0.26.0",
|
|
40
|
+
"@sdsrs/code-graph-darwin-x64": "0.26.0",
|
|
41
|
+
"@sdsrs/code-graph-darwin-arm64": "0.26.0",
|
|
42
|
+
"@sdsrs/code-graph-win32-x64": "0.26.0"
|
|
43
43
|
}
|
|
44
44
|
}
|