Documentation
¶
Index ¶
- func FindClaudeCodeCLIPath() (string, error)
- func WithSelectionMetadata(ctx context.Context, meta SelectionMetadata) context.Context
- type AnthropicClient
- type ChatMessage
- type ChatOptions
- type ChatResponse
- type ClaudeCodeCLIClient
- type Client
- type ClientConfig
- type CodexRateLimitSnapshot
- type CodexRateLimitSource
- type CodexRateLimitWindow
- type ContentBlock
- type FakeClient
- type GeminiNativeClient
- type ModelFetcher
- type OpenAICodexClient
- func (c *OpenAICodexClient) Ask(ctx context.Context, prompt string) (string, error)
- func (c *OpenAICodexClient) Chat(ctx context.Context, messages []ChatMessage, opts ChatOptions) (ChatResponse, error)
- func (c *OpenAICodexClient) LastCodexRateLimit() (CodexRateLimitSnapshot, bool)
- func (c *OpenAICodexClient) SetRateLimitObserver(fn func(CodexRateLimitSnapshot))
- type OpenAICompatibleClient
- type ProviderError
- type ProviderOptions
- type ResponseFormat
- type ResponseFormatType
- type Role
- type Router
- type RouterConfig
- type SelectionMetadata
- type Tier
- type TierEntry
- type TierRecommendation
- type TierResolution
- type ToolCall
- type ToolChoice
- type ToolChoiceMode
- type ToolFunctionSchema
- type ToolSchema
- type Usage
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func FindClaudeCodeCLIPath ¶ added in v0.5.5
func WithSelectionMetadata ¶ added in v0.25.0
func WithSelectionMetadata(ctx context.Context, meta SelectionMetadata) context.Context
Types ¶
type AnthropicClient ¶
type AnthropicClient struct {
// contains filtered or unexported fields
}
func NewAnthropicClient ¶
func NewAnthropicClient(baseURL, apiKey, model string, maxTokens int) (*AnthropicClient, error)
func (*AnthropicClient) Chat ¶
func (c *AnthropicClient) Chat(ctx context.Context, messages []ChatMessage, opts ChatOptions) (ChatResponse, error)
type ChatMessage ¶
type ChatMessage struct {
Role string `json:"role"` // system, user, assistant, tool
Content string `json:"content"`
ContentBlocks []ContentBlock `json:"content_blocks,omitempty"` // multimodal content (takes priority over Content when non-empty)
ToolCalls []ToolCall `json:"tool_calls,omitempty"`
ToolCallID string `json:"tool_call_id,omitempty"`
// ReasoningContent is provider-specific payload metadata for tool-calling
// requests. Kimi requires it on assistant messages that include tool calls.
ReasoningContent string `json:"reasoning_content,omitempty"`
}
type ChatOptions ¶
type ChatOptions struct {
OnDelta func(text string) // SSE streaming callback (nil = no streaming)
// OnReasoningDelta receives provider-native chain-of-thought / thinking
// deltas as they stream. Called only when the provider exposes a
// distinct reasoning channel (kimi reasoning_content, anthropic
// thinking_delta, openai responses reasoning summary). nil = ignore.
// OnDelta governs whether streaming is requested; reasoning deltas only
// fire when streaming is active.
OnReasoningDelta func(text string)
Tools []ToolSchema
// ToolChoice picks how the LLM selects tools. nil = provider default (auto).
ToolChoice *ToolChoice
// ResponseFormat constrains the response shape. nil = free-form text.
ResponseFormat *ResponseFormat
// ReasoningEffort is a provider-agnostic hint. Supported values are
// none, minimal, low, medium, high.
ReasoningEffort string
// ThinkingBudget enables provider-native thinking when budgeted tokens are supported.
ThinkingBudget int
// ServiceTier controls provider-side latency tier when supported.
ServiceTier string
}
type ChatResponse ¶
type ChatResponse struct {
Message ChatMessage
Usage Usage
StopReason string
}
type ClaudeCodeCLIClient ¶ added in v0.5.5
type ClaudeCodeCLIClient struct {
// contains filtered or unexported fields
}
func NewClaudeCodeCLIClient ¶ added in v0.5.5
func NewClaudeCodeCLIClient(workDir, model string) (*ClaudeCodeCLIClient, error)
func (*ClaudeCodeCLIClient) Chat ¶ added in v0.5.5
func (c *ClaudeCodeCLIClient) Chat(ctx context.Context, messages []ChatMessage, opts ChatOptions) (ChatResponse, error)
type Client ¶
type Client interface {
Ask(ctx context.Context, prompt string) (string, error)
Chat(ctx context.Context, messages []ChatMessage, opts ChatOptions) (ChatResponse, error)
}
func NewProvider ¶
func NewProvider(opts ProviderOptions) (Client, error)
type ClientConfig ¶
type ClientConfig struct {
HTTPTimeout time.Duration
MaxTokens int
ReasoningEffort string
ThinkingBudget int
ServiceTier string
}
func DefaultClientConfig ¶
func DefaultClientConfig() ClientConfig
type CodexRateLimitSnapshot ¶ added in v0.32.27
type CodexRateLimitSnapshot struct {
Primary *CodexRateLimitWindow `json:"primary,omitempty"`
Secondary *CodexRateLimitWindow `json:"secondary,omitempty"`
RawHeaders map[string]string `json:"raw_headers,omitempty"`
CapturedAt time.Time `json:"captured_at"`
}
CodexRateLimitSnapshot is the most recently observed Codex subscription usage for a given client. RawHeaders preserves every `x-codex-*` header (including ones we don't yet model) so the API surface is forward-compatible when OpenAI ships new headers.
type CodexRateLimitSource ¶ added in v0.32.27
type CodexRateLimitSource interface {
LastCodexRateLimit() (CodexRateLimitSnapshot, bool)
}
CodexRateLimitSource is implemented by clients (and wrappers) that can surface the most recently observed Codex rate-limit snapshot. Used by the admin handler to fish the snapshot out of whatever client the router holds (raw OpenAICodexClient, or a TrackedClient wrapping one).
type CodexRateLimitWindow ¶ added in v0.32.27
type CodexRateLimitWindow struct {
UsedPercent float64 `json:"used_percent"`
WindowMinutes int `json:"window_minutes,omitempty"`
ResetAfterSeconds int `json:"reset_after_seconds,omitempty"`
}
CodexRateLimitWindow holds parsed values for one rate-limit window (primary = 5h-ish, secondary = weekly) reported by OpenAI Codex via `x-codex-*` response headers on /codex/responses calls.
type ContentBlock ¶ added in v0.14.0
type ContentBlock struct {
Type string `json:"type"` // "text", "image", "document"
Text string `json:"text,omitempty"` // for type=text
MediaType string `json:"media_type,omitempty"` // e.g. "image/png", "application/pdf"
Data string `json:"data,omitempty"` // base64-encoded binary
}
ContentBlock represents a single block in a multimodal message. Type is "text", "image", or "document".
type FakeClient ¶ added in v0.25.0
type FakeClient struct {
// Label identifies this client in assertions (e.g. "heavy", "light").
Label string
// AskResponse is returned from Ask; if empty, a default is synthesized.
AskResponse string
// ChatResponse is returned from Chat; if zero-valued, a default is
// synthesized that echoes Label in the message content.
ChatResponse ChatResponse
// AskCalls counts invocations of Ask.
AskCalls int
// ChatCalls counts invocations of Chat.
ChatCalls int
// LastChatOptions records the most recent Chat options.
LastChatOptions ChatOptions
}
FakeClient is a minimal Client implementation for tests. Each call records its arguments and returns a canned response so that test code can assert which tier/role was resolved.
func (*FakeClient) Chat ¶ added in v0.25.0
func (f *FakeClient) Chat(_ context.Context, _ []ChatMessage, opts ChatOptions) (ChatResponse, error)
Chat implements llm.Client.
type GeminiNativeClient ¶
type GeminiNativeClient struct {
// contains filtered or unexported fields
}
func NewGeminiNativeClient ¶
func NewGeminiNativeClient(baseURL, apiKey, model string) (*GeminiNativeClient, error)
func (*GeminiNativeClient) Chat ¶
func (c *GeminiNativeClient) Chat(ctx context.Context, messages []ChatMessage, opts ChatOptions) (ChatResponse, error)
type ModelFetcher ¶
type ModelFetcher interface {
FetchModels(ctx context.Context, opts ProviderOptions) ([]string, error)
}
ModelFetcher resolves provider model ids via provider-specific live APIs.
func NewModelFetcher ¶
func NewModelFetcher() ModelFetcher
type OpenAICodexClient ¶
type OpenAICodexClient struct {
// contains filtered or unexported fields
}
func NewOpenAICodexClient ¶
func NewOpenAICodexClient(baseURL, model, authMode, oauthProvider, apiKey string) (*OpenAICodexClient, error)
func (*OpenAICodexClient) Chat ¶
func (c *OpenAICodexClient) Chat(ctx context.Context, messages []ChatMessage, opts ChatOptions) (ChatResponse, error)
func (*OpenAICodexClient) LastCodexRateLimit ¶ added in v0.32.27
func (c *OpenAICodexClient) LastCodexRateLimit() (CodexRateLimitSnapshot, bool)
LastCodexRateLimit returns the most recent rate-limit snapshot observed from `/codex/responses` response headers, if any. Implements CodexRateLimitSource.
func (*OpenAICodexClient) SetRateLimitObserver ¶ added in v0.32.28
func (c *OpenAICodexClient) SetRateLimitObserver(fn func(CodexRateLimitSnapshot))
SetRateLimitObserver registers a callback invoked once per parsed `x-codex-*` snapshot. Wired by the server at startup so that an external watcher (e.g. SSE notification dispatcher) can react to threshold crossings without the client having to know about server concerns. Passing nil clears the observer.
type OpenAICompatibleClient ¶
type OpenAICompatibleClient struct {
// contains filtered or unexported fields
}
OpenAICompatibleClient works with any OpenAI-compatible /chat/completions API (OpenAI, Azure OpenAI, etc.).
func NewGeminiClient ¶
func NewGeminiClient(baseURL, apiKey, model string) (*OpenAICompatibleClient, error)
func NewOpenAIClient ¶
func NewOpenAIClient(baseURL, apiKey, model string) (*OpenAICompatibleClient, error)
func (*OpenAICompatibleClient) Chat ¶
func (c *OpenAICompatibleClient) Chat(ctx context.Context, messages []ChatMessage, opts ChatOptions) (ChatResponse, error)
type ProviderError ¶
type ProviderError struct {
Provider string
Operation string
StatusCode int
Message string
Cause error
}
ProviderError is a structured error for LLM provider failures.
func (*ProviderError) Error ¶
func (e *ProviderError) Error() string
func (*ProviderError) Unwrap ¶
func (e *ProviderError) Unwrap() error
type ProviderOptions ¶
type ResponseFormat ¶ added in v0.31.0
type ResponseFormat struct {
Type ResponseFormatType
Name string
Schema json.RawMessage
Strict bool
}
ResponseFormat constrains the model output. Schema is required when Type == ResponseFormatJSONSchema. Strict enables provider-side strict validation (currently OpenAI-style only).
type ResponseFormatType ¶ added in v0.31.0
type ResponseFormatType string
ResponseFormatType enumerates the supported response shapes.
const ( ResponseFormatText ResponseFormatType = "text" ResponseFormatJSONObject ResponseFormatType = "json_object" ResponseFormatJSONSchema ResponseFormatType = "json_schema" )
type Role ¶ added in v0.25.0
type Role string
Role identifies a semantic caller of the LLM layer. Role → Tier is a many-to-one mapping controlled by config; code references Role constants and never concrete tier names, so that reassigning a role to a different tier is a config-only change.
const ( // RoleChatMain is the user-facing chat handler that streams responses // to the console/API. RoleChatMain Role = "chat_main" // RoleContextCompactor runs background transcript compaction and // compaction-memory extraction. Light by default. RoleContextCompactor Role = "context_compactor" // RoleMemoryHook runs per-turn memory maintenance (daily log append, // explicit "remember ..." hot path). Light by default. RoleMemoryHook Role = "memory_hook" // RoleReflectionMemory was the nightly knowledge-base compilation // role. The KB system was removed in ID-001; this role is kept in // the enumeration for backward-compatible config parsing but no // production code resolves it anymore. RoleReflectionMemory Role = "reflection_memory" // RoleReflectionKB runs nightly KB cleanup. Currently non-LLM, reserved // for future use. RoleReflectionKB Role = "reflection_kb" // RolePulseDecider is the pulse watchdog classifier. Light by default. RolePulseDecider Role = "pulse_decider" // RoleSessionCleanup analyzes compact session metadata and transcript // snippets for user-reviewed archive/delete cleanup suggestions. RoleSessionCleanup Role = "session_cleanup" // RoleAgentRuntimeDefault is the default executor role for agent runtime agents // that do not declare a tier explicitly. Standard by default. RoleAgentRuntimeDefault Role = "agentruntime_default" // RoleAgentRuntimePlanner is reserved for planner-style agents that benefit // from heavy reasoning. RoleAgentRuntimePlanner Role = "agentruntime_planner" // RoleGoalJudge classifies whether a session's active goal has been // satisfied after the latest assistant turn. Light by default — a fast // model is preferable for quick yes/no judgments. RoleGoalJudge Role = "goal_judge" // RoleCritic reviews a freshly-proposed or just-completed plan and // returns concrete improvement feedback or an "acceptable" verdict. Used // by the session-level critic agent loop (up to N iterations per plan // transition). Standard by default — needs enough capability to spot // non-trivial gaps but does not require heavy reasoning. RoleCritic Role = "critic" )
func AllRoles ¶ added in v0.25.0
func AllRoles() []Role
AllRoles returns the exhaustive list of roles in canonical order. Used for config validation and defaulting.
func ParseRole ¶ added in v0.25.0
ParseRole parses a role name (case-insensitive, trimmed). Returns the zero value and false when the role is unknown.
func ParseRoleOrKeep ¶ added in v0.25.0
type Router ¶ added in v0.25.0
type Router interface {
// ClientFor returns the client for the given role, applying the
// configured Role→Tier mapping. Unknown roles fall back to DefaultTier.
ClientFor(role Role) (Client, TierResolution, error)
// ClientForTier returns the client for an explicitly requested tier.
// This is used by callers that already know the tier (e.g. a sub-agent
// task has set an explicit tier override).
ClientForTier(tier Tier) (Client, TierResolution, error)
// DefaultTier reports the tier used when a role has no explicit mapping.
DefaultTier() Tier
// TierForRole reports which tier the given role resolves to without
// fetching the client. Returns DefaultTier when the role is not mapped.
TierForRole(role Role) Tier
}
Router resolves (Role | Tier) to a concrete llm.Client.
The intended usage pattern is: construct exactly one Router at server startup with three pre-wrapped tier clients; hand it to every subsystem (chat, pulse, reflection, agent runtime, compaction); callers ask for a client by Role and remain oblivious to which tier or model actually served them.
func NewFakeRouter ¶ added in v0.25.0
func NewFakeRouter(defaultTier Tier, roleDefaults map[Role]Tier) (Router, map[Tier]*FakeClient, error)
NewFakeRouter builds a Router backed by FakeClients, one per tier. Each tier gets a FakeClient labelled with the tier name. Useful in tests that need to assert which tier was used for which call.
func NewRouter ¶ added in v0.25.0
func NewRouter(cfg RouterConfig) (Router, error)
NewRouter validates the config and returns a Router ready to serve clients. Returns an error if any required tier is missing or if RoleDefaults references an unknown tier.
type RouterConfig ¶ added in v0.25.0
type RouterConfig struct {
// Tiers maps tier → client binding. All three tiers (heavy/standard/light)
// should be present for production use; NewRouter will error if any is
// missing, although the backing clients may be identical when the caller
// wants a single model everywhere (legacy mode).
Tiers map[Tier]TierEntry
// DefaultTier is used when a role has no explicit mapping. Must be one
// of the tiers present in Tiers.
DefaultTier Tier
// RoleDefaults maps role → tier. Roles not present here fall back to
// DefaultTier. An unknown role in the map is silently ignored — the
// Router validates only the tier side.
RoleDefaults map[Role]Tier
}
RouterConfig is the input to NewRouter. The caller is responsible for constructing and (optionally) wrapping the clients for each tier before handing them to the router; this keeps the llm package free of a dependency on internal/usage.
type SelectionMetadata ¶ added in v0.25.0
type SelectionMetadata struct {
Role Role
Tier Tier
Provider string
Model string
Source string
SessionID string
RunID string
AgentName string
FlowID string
StepID string
}
func SelectionMetadataFromContext ¶ added in v0.25.0
func SelectionMetadataFromContext(ctx context.Context) (SelectionMetadata, bool)
type Tier ¶ added in v0.25.0
type Tier string
Tier identifies a named LLM configuration bundle (provider+model+knobs). Three tiers are supported so that callers can target a class of model (heavy reasoning / standard / fast-light) without knowing the concrete provider or model name at the call site.
const ( // TierHeavy is for high-reasoning work: planning, complex code changes, // architectural decisions, long-context synthesis. TierHeavy Tier = "heavy" // TierStandard is the general-purpose default used for chat and most // agent runtime work. TierStandard Tier = "standard" // TierLight is for fast, cheap operations: summarization, classification, // memory hooks, pulse deciders, reflection compaction. TierLight Tier = "light" )
func AllTiers ¶ added in v0.25.0
func AllTiers() []Tier
AllTiers returns the full set of supported tiers in canonical order.
func ParseTier ¶ added in v0.25.0
ParseTier parses a tier name, returning an error for unknown values. Empty input is treated as an error so that callers can distinguish "unset" (use default) from "explicit but invalid".
func ParseTierOrKeep ¶ added in v0.25.0
type TierEntry ¶ added in v0.25.0
TierEntry is one tier's concrete binding: the client to use and the provider/model labels that identify it (for logs and usage tracking).
type TierRecommendation ¶ added in v0.31.119
type TierRecommendation struct {
TaskType string `json:"task_type"`
RecommendedTier Tier `json:"recommended_tier"`
Reason string `json:"reason"`
Confidence float64 `json:"confidence"`
ShouldPrompt bool `json:"should_prompt"`
}
func RecommendTierForTask ¶ added in v0.31.119
func RecommendTierForTask(message string) TierRecommendation
type TierResolution ¶ added in v0.25.0
type TierResolution struct {
// Tier is the tier that was selected.
Tier Tier
// Role is the role the caller asked for; zero value when the caller
// asked for a tier directly via ClientForTier.
Role Role
// Provider is the provider identifier backing the selected tier
// (e.g. "anthropic", "openai", "gemini-native").
Provider string
// Model is the concrete model name backing the selected tier.
Model string
// Source describes why this tier was picked. One of:
// "role" (role→tier map), "default" (fell back to DefaultTier),
// "explicit" (ClientForTier was called).
Source string
}
TierResolution describes how a Router resolved a request for a client. It is returned alongside the Client so that callers can log or emit events that tell the user exactly which tier and model served the call.
type ToolChoice ¶ added in v0.31.0
type ToolChoice struct {
Mode ToolChoiceMode
Name string
}
ToolChoice expresses how the LLM should pick (or be forced to pick) a tool. nil means "no preference" — equivalent to ToolChoiceAuto for providers that require a value. Mode == ToolChoiceModeSpecific requires Name.
func ToolChoiceAuto ¶ added in v0.31.0
func ToolChoiceAuto() *ToolChoice
ToolChoiceAuto returns the default "auto" choice.
func ToolChoiceNone ¶ added in v0.31.0
func ToolChoiceNone() *ToolChoice
ToolChoiceNone forbids tool calls.
func ToolChoiceRequired ¶ added in v0.31.0
func ToolChoiceRequired() *ToolChoice
ToolChoiceRequired forces *some* tool call.
func ToolChoiceSpecific ¶ added in v0.31.0
func ToolChoiceSpecific(name string) *ToolChoice
ToolChoiceSpecific forces calling a specific tool by name.
func (*ToolChoice) String ¶ added in v0.31.0
func (tc *ToolChoice) String() string
String returns a short label for logging.
type ToolChoiceMode ¶ added in v0.31.0
type ToolChoiceMode string
ToolChoiceMode enumerates the provider-agnostic tool selection modes.
const ( ToolChoiceModeAuto ToolChoiceMode = "auto" ToolChoiceModeNone ToolChoiceMode = "none" ToolChoiceModeRequired ToolChoiceMode = "required" ToolChoiceModeSpecific ToolChoiceMode = "specific" )
type ToolFunctionSchema ¶
type ToolFunctionSchema struct {
Name string `json:"name"`
Description string `json:"description"`
Parameters json.RawMessage `json:"parameters,omitempty"`
}
type ToolSchema ¶
type ToolSchema struct {
Type string `json:"type"`
Function ToolFunctionSchema `json:"function"`
}
Source Files
¶
- anthropic.go
- ask.go
- claude_code_cli.go
- errors.go
- gemini_native.go
- gemini_native_chat.go
- gemini_native_convert.go
- http_utils.go
- model_lister.go
- openai_codex_client.go
- openai_codex_ratelimit.go
- openai_compat_client.go
- provider.go
- role.go
- router.go
- router_fake.go
- selection_context.go
- tier.go
- tier_recommendation.go
- tool_json.go
- transport.go
- validation.go