// Package wire defines the locked NDJSON ingest contract shared with the // lethe-collector. Changes here ripple into the collector — be deliberate. package wire import "encoding/json" // TurnEvent is the on-the-wire representation of a single turn in a session. // It is the only message type accepted by POST /api/v1/ingest. Sessions are // upserted from SessionMeta carried on each turn; there is no separate // session event on the wire. type TurnEvent struct { Tool string `json:"tool"` Host string `json:"host"` SessionID string `json:"session_id"` TurnID string `json:"turn_id"` Seq int64 `json:"seq"` Role string `json:"role"` // user | assistant | tool | system Timestamp int64 `json:"timestamp"` // unix epoch seconds Content string `json:"content"` Model *string `json:"model,omitempty"` TokensIn *int64 `json:"tokens_in,omitempty"` TokensOut *int64 `json:"tokens_out,omitempty"` CostUSD *float64 `json:"cost_usd,omitempty"` ToolCalls json.RawMessage `json:"tool_calls,omitempty"` SessionMeta SessionMeta `json:"session_meta"` Metadata json.RawMessage `json:"metadata,omitempty"` } // SessionMeta carries the per-session attributes that the server uses to // upsert the parent session row on first-seen turn for that session. type SessionMeta struct { WorkingDir *string `json:"working_dir,omitempty"` SourceFile string `json:"source_file"` StartedAt *int64 `json:"started_at,omitempty"` // optional; server falls back to MIN(turn.timestamp) Metadata json.RawMessage `json:"metadata,omitempty"` }