@hung319/opencode-hive 1.5.2 → 1.5.6
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/dist/index.js
CHANGED
|
@@ -235,410 +235,6 @@ 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
|
-
|
|
642
238
|
// src/utils/context-compression.ts
|
|
643
239
|
var exports_context_compression = {};
|
|
644
240
|
__export(exports_context_compression, {
|
|
@@ -18208,1164 +17804,1238 @@ var hiveVectorStatusTool = tool({
|
|
|
18208
17804
|
}
|
|
18209
17805
|
});
|
|
18210
17806
|
|
|
18211
|
-
// src/tools/
|
|
17807
|
+
// src/tools/hive-doctor.ts
|
|
17808
|
+
import { execSync as execSync2 } from "child_process";
|
|
18212
17809
|
import * as fs5 from "fs";
|
|
18213
|
-
|
|
18214
|
-
|
|
18215
|
-
|
|
18216
|
-
|
|
18217
|
-
|
|
18218
|
-
|
|
18219
|
-
|
|
18220
|
-
|
|
18221
|
-
|
|
18222
|
-
|
|
18223
|
-
|
|
18224
|
-
|
|
18225
|
-
|
|
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;
|
|
17810
|
+
import * as path6 from "path";
|
|
17811
|
+
async function checkPackage(packageName) {
|
|
17812
|
+
try {
|
|
17813
|
+
const packageJsonPath = __require.resolve(`${packageName}/package.json`, {
|
|
17814
|
+
paths: [
|
|
17815
|
+
process.cwd(),
|
|
17816
|
+
path6.join(process.cwd(), "node_modules"),
|
|
17817
|
+
path6.join(process.cwd(), "packages/opencode-hive/node_modules")
|
|
17818
|
+
]
|
|
17819
|
+
});
|
|
17820
|
+
if (fs5.existsSync(packageJsonPath)) {
|
|
17821
|
+
const pkg = JSON.parse(fs5.readFileSync(packageJsonPath, "utf-8"));
|
|
17822
|
+
return { installed: true, version: pkg.version };
|
|
18230
17823
|
}
|
|
18231
|
-
}
|
|
18232
|
-
|
|
17824
|
+
} catch {}
|
|
17825
|
+
return { installed: false };
|
|
18233
17826
|
}
|
|
18234
|
-
|
|
18235
|
-
|
|
18236
|
-
|
|
18237
|
-
|
|
18238
|
-
|
|
18239
|
-
|
|
18240
|
-
|
|
18241
|
-
|
|
18242
|
-
|
|
18243
|
-
|
|
18244
|
-
|
|
18245
|
-
|
|
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
|
-
}
|
|
17827
|
+
function checkCliTool(tool3) {
|
|
17828
|
+
try {
|
|
17829
|
+
const result = execSync2(tool3.command, { stdio: "pipe", timeout: 5000 });
|
|
17830
|
+
const output = result.toString().trim();
|
|
17831
|
+
const versionMatch = output.match(/(\d+\.\d+\.\d+)/);
|
|
17832
|
+
return {
|
|
17833
|
+
...tool3,
|
|
17834
|
+
installed: true,
|
|
17835
|
+
version: versionMatch ? versionMatch[1] : output.slice(0, 50)
|
|
17836
|
+
};
|
|
17837
|
+
} catch {
|
|
17838
|
+
const npxCmd = tool3.command.split(" ")[0];
|
|
18262
17839
|
try {
|
|
18263
|
-
|
|
18264
|
-
|
|
18265
|
-
|
|
18266
|
-
|
|
18267
|
-
|
|
18268
|
-
python: "Python",
|
|
18269
|
-
rust: "Rust",
|
|
18270
|
-
go: "Go",
|
|
18271
|
-
java: "Java",
|
|
18272
|
-
c: "C",
|
|
18273
|
-
cpp: "Cpp",
|
|
18274
|
-
csharp: "CSharp"
|
|
17840
|
+
execSync2(`npx -y ${npxCmd} --version`, { stdio: "pipe", timeout: 1e4 });
|
|
17841
|
+
return {
|
|
17842
|
+
...tool3,
|
|
17843
|
+
installed: true,
|
|
17844
|
+
version: "via npx"
|
|
18275
17845
|
};
|
|
18276
|
-
|
|
18277
|
-
|
|
18278
|
-
|
|
18279
|
-
|
|
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
|
-
};
|
|
17846
|
+
} catch {
|
|
17847
|
+
return {
|
|
17848
|
+
...tool3,
|
|
17849
|
+
installed: false
|
|
18308
17850
|
};
|
|
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
17851
|
}
|
|
18321
17852
|
}
|
|
18322
|
-
}
|
|
18323
|
-
|
|
18324
|
-
|
|
17853
|
+
}
|
|
17854
|
+
function checkOptimizations() {
|
|
17855
|
+
const checks3 = [];
|
|
17856
|
+
const configPaths = [
|
|
17857
|
+
path6.join(process.env.HOME || "", ".config/opencode/agent_hive.json"),
|
|
17858
|
+
path6.join(process.env.HOME || "", ".config/opencode/agent_hive.jsonc")
|
|
17859
|
+
];
|
|
17860
|
+
let config2 = null;
|
|
17861
|
+
for (const configPath of configPaths) {
|
|
17862
|
+
if (fs5.existsSync(configPath)) {
|
|
17863
|
+
try {
|
|
17864
|
+
const content = fs5.readFileSync(configPath, "utf-8");
|
|
17865
|
+
config2 = JSON.parse(content.replace(/\\/g, ""));
|
|
17866
|
+
break;
|
|
17867
|
+
} catch {}
|
|
17868
|
+
}
|
|
17869
|
+
}
|
|
17870
|
+
const snipConfig = config2?.snip;
|
|
17871
|
+
checks3.push({
|
|
17872
|
+
name: "snip",
|
|
17873
|
+
enabled: snipConfig?.enabled === true,
|
|
17874
|
+
recommendation: !snipConfig?.enabled ? "Enable snip in config for 60-90% token reduction on shell output" : undefined
|
|
17875
|
+
});
|
|
17876
|
+
const vectorConfig = config2?.vectorMemory;
|
|
17877
|
+
checks3.push({
|
|
17878
|
+
name: "vectorMemory",
|
|
17879
|
+
enabled: vectorConfig?.enabled === true,
|
|
17880
|
+
recommendation: !vectorConfig?.enabled ? "Enable vector memory for semantic search across memories" : undefined
|
|
17881
|
+
});
|
|
17882
|
+
const boosterConfig = config2?.agentBooster;
|
|
17883
|
+
checks3.push({
|
|
17884
|
+
name: "agentBooster",
|
|
17885
|
+
enabled: boosterConfig?.enabled !== false,
|
|
17886
|
+
recommendation: boosterConfig?.enabled === false ? "Enable agent booster for 52x faster code editing" : undefined
|
|
17887
|
+
});
|
|
17888
|
+
const sandboxConfig = config2?.sandbox;
|
|
17889
|
+
checks3.push({
|
|
17890
|
+
name: "sandbox",
|
|
17891
|
+
enabled: sandboxConfig !== "none",
|
|
17892
|
+
recommendation: sandboxConfig === "none" ? "Enable Docker sandbox for isolated test environments" : undefined
|
|
17893
|
+
});
|
|
17894
|
+
const disabledMcps = config2?.disableMcps || [];
|
|
17895
|
+
const hasPareSearch = !disabledMcps.includes("pare_search");
|
|
17896
|
+
checks3.push({
|
|
17897
|
+
name: "pareSearch",
|
|
17898
|
+
enabled: hasPareSearch,
|
|
17899
|
+
recommendation: !hasPareSearch ? "Enable pare_search for structured ripgrep output (65-95% token reduction)" : undefined
|
|
17900
|
+
});
|
|
17901
|
+
const hasVeil = !disabledMcps.includes("veil");
|
|
17902
|
+
checks3.push({
|
|
17903
|
+
name: "veil",
|
|
17904
|
+
enabled: hasVeil,
|
|
17905
|
+
recommendation: !hasVeil ? "Enable veil for code discovery and intelligent retrieval" : undefined
|
|
17906
|
+
});
|
|
17907
|
+
return checks3;
|
|
17908
|
+
}
|
|
17909
|
+
function generateRecommendations(dependencies, cliTools, optimizations) {
|
|
17910
|
+
const recommendations = [];
|
|
17911
|
+
const missingRequired = dependencies.filter((d) => d.required && !d.installed);
|
|
17912
|
+
if (missingRequired.length > 0) {
|
|
17913
|
+
recommendations.push(`Missing required packages: ${missingRequired.map((d) => d.name).join(", ")}`);
|
|
17914
|
+
}
|
|
17915
|
+
const missingCliTools = cliTools.filter((t) => !t.installed);
|
|
17916
|
+
if (missingCliTools.length > 0) {
|
|
17917
|
+
recommendations.push(`⚠️ Missing CLI tools: ${missingCliTools.map((t) => t.name).join(", ")}`, `Install with: ${missingCliTools.map((t) => `npx -y ${t.command}`).join(" | ")}`);
|
|
17918
|
+
}
|
|
17919
|
+
const disabledOptimizations = optimizations.filter((o) => !o.enabled && o.recommendation);
|
|
17920
|
+
for (const opt of disabledOptimizations) {
|
|
17921
|
+
if (opt.recommendation) {
|
|
17922
|
+
recommendations.push(opt.recommendation);
|
|
17923
|
+
}
|
|
17924
|
+
}
|
|
17925
|
+
if (recommendations.length === 0) {
|
|
17926
|
+
recommendations.push("✅ System is healthy! All checks passed.");
|
|
17927
|
+
}
|
|
17928
|
+
return recommendations;
|
|
17929
|
+
}
|
|
17930
|
+
function generateQuickFixes(dependencies, cliTools, optimizations) {
|
|
17931
|
+
const fixes = [];
|
|
17932
|
+
const missingPackages = dependencies.filter((d) => !d.installed && !d.required);
|
|
17933
|
+
for (const pkg of missingPackages) {
|
|
17934
|
+
fixes.push({
|
|
17935
|
+
command: `npm install ${pkg.package}`,
|
|
17936
|
+
description: `Install ${pkg.name}`
|
|
17937
|
+
});
|
|
17938
|
+
}
|
|
17939
|
+
const missingTools = cliTools.filter((t) => !t.installed);
|
|
17940
|
+
for (const tool3 of missingTools) {
|
|
17941
|
+
fixes.push({
|
|
17942
|
+
command: `npx -y ${tool3.command}`,
|
|
17943
|
+
description: `Install ${tool3.name} via npx`
|
|
17944
|
+
});
|
|
17945
|
+
}
|
|
17946
|
+
if (optimizations.find((o) => o.name === "snip" && !o.enabled)) {
|
|
17947
|
+
fixes.push({
|
|
17948
|
+
command: 'Add to ~/.config/opencode/agent_hive.json: { "snip": { "enabled": true } }',
|
|
17949
|
+
description: "Enable snip for token reduction"
|
|
17950
|
+
});
|
|
17951
|
+
}
|
|
17952
|
+
if (optimizations.find((o) => o.name === "vectorMemory" && !o.enabled)) {
|
|
17953
|
+
fixes.push({
|
|
17954
|
+
command: 'Add to ~/.config/opencode/agent_hive.json: { "vectorMemory": { "enabled": true } }',
|
|
17955
|
+
description: "Enable vector memory for semantic search"
|
|
17956
|
+
});
|
|
17957
|
+
}
|
|
17958
|
+
return fixes;
|
|
17959
|
+
}
|
|
17960
|
+
function calculateStatus(dependencies, cliTools, optimizations) {
|
|
17961
|
+
const missingRequired = dependencies.filter((d) => d.required && !d.installed);
|
|
17962
|
+
if (missingRequired.length > 0) {
|
|
17963
|
+
return "issues";
|
|
17964
|
+
}
|
|
17965
|
+
const missingTools = cliTools.filter((t) => !t.installed);
|
|
17966
|
+
const disabledCount = optimizations.filter((o) => !o.enabled).length;
|
|
17967
|
+
if (missingTools.length > 0 || disabledCount > 2) {
|
|
17968
|
+
return "warning";
|
|
17969
|
+
}
|
|
17970
|
+
return "healthy";
|
|
17971
|
+
}
|
|
17972
|
+
var hiveDoctorTool = tool({
|
|
17973
|
+
description: `Hive Doctor - System health check and optimization advisor.
|
|
18325
17974
|
|
|
18326
|
-
|
|
17975
|
+
**What it checks:**
|
|
17976
|
+
1. Dependencies - Optional packages installed and working
|
|
17977
|
+
2. CLI Tools - dora, auto-cr, etc. available via npx
|
|
17978
|
+
3. Optimizations - Features enabled in config
|
|
17979
|
+
4. Recommendations - Suggestions for improvements
|
|
18327
17980
|
|
|
18328
|
-
**
|
|
18329
|
-
-
|
|
18330
|
-
-
|
|
17981
|
+
**Use when:**
|
|
17982
|
+
- Setting up Hive for the first time
|
|
17983
|
+
- Troubleshooting issues
|
|
17984
|
+
- Optimizing performance
|
|
17985
|
+
- Checking if new features are available
|
|
18331
17986
|
|
|
18332
|
-
**
|
|
18333
|
-
-
|
|
18334
|
-
-
|
|
18335
|
-
|
|
18336
|
-
|
|
18337
|
-
|
|
18338
|
-
|
|
18339
|
-
|
|
18340
|
-
|
|
18341
|
-
|
|
18342
|
-
|
|
18343
|
-
|
|
18344
|
-
|
|
18345
|
-
|
|
18346
|
-
|
|
17987
|
+
**Example output:**
|
|
17988
|
+
- healthy: All checks pass
|
|
17989
|
+
- warning: Some optimizations disabled or CLI tools missing
|
|
17990
|
+
- issues: Missing required packages`,
|
|
17991
|
+
args: {},
|
|
17992
|
+
async execute() {
|
|
17993
|
+
const dependencyChecks = [
|
|
17994
|
+
{ name: "agent-booster", package: "@sparkleideas/agent-booster", required: false },
|
|
17995
|
+
{ name: "vector-memory", package: "@sparkleideas/memory", required: false },
|
|
17996
|
+
{ name: "pare-search", package: "@paretools/search", required: false },
|
|
17997
|
+
{ name: "context7", package: "@upstash/context7-mcp", required: false },
|
|
17998
|
+
{ name: "Exa search", package: "exa-mcp-server", required: false }
|
|
17999
|
+
];
|
|
18000
|
+
for (const dep of dependencyChecks) {
|
|
18001
|
+
const result2 = await checkPackage(dep.package);
|
|
18002
|
+
dep.installed = result2.installed;
|
|
18003
|
+
dep.version = result2.version;
|
|
18347
18004
|
}
|
|
18348
|
-
|
|
18349
|
-
|
|
18350
|
-
|
|
18351
|
-
|
|
18352
|
-
|
|
18353
|
-
|
|
18354
|
-
|
|
18355
|
-
|
|
18356
|
-
|
|
18357
|
-
|
|
18358
|
-
|
|
18359
|
-
|
|
18005
|
+
const cliToolChecks = [
|
|
18006
|
+
{
|
|
18007
|
+
name: "dora",
|
|
18008
|
+
command: "@butttons/dora",
|
|
18009
|
+
description: "SCIP-based code navigation",
|
|
18010
|
+
installCommand: "npx -y @butttons/dora"
|
|
18011
|
+
},
|
|
18012
|
+
{
|
|
18013
|
+
name: "auto-cr",
|
|
18014
|
+
command: "auto-cr-cmd",
|
|
18015
|
+
description: "SWC-based automated code review",
|
|
18016
|
+
installCommand: "npx -y auto-cr-cmd"
|
|
18017
|
+
},
|
|
18018
|
+
{
|
|
18019
|
+
name: "veil",
|
|
18020
|
+
command: "@ushiradineth/veil",
|
|
18021
|
+
description: "Code discovery and retrieval",
|
|
18022
|
+
installCommand: "npx -y @ushiradineth/veil"
|
|
18023
|
+
},
|
|
18024
|
+
{
|
|
18025
|
+
name: "scip-typescript",
|
|
18026
|
+
command: "@sourcegraph/scip-typescript",
|
|
18027
|
+
description: "TypeScript SCIP indexer (for dora)",
|
|
18028
|
+
installCommand: "npx -y @sourcegraph/scip-typescript"
|
|
18029
|
+
}
|
|
18030
|
+
];
|
|
18031
|
+
for (const tool3 of cliToolChecks) {
|
|
18032
|
+
checkCliTool(tool3);
|
|
18033
|
+
}
|
|
18034
|
+
const optimizationChecks = checkOptimizations();
|
|
18035
|
+
const recommendations = generateRecommendations(dependencyChecks, cliToolChecks, optimizationChecks);
|
|
18036
|
+
const quickFixes = generateQuickFixes(dependencyChecks, cliToolChecks, optimizationChecks);
|
|
18037
|
+
const status = calculateStatus(dependencyChecks, cliToolChecks, optimizationChecks);
|
|
18038
|
+
const result = {
|
|
18039
|
+
status,
|
|
18040
|
+
timestamp: new Date().toISOString(),
|
|
18041
|
+
checks: {
|
|
18042
|
+
dependencies: {
|
|
18043
|
+
total: dependencyChecks.length,
|
|
18044
|
+
installed: dependencyChecks.filter((d) => d.installed).length,
|
|
18045
|
+
packages: dependencyChecks
|
|
18046
|
+
},
|
|
18047
|
+
cliTools: {
|
|
18048
|
+
total: cliToolChecks.length,
|
|
18049
|
+
available: cliToolChecks.filter((t) => t.installed).length,
|
|
18050
|
+
tools: cliToolChecks,
|
|
18051
|
+
missing: cliToolChecks.filter((t) => !t.installed).map((t) => t.name)
|
|
18052
|
+
},
|
|
18053
|
+
optimizations: {
|
|
18054
|
+
total: optimizationChecks.length,
|
|
18055
|
+
enabled: optimizationChecks.filter((o) => o.enabled).length,
|
|
18056
|
+
features: optimizationChecks
|
|
18360
18057
|
}
|
|
18361
|
-
},
|
|
18362
|
-
|
|
18363
|
-
|
|
18364
|
-
|
|
18365
|
-
|
|
18366
|
-
|
|
18058
|
+
},
|
|
18059
|
+
recommendations,
|
|
18060
|
+
quickFixes
|
|
18061
|
+
};
|
|
18062
|
+
return JSON.stringify(result, null, 2);
|
|
18063
|
+
}
|
|
18064
|
+
});
|
|
18065
|
+
var hiveDoctorQuickTool = tool({
|
|
18066
|
+
description: `Quick health check - shows status summary only.
|
|
18067
|
+
|
|
18068
|
+
**Returns:**
|
|
18069
|
+
- healthy: All systems go
|
|
18070
|
+
- warning: Some CLI tools missing or optimizations disabled
|
|
18071
|
+
- issues: Action required`,
|
|
18072
|
+
args: {},
|
|
18073
|
+
async execute() {
|
|
18074
|
+
const keyPackages = [
|
|
18075
|
+
"@sparkleideas/agent-booster",
|
|
18076
|
+
"@paretools/search"
|
|
18077
|
+
];
|
|
18078
|
+
const results = {};
|
|
18079
|
+
let healthy = true;
|
|
18080
|
+
for (const pkg of keyPackages) {
|
|
18081
|
+
const result = await checkPackage(pkg);
|
|
18082
|
+
results[pkg] = result.installed;
|
|
18083
|
+
if (!result.installed) {
|
|
18084
|
+
healthy = false;
|
|
18085
|
+
}
|
|
18367
18086
|
}
|
|
18087
|
+
return JSON.stringify({
|
|
18088
|
+
status: healthy ? "healthy" : "warning",
|
|
18089
|
+
packages: results,
|
|
18090
|
+
runFullCheck: "Use hive_doctor for detailed analysis with CLI tool checks"
|
|
18091
|
+
}, null, 2);
|
|
18368
18092
|
}
|
|
18369
18093
|
});
|
|
18370
|
-
var astGrepFindCodeTool = tool({
|
|
18371
|
-
description: `Find code in a project folder that matches the given ast-grep pattern.
|
|
18372
18094
|
|
|
18373
|
-
|
|
18095
|
+
// src/tools/dora.ts
|
|
18096
|
+
import { execSync as execSync3 } from "child_process";
|
|
18097
|
+
function checkDoraStatus() {
|
|
18098
|
+
try {
|
|
18099
|
+
const output = execSync3("dora --version", { encoding: "utf-8" });
|
|
18100
|
+
const version2 = output.trim();
|
|
18101
|
+
const indexExists = __require("fs").existsSync(".dora/dora.db");
|
|
18102
|
+
return { installed: true, version: version2, indexed: indexExists };
|
|
18103
|
+
} catch {
|
|
18104
|
+
return { installed: false, indexed: false };
|
|
18105
|
+
}
|
|
18106
|
+
}
|
|
18107
|
+
function runDoraCommand(args2) {
|
|
18108
|
+
try {
|
|
18109
|
+
const output = execSync3(`dora ${args2.join(" ")}`, {
|
|
18110
|
+
encoding: "utf-8",
|
|
18111
|
+
maxBuffer: 10 * 1024 * 1024
|
|
18112
|
+
});
|
|
18113
|
+
return { success: true, output };
|
|
18114
|
+
} catch (error45) {
|
|
18115
|
+
return { success: false, error: error45.message || "Command failed" };
|
|
18116
|
+
}
|
|
18117
|
+
}
|
|
18118
|
+
var doraStatusTool = tool({
|
|
18119
|
+
description: `Check dora installation status and index state.
|
|
18374
18120
|
|
|
18375
|
-
**
|
|
18376
|
-
-
|
|
18377
|
-
-
|
|
18378
|
-
-
|
|
18121
|
+
**Returns:**
|
|
18122
|
+
- installed: Whether dora CLI is available
|
|
18123
|
+
- version: Dora version
|
|
18124
|
+
- indexed: Whether codebase has been indexed
|
|
18379
18125
|
|
|
18380
|
-
**
|
|
18381
|
-
-
|
|
18382
|
-
-
|
|
18383
|
-
-
|
|
18384
|
-
|
|
18385
|
-
|
|
18386
|
-
|
|
18387
|
-
|
|
18388
|
-
|
|
18389
|
-
|
|
18390
|
-
await initAstGrep();
|
|
18391
|
-
if (!astGrepModule) {
|
|
18126
|
+
**Requirements:**
|
|
18127
|
+
- Install dora: \`bun install -g @butttons/dora\`
|
|
18128
|
+
- Install SCIP indexer: \`npm install -g @sourcegraph/scip-typescript\`
|
|
18129
|
+
- Initialize: \`dora init && dora index\`
|
|
18130
|
+
|
|
18131
|
+
**Note:** Indexing is required once per codebase. After that, dora works instantly.`,
|
|
18132
|
+
args: {},
|
|
18133
|
+
async execute() {
|
|
18134
|
+
const status = checkDoraStatus();
|
|
18135
|
+
if (!status.installed) {
|
|
18392
18136
|
return JSON.stringify({
|
|
18393
|
-
|
|
18394
|
-
|
|
18395
|
-
|
|
18396
|
-
|
|
18397
|
-
|
|
18398
|
-
|
|
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
|
-
});
|
|
18137
|
+
status: "not_installed",
|
|
18138
|
+
message: "Dora CLI not found",
|
|
18139
|
+
installation: {
|
|
18140
|
+
step1: "bun install -g @butttons/dora",
|
|
18141
|
+
step2: "npm install -g @sourcegraph/scip-typescript",
|
|
18142
|
+
step3: "dora init && dora index"
|
|
18442
18143
|
}
|
|
18443
|
-
});
|
|
18444
|
-
return JSON.stringify({
|
|
18445
|
-
success: true,
|
|
18446
|
-
count: results.length,
|
|
18447
|
-
matches: results.slice(0, 50)
|
|
18448
18144
|
}, null, 2);
|
|
18449
|
-
}
|
|
18145
|
+
}
|
|
18146
|
+
if (!status.indexed) {
|
|
18450
18147
|
return JSON.stringify({
|
|
18451
|
-
|
|
18452
|
-
|
|
18148
|
+
status: "not_indexed",
|
|
18149
|
+
version: status.version,
|
|
18150
|
+
message: "Codebase not indexed",
|
|
18151
|
+
nextStep: "Run: dora init && dora index"
|
|
18453
18152
|
}, null, 2);
|
|
18454
18153
|
}
|
|
18154
|
+
return JSON.stringify({
|
|
18155
|
+
status: "ready",
|
|
18156
|
+
version: status.version,
|
|
18157
|
+
indexed: true,
|
|
18158
|
+
message: "Dora is ready"
|
|
18159
|
+
}, null, 2);
|
|
18455
18160
|
}
|
|
18456
18161
|
});
|
|
18457
|
-
var
|
|
18458
|
-
description: `
|
|
18162
|
+
var doraSymbolTool = tool({
|
|
18163
|
+
description: `Find symbol definitions using dora (SCIP-based).
|
|
18459
18164
|
|
|
18460
|
-
|
|
18165
|
+
**Parameters:**
|
|
18166
|
+
- name: Symbol name to search for
|
|
18167
|
+
- kind: Filter by symbol kind (function, class, method, etc.)
|
|
18461
18168
|
|
|
18462
|
-
**
|
|
18463
|
-
|
|
18464
|
-
|
|
18465
|
-
|
|
18466
|
-
- Import style issues
|
|
18467
|
-
- Common bugs
|
|
18169
|
+
**Example:**
|
|
18170
|
+
\`\`\`
|
|
18171
|
+
dora_symbol({ name: "getUserById" })
|
|
18172
|
+
\`\`\`
|
|
18468
18173
|
|
|
18469
|
-
**
|
|
18470
|
-
- project_folder: Optional - path to scan (defaults to current directory)`,
|
|
18174
|
+
**Note:** Requires dora to be installed and indexed.`,
|
|
18471
18175
|
args: {
|
|
18472
|
-
|
|
18176
|
+
name: tool.schema.string().describe("Symbol name to search for"),
|
|
18177
|
+
kind: tool.schema.string().optional().describe("Filter by symbol kind (function, class, method, etc.)")
|
|
18473
18178
|
},
|
|
18474
|
-
async execute({
|
|
18475
|
-
|
|
18476
|
-
if (!
|
|
18179
|
+
async execute({ name, kind }) {
|
|
18180
|
+
const status = checkDoraStatus();
|
|
18181
|
+
if (!status.installed || !status.indexed) {
|
|
18477
18182
|
return JSON.stringify({
|
|
18478
18183
|
success: false,
|
|
18479
|
-
error: "
|
|
18480
|
-
hint: "Install
|
|
18184
|
+
error: "Dora not ready. Run dora_status first.",
|
|
18185
|
+
hint: "Install and index: dora init && dora index"
|
|
18481
18186
|
}, null, 2);
|
|
18482
18187
|
}
|
|
18483
|
-
|
|
18484
|
-
|
|
18485
|
-
|
|
18486
|
-
|
|
18487
|
-
|
|
18488
|
-
|
|
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) {
|
|
18188
|
+
const args2 = ["symbol", name];
|
|
18189
|
+
if (kind) {
|
|
18190
|
+
args2.push("--kind", kind);
|
|
18191
|
+
}
|
|
18192
|
+
const result = runDoraCommand(args2);
|
|
18193
|
+
if (!result.success) {
|
|
18523
18194
|
return JSON.stringify({
|
|
18524
18195
|
success: false,
|
|
18525
|
-
error:
|
|
18196
|
+
error: result.error,
|
|
18197
|
+
hint: "Symbol may not exist or not indexed"
|
|
18526
18198
|
}, null, 2);
|
|
18527
18199
|
}
|
|
18200
|
+
return JSON.stringify({
|
|
18201
|
+
success: true,
|
|
18202
|
+
symbol: name,
|
|
18203
|
+
output: result.output
|
|
18204
|
+
}, null, 2);
|
|
18528
18205
|
}
|
|
18529
18206
|
});
|
|
18530
|
-
var
|
|
18531
|
-
description: `
|
|
18207
|
+
var doraFileTool = tool({
|
|
18208
|
+
description: `Get file dependencies and information using dora.
|
|
18532
18209
|
|
|
18533
|
-
|
|
18210
|
+
**Parameters:**
|
|
18211
|
+
- path: File path to analyze
|
|
18534
18212
|
|
|
18535
|
-
**Example:**
|
|
18213
|
+
**Example:**
|
|
18214
|
+
\`\`\`
|
|
18215
|
+
dora_file({ path: "src/index.ts" })
|
|
18216
|
+
\`\`\`
|
|
18536
18217
|
|
|
18537
|
-
**
|
|
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)`,
|
|
18218
|
+
**Returns:** File metadata, exports, and dependencies.`,
|
|
18542
18219
|
args: {
|
|
18543
|
-
|
|
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")
|
|
18220
|
+
path: tool.schema.string().describe("File path to analyze")
|
|
18547
18221
|
},
|
|
18548
|
-
async execute({
|
|
18549
|
-
|
|
18550
|
-
if (!
|
|
18222
|
+
async execute({ path: path7 }) {
|
|
18223
|
+
const status = checkDoraStatus();
|
|
18224
|
+
if (!status.installed || !status.indexed) {
|
|
18551
18225
|
return JSON.stringify({
|
|
18552
18226
|
success: false,
|
|
18553
|
-
error: "
|
|
18554
|
-
hint: "Install @ast-grep/napi or use MCP-based ast_grep"
|
|
18227
|
+
error: "Dora not ready. Run dora_status first."
|
|
18555
18228
|
}, null, 2);
|
|
18556
18229
|
}
|
|
18557
|
-
|
|
18558
|
-
|
|
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) {
|
|
18230
|
+
const result = runDoraCommand(["file", path7]);
|
|
18231
|
+
if (!result.success) {
|
|
18584
18232
|
return JSON.stringify({
|
|
18585
18233
|
success: false,
|
|
18586
|
-
error:
|
|
18234
|
+
error: result.error,
|
|
18235
|
+
hint: "File may not exist or not indexed"
|
|
18587
18236
|
}, null, 2);
|
|
18588
18237
|
}
|
|
18238
|
+
return JSON.stringify({
|
|
18239
|
+
success: true,
|
|
18240
|
+
path: path7,
|
|
18241
|
+
output: result.output
|
|
18242
|
+
}, null, 2);
|
|
18589
18243
|
}
|
|
18590
18244
|
});
|
|
18591
|
-
var
|
|
18592
|
-
description: `
|
|
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).
|
|
18245
|
+
var doraReferencesTool = tool({
|
|
18246
|
+
description: `Find all references to a symbol using dora.
|
|
18595
18247
|
|
|
18596
18248
|
**Parameters:**
|
|
18597
|
-
-
|
|
18598
|
-
|
|
18249
|
+
- name: Symbol name to find references for
|
|
18250
|
+
|
|
18251
|
+
**Example:**
|
|
18252
|
+
\`\`\`
|
|
18253
|
+
dora_references({ name: "UserService" })
|
|
18254
|
+
\`\`\`
|
|
18255
|
+
|
|
18256
|
+
**Note:** Returns all usages across the codebase.`,
|
|
18599
18257
|
args: {
|
|
18600
|
-
|
|
18601
|
-
path: tool.schema.string().optional().describe("Directory or file to analyze")
|
|
18258
|
+
name: tool.schema.string().describe("Symbol name to find references for")
|
|
18602
18259
|
},
|
|
18603
|
-
async execute({
|
|
18604
|
-
|
|
18605
|
-
if (!
|
|
18260
|
+
async execute({ name }) {
|
|
18261
|
+
const status = checkDoraStatus();
|
|
18262
|
+
if (!status.installed || !status.indexed) {
|
|
18606
18263
|
return JSON.stringify({
|
|
18607
18264
|
success: false,
|
|
18608
|
-
error: "
|
|
18265
|
+
error: "Dora not ready. Run dora_status first."
|
|
18609
18266
|
}, null, 2);
|
|
18610
18267
|
}
|
|
18611
|
-
|
|
18612
|
-
|
|
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) {
|
|
18268
|
+
const result = runDoraCommand(["references", name]);
|
|
18269
|
+
if (!result.success) {
|
|
18664
18270
|
return JSON.stringify({
|
|
18665
18271
|
success: false,
|
|
18666
|
-
error:
|
|
18272
|
+
error: result.error
|
|
18667
18273
|
}, null, 2);
|
|
18668
18274
|
}
|
|
18275
|
+
return JSON.stringify({
|
|
18276
|
+
success: true,
|
|
18277
|
+
symbol: name,
|
|
18278
|
+
output: result.output
|
|
18279
|
+
}, null, 2);
|
|
18669
18280
|
}
|
|
18670
18281
|
});
|
|
18282
|
+
var doraCyclesTool = tool({
|
|
18283
|
+
description: `Detect circular dependencies in the codebase using dora.
|
|
18671
18284
|
|
|
18672
|
-
|
|
18673
|
-
|
|
18674
|
-
|
|
18675
|
-
|
|
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
|
|
18285
|
+
**Example:**
|
|
18286
|
+
\`\`\`
|
|
18287
|
+
dora_cycles()
|
|
18288
|
+
\`\`\`
|
|
18810
18289
|
|
|
18811
|
-
**
|
|
18812
|
-
- healthy: All checks pass
|
|
18813
|
-
- warning: Some optimizations disabled
|
|
18814
|
-
- issues: Missing required packages`,
|
|
18290
|
+
**Returns:** List of circular dependency paths if found.`,
|
|
18815
18291
|
args: {},
|
|
18816
18292
|
async execute() {
|
|
18817
|
-
const
|
|
18818
|
-
|
|
18819
|
-
{
|
|
18820
|
-
|
|
18821
|
-
|
|
18822
|
-
|
|
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;
|
|
18293
|
+
const status = checkDoraStatus();
|
|
18294
|
+
if (!status.installed || !status.indexed) {
|
|
18295
|
+
return JSON.stringify({
|
|
18296
|
+
success: false,
|
|
18297
|
+
error: "Dora not ready. Run dora_status first."
|
|
18298
|
+
}, null, 2);
|
|
18829
18299
|
}
|
|
18830
|
-
const
|
|
18831
|
-
|
|
18832
|
-
|
|
18833
|
-
|
|
18834
|
-
|
|
18835
|
-
|
|
18836
|
-
|
|
18837
|
-
|
|
18838
|
-
|
|
18839
|
-
|
|
18840
|
-
|
|
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);
|
|
18300
|
+
const result = runDoraCommand(["cycles"]);
|
|
18301
|
+
if (!result.success) {
|
|
18302
|
+
return JSON.stringify({
|
|
18303
|
+
success: false,
|
|
18304
|
+
error: result.error
|
|
18305
|
+
}, null, 2);
|
|
18306
|
+
}
|
|
18307
|
+
return JSON.stringify({
|
|
18308
|
+
success: true,
|
|
18309
|
+
cycles: result.output
|
|
18310
|
+
}, null, 2);
|
|
18853
18311
|
}
|
|
18854
18312
|
});
|
|
18855
|
-
var
|
|
18856
|
-
description: `
|
|
18313
|
+
var doraUnusedTool = tool({
|
|
18314
|
+
description: `Find unused/dead code in the codebase using dora.
|
|
18857
18315
|
|
|
18858
|
-
**
|
|
18859
|
-
|
|
18860
|
-
|
|
18861
|
-
|
|
18316
|
+
**Example:**
|
|
18317
|
+
\`\`\`
|
|
18318
|
+
dora_unused()
|
|
18319
|
+
\`\`\`
|
|
18320
|
+
|
|
18321
|
+
**Returns:** List of symbols with zero references.`,
|
|
18862
18322
|
args: {},
|
|
18863
18323
|
async execute() {
|
|
18864
|
-
const
|
|
18865
|
-
|
|
18866
|
-
|
|
18867
|
-
|
|
18868
|
-
|
|
18869
|
-
|
|
18870
|
-
|
|
18871
|
-
|
|
18872
|
-
|
|
18873
|
-
|
|
18874
|
-
|
|
18875
|
-
|
|
18876
|
-
}
|
|
18324
|
+
const status = checkDoraStatus();
|
|
18325
|
+
if (!status.installed || !status.indexed) {
|
|
18326
|
+
return JSON.stringify({
|
|
18327
|
+
success: false,
|
|
18328
|
+
error: "Dora not ready. Run dora_status first."
|
|
18329
|
+
}, null, 2);
|
|
18330
|
+
}
|
|
18331
|
+
const result = runDoraCommand(["unused"]);
|
|
18332
|
+
if (!result.success) {
|
|
18333
|
+
return JSON.stringify({
|
|
18334
|
+
success: false,
|
|
18335
|
+
error: result.error
|
|
18336
|
+
}, null, 2);
|
|
18877
18337
|
}
|
|
18878
18338
|
return JSON.stringify({
|
|
18879
|
-
|
|
18880
|
-
|
|
18881
|
-
runFullCheck: "Use hive_doctor for detailed analysis"
|
|
18339
|
+
success: true,
|
|
18340
|
+
unused: result.output
|
|
18882
18341
|
}, null, 2);
|
|
18883
18342
|
}
|
|
18884
18343
|
});
|
|
18885
18344
|
|
|
18886
|
-
// src/tools/
|
|
18887
|
-
import { execSync as
|
|
18888
|
-
|
|
18345
|
+
// src/tools/auto-cr.ts
|
|
18346
|
+
import { execSync as execSync4 } from "child_process";
|
|
18347
|
+
import * as fs6 from "fs";
|
|
18348
|
+
function checkAutoCrStatus() {
|
|
18889
18349
|
try {
|
|
18890
|
-
const output =
|
|
18350
|
+
const output = execSync4("auto-cr-cmd --version", { encoding: "utf-8" });
|
|
18891
18351
|
const version2 = output.trim();
|
|
18892
|
-
|
|
18893
|
-
return { installed: true, version: version2, indexed: indexExists };
|
|
18352
|
+
return { installed: true, version: version2 };
|
|
18894
18353
|
} catch {
|
|
18895
|
-
return { installed: false
|
|
18354
|
+
return { installed: false };
|
|
18896
18355
|
}
|
|
18897
18356
|
}
|
|
18898
|
-
function
|
|
18357
|
+
function runAutoCr(args2) {
|
|
18899
18358
|
try {
|
|
18900
|
-
const
|
|
18359
|
+
const allArgs = [...args2, "--output", "json"];
|
|
18360
|
+
const output = execSync4(`auto-cr-cmd ${allArgs.join(" ")}`, {
|
|
18901
18361
|
encoding: "utf-8",
|
|
18902
|
-
maxBuffer:
|
|
18362
|
+
maxBuffer: 50 * 1024 * 1024
|
|
18903
18363
|
});
|
|
18904
|
-
|
|
18364
|
+
try {
|
|
18365
|
+
const json2 = JSON.parse(output);
|
|
18366
|
+
return { success: true, output, json: json2 };
|
|
18367
|
+
} catch {
|
|
18368
|
+
return { success: true, output };
|
|
18369
|
+
}
|
|
18905
18370
|
} catch (error45) {
|
|
18906
|
-
|
|
18371
|
+
const stderr = error45.stderr || "";
|
|
18372
|
+
const stdout = error45.stdout || "";
|
|
18373
|
+
const combined = stdout + stderr;
|
|
18374
|
+
try {
|
|
18375
|
+
const json2 = JSON.parse(combined);
|
|
18376
|
+
return { success: true, output: combined, json: json2 };
|
|
18377
|
+
} catch {
|
|
18378
|
+
return { success: false, error: combined || error45.message };
|
|
18379
|
+
}
|
|
18907
18380
|
}
|
|
18908
18381
|
}
|
|
18909
|
-
var
|
|
18910
|
-
description: `Check
|
|
18382
|
+
var autoCrStatusTool = tool({
|
|
18383
|
+
description: `Check auto-cr-cmd installation status.
|
|
18911
18384
|
|
|
18912
18385
|
**Returns:**
|
|
18913
|
-
- installed: Whether
|
|
18914
|
-
- version:
|
|
18915
|
-
-
|
|
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\`
|
|
18386
|
+
- installed: Whether auto-cr-cmd is available
|
|
18387
|
+
- version: Auto-CR version
|
|
18388
|
+
- ready: Whether it's ready to scan
|
|
18921
18389
|
|
|
18922
|
-
**
|
|
18390
|
+
**Installation:**
|
|
18391
|
+
\`\`\`bash
|
|
18392
|
+
npm install auto-cr-cmd
|
|
18393
|
+
# or
|
|
18394
|
+
pnpm add auto-cr-cmd
|
|
18395
|
+
\`\`\``,
|
|
18923
18396
|
args: {},
|
|
18924
18397
|
async execute() {
|
|
18925
|
-
const status =
|
|
18398
|
+
const status = checkAutoCrStatus();
|
|
18926
18399
|
if (!status.installed) {
|
|
18927
18400
|
return JSON.stringify({
|
|
18928
18401
|
status: "not_installed",
|
|
18929
|
-
message: "
|
|
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"
|
|
18402
|
+
message: "auto-cr-cmd not found",
|
|
18403
|
+
installation: "npm install auto-cr-cmd"
|
|
18943
18404
|
}, null, 2);
|
|
18944
18405
|
}
|
|
18945
18406
|
return JSON.stringify({
|
|
18946
18407
|
status: "ready",
|
|
18947
18408
|
version: status.version,
|
|
18948
|
-
|
|
18949
|
-
|
|
18409
|
+
message: "Auto-CR is ready to scan",
|
|
18410
|
+
rules: [
|
|
18411
|
+
"no-deep-relative-imports",
|
|
18412
|
+
"no-circular-dependencies",
|
|
18413
|
+
"no-swallowed-errors",
|
|
18414
|
+
"no-catastrophic-regex",
|
|
18415
|
+
"no-deep-clone-in-loop",
|
|
18416
|
+
"no-n2-array-lookup"
|
|
18417
|
+
]
|
|
18950
18418
|
}, null, 2);
|
|
18951
18419
|
}
|
|
18952
18420
|
});
|
|
18953
|
-
var
|
|
18954
|
-
description: `
|
|
18421
|
+
var autoCrScanTool = tool({
|
|
18422
|
+
description: `Scan directory for code issues using auto-cr (SWC-based static analysis).
|
|
18955
18423
|
|
|
18956
18424
|
**Parameters:**
|
|
18957
|
-
-
|
|
18958
|
-
-
|
|
18425
|
+
- path: Directory path to scan (defaults to ./src)
|
|
18426
|
+
- language: Output language (en/zh, defaults to en)
|
|
18427
|
+
|
|
18428
|
+
**Rules detected:**
|
|
18429
|
+
- no-deep-relative-imports: Import paths exceeding depth limit
|
|
18430
|
+
- no-circular-dependencies: Circular module dependencies
|
|
18431
|
+
- no-swallowed-errors: try-catch blocks that swallow errors
|
|
18432
|
+
- no-catastrophic-regex: Potentially catastrophic regex patterns
|
|
18433
|
+
- no-deep-clone-in-loop: Performance anti-patterns
|
|
18434
|
+
- no-n2-array-lookup: O(n²) array operations
|
|
18959
18435
|
|
|
18960
18436
|
**Example:**
|
|
18961
18437
|
\`\`\`
|
|
18962
|
-
|
|
18963
|
-
|
|
18964
|
-
|
|
18965
|
-
**Note:** Requires dora to be installed and indexed.`,
|
|
18438
|
+
auto_cr_scan({ path: "./src" })
|
|
18439
|
+
\`\`\``,
|
|
18966
18440
|
args: {
|
|
18967
|
-
|
|
18968
|
-
|
|
18441
|
+
path: tool.schema.string().optional().default("./src").describe("Directory path to scan"),
|
|
18442
|
+
language: tool.schema.string().optional().default("en").describe("Output language (en or zh)")
|
|
18969
18443
|
},
|
|
18970
|
-
async execute({
|
|
18971
|
-
const status =
|
|
18972
|
-
if (!status.installed
|
|
18444
|
+
async execute({ path: path7, language }) {
|
|
18445
|
+
const status = checkAutoCrStatus();
|
|
18446
|
+
if (!status.installed) {
|
|
18973
18447
|
return JSON.stringify({
|
|
18974
18448
|
success: false,
|
|
18975
|
-
error: "
|
|
18976
|
-
hint: "
|
|
18449
|
+
error: "auto-cr-cmd not installed",
|
|
18450
|
+
hint: "npm install auto-cr-cmd"
|
|
18977
18451
|
}, null, 2);
|
|
18978
18452
|
}
|
|
18979
|
-
|
|
18980
|
-
|
|
18981
|
-
|
|
18453
|
+
if (!fs6.existsSync(path7)) {
|
|
18454
|
+
return JSON.stringify({
|
|
18455
|
+
success: false,
|
|
18456
|
+
error: `Path not found: ${path7}`
|
|
18457
|
+
}, null, 2);
|
|
18982
18458
|
}
|
|
18983
|
-
const result =
|
|
18984
|
-
if (!result.success) {
|
|
18459
|
+
const result = runAutoCr(["--language", language, path7]);
|
|
18460
|
+
if (!result.success && !result.json) {
|
|
18985
18461
|
return JSON.stringify({
|
|
18986
18462
|
success: false,
|
|
18987
|
-
error: result.error
|
|
18988
|
-
|
|
18463
|
+
error: result.error || "Scan failed"
|
|
18464
|
+
}, null, 2);
|
|
18465
|
+
}
|
|
18466
|
+
if (result.json) {
|
|
18467
|
+
const { summary, files, notifications } = result.json;
|
|
18468
|
+
return JSON.stringify({
|
|
18469
|
+
success: true,
|
|
18470
|
+
scanned: path7,
|
|
18471
|
+
summary: {
|
|
18472
|
+
filesScanned: summary?.scannedFiles || 0,
|
|
18473
|
+
filesWithErrors: summary?.filesWithErrors || 0,
|
|
18474
|
+
filesWithWarnings: summary?.filesWithWarnings || 0,
|
|
18475
|
+
totalViolations: summary?.violationTotals?.total || 0
|
|
18476
|
+
},
|
|
18477
|
+
files: files?.map((f) => ({
|
|
18478
|
+
path: f.filePath,
|
|
18479
|
+
violations: f.totalViolations,
|
|
18480
|
+
errors: f.severityCounts?.error || 0,
|
|
18481
|
+
warnings: f.severityCounts?.warning || 0,
|
|
18482
|
+
details: f.violations?.map((v) => ({
|
|
18483
|
+
rule: v.ruleName,
|
|
18484
|
+
severity: v.severity,
|
|
18485
|
+
message: v.message,
|
|
18486
|
+
line: v.line
|
|
18487
|
+
}))
|
|
18488
|
+
})),
|
|
18489
|
+
notifications: notifications || []
|
|
18989
18490
|
}, null, 2);
|
|
18990
18491
|
}
|
|
18991
18492
|
return JSON.stringify({
|
|
18992
18493
|
success: true,
|
|
18993
|
-
|
|
18994
|
-
|
|
18494
|
+
scanned: path7,
|
|
18495
|
+
rawOutput: result.output
|
|
18995
18496
|
}, null, 2);
|
|
18996
18497
|
}
|
|
18997
18498
|
});
|
|
18998
|
-
var
|
|
18999
|
-
description: `
|
|
18499
|
+
var autoCrDiffTool = tool({
|
|
18500
|
+
description: `Scan git diff output for code issues using auto-cr.
|
|
19000
18501
|
|
|
19001
|
-
**
|
|
19002
|
-
- path: File path to analyze
|
|
18502
|
+
**Use case:** Run in CI to check only changed files.
|
|
19003
18503
|
|
|
19004
18504
|
**Example:**
|
|
19005
|
-
\`\`\`
|
|
19006
|
-
|
|
18505
|
+
\`\`\`bash
|
|
18506
|
+
git diff --name-only -z | xargs -0 auto-cr-cmd --stdin --output json
|
|
19007
18507
|
\`\`\`
|
|
19008
18508
|
|
|
19009
|
-
**
|
|
18509
|
+
**Note:** This tool requires git diff output piped via stdin.`,
|
|
19010
18510
|
args: {
|
|
19011
|
-
|
|
18511
|
+
language: tool.schema.string().optional().default("en").describe("Output language (en or zh)")
|
|
19012
18512
|
},
|
|
19013
|
-
async execute({
|
|
19014
|
-
const status =
|
|
19015
|
-
if (!status.installed
|
|
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) {
|
|
18513
|
+
async execute({ language }) {
|
|
18514
|
+
const status = checkAutoCrStatus();
|
|
18515
|
+
if (!status.installed) {
|
|
19023
18516
|
return JSON.stringify({
|
|
19024
18517
|
success: false,
|
|
19025
|
-
error:
|
|
19026
|
-
hint: "
|
|
18518
|
+
error: "auto-cr-cmd not installed",
|
|
18519
|
+
hint: "npm install auto-cr-cmd"
|
|
19027
18520
|
}, null, 2);
|
|
19028
18521
|
}
|
|
19029
18522
|
return JSON.stringify({
|
|
19030
18523
|
success: true,
|
|
19031
|
-
|
|
19032
|
-
|
|
18524
|
+
message: "Use git diff with auto-cr directly",
|
|
18525
|
+
example: "git diff --name-only -z | xargs -0 npx auto-cr-cmd --stdin --output json"
|
|
19033
18526
|
}, null, 2);
|
|
19034
18527
|
}
|
|
19035
18528
|
});
|
|
19036
|
-
var
|
|
19037
|
-
description: `
|
|
18529
|
+
var autoCrRulesTool = tool({
|
|
18530
|
+
description: `List available auto-cr rules and their descriptions.
|
|
19038
18531
|
|
|
19039
|
-
**
|
|
19040
|
-
|
|
18532
|
+
**Returns:** All built-in rules with descriptions.`,
|
|
18533
|
+
args: {},
|
|
18534
|
+
async execute() {
|
|
18535
|
+
const rules = [
|
|
18536
|
+
{
|
|
18537
|
+
name: "no-deep-relative-imports",
|
|
18538
|
+
severity: "error",
|
|
18539
|
+
description: "Import paths should not exceed maximum depth",
|
|
18540
|
+
example: "Use path aliases (@shared/utils) instead of ../../../../shared/utils"
|
|
18541
|
+
},
|
|
18542
|
+
{
|
|
18543
|
+
name: "no-circular-dependencies",
|
|
18544
|
+
severity: "warning",
|
|
18545
|
+
description: "Detect circular module dependencies",
|
|
18546
|
+
example: "A imports B, B imports A creates a cycle"
|
|
18547
|
+
},
|
|
18548
|
+
{
|
|
18549
|
+
name: "no-swallowed-errors",
|
|
18550
|
+
severity: "warning",
|
|
18551
|
+
description: "try-catch blocks that swallow errors without rethrowing",
|
|
18552
|
+
example: "catch (e) {} without logging or rethrowing"
|
|
18553
|
+
},
|
|
18554
|
+
{
|
|
18555
|
+
name: "no-catastrophic-regex",
|
|
18556
|
+
severity: "error",
|
|
18557
|
+
description: "Potentially catastrophic regex backtracking",
|
|
18558
|
+
example: "Regex with nested quantifiers that can hang"
|
|
18559
|
+
},
|
|
18560
|
+
{
|
|
18561
|
+
name: "no-deep-clone-in-loop",
|
|
18562
|
+
severity: "warning",
|
|
18563
|
+
description: "Performance: deep clone operations inside loops",
|
|
18564
|
+
example: "for loop calling JSON.parse(JSON.stringify())"
|
|
18565
|
+
},
|
|
18566
|
+
{
|
|
18567
|
+
name: "no-n2-array-lookup",
|
|
18568
|
+
severity: "warning",
|
|
18569
|
+
description: "O(n²) array operations",
|
|
18570
|
+
example: "Nested for loops accessing array elements"
|
|
18571
|
+
}
|
|
18572
|
+
];
|
|
18573
|
+
return JSON.stringify({
|
|
18574
|
+
success: true,
|
|
18575
|
+
rules,
|
|
18576
|
+
totalRules: rules.length
|
|
18577
|
+
}, null, 2);
|
|
18578
|
+
}
|
|
18579
|
+
});
|
|
19041
18580
|
|
|
19042
|
-
|
|
19043
|
-
|
|
19044
|
-
|
|
19045
|
-
|
|
18581
|
+
// src/tools/ast-grep-native.ts
|
|
18582
|
+
import * as fs7 from "fs";
|
|
18583
|
+
var astGrepModule = null;
|
|
18584
|
+
var astGrepInitPromise = null;
|
|
18585
|
+
async function initAstGrep() {
|
|
18586
|
+
if (astGrepModule !== null) {
|
|
18587
|
+
return;
|
|
18588
|
+
}
|
|
18589
|
+
if (astGrepInitPromise !== null) {
|
|
18590
|
+
await astGrepInitPromise;
|
|
18591
|
+
return;
|
|
18592
|
+
}
|
|
18593
|
+
astGrepInitPromise = (async () => {
|
|
18594
|
+
try {
|
|
18595
|
+
astGrepModule = await import("@ast-grep/napi");
|
|
18596
|
+
console.log("[ast-grep] Native NAPI initialized successfully");
|
|
18597
|
+
} catch (error45) {
|
|
18598
|
+
console.warn("[ast-grep] Failed to load @ast-grep/napi:", error45 instanceof Error ? error45.message : error45);
|
|
18599
|
+
astGrepModule = null;
|
|
18600
|
+
}
|
|
18601
|
+
})();
|
|
18602
|
+
await astGrepInitPromise;
|
|
18603
|
+
}
|
|
18604
|
+
var astGrepDumpSyntaxTreeTool = tool({
|
|
18605
|
+
description: `Dump code's syntax structure or dump a query's pattern structure.
|
|
19046
18606
|
|
|
19047
|
-
|
|
18607
|
+
This is useful to discover correct syntax kind and syntax tree structure. Call it when debugging a rule.
|
|
18608
|
+
|
|
18609
|
+
**Parameters:**
|
|
18610
|
+
- code: The code you need
|
|
18611
|
+
- language: Programming language (typescript, javascript, python, rust, go, java, etc.)
|
|
18612
|
+
- format: Output format - 'cst' (concrete syntax tree) or 'pattern' (to inspect rule patterns)
|
|
18613
|
+
|
|
18614
|
+
**Use when:**
|
|
18615
|
+
- Debugging AST patterns
|
|
18616
|
+
- Finding correct syntax kind names
|
|
18617
|
+
- Understanding code structure`,
|
|
19048
18618
|
args: {
|
|
19049
|
-
|
|
18619
|
+
code: tool.schema.string().describe("The code to analyze"),
|
|
18620
|
+
language: tool.schema.string().describe("Programming language (typescript, javascript, python, rust, go, java, etc.)"),
|
|
18621
|
+
format: tool.schema.enum(["cst", "pattern"]).default("cst").describe("Output format")
|
|
19050
18622
|
},
|
|
19051
|
-
async execute({
|
|
19052
|
-
|
|
19053
|
-
if (!
|
|
18623
|
+
async execute({ code, language, format }) {
|
|
18624
|
+
await initAstGrep();
|
|
18625
|
+
if (!astGrepModule) {
|
|
19054
18626
|
return JSON.stringify({
|
|
19055
18627
|
success: false,
|
|
19056
|
-
error: "
|
|
18628
|
+
error: "@ast-grep/napi not available",
|
|
18629
|
+
hint: "Install @ast-grep/napi or use MCP-based ast_grep"
|
|
19057
18630
|
}, null, 2);
|
|
19058
18631
|
}
|
|
19059
|
-
|
|
19060
|
-
|
|
18632
|
+
try {
|
|
18633
|
+
const langMap = {
|
|
18634
|
+
typescript: "TypeScript",
|
|
18635
|
+
javascript: "JavaScript",
|
|
18636
|
+
tsx: "Tsx",
|
|
18637
|
+
jsx: "Jsx",
|
|
18638
|
+
python: "Python",
|
|
18639
|
+
rust: "Rust",
|
|
18640
|
+
go: "Go",
|
|
18641
|
+
java: "Java",
|
|
18642
|
+
c: "C",
|
|
18643
|
+
cpp: "Cpp",
|
|
18644
|
+
csharp: "CSharp"
|
|
18645
|
+
};
|
|
18646
|
+
const lang = langMap[language.toLowerCase()] || language;
|
|
18647
|
+
const Lang = astGrepModule.Lang;
|
|
18648
|
+
if (!Lang || !Lang[lang]) {
|
|
18649
|
+
return JSON.stringify({
|
|
18650
|
+
success: false,
|
|
18651
|
+
error: `Unsupported language: ${language}`,
|
|
18652
|
+
availableLanguages: Object.keys(langMap)
|
|
18653
|
+
}, null, 2);
|
|
18654
|
+
}
|
|
18655
|
+
if (format === "pattern") {
|
|
18656
|
+
return JSON.stringify({
|
|
18657
|
+
success: true,
|
|
18658
|
+
format: "pattern",
|
|
18659
|
+
language,
|
|
18660
|
+
example: {
|
|
18661
|
+
match: "AwaitExpression",
|
|
18662
|
+
kind: "Use kind to match AST node types",
|
|
18663
|
+
pattern: "Use pattern for code templates"
|
|
18664
|
+
}
|
|
18665
|
+
}, null, 2);
|
|
18666
|
+
}
|
|
18667
|
+
const parse5 = astGrepModule.parse;
|
|
18668
|
+
const ast = parse5(Lang[lang], code);
|
|
18669
|
+
const root = ast.root();
|
|
18670
|
+
const dump = (node, depth = 0) => {
|
|
18671
|
+
if (!node)
|
|
18672
|
+
return null;
|
|
18673
|
+
return {
|
|
18674
|
+
kind: node.kind(),
|
|
18675
|
+
text: node.text(),
|
|
18676
|
+
children: node.children().map((child) => dump(child, depth + 1))
|
|
18677
|
+
};
|
|
18678
|
+
};
|
|
18679
|
+
return JSON.stringify({
|
|
18680
|
+
success: true,
|
|
18681
|
+
format: "cst",
|
|
18682
|
+
language,
|
|
18683
|
+
tree: dump(root)
|
|
18684
|
+
}, null, 2);
|
|
18685
|
+
} catch (error45) {
|
|
19061
18686
|
return JSON.stringify({
|
|
19062
18687
|
success: false,
|
|
19063
|
-
error:
|
|
18688
|
+
error: error45 instanceof Error ? error45.message : String(error45)
|
|
19064
18689
|
}, null, 2);
|
|
19065
18690
|
}
|
|
19066
|
-
return JSON.stringify({
|
|
19067
|
-
success: true,
|
|
19068
|
-
symbol: name,
|
|
19069
|
-
output: result.output
|
|
19070
|
-
}, null, 2);
|
|
19071
18691
|
}
|
|
19072
18692
|
});
|
|
19073
|
-
var
|
|
19074
|
-
description: `
|
|
18693
|
+
var astGrepTestMatchCodeRuleTool = tool({
|
|
18694
|
+
description: `Test a code against an ast-grep YAML rule.
|
|
19075
18695
|
|
|
19076
|
-
|
|
19077
|
-
\`\`\`
|
|
19078
|
-
dora_cycles()
|
|
19079
|
-
\`\`\`
|
|
18696
|
+
This is useful to test a rule before using it in a project.
|
|
19080
18697
|
|
|
19081
|
-
**
|
|
19082
|
-
|
|
19083
|
-
|
|
19084
|
-
|
|
19085
|
-
|
|
18698
|
+
**Parameters:**
|
|
18699
|
+
- code: The code to test against the rule
|
|
18700
|
+
- yaml: The ast-grep YAML rule to test
|
|
18701
|
+
|
|
18702
|
+
**Returns:**
|
|
18703
|
+
- Whether the rule matched
|
|
18704
|
+
- Matched nodes with locations`,
|
|
18705
|
+
args: {
|
|
18706
|
+
code: tool.schema.string().describe("The code to test against the rule"),
|
|
18707
|
+
yaml: tool.schema.string().describe("The ast-grep YAML rule to search")
|
|
18708
|
+
},
|
|
18709
|
+
async execute({ code, yaml }) {
|
|
18710
|
+
await initAstGrep();
|
|
18711
|
+
if (!astGrepModule) {
|
|
19086
18712
|
return JSON.stringify({
|
|
19087
18713
|
success: false,
|
|
19088
|
-
error: "
|
|
18714
|
+
error: "@ast-grep/napi not available",
|
|
18715
|
+
hint: "Install @ast-grep/napi or use MCP-based ast_grep"
|
|
18716
|
+
}, null, 2);
|
|
18717
|
+
}
|
|
18718
|
+
try {
|
|
18719
|
+
const parse5 = astGrepModule.parse;
|
|
18720
|
+
const Lang = astGrepModule.Lang;
|
|
18721
|
+
const ast = parse5(Lang.TypeScript, code);
|
|
18722
|
+
const root = ast.root();
|
|
18723
|
+
return JSON.stringify({
|
|
18724
|
+
success: true,
|
|
18725
|
+
matched: false,
|
|
18726
|
+
note: "YAML rule testing requires @ast-grep/cli. Use ast_grep_find_code for pattern-based search.",
|
|
18727
|
+
example: {
|
|
18728
|
+
pattern: "console.log($ARG)",
|
|
18729
|
+
description: "Match console.log with any argument"
|
|
18730
|
+
}
|
|
19089
18731
|
}, null, 2);
|
|
19090
|
-
}
|
|
19091
|
-
const result = runDoraCommand(["cycles"]);
|
|
19092
|
-
if (!result.success) {
|
|
18732
|
+
} catch (error45) {
|
|
19093
18733
|
return JSON.stringify({
|
|
19094
18734
|
success: false,
|
|
19095
|
-
error:
|
|
18735
|
+
error: error45 instanceof Error ? error45.message : String(error45)
|
|
19096
18736
|
}, null, 2);
|
|
19097
18737
|
}
|
|
19098
|
-
return JSON.stringify({
|
|
19099
|
-
success: true,
|
|
19100
|
-
cycles: result.output
|
|
19101
|
-
}, null, 2);
|
|
19102
18738
|
}
|
|
19103
18739
|
});
|
|
19104
|
-
var
|
|
19105
|
-
description: `Find
|
|
18740
|
+
var astGrepFindCodeTool = tool({
|
|
18741
|
+
description: `Find code in a project folder that matches the given ast-grep pattern.
|
|
19106
18742
|
|
|
19107
|
-
|
|
19108
|
-
\`\`\`
|
|
19109
|
-
dora_unused()
|
|
19110
|
-
\`\`\`
|
|
18743
|
+
Pattern is good for simple and single-AST node result. For more complex usage, use ast_grep_scan_code.
|
|
19111
18744
|
|
|
19112
|
-
**
|
|
19113
|
-
|
|
19114
|
-
|
|
19115
|
-
|
|
19116
|
-
|
|
18745
|
+
**Parameters:**
|
|
18746
|
+
- project_folder: The absolute path to the project folder
|
|
18747
|
+
- pattern: The ast-grep pattern to search for (e.g., 'console.log($ARG)', '$VAR = $VALUE')
|
|
18748
|
+
- language: Optional - programming language filter
|
|
18749
|
+
|
|
18750
|
+
**Pattern Examples:**
|
|
18751
|
+
- 'console.log($ARG)' - Match console.log with any argument
|
|
18752
|
+
- '$VAR = $VALUE' - Match any assignment
|
|
18753
|
+
- 'function $NAME($PARAMS) { $BODY }' - Match function declarations`,
|
|
18754
|
+
args: {
|
|
18755
|
+
project_folder: tool.schema.string().describe("The absolute path to the project folder"),
|
|
18756
|
+
pattern: tool.schema.string().describe("The ast-grep pattern to search for"),
|
|
18757
|
+
language: tool.schema.string().optional().describe("Programming language filter (typescript, javascript, python, etc.)")
|
|
18758
|
+
},
|
|
18759
|
+
async execute({ project_folder, pattern, language }) {
|
|
18760
|
+
await initAstGrep();
|
|
18761
|
+
if (!astGrepModule) {
|
|
19117
18762
|
return JSON.stringify({
|
|
19118
18763
|
success: false,
|
|
19119
|
-
error: "
|
|
18764
|
+
error: "@ast-grep/napi not available",
|
|
18765
|
+
hint: "Install @ast-grep/napi or use MCP-based ast_grep"
|
|
19120
18766
|
}, null, 2);
|
|
19121
18767
|
}
|
|
19122
|
-
|
|
19123
|
-
|
|
18768
|
+
try {
|
|
18769
|
+
if (!fs7.existsSync(project_folder)) {
|
|
18770
|
+
return JSON.stringify({
|
|
18771
|
+
success: false,
|
|
18772
|
+
error: `Path not found: ${project_folder}`
|
|
18773
|
+
}, null, 2);
|
|
18774
|
+
}
|
|
18775
|
+
const langMap = {
|
|
18776
|
+
typescript: "TypeScript",
|
|
18777
|
+
javascript: "JavaScript",
|
|
18778
|
+
tsx: "Tsx",
|
|
18779
|
+
jsx: "Jsx",
|
|
18780
|
+
python: "Python",
|
|
18781
|
+
rust: "Rust",
|
|
18782
|
+
go: "Go",
|
|
18783
|
+
java: "Java"
|
|
18784
|
+
};
|
|
18785
|
+
const lang = language ? langMap[language.toLowerCase()] || language : "TypeScript";
|
|
18786
|
+
const Lang = astGrepModule.Lang;
|
|
18787
|
+
if (!Lang[lang]) {
|
|
18788
|
+
return JSON.stringify({
|
|
18789
|
+
success: false,
|
|
18790
|
+
error: `Unsupported language: ${language}`
|
|
18791
|
+
}, null, 2);
|
|
18792
|
+
}
|
|
18793
|
+
const findInFiles = astGrepModule.findInFiles;
|
|
18794
|
+
const results = [];
|
|
18795
|
+
await findInFiles(Lang[lang], {
|
|
18796
|
+
paths: [project_folder],
|
|
18797
|
+
matcher: { rule: { pattern } }
|
|
18798
|
+
}, (err, node) => {
|
|
18799
|
+
if (err) {
|
|
18800
|
+
console.warn("[ast-grep] Search error:", err);
|
|
18801
|
+
return;
|
|
18802
|
+
}
|
|
18803
|
+
if (node) {
|
|
18804
|
+
const text = node.text();
|
|
18805
|
+
const range = node.range();
|
|
18806
|
+
results.push({
|
|
18807
|
+
file: node.filename() || "unknown",
|
|
18808
|
+
line: range ? range.start.index : 0,
|
|
18809
|
+
column: range ? range.start.column : 0,
|
|
18810
|
+
matched: text.slice(0, 100)
|
|
18811
|
+
});
|
|
18812
|
+
}
|
|
18813
|
+
});
|
|
19124
18814
|
return JSON.stringify({
|
|
19125
|
-
success:
|
|
19126
|
-
|
|
18815
|
+
success: true,
|
|
18816
|
+
count: results.length,
|
|
18817
|
+
matches: results.slice(0, 50)
|
|
19127
18818
|
}, 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 };
|
|
19144
|
-
} catch {
|
|
19145
|
-
return { installed: false };
|
|
19146
|
-
}
|
|
19147
|
-
}
|
|
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
|
-
});
|
|
19155
|
-
try {
|
|
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
|
-
}
|
|
19171
|
-
}
|
|
19172
|
-
}
|
|
19173
|
-
var autoCrStatusTool = tool({
|
|
19174
|
-
description: `Check auto-cr-cmd installation status.
|
|
19175
|
-
|
|
19176
|
-
**Returns:**
|
|
19177
|
-
- installed: Whether auto-cr-cmd is available
|
|
19178
|
-
- version: Auto-CR version
|
|
19179
|
-
- ready: Whether it's ready to scan
|
|
19180
|
-
|
|
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) {
|
|
18819
|
+
} catch (error45) {
|
|
19191
18820
|
return JSON.stringify({
|
|
19192
|
-
|
|
19193
|
-
|
|
19194
|
-
installation: "npm install auto-cr-cmd"
|
|
18821
|
+
success: false,
|
|
18822
|
+
error: error45 instanceof Error ? error45.message : String(error45)
|
|
19195
18823
|
}, null, 2);
|
|
19196
18824
|
}
|
|
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
18825
|
}
|
|
19211
18826
|
});
|
|
19212
|
-
var
|
|
19213
|
-
description: `
|
|
18827
|
+
var astGrepScanCodeTool = tool({
|
|
18828
|
+
description: `Analyze TypeScript/JS code for common bugs, performance issues and best practices.
|
|
19214
18829
|
|
|
19215
|
-
|
|
19216
|
-
- path: Directory path to scan (defaults to ./src)
|
|
19217
|
-
- language: Output language (en/zh, defaults to en)
|
|
18830
|
+
Uses AST-based analysis for precise detection without false positives. Essential for maintaining code quality and preventing runtime errors.
|
|
19218
18831
|
|
|
19219
|
-
**
|
|
19220
|
-
-
|
|
19221
|
-
-
|
|
19222
|
-
-
|
|
19223
|
-
-
|
|
19224
|
-
-
|
|
19225
|
-
- no-n2-array-lookup: O(n²) array operations
|
|
18832
|
+
**Detects:**
|
|
18833
|
+
- Type safety violations
|
|
18834
|
+
- Loose object types
|
|
18835
|
+
- Incorrect async patterns
|
|
18836
|
+
- Import style issues
|
|
18837
|
+
- Common bugs
|
|
19226
18838
|
|
|
19227
|
-
**
|
|
19228
|
-
|
|
19229
|
-
auto_cr_scan({ path: "./src" })
|
|
19230
|
-
\`\`\``,
|
|
18839
|
+
**Parameters:**
|
|
18840
|
+
- project_folder: Optional - path to scan (defaults to current directory)`,
|
|
19231
18841
|
args: {
|
|
19232
|
-
|
|
19233
|
-
language: tool.schema.string().optional().default("en").describe("Output language (en or zh)")
|
|
18842
|
+
project_folder: tool.schema.string().optional().describe("Path to scan (defaults to current directory)")
|
|
19234
18843
|
},
|
|
19235
|
-
async execute({
|
|
19236
|
-
|
|
19237
|
-
if (!
|
|
18844
|
+
async execute({ project_folder }) {
|
|
18845
|
+
await initAstGrep();
|
|
18846
|
+
if (!astGrepModule) {
|
|
18847
|
+
return JSON.stringify({
|
|
18848
|
+
success: false,
|
|
18849
|
+
error: "@ast-grep/napi not available",
|
|
18850
|
+
hint: "Install @ast-grep/napi or use MCP-based ast_grep"
|
|
18851
|
+
}, null, 2);
|
|
18852
|
+
}
|
|
18853
|
+
try {
|
|
18854
|
+
const scanPath = project_folder || process.cwd();
|
|
18855
|
+
if (!fs7.existsSync(scanPath)) {
|
|
18856
|
+
return JSON.stringify({
|
|
18857
|
+
success: false,
|
|
18858
|
+
error: `Path not found: ${scanPath}`
|
|
18859
|
+
}, null, 2);
|
|
18860
|
+
}
|
|
18861
|
+
const bugPatterns = [
|
|
18862
|
+
{ pattern: "await Promise.all($ARR)", severity: "warning", message: "Check if Promise.all is used correctly with async operations" },
|
|
18863
|
+
{ pattern: "JSON.parse($STR)", severity: "info", message: "Consider adding try-catch for JSON.parse" },
|
|
18864
|
+
{ pattern: "$VAR == $VAL", severity: "warning", message: "Use === instead of == for strict equality" }
|
|
18865
|
+
];
|
|
18866
|
+
const issues = [];
|
|
18867
|
+
const Lang = astGrepModule.Lang;
|
|
18868
|
+
const findInFiles = astGrepModule.findInFiles;
|
|
18869
|
+
for (const bug of bugPatterns) {
|
|
18870
|
+
await findInFiles(Lang.TypeScript, {
|
|
18871
|
+
paths: [scanPath],
|
|
18872
|
+
matcher: { rule: { pattern: bug.pattern } }
|
|
18873
|
+
}, (err, node) => {
|
|
18874
|
+
if (err || !node)
|
|
18875
|
+
return;
|
|
18876
|
+
issues.push({
|
|
18877
|
+
file: node.filename() || "unknown",
|
|
18878
|
+
line: node.range()?.start.index || 0,
|
|
18879
|
+
severity: bug.severity,
|
|
18880
|
+
message: bug.message,
|
|
18881
|
+
pattern: bug.pattern
|
|
18882
|
+
});
|
|
18883
|
+
});
|
|
18884
|
+
}
|
|
19238
18885
|
return JSON.stringify({
|
|
19239
|
-
success:
|
|
19240
|
-
|
|
19241
|
-
|
|
18886
|
+
success: true,
|
|
18887
|
+
scanned: scanPath,
|
|
18888
|
+
issuesFound: issues.length,
|
|
18889
|
+
issues: issues.slice(0, 20),
|
|
18890
|
+
summary: issues.length === 0 ? "No common issues detected" : `Found ${issues.length} potential issues`
|
|
19242
18891
|
}, null, 2);
|
|
19243
|
-
}
|
|
19244
|
-
if (!fs7.existsSync(path7)) {
|
|
18892
|
+
} catch (error45) {
|
|
19245
18893
|
return JSON.stringify({
|
|
19246
18894
|
success: false,
|
|
19247
|
-
error:
|
|
18895
|
+
error: error45 instanceof Error ? error45.message : String(error45)
|
|
19248
18896
|
}, null, 2);
|
|
19249
18897
|
}
|
|
19250
|
-
|
|
19251
|
-
|
|
18898
|
+
}
|
|
18899
|
+
});
|
|
18900
|
+
var astGrepRewriteCodeTool = tool({
|
|
18901
|
+
description: `Transform and refactor code using AST-based find-and-replace patterns.
|
|
18902
|
+
|
|
18903
|
+
Use metavariables ($VAR, $$$VARS) in both pattern and replacement.
|
|
18904
|
+
|
|
18905
|
+
**Example:** Find 'console.log($ARG)' and replace with 'logger.info($ARG)'
|
|
18906
|
+
|
|
18907
|
+
**Parameters:**
|
|
18908
|
+
- project_folder: Path to the project folder
|
|
18909
|
+
- pattern: AST pattern to find
|
|
18910
|
+
- replacement: Replacement pattern
|
|
18911
|
+
- language: Programming language (defaults to TypeScript)`,
|
|
18912
|
+
args: {
|
|
18913
|
+
project_folder: tool.schema.string().describe("Path to the project folder"),
|
|
18914
|
+
pattern: tool.schema.string().describe("AST pattern to find"),
|
|
18915
|
+
replacement: tool.schema.string().describe("Replacement pattern"),
|
|
18916
|
+
language: tool.schema.string().optional().default("TypeScript").describe("Programming language")
|
|
18917
|
+
},
|
|
18918
|
+
async execute({ project_folder, pattern, replacement, language }) {
|
|
18919
|
+
await initAstGrep();
|
|
18920
|
+
if (!astGrepModule) {
|
|
19252
18921
|
return JSON.stringify({
|
|
19253
18922
|
success: false,
|
|
19254
|
-
error:
|
|
18923
|
+
error: "@ast-grep/napi not available",
|
|
18924
|
+
hint: "Install @ast-grep/napi or use MCP-based ast_grep"
|
|
19255
18925
|
}, null, 2);
|
|
19256
18926
|
}
|
|
19257
|
-
|
|
19258
|
-
|
|
18927
|
+
try {
|
|
18928
|
+
if (!fs7.existsSync(project_folder)) {
|
|
18929
|
+
return JSON.stringify({
|
|
18930
|
+
success: false,
|
|
18931
|
+
error: `Path not found: ${project_folder}`
|
|
18932
|
+
}, null, 2);
|
|
18933
|
+
}
|
|
18934
|
+
const Lang = astGrepModule.Lang;
|
|
18935
|
+
if (!Lang[language]) {
|
|
18936
|
+
return JSON.stringify({
|
|
18937
|
+
success: false,
|
|
18938
|
+
error: `Unsupported language: ${language}`
|
|
18939
|
+
}, null, 2);
|
|
18940
|
+
}
|
|
19259
18941
|
return JSON.stringify({
|
|
19260
18942
|
success: true,
|
|
19261
|
-
|
|
19262
|
-
|
|
19263
|
-
|
|
19264
|
-
|
|
19265
|
-
|
|
19266
|
-
|
|
19267
|
-
|
|
19268
|
-
|
|
19269
|
-
|
|
19270
|
-
|
|
19271
|
-
|
|
19272
|
-
|
|
19273
|
-
|
|
19274
|
-
|
|
19275
|
-
severity: v.severity,
|
|
19276
|
-
message: v.message,
|
|
19277
|
-
line: v.line
|
|
19278
|
-
}))
|
|
19279
|
-
})),
|
|
19280
|
-
notifications: notifications || []
|
|
18943
|
+
operation: "info",
|
|
18944
|
+
message: "Full rewrite requires @ast-grep/cli with config file",
|
|
18945
|
+
suggestion: "Use ast_grep_find_code to find matches, then hive_code_edit for individual replacements",
|
|
18946
|
+
parameters: {
|
|
18947
|
+
projectFolder: project_folder,
|
|
18948
|
+
pattern,
|
|
18949
|
+
replacement,
|
|
18950
|
+
language
|
|
18951
|
+
}
|
|
18952
|
+
}, null, 2);
|
|
18953
|
+
} catch (error45) {
|
|
18954
|
+
return JSON.stringify({
|
|
18955
|
+
success: false,
|
|
18956
|
+
error: error45 instanceof Error ? error45.message : String(error45)
|
|
19281
18957
|
}, null, 2);
|
|
19282
18958
|
}
|
|
19283
|
-
return JSON.stringify({
|
|
19284
|
-
success: true,
|
|
19285
|
-
scanned: path7,
|
|
19286
|
-
rawOutput: result.output
|
|
19287
|
-
}, null, 2);
|
|
19288
18959
|
}
|
|
19289
18960
|
});
|
|
19290
|
-
var
|
|
19291
|
-
description: `
|
|
19292
|
-
|
|
19293
|
-
**Use case:** Run in CI to check only changed files.
|
|
18961
|
+
var astGrepAnalyzeImportsTool = tool({
|
|
18962
|
+
description: `Analyze import statements and dependencies in your codebase.
|
|
19294
18963
|
|
|
19295
|
-
|
|
19296
|
-
\`\`\`bash
|
|
19297
|
-
git diff --name-only -z | xargs -0 auto-cr-cmd --stdin --output json
|
|
19298
|
-
\`\`\`
|
|
18964
|
+
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).
|
|
19299
18965
|
|
|
19300
|
-
**
|
|
18966
|
+
**Parameters:**
|
|
18967
|
+
- mode: "usage" (default) shows where imports are used, "discovery" shows all imports
|
|
18968
|
+
- path: Specific directory or file to analyze (defaults to current directory)`,
|
|
19301
18969
|
args: {
|
|
19302
|
-
|
|
18970
|
+
mode: tool.schema.enum(["usage", "discovery"]).default("usage").describe("Analysis mode"),
|
|
18971
|
+
path: tool.schema.string().optional().describe("Directory or file to analyze")
|
|
19303
18972
|
},
|
|
19304
|
-
async execute({
|
|
19305
|
-
|
|
19306
|
-
if (!
|
|
18973
|
+
async execute({ mode, path: path7 }) {
|
|
18974
|
+
await initAstGrep();
|
|
18975
|
+
if (!astGrepModule) {
|
|
19307
18976
|
return JSON.stringify({
|
|
19308
18977
|
success: false,
|
|
19309
|
-
error: "
|
|
19310
|
-
hint: "npm install auto-cr-cmd"
|
|
18978
|
+
error: "@ast-grep/napi not available"
|
|
19311
18979
|
}, null, 2);
|
|
19312
18980
|
}
|
|
19313
|
-
|
|
19314
|
-
|
|
19315
|
-
|
|
19316
|
-
|
|
19317
|
-
|
|
19318
|
-
|
|
19319
|
-
});
|
|
19320
|
-
var autoCrRulesTool = tool({
|
|
19321
|
-
description: `List available auto-cr rules and their descriptions.
|
|
19322
|
-
|
|
19323
|
-
**Returns:** All built-in rules with descriptions.`,
|
|
19324
|
-
args: {},
|
|
19325
|
-
async execute() {
|
|
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"
|
|
18981
|
+
try {
|
|
18982
|
+
const analyzePath = path7 || process.cwd();
|
|
18983
|
+
if (!fs7.existsSync(analyzePath)) {
|
|
18984
|
+
return JSON.stringify({
|
|
18985
|
+
success: false,
|
|
18986
|
+
error: `Path not found: ${analyzePath}`
|
|
18987
|
+
}, null, 2);
|
|
19362
18988
|
}
|
|
19363
|
-
|
|
19364
|
-
|
|
19365
|
-
|
|
19366
|
-
|
|
19367
|
-
|
|
19368
|
-
|
|
18989
|
+
const Lang = astGrepModule.Lang;
|
|
18990
|
+
const findInFiles = astGrepModule.findInFiles;
|
|
18991
|
+
const imports = {};
|
|
18992
|
+
await findInFiles(Lang.TypeScript, {
|
|
18993
|
+
paths: [analyzePath],
|
|
18994
|
+
matcher: { rule: { kind: "import_statement" } }
|
|
18995
|
+
}, (err, node) => {
|
|
18996
|
+
if (err || !node)
|
|
18997
|
+
return;
|
|
18998
|
+
const text = node.text();
|
|
18999
|
+
const match = text.match(/from ['"]([^'"]+)['"]/);
|
|
19000
|
+
if (match) {
|
|
19001
|
+
const module = match[1];
|
|
19002
|
+
const file2 = node.filename() || "unknown";
|
|
19003
|
+
if (!imports[module]) {
|
|
19004
|
+
imports[module] = [];
|
|
19005
|
+
}
|
|
19006
|
+
if (!imports[module].includes(file2)) {
|
|
19007
|
+
imports[module].push(file2);
|
|
19008
|
+
}
|
|
19009
|
+
}
|
|
19010
|
+
});
|
|
19011
|
+
if (mode === "usage") {
|
|
19012
|
+
return JSON.stringify({
|
|
19013
|
+
success: true,
|
|
19014
|
+
mode: "usage",
|
|
19015
|
+
imports: Object.entries(imports).map(([module, files]) => ({
|
|
19016
|
+
module,
|
|
19017
|
+
importCount: 1,
|
|
19018
|
+
filesCount: files.length
|
|
19019
|
+
})),
|
|
19020
|
+
note: "Full usage analysis requires @ast-grep/cli"
|
|
19021
|
+
}, null, 2);
|
|
19022
|
+
}
|
|
19023
|
+
return JSON.stringify({
|
|
19024
|
+
success: true,
|
|
19025
|
+
mode: "discovery",
|
|
19026
|
+
totalModules: Object.keys(imports).length,
|
|
19027
|
+
imports: Object.entries(imports).map(([module, files]) => ({
|
|
19028
|
+
module,
|
|
19029
|
+
importCount: files.length,
|
|
19030
|
+
files: files.slice(0, 5)
|
|
19031
|
+
}))
|
|
19032
|
+
}, null, 2);
|
|
19033
|
+
} catch (error45) {
|
|
19034
|
+
return JSON.stringify({
|
|
19035
|
+
success: false,
|
|
19036
|
+
error: error45 instanceof Error ? error45.message : String(error45)
|
|
19037
|
+
}, null, 2);
|
|
19038
|
+
}
|
|
19369
19039
|
}
|
|
19370
19040
|
});
|
|
19371
19041
|
|
|
@@ -20696,12 +20366,6 @@ var grepAppMcp = {
|
|
|
20696
20366
|
oauth: false
|
|
20697
20367
|
};
|
|
20698
20368
|
|
|
20699
|
-
// src/mcp/ast-grep.ts
|
|
20700
|
-
var astGrepMcp = {
|
|
20701
|
-
type: "local",
|
|
20702
|
-
command: ["npx", "-y", "@notprolands/ast-grep-mcp"]
|
|
20703
|
-
};
|
|
20704
|
-
|
|
20705
20369
|
// src/mcp/pare-search.ts
|
|
20706
20370
|
var pareSearchMcp = {
|
|
20707
20371
|
type: "local",
|
|
@@ -20714,14 +20378,20 @@ var veilMcp = {
|
|
|
20714
20378
|
command: ["npx", "-y", "@ushiradineth/veil@latest", "mcp", "server"]
|
|
20715
20379
|
};
|
|
20716
20380
|
|
|
20381
|
+
// src/mcp/ast-grep.ts
|
|
20382
|
+
var astGrepMcp = {
|
|
20383
|
+
type: "local",
|
|
20384
|
+
command: ["npx", "-y", "@notprolands/ast-grep-mcp"]
|
|
20385
|
+
};
|
|
20386
|
+
|
|
20717
20387
|
// src/mcp/index.ts
|
|
20718
20388
|
var allBuiltinMcps = {
|
|
20719
20389
|
websearch: websearchMcp,
|
|
20720
20390
|
context7: context7Mcp,
|
|
20721
20391
|
grep_app: grepAppMcp,
|
|
20722
|
-
ast_grep: astGrepMcp,
|
|
20723
20392
|
pare_search: pareSearchMcp,
|
|
20724
|
-
veil: veilMcp
|
|
20393
|
+
veil: veilMcp,
|
|
20394
|
+
ast_grep: astGrepMcp
|
|
20725
20395
|
};
|
|
20726
20396
|
var createBuiltinMcps = (disabledMcps = []) => {
|
|
20727
20397
|
const disabled = new Set(disabledMcps);
|
|
@@ -20753,7 +20423,7 @@ import * as fs11 from "fs";
|
|
|
20753
20423
|
import * as path8 from "path";
|
|
20754
20424
|
import { existsSync as existsSync52 } from "fs";
|
|
20755
20425
|
import { join as join92, sep } from "path";
|
|
20756
|
-
import { execSync as
|
|
20426
|
+
import { execSync as execSync5 } from "child_process";
|
|
20757
20427
|
var __create2 = Object.create;
|
|
20758
20428
|
var __getProtoOf2 = Object.getPrototypeOf;
|
|
20759
20429
|
var __defProp2 = Object.defineProperty;
|
|
@@ -27618,10 +27288,10 @@ class DockerSandboxService {
|
|
|
27618
27288
|
static ensureContainer(worktreePath, image) {
|
|
27619
27289
|
const name = this.containerName(worktreePath);
|
|
27620
27290
|
try {
|
|
27621
|
-
|
|
27291
|
+
execSync5(`docker inspect --format='{{.State.Running}}' ${name}`, { stdio: "pipe" });
|
|
27622
27292
|
return name;
|
|
27623
27293
|
} catch {
|
|
27624
|
-
|
|
27294
|
+
execSync5(`docker run -d --name ${name} -v ${worktreePath}:/app -w /app ${image} tail -f /dev/null`, { stdio: "pipe" });
|
|
27625
27295
|
return name;
|
|
27626
27296
|
}
|
|
27627
27297
|
}
|
|
@@ -27632,12 +27302,12 @@ class DockerSandboxService {
|
|
|
27632
27302
|
static stopContainer(worktreePath) {
|
|
27633
27303
|
const name = this.containerName(worktreePath);
|
|
27634
27304
|
try {
|
|
27635
|
-
|
|
27305
|
+
execSync5(`docker rm -f ${name}`, { stdio: "ignore" });
|
|
27636
27306
|
} catch {}
|
|
27637
27307
|
}
|
|
27638
27308
|
static isDockerAvailable() {
|
|
27639
27309
|
try {
|
|
27640
|
-
|
|
27310
|
+
execSync5("docker info", { stdio: "ignore" });
|
|
27641
27311
|
return true;
|
|
27642
27312
|
} catch {
|
|
27643
27313
|
return false;
|
|
@@ -28988,12 +28658,6 @@ ${snapshot}
|
|
|
28988
28658
|
hive_vector_search: hiveVectorSearchTool,
|
|
28989
28659
|
hive_vector_add: hiveVectorAddTool,
|
|
28990
28660
|
hive_vector_status: hiveVectorStatusTool,
|
|
28991
|
-
ast_grep_dump_syntax_tree: astGrepDumpSyntaxTreeTool,
|
|
28992
|
-
ast_grep_test_match_code_rule: astGrepTestMatchCodeRuleTool,
|
|
28993
|
-
ast_grep_find_code: astGrepFindCodeTool,
|
|
28994
|
-
ast_grep_scan_code: astGrepScanCodeTool,
|
|
28995
|
-
ast_grep_rewrite_code: astGrepRewriteCodeTool,
|
|
28996
|
-
ast_grep_analyze_imports: astGrepAnalyzeImportsTool,
|
|
28997
28661
|
hive_doctor: hiveDoctorTool,
|
|
28998
28662
|
hive_doctor_quick: hiveDoctorQuickTool,
|
|
28999
28663
|
dora_status: doraStatusTool,
|
|
@@ -29006,6 +28670,12 @@ ${snapshot}
|
|
|
29006
28670
|
auto_cr_scan: autoCrScanTool,
|
|
29007
28671
|
auto_cr_diff: autoCrDiffTool,
|
|
29008
28672
|
auto_cr_rules: autoCrRulesTool,
|
|
28673
|
+
ast_grep_dump_syntax_tree: astGrepDumpSyntaxTreeTool,
|
|
28674
|
+
ast_grep_test_match_code_rule: astGrepTestMatchCodeRuleTool,
|
|
28675
|
+
ast_grep_find_code: astGrepFindCodeTool,
|
|
28676
|
+
ast_grep_scan_code: astGrepScanCodeTool,
|
|
28677
|
+
ast_grep_rewrite_code: astGrepRewriteCodeTool,
|
|
28678
|
+
ast_grep_analyze_imports: astGrepAnalyzeImportsTool,
|
|
29009
28679
|
hive_skill: createHiveSkillTool(filteredSkills),
|
|
29010
28680
|
hive_feature_create: tool({
|
|
29011
28681
|
description: "Create a new feature and set it as active",
|