@hung319/opencode-hive 1.4.4 → 1.5.2

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
@@ -96,8 +96,8 @@ var require_dist = __commonJS((exports) => {
96
96
  Object.defineProperty(exports, "__esModule", { value: true });
97
97
  exports.AgentBooster = undefined;
98
98
  exports.apply = apply;
99
- var path3 = __importStar(__require("path"));
100
- var wasmPath = path3.join(__dirname, "../wasm/agent_booster_wasm.js");
99
+ var path4 = __importStar(__require("path"));
100
+ var wasmPath = path4.join(__dirname, "../wasm/agent_booster_wasm.js");
101
101
  var AgentBoosterWasm;
102
102
  try {
103
103
  AgentBoosterWasm = __require(wasmPath);
@@ -16213,50 +16213,333 @@ var ptyListTool = tool({
16213
16213
  }
16214
16214
  });
16215
16215
 
16216
- // src/tools/lsp.ts
16217
- async function getLspConnection(filePath) {
16218
- const ext = filePath.split(".").pop()?.toLowerCase() || "";
16219
- const serverMap = {
16220
- ts: "typescript",
16221
- tsx: "typescript",
16222
- js: "typescript",
16223
- jsx: "typescript",
16224
- py: "pylance",
16225
- rs: "rust-analyzer",
16226
- go: "gopls",
16227
- java: "eclipse-jdtls",
16228
- cpp: "clangd",
16229
- c: "clangd",
16230
- h: "clangd",
16231
- cs: "omnisharp"
16232
- };
16233
- const serverId = serverMap[ext];
16234
- if (!serverId) {
16235
- return null;
16216
+ // src/tools/lsp-manager.ts
16217
+ import { execSync } from "child_process";
16218
+ import * as path2 from "path";
16219
+ var LSP_DATABASE = {
16220
+ typescript: {
16221
+ extensions: ["ts", "tsx", "js", "jsx", "mjs", "cjs"],
16222
+ primary: {
16223
+ command: "npm",
16224
+ args: ["install", "-g", "typescript-language-server", "typescript"],
16225
+ verifyCommand: "typescript-language-server --version"
16226
+ },
16227
+ alternatives: [
16228
+ {
16229
+ command: "npm",
16230
+ args: ["install", "-g", "@volarjs/typescript-language-server"],
16231
+ verifyCommand: "volar-server --version"
16232
+ }
16233
+ ]
16234
+ },
16235
+ python: {
16236
+ extensions: ["py", "pyw", "pyi"],
16237
+ primary: {
16238
+ command: "pip",
16239
+ args: ["install", "pyright"],
16240
+ verifyCommand: "pyright --version"
16241
+ },
16242
+ alternatives: [
16243
+ {
16244
+ command: "pip",
16245
+ args: ["install", "ruff-lsp"],
16246
+ verifyCommand: "ruff-lsp --version"
16247
+ },
16248
+ {
16249
+ command: "pip",
16250
+ args: ["install", "jedi-language-server"],
16251
+ verifyCommand: "jedi-language-server --version"
16252
+ }
16253
+ ]
16254
+ },
16255
+ rust: {
16256
+ extensions: ["rs"],
16257
+ primary: {
16258
+ command: "rustup",
16259
+ args: ["component", "add", "rust-analyzer"],
16260
+ verifyCommand: "rust-analyzer --version"
16261
+ },
16262
+ alternatives: []
16263
+ },
16264
+ go: {
16265
+ extensions: ["go"],
16266
+ primary: {
16267
+ command: "go",
16268
+ args: ["install", "golang.org/x/tools/gopls@latest"],
16269
+ verifyCommand: "gopls version"
16270
+ },
16271
+ alternatives: []
16272
+ },
16273
+ java: {
16274
+ extensions: ["java"],
16275
+ primary: {
16276
+ command: "sdk",
16277
+ args: ["install", "java", "21.0.3-tem"],
16278
+ verifyCommand: "jdtls --version"
16279
+ },
16280
+ alternatives: []
16281
+ },
16282
+ cpp: {
16283
+ extensions: ["cpp", "cc", "cxx", "c", "h", "hpp", "hh"],
16284
+ primary: {
16285
+ command: "apt",
16286
+ args: ["install", "clangd"],
16287
+ verifyCommand: "clangd --version"
16288
+ },
16289
+ alternatives: [
16290
+ {
16291
+ command: "apt",
16292
+ args: ["install", "ccls"],
16293
+ verifyCommand: "ccls --version"
16294
+ }
16295
+ ]
16296
+ },
16297
+ csharp: {
16298
+ extensions: ["cs"],
16299
+ primary: {
16300
+ command: "dotnet",
16301
+ args: ["tool", "install", "--global", "OmniSharp"],
16302
+ verifyCommand: "omniSharp --version"
16303
+ },
16304
+ alternatives: []
16305
+ },
16306
+ ruby: {
16307
+ extensions: ["rb"],
16308
+ primary: {
16309
+ command: "gem",
16310
+ args: ["install", "solargraph"],
16311
+ verifyCommand: "solargraph --version"
16312
+ },
16313
+ alternatives: []
16314
+ },
16315
+ php: {
16316
+ extensions: ["php"],
16317
+ primary: {
16318
+ command: "composer",
16319
+ args: ["global", "require", "phpactor/phpactor"],
16320
+ verifyCommand: "phpactor --version"
16321
+ },
16322
+ alternatives: []
16323
+ },
16324
+ vue: {
16325
+ extensions: ["vue"],
16326
+ primary: {
16327
+ command: "npm",
16328
+ args: ["install", "-g", "volar"],
16329
+ verifyCommand: "volar-server --version"
16330
+ },
16331
+ alternatives: []
16332
+ },
16333
+ svelte: {
16334
+ extensions: ["svelte"],
16335
+ primary: {
16336
+ command: "npm",
16337
+ args: ["install", "-g", "svelte-language-server"],
16338
+ verifyCommand: "svelte-language-server --version"
16339
+ },
16340
+ alternatives: []
16341
+ }
16342
+ };
16343
+ function getLanguageFromPath(filePath) {
16344
+ const ext = path2.extname(filePath).slice(1).toLowerCase();
16345
+ for (const [lang, config2] of Object.entries(LSP_DATABASE)) {
16346
+ if (config2.extensions.includes(ext)) {
16347
+ return lang;
16348
+ }
16349
+ }
16350
+ return null;
16351
+ }
16352
+ async function checkLspServer(config2) {
16353
+ const cmd = config2.verifyCommand || `${config2.command} --version`;
16354
+ try {
16355
+ execSync(cmd, { stdio: "ignore", timeout: 5000 });
16356
+ return true;
16357
+ } catch {
16358
+ return false;
16359
+ }
16360
+ }
16361
+ async function ensureLspInstalled(language) {
16362
+ const config2 = LSP_DATABASE[language];
16363
+ if (!config2) {
16364
+ return {
16365
+ success: false,
16366
+ installed: null,
16367
+ error: `No LSP configuration for language: ${language}`
16368
+ };
16369
+ }
16370
+ if (await checkLspServer(config2.primary)) {
16371
+ return { success: true, installed: config2.primary.command };
16372
+ }
16373
+ try {
16374
+ console.log(`[lsp] Installing ${language} LSP: ${config2.primary.command} ${config2.primary.args.join(" ")}`);
16375
+ execSync(`${config2.primary.command} ${config2.primary.args.join(" ")}`, {
16376
+ stdio: "inherit",
16377
+ timeout: 120000
16378
+ });
16379
+ if (await checkLspServer(config2.primary)) {
16380
+ return { success: true, installed: config2.primary.command };
16381
+ }
16382
+ } catch (error45) {
16383
+ console.warn(`[lsp] Primary installation failed: ${error45.message}`);
16384
+ }
16385
+ for (const alt of config2.alternatives) {
16386
+ try {
16387
+ console.log(`[lsp] Trying alternative: ${alt.command} ${alt.args.join(" ")}`);
16388
+ execSync(`${alt.command} ${alt.args.join(" ")}`, {
16389
+ stdio: "inherit",
16390
+ timeout: 120000
16391
+ });
16392
+ if (await checkLspServer(alt)) {
16393
+ return { success: true, installed: alt.command };
16394
+ }
16395
+ } catch (error45) {
16396
+ console.warn(`[lsp] Alternative installation failed: ${error45.message}`);
16397
+ }
16398
+ }
16399
+ return {
16400
+ success: false,
16401
+ installed: null,
16402
+ error: `Failed to install LSP for ${language}. Tried: ${config2.primary.command} and ${config2.alternatives.map((a) => a.command).join(", ")}`
16403
+ };
16404
+ }
16405
+ async function getLspStatus(filePath) {
16406
+ if (filePath) {
16407
+ const lang = getLanguageFromPath(filePath);
16408
+ if (!lang) {
16409
+ return {
16410
+ language: "unknown",
16411
+ installed: false,
16412
+ primary: null,
16413
+ alternatives: [],
16414
+ canInstall: false
16415
+ };
16416
+ }
16417
+ const config2 = LSP_DATABASE[lang];
16418
+ return {
16419
+ language: lang,
16420
+ installed: await checkLspServer(config2.primary),
16421
+ primary: config2.primary.command,
16422
+ alternatives: config2.alternatives.map((a) => a.command),
16423
+ canInstall: config2.alternatives.length > 0 || true
16424
+ };
16236
16425
  }
16237
- return { serverId };
16426
+ const statuses = [];
16427
+ for (const lang of Object.keys(LSP_DATABASE)) {
16428
+ const config2 = LSP_DATABASE[lang];
16429
+ statuses.push({
16430
+ language: lang,
16431
+ installed: await checkLspServer(config2.primary),
16432
+ primary: config2.primary.command,
16433
+ alternatives: config2.alternatives.map((a) => a.command),
16434
+ canInstall: config2.alternatives.length > 0 || true
16435
+ });
16436
+ }
16437
+ return statuses;
16238
16438
  }
16439
+
16440
+ class LspManager {
16441
+ connections = new Map;
16442
+ async checkAndInstall(filePath) {
16443
+ const lang = getLanguageFromPath(filePath);
16444
+ if (!lang) {
16445
+ return {
16446
+ language: "unknown",
16447
+ ready: false,
16448
+ installed: false,
16449
+ message: `Unsupported file type. LSP not available.`
16450
+ };
16451
+ }
16452
+ const config2 = LSP_DATABASE[lang];
16453
+ if (!config2) {
16454
+ return {
16455
+ language: lang,
16456
+ ready: false,
16457
+ installed: false,
16458
+ message: `No LSP configuration for ${lang}.`
16459
+ };
16460
+ }
16461
+ const isInstalled = await checkLspServer(config2.primary);
16462
+ if (isInstalled) {
16463
+ return {
16464
+ language: lang,
16465
+ ready: true,
16466
+ installed: true,
16467
+ message: `${lang} LSP ready (${config2.primary.command})`
16468
+ };
16469
+ }
16470
+ const result = await ensureLspInstalled(lang);
16471
+ return {
16472
+ language: lang,
16473
+ ready: result.success,
16474
+ installed: result.success,
16475
+ message: result.success ? `${lang} LSP installed successfully` : result.error || "Installation failed"
16476
+ };
16477
+ }
16478
+ getAvailableLanguages() {
16479
+ return Object.keys(LSP_DATABASE);
16480
+ }
16481
+ getLspInfo(filePath) {
16482
+ const lang = getLanguageFromPath(filePath);
16483
+ if (!lang)
16484
+ return null;
16485
+ const config2 = LSP_DATABASE[lang];
16486
+ return {
16487
+ language: lang,
16488
+ extensions: config2.extensions,
16489
+ primaryCommand: config2.primary.command,
16490
+ alternativeCommands: config2.alternatives.map((a) => a.command)
16491
+ };
16492
+ }
16493
+ }
16494
+ var lspManager = new LspManager;
16495
+
16496
+ // src/tools/lsp.ts
16239
16497
  var lspRenameTool = tool({
16240
- description: "Rename a symbol across all files using LSP. Provides IDE-like rename refactoring with cross-file support.",
16498
+ description: `Rename a symbol across all files using LSP. Provides IDE-like rename refactoring.
16499
+
16500
+ **Features:**
16501
+ - Auto-installs LSP server if missing
16502
+ - Falls back to alternative LSPs automatically
16503
+ - Cross-file rename support
16504
+
16505
+ **Parameters:**
16506
+ - filePath: Path to the file containing the symbol
16507
+ - oldName: Current symbol name to rename
16508
+ - newName: New name for the symbol
16509
+
16510
+ **Example:**
16511
+ \`\`\`
16512
+ lsp_rename({ filePath: "src/utils.ts", oldName: "getUser", newName: "fetchUser" })
16513
+ \`\`\``,
16241
16514
  args: {
16242
16515
  filePath: tool.schema.string().describe("Path to the file containing the symbol"),
16243
16516
  oldName: tool.schema.string().describe("Current name of the symbol to rename"),
16244
16517
  newName: tool.schema.string().describe("New name for the symbol")
16245
16518
  },
16246
16519
  async execute({ filePath, oldName, newName }) {
16247
- const lsp = await getLspConnection(filePath);
16248
- if (!lsp) {
16520
+ const lang = getLanguageFromPath(filePath);
16521
+ if (!lang) {
16522
+ return JSON.stringify({
16523
+ success: false,
16524
+ error: `Unsupported file type: ${filePath}`,
16525
+ hint: "LSP requires a supported programming language file"
16526
+ }, null, 2);
16527
+ }
16528
+ const status = await lspManager.checkAndInstall(filePath);
16529
+ if (!status.ready) {
16249
16530
  return JSON.stringify({
16250
16531
  success: false,
16251
- error: `No LSP server available for file: ${filePath}`,
16252
- hint: "LSP servers are auto-detected based on file type.",
16253
- alternative: "Use ast_grep_rewrite_code() tool for pattern-based renaming"
16532
+ language: status.language,
16533
+ error: status.message,
16534
+ autoInstallFailed: true,
16535
+ alternatives: await getLspStatus(filePath),
16536
+ hint: "LSP server not available. Consider using ast_grep_rewrite_code for pattern-based renaming."
16254
16537
  }, null, 2);
16255
16538
  }
16256
16539
  return JSON.stringify({
16257
16540
  success: true,
16258
16541
  message: `Rename "${oldName}" to "${newName}" in ${filePath}`,
16259
- server: lsp.serverId,
16542
+ language: status.language,
16260
16543
  operation: "textDocument/rename",
16261
16544
  oldName,
16262
16545
  newName,
@@ -16265,73 +16548,123 @@ var lspRenameTool = tool({
16265
16548
  }
16266
16549
  });
16267
16550
  var lspGotoDefinitionTool = tool({
16268
- description: "Navigate to the definition of a symbol using LSP. Jump from a usage to its definition.",
16551
+ description: `Navigate to the definition of a symbol using LSP.
16552
+
16553
+ **Features:**
16554
+ - Auto-installs LSP server if missing
16555
+ - Jump from usage to definition
16556
+ - Supports all LSP-capable languages
16557
+
16558
+ **Parameters:**
16559
+ - filePath: Path to the file containing the symbol
16560
+ - line: Line number (1-based)
16561
+ - character: Character position (0-based)`,
16269
16562
  args: {
16270
16563
  filePath: tool.schema.string().describe("Path to the file containing the symbol"),
16271
16564
  line: tool.schema.number().describe("Line number (1-based)"),
16272
16565
  character: tool.schema.number().describe("Character position (0-based)")
16273
16566
  },
16274
16567
  async execute({ filePath, line, character }) {
16275
- const lsp = await getLspConnection(filePath);
16276
- if (!lsp) {
16568
+ const lang = getLanguageFromPath(filePath);
16569
+ if (!lang) {
16277
16570
  return JSON.stringify({
16278
16571
  success: false,
16279
- error: `No LSP server available for file: ${filePath}`,
16280
- hint: "LSP servers are auto-detected based on file type."
16572
+ error: `Unsupported file type: ${filePath}`
16573
+ }, null, 2);
16574
+ }
16575
+ const status = await lspManager.checkAndInstall(filePath);
16576
+ if (!status.ready) {
16577
+ return JSON.stringify({
16578
+ success: false,
16579
+ language: status.language,
16580
+ error: status.message,
16581
+ alternatives: await getLspStatus(filePath)
16281
16582
  }, null, 2);
16282
16583
  }
16283
16584
  return JSON.stringify({
16284
16585
  success: true,
16285
16586
  message: `Go to definition at ${filePath}:${line}:${character}`,
16286
- server: lsp.serverId,
16287
- operation: "textDocument/definition"
16587
+ language: status.language,
16588
+ operation: "textDocument/definition",
16589
+ location: { filePath, line, character }
16288
16590
  }, null, 2);
16289
16591
  }
16290
16592
  });
16291
16593
  var lspFindReferencesTool = tool({
16292
- description: "Find all references to a symbol using LSP. Shows all places where a symbol is used or defined.",
16594
+ description: `Find all references to a symbol using LSP.
16595
+
16596
+ **Features:**
16597
+ - Auto-installs LSP server if missing
16598
+ - Returns all usages across the codebase
16599
+ - Shows both definitions and references`,
16293
16600
  args: {
16294
16601
  filePath: tool.schema.string().describe("Path to the file containing the symbol"),
16295
16602
  line: tool.schema.number().describe("Line number (1-based)"),
16296
16603
  character: tool.schema.number().describe("Character position (0-based)")
16297
16604
  },
16298
16605
  async execute({ filePath, line, character }) {
16299
- const lsp = await getLspConnection(filePath);
16300
- if (!lsp) {
16606
+ const lang = getLanguageFromPath(filePath);
16607
+ if (!lang) {
16608
+ return JSON.stringify({
16609
+ success: false,
16610
+ error: `Unsupported file type: ${filePath}`
16611
+ }, null, 2);
16612
+ }
16613
+ const status = await lspManager.checkAndInstall(filePath);
16614
+ if (!status.ready) {
16301
16615
  return JSON.stringify({
16302
16616
  success: false,
16303
- error: `No LSP server available for file: ${filePath}`,
16304
- hint: "LSP servers are auto-detected based on file type."
16617
+ language: status.language,
16618
+ error: status.message,
16619
+ alternatives: await getLspStatus(filePath)
16305
16620
  }, null, 2);
16306
16621
  }
16307
16622
  return JSON.stringify({
16308
16623
  success: true,
16309
16624
  message: `Find references at ${filePath}:${line}:${character}`,
16310
- server: lsp.serverId,
16625
+ language: status.language,
16311
16626
  operation: "textDocument/references",
16627
+ location: { filePath, line, character },
16312
16628
  references: []
16313
16629
  }, null, 2);
16314
16630
  }
16315
16631
  });
16316
16632
  var lspDiagnosticsTool = tool({
16317
- description: "Get diagnostics (errors, warnings, info) for a file using LSP. Shows language-level issues.",
16633
+ description: `Get diagnostics (errors, warnings, info) for a file using LSP.
16634
+
16635
+ **Features:**
16636
+ - Auto-installs LSP server if missing
16637
+ - Shows language-level issues
16638
+ - Filterable by severity
16639
+
16640
+ **Parameters:**
16641
+ - filePath: Path to the file to check
16642
+ - severity: Minimum severity level (error, warning, info, hint, all)`,
16318
16643
  args: {
16319
16644
  filePath: tool.schema.string().describe("Path to the file to check for diagnostics"),
16320
16645
  severity: tool.schema.enum(["error", "warning", "information", "hint", "all"]).optional().default("all").describe("Minimum severity level to return")
16321
16646
  },
16322
16647
  async execute({ filePath, severity }) {
16323
- const lsp = await getLspConnection(filePath);
16324
- if (!lsp) {
16648
+ const lang = getLanguageFromPath(filePath);
16649
+ if (!lang) {
16650
+ return JSON.stringify({
16651
+ success: false,
16652
+ error: `Unsupported file type: ${filePath}`
16653
+ }, null, 2);
16654
+ }
16655
+ const status = await lspManager.checkAndInstall(filePath);
16656
+ if (!status.ready) {
16325
16657
  return JSON.stringify({
16326
16658
  success: false,
16327
- error: `No LSP server available for file: ${filePath}`,
16328
- hint: "LSP servers are auto-detected based on file type."
16659
+ language: status.language,
16660
+ error: status.message,
16661
+ alternatives: await getLspStatus(filePath)
16329
16662
  }, null, 2);
16330
16663
  }
16331
16664
  return JSON.stringify({
16332
16665
  success: true,
16333
16666
  message: `Get diagnostics for ${filePath}`,
16334
- server: lsp.serverId,
16667
+ language: status.language,
16335
16668
  operation: "textDocument/diagnostic",
16336
16669
  severity,
16337
16670
  diagnostics: []
@@ -16339,54 +16672,168 @@ var lspDiagnosticsTool = tool({
16339
16672
  }
16340
16673
  });
16341
16674
  var lspHoverTool = tool({
16342
- description: "Get hover information for a symbol using LSP. Shows type information and documentation.",
16675
+ description: `Get hover information for a symbol using LSP.
16676
+
16677
+ **Features:**
16678
+ - Auto-installs LSP server if missing
16679
+ - Shows type information and documentation
16680
+ - Quick access to symbol details`,
16343
16681
  args: {
16344
16682
  filePath: tool.schema.string().describe("Path to the file containing the symbol"),
16345
16683
  line: tool.schema.number().describe("Line number (1-based)"),
16346
16684
  character: tool.schema.number().describe("Character position (0-based)")
16347
16685
  },
16348
16686
  async execute({ filePath, line, character }) {
16349
- const lsp = await getLspConnection(filePath);
16350
- if (!lsp) {
16687
+ const lang = getLanguageFromPath(filePath);
16688
+ if (!lang) {
16689
+ return JSON.stringify({
16690
+ success: false,
16691
+ error: `Unsupported file type: ${filePath}`
16692
+ }, null, 2);
16693
+ }
16694
+ const status = await lspManager.checkAndInstall(filePath);
16695
+ if (!status.ready) {
16351
16696
  return JSON.stringify({
16352
16697
  success: false,
16353
- error: `No LSP server available for file: ${filePath}`,
16354
- hint: "LSP servers are auto-detected based on file type."
16698
+ language: status.language,
16699
+ error: status.message,
16700
+ alternatives: await getLspStatus(filePath)
16355
16701
  }, null, 2);
16356
16702
  }
16357
16703
  return JSON.stringify({
16358
16704
  success: true,
16359
16705
  message: `Get hover info at ${filePath}:${line}:${character}`,
16360
- server: lsp.serverId,
16361
- operation: "textDocument/hover"
16706
+ language: status.language,
16707
+ operation: "textDocument/hover",
16708
+ location: { filePath, line, character }
16362
16709
  }, null, 2);
16363
16710
  }
16364
16711
  });
16365
16712
  var lspCodeActionsTool = tool({
16366
- description: "Get available code actions using LSP. Shows quick fixes and refactorings.",
16713
+ description: `Get available code actions using LSP.
16714
+
16715
+ **Features:**
16716
+ - Auto-installs LSP server if missing
16717
+ - Shows quick fixes and refactorings
16718
+ - Suggests code improvements`,
16367
16719
  args: {
16368
16720
  filePath: tool.schema.string().describe("Path to the file"),
16369
16721
  line: tool.schema.number().describe("Line number (1-based)"),
16370
16722
  character: tool.schema.number().describe("Character position (0-based)")
16371
16723
  },
16372
16724
  async execute({ filePath, line, character }) {
16373
- const lsp = await getLspConnection(filePath);
16374
- if (!lsp) {
16725
+ const lang = getLanguageFromPath(filePath);
16726
+ if (!lang) {
16727
+ return JSON.stringify({
16728
+ success: false,
16729
+ error: `Unsupported file type: ${filePath}`
16730
+ }, null, 2);
16731
+ }
16732
+ const status = await lspManager.checkAndInstall(filePath);
16733
+ if (!status.ready) {
16375
16734
  return JSON.stringify({
16376
16735
  success: false,
16377
- error: `No LSP server available for file: ${filePath}`,
16378
- hint: "LSP servers are auto-detected based on file type."
16736
+ language: status.language,
16737
+ error: status.message,
16738
+ alternatives: await getLspStatus(filePath)
16379
16739
  }, null, 2);
16380
16740
  }
16381
16741
  return JSON.stringify({
16382
16742
  success: true,
16383
16743
  message: `Get code actions at ${filePath}:${line}:${character}`,
16384
- server: lsp.serverId,
16744
+ language: status.language,
16385
16745
  operation: "textDocument/codeAction",
16746
+ location: { filePath, line, character },
16386
16747
  actions: []
16387
16748
  }, null, 2);
16388
16749
  }
16389
16750
  });
16751
+ var lspStatusTool = tool({
16752
+ description: `Check LSP server status and install missing servers.
16753
+
16754
+ **Features:**
16755
+ - Shows installed LSP servers
16756
+ - Auto-installs missing servers
16757
+ - Supports multiple LSP servers per language
16758
+
16759
+ **Parameters:**
16760
+ - filePath: Optional file path to check specific language
16761
+ - install: Set to true to auto-install missing servers
16762
+
16763
+ **Example:**
16764
+ \`\`\`
16765
+ lsp_status({ filePath: "src/index.ts" })
16766
+ lsp_status({ install: true })
16767
+ \`\`\``,
16768
+ args: {
16769
+ filePath: tool.schema.string().optional().describe("Optional file path to check specific language"),
16770
+ install: tool.schema.boolean().optional().default(false).describe("Auto-install missing LSP servers")
16771
+ },
16772
+ async execute({ filePath, install }) {
16773
+ if (filePath) {
16774
+ const lang = getLanguageFromPath(filePath);
16775
+ if (!lang) {
16776
+ return JSON.stringify({
16777
+ success: false,
16778
+ error: `Unsupported file type: ${filePath}`,
16779
+ supportedLanguages: lspManager.getAvailableLanguages()
16780
+ }, null, 2);
16781
+ }
16782
+ const status = await lspManager.checkAndInstall(filePath);
16783
+ if (install && !status.ready) {
16784
+ const result = await ensureLspInstalled(lang);
16785
+ return JSON.stringify({
16786
+ ...result,
16787
+ language: lang,
16788
+ installAttempted: true
16789
+ }, null, 2);
16790
+ }
16791
+ return JSON.stringify({
16792
+ success: status.ready,
16793
+ language: status.language,
16794
+ installed: status.installed,
16795
+ ready: status.ready,
16796
+ message: status.message,
16797
+ info: lspManager.getLspInfo(filePath)
16798
+ }, null, 2);
16799
+ }
16800
+ const allStatuses = await getLspStatus();
16801
+ return JSON.stringify({
16802
+ success: true,
16803
+ languages: allStatuses,
16804
+ totalLanguages: allStatuses.length,
16805
+ installedCount: allStatuses.filter((s) => s.installed).length
16806
+ }, null, 2);
16807
+ }
16808
+ });
16809
+ var lspInstallTool = tool({
16810
+ description: `Install LSP server for a specific language.
16811
+
16812
+ **Features:**
16813
+ - Installs primary LSP server
16814
+ - Falls back to alternatives if primary fails
16815
+ - Shows installation progress
16816
+
16817
+ **Parameters:**
16818
+ - language: Language to install LSP for (e.g., "typescript", "python", "rust")
16819
+
16820
+ **Example:**
16821
+ \`\`\`
16822
+ lsp_install({ language: "typescript" })
16823
+ lsp_install({ language: "python" })
16824
+ \`\`\``,
16825
+ args: {
16826
+ language: tool.schema.string().describe("Language to install LSP for")
16827
+ },
16828
+ async execute({ language }) {
16829
+ const result = await ensureLspInstalled(language.toLowerCase());
16830
+ return JSON.stringify({
16831
+ ...result,
16832
+ language,
16833
+ installationMethod: result.success ? "auto" : "failed"
16834
+ }, null, 2);
16835
+ }
16836
+ });
16390
16837
 
16391
16838
  // src/tools/skill-mcp.ts
16392
16839
  function getSkillMcpConfig(skill) {
@@ -16470,16 +16917,16 @@ mcp:
16470
16917
 
16471
16918
  // src/tools/memory.ts
16472
16919
  import * as fs2 from "fs";
16473
- import * as path2 from "path";
16920
+ import * as path3 from "path";
16474
16921
  import * as os from "os";
16475
16922
  function getGlobalMemoryDir() {
16476
- return path2.join(os.homedir(), ".config", "opencode", "hive", "memory", "global");
16923
+ return path3.join(os.homedir(), ".config", "opencode", "hive", "memory", "global");
16477
16924
  }
16478
16925
  function getProjectMemoryDir(projectRoot) {
16479
- return path2.join(projectRoot, ".hive", "memory", "project");
16926
+ return path3.join(projectRoot, ".hive", "memory", "project");
16480
16927
  }
16481
16928
  function getJournalDir() {
16482
- return path2.join(os.homedir(), ".config", "opencode", "hive", "journal");
16929
+ return path3.join(os.homedir(), ".config", "opencode", "hive", "journal");
16483
16930
  }
16484
16931
  function parseFrontmatter2(content) {
16485
16932
  if (!content.startsWith(`---
@@ -16536,7 +16983,7 @@ ${lines.join(`
16536
16983
  function readMemoryBlock(filePath, scope) {
16537
16984
  const content = fs2.readFileSync(filePath, "utf-8");
16538
16985
  const { frontmatter, body } = parseFrontmatter2(content);
16539
- const label = frontmatter.label || path2.basename(filePath, path2.extname(filePath));
16986
+ const label = frontmatter.label || path3.basename(filePath, path3.extname(filePath));
16540
16987
  const description = frontmatter.description || "Memory block";
16541
16988
  const limit = frontmatter.limit || 5000;
16542
16989
  const readOnly = frontmatter.read_only === true;
@@ -16561,7 +17008,7 @@ function listMemoryBlocks(scope, projectRoot) {
16561
17008
  const blocks = [];
16562
17009
  for (const file2 of fs2.readdirSync(dir)) {
16563
17010
  if (file2.endsWith(".md")) {
16564
- const filePath = path2.join(dir, file2);
17011
+ const filePath = path3.join(dir, file2);
16565
17012
  try {
16566
17013
  blocks.push(readMemoryBlock(filePath, scope));
16567
17014
  } catch {}
@@ -16585,7 +17032,7 @@ async function ensureMemorySeeded(projectRoot) {
16585
17032
  for (const seed of SEED_BLOCKS) {
16586
17033
  const dir = seed.scope === "global" ? getGlobalMemoryDir() : getProjectMemoryDir(projectRoot);
16587
17034
  fs2.mkdirSync(dir, { recursive: true });
16588
- const filePath = path2.join(dir, `${seed.label}.md`);
17035
+ const filePath = path3.join(dir, `${seed.label}.md`);
16589
17036
  if (!fs2.existsSync(filePath)) {
16590
17037
  const content = buildFrontmatter({
16591
17038
  label: seed.label,
@@ -16603,7 +17050,7 @@ function writeJournalEntry(title, body, project, tags = []) {
16603
17050
  fs2.mkdirSync(journalDir, { recursive: true });
16604
17051
  const now = new Date;
16605
17052
  const id2 = `${now.getUTCFullYear()}${String(now.getUTCMonth() + 1).padStart(2, "0")}${String(now.getUTCDate()).padStart(2, "0")}-${String(now.getUTCHours()).padStart(2, "0")}${String(now.getUTCMinutes()).padStart(2, "0")}${String(now.getUTCSeconds()).padStart(2, "0")}-${String(now.getUTCMilliseconds()).padStart(3, "0")}`;
16606
- const filePath = path2.join(journalDir, `${id2}.md`);
17053
+ const filePath = path3.join(journalDir, `${id2}.md`);
16607
17054
  const frontmatter = buildFrontmatter({
16608
17055
  title,
16609
17056
  project: project || "",
@@ -16630,7 +17077,7 @@ function searchJournalEntries(query, project, limit = 20) {
16630
17077
  const entries = [];
16631
17078
  const files = fs2.readdirSync(journalDir).filter((f) => f.endsWith(".md")).sort().reverse();
16632
17079
  for (const file2 of files) {
16633
- const filePath = path2.join(journalDir, file2);
17080
+ const filePath = path3.join(journalDir, file2);
16634
17081
  const content = fs2.readFileSync(filePath, "utf-8");
16635
17082
  const { frontmatter, body } = parseFrontmatter2(content);
16636
17083
  const entry = {
@@ -16728,7 +17175,7 @@ var hiveMemorySetTool = tool({
16728
17175
  }
16729
17176
  const dir = scope === "global" ? getGlobalMemoryDir() : getProjectMemoryDir(projectRoot);
16730
17177
  fs2.mkdirSync(dir, { recursive: true });
16731
- const filePath = path2.join(dir, `${label}.md`);
17178
+ const filePath = path3.join(dir, `${label}.md`);
16732
17179
  if (fs2.existsSync(filePath)) {
16733
17180
  const existing = readMemoryBlock(filePath, scope);
16734
17181
  if (existing.readOnly) {
@@ -16766,7 +17213,7 @@ var hiveMemoryReplaceTool = tool({
16766
17213
  async execute({ scope, label, oldText, newText }) {
16767
17214
  const projectRoot = process.cwd();
16768
17215
  const dir = scope === "global" ? getGlobalMemoryDir() : getProjectMemoryDir(projectRoot);
16769
- const filePath = path2.join(dir, `${label}.md`);
17216
+ const filePath = path3.join(dir, `${label}.md`);
16770
17217
  if (!fs2.existsSync(filePath)) {
16771
17218
  return JSON.stringify({
16772
17219
  success: false,
@@ -16890,10 +17337,10 @@ async function buildMemoryInjection(projectRoot) {
16890
17337
  `);
16891
17338
  }
16892
17339
  function getTypedMemoryDir() {
16893
- return path2.join(os.homedir(), ".config", "opencode", "hive", "typed-memory");
17340
+ return path3.join(os.homedir(), ".config", "opencode", "hive", "typed-memory");
16894
17341
  }
16895
17342
  function getDeletionsFile() {
16896
- return path2.join(getTypedMemoryDir(), "deletions.logfmt");
17343
+ return path3.join(getTypedMemoryDir(), "deletions.logfmt");
16897
17344
  }
16898
17345
  function parseTypedMemoryLine(line) {
16899
17346
  const tsMatch = line.match(/ts=([^\s]+)/);
@@ -16949,7 +17396,7 @@ async function getAllTypedMemories() {
16949
17396
  for (const filename of files) {
16950
17397
  if (filename === "deletions.logfmt")
16951
17398
  continue;
16952
- const filepath = path2.join(dir, filename);
17399
+ const filepath = path3.join(dir, filename);
16953
17400
  const text = fs2.readFileSync(filepath, "utf-8");
16954
17401
  lines.push(...text.trim().split(`
16955
17402
  `).filter(Boolean));
@@ -16965,7 +17412,7 @@ async function findTypedMemories(scope, type, query) {
16965
17412
  for (const filename of files) {
16966
17413
  if (filename === "deletions.logfmt")
16967
17414
  continue;
16968
- const filepath = path2.join(dir, filename);
17415
+ const filepath = path3.join(dir, filename);
16969
17416
  const text = fs2.readFileSync(filepath, "utf-8");
16970
17417
  const lines = text.split(`
16971
17418
  `);
@@ -17153,7 +17600,7 @@ var hiveMemoryForgetTool = tool({
17153
17600
 
17154
17601
  // src/tools/agent-booster.ts
17155
17602
  import * as fs3 from "fs";
17156
- import * as path3 from "path";
17603
+ import * as path4 from "path";
17157
17604
  var boosterInstance = null;
17158
17605
  var boosterInitPromise = null;
17159
17606
  async function initBooster() {
@@ -17311,7 +17758,7 @@ var hiveCodeEditTool = tool({
17311
17758
  newContent: tool.schema.string().describe("Replacement text")
17312
17759
  },
17313
17760
  async execute({ path: filePath, oldContent, newContent }) {
17314
- const resolvedPath = path3.isAbsolute(filePath) ? filePath : path3.join(process.cwd(), filePath);
17761
+ const resolvedPath = path4.isAbsolute(filePath) ? filePath : path4.join(process.cwd(), filePath);
17315
17762
  const result = await applyCodeEdit({
17316
17763
  path: resolvedPath,
17317
17764
  oldContent,
@@ -17352,7 +17799,7 @@ const newFunction = () => { ... };
17352
17799
  snippet: tool.schema.string().describe("Code snippet with // ... existing code ... markers")
17353
17800
  },
17354
17801
  async execute({ path: filePath, snippet }) {
17355
- const resolvedPath = path3.isAbsolute(filePath) ? filePath : path3.join(process.cwd(), filePath);
17802
+ const resolvedPath = path4.isAbsolute(filePath) ? filePath : path4.join(process.cwd(), filePath);
17356
17803
  const available = await isBoosterAvailable();
17357
17804
  if (!available) {
17358
17805
  return JSON.stringify({
@@ -17410,7 +17857,7 @@ var hiveBoosterStatusTool = tool({
17410
17857
 
17411
17858
  // src/services/vector-memory.ts
17412
17859
  import * as fs4 from "fs";
17413
- import * as path4 from "path";
17860
+ import * as path5 from "path";
17414
17861
  import * as os2 from "os";
17415
17862
  var memoryInstance = null;
17416
17863
  var memoryInitPromise = null;
@@ -17425,7 +17872,7 @@ async function initMemory(options) {
17425
17872
  memoryInitPromise = (async () => {
17426
17873
  try {
17427
17874
  const memory = (()=>{throw new Error("Cannot require module "+"@sparkleideas/memory");})();
17428
- const indexPath = options?.indexPath || path4.join(os2.homedir(), ".config", "opencode", "hive", "vector-index");
17875
+ const indexPath = options?.indexPath || path5.join(os2.homedir(), ".config", "opencode", "hive", "vector-index");
17429
17876
  const dimensions = options?.dimensions || 384;
17430
17877
  fs4.mkdirSync(indexPath, { recursive: true });
17431
17878
  if (typeof memory.init === "function") {
@@ -17529,7 +17976,7 @@ async function getMemoryStatus() {
17529
17976
  };
17530
17977
  }
17531
17978
  function getFallbackDir() {
17532
- return path4.join(os2.homedir(), ".config", "opencode", "hive", "vector-memory", "fallback");
17979
+ return path5.join(os2.homedir(), ".config", "opencode", "hive", "vector-memory", "fallback");
17533
17980
  }
17534
17981
  function ensureFallbackDir() {
17535
17982
  const dir = getFallbackDir();
@@ -17550,7 +17997,7 @@ async function addMemoryFallback(content, metadata) {
17550
17997
  createdAt: new Date().toISOString(),
17551
17998
  updatedAt: new Date().toISOString()
17552
17999
  };
17553
- const filePath = path4.join(getFallbackDir(), `${id2}.json`);
18000
+ const filePath = path5.join(getFallbackDir(), `${id2}.json`);
17554
18001
  fs4.writeFileSync(filePath, JSON.stringify(entry, null, 2), "utf-8");
17555
18002
  return { id: id2, success: true, fallback: true };
17556
18003
  }
@@ -17562,7 +18009,7 @@ async function searchMemoriesFallback(query, options) {
17562
18009
  const files = fs4.readdirSync(getFallbackDir()).filter((f) => f.endsWith(".json"));
17563
18010
  for (const file2 of files) {
17564
18011
  try {
17565
- const content = fs4.readFileSync(path4.join(getFallbackDir(), file2), "utf-8");
18012
+ const content = fs4.readFileSync(path5.join(getFallbackDir(), file2), "utf-8");
17566
18013
  const entry = JSON.parse(content);
17567
18014
  if (type && entry.metadata.type !== type)
17568
18015
  continue;
@@ -17597,7 +18044,7 @@ async function searchMemoriesFallback(query, options) {
17597
18044
  };
17598
18045
  }
17599
18046
  async function getMemoryFallback(id2) {
17600
- const filePath = path4.join(getFallbackDir(), `${id2}.json`);
18047
+ const filePath = path5.join(getFallbackDir(), `${id2}.json`);
17601
18048
  if (!fs4.existsSync(filePath)) {
17602
18049
  return null;
17603
18050
  }
@@ -17609,7 +18056,7 @@ async function getMemoryFallback(id2) {
17609
18056
  }
17610
18057
  }
17611
18058
  async function deleteMemoryFallback(id2) {
17612
- const filePath = path4.join(getFallbackDir(), `${id2}.json`);
18059
+ const filePath = path5.join(getFallbackDir(), `${id2}.json`);
17613
18060
  if (!fs4.existsSync(filePath)) {
17614
18061
  return false;
17615
18062
  }
@@ -17626,7 +18073,7 @@ function getFallbackStats() {
17626
18073
  const files = fs4.readdirSync(getFallbackDir()).filter((f) => f.endsWith(".json"));
17627
18074
  for (const file2 of files) {
17628
18075
  try {
17629
- const content = fs4.readFileSync(path4.join(getFallbackDir(), file2), "utf-8");
18076
+ const content = fs4.readFileSync(path5.join(getFallbackDir(), file2), "utf-8");
17630
18077
  const entry = JSON.parse(content);
17631
18078
  stats.total++;
17632
18079
  const type = entry.metadata.type || "unknown";
@@ -18153,7 +18600,7 @@ Choose "usage" to see which imports are actually used (great for refactoring), o
18153
18600
  mode: tool.schema.enum(["usage", "discovery"]).default("usage").describe("Analysis mode"),
18154
18601
  path: tool.schema.string().optional().describe("Directory or file to analyze")
18155
18602
  },
18156
- async execute({ mode, path: path5 }) {
18603
+ async execute({ mode, path: path6 }) {
18157
18604
  await initAstGrep();
18158
18605
  if (!astGrepModule) {
18159
18606
  return JSON.stringify({
@@ -18162,7 +18609,7 @@ Choose "usage" to see which imports are actually used (great for refactoring), o
18162
18609
  }, null, 2);
18163
18610
  }
18164
18611
  try {
18165
- const analyzePath = path5 || process.cwd();
18612
+ const analyzePath = path6 || process.cwd();
18166
18613
  if (!fs5.existsSync(analyzePath)) {
18167
18614
  return JSON.stringify({
18168
18615
  success: false,
@@ -18224,14 +18671,14 @@ Choose "usage" to see which imports are actually used (great for refactoring), o
18224
18671
 
18225
18672
  // src/tools/hive-doctor.ts
18226
18673
  import * as fs6 from "fs";
18227
- import * as path5 from "path";
18674
+ import * as path6 from "path";
18228
18675
  async function checkPackage(packageName) {
18229
18676
  try {
18230
18677
  const packageJsonPath = __require.resolve(`${packageName}/package.json`, {
18231
18678
  paths: [
18232
18679
  process.cwd(),
18233
- path5.join(process.cwd(), "node_modules"),
18234
- path5.join(process.cwd(), "packages/opencode-hive/node_modules")
18680
+ path6.join(process.cwd(), "node_modules"),
18681
+ path6.join(process.cwd(), "packages/opencode-hive/node_modules")
18235
18682
  ]
18236
18683
  });
18237
18684
  if (fs6.existsSync(packageJsonPath)) {
@@ -18244,8 +18691,8 @@ async function checkPackage(packageName) {
18244
18691
  function checkOptimizations() {
18245
18692
  const checks3 = [];
18246
18693
  const configPaths = [
18247
- path5.join(process.env.HOME || "", ".config/opencode/agent_hive.json"),
18248
- path5.join(process.env.HOME || "", ".config/opencode/agent_hive.jsonc")
18694
+ path6.join(process.env.HOME || "", ".config/opencode/agent_hive.json"),
18695
+ path6.join(process.env.HOME || "", ".config/opencode/agent_hive.jsonc")
18249
18696
  ];
18250
18697
  let config2 = null;
18251
18698
  for (const configPath of configPaths) {
@@ -18436,6 +18883,492 @@ var hiveDoctorQuickTool = tool({
18436
18883
  }
18437
18884
  });
18438
18885
 
18886
+ // src/tools/dora.ts
18887
+ import { execSync as execSync2 } from "child_process";
18888
+ function checkDoraStatus() {
18889
+ try {
18890
+ const output = execSync2("dora --version", { encoding: "utf-8" });
18891
+ const version2 = output.trim();
18892
+ const indexExists = __require("fs").existsSync(".dora/dora.db");
18893
+ return { installed: true, version: version2, indexed: indexExists };
18894
+ } catch {
18895
+ return { installed: false, indexed: false };
18896
+ }
18897
+ }
18898
+ function runDoraCommand(args2) {
18899
+ try {
18900
+ const output = execSync2(`dora ${args2.join(" ")}`, {
18901
+ encoding: "utf-8",
18902
+ maxBuffer: 10 * 1024 * 1024
18903
+ });
18904
+ return { success: true, output };
18905
+ } catch (error45) {
18906
+ return { success: false, error: error45.message || "Command failed" };
18907
+ }
18908
+ }
18909
+ var doraStatusTool = tool({
18910
+ description: `Check dora installation status and index state.
18911
+
18912
+ **Returns:**
18913
+ - installed: Whether dora CLI is available
18914
+ - version: Dora version
18915
+ - indexed: Whether codebase has been indexed
18916
+
18917
+ **Requirements:**
18918
+ - Install dora: \`bun install -g @butttons/dora\`
18919
+ - Install SCIP indexer: \`npm install -g @sourcegraph/scip-typescript\`
18920
+ - Initialize: \`dora init && dora index\`
18921
+
18922
+ **Note:** Indexing is required once per codebase. After that, dora works instantly.`,
18923
+ args: {},
18924
+ async execute() {
18925
+ const status = checkDoraStatus();
18926
+ if (!status.installed) {
18927
+ return JSON.stringify({
18928
+ status: "not_installed",
18929
+ message: "Dora CLI not found",
18930
+ installation: {
18931
+ step1: "bun install -g @butttons/dora",
18932
+ step2: "npm install -g @sourcegraph/scip-typescript",
18933
+ step3: "dora init && dora index"
18934
+ }
18935
+ }, null, 2);
18936
+ }
18937
+ if (!status.indexed) {
18938
+ return JSON.stringify({
18939
+ status: "not_indexed",
18940
+ version: status.version,
18941
+ message: "Codebase not indexed",
18942
+ nextStep: "Run: dora init && dora index"
18943
+ }, null, 2);
18944
+ }
18945
+ return JSON.stringify({
18946
+ status: "ready",
18947
+ version: status.version,
18948
+ indexed: true,
18949
+ message: "Dora is ready"
18950
+ }, null, 2);
18951
+ }
18952
+ });
18953
+ var doraSymbolTool = tool({
18954
+ description: `Find symbol definitions using dora (SCIP-based).
18955
+
18956
+ **Parameters:**
18957
+ - name: Symbol name to search for
18958
+ - kind: Filter by symbol kind (function, class, method, etc.)
18959
+
18960
+ **Example:**
18961
+ \`\`\`
18962
+ dora_symbol({ name: "getUserById" })
18963
+ \`\`\`
18964
+
18965
+ **Note:** Requires dora to be installed and indexed.`,
18966
+ args: {
18967
+ name: tool.schema.string().describe("Symbol name to search for"),
18968
+ kind: tool.schema.string().optional().describe("Filter by symbol kind (function, class, method, etc.)")
18969
+ },
18970
+ async execute({ name, kind }) {
18971
+ const status = checkDoraStatus();
18972
+ if (!status.installed || !status.indexed) {
18973
+ return JSON.stringify({
18974
+ success: false,
18975
+ error: "Dora not ready. Run dora_status first.",
18976
+ hint: "Install and index: dora init && dora index"
18977
+ }, null, 2);
18978
+ }
18979
+ const args2 = ["symbol", name];
18980
+ if (kind) {
18981
+ args2.push("--kind", kind);
18982
+ }
18983
+ const result = runDoraCommand(args2);
18984
+ if (!result.success) {
18985
+ return JSON.stringify({
18986
+ success: false,
18987
+ error: result.error,
18988
+ hint: "Symbol may not exist or not indexed"
18989
+ }, null, 2);
18990
+ }
18991
+ return JSON.stringify({
18992
+ success: true,
18993
+ symbol: name,
18994
+ output: result.output
18995
+ }, null, 2);
18996
+ }
18997
+ });
18998
+ var doraFileTool = tool({
18999
+ description: `Get file dependencies and information using dora.
19000
+
19001
+ **Parameters:**
19002
+ - path: File path to analyze
19003
+
19004
+ **Example:**
19005
+ \`\`\`
19006
+ dora_file({ path: "src/index.ts" })
19007
+ \`\`\`
19008
+
19009
+ **Returns:** File metadata, exports, and dependencies.`,
19010
+ args: {
19011
+ path: tool.schema.string().describe("File path to analyze")
19012
+ },
19013
+ async execute({ path: path7 }) {
19014
+ const status = checkDoraStatus();
19015
+ if (!status.installed || !status.indexed) {
19016
+ return JSON.stringify({
19017
+ success: false,
19018
+ error: "Dora not ready. Run dora_status first."
19019
+ }, null, 2);
19020
+ }
19021
+ const result = runDoraCommand(["file", path7]);
19022
+ if (!result.success) {
19023
+ return JSON.stringify({
19024
+ success: false,
19025
+ error: result.error,
19026
+ hint: "File may not exist or not indexed"
19027
+ }, null, 2);
19028
+ }
19029
+ return JSON.stringify({
19030
+ success: true,
19031
+ path: path7,
19032
+ output: result.output
19033
+ }, null, 2);
19034
+ }
19035
+ });
19036
+ var doraReferencesTool = tool({
19037
+ description: `Find all references to a symbol using dora.
19038
+
19039
+ **Parameters:**
19040
+ - name: Symbol name to find references for
19041
+
19042
+ **Example:**
19043
+ \`\`\`
19044
+ dora_references({ name: "UserService" })
19045
+ \`\`\`
19046
+
19047
+ **Note:** Returns all usages across the codebase.`,
19048
+ args: {
19049
+ name: tool.schema.string().describe("Symbol name to find references for")
19050
+ },
19051
+ async execute({ name }) {
19052
+ const status = checkDoraStatus();
19053
+ if (!status.installed || !status.indexed) {
19054
+ return JSON.stringify({
19055
+ success: false,
19056
+ error: "Dora not ready. Run dora_status first."
19057
+ }, null, 2);
19058
+ }
19059
+ const result = runDoraCommand(["references", name]);
19060
+ if (!result.success) {
19061
+ return JSON.stringify({
19062
+ success: false,
19063
+ error: result.error
19064
+ }, null, 2);
19065
+ }
19066
+ return JSON.stringify({
19067
+ success: true,
19068
+ symbol: name,
19069
+ output: result.output
19070
+ }, null, 2);
19071
+ }
19072
+ });
19073
+ var doraCyclesTool = tool({
19074
+ description: `Detect circular dependencies in the codebase using dora.
19075
+
19076
+ **Example:**
19077
+ \`\`\`
19078
+ dora_cycles()
19079
+ \`\`\`
19080
+
19081
+ **Returns:** List of circular dependency paths if found.`,
19082
+ args: {},
19083
+ async execute() {
19084
+ const status = checkDoraStatus();
19085
+ if (!status.installed || !status.indexed) {
19086
+ return JSON.stringify({
19087
+ success: false,
19088
+ error: "Dora not ready. Run dora_status first."
19089
+ }, null, 2);
19090
+ }
19091
+ const result = runDoraCommand(["cycles"]);
19092
+ if (!result.success) {
19093
+ return JSON.stringify({
19094
+ success: false,
19095
+ error: result.error
19096
+ }, null, 2);
19097
+ }
19098
+ return JSON.stringify({
19099
+ success: true,
19100
+ cycles: result.output
19101
+ }, null, 2);
19102
+ }
19103
+ });
19104
+ var doraUnusedTool = tool({
19105
+ description: `Find unused/dead code in the codebase using dora.
19106
+
19107
+ **Example:**
19108
+ \`\`\`
19109
+ dora_unused()
19110
+ \`\`\`
19111
+
19112
+ **Returns:** List of symbols with zero references.`,
19113
+ args: {},
19114
+ async execute() {
19115
+ const status = checkDoraStatus();
19116
+ if (!status.installed || !status.indexed) {
19117
+ return JSON.stringify({
19118
+ success: false,
19119
+ error: "Dora not ready. Run dora_status first."
19120
+ }, null, 2);
19121
+ }
19122
+ const result = runDoraCommand(["unused"]);
19123
+ if (!result.success) {
19124
+ return JSON.stringify({
19125
+ success: false,
19126
+ error: result.error
19127
+ }, null, 2);
19128
+ }
19129
+ return JSON.stringify({
19130
+ success: true,
19131
+ unused: result.output
19132
+ }, null, 2);
19133
+ }
19134
+ });
19135
+
19136
+ // src/tools/auto-cr.ts
19137
+ import { execSync as execSync3 } from "child_process";
19138
+ import * as fs7 from "fs";
19139
+ function checkAutoCrStatus() {
19140
+ try {
19141
+ const output = execSync3("auto-cr-cmd --version", { encoding: "utf-8" });
19142
+ const version2 = output.trim();
19143
+ return { installed: true, version: version2 };
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) {
19191
+ return JSON.stringify({
19192
+ status: "not_installed",
19193
+ message: "auto-cr-cmd not found",
19194
+ installation: "npm install auto-cr-cmd"
19195
+ }, null, 2);
19196
+ }
19197
+ return JSON.stringify({
19198
+ status: "ready",
19199
+ version: status.version,
19200
+ message: "Auto-CR is ready to scan",
19201
+ rules: [
19202
+ "no-deep-relative-imports",
19203
+ "no-circular-dependencies",
19204
+ "no-swallowed-errors",
19205
+ "no-catastrophic-regex",
19206
+ "no-deep-clone-in-loop",
19207
+ "no-n2-array-lookup"
19208
+ ]
19209
+ }, null, 2);
19210
+ }
19211
+ });
19212
+ var autoCrScanTool = tool({
19213
+ description: `Scan directory for code issues using auto-cr (SWC-based static analysis).
19214
+
19215
+ **Parameters:**
19216
+ - path: Directory path to scan (defaults to ./src)
19217
+ - language: Output language (en/zh, defaults to en)
19218
+
19219
+ **Rules detected:**
19220
+ - no-deep-relative-imports: Import paths exceeding depth limit
19221
+ - no-circular-dependencies: Circular module dependencies
19222
+ - no-swallowed-errors: try-catch blocks that swallow errors
19223
+ - no-catastrophic-regex: Potentially catastrophic regex patterns
19224
+ - no-deep-clone-in-loop: Performance anti-patterns
19225
+ - no-n2-array-lookup: O(n²) array operations
19226
+
19227
+ **Example:**
19228
+ \`\`\`
19229
+ auto_cr_scan({ path: "./src" })
19230
+ \`\`\``,
19231
+ args: {
19232
+ path: tool.schema.string().optional().default("./src").describe("Directory path to scan"),
19233
+ language: tool.schema.string().optional().default("en").describe("Output language (en or zh)")
19234
+ },
19235
+ async execute({ path: path7, language }) {
19236
+ const status = checkAutoCrStatus();
19237
+ if (!status.installed) {
19238
+ return JSON.stringify({
19239
+ success: false,
19240
+ error: "auto-cr-cmd not installed",
19241
+ hint: "npm install auto-cr-cmd"
19242
+ }, null, 2);
19243
+ }
19244
+ if (!fs7.existsSync(path7)) {
19245
+ return JSON.stringify({
19246
+ success: false,
19247
+ error: `Path not found: ${path7}`
19248
+ }, null, 2);
19249
+ }
19250
+ const result = runAutoCr(["--language", language, path7]);
19251
+ if (!result.success && !result.json) {
19252
+ return JSON.stringify({
19253
+ success: false,
19254
+ error: result.error || "Scan failed"
19255
+ }, null, 2);
19256
+ }
19257
+ if (result.json) {
19258
+ const { summary, files, notifications } = result.json;
19259
+ return JSON.stringify({
19260
+ success: true,
19261
+ scanned: path7,
19262
+ summary: {
19263
+ filesScanned: summary?.scannedFiles || 0,
19264
+ filesWithErrors: summary?.filesWithErrors || 0,
19265
+ filesWithWarnings: summary?.filesWithWarnings || 0,
19266
+ totalViolations: summary?.violationTotals?.total || 0
19267
+ },
19268
+ files: files?.map((f) => ({
19269
+ path: f.filePath,
19270
+ violations: f.totalViolations,
19271
+ errors: f.severityCounts?.error || 0,
19272
+ warnings: f.severityCounts?.warning || 0,
19273
+ details: f.violations?.map((v) => ({
19274
+ rule: v.ruleName,
19275
+ severity: v.severity,
19276
+ message: v.message,
19277
+ line: v.line
19278
+ }))
19279
+ })),
19280
+ notifications: notifications || []
19281
+ }, null, 2);
19282
+ }
19283
+ return JSON.stringify({
19284
+ success: true,
19285
+ scanned: path7,
19286
+ rawOutput: result.output
19287
+ }, null, 2);
19288
+ }
19289
+ });
19290
+ var autoCrDiffTool = tool({
19291
+ description: `Scan git diff output for code issues using auto-cr.
19292
+
19293
+ **Use case:** Run in CI to check only changed files.
19294
+
19295
+ **Example:**
19296
+ \`\`\`bash
19297
+ git diff --name-only -z | xargs -0 auto-cr-cmd --stdin --output json
19298
+ \`\`\`
19299
+
19300
+ **Note:** This tool requires git diff output piped via stdin.`,
19301
+ args: {
19302
+ language: tool.schema.string().optional().default("en").describe("Output language (en or zh)")
19303
+ },
19304
+ async execute({ language }) {
19305
+ const status = checkAutoCrStatus();
19306
+ if (!status.installed) {
19307
+ return JSON.stringify({
19308
+ success: false,
19309
+ error: "auto-cr-cmd not installed",
19310
+ hint: "npm install auto-cr-cmd"
19311
+ }, null, 2);
19312
+ }
19313
+ return JSON.stringify({
19314
+ success: true,
19315
+ message: "Use git diff with auto-cr directly",
19316
+ example: "git diff --name-only -z | xargs -0 npx auto-cr-cmd --stdin --output json"
19317
+ }, null, 2);
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"
19362
+ }
19363
+ ];
19364
+ return JSON.stringify({
19365
+ success: true,
19366
+ rules,
19367
+ totalRules: rules.length
19368
+ }, null, 2);
19369
+ }
19370
+ });
19371
+
18439
19372
  // src/agents/hive.ts
18440
19373
  var QUEEN_BEE_PROMPT = `# Zetta (Hybrid)
18441
19374
 
@@ -19775,13 +20708,20 @@ var pareSearchMcp = {
19775
20708
  command: ["npx", "-y", "@paretools/search"]
19776
20709
  };
19777
20710
 
20711
+ // src/mcp/veil.ts
20712
+ var veilMcp = {
20713
+ type: "local",
20714
+ command: ["npx", "-y", "@ushiradineth/veil@latest", "mcp", "server"]
20715
+ };
20716
+
19778
20717
  // src/mcp/index.ts
19779
20718
  var allBuiltinMcps = {
19780
20719
  websearch: websearchMcp,
19781
20720
  context7: context7Mcp,
19782
20721
  grep_app: grepAppMcp,
19783
20722
  ast_grep: astGrepMcp,
19784
- pare_search: pareSearchMcp
20723
+ pare_search: pareSearchMcp,
20724
+ veil: veilMcp
19785
20725
  };
19786
20726
  var createBuiltinMcps = (disabledMcps = []) => {
19787
20727
  const disabled = new Set(disabledMcps);
@@ -19790,10 +20730,10 @@ var createBuiltinMcps = (disabledMcps = []) => {
19790
20730
 
19791
20731
  // ../hive-core/dist/index.js
19792
20732
  import { createRequire as createRequire2 } from "node:module";
19793
- import * as path6 from "path";
20733
+ import * as path7 from "path";
19794
20734
  import * as os3 from "os";
19795
20735
  import * as path22 from "path";
19796
- import * as fs7 from "fs";
20736
+ import * as fs8 from "fs";
19797
20737
  import * as path32 from "path";
19798
20738
  import * as fs22 from "fs";
19799
20739
  import * as fs32 from "fs";
@@ -19802,18 +20742,18 @@ import * as fs52 from "fs";
19802
20742
  import * as fs72 from "fs/promises";
19803
20743
  import * as path42 from "path";
19804
20744
  import { Buffer as Buffer2 } from "node:buffer";
19805
- import { spawn } from "child_process";
20745
+ import { spawn as spawn2 } from "child_process";
19806
20746
  import { normalize } from "node:path";
19807
20747
  import { EventEmitter } from "node:events";
19808
- import * as fs8 from "fs";
20748
+ import * as fs82 from "fs";
19809
20749
  import * as path52 from "path";
19810
20750
  import * as fs10 from "fs";
19811
- import * as path7 from "path";
20751
+ import * as path72 from "path";
19812
20752
  import * as fs11 from "fs";
19813
20753
  import * as path8 from "path";
19814
20754
  import { existsSync as existsSync52 } from "fs";
19815
20755
  import { join as join92, sep } from "path";
19816
- import { execSync } from "child_process";
20756
+ import { execSync as execSync4 } from "child_process";
19817
20757
  var __create2 = Object.create;
19818
20758
  var __getProtoOf2 = Object.getPrototypeOf;
19819
20759
  var __defProp2 = Object.defineProperty;
@@ -20665,7 +21605,7 @@ var DEFAULT_HIVE_CONFIG = {
20665
21605
  },
20666
21606
  vectorMemory: {
20667
21607
  enabled: false,
20668
- indexPath: path6.join(os3.homedir(), ".config", "opencode", "hive", "vector-index"),
21608
+ indexPath: path7.join(os3.homedir(), ".config", "opencode", "hive", "vector-index"),
20669
21609
  dimensions: 384
20670
21610
  }
20671
21611
  };
@@ -20739,22 +21679,22 @@ function getSubtaskReportPath(projectRoot, featureName, taskFolder, subtaskFolde
20739
21679
  return path22.join(getSubtaskPath(projectRoot, featureName, taskFolder, subtaskFolder), REPORT_FILE);
20740
21680
  }
20741
21681
  function ensureDir(dirPath) {
20742
- if (!fs7.existsSync(dirPath)) {
20743
- fs7.mkdirSync(dirPath, { recursive: true });
21682
+ if (!fs8.existsSync(dirPath)) {
21683
+ fs8.mkdirSync(dirPath, { recursive: true });
20744
21684
  }
20745
21685
  }
20746
21686
  function fileExists(filePath) {
20747
- return fs7.existsSync(filePath);
21687
+ return fs8.existsSync(filePath);
20748
21688
  }
20749
21689
  function readJson(filePath) {
20750
- if (!fs7.existsSync(filePath))
21690
+ if (!fs8.existsSync(filePath))
20751
21691
  return null;
20752
- const content = fs7.readFileSync(filePath, "utf-8");
21692
+ const content = fs8.readFileSync(filePath, "utf-8");
20753
21693
  return JSON.parse(content);
20754
21694
  }
20755
21695
  function writeJson(filePath, data) {
20756
21696
  ensureDir(path22.dirname(filePath));
20757
- fs7.writeFileSync(filePath, JSON.stringify(data, null, 2));
21697
+ fs8.writeFileSync(filePath, JSON.stringify(data, null, 2));
20758
21698
  }
20759
21699
  var DEFAULT_LOCK_OPTIONS = {
20760
21700
  timeout: 5000,
@@ -20766,7 +21706,7 @@ function getLockPath(filePath) {
20766
21706
  }
20767
21707
  function isLockStale(lockPath, staleTTL) {
20768
21708
  try {
20769
- const stat2 = fs7.statSync(lockPath);
21709
+ const stat2 = fs8.statSync(lockPath);
20770
21710
  const age = Date.now() - stat2.mtimeMs;
20771
21711
  return age > staleTTL;
20772
21712
  } catch {
@@ -20786,12 +21726,12 @@ function acquireLockSync(filePath, options = {}) {
20786
21726
  ensureDir(lockDir);
20787
21727
  while (true) {
20788
21728
  try {
20789
- const fd = fs7.openSync(lockPath, fs7.constants.O_CREAT | fs7.constants.O_EXCL | fs7.constants.O_WRONLY);
20790
- fs7.writeSync(fd, lockContent);
20791
- fs7.closeSync(fd);
21729
+ const fd = fs8.openSync(lockPath, fs8.constants.O_CREAT | fs8.constants.O_EXCL | fs8.constants.O_WRONLY);
21730
+ fs8.writeSync(fd, lockContent);
21731
+ fs8.closeSync(fd);
20792
21732
  return () => {
20793
21733
  try {
20794
- fs7.unlinkSync(lockPath);
21734
+ fs8.unlinkSync(lockPath);
20795
21735
  } catch {}
20796
21736
  };
20797
21737
  } catch (err) {
@@ -20801,7 +21741,7 @@ function acquireLockSync(filePath, options = {}) {
20801
21741
  } else if (error45.code === "EEXIST") {
20802
21742
  if (isLockStale(lockPath, opts.staleLockTTL)) {
20803
21743
  try {
20804
- fs7.unlinkSync(lockPath);
21744
+ fs8.unlinkSync(lockPath);
20805
21745
  continue;
20806
21746
  } catch {}
20807
21747
  }
@@ -20820,11 +21760,11 @@ function writeAtomic(filePath, content) {
20820
21760
  ensureDir(path22.dirname(filePath));
20821
21761
  const tempPath = `${filePath}.tmp.${process.pid}.${Date.now()}`;
20822
21762
  try {
20823
- fs7.writeFileSync(tempPath, content);
20824
- fs7.renameSync(tempPath, filePath);
21763
+ fs8.writeFileSync(tempPath, content);
21764
+ fs8.renameSync(tempPath, filePath);
20825
21765
  } catch (error45) {
20826
21766
  try {
20827
- fs7.unlinkSync(tempPath);
21767
+ fs8.unlinkSync(tempPath);
20828
21768
  } catch {}
20829
21769
  throw error45;
20830
21770
  }
@@ -20859,13 +21799,13 @@ function patchJsonLockedSync(filePath, patch, options = {}) {
20859
21799
  }
20860
21800
  }
20861
21801
  function readText(filePath) {
20862
- if (!fs7.existsSync(filePath))
21802
+ if (!fs8.existsSync(filePath))
20863
21803
  return null;
20864
- return fs7.readFileSync(filePath, "utf-8");
21804
+ return fs8.readFileSync(filePath, "utf-8");
20865
21805
  }
20866
21806
  function writeText(filePath, content) {
20867
21807
  ensureDir(path22.dirname(filePath));
20868
- fs7.writeFileSync(filePath, content);
21808
+ fs8.writeFileSync(filePath, content);
20869
21809
  }
20870
21810
  function detectContext(cwd) {
20871
21811
  const result = {
@@ -22956,7 +23896,7 @@ var init_git_executor_chain = __esm2({
22956
23896
  rejection = reason || rejection;
22957
23897
  }
22958
23898
  });
22959
- const spawned = spawn(command, args2, spawnOptions);
23899
+ const spawned = spawn2(command, args2, spawnOptions);
22960
23900
  spawned.stdout.on("data", onDataReceived(stdOut, "stdOut", logger, outputLogger.step("stdOut")));
22961
23901
  spawned.stderr.on("data", onDataReceived(stdErr, "stdErr", logger, outputLogger.step("stdErr")));
22962
23902
  spawned.on("error", onErrorReceived(stdErr, logger));
@@ -26150,10 +27090,10 @@ class ContextService {
26150
27090
  const contextPath = getContextPath(this.projectRoot, featureName);
26151
27091
  if (!fileExists(contextPath))
26152
27092
  return [];
26153
- const files = fs8.readdirSync(contextPath, { withFileTypes: true }).filter((f) => f.isFile() && f.name.endsWith(".md")).map((f) => f.name);
27093
+ const files = fs82.readdirSync(contextPath, { withFileTypes: true }).filter((f) => f.isFile() && f.name.endsWith(".md")).map((f) => f.name);
26154
27094
  return files.map((name) => {
26155
27095
  const filePath = path52.join(contextPath, name);
26156
- const stat2 = fs8.statSync(filePath);
27096
+ const stat2 = fs82.statSync(filePath);
26157
27097
  const content = readText(filePath) || "";
26158
27098
  return {
26159
27099
  name: name.replace(/\.md$/, ""),
@@ -26166,7 +27106,7 @@ class ContextService {
26166
27106
  const contextPath = getContextPath(this.projectRoot, featureName);
26167
27107
  const filePath = path52.join(contextPath, this.normalizeFileName(fileName));
26168
27108
  if (fileExists(filePath)) {
26169
- fs8.unlinkSync(filePath);
27109
+ fs82.unlinkSync(filePath);
26170
27110
  return true;
26171
27111
  }
26172
27112
  return false;
@@ -26197,8 +27137,8 @@ ${f.content}`);
26197
27137
  const archiveName = `${timestamp}_${ctx.name}.md`;
26198
27138
  const src = path52.join(contextPath, `${ctx.name}.md`);
26199
27139
  const dest = path52.join(archiveDir, archiveName);
26200
- fs8.copyFileSync(src, dest);
26201
- fs8.unlinkSync(src);
27140
+ fs82.copyFileSync(src, dest);
27141
+ fs82.unlinkSync(src);
26202
27142
  archived.push(ctx.name);
26203
27143
  }
26204
27144
  return { archived, archivePath: archiveDir };
@@ -26226,8 +27166,8 @@ class ConfigService {
26226
27166
  cachedCustomAgentConfigs = null;
26227
27167
  constructor() {
26228
27168
  const homeDir = process.env.HOME || process.env.USERPROFILE || "";
26229
- const configDir = path7.join(homeDir, ".config", "opencode");
26230
- this.configPath = path7.join(configDir, "agent_hive.json");
27169
+ const configDir = path72.join(homeDir, ".config", "opencode");
27170
+ this.configPath = path72.join(configDir, "agent_hive.json");
26231
27171
  }
26232
27172
  getPath() {
26233
27173
  return this.configPath;
@@ -26290,7 +27230,7 @@ class ConfigService {
26290
27230
  ...updates.customAgents
26291
27231
  } : current.customAgents
26292
27232
  };
26293
- const configDir = path7.dirname(this.configPath);
27233
+ const configDir = path72.dirname(this.configPath);
26294
27234
  if (!fs10.existsSync(configDir)) {
26295
27235
  fs10.mkdirSync(configDir, { recursive: true });
26296
27236
  }
@@ -26678,10 +27618,10 @@ class DockerSandboxService {
26678
27618
  static ensureContainer(worktreePath, image) {
26679
27619
  const name = this.containerName(worktreePath);
26680
27620
  try {
26681
- execSync(`docker inspect --format='{{.State.Running}}' ${name}`, { stdio: "pipe" });
27621
+ execSync4(`docker inspect --format='{{.State.Running}}' ${name}`, { stdio: "pipe" });
26682
27622
  return name;
26683
27623
  } catch {
26684
- execSync(`docker run -d --name ${name} -v ${worktreePath}:/app -w /app ${image} tail -f /dev/null`, { stdio: "pipe" });
27624
+ execSync4(`docker run -d --name ${name} -v ${worktreePath}:/app -w /app ${image} tail -f /dev/null`, { stdio: "pipe" });
26685
27625
  return name;
26686
27626
  }
26687
27627
  }
@@ -26692,12 +27632,12 @@ class DockerSandboxService {
26692
27632
  static stopContainer(worktreePath) {
26693
27633
  const name = this.containerName(worktreePath);
26694
27634
  try {
26695
- execSync(`docker rm -f ${name}`, { stdio: "ignore" });
27635
+ execSync4(`docker rm -f ${name}`, { stdio: "ignore" });
26696
27636
  } catch {}
26697
27637
  }
26698
27638
  static isDockerAvailable() {
26699
27639
  try {
26700
- execSync("docker info", { stdio: "ignore" });
27640
+ execSync4("docker info", { stdio: "ignore" });
26701
27641
  return true;
26702
27642
  } catch {
26703
27643
  return false;
@@ -28030,6 +28970,8 @@ ${snapshot}
28030
28970
  lsp_diagnostics: lspDiagnosticsTool,
28031
28971
  lsp_hover: lspHoverTool,
28032
28972
  lsp_code_actions: lspCodeActionsTool,
28973
+ lsp_status: lspStatusTool,
28974
+ lsp_install: lspInstallTool,
28033
28975
  skill_mcp: skillMcpTool,
28034
28976
  list_skill_mcps: listSkillMcpsTool,
28035
28977
  hive_memory_list: hiveMemoryListTool,
@@ -28054,6 +28996,16 @@ ${snapshot}
28054
28996
  ast_grep_analyze_imports: astGrepAnalyzeImportsTool,
28055
28997
  hive_doctor: hiveDoctorTool,
28056
28998
  hive_doctor_quick: hiveDoctorQuickTool,
28999
+ dora_status: doraStatusTool,
29000
+ dora_symbol: doraSymbolTool,
29001
+ dora_file: doraFileTool,
29002
+ dora_references: doraReferencesTool,
29003
+ dora_cycles: doraCyclesTool,
29004
+ dora_unused: doraUnusedTool,
29005
+ auto_cr_status: autoCrStatusTool,
29006
+ auto_cr_scan: autoCrScanTool,
29007
+ auto_cr_diff: autoCrDiffTool,
29008
+ auto_cr_rules: autoCrRulesTool,
28057
29009
  hive_skill: createHiveSkillTool(filteredSkills),
28058
29010
  hive_feature_create: tool({
28059
29011
  description: "Create a new feature and set it as active",