MCPcopy Create free account
hub / github.com/colbymchenry/codegraph / withStalenessNotice

Method withStalenessNotice

src/mcp/tools.ts:1332–1421  ·  view source on GitHub ↗
(result: ToolResult, projectPath?: string)

Source from the content-addressed store, hash-verified

1330 }
1331
1332 private withStalenessNotice(result: ToolResult, projectPath?: string): ToolResult {
1333 if (result.isError) return result;
1334
1335 let cg: CodeGraph;
1336 try {
1337 cg = this.getCodeGraph(projectPath);
1338 } catch {
1339 return result; // no default project — leave as is
1340 }
1341
1342 // Cross-project `projectPath` calls open a cached CodeGraph WITHOUT a
1343 // watcher (watchers are only attached to the default session project).
1344 // When the cross-project path happens to be the same project as the
1345 // default cg, the cached instance is the wrong one — its pendingFiles is
1346 // permanently empty. Detect the equal-path case and prefer the default
1347 // cg so the staleness signal still fires when an agent passes the
1348 // explicit projectPath form of its own project.
1349 if (this.cg && cg !== this.cg) {
1350 try {
1351 const sameProject =
1352 resolvePath(this.cg.getProjectRoot()) === resolvePath(cg.getProjectRoot());
1353 if (sameProject) cg = this.cg;
1354 } catch {
1355 /* getProjectRoot may throw on a closed instance — leave cg as is */
1356 }
1357 }
1358
1359 // Whole-index degradation (#876): once live watching has permanently
1360 // stopped, getPendingFiles() is empty so the per-file banner below can't
1361 // fire — but the index is now FROZEN and silently drifting stale. Surface
1362 // one global notice instead, so the agent Reads for current content rather
1363 // than trusting a response off a no-longer-updating index. (Cross-project
1364 // calls open a watcher-less CodeGraph, so this is false there — correct: we
1365 // only know degraded state for the default session project.)
1366 let degraded = false;
1367 try {
1368 degraded = cg.isWatcherDegraded?.() ?? false;
1369 } catch {
1370 degraded = false;
1371 }
1372 if (degraded) {
1373 const [head, ...tail] = result.content;
1374 if (!head || head.type !== 'text') return result;
1375 let reason: string | null = null;
1376 try {
1377 reason = cg.getWatcherDegradedReason?.() ?? null;
1378 } catch {
1379 reason = null;
1380 }
1381 const composed = `${formatDegradedBanner(reason)}\n\n${head.text}`;
1382 return { ...result, content: [{ type: 'text', text: composed }, ...tail] };
1383 }
1384
1385 // Defensive: some test fakes inject a partial CodeGraph stub without the
1386 // newer pending-files API. Treat missing/throwing as "no pending files."
1387 let pending: PendingFile[] = [];
1388 try {
1389 pending = cg.getPendingFiles?.() ?? [];

Callers 1

executeMethod · 0.95

Calls 9

getCodeGraphMethod · 0.95
formatDegradedBannerFunction · 0.85
formatStaleBannerFunction · 0.85
formatStaleFooterFunction · 0.85
isWatcherDegradedMethod · 0.80
getProjectRootMethod · 0.65
getPendingFilesMethod · 0.45
joinMethod · 0.45

Tested by

no test coverage detected