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;
|
||||
}
|
||||
|
||||
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") {
|
||||
resultEvent = event;
|
||||
accumulateUsage(usage, event.usage ?? event.usageMetadata);
|
||||
|
||||
Reference in New Issue
Block a user