canonicalProviderKind function

String canonicalProviderKind(
  1. String id
)

The canonical PERSISTED identity for a provider id (issue #772): the catalog entry's adapter ProviderSpec.kind. Config files (provider:, folder model state, handoffs) carry the kind — the name (chatgpt) is display/command sugar that resolves here, in ONE place.

Only UNIQUE-kind entries canonicalize: when several catalog entries share one kind (openai-completions is openrouter/openai/kimi/codemie), the kind is coarser than the saved name and the name stays (the endpoint base URL carries the identity there). A kind owned by exactly one entry (chatgpt-codex → chatgpt) folds its name-shaped spellings onto the kind. Alias spellings (chatgpt.com) fold first via canonicalProviderName at the config boundary. Unknown ids return unchanged — the boot boundary warns and degrades (issue #760), it never rewrites a value it cannot resolve.

Implementation

String canonicalProviderKind(String id) {
  final spec = resolveCliProviderSpec(id);
  if (spec == null) return id;
  for (final other in providerCatalog.values) {
    if (other.kind == spec.kind && other.name != spec.name) return id;
  }
  return spec.kind;
}