Files
oh-my-opencode/src/hooks/claude-code-hooks/transcript.test.ts
T
popododo0720 eb56701996 fix: reduce session.messages() calls with event-based caching to prevent memory leaks
- Replace session.messages() fetch in context-window-monitor with message.updated event cache
- Replace session.messages() fetch in preemptive-compaction with message.updated event cache
- Add per-session transcript cache (5min TTL) to avoid full rebuild per tool call
- Remove session.messages() from background-agent polling (use event-based progress)
- Add TTL pruning to todo-continuation-enforcer session state Map
- Add setInterval.unref() to tool-input-cache cleanup timer

Fixes #1222
2026-02-12 11:38:11 +09:00

103 lines
2.7 KiB
TypeScript

import { describe, it, expect, mock, beforeEach, afterEach } from "bun:test"
import { existsSync, unlinkSync, readFileSync } from "fs"
import {
buildTranscriptFromSession,
deleteTempTranscript,
clearTranscriptCache,
} from "./transcript"
function createMockClient(messages: unknown[] = []) {
return {
session: {
messages: mock(() =>
Promise.resolve({
data: messages,
})
),
},
}
}
describe("transcript caching", () => {
afterEach(() => {
clearTranscriptCache()
})
// #given same session called twice
// #when buildTranscriptFromSession is invoked
// #then session.messages() should be called only once (cached)
it("should cache transcript and not re-fetch for same session", async () => {
const client = createMockClient([
{
info: { role: "assistant" },
parts: [
{
type: "tool",
tool: "bash",
state: { status: "completed", input: { command: "ls" } },
},
],
},
])
const path1 = await buildTranscriptFromSession(
client,
"ses_cache1",
"/tmp",
"bash",
{ command: "echo hi" }
)
const path2 = await buildTranscriptFromSession(
client,
"ses_cache1",
"/tmp",
"read",
{ path: "/tmp/file" }
)
// session.messages() called only once
expect(client.session.messages).toHaveBeenCalledTimes(1)
// Both return valid paths
expect(path1).not.toBeNull()
expect(path2).not.toBeNull()
// Second call should append the new tool entry
if (path2) {
const content = readFileSync(path2, "utf-8")
expect(content).toContain("Read")
}
deleteTempTranscript(path1)
deleteTempTranscript(path2)
})
// #given different sessions
// #when buildTranscriptFromSession called for each
// #then session.messages() should be called for each
it("should not share cache between different sessions", async () => {
const client = createMockClient([])
await buildTranscriptFromSession(client, "ses_a", "/tmp", "bash", {})
await buildTranscriptFromSession(client, "ses_b", "/tmp", "bash", {})
expect(client.session.messages).toHaveBeenCalledTimes(2)
clearTranscriptCache()
})
// #given clearTranscriptCache is called
// #when buildTranscriptFromSession called again
// #then should re-fetch
it("should re-fetch after cache is cleared", async () => {
const client = createMockClient([])
await buildTranscriptFromSession(client, "ses_clear", "/tmp", "bash", {})
clearTranscriptCache()
await buildTranscriptFromSession(client, "ses_clear", "/tmp", "bash", {})
expect(client.session.messages).toHaveBeenCalledTimes(2)
})
})