providerpool

package
v0.0.0-...-8acab51 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 26, 2026 License: MIT Imports: 43 Imported by: 0

Documentation

Overview

Package providerpool provides unified LLM provider management for ZimaOS-Blue. It supports multiple providers, intelligent routing, and usage tracking.

Index

Constants

View Source
const (
	// TrialProviderID is the ID of the trial provider
	TrialProviderID = "zimaos-blue-trial"
)

Variables

View Source
var (
	// ErrProviderNotFound indicates the requested provider does not exist
	ErrProviderNotFound = errors.New("provider not found")

	// ErrProviderExists indicates a provider with the same ID already exists
	ErrProviderExists = errors.New("provider already exists")

	// ErrInvalidProviderID indicates the provider ID is malformed or unsafe.
	ErrInvalidProviderID = errors.New("invalid provider id")

	// ErrProviderDisabled indicates the provider is disabled
	ErrProviderDisabled = errors.New("provider is disabled")

	// ErrNoAvailableProvider indicates no healthy provider is available
	ErrNoAvailableProvider = errors.New("no available provider")

	// ErrModelNotFound indicates the requested model does not exist
	ErrModelNotFound = errors.New("model not found")

	// ErrModelDisabled indicates the model is disabled
	ErrModelDisabled = errors.New("model is disabled")

	// ErrAPIKeyNotFound indicates the requested API key does not exist
	ErrAPIKeyNotFound = errors.New("api key not found")

	// ErrAPIKeyInvalid indicates the API key is invalid or expired
	ErrAPIKeyInvalid = errors.New("api key is invalid")

	// ErrAuthRequired indicates authentication is required but no valid credentials provided
	ErrAuthRequired = errors.New("authentication required - please provide a valid API key")

	// ErrNoAPIKey indicates no API key is configured for the provider
	ErrNoAPIKey = errors.New("no api key configured")

	// ErrRateLimitExceeded indicates the rate limit has been exceeded
	ErrRateLimitExceeded = errors.New("rate limit exceeded")

	// ErrQuotaExceeded indicates the usage quota has been exceeded
	ErrQuotaExceeded = errors.New("quota exceeded")

	// ErrEncryptionFailed indicates encryption/decryption failed
	ErrEncryptionFailed = errors.New("encryption failed")

	// ErrStorageError indicates a storage operation failed
	ErrStorageError = errors.New("storage error")

	// ErrInvalidConfig indicates invalid configuration
	ErrInvalidConfig = errors.New("invalid configuration")

	// ErrIDENotFound indicates the IDE was not found
	ErrIDENotFound = errors.New("ide not found")

	// ErrIDEConnectionFailed indicates connection to IDE failed
	ErrIDEConnectionFailed = errors.New("ide connection failed")

	// ErrPricingNotFound indicates the pricing configuration was not found
	ErrPricingNotFound = errors.New("pricing not found")
)
View Source
var (
	ErrLicenseInvalid   = errors.New("invalid license")
	ErrLicenseExpired   = errors.New("license expired")
	ErrLicenseKeyID     = errors.New("unknown key ID")
	ErrLicenseSignature = errors.New("signature verification failed")
	ErrStateTampered    = errors.New("state file tampered")
)
View Source
var (
	// BuiltinModelPricing contains known model pricing (per 1M tokens, USD).
	// Updated: 2026-02
	BuiltinModelPricing map[string]*ModelPricing
)
View Source
var (
	// ErrTrialQuotaExhausted is returned when trial quota is exhausted
	ErrTrialQuotaExhausted = errors.New("trial quota exhausted")
)

Functions

func BuiltinModels

func BuiltinModels() map[string][]*Model

BuiltinModels returns effective built-in models with remote catalog overrides applied.

func BuiltinModelsSnapshot

func BuiltinModelsSnapshot() map[string][]*Model

func CheckMigrationNeeded

func CheckMigrationNeeded(dataDir string) bool

CheckMigrationNeeded checks if there's a legacy config that needs migration

func ClearOfficialProviderCatalog

func ClearOfficialProviderCatalog()

func DeleteTrialState

func DeleteTrialState(dataDir string) error

DeleteTrialState removes the state file.

func GenerateID

func GenerateID(prefix string) string

GenerateID generates a random ID with the given prefix

func GetTrialLicense

func GetTrialLicense() string

GetTrialLicense returns the raw build-time license string.

func HashAPIKey

func HashAPIKey(key string) string

HashAPIKey creates a display-safe hash of an API key Returns first 8 chars + "..." + last 4 chars

func HashAPIKeyFull

func HashAPIKeyFull(key string) string

HashAPIKeyFull creates a full SHA-256 hash of an API key for identification

func IsTrialProvider

func IsTrialProvider(providerID string) bool

IsTrialProvider checks if a provider ID is the trial provider

func LoadLicenseIAT

func LoadLicenseIAT(dataDir string) int64

LoadLicenseIAT reads the stored license IAT. Returns 0 if not found.

func LoadTrialState

func LoadTrialState(dataDir string, licenseSig []byte) (*trialState, error)

LoadTrialState reads and verifies the HMAC-protected state file. Returns (nil, nil) if file doesn't exist (fresh install). Returns (nil, ErrStateTampered) if HMAC verification fails.

func SaveLicenseIAT

func SaveLicenseIAT(dataDir string, iat int64) error

SaveLicenseIAT writes the license issued-at timestamp to a plain file.

func SaveTrialState

func SaveTrialState(dataDir string, licenseSig []byte, state *trialState) error

SaveTrialState writes HMAC-protected state to disk. Format: base64(json) + "." + base64(hmac-sha256)

func SetOfficialProviderCatalog

func SetOfficialProviderCatalog(catalog officialProviderCatalog)

func SignLicense

func SignLicense(claims *LicenseClaims, privateKeyPEM string) (string, error)

SignLicense signs claims with an Ed25519 private key (PEM-encoded PKCS8). Used by the build tool and tests only.

func SupportsChatCompletions

func SupportsChatCompletions(model *Model) bool

SupportsChatCompletions reports whether a discovered model should be used for chat-completions style routing.

func SupportsChatCompletionsModelID

func SupportsChatCompletionsModelID(modelID string) bool

SupportsChatCompletionsModelID returns whether the model identifier looks suitable for chat-completions style requests. Unknown model IDs default to true so custom relays still work, but clearly non-chat families are rejected.

func UsesResponsesIntegration

func UsesResponsesIntegration(provider *Provider) bool

UsesResponsesIntegration reports whether a provider targets the Codex/Responses-native integration path. This is used for routing heuristics and warmup behavior, not gating.

func ValidateProviderID

func ValidateProviderID(raw string) (string, error)

ValidateProviderID ensures provider IDs are safe for routing and file-backed storage.

Types

type APIFormat

type APIFormat string

APIFormat represents the API format used by a provider

const (
	// APIFormatOpenAI represents OpenAI-compatible API format (default)
	APIFormatOpenAI APIFormat = "openai"
	// APIFormatResponses represents Responses API format (e.g. /v1/responses, /backend-api/codex/responses)
	APIFormatResponses APIFormat = "responses"
	// APIFormatAnthropic represents Anthropic Claude API format
	APIFormatAnthropic APIFormat = "anthropic"
	// APIFormatOllama represents Ollama API format
	APIFormatOllama APIFormat = "ollama"
	// APIFormatGoogle represents Google AI API format
	APIFormatGoogle APIFormat = "google"
	// APIFormatCloudCode represents Google Cloud Code Assist API format (used by Antigravity/Gemini CLI OAuth)
	APIFormatCloudCode APIFormat = "cloudcode"
	// APIFormatCopilot represents GitHub Copilot API format (OpenAI-compatible with Copilot auth)
	APIFormatCopilot APIFormat = "copilot"
)

func DetectEndpointFixedFormat

func DetectEndpointFixedFormat(raw string) (APIFormat, bool)

DetectEndpointFixedFormat infers a fixed API family from an endpoint-specific base URL.

func DetectEndpointFixedFormatFromPath

func DetectEndpointFixedFormatFromPath(path string) (APIFormat, bool)

DetectEndpointFixedFormatFromPath infers a fixed API family from a URL path.

func PreferredAPIFormatsForModel

func PreferredAPIFormatsForModel(modelID string) []APIFormat

type APIFormatMode

type APIFormatMode string

APIFormatMode controls whether a provider uses a fixed format or runtime resolution.

const (
	// APIFormatModeAuto lets the runtime resolve the best format for the request.
	APIFormatModeAuto APIFormatMode = "auto"
	// APIFormatModePinned forces a single configured format.
	APIFormatModePinned APIFormatMode = "pinned"
)

func ProviderAPIFormatMode

func ProviderAPIFormatMode(provider *Provider) APIFormatMode

ProviderAPIFormatMode returns the effective format mode, applying sensible defaults.

type APIKey

type APIKey struct {
	ID         string    `json:"id"`
	Key        string    `json:"-"`        // Never expose in JSON
	KeyHash    string    `json:"key_hash"` // For identification (first 8 + last 4 chars)
	KeyDigest  string    `json:"-"`        // Internal full fingerprint for dedupe/storage only
	Label      string    `json:"label,omitempty"`
	UsageCount int64     `json:"usage_count"`
	LastUsed   time.Time `json:"last_used,omitempty"`
	CreatedAt  time.Time `json:"created_at"`
	Enabled    bool      `json:"enabled"`
}

APIKey represents a single API key with metadata

type CapabilityProfile

type CapabilityProfile struct {
	ToolCallMode               string `json:"tool_call_mode,omitempty"`
	SupportsParallelToolCalls  bool   `json:"supports_parallel_tool_calls,omitempty"`
	SupportsStreamingToolCalls bool   `json:"supports_streaming_tool_calls,omitempty"`
	SupportsJSONSchema         bool   `json:"supports_json_schema,omitempty"`
	MaxToolSchemaBytes         int    `json:"max_tool_schema_bytes,omitempty"`
	SupportsVision             bool   `json:"supports_vision,omitempty"`
	SupportsAudio              bool   `json:"supports_audio,omitempty"`
}

