opencode-codebase-index 0.19.0 → 0.20.0
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/README.md +7 -5
- package/dist/cli.cjs +766 -127
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +766 -127
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +408 -59
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +408 -59
- package/dist/index.js.map +1 -1
- package/dist/pi-extension.cjs +362 -51
- package/dist/pi-extension.cjs.map +1 -1
- package/dist/pi-extension.js +362 -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 +4 -3
package/dist/index.js
CHANGED
|
@@ -777,6 +777,7 @@ function getDefaultIndexingConfig() {
|
|
|
777
777
|
autoIndexMaxRetries: 5,
|
|
778
778
|
autoIndexRetryDelayMs: 100,
|
|
779
779
|
watchFiles: true,
|
|
780
|
+
pauseBackgroundIndexingOnBattery: false,
|
|
780
781
|
maxFileSize: 1048576,
|
|
781
782
|
maxChunksPerFile: 100,
|
|
782
783
|
semanticOnly: false,
|
|
@@ -908,6 +909,7 @@ function parseConfig(raw) {
|
|
|
908
909
|
autoIndexMaxRetries: typeof rawIndexing.autoIndexMaxRetries === "number" ? Math.min(10, Math.max(0, Math.floor(rawIndexing.autoIndexMaxRetries))) : defaultIndexing.autoIndexMaxRetries,
|
|
909
910
|
autoIndexRetryDelayMs: typeof rawIndexing.autoIndexRetryDelayMs === "number" ? Math.min(1e4, Math.max(10, Math.floor(rawIndexing.autoIndexRetryDelayMs))) : defaultIndexing.autoIndexRetryDelayMs,
|
|
910
911
|
watchFiles: typeof rawIndexing.watchFiles === "boolean" ? rawIndexing.watchFiles : defaultIndexing.watchFiles,
|
|
912
|
+
pauseBackgroundIndexingOnBattery: typeof rawIndexing.pauseBackgroundIndexingOnBattery === "boolean" ? rawIndexing.pauseBackgroundIndexingOnBattery : defaultIndexing.pauseBackgroundIndexingOnBattery,
|
|
911
913
|
maxFileSize: typeof rawIndexing.maxFileSize === "number" ? rawIndexing.maxFileSize : defaultIndexing.maxFileSize,
|
|
912
914
|
maxChunksPerFile: typeof rawIndexing.maxChunksPerFile === "number" ? Math.max(1, rawIndexing.maxChunksPerFile) : defaultIndexing.maxChunksPerFile,
|
|
913
915
|
semanticOnly: typeof rawIndexing.semanticOnly === "boolean" ? rawIndexing.semanticOnly : defaultIndexing.semanticOnly,
|
|
@@ -3486,9 +3488,7 @@ var PROJECT_MARKERS = [
|
|
|
3486
3488
|
"pom.xml",
|
|
3487
3489
|
"build.gradle",
|
|
3488
3490
|
"CMakeLists.txt",
|
|
3489
|
-
"Makefile"
|
|
3490
|
-
".opencode",
|
|
3491
|
-
".codebase-index"
|
|
3491
|
+
"Makefile"
|
|
3492
3492
|
];
|
|
3493
3493
|
function hasProjectMarker(projectRoot) {
|
|
3494
3494
|
for (const marker of PROJECT_MARKERS) {
|
|
@@ -4179,9 +4179,21 @@ function parseFiles(files) {
|
|
|
4179
4179
|
return result.map((f) => ({
|
|
4180
4180
|
path: f.path,
|
|
4181
4181
|
chunks: f.chunks.map(mapChunk),
|
|
4182
|
+
symbols: (f.symbols ?? []).map(mapParsedSymbol),
|
|
4182
4183
|
hash: f.hash
|
|
4183
4184
|
}));
|
|
4184
4185
|
}
|
|
4186
|
+
function mapParsedSymbol(symbol) {
|
|
4187
|
+
return {
|
|
4188
|
+
name: symbol.name,
|
|
4189
|
+
kind: symbol.kind,
|
|
4190
|
+
startLine: symbol.startLine ?? symbol.start_line,
|
|
4191
|
+
startCol: symbol.startCol ?? symbol.start_col,
|
|
4192
|
+
endLine: symbol.endLine ?? symbol.end_line,
|
|
4193
|
+
endCol: symbol.endCol ?? symbol.end_col,
|
|
4194
|
+
language: symbol.language
|
|
4195
|
+
};
|
|
4196
|
+
}
|
|
4185
4197
|
function mapChunk(c) {
|
|
4186
4198
|
return {
|
|
4187
4199
|
content: c.content,
|
|
@@ -6708,6 +6720,7 @@ var INDEX_METADATA_VERSION = "1";
|
|
|
6708
6720
|
var EMBEDDING_STRATEGY_VERSION = "2";
|
|
6709
6721
|
var SWIFT_PARSER_VERSION = "1";
|
|
6710
6722
|
var METAL_PARSER_VERSION = "1";
|
|
6723
|
+
var SYMBOL_EXTRACTOR_VERSION = "1";
|
|
6711
6724
|
var RANKING_TOKEN_CACHE_LIMIT = 4096;
|
|
6712
6725
|
var RANK_HYBRID_CACHE_LIMIT = 256;
|
|
6713
6726
|
function createPendingChunkStorageText(texts) {
|
|
@@ -7009,7 +7022,7 @@ function classifyQueryIntentRaw(query) {
|
|
|
7009
7022
|
return "neutral";
|
|
7010
7023
|
}
|
|
7011
7024
|
function isImplementationChunkType(chunkType) {
|
|
7012
|
-
return [
|
|
7025
|
+
return CALL_GRAPH_SYMBOL_CHUNK_TYPES.has(chunkType) || [
|
|
7013
7026
|
"export_statement",
|
|
7014
7027
|
"function",
|
|
7015
7028
|
"function_declaration",
|
|
@@ -7454,7 +7467,7 @@ function promoteIdentifierMatches(query, combined, semanticCandidates, keywordCa
|
|
|
7454
7467
|
const remainder = combined.filter((candidate) => !promotedIds.has(candidate.id));
|
|
7455
7468
|
return [...promoted, ...remainder];
|
|
7456
7469
|
}
|
|
7457
|
-
function buildSymbolDefinitionLane(query, database, branchChunkIds, limit, fallbackCandidates, prioritizeSourcePaths = classifyQueryIntentRaw(query) === "source") {
|
|
7470
|
+
function buildSymbolDefinitionLane(query, database, branchChunkIds, branchSymbolIds, limit, fallbackCandidates, prioritizeSourcePaths = classifyQueryIntentRaw(query) === "source") {
|
|
7458
7471
|
if (!prioritizeSourcePaths) {
|
|
7459
7472
|
return [];
|
|
7460
7473
|
}
|
|
@@ -7468,14 +7481,14 @@ function buildSymbolDefinitionLane(query, database, branchChunkIds, limit, fallb
|
|
|
7468
7481
|
const primaryHint = extractPrimaryIdentifierQueryHint(query);
|
|
7469
7482
|
const upsertChunkCandidate = (chunk, identifier, normalizedIdentifier, baseScore) => {
|
|
7470
7483
|
if (branchChunkIds && !branchChunkIds.has(chunk.chunkId)) {
|
|
7471
|
-
return;
|
|
7484
|
+
return false;
|
|
7472
7485
|
}
|
|
7473
7486
|
const chunkType = chunk.nodeType ?? "other";
|
|
7474
7487
|
if (!isImplementationChunkType(chunkType)) {
|
|
7475
|
-
return;
|
|
7488
|
+
return false;
|
|
7476
7489
|
}
|
|
7477
7490
|
if (!isLikelyImplementationPath2(chunk.filePath)) {
|
|
7478
|
-
return;
|
|
7491
|
+
return false;
|
|
7479
7492
|
}
|
|
7480
7493
|
const nameLower = (chunk.name ?? "").toLowerCase();
|
|
7481
7494
|
const exactName = nameLower === identifier || nameLower.replace(/_/g, "") === normalizedIdentifier;
|
|
@@ -7497,6 +7510,7 @@ function buildSymbolDefinitionLane(query, database, branchChunkIds, limit, fallb
|
|
|
7497
7510
|
}
|
|
7498
7511
|
});
|
|
7499
7512
|
}
|
|
7513
|
+
return true;
|
|
7500
7514
|
};
|
|
7501
7515
|
const normalizedHints = identifierHints.flatMap((hint) => [
|
|
7502
7516
|
hint,
|
|
@@ -7518,12 +7532,46 @@ function buildSymbolDefinitionLane(query, database, branchChunkIds, limit, fallb
|
|
|
7518
7532
|
dedupSymbols.set(symbol.id, symbol);
|
|
7519
7533
|
}
|
|
7520
7534
|
for (const symbol of dedupSymbols.values()) {
|
|
7535
|
+
if (branchSymbolIds && !branchSymbolIds.has(symbol.id)) {
|
|
7536
|
+
continue;
|
|
7537
|
+
}
|
|
7538
|
+
if (filePathHint && !pathMatchesHint(symbol.filePath, filePathHint)) {
|
|
7539
|
+
continue;
|
|
7540
|
+
}
|
|
7521
7541
|
const chunks = database.getChunksByFile(symbol.filePath);
|
|
7542
|
+
let foundCoveringChunk = false;
|
|
7522
7543
|
for (const chunk of chunks) {
|
|
7523
7544
|
if (chunk.startLine > symbol.startLine || chunk.endLine < symbol.endLine) {
|
|
7524
7545
|
continue;
|
|
7525
7546
|
}
|
|
7526
|
-
|
|
7547
|
+
const chunkName = (chunk.name ?? "").toLowerCase();
|
|
7548
|
+
const symbolName2 = symbol.name.toLowerCase();
|
|
7549
|
+
if (chunkName !== symbolName2 && chunkName.replace(/_/g, "") !== symbolName2.replace(/_/g, "")) {
|
|
7550
|
+
continue;
|
|
7551
|
+
}
|
|
7552
|
+
foundCoveringChunk = upsertChunkCandidate(chunk, identifier, normalizedIdentifier) || foundCoveringChunk;
|
|
7553
|
+
}
|
|
7554
|
+
if (foundCoveringChunk || !isLikelyImplementationPath2(symbol.filePath)) {
|
|
7555
|
+
continue;
|
|
7556
|
+
}
|
|
7557
|
+
const symbolName = symbol.name.toLowerCase();
|
|
7558
|
+
const exactName = symbolName === identifier || symbolName.replace(/_/g, "") === normalizedIdentifier;
|
|
7559
|
+
const score = exactName ? 0.99 : 0.88;
|
|
7560
|
+
const existing = symbolCandidates.get(symbol.id);
|
|
7561
|
+
if (!existing || score > existing.score) {
|
|
7562
|
+
symbolCandidates.set(symbol.id, {
|
|
7563
|
+
id: symbol.id,
|
|
7564
|
+
score,
|
|
7565
|
+
metadata: {
|
|
7566
|
+
filePath: symbol.filePath,
|
|
7567
|
+
startLine: symbol.startLine,
|
|
7568
|
+
endLine: symbol.endLine,
|
|
7569
|
+
chunkType: symbol.kind,
|
|
7570
|
+
name: symbol.name,
|
|
7571
|
+
language: symbol.language,
|
|
7572
|
+
hash: symbol.id
|
|
7573
|
+
}
|
|
7574
|
+
});
|
|
7527
7575
|
}
|
|
7528
7576
|
}
|
|
7529
7577
|
const dedupChunksByName = /* @__PURE__ */ new Map();
|
|
@@ -7531,6 +7579,9 @@ function buildSymbolDefinitionLane(query, database, branchChunkIds, limit, fallb
|
|
|
7531
7579
|
dedupChunksByName.set(chunk.chunkId, chunk);
|
|
7532
7580
|
}
|
|
7533
7581
|
for (const chunk of dedupChunksByName.values()) {
|
|
7582
|
+
if (filePathHint && !pathMatchesHint(chunk.filePath, filePathHint)) {
|
|
7583
|
+
continue;
|
|
7584
|
+
}
|
|
7534
7585
|
upsertChunkCandidate(chunk, identifier, normalizedIdentifier);
|
|
7535
7586
|
}
|
|
7536
7587
|
}
|
|
@@ -8072,6 +8123,10 @@ var Indexer = class _Indexer {
|
|
|
8072
8123
|
const projectHash = hashContent(path14.resolve(this.projectRoot)).slice(0, 16);
|
|
8073
8124
|
return `${key}.${projectHash}`;
|
|
8074
8125
|
}
|
|
8126
|
+
getSymbolExtractorVersionMetadataKey(catalogIdentity = this.getBranchCatalogIdentity()) {
|
|
8127
|
+
const branchKey = this.getBranchCatalogKeyFor(catalogIdentity);
|
|
8128
|
+
return `index.symbolExtractorVersion.${hashContent(branchKey).slice(0, 24)}`;
|
|
8129
|
+
}
|
|
8075
8130
|
hasProjectForceReembedPending() {
|
|
8076
8131
|
return this.config.scope === "global" && this.database?.getMetadata(this.getProjectForceReembedMetadataKey()) === "true";
|
|
8077
8132
|
}
|
|
@@ -9415,7 +9470,8 @@ var Indexer = class _Indexer {
|
|
|
9415
9470
|
}
|
|
9416
9471
|
const branchKey = this.getBranchCatalogKey();
|
|
9417
9472
|
const alreadyIndexed = database.getBranchChunkIds(branchKey).length > 0 && database.getBranchSymbolIds(branchKey).length > 0;
|
|
9418
|
-
|
|
9473
|
+
const symbolsCurrent = database.getMetadata(this.getSymbolExtractorVersionMetadataKey()) === SYMBOL_EXTRACTOR_VERSION;
|
|
9474
|
+
if (alreadyIndexed && symbolsCurrent && this.getStoredBranchCommit(database) === normalizedCommit) {
|
|
9419
9475
|
return { prepared: false };
|
|
9420
9476
|
}
|
|
9421
9477
|
const stats = await this.indexUnlocked(onProgress, [], true);
|
|
@@ -9474,6 +9530,8 @@ var Indexer = class _Indexer {
|
|
|
9474
9530
|
const reparseCachedSwiftFiles = database.getMetadata(swiftParserMetadataKey) !== SWIFT_PARSER_VERSION;
|
|
9475
9531
|
const metalParserMetadataKey = this.getMetalParserVersionMetadataKey();
|
|
9476
9532
|
const reparseCachedMetalFiles = database.getMetadata(metalParserMetadataKey) !== METAL_PARSER_VERSION;
|
|
9533
|
+
const symbolExtractorMetadataKey = this.getSymbolExtractorVersionMetadataKey();
|
|
9534
|
+
const refreshCachedSymbols = database.getMetadata(symbolExtractorMetadataKey) !== SYMBOL_EXTRACTOR_VERSION;
|
|
9477
9535
|
if (reparseCachedSwiftFiles && Array.from(this.fileHashCache.keys()).some(
|
|
9478
9536
|
(filePath) => path14.extname(filePath).toLowerCase() === ".swift"
|
|
9479
9537
|
)) {
|
|
@@ -9517,7 +9575,7 @@ var Indexer = class _Indexer {
|
|
|
9517
9575
|
);
|
|
9518
9576
|
const requiresSwiftParserUpgrade = reparseCachedSwiftFiles && path14.extname(canonicalPath).toLowerCase() === ".swift";
|
|
9519
9577
|
const requiresMetalParserUpgrade = reparseCachedMetalFiles && path14.extname(canonicalPath).toLowerCase() === ".metal";
|
|
9520
|
-
if (cachedHashMatches && !needsCallGraphRefresh && !requiresSwiftParserUpgrade && !requiresMetalParserUpgrade) {
|
|
9578
|
+
if (cachedHashMatches && !needsCallGraphRefresh && !requiresSwiftParserUpgrade && !requiresMetalParserUpgrade && !refreshCachedSymbols) {
|
|
9521
9579
|
unchangedFilePaths.add(canonicalPath);
|
|
9522
9580
|
this.logger.recordCacheHit();
|
|
9523
9581
|
} else {
|
|
@@ -9728,37 +9786,27 @@ var Indexer = class _Indexer {
|
|
|
9728
9786
|
const parsed = parsedFiles[i];
|
|
9729
9787
|
const changedFile = changedFiles[i];
|
|
9730
9788
|
const fileSymbols = [];
|
|
9731
|
-
for (const
|
|
9732
|
-
if (!
|
|
9733
|
-
const existingMetalSymbol = chunk.language === "metal" ? fileSymbols.find(
|
|
9734
|
-
(symbol2) => symbol2.name === chunk.name && symbol2.kind === chunk.chunkType && symbol2.startLine <= chunk.endLine && chunk.startLine <= symbol2.endLine
|
|
9735
|
-
) : void 0;
|
|
9736
|
-
if (existingMetalSymbol) {
|
|
9737
|
-
existingMetalSymbol.startLine = Math.min(existingMetalSymbol.startLine, chunk.startLine);
|
|
9738
|
-
existingMetalSymbol.endLine = Math.max(existingMetalSymbol.endLine, chunk.endLine);
|
|
9739
|
-
existingMetalSymbol.startCol = Math.min(existingMetalSymbol.startCol, chunk.startCol ?? 0);
|
|
9740
|
-
existingMetalSymbol.endCol = Math.max(existingMetalSymbol.endCol, chunk.endCol ?? 0);
|
|
9741
|
-
continue;
|
|
9742
|
-
}
|
|
9789
|
+
for (const parsedSymbol of parsed.symbols) {
|
|
9790
|
+
if (!CALL_GRAPH_SYMBOL_CHUNK_TYPES.has(parsedSymbol.kind)) continue;
|
|
9743
9791
|
const preparedNamespace = this.getPreparedBranchNamespace();
|
|
9744
9792
|
const symbolId = `sym_${hashContent(
|
|
9745
|
-
(preparedNamespace ? `${preparedNamespace}:` : "") + parsed.path + ":" +
|
|
9793
|
+
(preparedNamespace ? `${preparedNamespace}:` : "") + parsed.path + ":" + parsedSymbol.name + ":" + parsedSymbol.kind + ":" + parsedSymbol.startLine + ":" + parsedSymbol.startCol + ":" + changedFile.hash
|
|
9746
9794
|
).slice(0, 16)}`;
|
|
9747
9795
|
const symbol = {
|
|
9748
9796
|
id: symbolId,
|
|
9749
9797
|
filePath: parsed.path,
|
|
9750
|
-
name:
|
|
9751
|
-
kind:
|
|
9752
|
-
startLine:
|
|
9753
|
-
startCol:
|
|
9754
|
-
endLine:
|
|
9755
|
-
endCol:
|
|
9756
|
-
language:
|
|
9798
|
+
name: parsedSymbol.name,
|
|
9799
|
+
kind: parsedSymbol.kind,
|
|
9800
|
+
startLine: parsedSymbol.startLine,
|
|
9801
|
+
startCol: parsedSymbol.startCol,
|
|
9802
|
+
endLine: parsedSymbol.endLine,
|
|
9803
|
+
endCol: parsedSymbol.endCol,
|
|
9804
|
+
language: parsedSymbol.language
|
|
9757
9805
|
};
|
|
9758
9806
|
fileSymbols.push(symbol);
|
|
9759
9807
|
allSymbolIds.add(symbolId);
|
|
9760
9808
|
}
|
|
9761
|
-
const fileLanguage = parsed.chunks[0]?.language;
|
|
9809
|
+
const fileLanguage = parsed.symbols[0]?.language ?? parsed.chunks[0]?.language;
|
|
9762
9810
|
const isCaseInsensitiveLanguage = !!fileLanguage && CASE_INSENSITIVE_LANGUAGES.has(fileLanguage);
|
|
9763
9811
|
const normalizeSymbolKey = (name) => isCaseInsensitiveLanguage ? name.toLowerCase() : name;
|
|
9764
9812
|
const symbolsByName = /* @__PURE__ */ new Map();
|
|
@@ -9874,6 +9922,7 @@ var Indexer = class _Indexer {
|
|
|
9874
9922
|
}
|
|
9875
9923
|
database.setMetadata(swiftParserMetadataKey, SWIFT_PARSER_VERSION);
|
|
9876
9924
|
database.setMetadata(metalParserMetadataKey, METAL_PARSER_VERSION);
|
|
9925
|
+
database.setMetadata(symbolExtractorMetadataKey, SYMBOL_EXTRACTOR_VERSION);
|
|
9877
9926
|
this.saveBranchCommit(database, indexedCommit);
|
|
9878
9927
|
this.saveIndexMetadata(configuredProviderInfo);
|
|
9879
9928
|
this.indexCompatibility = { compatible: true };
|
|
@@ -9910,6 +9959,7 @@ var Indexer = class _Indexer {
|
|
|
9910
9959
|
}
|
|
9911
9960
|
database.setMetadata(swiftParserMetadataKey, SWIFT_PARSER_VERSION);
|
|
9912
9961
|
database.setMetadata(metalParserMetadataKey, METAL_PARSER_VERSION);
|
|
9962
|
+
database.setMetadata(symbolExtractorMetadataKey, SYMBOL_EXTRACTOR_VERSION);
|
|
9913
9963
|
this.saveBranchCommit(database, indexedCommit);
|
|
9914
9964
|
this.saveIndexMetadata(configuredProviderInfo);
|
|
9915
9965
|
this.indexCompatibility = { compatible: true };
|
|
@@ -10189,6 +10239,7 @@ var Indexer = class _Indexer {
|
|
|
10189
10239
|
}
|
|
10190
10240
|
database.setMetadata(swiftParserMetadataKey, SWIFT_PARSER_VERSION);
|
|
10191
10241
|
database.setMetadata(metalParserMetadataKey, METAL_PARSER_VERSION);
|
|
10242
|
+
database.setMetadata(symbolExtractorMetadataKey, SYMBOL_EXTRACTOR_VERSION);
|
|
10192
10243
|
this.saveBranchCommit(database, indexedCommit);
|
|
10193
10244
|
this.saveIndexMetadata(configuredProviderInfo);
|
|
10194
10245
|
this.indexCompatibility = { compatible: true };
|
|
@@ -10327,10 +10378,11 @@ var Indexer = class _Indexer {
|
|
|
10327
10378
|
const keywordResults = await this.keywordSearch(query, maxResults * 4, store, invertedIndex);
|
|
10328
10379
|
const keywordMs = performance2.now() - keywordStartTime;
|
|
10329
10380
|
let branchChunkIds = null;
|
|
10381
|
+
let branchSymbolIds = null;
|
|
10330
10382
|
if (filterByBranch && (this.config.scope === "global" || this.currentBranch !== "default")) {
|
|
10331
|
-
|
|
10332
|
-
|
|
10333
|
-
);
|
|
10383
|
+
const branchCatalogKeys = this.getBranchCatalogKeys();
|
|
10384
|
+
branchChunkIds = new Set(branchCatalogKeys.flatMap((branchKey) => database.getBranchChunkIds(branchKey)));
|
|
10385
|
+
branchSymbolIds = new Set(branchCatalogKeys.flatMap((branchKey) => database.getBranchSymbolIds(branchKey)));
|
|
10334
10386
|
}
|
|
10335
10387
|
const prefilterStartTime = performance2.now();
|
|
10336
10388
|
const shouldPrefilterByBranch = branchChunkIds !== null && (this.config.scope === "global" || branchChunkIds.size > 0);
|
|
@@ -10402,6 +10454,7 @@ var Indexer = class _Indexer {
|
|
|
10402
10454
|
query,
|
|
10403
10455
|
database,
|
|
10404
10456
|
branchChunkIds,
|
|
10457
|
+
branchSymbolIds,
|
|
10405
10458
|
maxResults,
|
|
10406
10459
|
union,
|
|
10407
10460
|
sourceIntent
|
|
@@ -10415,7 +10468,7 @@ var Indexer = class _Indexer {
|
|
|
10415
10468
|
(r) => isLikelyImplementationPath2(r.metadata.filePath) && isImplementationChunkType(r.metadata.chunkType)
|
|
10416
10469
|
);
|
|
10417
10470
|
const filtered = (sourceIntent && hasCodeHints && implementationOnly.length > 0 ? implementationOnly : baseFiltered).slice(0, maxResults);
|
|
10418
|
-
const identifierFallback = !options?.definitionIntent && filtered.length === 0 && identifierHints.length > 0 ? buildSymbolDefinitionLane(query, database, branchChunkIds, maxResults, union, true).filter((r) => matchesSearchFilters(r, options, this.config.search.minScore)).slice(0, maxResults) : [];
|
|
10471
|
+
const identifierFallback = !options?.definitionIntent && filtered.length === 0 && identifierHints.length > 0 ? buildSymbolDefinitionLane(query, database, branchChunkIds, branchSymbolIds, maxResults, union, true).filter((r) => matchesSearchFilters(r, options, this.config.search.minScore)).slice(0, maxResults) : [];
|
|
10419
10472
|
const finalResults = filtered.length > 0 ? filtered : identifierFallback;
|
|
10420
10473
|
const totalSearchMs = performance2.now() - searchStartTime;
|
|
10421
10474
|
this.logger.recordSearch(totalSearchMs, {
|
|
@@ -10572,7 +10625,7 @@ var Indexer = class _Indexer {
|
|
|
10572
10625
|
const extension = path14.extname(filePath).toLowerCase();
|
|
10573
10626
|
return extension === ".php" || extension === ".c" || extension === ".cc" || extension === ".cpp" || extension === ".cxx";
|
|
10574
10627
|
});
|
|
10575
|
-
if (hasSwiftFiles && database.getMetadata(this.getSwiftParserVersionMetadataKey()) !== SWIFT_PARSER_VERSION || hasMetalFiles && database.getMetadata(this.getMetalParserVersionMetadataKey()) !== METAL_PARSER_VERSION || hasCallGraphMigrationFiles && database.getMetadata(this.getCallGraphResolutionMetadataKey()) !== CALL_GRAPH_RESOLUTION_VERSION) {
|
|
10628
|
+
if (hasSwiftFiles && database.getMetadata(this.getSwiftParserVersionMetadataKey()) !== SWIFT_PARSER_VERSION || hasMetalFiles && database.getMetadata(this.getMetalParserVersionMetadataKey()) !== METAL_PARSER_VERSION || database.getMetadata(this.getSymbolExtractorVersionMetadataKey()) !== SYMBOL_EXTRACTOR_VERSION || hasCallGraphMigrationFiles && database.getMetadata(this.getCallGraphResolutionMetadataKey()) !== CALL_GRAPH_RESOLUTION_VERSION) {
|
|
10576
10629
|
return { readable: true, current: false, reason: "migration-required" };
|
|
10577
10630
|
}
|
|
10578
10631
|
if (isGitRepo(this.materializedProjectRoot)) {
|
|
@@ -11280,7 +11333,10 @@ var Indexer = class _Indexer {
|
|
|
11280
11333
|
const requestedRef = opts.pr !== void 0 ? expectedCommit : headRefName ?? resolvedBranch;
|
|
11281
11334
|
const storedCommit = this.getStoredBranchCommit(database, catalogIdentity);
|
|
11282
11335
|
const catalogIdentityMatches = storedCommit === expectedCommit;
|
|
11283
|
-
|
|
11336
|
+
const symbolsCurrent = database.getMetadata(
|
|
11337
|
+
this.getSymbolExtractorVersionMetadataKey(catalogIdentity)
|
|
11338
|
+
) === SYMBOL_EXTRACTOR_VERSION;
|
|
11339
|
+
if (branchSymbols.length === 0 || !catalogIdentityMatches || !symbolsCurrent) {
|
|
11284
11340
|
if (!resolvedBranch || resolvedBranch === "default") {
|
|
11285
11341
|
throw new Error("Run index_codebase first to build the call graph and symbol index for this project.");
|
|
11286
11342
|
}
|
|
@@ -11622,8 +11678,17 @@ function fitTextToContextBudget(text, tokenBudget) {
|
|
|
11622
11678
|
function normalizedLineRange(result) {
|
|
11623
11679
|
return result.startLine <= result.endLine ? { start: result.startLine, end: result.endLine } : { start: result.endLine, end: result.startLine };
|
|
11624
11680
|
}
|
|
11625
|
-
function rankContextCandidates(results) {
|
|
11626
|
-
return results.map((result, originalIndex) => ({ result, originalIndex })).sort((left, right) =>
|
|
11681
|
+
function rankContextCandidates(results, preferImplementationPaths) {
|
|
11682
|
+
return results.map((result, originalIndex) => ({ result, originalIndex })).sort((left, right) => {
|
|
11683
|
+
if (preferImplementationPaths) {
|
|
11684
|
+
const leftIsImplementation = isLikelyImplementationPath(left.result.filePath);
|
|
11685
|
+
const rightIsImplementation = isLikelyImplementationPath(right.result.filePath);
|
|
11686
|
+
if (leftIsImplementation !== rightIsImplementation) {
|
|
11687
|
+
return leftIsImplementation ? -1 : 1;
|
|
11688
|
+
}
|
|
11689
|
+
}
|
|
11690
|
+
return right.result.score - left.result.score || left.originalIndex - right.originalIndex;
|
|
11691
|
+
});
|
|
11627
11692
|
}
|
|
11628
11693
|
function deduplicateContextCandidates(candidates) {
|
|
11629
11694
|
const acceptedByFile = /* @__PURE__ */ new Map();
|
|
@@ -11712,7 +11777,12 @@ function buildContextPack(results, options = {}) {
|
|
|
11712
11777
|
const maxResults = Math.max(0, Math.floor(options.maxResults ?? results.length));
|
|
11713
11778
|
const includeExactSearchHandoff = options.includeExactSearchHandoff ?? false;
|
|
11714
11779
|
const candidateCount = results.length;
|
|
11715
|
-
const deduplicated = deduplicateContextCandidates(
|
|
11780
|
+
const deduplicated = deduplicateContextCandidates(
|
|
11781
|
+
rankContextCandidates(
|
|
11782
|
+
results,
|
|
11783
|
+
options.preferImplementationPaths ?? false
|
|
11784
|
+
)
|
|
11785
|
+
);
|
|
11716
11786
|
const diversified = diversifyContextCandidates(deduplicated);
|
|
11717
11787
|
const duplicateCount = candidateCount - deduplicated.length;
|
|
11718
11788
|
const selectable = diversified.slice(0, maxResults);
|
|
@@ -12084,7 +12154,7 @@ ${truncateContent(r.content)}
|
|
|
12084
12154
|
}
|
|
12085
12155
|
|
|
12086
12156
|
// src/utils/effectiveness-metrics.ts
|
|
12087
|
-
var EFFECTIVENESS_METRICS_SCHEMA_VERSION =
|
|
12157
|
+
var EFFECTIVENESS_METRICS_SCHEMA_VERSION = 3;
|
|
12088
12158
|
var MAX_EFFECTIVENESS_COUNTER = 1e9;
|
|
12089
12159
|
var EFFECTIVENESS_TOOL_ROUTES = [
|
|
12090
12160
|
"context-conceptual",
|
|
@@ -12130,6 +12200,9 @@ var EFFECTIVENESS_SCOPE_RELAXATION_BUCKETS = ["none", "directory", "file-type",
|
|
|
12130
12200
|
function emptyCounterMap(values) {
|
|
12131
12201
|
return Object.fromEntries(values.map((value) => [value, 0]));
|
|
12132
12202
|
}
|
|
12203
|
+
function emptyRouteCounterMap(routes, values) {
|
|
12204
|
+
return Object.fromEntries(routes.map((route) => [route, emptyCounterMap(values)]));
|
|
12205
|
+
}
|
|
12133
12206
|
function boundedNumber(value) {
|
|
12134
12207
|
if (value === void 0 || !Number.isFinite(value)) return 0;
|
|
12135
12208
|
return Math.max(0, Math.floor(value));
|
|
@@ -12178,6 +12251,11 @@ function allowedValue(value, allowed, fallback) {
|
|
|
12178
12251
|
function cloneCounterMap(counters) {
|
|
12179
12252
|
return { ...counters };
|
|
12180
12253
|
}
|
|
12254
|
+
function cloneRouteCounterMap(counters) {
|
|
12255
|
+
return Object.fromEntries(
|
|
12256
|
+
EFFECTIVENESS_TOOL_ROUTES.map((route) => [route, cloneCounterMap(counters[route])])
|
|
12257
|
+
);
|
|
12258
|
+
}
|
|
12181
12259
|
var EffectivenessMetrics = class {
|
|
12182
12260
|
constructor(counterCap = MAX_EFFECTIVENESS_COUNTER) {
|
|
12183
12261
|
this.counterCap = counterCap;
|
|
@@ -12193,7 +12271,7 @@ var EffectivenessMetrics = class {
|
|
|
12193
12271
|
lifetime: "process",
|
|
12194
12272
|
reset: "index_metrics-reset-or-process-exit",
|
|
12195
12273
|
maxCounterValue: this.counterCap,
|
|
12196
|
-
dimensions: "bounded-
|
|
12274
|
+
dimensions: "bounded-route-and-bucketed-performance-only"
|
|
12197
12275
|
},
|
|
12198
12276
|
totalCalls: 0,
|
|
12199
12277
|
toolRoute: emptyCounterMap(EFFECTIVENESS_TOOL_ROUTES),
|
|
@@ -12205,7 +12283,14 @@ var EffectivenessMetrics = class {
|
|
|
12205
12283
|
tokenBudget: emptyCounterMap(EFFECTIVENESS_TOKEN_BUDGET_BUCKETS),
|
|
12206
12284
|
returnedTokenEstimate: emptyCounterMap(EFFECTIVENESS_RETURNED_TOKEN_BUCKETS),
|
|
12207
12285
|
exactHandoffEmitted: emptyCounterMap(EFFECTIVENESS_BOOLEAN_BUCKETS),
|
|
12208
|
-
scopeRelaxation: emptyCounterMap(EFFECTIVENESS_SCOPE_RELAXATION_BUCKETS)
|
|
12286
|
+
scopeRelaxation: emptyCounterMap(EFFECTIVENESS_SCOPE_RELAXATION_BUCKETS),
|
|
12287
|
+
routeOutcome: emptyRouteCounterMap(EFFECTIVENESS_TOOL_ROUTES, EFFECTIVENESS_OUTCOMES),
|
|
12288
|
+
routeLatency: emptyRouteCounterMap(EFFECTIVENESS_TOOL_ROUTES, EFFECTIVENESS_LATENCY_BUCKETS),
|
|
12289
|
+
routeResultCount: emptyRouteCounterMap(EFFECTIVENESS_TOOL_ROUTES, EFFECTIVENESS_RESULT_COUNT_BUCKETS),
|
|
12290
|
+
routeReturnedTokenEstimate: emptyRouteCounterMap(
|
|
12291
|
+
EFFECTIVENESS_TOOL_ROUTES,
|
|
12292
|
+
EFFECTIVENESS_RETURNED_TOKEN_BUCKETS
|
|
12293
|
+
)
|
|
12209
12294
|
};
|
|
12210
12295
|
}
|
|
12211
12296
|
increment(counters, key) {
|
|
@@ -12227,12 +12312,19 @@ var EffectivenessMetrics = class {
|
|
|
12227
12312
|
this.increment(this.snapshot.hostMode, host);
|
|
12228
12313
|
this.increment(this.snapshot.outcome, outcome);
|
|
12229
12314
|
this.increment(this.snapshot.recoveryUsed, recoveryUsed);
|
|
12230
|
-
|
|
12231
|
-
|
|
12315
|
+
const resultCountBucketValue = resultCountBucket(event.resultCount);
|
|
12316
|
+
const latencyBucketValue = latencyBucket(event.latencyMs);
|
|
12317
|
+
const returnedTokenBucketValue = returnedTokenBucket(event.returnedTokenEstimate);
|
|
12318
|
+
this.increment(this.snapshot.resultCount, resultCountBucketValue);
|
|
12319
|
+
this.increment(this.snapshot.latency, latencyBucketValue);
|
|
12232
12320
|
this.increment(this.snapshot.tokenBudget, tokenBudgetBucket(event.tokenBudget));
|
|
12233
|
-
this.increment(this.snapshot.returnedTokenEstimate,
|
|
12321
|
+
this.increment(this.snapshot.returnedTokenEstimate, returnedTokenBucketValue);
|
|
12234
12322
|
this.increment(this.snapshot.exactHandoffEmitted, exactHandoffEmitted);
|
|
12235
12323
|
this.increment(this.snapshot.scopeRelaxation, scopeRelaxation);
|
|
12324
|
+
this.increment(this.snapshot.routeOutcome[route], outcome);
|
|
12325
|
+
this.increment(this.snapshot.routeLatency[route], latencyBucketValue);
|
|
12326
|
+
this.increment(this.snapshot.routeResultCount[route], resultCountBucketValue);
|
|
12327
|
+
this.increment(this.snapshot.routeReturnedTokenEstimate[route], returnedTokenBucketValue);
|
|
12236
12328
|
}
|
|
12237
12329
|
getSnapshot() {
|
|
12238
12330
|
return {
|
|
@@ -12247,7 +12339,11 @@ var EffectivenessMetrics = class {
|
|
|
12247
12339
|
tokenBudget: cloneCounterMap(this.snapshot.tokenBudget),
|
|
12248
12340
|
returnedTokenEstimate: cloneCounterMap(this.snapshot.returnedTokenEstimate),
|
|
12249
12341
|
exactHandoffEmitted: cloneCounterMap(this.snapshot.exactHandoffEmitted),
|
|
12250
|
-
scopeRelaxation: cloneCounterMap(this.snapshot.scopeRelaxation)
|
|
12342
|
+
scopeRelaxation: cloneCounterMap(this.snapshot.scopeRelaxation),
|
|
12343
|
+
routeOutcome: cloneRouteCounterMap(this.snapshot.routeOutcome),
|
|
12344
|
+
routeLatency: cloneRouteCounterMap(this.snapshot.routeLatency),
|
|
12345
|
+
routeResultCount: cloneRouteCounterMap(this.snapshot.routeResultCount),
|
|
12346
|
+
routeReturnedTokenEstimate: cloneRouteCounterMap(this.snapshot.routeReturnedTokenEstimate)
|
|
12251
12347
|
};
|
|
12252
12348
|
}
|
|
12253
12349
|
reset() {
|
|
@@ -12266,6 +12362,7 @@ function resetProcessEffectivenessMetrics() {
|
|
|
12266
12362
|
}
|
|
12267
12363
|
function formatEffectivenessMetrics(snapshot) {
|
|
12268
12364
|
const formatCounters = (counters) => Object.entries(counters).map(([bucket, count]) => `${bucket}=${count}`).join(", ");
|
|
12365
|
+
const formatRouteCounters = (counters) => EFFECTIVENESS_TOOL_ROUTES.map((route) => `${route} => ${formatCounters(counters[route])}`).join("; ");
|
|
12269
12366
|
const lines = [
|
|
12270
12367
|
`Privacy-safe effectiveness (schema v${snapshot.schemaVersion}):`,
|
|
12271
12368
|
` Retention: ${snapshot.retention.storage}, ${snapshot.retention.lifetime}-lifetime; reset with index_metrics(reset=true) or process exit`,
|
|
@@ -12280,6 +12377,10 @@ function formatEffectivenessMetrics(snapshot) {
|
|
|
12280
12377
|
` Latency bucket: ${formatCounters(snapshot.latency)}`,
|
|
12281
12378
|
` Token-budget bucket: ${formatCounters(snapshot.tokenBudget)}`,
|
|
12282
12379
|
` Returned-token estimate: ${formatCounters(snapshot.returnedTokenEstimate)}`,
|
|
12380
|
+
` Route outcome buckets: ${formatRouteCounters(snapshot.routeOutcome)}`,
|
|
12381
|
+
` Route latency buckets: ${formatRouteCounters(snapshot.routeLatency)}`,
|
|
12382
|
+
` Route result-count buckets: ${formatRouteCounters(snapshot.routeResultCount)}`,
|
|
12383
|
+
` Route returned-token buckets: ${formatRouteCounters(snapshot.routeReturnedTokenEstimate)}`,
|
|
12283
12384
|
` Exact handoff emitted: ${formatCounters(snapshot.exactHandoffEmitted)}`,
|
|
12284
12385
|
` Scope relaxation: ${formatCounters(snapshot.scopeRelaxation)}`,
|
|
12285
12386
|
" Privacy: no queries, response text, source, symbols, paths, repository names, user identity, or stable identifiers are retained."
|
|
@@ -12291,6 +12392,103 @@ function formatEffectivenessMetrics(snapshot) {
|
|
|
12291
12392
|
import { existsSync as existsSync9, realpathSync as realpathSync4 } from "fs";
|
|
12292
12393
|
import * as os6 from "os";
|
|
12293
12394
|
import * as path16 from "path";
|
|
12395
|
+
|
|
12396
|
+
// src/utils/power-source.ts
|
|
12397
|
+
import * as childProcess from "child_process";
|
|
12398
|
+
var POWER_SOURCE_RECHECK_DELAY_MS = 6e4;
|
|
12399
|
+
var PMSET_TIMEOUT_MS = 5e3;
|
|
12400
|
+
function getErrorMessage4(error) {
|
|
12401
|
+
return error instanceof Error ? error.message : String(error);
|
|
12402
|
+
}
|
|
12403
|
+
function runCommand(file, args, options) {
|
|
12404
|
+
return new Promise((resolve14, reject) => {
|
|
12405
|
+
childProcess.execFile(
|
|
12406
|
+
file,
|
|
12407
|
+
args,
|
|
12408
|
+
{ encoding: "utf8", timeout: options.timeoutMs },
|
|
12409
|
+
(error, stdout) => {
|
|
12410
|
+
if (error) {
|
|
12411
|
+
reject(error);
|
|
12412
|
+
return;
|
|
12413
|
+
}
|
|
12414
|
+
resolve14(stdout);
|
|
12415
|
+
}
|
|
12416
|
+
);
|
|
12417
|
+
});
|
|
12418
|
+
}
|
|
12419
|
+
function parseMacOsPowerSource(output) {
|
|
12420
|
+
const match = output.match(/Now drawing from '([^']+)'/i);
|
|
12421
|
+
if (!match) {
|
|
12422
|
+
return "unknown";
|
|
12423
|
+
}
|
|
12424
|
+
const source = match[1].toLowerCase();
|
|
12425
|
+
if (source === "battery power") {
|
|
12426
|
+
return "battery";
|
|
12427
|
+
}
|
|
12428
|
+
if (source === "ac power") {
|
|
12429
|
+
return "ac";
|
|
12430
|
+
}
|
|
12431
|
+
return "unknown";
|
|
12432
|
+
}
|
|
12433
|
+
async function readMacOsPowerSource(commandRunner = runCommand) {
|
|
12434
|
+
const output = await commandRunner(
|
|
12435
|
+
"/usr/bin/pmset",
|
|
12436
|
+
["-g", "batt"],
|
|
12437
|
+
{ timeoutMs: PMSET_TIMEOUT_MS }
|
|
12438
|
+
);
|
|
12439
|
+
return parseMacOsPowerSource(output);
|
|
12440
|
+
}
|
|
12441
|
+
var MacOsBackgroundIndexingPolicy = class {
|
|
12442
|
+
constructor(readPowerSource, recheckDelayMs) {
|
|
12443
|
+
this.readPowerSource = readPowerSource;
|
|
12444
|
+
this.recheckDelayMs = recheckDelayMs;
|
|
12445
|
+
}
|
|
12446
|
+
readPowerSource;
|
|
12447
|
+
recheckDelayMs;
|
|
12448
|
+
lastPaused = null;
|
|
12449
|
+
reportedFailure = false;
|
|
12450
|
+
isPaused() {
|
|
12451
|
+
return this.checkPowerSource();
|
|
12452
|
+
}
|
|
12453
|
+
async checkPowerSource() {
|
|
12454
|
+
try {
|
|
12455
|
+
const source = await this.readPowerSource();
|
|
12456
|
+
if (source === "unknown") {
|
|
12457
|
+
throw new Error("pmset returned an unrecognized power source");
|
|
12458
|
+
}
|
|
12459
|
+
this.reportedFailure = false;
|
|
12460
|
+
const paused = source === "battery";
|
|
12461
|
+
if (paused && this.lastPaused !== true) {
|
|
12462
|
+
console.warn("[codebase-index] Background indexing paused while macOS is using battery power.");
|
|
12463
|
+
} else if (!paused && this.lastPaused === true) {
|
|
12464
|
+
console.warn("[codebase-index] AC power detected; resuming pending background indexing.");
|
|
12465
|
+
}
|
|
12466
|
+
this.lastPaused = paused;
|
|
12467
|
+
return paused;
|
|
12468
|
+
} catch (error) {
|
|
12469
|
+
if (!this.reportedFailure) {
|
|
12470
|
+
console.error(
|
|
12471
|
+
`[codebase-index] Failed to determine the macOS power source; background indexing will continue: ${getErrorMessage4(error)}`
|
|
12472
|
+
);
|
|
12473
|
+
this.reportedFailure = true;
|
|
12474
|
+
}
|
|
12475
|
+
this.lastPaused = false;
|
|
12476
|
+
return false;
|
|
12477
|
+
}
|
|
12478
|
+
}
|
|
12479
|
+
};
|
|
12480
|
+
function createBackgroundIndexingPolicy(pauseOnBattery, options = {}) {
|
|
12481
|
+
const platform2 = options.platform ?? process.platform;
|
|
12482
|
+
if (!pauseOnBattery || platform2 !== "darwin") {
|
|
12483
|
+
return null;
|
|
12484
|
+
}
|
|
12485
|
+
return new MacOsBackgroundIndexingPolicy(
|
|
12486
|
+
options.readPowerSource ?? readMacOsPowerSource,
|
|
12487
|
+
options.recheckDelayMs ?? POWER_SOURCE_RECHECK_DELAY_MS
|
|
12488
|
+
);
|
|
12489
|
+
}
|
|
12490
|
+
|
|
12491
|
+
// src/utils/auto-index.ts
|
|
12294
12492
|
var MAX_RETRY_DELAY_MS = 1e4;
|
|
12295
12493
|
var SHUTDOWN_WAIT_MS = 2e3;
|
|
12296
12494
|
var coordinators = /* @__PURE__ */ new Map();
|
|
@@ -12407,7 +12605,13 @@ var AutoIndexCoordinator = class {
|
|
|
12407
12605
|
activation = Promise.resolve();
|
|
12408
12606
|
inFlight = null;
|
|
12409
12607
|
activeRequest = null;
|
|
12608
|
+
batteryCheck = null;
|
|
12609
|
+
batteryIndexJob = null;
|
|
12610
|
+
batteryDeferredRequest = null;
|
|
12611
|
+
batteryRetryTimer = null;
|
|
12612
|
+
resolveBatteryRetry = null;
|
|
12410
12613
|
pendingRequest = null;
|
|
12614
|
+
pendingFollowUp = null;
|
|
12411
12615
|
abortController = null;
|
|
12412
12616
|
stopped = false;
|
|
12413
12617
|
constructor(registration) {
|
|
@@ -12420,6 +12624,7 @@ var AutoIndexCoordinator = class {
|
|
|
12420
12624
|
};
|
|
12421
12625
|
}
|
|
12422
12626
|
update(registration) {
|
|
12627
|
+
const pauseOnBatteryChanged = registration.config.indexing.pauseBackgroundIndexingOnBattery !== this.registration.config.indexing.pauseBackgroundIndexingOnBattery;
|
|
12423
12628
|
this.registration = registration;
|
|
12424
12629
|
this.status.enabled = registration.config.indexing.autoIndex;
|
|
12425
12630
|
this.status.blockedReason = registration.blockedReason;
|
|
@@ -12435,6 +12640,9 @@ var AutoIndexCoordinator = class {
|
|
|
12435
12640
|
this.setState("idle", { source: void 0 });
|
|
12436
12641
|
}
|
|
12437
12642
|
}
|
|
12643
|
+
if (pauseOnBatteryChanged) {
|
|
12644
|
+
this.cancelBatteryRetry();
|
|
12645
|
+
}
|
|
12438
12646
|
}
|
|
12439
12647
|
activateAfter(activation) {
|
|
12440
12648
|
this.activation = activation;
|
|
@@ -12456,7 +12664,26 @@ var AutoIndexCoordinator = class {
|
|
|
12456
12664
|
if (this.stopped) {
|
|
12457
12665
|
return Promise.resolve({ outcome: "stopped" });
|
|
12458
12666
|
}
|
|
12459
|
-
return this.activation.then(() => this.
|
|
12667
|
+
return this.activation.then(() => this.enqueueBatteryAwareRequest(request));
|
|
12668
|
+
}
|
|
12669
|
+
enqueueBatteryAwareRequest(request) {
|
|
12670
|
+
if (!this.shouldDeferForBattery(request)) {
|
|
12671
|
+
return this.enqueueRequest(request);
|
|
12672
|
+
}
|
|
12673
|
+
if (this.batteryCheck && this.batteryIndexJob !== null && this.batteryIndexJob === this.inFlight) {
|
|
12674
|
+
return this.enqueueRequest(request);
|
|
12675
|
+
}
|
|
12676
|
+
this.batteryDeferredRequest = mergeRequests(this.batteryDeferredRequest, request);
|
|
12677
|
+
if (this.batteryCheck) {
|
|
12678
|
+
return this.batteryCheck;
|
|
12679
|
+
}
|
|
12680
|
+
const batteryCheck = this.waitForACPower();
|
|
12681
|
+
this.batteryCheck = batteryCheck;
|
|
12682
|
+
void batteryCheck.then(
|
|
12683
|
+
() => this.finishBatteryCheck(batteryCheck),
|
|
12684
|
+
() => this.finishBatteryCheck(batteryCheck)
|
|
12685
|
+
);
|
|
12686
|
+
return batteryCheck;
|
|
12460
12687
|
}
|
|
12461
12688
|
enqueueRequest(request) {
|
|
12462
12689
|
if (this.stopped || !this.canRun(request)) {
|
|
@@ -12474,6 +12701,11 @@ var AutoIndexCoordinator = class {
|
|
|
12474
12701
|
}
|
|
12475
12702
|
if (request.source === "watcher") {
|
|
12476
12703
|
this.pendingRequest = mergeRequests(this.pendingRequest, request);
|
|
12704
|
+
const active = this.inFlight;
|
|
12705
|
+
return active.then(() => {
|
|
12706
|
+
if (this.stopped) return { outcome: "stopped" };
|
|
12707
|
+
return this.pendingFollowUp ?? { outcome: "stopped" };
|
|
12708
|
+
});
|
|
12477
12709
|
}
|
|
12478
12710
|
return this.inFlight;
|
|
12479
12711
|
}
|
|
@@ -12490,6 +12722,8 @@ var AutoIndexCoordinator = class {
|
|
|
12490
12722
|
}
|
|
12491
12723
|
async stop(waitForCompletion = false) {
|
|
12492
12724
|
this.stopped = true;
|
|
12725
|
+
this.batteryDeferredRequest = null;
|
|
12726
|
+
this.cancelBatteryRetry();
|
|
12493
12727
|
this.pendingRequest = null;
|
|
12494
12728
|
this.abortController?.abort();
|
|
12495
12729
|
this.setState("stopped", {
|
|
@@ -12519,10 +12753,20 @@ var AutoIndexCoordinator = class {
|
|
|
12519
12753
|
this.inFlight = null;
|
|
12520
12754
|
this.activeRequest = null;
|
|
12521
12755
|
this.abortController = null;
|
|
12756
|
+
if (this.batteryIndexJob === job) {
|
|
12757
|
+
this.batteryIndexJob = null;
|
|
12758
|
+
this.batteryCheck = null;
|
|
12759
|
+
}
|
|
12522
12760
|
const pending = this.pendingRequest;
|
|
12523
12761
|
this.pendingRequest = null;
|
|
12524
12762
|
if (pending && !this.stopped) {
|
|
12525
|
-
this.
|
|
12763
|
+
const followUp = this.request(pending);
|
|
12764
|
+
this.pendingFollowUp = followUp;
|
|
12765
|
+
void followUp.then(() => {
|
|
12766
|
+
if (this.pendingFollowUp === followUp) {
|
|
12767
|
+
this.pendingFollowUp = null;
|
|
12768
|
+
}
|
|
12769
|
+
});
|
|
12526
12770
|
}
|
|
12527
12771
|
});
|
|
12528
12772
|
return job;
|
|
@@ -12686,6 +12930,68 @@ var AutoIndexCoordinator = class {
|
|
|
12686
12930
|
}
|
|
12687
12931
|
return this.registration.safeToRun && this.registration.config.indexing.autoIndex;
|
|
12688
12932
|
}
|
|
12933
|
+
shouldDeferForBattery(request) {
|
|
12934
|
+
return this.registration.backgroundIndexingPolicy !== null && (request.source === "startup" || request.source === "watcher");
|
|
12935
|
+
}
|
|
12936
|
+
async waitForACPower() {
|
|
12937
|
+
while (!this.stopped) {
|
|
12938
|
+
const policy = this.registration.backgroundIndexingPolicy;
|
|
12939
|
+
if (!policy || !await this.isBatteryPauseActive(policy)) {
|
|
12940
|
+
const request = this.batteryDeferredRequest;
|
|
12941
|
+
this.batteryDeferredRequest = null;
|
|
12942
|
+
if (!request) return { outcome: "stopped" };
|
|
12943
|
+
const job = this.enqueueRequest(request);
|
|
12944
|
+
if (this.inFlight === job) {
|
|
12945
|
+
this.batteryIndexJob = job;
|
|
12946
|
+
}
|
|
12947
|
+
return job;
|
|
12948
|
+
}
|
|
12949
|
+
await this.waitForBatteryRetry(policy.recheckDelayMs);
|
|
12950
|
+
}
|
|
12951
|
+
return { outcome: "stopped" };
|
|
12952
|
+
}
|
|
12953
|
+
async isBatteryPauseActive(policy) {
|
|
12954
|
+
try {
|
|
12955
|
+
return await policy.isPaused();
|
|
12956
|
+
} catch (error) {
|
|
12957
|
+
console.error(
|
|
12958
|
+
`[codebase-index] Failed to apply the background indexing power policy; background indexing will continue: ${safeFailureMessage(error)}`
|
|
12959
|
+
);
|
|
12960
|
+
return false;
|
|
12961
|
+
}
|
|
12962
|
+
}
|
|
12963
|
+
waitForBatteryRetry(delayMs) {
|
|
12964
|
+
return new Promise((resolve14) => {
|
|
12965
|
+
const timer = setTimeout(() => {
|
|
12966
|
+
if (this.batteryRetryTimer === timer) {
|
|
12967
|
+
this.batteryRetryTimer = null;
|
|
12968
|
+
this.resolveBatteryRetry = null;
|
|
12969
|
+
}
|
|
12970
|
+
resolve14();
|
|
12971
|
+
}, delayMs);
|
|
12972
|
+
timer.unref?.();
|
|
12973
|
+
this.batteryRetryTimer = timer;
|
|
12974
|
+
this.resolveBatteryRetry = resolve14;
|
|
12975
|
+
});
|
|
12976
|
+
}
|
|
12977
|
+
cancelBatteryRetry() {
|
|
12978
|
+
if (this.batteryRetryTimer) {
|
|
12979
|
+
clearTimeout(this.batteryRetryTimer);
|
|
12980
|
+
this.batteryRetryTimer = null;
|
|
12981
|
+
}
|
|
12982
|
+
const resolve14 = this.resolveBatteryRetry;
|
|
12983
|
+
this.resolveBatteryRetry = null;
|
|
12984
|
+
resolve14?.();
|
|
12985
|
+
}
|
|
12986
|
+
finishBatteryCheck(batteryCheck) {
|
|
12987
|
+
if (this.batteryCheck !== batteryCheck) return;
|
|
12988
|
+
this.batteryCheck = null;
|
|
12989
|
+
const deferredRequest = this.batteryDeferredRequest;
|
|
12990
|
+
this.batteryDeferredRequest = null;
|
|
12991
|
+
if (deferredRequest && !this.stopped) {
|
|
12992
|
+
void this.request(deferredRequest);
|
|
12993
|
+
}
|
|
12994
|
+
}
|
|
12689
12995
|
};
|
|
12690
12996
|
function getCoordinator(projectRoot, host) {
|
|
12691
12997
|
const key = coordinatorKeysByProject.get(projectLookupKey(projectRoot, host));
|
|
@@ -12695,6 +13001,9 @@ function configureAutoIndex(projectRoot, host, config, getIndexer) {
|
|
|
12695
13001
|
const projectKey = projectLookupKey(projectRoot, host);
|
|
12696
13002
|
const safety = getProjectSafety(projectRoot, config);
|
|
12697
13003
|
const registration = {
|
|
13004
|
+
backgroundIndexingPolicy: createBackgroundIndexingPolicy(
|
|
13005
|
+
config.indexing.pauseBackgroundIndexingOnBattery
|
|
13006
|
+
),
|
|
12698
13007
|
config,
|
|
12699
13008
|
getIndexer,
|
|
12700
13009
|
projectRoot,
|
|
@@ -15446,7 +15755,10 @@ function createWatcherWithIndexer(getIndexer, projectRoot, config, host = "openc
|
|
|
15446
15755
|
if (isGitRepo(projectRoot)) {
|
|
15447
15756
|
gitWatcher = new GitHeadWatcher(projectRoot);
|
|
15448
15757
|
gitWatcher.start(async (oldBranch, newBranch) => {
|
|
15449
|
-
|
|
15758
|
+
getIndexer().getLogger().branch("info", "Branch changed", {
|
|
15759
|
+
oldBranch,
|
|
15760
|
+
newBranch
|
|
15761
|
+
});
|
|
15450
15762
|
requestReindex();
|
|
15451
15763
|
});
|
|
15452
15764
|
}
|
|
@@ -15998,6 +16310,7 @@ Explicit symbol lookup only; conceptual search was not attempted.`
|
|
|
15998
16310
|
const results = await tryConceptualSearch(attempt.queryText, attempt.scope, attempt.relaxed);
|
|
15999
16311
|
if (results.length > 0) {
|
|
16000
16312
|
const heading = buildPackHeading("conceptual", decisions);
|
|
16313
|
+
const intent = analyzeQueryIntent(attempt.queryText);
|
|
16001
16314
|
return toResult(
|
|
16002
16315
|
"conceptual",
|
|
16003
16316
|
attempt.queryText,
|
|
@@ -16005,7 +16318,8 @@ Explicit symbol lookup only; conceptual search was not attempted.`
|
|
|
16005
16318
|
tokenBudget,
|
|
16006
16319
|
maxResults: limit,
|
|
16007
16320
|
heading,
|
|
16008
|
-
includeExactSearchHandoff: true
|
|
16321
|
+
includeExactSearchHandoff: true,
|
|
16322
|
+
preferImplementationPaths: intent.preferSourcePaths || intent.primary !== "docs" && intent.primary !== "test"
|
|
16009
16323
|
})
|
|
16010
16324
|
);
|
|
16011
16325
|
}
|
|
@@ -17295,6 +17609,21 @@ var CONCEPTUAL_DISCOVERY_HINTS = [
|
|
|
17295
17609
|
"pattern",
|
|
17296
17610
|
"code that"
|
|
17297
17611
|
];
|
|
17612
|
+
var BROAD_LOCAL_TASK_HINTS = [
|
|
17613
|
+
"fix the bug",
|
|
17614
|
+
"fix this",
|
|
17615
|
+
"fix issue",
|
|
17616
|
+
"implement ",
|
|
17617
|
+
"add support",
|
|
17618
|
+
"investigate ",
|
|
17619
|
+
"debug ",
|
|
17620
|
+
"refactor ",
|
|
17621
|
+
"review this",
|
|
17622
|
+
"review codebase",
|
|
17623
|
+
"review the codebase",
|
|
17624
|
+
"audit this",
|
|
17625
|
+
"audit the codebase"
|
|
17626
|
+
];
|
|
17298
17627
|
var DEFINITION_HINTS = [
|
|
17299
17628
|
"defined",
|
|
17300
17629
|
"definition",
|
|
@@ -17341,6 +17670,9 @@ function isExternalLookup(text) {
|
|
|
17341
17670
|
function hasConceptualDiscoveryHint(text) {
|
|
17342
17671
|
return includesHint(text, CONCEPTUAL_DISCOVERY_HINTS);
|
|
17343
17672
|
}
|
|
17673
|
+
function hasBroadLocalTaskHint(text) {
|
|
17674
|
+
return includesHint(text, BROAD_LOCAL_TASK_HINTS);
|
|
17675
|
+
}
|
|
17344
17676
|
function hasDefinitionHint(text) {
|
|
17345
17677
|
return includesHint(text, DEFINITION_HINTS);
|
|
17346
17678
|
}
|
|
@@ -17398,10 +17730,11 @@ function assessRoutingIntent(text) {
|
|
|
17398
17730
|
const matchedDefinitionHint = hasDefinitionHint(lowered);
|
|
17399
17731
|
const matchedExactMatchHint = hasExactMatchHint(lowered);
|
|
17400
17732
|
const matchedNonDiscoveryHint = hasNonDiscoveryHint(lowered);
|
|
17733
|
+
const matchedBroadLocalTask = hasBroadLocalTaskHint(lowered);
|
|
17401
17734
|
const hasIdentifier = hasIdentifierShape(normalizedText);
|
|
17402
17735
|
const hasQuotedIdentifier = containsQuotedIdentifier(normalizedText);
|
|
17403
17736
|
const shortQuery = countWords(lowered) <= 10;
|
|
17404
|
-
if (matchedNonDiscoveryHint && !matchedConceptualHint) {
|
|
17737
|
+
if (matchedNonDiscoveryHint && !matchedConceptualHint && !matchedBroadLocalTask) {
|
|
17405
17738
|
return {
|
|
17406
17739
|
intent: "other",
|
|
17407
17740
|
text: normalizedText,
|
|
@@ -17422,6 +17755,13 @@ function assessRoutingIntent(text) {
|
|
|
17422
17755
|
reason: "definition_lookup_request"
|
|
17423
17756
|
};
|
|
17424
17757
|
}
|
|
17758
|
+
if (matchedBroadLocalTask) {
|
|
17759
|
+
return {
|
|
17760
|
+
intent: "local_broad_task",
|
|
17761
|
+
text: normalizedText,
|
|
17762
|
+
reason: "broad_local_code_task"
|
|
17763
|
+
};
|
|
17764
|
+
}
|
|
17425
17765
|
if ((matchedExactMatchHint || hasQuotedIdentifier || hasIdentifier) && !matchedConceptualHint && shortQuery) {
|
|
17426
17766
|
return {
|
|
17427
17767
|
intent: "exact_identifier",
|
|
@@ -17449,15 +17789,15 @@ function buildRoutingHint(assessment, status, includeGraphHandoff = false) {
|
|
|
17449
17789
|
}
|
|
17450
17790
|
return "For this turn, prefer `implementation_lookup` to find the authoritative definition site. Use `codebase_search` only if no definition is found, and use `grep` for exhaustive literal matches.";
|
|
17451
17791
|
}
|
|
17452
|
-
if (assessment.intent !== "local_conceptual") {
|
|
17792
|
+
if (assessment.intent !== "local_conceptual" && assessment.intent !== "local_broad_task") {
|
|
17453
17793
|
return null;
|
|
17454
17794
|
}
|
|
17455
17795
|
if (!status || !status.indexed || status.compatibility?.compatible === false) {
|
|
17456
17796
|
const graphHandoff2 = includeGraphHandoff ? " Use graph tools after semantic discovery identifies relevant symbols." : "";
|
|
17457
|
-
return `For this turn, if local code discovery by behavior is needed, check \`index_status\` first and run \`index_codebase\` if the index is missing or incompatible.${graphHandoff2} Use \`grep\` for exact identifiers or exhaustive matches.`;
|
|
17797
|
+
return `For this turn, if local code discovery by behavior is needed, check \`index_status\` first and run \`index_codebase\` if the index is missing or incompatible.${graphHandoff2} Then use \`codebase_context\` as the first local repository lookup. Use \`grep\` for exact identifiers or exhaustive matches.`;
|
|
17458
17798
|
}
|
|
17459
17799
|
const graphHandoff = includeGraphHandoff ? " before graph tools such as `call_graph`, `call_graph_path`, `pr_impact`, or OMO CodeGraph" : "";
|
|
17460
|
-
return `For this turn, prefer \`
|
|
17800
|
+
return `For this turn, prefer \`codebase_context\` for local code discovery, then use \`codebase_peek\` for metadata and \`codebase_search\` when you need implementation content${graphHandoff}. Use \`grep\` for exact identifiers or exhaustive matches.`;
|
|
17461
17801
|
}
|
|
17462
17802
|
var RoutingHintController = class {
|
|
17463
17803
|
constructor(getStatus, maxSessions = 200, includeGraphHandoff = false) {
|
|
@@ -17474,7 +17814,7 @@ var RoutingHintController = class {
|
|
|
17474
17814
|
this.compactSessions();
|
|
17475
17815
|
this.sessionState.set(sessionID, {
|
|
17476
17816
|
assessment,
|
|
17477
|
-
pendingHint: assessment.intent === "local_conceptual" || assessment.intent === "definition_lookup",
|
|
17817
|
+
pendingHint: assessment.intent === "local_conceptual" || assessment.intent === "local_broad_task" || assessment.intent === "definition_lookup",
|
|
17478
17818
|
updatedAt: Date.now()
|
|
17479
17819
|
});
|
|
17480
17820
|
return assessment;
|
|
@@ -17489,6 +17829,9 @@ var RoutingHintController = class {
|
|
|
17489
17829
|
}
|
|
17490
17830
|
const status = await this.safeGetStatus();
|
|
17491
17831
|
const hint = buildRoutingHint(state.assessment, status, this.includeGraphHandoff);
|
|
17832
|
+
state.pendingHint = false;
|
|
17833
|
+
state.updatedAt = Date.now();
|
|
17834
|
+
this.sessionState.set(sessionID, state);
|
|
17492
17835
|
return hint ? [hint] : [];
|
|
17493
17836
|
}
|
|
17494
17837
|
markToolUsed(sessionID, toolName) {
|
|
@@ -17496,7 +17839,7 @@ var RoutingHintController = class {
|
|
|
17496
17839
|
if (!state || !state.pendingHint) {
|
|
17497
17840
|
return;
|
|
17498
17841
|
}
|
|
17499
|
-
if (toolName === "codebase_peek" || toolName === "codebase_search" || toolName === "implementation_lookup" || toolName === "index_status" || toolName === "index_codebase") {
|
|
17842
|
+
if (toolName === "codebase_context" || toolName === "codebase_peek" || toolName === "codebase_search" || toolName === "implementation_lookup" || toolName === "index_status" || toolName === "index_codebase") {
|
|
17500
17843
|
state.pendingHint = false;
|
|
17501
17844
|
state.updatedAt = Date.now();
|
|
17502
17845
|
this.sessionState.set(sessionID, state);
|
|
@@ -17552,9 +17895,15 @@ function appendRoutingHints(output, hints, preferredRole) {
|
|
|
17552
17895
|
output.system.push(...hints);
|
|
17553
17896
|
}
|
|
17554
17897
|
}
|
|
17898
|
+
function resolveProjectRoot(directory, worktree) {
|
|
17899
|
+
if (worktree && isGitRepo(worktree)) {
|
|
17900
|
+
return worktree;
|
|
17901
|
+
}
|
|
17902
|
+
return directory;
|
|
17903
|
+
}
|
|
17555
17904
|
var plugin = async ({ directory, worktree }) => {
|
|
17556
17905
|
try {
|
|
17557
|
-
const projectRoot = worktree
|
|
17906
|
+
const projectRoot = resolveProjectRoot(directory, worktree);
|
|
17558
17907
|
const rawConfig = loadMergedConfig(projectRoot);
|
|
17559
17908
|
const config = parseConfig(rawConfig);
|
|
17560
17909
|
initializeTools2(projectRoot, config);
|