mirror of https://github.com/openclaw/openclaw.git
fix(sessions): ignore streamTo for runtime=subagent
\nThis prevents schema-following models from breaking subagent spawns when the tool schema includes streamTo.\n\nAuthored by OpenClaw (model: gpt-5.2)
This commit is contained in:
parent
843e3c1efb
commit
3d88e8f5ce
|
|
@ -224,24 +224,22 @@ describe("sessions_spawn tool", () => {
|
|||
expect(hoisted.spawnSubagentDirectMock).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('rejects streamTo when runtime is not "acp"', async () => {
|
||||
it('ignores streamTo when runtime is not "acp" (schema-following models may include it)', async () => {
|
||||
const tool = createSessionsSpawnTool({
|
||||
agentSessionKey: "agent:main:main",
|
||||
});
|
||||
|
||||
const result = await tool.execute("call-3b", {
|
||||
const result = await tool.execute("call-streamto-ignore", {
|
||||
runtime: "subagent",
|
||||
task: "analyze file",
|
||||
streamTo: "parent",
|
||||
});
|
||||
|
||||
expect(result.details).toMatchObject({
|
||||
status: "error",
|
||||
status: "accepted",
|
||||
});
|
||||
const details = result.details as { error?: string };
|
||||
expect(details.error).toContain("streamTo is only supported for runtime=acp");
|
||||
expect(hoisted.spawnSubagentDirectMock).toHaveBeenCalled();
|
||||
expect(hoisted.spawnAcpDirectMock).not.toHaveBeenCalled();
|
||||
expect(hoisted.spawnSubagentDirectMock).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("keeps attachment content schema unconstrained for llama.cpp grammar safety", () => {
|
||||
|
|
|
|||
|
|
@ -41,7 +41,9 @@ const SessionsSpawnToolSchema = Type.Object({
|
|||
mode: optionalStringEnum(SUBAGENT_SPAWN_MODES),
|
||||
cleanup: optionalStringEnum(["delete", "keep"] as const),
|
||||
sandbox: optionalStringEnum(SESSIONS_SPAWN_SANDBOX_MODES),
|
||||
streamTo: optionalStringEnum(ACP_SPAWN_STREAM_TARGETS),
|
||||
streamTo: optionalStringEnum(ACP_SPAWN_STREAM_TARGETS, {
|
||||
description: 'ACP-only. Ignored when runtime != "acp".',
|
||||
}),
|
||||
|
||||
// Inline attachments (snapshot-by-value).
|
||||
// NOTE: Attachment contents are redacted from transcript persistence by sanitizeToolCallInputs.
|
||||
|
|
@ -105,7 +107,8 @@ export function createSessionsSpawnTool(
|
|||
const cleanup =
|
||||
params.cleanup === "keep" || params.cleanup === "delete" ? params.cleanup : "keep";
|
||||
const sandbox = params.sandbox === "require" ? "require" : "inherit";
|
||||
const streamTo = params.streamTo === "parent" ? "parent" : undefined;
|
||||
// Only relevant for ACP. For runtime=subagent, ignore it (schema-following models may still send it).
|
||||
const streamTo = runtime === "acp" && params.streamTo === "parent" ? "parent" : undefined;
|
||||
// Back-compat: older callers used timeoutSeconds for this tool.
|
||||
const timeoutSecondsCandidate =
|
||||
typeof params.runTimeoutSeconds === "number"
|
||||
|
|
@ -127,12 +130,8 @@ export function createSessionsSpawnTool(
|
|||
}>)
|
||||
: undefined;
|
||||
|
||||
if (streamTo && runtime !== "acp") {
|
||||
return jsonResult({
|
||||
status: "error",
|
||||
error: `streamTo is only supported for runtime=acp; got runtime=${runtime}`,
|
||||
});
|
||||
}
|
||||
// NOTE: streamTo is ACP-only. For runtime=subagent we intentionally ignore it,
|
||||
// because schema-following models may include it if it is present in the tool schema.
|
||||
|
||||
if (resumeSessionId && runtime !== "acp") {
|
||||
return jsonResult({
|
||||
|
|
|
|||
Loading…
Reference in New Issue