feat: Add dynamic codegraph_explore call budgets based on project size
Replaces fixed 6-call limit with adaptive budgets that scale from 2 calls for small projects (
This commit is contained in:
@@ -262,7 +262,7 @@ CodeGraph builds a semantic knowledge graph of codebases for faster, smarter cod
|
|||||||
> This project has CodeGraph initialized (.codegraph/ exists). Use `codegraph_explore` as your PRIMARY tool — it returns full source code sections from all relevant files in one call.
|
> This project has CodeGraph initialized (.codegraph/ exists). Use `codegraph_explore` as your PRIMARY tool — it returns full source code sections from all relevant files in one call.
|
||||||
>
|
>
|
||||||
> **Rules:**
|
> **Rules:**
|
||||||
> 1. Make at most 6 `codegraph_explore` calls — one broad query, then up to 5 focused follow-ups.
|
> 1. Follow the explore call budget in the `codegraph_explore` tool description — it scales automatically based on project size.
|
||||||
> 2. Do NOT re-read files that codegraph_explore already returned source code for. The source sections are complete and authoritative.
|
> 2. Do NOT re-read files that codegraph_explore already returned source code for. The source sections are complete and authoritative.
|
||||||
> 3. Only fall back to grep/glob/read for files listed under "Additional relevant files" if you need more detail, or if codegraph returned no results.
|
> 3. Only fall back to grep/glob/read for files listed under "Additional relevant files" if you need more detail, or if codegraph returned no results.
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ CodeGraph builds a semantic knowledge graph of codebases for faster, smarter cod
|
|||||||
> This project has CodeGraph initialized (.codegraph/ exists). Use \`codegraph_explore\` as your PRIMARY tool — it returns full source code sections from all relevant files in one call.
|
> This project has CodeGraph initialized (.codegraph/ exists). Use \`codegraph_explore\` as your PRIMARY tool — it returns full source code sections from all relevant files in one call.
|
||||||
>
|
>
|
||||||
> **Rules:**
|
> **Rules:**
|
||||||
> 1. Make at most 6 \`codegraph_explore\` calls — one broad query, then up to 5 focused follow-ups.
|
> 1. Follow the explore call budget in the \`codegraph_explore\` tool description — it scales automatically based on project size.
|
||||||
> 2. Do NOT re-read files that codegraph_explore already returned source code for. The source sections are complete and authoritative.
|
> 2. Do NOT re-read files that codegraph_explore already returned source code for. The source sections are complete and authoritative.
|
||||||
> 3. Only fall back to grep/glob/read for files listed under "Additional relevant files" if you need more detail, or if codegraph returned no results.
|
> 3. Only fall back to grep/glob/read for files listed under "Additional relevant files" if you need more detail, or if codegraph returned no results.
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -255,8 +255,9 @@ export class MCPServer {
|
|||||||
* Handle tools/list request
|
* Handle tools/list request
|
||||||
*/
|
*/
|
||||||
private async handleToolsList(request: JsonRpcRequest): Promise<void> {
|
private async handleToolsList(request: JsonRpcRequest): Promise<void> {
|
||||||
|
this.retryInitIfNeeded();
|
||||||
this.transport.sendResult(request.id, {
|
this.transport.sendResult(request.id, {
|
||||||
tools: tools,
|
tools: this.toolHandler.getTools(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,19 @@ import { join } from 'path';
|
|||||||
/** Maximum output length to prevent context bloat (characters) */
|
/** Maximum output length to prevent context bloat (characters) */
|
||||||
const MAX_OUTPUT_LENGTH = 15000;
|
const MAX_OUTPUT_LENGTH = 15000;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate the recommended number of codegraph_explore calls based on project size.
|
||||||
|
* Larger codebases need more exploration calls to cover their surface area,
|
||||||
|
* but smaller ones should use fewer to avoid unnecessary overhead.
|
||||||
|
*/
|
||||||
|
export function getExploreBudget(fileCount: number): number {
|
||||||
|
if (fileCount < 1000) return 2;
|
||||||
|
if (fileCount < 5000) return 3;
|
||||||
|
if (fileCount < 15000) return 4;
|
||||||
|
if (fileCount < 25000) return 5;
|
||||||
|
return 6;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mark a Claude session as having consulted MCP tools.
|
* Mark a Claude session as having consulted MCP tools.
|
||||||
* This enables Grep/Glob/Bash commands that would otherwise be blocked.
|
* This enables Grep/Glob/Bash commands that would otherwise be blocked.
|
||||||
@@ -298,6 +311,32 @@ export class ToolHandler {
|
|||||||
return this.cg !== null;
|
return this.cg !== null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get tool definitions with dynamic descriptions based on project size.
|
||||||
|
* The codegraph_explore tool description includes a budget recommendation
|
||||||
|
* scaled to the number of indexed files.
|
||||||
|
*/
|
||||||
|
getTools(): ToolDefinition[] {
|
||||||
|
if (!this.cg) return tools;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const stats = this.cg.getStats();
|
||||||
|
const budget = getExploreBudget(stats.fileCount);
|
||||||
|
|
||||||
|
return tools.map(tool => {
|
||||||
|
if (tool.name === 'codegraph_explore') {
|
||||||
|
return {
|
||||||
|
...tool,
|
||||||
|
description: `${tool.description} Budget: make at most ${budget} calls for this project (${stats.fileCount.toLocaleString()} files indexed).`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return tool;
|
||||||
|
});
|
||||||
|
} catch {
|
||||||
|
return tools;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get CodeGraph instance for a project
|
* Get CodeGraph instance for a project
|
||||||
*
|
*
|
||||||
@@ -854,6 +893,16 @@ export class ToolHandler {
|
|||||||
lines.push('---');
|
lines.push('---');
|
||||||
lines.push(`> **Complete source code is included above for ${filesIncluded} files.** You do NOT need to re-read these files — the relevant sections are already shown in full. Only use Read/Grep for files listed under "Additional relevant files" if you need more detail.`);
|
lines.push(`> **Complete source code is included above for ${filesIncluded} files.** You do NOT need to re-read these files — the relevant sections are already shown in full. Only use Read/Grep for files listed under "Additional relevant files" if you need more detail.`);
|
||||||
|
|
||||||
|
// Add explore budget note based on project size
|
||||||
|
try {
|
||||||
|
const stats = cg.getStats();
|
||||||
|
const budget = getExploreBudget(stats.fileCount);
|
||||||
|
lines.push('');
|
||||||
|
lines.push(`> **Explore budget: ${budget} calls max for this project (${stats.fileCount.toLocaleString()} files indexed).** Stop exploring and synthesize your answer once you've used ${budget} calls — do NOT make additional explore calls beyond this budget.`);
|
||||||
|
} catch {
|
||||||
|
// Stats unavailable — skip budget note
|
||||||
|
}
|
||||||
|
|
||||||
return this.textResult(lines.join('\n'));
|
return this.textResult(lines.join('\n'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user