@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.
Files changed (2) hide show
  1. package/dist/index.js +126 -32
  2. 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 authentication middleware")
11129
- nexus.spawn(role="reviewer", task="Review the auth implementation for security")
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
- Available roles: architect, coder, reviewer, tester, explorer, documenter
11133
-
11134
- ### Checking Status
11134
+ ### Spawning Agents (Parallel, No Wait)
11135
11135
  \`\`\`
11136
- nexus.status(detailed=true) — Full orchestrator state
11137
- nexus.agents(filter="working") — List active agents
11138
- nexus.costs() — Cost report and budget status
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
- ### Cost Management
11143
+ ### Getting Results
11142
11144
  \`\`\`
11143
- nexus.forecast(tasks='[...]') — Predict costs
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
- ### Performance & History
11148
+ ### Other Tools
11149
11149
  \`\`\`
11150
- nexus.performance.scores() — Model/role performance scores
11151
- nexus.history.list(count=10) — Recent execution history
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 the request into discrete tasks
11158
- 2. **Estimate** — Use nexus.forecast to predict costs
11159
- 3. **Execute** — Spawn agents in parallel where possible
11160
- 4. **Review** — Use nexus.spawn(role="reviewer") for each delivery
11161
- 5. **Report** — Summarize what was done, costs, and outcomes
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
- Never skip these steps:
11166
- - Every code change must be reviewed by nexus.spawn(role="reviewer")
11167
- - Run nexus.security.scan() on new code
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")) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@serkanalgur/opencode-nexus",
3
- "version": "1.5.0",
3
+ "version": "1.6.1",
4
4
  "description": "Adaptive Multi-Agent Orchestration with Cost Intelligence for OpenCode V2",
5
5
  "keywords": [
6
6
  "opencode",