@hung319/opencode-hive 1.4.4 → 1.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1276 -143
- package/dist/mcp/mcp-info.d.ts +37 -0
- package/dist/mcp/veil.d.ts +12 -0
- package/dist/tools/auto-cr.d.ts +5 -0
- package/dist/tools/dora.d.ts +7 -0
- package/dist/tools/lsp-manager.d.ts +52 -0
- package/dist/tools/lsp.d.ts +10 -0
- package/dist/utils/dep-installer.d.ts +80 -0
- package/dist/utils/model-selector.d.ts +68 -0
- package/package.json +5 -2
package/dist/index.js
CHANGED
|
@@ -96,8 +96,8 @@ var require_dist = __commonJS((exports) => {
|
|
|
96
96
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
97
97
|
exports.AgentBooster = undefined;
|
|
98
98
|
exports.apply = apply;
|
|
99
|
-
var
|
|
100
|
-
var wasmPath =
|
|
99
|
+
var path4 = __importStar(__require("path"));
|
|
100
|
+
var wasmPath = path4.join(__dirname, "../wasm/agent_booster_wasm.js");
|
|
101
101
|
var AgentBoosterWasm;
|
|
102
102
|
try {
|
|
103
103
|
AgentBoosterWasm = __require(wasmPath);
|
|
@@ -854,8 +854,8 @@ var init_context_compression = __esm(() => {
|
|
|
854
854
|
});
|
|
855
855
|
|
|
856
856
|
// src/index.ts
|
|
857
|
-
import * as
|
|
858
|
-
import * as
|
|
857
|
+
import * as path12 from "path";
|
|
858
|
+
import * as os5 from "os";
|
|
859
859
|
|
|
860
860
|
// ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/classic/external.js
|
|
861
861
|
var exports_external = {};
|
|
@@ -16213,50 +16213,333 @@ var ptyListTool = tool({
|
|
|
16213
16213
|
}
|
|
16214
16214
|
});
|
|
16215
16215
|
|
|
16216
|
-
// src/tools/lsp.ts
|
|
16217
|
-
|
|
16218
|
-
|
|
16219
|
-
|
|
16220
|
-
|
|
16221
|
-
|
|
16222
|
-
|
|
16223
|
-
|
|
16224
|
-
|
|
16225
|
-
|
|
16226
|
-
|
|
16227
|
-
|
|
16228
|
-
|
|
16229
|
-
|
|
16230
|
-
|
|
16231
|
-
|
|
16232
|
-
|
|
16233
|
-
|
|
16234
|
-
|
|
16235
|
-
|
|
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
|
+
};
|
|
16425
|
+
}
|
|
16426
|
+
const statuses = [];
|
|
16427
|
+
for (const lang of Object.keys(LSP_DATABASE)) {
|
|
16428
|
+
const config2 = LSP_DATABASE[lang];
|
|
16429
|
+
statuses.push({
|
|
16430
|
+
language: lang,
|
|
16431
|
+
installed: await checkLspServer(config2.primary),
|
|
16432
|
+
primary: config2.primary.command,
|
|
16433
|
+
alternatives: config2.alternatives.map((a) => a.command),
|
|
16434
|
+
canInstall: config2.alternatives.length > 0 || true
|
|
16435
|
+
});
|
|
16436
|
+
}
|
|
16437
|
+
return statuses;
|
|
16438
|
+
}
|
|
16439
|
+
|
|
16440
|
+
class LspManager {
|
|
16441
|
+
connections = new Map;
|
|
16442
|
+
async checkAndInstall(filePath) {
|
|
16443
|
+
const lang = getLanguageFromPath(filePath);
|
|
16444
|
+
if (!lang) {
|
|
16445
|
+
return {
|
|
16446
|
+
language: "unknown",
|
|
16447
|
+
ready: false,
|
|
16448
|
+
installed: false,
|
|
16449
|
+
message: `Unsupported file type. LSP not available.`
|
|
16450
|
+
};
|
|
16451
|
+
}
|
|
16452
|
+
const config2 = LSP_DATABASE[lang];
|
|
16453
|
+
if (!config2) {
|
|
16454
|
+
return {
|
|
16455
|
+
language: lang,
|
|
16456
|
+
ready: false,
|
|
16457
|
+
installed: false,
|
|
16458
|
+
message: `No LSP configuration for ${lang}.`
|
|
16459
|
+
};
|
|
16460
|
+
}
|
|
16461
|
+
const isInstalled = await checkLspServer(config2.primary);
|
|
16462
|
+
if (isInstalled) {
|
|
16463
|
+
return {
|
|
16464
|
+
language: lang,
|
|
16465
|
+
ready: true,
|
|
16466
|
+
installed: true,
|
|
16467
|
+
message: `${lang} LSP ready (${config2.primary.command})`
|
|
16468
|
+
};
|
|
16469
|
+
}
|
|
16470
|
+
const result = await ensureLspInstalled(lang);
|
|
16471
|
+
return {
|
|
16472
|
+
language: lang,
|
|
16473
|
+
ready: result.success,
|
|
16474
|
+
installed: result.success,
|
|
16475
|
+
message: result.success ? `${lang} LSP installed successfully` : result.error || "Installation failed"
|
|
16476
|
+
};
|
|
16477
|
+
}
|
|
16478
|
+
getAvailableLanguages() {
|
|
16479
|
+
return Object.keys(LSP_DATABASE);
|
|
16480
|
+
}
|
|
16481
|
+
getLspInfo(filePath) {
|
|
16482
|
+
const lang = getLanguageFromPath(filePath);
|
|
16483
|
+
if (!lang)
|
|
16484
|
+
return null;
|
|
16485
|
+
const config2 = LSP_DATABASE[lang];
|
|
16486
|
+
return {
|
|
16487
|
+
language: lang,
|
|
16488
|
+
extensions: config2.extensions,
|
|
16489
|
+
primaryCommand: config2.primary.command,
|
|
16490
|
+
alternativeCommands: config2.alternatives.map((a) => a.command)
|
|
16491
|
+
};
|
|
16236
16492
|
}
|
|
16237
|
-
return { serverId };
|
|
16238
16493
|
}
|
|
16494
|
+
var lspManager = new LspManager;
|
|
16495
|
+
|
|
16496
|
+
// src/tools/lsp.ts
|
|
16239
16497
|
var lspRenameTool = tool({
|
|
16240
|
-
description:
|
|
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
|
|
16248
|
-
if (!
|
|
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
|
-
|
|
16252
|
-
|
|
16253
|
-
|
|
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
|
-
|
|
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:
|
|
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
|
|
16276
|
-
if (!
|
|
16568
|
+
const lang = getLanguageFromPath(filePath);
|
|
16569
|
+
if (!lang) {
|
|
16277
16570
|
return JSON.stringify({
|
|
16278
16571
|
success: false,
|
|
16279
|
-
error: `
|
|
16280
|
-
|
|
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
|
-
|
|
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:
|
|
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
|
|
16300
|
-
if (!
|
|
16606
|
+
const lang = getLanguageFromPath(filePath);
|
|
16607
|
+
if (!lang) {
|
|
16301
16608
|
return JSON.stringify({
|
|
16302
16609
|
success: false,
|
|
16303
|
-
error: `
|
|
16304
|
-
|
|
16610
|
+
error: `Unsupported file type: ${filePath}`
|
|
16611
|
+
}, null, 2);
|
|
16612
|
+
}
|
|
16613
|
+
const status = await lspManager.checkAndInstall(filePath);
|
|
16614
|
+
if (!status.ready) {
|
|
16615
|
+
return JSON.stringify({
|
|
16616
|
+
success: false,
|
|
16617
|
+
language: status.language,
|
|
16618
|
+
error: status.message,
|
|
16619
|
+
alternatives: await getLspStatus(filePath)
|
|
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
|
-
|
|
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:
|
|
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
|
|
16324
|
-
if (!
|
|
16648
|
+
const lang = getLanguageFromPath(filePath);
|
|
16649
|
+
if (!lang) {
|
|
16325
16650
|
return JSON.stringify({
|
|
16326
16651
|
success: false,
|
|
16327
|
-
error: `
|
|
16328
|
-
|
|
16652
|
+
error: `Unsupported file type: ${filePath}`
|
|
16653
|
+
}, null, 2);
|
|
16654
|
+
}
|
|
16655
|
+
const status = await lspManager.checkAndInstall(filePath);
|
|
16656
|
+
if (!status.ready) {
|
|
16657
|
+
return JSON.stringify({
|
|
16658
|
+
success: false,
|
|
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
|
-
|
|
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:
|
|
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
|
|
16350
|
-
if (!
|
|
16687
|
+
const lang = getLanguageFromPath(filePath);
|
|
16688
|
+
if (!lang) {
|
|
16689
|
+
return JSON.stringify({
|
|
16690
|
+
success: false,
|
|
16691
|
+
error: `Unsupported file type: ${filePath}`
|
|
16692
|
+
}, null, 2);
|
|
16693
|
+
}
|
|
16694
|
+
const status = await lspManager.checkAndInstall(filePath);
|
|
16695
|
+
if (!status.ready) {
|
|
16351
16696
|
return JSON.stringify({
|
|
16352
16697
|
success: false,
|
|
16353
|
-
|
|
16354
|
-
|
|
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
|
-
|
|
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:
|
|
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
|
|
16374
|
-
if (!
|
|
16725
|
+
const lang = getLanguageFromPath(filePath);
|
|
16726
|
+
if (!lang) {
|
|
16727
|
+
return JSON.stringify({
|
|
16728
|
+
success: false,
|
|
16729
|
+
error: `Unsupported file type: ${filePath}`
|
|
16730
|
+
}, null, 2);
|
|
16731
|
+
}
|
|
16732
|
+
const status = await lspManager.checkAndInstall(filePath);
|
|
16733
|
+
if (!status.ready) {
|
|
16375
16734
|
return JSON.stringify({
|
|
16376
16735
|
success: false,
|
|
16377
|
-
|
|
16378
|
-
|
|
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
|
-
|
|
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
|
|
16920
|
+
import * as path3 from "path";
|
|
16474
16921
|
import * as os from "os";
|
|
16475
16922
|
function getGlobalMemoryDir() {
|
|
16476
|
-
return
|
|
16923
|
+
return path3.join(os.homedir(), ".config", "opencode", "hive", "memory", "global");
|
|
16477
16924
|
}
|
|
16478
16925
|
function getProjectMemoryDir(projectRoot) {
|
|
16479
|
-
return
|
|
16926
|
+
return path3.join(projectRoot, ".hive", "memory", "project");
|
|
16480
16927
|
}
|
|
16481
16928
|
function getJournalDir() {
|
|
16482
|
-
return
|
|
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 ||
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
|
17340
|
+
return path3.join(os.homedir(), ".config", "opencode", "hive", "typed-memory");
|
|
16894
17341
|
}
|
|
16895
17342
|
function getDeletionsFile() {
|
|
16896
|
-
return
|
|
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 =
|
|
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 =
|
|
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
|
|
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 =
|
|
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 =
|
|
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
|
|
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 ||
|
|
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
|
|
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 =
|
|
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(
|
|
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 =
|
|
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 =
|
|
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(
|
|
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:
|
|
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 =
|
|
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
|
|
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
|
-
|
|
18234
|
-
|
|
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
|
-
|
|
18248
|
-
|
|
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
|
|
20733
|
+
import * as path7 from "path";
|
|
19794
20734
|
import * as os3 from "os";
|
|
19795
20735
|
import * as path22 from "path";
|
|
19796
|
-
import * as
|
|
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
|
|
20748
|
+
import * as fs82 from "fs";
|
|
19809
20749
|
import * as path52 from "path";
|
|
19810
20750
|
import * as fs10 from "fs";
|
|
19811
|
-
import * as
|
|
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,9 +21605,10 @@ var DEFAULT_HIVE_CONFIG = {
|
|
|
20665
21605
|
},
|
|
20666
21606
|
vectorMemory: {
|
|
20667
21607
|
enabled: false,
|
|
20668
|
-
indexPath:
|
|
21608
|
+
indexPath: path7.join(os3.homedir(), ".config", "opencode", "hive", "vector-index"),
|
|
20669
21609
|
dimensions: 384
|
|
20670
|
-
}
|
|
21610
|
+
},
|
|
21611
|
+
autoInstallDeps: true
|
|
20671
21612
|
};
|
|
20672
21613
|
var HIVE_DIR = ".hive";
|
|
20673
21614
|
var FEATURES_DIR = "features";
|
|
@@ -20739,22 +21680,22 @@ function getSubtaskReportPath(projectRoot, featureName, taskFolder, subtaskFolde
|
|
|
20739
21680
|
return path22.join(getSubtaskPath(projectRoot, featureName, taskFolder, subtaskFolder), REPORT_FILE);
|
|
20740
21681
|
}
|
|
20741
21682
|
function ensureDir(dirPath) {
|
|
20742
|
-
if (!
|
|
20743
|
-
|
|
21683
|
+
if (!fs8.existsSync(dirPath)) {
|
|
21684
|
+
fs8.mkdirSync(dirPath, { recursive: true });
|
|
20744
21685
|
}
|
|
20745
21686
|
}
|
|
20746
21687
|
function fileExists(filePath) {
|
|
20747
|
-
return
|
|
21688
|
+
return fs8.existsSync(filePath);
|
|
20748
21689
|
}
|
|
20749
21690
|
function readJson(filePath) {
|
|
20750
|
-
if (!
|
|
21691
|
+
if (!fs8.existsSync(filePath))
|
|
20751
21692
|
return null;
|
|
20752
|
-
const content =
|
|
21693
|
+
const content = fs8.readFileSync(filePath, "utf-8");
|
|
20753
21694
|
return JSON.parse(content);
|
|
20754
21695
|
}
|
|
20755
21696
|
function writeJson(filePath, data) {
|
|
20756
21697
|
ensureDir(path22.dirname(filePath));
|
|
20757
|
-
|
|
21698
|
+
fs8.writeFileSync(filePath, JSON.stringify(data, null, 2));
|
|
20758
21699
|
}
|
|
20759
21700
|
var DEFAULT_LOCK_OPTIONS = {
|
|
20760
21701
|
timeout: 5000,
|
|
@@ -20766,7 +21707,7 @@ function getLockPath(filePath) {
|
|
|
20766
21707
|
}
|
|
20767
21708
|
function isLockStale(lockPath, staleTTL) {
|
|
20768
21709
|
try {
|
|
20769
|
-
const stat2 =
|
|
21710
|
+
const stat2 = fs8.statSync(lockPath);
|
|
20770
21711
|
const age = Date.now() - stat2.mtimeMs;
|
|
20771
21712
|
return age > staleTTL;
|
|
20772
21713
|
} catch {
|
|
@@ -20786,12 +21727,12 @@ function acquireLockSync(filePath, options = {}) {
|
|
|
20786
21727
|
ensureDir(lockDir);
|
|
20787
21728
|
while (true) {
|
|
20788
21729
|
try {
|
|
20789
|
-
const fd =
|
|
20790
|
-
|
|
20791
|
-
|
|
21730
|
+
const fd = fs8.openSync(lockPath, fs8.constants.O_CREAT | fs8.constants.O_EXCL | fs8.constants.O_WRONLY);
|
|
21731
|
+
fs8.writeSync(fd, lockContent);
|
|
21732
|
+
fs8.closeSync(fd);
|
|
20792
21733
|
return () => {
|
|
20793
21734
|
try {
|
|
20794
|
-
|
|
21735
|
+
fs8.unlinkSync(lockPath);
|
|
20795
21736
|
} catch {}
|
|
20796
21737
|
};
|
|
20797
21738
|
} catch (err) {
|
|
@@ -20801,7 +21742,7 @@ function acquireLockSync(filePath, options = {}) {
|
|
|
20801
21742
|
} else if (error45.code === "EEXIST") {
|
|
20802
21743
|
if (isLockStale(lockPath, opts.staleLockTTL)) {
|
|
20803
21744
|
try {
|
|
20804
|
-
|
|
21745
|
+
fs8.unlinkSync(lockPath);
|
|
20805
21746
|
continue;
|
|
20806
21747
|
} catch {}
|
|
20807
21748
|
}
|
|
@@ -20820,11 +21761,11 @@ function writeAtomic(filePath, content) {
|
|
|
20820
21761
|
ensureDir(path22.dirname(filePath));
|
|
20821
21762
|
const tempPath = `${filePath}.tmp.${process.pid}.${Date.now()}`;
|
|
20822
21763
|
try {
|
|
20823
|
-
|
|
20824
|
-
|
|
21764
|
+
fs8.writeFileSync(tempPath, content);
|
|
21765
|
+
fs8.renameSync(tempPath, filePath);
|
|
20825
21766
|
} catch (error45) {
|
|
20826
21767
|
try {
|
|
20827
|
-
|
|
21768
|
+
fs8.unlinkSync(tempPath);
|
|
20828
21769
|
} catch {}
|
|
20829
21770
|
throw error45;
|
|
20830
21771
|
}
|
|
@@ -20859,13 +21800,13 @@ function patchJsonLockedSync(filePath, patch, options = {}) {
|
|
|
20859
21800
|
}
|
|
20860
21801
|
}
|
|
20861
21802
|
function readText(filePath) {
|
|
20862
|
-
if (!
|
|
21803
|
+
if (!fs8.existsSync(filePath))
|
|
20863
21804
|
return null;
|
|
20864
|
-
return
|
|
21805
|
+
return fs8.readFileSync(filePath, "utf-8");
|
|
20865
21806
|
}
|
|
20866
21807
|
function writeText(filePath, content) {
|
|
20867
21808
|
ensureDir(path22.dirname(filePath));
|
|
20868
|
-
|
|
21809
|
+
fs8.writeFileSync(filePath, content);
|
|
20869
21810
|
}
|
|
20870
21811
|
function detectContext(cwd) {
|
|
20871
21812
|
const result = {
|
|
@@ -22956,7 +23897,7 @@ var init_git_executor_chain = __esm2({
|
|
|
22956
23897
|
rejection = reason || rejection;
|
|
22957
23898
|
}
|
|
22958
23899
|
});
|
|
22959
|
-
const spawned =
|
|
23900
|
+
const spawned = spawn2(command, args2, spawnOptions);
|
|
22960
23901
|
spawned.stdout.on("data", onDataReceived(stdOut, "stdOut", logger, outputLogger.step("stdOut")));
|
|
22961
23902
|
spawned.stderr.on("data", onDataReceived(stdErr, "stdErr", logger, outputLogger.step("stdErr")));
|
|
22962
23903
|
spawned.on("error", onErrorReceived(stdErr, logger));
|
|
@@ -26150,10 +27091,10 @@ class ContextService {
|
|
|
26150
27091
|
const contextPath = getContextPath(this.projectRoot, featureName);
|
|
26151
27092
|
if (!fileExists(contextPath))
|
|
26152
27093
|
return [];
|
|
26153
|
-
const files =
|
|
27094
|
+
const files = fs82.readdirSync(contextPath, { withFileTypes: true }).filter((f) => f.isFile() && f.name.endsWith(".md")).map((f) => f.name);
|
|
26154
27095
|
return files.map((name) => {
|
|
26155
27096
|
const filePath = path52.join(contextPath, name);
|
|
26156
|
-
const stat2 =
|
|
27097
|
+
const stat2 = fs82.statSync(filePath);
|
|
26157
27098
|
const content = readText(filePath) || "";
|
|
26158
27099
|
return {
|
|
26159
27100
|
name: name.replace(/\.md$/, ""),
|
|
@@ -26166,7 +27107,7 @@ class ContextService {
|
|
|
26166
27107
|
const contextPath = getContextPath(this.projectRoot, featureName);
|
|
26167
27108
|
const filePath = path52.join(contextPath, this.normalizeFileName(fileName));
|
|
26168
27109
|
if (fileExists(filePath)) {
|
|
26169
|
-
|
|
27110
|
+
fs82.unlinkSync(filePath);
|
|
26170
27111
|
return true;
|
|
26171
27112
|
}
|
|
26172
27113
|
return false;
|
|
@@ -26197,8 +27138,8 @@ ${f.content}`);
|
|
|
26197
27138
|
const archiveName = `${timestamp}_${ctx.name}.md`;
|
|
26198
27139
|
const src = path52.join(contextPath, `${ctx.name}.md`);
|
|
26199
27140
|
const dest = path52.join(archiveDir, archiveName);
|
|
26200
|
-
|
|
26201
|
-
|
|
27141
|
+
fs82.copyFileSync(src, dest);
|
|
27142
|
+
fs82.unlinkSync(src);
|
|
26202
27143
|
archived.push(ctx.name);
|
|
26203
27144
|
}
|
|
26204
27145
|
return { archived, archivePath: archiveDir };
|
|
@@ -26226,8 +27167,8 @@ class ConfigService {
|
|
|
26226
27167
|
cachedCustomAgentConfigs = null;
|
|
26227
27168
|
constructor() {
|
|
26228
27169
|
const homeDir = process.env.HOME || process.env.USERPROFILE || "";
|
|
26229
|
-
const configDir =
|
|
26230
|
-
this.configPath =
|
|
27170
|
+
const configDir = path72.join(homeDir, ".config", "opencode");
|
|
27171
|
+
this.configPath = path72.join(configDir, "agent_hive.json");
|
|
26231
27172
|
}
|
|
26232
27173
|
getPath() {
|
|
26233
27174
|
return this.configPath;
|
|
@@ -26290,7 +27231,7 @@ class ConfigService {
|
|
|
26290
27231
|
...updates.customAgents
|
|
26291
27232
|
} : current.customAgents
|
|
26292
27233
|
};
|
|
26293
|
-
const configDir =
|
|
27234
|
+
const configDir = path72.dirname(this.configPath);
|
|
26294
27235
|
if (!fs10.existsSync(configDir)) {
|
|
26295
27236
|
fs10.mkdirSync(configDir, { recursive: true });
|
|
26296
27237
|
}
|
|
@@ -26678,10 +27619,10 @@ class DockerSandboxService {
|
|
|
26678
27619
|
static ensureContainer(worktreePath, image) {
|
|
26679
27620
|
const name = this.containerName(worktreePath);
|
|
26680
27621
|
try {
|
|
26681
|
-
|
|
27622
|
+
execSync4(`docker inspect --format='{{.State.Running}}' ${name}`, { stdio: "pipe" });
|
|
26682
27623
|
return name;
|
|
26683
27624
|
} catch {
|
|
26684
|
-
|
|
27625
|
+
execSync4(`docker run -d --name ${name} -v ${worktreePath}:/app -w /app ${image} tail -f /dev/null`, { stdio: "pipe" });
|
|
26685
27626
|
return name;
|
|
26686
27627
|
}
|
|
26687
27628
|
}
|
|
@@ -26692,12 +27633,12 @@ class DockerSandboxService {
|
|
|
26692
27633
|
static stopContainer(worktreePath) {
|
|
26693
27634
|
const name = this.containerName(worktreePath);
|
|
26694
27635
|
try {
|
|
26695
|
-
|
|
27636
|
+
execSync4(`docker rm -f ${name}`, { stdio: "ignore" });
|
|
26696
27637
|
} catch {}
|
|
26697
27638
|
}
|
|
26698
27639
|
static isDockerAvailable() {
|
|
26699
27640
|
try {
|
|
26700
|
-
|
|
27641
|
+
execSync4("docker info", { stdio: "ignore" });
|
|
26701
27642
|
return true;
|
|
26702
27643
|
} catch {
|
|
26703
27644
|
return false;
|
|
@@ -27277,6 +28218,183 @@ function buildCompactionPrompt() {
|
|
|
27277
28218
|
return COMPACTION_RESUME_PROMPT;
|
|
27278
28219
|
}
|
|
27279
28220
|
|
|
28221
|
+
// src/utils/dep-installer.ts
|
|
28222
|
+
import { execSync as execSync5 } from "child_process";
|
|
28223
|
+
import * as path11 from "path";
|
|
28224
|
+
import * as os4 from "os";
|
|
28225
|
+
var PLUGIN_TOOLS = [
|
|
28226
|
+
{
|
|
28227
|
+
name: "btca",
|
|
28228
|
+
npmPackage: "btca-cli",
|
|
28229
|
+
installCommand: ["npm", "install", "-g", "btca-cli"],
|
|
28230
|
+
verifyCommand: "btca --version",
|
|
28231
|
+
description: "Bluetooth Classic Audio control",
|
|
28232
|
+
required: false
|
|
28233
|
+
},
|
|
28234
|
+
{
|
|
28235
|
+
name: "dora",
|
|
28236
|
+
npmPackage: "@butttons/dora",
|
|
28237
|
+
installCommand: ["npm", "install", "-g", "@butttons/dora"],
|
|
28238
|
+
verifyCommand: "dora --version",
|
|
28239
|
+
description: "SCIP-based code navigation",
|
|
28240
|
+
required: false
|
|
28241
|
+
},
|
|
28242
|
+
{
|
|
28243
|
+
name: "auto-cr",
|
|
28244
|
+
npmPackage: "auto-cr-cmd",
|
|
28245
|
+
installCommand: ["npm", "install", "-g", "auto-cr-cmd"],
|
|
28246
|
+
verifyCommand: "auto-cr-cmd --version",
|
|
28247
|
+
description: "SWC-based automated code review",
|
|
28248
|
+
required: false
|
|
28249
|
+
},
|
|
28250
|
+
{
|
|
28251
|
+
name: "scip-typescript",
|
|
28252
|
+
npmPackage: "@sourcegraph/scip-typescript",
|
|
28253
|
+
installCommand: ["npm", "install", "-g", "@sourcegraph/scip-typescript"],
|
|
28254
|
+
verifyCommand: "scip-typescript --version",
|
|
28255
|
+
description: "TypeScript SCIP indexer (for dora)",
|
|
28256
|
+
required: false
|
|
28257
|
+
},
|
|
28258
|
+
{
|
|
28259
|
+
name: "typescript-language-server",
|
|
28260
|
+
npmPackage: "typescript-language-server",
|
|
28261
|
+
installCommand: ["npm", "install", "-g", "typescript-language-server", "typescript"],
|
|
28262
|
+
verifyCommand: "typescript-language-server --version",
|
|
28263
|
+
description: "TypeScript/JavaScript LSP server",
|
|
28264
|
+
required: false
|
|
28265
|
+
},
|
|
28266
|
+
{
|
|
28267
|
+
name: "pyright",
|
|
28268
|
+
npmPackage: "pyright",
|
|
28269
|
+
installCommand: ["pip", "install", "pyright"],
|
|
28270
|
+
verifyCommand: "pyright --version",
|
|
28271
|
+
description: "Python LSP server",
|
|
28272
|
+
required: false
|
|
28273
|
+
}
|
|
28274
|
+
];
|
|
28275
|
+
|
|
28276
|
+
class DependencyInstaller {
|
|
28277
|
+
installDir;
|
|
28278
|
+
cache = new Map;
|
|
28279
|
+
cacheTimeout = 60000;
|
|
28280
|
+
constructor(installDir) {
|
|
28281
|
+
this.installDir = installDir || path11.join(os4.homedir(), ".local");
|
|
28282
|
+
}
|
|
28283
|
+
getBinDir() {
|
|
28284
|
+
return path11.join(this.installDir, "bin");
|
|
28285
|
+
}
|
|
28286
|
+
commandExists(cmd) {
|
|
28287
|
+
try {
|
|
28288
|
+
execSync5(`which ${cmd}`, { stdio: "ignore" });
|
|
28289
|
+
return true;
|
|
28290
|
+
} catch {
|
|
28291
|
+
return false;
|
|
28292
|
+
}
|
|
28293
|
+
}
|
|
28294
|
+
verifyTool(config2) {
|
|
28295
|
+
try {
|
|
28296
|
+
execSync5(config2.verifyCommand, { stdio: "ignore", timeout: 5000 });
|
|
28297
|
+
return true;
|
|
28298
|
+
} catch {
|
|
28299
|
+
return false;
|
|
28300
|
+
}
|
|
28301
|
+
}
|
|
28302
|
+
async install(config2) {
|
|
28303
|
+
console.log(`[dep-installer] Installing ${config2.name}...`);
|
|
28304
|
+
try {
|
|
28305
|
+
const [cmd, ...args2] = config2.installCommand;
|
|
28306
|
+
const fullCmd = `${cmd} ${args2.join(" ")}`;
|
|
28307
|
+
execSync5(fullCmd, {
|
|
28308
|
+
stdio: "inherit",
|
|
28309
|
+
timeout: 120000,
|
|
28310
|
+
env: {
|
|
28311
|
+
...process.env,
|
|
28312
|
+
...cmd === "npm" ? { npm_config_prefix: this.installDir } : {}
|
|
28313
|
+
}
|
|
28314
|
+
});
|
|
28315
|
+
const verified = this.verifyTool(config2);
|
|
28316
|
+
if (verified) {
|
|
28317
|
+
console.log(`[dep-installer] ✓ ${config2.name} installed successfully`);
|
|
28318
|
+
this.cache.set(config2.name, { installed: true, checked: Date.now() });
|
|
28319
|
+
return { success: true, output: `${config2.name} installed and verified` };
|
|
28320
|
+
} else {
|
|
28321
|
+
return { success: false, error: "Installation completed but verification failed" };
|
|
28322
|
+
}
|
|
28323
|
+
} catch (error45) {
|
|
28324
|
+
console.warn(`[dep-installer] ✗ ${config2.name} installation failed: ${error45.message}`);
|
|
28325
|
+
return { success: false, error: error45.message };
|
|
28326
|
+
}
|
|
28327
|
+
}
|
|
28328
|
+
isInstalled(toolName) {
|
|
28329
|
+
const cached2 = this.cache.get(toolName);
|
|
28330
|
+
if (cached2 && Date.now() - cached2.checked < this.cacheTimeout) {
|
|
28331
|
+
return cached2.installed;
|
|
28332
|
+
}
|
|
28333
|
+
const config2 = PLUGIN_TOOLS.find((t) => t.name === toolName);
|
|
28334
|
+
if (!config2)
|
|
28335
|
+
return false;
|
|
28336
|
+
const installed = this.verifyTool(config2);
|
|
28337
|
+
this.cache.set(toolName, { installed, checked: Date.now() });
|
|
28338
|
+
return installed;
|
|
28339
|
+
}
|
|
28340
|
+
getStatus() {
|
|
28341
|
+
return PLUGIN_TOOLS.map((config2) => ({
|
|
28342
|
+
name: config2.name,
|
|
28343
|
+
installed: this.isInstalled(config2.name),
|
|
28344
|
+
description: config2.description,
|
|
28345
|
+
required: config2.required
|
|
28346
|
+
}));
|
|
28347
|
+
}
|
|
28348
|
+
async ensureRequired() {
|
|
28349
|
+
const installed = [];
|
|
28350
|
+
const missing = [];
|
|
28351
|
+
const errors3 = {};
|
|
28352
|
+
for (const config2 of PLUGIN_TOOLS) {
|
|
28353
|
+
if (config2.required && !this.isInstalled(config2.name)) {
|
|
28354
|
+
const result = await this.install(config2);
|
|
28355
|
+
if (result.success) {
|
|
28356
|
+
installed.push(config2.name);
|
|
28357
|
+
} else {
|
|
28358
|
+
missing.push(config2.name);
|
|
28359
|
+
errors3[config2.name] = result.error || "Installation failed";
|
|
28360
|
+
}
|
|
28361
|
+
}
|
|
28362
|
+
}
|
|
28363
|
+
return { installed, missing, errors: errors3 };
|
|
28364
|
+
}
|
|
28365
|
+
async installAll() {
|
|
28366
|
+
const success2 = [];
|
|
28367
|
+
const failed = {};
|
|
28368
|
+
for (const config2 of PLUGIN_TOOLS) {
|
|
28369
|
+
if (!this.isInstalled(config2.name)) {
|
|
28370
|
+
const result = await this.install(config2);
|
|
28371
|
+
if (result.success) {
|
|
28372
|
+
success2.push(config2.name);
|
|
28373
|
+
} else {
|
|
28374
|
+
failed[config2.name] = result.error || "Installation failed";
|
|
28375
|
+
}
|
|
28376
|
+
} else {
|
|
28377
|
+
success2.push(config2.name);
|
|
28378
|
+
}
|
|
28379
|
+
}
|
|
28380
|
+
return { success: success2, failed };
|
|
28381
|
+
}
|
|
28382
|
+
async installTool(toolName) {
|
|
28383
|
+
const config2 = PLUGIN_TOOLS.find((t) => t.name === toolName);
|
|
28384
|
+
if (!config2) {
|
|
28385
|
+
return { success: false, error: `Unknown tool: ${toolName}. Available: ${PLUGIN_TOOLS.map((t) => t.name).join(", ")}` };
|
|
28386
|
+
}
|
|
28387
|
+
if (this.isInstalled(toolName)) {
|
|
28388
|
+
return { success: true, output: `${toolName} is already installed` };
|
|
28389
|
+
}
|
|
28390
|
+
return this.install(config2);
|
|
28391
|
+
}
|
|
28392
|
+
}
|
|
28393
|
+
var dependencyInstaller = new DependencyInstaller;
|
|
28394
|
+
async function ensurePluginDeps() {
|
|
28395
|
+
dependencyInstaller.ensureRequired().catch(console.error);
|
|
28396
|
+
}
|
|
28397
|
+
|
|
27280
28398
|
// src/index.ts
|
|
27281
28399
|
function formatSkillsXml(skills) {
|
|
27282
28400
|
if (skills.length === 0)
|
|
@@ -27302,7 +28420,7 @@ async function buildAutoLoadedSkillsContent(agentName, configService, projectRoo
|
|
|
27302
28420
|
if (autoLoadSkills.length === 0) {
|
|
27303
28421
|
return "";
|
|
27304
28422
|
}
|
|
27305
|
-
const homeDir = process.env.HOME ||
|
|
28423
|
+
const homeDir = process.env.HOME || os5.homedir();
|
|
27306
28424
|
const skillTemplates = [];
|
|
27307
28425
|
for (const skillId of autoLoadSkills) {
|
|
27308
28426
|
const builtinSkill = BUILTIN_SKILLS.find((entry) => entry.name === skillId);
|
|
@@ -27384,11 +28502,14 @@ var plugin = async (ctx) => {
|
|
|
27384
28502
|
const disabledMcps = configService.getDisabledMcps();
|
|
27385
28503
|
const disabledSkills = configService.getDisabledSkills();
|
|
27386
28504
|
const builtinMcps = createBuiltinMcps(disabledMcps);
|
|
28505
|
+
if (configService.get().autoInstallDeps !== false) {
|
|
28506
|
+
ensurePluginDeps();
|
|
28507
|
+
}
|
|
27387
28508
|
const filteredSkills = getFilteredSkills(disabledSkills);
|
|
27388
28509
|
const effectiveAutoLoadSkills = configService.getAgentConfig("zetta").autoLoadSkills ?? [];
|
|
27389
28510
|
const worktreeService = new WorktreeService({
|
|
27390
28511
|
baseDir: directory,
|
|
27391
|
-
hiveDir:
|
|
28512
|
+
hiveDir: path12.join(directory, ".hive")
|
|
27392
28513
|
});
|
|
27393
28514
|
const isOmoSlimEnabled = () => {
|
|
27394
28515
|
return configService.isOmoSlimEnabled();
|
|
@@ -27415,7 +28536,7 @@ var plugin = async (ctx) => {
|
|
|
27415
28536
|
};
|
|
27416
28537
|
const checkBlocked = (feature) => {
|
|
27417
28538
|
const fs12 = __require("fs");
|
|
27418
|
-
const blockedPath =
|
|
28539
|
+
const blockedPath = path12.join(directory, ".hive", "features", feature, "BLOCKED");
|
|
27419
28540
|
if (fs12.existsSync(blockedPath)) {
|
|
27420
28541
|
const reason = fs12.readFileSync(blockedPath, "utf-8").trim();
|
|
27421
28542
|
return `⛔ BLOCKED by Beekeeper
|
|
@@ -27569,9 +28690,9 @@ To unblock: Remove .hive/features/${feature}/BLOCKED`;
|
|
|
27569
28690
|
spec: specContent,
|
|
27570
28691
|
workerPrompt
|
|
27571
28692
|
});
|
|
27572
|
-
const hiveDir =
|
|
28693
|
+
const hiveDir = path12.join(directory, ".hive");
|
|
27573
28694
|
const workerPromptPath = writeWorkerPromptFile(feature, task, workerPrompt, hiveDir);
|
|
27574
|
-
const relativePromptPath = normalizePath(
|
|
28695
|
+
const relativePromptPath = normalizePath(path12.relative(directory, workerPromptPath));
|
|
27575
28696
|
const PREVIEW_MAX_LENGTH = 200;
|
|
27576
28697
|
const workerPromptPreview = workerPrompt.length > PREVIEW_MAX_LENGTH ? workerPrompt.slice(0, PREVIEW_MAX_LENGTH) + "..." : workerPrompt;
|
|
27577
28698
|
const taskToolPrompt = `Follow instructions in @${relativePromptPath}`;
|
|
@@ -27979,7 +29100,7 @@ ${snapshot}
|
|
|
27979
29100
|
if (sandboxConfig.mode !== "none") {
|
|
27980
29101
|
const workdir = output.args?.workdir;
|
|
27981
29102
|
if (workdir) {
|
|
27982
|
-
const hiveWorktreeBase =
|
|
29103
|
+
const hiveWorktreeBase = path12.join(directory, ".hive", ".worktrees");
|
|
27983
29104
|
if (workdir.startsWith(hiveWorktreeBase)) {
|
|
27984
29105
|
const wrapped = DockerSandboxService.wrapCommand(workdir, finalCommand, sandboxConfig);
|
|
27985
29106
|
output.args.command = wrapped;
|
|
@@ -28030,6 +29151,8 @@ ${snapshot}
|
|
|
28030
29151
|
lsp_diagnostics: lspDiagnosticsTool,
|
|
28031
29152
|
lsp_hover: lspHoverTool,
|
|
28032
29153
|
lsp_code_actions: lspCodeActionsTool,
|
|
29154
|
+
lsp_status: lspStatusTool,
|
|
29155
|
+
lsp_install: lspInstallTool,
|
|
28033
29156
|
skill_mcp: skillMcpTool,
|
|
28034
29157
|
list_skill_mcps: listSkillMcpsTool,
|
|
28035
29158
|
hive_memory_list: hiveMemoryListTool,
|
|
@@ -28054,6 +29177,16 @@ ${snapshot}
|
|
|
28054
29177
|
ast_grep_analyze_imports: astGrepAnalyzeImportsTool,
|
|
28055
29178
|
hive_doctor: hiveDoctorTool,
|
|
28056
29179
|
hive_doctor_quick: hiveDoctorQuickTool,
|
|
29180
|
+
dora_status: doraStatusTool,
|
|
29181
|
+
dora_symbol: doraSymbolTool,
|
|
29182
|
+
dora_file: doraFileTool,
|
|
29183
|
+
dora_references: doraReferencesTool,
|
|
29184
|
+
dora_cycles: doraCyclesTool,
|
|
29185
|
+
dora_unused: doraUnusedTool,
|
|
29186
|
+
auto_cr_status: autoCrStatusTool,
|
|
29187
|
+
auto_cr_scan: autoCrScanTool,
|
|
29188
|
+
auto_cr_diff: autoCrDiffTool,
|
|
29189
|
+
auto_cr_rules: autoCrRulesTool,
|
|
28057
29190
|
hive_skill: createHiveSkillTool(filteredSkills),
|
|
28058
29191
|
hive_feature_create: tool({
|
|
28059
29192
|
description: "Create a new feature and set it as active",
|