@hiai-gg/hiai-opencode 0.1.3 → 0.1.4

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.
Files changed (51) hide show
  1. package/.env.example +14 -18
  2. package/AGENTS.md +75 -23
  3. package/ARCHITECTURE.md +11 -14
  4. package/LICENSE.md +1 -0
  5. package/README.md +177 -94
  6. package/assets/cli/hiai-opencode.mjs +276 -0
  7. package/assets/mcp/playwright.mjs +7 -0
  8. package/config/hiai-opencode.schema.json +113 -1
  9. package/dist/config/defaults.d.ts +0 -3
  10. package/dist/config/index.d.ts +0 -1
  11. package/dist/config/platform-schema.d.ts +70 -0
  12. package/dist/config/schema/agent-overrides.d.ts +256 -0
  13. package/dist/config/schema/categories.d.ts +2 -2
  14. package/dist/config/schema/commands.d.ts +1 -0
  15. package/dist/config/schema/index.d.ts +2 -0
  16. package/dist/config/schema/oh-my-opencode-config.d.ts +267 -0
  17. package/dist/config/schema/skill-discovery.d.ts +11 -0
  18. package/dist/config/types.d.ts +12 -1
  19. package/dist/features/builtin-commands/templates/mcp-status.d.ts +1 -0
  20. package/dist/features/builtin-commands/types.d.ts +1 -1
  21. package/dist/features/opencode-skill-loader/loader.d.ts +2 -0
  22. package/dist/index.js +692 -541
  23. package/dist/plugin/skill-discovery-config.d.ts +4 -0
  24. package/dist/shared/startup-diagnostics.d.ts +6 -0
  25. package/hiai-opencode.json +191 -35
  26. package/package.json +4 -1
  27. package/src/agents/AGENTS.md +3 -4
  28. package/src/config/defaults.ts +60 -81
  29. package/src/config/index.ts +0 -1
  30. package/src/config/platform-schema.ts +17 -2
  31. package/src/config/schema/agent-overrides.ts +2 -0
  32. package/src/config/schema/commands.ts +1 -0
  33. package/src/config/schema/fast-apply.ts +4 -4
  34. package/src/config/schema/index.ts +2 -0
  35. package/src/config/schema/oh-my-opencode-config.ts +3 -0
  36. package/src/config/schema/skill-discovery.ts +25 -0
  37. package/src/config/types.ts +16 -0
  38. package/src/features/builtin-commands/commands.ts +7 -0
  39. package/src/features/builtin-commands/templates/mcp-status.ts +36 -0
  40. package/src/features/builtin-commands/types.ts +1 -1
  41. package/src/features/builtin-skills/skills/playwright.ts +24 -2
  42. package/src/features/opencode-skill-loader/loader.ts +11 -0
  43. package/src/index.ts +14 -13
  44. package/src/plugin/hooks/create-tool-guard-hooks.ts +1 -1
  45. package/src/plugin/skill-context.ts +31 -13
  46. package/src/plugin/skill-discovery-config.ts +32 -0
  47. package/src/plugin-handlers/agent-config-handler.ts +20 -13
  48. package/src/plugin-handlers/command-config-handler.ts +22 -12
  49. package/src/shared/migration/agent-names.ts +5 -5
  50. package/src/shared/startup-diagnostics.ts +77 -0
  51. package/src/config/models.ts +0 -32