CapabilityProfile describes the tool/runtime surface a provider can support.

type CooldownConfig

type CooldownConfig struct {
	// FailureThreshold is the number of failures before cooldown
	FailureThreshold int `json:"failure_threshold"`
	// InitialCooldown is the initial cooldown duration
	InitialCooldown time.Duration `json:"initial_cooldown"`
	// MaxCooldown is the maximum cooldown duration
	MaxCooldown time.Duration `json:"max_cooldown"`
	// CooldownMultiplier increases cooldown on repeated failures
	CooldownMultiplier float64 `json:"cooldown_multiplier"`
	// ResetAfter resets failure count after this duration of success
	ResetAfter time.Duration `json:"reset_after"`

	// Transient error overrides (502/503) — shorter cooldown for temporary upstream issues
	TransientFailureThreshold int           `json:"transient_failure_threshold"` // 0 = use FailureThreshold
	TransientInitialCooldown  time.Duration `json:"transient_initial_cooldown"`  // 0 = use InitialCooldown
	TransientMaxCooldown      time.Duration `json:"transient_max_cooldown"`      // 0 = use MaxCooldown
}

CooldownConfig configures the cooldown behavior

func DefaultCooldownConfig

func DefaultCooldownConfig() *CooldownConfig

DefaultCooldownConfig returns sensible defaults for cooldown

type CooldownEntry

type CooldownEntry struct {
	ProviderID            string    `json:"provider_id"`
	CooldownUntil         time.Time `json:"cooldown_until"`
	FailureCount          int       `json:"failure_count"`
	TransientFailureCount int       `json:"transient_failure_count"` // 502/503 failures tracked separately
	LastFailure           time.Time `json:"last_failure"`
	LastError             string    `json:"last_error"`
}

CooldownEntry tracks cooldown state for a provider

type DeduplicateResult

type DeduplicateResult struct {
	Merged       int      `json:"merged"`
	Deleted      []string `json:"deleted,omitempty"`
	KeptProvider string   `json:"kept_provider,omitempty"`
}

DeduplicateResult contains the result of a deduplication operation

func DeduplicateProviders

func DeduplicateProviders(pool *Pool) (*DeduplicateResult, error)

DeduplicateProviders finds and merges duplicate custom providers based on base_url and api_key. This handles historical data where providers like "claude-code" and "custom" may have been created with the same configuration.

type FailoverReason

type FailoverReason string

FailoverReason represents why a failover occurred

const (
	// FailoverReasonAPIError indicates the provider returned an API error
	FailoverReasonAPIError FailoverReason = "api_error"
	// FailoverReasonTimeout indicates the request timed out
	FailoverReasonTimeout FailoverReason = "timeout"
	// FailoverReasonRateLimit indicates rate limiting was hit
	FailoverReasonRateLimit FailoverReason = "rate_limit"
	// FailoverReasonAuthError indicates authentication failed
	FailoverReasonAuthError FailoverReason = "auth_error"
	// FailoverReasonModelNotFound indicates the model was not available
	FailoverReasonModelNotFound FailoverReason = "model_not_found"
	// FailoverReasonCooldown indicates the provider is in cooldown
	FailoverReasonCooldown FailoverReason = "cooldown"
	// FailoverReasonUnknown indicates an unknown error
	FailoverReasonUnknown FailoverReason = "unknown"
)

type FailoverRecord

type FailoverRecord struct {
	Timestamp      time.Time      `json:"timestamp"`
	ProviderID     string         `json:"provider_id"`
	ProviderName   string         `json:"provider_name"`
	ModelID        string         `json:"model_id"`
	Reason         FailoverReason `json:"reason"`
	Error          string         `json:"error"`
	Latency        time.Duration  `json:"latency"`
	NextProviderID string         `json:"next_provider_id,omitempty"`
}

FailoverRecord tracks a single failover event

type FailoverResult

type FailoverResult struct {
	RequestID       string            `json:"request_id"`
	StartTime       time.Time         `json:"start_time"`
	EndTime         time.Time         `json:"end_time"`
	TotalAttempts   int               `json:"total_attempts"`
	SuccessProvider string            `json:"success_provider,omitempty"`
	SuccessModel    string            `json:"success_model,omitempty"`
	FailedAttempts  []*FailoverRecord `json:"failed_attempts,omitempty"`
	FinalError      string            `json:"final_error,omitempty"`
}

FailoverResult contains the complete failover tracking for a request

func (*FailoverResult) Summary

func (r *FailoverResult) Summary() string

Summary returns a compact trace of provider attempts for logging.

type FileStorage

type FileStorage struct {
	// contains filtered or unexported fields
}

FileStorage implements Storage using JSON files

func NewFileStorage

func NewFileStorage(basePath string, opts ...StorageOption) (*FileStorage, error)

NewFileStorage creates a new FileStorage

func (*FileStorage) AppendUsage

func (s *FileStorage) AppendUsage(record *UsageRecord) error

AppendUsage appends a usage record to the daily log

func (*FileStorage) DeleteProvider

func (s *FileStorage) DeleteProvider(id string) error

DeleteProvider removes a provider from storage

func (*FileStorage) LoadAllProviders

func (s *FileStorage) LoadAllProviders() ([]*Provider, error)

LoadAllProviders loads all providers from storage

func (*FileStorage) LoadConfig

func (s *FileStorage) LoadConfig() (*PoolConfig, error)

LoadConfig loads the pool configuration

func (*FileStorage) LoadModels

func (s *FileStorage) LoadModels(providerID string) ([]*Model, error)

LoadModels loads models for a provider

func (*FileStorage) LoadPricingConfig

func (s *FileStorage) LoadPricingConfig() (*PricingConfig, error)

LoadPricingConfig loads the pricing configuration

func (*FileStorage) LoadProvider

func (s *FileStorage) LoadProvider(id string) (*Provider, error)

LoadProvider loads a provider from storage

func (*FileStorage) LoadUsage

func (s *FileStorage) LoadUsage(providerID string, start, end time.Time) ([]*UsageRecord, error)

LoadUsage loads usage records for a time range

func (*FileStorage) SaveConfig

func (s *FileStorage) SaveConfig(config *PoolConfig) error

SaveConfig saves the pool configuration

func (*FileStorage) SaveModels

func (s *FileStorage) SaveModels(providerID string, models []*Model) error

SaveModels saves models for a provider

func (*FileStorage) SavePricingConfig

func (s *FileStorage) SavePricingConfig(config *PricingConfig) error

SavePricingConfig saves the pricing configuration

func (*FileStorage) SaveProvider

func (s *FileStorage) SaveProvider(provider *Provider) error

SaveProvider saves a provider to storage

type FormatResolutionBaseURLMode

type FormatResolutionBaseURLMode string

FormatResolutionBaseURLMode describes how the provider base URL should be interpreted.

const (
	FormatResolutionBaseURLModeRoot          FormatResolutionBaseURLMode = "root"
	FormatResolutionBaseURLModeFixedEndpoint FormatResolutionBaseURLMode = "fixed_endpoint"
	FormatResolutionBaseURLModeDetected      FormatResolutionBaseURLMode = "detected_endpoint"
)

type FormatResolutionPlan

type FormatResolutionPlan struct {
	SelectedFormat   APIFormat                   `json:"selected_format"`
	CandidateFormats []APIFormat                 `json:"candidate_formats"`
	Source           FormatResolutionSource      `json:"resolution_source"`
	BaseURLMode      FormatResolutionBaseURLMode `json:"base_url_mode"`
	Mutable          bool                        `json:"mutable"`
	TrySelectedFirst bool                        `json:"try_selected_first"`
}

FormatResolutionPlan is the shared format-selection output used by verify/router/proxy.

func ResolveAPIFormatPlan

func ResolveAPIFormatPlan(req FormatResolutionRequest) FormatResolutionPlan

ResolveAPIFormatPlan returns the unified API format decision for a provider/model pair.

func (FormatResolutionPlan) Known

func (p FormatResolutionPlan) Known() bool

type FormatResolutionRequest

type FormatResolutionRequest struct {
	Provider             *Provider
	ModelID              string
	DetectedFormat       APIFormat
	ModelMemoryFormat    APIFormat
	ProviderMemoryFormat APIFormat
}

FormatResolutionRequest carries the facts used to resolve a format plan.

type FormatResolutionSource

type FormatResolutionSource string

FormatResolutionSource describes why a format was chosen.

const (
	FormatResolutionSourceEndpointLock  FormatResolutionSource = "endpoint_lock"
	FormatResolutionSourceUserPinned    FormatResolutionSource = "user_pinned"
	FormatResolutionSourceDetected      FormatResolutionSource = "detected"
	FormatResolutionSourceModelMemory   FormatResolutionSource = "model_memory"
	FormatResolutionSourceFamilyDefault FormatResolutionSource = "family_default"
)

type Handler

type Handler struct {
	// contains filtered or unexported fields
}

func NewHandler

func NewHandler(pool *Pool) *Handler

NewHandler creates a new Handler

func (*Handler) AddAPIKey

func (h *Handler) AddAPIKey(c echo.Context) error

AddAPIKey adds an API key to a provider

func (*Handler) AddProvider

func (h *Handler) AddProvider(c echo.Context) error

AddProvider adds a new custom provider

func (*Handler) ClearError

func (h *Handler) ClearError(c echo.Context) error

ClearError clears the error status of a provider, allowing manual retry

func (*Handler) CompleteDeviceFlow

func (h *Handler) CompleteDeviceFlow(c echo.Context) error

CompleteDeviceFlow completes a GitHub device code flow.

func (*Handler) ConnectIDE

func (h *Handler) ConnectIDE(c echo.Context) error

ConnectIDE connects to an IDE

func (*Handler) DeleteProvider

func (h *Handler) DeleteProvider(c echo.Context) error

DeleteProvider removes a provider

