package config import "time" const ( DefaultConfigPath = "./configs/dev.yaml" DefaultSource = "mcp" ) type Config struct { Version int `yaml:"version"` Server ServerConfig `yaml:"server"` MCP MCPConfig `yaml:"mcp"` Auth AuthConfig `yaml:"auth"` Database DatabaseConfig `yaml:"database"` AI AIConfig `yaml:"ai"` Capture CaptureConfig `yaml:"capture"` Search SearchConfig `yaml:"search"` Logging LoggingConfig `yaml:"logging"` Observability ObservabilityConfig `yaml:"observability"` Backfill BackfillConfig `yaml:"backfill"` MetadataRetry MetadataRetryConfig `yaml:"metadata_retry"` } type ServerConfig struct { Host string `yaml:"host"` Port int `yaml:"port"` ReadTimeout time.Duration `yaml:"read_timeout"` WriteTimeout time.Duration `yaml:"write_timeout"` IdleTimeout time.Duration `yaml:"idle_timeout"` AllowedOrigins []string `yaml:"allowed_origins"` } type MCPConfig struct { Path string `yaml:"path"` SSEPath string `yaml:"sse_path"` ServerName string `yaml:"server_name"` Version string `yaml:"version"` Transport string `yaml:"transport"` SessionTimeout time.Duration `yaml:"session_timeout"` PublicURL string `yaml:"public_url"` Instructions string `yaml:"-"` } type AuthConfig struct { HeaderName string `yaml:"header_name"` QueryParam string `yaml:"query_param"` AllowQueryParam bool `yaml:"allow_query_param"` Keys []APIKey `yaml:"keys"` OAuth OAuthConfig `yaml:"oauth"` } type APIKey struct { ID string `yaml:"id"` Value string `yaml:"value"` Description string `yaml:"description"` } type OAuthConfig struct { Clients []OAuthClient `yaml:"clients"` } type OAuthClient struct { ID string `yaml:"id"` ClientID string `yaml:"client_id"` ClientSecret string `yaml:"client_secret"` Description string `yaml:"description"` } type DatabaseConfig struct { URL string `yaml:"url"` MaxConns int32 `yaml:"max_conns"` MinConns int32 `yaml:"min_conns"` MaxConnLifetime time.Duration `yaml:"max_conn_lifetime"` MaxConnIdleTime time.Duration `yaml:"max_conn_idle_time"` } // AIConfig (v2): named providers + per-role chains. type AIConfig struct { Providers map[string]ProviderConfig `yaml:"providers"` Embeddings EmbeddingsRoleConfig `yaml:"embeddings"` Metadata MetadataRoleConfig `yaml:"metadata"` Background *BackgroundRolesConfig `yaml:"background,omitempty"` } type ProviderConfig struct { Type string `yaml:"type"` BaseURL string `yaml:"base_url"` APIKey string `yaml:"api_key"` RequestHeaders map[string]string `yaml:"request_headers,omitempty"` AppName string `yaml:"app_name,omitempty"` SiteURL string `yaml:"site_url,omitempty"` } type RoleTarget struct { Provider string `yaml:"provider"` Model string `yaml:"model"` } type RoleChain struct { Primary RoleTarget `yaml:"primary"` Fallbacks []RoleTarget `yaml:"fallbacks,omitempty"` } type EmbeddingsRoleConfig struct { Dimensions int `yaml:"dimensions"` Primary RoleTarget `yaml:"primary"` Fallbacks []RoleTarget `yaml:"fallbacks,omitempty"` } type MetadataRoleConfig struct { Temperature float64 `yaml:"temperature"` LogConversations bool `yaml:"log_conversations"` Timeout time.Duration `yaml:"timeout"` Primary RoleTarget `yaml:"primary"` Fallbacks []RoleTarget `yaml:"fallbacks,omitempty"` } // BackgroundRolesConfig overrides the foreground chains for background workers // (backfill_embeddings, metadata_retry, reparse_metadata). Either field may be // nil to inherit the foreground role unchanged. type BackgroundRolesConfig struct { Embeddings *RoleChain `yaml:"embeddings,omitempty"` Metadata *RoleChain `yaml:"metadata,omitempty"` } // Chain returns primary followed by fallbacks (deduped, blanks dropped). func (e EmbeddingsRoleConfig) Chain() []RoleTarget { return dedupeTargets(append([]RoleTarget{e.Primary}, e.Fallbacks...)) } func (m MetadataRoleConfig) Chain() []RoleTarget { return dedupeTargets(append([]RoleTarget{m.Primary}, m.Fallbacks...)) } func (c RoleChain) AsTargets() []RoleTarget { return dedupeTargets(append([]RoleTarget{c.Primary}, c.Fallbacks...)) } func dedupeTargets(in []RoleTarget) []RoleTarget { out := make([]RoleTarget, 0, len(in)) seen := make(map[RoleTarget]struct{}, len(in)) for _, t := range in { if t.Provider == "" || t.Model == "" { continue } if _, ok := seen[t]; ok { continue } seen[t] = struct{}{} out = append(out, t) } return out } type CaptureConfig struct { Source string `yaml:"source"` MetadataDefaults CaptureMetadataDefault `yaml:"metadata_defaults"` } type CaptureMetadataDefault struct { Type string `yaml:"type"` TopicFallback string `yaml:"topic_fallback"` } type SearchConfig struct { DefaultLimit int `yaml:"default_limit"` DefaultThreshold float64 `yaml:"default_threshold"` MaxLimit int `yaml:"max_limit"` } type LoggingConfig struct { Level string `yaml:"level"` Format string `yaml:"format"` } type ObservabilityConfig struct { MetricsEnabled bool `yaml:"metrics_enabled"` PprofEnabled bool `yaml:"pprof_enabled"` } type BackfillConfig struct { Enabled bool `yaml:"enabled"` RunOnStartup bool `yaml:"run_on_startup"` Interval time.Duration `yaml:"interval"` BatchSize int `yaml:"batch_size"` MaxPerRun int `yaml:"max_per_run"` IncludeArchived bool `yaml:"include_archived"` } type MetadataRetryConfig struct { Enabled bool `yaml:"enabled"` RunOnStartup bool `yaml:"run_on_startup"` Interval time.Duration `yaml:"interval"` MaxPerRun int `yaml:"max_per_run"` IncludeArchived bool `yaml:"include_archived"` }