Files
coder/coderd/x/chatd/title_override.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.7 KiB
Go

package chatd
import (
"context"
"charm.land/fantasy"
"github.com/google/uuid"
"golang.org/x/xerrors"
"github.com/coder/coder/v2/coderd/database"
"github.com/coder/coder/v2/coderd/database/dbauthz"
"github.com/coder/coder/v2/coderd/x/chatd/chatprovider"
)
const titleGenerationOverrideContext = "title_generation"
func readTitleGenerationModelOverride(
ctx context.Context,
db database.Store,
) (string, error) {
//nolint:gocritic // Chatd is internal, not a user, so this read uses AsChatd.
chatdCtx := dbauthz.AsChatd(ctx)
raw, err := db.GetChatTitleGenerationModelOverride(chatdCtx)
if err != nil {
return "", xerrors.Errorf(
"get chat title generation model override: %w",
err,
)
}
return raw, nil
}
// resolveTitleGenerationModelOverride resolves the deployment-wide title
// generation model override. overrideSet is true when an override was
// configured; in that case any returned error is a hard failure. When
// overrideSet is false, callers may fall back to the default title model.
func (p *Server) resolveTitleGenerationModelOverride(
ctx context.Context,
chat database.Chat,
modelOpts modelBuildOptions,
) (database.ChatModelConfig, fantasy.LanguageModel, aiGatewayModelRoute, bool, error) {
raw, err := readTitleGenerationModelOverride(ctx, p.db)
if err != nil {
return database.ChatModelConfig{}, nil, aiGatewayModelRoute{}, false, xerrors.Errorf(
"read title generation model override: %w",
err,
)
}
modelConfig, overrideSet, err := p.resolveConfiguredModelOverride(
ctx,
titleGenerationOverrideContext,
raw,
chat.OwnerID,
p.resolveModelConfigAndNormalizedProvider,
func(ctx context.Context, ownerID uuid.UUID, aiProviderID uuid.UUID) (chatprovider.ProviderAPIKeys, error) {
return p.resolveUserProviderAPIKeys(ctx, ownerID, aiProviderID)
},
modelOverrideFailureModeHard,
)
if err != nil {
return database.ChatModelConfig{}, nil, aiGatewayModelRoute{}, overrideSet, err
}
if !overrideSet {
return database.ChatModelConfig{}, nil, aiGatewayModelRoute{}, false, nil
}
//nolint:gocritic // Title overrides need chatd-scoped provider reads for user-owned chats.
route, err := p.resolveModelRouteForConfig(dbauthz.AsChatd(ctx), chat.OwnerID, modelConfig)
if err != nil {
return database.ChatModelConfig{}, nil, aiGatewayModelRoute{}, true, err
}
model, err := p.newModel(ctx, modelClientRequest{
Chat: chat,
ModelName: modelConfig.Model,
UserAgent: chatprovider.UserAgent(),
ExtraHeaders: chatprovider.CoderHeaders(chat),
}, route, modelOpts)
if err != nil {
return database.ChatModelConfig{}, nil, aiGatewayModelRoute{}, true, xerrors.Errorf(
"create title generation model override: %w",
err,
)
}
return modelConfig, model, route, true, nil
}