mirror of
https://github.com/coder/coder.git
synced 2026-10-31 19:36:41 +08:00
Moves chat model override settings from deployment scope to organization scope, following the org-scoping of chat model configs in #28440. Depends on #28440 (based on `ethan/chat-models-availability-consolidation`). Remote dogfood UAT passed on this change, including multi-organization scenarios on a licensed deployment with real models. ## Problem Chat model configs are now owned by organizations, but the override settings that reference them stayed deployment-wide: admin subagent/title/compaction overrides in `site_configs`, personal overrides in `user_configs`, and the advisor model embedded in the advisor runtime JSON. A single deployment-level override can only point at one organization's model config, so overrides effectively worked for the default organization only, and title generation had to soften its hard-failure contract to tolerate unusable overrides. ## Fix Admin overrides (general, explore, title generation, compaction, advisor) and personal overrides (root, general, explore) become organization-scoped rows in two new typed tables, `chat_organization_model_overrides` and `chat_user_model_overrides`. Composite foreign keys on `(organization_id, model_config_id)` make cross-organization model references unrepresentable. The migration deletes the legacy serialized `site_configs`/`user_configs` override keys instead of migrating them; admins and users re-select models in the new organization-scoped settings. New endpoints live under `/api/experimental/organizations/{organization}/chats/model-overrides` (admin defaults) and `/api/experimental/organizations/{organization}/members/{user}/chats/model-overrides` (personal overrides); the legacy deployment-level routes are removed. chatd resolves overrides via the chat's organization, restoring the hard-failure contract for configured-but-unusable title generation overrides. The deployment-level `AllowUsers` switch and advisor runtime limits stay deployment-scoped. The Coder Agents settings UI gains a per-organization "Defaults & overrides" page under AI Settings > Models, and the personal overrides page gains an organization selector for users in multiple organizations. Advisor telemetry now reports per-organization override rows. **BREAKING CHANGE**: Existing deployment-level overrides are dropped, not migrated. Every organization starts with no overrides after upgrade, and model selections must be re-applied in the new settings. The legacy deployment-level override endpoints are removed. Closes https://linear.app/coder/issue/CODAGT-872 > [!NOTE] > Xum (AI agent) authored this PR on behalf of @ibetitsmike. <!-- xum-attribution: model=claude-opus-4-6 thinking=high --> --------- Co-authored-by: Ethan Dickson <ethan@coder.com>
55 lines
1.0 KiB
Go
55 lines
1.0 KiB
Go
// Package ptr contains some utility methods related to pointers.
|
|
package ptr
|
|
|
|
import (
|
|
"database/sql"
|
|
|
|
"golang.org/x/exp/constraints"
|
|
)
|
|
|
|
type number interface {
|
|
constraints.Integer | constraints.Float
|
|
}
|
|
|
|
// Ref returns a reference to v.
|
|
func Ref[T any](v T) *T {
|
|
return &v
|
|
}
|
|
|
|
// NilOrEmpty returns true if s is nil or the empty string.
|
|
func NilOrEmpty(s *string) bool {
|
|
return s == nil || *s == ""
|
|
}
|
|
|
|
// NilToEmpty coalesces a nil value to the empty value.
|
|
func NilToEmpty[T any](s *T) T {
|
|
var def T
|
|
if s == nil {
|
|
return def
|
|
}
|
|
return *s
|
|
}
|
|
|
|
// NilToDefault coalesces a nil value to the provided default value.
|
|
func NilToDefault[T any](s *T, def T) T {
|
|
if s == nil {
|
|
return def
|
|
}
|
|
return *s
|
|
}
|
|
|
|
// NilOrZero returns true if v is nil or 0.
|
|
func NilOrZero[T number](v *T) bool {
|
|
return v == nil || *v == 0
|
|
}
|
|
|
|
// FromNullString returns a pointer to the string when it is valid and nil
|
|
// otherwise.
|
|
func FromNullString(v sql.NullString) *string {
|
|
if !v.Valid {
|
|
return nil
|
|
}
|
|
value := v.String
|
|
return &value
|
|
}
|