mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 18:30:44 +00:00
fix(subagent): include role, session key, and timing in error payloads
Error payloads from sessions_spawn and subagent wait outcomes now carry the context a parent needs to retry or report clearly: - sessions-spawn-tool: add role (requested agentId) to early validation errors, to the ACP register-failure payload, and to forwarded error results from both the ACP and subagent spawn paths. childSessionKey and runId are already populated by the inner spawn for the errors that know them; this just plumbs role through alongside. - subagent-announce-output: extend SubagentRunOutcome with optional startedAt/endedAt/elapsedMs and populate them in applySubagentWaitOutcome so timeout and error outcomes convey how long the child ran before failing. Scoped verification: tsgo:core, tsgo:core:test, and 43 targeted tests in src/agents (sessions-spawn-tool, subagent-registry lifecycle retry grace, subagent-announce timeout, subagent-announce, and capture-completion-reply) all green. Repo-wide pnpm check is red on latest origin/main for unrelated extensions/discord and extensions/qa-lab surfaces (missing @buape/carbon and @copilotkit/aimock members); not addressed here.
This commit is contained in:
committed by
Gustavo Madeira Santana
parent
f9a1875127
commit
41b628e686
@@ -58,6 +58,9 @@ export type AgentWaitResult = {
|
||||
export type SubagentRunOutcome = {
|
||||
status: "ok" | "error" | "timeout" | "unknown";
|
||||
error?: string;
|
||||
startedAt?: number;
|
||||
endedAt?: number;
|
||||
elapsedMs?: number;
|
||||
};
|
||||
|
||||
function extractToolResultText(content: unknown): string {
|
||||
@@ -297,20 +300,30 @@ export function applySubagentWaitOutcome(params: {
|
||||
startedAt: params.startedAt,
|
||||
endedAt: params.endedAt,
|
||||
};
|
||||
const waitError = typeof params.wait?.error === "string" ? params.wait.error : undefined;
|
||||
if (params.wait?.status === "timeout") {
|
||||
next.outcome = { status: "timeout" };
|
||||
} else if (params.wait?.status === "error") {
|
||||
next.outcome = { status: "error", error: waitError };
|
||||
} else if (params.wait?.status === "ok") {
|
||||
next.outcome = { status: "ok" };
|
||||
}
|
||||
if (typeof params.wait?.startedAt === "number" && !next.startedAt) {
|
||||
next.startedAt = params.wait.startedAt;
|
||||
}
|
||||
if (typeof params.wait?.endedAt === "number" && !next.endedAt) {
|
||||
next.endedAt = params.wait.endedAt;
|
||||
}
|
||||
const timing: Pick<SubagentRunOutcome, "startedAt" | "endedAt" | "elapsedMs"> = {};
|
||||
if (typeof next.startedAt === "number") {
|
||||
timing.startedAt = next.startedAt;
|
||||
}
|
||||
if (typeof next.endedAt === "number") {
|
||||
timing.endedAt = next.endedAt;
|
||||
}
|
||||
if (typeof next.startedAt === "number" && typeof next.endedAt === "number") {
|
||||
timing.elapsedMs = Math.max(0, next.endedAt - next.startedAt);
|
||||
}
|
||||
const waitError = typeof params.wait?.error === "string" ? params.wait.error : undefined;
|
||||
if (params.wait?.status === "timeout") {
|
||||
next.outcome = { status: "timeout", ...timing };
|
||||
} else if (params.wait?.status === "error") {
|
||||
next.outcome = { status: "error", error: waitError, ...timing };
|
||||
} else if (params.wait?.status === "ok") {
|
||||
next.outcome = { status: "ok", ...timing };
|
||||
}
|
||||
return next;
|
||||
}
|
||||
|
||||
|
||||
@@ -201,10 +201,13 @@ export function createSessionsSpawnTool(
|
||||
}>)
|
||||
: undefined;
|
||||
|
||||
const roleContext = requestedAgentId ? { role: requestedAgentId } : {};
|
||||
|
||||
if (streamTo && runtime !== "acp") {
|
||||
return jsonResult({
|
||||
status: "error",
|
||||
error: `streamTo is only supported for runtime=acp; got runtime=${runtime}`,
|
||||
...roleContext,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -212,6 +215,7 @@ export function createSessionsSpawnTool(
|
||||
return jsonResult({
|
||||
status: "error",
|
||||
error: `resumeSessionId is only supported for runtime=acp; got runtime=${runtime}`,
|
||||
...roleContext,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -222,6 +226,7 @@ export function createSessionsSpawnTool(
|
||||
status: "error",
|
||||
error:
|
||||
"attachments are currently unsupported for runtime=acp; use runtime=subagent or remove attachments",
|
||||
...roleContext,
|
||||
});
|
||||
}
|
||||
const result = await spawnAcpDirect(
|
||||
@@ -304,10 +309,15 @@ export function createSessionsSpawnTool(
|
||||
error: `Failed to register ACP run: ${summarizeError(err)}. Cleanup was attempted, but the already-started ACP run may still finish in the background.`,
|
||||
childSessionKey,
|
||||
runId: childRunId,
|
||||
...roleContext,
|
||||
});
|
||||
}
|
||||
}
|
||||
return jsonResult(result);
|
||||
return jsonResult(
|
||||
result.status === "error" && requestedAgentId
|
||||
? { ...result, role: requestedAgentId }
|
||||
: result,
|
||||
);
|
||||
}
|
||||
|
||||
const result = await spawnSubagentDirect(
|
||||
@@ -345,7 +355,11 @@ export function createSessionsSpawnTool(
|
||||
},
|
||||
);
|
||||
|
||||
return jsonResult(result);
|
||||
return jsonResult(
|
||||
result.status === "error" && requestedAgentId
|
||||
? { ...result, role: requestedAgentId }
|
||||
: result,
|
||||
);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user