Documentation
¶
Index ¶
- Constants
- Variables
- func BuildMCPBinary(t *testing.T, dir string) string
- func ChatContainsAny(replies []ChatReply, keywords ...string) bool
- func CountTool(entries []ScenarioAuditEntry, tool string) int
- func ModelContextWindow(modelID string) int
- func ModelEffectiveContextWindow(modelID string) int
- func Run()
- func RunScenario(t *testing.T, s Scenario)
- func SetVersion(version, buildTime string)
- func ThreadIDs(th *Thinker) []string
- func WaitFor(t *testing.T, timeout, interval time.Duration, desc string, cond func() bool)
- func WriteJSONFile(t *testing.T, dir, name string, v any)
- type APIEvent
- type APIServer
- type AnthropicProvider
- func (p *AnthropicProvider) AvailableBuiltinTools() []BuiltinTool
- func (p *AnthropicProvider) Chat(ctx context.Context, messages []Message, model string, tools []NativeTool, ...) (ChatResponse, error)
- func (p *AnthropicProvider) CostPer1M() (float64, float64, float64)
- func (p *AnthropicProvider) Models() map[ModelTier]string
- func (p *AnthropicProvider) Name() string
- func (p *AnthropicProvider) SetBuiltinTools(tools []string)
- func (p *AnthropicProvider) SupportsNativeTools() bool
- func (p *AnthropicProvider) WithBuiltins(builtins []string) LLMProvider
- type AudioFormat
- type AudioURL
- type BlobStore
- func (bs *BlobStore) Close()
- func (bs *BlobStore) Count() int
- func (bs *BlobStore) Get(ref string) ([]byte, string, bool)
- func (bs *BlobStore) Put(mime string, data []byte) string
- func (bs *BlobStore) RehydrateFileRefs(args map[string]string) map[string]string
- func (bs *BlobStore) RewriteBinaryToHandle(text string) string
- type BuiltinTool
- type ChatReply
- type ChatResponse
- type Config
- func (c *Config) ClearThreads() error
- func (c *Config) GetDefaultProvider() *ProviderConfig
- func (c *Config) GetDirective() string
- func (c *Config) GetExecutionControl() ExecutionControlConfig
- func (c *Config) GetMCPServers() []MCPServerConfig
- func (c *Config) GetMode() RunMode
- func (c *Config) GetProvider() *ProviderConfig
- func (c *Config) GetProviderByName(name string) *ProviderConfig
- func (c *Config) GetProviders() []ProviderConfig
- func (c *Config) GetRealtimeVoice() string
- func (c *Config) GetRealtimeVoiceMCP() []string
- func (c *Config) GetThreads() []PersistentThread
- func (c *Config) LoadError() error
- func (c *Config) RealtimeEnabledFlag() bool
- func (c *Config) RemoveMCPServer(name string) error
- func (c *Config) RemoveProvider(name string) error
- func (c *Config) RemoveThread(id string) error
- func (c *Config) RenameThread(oldID string, pt PersistentThread) error
- func (c *Config) ReplaceProviders(providers []ProviderConfig) error
- func (c *Config) Save() error
- func (c *Config) SaveMCPServer(cfg MCPServerConfig) error
- func (c *Config) SaveThread(pt PersistentThread) error
- func (c *Config) SetDefaultProvider(name string) error
- func (c *Config) SetDirective(d string) error
- func (c *Config) SetExecutionControl(ec ExecutionControlConfig) error
- func (c *Config) SetMode(m RunMode) error
- func (c *Config) SetProvider(pc *ProviderConfig) error
- func (c *Config) SetProviderModel(tier string, modelID string) error
- func (c *Config) SetProviderName(name string) error
- func (c *Config) SetRealtimeEnabled(enabled bool) error
- func (c *Config) SetRealtimeVoice(voice string) error
- func (c *Config) SetRealtimeVoiceMCP(names []string) error
- type ConsoleLogger
- type ContentPart
- type Delta
- type DirectiveChangeData
- type Event
- type EventBus
- func (b *EventBus) DropStats() map[string]uint64
- func (b *EventBus) HasSubscriber(id string) bool
- func (b *EventBus) Publish(ev Event)
- func (b *EventBus) RenameSubscription(oldID, newID string) error
- func (b *EventBus) Subscribe(id string, buffer int) *Subscription
- func (b *EventBus) SubscribeAll(id string, buffer int) *Subscription
- func (b *EventBus) SubscribeUnique(id string, buffer int) (*Subscription, error)
- func (b *EventBus) Unsubscribe(id string)
- type ExecutionCheckpointMeta
- type ExecutionCheckpointStore
- func (s *ExecutionCheckpointStore) Capture(t *Thinker, gate ExecutionGate) *ExecutionCheckpointMeta
- func (s *ExecutionCheckpointStore) Get(id string) (*executionCheckpoint, bool)
- func (s *ExecutionCheckpointStore) ListMeta() []ExecutionCheckpointMeta
- func (s *ExecutionCheckpointStore) RestoreTarget(threadID string) *ExecutionCheckpointMeta
- func (s *ExecutionCheckpointStore) RestoreTargetBeforeGate(gate ExecutionGate) *ExecutionCheckpointMeta
- type ExecutionControlAction
- type ExecutionControlConfig
- type ExecutionControlMode
- type ExecutionControlStatus
- type ExecutionController
- func (c *ExecutionController) ApplyConfig(cfg ExecutionControlConfig)
- func (c *ExecutionController) CancelThread(threadID string) bool
- func (c *ExecutionController) Config() ExecutionControlConfig
- func (c *ExecutionController) Control(action ExecutionControlAction) (ExecutionControlStatus, error)
- func (c *ExecutionController) ShouldGate(phase ExecutionPhase) bool
- func (c *ExecutionController) Status() ExecutionControlStatus
- func (c *ExecutionController) Wait(gate ExecutionGate, quit <-chan struct{}, ...) bool
- type ExecutionGate
- type ExecutionPhase
- type ExecutionPhaseData
- type ExtraSystemBlock
- type GoogleModel
- type GoogleProvider
- func (p *GoogleProvider) ActiveModel() string
- func (p *GoogleProvider) AvailableBuiltinTools() []BuiltinTool
- func (p *GoogleProvider) AvailableModels() []string
- func (p *GoogleProvider) Chat(ctx context.Context, messages []Message, model string, tools []NativeTool, ...) (ChatResponse, error)
- func (p *GoogleProvider) CostPer1M() (float64, float64, float64)
- func (p *GoogleProvider) Models() map[ModelTier]string
- func (p *GoogleProvider) Name() string
- func (p *GoogleProvider) SetBuiltinTools(tools []string)
- func (p *GoogleProvider) SetModel(modelID string)
- func (p *GoogleProvider) SupportsNativeTools() bool
- func (p *GoogleProvider) WithBuiltins(builtins []string) LLMProvider
- type GoogleRealtimeProvider
- func (p *GoogleRealtimeProvider) DefaultTranscriptionModel() string
- func (p *GoogleRealtimeProvider) DefaultVoice() string
- func (p *GoogleRealtimeProvider) Models() map[ModelTier]string
- func (p *GoogleRealtimeProvider) Name() string
- func (p *GoogleRealtimeProvider) Open(ctx context.Context, opts RealtimeSessionOpts) (RealtimeSession, error)
- func (p *GoogleRealtimeProvider) Pricing(string) RealtimePricing
- type ImageURL
- type IndexEntry
- type InputAudio
- type LLMChunkData
- type LLMDoneData
- type LLMErrorData
- type LLMProvider
- func NewAnthropicProvider(apiKey string) LLMProvider
- func NewFireworksProvider(apiKey string) LLMProvider
- func NewGoogleProvider(apiKey string) LLMProvider
- func NewNvidiaProvider(apiKey string) LLMProvider
- func NewOllamaProvider(host string) LLMProvider
- func NewOpenAICodexProvider(accessToken string) LLMProvider
- func NewOpenAINativeProvider(apiKey string) LLMProvider
- func NewOpenAIProvider(apiKey string) LLMProvider
- func NewOpenCodeGoProvider(apiKey string) LLMProvider
- func NewVeniceProvider(apiKey string) LLMProvider
- func NewXAIProvider(apiKey string) LLMProvider
- type MCPConn
- type MCPHTTPServer
- func (s *MCPHTTPServer) CallTool(name string, args map[string]string) (ToolResponse, error)
- func (s *MCPHTTPServer) CallToolTyped(name string, args map[string]string, inputSchema map[string]any) (ToolResponse, error)
- func (s *MCPHTTPServer) Close()
- func (s *MCPHTTPServer) GetName() string
- func (s *MCPHTTPServer) ListTools() ([]mcpToolDef, error)
- type MCPServer
- func (s *MCPServer) CallTool(name string, args map[string]string) (ToolResponse, error)
- func (s *MCPServer) CallToolTyped(name string, args map[string]string, inputSchema map[string]any) (ToolResponse, error)
- func (s *MCPServer) Close()
- func (s *MCPServer) GetName() string
- func (s *MCPServer) ListTools() ([]mcpToolDef, error)
- type MCPServerConfig
- type MCPServerInfo
- type MCPToolLoadingConfig
- type MemoryRecallMatch
- type MemoryRecord
- type MemoryStore
- func (ms *MemoryStore) Active() []MemoryRecord
- func (ms *MemoryStore) All() []MemoryRecord
- func (ms *MemoryStore) BuildContext(records []MemoryRecord) string
- func (ms *MemoryStore) Count() int
- func (ms *MemoryStore) Drop(id, reason string) error
- func (ms *MemoryStore) Enabled() bool
- func (ms *MemoryStore) HasID(id string) bool
- func (ms *MemoryStore) Recall(query string, n int) []MemoryRecord
- func (ms *MemoryStore) RecallMatches(query string, n int) []MemoryRecallMatch
- func (ms *MemoryStore) Remember(content string, tags []string, weight float64) (string, error)
- func (ms *MemoryStore) RememberWithID(id, content string, tags []string, weight float64) (string, error)
- func (ms *MemoryStore) Search(query string, limit int) []MemoryRecord
- func (ms *MemoryStore) Supersede(oldID, content string, tags []string, weight float64, reason string) (string, error)
- func (ms *MemoryStore) UpsertTargetID(id string) (string, bool)
- type Message
- type ModelCapabilities
- type ModelReasoningCapability
- type ModelTier
- type NativeTool
- type NativeToolCall
- type NativeToolSize
- type OpenAICompatProvider
- func (p *OpenAICompatProvider) AvailableBuiltinTools() []BuiltinTool
- func (p *OpenAICompatProvider) Chat(ctx context.Context, messages []Message, model string, tools []NativeTool, ...) (ChatResponse, error)
- func (p *OpenAICompatProvider) CostPer1M() (float64, float64, float64)
- func (p *OpenAICompatProvider) Models() map[ModelTier]string
- func (p *OpenAICompatProvider) Name() string
- func (p *OpenAICompatProvider) SetBuiltinTools(tools []string)
- func (p *OpenAICompatProvider) SupportsNativeTools() bool
- func (p *OpenAICompatProvider) WithBuiltins(builtins []string) LLMProvider
- type OpenAINativeProvider
- func (p *OpenAINativeProvider) AvailableBuiltinTools() []BuiltinTool
- func (p *OpenAINativeProvider) Chat(ctx context.Context, messages []Message, model string, tools []NativeTool, ...) (ChatResponse, error)
- func (p *OpenAINativeProvider) CostPer1M() (float64, float64, float64)
- func (p *OpenAINativeProvider) Models() map[ModelTier]string
- func (p *OpenAINativeProvider) Name() string
- func (p *OpenAINativeProvider) SetBuiltinTools(tools []string)
- func (p *OpenAINativeProvider) SupportsNativeTools() bool
- func (p *OpenAINativeProvider) WithBuiltins(builtins []string) LLMProvider
- func (p *OpenAINativeProvider) WithReasoning(settings ReasoningSettings) LLMProvider
- type OpenAIRealtimeProvider
- func (p *OpenAIRealtimeProvider) DefaultTranscriptionModel() string
- func (p *OpenAIRealtimeProvider) DefaultVoice() string
- func (p *OpenAIRealtimeProvider) Models() map[ModelTier]string
- func (p *OpenAIRealtimeProvider) Name() string
- func (p *OpenAIRealtimeProvider) Open(ctx context.Context, opts RealtimeSessionOpts) (RealtimeSession, error)
- func (p *OpenAIRealtimeProvider) Pricing(model string) RealtimePricing
- type PersistentThread
- type Phase
- type PromptComposition
- type PromptTokensDetails
- type ProviderConfig
- type ProviderPool
- func (pp *ProviderPool) Count() int
- func (pp *ProviderPool) Default() LLMProvider
- func (pp *ProviderPool) DefaultName() string
- func (pp *ProviderPool) Fallback(exclude string) LLMProvider
- func (pp *ProviderPool) Get(name string) LLMProvider
- func (pp *ProviderPool) HasRealtimeProvider() bool
- func (pp *ProviderPool) Names() []string
- func (pp *ProviderPool) ProviderSummary(name string) string
- func (pp *ProviderPool) RealtimeByName(name string) RealtimeProvider
- func (pp *ProviderPool) RealtimeDefault() RealtimeProvider
- func (pp *ProviderPool) RealtimeNames() []string
- type ProviderResponseState
- type RealtimeEvent
- type RealtimeEventType
- type RealtimePricing
- type RealtimeProvider
- type RealtimeSession
- type RealtimeSessionOpts
- type RealtimeThinker
- type RealtimeUsage
- type ReasoningLevel
- type ReasoningProvider
- type ReasoningSettings
- type Request
- type RunMode
- type Scenario
- type ScenarioAuditEntry
- type ServerToolResult
- type Session
- func (s *Session) Append(entry SessionEntry) error
- func (s *Session) AppendMessage(msg Message, iteration int, usage TokenUsage) error
- func (s *Session) ArchiveToolResults(msg Message) (Message, error)
- func (s *Session) Compact(summarize func(text string) string)
- func (s *Session) Count() int
- func (s *Session) Delete()
- func (s *Session) ForceCompact(keepRecent int, summarize func(text string) string)
- func (s *Session) LoadAfter(after int64, limit int) (entries []SessionEntry, nextCursor int64, err error)
- func (s *Session) LoadTail(n int) (messages []Message, compactedSummaries []string)
- func (s *Session) NeedsCompaction() bool
- func (s *Session) Rename(newThreadID string) error
- func (s *Session) Reset() error
- type SessionEntry
- type SpawnOpts
- type StreamChoice
- type StreamEvent
- type Subscription
- type SystemBreakdown
- type Telemetry
- func (t *Telemetry) DroppedLiveEvents() int64
- func (t *Telemetry) Emit(eventType, threadID string, data any)
- func (t *Telemetry) EmitLive(eventType, threadID string, data any)
- func (t *Telemetry) Events(since int) ([]TelemetryEvent, int)
- func (t *Telemetry) Stop()
- func (t *Telemetry) StoredEvents(since int) ([]TelemetryEvent, int)
- func (t *Telemetry) Subscribe() (<-chan struct{}, func())
- type TelemetryEvent
- type ThinkRate
- type Thinker
- func (t *Thinker) APIEvents(since int) ([]APIEvent, int)
- func (t *Thinker) Config() *Config
- func (t *Thinker) Inject(msg string)
- func (t *Thinker) InjectConsole(msg string)
- func (t *Thinker) InjectWithParts(text string, parts []ContentPart)
- func (t *Thinker) Iteration() int
- func (t *Thinker) Memory() *MemoryStore
- func (t *Thinker) Messages() []Message
- func (t *Thinker) Pool() *ProviderPool
- func (t *Thinker) ReloadDirective()
- func (t *Thinker) ReloadDirectiveQuiet()
- func (t *Thinker) ResetConversation()
- func (t *Thinker) Run()
- func (t *Thinker) Stop()
- func (t *Thinker) Threads() *ThreadManager
- func (t *Thinker) TogglePause()
- type Thread
- type ThreadDoneData
- type ThreadInfo
- type ThreadManager
- func (tm *ThreadManager) Count() int
- func (tm *ThreadManager) Directive(id string) (string, error)
- func (tm *ThreadManager) Kill(id string)
- func (tm *ThreadManager) KillAll()
- func (tm *ThreadManager) List() []ThreadInfo
- func (tm *ThreadManager) ListAgentVisible() []ThreadInfo
- func (tm *ThreadManager) PauseAll(paused bool)
- func (tm *ThreadManager) Rename(oldID, newID string) error
- func (tm *ThreadManager) RenewRealtimeAudioToken(id string) (string, error)
- func (tm *ThreadManager) Send(id, message string) bool
- func (tm *ThreadManager) SendAgentWithParts(id, message string, parts []ContentPart) error
- func (tm *ThreadManager) SendWithParts(id, message string, parts []ContentPart) bool
- func (tm *ThreadManager) Spawn(id, directive string, tools []string, initialMessages ...string) error
- func (tm *ThreadManager) SpawnWithMedia(id, directive string, tools []string, parts []ContentPart, ...) error
- func (tm *ThreadManager) SpawnWithOpts(id, directive string, tools []string, opts SpawnOpts) error
- func (tm *ThreadManager) StartAll()
- func (tm *ThreadManager) Update(id, name, directive string, tools []string) error
- func (tm *ThreadManager) ValidateAgentTarget(id string) error
- type ThreadMessageData
- type ThreadRenamedData
- type ThreadSpawnData
- type TokenUsage
- type ToolCallData
- type ToolDef
- type ToolHandler
- type ToolIndex
- func (ix *ToolIndex) Add(server string, tools []mcpToolDef, noSpawn bool, ...)
- func (ix *ToolIndex) AllNames(allowNoSpawn bool) []string
- func (ix *ToolIndex) AlwaysCount(allowNoSpawn bool) int
- func (ix *ToolIndex) BaselineNames(eagerMode, allowNoSpawn bool) []string
- func (ix *ToolIndex) Count() int
- func (ix *ToolIndex) DeferredCount(eagerMode, allowNoSpawn bool) int
- func (ix *ToolIndex) Get(name string) (IndexEntry, bool)
- func (ix *ToolIndex) Remove(server string)
- func (ix *ToolIndex) Search(query string, k int, allowNoSpawn bool) []IndexEntry
- func (ix *ToolIndex) Servers() []string
- func (ix *ToolIndex) ToolCountByServer() map[string]int
- func (ix *ToolIndex) ToolPolicyCountsByServer() map[string]map[ToolLoadMode]int
- func (ix *ToolIndex) ToolsForServer(server string) []string
- func (ix *ToolIndex) UpdatePolicy(server string, noSpawn bool, loading *MCPToolLoadingConfig)
- type ToolLoadMode
- type ToolRegistry
- func (tr *ToolRegistry) AllToolNames() []string
- func (tr *ToolRegistry) AllTools() []*ToolDef
- func (tr *ToolRegistry) CoreDocs(includeMainOnly bool, includeSystemOnly ...bool) string
- func (tr *ToolRegistry) CoreDocsSummary(includeMainOnly bool, includeSystemOnly ...bool) string
- func (tr *ToolRegistry) Count() int
- func (tr *ToolRegistry) Counts() (core, rag, total int)
- func (tr *ToolRegistry) Dispatch(name string, args map[string]string) (ToolResponse, bool)
- func (tr *ToolRegistry) Get(name string) *ToolDef
- func (tr *ToolRegistry) NativeTools(allowlist, active map[string]bool, includeSystemOnly ...bool) []NativeTool
- func (tr *ToolRegistry) Register(tool *ToolDef)
- func (tr *ToolRegistry) RemoveByMCPServer(serverName string)
- type ToolResponse
- type ToolResult
- type ToolResultArchive
- type ToolResultData
- type Usage
- type WakeOnResultPolicy
- type XAIProvider
- func (p *XAIProvider) AvailableBuiltinTools() []BuiltinTool
- func (p *XAIProvider) Chat(ctx context.Context, messages []Message, model string, tools []NativeTool, ...) (ChatResponse, error)
- func (p *XAIProvider) CostPer1M() (float64, float64, float64)
- func (p *XAIProvider) Models() map[ModelTier]string
- func (p *XAIProvider) Name() string
- func (p *XAIProvider) SetBuiltinTools(_ []string)
- func (p *XAIProvider) SupportsNativeTools() bool
- func (p *XAIProvider) WithBuiltins(_ []string) LLMProvider
- func (p *XAIProvider) WithReasoning(settings ReasoningSettings) LLMProvider
- type XAIRealtimeProvider
- func (p *XAIRealtimeProvider) DefaultTranscriptionModel() string
- func (p *XAIRealtimeProvider) DefaultVoice() string
- func (p *XAIRealtimeProvider) Models() map[ModelTier]string
- func (p *XAIRealtimeProvider) Name() string
- func (p *XAIRealtimeProvider) Open(ctx context.Context, opts RealtimeSessionOpts) (RealtimeSession, error)
- func (p *XAIRealtimeProvider) Pricing(string) RealtimePricing
Constants ¶
const ( DefaultBlobMaxTotal = int64(256 * 1024 * 1024) // 256 MB across all live blobs DefaultBlobTTL = 30 * time.Minute // age-based eviction )
Default caps — liberal enough for typical audio/small-video flows, strict enough that a runaway agent can't swallow the process.
const ( EventInbox = "inbox" // message addressed to a thinker (replaces inbox chan string) EventChunk = "chunk" // streaming token from LLM EventToolChunk = "tool_chunk" // streaming tool argument chunk from LLM EventThinkDone = "think_done" // completed a think cycle EventThinkError = "think_error" // error during think EventThreadStart = "thread_start" // thread spawned EventThreadDone = "thread_done" // thread terminated )
Event types
const MaxSpawnDepth = 2
MaxSpawnDepth is the maximum depth for sub-thread spawning. Main = depth -1 (conceptual), its children = 0, grandchildren = 1, etc.
Variables ¶
var ( Version = "dev" BuildTime = "dev" )
Version + BuildTime are populated by cmd/apteva-core at startup with the values that ldflags injected into its `package main`. Default to "dev" so direct `go test` runs (which never call core.SetVersion) still work.
var ErrStreamIdleTimeout = errors.New("stream idle timeout (provider went silent mid-response)")
ErrStreamIdleTimeout is returned by a stream reader that went silent for longer than the idle window. Callers can branch on it to tag telemetry as a stall instead of a generic I/O error.
var GeminiModelOrder = []string{
"gemini-3.1-pro-preview",
"gemini-3-flash-preview",
"gemini-3.1-flash-lite-preview",
"gemini-2.5-pro",
"gemini-2.5-flash",
}
GeminiModelOrder defines the cycle order for model switching in the TUI.
Functions ¶
func BuildMCPBinary ¶
BuildMCPBinary compiles the Go MCP server in `dir` and returns the binary path. Pass `dir` either as an absolute path, a path relative to the current working directory, OR a path relative to the core module root (e.g. "mcps/helpdesk") — the helper tries each in turn, so callers from sibling packages don't need to thread their cwd.
func ChatContainsAny ¶
ChatContainsAny returns true if any reply's message contains at least one of the keywords (case-insensitive).
func CountTool ¶
func CountTool(entries []ScenarioAuditEntry, tool string) int
CountTool returns the number of audit entries with `tool == name`.
func ModelContextWindow ¶
ModelContextWindow returns the advertised input-context window (in tokens) for a given model id. Pure static lookup — no network, no API call, ~hundreds of nanoseconds. Returns 0 if the model isn't in the table; the UI treats 0 as "unknown" and skips the % display.
Numbers come from each provider's own model documentation. Update when a new model ships or a provider changes a limit. Match is by substring so we tolerate the various id forms providers use (e.g. "claude-opus-4-7", "claude-opus-4-7-20251119", "claude-opus-4-7[1m]").
Order matters: longer / more specific keys checked first so "claude-opus-4-7[1m]" matches the 1M variant before falling through to the generic "claude-opus-4-7" 200K entry.
func ModelEffectiveContextWindow ¶ added in v0.8.9
ModelEffectiveContextWindow applies the provider's safety percentage for compaction while ModelContextWindow continues to report the advertised max.
func Run ¶
func Run()
Run is the apteva-core entrypoint. cmd/apteva-core/main.go calls this after wiring -ldflags Version/BuildTime via SetVersion.
func RunScenario ¶
RunScenario executes a scenario end-to-end against a freshly-built Thinker. Spawns a goroutine per scenario observer, polls each Phase's Wait condition until it returns true (or times out), runs Verify, and reports token/cost totals at the end.
func SetVersion ¶
func SetVersion(version, buildTime string)
SetVersion is called by cmd/apteva-core/main.go to forward the -ldflags-injected build info from the binary's `package main` into core. Keeping the actual ldflag targets in `package main` of cmd/apteva-core preserves the existing Dockerfile flags ("-X main.Version=...") unchanged.
Types ¶
type APIEvent ¶
type APIEvent struct {
Time time.Time `json:"time"`
Type string `json:"type"` // "thought", "chunk", "reply", "thread_started", "thread_done", "error"
ThreadID string `json:"thread_id"`
Message string `json:"message,omitempty"`
Iteration int `json:"iteration,omitempty"`
Duration string `json:"duration,omitempty"`
}
type AnthropicProvider ¶
type AnthropicProvider struct {
// contains filtered or unexported fields
}
func (*AnthropicProvider) AvailableBuiltinTools ¶
func (p *AnthropicProvider) AvailableBuiltinTools() []BuiltinTool
func (*AnthropicProvider) Chat ¶
func (p *AnthropicProvider) Chat(ctx context.Context, messages []Message, model string, tools []NativeTool, onChunk func(string), onThinking func(string), onToolChunk func(string, string, string)) (ChatResponse, error)
func (*AnthropicProvider) CostPer1M ¶
func (p *AnthropicProvider) CostPer1M() (float64, float64, float64)
func (*AnthropicProvider) Models ¶
func (p *AnthropicProvider) Models() map[ModelTier]string
func (*AnthropicProvider) Name ¶
func (p *AnthropicProvider) Name() string
func (*AnthropicProvider) SetBuiltinTools ¶
func (p *AnthropicProvider) SetBuiltinTools(tools []string)
func (*AnthropicProvider) SupportsNativeTools ¶
func (p *AnthropicProvider) SupportsNativeTools() bool
func (*AnthropicProvider) WithBuiltins ¶
func (p *AnthropicProvider) WithBuiltins(builtins []string) LLMProvider
type AudioFormat ¶
type AudioFormat string
AudioFormat names a wire encoding for realtime audio. Providers map these to their native config values (e.g. OpenAI "pcm16", "g711_ulaw").
const ( AudioPCM16 AudioFormat = "pcm16" AudioG711ULaw AudioFormat = "g711_ulaw" AudioG711ALaw AudioFormat = "g711_alaw" )
type BlobStore ¶
type BlobStore struct {
// contains filtered or unexported fields
}
BlobStore is an in-process, in-memory store for binary payloads that flow between MCP tools without ever entering the LLM context.
When an MCP tool returns a JSON envelope of the form
{"_binary": true, "base64": "...", "mimeType": "...", "size": N}
the store keeps the decoded bytes and the tool-result text is rewritten to a compact handle:
{"_file": true, "ref": "blobref://<id>", "mimeType": "...", "size": N}
The LLM reads and references the handle. When it calls another tool and passes either the scalar "blobref://<id>" or an object {"_file_ref": "..."} as an argument value, the store rehydrates the value back into the full _binary envelope before dispatch — so the downstream tool sees real bytes and the bytes never traverse the LLM boundary.
State is in-memory only. Blobs age out after the configured TTL and are capped in aggregate size; the oldest blob is evicted first when the cap is reached on Put.
func (*BlobStore) Get ¶
Get retrieves bytes and the original mimeType. Accepts either the full "blobref://<id>" ref or a bare id.
func (*BlobStore) Put ¶
Put stores bytes and returns a ref of the form "blobref://<id>". Evicts the oldest blob(s) if the aggregate cap would be exceeded.
func (*BlobStore) RehydrateFileRefs ¶
RehydrateFileRefs walks arg values and, for any value that references a known blob, replaces it with a full _binary envelope JSON string. Two reference forms are accepted:
- The scalar "blobref://<id>" — the LLM passed the ref string directly as an argument value.
- A JSON object {"_file_ref": "blobref://<id>"} — the LLM wrapped the ref to make intent explicit. The bare id form (without the blobref:// prefix) is also accepted inside _file_ref.
Unknown refs (expired / unknown ids) are left untouched so the downstream tool produces a clear error rather than a silent corruption. The original args map is not mutated; a new map is returned.
func (*BlobStore) RewriteBinaryToHandle ¶
RewriteBinaryToHandle inspects a tool-result string. If it parses as a JSON envelope with "_binary":true, the bytes are stored in the BlobStore and a compact "_file" handle string is returned in place of the original envelope. Non-binary text is returned unchanged.
The fast path (string does not contain "_binary") costs an O(n) substring search and no allocations, so this is cheap to call on every MCP tool result.
type BuiltinTool ¶
type BuiltinTool struct {
Type string `json:"type"` // e.g. "code_execution_20250825", "code_interpreter"
Name string `json:"name"` // e.g. "code_execution", "code_interpreter"
}
BuiltinTool defines a provider-side tool (executed by the LLM provider, not by us).
type ChatReply ¶
ChatReply represents a single chat reply parsed out of an audit log.
func ReadChatReplies ¶
ReadChatReplies parses send_reply audit entries into ChatReply records for chat-style scenarios.
type ChatResponse ¶
type ChatResponse struct {
Text string // streamed text content
Reasoning string // accumulated chain-of-thought (Fireworks reasoning_content / OpenRouter reasoning); empty when the provider didn't emit any
ToolCalls []NativeToolCall // structured tool calls WE need to execute
ServerResults []ServerToolResult // tools the PROVIDER already executed
ProviderState *ProviderResponseState // opaque provider output items needed for stateless continuation
Usage TokenUsage
}
ChatResponse is the structured return from Chat().
type Config ¶
type Config struct {
Directive string `json:"directive"`
Mode RunMode `json:"mode,omitempty"`
Unconscious bool `json:"unconscious,omitempty"` // enable background memory consolidation thread
RealtimeEnabled bool `json:"realtime_enabled,omitempty"` // master switch for realtime (voice/audio) threads; off = main never sees the capability and spawn rejects realtime=true
RealtimeVoice string `json:"realtime_voice,omitempty"` // dashboard/default realtime voice (provider validates at session open)
// RealtimeVoiceMCP is the operator-selected subset of attached MCP
// servers exposed to dashboard voice sessions. It is policy/config only;
// realtime execution still uses the normal thread registry and gates.
RealtimeVoiceMCP []string `json:"realtime_voice_mcp,omitempty"`
Providers []ProviderConfig `json:"providers,omitempty"` // multi-provider pool
Provider *ProviderConfig `json:"provider,omitempty"` // legacy single-provider (auto-migrated to Providers on load)
Threads []PersistentThread `json:"threads,omitempty"`
MCPServers []MCPServerConfig `json:"mcp_servers,omitempty"`
Execution ExecutionControlConfig `json:"execution_control,omitempty"`
// contains filtered or unexported fields
}
func (*Config) ClearThreads ¶
func (*Config) GetDefaultProvider ¶
func (c *Config) GetDefaultProvider() *ProviderConfig
GetDefaultProvider returns the default provider config, or nil.
func (*Config) GetDirective ¶
func (*Config) GetExecutionControl ¶ added in v0.3.0
func (c *Config) GetExecutionControl() ExecutionControlConfig
func (*Config) GetMCPServers ¶
func (c *Config) GetMCPServers() []MCPServerConfig
func (*Config) GetProvider ¶
func (c *Config) GetProvider() *ProviderConfig
GetProvider returns the persisted default provider config, or nil. Backward-compatible wrapper around GetDefaultProvider.
func (*Config) GetProviderByName ¶
func (c *Config) GetProviderByName(name string) *ProviderConfig
GetProviderByName returns a provider config by name, or nil.
func (*Config) GetProviders ¶
func (c *Config) GetProviders() []ProviderConfig
GetProviders returns a copy of the providers list.
func (*Config) GetRealtimeVoice ¶ added in v0.8.17
func (*Config) GetRealtimeVoiceMCP ¶ added in v0.8.17
func (*Config) GetThreads ¶
func (c *Config) GetThreads() []PersistentThread
func (*Config) RealtimeEnabledFlag ¶
RealtimeEnabledFlag returns whether realtime (voice/audio) threads are enabled on this instance. Read under the config lock so it reflects the current value if toggled at runtime via the HTTP config endpoint. Naming avoids collision with the bare field.
func (*Config) RemoveMCPServer ¶
func (*Config) RemoveProvider ¶
RemoveProvider removes a provider by name.
func (*Config) RemoveThread ¶
func (*Config) RenameThread ¶ added in v0.8.9
func (c *Config) RenameThread(oldID string, pt PersistentThread) error
func (*Config) ReplaceProviders ¶ added in v0.8.9
func (c *Config) ReplaceProviders(providers []ProviderConfig) error
func (*Config) SaveMCPServer ¶
func (c *Config) SaveMCPServer(cfg MCPServerConfig) error
func (*Config) SaveThread ¶
func (c *Config) SaveThread(pt PersistentThread) error
func (*Config) SetDefaultProvider ¶
SetDefaultProvider marks a provider as default (clears default on others).
func (*Config) SetDirective ¶
func (*Config) SetExecutionControl ¶ added in v0.3.0
func (c *Config) SetExecutionControl(ec ExecutionControlConfig) error
func (*Config) SetProvider ¶
func (c *Config) SetProvider(pc *ProviderConfig) error
SetProvider adds or updates a provider in the list. If it's the only one, marks it default.
func (*Config) SetProviderModel ¶
SetProviderModel updates a single model tier for a provider (default if not specified).
func (*Config) SetProviderName ¶
SetProviderName adds or updates a provider by name with default flag.
func (*Config) SetRealtimeEnabled ¶ added in v0.8.17
func (*Config) SetRealtimeVoice ¶ added in v0.8.17
func (*Config) SetRealtimeVoiceMCP ¶ added in v0.8.17
type ConsoleLogger ¶
type ConsoleLogger struct {
// contains filtered or unexported fields
}
ConsoleLogger renders live telemetry events to stderr with colors. Used in headless mode to provide human-readable output without the TUI.
func NewConsoleLogger ¶
func NewConsoleLogger(t *Telemetry) *ConsoleLogger
func (*ConsoleLogger) Run ¶
func (c *ConsoleLogger) Run()
type ContentPart ¶
type ContentPart struct {
Type string `json:"type"` // "text", "image_url", "input_audio", "audio_url"
Text string `json:"text,omitempty"` // type=text
ImageURL *ImageURL `json:"image_url,omitempty"` // type=image_url
InputAudio *InputAudio `json:"input_audio,omitempty"` // type=input_audio
AudioURL *AudioURL `json:"audio_url,omitempty"` // type=audio_url
}
ContentPart represents a multimodal content block (OpenAI Chat Completions format).
type DirectiveChangeData ¶
type Event ¶
type Event struct {
Type string // one of the Event* constants
From string // source: "main", thread ID, "tui", "api", "tool:name"
To string // target subscriber ID; "" = broadcast
Text string // message payload
ToolName string // tool name (for EventToolChunk)
Parts []ContentPart // optional media (images, audio) attached to this event
ToolResult *ToolResult // optional: structured tool result
// Structured fields (populated for ThinkDone events)
Iteration int
Duration time.Duration
ConsumedEvents []string
Usage TokenUsage
ToolCalls []string
Replies []string
Rate ThinkRate
SleepDuration time.Duration
Model ModelTier
Reasoning ReasoningLevel
MemoryCount int
ThreadCount int
ContextMsgs int // number of messages in context window
ContextChars int // approximate character count of context
Error error
}
Event is the single message type flowing through the system.
type EventBus ¶
type EventBus struct {
// contains filtered or unexported fields
}
EventBus is the central pub/sub hub. All thinkers share one bus.
func NewEventBus ¶
func NewEventBus() *EventBus
func (*EventBus) DropStats ¶
DropStats returns a snapshot of dropped-event counts keyed by subscription id. Useful for tests and ops dashboards to detect backpressure. Order is not guaranteed.
func (*EventBus) HasSubscriber ¶ added in v0.3.0
func (*EventBus) Publish ¶
Publish delivers an event to all matching subscriptions. It never blocks the publisher: when a subscriber's channel is full, the event is discarded and the subscription's Dropped counter is incremented. Drops are logged (rate-limited per subscription) so silent loss is impossible to miss in the logs.
Subscribers are snapshotted under a read lock and delivered to without holding the lock, so one slow channel never stalls other subscribers or blocks concurrent publishers / (un)subscribes.
func (*EventBus) RenameSubscription ¶ added in v0.8.9
RenameSubscription moves an existing subscription without replacing a different subscriber. The channel itself is preserved, including backlog.
func (*EventBus) Subscribe ¶
func (b *EventBus) Subscribe(id string, buffer int) *Subscription
Subscribe creates a targeted subscription. Receives events where To == id, plus broadcasts (To == "").
func (*EventBus) SubscribeAll ¶
func (b *EventBus) SubscribeAll(id string, buffer int) *Subscription
SubscribeAll creates an observer subscription that receives ALL events. Used by TUI, API SSE, tests.
func (*EventBus) SubscribeUnique ¶ added in v0.8.9
func (b *EventBus) SubscribeUnique(id string, buffer int) (*Subscription, error)
SubscribeUnique atomically reserves an ID. Thinker subscriptions use this path so two branches cannot silently replace each other's routing entry.
func (*EventBus) Unsubscribe ¶
Unsubscribe removes a subscription.
type ExecutionCheckpointMeta ¶ added in v0.3.0
type ExecutionCheckpointMeta struct {
ID string `json:"id"`
ThreadID string `json:"thread_id"`
Iteration int `json:"iteration"`
Phase string `json:"phase"`
Tool string `json:"tool,omitempty"`
CallID string `json:"call_id,omitempty"`
Summary string `json:"summary,omitempty"`
Args map[string]string `json:"args,omitempty"`
CreatedAt time.Time `json:"created_at"`
}
type ExecutionCheckpointStore ¶ added in v0.3.0
type ExecutionCheckpointStore struct {
// contains filtered or unexported fields
}
func NewExecutionCheckpointStore ¶ added in v0.3.0
func NewExecutionCheckpointStore() *ExecutionCheckpointStore
func (*ExecutionCheckpointStore) Capture ¶ added in v0.3.0
func (s *ExecutionCheckpointStore) Capture(t *Thinker, gate ExecutionGate) *ExecutionCheckpointMeta
func (*ExecutionCheckpointStore) Get ¶ added in v0.3.0
func (s *ExecutionCheckpointStore) Get(id string) (*executionCheckpoint, bool)
func (*ExecutionCheckpointStore) ListMeta ¶ added in v0.3.0
func (s *ExecutionCheckpointStore) ListMeta() []ExecutionCheckpointMeta
func (*ExecutionCheckpointStore) RestoreTarget ¶ added in v0.3.0
func (s *ExecutionCheckpointStore) RestoreTarget(threadID string) *ExecutionCheckpointMeta
func (*ExecutionCheckpointStore) RestoreTargetBeforeGate ¶ added in v0.3.0
func (s *ExecutionCheckpointStore) RestoreTargetBeforeGate(gate ExecutionGate) *ExecutionCheckpointMeta
type ExecutionControlAction ¶ added in v0.3.0
type ExecutionControlAction struct {
Action string `json:"action"`
ThreadID string `json:"thread_id,omitempty"`
CheckpointID string `json:"checkpoint_id,omitempty"`
Mode ExecutionControlMode `json:"mode,omitempty"`
}
type ExecutionControlConfig ¶ added in v0.3.0
type ExecutionControlConfig struct {
Mode ExecutionControlMode `json:"mode,omitempty"`
Scope string `json:"scope,omitempty"`
Breakpoints []string `json:"breakpoints,omitempty"`
Follow string `json:"follow,omitempty"`
}
type ExecutionControlMode ¶ added in v0.3.0
type ExecutionControlMode string
const ( ExecutionAuto ExecutionControlMode = "auto" ExecutionPaused ExecutionControlMode = "paused" ExecutionStep ExecutionControlMode = "step" )
type ExecutionControlStatus ¶ added in v0.3.0
type ExecutionControlStatus struct {
Mode ExecutionControlMode `json:"mode"`
Scope string `json:"scope"`
Breakpoints []string `json:"breakpoints"`
Follow string `json:"follow"`
Waiting bool `json:"waiting"`
Phase string `json:"phase,omitempty"`
ActiveThreadID string `json:"active_thread_id,omitempty"`
Iteration int `json:"iteration,omitempty"`
Tool string `json:"tool,omitempty"`
CallID string `json:"call_id,omitempty"`
Summary string `json:"summary,omitempty"`
Args map[string]string `json:"args,omitempty"`
WaitingCount int `json:"waiting_count,omitempty"`
CanRestore bool `json:"can_restore,omitempty"`
RestoreCheckpointID string `json:"restore_checkpoint_id,omitempty"`
RestoreSummary string `json:"restore_summary,omitempty"`
RestorePhase string `json:"restore_phase,omitempty"`
}
type ExecutionController ¶ added in v0.3.0
type ExecutionController struct {
// contains filtered or unexported fields
}
func NewExecutionController ¶ added in v0.3.0
func NewExecutionController(cfg ExecutionControlConfig) *ExecutionController
func (*ExecutionController) ApplyConfig ¶ added in v0.3.0
func (c *ExecutionController) ApplyConfig(cfg ExecutionControlConfig)
func (*ExecutionController) CancelThread ¶ added in v0.3.0
func (c *ExecutionController) CancelThread(threadID string) bool
func (*ExecutionController) Config ¶ added in v0.3.0
func (c *ExecutionController) Config() ExecutionControlConfig
func (*ExecutionController) Control ¶ added in v0.3.0
func (c *ExecutionController) Control(action ExecutionControlAction) (ExecutionControlStatus, error)
func (*ExecutionController) ShouldGate ¶ added in v0.3.0
func (c *ExecutionController) ShouldGate(phase ExecutionPhase) bool
func (*ExecutionController) Status ¶ added in v0.3.0
func (c *ExecutionController) Status() ExecutionControlStatus
func (*ExecutionController) Wait ¶ added in v0.3.0
func (c *ExecutionController) Wait(gate ExecutionGate, quit <-chan struct{}, emit func(string, ExecutionPhaseData)) bool
type ExecutionGate ¶ added in v0.3.0
type ExecutionPhase ¶ added in v0.3.0
type ExecutionPhase string
const ( ExecutionPhaseIterationStart ExecutionPhase = "iteration.start" ExecutionPhaseInputReady ExecutionPhase = "input.ready" ExecutionPhaseLLMStart ExecutionPhase = "llm.start" ExecutionPhaseLLMDone ExecutionPhase = "llm.done" ExecutionPhaseToolBefore ExecutionPhase = "tool.before" ExecutionPhaseToolAfter ExecutionPhase = "tool.after" ExecutionPhaseIterationDone ExecutionPhase = "iteration.done" ExecutionPhaseSleepBefore ExecutionPhase = "sleep.before" )
type ExecutionPhaseData ¶ added in v0.3.0
type ExecutionPhaseData struct {
ThreadID string `json:"thread_id"`
Iteration int `json:"iteration"`
Phase string `json:"phase"`
Tool string `json:"tool,omitempty"`
CallID string `json:"call_id,omitempty"`
Summary string `json:"summary,omitempty"`
Args map[string]string `json:"args,omitempty"`
ResultPreview string `json:"result_preview,omitempty"`
ParentThreadID string `json:"parent_thread_id,omitempty"`
}
type ExtraSystemBlock ¶
type ExtraSystemBlock struct {
Preview string `json:"preview"` // first ~60 chars, newlines stripped
Bytes int `json:"bytes"`
}
ExtraSystemBlock describes a role=system message that sits AFTER messages[0] — the [memories] block appended each iteration is the canonical example, but anything the thinker injects ends up here.
type GoogleModel ¶
type GoogleModel struct {
ID string
InputPer1M float64
CachedPer1M float64
OutputPer1M float64
MaxOutputTokens int
}
GoogleModel holds metadata for a Gemini model.
type GoogleProvider ¶
type GoogleProvider struct {
// contains filtered or unexported fields
}
func (*GoogleProvider) ActiveModel ¶
func (p *GoogleProvider) ActiveModel() string
ActiveModel returns the current model ID.
func (*GoogleProvider) AvailableBuiltinTools ¶
func (p *GoogleProvider) AvailableBuiltinTools() []BuiltinTool
func (*GoogleProvider) AvailableModels ¶
func (p *GoogleProvider) AvailableModels() []string
AvailableModels returns all supported Gemini model IDs in cycle order.
func (*GoogleProvider) Chat ¶
func (p *GoogleProvider) Chat(ctx context.Context, messages []Message, model string, tools []NativeTool, onChunk func(string), onThinking func(string), onToolChunk func(string, string, string)) (ChatResponse, error)
func (*GoogleProvider) Models ¶
func (p *GoogleProvider) Models() map[ModelTier]string
func (*GoogleProvider) Name ¶
func (p *GoogleProvider) Name() string
func (*GoogleProvider) SetBuiltinTools ¶
func (p *GoogleProvider) SetBuiltinTools(tools []string)
func (*GoogleProvider) SetModel ¶
func (p *GoogleProvider) SetModel(modelID string)
SetModel updates the active model. Called from TUI model cycling.
func (*GoogleProvider) SupportsNativeTools ¶
func (p *GoogleProvider) SupportsNativeTools() bool
func (*GoogleProvider) WithBuiltins ¶
func (p *GoogleProvider) WithBuiltins(builtins []string) LLMProvider
type GoogleRealtimeProvider ¶ added in v0.8.17
type GoogleRealtimeProvider struct {
// contains filtered or unexported fields
}
GoogleRealtimeProvider implements the Gemini Live bidirectional WebSocket API. Gemini uses its own BidiGenerateContent protocol, so only the generic RealtimeProvider boundary is shared with OpenAI/xAI sessions.
func NewGoogleRealtimeProvider ¶ added in v0.8.17
func NewGoogleRealtimeProvider(apiKey string) *GoogleRealtimeProvider
func (*GoogleRealtimeProvider) DefaultTranscriptionModel ¶ added in v0.8.17
func (p *GoogleRealtimeProvider) DefaultTranscriptionModel() string
Gemini Live provides transcription as part of the session setup rather than through a separately named transcription model.
func (*GoogleRealtimeProvider) DefaultVoice ¶ added in v0.8.17
func (p *GoogleRealtimeProvider) DefaultVoice() string
func (*GoogleRealtimeProvider) Models ¶ added in v0.8.17
func (p *GoogleRealtimeProvider) Models() map[ModelTier]string
func (*GoogleRealtimeProvider) Name ¶ added in v0.8.17
func (p *GoogleRealtimeProvider) Name() string
func (*GoogleRealtimeProvider) Open ¶ added in v0.8.17
func (p *GoogleRealtimeProvider) Open(ctx context.Context, opts RealtimeSessionOpts) (RealtimeSession, error)
func (*GoogleRealtimeProvider) Pricing ¶ added in v0.8.17
func (p *GoogleRealtimeProvider) Pricing(string) RealtimePricing
type IndexEntry ¶
type IndexEntry struct {
Server string
LocalName string // raw MCP name (for example "send")
Name string // fully-qualified (e.g. "storage_files_upload")
Description string
NoSpawn bool // sub-threads cannot see this tool in search
LoadMode ToolLoadMode
// contains filtered or unexported fields
}
IndexEntry is one tool's worth of searchable metadata.
type InputAudio ¶
type LLMChunkData ¶
type LLMDoneData ¶
type LLMDoneData struct {
Model string `json:"model"`
Reasoning string `json:"reasoning,omitempty"`
TokensIn int `json:"tokens_in"`
TokensCached int `json:"tokens_cached"`
CacheWriteTokens int `json:"cache_write_tokens,omitempty"`
TokensOut int `json:"tokens_out"`
DurationMs int64 `json:"duration_ms"`
// cost_usd is no longer populated by core — pricing lives in the
// server, which enriches llm.done events with a canonical
// cost_usd on ingest. Removing the field from the Go type keeps
// core free of pricing data, but the wire format is still the
// same map-of-strings consumed by dashboards and persisted by
// the server.
Iteration int `json:"iteration"`
Rate string `json:"rate"`
ContextMsgs int `json:"context_msgs"`
ContextChars int `json:"context_chars"`
ContextTokensEst int `json:"context_tokens_est,omitempty"`
RequestContextMsgs int `json:"request_context_msgs,omitempty"`
RequestContextChars int `json:"request_context_chars,omitempty"`
RequestTokensEst int `json:"request_context_tokens_est,omitempty"`
// MaxContextTokens is the model's advertised input-context window
// (in tokens). Comes from a static lookup keyed on the model id —
// see ModelContextWindow. 0 when the model isn't in the table; UI
// should treat 0 as "unknown" and skip percentage rendering.
MaxContextTokens int `json:"max_context_tokens,omitempty"`
MemoryCount int `json:"memory_count"`
ThreadCount int `json:"thread_count"`
Message string `json:"message,omitempty"`
NativeToolCount int `json:"native_tool_count,omitempty"`
ActiveMCPCount int `json:"active_mcp_count,omitempty"`
AlwaysMCPCount int `json:"always_mcp_count,omitempty"`
DeferredMCPCount int `json:"deferred_mcp_count,omitempty"`
ToolMode string `json:"tool_mode,omitempty"`
PromptCacheEpoch uint64 `json:"prompt_cache_epoch"`
PromptCacheResetReason string `json:"prompt_cache_reset_reason,omitempty"`
PromptCacheIdentityHash string `json:"prompt_cache_identity_hash,omitempty"`
PromptCacheStablePrefixHash string `json:"prompt_cache_stable_prefix_hash,omitempty"`
PromptCacheRequestHash string `json:"prompt_cache_request_hash,omitempty"`
PromptCacheCommonPrefixBytes int `json:"prompt_cache_common_prefix_bytes,omitempty"`
}
type LLMErrorData ¶
type LLMProvider ¶
type LLMProvider interface {
// Chat sends messages and streams the response.
// ctx is propagated to the underlying HTTP request so cancellation
// (user abort, shutdown) unblocks an in-flight stream cleanly.
// tools: native tool definitions to include in the request (nil = no tools).
// onChunk is called for each text token chunk as it arrives.
// onThinking is called for each reasoning/thinking token (separate from output).
// onToolChunk is called for each tool argument chunk as it streams
// (toolName, callID, argChunk). callID disambiguates two parallel
// calls of the same tool in one response — providers pass their own
// stable per-call id (tc.Index for OpenAI, content_block id for
// Anthropic). Empty string is acceptable.
// Returns ChatResponse with text, tool calls, and usage.
Chat(ctx context.Context, messages []Message, model string, tools []NativeTool, onChunk func(string), onThinking func(string), onToolChunk func(toolName, callID, chunk string)) (ChatResponse, error)
// Models returns model IDs for each tier.
Models() map[ModelTier]string
// Name returns the provider name for display/telemetry.
Name() string
// CostPer1M returns pricing per 1M tokens: (input, cached, output).
CostPer1M() (float64, float64, float64)
// SupportsNativeTools returns true if this provider handles structured tool calling.
SupportsNativeTools() bool
// AvailableBuiltinTools returns built-in tools this provider supports.
AvailableBuiltinTools() []BuiltinTool
// SetBuiltinTools enables specific built-in tools.
SetBuiltinTools(tools []string)
// WithBuiltins returns a shallow clone of this provider with only the specified builtins enabled.
// If builtins is nil, returns the provider unchanged (inherit all).
WithBuiltins(builtins []string) LLMProvider
}
LLMProvider abstracts the LLM API call. All thinking, threading, tool handling stays in the Thinker. The provider only handles: send messages → get streaming response.
func NewAnthropicProvider ¶
func NewAnthropicProvider(apiKey string) LLMProvider
func NewFireworksProvider ¶
func NewFireworksProvider(apiKey string) LLMProvider
func NewGoogleProvider ¶
func NewGoogleProvider(apiKey string) LLMProvider
func NewNvidiaProvider ¶
func NewNvidiaProvider(apiKey string) LLMProvider
NewNvidiaProvider wires up NVIDIA's NIM hosted catalog. They expose an OpenAI-compatible Chat Completions endpoint at integrate.api.nvidia.com, so we reuse OpenAICompatProvider verbatim — just the base URL and default model slugs are NVIDIA-specific. Pricing is left at zero by default because NIM billing is account-scoped rather than per-token-listed, so cost projections in the dashboard stats bar will stay at $0 unless the user manually overrides these costs via config.
func NewOllamaProvider ¶
func NewOllamaProvider(host string) LLMProvider
func NewOpenAICodexProvider ¶ added in v0.3.0
func NewOpenAICodexProvider(accessToken string) LLMProvider
func NewOpenAINativeProvider ¶
func NewOpenAINativeProvider(apiKey string) LLMProvider
func NewOpenAIProvider ¶
func NewOpenAIProvider(apiKey string) LLMProvider
func NewOpenCodeGoProvider ¶
func NewOpenCodeGoProvider(apiKey string) LLMProvider
NewOpenCodeGoProvider — flat-rate subscription gateway from opencode.ai/go that fronts the same Kimi K2.6 we use via Fireworks plus Qwen / GLM / MiMo variants under one OpenAI-compatible endpoint.
Per-token costs are placeholders (0/0/0) because OpenCode Go bills per subscription, not per call — the server's model_fetch.go pricing table reports the same so the dashboard's per-call $ figure stays blank rather than misleadingly nonzero.
Defaults: glm-5.2 across all three tiers. With a flat-rate plan the per-iteration cost incentive for choosing weaker small/medium models does not apply, so the agent uses the same capable model end-to-end. Users can still override individual tiers in the dashboard provider settings.
func NewVeniceProvider ¶
func NewVeniceProvider(apiKey string) LLMProvider
NewVeniceProvider — privacy-focused inference gateway at venice.ai. OpenAI-compatible /chat/completions endpoint, large rotating catalog (Llama, Qwen, GLM, Mistral, plus Claude/Grok/Gemini reseller variants). Pricing varies per model and is set per-account in their dashboard, so per-token costs are left at zero here — the model picker / picker dropdown is the source of truth for what's available right now.
func NewXAIProvider ¶ added in v0.8.17
func NewXAIProvider(apiKey string) LLMProvider
type MCPConn ¶
type MCPConn interface {
GetName() string
ListTools() ([]mcpToolDef, error)
CallTool(name string, args map[string]string) (ToolResponse, error)
Close()
}
MCPConn is the interface for any MCP server connection (stdio or HTTP)
type MCPHTTPServer ¶
type MCPHTTPServer struct {
Name string
// contains filtered or unexported fields
}
MCPHTTPServer connects to an MCP server via Streamable HTTP transport. Per MCP spec 2025-03-26: POST for requests, single endpoint.
Compatibility notes for real-world hosted MCP servers (observed against Composio's backend.composio.dev):
- Some servers host the MCP endpoint at a sub-path and respond to the parent path with HTTP 307 → Location (appending "/mcp"). Go's default client strips the POST body on 307 redirects, so we disable auto- redirects and re-issue the POST manually with the body intact. After the first successful hop we store the resolved URL and skip the redirect on every subsequent call.
- Some servers return SSE-framed responses (`Content-Type: text/event-stream` with one or more `event: message\ndata: {...}\n\n` frames) instead of plain JSON, even for POST requests. We parse both.
func (*MCPHTTPServer) CallTool ¶
func (s *MCPHTTPServer) CallTool(name string, args map[string]string) (ToolResponse, error)
func (*MCPHTTPServer) CallToolTyped ¶ added in v0.8.1
func (s *MCPHTTPServer) CallToolTyped(name string, args map[string]string, inputSchema map[string]any) (ToolResponse, error)
func (*MCPHTTPServer) Close ¶
func (s *MCPHTTPServer) Close()
func (*MCPHTTPServer) GetName ¶
func (s *MCPHTTPServer) GetName() string
func (*MCPHTTPServer) ListTools ¶
func (s *MCPHTTPServer) ListTools() ([]mcpToolDef, error)
type MCPServer ¶
type MCPServer struct {
Name string
// contains filtered or unexported fields
}
MCPServer manages a running MCP server subprocess (stdio transport)
func (*MCPServer) CallToolTyped ¶ added in v0.8.1
type MCPServerConfig ¶
type MCPServerConfig struct {
Name string `json:"name"`
Command string `json:"command,omitempty"` // stdio transport
Args []string `json:"args,omitempty"` // stdio transport
Env map[string]string `json:"env,omitempty"` // stdio transport
Transport string `json:"transport,omitempty"` // "stdio" (default) or "http"
URL string `json:"url,omitempty"` // http transport
// ToolLoading controls prompt-schema availability independently from
// connection and authorization. Always-loaded tools are present on every
// authorized model request; deferred tools require search/preload; auto
// preserves the global eager/discovery threshold behavior.
ToolLoading *MCPToolLoadingConfig `json:"tool_loading,omitempty"`
// NoSpawn, when true, hides this server's tools from sub-thread
// search_tools results and refuses sub-thread spawn(mcps=[...])
// attachments. Used for infrastructure-level servers the host
// wires in for main-thread-only responsibilities (management
// gateway, outbound channel bridges) where letting a worker
// invoke them would be a privilege escalation. Core has no
// knowledge of which names are "system" — the host sets this
// flag when registering those entries. The privileged HTTP spawn
// path (POST /threads/{id}) sets SpawnOpts.BypassNoSpawn to
// punch through this filter for system-initiated workers
// (channelchat's chat-handling thread needs `channels`).
NoSpawn bool `json:"no_spawn,omitempty"`
}
MCPServerConfig is stored in config.json.
Note: the legacy `main_access` field is intentionally absent. Earlier versions of core split MCPs into "main" (tools eagerly registered to the main thread) and "catalog" (tools held off main, attachable only by spawning a sub-thread with mcp="name"). That distinction is gone: every MCP attached here is connected and indexed, every thread activates the subset it needs via search_tools or spawn-time MCPNames. Old configs containing main_access:true|false deserialize cleanly — json.Unmarshal silently drops the unknown field.
type MCPServerInfo ¶
type MCPServerInfo struct {
Name string
ToolCount int
AlwaysCount int
AutoCount int
DeferredCount int
}
MCPServerInfo is a lightweight catalog entry for an MCP server. Main uses this to show available servers in its prompt without registering all tools.
type MCPToolLoadingConfig ¶ added in v0.8.17
type MCPToolLoadingConfig struct {
Default ToolLoadMode `json:"default,omitempty"`
Tools map[string]ToolLoadMode `json:"tools,omitempty"`
}
MCPToolLoadingConfig sets a server-wide default plus optional overrides for individual tools. Tool override keys are the raw names returned by the MCP server (for example "send"), not core's qualified name ("channels_send"). A nil config is equivalent to {"default":"auto"} for backward compatibility with every existing mcp_servers entry.
type MemoryRecallMatch ¶ added in v0.8.9
type MemoryRecallMatch struct {
Record MemoryRecord
Score float64
Signal float64
}
MemoryRecallMatch retains scoring metadata for request telemetry. All records intentionally share one path regardless of their free-form tags.
type MemoryRecord ¶
type MemoryRecord struct {
ID string `json:"id"`
TS time.Time `json:"ts"`
Content string `json:"content,omitempty"`
Tags []string `json:"tags,omitempty"`
Weight float64 `json:"weight,omitempty"`
Supersedes string `json:"supersedes,omitempty"`
Embedding []float64 `json:"embedding,omitempty"`
// Tombstone bits.
Tombstone bool `json:"tombstone,omitempty"`
IDTarget string `json:"id_target,omitempty"`
Reason string `json:"reason,omitempty"`
}
MemoryRecord is one line in memory.jsonl. Either a memory or a tombstone — never both.
func (MemoryRecord) IsTombstone ¶
func (r MemoryRecord) IsTombstone() bool
IsTombstone reports whether this record is a tombstone marker.
type MemoryStore ¶
type MemoryStore struct {
// contains filtered or unexported fields
}
MemoryStore is the in-process journal owner. Append-only on disk, rebuilds the active-set on load.
func NewMemoryStore ¶
func NewMemoryStore(apiKey string) *MemoryStore
NewMemoryStore opens (or creates) memory.jsonl at the cwd, picks an embedding backend from env, runs the legacy-format migration if needed, and returns a ready store. apiKey is kept for backward- compat as a forced Fireworks key when env-based detection finds nothing — passing "" defers entirely to env.
func (*MemoryStore) Active ¶
func (ms *MemoryStore) Active() []MemoryRecord
Active returns the current active memories — everything not tombstoned and not superseded by a newer record. Returned slice is a copy; callers can mutate / sort freely.
func (*MemoryStore) All ¶
func (ms *MemoryStore) All() []MemoryRecord
All returns every record in insertion order, including tombstones and superseded entries. Used by the dashboard memory panel for debugging / audit.
func (*MemoryStore) BuildContext ¶
func (ms *MemoryStore) BuildContext(records []MemoryRecord) string
BuildContext renders a slice of memories as the dynamic-context [memories] block. Header is explicit about provenance so the LLM reads these as memories, not current statements — that's the structural defense against the fabricated-approvals failure mode.
func (*MemoryStore) Count ¶
func (ms *MemoryStore) Count() int
Count returns the number of currently-active memories. Used by telemetry and the unconscious's directive ("you have N memories").
func (*MemoryStore) Drop ¶
func (ms *MemoryStore) Drop(id, reason string) error
Drop tombstones a memory by id. reason is required.
func (*MemoryStore) Enabled ¶
func (ms *MemoryStore) Enabled() bool
Enabled reports whether embeddings are available. Lexical scoring still works either way; callers that ONLY need embeddings (RAG tool indexing in api.go / thinker.go) check this to short-circuit.
func (*MemoryStore) HasID ¶
func (ms *MemoryStore) HasID(id string) bool
HasID reports whether a record with this id exists in the journal (active, tombstoned, or superseded — anything that was ever written). Used by callers that want to decide between RememberWithID (insert) and Supersede (update) without racing on the not-found error.
func (*MemoryStore) Recall ¶
func (ms *MemoryStore) Recall(query string, n int) []MemoryRecord
Recall returns the top-N active memories scored by relevance to the given query context — multi-factor: cosine × weight × decay, with a lexical fallback when no embedding backend.
Used by buildDynamicTurnContext for auto-injection at every turn. N is typically 3–5 with a token-budget cap applied by the caller.
func (*MemoryStore) RecallMatches ¶ added in v0.8.9
func (ms *MemoryStore) RecallMatches(query string, n int) []MemoryRecallMatch
RecallMatches is Recall with score metadata and content deduplication.
func (*MemoryStore) Remember ¶
Remember writes a fresh memory and returns its id. weight defaults to 0.7 if zero. tags may be nil. Embedding is computed when a backend is configured; on failure the record is still written without an embedding (lexical recall continues to work).
func (*MemoryStore) RememberWithID ¶
func (ms *MemoryStore) RememberWithID(id, content string, tags []string, weight float64) (string, error)
RememberWithID is Remember with a caller-supplied id instead of a freshly-minted ULID. Required for deterministic platform-managed records, where re-pushing the same source upserts via Supersede rather than creating a duplicate row.
Errors if id is empty (use Remember) or if the id already exists (caller should call HasID first and route to Supersede). Refusing silent overwrite keeps the journal append-only semantics intact.
func (*MemoryStore) Search ¶
func (ms *MemoryStore) Search(query string, limit int) []MemoryRecord
Search returns active memories matching the query. Embedding-based when a backend is configured, lexical (BM25-ish over content + tags) otherwise. Used by the unconscious's memory_search tool to look up existing memories before deciding remember vs supersede.
func (*MemoryStore) Supersede ¶
func (ms *MemoryStore) Supersede(oldID, content string, tags []string, weight float64, reason string) (string, error)
Supersede writes a NEW memory and a tombstone for oldID, linking them via the new record's Supersedes field. Both records are appended atomically (one after the other, no other writer in between because we hold the lock for both). Returns the new id.
func (*MemoryStore) UpsertTargetID ¶ added in v0.8.8
func (ms *MemoryStore) UpsertTargetID(id string) (string, bool)
UpsertTargetID returns the active record that should be superseded when a caller upserts a deterministic id. The first push writes the deterministic id itself. Later pushes create replacement records with generated ids, so a repeated push of the original id must supersede the latest active replacement, not the already-dead original.
type Message ¶
type Message struct {
Role string `json:"role"`
Content string `json:"content"`
Parts []ContentPart `json:"parts,omitempty"` // multimodal content
ToolCalls []NativeToolCall `json:"tool_calls,omitempty"` // assistant messages: structured tool calls
ToolResults []ToolResult `json:"tool_results,omitempty"` // user messages: results for prior tool calls
ProviderState *ProviderResponseState `json:"provider_state,omitempty"` // opaque state for exact provider replay
// RequestContext marks transient retrieval context. It is carried only in
// the prepared provider request and is never written to session history.
RequestContext bool `json:"-"`
// Reasoning is the model's chain-of-thought from the turn that
// produced this message. We replay it back to the provider on
// subsequent turns because Moonshot (Kimi K2.6 via OpenCode Go)
// requires `reasoning_content` to be present on assistant
// tool_call messages when thinking mode is enabled — without it
// every multi-turn tool flow 400s. Other providers ignore it.
Reasoning string `json:"reasoning,omitempty"`
}
func (Message) TextContent ¶
TextContent returns the text content of a message, whether plain Content or from Parts.
type ModelCapabilities ¶ added in v0.8.9
type ModelCapabilities struct {
ContextWindow int `json:"context_window,omitempty"`
MaxContextWindow int `json:"max_context_window,omitempty"`
EffectiveContextWindowPercent int `json:"effective_context_window_percent,omitempty"`
DefaultReasoningLevel string `json:"default_reasoning_level,omitempty"`
SupportedReasoningLevels []ModelReasoningCapability `json:"supported_reasoning_levels,omitempty"`
InputModalities []string `json:"input_modalities,omitempty"`
SupportsParallelToolCalls *bool `json:"supports_parallel_tool_calls,omitempty"`
SupportsReasoningSummaries *bool `json:"supports_reasoning_summaries,omitempty"`
SupportsImageDetailOriginal *bool `json:"supports_image_detail_original,omitempty"`
SupportsSearchTool *bool `json:"supports_search_tool,omitempty"`
}
type ModelReasoningCapability ¶ added in v0.8.9
type ModelReasoningCapability struct {
Effort string `json:"effort"`
Description string `json:"description,omitempty"`
}
ProviderConfig persists a provider and its model selections.
type NativeTool ¶
type NativeTool struct {
Name string `json:"name"`
Description string `json:"description"`
Parameters map[string]any `json:"parameters"` // JSON Schema
}
NativeTool defines a tool sent to the provider API.
type NativeToolCall ¶
type NativeToolCall struct {
ID string `json:"id"` // provider call ID for matching results
OutputItemID string `json:"output_item_id,omitempty"` // Responses output item ID (fc_...), distinct from call ID
Status string `json:"status,omitempty"` // Responses output item status for exact replay/debugging
Name string `json:"name"`
Args map[string]string `json:"args"`
ThoughtSignature string `json:"thought_signature,omitempty"` // Gemini: encrypted reasoning state
}
NativeToolCall is a structured tool call returned by the provider.
type NativeToolSize ¶
type NativeToolSize struct {
Name string `json:"name"`
Kind string `json:"kind"` // "core" | "mcp" | "local"
Bytes int `json:"bytes"`
}
NativeToolSize describes one entry in the tools[] payload sent to the LLM. Kind separates core loop tools from local / MCP-main-access tools so the user can see which flavor is burning bytes.
type OpenAICompatProvider ¶
type OpenAICompatProvider struct {
// contains filtered or unexported fields
}
OpenAICompatProvider works with any OpenAI-compatible API: Fireworks, OpenAI, Ollama, Together, Groq, etc.
func (*OpenAICompatProvider) AvailableBuiltinTools ¶
func (p *OpenAICompatProvider) AvailableBuiltinTools() []BuiltinTool
func (*OpenAICompatProvider) Chat ¶
func (p *OpenAICompatProvider) Chat(ctx context.Context, messages []Message, model string, tools []NativeTool, onChunk func(string), onThinking func(string), onToolChunk func(string, string, string)) (ChatResponse, error)
func (*OpenAICompatProvider) CostPer1M ¶
func (p *OpenAICompatProvider) CostPer1M() (float64, float64, float64)
func (*OpenAICompatProvider) Models ¶
func (p *OpenAICompatProvider) Models() map[ModelTier]string
func (*OpenAICompatProvider) Name ¶
func (p *OpenAICompatProvider) Name() string
func (*OpenAICompatProvider) SetBuiltinTools ¶
func (p *OpenAICompatProvider) SetBuiltinTools(tools []string)
func (*OpenAICompatProvider) SupportsNativeTools ¶
func (p *OpenAICompatProvider) SupportsNativeTools() bool
func (*OpenAICompatProvider) WithBuiltins ¶
func (p *OpenAICompatProvider) WithBuiltins(builtins []string) LLMProvider
type OpenAINativeProvider ¶
type OpenAINativeProvider struct {
// contains filtered or unexported fields
}
OpenAINativeProvider uses the OpenAI Responses API for web_search, code_interpreter, and other OpenAI-specific features. For OpenAI-compatible endpoints (Fireworks, Ollama, etc.), use OpenAICompatProvider.
func (*OpenAINativeProvider) AvailableBuiltinTools ¶
func (p *OpenAINativeProvider) AvailableBuiltinTools() []BuiltinTool
func (*OpenAINativeProvider) Chat ¶
func (p *OpenAINativeProvider) Chat(ctx context.Context, messages []Message, model string, tools []NativeTool, onChunk func(string), onThinking func(string), onToolChunk func(string, string, string)) (ChatResponse, error)
func (*OpenAINativeProvider) CostPer1M ¶
func (p *OpenAINativeProvider) CostPer1M() (float64, float64, float64)
func (*OpenAINativeProvider) Models ¶
func (p *OpenAINativeProvider) Models() map[ModelTier]string
func (*OpenAINativeProvider) Name ¶
func (p *OpenAINativeProvider) Name() string
func (*OpenAINativeProvider) SetBuiltinTools ¶
func (p *OpenAINativeProvider) SetBuiltinTools(tools []string)
func (*OpenAINativeProvider) SupportsNativeTools ¶
func (p *OpenAINativeProvider) SupportsNativeTools() bool
func (*OpenAINativeProvider) WithBuiltins ¶
func (p *OpenAINativeProvider) WithBuiltins(builtins []string) LLMProvider
func (*OpenAINativeProvider) WithReasoning ¶ added in v0.5.0
func (p *OpenAINativeProvider) WithReasoning(settings ReasoningSettings) LLMProvider
type OpenAIRealtimeProvider ¶
type OpenAIRealtimeProvider struct {
// contains filtered or unexported fields
}
OpenAIRealtimeProvider implements OpenAI's GA Realtime WebSocket API.
func NewOpenAIRealtimeProvider ¶
func NewOpenAIRealtimeProvider(apiKey string) *OpenAIRealtimeProvider
NewOpenAIRealtimeProvider constructs a provider bound to the given API key. Models map can be overridden via config; defaults pick OpenAI's current GA realtime models.
func (*OpenAIRealtimeProvider) DefaultTranscriptionModel ¶ added in v0.8.17
func (p *OpenAIRealtimeProvider) DefaultTranscriptionModel() string
func (*OpenAIRealtimeProvider) DefaultVoice ¶
func (p *OpenAIRealtimeProvider) DefaultVoice() string
func (*OpenAIRealtimeProvider) Models ¶
func (p *OpenAIRealtimeProvider) Models() map[ModelTier]string
func (*OpenAIRealtimeProvider) Name ¶
func (p *OpenAIRealtimeProvider) Name() string
func (*OpenAIRealtimeProvider) Open ¶
func (p *OpenAIRealtimeProvider) Open(ctx context.Context, opts RealtimeSessionOpts) (RealtimeSession, error)
Open dials the OpenAI Realtime WebSocket, sends the initial session.update, and returns a live session. ctx governs the dial + handshake; the returned session manages its own goroutines for reads/writes and will surface a RealtimeEventSessionEnded event when the connection drops.
func (*OpenAIRealtimeProvider) Pricing ¶ added in v0.8.17
func (p *OpenAIRealtimeProvider) Pricing(model string) RealtimePricing
type PersistentThread ¶
type PersistentThread struct {
ID string `json:"id"`
Name string `json:"name,omitempty"` // human-readable label; empty = display as ID
ParentID string `json:"parent_id,omitempty"` // empty = child of main
Depth int `json:"depth,omitempty"` // 0 = main's direct child
System bool `json:"system,omitempty"` // system thread (can't be killed by LLM)
Directive string `json:"directive"`
Tools []string `json:"tools"`
MCPNames []string `json:"mcp_names,omitempty"` // MCP servers to connect on respawn
Model string `json:"model,omitempty"` // starting model tier: large, medium, small
Reasoning string `json:"reasoning,omitempty"` // starting reasoning effort: auto, low, medium, high, ...
Provider string `json:"provider,omitempty"` // provider selected for this thread
Realtime bool `json:"realtime,omitempty"` // spawn as a realtime (voice/audio) thread
Voice string `json:"voice,omitempty"` // realtime voice id (e.g. "marin"); empty = provider default
}
type Phase ¶
type Phase struct {
Name string
Setup func(t *testing.T, dir string) // optional: inject data before this phase
Wait func(t *testing.T, dir string, th *Thinker) bool // poll condition (return true when done)
Verify func(t *testing.T, dir string, th *Thinker) // optional: assertions after Wait succeeds
Timeout time.Duration
}
Phase is a step in a scenario.
type PromptComposition ¶
type PromptComposition struct {
System SystemBreakdown `json:"system"`
NativeTools []NativeToolSize `json:"native_tools"`
NativeBytes int `json:"native_bytes"`
ExtraSystem []ExtraSystemBlock `json:"extra_system"` // role=system msgs after messages[0]
ExtraBytes int `json:"extra_bytes"`
ConvBytes int `json:"conv_bytes"` // user/assistant/tool/other messages
GrandTotal int `json:"grand_total"`
ModelMaxTokens int `json:"model_max_tokens,omitempty"`
}
buildComposition is a read-only instrumentation pass over a thread's current messages + live registry state. It produces a size breakdown of everything the LLM actually sees on a call:
System text (messages[0].Content) split into the sections that buildSystemPrompt emits. No double-pass required — we just look for the known "[SECTION]" markers in the text that was already built.
Native tool schemas (registry.NativeTools). Each tool's name + description + JSON-serialized Parameters contributes to the provider's `tools[]` payload; we estimate its on-wire size by marshalling it.
The separate "[memories]" system message and any other role=system messages appended after the main prompt (they all travel as prompt tokens too).
All remaining user / assistant / tool messages rolled up so the user sees grand_total = everything sent on the next call.
Pure read, pure compute. Nothing on the hot path calls this.
type PromptTokensDetails ¶
type ProviderConfig ¶
type ProviderConfig struct {
Name string `json:"name"` // "google", "openai", "anthropic", "fireworks", "xai", "ollama", or a "*-realtime" companion
Default bool `json:"default,omitempty"` // true = default provider (first match wins)
Models map[string]string `json:"models,omitempty"` // "large" → model ID, "medium" → ..., "small" → ...
ModelCapabilities map[string]ModelCapabilities `json:"model_capabilities,omitempty"` // selected model metadata keyed by model ID
BuiltinTools []string `json:"builtin_tools,omitempty"` // e.g. ["code_execution"]
RealtimeVoice string `json:"realtime_voice,omitempty"` // default voice for realtime providers (e.g. "marin")
}
type ProviderPool ¶
type ProviderPool struct {
// contains filtered or unexported fields
}
ProviderPool holds multiple LLM providers keyed by name. Supports default selection and fallback on error.
Realtime providers (RealtimeProvider) live in a separate map so the existing LLM-provider plumbing (Default, Fallback, ProviderSummary, etc.) stays untouched. A name can in principle appear in both maps if a vendor offers both APIs, though in practice they're distinct (e.g. "openai" text vs "openai-realtime").
func (*ProviderPool) Count ¶
func (pp *ProviderPool) Count() int
Count returns the number of providers in the pool.
func (*ProviderPool) Default ¶
func (pp *ProviderPool) Default() LLMProvider
Default returns the default provider.
func (*ProviderPool) DefaultName ¶
func (pp *ProviderPool) DefaultName() string
DefaultName returns the name of the default provider.
func (*ProviderPool) Fallback ¶
func (pp *ProviderPool) Fallback(exclude string) LLMProvider
Fallback returns the next provider in the fallback chain after the excluded one.
func (*ProviderPool) Get ¶
func (pp *ProviderPool) Get(name string) LLMProvider
Get returns a provider by name, or nil if not found.
func (*ProviderPool) HasRealtimeProvider ¶
func (pp *ProviderPool) HasRealtimeProvider() bool
HasRealtimeProvider reports whether any RealtimeProvider is registered. Used as one half of the realtime feature gate (the other being Config.RealtimeEnabled): if no provider is registered, the main thread is never told realtime exists and spawn rejects realtime=true.
func (*ProviderPool) Names ¶
func (pp *ProviderPool) Names() []string
Names returns all provider names in config order.
func (*ProviderPool) ProviderSummary ¶
func (pp *ProviderPool) ProviderSummary(name string) string
ProviderSummary returns a description of a provider for system prompt injection.
func (*ProviderPool) RealtimeByName ¶
func (pp *ProviderPool) RealtimeByName(name string) RealtimeProvider
RealtimeByName returns a RealtimeProvider by name, or nil.
func (*ProviderPool) RealtimeDefault ¶
func (pp *ProviderPool) RealtimeDefault() RealtimeProvider
RealtimeDefault returns the default RealtimeProvider, or nil if none registered.
func (*ProviderPool) RealtimeNames ¶
func (pp *ProviderPool) RealtimeNames() []string
RealtimeNames returns all registered realtime provider names.
type ProviderResponseState ¶ added in v0.8.11
type ProviderResponseState struct {
Provider string `json:"provider"`
Items []json.RawMessage `json:"items,omitempty"`
}
ProviderResponseState carries opaque, provider-specific response items that must be replayed on a later request. The generic thinking loop deliberately does not inspect Items. For example, stateless OpenAI Responses calls need the original reasoning/function-call output items (including encrypted reasoning) returned before a function_call_output.
type RealtimeEvent ¶
type RealtimeEvent struct {
Type RealtimeEventType
// Audio (RealtimeEventAudioOut)
Audio []byte
// Transcript (RealtimeEventTranscript*)
Transcript string
Final bool // true = end-of-utterance, false = partial
// Tool call (RealtimeEventToolCall)
ToolCallID string
ToolName string
ToolArgs string // raw JSON string
// Response/audio item metadata. ItemID + AudioEndMS let the caller
// truncate unplayed audio correctly on barge-in.
ResponseID string
ItemID string
AudioStartMS int
AudioEndMS int
Usage RealtimeUsage
DroppedAudio uint64
// Error (RealtimeEventError)
Err error
}
RealtimeEvent is a single event from a session. Only the fields relevant to the Type are populated.
type RealtimeEventType ¶
type RealtimeEventType string
RealtimeEventType discriminates the union of events a session can emit. Receivers should switch on Type before reading fields.
const ( RealtimeEventAudioOut RealtimeEventType = "audio_out" // PCM chunk RealtimeEventTranscriptInput RealtimeEventType = "transcript_input" // user said RealtimeEventTranscriptOutput RealtimeEventType = "transcript_output" // model said RealtimeEventToolCall RealtimeEventType = "tool_call" RealtimeEventResponseDone RealtimeEventType = "response_done" RealtimeEventSpeechStarted RealtimeEventType = "speech_started" RealtimeEventRateLimits RealtimeEventType = "rate_limits" RealtimeEventSessionEnded RealtimeEventType = "session_ended" RealtimeEventError RealtimeEventType = "error" )
type RealtimePricing ¶ added in v0.8.17
type RealtimePricing struct {
TextInput float64
TextCachedInput float64
TextOutput float64
AudioInput float64
AudioCachedInput float64
AudioOutput float64
// Some realtime vendors bill connection media by duration and text
// conversation items by count rather than by tokens. These optional
// dimensions coexist with token pricing so provider adapters do not
// leak billing rules into the generic thread runtime.
AudioInputPerMinute float64
AudioOutputPerMinute float64
TextInputPerMessage float64
}
RealtimePricing supports dollars per one million tokens plus optional duration/message rates. Providers leave unsupported dimensions at zero.
type RealtimeProvider ¶
type RealtimeProvider interface {
Name() string
Models() map[ModelTier]string
// Pricing returns the model-specific text and audio rates. Realtime
// providers report input/output audio separately, and cached audio has
// its own rate, so the ordinary three-number LLM price tuple is not
// expressive enough here.
Pricing(model string) RealtimePricing
// DefaultVoice returns the provider's preferred voice when the
// caller doesn't specify one. Empty string is acceptable for
// providers that pick a voice server-side.
DefaultVoice() string
// DefaultTranscriptionModel returns the provider-native streaming
// transcription model to request for input captions. Providers that
// do not support a separate transcription model may return empty.
DefaultTranscriptionModel() string
// Open establishes a session. ctx propagates to the underlying
// connection; cancelling ctx closes the session cleanly. The
// returned session is bound to ctx for its lifetime.
Open(ctx context.Context, opts RealtimeSessionOpts) (RealtimeSession, error)
}
RealtimeProvider is the parallel of LLMProvider for bidirectional, streaming, audio-capable models (e.g. OpenAI Realtime, Gemini Live).
Where LLMProvider.Chat() is request → response over HTTP+SSE, a RealtimeProvider holds a persistent WebSocket session for the lifetime of a realtime thread. Audio in / audio out flow over channels owned by the returned RealtimeSession; the thinker layer never touches the audio path itself.
Two interfaces, not one, because the request/response and streaming-session models are fundamentally different shapes — fusing them would either lossy-shim realtime into Chat() or force every text provider to implement methods it has no notion of. Common metadata (Name and Models) lives on both for uniformity at registration time.
type RealtimeSession ¶
type RealtimeSession interface {
// SendAudio pushes a chunk of input audio in the configured
// AudioInFmt to the model. Non-blocking on the model side — the
// session buffers and the network does its own back-pressure.
SendAudio(pcm []byte) error
// SendText injects a text message into the conversation. role is
// one of "user", "system", "assistant". Used by main to deliver
// out-of-band context to the realtime worker without speaking it
// into the call (e.g. "[from:main] caller is VIP, be warm").
SendText(role, text string) error
// SendToolResult delivers one tool result without starting the next model
// response. This separation lets the generic thinker submit every result
// from a parallel tool batch before requesting one continuation.
SendToolResult(callID, result string, isError bool) error
// RequestResponse asks the provider to continue after text or tool items
// have been added to its conversation.
RequestResponse() error
// UpdateConfiguration replaces mutable instructions and tools while
// preserving the provider-side conversation.
UpdateConfiguration(instructions string, tools []NativeTool) error
// RestoreConversation appends bounded transcript history without
// triggering a response. It is used after a provider-enforced session
// renewal so the worker can continue rather than becoming a blank agent.
RestoreConversation(messages []Message) error
// Interrupt cancels the model's current utterance. Used when new
// user audio arrives during model speech, or when main sends a
// course-correction the worker decides to act on immediately.
Interrupt() error
// Truncate removes the unplayed suffix of an assistant audio item after
// client-managed WebSocket playback is interrupted.
Truncate(itemID string, audioEndMS int) error
// Events returns the unified event stream from the session:
// audio out, transcript fragments, tool calls, lifecycle events,
// errors. Channel closes when the session ends.
Events() <-chan RealtimeEvent
// Close terminates the session and releases resources. Safe to
// call multiple times.
Close() error
}
RealtimeSession is the live, bidirectional handle to a single model session. All methods are safe to call concurrently with each other and with Events() consumption.
type RealtimeSessionOpts ¶
type RealtimeSessionOpts struct {
Model string // provider-specific model id
Voice string // empty = provider default
Instructions string // complete thread system prompt
Tools []NativeTool // tool schemas to expose to the model
AudioInFmt AudioFormat
AudioOutFmt AudioFormat
AudioInRate int // Hz; 0 = provider default
AudioOutRate int // Hz; 0 = provider default
Reasoning string // provider-supported reasoning effort; empty/auto = default
SafetyIdentifier string // stable privacy-preserving end-user/session identifier
TranscribeInput bool
TranscriptionModel string // empty = provider default
}
RealtimeSessionOpts is the connect-time configuration for a realtime session. Once the session is open, mutable fields can be updated via UpdateInstructions / similar — opts itself is consumed only at Open.
type RealtimeThinker ¶
type RealtimeThinker struct {
*Thinker
// contains filtered or unexported fields
}
RealtimeThinker is the event-driven counterpart to Thinker. It deliberately reuses Thinker's prompt, tool handler, execution gates, durable Session, bus, and telemetry instead of maintaining a second, weaker agent runtime.
func (*RealtimeThinker) Run ¶
func (rt *RealtimeThinker) Run()
Run survives normal provider-enforced session endings. Only explicit thread stop/cancellation ends the worker and invokes the normal cleanup path.
type RealtimeUsage ¶ added in v0.8.17
type RealtimeUsage struct {
TotalTokens int
InputTokens int
OutputTokens int
TextInputTokens int
TextCachedTokens int
TextOutputTokens int
AudioInputTokens int
AudioCachedTokens int
AudioOutputTokens int
AudioInputSeconds float64
AudioOutputSeconds float64
TextInputMessages int
}
RealtimeUsage is the detailed token accounting carried by a completed realtime response. Keeping text and audio separate is necessary for correct cost calculation and cache telemetry.
type ReasoningLevel ¶ added in v0.5.0
type ReasoningLevel string
const ( ReasoningAuto ReasoningLevel = "auto" ReasoningNone ReasoningLevel = "none" ReasoningMinimal ReasoningLevel = "minimal" ReasoningLow ReasoningLevel = "low" ReasoningMedium ReasoningLevel = "medium" ReasoningHigh ReasoningLevel = "high" ReasoningXHigh ReasoningLevel = "xhigh" )
func (ReasoningLevel) String ¶ added in v0.5.0
func (r ReasoningLevel) String() string
type ReasoningProvider ¶ added in v0.5.0
type ReasoningProvider interface {
WithReasoning(settings ReasoningSettings) LLMProvider
}
ReasoningProvider is an optional LLMProvider extension for APIs that support request-level reasoning or thinking effort controls.
type ReasoningSettings ¶ added in v0.5.0
type ReasoningSettings struct {
Level ReasoningLevel
}
type RunMode ¶
type RunMode string
RunMode controls the agent's safety behavior via system prompt guidance.
type Scenario ¶
type Scenario struct {
Name string
Directive string
MCPServers []MCPServerConfig // {{dataDir}} in Env values is replaced at runtime
Providers []ProviderConfig // multi-provider pool config (optional)
DataSetup func(t *testing.T, dir string)
Phases []Phase
Timeout time.Duration // hard cap for entire scenario
}
Scenario defines a complete agent behavior test.
Note: there are deliberately no thread-count knobs here. Scenarios assert on OUTCOMES — the goal got done — not on HOW the agent got there. Whether it spawned five workers or did the work inline on main is the agent's call; the harness only tracks peak threads as an informational line in the run summary.
type ScenarioAuditEntry ¶
type ScenarioAuditEntry struct {
Time string `json:"time"`
Tool string `json:"tool"`
Args map[string]string `json:"args"`
}
ScenarioAuditEntry is the row shape mock MCPs write into audit.jsonl.
func ReadAuditEntries ¶
func ReadAuditEntries(dir string) []ScenarioAuditEntry
ReadAuditEntries parses the audit.jsonl file the mock MCPs write into dataDir. Returns nil if the file doesn't exist yet.
type ServerToolResult ¶
type ServerToolResult struct {
ToolName string `json:"tool_name"`
Code string `json:"code,omitempty"` // code that was executed
Output string `json:"output,omitempty"` // stdout/result
Error string `json:"error,omitempty"` // stderr if any
}
ServerToolResult is the result of a built-in tool executed server-side.
type Session ¶
type Session struct {
// contains filtered or unexported fields
}
Session manages persistent JSONL history for one thread.
func NewSession ¶
NewSession creates or opens a session file for a thread.
func (*Session) Append ¶
func (s *Session) Append(entry SessionEntry) error
Append writes one entry to the history file.
func (*Session) AppendMessage ¶
func (s *Session) AppendMessage(msg Message, iteration int, usage TokenUsage) error
AppendMessage is a convenience to append a Message as a SessionEntry.
func (*Session) ArchiveToolResults ¶ added in v0.8.17
ArchiveToolResults stores each payload before it enters the in-memory conversation. The returned live message keeps the full payload through the short retention window; persistence stores only internal archive metadata.
func (*Session) Compact ¶
Compact summarizes old messages and rewrites the file. summarize is a function that takes messages text and returns a summary.
func (*Session) ForceCompact ¶ added in v0.8.7
func (*Session) LoadAfter ¶ added in v0.8.9
func (s *Session) LoadAfter(after int64, limit int) (entries []SessionEntry, nextCursor int64, err error)
LoadAfter returns durable session entries strictly newer than after. The cursor is the entry Sequence, not the current in-memory context index, so a consumer can keep observing a long-running thread even while its prompt is compacted or trimmed. Entries written before sequence support return no cursor and are intentionally excluded; callers use this endpoint only for fresh, live sessions.
func (*Session) LoadTail ¶
LoadTail reads the last n messages from the history file and converts them to Messages. Skips system messages and _compacted entries (compacted summaries are prepended as context).
func (*Session) NeedsCompaction ¶
NeedsCompaction returns true if the file is large enough to compact.
func (*Session) Rename ¶
Rename moves the on-disk history file when a thread's id changes. Best-effort: a missing source file (the thread had no entries yet) is treated as success so the caller can rename the in-memory record without worrying about whether disk state existed.
func (*Session) Reset ¶ added in v0.8.17
Reset removes the durable conversation journal while keeping the Session object usable. Reusing the same object matters for live thinkers: replacing the pointer during a reset can race an in-flight append and resurrect the deleted history through the old Session instance.
type SessionEntry ¶
type SessionEntry struct {
// Sequence is a per-session, monotonically increasing cursor. It makes the
// durable history safe for consumers that need to observe a running thread:
// unlike the in-memory context window, this cursor does not move when old
// messages are trimmed from the model prompt.
Sequence int64 `json:"seq,omitempty"`
Timestamp time.Time `json:"ts"`
Role string `json:"role"` // "system", "user", "assistant", "tool_result", "_compacted"
Content string `json:"content"`
Parts []ContentPart `json:"parts,omitempty"`
ToolCalls []NativeToolCall `json:"tool_calls,omitempty"`
ToolResults []ToolResult `json:"tool_results,omitempty"`
Reasoning string `json:"reasoning,omitempty"`
ProviderState *ProviderResponseState `json:"provider_state,omitempty"`
Summary string `json:"summary,omitempty"` // for _compacted entries
OrigCount int `json:"original_count,omitempty"` // how many messages were compacted
TokensIn int `json:"tokens_in,omitempty"`
TokensOut int `json:"tokens_out,omitempty"`
Iteration int `json:"iteration,omitempty"`
}
SessionEntry is one line in the JSONL history file.
type SpawnOpts ¶
type SpawnOpts struct {
MediaParts []ContentPart
ProviderName string // override provider from pool (empty = inherit parent)
Model string // starting model tier (empty = default large)
Reasoning ReasoningLevel
InitialMessages []string
ParentID string // "main" or parent thread ID (empty = "main")
Depth int // depth in the spawn tree (0 = child of main)
MCPNames []string // MCP servers whose tools preload into the child's activeTools at boot
// Tools, when set, preloads specific tool names (across any server)
// into the child's activeTools at boot. Complements MCPNames:
// MCPNames = "give me everything from these servers", Tools =
// "give me exactly these names". Both are additive. Used by the
// privileged HTTP spawn endpoint (POST /threads/{id}) for system
// callers that know which tools they need; the LLM-driven spawn
// tool path leaves this nil and uses mcps=[…] instead.
Tools []string
BuiltinTools []string // provider builtin overrides (nil = inherit, empty = none)
DeferRun bool // if true, don't start Run() — call StartAll() later
System bool // true for platform-owned system threads such as unconscious
Ephemeral bool // temporary caller-owned thread; cleanup also removes session history
// Paused: if true, the thread spawns in paused state. Run() loop
// blocks at the top of its first iteration until either an inbox
// event arrives (an explicit `send` from the leader) OR the
// thinker is unpaused via PauseAll(false). Useful for
// - "configure-then-launch" patterns where the leader spawns
// several workers atomically before any of them think
// - cautious/learn modes that want children to wait for explicit
// instruction rather than acting on the directive alone
// - debugging — inspect the worker before it does anything
Paused bool
// BypassNoSpawn skips the no_spawn MCP filter. Set by the
// authenticated HTTP spawn endpoint (POST /threads/{id}) where
// the caller has the core API key — the system itself is asking
// for a privileged sub-thread (e.g. channelchat's chat thread
// needs the `channels` MCP to reply to users). The LLM-driven
// spawn tool path never sets this, so an in-agent worker still
// can't escalate by attaching a no_spawn MCP.
BypassNoSpawn bool
// Realtime: if true, construct a realtime (voice/audio) thread
// driven by a RealtimeProvider session instead of the standard
// request/response Thinker. ProviderName must resolve to a
// registered RealtimeProvider (e.g. "openai-realtime"); when
// empty, the pool's RealtimeDefault is used. SpawnWithOpts will
// refuse with a clear error if no realtime provider is available.
Realtime bool
// Voice: realtime voice id (e.g. "alloy"). Empty = provider's
// default. Ignored when Realtime is false.
Voice string
// AudioIn: PCM audio chunks pushed by the caller (telephony
// bridge, browser WebRTC, mic source). The realtime thread reads
// these and forwards to session.SendAudio. nil = no inbound audio
// (text-only realtime — useful for tests). Ignored when
// Realtime is false.
AudioIn chan []byte
// AudioOut: PCM audio chunks the realtime thread writes when the
// model speaks. Caller plays/streams them. nil = audio output
// silently dropped. Ignored when Realtime is false.
AudioOut chan []byte
// AudioControl carries low-volume playback controls such as "interrupt"
// to the WebSocket bridge so telephony clients can clear queued audio.
AudioControl chan string
// BridgeDisconnectTTL asks core to stop this realtime thread if its audio
// bridge remains disconnected for the duration. Zero disables cleanup.
BridgeDisconnectTTL time.Duration
// InitialMessage is sent to the realtime provider after the first audio
// bridge connects, then immediately requests a response.
InitialMessage string
}
SpawnOpts holds optional parameters for spawning a thread.
type StreamChoice ¶
type StreamChoice struct {
Delta Delta `json:"delta"`
}
type StreamEvent ¶
type StreamEvent struct {
Choices []StreamChoice `json:"choices"`
Usage *Usage `json:"usage,omitempty"`
}
type Subscription ¶
type Subscription struct {
ID string
C chan Event
Wake chan struct{} // signaled on every new event delivery
Dropped uint64 // atomic
// contains filtered or unexported fields
}
Subscription is a handle returned by Subscribe/SubscribeAll.
Dropped is an atomic counter of events the bus discarded because this subscription's channel was full. Non-zero means the consumer is not keeping up with the publish rate and some events were lost (order of remaining events is preserved — drops are tail truncations of the backlog, not reorderings). Read with atomic.LoadUint64; inspect from anywhere safely.
func (*Subscription) DrainTargeted ¶ added in v0.8.9
func (sub *Subscription) DrainTargeted() []Event
DrainTargeted returns every currently queued event in publication order. Holding queueMu while draining C prevents a concurrent publisher from placing a newer event in C ahead of an older overflow event.
type SystemBreakdown ¶
type SystemBreakdown struct {
Base int `json:"base"` // up to "CORE TOOLS — always available:"
CoreTools int `json:"core_tools"` // "CORE TOOLS — always available:" to next [ marker
RetrievedTools int `json:"retrieved_tools"` // [available tools — matched to your current context] block (RAG per-turn)
MCPServers int `json:"mcp_servers"` // [AVAILABLE MCP SERVERS] block
MCPToolDocs int `json:"mcp_tool_docs"` // [MCP TOOLS — available for sub-threads] block
Providers int `json:"providers"` // [AVAILABLE PROVIDERS] block
ActiveThreads int `json:"active_threads"` // [ACTIVE THREADS] block
SafetyMode int `json:"safety_mode"` // [SAFETY MODE: ...] block
Skills int `json:"skills"` // [LEARNED SKILLS] block
BlobHint int `json:"blob_hint"` // [FILE HANDLES] block
PreviousContext int `json:"previous_context"` // [PREVIOUS CONTEXT] block (from session load)
Directive int `json:"directive"` // [DIRECTIVE — EXECUTE ON STARTUP] block
Other int `json:"other"` // text not matching any known marker
Total int `json:"total"`
}
SystemBreakdown is the per-section byte count of messages[0].Content, i.e. the main system prompt. Unknown text that falls between known markers lands in Other so the total always reconciles with Total.
type Telemetry ¶
type Telemetry struct {
// contains filtered or unexported fields
}
Telemetry collects events and forwards them to the server.
func NewTelemetry ¶
func NewTelemetry() *Telemetry
func (*Telemetry) DroppedLiveEvents ¶
DroppedLiveEvents returns the cumulative count of live-forward events that were discarded because the buffer was full. Useful for health checks and end-of-run diagnostics.
func (*Telemetry) EmitLive ¶
EmitLive records a telemetry event for SSE only (not forwarded to server).
func (*Telemetry) Events ¶
func (t *Telemetry) Events(since int) ([]TelemetryEvent, int)
Events returns all events (including live-only) since the given index. Used by SSE. If the log was truncated (since > len), reset to return everything available.
func (*Telemetry) StoredEvents ¶
func (t *Telemetry) StoredEvents(since int) ([]TelemetryEvent, int)
StoredEvents returns only stored events since the given index. Used by forwardLoop. If the log was truncated (since > len), reset to return everything available.
type TelemetryEvent ¶
type TelemetryEvent struct {
ID string `json:"id"`
InstanceID int64 `json:"instance_id,omitempty"`
ThreadID string `json:"thread_id"`
Type string `json:"type"`
Time time.Time `json:"time"`
Data json.RawMessage `json:"data"`
}
TelemetryEvent is the unified event format — matches server schema.
type Thinker ¶
type Thinker struct {
// contains filtered or unexported fields
}
func NewThinker ¶
func NewThinker(apiKey string, provider LLMProvider, cfg ...*Config) *Thinker
func (*Thinker) InjectConsole ¶
InjectConsole sends a console event to this thinker.
func (*Thinker) InjectWithParts ¶
func (t *Thinker) InjectWithParts(text string, parts []ContentPart)
InjectWithParts sends a text event with media parts attached.
func (*Thinker) Memory ¶
func (t *Thinker) Memory() *MemoryStore
Memory returns the MemoryStore this Thinker reads/writes against.
func (*Thinker) Messages ¶
Messages returns the current message slice. Returned slice shares backing storage with the Thinker — copy if you need to retain it.
func (*Thinker) Pool ¶
func (t *Thinker) Pool() *ProviderPool
Pool returns the underlying provider pool.
func (*Thinker) ReloadDirective ¶
func (t *Thinker) ReloadDirective()
func (*Thinker) ReloadDirectiveQuiet ¶ added in v0.3.0
func (t *Thinker) ReloadDirectiveQuiet()
func (*Thinker) ResetConversation ¶
func (t *Thinker) ResetConversation()
ResetConversation truncates the message history back to the initial system prompt. Used by long-running scenarios that need to clear context between phases without rebuilding the Thinker.
func (*Thinker) Threads ¶
func (t *Thinker) Threads() *ThreadManager
Threads returns the ThreadManager owning this Thinker's worker threads. Read-only intent; callers must not mutate the returned value's fields directly.
func (*Thinker) TogglePause ¶
func (t *Thinker) TogglePause()
type Thread ¶
type Thread struct {
ID string
Name string // human-readable label, separate from ID. ID is immutable;
System bool // platform-managed thread, not an agent-addressable worker
// Name can be edited via update without touching parent_id
// references or session storage. Empty means "use ID for display".
ParentID string // "main" or parent thread ID
Depth int // 0 = child of main, 1 = grandchild, etc.
Directive string // original directive before tool docs
MCPNames []string // MCP server names this thread connected to
Thinker *Thinker
Realtime *RealtimeThinker // non-nil for realtime (voice/audio) threads; runs in place of Thinker.Run
IsRealtime bool
Voice string
ProviderName string
Ephemeral bool
// BridgeDisconnectTTL is set only for caller-owned realtime sessions
// (the dashboard currently uses it). A zero value preserves the existing
// sidecar/telephony behaviour: losing the audio bridge does not kill the
// realtime worker.
BridgeDisconnectTTL time.Duration
Parent *Thinker
Children *ThreadManager // non-nil if this thread can spawn (depth < MaxSpawnDepth)
Tools map[string]bool
Started time.Time
// contains filtered or unexported fields
}
type ThreadDoneData ¶
type ThreadInfo ¶
type ThreadInfo struct {
ID string
Name string // human-readable display label; empty = render id
System bool // platform-managed; hidden from and immutable by agent tools
ParentID string // "main" or parent thread ID
Depth int
Directive string
Tools []string
MCPNames []string
Running bool
Iteration int
Rate ThinkRate
Model ModelTier
Reasoning ReasoningLevel
Provider string // active provider name
Realtime bool
Voice string
Started time.Time
ContextMsgs int
ContextChars int
SubThreads int // number of direct children
}
func AllThreadInfos ¶
func AllThreadInfos(tm *ThreadManager) []ThreadInfo
AllThreadInfos walks tm and all nested ThreadManagers, returning flattened ThreadInfo records. Used by scenarios that assert on the total tree of agent threads, not just the top-level set.
type ThreadManager ¶
type ThreadManager struct {
// contains filtered or unexported fields
}
func NewThreadManager ¶
func NewThreadManager(parent *Thinker) *ThreadManager
func (*ThreadManager) Count ¶
func (tm *ThreadManager) Count() int
func (*ThreadManager) Directive ¶ added in v0.8.5
func (tm *ThreadManager) Directive(id string) (string, error)
func (*ThreadManager) Kill ¶
func (tm *ThreadManager) Kill(id string)
func (*ThreadManager) KillAll ¶
func (tm *ThreadManager) KillAll()
func (*ThreadManager) List ¶
func (tm *ThreadManager) List() []ThreadInfo
func (*ThreadManager) ListAgentVisible ¶ added in v0.8.9
func (tm *ThreadManager) ListAgentVisible() []ThreadInfo
ListAgentVisible returns only worker threads the model may coordinate. List remains complete for APIs, dashboards, telemetry, and runtime control.
func (*ThreadManager) PauseAll ¶
func (tm *ThreadManager) PauseAll(paused bool)
PauseAll pauses or resumes all child threads.
func (*ThreadManager) Rename ¶
func (tm *ThreadManager) Rename(oldID, newID string) error
Rename changes a thread's immutable id. Touches every reference:
- the threads map key
- children's ParentID
- the persistent record (delete old, save new)
- the on-disk session file
- emits thread.renamed telemetry so the dashboard can swap its record over to the new identity
Returns an error if the new id is empty, equals the old, collides with an existing sibling, or any of the persistence steps fail.
func (*ThreadManager) RenewRealtimeAudioToken ¶ added in v0.8.17
func (tm *ThreadManager) RenewRealtimeAudioToken(id string) (string, error)
RenewRealtimeAudioToken reattaches a caller to the existing realtime provider session. Only the bridge capability rotates; model state, transcript, MCP connections, and tool state remain untouched.
func (*ThreadManager) Send ¶
func (tm *ThreadManager) Send(id, message string) bool
func (*ThreadManager) SendAgentWithParts ¶ added in v0.8.9
func (tm *ThreadManager) SendAgentWithParts(id, message string, parts []ContentPart) error
SendAgentWithParts is the unprivileged send path used by LLM-facing tools.
func (*ThreadManager) SendWithParts ¶
func (tm *ThreadManager) SendWithParts(id, message string, parts []ContentPart) bool
func (*ThreadManager) Spawn ¶
func (tm *ThreadManager) Spawn(id, directive string, tools []string, initialMessages ...string) error
func (*ThreadManager) SpawnWithMedia ¶
func (tm *ThreadManager) SpawnWithMedia(id, directive string, tools []string, parts []ContentPart, initialMessages ...string) error
SpawnWithMedia creates a thread and injects media parts before it starts thinking.
func (*ThreadManager) SpawnWithOpts ¶
func (tm *ThreadManager) SpawnWithOpts(id, directive string, tools []string, opts SpawnOpts) error
SpawnWithOpts creates a thread with full options (provider, media, etc).
func (*ThreadManager) StartAll ¶
func (tm *ThreadManager) StartAll()
StartAll starts Run() on all threads (and their children) that were spawned with DeferRun. Used after batch-respawning persisted threads so parents see their children before thinking.
func (*ThreadManager) Update ¶
func (tm *ThreadManager) Update(id, name, directive string, tools []string) error
Update changes a thread's directive and/or tools. Rebuilds the system prompt immediately.
func (*ThreadManager) ValidateAgentTarget ¶ added in v0.8.9
func (tm *ThreadManager) ValidateAgentTarget(id string) error
ValidateAgentTarget rejects platform-managed threads while leaving public manager operations privileged for server and runtime callers.
type ThreadMessageData ¶
type ThreadRenamedData ¶
type ThreadRenamedData struct {
OldID string `json:"old_id"`
NewID string `json:"new_id"`
Name string `json:"name,omitempty"`
ParentID string `json:"parent_id,omitempty"`
}
ThreadRenamedData fires when update changes a thread's display name or its immutable id. The dashboard uses old_id to swap its record for the new identity (id changes are rare but legal). When only Name changed, OldID == NewID.
type ThreadSpawnData ¶
type TokenUsage ¶
type ToolCallData ¶
type ToolDef ¶
type ToolDef struct {
Name string
Description string // human-readable
Syntax string // example usage
Rules string // usage rules for the prompt
Core bool // always in prompt (pace, send, done, evolve, search_tools)
MainOnly bool // only for main thread (spawn, kill)
ThreadOnly bool // only for sub-threads, not main (reply)
SystemOnly bool // only for system threads (unconscious)
MCP bool // provided by an MCP server — hidden from the per-turn tool list until activated (search_tools / spawn preload / BM25 preload)
MCPServer string // name of the MCP server that provides this tool
Handler func(args map[string]string) ToolResponse // nil = handled inline by tool handler
InputSchema map[string]any // JSON Schema for native tool calling (nil = auto-generated from Syntax)
// WakeOnResult controls whether an async tool result wakes the thinker.
// Default is always. MCP tools may override this via
// _meta["io.apteva/wakeOnResult"] = "on_error".
WakeOnResult WakeOnResultPolicy
}
ToolDef defines a tool available to threads.
type ToolHandler ¶
type ToolHandler func(t *Thinker, calls []toolCall, consumed []string) (replies []string, toolNames []string, results []ToolResult)
ToolHandler processes parsed tool calls from a thought. Returns replies, tool names logged, and tool results for inline-handled tools. consumed contains the events that were consumed this iteration (for context).
type ToolIndex ¶
type ToolIndex struct {
// contains filtered or unexported fields
}
ToolIndex catalogs every MCP tool known to the process by metadata (server, name, description, schema, no_spawn) and supports cheap keyword search. It is the search surface for `search_tools` and the per-turn preload, replacing the old main-access/catalog split.
The index is a metadata mirror of what's in ToolRegistry. The registry remains the source of truth for handlers and dispatch; the index is just a fast read-side view optimised for ranking.
Why a separate structure instead of querying the registry directly:
- The registry stores tools by name, not by server; per-server enumeration (for spawn-time preload) would mean an O(N) scan every time.
- Search wants tokenized text; precomputing it once at add-time keeps the per-query cost to a sort.
- The registry will eventually want to evict tools (uninstall an app); a separate index keeps that bookkeeping local.
func (*ToolIndex) Add ¶
func (ix *ToolIndex) Add(server string, tools []mcpToolDef, noSpawn bool, loading ...*MCPToolLoadingConfig)
Add registers a server's tools. Replaces any prior entries for the same server name so reconnect or hot-reload semantics work cleanly.
func (*ToolIndex) AllNames ¶
AllNames returns every indexed tool's fully-qualified name. Backs the APTEVA_EAGER_TOOLS escape hatch, which makes the whole attached surface visible every turn (the pre-discovery behaviour). When allowNoSpawn is false, no_spawn entries are excluded — a sub-thread in eager mode still must not see gateway/channels tools.
func (*ToolIndex) AlwaysCount ¶ added in v0.8.17
AlwaysCount reports pinned schemas in the caller's authorized scope.
func (*ToolIndex) BaselineNames ¶ added in v0.8.17
BaselineNames returns schemas that are visible without activation for the current global mode. Explicit policy wins over the global threshold: always is always present, deferred always requires activation, and auto follows eagerMode. no_spawn remains an authorization boundary.
func (*ToolIndex) Count ¶
Count returns the number of tools currently indexed. Backs the APTEVA_TOOL_SEARCH=auto decision: below a threshold the surface is small enough that eager-loading beats the search round-trip.
func (*ToolIndex) DeferredCount ¶ added in v0.8.17
DeferredCount reports schemas excluded from the baseline in the current global mode. It includes explicit deferred tools plus auto tools while the process is in discovery mode.
func (*ToolIndex) Get ¶
func (ix *ToolIndex) Get(name string) (IndexEntry, bool)
Get returns the entry for a fully-qualified tool name, if present.
func (*ToolIndex) Remove ¶
Remove drops every entry for the named server. Used when an app uninstalls or an MCP disconnects.
func (*ToolIndex) Search ¶
func (ix *ToolIndex) Search(query string, k int, allowNoSpawn bool) []IndexEntry
Search returns up to k entries matching the query, ranked. When allowNoSpawn is false, no_spawn entries are filtered out — that path is used from sub-threads, which must not discover gateway or channels tools they have no business calling.
func (*ToolIndex) ToolCountByServer ¶
ToolCountByServer returns name → count of indexed tools. Used by the system prompt's [AVAILABLE MCP SERVERS] block so the LLM sees which servers exist and how many tools each contributes without the full schemas appearing in context.
func (*ToolIndex) ToolPolicyCountsByServer ¶ added in v0.8.17
func (ix *ToolIndex) ToolPolicyCountsByServer() map[string]map[ToolLoadMode]int
ToolPolicyCountsByServer returns per-server counts keyed by normalized load mode. It feeds the prompt's compact catalog without exposing index internals.
func (*ToolIndex) ToolsForServer ¶
ToolsForServer returns every tool name a server contributes. Used by spawn-time preload (SpawnOpts.MCPNames) to seed a child thread's activeTools with the full surface of the listed servers.
func (*ToolIndex) UpdatePolicy ¶ added in v0.8.17
func (ix *ToolIndex) UpdatePolicy(server string, noSpawn bool, loading *MCPToolLoadingConfig)
UpdatePolicy changes only prompt visibility metadata. MCP connections and registered handlers remain untouched, which is required for host-owned no_spawn servers such as Channels that cannot safely reconnect while their management request is in flight.
type ToolLoadMode ¶ added in v0.8.17
type ToolLoadMode string
ToolLoadMode controls when an MCP tool schema is included in model requests. The policy is provider-neutral: core resolves it before handing the selected tool list to Codex, Anthropic, OpenCode Go, or any other native-tool provider.
const ( ToolLoadAuto ToolLoadMode = "auto" ToolLoadAlways ToolLoadMode = "always" ToolLoadDeferred ToolLoadMode = "deferred" )
type ToolRegistry ¶
type ToolRegistry struct {
// contains filtered or unexported fields
}
ToolRegistry holds all tool definitions.
func NewToolRegistry ¶
func NewToolRegistry(apiKey string) *ToolRegistry
func (*ToolRegistry) AllToolNames ¶
func (tr *ToolRegistry) AllToolNames() []string
AllToolNames returns all non-core tool names (for spawn docs).
func (*ToolRegistry) AllTools ¶
func (tr *ToolRegistry) AllTools() []*ToolDef
AllTools returns all tool definitions for display.
func (*ToolRegistry) CoreDocs ¶
func (tr *ToolRegistry) CoreDocs(includeMainOnly bool, includeSystemOnly ...bool) string
CoreDocs returns documentation for core tools, always included in prompts.
func (*ToolRegistry) CoreDocsSummary ¶
func (tr *ToolRegistry) CoreDocsSummary(includeMainOnly bool, includeSystemOnly ...bool) string
CoreDocsSummary returns a one-line summary of core tool names, sized for providers that receive full schemas via NativeTools in their `tools[]` payload. Emitting the full prose here (see CoreDocs) duplicates every tool's Description + Rules in the system prompt — ~5k extra input chars per iteration on a typical main thread.
Callers that target providers WITHOUT native-tool support should keep using CoreDocs: those providers only see the prose and need the rules in the system prompt to behave.
Ordering matches CoreDocs so the two agree when comparing, and the block is prefixed with the same marker so the composition breakdown still identifies it as the "core_tools" segment.
func (*ToolRegistry) Count ¶
func (tr *ToolRegistry) Count() int
Count returns the total number of registered tools.
func (*ToolRegistry) Counts ¶
func (tr *ToolRegistry) Counts() (core, rag, total int)
Counts returns core, discoverable (RAG), and total tool counts.
func (*ToolRegistry) Dispatch ¶
func (tr *ToolRegistry) Dispatch(name string, args map[string]string) (ToolResponse, bool)
Dispatch executes a tool by name if it has a Handler. Returns response and whether it was handled.
func (*ToolRegistry) Get ¶
func (tr *ToolRegistry) Get(name string) *ToolDef
func (*ToolRegistry) NativeTools ¶
func (tr *ToolRegistry) NativeTools(allowlist, active map[string]bool, includeSystemOnly ...bool) []NativeTool
NativeTools returns tool definitions for the LLM provider API.
Visibility model:
- Core / non-MCP tools: always visible unless excluded by an allowlist (sub-thread restriction) or by role flags (MainOnly / ThreadOnly / SystemOnly applied at caller via RetrieveTools — this method trusts what's in the registry).
- MCP tools (ToolDef.MCP == true): hidden by default — they only appear when their name is in `active`. That's how the "agent-driven discovery" model works: spawn-time MCPNames preload, search_tools, and per-turn BM25 preload all push names into the active set; nothing else gets MCP tools on the wire.
allowlist is the boot-time per-thread allowlist (sub-threads pass their tool set; main passes nil). active is the live per-turn set of MCP tools the thread has surfaced for use. Either argument may be nil.
func (*ToolRegistry) Register ¶
func (tr *ToolRegistry) Register(tool *ToolDef)
func (*ToolRegistry) RemoveByMCPServer ¶
func (tr *ToolRegistry) RemoveByMCPServer(serverName string)
RemoveByMCPServer removes all tools provided by the named MCP server.
type ToolResponse ¶
type ToolResponse struct {
Text string // text result (always present)
Image []byte // optional image (screenshot etc.) — sent as part of tool result to LLM
IsError bool // true when the tool returned an MCP-level isError result
}
ToolResponse is the return value from a tool handler.
type ToolResult ¶
type ToolResult struct {
CallID string `json:"call_id"`
ToolName string `json:"tool_name,omitempty"`
Content string `json:"content"` // full text for first consumption; bounded archive preview thereafter
Image []byte `json:"image,omitempty"` // optional image (screenshot etc.)
IsError bool `json:"is_error,omitempty"`
OriginalChars int `json:"original_chars,omitempty"`
OriginalBytes int `json:"original_bytes,omitempty"`
OriginalImageBytes int `json:"original_image_bytes,omitempty"`
SHA256 string `json:"sha256,omitempty"`
ArchiveRef string `json:"archive_ref,omitempty"`
ContentIsPreview bool `json:"content_is_preview,omitempty"`
}
ToolResult is sent back to the provider after executing a tool.
type ToolResultArchive ¶ added in v0.8.17
type ToolResultArchive struct {
// contains filtered or unexported fields
}
ToolResultArchive stores immutable payload objects by content hash and an append-only call ledger for one agent thread. Session compaction never touches either path.
func NewToolResultArchive ¶ added in v0.8.17
func NewToolResultArchive(baseDir, threadID string) *ToolResultArchive
func (*ToolResultArchive) Archive ¶ added in v0.8.17
func (a *ToolResultArchive) Archive(result ToolResult) (ToolResult, error)
func (*ToolResultArchive) Read ¶ added in v0.8.17
func (a *ToolResultArchive) Read(refOrHash string) (archivedToolResultObject, error)
func (*ToolResultArchive) RefForCall ¶ added in v0.8.17
func (a *ToolResultArchive) RefForCall(callID string) (string, bool)
func (*ToolResultArchive) RenameThread ¶ added in v0.8.17
func (a *ToolResultArchive) RenameThread(newThreadID string) error
RenameThread keeps the old ledger path as an append-only audit alias while making the same records discoverable under the new thread ID after restart.
type ToolResultData ¶
type ToolResultData struct {
ID string `json:"id,omitempty"`
Name string `json:"name"`
DurationMs int64 `json:"duration_ms"`
Success bool `json:"success"`
Result string `json:"result,omitempty"`
ResultOriginalBytes int `json:"result_original_bytes"`
ResultContextBytes int `json:"result_context_bytes"`
ResultPreviewBytes int `json:"result_preview_bytes"`
ResultImageBytes int `json:"result_image_bytes,omitempty"`
ResultTruncated bool `json:"result_truncated"`
}
type Usage ¶
type Usage struct {
PromptTokens int `json:"prompt_tokens"`
CompletionTokens int `json:"completion_tokens"`
TotalTokens int `json:"total_tokens"`
PromptTokensDetails *PromptTokensDetails `json:"prompt_tokens_details,omitempty"`
}
type WakeOnResultPolicy ¶ added in v0.5.0
type WakeOnResultPolicy string
const ( WakeOnResultAlways WakeOnResultPolicy = "always" WakeOnResultOnError WakeOnResultPolicy = "on_error" )
type XAIProvider ¶ added in v0.8.17
type XAIProvider struct {
// contains filtered or unexported fields
}
XAIProvider is a thin vendor adapter over the shared OpenAI-compatible Chat Completions transport. The shared transport owns message conversion, native function calling, streaming, and usage parsing; this wrapper adds only xAI's reasoning parameter and cache-routing header.
func (*XAIProvider) AvailableBuiltinTools ¶ added in v0.8.17
func (p *XAIProvider) AvailableBuiltinTools() []BuiltinTool
Provider-managed xAI web/X/code tools are intentionally not exposed by the Chat Completions adapter. Apteva's normal MCP/function tools remain native.
func (*XAIProvider) Chat ¶ added in v0.8.17
func (p *XAIProvider) Chat(ctx context.Context, messages []Message, model string, tools []NativeTool, onChunk func(string), onThinking func(string), onToolChunk func(string, string, string)) (ChatResponse, error)
func (*XAIProvider) CostPer1M ¶ added in v0.8.17
func (p *XAIProvider) CostPer1M() (float64, float64, float64)
func (*XAIProvider) Models ¶ added in v0.8.17
func (p *XAIProvider) Models() map[ModelTier]string
func (*XAIProvider) Name ¶ added in v0.8.17
func (p *XAIProvider) Name() string
func (*XAIProvider) SetBuiltinTools ¶ added in v0.8.17
func (p *XAIProvider) SetBuiltinTools(_ []string)
func (*XAIProvider) SupportsNativeTools ¶ added in v0.8.17
func (p *XAIProvider) SupportsNativeTools() bool
func (*XAIProvider) WithBuiltins ¶ added in v0.8.17
func (p *XAIProvider) WithBuiltins(_ []string) LLMProvider
func (*XAIProvider) WithReasoning ¶ added in v0.8.17
func (p *XAIProvider) WithReasoning(settings ReasoningSettings) LLMProvider
type XAIRealtimeProvider ¶ added in v0.8.17
type XAIRealtimeProvider struct {
// contains filtered or unexported fields
}
XAIRealtimeProvider implements xAI's Voice Agent WebSocket API. The API is event-compatible with OpenAI Realtime, while retaining its own session configuration shape, transcription events, voices, reasoning, and billing.
func NewXAIRealtimeProvider ¶ added in v0.8.17
func NewXAIRealtimeProvider(apiKey string) *XAIRealtimeProvider
func (*XAIRealtimeProvider) DefaultTranscriptionModel ¶ added in v0.8.17
func (p *XAIRealtimeProvider) DefaultTranscriptionModel() string
func (*XAIRealtimeProvider) DefaultVoice ¶ added in v0.8.17
func (p *XAIRealtimeProvider) DefaultVoice() string
func (*XAIRealtimeProvider) Models ¶ added in v0.8.17
func (p *XAIRealtimeProvider) Models() map[ModelTier]string
func (*XAIRealtimeProvider) Name ¶ added in v0.8.17
func (p *XAIRealtimeProvider) Name() string
func (*XAIRealtimeProvider) Open ¶ added in v0.8.17
func (p *XAIRealtimeProvider) Open(ctx context.Context, opts RealtimeSessionOpts) (RealtimeSession, error)
func (*XAIRealtimeProvider) Pricing ¶ added in v0.8.17
func (p *XAIRealtimeProvider) Pricing(string) RealtimePricing
Source Files
¶
- api.go
- blobs.go
- config.go
- console.go
- context_breakdown.go
- context_pressure.go
- directive_edit.go
- eventbus.go
- execution_checkpoint.go
- execution_control.go
- logger.go
- main.go
- mcp.go
- mcp_args.go
- mcp_http.go
- memory.go
- model_capabilities.go
- network_policy.go
- pace.go
- persistence.go
- prompt_cache_stability.go
- prompt_contract.go
- provider.go
- provider_anthropic.go
- provider_google.go
- provider_google_realtime.go
- provider_openai.go
- provider_openai_cache.go
- provider_openai_native.go
- provider_openai_realtime.go
- provider_openai_realtime_session.go
- provider_realtime.go
- provider_xai.go
- provider_xai_realtime.go
- realtime_audio_bridge.go
- realtime_thinker.go
- reasoning.go
- registry.go
- retrieval_context.go
- scenario_harness.go
- session.go
- telemetry.go
- thinker.go
- thinker_accessors.go
- thread.go
- thread_id.go
- tool_index.go
- tool_result_archive.go
- tool_result_history.go
- tool_search.go
- tools.go
- tools_system.go
- tui.go
Directories
¶
| Path | Synopsis |
|---|---|
|
cmd
|
|
|
apteva-core
command
apteva-core — agent runtime binary.
|
apteva-core — agent runtime binary. |
|
mcps
|
|
|
ads
command
MCP server for ad budget monitoring and cost-per-lead tracking.
|
MCP server for ad budget monitoring and cost-per-lead tracking. |
|
codebase
command
MCP server for file-based code read/write and test execution.
|
MCP server for file-based code read/write and test execution. |
|
files
command
MCP server for file fetching, deduplication, and CSV parsing.
|
MCP server for file fetching, deduplication, and CSV parsing. |
|
market
command
MCP server for simulated market data, portfolio management, and trading.
|
MCP server for simulated market data, portfolio management, and trading. |
|
metrics
command
MCP server for simulated time-series monitoring and alerting.
|
MCP server for simulated time-series monitoring and alerting. |
|
Package testkit provides a thin HTTP harness for writing phased, real-LLM tests against a live apteva-server.
|
Package testkit provides a thin HTTP harness for writing phased, real-LLM tests against a live apteva-server. |