Dev #11
@@ -0,0 +1,46 @@
|
|||||||
|
import { describe, expect, it } from "vitest";
|
||||||
|
import { parseGeminiJsonl } from "./parse.js";
|
||||||
|
|
||||||
|
describe("parseGeminiJsonl", () => {
|
||||||
|
it("collects assistant text from message events with string content", () => {
|
||||||
|
const stdout = [
|
||||||
|
'{"type":"init","session_id":"session-1"}',
|
||||||
|
'{"type":"message","role":"user","content":"Respond with hello."}',
|
||||||
|
'{"type":"message","role":"assistant","content":"hello","delta":true}',
|
||||||
|
'{"type":"result","status":"success"}',
|
||||||
|
].join("\n");
|
||||||
|
|
||||||
|
const parsed = parseGeminiJsonl(stdout);
|
||||||
|
|
||||||
|
expect(parsed.sessionId).toBe("session-1");
|
||||||
|
expect(parsed.summary).toBe("hello");
|
||||||
|
expect(parsed.errorMessage).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("collects assistant text from message events with structured object content", () => {
|
||||||
|
const stdout = [
|
||||||
|
'{"type":"init","session_id":"session-2"}',
|
||||||
|
'{"type":"message","role":"assistant","content":{"content":[{"type":"text","text":"first part"},{"type":"text","text":"second part"}]}}',
|
||||||
|
'{"type":"result","status":"success"}',
|
||||||
|
].join("\n");
|
||||||
|
|
||||||
|
const parsed = parseGeminiJsonl(stdout);
|
||||||
|
|
||||||
|
expect(parsed.sessionId).toBe("session-2");
|
||||||
|
expect(parsed.summary).toBe("first part\n\nsecond part");
|
||||||
|
expect(parsed.errorMessage).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("ignores non-assistant message events", () => {
|
||||||
|
const stdout = [
|
||||||
|
'{"type":"message","role":"user","content":"hidden user input"}',
|
||||||
|
'{"type":"message","role":"system","content":"hidden system note"}',
|
||||||
|
'{"type":"message","role":"assistant","content":"visible response"}',
|
||||||
|
'{"type":"result","status":"success"}',
|
||||||
|
].join("\n");
|
||||||
|
|
||||||
|
const parsed = parseGeminiJsonl(stdout);
|
||||||
|
|
||||||
|
expect(parsed.summary).toBe("visible response");
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -121,6 +121,19 @@ export function parseGeminiJsonl(stdout: string) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (type === "message") {
|
||||||
|
const role = asString(event.role, "").trim().toLowerCase();
|
||||||
|
if (role === "assistant") {
|
||||||
|
// Mirror the assistant-event handling above: collect every assistant
|
||||||
|
// message including deltas. Gemini CLI emits these as discrete final
|
||||||
|
// messages (one per assistant turn), not as cumulative streaming
|
||||||
|
// tokens, so collecting all of them produces the expected concatenated
|
||||||
|
// turn-by-turn summary rather than duplicated text.
|
||||||
|
messages.push(...collectMessageText(event.content));
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (type === "result") {
|
if (type === "result") {
|
||||||
resultEvent = event;
|
resultEvent = event;
|
||||||
accumulateUsage(usage, event.usage ?? event.usageMetadata);
|
accumulateUsage(usage, event.usage ?? event.usageMetadata);
|
||||||
|
|||||||
Reference in New Issue
Block a user