opencode-codebase-index 0.22.3 → 0.22.5
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 +681 -97
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +681 -97
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +455 -58
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +455 -58
- package/dist/index.js.map +1 -1
- package/dist/pi-extension.cjs +435 -51
- package/dist/pi-extension.cjs.map +1 -1
- package/dist/pi-extension.js +435 -51
- 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/pi-extension.cjs
CHANGED
|
@@ -2053,6 +2053,9 @@ function findKnowledgeBasePathIndex(knowledgeBases, inputPath, projectRoot3) {
|
|
|
2053
2053
|
}
|
|
2054
2054
|
|
|
2055
2055
|
// src/tools/contracts.ts
|
|
2056
|
+
var MIN_CODEBASE_EDIT_CONTEXT_EDGE_LIMIT = 1;
|
|
2057
|
+
var MAX_CODEBASE_EDIT_CONTEXT_EDGE_LIMIT = 20;
|
|
2058
|
+
var DEFAULT_CODEBASE_EDIT_CONTEXT_EDGE_LIMIT = 5;
|
|
2056
2059
|
var CODE_COMMUNITIES_MIN_SIZE = 1;
|
|
2057
2060
|
var CODE_COMMUNITIES_DEFAULT_LIMIT = 20;
|
|
2058
2061
|
var CODE_COMMUNITIES_MAX_LIMIT = 100;
|
|
@@ -2676,6 +2679,16 @@ function compactEvidenceValue(value, maxChars) {
|
|
|
2676
2679
|
}
|
|
2677
2680
|
var MAX_EXACT_SEARCH_HANDOFF_NAMES = 3;
|
|
2678
2681
|
var MAX_EXACT_SEARCH_HANDOFF_NAME_CHARS = 64;
|
|
2682
|
+
function toContextPackTraceCandidate(result) {
|
|
2683
|
+
return {
|
|
2684
|
+
filePath: result.filePath,
|
|
2685
|
+
startLine: result.startLine,
|
|
2686
|
+
endLine: result.endLine,
|
|
2687
|
+
score: result.score,
|
|
2688
|
+
chunkType: result.chunkType,
|
|
2689
|
+
name: result.name
|
|
2690
|
+
};
|
|
2691
|
+
}
|
|
2679
2692
|
function formatExactSearchHandoff(results) {
|
|
2680
2693
|
const suggestedNames = [];
|
|
2681
2694
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -2724,13 +2737,13 @@ function buildContextPack(results, options = {}) {
|
|
|
2724
2737
|
const maxResults = Math.max(0, Math.floor(options.maxResults ?? results.length));
|
|
2725
2738
|
const includeExactSearchHandoff = options.includeExactSearchHandoff ?? false;
|
|
2726
2739
|
const candidateCount = results.length;
|
|
2727
|
-
const
|
|
2728
|
-
|
|
2729
|
-
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
);
|
|
2733
|
-
const
|
|
2740
|
+
const preserveInputOrder = options.preserveInputOrder ?? false;
|
|
2741
|
+
const ranked = preserveInputOrder ? results.map((result, originalIndex) => ({ result, originalIndex })) : rankContextCandidates(results, options.preferImplementationPaths ?? false);
|
|
2742
|
+
const rankedCandidates = ranked.map((entry) => toContextPackTraceCandidate(entry.result));
|
|
2743
|
+
const deduplicated = deduplicateContextCandidates(ranked);
|
|
2744
|
+
const deduplicatedCandidates = deduplicated.map((result) => toContextPackTraceCandidate(result));
|
|
2745
|
+
const diversified = preserveInputOrder ? deduplicated : diversifyContextCandidates(deduplicated);
|
|
2746
|
+
const diversifiedCandidates = diversified.map((result) => toContextPackTraceCandidate(result));
|
|
2734
2747
|
const duplicateCount = candidateCount - deduplicated.length;
|
|
2735
2748
|
const selectable = diversified.slice(0, maxResults);
|
|
2736
2749
|
const limitOmittedCount = deduplicated.length - selectable.length;
|
|
@@ -2763,6 +2776,15 @@ function buildContextPack(results, options = {}) {
|
|
|
2763
2776
|
const fitted = fitTextToContextBudget(text3, tokenBudget);
|
|
2764
2777
|
const budgetOmittedCount = selectable.length - selected.length;
|
|
2765
2778
|
const omittedCount = candidateCount - selected.length;
|
|
2779
|
+
if (options.trace) {
|
|
2780
|
+
options.trace({
|
|
2781
|
+
inputCandidates: results.map(toContextPackTraceCandidate),
|
|
2782
|
+
rankedCandidates,
|
|
2783
|
+
deduplicatedCandidates,
|
|
2784
|
+
diversifiedCandidates,
|
|
2785
|
+
selectedCandidates: selected.map(toContextPackTraceCandidate)
|
|
2786
|
+
});
|
|
2787
|
+
}
|
|
2766
2788
|
return {
|
|
2767
2789
|
requestedTokenBudget,
|
|
2768
2790
|
tokenBudget,
|
|
@@ -8578,12 +8600,12 @@ function diversifyGroupBySymbol(entries, getCandidate) {
|
|
|
8578
8600
|
return [...primary, ...remainder];
|
|
8579
8601
|
}
|
|
8580
8602
|
function buildDiversityKey(metadata) {
|
|
8581
|
-
const
|
|
8603
|
+
const normalizedPath2 = metadata.filePath.toLowerCase();
|
|
8582
8604
|
const normalizedName = (metadata.name ?? "").trim().toLowerCase();
|
|
8583
8605
|
if (normalizedName.length > 0) {
|
|
8584
|
-
return `${
|
|
8606
|
+
return `${normalizedPath2}#${normalizedName}`;
|
|
8585
8607
|
}
|
|
8586
|
-
return
|
|
8608
|
+
return normalizedPath2;
|
|
8587
8609
|
}
|
|
8588
8610
|
function rankHybridResults(query, semanticResults, keywordResults, options) {
|
|
8589
8611
|
const prioritizeSourcePaths = options.prioritizeSourcePaths ?? classifyQueryIntentRaw(query) === "source";
|
|
@@ -8989,6 +9011,29 @@ function extractPrimaryIdentifierQueryHint(query) {
|
|
|
8989
9011
|
const best = codeTerms.find((term) => term.length >= 6);
|
|
8990
9012
|
return best ?? null;
|
|
8991
9013
|
}
|
|
9014
|
+
function pathSegmentsForAffinityMatch(filePath) {
|
|
9015
|
+
const normalizedPath2 = normalizeRankingText(filePath).replace(/\\/g, "/");
|
|
9016
|
+
const segments = normalizedPath2.split("/").filter((segment) => segment.length > 0);
|
|
9017
|
+
if (segments.length === 0) {
|
|
9018
|
+
return [];
|
|
9019
|
+
}
|
|
9020
|
+
const basename5 = segments[segments.length - 1] ?? "";
|
|
9021
|
+
const basenameWithoutExt = basename5.replace(/\.[^/.]+$/u, "");
|
|
9022
|
+
const normalizedSegments = segments.map((segment) => segment.toLowerCase());
|
|
9023
|
+
return Array.from(/* @__PURE__ */ new Set([
|
|
9024
|
+
...normalizedSegments,
|
|
9025
|
+
basenameWithoutExt.toLowerCase()
|
|
9026
|
+
]));
|
|
9027
|
+
}
|
|
9028
|
+
function hasModuleAffinity(filePath, exactIdentifierVariants) {
|
|
9029
|
+
const haystack = pathSegmentsForAffinityMatch(filePath);
|
|
9030
|
+
return exactIdentifierVariants.some((variant) => {
|
|
9031
|
+
if (!variant || variant.length < 2) {
|
|
9032
|
+
return false;
|
|
9033
|
+
}
|
|
9034
|
+
return haystack.includes(variant);
|
|
9035
|
+
});
|
|
9036
|
+
}
|
|
8992
9037
|
var FILE_PATH_HINT_EXTENSIONS = [
|
|
8993
9038
|
"ts",
|
|
8994
9039
|
"tsx",
|
|
@@ -9032,9 +9077,9 @@ function normalizeFilePathForHintMatch(filePath) {
|
|
|
9032
9077
|
return filePath.replace(/\\/g, "/").toLowerCase().replace(/^\.\//, "");
|
|
9033
9078
|
}
|
|
9034
9079
|
function pathMatchesHint(filePath, hint) {
|
|
9035
|
-
const
|
|
9080
|
+
const normalizedPath2 = normalizeFilePathForHintMatch(filePath);
|
|
9036
9081
|
const normalizedHint = normalizeFilePathForHintMatch(hint);
|
|
9037
|
-
return
|
|
9082
|
+
return normalizedPath2.endsWith(normalizedHint) || normalizedPath2.includes(`/${normalizedHint}`) || normalizedPath2.includes(normalizedHint);
|
|
9038
9083
|
}
|
|
9039
9084
|
function extractFilePathHint(query) {
|
|
9040
9085
|
const match = query.match(FILE_PATH_HINT_SUFFIX_REGEX);
|
|
@@ -9064,10 +9109,13 @@ function buildDeterministicIdentifierPass(query, candidates, limit, prioritizeSo
|
|
|
9064
9109
|
).map((candidate) => {
|
|
9065
9110
|
const nameLower = (candidate.metadata.name ?? "").toLowerCase();
|
|
9066
9111
|
const pathLower = candidate.metadata.filePath.toLowerCase();
|
|
9067
|
-
|
|
9068
|
-
const
|
|
9112
|
+
const exactIdentifierVariants = primaryVariants.filter((value) => value.length >= 2);
|
|
9113
|
+
const exactMatch = exactIdentifierVariants.some(
|
|
9069
9114
|
(variant) => nameLower === variant || nameLower.replace(/[^a-z0-9]/g, "") === variant.replace(/[^a-z0-9]/g, "")
|
|
9070
9115
|
);
|
|
9116
|
+
let maxMatch = 0;
|
|
9117
|
+
const nameMatchesPrimary = exactMatch;
|
|
9118
|
+
const pathAffinity = exactMatch ? hasModuleAffinity(candidate.metadata.filePath, exactIdentifierVariants) : false;
|
|
9071
9119
|
const pathMatchesFileHint = filePathHint ? pathMatchesHint(candidate.metadata.filePath, filePathHint) : false;
|
|
9072
9120
|
for (const hint of hints) {
|
|
9073
9121
|
const variants = normalizeIdentifierVariants(hint);
|
|
@@ -9088,12 +9136,17 @@ function buildDeterministicIdentifierPass(query, candidates, limit, prioritizeSo
|
|
|
9088
9136
|
candidate,
|
|
9089
9137
|
maxMatch,
|
|
9090
9138
|
pathMatchesFileHint,
|
|
9091
|
-
nameMatchesPrimary
|
|
9139
|
+
nameMatchesPrimary,
|
|
9140
|
+
pathAffinity
|
|
9092
9141
|
};
|
|
9093
9142
|
}).filter((entry) => entry.maxMatch >= 0.7).sort((a, b) => {
|
|
9094
9143
|
const aAnchored = a.pathMatchesFileHint && a.nameMatchesPrimary ? 1 : 0;
|
|
9095
9144
|
const bAnchored = b.pathMatchesFileHint && b.nameMatchesPrimary ? 1 : 0;
|
|
9096
9145
|
if (aAnchored !== bAnchored) return bAnchored - aAnchored;
|
|
9146
|
+
if (a.nameMatchesPrimary !== b.nameMatchesPrimary) {
|
|
9147
|
+
return b.nameMatchesPrimary ? 1 : -1;
|
|
9148
|
+
}
|
|
9149
|
+
if (a.pathAffinity !== b.pathAffinity) return b.pathAffinity ? 1 : -1;
|
|
9097
9150
|
if (b.maxMatch !== a.maxMatch) return b.maxMatch - a.maxMatch;
|
|
9098
9151
|
if (b.candidate.score !== a.candidate.score) return b.candidate.score - a.candidate.score;
|
|
9099
9152
|
return a.candidate.id.localeCompare(b.candidate.id);
|
|
@@ -12907,6 +12960,20 @@ var Indexer = class _Indexer {
|
|
|
12907
12960
|
requestedLimit = nextLimit;
|
|
12908
12961
|
}
|
|
12909
12962
|
}
|
|
12963
|
+
buildCandidateSnapshot(candidate) {
|
|
12964
|
+
return {
|
|
12965
|
+
id: candidate.id,
|
|
12966
|
+
filePath: candidate.metadata.filePath,
|
|
12967
|
+
startLine: candidate.metadata.startLine,
|
|
12968
|
+
endLine: candidate.metadata.endLine,
|
|
12969
|
+
score: candidate.score,
|
|
12970
|
+
chunkType: candidate.metadata.chunkType,
|
|
12971
|
+
name: candidate.metadata.name
|
|
12972
|
+
};
|
|
12973
|
+
}
|
|
12974
|
+
buildCandidateSnapshotList(candidates) {
|
|
12975
|
+
return candidates.map((candidate) => this.buildCandidateSnapshot(candidate));
|
|
12976
|
+
}
|
|
12910
12977
|
searchSemanticCandidates(store, embedding, initialLimit, branchChunkIds, shouldPrefilterByBranch) {
|
|
12911
12978
|
return this.searchCandidatesWithBranchPrefilter(
|
|
12912
12979
|
initialLimit,
|
|
@@ -13098,6 +13165,16 @@ var Indexer = class _Indexer {
|
|
|
13098
13165
|
prefilterMs: Math.round(prefilterMs * 100) / 100,
|
|
13099
13166
|
fusionMs: Math.round(fusionMs * 100) / 100
|
|
13100
13167
|
});
|
|
13168
|
+
if (options?.trace) {
|
|
13169
|
+
options.trace({
|
|
13170
|
+
semanticCandidates: this.buildCandidateSnapshotList(scopedSemanticCandidates),
|
|
13171
|
+
keywordCandidates: this.buildCandidateSnapshotList(scopedKeywordCandidates),
|
|
13172
|
+
hybridCandidates: this.buildCandidateSnapshotList(combined),
|
|
13173
|
+
postExternalRerankCandidates: this.buildCandidateSnapshotList(rerankedCombined),
|
|
13174
|
+
tieredCandidates: this.buildCandidateSnapshotList(tiered),
|
|
13175
|
+
finalCandidates: this.buildCandidateSnapshotList(finalResults)
|
|
13176
|
+
});
|
|
13177
|
+
}
|
|
13101
13178
|
const metadataOnly = options?.metadataOnly ?? false;
|
|
13102
13179
|
return Promise.all(
|
|
13103
13180
|
finalResults.map(async (r) => {
|
|
@@ -14358,7 +14435,8 @@ async function searchCodebase(projectRoot3, host, query, options = {}) {
|
|
|
14358
14435
|
definitionIntent: options.definitionIntent,
|
|
14359
14436
|
blameAuthor: options.blameAuthor,
|
|
14360
14437
|
blameSha: options.blameSha,
|
|
14361
|
-
blameSince: options.blameSince
|
|
14438
|
+
blameSince: options.blameSince,
|
|
14439
|
+
trace: options.trace
|
|
14362
14440
|
});
|
|
14363
14441
|
}
|
|
14364
14442
|
async function searchCodebaseWithEffectiveness(projectRoot3, host, route, query, options, render) {
|
|
@@ -14412,15 +14490,19 @@ async function implementationLookup(projectRoot3, host, query, options = {}) {
|
|
|
14412
14490
|
return indexer.search(query, options.limit, {
|
|
14413
14491
|
fileType: options.fileType,
|
|
14414
14492
|
directory: options.directory,
|
|
14415
|
-
definitionIntent: true
|
|
14493
|
+
definitionIntent: true,
|
|
14494
|
+
trace: options.trace
|
|
14416
14495
|
});
|
|
14417
14496
|
}
|
|
14418
14497
|
async function getCallGraphData(projectRoot3, host, params) {
|
|
14419
14498
|
await ensureAutoIndexReadyForRetrieval(projectRoot3, host);
|
|
14420
14499
|
const root = getProjectRoot(projectRoot3, host);
|
|
14421
14500
|
const indexer = getIndexerForProject(root, host);
|
|
14501
|
+
return getCallGraphDataForIndexer(indexer, root, params);
|
|
14502
|
+
}
|
|
14503
|
+
async function getCallGraphDataForIndexer(indexer, projectRoot3, params) {
|
|
14422
14504
|
const symbols = await indexer.getCallGraphSymbols();
|
|
14423
|
-
const resolution = resolveCallGraphSymbol(symbols,
|
|
14505
|
+
const resolution = resolveCallGraphSymbol(symbols, projectRoot3, params.name, params.filePath, params.symbolId);
|
|
14424
14506
|
const direction = params.direction === "callees" ? "callees" : "callers";
|
|
14425
14507
|
if (resolution.status !== "resolved") {
|
|
14426
14508
|
return { direction, resolution, callers: [], callees: [], relationshipType: params.relationshipType };
|
|
@@ -14648,17 +14730,17 @@ async function getIndexLogs(projectRoot3, host, args) {
|
|
|
14648
14730
|
function addKnowledgeBase(projectRoot3, host, knowledgeBasePath) {
|
|
14649
14731
|
const root = getProjectRoot(projectRoot3, host);
|
|
14650
14732
|
const inputPath = knowledgeBasePath.trim();
|
|
14651
|
-
const
|
|
14733
|
+
const normalizedPath2 = path20.resolve(
|
|
14652
14734
|
path20.isAbsolute(inputPath) ? inputPath : resolveKnowledgeBasePath(inputPath, root)
|
|
14653
14735
|
);
|
|
14654
|
-
if (!(0, import_fs13.existsSync)(
|
|
14655
|
-
return `Error: Directory does not exist: ${
|
|
14736
|
+
if (!(0, import_fs13.existsSync)(normalizedPath2)) {
|
|
14737
|
+
return `Error: Directory does not exist: ${normalizedPath2}`;
|
|
14656
14738
|
}
|
|
14657
14739
|
let realPath;
|
|
14658
14740
|
try {
|
|
14659
|
-
realPath = (0, import_fs13.realpathSync)(
|
|
14741
|
+
realPath = (0, import_fs13.realpathSync)(normalizedPath2);
|
|
14660
14742
|
} catch {
|
|
14661
|
-
return `Error: Cannot resolve path: ${
|
|
14743
|
+
return `Error: Cannot resolve path: ${normalizedPath2}`;
|
|
14662
14744
|
}
|
|
14663
14745
|
const blockedPrefixes = [
|
|
14664
14746
|
"/etc",
|
|
@@ -14681,34 +14763,34 @@ function addKnowledgeBase(projectRoot3, host, knowledgeBasePath) {
|
|
|
14681
14763
|
];
|
|
14682
14764
|
for (const prefix of blockedPrefixes) {
|
|
14683
14765
|
if (realPath === prefix || realPath.startsWith(`${prefix}/`)) {
|
|
14684
|
-
return `Error: Adding sensitive directory as knowledge base is not allowed: ${
|
|
14766
|
+
return `Error: Adding sensitive directory as knowledge base is not allowed: ${normalizedPath2}`;
|
|
14685
14767
|
}
|
|
14686
14768
|
}
|
|
14687
14769
|
for (const dotDir of sensitiveDotDirs) {
|
|
14688
14770
|
const sensitiveDir = path20.join(homeDir, dotDir);
|
|
14689
14771
|
if (sensitiveDir && (realPath === sensitiveDir || realPath.startsWith(`${sensitiveDir}/`))) {
|
|
14690
|
-
return `Error: Adding sensitive directory as knowledge base is not allowed: ${
|
|
14772
|
+
return `Error: Adding sensitive directory as knowledge base is not allowed: ${normalizedPath2}`;
|
|
14691
14773
|
}
|
|
14692
14774
|
}
|
|
14693
14775
|
try {
|
|
14694
|
-
const stat = (0, import_fs13.statSync)(
|
|
14776
|
+
const stat = (0, import_fs13.statSync)(normalizedPath2);
|
|
14695
14777
|
if (!stat.isDirectory()) {
|
|
14696
|
-
return `Error: Path is not a directory: ${
|
|
14778
|
+
return `Error: Path is not a directory: ${normalizedPath2}`;
|
|
14697
14779
|
}
|
|
14698
14780
|
} catch (error) {
|
|
14699
|
-
return `Error: Cannot access directory: ${
|
|
14781
|
+
return `Error: Cannot access directory: ${normalizedPath2} - ${error instanceof Error ? error.message : String(error)}`;
|
|
14700
14782
|
}
|
|
14701
14783
|
const config = loadEditableConfig(root, host);
|
|
14702
14784
|
const knowledgeBases = Array.isArray(config.knowledgeBases) ? config.knowledgeBases : [];
|
|
14703
|
-
const alreadyExists = hasMatchingKnowledgeBasePath(knowledgeBases,
|
|
14785
|
+
const alreadyExists = hasMatchingKnowledgeBasePath(knowledgeBases, normalizedPath2, root);
|
|
14704
14786
|
if (alreadyExists) {
|
|
14705
|
-
return `Knowledge base already configured: ${
|
|
14787
|
+
return `Knowledge base already configured: ${normalizedPath2}`;
|
|
14706
14788
|
}
|
|
14707
|
-
knowledgeBases.push(
|
|
14789
|
+
knowledgeBases.push(normalizedPath2);
|
|
14708
14790
|
config.knowledgeBases = knowledgeBases;
|
|
14709
14791
|
saveConfig(root, config, host);
|
|
14710
14792
|
refreshIndexerForDirectory(root, host);
|
|
14711
|
-
let result = `${
|
|
14793
|
+
let result = `${normalizedPath2}
|
|
14712
14794
|
`;
|
|
14713
14795
|
result += `Total knowledge bases: ${knowledgeBases.length}
|
|
14714
14796
|
`;
|
|
@@ -14883,6 +14965,27 @@ function buildRecoveryDetails(attempts, successIndex) {
|
|
|
14883
14965
|
successfulAttemptIndex: successIndex
|
|
14884
14966
|
};
|
|
14885
14967
|
}
|
|
14968
|
+
function serializeAttempts(attempts) {
|
|
14969
|
+
return attempts.map((attempt) => ({
|
|
14970
|
+
kind: attempt.kind,
|
|
14971
|
+
scope: attempt.scope,
|
|
14972
|
+
resultCount: attempt.resultCount,
|
|
14973
|
+
relaxedFields: attempt.relaxedFields
|
|
14974
|
+
}));
|
|
14975
|
+
}
|
|
14976
|
+
function buildSearchDiagnostic(attempt) {
|
|
14977
|
+
if (!attempt) {
|
|
14978
|
+
return void 0;
|
|
14979
|
+
}
|
|
14980
|
+
return {
|
|
14981
|
+
route: attempt.kind,
|
|
14982
|
+
routedQuery: attempt.query,
|
|
14983
|
+
searchQuery: attempt.query,
|
|
14984
|
+
searchScope: attempt.scopeFilter,
|
|
14985
|
+
searchTrace: attempt.searchTrace,
|
|
14986
|
+
contextPackTrace: attempt.contextPackTrace
|
|
14987
|
+
};
|
|
14988
|
+
}
|
|
14886
14989
|
function trimOrUndefined2(value) {
|
|
14887
14990
|
const normalized = value?.trim();
|
|
14888
14991
|
if (!normalized) {
|
|
@@ -14922,6 +15025,7 @@ async function resolveSearchContext(input, operations) {
|
|
|
14922
15025
|
const hasFilters = Boolean(fileType || directory);
|
|
14923
15026
|
const relaxedFields = relaxedHintFields(fileType, directory);
|
|
14924
15027
|
const attempts = [];
|
|
15028
|
+
const attemptStates = [];
|
|
14925
15029
|
const decisions = {
|
|
14926
15030
|
inferredDefinitionMiss: false,
|
|
14927
15031
|
fallbackFromOriginalConceptualToInferred: false,
|
|
@@ -14950,8 +15054,20 @@ async function resolveSearchContext(input, operations) {
|
|
|
14950
15054
|
if (seenAttempts.has(key)) {
|
|
14951
15055
|
return [];
|
|
14952
15056
|
}
|
|
14953
|
-
const
|
|
15057
|
+
const attemptState = {
|
|
15058
|
+
kind,
|
|
15059
|
+
scope: describeScope(scope.fileType, scope.directory),
|
|
15060
|
+
resultCount: 0,
|
|
15061
|
+
relaxedFields: [...relaxedFieldsForAttempt],
|
|
15062
|
+
query: attemptQuery,
|
|
15063
|
+
scopeFilter: scope
|
|
15064
|
+
};
|
|
15065
|
+
const results = await runAttempt((trace) => {
|
|
15066
|
+
attemptState.searchTrace = trace;
|
|
15067
|
+
});
|
|
15068
|
+
attemptState.resultCount = results.length;
|
|
14954
15069
|
seenAttempts.add(key);
|
|
15070
|
+
attemptStates.push(attemptState);
|
|
14955
15071
|
attempts.push({
|
|
14956
15072
|
kind,
|
|
14957
15073
|
scope: describeScope(scope.fileType, scope.directory),
|
|
@@ -14971,7 +15087,7 @@ async function resolveSearchContext(input, operations) {
|
|
|
14971
15087
|
symbol,
|
|
14972
15088
|
scope,
|
|
14973
15089
|
relaxedFieldsForAttempt,
|
|
14974
|
-
() => operations.lookup(symbol, MAX_CONTEXT_RESULT_LIMIT, scope)
|
|
15090
|
+
(trace) => operations.lookup(symbol, MAX_CONTEXT_RESULT_LIMIT, scope, input.diagnostic ? trace : void 0)
|
|
14975
15091
|
);
|
|
14976
15092
|
};
|
|
14977
15093
|
const tryConceptualSearch = async (searchQuery, scope, relaxedFieldsForAttempt) => {
|
|
@@ -14980,13 +15096,23 @@ async function resolveSearchContext(input, operations) {
|
|
|
14980
15096
|
searchQuery,
|
|
14981
15097
|
scope,
|
|
14982
15098
|
relaxedFieldsForAttempt,
|
|
14983
|
-
() => operations.search(searchQuery, MAX_CONTEXT_RESULT_LIMIT, scope)
|
|
15099
|
+
(trace) => operations.search(searchQuery, MAX_CONTEXT_RESULT_LIMIT, scope, input.diagnostic ? trace : void 0)
|
|
14984
15100
|
);
|
|
14985
15101
|
};
|
|
14986
|
-
const
|
|
15102
|
+
const findSuccessfulAttemptState = (route) => {
|
|
15103
|
+
for (let index = attemptStates.length - 1; index >= 0; index -= 1) {
|
|
15104
|
+
const attempt = attemptStates[index];
|
|
15105
|
+
if (attempt.kind === route && attempt.resultCount > 0) {
|
|
15106
|
+
return attempt;
|
|
15107
|
+
}
|
|
15108
|
+
}
|
|
15109
|
+
return void 0;
|
|
15110
|
+
};
|
|
15111
|
+
const toResult = (route, routedQuery, pack, successfulAttempt) => {
|
|
14987
15112
|
const base = packedResult(route, routedQuery, pack);
|
|
14988
15113
|
const baseDetails = base.details;
|
|
14989
15114
|
const successIndex = findSuccessfulAttemptIndex(route, attempts);
|
|
15115
|
+
const successState = successfulAttempt ?? findSuccessfulAttemptState(route);
|
|
14990
15116
|
return {
|
|
14991
15117
|
text: base.text,
|
|
14992
15118
|
details: {
|
|
@@ -14994,7 +15120,10 @@ async function resolveSearchContext(input, operations) {
|
|
|
14994
15120
|
tokenBudget: baseDetails.tokenBudget,
|
|
14995
15121
|
tokenEstimate: baseDetails.tokenEstimate,
|
|
14996
15122
|
truncated: false,
|
|
14997
|
-
recovery: buildRecoveryDetails(
|
|
15123
|
+
recovery: buildRecoveryDetails(serializeAttempts(attemptStates), successIndex),
|
|
15124
|
+
...input.diagnostic && {
|
|
15125
|
+
diagnostic: buildSearchDiagnostic(successState)
|
|
15126
|
+
}
|
|
14998
15127
|
}
|
|
14999
15128
|
};
|
|
15000
15129
|
};
|
|
@@ -15008,8 +15137,18 @@ async function resolveSearchContext(input, operations) {
|
|
|
15008
15137
|
buildContextPack(scopedDefinitionResults, {
|
|
15009
15138
|
tokenBudget,
|
|
15010
15139
|
maxResults: limit,
|
|
15011
|
-
heading
|
|
15012
|
-
|
|
15140
|
+
heading,
|
|
15141
|
+
preserveInputOrder: true,
|
|
15142
|
+
...input.diagnostic ? {
|
|
15143
|
+
trace: (trace) => {
|
|
15144
|
+
const attemptState = findSuccessfulAttemptState("definition");
|
|
15145
|
+
if (attemptState) {
|
|
15146
|
+
attemptState.contextPackTrace = trace;
|
|
15147
|
+
}
|
|
15148
|
+
}
|
|
15149
|
+
} : void 0
|
|
15150
|
+
}),
|
|
15151
|
+
findSuccessfulAttemptState("definition")
|
|
15013
15152
|
);
|
|
15014
15153
|
}
|
|
15015
15154
|
if (explicitSymbol) {
|
|
@@ -15027,8 +15166,18 @@ async function resolveSearchContext(input, operations) {
|
|
|
15027
15166
|
buildContextPack(unscopedDefinitionResults, {
|
|
15028
15167
|
tokenBudget,
|
|
15029
15168
|
maxResults: limit,
|
|
15030
|
-
heading: heading2
|
|
15031
|
-
|
|
15169
|
+
heading: heading2,
|
|
15170
|
+
preserveInputOrder: true,
|
|
15171
|
+
...input.diagnostic ? {
|
|
15172
|
+
trace: (trace) => {
|
|
15173
|
+
const attemptState = findSuccessfulAttemptState("definition");
|
|
15174
|
+
if (attemptState) {
|
|
15175
|
+
attemptState.contextPackTrace = trace;
|
|
15176
|
+
}
|
|
15177
|
+
}
|
|
15178
|
+
} : void 0
|
|
15179
|
+
}),
|
|
15180
|
+
findSuccessfulAttemptState("definition")
|
|
15032
15181
|
);
|
|
15033
15182
|
}
|
|
15034
15183
|
}
|
|
@@ -15047,7 +15196,10 @@ Explicit symbol lookup only; conceptual search was not attempted.`
|
|
|
15047
15196
|
tokenBudget: heading.tokenBudget,
|
|
15048
15197
|
tokenEstimate: heading.tokenEstimate,
|
|
15049
15198
|
truncated: heading.truncated,
|
|
15050
|
-
recovery: buildRecoveryDetails(
|
|
15199
|
+
recovery: buildRecoveryDetails(serializeAttempts(attemptStates), null),
|
|
15200
|
+
...input.diagnostic && {
|
|
15201
|
+
diagnostic: buildSearchDiagnostic(attemptStates[attemptStates.length - 1])
|
|
15202
|
+
}
|
|
15051
15203
|
}
|
|
15052
15204
|
};
|
|
15053
15205
|
}
|
|
@@ -15087,8 +15239,17 @@ Explicit symbol lookup only; conceptual search was not attempted.`
|
|
|
15087
15239
|
maxResults: limit,
|
|
15088
15240
|
heading,
|
|
15089
15241
|
includeExactSearchHandoff: true,
|
|
15090
|
-
preferImplementationPaths: intent.preferSourcePaths || intent.primary !== "docs" && intent.primary !== "test"
|
|
15091
|
-
|
|
15242
|
+
preferImplementationPaths: intent.preferSourcePaths || intent.primary !== "docs" && intent.primary !== "test",
|
|
15243
|
+
...input.diagnostic ? {
|
|
15244
|
+
trace: (trace) => {
|
|
15245
|
+
const attemptState = findSuccessfulAttemptState("conceptual");
|
|
15246
|
+
if (attemptState) {
|
|
15247
|
+
attemptState.contextPackTrace = trace;
|
|
15248
|
+
}
|
|
15249
|
+
}
|
|
15250
|
+
} : void 0
|
|
15251
|
+
}),
|
|
15252
|
+
findSuccessfulAttemptState("conceptual")
|
|
15092
15253
|
);
|
|
15093
15254
|
}
|
|
15094
15255
|
}
|
|
@@ -15104,7 +15265,10 @@ Explicit symbol lookup only; conceptual search was not attempted.`
|
|
|
15104
15265
|
tokenBudget: fallbackText.tokenBudget,
|
|
15105
15266
|
tokenEstimate: fallbackText.tokenEstimate,
|
|
15106
15267
|
truncated: fallbackText.truncated,
|
|
15107
|
-
recovery: buildRecoveryDetails(
|
|
15268
|
+
recovery: buildRecoveryDetails(serializeAttempts(attemptStates), null),
|
|
15269
|
+
...input.diagnostic && {
|
|
15270
|
+
diagnostic: buildSearchDiagnostic(attemptStates[attemptStates.length - 1])
|
|
15271
|
+
}
|
|
15108
15272
|
}
|
|
15109
15273
|
};
|
|
15110
15274
|
}
|
|
@@ -15185,17 +15349,27 @@ async function resolveCodebaseContextUnmeasured(projectRoot3, host, input) {
|
|
|
15185
15349
|
details: fittedDetails("path", fitted, 0)
|
|
15186
15350
|
};
|
|
15187
15351
|
}
|
|
15188
|
-
return resolveSearchContext({
|
|
15189
|
-
|
|
15352
|
+
return resolveSearchContext({
|
|
15353
|
+
query: input.query,
|
|
15354
|
+
symbol,
|
|
15355
|
+
limit,
|
|
15356
|
+
tokenBudget,
|
|
15357
|
+
fileType,
|
|
15358
|
+
directory,
|
|
15359
|
+
diagnostic: input.diagnostic
|
|
15360
|
+
}, {
|
|
15361
|
+
lookup: (lookupSymbol, retrievalLimit, scope, trace) => implementationLookup(projectRoot3, host, lookupSymbol, {
|
|
15190
15362
|
limit: retrievalLimit,
|
|
15191
15363
|
fileType: scope.fileType,
|
|
15192
|
-
directory: scope.directory
|
|
15364
|
+
directory: scope.directory,
|
|
15365
|
+
trace
|
|
15193
15366
|
}),
|
|
15194
|
-
search: (queryText, retrievalLimit, scope) => searchCodebase(projectRoot3, host, queryText, {
|
|
15367
|
+
search: (queryText, retrievalLimit, scope, trace) => searchCodebase(projectRoot3, host, queryText, {
|
|
15195
15368
|
limit: retrievalLimit,
|
|
15196
15369
|
fileType: scope.fileType,
|
|
15197
15370
|
directory: scope.directory,
|
|
15198
|
-
metadataOnly: true
|
|
15371
|
+
metadataOnly: true,
|
|
15372
|
+
trace
|
|
15199
15373
|
})
|
|
15200
15374
|
});
|
|
15201
15375
|
}
|
|
@@ -15260,12 +15434,188 @@ async function resolveCodebaseContext(projectRoot3, host, input) {
|
|
|
15260
15434
|
}
|
|
15261
15435
|
}
|
|
15262
15436
|
|
|
15437
|
+
// src/tools/edit-context.ts
|
|
15438
|
+
function edgeLimit(value) {
|
|
15439
|
+
if (value === null || value === void 0 || !Number.isFinite(value)) {
|
|
15440
|
+
return DEFAULT_CODEBASE_EDIT_CONTEXT_EDGE_LIMIT;
|
|
15441
|
+
}
|
|
15442
|
+
return Math.min(
|
|
15443
|
+
MAX_CODEBASE_EDIT_CONTEXT_EDGE_LIMIT,
|
|
15444
|
+
Math.max(MIN_CODEBASE_EDIT_CONTEXT_EDGE_LIMIT, Math.floor(value))
|
|
15445
|
+
);
|
|
15446
|
+
}
|
|
15447
|
+
function normalizedPath(value) {
|
|
15448
|
+
return value.replaceAll("\\", "/").replace(/^\.\//, "");
|
|
15449
|
+
}
|
|
15450
|
+
function pathsMatch(left, right) {
|
|
15451
|
+
const normalizedLeft = normalizedPath(left);
|
|
15452
|
+
const normalizedRight = normalizedPath(right);
|
|
15453
|
+
return normalizedLeft === normalizedRight || normalizedLeft.endsWith(`/${normalizedRight}`) || normalizedRight.endsWith(`/${normalizedLeft}`);
|
|
15454
|
+
}
|
|
15455
|
+
function targetSource(results, resolution) {
|
|
15456
|
+
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);
|
|
15457
|
+
}
|
|
15458
|
+
function formatSource(result) {
|
|
15459
|
+
const name = result.name ? ` ${result.name}` : "";
|
|
15460
|
+
return [
|
|
15461
|
+
"## Target implementation",
|
|
15462
|
+
`${result.filePath}:${result.startLine}-${result.endLine} (${result.chunkType}${name})`,
|
|
15463
|
+
"```",
|
|
15464
|
+
result.content,
|
|
15465
|
+
"```"
|
|
15466
|
+
].join("\n");
|
|
15467
|
+
}
|
|
15468
|
+
function formatCallers(edges) {
|
|
15469
|
+
if (edges.length === 0) return "## Direct callers\nNone found.";
|
|
15470
|
+
return [
|
|
15471
|
+
"## Direct callers",
|
|
15472
|
+
...edges.map((edge) => `- ${edge.fromSymbolName ?? "<unknown>"} at ${edge.fromSymbolFilePath ?? "<unknown file>"}:${edge.line} (${edge.callType}, ${edge.isResolved ? "resolved" : "unresolved"})`)
|
|
15473
|
+
].join("\n");
|
|
15474
|
+
}
|
|
15475
|
+
function formatCallees(edges, sourceFilePath) {
|
|
15476
|
+
if (edges.length === 0) return "## Direct callees\nNone found.";
|
|
15477
|
+
return [
|
|
15478
|
+
"## Direct callees",
|
|
15479
|
+
...edges.map((edge) => `- ${edge.targetName} from ${sourceFilePath}:${edge.line} (${edge.callType}, ${edge.isResolved ? "resolved" : "unresolved"})`)
|
|
15480
|
+
].join("\n");
|
|
15481
|
+
}
|
|
15482
|
+
function formatResolutionRisk(resolution) {
|
|
15483
|
+
if (resolution.status === "ambiguous") {
|
|
15484
|
+
const candidates = resolution.candidates.map((candidate) => `${candidate.filePath}:${candidate.startLine}`).join(", ");
|
|
15485
|
+
return `Risk: symbol "${resolution.name}" is ambiguous. Pass filePath to select a target.${candidates ? ` Candidates: ${candidates}.` : ""}`;
|
|
15486
|
+
}
|
|
15487
|
+
if (resolution.filePath && resolution.totalCandidates > 0) {
|
|
15488
|
+
return `Risk: symbol "${resolution.name}" did not resolve at filePath="${resolution.filePath}". Review the conceptual evidence before editing.`;
|
|
15489
|
+
}
|
|
15490
|
+
return `Risk: symbol "${resolution.name}" could not be resolved. Review the conceptual evidence before editing.`;
|
|
15491
|
+
}
|
|
15492
|
+
async function fallbackPack(dependencies, query, risk, resolution, tokenBudget, candidateSource = []) {
|
|
15493
|
+
const conceptual = await dependencies.searchCodebase(query, { limit: 5 });
|
|
15494
|
+
const pack = buildContextPack([...candidateSource, ...conceptual], {
|
|
15495
|
+
tokenBudget: tokenBudget ?? void 0,
|
|
15496
|
+
heading: "## Conceptual evidence",
|
|
15497
|
+
maxResults: 5,
|
|
15498
|
+
includeExactSearchHandoff: false,
|
|
15499
|
+
preferImplementationPaths: true
|
|
15500
|
+
});
|
|
15501
|
+
const fitted = fitTextToContextBudget(`${risk}
|
|
15502
|
+
|
|
15503
|
+
${pack.text}`, tokenBudget ?? void 0);
|
|
15504
|
+
return {
|
|
15505
|
+
text: fitted.text,
|
|
15506
|
+
details: {
|
|
15507
|
+
resolution,
|
|
15508
|
+
tokenBudget: fitted.tokenBudget,
|
|
15509
|
+
tokenEstimate: fitted.tokenEstimate,
|
|
15510
|
+
truncated: fitted.truncated,
|
|
15511
|
+
sourceIncluded: candidateSource.length > 0,
|
|
15512
|
+
callerCount: 0,
|
|
15513
|
+
calleeCount: 0
|
|
15514
|
+
}
|
|
15515
|
+
};
|
|
15516
|
+
}
|
|
15517
|
+
async function resolveCodebaseEditContextWithDependencies(input, dependencies) {
|
|
15518
|
+
const symbol = input.symbol?.trim();
|
|
15519
|
+
if (!symbol) {
|
|
15520
|
+
return fallbackPack(
|
|
15521
|
+
dependencies,
|
|
15522
|
+
input.query,
|
|
15523
|
+
"Risk: no authoritative symbol was supplied. Review the conceptual evidence before editing.",
|
|
15524
|
+
"not_requested",
|
|
15525
|
+
input.tokenBudget
|
|
15526
|
+
);
|
|
15527
|
+
}
|
|
15528
|
+
let callersResult;
|
|
15529
|
+
try {
|
|
15530
|
+
callersResult = await dependencies.getCallGraphData({
|
|
15531
|
+
name: symbol,
|
|
15532
|
+
filePath: input.filePath ?? void 0,
|
|
15533
|
+
direction: "callers"
|
|
15534
|
+
});
|
|
15535
|
+
} catch (error) {
|
|
15536
|
+
const candidates = await dependencies.implementationLookup(symbol, { limit: 5 });
|
|
15537
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
15538
|
+
return fallbackPack(
|
|
15539
|
+
dependencies,
|
|
15540
|
+
input.query,
|
|
15541
|
+
`Risk: graph data is unavailable (${message}). Target and dependencies are not graph-verified.`,
|
|
15542
|
+
"graph_unavailable",
|
|
15543
|
+
input.tokenBudget,
|
|
15544
|
+
candidates
|
|
15545
|
+
);
|
|
15546
|
+
}
|
|
15547
|
+
if (callersResult.resolution.status !== "resolved") {
|
|
15548
|
+
return fallbackPack(
|
|
15549
|
+
dependencies,
|
|
15550
|
+
input.query,
|
|
15551
|
+
formatResolutionRisk(callersResult.resolution),
|
|
15552
|
+
callersResult.resolution.status,
|
|
15553
|
+
input.tokenBudget
|
|
15554
|
+
);
|
|
15555
|
+
}
|
|
15556
|
+
const resolution = callersResult.resolution;
|
|
15557
|
+
const [definitionsResult, calleesResult] = await Promise.allSettled([
|
|
15558
|
+
dependencies.implementationLookup(symbol, { limit: 10 }),
|
|
15559
|
+
dependencies.getCallGraphData({
|
|
15560
|
+
name: symbol,
|
|
15561
|
+
filePath: input.filePath ?? resolution.filePath,
|
|
15562
|
+
direction: "callees"
|
|
15563
|
+
})
|
|
15564
|
+
]);
|
|
15565
|
+
if (definitionsResult.status === "rejected") throw definitionsResult.reason;
|
|
15566
|
+
let graphRisk;
|
|
15567
|
+
let callees = [];
|
|
15568
|
+
if (calleesResult.status === "rejected") {
|
|
15569
|
+
const message = calleesResult.reason instanceof Error ? calleesResult.reason.message : String(calleesResult.reason);
|
|
15570
|
+
graphRisk = `Risk: callee graph data is unavailable (${message}). Dependency evidence is incomplete.`;
|
|
15571
|
+
} else if (calleesResult.value.resolution.status !== "resolved") {
|
|
15572
|
+
graphRisk = "Risk: the target resolved for callers but not callees. Dependency evidence is incomplete.";
|
|
15573
|
+
} else {
|
|
15574
|
+
callees = calleesResult.value.callees.slice(0, edgeLimit(input.calleeLimit));
|
|
15575
|
+
}
|
|
15576
|
+
const source = targetSource(definitionsResult.value, resolution);
|
|
15577
|
+
const callers = callersResult.callers.slice(0, edgeLimit(input.callerLimit));
|
|
15578
|
+
const sourceBudget = Math.max(
|
|
15579
|
+
MIN_CONTEXT_PACK_TOKEN_BUDGET,
|
|
15580
|
+
Math.floor((input.tokenBudget ?? DEFAULT_CONTEXT_PACK_TOKEN_BUDGET) * 0.6)
|
|
15581
|
+
);
|
|
15582
|
+
const sourceText = source ? fitTextToContextBudget(formatSource(source), sourceBudget).text : `## Target implementation
|
|
15583
|
+
Risk: no implementation source matched the resolved target at ${resolution.filePath}:${resolution.startLine}.`;
|
|
15584
|
+
const fitted = fitTextToContextBudget([
|
|
15585
|
+
`# Pre-edit context for ${resolution.name}`,
|
|
15586
|
+
graphRisk,
|
|
15587
|
+
sourceText,
|
|
15588
|
+
formatCallers(callers),
|
|
15589
|
+
formatCallees(callees, resolution.filePath)
|
|
15590
|
+
].filter((section) => section !== void 0).join("\n\n"), input.tokenBudget ?? void 0);
|
|
15591
|
+
return {
|
|
15592
|
+
text: fitted.text,
|
|
15593
|
+
details: {
|
|
15594
|
+
resolution: "resolved",
|
|
15595
|
+
tokenBudget: fitted.tokenBudget,
|
|
15596
|
+
tokenEstimate: fitted.tokenEstimate,
|
|
15597
|
+
truncated: fitted.truncated,
|
|
15598
|
+
sourceIncluded: source !== void 0,
|
|
15599
|
+
callerCount: callers.length,
|
|
15600
|
+
calleeCount: callees.length
|
|
15601
|
+
}
|
|
15602
|
+
};
|
|
15603
|
+
}
|
|
15604
|
+
async function resolveCodebaseEditContext(projectRoot3, host, input) {
|
|
15605
|
+
return resolveCodebaseEditContextWithDependencies(input, {
|
|
15606
|
+
searchCodebase: (query, options) => searchCodebase(projectRoot3, host, query, options),
|
|
15607
|
+
implementationLookup: (query, options) => implementationLookup(projectRoot3, host, query, options),
|
|
15608
|
+
getCallGraphData: (params) => getCallGraphData(projectRoot3, host, params)
|
|
15609
|
+
});
|
|
15610
|
+
}
|
|
15611
|
+
|
|
15263
15612
|
// src/adapters/pi/call-graph.ts
|
|
15264
15613
|
var import_typebox = require("typebox");
|
|
15265
15614
|
|
|
15266
15615
|
// src/tools/tool-names.ts
|
|
15267
15616
|
var TOOL_NAME = {
|
|
15268
15617
|
CODEBASE_CONTEXT: "codebase_context",
|
|
15618
|
+
CODEBASE_EDIT_CONTEXT: "codebase_edit_context",
|
|
15269
15619
|
CODEBASE_SEARCH: "codebase_search",
|
|
15270
15620
|
CODEBASE_PEEK: "codebase_peek",
|
|
15271
15621
|
FIND_SIMILAR: "find_similar",
|
|
@@ -15289,6 +15639,7 @@ var TOOL_NAME = {
|
|
|
15289
15639
|
};
|
|
15290
15640
|
var PORTABLE_TOOL_NAMES = [
|
|
15291
15641
|
TOOL_NAME.CODEBASE_CONTEXT,
|
|
15642
|
+
TOOL_NAME.CODEBASE_EDIT_CONTEXT,
|
|
15292
15643
|
TOOL_NAME.CODEBASE_SEARCH,
|
|
15293
15644
|
TOOL_NAME.CODEBASE_PEEK,
|
|
15294
15645
|
TOOL_NAME.INDEX_CODEBASE,
|
|
@@ -15305,6 +15656,7 @@ var PORTABLE_TOOL_NAMES = [
|
|
|
15305
15656
|
];
|
|
15306
15657
|
var OPENCODE_TOOL_NAMES = [
|
|
15307
15658
|
TOOL_NAME.CODEBASE_CONTEXT,
|
|
15659
|
+
TOOL_NAME.CODEBASE_EDIT_CONTEXT,
|
|
15308
15660
|
TOOL_NAME.CODEBASE_SEARCH,
|
|
15309
15661
|
TOOL_NAME.CODEBASE_PEEK,
|
|
15310
15662
|
TOOL_NAME.INDEX_CODEBASE,
|
|
@@ -15325,6 +15677,7 @@ var OPENCODE_TOOL_NAMES = [
|
|
|
15325
15677
|
];
|
|
15326
15678
|
var PI_TOOL_NAMES = [
|
|
15327
15679
|
TOOL_NAME.CODEBASE_CONTEXT,
|
|
15680
|
+
TOOL_NAME.CODEBASE_EDIT_CONTEXT,
|
|
15328
15681
|
TOOL_NAME.CODEBASE_SEARCH,
|
|
15329
15682
|
TOOL_NAME.CODEBASE_PEEK,
|
|
15330
15683
|
TOOL_NAME.FIND_SIMILAR,
|
|
@@ -15439,6 +15792,7 @@ function codebaseIndexPiExtension(pi) {
|
|
|
15439
15792
|
import_typebox2.Type.Integer({ minimum: MIN_CONTEXT_PATH_DEPTH, maximum: MAX_CONTEXT_PATH_DEPTH }),
|
|
15440
15793
|
import_typebox2.Type.Null()
|
|
15441
15794
|
], { default: 10, description: `Maximum call-graph traversal depth (${MIN_CONTEXT_PATH_DEPTH}-${MAX_CONTEXT_PATH_DEPTH})` })),
|
|
15795
|
+
diagnostic: import_typebox2.Type.Optional(import_typebox2.Type.Union([import_typebox2.Type.Boolean(), import_typebox2.Type.Null()], { description: "Collect diagnostic routing and search traces without changing normal output." })),
|
|
15442
15796
|
fileType: import_typebox2.Type.Optional(import_typebox2.Type.Union([import_typebox2.Type.String(), import_typebox2.Type.Null()], { description: "Filter by file extension, e.g., ts, py, rs" })),
|
|
15443
15797
|
directory: import_typebox2.Type.Optional(import_typebox2.Type.Union([import_typebox2.Type.String(), import_typebox2.Type.Null()], { description: "Filter by directory path" })),
|
|
15444
15798
|
tokenBudget: import_typebox2.Type.Optional(import_typebox2.Type.Union([
|
|
@@ -15450,10 +15804,40 @@ function codebaseIndexPiExtension(pi) {
|
|
|
15450
15804
|
}))
|
|
15451
15805
|
}),
|
|
15452
15806
|
async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
|
|
15453
|
-
const
|
|
15807
|
+
const normalizedParams = {
|
|
15808
|
+
...params,
|
|
15809
|
+
diagnostic: params.diagnostic ?? void 0
|
|
15810
|
+
};
|
|
15811
|
+
const result = await resolveCodebaseContext(projectRoot2(ctx), HOST2, normalizedParams);
|
|
15454
15812
|
return text2(result.text, result.details);
|
|
15455
15813
|
}
|
|
15456
15814
|
});
|
|
15815
|
+
pi.registerTool({
|
|
15816
|
+
name: TOOL_NAME.CODEBASE_EDIT_CONTEXT,
|
|
15817
|
+
label: "Codebase Edit Context",
|
|
15818
|
+
description: "PRE-EDIT TOOL for a known or suspected symbol. Returns bounded target source and direct graph evidence, with a risk-marked fallback when unresolved.",
|
|
15819
|
+
parameters: import_typebox2.Type.Object({
|
|
15820
|
+
query: import_typebox2.Type.String({ description: "The requested change or target behavior" }),
|
|
15821
|
+
symbol: import_typebox2.Type.Optional(import_typebox2.Type.Union([import_typebox2.Type.String(), import_typebox2.Type.Null()])),
|
|
15822
|
+
filePath: import_typebox2.Type.Optional(import_typebox2.Type.Union([import_typebox2.Type.String(), import_typebox2.Type.Null()])),
|
|
15823
|
+
callerLimit: import_typebox2.Type.Optional(import_typebox2.Type.Union([
|
|
15824
|
+
import_typebox2.Type.Integer({ minimum: MIN_CODEBASE_EDIT_CONTEXT_EDGE_LIMIT, maximum: MAX_CODEBASE_EDIT_CONTEXT_EDGE_LIMIT }),
|
|
15825
|
+
import_typebox2.Type.Null()
|
|
15826
|
+
], { default: DEFAULT_CODEBASE_EDIT_CONTEXT_EDGE_LIMIT })),
|
|
15827
|
+
calleeLimit: import_typebox2.Type.Optional(import_typebox2.Type.Union([
|
|
15828
|
+
import_typebox2.Type.Integer({ minimum: MIN_CODEBASE_EDIT_CONTEXT_EDGE_LIMIT, maximum: MAX_CODEBASE_EDIT_CONTEXT_EDGE_LIMIT }),
|
|
15829
|
+
import_typebox2.Type.Null()
|
|
15830
|
+
], { default: DEFAULT_CODEBASE_EDIT_CONTEXT_EDGE_LIMIT })),
|
|
15831
|
+
tokenBudget: import_typebox2.Type.Optional(import_typebox2.Type.Union([
|
|
15832
|
+
import_typebox2.Type.Integer({ minimum: MIN_CONTEXT_PACK_TOKEN_BUDGET, maximum: MAX_CONTEXT_PACK_TOKEN_BUDGET }),
|
|
15833
|
+
import_typebox2.Type.Null()
|
|
15834
|
+
], { default: DEFAULT_CONTEXT_PACK_TOKEN_BUDGET }))
|
|
15835
|
+
}),
|
|
15836
|
+
async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
|
|
15837
|
+
const result = await resolveCodebaseEditContext(projectRoot2(ctx), HOST2, params);
|
|
15838
|
+
return text2(result.text);
|
|
15839
|
+
}
|
|
15840
|
+
});
|
|
15457
15841
|
pi.registerTool({
|
|
15458
15842
|
name: TOOL_NAME.CODEBASE_SEARCH,
|
|
15459
15843
|
label: "Codebase Search",
|