| 238 | type AppOption func(*ApplicationConfig) |
| 239 | |
| 240 | func NewApplicationConfig(o ...AppOption) *ApplicationConfig { |
| 241 | opt := &ApplicationConfig{ |
| 242 | Context: context.Background(), |
| 243 | UploadLimitMB: 15, |
| 244 | Debug: true, |
| 245 | AgentJobRetentionDays: 30, // Default: 30 days |
| 246 | LRUEvictionMaxRetries: 30, // Default: 30 retries |
| 247 | LRUEvictionRetryInterval: 1 * time.Second, // Default: 1 second |
| 248 | // WatchDogInterval is intentionally left at the zero value here. |
| 249 | // The startup loader applies a persisted runtime_settings.json value |
| 250 | // only when the interval is still 0 (its "not set by env var" |
| 251 | // heuristic, matching the idle/busy timeouts); a non-zero baseline |
| 252 | // default would defeat that and silently revert a UI-saved Check |
| 253 | // Interval to the default on every restart (#10601). The effective |
| 254 | // 500ms default is supplied at the watchdog layer (DefaultWatchdogInterval) |
| 255 | // when the value is still 0. |
| 256 | TracingMaxItems: 1024, |
| 257 | TracingMaxBodyBytes: 64 * 1024, // 64 KiB - caps each request/response body in the trace buffer |
| 258 | AgentPool: AgentPoolConfig{ |
| 259 | Enabled: true, |
| 260 | Timeout: "5m", |
| 261 | VectorEngine: "chromem", |
| 262 | EmbeddingModel: "granite-embedding-107m-multilingual", |
| 263 | MaxChunkingSize: 400, |
| 264 | AgentHubURL: "https://agenthub.localai.io", |
| 265 | }, |
| 266 | PathWithoutAuth: []string{ |
| 267 | "/static/", |
| 268 | "/generated-audio/", |
| 269 | "/generated-images/", |
| 270 | "/generated-videos/", |
| 271 | "/favicon.svg", |
| 272 | "/readyz", |
| 273 | "/healthz", |
| 274 | "/api/auth/", |
| 275 | "/assets/", |
| 276 | // Branding read endpoint + public asset server. The login |
| 277 | // screen renders before authentication completes, so it has |
| 278 | // to be able to GET /api/branding and the configured logo. |
| 279 | // |
| 280 | // IMPORTANT: PathWithoutAuth uses a prefix match (see |
| 281 | // auth.isExemptPath). The "/api/branding" entry therefore |
| 282 | // also exempts POST/DELETE /api/branding/asset/:kind from |
| 283 | // the *global* auth middleware. Those routes are still |
| 284 | // admin-gated because they are registered with the |
| 285 | // route-level adminMiddleware (auth.RequireAdmin) in |
| 286 | // core/http/routes/ui_api.go — that's what keeps anonymous |
| 287 | // uploads/deletes returning 401. Any new admin-only sub-route |
| 288 | // added under /api/branding/* MUST also carry adminMiddleware |
| 289 | // at the route registration site, otherwise it ships |
| 290 | // unauthenticated. The TestBrandingRoutes_AdminGatingHolds |
| 291 | // integration test in core/http/auth pins this contract. |
| 292 | "/api/branding", |
| 293 | "/branding/", |
| 294 | }, |
| 295 | } |
| 296 | for _, oo := range o { |
| 297 | oo(opt) |