package config import ( "encoding/hex" "fmt" "strings" "github.com/spf13/viper" ) const AgentKindGenericNode = "generic-node" // NormalizeAgentKind returns the canonical agent kind for a node definition. // An empty value defaults to generic-node; any other unsupported value is // rejected so misconfigured kinds fail at config load time. func NormalizeAgentKind(kind string) (string, error) { switch kind { case "": return AgentKindGenericNode, nil case AgentKindGenericNode: return kind, nil default: return "", fmt.Errorf("invalid agent_kind %q (allowed: %q)", kind, AgentKindGenericNode) } } // NormalizeProviderType returns the canonical driver name for provider type. func NormalizeProviderType(t string) string { switch strings.ToLower(strings.TrimSpace(t)) { case "openai_compat", "openai_api", "vllm", "lemonade", "sglang", "seulgivibe_claude", "seulgivibe_openai": return "openai_compat" case "ollama": return "ollama" case "cli": return "cli" default: return t } } type NodeConfig struct { Transport TransportConf `mapstructure:"transport" yaml:"transport"` Reconnect ReconnectConf `mapstructure:"reconnect" yaml:"reconnect"` Logging LoggingConf `mapstructure:"logging" yaml:"logging"` Metrics MetricsConf `mapstructure:"metrics" yaml:"metrics"` } // ReconnectConf controls Edge reconnect behaviour after a disconnect. type ReconnectConf struct { IntervalSec int `mapstructure:"interval_sec" yaml:"interval_sec"` MaxAttempts int `mapstructure:"max_attempts" yaml:"max_attempts"` } // EdgeRefreshConf configures the Edge-local refresh admin HTTP server. // When Enabled is false (default) the admin server is not started and // config refresh is not available without a restart. type EdgeRefreshConf struct { Enabled bool `mapstructure:"enabled" yaml:"enabled"` Listen string `mapstructure:"listen" yaml:"listen"` } type EdgeConfig struct { Edge EdgeInfo `mapstructure:"edge" yaml:"edge"` Server EdgeServerConf `mapstructure:"server" yaml:"server"` Bootstrap EdgeBootstrapConf `mapstructure:"bootstrap" yaml:"bootstrap"` OpenAI EdgeOpenAIConf `mapstructure:"openai" yaml:"openai"` A2A EdgeA2AConf `mapstructure:"a2a" yaml:"a2a"` TLS TLSConf `mapstructure:"tls" yaml:"tls"` Logging LoggingConf `mapstructure:"logging" yaml:"logging"` Metrics MetricsConf `mapstructure:"metrics" yaml:"metrics"` Console EdgeConsoleConf `mapstructure:"console" yaml:"console"` ControlPlane EdgeControlPlaneConf `mapstructure:"control_plane" yaml:"control_plane"` Refresh EdgeRefreshConf `mapstructure:"refresh" yaml:"refresh,omitempty"` // LongContextThresholdTokens is the input-token estimate at or above which // a request is classified as long-context for admission policy. LongContextThresholdTokens int `mapstructure:"long_context_threshold_tokens" yaml:"long_context_threshold_tokens,omitempty"` Nodes []NodeDefinition `mapstructure:"nodes" yaml:"nodes"` // Models is the top-level model catalog. Each entry defines a canonical // routing key (ID) and its provider-pool mapping. When set it takes // precedence over the legacy openai.model_routes for runtime dispatch. Models []ModelCatalogEntry `mapstructure:"models" yaml:"models,omitempty"` } // EdgeControlPlaneConf holds the outbound connector settings for the // Control Plane-Edge wire. When Enabled is false or WireAddr is empty the // connector is a no-op and existing Edge behaviour is unaffected. type EdgeControlPlaneConf struct { Enabled bool `mapstructure:"enabled" yaml:"enabled"` WireAddr string `mapstructure:"wire_addr" yaml:"wire_addr"` ReconnectIntervalSec int `mapstructure:"reconnect_interval_sec" yaml:"reconnect_interval_sec"` } // EdgeInfo carries this edge instance's stable identity for loading and logging. // It is not used for Control Plane registration. type EdgeInfo struct { ID string `mapstructure:"id" yaml:"id"` Name string `mapstructure:"name" yaml:"name"` } // NodeDefinition is the edge-side record for a pre-registered node. type NodeDefinition struct { ID string `mapstructure:"id" yaml:"id"` // stable node identity; if empty, a UUID v4 is auto-assigned (dev fallback only) Alias string `mapstructure:"alias" yaml:"alias"` Token string `mapstructure:"token" yaml:"token"` AgentKind string `mapstructure:"agent_kind" yaml:"agent_kind"` // generic-node (default) Adapters AdaptersConf `mapstructure:"adapters" yaml:"adapters"` Providers []NodeProviderConf `mapstructure:"providers" yaml:"providers,omitempty"` Runtime RuntimeConf `mapstructure:"runtime" yaml:"runtime"` } // Category represents the provider category. type Category string const ( CategoryAPI Category = "api" CategoryCLI Category = "cli" CategoryLocalInference Category = "local_inference" ) // validateCategory returns nil when category is valid. func validateCategory(c Category) error { switch c { case CategoryAPI, CategoryCLI, CategoryLocalInference: return nil default: return fmt.Errorf("invalid provider category %q (allowed: %q, %q, %q)", c, CategoryAPI, CategoryCLI, CategoryLocalInference) } } // NodeProviderConf defines a resource/provider candidate that belongs to a // node. Provider-first resources can declare type-specific execution fields // directly, while Adapter remains available for legacy/compat overrides. type NodeProviderConf struct { // ID uniquely identifies this provider within the node and is referenced // by models[].providers keys. ID string `mapstructure:"id" yaml:"id"` // Type is the runtime type (e.g. "ollama", "vllm", "lemonade", "sglang", "openai_api", "cli"). Type string `mapstructure:"type" yaml:"type"` // Category classifies the resource; MVP values: api, cli, local_inference. Category Category `mapstructure:"category" yaml:"category"` // Adapter is the optional concrete enabled adapter instance key used by // legacy/compat provider resources. A legacy type-name route is valid only // when exactly one enabled adapter instance of that type exists on the same // node. Adapter string `mapstructure:"adapter" yaml:"adapter,omitempty"` // Models lists the served model names this provider can actually serve. Models []string `mapstructure:"models" yaml:"models,omitempty"` // Health is the observed provider health state. Health string `mapstructure:"health" yaml:"health,omitempty"` // Capacity is the provider/resource maximum concurrent execution slots. // Provider-pool dispatch treats 0 as not dispatchable rather than falling // back to node runtime concurrency metadata. Capacity int `mapstructure:"capacity" yaml:"capacity,omitempty"` // TotalContextTokens is the provider runtime's total KV/context budget used // as the long-context admission budget. Runtime-specific options (e.g. // ctx_size) map onto this value. Must satisfy // total_context_tokens >= context_window_tokens * long_context_capacity for // every model group that references this provider. TotalContextTokens int `mapstructure:"total_context_tokens" yaml:"total_context_tokens,omitempty"` // LongContextCapacity is the number of concurrent long-context slots this // provider allows (context_window_tokens-sized requests). Long requests // occupy both a normal capacity slot and a long slot. Zero means the // provider declares no dedicated long-slot limit. LongContextCapacity int `mapstructure:"long_context_capacity" yaml:"long_context_capacity,omitempty"` // MaxQueue is the maximum queue depth. MaxQueue int `mapstructure:"max_queue" yaml:"max_queue,omitempty"` // QueueTimeoutMS is the queue timeout in milliseconds. Zero means no queue // timeout when a queue policy is configured. QueueTimeoutMS int `mapstructure:"queue_timeout_ms" yaml:"queue_timeout_ms,omitempty"` // Priority is the provider dispatch priority. Lower values are preferred // when in_flight counts are equal. Must be non-negative; zero is the // default priority. Priority int `mapstructure:"priority" yaml:"priority,omitempty"` // LifecycleCapabilities lists coarse lifecycle capabilities. LifecycleCapabilities []string `mapstructure:"lifecycle_capabilities" yaml:"lifecycle_capabilities,omitempty"` // Enabled controls whether this provider participates in the dispatch pool. // Nil (omitted) means enabled; false disables the provider without removing it. Enabled *bool `mapstructure:"enabled" yaml:"enabled,omitempty"` // Provider-First fields (G06) Provider string `mapstructure:"provider" yaml:"provider,omitempty"` Endpoint string `mapstructure:"endpoint" yaml:"endpoint,omitempty"` BaseURL string `mapstructure:"base_url" yaml:"base_url,omitempty"` Headers map[string]string `mapstructure:"headers" yaml:"headers,omitempty"` Command string `mapstructure:"command" yaml:"command,omitempty"` Args []string `mapstructure:"args" yaml:"args,omitempty"` Env []string `mapstructure:"env" yaml:"env,omitempty"` Mode string `mapstructure:"mode" yaml:"mode,omitempty"` ResumeArgs []string `mapstructure:"resume_args" yaml:"resume_args,omitempty"` OutputFormat string `mapstructure:"output_format" yaml:"output_format,omitempty"` ContextSize int `mapstructure:"context_size" yaml:"context_size,omitempty"` RequestTimeoutMS int `mapstructure:"request_timeout_ms" yaml:"request_timeout_ms,omitempty"` } // Validate checks internal consistency of the provider candidate config. func (p NodeProviderConf) Validate() error { id := strings.TrimSpace(p.ID) if id == "" { return fmt.Errorf("nodes[].providers[].id must not be empty") } if strings.TrimSpace(p.Type) == "" { return fmt.Errorf("nodes[].providers[%q]: type must not be empty", id) } if err := validateCategory(p.Category); err != nil { return fmt.Errorf("nodes[].providers[%q]: %w", id, err) } for i, m := range p.Models { if strings.TrimSpace(m) == "" { return fmt.Errorf("nodes[].providers[%q].models[%d]: served model name must not be empty", id, i) } } if p.Capacity < 0 { return fmt.Errorf("nodes[].providers[%q].capacity must be non-negative", id) } if p.MaxQueue < 0 { return fmt.Errorf("nodes[].providers[%q].max_queue must be non-negative", id) } if p.QueueTimeoutMS < 0 { return fmt.Errorf("nodes[].providers[%q].queue_timeout_ms must be non-negative", id) } if p.RequestTimeoutMS < 0 { return fmt.Errorf("nodes[].providers[%q].request_timeout_ms must be non-negative", id) } if p.ContextSize < 0 { return fmt.Errorf("nodes[].providers[%q].context_size must be non-negative", id) } if p.Priority < 0 { return fmt.Errorf("nodes[].providers[%q].priority must be non-negative", id) } if p.TotalContextTokens < 0 { return fmt.Errorf("nodes[].providers[%q].total_context_tokens must be non-negative", id) } if p.LongContextCapacity < 0 { return fmt.Errorf("nodes[].providers[%q].long_context_capacity must be non-negative", id) } if p.LongContextCapacity > 0 && p.TotalContextTokens <= 0 { return fmt.Errorf("nodes[].providers[%q].total_context_tokens must be positive when long_context_capacity > 0", id) } return nil } // ProviderEnabled reports whether a provider is enabled. // Returns true when Enabled is nil (omitted) or *Enabled is true. // Returns false only when Enabled is explicitly set to false. func ProviderEnabled(p NodeProviderConf) bool { return p.Enabled == nil || *p.Enabled } type NodeInfo struct { ID string `mapstructure:"id" yaml:"id"` Name string `mapstructure:"name" yaml:"name"` } type EdgeServerConf struct { Listen string `mapstructure:"listen" yaml:"listen"` AdvertiseHost string `mapstructure:"advertise_host" yaml:"advertise_host"` } type EdgeBootstrapConf struct { ArtifactBaseURL string `mapstructure:"artifact_base_url" yaml:"artifact_base_url"` Listen string `mapstructure:"listen" yaml:"listen"` ArtifactDir string `mapstructure:"artifact_dir" yaml:"artifact_dir"` } // OpenAIRouteEntry maps an external model id to an internal adapter/target routing. // Fields not set here fall back to the top-level EdgeOpenAIConf defaults. type OpenAIRouteEntry struct { Model string `mapstructure:"model" yaml:"model"` NodeRef string `mapstructure:"node" yaml:"node,omitempty"` Adapter string `mapstructure:"adapter" yaml:"adapter,omitempty"` Target string `mapstructure:"target" yaml:"target"` SessionID string `mapstructure:"session_id" yaml:"session_id,omitempty"` TimeoutSec int `mapstructure:"timeout_sec" yaml:"timeout_sec,omitempty"` MaxQueue int `mapstructure:"max_queue" yaml:"max_queue,omitempty"` QueueTimeoutMS int `mapstructure:"queue_timeout_ms" yaml:"queue_timeout_ms,omitempty"` WorkspaceRequired bool `mapstructure:"workspace_required" yaml:"workspace_required,omitempty"` } // ModelCatalogEntry is a top-level Edge config entry that defines a canonical // routing key (`ID`) and its provider-pool mapping. Each provider id key // maps to the concrete served model name that the provider actually exposes. type ModelCatalogEntry struct { // ID is the canonical routing key (e.g. "qwen3.6:35b") that matches the // external OpenAI-compatible model field. ID string `mapstructure:"id" yaml:"id"` // DisplayName is a human-readable name shown in operation dashboards. DisplayName string `mapstructure:"display_name" yaml:"display_name,omitempty"` // ContextWindowTokens is the model group's single-request maximum context // contract shared by every provider in the group. ContextWindowTokens int `mapstructure:"context_window_tokens" yaml:"context_window_tokens,omitempty"` // DefaultMaxTokens is injected when OpenAI-compatible requests omit an // output-token limit for this model group. DefaultMaxTokens int `mapstructure:"default_max_tokens" yaml:"default_max_tokens,omitempty"` // MinMaxTokens raises too-small OpenAI-compatible output-token limits for // this model group. MinMaxTokens int `mapstructure:"min_max_tokens" yaml:"min_max_tokens,omitempty"` // DefaultThinkingTokenBudget bounds reasoning tokens for think-capable // providers when callers do not explicitly set a budget. DefaultThinkingTokenBudget int `mapstructure:"default_thinking_token_budget" yaml:"default_thinking_token_budget,omitempty"` // Providers maps provider id to the concrete served model name that the // provider actually exposes. Keys must match nodes[].providers[].id. Providers map[string]string `mapstructure:"providers" yaml:"providers"` } // buildProviderServedModelsIndex aggregates all nodes[].providers[].models // keyed by provider id. Returns the index for Validate. func buildProviderServedModelsIndex(nodes []NodeDefinition) map[string]map[string]struct{} { serveModels := make(map[string]map[string]struct{}) for i := range nodes { for _, p := range nodes[i].Providers { if _, ok := serveModels[p.ID]; !ok { serveModels[p.ID] = make(map[string]struct{}) } for _, m := range p.Models { serveModels[p.ID][m] = struct{}{} } } } return serveModels } // Validate checks the structure and internal references of the model catalog entry. // When serveModels is non-nil, it also verifies that each models[].providers[pid]=model // refers to a served model that exists in nodes[].providers[id].models. func (e ModelCatalogEntry) Validate(resolvedProviderIDs map[string]struct{}, serveModels map[string]map[string]struct{}) error { id := strings.TrimSpace(e.ID) if id == "" { return fmt.Errorf("models[].id must not be empty") } if e.DefaultMaxTokens < 0 { return fmt.Errorf("models[%q].default_max_tokens must be non-negative", id) } if e.MinMaxTokens < 0 { return fmt.Errorf("models[%q].min_max_tokens must be non-negative", id) } if e.DefaultThinkingTokenBudget < 0 { return fmt.Errorf("models[%q].default_thinking_token_budget must be non-negative", id) } if e.ContextWindowTokens < 0 { return fmt.Errorf("models[%q].context_window_tokens must be non-negative", id) } if e.DefaultMaxTokens > 0 && e.MinMaxTokens > 0 && e.DefaultMaxTokens < e.MinMaxTokens { return fmt.Errorf("models[%q].default_max_tokens must be greater than or equal to min_max_tokens", id) } if len(e.Providers) == 0 { return fmt.Errorf("models[%q].providers must not be empty", id) } for pid, model := range e.Providers { p := strings.TrimSpace(pid) if p == "" { return fmt.Errorf("models[%q].providers: provider id must not be empty", id) } m := strings.TrimSpace(model) if m == "" { return fmt.Errorf("models[%q].providers[%q]: served model name must not be empty", id, p) } if _, ok := resolvedProviderIDs[p]; !ok { return fmt.Errorf("models[%q].providers[%q]: provider id %q does not resolve to any nodes[].providers[].id", id, p, p) } // Serve model membership validation (REVIEW_API-1): // The served model must be listed in the provider's own models[]. if serveModels != nil { servedSet, exists := serveModels[p] if !exists { // No providers list yet (should not happen in modern configs). return fmt.Errorf("models[%q].providers[%q]: provider %q has no models[] defined", id, p, p) } if _, ok := servedSet[m]; !ok { return fmt.Errorf("models[%q].providers[%q]: served model %q is not listed in nodes[].providers[%q].models", id, p, m, p) } } } return nil } type EdgeOpenAIConf struct { Enabled bool `mapstructure:"enabled" yaml:"enabled"` Listen string `mapstructure:"listen" yaml:"listen"` BearerToken string `mapstructure:"bearer_token" yaml:"bearer_token"` PrincipalTokens []OpenAIPrincipalTokenConf `mapstructure:"principal_tokens" yaml:"principal_tokens,omitempty"` ProviderAuth EdgeOpenAIProviderAuthConf `mapstructure:"provider_auth" yaml:"provider_auth,omitempty"` NodeRef string `mapstructure:"node" yaml:"node"` Adapter string `mapstructure:"adapter" yaml:"adapter"` Target string `mapstructure:"target" yaml:"target"` Models []string `mapstructure:"models" yaml:"models"` ModelRoutes []OpenAIRouteEntry `mapstructure:"model_routes" yaml:"model_routes,omitempty"` SessionID string `mapstructure:"session_id" yaml:"session_id"` TimeoutSec int `mapstructure:"timeout_sec" yaml:"timeout_sec"` StrictOutput bool `mapstructure:"strict_output" yaml:"strict_output"` StrictStreamBuffer bool `mapstructure:"strict_stream_buffer" yaml:"strict_stream_buffer"` } // EdgeOpenAIProviderAuthConf configures request-time provider token forwarding. // It only describes which caller header to forward and never stores raw token // values in config. type EdgeOpenAIProviderAuthConf struct { Enabled bool `mapstructure:"enabled" yaml:"enabled,omitempty"` FromHeader string `mapstructure:"from_header" yaml:"from_header,omitempty"` TargetHeader string `mapstructure:"target_header" yaml:"target_header,omitempty"` Scheme string `mapstructure:"scheme" yaml:"scheme,omitempty"` Required bool `mapstructure:"required" yaml:"required,omitempty"` } // OpenAIPrincipalTokenConf maps a hashed OpenAI-compatible bearer token to the // IOP bearer-token-operation identity it authenticates as. Raw tokens are // never stored in config; only the SHA-256 hash is persisted. type OpenAIPrincipalTokenConf struct { TokenRef string `mapstructure:"token_ref" yaml:"token_ref"` TokenHashSHA256 string `mapstructure:"token_hash_sha256" yaml:"token_hash_sha256"` PrincipalRef string `mapstructure:"principal_ref" yaml:"principal_ref"` PrincipalAlias string `mapstructure:"principal_alias" yaml:"principal_alias,omitempty"` } type EdgeA2AConf struct { Enabled bool `mapstructure:"enabled" yaml:"enabled"` Listen string `mapstructure:"listen" yaml:"listen"` Path string `mapstructure:"path" yaml:"path"` NodeRef string `mapstructure:"node" yaml:"node"` Adapter string `mapstructure:"adapter" yaml:"adapter"` Target string `mapstructure:"target" yaml:"target"` SessionID string `mapstructure:"session_id" yaml:"session_id"` TimeoutSec int `mapstructure:"timeout_sec" yaml:"timeout_sec"` BearerToken string `mapstructure:"bearer_token" yaml:"bearer_token"` } type EdgeConsoleConf struct { Adapter string `mapstructure:"adapter" yaml:"adapter"` Target string `mapstructure:"target" yaml:"target"` Agent string `mapstructure:"agent" yaml:"agent"` // legacy alias for target Model string `mapstructure:"model" yaml:"model"` // legacy alias for target SessionID string `mapstructure:"session_id" yaml:"session_id"` Background bool `mapstructure:"background" yaml:"background"` TimeoutSec int `mapstructure:"timeout_sec" yaml:"timeout_sec"` } func (c EdgeConsoleConf) ResolveTarget() string { if c.Target != "" { return c.Target } if c.Agent != "" { return c.Agent } return c.Model } // ResolveAgent is kept for callers still using the legacy console.agent name. func (c EdgeConsoleConf) ResolveAgent() string { return c.ResolveTarget() } type TransportConf struct { EdgeAddr string `mapstructure:"edge_addr" yaml:"edge_addr"` Token string `mapstructure:"token" yaml:"token"` } type TLSConf struct { Enabled bool `mapstructure:"enabled" yaml:"enabled"` Cert string `mapstructure:"cert" yaml:"cert"` Key string `mapstructure:"key" yaml:"key"` CA string `mapstructure:"ca" yaml:"ca"` } type RuntimeConf struct { // Concurrency is legacy compatibility metadata. Runtime admission must use // provider/resource capacity rather than treating this as a node-wide gate. Concurrency int `mapstructure:"concurrency" yaml:"concurrency"` } type SQLiteConf struct { DSN string `mapstructure:"dsn" yaml:"dsn"` } type LoggingConf struct { Level string `mapstructure:"level" yaml:"level"` Pretty bool `mapstructure:"pretty" yaml:"pretty"` Path string `mapstructure:"path" yaml:"path"` } type MetricsConf struct { Port int `mapstructure:"port" yaml:"port"` } type AdaptersConf struct { // Legacy single-instance fields. When non-empty they are normalised into // OllamaInstances / VllmInstances / OpenAICompatInstances during config load // so that all downstream code only needs to inspect the slice fields. Ollama OllamaConf `mapstructure:"ollama" yaml:"ollama"` Vllm VllmConf `mapstructure:"vllm" yaml:"vllm"` OpenAICompat OpenAICompatConf `mapstructure:"openai_compat" yaml:"openai_compat"` CLI CLIConf `mapstructure:"cli" yaml:"cli"` Mock MockConf `mapstructure:"mock" yaml:"mock"` // Multi-instance collections. Each entry carries a unique Name that acts as // the stable adapter instance identity within the node. Names must be unique // within each type collection; duplicate names are rejected at load time. OllamaInstances []OllamaInstanceConf `mapstructure:"ollama_instances" yaml:"ollama_instances,omitempty"` VllmInstances []VllmInstanceConf `mapstructure:"vllm_instances" yaml:"vllm_instances,omitempty"` OpenAICompatInstances []OpenAICompatInstanceConf `mapstructure:"openai_compat_instances" yaml:"openai_compat_instances,omitempty"` } // OllamaInstanceConf is one named Ollama engine instance within a node. type OllamaInstanceConf struct { Name string `mapstructure:"name" yaml:"name"` Enabled bool `mapstructure:"enabled" yaml:"enabled"` BaseURL string `mapstructure:"base_url" yaml:"base_url"` ContextSize int `mapstructure:"context_size" yaml:"context_size"` Capacity int `mapstructure:"capacity" yaml:"capacity"` MaxQueue int `mapstructure:"max_queue" yaml:"max_queue"` QueueTimeoutMS int `mapstructure:"queue_timeout_ms" yaml:"queue_timeout_ms"` // zero means no queue timeout RequestTimeoutMS int `mapstructure:"request_timeout_ms" yaml:"request_timeout_ms"` } // VllmInstanceConf is one named vLLM engine instance within a node. type VllmInstanceConf struct { Name string `mapstructure:"name" yaml:"name"` Enabled bool `mapstructure:"enabled" yaml:"enabled"` Endpoint string `mapstructure:"endpoint" yaml:"endpoint"` Capacity int `mapstructure:"capacity" yaml:"capacity"` MaxQueue int `mapstructure:"max_queue" yaml:"max_queue"` QueueTimeoutMS int `mapstructure:"queue_timeout_ms" yaml:"queue_timeout_ms"` // zero means no queue timeout RequestTimeoutMS int `mapstructure:"request_timeout_ms" yaml:"request_timeout_ms"` } type OpenAICompatConf struct { Enabled bool `mapstructure:"enabled" yaml:"enabled"` Provider string `mapstructure:"provider" yaml:"provider"` Endpoint string `mapstructure:"endpoint" yaml:"endpoint"` Headers map[string]string `mapstructure:"headers" yaml:"headers"` Capacity int `mapstructure:"capacity" yaml:"capacity"` MaxQueue int `mapstructure:"max_queue" yaml:"max_queue"` QueueTimeoutMS int `mapstructure:"queue_timeout_ms" yaml:"queue_timeout_ms"` // zero means no queue timeout RequestTimeoutMS int `mapstructure:"request_timeout_ms" yaml:"request_timeout_ms"` } type OpenAICompatInstanceConf struct { Name string `mapstructure:"name" yaml:"name"` Enabled bool `mapstructure:"enabled" yaml:"enabled"` Provider string `mapstructure:"provider" yaml:"provider"` Endpoint string `mapstructure:"endpoint" yaml:"endpoint"` Headers map[string]string `mapstructure:"headers" yaml:"headers"` Capacity int `mapstructure:"capacity" yaml:"capacity"` MaxQueue int `mapstructure:"max_queue" yaml:"max_queue"` QueueTimeoutMS int `mapstructure:"queue_timeout_ms" yaml:"queue_timeout_ms"` // zero means no queue timeout RequestTimeoutMS int `mapstructure:"request_timeout_ms" yaml:"request_timeout_ms"` } type OllamaConf struct { Enabled bool `mapstructure:"enabled" yaml:"enabled"` BaseURL string `mapstructure:"base_url" yaml:"base_url"` ContextSize int `mapstructure:"context_size" yaml:"context_size"` Capacity int `mapstructure:"capacity" yaml:"capacity"` MaxQueue int `mapstructure:"max_queue" yaml:"max_queue"` QueueTimeoutMS int `mapstructure:"queue_timeout_ms" yaml:"queue_timeout_ms"` // zero means no queue timeout RequestTimeoutMS int `mapstructure:"request_timeout_ms" yaml:"request_timeout_ms"` } type VllmConf struct { Enabled bool `mapstructure:"enabled" yaml:"enabled"` Endpoint string `mapstructure:"endpoint" yaml:"endpoint"` Capacity int `mapstructure:"capacity" yaml:"capacity"` MaxQueue int `mapstructure:"max_queue" yaml:"max_queue"` QueueTimeoutMS int `mapstructure:"queue_timeout_ms" yaml:"queue_timeout_ms"` // zero means no queue timeout RequestTimeoutMS int `mapstructure:"request_timeout_ms" yaml:"request_timeout_ms"` } type CLIConf struct { Enabled bool `mapstructure:"enabled" yaml:"enabled"` Profiles map[string]CLIProfileConf `mapstructure:"profiles" yaml:"profiles"` } // MockConf defines the mock adapter instance. It has no execution fields and // only serves as a flag to enable the mock adapter in the payload. type MockConf struct { Enabled bool `mapstructure:"enabled" yaml:"enabled"` } type CLIProfileConf struct { Command string `mapstructure:"command" yaml:"command"` Args []string `mapstructure:"args" yaml:"args"` Env []string `mapstructure:"env" yaml:"env"` Persistent bool `mapstructure:"persistent" yaml:"persistent"` Terminal bool `mapstructure:"terminal" yaml:"terminal"` ResponseIdleTimeoutMS int `mapstructure:"response_idle_timeout_ms" yaml:"response_idle_timeout_ms"` StartupIdleTimeoutMS int `mapstructure:"startup_idle_timeout_ms" yaml:"startup_idle_timeout_ms"` OutputFormat string `mapstructure:"output_format" yaml:"output_format"` CompletionMarker CompletionMarkerConf `mapstructure:"completion_marker" yaml:"completion_marker"` Mode string `mapstructure:"mode" yaml:"mode"` ResumeArgs []string `mapstructure:"resume_args" yaml:"resume_args"` } type CompletionMarkerConf struct { Line string `mapstructure:"line" yaml:"line"` Regex string `mapstructure:"regex" yaml:"regex"` } func (m CompletionMarkerConf) Empty() bool { return m.Line == "" && m.Regex == "" } func Load(cfgFile string) (*NodeConfig, error) { v := viper.New() v.SetConfigFile(cfgFile) setDefaults(v) if err := v.ReadInConfig(); err != nil { return nil, err } var cfg NodeConfig if err := v.Unmarshal(&cfg); err != nil { return nil, err } return &cfg, nil } func LoadEdge(cfgFile string) (*EdgeConfig, error) { v := viper.New() v.SetConfigFile(cfgFile) setEdgeDefaults(v) if err := v.ReadInConfig(); err != nil { return nil, err } var cfg EdgeConfig if err := v.Unmarshal(&cfg); err != nil { return nil, err } if !v.InConfig("console.target") { if v.InConfig("console.agent") { cfg.Console.Target = cfg.Console.Agent } else if v.InConfig("console.model") { cfg.Console.Target = cfg.Console.Model } } if err := validateOpenAIRoutes(cfg.OpenAI.ModelRoutes); err != nil { return nil, err } if err := validateOpenAIPrincipalTokens(cfg.OpenAI.PrincipalTokens); err != nil { return nil, err } if err := normalizeOpenAIProviderAuth(v, &cfg.OpenAI.ProviderAuth); err != nil { return nil, err } if cfg.LongContextThresholdTokens <= 0 { return nil, fmt.Errorf("long_context_threshold_tokens must be positive") } // Collect all provider IDs from nodes[].providers[] for cross-referencing // and validate uniqueness within each node. providerIDs := make(map[string]struct{}) providerByID := make(map[string]NodeProviderConf) for i := range cfg.Nodes { kind, err := NormalizeAgentKind(cfg.Nodes[i].AgentKind) if err != nil { return nil, fmt.Errorf("nodes[%d] alias=%q: %w", i, cfg.Nodes[i].Alias, err) } cfg.Nodes[i].AgentKind = kind if err := normalizeAdapters(&cfg.Nodes[i].Adapters); err != nil { name := cfg.Nodes[i].ID if name == "" { name = cfg.Nodes[i].Alias } return nil, fmt.Errorf("nodes[%d] %q adapters: %w", i, name, err) } // Validate unique provider IDs within this node and across all nodes. seenProviderIDs := make(map[string]struct{}, len(cfg.Nodes[i].Providers)) for j, p := range cfg.Nodes[i].Providers { if err := p.Validate(); err != nil { return nil, fmt.Errorf("nodes[%d].providers[%d]: %w", i, j, err) } if _, dup := seenProviderIDs[p.ID]; dup { return nil, fmt.Errorf("nodes[%d].providers: duplicate provider id %q within node", i, p.ID) } seenProviderIDs[p.ID] = struct{}{} if _, globalDup := providerIDs[p.ID]; globalDup { return nil, fmt.Errorf("nodes[%d].providers[%d]: duplicate provider id %q across nodes (global uniqueness violation)", i, j, p.ID) } providerIDs[p.ID] = struct{}{} providerByID[p.ID] = p } } for i := range cfg.Nodes { if err := CheckProviderLegacyConflict(i, cfg.Nodes[i].Alias, &cfg.Nodes[i]); err != nil { return nil, err } } // Build the provider->servedModels index so Validate can check membership. serveModels := buildProviderServedModelsIndex(cfg.Nodes) // Validate models[].providers reference valid provider IDs. seenModelIDs := make(map[string]struct{}, len(cfg.Models)) for i, m := range cfg.Models { id := strings.TrimSpace(m.ID) if id == "" { return nil, fmt.Errorf("models[%d]: id must not be empty", i) } if _, dup := seenModelIDs[id]; dup { return nil, fmt.Errorf("models: duplicate model id %q", id) } seenModelIDs[id] = struct{}{} if err := m.Validate(providerIDs, serveModels); err != nil { return nil, fmt.Errorf("models[%d]: %w", i, err) } if err := validateProviderLongContextBudget(m, providerByID); err != nil { return nil, fmt.Errorf("models[%d]: %w", i, err) } } return &cfg, nil } // validateProviderLongContextBudget enforces the long-context admission budget: // every provider referenced by a model group with a positive context window must // have total_context_tokens >= context_window_tokens * long_context_capacity. // Providers with long_context_capacity == 0 declare no long-slot budget and are // therefore unconstrained by this check. func validateProviderLongContextBudget(m ModelCatalogEntry, providerByID map[string]NodeProviderConf) error { if m.ContextWindowTokens <= 0 { return nil } for pid := range m.Providers { p := strings.TrimSpace(pid) prov, ok := providerByID[p] if !ok { continue } if prov.LongContextCapacity <= 0 { continue } required := m.ContextWindowTokens * prov.LongContextCapacity if prov.TotalContextTokens < required { return fmt.Errorf("providers[%q].total_context_tokens (%d) must be >= context_window_tokens (%d) * long_context_capacity (%d) = %d", p, prov.TotalContextTokens, m.ContextWindowTokens, prov.LongContextCapacity, required) } } return nil } // NormalizeAdapters promotes legacy single-instance Ollama/Vllm fields into the // typed instance slices and validates that all instance names are unique. func NormalizeAdapters(a *AdaptersConf) error { return normalizeAdapters(a) } func normalizeAdapters(a *AdaptersConf) error { if a.Ollama.Enabled { existing := findOllamaInstance(a.OllamaInstances, "ollama") if existing == nil { a.OllamaInstances = append([]OllamaInstanceConf{{ Name: "ollama", Enabled: a.Ollama.Enabled, BaseURL: a.Ollama.BaseURL, ContextSize: a.Ollama.ContextSize, Capacity: a.Ollama.Capacity, MaxQueue: a.Ollama.MaxQueue, QueueTimeoutMS: a.Ollama.QueueTimeoutMS, RequestTimeoutMS: a.Ollama.RequestTimeoutMS, }}, a.OllamaInstances...) } else if !sameOllamaInstance(*existing, a.Ollama) { return fmt.Errorf("ollama: legacy field conflicts with explicit instance %q: enabled/base_url/context_size/capacity/max_queue/queue_timeout_ms/request_timeout_ms mismatch", "ollama") } } if a.Vllm.Enabled { existing := findVllmInstance(a.VllmInstances, "vllm") if existing == nil { a.VllmInstances = append([]VllmInstanceConf{{ Name: "vllm", Enabled: a.Vllm.Enabled, Endpoint: a.Vllm.Endpoint, Capacity: a.Vllm.Capacity, MaxQueue: a.Vllm.MaxQueue, QueueTimeoutMS: a.Vllm.QueueTimeoutMS, RequestTimeoutMS: a.Vllm.RequestTimeoutMS, }}, a.VllmInstances...) } else if !sameVllmInstance(*existing, a.Vllm) { return fmt.Errorf("vllm: legacy field conflicts with explicit instance %q: enabled/endpoint/capacity/max_queue/queue_timeout_ms/request_timeout_ms mismatch", "vllm") } } if a.OpenAICompat.Enabled { existing := findOpenAICompatInstance(a.OpenAICompatInstances, "openai_compat") if existing == nil { a.OpenAICompatInstances = append([]OpenAICompatInstanceConf{{ Name: "openai_compat", Enabled: a.OpenAICompat.Enabled, Provider: a.OpenAICompat.Provider, Endpoint: a.OpenAICompat.Endpoint, Headers: a.OpenAICompat.Headers, Capacity: a.OpenAICompat.Capacity, MaxQueue: a.OpenAICompat.MaxQueue, QueueTimeoutMS: a.OpenAICompat.QueueTimeoutMS, RequestTimeoutMS: a.OpenAICompat.RequestTimeoutMS, }}, a.OpenAICompatInstances...) } else if !sameOpenAICompatInstance(*existing, a.OpenAICompat) { return fmt.Errorf("openai_compat: legacy field conflicts with explicit instance %q: enabled/provider/endpoint/headers/capacity/max_queue/queue_timeout_ms/request_timeout_ms mismatch", "openai_compat") } } if err := checkUniqueNames("ollama_instances", func(i int) string { return a.OllamaInstances[i].Name }, len(a.OllamaInstances)); err != nil { return err } if err := checkUniqueNames("vllm_instances", func(i int) string { return a.VllmInstances[i].Name }, len(a.VllmInstances)); err != nil { return err } if err := checkUniqueNames("openai_compat_instances", func(i int) string { return a.OpenAICompatInstances[i].Name }, len(a.OpenAICompatInstances)); err != nil { return err } for i, inst := range a.OllamaInstances { field := fmt.Sprintf("ollama_instances[%d]", i) if err := validateProviderQueueConfig(field, inst.Capacity, inst.MaxQueue, inst.QueueTimeoutMS, inst.RequestTimeoutMS); err != nil { return err } } for i, inst := range a.VllmInstances { field := fmt.Sprintf("vllm_instances[%d]", i) if err := validateProviderQueueConfig(field, inst.Capacity, inst.MaxQueue, inst.QueueTimeoutMS, inst.RequestTimeoutMS); err != nil { return err } } for i, inst := range a.OpenAICompatInstances { field := fmt.Sprintf("openai_compat_instances[%d]", i) if err := validateProviderQueueConfig(field, inst.Capacity, inst.MaxQueue, inst.QueueTimeoutMS, inst.RequestTimeoutMS); err != nil { return err } } return nil } func validateProviderQueueConfig(field string, capacity, maxQueue, queueTimeoutMS, requestTimeoutMS int) error { if capacity < 0 { return fmt.Errorf("%s.capacity must be non-negative", field) } if maxQueue < 0 { return fmt.Errorf("%s.max_queue must be non-negative", field) } if queueTimeoutMS < 0 { return fmt.Errorf("%s.queue_timeout_ms must be non-negative", field) } if requestTimeoutMS < 0 { return fmt.Errorf("%s.request_timeout_ms must be non-negative", field) } return nil } func sameOllamaInstance(inst OllamaInstanceConf, legacy OllamaConf) bool { return inst.Enabled == legacy.Enabled && inst.BaseURL == legacy.BaseURL && inst.ContextSize == legacy.ContextSize && inst.Capacity == legacy.Capacity && inst.MaxQueue == legacy.MaxQueue && inst.QueueTimeoutMS == legacy.QueueTimeoutMS && inst.RequestTimeoutMS == legacy.RequestTimeoutMS } func sameVllmInstance(inst VllmInstanceConf, legacy VllmConf) bool { return inst.Enabled == legacy.Enabled && inst.Endpoint == legacy.Endpoint && inst.Capacity == legacy.Capacity && inst.MaxQueue == legacy.MaxQueue && inst.QueueTimeoutMS == legacy.QueueTimeoutMS && inst.RequestTimeoutMS == legacy.RequestTimeoutMS } func findOllamaInstance(instances []OllamaInstanceConf, name string) *OllamaInstanceConf { for i := range instances { if instances[i].Name == name { return &instances[i] } } return nil } func findVllmInstance(instances []VllmInstanceConf, name string) *VllmInstanceConf { for i := range instances { if instances[i].Name == name { return &instances[i] } } return nil } func sameOpenAICompatInstance(inst OpenAICompatInstanceConf, legacy OpenAICompatConf) bool { if inst.Enabled != legacy.Enabled || inst.Provider != legacy.Provider || inst.Endpoint != legacy.Endpoint || inst.Capacity != legacy.Capacity || inst.MaxQueue != legacy.MaxQueue || inst.QueueTimeoutMS != legacy.QueueTimeoutMS || inst.RequestTimeoutMS != legacy.RequestTimeoutMS { return false } if len(inst.Headers) != len(legacy.Headers) { return false } for k, v := range inst.Headers { if lv, ok := legacy.Headers[k]; !ok || lv != v { return false } } return true } func findOpenAICompatInstance(instances []OpenAICompatInstanceConf, name string) *OpenAICompatInstanceConf { for i := range instances { if instances[i].Name == name { return &instances[i] } } return nil } // validateOpenAIRoutes rejects duplicate and empty model ids in the route catalog. func validateOpenAIRoutes(routes []OpenAIRouteEntry) error { seen := make(map[string]struct{}, len(routes)) for i, r := range routes { model := strings.TrimSpace(r.Model) if model == "" { return fmt.Errorf("openai.model_routes[%d]: model must not be empty", i) } if _, dup := seen[model]; dup { return fmt.Errorf("openai.model_routes: duplicate model %q", model) } seen[model] = struct{}{} if r.MaxQueue < 0 { return fmt.Errorf("openai.model_routes[%d].max_queue must be non-negative", i) } if r.QueueTimeoutMS < 0 { return fmt.Errorf("openai.model_routes[%d].queue_timeout_ms must be non-negative", i) } } return nil } // validateOpenAIPrincipalTokens validates the raw-token-free bearer token // operation mapping. Each entry must resolve to a unique, 64-char lowercase // hex SHA-256 hash and a non-empty principal_ref; token_ref must be unique. func validateOpenAIPrincipalTokens(tokens []OpenAIPrincipalTokenConf) error { seenTokenRef := make(map[string]struct{}, len(tokens)) seenHash := make(map[string]struct{}, len(tokens)) for i, t := range tokens { ref := strings.TrimSpace(t.TokenRef) if ref == "" { return fmt.Errorf("openai.principal_tokens[%d]: token_ref must not be empty", i) } if _, dup := seenTokenRef[ref]; dup { return fmt.Errorf("openai.principal_tokens: duplicate token_ref %q", ref) } seenTokenRef[ref] = struct{}{} hash := strings.ToLower(strings.TrimSpace(t.TokenHashSHA256)) if len(hash) != 64 { return fmt.Errorf("openai.principal_tokens[%q]: token_hash_sha256 must be a 64-character hex SHA-256 hash", ref) } if _, err := hex.DecodeString(hash); err != nil { return fmt.Errorf("openai.principal_tokens[%q]: token_hash_sha256 must be hex-encoded: %w", ref, err) } if _, dup := seenHash[hash]; dup { return fmt.Errorf("openai.principal_tokens: duplicate token_hash_sha256 for token_ref %q", ref) } seenHash[hash] = struct{}{} if strings.TrimSpace(t.PrincipalRef) == "" { return fmt.Errorf("openai.principal_tokens[%q]: principal_ref must not be empty", ref) } } return nil } func normalizeOpenAIProviderAuth(v *viper.Viper, auth *EdgeOpenAIProviderAuthConf) error { if !auth.Enabled { return nil } if v.InConfig("openai.provider_auth.from_header") { auth.FromHeader = strings.TrimSpace(auth.FromHeader) if auth.FromHeader == "" { return fmt.Errorf("openai.provider_auth.from_header must not be empty when provider_auth is enabled") } } else { auth.FromHeader = "X-IOP-Provider-Authorization" } if v.InConfig("openai.provider_auth.target_header") { auth.TargetHeader = strings.TrimSpace(auth.TargetHeader) if auth.TargetHeader == "" { return fmt.Errorf("openai.provider_auth.target_header must not be empty when provider_auth is enabled") } } else { auth.TargetHeader = "Authorization" } auth.Scheme = strings.TrimSpace(auth.Scheme) if auth.Scheme == "" { auth.Scheme = "Bearer" } if !v.InConfig("openai.provider_auth.required") { auth.Required = true } return nil } func checkUniqueNames(field string, name func(int) string, n int) error { seen := make(map[string]struct{}, n) for i := 0; i < n; i++ { k := name(i) if k == "" { return fmt.Errorf("%s[%d]: name must not be empty", field, i) } if _, dup := seen[k]; dup { return fmt.Errorf("%s: duplicate name %q", field, k) } seen[k] = struct{}{} } return nil } // CheckProviderLegacyConflict validates that when a provider-first resource // declares an ID matching an enabled legacy adapter instance name, the // provider's execution fields match the legacy adapter's fields. A mismatch // produces a validation error to prevent silent precedence between the two // config paths. func CheckProviderLegacyConflict(nodeIdx int, nodeName string, node *NodeDefinition) error { // Build a map of enabled adapter instance names to their configs per type. legacyByKey := make(map[string]*legacyAdapterRef) for _, inst := range node.Adapters.OllamaInstances { if inst.Enabled { legacyByKey[inst.Name] = &legacyAdapterRef{ Type: "ollama", BaseURL: inst.BaseURL, ContextSize: inst.ContextSize, Capacity: inst.Capacity, } } } for _, inst := range node.Adapters.VllmInstances { if inst.Enabled { legacyByKey[inst.Name] = &legacyAdapterRef{ Type: "vllm", Endpoint: inst.Endpoint, Capacity: inst.Capacity, } } } for _, inst := range node.Adapters.OpenAICompatInstances { if inst.Enabled { legacyByKey[inst.Name] = &legacyAdapterRef{ Type: "openai_compat", Provider: inst.Provider, Endpoint: inst.Endpoint, Headers: inst.Headers, Capacity: inst.Capacity, MaxQueue: inst.MaxQueue, QueueTimeoutMS: inst.QueueTimeoutMS, } } } // CLI legacy: enabled cli adapter with its profiles. if node.Adapters.CLI.Enabled { for name, profile := range node.Adapters.CLI.Profiles { legacyByKey[name] = &legacyAdapterRef{ Type: "cli", Command: profile.Command, Args: profile.Args, } } } for j, p := range node.Providers { legacy, exists := legacyByKey[p.ID] if !exists { continue } normType := NormalizeProviderType(p.Type) switch normType { case "ollama": if legacy.Type != "ollama" { continue } if p.BaseURL != "" && p.BaseURL != legacy.BaseURL { return fmt.Errorf("nodes[%d].providers[%d] %q conflicts with adapters.ollama instance %q: base_url mismatch (provider=%q, legacy=%q)", nodeIdx, j, p.ID, p.ID, p.BaseURL, legacy.BaseURL) } if p.ContextSize != 0 && p.ContextSize != legacy.ContextSize { return fmt.Errorf("nodes[%d].providers[%d] %q conflicts with adapters.ollama instance %q: context_size mismatch (provider=%d, legacy=%d)", nodeIdx, j, p.ID, p.ID, p.ContextSize, legacy.ContextSize) } if p.Capacity != legacy.Capacity { return fmt.Errorf("nodes[%d].providers[%d] %q conflicts with adapters.ollama instance %q: capacity mismatch (provider=%d, legacy=%d)", nodeIdx, j, p.ID, p.ID, p.Capacity, legacy.Capacity) } case "vllm", "openai_compat": if legacy.Type != "vllm" && legacy.Type != "openai_compat" { continue } if p.Endpoint != "" && p.Endpoint != legacy.Endpoint { return fmt.Errorf("nodes[%d].providers[%d] %q conflicts with adapters.%s instance %q: endpoint mismatch (provider=%q, legacy=%q)", nodeIdx, j, p.ID, legacy.Type, p.ID, p.Endpoint, legacy.Endpoint) } if p.Capacity != legacy.Capacity { return fmt.Errorf("nodes[%d].providers[%d] %q conflicts with adapters.%s instance %q: capacity mismatch (provider=%d, legacy=%d)", nodeIdx, j, p.ID, legacy.Type, p.ID, p.Capacity, legacy.Capacity) } case "cli": if legacy.Type != "cli" { continue } if p.Command != "" && p.Command != legacy.Command { return fmt.Errorf("nodes[%d].providers[%d] %q conflicts with adapters.cli profile %q: command mismatch (provider=%q, legacy=%q)", nodeIdx, j, p.ID, p.ID, p.Command, legacy.Command) } } } return nil } type legacyAdapterRef struct { Type string Endpoint string BaseURL string Provider string Headers map[string]string ContextSize int Capacity int MaxQueue int QueueTimeoutMS int Command string Args []string } func setDefaults(v *viper.Viper) { v.SetDefault("transport.edge_addr", "localhost:9090") v.SetDefault("reconnect.interval_sec", 10) v.SetDefault("reconnect.max_attempts", 10) v.SetDefault("logging.level", "info") v.SetDefault("metrics.port", 9091) } func setEdgeDefaults(v *viper.Viper) { v.SetDefault("server.listen", "0.0.0.0:9090") v.SetDefault("bootstrap.listen", "0.0.0.0:18080") v.SetDefault("bootstrap.artifact_dir", "artifacts") v.SetDefault("openai.enabled", false) v.SetDefault("openai.listen", "0.0.0.0:18081") v.SetDefault("openai.bearer_token", "") v.SetDefault("openai.adapter", "ollama") v.SetDefault("openai.session_id", "openai") v.SetDefault("openai.timeout_sec", 120) v.SetDefault("openai.strict_output", true) v.SetDefault("openai.strict_stream_buffer", false) v.SetDefault("a2a.enabled", false) v.SetDefault("a2a.listen", "0.0.0.0:8081") v.SetDefault("a2a.path", "/a2a") v.SetDefault("a2a.adapter", "cli") v.SetDefault("a2a.session_id", "a2a") v.SetDefault("a2a.timeout_sec", 120) v.SetDefault("logging.level", "info") v.SetDefault("metrics.port", 19092) v.SetDefault("tls.enabled", false) v.SetDefault("console.adapter", "cli") v.SetDefault("console.target", "claude") v.SetDefault("console.session_id", "default") v.SetDefault("console.background", false) v.SetDefault("console.timeout_sec", 120) v.SetDefault("control_plane.enabled", false) v.SetDefault("control_plane.wire_addr", "") v.SetDefault("control_plane.reconnect_interval_sec", 5) v.SetDefault("refresh.enabled", false) v.SetDefault("refresh.listen", "127.0.0.1:19093") v.SetDefault("long_context_threshold_tokens", 100000) }