oh-my-opencode-slim 0.2.1 → 0.3.0
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/README.md +256 -33
- package/dist/cli/index.js +92 -57
- package/dist/config/schema.d.ts +31 -0
- package/dist/features/background-manager.d.ts +3 -1
- package/dist/features/index.d.ts +1 -0
- package/dist/features/tmux-session-manager.d.ts +46 -0
- package/dist/hooks/auto-update-checker/cache.d.ts +1 -0
- package/dist/hooks/auto-update-checker/checker.d.ts +12 -0
- package/dist/hooks/auto-update-checker/constants.d.ts +8 -0
- package/dist/hooks/auto-update-checker/index.d.ts +11 -0
- package/dist/hooks/auto-update-checker/types.d.ts +17 -0
- package/dist/hooks/index.d.ts +2 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +925 -92
- package/dist/shared/index.d.ts +1 -0
- package/dist/shared/logger.d.ts +1 -0
- package/dist/tools/background.d.ts +2 -1
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/tmux.d.ts +32 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,13 +4,42 @@
|
|
|
4
4
|
|
|
5
5
|
**A lightweight, powerful agent orchestration plugin for OpenCode**
|
|
6
6
|
|
|
7
|
-
<img src="img/
|
|
7
|
+
<img src="img/team.png" alt="The Pantheon - Agent Team" width="600">
|
|
8
8
|
|
|
9
9
|
*Transform your AI assistant into a manager capable of delegating complex tasks to specialized sub-agents, running searches in the background, and managing multi-step workflows with ease.*
|
|
10
10
|
|
|
11
11
|
</div>
|
|
12
12
|
|
|
13
|
-
> Slimmed-down fork of [oh-my-opencode](https://github.com/code-yeongyu/oh-my-opencode)
|
|
13
|
+
> Slimmed-down fork of [oh-my-opencode](https://github.com/code-yeongyu/oh-my-opencode) - focused on core agent orchestration without the extra bells and whistles.
|
|
14
|
+
|
|
15
|
+
> **[Antigravity](https://antigravity.ai) subscription recommended.** The pantheon is tuned for Antigravity's model routing. Other providers work, but you'll get the best experience with Antigravity.
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## ⚡ Quick Navigation
|
|
20
|
+
|
|
21
|
+
- [🚀 **Installation**](#installation)
|
|
22
|
+
- [For Humans](#for-humans)
|
|
23
|
+
- [For LLM Agents](#for-llm-agents)
|
|
24
|
+
- [🏗️ **Architecture & Flow**](#architecture--flow)
|
|
25
|
+
- [🏛️ **Meet the Pantheon**](#meet-the-pantheon)
|
|
26
|
+
- [The Orchestrator](#the-orchestrator---architect-of-realms)
|
|
27
|
+
- [The Explorer](#the-explorer---pathfinder)
|
|
28
|
+
- [The Oracle](#the-oracle---seer-beyond-the-stack-trace)
|
|
29
|
+
- [The Librarian](#the-librarian---keeper-of-infinite-scrolls)
|
|
30
|
+
- [The Designer](#the-designer---artisan-of-interfaces)
|
|
31
|
+
- [The Scribe](#the-scribe---chronicle-keeper)
|
|
32
|
+
- [The Visionary](#the-visionary---reader-of-pixels)
|
|
33
|
+
- [The Minimalist](#the-minimalist---destroyer-of-bloat)
|
|
34
|
+
- [🛠️ **Tools & Capabilities**](#tools--capabilities)
|
|
35
|
+
- [Tmux Integration](#tmux-integration)
|
|
36
|
+
- [Quota Tool](#quota-tool)
|
|
37
|
+
- [Background Tasks](#background-tasks)
|
|
38
|
+
- [LSP Tools](#lsp-tools)
|
|
39
|
+
- [Code Search Tools](#code-search-tools)
|
|
40
|
+
- [🔌 **MCP Servers**](#mcp-servers)
|
|
41
|
+
- [⚙️ **Configuration**](#configuration)
|
|
42
|
+
- [🗑️ **Uninstallation**](#uninstallation)
|
|
14
43
|
|
|
15
44
|
---
|
|
16
45
|
|
|
@@ -98,23 +127,16 @@ The installer automatically:
|
|
|
98
127
|
|
|
99
128
|
#### Step 4: Authentication
|
|
100
129
|
|
|
101
|
-
After installation, guide the user:
|
|
130
|
+
After installation, guide the user to log in for each enabled provider:
|
|
102
131
|
|
|
103
|
-
**For Antigravity:**
|
|
104
132
|
```bash
|
|
105
133
|
opencode auth login
|
|
106
|
-
# Select: Google → OAuth with Google (Antigravity)
|
|
107
134
|
```
|
|
108
135
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
**For Cerebras:**
|
|
115
|
-
```bash
|
|
116
|
-
export CEREBRAS_API_KEY="..."
|
|
117
|
-
```
|
|
136
|
+
The user should select:
|
|
137
|
+
- **For Antigravity**: Google → OAuth with Google (Antigravity)
|
|
138
|
+
- **For OpenAI**: OpenAI → Enter API Key
|
|
139
|
+
- **For Cerebras**: Cerebras → Enter API Key
|
|
118
140
|
|
|
119
141
|
---
|
|
120
142
|
|
|
@@ -151,6 +173,8 @@ The plugin follows a "Hub and Spoke" model:
|
|
|
151
173
|
|
|
152
174
|
### The Flow of a Request
|
|
153
175
|
|
|
176
|
+
<img src="img/intro.png" alt="Orchestration Flow" width="800">
|
|
177
|
+
|
|
154
178
|
1. **User Prompt**: "Refactor the auth logic and update the docs."
|
|
155
179
|
2. **Orchestrator**: Creates a TODO list.
|
|
156
180
|
3. **Delegation**:
|
|
@@ -161,25 +185,228 @@ The plugin follows a "Hub and Spoke" model:
|
|
|
161
185
|
|
|
162
186
|
---
|
|
163
187
|
|
|
164
|
-
##
|
|
188
|
+
## Meet the Pantheon
|
|
189
|
+
|
|
190
|
+
<br clear="both">
|
|
191
|
+
|
|
192
|
+
### The Orchestrator - *Architect of Realms*
|
|
193
|
+
|
|
194
|
+
<a href="src/agents/orchestrator.ts"><img src="img/orchestrator.png" alt="The Orchestrator" align="right" width="240"></a>
|
|
195
|
+
|
|
196
|
+
> **The Orchestrator** was born when the first codebase collapsed under its own complexity. Neither god nor mortal would claim responsibility-so The Orchestrator emerged from the void, forging order from chaos. They don't merely command armies; they fight alongside them. Every line of code passes through their hands before they decide which lesser deity deserves a piece of the puzzle.
|
|
197
|
+
|
|
198
|
+
**Role:** Supreme executor, delegator, and overseer - **Model:** `google/claude-opus-4-5-thinking`
|
|
199
|
+
|
|
200
|
+
Write and execute code, orchestrate multi-agent workflows, parse the unspoken from the spoken, summon specialists mid-battle. Shape reality directly-and assign realms to others when the universe grows too vast.
|
|
201
|
+
|
|
202
|
+
<br clear="both">
|
|
203
|
+
|
|
204
|
+
---
|
|
205
|
+
|
|
206
|
+
### The Explorer - *Pathfinder*
|
|
207
|
+
|
|
208
|
+
<a href="src/agents/explore.ts"><img src="img/explorer.png" alt="The Explorer" align="right" width="240"></a>
|
|
209
|
+
|
|
210
|
+
> **The Explorer** moves through codebases like wind through trees-swift, silent, everywhere at once. When The Orchestrator whispers "find me the auth module," The Explorer has already returned with forty file paths and a map. They were born from the first `grep` command, evolved beyond it, and now see patterns mortals miss.
|
|
165
211
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
212
|
+
**Role:** Codebase reconnaissance - **Model:** `cerebras/zai-glm-4.6`
|
|
213
|
+
|
|
214
|
+
Regex search, AST pattern matching, file discovery, parallel exploration. Read-only: they chart the territory; others conquer it.
|
|
215
|
+
|
|
216
|
+
<br clear="both">
|
|
217
|
+
|
|
218
|
+
---
|
|
219
|
+
|
|
220
|
+
### The Oracle - *Seer Beyond the Stack Trace*
|
|
221
|
+
|
|
222
|
+
<a href="src/agents/oracle.ts"><img src="img/oracle.png" alt="The Oracle" align="right" width="240"></a>
|
|
223
|
+
|
|
224
|
+
> **The Oracle** does not code-they *know*. When bugs defy logic and architectures crumble, The Oracle gazes into the abyss of your codebase and speaks truth. They've seen a thousand systems rise and fall. They'll tell you which path leads to ruin, and which to production.
|
|
225
|
+
|
|
226
|
+
**Role:** Strategic advisor and debugger of last resort - **Model:** `openai/gpt-5.2-codex`
|
|
227
|
+
|
|
228
|
+
Root cause analysis, architecture review, debugging guidance, tradeoff analysis. Read-only: Oracles advise; they don't intervene.
|
|
229
|
+
|
|
230
|
+
<br clear="both">
|
|
231
|
+
|
|
232
|
+
---
|
|
233
|
+
|
|
234
|
+
### The Librarian - *Keeper of Infinite Scrolls*
|
|
235
|
+
|
|
236
|
+
<a href="src/agents/librarian.ts"><img src="img/librarian.png" alt="The Librarian" align="right" width="240"></a>
|
|
237
|
+
|
|
238
|
+
> **The Librarian** guards a library with no walls-every GitHub repo, every npm package, every StackOverflow answer ever written. Ask them "how does React handle concurrent rendering?" and they'll return with official docs, real-world examples, and a warning about the footgun you're about to step on.
|
|
239
|
+
|
|
240
|
+
**Role:** External knowledge retrieval - **Model:** `google/gemini-3-flash`
|
|
241
|
+
|
|
242
|
+
Documentation lookup, GitHub code search, library research, best practice retrieval. Read-only: they fetch wisdom; implementation is for others.
|
|
243
|
+
|
|
244
|
+
<br clear="both">
|
|
245
|
+
|
|
246
|
+
---
|
|
247
|
+
|
|
248
|
+
### The Designer - *Artisan of Interfaces*
|
|
249
|
+
|
|
250
|
+
<a href="src/agents/frontend.ts"><img src="img/designer.png" alt="The Designer" align="right" width="240"></a>
|
|
251
|
+
|
|
252
|
+
> **The Designer** believes code should be beautiful-and so should everything it renders. Born from the frustration of a thousand ugly MVPs, they wield CSS like a brush and components like clay. Hand them a feature request; receive a masterpiece. They don't do "good enough."
|
|
253
|
+
|
|
254
|
+
**Role:** UI/UX implementation and visual excellence - **Model:** `google/gemini-3-flash`
|
|
255
|
+
|
|
256
|
+
Modern responsive design, CSS/Tailwind mastery, micro-animations, component architecture. Visual excellence over code perfection-beauty is the priority.
|
|
257
|
+
|
|
258
|
+
<br clear="both">
|
|
259
|
+
|
|
260
|
+
---
|
|
261
|
+
|
|
262
|
+
### The Scribe - *Chronicle Keeper*
|
|
263
|
+
|
|
264
|
+
<a href="src/agents/document-writer.ts"><img src="img/scribe.png" alt="The Scribe" align="right" width="240"></a>
|
|
265
|
+
|
|
266
|
+
> **The Scribe** was there when the first README was written-and wept, for it was incomplete. They have devoted eternity to the sacred art of documentation: clear, scannable, honest. While others ship features, The Scribe ensures those features are understood. Every code example works. Every explanation enlightens.
|
|
267
|
+
|
|
268
|
+
**Role:** Technical documentation and knowledge capture - **Model:** `google/gemini-3-flash`
|
|
269
|
+
|
|
270
|
+
README crafting, API documentation, architecture docs, inline comments that don't insult your intelligence. Match existing style; focus on "why," not just "what."
|
|
271
|
+
|
|
272
|
+
<br clear="both">
|
|
273
|
+
|
|
274
|
+
---
|
|
275
|
+
|
|
276
|
+
### The Visionary - *Reader of Pixels*
|
|
277
|
+
|
|
278
|
+
<a href="src/agents/multimodal.ts"><img src="img/multimodal.png" alt="The Visionary" align="right" width="240"></a>
|
|
279
|
+
|
|
280
|
+
> **The Visionary** sees what others cannot-literally. Screenshots, wireframes, diagrams, PDFs: all are text to them. When a designer throws a Figma mockup at the team and vanishes, The Visionary translates vision into specification. They read the unreadable and describe the indescribable.
|
|
281
|
+
|
|
282
|
+
**Role:** Image and visual content analysis - **Model:** `google/gemini-3-flash`
|
|
283
|
+
|
|
284
|
+
Extract text from images, interpret diagrams, analyze UI screenshots, summarize visual documents. Report what they observe; inference is for others.
|
|
285
|
+
|
|
286
|
+
<br clear="both">
|
|
287
|
+
|
|
288
|
+
---
|
|
289
|
+
|
|
290
|
+
### The Minimalist - *Destroyer of Bloat*
|
|
291
|
+
|
|
292
|
+
<a href="src/agents/simplicity-reviewer.ts"><img src="img/code-simplicity.png" alt="The Minimalist" align="right" width="240"></a>
|
|
293
|
+
|
|
294
|
+
> **The Minimalist** has one sacred truth: every line of code is a liability. They hunt abstractions that serve no purpose, defensive checks that defend nothing, and "clever" solutions that will haunt you in six months. Where others add, The Minimalist subtracts-ruthlessly, joyfully, necessarily.
|
|
295
|
+
|
|
296
|
+
**Role:** Code simplification and YAGNI enforcement - **Model:** `google/claude-opus-4-5-thinking`
|
|
297
|
+
|
|
298
|
+
Identify unnecessary complexity, challenge premature abstractions, estimate LOC reduction, enforce minimalism. Read-only: they judge; The Orchestrator executes the sentence.
|
|
299
|
+
|
|
300
|
+
<br clear="both">
|
|
176
301
|
|
|
177
302
|
---
|
|
178
303
|
|
|
179
304
|
## Tools & Capabilities
|
|
180
305
|
|
|
306
|
+
### Tmux Integration
|
|
307
|
+
|
|
308
|
+
<img src="img/tmux.png" alt="Tmux Integration" width="800">
|
|
309
|
+
|
|
310
|
+
**Watch your agents work in real-time.** When the Orchestrator launches sub-agents or initiates background tasks, new tmux panes automatically spawn showing each agent's live progress. No more waiting in the dark.
|
|
311
|
+
|
|
312
|
+
#### Why This Matters
|
|
313
|
+
|
|
314
|
+
| Without Tmux Integration | With Tmux Integration |
|
|
315
|
+
|--------------------------|----------------------|
|
|
316
|
+
| Fire off a background task, wait anxiously | See the agent thinking, searching, coding |
|
|
317
|
+
| "Is it stuck or just slow?" | Watch tool calls happen in real-time |
|
|
318
|
+
| Results appear out of nowhere | Follow the journey from question to answer |
|
|
319
|
+
| Debug by guessing | Debug by observation |
|
|
320
|
+
|
|
321
|
+
#### What You Get
|
|
322
|
+
|
|
323
|
+
- **Live Visibility**: Each sub-agent gets its own pane showing real-time output
|
|
324
|
+
- **Auto-Layout**: Tmux automatically arranges panes using your preferred layout
|
|
325
|
+
- **Auto-Cleanup**: Panes close when agents finish, layout rebalances
|
|
326
|
+
- **Zero Overhead**: Works with OpenCode's built-in `task` tool AND our `background_task` tool
|
|
327
|
+
|
|
328
|
+
#### Quick Setup
|
|
329
|
+
|
|
330
|
+
**1. Enable the OpenCode HTTP server** (one-time setup)
|
|
331
|
+
|
|
332
|
+
Add to your `~/.config/opencode/opencode.json`:
|
|
333
|
+
|
|
334
|
+
```json
|
|
335
|
+
{
|
|
336
|
+
"server": {
|
|
337
|
+
"port": 4096
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
**2. Enable tmux integration in the plugin**
|
|
343
|
+
|
|
344
|
+
Add to your `~/.config/opencode/oh-my-opencode-slim.json`:
|
|
345
|
+
|
|
346
|
+
```json
|
|
347
|
+
{
|
|
348
|
+
"tmux": {
|
|
349
|
+
"enabled": true,
|
|
350
|
+
"layout": "main-vertical",
|
|
351
|
+
"main_pane_size": 60
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
**3. Run OpenCode inside tmux**
|
|
357
|
+
|
|
358
|
+
```bash
|
|
359
|
+
tmux
|
|
360
|
+
opencode
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
That's it. When agents spawn, they'll appear in new panes.
|
|
364
|
+
|
|
365
|
+
#### Layout Options
|
|
366
|
+
|
|
367
|
+
| Layout | Description |
|
|
368
|
+
|--------|-------------|
|
|
369
|
+
| `main-vertical` | Your session on the left (60%), agents stacked on the right |
|
|
370
|
+
| `main-horizontal` | Your session on top (60%), agents stacked below |
|
|
371
|
+
| `tiled` | All panes in equal-sized grid |
|
|
372
|
+
| `even-horizontal` | All panes side by side |
|
|
373
|
+
| `even-vertical` | All panes stacked vertically |
|
|
374
|
+
|
|
375
|
+
#### Configuration Reference
|
|
376
|
+
|
|
377
|
+
```json
|
|
378
|
+
{
|
|
379
|
+
"tmux": {
|
|
380
|
+
"enabled": true,
|
|
381
|
+
"layout": "main-vertical",
|
|
382
|
+
"main_pane_size": 60
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
| Option | Type | Default | Description |
|
|
388
|
+
|--------|------|---------|-------------|
|
|
389
|
+
| `enabled` | boolean | `false` | Enable/disable tmux integration |
|
|
390
|
+
| `layout` | string | `"main-vertical"` | Tmux layout preset |
|
|
391
|
+
| `main_pane_size` | number | `60` | Size of main pane as percentage (20-80) |
|
|
392
|
+
|
|
393
|
+
---
|
|
394
|
+
|
|
395
|
+
### Quota Tool
|
|
396
|
+
|
|
397
|
+
For Antigravity users. You can trigger this at any time by asking the agent to **"check my quota"** or **"show status."**
|
|
398
|
+
|
|
399
|
+
<img src="img/quota.png" alt="Antigravity Quota" width="600">
|
|
400
|
+
|
|
401
|
+
| Tool | Description |
|
|
402
|
+
|------|-------------|
|
|
403
|
+
| `antigravity_quota` | Check API quota for all Antigravity accounts (compact view with progress bars) |
|
|
404
|
+
|
|
405
|
+
---
|
|
406
|
+
|
|
181
407
|
### Background Tasks
|
|
182
408
|
|
|
409
|
+
|
|
183
410
|
The plugin provides tools to manage asynchronous work:
|
|
184
411
|
|
|
185
412
|
| Tool | Description |
|
|
@@ -188,6 +415,8 @@ The plugin provides tools to manage asynchronous work:
|
|
|
188
415
|
| `background_output` | Fetch the result of a background task by ID |
|
|
189
416
|
| `background_cancel` | Abort running tasks |
|
|
190
417
|
|
|
418
|
+
---
|
|
419
|
+
|
|
191
420
|
### LSP Tools
|
|
192
421
|
|
|
193
422
|
Language Server Protocol integration for code intelligence:
|
|
@@ -199,6 +428,8 @@ Language Server Protocol integration for code intelligence:
|
|
|
199
428
|
| `lsp_diagnostics` | Get errors/warnings from the language server |
|
|
200
429
|
| `lsp_rename` | Rename a symbol across all files |
|
|
201
430
|
|
|
431
|
+
---
|
|
432
|
+
|
|
202
433
|
### Code Search Tools
|
|
203
434
|
|
|
204
435
|
Fast code search and refactoring:
|
|
@@ -209,14 +440,6 @@ Fast code search and refactoring:
|
|
|
209
440
|
| `ast_grep_search` | AST-aware code pattern matching (25 languages) |
|
|
210
441
|
| `ast_grep_replace` | AST-aware code refactoring with dry-run support |
|
|
211
442
|
|
|
212
|
-
### Quota Tool
|
|
213
|
-
|
|
214
|
-
For Antigravity users:
|
|
215
|
-
|
|
216
|
-
| Tool | Description |
|
|
217
|
-
|------|-------------|
|
|
218
|
-
| `antigravity_quota` | Check API quota for all Antigravity accounts (compact view with progress bars) |
|
|
219
|
-
|
|
220
443
|
---
|
|
221
444
|
|
|
222
445
|
## MCP Servers
|
package/dist/cli/index.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
// @bun
|
|
3
3
|
|
|
4
|
+
// src/cli/install.ts
|
|
5
|
+
import * as readline from "readline";
|
|
6
|
+
|
|
4
7
|
// src/cli/config-manager.ts
|
|
5
8
|
import { existsSync, mkdirSync, readFileSync, writeFileSync, statSync } from "fs";
|
|
6
9
|
import { homedir } from "os";
|
|
@@ -270,6 +273,49 @@ function detectCurrentConfig() {
|
|
|
270
273
|
}
|
|
271
274
|
|
|
272
275
|
// src/cli/install.ts
|
|
276
|
+
var lineReader = null;
|
|
277
|
+
var lineBuffer = [];
|
|
278
|
+
var lineResolvers = [];
|
|
279
|
+
function initLineReader() {
|
|
280
|
+
if (lineReader)
|
|
281
|
+
return;
|
|
282
|
+
lineReader = readline.createInterface({
|
|
283
|
+
input: process.stdin,
|
|
284
|
+
output: process.stdout,
|
|
285
|
+
terminal: process.stdin.isTTY ?? false
|
|
286
|
+
});
|
|
287
|
+
lineReader.on("line", (line) => {
|
|
288
|
+
if (lineResolvers.length > 0) {
|
|
289
|
+
const resolve = lineResolvers.shift();
|
|
290
|
+
resolve(line);
|
|
291
|
+
} else {
|
|
292
|
+
lineBuffer.push(line);
|
|
293
|
+
}
|
|
294
|
+
});
|
|
295
|
+
lineReader.on("close", () => {
|
|
296
|
+
while (lineResolvers.length > 0) {
|
|
297
|
+
const resolve = lineResolvers.shift();
|
|
298
|
+
resolve("");
|
|
299
|
+
}
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
async function readLine() {
|
|
303
|
+
initLineReader();
|
|
304
|
+
if (lineBuffer.length > 0) {
|
|
305
|
+
return lineBuffer.shift();
|
|
306
|
+
}
|
|
307
|
+
return new Promise((resolve) => {
|
|
308
|
+
lineResolvers.push(resolve);
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
function closeLineReader() {
|
|
312
|
+
if (lineReader) {
|
|
313
|
+
lineReader.close();
|
|
314
|
+
lineReader = null;
|
|
315
|
+
lineBuffer = [];
|
|
316
|
+
lineResolvers = [];
|
|
317
|
+
}
|
|
318
|
+
}
|
|
273
319
|
var GREEN = "\x1B[32m";
|
|
274
320
|
var BLUE = "\x1B[34m";
|
|
275
321
|
var YELLOW = "\x1B[33m";
|
|
@@ -308,6 +354,26 @@ function printInfo(message) {
|
|
|
308
354
|
function printWarning(message) {
|
|
309
355
|
console.log(`${SYMBOLS.warn} ${YELLOW}${message}${RESET}`);
|
|
310
356
|
}
|
|
357
|
+
async function checkOpenCodeInstalled() {
|
|
358
|
+
const installed = await isOpenCodeInstalled();
|
|
359
|
+
if (!installed) {
|
|
360
|
+
printError("OpenCode is not installed on this system.");
|
|
361
|
+
printInfo("Install it with:");
|
|
362
|
+
console.log(` ${BLUE}curl -fsSL https://opencode.ai/install | bash${RESET}`);
|
|
363
|
+
return { ok: false };
|
|
364
|
+
}
|
|
365
|
+
const version = await getOpenCodeVersion();
|
|
366
|
+
printSuccess(`OpenCode ${version ?? ""} detected`);
|
|
367
|
+
return { ok: true, version: version ?? undefined };
|
|
368
|
+
}
|
|
369
|
+
function handleStepResult(result, successMsg) {
|
|
370
|
+
if (!result.success) {
|
|
371
|
+
printError(`Failed: ${result.error}`);
|
|
372
|
+
return false;
|
|
373
|
+
}
|
|
374
|
+
printSuccess(`${successMsg} ${SYMBOLS.arrow} ${DIM}${result.configPath}${RESET}`);
|
|
375
|
+
return true;
|
|
376
|
+
}
|
|
311
377
|
function formatConfigSummary(config) {
|
|
312
378
|
const lines = [];
|
|
313
379
|
lines.push(`${BOLD}Configuration Summary${RESET}`);
|
|
@@ -319,22 +385,15 @@ function formatConfigSummary(config) {
|
|
|
319
385
|
`);
|
|
320
386
|
}
|
|
321
387
|
function validateNonTuiArgs(args) {
|
|
322
|
-
const
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
}
|
|
331
|
-
errors.push(`Invalid --openai value: ${args.openai} (expected: yes, no)`);
|
|
332
|
-
}
|
|
333
|
-
if (args.cerebras === undefined) {
|
|
334
|
-
errors.push("--cerebras is required (values: yes, no)");
|
|
335
|
-
} else if (!["yes", "no"].includes(args.cerebras)) {
|
|
336
|
-
errors.push(`Invalid --cerebras value: ${args.cerebras} (expected: yes, no)`);
|
|
337
|
-
}
|
|
388
|
+
const requiredArgs = ["antigravity", "openai", "cerebras"];
|
|
389
|
+
const errors = requiredArgs.flatMap((key) => {
|
|
390
|
+
const value = args[key];
|
|
391
|
+
if (value === undefined)
|
|
392
|
+
return [`--${key} is required (values: yes, no)`];
|
|
393
|
+
if (!["yes", "no"].includes(value))
|
|
394
|
+
return [`Invalid --${key} value: ${value} (expected: yes, no)`];
|
|
395
|
+
return [];
|
|
396
|
+
});
|
|
338
397
|
return { valid: errors.length === 0, errors };
|
|
339
398
|
}
|
|
340
399
|
function argsToConfig(args) {
|
|
@@ -351,15 +410,12 @@ function detectedToInitialValues(detected) {
|
|
|
351
410
|
cerebras: detected.hasCerebras ? "yes" : "no"
|
|
352
411
|
};
|
|
353
412
|
}
|
|
354
|
-
async function askYesNo(
|
|
413
|
+
async function askYesNo(promptText, defaultValue = "no") {
|
|
355
414
|
const defaultHint = defaultValue === "yes" ? "[Y/n]" : "[y/N]";
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
const
|
|
359
|
-
|
|
360
|
-
const answer = value ? new TextDecoder().decode(value).trim().toLowerCase() : "";
|
|
361
|
-
if (answer === "" || answer === `
|
|
362
|
-
`)
|
|
415
|
+
const fullPrompt = `${BLUE}${promptText}${RESET} ${defaultHint}: `;
|
|
416
|
+
process.stdout.write(fullPrompt);
|
|
417
|
+
const answer = (await readLine()).trim().toLowerCase();
|
|
418
|
+
if (answer === "")
|
|
363
419
|
return defaultValue;
|
|
364
420
|
if (answer === "y" || answer === "yes")
|
|
365
421
|
return "yes";
|
|
@@ -378,57 +434,41 @@ async function runTuiMode(detected) {
|
|
|
378
434
|
console.log(`${BOLD}Question 3/3:${RESET}`);
|
|
379
435
|
const cerebras = await askYesNo("Do you have access to Cerebras API?", initial.cerebras);
|
|
380
436
|
console.log();
|
|
437
|
+
closeLineReader();
|
|
381
438
|
return {
|
|
382
439
|
hasAntigravity: antigravity === "yes",
|
|
383
440
|
hasOpenAI: openai === "yes",
|
|
384
441
|
hasCerebras: cerebras === "yes"
|
|
385
442
|
};
|
|
386
443
|
}
|
|
387
|
-
async function runInstall(
|
|
444
|
+
async function runInstall(config) {
|
|
388
445
|
const detected = detectCurrentConfig();
|
|
389
446
|
const isUpdate = detected.isInstalled;
|
|
390
447
|
printHeader(isUpdate);
|
|
391
448
|
const totalSteps = config.hasAntigravity ? 5 : 3;
|
|
392
449
|
let step = 1;
|
|
393
450
|
printStep(step++, totalSteps, "Checking OpenCode installation...");
|
|
394
|
-
const
|
|
395
|
-
if (!
|
|
396
|
-
printError("OpenCode is not installed on this system.");
|
|
397
|
-
printInfo("Visit https://opencode.ai/docs for installation instructions");
|
|
451
|
+
const { ok } = await checkOpenCodeInstalled();
|
|
452
|
+
if (!ok)
|
|
398
453
|
return 1;
|
|
399
|
-
}
|
|
400
|
-
const version = await getOpenCodeVersion();
|
|
401
|
-
printSuccess(`OpenCode ${version ?? ""} detected`);
|
|
402
454
|
printStep(step++, totalSteps, "Adding oh-my-opencode-slim plugin...");
|
|
403
455
|
const pluginResult = await addPluginToOpenCodeConfig();
|
|
404
|
-
if (!pluginResult
|
|
405
|
-
printError(`Failed: ${pluginResult.error}`);
|
|
456
|
+
if (!handleStepResult(pluginResult, "Plugin added"))
|
|
406
457
|
return 1;
|
|
407
|
-
}
|
|
408
|
-
printSuccess(`Plugin added ${SYMBOLS.arrow} ${DIM}${pluginResult.configPath}${RESET}`);
|
|
409
458
|
if (config.hasAntigravity) {
|
|
410
459
|
printStep(step++, totalSteps, "Adding auth plugins...");
|
|
411
460
|
const authResult = await addAuthPlugins(config);
|
|
412
|
-
if (!authResult
|
|
413
|
-
printError(`Failed: ${authResult.error}`);
|
|
461
|
+
if (!handleStepResult(authResult, "Auth plugins configured"))
|
|
414
462
|
return 1;
|
|
415
|
-
}
|
|
416
|
-
printSuccess(`Auth plugins configured ${SYMBOLS.arrow} ${DIM}${authResult.configPath}${RESET}`);
|
|
417
463
|
printStep(step++, totalSteps, "Adding provider configurations...");
|
|
418
464
|
const providerResult = addProviderConfig(config);
|
|
419
|
-
if (!providerResult
|
|
420
|
-
printError(`Failed: ${providerResult.error}`);
|
|
465
|
+
if (!handleStepResult(providerResult, "Providers configured"))
|
|
421
466
|
return 1;
|
|
422
|
-
}
|
|
423
|
-
printSuccess(`Providers configured ${SYMBOLS.arrow} ${DIM}${providerResult.configPath}${RESET}`);
|
|
424
467
|
}
|
|
425
468
|
printStep(step++, totalSteps, "Writing oh-my-opencode-slim configuration...");
|
|
426
469
|
const liteResult = writeLiteConfig(config);
|
|
427
|
-
if (!liteResult
|
|
428
|
-
printError(`Failed: ${liteResult.error}`);
|
|
470
|
+
if (!handleStepResult(liteResult, "Config written"))
|
|
429
471
|
return 1;
|
|
430
|
-
}
|
|
431
|
-
printSuccess(`Config written ${SYMBOLS.arrow} ${DIM}${liteResult.configPath}${RESET}`);
|
|
432
472
|
console.log();
|
|
433
473
|
console.log(formatConfigSummary(config));
|
|
434
474
|
console.log();
|
|
@@ -463,24 +503,19 @@ async function install(args) {
|
|
|
463
503
|
return 1;
|
|
464
504
|
}
|
|
465
505
|
const config2 = argsToConfig(args);
|
|
466
|
-
return runInstall(
|
|
506
|
+
return runInstall(config2);
|
|
467
507
|
}
|
|
468
508
|
const detected = detectCurrentConfig();
|
|
469
509
|
printHeader(detected.isInstalled);
|
|
470
510
|
printStep(1, 1, "Checking OpenCode installation...");
|
|
471
|
-
const
|
|
472
|
-
if (!
|
|
473
|
-
printError("OpenCode is not installed on this system.");
|
|
474
|
-
printInfo("Visit https://opencode.ai/docs for installation instructions");
|
|
511
|
+
const { ok } = await checkOpenCodeInstalled();
|
|
512
|
+
if (!ok)
|
|
475
513
|
return 1;
|
|
476
|
-
}
|
|
477
|
-
const version = await getOpenCodeVersion();
|
|
478
|
-
printSuccess(`OpenCode ${version ?? ""} detected`);
|
|
479
514
|
console.log();
|
|
480
515
|
const config = await runTuiMode(detected);
|
|
481
516
|
if (!config)
|
|
482
517
|
return 1;
|
|
483
|
-
return runInstall(
|
|
518
|
+
return runInstall(config);
|
|
484
519
|
}
|
|
485
520
|
|
|
486
521
|
// src/cli/index.ts
|
package/dist/config/schema.d.ts
CHANGED
|
@@ -6,6 +6,26 @@ export declare const AgentOverrideConfigSchema: z.ZodObject<{
|
|
|
6
6
|
prompt_append: z.ZodOptional<z.ZodString>;
|
|
7
7
|
disable: z.ZodOptional<z.ZodBoolean>;
|
|
8
8
|
}, z.core.$strip>;
|
|
9
|
+
export declare const TmuxLayoutSchema: z.ZodEnum<{
|
|
10
|
+
"main-horizontal": "main-horizontal";
|
|
11
|
+
"main-vertical": "main-vertical";
|
|
12
|
+
tiled: "tiled";
|
|
13
|
+
"even-horizontal": "even-horizontal";
|
|
14
|
+
"even-vertical": "even-vertical";
|
|
15
|
+
}>;
|
|
16
|
+
export type TmuxLayout = z.infer<typeof TmuxLayoutSchema>;
|
|
17
|
+
export declare const TmuxConfigSchema: z.ZodObject<{
|
|
18
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
19
|
+
layout: z.ZodDefault<z.ZodEnum<{
|
|
20
|
+
"main-horizontal": "main-horizontal";
|
|
21
|
+
"main-vertical": "main-vertical";
|
|
22
|
+
tiled: "tiled";
|
|
23
|
+
"even-horizontal": "even-horizontal";
|
|
24
|
+
"even-vertical": "even-vertical";
|
|
25
|
+
}>>;
|
|
26
|
+
main_pane_size: z.ZodDefault<z.ZodNumber>;
|
|
27
|
+
}, z.core.$strip>;
|
|
28
|
+
export type TmuxConfig = z.infer<typeof TmuxConfigSchema>;
|
|
9
29
|
export type AgentOverrideConfig = z.infer<typeof AgentOverrideConfigSchema>;
|
|
10
30
|
export declare const McpNameSchema: z.ZodEnum<{
|
|
11
31
|
websearch: "websearch";
|
|
@@ -23,6 +43,17 @@ export declare const PluginConfigSchema: z.ZodObject<{
|
|
|
23
43
|
}, z.core.$strip>>>;
|
|
24
44
|
disabled_agents: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
25
45
|
disabled_mcps: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
46
|
+
tmux: z.ZodOptional<z.ZodObject<{
|
|
47
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
48
|
+
layout: z.ZodDefault<z.ZodEnum<{
|
|
49
|
+
"main-horizontal": "main-horizontal";
|
|
50
|
+
"main-vertical": "main-vertical";
|
|
51
|
+
tiled: "tiled";
|
|
52
|
+
"even-horizontal": "even-horizontal";
|
|
53
|
+
"even-vertical": "even-vertical";
|
|
54
|
+
}>>;
|
|
55
|
+
main_pane_size: z.ZodDefault<z.ZodNumber>;
|
|
56
|
+
}, z.core.$strip>>;
|
|
26
57
|
}, z.core.$strip>;
|
|
27
58
|
export type PluginConfig = z.infer<typeof PluginConfigSchema>;
|
|
28
59
|
export type AgentName = "orchestrator" | "oracle" | "librarian" | "explore" | "frontend-ui-ux-engineer" | "document-writer" | "multimodal-looker" | "code-simplicity-reviewer";
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { PluginInput } from "@opencode-ai/plugin";
|
|
2
|
+
import type { TmuxConfig } from "../config/schema";
|
|
2
3
|
export interface BackgroundTask {
|
|
3
4
|
id: string;
|
|
4
5
|
sessionId: string;
|
|
@@ -22,7 +23,8 @@ export declare class BackgroundTaskManager {
|
|
|
22
23
|
private client;
|
|
23
24
|
private directory;
|
|
24
25
|
private pollInterval?;
|
|
25
|
-
|
|
26
|
+
private tmuxEnabled;
|
|
27
|
+
constructor(ctx: PluginInput, tmuxConfig?: TmuxConfig);
|
|
26
28
|
launch(opts: LaunchOptions): Promise<BackgroundTask>;
|
|
27
29
|
getResult(taskId: string, block?: boolean, timeout?: number): Promise<BackgroundTask | null>;
|
|
28
30
|
cancel(taskId?: string): number;
|
package/dist/features/index.d.ts
CHANGED