opencode-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.js
CHANGED
|
@@ -1913,6 +1913,9 @@ var RELATIONSHIP_TYPES = [
|
|
|
1913
1913
|
];
|
|
1914
1914
|
var INDEX_LOG_CATEGORIES = ["search", "embedding", "cache", "gc", "branch", "general"];
|
|
1915
1915
|
var INDEX_LOG_LEVELS = ["error", "warn", "info", "debug"];
|
|
1916
|
+
var MIN_CODEBASE_EDIT_CONTEXT_EDGE_LIMIT = 1;
|
|
1917
|
+
var MAX_CODEBASE_EDIT_CONTEXT_EDGE_LIMIT = 20;
|
|
1918
|
+
var DEFAULT_CODEBASE_EDIT_CONTEXT_EDGE_LIMIT = 5;
|
|
1916
1919
|
var CODE_COMMUNITIES_MIN_SIZE = 1;
|
|
1917
1920
|
var CODE_COMMUNITIES_DEFAULT_LIMIT = 20;
|
|
1918
1921
|
var CODE_COMMUNITIES_MAX_LIMIT = 100;
|
|
@@ -2536,6 +2539,16 @@ function compactEvidenceValue(value, maxChars) {
|
|
|
2536
2539
|
}
|
|
2537
2540
|
var MAX_EXACT_SEARCH_HANDOFF_NAMES = 3;
|
|
2538
2541
|
var MAX_EXACT_SEARCH_HANDOFF_NAME_CHARS = 64;
|
|
2542
|
+
function toContextPackTraceCandidate(result) {
|
|
2543
|
+
return {
|
|
2544
|
+
filePath: result.filePath,
|
|
2545
|
+
startLine: result.startLine,
|
|
2546
|
+
endLine: result.endLine,
|
|
2547
|
+
score: result.score,
|
|
2548
|
+
chunkType: result.chunkType,
|
|
2549
|
+
name: result.name
|
|
2550
|
+
};
|
|
2551
|
+
}
|
|
2539
2552
|
function formatExactSearchHandoff(results) {
|
|
2540
2553
|
const suggestedNames = [];
|
|
2541
2554
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -2584,13 +2597,13 @@ function buildContextPack(results, options = {}) {
|
|
|
2584
2597
|
const maxResults = Math.max(0, Math.floor(options.maxResults ?? results.length));
|
|
2585
2598
|
const includeExactSearchHandoff = options.includeExactSearchHandoff ?? false;
|
|
2586
2599
|
const candidateCount = results.length;
|
|
2587
|
-
const
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
);
|
|
2593
|
-
const
|
|
2600
|
+
const preserveInputOrder = options.preserveInputOrder ?? false;
|
|
2601
|
+
const ranked = preserveInputOrder ? results.map((result, originalIndex) => ({ result, originalIndex })) : rankContextCandidates(results, options.preferImplementationPaths ?? false);
|
|
2602
|
+
const rankedCandidates = ranked.map((entry) => toContextPackTraceCandidate(entry.result));
|
|
2603
|
+
const deduplicated = deduplicateContextCandidates(ranked);
|
|
2604
|
+
const deduplicatedCandidates = deduplicated.map((result) => toContextPackTraceCandidate(result));
|
|
2605
|
+
const diversified = preserveInputOrder ? deduplicated : diversifyContextCandidates(deduplicated);
|
|
2606
|
+
const diversifiedCandidates = diversified.map((result) => toContextPackTraceCandidate(result));
|
|
2594
2607
|
const duplicateCount = candidateCount - deduplicated.length;
|
|
2595
2608
|
const selectable = diversified.slice(0, maxResults);
|
|
2596
2609
|
const limitOmittedCount = deduplicated.length - selectable.length;
|
|
@@ -2623,6 +2636,15 @@ function buildContextPack(results, options = {}) {
|
|
|
2623
2636
|
const fitted = fitTextToContextBudget(text, tokenBudget);
|
|
2624
2637
|
const budgetOmittedCount = selectable.length - selected.length;
|
|
2625
2638
|
const omittedCount = candidateCount - selected.length;
|
|
2639
|
+
if (options.trace) {
|
|
2640
|
+
options.trace({
|
|
2641
|
+
inputCandidates: results.map(toContextPackTraceCandidate),
|
|
2642
|
+
rankedCandidates,
|
|
2643
|
+
deduplicatedCandidates,
|
|
2644
|
+
diversifiedCandidates,
|
|
2645
|
+
selectedCandidates: selected.map(toContextPackTraceCandidate)
|
|
2646
|
+
});
|
|
2647
|
+
}
|
|
2626
2648
|
return {
|
|
2627
2649
|
requestedTokenBudget,
|
|
2628
2650
|
tokenBudget,
|
|
@@ -8610,12 +8632,12 @@ function diversifyGroupBySymbol(entries, getCandidate) {
|
|
|
8610
8632
|
return [...primary, ...remainder];
|
|
8611
8633
|
}
|
|
8612
8634
|
function buildDiversityKey(metadata) {
|
|
8613
|
-
const
|
|
8635
|
+
const normalizedPath2 = metadata.filePath.toLowerCase();
|
|
8614
8636
|
const normalizedName = (metadata.name ?? "").trim().toLowerCase();
|
|
8615
8637
|
if (normalizedName.length > 0) {
|
|
8616
|
-
return `${
|
|
8638
|
+
return `${normalizedPath2}#${normalizedName}`;
|
|
8617
8639
|
}
|
|
8618
|
-
return
|
|
8640
|
+
return normalizedPath2;
|
|
8619
8641
|
}
|
|
8620
8642
|
function rankHybridResults(query, semanticResults, keywordResults, options) {
|
|
8621
8643
|
const prioritizeSourcePaths = options.prioritizeSourcePaths ?? classifyQueryIntentRaw(query) === "source";
|
|
@@ -9064,9 +9086,9 @@ function normalizeFilePathForHintMatch(filePath) {
|
|
|
9064
9086
|
return filePath.replace(/\\/g, "/").toLowerCase().replace(/^\.\//, "");
|
|
9065
9087
|
}
|
|
9066
9088
|
function pathMatchesHint(filePath, hint) {
|
|
9067
|
-
const
|
|
9089
|
+
const normalizedPath2 = normalizeFilePathForHintMatch(filePath);
|
|
9068
9090
|
const normalizedHint = normalizeFilePathForHintMatch(hint);
|
|
9069
|
-
return
|
|
9091
|
+
return normalizedPath2.endsWith(normalizedHint) || normalizedPath2.includes(`/${normalizedHint}`) || normalizedPath2.includes(normalizedHint);
|
|
9070
9092
|
}
|
|
9071
9093
|
function extractFilePathHint(query) {
|
|
9072
9094
|
const match = query.match(FILE_PATH_HINT_SUFFIX_REGEX);
|
|
@@ -12939,6 +12961,20 @@ var Indexer = class _Indexer {
|
|
|
12939
12961
|
requestedLimit = nextLimit;
|
|
12940
12962
|
}
|
|
12941
12963
|
}
|
|
12964
|
+
buildCandidateSnapshot(candidate) {
|
|
12965
|
+
return {
|
|
12966
|
+
id: candidate.id,
|
|
12967
|
+
filePath: candidate.metadata.filePath,
|
|
12968
|
+
startLine: candidate.metadata.startLine,
|
|
12969
|
+
endLine: candidate.metadata.endLine,
|
|
12970
|
+
score: candidate.score,
|
|
12971
|
+
chunkType: candidate.metadata.chunkType,
|
|
12972
|
+
name: candidate.metadata.name
|
|
12973
|
+
};
|
|
12974
|
+
}
|
|
12975
|
+
buildCandidateSnapshotList(candidates) {
|
|
12976
|
+
return candidates.map((candidate) => this.buildCandidateSnapshot(candidate));
|
|
12977
|
+
}
|
|
12942
12978
|
searchSemanticCandidates(store, embedding, initialLimit, branchChunkIds, shouldPrefilterByBranch) {
|
|
12943
12979
|
return this.searchCandidatesWithBranchPrefilter(
|
|
12944
12980
|
initialLimit,
|
|
@@ -13130,6 +13166,16 @@ var Indexer = class _Indexer {
|
|
|
13130
13166
|
prefilterMs: Math.round(prefilterMs * 100) / 100,
|
|
13131
13167
|
fusionMs: Math.round(fusionMs * 100) / 100
|
|
13132
13168
|
});
|
|
13169
|
+
if (options?.trace) {
|
|
13170
|
+
options.trace({
|
|
13171
|
+
semanticCandidates: this.buildCandidateSnapshotList(scopedSemanticCandidates),
|
|
13172
|
+
keywordCandidates: this.buildCandidateSnapshotList(scopedKeywordCandidates),
|
|
13173
|
+
hybridCandidates: this.buildCandidateSnapshotList(combined),
|
|
13174
|
+
postExternalRerankCandidates: this.buildCandidateSnapshotList(rerankedCombined),
|
|
13175
|
+
tieredCandidates: this.buildCandidateSnapshotList(tiered),
|
|
13176
|
+
finalCandidates: this.buildCandidateSnapshotList(finalResults)
|
|
13177
|
+
});
|
|
13178
|
+
}
|
|
13133
13179
|
const metadataOnly = options?.metadataOnly ?? false;
|
|
13134
13180
|
return Promise.all(
|
|
13135
13181
|
finalResults.map(async (r) => {
|
|
@@ -14397,7 +14443,8 @@ async function searchCodebase(projectRoot, host, query, options = {}) {
|
|
|
14397
14443
|
definitionIntent: options.definitionIntent,
|
|
14398
14444
|
blameAuthor: options.blameAuthor,
|
|
14399
14445
|
blameSha: options.blameSha,
|
|
14400
|
-
blameSince: options.blameSince
|
|
14446
|
+
blameSince: options.blameSince,
|
|
14447
|
+
trace: options.trace
|
|
14401
14448
|
});
|
|
14402
14449
|
}
|
|
14403
14450
|
async function searchCodebaseWithEffectiveness(projectRoot, host, route, query, options, render) {
|
|
@@ -14451,15 +14498,19 @@ async function implementationLookup(projectRoot, host, query, options = {}) {
|
|
|
14451
14498
|
return indexer.search(query, options.limit, {
|
|
14452
14499
|
fileType: options.fileType,
|
|
14453
14500
|
directory: options.directory,
|
|
14454
|
-
definitionIntent: true
|
|
14501
|
+
definitionIntent: true,
|
|
14502
|
+
trace: options.trace
|
|
14455
14503
|
});
|
|
14456
14504
|
}
|
|
14457
14505
|
async function getCallGraphData(projectRoot, host, params) {
|
|
14458
14506
|
await ensureAutoIndexReadyForRetrieval(projectRoot, host);
|
|
14459
14507
|
const root = getProjectRoot(projectRoot, host);
|
|
14460
14508
|
const indexer = getIndexerForProject(root, host);
|
|
14509
|
+
return getCallGraphDataForIndexer(indexer, root, params);
|
|
14510
|
+
}
|
|
14511
|
+
async function getCallGraphDataForIndexer(indexer, projectRoot, params) {
|
|
14461
14512
|
const symbols = await indexer.getCallGraphSymbols();
|
|
14462
|
-
const resolution = resolveCallGraphSymbol(symbols,
|
|
14513
|
+
const resolution = resolveCallGraphSymbol(symbols, projectRoot, params.name, params.filePath, params.symbolId);
|
|
14463
14514
|
const direction = params.direction === "callees" ? "callees" : "callers";
|
|
14464
14515
|
if (resolution.status !== "resolved") {
|
|
14465
14516
|
return { direction, resolution, callers: [], callees: [], relationshipType: params.relationshipType };
|
|
@@ -14675,17 +14726,17 @@ async function getIndexLogs(projectRoot, host, args) {
|
|
|
14675
14726
|
function addKnowledgeBase(projectRoot, host, knowledgeBasePath) {
|
|
14676
14727
|
const root = getProjectRoot(projectRoot, host);
|
|
14677
14728
|
const inputPath = knowledgeBasePath.trim();
|
|
14678
|
-
const
|
|
14729
|
+
const normalizedPath2 = path20.resolve(
|
|
14679
14730
|
path20.isAbsolute(inputPath) ? inputPath : resolveKnowledgeBasePath(inputPath, root)
|
|
14680
14731
|
);
|
|
14681
|
-
if (!existsSync12(
|
|
14682
|
-
return `Error: Directory does not exist: ${
|
|
14732
|
+
if (!existsSync12(normalizedPath2)) {
|
|
14733
|
+
return `Error: Directory does not exist: ${normalizedPath2}`;
|
|
14683
14734
|
}
|
|
14684
14735
|
let realPath;
|
|
14685
14736
|
try {
|
|
14686
|
-
realPath = realpathSync5(
|
|
14737
|
+
realPath = realpathSync5(normalizedPath2);
|
|
14687
14738
|
} catch {
|
|
14688
|
-
return `Error: Cannot resolve path: ${
|
|
14739
|
+
return `Error: Cannot resolve path: ${normalizedPath2}`;
|
|
14689
14740
|
}
|
|
14690
14741
|
const blockedPrefixes = [
|
|
14691
14742
|
"/etc",
|
|
@@ -14708,34 +14759,34 @@ function addKnowledgeBase(projectRoot, host, knowledgeBasePath) {
|
|
|
14708
14759
|
];
|
|
14709
14760
|
for (const prefix of blockedPrefixes) {
|
|
14710
14761
|
if (realPath === prefix || realPath.startsWith(`${prefix}/`)) {
|
|
14711
|
-
return `Error: Adding sensitive directory as knowledge base is not allowed: ${
|
|
14762
|
+
return `Error: Adding sensitive directory as knowledge base is not allowed: ${normalizedPath2}`;
|
|
14712
14763
|
}
|
|
14713
14764
|
}
|
|
14714
14765
|
for (const dotDir of sensitiveDotDirs) {
|
|
14715
14766
|
const sensitiveDir = path20.join(homeDir, dotDir);
|
|
14716
14767
|
if (sensitiveDir && (realPath === sensitiveDir || realPath.startsWith(`${sensitiveDir}/`))) {
|
|
14717
|
-
return `Error: Adding sensitive directory as knowledge base is not allowed: ${
|
|
14768
|
+
return `Error: Adding sensitive directory as knowledge base is not allowed: ${normalizedPath2}`;
|
|
14718
14769
|
}
|
|
14719
14770
|
}
|
|
14720
14771
|
try {
|
|
14721
|
-
const stat4 = statSync5(
|
|
14772
|
+
const stat4 = statSync5(normalizedPath2);
|
|
14722
14773
|
if (!stat4.isDirectory()) {
|
|
14723
|
-
return `Error: Path is not a directory: ${
|
|
14774
|
+
return `Error: Path is not a directory: ${normalizedPath2}`;
|
|
14724
14775
|
}
|
|
14725
14776
|
} catch (error) {
|
|
14726
|
-
return `Error: Cannot access directory: ${
|
|
14777
|
+
return `Error: Cannot access directory: ${normalizedPath2} - ${error instanceof Error ? error.message : String(error)}`;
|
|
14727
14778
|
}
|
|
14728
14779
|
const config = loadEditableConfig(root, host);
|
|
14729
14780
|
const knowledgeBases = Array.isArray(config.knowledgeBases) ? config.knowledgeBases : [];
|
|
14730
|
-
const alreadyExists = hasMatchingKnowledgeBasePath(knowledgeBases,
|
|
14781
|
+
const alreadyExists = hasMatchingKnowledgeBasePath(knowledgeBases, normalizedPath2, root);
|
|
14731
14782
|
if (alreadyExists) {
|
|
14732
|
-
return `Knowledge base already configured: ${
|
|
14783
|
+
return `Knowledge base already configured: ${normalizedPath2}`;
|
|
14733
14784
|
}
|
|
14734
|
-
knowledgeBases.push(
|
|
14785
|
+
knowledgeBases.push(normalizedPath2);
|
|
14735
14786
|
config.knowledgeBases = knowledgeBases;
|
|
14736
14787
|
saveConfig(root, config, host);
|
|
14737
14788
|
refreshIndexerForDirectory(root, host);
|
|
14738
|
-
let result = `${
|
|
14789
|
+
let result = `${normalizedPath2}
|
|
14739
14790
|
`;
|
|
14740
14791
|
result += `Total knowledge bases: ${knowledgeBases.length}
|
|
14741
14792
|
`;
|
|
@@ -17048,6 +17099,181 @@ var pr_impact = tool({
|
|
|
17048
17099
|
}
|
|
17049
17100
|
});
|
|
17050
17101
|
|
|
17102
|
+
// src/tools/edit-context.ts
|
|
17103
|
+
function edgeLimit(value) {
|
|
17104
|
+
if (value === null || value === void 0 || !Number.isFinite(value)) {
|
|
17105
|
+
return DEFAULT_CODEBASE_EDIT_CONTEXT_EDGE_LIMIT;
|
|
17106
|
+
}
|
|
17107
|
+
return Math.min(
|
|
17108
|
+
MAX_CODEBASE_EDIT_CONTEXT_EDGE_LIMIT,
|
|
17109
|
+
Math.max(MIN_CODEBASE_EDIT_CONTEXT_EDGE_LIMIT, Math.floor(value))
|
|
17110
|
+
);
|
|
17111
|
+
}
|
|
17112
|
+
function normalizedPath(value) {
|
|
17113
|
+
return value.replaceAll("\\", "/").replace(/^\.\//, "");
|
|
17114
|
+
}
|
|
17115
|
+
function pathsMatch(left, right) {
|
|
17116
|
+
const normalizedLeft = normalizedPath(left);
|
|
17117
|
+
const normalizedRight = normalizedPath(right);
|
|
17118
|
+
return normalizedLeft === normalizedRight || normalizedLeft.endsWith(`/${normalizedRight}`) || normalizedRight.endsWith(`/${normalizedLeft}`);
|
|
17119
|
+
}
|
|
17120
|
+
function targetSource(results, resolution) {
|
|
17121
|
+
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);
|
|
17122
|
+
}
|
|
17123
|
+
function formatSource(result) {
|
|
17124
|
+
const name = result.name ? ` ${result.name}` : "";
|
|
17125
|
+
return [
|
|
17126
|
+
"## Target implementation",
|
|
17127
|
+
`${result.filePath}:${result.startLine}-${result.endLine} (${result.chunkType}${name})`,
|
|
17128
|
+
"```",
|
|
17129
|
+
result.content,
|
|
17130
|
+
"```"
|
|
17131
|
+
].join("\n");
|
|
17132
|
+
}
|
|
17133
|
+
function formatCallers(edges) {
|
|
17134
|
+
if (edges.length === 0) return "## Direct callers\nNone found.";
|
|
17135
|
+
return [
|
|
17136
|
+
"## Direct callers",
|
|
17137
|
+
...edges.map((edge) => `- ${edge.fromSymbolName ?? "<unknown>"} at ${edge.fromSymbolFilePath ?? "<unknown file>"}:${edge.line} (${edge.callType}, ${edge.isResolved ? "resolved" : "unresolved"})`)
|
|
17138
|
+
].join("\n");
|
|
17139
|
+
}
|
|
17140
|
+
function formatCallees(edges, sourceFilePath) {
|
|
17141
|
+
if (edges.length === 0) return "## Direct callees\nNone found.";
|
|
17142
|
+
return [
|
|
17143
|
+
"## Direct callees",
|
|
17144
|
+
...edges.map((edge) => `- ${edge.targetName} from ${sourceFilePath}:${edge.line} (${edge.callType}, ${edge.isResolved ? "resolved" : "unresolved"})`)
|
|
17145
|
+
].join("\n");
|
|
17146
|
+
}
|
|
17147
|
+
function formatResolutionRisk(resolution) {
|
|
17148
|
+
if (resolution.status === "ambiguous") {
|
|
17149
|
+
const candidates = resolution.candidates.map((candidate) => `${candidate.filePath}:${candidate.startLine}`).join(", ");
|
|
17150
|
+
return `Risk: symbol "${resolution.name}" is ambiguous. Pass filePath to select a target.${candidates ? ` Candidates: ${candidates}.` : ""}`;
|
|
17151
|
+
}
|
|
17152
|
+
if (resolution.filePath && resolution.totalCandidates > 0) {
|
|
17153
|
+
return `Risk: symbol "${resolution.name}" did not resolve at filePath="${resolution.filePath}". Review the conceptual evidence before editing.`;
|
|
17154
|
+
}
|
|
17155
|
+
return `Risk: symbol "${resolution.name}" could not be resolved. Review the conceptual evidence before editing.`;
|
|
17156
|
+
}
|
|
17157
|
+
async function fallbackPack(dependencies, query, risk, resolution, tokenBudget, candidateSource = []) {
|
|
17158
|
+
const conceptual = await dependencies.searchCodebase(query, { limit: 5 });
|
|
17159
|
+
const pack = buildContextPack([...candidateSource, ...conceptual], {
|
|
17160
|
+
tokenBudget: tokenBudget ?? void 0,
|
|
17161
|
+
heading: "## Conceptual evidence",
|
|
17162
|
+
maxResults: 5,
|
|
17163
|
+
includeExactSearchHandoff: false,
|
|
17164
|
+
preferImplementationPaths: true
|
|
17165
|
+
});
|
|
17166
|
+
const fitted = fitTextToContextBudget(`${risk}
|
|
17167
|
+
|
|
17168
|
+
${pack.text}`, tokenBudget ?? void 0);
|
|
17169
|
+
return {
|
|
17170
|
+
text: fitted.text,
|
|
17171
|
+
details: {
|
|
17172
|
+
resolution,
|
|
17173
|
+
tokenBudget: fitted.tokenBudget,
|
|
17174
|
+
tokenEstimate: fitted.tokenEstimate,
|
|
17175
|
+
truncated: fitted.truncated,
|
|
17176
|
+
sourceIncluded: candidateSource.length > 0,
|
|
17177
|
+
callerCount: 0,
|
|
17178
|
+
calleeCount: 0
|
|
17179
|
+
}
|
|
17180
|
+
};
|
|
17181
|
+
}
|
|
17182
|
+
async function resolveCodebaseEditContextWithDependencies(input, dependencies) {
|
|
17183
|
+
const symbol = input.symbol?.trim();
|
|
17184
|
+
if (!symbol) {
|
|
17185
|
+
return fallbackPack(
|
|
17186
|
+
dependencies,
|
|
17187
|
+
input.query,
|
|
17188
|
+
"Risk: no authoritative symbol was supplied. Review the conceptual evidence before editing.",
|
|
17189
|
+
"not_requested",
|
|
17190
|
+
input.tokenBudget
|
|
17191
|
+
);
|
|
17192
|
+
}
|
|
17193
|
+
let callersResult;
|
|
17194
|
+
try {
|
|
17195
|
+
callersResult = await dependencies.getCallGraphData({
|
|
17196
|
+
name: symbol,
|
|
17197
|
+
filePath: input.filePath ?? void 0,
|
|
17198
|
+
direction: "callers"
|
|
17199
|
+
});
|
|
17200
|
+
} catch (error) {
|
|
17201
|
+
const candidates = await dependencies.implementationLookup(symbol, { limit: 5 });
|
|
17202
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
17203
|
+
return fallbackPack(
|
|
17204
|
+
dependencies,
|
|
17205
|
+
input.query,
|
|
17206
|
+
`Risk: graph data is unavailable (${message}). Target and dependencies are not graph-verified.`,
|
|
17207
|
+
"graph_unavailable",
|
|
17208
|
+
input.tokenBudget,
|
|
17209
|
+
candidates
|
|
17210
|
+
);
|
|
17211
|
+
}
|
|
17212
|
+
if (callersResult.resolution.status !== "resolved") {
|
|
17213
|
+
return fallbackPack(
|
|
17214
|
+
dependencies,
|
|
17215
|
+
input.query,
|
|
17216
|
+
formatResolutionRisk(callersResult.resolution),
|
|
17217
|
+
callersResult.resolution.status,
|
|
17218
|
+
input.tokenBudget
|
|
17219
|
+
);
|
|
17220
|
+
}
|
|
17221
|
+
const resolution = callersResult.resolution;
|
|
17222
|
+
const [definitionsResult, calleesResult] = await Promise.allSettled([
|
|
17223
|
+
dependencies.implementationLookup(symbol, { limit: 10 }),
|
|
17224
|
+
dependencies.getCallGraphData({
|
|
17225
|
+
name: symbol,
|
|
17226
|
+
filePath: input.filePath ?? resolution.filePath,
|
|
17227
|
+
direction: "callees"
|
|
17228
|
+
})
|
|
17229
|
+
]);
|
|
17230
|
+
if (definitionsResult.status === "rejected") throw definitionsResult.reason;
|
|
17231
|
+
let graphRisk;
|
|
17232
|
+
let callees = [];
|
|
17233
|
+
if (calleesResult.status === "rejected") {
|
|
17234
|
+
const message = calleesResult.reason instanceof Error ? calleesResult.reason.message : String(calleesResult.reason);
|
|
17235
|
+
graphRisk = `Risk: callee graph data is unavailable (${message}). Dependency evidence is incomplete.`;
|
|
17236
|
+
} else if (calleesResult.value.resolution.status !== "resolved") {
|
|
17237
|
+
graphRisk = "Risk: the target resolved for callers but not callees. Dependency evidence is incomplete.";
|
|
17238
|
+
} else {
|
|
17239
|
+
callees = calleesResult.value.callees.slice(0, edgeLimit(input.calleeLimit));
|
|
17240
|
+
}
|
|
17241
|
+
const source = targetSource(definitionsResult.value, resolution);
|
|
17242
|
+
const callers = callersResult.callers.slice(0, edgeLimit(input.callerLimit));
|
|
17243
|
+
const sourceBudget = Math.max(
|
|
17244
|
+
MIN_CONTEXT_PACK_TOKEN_BUDGET,
|
|
17245
|
+
Math.floor((input.tokenBudget ?? DEFAULT_CONTEXT_PACK_TOKEN_BUDGET) * 0.6)
|
|
17246
|
+
);
|
|
17247
|
+
const sourceText = source ? fitTextToContextBudget(formatSource(source), sourceBudget).text : `## Target implementation
|
|
17248
|
+
Risk: no implementation source matched the resolved target at ${resolution.filePath}:${resolution.startLine}.`;
|
|
17249
|
+
const fitted = fitTextToContextBudget([
|
|
17250
|
+
`# Pre-edit context for ${resolution.name}`,
|
|
17251
|
+
graphRisk,
|
|
17252
|
+
sourceText,
|
|
17253
|
+
formatCallers(callers),
|
|
17254
|
+
formatCallees(callees, resolution.filePath)
|
|
17255
|
+
].filter((section) => section !== void 0).join("\n\n"), input.tokenBudget ?? void 0);
|
|
17256
|
+
return {
|
|
17257
|
+
text: fitted.text,
|
|
17258
|
+
details: {
|
|
17259
|
+
resolution: "resolved",
|
|
17260
|
+
tokenBudget: fitted.tokenBudget,
|
|
17261
|
+
tokenEstimate: fitted.tokenEstimate,
|
|
17262
|
+
truncated: fitted.truncated,
|
|
17263
|
+
sourceIncluded: source !== void 0,
|
|
17264
|
+
callerCount: callers.length,
|
|
17265
|
+
calleeCount: callees.length
|
|
17266
|
+
}
|
|
17267
|
+
};
|
|
17268
|
+
}
|
|
17269
|
+
async function resolveCodebaseEditContext(projectRoot, host, input) {
|
|
17270
|
+
return resolveCodebaseEditContextWithDependencies(input, {
|
|
17271
|
+
searchCodebase: (query, options) => searchCodebase(projectRoot, host, query, options),
|
|
17272
|
+
implementationLookup: (query, options) => implementationLookup(projectRoot, host, query, options),
|
|
17273
|
+
getCallGraphData: (params) => getCallGraphData(projectRoot, host, params)
|
|
17274
|
+
});
|
|
17275
|
+
}
|
|
17276
|
+
|
|
17051
17277
|
// src/tools/context-search.ts
|
|
17052
17278
|
var MIN_CONTEXT_RESULT_LIMIT = 1;
|
|
17053
17279
|
var MAX_CONTEXT_RESULT_LIMIT = 100;
|
|
@@ -17150,6 +17376,27 @@ function buildRecoveryDetails(attempts, successIndex) {
|
|
|
17150
17376
|
successfulAttemptIndex: successIndex
|
|
17151
17377
|
};
|
|
17152
17378
|
}
|
|
17379
|
+
function serializeAttempts(attempts) {
|
|
17380
|
+
return attempts.map((attempt) => ({
|
|
17381
|
+
kind: attempt.kind,
|
|
17382
|
+
scope: attempt.scope,
|
|
17383
|
+
resultCount: attempt.resultCount,
|
|
17384
|
+
relaxedFields: attempt.relaxedFields
|
|
17385
|
+
}));
|
|
17386
|
+
}
|
|
17387
|
+
function buildSearchDiagnostic(attempt) {
|
|
17388
|
+
if (!attempt) {
|
|
17389
|
+
return void 0;
|
|
17390
|
+
}
|
|
17391
|
+
return {
|
|
17392
|
+
route: attempt.kind,
|
|
17393
|
+
routedQuery: attempt.query,
|
|
17394
|
+
searchQuery: attempt.query,
|
|
17395
|
+
searchScope: attempt.scopeFilter,
|
|
17396
|
+
searchTrace: attempt.searchTrace,
|
|
17397
|
+
contextPackTrace: attempt.contextPackTrace
|
|
17398
|
+
};
|
|
17399
|
+
}
|
|
17153
17400
|
function trimOrUndefined2(value) {
|
|
17154
17401
|
const normalized = value?.trim();
|
|
17155
17402
|
if (!normalized) {
|
|
@@ -17189,6 +17436,7 @@ async function resolveSearchContext(input, operations) {
|
|
|
17189
17436
|
const hasFilters = Boolean(fileType || directory);
|
|
17190
17437
|
const relaxedFields = relaxedHintFields(fileType, directory);
|
|
17191
17438
|
const attempts = [];
|
|
17439
|
+
const attemptStates = [];
|
|
17192
17440
|
const decisions = {
|
|
17193
17441
|
inferredDefinitionMiss: false,
|
|
17194
17442
|
fallbackFromOriginalConceptualToInferred: false,
|
|
@@ -17217,8 +17465,20 @@ async function resolveSearchContext(input, operations) {
|
|
|
17217
17465
|
if (seenAttempts.has(key)) {
|
|
17218
17466
|
return [];
|
|
17219
17467
|
}
|
|
17220
|
-
const
|
|
17468
|
+
const attemptState = {
|
|
17469
|
+
kind,
|
|
17470
|
+
scope: describeScope(scope.fileType, scope.directory),
|
|
17471
|
+
resultCount: 0,
|
|
17472
|
+
relaxedFields: [...relaxedFieldsForAttempt],
|
|
17473
|
+
query: attemptQuery,
|
|
17474
|
+
scopeFilter: scope
|
|
17475
|
+
};
|
|
17476
|
+
const results = await runAttempt((trace) => {
|
|
17477
|
+
attemptState.searchTrace = trace;
|
|
17478
|
+
});
|
|
17479
|
+
attemptState.resultCount = results.length;
|
|
17221
17480
|
seenAttempts.add(key);
|
|
17481
|
+
attemptStates.push(attemptState);
|
|
17222
17482
|
attempts.push({
|
|
17223
17483
|
kind,
|
|
17224
17484
|
scope: describeScope(scope.fileType, scope.directory),
|
|
@@ -17238,7 +17498,7 @@ async function resolveSearchContext(input, operations) {
|
|
|
17238
17498
|
symbol,
|
|
17239
17499
|
scope,
|
|
17240
17500
|
relaxedFieldsForAttempt,
|
|
17241
|
-
() => operations.lookup(symbol, MAX_CONTEXT_RESULT_LIMIT, scope)
|
|
17501
|
+
(trace) => operations.lookup(symbol, MAX_CONTEXT_RESULT_LIMIT, scope, input.diagnostic ? trace : void 0)
|
|
17242
17502
|
);
|
|
17243
17503
|
};
|
|
17244
17504
|
const tryConceptualSearch = async (searchQuery, scope, relaxedFieldsForAttempt) => {
|
|
@@ -17247,13 +17507,23 @@ async function resolveSearchContext(input, operations) {
|
|
|
17247
17507
|
searchQuery,
|
|
17248
17508
|
scope,
|
|
17249
17509
|
relaxedFieldsForAttempt,
|
|
17250
|
-
() => operations.search(searchQuery, MAX_CONTEXT_RESULT_LIMIT, scope)
|
|
17510
|
+
(trace) => operations.search(searchQuery, MAX_CONTEXT_RESULT_LIMIT, scope, input.diagnostic ? trace : void 0)
|
|
17251
17511
|
);
|
|
17252
17512
|
};
|
|
17253
|
-
const
|
|
17513
|
+
const findSuccessfulAttemptState = (route) => {
|
|
17514
|
+
for (let index = attemptStates.length - 1; index >= 0; index -= 1) {
|
|
17515
|
+
const attempt = attemptStates[index];
|
|
17516
|
+
if (attempt.kind === route && attempt.resultCount > 0) {
|
|
17517
|
+
return attempt;
|
|
17518
|
+
}
|
|
17519
|
+
}
|
|
17520
|
+
return void 0;
|
|
17521
|
+
};
|
|
17522
|
+
const toResult = (route, routedQuery, pack, successfulAttempt) => {
|
|
17254
17523
|
const base = packedResult(route, routedQuery, pack);
|
|
17255
17524
|
const baseDetails = base.details;
|
|
17256
17525
|
const successIndex = findSuccessfulAttemptIndex(route, attempts);
|
|
17526
|
+
const successState = successfulAttempt ?? findSuccessfulAttemptState(route);
|
|
17257
17527
|
return {
|
|
17258
17528
|
text: base.text,
|
|
17259
17529
|
details: {
|
|
@@ -17261,7 +17531,10 @@ async function resolveSearchContext(input, operations) {
|
|
|
17261
17531
|
tokenBudget: baseDetails.tokenBudget,
|
|
17262
17532
|
tokenEstimate: baseDetails.tokenEstimate,
|
|
17263
17533
|
truncated: false,
|
|
17264
|
-
recovery: buildRecoveryDetails(
|
|
17534
|
+
recovery: buildRecoveryDetails(serializeAttempts(attemptStates), successIndex),
|
|
17535
|
+
...input.diagnostic && {
|
|
17536
|
+
diagnostic: buildSearchDiagnostic(successState)
|
|
17537
|
+
}
|
|
17265
17538
|
}
|
|
17266
17539
|
};
|
|
17267
17540
|
};
|
|
@@ -17275,8 +17548,18 @@ async function resolveSearchContext(input, operations) {
|
|
|
17275
17548
|
buildContextPack(scopedDefinitionResults, {
|
|
17276
17549
|
tokenBudget,
|
|
17277
17550
|
maxResults: limit,
|
|
17278
|
-
heading
|
|
17279
|
-
|
|
17551
|
+
heading,
|
|
17552
|
+
preserveInputOrder: true,
|
|
17553
|
+
...input.diagnostic ? {
|
|
17554
|
+
trace: (trace) => {
|
|
17555
|
+
const attemptState = findSuccessfulAttemptState("definition");
|
|
17556
|
+
if (attemptState) {
|
|
17557
|
+
attemptState.contextPackTrace = trace;
|
|
17558
|
+
}
|
|
17559
|
+
}
|
|
17560
|
+
} : void 0
|
|
17561
|
+
}),
|
|
17562
|
+
findSuccessfulAttemptState("definition")
|
|
17280
17563
|
);
|
|
17281
17564
|
}
|
|
17282
17565
|
if (explicitSymbol) {
|
|
@@ -17294,8 +17577,18 @@ async function resolveSearchContext(input, operations) {
|
|
|
17294
17577
|
buildContextPack(unscopedDefinitionResults, {
|
|
17295
17578
|
tokenBudget,
|
|
17296
17579
|
maxResults: limit,
|
|
17297
|
-
heading: heading2
|
|
17298
|
-
|
|
17580
|
+
heading: heading2,
|
|
17581
|
+
preserveInputOrder: true,
|
|
17582
|
+
...input.diagnostic ? {
|
|
17583
|
+
trace: (trace) => {
|
|
17584
|
+
const attemptState = findSuccessfulAttemptState("definition");
|
|
17585
|
+
if (attemptState) {
|
|
17586
|
+
attemptState.contextPackTrace = trace;
|
|
17587
|
+
}
|
|
17588
|
+
}
|
|
17589
|
+
} : void 0
|
|
17590
|
+
}),
|
|
17591
|
+
findSuccessfulAttemptState("definition")
|
|
17299
17592
|
);
|
|
17300
17593
|
}
|
|
17301
17594
|
}
|
|
@@ -17314,7 +17607,10 @@ Explicit symbol lookup only; conceptual search was not attempted.`
|
|
|
17314
17607
|
tokenBudget: heading.tokenBudget,
|
|
17315
17608
|
tokenEstimate: heading.tokenEstimate,
|
|
17316
17609
|
truncated: heading.truncated,
|
|
17317
|
-
recovery: buildRecoveryDetails(
|
|
17610
|
+
recovery: buildRecoveryDetails(serializeAttempts(attemptStates), null),
|
|
17611
|
+
...input.diagnostic && {
|
|
17612
|
+
diagnostic: buildSearchDiagnostic(attemptStates[attemptStates.length - 1])
|
|
17613
|
+
}
|
|
17318
17614
|
}
|
|
17319
17615
|
};
|
|
17320
17616
|
}
|
|
@@ -17354,8 +17650,17 @@ Explicit symbol lookup only; conceptual search was not attempted.`
|
|
|
17354
17650
|
maxResults: limit,
|
|
17355
17651
|
heading,
|
|
17356
17652
|
includeExactSearchHandoff: true,
|
|
17357
|
-
preferImplementationPaths: intent.preferSourcePaths || intent.primary !== "docs" && intent.primary !== "test"
|
|
17358
|
-
|
|
17653
|
+
preferImplementationPaths: intent.preferSourcePaths || intent.primary !== "docs" && intent.primary !== "test",
|
|
17654
|
+
...input.diagnostic ? {
|
|
17655
|
+
trace: (trace) => {
|
|
17656
|
+
const attemptState = findSuccessfulAttemptState("conceptual");
|
|
17657
|
+
if (attemptState) {
|
|
17658
|
+
attemptState.contextPackTrace = trace;
|
|
17659
|
+
}
|
|
17660
|
+
}
|
|
17661
|
+
} : void 0
|
|
17662
|
+
}),
|
|
17663
|
+
findSuccessfulAttemptState("conceptual")
|
|
17359
17664
|
);
|
|
17360
17665
|
}
|
|
17361
17666
|
}
|
|
@@ -17371,7 +17676,10 @@ Explicit symbol lookup only; conceptual search was not attempted.`
|
|
|
17371
17676
|
tokenBudget: fallbackText.tokenBudget,
|
|
17372
17677
|
tokenEstimate: fallbackText.tokenEstimate,
|
|
17373
17678
|
truncated: fallbackText.truncated,
|
|
17374
|
-
recovery: buildRecoveryDetails(
|
|
17679
|
+
recovery: buildRecoveryDetails(serializeAttempts(attemptStates), null),
|
|
17680
|
+
...input.diagnostic && {
|
|
17681
|
+
diagnostic: buildSearchDiagnostic(attemptStates[attemptStates.length - 1])
|
|
17682
|
+
}
|
|
17375
17683
|
}
|
|
17376
17684
|
};
|
|
17377
17685
|
}
|
|
@@ -17452,17 +17760,27 @@ async function resolveCodebaseContextUnmeasured(projectRoot, host, input) {
|
|
|
17452
17760
|
details: fittedDetails("path", fitted, 0)
|
|
17453
17761
|
};
|
|
17454
17762
|
}
|
|
17455
|
-
return resolveSearchContext({
|
|
17456
|
-
|
|
17763
|
+
return resolveSearchContext({
|
|
17764
|
+
query: input.query,
|
|
17765
|
+
symbol,
|
|
17766
|
+
limit,
|
|
17767
|
+
tokenBudget,
|
|
17768
|
+
fileType,
|
|
17769
|
+
directory,
|
|
17770
|
+
diagnostic: input.diagnostic
|
|
17771
|
+
}, {
|
|
17772
|
+
lookup: (lookupSymbol, retrievalLimit, scope, trace) => implementationLookup(projectRoot, host, lookupSymbol, {
|
|
17457
17773
|
limit: retrievalLimit,
|
|
17458
17774
|
fileType: scope.fileType,
|
|
17459
|
-
directory: scope.directory
|
|
17775
|
+
directory: scope.directory,
|
|
17776
|
+
trace
|
|
17460
17777
|
}),
|
|
17461
|
-
search: (queryText, retrievalLimit, scope) => searchCodebase(projectRoot, host, queryText, {
|
|
17778
|
+
search: (queryText, retrievalLimit, scope, trace) => searchCodebase(projectRoot, host, queryText, {
|
|
17462
17779
|
limit: retrievalLimit,
|
|
17463
17780
|
fileType: scope.fileType,
|
|
17464
17781
|
directory: scope.directory,
|
|
17465
|
-
metadataOnly: true
|
|
17782
|
+
metadataOnly: true,
|
|
17783
|
+
trace
|
|
17466
17784
|
})
|
|
17467
17785
|
});
|
|
17468
17786
|
}
|
|
@@ -17529,7 +17847,11 @@ async function resolveCodebaseContext(projectRoot, host, input) {
|
|
|
17529
17847
|
|
|
17530
17848
|
// src/tools/execute-common.ts
|
|
17531
17849
|
async function executeCodebaseContext(projectRoot, host, args) {
|
|
17532
|
-
|
|
17850
|
+
const result = await resolveCodebaseContext(projectRoot, host, args);
|
|
17851
|
+
return { text: result.text, details: result.details };
|
|
17852
|
+
}
|
|
17853
|
+
async function executeCodebaseEditContext(projectRoot, host, args) {
|
|
17854
|
+
return { text: (await resolveCodebaseEditContext(projectRoot, host, args)).text };
|
|
17533
17855
|
}
|
|
17534
17856
|
async function executeIndexCodebase(projectRoot, host, args, onProgress) {
|
|
17535
17857
|
const result = await runIndexCodebase(projectRoot, host, args, onProgress);
|
|
@@ -17632,9 +17954,9 @@ function parseGitActivity(output) {
|
|
|
17632
17954
|
if (!filePath || addedRaw === "-" || deletedRaw === "-") continue;
|
|
17633
17955
|
const churn = Number(addedRaw) + Number(deletedRaw);
|
|
17634
17956
|
if (!Number.isFinite(churn) || churn <= 0) continue;
|
|
17635
|
-
const
|
|
17636
|
-
const previous = activity.get(
|
|
17637
|
-
activity.set(
|
|
17957
|
+
const normalizedPath2 = normalizePath3(filePath);
|
|
17958
|
+
const previous = activity.get(normalizedPath2);
|
|
17959
|
+
activity.set(normalizedPath2, {
|
|
17638
17960
|
churn: (previous?.churn ?? 0) + churn,
|
|
17639
17961
|
commits: (previous?.commits ?? 0) + 1,
|
|
17640
17962
|
latestDate: previous?.latestDate ?? latestDate,
|
|
@@ -18224,8 +18546,8 @@ function transformForVisualization(symbols, edges, options = {}) {
|
|
|
18224
18546
|
const normalizedAbsoluteSuffix = `/${normalizedDirWithSlash}`;
|
|
18225
18547
|
filteredSymbols = symbols.filter(
|
|
18226
18548
|
(s) => {
|
|
18227
|
-
const
|
|
18228
|
-
return
|
|
18549
|
+
const normalizedPath2 = s.filePath.replace(/\\/g, "/");
|
|
18550
|
+
return normalizedPath2 === normalizedDir || normalizedPath2.startsWith(normalizedDirWithSlash) || normalizedPath2.endsWith(`/${normalizedDir}`) || normalizedPath2.includes(normalizedAbsoluteSuffix);
|
|
18229
18551
|
}
|
|
18230
18552
|
);
|
|
18231
18553
|
}
|
|
@@ -18299,6 +18621,26 @@ var z3 = tool.schema;
|
|
|
18299
18621
|
var DEFAULT_HOST = "opencode";
|
|
18300
18622
|
var CHUNK_TYPE_VALUES = CHUNK_TYPES;
|
|
18301
18623
|
var RELATIONSHIP_TYPE_VALUES = RELATIONSHIP_TYPES;
|
|
18624
|
+
function stableSortedDiagnosticValue(value) {
|
|
18625
|
+
if (Array.isArray(value)) {
|
|
18626
|
+
return value.map((item) => stableSortedDiagnosticValue(item));
|
|
18627
|
+
}
|
|
18628
|
+
if (value === null || typeof value !== "object") {
|
|
18629
|
+
return value;
|
|
18630
|
+
}
|
|
18631
|
+
const entries = Object.entries(value).sort(([left], [right]) => left.localeCompare(right));
|
|
18632
|
+
const sorted = {};
|
|
18633
|
+
for (const [key, item] of entries) {
|
|
18634
|
+
sorted[key] = stableSortedDiagnosticValue(item);
|
|
18635
|
+
}
|
|
18636
|
+
return sorted;
|
|
18637
|
+
}
|
|
18638
|
+
function formatCodebaseContextDiagnostic(details) {
|
|
18639
|
+
const sorted = stableSortedDiagnosticValue(details);
|
|
18640
|
+
return `
|
|
18641
|
+
Diagnostics:
|
|
18642
|
+
${JSON.stringify(sorted, null, 2)}`;
|
|
18643
|
+
}
|
|
18302
18644
|
function initializeTools2(projectRoot, config) {
|
|
18303
18645
|
initializeTools(projectRoot, config, DEFAULT_HOST);
|
|
18304
18646
|
}
|
|
@@ -18318,10 +18660,29 @@ var codebase_context = tool({
|
|
|
18318
18660
|
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})`),
|
|
18319
18661
|
fileType: z3.string().nullable().optional().describe("Filter by file extension"),
|
|
18320
18662
|
directory: z3.string().nullable().optional().describe("Filter by directory path"),
|
|
18321
|
-
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})`)
|
|
18663
|
+
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})`),
|
|
18664
|
+
diagnostic: z3.boolean().optional().describe("Collect diagnostic routing and search traces without changing normal text output.")
|
|
18665
|
+
},
|
|
18666
|
+
async execute(args, context) {
|
|
18667
|
+
const result = await executeCodebaseContext(context?.worktree, DEFAULT_HOST, args);
|
|
18668
|
+
if (!args.diagnostic || !result.details?.diagnostic) {
|
|
18669
|
+
return result.text;
|
|
18670
|
+
}
|
|
18671
|
+
return `${result.text}${formatCodebaseContextDiagnostic(result.details.diagnostic)}`;
|
|
18672
|
+
}
|
|
18673
|
+
});
|
|
18674
|
+
var codebase_edit_context = tool({
|
|
18675
|
+
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.",
|
|
18676
|
+
args: {
|
|
18677
|
+
query: z3.string().describe("The requested change or target behavior"),
|
|
18678
|
+
symbol: z3.string().nullable().optional().describe("Authoritative target symbol when known"),
|
|
18679
|
+
filePath: z3.string().nullable().optional().describe("Optional file path used to disambiguate duplicate symbol names"),
|
|
18680
|
+
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),
|
|
18681
|
+
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),
|
|
18682
|
+
tokenBudget: z3.number().int().min(MIN_CONTEXT_PACK_TOKEN_BUDGET).max(MAX_CONTEXT_PACK_TOKEN_BUDGET).nullable().optional().default(DEFAULT_CONTEXT_PACK_TOKEN_BUDGET)
|
|
18322
18683
|
},
|
|
18323
18684
|
async execute(args, context) {
|
|
18324
|
-
return (await
|
|
18685
|
+
return (await executeCodebaseEditContext(context?.worktree, DEFAULT_HOST, args)).text;
|
|
18325
18686
|
}
|
|
18326
18687
|
});
|
|
18327
18688
|
var codebase_peek = tool({
|
|
@@ -18578,6 +18939,7 @@ var index_visualize = tool({
|
|
|
18578
18939
|
// src/tools/tool-names.ts
|
|
18579
18940
|
var TOOL_NAME = {
|
|
18580
18941
|
CODEBASE_CONTEXT: "codebase_context",
|
|
18942
|
+
CODEBASE_EDIT_CONTEXT: "codebase_edit_context",
|
|
18581
18943
|
CODEBASE_SEARCH: "codebase_search",
|
|
18582
18944
|
CODEBASE_PEEK: "codebase_peek",
|
|
18583
18945
|
FIND_SIMILAR: "find_similar",
|
|
@@ -18601,6 +18963,7 @@ var TOOL_NAME = {
|
|
|
18601
18963
|
};
|
|
18602
18964
|
var PORTABLE_TOOL_NAMES = [
|
|
18603
18965
|
TOOL_NAME.CODEBASE_CONTEXT,
|
|
18966
|
+
TOOL_NAME.CODEBASE_EDIT_CONTEXT,
|
|
18604
18967
|
TOOL_NAME.CODEBASE_SEARCH,
|
|
18605
18968
|
TOOL_NAME.CODEBASE_PEEK,
|
|
18606
18969
|
TOOL_NAME.INDEX_CODEBASE,
|
|
@@ -18617,6 +18980,7 @@ var PORTABLE_TOOL_NAMES = [
|
|
|
18617
18980
|
];
|
|
18618
18981
|
var OPENCODE_TOOL_NAMES = [
|
|
18619
18982
|
TOOL_NAME.CODEBASE_CONTEXT,
|
|
18983
|
+
TOOL_NAME.CODEBASE_EDIT_CONTEXT,
|
|
18620
18984
|
TOOL_NAME.CODEBASE_SEARCH,
|
|
18621
18985
|
TOOL_NAME.CODEBASE_PEEK,
|
|
18622
18986
|
TOOL_NAME.INDEX_CODEBASE,
|
|
@@ -18637,6 +19001,7 @@ var OPENCODE_TOOL_NAMES = [
|
|
|
18637
19001
|
];
|
|
18638
19002
|
var PI_TOOL_NAMES = [
|
|
18639
19003
|
TOOL_NAME.CODEBASE_CONTEXT,
|
|
19004
|
+
TOOL_NAME.CODEBASE_EDIT_CONTEXT,
|
|
18640
19005
|
TOOL_NAME.CODEBASE_SEARCH,
|
|
18641
19006
|
TOOL_NAME.CODEBASE_PEEK,
|
|
18642
19007
|
TOOL_NAME.FIND_SIMILAR,
|
|
@@ -19090,6 +19455,7 @@ var plugin = async ({ directory, worktree }) => {
|
|
|
19090
19455
|
return {
|
|
19091
19456
|
tool: {
|
|
19092
19457
|
[TOOL_NAME.CODEBASE_CONTEXT]: codebase_context,
|
|
19458
|
+
[TOOL_NAME.CODEBASE_EDIT_CONTEXT]: codebase_edit_context,
|
|
19093
19459
|
[TOOL_NAME.CODEBASE_SEARCH]: codebase_search,
|
|
19094
19460
|
[TOOL_NAME.CODEBASE_PEEK]: codebase_peek,
|
|
19095
19461
|
[TOOL_NAME.INDEX_CODEBASE]: index_codebase,
|