| import { describe, expect, it, vi } from "vitest"; |
| import type { AcpRuntime } from "../runtime/types.js"; |
| import type { AcpRuntimeHandle } from "../runtime/types.js"; |
| import type { CachedRuntimeState } from "./runtime-cache.js"; |
| import { RuntimeCache } from "./runtime-cache.js"; |
|
|
| function mockState(sessionKey: string): CachedRuntimeState { |
| const runtime = { |
| ensureSession: vi.fn(async () => ({ |
| sessionKey, |
| backend: "acpx", |
| runtimeSessionName: `runtime:${sessionKey}`, |
| })), |
| runTurn: vi.fn(async function* () { |
| yield { type: "done" as const }; |
| }), |
| cancel: vi.fn(async () => {}), |
| close: vi.fn(async () => {}), |
| } as unknown as AcpRuntime; |
| return { |
| runtime, |
| handle: { |
| sessionKey, |
| backend: "acpx", |
| runtimeSessionName: `runtime:${sessionKey}`, |
| } as AcpRuntimeHandle, |
| backend: "acpx", |
| agent: "codex", |
| mode: "persistent", |
| }; |
| } |
|
|
| describe("RuntimeCache", () => { |
| it("tracks idle candidates with touch-aware lookups", () => { |
| vi.useFakeTimers(); |
| try { |
| const cache = new RuntimeCache(); |
| const actor = "agent:codex:acp:s1"; |
| cache.set(actor, mockState(actor), { now: 1_000 }); |
|
|
| expect(cache.collectIdleCandidates({ maxIdleMs: 1_000, now: 1_999 })).toHaveLength(0); |
| expect(cache.collectIdleCandidates({ maxIdleMs: 1_000, now: 2_000 })).toHaveLength(1); |
|
|
| cache.get(actor, { now: 2_500 }); |
| expect(cache.collectIdleCandidates({ maxIdleMs: 1_000, now: 3_200 })).toHaveLength(0); |
| expect(cache.collectIdleCandidates({ maxIdleMs: 1_000, now: 3_500 })).toHaveLength(1); |
| } finally { |
| vi.useRealTimers(); |
| } |
| }); |
|
|
| it("returns snapshot entries with idle durations", () => { |
| const cache = new RuntimeCache(); |
| cache.set("a", mockState("a"), { now: 10 }); |
| cache.set("b", mockState("b"), { now: 100 }); |
|
|
| const snapshot = cache.snapshot({ now: 1_100 }); |
| const byActor = new Map(snapshot.map((entry) => [entry.actorKey, entry])); |
| expect(byActor.get("a")?.idleMs).toBe(1_090); |
| expect(byActor.get("b")?.idleMs).toBe(1_000); |
| }); |
| }); |
|
|