@@ -0,0 +1,4 @@
1
+ import type { HiaiOpenCodeConfig } from "../config";
2
+ import type { SkillDiscoveryConfig } from "../config/schema";
3
+ export type ResolvedSkillDiscoveryConfig = Required<SkillDiscoveryConfig>;
4
+ export declare function resolveSkillDiscoveryConfig(pluginConfig: HiaiOpenCodeConfig): ResolvedSkillDiscoveryConfig;
@@ -0,0 +1,6 @@
1
+ import type { HiaiOpenCodeConfig, HiaiOpencodeConfig } from "../config";
2
+ export declare function warnIfListPluginEntry(directory: string): void;
3
+ export declare function warnMissingRequiredMcpEnv(args: {
4
+ pluginConfig: HiaiOpenCodeConfig;
5
+ platformConfig: HiaiOpencodeConfig;
6
+ }): void;
@@ -1,32 +1,107 @@
1
1
  {
2
- "_description": "hiai-opencode user configuration template. Public display names (shown to users): Bob, Coder, Strategist, Guard, Critic, Designer, Researcher, Manager, Brainstormer, Vision. Config keys (used in this file and in code) are: bob, coder, strategist, guard, critic, designer, researcher, manager, brainstormer, vision. Internal-only keys (hidden from normal users): sub, agent-skills. MCP enable/disable lives in the mcp object below; default MCP definitions live in src/mcp/registry.ts. Source model defaults: src/config/defaults.ts and src/config/models.ts.",
2
+ "_description": "Canonical hiai-opencode runtime config. Copy this file to .opencode/hiai-opencode.json and edit it there. This file is the user-facing source of truth for agent models, category models, MCP switches, LSP defaults, skill discovery, service auth placeholders, and local helper defaults. Model provider credentials are configured in OpenCode Connect; this file stores model IDs only.",
3
3
  "$schema": "./config/hiai-opencode.schema.json",
4
4
  "agents": {
5
- "bob": { "model": "openrouter/anthropic/claude-3.5-opus" },
6
- "coder": { "model": "openrouter/anthropic/claude-3.5-sonnet" },
7
- "strategist": { "model": "openrouter/anthropic/claude-3.5-haiku" },
8
- "guard": { "model": "openrouter/openai/gpt-4o" },
9
- "critic": { "model": "openrouter/qwen/qwen2.5-72b-instruct" },
10
- "designer": { "model": "openrouter/google/gemini-3.1-pro" },
11
- "researcher": { "model": "openrouter/google/gemini-2.0-flash" },
12
- "manager": { "model": "openrouter/google/gemini-2.0-flash" },
13
- "brainstormer": { "model": "openrouter/google/gemini-2.0-flash" },
14
- "vision": { "model": "openrouter/google/gemini-3.1-pro" }
5
+ "bob": {
6
+ "model": "openrouter/anthropic/claude-3.5-opus",
7
+ "description": "Primary orchestrator for end-to-end task execution, delegation, and high-level workflow control."
8
+ },
9
+ "coder": {
10
+ "model": "openrouter/anthropic/claude-3.5-sonnet",
11
+ "description": "High-depth executor for multi-file implementation, substantial refactors, and technical delivery."
12
+ },
13
+ "strategist": {
14
+ "model": "openrouter/z-ai/glm-5.1",
15
+ "description": "Planning and architecture agent for decomposition, sequencing, and decision framing before execution."
16
+ },
17
+ "guard": {
18
+ "model": "openrouter/openai/gpt-4o",
19
+ "description": "Execution supervisor that routes work, enforces discipline, and keeps delegated flows on track."
20
+ },
21
+ "critic": {
22
+ "model": "openrouter/qwen/qwen2.5-72b-instruct",
23
+ "description": "High-accuracy review gate for implementation quality, correctness, and plan validation."
24
+ },
25
+ "designer": {
26
+ "model": "openrouter/google/gemini-3.1-pro",
27
+ "description": "Creative visual problem-solver for high-touch UI, interaction, and brand-level interface direction."
28
+ },
29
+ "researcher": {
30
+ "model": "openrouter/google/gemini-2.0-flash",
31
+ "description": "Codebase exploration and external documentation research."
32
+ },
33
+ "platform-manager": {
34
+ "model": "openrouter/google/gemini-2.0-flash",
35
+ "description": "Manager. Unified platform management agent for session continuity, project initialization, and orchestration."
36
+ },
37
+ "brainstormer": {
38
+ "model": "openrouter/google/gemini-2.0-flash",
39
+ "description": "Idea exploration agent for divergent thinking, option generation, and concept shaping before execution."
40
+ },
41
+ "multimodal": {
42
+ "model": "openrouter/google/gemini-3.1-pro",
43
+ "description": "Vision. Multimodal analysis agent for images, PDFs, diagrams, and other non-text inputs."
44
+ },
45
+ "sub": {
46
+ "model": "openrouter/google/gemini-2.0-flash",
47
+ "description": "Hidden compatibility executor. Primary subtask execution is handled by Coder."
48
+ },
49
+ "quality-guardian": {
50
+ "model": "openrouter/anthropic/claude-3.5-sonnet",
51
+ "description": "Hidden compatibility review agent. Primary review work is handled by Critic."
52
+ },
53
+ "agent-skills": {
54
+ "model": "openrouter/google/gemini-2.0-flash",
55
+ "description": "Hidden system agent for skill registry, discovery, and capability orchestration."
56
+ }
15
57
  },
58
+ "agentRequirements": {},
16
59
  "categories": {
17
- "visual-engineering": { "model": "openrouter/google/gemini-2.0-pro-exp-02-05", "variant": "high" },
18
- "artistry": { "model": "openrouter/google/gemini-2.0-pro-exp-02-05", "variant": "high" },
19
- "ultrabrain": { "model": "openrouter/openai/gpt-4o", "variant": "xhigh" },
20
- "deep": { "model": "openrouter/anthropic/claude-3.5-sonnet", "variant": "medium" },
21
- "quick": { "model": "openrouter/google/gemini-2.0-flash" },
22
- "writing": { "model": "openrouter/openai/gpt-4o-mini" },
23
- "git": { "model": "openrouter/google/gemini-2.0-flash" },
24
- "unspecified-low": { "model": "openrouter/anthropic/claude-3.5-haiku" },
25
- "unspecified-high": { "model": "openrouter/anthropic/claude-3.5-opus", "variant": "max" }
60
+ "visual-engineering": {
61
+ "model": "openrouter/google/gemini-2.0-pro-exp-02-05",
62
+ "variant": "high",
63
+ "description": "Frontend and UI systems work with design-system discipline. Uses Coder deep execution contour."
64
+ },
65
+ "artistry": {
66
+ "model": "openrouter/google/gemini-2.0-pro-exp-02-05",
67
+ "variant": "high",
68
+ "description": "High-effort creative problem solving beyond standard patterns. Uses Coder deep execution contour."
69
+ },
70
+ "ultrabrain": {
71
+ "model": "openrouter/openai/gpt-4o",
72
+ "variant": "xhigh",
73
+ "description": "Hard logic and architecture tasks. Uses Coder deep execution contour."
74
+ },
75
+ "deep": {
76
+ "model": "openrouter/openai/o1",
77
+ "variant": "medium",
78
+ "description": "Deep autonomous implementation with full context buildup. Uses Coder deep execution contour."
79
+ },
80
+ "quick": {
81
+ "model": "openrouter/google/gemini-2.0-flash",
82
+ "description": "Fast bounded execution: single-file fixes, typos, and simple modifications. Uses Coder fast execution contour."
83
+ },
84
+ "writing": {
85
+ "model": "openrouter/kimi/kimi-latest",
86
+ "description": "Documentation and prose tasks with bounded scope. Uses Coder fast execution contour."
87
+ },
88
+ "git": {
89
+ "model": "openrouter/google/gemini-2.0-flash",
90
+ "description": "Git, commit, diff, and repository hygiene tasks."
91
+ },
92
+ "unspecified-low": {
93
+ "model": "openrouter/anthropic/claude-3.5-sonnet",
94
+ "description": "Unclassifiable moderate tasks with bounded scope. Uses Coder fast execution contour."
95
+ },
96
+ "unspecified-high": {
97
+ "model": "openrouter/anthropic/claude-3.5-opus",
98
+ "variant": "max",
99
+ "description": "Unclassifiable substantial tasks across modules. Uses Coder deep execution contour."
100
+ }
26
101
  },
102
+ "categoryRequirements": {},
103
+ "modelFamilies": [],
27
104
  "auth": {
28
- "openrouter": "{env:OPENROUTER_API_KEY}",
29
- "openai": "{env:OPENAI_API_KEY}",
30
105
  "googleSearch": "{env:GOOGLE_SEARCH_API_KEY}",
31
106
  "stitch": "{env:STITCH_AI_API_KEY}",
32
107
  "firecrawl": "{env:FIRECRAWL_API_KEY}",
@@ -34,25 +109,106 @@
34
109
  },
35
110
  "ollama": {
36
111
  "enabled": false,
37
- "model": "qwen3.5:4b",
38
- "baseUrl": "http://localhost:11434",
112
+ "model": "{env:OLLAMA_MODEL:-qwen3.5:4b}",
113
+ "baseUrl": "{env:OLLAMA_BASE_URL:-http://localhost:11434}",
39
114
  "purpose": "helper"
40
115
  },
116
+ "fast_apply": {
117
+ "enabled": false,
118
+ "ollama_url": "{env:OLLAMA_BASE_URL:-http://localhost:11434}",
119
+ "model": "{env:OLLAMA_MODEL:-qwen3.5:4b}",
120
+ "timeout": 30000
121
+ },
41
122
  "mcp": {
42
- "playwright": { "enabled": true },
43
- "stitch": { "enabled": true },
44
- "sequential-thinking": { "enabled": true },
45
- "firecrawl": { "enabled": true },
46
- "rag": { "enabled": true },
47
- "mempalace": { "enabled": true },
48
- "context7": { "enabled": true }
123
+ "playwright": {
124
+ "enabled": true,
125
+ "command": ["node", "{pluginRoot}/assets/mcp/playwright.mjs"],
126
+ "timeout": 600000
127
+ },
128
+ "stitch": {
129
+ "enabled": true,
130
+ "type": "remote",
131
+ "url": "https://stitch.googleapis.com/mcp",
132
+ "headers": { "X-Goog-Api-Key": "{env:STITCH_AI_API_KEY}" },
133
+ "timeout": 600000
134
+ },
135
+ "sequential-thinking": {
136
+ "enabled": true,
137
+ "command": ["node", "{pluginRoot}/assets/runtime/npm-package-runner.mjs", "@modelcontextprotocol/server-sequential-thinking"],
138
+ "timeout": 600000
139
+ },
140
+ "firecrawl": {
141
+ "enabled": true,
142
+ "command": ["node", "{pluginRoot}/assets/runtime/npm-package-runner.mjs", "firecrawl-mcp"],
143
+ "environment": { "FIRECRAWL_API_KEY": "{env:FIRECRAWL_API_KEY}" },
144
+ "timeout": 600000
145
+ },
146
+ "rag": {
147
+ "enabled": true,
148
+ "type": "local",
149
+ "command": ["node", "{pluginRoot}/assets/mcp/rag.mjs"],
150
+ "environment": {
151
+ "OPENCODE_RAG_URL": "{env:OPENCODE_RAG_URL:-http://localhost:9002/tools/search}"
152
+ },
153
+ "timeout": 600000
154
+ },
155
+ "mempalace": {
156
+ "enabled": true,
157
+ "type": "local",
158
+ "command": ["node", "{pluginRoot}/assets/mcp/mempalace.mjs", "--palace", "./.opencode/palace"],
159
+ "timeout": 600000
160
+ },
161
+ "context7": {
162
+ "enabled": true,
163
+ "type": "remote",
164
+ "url": "https://mcp.context7.com/mcp",
165
+ "headers": { "X-API-KEY": "{env:CONTEXT7_API_KEY}" },
166
+ "timeout": 600000
167
+ }
168
+ },
169
+ "skill_discovery": {
170
+ "config_sources": true,
171
+ "project_opencode": true,
172
+ "global_opencode": false,
173
+ "project_claude": false,
174
+ "global_claude": false,
175
+ "project_agents": false,
176
+ "global_agents": false
177
+ },
178
+ "skills": {
179
+ "enabled": true,
180
+ "disabled": []
49
181
  },
50
182
  "lsp": {
51
- "typescript": { "enabled": true },
52
- "python": { "enabled": true },
53
- "svelte": { "enabled": true }
183
+ "typescript": {
184
+ "command": ["typescript-language-server", "--stdio"],
185
+ "extensions": [".ts", ".tsx", ".mts", ".cts"]
186
+ },
187
+ "svelte": {
188
+ "command": ["svelteserver", "--stdio"],
189
+ "extensions": [".svelte"]
190
+ },
191
+ "eslint": {
192
+ "command": ["node", "{pluginRoot}/assets/runtime/npm-package-runner.mjs", "eslint-lsp", "--stdio"],
193
+ "extensions": [".js", ".jsx", ".ts", ".tsx", ".mjs", ".cjs", ".svelte"]
194
+ },
195
+ "bash": {
196
+ "command": ["node", "{pluginRoot}/assets/runtime/npm-package-runner.mjs", "bash-language-server", "start"],
197
+ "extensions": [".sh", ".bash"]
198
+ },
199
+ "pyright": {
200
+ "command": ["pyright-langserver", "--stdio"],
201
+ "extensions": [".py"]
202
+ }
54
203
  },
55
204
  "subtask2": {
56
- "replace_generic": true
205
+ "replace_generic": true,
206
+ "generic_return": null
207
+ },
208
+ "permissions": {
209
+ "read": { "*": "allow", "*.env": "deny", "*.env.*": "deny", "*.env.example": "allow" },
210
+ "edit": { "*": "allow" },
211
+ "bash": { "*": "allow" },
212
+ "deny_paths": ["**/backup/**", "**/secrets.*", "**/.env", "**/.env.*"]
57
213
  }
58
214
  }
