@serkanalgur/opencode-nexus 1.4.0 → 1.4.1
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 +82 -8
- package/dist/index.js +18 -7
- package/dist/tui.js +20 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -147,14 +147,14 @@ await ctx.session.prompt({ sessionID: session.id, text: 'You are a senior softwa
|
|
|
147
147
|
|
|
148
148
|
Each agent role gets a specialized prompt:
|
|
149
149
|
|
|
150
|
-
| Role | Focus |
|
|
151
|
-
|
|
152
|
-
| **Architect** | System design, architecture patterns, high-level decisions |
|
|
153
|
-
| **Coder** | Clean, efficient code following best practices |
|
|
154
|
-
| **Reviewer** | Code review for correctness, security, performance |
|
|
155
|
-
| **Tester** | Comprehensive tests, edge cases, quality assurance |
|
|
156
|
-
| **Explorer** | Codebase navigation, architecture analysis |
|
|
157
|
-
| **Documenter** | Clear technical documentation |
|
|
150
|
+
| Role | OpenCode Agent | Focus |
|
|
151
|
+
|------|----------------|-------|
|
|
152
|
+
| **Architect** | `architect` | System design, architecture patterns, high-level decisions |
|
|
153
|
+
| **Coder** | `build-orchestrator` | Clean, efficient code following best practices |
|
|
154
|
+
| **Reviewer** | `code-reviewer` | Code review for correctness, security, performance |
|
|
155
|
+
| **Tester** | `build-orchestrator` | Comprehensive tests, edge cases, quality assurance |
|
|
156
|
+
| **Explorer** | `explore` | Codebase navigation, architecture analysis |
|
|
157
|
+
| **Documenter** | `doc-writer` | Clear technical documentation |
|
|
158
158
|
|
|
159
159
|
### Cost-Aware Model Selection
|
|
160
160
|
|
|
@@ -278,6 +278,68 @@ NexusPlugin.register({
|
|
|
278
278
|
})
|
|
279
279
|
```
|
|
280
280
|
|
|
281
|
+
### Custom Agent Roles
|
|
282
|
+
|
|
283
|
+
Define your own agent roles with custom prompts:
|
|
284
|
+
|
|
285
|
+
```jsonc
|
|
286
|
+
// .opencode/nexus.jsonc
|
|
287
|
+
{
|
|
288
|
+
"customRoles": [
|
|
289
|
+
{
|
|
290
|
+
"name": "security-auditor",
|
|
291
|
+
"displayName": "Security Auditor",
|
|
292
|
+
"emoji": "🔐",
|
|
293
|
+
"prompt": "You are a security auditor. Focus on OWASP Top 10, vulnerability scanning, and security best practices.",
|
|
294
|
+
"model": "anthropic/claude-sonnet-4-6"
|
|
295
|
+
}
|
|
296
|
+
]
|
|
297
|
+
}
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
Or register dynamically via tools: `nexus.roles.add(name="security-auditor", displayName="Security Auditor", prompt="...")`
|
|
301
|
+
|
|
302
|
+
### Execution History
|
|
303
|
+
|
|
304
|
+
Track all task executions with costs, durations, and outcomes:
|
|
305
|
+
|
|
306
|
+
```
|
|
307
|
+
nexus.history.list(count=10) — Recent executions
|
|
308
|
+
nexus.history.stats() — Success rate, avg cost, breakdown by role
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
### Cost Forecasting
|
|
312
|
+
|
|
313
|
+
Predict costs before executing tasks:
|
|
314
|
+
|
|
315
|
+
```typescript
|
|
316
|
+
const forecast = orchestrator.forecaster.forecastAll([
|
|
317
|
+
{ task: myTask, role: 'coder', model: 'claude-sonnet-4-6', complexity: score }
|
|
318
|
+
], budgetRemaining)
|
|
319
|
+
// → { totalEstimatedCost: 0.0234, withinBudget: true }
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
### Agent Performance Scoring
|
|
323
|
+
|
|
324
|
+
Track which model/role combinations work best:
|
|
325
|
+
|
|
326
|
+
```
|
|
327
|
+
nexus.performance.scores() — All model/role scores
|
|
328
|
+
nexus.performance.best(role="coder") — Best model for a role
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
Score = 40% success rate + 30% speed + 30% cost efficiency.
|
|
332
|
+
|
|
333
|
+
### Git Worktree Per Agent
|
|
334
|
+
|
|
335
|
+
Each agent works in its own isolated git worktree:
|
|
336
|
+
|
|
337
|
+
```
|
|
338
|
+
nexus.worktree.enable() — Enable isolation
|
|
339
|
+
nexus.worktree.list() — List active worktrees
|
|
340
|
+
nexus.worktree.disable() — Clean up all
|
|
341
|
+
```
|
|
342
|
+
|
|
281
343
|
---
|
|
282
344
|
|
|
283
345
|
## TUI Commands
|
|
@@ -313,6 +375,18 @@ Register these tools in your agent prompts:
|
|
|
313
375
|
| `nexus.dashboard.stop` | Stop web dashboard | `{}` |
|
|
314
376
|
| `nexus.preset` | Apply preset config | `{ name: string }` |
|
|
315
377
|
| `nexus.template` | List/instantiate templates | `{ name?: string, baseDir?: string }` |
|
|
378
|
+
| `nexus.model.costs` | Show/set model pricing | `{ model?: string, setInput?: number, setOutput?: number }` |
|
|
379
|
+
| `nexus.security.scan` | Scan code for security issues | `{ content: string, filename?: string }` |
|
|
380
|
+
| `nexus.roles.list` | List custom agent roles | `{}` |
|
|
381
|
+
| `nexus.roles.add` | Add a custom role | `{ name, displayName, prompt, emoji?, model? }` |
|
|
382
|
+
| `nexus.history.list` | List execution history | `{ count?: number }` |
|
|
383
|
+
| `nexus.history.stats` | Execution statistics | `{}` |
|
|
384
|
+
| `nexus.forecast` | Predict costs before execution | `{ tasks: string }` |
|
|
385
|
+
| `nexus.performance.scores` | Model/role performance scores | `{}` |
|
|
386
|
+
| `nexus.performance.best` | Best model for a role | `{ role: string }` |
|
|
387
|
+
| `nexus.worktree.enable` | Enable git worktree isolation | `{ repoRoot?: string }` |
|
|
388
|
+
| `nexus.worktree.list` | List active worktrees | `{}` |
|
|
389
|
+
| `nexus.worktree.disable` | Disable and clean up | `{}` |
|
|
316
390
|
|
|
317
391
|
### Tool Examples
|
|
318
392
|
|
package/dist/index.js
CHANGED
|
@@ -8817,6 +8817,7 @@ class StateBroadcaster {
|
|
|
8817
8817
|
}
|
|
8818
8818
|
|
|
8819
8819
|
// src/dashboard.ts
|
|
8820
|
+
import { join as join2 } from "node:path";
|
|
8820
8821
|
var CORS_HEADERS = {
|
|
8821
8822
|
"Access-Control-Allow-Origin": "*",
|
|
8822
8823
|
"Access-Control-Allow-Methods": "GET, POST, OPTIONS",
|
|
@@ -8871,6 +8872,16 @@ class DashboardModule {
|
|
|
8871
8872
|
if (url.pathname === "/api/health") {
|
|
8872
8873
|
return jsonResponse({ ok: true, uptime: process.uptime() });
|
|
8873
8874
|
}
|
|
8875
|
+
try {
|
|
8876
|
+
const spaPath = join2(process.cwd(), "dashboard", "index.html");
|
|
8877
|
+
const spaFile = Bun.file(spaPath);
|
|
8878
|
+
const exists = spaFile.size > 0;
|
|
8879
|
+
if (exists) {
|
|
8880
|
+
return new Response(spaFile, {
|
|
8881
|
+
headers: { "Content-Type": "text/html; charset=utf-8", ...CORS_HEADERS }
|
|
8882
|
+
});
|
|
8883
|
+
}
|
|
8884
|
+
} catch {}
|
|
8874
8885
|
return new Response("Nexus Dashboard API", {
|
|
8875
8886
|
headers: {
|
|
8876
8887
|
"Content-Type": "text/plain",
|
|
@@ -8973,9 +8984,9 @@ function detectCycles(nodes) {
|
|
|
8973
8984
|
|
|
8974
8985
|
// src/message-store.ts
|
|
8975
8986
|
import { appendFileSync, readFileSync as readFileSync2, existsSync, mkdirSync as mkdirSync2 } from "node:fs";
|
|
8976
|
-
import { join as
|
|
8987
|
+
import { join as join3, dirname as dirname2 } from "node:path";
|
|
8977
8988
|
var DEFAULT_CONFIG2 = {
|
|
8978
|
-
storagePath:
|
|
8989
|
+
storagePath: join3(process.env.HOME || "~", ".local", "share", "opencode-nexus", "messages.jsonl"),
|
|
8979
8990
|
maxMessages: 1e4,
|
|
8980
8991
|
rotationSize: 1000
|
|
8981
8992
|
};
|
|
@@ -9063,10 +9074,10 @@ class MessageStore {
|
|
|
9063
9074
|
|
|
9064
9075
|
// src/memory-store.ts
|
|
9065
9076
|
import { Database } from "bun:sqlite";
|
|
9066
|
-
import { join as
|
|
9077
|
+
import { join as join4, dirname as dirname3 } from "node:path";
|
|
9067
9078
|
import { mkdirSync as mkdirSync3 } from "node:fs";
|
|
9068
9079
|
var DEFAULT_CONFIG3 = {
|
|
9069
|
-
dbPath:
|
|
9080
|
+
dbPath: join4(process.env.HOME || "~", ".local", "share", "opencode-nexus", "memory.db"),
|
|
9070
9081
|
defaultTTL: 0,
|
|
9071
9082
|
maxEntries: 1e4
|
|
9072
9083
|
};
|
|
@@ -9880,7 +9891,7 @@ class CostForecaster {
|
|
|
9880
9891
|
// src/worktree.ts
|
|
9881
9892
|
import { execSync } from "node:child_process";
|
|
9882
9893
|
import { existsSync as existsSync2 } from "node:fs";
|
|
9883
|
-
import { join as
|
|
9894
|
+
import { join as join5 } from "node:path";
|
|
9884
9895
|
|
|
9885
9896
|
class WorktreeManager {
|
|
9886
9897
|
worktrees = new Map;
|
|
@@ -9888,11 +9899,11 @@ class WorktreeManager {
|
|
|
9888
9899
|
repoRoot;
|
|
9889
9900
|
constructor(repoRoot, baseDir) {
|
|
9890
9901
|
this.repoRoot = repoRoot;
|
|
9891
|
-
this.baseDir = baseDir ||
|
|
9902
|
+
this.baseDir = baseDir || join5(repoRoot, ".worktrees", "nexus-agents");
|
|
9892
9903
|
}
|
|
9893
9904
|
create(agentId) {
|
|
9894
9905
|
const branch = `nexus-agent-${agentId}`;
|
|
9895
|
-
const path =
|
|
9906
|
+
const path = join5(this.baseDir, agentId);
|
|
9896
9907
|
try {
|
|
9897
9908
|
if (!existsSync2(this.baseDir)) {
|
|
9898
9909
|
execSync(`mkdir -p "${this.baseDir}"`, { cwd: this.repoRoot });
|
package/dist/tui.js
CHANGED
|
@@ -34532,6 +34532,25 @@ var tui_default = define({
|
|
|
34532
34532
|
case "d":
|
|
34533
34533
|
await handleDashboard();
|
|
34534
34534
|
break;
|
|
34535
|
+
case "web":
|
|
34536
|
+
case "w":
|
|
34537
|
+
try {
|
|
34538
|
+
const port = parts[1] ? parseInt(parts[1]) : 4747;
|
|
34539
|
+
context.ui.toast.show({
|
|
34540
|
+
title: "Nexus Dashboard",
|
|
34541
|
+
message: `Starting web dashboard on port ${port}...
|
|
34542
|
+
Open http://localhost:${port} in your browser`,
|
|
34543
|
+
variant: "success",
|
|
34544
|
+
duration: 5000
|
|
34545
|
+
});
|
|
34546
|
+
} catch (e) {
|
|
34547
|
+
context.ui.toast.show({
|
|
34548
|
+
title: "Nexus",
|
|
34549
|
+
message: `Failed to start dashboard: ${e.message}`,
|
|
34550
|
+
variant: "error"
|
|
34551
|
+
});
|
|
34552
|
+
}
|
|
34553
|
+
break;
|
|
34535
34554
|
case "model":
|
|
34536
34555
|
case "m":
|
|
34537
34556
|
if (parts[1]) {
|
|
@@ -34568,7 +34587,7 @@ var tui_default = define({
|
|
|
34568
34587
|
default:
|
|
34569
34588
|
context.ui.toast.show({
|
|
34570
34589
|
title: "Nexus",
|
|
34571
|
-
message: "Commands: config, status, dashboard, model <role>, reset",
|
|
34590
|
+
message: "Commands: config, status, dashboard, web [port], model <role>, reset",
|
|
34572
34591
|
variant: "info"
|
|
34573
34592
|
});
|
|
34574
34593
|
}
|