mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 06:00:43 +00:00
agents/cli: unwrap nested claude result json
This commit is contained in:
@@ -125,6 +125,33 @@ describe("parseCliJson", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("unwraps nested Claude result JSON from JSON output", () => {
|
||||
const result = parseCliJson(
|
||||
JSON.stringify({
|
||||
session_id: "session-nested-json",
|
||||
result: JSON.stringify({
|
||||
type: "result",
|
||||
result: JSON.stringify({
|
||||
type: "result",
|
||||
subtype: "success",
|
||||
result: "actual response text",
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
{
|
||||
command: "claude",
|
||||
output: "json",
|
||||
sessionIdFields: ["session_id"],
|
||||
},
|
||||
);
|
||||
|
||||
expect(result).toEqual({
|
||||
text: "actual response text",
|
||||
sessionId: "session-nested-json",
|
||||
usage: undefined,
|
||||
});
|
||||
});
|
||||
|
||||
it("parses nested OpenAI-style cached token details from CLI json payloads", () => {
|
||||
const result = parseCliJson(
|
||||
JSON.stringify({
|
||||
@@ -295,6 +322,38 @@ describe("parseCliJsonl", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("unwraps nested Claude agent result JSON from stream-json output", () => {
|
||||
const result = parseCliJsonl(
|
||||
[
|
||||
JSON.stringify({ type: "init", session_id: "session-nested-jsonl" }),
|
||||
JSON.stringify({
|
||||
type: "result",
|
||||
session_id: "session-nested-jsonl",
|
||||
result: JSON.stringify({
|
||||
type: "result",
|
||||
result: JSON.stringify({
|
||||
type: "result",
|
||||
subtype: "success",
|
||||
result: "actual response text",
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
].join("\n"),
|
||||
{
|
||||
command: "claude",
|
||||
output: "jsonl",
|
||||
sessionIdFields: ["session_id"],
|
||||
},
|
||||
"claude-cli",
|
||||
);
|
||||
|
||||
expect(result).toEqual({
|
||||
text: "actual response text",
|
||||
sessionId: "session-nested-jsonl",
|
||||
usage: undefined,
|
||||
});
|
||||
});
|
||||
|
||||
it("parses multiple JSON objects embedded on the same line", () => {
|
||||
const result = parseCliJsonl(
|
||||
'{"type":"init","session_id":"session-999"} {"type":"result","session_id":"session-999","result":"done"}',
|
||||
|
||||
@@ -193,6 +193,31 @@ function collectCliText(value: unknown): string {
|
||||
return "";
|
||||
}
|
||||
|
||||
function unwrapNestedCliResultText(raw: string): string {
|
||||
let text = raw;
|
||||
for (let depth = 0; depth < 8; depth += 1) {
|
||||
const trimmed = text.trim();
|
||||
if (!trimmed.startsWith("{")) {
|
||||
return text;
|
||||
}
|
||||
try {
|
||||
const parsed = JSON.parse(trimmed);
|
||||
if (
|
||||
!isRecord(parsed) ||
|
||||
typeof parsed.type !== "string" ||
|
||||
parsed.type !== "result" ||
|
||||
typeof parsed.result !== "string"
|
||||
) {
|
||||
return text;
|
||||
}
|
||||
text = parsed.result;
|
||||
} catch {
|
||||
return text;
|
||||
}
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
function collectExplicitCliErrorText(parsed: Record<string, unknown>): string {
|
||||
const nested = readNestedErrorMessage(parsed);
|
||||
if (nested) {
|
||||
@@ -260,7 +285,7 @@ export function parseCliJson(raw: string, backend: CliBackendConfig): CliOutput
|
||||
collectCliText(parsed.result) ||
|
||||
collectCliText(parsed.response) ||
|
||||
collectCliText(parsed);
|
||||
const trimmedText = nextText.trim();
|
||||
const trimmedText = unwrapNestedCliResultText(nextText).trim();
|
||||
if (trimmedText) {
|
||||
text = trimmedText;
|
||||
sawStructuredOutput = true;
|
||||
@@ -292,7 +317,7 @@ function parseClaudeCliJsonlResult(params: {
|
||||
params.parsed.type === "result" &&
|
||||
typeof params.parsed.result === "string"
|
||||
) {
|
||||
const resultText = params.parsed.result.trim();
|
||||
const resultText = unwrapNestedCliResultText(params.parsed.result).trim();
|
||||
if (resultText) {
|
||||
return { text: resultText, sessionId: params.sessionId, usage: params.usage };
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user