mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
chore: add client_type field to chats and telemetry (#24342)
Add a `chat_client_type` enum (`ui` | `api`) and `client_type` column to the `chats` table. The column defaults to `api` for new rows so API callers don't need to set it explicitly. Existing rows are backfilled to `ui`. The field flows through `CreateChatRequest`, `chatd.CreateOptions`, `InsertChat`, and is returned in the `Chat` response via `db2sdk`. <details> <summary>Implementation notes (Coder Agents generated)</summary> ### Changes **Database migration (000469)** - New enum `chat_client_type` with values `ui`, `api`. - New `client_type` column, `NOT NULL DEFAULT 'api'`. - Backfill: `UPDATE chats SET client_type = 'ui'`. **SQL query** — `InsertChat` now includes `client_type`. **SDK** — `ChatClientType` type added; `ClientType` field added to both `CreateChatRequest` (optional, defaults server-side to `api`) and `Chat` response. **Handler** — `postChats` maps the request field (defaulting to `api`) and passes it through `chatd.CreateOptions`. **Sub-agent** — Child chats inherit their parent's `client_type`. **db2sdk** — Maps the database value to the SDK type. ### Decision log - Default is `api` (not `ui`) so existing API integrations get the correct value without code changes. - Backfill sets existing rows to `ui` per requirement. - Child chats inherit `client_type` from parent rather than defaulting. </details>
This commit is contained in:
@@ -1107,6 +1107,64 @@ func AllBuildReasonValues() []BuildReason {
|
||||
}
|
||||
}
|
||||
|
||||
type ChatClientType string
|
||||
|
||||
const (
|
||||
ChatClientTypeUi ChatClientType = "ui"
|
||||
ChatClientTypeApi ChatClientType = "api"
|
||||
)
|
||||
|
||||
func (e *ChatClientType) Scan(src interface{}) error {
|
||||
switch s := src.(type) {
|
||||
case []byte:
|
||||
*e = ChatClientType(s)
|
||||
case string:
|
||||
*e = ChatClientType(s)
|
||||
default:
|
||||
return fmt.Errorf("unsupported scan type for ChatClientType: %T", src)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type NullChatClientType struct {
|
||||
ChatClientType ChatClientType `json:"chat_client_type"`
|
||||
Valid bool `json:"valid"` // Valid is true if ChatClientType is not NULL
|
||||
}
|
||||
|
||||
// Scan implements the Scanner interface.
|
||||
func (ns *NullChatClientType) Scan(value interface{}) error {
|
||||
if value == nil {
|
||||
ns.ChatClientType, ns.Valid = "", false
|
||||
return nil
|
||||
}
|
||||
ns.Valid = true
|
||||
return ns.ChatClientType.Scan(value)
|
||||
}
|
||||
|
||||
// Value implements the driver Valuer interface.
|
||||
func (ns NullChatClientType) Value() (driver.Value, error) {
|
||||
if !ns.Valid {
|
||||
return nil, nil
|
||||
}
|
||||
return string(ns.ChatClientType), nil
|
||||
}
|
||||
|
||||
func (e ChatClientType) Valid() bool {
|
||||
switch e {
|
||||
case ChatClientTypeUi,
|
||||
ChatClientTypeApi:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func AllChatClientTypeValues() []ChatClientType {
|
||||
return []ChatClientType{
|
||||
ChatClientTypeUi,
|
||||
ChatClientTypeApi,
|
||||
}
|
||||
}
|
||||
|
||||
type ChatMessageRole string
|
||||
|
||||
const (
|
||||
@@ -4303,6 +4361,7 @@ type Chat struct {
|
||||
DynamicTools pqtype.NullRawMessage `db:"dynamic_tools" json:"dynamic_tools"`
|
||||
OrganizationID uuid.UUID `db:"organization_id" json:"organization_id"`
|
||||
PlanMode NullChatPlanMode `db:"plan_mode" json:"plan_mode"`
|
||||
ClientType ChatClientType `db:"client_type" json:"client_type"`
|
||||
}
|
||||
|
||||
type ChatDebugRun struct {
|
||||
|
||||
Reference in New Issue
Block a user