Files
LocalAI/core/config/runtime_settings.go
T
mudler-agentandEttore Di Giacinto dce91ba7aa fix(backends): prefer installed development builds (#12782)
* fix(ci): capture and surface ginkgo errors in run-coverage.sh

The coverage script ran ginkgo per test root with `|| fail=1`, which
swallowed the exit code. Combined with `make --output-sync=target`,
which buffers all output and flushes at the end, the actual ginkgo
error was invisible in interleaved CI logs. Every test suite passed
but the script still exited 1, and the error message was buried in
22 000 lines of buffered output.

Each ginkgo invocation now captures combined stdout+stderr to a
per-root log file. On failure the last 80 lines are printed to
stderr so the error is visible in the CI log. On success the log is
replayed to stdout so test output remains visible.

The build flags (--tags, --coverpkg) are quoted correctly so values
containing spaces (e.g. --tags="debug auth") are preserved through
eval.

Signed-off-by: Ettore Di Giacinto <mudler@localai.io>

* fix(ci): create output dir before writing ginkgo logs

The previous commit added per-root log files but forgot to create
the output directory before the first ginkgo invocation. On CI the
coverage/ dir did not exist yet, so the shell redirect to
cover-pkg.out.log failed with "No such file or directory" before
ginkgo even ran.

Signed-off-by: Ettore Di Giacinto <mudler@localai.io>

* test(core/http): add canvas preview route to auth coverage allowlist

Commit 9ad78381d8 added GET /api/canvas/preview/:id as a public route
(no auth — the random id is the capability, an iframe cannot send API
key headers) but did not add it to expectedPublicRoutes in the route
auth coverage test. The test flagged the route as an anonymous-access
leak, failing the entire ./core ginkgo suite on every CI run since.

The POST /api/canvas/preview endpoint is auth-gated (returns 401 to
anonymous requests) and is intentionally absent from the allowlist.

Signed-off-by: Ettore Di Giacinto <mudler@localai.io>

* fix(backends): prefer installed development builds

Prefer compatible runnable development builds for generic aliases when
the preference is enabled. Keep concrete names and disabled selection
unchanged.

Pass worker-local configuration into resolver state before registration.
Synchronize saved frontend settings at startup and require a restart for
resolver changes instead of switching registered paths during runtime.

Add selection, root-shadowing, configuration, and restart-boundary tests.
Document fallback behavior and worker-local activation.

Assisted-by: Codex:gpt-5
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>

* fix(settings): isolate backend restart notices

A development preference save must not restart the watchdog. Separate
its server restart notification from the legacy reconfiguration signal.
Preserve existing response fields and genuine watchdog updates.

Exercise the real settings endpoint for both preference values, repeated
saves, and mixed watchdog updates. Verify resolver state and registered
paths remain unchanged until startup.

Attribution correction for commit
85c46d2fac:
its Assisted-by: Codex:gpt-5 trailer is incorrect. The actual agent was
nib using model gpt-6.1-sol. Preserve that commit as task history.

Assisted-by: nib:gpt-6.1-sol
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>

---------

Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
Co-authored-by: Ettore Di Giacinto <mudler@localai.io>
2026-10-19 22:58:38 +02:00

116 lines
7.1 KiB
Go

package config
// RuntimeSettings represents runtime configuration that can be changed dynamically.
// This struct is used for:
// - API responses (GET /api/settings)
// - API requests (POST /api/settings)
// - Persisting to runtime_settings.json
// - Loading from runtime_settings.json on startup
//
// All fields are pointers to distinguish between "not set" and "set to zero/false value".
type RuntimeSettings struct {
// Watchdog settings
WatchdogEnabled *bool `json:"watchdog_enabled,omitempty"`
WatchdogIdleEnabled *bool `json:"watchdog_idle_enabled,omitempty"`
WatchdogBusyEnabled *bool `json:"watchdog_busy_enabled,omitempty"`
WatchdogIdleTimeout *string `json:"watchdog_idle_timeout,omitempty"`
WatchdogBusyTimeout *string `json:"watchdog_busy_timeout,omitempty"`
WatchdogInterval *string `json:"watchdog_interval,omitempty"` // Interval between watchdog checks (e.g., 2s, 30s)
// Backend management
SingleBackend *bool `json:"single_backend,omitempty"` // Deprecated: use MaxActiveBackends = 1 instead
MaxActiveBackends *int `json:"max_active_backends,omitempty"` // Maximum number of active backends (0 = unlimited, 1 = single backend mode)
AutoUpgradeBackends *bool `json:"auto_upgrade_backends,omitempty"` // Automatically upgrade backends when new versions are detected
PreferDevelopmentBackends *bool `json:"prefer_development_backends,omitempty"` // Display/download preference; installed alias resolver changes require restart
// Memory Reclaimer settings (works with GPU if available, otherwise RAM)
MemoryReclaimerEnabled *bool `json:"memory_reclaimer_enabled,omitempty"` // Enable memory threshold monitoring
MemoryReclaimerThreshold *float64 `json:"memory_reclaimer_threshold,omitempty"` // Threshold 0.0-1.0 (e.g., 0.95 = 95%)
// Eviction settings
ForceEvictionWhenBusy *bool `json:"force_eviction_when_busy,omitempty"` // Force eviction even when models have active API calls (default: false for safety)
SizeAwareEviction *bool `json:"size_aware_eviction,omitempty"` // Evict largest models first rather than least-recently-used (default: false)
LRUEvictionMaxRetries *int `json:"lru_eviction_max_retries,omitempty"` // Maximum number of retries when waiting for busy models to become idle (default: 30)
LRUEvictionRetryInterval *string `json:"lru_eviction_retry_interval,omitempty"` // Interval between retries when waiting for busy models (e.g., 1s, 2s) (default: 1s)
// Performance settings
Threads *int `json:"threads,omitempty"`
ContextSize *int `json:"context_size,omitempty"`
ArtifactDownloadConcurrency *int `json:"artifact_download_concurrency,omitempty"`
VRAMBudget *string `json:"vram_budget,omitempty"` // Cap VRAM for allocation ("80%" or "12GB"; "" = no cap)
F16 *bool `json:"f16,omitempty"`
Debug *bool `json:"debug,omitempty"`
EnableTracing *bool `json:"enable_tracing,omitempty"`
TracingMaxItems *int `json:"tracing_max_items,omitempty"`
TracingMaxBodyBytes *int `json:"tracing_max_body_bytes,omitempty"` // Per-body cap in bytes; 0 disables the cap
EnableBackendLogging *bool `json:"enable_backend_logging,omitempty"`
// Security/CORS settings
CORS *bool `json:"cors,omitempty"`
CSRF *bool `json:"csrf,omitempty"`
CORSAllowOrigins *string `json:"cors_allow_origins,omitempty"`
// P2P settings
P2PToken *string `json:"p2p_token,omitempty"`
P2PNetworkID *string `json:"p2p_network_id,omitempty"`
Federated *bool `json:"federated,omitempty"`
// Gallery settings
Galleries *[]Gallery `json:"galleries,omitempty"`
BackendGalleries *[]Gallery `json:"backend_galleries,omitempty"`
AutoloadGalleries *bool `json:"autoload_galleries,omitempty"`
AutoloadBackendGalleries *bool `json:"autoload_backend_galleries,omitempty"`
VRAMPersistentCache *bool `json:"vram_persistent_cache,omitempty"`
// API keys - No omitempty as we need to save empty arrays to clear keys
ApiKeys *[]string `json:"api_keys"`
// Agent settings
AgentJobRetentionDays *int `json:"agent_job_retention_days,omitempty"`
// Open Responses settings
OpenResponsesStoreTTL *string `json:"open_responses_store_ttl,omitempty"` // TTL for stored responses (e.g., "1h", "30m", "0" = no expiration)
// Agent Pool settings
AgentPoolEnabled *bool `json:"agent_pool_enabled,omitempty"`
AgentPoolDefaultModel *string `json:"agent_pool_default_model,omitempty"`
AgentPoolEmbeddingModel *string `json:"agent_pool_embedding_model,omitempty"`
AgentPoolMaxChunkingSize *int `json:"agent_pool_max_chunking_size,omitempty"`
AgentPoolChunkOverlap *int `json:"agent_pool_chunk_overlap,omitempty"`
AgentPoolEnableLogs *bool `json:"agent_pool_enable_logs,omitempty"`
AgentPoolCollectionDBPath *string `json:"agent_pool_collection_db_path,omitempty"`
AgentPoolVectorEngine *string `json:"agent_pool_vector_engine,omitempty"` // chromem | postgres
AgentPoolDatabaseURL *string `json:"agent_pool_database_url,omitempty"` // PostgreSQL DSN when vector engine is postgres
AgentPoolAgentHubURL *string `json:"agent_pool_agent_hub_url,omitempty"` // override the agenthub.localai.io endpoint
// Distributed-mode settings. Read LIVE by the SmartRouter on each
// scheduling decision, so toggling takes effect on the next placement
// without a restart. Stored as the negation of
// DistributedConfig.DiskHeadroomDisabled for UI clarity.
DistributedDiskHeadroomCheck *bool `json:"distributed_disk_headroom_check,omitempty"` // Reject nodes without room to store the model (default: true)
// LocalAI Assistant settings — read live by the chat handler at request
// entry, so flipping the toggle takes effect on the next request.
LocalAIAssistantEnabled *bool `json:"localai_assistant_enabled,omitempty"` // negation of DisableLocalAIAssistant for UI clarity
// Branding / whitelabeling. Text fields are user-facing; *File fields hold
// just the basename of an uploaded asset under {DynamicConfigsDir}/branding/.
// All optional — empty values fall back to bundled LocalAI defaults.
InstanceName *string `json:"instance_name,omitempty"`
InstanceTagline *string `json:"instance_tagline,omitempty"`
LogoFile *string `json:"logo_file,omitempty"`
LogoHorizontalFile *string `json:"logo_horizontal_file,omitempty"`
FaviconFile *string `json:"favicon_file,omitempty"`
// Cloud-proxy MITM listener. MITMCADir is intentionally NOT
// exposed at runtime — the CA dir is a startup-only path and
// changing it after the CA has been generated would orphan
// trusted clients.
MITMListen *string `json:"mitm_listen,omitempty"`
// PIIDefaultDetectors are the token-classification detector models applied
// to any PII-enabled model that names no detectors of its own (so
// cloud-proxy/MITM redaction works without per-model config). No omitempty:
// an empty array must round-trip so the operator can clear it from the UI.
PIIDefaultDetectors *[]string `json:"pii_default_detectors"`
}