opencode-codebase-index 0.9.0 → 0.11.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/README.md +4 -2
- package/dist/cli.cjs +78 -28
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +78 -28
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +244 -113
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +244 -113
- package/dist/index.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 +3 -2
package/dist/index.js
CHANGED
|
@@ -7,7 +7,11 @@ var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
|
7
7
|
var __getProtoOf = Object.getPrototypeOf;
|
|
8
8
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
9
|
var __commonJS = (cb, mod) => function __require() {
|
|
10
|
-
|
|
10
|
+
try {
|
|
11
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
12
|
+
} catch (e) {
|
|
13
|
+
throw mod = 0, e;
|
|
14
|
+
}
|
|
11
15
|
};
|
|
12
16
|
var __copyProps = (to, from, except, desc) => {
|
|
13
17
|
if (from && typeof from === "object" || typeof from === "function") {
|
|
@@ -647,6 +651,7 @@ var require_eventemitter3 = __commonJS({
|
|
|
647
651
|
});
|
|
648
652
|
|
|
649
653
|
// src/index.ts
|
|
654
|
+
import * as os6 from "os";
|
|
650
655
|
import * as path17 from "path";
|
|
651
656
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
652
657
|
|
|
@@ -793,7 +798,8 @@ function getDefaultSearchConfig() {
|
|
|
793
798
|
rrfK: 60,
|
|
794
799
|
rerankTopN: 20,
|
|
795
800
|
contextLines: 0,
|
|
796
|
-
routingHints: true
|
|
801
|
+
routingHints: true,
|
|
802
|
+
routingHintRole: "system"
|
|
797
803
|
};
|
|
798
804
|
}
|
|
799
805
|
function getDefaultRerankerBaseUrl(provider) {
|
|
@@ -914,7 +920,8 @@ function parseConfig(raw) {
|
|
|
914
920
|
rrfK: typeof rawSearch.rrfK === "number" ? Math.max(1, Math.floor(rawSearch.rrfK)) : defaultSearch.rrfK,
|
|
915
921
|
rerankTopN: typeof rawSearch.rerankTopN === "number" ? Math.min(200, Math.max(0, Math.floor(rawSearch.rerankTopN))) : defaultSearch.rerankTopN,
|
|
916
922
|
contextLines: typeof rawSearch.contextLines === "number" ? Math.min(50, Math.max(0, rawSearch.contextLines)) : defaultSearch.contextLines,
|
|
917
|
-
routingHints: typeof rawSearch.routingHints === "boolean" ? rawSearch.routingHints : defaultSearch.routingHints
|
|
923
|
+
routingHints: typeof rawSearch.routingHints === "boolean" ? rawSearch.routingHints : defaultSearch.routingHints,
|
|
924
|
+
routingHintRole: rawSearch.routingHintRole === "developer" || rawSearch.routingHintRole === "system" ? rawSearch.routingHintRole : defaultSearch.routingHintRole
|
|
918
925
|
};
|
|
919
926
|
const rawDebug = input.debug && typeof input.debug === "object" ? input.debug : {};
|
|
920
927
|
const debug = {
|
|
@@ -1236,6 +1243,32 @@ function hasFilteredPathSegment(relativePath, separator = path4.sep) {
|
|
|
1236
1243
|
(part) => isHiddenPathSegment(part) || isBuildPathSegment(part)
|
|
1237
1244
|
);
|
|
1238
1245
|
}
|
|
1246
|
+
var RESTRICTED_DIRECTORIES = /* @__PURE__ */ new Set([
|
|
1247
|
+
// macOS
|
|
1248
|
+
"library",
|
|
1249
|
+
"applications",
|
|
1250
|
+
"system",
|
|
1251
|
+
"volumes",
|
|
1252
|
+
"private",
|
|
1253
|
+
"cores",
|
|
1254
|
+
// Linux
|
|
1255
|
+
"proc",
|
|
1256
|
+
"sys",
|
|
1257
|
+
"dev",
|
|
1258
|
+
"run",
|
|
1259
|
+
"snap",
|
|
1260
|
+
// Windows
|
|
1261
|
+
"windows",
|
|
1262
|
+
"programdata",
|
|
1263
|
+
"program files",
|
|
1264
|
+
"program files (x86)",
|
|
1265
|
+
"$recycle.bin"
|
|
1266
|
+
]);
|
|
1267
|
+
function isRestrictedDirectory(relativePath, separator = path4.sep) {
|
|
1268
|
+
const firstSegment = relativePath.split(separator)[0];
|
|
1269
|
+
if (!firstSegment) return false;
|
|
1270
|
+
return RESTRICTED_DIRECTORIES.has(firstSegment.toLowerCase());
|
|
1271
|
+
}
|
|
1239
1272
|
|
|
1240
1273
|
// src/config/rebase.ts
|
|
1241
1274
|
function isWithinRoot(rootDir, targetPath) {
|
|
@@ -2295,7 +2328,7 @@ var NodeFsHandler = class {
|
|
|
2295
2328
|
this._addToNodeFs(path18, initialAdd, wh, depth + 1);
|
|
2296
2329
|
}
|
|
2297
2330
|
}).on(EV.ERROR, this._boundHandleError);
|
|
2298
|
-
return new Promise((
|
|
2331
|
+
return new Promise((resolve12, reject) => {
|
|
2299
2332
|
if (!stream)
|
|
2300
2333
|
return reject();
|
|
2301
2334
|
stream.once(STR_END, () => {
|
|
@@ -2304,7 +2337,7 @@ var NodeFsHandler = class {
|
|
|
2304
2337
|
return;
|
|
2305
2338
|
}
|
|
2306
2339
|
const wasThrottled = throttler ? throttler.clear() : false;
|
|
2307
|
-
|
|
2340
|
+
resolve12(void 0);
|
|
2308
2341
|
previous.getChildren().filter((item) => {
|
|
2309
2342
|
return item !== directory && !current.has(item);
|
|
2310
2343
|
}).forEach((item) => {
|
|
@@ -3404,6 +3437,9 @@ var FileWatcher = class {
|
|
|
3404
3437
|
if (hasFilteredPathSegment(relativePath, path8.sep)) {
|
|
3405
3438
|
return true;
|
|
3406
3439
|
}
|
|
3440
|
+
if (isRestrictedDirectory(relativePath, path8.sep)) {
|
|
3441
|
+
return true;
|
|
3442
|
+
}
|
|
3407
3443
|
if (ignoreFilter.ignores(relativePath)) {
|
|
3408
3444
|
return true;
|
|
3409
3445
|
}
|
|
@@ -3416,6 +3452,13 @@ var FileWatcher = class {
|
|
|
3416
3452
|
pollInterval: 100
|
|
3417
3453
|
}
|
|
3418
3454
|
});
|
|
3455
|
+
this.watcher.on("error", (error) => {
|
|
3456
|
+
const err = error instanceof Error ? error : null;
|
|
3457
|
+
if (err?.code === "EPERM" || err?.code === "EACCES") {
|
|
3458
|
+
return;
|
|
3459
|
+
}
|
|
3460
|
+
console.error("[codebase-index] Watcher error:", err?.message ?? error);
|
|
3461
|
+
});
|
|
3419
3462
|
this.watcher.on("add", (filePath) => this.handleChange("add", filePath));
|
|
3420
3463
|
this.watcher.on("change", (filePath) => this.handleChange("change", filePath));
|
|
3421
3464
|
this.watcher.on("unlink", (filePath) => this.handleChange("unlink", filePath));
|
|
@@ -3550,7 +3593,7 @@ var GitHeadWatcher = class {
|
|
|
3550
3593
|
};
|
|
3551
3594
|
|
|
3552
3595
|
// src/watcher/index.ts
|
|
3553
|
-
function createWatcherWithIndexer(
|
|
3596
|
+
function createWatcherWithIndexer(getIndexer, projectRoot, config) {
|
|
3554
3597
|
const fileWatcher = new FileWatcher(projectRoot, config);
|
|
3555
3598
|
fileWatcher.start(async (changes) => {
|
|
3556
3599
|
const hasAddOrChange = changes.some(
|
|
@@ -3558,7 +3601,7 @@ function createWatcherWithIndexer(getIndexer2, projectRoot, config) {
|
|
|
3558
3601
|
);
|
|
3559
3602
|
const hasDelete = changes.some((c) => c.type === "unlink");
|
|
3560
3603
|
if (hasAddOrChange || hasDelete) {
|
|
3561
|
-
await
|
|
3604
|
+
await getIndexer().index();
|
|
3562
3605
|
}
|
|
3563
3606
|
});
|
|
3564
3607
|
let gitWatcher = null;
|
|
@@ -3566,7 +3609,7 @@ function createWatcherWithIndexer(getIndexer2, projectRoot, config) {
|
|
|
3566
3609
|
gitWatcher = new GitHeadWatcher(projectRoot);
|
|
3567
3610
|
gitWatcher.start(async (oldBranch, newBranch) => {
|
|
3568
3611
|
console.log(`Branch changed: ${oldBranch ?? "(none)"} -> ${newBranch}`);
|
|
3569
|
-
await
|
|
3612
|
+
await getIndexer().index();
|
|
3570
3613
|
});
|
|
3571
3614
|
}
|
|
3572
3615
|
return {
|
|
@@ -3609,7 +3652,7 @@ function pTimeout(promise, options) {
|
|
|
3609
3652
|
} = options;
|
|
3610
3653
|
let timer;
|
|
3611
3654
|
let abortHandler;
|
|
3612
|
-
const wrappedPromise = new Promise((
|
|
3655
|
+
const wrappedPromise = new Promise((resolve12, reject) => {
|
|
3613
3656
|
if (typeof milliseconds !== "number" || Math.sign(milliseconds) !== 1) {
|
|
3614
3657
|
throw new TypeError(`Expected \`milliseconds\` to be a positive number, got \`${milliseconds}\``);
|
|
3615
3658
|
}
|
|
@@ -3623,7 +3666,7 @@ function pTimeout(promise, options) {
|
|
|
3623
3666
|
};
|
|
3624
3667
|
signal.addEventListener("abort", abortHandler, { once: true });
|
|
3625
3668
|
}
|
|
3626
|
-
promise.then(
|
|
3669
|
+
promise.then(resolve12, reject);
|
|
3627
3670
|
if (milliseconds === Number.POSITIVE_INFINITY) {
|
|
3628
3671
|
return;
|
|
3629
3672
|
}
|
|
@@ -3631,7 +3674,7 @@ function pTimeout(promise, options) {
|
|
|
3631
3674
|
timer = customTimers.setTimeout.call(void 0, () => {
|
|
3632
3675
|
if (fallback) {
|
|
3633
3676
|
try {
|
|
3634
|
-
|
|
3677
|
+
resolve12(fallback());
|
|
3635
3678
|
} catch (error) {
|
|
3636
3679
|
reject(error);
|
|
3637
3680
|
}
|
|
@@ -3641,7 +3684,7 @@ function pTimeout(promise, options) {
|
|
|
3641
3684
|
promise.cancel();
|
|
3642
3685
|
}
|
|
3643
3686
|
if (message === false) {
|
|
3644
|
-
|
|
3687
|
+
resolve12();
|
|
3645
3688
|
} else if (message instanceof Error) {
|
|
3646
3689
|
reject(message);
|
|
3647
3690
|
} else {
|
|
@@ -4043,7 +4086,7 @@ var PQueue = class extends import_index.default {
|
|
|
4043
4086
|
// Assign unique ID if not provided
|
|
4044
4087
|
id: options.id ?? (this.#idAssigner++).toString()
|
|
4045
4088
|
};
|
|
4046
|
-
return new Promise((
|
|
4089
|
+
return new Promise((resolve12, reject) => {
|
|
4047
4090
|
const taskSymbol = /* @__PURE__ */ Symbol(`task-${options.id}`);
|
|
4048
4091
|
let cleanupQueueAbortHandler = () => void 0;
|
|
4049
4092
|
const run = async () => {
|
|
@@ -4083,7 +4126,7 @@ var PQueue = class extends import_index.default {
|
|
|
4083
4126
|
})]);
|
|
4084
4127
|
}
|
|
4085
4128
|
const result = await operation;
|
|
4086
|
-
|
|
4129
|
+
resolve12(result);
|
|
4087
4130
|
this.emit("completed", result);
|
|
4088
4131
|
} catch (error) {
|
|
4089
4132
|
reject(error);
|
|
@@ -4271,13 +4314,13 @@ var PQueue = class extends import_index.default {
|
|
|
4271
4314
|
});
|
|
4272
4315
|
}
|
|
4273
4316
|
async #onEvent(event, filter) {
|
|
4274
|
-
return new Promise((
|
|
4317
|
+
return new Promise((resolve12) => {
|
|
4275
4318
|
const listener = () => {
|
|
4276
4319
|
if (filter && !filter()) {
|
|
4277
4320
|
return;
|
|
4278
4321
|
}
|
|
4279
4322
|
this.off(event, listener);
|
|
4280
|
-
|
|
4323
|
+
resolve12();
|
|
4281
4324
|
};
|
|
4282
4325
|
this.on(event, listener);
|
|
4283
4326
|
});
|
|
@@ -4563,7 +4606,7 @@ async function onAttemptFailure({ error, attemptNumber, retriesConsumed, startTi
|
|
|
4563
4606
|
const finalDelay = Math.min(delayTime, remainingTime);
|
|
4564
4607
|
options.signal?.throwIfAborted();
|
|
4565
4608
|
if (finalDelay > 0) {
|
|
4566
|
-
await new Promise((
|
|
4609
|
+
await new Promise((resolve12, reject) => {
|
|
4567
4610
|
const onAbort = () => {
|
|
4568
4611
|
clearTimeout(timeoutToken);
|
|
4569
4612
|
options.signal?.removeEventListener("abort", onAbort);
|
|
@@ -4571,7 +4614,7 @@ async function onAttemptFailure({ error, attemptNumber, retriesConsumed, startTi
|
|
|
4571
4614
|
};
|
|
4572
4615
|
const timeoutToken = setTimeout(() => {
|
|
4573
4616
|
options.signal?.removeEventListener("abort", onAbort);
|
|
4574
|
-
|
|
4617
|
+
resolve12();
|
|
4575
4618
|
}, finalDelay);
|
|
4576
4619
|
if (options.unref) {
|
|
4577
4620
|
timeoutToken.unref?.();
|
|
@@ -4812,6 +4855,8 @@ var BaseEmbeddingProvider = class {
|
|
|
4812
4855
|
this.credentials = credentials;
|
|
4813
4856
|
this.modelInfo = modelInfo;
|
|
4814
4857
|
}
|
|
4858
|
+
credentials;
|
|
4859
|
+
modelInfo;
|
|
4815
4860
|
async embedQuery(query) {
|
|
4816
4861
|
const result = await this.embedBatch([query]);
|
|
4817
4862
|
return {
|
|
@@ -6359,17 +6404,17 @@ var Database = class {
|
|
|
6359
6404
|
if (edges.length === 0) return;
|
|
6360
6405
|
this.inner.upsertCallEdgesBatch(edges);
|
|
6361
6406
|
}
|
|
6362
|
-
getCallers(targetName, branch) {
|
|
6407
|
+
getCallers(targetName, branch, callTypeFilter) {
|
|
6363
6408
|
this.throwIfClosed();
|
|
6364
|
-
return this.inner.getCallers(targetName, branch);
|
|
6409
|
+
return this.inner.getCallers(targetName, branch, callTypeFilter ?? null);
|
|
6365
6410
|
}
|
|
6366
|
-
getCallersWithContext(targetName, branch) {
|
|
6411
|
+
getCallersWithContext(targetName, branch, callTypeFilter) {
|
|
6367
6412
|
this.throwIfClosed();
|
|
6368
|
-
return this.inner.getCallersWithContext(targetName, branch);
|
|
6413
|
+
return this.inner.getCallersWithContext(targetName, branch, callTypeFilter ?? null);
|
|
6369
6414
|
}
|
|
6370
|
-
getCallees(symbolId, branch) {
|
|
6415
|
+
getCallees(symbolId, branch, callTypeFilter) {
|
|
6371
6416
|
this.throwIfClosed();
|
|
6372
|
-
return this.inner.getCallees(symbolId, branch);
|
|
6417
|
+
return this.inner.getCallees(symbolId, branch, callTypeFilter ?? null);
|
|
6373
6418
|
}
|
|
6374
6419
|
deleteCallEdgesByFile(filePath) {
|
|
6375
6420
|
this.throwIfClosed();
|
|
@@ -6379,6 +6424,10 @@ var Database = class {
|
|
|
6379
6424
|
this.throwIfClosed();
|
|
6380
6425
|
this.inner.resolveCallEdge(edgeId, toSymbolId);
|
|
6381
6426
|
}
|
|
6427
|
+
findShortestPath(fromName, toName, branch, maxDepth) {
|
|
6428
|
+
this.throwIfClosed();
|
|
6429
|
+
return this.inner.findShortestPath(fromName, toName, branch, maxDepth ?? null);
|
|
6430
|
+
}
|
|
6382
6431
|
addSymbolsToBranch(branch, symbolIds) {
|
|
6383
6432
|
this.throwIfClosed();
|
|
6384
6433
|
this.inner.addSymbolsToBranch(branch, symbolIds);
|
|
@@ -9006,6 +9055,7 @@ var Indexer = class {
|
|
|
9006
9055
|
targetName: site.calleeName,
|
|
9007
9056
|
toSymbolId: void 0,
|
|
9008
9057
|
callType: site.callType,
|
|
9058
|
+
confidence: site.confidence,
|
|
9009
9059
|
line: site.line,
|
|
9010
9060
|
col: site.column,
|
|
9011
9061
|
isResolved: false
|
|
@@ -9150,7 +9200,7 @@ var Indexer = class {
|
|
|
9150
9200
|
for (const requestBatch of requestBatches) {
|
|
9151
9201
|
queue.add(async () => {
|
|
9152
9202
|
if (rateLimitBackoffMs > 0) {
|
|
9153
|
-
await new Promise((
|
|
9203
|
+
await new Promise((resolve12) => setTimeout(resolve12, rateLimitBackoffMs));
|
|
9154
9204
|
}
|
|
9155
9205
|
try {
|
|
9156
9206
|
const result = await pRetry(
|
|
@@ -10125,12 +10175,12 @@ var Indexer = class {
|
|
|
10125
10175
|
})
|
|
10126
10176
|
);
|
|
10127
10177
|
}
|
|
10128
|
-
async getCallers(targetName) {
|
|
10178
|
+
async getCallers(targetName, callTypeFilter) {
|
|
10129
10179
|
const { database } = await this.ensureInitialized();
|
|
10130
10180
|
const seen = /* @__PURE__ */ new Set();
|
|
10131
10181
|
const results = [];
|
|
10132
10182
|
for (const branchKey of this.getBranchCatalogKeys()) {
|
|
10133
|
-
for (const edge of database.getCallersWithContext(targetName, branchKey)) {
|
|
10183
|
+
for (const edge of database.getCallersWithContext(targetName, branchKey, callTypeFilter)) {
|
|
10134
10184
|
if (!seen.has(edge.id)) {
|
|
10135
10185
|
seen.add(edge.id);
|
|
10136
10186
|
results.push(edge);
|
|
@@ -10139,12 +10189,12 @@ var Indexer = class {
|
|
|
10139
10189
|
}
|
|
10140
10190
|
return results;
|
|
10141
10191
|
}
|
|
10142
|
-
async getCallees(symbolId) {
|
|
10192
|
+
async getCallees(symbolId, callTypeFilter) {
|
|
10143
10193
|
const { database } = await this.ensureInitialized();
|
|
10144
10194
|
const seen = /* @__PURE__ */ new Set();
|
|
10145
10195
|
const results = [];
|
|
10146
10196
|
for (const branchKey of this.getBranchCatalogKeys()) {
|
|
10147
|
-
for (const edge of database.getCallees(symbolId, branchKey)) {
|
|
10197
|
+
for (const edge of database.getCallees(symbolId, branchKey, callTypeFilter)) {
|
|
10148
10198
|
if (!seen.has(edge.id)) {
|
|
10149
10199
|
seen.add(edge.id);
|
|
10150
10200
|
results.push(edge);
|
|
@@ -10153,6 +10203,17 @@ var Indexer = class {
|
|
|
10153
10203
|
}
|
|
10154
10204
|
return results;
|
|
10155
10205
|
}
|
|
10206
|
+
async findCallPath(fromName, toName, maxDepth) {
|
|
10207
|
+
const { database } = await this.ensureInitialized();
|
|
10208
|
+
let shortest = [];
|
|
10209
|
+
for (const branchKey of this.getBranchCatalogKeys()) {
|
|
10210
|
+
const path18 = database.findShortestPath(fromName, toName, branchKey, maxDepth);
|
|
10211
|
+
if (path18.length > 0 && (shortest.length === 0 || path18.length < shortest.length)) {
|
|
10212
|
+
shortest = path18;
|
|
10213
|
+
}
|
|
10214
|
+
}
|
|
10215
|
+
return shortest;
|
|
10216
|
+
}
|
|
10156
10217
|
async close() {
|
|
10157
10218
|
await this.database?.close();
|
|
10158
10219
|
this.database = null;
|
|
@@ -10474,39 +10535,45 @@ function ensureStringArray(value) {
|
|
|
10474
10535
|
return Array.isArray(value) ? value : [];
|
|
10475
10536
|
}
|
|
10476
10537
|
var z = tool.schema;
|
|
10477
|
-
var
|
|
10478
|
-
var
|
|
10538
|
+
var indexerMap = /* @__PURE__ */ new Map();
|
|
10539
|
+
var defaultProjectRoot = "";
|
|
10479
10540
|
function initializeTools(projectRoot, config) {
|
|
10480
|
-
|
|
10481
|
-
|
|
10482
|
-
|
|
10483
|
-
function getSharedIndexer() {
|
|
10484
|
-
return getIndexer();
|
|
10541
|
+
defaultProjectRoot = projectRoot;
|
|
10542
|
+
const indexer = new Indexer(projectRoot, config);
|
|
10543
|
+
indexerMap.set(projectRoot, indexer);
|
|
10485
10544
|
}
|
|
10486
|
-
function
|
|
10487
|
-
if (!
|
|
10545
|
+
function refreshIndexerForDirectory(projectRoot) {
|
|
10546
|
+
if (!projectRoot) {
|
|
10488
10547
|
throw new Error("Codebase index tools not initialized. Plugin may not be loaded correctly.");
|
|
10489
10548
|
}
|
|
10490
|
-
|
|
10549
|
+
const indexer = new Indexer(projectRoot, parseConfig(loadRuntimeConfig(projectRoot)));
|
|
10550
|
+
indexerMap.set(projectRoot, indexer);
|
|
10491
10551
|
}
|
|
10492
|
-
function shouldForceLocalizeProjectIndex() {
|
|
10493
|
-
const currentConfig = parseConfig(loadRuntimeConfig(
|
|
10552
|
+
function shouldForceLocalizeProjectIndex(projectRoot) {
|
|
10553
|
+
const currentConfig = parseConfig(loadRuntimeConfig(projectRoot));
|
|
10494
10554
|
if (currentConfig.scope !== "project") {
|
|
10495
10555
|
return false;
|
|
10496
10556
|
}
|
|
10497
|
-
const localIndexPath = path15.join(
|
|
10498
|
-
const mainRepoRoot = resolveWorktreeMainRepoRoot(
|
|
10557
|
+
const localIndexPath = path15.join(projectRoot, ".opencode", "index");
|
|
10558
|
+
const mainRepoRoot = resolveWorktreeMainRepoRoot(projectRoot);
|
|
10499
10559
|
if (!mainRepoRoot) {
|
|
10500
10560
|
return false;
|
|
10501
10561
|
}
|
|
10502
10562
|
const inheritedIndexPath = path15.join(mainRepoRoot, ".opencode", "index");
|
|
10503
10563
|
return !existsSync9(localIndexPath) && existsSync9(inheritedIndexPath);
|
|
10504
10564
|
}
|
|
10505
|
-
function
|
|
10506
|
-
|
|
10565
|
+
function getIndexerForProject(directory) {
|
|
10566
|
+
const projectRoot = directory || defaultProjectRoot;
|
|
10567
|
+
if (!projectRoot) {
|
|
10507
10568
|
throw new Error("Codebase index tools not initialized. Plugin may not be loaded correctly.");
|
|
10508
10569
|
}
|
|
10509
|
-
|
|
10570
|
+
let indexer = indexerMap.get(projectRoot);
|
|
10571
|
+
if (!indexer) {
|
|
10572
|
+
const config = parseConfig(loadRuntimeConfig(projectRoot));
|
|
10573
|
+
indexer = new Indexer(projectRoot, config);
|
|
10574
|
+
indexerMap.set(projectRoot, indexer);
|
|
10575
|
+
}
|
|
10576
|
+
return indexer;
|
|
10510
10577
|
}
|
|
10511
10578
|
var codebase_peek = tool({
|
|
10512
10579
|
description: "Quick lookup of code locations by meaning. Returns only metadata (file, line, name, type) WITHOUT code content. Use this first to find WHERE code is, then use Read tool to examine specific files. Saves tokens by not returning full code blocks. Best for: discovery, navigation, finding multiple related locations.",
|
|
@@ -10517,8 +10584,8 @@ var codebase_peek = tool({
|
|
|
10517
10584
|
directory: z.string().optional().describe("Filter by directory path (e.g., 'src/utils', 'lib')"),
|
|
10518
10585
|
chunkType: z.enum(["function", "class", "method", "interface", "type", "enum", "struct", "impl", "trait", "module", "other"]).optional().describe("Filter by code chunk type")
|
|
10519
10586
|
},
|
|
10520
|
-
async execute(args) {
|
|
10521
|
-
const indexer =
|
|
10587
|
+
async execute(args, context) {
|
|
10588
|
+
const indexer = getIndexerForProject(context?.worktree);
|
|
10522
10589
|
const results = await indexer.search(args.query, args.limit ?? 10, {
|
|
10523
10590
|
fileType: args.fileType,
|
|
10524
10591
|
directory: args.directory,
|
|
@@ -10536,16 +10603,17 @@ var index_codebase = tool({
|
|
|
10536
10603
|
verbose: z.boolean().optional().default(false).describe("Show detailed info about skipped files and parsing failures")
|
|
10537
10604
|
},
|
|
10538
10605
|
async execute(args, context) {
|
|
10539
|
-
|
|
10606
|
+
const projectRoot = context?.worktree || defaultProjectRoot;
|
|
10607
|
+
let indexer = getIndexerForProject(projectRoot);
|
|
10540
10608
|
if (args.estimateOnly) {
|
|
10541
10609
|
const estimate = await indexer.estimateCost();
|
|
10542
10610
|
return formatCostEstimate(estimate);
|
|
10543
10611
|
}
|
|
10544
10612
|
if (args.force) {
|
|
10545
|
-
if (shouldForceLocalizeProjectIndex()) {
|
|
10546
|
-
materializeLocalProjectConfig(
|
|
10547
|
-
|
|
10548
|
-
indexer =
|
|
10613
|
+
if (shouldForceLocalizeProjectIndex(projectRoot)) {
|
|
10614
|
+
materializeLocalProjectConfig(projectRoot, loadProjectConfigLayer(projectRoot));
|
|
10615
|
+
refreshIndexerForDirectory(projectRoot);
|
|
10616
|
+
indexer = getIndexerForProject(projectRoot);
|
|
10549
10617
|
}
|
|
10550
10618
|
await indexer.clearIndex();
|
|
10551
10619
|
}
|
|
@@ -10568,8 +10636,8 @@ var index_codebase = tool({
|
|
|
10568
10636
|
var index_status = tool({
|
|
10569
10637
|
description: "Check the status of the codebase index. Shows whether the codebase is indexed, how many chunks are stored, and the embedding provider being used.",
|
|
10570
10638
|
args: {},
|
|
10571
|
-
async execute() {
|
|
10572
|
-
const indexer =
|
|
10639
|
+
async execute(_args, context) {
|
|
10640
|
+
const indexer = getIndexerForProject(context?.worktree);
|
|
10573
10641
|
const status = await indexer.getStatus();
|
|
10574
10642
|
return formatStatus(status);
|
|
10575
10643
|
}
|
|
@@ -10577,8 +10645,8 @@ var index_status = tool({
|
|
|
10577
10645
|
var index_health_check = tool({
|
|
10578
10646
|
description: "Check index health and remove stale entries from deleted files. Run this to clean up the index after files have been deleted.",
|
|
10579
10647
|
args: {},
|
|
10580
|
-
async execute() {
|
|
10581
|
-
const indexer =
|
|
10648
|
+
async execute(_args, context) {
|
|
10649
|
+
const indexer = getIndexerForProject(context?.worktree);
|
|
10582
10650
|
const result = await indexer.healthCheck();
|
|
10583
10651
|
return formatHealthCheck(result);
|
|
10584
10652
|
}
|
|
@@ -10586,8 +10654,8 @@ var index_health_check = tool({
|
|
|
10586
10654
|
var index_metrics = tool({
|
|
10587
10655
|
description: "Get metrics and performance statistics for the codebase index. Shows indexing stats, search timings, cache hit rates, and API usage. Requires debug.enabled=true and debug.metrics=true in config.",
|
|
10588
10656
|
args: {},
|
|
10589
|
-
async execute() {
|
|
10590
|
-
const indexer =
|
|
10657
|
+
async execute(_args, context) {
|
|
10658
|
+
const indexer = getIndexerForProject(context?.worktree);
|
|
10591
10659
|
const logger = indexer.getLogger();
|
|
10592
10660
|
if (!logger.isEnabled()) {
|
|
10593
10661
|
return 'Debug mode is disabled. Enable it in your config:\n\n```json\n{\n "debug": {\n "enabled": true,\n "metrics": true\n }\n}\n```';
|
|
@@ -10605,8 +10673,8 @@ var index_logs = tool({
|
|
|
10605
10673
|
category: z.enum(["search", "embedding", "cache", "gc", "branch", "general"]).optional().describe("Filter by log category"),
|
|
10606
10674
|
level: z.enum(["error", "warn", "info", "debug"]).optional().describe("Filter by minimum log level")
|
|
10607
10675
|
},
|
|
10608
|
-
async execute(args) {
|
|
10609
|
-
const indexer =
|
|
10676
|
+
async execute(args, context) {
|
|
10677
|
+
const indexer = getIndexerForProject(context?.worktree);
|
|
10610
10678
|
const logger = indexer.getLogger();
|
|
10611
10679
|
if (!logger.isEnabled()) {
|
|
10612
10680
|
return 'Debug mode is disabled. Enable it in your config:\n\n```json\n{\n "debug": {\n "enabled": true\n }\n}\n```';
|
|
@@ -10632,8 +10700,8 @@ var find_similar = tool({
|
|
|
10632
10700
|
chunkType: z.enum(["function", "class", "method", "interface", "type", "enum", "struct", "impl", "trait", "module", "other"]).optional().describe("Filter by code chunk type"),
|
|
10633
10701
|
excludeFile: z.string().optional().describe("Exclude results from this file path (useful when searching for duplicates of code from a specific file)")
|
|
10634
10702
|
},
|
|
10635
|
-
async execute(args) {
|
|
10636
|
-
const indexer =
|
|
10703
|
+
async execute(args, context) {
|
|
10704
|
+
const indexer = getIndexerForProject(context?.worktree);
|
|
10637
10705
|
const results = await indexer.findSimilar(args.code, args.limit, {
|
|
10638
10706
|
fileType: args.fileType,
|
|
10639
10707
|
directory: args.directory,
|
|
@@ -10656,8 +10724,8 @@ var codebase_search = tool({
|
|
|
10656
10724
|
chunkType: z.enum(["function", "class", "method", "interface", "type", "enum", "struct", "impl", "trait", "module", "other"]).optional().describe("Filter by code chunk type"),
|
|
10657
10725
|
contextLines: z.number().optional().describe("Number of extra lines to include before/after each match (default: 0)")
|
|
10658
10726
|
},
|
|
10659
|
-
async execute(args) {
|
|
10660
|
-
const indexer =
|
|
10727
|
+
async execute(args, context) {
|
|
10728
|
+
const indexer = getIndexerForProject(context?.worktree);
|
|
10661
10729
|
const results = await indexer.search(args.query, args.limit ?? 5, {
|
|
10662
10730
|
fileType: args.fileType,
|
|
10663
10731
|
directory: args.directory,
|
|
@@ -10678,8 +10746,8 @@ var implementation_lookup = tool({
|
|
|
10678
10746
|
fileType: z.string().optional().describe("Filter by file extension (e.g., 'ts', 'py')"),
|
|
10679
10747
|
directory: z.string().optional().describe("Filter by directory path (e.g., 'src/utils')")
|
|
10680
10748
|
},
|
|
10681
|
-
async execute(args) {
|
|
10682
|
-
const indexer =
|
|
10749
|
+
async execute(args, context) {
|
|
10750
|
+
const indexer = getIndexerForProject(context?.worktree);
|
|
10683
10751
|
const results = await indexer.search(args.query, args.limit ?? 5, {
|
|
10684
10752
|
fileType: args.fileType,
|
|
10685
10753
|
directory: args.directory,
|
|
@@ -10689,46 +10757,72 @@ var implementation_lookup = tool({
|
|
|
10689
10757
|
}
|
|
10690
10758
|
});
|
|
10691
10759
|
var call_graph = tool({
|
|
10692
|
-
description: "Query the call graph to find callers or callees of a function/method. Use to understand code flow and dependencies between functions.",
|
|
10760
|
+
description: "Query the call graph to find callers or callees of a function/method. Use to understand code flow and dependencies between functions. Supports relationship types: Call, MethodCall, Constructor, Import, Inherits, Implements.",
|
|
10693
10761
|
args: {
|
|
10694
10762
|
name: z.string().describe("Function or method name to query"),
|
|
10695
10763
|
direction: z.enum(["callers", "callees"]).default("callers").describe("Direction: 'callers' finds who calls this function, 'callees' finds what this function calls"),
|
|
10696
|
-
symbolId: z.string().optional().describe("Symbol ID (required for 'callees' direction, returned by previous call_graph queries)")
|
|
10764
|
+
symbolId: z.string().optional().describe("Symbol ID (required for 'callees' direction, returned by previous call_graph queries)"),
|
|
10765
|
+
relationshipType: z.enum(["Call", "MethodCall", "Constructor", "Import", "Inherits", "Implements"]).optional().describe("Filter by relationship type. Omit to show all.")
|
|
10697
10766
|
},
|
|
10698
|
-
async execute(args) {
|
|
10699
|
-
const indexer =
|
|
10767
|
+
async execute(args, context) {
|
|
10768
|
+
const indexer = getIndexerForProject(context?.worktree);
|
|
10700
10769
|
if (args.direction === "callees") {
|
|
10701
10770
|
if (!args.symbolId) {
|
|
10702
10771
|
return "Error: 'symbolId' is required when direction is 'callees'. First use direction='callers' to find the symbol ID.";
|
|
10703
10772
|
}
|
|
10704
|
-
const callees = await indexer.getCallees(args.symbolId);
|
|
10773
|
+
const callees = await indexer.getCallees(args.symbolId, args.relationshipType);
|
|
10705
10774
|
if (callees.length === 0) {
|
|
10706
|
-
return `No callees found for symbol ${args.symbolId}. The function may not call any other tracked functions.`;
|
|
10775
|
+
return `No callees found for symbol ${args.symbolId}${args.relationshipType ? ` with type ${args.relationshipType}` : ""}. The function may not call any other tracked functions.`;
|
|
10707
10776
|
}
|
|
10708
|
-
const formatted2 = callees.map(
|
|
10709
|
-
|
|
10710
|
-
|
|
10777
|
+
const formatted2 = callees.map((e, i) => {
|
|
10778
|
+
const conf = e.confidence !== "Direct" ? ` [${e.confidence.toLowerCase()}]` : "";
|
|
10779
|
+
return `[${i + 1}] \u2192 ${e.targetName} (${e.callType})${conf} at line ${e.line}${e.isResolved ? ` [resolved: ${e.toSymbolId}]` : " [unresolved]"}`;
|
|
10780
|
+
});
|
|
10711
10781
|
return formatted2.join("\n");
|
|
10712
10782
|
}
|
|
10713
|
-
const callers = await indexer.getCallers(args.name);
|
|
10783
|
+
const callers = await indexer.getCallers(args.name, args.relationshipType);
|
|
10714
10784
|
if (callers.length === 0) {
|
|
10715
|
-
return `No callers found for "${args.name}". It may not be called by any tracked function, or the index needs updating.`;
|
|
10785
|
+
return `No callers found for "${args.name}"${args.relationshipType ? ` with type ${args.relationshipType}` : ""}. It may not be called by any tracked function, or the index needs updating.`;
|
|
10716
10786
|
}
|
|
10717
|
-
const formatted = callers.map(
|
|
10718
|
-
|
|
10719
|
-
|
|
10787
|
+
const formatted = callers.map((e, i) => {
|
|
10788
|
+
const conf = e.confidence !== "Direct" ? ` [${e.confidence.toLowerCase()}]` : "";
|
|
10789
|
+
return `[${i + 1}] \u2190 from ${e.fromSymbolName ?? "<unknown>"} in ${e.fromSymbolFilePath ?? "<unknown file>"} [${e.fromSymbolId}] (${e.callType})${conf} at line ${e.line}${e.isResolved ? " [resolved]" : " [unresolved]"}`;
|
|
10790
|
+
});
|
|
10720
10791
|
return formatted.join("\n");
|
|
10721
10792
|
}
|
|
10722
10793
|
});
|
|
10794
|
+
var call_graph_path = tool({
|
|
10795
|
+
description: "Find the shortest connection path between two symbols in the call graph. Given a source and target function/method name, returns the chain of calls connecting them.",
|
|
10796
|
+
args: {
|
|
10797
|
+
from: z.string().describe("Source function/method name (starting point)"),
|
|
10798
|
+
to: z.string().describe("Target function/method name (destination)"),
|
|
10799
|
+
maxDepth: z.number().optional().default(10).describe("Maximum traversal depth (default: 10)")
|
|
10800
|
+
},
|
|
10801
|
+
async execute(args, context) {
|
|
10802
|
+
const indexer = getIndexerForProject(context?.worktree);
|
|
10803
|
+
const path18 = await indexer.findCallPath(args.from, args.to, args.maxDepth);
|
|
10804
|
+
if (path18.length === 0) {
|
|
10805
|
+
return `No path found between "${args.from}" and "${args.to}". They may be in disconnected components, or the call graph index needs updating.`;
|
|
10806
|
+
}
|
|
10807
|
+
const formatted = path18.map((hop, i) => {
|
|
10808
|
+
const prefix = i === 0 ? "[start]" : `--${hop.callType}-->`;
|
|
10809
|
+
const location = hop.filePath ? ` (${hop.filePath}:${hop.line})` : "";
|
|
10810
|
+
return `${prefix} ${hop.symbolName}${location}`;
|
|
10811
|
+
});
|
|
10812
|
+
return `Path (${path18.length} hops):
|
|
10813
|
+
${formatted.join("\n")}`;
|
|
10814
|
+
}
|
|
10815
|
+
});
|
|
10723
10816
|
var add_knowledge_base = tool({
|
|
10724
10817
|
description: "Add a folder as a knowledge base to the semantic search index. The folder will be indexed alongside the main project code. Supports absolute paths or relative paths (relative to the project root).",
|
|
10725
10818
|
args: {
|
|
10726
10819
|
path: z.string().describe("Path to the folder to add as a knowledge base (absolute or relative to project root)")
|
|
10727
10820
|
},
|
|
10728
|
-
async execute(args) {
|
|
10821
|
+
async execute(args, context) {
|
|
10822
|
+
const projectRoot = context?.worktree || defaultProjectRoot;
|
|
10729
10823
|
const inputPath = args.path.trim();
|
|
10730
10824
|
const normalizedPath = path15.resolve(
|
|
10731
|
-
path15.isAbsolute(inputPath) ? inputPath : resolveKnowledgeBasePath(inputPath,
|
|
10825
|
+
path15.isAbsolute(inputPath) ? inputPath : resolveKnowledgeBasePath(inputPath, projectRoot)
|
|
10732
10826
|
);
|
|
10733
10827
|
if (!existsSync9(normalizedPath)) {
|
|
10734
10828
|
return `Error: Directory does not exist: ${normalizedPath}`;
|
|
@@ -10770,21 +10864,21 @@ var add_knowledge_base = tool({
|
|
|
10770
10864
|
} catch (error) {
|
|
10771
10865
|
return `Error: Cannot access directory: ${normalizedPath} - ${error instanceof Error ? error.message : String(error)}`;
|
|
10772
10866
|
}
|
|
10773
|
-
const config = loadEditableConfig(
|
|
10867
|
+
const config = loadEditableConfig(projectRoot);
|
|
10774
10868
|
const knowledgeBases = ensureStringArray(config.knowledgeBases);
|
|
10775
|
-
const alreadyExists = hasMatchingKnowledgeBasePath(knowledgeBases, normalizedPath,
|
|
10869
|
+
const alreadyExists = hasMatchingKnowledgeBasePath(knowledgeBases, normalizedPath, projectRoot);
|
|
10776
10870
|
if (alreadyExists) {
|
|
10777
10871
|
return `Knowledge base already configured: ${normalizedPath}`;
|
|
10778
10872
|
}
|
|
10779
10873
|
knowledgeBases.push(normalizedPath);
|
|
10780
10874
|
config.knowledgeBases = knowledgeBases;
|
|
10781
|
-
saveConfig(
|
|
10782
|
-
|
|
10875
|
+
saveConfig(projectRoot, config);
|
|
10876
|
+
refreshIndexerForDirectory(projectRoot);
|
|
10783
10877
|
let result = `${normalizedPath}
|
|
10784
10878
|
`;
|
|
10785
10879
|
result += `Total knowledge bases: ${knowledgeBases.length}
|
|
10786
10880
|
`;
|
|
10787
|
-
result += `Config saved to: ${getConfigPath(
|
|
10881
|
+
result += `Config saved to: ${getConfigPath(projectRoot)}
|
|
10788
10882
|
`;
|
|
10789
10883
|
result += `
|
|
10790
10884
|
Run /index to rebuild the index with the new knowledge base.`;
|
|
@@ -10794,8 +10888,9 @@ Run /index to rebuild the index with the new knowledge base.`;
|
|
|
10794
10888
|
var list_knowledge_bases = tool({
|
|
10795
10889
|
description: "List all configured knowledge base folders that are indexed alongside the main project.",
|
|
10796
10890
|
args: {},
|
|
10797
|
-
async execute() {
|
|
10798
|
-
const
|
|
10891
|
+
async execute(_args, context) {
|
|
10892
|
+
const projectRoot = context?.worktree || defaultProjectRoot;
|
|
10893
|
+
const config = loadRuntimeConfig(projectRoot);
|
|
10799
10894
|
const knowledgeBases = ensureStringArray(config.knowledgeBases);
|
|
10800
10895
|
if (knowledgeBases.length === 0) {
|
|
10801
10896
|
return "No knowledge bases configured. Use add_knowledge_base to add folders.";
|
|
@@ -10805,7 +10900,7 @@ var list_knowledge_bases = tool({
|
|
|
10805
10900
|
`;
|
|
10806
10901
|
for (let i = 0; i < knowledgeBases.length; i++) {
|
|
10807
10902
|
const kb = knowledgeBases[i];
|
|
10808
|
-
const resolvedPath = resolveKnowledgeBasePath(kb,
|
|
10903
|
+
const resolvedPath = resolveKnowledgeBasePath(kb, projectRoot);
|
|
10809
10904
|
const exists = existsSync9(resolvedPath);
|
|
10810
10905
|
result += `[${i + 1}] ${kb}
|
|
10811
10906
|
`;
|
|
@@ -10823,7 +10918,7 @@ var list_knowledge_bases = tool({
|
|
|
10823
10918
|
}
|
|
10824
10919
|
result += "\n";
|
|
10825
10920
|
}
|
|
10826
|
-
result += `Config file: ${getConfigPath(
|
|
10921
|
+
result += `Config file: ${getConfigPath(projectRoot)}`;
|
|
10827
10922
|
return result;
|
|
10828
10923
|
}
|
|
10829
10924
|
});
|
|
@@ -10832,14 +10927,15 @@ var remove_knowledge_base = tool({
|
|
|
10832
10927
|
args: {
|
|
10833
10928
|
path: z.string().describe("Path of the knowledge base to remove (must match the configured path exactly)")
|
|
10834
10929
|
},
|
|
10835
|
-
async execute(args) {
|
|
10930
|
+
async execute(args, context) {
|
|
10931
|
+
const projectRoot = context?.worktree || defaultProjectRoot;
|
|
10836
10932
|
const inputPath = args.path.trim();
|
|
10837
|
-
const config = loadEditableConfig(
|
|
10933
|
+
const config = loadEditableConfig(projectRoot);
|
|
10838
10934
|
const knowledgeBases = ensureStringArray(config.knowledgeBases);
|
|
10839
10935
|
if (knowledgeBases.length === 0) {
|
|
10840
10936
|
return "No knowledge bases configured.";
|
|
10841
10937
|
}
|
|
10842
|
-
const index = findKnowledgeBasePathIndex(knowledgeBases, inputPath,
|
|
10938
|
+
const index = findKnowledgeBasePathIndex(knowledgeBases, inputPath, projectRoot);
|
|
10843
10939
|
if (index === -1) {
|
|
10844
10940
|
let result2 = `Knowledge base not found: ${inputPath}
|
|
10845
10941
|
|
|
@@ -10854,14 +10950,14 @@ var remove_knowledge_base = tool({
|
|
|
10854
10950
|
}
|
|
10855
10951
|
const removed = knowledgeBases.splice(index, 1)[0];
|
|
10856
10952
|
config.knowledgeBases = knowledgeBases;
|
|
10857
|
-
saveConfig(
|
|
10858
|
-
|
|
10953
|
+
saveConfig(projectRoot, config);
|
|
10954
|
+
refreshIndexerForDirectory(projectRoot);
|
|
10859
10955
|
let result = `Removed: ${removed}
|
|
10860
10956
|
|
|
10861
10957
|
`;
|
|
10862
10958
|
result += `Remaining knowledge bases: ${knowledgeBases.length}
|
|
10863
10959
|
`;
|
|
10864
|
-
result += `Config saved to: ${getConfigPath(
|
|
10960
|
+
result += `Config saved to: ${getConfigPath(projectRoot)}
|
|
10865
10961
|
`;
|
|
10866
10962
|
result += `
|
|
10867
10963
|
Run /index to rebuild the index without the removed knowledge base.`;
|
|
@@ -11148,6 +11244,8 @@ var RoutingHintController = class {
|
|
|
11148
11244
|
this.getStatus = getStatus;
|
|
11149
11245
|
this.maxSessions = maxSessions;
|
|
11150
11246
|
}
|
|
11247
|
+
getStatus;
|
|
11248
|
+
maxSessions;
|
|
11151
11249
|
sessionState = /* @__PURE__ */ new Map();
|
|
11152
11250
|
observeUserMessage(sessionID, parts) {
|
|
11153
11251
|
const assessment = assessRoutingIntent(extractUserText(parts));
|
|
@@ -11204,10 +11302,16 @@ var RoutingHintController = class {
|
|
|
11204
11302
|
};
|
|
11205
11303
|
|
|
11206
11304
|
// src/index.ts
|
|
11207
|
-
var
|
|
11208
|
-
function replaceActiveWatcher(nextWatcher) {
|
|
11209
|
-
|
|
11210
|
-
|
|
11305
|
+
var activeWatchers = /* @__PURE__ */ new Map();
|
|
11306
|
+
function replaceActiveWatcher(projectRoot, nextWatcher) {
|
|
11307
|
+
const existing = activeWatchers.get(projectRoot);
|
|
11308
|
+
if (existing) {
|
|
11309
|
+
existing.stop();
|
|
11310
|
+
activeWatchers.delete(projectRoot);
|
|
11311
|
+
}
|
|
11312
|
+
if (nextWatcher) {
|
|
11313
|
+
activeWatchers.set(projectRoot, nextWatcher);
|
|
11314
|
+
}
|
|
11211
11315
|
}
|
|
11212
11316
|
function getCommandsDir() {
|
|
11213
11317
|
let currentDir = process.cwd();
|
|
@@ -11216,21 +11320,37 @@ function getCommandsDir() {
|
|
|
11216
11320
|
}
|
|
11217
11321
|
return path17.join(currentDir, "..", "commands");
|
|
11218
11322
|
}
|
|
11219
|
-
|
|
11323
|
+
function appendRoutingHints(output, hints, preferredRole) {
|
|
11324
|
+
const preferredBucket = preferredRole === "developer" ? output.developer : output.system;
|
|
11325
|
+
if (Array.isArray(preferredBucket)) {
|
|
11326
|
+
preferredBucket.push(...hints);
|
|
11327
|
+
return;
|
|
11328
|
+
}
|
|
11329
|
+
if (Array.isArray(output.system)) {
|
|
11330
|
+
output.system.push(...hints);
|
|
11331
|
+
}
|
|
11332
|
+
}
|
|
11333
|
+
var plugin = async ({ directory, worktree }) => {
|
|
11220
11334
|
try {
|
|
11221
|
-
const projectRoot = directory;
|
|
11335
|
+
const projectRoot = worktree || directory;
|
|
11222
11336
|
const rawConfig = loadMergedConfig(projectRoot);
|
|
11223
11337
|
const config = parseConfig(rawConfig);
|
|
11224
11338
|
initializeTools(projectRoot, config);
|
|
11225
|
-
const
|
|
11226
|
-
const routingHints = config.search.routingHints ? new RoutingHintController(() =>
|
|
11227
|
-
const
|
|
11228
|
-
|
|
11339
|
+
const getProjectIndexer = () => getIndexerForProject(projectRoot);
|
|
11340
|
+
const routingHints = config.search.routingHints ? new RoutingHintController(() => getProjectIndexer().getStatus()) : null;
|
|
11341
|
+
const isHomeDir = path17.resolve(projectRoot) === path17.resolve(os6.homedir());
|
|
11342
|
+
const isValidProject = !isHomeDir && (!config.indexing.requireProjectMarker || hasProjectMarker(projectRoot));
|
|
11343
|
+
if (isHomeDir) {
|
|
11344
|
+
console.warn(
|
|
11345
|
+
`[codebase-index] Refusing to watch or index home directory "${projectRoot}". Open a specific project directory instead.`
|
|
11346
|
+
);
|
|
11347
|
+
} else if (!isValidProject) {
|
|
11229
11348
|
console.warn(
|
|
11230
11349
|
`[codebase-index] Skipping file watching and auto-indexing: no project marker found in "${projectRoot}". Set "indexing.requireProjectMarker": false in config to override.`
|
|
11231
11350
|
);
|
|
11232
11351
|
}
|
|
11233
11352
|
if (config.indexing.autoIndex && isValidProject) {
|
|
11353
|
+
const indexer = getProjectIndexer();
|
|
11234
11354
|
indexer.initialize().then(() => {
|
|
11235
11355
|
indexer.index().catch(() => {
|
|
11236
11356
|
});
|
|
@@ -11238,9 +11358,9 @@ var plugin = async ({ directory }) => {
|
|
|
11238
11358
|
});
|
|
11239
11359
|
}
|
|
11240
11360
|
if (config.indexing.watchFiles && isValidProject) {
|
|
11241
|
-
replaceActiveWatcher(createWatcherWithIndexer(
|
|
11361
|
+
replaceActiveWatcher(projectRoot, createWatcherWithIndexer(getProjectIndexer, projectRoot, config));
|
|
11242
11362
|
} else {
|
|
11243
|
-
replaceActiveWatcher(null);
|
|
11363
|
+
replaceActiveWatcher(projectRoot, null);
|
|
11244
11364
|
}
|
|
11245
11365
|
return {
|
|
11246
11366
|
tool: {
|
|
@@ -11253,6 +11373,7 @@ var plugin = async ({ directory }) => {
|
|
|
11253
11373
|
index_logs,
|
|
11254
11374
|
find_similar,
|
|
11255
11375
|
call_graph,
|
|
11376
|
+
call_graph_path,
|
|
11256
11377
|
implementation_lookup,
|
|
11257
11378
|
add_knowledge_base,
|
|
11258
11379
|
list_knowledge_bases,
|
|
@@ -11262,8 +11383,18 @@ var plugin = async ({ directory }) => {
|
|
|
11262
11383
|
routingHints?.observeUserMessage(input.sessionID, output.parts);
|
|
11263
11384
|
},
|
|
11264
11385
|
async "experimental.chat.system.transform"(input, output) {
|
|
11386
|
+
if (config.search.routingHintRole !== "system") {
|
|
11387
|
+
return;
|
|
11388
|
+
}
|
|
11265
11389
|
const hints = await routingHints?.getSystemHints(input.sessionID) ?? [];
|
|
11266
|
-
output
|
|
11390
|
+
appendRoutingHints(output, hints, "system");
|
|
11391
|
+
},
|
|
11392
|
+
async "experimental.chat.developer.transform"(input, output) {
|
|
11393
|
+
if (config.search.routingHintRole !== "developer") {
|
|
11394
|
+
return;
|
|
11395
|
+
}
|
|
11396
|
+
const hints = await routingHints?.getSystemHints(input.sessionID) ?? [];
|
|
11397
|
+
appendRoutingHints(output, hints, "developer");
|
|
11267
11398
|
},
|
|
11268
11399
|
async "tool.execute.after"(input) {
|
|
11269
11400
|
routingHints?.markToolUsed(input.sessionID, input.tool);
|
|
@@ -11277,8 +11408,8 @@ var plugin = async ({ directory }) => {
|
|
|
11277
11408
|
}
|
|
11278
11409
|
}
|
|
11279
11410
|
};
|
|
11280
|
-
} catch
|
|
11281
|
-
console.error("[codebase-index] Failed to initialize plugin
|
|
11411
|
+
} catch {
|
|
11412
|
+
console.error("[codebase-index] Failed to initialize plugin (check config and network)");
|
|
11282
11413
|
return {
|
|
11283
11414
|
tool: void 0,
|
|
11284
11415
|
async config() {
|