Documentation
¶
Index ¶
- Constants
- func DeleteModelCacheSupport(database *db.DB, modelID string) error
- func DeleteModelCapability(database *db.DB, modelID string) error
- func DeleteModelPreference(database *db.DB, id string) error
- func FinishedNaturally(finish *string) bool
- func GetModelCacheSupport(database *db.DB, modelID, endpoint string) (string, bool, error)
- func LearnModelContextWindow(database *db.DB, modelID string, window int) error
- func Now() int64
- func SetModelCacheSupport(database *db.DB, modelID, endpoint, verdict string, observedAt int64) error
- func SetModelCapability(database *db.DB, c *ModelCapability) error
- func SetModelPreference(database *db.DB, p *ModelPreference) error
- func SetProviderConfig(database *db.DB, c *ProviderConfig) error
- func SetSearchConfig(database *db.DB, c *SearchConfig) error
- type Delivery
- type ImagePartData
- type InterruptReason
- type Interruption
- type MessageID
- type MessageInfo
- type MessageRole
- type MessageWithParts
- type ModelCapability
- type ModelPreference
- type ModelPreferenceStore
- type Part
- type PartID
- type PartType
- type PermissionID
- type ProviderConfig
- type ReasoningPartData
- type SearchConfig
- type Session
- type SessionID
- type Store
- func (s *Store) Create(session *Session) error
- func (s *Store) CreateMessage(msg *MessageInfo) error
- func (s *Store) CreatePart(part *Part) error
- func (s *Store) DB() *db.DB
- func (s *Store) Delete(id SessionID) error
- func (s *Store) DeleteMessage(messageID MessageID) error
- func (s *Store) Get(id SessionID) (*Session, error)
- func (s *Store) GetMessage(messageID MessageID) (*MessageWithParts, error)
- func (s *Store) GetMessages(sessionID SessionID, before MessageID, limit int) ([]*MessageWithParts, error)
- func (s *Store) GetPart(partID PartID) (*Part, error)
- func (s *Store) GetParts(messageID MessageID) ([]Part, error)
- func (s *Store) List(directory string) ([]*Session, error)
- func (s *Store) ListAll() ([]*Session, error)
- func (s *Store) Update(session *Session) error
- func (s *Store) UpdateCompactionSummary(id SessionID, summary string) error
- func (s *Store) UpdateMemoryTokensSaved(id SessionID, delta int) error
- func (s *Store) UpdateMessage(msg *MessageInfo) error
- func (s *Store) UpdatePart(part *Part) error
- type TextPartData
- type TokenCounts
- type ToolImage
- type ToolPartData
- type ToolState
- type ToolStatus
- type ToolTime
Constants ¶
const ( DefaultSearchFetchTopK = 4 DefaultSearchPageChars = 6000 )
Deep-research tuning defaults and bounds. Defaults mirror the pipeline's built-in constants; bounds keep user-entered values sane.
const ( SearchProviderNative = "native" SearchProviderTavily = "tavily" )
Search providers. Native is the built-in engine compiled into the binary; Tavily is a third-party API keyed by the user's own token. The value is stored as a string so future providers slot in without a schema change.
const MaskedAPIKey = "__SET__"
MaskedAPIKey is the sentinel the UI receives in place of a stored secret, and sends back unchanged to mean "keep the key you already have". Shared with the provider-config masking so both credential surfaces behave identically.
Variables ¶
This section is empty.
Functions ¶
func DeleteModelCacheSupport ¶ added in v0.26.1
DeleteModelCacheSupport clears a persisted verdict so the pair is observed again on next use. An empty modelID clears every verdict — the escape hatch for an endpoint that changed behaviour under a stable URL.
func DeleteModelCapability ¶ added in v0.6.0
DeleteModelCapability clears a model's cached capability so it is re-probed on next use. An empty modelID clears every cached capability. Used by the manual-refresh path.
func DeleteModelPreference ¶
DeleteModelPreference removes a model preference from the database.
func FinishedNaturally ¶ added in v0.26.0
FinishedNaturally reports whether a finish reason means the model was done.
Only three are: the model saying it finished, and the user saying stop. Every other reason — none recorded at all, a request for tools that nothing ran, an error, the output cap — describes a turn that stopped without reaching an end, which is what makes it something to pick back up.
The default is deliberately "not finished". A finish reason this code has never seen is far more likely to be a provider spelling one of the failures its own way than a fourth kind of success, and the cost of the two mistakes is not symmetric: offering a resume that turns out to be unnecessary wastes a click, while withholding one strands the conversation.
func GetModelCacheSupport ¶ added in v0.26.1
GetModelCacheSupport returns the persisted cache verdict for a model on a specific endpoint. The second return value is false when the pair has not been resolved yet.
func LearnModelContextWindow ¶ added in v0.35.0
LearnModelContextWindow records a context window discovered from a context-overflow error body, without disturbing whatever else is known about the model. Windows ≤ 0 (nothing parsed) are ignored. When no capability record exists yet, one is created carrying only the window — the image fields stay at their defaults until a probe writes them.
func SetModelCacheSupport ¶ added in v0.26.1
func SetModelCacheSupport(database *db.DB, modelID, endpoint, verdict string, observedAt int64) error
SetModelCacheSupport records a resolved cache verdict so later sessions skip the observation window entirely.
func SetModelCapability ¶ added in v0.6.0
func SetModelCapability(database *db.DB, c *ModelCapability) error
SetModelCapability upserts a probed capability record for a model.
The upsert MERGES rather than replaces: supports_images and probed_at are taken from the incoming record (an image probe is authoritative each time it runs), but a learned context window survives a write that carries none — otherwise the image probe (which always writes ContextWindow 0) would erase a window the loop learned from an overflow error. Only an explicit positive ContextWindow in the incoming record overwrites the stored one.
func SetModelPreference ¶
func SetModelPreference(database *db.DB, p *ModelPreference) error
SetModelPreference upserts a model preference into the database.
func SetProviderConfig ¶ added in v0.2.1
func SetProviderConfig(database *db.DB, c *ProviderConfig) error
SetProviderConfig upserts a provider config row.
func SetSearchConfig ¶ added in v0.8.0
func SetSearchConfig(database *db.DB, c *SearchConfig) error
SetSearchConfig upserts the singleton config row, clamping the research params before persisting so an invalid client payload can never store bad values.
Types ¶
type Delivery ¶ added in v0.29.0
type Delivery struct {
// DispatchedAt is when the StreamChat attempt that succeeded left for the
// provider. Re-stamped on every attempt so that retry backoff, which can run
// to seconds, never lands inside TTFTMs.
DispatchedAt int64 `json:"dispatchedAt,omitempty"`
// ConnectedAt is when the provider answered 200 and the stream opened. This
// is the moment the request is known to have reached the model.
ConnectedAt int64 `json:"connectedAt,omitempty"`
// FirstTokenAt is when the first content event of any kind arrived — text,
// reasoning or a tool call. Reasoning counts: on a thinking model it is what
// arrives first, and waiting for text instead would report the whole
// thinking phase as latency.
FirstTokenAt int64 `json:"firstTokenAt,omitempty"`
// TTFTMs is FirstTokenAt − DispatchedAt: time to first token, the model's
// own queue and prefill, free of ogcode's prompt building and of backoff.
TTFTMs int64 `json:"ttftMs,omitempty"`
// QueuedMs is DispatchedAt − the prompt's CreatedAt: everything ogcode did
// before the request left, which is prompt building, memory retrieval and
// compaction. Kept apart from TTFTMs so a slow turn can be attributed.
QueuedMs int64 `json:"queuedMs,omitempty"`
// Attempts is how many StreamChat tries the connection took. Above 1 means
// the stream was opened more than once before it held.
Attempts int `json:"attempts,omitempty"`
// FirstTokenKind is what opened the response: "text", "reasoning" or "tool".
FirstTokenKind string `json:"firstTokenKind,omitempty"`
}
Delivery records how far a turn got on its way to the model, and how long the model took to say its first word.
It hangs off the assistant message rather than the prompt that caused it: the loop owns that record from the moment it creates it, and ParentID already points back at the prompt, so the pairing costs nothing. Only the first step of a turn can point at a human prompt — from step 2 on, the preceding user message is the tool-result message the loop wrote itself — so a client reading Delivery through ParentID never has to reason about steps.
type ImagePartData ¶ added in v0.14.0
type ImagePartData struct {
MediaType string `json:"mediaType"`
Data string `json:"data"`
Name string `json:"name,omitempty"`
}
ImagePartData stores a user-uploaded image attachment. Data is base64-encoded image bytes; MediaType is e.g. "image/jpeg" or "image/png". The Name field carries the original filename (optional, for display only).
type InterruptReason ¶ added in v0.26.0
type InterruptReason string
InterruptReason classifies why a turn stopped short.
const ( // InterruptRateLimit is a 429 or a provider quota, the case where waiting // is the whole fix. RetryAfter carries when waiting is over, where the // provider said. InterruptRateLimit InterruptReason = "rate_limit" // InterruptServerError is a 5xx or an overloaded provider. InterruptServerError InterruptReason = "server_error" // InterruptNetwork is a connection that dropped, timed out or was refused. InterruptNetwork InterruptReason = "network" // InterruptAuth is a rejected key, an expired token, an exhausted balance — // resumable, but only once a human has fixed the account behind it. InterruptAuth InterruptReason = "auth" // InterruptContext is a request too large for the model's window that // compaction could not bring back under it. InterruptContext InterruptReason = "context" // InterruptModelCapability is a 400 because the model lacks a capability the // request used (e.g. image input). Resumable: resume strips the offending // content and retries, or the user switches to a model that has the capability. InterruptModelCapability InterruptReason = "model_capability" // InterruptCrashed marks a turn found unfinished at startup: the process // died mid-stream and never got to record anything about why. InterruptCrashed InterruptReason = "crashed" // InterruptStalled marks a turn that recorded a finish reason but not one // the model chose — it asked for a tool and nothing ran it, or it hit the // output cap mid-answer. The loop that would have carried on is gone. InterruptStalled InterruptReason = "stalled" // InterruptFatal is everything a retry cannot help — a malformed request, a // model that does not exist, a provider rejecting the tool schema. InterruptFatal InterruptReason = "fatal" )
type Interruption ¶ added in v0.26.0
type Interruption struct {
Reason InterruptReason `json:"reason"`
Resumable bool `json:"resumable"`
// Detail is a short human-facing sentence naming what to do about it. The
// raw provider error stays in Error.
Detail string `json:"detail,omitempty"`
// RetryAfter is the unix second the provider said to come back at, or 0
// where it said nothing. Only a rate limit tends to carry one.
RetryAfter int64 `json:"retryAfter,omitempty"`
// Step is the loop step the turn died on, for the UI to say how far it got.
Step int `json:"step,omitempty"`
}
Interruption records why a turn stopped short of finishing and whether picking it up again is worth trying.
It sits beside Error rather than replacing it. Error is the provider's own words, which a user needs to read; this is the classification the resume path acts on, and the two answer different questions.
type MessageInfo ¶
type MessageInfo struct {
ID MessageID `json:"id"`
SessionID SessionID `json:"sessionId"`
Role MessageRole `json:"role"`
Agent string `json:"agent,omitempty"`
ParentID *MessageID `json:"parentId,omitempty"`
Finish *string `json:"finish,omitempty"`
Cost float64 `json:"cost,omitempty"`
Tokens *TokenCounts `json:"tokens,omitempty"`
Error *string `json:"error,omitempty"`
// Interrupted is set when a loop stopped part-way through this turn rather
// than because the model finished. It is what a resume decides from.
Interrupted *Interruption `json:"interrupted,omitempty"`
// Delivery records how far this turn got on its way to the model and how
// long the model took to start answering. Set on assistant messages only,
// and nil on any written before the field existed.
Delivery *Delivery `json:"delivery,omitempty"`
CreatedAt int64 `json:"createdAt"`
}
func (*MessageInfo) CanResume ¶ added in v0.26.0
func (m *MessageInfo) CanResume() bool
CanResume reports whether a message is one a resume should act on.
type MessageRole ¶
type MessageRole string
const ( RoleUser MessageRole = "user" RoleAssistant MessageRole = "assistant" )
type MessageWithParts ¶
type MessageWithParts struct {
Info MessageInfo `json:"info"`
Parts []Part `json:"parts"`
}
type ModelCapability ¶ added in v0.6.0
type ModelCapability struct {
ModelID string `json:"modelId"`
SupportsImages bool `json:"supportsImages"`
ProbedAt int64 `json:"probedAt"`
ContextWindow int `json:"contextWindow"`
}
ModelCapability is a probed/known capability record for a model, persisted so the image-support probe runs at most once per model (until manually refreshed). ContextWindow carries a window learned from a context-overflow error body (0 = unknown); see session.LearnModelContextWindow.
func GetModelCapability ¶ added in v0.6.0
GetModelCapability returns the persisted capability record for a model. The second return value is false when no record exists (not yet probed).
type ModelPreference ¶
type ModelPreference struct {
ID string `json:"id"`
Enabled bool `json:"enabled"`
ProviderID string `json:"providerId"`
DisplayName string `json:"displayName"`
IsCustom bool `json:"isCustom"`
// Collection is an optional group name for custom models so OpenAI-compatible
// providers added through the OpenAI provider (Gemini, DeepSeek, Groq, …) can
// be grouped together in the UI instead of all collapsing under "OpenAI".
// Empty for built-in models and legacy custom models (falls back to providerId).
Collection string `json:"collection"`
CreatedAt int64 `json:"createdAt"`
UpdatedAt int64 `json:"updatedAt"`
}
func GetModelPreferences ¶
func GetModelPreferences(database *db.DB) ([]*ModelPreference, error)
GetModelPreferences returns all model preference overrides from the database.
type ModelPreferenceStore ¶
type ModelPreferenceStore struct{}
type PermissionID ¶
type PermissionID = id.PermissionID
func NewPermissionID ¶
func NewPermissionID() PermissionID
type ProviderConfig ¶ added in v0.2.1
type ProviderConfig struct {
ProviderID string `json:"providerId"`
APIKey string `json:"apiKey"`
BaseURL string `json:"baseUrl"`
UpdatedAt int64 `json:"updatedAt"`
}
ProviderConfig holds credentials for a single LLM provider stored in the DB.
func GetAllProviderConfigs ¶ added in v0.2.1
func GetAllProviderConfigs(database *db.DB) ([]*ProviderConfig, error)
GetAllProviderConfigs returns stored configs for all providers.
func GetProviderConfig ¶ added in v0.2.1
func GetProviderConfig(database *db.DB, providerID string) (*ProviderConfig, error)
GetProviderConfig returns the stored config for a provider. Returns a zero-value config (empty fields) when no row exists.
func MaskedProviderConfig ¶ added in v0.2.1
func MaskedProviderConfig(c *ProviderConfig) *ProviderConfig
MaskedProviderConfig returns a copy with the API key replaced by a sentinel so it can be sent to the UI without leaking the real value.
type ReasoningPartData ¶
type ReasoningPartData struct {
Text string `json:"text"`
Signature string `json:"signature,omitempty"`
// RedactedData is the opaque payload of an Anthropic redacted_thinking
// block. Such a block has no readable text, and dropping it — or replaying
// it as an ordinary thinking block — breaks the round-trip the API
// requires within a tool-use turn.
RedactedData string `json:"redactedData,omitempty"`
// Model is the model that produced this block. Thinking blocks are tied to
// the model that generated them: replayed to any other model they are
// silently ignored but still billed as input, and an unsigned block from an
// OpenAI-family model is rejected outright. Recording the origin lets the
// conversion drop what the current model cannot use.
Model string `json:"model,omitempty"`
}
type SearchConfig ¶ added in v0.8.0
type SearchConfig struct {
Enabled bool `json:"enabled"`
// Provider selects the search backend: "native" (default) or "tavily".
Provider string `json:"provider"`
// TavilyAPIKey is the token for the Tavily provider. Masked to MaskedAPIKey
// on read so it never reaches the UI in the clear.
TavilyAPIKey string `json:"tavilyApiKey"`
FetchTopK int `json:"fetchTopK"`
PageChars int `json:"pageChars"`
UpdatedAt int64 `json:"updatedAt"`
}
SearchConfig holds the global web-search toggle, the active search provider and its credential, plus the deep-research pipeline tuning knobs (pages fetched, per-page size).
func GetSearchConfig ¶ added in v0.8.0
func GetSearchConfig(database *db.DB) (*SearchConfig, error)
GetSearchConfig returns the stored config. If no row exists it returns the defaults, which have search ENABLED: the backend is compiled into the binary and needs nothing installed, so there is no setup step to gate it behind. A user who does not want outbound requests turns the toggle off, and that stored choice is honoured on every later read. Research params are always clamped so callers never receive zero/invalid values.
func MaskedSearchConfig ¶ added in v0.32.0
func MaskedSearchConfig(c *SearchConfig) *SearchConfig
MaskedSearchConfig returns a copy with the Tavily key replaced by the mask sentinel so the config can be sent to the UI without leaking the real value. Mirrors MaskedProviderConfig.
type Session ¶
type Session struct {
ID SessionID `json:"id"`
ProjectID string `json:"projectId"`
Directory string `json:"directory"`
Title string `json:"title"`
Model string `json:"model,omitempty"`
SessionType string `json:"sessionType,omitempty"`
Permission string `json:"permission,omitempty"`
CompactionSummary string `json:"compactionSummary,omitempty"`
MemoryTokensSaved int `json:"memoryTokensSaved,omitempty"`
CreatedAt int64 `json:"createdAt"`
UpdatedAt int64 `json:"updatedAt"`
}
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
func (*Store) CreateMessage ¶
func (s *Store) CreateMessage(msg *MessageInfo) error
func (*Store) CreatePart ¶
func (*Store) DB ¶ added in v0.6.0
DB returns the underlying database handle, used by helpers that operate on other tables (e.g. model capability records).
func (*Store) DeleteMessage ¶ added in v0.19.1
DeleteMessage removes a message and all of its parts. Foreign-key cascade handles part deletion automatically. Used to clean up partial assistant messages left behind when mid-loop guidance cancels a text-only stream — keeping them would produce two consecutive assistant role messages on the next prompt, which the Anthropic and OpenAI APIs reject with a 400.
func (*Store) GetMessage ¶
func (s *Store) GetMessage(messageID MessageID) (*MessageWithParts, error)
func (*Store) GetMessages ¶
func (*Store) ListAll ¶ added in v0.23.0
ListAll returns every session row regardless of directory or type, including the note/index/search sessions List hides. Agentic memory uses it to backfill project identity onto nodes written before that column existed.
func (*Store) UpdateCompactionSummary ¶
UpdateCompactionSummary updates only the compaction_summary column for a session, avoiding the race condition of overwriting other fields (e.g., title, model) that may have changed concurrently.
func (*Store) UpdateMemoryTokensSaved ¶ added in v0.2.1
UpdateMemoryTokensSaved atomically increments memory_tokens_saved by delta (may be negative). delta is clamped above at 1_000_000_000 to prevent overflow; negative values are preserved so callers can track memory overhead accurately.
func (*Store) UpdateMessage ¶
func (s *Store) UpdateMessage(msg *MessageInfo) error
func (*Store) UpdatePart ¶
type TextPartData ¶
type TextPartData struct {
Text string `json:"text"`
}
type TokenCounts ¶
type ToolImage ¶ added in v0.6.0
ToolImage is an image produced by a tool, persisted so the model can be re-sent the image on history replay. Data is base64-encoded image bytes.
type ToolPartData ¶
type ToolState ¶
type ToolState struct {
Status ToolStatus `json:"status"`
Input json.RawMessage `json:"input"`
Output *string `json:"output,omitempty"`
Error *string `json:"error,omitempty"`
Title *string `json:"title,omitempty"`
Metadata json.RawMessage `json:"metadata,omitempty"`
Image *ToolImage `json:"image,omitempty"`
Time ToolTime `json:"time"`
}
type ToolStatus ¶
type ToolStatus string
const ( ToolPending ToolStatus = "pending" ToolRunning ToolStatus = "running" ToolCompleted ToolStatus = "completed" ToolError ToolStatus = "error" ToolDenied ToolStatus = "denied" )