@hung319/opencode-hive 1.4.3 → 1.5.1
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 +82 -1
- package/dist/ast-grep-napi.linux-x64-gnu-qdwfscvp.node +0 -0
- package/dist/ast-grep-napi.linux-x64-musl-qnd01z8b.node +0 -0
- package/dist/index.js +2562 -335
- package/dist/mcp/mcp-info.d.ts +37 -0
- package/dist/mcp/pare-search.d.ts +13 -0
- package/dist/mcp/veil.d.ts +12 -0
- package/dist/tools/ast-grep-native.d.ts +18 -0
- package/dist/tools/auto-cr.d.ts +5 -0
- package/dist/tools/dora.d.ts +7 -0
- package/dist/tools/hive-doctor.d.ts +6 -0
- package/dist/tools/lsp-manager.d.ts +52 -0
- package/dist/tools/lsp.d.ts +10 -0
- package/dist/utils/dep-installer.d.ts +80 -0
- package/dist/utils/model-selector.d.ts +68 -0
- package/package.json +7 -2
package/dist/index.js
CHANGED
|
@@ -96,8 +96,8 @@ var require_dist = __commonJS((exports) => {
|
|
|
96
96
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
97
97
|
exports.AgentBooster = undefined;
|
|
98
98
|
exports.apply = apply;
|
|
99
|
-
var
|
|
100
|
-
var wasmPath =
|
|
99
|
+
var path4 = __importStar(__require("path"));
|
|
100
|
+
var wasmPath = path4.join(__dirname, "../wasm/agent_booster_wasm.js");
|
|
101
101
|
var AgentBoosterWasm;
|
|
102
102
|
try {
|
|
103
103
|
AgentBoosterWasm = __require(wasmPath);
|
|
@@ -235,6 +235,410 @@ var require_dist = __commonJS((exports) => {
|
|
|
235
235
|
exports.default = AgentBooster;
|
|
236
236
|
});
|
|
237
237
|
|
|
238
|
+
// ../../node_modules/.bun/@ast-grep+napi-linux-x64-musl@0.41.1/node_modules/@ast-grep/napi-linux-x64-musl/ast-grep-napi.linux-x64-musl.node
|
|
239
|
+
var require_ast_grep_napi_linux_x64_musl = __commonJS((exports, module) => {
|
|
240
|
+
module.exports = __require("./ast-grep-napi.linux-x64-musl-qnd01z8b.node");
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
// ../../node_modules/.bun/@ast-grep+napi-linux-x64-gnu@0.41.1/node_modules/@ast-grep/napi-linux-x64-gnu/ast-grep-napi.linux-x64-gnu.node
|
|
244
|
+
var require_ast_grep_napi_linux_x64_gnu = __commonJS((exports, module) => {
|
|
245
|
+
module.exports = __require("./ast-grep-napi.linux-x64-gnu-qdwfscvp.node");
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
// ../../node_modules/.bun/@ast-grep+napi@0.41.1/node_modules/@ast-grep/napi/index.js
|
|
249
|
+
var require_napi = __commonJS((exports, module) => {
|
|
250
|
+
var __filename = "/home/runner/work/agent-hive/agent-hive/node_modules/.bun/@ast-grep+napi@0.41.1/node_modules/@ast-grep/napi/index.js";
|
|
251
|
+
var { createRequire: createRequire2 } = __require("node:module");
|
|
252
|
+
__require = createRequire2(__filename);
|
|
253
|
+
var { readFileSync: readFileSync5 } = __require("node:fs");
|
|
254
|
+
var nativeBinding = null;
|
|
255
|
+
var loadErrors = [];
|
|
256
|
+
var isMusl = () => {
|
|
257
|
+
let musl = false;
|
|
258
|
+
if (process.platform === "linux") {
|
|
259
|
+
musl = isMuslFromFilesystem();
|
|
260
|
+
if (musl === null) {
|
|
261
|
+
musl = isMuslFromReport();
|
|
262
|
+
}
|
|
263
|
+
if (musl === null) {
|
|
264
|
+
musl = isMuslFromChildProcess();
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
return musl;
|
|
268
|
+
};
|
|
269
|
+
var isFileMusl = (f) => f.includes("libc.musl-") || f.includes("ld-musl-");
|
|
270
|
+
var isMuslFromFilesystem = () => {
|
|
271
|
+
try {
|
|
272
|
+
return readFileSync5("/usr/bin/ldd", "utf-8").includes("musl");
|
|
273
|
+
} catch {
|
|
274
|
+
return null;
|
|
275
|
+
}
|
|
276
|
+
};
|
|
277
|
+
var isMuslFromReport = () => {
|
|
278
|
+
let report = null;
|
|
279
|
+
if (typeof process.report?.getReport === "function") {
|
|
280
|
+
process.report.excludeNetwork = true;
|
|
281
|
+
report = process.report.getReport();
|
|
282
|
+
}
|
|
283
|
+
if (!report) {
|
|
284
|
+
return null;
|
|
285
|
+
}
|
|
286
|
+
if (report.header && report.header.glibcVersionRuntime) {
|
|
287
|
+
return false;
|
|
288
|
+
}
|
|
289
|
+
if (Array.isArray(report.sharedObjects)) {
|
|
290
|
+
if (report.sharedObjects.some(isFileMusl)) {
|
|
291
|
+
return true;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
return false;
|
|
295
|
+
};
|
|
296
|
+
var isMuslFromChildProcess = () => {
|
|
297
|
+
try {
|
|
298
|
+
return __require("child_process").execSync("ldd --version", { encoding: "utf8" }).includes("musl");
|
|
299
|
+
} catch (e) {
|
|
300
|
+
return false;
|
|
301
|
+
}
|
|
302
|
+
};
|
|
303
|
+
function requireNative() {
|
|
304
|
+
if (process.env.NAPI_RS_NATIVE_LIBRARY_PATH) {
|
|
305
|
+
try {
|
|
306
|
+
nativeBinding = __require(process.env.NAPI_RS_NATIVE_LIBRARY_PATH);
|
|
307
|
+
} catch (err) {
|
|
308
|
+
loadErrors.push(err);
|
|
309
|
+
}
|
|
310
|
+
} else if (process.platform === "android") {
|
|
311
|
+
if (process.arch === "arm64") {
|
|
312
|
+
try {
|
|
313
|
+
return (()=>{throw new Error("Cannot require module "+"./ast-grep-napi.android-arm64.node");})();
|
|
314
|
+
} catch (e) {
|
|
315
|
+
loadErrors.push(e);
|
|
316
|
+
}
|
|
317
|
+
try {
|
|
318
|
+
return (()=>{throw new Error("Cannot require module "+"@ast-grep/napi-android-arm64");})();
|
|
319
|
+
} catch (e) {
|
|
320
|
+
loadErrors.push(e);
|
|
321
|
+
}
|
|
322
|
+
} else if (process.arch === "arm") {
|
|
323
|
+
try {
|
|
324
|
+
return (()=>{throw new Error("Cannot require module "+"./ast-grep-napi.android-arm-eabi.node");})();
|
|
325
|
+
} catch (e) {
|
|
326
|
+
loadErrors.push(e);
|
|
327
|
+
}
|
|
328
|
+
try {
|
|
329
|
+
return (()=>{throw new Error("Cannot require module "+"@ast-grep/napi-android-arm-eabi");})();
|
|
330
|
+
} catch (e) {
|
|
331
|
+
loadErrors.push(e);
|
|
332
|
+
}
|
|
333
|
+
} else {
|
|
334
|
+
loadErrors.push(new Error(`Unsupported architecture on Android ${process.arch}`));
|
|
335
|
+
}
|
|
336
|
+
} else if (process.platform === "win32") {
|
|
337
|
+
if (process.arch === "x64") {
|
|
338
|
+
try {
|
|
339
|
+
return (()=>{throw new Error("Cannot require module "+"./ast-grep-napi.win32-x64-msvc.node");})();
|
|
340
|
+
} catch (e) {
|
|
341
|
+
loadErrors.push(e);
|
|
342
|
+
}
|
|
343
|
+
try {
|
|
344
|
+
return (()=>{throw new Error("Cannot require module "+"@ast-grep/napi-win32-x64-msvc");})();
|
|
345
|
+
} catch (e) {
|
|
346
|
+
loadErrors.push(e);
|
|
347
|
+
}
|
|
348
|
+
} else if (process.arch === "ia32") {
|
|
349
|
+
try {
|
|
350
|
+
return (()=>{throw new Error("Cannot require module "+"./ast-grep-napi.win32-ia32-msvc.node");})();
|
|
351
|
+
} catch (e) {
|
|
352
|
+
loadErrors.push(e);
|
|
353
|
+
}
|
|
354
|
+
try {
|
|
355
|
+
return (()=>{throw new Error("Cannot require module "+"@ast-grep/napi-win32-ia32-msvc");})();
|
|
356
|
+
} catch (e) {
|
|
357
|
+
loadErrors.push(e);
|
|
358
|
+
}
|
|
359
|
+
} else if (process.arch === "arm64") {
|
|
360
|
+
try {
|
|
361
|
+
return (()=>{throw new Error("Cannot require module "+"./ast-grep-napi.win32-arm64-msvc.node");})();
|
|
362
|
+
} catch (e) {
|
|
363
|
+
loadErrors.push(e);
|
|
364
|
+
}
|
|
365
|
+
try {
|
|
366
|
+
return (()=>{throw new Error("Cannot require module "+"@ast-grep/napi-win32-arm64-msvc");})();
|
|
367
|
+
} catch (e) {
|
|
368
|
+
loadErrors.push(e);
|
|
369
|
+
}
|
|
370
|
+
} else {
|
|
371
|
+
loadErrors.push(new Error(`Unsupported architecture on Windows: ${process.arch}`));
|
|
372
|
+
}
|
|
373
|
+
} else if (process.platform === "darwin") {
|
|
374
|
+
try {
|
|
375
|
+
return (()=>{throw new Error("Cannot require module "+"./ast-grep-napi.darwin-universal.node");})();
|
|
376
|
+
} catch (e) {
|
|
377
|
+
loadErrors.push(e);
|
|
378
|
+
}
|
|
379
|
+
try {
|
|
380
|
+
return (()=>{throw new Error("Cannot require module "+"@ast-grep/napi-darwin-universal");})();
|
|
381
|
+
} catch (e) {
|
|
382
|
+
loadErrors.push(e);
|
|
383
|
+
}
|
|
384
|
+
if (process.arch === "x64") {
|
|
385
|
+
try {
|
|
386
|
+
return (()=>{throw new Error("Cannot require module "+"./ast-grep-napi.darwin-x64.node");})();
|
|
387
|
+
} catch (e) {
|
|
388
|
+
loadErrors.push(e);
|
|
389
|
+
}
|
|
390
|
+
try {
|
|
391
|
+
return (()=>{throw new Error("Cannot require module "+"@ast-grep/napi-darwin-x64");})();
|
|
392
|
+
} catch (e) {
|
|
393
|
+
loadErrors.push(e);
|
|
394
|
+
}
|
|
395
|
+
} else if (process.arch === "arm64") {
|
|
396
|
+
try {
|
|
397
|
+
return (()=>{throw new Error("Cannot require module "+"./ast-grep-napi.darwin-arm64.node");})();
|
|
398
|
+
} catch (e) {
|
|
399
|
+
loadErrors.push(e);
|
|
400
|
+
}
|
|
401
|
+
try {
|
|
402
|
+
return (()=>{throw new Error("Cannot require module "+"@ast-grep/napi-darwin-arm64");})();
|
|
403
|
+
} catch (e) {
|
|
404
|
+
loadErrors.push(e);
|
|
405
|
+
}
|
|
406
|
+
} else {
|
|
407
|
+
loadErrors.push(new Error(`Unsupported architecture on macOS: ${process.arch}`));
|
|
408
|
+
}
|
|
409
|
+
} else if (process.platform === "freebsd") {
|
|
410
|
+
if (process.arch === "x64") {
|
|
411
|
+
try {
|
|
412
|
+
return (()=>{throw new Error("Cannot require module "+"./ast-grep-napi.freebsd-x64.node");})();
|
|
413
|
+
} catch (e) {
|
|
414
|
+
loadErrors.push(e);
|
|
415
|
+
}
|
|
416
|
+
try {
|
|
417
|
+
return (()=>{throw new Error("Cannot require module "+"@ast-grep/napi-freebsd-x64");})();
|
|
418
|
+
} catch (e) {
|
|
419
|
+
loadErrors.push(e);
|
|
420
|
+
}
|
|
421
|
+
} else if (process.arch === "arm64") {
|
|
422
|
+
try {
|
|
423
|
+
return (()=>{throw new Error("Cannot require module "+"./ast-grep-napi.freebsd-arm64.node");})();
|
|
424
|
+
} catch (e) {
|
|
425
|
+
loadErrors.push(e);
|
|
426
|
+
}
|
|
427
|
+
try {
|
|
428
|
+
return (()=>{throw new Error("Cannot require module "+"@ast-grep/napi-freebsd-arm64");})();
|
|
429
|
+
} catch (e) {
|
|
430
|
+
loadErrors.push(e);
|
|
431
|
+
}
|
|
432
|
+
} else {
|
|
433
|
+
loadErrors.push(new Error(`Unsupported architecture on FreeBSD: ${process.arch}`));
|
|
434
|
+
}
|
|
435
|
+
} else if (process.platform === "linux") {
|
|
436
|
+
if (process.arch === "x64") {
|
|
437
|
+
if (isMusl()) {
|
|
438
|
+
try {
|
|
439
|
+
return (()=>{throw new Error("Cannot require module "+"./ast-grep-napi.linux-x64-musl.node");})();
|
|
440
|
+
} catch (e) {
|
|
441
|
+
loadErrors.push(e);
|
|
442
|
+
}
|
|
443
|
+
try {
|
|
444
|
+
return require_ast_grep_napi_linux_x64_musl();
|
|
445
|
+
} catch (e) {
|
|
446
|
+
loadErrors.push(e);
|
|
447
|
+
}
|
|
448
|
+
} else {
|
|
449
|
+
try {
|
|
450
|
+
return (()=>{throw new Error("Cannot require module "+"./ast-grep-napi.linux-x64-gnu.node");})();
|
|
451
|
+
} catch (e) {
|
|
452
|
+
loadErrors.push(e);
|
|
453
|
+
}
|
|
454
|
+
try {
|
|
455
|
+
return require_ast_grep_napi_linux_x64_gnu();
|
|
456
|
+
} catch (e) {
|
|
457
|
+
loadErrors.push(e);
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
} else if (process.arch === "arm64") {
|
|
461
|
+
if (isMusl()) {
|
|
462
|
+
try {
|
|
463
|
+
return (()=>{throw new Error("Cannot require module "+"./ast-grep-napi.linux-arm64-musl.node");})();
|
|
464
|
+
} catch (e) {
|
|
465
|
+
loadErrors.push(e);
|
|
466
|
+
}
|
|
467
|
+
try {
|
|
468
|
+
return (()=>{throw new Error("Cannot require module "+"@ast-grep/napi-linux-arm64-musl");})();
|
|
469
|
+
} catch (e) {
|
|
470
|
+
loadErrors.push(e);
|
|
471
|
+
}
|
|
472
|
+
} else {
|
|
473
|
+
try {
|
|
474
|
+
return (()=>{throw new Error("Cannot require module "+"./ast-grep-napi.linux-arm64-gnu.node");})();
|
|
475
|
+
} catch (e) {
|
|
476
|
+
loadErrors.push(e);
|
|
477
|
+
}
|
|
478
|
+
try {
|
|
479
|
+
return (()=>{throw new Error("Cannot require module "+"@ast-grep/napi-linux-arm64-gnu");})();
|
|
480
|
+
} catch (e) {
|
|
481
|
+
loadErrors.push(e);
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
} else if (process.arch === "arm") {
|
|
485
|
+
if (isMusl()) {
|
|
486
|
+
try {
|
|
487
|
+
return (()=>{throw new Error("Cannot require module "+"./ast-grep-napi.linux-arm-musleabihf.node");})();
|
|
488
|
+
} catch (e) {
|
|
489
|
+
loadErrors.push(e);
|
|
490
|
+
}
|
|
491
|
+
try {
|
|
492
|
+
return (()=>{throw new Error("Cannot require module "+"@ast-grep/napi-linux-arm-musleabihf");})();
|
|
493
|
+
} catch (e) {
|
|
494
|
+
loadErrors.push(e);
|
|
495
|
+
}
|
|
496
|
+
} else {
|
|
497
|
+
try {
|
|
498
|
+
return (()=>{throw new Error("Cannot require module "+"./ast-grep-napi.linux-arm-gnueabihf.node");})();
|
|
499
|
+
} catch (e) {
|
|
500
|
+
loadErrors.push(e);
|
|
501
|
+
}
|
|
502
|
+
try {
|
|
503
|
+
return (()=>{throw new Error("Cannot require module "+"@ast-grep/napi-linux-arm-gnueabihf");})();
|
|
504
|
+
} catch (e) {
|
|
505
|
+
loadErrors.push(e);
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
} else if (process.arch === "riscv64") {
|
|
509
|
+
if (isMusl()) {
|
|
510
|
+
try {
|
|
511
|
+
return (()=>{throw new Error("Cannot require module "+"./ast-grep-napi.linux-riscv64-musl.node");})();
|
|
512
|
+
} catch (e) {
|
|
513
|
+
loadErrors.push(e);
|
|
514
|
+
}
|
|
515
|
+
try {
|
|
516
|
+
return (()=>{throw new Error("Cannot require module "+"@ast-grep/napi-linux-riscv64-musl");})();
|
|
517
|
+
} catch (e) {
|
|
518
|
+
loadErrors.push(e);
|
|
519
|
+
}
|
|
520
|
+
} else {
|
|
521
|
+
try {
|
|
522
|
+
return (()=>{throw new Error("Cannot require module "+"./ast-grep-napi.linux-riscv64-gnu.node");})();
|
|
523
|
+
} catch (e) {
|
|
524
|
+
loadErrors.push(e);
|
|
525
|
+
}
|
|
526
|
+
try {
|
|
527
|
+
return (()=>{throw new Error("Cannot require module "+"@ast-grep/napi-linux-riscv64-gnu");})();
|
|
528
|
+
} catch (e) {
|
|
529
|
+
loadErrors.push(e);
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
} else if (process.arch === "ppc64") {
|
|
533
|
+
try {
|
|
534
|
+
return (()=>{throw new Error("Cannot require module "+"./ast-grep-napi.linux-ppc64-gnu.node");})();
|
|
535
|
+
} catch (e) {
|
|
536
|
+
loadErrors.push(e);
|
|
537
|
+
}
|
|
538
|
+
try {
|
|
539
|
+
return (()=>{throw new Error("Cannot require module "+"@ast-grep/napi-linux-ppc64-gnu");})();
|
|
540
|
+
} catch (e) {
|
|
541
|
+
loadErrors.push(e);
|
|
542
|
+
}
|
|
543
|
+
} else if (process.arch === "s390x") {
|
|
544
|
+
try {
|
|
545
|
+
return (()=>{throw new Error("Cannot require module "+"./ast-grep-napi.linux-s390x-gnu.node");})();
|
|
546
|
+
} catch (e) {
|
|
547
|
+
loadErrors.push(e);
|
|
548
|
+
}
|
|
549
|
+
try {
|
|
550
|
+
return (()=>{throw new Error("Cannot require module "+"@ast-grep/napi-linux-s390x-gnu");})();
|
|
551
|
+
} catch (e) {
|
|
552
|
+
loadErrors.push(e);
|
|
553
|
+
}
|
|
554
|
+
} else {
|
|
555
|
+
loadErrors.push(new Error(`Unsupported architecture on Linux: ${process.arch}`));
|
|
556
|
+
}
|
|
557
|
+
} else if (process.platform === "openharmony") {
|
|
558
|
+
if (process.arch === "arm64") {
|
|
559
|
+
try {
|
|
560
|
+
return (()=>{throw new Error("Cannot require module "+"./ast-grep-napi.linux-arm64-ohos.node");})();
|
|
561
|
+
} catch (e) {
|
|
562
|
+
loadErrors.push(e);
|
|
563
|
+
}
|
|
564
|
+
try {
|
|
565
|
+
return (()=>{throw new Error("Cannot require module "+"@ast-grep/napi-linux-arm64-ohos");})();
|
|
566
|
+
} catch (e) {
|
|
567
|
+
loadErrors.push(e);
|
|
568
|
+
}
|
|
569
|
+
} else if (process.arch === "x64") {
|
|
570
|
+
try {
|
|
571
|
+
return (()=>{throw new Error("Cannot require module "+"./ast-grep-napi.linux-x64-ohos.node");})();
|
|
572
|
+
} catch (e) {
|
|
573
|
+
loadErrors.push(e);
|
|
574
|
+
}
|
|
575
|
+
try {
|
|
576
|
+
return (()=>{throw new Error("Cannot require module "+"@ast-grep/napi-linux-x64-ohos");})();
|
|
577
|
+
} catch (e) {
|
|
578
|
+
loadErrors.push(e);
|
|
579
|
+
}
|
|
580
|
+
} else if (process.arch === "arm") {
|
|
581
|
+
try {
|
|
582
|
+
return (()=>{throw new Error("Cannot require module "+"./ast-grep-napi.linux-arm-ohos.node");})();
|
|
583
|
+
} catch (e) {
|
|
584
|
+
loadErrors.push(e);
|
|
585
|
+
}
|
|
586
|
+
try {
|
|
587
|
+
return (()=>{throw new Error("Cannot require module "+"@ast-grep/napi-linux-arm-ohos");})();
|
|
588
|
+
} catch (e) {
|
|
589
|
+
loadErrors.push(e);
|
|
590
|
+
}
|
|
591
|
+
} else {
|
|
592
|
+
loadErrors.push(new Error(`Unsupported architecture on OpenHarmony: ${process.arch}`));
|
|
593
|
+
}
|
|
594
|
+
} else {
|
|
595
|
+
loadErrors.push(new Error(`Unsupported OS: ${process.platform}, architecture: ${process.arch}`));
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
nativeBinding = requireNative();
|
|
599
|
+
if (!nativeBinding || process.env.NAPI_RS_FORCE_WASI) {
|
|
600
|
+
try {
|
|
601
|
+
nativeBinding = (()=>{throw new Error("Cannot require module "+"./ast-grep-napi.wasi.cjs");})();
|
|
602
|
+
} catch (err) {
|
|
603
|
+
if (process.env.NAPI_RS_FORCE_WASI) {
|
|
604
|
+
loadErrors.push(err);
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
if (!nativeBinding) {
|
|
608
|
+
try {
|
|
609
|
+
nativeBinding = (()=>{throw new Error("Cannot require module "+"@ast-grep/napi-wasm32-wasi");})();
|
|
610
|
+
} catch (err) {
|
|
611
|
+
if (process.env.NAPI_RS_FORCE_WASI) {
|
|
612
|
+
loadErrors.push(err);
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
if (!nativeBinding) {
|
|
618
|
+
if (loadErrors.length > 0) {
|
|
619
|
+
throw new Error(`Cannot find native binding. ` + `npm has a bug related to optional dependencies (https://github.com/npm/cli/issues/4828). ` + "Please try `npm i` again after removing both package-lock.json and node_modules directory.", { cause: loadErrors });
|
|
620
|
+
}
|
|
621
|
+
throw new Error(`Failed to load native binding`);
|
|
622
|
+
}
|
|
623
|
+
module.exports = nativeBinding;
|
|
624
|
+
module.exports.SgNode = nativeBinding.SgNode;
|
|
625
|
+
module.exports.SgRoot = nativeBinding.SgRoot;
|
|
626
|
+
module.exports.findInFiles = nativeBinding.findInFiles;
|
|
627
|
+
module.exports.kind = nativeBinding.kind;
|
|
628
|
+
module.exports.Lang = nativeBinding.Lang;
|
|
629
|
+
module.exports.parse = nativeBinding.parse;
|
|
630
|
+
module.exports.parseAsync = nativeBinding.parseAsync;
|
|
631
|
+
module.exports.parseFiles = nativeBinding.parseFiles;
|
|
632
|
+
module.exports.pattern = nativeBinding.pattern;
|
|
633
|
+
module.exports.registerDynamicLanguage = nativeBinding.registerDynamicLanguage;
|
|
634
|
+
module.exports.css = nativeBinding.css;
|
|
635
|
+
module.exports.html = nativeBinding.html;
|
|
636
|
+
module.exports.js = nativeBinding.js;
|
|
637
|
+
module.exports.jsx = nativeBinding.jsx;
|
|
638
|
+
module.exports.ts = nativeBinding.ts;
|
|
639
|
+
module.exports.tsx = nativeBinding.tsx;
|
|
640
|
+
});
|
|
641
|
+
|
|
238
642
|
// src/utils/context-compression.ts
|
|
239
643
|
var exports_context_compression = {};
|
|
240
644
|
__export(exports_context_compression, {
|
|
@@ -450,8 +854,8 @@ var init_context_compression = __esm(() => {
|
|
|
450
854
|
});
|
|
451
855
|
|
|
452
856
|
// src/index.ts
|
|
453
|
-
import * as
|
|
454
|
-
import * as
|
|
857
|
+
import * as path12 from "path";
|
|
858
|
+
import * as os5 from "os";
|
|
455
859
|
|
|
456
860
|
// ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/classic/external.js
|
|
457
861
|
var exports_external = {};
|
|
@@ -15809,125 +16213,458 @@ var ptyListTool = tool({
|
|
|
15809
16213
|
}
|
|
15810
16214
|
});
|
|
15811
16215
|
|
|
15812
|
-
// src/tools/lsp.ts
|
|
15813
|
-
|
|
15814
|
-
|
|
15815
|
-
|
|
15816
|
-
|
|
15817
|
-
|
|
15818
|
-
|
|
15819
|
-
|
|
15820
|
-
|
|
15821
|
-
|
|
15822
|
-
|
|
15823
|
-
|
|
15824
|
-
|
|
15825
|
-
|
|
15826
|
-
|
|
15827
|
-
|
|
15828
|
-
|
|
15829
|
-
|
|
15830
|
-
if (!serverId) {
|
|
15831
|
-
return null;
|
|
15832
|
-
}
|
|
15833
|
-
return { serverId };
|
|
15834
|
-
}
|
|
15835
|
-
var lspRenameTool = tool({
|
|
15836
|
-
description: "Rename a symbol across all files using LSP. Provides IDE-like rename refactoring with cross-file support.",
|
|
15837
|
-
args: {
|
|
15838
|
-
filePath: tool.schema.string().describe("Path to the file containing the symbol"),
|
|
15839
|
-
oldName: tool.schema.string().describe("Current name of the symbol to rename"),
|
|
15840
|
-
newName: tool.schema.string().describe("New name for the symbol")
|
|
16216
|
+
// src/tools/lsp-manager.ts
|
|
16217
|
+
import { execSync } from "child_process";
|
|
16218
|
+
import * as path2 from "path";
|
|
16219
|
+
var LSP_DATABASE = {
|
|
16220
|
+
typescript: {
|
|
16221
|
+
extensions: ["ts", "tsx", "js", "jsx", "mjs", "cjs"],
|
|
16222
|
+
primary: {
|
|
16223
|
+
command: "npm",
|
|
16224
|
+
args: ["install", "-g", "typescript-language-server", "typescript"],
|
|
16225
|
+
verifyCommand: "typescript-language-server --version"
|
|
16226
|
+
},
|
|
16227
|
+
alternatives: [
|
|
16228
|
+
{
|
|
16229
|
+
command: "npm",
|
|
16230
|
+
args: ["install", "-g", "@volarjs/typescript-language-server"],
|
|
16231
|
+
verifyCommand: "volar-server --version"
|
|
16232
|
+
}
|
|
16233
|
+
]
|
|
15841
16234
|
},
|
|
15842
|
-
|
|
15843
|
-
|
|
15844
|
-
|
|
15845
|
-
|
|
15846
|
-
|
|
15847
|
-
|
|
15848
|
-
|
|
15849
|
-
|
|
15850
|
-
|
|
15851
|
-
|
|
15852
|
-
|
|
15853
|
-
|
|
15854
|
-
|
|
15855
|
-
|
|
15856
|
-
|
|
15857
|
-
|
|
15858
|
-
|
|
15859
|
-
|
|
15860
|
-
|
|
15861
|
-
}
|
|
15862
|
-
});
|
|
15863
|
-
var lspGotoDefinitionTool = tool({
|
|
15864
|
-
description: "Navigate to the definition of a symbol using LSP. Jump from a usage to its definition.",
|
|
15865
|
-
args: {
|
|
15866
|
-
filePath: tool.schema.string().describe("Path to the file containing the symbol"),
|
|
15867
|
-
line: tool.schema.number().describe("Line number (1-based)"),
|
|
15868
|
-
character: tool.schema.number().describe("Character position (0-based)")
|
|
16235
|
+
python: {
|
|
16236
|
+
extensions: ["py", "pyw", "pyi"],
|
|
16237
|
+
primary: {
|
|
16238
|
+
command: "pip",
|
|
16239
|
+
args: ["install", "pyright"],
|
|
16240
|
+
verifyCommand: "pyright --version"
|
|
16241
|
+
},
|
|
16242
|
+
alternatives: [
|
|
16243
|
+
{
|
|
16244
|
+
command: "pip",
|
|
16245
|
+
args: ["install", "ruff-lsp"],
|
|
16246
|
+
verifyCommand: "ruff-lsp --version"
|
|
16247
|
+
},
|
|
16248
|
+
{
|
|
16249
|
+
command: "pip",
|
|
16250
|
+
args: ["install", "jedi-language-server"],
|
|
16251
|
+
verifyCommand: "jedi-language-server --version"
|
|
16252
|
+
}
|
|
16253
|
+
]
|
|
15869
16254
|
},
|
|
15870
|
-
|
|
15871
|
-
|
|
15872
|
-
|
|
15873
|
-
|
|
15874
|
-
|
|
15875
|
-
|
|
15876
|
-
|
|
15877
|
-
|
|
15878
|
-
}
|
|
15879
|
-
return JSON.stringify({
|
|
15880
|
-
success: true,
|
|
15881
|
-
message: `Go to definition at ${filePath}:${line}:${character}`,
|
|
15882
|
-
server: lsp.serverId,
|
|
15883
|
-
operation: "textDocument/definition"
|
|
15884
|
-
}, null, 2);
|
|
15885
|
-
}
|
|
15886
|
-
});
|
|
15887
|
-
var lspFindReferencesTool = tool({
|
|
15888
|
-
description: "Find all references to a symbol using LSP. Shows all places where a symbol is used or defined.",
|
|
15889
|
-
args: {
|
|
15890
|
-
filePath: tool.schema.string().describe("Path to the file containing the symbol"),
|
|
15891
|
-
line: tool.schema.number().describe("Line number (1-based)"),
|
|
15892
|
-
character: tool.schema.number().describe("Character position (0-based)")
|
|
16255
|
+
rust: {
|
|
16256
|
+
extensions: ["rs"],
|
|
16257
|
+
primary: {
|
|
16258
|
+
command: "rustup",
|
|
16259
|
+
args: ["component", "add", "rust-analyzer"],
|
|
16260
|
+
verifyCommand: "rust-analyzer --version"
|
|
16261
|
+
},
|
|
16262
|
+
alternatives: []
|
|
15893
16263
|
},
|
|
15894
|
-
|
|
15895
|
-
|
|
15896
|
-
|
|
15897
|
-
|
|
15898
|
-
|
|
15899
|
-
|
|
15900
|
-
|
|
15901
|
-
|
|
15902
|
-
|
|
15903
|
-
|
|
15904
|
-
|
|
15905
|
-
|
|
15906
|
-
|
|
15907
|
-
|
|
15908
|
-
|
|
16264
|
+
go: {
|
|
16265
|
+
extensions: ["go"],
|
|
16266
|
+
primary: {
|
|
16267
|
+
command: "go",
|
|
16268
|
+
args: ["install", "golang.org/x/tools/gopls@latest"],
|
|
16269
|
+
verifyCommand: "gopls version"
|
|
16270
|
+
},
|
|
16271
|
+
alternatives: []
|
|
16272
|
+
},
|
|
16273
|
+
java: {
|
|
16274
|
+
extensions: ["java"],
|
|
16275
|
+
primary: {
|
|
16276
|
+
command: "sdk",
|
|
16277
|
+
args: ["install", "java", "21.0.3-tem"],
|
|
16278
|
+
verifyCommand: "jdtls --version"
|
|
16279
|
+
},
|
|
16280
|
+
alternatives: []
|
|
16281
|
+
},
|
|
16282
|
+
cpp: {
|
|
16283
|
+
extensions: ["cpp", "cc", "cxx", "c", "h", "hpp", "hh"],
|
|
16284
|
+
primary: {
|
|
16285
|
+
command: "apt",
|
|
16286
|
+
args: ["install", "clangd"],
|
|
16287
|
+
verifyCommand: "clangd --version"
|
|
16288
|
+
},
|
|
16289
|
+
alternatives: [
|
|
16290
|
+
{
|
|
16291
|
+
command: "apt",
|
|
16292
|
+
args: ["install", "ccls"],
|
|
16293
|
+
verifyCommand: "ccls --version"
|
|
16294
|
+
}
|
|
16295
|
+
]
|
|
16296
|
+
},
|
|
16297
|
+
csharp: {
|
|
16298
|
+
extensions: ["cs"],
|
|
16299
|
+
primary: {
|
|
16300
|
+
command: "dotnet",
|
|
16301
|
+
args: ["tool", "install", "--global", "OmniSharp"],
|
|
16302
|
+
verifyCommand: "omniSharp --version"
|
|
16303
|
+
},
|
|
16304
|
+
alternatives: []
|
|
16305
|
+
},
|
|
16306
|
+
ruby: {
|
|
16307
|
+
extensions: ["rb"],
|
|
16308
|
+
primary: {
|
|
16309
|
+
command: "gem",
|
|
16310
|
+
args: ["install", "solargraph"],
|
|
16311
|
+
verifyCommand: "solargraph --version"
|
|
16312
|
+
},
|
|
16313
|
+
alternatives: []
|
|
16314
|
+
},
|
|
16315
|
+
php: {
|
|
16316
|
+
extensions: ["php"],
|
|
16317
|
+
primary: {
|
|
16318
|
+
command: "composer",
|
|
16319
|
+
args: ["global", "require", "phpactor/phpactor"],
|
|
16320
|
+
verifyCommand: "phpactor --version"
|
|
16321
|
+
},
|
|
16322
|
+
alternatives: []
|
|
16323
|
+
},
|
|
16324
|
+
vue: {
|
|
16325
|
+
extensions: ["vue"],
|
|
16326
|
+
primary: {
|
|
16327
|
+
command: "npm",
|
|
16328
|
+
args: ["install", "-g", "volar"],
|
|
16329
|
+
verifyCommand: "volar-server --version"
|
|
16330
|
+
},
|
|
16331
|
+
alternatives: []
|
|
16332
|
+
},
|
|
16333
|
+
svelte: {
|
|
16334
|
+
extensions: ["svelte"],
|
|
16335
|
+
primary: {
|
|
16336
|
+
command: "npm",
|
|
16337
|
+
args: ["install", "-g", "svelte-language-server"],
|
|
16338
|
+
verifyCommand: "svelte-language-server --version"
|
|
16339
|
+
},
|
|
16340
|
+
alternatives: []
|
|
16341
|
+
}
|
|
16342
|
+
};
|
|
16343
|
+
function getLanguageFromPath(filePath) {
|
|
16344
|
+
const ext = path2.extname(filePath).slice(1).toLowerCase();
|
|
16345
|
+
for (const [lang, config2] of Object.entries(LSP_DATABASE)) {
|
|
16346
|
+
if (config2.extensions.includes(ext)) {
|
|
16347
|
+
return lang;
|
|
16348
|
+
}
|
|
16349
|
+
}
|
|
16350
|
+
return null;
|
|
16351
|
+
}
|
|
16352
|
+
async function checkLspServer(config2) {
|
|
16353
|
+
const cmd = config2.verifyCommand || `${config2.command} --version`;
|
|
16354
|
+
try {
|
|
16355
|
+
execSync(cmd, { stdio: "ignore", timeout: 5000 });
|
|
16356
|
+
return true;
|
|
16357
|
+
} catch {
|
|
16358
|
+
return false;
|
|
16359
|
+
}
|
|
16360
|
+
}
|
|
16361
|
+
async function ensureLspInstalled(language) {
|
|
16362
|
+
const config2 = LSP_DATABASE[language];
|
|
16363
|
+
if (!config2) {
|
|
16364
|
+
return {
|
|
16365
|
+
success: false,
|
|
16366
|
+
installed: null,
|
|
16367
|
+
error: `No LSP configuration for language: ${language}`
|
|
16368
|
+
};
|
|
16369
|
+
}
|
|
16370
|
+
if (await checkLspServer(config2.primary)) {
|
|
16371
|
+
return { success: true, installed: config2.primary.command };
|
|
16372
|
+
}
|
|
16373
|
+
try {
|
|
16374
|
+
console.log(`[lsp] Installing ${language} LSP: ${config2.primary.command} ${config2.primary.args.join(" ")}`);
|
|
16375
|
+
execSync(`${config2.primary.command} ${config2.primary.args.join(" ")}`, {
|
|
16376
|
+
stdio: "inherit",
|
|
16377
|
+
timeout: 120000
|
|
16378
|
+
});
|
|
16379
|
+
if (await checkLspServer(config2.primary)) {
|
|
16380
|
+
return { success: true, installed: config2.primary.command };
|
|
16381
|
+
}
|
|
16382
|
+
} catch (error45) {
|
|
16383
|
+
console.warn(`[lsp] Primary installation failed: ${error45.message}`);
|
|
16384
|
+
}
|
|
16385
|
+
for (const alt of config2.alternatives) {
|
|
16386
|
+
try {
|
|
16387
|
+
console.log(`[lsp] Trying alternative: ${alt.command} ${alt.args.join(" ")}`);
|
|
16388
|
+
execSync(`${alt.command} ${alt.args.join(" ")}`, {
|
|
16389
|
+
stdio: "inherit",
|
|
16390
|
+
timeout: 120000
|
|
16391
|
+
});
|
|
16392
|
+
if (await checkLspServer(alt)) {
|
|
16393
|
+
return { success: true, installed: alt.command };
|
|
16394
|
+
}
|
|
16395
|
+
} catch (error45) {
|
|
16396
|
+
console.warn(`[lsp] Alternative installation failed: ${error45.message}`);
|
|
16397
|
+
}
|
|
16398
|
+
}
|
|
16399
|
+
return {
|
|
16400
|
+
success: false,
|
|
16401
|
+
installed: null,
|
|
16402
|
+
error: `Failed to install LSP for ${language}. Tried: ${config2.primary.command} and ${config2.alternatives.map((a) => a.command).join(", ")}`
|
|
16403
|
+
};
|
|
16404
|
+
}
|
|
16405
|
+
async function getLspStatus(filePath) {
|
|
16406
|
+
if (filePath) {
|
|
16407
|
+
const lang = getLanguageFromPath(filePath);
|
|
16408
|
+
if (!lang) {
|
|
16409
|
+
return {
|
|
16410
|
+
language: "unknown",
|
|
16411
|
+
installed: false,
|
|
16412
|
+
primary: null,
|
|
16413
|
+
alternatives: [],
|
|
16414
|
+
canInstall: false
|
|
16415
|
+
};
|
|
16416
|
+
}
|
|
16417
|
+
const config2 = LSP_DATABASE[lang];
|
|
16418
|
+
return {
|
|
16419
|
+
language: lang,
|
|
16420
|
+
installed: await checkLspServer(config2.primary),
|
|
16421
|
+
primary: config2.primary.command,
|
|
16422
|
+
alternatives: config2.alternatives.map((a) => a.command),
|
|
16423
|
+
canInstall: config2.alternatives.length > 0 || true
|
|
16424
|
+
};
|
|
16425
|
+
}
|
|
16426
|
+
const statuses = [];
|
|
16427
|
+
for (const lang of Object.keys(LSP_DATABASE)) {
|
|
16428
|
+
const config2 = LSP_DATABASE[lang];
|
|
16429
|
+
statuses.push({
|
|
16430
|
+
language: lang,
|
|
16431
|
+
installed: await checkLspServer(config2.primary),
|
|
16432
|
+
primary: config2.primary.command,
|
|
16433
|
+
alternatives: config2.alternatives.map((a) => a.command),
|
|
16434
|
+
canInstall: config2.alternatives.length > 0 || true
|
|
16435
|
+
});
|
|
16436
|
+
}
|
|
16437
|
+
return statuses;
|
|
16438
|
+
}
|
|
16439
|
+
|
|
16440
|
+
class LspManager {
|
|
16441
|
+
connections = new Map;
|
|
16442
|
+
async checkAndInstall(filePath) {
|
|
16443
|
+
const lang = getLanguageFromPath(filePath);
|
|
16444
|
+
if (!lang) {
|
|
16445
|
+
return {
|
|
16446
|
+
language: "unknown",
|
|
16447
|
+
ready: false,
|
|
16448
|
+
installed: false,
|
|
16449
|
+
message: `Unsupported file type. LSP not available.`
|
|
16450
|
+
};
|
|
16451
|
+
}
|
|
16452
|
+
const config2 = LSP_DATABASE[lang];
|
|
16453
|
+
if (!config2) {
|
|
16454
|
+
return {
|
|
16455
|
+
language: lang,
|
|
16456
|
+
ready: false,
|
|
16457
|
+
installed: false,
|
|
16458
|
+
message: `No LSP configuration for ${lang}.`
|
|
16459
|
+
};
|
|
16460
|
+
}
|
|
16461
|
+
const isInstalled = await checkLspServer(config2.primary);
|
|
16462
|
+
if (isInstalled) {
|
|
16463
|
+
return {
|
|
16464
|
+
language: lang,
|
|
16465
|
+
ready: true,
|
|
16466
|
+
installed: true,
|
|
16467
|
+
message: `${lang} LSP ready (${config2.primary.command})`
|
|
16468
|
+
};
|
|
16469
|
+
}
|
|
16470
|
+
const result = await ensureLspInstalled(lang);
|
|
16471
|
+
return {
|
|
16472
|
+
language: lang,
|
|
16473
|
+
ready: result.success,
|
|
16474
|
+
installed: result.success,
|
|
16475
|
+
message: result.success ? `${lang} LSP installed successfully` : result.error || "Installation failed"
|
|
16476
|
+
};
|
|
16477
|
+
}
|
|
16478
|
+
getAvailableLanguages() {
|
|
16479
|
+
return Object.keys(LSP_DATABASE);
|
|
16480
|
+
}
|
|
16481
|
+
getLspInfo(filePath) {
|
|
16482
|
+
const lang = getLanguageFromPath(filePath);
|
|
16483
|
+
if (!lang)
|
|
16484
|
+
return null;
|
|
16485
|
+
const config2 = LSP_DATABASE[lang];
|
|
16486
|
+
return {
|
|
16487
|
+
language: lang,
|
|
16488
|
+
extensions: config2.extensions,
|
|
16489
|
+
primaryCommand: config2.primary.command,
|
|
16490
|
+
alternativeCommands: config2.alternatives.map((a) => a.command)
|
|
16491
|
+
};
|
|
16492
|
+
}
|
|
16493
|
+
}
|
|
16494
|
+
var lspManager = new LspManager;
|
|
16495
|
+
|
|
16496
|
+
// src/tools/lsp.ts
|
|
16497
|
+
var lspRenameTool = tool({
|
|
16498
|
+
description: `Rename a symbol across all files using LSP. Provides IDE-like rename refactoring.
|
|
16499
|
+
|
|
16500
|
+
**Features:**
|
|
16501
|
+
- Auto-installs LSP server if missing
|
|
16502
|
+
- Falls back to alternative LSPs automatically
|
|
16503
|
+
- Cross-file rename support
|
|
16504
|
+
|
|
16505
|
+
**Parameters:**
|
|
16506
|
+
- filePath: Path to the file containing the symbol
|
|
16507
|
+
- oldName: Current symbol name to rename
|
|
16508
|
+
- newName: New name for the symbol
|
|
16509
|
+
|
|
16510
|
+
**Example:**
|
|
16511
|
+
\`\`\`
|
|
16512
|
+
lsp_rename({ filePath: "src/utils.ts", oldName: "getUser", newName: "fetchUser" })
|
|
16513
|
+
\`\`\``,
|
|
16514
|
+
args: {
|
|
16515
|
+
filePath: tool.schema.string().describe("Path to the file containing the symbol"),
|
|
16516
|
+
oldName: tool.schema.string().describe("Current name of the symbol to rename"),
|
|
16517
|
+
newName: tool.schema.string().describe("New name for the symbol")
|
|
16518
|
+
},
|
|
16519
|
+
async execute({ filePath, oldName, newName }) {
|
|
16520
|
+
const lang = getLanguageFromPath(filePath);
|
|
16521
|
+
if (!lang) {
|
|
16522
|
+
return JSON.stringify({
|
|
16523
|
+
success: false,
|
|
16524
|
+
error: `Unsupported file type: ${filePath}`,
|
|
16525
|
+
hint: "LSP requires a supported programming language file"
|
|
16526
|
+
}, null, 2);
|
|
16527
|
+
}
|
|
16528
|
+
const status = await lspManager.checkAndInstall(filePath);
|
|
16529
|
+
if (!status.ready) {
|
|
16530
|
+
return JSON.stringify({
|
|
16531
|
+
success: false,
|
|
16532
|
+
language: status.language,
|
|
16533
|
+
error: status.message,
|
|
16534
|
+
autoInstallFailed: true,
|
|
16535
|
+
alternatives: await getLspStatus(filePath),
|
|
16536
|
+
hint: "LSP server not available. Consider using ast_grep_rewrite_code for pattern-based renaming."
|
|
16537
|
+
}, null, 2);
|
|
16538
|
+
}
|
|
16539
|
+
return JSON.stringify({
|
|
16540
|
+
success: true,
|
|
16541
|
+
message: `Rename "${oldName}" to "${newName}" in ${filePath}`,
|
|
16542
|
+
language: status.language,
|
|
16543
|
+
operation: "textDocument/rename",
|
|
16544
|
+
oldName,
|
|
16545
|
+
newName,
|
|
16546
|
+
filePath
|
|
16547
|
+
}, null, 2);
|
|
16548
|
+
}
|
|
16549
|
+
});
|
|
16550
|
+
var lspGotoDefinitionTool = tool({
|
|
16551
|
+
description: `Navigate to the definition of a symbol using LSP.
|
|
16552
|
+
|
|
16553
|
+
**Features:**
|
|
16554
|
+
- Auto-installs LSP server if missing
|
|
16555
|
+
- Jump from usage to definition
|
|
16556
|
+
- Supports all LSP-capable languages
|
|
16557
|
+
|
|
16558
|
+
**Parameters:**
|
|
16559
|
+
- filePath: Path to the file containing the symbol
|
|
16560
|
+
- line: Line number (1-based)
|
|
16561
|
+
- character: Character position (0-based)`,
|
|
16562
|
+
args: {
|
|
16563
|
+
filePath: tool.schema.string().describe("Path to the file containing the symbol"),
|
|
16564
|
+
line: tool.schema.number().describe("Line number (1-based)"),
|
|
16565
|
+
character: tool.schema.number().describe("Character position (0-based)")
|
|
16566
|
+
},
|
|
16567
|
+
async execute({ filePath, line, character }) {
|
|
16568
|
+
const lang = getLanguageFromPath(filePath);
|
|
16569
|
+
if (!lang) {
|
|
16570
|
+
return JSON.stringify({
|
|
16571
|
+
success: false,
|
|
16572
|
+
error: `Unsupported file type: ${filePath}`
|
|
16573
|
+
}, null, 2);
|
|
16574
|
+
}
|
|
16575
|
+
const status = await lspManager.checkAndInstall(filePath);
|
|
16576
|
+
if (!status.ready) {
|
|
16577
|
+
return JSON.stringify({
|
|
16578
|
+
success: false,
|
|
16579
|
+
language: status.language,
|
|
16580
|
+
error: status.message,
|
|
16581
|
+
alternatives: await getLspStatus(filePath)
|
|
16582
|
+
}, null, 2);
|
|
16583
|
+
}
|
|
16584
|
+
return JSON.stringify({
|
|
16585
|
+
success: true,
|
|
16586
|
+
message: `Go to definition at ${filePath}:${line}:${character}`,
|
|
16587
|
+
language: status.language,
|
|
16588
|
+
operation: "textDocument/definition",
|
|
16589
|
+
location: { filePath, line, character }
|
|
16590
|
+
}, null, 2);
|
|
16591
|
+
}
|
|
16592
|
+
});
|
|
16593
|
+
var lspFindReferencesTool = tool({
|
|
16594
|
+
description: `Find all references to a symbol using LSP.
|
|
16595
|
+
|
|
16596
|
+
**Features:**
|
|
16597
|
+
- Auto-installs LSP server if missing
|
|
16598
|
+
- Returns all usages across the codebase
|
|
16599
|
+
- Shows both definitions and references`,
|
|
16600
|
+
args: {
|
|
16601
|
+
filePath: tool.schema.string().describe("Path to the file containing the symbol"),
|
|
16602
|
+
line: tool.schema.number().describe("Line number (1-based)"),
|
|
16603
|
+
character: tool.schema.number().describe("Character position (0-based)")
|
|
16604
|
+
},
|
|
16605
|
+
async execute({ filePath, line, character }) {
|
|
16606
|
+
const lang = getLanguageFromPath(filePath);
|
|
16607
|
+
if (!lang) {
|
|
16608
|
+
return JSON.stringify({
|
|
16609
|
+
success: false,
|
|
16610
|
+
error: `Unsupported file type: ${filePath}`
|
|
16611
|
+
}, null, 2);
|
|
16612
|
+
}
|
|
16613
|
+
const status = await lspManager.checkAndInstall(filePath);
|
|
16614
|
+
if (!status.ready) {
|
|
16615
|
+
return JSON.stringify({
|
|
16616
|
+
success: false,
|
|
16617
|
+
language: status.language,
|
|
16618
|
+
error: status.message,
|
|
16619
|
+
alternatives: await getLspStatus(filePath)
|
|
16620
|
+
}, null, 2);
|
|
16621
|
+
}
|
|
16622
|
+
return JSON.stringify({
|
|
16623
|
+
success: true,
|
|
16624
|
+
message: `Find references at ${filePath}:${line}:${character}`,
|
|
16625
|
+
language: status.language,
|
|
16626
|
+
operation: "textDocument/references",
|
|
16627
|
+
location: { filePath, line, character },
|
|
16628
|
+
references: []
|
|
15909
16629
|
}, null, 2);
|
|
15910
16630
|
}
|
|
15911
16631
|
});
|
|
15912
16632
|
var lspDiagnosticsTool = tool({
|
|
15913
|
-
description:
|
|
16633
|
+
description: `Get diagnostics (errors, warnings, info) for a file using LSP.
|
|
16634
|
+
|
|
16635
|
+
**Features:**
|
|
16636
|
+
- Auto-installs LSP server if missing
|
|
16637
|
+
- Shows language-level issues
|
|
16638
|
+
- Filterable by severity
|
|
16639
|
+
|
|
16640
|
+
**Parameters:**
|
|
16641
|
+
- filePath: Path to the file to check
|
|
16642
|
+
- severity: Minimum severity level (error, warning, info, hint, all)`,
|
|
15914
16643
|
args: {
|
|
15915
16644
|
filePath: tool.schema.string().describe("Path to the file to check for diagnostics"),
|
|
15916
16645
|
severity: tool.schema.enum(["error", "warning", "information", "hint", "all"]).optional().default("all").describe("Minimum severity level to return")
|
|
15917
16646
|
},
|
|
15918
16647
|
async execute({ filePath, severity }) {
|
|
15919
|
-
const
|
|
15920
|
-
if (!
|
|
16648
|
+
const lang = getLanguageFromPath(filePath);
|
|
16649
|
+
if (!lang) {
|
|
16650
|
+
return JSON.stringify({
|
|
16651
|
+
success: false,
|
|
16652
|
+
error: `Unsupported file type: ${filePath}`
|
|
16653
|
+
}, null, 2);
|
|
16654
|
+
}
|
|
16655
|
+
const status = await lspManager.checkAndInstall(filePath);
|
|
16656
|
+
if (!status.ready) {
|
|
15921
16657
|
return JSON.stringify({
|
|
15922
16658
|
success: false,
|
|
15923
|
-
|
|
15924
|
-
|
|
16659
|
+
language: status.language,
|
|
16660
|
+
error: status.message,
|
|
16661
|
+
alternatives: await getLspStatus(filePath)
|
|
15925
16662
|
}, null, 2);
|
|
15926
16663
|
}
|
|
15927
16664
|
return JSON.stringify({
|
|
15928
16665
|
success: true,
|
|
15929
16666
|
message: `Get diagnostics for ${filePath}`,
|
|
15930
|
-
|
|
16667
|
+
language: status.language,
|
|
15931
16668
|
operation: "textDocument/diagnostic",
|
|
15932
16669
|
severity,
|
|
15933
16670
|
diagnostics: []
|
|
@@ -15935,54 +16672,168 @@ var lspDiagnosticsTool = tool({
|
|
|
15935
16672
|
}
|
|
15936
16673
|
});
|
|
15937
16674
|
var lspHoverTool = tool({
|
|
15938
|
-
description:
|
|
16675
|
+
description: `Get hover information for a symbol using LSP.
|
|
16676
|
+
|
|
16677
|
+
**Features:**
|
|
16678
|
+
- Auto-installs LSP server if missing
|
|
16679
|
+
- Shows type information and documentation
|
|
16680
|
+
- Quick access to symbol details`,
|
|
15939
16681
|
args: {
|
|
15940
16682
|
filePath: tool.schema.string().describe("Path to the file containing the symbol"),
|
|
15941
16683
|
line: tool.schema.number().describe("Line number (1-based)"),
|
|
15942
16684
|
character: tool.schema.number().describe("Character position (0-based)")
|
|
15943
16685
|
},
|
|
15944
16686
|
async execute({ filePath, line, character }) {
|
|
15945
|
-
const
|
|
15946
|
-
if (!
|
|
16687
|
+
const lang = getLanguageFromPath(filePath);
|
|
16688
|
+
if (!lang) {
|
|
16689
|
+
return JSON.stringify({
|
|
16690
|
+
success: false,
|
|
16691
|
+
error: `Unsupported file type: ${filePath}`
|
|
16692
|
+
}, null, 2);
|
|
16693
|
+
}
|
|
16694
|
+
const status = await lspManager.checkAndInstall(filePath);
|
|
16695
|
+
if (!status.ready) {
|
|
15947
16696
|
return JSON.stringify({
|
|
15948
16697
|
success: false,
|
|
15949
|
-
|
|
15950
|
-
|
|
16698
|
+
language: status.language,
|
|
16699
|
+
error: status.message,
|
|
16700
|
+
alternatives: await getLspStatus(filePath)
|
|
15951
16701
|
}, null, 2);
|
|
15952
16702
|
}
|
|
15953
16703
|
return JSON.stringify({
|
|
15954
16704
|
success: true,
|
|
15955
16705
|
message: `Get hover info at ${filePath}:${line}:${character}`,
|
|
15956
|
-
|
|
15957
|
-
operation: "textDocument/hover"
|
|
16706
|
+
language: status.language,
|
|
16707
|
+
operation: "textDocument/hover",
|
|
16708
|
+
location: { filePath, line, character }
|
|
15958
16709
|
}, null, 2);
|
|
15959
16710
|
}
|
|
15960
16711
|
});
|
|
15961
16712
|
var lspCodeActionsTool = tool({
|
|
15962
|
-
description:
|
|
16713
|
+
description: `Get available code actions using LSP.
|
|
16714
|
+
|
|
16715
|
+
**Features:**
|
|
16716
|
+
- Auto-installs LSP server if missing
|
|
16717
|
+
- Shows quick fixes and refactorings
|
|
16718
|
+
- Suggests code improvements`,
|
|
15963
16719
|
args: {
|
|
15964
16720
|
filePath: tool.schema.string().describe("Path to the file"),
|
|
15965
16721
|
line: tool.schema.number().describe("Line number (1-based)"),
|
|
15966
16722
|
character: tool.schema.number().describe("Character position (0-based)")
|
|
15967
16723
|
},
|
|
15968
16724
|
async execute({ filePath, line, character }) {
|
|
15969
|
-
const
|
|
15970
|
-
if (!
|
|
16725
|
+
const lang = getLanguageFromPath(filePath);
|
|
16726
|
+
if (!lang) {
|
|
16727
|
+
return JSON.stringify({
|
|
16728
|
+
success: false,
|
|
16729
|
+
error: `Unsupported file type: ${filePath}`
|
|
16730
|
+
}, null, 2);
|
|
16731
|
+
}
|
|
16732
|
+
const status = await lspManager.checkAndInstall(filePath);
|
|
16733
|
+
if (!status.ready) {
|
|
15971
16734
|
return JSON.stringify({
|
|
15972
16735
|
success: false,
|
|
15973
|
-
|
|
15974
|
-
|
|
16736
|
+
language: status.language,
|
|
16737
|
+
error: status.message,
|
|
16738
|
+
alternatives: await getLspStatus(filePath)
|
|
15975
16739
|
}, null, 2);
|
|
15976
16740
|
}
|
|
15977
16741
|
return JSON.stringify({
|
|
15978
16742
|
success: true,
|
|
15979
16743
|
message: `Get code actions at ${filePath}:${line}:${character}`,
|
|
15980
|
-
|
|
16744
|
+
language: status.language,
|
|
15981
16745
|
operation: "textDocument/codeAction",
|
|
16746
|
+
location: { filePath, line, character },
|
|
15982
16747
|
actions: []
|
|
15983
16748
|
}, null, 2);
|
|
15984
16749
|
}
|
|
15985
16750
|
});
|
|
16751
|
+
var lspStatusTool = tool({
|
|
16752
|
+
description: `Check LSP server status and install missing servers.
|
|
16753
|
+
|
|
16754
|
+
**Features:**
|
|
16755
|
+
- Shows installed LSP servers
|
|
16756
|
+
- Auto-installs missing servers
|
|
16757
|
+
- Supports multiple LSP servers per language
|
|
16758
|
+
|
|
16759
|
+
**Parameters:**
|
|
16760
|
+
- filePath: Optional file path to check specific language
|
|
16761
|
+
- install: Set to true to auto-install missing servers
|
|
16762
|
+
|
|
16763
|
+
**Example:**
|
|
16764
|
+
\`\`\`
|
|
16765
|
+
lsp_status({ filePath: "src/index.ts" })
|
|
16766
|
+
lsp_status({ install: true })
|
|
16767
|
+
\`\`\``,
|
|
16768
|
+
args: {
|
|
16769
|
+
filePath: tool.schema.string().optional().describe("Optional file path to check specific language"),
|
|
16770
|
+
install: tool.schema.boolean().optional().default(false).describe("Auto-install missing LSP servers")
|
|
16771
|
+
},
|
|
16772
|
+
async execute({ filePath, install }) {
|
|
16773
|
+
if (filePath) {
|
|
16774
|
+
const lang = getLanguageFromPath(filePath);
|
|
16775
|
+
if (!lang) {
|
|
16776
|
+
return JSON.stringify({
|
|
16777
|
+
success: false,
|
|
16778
|
+
error: `Unsupported file type: ${filePath}`,
|
|
16779
|
+
supportedLanguages: lspManager.getAvailableLanguages()
|
|
16780
|
+
}, null, 2);
|
|
16781
|
+
}
|
|
16782
|
+
const status = await lspManager.checkAndInstall(filePath);
|
|
16783
|
+
if (install && !status.ready) {
|
|
16784
|
+
const result = await ensureLspInstalled(lang);
|
|
16785
|
+
return JSON.stringify({
|
|
16786
|
+
...result,
|
|
16787
|
+
language: lang,
|
|
16788
|
+
installAttempted: true
|
|
16789
|
+
}, null, 2);
|
|
16790
|
+
}
|
|
16791
|
+
return JSON.stringify({
|
|
16792
|
+
success: status.ready,
|
|
16793
|
+
language: status.language,
|
|
16794
|
+
installed: status.installed,
|
|
16795
|
+
ready: status.ready,
|
|
16796
|
+
message: status.message,
|
|
16797
|
+
info: lspManager.getLspInfo(filePath)
|
|
16798
|
+
}, null, 2);
|
|
16799
|
+
}
|
|
16800
|
+
const allStatuses = await getLspStatus();
|
|
16801
|
+
return JSON.stringify({
|
|
16802
|
+
success: true,
|
|
16803
|
+
languages: allStatuses,
|
|
16804
|
+
totalLanguages: allStatuses.length,
|
|
16805
|
+
installedCount: allStatuses.filter((s) => s.installed).length
|
|
16806
|
+
}, null, 2);
|
|
16807
|
+
}
|
|
16808
|
+
});
|
|
16809
|
+
var lspInstallTool = tool({
|
|
16810
|
+
description: `Install LSP server for a specific language.
|
|
16811
|
+
|
|
16812
|
+
**Features:**
|
|
16813
|
+
- Installs primary LSP server
|
|
16814
|
+
- Falls back to alternatives if primary fails
|
|
16815
|
+
- Shows installation progress
|
|
16816
|
+
|
|
16817
|
+
**Parameters:**
|
|
16818
|
+
- language: Language to install LSP for (e.g., "typescript", "python", "rust")
|
|
16819
|
+
|
|
16820
|
+
**Example:**
|
|
16821
|
+
\`\`\`
|
|
16822
|
+
lsp_install({ language: "typescript" })
|
|
16823
|
+
lsp_install({ language: "python" })
|
|
16824
|
+
\`\`\``,
|
|
16825
|
+
args: {
|
|
16826
|
+
language: tool.schema.string().describe("Language to install LSP for")
|
|
16827
|
+
},
|
|
16828
|
+
async execute({ language }) {
|
|
16829
|
+
const result = await ensureLspInstalled(language.toLowerCase());
|
|
16830
|
+
return JSON.stringify({
|
|
16831
|
+
...result,
|
|
16832
|
+
language,
|
|
16833
|
+
installationMethod: result.success ? "auto" : "failed"
|
|
16834
|
+
}, null, 2);
|
|
16835
|
+
}
|
|
16836
|
+
});
|
|
15986
16837
|
|
|
15987
16838
|
// src/tools/skill-mcp.ts
|
|
15988
16839
|
function getSkillMcpConfig(skill) {
|
|
@@ -16066,16 +16917,16 @@ mcp:
|
|
|
16066
16917
|
|
|
16067
16918
|
// src/tools/memory.ts
|
|
16068
16919
|
import * as fs2 from "fs";
|
|
16069
|
-
import * as
|
|
16920
|
+
import * as path3 from "path";
|
|
16070
16921
|
import * as os from "os";
|
|
16071
16922
|
function getGlobalMemoryDir() {
|
|
16072
|
-
return
|
|
16923
|
+
return path3.join(os.homedir(), ".config", "opencode", "hive", "memory", "global");
|
|
16073
16924
|
}
|
|
16074
16925
|
function getProjectMemoryDir(projectRoot) {
|
|
16075
|
-
return
|
|
16926
|
+
return path3.join(projectRoot, ".hive", "memory", "project");
|
|
16076
16927
|
}
|
|
16077
16928
|
function getJournalDir() {
|
|
16078
|
-
return
|
|
16929
|
+
return path3.join(os.homedir(), ".config", "opencode", "hive", "journal");
|
|
16079
16930
|
}
|
|
16080
16931
|
function parseFrontmatter2(content) {
|
|
16081
16932
|
if (!content.startsWith(`---
|
|
@@ -16132,7 +16983,7 @@ ${lines.join(`
|
|
|
16132
16983
|
function readMemoryBlock(filePath, scope) {
|
|
16133
16984
|
const content = fs2.readFileSync(filePath, "utf-8");
|
|
16134
16985
|
const { frontmatter, body } = parseFrontmatter2(content);
|
|
16135
|
-
const label = frontmatter.label ||
|
|
16986
|
+
const label = frontmatter.label || path3.basename(filePath, path3.extname(filePath));
|
|
16136
16987
|
const description = frontmatter.description || "Memory block";
|
|
16137
16988
|
const limit = frontmatter.limit || 5000;
|
|
16138
16989
|
const readOnly = frontmatter.read_only === true;
|
|
@@ -16157,7 +17008,7 @@ function listMemoryBlocks(scope, projectRoot) {
|
|
|
16157
17008
|
const blocks = [];
|
|
16158
17009
|
for (const file2 of fs2.readdirSync(dir)) {
|
|
16159
17010
|
if (file2.endsWith(".md")) {
|
|
16160
|
-
const filePath =
|
|
17011
|
+
const filePath = path3.join(dir, file2);
|
|
16161
17012
|
try {
|
|
16162
17013
|
blocks.push(readMemoryBlock(filePath, scope));
|
|
16163
17014
|
} catch {}
|
|
@@ -16181,7 +17032,7 @@ async function ensureMemorySeeded(projectRoot) {
|
|
|
16181
17032
|
for (const seed of SEED_BLOCKS) {
|
|
16182
17033
|
const dir = seed.scope === "global" ? getGlobalMemoryDir() : getProjectMemoryDir(projectRoot);
|
|
16183
17034
|
fs2.mkdirSync(dir, { recursive: true });
|
|
16184
|
-
const filePath =
|
|
17035
|
+
const filePath = path3.join(dir, `${seed.label}.md`);
|
|
16185
17036
|
if (!fs2.existsSync(filePath)) {
|
|
16186
17037
|
const content = buildFrontmatter({
|
|
16187
17038
|
label: seed.label,
|
|
@@ -16199,7 +17050,7 @@ function writeJournalEntry(title, body, project, tags = []) {
|
|
|
16199
17050
|
fs2.mkdirSync(journalDir, { recursive: true });
|
|
16200
17051
|
const now = new Date;
|
|
16201
17052
|
const id2 = `${now.getUTCFullYear()}${String(now.getUTCMonth() + 1).padStart(2, "0")}${String(now.getUTCDate()).padStart(2, "0")}-${String(now.getUTCHours()).padStart(2, "0")}${String(now.getUTCMinutes()).padStart(2, "0")}${String(now.getUTCSeconds()).padStart(2, "0")}-${String(now.getUTCMilliseconds()).padStart(3, "0")}`;
|
|
16202
|
-
const filePath =
|
|
17053
|
+
const filePath = path3.join(journalDir, `${id2}.md`);
|
|
16203
17054
|
const frontmatter = buildFrontmatter({
|
|
16204
17055
|
title,
|
|
16205
17056
|
project: project || "",
|
|
@@ -16226,7 +17077,7 @@ function searchJournalEntries(query, project, limit = 20) {
|
|
|
16226
17077
|
const entries = [];
|
|
16227
17078
|
const files = fs2.readdirSync(journalDir).filter((f) => f.endsWith(".md")).sort().reverse();
|
|
16228
17079
|
for (const file2 of files) {
|
|
16229
|
-
const filePath =
|
|
17080
|
+
const filePath = path3.join(journalDir, file2);
|
|
16230
17081
|
const content = fs2.readFileSync(filePath, "utf-8");
|
|
16231
17082
|
const { frontmatter, body } = parseFrontmatter2(content);
|
|
16232
17083
|
const entry = {
|
|
@@ -16324,7 +17175,7 @@ var hiveMemorySetTool = tool({
|
|
|
16324
17175
|
}
|
|
16325
17176
|
const dir = scope === "global" ? getGlobalMemoryDir() : getProjectMemoryDir(projectRoot);
|
|
16326
17177
|
fs2.mkdirSync(dir, { recursive: true });
|
|
16327
|
-
const filePath =
|
|
17178
|
+
const filePath = path3.join(dir, `${label}.md`);
|
|
16328
17179
|
if (fs2.existsSync(filePath)) {
|
|
16329
17180
|
const existing = readMemoryBlock(filePath, scope);
|
|
16330
17181
|
if (existing.readOnly) {
|
|
@@ -16362,7 +17213,7 @@ var hiveMemoryReplaceTool = tool({
|
|
|
16362
17213
|
async execute({ scope, label, oldText, newText }) {
|
|
16363
17214
|
const projectRoot = process.cwd();
|
|
16364
17215
|
const dir = scope === "global" ? getGlobalMemoryDir() : getProjectMemoryDir(projectRoot);
|
|
16365
|
-
const filePath =
|
|
17216
|
+
const filePath = path3.join(dir, `${label}.md`);
|
|
16366
17217
|
if (!fs2.existsSync(filePath)) {
|
|
16367
17218
|
return JSON.stringify({
|
|
16368
17219
|
success: false,
|
|
@@ -16486,10 +17337,10 @@ async function buildMemoryInjection(projectRoot) {
|
|
|
16486
17337
|
`);
|
|
16487
17338
|
}
|
|
16488
17339
|
function getTypedMemoryDir() {
|
|
16489
|
-
return
|
|
17340
|
+
return path3.join(os.homedir(), ".config", "opencode", "hive", "typed-memory");
|
|
16490
17341
|
}
|
|
16491
17342
|
function getDeletionsFile() {
|
|
16492
|
-
return
|
|
17343
|
+
return path3.join(getTypedMemoryDir(), "deletions.logfmt");
|
|
16493
17344
|
}
|
|
16494
17345
|
function parseTypedMemoryLine(line) {
|
|
16495
17346
|
const tsMatch = line.match(/ts=([^\s]+)/);
|
|
@@ -16545,7 +17396,7 @@ async function getAllTypedMemories() {
|
|
|
16545
17396
|
for (const filename of files) {
|
|
16546
17397
|
if (filename === "deletions.logfmt")
|
|
16547
17398
|
continue;
|
|
16548
|
-
const filepath =
|
|
17399
|
+
const filepath = path3.join(dir, filename);
|
|
16549
17400
|
const text = fs2.readFileSync(filepath, "utf-8");
|
|
16550
17401
|
lines.push(...text.trim().split(`
|
|
16551
17402
|
`).filter(Boolean));
|
|
@@ -16561,7 +17412,7 @@ async function findTypedMemories(scope, type, query) {
|
|
|
16561
17412
|
for (const filename of files) {
|
|
16562
17413
|
if (filename === "deletions.logfmt")
|
|
16563
17414
|
continue;
|
|
16564
|
-
const filepath =
|
|
17415
|
+
const filepath = path3.join(dir, filename);
|
|
16565
17416
|
const text = fs2.readFileSync(filepath, "utf-8");
|
|
16566
17417
|
const lines = text.split(`
|
|
16567
17418
|
`);
|
|
@@ -16749,7 +17600,7 @@ var hiveMemoryForgetTool = tool({
|
|
|
16749
17600
|
|
|
16750
17601
|
// src/tools/agent-booster.ts
|
|
16751
17602
|
import * as fs3 from "fs";
|
|
16752
|
-
import * as
|
|
17603
|
+
import * as path4 from "path";
|
|
16753
17604
|
var boosterInstance = null;
|
|
16754
17605
|
var boosterInitPromise = null;
|
|
16755
17606
|
async function initBooster() {
|
|
@@ -16907,7 +17758,7 @@ var hiveCodeEditTool = tool({
|
|
|
16907
17758
|
newContent: tool.schema.string().describe("Replacement text")
|
|
16908
17759
|
},
|
|
16909
17760
|
async execute({ path: filePath, oldContent, newContent }) {
|
|
16910
|
-
const resolvedPath =
|
|
17761
|
+
const resolvedPath = path4.isAbsolute(filePath) ? filePath : path4.join(process.cwd(), filePath);
|
|
16911
17762
|
const result = await applyCodeEdit({
|
|
16912
17763
|
path: resolvedPath,
|
|
16913
17764
|
oldContent,
|
|
@@ -16948,7 +17799,7 @@ const newFunction = () => { ... };
|
|
|
16948
17799
|
snippet: tool.schema.string().describe("Code snippet with // ... existing code ... markers")
|
|
16949
17800
|
},
|
|
16950
17801
|
async execute({ path: filePath, snippet }) {
|
|
16951
|
-
const resolvedPath =
|
|
17802
|
+
const resolvedPath = path4.isAbsolute(filePath) ? filePath : path4.join(process.cwd(), filePath);
|
|
16952
17803
|
const available = await isBoosterAvailable();
|
|
16953
17804
|
if (!available) {
|
|
16954
17805
|
return JSON.stringify({
|
|
@@ -17006,7 +17857,7 @@ var hiveBoosterStatusTool = tool({
|
|
|
17006
17857
|
|
|
17007
17858
|
// src/services/vector-memory.ts
|
|
17008
17859
|
import * as fs4 from "fs";
|
|
17009
|
-
import * as
|
|
17860
|
+
import * as path5 from "path";
|
|
17010
17861
|
import * as os2 from "os";
|
|
17011
17862
|
var memoryInstance = null;
|
|
17012
17863
|
var memoryInitPromise = null;
|
|
@@ -17021,7 +17872,7 @@ async function initMemory(options) {
|
|
|
17021
17872
|
memoryInitPromise = (async () => {
|
|
17022
17873
|
try {
|
|
17023
17874
|
const memory = (()=>{throw new Error("Cannot require module "+"@sparkleideas/memory");})();
|
|
17024
|
-
const indexPath = options?.indexPath ||
|
|
17875
|
+
const indexPath = options?.indexPath || path5.join(os2.homedir(), ".config", "opencode", "hive", "vector-index");
|
|
17025
17876
|
const dimensions = options?.dimensions || 384;
|
|
17026
17877
|
fs4.mkdirSync(indexPath, { recursive: true });
|
|
17027
17878
|
if (typeof memory.init === "function") {
|
|
@@ -17125,7 +17976,7 @@ async function getMemoryStatus() {
|
|
|
17125
17976
|
};
|
|
17126
17977
|
}
|
|
17127
17978
|
function getFallbackDir() {
|
|
17128
|
-
return
|
|
17979
|
+
return path5.join(os2.homedir(), ".config", "opencode", "hive", "vector-memory", "fallback");
|
|
17129
17980
|
}
|
|
17130
17981
|
function ensureFallbackDir() {
|
|
17131
17982
|
const dir = getFallbackDir();
|
|
@@ -17146,7 +17997,7 @@ async function addMemoryFallback(content, metadata) {
|
|
|
17146
17997
|
createdAt: new Date().toISOString(),
|
|
17147
17998
|
updatedAt: new Date().toISOString()
|
|
17148
17999
|
};
|
|
17149
|
-
const filePath =
|
|
18000
|
+
const filePath = path5.join(getFallbackDir(), `${id2}.json`);
|
|
17150
18001
|
fs4.writeFileSync(filePath, JSON.stringify(entry, null, 2), "utf-8");
|
|
17151
18002
|
return { id: id2, success: true, fallback: true };
|
|
17152
18003
|
}
|
|
@@ -17158,7 +18009,7 @@ async function searchMemoriesFallback(query, options) {
|
|
|
17158
18009
|
const files = fs4.readdirSync(getFallbackDir()).filter((f) => f.endsWith(".json"));
|
|
17159
18010
|
for (const file2 of files) {
|
|
17160
18011
|
try {
|
|
17161
|
-
const content = fs4.readFileSync(
|
|
18012
|
+
const content = fs4.readFileSync(path5.join(getFallbackDir(), file2), "utf-8");
|
|
17162
18013
|
const entry = JSON.parse(content);
|
|
17163
18014
|
if (type && entry.metadata.type !== type)
|
|
17164
18015
|
continue;
|
|
@@ -17193,7 +18044,7 @@ async function searchMemoriesFallback(query, options) {
|
|
|
17193
18044
|
};
|
|
17194
18045
|
}
|
|
17195
18046
|
async function getMemoryFallback(id2) {
|
|
17196
|
-
const filePath =
|
|
18047
|
+
const filePath = path5.join(getFallbackDir(), `${id2}.json`);
|
|
17197
18048
|
if (!fs4.existsSync(filePath)) {
|
|
17198
18049
|
return null;
|
|
17199
18050
|
}
|
|
@@ -17205,154 +18056,1315 @@ async function getMemoryFallback(id2) {
|
|
|
17205
18056
|
}
|
|
17206
18057
|
}
|
|
17207
18058
|
async function deleteMemoryFallback(id2) {
|
|
17208
|
-
const filePath =
|
|
18059
|
+
const filePath = path5.join(getFallbackDir(), `${id2}.json`);
|
|
17209
18060
|
if (!fs4.existsSync(filePath)) {
|
|
17210
18061
|
return false;
|
|
17211
18062
|
}
|
|
17212
18063
|
try {
|
|
17213
|
-
fs4.unlinkSync(filePath);
|
|
17214
|
-
return true;
|
|
18064
|
+
fs4.unlinkSync(filePath);
|
|
18065
|
+
return true;
|
|
18066
|
+
} catch {
|
|
18067
|
+
return false;
|
|
18068
|
+
}
|
|
18069
|
+
}
|
|
18070
|
+
function getFallbackStats() {
|
|
18071
|
+
ensureFallbackDir();
|
|
18072
|
+
const stats = { total: 0, byType: {} };
|
|
18073
|
+
const files = fs4.readdirSync(getFallbackDir()).filter((f) => f.endsWith(".json"));
|
|
18074
|
+
for (const file2 of files) {
|
|
18075
|
+
try {
|
|
18076
|
+
const content = fs4.readFileSync(path5.join(getFallbackDir(), file2), "utf-8");
|
|
18077
|
+
const entry = JSON.parse(content);
|
|
18078
|
+
stats.total++;
|
|
18079
|
+
const type = entry.metadata.type || "unknown";
|
|
18080
|
+
stats.byType[type] = (stats.byType[type] || 0) + 1;
|
|
18081
|
+
} catch {}
|
|
18082
|
+
}
|
|
18083
|
+
return stats;
|
|
18084
|
+
}
|
|
18085
|
+
var VectorMemoryService = {
|
|
18086
|
+
init: initMemory,
|
|
18087
|
+
add: addMemory,
|
|
18088
|
+
search: searchMemories,
|
|
18089
|
+
get: getMemory,
|
|
18090
|
+
delete: deleteMemory,
|
|
18091
|
+
status: getMemoryStatus
|
|
18092
|
+
};
|
|
18093
|
+
|
|
18094
|
+
// src/tools/vector-memory.ts
|
|
18095
|
+
var hiveVectorSearchTool = tool({
|
|
18096
|
+
description: `Semantic memory search using vector embeddings.
|
|
18097
|
+
|
|
18098
|
+
**Features:**
|
|
18099
|
+
- HNSW indexing for fast similarity search
|
|
18100
|
+
- Semantic matching (finds conceptually similar content)
|
|
18101
|
+
- Filter by type and scope
|
|
18102
|
+
- Fallback to text search if vector unavailable
|
|
18103
|
+
|
|
18104
|
+
**Types:**
|
|
18105
|
+
- decision: Architectural decisions, design choices
|
|
18106
|
+
- learning: Insights, discoveries, patterns found
|
|
18107
|
+
- preference: User preferences, coding style
|
|
18108
|
+
- blocker: Known blockers, workarounds
|
|
18109
|
+
- context: Important context about the project
|
|
18110
|
+
- pattern: Code patterns, recurring solutions`,
|
|
18111
|
+
args: {
|
|
18112
|
+
query: tool.schema.string().describe("Search query (semantic or keyword)"),
|
|
18113
|
+
type: tool.schema.enum(["decision", "learning", "preference", "blocker", "context", "pattern"]).optional().describe("Filter by memory type"),
|
|
18114
|
+
scope: tool.schema.string().optional().describe("Filter by scope (e.g., auth, api, ui)"),
|
|
18115
|
+
limit: tool.schema.number().optional().describe("Maximum results (default: 10)")
|
|
18116
|
+
},
|
|
18117
|
+
async execute({ query, type, scope, limit = 10 }) {
|
|
18118
|
+
const result = await VectorMemoryService.search(query, {
|
|
18119
|
+
limit,
|
|
18120
|
+
type,
|
|
18121
|
+
scope
|
|
18122
|
+
});
|
|
18123
|
+
if (result.results.length === 0) {
|
|
18124
|
+
return JSON.stringify({
|
|
18125
|
+
message: "No matching memories found",
|
|
18126
|
+
query,
|
|
18127
|
+
fallback: result.fallback || false,
|
|
18128
|
+
tips: [
|
|
18129
|
+
"Try different keywords",
|
|
18130
|
+
"Use broader search terms",
|
|
18131
|
+
"Create memories with hive_memory_set first"
|
|
18132
|
+
]
|
|
18133
|
+
}, null, 2);
|
|
18134
|
+
}
|
|
18135
|
+
return JSON.stringify({
|
|
18136
|
+
total: result.results.length,
|
|
18137
|
+
query,
|
|
18138
|
+
fallback: result.fallback || false,
|
|
18139
|
+
results: result.results.map((r) => ({
|
|
18140
|
+
id: r.id,
|
|
18141
|
+
content: r.content,
|
|
18142
|
+
score: Math.round(r.score * 100) / 100,
|
|
18143
|
+
type: r.metadata.type,
|
|
18144
|
+
scope: r.metadata.scope,
|
|
18145
|
+
tags: r.metadata.tags
|
|
18146
|
+
}))
|
|
18147
|
+
}, null, 2);
|
|
18148
|
+
}
|
|
18149
|
+
});
|
|
18150
|
+
var hiveVectorAddTool = tool({
|
|
18151
|
+
description: `Add a memory with semantic indexing for future search.
|
|
18152
|
+
|
|
18153
|
+
**Metadata:**
|
|
18154
|
+
- type: Categorize the memory
|
|
18155
|
+
- scope: Project area or component
|
|
18156
|
+
- tags: Additional categorization
|
|
18157
|
+
|
|
18158
|
+
**Example:**
|
|
18159
|
+
\`\`\`
|
|
18160
|
+
Content: "Use async/await instead of .then() chains"
|
|
18161
|
+
Type: learning
|
|
18162
|
+
Scope: async-patterns
|
|
18163
|
+
Tags: javascript, promises, best-practice
|
|
18164
|
+
\`\`\``,
|
|
18165
|
+
args: {
|
|
18166
|
+
content: tool.schema.string().describe("Memory content to store"),
|
|
18167
|
+
type: tool.schema.enum(["decision", "learning", "preference", "blocker", "context", "pattern"]).optional().describe("Memory type"),
|
|
18168
|
+
scope: tool.schema.string().optional().describe("Scope (e.g., auth, api, ui)"),
|
|
18169
|
+
tags: tool.schema.array(tool.schema.string()).optional().describe("Tags for categorization")
|
|
18170
|
+
},
|
|
18171
|
+
async execute({ content, type, scope, tags }) {
|
|
18172
|
+
const metadata = {};
|
|
18173
|
+
if (type)
|
|
18174
|
+
metadata.type = type;
|
|
18175
|
+
if (scope)
|
|
18176
|
+
metadata.scope = scope;
|
|
18177
|
+
if (tags)
|
|
18178
|
+
metadata.tags = tags;
|
|
18179
|
+
const result = await VectorMemoryService.add(content, metadata);
|
|
18180
|
+
return JSON.stringify({
|
|
18181
|
+
success: result.success,
|
|
18182
|
+
id: result.id,
|
|
18183
|
+
fallback: result.fallback || false,
|
|
18184
|
+
message: `Memory stored${result.fallback ? " (text search mode)" : " (vector indexed)"}`
|
|
18185
|
+
}, null, 2);
|
|
18186
|
+
}
|
|
18187
|
+
});
|
|
18188
|
+
var hiveVectorStatusTool = tool({
|
|
18189
|
+
description: `Check vector memory status and statistics.
|
|
18190
|
+
|
|
18191
|
+
**Returns:**
|
|
18192
|
+
- available: Whether @sparkleideas/memory is working
|
|
18193
|
+
- type: vector or fallback
|
|
18194
|
+
- stats: Memory counts by type`,
|
|
18195
|
+
args: {},
|
|
18196
|
+
async execute() {
|
|
18197
|
+
const status = await VectorMemoryService.status();
|
|
18198
|
+
return JSON.stringify({
|
|
18199
|
+
status: status.available ? "ready" : "fallback",
|
|
18200
|
+
type: status.type,
|
|
18201
|
+
backend: status.available ? "@sparkleideas/memory (HNSW + Vector)" : "Simple text search",
|
|
18202
|
+
stats: status.stats,
|
|
18203
|
+
tips: status.available ? [] : [
|
|
18204
|
+
"Install @sparkleideas/memory for vector search",
|
|
18205
|
+
"npm install @sparkleideas/memory"
|
|
18206
|
+
]
|
|
18207
|
+
}, null, 2);
|
|
18208
|
+
}
|
|
18209
|
+
});
|
|
18210
|
+
|
|
18211
|
+
// src/tools/ast-grep-native.ts
|
|
18212
|
+
import * as fs5 from "fs";
|
|
18213
|
+
var astGrepModule = null;
|
|
18214
|
+
var astGrepInitPromise = null;
|
|
18215
|
+
async function initAstGrep() {
|
|
18216
|
+
if (astGrepModule !== null) {
|
|
18217
|
+
return;
|
|
18218
|
+
}
|
|
18219
|
+
if (astGrepInitPromise !== null) {
|
|
18220
|
+
await astGrepInitPromise;
|
|
18221
|
+
return;
|
|
18222
|
+
}
|
|
18223
|
+
astGrepInitPromise = (async () => {
|
|
18224
|
+
try {
|
|
18225
|
+
astGrepModule = await Promise.resolve().then(() => __toESM(require_napi(), 1));
|
|
18226
|
+
console.log("[ast-grep] Native NAPI initialized successfully");
|
|
18227
|
+
} catch (error45) {
|
|
18228
|
+
console.warn("[ast-grep] Failed to load @ast-grep/napi:", error45 instanceof Error ? error45.message : error45);
|
|
18229
|
+
astGrepModule = null;
|
|
18230
|
+
}
|
|
18231
|
+
})();
|
|
18232
|
+
await astGrepInitPromise;
|
|
18233
|
+
}
|
|
18234
|
+
var astGrepDumpSyntaxTreeTool = tool({
|
|
18235
|
+
description: `Dump code's syntax structure or dump a query's pattern structure.
|
|
18236
|
+
|
|
18237
|
+
This is useful to discover correct syntax kind and syntax tree structure. Call it when debugging a rule.
|
|
18238
|
+
|
|
18239
|
+
**Parameters:**
|
|
18240
|
+
- code: The code you need
|
|
18241
|
+
- language: Programming language (typescript, javascript, python, rust, go, java, etc.)
|
|
18242
|
+
- format: Output format - 'cst' (concrete syntax tree) or 'pattern' (to inspect rule patterns)
|
|
18243
|
+
|
|
18244
|
+
**Use when:**
|
|
18245
|
+
- Debugging AST patterns
|
|
18246
|
+
- Finding correct syntax kind names
|
|
18247
|
+
- Understanding code structure`,
|
|
18248
|
+
args: {
|
|
18249
|
+
code: tool.schema.string().describe("The code to analyze"),
|
|
18250
|
+
language: tool.schema.string().describe("Programming language (typescript, javascript, python, rust, go, java, etc.)"),
|
|
18251
|
+
format: tool.schema.enum(["cst", "pattern"]).default("cst").describe("Output format")
|
|
18252
|
+
},
|
|
18253
|
+
async execute({ code, language, format }) {
|
|
18254
|
+
await initAstGrep();
|
|
18255
|
+
if (!astGrepModule) {
|
|
18256
|
+
return JSON.stringify({
|
|
18257
|
+
success: false,
|
|
18258
|
+
error: "@ast-grep/napi not available",
|
|
18259
|
+
hint: "Install @ast-grep/napi or use MCP-based ast_grep"
|
|
18260
|
+
}, null, 2);
|
|
18261
|
+
}
|
|
18262
|
+
try {
|
|
18263
|
+
const langMap = {
|
|
18264
|
+
typescript: "TypeScript",
|
|
18265
|
+
javascript: "JavaScript",
|
|
18266
|
+
tsx: "Tsx",
|
|
18267
|
+
jsx: "Jsx",
|
|
18268
|
+
python: "Python",
|
|
18269
|
+
rust: "Rust",
|
|
18270
|
+
go: "Go",
|
|
18271
|
+
java: "Java",
|
|
18272
|
+
c: "C",
|
|
18273
|
+
cpp: "Cpp",
|
|
18274
|
+
csharp: "CSharp"
|
|
18275
|
+
};
|
|
18276
|
+
const lang = langMap[language.toLowerCase()] || language;
|
|
18277
|
+
const Lang = astGrepModule.Lang;
|
|
18278
|
+
if (!Lang || !Lang[lang]) {
|
|
18279
|
+
return JSON.stringify({
|
|
18280
|
+
success: false,
|
|
18281
|
+
error: `Unsupported language: ${language}`,
|
|
18282
|
+
availableLanguages: Object.keys(langMap)
|
|
18283
|
+
}, null, 2);
|
|
18284
|
+
}
|
|
18285
|
+
if (format === "pattern") {
|
|
18286
|
+
return JSON.stringify({
|
|
18287
|
+
success: true,
|
|
18288
|
+
format: "pattern",
|
|
18289
|
+
language,
|
|
18290
|
+
example: {
|
|
18291
|
+
match: "AwaitExpression",
|
|
18292
|
+
kind: "Use kind to match AST node types",
|
|
18293
|
+
pattern: "Use pattern for code templates"
|
|
18294
|
+
}
|
|
18295
|
+
}, null, 2);
|
|
18296
|
+
}
|
|
18297
|
+
const parse5 = astGrepModule.parse;
|
|
18298
|
+
const ast = parse5(Lang[lang], code);
|
|
18299
|
+
const root = ast.root();
|
|
18300
|
+
const dump = (node, depth = 0) => {
|
|
18301
|
+
if (!node)
|
|
18302
|
+
return null;
|
|
18303
|
+
return {
|
|
18304
|
+
kind: node.kind(),
|
|
18305
|
+
text: node.text(),
|
|
18306
|
+
children: node.children().map((child) => dump(child, depth + 1))
|
|
18307
|
+
};
|
|
18308
|
+
};
|
|
18309
|
+
return JSON.stringify({
|
|
18310
|
+
success: true,
|
|
18311
|
+
format: "cst",
|
|
18312
|
+
language,
|
|
18313
|
+
tree: dump(root)
|
|
18314
|
+
}, null, 2);
|
|
18315
|
+
} catch (error45) {
|
|
18316
|
+
return JSON.stringify({
|
|
18317
|
+
success: false,
|
|
18318
|
+
error: error45 instanceof Error ? error45.message : String(error45)
|
|
18319
|
+
}, null, 2);
|
|
18320
|
+
}
|
|
18321
|
+
}
|
|
18322
|
+
});
|
|
18323
|
+
var astGrepTestMatchCodeRuleTool = tool({
|
|
18324
|
+
description: `Test a code against an ast-grep YAML rule.
|
|
18325
|
+
|
|
18326
|
+
This is useful to test a rule before using it in a project.
|
|
18327
|
+
|
|
18328
|
+
**Parameters:**
|
|
18329
|
+
- code: The code to test against the rule
|
|
18330
|
+
- yaml: The ast-grep YAML rule to test
|
|
18331
|
+
|
|
18332
|
+
**Returns:**
|
|
18333
|
+
- Whether the rule matched
|
|
18334
|
+
- Matched nodes with locations`,
|
|
18335
|
+
args: {
|
|
18336
|
+
code: tool.schema.string().describe("The code to test against the rule"),
|
|
18337
|
+
yaml: tool.schema.string().describe("The ast-grep YAML rule to search")
|
|
18338
|
+
},
|
|
18339
|
+
async execute({ code, yaml }) {
|
|
18340
|
+
await initAstGrep();
|
|
18341
|
+
if (!astGrepModule) {
|
|
18342
|
+
return JSON.stringify({
|
|
18343
|
+
success: false,
|
|
18344
|
+
error: "@ast-grep/napi not available",
|
|
18345
|
+
hint: "Install @ast-grep/napi or use MCP-based ast_grep"
|
|
18346
|
+
}, null, 2);
|
|
18347
|
+
}
|
|
18348
|
+
try {
|
|
18349
|
+
const parse5 = astGrepModule.parse;
|
|
18350
|
+
const Lang = astGrepModule.Lang;
|
|
18351
|
+
const ast = parse5(Lang.TypeScript, code);
|
|
18352
|
+
const root = ast.root();
|
|
18353
|
+
return JSON.stringify({
|
|
18354
|
+
success: true,
|
|
18355
|
+
matched: false,
|
|
18356
|
+
note: "YAML rule testing requires @ast-grep/cli. Use ast_grep_find_code for pattern-based search.",
|
|
18357
|
+
example: {
|
|
18358
|
+
pattern: "console.log($ARG)",
|
|
18359
|
+
description: "Match console.log with any argument"
|
|
18360
|
+
}
|
|
18361
|
+
}, null, 2);
|
|
18362
|
+
} catch (error45) {
|
|
18363
|
+
return JSON.stringify({
|
|
18364
|
+
success: false,
|
|
18365
|
+
error: error45 instanceof Error ? error45.message : String(error45)
|
|
18366
|
+
}, null, 2);
|
|
18367
|
+
}
|
|
18368
|
+
}
|
|
18369
|
+
});
|
|
18370
|
+
var astGrepFindCodeTool = tool({
|
|
18371
|
+
description: `Find code in a project folder that matches the given ast-grep pattern.
|
|
18372
|
+
|
|
18373
|
+
Pattern is good for simple and single-AST node result. For more complex usage, use ast_grep_scan_code.
|
|
18374
|
+
|
|
18375
|
+
**Parameters:**
|
|
18376
|
+
- project_folder: The absolute path to the project folder
|
|
18377
|
+
- pattern: The ast-grep pattern to search for (e.g., 'console.log($ARG)', '$VAR = $VALUE')
|
|
18378
|
+
- language: Optional - programming language filter
|
|
18379
|
+
|
|
18380
|
+
**Pattern Examples:**
|
|
18381
|
+
- 'console.log($ARG)' - Match console.log with any argument
|
|
18382
|
+
- '$VAR = $VALUE' - Match any assignment
|
|
18383
|
+
- 'function $NAME($PARAMS) { $BODY }' - Match function declarations`,
|
|
18384
|
+
args: {
|
|
18385
|
+
project_folder: tool.schema.string().describe("The absolute path to the project folder"),
|
|
18386
|
+
pattern: tool.schema.string().describe("The ast-grep pattern to search for"),
|
|
18387
|
+
language: tool.schema.string().optional().describe("Programming language filter (typescript, javascript, python, etc.)")
|
|
18388
|
+
},
|
|
18389
|
+
async execute({ project_folder, pattern, language }) {
|
|
18390
|
+
await initAstGrep();
|
|
18391
|
+
if (!astGrepModule) {
|
|
18392
|
+
return JSON.stringify({
|
|
18393
|
+
success: false,
|
|
18394
|
+
error: "@ast-grep/napi not available",
|
|
18395
|
+
hint: "Install @ast-grep/napi or use MCP-based ast_grep"
|
|
18396
|
+
}, null, 2);
|
|
18397
|
+
}
|
|
18398
|
+
try {
|
|
18399
|
+
if (!fs5.existsSync(project_folder)) {
|
|
18400
|
+
return JSON.stringify({
|
|
18401
|
+
success: false,
|
|
18402
|
+
error: `Path not found: ${project_folder}`
|
|
18403
|
+
}, null, 2);
|
|
18404
|
+
}
|
|
18405
|
+
const langMap = {
|
|
18406
|
+
typescript: "TypeScript",
|
|
18407
|
+
javascript: "JavaScript",
|
|
18408
|
+
tsx: "Tsx",
|
|
18409
|
+
jsx: "Jsx",
|
|
18410
|
+
python: "Python",
|
|
18411
|
+
rust: "Rust",
|
|
18412
|
+
go: "Go",
|
|
18413
|
+
java: "Java"
|
|
18414
|
+
};
|
|
18415
|
+
const lang = language ? langMap[language.toLowerCase()] || language : "TypeScript";
|
|
18416
|
+
const Lang = astGrepModule.Lang;
|
|
18417
|
+
if (!Lang[lang]) {
|
|
18418
|
+
return JSON.stringify({
|
|
18419
|
+
success: false,
|
|
18420
|
+
error: `Unsupported language: ${language}`
|
|
18421
|
+
}, null, 2);
|
|
18422
|
+
}
|
|
18423
|
+
const findInFiles = astGrepModule.findInFiles;
|
|
18424
|
+
const results = [];
|
|
18425
|
+
await findInFiles(Lang[lang], {
|
|
18426
|
+
paths: [project_folder],
|
|
18427
|
+
matcher: { rule: { pattern } }
|
|
18428
|
+
}, (err, node) => {
|
|
18429
|
+
if (err) {
|
|
18430
|
+
console.warn("[ast-grep] Search error:", err);
|
|
18431
|
+
return;
|
|
18432
|
+
}
|
|
18433
|
+
if (node) {
|
|
18434
|
+
const text = node.text();
|
|
18435
|
+
const range = node.range();
|
|
18436
|
+
results.push({
|
|
18437
|
+
file: node.filename() || "unknown",
|
|
18438
|
+
line: range ? range.start.index : 0,
|
|
18439
|
+
column: range ? range.start.column : 0,
|
|
18440
|
+
matched: text.slice(0, 100)
|
|
18441
|
+
});
|
|
18442
|
+
}
|
|
18443
|
+
});
|
|
18444
|
+
return JSON.stringify({
|
|
18445
|
+
success: true,
|
|
18446
|
+
count: results.length,
|
|
18447
|
+
matches: results.slice(0, 50)
|
|
18448
|
+
}, null, 2);
|
|
18449
|
+
} catch (error45) {
|
|
18450
|
+
return JSON.stringify({
|
|
18451
|
+
success: false,
|
|
18452
|
+
error: error45 instanceof Error ? error45.message : String(error45)
|
|
18453
|
+
}, null, 2);
|
|
18454
|
+
}
|
|
18455
|
+
}
|
|
18456
|
+
});
|
|
18457
|
+
var astGrepScanCodeTool = tool({
|
|
18458
|
+
description: `Analyze TypeScript/JS code for common bugs, performance issues and best practices.
|
|
18459
|
+
|
|
18460
|
+
Uses AST-based analysis for precise detection without false positives. Essential for maintaining code quality and preventing runtime errors.
|
|
18461
|
+
|
|
18462
|
+
**Detects:**
|
|
18463
|
+
- Type safety violations
|
|
18464
|
+
- Loose object types
|
|
18465
|
+
- Incorrect async patterns
|
|
18466
|
+
- Import style issues
|
|
18467
|
+
- Common bugs
|
|
18468
|
+
|
|
18469
|
+
**Parameters:**
|
|
18470
|
+
- project_folder: Optional - path to scan (defaults to current directory)`,
|
|
18471
|
+
args: {
|
|
18472
|
+
project_folder: tool.schema.string().optional().describe("Path to scan (defaults to current directory)")
|
|
18473
|
+
},
|
|
18474
|
+
async execute({ project_folder }) {
|
|
18475
|
+
await initAstGrep();
|
|
18476
|
+
if (!astGrepModule) {
|
|
18477
|
+
return JSON.stringify({
|
|
18478
|
+
success: false,
|
|
18479
|
+
error: "@ast-grep/napi not available",
|
|
18480
|
+
hint: "Install @ast-grep/napi or use MCP-based ast_grep"
|
|
18481
|
+
}, null, 2);
|
|
18482
|
+
}
|
|
18483
|
+
try {
|
|
18484
|
+
const scanPath = project_folder || process.cwd();
|
|
18485
|
+
if (!fs5.existsSync(scanPath)) {
|
|
18486
|
+
return JSON.stringify({
|
|
18487
|
+
success: false,
|
|
18488
|
+
error: `Path not found: ${scanPath}`
|
|
18489
|
+
}, null, 2);
|
|
18490
|
+
}
|
|
18491
|
+
const bugPatterns = [
|
|
18492
|
+
{ pattern: "await Promise.all($ARR)", severity: "warning", message: "Check if Promise.all is used correctly with async operations" },
|
|
18493
|
+
{ pattern: "JSON.parse($STR)", severity: "info", message: "Consider adding try-catch for JSON.parse" },
|
|
18494
|
+
{ pattern: "$VAR == $VAL", severity: "warning", message: "Use === instead of == for strict equality" }
|
|
18495
|
+
];
|
|
18496
|
+
const issues = [];
|
|
18497
|
+
const Lang = astGrepModule.Lang;
|
|
18498
|
+
const findInFiles = astGrepModule.findInFiles;
|
|
18499
|
+
for (const bug of bugPatterns) {
|
|
18500
|
+
await findInFiles(Lang.TypeScript, {
|
|
18501
|
+
paths: [scanPath],
|
|
18502
|
+
matcher: { rule: { pattern: bug.pattern } }
|
|
18503
|
+
}, (err, node) => {
|
|
18504
|
+
if (err || !node)
|
|
18505
|
+
return;
|
|
18506
|
+
issues.push({
|
|
18507
|
+
file: node.filename() || "unknown",
|
|
18508
|
+
line: node.range()?.start.index || 0,
|
|
18509
|
+
severity: bug.severity,
|
|
18510
|
+
message: bug.message,
|
|
18511
|
+
pattern: bug.pattern
|
|
18512
|
+
});
|
|
18513
|
+
});
|
|
18514
|
+
}
|
|
18515
|
+
return JSON.stringify({
|
|
18516
|
+
success: true,
|
|
18517
|
+
scanned: scanPath,
|
|
18518
|
+
issuesFound: issues.length,
|
|
18519
|
+
issues: issues.slice(0, 20),
|
|
18520
|
+
summary: issues.length === 0 ? "No common issues detected" : `Found ${issues.length} potential issues`
|
|
18521
|
+
}, null, 2);
|
|
18522
|
+
} catch (error45) {
|
|
18523
|
+
return JSON.stringify({
|
|
18524
|
+
success: false,
|
|
18525
|
+
error: error45 instanceof Error ? error45.message : String(error45)
|
|
18526
|
+
}, null, 2);
|
|
18527
|
+
}
|
|
18528
|
+
}
|
|
18529
|
+
});
|
|
18530
|
+
var astGrepRewriteCodeTool = tool({
|
|
18531
|
+
description: `Transform and refactor code using AST-based find-and-replace patterns.
|
|
18532
|
+
|
|
18533
|
+
Use metavariables ($VAR, $$$VARS) in both pattern and replacement.
|
|
18534
|
+
|
|
18535
|
+
**Example:** Find 'console.log($ARG)' and replace with 'logger.info($ARG)'
|
|
18536
|
+
|
|
18537
|
+
**Parameters:**
|
|
18538
|
+
- project_folder: Path to the project folder
|
|
18539
|
+
- pattern: AST pattern to find
|
|
18540
|
+
- replacement: Replacement pattern
|
|
18541
|
+
- language: Programming language (defaults to TypeScript)`,
|
|
18542
|
+
args: {
|
|
18543
|
+
project_folder: tool.schema.string().describe("Path to the project folder"),
|
|
18544
|
+
pattern: tool.schema.string().describe("AST pattern to find"),
|
|
18545
|
+
replacement: tool.schema.string().describe("Replacement pattern"),
|
|
18546
|
+
language: tool.schema.string().optional().default("TypeScript").describe("Programming language")
|
|
18547
|
+
},
|
|
18548
|
+
async execute({ project_folder, pattern, replacement, language }) {
|
|
18549
|
+
await initAstGrep();
|
|
18550
|
+
if (!astGrepModule) {
|
|
18551
|
+
return JSON.stringify({
|
|
18552
|
+
success: false,
|
|
18553
|
+
error: "@ast-grep/napi not available",
|
|
18554
|
+
hint: "Install @ast-grep/napi or use MCP-based ast_grep"
|
|
18555
|
+
}, null, 2);
|
|
18556
|
+
}
|
|
18557
|
+
try {
|
|
18558
|
+
if (!fs5.existsSync(project_folder)) {
|
|
18559
|
+
return JSON.stringify({
|
|
18560
|
+
success: false,
|
|
18561
|
+
error: `Path not found: ${project_folder}`
|
|
18562
|
+
}, null, 2);
|
|
18563
|
+
}
|
|
18564
|
+
const Lang = astGrepModule.Lang;
|
|
18565
|
+
if (!Lang[language]) {
|
|
18566
|
+
return JSON.stringify({
|
|
18567
|
+
success: false,
|
|
18568
|
+
error: `Unsupported language: ${language}`
|
|
18569
|
+
}, null, 2);
|
|
18570
|
+
}
|
|
18571
|
+
return JSON.stringify({
|
|
18572
|
+
success: true,
|
|
18573
|
+
operation: "info",
|
|
18574
|
+
message: "Full rewrite requires @ast-grep/cli with config file",
|
|
18575
|
+
suggestion: "Use ast_grep_find_code to find matches, then hive_code_edit for individual replacements",
|
|
18576
|
+
parameters: {
|
|
18577
|
+
projectFolder: project_folder,
|
|
18578
|
+
pattern,
|
|
18579
|
+
replacement,
|
|
18580
|
+
language
|
|
18581
|
+
}
|
|
18582
|
+
}, null, 2);
|
|
18583
|
+
} catch (error45) {
|
|
18584
|
+
return JSON.stringify({
|
|
18585
|
+
success: false,
|
|
18586
|
+
error: error45 instanceof Error ? error45.message : String(error45)
|
|
18587
|
+
}, null, 2);
|
|
18588
|
+
}
|
|
18589
|
+
}
|
|
18590
|
+
});
|
|
18591
|
+
var astGrepAnalyzeImportsTool = tool({
|
|
18592
|
+
description: `Analyze import statements and dependencies in your codebase.
|
|
18593
|
+
|
|
18594
|
+
Choose "usage" to see which imports are actually used (great for refactoring), or "discovery" to explore all imports and identifiers in the code (great for understanding structure).
|
|
18595
|
+
|
|
18596
|
+
**Parameters:**
|
|
18597
|
+
- mode: "usage" (default) shows where imports are used, "discovery" shows all imports
|
|
18598
|
+
- path: Specific directory or file to analyze (defaults to current directory)`,
|
|
18599
|
+
args: {
|
|
18600
|
+
mode: tool.schema.enum(["usage", "discovery"]).default("usage").describe("Analysis mode"),
|
|
18601
|
+
path: tool.schema.string().optional().describe("Directory or file to analyze")
|
|
18602
|
+
},
|
|
18603
|
+
async execute({ mode, path: path6 }) {
|
|
18604
|
+
await initAstGrep();
|
|
18605
|
+
if (!astGrepModule) {
|
|
18606
|
+
return JSON.stringify({
|
|
18607
|
+
success: false,
|
|
18608
|
+
error: "@ast-grep/napi not available"
|
|
18609
|
+
}, null, 2);
|
|
18610
|
+
}
|
|
18611
|
+
try {
|
|
18612
|
+
const analyzePath = path6 || process.cwd();
|
|
18613
|
+
if (!fs5.existsSync(analyzePath)) {
|
|
18614
|
+
return JSON.stringify({
|
|
18615
|
+
success: false,
|
|
18616
|
+
error: `Path not found: ${analyzePath}`
|
|
18617
|
+
}, null, 2);
|
|
18618
|
+
}
|
|
18619
|
+
const Lang = astGrepModule.Lang;
|
|
18620
|
+
const findInFiles = astGrepModule.findInFiles;
|
|
18621
|
+
const imports = {};
|
|
18622
|
+
await findInFiles(Lang.TypeScript, {
|
|
18623
|
+
paths: [analyzePath],
|
|
18624
|
+
matcher: { rule: { kind: "import_statement" } }
|
|
18625
|
+
}, (err, node) => {
|
|
18626
|
+
if (err || !node)
|
|
18627
|
+
return;
|
|
18628
|
+
const text = node.text();
|
|
18629
|
+
const match = text.match(/from ['"]([^'"]+)['"]/);
|
|
18630
|
+
if (match) {
|
|
18631
|
+
const module = match[1];
|
|
18632
|
+
const file2 = node.filename() || "unknown";
|
|
18633
|
+
if (!imports[module]) {
|
|
18634
|
+
imports[module] = [];
|
|
18635
|
+
}
|
|
18636
|
+
if (!imports[module].includes(file2)) {
|
|
18637
|
+
imports[module].push(file2);
|
|
18638
|
+
}
|
|
18639
|
+
}
|
|
18640
|
+
});
|
|
18641
|
+
if (mode === "usage") {
|
|
18642
|
+
return JSON.stringify({
|
|
18643
|
+
success: true,
|
|
18644
|
+
mode: "usage",
|
|
18645
|
+
imports: Object.entries(imports).map(([module, files]) => ({
|
|
18646
|
+
module,
|
|
18647
|
+
importCount: 1,
|
|
18648
|
+
filesCount: files.length
|
|
18649
|
+
})),
|
|
18650
|
+
note: "Full usage analysis requires @ast-grep/cli"
|
|
18651
|
+
}, null, 2);
|
|
18652
|
+
}
|
|
18653
|
+
return JSON.stringify({
|
|
18654
|
+
success: true,
|
|
18655
|
+
mode: "discovery",
|
|
18656
|
+
totalModules: Object.keys(imports).length,
|
|
18657
|
+
imports: Object.entries(imports).map(([module, files]) => ({
|
|
18658
|
+
module,
|
|
18659
|
+
importCount: files.length,
|
|
18660
|
+
files: files.slice(0, 5)
|
|
18661
|
+
}))
|
|
18662
|
+
}, null, 2);
|
|
18663
|
+
} catch (error45) {
|
|
18664
|
+
return JSON.stringify({
|
|
18665
|
+
success: false,
|
|
18666
|
+
error: error45 instanceof Error ? error45.message : String(error45)
|
|
18667
|
+
}, null, 2);
|
|
18668
|
+
}
|
|
18669
|
+
}
|
|
18670
|
+
});
|
|
18671
|
+
|
|
18672
|
+
// src/tools/hive-doctor.ts
|
|
18673
|
+
import * as fs6 from "fs";
|
|
18674
|
+
import * as path6 from "path";
|
|
18675
|
+
async function checkPackage(packageName) {
|
|
18676
|
+
try {
|
|
18677
|
+
const packageJsonPath = __require.resolve(`${packageName}/package.json`, {
|
|
18678
|
+
paths: [
|
|
18679
|
+
process.cwd(),
|
|
18680
|
+
path6.join(process.cwd(), "node_modules"),
|
|
18681
|
+
path6.join(process.cwd(), "packages/opencode-hive/node_modules")
|
|
18682
|
+
]
|
|
18683
|
+
});
|
|
18684
|
+
if (fs6.existsSync(packageJsonPath)) {
|
|
18685
|
+
const pkg = JSON.parse(fs6.readFileSync(packageJsonPath, "utf-8"));
|
|
18686
|
+
return { installed: true, version: pkg.version };
|
|
18687
|
+
}
|
|
18688
|
+
} catch {}
|
|
18689
|
+
return { installed: false };
|
|
18690
|
+
}
|
|
18691
|
+
function checkOptimizations() {
|
|
18692
|
+
const checks3 = [];
|
|
18693
|
+
const configPaths = [
|
|
18694
|
+
path6.join(process.env.HOME || "", ".config/opencode/agent_hive.json"),
|
|
18695
|
+
path6.join(process.env.HOME || "", ".config/opencode/agent_hive.jsonc")
|
|
18696
|
+
];
|
|
18697
|
+
let config2 = null;
|
|
18698
|
+
for (const configPath of configPaths) {
|
|
18699
|
+
if (fs6.existsSync(configPath)) {
|
|
18700
|
+
try {
|
|
18701
|
+
const content = fs6.readFileSync(configPath, "utf-8");
|
|
18702
|
+
config2 = JSON.parse(content.replace(/\\/g, ""));
|
|
18703
|
+
break;
|
|
18704
|
+
} catch {}
|
|
18705
|
+
}
|
|
18706
|
+
}
|
|
18707
|
+
const snipConfig = config2?.snip;
|
|
18708
|
+
checks3.push({
|
|
18709
|
+
name: "snip",
|
|
18710
|
+
enabled: snipConfig?.enabled === true,
|
|
18711
|
+
recommendation: !snipConfig?.enabled ? "Enable snip in config for 60-90% token reduction on shell output" : undefined
|
|
18712
|
+
});
|
|
18713
|
+
const vectorConfig = config2?.vectorMemory;
|
|
18714
|
+
checks3.push({
|
|
18715
|
+
name: "vectorMemory",
|
|
18716
|
+
enabled: vectorConfig?.enabled === true,
|
|
18717
|
+
recommendation: !vectorConfig?.enabled ? "Enable vector memory for semantic search across memories" : undefined
|
|
18718
|
+
});
|
|
18719
|
+
const boosterConfig = config2?.agentBooster;
|
|
18720
|
+
checks3.push({
|
|
18721
|
+
name: "agentBooster",
|
|
18722
|
+
enabled: boosterConfig?.enabled !== false,
|
|
18723
|
+
recommendation: boosterConfig?.enabled === false ? "Enable agent booster for 52x faster code editing" : undefined
|
|
18724
|
+
});
|
|
18725
|
+
const sandboxConfig = config2?.sandbox;
|
|
18726
|
+
checks3.push({
|
|
18727
|
+
name: "sandbox",
|
|
18728
|
+
enabled: sandboxConfig !== "none",
|
|
18729
|
+
recommendation: sandboxConfig === "none" ? "Enable Docker sandbox for isolated test environments" : undefined
|
|
18730
|
+
});
|
|
18731
|
+
const disabledMcps = config2?.disableMcps || [];
|
|
18732
|
+
const hasAstGrep = !disabledMcps.includes("ast_grep");
|
|
18733
|
+
checks3.push({
|
|
18734
|
+
name: "nativeAstGrep",
|
|
18735
|
+
enabled: hasAstGrep,
|
|
18736
|
+
recommendation: !hasAstGrep ? "Enable native ast-grep for fast AST analysis" : undefined
|
|
18737
|
+
});
|
|
18738
|
+
const hasPareSearch = !disabledMcps.includes("pare_search");
|
|
18739
|
+
checks3.push({
|
|
18740
|
+
name: "pareSearch",
|
|
18741
|
+
enabled: hasPareSearch,
|
|
18742
|
+
recommendation: !hasPareSearch ? "Enable pare_search for structured ripgrep output (65-95% token reduction)" : undefined
|
|
18743
|
+
});
|
|
18744
|
+
return checks3;
|
|
18745
|
+
}
|
|
18746
|
+
function generateRecommendations(dependencies, optimizations) {
|
|
18747
|
+
const recommendations = [];
|
|
18748
|
+
const missingRequired = dependencies.filter((d) => d.required && !d.installed);
|
|
18749
|
+
if (missingRequired.length > 0) {
|
|
18750
|
+
recommendations.push(`Missing required packages: ${missingRequired.map((d) => d.name).join(", ")}`);
|
|
18751
|
+
}
|
|
18752
|
+
const disabledOptimizations = optimizations.filter((o) => !o.enabled && o.recommendation);
|
|
18753
|
+
for (const opt of disabledOptimizations) {
|
|
18754
|
+
if (opt.recommendation) {
|
|
18755
|
+
recommendations.push(opt.recommendation);
|
|
18756
|
+
}
|
|
18757
|
+
}
|
|
18758
|
+
if (recommendations.length === 0) {
|
|
18759
|
+
recommendations.push("System is optimized! No immediate actions needed.");
|
|
18760
|
+
}
|
|
18761
|
+
return recommendations;
|
|
18762
|
+
}
|
|
18763
|
+
function generateQuickFixes(dependencies, optimizations) {
|
|
18764
|
+
const fixes = [];
|
|
18765
|
+
const missingPackages = dependencies.filter((d) => !d.installed && !d.required);
|
|
18766
|
+
for (const pkg of missingPackages) {
|
|
18767
|
+
fixes.push({
|
|
18768
|
+
command: `npm install ${pkg.package}`,
|
|
18769
|
+
description: `Install ${pkg.name}`
|
|
18770
|
+
});
|
|
18771
|
+
}
|
|
18772
|
+
if (optimizations.find((o) => o.name === "snip" && !o.enabled)) {
|
|
18773
|
+
fixes.push({
|
|
18774
|
+
command: 'Add to ~/.config/opencode/agent_hive.json: { "snip": { "enabled": true } }',
|
|
18775
|
+
description: "Enable snip for token reduction"
|
|
18776
|
+
});
|
|
18777
|
+
}
|
|
18778
|
+
if (optimizations.find((o) => o.name === "vectorMemory" && !o.enabled)) {
|
|
18779
|
+
fixes.push({
|
|
18780
|
+
command: 'Add to ~/.config/opencode/agent_hive.json: { "vectorMemory": { "enabled": true } }',
|
|
18781
|
+
description: "Enable vector memory for semantic search"
|
|
18782
|
+
});
|
|
18783
|
+
}
|
|
18784
|
+
return fixes;
|
|
18785
|
+
}
|
|
18786
|
+
function calculateStatus(dependencies, optimizations) {
|
|
18787
|
+
const missingRequired = dependencies.filter((d) => d.required && !d.installed);
|
|
18788
|
+
if (missingRequired.length > 0) {
|
|
18789
|
+
return "issues";
|
|
18790
|
+
}
|
|
18791
|
+
const disabledCount = optimizations.filter((o) => !o.enabled).length;
|
|
18792
|
+
if (disabledCount > 2) {
|
|
18793
|
+
return "warning";
|
|
18794
|
+
}
|
|
18795
|
+
return "healthy";
|
|
18796
|
+
}
|
|
18797
|
+
var hiveDoctorTool = tool({
|
|
18798
|
+
description: `Hive Doctor - System health check and optimization advisor.
|
|
18799
|
+
|
|
18800
|
+
**What it checks:**
|
|
18801
|
+
1. Dependencies - Optional packages installed and working
|
|
18802
|
+
2. Optimizations - Features enabled in config
|
|
18803
|
+
3. Recommendations - Suggestions for improvements
|
|
18804
|
+
|
|
18805
|
+
**Use when:**
|
|
18806
|
+
- Setting up Hive for the first time
|
|
18807
|
+
- Troubleshooting issues
|
|
18808
|
+
- Optimizing performance
|
|
18809
|
+
- Checking if new features are available
|
|
18810
|
+
|
|
18811
|
+
**Example output:**
|
|
18812
|
+
- healthy: All checks pass
|
|
18813
|
+
- warning: Some optimizations disabled
|
|
18814
|
+
- issues: Missing required packages`,
|
|
18815
|
+
args: {},
|
|
18816
|
+
async execute() {
|
|
18817
|
+
const dependencyChecks = [
|
|
18818
|
+
{ name: "agent-booster", package: "@sparkleideas/agent-booster", required: false },
|
|
18819
|
+
{ name: "vector-memory", package: "@sparkleideas/memory", required: false },
|
|
18820
|
+
{ name: "ast-grep NAPI", package: "@ast-grep/napi", required: false },
|
|
18821
|
+
{ name: "pare-search", package: "@paretools/search", required: false },
|
|
18822
|
+
{ name: "context7", package: "@upstash/context7-mcp", required: false },
|
|
18823
|
+
{ name: "Exa search", package: "exa-mcp-server", required: false }
|
|
18824
|
+
];
|
|
18825
|
+
for (const dep of dependencyChecks) {
|
|
18826
|
+
const result2 = await checkPackage(dep.package);
|
|
18827
|
+
dep.installed = result2.installed;
|
|
18828
|
+
dep.version = result2.version;
|
|
18829
|
+
}
|
|
18830
|
+
const optimizationChecks = checkOptimizations();
|
|
18831
|
+
const recommendations = generateRecommendations(dependencyChecks, optimizationChecks);
|
|
18832
|
+
const quickFixes = generateQuickFixes(dependencyChecks, optimizationChecks);
|
|
18833
|
+
const status = calculateStatus(dependencyChecks, optimizationChecks);
|
|
18834
|
+
const result = {
|
|
18835
|
+
status,
|
|
18836
|
+
timestamp: new Date().toISOString(),
|
|
18837
|
+
checks: {
|
|
18838
|
+
dependencies: {
|
|
18839
|
+
total: dependencyChecks.length,
|
|
18840
|
+
installed: dependencyChecks.filter((d) => d.installed).length,
|
|
18841
|
+
packages: dependencyChecks
|
|
18842
|
+
},
|
|
18843
|
+
optimizations: {
|
|
18844
|
+
total: optimizationChecks.length,
|
|
18845
|
+
enabled: optimizationChecks.filter((o) => o.enabled).length,
|
|
18846
|
+
features: optimizationChecks
|
|
18847
|
+
}
|
|
18848
|
+
},
|
|
18849
|
+
recommendations,
|
|
18850
|
+
quickFixes
|
|
18851
|
+
};
|
|
18852
|
+
return JSON.stringify(result, null, 2);
|
|
18853
|
+
}
|
|
18854
|
+
});
|
|
18855
|
+
var hiveDoctorQuickTool = tool({
|
|
18856
|
+
description: `Quick health check - shows status summary only.
|
|
18857
|
+
|
|
18858
|
+
**Returns:**
|
|
18859
|
+
- healthy: All systems go
|
|
18860
|
+
- warning: Some optimizations disabled
|
|
18861
|
+
- issues: Action required`,
|
|
18862
|
+
args: {},
|
|
18863
|
+
async execute() {
|
|
18864
|
+
const keyPackages = [
|
|
18865
|
+
"@ast-grep/napi",
|
|
18866
|
+
"@sparkleideas/agent-booster",
|
|
18867
|
+
"@paretools/search"
|
|
18868
|
+
];
|
|
18869
|
+
const results = {};
|
|
18870
|
+
let healthy = true;
|
|
18871
|
+
for (const pkg of keyPackages) {
|
|
18872
|
+
const result = await checkPackage(pkg);
|
|
18873
|
+
results[pkg] = result.installed;
|
|
18874
|
+
if (!result.installed) {
|
|
18875
|
+
healthy = false;
|
|
18876
|
+
}
|
|
18877
|
+
}
|
|
18878
|
+
return JSON.stringify({
|
|
18879
|
+
status: healthy ? "healthy" : "warning",
|
|
18880
|
+
packages: results,
|
|
18881
|
+
runFullCheck: "Use hive_doctor for detailed analysis"
|
|
18882
|
+
}, null, 2);
|
|
18883
|
+
}
|
|
18884
|
+
});
|
|
18885
|
+
|
|
18886
|
+
// src/tools/dora.ts
|
|
18887
|
+
import { execSync as execSync2 } from "child_process";
|
|
18888
|
+
function checkDoraStatus() {
|
|
18889
|
+
try {
|
|
18890
|
+
const output = execSync2("dora --version", { encoding: "utf-8" });
|
|
18891
|
+
const version2 = output.trim();
|
|
18892
|
+
const indexExists = __require("fs").existsSync(".dora/dora.db");
|
|
18893
|
+
return { installed: true, version: version2, indexed: indexExists };
|
|
18894
|
+
} catch {
|
|
18895
|
+
return { installed: false, indexed: false };
|
|
18896
|
+
}
|
|
18897
|
+
}
|
|
18898
|
+
function runDoraCommand(args2) {
|
|
18899
|
+
try {
|
|
18900
|
+
const output = execSync2(`dora ${args2.join(" ")}`, {
|
|
18901
|
+
encoding: "utf-8",
|
|
18902
|
+
maxBuffer: 10 * 1024 * 1024
|
|
18903
|
+
});
|
|
18904
|
+
return { success: true, output };
|
|
18905
|
+
} catch (error45) {
|
|
18906
|
+
return { success: false, error: error45.message || "Command failed" };
|
|
18907
|
+
}
|
|
18908
|
+
}
|
|
18909
|
+
var doraStatusTool = tool({
|
|
18910
|
+
description: `Check dora installation status and index state.
|
|
18911
|
+
|
|
18912
|
+
**Returns:**
|
|
18913
|
+
- installed: Whether dora CLI is available
|
|
18914
|
+
- version: Dora version
|
|
18915
|
+
- indexed: Whether codebase has been indexed
|
|
18916
|
+
|
|
18917
|
+
**Requirements:**
|
|
18918
|
+
- Install dora: \`bun install -g @butttons/dora\`
|
|
18919
|
+
- Install SCIP indexer: \`npm install -g @sourcegraph/scip-typescript\`
|
|
18920
|
+
- Initialize: \`dora init && dora index\`
|
|
18921
|
+
|
|
18922
|
+
**Note:** Indexing is required once per codebase. After that, dora works instantly.`,
|
|
18923
|
+
args: {},
|
|
18924
|
+
async execute() {
|
|
18925
|
+
const status = checkDoraStatus();
|
|
18926
|
+
if (!status.installed) {
|
|
18927
|
+
return JSON.stringify({
|
|
18928
|
+
status: "not_installed",
|
|
18929
|
+
message: "Dora CLI not found",
|
|
18930
|
+
installation: {
|
|
18931
|
+
step1: "bun install -g @butttons/dora",
|
|
18932
|
+
step2: "npm install -g @sourcegraph/scip-typescript",
|
|
18933
|
+
step3: "dora init && dora index"
|
|
18934
|
+
}
|
|
18935
|
+
}, null, 2);
|
|
18936
|
+
}
|
|
18937
|
+
if (!status.indexed) {
|
|
18938
|
+
return JSON.stringify({
|
|
18939
|
+
status: "not_indexed",
|
|
18940
|
+
version: status.version,
|
|
18941
|
+
message: "Codebase not indexed",
|
|
18942
|
+
nextStep: "Run: dora init && dora index"
|
|
18943
|
+
}, null, 2);
|
|
18944
|
+
}
|
|
18945
|
+
return JSON.stringify({
|
|
18946
|
+
status: "ready",
|
|
18947
|
+
version: status.version,
|
|
18948
|
+
indexed: true,
|
|
18949
|
+
message: "Dora is ready"
|
|
18950
|
+
}, null, 2);
|
|
18951
|
+
}
|
|
18952
|
+
});
|
|
18953
|
+
var doraSymbolTool = tool({
|
|
18954
|
+
description: `Find symbol definitions using dora (SCIP-based).
|
|
18955
|
+
|
|
18956
|
+
**Parameters:**
|
|
18957
|
+
- name: Symbol name to search for
|
|
18958
|
+
- kind: Filter by symbol kind (function, class, method, etc.)
|
|
18959
|
+
|
|
18960
|
+
**Example:**
|
|
18961
|
+
\`\`\`
|
|
18962
|
+
dora_symbol({ name: "getUserById" })
|
|
18963
|
+
\`\`\`
|
|
18964
|
+
|
|
18965
|
+
**Note:** Requires dora to be installed and indexed.`,
|
|
18966
|
+
args: {
|
|
18967
|
+
name: tool.schema.string().describe("Symbol name to search for"),
|
|
18968
|
+
kind: tool.schema.string().optional().describe("Filter by symbol kind (function, class, method, etc.)")
|
|
18969
|
+
},
|
|
18970
|
+
async execute({ name, kind }) {
|
|
18971
|
+
const status = checkDoraStatus();
|
|
18972
|
+
if (!status.installed || !status.indexed) {
|
|
18973
|
+
return JSON.stringify({
|
|
18974
|
+
success: false,
|
|
18975
|
+
error: "Dora not ready. Run dora_status first.",
|
|
18976
|
+
hint: "Install and index: dora init && dora index"
|
|
18977
|
+
}, null, 2);
|
|
18978
|
+
}
|
|
18979
|
+
const args2 = ["symbol", name];
|
|
18980
|
+
if (kind) {
|
|
18981
|
+
args2.push("--kind", kind);
|
|
18982
|
+
}
|
|
18983
|
+
const result = runDoraCommand(args2);
|
|
18984
|
+
if (!result.success) {
|
|
18985
|
+
return JSON.stringify({
|
|
18986
|
+
success: false,
|
|
18987
|
+
error: result.error,
|
|
18988
|
+
hint: "Symbol may not exist or not indexed"
|
|
18989
|
+
}, null, 2);
|
|
18990
|
+
}
|
|
18991
|
+
return JSON.stringify({
|
|
18992
|
+
success: true,
|
|
18993
|
+
symbol: name,
|
|
18994
|
+
output: result.output
|
|
18995
|
+
}, null, 2);
|
|
18996
|
+
}
|
|
18997
|
+
});
|
|
18998
|
+
var doraFileTool = tool({
|
|
18999
|
+
description: `Get file dependencies and information using dora.
|
|
19000
|
+
|
|
19001
|
+
**Parameters:**
|
|
19002
|
+
- path: File path to analyze
|
|
19003
|
+
|
|
19004
|
+
**Example:**
|
|
19005
|
+
\`\`\`
|
|
19006
|
+
dora_file({ path: "src/index.ts" })
|
|
19007
|
+
\`\`\`
|
|
19008
|
+
|
|
19009
|
+
**Returns:** File metadata, exports, and dependencies.`,
|
|
19010
|
+
args: {
|
|
19011
|
+
path: tool.schema.string().describe("File path to analyze")
|
|
19012
|
+
},
|
|
19013
|
+
async execute({ path: path7 }) {
|
|
19014
|
+
const status = checkDoraStatus();
|
|
19015
|
+
if (!status.installed || !status.indexed) {
|
|
19016
|
+
return JSON.stringify({
|
|
19017
|
+
success: false,
|
|
19018
|
+
error: "Dora not ready. Run dora_status first."
|
|
19019
|
+
}, null, 2);
|
|
19020
|
+
}
|
|
19021
|
+
const result = runDoraCommand(["file", path7]);
|
|
19022
|
+
if (!result.success) {
|
|
19023
|
+
return JSON.stringify({
|
|
19024
|
+
success: false,
|
|
19025
|
+
error: result.error,
|
|
19026
|
+
hint: "File may not exist or not indexed"
|
|
19027
|
+
}, null, 2);
|
|
19028
|
+
}
|
|
19029
|
+
return JSON.stringify({
|
|
19030
|
+
success: true,
|
|
19031
|
+
path: path7,
|
|
19032
|
+
output: result.output
|
|
19033
|
+
}, null, 2);
|
|
19034
|
+
}
|
|
19035
|
+
});
|
|
19036
|
+
var doraReferencesTool = tool({
|
|
19037
|
+
description: `Find all references to a symbol using dora.
|
|
19038
|
+
|
|
19039
|
+
**Parameters:**
|
|
19040
|
+
- name: Symbol name to find references for
|
|
19041
|
+
|
|
19042
|
+
**Example:**
|
|
19043
|
+
\`\`\`
|
|
19044
|
+
dora_references({ name: "UserService" })
|
|
19045
|
+
\`\`\`
|
|
19046
|
+
|
|
19047
|
+
**Note:** Returns all usages across the codebase.`,
|
|
19048
|
+
args: {
|
|
19049
|
+
name: tool.schema.string().describe("Symbol name to find references for")
|
|
19050
|
+
},
|
|
19051
|
+
async execute({ name }) {
|
|
19052
|
+
const status = checkDoraStatus();
|
|
19053
|
+
if (!status.installed || !status.indexed) {
|
|
19054
|
+
return JSON.stringify({
|
|
19055
|
+
success: false,
|
|
19056
|
+
error: "Dora not ready. Run dora_status first."
|
|
19057
|
+
}, null, 2);
|
|
19058
|
+
}
|
|
19059
|
+
const result = runDoraCommand(["references", name]);
|
|
19060
|
+
if (!result.success) {
|
|
19061
|
+
return JSON.stringify({
|
|
19062
|
+
success: false,
|
|
19063
|
+
error: result.error
|
|
19064
|
+
}, null, 2);
|
|
19065
|
+
}
|
|
19066
|
+
return JSON.stringify({
|
|
19067
|
+
success: true,
|
|
19068
|
+
symbol: name,
|
|
19069
|
+
output: result.output
|
|
19070
|
+
}, null, 2);
|
|
19071
|
+
}
|
|
19072
|
+
});
|
|
19073
|
+
var doraCyclesTool = tool({
|
|
19074
|
+
description: `Detect circular dependencies in the codebase using dora.
|
|
19075
|
+
|
|
19076
|
+
**Example:**
|
|
19077
|
+
\`\`\`
|
|
19078
|
+
dora_cycles()
|
|
19079
|
+
\`\`\`
|
|
19080
|
+
|
|
19081
|
+
**Returns:** List of circular dependency paths if found.`,
|
|
19082
|
+
args: {},
|
|
19083
|
+
async execute() {
|
|
19084
|
+
const status = checkDoraStatus();
|
|
19085
|
+
if (!status.installed || !status.indexed) {
|
|
19086
|
+
return JSON.stringify({
|
|
19087
|
+
success: false,
|
|
19088
|
+
error: "Dora not ready. Run dora_status first."
|
|
19089
|
+
}, null, 2);
|
|
19090
|
+
}
|
|
19091
|
+
const result = runDoraCommand(["cycles"]);
|
|
19092
|
+
if (!result.success) {
|
|
19093
|
+
return JSON.stringify({
|
|
19094
|
+
success: false,
|
|
19095
|
+
error: result.error
|
|
19096
|
+
}, null, 2);
|
|
19097
|
+
}
|
|
19098
|
+
return JSON.stringify({
|
|
19099
|
+
success: true,
|
|
19100
|
+
cycles: result.output
|
|
19101
|
+
}, null, 2);
|
|
19102
|
+
}
|
|
19103
|
+
});
|
|
19104
|
+
var doraUnusedTool = tool({
|
|
19105
|
+
description: `Find unused/dead code in the codebase using dora.
|
|
19106
|
+
|
|
19107
|
+
**Example:**
|
|
19108
|
+
\`\`\`
|
|
19109
|
+
dora_unused()
|
|
19110
|
+
\`\`\`
|
|
19111
|
+
|
|
19112
|
+
**Returns:** List of symbols with zero references.`,
|
|
19113
|
+
args: {},
|
|
19114
|
+
async execute() {
|
|
19115
|
+
const status = checkDoraStatus();
|
|
19116
|
+
if (!status.installed || !status.indexed) {
|
|
19117
|
+
return JSON.stringify({
|
|
19118
|
+
success: false,
|
|
19119
|
+
error: "Dora not ready. Run dora_status first."
|
|
19120
|
+
}, null, 2);
|
|
19121
|
+
}
|
|
19122
|
+
const result = runDoraCommand(["unused"]);
|
|
19123
|
+
if (!result.success) {
|
|
19124
|
+
return JSON.stringify({
|
|
19125
|
+
success: false,
|
|
19126
|
+
error: result.error
|
|
19127
|
+
}, null, 2);
|
|
19128
|
+
}
|
|
19129
|
+
return JSON.stringify({
|
|
19130
|
+
success: true,
|
|
19131
|
+
unused: result.output
|
|
19132
|
+
}, null, 2);
|
|
19133
|
+
}
|
|
19134
|
+
});
|
|
19135
|
+
|
|
19136
|
+
// src/tools/auto-cr.ts
|
|
19137
|
+
import { execSync as execSync3 } from "child_process";
|
|
19138
|
+
import * as fs7 from "fs";
|
|
19139
|
+
function checkAutoCrStatus() {
|
|
19140
|
+
try {
|
|
19141
|
+
const output = execSync3("auto-cr-cmd --version", { encoding: "utf-8" });
|
|
19142
|
+
const version2 = output.trim();
|
|
19143
|
+
return { installed: true, version: version2 };
|
|
17215
19144
|
} catch {
|
|
17216
|
-
return false;
|
|
19145
|
+
return { installed: false };
|
|
17217
19146
|
}
|
|
17218
19147
|
}
|
|
17219
|
-
function
|
|
17220
|
-
|
|
17221
|
-
|
|
17222
|
-
|
|
17223
|
-
|
|
19148
|
+
function runAutoCr(args2) {
|
|
19149
|
+
try {
|
|
19150
|
+
const allArgs = [...args2, "--output", "json"];
|
|
19151
|
+
const output = execSync3(`auto-cr-cmd ${allArgs.join(" ")}`, {
|
|
19152
|
+
encoding: "utf-8",
|
|
19153
|
+
maxBuffer: 50 * 1024 * 1024
|
|
19154
|
+
});
|
|
17224
19155
|
try {
|
|
17225
|
-
const
|
|
17226
|
-
|
|
17227
|
-
|
|
17228
|
-
|
|
17229
|
-
|
|
17230
|
-
|
|
19156
|
+
const json2 = JSON.parse(output);
|
|
19157
|
+
return { success: true, output, json: json2 };
|
|
19158
|
+
} catch {
|
|
19159
|
+
return { success: true, output };
|
|
19160
|
+
}
|
|
19161
|
+
} catch (error45) {
|
|
19162
|
+
const stderr = error45.stderr || "";
|
|
19163
|
+
const stdout = error45.stdout || "";
|
|
19164
|
+
const combined = stdout + stderr;
|
|
19165
|
+
try {
|
|
19166
|
+
const json2 = JSON.parse(combined);
|
|
19167
|
+
return { success: true, output: combined, json: json2 };
|
|
19168
|
+
} catch {
|
|
19169
|
+
return { success: false, error: combined || error45.message };
|
|
19170
|
+
}
|
|
17231
19171
|
}
|
|
17232
|
-
return stats;
|
|
17233
19172
|
}
|
|
17234
|
-
var
|
|
17235
|
-
|
|
17236
|
-
add: addMemory,
|
|
17237
|
-
search: searchMemories,
|
|
17238
|
-
get: getMemory,
|
|
17239
|
-
delete: deleteMemory,
|
|
17240
|
-
status: getMemoryStatus
|
|
17241
|
-
};
|
|
19173
|
+
var autoCrStatusTool = tool({
|
|
19174
|
+
description: `Check auto-cr-cmd installation status.
|
|
17242
19175
|
|
|
17243
|
-
|
|
17244
|
-
|
|
17245
|
-
|
|
19176
|
+
**Returns:**
|
|
19177
|
+
- installed: Whether auto-cr-cmd is available
|
|
19178
|
+
- version: Auto-CR version
|
|
19179
|
+
- ready: Whether it's ready to scan
|
|
17246
19180
|
|
|
17247
|
-
**
|
|
17248
|
-
|
|
17249
|
-
|
|
17250
|
-
|
|
17251
|
-
|
|
19181
|
+
**Installation:**
|
|
19182
|
+
\`\`\`bash
|
|
19183
|
+
npm install auto-cr-cmd
|
|
19184
|
+
# or
|
|
19185
|
+
pnpm add auto-cr-cmd
|
|
19186
|
+
\`\`\``,
|
|
19187
|
+
args: {},
|
|
19188
|
+
async execute() {
|
|
19189
|
+
const status = checkAutoCrStatus();
|
|
19190
|
+
if (!status.installed) {
|
|
19191
|
+
return JSON.stringify({
|
|
19192
|
+
status: "not_installed",
|
|
19193
|
+
message: "auto-cr-cmd not found",
|
|
19194
|
+
installation: "npm install auto-cr-cmd"
|
|
19195
|
+
}, null, 2);
|
|
19196
|
+
}
|
|
19197
|
+
return JSON.stringify({
|
|
19198
|
+
status: "ready",
|
|
19199
|
+
version: status.version,
|
|
19200
|
+
message: "Auto-CR is ready to scan",
|
|
19201
|
+
rules: [
|
|
19202
|
+
"no-deep-relative-imports",
|
|
19203
|
+
"no-circular-dependencies",
|
|
19204
|
+
"no-swallowed-errors",
|
|
19205
|
+
"no-catastrophic-regex",
|
|
19206
|
+
"no-deep-clone-in-loop",
|
|
19207
|
+
"no-n2-array-lookup"
|
|
19208
|
+
]
|
|
19209
|
+
}, null, 2);
|
|
19210
|
+
}
|
|
19211
|
+
});
|
|
19212
|
+
var autoCrScanTool = tool({
|
|
19213
|
+
description: `Scan directory for code issues using auto-cr (SWC-based static analysis).
|
|
17252
19214
|
|
|
17253
|
-
**
|
|
17254
|
-
-
|
|
17255
|
-
-
|
|
17256
|
-
|
|
17257
|
-
|
|
17258
|
-
-
|
|
17259
|
-
-
|
|
19215
|
+
**Parameters:**
|
|
19216
|
+
- path: Directory path to scan (defaults to ./src)
|
|
19217
|
+
- language: Output language (en/zh, defaults to en)
|
|
19218
|
+
|
|
19219
|
+
**Rules detected:**
|
|
19220
|
+
- no-deep-relative-imports: Import paths exceeding depth limit
|
|
19221
|
+
- no-circular-dependencies: Circular module dependencies
|
|
19222
|
+
- no-swallowed-errors: try-catch blocks that swallow errors
|
|
19223
|
+
- no-catastrophic-regex: Potentially catastrophic regex patterns
|
|
19224
|
+
- no-deep-clone-in-loop: Performance anti-patterns
|
|
19225
|
+
- no-n2-array-lookup: O(n²) array operations
|
|
19226
|
+
|
|
19227
|
+
**Example:**
|
|
19228
|
+
\`\`\`
|
|
19229
|
+
auto_cr_scan({ path: "./src" })
|
|
19230
|
+
\`\`\``,
|
|
17260
19231
|
args: {
|
|
17261
|
-
|
|
17262
|
-
|
|
17263
|
-
scope: tool.schema.string().optional().describe("Filter by scope (e.g., auth, api, ui)"),
|
|
17264
|
-
limit: tool.schema.number().optional().describe("Maximum results (default: 10)")
|
|
19232
|
+
path: tool.schema.string().optional().default("./src").describe("Directory path to scan"),
|
|
19233
|
+
language: tool.schema.string().optional().default("en").describe("Output language (en or zh)")
|
|
17265
19234
|
},
|
|
17266
|
-
async execute({
|
|
17267
|
-
const
|
|
17268
|
-
|
|
17269
|
-
type,
|
|
17270
|
-
scope
|
|
17271
|
-
});
|
|
17272
|
-
if (result.results.length === 0) {
|
|
19235
|
+
async execute({ path: path7, language }) {
|
|
19236
|
+
const status = checkAutoCrStatus();
|
|
19237
|
+
if (!status.installed) {
|
|
17273
19238
|
return JSON.stringify({
|
|
17274
|
-
|
|
17275
|
-
|
|
17276
|
-
|
|
17277
|
-
|
|
17278
|
-
|
|
17279
|
-
|
|
17280
|
-
|
|
17281
|
-
|
|
19239
|
+
success: false,
|
|
19240
|
+
error: "auto-cr-cmd not installed",
|
|
19241
|
+
hint: "npm install auto-cr-cmd"
|
|
19242
|
+
}, null, 2);
|
|
19243
|
+
}
|
|
19244
|
+
if (!fs7.existsSync(path7)) {
|
|
19245
|
+
return JSON.stringify({
|
|
19246
|
+
success: false,
|
|
19247
|
+
error: `Path not found: ${path7}`
|
|
19248
|
+
}, null, 2);
|
|
19249
|
+
}
|
|
19250
|
+
const result = runAutoCr(["--language", language, path7]);
|
|
19251
|
+
if (!result.success && !result.json) {
|
|
19252
|
+
return JSON.stringify({
|
|
19253
|
+
success: false,
|
|
19254
|
+
error: result.error || "Scan failed"
|
|
19255
|
+
}, null, 2);
|
|
19256
|
+
}
|
|
19257
|
+
if (result.json) {
|
|
19258
|
+
const { summary, files, notifications } = result.json;
|
|
19259
|
+
return JSON.stringify({
|
|
19260
|
+
success: true,
|
|
19261
|
+
scanned: path7,
|
|
19262
|
+
summary: {
|
|
19263
|
+
filesScanned: summary?.scannedFiles || 0,
|
|
19264
|
+
filesWithErrors: summary?.filesWithErrors || 0,
|
|
19265
|
+
filesWithWarnings: summary?.filesWithWarnings || 0,
|
|
19266
|
+
totalViolations: summary?.violationTotals?.total || 0
|
|
19267
|
+
},
|
|
19268
|
+
files: files?.map((f) => ({
|
|
19269
|
+
path: f.filePath,
|
|
19270
|
+
violations: f.totalViolations,
|
|
19271
|
+
errors: f.severityCounts?.error || 0,
|
|
19272
|
+
warnings: f.severityCounts?.warning || 0,
|
|
19273
|
+
details: f.violations?.map((v) => ({
|
|
19274
|
+
rule: v.ruleName,
|
|
19275
|
+
severity: v.severity,
|
|
19276
|
+
message: v.message,
|
|
19277
|
+
line: v.line
|
|
19278
|
+
}))
|
|
19279
|
+
})),
|
|
19280
|
+
notifications: notifications || []
|
|
17282
19281
|
}, null, 2);
|
|
17283
19282
|
}
|
|
17284
19283
|
return JSON.stringify({
|
|
17285
|
-
|
|
17286
|
-
|
|
17287
|
-
|
|
17288
|
-
results: result.results.map((r) => ({
|
|
17289
|
-
id: r.id,
|
|
17290
|
-
content: r.content,
|
|
17291
|
-
score: Math.round(r.score * 100) / 100,
|
|
17292
|
-
type: r.metadata.type,
|
|
17293
|
-
scope: r.metadata.scope,
|
|
17294
|
-
tags: r.metadata.tags
|
|
17295
|
-
}))
|
|
19284
|
+
success: true,
|
|
19285
|
+
scanned: path7,
|
|
19286
|
+
rawOutput: result.output
|
|
17296
19287
|
}, null, 2);
|
|
17297
19288
|
}
|
|
17298
19289
|
});
|
|
17299
|
-
var
|
|
17300
|
-
description: `
|
|
19290
|
+
var autoCrDiffTool = tool({
|
|
19291
|
+
description: `Scan git diff output for code issues using auto-cr.
|
|
17301
19292
|
|
|
17302
|
-
**
|
|
17303
|
-
- type: Categorize the memory
|
|
17304
|
-
- scope: Project area or component
|
|
17305
|
-
- tags: Additional categorization
|
|
19293
|
+
**Use case:** Run in CI to check only changed files.
|
|
17306
19294
|
|
|
17307
19295
|
**Example:**
|
|
19296
|
+
\`\`\`bash
|
|
19297
|
+
git diff --name-only -z | xargs -0 auto-cr-cmd --stdin --output json
|
|
17308
19298
|
\`\`\`
|
|
17309
|
-
|
|
17310
|
-
|
|
17311
|
-
Scope: async-patterns
|
|
17312
|
-
Tags: javascript, promises, best-practice
|
|
17313
|
-
\`\`\``,
|
|
19299
|
+
|
|
19300
|
+
**Note:** This tool requires git diff output piped via stdin.`,
|
|
17314
19301
|
args: {
|
|
17315
|
-
|
|
17316
|
-
type: tool.schema.enum(["decision", "learning", "preference", "blocker", "context", "pattern"]).optional().describe("Memory type"),
|
|
17317
|
-
scope: tool.schema.string().optional().describe("Scope (e.g., auth, api, ui)"),
|
|
17318
|
-
tags: tool.schema.array(tool.schema.string()).optional().describe("Tags for categorization")
|
|
19302
|
+
language: tool.schema.string().optional().default("en").describe("Output language (en or zh)")
|
|
17319
19303
|
},
|
|
17320
|
-
async execute({
|
|
17321
|
-
const
|
|
17322
|
-
if (
|
|
17323
|
-
|
|
17324
|
-
|
|
17325
|
-
|
|
17326
|
-
|
|
17327
|
-
|
|
17328
|
-
|
|
19304
|
+
async execute({ language }) {
|
|
19305
|
+
const status = checkAutoCrStatus();
|
|
19306
|
+
if (!status.installed) {
|
|
19307
|
+
return JSON.stringify({
|
|
19308
|
+
success: false,
|
|
19309
|
+
error: "auto-cr-cmd not installed",
|
|
19310
|
+
hint: "npm install auto-cr-cmd"
|
|
19311
|
+
}, null, 2);
|
|
19312
|
+
}
|
|
17329
19313
|
return JSON.stringify({
|
|
17330
|
-
success:
|
|
17331
|
-
|
|
17332
|
-
|
|
17333
|
-
message: `Memory stored${result.fallback ? " (text search mode)" : " (vector indexed)"}`
|
|
19314
|
+
success: true,
|
|
19315
|
+
message: "Use git diff with auto-cr directly",
|
|
19316
|
+
example: "git diff --name-only -z | xargs -0 npx auto-cr-cmd --stdin --output json"
|
|
17334
19317
|
}, null, 2);
|
|
17335
19318
|
}
|
|
17336
19319
|
});
|
|
17337
|
-
var
|
|
17338
|
-
description: `
|
|
19320
|
+
var autoCrRulesTool = tool({
|
|
19321
|
+
description: `List available auto-cr rules and their descriptions.
|
|
17339
19322
|
|
|
17340
|
-
**Returns:**
|
|
17341
|
-
- available: Whether @sparkleideas/memory is working
|
|
17342
|
-
- type: vector or fallback
|
|
17343
|
-
- stats: Memory counts by type`,
|
|
19323
|
+
**Returns:** All built-in rules with descriptions.`,
|
|
17344
19324
|
args: {},
|
|
17345
19325
|
async execute() {
|
|
17346
|
-
const
|
|
19326
|
+
const rules = [
|
|
19327
|
+
{
|
|
19328
|
+
name: "no-deep-relative-imports",
|
|
19329
|
+
severity: "error",
|
|
19330
|
+
description: "Import paths should not exceed maximum depth",
|
|
19331
|
+
example: "Use path aliases (@shared/utils) instead of ../../../../shared/utils"
|
|
19332
|
+
},
|
|
19333
|
+
{
|
|
19334
|
+
name: "no-circular-dependencies",
|
|
19335
|
+
severity: "warning",
|
|
19336
|
+
description: "Detect circular module dependencies",
|
|
19337
|
+
example: "A imports B, B imports A creates a cycle"
|
|
19338
|
+
},
|
|
19339
|
+
{
|
|
19340
|
+
name: "no-swallowed-errors",
|
|
19341
|
+
severity: "warning",
|
|
19342
|
+
description: "try-catch blocks that swallow errors without rethrowing",
|
|
19343
|
+
example: "catch (e) {} without logging or rethrowing"
|
|
19344
|
+
},
|
|
19345
|
+
{
|
|
19346
|
+
name: "no-catastrophic-regex",
|
|
19347
|
+
severity: "error",
|
|
19348
|
+
description: "Potentially catastrophic regex backtracking",
|
|
19349
|
+
example: "Regex with nested quantifiers that can hang"
|
|
19350
|
+
},
|
|
19351
|
+
{
|
|
19352
|
+
name: "no-deep-clone-in-loop",
|
|
19353
|
+
severity: "warning",
|
|
19354
|
+
description: "Performance: deep clone operations inside loops",
|
|
19355
|
+
example: "for loop calling JSON.parse(JSON.stringify())"
|
|
19356
|
+
},
|
|
19357
|
+
{
|
|
19358
|
+
name: "no-n2-array-lookup",
|
|
19359
|
+
severity: "warning",
|
|
19360
|
+
description: "O(n²) array operations",
|
|
19361
|
+
example: "Nested for loops accessing array elements"
|
|
19362
|
+
}
|
|
19363
|
+
];
|
|
17347
19364
|
return JSON.stringify({
|
|
17348
|
-
|
|
17349
|
-
|
|
17350
|
-
|
|
17351
|
-
stats: status.stats,
|
|
17352
|
-
tips: status.available ? [] : [
|
|
17353
|
-
"Install @sparkleideas/memory for vector search",
|
|
17354
|
-
"npm install @sparkleideas/memory"
|
|
17355
|
-
]
|
|
19365
|
+
success: true,
|
|
19366
|
+
rules,
|
|
19367
|
+
totalRules: rules.length
|
|
17356
19368
|
}, null, 2);
|
|
17357
19369
|
}
|
|
17358
19370
|
});
|
|
@@ -18690,12 +20702,26 @@ var astGrepMcp = {
|
|
|
18690
20702
|
command: ["npx", "-y", "@notprolands/ast-grep-mcp"]
|
|
18691
20703
|
};
|
|
18692
20704
|
|
|
20705
|
+
// src/mcp/pare-search.ts
|
|
20706
|
+
var pareSearchMcp = {
|
|
20707
|
+
type: "local",
|
|
20708
|
+
command: ["npx", "-y", "@paretools/search"]
|
|
20709
|
+
};
|
|
20710
|
+
|
|
20711
|
+
// src/mcp/veil.ts
|
|
20712
|
+
var veilMcp = {
|
|
20713
|
+
type: "local",
|
|
20714
|
+
command: ["npx", "-y", "@ushiradineth/veil@latest", "mcp", "server"]
|
|
20715
|
+
};
|
|
20716
|
+
|
|
18693
20717
|
// src/mcp/index.ts
|
|
18694
20718
|
var allBuiltinMcps = {
|
|
18695
20719
|
websearch: websearchMcp,
|
|
18696
20720
|
context7: context7Mcp,
|
|
18697
20721
|
grep_app: grepAppMcp,
|
|
18698
|
-
ast_grep: astGrepMcp
|
|
20722
|
+
ast_grep: astGrepMcp,
|
|
20723
|
+
pare_search: pareSearchMcp,
|
|
20724
|
+
veil: veilMcp
|
|
18699
20725
|
};
|
|
18700
20726
|
var createBuiltinMcps = (disabledMcps = []) => {
|
|
18701
20727
|
const disabled = new Set(disabledMcps);
|
|
@@ -18704,30 +20730,30 @@ var createBuiltinMcps = (disabledMcps = []) => {
|
|
|
18704
20730
|
|
|
18705
20731
|
// ../hive-core/dist/index.js
|
|
18706
20732
|
import { createRequire as createRequire2 } from "node:module";
|
|
18707
|
-
import * as
|
|
20733
|
+
import * as path7 from "path";
|
|
18708
20734
|
import * as os3 from "os";
|
|
18709
20735
|
import * as path22 from "path";
|
|
18710
|
-
import * as
|
|
20736
|
+
import * as fs8 from "fs";
|
|
18711
20737
|
import * as path32 from "path";
|
|
18712
20738
|
import * as fs22 from "fs";
|
|
18713
20739
|
import * as fs32 from "fs";
|
|
18714
20740
|
import * as fs42 from "fs";
|
|
18715
20741
|
import * as fs52 from "fs";
|
|
18716
|
-
import * as
|
|
20742
|
+
import * as fs72 from "fs/promises";
|
|
18717
20743
|
import * as path42 from "path";
|
|
18718
20744
|
import { Buffer as Buffer2 } from "node:buffer";
|
|
18719
|
-
import { spawn } from "child_process";
|
|
20745
|
+
import { spawn as spawn2 } from "child_process";
|
|
18720
20746
|
import { normalize } from "node:path";
|
|
18721
20747
|
import { EventEmitter } from "node:events";
|
|
18722
|
-
import * as
|
|
20748
|
+
import * as fs82 from "fs";
|
|
18723
20749
|
import * as path52 from "path";
|
|
18724
20750
|
import * as fs10 from "fs";
|
|
18725
|
-
import * as
|
|
20751
|
+
import * as path72 from "path";
|
|
18726
20752
|
import * as fs11 from "fs";
|
|
18727
20753
|
import * as path8 from "path";
|
|
18728
20754
|
import { existsSync as existsSync52 } from "fs";
|
|
18729
20755
|
import { join as join92, sep } from "path";
|
|
18730
|
-
import { execSync } from "child_process";
|
|
20756
|
+
import { execSync as execSync4 } from "child_process";
|
|
18731
20757
|
var __create2 = Object.create;
|
|
18732
20758
|
var __getProtoOf2 = Object.getPrototypeOf;
|
|
18733
20759
|
var __defProp2 = Object.defineProperty;
|
|
@@ -19579,9 +21605,10 @@ var DEFAULT_HIVE_CONFIG = {
|
|
|
19579
21605
|
},
|
|
19580
21606
|
vectorMemory: {
|
|
19581
21607
|
enabled: false,
|
|
19582
|
-
indexPath:
|
|
21608
|
+
indexPath: path7.join(os3.homedir(), ".config", "opencode", "hive", "vector-index"),
|
|
19583
21609
|
dimensions: 384
|
|
19584
|
-
}
|
|
21610
|
+
},
|
|
21611
|
+
autoInstallDeps: true
|
|
19585
21612
|
};
|
|
19586
21613
|
var HIVE_DIR = ".hive";
|
|
19587
21614
|
var FEATURES_DIR = "features";
|
|
@@ -19653,22 +21680,22 @@ function getSubtaskReportPath(projectRoot, featureName, taskFolder, subtaskFolde
|
|
|
19653
21680
|
return path22.join(getSubtaskPath(projectRoot, featureName, taskFolder, subtaskFolder), REPORT_FILE);
|
|
19654
21681
|
}
|
|
19655
21682
|
function ensureDir(dirPath) {
|
|
19656
|
-
if (!
|
|
19657
|
-
|
|
21683
|
+
if (!fs8.existsSync(dirPath)) {
|
|
21684
|
+
fs8.mkdirSync(dirPath, { recursive: true });
|
|
19658
21685
|
}
|
|
19659
21686
|
}
|
|
19660
21687
|
function fileExists(filePath) {
|
|
19661
|
-
return
|
|
21688
|
+
return fs8.existsSync(filePath);
|
|
19662
21689
|
}
|
|
19663
21690
|
function readJson(filePath) {
|
|
19664
|
-
if (!
|
|
21691
|
+
if (!fs8.existsSync(filePath))
|
|
19665
21692
|
return null;
|
|
19666
|
-
const content =
|
|
21693
|
+
const content = fs8.readFileSync(filePath, "utf-8");
|
|
19667
21694
|
return JSON.parse(content);
|
|
19668
21695
|
}
|
|
19669
21696
|
function writeJson(filePath, data) {
|
|
19670
21697
|
ensureDir(path22.dirname(filePath));
|
|
19671
|
-
|
|
21698
|
+
fs8.writeFileSync(filePath, JSON.stringify(data, null, 2));
|
|
19672
21699
|
}
|
|
19673
21700
|
var DEFAULT_LOCK_OPTIONS = {
|
|
19674
21701
|
timeout: 5000,
|
|
@@ -19680,7 +21707,7 @@ function getLockPath(filePath) {
|
|
|
19680
21707
|
}
|
|
19681
21708
|
function isLockStale(lockPath, staleTTL) {
|
|
19682
21709
|
try {
|
|
19683
|
-
const stat2 =
|
|
21710
|
+
const stat2 = fs8.statSync(lockPath);
|
|
19684
21711
|
const age = Date.now() - stat2.mtimeMs;
|
|
19685
21712
|
return age > staleTTL;
|
|
19686
21713
|
} catch {
|
|
@@ -19700,12 +21727,12 @@ function acquireLockSync(filePath, options = {}) {
|
|
|
19700
21727
|
ensureDir(lockDir);
|
|
19701
21728
|
while (true) {
|
|
19702
21729
|
try {
|
|
19703
|
-
const fd =
|
|
19704
|
-
|
|
19705
|
-
|
|
21730
|
+
const fd = fs8.openSync(lockPath, fs8.constants.O_CREAT | fs8.constants.O_EXCL | fs8.constants.O_WRONLY);
|
|
21731
|
+
fs8.writeSync(fd, lockContent);
|
|
21732
|
+
fs8.closeSync(fd);
|
|
19706
21733
|
return () => {
|
|
19707
21734
|
try {
|
|
19708
|
-
|
|
21735
|
+
fs8.unlinkSync(lockPath);
|
|
19709
21736
|
} catch {}
|
|
19710
21737
|
};
|
|
19711
21738
|
} catch (err) {
|
|
@@ -19715,7 +21742,7 @@ function acquireLockSync(filePath, options = {}) {
|
|
|
19715
21742
|
} else if (error45.code === "EEXIST") {
|
|
19716
21743
|
if (isLockStale(lockPath, opts.staleLockTTL)) {
|
|
19717
21744
|
try {
|
|
19718
|
-
|
|
21745
|
+
fs8.unlinkSync(lockPath);
|
|
19719
21746
|
continue;
|
|
19720
21747
|
} catch {}
|
|
19721
21748
|
}
|
|
@@ -19734,11 +21761,11 @@ function writeAtomic(filePath, content) {
|
|
|
19734
21761
|
ensureDir(path22.dirname(filePath));
|
|
19735
21762
|
const tempPath = `${filePath}.tmp.${process.pid}.${Date.now()}`;
|
|
19736
21763
|
try {
|
|
19737
|
-
|
|
19738
|
-
|
|
21764
|
+
fs8.writeFileSync(tempPath, content);
|
|
21765
|
+
fs8.renameSync(tempPath, filePath);
|
|
19739
21766
|
} catch (error45) {
|
|
19740
21767
|
try {
|
|
19741
|
-
|
|
21768
|
+
fs8.unlinkSync(tempPath);
|
|
19742
21769
|
} catch {}
|
|
19743
21770
|
throw error45;
|
|
19744
21771
|
}
|
|
@@ -19773,13 +21800,13 @@ function patchJsonLockedSync(filePath, patch, options = {}) {
|
|
|
19773
21800
|
}
|
|
19774
21801
|
}
|
|
19775
21802
|
function readText(filePath) {
|
|
19776
|
-
if (!
|
|
21803
|
+
if (!fs8.existsSync(filePath))
|
|
19777
21804
|
return null;
|
|
19778
|
-
return
|
|
21805
|
+
return fs8.readFileSync(filePath, "utf-8");
|
|
19779
21806
|
}
|
|
19780
21807
|
function writeText(filePath, content) {
|
|
19781
21808
|
ensureDir(path22.dirname(filePath));
|
|
19782
|
-
|
|
21809
|
+
fs8.writeFileSync(filePath, content);
|
|
19783
21810
|
}
|
|
19784
21811
|
function detectContext(cwd) {
|
|
19785
21812
|
const result = {
|
|
@@ -21870,7 +23897,7 @@ var init_git_executor_chain = __esm2({
|
|
|
21870
23897
|
rejection = reason || rejection;
|
|
21871
23898
|
}
|
|
21872
23899
|
});
|
|
21873
|
-
const spawned =
|
|
23900
|
+
const spawned = spawn2(command, args2, spawnOptions);
|
|
21874
23901
|
spawned.stdout.on("data", onDataReceived(stdOut, "stdOut", logger, outputLogger.step("stdOut")));
|
|
21875
23902
|
spawned.stderr.on("data", onDataReceived(stdErr, "stdErr", logger, outputLogger.step("stdErr")));
|
|
21876
23903
|
spawned.on("error", onErrorReceived(stdErr, logger));
|
|
@@ -24614,7 +26641,7 @@ class WorktreeService {
|
|
|
24614
26641
|
const featurePath = path42.join(this.config.hiveDir, "features", feature);
|
|
24615
26642
|
const tasksPath = path42.join(featurePath, "tasks", step, "status.json");
|
|
24616
26643
|
try {
|
|
24617
|
-
await
|
|
26644
|
+
await fs72.access(tasksPath);
|
|
24618
26645
|
return tasksPath;
|
|
24619
26646
|
} catch {}
|
|
24620
26647
|
return path42.join(featurePath, "execution", step, "status.json");
|
|
@@ -24626,7 +26653,7 @@ class WorktreeService {
|
|
|
24626
26653
|
const worktreePath = this.getWorktreePath(feature, step);
|
|
24627
26654
|
const branchName = this.getBranchName(feature, step);
|
|
24628
26655
|
const git = this.getGit();
|
|
24629
|
-
await
|
|
26656
|
+
await fs72.mkdir(path42.dirname(worktreePath), { recursive: true });
|
|
24630
26657
|
const base = baseBranch || (await git.revparse(["HEAD"])).trim();
|
|
24631
26658
|
const existing = await this.get(feature, step);
|
|
24632
26659
|
if (existing) {
|
|
@@ -24655,7 +26682,7 @@ class WorktreeService {
|
|
|
24655
26682
|
const worktreePath = this.getWorktreePath(feature, step);
|
|
24656
26683
|
const branchName = this.getBranchName(feature, step);
|
|
24657
26684
|
try {
|
|
24658
|
-
await
|
|
26685
|
+
await fs72.access(worktreePath);
|
|
24659
26686
|
const worktreeGit = this.getGit(worktreePath);
|
|
24660
26687
|
const commit = (await worktreeGit.revparse(["HEAD"])).trim();
|
|
24661
26688
|
return {
|
|
@@ -24675,7 +26702,7 @@ class WorktreeService {
|
|
|
24675
26702
|
let base = baseCommit;
|
|
24676
26703
|
if (!base) {
|
|
24677
26704
|
try {
|
|
24678
|
-
const status = JSON.parse(await
|
|
26705
|
+
const status = JSON.parse(await fs72.readFile(statusPath, "utf-8"));
|
|
24679
26706
|
base = status.baseCommit;
|
|
24680
26707
|
} catch {}
|
|
24681
26708
|
}
|
|
@@ -24725,7 +26752,7 @@ class WorktreeService {
|
|
|
24725
26752
|
const base = baseBranch || "HEAD~1";
|
|
24726
26753
|
const worktreeGit = this.getGit(worktreePath);
|
|
24727
26754
|
const diff = await worktreeGit.diff([`${base}...HEAD`]);
|
|
24728
|
-
await
|
|
26755
|
+
await fs72.writeFile(patchPath, diff);
|
|
24729
26756
|
return patchPath;
|
|
24730
26757
|
}
|
|
24731
26758
|
async applyDiff(feature, step, baseBranch) {
|
|
@@ -24735,13 +26762,13 @@ class WorktreeService {
|
|
|
24735
26762
|
}
|
|
24736
26763
|
const patchPath = path42.join(this.config.hiveDir, ".worktrees", feature, `${step}.patch`);
|
|
24737
26764
|
try {
|
|
24738
|
-
await
|
|
26765
|
+
await fs72.writeFile(patchPath, diffContent);
|
|
24739
26766
|
const git = this.getGit();
|
|
24740
26767
|
await git.applyPatch(patchPath);
|
|
24741
|
-
await
|
|
26768
|
+
await fs72.unlink(patchPath).catch(() => {});
|
|
24742
26769
|
return { success: true, filesAffected: filesChanged };
|
|
24743
26770
|
} catch (error45) {
|
|
24744
|
-
await
|
|
26771
|
+
await fs72.unlink(patchPath).catch(() => {});
|
|
24745
26772
|
const err = error45;
|
|
24746
26773
|
return {
|
|
24747
26774
|
success: false,
|
|
@@ -24757,13 +26784,13 @@ class WorktreeService {
|
|
|
24757
26784
|
}
|
|
24758
26785
|
const patchPath = path42.join(this.config.hiveDir, ".worktrees", feature, `${step}.patch`);
|
|
24759
26786
|
try {
|
|
24760
|
-
await
|
|
26787
|
+
await fs72.writeFile(patchPath, diffContent);
|
|
24761
26788
|
const git = this.getGit();
|
|
24762
26789
|
await git.applyPatch(patchPath, ["-R"]);
|
|
24763
|
-
await
|
|
26790
|
+
await fs72.unlink(patchPath).catch(() => {});
|
|
24764
26791
|
return { success: true, filesAffected: filesChanged };
|
|
24765
26792
|
} catch (error45) {
|
|
24766
|
-
await
|
|
26793
|
+
await fs72.unlink(patchPath).catch(() => {});
|
|
24767
26794
|
const err = error45;
|
|
24768
26795
|
return {
|
|
24769
26796
|
success: false,
|
|
@@ -24782,7 +26809,7 @@ class WorktreeService {
|
|
|
24782
26809
|
return [...new Set(files)];
|
|
24783
26810
|
}
|
|
24784
26811
|
async revertFromSavedDiff(diffPath) {
|
|
24785
|
-
const diffContent = await
|
|
26812
|
+
const diffContent = await fs72.readFile(diffPath, "utf-8");
|
|
24786
26813
|
if (!diffContent.trim()) {
|
|
24787
26814
|
return { success: true, filesAffected: [] };
|
|
24788
26815
|
}
|
|
@@ -24807,7 +26834,7 @@ class WorktreeService {
|
|
|
24807
26834
|
try {
|
|
24808
26835
|
await git.raw(["worktree", "remove", worktreePath, "--force"]);
|
|
24809
26836
|
} catch {
|
|
24810
|
-
await
|
|
26837
|
+
await fs72.rm(worktreePath, { recursive: true, force: true });
|
|
24811
26838
|
}
|
|
24812
26839
|
try {
|
|
24813
26840
|
await git.raw(["worktree", "prune"]);
|
|
@@ -24822,13 +26849,13 @@ class WorktreeService {
|
|
|
24822
26849
|
const worktreesDir = this.getWorktreesDir();
|
|
24823
26850
|
const results = [];
|
|
24824
26851
|
try {
|
|
24825
|
-
const features = feature ? [feature] : await
|
|
26852
|
+
const features = feature ? [feature] : await fs72.readdir(worktreesDir);
|
|
24826
26853
|
for (const feat of features) {
|
|
24827
26854
|
const featurePath = path42.join(worktreesDir, feat);
|
|
24828
|
-
const stat2 = await
|
|
26855
|
+
const stat2 = await fs72.stat(featurePath).catch(() => null);
|
|
24829
26856
|
if (!stat2?.isDirectory())
|
|
24830
26857
|
continue;
|
|
24831
|
-
const steps = await
|
|
26858
|
+
const steps = await fs72.readdir(featurePath).catch(() => []);
|
|
24832
26859
|
for (const step of steps) {
|
|
24833
26860
|
const info = await this.get(feat, step);
|
|
24834
26861
|
if (info) {
|
|
@@ -24846,16 +26873,16 @@ class WorktreeService {
|
|
|
24846
26873
|
await git.raw(["worktree", "prune"]);
|
|
24847
26874
|
} catch {}
|
|
24848
26875
|
const worktreesDir = this.getWorktreesDir();
|
|
24849
|
-
const features = feature ? [feature] : await
|
|
26876
|
+
const features = feature ? [feature] : await fs72.readdir(worktreesDir).catch(() => []);
|
|
24850
26877
|
for (const feat of features) {
|
|
24851
26878
|
const featurePath = path42.join(worktreesDir, feat);
|
|
24852
|
-
const stat2 = await
|
|
26879
|
+
const stat2 = await fs72.stat(featurePath).catch(() => null);
|
|
24853
26880
|
if (!stat2?.isDirectory())
|
|
24854
26881
|
continue;
|
|
24855
|
-
const steps = await
|
|
26882
|
+
const steps = await fs72.readdir(featurePath).catch(() => []);
|
|
24856
26883
|
for (const step of steps) {
|
|
24857
26884
|
const worktreePath = path42.join(featurePath, step);
|
|
24858
|
-
const stepStat = await
|
|
26885
|
+
const stepStat = await fs72.stat(worktreePath).catch(() => null);
|
|
24859
26886
|
if (!stepStat?.isDirectory())
|
|
24860
26887
|
continue;
|
|
24861
26888
|
try {
|
|
@@ -24876,13 +26903,13 @@ class WorktreeService {
|
|
|
24876
26903
|
}
|
|
24877
26904
|
const patchPath = path42.join(this.config.hiveDir, ".worktrees", feature, `${step}-check.patch`);
|
|
24878
26905
|
try {
|
|
24879
|
-
await
|
|
26906
|
+
await fs72.writeFile(patchPath, diffContent);
|
|
24880
26907
|
const git = this.getGit();
|
|
24881
26908
|
await git.applyPatch(patchPath, ["--check"]);
|
|
24882
|
-
await
|
|
26909
|
+
await fs72.unlink(patchPath).catch(() => {});
|
|
24883
26910
|
return [];
|
|
24884
26911
|
} catch (error45) {
|
|
24885
|
-
await
|
|
26912
|
+
await fs72.unlink(patchPath).catch(() => {});
|
|
24886
26913
|
const err = error45;
|
|
24887
26914
|
const stderr = err.message || "";
|
|
24888
26915
|
const conflicts2 = stderr.split(`
|
|
@@ -24895,7 +26922,7 @@ class WorktreeService {
|
|
|
24895
26922
|
}
|
|
24896
26923
|
async checkConflictsFromSavedDiff(diffPath, reverse = false) {
|
|
24897
26924
|
try {
|
|
24898
|
-
await
|
|
26925
|
+
await fs72.access(diffPath);
|
|
24899
26926
|
} catch {
|
|
24900
26927
|
return [];
|
|
24901
26928
|
}
|
|
@@ -24918,7 +26945,7 @@ class WorktreeService {
|
|
|
24918
26945
|
async commitChanges(feature, step, message) {
|
|
24919
26946
|
const worktreePath = this.getWorktreePath(feature, step);
|
|
24920
26947
|
try {
|
|
24921
|
-
await
|
|
26948
|
+
await fs72.access(worktreePath);
|
|
24922
26949
|
} catch {
|
|
24923
26950
|
return { committed: false, sha: "", message: "Worktree not found" };
|
|
24924
26951
|
}
|
|
@@ -25064,10 +27091,10 @@ class ContextService {
|
|
|
25064
27091
|
const contextPath = getContextPath(this.projectRoot, featureName);
|
|
25065
27092
|
if (!fileExists(contextPath))
|
|
25066
27093
|
return [];
|
|
25067
|
-
const files =
|
|
27094
|
+
const files = fs82.readdirSync(contextPath, { withFileTypes: true }).filter((f) => f.isFile() && f.name.endsWith(".md")).map((f) => f.name);
|
|
25068
27095
|
return files.map((name) => {
|
|
25069
27096
|
const filePath = path52.join(contextPath, name);
|
|
25070
|
-
const stat2 =
|
|
27097
|
+
const stat2 = fs82.statSync(filePath);
|
|
25071
27098
|
const content = readText(filePath) || "";
|
|
25072
27099
|
return {
|
|
25073
27100
|
name: name.replace(/\.md$/, ""),
|
|
@@ -25080,7 +27107,7 @@ class ContextService {
|
|
|
25080
27107
|
const contextPath = getContextPath(this.projectRoot, featureName);
|
|
25081
27108
|
const filePath = path52.join(contextPath, this.normalizeFileName(fileName));
|
|
25082
27109
|
if (fileExists(filePath)) {
|
|
25083
|
-
|
|
27110
|
+
fs82.unlinkSync(filePath);
|
|
25084
27111
|
return true;
|
|
25085
27112
|
}
|
|
25086
27113
|
return false;
|
|
@@ -25111,8 +27138,8 @@ ${f.content}`);
|
|
|
25111
27138
|
const archiveName = `${timestamp}_${ctx.name}.md`;
|
|
25112
27139
|
const src = path52.join(contextPath, `${ctx.name}.md`);
|
|
25113
27140
|
const dest = path52.join(archiveDir, archiveName);
|
|
25114
|
-
|
|
25115
|
-
|
|
27141
|
+
fs82.copyFileSync(src, dest);
|
|
27142
|
+
fs82.unlinkSync(src);
|
|
25116
27143
|
archived.push(ctx.name);
|
|
25117
27144
|
}
|
|
25118
27145
|
return { archived, archivePath: archiveDir };
|
|
@@ -25140,8 +27167,8 @@ class ConfigService {
|
|
|
25140
27167
|
cachedCustomAgentConfigs = null;
|
|
25141
27168
|
constructor() {
|
|
25142
27169
|
const homeDir = process.env.HOME || process.env.USERPROFILE || "";
|
|
25143
|
-
const configDir =
|
|
25144
|
-
this.configPath =
|
|
27170
|
+
const configDir = path72.join(homeDir, ".config", "opencode");
|
|
27171
|
+
this.configPath = path72.join(configDir, "agent_hive.json");
|
|
25145
27172
|
}
|
|
25146
27173
|
getPath() {
|
|
25147
27174
|
return this.configPath;
|
|
@@ -25204,7 +27231,7 @@ class ConfigService {
|
|
|
25204
27231
|
...updates.customAgents
|
|
25205
27232
|
} : current.customAgents
|
|
25206
27233
|
};
|
|
25207
|
-
const configDir =
|
|
27234
|
+
const configDir = path72.dirname(this.configPath);
|
|
25208
27235
|
if (!fs10.existsSync(configDir)) {
|
|
25209
27236
|
fs10.mkdirSync(configDir, { recursive: true });
|
|
25210
27237
|
}
|
|
@@ -25592,10 +27619,10 @@ class DockerSandboxService {
|
|
|
25592
27619
|
static ensureContainer(worktreePath, image) {
|
|
25593
27620
|
const name = this.containerName(worktreePath);
|
|
25594
27621
|
try {
|
|
25595
|
-
|
|
27622
|
+
execSync4(`docker inspect --format='{{.State.Running}}' ${name}`, { stdio: "pipe" });
|
|
25596
27623
|
return name;
|
|
25597
27624
|
} catch {
|
|
25598
|
-
|
|
27625
|
+
execSync4(`docker run -d --name ${name} -v ${worktreePath}:/app -w /app ${image} tail -f /dev/null`, { stdio: "pipe" });
|
|
25599
27626
|
return name;
|
|
25600
27627
|
}
|
|
25601
27628
|
}
|
|
@@ -25606,12 +27633,12 @@ class DockerSandboxService {
|
|
|
25606
27633
|
static stopContainer(worktreePath) {
|
|
25607
27634
|
const name = this.containerName(worktreePath);
|
|
25608
27635
|
try {
|
|
25609
|
-
|
|
27636
|
+
execSync4(`docker rm -f ${name}`, { stdio: "ignore" });
|
|
25610
27637
|
} catch {}
|
|
25611
27638
|
}
|
|
25612
27639
|
static isDockerAvailable() {
|
|
25613
27640
|
try {
|
|
25614
|
-
|
|
27641
|
+
execSync4("docker info", { stdio: "ignore" });
|
|
25615
27642
|
return true;
|
|
25616
27643
|
} catch {
|
|
25617
27644
|
return false;
|
|
@@ -26130,15 +28157,15 @@ function applyContextBudget(files, config2 = {}) {
|
|
|
26130
28157
|
}
|
|
26131
28158
|
|
|
26132
28159
|
// src/utils/prompt-file.ts
|
|
26133
|
-
import * as
|
|
26134
|
-
import * as
|
|
28160
|
+
import * as fs9 from "fs";
|
|
28161
|
+
import * as path9 from "path";
|
|
26135
28162
|
function writeWorkerPromptFile(feature, task, prompt, hiveDir) {
|
|
26136
|
-
const promptDir =
|
|
26137
|
-
const promptPath =
|
|
26138
|
-
if (!
|
|
26139
|
-
|
|
28163
|
+
const promptDir = path9.join(hiveDir, "features", feature, "tasks", task);
|
|
28164
|
+
const promptPath = path9.join(promptDir, "worker-prompt.md");
|
|
28165
|
+
if (!fs9.existsSync(promptDir)) {
|
|
28166
|
+
fs9.mkdirSync(promptDir, { recursive: true });
|
|
26140
28167
|
}
|
|
26141
|
-
|
|
28168
|
+
fs9.writeFileSync(promptPath, prompt, "utf-8");
|
|
26142
28169
|
return promptPath;
|
|
26143
28170
|
}
|
|
26144
28171
|
|
|
@@ -26191,6 +28218,183 @@ function buildCompactionPrompt() {
|
|
|
26191
28218
|
return COMPACTION_RESUME_PROMPT;
|
|
26192
28219
|
}
|
|
26193
28220
|
|
|
28221
|
+
// src/utils/dep-installer.ts
|
|
28222
|
+
import { execSync as execSync5 } from "child_process";
|
|
28223
|
+
import * as path11 from "path";
|
|
28224
|
+
import * as os4 from "os";
|
|
28225
|
+
var PLUGIN_TOOLS = [
|
|
28226
|
+
{
|
|
28227
|
+
name: "btca",
|
|
28228
|
+
npmPackage: "btca-cli",
|
|
28229
|
+
installCommand: ["npm", "install", "-g", "btca-cli"],
|
|
28230
|
+
verifyCommand: "btca --version",
|
|
28231
|
+
description: "Bluetooth Classic Audio control",
|
|
28232
|
+
required: false
|
|
28233
|
+
},
|
|
28234
|
+
{
|
|
28235
|
+
name: "dora",
|
|
28236
|
+
npmPackage: "@butttons/dora",
|
|
28237
|
+
installCommand: ["npm", "install", "-g", "@butttons/dora"],
|
|
28238
|
+
verifyCommand: "dora --version",
|
|
28239
|
+
description: "SCIP-based code navigation",
|
|
28240
|
+
required: false
|
|
28241
|
+
},
|
|
28242
|
+
{
|
|
28243
|
+
name: "auto-cr",
|
|
28244
|
+
npmPackage: "auto-cr-cmd",
|
|
28245
|
+
installCommand: ["npm", "install", "-g", "auto-cr-cmd"],
|
|
28246
|
+
verifyCommand: "auto-cr-cmd --version",
|
|
28247
|
+
description: "SWC-based automated code review",
|
|
28248
|
+
required: false
|
|
28249
|
+
},
|
|
28250
|
+
{
|
|
28251
|
+
name: "scip-typescript",
|
|
28252
|
+
npmPackage: "@sourcegraph/scip-typescript",
|
|
28253
|
+
installCommand: ["npm", "install", "-g", "@sourcegraph/scip-typescript"],
|
|
28254
|
+
verifyCommand: "scip-typescript --version",
|
|
28255
|
+
description: "TypeScript SCIP indexer (for dora)",
|
|
28256
|
+
required: false
|
|
28257
|
+
},
|
|
28258
|
+
{
|
|
28259
|
+
name: "typescript-language-server",
|
|
28260
|
+
npmPackage: "typescript-language-server",
|
|
28261
|
+
installCommand: ["npm", "install", "-g", "typescript-language-server", "typescript"],
|
|
28262
|
+
verifyCommand: "typescript-language-server --version",
|
|
28263
|
+
description: "TypeScript/JavaScript LSP server",
|
|
28264
|
+
required: false
|
|
28265
|
+
},
|
|
28266
|
+
{
|
|
28267
|
+
name: "pyright",
|
|
28268
|
+
npmPackage: "pyright",
|
|
28269
|
+
installCommand: ["pip", "install", "pyright"],
|
|
28270
|
+
verifyCommand: "pyright --version",
|
|
28271
|
+
description: "Python LSP server",
|
|
28272
|
+
required: false
|
|
28273
|
+
}
|
|
28274
|
+
];
|
|
28275
|
+
|
|
28276
|
+
class DependencyInstaller {
|
|
28277
|
+
installDir;
|
|
28278
|
+
cache = new Map;
|
|
28279
|
+
cacheTimeout = 60000;
|
|
28280
|
+
constructor(installDir) {
|
|
28281
|
+
this.installDir = installDir || path11.join(os4.homedir(), ".local");
|
|
28282
|
+
}
|
|
28283
|
+
getBinDir() {
|
|
28284
|
+
return path11.join(this.installDir, "bin");
|
|
28285
|
+
}
|
|
28286
|
+
commandExists(cmd) {
|
|
28287
|
+
try {
|
|
28288
|
+
execSync5(`which ${cmd}`, { stdio: "ignore" });
|
|
28289
|
+
return true;
|
|
28290
|
+
} catch {
|
|
28291
|
+
return false;
|
|
28292
|
+
}
|
|
28293
|
+
}
|
|
28294
|
+
verifyTool(config2) {
|
|
28295
|
+
try {
|
|
28296
|
+
execSync5(config2.verifyCommand, { stdio: "ignore", timeout: 5000 });
|
|
28297
|
+
return true;
|
|
28298
|
+
} catch {
|
|
28299
|
+
return false;
|
|
28300
|
+
}
|
|
28301
|
+
}
|
|
28302
|
+
async install(config2) {
|
|
28303
|
+
console.log(`[dep-installer] Installing ${config2.name}...`);
|
|
28304
|
+
try {
|
|
28305
|
+
const [cmd, ...args2] = config2.installCommand;
|
|
28306
|
+
const fullCmd = `${cmd} ${args2.join(" ")}`;
|
|
28307
|
+
execSync5(fullCmd, {
|
|
28308
|
+
stdio: "inherit",
|
|
28309
|
+
timeout: 120000,
|
|
28310
|
+
env: {
|
|
28311
|
+
...process.env,
|
|
28312
|
+
...cmd === "npm" ? { npm_config_prefix: this.installDir } : {}
|
|
28313
|
+
}
|
|
28314
|
+
});
|
|
28315
|
+
const verified = this.verifyTool(config2);
|
|
28316
|
+
if (verified) {
|
|
28317
|
+
console.log(`[dep-installer] ✓ ${config2.name} installed successfully`);
|
|
28318
|
+
this.cache.set(config2.name, { installed: true, checked: Date.now() });
|
|
28319
|
+
return { success: true, output: `${config2.name} installed and verified` };
|
|
28320
|
+
} else {
|
|
28321
|
+
return { success: false, error: "Installation completed but verification failed" };
|
|
28322
|
+
}
|
|
28323
|
+
} catch (error45) {
|
|
28324
|
+
console.warn(`[dep-installer] ✗ ${config2.name} installation failed: ${error45.message}`);
|
|
28325
|
+
return { success: false, error: error45.message };
|
|
28326
|
+
}
|
|
28327
|
+
}
|
|
28328
|
+
isInstalled(toolName) {
|
|
28329
|
+
const cached2 = this.cache.get(toolName);
|
|
28330
|
+
if (cached2 && Date.now() - cached2.checked < this.cacheTimeout) {
|
|
28331
|
+
return cached2.installed;
|
|
28332
|
+
}
|
|
28333
|
+
const config2 = PLUGIN_TOOLS.find((t) => t.name === toolName);
|
|
28334
|
+
if (!config2)
|
|
28335
|
+
return false;
|
|
28336
|
+
const installed = this.verifyTool(config2);
|
|
28337
|
+
this.cache.set(toolName, { installed, checked: Date.now() });
|
|
28338
|
+
return installed;
|
|
28339
|
+
}
|
|
28340
|
+
getStatus() {
|
|
28341
|
+
return PLUGIN_TOOLS.map((config2) => ({
|
|
28342
|
+
name: config2.name,
|
|
28343
|
+
installed: this.isInstalled(config2.name),
|
|
28344
|
+
description: config2.description,
|
|
28345
|
+
required: config2.required
|
|
28346
|
+
}));
|
|
28347
|
+
}
|
|
28348
|
+
async ensureRequired() {
|
|
28349
|
+
const installed = [];
|
|
28350
|
+
const missing = [];
|
|
28351
|
+
const errors3 = {};
|
|
28352
|
+
for (const config2 of PLUGIN_TOOLS) {
|
|
28353
|
+
if (config2.required && !this.isInstalled(config2.name)) {
|
|
28354
|
+
const result = await this.install(config2);
|
|
28355
|
+
if (result.success) {
|
|
28356
|
+
installed.push(config2.name);
|
|
28357
|
+
} else {
|
|
28358
|
+
missing.push(config2.name);
|
|
28359
|
+
errors3[config2.name] = result.error || "Installation failed";
|
|
28360
|
+
}
|
|
28361
|
+
}
|
|
28362
|
+
}
|
|
28363
|
+
return { installed, missing, errors: errors3 };
|
|
28364
|
+
}
|
|
28365
|
+
async installAll() {
|
|
28366
|
+
const success2 = [];
|
|
28367
|
+
const failed = {};
|
|
28368
|
+
for (const config2 of PLUGIN_TOOLS) {
|
|
28369
|
+
if (!this.isInstalled(config2.name)) {
|
|
28370
|
+
const result = await this.install(config2);
|
|
28371
|
+
if (result.success) {
|
|
28372
|
+
success2.push(config2.name);
|
|
28373
|
+
} else {
|
|
28374
|
+
failed[config2.name] = result.error || "Installation failed";
|
|
28375
|
+
}
|
|
28376
|
+
} else {
|
|
28377
|
+
success2.push(config2.name);
|
|
28378
|
+
}
|
|
28379
|
+
}
|
|
28380
|
+
return { success: success2, failed };
|
|
28381
|
+
}
|
|
28382
|
+
async installTool(toolName) {
|
|
28383
|
+
const config2 = PLUGIN_TOOLS.find((t) => t.name === toolName);
|
|
28384
|
+
if (!config2) {
|
|
28385
|
+
return { success: false, error: `Unknown tool: ${toolName}. Available: ${PLUGIN_TOOLS.map((t) => t.name).join(", ")}` };
|
|
28386
|
+
}
|
|
28387
|
+
if (this.isInstalled(toolName)) {
|
|
28388
|
+
return { success: true, output: `${toolName} is already installed` };
|
|
28389
|
+
}
|
|
28390
|
+
return this.install(config2);
|
|
28391
|
+
}
|
|
28392
|
+
}
|
|
28393
|
+
var dependencyInstaller = new DependencyInstaller;
|
|
28394
|
+
async function ensurePluginDeps() {
|
|
28395
|
+
dependencyInstaller.ensureRequired().catch(console.error);
|
|
28396
|
+
}
|
|
28397
|
+
|
|
26194
28398
|
// src/index.ts
|
|
26195
28399
|
function formatSkillsXml(skills) {
|
|
26196
28400
|
if (skills.length === 0)
|
|
@@ -26216,7 +28420,7 @@ async function buildAutoLoadedSkillsContent(agentName, configService, projectRoo
|
|
|
26216
28420
|
if (autoLoadSkills.length === 0) {
|
|
26217
28421
|
return "";
|
|
26218
28422
|
}
|
|
26219
|
-
const homeDir = process.env.HOME ||
|
|
28423
|
+
const homeDir = process.env.HOME || os5.homedir();
|
|
26220
28424
|
const skillTemplates = [];
|
|
26221
28425
|
for (const skillId of autoLoadSkills) {
|
|
26222
28426
|
const builtinSkill = BUILTIN_SKILLS.find((entry) => entry.name === skillId);
|
|
@@ -26298,11 +28502,14 @@ var plugin = async (ctx) => {
|
|
|
26298
28502
|
const disabledMcps = configService.getDisabledMcps();
|
|
26299
28503
|
const disabledSkills = configService.getDisabledSkills();
|
|
26300
28504
|
const builtinMcps = createBuiltinMcps(disabledMcps);
|
|
28505
|
+
if (configService.get().autoInstallDeps !== false) {
|
|
28506
|
+
ensurePluginDeps();
|
|
28507
|
+
}
|
|
26301
28508
|
const filteredSkills = getFilteredSkills(disabledSkills);
|
|
26302
28509
|
const effectiveAutoLoadSkills = configService.getAgentConfig("zetta").autoLoadSkills ?? [];
|
|
26303
28510
|
const worktreeService = new WorktreeService({
|
|
26304
28511
|
baseDir: directory,
|
|
26305
|
-
hiveDir:
|
|
28512
|
+
hiveDir: path12.join(directory, ".hive")
|
|
26306
28513
|
});
|
|
26307
28514
|
const isOmoSlimEnabled = () => {
|
|
26308
28515
|
return configService.isOmoSlimEnabled();
|
|
@@ -26328,10 +28535,10 @@ var plugin = async (ctx) => {
|
|
|
26328
28535
|
}
|
|
26329
28536
|
};
|
|
26330
28537
|
const checkBlocked = (feature) => {
|
|
26331
|
-
const
|
|
26332
|
-
const blockedPath =
|
|
26333
|
-
if (
|
|
26334
|
-
const reason =
|
|
28538
|
+
const fs12 = __require("fs");
|
|
28539
|
+
const blockedPath = path12.join(directory, ".hive", "features", feature, "BLOCKED");
|
|
28540
|
+
if (fs12.existsSync(blockedPath)) {
|
|
28541
|
+
const reason = fs12.readFileSync(blockedPath, "utf-8").trim();
|
|
26335
28542
|
return `⛔ BLOCKED by Beekeeper
|
|
26336
28543
|
|
|
26337
28544
|
${reason || "(No reason provided)"}
|
|
@@ -26483,9 +28690,9 @@ To unblock: Remove .hive/features/${feature}/BLOCKED`;
|
|
|
26483
28690
|
spec: specContent,
|
|
26484
28691
|
workerPrompt
|
|
26485
28692
|
});
|
|
26486
|
-
const hiveDir =
|
|
28693
|
+
const hiveDir = path12.join(directory, ".hive");
|
|
26487
28694
|
const workerPromptPath = writeWorkerPromptFile(feature, task, workerPrompt, hiveDir);
|
|
26488
|
-
const relativePromptPath = normalizePath(
|
|
28695
|
+
const relativePromptPath = normalizePath(path12.relative(directory, workerPromptPath));
|
|
26489
28696
|
const PREVIEW_MAX_LENGTH = 200;
|
|
26490
28697
|
const workerPromptPreview = workerPrompt.length > PREVIEW_MAX_LENGTH ? workerPrompt.slice(0, PREVIEW_MAX_LENGTH) + "..." : workerPrompt;
|
|
26491
28698
|
const taskToolPrompt = `Follow instructions in @${relativePromptPath}`;
|
|
@@ -26893,7 +29100,7 @@ ${snapshot}
|
|
|
26893
29100
|
if (sandboxConfig.mode !== "none") {
|
|
26894
29101
|
const workdir = output.args?.workdir;
|
|
26895
29102
|
if (workdir) {
|
|
26896
|
-
const hiveWorktreeBase =
|
|
29103
|
+
const hiveWorktreeBase = path12.join(directory, ".hive", ".worktrees");
|
|
26897
29104
|
if (workdir.startsWith(hiveWorktreeBase)) {
|
|
26898
29105
|
const wrapped = DockerSandboxService.wrapCommand(workdir, finalCommand, sandboxConfig);
|
|
26899
29106
|
output.args.command = wrapped;
|
|
@@ -26944,6 +29151,8 @@ ${snapshot}
|
|
|
26944
29151
|
lsp_diagnostics: lspDiagnosticsTool,
|
|
26945
29152
|
lsp_hover: lspHoverTool,
|
|
26946
29153
|
lsp_code_actions: lspCodeActionsTool,
|
|
29154
|
+
lsp_status: lspStatusTool,
|
|
29155
|
+
lsp_install: lspInstallTool,
|
|
26947
29156
|
skill_mcp: skillMcpTool,
|
|
26948
29157
|
list_skill_mcps: listSkillMcpsTool,
|
|
26949
29158
|
hive_memory_list: hiveMemoryListTool,
|
|
@@ -26960,6 +29169,24 @@ ${snapshot}
|
|
|
26960
29169
|
hive_vector_search: hiveVectorSearchTool,
|
|
26961
29170
|
hive_vector_add: hiveVectorAddTool,
|
|
26962
29171
|
hive_vector_status: hiveVectorStatusTool,
|
|
29172
|
+
ast_grep_dump_syntax_tree: astGrepDumpSyntaxTreeTool,
|
|
29173
|
+
ast_grep_test_match_code_rule: astGrepTestMatchCodeRuleTool,
|
|
29174
|
+
ast_grep_find_code: astGrepFindCodeTool,
|
|
29175
|
+
ast_grep_scan_code: astGrepScanCodeTool,
|
|
29176
|
+
ast_grep_rewrite_code: astGrepRewriteCodeTool,
|
|
29177
|
+
ast_grep_analyze_imports: astGrepAnalyzeImportsTool,
|
|
29178
|
+
hive_doctor: hiveDoctorTool,
|
|
29179
|
+
hive_doctor_quick: hiveDoctorQuickTool,
|
|
29180
|
+
dora_status: doraStatusTool,
|
|
29181
|
+
dora_symbol: doraSymbolTool,
|
|
29182
|
+
dora_file: doraFileTool,
|
|
29183
|
+
dora_references: doraReferencesTool,
|
|
29184
|
+
dora_cycles: doraCyclesTool,
|
|
29185
|
+
dora_unused: doraUnusedTool,
|
|
29186
|
+
auto_cr_status: autoCrStatusTool,
|
|
29187
|
+
auto_cr_scan: autoCrScanTool,
|
|
29188
|
+
auto_cr_diff: autoCrDiffTool,
|
|
29189
|
+
auto_cr_rules: autoCrRulesTool,
|
|
26963
29190
|
hive_skill: createHiveSkillTool(filteredSkills),
|
|
26964
29191
|
hive_feature_create: tool({
|
|
26965
29192
|
description: "Create a new feature and set it as active",
|