package/package.json CHANGED
@@ -1,10 +1,13 @@
1
1
  {
2
2
  "name": "@hiai-gg/hiai-opencode",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "description": "Unified OpenCode plugin — canonical 12-agent model with bundled skills, MCP integrations, LSP, and permissions in one install.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
8
+ "bin": {
9
+ "hiai-opencode": "./assets/cli/hiai-opencode.mjs"
10
+ },
8
11
  "exports": {
9
12
  ".": {
10
13
  "import": "./dist/index.js",
@@ -56,9 +56,8 @@ These files run after the prompt library and can override what was authored. Alw
56
56
 
57
57
  | What to change | Edit |
58
58
  |---|---|
59
- | Preset definitions (`fast`, `mid`, `high`, `vision`) | `src/config/models.ts` |
60
- | Per-agent default model | `src/config/defaults.ts` |
61
- | Per-category default model | `src/config/defaults.ts` |
59
+ | Per-agent default model | `hiai-opencode.json` |
60
+ | Per-category default model | `hiai-opencode.json` |
62
61
  | Config schema defaults | `src/config/types.ts` |
63
62
 
64
63
  ## Prompt Measurement
@@ -72,4 +71,4 @@ Run `bun run prompts:measure` to generate snapshot files in `dist/prompt-snapsho
72
71
  3. Local helper launchers: `assets/mcp/*`
73
72
  4. NPM bootstrapper for local tools: `assets/runtime/npm-package-runner.mjs`
74
73
 
75
- For more detail see `AGENTS.md` (root) and `ARCHITECTURE.md` (root).
74
+ For more detail see `AGENTS.md` (root) and `ARCHITECTURE.md` (root).
@@ -1,89 +1,68 @@
1
1
  /**
2
- * Default config values for hiai-opencode
2
+ * Runtime defaults for hiai-opencode.
3
+ *
4
+ * Model defaults are intentionally not defined in TypeScript.
5
+ * The bundled hiai-opencode.json file is the single source of truth for:
6
+ * - agent models
7
+ * - category models
8
+ * - user-editable runtime defaults
3
9
  */
4
- import type { HiaiOpencodeConfig } from "./types.js";
5
- import { MODEL_PRESETS } from "./models.js";
6
- import { createDefaultMcpConfig } from "../mcp/registry.js";
7
- import { join } from "node:path";
10
+ import { existsSync, readFileSync } from "node:fs"
11
+ import { dirname, join, normalize } from "node:path"
12
+ import type { HiaiOpencodeConfig } from "./types.js"
8
13
 
9
- export const defaultConfig: HiaiOpencodeConfig = {
10
- agents: {
11
- bob: { model: MODEL_PRESETS.high },
12
- guard: { model: MODEL_PRESETS.ultrahigh },
13
- strategist: { model: MODEL_PRESETS.strategist },
14
- critic: { model: MODEL_PRESETS.critic },
15
- coder: { model: MODEL_PRESETS.mid },
16
- designer: {
17
- model: "openrouter/google/gemini-3.1-pro",
18
- description: "Creative visual problem-solver for high-touch UI, interaction, and brand-level interface direction. Best used when the task needs taste, composition, and design judgment rather than plain implementation. (Designer - HiaiOpenCode)",
19
- },
20
- sub: { model: MODEL_PRESETS.fast },
21
- researcher: { model: MODEL_PRESETS.fast },
22
- multimodal: { model: MODEL_PRESETS.vision },
23
- "quality-guardian": { model: MODEL_PRESETS.mid },
24
- "platform-manager": { model: MODEL_PRESETS.fast },
25
- brainstormer: { model: MODEL_PRESETS.fast },
26
- "agent-skills": { model: MODEL_PRESETS.fast },
27
- },
28
- agentRequirements: {},
29
- categories: {
30
- "visual-engineering": { model: MODEL_PRESETS.vision, variant: "high" },
31
- artistry: { model: MODEL_PRESETS.vision, variant: "high" },
32
- ultrabrain: { model: MODEL_PRESETS.ultrahigh, variant: "xhigh" },
33
- deep: { model: MODEL_PRESETS.reasoning, variant: "medium" },
34
- quick: { model: MODEL_PRESETS.fast },
35
- writing: { model: MODEL_PRESETS.writing },
36
- git: { model: MODEL_PRESETS.fast },
37
- "unspecified-low": { model: MODEL_PRESETS.mid },
38
- "unspecified-high": { model: MODEL_PRESETS.high, variant: "max" },
39
- },
40
- categoryRequirements: {},
14
+ function findPluginRoot(): string {
15
+ const candidates = [
16
+ // Source tree: src/config/defaults.ts -> repo root
17
+ join(import.meta.dirname, "..", ".."),
18
+ // Built package: dist/index.js bundle -> package root
19
+ join(import.meta.dirname, ".."),
20
+ // Non-bundled compiled output: dist/config/defaults.js -> package root
21
+ join(import.meta.dirname, "..", ".."),
22
+ dirname(process.argv[1] ?? ""),
23
+ process.cwd(),
24
+ ]
41
25
 
42
- mcp: createDefaultMcpConfig(),
26
+ for (const candidate of candidates) {
27
+ const root = normalize(candidate)
28
+ if (existsSync(join(root, "hiai-opencode.json"))) {
29
+ return root
30
+ }
31
+ }
43
32
 
44
- lsp: {
45
- typescript: {
46
- command: ["typescript-language-server", "--stdio"],
47
- extensions: [".ts", ".tsx", ".mts", ".cts"],
48
- },
49
- svelte: {
50
- command: ["svelteserver", "--stdio"],
51
- extensions: [".svelte"],
52
- },
53
- eslint: {
54
- command: ["node", join(import.meta.dirname, "..", "assets", "runtime", "npm-package-runner.mjs"), "eslint-lsp", "--stdio"],
55
- extensions: [".js", ".jsx", ".ts", ".tsx", ".mjs", ".cjs", ".svelte"],
56
- },
57
- bash: {
58
- command: ["node", join(import.meta.dirname, "..", "assets", "runtime", "npm-package-runner.mjs"), "bash-language-server", "start"],
59
- extensions: [".sh", ".bash"],
60
- },
61
- pyright: {
62
- command: ["pyright-langserver", "--stdio"],
63
- extensions: [".py"],
64
- },
65
- },
33
+ throw new Error(
34
+ "[hiai-opencode] Cannot find bundled hiai-opencode.json. The package is incomplete.",
35
+ )
36
+ }
66
37
 
67
- subtask2: {
68
- replace_generic: true,
69
- generic_return: null,
70
- },
38
+ function expandPluginRootPlaceholders(value: unknown, pluginRoot: string): unknown {
39
+ if (typeof value === "string") {
40
+ return value.replaceAll("{pluginRoot}", pluginRoot)
41
+ }
71
42
 
72
- skills: {
73
- enabled: true,
74
- disabled: [],
75
- },
43
+ if (Array.isArray(value)) {
44
+ return value.map((item) => expandPluginRootPlaceholders(item, pluginRoot))
45
+ }
76
46
 
77
- permissions: {
78
- read: { "*": "allow", "*.env": "deny", "*.env.*": "deny", "*.env.example": "allow" },
79
- edit: { "*": "allow" },
80
- bash: { "*": "allow" },
81
- deny_paths: ["**/backup/**", "**/secrets.*", "**/.env", "**/.env.*"],
82
- },
83
- ollama: {
84
- enabled: false,
85
- model: "{env:OLLAMA_MODEL:-qwen3.5:4b}",
86
- baseUrl: "http://localhost:11434",
87
- purpose: "helper",
88
- },
89
- };
47
+ if (value && typeof value === "object") {
48
+ return Object.fromEntries(
49
+ Object.entries(value).map(([key, entry]) => [
50
+ key,
51
+ expandPluginRootPlaceholders(entry, pluginRoot),
52
+ ]),
53
+ )
54
+ }
55
+
56
+ return value
57
+ }
58
+
59
+ function loadBundledDefaultConfig(): HiaiOpencodeConfig {
60
+ const pluginRoot = findPluginRoot()
61
+ const configPath = join(pluginRoot, "hiai-opencode.json")
62
+ const raw = readFileSync(configPath, "utf-8")
63
+ const parsed = JSON.parse(raw) as HiaiOpencodeConfig
64
+
65
+ return expandPluginRootPlaceholders(parsed, pluginRoot) as HiaiOpencodeConfig
66
+ }
67
+
68
+ export const defaultConfig: HiaiOpencodeConfig = loadBundledDefaultConfig()
@@ -11,7 +11,6 @@
11
11
  export { loadConfig, resolveEnvVars, resolveMcpEnv } from "./loader.js";
12
12
  export { HiaiOpencodeConfigSchema } from "./platform-schema.js";
13
13
  export { defaultConfig } from "./defaults.js";
14
- export { MODEL_PRESETS, MODEL_ROLE_GUIDE, PROVIDER_MODEL_RULES } from "./models.js";
15
14
  export type {
16
15
  HiaiOpencodeConfig,
17
16
  AgentConfig,
@@ -63,6 +63,16 @@ export const SkillsConfigSchema = z.object({
63
63
  disabled: z.array(z.string()).optional(),
64
64
  });
65
65
 
66
+ export const SkillDiscoveryConfigSchema = z.object({
67
+ config_sources: z.boolean().optional(),
68
+ project_opencode: z.boolean().optional(),
69
+ global_opencode: z.boolean().optional(),
70
+ project_claude: z.boolean().optional(),
71
+ global_claude: z.boolean().optional(),
72
+ project_agents: z.boolean().optional(),
73
+ global_agents: z.boolean().optional(),
74
+ });
75
+
66
76
  export const PermissionsConfigSchema = z.object({
67
77
  read: z.record(z.string(), z.string()).optional(),
68
78
  edit: z.record(z.string(), z.string()).optional(),
@@ -96,8 +106,8 @@ export const AuthKeysSchema = z.object({
96
106
 
97
107
  export const OllamaConfigSchema = z.object({
98
108
  enabled: z.boolean().default(false),
99
- model: z.string().default("qwen3.5:4b"),
100
- baseUrl: z.string().default("http://localhost:11434"),
109
+ model: z.string().default(""),
110
+ baseUrl: z.string().default(""),
101
111
  purpose: z.enum(["verification", "helper", "fallback"]).default("helper"),
102
112
  });
103
113
 
@@ -130,6 +140,8 @@ const AgentsConfigSchema = z.object({
130
140
  zoe: AgentConfigSchema.optional(),
131
141
  build: AgentConfigSchema.optional(),
132
142
  "pre-plan": AgentConfigSchema.optional(),
143
+ manager: AgentConfigSchema.optional(),
144
+ vision: AgentConfigSchema.optional(),
133
145
  logician: AgentConfigSchema.optional(),
134
146
  librarian: AgentConfigSchema.optional(),
135
147
  explore: AgentConfigSchema.optional(),
@@ -162,6 +174,8 @@ const AgentRequirementsConfigSchema = z.object({
162
174
  zoe: ModelRequirementSchema.optional(),
163
175
  build: ModelRequirementSchema.optional(),
164
176
  "pre-plan": ModelRequirementSchema.optional(),
177
+ manager: ModelRequirementSchema.optional(),
178
+ vision: ModelRequirementSchema.optional(),
165
179
  logician: ModelRequirementSchema.optional(),
166
180
  librarian: ModelRequirementSchema.optional(),
167
181
  explore: ModelRequirementSchema.optional(),
@@ -185,6 +199,7 @@ export const HiaiOpencodeConfigSchema = z.object({
185
199
  lsp: z.record(z.string(), LspServerConfigSchema).optional(),
186
200
  subtask2: Subtask2ConfigSchema.optional(),
187
201
  skills: SkillsConfigSchema.optional(),
202
+ skill_discovery: SkillDiscoveryConfigSchema.optional(),
188
203
  permissions: PermissionsConfigSchema.optional(),
189
204
  auth: AuthKeysSchema.optional(),
190
205
  ollama: OllamaConfigSchema.optional(),
@@ -79,6 +79,8 @@ export const AgentOverridesSchema = z.object({
79
79
  general: AgentOverrideConfigSchema.optional(),
80
80
  zoe: AgentOverrideConfigSchema.optional(),
81
81
  "pre-plan": AgentOverrideConfigSchema.optional(),
82
+ manager: AgentOverrideConfigSchema.optional(),
83
+ vision: AgentOverrideConfigSchema.optional(),
82
84
  "logician": AgentOverrideConfigSchema.optional(),
83
85
  librarian: AgentOverrideConfigSchema.optional(),
84
86
  explore: AgentOverrideConfigSchema.optional(),
@@ -9,6 +9,7 @@ export const BuiltinCommandNameSchema = z.enum([
9
9
  "start-work",
10
10
  "stop-continuation",
11
11
  "remove-ai-slops",
12
+ "mcp-status",
12
13
  ])
13
14
 
14
15
  export type BuiltinCommandName = z.infer<typeof BuiltinCommandNameSchema>
@@ -3,10 +3,10 @@ import { z } from "zod"
3
3
  export const FastApplyConfigSchema = z.object({
4
4
  /** Enable fast-apply via Ollama (default: false) */
5
5
  enabled: z.boolean().optional().default(false),
6
- /** Ollama API URL (default: http://localhost:11434) */
7
- ollama_url: z.string().optional().default("http://localhost:11434"),
8
- /** Model name for fast-apply (default: qwen3.5:9b) */
9
- model: z.string().optional().default("qwen3.5:9b"),
6
+ /** Ollama API URL. Configure in hiai-opencode.json. */
7
+ ollama_url: z.string().optional().default(""),
8
+ /** Model name for fast-apply. Configure in hiai-opencode.json. */
9
+ model: z.string().optional().default(""),
10
10
  /** Timeout in milliseconds for Ollama request (default: 30000) */
11
11
  timeout: z.number().int().positive().optional().default(30000),
12
12
  })
@@ -44,6 +44,8 @@ export { BobAgentConfigSchema } from "./bob-agent"
44
44
  export type { BobAgentConfig } from "./bob-agent"
45
45
  export { SkillsConfigSchema } from "./skills"
46
46
  export type { SkillsConfig, SkillDefinition } from "./skills"
47
+ export { SkillDiscoveryConfigSchema } from "./skill-discovery"
48
+ export type { SkillDiscoveryConfig } from "./skill-discovery"
47
49
  export { StartWorkConfigSchema } from "./start-work"
48
50
  export type { StartWorkConfig } from "./start-work"
49
51
  export { TmuxConfigSchema, TmuxLayoutSchema, TmuxIsolationSchema } from "./tmux"
@@ -17,6 +17,7 @@ import { ModelCapabilitiesConfigSchema } from "./model-capabilities"
17
17
  import { RalphLoopConfigSchema } from "./ralph-loop"
18
18
  import { RuntimeFallbackConfigSchema } from "./runtime-fallback"
19
19
  import { SkillsConfigSchema } from "./skills"
20
+ import { SkillDiscoveryConfigSchema } from "./skill-discovery"
20
21
  import { BobConfigSchema } from "./bob"
21
22
  import { BobAgentConfigSchema } from "./bob-agent"
22
23
  import { TmuxConfigSchema } from "./tmux"
@@ -30,6 +31,7 @@ const AuthConfigSchema = z.object({
30
31
  openrouter: z.string().optional(),
31
32
  stitch: z.string().optional(),
32
33
  firecrawl: z.string().optional(),
34
+ context7: z.string().optional(),
33
35
  }).optional()
34
36
 
35
37
  export const HiaiOpenCodeConfigSchema = z.object({
@@ -60,6 +62,7 @@ export const HiaiOpenCodeConfigSchema = z.object({
60
62
  experimental: ExperimentalConfigSchema.optional(),
61
63
  auto_update: z.boolean().optional(),
62
64
  skills: SkillsConfigSchema.optional(),
65
+ skill_discovery: SkillDiscoveryConfigSchema.optional(),
63
66
  ralph_loop: RalphLoopConfigSchema.optional(),
64
67
  /**
65
68
  * Enable runtime fallback (default: false)
@@ -0,0 +1,25 @@
1
+ import { z } from "zod"
2
+
3
+ export const SkillDiscoveryConfigSchema = z.object({
4
+ /**
5
+ * Explicit skills.sources entries from hiai-opencode config.
6
+ * Safe by default because the user intentionally configured them.
7
+ */
8
+ config_sources: z.boolean().default(true),
9
+ /**
10
+ * Project-local OpenCode skills: .opencode/skills and .opencode/skill.
11
+ * Kept on by default because they are part of the current project contract.
12
+ */
13
+ project_opencode: z.boolean().default(true),
14
+ /**
15
+ * Global OpenCode skills from the user's OpenCode config directory.
16
+ * Off by default to keep clean installs deterministic.
17
+ */
18
+ global_opencode: z.boolean().default(false),
19
+ project_claude: z.boolean().default(false),
20
+ global_claude: z.boolean().default(false),
21
+ project_agents: z.boolean().default(false),
22
+ global_agents: z.boolean().default(false),
23
+ })
24
+
25
+ export type SkillDiscoveryConfig = z.infer<typeof SkillDiscoveryConfigSchema>