Documentation
¶
Overview ¶
Package sessnap provides a stable, JSON-friendly serialization ("snapshot") of a session.Session that the store adapters (memstore, jsonlstore) share.
The Session aggregate exposes its lifecycle data through exported fields (ID, State, Mode, Conversation, Limits, Counters, EnvironmentRef, CreatedAt) and through the PendingAsk, PendingAuthorization, and PendingWorkspaceEnrollment accessors. Four pieces of its state are unexported and not directly addressable from outside the session package:
- pending *PendingAsk — readable via Session.PendingAsk() (only while StateAwaiting) and restorable via Session.PauseForApproval() (only from StateRunning). The snapshot round-trips it for the awaiting case.
- pendingAuthorization *PendingAuthorization — readable through a deep-copy accessor while StateAuthorizing and restored through PauseForAuthorization. Its private DTO preserves effective tool-argument bytes exactly.
- pendingWorkspaceEnrollment *PendingWorkspaceEnrollment — safe pre-prompt correlation restored through BeginWorkspaceEnrollment.
- stop StopReason — the recorded terminal stop reason. It is captured faithfully via Session.RecordedStopReason() (which performs no limit derivation) and restored via the matching terminal transition Complete/Stop/Cancel/Fail. Capturing the recorded value directly means the snapshot no longer has to infer the reason from the conflated Session.StopReason(), so terminal round-trips are exact.
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ErrNilSession = errors.New("sessnap: nil session")
ErrNilSession is returned by Of when given a nil session.
Functions ¶
func RestoreState ¶
func RestoreState(s *session.Session, data RestoreData) error
RestoreState drives a fresh idle Session to the supplied current state.
func ValidatePersistedAuthority ¶
ValidatePersistedAuthority rejects an authority claim that cannot represent a usable derived capability set. Callers must distinguish a nil authority pointer caused by a genuinely absent legacy field before calling it.
Types ¶
type RestoreData ¶ added in v0.15.0
type RestoreData struct {
State session.State
Stop session.StopReason
Pending *session.PendingAsk
PendingAuthorization *session.PendingAuthorization
Counters session.Counters
TokenUsage map[session.UsageKind]session.TokenUsage
Failure session.RetryMetadata
RetryPending bool
Retry session.RetryMetadata
LastError string
}
RestoreData is the adapter-owned complete lifecycle state used to rehydrate a freshly constructed session without positional compatibility parameters.
type Snapshot ¶
type Snapshot struct {
ID session.SessionID `json:"id"`
State session.State `json:"state"`
Mode session.PermissionMode `json:"mode"`
Limits session.Limits `json:"limits"`
Counters session.Counters `json:"counters"`
ExternalBinding session.ExternalBinding `json:"external_binding,omitempty"`
CreatedAt time.Time `json:"created_at"`
Incarnation session.IncarnationID `json:"incarnation,omitempty"`
Messages []messageDTO `json:"messages"`
Pending *session.PendingAsk `json:"pending,omitempty"`
// PendingAuthorization is present exactly while StateAuthorizing. Its private
// DTO base64-encodes tool arguments so JSON normalization cannot change bytes.
PendingAuthorization *pendingAuthorizationDTO `json:"pending_authorization,omitempty"`
// PendingWorkspaceEnrollment contains only safe enrollment correlation; no
// endpoint, credential, callback, or discovered-service state is persisted.
PendingWorkspaceEnrollment *session.PendingWorkspaceEnrollment `json:"pending_workspace_enrollment,omitempty"`
StopReason session.StopReason `json:"stop_reason,omitempty"`
// Kind and Relationship are the validated producer taxonomy from ADR 0217.
// A missing kind is legacy data and restores as unknown (fail-closed).
Kind session.SessionKind `json:"kind,omitempty"`
Relationship session.SessionRelationship `json:"relationship,omitzero"`
// Profile is the session's opaque tool-surface profile label. omitempty keeps a
// v1 snapshot with no "profile" key decoding to "" (the default profile) —
// purely additive, no format-tag bump (the same precedent as ProviderPhase /
// Parts).
Profile string `json:"profile,omitempty"`
// ProviderID and ModelID are the session's opaque neutral provider+model
// selector pair. omitempty keeps a v1 snapshot with no key decoding to the empty
// pair ("server default") — additive, no version bump. Persisting them lets a
// restarted process re-derive the SAME per-session engine via the factory.
ProviderID string `json:"provider_id,omitempty"`
ModelID string `json:"model_id,omitempty"`
// ReasoningEffort is the session's opaque neutral reasoning-effort token (ADR
// 0055). omitempty keeps a pre-0055 snapshot with no key decoding to "" (unset)
// — additive, no version bump. Persisting it lets a restarted process re-mint the
// SAME per-session engine (the same-effort adapter) via the factory.
ReasoningEffort string `json:"reasoning_effort,omitempty"`
// DebugMCPServers names only the configured server-global MCP servers selected
// for a debug session. DebugMCPTools is the exact direct-tool ceiling captured
// at creation; neither field contains URLs, headers, or connection details.
DebugMCPServers []string `json:"debug_mcp_servers,omitempty"`
DebugMCPTools []string `json:"debug_mcp_tools,omitempty"`
// DebugTargetFingerprint is the non-projectable target-incarnation binding.
DebugTargetFingerprint string `json:"debug_target_fingerprint,omitempty"`
// Title is the session's human-readable label seeded from the first genuine
// user prompt. omitempty keeps a pre-Title snapshot with no "title" key
// decoding to "" — additive, no format-tag bump (the same precedent as
// Profile / ProviderID / Parts). Persisting it lets a restarted process show
// the label without re-deriving it. It is an inert stored label (like
// Profile), restored by direct assignment, NOT a state transition.
Title string `json:"title,omitempty"`
TitleProvenance session.TitleProvenance `json:"title_provenance,omitempty"`
// TitleRevision is the title-specific durable metadata revision. omitempty
// preserves the zero value for legacy snapshots.
TitleRevision uint64 `json:"title_revision,omitempty"`
// TitleGeneration metadata is distinct from main Usage and conversation.
TitleGeneration session.TitleGenerationState `json:"title_generation,omitempty"`
TitleSourcePrompts []string `json:"title_source_prompts,omitempty"`
TitleAttempts []session.TitleAttempt `json:"title_attempts,omitempty"`
// TokenUsage is the canonical durable usage ledger. The writer always emits it;
// an omitted empty ledger decodes to the zero value.
TokenUsage map[session.UsageKind]session.TokenUsage `json:"token_usage"`
// LatestContextOccupancy is the optional, display-only context-meter numerator
// from the last completed turn. A missing field remains unknown for legacy snapshots.
LatestContextOccupancy *session.ContextOccupancy `json:"latest_context_occupancy,omitempty"`
// RetryDisposition and StreamProgress are the typed terminal facts for a failed
// model stream. Missing fields decode conservatively to unknown.
RetryDisposition session.RetryDisposition `json:"retry_disposition,omitempty"`
StreamProgress session.StreamProgress `json:"stream_progress,omitempty"`
// RetryPending persists the consumed failed-step retry intent across the crash window
// between preparation and terminal completion. Its metadata remains separate
// from failed-state metadata because the prepared aggregate is idle/running.
RetryPending bool `json:"retry_pending,omitempty"`
RetryPendingDisposition session.RetryDisposition `json:"retry_pending_disposition,omitempty"`
RetryPendingProgress session.StreamProgress `json:"retry_pending_progress,omitempty"`
// LastError records a StateFailed session's terminal failure CAUSE
// (session.RecordLastError, the Permanent-analog for the failure detail).
// omitempty keeps a pre-#332 snapshot with no "last_error" key decoding to ""
// — purely additive, no format-tag bump (the same precedent as Permanent). It
// is normalised at stamp time (one line, rune-clamped), mirroring the
// event-side subagentCausePayload so the snapshot and the subagent.end event
// carry the same persisted cause.
LastError string `json:"last_error,omitempty"`
// RunID is the opaque, host-minted identity of the run this session is
// currently driving or most recently drove (ADR 0249). Persisting it is what
// makes an awaiting-approval resume continue THE SAME run across a process
// restart: the resume path reads it back and reuses it instead of minting a
// new one.
//
// omitempty keeps a pre-0245 snapshot with no "run_id" key decoding to "" —
// purely additive, no format-tag bump (the Profile/ProviderID/Usage
// precedent). A legacy session restores with no run id and is stamped on its
// next run; there is no migration sweep.
RunID string `json:"run_id,omitempty"`
// Owner is the verified caller the session is attributed to (ADR 0204). A
// POINTER for true omitempty: an ownerless session emits no "owner" key, so a
// pre-ship snapshot decodes to a nil owner and an ownerless snapshot stays
// byte-identical to a pre-ship one — purely additive, no format-tag bump.
// Restored via the write-once aggregate method Session.RestoreLabels, NOT a
// RestoreState parameter (widening that signature would be a Changed/breaking
// entry under engine/COMPATIBILITY.md; a direct-assignment field is
// Added/minor).
Owner *session.Principal `json:"owner,omitempty"`
// Authority is the plain, derived capability payload. A nil pointer is a
// genuinely pre-feature legacy record; a present payload must decode to the
// one governance.CapabilitySet representation or restore fails closed.
Authority *session.Authority `json:"authority,omitempty"`
// EnvironmentRef is the sole durable execution-environment identity. It is
// required and must contain the exact provider revision used for reattachment.
EnvironmentRef session.EnvironmentRef `json:"environment_ref"`
// Placement is safe display-only metadata and is never used for reattachment.
Placement session.PlacementMetadata `json:"placement,omitempty"`
}
Snapshot is the on-the-wire form of a session.Session. It is a plain data struct with JSON tags so it serializes deterministically regardless of the (untagged) layout of the domain types.