@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.
- package/.env.example +14 -18
- package/AGENTS.md +75 -23
- package/ARCHITECTURE.md +11 -14
- package/LICENSE.md +1 -0
- package/README.md +177 -94
- package/assets/cli/hiai-opencode.mjs +276 -0
- package/assets/mcp/playwright.mjs +7 -0
- package/config/hiai-opencode.schema.json +113 -1
- package/dist/config/defaults.d.ts +0 -3
- package/dist/config/index.d.ts +0 -1
- package/dist/config/platform-schema.d.ts +70 -0
- package/dist/config/schema/agent-overrides.d.ts +256 -0
- package/dist/config/schema/categories.d.ts +2 -2
- package/dist/config/schema/commands.d.ts +1 -0
- package/dist/config/schema/index.d.ts +2 -0
- package/dist/config/schema/oh-my-opencode-config.d.ts +267 -0
- package/dist/config/schema/skill-discovery.d.ts +11 -0
- package/dist/config/types.d.ts +12 -1
- package/dist/features/builtin-commands/templates/mcp-status.d.ts +1 -0
- package/dist/features/builtin-commands/types.d.ts +1 -1
- package/dist/features/opencode-skill-loader/loader.d.ts +2 -0
- package/dist/index.js +692 -541
- package/dist/plugin/skill-discovery-config.d.ts +4 -0
- package/dist/shared/startup-diagnostics.d.ts +6 -0
- package/hiai-opencode.json +191 -35
- package/package.json +4 -1
- package/src/agents/AGENTS.md +3 -4
- package/src/config/defaults.ts +60 -81
- package/src/config/index.ts +0 -1
- package/src/config/platform-schema.ts +17 -2
- package/src/config/schema/agent-overrides.ts +2 -0
- package/src/config/schema/commands.ts +1 -0
- package/src/config/schema/fast-apply.ts +4 -4
- package/src/config/schema/index.ts +2 -0
- package/src/config/schema/oh-my-opencode-config.ts +3 -0
- package/src/config/schema/skill-discovery.ts +25 -0
- package/src/config/types.ts +16 -0
- package/src/features/builtin-commands/commands.ts +7 -0
- package/src/features/builtin-commands/templates/mcp-status.ts +36 -0
- package/src/features/builtin-commands/types.ts +1 -1
- package/src/features/builtin-skills/skills/playwright.ts +24 -2
- package/src/features/opencode-skill-loader/loader.ts +11 -0
- package/src/index.ts +14 -13
- package/src/plugin/hooks/create-tool-guard-hooks.ts +1 -1
- package/src/plugin/skill-context.ts +31 -13
- package/src/plugin/skill-discovery-config.ts +32 -0
- package/src/plugin-handlers/agent-config-handler.ts +20 -13
- package/src/plugin-handlers/command-config-handler.ts +22 -12
- package/src/shared/migration/agent-names.ts +5 -5
- package/src/shared/startup-diagnostics.ts +77 -0
- package/src/config/models.ts +0 -32
package/README.md
CHANGED
|
@@ -60,7 +60,7 @@ Minimum:
|
|
|
60
60
|
|
|
61
61
|
Usually required:
|
|
62
62
|
|
|
63
|
-
-
|
|
63
|
+
- at least one model provider connected in OpenCode for the model IDs you configure
|
|
64
64
|
|
|
65
65
|
Optional, depending on which services you want:
|
|
66
66
|
|
|
@@ -73,19 +73,21 @@ Optional, depending on which services you want:
|
|
|
73
73
|
|
|
74
74
|
## Install
|
|
75
75
|
|
|
76
|
-
|
|
76
|
+
### 1. Register the OpenCode plugin
|
|
77
77
|
|
|
78
78
|
```bash
|
|
79
79
|
opencode plugin @hiai-gg/hiai-opencode@latest --global
|
|
80
80
|
```
|
|
81
81
|
|
|
82
|
-
Optional
|
|
82
|
+
Optional Dynamic Context Pruning plugin:
|
|
83
83
|
|
|
84
84
|
```bash
|
|
85
85
|
opencode plugin @tarquinen/opencode-dcp@latest --global
|
|
86
86
|
```
|
|
87
87
|
|
|
88
|
-
|
|
88
|
+
Do not put MCP server packages such as `firecrawl-mcp`, `@playwright/mcp`, or `@modelcontextprotocol/server-sequential-thinking` into the OpenCode `plugin` array. They are MCP servers, not OpenCode plugins. `hiai-opencode` only provides the OpenCode-side launch wiring for them through its `mcp` config and helper launchers.
|
|
89
|
+
|
|
90
|
+
Manual OpenCode config equivalent:
|
|
89
91
|
|
|
90
92
|
```json
|
|
91
93
|
{
|
|
@@ -94,107 +96,87 @@ Manual config alternative:
|
|
|
94
96
|
}
|
|
95
97
|
```
|
|
96
98
|
|
|
97
|
-
|
|
99
|
+
The packaged minimal OpenCode example lives in [config/opencode.json](config/opencode.json).
|
|
98
100
|
|
|
99
|
-
|
|
100
|
-
opencode
|
|
101
|
-
```
|
|
101
|
+
### 2. Create project config
|
|
102
102
|
|
|
103
|
-
|
|
103
|
+
Create a project-level config file at `hiai-opencode.json` in the project root or at `.opencode/hiai-opencode.json`.
|
|
104
104
|
|
|
105
|
-
|
|
106
|
-
npm install @hiai-gg/hiai-opencode
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
For local development:
|
|
105
|
+
Bash:
|
|
110
106
|
|
|
111
107
|
```bash
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
bun install
|
|
115
|
-
bun run build
|
|
108
|
+
mkdir -p .opencode
|
|
109
|
+
cp hiai-opencode.json .opencode/hiai-opencode.json
|
|
116
110
|
```
|
|
117
111
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
Use the OpenCode plugin CLI:
|
|
112
|
+
PowerShell:
|
|
121
113
|
|
|
122
|
-
```
|
|
123
|
-
|
|
114
|
+
```powershell
|
|
115
|
+
New-Item -ItemType Directory -Force .opencode
|
|
116
|
+
Copy-Item .\hiai-opencode.json .\.opencode\hiai-opencode.json
|
|
124
117
|
```
|
|
125
118
|
|
|
126
|
-
If you
|
|
127
|
-
|
|
128
|
-
```bash
|
|
129
|
-
opencode plugin @tarquinen/opencode-dcp@latest --global
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
If you prefer manual config, add the plugin package to your OpenCode config. OpenCode installs npm plugins automatically at startup.
|
|
119
|
+
If you installed only from npm/OpenCode and do not have this repository checked out, create `.opencode/hiai-opencode.json` with the service block below and adjust it later.
|
|
133
120
|
|
|
134
121
|
```json
|
|
135
122
|
{
|
|
136
|
-
"
|
|
137
|
-
|
|
123
|
+
"mcp": {
|
|
124
|
+
"playwright": { "enabled": true },
|
|
125
|
+
"sequential-thinking": { "enabled": true },
|
|
126
|
+
"firecrawl": { "enabled": true },
|
|
127
|
+
"mempalace": { "enabled": true },
|
|
128
|
+
"rag": { "enabled": false },
|
|
129
|
+
"stitch": { "enabled": false },
|
|
130
|
+
"context7": { "enabled": true }
|
|
131
|
+
}
|
|
138
132
|
}
|
|
139
133
|
```
|
|
140
134
|
|
|
141
|
-
|
|
135
|
+
By default, skill discovery is deterministic: `hiai-opencode` skills plus project-local `.opencode/skills` only. Global Claude/OpenCode/Agents skill folders are opt-in.
|
|
142
136
|
|
|
143
|
-
|
|
137
|
+
### 3. Connect models and add service keys
|
|
144
138
|
|
|
145
|
-
|
|
139
|
+
Model provider credentials belong to OpenCode Connect, not to `hiai-opencode`.
|
|
140
|
+
This plugin only writes model IDs such as `openrouter/anthropic/claude-3.5-sonnet` into agent and category config.
|
|
146
141
|
|
|
147
|
-
|
|
142
|
+
Use OpenCode Connect to authorize the providers behind your configured model IDs. Then add only the service keys for MCP or search integrations you actually use:
|
|
148
143
|
|
|
149
144
|
```bash
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
bun run build
|
|
145
|
+
export FIRECRAWL_API_KEY=...
|
|
146
|
+
export STITCH_AI_API_KEY=...
|
|
147
|
+
export CONTEXT7_API_KEY=...
|
|
154
148
|
```
|
|
155
149
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
```bash
|
|
159
|
-
opencode plugin @hiai-gg/hiai-opencode@latest --global
|
|
160
|
-
```
|
|
150
|
+
See [Environment Variables And Keys](#environment-variables-and-keys) for the full list.
|
|
161
151
|
|
|
162
|
-
|
|
152
|
+
### 4. Start and verify
|
|
163
153
|
|
|
164
154
|
```bash
|
|
165
|
-
opencode
|
|
155
|
+
opencode
|
|
156
|
+
hiai-opencode mcp-status
|
|
157
|
+
opencode debug config
|
|
158
|
+
opencode mcp list --print-logs --log-level INFO
|
|
166
159
|
```
|
|
167
160
|
|
|
168
|
-
|
|
161
|
+
`opencode mcp list` may not show plugin-provided MCP servers in every OpenCode version. If that happens, use `opencode debug config` and startup logs as the source of truth.
|
|
169
162
|
|
|
170
|
-
|
|
171
|
-
{
|
|
172
|
-
"$schema": "https://opencode.ai/config.json",
|
|
173
|
-
"plugin": ["@hiai-gg/hiai-opencode"]
|
|
174
|
-
}
|
|
175
|
-
```
|
|
163
|
+
`hiai-opencode mcp-status` is the fastest visibility check. It does not change OpenCode config; it reports config location, enabled MCP services, missing keys, and basic local runtime availability.
|
|
176
164
|
|
|
177
|
-
|
|
165
|
+
## Development Install
|
|
178
166
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
"sequential-thinking": { "enabled": true },
|
|
184
|
-
"firecrawl": { "enabled": true },
|
|
185
|
-
"mempalace": { "enabled": true },
|
|
186
|
-
"rag": { "enabled": false },
|
|
187
|
-
"stitch": { "enabled": false },
|
|
188
|
-
"context7": { "enabled": true }
|
|
189
|
-
}
|
|
190
|
-
}
|
|
167
|
+
Direct npm install is only needed for development or inspection:
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
npm install @hiai-gg/hiai-opencode
|
|
191
171
|
```
|
|
192
172
|
|
|
193
|
-
|
|
173
|
+
Local development:
|
|
194
174
|
|
|
195
175
|
```bash
|
|
196
|
-
|
|
197
|
-
|
|
176
|
+
git clone https://github.com/HiAi-gg/hiai-opencode.git
|
|
177
|
+
cd hiai-opencode
|
|
178
|
+
bun install
|
|
179
|
+
bun run build
|
|
198
180
|
```
|
|
199
181
|
|
|
200
182
|
## Post-Install Bootstrap Prompt
|
|
@@ -210,6 +192,8 @@ Check that @hiai-gg/hiai-opencode is registered. If Dynamic Context Pruning is r
|
|
|
210
192
|
|
|
211
193
|
Find or create hiai-opencode.json in the project root or .opencode/. Use its mcp object as the single switchboard for enabling or disabling MCP services.
|
|
212
194
|
|
|
195
|
+
Keep skill discovery deterministic unless I explicitly ask for external skills. Leave global_opencode, project_claude, global_claude, project_agents, and global_agents disabled by default.
|
|
196
|
+
|
|
213
197
|
Enable only services that can run on this machine:
|
|
214
198
|
- playwright: requires node/npx; optionally set HIAI_PLAYWRIGHT_INSTALL_BROWSERS=1 before first run if browser binaries are needed.
|
|
215
199
|
- sequential-thinking: requires node/npx.
|
|
@@ -232,21 +216,17 @@ If a dependency is missing, install only user-level or project-local dependencie
|
|
|
232
216
|
|
|
233
217
|
### Models
|
|
234
218
|
|
|
235
|
-
|
|
219
|
+
Canonical runtime defaults for agents, categories, MCP, LSP, and model IDs:
|
|
236
220
|
|
|
237
|
-
- [
|
|
221
|
+
- [hiai-opencode.json](hiai-opencode.json)
|
|
238
222
|
|
|
239
|
-
Runtime
|
|
223
|
+
Runtime loader for the bundled canonical config:
|
|
240
224
|
|
|
241
225
|
- [src/config/defaults.ts](src/config/defaults.ts)
|
|
242
226
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
- [hiai-opencode.json](hiai-opencode.json)
|
|
246
|
-
|
|
247
|
-
If you want to change which model a specific agent uses by default, edit `src/config/defaults.ts`.
|
|
227
|
+
If you want to change which model a specific agent or category uses by default, edit `hiai-opencode.json`.
|
|
248
228
|
|
|
249
|
-
|
|
229
|
+
Use fully qualified model IDs. Do not introduce local aliases like `hiai-fast`, `sonnet`, `fast`, or `high`.
|
|
250
230
|
|
|
251
231
|
### Prompting
|
|
252
232
|
|
|
@@ -281,6 +261,24 @@ Skill materialization logic:
|
|
|
281
261
|
|
|
282
262
|
- [src/features/builtin-skills/materialize.ts](src/features/builtin-skills/materialize.ts)
|
|
283
263
|
|
|
264
|
+
Skill discovery defaults:
|
|
265
|
+
|
|
266
|
+
```json
|
|
267
|
+
{
|
|
268
|
+
"skill_discovery": {
|
|
269
|
+
"config_sources": true,
|
|
270
|
+
"project_opencode": true,
|
|
271
|
+
"global_opencode": false,
|
|
272
|
+
"project_claude": false,
|
|
273
|
+
"global_claude": false,
|
|
274
|
+
"project_agents": false,
|
|
275
|
+
"global_agents": false
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
This keeps clean installs reproducible and avoids accidentally mixing Codex, Claude, Antigravity, and global OpenCode skill collections. To opt into external skill folders, enable the specific source you want instead of turning everything on.
|
|
281
|
+
|
|
284
282
|
### MCP
|
|
285
283
|
|
|
286
284
|
Default MCP registry:
|
|
@@ -304,21 +302,23 @@ LSP defaults are defined in:
|
|
|
304
302
|
|
|
305
303
|
## Environment Variables And Keys
|
|
306
304
|
|
|
307
|
-
|
|
305
|
+
Model provider keys are handled by OpenCode Connect. Do not add `OPENROUTER_API_KEY`, `OPENAI_API_KEY`, or `ANTHROPIC_API_KEY` to `hiai-opencode` config for normal model usage.
|
|
306
|
+
|
|
307
|
+
Important service variables:
|
|
308
308
|
|
|
309
|
-
- `OPENROUTER_API_KEY`
|
|
310
|
-
- `OPENAI_API_KEY`
|
|
311
|
-
- `ANTHROPIC_API_KEY`
|
|
312
|
-
- `DEEPSEEK_API_KEY`
|
|
313
|
-
- `GLM_API_KEY`
|
|
314
|
-
- `MINIMAX_API_KEY`
|
|
315
|
-
- `QWEN_API_KEY`
|
|
316
309
|
- `STITCH_AI_API_KEY`
|
|
317
310
|
- `FIRECRAWL_API_KEY`
|
|
318
311
|
- `CONTEXT7_API_KEY`
|
|
312
|
+
- `GOOGLE_SEARCH_API_KEY`
|
|
319
313
|
- `OLLAMA_BASE_URL`
|
|
320
314
|
- `OLLAMA_MODEL`
|
|
321
315
|
- `MEMPALACE_PYTHON`
|
|
316
|
+
- `MEMPALACE_PALACE_PATH`
|
|
317
|
+
- `OPENCODE_RAG_URL`
|
|
318
|
+
- `HIAI_PLAYWRIGHT_INSTALL_BROWSERS`
|
|
319
|
+
- `HIAI_MCP_AUTO_INSTALL`
|
|
320
|
+
|
|
321
|
+
Optional headless or non-Connect fallback variables are documented in [.env.example](.env.example), but they are not required for normal OpenCode model auth.
|
|
322
322
|
|
|
323
323
|
Use [.env.example](.env.example) as the reference template. Create a local `.env` in your OpenCode environment or export these variables in your shell before startup.
|
|
324
324
|
|
|
@@ -350,19 +350,40 @@ The source of truth for default MCP wiring is `src/mcp/registry.ts`. Change that
|
|
|
350
350
|
- `sequential-thinking`: launches `@modelcontextprotocol/server-sequential-thinking` through the helper npm runner.
|
|
351
351
|
- `firecrawl`: launches `firecrawl-mcp` through the helper npm runner and requires `FIRECRAWL_API_KEY`.
|
|
352
352
|
|
|
353
|
-
###
|
|
353
|
+
### Playwright On Minimal Linux Hosts
|
|
354
354
|
|
|
355
|
-
- `
|
|
356
|
-
- `rag`: requires your own running endpoint
|
|
355
|
+
`hiai-opencode mcp-status` can confirm that the Playwright MCP launcher is available, but it cannot guarantee that Chromium can start on a minimal Linux image.
|
|
357
356
|
|
|
358
|
-
|
|
357
|
+
Playwright has two dependency layers:
|
|
359
358
|
|
|
360
|
-
|
|
359
|
+
- Browser binary: install with `HIAI_PLAYWRIGHT_INSTALL_BROWSERS=1` before OpenCode starts, or run `npx playwright install chromium`.
|
|
360
|
+
- System libraries: if Chromium errors with missing packages like `libnspr4`, `libnss3`, `libatk-bridge`, or `libgtk-3`, install them with admin rights, usually `sudo npx playwright install-deps chromium`.
|
|
361
361
|
|
|
362
|
-
|
|
363
|
-
|
|
362
|
+
If sudo is not available:
|
|
363
|
+
|
|
364
|
+
- Use an already installed system browser by editing the Playwright command in `.opencode/hiai-opencode.json`, for example:
|
|
365
|
+
|
|
366
|
+
```json
|
|
367
|
+
{
|
|
368
|
+
"mcp": {
|
|
369
|
+
"playwright": {
|
|
370
|
+
"enabled": true,
|
|
371
|
+
"command": ["node", "{pluginRoot}/assets/mcp/playwright.mjs", "--browser", "chrome"],
|
|
372
|
+
"timeout": 600000
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
}
|
|
364
376
|
```
|
|
365
377
|
|
|
378
|
+
- Try `--browser msedge` if Edge is installed.
|
|
379
|
+
- Use a remote/CDP browser or the `agent-browser`/`playwright-cli` skill path if those tools are installed.
|
|
380
|
+
- Use `curl` only as a degraded HTTP check. It does not replace browser interaction, screenshots, auth flows, or client-side app verification.
|
|
381
|
+
|
|
382
|
+
### Needs upstream runtime or extra setup
|
|
383
|
+
|
|
384
|
+
- `mempalace`: prefers `uv`; otherwise uses Python. If `HIAI_MCP_AUTO_INSTALL` is not `0`, `false`, or `no`, the launcher can run `python -m pip install --user mempalace` on first start.
|
|
385
|
+
- `rag`: requires your own running endpoint
|
|
386
|
+
|
|
366
387
|
### Important Windows note
|
|
367
388
|
|
|
368
389
|
On some Windows/OpenCode environments, local MCP process spawning can fail with `EPERM` for `cmd` or `node`. If you see that:
|
|
@@ -372,6 +393,68 @@ On some Windows/OpenCode environments, local MCP process spawning can fail with
|
|
|
372
393
|
|
|
373
394
|
This most often affects `sequential-thinking` and `mempalace`, and sometimes local `npx`-backed tools.
|
|
374
395
|
|
|
396
|
+
## Diagnostics
|
|
397
|
+
|
|
398
|
+
The plugin now emits startup warnings for common misconfiguration, including:
|
|
399
|
+
|
|
400
|
+
- `.opencode/opencode.json` containing `plugin: ["list"]`
|
|
401
|
+
- enabled MCP integrations with missing required env vars such as `FIRECRAWL_API_KEY` or `STITCH_AI_API_KEY`
|
|
402
|
+
|
|
403
|
+
Available CLI:
|
|
404
|
+
|
|
405
|
+
```bash
|
|
406
|
+
hiai-opencode mcp-status
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
Inside OpenCode, use the slash command:
|
|
410
|
+
|
|
411
|
+
```text
|
|
412
|
+
/mcp-status
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
Example output:
|
|
416
|
+
|
|
417
|
+
```text
|
|
418
|
+
MCP Servers:
|
|
419
|
+
✅ playwright - backend ok
|
|
420
|
+
⚠️ rag - enabled, http://localhost:9002/tools/search not reachable
|
|
421
|
+
✅ firecrawl - backend ok
|
|
422
|
+
❌ mempalace - python not found
|
|
423
|
+
⚠️ stitch - enabled, API key missing (STITCH_AI_API_KEY)
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
Planned follow-up commands:
|
|
427
|
+
|
|
428
|
+
- `hiai-opencode doctor`: report config location, MCP status, missing keys, and local dependency checks.
|
|
429
|
+
- `hiai-opencode export-mcp`: generate a standard `.mcp.json` for hosts that do not expose plugin-provided MCP servers through `opencode mcp list`.
|
|
430
|
+
|
|
431
|
+
Until those commands ship, use:
|
|
432
|
+
|
|
433
|
+
```bash
|
|
434
|
+
opencode debug config
|
|
435
|
+
opencode mcp list --print-logs --log-level INFO
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
## Core Components And Upstream Projects
|
|
439
|
+
|
|
440
|
+
`hiai-opencode` wires these projects and ideas into an OpenCode-friendly setup. Upstream projects remain independent; this table is attribution and orientation, not an ownership claim.
|
|
441
|
+
|
|
442
|
+
| Component | Upstream | Notes |
|
|
443
|
+
|---|---|---|
|
|
444
|
+
| OpenCode host/runtime | [anomalyco/opencode](https://github.com/anomalyco/opencode) | plugin host and runtime target |
|
|
445
|
+
| Core orchestration influences | [code-yeongyu/oh-my-openagent](https://github.com/code-yeongyu/oh-my-openagent) | architectural influence |
|
|
446
|
+
| Planning / workflow influences | [obra/superpowers](https://github.com/obra/superpowers) | planning, review, and debugging ideas |
|
|
447
|
+
| Specialist / platform influences | [vtemian/micode](https://github.com/vtemian/micode) | platform-style specialist behavior |
|
|
448
|
+
| Agent skill ecosystem | [addyosmani/agent-skills](https://github.com/addyosmani/agent-skills) | tactical workflow skill ideas |
|
|
449
|
+
| Optional external plugin | [Opencode-DCP/opencode-dynamic-context-pruning](https://github.com/Opencode-DCP/opencode-dynamic-context-pruning) | installed separately |
|
|
450
|
+
| MemPalace | [MemPalace/mempalace](https://github.com/MemPalace/mempalace) | external MCP/runtime |
|
|
451
|
+
| Playwright MCP | [microsoft/playwright-mcp](https://github.com/microsoft/playwright-mcp) | external MCP |
|
|
452
|
+
| Sequential Thinking | [modelcontextprotocol/servers](https://github.com/modelcontextprotocol/servers) | external MCP |
|
|
453
|
+
| Firecrawl MCP | [firecrawl-ai/firecrawl-mcp-server](https://github.com/firecrawl-ai/firecrawl-mcp-server) | external MCP |
|
|
454
|
+
| Context7 MCP | [upstash/context7-mcp](https://github.com/upstash/context7-mcp) | external MCP |
|
|
455
|
+
| Websearch cited | [ghoulr/opencode-websearch-cited](https://github.com/ghoulr/opencode-websearch-cited) | search integration influence |
|
|
456
|
+
| bun-pty / PTY ecosystem | [shekohex/opencode-pty](https://github.com/shekohex/opencode-pty) | PTY/runtime integration influence |
|
|
457
|
+
|
|
375
458
|
## Build And Publish
|
|
376
459
|
|
|
377
460
|
Build:
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { spawnSync } from "node:child_process"
|
|
4
|
+
import { existsSync, readFileSync } from "node:fs"
|
|
5
|
+
import { dirname, join } from "node:path"
|
|
6
|
+
import { homedir } from "node:os"
|
|
7
|
+
import { parse } from "jsonc-parser"
|
|
8
|
+
|
|
9
|
+
const DEFAULT_RAG_URL = "http://localhost:9002/tools/search"
|
|
10
|
+
|
|
11
|
+
const MCP_REGISTRY = {
|
|
12
|
+
playwright: {
|
|
13
|
+
defaultEnabled: true,
|
|
14
|
+
requiredEnv: [],
|
|
15
|
+
check: checkNodeNpx,
|
|
16
|
+
},
|
|
17
|
+
rag: {
|
|
18
|
+
defaultEnabled: true,
|
|
19
|
+
requiredEnv: [],
|
|
20
|
+
check: checkRag,
|
|
21
|
+
},
|
|
22
|
+
firecrawl: {
|
|
23
|
+
defaultEnabled: true,
|
|
24
|
+
requiredEnv: ["FIRECRAWL_API_KEY"],
|
|
25
|
+
authFallback: "firecrawl",
|
|
26
|
+
check: checkNodeNpx,
|
|
27
|
+
},
|
|
28
|
+
mempalace: {
|
|
29
|
+
defaultEnabled: true,
|
|
30
|
+
requiredEnv: [],
|
|
31
|
+
check: checkMempalace,
|
|
32
|
+
},
|
|
33
|
+
stitch: {
|
|
34
|
+
defaultEnabled: true,
|
|
35
|
+
requiredEnv: ["STITCH_AI_API_KEY"],
|
|
36
|
+
authFallback: "stitch",
|
|
37
|
+
check: checkRemoteKeyOnly,
|
|
38
|
+
},
|
|
39
|
+
context7: {
|
|
40
|
+
defaultEnabled: true,
|
|
41
|
+
requiredEnv: [],
|
|
42
|
+
check: checkRemoteOptionalKey,
|
|
43
|
+
},
|
|
44
|
+
"sequential-thinking": {
|
|
45
|
+
defaultEnabled: true,
|
|
46
|
+
requiredEnv: [],
|
|
47
|
+
check: checkNodeNpx,
|
|
48
|
+
},
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function usage() {
|
|
52
|
+
console.log(`hiai-opencode
|
|
53
|
+
|
|
54
|
+
Usage:
|
|
55
|
+
hiai-opencode mcp-status
|
|
56
|
+
|
|
57
|
+
Commands:
|
|
58
|
+
mcp-status Check hiai-opencode MCP configuration, keys, and local runtimes.
|
|
59
|
+
`)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function resolveEnvTemplate(value) {
|
|
63
|
+
if (typeof value !== "string") return value
|
|
64
|
+
return value.replace(/\{env:([^}]+)\}/g, (_match, expression) => {
|
|
65
|
+
const [name, fallback] = String(expression).split(":-", 2)
|
|
66
|
+
return process.env[name] || fallback || ""
|
|
67
|
+
})
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function candidateConfigPaths() {
|
|
71
|
+
const cwd = process.cwd()
|
|
72
|
+
const paths = [
|
|
73
|
+
join(cwd, "hiai-opencode.json"),
|
|
74
|
+
join(cwd, "hiai-opencode.jsonc"),
|
|
75
|
+
join(cwd, ".opencode", "hiai-opencode.json"),
|
|
76
|
+
join(cwd, ".opencode", "hiai-opencode.jsonc"),
|
|
77
|
+
join(homedir(), ".config", "opencode", "hiai-opencode.json"),
|
|
78
|
+
join(homedir(), ".config", "opencode", "hiai-opencode.jsonc"),
|
|
79
|
+
]
|
|
80
|
+
|
|
81
|
+
if (process.platform === "win32" && process.env.APPDATA) {
|
|
82
|
+
paths.push(join(process.env.APPDATA, "opencode", "hiai-opencode.json"))
|
|
83
|
+
paths.push(join(process.env.APPDATA, "opencode", "hiai-opencode.jsonc"))
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return paths
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function loadConfig() {
|
|
90
|
+
for (const path of candidateConfigPaths()) {
|
|
91
|
+
if (!existsSync(path)) continue
|
|
92
|
+
try {
|
|
93
|
+
return {
|
|
94
|
+
path,
|
|
95
|
+
config: parse(readFileSync(path, "utf-8")) ?? {},
|
|
96
|
+
}
|
|
97
|
+
} catch (error) {
|
|
98
|
+
return {
|
|
99
|
+
path,
|
|
100
|
+
config: {},
|
|
101
|
+
error: error instanceof Error ? error.message : String(error),
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return { path: null, config: {} }
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function hasCommand(command, args = ["--version"]) {
|
|
110
|
+
const result = spawnSync(command, args, {
|
|
111
|
+
stdio: "ignore",
|
|
112
|
+
timeout: 10000,
|
|
113
|
+
shell: process.platform === "win32",
|
|
114
|
+
})
|
|
115
|
+
return result.status === 0
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function hasNode() {
|
|
119
|
+
return hasCommand(process.platform === "win32" ? "node.exe" : "node")
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function hasNpx() {
|
|
123
|
+
return hasCommand(process.platform === "win32" ? "npx.cmd" : "npx")
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function checkNodeNpx() {
|
|
127
|
+
const node = hasNode()
|
|
128
|
+
const npx = hasNpx()
|
|
129
|
+
if (node && npx) return { level: "ok", detail: "backend ok" }
|
|
130
|
+
return {
|
|
131
|
+
level: "error",
|
|
132
|
+
detail: `${node ? "node ok" : "node not found"}, ${npx ? "npx ok" : "npx not found"}`,
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function pythonCandidates() {
|
|
137
|
+
const configured = process.env.MEMPALACE_PYTHON?.trim()
|
|
138
|
+
const candidates = []
|
|
139
|
+
if (configured) candidates.push(configured)
|
|
140
|
+
if (process.platform === "win32") {
|
|
141
|
+
candidates.push("py", "python", "python3")
|
|
142
|
+
} else {
|
|
143
|
+
candidates.push("python3", "python")
|
|
144
|
+
}
|
|
145
|
+
return [...new Set(candidates)]
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function canImportMempalace(command) {
|
|
149
|
+
const args =
|
|
150
|
+
command === "py"
|
|
151
|
+
? ["-3", "-c", "import mempalace.mcp_server"]
|
|
152
|
+
: ["-c", "import mempalace.mcp_server"]
|
|
153
|
+
const result = spawnSync(command, args, {
|
|
154
|
+
stdio: "ignore",
|
|
155
|
+
timeout: 10000,
|
|
156
|
+
shell: process.platform === "win32",
|
|
157
|
+
})
|
|
158
|
+
return result.status === 0
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function checkMempalace() {
|
|
162
|
+
if (hasCommand(process.platform === "win32" ? "uv.exe" : "uv")) {
|
|
163
|
+
return { level: "ok", detail: "uv available" }
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
for (const candidate of pythonCandidates()) {
|
|
167
|
+
if (canImportMempalace(candidate)) {
|
|
168
|
+
return { level: "ok", detail: `${candidate} with mempalace available` }
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
const hasPython = pythonCandidates().some((candidate) =>
|
|
173
|
+
hasCommand(candidate, candidate === "py" ? ["-3", "--version"] : ["--version"]),
|
|
174
|
+
)
|
|
175
|
+
|
|
176
|
+
return {
|
|
177
|
+
level: "error",
|
|
178
|
+
detail: hasPython ? "mempalace Python package not found" : "python not found",
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
async function checkRag(config) {
|
|
183
|
+
const url =
|
|
184
|
+
process.env.OPENCODE_RAG_URL?.trim()
|
|
185
|
+
|| resolveEnvTemplate(config?.mcp?.rag?.environment?.OPENCODE_RAG_URL)
|
|
186
|
+
|| DEFAULT_RAG_URL
|
|
187
|
+
|
|
188
|
+
try {
|
|
189
|
+
const controller = new AbortController()
|
|
190
|
+
const timeout = setTimeout(() => controller.abort(), 2500)
|
|
191
|
+
const response = await fetch(url, { method: "GET", signal: controller.signal })
|
|
192
|
+
clearTimeout(timeout)
|
|
193
|
+
|
|
194
|
+
if (response.status < 500) {
|
|
195
|
+
return { level: "ok", detail: `enabled, ${url} reachable` }
|
|
196
|
+
}
|
|
197
|
+
return { level: "warn", detail: `enabled, ${url} returned ${response.status}` }
|
|
198
|
+
} catch {
|
|
199
|
+
return { level: "warn", detail: `enabled, ${url} not reachable` }
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
function checkRemoteKeyOnly() {
|
|
204
|
+
return { level: "ok", detail: "remote endpoint configured" }
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
function checkRemoteOptionalKey(_config, name) {
|
|
208
|
+
if (name === "context7" && !process.env.CONTEXT7_API_KEY?.trim()) {
|
|
209
|
+
return { level: "ok", detail: "remote endpoint configured, API key optional/missing" }
|
|
210
|
+
}
|
|
211
|
+
return { level: "ok", detail: "remote endpoint configured" }
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
function hasEnvOrAuth(config, envName, authKey) {
|
|
215
|
+
if (process.env[envName]?.trim()) return true
|
|
216
|
+
if (authKey && config?.auth?.[authKey]?.trim()) return true
|
|
217
|
+
return false
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
function statusIcon(level) {
|
|
221
|
+
if (level === "ok") return "✅"
|
|
222
|
+
if (level === "warn") return "⚠️ "
|
|
223
|
+
return "❌"
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
async function mcpStatus() {
|
|
227
|
+
const { path, config, error } = loadConfig()
|
|
228
|
+
console.log("hiai-opencode mcp-status")
|
|
229
|
+
console.log(`Config: ${path ?? "not found; using defaults"}`)
|
|
230
|
+
if (error) console.log(`Config parse warning: ${error}`)
|
|
231
|
+
console.log("")
|
|
232
|
+
console.log("MCP Servers:")
|
|
233
|
+
|
|
234
|
+
for (const [name, entry] of Object.entries(MCP_REGISTRY)) {
|
|
235
|
+
const userEntry = config?.mcp?.[name]
|
|
236
|
+
const enabled = userEntry?.enabled ?? entry.defaultEnabled
|
|
237
|
+
if (!enabled) {
|
|
238
|
+
console.log(`⚪ ${name.padEnd(20)} - disabled`)
|
|
239
|
+
continue
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
const missingEnv = entry.requiredEnv.filter((envName) =>
|
|
243
|
+
!hasEnvOrAuth(config, envName, entry.authFallback),
|
|
244
|
+
)
|
|
245
|
+
|
|
246
|
+
if (missingEnv.length > 0) {
|
|
247
|
+
console.log(`⚠️ ${name.padEnd(20)} - enabled, API key missing (${missingEnv.join(", ")})`)
|
|
248
|
+
continue
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
const result = await entry.check(config, name)
|
|
252
|
+
console.log(`${statusIcon(result.level)} ${name.padEnd(20)} - ${result.detail}`)
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
async function main() {
|
|
257
|
+
const command = process.argv[2]
|
|
258
|
+
if (!command || command === "-h" || command === "--help") {
|
|
259
|
+
usage()
|
|
260
|
+
return
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
if (command === "mcp-status") {
|
|
264
|
+
await mcpStatus()
|
|
265
|
+
return
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
console.error(`Unknown command: ${command}`)
|
|
269
|
+
usage()
|
|
270
|
+
process.exit(1)
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
main().catch((error) => {
|
|
274
|
+
console.error(error instanceof Error ? error.message : String(error))
|
|
275
|
+
process.exit(1)
|
|
276
|
+
})
|
|
@@ -42,6 +42,13 @@ if (shouldInstallBrowsers()) {
|
|
|
42
42
|
const result = runNpx(["-y", "playwright@latest", "install", "chromium"])
|
|
43
43
|
if (result.status !== 0) {
|
|
44
44
|
console.error("[hiai-opencode] playwright browser install failed")
|
|
45
|
+
console.error("[hiai-opencode] Try: npx playwright install chromium")
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (process.platform === "linux") {
|
|
49
|
+
console.error("[hiai-opencode] Playwright Chromium may also need Linux system libraries.")
|
|
50
|
+
console.error("[hiai-opencode] If browser launch fails with libnspr4/libnss3/libgtk errors, run: sudo npx playwright install-deps chromium")
|
|
51
|
+
console.error("[hiai-opencode] Without sudo, use an existing browser by adding args in hiai-opencode.json, e.g. --browser chrome")
|
|
45
52
|
}
|
|
46
53
|
}
|
|
47
54
|
|