Documentation
¶
Overview ¶
Package contextstate is the CLI's durable context contract layer. It composes the upstream mivia-ai-sdk/contextstate transport structs with the CLI's identity, redaction, worktree, and lifecycle extensions.
The byte-identical subset (shape constants and the ref-mint primitives) is re-exported from mivia-ai-sdk/contextstate so every CLI caller sees the SDK's canonical implementation under one symbol. The divergent subset (ContentRef with the CLI's "ctxp_<hex>" primary-key namespace, CheckpointID with the CLI's SummaryModel field, the commit/checkpoint records with the CLI's Principal, fingerprint, and worktree-instance fields, and the 13 CLI sentinel errors) stays as distinct local types so the CLI's failure modes and persisted shape do not move with an SDK release.
Index ¶
- Constants
- Variables
- func Digest(chunks ...[]byte) string
- func EffectiveCheckpointMetadataLimit() int
- func EffectiveSummaryMetadataLimit() int
- func Exceeds(size, bound int) bool
- func FingerprintCommitRequest(r CommitRequest) (string, error)
- func IsRef(s string) bool
- func MarshalCanonical(value any) ([]byte, error)
- func Mint(chunks ...[]byte) string
- func NewContentRef(namespace, workspaceID, sessionID, subjectID string, chunks ...[]byte) (sdkctx.ContentRef, error)
- func NormalizeSessionTitle(title string) (string, error)
- func ParseCatalogTimestamp(s string) time.Time
- func PayloadChunkSize() int
- func SetLimits(limits Limits)
- func UnmarshalCanonical(data []byte, target any) error
- func ValidSessionDir(dir string) bool
- func ValidateSourceEvent(event SourceEvent) error
- func ValidateSourceEvents(events []SourceEvent, sessionID string, firstSequence uint64) error
- type AdvanceRequest
- type AuditAction
- type AuditRecord
- type BindingRevision
- type CheckpointID
- type CheckpointRecord
- type CommitRequest
- type ContentRef
- type CutoverState
- type DeleteResult
- type EnsureSessionRequest
- type ExportResult
- type ImportResult
- type LegacyImporter
- type Limits
- type PayloadRecord
- type PolicySnapshot
- type Principal
- type RedactionPolicy
- type RetentionClass
- type Revision
- type RollbackToken
- type SanitizedPayload
- type SessionAdmission
- type SessionAdmissionCatalog
- type SessionCatalog
- type SessionCatalogInfo
- type SessionFirstMessageSource
- type SessionLeaseRenewer
- type SessionLifecycle
- type SessionLiveError
- type SessionReclaimer
- type SessionSaveOptions
- type SessionTitleCatalog
- type Snapshot
- type SourceEvent
- type SourceID
- type SourceMapping
- type SourceRange
- type SourceReader
- type Store
- type ValidationError
- type WorktreeAdmissionCatalog
- type WorktreeInstance
- type WorktreeInstanceInfo
- type WorktreeInstanceState
- type WorktreeRouteCatalog
- type WorktreeSessionCatalog
- type WorktreeStore
Constants ¶
const ( // MaxIdentifierBytes is the byte cap on every transport identifier. MaxIdentifierBytes = sdkctx.MaxIdentifierBytes // MaxPayloadReferenceBytes is the byte cap on a payload reference. MaxPayloadReferenceBytes = sdkctx.MaxPayloadReferenceBytes // MaxSourceRangeEvents is the inclusive span that keeps range arithmetic honest. MaxSourceRangeEvents = sdkctx.MaxSourceRangeEvents // HashPrefix is the SDK's canonical content-address prefix. HashPrefix = sdkctx.HashPrefix // Namespace is the CLI's local payload namespace. The SDK exposes // none, and the CLI's ContentRef rejects every other value at // Validate time, so this stays local. Namespace = "mivia.context.payload.v1" // DefaultMaxCheckpointMetadata bounds a checkpoint's summary_metadata column. DefaultMaxCheckpointMetadata = 16 * 1024 // DefaultMaxSummaryMetadata bounds the persisted summary envelope. DefaultMaxSummaryMetadata = 12 * 1024 // MaxAuditBytes bounds an audit record's serialized size. MaxAuditBytes = 1 * 1024 )
Shape bounds the SDK pins FOR the transport structs, re-exported so callers read "contextstate.MaxIdentifierBytes" rather than reaching into the SDK directly. Volume bounds live in the local Limits type (limits.go); they are operator-owned and uncapped by default.
const DefaultPayloadChunkBytes = 64 << 10 // 64 KiB
DefaultPayloadChunkBytes is the built-in source-event payload chunk size when SourceEventBytes is 0 (uncapped volume). Large payloads are split into ordered chunks of this size under one content ref; they are never rejected for whole-payload size under defaults.
const MaxSessionDirBytes = 4096
MaxSessionDirBytes bounds the stored session directory string so a hostile or corrupt row cannot inflate every picker payload without limit.
const MaxSessionTitleBytes = 256
MaxSessionTitleBytes bounds a title that the terminal can render safely.
Variables ¶
var ( // ErrInvalidDTO wraps every CLI DTO validation failure. ErrInvalidDTO = errors.New("invalid context DTO") // ErrPrincipalMismatch marks a payload whose owner tuple does not match the writing principal. ErrPrincipalMismatch = errors.New("principal mismatch") // ErrSessionNotFound marks a read of an unknown session. ErrSessionNotFound = errors.New("session not found") // ErrSessionTombstoned marks a read of a session that has been deleted. ErrSessionTombstoned = errors.New("session tombstoned") // ErrPayloadNotFound marks a read of an unknown payload. ErrPayloadNotFound = errors.New("payload not found") // ErrPayloadRevoked marks a Get of a payload marked revoked. ErrPayloadRevoked = errors.New("payload revoked") // ErrExportTooLarge marks a context export that broke the ExportBytes bound. ErrExportTooLarge = errors.New("context export too large") ErrSummaryUnavailable = errors.New("summary unavailable") // ErrStaleRevision marks a commit against a moved revision. ErrStaleRevision = errors.New("stale revision") // ErrStaleBinding marks a commit against a moved binding. ErrStaleBinding = errors.New("stale binding") // ErrCheckpointConflict marks a reused operation key carrying a different request. ErrCheckpointConflict = errors.New("checkpoint conflict") // ErrWorktreeDeleted marks a commit or read against a deleted worktree instance. ErrWorktreeDeleted = errors.New("worktree session deleted") // ErrPromptBudgetExceeded marks a prompt that broke the model's input budget. ErrPromptBudgetExceeded = errors.New("prompt budget exceeded") // ErrSessionLiveElsewhere marks a ReclaimSession attempt against a session // whose current owner's lease is still fresh (an actively-heartbeating // process), rather than the session being unknown, tombstoned, or owned by // a different subject/managed worktree. ErrSessionLiveElsewhere = errors.New("context session is live in another process") )
CLI sentinels. The names intentionally overlap with the SDK's sentinels (ErrSessionNotFound, ErrStaleRevision, ...); callers write errors.Is(err, contextstate.ErrSessionNotFound) and resolve to the CLI's, not the SDK's, so storage code that wraps %w produces a caller-visible chain that points back at this package.
Functions ¶
func Digest ¶
Digest returns the SDK's SHA-256 of the ordered concatenation of chunks, as 64 lowercase hex characters. The CLI never mixes namespace or owner fields into the digest.
func EffectiveCheckpointMetadataLimit ¶
func EffectiveCheckpointMetadataLimit() int
EffectiveCheckpointMetadataLimit returns the operator-configured checkpoint metadata bound, falling back to the compiled-in default.
func EffectiveSummaryMetadataLimit ¶
func EffectiveSummaryMetadataLimit() int
EffectiveSummaryMetadataLimit returns the operator-configured summary metadata bound, falling back to the compiled-in default when uncapped.
func Exceeds ¶
Exceeds is exceedsLimit for hosts outside this package, so every layer asks the same question about a bound and a zero never reads as "allow nothing".
func FingerprintCommitRequest ¶
func FingerprintCommitRequest(r CommitRequest) (string, error)
FingerprintCommitRequest hashes the canonical request fields while omitting the fingerprint itself. Storage uses it to distinguish safe retries from a reused operation key carrying different state.
func IsRef ¶
IsRef reports whether ref matches the SDK's canonical "sha256:<64 hex>" shape. The CLI's own contentRefID mints "ctxp_<hex>" strings that fail this check, which is the point: a CLI reference is not an SDK reference.
func MarshalCanonical ¶
MarshalCanonical encodes a DTO with sorted object keys and no insignificant whitespace. Validation remains the responsibility of the DTO's Validate method; this function only canonicalizes the JSON representation.
func Mint ¶
Mint returns the SDK's canonical content address of the concatenated chunks: HashPrefix plus Digest. The CLI's own contentRefID is a different function with a different prefix.
func NewContentRef ¶
func NewContentRef(namespace, workspaceID, sessionID, subjectID string, chunks ...[]byte) (sdkctx.ContentRef, error)
NewContentRef mints an SDK-shaped ContentRef. The CLI's own contentRefID minter lives in sanitize.go.
func NormalizeSessionTitle ¶
NormalizeSessionTitle validates and trims user-facing session title text.
func ParseCatalogTimestamp ¶
ParseCatalogTimestamp parses a SessionCatalogInfo timestamp written by either producer (see sqliteDefaultTimestampLayout). It returns the zero time when s does not match either layout, mirroring time.Parse's error contract for callers that already treat a parse failure as "unknown".
func PayloadChunkSize ¶
func PayloadChunkSize() int
PayloadChunkSize returns the effective per-chunk byte size for source-event payloads. Zero / negative SourceEventBytes settles to DefaultPayloadChunkBytes so storage always has a finite chunk granularity without whole-payload reject.
func SetLimits ¶
func SetLimits(limits Limits)
SetLimits installs the operator's durable ceilings process-wide. The host calls it once during startup from configuration, exactly as it installs the redaction policy; a process that never calls it stays uncapped, so any path that runs before startup - tests, `mivia version`, a store constructed directly - is uncapped rather than falling back to a compiled ceiling.
func UnmarshalCanonical ¶
func ValidSessionDir ¶
ValidSessionDir reports whether dir is safe to persist: no NUL bytes and within the length bound. The empty string is valid (no directory recorded).
func ValidateSourceEvent ¶
func ValidateSourceEvent(event SourceEvent) error
ValidateSourceEvent is the named source-boundary validator used by storage and import adapters. The implementation delegates to the DTO validator so callers have one stable entry point for source records.
func ValidateSourceEvents ¶
func ValidateSourceEvents(events []SourceEvent, sessionID string, firstSequence uint64) error
Types ¶
type AdvanceRequest ¶
type AdvanceRequest struct {
OperationID string `json:"operation_id"`
Principal Principal `json:"principal"`
SessionID string `json:"session_id"`
Expected Revision `json:"expected"`
ExpectedBinding BindingRevision `json:"expected_binding"`
NewSession uint64 `json:"new_session"`
NewDurable uint64 `json:"new_durable"`
NewSourceSequence uint64 `json:"new_source_sequence"`
NewBinding BindingRevision `json:"new_binding"`
ActiveCheckpointID string `json:"active_checkpoint_id,omitempty"`
ClearActive bool `json:"clear_active"`
Reason string `json:"reason"`
WorktreeInstance WorktreeInstance `json:"worktree_instance,omitempty"`
}
func (AdvanceRequest) Validate ¶
func (r AdvanceRequest) Validate() error
type AuditAction ¶
type AuditAction string
const ( AuditDelete AuditAction = "delete" AuditExport AuditAction = "export" AuditImport AuditAction = "import" )
type AuditRecord ¶
type AuditRecord struct {
ID string `json:"id"`
Action AuditAction `json:"action"`
WorkspaceID string `json:"workspace_id"`
SessionID string `json:"session_id"`
SubjectID string `json:"subject_id"`
Revision uint64 `json:"revision"`
Size int `json:"size"`
Retention RetentionClass `json:"retention"`
CreatedAt time.Time `json:"created_at"`
ExpiresAt time.Time `json:"expires_at"`
}
type BindingRevision ¶
type BindingRevision struct {
Provider string `json:"provider"`
Model string `json:"model"`
Generation uint64 `json:"generation"`
}
BindingRevision names the provider-model pair and its generation.
func NewBindingRevision ¶
func NewBindingRevision(providerName, model string, generation uint64) (BindingRevision, error)
NewBindingRevision builds one BindingRevision and validates it.
func (BindingRevision) Validate ¶
func (b BindingRevision) Validate() error
Validate bounds both identifiers and requires a positive generation.
type CheckpointID ¶
type CheckpointID struct {
SessionID string `json:"session_id"`
SourceRange SourceRange `json:"source_range"`
Algorithm string `json:"algorithm"`
SchemaVersion uint32 `json:"schema_version"`
SummaryModel string `json:"summary_model"`
IdempotencyKey string `json:"idempotency_key"`
}
CheckpointID identifies one checkpoint within a session. The CLI adds SummaryModel so storage can record which model authored the summary; the SDK has no such field, so this type stays local.
func NewCheckpointID ¶
func NewCheckpointID(sessionID string, sourceRange SourceRange, algorithm string, schemaVersion uint32, summaryModel, key string) (CheckpointID, error)
NewCheckpointID builds one CheckpointID and validates it.
func (CheckpointID) Validate ¶
func (id CheckpointID) Validate() error
Validate enforces the identifier bounds, a valid same-session SourceRange, an Algorithm bounded at 64 bytes, a positive SchemaVersion, an optional bounded SummaryModel, and a bounded IdempotencyKey.
type CheckpointRecord ¶
type CheckpointRecord struct {
ID CheckpointID `json:"id"`
Revision Revision `json:"revision"`
Binding BindingRevision `json:"binding"`
SourceRange SourceRange `json:"source_range"`
ActiveContext []byte `json:"active_context"`
SummaryMetadata []byte `json:"summary_metadata"`
TurnID uint64 `json:"turn_id"`
Complete bool `json:"complete"`
}
CheckpointRecord is one committed state of a session with the CLI's summary metadata column and Complete flag. Distinct from the SDK's Checkpoint because storage persists Complete and SummaryMetadata.
func (CheckpointRecord) Validate ¶
func (c CheckpointRecord) Validate() error
Validate enforces a valid ID, a valid Binding, a SourceRange that matches the ID, a non-empty ActiveContext within the CheckpointBytes bound, a SummaryMetadata within the EffectiveCheckpointMetadataLimit, a positive TurnID, and that ActiveContext + SummaryMetadata fit the overall checkpoint bound.
type CommitRequest ¶
type CommitRequest struct {
OperationID string `json:"operation_id"`
Principal Principal `json:"principal"`
SessionID string `json:"session_id"`
Expected Revision `json:"expected"`
ExpectedBinding BindingRevision `json:"expected_binding"`
NewSourceEvents []SourceEvent `json:"new_source_events"`
Payloads []PayloadRecord `json:"payloads,omitempty"`
Checkpoint CheckpointRecord `json:"checkpoint"`
ActiveContext []byte `json:"active_context"`
NewSession uint64 `json:"new_session"`
NewDurable uint64 `json:"new_durable"`
NewSourceSequence uint64 `json:"new_source_sequence"`
NewBinding BindingRevision `json:"new_binding"`
TurnID uint64 `json:"turn_id"`
BaseDigest string `json:"base_digest"`
Fingerprint string `json:"fingerprint"`
WorktreeInstance WorktreeInstance `json:"worktree_instance,omitempty"`
}
func NewCommitRequest ¶
func NewCommitRequest(principal Principal, sessionID string, expected Revision, expectedBinding BindingRevision, events []SourceEvent, checkpoint CheckpointRecord, activeContext []byte, newBinding BindingRevision, turnID uint64) (CommitRequest, error)
func (CommitRequest) Validate ¶
func (r CommitRequest) Validate() error
type ContentRef ¶
type ContentRef struct {
Ref string `json:"ref"`
Namespace string `json:"namespace"`
SHA256 string `json:"sha256"`
WorkspaceID string `json:"workspace_id"`
SessionID string `json:"session_id"`
SubjectID string `json:"subject_id"`
Size int `json:"size"`
}
ContentRef is the CLI's durable address of one shared context blob. The SDK's ContentRef enforces Ref == HashPrefix+SHA256; the CLI uses "ctxp_<hex>" refs derived from the owner tuple so two principals with identical content do not collide on a global primary key. The two types share their field set and stay as two distinct Go types so the local validator can enforce the CLI's namespace.
func (ContentRef) Validate ¶
func (r ContentRef) Validate() error
Validate bounds the Ref, enforces the CLI namespace, requires a lowercase 64-character SHA-256, bounds the owner strings, and rejects a negative Size. The validator refuses any "sha256:"-prefixed Ref so an SDK reference cannot pass through the CLI's storage.
type CutoverState ¶
type DeleteResult ¶
type EnsureSessionRequest ¶
type EnsureSessionRequest struct {
Principal Principal `json:"principal"`
Binding BindingRevision `json:"binding"`
// Dir and Worktree record where the live session lives. They are written
// once with the session row and drive TUI session restore.
Dir string `json:"dir,omitempty"`
Worktree string `json:"worktree,omitempty"`
// WorktreeInstance binds this session to one physical managed worktree.
WorktreeInstance WorktreeInstance `json:"worktree_instance,omitempty"`
}
type ExportResult ¶
type ImportResult ¶
type ImportResult struct {
SessionID string `json:"session_id"`
SourceRange SourceRange `json:"source_range"`
Revision Revision `json:"revision"`
Imported int `json:"imported"`
IdempotencyKey string `json:"idempotency_key"`
Status string `json:"status"`
SourceMap []SourceMapping `json:"source_map"`
Cutover CutoverState `json:"cutover"`
Rollback RollbackToken `json:"rollback"`
PartialArtifacts []ContentRef `json:"partial_artifacts"`
Warnings []string `json:"warnings"`
}
type LegacyImporter ¶
type Limits ¶
type Limits struct {
// SourceEventBytes is the payload CHUNK size for durable source events
// ([context] max_source_event_bytes). 0 means use DefaultPayloadChunkBytes.
// It is NOT a whole-payload reject bound: multi-chunk payloads of any size
// reassemble under one content ref.
SourceEventBytes int
// CheckpointBytes bounds a checkpoint's serialized active context, which is
// the conversation the provider is sent. Its natural ceiling is the model's
// prompt budget, which the planner already enforces upstream.
CheckpointBytes int
// CommitEvents bounds how many messages one turn may publish.
CommitEvents int
// CommitEventBytes bounds the aggregate payload bytes of one turn.
CommitEventBytes int
// SessionStateBytes bounds a stored session's serialized message state.
SessionStateBytes int
// ExportBytes bounds a context export.
ExportBytes int
// SummaryMetadataBytes bounds the persisted summary envelope.
// Zero (uncapped by default) means the host imposes no compiled-in ceiling
// on model-generated summary content.
SummaryMetadataBytes int
// CheckpointMetadataBytes bounds the summary_metadata column within a
// checkpoint record. Zero means uncapped.
CheckpointMetadataBytes int
}
Limits is the single declaration of every durable context bound that scales with how much the user and the model actually said.
A ZERO field means UNCAPPED, and every field is zero by default. That is not an oversight, it is the lesson of the wedge this file exists to prevent: the bounds used to be compiled-in constants (32 KiB of active context, 64 KiB per message) sized for a demo, while the models this product ships against carry 200k-1M token windows and `read_file`, `grep` and `run_command` results are uncapped by default. The first turn in which the agent did real work therefore exceeded them, and because publication is one transaction the WHOLE commit was refused - no source events, no checkpoint, no operation row. An active context only grows, so that turn wedged the session permanently and history stopped persisting with no way back.
A durable bound must never be able to destroy work the agent already finished. Anything set here is a deliberate operator ceiling, chosen by someone who knows their storage, not a default this binary imposes.
Bounds that describe SHAPE rather than volume stay compiled in, because they are correctness invariants rather than capacity policy: identifier and reference lengths, the source-range span that keeps range arithmetic honest, and the host-authored metadata envelopes the summarizer produces.
func CurrentLimits ¶
func CurrentLimits() Limits
CurrentLimits returns the installed ceilings, or the uncapped default.
func DefaultLimits ¶
func DefaultLimits() Limits
DefaultLimits is the shipped policy: every volume bound uncapped.
type PayloadRecord ¶
type PayloadRecord struct {
Ref ContentRef `json:"ref"`
Retention RetentionClass `json:"retention"`
Revoked bool `json:"revoked"`
Data []byte `json:"data,omitempty"`
}
PayloadRecord is one stored payload under its content address. The field set matches the SDK's, but Ref is the CLI's local ContentRef (sha256:-prefixed SDK references do not pass Validate), so the type stays local.
func (PayloadRecord) Validate ¶
func (p PayloadRecord) Validate() error
Validate enforces a valid Ref, a non-empty Retention, and, when Data is present, a length and digest that match Ref.
type PolicySnapshot ¶
type PolicySnapshot struct {
SummaryEnabled bool `json:"summary_enabled"`
RedactionConfigured bool `json:"redaction_configured"`
Provider string `json:"provider"`
Model string `json:"model"`
CredentialScope string `json:"credential_scope"`
NetworkEnabled bool `json:"network_enabled"`
EndpointAllowlist []string `json:"endpoint_allowlist,omitempty"`
PolicyDigest string `json:"policy_digest"`
}
PolicySnapshot exposes the resolved redaction and credential policy to the runtime so a UI surface can render the operator's ceiling.
type Principal ¶
type Principal struct {
WorkspaceID string `json:"workspace_id"`
SessionID string `json:"session_id"`
SubjectID string `json:"subject_id"`
// contains filtered or unexported fields
}
Principal is the CLI's three-tuple identity plus a per-process capability secret. The SDK has no equivalent; storage persists the capability digest alongside the owner tuple so a second handle with matching strings cannot authorize reads or writes.
func NewPrincipal ¶
NewPrincipal mints a Principal with a fresh capability secret.
func (Principal) CapabilityDigest ¶
CapabilityDigest is the durable, non-reversible identity of this principal handle. Storage persists this digest alongside the owner tuple so a second handle with matching strings cannot authorize reads or writes.
type RedactionPolicy ¶
type RedactionPolicy struct {
Configured bool `json:"configured"`
Patterns []string `json:"patterns,omitempty"`
KeyNames []string `json:"key_names,omitempty"`
Classifier func([]byte) error `json:"-"`
// Redactor replaces sensitive spans in a source payload. It is supplied by
// the host so this package keeps one redaction implementation rather than
// growing a second that drifts from it. Without one, a flagged payload is
// stored as metadata only - never refused.
Redactor func([]byte) []byte `json:"-"`
}
RedactionPolicy is host-owned classifier configuration. A policy with no configured classifier is intentionally treated as unconfigured.
func (RedactionPolicy) Classify ¶
func (policy RedactionPolicy) Classify(data []byte) error
Classify applies the host-owned redaction rules without minting a content reference. Summary validation uses the same classifier before model output can be persisted or sent to a provider.
type RetentionClass ¶
type RetentionClass string
RetentionClass labels how long a payload is kept.
const ( // RetentionSession keeps a payload for the session's lifetime. RetentionSession RetentionClass = "session" // RetentionCompliance keeps a payload past session deletion. RetentionCompliance RetentionClass = "compliance" )
type Revision ¶
type Revision struct {
Session uint64 `json:"session"`
Durable uint64 `json:"durable"`
Source uint64 `json:"source"`
}
Revision is a session's three counters. It carries no Validate; the commit rules compare it as a whole.
func NewRevision ¶
NewRevision builds one Revision from its three counters.
type RollbackToken ¶
type SanitizedPayload ¶
type SanitizedPayload struct {
Ref ContentRef `json:"ref"`
Bytes []byte `json:"bytes,omitempty"`
HashOnly bool `json:"hash_only"`
Dereferenceable bool `json:"dereferenceable"`
Revoked bool `json:"revoked"`
Retention RetentionClass `json:"retention"`
}
SanitizedPayload is the CLI's content-addressed payload shape with the redaction outcome attached.
func SanitizeSourcePayload ¶
func SanitizeSourcePayload(ctx context.Context, principal Principal, data []byte, policy RedactionPolicy) (SanitizedPayload, error)
SanitizeSourcePayload is the host boundary before any context bytes are persisted. Unconfigured policies deliberately produce metadata only.
type SessionAdmission ¶
type SessionAdmission struct {
Agent string `json:"agent"`
Digest string `json:"digest"`
Names []string `json:"names"`
}
SessionAdmission is a named session's deferred-tool admission record (plan tools/05 D3). Names are the tools admitted into the surface; Agent and Digest identify the agent binding and tier split they were admitted against, so a resume against a changed split can drop them fail-closed.
type SessionAdmissionCatalog ¶
type SessionAdmissionCatalog interface {
SaveSessionAdmission(context.Context, Principal, string, SessionAdmission) error
LoadSessionAdmission(context.Context, Principal, string) (SessionAdmission, error)
}
SessionAdmissionCatalog is the optional durable surface for admission records. A store that does not implement it simply resumes with no admitted tools, which is the fail-closed direction.
type SessionCatalog ¶
type SessionCatalog interface {
SaveSession(context.Context, Principal, string, []byte, string, string, int, int, int, SessionSaveOptions) error
LoadSession(context.Context, Principal, string) ([]byte, SessionCatalogInfo, error)
ListSessions(context.Context, Principal) ([]SessionCatalogInfo, error)
DeleteSessionSnapshot(context.Context, Principal, string) error
PruneSessionSnapshots(context.Context, Principal, []string) error
}
SessionCatalog is the durable user-facing transcript surface. It is optional on the low-level context Store so memory/test stores need not implement named persistence.
type SessionCatalogInfo ¶
type SessionCatalogInfo struct {
SessionID string `json:"session_id,omitempty"`
Title string `json:"title,omitempty"`
Name string `json:"name"`
Model string `json:"model"`
Provider string `json:"provider"`
CreatedAt string `json:"created_at"`
UpdatedAt string `json:"updated_at"`
TurnCount int `json:"turn_count"`
TokenCount int `json:"token_count"`
MessageCount int `json:"message_count"`
// Dir is the absolute directory the session was created or used in.
Dir string `json:"dir,omitempty"`
// Worktree is the mivia worktree name when Dir lies inside one.
Worktree string `json:"worktree,omitempty"`
// WorktreeRoute marks a route that starts a new session in a worktree.
// It does not contain a chat transcript or model binding.
WorktreeRoute bool `json:"worktree_route,omitempty"`
// WorktreeInstance retains the exact managed worktree for picker actions.
WorktreeInstance WorktreeInstance `json:"worktree_instance,omitempty"`
}
SessionCatalogInfo is the metadata exposed to user-facing session pickers. Messages remain opaque to this package and are carried as canonical bytes. Dir and Worktree record where the session lived; the TUI restores that directory when the session is opened.
type SessionFirstMessageSource ¶
type SessionFirstMessageSource interface {
FirstUserMessage(context.Context, Principal, string) (string, error)
}
SessionFirstMessageSource resolves the first user message of a live context session for display titling. It is optional: a store that does not implement it simply leaves sessions untitled. The lookup is subject-scoped, never capability-scoped, so stale-capability rows (older runs) can still be titled.
type SessionLeaseRenewer ¶ added in v0.1.2
type SessionLeaseRenewer interface {
RenewLease(ctx context.Context, principal Principal, sessionID string) error
ReleaseLease(ctx context.Context, principal Principal, sessionID string) error
}
SessionLeaseRenewer is the optional surface a live process uses to prove to ReclaimSession that it is still actively working a session, so a second process resuming the same session id cannot silently evict it mid-turn. RenewLease is scoped by capability_digest (not just subject) so a process whose capability was already reclaimed away cannot resurrect its own stale lease and block the process that legitimately took over.
ReleaseLease clears a lease this process is voluntarily giving up (a clean shutdown), so the NEXT resume of this same session id does not have to wait out the staleness TTL just because this process quit before its lease happened to expire on its own - without this, a heartbeat that had renewed even once looks "live" to ReclaimSession for the full TTL after the owning process is already gone, and an ordinary "quit, then resume" within that window is refused as ErrSessionLiveElsewhere even though nothing is actually still using the session.
type SessionLifecycle ¶
type SessionLiveError ¶ added in v0.1.2
SessionLiveError is the typed refusal ReclaimSession returns while another process's lease is still fresh. It wraps ErrSessionLiveElsewhere and carries what the refused caller can act on: how old the holder's last heartbeat is, and how long until the lease expires and takeover succeeds. Without these two numbers the refusal is indistinguishable from "broken" - the user cannot tell a 10-second wait from a permanent failure.
func (*SessionLiveError) Error ¶ added in v0.1.2
func (e *SessionLiveError) Error() string
func (*SessionLiveError) Unwrap ¶ added in v0.1.2
func (e *SessionLiveError) Unwrap() error
type SessionReclaimer ¶
type SessionReclaimer interface {
ReclaimSession(context.Context, Principal, string) (Snapshot, error)
}
SessionReclaimer is the optional surface that lets a resumed process take over write ownership of an existing, non-tombstoned live context session. A session's owner capability is minted fresh and only ever held in the process that created it (Principal.capability), so a later process that legitimately knows the session's id - the same id LoadSession/ DeleteSessionSnapshot already accept scoped only to workspace+subject, with no capability check - is trusted to reclaim it for resumed commits. Without this, a resumed session can read its prior history but every subsequent turn commits under the resuming process's own, unrelated session id instead of updating the one the caller asked to resume.
type SessionSaveOptions ¶
type SessionSaveOptions struct {
Dir string
Worktree string
WorktreeInstance WorktreeInstance
// SessionID declares the live context session this save projects ("id is
// id, name is name"). The storage layer stamps chat_sessions.session_id
// with it only when it matches the catalog name and a live row exists at
// write time; every other shape keeps the row a plain snapshot copy.
SessionID string
// SessionRevision stamps the live session's session_revision as of this
// save, so a later LoadSession can tell "nothing has advanced the head
// since this snapshot was taken" (safe to serve when there is no
// completed checkpoint) apart from "a clear or a commit happened after
// this snapshot" (the snapshot is stale). Only stored when SessionID is
// also stamped; nil means unknown (e.g. a plain named copy), and the
// storage layer then treats the row conservatively, exactly as it did
// before this field existed.
SessionRevision *uint64
}
SessionSaveOptions carries the optional metadata written with a named session snapshot. The zero value is valid and records no directory.
type SessionTitleCatalog ¶
type SessionTitleCatalog interface {
SetSessionTitle(context.Context, Principal, string, string, WorktreeInstance) error
}
SessionTitleCatalog stores optional display metadata for a bound context session.
type Snapshot ¶
type Snapshot struct {
Revision Revision `json:"revision"`
Binding BindingRevision `json:"binding"`
Active CheckpointRecord `json:"active"`
Source []SourceEvent `json:"source"`
Tombstoned bool `json:"tombstoned"`
}
Snapshot is the read model of one session. Tombstoned marks a session that DeleteSession removed.
type SourceEvent ¶
type SourceEvent struct {
ID SourceID `json:"id"`
Kind string `json:"kind"`
Role string `json:"role"`
ToolCallID string `json:"tool_call_id,omitempty"`
PayloadRef string `json:"payload_ref,omitempty"`
Provenance string `json:"provenance"`
RedactionStatus string `json:"redaction_status"`
Size int `json:"size"`
}
SourceEvent is one durable event in a session's source log. The field set matches the SDK's; the local Validate wraps ErrInvalidDTO so the CLI's failure mode does not move with an SDK release.
func (SourceEvent) Validate ¶
func (e SourceEvent) Validate() error
Validate bounds the four required text fields at 256 bytes, the two optional fields when set, and rejects a negative Size.
type SourceID ¶
SourceID names one event: a session and a sequence number. The local Validate wraps ErrInvalidDTO so the CLI's failure mode does not move with an SDK release; the SDK's Validate wraps ErrInvalidRecord.
func NewSourceID ¶
NewSourceID builds one SourceID and validates it.
type SourceMapping ¶
type SourceRange ¶
SourceRange spans events of one session, inclusive of both ends.
func NewSourceRange ¶
func NewSourceRange(start, end SourceID) (SourceRange, error)
NewSourceRange builds one SourceRange and validates it.
func (SourceRange) Validate ¶
func (r SourceRange) Validate() error
Validate enforces one session, an ordered span, and a span under MaxSourceRangeEvents.
type SourceReader ¶
type SourceReader interface {
ReadRange(context.Context, Principal, SourceRange) ([]SourceEvent, error)
ReadPayload(context.Context, Principal, ContentRef) (SanitizedPayload, error)
}
type ValidationError ¶
ValidationError retains the field that made a DTO invalid while allowing callers to use errors.Is(err, ErrInvalidDTO).
func (*ValidationError) Error ¶
func (e *ValidationError) Error() string
Error renders the sentinel, the field, and the reason.
func (*ValidationError) Unwrap ¶
func (e *ValidationError) Unwrap() error
Unwrap reports the sentinel under every validation failure.
type WorktreeAdmissionCatalog ¶
type WorktreeAdmissionCatalog interface {
SaveWorktreeSessionAdmission(context.Context, Principal, string, SessionAdmission, WorktreeInstance) error
LoadWorktreeSessionAdmission(context.Context, Principal, string, WorktreeInstance) (SessionAdmission, error)
}
type WorktreeInstance ¶
WorktreeInstance identifies one lifetime of a managed worktree. The random ID prevents an old process from using a same-name replacement.
func (WorktreeInstance) IsZero ¶
func (i WorktreeInstance) IsZero() bool
IsZero reports whether no managed worktree binding exists.
func (WorktreeInstance) Validate ¶
func (i WorktreeInstance) Validate() error
Validate rejects a partial or unsafe worktree binding.
type WorktreeInstanceInfo ¶
type WorktreeInstanceInfo struct {
Instance WorktreeInstance
CanonicalPath string
State WorktreeInstanceState
}
WorktreeInstanceInfo is the catalog record for one physical worktree.
type WorktreeInstanceState ¶
type WorktreeInstanceState string
WorktreeInstanceState is the durable lifecycle state of one instance.
const ( WorktreeCreating WorktreeInstanceState = "creating" WorktreeActive WorktreeInstanceState = "active" WorktreeDeleting WorktreeInstanceState = "deleting" WorktreeDeleted WorktreeInstanceState = "deleted" )
type WorktreeRouteCatalog ¶
type WorktreeRouteCatalog interface {
SaveWorktreeRoute(context.Context, Principal, string, string) error
DeleteWorktreeRoute(context.Context, Principal, string) (int64, error)
}
WorktreeRouteCatalog stores launch routes for mivia-managed worktrees. A route is separate from a chat session because it has no model binding.
type WorktreeSessionCatalog ¶
type WorktreeSessionCatalog interface {
BeginWorktreeCreation(context.Context, Principal, WorktreeInstance, string) error
RegisterWorktreeInstance(context.Context, Principal, WorktreeInstance, string) error
AbandonWorktreeCreation(context.Context, Principal, WorktreeInstance) error
BeginWorktreeDeletion(context.Context, Principal, WorktreeInstance) error
DeleteWorktreeSessions(context.Context, Principal, WorktreeInstance) (int, error)
LoadWorktreeSession(context.Context, Principal, string, WorktreeInstance) ([]byte, SessionCatalogInfo, error)
ListWorktreeSessions(context.Context, Principal, WorktreeInstance) ([]SessionCatalogInfo, error)
DeleteWorktreeSessionSnapshot(context.Context, Principal, string, WorktreeInstance) error
PruneWorktreeSessionSnapshots(context.Context, Principal, []string, WorktreeInstance) error
}
WorktreeSessionCatalog controls a managed worktree session lifecycle. The caller supplies the immutable instance to prevent same-name reuse.
type WorktreeStore ¶
type WorktreeStore interface {
LoadWorktree(context.Context, Principal, string, WorktreeInstance) (Snapshot, error)
}
WorktreeStore is the optional scoped read surface for a managed worktree. Implementations reject a non-active or mismatched physical instance.