opencode-codebase-index 0.22.2 → 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 +668 -96
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +668 -96
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +442 -57
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +442 -57
- package/dist/index.js.map +1 -1
- package/dist/pi-extension.cjs +402 -49
- package/dist/pi-extension.cjs.map +1 -1
- package/dist/pi-extension.js +402 -49
- 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
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
//
|
|
1
|
+
// open-codebase-index - Semantic codebase indexing and search
|
|
2
2
|
import { createRequire } from 'module'; const require = createRequire(import.meta.url);
|
|
3
3
|
var __create = Object.create;
|
|
4
4
|
var __defProp = Object.defineProperty;
|
|
@@ -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
|
`;
|
|
@@ -16780,6 +16831,8 @@ var GitHeadWatcher = class {
|
|
|
16780
16831
|
debounceTimer = null;
|
|
16781
16832
|
debounceMs = 100;
|
|
16782
16833
|
// Short debounce for git operations
|
|
16834
|
+
readyPromise = Promise.resolve();
|
|
16835
|
+
resolveReady = null;
|
|
16783
16836
|
constructor(projectRoot) {
|
|
16784
16837
|
this.projectRoot = projectRoot;
|
|
16785
16838
|
}
|
|
@@ -16788,8 +16841,12 @@ var GitHeadWatcher = class {
|
|
|
16788
16841
|
return;
|
|
16789
16842
|
}
|
|
16790
16843
|
if (!isGitRepo(this.projectRoot)) {
|
|
16844
|
+
this.readyPromise = Promise.resolve();
|
|
16791
16845
|
return;
|
|
16792
16846
|
}
|
|
16847
|
+
this.readyPromise = new Promise((resolve15) => {
|
|
16848
|
+
this.resolveReady = resolve15;
|
|
16849
|
+
});
|
|
16793
16850
|
this.onBranchChange = handler;
|
|
16794
16851
|
this.currentBranch = getCurrentBranch(this.projectRoot);
|
|
16795
16852
|
const headPath = getHeadPath(this.projectRoot);
|
|
@@ -16804,6 +16861,10 @@ var GitHeadWatcher = class {
|
|
|
16804
16861
|
});
|
|
16805
16862
|
this.watcher.on("change", () => this.handleHeadChange());
|
|
16806
16863
|
this.watcher.on("add", () => this.handleHeadChange());
|
|
16864
|
+
this.watcher.once("ready", () => {
|
|
16865
|
+
this.resolveReady?.();
|
|
16866
|
+
this.resolveReady = null;
|
|
16867
|
+
});
|
|
16807
16868
|
}
|
|
16808
16869
|
handleHeadChange() {
|
|
16809
16870
|
if (this.debounceTimer) {
|
|
@@ -16841,10 +16902,16 @@ var GitHeadWatcher = class {
|
|
|
16841
16902
|
await watcher.close();
|
|
16842
16903
|
}
|
|
16843
16904
|
this.onBranchChange = null;
|
|
16905
|
+
this.resolveReady?.();
|
|
16906
|
+
this.resolveReady = null;
|
|
16907
|
+
this.readyPromise = Promise.resolve();
|
|
16844
16908
|
}
|
|
16845
16909
|
isRunning() {
|
|
16846
16910
|
return this.watcher !== null;
|
|
16847
16911
|
}
|
|
16912
|
+
async waitUntilReady() {
|
|
16913
|
+
await this.readyPromise;
|
|
16914
|
+
}
|
|
16848
16915
|
};
|
|
16849
16916
|
|
|
16850
16917
|
// src/watcher/index.ts
|
|
@@ -16894,7 +16961,10 @@ function createWatcherWithIndexer(getIndexer, projectRoot, config, host, options
|
|
|
16894
16961
|
fileWatcher,
|
|
16895
16962
|
gitWatcher,
|
|
16896
16963
|
whenReady() {
|
|
16897
|
-
return
|
|
16964
|
+
return Promise.all([
|
|
16965
|
+
fileWatcher.waitUntilReady(),
|
|
16966
|
+
gitWatcher?.waitUntilReady()
|
|
16967
|
+
]).then(() => void 0);
|
|
16898
16968
|
},
|
|
16899
16969
|
async stop() {
|
|
16900
16970
|
stopped = true;
|
|
@@ -17029,6 +17099,181 @@ var pr_impact = tool({
|
|
|
17029
17099
|
}
|
|
17030
17100
|
});
|
|
17031
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
|
+
|
|
17032
17277
|
// src/tools/context-search.ts
|
|
17033
17278
|
var MIN_CONTEXT_RESULT_LIMIT = 1;
|
|
17034
17279
|
var MAX_CONTEXT_RESULT_LIMIT = 100;
|
|
@@ -17131,6 +17376,27 @@ function buildRecoveryDetails(attempts, successIndex) {
|
|
|
17131
17376
|
successfulAttemptIndex: successIndex
|
|
17132
17377
|
};
|
|
17133
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
|
+
}
|
|
17134
17400
|
function trimOrUndefined2(value) {
|
|
17135
17401
|
const normalized = value?.trim();
|
|
17136
17402
|
if (!normalized) {
|
|
@@ -17170,6 +17436,7 @@ async function resolveSearchContext(input, operations) {
|
|
|
17170
17436
|
const hasFilters = Boolean(fileType || directory);
|
|
17171
17437
|
const relaxedFields = relaxedHintFields(fileType, directory);
|
|
17172
17438
|
const attempts = [];
|
|
17439
|
+
const attemptStates = [];
|
|
17173
17440
|
const decisions = {
|
|
17174
17441
|
inferredDefinitionMiss: false,
|
|
17175
17442
|
fallbackFromOriginalConceptualToInferred: false,
|
|
@@ -17198,8 +17465,20 @@ async function resolveSearchContext(input, operations) {
|
|
|
17198
17465
|
if (seenAttempts.has(key)) {
|
|
17199
17466
|
return [];
|
|
17200
17467
|
}
|
|
17201
|
-
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;
|
|
17202
17480
|
seenAttempts.add(key);
|
|
17481
|
+
attemptStates.push(attemptState);
|
|
17203
17482
|
attempts.push({
|
|
17204
17483
|
kind,
|
|
17205
17484
|
scope: describeScope(scope.fileType, scope.directory),
|
|
@@ -17219,7 +17498,7 @@ async function resolveSearchContext(input, operations) {
|
|
|
17219
17498
|
symbol,
|
|
17220
17499
|
scope,
|
|
17221
17500
|
relaxedFieldsForAttempt,
|
|
17222
|
-
() => operations.lookup(symbol, MAX_CONTEXT_RESULT_LIMIT, scope)
|
|
17501
|
+
(trace) => operations.lookup(symbol, MAX_CONTEXT_RESULT_LIMIT, scope, input.diagnostic ? trace : void 0)
|
|
17223
17502
|
);
|
|
17224
17503
|
};
|
|
17225
17504
|
const tryConceptualSearch = async (searchQuery, scope, relaxedFieldsForAttempt) => {
|
|
@@ -17228,13 +17507,23 @@ async function resolveSearchContext(input, operations) {
|
|
|
17228
17507
|
searchQuery,
|
|
17229
17508
|
scope,
|
|
17230
17509
|
relaxedFieldsForAttempt,
|
|
17231
|
-
() => operations.search(searchQuery, MAX_CONTEXT_RESULT_LIMIT, scope)
|
|
17510
|
+
(trace) => operations.search(searchQuery, MAX_CONTEXT_RESULT_LIMIT, scope, input.diagnostic ? trace : void 0)
|
|
17232
17511
|
);
|
|
17233
17512
|
};
|
|
17234
|
-
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) => {
|
|
17235
17523
|
const base = packedResult(route, routedQuery, pack);
|
|
17236
17524
|
const baseDetails = base.details;
|
|
17237
17525
|
const successIndex = findSuccessfulAttemptIndex(route, attempts);
|
|
17526
|
+
const successState = successfulAttempt ?? findSuccessfulAttemptState(route);
|
|
17238
17527
|
return {
|
|
17239
17528
|
text: base.text,
|
|
17240
17529
|
details: {
|
|
@@ -17242,7 +17531,10 @@ async function resolveSearchContext(input, operations) {
|
|
|
17242
17531
|
tokenBudget: baseDetails.tokenBudget,
|
|
17243
17532
|
tokenEstimate: baseDetails.tokenEstimate,
|
|
17244
17533
|
truncated: false,
|
|
17245
|
-
recovery: buildRecoveryDetails(
|
|
17534
|
+
recovery: buildRecoveryDetails(serializeAttempts(attemptStates), successIndex),
|
|
17535
|
+
...input.diagnostic && {
|
|
17536
|
+
diagnostic: buildSearchDiagnostic(successState)
|
|
17537
|
+
}
|
|
17246
17538
|
}
|
|
17247
17539
|
};
|
|
17248
17540
|
};
|
|
@@ -17256,8 +17548,18 @@ async function resolveSearchContext(input, operations) {
|
|
|
17256
17548
|
buildContextPack(scopedDefinitionResults, {
|
|
17257
17549
|
tokenBudget,
|
|
17258
17550
|
maxResults: limit,
|
|
17259
|
-
heading
|
|
17260
|
-
|
|
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")
|
|
17261
17563
|
);
|
|
17262
17564
|
}
|
|
17263
17565
|
if (explicitSymbol) {
|
|
@@ -17275,8 +17577,18 @@ async function resolveSearchContext(input, operations) {
|
|
|
17275
17577
|
buildContextPack(unscopedDefinitionResults, {
|
|
17276
17578
|
tokenBudget,
|
|
17277
17579
|
maxResults: limit,
|
|
17278
|
-
heading: heading2
|
|
17279
|
-
|
|
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")
|
|
17280
17592
|
);
|
|
17281
17593
|
}
|
|
17282
17594
|
}
|
|
@@ -17295,7 +17607,10 @@ Explicit symbol lookup only; conceptual search was not attempted.`
|
|
|
17295
17607
|
tokenBudget: heading.tokenBudget,
|
|
17296
17608
|
tokenEstimate: heading.tokenEstimate,
|
|
17297
17609
|
truncated: heading.truncated,
|
|
17298
|
-
recovery: buildRecoveryDetails(
|
|
17610
|
+
recovery: buildRecoveryDetails(serializeAttempts(attemptStates), null),
|
|
17611
|
+
...input.diagnostic && {
|
|
17612
|
+
diagnostic: buildSearchDiagnostic(attemptStates[attemptStates.length - 1])
|
|
17613
|
+
}
|
|
17299
17614
|
}
|
|
17300
17615
|
};
|
|
17301
17616
|
}
|
|
@@ -17335,8 +17650,17 @@ Explicit symbol lookup only; conceptual search was not attempted.`
|
|
|
17335
17650
|
maxResults: limit,
|
|
17336
17651
|
heading,
|
|
17337
17652
|
includeExactSearchHandoff: true,
|
|
17338
|
-
preferImplementationPaths: intent.preferSourcePaths || intent.primary !== "docs" && intent.primary !== "test"
|
|
17339
|
-
|
|
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")
|
|
17340
17664
|
);
|
|
17341
17665
|
}
|
|
17342
17666
|
}
|
|
@@ -17352,7 +17676,10 @@ Explicit symbol lookup only; conceptual search was not attempted.`
|
|
|
17352
17676
|
tokenBudget: fallbackText.tokenBudget,
|
|
17353
17677
|
tokenEstimate: fallbackText.tokenEstimate,
|
|
17354
17678
|
truncated: fallbackText.truncated,
|
|
17355
|
-
recovery: buildRecoveryDetails(
|
|
17679
|
+
recovery: buildRecoveryDetails(serializeAttempts(attemptStates), null),
|
|
17680
|
+
...input.diagnostic && {
|
|
17681
|
+
diagnostic: buildSearchDiagnostic(attemptStates[attemptStates.length - 1])
|
|
17682
|
+
}
|
|
17356
17683
|
}
|
|
17357
17684
|
};
|
|
17358
17685
|
}
|
|
@@ -17433,17 +17760,27 @@ async function resolveCodebaseContextUnmeasured(projectRoot, host, input) {
|
|
|
17433
17760
|
details: fittedDetails("path", fitted, 0)
|
|
17434
17761
|
};
|
|
17435
17762
|
}
|
|
17436
|
-
return resolveSearchContext({
|
|
17437
|
-
|
|
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, {
|
|
17438
17773
|
limit: retrievalLimit,
|
|
17439
17774
|
fileType: scope.fileType,
|
|
17440
|
-
directory: scope.directory
|
|
17775
|
+
directory: scope.directory,
|
|
17776
|
+
trace
|
|
17441
17777
|
}),
|
|
17442
|
-
search: (queryText, retrievalLimit, scope) => searchCodebase(projectRoot, host, queryText, {
|
|
17778
|
+
search: (queryText, retrievalLimit, scope, trace) => searchCodebase(projectRoot, host, queryText, {
|
|
17443
17779
|
limit: retrievalLimit,
|
|
17444
17780
|
fileType: scope.fileType,
|
|
17445
17781
|
directory: scope.directory,
|
|
17446
|
-
metadataOnly: true
|
|
17782
|
+
metadataOnly: true,
|
|
17783
|
+
trace
|
|
17447
17784
|
})
|
|
17448
17785
|
});
|
|
17449
17786
|
}
|
|
@@ -17510,7 +17847,11 @@ async function resolveCodebaseContext(projectRoot, host, input) {
|
|
|
17510
17847
|
|
|
17511
17848
|
// src/tools/execute-common.ts
|
|
17512
17849
|
async function executeCodebaseContext(projectRoot, host, args) {
|
|
17513
|
-
|
|
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 };
|
|
17514
17855
|
}
|
|
17515
17856
|
async function executeIndexCodebase(projectRoot, host, args, onProgress) {
|
|
17516
17857
|
const result = await runIndexCodebase(projectRoot, host, args, onProgress);
|
|
@@ -17613,9 +17954,9 @@ function parseGitActivity(output) {
|
|
|
17613
17954
|
if (!filePath || addedRaw === "-" || deletedRaw === "-") continue;
|
|
17614
17955
|
const churn = Number(addedRaw) + Number(deletedRaw);
|
|
17615
17956
|
if (!Number.isFinite(churn) || churn <= 0) continue;
|
|
17616
|
-
const
|
|
17617
|
-
const previous = activity.get(
|
|
17618
|
-
activity.set(
|
|
17957
|
+
const normalizedPath2 = normalizePath3(filePath);
|
|
17958
|
+
const previous = activity.get(normalizedPath2);
|
|
17959
|
+
activity.set(normalizedPath2, {
|
|
17619
17960
|
churn: (previous?.churn ?? 0) + churn,
|
|
17620
17961
|
commits: (previous?.commits ?? 0) + 1,
|
|
17621
17962
|
latestDate: previous?.latestDate ?? latestDate,
|
|
@@ -18205,8 +18546,8 @@ function transformForVisualization(symbols, edges, options = {}) {
|
|
|
18205
18546
|
const normalizedAbsoluteSuffix = `/${normalizedDirWithSlash}`;
|
|
18206
18547
|
filteredSymbols = symbols.filter(
|
|
18207
18548
|
(s) => {
|
|
18208
|
-
const
|
|
18209
|
-
return
|
|
18549
|
+
const normalizedPath2 = s.filePath.replace(/\\/g, "/");
|
|
18550
|
+
return normalizedPath2 === normalizedDir || normalizedPath2.startsWith(normalizedDirWithSlash) || normalizedPath2.endsWith(`/${normalizedDir}`) || normalizedPath2.includes(normalizedAbsoluteSuffix);
|
|
18210
18551
|
}
|
|
18211
18552
|
);
|
|
18212
18553
|
}
|
|
@@ -18280,6 +18621,26 @@ var z3 = tool.schema;
|
|
|
18280
18621
|
var DEFAULT_HOST = "opencode";
|
|
18281
18622
|
var CHUNK_TYPE_VALUES = CHUNK_TYPES;
|
|
18282
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
|
+
}
|
|
18283
18644
|
function initializeTools2(projectRoot, config) {
|
|
18284
18645
|
initializeTools(projectRoot, config, DEFAULT_HOST);
|
|
18285
18646
|
}
|
|
@@ -18299,10 +18660,29 @@ var codebase_context = tool({
|
|
|
18299
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})`),
|
|
18300
18661
|
fileType: z3.string().nullable().optional().describe("Filter by file extension"),
|
|
18301
18662
|
directory: z3.string().nullable().optional().describe("Filter by directory path"),
|
|
18302
|
-
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)
|
|
18303
18683
|
},
|
|
18304
18684
|
async execute(args, context) {
|
|
18305
|
-
return (await
|
|
18685
|
+
return (await executeCodebaseEditContext(context?.worktree, DEFAULT_HOST, args)).text;
|
|
18306
18686
|
}
|
|
18307
18687
|
});
|
|
18308
18688
|
var codebase_peek = tool({
|
|
@@ -18559,6 +18939,7 @@ var index_visualize = tool({
|
|
|
18559
18939
|
// src/tools/tool-names.ts
|
|
18560
18940
|
var TOOL_NAME = {
|
|
18561
18941
|
CODEBASE_CONTEXT: "codebase_context",
|
|
18942
|
+
CODEBASE_EDIT_CONTEXT: "codebase_edit_context",
|
|
18562
18943
|
CODEBASE_SEARCH: "codebase_search",
|
|
18563
18944
|
CODEBASE_PEEK: "codebase_peek",
|
|
18564
18945
|
FIND_SIMILAR: "find_similar",
|
|
@@ -18582,6 +18963,7 @@ var TOOL_NAME = {
|
|
|
18582
18963
|
};
|
|
18583
18964
|
var PORTABLE_TOOL_NAMES = [
|
|
18584
18965
|
TOOL_NAME.CODEBASE_CONTEXT,
|
|
18966
|
+
TOOL_NAME.CODEBASE_EDIT_CONTEXT,
|
|
18585
18967
|
TOOL_NAME.CODEBASE_SEARCH,
|
|
18586
18968
|
TOOL_NAME.CODEBASE_PEEK,
|
|
18587
18969
|
TOOL_NAME.INDEX_CODEBASE,
|
|
@@ -18598,6 +18980,7 @@ var PORTABLE_TOOL_NAMES = [
|
|
|
18598
18980
|
];
|
|
18599
18981
|
var OPENCODE_TOOL_NAMES = [
|
|
18600
18982
|
TOOL_NAME.CODEBASE_CONTEXT,
|
|
18983
|
+
TOOL_NAME.CODEBASE_EDIT_CONTEXT,
|
|
18601
18984
|
TOOL_NAME.CODEBASE_SEARCH,
|
|
18602
18985
|
TOOL_NAME.CODEBASE_PEEK,
|
|
18603
18986
|
TOOL_NAME.INDEX_CODEBASE,
|
|
@@ -18618,6 +19001,7 @@ var OPENCODE_TOOL_NAMES = [
|
|
|
18618
19001
|
];
|
|
18619
19002
|
var PI_TOOL_NAMES = [
|
|
18620
19003
|
TOOL_NAME.CODEBASE_CONTEXT,
|
|
19004
|
+
TOOL_NAME.CODEBASE_EDIT_CONTEXT,
|
|
18621
19005
|
TOOL_NAME.CODEBASE_SEARCH,
|
|
18622
19006
|
TOOL_NAME.CODEBASE_PEEK,
|
|
18623
19007
|
TOOL_NAME.FIND_SIMILAR,
|
|
@@ -19071,6 +19455,7 @@ var plugin = async ({ directory, worktree }) => {
|
|
|
19071
19455
|
return {
|
|
19072
19456
|
tool: {
|
|
19073
19457
|
[TOOL_NAME.CODEBASE_CONTEXT]: codebase_context,
|
|
19458
|
+
[TOOL_NAME.CODEBASE_EDIT_CONTEXT]: codebase_edit_context,
|
|
19074
19459
|
[TOOL_NAME.CODEBASE_SEARCH]: codebase_search,
|
|
19075
19460
|
[TOOL_NAME.CODEBASE_PEEK]: codebase_peek,
|
|
19076
19461
|
[TOOL_NAME.INDEX_CODEBASE]: index_codebase,
|