mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-07 04:21:38 +00:00
feat(commands): add /subagents spawn command
Add a `spawn` action to the /subagents command handler that invokes spawnSubagentDirect() to deterministically launch a named subagent. Usage: /subagents spawn <agentId> <task> [--model <model>] [--thinking <level>] Also includes the shared subagent-spawn module extraction (same as the refactor/extract-shared-subagent-spawn branch) since it hasn't merged yet. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
committed by
Peter Steinberger
parent
bb5ce3b02f
commit
5a3a448bc4
@@ -10,6 +10,7 @@ import {
|
||||
markSubagentRunForSteerRestart,
|
||||
replaceSubagentRunAfterSteer,
|
||||
} from "../../agents/subagent-registry.js";
|
||||
import { spawnSubagentDirect } from "../../agents/subagent-spawn.js";
|
||||
import {
|
||||
extractAssistantText,
|
||||
resolveInternalSessionKey,
|
||||
@@ -47,7 +48,7 @@ const COMMAND = "/subagents";
|
||||
const COMMAND_KILL = "/kill";
|
||||
const COMMAND_STEER = "/steer";
|
||||
const COMMAND_TELL = "/tell";
|
||||
const ACTIONS = new Set(["list", "kill", "log", "send", "steer", "info", "help"]);
|
||||
const ACTIONS = new Set(["list", "kill", "log", "send", "steer", "info", "spawn", "help"]);
|
||||
const RECENT_WINDOW_MINUTES = 30;
|
||||
const SUBAGENT_TASK_PREVIEW_MAX = 110;
|
||||
const STEER_ABORT_SETTLE_TIMEOUT_MS = 5_000;
|
||||
@@ -192,6 +193,7 @@ function buildSubagentsHelp() {
|
||||
"- /subagents info <id|#>",
|
||||
"- /subagents send <id|#> <message>",
|
||||
"- /subagents steer <id|#> <message>",
|
||||
"- /subagents spawn <agentId> <task> [--model <model>] [--thinking <level>]",
|
||||
"- /kill <id|#|all>",
|
||||
"- /steer <id|#> <message>",
|
||||
"- /tell <id|#> <message>",
|
||||
@@ -644,5 +646,56 @@ export const handleSubagentsCommand: CommandHandler = async (params, allowTextCo
|
||||
};
|
||||
}
|
||||
|
||||
if (action === "spawn") {
|
||||
const agentId = restTokens[0];
|
||||
// Parse remaining tokens: task text with optional --model and --thinking flags.
|
||||
const taskParts: string[] = [];
|
||||
let model: string | undefined;
|
||||
let thinking: string | undefined;
|
||||
for (let i = 1; i < restTokens.length; i++) {
|
||||
if (restTokens[i] === "--model" && i + 1 < restTokens.length) {
|
||||
i += 1;
|
||||
model = restTokens[i];
|
||||
} else if (restTokens[i] === "--thinking" && i + 1 < restTokens.length) {
|
||||
i += 1;
|
||||
thinking = restTokens[i];
|
||||
} else {
|
||||
taskParts.push(restTokens[i]);
|
||||
}
|
||||
}
|
||||
const task = taskParts.join(" ").trim();
|
||||
if (!agentId || !task) {
|
||||
return {
|
||||
shouldContinue: false,
|
||||
reply: {
|
||||
text: "Usage: /subagents spawn <agentId> <task> [--model <model>] [--thinking <level>]",
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const result = await spawnSubagentDirect(
|
||||
{ task, agentId, model, thinking, cleanup: "keep" },
|
||||
{
|
||||
agentSessionKey: requesterKey,
|
||||
agentChannel: params.command.channel,
|
||||
agentAccountId: params.ctx.AccountId,
|
||||
agentTo: params.command.to,
|
||||
agentThreadId: params.ctx.MessageThreadId,
|
||||
},
|
||||
);
|
||||
if (result.status === "accepted") {
|
||||
return {
|
||||
shouldContinue: false,
|
||||
reply: {
|
||||
text: `Spawned subagent ${agentId} (session ${result.childSessionKey}, run ${result.runId?.slice(0, 8)}).${result.warning ? ` Warning: ${result.warning}` : ""}`,
|
||||
},
|
||||
};
|
||||
}
|
||||
return {
|
||||
shouldContinue: false,
|
||||
reply: { text: `Spawn failed: ${result.error ?? result.status}` },
|
||||
};
|
||||
}
|
||||
|
||||
return { shouldContinue: false, reply: { text: buildSubagentsHelp() } };
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user