@hiai-gg/hiai-opencode 0.1.4 → 0.1.5
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/AGENTS.md +5 -3
- package/ARCHITECTURE.md +7 -6
- package/README.md +16 -4
- package/config/hiai-opencode.schema.json +71 -148
- package/dist/config/defaults.d.ts +1 -0
- package/dist/config/platform-schema.d.ts +273 -4
- package/dist/config/schema/categories.d.ts +2 -2
- package/dist/config/types.d.ts +21 -2
- package/dist/create-tools.d.ts +2 -0
- package/dist/index.js +577 -342
- package/dist/internals/plugins/websearch-cited/index.d.ts +7 -1
- package/dist/mcp/types.d.ts +1 -1
- package/dist/plugin/tool-registry.d.ts +2 -0
- package/dist/tools/skill-mcp/tools.d.ts +2 -0
- package/hiai-opencode.json +39 -173
- package/package.json +1 -1
- package/src/config/defaults.ts +158 -28
- package/src/config/loader.test.ts +16 -1
- package/src/config/loader.ts +4 -2
- package/src/config/platform-schema.ts +36 -2
- package/src/config/types.ts +33 -2
- package/src/create-tools.ts +4 -1
- package/src/index.ts +39 -1
- package/src/internals/plugins/websearch-cited/index.ts +10 -5
- package/src/lsp/index.ts +1 -0
- package/src/mcp/registry.ts +6 -1
- package/src/plugin/tool-registry.ts +4 -0
- package/src/tools/skill-mcp/tools.ts +45 -7
|
@@ -8,6 +8,37 @@ export const AgentConfigSchema = z.object({
|
|
|
8
8
|
description: z.string().optional(),
|
|
9
9
|
});
|
|
10
10
|
|
|
11
|
+
export const ModelRecommendationSchema = z.enum([
|
|
12
|
+
"xhigh",
|
|
13
|
+
"high",
|
|
14
|
+
"middle",
|
|
15
|
+
"fast",
|
|
16
|
+
"vision",
|
|
17
|
+
"writing",
|
|
18
|
+
"design",
|
|
19
|
+
]);
|
|
20
|
+
|
|
21
|
+
export const ModelSlotConfigSchema = z.union([
|
|
22
|
+
z.string(),
|
|
23
|
+
z.object({
|
|
24
|
+
model: z.string(),
|
|
25
|
+
recommended: ModelRecommendationSchema.optional(),
|
|
26
|
+
}),
|
|
27
|
+
]);
|
|
28
|
+
|
|
29
|
+
export const ModelSlotsConfigSchema = z.object({
|
|
30
|
+
bob: ModelSlotConfigSchema.optional(),
|
|
31
|
+
coder: ModelSlotConfigSchema.optional(),
|
|
32
|
+
strategist: ModelSlotConfigSchema.optional(),
|
|
33
|
+
guard: ModelSlotConfigSchema.optional(),
|
|
34
|
+
critic: ModelSlotConfigSchema.optional(),
|
|
35
|
+
designer: ModelSlotConfigSchema.optional(),
|
|
36
|
+
researcher: ModelSlotConfigSchema.optional(),
|
|
37
|
+
manager: ModelSlotConfigSchema.optional(),
|
|
38
|
+
brainstormer: ModelSlotConfigSchema.optional(),
|
|
39
|
+
vision: ModelSlotConfigSchema.optional(),
|
|
40
|
+
});
|
|
41
|
+
|
|
11
42
|
export const FallbackEntrySchema = z.object({
|
|
12
43
|
providers: z.array(z.string()),
|
|
13
44
|
model: z.string(),
|
|
@@ -48,8 +79,9 @@ export const McpServerConfigSchema = z.object({
|
|
|
48
79
|
});
|
|
49
80
|
|
|
50
81
|
export const LspServerConfigSchema = z.object({
|
|
51
|
-
|
|
52
|
-
|
|
82
|
+
enabled: z.boolean().optional(),
|
|
83
|
+
command: z.array(z.string()).optional(),
|
|
84
|
+
extensions: z.array(z.string()).optional(),
|
|
53
85
|
initialization: z.record(z.string(), z.unknown()).optional(),
|
|
54
86
|
});
|
|
55
87
|
|
|
@@ -102,6 +134,7 @@ export const AuthKeysSchema = z.object({
|
|
|
102
134
|
openrouter: z.string().optional(),
|
|
103
135
|
stitch: z.string().optional(),
|
|
104
136
|
firecrawl: z.string().optional(),
|
|
137
|
+
context7: z.string().optional(),
|
|
105
138
|
});
|
|
106
139
|
|
|
107
140
|
export const OllamaConfigSchema = z.object({
|
|
@@ -190,6 +223,7 @@ const AgentRequirementsConfigSchema = z.object({
|
|
|
190
223
|
|
|
191
224
|
export const HiaiOpencodeConfigSchema = z.object({
|
|
192
225
|
$schema: z.string().optional(),
|
|
226
|
+
models: ModelSlotsConfigSchema.optional(),
|
|
193
227
|
agents: AgentsConfigSchema.optional(),
|
|
194
228
|
agentRequirements: AgentRequirementsConfigSchema.optional(),
|
|
195
229
|
categories: z.record(z.string(), CategoryConfigSchema).optional(),
|
package/src/config/types.ts
CHANGED
|
@@ -7,6 +7,35 @@ export interface AgentConfig {
|
|
|
7
7
|
description?: string;
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
+
export type ModelRecommendation =
|
|
11
|
+
| "xhigh"
|
|
12
|
+
| "high"
|
|
13
|
+
| "middle"
|
|
14
|
+
| "fast"
|
|
15
|
+
| "vision"
|
|
16
|
+
| "writing"
|
|
17
|
+
| "design";
|
|
18
|
+
|
|
19
|
+
export type ModelSlotConfig =
|
|
20
|
+
| string
|
|
21
|
+
| {
|
|
22
|
+
model: string;
|
|
23
|
+
recommended?: ModelRecommendation;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export interface ModelSlotsConfig {
|
|
27
|
+
bob?: ModelSlotConfig;
|
|
28
|
+
coder?: ModelSlotConfig;
|
|
29
|
+
strategist?: ModelSlotConfig;
|
|
30
|
+
guard?: ModelSlotConfig;
|
|
31
|
+
critic?: ModelSlotConfig;
|
|
32
|
+
designer?: ModelSlotConfig;
|
|
33
|
+
researcher?: ModelSlotConfig;
|
|
34
|
+
manager?: ModelSlotConfig;
|
|
35
|
+
brainstormer?: ModelSlotConfig;
|
|
36
|
+
vision?: ModelSlotConfig;
|
|
37
|
+
}
|
|
38
|
+
|
|
10
39
|
// Canonical 12-agent model exposed by schema/default config.
|
|
11
40
|
export const CANONICAL_AGENT_NAMES = [
|
|
12
41
|
"bob",
|
|
@@ -124,8 +153,9 @@ export interface McpServerConfig {
|
|
|
124
153
|
}
|
|
125
154
|
|
|
126
155
|
export interface LspServerConfig {
|
|
127
|
-
|
|
128
|
-
|
|
156
|
+
enabled?: boolean;
|
|
157
|
+
command?: string[];
|
|
158
|
+
extensions?: string[];
|
|
129
159
|
initialization?: Record<string, unknown>;
|
|
130
160
|
}
|
|
131
161
|
|
|
@@ -174,6 +204,7 @@ export interface OllamaConfig {
|
|
|
174
204
|
|
|
175
205
|
export interface HiaiOpencodeConfig {
|
|
176
206
|
$schema?: string;
|
|
207
|
+
models?: ModelSlotsConfig;
|
|
177
208
|
agents?: AgentConfigMap;
|
|
178
209
|
agentRequirements?: AgentRequirementMap;
|
|
179
210
|
categories?: Record<string, CategoryConfig>;
|
package/src/create-tools.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { AvailableCategory, AvailableSkill } from "./agents/dynamic-agent-prompt-builder"
|
|
2
2
|
import type { HiaiOpenCodeConfig } from "./config"
|
|
3
|
+
import type { HiaiOpencodeConfig } from "./config/types"
|
|
3
4
|
import type { BrowserAutomationProvider } from "./config/schema/browser-automation"
|
|
4
5
|
import type { LoadedSkill } from "./features/opencode-skill-loader/types"
|
|
5
6
|
import type { PluginContext, ToolsRecord } from "./plugin/types"
|
|
@@ -22,9 +23,10 @@ type CreateToolsResult = {
|
|
|
22
23
|
export async function createTools(args: {
|
|
23
24
|
ctx: PluginContext
|
|
24
25
|
pluginConfig: HiaiOpenCodeConfig
|
|
26
|
+
platformConfig?: HiaiOpencodeConfig
|
|
25
27
|
managers: Pick<Managers, "backgroundManager" | "tmuxSessionManager" | "skillMcpManager">
|
|
26
28
|
}): Promise<CreateToolsResult> {
|
|
27
|
-
const { ctx, pluginConfig, managers } = args
|
|
29
|
+
const { ctx, pluginConfig, platformConfig, managers } = args
|
|
28
30
|
|
|
29
31
|
const skillContext = await createSkillContext({
|
|
30
32
|
directory: ctx.directory,
|
|
@@ -39,6 +41,7 @@ export async function createTools(args: {
|
|
|
39
41
|
managers,
|
|
40
42
|
skillContext,
|
|
41
43
|
availableCategories,
|
|
44
|
+
builtinMcp: platformConfig?.mcp,
|
|
42
45
|
})
|
|
43
46
|
|
|
44
47
|
return {
|
package/src/index.ts
CHANGED
|
@@ -27,9 +27,13 @@ import type { HiaiOpencodeConfig } from "./config/types"
|
|
|
27
27
|
|
|
28
28
|
import { createPlugin as createSubtask2Plugin } from "./internals/plugins/subtask2/core/plugin"
|
|
29
29
|
import WebsearchCitedPlugin, {
|
|
30
|
+
GOOGLE_PROVIDER_ID,
|
|
31
|
+
OPENAI_PROVIDER_ID,
|
|
32
|
+
OPENROUTER_PROVIDER_ID,
|
|
30
33
|
WebsearchCitedGooglePlugin,
|
|
31
34
|
WebsearchCitedOpenAIPlugin
|
|
32
35
|
} from "./internals/plugins/websearch-cited/index"
|
|
36
|
+
import type { WebsearchCitedFallback } from "./internals/plugins/websearch-cited/index"
|
|
33
37
|
import { createBuiltinSkills } from "./features/builtin-skills"
|
|
34
38
|
import {
|
|
35
39
|
materializeBuiltinSkills,
|
|
@@ -38,6 +42,39 @@ import {
|
|
|
38
42
|
|
|
39
43
|
let activePluginDispose: PluginDispose | null = null
|
|
40
44
|
|
|
45
|
+
function createWebsearchFallback(config: HiaiOpencodeConfig): WebsearchCitedFallback | undefined {
|
|
46
|
+
const model = config.agents?.researcher?.model?.trim()
|
|
47
|
+
if (!model) {
|
|
48
|
+
return undefined
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (model.startsWith("openrouter/")) {
|
|
52
|
+
return {
|
|
53
|
+
providerID: OPENROUTER_PROVIDER_ID,
|
|
54
|
+
model: model.slice("openrouter/".length),
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (model.startsWith("openai/")) {
|
|
59
|
+
return {
|
|
60
|
+
providerID: OPENAI_PROVIDER_ID,
|
|
61
|
+
model: model.slice("openai/".length),
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (model.startsWith("google/")) {
|
|
66
|
+
return {
|
|
67
|
+
providerID: GOOGLE_PROVIDER_ID,
|
|
68
|
+
model: model.slice("google/".length),
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return {
|
|
73
|
+
providerID: OPENROUTER_PROVIDER_ID,
|
|
74
|
+
model,
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
41
78
|
function configureBundledBunPtyLibrary(): void {
|
|
42
79
|
if (process.env.BUN_PTY_LIB?.trim()) {
|
|
43
80
|
return
|
|
@@ -129,6 +166,7 @@ const HiaiOpenCodePlugin: Plugin = async (ctx) => {
|
|
|
129
166
|
const toolsResult = await createTools({
|
|
130
167
|
ctx,
|
|
131
168
|
pluginConfig,
|
|
169
|
+
platformConfig: internalConfig,
|
|
132
170
|
managers,
|
|
133
171
|
})
|
|
134
172
|
|
|
@@ -169,7 +207,7 @@ const HiaiOpenCodePlugin: Plugin = async (ctx) => {
|
|
|
169
207
|
} catch (err) {
|
|
170
208
|
console.error("[hiai-opencode] PTYPlugin failed to load:", err);
|
|
171
209
|
}
|
|
172
|
-
const websearchResult = await WebsearchCitedPlugin(ctx)
|
|
210
|
+
const websearchResult = await WebsearchCitedPlugin(ctx, createWebsearchFallback(internalConfig))
|
|
173
211
|
const websearchGoogleResult = await WebsearchCitedGooglePlugin(ctx)
|
|
174
212
|
const websearchOpenAIResult = await WebsearchCitedOpenAIPlugin(ctx)
|
|
175
213
|
|
|
@@ -44,6 +44,8 @@ type SelectedWebsearchConfig = {
|
|
|
44
44
|
model: string;
|
|
45
45
|
};
|
|
46
46
|
|
|
47
|
+
export type WebsearchCitedFallback = SelectedWebsearchConfig;
|
|
48
|
+
|
|
47
49
|
type WebsearchCitedSelection = {
|
|
48
50
|
selected?: SelectedWebsearchConfig;
|
|
49
51
|
error?: string;
|
|
@@ -164,16 +166,16 @@ function parseOpenAIOptions(providerConfig: unknown, model: string | undefined):
|
|
|
164
166
|
return result;
|
|
165
167
|
}
|
|
166
168
|
|
|
167
|
-
const WebsearchCitedPlugin
|
|
168
|
-
let selectedProvider: SelectedProviderID | undefined;
|
|
169
|
-
let selectedModel: string | undefined;
|
|
169
|
+
const WebsearchCitedPlugin = (_ctx?: unknown, fallback?: WebsearchCitedFallback): Promise<any> => {
|
|
170
|
+
let selectedProvider: SelectedProviderID | undefined = fallback?.providerID;
|
|
171
|
+
let selectedModel: string | undefined = fallback?.model;
|
|
170
172
|
let openaiConfig: OpenAIWebsearchConfig = {};
|
|
171
173
|
let configError: string | undefined;
|
|
172
174
|
|
|
173
175
|
return Promise.resolve({
|
|
174
176
|
auth: {
|
|
175
177
|
provider: OPENROUTER_PROVIDER_ID,
|
|
176
|
-
loader(getAuth) {
|
|
178
|
+
loader(getAuth: GetAuth) {
|
|
177
179
|
registerGetAuth(OPENROUTER_PROVIDER_ID, getAuth);
|
|
178
180
|
return Promise.resolve({});
|
|
179
181
|
},
|
|
@@ -184,7 +186,7 @@ const WebsearchCitedPlugin: Plugin = () => {
|
|
|
184
186
|
},
|
|
185
187
|
],
|
|
186
188
|
},
|
|
187
|
-
config: (config) => {
|
|
189
|
+
config: (config: Config) => {
|
|
188
190
|
const { selected, error } = findFirstWebsearchCitedConfig(config as any);
|
|
189
191
|
|
|
190
192
|
selectedProvider = undefined;
|
|
@@ -199,6 +201,9 @@ const WebsearchCitedPlugin: Plugin = () => {
|
|
|
199
201
|
const openaiProvider = config.provider?.openai;
|
|
200
202
|
openaiConfig = parseOpenAIOptions(openaiProvider, selectedModel);
|
|
201
203
|
}
|
|
204
|
+
} else if (!error && fallback) {
|
|
205
|
+
selectedProvider = fallback.providerID;
|
|
206
|
+
selectedModel = fallback.model;
|
|
202
207
|
}
|
|
203
208
|
|
|
204
209
|
return Promise.resolve();
|
package/src/lsp/index.ts
CHANGED
|
@@ -4,6 +4,7 @@ export function buildLspConfig(lsp: Record<string, LspServerConfig>): Record<str
|
|
|
4
4
|
const result: Record<string, unknown> = {};
|
|
5
5
|
|
|
6
6
|
for (const [name, server] of Object.entries(lsp)) {
|
|
7
|
+
if (server.enabled === false) continue;
|
|
7
8
|
result[name] = {
|
|
8
9
|
command: server.command,
|
|
9
10
|
extensions: server.extensions,
|
package/src/mcp/registry.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { join } from "node:path"
|
|
2
|
+
import { existsSync } from "node:fs"
|
|
2
3
|
import type { McpServerConfig } from "../config/types.js"
|
|
3
4
|
|
|
4
5
|
export type HiaiMcpName =
|
|
@@ -22,7 +23,11 @@ export interface HiaiMcpRegistryEntry {
|
|
|
22
23
|
}
|
|
23
24
|
|
|
24
25
|
function resolveAssetScript(...segments: string[]): string {
|
|
25
|
-
|
|
26
|
+
const candidates = [
|
|
27
|
+
join(import.meta.dirname, "..", "assets", ...segments),
|
|
28
|
+
join(import.meta.dirname, "..", "..", "assets", ...segments),
|
|
29
|
+
]
|
|
30
|
+
return candidates.find((candidate) => existsSync(candidate)) ?? candidates[0]
|
|
26
31
|
}
|
|
27
32
|
|
|
28
33
|
function createNpmPackageCommand(pkg: string, ...args: string[]): string[] {
|
|
@@ -5,6 +5,7 @@ import type {
|
|
|
5
5
|
AvailableCategory,
|
|
6
6
|
} from "../agents/dynamic-agent-prompt-builder"
|
|
7
7
|
import type { HiaiOpenCodeConfig } from "../config"
|
|
8
|
+
import type { McpServerConfig } from "../config/types"
|
|
8
9
|
import { isInteractiveBashEnabled } from "../create-runtime-tmux-config"
|
|
9
10
|
import type { PluginContext, ToolsRecord } from "./types"
|
|
10
11
|
|
|
@@ -146,6 +147,7 @@ export function createToolRegistry(args: {
|
|
|
146
147
|
managers: Pick<Managers, "backgroundManager" | "tmuxSessionManager" | "skillMcpManager">
|
|
147
148
|
skillContext: SkillContext
|
|
148
149
|
availableCategories: AvailableCategory[]
|
|
150
|
+
builtinMcp?: Record<string, McpServerConfig>
|
|
149
151
|
interactiveBashEnabled?: boolean
|
|
150
152
|
toolFactories?: Partial<ToolRegistryFactories>
|
|
151
153
|
}): ToolRegistryResult {
|
|
@@ -155,6 +157,7 @@ export function createToolRegistry(args: {
|
|
|
155
157
|
managers,
|
|
156
158
|
skillContext,
|
|
157
159
|
availableCategories,
|
|
160
|
+
builtinMcp,
|
|
158
161
|
interactiveBashEnabled = isInteractiveBashEnabled(),
|
|
159
162
|
toolFactories,
|
|
160
163
|
} = args
|
|
@@ -216,6 +219,7 @@ export function createToolRegistry(args: {
|
|
|
216
219
|
manager: managers.skillMcpManager,
|
|
217
220
|
getLoadedSkills: () => skillContext.mergedSkills,
|
|
218
221
|
getSessionID: getSessionIDForMcp,
|
|
222
|
+
builtinMcp,
|
|
219
223
|
})
|
|
220
224
|
|
|
221
225
|
const commands = factories.discoverCommandsSync(ctx.directory, {
|
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
import { tool, type ToolDefinition } from "@opencode-ai/plugin"
|
|
2
2
|
import type { ToolContext } from "@opencode-ai/plugin/tool"
|
|
3
3
|
import { BUILTIN_MCP_TOOL_HINTS, SKILL_MCP_DESCRIPTION } from "./constants"
|
|
4
|
+
import type { McpServerConfig } from "../../config/types"
|
|
4
5
|
import type { SkillMcpArgs } from "./types"
|
|
5
6
|
import type { SkillMcpManager, SkillMcpClientInfo, SkillMcpServerContext } from "../../features/skill-mcp-manager"
|
|
7
|
+
import type { ClaudeCodeMcpServer } from "../../features/claude-code-mcp-loader/types"
|
|
6
8
|
import type { LoadedSkill } from "../../features/opencode-skill-loader/types"
|
|
7
9
|
|
|
8
10
|
interface SkillMcpToolOptions {
|
|
9
11
|
manager: SkillMcpManager
|
|
10
12
|
getLoadedSkills: () => LoadedSkill[]
|
|
11
13
|
getSessionID?: () => string | undefined
|
|
14
|
+
builtinMcp?: Record<string, McpServerConfig>
|
|
12
15
|
}
|
|
13
16
|
|
|
14
17
|
type OperationType = { type: "tool" | "resource" | "prompt"; name: string }
|
|
@@ -60,6 +63,28 @@ function findMcpServer(
|
|
|
60
63
|
return null
|
|
61
64
|
}
|
|
62
65
|
|
|
66
|
+
function convertBuiltinMcpConfig(config: McpServerConfig): ClaudeCodeMcpServer | null {
|
|
67
|
+
if (config.enabled === false) return null
|
|
68
|
+
|
|
69
|
+
if (config.type === "remote") {
|
|
70
|
+
return {
|
|
71
|
+
type: "http",
|
|
72
|
+
url: config.url,
|
|
73
|
+
headers: config.headers,
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const [command, ...args] = config.command ?? []
|
|
78
|
+
if (!command) return null
|
|
79
|
+
|
|
80
|
+
return {
|
|
81
|
+
type: "stdio",
|
|
82
|
+
command,
|
|
83
|
+
args,
|
|
84
|
+
env: config.environment,
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
63
88
|
function formatAvailableMcps(skills: LoadedSkill[]): string {
|
|
64
89
|
const mcps: string[] = []
|
|
65
90
|
for (const skill of skills) {
|
|
@@ -72,6 +97,14 @@ function formatAvailableMcps(skills: LoadedSkill[]): string {
|
|
|
72
97
|
return mcps.length > 0 ? mcps.join("\n") : " (none found)"
|
|
73
98
|
}
|
|
74
99
|
|
|
100
|
+
function formatAvailableBuiltinMcps(builtinMcp: Record<string, McpServerConfig> | undefined): string {
|
|
101
|
+
const names = Object.entries(builtinMcp ?? {})
|
|
102
|
+
.filter(([, config]) => config.enabled !== false)
|
|
103
|
+
.map(([name]) => ` - "${name}" from hiai-opencode config`)
|
|
104
|
+
|
|
105
|
+
return names.length > 0 ? names.join("\n") : " (none found)"
|
|
106
|
+
}
|
|
107
|
+
|
|
75
108
|
function formatBuiltinMcpHint(mcpName: string): string | null {
|
|
76
109
|
const nativeTools = BUILTIN_MCP_TOOL_HINTS[mcpName]
|
|
77
110
|
if (!nativeTools) return null
|
|
@@ -119,7 +152,7 @@ export function applyGrepFilter(output: string, pattern: string | undefined): st
|
|
|
119
152
|
}
|
|
120
153
|
|
|
121
154
|
export function createSkillMcpTool(options: SkillMcpToolOptions): ToolDefinition {
|
|
122
|
-
const { manager, getLoadedSkills, getSessionID } = options
|
|
155
|
+
const { manager, getLoadedSkills, getSessionID, builtinMcp } = options
|
|
123
156
|
|
|
124
157
|
return tool({
|
|
125
158
|
description: SKILL_MCP_DESCRIPTION,
|
|
@@ -141,8 +174,10 @@ export function createSkillMcpTool(options: SkillMcpToolOptions): ToolDefinition
|
|
|
141
174
|
const operation = validateOperationParams(args)
|
|
142
175
|
const skills = getLoadedSkills()
|
|
143
176
|
const found = findMcpServer(args.mcp_name, skills)
|
|
177
|
+
const builtinConfig = builtinMcp?.[args.mcp_name]
|
|
178
|
+
const convertedBuiltinConfig = builtinConfig ? convertBuiltinMcpConfig(builtinConfig) : null
|
|
144
179
|
|
|
145
|
-
if (!found) {
|
|
180
|
+
if (!found && !convertedBuiltinConfig) {
|
|
146
181
|
const builtinHint = formatBuiltinMcpHint(args.mcp_name)
|
|
147
182
|
if (builtinHint) {
|
|
148
183
|
throw new Error(builtinHint)
|
|
@@ -153,7 +188,10 @@ export function createSkillMcpTool(options: SkillMcpToolOptions): ToolDefinition
|
|
|
153
188
|
`Available MCP servers in loaded skills:\n` +
|
|
154
189
|
formatAvailableMcps(skills) +
|
|
155
190
|
`\n\n` +
|
|
156
|
-
`
|
|
191
|
+
`Available MCP servers in hiai-opencode config:\n` +
|
|
192
|
+
formatAvailableBuiltinMcps(builtinMcp) +
|
|
193
|
+
`\n\n` +
|
|
194
|
+
`Hint: Load the skill first for skill-embedded MCPs. Builtin hiai-opencode MCPs can be called directly when enabled in hiai-opencode.json.`,
|
|
157
195
|
)
|
|
158
196
|
}
|
|
159
197
|
|
|
@@ -164,14 +202,14 @@ export function createSkillMcpTool(options: SkillMcpToolOptions): ToolDefinition
|
|
|
164
202
|
|
|
165
203
|
const info: SkillMcpClientInfo = {
|
|
166
204
|
serverName: args.mcp_name,
|
|
167
|
-
skillName: found
|
|
205
|
+
skillName: found?.skill.name ?? "hiai-opencode",
|
|
168
206
|
sessionID,
|
|
169
|
-
scope: found
|
|
207
|
+
scope: found?.skill.scope ?? "user",
|
|
170
208
|
}
|
|
171
209
|
|
|
172
210
|
const context: SkillMcpServerContext = {
|
|
173
|
-
config: found
|
|
174
|
-
skillName: found
|
|
211
|
+
config: found?.config ?? convertedBuiltinConfig!,
|
|
212
|
+
skillName: found?.skill.name ?? "hiai-opencode",
|
|
175
213
|
}
|
|
176
214
|
|
|
177
215
|
const parsedArgs = parseArguments(args.arguments)
|