(ctx context.Context, cfg *latest.Config, a *latest.AgentConfig, autoModelFn func() latest.ModelConfig, dmrFallbackSelectors map[string]bool, runConfig *config.RuntimeConfig, providerRegistry *provider.Registry)
| 420 | } |
| 421 | |
| 422 | func getModelsForAgent(ctx context.Context, cfg *latest.Config, a *latest.AgentConfig, autoModelFn func() latest.ModelConfig, dmrFallbackSelectors map[string]bool, runConfig *config.RuntimeConfig, providerRegistry *provider.Registry) ([]provider.Provider, error) { |
| 423 | var models []provider.Provider |
| 424 | |
| 425 | // Obtain the singleton store once, outside the loop. |
| 426 | modelsStore, modelsStoreErr := runConfig.ModelsDevStore() |
| 427 | |
| 428 | for name := range strings.SplitSeq(a.Model, ",") { |
| 429 | modelCfg, exists := cfg.Models[name] |
| 430 | isAutoModel := false |
| 431 | if !exists { |
| 432 | if name == "auto" { |
| 433 | modelCfg = autoModelFn() |
| 434 | isAutoModel = true |
| 435 | } else { |
| 436 | return nil, fmt.Errorf("model '%s' not found in configuration", name) |
| 437 | } |
| 438 | } |
| 439 | // A `first_available` selector that fell back to Docker Model Runner with |
| 440 | // no usable local model is, like `auto`, a best-effort selection: surface |
| 441 | // init failures as a "no model available" fallback rather than a raw |
| 442 | // pull error. |
| 443 | if dmrFallbackSelectors[name] { |
| 444 | isAutoModel = true |
| 445 | } |
| 446 | modelCfg.Name = name |
| 447 | |
| 448 | // Use max_tokens from config if specified, otherwise look up from models.dev |
| 449 | maxTokens := &defaultMaxTokens |
| 450 | if modelCfg.MaxTokens != nil { |
| 451 | maxTokens = modelCfg.MaxTokens |
| 452 | } else if modelsStoreErr == nil { |
| 453 | m, err := modelsStore.GetModel(ctx, modelsdev.NewID(modelCfg.Provider, modelCfg.Model)) |
| 454 | if err == nil { |
| 455 | maxTokens = &m.Limit.Output |
| 456 | } |
| 457 | } |
| 458 | |
| 459 | opts := []options.Opt{ |
| 460 | options.WithGateway(runConfig.ModelsGateway), |
| 461 | options.WithStructuredOutput(a.StructuredOutput), |
| 462 | options.WithProviders(cfg.Providers), |
| 463 | } |
| 464 | if maxTokens != nil { |
| 465 | opts = append(opts, options.WithMaxTokens(*maxTokens)) |
| 466 | } |
| 467 | if modelsStoreErr == nil { |
| 468 | opts = append(opts, options.WithModelsDevStore(modelsStore)) |
| 469 | } |
| 470 | |
| 471 | // Pass the full models map for routing rules to resolve model references |
| 472 | model, err := providerRegistry.NewWithModels(ctx, |
| 473 | &modelCfg, |
| 474 | cfg.Models, |
| 475 | runConfig.EnvProvider(), |
| 476 | opts..., |
| 477 | ) |
| 478 | if err != nil { |
| 479 | // Return a cleaner error message for auto model selection failures, |
no test coverage detected