The persistence seam is now create/open/stat/list returning per-session SessionHandles (read/append/flush/close); every log read and write flows through the owning handle. The seam package exports only the service and handle contracts, consumer-visible errors, and pure durable-data validation helpers; each backend owns its complete storage runtime, and the shared contract suites pin equivalent observable behavior. The backend routes published sessions' live events by id into the active write handle; agent-loop only acquires, seeds, and closes the handle. Resume appends interruptedTurnClosers through its write handle; session-query owns the revision-keyed cold cache. Legacy-only surfaces are removed in the same swap: locate/readRaw/supportsRawArtifacts, the legacy event-shape read migration, zstd torn-frame salvage, DSH_SESSION_JSONL, and hook transcript_path population; a torn final zstd frame is discarded whole; the session-list cold blank probe returns on stat metadata (eventCount derived from the last physical row, sizeBytes). The WebUI ZIP export serializes the logical log from a read handle, so both backends export identically. Refs #3245
6.2 KiB
description, kind
| description | kind |
|---|---|
| Host and Client session control: create, resume, prompt, follow history, and project live session state. | package-reference |
Session Controller
English | 中文
Summary
@deepseek-ai/dsh-api-session-controller owns the Host ctx.sessionController service and the generated Client session, skills, and fileReferences Remote namespaces. It serves Session lifecycle and history, the Host-generation model catalog, workspace-path opening, user-invocable skill discovery, and the adapter for Agent-scoped file references. Use it through API Gateway when a Client needs operations addressed by a Session.
Table of Contents
Use this package
History pages and follow opening snapshots carry a discriminated SessionHistoryRecord. Both variants use { type, event }: type: 'event' carries one raw SessionWireEvent, while type: 'chunks' carries one lossless ChunkRowEvent for consecutive same-block assistant/chunk deltas. Both inner values expose type, seq, time, and data, so the Client retains each accepted record as one SessionEventLikeEntry without record-by-record conversion. A packed event's seq and time identify its first member, and data retains the fragment and timestamp-gap arrays. Live follow frames remain individual event records. Tool arguments, result content, failures, and tool/result.data.meta pass through unchanged; the controller does not resolve a Tool definition, run a presenter, or attach UI data.
Each endpoint states its activation policy. List, search, attachment, history pages, log following, skill discovery, and workspace-path opening can inspect persistence without activating an Agent; canOpenWorkspacePath() reports native-opening availability without addressing a Session. Queue mutation and cancellation require live state; model, rename, prompt, and file-reference operations may resolve or resume an ordinary Session. Create and fork are the only operations that create a new Agent directly. The skill catalog instead uses a live Agent when present or the recorded preset's standing scope when cold, so listing never starts an Agent.
The Client adapter exposes SessionEventStream, a Gateway RemoteJournalStream bound to one ordinary or direct-subagent address. It opens follow before the initial page, publishes only contiguous replace, prepend, and append changes, and repairs reconnect or sequence gaps through a tail page. Backwards paging has two verbs: loadOlder() pulls one 50-message page, and loadThrough(seq) — the turn-jump loader — loops 200-message pages until the window covers the target seq, lowering a shared target on repeated calls, stopping on a page that makes no progress, and reporting busy through the same loadingOlder snapshot bit. Ordinary records cover [event.seq, event.seq]; packed rows cover [event.seq, event.seq + memberCount - 1]. A business, persistence, or unresolved continuity failure terminates the stream, while only physical carrier loss selects automatic resumption. SessionControlStream is a Gateway RemoteSnapshotStream; every generation opens with a complete process-local baseline, so reconnect replaces queue, jobs, and projection state instead of treating transient values as durable events.
The Session object also carries local submission echoes: session.beginSubmission inserts one into SessionSnapshot.pendingSubmissions synchronously, before the caller serializes and prompts, so a conversation UI can show the message on the submit click's own frame. Session derives each echo's transcript, queued, or steering placement from its current running state and the requested delivery mode, then retains that placement while serialization is in flight. The prompt's requestId is the correlation identity: the Host echoes it as the durable user source's rpcId, and queue occurrences project it as SessionQueuedItem.rpcId. An echo retires one animation frame after its durable event or queue occurrence is observed (the delay keeps it renderable until the replacement is ready), immediately when its identified prompt fails or is abandoned, and as failed on disposal; each retirement fires the registered onRetire callback exactly once. Echoes are Client memory only; reload and reconnect rebuild the conversation from durable events alone.
Configuration
| Field | Default | Meaning |
|---|---|---|
coldBlankProbeMaxEvents |
16 |
Maximum stat-reported event count of a cold Session eligible for blankness verification; 0 disables the event-count gate |
coldBlankProbeMaxBytes |
1,024 |
Maximum stat-reported artifact byte size of a cold Session eligible for blankness verification when the backend offers no event count; 0 disables the byte-size gate |
nativeOpen |
platform-detected | Whether Session workspace paths can be handed to a native desktop opener |
The generated configuration catalog is the exhaustive source for accepted fields and their JSDoc.
Model Experience
None, as invoked Agent commands own any model-visible effect.
KV Cache effect
No direct effect; model requests remain owned by the Agent and LLM packages.
Known Limitations and Deferred Work
- Control baselines represent process-local state and therefore cannot reconstruct jobs after a Host restart.
- A failed follow resumption remains visible to the caller instead of retrying indefinitely.
- File-reference completion uses the shared Agent lookup and can resume a cold Session; the
skills/listcatalog is the non-activating alternative for skill metadata.
Dev Note
Working context for maintainers — click to expand
None.
Runtime invariant: No companion is published. Every page and frame is checked against the addressed durable Session.