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.cjs
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 __export = (target, all) => {
|
|
13
17
|
for (var name in all)
|
|
@@ -657,6 +661,7 @@ __export(index_exports, {
|
|
|
657
661
|
default: () => index_default
|
|
658
662
|
});
|
|
659
663
|
module.exports = __toCommonJS(index_exports);
|
|
664
|
+
var os6 = __toESM(require("os"), 1);
|
|
660
665
|
var path17 = __toESM(require("path"), 1);
|
|
661
666
|
var import_url2 = require("url");
|
|
662
667
|
|
|
@@ -803,7 +808,8 @@ function getDefaultSearchConfig() {
|
|
|
803
808
|
rrfK: 60,
|
|
804
809
|
rerankTopN: 20,
|
|
805
810
|
contextLines: 0,
|
|
806
|
-
routingHints: true
|
|
811
|
+
routingHints: true,
|
|
812
|
+
routingHintRole: "system"
|
|
807
813
|
};
|
|
808
814
|
}
|
|
809
815
|
function getDefaultRerankerBaseUrl(provider) {
|
|
@@ -924,7 +930,8 @@ function parseConfig(raw) {
|
|
|
924
930
|
rrfK: typeof rawSearch.rrfK === "number" ? Math.max(1, Math.floor(rawSearch.rrfK)) : defaultSearch.rrfK,
|
|
925
931
|
rerankTopN: typeof rawSearch.rerankTopN === "number" ? Math.min(200, Math.max(0, Math.floor(rawSearch.rerankTopN))) : defaultSearch.rerankTopN,
|
|
926
932
|
contextLines: typeof rawSearch.contextLines === "number" ? Math.min(50, Math.max(0, rawSearch.contextLines)) : defaultSearch.contextLines,
|
|
927
|
-
routingHints: typeof rawSearch.routingHints === "boolean" ? rawSearch.routingHints : defaultSearch.routingHints
|
|
933
|
+
routingHints: typeof rawSearch.routingHints === "boolean" ? rawSearch.routingHints : defaultSearch.routingHints,
|
|
934
|
+
routingHintRole: rawSearch.routingHintRole === "developer" || rawSearch.routingHintRole === "system" ? rawSearch.routingHintRole : defaultSearch.routingHintRole
|
|
928
935
|
};
|
|
929
936
|
const rawDebug = input.debug && typeof input.debug === "object" ? input.debug : {};
|
|
930
937
|
const debug = {
|
|
@@ -1246,6 +1253,32 @@ function hasFilteredPathSegment(relativePath, separator = path4.sep) {
|
|
|
1246
1253
|
(part) => isHiddenPathSegment(part) || isBuildPathSegment(part)
|
|
1247
1254
|
);
|
|
1248
1255
|
}
|
|
1256
|
+
var RESTRICTED_DIRECTORIES = /* @__PURE__ */ new Set([
|
|
1257
|
+
// macOS
|
|
1258
|
+
"library",
|
|
1259
|
+
"applications",
|
|
1260
|
+
"system",
|
|
1261
|
+
"volumes",
|
|
1262
|
+
"private",
|
|
1263
|
+
"cores",
|
|
1264
|
+
// Linux
|
|
1265
|
+
"proc",
|
|
1266
|
+
"sys",
|
|
1267
|
+
"dev",
|
|
1268
|
+
"run",
|
|
1269
|
+
"snap",
|
|
1270
|
+
// Windows
|
|
1271
|
+
"windows",
|
|
1272
|
+
"programdata",
|
|
1273
|
+
"program files",
|
|
1274
|
+
"program files (x86)",
|
|
1275
|
+
"$recycle.bin"
|
|
1276
|
+
]);
|
|
1277
|
+
function isRestrictedDirectory(relativePath, separator = path4.sep) {
|
|
1278
|
+
const firstSegment = relativePath.split(separator)[0];
|
|
1279
|
+
if (!firstSegment) return false;
|
|
1280
|
+
return RESTRICTED_DIRECTORIES.has(firstSegment.toLowerCase());
|
|
1281
|
+
}
|
|
1249
1282
|
|
|
1250
1283
|
// src/config/rebase.ts
|
|
1251
1284
|
function isWithinRoot(rootDir, targetPath) {
|
|
@@ -2305,7 +2338,7 @@ var NodeFsHandler = class {
|
|
|
2305
2338
|
this._addToNodeFs(path18, initialAdd, wh, depth + 1);
|
|
2306
2339
|
}
|
|
2307
2340
|
}).on(EV.ERROR, this._boundHandleError);
|
|
2308
|
-
return new Promise((
|
|
2341
|
+
return new Promise((resolve12, reject) => {
|
|
2309
2342
|
if (!stream)
|
|
2310
2343
|
return reject();
|
|
2311
2344
|
stream.once(STR_END, () => {
|
|
@@ -2314,7 +2347,7 @@ var NodeFsHandler = class {
|
|
|
2314
2347
|
return;
|
|
2315
2348
|
}
|
|
2316
2349
|
const wasThrottled = throttler ? throttler.clear() : false;
|
|
2317
|
-
|
|
2350
|
+
resolve12(void 0);
|
|
2318
2351
|
previous.getChildren().filter((item) => {
|
|
2319
2352
|
return item !== directory && !current.has(item);
|
|
2320
2353
|
}).forEach((item) => {
|
|
@@ -3414,6 +3447,9 @@ var FileWatcher = class {
|
|
|
3414
3447
|
if (hasFilteredPathSegment(relativePath, path8.sep)) {
|
|
3415
3448
|
return true;
|
|
3416
3449
|
}
|
|
3450
|
+
if (isRestrictedDirectory(relativePath, path8.sep)) {
|
|
3451
|
+
return true;
|
|
3452
|
+
}
|
|
3417
3453
|
if (ignoreFilter.ignores(relativePath)) {
|
|
3418
3454
|
return true;
|
|
3419
3455
|
}
|
|
@@ -3426,6 +3462,13 @@ var FileWatcher = class {
|
|
|
3426
3462
|
pollInterval: 100
|
|
3427
3463
|
}
|
|
3428
3464
|
});
|
|
3465
|
+
this.watcher.on("error", (error) => {
|
|
3466
|
+
const err = error instanceof Error ? error : null;
|
|
3467
|
+
if (err?.code === "EPERM" || err?.code === "EACCES") {
|
|
3468
|
+
return;
|
|
3469
|
+
}
|
|
3470
|
+
console.error("[codebase-index] Watcher error:", err?.message ?? error);
|
|
3471
|
+
});
|
|
3429
3472
|
this.watcher.on("add", (filePath) => this.handleChange("add", filePath));
|
|
3430
3473
|
this.watcher.on("change", (filePath) => this.handleChange("change", filePath));
|
|
3431
3474
|
this.watcher.on("unlink", (filePath) => this.handleChange("unlink", filePath));
|
|
@@ -3560,7 +3603,7 @@ var GitHeadWatcher = class {
|
|
|
3560
3603
|
};
|
|
3561
3604
|
|
|
3562
3605
|
// src/watcher/index.ts
|
|
3563
|
-
function createWatcherWithIndexer(
|
|
3606
|
+
function createWatcherWithIndexer(getIndexer, projectRoot, config) {
|
|
3564
3607
|
const fileWatcher = new FileWatcher(projectRoot, config);
|
|
3565
3608
|
fileWatcher.start(async (changes) => {
|
|
3566
3609
|
const hasAddOrChange = changes.some(
|
|
@@ -3568,7 +3611,7 @@ function createWatcherWithIndexer(getIndexer2, projectRoot, config) {
|
|
|
3568
3611
|
);
|
|
3569
3612
|
const hasDelete = changes.some((c) => c.type === "unlink");
|
|
3570
3613
|
if (hasAddOrChange || hasDelete) {
|
|
3571
|
-
await
|
|
3614
|
+
await getIndexer().index();
|
|
3572
3615
|
}
|
|
3573
3616
|
});
|
|
3574
3617
|
let gitWatcher = null;
|
|
@@ -3576,7 +3619,7 @@ function createWatcherWithIndexer(getIndexer2, projectRoot, config) {
|
|
|
3576
3619
|
gitWatcher = new GitHeadWatcher(projectRoot);
|
|
3577
3620
|
gitWatcher.start(async (oldBranch, newBranch) => {
|
|
3578
3621
|
console.log(`Branch changed: ${oldBranch ?? "(none)"} -> ${newBranch}`);
|
|
3579
|
-
await
|
|
3622
|
+
await getIndexer().index();
|
|
3580
3623
|
});
|
|
3581
3624
|
}
|
|
3582
3625
|
return {
|
|
@@ -3619,7 +3662,7 @@ function pTimeout(promise, options) {
|
|
|
3619
3662
|
} = options;
|
|
3620
3663
|
let timer;
|
|
3621
3664
|
let abortHandler;
|
|
3622
|
-
const wrappedPromise = new Promise((
|
|
3665
|
+
const wrappedPromise = new Promise((resolve12, reject) => {
|
|
3623
3666
|
if (typeof milliseconds !== "number" || Math.sign(milliseconds) !== 1) {
|
|
3624
3667
|
throw new TypeError(`Expected \`milliseconds\` to be a positive number, got \`${milliseconds}\``);
|
|
3625
3668
|
}
|
|
@@ -3633,7 +3676,7 @@ function pTimeout(promise, options) {
|
|
|
3633
3676
|
};
|
|
3634
3677
|
signal.addEventListener("abort", abortHandler, { once: true });
|
|
3635
3678
|
}
|
|
3636
|
-
promise.then(
|
|
3679
|
+
promise.then(resolve12, reject);
|
|
3637
3680
|
if (milliseconds === Number.POSITIVE_INFINITY) {
|
|
3638
3681
|
return;
|
|
3639
3682
|
}
|
|
@@ -3641,7 +3684,7 @@ function pTimeout(promise, options) {
|
|
|
3641
3684
|
timer = customTimers.setTimeout.call(void 0, () => {
|
|
3642
3685
|
if (fallback) {
|
|
3643
3686
|
try {
|
|
3644
|
-
|
|
3687
|
+
resolve12(fallback());
|
|
3645
3688
|
} catch (error) {
|
|
3646
3689
|
reject(error);
|
|
3647
3690
|
}
|
|
@@ -3651,7 +3694,7 @@ function pTimeout(promise, options) {
|
|
|
3651
3694
|
promise.cancel();
|
|
3652
3695
|
}
|
|
3653
3696
|
if (message === false) {
|
|
3654
|
-
|
|
3697
|
+
resolve12();
|
|
3655
3698
|
} else if (message instanceof Error) {
|
|
3656
3699
|
reject(message);
|
|
3657
3700
|
} else {
|
|
@@ -4053,7 +4096,7 @@ var PQueue = class extends import_index.default {
|
|
|
4053
4096
|
// Assign unique ID if not provided
|
|
4054
4097
|
id: options.id ?? (this.#idAssigner++).toString()
|
|
4055
4098
|
};
|
|
4056
|
-
return new Promise((
|
|
4099
|
+
return new Promise((resolve12, reject) => {
|
|
4057
4100
|
const taskSymbol = /* @__PURE__ */ Symbol(`task-${options.id}`);
|
|
4058
4101
|
let cleanupQueueAbortHandler = () => void 0;
|
|
4059
4102
|
const run = async () => {
|
|
@@ -4093,7 +4136,7 @@ var PQueue = class extends import_index.default {
|
|
|
4093
4136
|
})]);
|
|
4094
4137
|
}
|
|
4095
4138
|
const result = await operation;
|
|
4096
|
-
|
|
4139
|
+
resolve12(result);
|
|
4097
4140
|
this.emit("completed", result);
|
|
4098
4141
|
} catch (error) {
|
|
4099
4142
|
reject(error);
|
|
@@ -4281,13 +4324,13 @@ var PQueue = class extends import_index.default {
|
|
|
4281
4324
|
});
|
|
4282
4325
|
}
|
|
4283
4326
|
async #onEvent(event, filter) {
|
|
4284
|
-
return new Promise((
|
|
4327
|
+
return new Promise((resolve12) => {
|
|
4285
4328
|
const listener = () => {
|
|
4286
4329
|
if (filter && !filter()) {
|
|
4287
4330
|
return;
|
|
4288
4331
|
}
|
|
4289
4332
|
this.off(event, listener);
|
|
4290
|
-
|
|
4333
|
+
resolve12();
|
|
4291
4334
|
};
|
|
4292
4335
|
this.on(event, listener);
|
|
4293
4336
|
});
|
|
@@ -4573,7 +4616,7 @@ async function onAttemptFailure({ error, attemptNumber, retriesConsumed, startTi
|
|
|
4573
4616
|
const finalDelay = Math.min(delayTime, remainingTime);
|
|
4574
4617
|
options.signal?.throwIfAborted();
|
|
4575
4618
|
if (finalDelay > 0) {
|
|
4576
|
-
await new Promise((
|
|
4619
|
+
await new Promise((resolve12, reject) => {
|
|
4577
4620
|
const onAbort = () => {
|
|
4578
4621
|
clearTimeout(timeoutToken);
|
|
4579
4622
|
options.signal?.removeEventListener("abort", onAbort);
|
|
@@ -4581,7 +4624,7 @@ async function onAttemptFailure({ error, attemptNumber, retriesConsumed, startTi
|
|
|
4581
4624
|
};
|
|
4582
4625
|
const timeoutToken = setTimeout(() => {
|
|
4583
4626
|
options.signal?.removeEventListener("abort", onAbort);
|
|
4584
|
-
|
|
4627
|
+
resolve12();
|
|
4585
4628
|
}, finalDelay);
|
|
4586
4629
|
if (options.unref) {
|
|
4587
4630
|
timeoutToken.unref?.();
|
|
@@ -4822,6 +4865,8 @@ var BaseEmbeddingProvider = class {
|
|
|
4822
4865
|
this.credentials = credentials;
|
|
4823
4866
|
this.modelInfo = modelInfo;
|
|
4824
4867
|
}
|
|
4868
|
+
credentials;
|
|
4869
|
+
modelInfo;
|
|
4825
4870
|
async embedQuery(query) {
|
|
4826
4871
|
const result = await this.embedBatch([query]);
|
|
4827
4872
|
return {
|
|
@@ -6370,17 +6415,17 @@ var Database = class {
|
|
|
6370
6415
|
if (edges.length === 0) return;
|
|
6371
6416
|
this.inner.upsertCallEdgesBatch(edges);
|
|
6372
6417
|
}
|
|
6373
|
-
getCallers(targetName, branch) {
|
|
6418
|
+
getCallers(targetName, branch, callTypeFilter) {
|
|
6374
6419
|
this.throwIfClosed();
|
|
6375
|
-
return this.inner.getCallers(targetName, branch);
|
|
6420
|
+
return this.inner.getCallers(targetName, branch, callTypeFilter ?? null);
|
|
6376
6421
|
}
|
|
6377
|
-
getCallersWithContext(targetName, branch) {
|
|
6422
|
+
getCallersWithContext(targetName, branch, callTypeFilter) {
|
|
6378
6423
|
this.throwIfClosed();
|
|
6379
|
-
return this.inner.getCallersWithContext(targetName, branch);
|
|
6424
|
+
return this.inner.getCallersWithContext(targetName, branch, callTypeFilter ?? null);
|
|
6380
6425
|
}
|
|
6381
|
-
getCallees(symbolId, branch) {
|
|
6426
|
+
getCallees(symbolId, branch, callTypeFilter) {
|
|
6382
6427
|
this.throwIfClosed();
|
|
6383
|
-
return this.inner.getCallees(symbolId, branch);
|
|
6428
|
+
return this.inner.getCallees(symbolId, branch, callTypeFilter ?? null);
|
|
6384
6429
|
}
|
|
6385
6430
|
deleteCallEdgesByFile(filePath) {
|
|
6386
6431
|
this.throwIfClosed();
|
|
@@ -6390,6 +6435,10 @@ var Database = class {
|
|
|
6390
6435
|
this.throwIfClosed();
|
|
6391
6436
|
this.inner.resolveCallEdge(edgeId, toSymbolId);
|
|
6392
6437
|
}
|
|
6438
|
+
findShortestPath(fromName, toName, branch, maxDepth) {
|
|
6439
|
+
this.throwIfClosed();
|
|
6440
|
+
return this.inner.findShortestPath(fromName, toName, branch, maxDepth ?? null);
|
|
6441
|
+
}
|
|
6393
6442
|
addSymbolsToBranch(branch, symbolIds) {
|
|
6394
6443
|
this.throwIfClosed();
|
|
6395
6444
|
this.inner.addSymbolsToBranch(branch, symbolIds);
|
|
@@ -9017,6 +9066,7 @@ var Indexer = class {
|
|
|
9017
9066
|
targetName: site.calleeName,
|
|
9018
9067
|
toSymbolId: void 0,
|
|
9019
9068
|
callType: site.callType,
|
|
9069
|
+
confidence: site.confidence,
|
|
9020
9070
|
line: site.line,
|
|
9021
9071
|
col: site.column,
|
|
9022
9072
|
isResolved: false
|
|
@@ -9161,7 +9211,7 @@ var Indexer = class {
|
|
|
9161
9211
|
for (const requestBatch of requestBatches) {
|
|
9162
9212
|
queue.add(async () => {
|
|
9163
9213
|
if (rateLimitBackoffMs > 0) {
|
|
9164
|
-
await new Promise((
|
|
9214
|
+
await new Promise((resolve12) => setTimeout(resolve12, rateLimitBackoffMs));
|
|
9165
9215
|
}
|
|
9166
9216
|
try {
|
|
9167
9217
|
const result = await pRetry(
|
|
@@ -10136,12 +10186,12 @@ var Indexer = class {
|
|
|
10136
10186
|
})
|
|
10137
10187
|
);
|
|
10138
10188
|
}
|
|
10139
|
-
async getCallers(targetName) {
|
|
10189
|
+
async getCallers(targetName, callTypeFilter) {
|
|
10140
10190
|
const { database } = await this.ensureInitialized();
|
|
10141
10191
|
const seen = /* @__PURE__ */ new Set();
|
|
10142
10192
|
const results = [];
|
|
10143
10193
|
for (const branchKey of this.getBranchCatalogKeys()) {
|
|
10144
|
-
for (const edge of database.getCallersWithContext(targetName, branchKey)) {
|
|
10194
|
+
for (const edge of database.getCallersWithContext(targetName, branchKey, callTypeFilter)) {
|
|
10145
10195
|
if (!seen.has(edge.id)) {
|
|
10146
10196
|
seen.add(edge.id);
|
|
10147
10197
|
results.push(edge);
|
|
@@ -10150,12 +10200,12 @@ var Indexer = class {
|
|
|
10150
10200
|
}
|
|
10151
10201
|
return results;
|
|
10152
10202
|
}
|
|
10153
|
-
async getCallees(symbolId) {
|
|
10203
|
+
async getCallees(symbolId, callTypeFilter) {
|
|
10154
10204
|
const { database } = await this.ensureInitialized();
|
|
10155
10205
|
const seen = /* @__PURE__ */ new Set();
|
|
10156
10206
|
const results = [];
|
|
10157
10207
|
for (const branchKey of this.getBranchCatalogKeys()) {
|
|
10158
|
-
for (const edge of database.getCallees(symbolId, branchKey)) {
|
|
10208
|
+
for (const edge of database.getCallees(symbolId, branchKey, callTypeFilter)) {
|
|
10159
10209
|
if (!seen.has(edge.id)) {
|
|
10160
10210
|
seen.add(edge.id);
|
|
10161
10211
|
results.push(edge);
|
|
@@ -10164,6 +10214,17 @@ var Indexer = class {
|
|
|
10164
10214
|
}
|
|
10165
10215
|
return results;
|
|
10166
10216
|
}
|
|
10217
|
+
async findCallPath(fromName, toName, maxDepth) {
|
|
10218
|
+
const { database } = await this.ensureInitialized();
|
|
10219
|
+
let shortest = [];
|
|
10220
|
+
for (const branchKey of this.getBranchCatalogKeys()) {
|
|
10221
|
+
const path18 = database.findShortestPath(fromName, toName, branchKey, maxDepth);
|
|
10222
|
+
if (path18.length > 0 && (shortest.length === 0 || path18.length < shortest.length)) {
|
|
10223
|
+
shortest = path18;
|
|
10224
|
+
}
|
|
10225
|
+
}
|
|
10226
|
+
return shortest;
|
|
10227
|
+
}
|
|
10167
10228
|
async close() {
|
|
10168
10229
|
await this.database?.close();
|
|
10169
10230
|
this.database = null;
|
|
@@ -10485,39 +10546,45 @@ function ensureStringArray(value) {
|
|
|
10485
10546
|
return Array.isArray(value) ? value : [];
|
|
10486
10547
|
}
|
|
10487
10548
|
var z = import_plugin.tool.schema;
|
|
10488
|
-
var
|
|
10489
|
-
var
|
|
10549
|
+
var indexerMap = /* @__PURE__ */ new Map();
|
|
10550
|
+
var defaultProjectRoot = "";
|
|
10490
10551
|
function initializeTools(projectRoot, config) {
|
|
10491
|
-
|
|
10492
|
-
|
|
10493
|
-
|
|
10494
|
-
function getSharedIndexer() {
|
|
10495
|
-
return getIndexer();
|
|
10552
|
+
defaultProjectRoot = projectRoot;
|
|
10553
|
+
const indexer = new Indexer(projectRoot, config);
|
|
10554
|
+
indexerMap.set(projectRoot, indexer);
|
|
10496
10555
|
}
|
|
10497
|
-
function
|
|
10498
|
-
if (!
|
|
10556
|
+
function refreshIndexerForDirectory(projectRoot) {
|
|
10557
|
+
if (!projectRoot) {
|
|
10499
10558
|
throw new Error("Codebase index tools not initialized. Plugin may not be loaded correctly.");
|
|
10500
10559
|
}
|
|
10501
|
-
|
|
10560
|
+
const indexer = new Indexer(projectRoot, parseConfig(loadRuntimeConfig(projectRoot)));
|
|
10561
|
+
indexerMap.set(projectRoot, indexer);
|
|
10502
10562
|
}
|
|
10503
|
-
function shouldForceLocalizeProjectIndex() {
|
|
10504
|
-
const currentConfig = parseConfig(loadRuntimeConfig(
|
|
10563
|
+
function shouldForceLocalizeProjectIndex(projectRoot) {
|
|
10564
|
+
const currentConfig = parseConfig(loadRuntimeConfig(projectRoot));
|
|
10505
10565
|
if (currentConfig.scope !== "project") {
|
|
10506
10566
|
return false;
|
|
10507
10567
|
}
|
|
10508
|
-
const localIndexPath = path15.join(
|
|
10509
|
-
const mainRepoRoot = resolveWorktreeMainRepoRoot(
|
|
10568
|
+
const localIndexPath = path15.join(projectRoot, ".opencode", "index");
|
|
10569
|
+
const mainRepoRoot = resolveWorktreeMainRepoRoot(projectRoot);
|
|
10510
10570
|
if (!mainRepoRoot) {
|
|
10511
10571
|
return false;
|
|
10512
10572
|
}
|
|
10513
10573
|
const inheritedIndexPath = path15.join(mainRepoRoot, ".opencode", "index");
|
|
10514
10574
|
return !(0, import_fs9.existsSync)(localIndexPath) && (0, import_fs9.existsSync)(inheritedIndexPath);
|
|
10515
10575
|
}
|
|
10516
|
-
function
|
|
10517
|
-
|
|
10576
|
+
function getIndexerForProject(directory) {
|
|
10577
|
+
const projectRoot = directory || defaultProjectRoot;
|
|
10578
|
+
if (!projectRoot) {
|
|
10518
10579
|
throw new Error("Codebase index tools not initialized. Plugin may not be loaded correctly.");
|
|
10519
10580
|
}
|
|
10520
|
-
|
|
10581
|
+
let indexer = indexerMap.get(projectRoot);
|
|
10582
|
+
if (!indexer) {
|
|
10583
|
+
const config = parseConfig(loadRuntimeConfig(projectRoot));
|
|
10584
|
+
indexer = new Indexer(projectRoot, config);
|
|
10585
|
+
indexerMap.set(projectRoot, indexer);
|
|
10586
|
+
}
|
|
10587
|
+
return indexer;
|
|
10521
10588
|
}
|
|
10522
10589
|
var codebase_peek = (0, import_plugin.tool)({
|
|
10523
10590
|
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.",
|
|
@@ -10528,8 +10595,8 @@ var codebase_peek = (0, import_plugin.tool)({
|
|
|
10528
10595
|
directory: z.string().optional().describe("Filter by directory path (e.g., 'src/utils', 'lib')"),
|
|
10529
10596
|
chunkType: z.enum(["function", "class", "method", "interface", "type", "enum", "struct", "impl", "trait", "module", "other"]).optional().describe("Filter by code chunk type")
|
|
10530
10597
|
},
|
|
10531
|
-
async execute(args) {
|
|
10532
|
-
const indexer =
|
|
10598
|
+
async execute(args, context) {
|
|
10599
|
+
const indexer = getIndexerForProject(context?.worktree);
|
|
10533
10600
|
const results = await indexer.search(args.query, args.limit ?? 10, {
|
|
10534
10601
|
fileType: args.fileType,
|
|
10535
10602
|
directory: args.directory,
|
|
@@ -10547,16 +10614,17 @@ var index_codebase = (0, import_plugin.tool)({
|
|
|
10547
10614
|
verbose: z.boolean().optional().default(false).describe("Show detailed info about skipped files and parsing failures")
|
|
10548
10615
|
},
|
|
10549
10616
|
async execute(args, context) {
|
|
10550
|
-
|
|
10617
|
+
const projectRoot = context?.worktree || defaultProjectRoot;
|
|
10618
|
+
let indexer = getIndexerForProject(projectRoot);
|
|
10551
10619
|
if (args.estimateOnly) {
|
|
10552
10620
|
const estimate = await indexer.estimateCost();
|
|
10553
10621
|
return formatCostEstimate(estimate);
|
|
10554
10622
|
}
|
|
10555
10623
|
if (args.force) {
|
|
10556
|
-
if (shouldForceLocalizeProjectIndex()) {
|
|
10557
|
-
materializeLocalProjectConfig(
|
|
10558
|
-
|
|
10559
|
-
indexer =
|
|
10624
|
+
if (shouldForceLocalizeProjectIndex(projectRoot)) {
|
|
10625
|
+
materializeLocalProjectConfig(projectRoot, loadProjectConfigLayer(projectRoot));
|
|
10626
|
+
refreshIndexerForDirectory(projectRoot);
|
|
10627
|
+
indexer = getIndexerForProject(projectRoot);
|
|
10560
10628
|
}
|
|
10561
10629
|
await indexer.clearIndex();
|
|
10562
10630
|
}
|
|
@@ -10579,8 +10647,8 @@ var index_codebase = (0, import_plugin.tool)({
|
|
|
10579
10647
|
var index_status = (0, import_plugin.tool)({
|
|
10580
10648
|
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.",
|
|
10581
10649
|
args: {},
|
|
10582
|
-
async execute() {
|
|
10583
|
-
const indexer =
|
|
10650
|
+
async execute(_args, context) {
|
|
10651
|
+
const indexer = getIndexerForProject(context?.worktree);
|
|
10584
10652
|
const status = await indexer.getStatus();
|
|
10585
10653
|
return formatStatus(status);
|
|
10586
10654
|
}
|
|
@@ -10588,8 +10656,8 @@ var index_status = (0, import_plugin.tool)({
|
|
|
10588
10656
|
var index_health_check = (0, import_plugin.tool)({
|
|
10589
10657
|
description: "Check index health and remove stale entries from deleted files. Run this to clean up the index after files have been deleted.",
|
|
10590
10658
|
args: {},
|
|
10591
|
-
async execute() {
|
|
10592
|
-
const indexer =
|
|
10659
|
+
async execute(_args, context) {
|
|
10660
|
+
const indexer = getIndexerForProject(context?.worktree);
|
|
10593
10661
|
const result = await indexer.healthCheck();
|
|
10594
10662
|
return formatHealthCheck(result);
|
|
10595
10663
|
}
|
|
@@ -10597,8 +10665,8 @@ var index_health_check = (0, import_plugin.tool)({
|
|
|
10597
10665
|
var index_metrics = (0, import_plugin.tool)({
|
|
10598
10666
|
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.",
|
|
10599
10667
|
args: {},
|
|
10600
|
-
async execute() {
|
|
10601
|
-
const indexer =
|
|
10668
|
+
async execute(_args, context) {
|
|
10669
|
+
const indexer = getIndexerForProject(context?.worktree);
|
|
10602
10670
|
const logger = indexer.getLogger();
|
|
10603
10671
|
if (!logger.isEnabled()) {
|
|
10604
10672
|
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```';
|
|
@@ -10616,8 +10684,8 @@ var index_logs = (0, import_plugin.tool)({
|
|
|
10616
10684
|
category: z.enum(["search", "embedding", "cache", "gc", "branch", "general"]).optional().describe("Filter by log category"),
|
|
10617
10685
|
level: z.enum(["error", "warn", "info", "debug"]).optional().describe("Filter by minimum log level")
|
|
10618
10686
|
},
|
|
10619
|
-
async execute(args) {
|
|
10620
|
-
const indexer =
|
|
10687
|
+
async execute(args, context) {
|
|
10688
|
+
const indexer = getIndexerForProject(context?.worktree);
|
|
10621
10689
|
const logger = indexer.getLogger();
|
|
10622
10690
|
if (!logger.isEnabled()) {
|
|
10623
10691
|
return 'Debug mode is disabled. Enable it in your config:\n\n```json\n{\n "debug": {\n "enabled": true\n }\n}\n```';
|
|
@@ -10643,8 +10711,8 @@ var find_similar = (0, import_plugin.tool)({
|
|
|
10643
10711
|
chunkType: z.enum(["function", "class", "method", "interface", "type", "enum", "struct", "impl", "trait", "module", "other"]).optional().describe("Filter by code chunk type"),
|
|
10644
10712
|
excludeFile: z.string().optional().describe("Exclude results from this file path (useful when searching for duplicates of code from a specific file)")
|
|
10645
10713
|
},
|
|
10646
|
-
async execute(args) {
|
|
10647
|
-
const indexer =
|
|
10714
|
+
async execute(args, context) {
|
|
10715
|
+
const indexer = getIndexerForProject(context?.worktree);
|
|
10648
10716
|
const results = await indexer.findSimilar(args.code, args.limit, {
|
|
10649
10717
|
fileType: args.fileType,
|
|
10650
10718
|
directory: args.directory,
|
|
@@ -10667,8 +10735,8 @@ var codebase_search = (0, import_plugin.tool)({
|
|
|
10667
10735
|
chunkType: z.enum(["function", "class", "method", "interface", "type", "enum", "struct", "impl", "trait", "module", "other"]).optional().describe("Filter by code chunk type"),
|
|
10668
10736
|
contextLines: z.number().optional().describe("Number of extra lines to include before/after each match (default: 0)")
|
|
10669
10737
|
},
|
|
10670
|
-
async execute(args) {
|
|
10671
|
-
const indexer =
|
|
10738
|
+
async execute(args, context) {
|
|
10739
|
+
const indexer = getIndexerForProject(context?.worktree);
|
|
10672
10740
|
const results = await indexer.search(args.query, args.limit ?? 5, {
|
|
10673
10741
|
fileType: args.fileType,
|
|
10674
10742
|
directory: args.directory,
|
|
@@ -10689,8 +10757,8 @@ var implementation_lookup = (0, import_plugin.tool)({
|
|
|
10689
10757
|
fileType: z.string().optional().describe("Filter by file extension (e.g., 'ts', 'py')"),
|
|
10690
10758
|
directory: z.string().optional().describe("Filter by directory path (e.g., 'src/utils')")
|
|
10691
10759
|
},
|
|
10692
|
-
async execute(args) {
|
|
10693
|
-
const indexer =
|
|
10760
|
+
async execute(args, context) {
|
|
10761
|
+
const indexer = getIndexerForProject(context?.worktree);
|
|
10694
10762
|
const results = await indexer.search(args.query, args.limit ?? 5, {
|
|
10695
10763
|
fileType: args.fileType,
|
|
10696
10764
|
directory: args.directory,
|
|
@@ -10700,46 +10768,72 @@ var implementation_lookup = (0, import_plugin.tool)({
|
|
|
10700
10768
|
}
|
|
10701
10769
|
});
|
|
10702
10770
|
var call_graph = (0, import_plugin.tool)({
|
|
10703
|
-
description: "Query the call graph to find callers or callees of a function/method. Use to understand code flow and dependencies between functions.",
|
|
10771
|
+
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.",
|
|
10704
10772
|
args: {
|
|
10705
10773
|
name: z.string().describe("Function or method name to query"),
|
|
10706
10774
|
direction: z.enum(["callers", "callees"]).default("callers").describe("Direction: 'callers' finds who calls this function, 'callees' finds what this function calls"),
|
|
10707
|
-
symbolId: z.string().optional().describe("Symbol ID (required for 'callees' direction, returned by previous call_graph queries)")
|
|
10775
|
+
symbolId: z.string().optional().describe("Symbol ID (required for 'callees' direction, returned by previous call_graph queries)"),
|
|
10776
|
+
relationshipType: z.enum(["Call", "MethodCall", "Constructor", "Import", "Inherits", "Implements"]).optional().describe("Filter by relationship type. Omit to show all.")
|
|
10708
10777
|
},
|
|
10709
|
-
async execute(args) {
|
|
10710
|
-
const indexer =
|
|
10778
|
+
async execute(args, context) {
|
|
10779
|
+
const indexer = getIndexerForProject(context?.worktree);
|
|
10711
10780
|
if (args.direction === "callees") {
|
|
10712
10781
|
if (!args.symbolId) {
|
|
10713
10782
|
return "Error: 'symbolId' is required when direction is 'callees'. First use direction='callers' to find the symbol ID.";
|
|
10714
10783
|
}
|
|
10715
|
-
const callees = await indexer.getCallees(args.symbolId);
|
|
10784
|
+
const callees = await indexer.getCallees(args.symbolId, args.relationshipType);
|
|
10716
10785
|
if (callees.length === 0) {
|
|
10717
|
-
return `No callees found for symbol ${args.symbolId}. The function may not call any other tracked functions.`;
|
|
10786
|
+
return `No callees found for symbol ${args.symbolId}${args.relationshipType ? ` with type ${args.relationshipType}` : ""}. The function may not call any other tracked functions.`;
|
|
10718
10787
|
}
|
|
10719
|
-
const formatted2 = callees.map(
|
|
10720
|
-
|
|
10721
|
-
|
|
10788
|
+
const formatted2 = callees.map((e, i) => {
|
|
10789
|
+
const conf = e.confidence !== "Direct" ? ` [${e.confidence.toLowerCase()}]` : "";
|
|
10790
|
+
return `[${i + 1}] \u2192 ${e.targetName} (${e.callType})${conf} at line ${e.line}${e.isResolved ? ` [resolved: ${e.toSymbolId}]` : " [unresolved]"}`;
|
|
10791
|
+
});
|
|
10722
10792
|
return formatted2.join("\n");
|
|
10723
10793
|
}
|
|
10724
|
-
const callers = await indexer.getCallers(args.name);
|
|
10794
|
+
const callers = await indexer.getCallers(args.name, args.relationshipType);
|
|
10725
10795
|
if (callers.length === 0) {
|
|
10726
|
-
return `No callers found for "${args.name}". It may not be called by any tracked function, or the index needs updating.`;
|
|
10796
|
+
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.`;
|
|
10727
10797
|
}
|
|
10728
|
-
const formatted = callers.map(
|
|
10729
|
-
|
|
10730
|
-
|
|
10798
|
+
const formatted = callers.map((e, i) => {
|
|
10799
|
+
const conf = e.confidence !== "Direct" ? ` [${e.confidence.toLowerCase()}]` : "";
|
|
10800
|
+
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]"}`;
|
|
10801
|
+
});
|
|
10731
10802
|
return formatted.join("\n");
|
|
10732
10803
|
}
|
|
10733
10804
|
});
|
|
10805
|
+
var call_graph_path = (0, import_plugin.tool)({
|
|
10806
|
+
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.",
|
|
10807
|
+
args: {
|
|
10808
|
+
from: z.string().describe("Source function/method name (starting point)"),
|
|
10809
|
+
to: z.string().describe("Target function/method name (destination)"),
|
|
10810
|
+
maxDepth: z.number().optional().default(10).describe("Maximum traversal depth (default: 10)")
|
|
10811
|
+
},
|
|
10812
|
+
async execute(args, context) {
|
|
10813
|
+
const indexer = getIndexerForProject(context?.worktree);
|
|
10814
|
+
const path18 = await indexer.findCallPath(args.from, args.to, args.maxDepth);
|
|
10815
|
+
if (path18.length === 0) {
|
|
10816
|
+
return `No path found between "${args.from}" and "${args.to}". They may be in disconnected components, or the call graph index needs updating.`;
|
|
10817
|
+
}
|
|
10818
|
+
const formatted = path18.map((hop, i) => {
|
|
10819
|
+
const prefix = i === 0 ? "[start]" : `--${hop.callType}-->`;
|
|
10820
|
+
const location = hop.filePath ? ` (${hop.filePath}:${hop.line})` : "";
|
|
10821
|
+
return `${prefix} ${hop.symbolName}${location}`;
|
|
10822
|
+
});
|
|
10823
|
+
return `Path (${path18.length} hops):
|
|
10824
|
+
${formatted.join("\n")}`;
|
|
10825
|
+
}
|
|
10826
|
+
});
|
|
10734
10827
|
var add_knowledge_base = (0, import_plugin.tool)({
|
|
10735
10828
|
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).",
|
|
10736
10829
|
args: {
|
|
10737
10830
|
path: z.string().describe("Path to the folder to add as a knowledge base (absolute or relative to project root)")
|
|
10738
10831
|
},
|
|
10739
|
-
async execute(args) {
|
|
10832
|
+
async execute(args, context) {
|
|
10833
|
+
const projectRoot = context?.worktree || defaultProjectRoot;
|
|
10740
10834
|
const inputPath = args.path.trim();
|
|
10741
10835
|
const normalizedPath = path15.resolve(
|
|
10742
|
-
path15.isAbsolute(inputPath) ? inputPath : resolveKnowledgeBasePath(inputPath,
|
|
10836
|
+
path15.isAbsolute(inputPath) ? inputPath : resolveKnowledgeBasePath(inputPath, projectRoot)
|
|
10743
10837
|
);
|
|
10744
10838
|
if (!(0, import_fs9.existsSync)(normalizedPath)) {
|
|
10745
10839
|
return `Error: Directory does not exist: ${normalizedPath}`;
|
|
@@ -10781,21 +10875,21 @@ var add_knowledge_base = (0, import_plugin.tool)({
|
|
|
10781
10875
|
} catch (error) {
|
|
10782
10876
|
return `Error: Cannot access directory: ${normalizedPath} - ${error instanceof Error ? error.message : String(error)}`;
|
|
10783
10877
|
}
|
|
10784
|
-
const config = loadEditableConfig(
|
|
10878
|
+
const config = loadEditableConfig(projectRoot);
|
|
10785
10879
|
const knowledgeBases = ensureStringArray(config.knowledgeBases);
|
|
10786
|
-
const alreadyExists = hasMatchingKnowledgeBasePath(knowledgeBases, normalizedPath,
|
|
10880
|
+
const alreadyExists = hasMatchingKnowledgeBasePath(knowledgeBases, normalizedPath, projectRoot);
|
|
10787
10881
|
if (alreadyExists) {
|
|
10788
10882
|
return `Knowledge base already configured: ${normalizedPath}`;
|
|
10789
10883
|
}
|
|
10790
10884
|
knowledgeBases.push(normalizedPath);
|
|
10791
10885
|
config.knowledgeBases = knowledgeBases;
|
|
10792
|
-
saveConfig(
|
|
10793
|
-
|
|
10886
|
+
saveConfig(projectRoot, config);
|
|
10887
|
+
refreshIndexerForDirectory(projectRoot);
|
|
10794
10888
|
let result = `${normalizedPath}
|
|
10795
10889
|
`;
|
|
10796
10890
|
result += `Total knowledge bases: ${knowledgeBases.length}
|
|
10797
10891
|
`;
|
|
10798
|
-
result += `Config saved to: ${getConfigPath(
|
|
10892
|
+
result += `Config saved to: ${getConfigPath(projectRoot)}
|
|
10799
10893
|
`;
|
|
10800
10894
|
result += `
|
|
10801
10895
|
Run /index to rebuild the index with the new knowledge base.`;
|
|
@@ -10805,8 +10899,9 @@ Run /index to rebuild the index with the new knowledge base.`;
|
|
|
10805
10899
|
var list_knowledge_bases = (0, import_plugin.tool)({
|
|
10806
10900
|
description: "List all configured knowledge base folders that are indexed alongside the main project.",
|
|
10807
10901
|
args: {},
|
|
10808
|
-
async execute() {
|
|
10809
|
-
const
|
|
10902
|
+
async execute(_args, context) {
|
|
10903
|
+
const projectRoot = context?.worktree || defaultProjectRoot;
|
|
10904
|
+
const config = loadRuntimeConfig(projectRoot);
|
|
10810
10905
|
const knowledgeBases = ensureStringArray(config.knowledgeBases);
|
|
10811
10906
|
if (knowledgeBases.length === 0) {
|
|
10812
10907
|
return "No knowledge bases configured. Use add_knowledge_base to add folders.";
|
|
@@ -10816,7 +10911,7 @@ var list_knowledge_bases = (0, import_plugin.tool)({
|
|
|
10816
10911
|
`;
|
|
10817
10912
|
for (let i = 0; i < knowledgeBases.length; i++) {
|
|
10818
10913
|
const kb = knowledgeBases[i];
|
|
10819
|
-
const resolvedPath = resolveKnowledgeBasePath(kb,
|
|
10914
|
+
const resolvedPath = resolveKnowledgeBasePath(kb, projectRoot);
|
|
10820
10915
|
const exists = (0, import_fs9.existsSync)(resolvedPath);
|
|
10821
10916
|
result += `[${i + 1}] ${kb}
|
|
10822
10917
|
`;
|
|
@@ -10834,7 +10929,7 @@ var list_knowledge_bases = (0, import_plugin.tool)({
|
|
|
10834
10929
|
}
|
|
10835
10930
|
result += "\n";
|
|
10836
10931
|
}
|
|
10837
|
-
result += `Config file: ${getConfigPath(
|
|
10932
|
+
result += `Config file: ${getConfigPath(projectRoot)}`;
|
|
10838
10933
|
return result;
|
|
10839
10934
|
}
|
|
10840
10935
|
});
|
|
@@ -10843,14 +10938,15 @@ var remove_knowledge_base = (0, import_plugin.tool)({
|
|
|
10843
10938
|
args: {
|
|
10844
10939
|
path: z.string().describe("Path of the knowledge base to remove (must match the configured path exactly)")
|
|
10845
10940
|
},
|
|
10846
|
-
async execute(args) {
|
|
10941
|
+
async execute(args, context) {
|
|
10942
|
+
const projectRoot = context?.worktree || defaultProjectRoot;
|
|
10847
10943
|
const inputPath = args.path.trim();
|
|
10848
|
-
const config = loadEditableConfig(
|
|
10944
|
+
const config = loadEditableConfig(projectRoot);
|
|
10849
10945
|
const knowledgeBases = ensureStringArray(config.knowledgeBases);
|
|
10850
10946
|
if (knowledgeBases.length === 0) {
|
|
10851
10947
|
return "No knowledge bases configured.";
|
|
10852
10948
|
}
|
|
10853
|
-
const index = findKnowledgeBasePathIndex(knowledgeBases, inputPath,
|
|
10949
|
+
const index = findKnowledgeBasePathIndex(knowledgeBases, inputPath, projectRoot);
|
|
10854
10950
|
if (index === -1) {
|
|
10855
10951
|
let result2 = `Knowledge base not found: ${inputPath}
|
|
10856
10952
|
|
|
@@ -10865,14 +10961,14 @@ var remove_knowledge_base = (0, import_plugin.tool)({
|
|
|
10865
10961
|
}
|
|
10866
10962
|
const removed = knowledgeBases.splice(index, 1)[0];
|
|
10867
10963
|
config.knowledgeBases = knowledgeBases;
|
|
10868
|
-
saveConfig(
|
|
10869
|
-
|
|
10964
|
+
saveConfig(projectRoot, config);
|
|
10965
|
+
refreshIndexerForDirectory(projectRoot);
|
|
10870
10966
|
let result = `Removed: ${removed}
|
|
10871
10967
|
|
|
10872
10968
|
`;
|
|
10873
10969
|
result += `Remaining knowledge bases: ${knowledgeBases.length}
|
|
10874
10970
|
`;
|
|
10875
|
-
result += `Config saved to: ${getConfigPath(
|
|
10971
|
+
result += `Config saved to: ${getConfigPath(projectRoot)}
|
|
10876
10972
|
`;
|
|
10877
10973
|
result += `
|
|
10878
10974
|
Run /index to rebuild the index without the removed knowledge base.`;
|
|
@@ -11159,6 +11255,8 @@ var RoutingHintController = class {
|
|
|
11159
11255
|
this.getStatus = getStatus;
|
|
11160
11256
|
this.maxSessions = maxSessions;
|
|
11161
11257
|
}
|
|
11258
|
+
getStatus;
|
|
11259
|
+
maxSessions;
|
|
11162
11260
|
sessionState = /* @__PURE__ */ new Map();
|
|
11163
11261
|
observeUserMessage(sessionID, parts) {
|
|
11164
11262
|
const assessment = assessRoutingIntent(extractUserText(parts));
|
|
@@ -11216,10 +11314,16 @@ var RoutingHintController = class {
|
|
|
11216
11314
|
|
|
11217
11315
|
// src/index.ts
|
|
11218
11316
|
var import_meta2 = {};
|
|
11219
|
-
var
|
|
11220
|
-
function replaceActiveWatcher(nextWatcher) {
|
|
11221
|
-
|
|
11222
|
-
|
|
11317
|
+
var activeWatchers = /* @__PURE__ */ new Map();
|
|
11318
|
+
function replaceActiveWatcher(projectRoot, nextWatcher) {
|
|
11319
|
+
const existing = activeWatchers.get(projectRoot);
|
|
11320
|
+
if (existing) {
|
|
11321
|
+
existing.stop();
|
|
11322
|
+
activeWatchers.delete(projectRoot);
|
|
11323
|
+
}
|
|
11324
|
+
if (nextWatcher) {
|
|
11325
|
+
activeWatchers.set(projectRoot, nextWatcher);
|
|
11326
|
+
}
|
|
11223
11327
|
}
|
|
11224
11328
|
function getCommandsDir() {
|
|
11225
11329
|
let currentDir = process.cwd();
|
|
@@ -11228,21 +11332,37 @@ function getCommandsDir() {
|
|
|
11228
11332
|
}
|
|
11229
11333
|
return path17.join(currentDir, "..", "commands");
|
|
11230
11334
|
}
|
|
11231
|
-
|
|
11335
|
+
function appendRoutingHints(output, hints, preferredRole) {
|
|
11336
|
+
const preferredBucket = preferredRole === "developer" ? output.developer : output.system;
|
|
11337
|
+
if (Array.isArray(preferredBucket)) {
|
|
11338
|
+
preferredBucket.push(...hints);
|
|
11339
|
+
return;
|
|
11340
|
+
}
|
|
11341
|
+
if (Array.isArray(output.system)) {
|
|
11342
|
+
output.system.push(...hints);
|
|
11343
|
+
}
|
|
11344
|
+
}
|
|
11345
|
+
var plugin = async ({ directory, worktree }) => {
|
|
11232
11346
|
try {
|
|
11233
|
-
const projectRoot = directory;
|
|
11347
|
+
const projectRoot = worktree || directory;
|
|
11234
11348
|
const rawConfig = loadMergedConfig(projectRoot);
|
|
11235
11349
|
const config = parseConfig(rawConfig);
|
|
11236
11350
|
initializeTools(projectRoot, config);
|
|
11237
|
-
const
|
|
11238
|
-
const routingHints = config.search.routingHints ? new RoutingHintController(() =>
|
|
11239
|
-
const
|
|
11240
|
-
|
|
11351
|
+
const getProjectIndexer = () => getIndexerForProject(projectRoot);
|
|
11352
|
+
const routingHints = config.search.routingHints ? new RoutingHintController(() => getProjectIndexer().getStatus()) : null;
|
|
11353
|
+
const isHomeDir = path17.resolve(projectRoot) === path17.resolve(os6.homedir());
|
|
11354
|
+
const isValidProject = !isHomeDir && (!config.indexing.requireProjectMarker || hasProjectMarker(projectRoot));
|
|
11355
|
+
if (isHomeDir) {
|
|
11356
|
+
console.warn(
|
|
11357
|
+
`[codebase-index] Refusing to watch or index home directory "${projectRoot}". Open a specific project directory instead.`
|
|
11358
|
+
);
|
|
11359
|
+
} else if (!isValidProject) {
|
|
11241
11360
|
console.warn(
|
|
11242
11361
|
`[codebase-index] Skipping file watching and auto-indexing: no project marker found in "${projectRoot}". Set "indexing.requireProjectMarker": false in config to override.`
|
|
11243
11362
|
);
|
|
11244
11363
|
}
|
|
11245
11364
|
if (config.indexing.autoIndex && isValidProject) {
|
|
11365
|
+
const indexer = getProjectIndexer();
|
|
11246
11366
|
indexer.initialize().then(() => {
|
|
11247
11367
|
indexer.index().catch(() => {
|
|
11248
11368
|
});
|
|
@@ -11250,9 +11370,9 @@ var plugin = async ({ directory }) => {
|
|
|
11250
11370
|
});
|
|
11251
11371
|
}
|
|
11252
11372
|
if (config.indexing.watchFiles && isValidProject) {
|
|
11253
|
-
replaceActiveWatcher(createWatcherWithIndexer(
|
|
11373
|
+
replaceActiveWatcher(projectRoot, createWatcherWithIndexer(getProjectIndexer, projectRoot, config));
|
|
11254
11374
|
} else {
|
|
11255
|
-
replaceActiveWatcher(null);
|
|
11375
|
+
replaceActiveWatcher(projectRoot, null);
|
|
11256
11376
|
}
|
|
11257
11377
|
return {
|
|
11258
11378
|
tool: {
|
|
@@ -11265,6 +11385,7 @@ var plugin = async ({ directory }) => {
|
|
|
11265
11385
|
index_logs,
|
|
11266
11386
|
find_similar,
|
|
11267
11387
|
call_graph,
|
|
11388
|
+
call_graph_path,
|
|
11268
11389
|
implementation_lookup,
|
|
11269
11390
|
add_knowledge_base,
|
|
11270
11391
|
list_knowledge_bases,
|
|
@@ -11274,8 +11395,18 @@ var plugin = async ({ directory }) => {
|
|
|
11274
11395
|
routingHints?.observeUserMessage(input.sessionID, output.parts);
|
|
11275
11396
|
},
|
|
11276
11397
|
async "experimental.chat.system.transform"(input, output) {
|
|
11398
|
+
if (config.search.routingHintRole !== "system") {
|
|
11399
|
+
return;
|
|
11400
|
+
}
|
|
11277
11401
|
const hints = await routingHints?.getSystemHints(input.sessionID) ?? [];
|
|
11278
|
-
output
|
|
11402
|
+
appendRoutingHints(output, hints, "system");
|
|
11403
|
+
},
|
|
11404
|
+
async "experimental.chat.developer.transform"(input, output) {
|
|
11405
|
+
if (config.search.routingHintRole !== "developer") {
|
|
11406
|
+
return;
|
|
11407
|
+
}
|
|
11408
|
+
const hints = await routingHints?.getSystemHints(input.sessionID) ?? [];
|
|
11409
|
+
appendRoutingHints(output, hints, "developer");
|
|
11279
11410
|
},
|
|
11280
11411
|
async "tool.execute.after"(input) {
|
|
11281
11412
|
routingHints?.markToolUsed(input.sessionID, input.tool);
|
|
@@ -11289,8 +11420,8 @@ var plugin = async ({ directory }) => {
|
|
|
11289
11420
|
}
|
|
11290
11421
|
}
|
|
11291
11422
|
};
|
|
11292
|
-
} catch
|
|
11293
|
-
console.error("[codebase-index] Failed to initialize plugin
|
|
11423
|
+
} catch {
|
|
11424
|
+
console.error("[codebase-index] Failed to initialize plugin (check config and network)");
|
|
11294
11425
|
return {
|
|
11295
11426
|
tool: void 0,
|
|
11296
11427
|
async config() {
|