func (*Handler) DeleteProviderIcon

func (h *Handler) DeleteProviderIcon(c echo.Context) error

DeleteProviderIcon removes the custom icon for a provider

func (*Handler) DetectCapabilities

func (h *Handler) DetectCapabilities(c echo.Context) error

DetectCapabilities detects server capabilities for a provider

func (*Handler) DisableProvider

func (h *Handler) DisableProvider(c echo.Context) error

DisableProvider disables a provider

func (*Handler) DisconnectOAuth

func (h *Handler) DisconnectOAuth(c echo.Context) error

DisconnectOAuth disconnects OAuth for a provider. Supports both /:id/oauth/disconnect (disconnect all) and /:id/oauth/:accountId/disconnect.

func (*Handler) EnableProvider

func (h *Handler) EnableProvider(c echo.Context) error

EnableProvider enables a provider

func (*Handler) FetchProviderModels

func (h *Handler) FetchProviderModels(c echo.Context) error

FetchProviderModels fetches models from a provider

func (*Handler) GetEnvHints

func (h *Handler) GetEnvHints(c echo.Context) error

GetEnvHints returns environment variable hints for IDE configuration

func (*Handler) GetImportableConfigs

func (h *Handler) GetImportableConfigs(c echo.Context) error

GetImportableConfigs returns all IDE configurations that can be imported

func (*Handler) GetLocationStats

func (h *Handler) GetLocationStats(c echo.Context) error

GetLocationStats returns statistics about provider locations

func (*Handler) GetOAuthAccounts

func (h *Handler) GetOAuthAccounts(c echo.Context) error

GetOAuthAccounts returns all connected OAuth accounts for a provider.

func (*Handler) GetOAuthQuota

func (h *Handler) GetOAuthQuota(c echo.Context) error

GetOAuthQuota returns subscription tier and per-model quota for an OAuth provider. Results are cached for 5 minutes.

func (*Handler) GetOAuthStatus

func (h *Handler) GetOAuthStatus(c echo.Context) error

GetOAuthStatus returns the OAuth status for a provider.

func (*Handler) GetPricingConfig

func (h *Handler) GetPricingConfig(c echo.Context) error

GetPricingConfig returns the current pricing configuration

func (*Handler) GetProvider

func (h *Handler) GetProvider(c echo.Context) error

GetProvider returns a specific provider

func (*Handler) GetProviderAccountStatus

func (h *Handler) GetProviderAccountStatus(c echo.Context) error

GetProviderAccountStatus returns provider-native account telemetry for supported providers.

func (*Handler) GetProviderCatalogStatus

func (h *Handler) GetProviderCatalogStatus(c echo.Context) error

func (*Handler) GetProviderUsage

func (h *Handler) GetProviderUsage(c echo.Context) error

GetProviderUsage returns usage for a specific provider

func (*Handler) GetRoutingMode

func (h *Handler) GetRoutingMode(c echo.Context) error

GetRoutingMode returns the current routing mode

func (*Handler) GetTrialQuota

func (h *Handler) GetTrialQuota(c echo.Context) error

GetTrialQuota returns the current trial quota status

func (*Handler) GetUsageStats

func (h *Handler) GetUsageStats(c echo.Context) error

GetUsageStats returns overall usage statistics

func (*Handler) HandleOAuthCallback

func (h *Handler) HandleOAuthCallback(c echo.Context) error

HandleOAuthCallback handles the OAuth redirect callback.

func (*Handler) ImportExtensionConfig

func (h *Handler) ImportExtensionConfig(c echo.Context) error

ImportExtensionConfig imports Claude Code extension config from an IDE's settings.json

func (*Handler) ImportFromCCSwitch

func (h *Handler) ImportFromCCSwitch(c echo.Context) error

ImportFromCCSwitch imports configuration from Claude Code's cc switch output

func (*Handler) ImportIDEConfig

func (h *Handler) ImportIDEConfig(c echo.Context) error

ImportIDEConfig imports configuration from a specific IDE

func (*Handler) ImportOAuthToken

func (h *Handler) ImportOAuthToken(c echo.Context) error

ImportOAuthToken imports an OAuth token scanned from a local IDE.

func (*Handler) ListAllModels

func (h *Handler) ListAllModels(c echo.Context) error

ListAllModels returns all models from all providers

func (*Handler) ListModelPricing

func (h *Handler) ListModelPricing(c echo.Context) error

ListModelPricing returns all custom model pricing configurations

func (*Handler) ListProviderModels

func (h *Handler) ListProviderModels(c echo.Context) error

ListProviderModels returns models for a provider

func (*Handler) ListProviders

func (h *Handler) ListProviders(c echo.Context) error

ListProviders returns all providers with their models inlined.

func (*Handler) ProbeProviderModels

func (h *Handler) ProbeProviderModels(c echo.Context) error

ProbeProviderModels probes all models for a provider to check which are actually configured. This sends a minimal request (max_tokens:1) to each model in parallel and disables models that return "not configured" errors.

func (*Handler) RecalculateCosts

func (h *Handler) RecalculateCosts(c echo.Context) error

RecalculateCosts recalculates costs for historical usage records

func (*Handler) RegisterConfigRoutes

func (h *Handler) RegisterConfigRoutes(g *echo.Group)

RegisterConfigRoutes registers configuration routes on a separate group

func (*Handler) RegisterIDERoutes

func (h *Handler) RegisterIDERoutes(g *echo.Group)

RegisterIDERoutes registers IDE discovery routes on a separate group

func (*Handler) RegisterModelRoutes

func (h *Handler) RegisterModelRoutes(g *echo.Group)

RegisterModelRoutes registers model routes on a separate group

func (*Handler) RegisterOAuthCallbackRoute

func (h *Handler) RegisterOAuthCallbackRoute(e *echo.Echo, configs map[string]*oauth.ProviderConfig)

RegisterOAuthCallbackRoute registers OAuth callback routes for all provider types. Each provider may have a different callback path (e.g., /oauth-callback, /oauth2callback).

func (*Handler) RegisterPricingRoutes

func (h *Handler) RegisterPricingRoutes(g *echo.Group)

RegisterPricingRoutes registers pricing management routes on a separate group

func (*Handler) RegisterRoutes

func (h *Handler) RegisterRoutes(g *echo.Group)

RegisterRoutes registers all API routes on an Echo group

func (*Handler) RemoveAPIKey

func (h *Handler) RemoveAPIKey(c echo.Context) error

RemoveAPIKey removes an API key from a provider

func (*Handler) RemoveModelPricing

func (h *Handler) RemoveModelPricing(c echo.Context) error

RemoveModelPricing removes custom pricing for a model (reverts to default)

func (*Handler) ScanIDEs

func (h *Handler) ScanIDEs(c echo.Context) error

ScanIDEs scans for available IDEs and returns all results (including not found)

func (*Handler) ScanOAuthTokens

func (h *Handler) ScanOAuthTokens(c echo.Context) error

ScanOAuthTokens scans all supported IDEs for OAuth tokens.

func (*Handler) SetDefaultPricing

func (h *Handler) SetDefaultPricing(c echo.Context) error

SetDefaultPricing updates the default pricing for unknown models

func (*Handler) SetMediaPricingLookup

func (h *Handler) SetMediaPricingLookup(fn MediaPricingLookup)

SetMediaPricingLookup sets the callback for looking up media model pricing.

func (*Handler) SetModelPricing

func (h *Handler) SetModelPricing(c echo.Context) error

SetModelPricing sets custom pricing for a specific model

func (*Handler) SetOAuthManager

func (h *Handler) SetOAuthManager(m oauth.RuntimeManager)

SetOAuthManager sets the OAuth manager for the handler.

func (*Handler) SetRoutingMode

func (h *Handler) SetRoutingMode(c echo.Context) error

SetRoutingMode sets the routing mode

func (*Handler) StartOAuth

func (h *Handler) StartOAuth(c echo.Context) error

StartOAuth starts an OAuth flow for a provider.

func (*Handler) UpdateAllowedModels

func (h *Handler) UpdateAllowedModels(c echo.Context) error

UpdateAllowedModels updates the allowed models for a provider

func (*Handler) UpdateModelParams

func (h *Handler) UpdateModelParams(c echo.Context) error

UpdateModelParams updates model parameters for a provider

func (*Handler) UpdateProvider

func (h *Handler) UpdateProvider(c echo.Context) error

UpdateProvider updates a provider

func (*Handler) UpdateProviderIcon

func (h *Handler) UpdateProviderIcon(c echo.Context) error

UpdateProviderIcon updates the custom icon for a provider

func (*Handler) VerifyProvider

func (h *Handler) VerifyProvider(c echo.Context) error

VerifyProvider verifies a provider candidate and returns recommended API format/base URL.

func (*Handler) VerifyProviderByID

func (h *Handler) VerifyProviderByID(c echo.Context) error

VerifyProviderByID verifies an existing provider and can optionally apply recommendations.

type IDEProvider

type IDEProvider struct {
	IDEName      string    `json:"ide_name"` // e.g., "antigravity", "cursor"
	IDEVersion   string    `json:"ide_version,omitempty"`
	ProxyURL     string    `json:"proxy_url"`   // Local proxy endpoint
	ConfigPath   string    `json:"config_path"` // Path to IDE config
	Connected    bool      `json:"connected"`
	Models       []string  `json:"models,omitempty"`
	DiscoveredAt time.Time `json:"discovered_at"`
}

IDEProvider represents a provider discovered from a local IDE

type LegacyProviderConfig

type LegacyProviderConfig struct {
	Name    string `json:"name"`
	APIKey  string `json:"api_key,omitempty"`
	BaseURL string `json:"base_url,omitempty"`
	Enabled bool   `json:"enabled"`
}

LegacyProviderConfig represents the old provider configuration format

type LegacyProvidersConfig

type LegacyProvidersConfig struct {
	Providers map[string]LegacyProviderConfig `json:"providers"`
}

LegacyProvidersConfig represents the old providers configuration file

type LicenseClaims

