@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 +1086 -134
- 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/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);
|
|
@@ -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
|
+
};
|
|
16236
16425
|
}
|
|
16237
|
-
|
|
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:
|
|
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) {
|
|
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
|
-
|
|
16304
|
-
|
|
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) {
|
|
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
|
-
|
|
16328
|
-
|
|
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,7 +21605,7 @@ 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
|
}
|
|
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 (!
|
|
20743
|
-
|
|
21682
|
+
if (!fs8.existsSync(dirPath)) {
|
|
21683
|
+
fs8.mkdirSync(dirPath, { recursive: true });
|
|
20744
21684
|
}
|
|
20745
21685
|
}
|
|
20746
21686
|
function fileExists(filePath) {
|
|
20747
|
-
return
|
|
21687
|
+
return fs8.existsSync(filePath);
|
|
20748
21688
|
}
|
|
20749
21689
|
function readJson(filePath) {
|
|
20750
|
-
if (!
|
|
21690
|
+
if (!fs8.existsSync(filePath))
|
|
20751
21691
|
return null;
|
|
20752
|
-
const content =
|
|
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
|
-
|
|
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 =
|
|
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 =
|
|
20790
|
-
|
|
20791
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
20824
|
-
|
|
21763
|
+
fs8.writeFileSync(tempPath, content);
|
|
21764
|
+
fs8.renameSync(tempPath, filePath);
|
|
20825
21765
|
} catch (error45) {
|
|
20826
21766
|
try {
|
|
20827
|
-
|
|
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 (!
|
|
21802
|
+
if (!fs8.existsSync(filePath))
|
|
20863
21803
|
return null;
|
|
20864
|
-
return
|
|
21804
|
+
return fs8.readFileSync(filePath, "utf-8");
|
|
20865
21805
|
}
|
|
20866
21806
|
function writeText(filePath, content) {
|
|
20867
21807
|
ensureDir(path22.dirname(filePath));
|
|
20868
|
-
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
26201
|
-
|
|
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 =
|
|
26230
|
-
this.configPath =
|
|
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 =
|
|
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
|
-
|
|
27621
|
+
execSync4(`docker inspect --format='{{.State.Running}}' ${name}`, { stdio: "pipe" });
|
|
26682
27622
|
return name;
|
|
26683
27623
|
} catch {
|
|
26684
|
-
|
|
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
|
-
|
|
27635
|
+
execSync4(`docker rm -f ${name}`, { stdio: "ignore" });
|
|
26696
27636
|
} catch {}
|
|
26697
27637
|
}
|
|
26698
27638
|
static isDockerAvailable() {
|
|
26699
27639
|
try {
|
|
26700
|
-
|
|
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",
|