@sdsrs/code-graph 0.45.1 → 0.45.2

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,7 +4,7 @@
4
4
  "author": {
5
5
  "name": "sdsrs"
6
6
  },
7
- "version": "0.45.1",
7
+ "version": "0.45.2",
8
8
  "keywords": [
9
9
  "code-graph",
10
10
  "ast",
@@ -197,6 +197,20 @@ function cachedBinaryNeedsUpdate(latest, { binaryPath = cachedBinaryPath(), read
197
197
  return readVersion(binaryPath) !== latest.version;
198
198
  }
199
199
 
200
+ /**
201
+ * Throttle-bypass predicate: is a *present* cached binary stale relative to the
202
+ * last known latest release (`state.latestVersion`, set on the previous fetch —
203
+ * no network here)? Used so a present-but-stale binary skips the time-based
204
+ * throttle instead of staying pinned for up to a full check interval. Returns
205
+ * false when there is no prior latestVersion (first run fetches anyway) or the
206
+ * binary is missing (handled by the separate `binaryMissing` bypass).
207
+ */
208
+ function cachedBinaryStaleVsState(state, { binaryPath = cachedBinaryPath(), readVersion = readBinaryVersion } = {}) {
209
+ if (!state || !state.latestVersion) return false;
210
+ if (!fs.existsSync(binaryPath)) return false;
211
+ return readVersion(binaryPath) !== state.latestVersion;
212
+ }
213
+
200
214
  /**
201
215
  * Download just the platform binary from a GitHub release into the cache.
202
216
  * Used in two paths:
@@ -365,11 +379,14 @@ async function checkForUpdate({ installMissing = false } = {}) {
365
379
  // bypasses auto-update.js, so re-sync state.installedVersion every call.
366
380
  const installedVersion = readManifest().version || '0.0.0';
367
381
 
368
- // Time-based throttle. A missing cache binary is a hard failure (launcher
369
- // cannot start) so it overrides the throttle without this bypass the
370
- // session wedges for up to 6h waiting for the next check window.
382
+ // Time-based throttle. Two conditions override it: a missing cache binary
383
+ // (launcher cannot start) and a present-but-stale binary (otherwise it stays
384
+ // pinned to the old version for up to a full check interval the binary
385
+ // self-heal would never run inside the throttle window). Both bypass to the
386
+ // fetch + self-heal path below.
371
387
  const binaryMissing = !fs.existsSync(cachedBinaryPath());
372
- if (!binaryMissing && !shouldCheck(state)) {
388
+ const binaryStale = cachedBinaryStaleVsState(state);
389
+ if (!binaryMissing && !binaryStale && !shouldCheck(state)) {
373
390
  if (state.installedVersion !== installedVersion) {
374
391
  saveState({ ...state, installedVersion });
375
392
  }
@@ -446,7 +463,7 @@ module.exports = {
446
463
  getExtractedPluginVersion, readBinaryVersion, promoteVerifiedBinary,
447
464
  isSilentMode, isInstallMissingMode,
448
465
  requestJson, parseLatestRelease, fetchLatestRelease,
449
- downloadBinary, cachedBinaryPath, cachedBinaryNeedsUpdate,
466
+ downloadBinary, cachedBinaryPath, cachedBinaryNeedsUpdate, cachedBinaryStaleVsState,
450
467
  };
451
468
 
452
469
  // CLI: node auto-update.js [check|status] [--silent] [--install-missing]
@@ -14,6 +14,7 @@ const {
14
14
  promoteVerifiedBinary,
15
15
  cachedBinaryPath,
16
16
  cachedBinaryNeedsUpdate,
17
+ cachedBinaryStaleVsState,
17
18
  downloadBinary,
18
19
  isInstallMissingMode,
19
20
  isSilentMode,
@@ -116,6 +117,32 @@ test('cachedBinaryNeedsUpdate is version-aware, not existence-only', (t) => {
116
117
  assert.equal(cachedBinaryNeedsUpdate(null, { binaryPath }), false);
117
118
  });
118
119
 
120
+ test('cachedBinaryStaleVsState bypasses throttle only for a present-but-stale binary', (t) => {
121
+ const dir = mkDir(t, 'code-graph-throttle-');
122
+ const binaryPath = path.join(dir, 'code-graph-mcp');
123
+ fs.writeFileSync(binaryPath, 'x'); // present
124
+
125
+ // no prior latestVersion → don't bypass (first run fetches anyway)
126
+ assert.equal(cachedBinaryStaleVsState({}, { binaryPath }), false);
127
+ assert.equal(cachedBinaryStaleVsState(null, { binaryPath }), false);
128
+
129
+ // present + stale vs last known latest → bypass throttle (the 6h-gap fix)
130
+ assert.equal(
131
+ cachedBinaryStaleVsState({ latestVersion: '0.45.1' }, { binaryPath, readVersion: () => '0.16.6' }),
132
+ true,
133
+ );
134
+
135
+ // present + current → stay throttled
136
+ assert.equal(
137
+ cachedBinaryStaleVsState({ latestVersion: '0.45.1' }, { binaryPath, readVersion: () => '0.45.1' }),
138
+ false,
139
+ );
140
+
141
+ // missing binary → false here (the separate binaryMissing bypass handles it)
142
+ fs.rmSync(binaryPath);
143
+ assert.equal(cachedBinaryStaleVsState({ latestVersion: '0.45.1' }, { binaryPath }), false);
144
+ });
145
+
119
146
  test('parseLatestRelease selects the matching platform asset', () => {
120
147
  const latest = parseLatestRelease({
121
148
  tag_name: 'v1.2.3',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sdsrs/code-graph",
3
- "version": "0.45.1",
3
+ "version": "0.45.2",
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.45.1",
39
- "@sdsrs/code-graph-linux-arm64": "0.45.1",
40
- "@sdsrs/code-graph-darwin-x64": "0.45.1",
41
- "@sdsrs/code-graph-darwin-arm64": "0.45.1",
42
- "@sdsrs/code-graph-win32-x64": "0.45.1"
38
+ "@sdsrs/code-graph-linux-x64": "0.45.2",
39
+ "@sdsrs/code-graph-linux-arm64": "0.45.2",
40
+ "@sdsrs/code-graph-darwin-x64": "0.45.2",
41
+ "@sdsrs/code-graph-darwin-arm64": "0.45.2",
42
+ "@sdsrs/code-graph-win32-x64": "0.45.2"
43
43
  }
44
44
  }