Files
coder/coderd/x/chatd/chatstate_bridge.go
T
Michael Suchacz 4ed6fcced7 refactor(coderd): stop storing chat gateway key IDs and drop the columns (#27171)
> Mux is working on behalf of Mike.

## Summary

Stop reading and writing the legacy `api_key_id` columns on chat
messages and queued messages, and drop the columns in the same PR.
Runtime AI Gateway attribution continues to use the per-user synthetic
key introduced by #27170.

With the columns gone, `sqlc` generates `database.ChatMessage` and
`database.ChatQueuedMessage` without `api_key_id`, so no transitional
query scaffolding is needed.

Migration `000548` drops the `api_key_id` columns. #27170 already
removed their foreign keys, so the down migration re-adds nullable text
columns without constraints. Previous column values cannot be restored.

Also moves the model config validation in `CreateChat` above the
message-building work so a disabled or invalid model fails fast. On main
this mattered more: the old ordering minted a synthetic API key before
rejecting the request.

Deploy note: replicas still running the previous release write
`api_key_id` on insert, so chat message inserts on old replicas fail
during the rolling window after the column drop. This was previously
split across two PRs to avoid that window; per review feedback the split
added more churn than it was worth for an experimental surface.

Depends on #27170 (merged).
2026-07-20 19:49:19 +02:00

56 lines
2.1 KiB
Go

package chatd
import (
"github.com/google/uuid"
"github.com/sqlc-dev/pqtype"
"github.com/coder/coder/v2/coderd/database"
"github.com/coder/coder/v2/coderd/x/chatd/chatprompt"
"github.com/coder/coder/v2/coderd/x/chatd/chatstate"
)
// newChatMachine constructs a chat-scoped state machine handle bound to
// the server's database and pubsub.
func (p *Server) newChatMachine(chatID uuid.UUID) *chatstate.ChatMachine {
return chatstate.NewChatMachine(p.db, p.pubsub, chatID)
}
// systemMessage builds a chatstate.Message representing a system
// prompt entry for the initial-history slice of CreateChat.
func systemMessage(rawContent pqtype.NullRawMessage, modelConfigID uuid.UUID) chatstate.Message {
return chatstate.Message{
Role: database.ChatMessageRoleSystem,
Content: rawContent,
Visibility: database.ChatMessageVisibilityModel,
ModelConfigID: uuid.NullUUID{UUID: modelConfigID, Valid: modelConfigID != uuid.Nil},
ContentVersion: chatprompt.CurrentContentVersion,
}
}
func userMessage(rawContent pqtype.NullRawMessage, modelConfigID, createdBy uuid.UUID, reasoningEffort *string) chatstate.Message {
var effort database.NullChatReasoningEffort
if reasoningEffort != nil && *reasoningEffort != "" {
effort = database.NullChatReasoningEffort{ChatReasoningEffort: database.ChatReasoningEffort(*reasoningEffort), Valid: true}
}
return chatstate.Message{
Role: database.ChatMessageRoleUser,
Content: rawContent,
Visibility: database.ChatMessageVisibilityBoth,
ModelConfigID: uuid.NullUUID{UUID: modelConfigID, Valid: modelConfigID != uuid.Nil},
ReasoningEffort: effort,
CreatedBy: uuid.NullUUID{UUID: createdBy, Valid: createdBy != uuid.Nil},
ContentVersion: chatprompt.CurrentContentVersion,
}
}
// busyBehaviorToChatState converts the public busy-behavior enum used
// by the server API to the chatstate variant.
func busyBehaviorToChatState(b SendMessageBusyBehavior) chatstate.BusyBehavior {
switch b {
case SendMessageBusyBehaviorInterrupt:
return chatstate.BusyBehaviorInterrupt
default:
return chatstate.BusyBehaviorQueue
}
}