type LicenseClaims struct {
	KID       string `json:"kid"`   // key ID
	Key       string `json:"key"`   // trial API key (plaintext in signed payload)
	URL       string `json:"url"`   // trial base URL
	Limit     int64  `json:"lim"`   // token limit
	IssuedAt  int64  `json:"iat"`   // issued-at unix timestamp
	ExpiresAt int64  `json:"exp"`   // expiry unix timestamp (0=no expiry)
	Format    string `json:"fmt"`   // API format (e.g. "anthropic")
	Model     string `json:"model"` // default model ID
}

LicenseClaims contains the verified claims from a trial license.

func VerifyLicense

func VerifyLicense(licenseStr string) (*LicenseClaims, []byte, error)

VerifyLicense verifies an Ed25519-signed license string and returns the claims. License format: base64url(json) + "." + base64url(signature)

type MediaPricingApplier

type MediaPricingApplier func(modelID string, outputPrice float64, unit string)

MediaPricingApplier is a callback for applying media model pricing updates. The callback receives (modelID, outputPrice, unit) for each media model.

type MediaPricingInfo

type MediaPricingInfo struct {
	Price float64 // USD per unit
	Unit  string  // "image", "second", "video"
}

Handler provides HTTP handlers for the provider pool API MediaPricingInfo holds per-unit pricing for a media model.

type MediaPricingLookup

type MediaPricingLookup func(modelID string) *MediaPricingInfo

MediaPricingLookup returns pricing for a media model by ID, or nil if unknown.

type MigrationResult

type MigrationResult struct {
	Migrated      int      `json:"migrated"`
	Skipped       int      `json:"skipped"`
	Errors        []string `json:"errors,omitempty"`
	MigratedNames []string `json:"migrated_names,omitempty"`
	SkippedNames  []string `json:"skipped_names,omitempty"`
	BackupPath    string   `json:"backup_path,omitempty"`
}

MigrationResult contains the result of a migration operation

func MigrateFromLegacy

func MigrateFromLegacy(dataDir string, pool *Pool) (*MigrationResult, error)

MigrateFromLegacy migrates provider settings from the old format to the new Provider Pool format

type Model

type Model struct {
	ID          string `json:"id"`
	ProviderID  string `json:"provider_id"`
	Name        string `json:"name"`
	DisplayName string `json:"display_name"`
	Enabled     bool   `json:"enabled"`

	// Capabilities
	Capabilities ModelCapabilities `json:"capabilities"`

	// Pricing (per 1M tokens, in USD)
	InputPrice  float64 `json:"input_price,omitempty"`
	OutputPrice float64 `json:"output_price,omitempty"`
	CachePrice  float64 `json:"cache_price,omitempty"` // Cache read price

	// Per-request pricing (USD) — for media generation models (image/video/audio)
	PricePerRequest float64 `json:"price_per_request,omitempty"`

	// Limits
	ContextWindow int `json:"context_window,omitempty"`
	MaxOutput     int `json:"max_output,omitempty"`

	// Metadata
	Description     string    `json:"description,omitempty"`
	Deprecated      bool      `json:"deprecated,omitempty"`
	PinchBenchScore *float64  `json:"pinchbench_score,omitempty"`
	PinchBenchURL   string    `json:"pinchbench_url,omitempty"`
	CreatedAt       time.Time `json:"created_at,omitempty"`
	UpdatedAt       time.Time `json:"updated_at,omitempty"`
}

Model represents an available model from a provider

func GetBuiltinModels

func GetBuiltinModels(providerID string) []*Model

GetBuiltinModels returns built-in models for a provider

type ModelCapabilities

type ModelCapabilities struct {
	Chat            bool `json:"chat"`
	Completion      bool `json:"completion"`
	Vision          bool `json:"vision"`
	FunctionCall    bool `json:"function_call"`
	Streaming       bool `json:"streaming"`
	Thinking        bool `json:"thinking"`         // Extended thinking mode (Claude)
	JSON            bool `json:"json"`             // JSON mode support
	SystemPrompt    bool `json:"system_prompt"`    // System prompt support
	ImageGeneration bool `json:"image_generation"` // Image generation (text-to-image)
	VideoGeneration bool `json:"video_generation"` // Video generation (text-to-video)
	AudioGeneration bool `json:"audio_generation"` // Audio generation (TTS, music)
}

ModelCapabilities describes what a model can do

type ModelDiscovery

type ModelDiscovery struct {
	// contains filtered or unexported fields
}

ModelDiscovery handles model discovery and caching

func NewModelDiscovery

func NewModelDiscovery(registry *Registry, storage Storage, cacheTTL time.Duration) *ModelDiscovery

NewModelDiscovery creates a new ModelDiscovery

func (*ModelDiscovery) FetchModels

func (d *ModelDiscovery) FetchModels(ctx context.Context, providerID string) ([]*Model, error)

FetchModels fetches models from a provider

func (*ModelDiscovery) FindModel

func (d *ModelDiscovery) FindModel(modelID string) (*Model, *Provider, error)

FindModel searches for a model across all providers

func (*ModelDiscovery) FindModelsByCapability

func (d *ModelDiscovery) FindModelsByCapability(cap ModelCapabilities) []*Model

FindModelsByCapability finds models with specific capabilities

func (*ModelDiscovery) GetAllModels

func (d *ModelDiscovery) GetAllModels() []*Model

GetAllModels returns all models from all providers (including built-in models from disabled providers)

func (*ModelDiscovery) GetFilteredModels

func (d *ModelDiscovery) GetFilteredModels(providerID string) ([]*Model, error)

GetFilteredModels returns models for a provider, filtered by AllowedModels if set

func (*ModelDiscovery) GetModel

func (d *ModelDiscovery) GetModel(providerID, modelID string) (*Model, error)

GetModel returns a specific model by ID

func (*ModelDiscovery) GetModels

func (d *ModelDiscovery) GetModels(providerID string) ([]*Model, error)

GetModels returns cached models for a provider

func (*ModelDiscovery) ProbeModels

func (d *ModelDiscovery) ProbeModels(ctx context.Context, providerID string, concurrency int) ([]ProbeResult, error)

ProbeModels sends a minimal chat completion request to each model in parallel to determine which ones are actually configured and usable. Models that return a "not configured" error (HTTP 400/404 with model-not-found patterns) are marked as Enabled=false. Returns the probe results for all models.

concurrency controls how many probes run in parallel (0 = len(models)).

func (*ModelDiscovery) RefreshAll

func (d *ModelDiscovery) RefreshAll(ctx context.Context) error

RefreshAll refreshes models for all enabled providers

func (*ModelDiscovery) SetModelsChangedHook

func (d *ModelDiscovery) SetModelsChangedHook(hook func(providerID string))

SetModelsChangedHook registers a callback that runs after fresh model data is written into discovery cache/storage. Callers typically use this to rebuild router snapshots so empty-model routing doesn't keep serving stale candidates.

func (*ModelDiscovery) SetOAuthManager

func (d *ModelDiscovery) SetOAuthManager(m interface {
	GetCopilotAccessToken(providerID string) (string, error)
	GetCopilotEndpoint() string
})

SetOAuthManager sets the OAuth manager for Copilot token exchange

type ModelError

type ModelError struct {
	ProviderID string
	ModelID    string
	Operation  string
	Err        error
}

ModelError wraps an error with model context

func NewModelError

func NewModelError(providerID, modelID, operation string, err error) *ModelError

NewModelError creates a new ModelError

func (*ModelError) Error

func (e *ModelError) Error() string

func (*ModelError) Unwrap

func (e *ModelError) Unwrap() error

type ModelFamily

type ModelFamily struct {
	Name        string                   // Family name (e.g., "claude", "gpt")
	Keywords    []string                 // Keywords to match (e.g., ["claude", "anthropic"])
	DefaultTier string                   // Default tier when no tier matches (e.g., "sonnet", "4o")
	Tiers       map[string]*ModelPricing // Tier name -> pricing
}

ModelFamily represents a family of models with similar pricing tiers

type ModelParams

type ModelParams struct {
	Temperature      *float64 `json:"temperature,omitempty"`       // 0.0 - 2.0, nil means use model default
	MaxTokens        *int     `json:"max_tokens,omitempty"`        // Max output tokens, nil means use model default
	TopP             *float64 `json:"top_p,omitempty"`             // 0.0 - 1.0
	FrequencyPenalty *float64 `json:"frequency_penalty,omitempty"` // -2.0 - 2.0
	PresencePenalty  *float64 `json:"presence_penalty,omitempty"`  // -2.0 - 2.0

	// Server-detected output limit fallback (read-only, dynamic providers only)
	DetectedMaxTokens *int   `json:"detected_max_tokens,omitempty"` // Detected or inferred max output tokens
	DetectedAt        *int64 `json:"detected_at,omitempty"`         // Unix timestamp of last detection
}

ModelParams represents default model parameters for a provider

type ModelPricing

type ModelPricing struct {
	ModelID     string    `json:"model_id"`              // Model identifier (can be pattern like "gpt-*")
	ProviderID  string    `json:"provider_id,omitempty"` // Optional: specific provider
	InputPrice  float64   `json:"input_price"`           // Price per 1M input tokens (USD)
	OutputPrice float64   `json:"output_price"`          // Price per 1M output tokens (USD)
	CachePrice  float64   `json:"cache_price,omitempty"` // Price per 1M cache read tokens (USD)
	IsCustom    bool      `json:"is_custom"`             // True if user-defined, false if default
	UpdatedAt   time.Time `json:"updated_at"`
}

ModelPricing represents custom pricing configuration for a model

func MatchModelPricing

func MatchModelPricing(modelID string) *ModelPricing

MatchModelPricing attempts to match a model ID to known pricing using heuristics Returns nil if no match found

type OAuthAccount

