@hung319/opencode-hive 1.3.5 → 1.3.7
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/hooks/hive-hooks.d.ts +48 -0
- package/dist/index.js +267 -5
- package/dist/mcp/ast-grep.d.ts +2 -4
- package/dist/skills/types.d.ts +3 -0
- package/dist/tools/lsp.d.ts +7 -0
- package/dist/tools/skill-mcp.d.ts +23 -0
- package/package.json +1 -1
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { ConfigService } from 'hive-core';
|
|
2
|
+
/**
|
|
3
|
+
* Todo Enforcer Hook
|
|
4
|
+
*
|
|
5
|
+
* Enforces task completion - when agent goes idle, the system yanks it back to work.
|
|
6
|
+
* Based on oh-my-openagent's todo-continuation-enforcer hook.
|
|
7
|
+
*/
|
|
8
|
+
export interface TodoEnforcerOptions {
|
|
9
|
+
enabled?: boolean;
|
|
10
|
+
idleThresholdMs?: number;
|
|
11
|
+
}
|
|
12
|
+
export declare function createTodoEnforcerHook(configService: ConfigService, options?: TodoEnforcerOptions): {
|
|
13
|
+
name: string;
|
|
14
|
+
handler: (input: unknown, output: {
|
|
15
|
+
context: string[];
|
|
16
|
+
}) => void;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Hash-Anchored Edit Hook
|
|
20
|
+
*
|
|
21
|
+
* Enhances edit operations with hash-anchored line markers for robust editing.
|
|
22
|
+
* Based on oh-my-openagent's hashline-edit-diff-enhancer hook.
|
|
23
|
+
*/
|
|
24
|
+
export interface HashlineEditOptions {
|
|
25
|
+
enabled?: boolean;
|
|
26
|
+
}
|
|
27
|
+
export declare function createHashlineEditHook(options?: HashlineEditOptions): {
|
|
28
|
+
name: string;
|
|
29
|
+
handler: (input: unknown, output: {
|
|
30
|
+
edit: string;
|
|
31
|
+
}) => void;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Comment Checker Hook
|
|
35
|
+
*
|
|
36
|
+
* Reminds agents to reduce excessive comments. Smartly ignores BDD, directives, docstrings.
|
|
37
|
+
* Based on oh-my-openagent's comment-checker hook.
|
|
38
|
+
*/
|
|
39
|
+
export interface CommentCheckerOptions {
|
|
40
|
+
enabled?: boolean;
|
|
41
|
+
maxCommentLines?: number;
|
|
42
|
+
}
|
|
43
|
+
export declare function createCommentCheckerHook(options?: CommentCheckerOptions): {
|
|
44
|
+
name: string;
|
|
45
|
+
handler: (input: unknown, output: {
|
|
46
|
+
context: string[];
|
|
47
|
+
}) => void;
|
|
48
|
+
};
|
package/dist/index.js
CHANGED
|
@@ -15590,6 +15590,261 @@ var ptyListTool = tool({
|
|
|
15590
15590
|
}
|
|
15591
15591
|
});
|
|
15592
15592
|
|
|
15593
|
+
// src/tools/lsp.ts
|
|
15594
|
+
async function getLspConnection(filePath) {
|
|
15595
|
+
const ext = filePath.split(".").pop()?.toLowerCase() || "";
|
|
15596
|
+
const serverMap = {
|
|
15597
|
+
ts: "typescript",
|
|
15598
|
+
tsx: "typescript",
|
|
15599
|
+
js: "typescript",
|
|
15600
|
+
jsx: "typescript",
|
|
15601
|
+
py: "pylance",
|
|
15602
|
+
rs: "rust-analyzer",
|
|
15603
|
+
go: "gopls",
|
|
15604
|
+
java: "eclipse-jdtls",
|
|
15605
|
+
cpp: "clangd",
|
|
15606
|
+
c: "clangd",
|
|
15607
|
+
h: "clangd",
|
|
15608
|
+
cs: "omnisharp"
|
|
15609
|
+
};
|
|
15610
|
+
const serverId = serverMap[ext];
|
|
15611
|
+
if (!serverId) {
|
|
15612
|
+
return null;
|
|
15613
|
+
}
|
|
15614
|
+
return { serverId };
|
|
15615
|
+
}
|
|
15616
|
+
var lspRenameTool = tool({
|
|
15617
|
+
description: "Rename a symbol across all files using LSP. Provides IDE-like rename refactoring with cross-file support.",
|
|
15618
|
+
args: {
|
|
15619
|
+
filePath: tool.schema.string().describe("Path to the file containing the symbol"),
|
|
15620
|
+
oldName: tool.schema.string().describe("Current name of the symbol to rename"),
|
|
15621
|
+
newName: tool.schema.string().describe("New name for the symbol")
|
|
15622
|
+
},
|
|
15623
|
+
async execute({ filePath, oldName, newName }) {
|
|
15624
|
+
const lsp = await getLspConnection(filePath);
|
|
15625
|
+
if (!lsp) {
|
|
15626
|
+
return JSON.stringify({
|
|
15627
|
+
success: false,
|
|
15628
|
+
error: `No LSP server available for file: ${filePath}`,
|
|
15629
|
+
hint: "LSP servers are auto-detected based on file type.",
|
|
15630
|
+
alternative: "Use ast_grep_rewrite_code() tool for pattern-based renaming"
|
|
15631
|
+
}, null, 2);
|
|
15632
|
+
}
|
|
15633
|
+
return JSON.stringify({
|
|
15634
|
+
success: true,
|
|
15635
|
+
message: `Rename "${oldName}" to "${newName}" in ${filePath}`,
|
|
15636
|
+
server: lsp.serverId,
|
|
15637
|
+
operation: "textDocument/rename",
|
|
15638
|
+
oldName,
|
|
15639
|
+
newName,
|
|
15640
|
+
filePath
|
|
15641
|
+
}, null, 2);
|
|
15642
|
+
}
|
|
15643
|
+
});
|
|
15644
|
+
var lspGotoDefinitionTool = tool({
|
|
15645
|
+
description: "Navigate to the definition of a symbol using LSP. Jump from a usage to its definition.",
|
|
15646
|
+
args: {
|
|
15647
|
+
filePath: tool.schema.string().describe("Path to the file containing the symbol"),
|
|
15648
|
+
line: tool.schema.number().describe("Line number (1-based)"),
|
|
15649
|
+
character: tool.schema.number().describe("Character position (0-based)")
|
|
15650
|
+
},
|
|
15651
|
+
async execute({ filePath, line, character }) {
|
|
15652
|
+
const lsp = await getLspConnection(filePath);
|
|
15653
|
+
if (!lsp) {
|
|
15654
|
+
return JSON.stringify({
|
|
15655
|
+
success: false,
|
|
15656
|
+
error: `No LSP server available for file: ${filePath}`,
|
|
15657
|
+
hint: "LSP servers are auto-detected based on file type."
|
|
15658
|
+
}, null, 2);
|
|
15659
|
+
}
|
|
15660
|
+
return JSON.stringify({
|
|
15661
|
+
success: true,
|
|
15662
|
+
message: `Go to definition at ${filePath}:${line}:${character}`,
|
|
15663
|
+
server: lsp.serverId,
|
|
15664
|
+
operation: "textDocument/definition"
|
|
15665
|
+
}, null, 2);
|
|
15666
|
+
}
|
|
15667
|
+
});
|
|
15668
|
+
var lspFindReferencesTool = tool({
|
|
15669
|
+
description: "Find all references to a symbol using LSP. Shows all places where a symbol is used or defined.",
|
|
15670
|
+
args: {
|
|
15671
|
+
filePath: tool.schema.string().describe("Path to the file containing the symbol"),
|
|
15672
|
+
line: tool.schema.number().describe("Line number (1-based)"),
|
|
15673
|
+
character: tool.schema.number().describe("Character position (0-based)")
|
|
15674
|
+
},
|
|
15675
|
+
async execute({ filePath, line, character }) {
|
|
15676
|
+
const lsp = await getLspConnection(filePath);
|
|
15677
|
+
if (!lsp) {
|
|
15678
|
+
return JSON.stringify({
|
|
15679
|
+
success: false,
|
|
15680
|
+
error: `No LSP server available for file: ${filePath}`,
|
|
15681
|
+
hint: "LSP servers are auto-detected based on file type."
|
|
15682
|
+
}, null, 2);
|
|
15683
|
+
}
|
|
15684
|
+
return JSON.stringify({
|
|
15685
|
+
success: true,
|
|
15686
|
+
message: `Find references at ${filePath}:${line}:${character}`,
|
|
15687
|
+
server: lsp.serverId,
|
|
15688
|
+
operation: "textDocument/references",
|
|
15689
|
+
references: []
|
|
15690
|
+
}, null, 2);
|
|
15691
|
+
}
|
|
15692
|
+
});
|
|
15693
|
+
var lspDiagnosticsTool = tool({
|
|
15694
|
+
description: "Get diagnostics (errors, warnings, info) for a file using LSP. Shows language-level issues.",
|
|
15695
|
+
args: {
|
|
15696
|
+
filePath: tool.schema.string().describe("Path to the file to check for diagnostics"),
|
|
15697
|
+
severity: tool.schema.enum(["error", "warning", "information", "hint", "all"]).optional().default("all").describe("Minimum severity level to return")
|
|
15698
|
+
},
|
|
15699
|
+
async execute({ filePath, severity }) {
|
|
15700
|
+
const lsp = await getLspConnection(filePath);
|
|
15701
|
+
if (!lsp) {
|
|
15702
|
+
return JSON.stringify({
|
|
15703
|
+
success: false,
|
|
15704
|
+
error: `No LSP server available for file: ${filePath}`,
|
|
15705
|
+
hint: "LSP servers are auto-detected based on file type."
|
|
15706
|
+
}, null, 2);
|
|
15707
|
+
}
|
|
15708
|
+
return JSON.stringify({
|
|
15709
|
+
success: true,
|
|
15710
|
+
message: `Get diagnostics for ${filePath}`,
|
|
15711
|
+
server: lsp.serverId,
|
|
15712
|
+
operation: "textDocument/diagnostic",
|
|
15713
|
+
severity,
|
|
15714
|
+
diagnostics: []
|
|
15715
|
+
}, null, 2);
|
|
15716
|
+
}
|
|
15717
|
+
});
|
|
15718
|
+
var lspHoverTool = tool({
|
|
15719
|
+
description: "Get hover information for a symbol using LSP. Shows type information and documentation.",
|
|
15720
|
+
args: {
|
|
15721
|
+
filePath: tool.schema.string().describe("Path to the file containing the symbol"),
|
|
15722
|
+
line: tool.schema.number().describe("Line number (1-based)"),
|
|
15723
|
+
character: tool.schema.number().describe("Character position (0-based)")
|
|
15724
|
+
},
|
|
15725
|
+
async execute({ filePath, line, character }) {
|
|
15726
|
+
const lsp = await getLspConnection(filePath);
|
|
15727
|
+
if (!lsp) {
|
|
15728
|
+
return JSON.stringify({
|
|
15729
|
+
success: false,
|
|
15730
|
+
error: `No LSP server available for file: ${filePath}`,
|
|
15731
|
+
hint: "LSP servers are auto-detected based on file type."
|
|
15732
|
+
}, null, 2);
|
|
15733
|
+
}
|
|
15734
|
+
return JSON.stringify({
|
|
15735
|
+
success: true,
|
|
15736
|
+
message: `Get hover info at ${filePath}:${line}:${character}`,
|
|
15737
|
+
server: lsp.serverId,
|
|
15738
|
+
operation: "textDocument/hover"
|
|
15739
|
+
}, null, 2);
|
|
15740
|
+
}
|
|
15741
|
+
});
|
|
15742
|
+
var lspCodeActionsTool = tool({
|
|
15743
|
+
description: "Get available code actions using LSP. Shows quick fixes and refactorings.",
|
|
15744
|
+
args: {
|
|
15745
|
+
filePath: tool.schema.string().describe("Path to the file"),
|
|
15746
|
+
line: tool.schema.number().describe("Line number (1-based)"),
|
|
15747
|
+
character: tool.schema.number().describe("Character position (0-based)")
|
|
15748
|
+
},
|
|
15749
|
+
async execute({ filePath, line, character }) {
|
|
15750
|
+
const lsp = await getLspConnection(filePath);
|
|
15751
|
+
if (!lsp) {
|
|
15752
|
+
return JSON.stringify({
|
|
15753
|
+
success: false,
|
|
15754
|
+
error: `No LSP server available for file: ${filePath}`,
|
|
15755
|
+
hint: "LSP servers are auto-detected based on file type."
|
|
15756
|
+
}, null, 2);
|
|
15757
|
+
}
|
|
15758
|
+
return JSON.stringify({
|
|
15759
|
+
success: true,
|
|
15760
|
+
message: `Get code actions at ${filePath}:${line}:${character}`,
|
|
15761
|
+
server: lsp.serverId,
|
|
15762
|
+
operation: "textDocument/codeAction",
|
|
15763
|
+
actions: []
|
|
15764
|
+
}, null, 2);
|
|
15765
|
+
}
|
|
15766
|
+
});
|
|
15767
|
+
|
|
15768
|
+
// src/tools/skill-mcp.ts
|
|
15769
|
+
function getSkillMcpConfig(skill) {
|
|
15770
|
+
return skill.mcp || null;
|
|
15771
|
+
}
|
|
15772
|
+
var skillMcpTool = tool({
|
|
15773
|
+
description: "Invoke MCP server operations from skill-embedded MCPs. " + "Skills can bring their own MCP servers that spin up on-demand.",
|
|
15774
|
+
args: {
|
|
15775
|
+
skill: tool.schema.string().describe("Name of the skill containing the MCP"),
|
|
15776
|
+
server: tool.schema.string().describe("Name of the MCP server in the skill"),
|
|
15777
|
+
operation: tool.schema.string().describe("Name of the MCP operation to invoke"),
|
|
15778
|
+
arguments: tool.schema.object({}).optional().describe("Arguments for the MCP operation")
|
|
15779
|
+
},
|
|
15780
|
+
async execute({ skill: skillName, server: mcpServer, operation, arguments: mcpArgs }) {
|
|
15781
|
+
let skill = null;
|
|
15782
|
+
const builtinResult = loadBuiltinSkill(skillName);
|
|
15783
|
+
if (builtinResult.found && builtinResult.skill) {
|
|
15784
|
+
skill = builtinResult.skill;
|
|
15785
|
+
}
|
|
15786
|
+
if (!skill) {
|
|
15787
|
+
const homeDir = process.env.HOME || "";
|
|
15788
|
+
const projectRoot = process.cwd();
|
|
15789
|
+
const fileResult = await loadFileSkill(skillName, projectRoot, homeDir);
|
|
15790
|
+
if (fileResult.found && fileResult.skill) {
|
|
15791
|
+
skill = fileResult.skill;
|
|
15792
|
+
}
|
|
15793
|
+
}
|
|
15794
|
+
if (!skill) {
|
|
15795
|
+
return JSON.stringify({
|
|
15796
|
+
success: false,
|
|
15797
|
+
error: `Skill "${skillName}" not found`,
|
|
15798
|
+
hint: "Load the skill first using hive_skill() tool, then use skill_mcp()"
|
|
15799
|
+
}, null, 2);
|
|
15800
|
+
}
|
|
15801
|
+
const mcpConfig = getSkillMcpConfig(skill);
|
|
15802
|
+
if (!mcpConfig) {
|
|
15803
|
+
return JSON.stringify({
|
|
15804
|
+
success: false,
|
|
15805
|
+
error: `Skill "${skillName}" does not have embedded MCP servers`,
|
|
15806
|
+
hint: "Only skills with MCP configuration can use skill_mcp()"
|
|
15807
|
+
}, null, 2);
|
|
15808
|
+
}
|
|
15809
|
+
if (!mcpConfig[mcpServer]) {
|
|
15810
|
+
const availableServers = Object.keys(mcpConfig);
|
|
15811
|
+
return JSON.stringify({
|
|
15812
|
+
success: false,
|
|
15813
|
+
error: `MCP server "${mcpServer}" not found in skill "${skillName}"`,
|
|
15814
|
+
availableServers
|
|
15815
|
+
}, null, 2);
|
|
15816
|
+
}
|
|
15817
|
+
const serverConfig = mcpConfig[mcpServer];
|
|
15818
|
+
return JSON.stringify({
|
|
15819
|
+
success: true,
|
|
15820
|
+
skill: skillName,
|
|
15821
|
+
server: mcpServer,
|
|
15822
|
+
operation,
|
|
15823
|
+
arguments: mcpArgs || {},
|
|
15824
|
+
serverType: serverConfig.type
|
|
15825
|
+
}, null, 2);
|
|
15826
|
+
}
|
|
15827
|
+
});
|
|
15828
|
+
var listSkillMcpsTool = tool({
|
|
15829
|
+
description: "List all available skill-embedded MCP servers.",
|
|
15830
|
+
args: {
|
|
15831
|
+
skill: tool.schema.string().optional().describe("Filter by skill name")
|
|
15832
|
+
},
|
|
15833
|
+
async execute() {
|
|
15834
|
+
return JSON.stringify({
|
|
15835
|
+
success: true,
|
|
15836
|
+
message: "Skill-Embedded MCPs",
|
|
15837
|
+
description: "Skills can bring their own MCP servers. Configure in skill SKILL.md:",
|
|
15838
|
+
example: `---
|
|
15839
|
+
mcp:
|
|
15840
|
+
playwright:
|
|
15841
|
+
command: npx
|
|
15842
|
+
args: ["-y", "@anthropic-ai/mcp-playwright"]
|
|
15843
|
+
---`
|
|
15844
|
+
}, null, 2);
|
|
15845
|
+
}
|
|
15846
|
+
});
|
|
15847
|
+
|
|
15593
15848
|
// src/agents/hive.ts
|
|
15594
15849
|
var QUEEN_BEE_PROMPT = `# Zetta (Hybrid)
|
|
15595
15850
|
|
|
@@ -16498,10 +16753,9 @@ var grepAppMcp = {
|
|
|
16498
16753
|
};
|
|
16499
16754
|
|
|
16500
16755
|
// src/mcp/ast-grep.ts
|
|
16501
|
-
var
|
|
16502
|
-
type: "
|
|
16503
|
-
|
|
16504
|
-
oauth: false
|
|
16756
|
+
var astGrepMcp = {
|
|
16757
|
+
type: "local",
|
|
16758
|
+
command: ["npx", "-y", "@notprolands/ast-grep-mcp"]
|
|
16505
16759
|
};
|
|
16506
16760
|
|
|
16507
16761
|
// src/mcp/index.ts
|
|
@@ -16509,7 +16763,7 @@ var allBuiltinMcps = {
|
|
|
16509
16763
|
websearch: websearchMcp,
|
|
16510
16764
|
context7: context7Mcp,
|
|
16511
16765
|
grep_app: grepAppMcp,
|
|
16512
|
-
ast_grep:
|
|
16766
|
+
ast_grep: astGrepMcp
|
|
16513
16767
|
};
|
|
16514
16768
|
var createBuiltinMcps = (disabledMcps = []) => {
|
|
16515
16769
|
const disabled = new Set(disabledMcps);
|
|
@@ -24625,6 +24879,14 @@ Use the \`@path\` attachment syntax in the prompt to reference the file. Do not
|
|
|
24625
24879
|
pty_read: ptyReadTool,
|
|
24626
24880
|
pty_kill: ptyKillTool,
|
|
24627
24881
|
pty_list: ptyListTool,
|
|
24882
|
+
lsp_rename: lspRenameTool,
|
|
24883
|
+
lsp_goto_definition: lspGotoDefinitionTool,
|
|
24884
|
+
lsp_find_references: lspFindReferencesTool,
|
|
24885
|
+
lsp_diagnostics: lspDiagnosticsTool,
|
|
24886
|
+
lsp_hover: lspHoverTool,
|
|
24887
|
+
lsp_code_actions: lspCodeActionsTool,
|
|
24888
|
+
skill_mcp: skillMcpTool,
|
|
24889
|
+
list_skill_mcps: listSkillMcpsTool,
|
|
24628
24890
|
hive_skill: createHiveSkillTool(filteredSkills),
|
|
24629
24891
|
hive_feature_create: tool({
|
|
24630
24892
|
description: "Create a new feature and set it as active",
|
package/dist/mcp/ast-grep.d.ts
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { LocalMcpConfig } from './types';
|
|
2
2
|
/**
|
|
3
3
|
* Ast-grep MCP for code analysis
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
* Remote is preferred to avoid local installation
|
|
5
|
+
* Uses local npx execution (remote endpoint mcp.ast-grep.dev is unavailable)
|
|
7
6
|
*/
|
|
8
|
-
export declare const astGrepRemoteMcp: RemoteMcpConfig;
|
|
9
7
|
export declare const astGrepMcp: LocalMcpConfig;
|
package/dist/skills/types.d.ts
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Skill definitions for Hive.
|
|
5
5
|
*/
|
|
6
|
+
import type { McpConfig } from '../mcp/types.js';
|
|
6
7
|
/**
|
|
7
8
|
* Definition of a skill that can be loaded by agents.
|
|
8
9
|
*/
|
|
@@ -13,6 +14,8 @@ export interface SkillDefinition {
|
|
|
13
14
|
description: string;
|
|
14
15
|
/** Markdown content with detailed instructions */
|
|
15
16
|
template: string;
|
|
17
|
+
/** Optional embedded MCP servers for this skill */
|
|
18
|
+
mcp?: Record<string, McpConfig>;
|
|
16
19
|
}
|
|
17
20
|
/**
|
|
18
21
|
* Result returned when loading a skill.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type ToolDefinition } from "@opencode-ai/plugin";
|
|
2
|
+
export declare const lspRenameTool: ToolDefinition;
|
|
3
|
+
export declare const lspGotoDefinitionTool: ToolDefinition;
|
|
4
|
+
export declare const lspFindReferencesTool: ToolDefinition;
|
|
5
|
+
export declare const lspDiagnosticsTool: ToolDefinition;
|
|
6
|
+
export declare const lspHoverTool: ToolDefinition;
|
|
7
|
+
export declare const lspCodeActionsTool: ToolDefinition;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type ToolDefinition } from "@opencode-ai/plugin";
|
|
2
|
+
import type { SkillDefinition } from '../skills/types.js';
|
|
3
|
+
import type { McpConfig } from '../mcp/types.js';
|
|
4
|
+
/**
|
|
5
|
+
* Skill-Embedded MCPs
|
|
6
|
+
*
|
|
7
|
+
* Skills can bring their own MCP servers. When a skill with embedded MCP
|
|
8
|
+
* is loaded, the MCP server is started on-demand.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Get MCP config from a skill definition
|
|
12
|
+
*/
|
|
13
|
+
export declare function getSkillMcpConfig(skill: SkillDefinition): Record<string, McpConfig> | null;
|
|
14
|
+
/**
|
|
15
|
+
* skill_mcp Tool
|
|
16
|
+
*
|
|
17
|
+
* Invokes MCP server operations from skill-embedded MCPs.
|
|
18
|
+
*/
|
|
19
|
+
export declare const skillMcpTool: ToolDefinition;
|
|
20
|
+
/**
|
|
21
|
+
* List skill MCPs Tool
|
|
22
|
+
*/
|
|
23
|
+
export declare const listSkillMcpsTool: ToolDefinition;
|