@serkanalgur/opencode-nexus 1.5.0 → 1.6.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/dist/index.js +95 -5
- 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,
|
|
@@ -11397,25 +11399,54 @@ var src_default = define({
|
|
|
11397
11399
|
});
|
|
11398
11400
|
editor.add({
|
|
11399
11401
|
name: "spawn",
|
|
11400
|
-
description: "Spawn a sub-agent for a task",
|
|
11402
|
+
description: "Spawn a sub-agent for a task. Use wait=true to wait for completion.",
|
|
11401
11403
|
input: {
|
|
11402
11404
|
type: "object",
|
|
11403
11405
|
properties: {
|
|
11404
11406
|
role: { type: "string", description: "Agent role (architect, coder, reviewer, tester, explorer, documenter)" },
|
|
11405
11407
|
task: { type: "string", description: "Task description" },
|
|
11406
|
-
model: { type: "string", description: "Model override (optional)" }
|
|
11408
|
+
model: { type: "string", description: "Model override (optional)" },
|
|
11409
|
+
wait: { type: "boolean", description: "Wait for completion (default: false)" },
|
|
11410
|
+
timeout: { type: "number", description: "Timeout in ms when waiting (default: 120000)" }
|
|
11407
11411
|
},
|
|
11408
11412
|
required: ["role", "task"],
|
|
11409
11413
|
additionalProperties: false
|
|
11410
11414
|
},
|
|
11411
11415
|
execute: async (input) => {
|
|
11412
|
-
const { role, task, model } = input;
|
|
11416
|
+
const { role, task, model, wait, timeout } = input;
|
|
11413
11417
|
try {
|
|
11418
|
+
orchestrator.parentSessionID = null;
|
|
11414
11419
|
const agent = await orchestrator.spawnAgent({ role, model });
|
|
11415
11420
|
await orchestrator.ctx.session.prompt({
|
|
11416
11421
|
sessionID: agent.sessionID,
|
|
11417
11422
|
text: task
|
|
11418
11423
|
});
|
|
11424
|
+
if (wait) {
|
|
11425
|
+
const waitTimeout = timeout || 120000;
|
|
11426
|
+
try {
|
|
11427
|
+
await orchestrator.ctx.session.wait({ sessionID: agent.sessionID });
|
|
11428
|
+
} catch {}
|
|
11429
|
+
try {
|
|
11430
|
+
const messages = await orchestrator.ctx.session.context({ sessionID: agent.sessionID });
|
|
11431
|
+
const lastMsg = messages.filter((m) => m.role === "assistant").pop();
|
|
11432
|
+
const result = lastMsg?.content || "Task completed (no output captured)";
|
|
11433
|
+
agent.status = "completed";
|
|
11434
|
+
await ctx.storage.set("orchestrator-state", JSON.parse(JSON.stringify(orchestrator.getState())));
|
|
11435
|
+
const taskPreview = task.length > 80 ? task.substring(0, 77) + "..." : task;
|
|
11436
|
+
return {
|
|
11437
|
+
content: [
|
|
11438
|
+
`${agent.name}`,
|
|
11439
|
+
`\uD83D\uDCCB Task: ${taskPreview}`,
|
|
11440
|
+
`✅ Status: completed`,
|
|
11441
|
+
`\uD83D\uDCCE Session: ${agent.sessionID}`,
|
|
11442
|
+
`
|
|
11443
|
+
--- Result ---`,
|
|
11444
|
+
result
|
|
11445
|
+
].join(`
|
|
11446
|
+
`)
|
|
11447
|
+
};
|
|
11448
|
+
} catch {}
|
|
11449
|
+
}
|
|
11419
11450
|
const complexity = orchestrator.analyzeComplexity({
|
|
11420
11451
|
id: `spawn-${Date.now()}`,
|
|
11421
11452
|
name: task,
|
|
@@ -11436,7 +11467,8 @@ var src_default = define({
|
|
|
11436
11467
|
`\uD83D\uDCCB Task: ${taskPreview}`,
|
|
11437
11468
|
`\uD83D\uDCCA Complexity: ${complexity.overall}/100 (${complexity.factors.riskLevel} risk)`,
|
|
11438
11469
|
`\uD83E\uDD16 Model reasoning: ${modelSelection.reasoning}`,
|
|
11439
|
-
`\uD83D\uDCCE Session: ${agent.sessionID}
|
|
11470
|
+
`\uD83D\uDCCE Session: ${agent.sessionID}`,
|
|
11471
|
+
`\uD83D\uDCA1 Use wait=true to wait for completion`
|
|
11440
11472
|
].join(`
|
|
11441
11473
|
`);
|
|
11442
11474
|
return { content: output };
|
|
@@ -11657,6 +11689,64 @@ Total: ~$${result.totalEstimatedCost.toFixed(4)}`);
|
|
|
11657
11689
|
return { content: "Worktree isolation disabled." };
|
|
11658
11690
|
}
|
|
11659
11691
|
});
|
|
11692
|
+
editor.add({
|
|
11693
|
+
name: "sessions",
|
|
11694
|
+
description: "List all active Nexus agent sessions",
|
|
11695
|
+
input: { type: "object", properties: {}, additionalProperties: false },
|
|
11696
|
+
execute: async () => {
|
|
11697
|
+
const agents = orchestrator.getState().agents;
|
|
11698
|
+
if (agents.length === 0)
|
|
11699
|
+
return { content: "No active agent sessions." };
|
|
11700
|
+
const lines = agents.map((a) => {
|
|
11701
|
+
const statusIcon = a.status === "working" ? "\uD83D\uDD04" : a.status === "idle" ? "⏸️" : a.status === "completed" ? "✅" : "❌";
|
|
11702
|
+
return `${statusIcon} ${a.name} (${a.role}) — Session: ${a.sessionID}`;
|
|
11703
|
+
});
|
|
11704
|
+
return { content: `Active Sessions (${agents.length}):
|
|
11705
|
+
${lines.join(`
|
|
11706
|
+
`)}` };
|
|
11707
|
+
}
|
|
11708
|
+
});
|
|
11709
|
+
editor.add({
|
|
11710
|
+
name: "background",
|
|
11711
|
+
description: "Move running agents to background (detach from current session)",
|
|
11712
|
+
input: { type: "object", properties: {}, additionalProperties: false },
|
|
11713
|
+
execute: async () => {
|
|
11714
|
+
const agents = orchestrator.getState().agents.filter((a) => a.status === "working" || a.status === "idle");
|
|
11715
|
+
if (agents.length === 0)
|
|
11716
|
+
return { content: "No running agents to move to background." };
|
|
11717
|
+
for (const agent of agents) {
|
|
11718
|
+
try {
|
|
11719
|
+
await orchestrator.ctx.session.background({ sessionID: agent.sessionID });
|
|
11720
|
+
} catch {}
|
|
11721
|
+
}
|
|
11722
|
+
return { content: `${agents.length} agent(s) moved to background. You can continue working while they run.` };
|
|
11723
|
+
}
|
|
11724
|
+
});
|
|
11725
|
+
editor.add({
|
|
11726
|
+
name: "result",
|
|
11727
|
+
description: "Get the result of a completed agent session",
|
|
11728
|
+
input: {
|
|
11729
|
+
type: "object",
|
|
11730
|
+
properties: {
|
|
11731
|
+
sessionID: { type: "string", description: "Session ID of the agent" }
|
|
11732
|
+
},
|
|
11733
|
+
required: ["sessionID"]
|
|
11734
|
+
},
|
|
11735
|
+
execute: async (input) => {
|
|
11736
|
+
const { sessionID } = input;
|
|
11737
|
+
try {
|
|
11738
|
+
const messages = await orchestrator.ctx.session.context({ sessionID });
|
|
11739
|
+
const lastMsg = messages.filter((m) => m.role === "assistant").pop();
|
|
11740
|
+
if (lastMsg) {
|
|
11741
|
+
return { content: `Session ${sessionID} result:
|
|
11742
|
+
${lastMsg.content}` };
|
|
11743
|
+
}
|
|
11744
|
+
return { content: `Session ${sessionID} has no assistant messages yet.` };
|
|
11745
|
+
} catch (error) {
|
|
11746
|
+
return { content: `Failed to get result: ${error.message}` };
|
|
11747
|
+
}
|
|
11748
|
+
}
|
|
11749
|
+
});
|
|
11660
11750
|
});
|
|
11661
11751
|
await ctx.session.hook("prompt", (event) => {
|
|
11662
11752
|
if (event.prompt.text.startsWith("/nexus")) {
|