type OAuthAccount struct {
	ID           string    `json:"id"`
	ProviderType string    `json:"provider_type"`
	Email        string    `json:"email,omitempty"`
	ProjectID    string    `json:"project_id,omitempty"`
	Endpoint     string    `json:"endpoint,omitempty"`
	TokenExpiry  time.Time `json:"token_expiry,omitempty"`
	Connected    bool      `json:"connected"`
}

OAuthAccount represents a single connected OAuth account (returned in API responses).

type OAuthConfig

type OAuthConfig struct {
	ClientID     string    `json:"client_id"`
	ClientSecret string    `json:"-"` // Never expose
	AccessToken  string    `json:"-"` // Never expose
	RefreshToken string    `json:"-"` // Never expose
	TokenExpiry  time.Time `json:"token_expiry,omitempty"`
	Scopes       []string  `json:"scopes,omitempty"`

	// OAuth provider metadata
	ProviderType string `json:"provider_type,omitempty"` // "antigravity", "gemini-cli", "copilot"
	ProjectID    string `json:"project_id,omitempty"`    // Google Cloud Code project ID
	Email        string `json:"email,omitempty"`         // Authenticated user email
	Endpoint     string `json:"endpoint,omitempty"`      // API endpoint URL (e.g., cloudcode-pa.googleapis.com)
	Connected    bool   `json:"connected"`               // Whether OAuth is currently connected (legacy: true if any account connected)

	// Multi-account: number of connected OAuth accounts (populated at runtime from oauth_tokens table)
	AccountCount int `json:"account_count,omitempty"`
}

OAuthConfig represents OAuth template configuration for providers that support it. The actual connected accounts (tokens) are stored in the oauth_tokens table. This struct on Provider holds the template (provider_type, scopes, endpoint, etc.).

type Pool

type Pool struct {
	Registry          *Registry
	Discovery         *ModelDiscovery
	Router            *Router
	IDEDiscovery      *ide.Discovery
	UsageTracker      *UsageTracker
	PricingManager    *PricingManager
	Storage           Storage
	Config            *PoolConfig
	TrialQuotaManager *TrialQuotaManager
	// contains filtered or unexported fields
}

Pool is the main entry point for the provider pool functionality

func NewPool

func NewPool(dataPath string, opts ...PoolOption) (*Pool, error)

NewPool creates a new Pool with all components

func (*Pool) IsReady

func (p *Pool) IsReady() bool

IsReady returns true if the initial model refresh has completed.

func (*Pool) SetMediaPricingApplier

func (p *Pool) SetMediaPricingApplier(applier MediaPricingApplier)

SetMediaPricingApplier wires a callback for applying media model pricing from remote updates.

func (*Pool) Start

func (p *Pool) Start(ctx context.Context)

Start starts background services

func (*Pool) Stop

func (p *Pool) Stop()

Stop stops background services

func (*Pool) WaitReady

func (p *Pool) WaitReady(timeout time.Duration) bool

WaitReady blocks until the initial model refresh completes or the timeout expires. Returns true if the pool is ready, false on timeout.

type PoolConfig

type PoolConfig struct {
	// Routing
	DefaultStrategy    RoutingStrategy `json:"default_strategy"`
	DefaultRoutingMode RoutingMode     `json:"default_routing_mode"` // auto, cloud, local

	// IDE discovery
	IDEDiscoveryEnabled      bool          `json:"ide_discovery_enabled"`
	IDEDiscoveryScanInterval time.Duration `json:"ide_discovery_scan_interval"`

	// Usage tracking
	UsageTrackingEnabled bool `json:"usage_tracking_enabled"`
	UsageRetentionDays   int  `json:"usage_retention_days"`

	// Encryption
	EncryptionKey string `json:"-"` // Never expose
}

PoolConfig represents the provider pool configuration

type PoolOption

type PoolOption func(*poolInitOpts)

PoolOption configures the Pool

func WithConfig

func WithConfig(config *PoolConfig) PoolOption

WithConfig sets the pool configuration

func WithDB

func WithDB(db *sql.DB) PoolOption

WithDB uses SQLite-backed storage instead of JSON files. When set, dataPath is only used for migration from legacy JSON files.

func WithReadDB

func WithReadDB(readDB *sql.DB) PoolOption

WithReadDB provides a dedicated read-only SQLite handle for provider pool storage reads when WithDB is also configured.

func WithSecretEncryptor

func WithSecretEncryptor(enc SecretEncryptor) PoolOption

WithSecretEncryptor enables at-rest encryption for persisted provider secrets.

type PricingConfig

type PricingConfig struct {
	// Default price for unknown models (per 1M tokens)
	DefaultInputPrice  float64 `json:"default_input_price"`
	DefaultOutputPrice float64 `json:"default_output_price"`
	DefaultCachePrice  float64 `json:"default_cache_price"`

	// Custom pricing overrides (model_id -> pricing)
	CustomPricing map[string]*ModelPricing `json:"custom_pricing"`

	// Last update timestamp
	UpdatedAt time.Time `json:"updated_at"`
}

PricingConfig holds all pricing configurations

func DefaultPricingConfig

func DefaultPricingConfig() *PricingConfig

DefaultPricingConfig returns the default pricing configuration

func GetBuiltinPricingConfig

func GetBuiltinPricingConfig() *PricingConfig

GetBuiltinPricingConfig returns pricing configuration from built-in models

type PricingManager

type PricingManager struct {
	// contains filtered or unexported fields
}

PricingManager manages model pricing configuration

func NewPricingManager

func NewPricingManager(storage Storage) (*PricingManager, error)

NewPricingManager creates a new pricing manager

func (*PricingManager) CalculateCost

func (pm *PricingManager) CalculateCost(modelID, providerID string, inputTokens, outputTokens, cacheTokens int64) float64

CalculateCost calculates the cost for a usage record using current pricing

func (*PricingManager) GetModelPricing

func (pm *PricingManager) GetModelPricing(modelID, providerID string) *ModelPricing

GetModelPricing returns the pricing for a specific model It checks in order: provider-specific pricing, model pricing, heuristic match, default pricing

func (*PricingManager) GetModelPricingWithHeuristics

func (pm *PricingManager) GetModelPricingWithHeuristics(modelID, providerID string) *ModelPricing

GetModelPricingWithHeuristics returns pricing for a model, using heuristic matching if no exact match is found. This is the enhanced version of GetModelPricing.

func (*PricingManager) GetPricingConfig

func (pm *PricingManager) GetPricingConfig() *PricingConfig

GetPricingConfig returns the current pricing configuration

func (*PricingManager) ListCustomPricing

func (pm *PricingManager) ListCustomPricing() []*ModelPricing

ListCustomPricing returns all custom pricing configurations

func (*PricingManager) RemoveModelPricing

func (pm *PricingManager) RemoveModelPricing(modelID, providerID string) error

RemoveModelPricing removes custom pricing for a model (reverts to default)

func (*PricingManager) SetDefaultPricing

func (pm *PricingManager) SetDefaultPricing(inputPrice, outputPrice, cachePrice float64) error

SetDefaultPricing updates the default pricing for unknown models

func (*PricingManager) SetModelPricing

func (pm *PricingManager) SetModelPricing(pricing *ModelPricing) error

SetModelPricing sets custom pricing for a specific model

func (*PricingManager) SetPricingChangeCallback

func (pm *PricingManager) SetPricingChangeCallback(cb func())

SetPricingChangeCallback sets a callback for pricing changes

type PricingUpdater

type PricingUpdater struct {
	// contains filtered or unexported fields
}

PricingUpdater periodically fetches remote pricing and merges into BuiltinModelPricing. Uses HTTP ETag to avoid re-parsing unchanged content.

func NewPricingUpdater

func NewPricingUpdater(logger *zap.Logger) *PricingUpdater

NewPricingUpdater creates a new updater. Call Start() to begin background polling.

func (*PricingUpdater) SetMediaPricingApplier

func (u *PricingUpdater) SetMediaPricingApplier(applier MediaPricingApplier)

SetMediaPricingApplier sets the callback for applying media model pricing.

func (*PricingUpdater) Start

func (u *PricingUpdater) Start()

Start begins background polling. Non-blocking.

func (*PricingUpdater) Stop

func (u *PricingUpdater) Stop()

Stop stops the background polling.

type ProbeResult

type ProbeResult struct {
	ModelID    string        `json:"model_id"`
	Available  bool          `json:"available"`
	StatusCode int           `json:"status_code"`
	Error      string        `json:"error,omitempty"`
	Latency    time.Duration `json:"latency"`
}

ProbeResult holds the result of probing a single model.

type Provider

