@serkanalgur/opencode-nexus 2.7.0 → 2.8.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.
Files changed (4) hide show
  1. package/README.md +63 -28
  2. package/dist/index.js +754 -120
  3. package/dist/tui.js +111 -23
  4. package/package.json +1 -1
package/README.md CHANGED
@@ -4,6 +4,7 @@
4
4
 
5
5
  [![npm version](https://img.shields.io/npm/v/@serkanalgur/opencode-nexus?style=flat-square&color=6366f1)](https://www.npmjs.com/package/@serkanalgur/opencode-nexus)
6
6
  [![npm downloads](https://img.shields.io/npm/dw/@serkanalgur/opencode-nexus?style=flat-square&color=22c55e)](https://www.npmjs.com/package/@serkanalgur/opencode-nexus)
7
+ [![stars](https://img.shields.io/github/stars/serkanalgur/opencode-nexus?style=flat-square&color=f59e0b)](https://github.com/serkanalgur/opencode-nexus/stargazers)
7
8
  [![license](https://img.shields.io/npm/l/@serkanalgur/opencode-nexus?style=flat-square&color=8b5cf6)](https://github.com/serkanalgur/opencode-nexus/blob/main/LICENSE)
8
9
  [![opencode](https://img.shields.io/badge/OpenCode-V2-6366f1?style=flat-square)](https://opencode.ai)
9
10
  [![typescript](https://img.shields.io/badge/TypeScript-5.5+-3178c6?style=flat-square)](https://www.typescriptlang.org/)
@@ -30,7 +31,7 @@ OpenCode Nexus is an agent orchestration plugin for [OpenCode V2](https://openco
30
31
  | **DAG Execution** | Tasks are parallelized based on dependency graphs with priority queuing |
31
32
  | **Cost-Aware Routing** | Scores models by quality/cost/speed, selects optimal per task complexity |
32
33
  | **Self-Healing** | Retries with exponential backoff, context transfer, escalation policies |
33
- | **Web Dashboard** | A live view of sessions, agents, tasks, costs and config, served over HTTP + WebSocket (default port 4747) — started on request, never automatically |
34
+ | **Web Dashboard** | A live view of sessions, agents, tasks, costs and config, served over HTTP + WebSocket (default port 4747) — started on request from `/nexus-dashboard` or the agent, never automatically |
34
35
  | **TUI Dashboard** | Monitor agents, budget, and config from the terminal |
35
36
  | **Team Mode** | Lead agent orchestrates specialist agents in parallel |
36
37
  | **Todo & Goal Tracking** | Enforce task completion, persist objectives across sessions |
@@ -40,7 +41,7 @@ OpenCode Nexus is an agent orchestration plugin for [OpenCode V2](https://openco
40
41
  | **OpenCode LSP opt-in** | On startup, inserts `"lsp": true` into your global `opencode.jsonc` if it isn't already there. That is the whole of it — Nexus does not read LSP state, manage servers, or report anything about them |
41
42
  | **AST-Grep** | Pattern-aware code search and rewriting |
42
43
  | **Security Scanning** | Automated secrets and vulnerability detection |
43
- | **Slash Commands** | `/nexus`, `/nexus-web`, `/nexus-config`, `/nexus-model`, `/nexus-status`, `/nexus-dashboard`, `/nexus-reset` |
44
+ | **Slash Commands** | `/nexus`, `/nexus-dashboard`, `/nexus-web`, `/nexus-overview`, `/nexus-config`, `/nexus-model`, `/nexus-status`, `/nexus-reset` |
44
45
 
45
46
  ---
46
47
 
@@ -106,7 +107,7 @@ Use nexus.goal.set with description="Build complete auth system"
106
107
 
107
108
  ```
108
109
  /nexus # Open full configuration dialog
109
- /nexus web # Open the web dashboard, if one is running
110
+ /nexus dashboard # Start the web dashboard and open it in your browser
110
111
  /nexus status # Show the config summary
111
112
  /nexus model coder # Pick the model for a role
112
113
  /nexus reset # Reset configuration to defaults
@@ -149,35 +150,46 @@ Failed tasks follow a 4-step escalation chain:
149
150
  A live view of the orchestrator, served by an HTTP + WebSocket server on port 4747 (`127.0.0.1`).
150
151
 
151
152
  **Nothing is listening until you ask for it.** The server is not started at
152
- startup, and no command starts it implicitly. There is exactly one call that
153
- does, and it has to come from the agent, because the server runs in the OpenCode
154
- server process next to the orchestrator that feeds it:
153
+ startup, and no command starts it implicitly. The start has to happen in the
154
+ OpenCode *server* process, next to the orchestrator that feeds it, and there are
155
+ two ways to reach it:
155
156
 
156
157
  ```
158
+ /nexus dashboard [port] [host] # from the TUI — starts it and opens it
157
159
  Ask the agent: "start the nexus dashboard"
158
160
  ```
159
161
 
160
- which calls `nexus.dashboard.start(port=4747, host="127.0.0.1")` and prints the
161
- URL. **If the start fails, nothing is listening and no browser is opened** — the
162
- tool says so and names the reason. The two ways it fails are a port already in
162
+ The TUI command submits `/nexus dashboard [port] [host]` to that server process,
163
+ whose prompt hook routes it to the orchestrator; the agent's route calls
164
+ `nexus.dashboard.start(port=4747, host="127.0.0.1")` directly. Both end at the
165
+ same start, and both print the URL it bound. **If the start fails, nothing is
166
+ listening and no browser is opened** — the reason is reported, and no URL is
167
+ offered for a server that is not there. The ways it fails are a port already in
163
168
  use (the bind is refused; pass a different `port`) and `dashboard.enabled: false`
164
- in `nexus.jsonc`, which the tool reports by name.
169
+ in `nexus.jsonc`, which is refused by name.
165
170
 
166
- Once it is running, the TUI command opens it for you:
171
+ Once it is serving, the same command opens it:
167
172
 
168
173
  ```
174
+ /nexus dashboard [port] [host] # /nexus web is an alias of this
169
175
  /nexus web [port] [host]
170
176
  ```
171
177
 
172
- `/nexus web` **cannot start the server** and does not pretend to. It asks
173
- `http://host:port/api/health` whether a nexus dashboard is already serving there,
174
- and then does one of three things:
178
+ The TUI cannot start the server itself — its process has no orchestrator, no
179
+ module registry and no way to invoke a tool — but it can reach the process that
180
+ has all three, and it can ask whether anything is listening. So the command asks
181
+ `http://host:port/api/health` first, and then does one of four things:
175
182
 
176
183
  | What it found | What it does |
177
184
  |---|---|
178
- | A nexus dashboard | Opens your browser at that URL |
185
+ | A nexus dashboard | Opens your browser at that URL. Nothing is started a second time |
179
186
  | A different process on that port | Says so, opens nothing, suggests another port |
180
- | Nothing there | Says so, opens nothing, and gives you the one `nexus.dashboard.start` call to make |
187
+ | Nothing there | Submits `/nexus dashboard [port] [host]` to the server, waits for the port to answer, then opens the browser |
188
+ | Still nothing after ~3s | Says the start did not confirm, opens nothing, and points at the command's own reply for the reason |
189
+
190
+ The browser opens **only** after a confirmed listen. That is the whole point of
191
+ the wait: a browser pointed at a dead address gives a connection-refused page,
192
+ which looks like the dashboard failing rather than the dashboard not running.
181
193
 
182
194
  **How it stays current.** A WebSocket to `/ws/events` carries a throttled
183
195
  `orchestrator:state` push — every state change schedules a full snapshot, at
@@ -191,10 +203,14 @@ shows how old the last snapshot is, and labels it stale past 15 seconds.
191
203
  **What it shows:**
192
204
  - **Sessions** — one row per session nexus owns, is still collecting cost from,
193
205
  or has abandoned, with each one's state (`running` / `idle` / `abandoned` /
194
- `settled`), last read token count, and unbilled spend. Rows with **no owning
195
- agent** are called out in a banner above the table, because a session that is
196
- still generating after its agent was terminated keeps spending and nothing is
197
- collecting that spend — a case that was invisible on every layer before.
206
+ `settled`), age, last read token count, and unbilled spend. Rows with **no
207
+ owning agent** are called out in a banner above the table, because a session
208
+ that is still generating after its agent was terminated keeps spending and
209
+ nothing is collecting that spend — a case that was invisible on every layer
210
+ before. The **Age** column is elapsed time, not a wall clock, and reads `—`
211
+ for those orphan rows: `spawnedAt` comes from the owning agent, so an unowned
212
+ session has no start time to show. The cell says so in its tooltip, and the
213
+ `—` is shown rather than the column dropped, so the gap is visible.
198
214
  This list is nexus's own bookkeeping, not an enumeration of every open session
199
215
  on the server, and the page says so on the section itself.
200
216
  - **Agents** — role, status, model, session id, and metrics
@@ -212,14 +228,28 @@ shows how old the last snapshot is, and labels it stale past 15 seconds.
212
228
  nothing happened. There is no auth story for writes and the socket is a
213
229
  localhost server answering with `CORS: *`, so no write path was added to
214
230
  replace it — edit `nexus.jsonc` instead.
215
- - **Activity log** — every event the broadcaster forwards, each delivered once
231
+ - **Activity log** — every event the broadcaster forwards, each delivered once.
232
+ Two of them carry a fact the line used to leave out:
233
+ - `cost:delta` names **where the price came from** (`settledTier.pricing`) and
234
+ which token tier the amount was priced at. That is deliberately not the same
235
+ as the measured/estimated split elsewhere on the page: `settledTier.pricing`
236
+ is about the *price* — the model's published list, a fallback table because
237
+ this model is not in it, or an unknown-model fallback — while
238
+ measured/estimated is about the *token counts*, which the orchestrator reads
239
+ off a real session. A line whose `settledTier` is missing says so instead of
240
+ implying a price source.
241
+ - `config:reloaded` names the **cause** (`trigger`) alongside the load number,
242
+ the raw ISO load time, and both config files' state, so a reload that
243
+ happened for a reason you did not ask for is visible as one.
216
244
 
217
245
  **Stop the dashboard:**
218
246
  ```
247
+ /nexus dashboard stop
219
248
  Ask the agent to call nexus.dashboard.stop
220
249
  ```
221
250
  This stops the HTTP/WebSocket server only. The orchestrator, its agents and its
222
- sessions keep running.
251
+ sessions keep running. Both routes say so plainly when there was nothing
252
+ running, rather than reporting a stop that did not happen.
223
253
 
224
254
  ### Team Mode
225
255
 
@@ -375,23 +405,28 @@ nexus.clarify(question="Should I use JWT or OAuth?", options="JWT, OAuth", assum
375
405
  The TUI plugin registers exactly these slash commands. With no argument,
376
406
  `/nexus` opens the full configuration dialog; with one, it dispatches to a
377
407
  subcommand (`config`/`c`, `status`/`s`, `dashboard`/`d`, `web`/`w`,
378
- `model`/`m`, `reset`).
408
+ `overview`, `model`/`m`, `reset`).
379
409
 
380
410
  | Command | Alias | Description |
381
411
  |---------|-------|-------------|
382
412
  | `/nexus` | `Ctrl+N` | Full configuration dialog, or a subcommand |
383
- | `/nexus-web` | `/nw` | Open the web dashboard if one is already serving; otherwise say how to start it. Does not start the server — see [Web Dashboard](#web-dashboard) |
413
+ | `/nexus-dashboard` | `/nd` | Start the web dashboard and open it. If one is already serving, opens that and starts nothing — see [Web Dashboard](#web-dashboard) |
414
+ | `/nexus-web` | `/nw` | Alias of `/nexus-dashboard` |
415
+ | `/nexus-overview` | `/no` | Config, budget and dashboard-status overview. Prints text; starts nothing |
384
416
  | `/nexus-config` | `/nc` | Configure models & budget |
385
417
  | `/nexus-model` | `/nm` | Select a model for a role |
386
418
  | `/nexus-status` | `/ns` | Show the config summary |
387
- | `/nexus-dashboard` | `/nd` | Config, budget and dashboard-status overview. Prints text; starts nothing |
388
419
  | `/nexus-reset` | — | Reset all settings to defaults |
389
420
 
390
421
  A prompt beginning `/nexus …` typed into the composer is a *different* thing: it
391
422
  is intercepted by a prompt hook and routed to `orchestrator.handleCommand()`,
392
- which understands only `status`, `agents`, `costs`, `pause`, `resume` and
393
- `dashboard` (which returns the state as JSON). Anything else answers
394
- `Unknown command`. The table above is the TUI palette.
423
+ which understands `status`, `agents`, `costs`, `pause`, `resume`, and
424
+ `dashboard [port] [host]` (which starts the server, or says why it did not),
425
+ `dashboard stop`, and `dashboard state` (the state as JSON). Anything else
426
+ answers `Unknown command`. This hook cannot cancel the prompt — the plugin API
427
+ gives it no way to — so it replaces the command text with the command's result
428
+ rather than leaving the model holding a bare `/nexus dashboard` next to an
429
+ answer it has no reason to read. The table above is the TUI palette.
395
430
 
396
431
  ---
397
432