opencode-codebase-index 0.9.0 → 0.10.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 +6 -5
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +6 -5
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +171 -90
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +171 -90
- 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.win32-x64-msvc.node +0 -0
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -657,6 +657,7 @@ __export(index_exports, {
|
|
|
657
657
|
default: () => index_default
|
|
658
658
|
});
|
|
659
659
|
module.exports = __toCommonJS(index_exports);
|
|
660
|
+
var os6 = __toESM(require("os"), 1);
|
|
660
661
|
var path17 = __toESM(require("path"), 1);
|
|
661
662
|
var import_url2 = require("url");
|
|
662
663
|
|
|
@@ -803,7 +804,8 @@ function getDefaultSearchConfig() {
|
|
|
803
804
|
rrfK: 60,
|
|
804
805
|
rerankTopN: 20,
|
|
805
806
|
contextLines: 0,
|
|
806
|
-
routingHints: true
|
|
807
|
+
routingHints: true,
|
|
808
|
+
routingHintRole: "system"
|
|
807
809
|
};
|
|
808
810
|
}
|
|
809
811
|
function getDefaultRerankerBaseUrl(provider) {
|
|
@@ -924,7 +926,8 @@ function parseConfig(raw) {
|
|
|
924
926
|
rrfK: typeof rawSearch.rrfK === "number" ? Math.max(1, Math.floor(rawSearch.rrfK)) : defaultSearch.rrfK,
|
|
925
927
|
rerankTopN: typeof rawSearch.rerankTopN === "number" ? Math.min(200, Math.max(0, Math.floor(rawSearch.rerankTopN))) : defaultSearch.rerankTopN,
|
|
926
928
|
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
|
|
929
|
+
routingHints: typeof rawSearch.routingHints === "boolean" ? rawSearch.routingHints : defaultSearch.routingHints,
|
|
930
|
+
routingHintRole: rawSearch.routingHintRole === "developer" || rawSearch.routingHintRole === "system" ? rawSearch.routingHintRole : defaultSearch.routingHintRole
|
|
928
931
|
};
|
|
929
932
|
const rawDebug = input.debug && typeof input.debug === "object" ? input.debug : {};
|
|
930
933
|
const debug = {
|
|
@@ -1246,6 +1249,32 @@ function hasFilteredPathSegment(relativePath, separator = path4.sep) {
|
|
|
1246
1249
|
(part) => isHiddenPathSegment(part) || isBuildPathSegment(part)
|
|
1247
1250
|
);
|
|
1248
1251
|
}
|
|
1252
|
+
var RESTRICTED_DIRECTORIES = /* @__PURE__ */ new Set([
|
|
1253
|
+
// macOS
|
|
1254
|
+
"library",
|
|
1255
|
+
"applications",
|
|
1256
|
+
"system",
|
|
1257
|
+
"volumes",
|
|
1258
|
+
"private",
|
|
1259
|
+
"cores",
|
|
1260
|
+
// Linux
|
|
1261
|
+
"proc",
|
|
1262
|
+
"sys",
|
|
1263
|
+
"dev",
|
|
1264
|
+
"run",
|
|
1265
|
+
"snap",
|
|
1266
|
+
// Windows
|
|
1267
|
+
"windows",
|
|
1268
|
+
"programdata",
|
|
1269
|
+
"program files",
|
|
1270
|
+
"program files (x86)",
|
|
1271
|
+
"$recycle.bin"
|
|
1272
|
+
]);
|
|
1273
|
+
function isRestrictedDirectory(relativePath, separator = path4.sep) {
|
|
1274
|
+
const firstSegment = relativePath.split(separator)[0];
|
|
1275
|
+
if (!firstSegment) return false;
|
|
1276
|
+
return RESTRICTED_DIRECTORIES.has(firstSegment.toLowerCase());
|
|
1277
|
+
}
|
|
1249
1278
|
|
|
1250
1279
|
// src/config/rebase.ts
|
|
1251
1280
|
function isWithinRoot(rootDir, targetPath) {
|
|
@@ -2305,7 +2334,7 @@ var NodeFsHandler = class {
|
|
|
2305
2334
|
this._addToNodeFs(path18, initialAdd, wh, depth + 1);
|
|
2306
2335
|
}
|
|
2307
2336
|
}).on(EV.ERROR, this._boundHandleError);
|
|
2308
|
-
return new Promise((
|
|
2337
|
+
return new Promise((resolve12, reject) => {
|
|
2309
2338
|
if (!stream)
|
|
2310
2339
|
return reject();
|
|
2311
2340
|
stream.once(STR_END, () => {
|
|
@@ -2314,7 +2343,7 @@ var NodeFsHandler = class {
|
|
|
2314
2343
|
return;
|
|
2315
2344
|
}
|
|
2316
2345
|
const wasThrottled = throttler ? throttler.clear() : false;
|
|
2317
|
-
|
|
2346
|
+
resolve12(void 0);
|
|
2318
2347
|
previous.getChildren().filter((item) => {
|
|
2319
2348
|
return item !== directory && !current.has(item);
|
|
2320
2349
|
}).forEach((item) => {
|
|
@@ -3414,6 +3443,9 @@ var FileWatcher = class {
|
|
|
3414
3443
|
if (hasFilteredPathSegment(relativePath, path8.sep)) {
|
|
3415
3444
|
return true;
|
|
3416
3445
|
}
|
|
3446
|
+
if (isRestrictedDirectory(relativePath, path8.sep)) {
|
|
3447
|
+
return true;
|
|
3448
|
+
}
|
|
3417
3449
|
if (ignoreFilter.ignores(relativePath)) {
|
|
3418
3450
|
return true;
|
|
3419
3451
|
}
|
|
@@ -3426,6 +3458,13 @@ var FileWatcher = class {
|
|
|
3426
3458
|
pollInterval: 100
|
|
3427
3459
|
}
|
|
3428
3460
|
});
|
|
3461
|
+
this.watcher.on("error", (error) => {
|
|
3462
|
+
const err = error instanceof Error ? error : null;
|
|
3463
|
+
if (err?.code === "EPERM" || err?.code === "EACCES") {
|
|
3464
|
+
return;
|
|
3465
|
+
}
|
|
3466
|
+
console.error("[codebase-index] Watcher error:", err?.message ?? error);
|
|
3467
|
+
});
|
|
3429
3468
|
this.watcher.on("add", (filePath) => this.handleChange("add", filePath));
|
|
3430
3469
|
this.watcher.on("change", (filePath) => this.handleChange("change", filePath));
|
|
3431
3470
|
this.watcher.on("unlink", (filePath) => this.handleChange("unlink", filePath));
|
|
@@ -3560,7 +3599,7 @@ var GitHeadWatcher = class {
|
|
|
3560
3599
|
};
|
|
3561
3600
|
|
|
3562
3601
|
// src/watcher/index.ts
|
|
3563
|
-
function createWatcherWithIndexer(
|
|
3602
|
+
function createWatcherWithIndexer(getIndexer, projectRoot, config) {
|
|
3564
3603
|
const fileWatcher = new FileWatcher(projectRoot, config);
|
|
3565
3604
|
fileWatcher.start(async (changes) => {
|
|
3566
3605
|
const hasAddOrChange = changes.some(
|
|
@@ -3568,7 +3607,7 @@ function createWatcherWithIndexer(getIndexer2, projectRoot, config) {
|
|
|
3568
3607
|
);
|
|
3569
3608
|
const hasDelete = changes.some((c) => c.type === "unlink");
|
|
3570
3609
|
if (hasAddOrChange || hasDelete) {
|
|
3571
|
-
await
|
|
3610
|
+
await getIndexer().index();
|
|
3572
3611
|
}
|
|
3573
3612
|
});
|
|
3574
3613
|
let gitWatcher = null;
|
|
@@ -3576,7 +3615,7 @@ function createWatcherWithIndexer(getIndexer2, projectRoot, config) {
|
|
|
3576
3615
|
gitWatcher = new GitHeadWatcher(projectRoot);
|
|
3577
3616
|
gitWatcher.start(async (oldBranch, newBranch) => {
|
|
3578
3617
|
console.log(`Branch changed: ${oldBranch ?? "(none)"} -> ${newBranch}`);
|
|
3579
|
-
await
|
|
3618
|
+
await getIndexer().index();
|
|
3580
3619
|
});
|
|
3581
3620
|
}
|
|
3582
3621
|
return {
|
|
@@ -3619,7 +3658,7 @@ function pTimeout(promise, options) {
|
|
|
3619
3658
|
} = options;
|
|
3620
3659
|
let timer;
|
|
3621
3660
|
let abortHandler;
|
|
3622
|
-
const wrappedPromise = new Promise((
|
|
3661
|
+
const wrappedPromise = new Promise((resolve12, reject) => {
|
|
3623
3662
|
if (typeof milliseconds !== "number" || Math.sign(milliseconds) !== 1) {
|
|
3624
3663
|
throw new TypeError(`Expected \`milliseconds\` to be a positive number, got \`${milliseconds}\``);
|
|
3625
3664
|
}
|
|
@@ -3633,7 +3672,7 @@ function pTimeout(promise, options) {
|
|
|
3633
3672
|
};
|
|
3634
3673
|
signal.addEventListener("abort", abortHandler, { once: true });
|
|
3635
3674
|
}
|
|
3636
|
-
promise.then(
|
|
3675
|
+
promise.then(resolve12, reject);
|
|
3637
3676
|
if (milliseconds === Number.POSITIVE_INFINITY) {
|
|
3638
3677
|
return;
|
|
3639
3678
|
}
|
|
@@ -3641,7 +3680,7 @@ function pTimeout(promise, options) {
|
|
|
3641
3680
|
timer = customTimers.setTimeout.call(void 0, () => {
|
|
3642
3681
|
if (fallback) {
|
|
3643
3682
|
try {
|
|
3644
|
-
|
|
3683
|
+
resolve12(fallback());
|
|
3645
3684
|
} catch (error) {
|
|
3646
3685
|
reject(error);
|
|
3647
3686
|
}
|
|
@@ -3651,7 +3690,7 @@ function pTimeout(promise, options) {
|
|
|
3651
3690
|
promise.cancel();
|
|
3652
3691
|
}
|
|
3653
3692
|
if (message === false) {
|
|
3654
|
-
|
|
3693
|
+
resolve12();
|
|
3655
3694
|
} else if (message instanceof Error) {
|
|
3656
3695
|
reject(message);
|
|
3657
3696
|
} else {
|
|
@@ -4053,7 +4092,7 @@ var PQueue = class extends import_index.default {
|
|
|
4053
4092
|
// Assign unique ID if not provided
|
|
4054
4093
|
id: options.id ?? (this.#idAssigner++).toString()
|
|
4055
4094
|
};
|
|
4056
|
-
return new Promise((
|
|
4095
|
+
return new Promise((resolve12, reject) => {
|
|
4057
4096
|
const taskSymbol = /* @__PURE__ */ Symbol(`task-${options.id}`);
|
|
4058
4097
|
let cleanupQueueAbortHandler = () => void 0;
|
|
4059
4098
|
const run = async () => {
|
|
@@ -4093,7 +4132,7 @@ var PQueue = class extends import_index.default {
|
|
|
4093
4132
|
})]);
|
|
4094
4133
|
}
|
|
4095
4134
|
const result = await operation;
|
|
4096
|
-
|
|
4135
|
+
resolve12(result);
|
|
4097
4136
|
this.emit("completed", result);
|
|
4098
4137
|
} catch (error) {
|
|
4099
4138
|
reject(error);
|
|
@@ -4281,13 +4320,13 @@ var PQueue = class extends import_index.default {
|
|
|
4281
4320
|
});
|
|
4282
4321
|
}
|
|
4283
4322
|
async #onEvent(event, filter) {
|
|
4284
|
-
return new Promise((
|
|
4323
|
+
return new Promise((resolve12) => {
|
|
4285
4324
|
const listener = () => {
|
|
4286
4325
|
if (filter && !filter()) {
|
|
4287
4326
|
return;
|
|
4288
4327
|
}
|
|
4289
4328
|
this.off(event, listener);
|
|
4290
|
-
|
|
4329
|
+
resolve12();
|
|
4291
4330
|
};
|
|
4292
4331
|
this.on(event, listener);
|
|
4293
4332
|
});
|
|
@@ -4573,7 +4612,7 @@ async function onAttemptFailure({ error, attemptNumber, retriesConsumed, startTi
|
|
|
4573
4612
|
const finalDelay = Math.min(delayTime, remainingTime);
|
|
4574
4613
|
options.signal?.throwIfAborted();
|
|
4575
4614
|
if (finalDelay > 0) {
|
|
4576
|
-
await new Promise((
|
|
4615
|
+
await new Promise((resolve12, reject) => {
|
|
4577
4616
|
const onAbort = () => {
|
|
4578
4617
|
clearTimeout(timeoutToken);
|
|
4579
4618
|
options.signal?.removeEventListener("abort", onAbort);
|
|
@@ -4581,7 +4620,7 @@ async function onAttemptFailure({ error, attemptNumber, retriesConsumed, startTi
|
|
|
4581
4620
|
};
|
|
4582
4621
|
const timeoutToken = setTimeout(() => {
|
|
4583
4622
|
options.signal?.removeEventListener("abort", onAbort);
|
|
4584
|
-
|
|
4623
|
+
resolve12();
|
|
4585
4624
|
}, finalDelay);
|
|
4586
4625
|
if (options.unref) {
|
|
4587
4626
|
timeoutToken.unref?.();
|
|
@@ -9161,7 +9200,7 @@ var Indexer = class {
|
|
|
9161
9200
|
for (const requestBatch of requestBatches) {
|
|
9162
9201
|
queue.add(async () => {
|
|
9163
9202
|
if (rateLimitBackoffMs > 0) {
|
|
9164
|
-
await new Promise((
|
|
9203
|
+
await new Promise((resolve12) => setTimeout(resolve12, rateLimitBackoffMs));
|
|
9165
9204
|
}
|
|
9166
9205
|
try {
|
|
9167
9206
|
const result = await pRetry(
|
|
@@ -10485,39 +10524,45 @@ function ensureStringArray(value) {
|
|
|
10485
10524
|
return Array.isArray(value) ? value : [];
|
|
10486
10525
|
}
|
|
10487
10526
|
var z = import_plugin.tool.schema;
|
|
10488
|
-
var
|
|
10489
|
-
var
|
|
10527
|
+
var indexerMap = /* @__PURE__ */ new Map();
|
|
10528
|
+
var defaultProjectRoot = "";
|
|
10490
10529
|
function initializeTools(projectRoot, config) {
|
|
10491
|
-
|
|
10492
|
-
|
|
10530
|
+
defaultProjectRoot = projectRoot;
|
|
10531
|
+
const indexer = new Indexer(projectRoot, config);
|
|
10532
|
+
indexerMap.set(projectRoot, indexer);
|
|
10493
10533
|
}
|
|
10494
|
-
function
|
|
10495
|
-
|
|
10496
|
-
}
|
|
10497
|
-
function refreshIndexerFromConfig() {
|
|
10498
|
-
if (!sharedProjectRoot) {
|
|
10534
|
+
function refreshIndexerForDirectory(projectRoot) {
|
|
10535
|
+
if (!projectRoot) {
|
|
10499
10536
|
throw new Error("Codebase index tools not initialized. Plugin may not be loaded correctly.");
|
|
10500
10537
|
}
|
|
10501
|
-
|
|
10538
|
+
const indexer = new Indexer(projectRoot, parseConfig(loadRuntimeConfig(projectRoot)));
|
|
10539
|
+
indexerMap.set(projectRoot, indexer);
|
|
10502
10540
|
}
|
|
10503
|
-
function shouldForceLocalizeProjectIndex() {
|
|
10504
|
-
const currentConfig = parseConfig(loadRuntimeConfig(
|
|
10541
|
+
function shouldForceLocalizeProjectIndex(projectRoot) {
|
|
10542
|
+
const currentConfig = parseConfig(loadRuntimeConfig(projectRoot));
|
|
10505
10543
|
if (currentConfig.scope !== "project") {
|
|
10506
10544
|
return false;
|
|
10507
10545
|
}
|
|
10508
|
-
const localIndexPath = path15.join(
|
|
10509
|
-
const mainRepoRoot = resolveWorktreeMainRepoRoot(
|
|
10546
|
+
const localIndexPath = path15.join(projectRoot, ".opencode", "index");
|
|
10547
|
+
const mainRepoRoot = resolveWorktreeMainRepoRoot(projectRoot);
|
|
10510
10548
|
if (!mainRepoRoot) {
|
|
10511
10549
|
return false;
|
|
10512
10550
|
}
|
|
10513
10551
|
const inheritedIndexPath = path15.join(mainRepoRoot, ".opencode", "index");
|
|
10514
10552
|
return !(0, import_fs9.existsSync)(localIndexPath) && (0, import_fs9.existsSync)(inheritedIndexPath);
|
|
10515
10553
|
}
|
|
10516
|
-
function
|
|
10517
|
-
|
|
10554
|
+
function getIndexerForProject(directory) {
|
|
10555
|
+
const projectRoot = directory || defaultProjectRoot;
|
|
10556
|
+
if (!projectRoot) {
|
|
10518
10557
|
throw new Error("Codebase index tools not initialized. Plugin may not be loaded correctly.");
|
|
10519
10558
|
}
|
|
10520
|
-
|
|
10559
|
+
let indexer = indexerMap.get(projectRoot);
|
|
10560
|
+
if (!indexer) {
|
|
10561
|
+
const config = parseConfig(loadRuntimeConfig(projectRoot));
|
|
10562
|
+
indexer = new Indexer(projectRoot, config);
|
|
10563
|
+
indexerMap.set(projectRoot, indexer);
|
|
10564
|
+
}
|
|
10565
|
+
return indexer;
|
|
10521
10566
|
}
|
|
10522
10567
|
var codebase_peek = (0, import_plugin.tool)({
|
|
10523
10568
|
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 +10573,8 @@ var codebase_peek = (0, import_plugin.tool)({
|
|
|
10528
10573
|
directory: z.string().optional().describe("Filter by directory path (e.g., 'src/utils', 'lib')"),
|
|
10529
10574
|
chunkType: z.enum(["function", "class", "method", "interface", "type", "enum", "struct", "impl", "trait", "module", "other"]).optional().describe("Filter by code chunk type")
|
|
10530
10575
|
},
|
|
10531
|
-
async execute(args) {
|
|
10532
|
-
const indexer =
|
|
10576
|
+
async execute(args, context) {
|
|
10577
|
+
const indexer = getIndexerForProject(context?.worktree);
|
|
10533
10578
|
const results = await indexer.search(args.query, args.limit ?? 10, {
|
|
10534
10579
|
fileType: args.fileType,
|
|
10535
10580
|
directory: args.directory,
|
|
@@ -10547,16 +10592,17 @@ var index_codebase = (0, import_plugin.tool)({
|
|
|
10547
10592
|
verbose: z.boolean().optional().default(false).describe("Show detailed info about skipped files and parsing failures")
|
|
10548
10593
|
},
|
|
10549
10594
|
async execute(args, context) {
|
|
10550
|
-
|
|
10595
|
+
const projectRoot = context?.worktree || defaultProjectRoot;
|
|
10596
|
+
let indexer = getIndexerForProject(projectRoot);
|
|
10551
10597
|
if (args.estimateOnly) {
|
|
10552
10598
|
const estimate = await indexer.estimateCost();
|
|
10553
10599
|
return formatCostEstimate(estimate);
|
|
10554
10600
|
}
|
|
10555
10601
|
if (args.force) {
|
|
10556
|
-
if (shouldForceLocalizeProjectIndex()) {
|
|
10557
|
-
materializeLocalProjectConfig(
|
|
10558
|
-
|
|
10559
|
-
indexer =
|
|
10602
|
+
if (shouldForceLocalizeProjectIndex(projectRoot)) {
|
|
10603
|
+
materializeLocalProjectConfig(projectRoot, loadProjectConfigLayer(projectRoot));
|
|
10604
|
+
refreshIndexerForDirectory(projectRoot);
|
|
10605
|
+
indexer = getIndexerForProject(projectRoot);
|
|
10560
10606
|
}
|
|
10561
10607
|
await indexer.clearIndex();
|
|
10562
10608
|
}
|
|
@@ -10579,8 +10625,8 @@ var index_codebase = (0, import_plugin.tool)({
|
|
|
10579
10625
|
var index_status = (0, import_plugin.tool)({
|
|
10580
10626
|
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
10627
|
args: {},
|
|
10582
|
-
async execute() {
|
|
10583
|
-
const indexer =
|
|
10628
|
+
async execute(_args, context) {
|
|
10629
|
+
const indexer = getIndexerForProject(context?.worktree);
|
|
10584
10630
|
const status = await indexer.getStatus();
|
|
10585
10631
|
return formatStatus(status);
|
|
10586
10632
|
}
|
|
@@ -10588,8 +10634,8 @@ var index_status = (0, import_plugin.tool)({
|
|
|
10588
10634
|
var index_health_check = (0, import_plugin.tool)({
|
|
10589
10635
|
description: "Check index health and remove stale entries from deleted files. Run this to clean up the index after files have been deleted.",
|
|
10590
10636
|
args: {},
|
|
10591
|
-
async execute() {
|
|
10592
|
-
const indexer =
|
|
10637
|
+
async execute(_args, context) {
|
|
10638
|
+
const indexer = getIndexerForProject(context?.worktree);
|
|
10593
10639
|
const result = await indexer.healthCheck();
|
|
10594
10640
|
return formatHealthCheck(result);
|
|
10595
10641
|
}
|
|
@@ -10597,8 +10643,8 @@ var index_health_check = (0, import_plugin.tool)({
|
|
|
10597
10643
|
var index_metrics = (0, import_plugin.tool)({
|
|
10598
10644
|
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
10645
|
args: {},
|
|
10600
|
-
async execute() {
|
|
10601
|
-
const indexer =
|
|
10646
|
+
async execute(_args, context) {
|
|
10647
|
+
const indexer = getIndexerForProject(context?.worktree);
|
|
10602
10648
|
const logger = indexer.getLogger();
|
|
10603
10649
|
if (!logger.isEnabled()) {
|
|
10604
10650
|
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 +10662,8 @@ var index_logs = (0, import_plugin.tool)({
|
|
|
10616
10662
|
category: z.enum(["search", "embedding", "cache", "gc", "branch", "general"]).optional().describe("Filter by log category"),
|
|
10617
10663
|
level: z.enum(["error", "warn", "info", "debug"]).optional().describe("Filter by minimum log level")
|
|
10618
10664
|
},
|
|
10619
|
-
async execute(args) {
|
|
10620
|
-
const indexer =
|
|
10665
|
+
async execute(args, context) {
|
|
10666
|
+
const indexer = getIndexerForProject(context?.worktree);
|
|
10621
10667
|
const logger = indexer.getLogger();
|
|
10622
10668
|
if (!logger.isEnabled()) {
|
|
10623
10669
|
return 'Debug mode is disabled. Enable it in your config:\n\n```json\n{\n "debug": {\n "enabled": true\n }\n}\n```';
|
|
@@ -10643,8 +10689,8 @@ var find_similar = (0, import_plugin.tool)({
|
|
|
10643
10689
|
chunkType: z.enum(["function", "class", "method", "interface", "type", "enum", "struct", "impl", "trait", "module", "other"]).optional().describe("Filter by code chunk type"),
|
|
10644
10690
|
excludeFile: z.string().optional().describe("Exclude results from this file path (useful when searching for duplicates of code from a specific file)")
|
|
10645
10691
|
},
|
|
10646
|
-
async execute(args) {
|
|
10647
|
-
const indexer =
|
|
10692
|
+
async execute(args, context) {
|
|
10693
|
+
const indexer = getIndexerForProject(context?.worktree);
|
|
10648
10694
|
const results = await indexer.findSimilar(args.code, args.limit, {
|
|
10649
10695
|
fileType: args.fileType,
|
|
10650
10696
|
directory: args.directory,
|
|
@@ -10667,8 +10713,8 @@ var codebase_search = (0, import_plugin.tool)({
|
|
|
10667
10713
|
chunkType: z.enum(["function", "class", "method", "interface", "type", "enum", "struct", "impl", "trait", "module", "other"]).optional().describe("Filter by code chunk type"),
|
|
10668
10714
|
contextLines: z.number().optional().describe("Number of extra lines to include before/after each match (default: 0)")
|
|
10669
10715
|
},
|
|
10670
|
-
async execute(args) {
|
|
10671
|
-
const indexer =
|
|
10716
|
+
async execute(args, context) {
|
|
10717
|
+
const indexer = getIndexerForProject(context?.worktree);
|
|
10672
10718
|
const results = await indexer.search(args.query, args.limit ?? 5, {
|
|
10673
10719
|
fileType: args.fileType,
|
|
10674
10720
|
directory: args.directory,
|
|
@@ -10689,8 +10735,8 @@ var implementation_lookup = (0, import_plugin.tool)({
|
|
|
10689
10735
|
fileType: z.string().optional().describe("Filter by file extension (e.g., 'ts', 'py')"),
|
|
10690
10736
|
directory: z.string().optional().describe("Filter by directory path (e.g., 'src/utils')")
|
|
10691
10737
|
},
|
|
10692
|
-
async execute(args) {
|
|
10693
|
-
const indexer =
|
|
10738
|
+
async execute(args, context) {
|
|
10739
|
+
const indexer = getIndexerForProject(context?.worktree);
|
|
10694
10740
|
const results = await indexer.search(args.query, args.limit ?? 5, {
|
|
10695
10741
|
fileType: args.fileType,
|
|
10696
10742
|
directory: args.directory,
|
|
@@ -10706,8 +10752,8 @@ var call_graph = (0, import_plugin.tool)({
|
|
|
10706
10752
|
direction: z.enum(["callers", "callees"]).default("callers").describe("Direction: 'callers' finds who calls this function, 'callees' finds what this function calls"),
|
|
10707
10753
|
symbolId: z.string().optional().describe("Symbol ID (required for 'callees' direction, returned by previous call_graph queries)")
|
|
10708
10754
|
},
|
|
10709
|
-
async execute(args) {
|
|
10710
|
-
const indexer =
|
|
10755
|
+
async execute(args, context) {
|
|
10756
|
+
const indexer = getIndexerForProject(context?.worktree);
|
|
10711
10757
|
if (args.direction === "callees") {
|
|
10712
10758
|
if (!args.symbolId) {
|
|
10713
10759
|
return "Error: 'symbolId' is required when direction is 'callees'. First use direction='callers' to find the symbol ID.";
|
|
@@ -10736,10 +10782,11 @@ var add_knowledge_base = (0, import_plugin.tool)({
|
|
|
10736
10782
|
args: {
|
|
10737
10783
|
path: z.string().describe("Path to the folder to add as a knowledge base (absolute or relative to project root)")
|
|
10738
10784
|
},
|
|
10739
|
-
async execute(args) {
|
|
10785
|
+
async execute(args, context) {
|
|
10786
|
+
const projectRoot = context?.worktree || defaultProjectRoot;
|
|
10740
10787
|
const inputPath = args.path.trim();
|
|
10741
10788
|
const normalizedPath = path15.resolve(
|
|
10742
|
-
path15.isAbsolute(inputPath) ? inputPath : resolveKnowledgeBasePath(inputPath,
|
|
10789
|
+
path15.isAbsolute(inputPath) ? inputPath : resolveKnowledgeBasePath(inputPath, projectRoot)
|
|
10743
10790
|
);
|
|
10744
10791
|
if (!(0, import_fs9.existsSync)(normalizedPath)) {
|
|
10745
10792
|
return `Error: Directory does not exist: ${normalizedPath}`;
|
|
@@ -10781,21 +10828,21 @@ var add_knowledge_base = (0, import_plugin.tool)({
|
|
|
10781
10828
|
} catch (error) {
|
|
10782
10829
|
return `Error: Cannot access directory: ${normalizedPath} - ${error instanceof Error ? error.message : String(error)}`;
|
|
10783
10830
|
}
|
|
10784
|
-
const config = loadEditableConfig(
|
|
10831
|
+
const config = loadEditableConfig(projectRoot);
|
|
10785
10832
|
const knowledgeBases = ensureStringArray(config.knowledgeBases);
|
|
10786
|
-
const alreadyExists = hasMatchingKnowledgeBasePath(knowledgeBases, normalizedPath,
|
|
10833
|
+
const alreadyExists = hasMatchingKnowledgeBasePath(knowledgeBases, normalizedPath, projectRoot);
|
|
10787
10834
|
if (alreadyExists) {
|
|
10788
10835
|
return `Knowledge base already configured: ${normalizedPath}`;
|
|
10789
10836
|
}
|
|
10790
10837
|
knowledgeBases.push(normalizedPath);
|
|
10791
10838
|
config.knowledgeBases = knowledgeBases;
|
|
10792
|
-
saveConfig(
|
|
10793
|
-
|
|
10839
|
+
saveConfig(projectRoot, config);
|
|
10840
|
+
refreshIndexerForDirectory(projectRoot);
|
|
10794
10841
|
let result = `${normalizedPath}
|
|
10795
10842
|
`;
|
|
10796
10843
|
result += `Total knowledge bases: ${knowledgeBases.length}
|
|
10797
10844
|
`;
|
|
10798
|
-
result += `Config saved to: ${getConfigPath(
|
|
10845
|
+
result += `Config saved to: ${getConfigPath(projectRoot)}
|
|
10799
10846
|
`;
|
|
10800
10847
|
result += `
|
|
10801
10848
|
Run /index to rebuild the index with the new knowledge base.`;
|
|
@@ -10805,8 +10852,9 @@ Run /index to rebuild the index with the new knowledge base.`;
|
|
|
10805
10852
|
var list_knowledge_bases = (0, import_plugin.tool)({
|
|
10806
10853
|
description: "List all configured knowledge base folders that are indexed alongside the main project.",
|
|
10807
10854
|
args: {},
|
|
10808
|
-
async execute() {
|
|
10809
|
-
const
|
|
10855
|
+
async execute(_args, context) {
|
|
10856
|
+
const projectRoot = context?.worktree || defaultProjectRoot;
|
|
10857
|
+
const config = loadRuntimeConfig(projectRoot);
|
|
10810
10858
|
const knowledgeBases = ensureStringArray(config.knowledgeBases);
|
|
10811
10859
|
if (knowledgeBases.length === 0) {
|
|
10812
10860
|
return "No knowledge bases configured. Use add_knowledge_base to add folders.";
|
|
@@ -10816,7 +10864,7 @@ var list_knowledge_bases = (0, import_plugin.tool)({
|
|
|
10816
10864
|
`;
|
|
10817
10865
|
for (let i = 0; i < knowledgeBases.length; i++) {
|
|
10818
10866
|
const kb = knowledgeBases[i];
|
|
10819
|
-
const resolvedPath = resolveKnowledgeBasePath(kb,
|
|
10867
|
+
const resolvedPath = resolveKnowledgeBasePath(kb, projectRoot);
|
|
10820
10868
|
const exists = (0, import_fs9.existsSync)(resolvedPath);
|
|
10821
10869
|
result += `[${i + 1}] ${kb}
|
|
10822
10870
|
`;
|
|
@@ -10834,7 +10882,7 @@ var list_knowledge_bases = (0, import_plugin.tool)({
|
|
|
10834
10882
|
}
|
|
10835
10883
|
result += "\n";
|
|
10836
10884
|
}
|
|
10837
|
-
result += `Config file: ${getConfigPath(
|
|
10885
|
+
result += `Config file: ${getConfigPath(projectRoot)}`;
|
|
10838
10886
|
return result;
|
|
10839
10887
|
}
|
|
10840
10888
|
});
|
|
@@ -10843,14 +10891,15 @@ var remove_knowledge_base = (0, import_plugin.tool)({
|
|
|
10843
10891
|
args: {
|
|
10844
10892
|
path: z.string().describe("Path of the knowledge base to remove (must match the configured path exactly)")
|
|
10845
10893
|
},
|
|
10846
|
-
async execute(args) {
|
|
10894
|
+
async execute(args, context) {
|
|
10895
|
+
const projectRoot = context?.worktree || defaultProjectRoot;
|
|
10847
10896
|
const inputPath = args.path.trim();
|
|
10848
|
-
const config = loadEditableConfig(
|
|
10897
|
+
const config = loadEditableConfig(projectRoot);
|
|
10849
10898
|
const knowledgeBases = ensureStringArray(config.knowledgeBases);
|
|
10850
10899
|
if (knowledgeBases.length === 0) {
|
|
10851
10900
|
return "No knowledge bases configured.";
|
|
10852
10901
|
}
|
|
10853
|
-
const index = findKnowledgeBasePathIndex(knowledgeBases, inputPath,
|
|
10902
|
+
const index = findKnowledgeBasePathIndex(knowledgeBases, inputPath, projectRoot);
|
|
10854
10903
|
if (index === -1) {
|
|
10855
10904
|
let result2 = `Knowledge base not found: ${inputPath}
|
|
10856
10905
|
|
|
@@ -10865,14 +10914,14 @@ var remove_knowledge_base = (0, import_plugin.tool)({
|
|
|
10865
10914
|
}
|
|
10866
10915
|
const removed = knowledgeBases.splice(index, 1)[0];
|
|
10867
10916
|
config.knowledgeBases = knowledgeBases;
|
|
10868
|
-
saveConfig(
|
|
10869
|
-
|
|
10917
|
+
saveConfig(projectRoot, config);
|
|
10918
|
+
refreshIndexerForDirectory(projectRoot);
|
|
10870
10919
|
let result = `Removed: ${removed}
|
|
10871
10920
|
|
|
10872
10921
|
`;
|
|
10873
10922
|
result += `Remaining knowledge bases: ${knowledgeBases.length}
|
|
10874
10923
|
`;
|
|
10875
|
-
result += `Config saved to: ${getConfigPath(
|
|
10924
|
+
result += `Config saved to: ${getConfigPath(projectRoot)}
|
|
10876
10925
|
`;
|
|
10877
10926
|
result += `
|
|
10878
10927
|
Run /index to rebuild the index without the removed knowledge base.`;
|
|
@@ -11216,10 +11265,16 @@ var RoutingHintController = class {
|
|
|
11216
11265
|
|
|
11217
11266
|
// src/index.ts
|
|
11218
11267
|
var import_meta2 = {};
|
|
11219
|
-
var
|
|
11220
|
-
function replaceActiveWatcher(nextWatcher) {
|
|
11221
|
-
|
|
11222
|
-
|
|
11268
|
+
var activeWatchers = /* @__PURE__ */ new Map();
|
|
11269
|
+
function replaceActiveWatcher(projectRoot, nextWatcher) {
|
|
11270
|
+
const existing = activeWatchers.get(projectRoot);
|
|
11271
|
+
if (existing) {
|
|
11272
|
+
existing.stop();
|
|
11273
|
+
activeWatchers.delete(projectRoot);
|
|
11274
|
+
}
|
|
11275
|
+
if (nextWatcher) {
|
|
11276
|
+
activeWatchers.set(projectRoot, nextWatcher);
|
|
11277
|
+
}
|
|
11223
11278
|
}
|
|
11224
11279
|
function getCommandsDir() {
|
|
11225
11280
|
let currentDir = process.cwd();
|
|
@@ -11228,21 +11283,37 @@ function getCommandsDir() {
|
|
|
11228
11283
|
}
|
|
11229
11284
|
return path17.join(currentDir, "..", "commands");
|
|
11230
11285
|
}
|
|
11231
|
-
|
|
11286
|
+
function appendRoutingHints(output, hints, preferredRole) {
|
|
11287
|
+
const preferredBucket = preferredRole === "developer" ? output.developer : output.system;
|
|
11288
|
+
if (Array.isArray(preferredBucket)) {
|
|
11289
|
+
preferredBucket.push(...hints);
|
|
11290
|
+
return;
|
|
11291
|
+
}
|
|
11292
|
+
if (Array.isArray(output.system)) {
|
|
11293
|
+
output.system.push(...hints);
|
|
11294
|
+
}
|
|
11295
|
+
}
|
|
11296
|
+
var plugin = async ({ directory, worktree }) => {
|
|
11232
11297
|
try {
|
|
11233
|
-
const projectRoot = directory;
|
|
11298
|
+
const projectRoot = worktree || directory;
|
|
11234
11299
|
const rawConfig = loadMergedConfig(projectRoot);
|
|
11235
11300
|
const config = parseConfig(rawConfig);
|
|
11236
11301
|
initializeTools(projectRoot, config);
|
|
11237
|
-
const
|
|
11238
|
-
const routingHints = config.search.routingHints ? new RoutingHintController(() =>
|
|
11239
|
-
const
|
|
11240
|
-
|
|
11302
|
+
const getProjectIndexer = () => getIndexerForProject(projectRoot);
|
|
11303
|
+
const routingHints = config.search.routingHints ? new RoutingHintController(() => getProjectIndexer().getStatus()) : null;
|
|
11304
|
+
const isHomeDir = path17.resolve(projectRoot) === path17.resolve(os6.homedir());
|
|
11305
|
+
const isValidProject = !isHomeDir && (!config.indexing.requireProjectMarker || hasProjectMarker(projectRoot));
|
|
11306
|
+
if (isHomeDir) {
|
|
11307
|
+
console.warn(
|
|
11308
|
+
`[codebase-index] Refusing to watch or index home directory "${projectRoot}". Open a specific project directory instead.`
|
|
11309
|
+
);
|
|
11310
|
+
} else if (!isValidProject) {
|
|
11241
11311
|
console.warn(
|
|
11242
11312
|
`[codebase-index] Skipping file watching and auto-indexing: no project marker found in "${projectRoot}". Set "indexing.requireProjectMarker": false in config to override.`
|
|
11243
11313
|
);
|
|
11244
11314
|
}
|
|
11245
11315
|
if (config.indexing.autoIndex && isValidProject) {
|
|
11316
|
+
const indexer = getProjectIndexer();
|
|
11246
11317
|
indexer.initialize().then(() => {
|
|
11247
11318
|
indexer.index().catch(() => {
|
|
11248
11319
|
});
|
|
@@ -11250,9 +11321,9 @@ var plugin = async ({ directory }) => {
|
|
|
11250
11321
|
});
|
|
11251
11322
|
}
|
|
11252
11323
|
if (config.indexing.watchFiles && isValidProject) {
|
|
11253
|
-
replaceActiveWatcher(createWatcherWithIndexer(
|
|
11324
|
+
replaceActiveWatcher(projectRoot, createWatcherWithIndexer(getProjectIndexer, projectRoot, config));
|
|
11254
11325
|
} else {
|
|
11255
|
-
replaceActiveWatcher(null);
|
|
11326
|
+
replaceActiveWatcher(projectRoot, null);
|
|
11256
11327
|
}
|
|
11257
11328
|
return {
|
|
11258
11329
|
tool: {
|
|
@@ -11274,8 +11345,18 @@ var plugin = async ({ directory }) => {
|
|
|
11274
11345
|
routingHints?.observeUserMessage(input.sessionID, output.parts);
|
|
11275
11346
|
},
|
|
11276
11347
|
async "experimental.chat.system.transform"(input, output) {
|
|
11348
|
+
if (config.search.routingHintRole !== "system") {
|
|
11349
|
+
return;
|
|
11350
|
+
}
|
|
11277
11351
|
const hints = await routingHints?.getSystemHints(input.sessionID) ?? [];
|
|
11278
|
-
output
|
|
11352
|
+
appendRoutingHints(output, hints, "system");
|
|
11353
|
+
},
|
|
11354
|
+
async "experimental.chat.developer.transform"(input, output) {
|
|
11355
|
+
if (config.search.routingHintRole !== "developer") {
|
|
11356
|
+
return;
|
|
11357
|
+
}
|
|
11358
|
+
const hints = await routingHints?.getSystemHints(input.sessionID) ?? [];
|
|
11359
|
+
appendRoutingHints(output, hints, "developer");
|
|
11279
11360
|
},
|
|
11280
11361
|
async "tool.execute.after"(input) {
|
|
11281
11362
|
routingHints?.markToolUsed(input.sessionID, input.tool);
|
|
@@ -11289,8 +11370,8 @@ var plugin = async ({ directory }) => {
|
|
|
11289
11370
|
}
|
|
11290
11371
|
}
|
|
11291
11372
|
};
|
|
11292
|
-
} catch
|
|
11293
|
-
console.error("[codebase-index] Failed to initialize plugin
|
|
11373
|
+
} catch {
|
|
11374
|
+
console.error("[codebase-index] Failed to initialize plugin (check config and network)");
|
|
11294
11375
|
return {
|
|
11295
11376
|
tool: void 0,
|
|
11296
11377
|
async config() {
|