type Provider struct {
	ID            string           `json:"id"`
	Name          string           `json:"name"`
	Type          ProviderType     `json:"type"`
	Location      ProviderLocation `json:"location"` // cloud or local
	Enabled       bool             `json:"enabled"`
	Status        ProviderStatus   `json:"status"`
	BaseURL       string           `json:"base_url,omitempty"`
	APIVersion    string           `json:"api_version,omitempty"`     // e.g., "v1", "2024-01"
	APIFormat     APIFormat        `json:"api_format,omitempty"`      // openai, anthropic, ollama, google (auto-detected if empty)
	APIFormatMode APIFormatMode    `json:"api_format_mode,omitempty"` // auto or pinned
	SkipTLSVerify bool             `json:"skip_tls_verify,omitempty"` // skip TLS certificate verification for self-signed certs

	// Authentication
	APIKeys []APIKey     `json:"api_keys,omitempty"`
	OAuth   *OAuthConfig `json:"oauth,omitempty"`

	// Configuration
	Priority  int               `json:"priority"` // Higher = preferred
	RateLimit *RateLimitConfig  `json:"rate_limit,omitempty"`
	Headers   map[string]string `json:"headers,omitempty"` // Custom headers

	// Model Parameters (defaults for this provider)
	ModelParams *ModelParams `json:"model_params,omitempty"`

	// Allowed Models holds the normalized model allowlist.
	// Nil/empty means no allowlist is configured.
	AllowedModels []string `json:"allowed_models,omitempty"`
	// AllowlistConfigured tracks whether a non-empty model allowlist is enabled.
	AllowlistConfigured bool `json:"allowlist_configured,omitempty"`

	// Metadata
	Icon         string               `json:"icon,omitempty"`        // Built-in icon name (e.g., "openai", "anthropic")
	CustomIcon   string               `json:"custom_icon,omitempty"` // Custom icon: base64 data URL or relative file path
	Description  string               `json:"description,omitempty"`
	Website      string               `json:"website,omitempty"`     // Official website URL for the provider
	APIKeyURL    string               `json:"api_key_url,omitempty"` // URL to obtain/manage API keys
	MetadataMode ProviderMetadataMode `json:"metadata_mode,omitempty"`
	Beta         bool                 `json:"beta,omitempty"` // Beta providers are shown in "Other" with a beta badge
	CreatedAt    time.Time            `json:"created_at"`
	UpdatedAt    time.Time            `json:"updated_at"`

	// Detected capabilities (persisted across restarts)
	DetectedFormat    APIFormat          `json:"detected_format,omitempty"`    // Probed API format that works (persisted)
	DetectedAt        time.Time          `json:"detected_at,omitempty"`        // When format was last probed
	CapabilityProfile *CapabilityProfile `json:"capability_profile,omitempty"` // Derived routing/runtime capability surface

	// AlternateBaseURLs is a list of alternate base URLs to try when auth fails on the primary BaseURL.
	// The system will probe these in order when the primary endpoint returns 401/403.
	// When an alternate URL succeeds, it's persisted as the new BaseURL via DetectedEndpoint.
	AlternateBaseURLs []string `json:"alternate_base_urls,omitempty"`

	// DetectedEndpoint remembers which endpoint worked (full base URL without path).
	// This is persisted and survives restarts. When set, it overrides BaseURL.
	DetectedEndpoint string `json:"detected_endpoint,omitempty"`

	// Runtime error state
	LastError     string    `json:"last_error,omitempty"`
	LastErrorTime time.Time `json:"last_error_time,omitempty"`
	// contains filtered or unexported fields
}

Provider represents an LLM provider configuration

func BuiltinProviders

func BuiltinProviders() []*Provider

BuiltinModels returns effective built-in models with remote catalog overrides applied.

func BuiltinProvidersSnapshot

func BuiltinProvidersSnapshot() []*Provider

BuiltinProviders returns the effective built-in provider list with remote catalog overrides applied.

func GetBuiltinProvider

func GetBuiltinProvider(id string) *Provider

GetBuiltinProvider returns a built-in provider by ID

func (*Provider) EffectiveBaseURL

func (p *Provider) EffectiveBaseURL() string

EffectiveBaseURL returns the effective base URL to use, considering DetectedEndpoint. If DetectedEndpoint is set, it takes precedence over BaseURL.

func (*Provider) ParsedBaseURL

func (p *Provider) ParsedBaseURL() *url.URL

ParsedBaseURL returns the cached parsed URL for this provider. Thread-safe, parsed once on first call. Returns nil if BaseURL is invalid. Use EffectiveBaseURL() for the actual URL to use (considers DetectedEndpoint).

func (*Provider) ParsedEffectiveBaseURL

func (p *Provider) ParsedEffectiveBaseURL() *url.URL

ParsedEffectiveBaseURL returns the cached parsed effective base URL. Thread-safe, parsed once on first call.

func (*Provider) ResetParsedURL

func (p *Provider) ResetParsedURL()

ResetParsedURL invalidates the cached parsed URL so it will be re-parsed on next access. Call this after changing BaseURL or DetectedEndpoint.

type ProviderAccountStatus

type ProviderAccountStatus struct {
	ProviderID     string                      `json:"provider_id"`
	KeyID          string                      `json:"key_id,omitempty"`
	KeyHash        string                      `json:"key_hash,omitempty"`
	Kind           ProviderAccountStatusKind   `json:"kind"`
	PrimaryItemKey string                      `json:"primary_item_key,omitempty"`
	Items          []ProviderAccountStatusItem `json:"items,omitempty"`
	Error          string                      `json:"error,omitempty"`
	FetchedAt      int64                       `json:"fetched_at"`
}

func FetchProviderAccountStatus

func FetchProviderAccountStatus(ctx context.Context, provider *Provider, keyID string) *ProviderAccountStatus

type ProviderAccountStatusItem

type ProviderAccountStatusItem struct {
	Key      string  `json:"key"`
	Value    float64 `json:"value"`
	Currency string  `json:"currency,omitempty"`
}

type ProviderAccountStatusKind

type ProviderAccountStatusKind string
const (
	ProviderAccountStatusKindBalance     ProviderAccountStatusKind = "balance"
	ProviderAccountStatusKindCredits     ProviderAccountStatusKind = "credits"
	ProviderAccountStatusKindUnsupported ProviderAccountStatusKind = "unsupported"
)

type ProviderCatalogStatus

type ProviderCatalogStatus struct {
	ETag          string    `json:"etag,omitempty"`
	LastUpdatedAt time.Time `json:"last_updated_at,omitempty"`
	SourceURL     string    `json:"source_url"`
	FallbackInUse bool      `json:"fallback_in_use"`
}

type ProviderCatalogUpdater

type ProviderCatalogUpdater struct {
	// contains filtered or unexported fields
}

func NewProviderCatalogUpdater

func NewProviderCatalogUpdater(logger *zap.Logger) *ProviderCatalogUpdater

func (*ProviderCatalogUpdater) LoadEmbeddedCatalog

func (u *ProviderCatalogUpdater) LoadEmbeddedCatalog() error

LoadEmbeddedCatalog loads the embedded catalog from local file as fallback. This should be called before Start() to ensure data is available even if remote fetch fails.

func (*ProviderCatalogUpdater) SetApplyCallback

func (u *ProviderCatalogUpdater) SetApplyCallback(callback func())

func (*ProviderCatalogUpdater) Start

func (u *ProviderCatalogUpdater) Start()

func (*ProviderCatalogUpdater) Status

func (*ProviderCatalogUpdater) Stop

func (u *ProviderCatalogUpdater) Stop()

type ProviderError

type ProviderError struct {
	ProviderID string
	Operation  string
	Err        error
}

ProviderError wraps an error with provider context

func NewProviderError

func NewProviderError(providerID, operation string, err error) *ProviderError

NewProviderError creates a new ProviderError

func (*ProviderError) Error

func (e *ProviderError) Error() string

func (*ProviderError) Unwrap

func (e *ProviderError) Unwrap() error

type ProviderLocation

type ProviderLocation string

ProviderLocation represents where the provider runs

const (
	// ProviderLocationCloud represents cloud-based providers (OpenAI, Anthropic, etc.)
	ProviderLocationCloud ProviderLocation = "cloud"
	// ProviderLocationLocal represents locally running providers (Ollama, LM Studio, etc.)
	ProviderLocationLocal ProviderLocation = "local"
)

type ProviderMetadataMode

type ProviderMetadataMode string

ProviderMetadataMode controls how provider/model metadata is sourced.

const (
	// ProviderMetadataModeCatalog means provider/model metadata comes from the official catalog.
	ProviderMetadataModeCatalog ProviderMetadataMode = "catalog"
	// ProviderMetadataModeDynamic means provider/model metadata is discovered dynamically.
	ProviderMetadataModeDynamic ProviderMetadataMode = "dynamic"
)

func EffectiveProviderMetadataMode

func EffectiveProviderMetadataMode(provider *Provider) ProviderMetadataMode

type ProviderStatus

type ProviderStatus string

ProviderStatus represents the current status of a provider

const (
	// ProviderStatusActive indicates the provider is healthy and available
	ProviderStatusActive ProviderStatus = "active"
	// ProviderStatusInactive indicates the provider is disabled
	ProviderStatusInactive ProviderStatus = "inactive"
	// ProviderStatusError indicates the provider recently encountered request/runtime issues
	ProviderStatusError ProviderStatus = "error"
)

type ProviderType

type ProviderType string

ProviderType represents the type of provider

const (
	// ProviderTypeBuiltin represents built-in providers (OpenAI, Anthropic, etc.)
	ProviderTypeBuiltin ProviderType = "builtin"
	// ProviderTypePlatform represents platform/aggregator providers (OpenRouter, SiliconFlow, etc.)
	ProviderTypePlatform ProviderType = "platform"
	// ProviderTypeCustom represents user-defined OpenAI-compatible providers
	ProviderTypeCustom ProviderType = "custom"
	// ProviderTypeACP represents ACP (Agent Communication Protocol) providers
	ProviderTypeACP ProviderType = "acp"
	// ProviderTypeIDE represents providers discovered from local IDE tools
	ProviderTypeIDE ProviderType = "ide"
	// ProviderTypeTrial represents trial providers with limited quota
	ProviderTypeTrial ProviderType = "trial"
	// ProviderTypeMedia represents media generation providers (image/video)
	ProviderTypeMedia ProviderType = "media"
)

type RateLimitConfig

type RateLimitConfig struct {
	RequestsPerMinute int `json:"requests_per_minute,omitempty"`
	TokensPerMinute   int `json:"tokens_per_minute,omitempty"`
	TokensPerDay      int `json:"tokens_per_day,omitempty"`
}

RateLimitConfig represents rate limiting configuration

type Registry

type Registry struct {
	// contains filtered or unexported fields
}

Registry manages provider registration and lifecycle

func NewRegistry

func NewRegistry(storage Storage, opts ...RegistryOption) (*Registry, error)

NewRegistry creates a new Registry

func (*Registry) AddAPIKey

func (r *Registry) AddAPIKey(providerID string, key *APIKey) error

AddAPIKey adds an API key to a provider

func (*Registry) AddProviderChangeListener

func (r *Registry) AddProviderChangeListener(cb func(provider *Provider, action string))

AddProviderChangeListener chains an additional callback onto the existing onProviderChange handler. The new listener fires after the original callback.

func (*Registry) ClearError

func (r *Registry) ClearError(id string) error

ClearError clears the error status of a provider, allowing manual retry

