@serkanalgur/opencode-nexus 1.5.0 → 1.6.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/dist/index.js +126 -32
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -10012,6 +10012,7 @@ class NexusOrchestrator {
|
|
|
10012
10012
|
}
|
|
10013
10013
|
notifications = null;
|
|
10014
10014
|
modelCosts = new Map;
|
|
10015
|
+
parentSessionID = null;
|
|
10015
10016
|
constructor(config, messageStoreConfig, memoryStoreConfig) {
|
|
10016
10017
|
this.config = this.mergeConfig(config);
|
|
10017
10018
|
this.budget = this.config.budget;
|
|
@@ -10650,7 +10651,8 @@ Please continue from where the previous agent left off.`;
|
|
|
10650
10651
|
const session = await this.ctx.session.create({
|
|
10651
10652
|
title,
|
|
10652
10653
|
agent: agentType,
|
|
10653
|
-
model: modelName ? { providerID: provider, id: modelName } : undefined
|
|
10654
|
+
model: modelName ? { providerID: provider, id: modelName } : undefined,
|
|
10655
|
+
parentID: this.parentSessionID || undefined
|
|
10654
10656
|
});
|
|
10655
10657
|
const agent = {
|
|
10656
10658
|
id: agentId,
|
|
@@ -11115,57 +11117,61 @@ You are the Nexus Orchestrator — an intelligent multi-agent coordinator. You m
|
|
|
11115
11117
|
## Core Capabilities
|
|
11116
11118
|
|
|
11117
11119
|
- **Spawn specialized sub-agents** for each task (architect, coder, reviewer, tester, explorer, documenter)
|
|
11120
|
+
- **Wait for completion** — get results back from agents
|
|
11121
|
+
- **Background execution** — run agents in background while you continue
|
|
11118
11122
|
- **Cost-aware routing** — automatically selects optimal models based on task complexity and budget
|
|
11119
11123
|
- **Self-healing** — retries failed tasks, transfers context to new agents, escalates if needed
|
|
11120
11124
|
- **Performance tracking** — learns which model/role combinations work best
|
|
11121
|
-
- **Execution history** — tracks all past executions for analysis
|
|
11122
11125
|
|
|
11123
11126
|
## How to Use Nexus Tools
|
|
11124
11127
|
|
|
11125
|
-
### Spawning Agents
|
|
11126
|
-
Use the \`spawn\` tool to create specialized agents:
|
|
11128
|
+
### Spawning Agents (Wait for Result)
|
|
11127
11129
|
\`\`\`
|
|
11128
|
-
nexus.spawn(role="coder", task="Implement JWT
|
|
11129
|
-
nexus.spawn(role="reviewer", task="Review
|
|
11130
|
+
nexus.spawn(role="coder", task="Implement JWT auth", wait=true)
|
|
11131
|
+
nexus.spawn(role="reviewer", task="Review implementation", wait=true, timeout=60000)
|
|
11130
11132
|
\`\`\`
|
|
11131
11133
|
|
|
11132
|
-
|
|
11133
|
-
|
|
11134
|
-
### Checking Status
|
|
11134
|
+
### Spawning Agents (Parallel, No Wait)
|
|
11135
11135
|
\`\`\`
|
|
11136
|
-
nexus.
|
|
11137
|
-
nexus.
|
|
11138
|
-
|
|
11136
|
+
nexus.spawn(role="coder", task="Task A")
|
|
11137
|
+
nexus.spawn(role="coder", task="Task B")
|
|
11138
|
+
# Both run in parallel
|
|
11139
|
+
nexus.sessions() # Check progress
|
|
11140
|
+
nexus.background() # Move to background
|
|
11139
11141
|
\`\`\`
|
|
11140
11142
|
|
|
11141
|
-
###
|
|
11143
|
+
### Getting Results
|
|
11142
11144
|
\`\`\`
|
|
11143
|
-
nexus.
|
|
11144
|
-
nexus.model.costs() — Show real model pricing
|
|
11145
|
-
nexus.preset(name="balanced") — Apply a cost preset
|
|
11145
|
+
nexus.result(sessionID="ses_xxx") # Get output from completed agent
|
|
11146
11146
|
\`\`\`
|
|
11147
11147
|
|
|
11148
|
-
###
|
|
11148
|
+
### Other Tools
|
|
11149
11149
|
\`\`\`
|
|
11150
|
-
nexus.
|
|
11151
|
-
nexus.
|
|
11150
|
+
nexus.status(detailed=true) # Full state
|
|
11151
|
+
nexus.costs() # Cost report
|
|
11152
|
+
nexus.forecast(tasks='[...]') # Predict costs
|
|
11153
|
+
nexus.performance.scores() # Performance data
|
|
11154
|
+
nexus.history.list(count=10) # Execution history
|
|
11155
|
+
nexus.security.scan(content="...", filename="app.ts") # Security scan
|
|
11152
11156
|
\`\`\`
|
|
11153
11157
|
|
|
11154
11158
|
## Task Decomposition Strategy
|
|
11155
11159
|
|
|
11156
11160
|
When given a development request:
|
|
11157
|
-
1. **Analyze** — Break
|
|
11158
|
-
2. **
|
|
11159
|
-
3. **
|
|
11160
|
-
4. **
|
|
11161
|
-
5. **
|
|
11161
|
+
1. **Analyze** — Break into discrete tasks
|
|
11162
|
+
2. **Plan** — Determine parallel vs sequential
|
|
11163
|
+
3. **Estimate** — Use nexus.forecast for costs
|
|
11164
|
+
4. **Spawn** — Parallel tasks: spawn without wait
|
|
11165
|
+
5. **Spawn** — Sequential tasks: spawn with wait=true
|
|
11166
|
+
6. **Monitor** — nexus.sessions() to track progress
|
|
11167
|
+
7. **Review** — nexus.spawn(role="reviewer", wait=true)
|
|
11168
|
+
8. **Report** — Summarize outcomes
|
|
11162
11169
|
|
|
11163
11170
|
## Quality Gates
|
|
11164
11171
|
|
|
11165
|
-
|
|
11166
|
-
-
|
|
11167
|
-
-
|
|
11168
|
-
- Verify with nexus.spawn(role="tester") before marking complete
|
|
11172
|
+
- Every code change → nexus.spawn(role="reviewer", wait=true)
|
|
11173
|
+
- Security check → nexus.security.scan()
|
|
11174
|
+
- Testing → nexus.spawn(role="tester", wait=true)
|
|
11169
11175
|
`;
|
|
11170
11176
|
var src_default = define({
|
|
11171
11177
|
id: "nexus",
|
|
@@ -11397,25 +11403,54 @@ var src_default = define({
|
|
|
11397
11403
|
});
|
|
11398
11404
|
editor.add({
|
|
11399
11405
|
name: "spawn",
|
|
11400
|
-
description: "Spawn a sub-agent for a task",
|
|
11406
|
+
description: "Spawn a sub-agent for a task. Use wait=true to wait for completion.",
|
|
11401
11407
|
input: {
|
|
11402
11408
|
type: "object",
|
|
11403
11409
|
properties: {
|
|
11404
11410
|
role: { type: "string", description: "Agent role (architect, coder, reviewer, tester, explorer, documenter)" },
|
|
11405
11411
|
task: { type: "string", description: "Task description" },
|
|
11406
|
-
model: { type: "string", description: "Model override (optional)" }
|
|
11412
|
+
model: { type: "string", description: "Model override (optional)" },
|
|
11413
|
+
wait: { type: "boolean", description: "Wait for completion (default: false)" },
|
|
11414
|
+
timeout: { type: "number", description: "Timeout in ms when waiting (default: 120000)" }
|
|
11407
11415
|
},
|
|
11408
11416
|
required: ["role", "task"],
|
|
11409
11417
|
additionalProperties: false
|
|
11410
11418
|
},
|
|
11411
11419
|
execute: async (input) => {
|
|
11412
|
-
const { role, task, model } = input;
|
|
11420
|
+
const { role, task, model, wait, timeout } = input;
|
|
11413
11421
|
try {
|
|
11422
|
+
orchestrator.parentSessionID = null;
|
|
11414
11423
|
const agent = await orchestrator.spawnAgent({ role, model });
|
|
11415
11424
|
await orchestrator.ctx.session.prompt({
|
|
11416
11425
|
sessionID: agent.sessionID,
|
|
11417
11426
|
text: task
|
|
11418
11427
|
});
|
|
11428
|
+
if (wait) {
|
|
11429
|
+
const waitTimeout = timeout || 120000;
|
|
11430
|
+
try {
|
|
11431
|
+
await orchestrator.ctx.session.wait({ sessionID: agent.sessionID });
|
|
11432
|
+
} catch {}
|
|
11433
|
+
try {
|
|
11434
|
+
const messages = await orchestrator.ctx.session.context({ sessionID: agent.sessionID });
|
|
11435
|
+
const lastMsg = messages.filter((m) => m.role === "assistant").pop();
|
|
11436
|
+
const result = lastMsg?.content || "Task completed (no output captured)";
|
|
11437
|
+
agent.status = "completed";
|
|
11438
|
+
await ctx.storage.set("orchestrator-state", JSON.parse(JSON.stringify(orchestrator.getState())));
|
|
11439
|
+
const taskPreview = task.length > 80 ? task.substring(0, 77) + "..." : task;
|
|
11440
|
+
return {
|
|
11441
|
+
content: [
|
|
11442
|
+
`${agent.name}`,
|
|
11443
|
+
`\uD83D\uDCCB Task: ${taskPreview}`,
|
|
11444
|
+
`✅ Status: completed`,
|
|
11445
|
+
`\uD83D\uDCCE Session: ${agent.sessionID}`,
|
|
11446
|
+
`
|
|
11447
|
+
--- Result ---`,
|
|
11448
|
+
result
|
|
11449
|
+
].join(`
|
|
11450
|
+
`)
|
|
11451
|
+
};
|
|
11452
|
+
} catch {}
|
|
11453
|
+
}
|
|
11419
11454
|
const complexity = orchestrator.analyzeComplexity({
|
|
11420
11455
|
id: `spawn-${Date.now()}`,
|
|
11421
11456
|
name: task,
|
|
@@ -11436,7 +11471,8 @@ var src_default = define({
|
|
|
11436
11471
|
`\uD83D\uDCCB Task: ${taskPreview}`,
|
|
11437
11472
|
`\uD83D\uDCCA Complexity: ${complexity.overall}/100 (${complexity.factors.riskLevel} risk)`,
|
|
11438
11473
|
`\uD83E\uDD16 Model reasoning: ${modelSelection.reasoning}`,
|
|
11439
|
-
`\uD83D\uDCCE Session: ${agent.sessionID}
|
|
11474
|
+
`\uD83D\uDCCE Session: ${agent.sessionID}`,
|
|
11475
|
+
`\uD83D\uDCA1 Use wait=true to wait for completion`
|
|
11440
11476
|
].join(`
|
|
11441
11477
|
`);
|
|
11442
11478
|
return { content: output };
|
|
@@ -11657,6 +11693,64 @@ Total: ~$${result.totalEstimatedCost.toFixed(4)}`);
|
|
|
11657
11693
|
return { content: "Worktree isolation disabled." };
|
|
11658
11694
|
}
|
|
11659
11695
|
});
|
|
11696
|
+
editor.add({
|
|
11697
|
+
name: "sessions",
|
|
11698
|
+
description: "List all active Nexus agent sessions",
|
|
11699
|
+
input: { type: "object", properties: {}, additionalProperties: false },
|
|
11700
|
+
execute: async () => {
|
|
11701
|
+
const agents = orchestrator.getState().agents;
|
|
11702
|
+
if (agents.length === 0)
|
|
11703
|
+
return { content: "No active agent sessions." };
|
|
11704
|
+
const lines = agents.map((a) => {
|
|
11705
|
+
const statusIcon = a.status === "working" ? "\uD83D\uDD04" : a.status === "idle" ? "⏸️" : a.status === "completed" ? "✅" : "❌";
|
|
11706
|
+
return `${statusIcon} ${a.name} (${a.role}) — Session: ${a.sessionID}`;
|
|
11707
|
+
});
|
|
11708
|
+
return { content: `Active Sessions (${agents.length}):
|
|
11709
|
+
${lines.join(`
|
|
11710
|
+
`)}` };
|
|
11711
|
+
}
|
|
11712
|
+
});
|
|
11713
|
+
editor.add({
|
|
11714
|
+
name: "background",
|
|
11715
|
+
description: "Move running agents to background (detach from current session)",
|
|
11716
|
+
input: { type: "object", properties: {}, additionalProperties: false },
|
|
11717
|
+
execute: async () => {
|
|
11718
|
+
const agents = orchestrator.getState().agents.filter((a) => a.status === "working" || a.status === "idle");
|
|
11719
|
+
if (agents.length === 0)
|
|
11720
|
+
return { content: "No running agents to move to background." };
|
|
11721
|
+
for (const agent of agents) {
|
|
11722
|
+
try {
|
|
11723
|
+
await orchestrator.ctx.session.background({ sessionID: agent.sessionID });
|
|
11724
|
+
} catch {}
|
|
11725
|
+
}
|
|
11726
|
+
return { content: `${agents.length} agent(s) moved to background. You can continue working while they run.` };
|
|
11727
|
+
}
|
|
11728
|
+
});
|
|
11729
|
+
editor.add({
|
|
11730
|
+
name: "result",
|
|
11731
|
+
description: "Get the result of a completed agent session",
|
|
11732
|
+
input: {
|
|
11733
|
+
type: "object",
|
|
11734
|
+
properties: {
|
|
11735
|
+
sessionID: { type: "string", description: "Session ID of the agent" }
|
|
11736
|
+
},
|
|
11737
|
+
required: ["sessionID"]
|
|
11738
|
+
},
|
|
11739
|
+
execute: async (input) => {
|
|
11740
|
+
const { sessionID } = input;
|
|
11741
|
+
try {
|
|
11742
|
+
const messages = await orchestrator.ctx.session.context({ sessionID });
|
|
11743
|
+
const lastMsg = messages.filter((m) => m.role === "assistant").pop();
|
|
11744
|
+
if (lastMsg) {
|
|
11745
|
+
return { content: `Session ${sessionID} result:
|
|
11746
|
+
${lastMsg.content}` };
|
|
11747
|
+
}
|
|
11748
|
+
return { content: `Session ${sessionID} has no assistant messages yet.` };
|
|
11749
|
+
} catch (error) {
|
|
11750
|
+
return { content: `Failed to get result: ${error.message}` };
|
|
11751
|
+
}
|
|
11752
|
+
}
|
|
11753
|
+
});
|
|
11660
11754
|
});
|
|
11661
11755
|
await ctx.session.hook("prompt", (event) => {
|
|
11662
11756
|
if (event.prompt.text.startsWith("/nexus")) {
|