Hide OpenCode compact summaries from chat

This commit is contained in:
Mohamed Boudra
2026-06-08 23:03:55 +07:00
parent b04ff0e6b8
commit 9d9f6905c6
2 changed files with 130 additions and 0 deletions
@@ -2510,6 +2510,10 @@ function appendOpenCodeMessagePartDelta(
const knownPartType = partID ? state.partTypes.get(partID) : undefined;
const isReasoning = knownPartType === "reasoning" || field === "reasoning";
if (messageID && state.compactionSummaryMessageIds.has(messageID)) {
return;
}
if (isReasoning) {
if (partID) {
state.streamedPartKeys.add(`reasoning:${partID}`);
@@ -2527,6 +2531,10 @@ function appendOpenCodeMessagePartDelta(
if (messageRole === "user") {
return;
}
if (messageID && state.suppressAssistantMessagesUntilIdle?.active === true) {
state.compactionSummaryMessageIds.add(messageID);
return;
}
if (partID) {
state.streamedPartKeys.add(`text:${partID}`);
}
@@ -0,0 +1,122 @@
import { afterAll, beforeAll, beforeEach, describe, expect, test } from "vitest";
import { mkdtempSync, rmSync } from "node:fs";
import { tmpdir } from "node:os";
import path from "node:path";
import pino from "pino";
import type { AgentStreamEvent } from "../agent-sdk-types.js";
import {
canRunRealProvider,
createRealProviderClient,
getRealProviderConfig,
} from "../../daemon-e2e/real-provider-test-config.js";
import { OpenCodeServerManager } from "./opencode/server-manager.js";
const OPENCODE_REAL_TEST_MODEL = getRealProviderConfig("opencode").model;
const logger = pino({ level: "silent" });
function tmpCwd(): string {
return mkdtempSync(path.join(tmpdir(), "opencode-compact-dump-"));
}
function waitForTurnToFinish(session: {
subscribe: (callback: (event: AgentStreamEvent) => void) => () => void;
}): Promise<void> {
return new Promise((resolve, reject) => {
let unsubscribe: () => void = () => undefined;
const timeout = setTimeout(() => {
unsubscribe();
reject(new Error("Timed out waiting for OpenCode compact turn to finish"));
}, 60_000);
unsubscribe = session.subscribe((event) => {
if (
event.type !== "turn_completed" &&
event.type !== "turn_failed" &&
event.type !== "turn_canceled"
) {
return;
}
clearTimeout(timeout);
unsubscribe();
if (event.type === "turn_failed") {
reject(new Error(event.error));
return;
}
resolve();
});
});
}
function dumpCompactEvents(events: AgentStreamEvent[]): void {
console.info(
"OPENCODE_COMPACT_EVENT_DUMP",
JSON.stringify(
events.map((event) => ({
type: event.type,
turnId: "turnId" in event ? event.turnId : undefined,
item: event.type === "timeline" ? event.item : undefined,
usage: event.type === "turn_completed" ? event.usage : undefined,
})),
null,
2,
),
);
}
describe("OpenCode compact event dump (real)", () => {
let canRun = false;
beforeAll(async () => {
canRun = await canRunRealProvider("opencode");
});
beforeEach((context) => {
if (!canRun) {
context.skip();
}
});
afterAll(async () => {
await OpenCodeServerManager.getInstance(logger).shutdown();
});
test("dumps live events emitted by a real /compact turn", async () => {
const cwd = tmpCwd();
const client = createRealProviderClient("opencode", logger);
try {
const session = await client.createSession({
provider: "opencode",
cwd,
model: OPENCODE_REAL_TEST_MODEL,
modeId: "build",
});
await session.run("Reply with exactly: COMPACT_SEED_OK");
const compactEvents: AgentStreamEvent[] = [];
const unsubscribe = session.subscribe((event) => {
compactEvents.push(event);
});
const compactFinished = waitForTurnToFinish(session);
try {
await session.startTurn("/compact");
await compactFinished;
} finally {
unsubscribe();
}
dumpCompactEvents(compactEvents);
expect(compactEvents.some((event) => event.type === "turn_completed")).toBe(true);
expect(
compactEvents.filter(
(event) => event.type === "timeline" && event.item.type === "assistant_message",
),
).toEqual([]);
} finally {
rmSync(cwd, { recursive: true, force: true });
}
}, 120_000);
});