Something went wrong. Try again.
fork of prime agent with changes i want but are not upstreamable probqbly (and some fixes)
Something went wrong. Try again.
4.8 kB · 140 lines
TypeScript
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141import { Container } from "@earendil-works/pi-tui";import stripAnsi from "strip-ansi";import { beforeAll, describe, expect, test, vi } from "vitest";import { AgentActivityTracker } from "../src/modes/interactive/agent-activity.js";import { InteractiveMode } from "../src/modes/interactive/interactive-mode.js";import { initTheme } from "../src/modes/interactive/theme/theme.js";
const handleEvent = Reflect.get(InteractiveMode.prototype, "handleEvent") as ( this: unknown, event: Record<string, unknown>,) => Promise<void>;
const startCompactionLoader = Reflect.get(InteractiveMode.prototype, "startCompactionLoader") as ( this: unknown, reason: string, customInstructions?: string,) => void;
function createFakeThis(overrides: Record<string, unknown> = {}) { return { isInitialized: true, footer: { invalidate: vi.fn() }, updateConnectionStateFromEvent: vi.fn(), activityTracker: new AgentActivityTracker(), updateWorkingLoaderMessage: vi.fn(), autoCompactionLoader: undefined, retryLoader: undefined, startCompactionLoader(this: Record<string, unknown>, reason: string, customInstructions?: string) { startCompactionLoader.call(this, reason, customInstructions); }, workingVisible: true, stopWorkingLoader: vi.fn(), syncWorkingLoader: vi.fn(), defaultEditor: {}, statusContainer: { clear: vi.fn() }, chatContainer: { clear: vi.fn() }, rebuildChatFromMessages: vi.fn(function (this: { chatContainer: { clear(): void } }) { this.chatContainer.clear(); return Promise.resolve(); }), addMessageToChat: vi.fn(), refreshConnectionContextUsage: vi.fn().mockResolvedValue(undefined), showError: vi.fn(), showWarning: vi.fn(), showStatus: vi.fn(), settingsManager: { getShowTerminalProgress: () => false }, ui: { requestRender: vi.fn(), terminal: { setProgress: vi.fn() } }, ...overrides, };}
describe("InteractiveMode compaction events", () => { beforeAll(() => initTheme("dark"));
test("shows an automatic compaction loader for the full operation", async () => { const statusContainer = new Container(); const fakeThis = createFakeThis({ statusContainer });
await handleEvent.call(fakeThis, { type: "compaction_start", reason: "threshold" });
expect(stripAnsi(statusContainer.render(80).join("\n"))).toContain("Auto-compacting"); expect(fakeThis.ui.requestRender).toHaveBeenCalled();
await handleEvent.call(fakeThis, { type: "compaction_end", reason: "threshold", result: undefined, aborted: true, willRetry: false, }); expect(statusContainer.children).toHaveLength(0); });
test.each([ { name: "rebuilds successful compaction from its single persisted summary", refresh: "succeeds" }, { name: "keeps stale chat and reports a failed post-compaction refresh", refresh: "fails" }, ] as const)("$name", async ({ refresh }) => { const fakeThis = createFakeThis( refresh === "fails" ? { rebuildChatFromMessages: vi.fn().mockRejectedValue(new Error("context unavailable")) } : {}, );
await handleEvent.call(fakeThis, { type: "compaction_end", reason: "requested", result: { tokensBefore: 123, summary: "summary" }, aborted: false, willRetry: false, });
expect(fakeThis.chatContainer.clear).toHaveBeenCalledTimes(refresh === "succeeds" ? 1 : 0); expect(fakeThis.rebuildChatFromMessages).toHaveBeenCalledOnce(); expect(fakeThis.addMessageToChat).not.toHaveBeenCalled(); if (refresh === "fails") { expect(fakeThis.showError).toHaveBeenCalledWith( "Compaction succeeded, but the transcript could not be refreshed: context unavailable", ); } else { expect(fakeThis.showError).not.toHaveBeenCalled(); } });
test("shows manual warning-severity outcomes as warnings, not errors", async () => { const fakeThis = createFakeThis();
await handleEvent.call(fakeThis, { type: "compaction_end", reason: "manual", result: undefined, aborted: false, willRetry: false, errorMessage: "Session is too short to compact", errorSeverity: "warning", });
expect(fakeThis.showWarning).toHaveBeenCalledWith("Session is too short to compact"); expect(fakeThis.showError).not.toHaveBeenCalled(); });
test("restores the compaction loader from state when no start event was seen", () => { const statusContainer = new Container(); const fakeThis = createFakeThis({ statusContainer, connectionState: { isCompacting: true }, isAgentCompacting() { return true; }, loadingAnimation: undefined, workingVisible: true, isAgentStreaming: () => false, stopWorkingLoader: vi.fn(), startWorkingLoader: vi.fn(), });
(Reflect.get(InteractiveMode.prototype, "syncWorkingLoader") as (this: unknown) => void).call(fakeThis);
expect(stripAnsi(statusContainer.render(80).join("\n"))).toContain("Compacting context"); });});