Files
coder/coderd/x/chatd/model_routing.go
T
Cian Johnston 843754a547 refactor(coderd/x/chatd): remove dead model-routing dispatch shim (#26942)
Follow-up to #26862 ("remove direct chat routing"), which collapsed the
routing discriminated union into a single `aiGatewayModelRoute` but left
a one-path dispatch shim behind in `model_routing.go`.

Removes
`resolveModelRouteForConfig`/`resolveModelRouteForProviderType`/`newModel`
wrapper functions that did nothing but call their `*AIGateway*`
counterparts, and renames the `*AIGateway*` targets to take over those
names directly. Also collapses a redundant if/else in
`title_override.go` where both branches called the same function with
the same effective argument, and has `chatutil.NormalizedStringPointer`
delegate to the existing `coderd/util/strings.EmptyToNil` instead of
reimplementing empty-string-to-nil logic.

No behavior change.

<details>
<summary>Investigation notes / decision log</summary>

Two independent read-only investigations were run over `coderd/x/chatd`
looking for cleanup opportunities following #26862: one focused on
residue from that PR specifically, one a general over-engineering pass
on the whole package. Both independently converged on the
`model_routing.go` shim as the top finding (verified zero divergent call
sites).

Other candidates considered and explicitly deferred/rejected for this
PR:

- Renaming away the vestigial `AIGateway` prefix package-wide:
cosmetic-only, touches many call sites, skipped.
- Inlining the `chatcost` subpackage into `chatd`: unrelated to #26862,
skipped.
- Deleting the deprecated `AIGatewayRoutingEnabled` deployment flag:
confirmed dead/no-op, but intentionally kept as a back-compat shim per
#26862; removal should follow the same deprecation cadence as other
deprecated deployment options, as a separate, differently-timed change.
- Folding `chatutil` entirely into `chatprovider`/`chatopenai`:
`NormalizedStringPointer` overlapped with
`coderd/util/strings.EmptyToNil` (now reused), but `NormalizedEnumValue`
has no equivalent elsewhere in the repo and still has 2 real call sites,
so the package stays.

</details>

---
Generated by Coder Agents on behalf of @johnstcn.
2026-07-02 11:22:56 +01:00

87 lines
2.2 KiB
Go

package chatd
import (
"context"
"net/http"
"charm.land/fantasy"
"github.com/google/uuid"
"golang.org/x/xerrors"
"github.com/coder/coder/v2/coderd/aibridge"
"github.com/coder/coder/v2/coderd/database"
"github.com/coder/coder/v2/coderd/x/chatd/chatprovider"
)
type modelClientRequest struct {
Chat database.Chat
ModelName string
UserAgent string
ExtraHeaders map[string]string
}
type modelBuildOptions struct {
ActiveAPIKeyID string
RecordHTTP bool
}
func modelBuildOptionsFromMessages(messages []database.ChatMessage) modelBuildOptions {
apiKeyID, _ := activeTurnAPIKeyIDFromMessages(messages)
return modelBuildOptions{ActiveAPIKeyID: apiKeyID}
}
// withActiveTurnAPIKeyID augments ctx with the active turn's delegated API
// key ID when one is known. AI Gateway routing and subagent tool callbacks
// read this value from the context to attribute requests to the correct
// turn. When no key is known, ctx is returned unchanged.
func withActiveTurnAPIKeyID(ctx context.Context, opts modelBuildOptions) context.Context {
if opts.ActiveAPIKeyID == "" {
return ctx
}
return aibridge.WithDelegatedAPIKeyID(ctx, opts.ActiveAPIKeyID)
}
func (p *Server) enabledAIProviderByID(ctx context.Context, providerID uuid.UUID) (database.AIProvider, error) {
provider, err := p.db.GetAIProviderByID(ctx, providerID)
if err != nil {
return database.AIProvider{}, xerrors.Errorf("get AI provider: %w", err)
}
if !provider.Enabled {
return database.AIProvider{}, xerrors.Errorf("AI provider %s is disabled", provider.ID)
}
return provider, nil
}
func newLanguageModel(
providerHint string,
modelName string,
providerKeys chatprovider.ProviderAPIKeys,
userAgent string,
extraHeaders map[string]string,
httpClient *http.Client,
) (fantasy.LanguageModel, error) {
model, err := chatprovider.ModelFromConfig(
providerHint,
modelName,
providerKeys,
userAgent,
extraHeaders,
httpClient,
)
if err != nil {
return nil, err
}
if model == nil {
provider, resolvedModel, resolveErr := chatprovider.ResolveModelWithProviderHint(modelName, providerHint)
if resolveErr != nil {
return nil, resolveErr
}
return nil, xerrors.Errorf(
"create model for %s/%s returned nil",
provider,
resolvedModel,
)
}
return model, nil
}