Documentation
¶
Index ¶
- Constants
- Variables
- func CountDispatchedProviderToolOperations(snapshots []ProviderToolOperationSnapshot, ...) int
- func DeleteSessionByUUID(uuid string) (bool, error)
- func IsConfigurableSessionTool(SessionTool) bool
- func ListAllSessions() (map[string][]SessionMeta, error)
- func ListProjectMeta() (map[string]ProjectMeta, error)
- func LoadArtifactRecords(id string) ([]artifact.Record, error)
- func LoadLastSession(project string) string
- func LoadSessionModeStrict(id string) (string, error)
- func LoadSessionToolOverrides(id string) (map[SessionTool]SessionToolOverride, error)
- func MarkArtifactViewed(sessionID, artifactID string, revision int) error
- func PruneOldToolOutputs(msgs []adk.Message, protectTurns int) []adk.Message
- func ReplayGenerationOperations(entries []Entry) map[string]GenerationOperationSnapshot
- func ReplayProviderToolOperations(entries []Entry) map[string]ProviderToolOperationSnapshot
- func ReplaySessionToolOverrides(entries []Entry) map[SessionTool]SessionToolOverride
- func SaveLastSession(project, id string)
- func TruncateToolOutput(output, sessionUUID, toolCallID string) string
- func ValidateGenerationStart(operation GenerationOperation) error
- func ValidateGenerationTransition(previous, next GenerationOperation) error
- func ValidateProviderToolStart(operation ProviderToolOperation) error
- func ValidateProviderToolTransition(previous, next ProviderToolOperation) error
- func ValidateSessionID(id string) error
- type DispatchPolicy
- type Entry
- type EntryImage
- type EntryType
- type GenerationOperation
- type GenerationOperationSnapshot
- type GenerationOperationState
- type GenerationRecoveryPriority
- type GoalSnapshot
- type OperationCapabilityKey
- type PlanSnapshot
- type ProjectMeta
- type ProviderToolOperation
- type ProviderToolOperationSnapshot
- type ProviderToolOperationState
- type Recorder
- func (r *Recorder) Close()
- func (r *Recorder) CompareAndSwapSessionToolOverride(tool SessionTool, persisted bool, expectedRevision uint64) (SessionToolOverride, error)
- func (r *Recorder) HasRecording() bool
- func (r *Recorder) Model() string
- func (r *Recorder) Project() string
- func (r *Recorder) Provider() string
- func (r *Recorder) RecordArtifact(record artifact.Record) error
- func (r *Recorder) RecordAssistant(content string)
- func (r *Recorder) RecordAssistantMessage(message *schema.Message)
- func (r *Recorder) RecordCompact(summary string, compactedN, keptN int)
- func (r *Recorder) RecordGenerationDispatch(operation GenerationOperation, policy DispatchPolicy) error
- func (r *Recorder) RecordGenerationOperation(operation GenerationOperation) error
- func (r *Recorder) RecordGoalUpdate(objective, status string, tokensUsed, createdAt, updatedAt int64)
- func (r *Recorder) RecordModeChange(mode string)
- func (r *Recorder) RecordModeChangeStrict(mode string) error
- func (r *Recorder) RecordPlanUpdate(status, title, content, feedback string)
- func (r *Recorder) RecordProviderToolDispatch(operation ProviderToolOperation, policy DispatchPolicy) error
- func (r *Recorder) RecordProviderToolOperation(operation ProviderToolOperation) error
- func (r *Recorder) RecordSubagentAsync(name, taskID, agentType string)
- func (r *Recorder) RecordSubagentResult(name, output string, err error)
- func (r *Recorder) RecordSubagentStart(name, agentType string)
- func (r *Recorder) RecordSystemPrompt(prompt, envInfo string)
- func (r *Recorder) RecordTodoSnapshot(todos []TodoSnapshotItem)
- func (r *Recorder) RecordToolCall(name, args, toolCallID, batchID string, batchIndex, batchSize int)
- func (r *Recorder) RecordToolObservation(observation ToolObservation)
- func (r *Recorder) RecordToolResult(name, output, toolCallID string, err error, denied bool, ...) (string, error)
- func (r *Recorder) RecordToolResultWithDetails(name, output, toolCallID string, err error, denied bool, ...) (string, error)
- func (r *Recorder) RecordUser(content string, images ...EntryImage)
- func (r *Recorder) SessionToolOverrides() (map[SessionTool]SessionToolOverride, error)
- func (r *Recorder) SetAgent(agent string)
- func (r *Recorder) SetModel(model string)
- func (r *Recorder) SetTitleFor(id, title string)
- func (r *Recorder) SetTitleRefiner(fn func(firstUserMsg string))
- func (r *Recorder) SetUUID(id string)
- func (r *Recorder) TruncateAtUserMessage(beforeCount int) error
- func (r *Recorder) UUID() string
- type SessionMeta
- type SessionState
- type SessionTool
- type SessionToolOverride
- type SessionToolOverrideRevisionError
- type TodoSnapshotItem
- type ToolObservation
- type ToolResultDetails
Constants ¶
const ( // MaxOutputBytes is the maximum byte size of a tool output before truncation. MaxOutputBytes = 50 * 1024 // 50 KB // MaxOutputLines is the maximum line count of a tool output before truncation. MaxOutputLines = 2000 // HeadLines is the number of lines to preserve from the beginning. HeadLines = 200 // TailLines is the number of lines to preserve from the end. TailLines = 500 )
const InterruptedToolOutput = "[Interrupted before result was recorded]"
InterruptedToolOutput is the placeholder content backfilled for tool calls whose result never made it to disk (user stop, process kill, or a recording gap). It tells the model what happened instead of fabricating an output. The runner records the same marker for interrupted calls so live sessions and reconstructed history stay identical.
Variables ¶
var ( // ErrDispatchSessionLimit means the durable consume count already reached // the policy cap. Callers must not invoke the provider. ErrDispatchSessionLimit = errors.New("provider call limit reached for this session") // ErrDispatchOperationExists prevents reuse of an operation identifier from // creating another provider side effect while counting as one operation. ErrDispatchOperationExists = errors.New("provider operation already exists") )
var ( // ErrArtifactNotFound reports that an opaque artifact ID is not present in // the requested session. ErrArtifactNotFound = errors.New("artifact not found") // ErrArtifactRevisionMismatch prevents a stale viewer from marking a newer // artifact revision as read. ErrArtifactRevisionMismatch = errors.New("artifact revision changed") )
var ErrSessionToolOverrideRevision = errors.New("session tool override revision conflict")
Functions ¶
func CountDispatchedProviderToolOperations ¶ added in v0.12.3
func CountDispatchedProviderToolOperations( snapshots []ProviderToolOperationSnapshot, capabilityKey, providerProfileID string, ) int
CountDispatchedProviderToolOperations counts durable consume points for one capability/provider pair. Empty filters match all values.
func DeleteSessionByUUID ¶ added in v0.6.1
DeleteSessionByUUID removes a session (index entry + JSONL file) located by uuid across ALL projects. The web task tree can delete a task that does not belong to the active project, so we must not assume a single project key. Returns false if no session with that uuid exists. The JSONL file is only removed when the uuid was actually found in the index, which also prevents a crafted uuid from deleting an arbitrary file.
func IsConfigurableSessionTool ¶ added in v0.12.3
func IsConfigurableSessionTool(SessionTool) bool
IsConfigurableSessionTool always returns false. ParseSessionTool and the journal replay/CAS methods remain available only for historical records.
func ListAllSessions ¶ added in v0.3.4
func ListAllSessions() (map[string][]SessionMeta, error)
ListAllSessions returns all sessions across all projects, keyed by project path.
func ListProjectMeta ¶ added in v0.11.1
func ListProjectMeta() (map[string]ProjectMeta, error)
ListProjectMeta returns the per-project metadata (last-activity timestamps) keyed by project path. A nil map (legacy install: no projects.json yet) is returned as-is; callers fall back to deriving recency from sessions. Lock-free like ListSessions/ListAllSessions: writers persist via atomic rename, so readers always observe a complete file.
func LoadArtifactRecords ¶ added in v0.12.1
LoadArtifactRecords rebuilds the latest metadata revision for every Artifact in a session. Entry order is not trusted: the greatest revision wins, with a later timestamp breaking ties for defensive recovery from duplicated lines.
func LoadLastSession ¶ added in v0.10.1
LoadLastSession returns the last foregrounded session uuid for project, or "" when none is recorded — or when the recorded session no longer exists on disk (deleted, or a "new chat" that was never written), so callers fall back to a fresh session instead of resurrecting a stale id.
func LoadSessionModeStrict ¶ added in v0.12.3
LoadSessionModeStrict reads the latest durable unified mode without the conversational replay loader's corrupt-line tolerance. A malformed line could itself be a newer mode transition, so authorization restore must fail closed rather than silently skipping it and reviving an older Full access value. An empty result is the legacy/default Approval mode.
func LoadSessionToolOverrides ¶ added in v0.12.3
func LoadSessionToolOverrides(id string) (map[SessionTool]SessionToolOverride, error)
LoadSessionToolOverrides replays the latest persisted override for a session.
func MarkArtifactViewed ¶ added in v0.12.3
MarkArtifactViewed advances exactly one artifact's revision cursor. It is serialized with artifact journal appends so a concurrent new revision is always left unseen. The operation never advances the legacy session-wide timestamp.
func PruneOldToolOutputs ¶ added in v0.4.6
PruneOldToolOutputs replaces old tool result outputs with actionable placeholders, protecting the most recent turns from pruning. This implements the Tier 1.5 "placeholder compression" strategy: recent tool outputs are preserved verbatim; older ones are replaced with hints telling the model how to recover the data.
protectTurns is the number of recent user turns to protect (default 2). Returns the pruned messages slice (same backing array, modified in place).
func ReplayGenerationOperations ¶ added in v0.12.3
func ReplayGenerationOperations(entries []Entry) map[string]GenerationOperationSnapshot
ReplayGenerationOperations rebuilds the latest monotonic projection for each operation and separately remembers whether its durable consume point was observed. It tolerates corrupted/out-of-order lines conservatively: terminal evidence never regresses to a progress state, while dispatch evidence is sticky for ledger reconstruction.
func ReplayProviderToolOperations ¶ added in v0.12.3
func ReplayProviderToolOperations(entries []Entry) map[string]ProviderToolOperationSnapshot
ReplayProviderToolOperations conservatively rebuilds one snapshot per operation. Terminal evidence always outranks a later nonterminal line; malformed entries are ignored and dispatch evidence remains sticky.
func ReplaySessionToolOverrides ¶ added in v0.12.3
func ReplaySessionToolOverrides(entries []Entry) map[SessionTool]SessionToolOverride
ReplaySessionToolOverrides projects the latest valid revision for each allowlisted tool. The greatest revision wins rather than line order, so a duplicated or out-of-order line cannot roll state backwards.
func SaveLastSession ¶ added in v0.10.1
func SaveLastSession(project, id string)
SaveLastSession records id as the last foregrounded session for project. Best-effort: persistence must never break session switching, and callers run outside any engine lock (file I/O).
func TruncateToolOutput ¶ added in v0.4.6
TruncateToolOutput truncates a tool output string if it exceeds size limits. It preserves head + tail lines and writes the full content to disk. Returns the (possibly truncated) output. If no truncation is needed, the original string is returned unchanged.
sessionUUID is used to namespace the overflow files. toolCallID identifies the specific tool call.
func ValidateGenerationStart ¶ added in v0.12.3
func ValidateGenerationStart(operation GenerationOperation) error
ValidateGenerationStart is the pre-dispatch guard used before the first journal append. Recovery code may append a terminal repair entry to a legacy transcript, so RecordGenerationOperation validates shape but deliberately leaves first-state policy to this explicit helper.
func ValidateGenerationTransition ¶ added in v0.12.3
func ValidateGenerationTransition(previous, next GenerationOperation) error
ValidateGenerationTransition enforces monotonic state and immutable intent. Duplicate transitions are allowed so crash recovery can append idempotently.
func ValidateProviderToolStart ¶ added in v0.12.3
func ValidateProviderToolStart(operation ProviderToolOperation) error
ValidateProviderToolStart must be called before the first synchronous journal append and before invoking the external endpoint.
func ValidateProviderToolTransition ¶ added in v0.12.3
func ValidateProviderToolTransition(previous, next ProviderToolOperation) error
ValidateProviderToolTransition permits exactly one terminal transition and enforces immutable approved intent. Duplicate state writes are accepted for idempotent repair, but a terminal state can never change.
func ValidateSessionID ¶ added in v0.3.3
ValidateSessionID checks that a session ID is safe for use as a filename. It rejects empty IDs, path traversal sequences, and path separators.
Types ¶
type DispatchPolicy ¶ added in v0.12.3
type DispatchPolicy struct {
Tool SessionTool
MaxPerSession int
}
DispatchPolicy binds a prepared billable tool to its hard session cap.
type Entry ¶
type Entry struct {
Type EntryType `json:"type"`
UUID string `json:"uuid,omitempty"`
Project string `json:"project,omitempty"`
Provider string `json:"provider,omitempty"`
Model string `json:"model,omitempty"`
Agent string `json:"agent,omitempty"`
Content string `json:"content,omitempty"`
Name string `json:"name,omitempty"` // tool name
Args string `json:"args,omitempty"` // tool args JSON
Output string `json:"output,omitempty"` // tool output
Error string `json:"error,omitempty"` // tool error
ToolCallID string `json:"tool_call_id,omitempty"` // links tool_call ↔ tool_result
Timestamp string `json:"timestamp"`
// Typed tool/generation correlation. These additive fields are shared by
// operation journal and enhanced tool-result entries.
OperationID string `json:"operation_id,omitempty"`
Outcome string `json:"outcome,omitempty"`
ErrorCode string `json:"error_code,omitempty"`
ArtifactIDs []string `json:"artifact_ids,omitempty"`
// Tool-call batch fields. Tool calls issued by one assistant message share
// a BatchID; legacy files simply lack these keys (unmarshal to zero values,
// i.e. "no batch info").
BatchID string `json:"batch_id,omitempty"`
BatchIndex int `json:"batch_index,omitempty"`
BatchSize int `json:"batch_size,omitempty"`
// tool_result semantics. Denied marks a user-rejected approval (replay
// renders it struck-through, not as an error); DurationMs is the runner's
// approval-wait-adjusted execution latency. Legacy files lack both keys.
Denied bool `json:"denied,omitempty"`
DurationMs int64 `json:"duration_ms,omitempty"`
// Images attached to a user message.
Images []EntryImage `json:"images,omitempty"`
// OpaqueResponseItems carries only bounded encrypted Responses API
// reasoning items. Cleartext ReasoningContent is intentionally never
// persisted. Legacy JSONL files simply omit this additive field.
OpaqueResponseItems []json.RawMessage `json:"opaque_response_items,omitempty"`
// plan_update fields
PlanStatus string `json:"plan_status,omitempty"`
PlanTitle string `json:"plan_title,omitempty"`
PlanContent string `json:"plan_content,omitempty"`
Feedback string `json:"feedback,omitempty"`
// todo_snapshot fields
Todos []TodoSnapshotItem `json:"todos,omitempty"`
// subagent_start / subagent_result fields
SubagentName string `json:"subagent_name,omitempty"`
SubagentType string `json:"subagent_type,omitempty"`
// mode_change field
Mode string `json:"mode,omitempty"`
// compact fields. KeptN is the number of trailing messages the live agent
// kept verbatim after the summary; replay re-attaches that many entries
// from before the compact event. Legacy files lack kept_n (unmarshals to
// 0), which replays as "summary only" — the pre-KeptN behaviour.
Summary string `json:"summary,omitempty"`
CompactedN int `json:"compacted_n,omitempty"`
KeptN int `json:"kept_n,omitempty"`
// system_prompt fields
EnvInfo string `json:"env_info,omitempty"` // serialized environment snapshot
// goal_update fields. GoalStatus == "cleared" marks goal removal.
GoalObjective string `json:"goal_objective,omitempty"`
GoalStatus string `json:"goal_status,omitempty"`
GoalTokensUsed int64 `json:"goal_tokens_used,omitempty"`
GoalCreatedAt int64 `json:"goal_created_at,omitempty"`
GoalUpdatedAt int64 `json:"goal_updated_at,omitempty"`
// tool_observation fields
ToolObservation *ToolObservation `json:"tool_observation,omitempty"`
// Artifact fields. Content and absolute paths are never persisted. A missing
// storage kind is a legacy workspace record.
ArtifactID string `json:"artifact_id,omitempty"`
ArtifactPath string `json:"artifact_path,omitempty"`
ArtifactStorageKind string `json:"artifact_storage_kind,omitempty"`
ArtifactKey string `json:"artifact_key,omitempty"`
ArtifactTitle string `json:"artifact_title,omitempty"`
ArtifactKind string `json:"artifact_kind,omitempty"`
ArtifactMediaType string `json:"artifact_media_type,omitempty"`
ArtifactSize int64 `json:"artifact_size,omitempty"`
ArtifactWidth int `json:"artifact_width,omitempty"`
ArtifactHeight int `json:"artifact_height,omitempty"`
ArtifactSHA256 string `json:"artifact_sha256,omitempty"`
ArtifactProviderID string `json:"artifact_provider_id,omitempty"`
ArtifactModelID string `json:"artifact_model_id,omitempty"`
ArtifactParentID string `json:"artifact_parent_id,omitempty"`
ArtifactRevision int `json:"artifact_revision,omitempty"`
ArtifactFocus bool `json:"artifact_focus,omitempty"`
// generation_operation fields.
OperationState string `json:"operation_state,omitempty"`
OperationCapabilityKey *OperationCapabilityKey `json:"operation_capability_key,omitempty"`
OperationCredentialFingerprint string `json:"operation_credential_fingerprint,omitempty"`
OperationConfigEpoch uint64 `json:"operation_config_epoch,omitempty"`
OperationIdempotencyKey string `json:"operation_idempotency_key,omitempty"`
OperationProviderRequestIDHash string `json:"operation_provider_request_id_hash,omitempty"`
OperationUpdatedAt string `json:"operation_updated_at,omitempty"`
// provider_tool_operation fields. These entries deliberately persist only
// metadata hashes and stable identifiers: never tool arguments, raw
// credentials, endpoint URLs, response bodies, or result content.
ProviderToolState string `json:"provider_tool_state,omitempty"`
ProviderToolRunID string `json:"provider_tool_run_id,omitempty"`
ProviderToolCapabilityKey string `json:"provider_tool_capability_key,omitempty"`
ProviderToolProviderProfileID string `json:"provider_tool_provider_profile_id,omitempty"`
ProviderToolName string `json:"provider_tool_name,omitempty"`
ProviderToolIntentHash string `json:"provider_tool_intent_hash,omitempty"`
ProviderToolConfigEpoch string `json:"provider_tool_config_epoch,omitempty"`
ProviderToolIdempotencyKey string `json:"provider_tool_idempotency_key,omitempty"`
ProviderToolUpdatedAt string `json:"provider_tool_updated_at,omitempty"`
// session_tool_override fields. Persisted is deliberately separate from
// runtime availability/effectiveness: those are evaluated from the current
// engine configuration and must never be replayed as durable truth.
SessionToolOverrideTool string `json:"session_tool_override_tool,omitempty"`
SessionToolOverridePersisted bool `json:"session_tool_override_persisted,omitempty"`
SessionToolOverrideRevision uint64 `json:"session_tool_override_revision,omitempty"`
}
Entry is one line of the JSONL session file.
func LoadSession ¶
LoadSession reads all entries from a session JSONL file identified by uuid.
type EntryImage ¶ added in v0.4.1
type EntryImage struct {
MimeType string `json:"media_type"`
Data string `json:"data"` // base64-encoded
}
EntryImage stores a single image attached to a user message.
type EntryType ¶
type EntryType string
EntryType identifies the kind of JSONL record.
const ( EntrySessionStart EntryType = "session_start" EntryUser EntryType = "user" EntryAssistant EntryType = "assistant" EntryToolCall EntryType = "tool_call" EntryToolResult EntryType = "tool_result" // Extended entry types for structured state tracking. EntryPlanUpdate EntryType = "plan_update" EntryTodoSnapshot EntryType = "todo_snapshot" EntrySubagentStart EntryType = "subagent_start" EntrySubagentResult EntryType = "subagent_result" EntrySubagentAsync EntryType = "subagent_async" EntryModeChange EntryType = "mode_change" EntryAgentChange EntryType = "agent_change" EntryCompact EntryType = "compact" EntryBudgetWarning EntryType = "budget_warning" EntrySystemPrompt EntryType = "system_prompt" EntryGoalUpdate EntryType = "goal_update" EntryToolObservation EntryType = "tool_observation" EntryArtifact EntryType = "artifact" EntryGenerationOperation EntryType = "generation_operation" EntryProviderToolOperation EntryType = "provider_tool_operation" EntrySessionToolOverride EntryType = "session_tool_override" )
type GenerationOperation ¶ added in v0.12.3
type GenerationOperation struct {
OperationID string `json:"operation_id"`
ToolCallID string `json:"tool_call_id"`
State GenerationOperationState `json:"state"`
CapabilityKey OperationCapabilityKey `json:"capability_key"`
CredentialFingerprint string `json:"credential_fingerprint"`
ConfigEpoch uint64 `json:"config_epoch"`
IdempotencyKey string `json:"idempotency_key"`
ProviderRequestIDHash string `json:"provider_request_id_hash,omitempty"`
ArtifactIDs []string `json:"artifact_ids,omitempty"`
ErrorCode string `json:"error_code,omitempty"`
UpdatedAt time.Time `json:"updated_at"`
}
GenerationOperation is one immutable-intent state transition. Secret credentials, prompts, signed URLs, and provider response bodies are never persisted here.
type GenerationOperationSnapshot ¶ added in v0.12.3
type GenerationOperationSnapshot struct {
Latest GenerationOperation `json:"latest"`
Dispatched bool `json:"dispatched"`
}
GenerationOperationSnapshot is the replay projection used to rebuild the atomic session ledger. Dispatched remains true once a dispatch_attempted entry was observed, independent of later success or failure.
func LoadGenerationOperations ¶ added in v0.12.3
func LoadGenerationOperations(id string) ([]GenerationOperationSnapshot, error)
LoadGenerationOperations reads one session and returns snapshots sorted by operation ID for deterministic callers and tests.
type GenerationOperationState ¶ added in v0.12.3
type GenerationOperationState string
GenerationOperationState is a durable provider-dispatch state. Progress UI phases are ephemeral; these states exist to answer the crash-recovery question "could the provider already have accepted a billable request?".
const ( GenerationDispatchAttempted GenerationOperationState = "dispatch_attempted" GenerationAccepted GenerationOperationState = "accepted" GenerationSaving GenerationOperationState = "saving" GenerationSucceeded GenerationOperationState = "succeeded" GenerationFailed GenerationOperationState = "failed" GenerationUncertain GenerationOperationState = "uncertain" )
func (GenerationOperationState) IsTerminal ¶ added in v0.12.3
func (state GenerationOperationState) IsTerminal() bool
type GenerationRecoveryPriority ¶ added in v0.12.3
type GenerationRecoveryPriority int
GenerationRecoveryPriority formalizes the release ordering. Higher evidence wins: terminal operation > artifact > terminal tool result > nonterminal op.
const ( GenerationRecoveryNone GenerationRecoveryPriority = iota GenerationRecoveryNonTerminalOperation GenerationRecoveryTerminalToolResult GenerationRecoveryArtifact GenerationRecoveryTerminalOperation )
func GenerationRecoveryEvidencePriority ¶ added in v0.12.3
func GenerationRecoveryEvidencePriority( snapshot GenerationOperationSnapshot, hasVerifiedArtifact bool, hasTerminalToolResult bool, ) GenerationRecoveryPriority
GenerationRecoveryEvidencePriority returns the fixed reconciliation ordering without deciding transport presentation. A terminal operation always wins; otherwise a safely verified artifact outranks a typed terminal tool result, which outranks a nonterminal operation.
type GoalSnapshot ¶ added in v0.5.0
type GoalSnapshot struct {
Objective string
Status string
TokensUsed int64
CreatedAt int64
UpdatedAt int64
}
GoalSnapshot is the recoverable state of a session goal.
type OperationCapabilityKey ¶ added in v0.12.3
type OperationCapabilityKey struct {
ProviderProfileID string `json:"provider_profile_id"`
CredentialKind string `json:"credential_kind,omitempty"`
EndpointProfile string `json:"endpoint_profile"`
ModelID string `json:"model_id"`
}
OperationCapabilityKey is the metadata-only snapshot used by the durable journal. Runtime capability implementations map their key into this neutral representation; session replay never imports provider/config packages.
type PlanSnapshot ¶
PlanSnapshot holds the last known plan state from a session.
type ProjectMeta ¶ added in v0.11.1
type ProjectMeta struct {
UpdatedAt string `json:"updated_at,omitempty"` // RFC3339
}
ProjectMeta is project-level metadata kept in its own file (projects.json, alongside the session index). UpdatedAt is the project's "last activity" timestamp: it is bumped when a session is created or when a session's own UpdatedAt moves (a real turn), and — deliberately — is NEVER rolled back when a session is deleted. The sidebar sorts projects by this timestamp, so deleting a conversation must not reorder the project list.
Stored separately from session.json on purpose: older binaries rewriting the index don't know this data exists, and would silently drop an embedded "projects" section on their next read-modify-write (the index is shared across processes — desktop sidecar + CLI may run different versions). A sidecar file they never touch is immune; losing it only degrades the sidebar to session-derived recency, and the next turn re-stamps it.
type ProviderToolOperation ¶ added in v0.12.3
type ProviderToolOperation struct {
OperationID string `json:"operation_id"`
ToolCallID string `json:"tool_call_id"`
RunID string `json:"run_id"`
State ProviderToolOperationState `json:"state"`
CapabilityKey string `json:"capability_key"`
ProviderProfileID string `json:"provider_profile_id"`
ToolName string `json:"tool_name"`
IntentHash string `json:"intent_hash"`
ConfigEpoch string `json:"config_epoch"`
IdempotencyKey string `json:"idempotency_key"`
ErrorCode string `json:"error_code,omitempty"`
UpdatedAt time.Time `json:"updated_at"`
}
ProviderToolOperation is metadata-only durable evidence for a provider tool call. IntentHash binds the approved post-hook arguments and credential fingerprint without persisting either value. Tool arguments, credentials, endpoint URLs, provider bodies, and tool results must never be added here.
type ProviderToolOperationSnapshot ¶ added in v0.12.3
type ProviderToolOperationSnapshot struct {
Latest ProviderToolOperation `json:"latest"`
Dispatched bool `json:"dispatched"`
}
ProviderToolOperationSnapshot is the replay projection used to reconstruct usage limits. Dispatched is sticky once dispatch_attempted was durably observed, even if later terminal evidence is corrupt or missing.
func LoadProviderToolOperations ¶ added in v0.12.3
func LoadProviderToolOperations(id string) ([]ProviderToolOperationSnapshot, error)
LoadProviderToolOperations returns replay snapshots sorted by operation ID.
type ProviderToolOperationState ¶ added in v0.12.3
type ProviderToolOperationState string
ProviderToolOperationState is the durable lifecycle for a billable provider-managed tool call. There is intentionally no pre-dispatch state in the journal: dispatch_attempted is the atomic consume point written and fsynced immediately before the wrapped endpoint is invoked.
const ( ProviderToolDispatchAttempted ProviderToolOperationState = "dispatch_attempted" ProviderToolSucceeded ProviderToolOperationState = "succeeded" ProviderToolFailed ProviderToolOperationState = "failed" ProviderToolUncertain ProviderToolOperationState = "uncertain" )
func (ProviderToolOperationState) IsTerminal ¶ added in v0.12.3
func (state ProviderToolOperationState) IsTerminal() bool
type Recorder ¶
type Recorder struct {
// contains filtered or unexported fields
}
Recorder appends events to a JSONL session file synchronously. The file and index entry are created lazily on the first real message so that sessions with no conversation are never persisted. Call Close() (or defer it) to finalize.
func NewRecorder ¶
NewRecorder returns a Recorder that will create the session file only when the first message is recorded. Never returns an error — recording is best-effort and must not break normal operation.
func NewTeammateRecorder ¶
NewTeammateRecorder creates a Recorder that stores its JSONL transcript under the leader session's subagents directory:
~/.jcode/sessions/{leaderUUID}/subagents/agent-{agentID}.jsonl
This mirrors Claude Code's per-agent transcript pattern.
func (*Recorder) Close ¶
func (r *Recorder) Close()
Close flushes and closes the underlying file. Safe to call multiple times. If no messages were ever recorded the file is never created.
func (*Recorder) CompareAndSwapSessionToolOverride ¶ added in v0.12.3
func (r *Recorder) CompareAndSwapSessionToolOverride( tool SessionTool, persisted bool, expectedRevision uint64, ) (SessionToolOverride, error)
CompareAndSwapSessionToolOverride persists one monotonic revision. The in-memory replay cache is published only after write+fsync succeeds.
func (*Recorder) HasRecording ¶ added in v0.0.4
HasRecording reports whether any message has been recorded (i.e. the session file has been created). Returns false for sessions where the user quit without any conversation.
func (*Recorder) Model ¶ added in v0.6.3
Model returns the model currently attributed to recorded usage. It is the model the session was opened with unless SetModel updated it after a switch.
func (*Recorder) Project ¶ added in v0.6.3
Project returns the workspace path this recorder is scoped to.
func (*Recorder) Provider ¶ added in v0.6.3
Provider returns the provider the session was opened with.
func (*Recorder) RecordArtifact ¶ added in v0.12.1
RecordArtifact durably appends one metadata-only Artifact revision. Unlike the historical best-effort recorder helpers, it returns append failures so the show_artifact tool cannot report a revision that was never persisted.
func (*Recorder) RecordAssistant ¶
RecordAssistant appends an assistant message entry.
func (*Recorder) RecordAssistantMessage ¶ added in v0.12.3
RecordAssistantMessage appends the persistable subset of an assistant message. Cleartext reasoning and arbitrary Extra fields are never written; only canonical encrypted Responses continuation items are retained.
func (*Recorder) RecordCompact ¶
RecordCompact appends a compact/summarization event entry. keptN is the number of trailing messages preserved verbatim alongside the summary, so a resume can rebuild the same tail from the entries already on disk.
func (*Recorder) RecordGenerationDispatch ¶ added in v0.12.3
func (r *Recorder) RecordGenerationDispatch( operation GenerationOperation, policy DispatchPolicy, ) error
RecordGenerationDispatch atomically performs strict replay, hard session-cap enforcement, and the fsynced consume append under the per-session OS lock. A nil result is the sole permission to invoke the external image provider.
func (*Recorder) RecordGenerationOperation ¶ added in v0.12.3
func (r *Recorder) RecordGenerationOperation(operation GenerationOperation) error
RecordGenerationOperation synchronously appends and fsyncs one provider dispatch transition. Callers must receive nil before initiating the billable POST. The operation contains fingerprints only, never raw credentials.
func (*Recorder) RecordGoalUpdate ¶ added in v0.5.0
func (r *Recorder) RecordGoalUpdate(objective, status string, tokensUsed, createdAt, updatedAt int64)
RecordGoalUpdate appends a goal state change entry. An empty status records a "cleared" marker so resume knows the goal was removed.
func (*Recorder) RecordModeChange ¶
RecordModeChange appends a mode transition entry on a best-effort basis. Authorization-sensitive callers that must not publish an in-memory mode before it is durable use RecordModeChangeStrict instead.
func (*Recorder) RecordModeChangeStrict ¶ added in v0.12.3
RecordModeChangeStrict durably appends a canonical unified mode transition. Mode is authorization state (Full access removes per-call approval), so it is serialized with transcript replacement and bound to the current on-disk inode just like the other append-only session metadata. A nil return is the caller's permission to publish the corresponding in-memory/UI transition.
func (*Recorder) RecordPlanUpdate ¶
RecordPlanUpdate appends a plan state change entry.
func (*Recorder) RecordProviderToolDispatch ¶ added in v0.12.3
func (r *Recorder) RecordProviderToolDispatch( operation ProviderToolOperation, policy DispatchPolicy, ) error
RecordProviderToolDispatch is the provider-managed equivalent of RecordGenerationDispatch. Its durable count is scoped to the capability and provider profile, matching ledger reconstruction.
func (*Recorder) RecordProviderToolOperation ¶ added in v0.12.3
func (r *Recorder) RecordProviderToolOperation(operation ProviderToolOperation) error
RecordProviderToolOperation synchronously appends and fsyncs one metadata- only state transition. Callers must receive nil for dispatch_attempted before invoking the external endpoint.
func (*Recorder) RecordSubagentAsync ¶
RecordSubagentAsync appends an async subagent launch entry with the task ID.
func (*Recorder) RecordSubagentResult ¶
RecordSubagentResult appends a subagent completion entry.
func (*Recorder) RecordSubagentStart ¶
RecordSubagentStart appends a subagent launch entry.
func (*Recorder) RecordSystemPrompt ¶ added in v0.4.6
RecordSystemPrompt buffers the system prompt so it can be written together with the first real message. This avoids creating a session file when the user opens and immediately closes jcode without any conversation.
func (*Recorder) RecordTodoSnapshot ¶
func (r *Recorder) RecordTodoSnapshot(todos []TodoSnapshotItem)
RecordTodoSnapshot appends a full todo list snapshot entry.
func (*Recorder) RecordToolCall ¶
func (r *Recorder) RecordToolCall(name, args, toolCallID, batchID string, batchIndex, batchSize int)
RecordToolCall appends a tool-call entry. The batch fields group tool calls issued by the same assistant message so replay can rebuild batch boundaries (batchSize > 1 means a concurrent batch).
func (*Recorder) RecordToolObservation ¶ added in v0.10.1
func (r *Recorder) RecordToolObservation(observation ToolObservation)
RecordToolObservation appends metadata-only progressive-disclosure evidence.
func (*Recorder) RecordToolResult ¶
func (r *Recorder) RecordToolResult(name, output, toolCallID string, err error, denied bool, duration time.Duration) (string, error)
RecordToolResult appends a tool-result entry and returns the exact output stored in the transcript. denied marks a user-rejected approval; duration is the approval-wait-adjusted execution latency (0 when unknown). Large outputs are automatically truncated (head+tail preserved) and the full content is saved to an overflow file on disk. Callers should use the returned output in live model history so live and replayed sessions have the same context. A persistence failure is returned so callers do not treat an unstored result as durable conversation history.
func (*Recorder) RecordToolResultWithDetails ¶ added in v0.12.3
func (*Recorder) RecordUser ¶
func (r *Recorder) RecordUser(content string, images ...EntryImage)
RecordUser appends a user message entry. On the first user message, the title is auto-generated from the content. Optional images are persisted alongside the text so they survive session restore.
func (*Recorder) SessionToolOverrides ¶ added in v0.12.3
func (r *Recorder) SessionToolOverrides() (map[SessionTool]SessionToolOverride, error)
SessionToolOverrides returns a snapshot for this recorder. A brand-new recorder has an empty snapshot without forcing creation of a session file.
func (*Recorder) SetAgent ¶ added in v0.11.3
SetAgent records the selected top-level custom agent. Empty means the default agent. Before the first message it is buffered into session_start; after a session exists it also appends an agent_change event for replay.
func (*Recorder) SetModel ¶ added in v0.6.4
SetModel updates the model attributed to subsequently recorded usage so a mid-session model switch attributes new turns to the new model rather than the one the session was opened with. The session-start header is unchanged (it records the opening model).
func (*Recorder) SetTitleFor ¶ added in v0.9.5
SetTitleFor overrides the session title and persists it to the shared index — but only while the recorder still records session id. A title computed for one session (e.g. by the async LLM refiner) must never clobber another session's index entry after SetUUID re-points this recorder (the TUI /resume path reuses the live recorder). Empty titles are ignored.
func (*Recorder) SetTitleRefiner ¶ added in v0.9.5
SetTitleRefiner installs a hook invoked once with the first user message, right after the truncated fallback title is persisted. The hook must not block; it upgrades the title asynchronously via SetTitleFor.
func (*Recorder) SetUUID ¶ added in v0.3.3
SetUUID overrides the session identifier. Used when resuming an existing session so that new messages are appended to the same session file. If the session file does not yet exist on disk, the recorder is NOT marked as resuming, so the first user message will still generate a title.
func (*Recorder) TruncateAtUserMessage ¶ added in v0.4.2
TruncateAtUserMessage rewrites the conversational projection, keeping only entries that appear before the (beforeCount)th user message (0-indexed). Security-critical provider dispatch journals and session tool policy entries are append-only and survive truncation wherever they occur in the file. If beforeCount == 0, conversational history is truncated to session_start. The recorder is reset to append mode on the (now shorter) file. This preserves the session UUID and index entry — no new session is created.
type SessionMeta ¶
type SessionMeta struct {
UUID string `json:"uuid"`
Project string `json:"project"`
Provider string `json:"provider"`
Model string `json:"model"`
Agent string `json:"agent,omitempty"`
StartTime string `json:"start_time"` // RFC3339
Title string `json:"title,omitempty"`
// Task metadata. Additive — legacy index files simply lack these keys, which
// unmarshal to zero values (not pinned / not archived / read).
Pinned bool `json:"pinned,omitempty"`
Archived bool `json:"archived,omitempty"`
Unread bool `json:"unread,omitempty"`
Status string `json:"status,omitempty"` // idle/running/done/error (set by the web layer)
UpdatedAt string `json:"updated_at,omitempty"` // RFC3339
// Automation metadata. A run launched by an automation is a normal session
// tagged here: AutomationID is the correlation key for the "Recent runs"
// list, and the main task list excludes any session with AutomationID set so
// nightly runs don't pollute the sidebar. TerminalStatus/EndTime/ErrorReason
// are the run-outcome audit fields (success|error|interrupted) that back the
// Status filter — Status alone is only idle/running.
AutomationID string `json:"automation_id,omitempty"`
TriggerKind string `json:"trigger_kind,omitempty"` // scheduled|manual
TerminalStatus string `json:"terminal_status,omitempty"`
EndTime string `json:"end_time,omitempty"`
ErrorReason string `json:"error_reason,omitempty"`
// Artifact summary is a repairable materialized view over artifact entries.
ArtifactCount int `json:"artifact_count,omitempty"`
ArtifactUnseen bool `json:"artifact_unseen,omitempty"`
ArtifactUpdatedAt string `json:"artifact_updated_at,omitempty"`
ArtifactViewedAt string `json:"artifact_viewed_at,omitempty"`
// ArtifactViewedRevisions is the durable per-artifact read cursor. The
// legacy ArtifactViewedAt timestamp remains a read-only fallback for index
// files written by older versions; new views never advance that global
// timestamp because doing so would mark unrelated artifacts as read.
ArtifactViewedRevisions map[string]int `json:"artifact_viewed_revisions,omitempty"`
}
SessionMeta is stored in the index for fast listing.
func ListSessions ¶
func ListSessions(project string) ([]SessionMeta, error)
ListSessions returns all sessions recorded for a given project path, newest last.
func UpdateSessionMeta ¶ added in v0.6.1
func UpdateSessionMeta(uuid string, mutate func(*SessionMeta)) (*SessionMeta, error)
UpdateSessionMeta finds a session by uuid across all projects, applies mutate to its metadata, and persists the index atomically. Returns the updated meta, or (nil, nil) if no session with that uuid exists. uuid is only compared in memory (never used as a path), so no path validation is required here.
type SessionState ¶
type SessionState struct {
History []adk.Message
Plan *PlanSnapshot // nil if no plan events found
Todos []TodoSnapshotItem // last todo snapshot, nil if none
Goal *GoalSnapshot // nil if no goal events or last event cleared it
Mode string // last unified session mode (approval/plan/full_access); empty = approval
Agent string // selected top-level custom agent; empty = default
EnvTarget string // last environment (local/ssh alias)
SystemPrompt string // recorded system prompt for KV-cache-friendly resume
EnvInfo string // environment snapshot at recording time
}
SessionState is the full recoverable state from a session file, including conversation history, plan, todos, mode, and environment.
func ReconstructState ¶
func ReconstructState(entries []Entry) *SessionState
ReconstructState rebuilds the full session state from recorded entries. It is compact-aware: if a compact entry is found, messages before it are replaced with the compact summary.
Subagent marker entries (subagent_start/result/async) carry no conversation content and are skipped — but entries BETWEEN them are NOT skipped: subagent internal tool calls are never persisted (only the main runner records tool_call/tool_result), so entries in that window are the main agent's own parallel tool calls and must be kept.
type SessionTool ¶ added in v0.12.3
type SessionTool string
SessionTool identifies historical provider-backed task preferences in durable journals. Both identifiers remain parseable for replay compatibility, but neither is a current product configuration surface.
const ( SessionToolImageGeneration SessionTool = "image_generation" SessionToolWebSearch SessionTool = "web_search" )
func ParseSessionTool ¶ added in v0.12.3
func ParseSessionTool(raw string) (SessionTool, error)
ParseSessionTool validates the exact persisted/API identifier.
func SupportedSessionTools ¶ added in v0.12.3
func SupportedSessionTools() []SessionTool
SupportedSessionTools is empty because provider tools are no longer user-selectable per session. Retained so older integrations compile while discovering that the product exposes no configurable session tools.
type SessionToolOverride ¶ added in v0.12.3
type SessionToolOverride struct {
Tool SessionTool `json:"tool"`
Persisted bool `json:"persisted"`
Revision uint64 `json:"revision"`
}
SessionToolOverride is the historical durable preference projection. It is parsed for compatibility and does not gate current runtime availability.
type SessionToolOverrideRevisionError ¶ added in v0.12.3
type SessionToolOverrideRevisionError struct {
Tool SessionTool
Expected uint64
Actual uint64
}
SessionToolOverrideRevisionError reports a failed compare-and-swap without losing the actual current revision needed by a client to resynchronize.
func (*SessionToolOverrideRevisionError) Error ¶ added in v0.12.3
func (e *SessionToolOverrideRevisionError) Error() string
func (*SessionToolOverrideRevisionError) Unwrap ¶ added in v0.12.3
func (e *SessionToolOverrideRevisionError) Unwrap() error
type TodoSnapshotItem ¶
type TodoSnapshotItem struct {
ID int `json:"id"`
Title string `json:"title"`
Status string `json:"status"`
}
TodoSnapshotItem is a single todo entry stored in a todo_snapshot event.
type ToolObservation ¶ added in v0.10.1
type ToolObservation struct {
Kind string `json:"kind"`
ModelRequestSeq int `json:"model_request_seq,omitempty"`
VisibleNames []string `json:"visible_names,omitempty"`
VisibleCount int `json:"visible_count,omitempty"`
SchemaBytes int `json:"schema_bytes,omitempty"`
SchemaTokensEstimate int64 `json:"schema_tokens_estimate,omitempty"`
NewlyVisibleDeferred []string `json:"newly_visible_deferred,omitempty"`
ToolCallID string `json:"tool_call_id,omitempty"`
QueryMode string `json:"query_mode,omitempty"`
QueryBytes int `json:"query_bytes,omitempty"`
TermCount int `json:"term_count,omitempty"`
RequiredTermCount int `json:"required_term_count,omitempty"`
MaxResults int `json:"max_results,omitempty"`
ValidatedSelectNames []string `json:"validated_select_names,omitempty"`
UnknownSelectCount int `json:"unknown_select_count,omitempty"`
MatchNames []string `json:"match_names,omitempty"`
NewMatchNames []string `json:"new_match_names,omitempty"`
RepeatedQuery bool `json:"repeated_query,omitempty"`
Redundant bool `json:"redundant,omitempty"`
Success bool `json:"success,omitempty"`
ToolName string `json:"tool_name,omitempty"`
Reason string `json:"reason,omitempty"`
}
ToolObservation stores metadata-only evidence about progressive tool disclosure. It intentionally contains no raw query, arguments, schema, output, model content, or error text.
type ToolResultDetails ¶ added in v0.12.3
type ToolResultDetails struct {
OperationID string
Outcome string
ErrorCode string
Provider string
Model string
ArtifactIDs []string
}
ToolResultDetails persists the transport-neutral terminal evidence needed to reconstruct a provider-backed operation without parsing its human-readable output. It deliberately contains identifiers and classifications only.