open-codebase-index 0.22.3 → 0.22.4
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/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/dist/cli.cjs +647 -94
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +647 -94
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +421 -55
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +421 -55
- package/dist/index.js.map +1 -1
- package/dist/pi-extension.cjs +401 -48
- package/dist/pi-extension.cjs.map +1 -1
- package/dist/pi-extension.js +401 -48
- package/dist/pi-extension.js.map +1 -1
- package/native/codebase-index-native.darwin-arm64.node +0 -0
- package/native/codebase-index-native.darwin-x64.node +0 -0
- package/native/codebase-index-native.linux-arm64-gnu.node +0 -0
- package/native/codebase-index-native.linux-x64-gnu.node +0 -0
- package/native/codebase-index-native.win32-x64-msvc.node +0 -0
- package/package.json +13 -9
package/dist/index.cjs
CHANGED
|
@@ -1925,6 +1925,9 @@ var RELATIONSHIP_TYPES = [
|
|
|
1925
1925
|
];
|
|
1926
1926
|
var INDEX_LOG_CATEGORIES = ["search", "embedding", "cache", "gc", "branch", "general"];
|
|
1927
1927
|
var INDEX_LOG_LEVELS = ["error", "warn", "info", "debug"];
|
|
1928
|
+
var MIN_CODEBASE_EDIT_CONTEXT_EDGE_LIMIT = 1;
|
|
1929
|
+
var MAX_CODEBASE_EDIT_CONTEXT_EDGE_LIMIT = 20;
|
|
1930
|
+
var DEFAULT_CODEBASE_EDIT_CONTEXT_EDGE_LIMIT = 5;
|
|
1928
1931
|
var CODE_COMMUNITIES_MIN_SIZE = 1;
|
|
1929
1932
|
var CODE_COMMUNITIES_DEFAULT_LIMIT = 20;
|
|
1930
1933
|
var CODE_COMMUNITIES_MAX_LIMIT = 100;
|
|
@@ -2548,6 +2551,16 @@ function compactEvidenceValue(value, maxChars) {
|
|
|
2548
2551
|
}
|
|
2549
2552
|
var MAX_EXACT_SEARCH_HANDOFF_NAMES = 3;
|
|
2550
2553
|
var MAX_EXACT_SEARCH_HANDOFF_NAME_CHARS = 64;
|
|
2554
|
+
function toContextPackTraceCandidate(result) {
|
|
2555
|
+
return {
|
|
2556
|
+
filePath: result.filePath,
|
|
2557
|
+
startLine: result.startLine,
|
|
2558
|
+
endLine: result.endLine,
|
|
2559
|
+
score: result.score,
|
|
2560
|
+
chunkType: result.chunkType,
|
|
2561
|
+
name: result.name
|
|
2562
|
+
};
|
|
2563
|
+
}
|
|
2551
2564
|
function formatExactSearchHandoff(results) {
|
|
2552
2565
|
const suggestedNames = [];
|
|
2553
2566
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -2596,13 +2609,13 @@ function buildContextPack(results, options = {}) {
|
|
|
2596
2609
|
const maxResults = Math.max(0, Math.floor(options.maxResults ?? results.length));
|
|
2597
2610
|
const includeExactSearchHandoff = options.includeExactSearchHandoff ?? false;
|
|
2598
2611
|
const candidateCount = results.length;
|
|
2599
|
-
const
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
);
|
|
2605
|
-
const
|
|
2612
|
+
const preserveInputOrder = options.preserveInputOrder ?? false;
|
|
2613
|
+
const ranked = preserveInputOrder ? results.map((result, originalIndex) => ({ result, originalIndex })) : rankContextCandidates(results, options.preferImplementationPaths ?? false);
|
|
2614
|
+
const rankedCandidates = ranked.map((entry) => toContextPackTraceCandidate(entry.result));
|
|
2615
|
+
const deduplicated = deduplicateContextCandidates(ranked);
|
|
2616
|
+
const deduplicatedCandidates = deduplicated.map((result) => toContextPackTraceCandidate(result));
|
|
2617
|
+
const diversified = preserveInputOrder ? deduplicated : diversifyContextCandidates(deduplicated);
|
|
2618
|
+
const diversifiedCandidates = diversified.map((result) => toContextPackTraceCandidate(result));
|
|
2606
2619
|
const duplicateCount = candidateCount - deduplicated.length;
|
|
2607
2620
|
const selectable = diversified.slice(0, maxResults);
|
|
2608
2621
|
const limitOmittedCount = deduplicated.length - selectable.length;
|
|
@@ -2635,6 +2648,15 @@ function buildContextPack(results, options = {}) {
|
|
|
2635
2648
|
const fitted = fitTextToContextBudget(text, tokenBudget);
|
|
2636
2649
|
const budgetOmittedCount = selectable.length - selected.length;
|
|
2637
2650
|
const omittedCount = candidateCount - selected.length;
|
|
2651
|
+
if (options.trace) {
|
|
2652
|
+
options.trace({
|
|
2653
|
+
inputCandidates: results.map(toContextPackTraceCandidate),
|
|
2654
|
+
rankedCandidates,
|
|
2655
|
+
deduplicatedCandidates,
|
|
2656
|
+
diversifiedCandidates,
|
|
2657
|
+
selectedCandidates: selected.map(toContextPackTraceCandidate)
|
|
2658
|
+
});
|
|
2659
|
+
}
|
|
2638
2660
|
return {
|
|
2639
2661
|
requestedTokenBudget,
|
|
2640
2662
|
tokenBudget,
|
|
@@ -8613,12 +8635,12 @@ function diversifyGroupBySymbol(entries, getCandidate) {
|
|
|
8613
8635
|
return [...primary, ...remainder];
|
|
8614
8636
|
}
|
|
8615
8637
|
function buildDiversityKey(metadata) {
|
|
8616
|
-
const
|
|
8638
|
+
const normalizedPath2 = metadata.filePath.toLowerCase();
|
|
8617
8639
|
const normalizedName = (metadata.name ?? "").trim().toLowerCase();
|
|
8618
8640
|
if (normalizedName.length > 0) {
|
|
8619
|
-
return `${
|
|
8641
|
+
return `${normalizedPath2}#${normalizedName}`;
|
|
8620
8642
|
}
|
|
8621
|
-
return
|
|
8643
|
+
return normalizedPath2;
|
|
8622
8644
|
}
|
|
8623
8645
|
function rankHybridResults(query, semanticResults, keywordResults, options) {
|
|
8624
8646
|
const prioritizeSourcePaths = options.prioritizeSourcePaths ?? classifyQueryIntentRaw(query) === "source";
|
|
@@ -9067,9 +9089,9 @@ function normalizeFilePathForHintMatch(filePath) {
|
|
|
9067
9089
|
return filePath.replace(/\\/g, "/").toLowerCase().replace(/^\.\//, "");
|
|
9068
9090
|
}
|
|
9069
9091
|
function pathMatchesHint(filePath, hint) {
|
|
9070
|
-
const
|
|
9092
|
+
const normalizedPath2 = normalizeFilePathForHintMatch(filePath);
|
|
9071
9093
|
const normalizedHint = normalizeFilePathForHintMatch(hint);
|
|
9072
|
-
return
|
|
9094
|
+
return normalizedPath2.endsWith(normalizedHint) || normalizedPath2.includes(`/${normalizedHint}`) || normalizedPath2.includes(normalizedHint);
|
|
9073
9095
|
}
|
|
9074
9096
|
function extractFilePathHint(query) {
|
|
9075
9097
|
const match = query.match(FILE_PATH_HINT_SUFFIX_REGEX);
|
|
@@ -12942,6 +12964,20 @@ var Indexer = class _Indexer {
|
|
|
12942
12964
|
requestedLimit = nextLimit;
|
|
12943
12965
|
}
|
|
12944
12966
|
}
|
|
12967
|
+
buildCandidateSnapshot(candidate) {
|
|
12968
|
+
return {
|
|
12969
|
+
id: candidate.id,
|
|
12970
|
+
filePath: candidate.metadata.filePath,
|
|
12971
|
+
startLine: candidate.metadata.startLine,
|
|
12972
|
+
endLine: candidate.metadata.endLine,
|
|
12973
|
+
score: candidate.score,
|
|
12974
|
+
chunkType: candidate.metadata.chunkType,
|
|
12975
|
+
name: candidate.metadata.name
|
|
12976
|
+
};
|
|
12977
|
+
}
|
|
12978
|
+
buildCandidateSnapshotList(candidates) {
|
|
12979
|
+
return candidates.map((candidate) => this.buildCandidateSnapshot(candidate));
|
|
12980
|
+
}
|
|
12945
12981
|
searchSemanticCandidates(store, embedding, initialLimit, branchChunkIds, shouldPrefilterByBranch) {
|
|
12946
12982
|
return this.searchCandidatesWithBranchPrefilter(
|
|
12947
12983
|
initialLimit,
|
|
@@ -13133,6 +13169,16 @@ var Indexer = class _Indexer {
|
|
|
13133
13169
|
prefilterMs: Math.round(prefilterMs * 100) / 100,
|
|
13134
13170
|
fusionMs: Math.round(fusionMs * 100) / 100
|
|
13135
13171
|
});
|
|
13172
|
+
if (options?.trace) {
|
|
13173
|
+
options.trace({
|
|
13174
|
+
semanticCandidates: this.buildCandidateSnapshotList(scopedSemanticCandidates),
|
|
13175
|
+
keywordCandidates: this.buildCandidateSnapshotList(scopedKeywordCandidates),
|
|
13176
|
+
hybridCandidates: this.buildCandidateSnapshotList(combined),
|
|
13177
|
+
postExternalRerankCandidates: this.buildCandidateSnapshotList(rerankedCombined),
|
|
13178
|
+
tieredCandidates: this.buildCandidateSnapshotList(tiered),
|
|
13179
|
+
finalCandidates: this.buildCandidateSnapshotList(finalResults)
|
|
13180
|
+
});
|
|
13181
|
+
}
|
|
13136
13182
|
const metadataOnly = options?.metadataOnly ?? false;
|
|
13137
13183
|
return Promise.all(
|
|
13138
13184
|
finalResults.map(async (r) => {
|
|
@@ -14400,7 +14446,8 @@ async function searchCodebase(projectRoot, host, query, options = {}) {
|
|
|
14400
14446
|
definitionIntent: options.definitionIntent,
|
|
14401
14447
|
blameAuthor: options.blameAuthor,
|
|
14402
14448
|
blameSha: options.blameSha,
|
|
14403
|
-
blameSince: options.blameSince
|
|
14449
|
+
blameSince: options.blameSince,
|
|
14450
|
+
trace: options.trace
|
|
14404
14451
|
});
|
|
14405
14452
|
}
|
|
14406
14453
|
async function searchCodebaseWithEffectiveness(projectRoot, host, route, query, options, render) {
|
|
@@ -14454,15 +14501,19 @@ async function implementationLookup(projectRoot, host, query, options = {}) {
|
|
|
14454
14501
|
return indexer.search(query, options.limit, {
|
|
14455
14502
|
fileType: options.fileType,
|
|
14456
14503
|
directory: options.directory,
|
|
14457
|
-
definitionIntent: true
|
|
14504
|
+
definitionIntent: true,
|
|
14505
|
+
trace: options.trace
|
|
14458
14506
|
});
|
|
14459
14507
|
}
|
|
14460
14508
|
async function getCallGraphData(projectRoot, host, params) {
|
|
14461
14509
|
await ensureAutoIndexReadyForRetrieval(projectRoot, host);
|
|
14462
14510
|
const root = getProjectRoot(projectRoot, host);
|
|
14463
14511
|
const indexer = getIndexerForProject(root, host);
|
|
14512
|
+
return getCallGraphDataForIndexer(indexer, root, params);
|
|
14513
|
+
}
|
|
14514
|
+
async function getCallGraphDataForIndexer(indexer, projectRoot, params) {
|
|
14464
14515
|
const symbols = await indexer.getCallGraphSymbols();
|
|
14465
|
-
const resolution = resolveCallGraphSymbol(symbols,
|
|
14516
|
+
const resolution = resolveCallGraphSymbol(symbols, projectRoot, params.name, params.filePath, params.symbolId);
|
|
14466
14517
|
const direction = params.direction === "callees" ? "callees" : "callers";
|
|
14467
14518
|
if (resolution.status !== "resolved") {
|
|
14468
14519
|
return { direction, resolution, callers: [], callees: [], relationshipType: params.relationshipType };
|
|
@@ -14678,17 +14729,17 @@ async function getIndexLogs(projectRoot, host, args) {
|
|
|
14678
14729
|
function addKnowledgeBase(projectRoot, host, knowledgeBasePath) {
|
|
14679
14730
|
const root = getProjectRoot(projectRoot, host);
|
|
14680
14731
|
const inputPath = knowledgeBasePath.trim();
|
|
14681
|
-
const
|
|
14732
|
+
const normalizedPath2 = path20.resolve(
|
|
14682
14733
|
path20.isAbsolute(inputPath) ? inputPath : resolveKnowledgeBasePath(inputPath, root)
|
|
14683
14734
|
);
|
|
14684
|
-
if (!(0, import_fs13.existsSync)(
|
|
14685
|
-
return `Error: Directory does not exist: ${
|
|
14735
|
+
if (!(0, import_fs13.existsSync)(normalizedPath2)) {
|
|
14736
|
+
return `Error: Directory does not exist: ${normalizedPath2}`;
|
|
14686
14737
|
}
|
|
14687
14738
|
let realPath;
|
|
14688
14739
|
try {
|
|
14689
|
-
realPath = (0, import_fs13.realpathSync)(
|
|
14740
|
+
realPath = (0, import_fs13.realpathSync)(normalizedPath2);
|
|
14690
14741
|
} catch {
|
|
14691
|
-
return `Error: Cannot resolve path: ${
|
|
14742
|
+
return `Error: Cannot resolve path: ${normalizedPath2}`;
|
|
14692
14743
|
}
|
|
14693
14744
|
const blockedPrefixes = [
|
|
14694
14745
|
"/etc",
|
|
@@ -14711,34 +14762,34 @@ function addKnowledgeBase(projectRoot, host, knowledgeBasePath) {
|
|
|
14711
14762
|
];
|
|
14712
14763
|
for (const prefix of blockedPrefixes) {
|
|
14713
14764
|
if (realPath === prefix || realPath.startsWith(`${prefix}/`)) {
|
|
14714
|
-
return `Error: Adding sensitive directory as knowledge base is not allowed: ${
|
|
14765
|
+
return `Error: Adding sensitive directory as knowledge base is not allowed: ${normalizedPath2}`;
|
|
14715
14766
|
}
|
|
14716
14767
|
}
|
|
14717
14768
|
for (const dotDir of sensitiveDotDirs) {
|
|
14718
14769
|
const sensitiveDir = path20.join(homeDir, dotDir);
|
|
14719
14770
|
if (sensitiveDir && (realPath === sensitiveDir || realPath.startsWith(`${sensitiveDir}/`))) {
|
|
14720
|
-
return `Error: Adding sensitive directory as knowledge base is not allowed: ${
|
|
14771
|
+
return `Error: Adding sensitive directory as knowledge base is not allowed: ${normalizedPath2}`;
|
|
14721
14772
|
}
|
|
14722
14773
|
}
|
|
14723
14774
|
try {
|
|
14724
|
-
const stat4 = (0, import_fs13.statSync)(
|
|
14775
|
+
const stat4 = (0, import_fs13.statSync)(normalizedPath2);
|
|
14725
14776
|
if (!stat4.isDirectory()) {
|
|
14726
|
-
return `Error: Path is not a directory: ${
|
|
14777
|
+
return `Error: Path is not a directory: ${normalizedPath2}`;
|
|
14727
14778
|
}
|
|
14728
14779
|
} catch (error) {
|
|
14729
|
-
return `Error: Cannot access directory: ${
|
|
14780
|
+
return `Error: Cannot access directory: ${normalizedPath2} - ${error instanceof Error ? error.message : String(error)}`;
|
|
14730
14781
|
}
|
|
14731
14782
|
const config = loadEditableConfig(root, host);
|
|
14732
14783
|
const knowledgeBases = Array.isArray(config.knowledgeBases) ? config.knowledgeBases : [];
|
|
14733
|
-
const alreadyExists = hasMatchingKnowledgeBasePath(knowledgeBases,
|
|
14784
|
+
const alreadyExists = hasMatchingKnowledgeBasePath(knowledgeBases, normalizedPath2, root);
|
|
14734
14785
|
if (alreadyExists) {
|
|
14735
|
-
return `Knowledge base already configured: ${
|
|
14786
|
+
return `Knowledge base already configured: ${normalizedPath2}`;
|
|
14736
14787
|
}
|
|
14737
|
-
knowledgeBases.push(
|
|
14788
|
+
knowledgeBases.push(normalizedPath2);
|
|
14738
14789
|
config.knowledgeBases = knowledgeBases;
|
|
14739
14790
|
saveConfig(root, config, host);
|
|
14740
14791
|
refreshIndexerForDirectory(root, host);
|
|
14741
|
-
let result = `${
|
|
14792
|
+
let result = `${normalizedPath2}
|
|
14742
14793
|
`;
|
|
14743
14794
|
result += `Total knowledge bases: ${knowledgeBases.length}
|
|
14744
14795
|
`;
|
|
@@ -17051,6 +17102,181 @@ var pr_impact = tool({
|
|
|
17051
17102
|
}
|
|
17052
17103
|
});
|
|
17053
17104
|
|
|
17105
|
+
// src/tools/edit-context.ts
|
|
17106
|
+
function edgeLimit(value) {
|
|
17107
|
+
if (value === null || value === void 0 || !Number.isFinite(value)) {
|
|
17108
|
+
return DEFAULT_CODEBASE_EDIT_CONTEXT_EDGE_LIMIT;
|
|
17109
|
+
}
|
|
17110
|
+
return Math.min(
|
|
17111
|
+
MAX_CODEBASE_EDIT_CONTEXT_EDGE_LIMIT,
|
|
17112
|
+
Math.max(MIN_CODEBASE_EDIT_CONTEXT_EDGE_LIMIT, Math.floor(value))
|
|
17113
|
+
);
|
|
17114
|
+
}
|
|
17115
|
+
function normalizedPath(value) {
|
|
17116
|
+
return value.replaceAll("\\", "/").replace(/^\.\//, "");
|
|
17117
|
+
}
|
|
17118
|
+
function pathsMatch(left, right) {
|
|
17119
|
+
const normalizedLeft = normalizedPath(left);
|
|
17120
|
+
const normalizedRight = normalizedPath(right);
|
|
17121
|
+
return normalizedLeft === normalizedRight || normalizedLeft.endsWith(`/${normalizedRight}`) || normalizedRight.endsWith(`/${normalizedLeft}`);
|
|
17122
|
+
}
|
|
17123
|
+
function targetSource(results, resolution) {
|
|
17124
|
+
return results.find((result) => pathsMatch(result.filePath, resolution.filePath) && result.startLine <= resolution.startLine && result.endLine >= resolution.startLine) ?? results.find((result) => pathsMatch(result.filePath, resolution.filePath) && result.name === resolution.name);
|
|
17125
|
+
}
|
|
17126
|
+
function formatSource(result) {
|
|
17127
|
+
const name = result.name ? ` ${result.name}` : "";
|
|
17128
|
+
return [
|
|
17129
|
+
"## Target implementation",
|
|
17130
|
+
`${result.filePath}:${result.startLine}-${result.endLine} (${result.chunkType}${name})`,
|
|
17131
|
+
"```",
|
|
17132
|
+
result.content,
|
|
17133
|
+
"```"
|
|
17134
|
+
].join("\n");
|
|
17135
|
+
}
|
|
17136
|
+
function formatCallers(edges) {
|
|
17137
|
+
if (edges.length === 0) return "## Direct callers\nNone found.";
|
|
17138
|
+
return [
|
|
17139
|
+
"## Direct callers",
|
|
17140
|
+
...edges.map((edge) => `- ${edge.fromSymbolName ?? "<unknown>"} at ${edge.fromSymbolFilePath ?? "<unknown file>"}:${edge.line} (${edge.callType}, ${edge.isResolved ? "resolved" : "unresolved"})`)
|
|
17141
|
+
].join("\n");
|
|
17142
|
+
}
|
|
17143
|
+
function formatCallees(edges, sourceFilePath) {
|
|
17144
|
+
if (edges.length === 0) return "## Direct callees\nNone found.";
|
|
17145
|
+
return [
|
|
17146
|
+
"## Direct callees",
|
|
17147
|
+
...edges.map((edge) => `- ${edge.targetName} from ${sourceFilePath}:${edge.line} (${edge.callType}, ${edge.isResolved ? "resolved" : "unresolved"})`)
|
|
17148
|
+
].join("\n");
|
|
17149
|
+
}
|
|
17150
|
+
function formatResolutionRisk(resolution) {
|
|
17151
|
+
if (resolution.status === "ambiguous") {
|
|
17152
|
+
const candidates = resolution.candidates.map((candidate) => `${candidate.filePath}:${candidate.startLine}`).join(", ");
|
|
17153
|
+
return `Risk: symbol "${resolution.name}" is ambiguous. Pass filePath to select a target.${candidates ? ` Candidates: ${candidates}.` : ""}`;
|
|
17154
|
+
}
|
|
17155
|
+
if (resolution.filePath && resolution.totalCandidates > 0) {
|
|
17156
|
+
return `Risk: symbol "${resolution.name}" did not resolve at filePath="${resolution.filePath}". Review the conceptual evidence before editing.`;
|
|
17157
|
+
}
|
|
17158
|
+
return `Risk: symbol "${resolution.name}" could not be resolved. Review the conceptual evidence before editing.`;
|
|
17159
|
+
}
|
|
17160
|
+
async function fallbackPack(dependencies, query, risk, resolution, tokenBudget, candidateSource = []) {
|
|
17161
|
+
const conceptual = await dependencies.searchCodebase(query, { limit: 5 });
|
|
17162
|
+
const pack = buildContextPack([...candidateSource, ...conceptual], {
|
|
17163
|
+
tokenBudget: tokenBudget ?? void 0,
|
|
17164
|
+
heading: "## Conceptual evidence",
|
|
17165
|
+
maxResults: 5,
|
|
17166
|
+
includeExactSearchHandoff: false,
|
|
17167
|
+
preferImplementationPaths: true
|
|
17168
|
+
});
|
|
17169
|
+
const fitted = fitTextToContextBudget(`${risk}
|
|
17170
|
+
|
|
17171
|
+
${pack.text}`, tokenBudget ?? void 0);
|
|
17172
|
+
return {
|
|
17173
|
+
text: fitted.text,
|
|
17174
|
+
details: {
|
|
17175
|
+
resolution,
|
|
17176
|
+
tokenBudget: fitted.tokenBudget,
|
|
17177
|
+
tokenEstimate: fitted.tokenEstimate,
|
|
17178
|
+
truncated: fitted.truncated,
|
|
17179
|
+
sourceIncluded: candidateSource.length > 0,
|
|
17180
|
+
callerCount: 0,
|
|
17181
|
+
calleeCount: 0
|
|
17182
|
+
}
|
|
17183
|
+
};
|
|
17184
|
+
}
|
|
17185
|
+
async function resolveCodebaseEditContextWithDependencies(input, dependencies) {
|
|
17186
|
+
const symbol = input.symbol?.trim();
|
|
17187
|
+
if (!symbol) {
|
|
17188
|
+
return fallbackPack(
|
|
17189
|
+
dependencies,
|
|
17190
|
+
input.query,
|
|
17191
|
+
"Risk: no authoritative symbol was supplied. Review the conceptual evidence before editing.",
|
|
17192
|
+
"not_requested",
|
|
17193
|
+
input.tokenBudget
|
|
17194
|
+
);
|
|
17195
|
+
}
|
|
17196
|
+
let callersResult;
|
|
17197
|
+
try {
|
|
17198
|
+
callersResult = await dependencies.getCallGraphData({
|
|
17199
|
+
name: symbol,
|
|
17200
|
+
filePath: input.filePath ?? void 0,
|
|
17201
|
+
direction: "callers"
|
|
17202
|
+
});
|
|
17203
|
+
} catch (error) {
|
|
17204
|
+
const candidates = await dependencies.implementationLookup(symbol, { limit: 5 });
|
|
17205
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
17206
|
+
return fallbackPack(
|
|
17207
|
+
dependencies,
|
|
17208
|
+
input.query,
|
|
17209
|
+
`Risk: graph data is unavailable (${message}). Target and dependencies are not graph-verified.`,
|
|
17210
|
+
"graph_unavailable",
|
|
17211
|
+
input.tokenBudget,
|
|
17212
|
+
candidates
|
|
17213
|
+
);
|
|
17214
|
+
}
|
|
17215
|
+
if (callersResult.resolution.status !== "resolved") {
|
|
17216
|
+
return fallbackPack(
|
|
17217
|
+
dependencies,
|
|
17218
|
+
input.query,
|
|
17219
|
+
formatResolutionRisk(callersResult.resolution),
|
|
17220
|
+
callersResult.resolution.status,
|
|
17221
|
+
input.tokenBudget
|
|
17222
|
+
);
|
|
17223
|
+
}
|
|
17224
|
+
const resolution = callersResult.resolution;
|
|
17225
|
+
const [definitionsResult, calleesResult] = await Promise.allSettled([
|
|
17226
|
+
dependencies.implementationLookup(symbol, { limit: 10 }),
|
|
17227
|
+
dependencies.getCallGraphData({
|
|
17228
|
+
name: symbol,
|
|
17229
|
+
filePath: input.filePath ?? resolution.filePath,
|
|
17230
|
+
direction: "callees"
|
|
17231
|
+
})
|
|
17232
|
+
]);
|
|
17233
|
+
if (definitionsResult.status === "rejected") throw definitionsResult.reason;
|
|
17234
|
+
let graphRisk;
|
|
17235
|
+
let callees = [];
|
|
17236
|
+
if (calleesResult.status === "rejected") {
|
|
17237
|
+
const message = calleesResult.reason instanceof Error ? calleesResult.reason.message : String(calleesResult.reason);
|
|
17238
|
+
graphRisk = `Risk: callee graph data is unavailable (${message}). Dependency evidence is incomplete.`;
|
|
17239
|
+
} else if (calleesResult.value.resolution.status !== "resolved") {
|
|
17240
|
+
graphRisk = "Risk: the target resolved for callers but not callees. Dependency evidence is incomplete.";
|
|
17241
|
+
} else {
|
|
17242
|
+
callees = calleesResult.value.callees.slice(0, edgeLimit(input.calleeLimit));
|
|
17243
|
+
}
|
|
17244
|
+
const source = targetSource(definitionsResult.value, resolution);
|
|
17245
|
+
const callers = callersResult.callers.slice(0, edgeLimit(input.callerLimit));
|
|
17246
|
+
const sourceBudget = Math.max(
|
|
17247
|
+
MIN_CONTEXT_PACK_TOKEN_BUDGET,
|
|
17248
|
+
Math.floor((input.tokenBudget ?? DEFAULT_CONTEXT_PACK_TOKEN_BUDGET) * 0.6)
|
|
17249
|
+
);
|
|
17250
|
+
const sourceText = source ? fitTextToContextBudget(formatSource(source), sourceBudget).text : `## Target implementation
|
|
17251
|
+
Risk: no implementation source matched the resolved target at ${resolution.filePath}:${resolution.startLine}.`;
|
|
17252
|
+
const fitted = fitTextToContextBudget([
|
|
17253
|
+
`# Pre-edit context for ${resolution.name}`,
|
|
17254
|
+
graphRisk,
|
|
17255
|
+
sourceText,
|
|
17256
|
+
formatCallers(callers),
|
|
17257
|
+
formatCallees(callees, resolution.filePath)
|
|
17258
|
+
].filter((section) => section !== void 0).join("\n\n"), input.tokenBudget ?? void 0);
|
|
17259
|
+
return {
|
|
17260
|
+
text: fitted.text,
|
|
17261
|
+
details: {
|
|
17262
|
+
resolution: "resolved",
|
|
17263
|
+
tokenBudget: fitted.tokenBudget,
|
|
17264
|
+
tokenEstimate: fitted.tokenEstimate,
|
|
17265
|
+
truncated: fitted.truncated,
|
|
17266
|
+
sourceIncluded: source !== void 0,
|
|
17267
|
+
callerCount: callers.length,
|
|
17268
|
+
calleeCount: callees.length
|
|
17269
|
+
}
|
|
17270
|
+
};
|
|
17271
|
+
}
|
|
17272
|
+
async function resolveCodebaseEditContext(projectRoot, host, input) {
|
|
17273
|
+
return resolveCodebaseEditContextWithDependencies(input, {
|
|
17274
|
+
searchCodebase: (query, options) => searchCodebase(projectRoot, host, query, options),
|
|
17275
|
+
implementationLookup: (query, options) => implementationLookup(projectRoot, host, query, options),
|
|
17276
|
+
getCallGraphData: (params) => getCallGraphData(projectRoot, host, params)
|
|
17277
|
+
});
|
|
17278
|
+
}
|
|
17279
|
+
|
|
17054
17280
|
// src/tools/context-search.ts
|
|
17055
17281
|
var MIN_CONTEXT_RESULT_LIMIT = 1;
|
|
17056
17282
|
var MAX_CONTEXT_RESULT_LIMIT = 100;
|
|
@@ -17153,6 +17379,27 @@ function buildRecoveryDetails(attempts, successIndex) {
|
|
|
17153
17379
|
successfulAttemptIndex: successIndex
|
|
17154
17380
|
};
|
|
17155
17381
|
}
|
|
17382
|
+
function serializeAttempts(attempts) {
|
|
17383
|
+
return attempts.map((attempt) => ({
|
|
17384
|
+
kind: attempt.kind,
|
|
17385
|
+
scope: attempt.scope,
|
|
17386
|
+
resultCount: attempt.resultCount,
|
|
17387
|
+
relaxedFields: attempt.relaxedFields
|
|
17388
|
+
}));
|
|
17389
|
+
}
|
|
17390
|
+
function buildSearchDiagnostic(attempt) {
|
|
17391
|
+
if (!attempt) {
|
|
17392
|
+
return void 0;
|
|
17393
|
+
}
|
|
17394
|
+
return {
|
|
17395
|
+
route: attempt.kind,
|
|
17396
|
+
routedQuery: attempt.query,
|
|
17397
|
+
searchQuery: attempt.query,
|
|
17398
|
+
searchScope: attempt.scopeFilter,
|
|
17399
|
+
searchTrace: attempt.searchTrace,
|
|
17400
|
+
contextPackTrace: attempt.contextPackTrace
|
|
17401
|
+
};
|
|
17402
|
+
}
|
|
17156
17403
|
function trimOrUndefined2(value) {
|
|
17157
17404
|
const normalized = value?.trim();
|
|
17158
17405
|
if (!normalized) {
|
|
@@ -17192,6 +17439,7 @@ async function resolveSearchContext(input, operations) {
|
|
|
17192
17439
|
const hasFilters = Boolean(fileType || directory);
|
|
17193
17440
|
const relaxedFields = relaxedHintFields(fileType, directory);
|
|
17194
17441
|
const attempts = [];
|
|
17442
|
+
const attemptStates = [];
|
|
17195
17443
|
const decisions = {
|
|
17196
17444
|
inferredDefinitionMiss: false,
|
|
17197
17445
|
fallbackFromOriginalConceptualToInferred: false,
|
|
@@ -17220,8 +17468,20 @@ async function resolveSearchContext(input, operations) {
|
|
|
17220
17468
|
if (seenAttempts.has(key)) {
|
|
17221
17469
|
return [];
|
|
17222
17470
|
}
|
|
17223
|
-
const
|
|
17471
|
+
const attemptState = {
|
|
17472
|
+
kind,
|
|
17473
|
+
scope: describeScope(scope.fileType, scope.directory),
|
|
17474
|
+
resultCount: 0,
|
|
17475
|
+
relaxedFields: [...relaxedFieldsForAttempt],
|
|
17476
|
+
query: attemptQuery,
|
|
17477
|
+
scopeFilter: scope
|
|
17478
|
+
};
|
|
17479
|
+
const results = await runAttempt((trace) => {
|
|
17480
|
+
attemptState.searchTrace = trace;
|
|
17481
|
+
});
|
|
17482
|
+
attemptState.resultCount = results.length;
|
|
17224
17483
|
seenAttempts.add(key);
|
|
17484
|
+
attemptStates.push(attemptState);
|
|
17225
17485
|
attempts.push({
|
|
17226
17486
|
kind,
|
|
17227
17487
|
scope: describeScope(scope.fileType, scope.directory),
|
|
@@ -17241,7 +17501,7 @@ async function resolveSearchContext(input, operations) {
|
|
|
17241
17501
|
symbol,
|
|
17242
17502
|
scope,
|
|
17243
17503
|
relaxedFieldsForAttempt,
|
|
17244
|
-
() => operations.lookup(symbol, MAX_CONTEXT_RESULT_LIMIT, scope)
|
|
17504
|
+
(trace) => operations.lookup(symbol, MAX_CONTEXT_RESULT_LIMIT, scope, input.diagnostic ? trace : void 0)
|
|
17245
17505
|
);
|
|
17246
17506
|
};
|
|
17247
17507
|
const tryConceptualSearch = async (searchQuery, scope, relaxedFieldsForAttempt) => {
|
|
@@ -17250,13 +17510,23 @@ async function resolveSearchContext(input, operations) {
|
|
|
17250
17510
|
searchQuery,
|
|
17251
17511
|
scope,
|
|
17252
17512
|
relaxedFieldsForAttempt,
|
|
17253
|
-
() => operations.search(searchQuery, MAX_CONTEXT_RESULT_LIMIT, scope)
|
|
17513
|
+
(trace) => operations.search(searchQuery, MAX_CONTEXT_RESULT_LIMIT, scope, input.diagnostic ? trace : void 0)
|
|
17254
17514
|
);
|
|
17255
17515
|
};
|
|
17256
|
-
const
|
|
17516
|
+
const findSuccessfulAttemptState = (route) => {
|
|
17517
|
+
for (let index = attemptStates.length - 1; index >= 0; index -= 1) {
|
|
17518
|
+
const attempt = attemptStates[index];
|
|
17519
|
+
if (attempt.kind === route && attempt.resultCount > 0) {
|
|
17520
|
+
return attempt;
|
|
17521
|
+
}
|
|
17522
|
+
}
|
|
17523
|
+
return void 0;
|
|
17524
|
+
};
|
|
17525
|
+
const toResult = (route, routedQuery, pack, successfulAttempt) => {
|
|
17257
17526
|
const base = packedResult(route, routedQuery, pack);
|
|
17258
17527
|
const baseDetails = base.details;
|
|
17259
17528
|
const successIndex = findSuccessfulAttemptIndex(route, attempts);
|
|
17529
|
+
const successState = successfulAttempt ?? findSuccessfulAttemptState(route);
|
|
17260
17530
|
return {
|
|
17261
17531
|
text: base.text,
|
|
17262
17532
|
details: {
|
|
@@ -17264,7 +17534,10 @@ async function resolveSearchContext(input, operations) {
|
|
|
17264
17534
|
tokenBudget: baseDetails.tokenBudget,
|
|
17265
17535
|
tokenEstimate: baseDetails.tokenEstimate,
|
|
17266
17536
|
truncated: false,
|
|
17267
|
-
recovery: buildRecoveryDetails(
|
|
17537
|
+
recovery: buildRecoveryDetails(serializeAttempts(attemptStates), successIndex),
|
|
17538
|
+
...input.diagnostic && {
|
|
17539
|
+
diagnostic: buildSearchDiagnostic(successState)
|
|
17540
|
+
}
|
|
17268
17541
|
}
|
|
17269
17542
|
};
|
|
17270
17543
|
};
|
|
@@ -17278,8 +17551,18 @@ async function resolveSearchContext(input, operations) {
|
|
|
17278
17551
|
buildContextPack(scopedDefinitionResults, {
|
|
17279
17552
|
tokenBudget,
|
|
17280
17553
|
maxResults: limit,
|
|
17281
|
-
heading
|
|
17282
|
-
|
|
17554
|
+
heading,
|
|
17555
|
+
preserveInputOrder: true,
|
|
17556
|
+
...input.diagnostic ? {
|
|
17557
|
+
trace: (trace) => {
|
|
17558
|
+
const attemptState = findSuccessfulAttemptState("definition");
|
|
17559
|
+
if (attemptState) {
|
|
17560
|
+
attemptState.contextPackTrace = trace;
|
|
17561
|
+
}
|
|
17562
|
+
}
|
|
17563
|
+
} : void 0
|
|
17564
|
+
}),
|
|
17565
|
+
findSuccessfulAttemptState("definition")
|
|
17283
17566
|
);
|
|
17284
17567
|
}
|
|
17285
17568
|
if (explicitSymbol) {
|
|
@@ -17297,8 +17580,18 @@ async function resolveSearchContext(input, operations) {
|
|
|
17297
17580
|
buildContextPack(unscopedDefinitionResults, {
|
|
17298
17581
|
tokenBudget,
|
|
17299
17582
|
maxResults: limit,
|
|
17300
|
-
heading: heading2
|
|
17301
|
-
|
|
17583
|
+
heading: heading2,
|
|
17584
|
+
preserveInputOrder: true,
|
|
17585
|
+
...input.diagnostic ? {
|
|
17586
|
+
trace: (trace) => {
|
|
17587
|
+
const attemptState = findSuccessfulAttemptState("definition");
|
|
17588
|
+
if (attemptState) {
|
|
17589
|
+
attemptState.contextPackTrace = trace;
|
|
17590
|
+
}
|
|
17591
|
+
}
|
|
17592
|
+
} : void 0
|
|
17593
|
+
}),
|
|
17594
|
+
findSuccessfulAttemptState("definition")
|
|
17302
17595
|
);
|
|
17303
17596
|
}
|
|
17304
17597
|
}
|
|
@@ -17317,7 +17610,10 @@ Explicit symbol lookup only; conceptual search was not attempted.`
|
|
|
17317
17610
|
tokenBudget: heading.tokenBudget,
|
|
17318
17611
|
tokenEstimate: heading.tokenEstimate,
|
|
17319
17612
|
truncated: heading.truncated,
|
|
17320
|
-
recovery: buildRecoveryDetails(
|
|
17613
|
+
recovery: buildRecoveryDetails(serializeAttempts(attemptStates), null),
|
|
17614
|
+
...input.diagnostic && {
|
|
17615
|
+
diagnostic: buildSearchDiagnostic(attemptStates[attemptStates.length - 1])
|
|
17616
|
+
}
|
|
17321
17617
|
}
|
|
17322
17618
|
};
|
|
17323
17619
|
}
|
|
@@ -17357,8 +17653,17 @@ Explicit symbol lookup only; conceptual search was not attempted.`
|
|
|
17357
17653
|
maxResults: limit,
|
|
17358
17654
|
heading,
|
|
17359
17655
|
includeExactSearchHandoff: true,
|
|
17360
|
-
preferImplementationPaths: intent.preferSourcePaths || intent.primary !== "docs" && intent.primary !== "test"
|
|
17361
|
-
|
|
17656
|
+
preferImplementationPaths: intent.preferSourcePaths || intent.primary !== "docs" && intent.primary !== "test",
|
|
17657
|
+
...input.diagnostic ? {
|
|
17658
|
+
trace: (trace) => {
|
|
17659
|
+
const attemptState = findSuccessfulAttemptState("conceptual");
|
|
17660
|
+
if (attemptState) {
|
|
17661
|
+
attemptState.contextPackTrace = trace;
|
|
17662
|
+
}
|
|
17663
|
+
}
|
|
17664
|
+
} : void 0
|
|
17665
|
+
}),
|
|
17666
|
+
findSuccessfulAttemptState("conceptual")
|
|
17362
17667
|
);
|
|
17363
17668
|
}
|
|
17364
17669
|
}
|
|
@@ -17374,7 +17679,10 @@ Explicit symbol lookup only; conceptual search was not attempted.`
|
|
|
17374
17679
|
tokenBudget: fallbackText.tokenBudget,
|
|
17375
17680
|
tokenEstimate: fallbackText.tokenEstimate,
|
|
17376
17681
|
truncated: fallbackText.truncated,
|
|
17377
|
-
recovery: buildRecoveryDetails(
|
|
17682
|
+
recovery: buildRecoveryDetails(serializeAttempts(attemptStates), null),
|
|
17683
|
+
...input.diagnostic && {
|
|
17684
|
+
diagnostic: buildSearchDiagnostic(attemptStates[attemptStates.length - 1])
|
|
17685
|
+
}
|
|
17378
17686
|
}
|
|
17379
17687
|
};
|
|
17380
17688
|
}
|
|
@@ -17455,17 +17763,27 @@ async function resolveCodebaseContextUnmeasured(projectRoot, host, input) {
|
|
|
17455
17763
|
details: fittedDetails("path", fitted, 0)
|
|
17456
17764
|
};
|
|
17457
17765
|
}
|
|
17458
|
-
return resolveSearchContext({
|
|
17459
|
-
|
|
17766
|
+
return resolveSearchContext({
|
|
17767
|
+
query: input.query,
|
|
17768
|
+
symbol,
|
|
17769
|
+
limit,
|
|
17770
|
+
tokenBudget,
|
|
17771
|
+
fileType,
|
|
17772
|
+
directory,
|
|
17773
|
+
diagnostic: input.diagnostic
|
|
17774
|
+
}, {
|
|
17775
|
+
lookup: (lookupSymbol, retrievalLimit, scope, trace) => implementationLookup(projectRoot, host, lookupSymbol, {
|
|
17460
17776
|
limit: retrievalLimit,
|
|
17461
17777
|
fileType: scope.fileType,
|
|
17462
|
-
directory: scope.directory
|
|
17778
|
+
directory: scope.directory,
|
|
17779
|
+
trace
|
|
17463
17780
|
}),
|
|
17464
|
-
search: (queryText, retrievalLimit, scope) => searchCodebase(projectRoot, host, queryText, {
|
|
17781
|
+
search: (queryText, retrievalLimit, scope, trace) => searchCodebase(projectRoot, host, queryText, {
|
|
17465
17782
|
limit: retrievalLimit,
|
|
17466
17783
|
fileType: scope.fileType,
|
|
17467
17784
|
directory: scope.directory,
|
|
17468
|
-
metadataOnly: true
|
|
17785
|
+
metadataOnly: true,
|
|
17786
|
+
trace
|
|
17469
17787
|
})
|
|
17470
17788
|
});
|
|
17471
17789
|
}
|
|
@@ -17532,7 +17850,11 @@ async function resolveCodebaseContext(projectRoot, host, input) {
|
|
|
17532
17850
|
|
|
17533
17851
|
// src/tools/execute-common.ts
|
|
17534
17852
|
async function executeCodebaseContext(projectRoot, host, args) {
|
|
17535
|
-
|
|
17853
|
+
const result = await resolveCodebaseContext(projectRoot, host, args);
|
|
17854
|
+
return { text: result.text, details: result.details };
|
|
17855
|
+
}
|
|
17856
|
+
async function executeCodebaseEditContext(projectRoot, host, args) {
|
|
17857
|
+
return { text: (await resolveCodebaseEditContext(projectRoot, host, args)).text };
|
|
17536
17858
|
}
|
|
17537
17859
|
async function executeIndexCodebase(projectRoot, host, args, onProgress) {
|
|
17538
17860
|
const result = await runIndexCodebase(projectRoot, host, args, onProgress);
|
|
@@ -17635,9 +17957,9 @@ function parseGitActivity(output) {
|
|
|
17635
17957
|
if (!filePath || addedRaw === "-" || deletedRaw === "-") continue;
|
|
17636
17958
|
const churn = Number(addedRaw) + Number(deletedRaw);
|
|
17637
17959
|
if (!Number.isFinite(churn) || churn <= 0) continue;
|
|
17638
|
-
const
|
|
17639
|
-
const previous = activity.get(
|
|
17640
|
-
activity.set(
|
|
17960
|
+
const normalizedPath2 = normalizePath3(filePath);
|
|
17961
|
+
const previous = activity.get(normalizedPath2);
|
|
17962
|
+
activity.set(normalizedPath2, {
|
|
17641
17963
|
churn: (previous?.churn ?? 0) + churn,
|
|
17642
17964
|
commits: (previous?.commits ?? 0) + 1,
|
|
17643
17965
|
latestDate: previous?.latestDate ?? latestDate,
|
|
@@ -18227,8 +18549,8 @@ function transformForVisualization(symbols, edges, options = {}) {
|
|
|
18227
18549
|
const normalizedAbsoluteSuffix = `/${normalizedDirWithSlash}`;
|
|
18228
18550
|
filteredSymbols = symbols.filter(
|
|
18229
18551
|
(s) => {
|
|
18230
|
-
const
|
|
18231
|
-
return
|
|
18552
|
+
const normalizedPath2 = s.filePath.replace(/\\/g, "/");
|
|
18553
|
+
return normalizedPath2 === normalizedDir || normalizedPath2.startsWith(normalizedDirWithSlash) || normalizedPath2.endsWith(`/${normalizedDir}`) || normalizedPath2.includes(normalizedAbsoluteSuffix);
|
|
18232
18554
|
}
|
|
18233
18555
|
);
|
|
18234
18556
|
}
|
|
@@ -18302,6 +18624,26 @@ var z3 = tool.schema;
|
|
|
18302
18624
|
var DEFAULT_HOST = "opencode";
|
|
18303
18625
|
var CHUNK_TYPE_VALUES = CHUNK_TYPES;
|
|
18304
18626
|
var RELATIONSHIP_TYPE_VALUES = RELATIONSHIP_TYPES;
|
|
18627
|
+
function stableSortedDiagnosticValue(value) {
|
|
18628
|
+
if (Array.isArray(value)) {
|
|
18629
|
+
return value.map((item) => stableSortedDiagnosticValue(item));
|
|
18630
|
+
}
|
|
18631
|
+
if (value === null || typeof value !== "object") {
|
|
18632
|
+
return value;
|
|
18633
|
+
}
|
|
18634
|
+
const entries = Object.entries(value).sort(([left], [right]) => left.localeCompare(right));
|
|
18635
|
+
const sorted = {};
|
|
18636
|
+
for (const [key, item] of entries) {
|
|
18637
|
+
sorted[key] = stableSortedDiagnosticValue(item);
|
|
18638
|
+
}
|
|
18639
|
+
return sorted;
|
|
18640
|
+
}
|
|
18641
|
+
function formatCodebaseContextDiagnostic(details) {
|
|
18642
|
+
const sorted = stableSortedDiagnosticValue(details);
|
|
18643
|
+
return `
|
|
18644
|
+
Diagnostics:
|
|
18645
|
+
${JSON.stringify(sorted, null, 2)}`;
|
|
18646
|
+
}
|
|
18305
18647
|
function initializeTools2(projectRoot, config) {
|
|
18306
18648
|
initializeTools(projectRoot, config, DEFAULT_HOST);
|
|
18307
18649
|
}
|
|
@@ -18321,10 +18663,29 @@ var codebase_context = tool({
|
|
|
18321
18663
|
maxDepth: z3.number().int().min(MIN_CONTEXT_PATH_DEPTH).max(MAX_CONTEXT_PATH_DEPTH).nullable().optional().default(10).describe(`Maximum call-path traversal depth (${MIN_CONTEXT_PATH_DEPTH}-${MAX_CONTEXT_PATH_DEPTH})`),
|
|
18322
18664
|
fileType: z3.string().nullable().optional().describe("Filter by file extension"),
|
|
18323
18665
|
directory: z3.string().nullable().optional().describe("Filter by directory path"),
|
|
18324
|
-
tokenBudget: z3.number().int().min(MIN_CONTEXT_PACK_TOKEN_BUDGET).max(MAX_CONTEXT_PACK_TOKEN_BUDGET).nullable().optional().default(DEFAULT_CONTEXT_PACK_TOKEN_BUDGET).describe(`Maximum response tokens (${MIN_CONTEXT_PACK_TOKEN_BUDGET}-${MAX_CONTEXT_PACK_TOKEN_BUDGET})`)
|
|
18666
|
+
tokenBudget: z3.number().int().min(MIN_CONTEXT_PACK_TOKEN_BUDGET).max(MAX_CONTEXT_PACK_TOKEN_BUDGET).nullable().optional().default(DEFAULT_CONTEXT_PACK_TOKEN_BUDGET).describe(`Maximum response tokens (${MIN_CONTEXT_PACK_TOKEN_BUDGET}-${MAX_CONTEXT_PACK_TOKEN_BUDGET})`),
|
|
18667
|
+
diagnostic: z3.boolean().optional().describe("Collect diagnostic routing and search traces without changing normal text output.")
|
|
18668
|
+
},
|
|
18669
|
+
async execute(args, context) {
|
|
18670
|
+
const result = await executeCodebaseContext(context?.worktree, DEFAULT_HOST, args);
|
|
18671
|
+
if (!args.diagnostic || !result.details?.diagnostic) {
|
|
18672
|
+
return result.text;
|
|
18673
|
+
}
|
|
18674
|
+
return `${result.text}${formatCodebaseContextDiagnostic(result.details.diagnostic)}`;
|
|
18675
|
+
}
|
|
18676
|
+
});
|
|
18677
|
+
var codebase_edit_context = tool({
|
|
18678
|
+
description: "PRE-EDIT TOOL for a known or suspected symbol. Returns token-bounded target source, direct callers and callees, or a risk-marked conceptual fallback when the target cannot be resolved.",
|
|
18679
|
+
args: {
|
|
18680
|
+
query: z3.string().describe("The requested change or target behavior"),
|
|
18681
|
+
symbol: z3.string().nullable().optional().describe("Authoritative target symbol when known"),
|
|
18682
|
+
filePath: z3.string().nullable().optional().describe("Optional file path used to disambiguate duplicate symbol names"),
|
|
18683
|
+
callerLimit: z3.number().int().min(MIN_CODEBASE_EDIT_CONTEXT_EDGE_LIMIT).max(MAX_CODEBASE_EDIT_CONTEXT_EDGE_LIMIT).nullable().optional().default(DEFAULT_CODEBASE_EDIT_CONTEXT_EDGE_LIMIT),
|
|
18684
|
+
calleeLimit: z3.number().int().min(MIN_CODEBASE_EDIT_CONTEXT_EDGE_LIMIT).max(MAX_CODEBASE_EDIT_CONTEXT_EDGE_LIMIT).nullable().optional().default(DEFAULT_CODEBASE_EDIT_CONTEXT_EDGE_LIMIT),
|
|
18685
|
+
tokenBudget: z3.number().int().min(MIN_CONTEXT_PACK_TOKEN_BUDGET).max(MAX_CONTEXT_PACK_TOKEN_BUDGET).nullable().optional().default(DEFAULT_CONTEXT_PACK_TOKEN_BUDGET)
|
|
18325
18686
|
},
|
|
18326
18687
|
async execute(args, context) {
|
|
18327
|
-
return (await
|
|
18688
|
+
return (await executeCodebaseEditContext(context?.worktree, DEFAULT_HOST, args)).text;
|
|
18328
18689
|
}
|
|
18329
18690
|
});
|
|
18330
18691
|
var codebase_peek = tool({
|
|
@@ -18581,6 +18942,7 @@ var index_visualize = tool({
|
|
|
18581
18942
|
// src/tools/tool-names.ts
|
|
18582
18943
|
var TOOL_NAME = {
|
|
18583
18944
|
CODEBASE_CONTEXT: "codebase_context",
|
|
18945
|
+
CODEBASE_EDIT_CONTEXT: "codebase_edit_context",
|
|
18584
18946
|
CODEBASE_SEARCH: "codebase_search",
|
|
18585
18947
|
CODEBASE_PEEK: "codebase_peek",
|
|
18586
18948
|
FIND_SIMILAR: "find_similar",
|
|
@@ -18604,6 +18966,7 @@ var TOOL_NAME = {
|
|
|
18604
18966
|
};
|
|
18605
18967
|
var PORTABLE_TOOL_NAMES = [
|
|
18606
18968
|
TOOL_NAME.CODEBASE_CONTEXT,
|
|
18969
|
+
TOOL_NAME.CODEBASE_EDIT_CONTEXT,
|
|
18607
18970
|
TOOL_NAME.CODEBASE_SEARCH,
|
|
18608
18971
|
TOOL_NAME.CODEBASE_PEEK,
|
|
18609
18972
|
TOOL_NAME.INDEX_CODEBASE,
|
|
@@ -18620,6 +18983,7 @@ var PORTABLE_TOOL_NAMES = [
|
|
|
18620
18983
|
];
|
|
18621
18984
|
var OPENCODE_TOOL_NAMES = [
|
|
18622
18985
|
TOOL_NAME.CODEBASE_CONTEXT,
|
|
18986
|
+
TOOL_NAME.CODEBASE_EDIT_CONTEXT,
|
|
18623
18987
|
TOOL_NAME.CODEBASE_SEARCH,
|
|
18624
18988
|
TOOL_NAME.CODEBASE_PEEK,
|
|
18625
18989
|
TOOL_NAME.INDEX_CODEBASE,
|
|
@@ -18640,6 +19004,7 @@ var OPENCODE_TOOL_NAMES = [
|
|
|
18640
19004
|
];
|
|
18641
19005
|
var PI_TOOL_NAMES = [
|
|
18642
19006
|
TOOL_NAME.CODEBASE_CONTEXT,
|
|
19007
|
+
TOOL_NAME.CODEBASE_EDIT_CONTEXT,
|
|
18643
19008
|
TOOL_NAME.CODEBASE_SEARCH,
|
|
18644
19009
|
TOOL_NAME.CODEBASE_PEEK,
|
|
18645
19010
|
TOOL_NAME.FIND_SIMILAR,
|
|
@@ -19094,6 +19459,7 @@ var plugin = async ({ directory, worktree }) => {
|
|
|
19094
19459
|
return {
|
|
19095
19460
|
tool: {
|
|
19096
19461
|
[TOOL_NAME.CODEBASE_CONTEXT]: codebase_context,
|
|
19462
|
+
[TOOL_NAME.CODEBASE_EDIT_CONTEXT]: codebase_edit_context,
|
|
19097
19463
|
[TOOL_NAME.CODEBASE_SEARCH]: codebase_search,
|
|
19098
19464
|
[TOOL_NAME.CODEBASE_PEEK]: codebase_peek,
|
|
19099
19465
|
[TOOL_NAME.INDEX_CODEBASE]: index_codebase,
|