opencode-codebase-index 0.15.0 → 0.16.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 +2 -2
- package/README.md +33 -8
- package/dist/cli.cjs +144 -51
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +144 -51
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +13 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +13 -3
- package/dist/index.js.map +1 -1
- package/dist/pi-extension.cjs +92 -9
- package/dist/pi-extension.cjs.map +1 -1
- package/dist/pi-extension.js +92 -9
- package/dist/pi-extension.js.map +1 -1
- package/hooks/hooks.json +2 -2
- 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.win32-x64-msvc.node +0 -0
- package/package.json +1 -1
- package/skills/codebase-search/SKILL.md +9 -7
package/dist/pi-extension.js
CHANGED
|
@@ -8901,10 +8901,19 @@ var Indexer = class {
|
|
|
8901
8901
|
});
|
|
8902
8902
|
const embeddingStartTime = performance2.now();
|
|
8903
8903
|
const embeddingQuery = stripFilePathHint(query);
|
|
8904
|
-
|
|
8904
|
+
let embedding;
|
|
8905
|
+
try {
|
|
8906
|
+
embedding = await this.getQueryEmbedding(embeddingQuery, provider);
|
|
8907
|
+
} catch (error) {
|
|
8908
|
+
this.logger.warn("Query embedding failed; falling back to keyword-only search", {
|
|
8909
|
+
query,
|
|
8910
|
+
error: getErrorMessage2(error),
|
|
8911
|
+
action: "Check the embedding provider configuration and retry search after restoring provider health."
|
|
8912
|
+
});
|
|
8913
|
+
}
|
|
8905
8914
|
const embeddingMs = performance2.now() - embeddingStartTime;
|
|
8906
8915
|
const vectorStartTime = performance2.now();
|
|
8907
|
-
const semanticResults = store.search(embedding, maxResults * 4);
|
|
8916
|
+
const semanticResults = embedding ? store.search(embedding, maxResults * 4) : [];
|
|
8908
8917
|
const vectorMs = performance2.now() - vectorStartTime;
|
|
8909
8918
|
const keywordStartTime = performance2.now();
|
|
8910
8919
|
const keywordResults = await this.keywordSearch(query, maxResults * 4, store, invertedIndex);
|
|
@@ -8939,12 +8948,13 @@ var Indexer = class {
|
|
|
8939
8948
|
});
|
|
8940
8949
|
}
|
|
8941
8950
|
const fusionStartTime = performance2.now();
|
|
8951
|
+
const rankingHybridWeight = embedding === void 0 && fusionStrategy === "weighted" ? 1 : effectiveHybridWeight;
|
|
8942
8952
|
const combined = rankHybridResults(query, semanticCandidates, keywordCandidates, {
|
|
8943
8953
|
fusionStrategy,
|
|
8944
8954
|
rrfK,
|
|
8945
8955
|
rerankTopN,
|
|
8946
8956
|
limit: maxResults,
|
|
8947
|
-
hybridWeight:
|
|
8957
|
+
hybridWeight: rankingHybridWeight,
|
|
8948
8958
|
prioritizeSourcePaths: sourceIntent
|
|
8949
8959
|
});
|
|
8950
8960
|
const rerankedCombined = await this.rerankCandidatesWithApi(query, combined, {
|
|
@@ -10064,6 +10074,17 @@ function calculatePercentage(progress) {
|
|
|
10064
10074
|
if (progress.phase === "storing") return 95;
|
|
10065
10075
|
return 0;
|
|
10066
10076
|
}
|
|
10077
|
+
function formatCodebasePeek(results) {
|
|
10078
|
+
if (results.length === 0) {
|
|
10079
|
+
return "No matching code found. Try a different query or run index_codebase first.";
|
|
10080
|
+
}
|
|
10081
|
+
const formatted = results.map((r, idx) => {
|
|
10082
|
+
const location = `${r.filePath}:${r.startLine}-${r.endLine}`;
|
|
10083
|
+
const name = r.name ? `"${r.name}"` : "(anonymous)";
|
|
10084
|
+
return `[${idx + 1}] ${r.chunkType} ${name} at ${location} (score: ${r.score.toFixed(2)})${formatBlame(r)}`;
|
|
10085
|
+
});
|
|
10086
|
+
return formatted.join("\n");
|
|
10087
|
+
}
|
|
10067
10088
|
function formatHealthCheck(result) {
|
|
10068
10089
|
if (result.resetCorruptedIndex) {
|
|
10069
10090
|
return result.warning ?? "Detected a corrupted local index and reset it. Run index_codebase to rebuild search data.";
|
|
@@ -10650,10 +10671,67 @@ function projectRoot2(ctx) {
|
|
|
10650
10671
|
return ctx?.cwd ?? process.cwd();
|
|
10651
10672
|
}
|
|
10652
10673
|
function codebaseIndexPiExtension(pi) {
|
|
10674
|
+
pi.registerTool({
|
|
10675
|
+
name: "codebase_context",
|
|
10676
|
+
label: "Codebase Context",
|
|
10677
|
+
description: "PREFERRED FIRST TOOL for any repository question. Check index_status when freshness is unknown, then use this tool for low-token location discovery and dependency flow.",
|
|
10678
|
+
parameters: Type2.Object({
|
|
10679
|
+
query: Type2.String({ description: "Natural language description of what code you're trying to locate" }),
|
|
10680
|
+
from: Type2.Optional(Type2.String({ description: "Source symbol when asking for a dependency path." })),
|
|
10681
|
+
to: Type2.Optional(Type2.String({ description: "Target symbol when asking for a dependency path." })),
|
|
10682
|
+
symbol: Type2.Optional(Type2.String({ description: "Exact symbol name for an authoritative definition lookup." })),
|
|
10683
|
+
limit: Type2.Optional(Type2.Number({ description: "Maximum results (default: 10)" })),
|
|
10684
|
+
maxDepth: Type2.Optional(Type2.Number({ description: "Maximum call-graph traversal depth for from/to paths" })),
|
|
10685
|
+
fileType: Type2.Optional(Type2.String({ description: "Filter by file extension, e.g., ts, py, rs" })),
|
|
10686
|
+
directory: Type2.Optional(Type2.String({ description: "Filter by directory path" }))
|
|
10687
|
+
}),
|
|
10688
|
+
async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
|
|
10689
|
+
const root = projectRoot2(ctx);
|
|
10690
|
+
if (params.from && params.to) {
|
|
10691
|
+
const path17 = await getCallGraphPath(root, HOST2, params.from, params.to, params.maxDepth);
|
|
10692
|
+
if (path17.length > 0) {
|
|
10693
|
+
return text2(formatCallGraphPath(params.from, params.to, path17), path17);
|
|
10694
|
+
}
|
|
10695
|
+
const { callers } = await getCallGraphData(root, HOST2, {
|
|
10696
|
+
name: params.to,
|
|
10697
|
+
direction: "callers"
|
|
10698
|
+
});
|
|
10699
|
+
const directEdge = callers.find((edge) => edge.fromSymbolName === params.from);
|
|
10700
|
+
if (directEdge) {
|
|
10701
|
+
const location = directEdge.fromSymbolFilePath ? ` at ${directEdge.fromSymbolFilePath}:${directEdge.line}` : "";
|
|
10702
|
+
return text2(
|
|
10703
|
+
`Direct path: ${params.from} --${directEdge.callType}--> ${params.to}${location} (edge is ${directEdge.isResolved ? "resolved" : "unresolved"}).`,
|
|
10704
|
+
path17
|
|
10705
|
+
);
|
|
10706
|
+
}
|
|
10707
|
+
return text2(formatCallGraphPath(params.from, params.to, path17), path17);
|
|
10708
|
+
}
|
|
10709
|
+
if (params.symbol) {
|
|
10710
|
+
const results2 = await implementationLookup(root, HOST2, params.symbol, {
|
|
10711
|
+
limit: params.limit ?? 10,
|
|
10712
|
+
fileType: params.fileType,
|
|
10713
|
+
directory: params.directory
|
|
10714
|
+
});
|
|
10715
|
+
return text2(formatDefinitionLookup(results2, params.symbol), results2);
|
|
10716
|
+
}
|
|
10717
|
+
const results = await searchCodebase(root, HOST2, params.query, {
|
|
10718
|
+
limit: params.limit ?? 10,
|
|
10719
|
+
fileType: params.fileType,
|
|
10720
|
+
directory: params.directory,
|
|
10721
|
+
metadataOnly: true
|
|
10722
|
+
});
|
|
10723
|
+
if (results.length === 0) {
|
|
10724
|
+
return text2("No matching code found. Try a different query or run index_status/index_codebase first.");
|
|
10725
|
+
}
|
|
10726
|
+
return text2(`Found ${results.length} locations for "${params.query}":
|
|
10727
|
+
|
|
10728
|
+
${formatCodebasePeek(results)}`, results);
|
|
10729
|
+
}
|
|
10730
|
+
});
|
|
10653
10731
|
pi.registerTool({
|
|
10654
10732
|
name: "codebase_search",
|
|
10655
10733
|
label: "Codebase Search",
|
|
10656
|
-
description: "
|
|
10734
|
+
description: "Use this after codebase_context when you need semantic content, not just locations. Describe behavior, not syntax.",
|
|
10657
10735
|
parameters: Type2.Object({
|
|
10658
10736
|
query: Type2.String({ description: "Natural language description of what code you're looking for" }),
|
|
10659
10737
|
limit: Type2.Optional(Type2.Number({ description: "Maximum results (default: 10)" })),
|
|
@@ -10673,7 +10751,7 @@ function codebaseIndexPiExtension(pi) {
|
|
|
10673
10751
|
pi.registerTool({
|
|
10674
10752
|
name: "codebase_peek",
|
|
10675
10753
|
label: "Codebase Peek",
|
|
10676
|
-
description: "
|
|
10754
|
+
description: "LOW-TOKEN location-first retrieval. Prefer codebase_context first, then use this for cheap conceptual lookup.",
|
|
10677
10755
|
parameters: Type2.Object({
|
|
10678
10756
|
query: Type2.String(),
|
|
10679
10757
|
limit: Type2.Optional(Type2.Number()),
|
|
@@ -10692,7 +10770,7 @@ function codebaseIndexPiExtension(pi) {
|
|
|
10692
10770
|
pi.registerTool({
|
|
10693
10771
|
name: "find_similar",
|
|
10694
10772
|
label: "Find Similar Code",
|
|
10695
|
-
description: "Find code similar to a snippet for duplicate detection and
|
|
10773
|
+
description: "Find code similar to a snippet for duplicate detection, pattern discovery, and refactor planning.",
|
|
10696
10774
|
parameters: Type2.Object({
|
|
10697
10775
|
code: Type2.String({ description: "Code snippet to compare" }),
|
|
10698
10776
|
limit: Type2.Optional(Type2.Number()),
|
|
@@ -10709,7 +10787,7 @@ function codebaseIndexPiExtension(pi) {
|
|
|
10709
10787
|
pi.registerTool({
|
|
10710
10788
|
name: "implementation_lookup",
|
|
10711
10789
|
label: "Implementation Lookup",
|
|
10712
|
-
description: "Find likely symbol definitions or implementations
|
|
10790
|
+
description: "Find likely symbol definitions or implementations after codebase_context identifies a symbol.",
|
|
10713
10791
|
parameters: Type2.Object({
|
|
10714
10792
|
query: Type2.String(),
|
|
10715
10793
|
limit: Type2.Optional(Type2.Number()),
|
|
@@ -10724,7 +10802,7 @@ function codebaseIndexPiExtension(pi) {
|
|
|
10724
10802
|
pi.registerTool({
|
|
10725
10803
|
name: "index_codebase",
|
|
10726
10804
|
label: "Index Codebase",
|
|
10727
|
-
description: "Build or refresh the semantic codebase index.",
|
|
10805
|
+
description: "Build or refresh the semantic codebase index. Run index_status when freshness is unknown.",
|
|
10728
10806
|
parameters: Type2.Object({
|
|
10729
10807
|
force: Type2.Optional(Type2.Boolean({ default: false })),
|
|
10730
10808
|
estimateOnly: Type2.Optional(Type2.Boolean({ default: false })),
|
|
@@ -10750,7 +10828,7 @@ function codebaseIndexPiExtension(pi) {
|
|
|
10750
10828
|
pi.registerTool({
|
|
10751
10829
|
name: "index_health_check",
|
|
10752
10830
|
label: "Index Health Check",
|
|
10753
|
-
description: "Garbage collect orphaned embeddings/chunks and report health.",
|
|
10831
|
+
description: "Garbage collect orphaned embeddings/chunks and report index health status.",
|
|
10754
10832
|
parameters: Type2.Object({}),
|
|
10755
10833
|
async execute(_toolCallId, _params, _signal, _onUpdate, ctx) {
|
|
10756
10834
|
const result = await runIndexHealthCheck(projectRoot2(ctx), HOST2);
|
|
@@ -10790,6 +10868,11 @@ function codebaseIndexPiExtension(pi) {
|
|
|
10790
10868
|
}
|
|
10791
10869
|
});
|
|
10792
10870
|
registerPiCallGraphTools(pi);
|
|
10871
|
+
pi.on("before_agent_start", (event) => ({
|
|
10872
|
+
systemPrompt: `${event.systemPrompt}
|
|
10873
|
+
|
|
10874
|
+
Check index_status first when index readiness is unknown. For repository questions, call codebase_context before search/grep/bash/read-style broad reads. Use implementation_lookup for known symbols and call_graph/call_graph_path after endpoints are identified for dependency flow. Avoid broad tool calls until semantic locations are known.`
|
|
10875
|
+
}));
|
|
10793
10876
|
pi.registerTool({
|
|
10794
10877
|
name: "pr_impact",
|
|
10795
10878
|
label: "PR Impact",
|