session: cache the derived history — one projection per node, frozen and shared

deriveMessages() no longer re-derives and re-clones the whole surface
per call: each node is projected exactly once, when first seen (O(new
nodes) per access), through the now-public deriveEventMessage — the
per-node pure function external reconstructors and the dev invariant
fold over a log prefix, so no two paths can disagree about a request's
messages. A surface rewrite (replace, invalidate) rebuilds, signalled
by SurfaceManager.replaceGeneration — monotonic, bumped by every folded
replace and by invalidate(), never reset. Callers get a fresh array
snapshot per call over SHARED deep-frozen messages: isolation of the
append-only log moves from per-call cloning to unrepresentability
(mutation throws), which the two isolation tests now pin directly.
This commit is contained in:
Tianyi Cui
2026-07-06 02:51:20 +08:00
parent a7b569850b
commit a4f7e757fa
10 changed files with 208 additions and 49 deletions
+1 -1
View File
@@ -163,7 +163,7 @@ get(id: SessionId): Session | undefined
list(): Session[]
```
Source: [`packages/core/session/src/index.ts:328`](../../packages/core/session/src/index.ts)
Source: [`packages/core/session/src/index.ts:345`](../../packages/core/session/src/index.ts)
## `ctx.subagents` — `SubagentService`