Dev #11

Merged
cpfarhood merged 86 commits from dev into local 2026-05-12 00:02:32 +00:00
2 changed files with 59 additions and 0 deletions
Showing only changes of commit a5430f010d - Show all commits
@@ -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);