func (*Registry) Disable

func (r *Registry) Disable(id string) error

Disable disables a provider

func (*Registry) Enable

func (r *Registry) Enable(id string) error

Enable enables a provider

func (*Registry) Get

func (r *Registry) Get(id string) (*Provider, error)

Get returns a provider by ID

func (*Registry) GetAPIKey

func (r *Registry) GetAPIKey(providerID string) (*APIKey, error)

GetAPIKey returns an API key for a provider

func (*Registry) GetOAuthConfig

func (r *Registry) GetOAuthConfig(providerID string) (*OAuthConfig, error)

GetOAuthConfig returns the OAuth configuration for a provider, if connected.

func (*Registry) List

func (r *Registry) List() []*Provider

List returns all registered providers

func (*Registry) ListEnabled

func (r *Registry) ListEnabled() []*Provider

ListEnabled returns all enabled providers

func (*Registry) ListHealthy

func (r *Registry) ListHealthy() []*Provider

ListHealthy returns all healthy providers

func (*Registry) Register

func (r *Registry) Register(provider *Provider) error

Register adds a new provider to the registry

func (*Registry) RemoveAPIKey

func (r *Registry) RemoveAPIKey(providerID, keyID string) error

RemoveAPIKey removes an API key from a provider

func (*Registry) SetOnStatusChange

func (r *Registry) SetOnStatusChange(cb func(providerID string, oldStatus, newStatus ProviderStatus))

SetOnStatusChange sets a callback invoked when a provider's status transitions (e.g. active → error or error → active).

func (*Registry) Unregister

func (r *Registry) Unregister(id string) error

Unregister removes a provider from the registry

func (*Registry) Update

func (r *Registry) Update(provider *Provider) error

Update updates a provider's configuration

func (*Registry) UpdateStatus

func (r *Registry) UpdateStatus(id string, status ProviderStatus, lastError string) error

UpdateStatus updates a provider's status

type RegistryOption

type RegistryOption func(*Registry)

RegistryOption configures the Registry

func WithProviderChangeCallback

func WithProviderChangeCallback(cb func(provider *Provider, action string)) RegistryOption

WithProviderChangeCallback sets a callback for provider changes

type RouteCandidate

type RouteCandidate struct {
	Provider *Provider `json:"provider"`
	Model    *Model    `json:"model"`
	Score    float64   `json:"score"` // Routing score (higher = better)
}

RouteCandidate represents a potential routing target

type RouteRequest

type RouteRequest struct {
	ModelID             string             `json:"model_id"`
	Strategy            RoutingStrategy    `json:"strategy,omitempty"`
	Mode                RoutingMode        `json:"mode,omitempty"`                  // Location preference: auto, cloud, local
	Exclude             []string           `json:"exclude,omitempty"`               // Provider IDs to exclude
	RequireCap          *ModelCapabilities `json:"require_cap,omitempty"`           // Required capabilities
	PreferredProviderID string             `json:"preferred_provider_id,omitempty"` // Sticky routing: try this provider first (tool rounds)
}

RouteRequest represents a routing request

type RouteResult

type RouteResult struct {
	Provider  *Provider         `json:"provider"`
	Model     *Model            `json:"model"`
	APIKey    *APIKey           `json:"api_key,omitempty"`
	OAuth     *OAuthConfig      `json:"oauth,omitempty"`
	Fallbacks []*RouteCandidate `json:"fallbacks,omitempty"`
}

RouteResult represents the routing decision

type Router

type Router struct {
	// contains filtered or unexported fields
}

Router handles intelligent model routing and provider selection

func NewRouter

func NewRouter(registry *Registry, discovery *ModelDiscovery, defaultStrategy RoutingStrategy) *Router

NewRouter creates a new Router

func (*Router) ClearCooldown

func (r *Router) ClearCooldown(providerID string)

ClearCooldown manually clears cooldown for a provider

func (*Router) FindBestProvider

func (r *Router) FindBestProvider(modelID string) (*Provider, *Model, error)

FindBestProvider finds the best provider for a model without executing

func (*Router) GetCooldownEntry

func (r *Router) GetCooldownEntry(providerID string) *CooldownEntry

GetCooldownEntry returns the cooldown entry for a provider

func (*Router) GetLatency

func (r *Router) GetLatency(providerID string) time.Duration

GetLatency returns the current latency for a provider

func (*Router) GetProviderForModel

func (r *Router) GetProviderForModel(modelID string, strategy RoutingStrategy) (*Provider, error)

GetProviderForModel returns the provider that would be selected for a model

func (*Router) HasModel

func (r *Router) HasModel(modelID string) bool

HasModel returns true if any provider in the snapshot can serve the given model. This is a fast, lock-free check used by routing rules to verify a target model is actually available before committing to a model swap.

func (*Router) IsInCooldown

func (r *Router) IsInCooldown(providerID string) bool

IsInCooldown checks if a provider is currently in cooldown

func (*Router) ListAvailableModels

func (r *Router) ListAvailableModels() []*Model

ListAvailableModels returns all models that can be routed

func (*Router) ListCooldowns

func (r *Router) ListCooldowns() []*CooldownEntry

ListCooldowns returns all providers currently in cooldown

func (*Router) RebuildCandidates

func (r *Router) RebuildCandidates()

RebuildCandidates rebuilds the static candidate snapshot from current provider/model state. Call this when providers are added/removed/updated or models change. The snapshot is swapped atomically — zero contention on the read path.

func (*Router) RecordFailure

func (r *Router) RecordFailure(providerID string, err error)

RecordFailure records a failure for a provider and potentially puts it in cooldown

func (*Router) RecordSuccess

func (r *Router) RecordSuccess(providerID string)

RecordSuccess records a successful request and potentially resets cooldown

func (*Router) Route

func (r *Router) Route(req *RouteRequest) (*RouteResult, error)

Route selects the best provider for a model request. Uses the precomputed candidate snapshot for O(1) lookup, falls back to dynamic search for alias matching or when the snapshot doesn't have the model.

func (*Router) RouteWithFallback

func (r *Router) RouteWithFallback(ctx context.Context, req *RouteRequest, execute func(*RouteResult) error) error

RouteWithFallback attempts to route within the discovered candidate set only. It never blind-falls back to providers/models outside the fetched model list (after allowlist filtering), so callers see the final routing error directly.

func (*Router) SetCooldownConfig

func (r *Router) SetCooldownConfig(cfg *CooldownConfig)

SetCooldownConfig sets the cooldown configuration

func (*Router) SetFailoverCallback

func (r *Router) SetFailoverCallback(cb func(*FailoverResult))

SetFailoverCallback sets a callback to be called after each failover operation

func (*Router) UpdateLatency

func (r *Router) UpdateLatency(providerID string, latency time.Duration)

UpdateLatency updates the latency for a provider

type RoutingMode

type RoutingMode string

RoutingMode defines the location preference for routing

const (
	// RoutingModeAuto uses intelligent routing across all providers
	RoutingModeAuto RoutingMode = "auto"
	// RoutingModeCloud only uses cloud providers
	RoutingModeCloud RoutingMode = "cloud"
	// RoutingModeLocal only uses local providers
	RoutingModeLocal RoutingMode = "local"
)

type RoutingStrategy

type RoutingStrategy string

RoutingStrategy defines how to select providers

const (
	// RoutingStrategyPriority selects by provider priority
	RoutingStrategyPriority RoutingStrategy = "priority"
	// RoutingStrategyCost selects the cheapest provider
	RoutingStrategyCost RoutingStrategy = "cost"
	// RoutingStrategyLatency selects the fastest provider
	RoutingStrategyLatency RoutingStrategy = "latency"
	// RoutingStrategyRoundRobin rotates through providers
	RoutingStrategyRoundRobin RoutingStrategy = "round_robin"
)

type SQLiteStorage

type SQLiteStorage struct {
	// contains filtered or unexported fields
}

SQLiteStorage implements Storage using SQLite tables.

func NewSQLiteStorage

func NewSQLiteStorage(db *sql.DB, opts ...StorageOption) (*SQLiteStorage, error)

NewSQLiteStorage creates a new SQLite-backed storage and runs migrations.

func NewSQLiteStorageWithReadDB

func NewSQLiteStorageWithReadDB(writeDB, readDB *sql.DB, opts ...StorageOption) (*SQLiteStorage, error)

NewSQLiteStorageWithReadDB creates a new SQLite-backed storage with separate write and read database handles and runs migrations.

func (*SQLiteStorage) AppendUsage

func (s *SQLiteStorage) AppendUsage(record *UsageRecord) error

func (*SQLiteStorage) DeleteProvider

func (s *SQLiteStorage) DeleteProvider(id string) error

func (*SQLiteStorage) LoadAllProviders

func (s *SQLiteStorage) LoadAllProviders() ([]*Provider, error)

func (*SQLiteStorage) LoadConfig

func (s *SQLiteStorage) LoadConfig() (*PoolConfig, error)

func (*SQLiteStorage) LoadModels

func (s *SQLiteStorage) LoadModels(providerID string) ([]*Model, error)

func (*SQLiteStorage) LoadPricingConfig

func (s *SQLiteStorage) LoadPricingConfig() (*PricingConfig, error)

func (*SQLiteStorage) LoadProvider

func (s *SQLiteStorage) LoadProvider(id string) (*Provider, error)

func (*SQLiteStorage) LoadUsage

func (s *SQLiteStorage) LoadUsage(providerID string, start, end time.Time) ([]*UsageRecord, error)

func (*SQLiteStorage) MigrateFromFiles

func (s *SQLiteStorage) MigrateFromFiles(basePath string) error

MigrateFromFiles imports data from the legacy FileStorage directory into SQLite. After successful migration, the old directory is renamed to basePath+".bak". This is idempotent — if the DB already has providers, migration is skipped.

func (*SQLiteStorage) SaveConfig

func (s *SQLiteStorage) SaveConfig(config *PoolConfig) error

func (*SQLiteStorage) SaveModels

