buildCatalogModel function

Model buildCatalogModel(
  1. String provider,
  2. String modelId, {
  3. String? baseUrl,
  4. int? contextWindow,
  5. int? maxTokens,
  6. List<String>? input,
  7. String? thinkingLevel,
  8. String? authHeader,
  9. Duration? connectTimeout,
  10. Duration? streamIdleTimeout,
  11. String? timeoutScopeLabel,
})

Builds a Model for provider/modelId with catalog defaults, overrid- able per reference (see ModelRef).

maxTokens resolution order: the capability override layer (modelCapabilityOverrides, gh-1426), the explicit override, then the Claude ceiling table (resolveModelMaxOutputTokens), then the provider spec default — per-model reality beats the blanket 16384. The same layered precedence governs contextWindow and thinkingLevel, and an override's omitMaxOutputTokens lands on the model compat (AC7).

Throws ConfigException for unknown providers.

Implementation

Model buildCatalogModel(
  String provider,
  String modelId, {
  String? baseUrl,
  int? contextWindow,
  int? maxTokens,
  List<String>? input,
  String? thinkingLevel,
  String? authHeader,
  Duration? connectTimeout,
  Duration? streamIdleTimeout,
  String? timeoutScopeLabel,
}) {
  final spec = catalogProvider(provider);
  if (spec == null) {
    throw ConfigException(
      'unknown provider "$provider" — supported providers: '
      '${providerCatalog.keys.join(', ')}',
    );
  }
  validateAuthHeaderDialect(authHeader, spec, 'provider "$provider"');
  final caps = resolveModelCapabilities(
    provider: spec.name,
    modelId: modelId,
    override: modelCapabilityOverrides?.lookup(spec.name, modelId),
    roleContextWindow: contextWindow,
    roleMaxTokens: maxTokens,
    roleThinkingLevel: thinkingLevel,
    spec: spec,
    api: spec.api,
    reasoning: spec.reasoning,
  );
  return Model(
    id: modelId,
    name: modelId,
    api: spec.api,
    provider: spec.name,
    baseUrl: baseUrl ?? spec.defaultBaseUrl,
    reasoning: spec.reasoning,
    input: input ?? spec.input,
    thinkingLevel: caps.thinkingLevel,
    contextWindow: caps.contextWindow,
    maxTokens: caps.maxTokens,
    authHeader: authHeader,
    // The omit-compat flag rides the model compat (AC7); every other
    // compat field stays null so the adapter's auto-detection applies.
    compat: caps.omitMaxOutputTokens
        ? const OpenAICompletionsCompat(omitMaxOutputTokens: true)
        : null,
    // The resolver's loud notes (E1 divergence, E3 gate, E4 catalog miss)
    // ride the model so the status surfaces can render them — never
    // dropped at the build boundary (gh-1426 rework).
    capabilityNotes: caps.notes,
    // Request-scoped watchdog windows from a roles chain entry (issue
    // #1554): the top precedence layer, riding the model like every other
    // per-entry config field (thinkingLevel/authHeader precedent).
    connectTimeout: connectTimeout,
    streamIdleTimeout: streamIdleTimeout,
    timeoutScopeLabel: timeoutScopeLabel,
  );
}