refactor: simplify session log representation

This commit is contained in:
Tianyi Cui
2026-07-13 23:56:10 +08:00
parent d060c0dd4f
commit 1123e946c0
64 changed files with 522 additions and 1032 deletions
+17 -27
View File
@@ -37,7 +37,7 @@ Source: [`packages/ui/user-approval/src/index.ts:95`](../packages/ui/user-approv
#### `approval/policy` — log-only
The session's approval policy was switched — log-only, durable, replayable, never in the model transcript (the model learns the policy from the prompt section and the narrator's notices). The LAST such event is the session's override (effectiveApprovalPolicy); who asked for it is derivable from position (an event after the log's last `request/header*` was a runtime switch by the user).
The session's approval policy was switched — log-only, durable, replayable, never in the model transcript (the model learns the policy from the prompt section and the narrator's notices). The LAST such event is the session's override (effectiveApprovalPolicy); who asked for it is derivable from position (an event after the log's last `request/header` was a runtime switch by the user).
```ts persistence-catalog
'approval/policy': { policy: ApprovalPolicy }
@@ -57,7 +57,7 @@ Raw stream chunk — token-level replay fidelity.
Types: [StreamChunk](core-data-structures/llm-streaming.md)
Source: [`packages/core/session/src/types.ts:322`](../packages/core/session/src/types.ts)
Source: [`packages/core/session/src/types.ts:287`](../packages/core/session/src/types.ts)
#### `assistant/message` — surface
@@ -69,13 +69,13 @@ Assembled assistant message for one step (derived history uses this). Carries th
Types: [ContentBlock](core-data-structures/core.md) · [TokenUsage](core-data-structures/llm-streaming.md)
Source: [`packages/core/session/src/types.ts:329`](../packages/core/session/src/types.ts)
Source: [`packages/core/session/src/types.ts:294`](../packages/core/session/src/types.ts)
### `bash/*`
#### `bash/sandbox-mode` — log-only
The session's sandbox mode was switched — log-only (like `approval/*`; NOT a surface event, carries no `surfaceOp`): durable and replayable, never in the model transcript. The LAST such event is the session's override (effectiveSandboxMode); who asked for it is derivable from position (an event after the log's last `request/header*` was a runtime switch by the user; see the tool layer's narrator).
The session's sandbox mode was switched — log-only (like `approval/*`; NOT a surface event, carries no `surfaceOp`): durable and replayable, never in the model transcript. The LAST such event is the session's override (effectiveSandboxMode); who asked for it is derivable from position (an event after the log's last `request/header` was a runtime switch by the user; see the tool layer's narrator).
```ts persistence-catalog
'bash/sandbox-mode': { mode: SandboxMode }
@@ -129,7 +129,7 @@ In-session context injection (file-change notices, subdir AGENTS.md, skill conte
Types: [ContentBlock](core-data-structures/core.md) · [MessageSource](core-data-structures/core.md)
Source: [`packages/core/session/src/types.ts:320`](../packages/core/session/src/types.ts)
Source: [`packages/core/session/src/types.ts:285`](../packages/core/session/src/types.ts)
### `hook/*`
@@ -165,29 +165,19 @@ A queued prompt an `agent/prompt-submit` listener VETOED — the durable record
Types: [ContentBlock](core-data-structures/core.md) · [MessageSource](core-data-structures/core.md)
Source: [`packages/core/session/src/types.ts:314`](../packages/core/session/src/types.ts)
Source: [`packages/core/session/src/types.ts:279`](../packages/core/session/src/types.ts)
### `request/*`
#### `request/header` — log-only
Full snapshot of the EpochHeader the NEXT request is built under, with the RequestHeaderReason it was recorded whole. Appended by the loop inside the step, before dispatch, on a loop instance's first request-building step (`'initial'`/`'resume'`) or when a delta failed its round-trip guard (`'fallback'`); always records what the request actually used, post-`agent/request`. Anchors the header fold: reconstruction reads the latest snapshot and applies the deltas after it. NOT a SurfaceEventType: it produces no LLM message — it is the request envelope, logged so every request is a pure function of the session log (the reconstructability RFC).
Full snapshot of the EpochHeader the NEXT request is built under, with the RequestHeaderReason it was recorded whole. Appended by the loop inside the step, before dispatch, on a loop instance's first request-building step (`'initial'`/`'resume'`) or when a later request's header changes (`'change'`); always records what the request actually used, post-`agent/request`. Reconstruction reads the latest snapshot. NOT a SurfaceEventType: it produces no LLM message — it is the request envelope, logged so every request is a pure function of the session log (the reconstructability RFC).
```ts persistence-catalog
'request/header': { header: EpochHeader; reason: RequestHeaderReason }
```
Source: [`packages/core/session/src/types.ts:374`](../packages/core/session/src/types.ts)
#### `request/header-delta` — log-only
Amendment to the folded EpochHeader: at least one of a SystemDelta, a ToolsDelta, a whole replacement LlmCallConfig (four scalars — not worth diffing), or a whole replacement session prefix (`messagePrefix` — small advisory content, replaced whole; an EMPTY array encodes the transition to "none", mirroring the canonical form's absent field — the loop never produces one in practice: the prefix is composed once per instance and anchored by that instance's snapshot, so this arm exists for codec totality). Appended by the loop inside the step, before dispatch, when the header for this request differs from the fold of the log so far; the writer verifies `applyHeaderDelta(previous, delta)` reproduces the new header exactly and falls back to a `'fallback'` `request/header` snapshot when it cannot, so a logged delta ALWAYS round-trips. NOT a SurfaceEventType.
```ts persistence-catalog
'request/header-delta': { system?: SystemDelta; tools?: ToolsDelta; config?: LlmCallConfig; messagePrefix?: Message[] }
```
Source: [`packages/core/session/src/types.ts:391`](../packages/core/session/src/types.ts)
Source: [`packages/core/session/src/types.ts:338`](../packages/core/session/src/types.ts)
### `steering/*`
@@ -201,7 +191,7 @@ Steering content injected between steps of a running turn.
Types: [ContentBlock](core-data-structures/core.md) · [MessageSource](core-data-structures/core.md)
Source: [`packages/core/session/src/types.ts:347`](../packages/core/session/src/types.ts)
Source: [`packages/core/session/src/types.ts:312`](../packages/core/session/src/types.ts)
### `step/*`
@@ -213,7 +203,7 @@ Closes step `step` of turn `turn`.
'step/end': { turn: number; step: number }
```
Source: [`packages/core/session/src/types.ts:301`](../packages/core/session/src/types.ts)
Source: [`packages/core/session/src/types.ts:266`](../packages/core/session/src/types.ts)
#### `step/start` — log-only
@@ -223,7 +213,7 @@ Opens step `step` of turn `turn` — one model call plus the tool executions it
'step/start': { turn: number; step: number }
```
Source: [`packages/core/session/src/types.ts:299`](../packages/core/session/src/types.ts)
Source: [`packages/core/session/src/types.ts:264`](../packages/core/session/src/types.ts)
### `todo/*`
@@ -239,7 +229,7 @@ NOT a SurfaceEventType: it produces no LLM message and never reaches `deriveMess
Types: [TodoItem](core-data-structures/session.md)
Source: [`packages/core/session/src/types.ts:361`](../packages/core/session/src/types.ts)
Source: [`packages/core/session/src/types.ts:326`](../packages/core/session/src/types.ts)
### `tool/*`
@@ -253,7 +243,7 @@ The model requested one tool invocation: `name` with the raw `arguments` JSON st
Types: [CallId](core-data-structures/core.md)
Source: [`packages/core/session/src/types.ts:335`](../packages/core/session/src/types.ts)
Source: [`packages/core/session/src/types.ts:300`](../packages/core/session/src/types.ts)
#### `tool/code-dispatch` — log-only
@@ -277,7 +267,7 @@ A completed tool call's model-facing result, plus an optional tool-private `meta
Types: [CallId](core-data-structures/core.md) · [ContentBlock](core-data-structures/core.md)
Source: [`packages/core/session/src/types.ts:345`](../packages/core/session/src/types.ts)
Source: [`packages/core/session/src/types.ts:310`](../packages/core/session/src/types.ts)
### `turn/*`
@@ -291,7 +281,7 @@ Closes turn `turn` with the TurnEndReason that ended it. The loop fires the awai
Types: [TurnEndReason](core-data-structures/session.md)
Source: [`packages/core/session/src/types.ts:297`](../packages/core/session/src/types.ts)
Source: [`packages/core/session/src/types.ts:262`](../packages/core/session/src/types.ts)
#### `turn/start` — log-only
@@ -303,7 +293,7 @@ Opens turn `turn`. `trigger` records what started it — a drained message batch
Types: [TurnTrigger](core-data-structures/session.md)
Source: [`packages/core/session/src/types.ts:291`](../packages/core/session/src/types.ts)
Source: [`packages/core/session/src/types.ts:256`](../packages/core/session/src/types.ts)
### `user/*`
@@ -317,4 +307,4 @@ A user-visible prompt (queued message drained at turn start).
Types: [ContentBlock](core-data-structures/core.md) · [MessageSource](core-data-structures/core.md)
Source: [`packages/core/session/src/types.ts:303`](../packages/core/session/src/types.ts)
Source: [`packages/core/session/src/types.ts:268`](../packages/core/session/src/types.ts)