func (s *SQLiteStorage) SaveModels(providerID string, models []*Model) error

func (*SQLiteStorage) SavePricingConfig

func (s *SQLiteStorage) SavePricingConfig(config *PricingConfig) error

func (*SQLiteStorage) SaveProvider

func (s *SQLiteStorage) SaveProvider(provider *Provider) error

type SecretEncryptor

type SecretEncryptor interface {
	EncryptString(plaintext string) (string, error)
	DecryptString(ciphertext string) (string, error)
}

SecretEncryptor encrypts/decrypts provider secrets at rest. *auth.Encryptor satisfies this interface.

type Storage

type Storage interface {
	// Provider operations
	SaveProvider(provider *Provider) error
	LoadProvider(id string) (*Provider, error)
	LoadAllProviders() ([]*Provider, error)
	DeleteProvider(id string) error

	// Model operations
	SaveModels(providerID string, models []*Model) error
	LoadModels(providerID string) ([]*Model, error)

	// Usage operations
	AppendUsage(record *UsageRecord) error
	LoadUsage(providerID string, start, end time.Time) ([]*UsageRecord, error)

	// Pricing configuration
	SavePricingConfig(config *PricingConfig) error
	LoadPricingConfig() (*PricingConfig, error)

	// Pool configuration
	SaveConfig(config *PoolConfig) error
	LoadConfig() (*PoolConfig, error)
}

Storage defines the interface for provider data persistence

type StorageOption

type StorageOption func(*storageOptions)

StorageOption configures provider storage behavior.

func WithStorageEncryptor

func WithStorageEncryptor(enc SecretEncryptor) StorageOption

WithStorageEncryptor enables encryption for persisted provider secrets.

type TrialPersistHook

type TrialPersistHook struct {
	Load           func(dataDir string, licenseSig []byte, claims *LicenseClaims) (*trialState, error)
	Save           func(dataDir string, licenseSig []byte, claims *LicenseClaims, state *trialState) error
	CheckActivated func(dataDir string, licenseSig []byte, claims *LicenseClaims) bool
}

TrialPersistHook provides optional external persistence for trial state.

type TrialQuotaManager

type TrialQuotaManager struct {
	// contains filtered or unexported fields
}

TrialQuotaManager manages trial quota tracking with Ed25519 license verification and HMAC-protected state persistence.

func NewTrialQuotaManager

func NewTrialQuotaManager(registry *Registry, dataDir string, licenseStr string) *TrialQuotaManager

NewTrialQuotaManager creates a new trial quota manager. licenseStr is the Ed25519-signed license injected at build time. dataDir is a persistent directory for state storage (not tmpdir).

func (*TrialQuotaManager) CheckQuota

func (m *TrialQuotaManager) CheckQuota() error

CheckQuota checks if trial quota is available

func (*TrialQuotaManager) Claims

func (m *TrialQuotaManager) Claims() *LicenseClaims

Claims returns the verified license claims, or nil if no valid license.

func (*TrialQuotaManager) DeleteTrialProvider

func (m *TrialQuotaManager) DeleteTrialProvider() error

DeleteTrialProvider deletes the trial provider from the registry

func (*TrialQuotaManager) GetStatus

func (m *TrialQuotaManager) GetStatus() *TrialQuotaStatus

GetStatus returns the current trial quota status

func (*TrialQuotaManager) HandleQuotaExhausted

func (m *TrialQuotaManager) HandleQuotaExhausted() (message string, err error)

HandleQuotaExhausted handles the quota exhausted event

func (*TrialQuotaManager) IsExhausted

func (m *TrialQuotaManager) IsExhausted() bool

IsExhausted returns whether the trial quota is exhausted

func (*TrialQuotaManager) RecordUsage

func (m *TrialQuotaManager) RecordUsage(inputTokens, outputTokens int64, sessionID string) (exhausted bool, err error)

RecordUsage records usage and checks if quota is exhausted

func (*TrialQuotaManager) Reset

func (m *TrialQuotaManager) Reset()

Reset resets the trial quota (for testing or admin purposes)

type TrialQuotaStatus

type TrialQuotaStatus struct {
	TokensUsed      int64     `json:"tokens_used"`
	TokensRemaining int64     `json:"tokens_remaining"`
	TokenLimit      int64     `json:"token_limit"`
	IsExhausted     bool      `json:"is_exhausted"`
	ExhaustedReason string    `json:"exhausted_reason,omitempty"`
	LastUpdated     time.Time `json:"last_updated"`
	ExpiresAt       int64     `json:"expires_at,omitempty"` // license expiry unix timestamp
	IsExpired       bool      `json:"is_expired,omitempty"`
}

TrialQuotaStatus represents the current trial quota status

type UsageRecord

type UsageRecord struct {
	ID         string    `json:"id"`
	ProviderID string    `json:"provider_id"`
	ModelID    string    `json:"model_id"`
	APIKeyID   string    `json:"api_key_id,omitempty"`
	Timestamp  time.Time `json:"timestamp"`

	// Token counts
	InputTokens      int64 `json:"input_tokens"`
	OutputTokens     int64 `json:"output_tokens"`
	CacheReadTokens  int64 `json:"cache_read_tokens,omitempty"`
	CacheWriteTokens int64 `json:"cache_write_tokens,omitempty"`

	// Request metrics
	RequestCount int64 `json:"request_count"`
	LatencyMs    int64 `json:"latency_ms"`
	Success      bool  `json:"success"`

	// Cost estimation
	EstimatedCost float64 `json:"estimated_cost,omitempty"`

	// Context
	SessionID string `json:"session_id,omitempty"`
	UserID    string `json:"user_id,omitempty"`
}

UsageRecord tracks usage per provider/model

type UsageSummary

type UsageSummary struct {
	ProviderID string `json:"provider_id,omitempty"`
	ModelID    string `json:"model_id,omitempty"`
	Period     string `json:"period"` // "day", "week", "month"

	// Aggregated metrics
	TotalInputTokens      int64   `json:"total_input_tokens"`
	TotalOutputTokens     int64   `json:"total_output_tokens"`
	TotalCacheReadTokens  int64   `json:"total_cache_read_tokens"`
	TotalCacheWriteTokens int64   `json:"total_cache_write_tokens"`
	TotalRequests         int64   `json:"total_requests"`
	SuccessfulRequests    int64   `json:"successful_requests"`
	FailedRequests        int64   `json:"failed_requests"`
	TotalEstimatedCost    float64 `json:"total_estimated_cost"`

	// Latency stats
	AvgLatencyMs int64 `json:"avg_latency_ms"`
	MinLatencyMs int64 `json:"min_latency_ms"`
	MaxLatencyMs int64 `json:"max_latency_ms"`
	P95LatencyMs int64 `json:"p95_latency_ms"`

	// Time range
	StartTime time.Time `json:"start_time"`
	EndTime   time.Time `json:"end_time"`
}

UsageSummary aggregates usage statistics

type UsageTracker

type UsageTracker struct {
	// contains filtered or unexported fields
}

UsageTracker tracks usage across providers and models

func NewUsageTracker

func NewUsageTracker(storage Storage, opts ...UsageTrackerOption) *UsageTracker

NewUsageTracker creates a new usage tracker

func (*UsageTracker) GetCurrentStats

func (t *UsageTracker) GetCurrentStats() map[string]*UsageSummary

GetCurrentStats returns current in-memory statistics

func (*UsageTracker) GetModelStats

func (t *UsageTracker) GetModelStats(providerID string, start, end time.Time) (map[string]*UsageSummary, error)

GetModelStats returns aggregated stats per model

func (*UsageTracker) GetProviderStats

func (t *UsageTracker) GetProviderStats(start, end time.Time) (map[string]*UsageSummary, error)

GetProviderStats returns aggregated stats per provider

func (*UsageTracker) GetSummary

func (t *UsageTracker) GetSummary(providerID string, start, end time.Time) (*UsageSummary, error)

GetSummary calculates a usage summary for a time range

func (*UsageTracker) GetUsage

func (t *UsageTracker) GetUsage(providerID string, start, end time.Time) ([]*UsageRecord, error)

GetUsage retrieves usage records for a time range

func (*UsageTracker) GetWeeklySummary

func (t *UsageTracker) GetWeeklySummary(providerID string) (*UsageSummary, error)

GetWeeklySummary returns usage summary for the past 7 days

func (*UsageTracker) Record

func (t *UsageTracker) Record(record *UsageRecord)

Record records a usage event

func (*UsageTracker) RecordRequest

func (t *UsageTracker) RecordRequest(providerID, modelID string, inputTokens, outputTokens int64, latencyMs int64, success bool)

RecordRequest is a convenience method to record a request

func (*UsageTracker) SetPricingManager

func (t *UsageTracker) SetPricingManager(pm *PricingManager)

SetPricingManager sets the pricing manager for cost calculation

func (*UsageTracker) Start

func (t *UsageTracker) Start()

Start starts the background processing

func (*UsageTracker) Stop

func (t *UsageTracker) Stop()

Stop stops the tracker and flushes remaining data

type UsageTrackerOption

type UsageTrackerOption func(*UsageTracker)

UsageTrackerOption configures the UsageTracker

func WithUsageBufferSize

func WithUsageBufferSize(size int) UsageTrackerOption

WithUsageBufferSize sets the buffer size

func WithUsageFlushInterval

func WithUsageFlushInterval(interval time.Duration) UsageTrackerOption

WithUsageFlushInterval sets the flush interval

Directories

Path Synopsis
Package embedded provides go:embed access to provider_catalog.json.
Package embedded provides go:embed access to provider_catalog.json.
Package ide provides discovery and integration with local IDE tools that have LLM provider capabilities (Antigravity, Cursor, Windsurf, etc.)
Package ide provides discovery and integration with local IDE tools that have LLM provider capabilities (Antigravity, Cursor, Windsurf, etc.)
Package oauth provides OAuth token management for LLM providers.
Package oauth provides OAuth token management for LLM providers.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL