From d2e566ba9d9da36619b60598c14f76dd196e7151 Mon Sep 17 00:00:00 2001 From: YeonGyu-Kim Date: Tue, 24 Mar 2026 20:36:22 +0900 Subject: [PATCH] fix(preemptive-compaction): mock session history in degradation test Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus --- ...ive-compaction.degradation-monitor.test.ts | 63 +++++++++++++++++-- 1 file changed, 59 insertions(+), 4 deletions(-) diff --git a/src/hooks/preemptive-compaction.degradation-monitor.test.ts b/src/hooks/preemptive-compaction.degradation-monitor.test.ts index 16a629834..1390a57e6 100644 --- a/src/hooks/preemptive-compaction.degradation-monitor.test.ts +++ b/src/hooks/preemptive-compaction.degradation-monitor.test.ts @@ -1,3 +1,5 @@ +/// + import { beforeEach, describe, expect, it, mock } from "bun:test" const logMock = mock(() => {}) @@ -8,11 +10,19 @@ mock.module("../shared/logger", () => ({ const { createPreemptiveCompactionHook } = await import("./preemptive-compaction") -function createMockCtx() { +type AssistantHistoryMessage = { + info: { + id: string + role: "assistant" + } + parts: Array<{ type: string; text?: string }> +} + +function createMockCtx(sessionHistory: AssistantHistoryMessage[]) { return { client: { session: { - messages: mock(() => Promise.resolve({ data: [] })), + messages: mock(() => Promise.resolve({ data: sessionHistory })), summarize: mock(() => Promise.resolve({})), }, tui: { @@ -23,6 +33,22 @@ function createMockCtx() { } } +function appendAssistantHistory( + sessionHistory: AssistantHistoryMessage[], + input: { + id: string + parts: AssistantHistoryMessage["parts"] + }, +): void { + sessionHistory.push({ + info: { + id: input.id, + role: "assistant", + }, + parts: input.parts, + }) +} + function buildAssistantUpdate(input: { sessionID: string id: string @@ -69,7 +95,9 @@ describe("preemptive-compaction post-compaction degradation monitor", () => { }) it("triggers recovery summarize after three consecutive no-text tail messages", async () => { - const ctx = createMockCtx() + // given + const sessionHistory: AssistantHistoryMessage[] = [] + const ctx = createMockCtx(sessionHistory) const hook = createPreemptiveCompactionHook(ctx as never, {} as never) const sessionID = "ses_tail_recovery" @@ -82,10 +110,17 @@ describe("preemptive-compaction post-compaction degradation monitor", () => { const stepOnlyParts = [{ type: "step-start" }, { type: "step-finish" }] + // when + appendAssistantHistory(sessionHistory, { id: "msg_1", parts: stepOnlyParts }) await hook.event(buildAssistantUpdate({ sessionID, id: "msg_1", parts: stepOnlyParts })) + + appendAssistantHistory(sessionHistory, { id: "msg_2", parts: stepOnlyParts }) await hook.event(buildAssistantUpdate({ sessionID, id: "msg_2", parts: stepOnlyParts })) + + appendAssistantHistory(sessionHistory, { id: "msg_3", parts: stepOnlyParts }) await hook.event(buildAssistantUpdate({ sessionID, id: "msg_3", parts: stepOnlyParts })) + // then expect(ctx.client.session.summarize).toHaveBeenCalledTimes(1) expect(ctx.client.tui.showToast).toHaveBeenCalledTimes(1) expect(logMock).toHaveBeenCalledWith( @@ -98,7 +133,9 @@ describe("preemptive-compaction post-compaction degradation monitor", () => { }) it("resets no-text streak when assistant emits text content", async () => { - const ctx = createMockCtx() + // given + const sessionHistory: AssistantHistoryMessage[] = [] + const ctx = createMockCtx(sessionHistory) const hook = createPreemptiveCompactionHook(ctx as never, {} as never) const sessionID = "ses_tail_reset" @@ -109,30 +146,48 @@ describe("preemptive-compaction post-compaction degradation monitor", () => { }, }) + // when + appendAssistantHistory(sessionHistory, { + id: "msg_1", + parts: [{ type: "step-start" }, { type: "step-finish" }], + }) await hook.event(buildAssistantUpdate({ sessionID, id: "msg_1", parts: [{ type: "step-start" }, { type: "step-finish" }], })) + appendAssistantHistory(sessionHistory, { + id: "msg_2", + parts: [{ type: "text", text: "Recovered response" }], + }) await hook.event(buildAssistantUpdate({ sessionID, id: "msg_2", parts: [{ type: "text", text: "Recovered response" }], })) + appendAssistantHistory(sessionHistory, { + id: "msg_3", + parts: [{ type: "step-start" }, { type: "step-finish" }], + }) await hook.event(buildAssistantUpdate({ sessionID, id: "msg_3", parts: [{ type: "step-start" }, { type: "step-finish" }], })) + appendAssistantHistory(sessionHistory, { + id: "msg_4", + parts: [{ type: "step-start" }, { type: "step-finish" }], + }) await hook.event(buildAssistantUpdate({ sessionID, id: "msg_4", parts: [{ type: "step-start" }, { type: "step-finish" }], })) + // then expect(ctx.client.session.summarize).not.toHaveBeenCalled() }) })