fix(cli): handle Claude CLI JSON array output format

Claude CLI with --output-format json returns a JSON array containing:
1. init message (type: "system", subtype: "init")
2. assistant response (type: "assistant")
3. result object (type: "result", with "result" field containing actual text)

parseCliJson only handled single JSON objects. When it encountered an
array, isRecord() returned false, the function returned null, and the
fallback returned raw stdout as text - sending the entire JSON blob
to users instead of the extracted response.

Fixes telegram/chat responses showing raw JSON when using claude-cli backend.
This commit is contained in:
ricardo 2026-01-29 11:27:39 +01:00
parent 15a8fc4d93
commit 1b27d907d9

View File

@ -282,6 +282,35 @@ export function parseCliJson(raw: string, backend: CliBackendConfig): CliOutput
} catch {
return null;
}
// Handle JSON array output (Claude CLI with --output-format json returns an array)
if (Array.isArray(parsed)) {
let sessionId: string | undefined;
let usage: CliUsage | undefined;
let text = "";
for (const item of parsed) {
if (!isRecord(item)) continue;
// Extract session_id from any item that has it
if (!sessionId) sessionId = pickSessionId(item, backend);
// Look for the result object (final output)
if (item.type === "result" && typeof item.result === "string") {
text = item.result;
if (isRecord(item.usage)) {
usage = toUsage(item.usage) ?? usage;
}
break; // Use first result object found
}
}
if (text) {
return { text: text.trim(), sessionId, usage };
}
return null;
}
if (!isRecord(parsed)) return null;
const sessionId = pickSessionId(parsed, backend);
const usage = isRecord(parsed.usage) ? toUsage(parsed.usage) : undefined;