@sdsrs/code-graph 0.5.25 → 0.5.27
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.
|
@@ -4,6 +4,12 @@
|
|
|
4
4
|
"author": {
|
|
5
5
|
"name": "sdsrs"
|
|
6
6
|
},
|
|
7
|
-
"version": "0.5.
|
|
8
|
-
"keywords": [
|
|
7
|
+
"version": "0.5.27",
|
|
8
|
+
"keywords": [
|
|
9
|
+
"code-graph",
|
|
10
|
+
"ast",
|
|
11
|
+
"navigation",
|
|
12
|
+
"mcp",
|
|
13
|
+
"knowledge-graph"
|
|
14
|
+
]
|
|
9
15
|
}
|
|
@@ -10,8 +10,9 @@ const { CACHE_DIR, PLUGIN_ID, MARKETPLACE_NAME, readManifest, readJson, writeJso
|
|
|
10
10
|
const GITHUB_REPO = 'sdsrss/code-graph-mcp';
|
|
11
11
|
const NPM_PACKAGE = '@sdsrs/code-graph';
|
|
12
12
|
const STATE_FILE = path.join(CACHE_DIR, 'update-state.json');
|
|
13
|
-
const CHECK_INTERVAL_MS =
|
|
14
|
-
const RATE_LIMIT_INTERVAL_MS =
|
|
13
|
+
const CHECK_INTERVAL_MS = 6 * 60 * 60 * 1000; // 6h (GitHub allows 60 req/h unauthenticated)
|
|
14
|
+
const RATE_LIMIT_INTERVAL_MS = 24 * 60 * 60 * 1000; // 24h if rate-limited
|
|
15
|
+
const POST_UPDATE_INTERVAL_MS = 1 * 60 * 60 * 1000; // 1h after update (verify success)
|
|
15
16
|
const FETCH_TIMEOUT_MS = 3000;
|
|
16
17
|
|
|
17
18
|
// ── State Persistence ──────────────────────────────────────
|
|
@@ -42,7 +43,9 @@ function isDevMode() {
|
|
|
42
43
|
function shouldCheck(state) {
|
|
43
44
|
if (!state.lastCheck) return true;
|
|
44
45
|
const elapsed = Date.now() - new Date(state.lastCheck).getTime();
|
|
45
|
-
|
|
46
|
+
let interval = CHECK_INTERVAL_MS;
|
|
47
|
+
if (state.rateLimited) interval = RATE_LIMIT_INTERVAL_MS;
|
|
48
|
+
else if (state.pendingBinaryUpdate) interval = POST_UPDATE_INTERVAL_MS;
|
|
46
49
|
return elapsed >= interval;
|
|
47
50
|
}
|
|
48
51
|
|
|
@@ -154,14 +157,18 @@ async function downloadAndInstall(latest) {
|
|
|
154
157
|
} catch { /* manifest update failed — not fatal */ }
|
|
155
158
|
|
|
156
159
|
// 6. Update npm binary (non-blocking, best-effort)
|
|
160
|
+
let binaryUpdated = false;
|
|
157
161
|
try {
|
|
158
162
|
execFileSync('npm', ['install', '-g', `${NPM_PACKAGE}@${latest.version}`], {
|
|
159
163
|
timeout: 60000,
|
|
160
164
|
stdio: 'pipe',
|
|
161
165
|
});
|
|
166
|
+
binaryUpdated = true;
|
|
167
|
+
// Clear pending flag on success
|
|
168
|
+
try { const s = readState(); delete s.pendingBinaryUpdate; saveState(s); } catch { /* ok */ }
|
|
162
169
|
} catch {
|
|
163
|
-
// npm
|
|
164
|
-
|
|
170
|
+
// npm package may not be published yet (race with CI). Record for retry.
|
|
171
|
+
try { const s = readState(); s.pendingBinaryUpdate = latest.version; saveState(s); } catch { /* ok */ }
|
|
165
172
|
}
|
|
166
173
|
|
|
167
174
|
return true;
|
|
@@ -6,10 +6,31 @@ const path = require('path');
|
|
|
6
6
|
const os = require('os');
|
|
7
7
|
const { findBinary } = require('./find-binary');
|
|
8
8
|
const { install, update, readManifest, getPluginVersion, checkScopeConflict } = require('./lifecycle');
|
|
9
|
-
const { checkForUpdate } = require('./auto-update');
|
|
9
|
+
const { checkForUpdate, readState: readUpdateState } = require('./auto-update');
|
|
10
10
|
|
|
11
11
|
let BIN = findBinary();
|
|
12
12
|
|
|
13
|
+
// --- 0b. Retry pending binary update from previous failed auto-update ---
|
|
14
|
+
{
|
|
15
|
+
const updateState = readUpdateState();
|
|
16
|
+
if (updateState.pendingBinaryUpdate) {
|
|
17
|
+
const pendingVer = updateState.pendingBinaryUpdate;
|
|
18
|
+
try {
|
|
19
|
+
execFileSync('npm', ['install', '-g', `@sdsrs/code-graph@${pendingVer}`], {
|
|
20
|
+
timeout: 30000, stdio: 'pipe'
|
|
21
|
+
});
|
|
22
|
+
try { fs.unlinkSync(path.join(os.homedir(), '.cache', 'code-graph', 'binary-path')); } catch {}
|
|
23
|
+
// Clear pending flag
|
|
24
|
+
const { writeJsonAtomic, CACHE_DIR } = require('./lifecycle');
|
|
25
|
+
const s = readUpdateState();
|
|
26
|
+
delete s.pendingBinaryUpdate;
|
|
27
|
+
writeJsonAtomic(path.join(CACHE_DIR, 'update-state.json'), s);
|
|
28
|
+
process.stderr.write(`[code-graph] Binary retry succeeded: v${pendingVer}\n`);
|
|
29
|
+
BIN = findBinary(); // refresh
|
|
30
|
+
} catch { /* npm still not available — will retry next session */ }
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
13
34
|
// --- 0. Auto-install binary if missing ---
|
|
14
35
|
if (!BIN) {
|
|
15
36
|
const version = getPluginVersion();
|
|
@@ -34,6 +55,7 @@ if (!BIN) {
|
|
|
34
55
|
}
|
|
35
56
|
|
|
36
57
|
// --- 1. Health check (always runs) ---
|
|
58
|
+
let healthNodes = -1;
|
|
37
59
|
if (BIN) {
|
|
38
60
|
try {
|
|
39
61
|
const out = execFileSync(BIN, ['health-check', '--format', 'oneline'], {
|
|
@@ -41,9 +63,38 @@ if (BIN) {
|
|
|
41
63
|
stdio: ['pipe', 'pipe', 'pipe']
|
|
42
64
|
}).toString().trim();
|
|
43
65
|
if (out) process.stdout.write(out);
|
|
66
|
+
// Parse node count for empty-index detection
|
|
67
|
+
const m = out.match(/(\d+)\s*nodes/);
|
|
68
|
+
if (m) healthNodes = parseInt(m[1], 10);
|
|
44
69
|
} catch { /* timeout — silent */ }
|
|
45
70
|
}
|
|
46
71
|
|
|
72
|
+
// --- 1a. Auto-index empty databases (fallback if MCP hasn't triggered indexing) ---
|
|
73
|
+
if (BIN && healthNodes === 0) {
|
|
74
|
+
const dbExists = fs.existsSync(path.join(process.cwd(), '.code-graph', 'index.db'));
|
|
75
|
+
if (dbExists) {
|
|
76
|
+
// DB exists but empty — MCP server likely hasn't received notifications/initialized yet.
|
|
77
|
+
// Trigger CLI indexing as fallback so the index is ready before first tool call.
|
|
78
|
+
try {
|
|
79
|
+
process.stderr.write('[code-graph] Empty index detected, running initial indexing...\n');
|
|
80
|
+
const result = execFileSync(BIN, ['incremental-index', '--quiet'], {
|
|
81
|
+
timeout: 15000, // 15s max (SessionStart hook has 20s budget)
|
|
82
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
83
|
+
}).toString().trim();
|
|
84
|
+
if (result) process.stderr.write(`[code-graph] ${result}\n`);
|
|
85
|
+
// Re-run health check to update statusline with new counts
|
|
86
|
+
try {
|
|
87
|
+
const out2 = execFileSync(BIN, ['health-check', '--format', 'oneline'], {
|
|
88
|
+
timeout: 2000, stdio: ['pipe', 'pipe', 'pipe']
|
|
89
|
+
}).toString().trim();
|
|
90
|
+
if (out2) process.stdout.write(`\n${out2}`);
|
|
91
|
+
} catch { /* ok */ }
|
|
92
|
+
} catch (e) {
|
|
93
|
+
process.stderr.write(`[code-graph] Auto-index failed: ${e.message || e}\n`);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
47
98
|
// --- 1b. Suggest project_map as first action ---
|
|
48
99
|
if (BIN) {
|
|
49
100
|
process.stdout.write(
|
|
@@ -66,6 +117,7 @@ if (BIN) {
|
|
|
66
117
|
(pv[0] === bv[0] && pv[1] === bv[1] && pv[2] > bv[2]);
|
|
67
118
|
if (pluginNewer) {
|
|
68
119
|
process.stderr.write(`[code-graph] Binary v${binVersion} < plugin v${pluginVersion}, updating...\n`);
|
|
120
|
+
let binarySynced = false;
|
|
69
121
|
try {
|
|
70
122
|
execFileSync('npm', ['install', '-g', `@sdsrs/code-graph@${pluginVersion}`], {
|
|
71
123
|
timeout: 30000, stdio: 'pipe'
|
|
@@ -73,11 +125,19 @@ if (BIN) {
|
|
|
73
125
|
// Clear cached binary path so next lookup finds the new binary
|
|
74
126
|
try { fs.unlinkSync(path.join(os.homedir(), '.cache', 'code-graph', 'binary-path')); } catch {}
|
|
75
127
|
process.stderr.write(`[code-graph] Binary updated to v${pluginVersion}\n`);
|
|
128
|
+
binarySynced = true;
|
|
76
129
|
} catch {
|
|
77
130
|
process.stderr.write(
|
|
78
131
|
`[code-graph] Auto-update failed. Run: npm install -g @sdsrs/code-graph@${pluginVersion}\n`
|
|
79
132
|
);
|
|
80
133
|
}
|
|
134
|
+
if (binarySynced) {
|
|
135
|
+
// MCP server is still running old binary — prompt user to reconnect
|
|
136
|
+
process.stdout.write(
|
|
137
|
+
`\n\u26A0\uFE0F [code-graph] Binary updated v${binVersion} \u2192 v${pluginVersion}. ` +
|
|
138
|
+
`Run /mcp to reconnect MCP server with new version.\n`
|
|
139
|
+
);
|
|
140
|
+
}
|
|
81
141
|
}
|
|
82
142
|
}
|
|
83
143
|
} catch { /* version check failed — not critical */ }
|
|
@@ -107,6 +167,10 @@ if (!manifest.version) {
|
|
|
107
167
|
const result = await checkForUpdate();
|
|
108
168
|
if (result && result.updated) {
|
|
109
169
|
process.stderr.write(`[code-graph] Updated: v${result.from} \u2192 v${result.to}\n`);
|
|
170
|
+
process.stdout.write(
|
|
171
|
+
`\n\uD83D\uDD04 [code-graph] Auto-updated v${result.from} \u2192 v${result.to}. ` +
|
|
172
|
+
`Run /mcp to use the new version.\n`
|
|
173
|
+
);
|
|
110
174
|
} else if (result && result.updateAvailable) {
|
|
111
175
|
process.stderr.write(
|
|
112
176
|
`[code-graph] Update available: v${result.from} \u2192 v${result.to}. ` +
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sdsrs/code-graph",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.27",
|
|
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": {
|
|
@@ -33,10 +33,10 @@
|
|
|
33
33
|
"node": ">=16"
|
|
34
34
|
},
|
|
35
35
|
"optionalDependencies": {
|
|
36
|
-
"@sdsrs/code-graph-linux-x64": "0.5.
|
|
37
|
-
"@sdsrs/code-graph-linux-arm64": "0.5.
|
|
38
|
-
"@sdsrs/code-graph-darwin-x64": "0.5.
|
|
39
|
-
"@sdsrs/code-graph-darwin-arm64": "0.5.
|
|
40
|
-
"@sdsrs/code-graph-win32-x64": "0.5.
|
|
36
|
+
"@sdsrs/code-graph-linux-x64": "0.5.27",
|
|
37
|
+
"@sdsrs/code-graph-linux-arm64": "0.5.27",
|
|
38
|
+
"@sdsrs/code-graph-darwin-x64": "0.5.27",
|
|
39
|
+
"@sdsrs/code-graph-darwin-arm64": "0.5.27",
|
|
40
|
+
"@sdsrs/code-graph-win32-x64": "0.5.27"
|
|
41
41
|
}
|
|
42
42
|
}
|