mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-14 16:30:43 +00:00
fix(agents): handle resumed cli jsonl output
Signed-off-by: samzong <samzong.lu@gmail.com>
This commit is contained in:
committed by
Peter Steinberger
parent
02ca572a26
commit
ee6b29b715
@@ -357,6 +357,7 @@ Docs: https://docs.openclaw.ai
|
||||
- Agents/failover: rotate auth profiles before deferred cooldown marking on rate-limit failures, so file-lock contention cannot stall profile failover. Fixes #57281. (#57283) Thanks @jeremyknows.
|
||||
- Gateway/sessions: when `session.dmScope: "main"` is configured, route a bare webchat `/new` against the agent's main session (`sessions.create` with `emitCommandHooks=true`) to an in-place reset instead of creating a parallel `dashboard:` child, matching `/new` behavior on Telegram/Discord. Fixes #77434. (#71170) Thanks @statxc.
|
||||
- Scripts/UI/Windows: launch `.cmd` and `.bat` UI runners through the shared cmd.exe escaping path with shell mode disabled, avoiding Node.js v24 DEP0190 warnings while preserving argument boundaries. (#62910) Thanks @nandanadileep.
|
||||
- Agents/CLI runner: disable supervisor stdout/stderr capture for prepared CLI runs while keeping bounded diagnostics and incremental JSONL output parsing, preventing long CLI output from being retained in memory. (#79617) Thanks @samzong.
|
||||
- Telegram: treat a DM binding that carries the chat id in both `conversationId` and `parentConversationId` as a direct conversation instead of a topic, so reverse delivery for Telegram DMs is not misrouted through a topic-shaped target. (#79700) Thanks @TSHOGX.
|
||||
|
||||
## 2026.5.7
|
||||
|
||||
@@ -768,27 +768,19 @@ describe("runCliAgent spawn path", () => {
|
||||
event: { type: "content_block_delta", delta: { type: "text_delta", text: " world" } },
|
||||
}) + "\n",
|
||||
);
|
||||
input.onStdout?.(
|
||||
JSON.stringify({
|
||||
type: "result",
|
||||
session_id: "session-123",
|
||||
result: "Hello world",
|
||||
}) + "\n",
|
||||
);
|
||||
return createManagedRun({
|
||||
reason: "exit",
|
||||
exitCode: 0,
|
||||
exitSignal: null,
|
||||
durationMs: 50,
|
||||
stdout: [
|
||||
JSON.stringify({ type: "init", session_id: "session-123" }),
|
||||
JSON.stringify({
|
||||
type: "stream_event",
|
||||
event: { type: "content_block_delta", delta: { type: "text_delta", text: "Hello" } },
|
||||
}),
|
||||
JSON.stringify({
|
||||
type: "stream_event",
|
||||
event: { type: "content_block_delta", delta: { type: "text_delta", text: " world" } },
|
||||
}),
|
||||
JSON.stringify({
|
||||
type: "result",
|
||||
session_id: "session-123",
|
||||
result: "Hello world",
|
||||
}),
|
||||
].join("\n"),
|
||||
stdout: "",
|
||||
stderr: "",
|
||||
timedOut: false,
|
||||
noOutputTimedOut: false,
|
||||
|
||||
@@ -150,6 +150,52 @@ describe("executePreparedCliRun supervisor output capture", () => {
|
||||
expect(result.sessionId).toBe("session-jsonl-large");
|
||||
});
|
||||
|
||||
it("parses oversized resume JSONL output from the effective resume output mode", async () => {
|
||||
const largeToolEvent = `${JSON.stringify({
|
||||
type: "stream_event",
|
||||
event: {
|
||||
type: "content_block_delta",
|
||||
delta: { type: "tool_delta", text: "x".repeat(2 * 1024 * 1024) },
|
||||
},
|
||||
})}\n`;
|
||||
const resultEvent = `${JSON.stringify({
|
||||
type: "result",
|
||||
session_id: "resume-jsonl-session",
|
||||
result: "resumed answer",
|
||||
})}\n`;
|
||||
const context = buildPreparedCliRunContext({
|
||||
output: "text",
|
||||
provider: "resume-jsonl-cli",
|
||||
});
|
||||
Object.assign(context.preparedBackend.backend, {
|
||||
jsonlDialect: "claude-stream-json" as const,
|
||||
resumeArgs: ["resume", "{sessionId}"],
|
||||
resumeOutput: "jsonl" as const,
|
||||
sessionMode: "existing" as const,
|
||||
});
|
||||
|
||||
supervisorSpawnMock.mockImplementationOnce(async (...args: unknown[]) => {
|
||||
const input = args[0] as SupervisorSpawnInput;
|
||||
input.onStdout?.(largeToolEvent);
|
||||
input.onStdout?.(resultEvent);
|
||||
return createManagedRun({
|
||||
reason: "exit",
|
||||
exitCode: 0,
|
||||
exitSignal: null,
|
||||
durationMs: 50,
|
||||
stdout: input.captureOutput === false ? "" : `${largeToolEvent}${resultEvent}`,
|
||||
stderr: "",
|
||||
timedOut: false,
|
||||
noOutputTimedOut: false,
|
||||
});
|
||||
});
|
||||
|
||||
const result = await executePreparedCliRun(context, "resume-jsonl-session");
|
||||
|
||||
expect(result.text).toBe("resumed answer");
|
||||
expect(result.sessionId).toBe("resume-jsonl-session");
|
||||
});
|
||||
|
||||
it("classifies failed stdout from the retained parse buffer before the diagnostic tail", async () => {
|
||||
const errorPrefix = `${JSON.stringify({
|
||||
type: "result",
|
||||
|
||||
@@ -442,7 +442,8 @@ export async function executePreparedCliRun(
|
||||
useResume,
|
||||
trigger: params.trigger,
|
||||
});
|
||||
const hasJsonlOutput = backend.output === "jsonl";
|
||||
const outputMode = useResume ? (backend.resumeOutput ?? backend.output) : backend.output;
|
||||
const hasJsonlOutput = outputMode === "jsonl";
|
||||
if (shouldUseClaudeLiveSession(context)) {
|
||||
if (!hasJsonlOutput) {
|
||||
throw new Error("Claude live session requires JSONL streaming parser");
|
||||
@@ -688,7 +689,6 @@ export async function executePreparedCliRun(
|
||||
});
|
||||
}
|
||||
|
||||
const outputMode = useResume ? (backend.resumeOutput ?? backend.output) : backend.output;
|
||||
const streamedJsonlOutput =
|
||||
outputMode === "jsonl" ? (streamingParser?.getOutput() ?? null) : null;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user