mirror of
https://github.com/NeuralNomadsAI/CodeNomad.git
synced 2026-08-21 06:13:26 +00:00
Re-scope the renderer-memory fix on the native V2 baseline after removal of the duplicate Tauri event transport. Bound Markdown, reasoning, tool output, diagnostics, diffs, task steps, todos, and per-message part rendering while retaining complete authoritative content behind lazy copy actions. Coordinate message records and derived render caches under one 64 MiB byte-aware LRU. Protect mounted, loading, and live transcripts; cap pending parts and prompt display overrides; fence stale cache writes; and conservatively account measurement failures. Reload evicted transcripts through bounded complete V2 pagination, reject stale lifecycle completions, purge all per-instance session state, and prevent delayed SSE/delta work from recreating removed stores. Keep DEV-v2 PR validation enabled without reintroducing native Tauri transport changes. Validated with full UI and Electron typecheck, UI production build, 248 standard UI tests, 71 browser-condition UI tests, 118 Electron native tests, and git diff checks. The long-duration WebKit soak remains pending while the PR stays draft.
99 lines
3.7 KiB
TypeScript
99 lines
3.7 KiB
TypeScript
import assert from "node:assert/strict"
|
|
import { describe, it } from "node:test"
|
|
|
|
import {
|
|
isSessionTranscriptProtected,
|
|
SessionTranscriptLru,
|
|
selectTranscriptEvictions,
|
|
type TranscriptLruEntry,
|
|
type TranscriptProtectionState,
|
|
} from "./session-transcript-lru.ts"
|
|
|
|
const entry = (instanceId: string, sessionId: string, bytes: number, lastUsed: number): TranscriptLruEntry => ({
|
|
instanceId, sessionId, bytes, lastUsed,
|
|
})
|
|
|
|
describe("session transcript LRU", () => {
|
|
it("selects the least-recently-used bytes globally across workspaces", () => {
|
|
const entries = [entry("a", "new", 5, 3), entry("b", "old", 4, 1), entry("a", "middle", 4, 2)]
|
|
assert.deepEqual(
|
|
selectTranscriptEvictions(entries, 6, () => false).map(({ instanceId, sessionId }) => `${instanceId}/${sessionId}`),
|
|
["b/old", "a/middle"],
|
|
)
|
|
})
|
|
|
|
it("evicts an unbounded entry without turning retained bytes into NaN", () => {
|
|
const entries = [entry("a", "unbounded", Number.POSITIVE_INFINITY, 1), entry("b", "fits", 4, 2)]
|
|
assert.deepEqual(
|
|
selectTranscriptEvictions(entries, 4, () => false).map(({ sessionId }) => sessionId),
|
|
["unbounded"],
|
|
)
|
|
})
|
|
|
|
it("skips every protected state and permits temporary protected overage", () => {
|
|
const states: Record<string, TranscriptProtectionState> = {
|
|
visible: { visible: true }, loading: { loading: true },
|
|
working: { status: "working" }, compacting: { status: "compacting" },
|
|
sending: { liveMessages: true }, streaming: { liveMessages: true }, pendingSend: { liveMessages: true },
|
|
permission: { permissionBlocked: true }, question: { questionBlocked: true },
|
|
generation: { generationPending: true },
|
|
}
|
|
const entries = Object.keys(states).map((sessionId, index) => entry("a", sessionId, 2, index))
|
|
entries.push(entry("b", "inactive", 2, entries.length))
|
|
assert.deepEqual(
|
|
selectTranscriptEvictions(entries, 1, ({ sessionId }) => isSessionTranscriptProtected(states[sessionId] ?? {})).map(({ sessionId }) => sessionId),
|
|
["inactive"],
|
|
)
|
|
})
|
|
|
|
it("touches entries without changing byte accounting", () => {
|
|
const sizes = new Map([["a/old", 6], ["b/new", 6]])
|
|
const evicted: string[] = []
|
|
const lru = new SessionTranscriptLru({
|
|
byteBudget: 12,
|
|
isProtected: () => false,
|
|
evict: (instanceId, sessionId) => evicted.push(`${instanceId}/${sessionId}`),
|
|
})
|
|
lru.account("a", "old", sizes.get("a/old")!)
|
|
lru.account("b", "new", sizes.get("b/new")!)
|
|
lru.touch("a", "old")
|
|
sizes.set("b/third", 6)
|
|
lru.account("b", "third", sizes.get("b/third")!)
|
|
assert.deepEqual(evicted, ["b/new"])
|
|
})
|
|
|
|
it("preserves access order when touches happen before accounting completes", () => {
|
|
const evicted: string[] = []
|
|
const lru = new SessionTranscriptLru({
|
|
byteBudget: 12,
|
|
isProtected: () => false,
|
|
evict: (instanceId, sessionId) => evicted.push(`${instanceId}/${sessionId}`),
|
|
})
|
|
|
|
lru.touch("a", "old")
|
|
lru.touch("b", "new")
|
|
lru.account("b", "new", 6)
|
|
lru.account("a", "old", 6)
|
|
lru.account("c", "latest", 6)
|
|
|
|
assert.deepEqual(evicted, ["a/old"])
|
|
})
|
|
|
|
it("does not retain a pending touch after empty terminal accounting", () => {
|
|
const evicted: string[] = []
|
|
const lru = new SessionTranscriptLru({
|
|
byteBudget: 12,
|
|
isProtected: () => false,
|
|
evict: (instanceId, sessionId) => evicted.push(`${instanceId}/${sessionId}`),
|
|
})
|
|
|
|
assert.equal(lru.touch("a", "empty"), true)
|
|
assert.equal(lru.touch("a", "empty"), false)
|
|
lru.account("a", "empty", 0)
|
|
lru.account("b", "old", 6)
|
|
lru.account("c", "new", 6)
|
|
lru.account("a", "empty", 6)
|
|
|
|
assert.deepEqual(evicted, ["b/old"])
|
|
})
|
|
})
|