mirror of
https://github.com/coder/coder.git
synced 2026-10-31 11:02:50 +08:00
feat!: scope chat model override settings to organizations (#28442)
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>
This commit is contained in:
co-authored by
Ethan Dickson
parent
3809314b31
commit
0ef331fcd0
Generated
+350
@@ -1359,6 +1359,106 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/experimental/organizations/{organization}/chats/model-overrides": {
|
||||
"get": {
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Chats"
|
||||
],
|
||||
"summary": "List organization chat model overrides",
|
||||
"operationId": "list-organization-chat-model-overrides",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Organization name or ID",
|
||||
"name": "organization",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/codersdk.ChatModelOverridesResponse"
|
||||
}
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"CoderSessionToken": []
|
||||
}
|
||||
],
|
||||
"x-apidocgen": {
|
||||
"skip": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/experimental/organizations/{organization}/chats/model-overrides/{context}": {
|
||||
"put": {
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Chats"
|
||||
],
|
||||
"summary": "Update organization chat model override",
|
||||
"operationId": "update-organization-chat-model-override",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Organization name or ID",
|
||||
"name": "organization",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"enum": [
|
||||
"general",
|
||||
"explore",
|
||||
"title_generation",
|
||||
"compaction",
|
||||
"advisor"
|
||||
],
|
||||
"type": "string",
|
||||
"description": "Override context",
|
||||
"name": "context",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"description": "Model override",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/codersdk.UpdateChatModelOverrideRequest"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/codersdk.ChatModelOverrideResponse"
|
||||
}
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"CoderSessionToken": []
|
||||
}
|
||||
],
|
||||
"x-apidocgen": {
|
||||
"skip": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/experimental/organizations/{organization}/chats/models": {
|
||||
"get": {
|
||||
"produces": [
|
||||
@@ -2036,6 +2136,112 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/experimental/organizations/{organization}/members/{user}/chats/model-overrides": {
|
||||
"get": {
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Chats"
|
||||
],
|
||||
"summary": "Get organization member chat model overrides",
|
||||
"operationId": "get-organization-member-chat-model-overrides",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Organization name or ID",
|
||||
"name": "organization",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "User name, ID, or me",
|
||||
"name": "user",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/codersdk.UserChatPersonalModelOverridesResponse"
|
||||
}
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"CoderSessionToken": []
|
||||
}
|
||||
],
|
||||
"x-apidocgen": {
|
||||
"skip": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/experimental/organizations/{organization}/members/{user}/chats/model-overrides/{context}": {
|
||||
"put": {
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Chats"
|
||||
],
|
||||
"summary": "Update organization member chat model override",
|
||||
"operationId": "update-organization-member-chat-model-override",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Organization name or ID",
|
||||
"name": "organization",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "User name, ID, or me",
|
||||
"name": "user",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"enum": [
|
||||
"root",
|
||||
"general",
|
||||
"explore"
|
||||
],
|
||||
"type": "string",
|
||||
"description": "Override context",
|
||||
"name": "context",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"description": "Personal model override",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/codersdk.UpdateUserChatPersonalModelOverrideRequest"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"204": {
|
||||
"description": "No Content"
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"CoderSessionToken": []
|
||||
}
|
||||
],
|
||||
"x-apidocgen": {
|
||||
"skip": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/experimental/users/{user}/skills": {
|
||||
"get": {
|
||||
"produces": [
|
||||
@@ -19280,6 +19486,48 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"codersdk.ChatModelOverrideContext": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"general",
|
||||
"explore",
|
||||
"title_generation",
|
||||
"compaction",
|
||||
"advisor"
|
||||
],
|
||||
"x-enum-varnames": [
|
||||
"ChatModelOverrideContextGeneral",
|
||||
"ChatModelOverrideContextExplore",
|
||||
"ChatModelOverrideContextTitleGeneration",
|
||||
"ChatModelOverrideContextCompaction",
|
||||
"ChatModelOverrideContextAdvisor"
|
||||
]
|
||||
},
|
||||
"codersdk.ChatModelOverrideResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"context": {
|
||||
"$ref": "#/definitions/codersdk.ChatModelOverrideContext"
|
||||
},
|
||||
"model_config_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"reasoning_effort": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"codersdk.ChatModelOverridesResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"overrides": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/codersdk.ChatModelOverrideResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"codersdk.ChatModelProviderDescriptor": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -19431,6 +19679,63 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"codersdk.ChatPersonalModelOverride": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"context": {
|
||||
"$ref": "#/definitions/codersdk.ChatPersonalModelOverrideContext"
|
||||
},
|
||||
"is_set": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"mode": {
|
||||
"$ref": "#/definitions/codersdk.ChatPersonalModelOverrideMode"
|
||||
},
|
||||
"model_config_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"reasoning_effort": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"codersdk.ChatPersonalModelOverrideContext": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"root",
|
||||
"general",
|
||||
"explore"
|
||||
],
|
||||
"x-enum-varnames": [
|
||||
"ChatPersonalModelOverrideContextRoot",
|
||||
"ChatPersonalModelOverrideContextGeneral",
|
||||
"ChatPersonalModelOverrideContextExplore"
|
||||
]
|
||||
},
|
||||
"codersdk.ChatPersonalModelOverrideDeploymentDefaults": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"explore": {
|
||||
"$ref": "#/definitions/codersdk.ChatModelOverrideResponse"
|
||||
},
|
||||
"general": {
|
||||
"$ref": "#/definitions/codersdk.ChatModelOverrideResponse"
|
||||
}
|
||||
}
|
||||
},
|
||||
"codersdk.ChatPersonalModelOverrideMode": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"deployment_default",
|
||||
"chat_default",
|
||||
"model"
|
||||
],
|
||||
"x-enum-varnames": [
|
||||
"ChatPersonalModelOverrideModeDeploymentDefault",
|
||||
"ChatPersonalModelOverrideModeChatDefault",
|
||||
"ChatPersonalModelOverrideModeModel"
|
||||
]
|
||||
},
|
||||
"codersdk.ChatPlanMode": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
@@ -27458,6 +27763,17 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"codersdk.UpdateChatModelOverrideRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"model_config_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"reasoning_effort": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"codersdk.UpdateChatModelRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -27872,6 +28188,20 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"codersdk.UpdateUserChatPersonalModelOverrideRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"mode": {
|
||||
"$ref": "#/definitions/codersdk.ChatPersonalModelOverrideMode"
|
||||
},
|
||||
"model_config_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"reasoning_effort": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"codersdk.UpdateUserNotificationPreferences": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -28425,6 +28755,26 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"codersdk.UserChatPersonalModelOverridesResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"deployment_defaults": {
|
||||
"$ref": "#/definitions/codersdk.ChatPersonalModelOverrideDeploymentDefaults"
|
||||
},
|
||||
"enabled": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"explore": {
|
||||
"$ref": "#/definitions/codersdk.ChatPersonalModelOverride"
|
||||
},
|
||||
"general": {
|
||||
"$ref": "#/definitions/codersdk.ChatPersonalModelOverride"
|
||||
},
|
||||
"root": {
|
||||
"$ref": "#/definitions/codersdk.ChatPersonalModelOverride"
|
||||
}
|
||||
}
|
||||
},
|
||||
"codersdk.UserLatency": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
||||
Generated
+320
@@ -1210,6 +1210,96 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/experimental/organizations/{organization}/chats/model-overrides": {
|
||||
"get": {
|
||||
"produces": ["application/json"],
|
||||
"tags": ["Chats"],
|
||||
"summary": "List organization chat model overrides",
|
||||
"operationId": "list-organization-chat-model-overrides",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Organization name or ID",
|
||||
"name": "organization",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/codersdk.ChatModelOverridesResponse"
|
||||
}
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"CoderSessionToken": []
|
||||
}
|
||||
],
|
||||
"x-apidocgen": {
|
||||
"skip": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/experimental/organizations/{organization}/chats/model-overrides/{context}": {
|
||||
"put": {
|
||||
"consumes": ["application/json"],
|
||||
"produces": ["application/json"],
|
||||
"tags": ["Chats"],
|
||||
"summary": "Update organization chat model override",
|
||||
"operationId": "update-organization-chat-model-override",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Organization name or ID",
|
||||
"name": "organization",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"enum": [
|
||||
"general",
|
||||
"explore",
|
||||
"title_generation",
|
||||
"compaction",
|
||||
"advisor"
|
||||
],
|
||||
"type": "string",
|
||||
"description": "Override context",
|
||||
"name": "context",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"description": "Model override",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/codersdk.UpdateChatModelOverrideRequest"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/codersdk.ChatModelOverrideResponse"
|
||||
}
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"CoderSessionToken": []
|
||||
}
|
||||
],
|
||||
"x-apidocgen": {
|
||||
"skip": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/experimental/organizations/{organization}/chats/models": {
|
||||
"get": {
|
||||
"produces": ["application/json"],
|
||||
@@ -1825,6 +1915,100 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/experimental/organizations/{organization}/members/{user}/chats/model-overrides": {
|
||||
"get": {
|
||||
"produces": ["application/json"],
|
||||
"tags": ["Chats"],
|
||||
"summary": "Get organization member chat model overrides",
|
||||
"operationId": "get-organization-member-chat-model-overrides",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Organization name or ID",
|
||||
"name": "organization",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "User name, ID, or me",
|
||||
"name": "user",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/codersdk.UserChatPersonalModelOverridesResponse"
|
||||
}
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"CoderSessionToken": []
|
||||
}
|
||||
],
|
||||
"x-apidocgen": {
|
||||
"skip": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/experimental/organizations/{organization}/members/{user}/chats/model-overrides/{context}": {
|
||||
"put": {
|
||||
"consumes": ["application/json"],
|
||||
"tags": ["Chats"],
|
||||
"summary": "Update organization member chat model override",
|
||||
"operationId": "update-organization-member-chat-model-override",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Organization name or ID",
|
||||
"name": "organization",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "User name, ID, or me",
|
||||
"name": "user",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"enum": ["root", "general", "explore"],
|
||||
"type": "string",
|
||||
"description": "Override context",
|
||||
"name": "context",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"description": "Personal model override",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/codersdk.UpdateUserChatPersonalModelOverrideRequest"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"204": {
|
||||
"description": "No Content"
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"CoderSessionToken": []
|
||||
}
|
||||
],
|
||||
"x-apidocgen": {
|
||||
"skip": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/experimental/users/{user}/skills": {
|
||||
"get": {
|
||||
"produces": ["application/json"],
|
||||
@@ -17436,6 +17620,48 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"codersdk.ChatModelOverrideContext": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"general",
|
||||
"explore",
|
||||
"title_generation",
|
||||
"compaction",
|
||||
"advisor"
|
||||
],
|
||||
"x-enum-varnames": [
|
||||
"ChatModelOverrideContextGeneral",
|
||||
"ChatModelOverrideContextExplore",
|
||||
"ChatModelOverrideContextTitleGeneration",
|
||||
"ChatModelOverrideContextCompaction",
|
||||
"ChatModelOverrideContextAdvisor"
|
||||
]
|
||||
},
|
||||
"codersdk.ChatModelOverrideResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"context": {
|
||||
"$ref": "#/definitions/codersdk.ChatModelOverrideContext"
|
||||
},
|
||||
"model_config_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"reasoning_effort": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"codersdk.ChatModelOverridesResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"overrides": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/codersdk.ChatModelOverrideResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"codersdk.ChatModelProviderDescriptor": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -17583,6 +17809,55 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"codersdk.ChatPersonalModelOverride": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"context": {
|
||||
"$ref": "#/definitions/codersdk.ChatPersonalModelOverrideContext"
|
||||
},
|
||||
"is_set": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"mode": {
|
||||
"$ref": "#/definitions/codersdk.ChatPersonalModelOverrideMode"
|
||||
},
|
||||
"model_config_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"reasoning_effort": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"codersdk.ChatPersonalModelOverrideContext": {
|
||||
"type": "string",
|
||||
"enum": ["root", "general", "explore"],
|
||||
"x-enum-varnames": [
|
||||
"ChatPersonalModelOverrideContextRoot",
|
||||
"ChatPersonalModelOverrideContextGeneral",
|
||||
"ChatPersonalModelOverrideContextExplore"
|
||||
]
|
||||
},
|
||||
"codersdk.ChatPersonalModelOverrideDeploymentDefaults": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"explore": {
|
||||
"$ref": "#/definitions/codersdk.ChatModelOverrideResponse"
|
||||
},
|
||||
"general": {
|
||||
"$ref": "#/definitions/codersdk.ChatModelOverrideResponse"
|
||||
}
|
||||
}
|
||||
},
|
||||
"codersdk.ChatPersonalModelOverrideMode": {
|
||||
"type": "string",
|
||||
"enum": ["deployment_default", "chat_default", "model"],
|
||||
"x-enum-varnames": [
|
||||
"ChatPersonalModelOverrideModeDeploymentDefault",
|
||||
"ChatPersonalModelOverrideModeChatDefault",
|
||||
"ChatPersonalModelOverrideModeModel"
|
||||
]
|
||||
},
|
||||
"codersdk.ChatPlanMode": {
|
||||
"type": "string",
|
||||
"enum": ["plan"],
|
||||
@@ -25275,6 +25550,17 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"codersdk.UpdateChatModelOverrideRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"model_config_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"reasoning_effort": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"codersdk.UpdateChatModelRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -25670,6 +25956,20 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"codersdk.UpdateUserChatPersonalModelOverrideRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"mode": {
|
||||
"$ref": "#/definitions/codersdk.ChatPersonalModelOverrideMode"
|
||||
},
|
||||
"model_config_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"reasoning_effort": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"codersdk.UpdateUserNotificationPreferences": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -26190,6 +26490,26 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"codersdk.UserChatPersonalModelOverridesResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"deployment_defaults": {
|
||||
"$ref": "#/definitions/codersdk.ChatPersonalModelOverrideDeploymentDefaults"
|
||||
},
|
||||
"enabled": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"explore": {
|
||||
"$ref": "#/definitions/codersdk.ChatPersonalModelOverride"
|
||||
},
|
||||
"general": {
|
||||
"$ref": "#/definitions/codersdk.ChatPersonalModelOverride"
|
||||
},
|
||||
"root": {
|
||||
"$ref": "#/definitions/codersdk.ChatPersonalModelOverride"
|
||||
}
|
||||
}
|
||||
},
|
||||
"codersdk.UserLatency": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
||||
+17
-4
@@ -1436,6 +1436,23 @@ func New(options *Options) *API {
|
||||
httpmw.ExtractOrganizationParam(options.Database),
|
||||
).Get("/chats/models", api.listChatModelConfigsByOrganization)
|
||||
|
||||
r.Route("/organizations/{organization}/chats/model-overrides", func(r chi.Router) {
|
||||
r.Use(
|
||||
apiKeyMiddleware,
|
||||
httpmw.ExtractOrganizationParam(options.Database),
|
||||
)
|
||||
r.Get("/", api.getOrganizationChatModelOverrides)
|
||||
r.Put("/{context}", api.putOrganizationChatModelOverride)
|
||||
})
|
||||
r.Route("/organizations/{organization}/members/{user}/chats/model-overrides", func(r chi.Router) {
|
||||
r.Use(
|
||||
apiKeyMiddleware,
|
||||
httpmw.ExtractOrganizationParam(options.Database),
|
||||
httpmw.ExtractOrganizationMemberParam(options.Database),
|
||||
)
|
||||
r.Get("/", api.getUserChatPersonalModelOverrides)
|
||||
r.Put("/{context}", api.putUserChatPersonalModelOverride)
|
||||
})
|
||||
r.Route("/organizations/{organization}/chats/models", func(r chi.Router) {
|
||||
r.Use(apiKeyMiddleware)
|
||||
r.With(httpmw.ExtractOrganizationParam(options.Database)).Get("/", api.listChatModelConfigsByOrganization)
|
||||
@@ -1473,12 +1490,8 @@ func New(options *Options) *API {
|
||||
r.Put("/system-prompt", api.putChatSystemPrompt)
|
||||
r.Get("/plan-mode-instructions", api.getChatPlanModeInstructions)
|
||||
r.Put("/plan-mode-instructions", api.putChatPlanModeInstructions)
|
||||
r.Get("/model-override/{context}", api.getChatModelOverride)
|
||||
r.Put("/model-override/{context}", api.putChatModelOverride)
|
||||
r.Get("/personal-model-overrides", api.getChatPersonalModelOverridesAdminSettings)
|
||||
r.Put("/personal-model-overrides", api.putChatPersonalModelOverridesAdminSettings)
|
||||
r.Get("/user-personal-model-overrides", api.getUserChatPersonalModelOverrides)
|
||||
r.Put("/user-personal-model-overrides/{context}", api.putUserChatPersonalModelOverride)
|
||||
r.Group(func(r chi.Router) {
|
||||
r.Use(httpmw.RequireExperimentWithDevBypass(api.Experiments, codersdk.ExperimentChatVirtualDesktop))
|
||||
r.Get("/computer-use-provider", api.getChatComputerUseProvider)
|
||||
|
||||
Generated
+4
@@ -27,9 +27,13 @@ const (
|
||||
CheckChatModelConfigsContextLimitCheck CheckConstraint = "chat_model_configs_context_limit_check" // chat_model_configs
|
||||
CheckChatModelConfigsGroupAclIsObject CheckConstraint = "chat_model_configs_group_acl_is_object" // chat_model_configs
|
||||
CheckChatModelConfigsUserAclIsObject CheckConstraint = "chat_model_configs_user_acl_is_object" // chat_model_configs
|
||||
CheckChatOrganizationModelOverridesContextCheck CheckConstraint = "chat_organization_model_overrides_context_check" // chat_organization_model_overrides
|
||||
CheckChatUsageLimitConfigDefaultLimitMicrosCheck CheckConstraint = "chat_usage_limit_config_default_limit_micros_check" // chat_usage_limit_config
|
||||
CheckChatUsageLimitConfigPeriodCheck CheckConstraint = "chat_usage_limit_config_period_check" // chat_usage_limit_config
|
||||
CheckChatUsageLimitConfigSingletonCheck CheckConstraint = "chat_usage_limit_config_singleton_check" // chat_usage_limit_config
|
||||
CheckChatUserModelOverridesContextCheck CheckConstraint = "chat_user_model_overrides_context_check" // chat_user_model_overrides
|
||||
CheckChatUserModelOverridesModeCheck CheckConstraint = "chat_user_model_overrides_mode_check" // chat_user_model_overrides
|
||||
CheckChatUserModelOverridesModelRequiresConfigCheck CheckConstraint = "chat_user_model_overrides_model_requires_config_check" // chat_user_model_overrides
|
||||
CheckChatAclOnlyOnRootChats CheckConstraint = "chat_acl_only_on_root_chats" // chats
|
||||
CheckChatGroupAclNotNullJsonb CheckConstraint = "chat_group_acl_not_null_jsonb" // chats
|
||||
CheckChatUserAclNotNullJsonb CheckConstraint = "chat_user_acl_not_null_jsonb" // chats
|
||||
|
||||
@@ -2238,6 +2238,13 @@ func (q *querier) DeleteChatModelConfigByID(ctx context.Context, id uuid.UUID) (
|
||||
return q.db.DeleteChatModelConfigByID(ctx, id)
|
||||
}
|
||||
|
||||
func (q *querier) DeleteChatOrganizationModelOverride(ctx context.Context, arg database.DeleteChatOrganizationModelOverrideParams) error {
|
||||
if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceChatModelConfig.InOrg(arg.OrganizationID)); err != nil {
|
||||
return err
|
||||
}
|
||||
return q.db.DeleteChatOrganizationModelOverride(ctx, arg)
|
||||
}
|
||||
|
||||
func (q *querier) DeleteChatQueuedMessage(ctx context.Context, arg database.DeleteChatQueuedMessageParams) error {
|
||||
chat, err := q.db.GetChatByID(ctx, arg.ChatID)
|
||||
if err != nil {
|
||||
@@ -3185,13 +3192,6 @@ func (q *querier) GetChatByIDForUpdate(ctx context.Context, id uuid.UUID) (datab
|
||||
return fetch(q.log, q.auth, q.db.GetChatByIDForUpdate)(ctx, id)
|
||||
}
|
||||
|
||||
func (q *querier) GetChatCompactionModelOverride(ctx context.Context) (string, error) {
|
||||
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceDeploymentConfig); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return q.db.GetChatCompactionModelOverride(ctx)
|
||||
}
|
||||
|
||||
func (q *querier) GetChatComputerUseProvider(ctx context.Context) (string, error) {
|
||||
// The computer-use provider is a deployment-wide runtime chat setting
|
||||
// read by authenticated chat users and chatd. Feature and experiment
|
||||
@@ -3317,13 +3317,6 @@ func (q *querier) GetChatDiffStatusesByChatIDs(ctx context.Context, chatIDs []uu
|
||||
return q.db.GetChatDiffStatusesByChatIDs(ctx, chatIDs)
|
||||
}
|
||||
|
||||
func (q *querier) GetChatExploreModelOverride(ctx context.Context) (string, error) {
|
||||
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceDeploymentConfig); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return q.db.GetChatExploreModelOverride(ctx)
|
||||
}
|
||||
|
||||
func (q *querier) GetChatFamilyIDsByRootID(ctx context.Context, id uuid.UUID) ([]uuid.UUID, error) {
|
||||
// This is a read-only query: it returns the chat IDs that belong
|
||||
// to a family. Authorize as Read against the root chat. The
|
||||
@@ -3427,13 +3420,6 @@ func (q *querier) GetChatGatewayAPIKey(ctx context.Context, arg database.GetChat
|
||||
return fetch(q.log, q.auth, q.db.GetChatGatewayAPIKey)(ctx, arg)
|
||||
}
|
||||
|
||||
func (q *querier) GetChatGeneralModelOverride(ctx context.Context) (string, error) {
|
||||
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceDeploymentConfig); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return q.db.GetChatGeneralModelOverride(ctx)
|
||||
}
|
||||
|
||||
func (q *querier) GetChatHeartbeat(ctx context.Context, arg database.GetChatHeartbeatParams) (database.ChatHeartbeat, error) {
|
||||
_, err := q.GetChatByID(ctx, arg.ChatID)
|
||||
if err != nil {
|
||||
@@ -3565,6 +3551,35 @@ func (q *querier) GetChatModelConfigsForTelemetry(ctx context.Context) ([]databa
|
||||
return q.db.GetChatModelConfigsForTelemetry(ctx)
|
||||
}
|
||||
|
||||
func (q *querier) GetChatOrganizationModelOverride(ctx context.Context, arg database.GetChatOrganizationModelOverrideParams) (database.ChatOrganizationModelOverride, error) {
|
||||
object := rbac.ResourceChatModelConfig.InOrg(arg.OrganizationID).WithGroupACL(map[string][]policy.Action{
|
||||
arg.OrganizationID.String(): {policy.ActionRead},
|
||||
})
|
||||
if err := q.authorizeContext(ctx, policy.ActionRead, object); err != nil {
|
||||
return database.ChatOrganizationModelOverride{}, err
|
||||
}
|
||||
return q.db.GetChatOrganizationModelOverride(ctx, arg)
|
||||
}
|
||||
|
||||
func (q *querier) GetChatOrganizationModelOverrides(ctx context.Context, organizationID uuid.UUID) ([]database.ChatOrganizationModelOverride, error) {
|
||||
object := rbac.ResourceChatModelConfig.InOrg(organizationID).WithGroupACL(map[string][]policy.Action{
|
||||
organizationID.String(): {policy.ActionRead},
|
||||
})
|
||||
if err := q.authorizeContext(ctx, policy.ActionRead, object); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return q.db.GetChatOrganizationModelOverrides(ctx, organizationID)
|
||||
}
|
||||
|
||||
func (q *querier) GetChatOrganizationModelOverridesByContext(ctx context.Context, argContext string) ([]database.GetChatOrganizationModelOverridesByContextRow, error) {
|
||||
// This read spans every organization, so it requires site-wide access to
|
||||
// chat model configs. It exists for bulk consumers such as telemetry.
|
||||
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceChatModelConfig); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return q.db.GetChatOrganizationModelOverridesByContext(ctx, argContext)
|
||||
}
|
||||
|
||||
func (q *querier) GetChatPersonalModelOverridesEnabled(ctx context.Context) (bool, error) {
|
||||
// The personal model overrides flag is a deployment-wide setting read by
|
||||
// authenticated chat users. We only require that an explicit actor is
|
||||
@@ -3663,11 +3678,26 @@ func (q *querier) GetChatSystemPromptConfig(ctx context.Context) (database.GetCh
|
||||
return q.db.GetChatSystemPromptConfig(ctx)
|
||||
}
|
||||
|
||||
func (q *querier) GetChatTitleGenerationModelOverride(ctx context.Context) (string, error) {
|
||||
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceDeploymentConfig); err != nil {
|
||||
return "", err
|
||||
func (q *querier) GetChatUserModelOverride(ctx context.Context, arg database.GetChatUserModelOverrideParams) (database.ChatUserModelOverride, error) {
|
||||
u, err := q.db.GetUserByID(ctx, arg.UserID)
|
||||
if err != nil {
|
||||
return database.ChatUserModelOverride{}, err
|
||||
}
|
||||
return q.db.GetChatTitleGenerationModelOverride(ctx)
|
||||
if err := q.authorizeContext(ctx, policy.ActionReadPersonal, u); err != nil {
|
||||
return database.ChatUserModelOverride{}, err
|
||||
}
|
||||
return q.db.GetChatUserModelOverride(ctx, arg)
|
||||
}
|
||||
|
||||
func (q *querier) GetChatUserModelOverrides(ctx context.Context, arg database.GetChatUserModelOverridesParams) ([]database.ChatUserModelOverride, error) {
|
||||
u, err := q.db.GetUserByID(ctx, arg.UserID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := q.authorizeContext(ctx, policy.ActionReadPersonal, u); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return q.db.GetChatUserModelOverrides(ctx, arg)
|
||||
}
|
||||
|
||||
func (q *querier) GetChatUserPromptsByChatID(ctx context.Context, arg database.GetChatUserPromptsByChatIDParams) ([]database.GetChatUserPromptsByChatIDRow, error) {
|
||||
@@ -5229,17 +5259,6 @@ func (q *querier) GetUserChatDebugLoggingEnabled(ctx context.Context, userID uui
|
||||
return q.db.GetUserChatDebugLoggingEnabled(ctx, userID)
|
||||
}
|
||||
|
||||
func (q *querier) GetUserChatPersonalModelOverride(ctx context.Context, arg database.GetUserChatPersonalModelOverrideParams) (string, error) {
|
||||
u, err := q.db.GetUserByID(ctx, arg.UserID)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if err := q.authorizeContext(ctx, policy.ActionReadPersonal, u); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return q.db.GetUserChatPersonalModelOverride(ctx, arg)
|
||||
}
|
||||
|
||||
func (q *querier) GetUserCodeDiffDisplayMode(ctx context.Context, userID uuid.UUID) (string, error) {
|
||||
user, err := q.db.GetUserByID(ctx, userID)
|
||||
if err != nil {
|
||||
@@ -6979,17 +6998,6 @@ func (q *querier) ListUserChatCompactionThresholds(ctx context.Context, userID u
|
||||
return q.db.ListUserChatCompactionThresholds(ctx, userID)
|
||||
}
|
||||
|
||||
func (q *querier) ListUserChatPersonalModelOverrides(ctx context.Context, userID uuid.UUID) ([]database.ListUserChatPersonalModelOverridesRow, error) {
|
||||
u, err := q.db.GetUserByID(ctx, userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := q.authorizeContext(ctx, policy.ActionReadPersonal, u); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return q.db.ListUserChatPersonalModelOverrides(ctx, userID)
|
||||
}
|
||||
|
||||
func (q *querier) ListUserSecrets(ctx context.Context, userID uuid.UUID) ([]database.ListUserSecretsRow, error) {
|
||||
obj := rbac.ResourceUserSecret.WithOwner(userID.String())
|
||||
if err := q.authorizeContext(ctx, policy.ActionRead, obj); err != nil {
|
||||
@@ -8988,13 +8996,6 @@ func (q *querier) UpsertChatAutoArchiveDays(ctx context.Context, autoArchiveDays
|
||||
return q.db.UpsertChatAutoArchiveDays(ctx, autoArchiveDays)
|
||||
}
|
||||
|
||||
func (q *querier) UpsertChatCompactionModelOverride(ctx context.Context, value string) error {
|
||||
if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceDeploymentConfig); err != nil {
|
||||
return err
|
||||
}
|
||||
return q.db.UpsertChatCompactionModelOverride(ctx, value)
|
||||
}
|
||||
|
||||
func (q *querier) UpsertChatComputerUseProvider(ctx context.Context, provider string) error {
|
||||
if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceDeploymentConfig); err != nil {
|
||||
return err
|
||||
@@ -9047,20 +9048,6 @@ func (q *querier) UpsertChatDiffStatusReference(ctx context.Context, arg databas
|
||||
return q.db.UpsertChatDiffStatusReference(ctx, arg)
|
||||
}
|
||||
|
||||
func (q *querier) UpsertChatExploreModelOverride(ctx context.Context, value string) error {
|
||||
if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceDeploymentConfig); err != nil {
|
||||
return err
|
||||
}
|
||||
return q.db.UpsertChatExploreModelOverride(ctx, value)
|
||||
}
|
||||
|
||||
func (q *querier) UpsertChatGeneralModelOverride(ctx context.Context, value string) error {
|
||||
if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceDeploymentConfig); err != nil {
|
||||
return err
|
||||
}
|
||||
return q.db.UpsertChatGeneralModelOverride(ctx, value)
|
||||
}
|
||||
|
||||
func (q *querier) UpsertChatHeartbeat(ctx context.Context, arg database.UpsertChatHeartbeatParams) error {
|
||||
chat, err := q.db.GetChatByID(ctx, arg.ChatID)
|
||||
if err != nil {
|
||||
@@ -9080,6 +9067,13 @@ func (q *querier) UpsertChatIncludeDefaultSystemPrompt(ctx context.Context, incl
|
||||
return q.db.UpsertChatIncludeDefaultSystemPrompt(ctx, includeDefaultSystemPrompt)
|
||||
}
|
||||
|
||||
func (q *querier) UpsertChatOrganizationModelOverride(ctx context.Context, arg database.UpsertChatOrganizationModelOverrideParams) error {
|
||||
if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceChatModelConfig.InOrg(arg.OrganizationID)); err != nil {
|
||||
return err
|
||||
}
|
||||
return q.db.UpsertChatOrganizationModelOverride(ctx, arg)
|
||||
}
|
||||
|
||||
func (q *querier) UpsertChatPersonalModelOverridesEnabled(ctx context.Context, enabled bool) error {
|
||||
if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceDeploymentConfig); err != nil {
|
||||
return err
|
||||
@@ -9108,11 +9102,15 @@ func (q *querier) UpsertChatSystemPrompt(ctx context.Context, value string) erro
|
||||
return q.db.UpsertChatSystemPrompt(ctx, value)
|
||||
}
|
||||
|
||||
func (q *querier) UpsertChatTitleGenerationModelOverride(ctx context.Context, value string) error {
|
||||
if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceDeploymentConfig); err != nil {
|
||||
func (q *querier) UpsertChatUserModelOverride(ctx context.Context, arg database.UpsertChatUserModelOverrideParams) error {
|
||||
u, err := q.db.GetUserByID(ctx, arg.UserID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return q.db.UpsertChatTitleGenerationModelOverride(ctx, value)
|
||||
if err := q.authorizeContext(ctx, policy.ActionUpdatePersonal, u); err != nil {
|
||||
return err
|
||||
}
|
||||
return q.db.UpsertChatUserModelOverride(ctx, arg)
|
||||
}
|
||||
|
||||
//nolint:revive,staticcheck // Parameter name matches the generated querier interface.
|
||||
@@ -9323,17 +9321,6 @@ func (q *querier) UpsertUserChatDebugLoggingEnabled(ctx context.Context, arg dat
|
||||
return q.db.UpsertUserChatDebugLoggingEnabled(ctx, arg)
|
||||
}
|
||||
|
||||
func (q *querier) UpsertUserChatPersonalModelOverride(ctx context.Context, arg database.UpsertUserChatPersonalModelOverrideParams) error {
|
||||
u, err := q.db.GetUserByID(ctx, arg.UserID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := q.authorizeContext(ctx, policy.ActionUpdatePersonal, u); err != nil {
|
||||
return err
|
||||
}
|
||||
return q.db.UpsertUserChatPersonalModelOverride(ctx, arg)
|
||||
}
|
||||
|
||||
func (q *querier) UpsertWebpushVAPIDKeys(ctx context.Context, arg database.UpsertWebpushVAPIDKeysParams) error {
|
||||
if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceDeploymentConfig); err != nil {
|
||||
return err
|
||||
|
||||
@@ -32,7 +32,6 @@ import (
|
||||
"github.com/coder/coder/v2/coderd/rbac"
|
||||
"github.com/coder/coder/v2/coderd/rbac/policy"
|
||||
"github.com/coder/coder/v2/coderd/util/slice"
|
||||
"github.com/coder/coder/v2/coderd/x/chatd"
|
||||
"github.com/coder/coder/v2/codersdk"
|
||||
"github.com/coder/coder/v2/provisionersdk"
|
||||
"github.com/coder/coder/v2/testutil"
|
||||
@@ -1292,21 +1291,32 @@ func (s *MethodTestSuite) TestChats() {
|
||||
dbm.EXPECT().GetChatComputerUseProvider(gomock.Any()).Return("anthropic", nil).AnyTimes()
|
||||
check.Args().Asserts()
|
||||
}))
|
||||
s.Run("GetChatGeneralModelOverride", s.Mocked(func(dbm *dbmock.MockStore, _ *gofakeit.Faker, check *expects) {
|
||||
dbm.EXPECT().GetChatGeneralModelOverride(gomock.Any()).Return("", nil).AnyTimes()
|
||||
check.Args().Asserts(rbac.ResourceDeploymentConfig, policy.ActionRead)
|
||||
s.Run("GetChatOrganizationModelOverride", s.Mocked(func(dbm *dbmock.MockStore, _ *gofakeit.Faker, check *expects) {
|
||||
orgID := uuid.New()
|
||||
arg := database.GetChatOrganizationModelOverrideParams{OrganizationID: orgID, Context: "general"}
|
||||
dbm.EXPECT().GetChatOrganizationModelOverride(gomock.Any(), arg).Return(database.ChatOrganizationModelOverride{}, nil).AnyTimes()
|
||||
object := rbac.ResourceChatModelConfig.InOrg(orgID).WithGroupACL(map[string][]policy.Action{
|
||||
orgID.String(): {policy.ActionRead},
|
||||
})
|
||||
check.Args(arg).Asserts(object, policy.ActionRead)
|
||||
}))
|
||||
s.Run("GetChatExploreModelOverride", s.Mocked(func(dbm *dbmock.MockStore, _ *gofakeit.Faker, check *expects) {
|
||||
dbm.EXPECT().GetChatExploreModelOverride(gomock.Any()).Return("", nil).AnyTimes()
|
||||
check.Args().Asserts(rbac.ResourceDeploymentConfig, policy.ActionRead)
|
||||
s.Run("GetChatOrganizationModelOverrides", s.Mocked(func(dbm *dbmock.MockStore, _ *gofakeit.Faker, check *expects) {
|
||||
orgID := uuid.New()
|
||||
dbm.EXPECT().GetChatOrganizationModelOverrides(gomock.Any(), orgID).Return([]database.ChatOrganizationModelOverride{}, nil).AnyTimes()
|
||||
object := rbac.ResourceChatModelConfig.InOrg(orgID).WithGroupACL(map[string][]policy.Action{
|
||||
orgID.String(): {policy.ActionRead},
|
||||
})
|
||||
check.Args(orgID).Asserts(object, policy.ActionRead)
|
||||
}))
|
||||
s.Run("GetChatTitleGenerationModelOverride", s.Mocked(func(dbm *dbmock.MockStore, _ *gofakeit.Faker, check *expects) {
|
||||
dbm.EXPECT().GetChatTitleGenerationModelOverride(gomock.Any()).Return("", nil).AnyTimes()
|
||||
check.Args().Asserts(rbac.ResourceDeploymentConfig, policy.ActionRead)
|
||||
s.Run("GetChatOrganizationModelOverridesByContext", s.Mocked(func(dbm *dbmock.MockStore, _ *gofakeit.Faker, check *expects) {
|
||||
dbm.EXPECT().GetChatOrganizationModelOverridesByContext(gomock.Any(), "advisor").Return([]database.GetChatOrganizationModelOverridesByContextRow{}, nil).AnyTimes()
|
||||
check.Args("advisor").Asserts(rbac.ResourceChatModelConfig, policy.ActionRead)
|
||||
}))
|
||||
s.Run("GetChatCompactionModelOverride", s.Mocked(func(dbm *dbmock.MockStore, _ *gofakeit.Faker, check *expects) {
|
||||
dbm.EXPECT().GetChatCompactionModelOverride(gomock.Any()).Return("", nil).AnyTimes()
|
||||
check.Args().Asserts(rbac.ResourceDeploymentConfig, policy.ActionRead)
|
||||
s.Run("DeleteChatOrganizationModelOverride", s.Mocked(func(dbm *dbmock.MockStore, _ *gofakeit.Faker, check *expects) {
|
||||
orgID := uuid.New()
|
||||
arg := database.DeleteChatOrganizationModelOverrideParams{OrganizationID: orgID, Context: "general"}
|
||||
dbm.EXPECT().DeleteChatOrganizationModelOverride(gomock.Any(), arg).Return(nil).AnyTimes()
|
||||
check.Args(arg).Asserts(rbac.ResourceChatModelConfig.InOrg(orgID), policy.ActionUpdate)
|
||||
}))
|
||||
s.Run("GetChatPlanModeInstructions", s.Mocked(func(dbm *dbmock.MockStore, _ *gofakeit.Faker, check *expects) {
|
||||
dbm.EXPECT().GetChatPlanModeInstructions(gomock.Any()).Return("", nil).AnyTimes()
|
||||
@@ -1774,21 +1784,15 @@ func (s *MethodTestSuite) TestChats() {
|
||||
dbm.EXPECT().UpsertChatComputerUseProvider(gomock.Any(), "anthropic").Return(nil).AnyTimes()
|
||||
check.Args("anthropic").Asserts(rbac.ResourceDeploymentConfig, policy.ActionUpdate)
|
||||
}))
|
||||
s.Run("UpsertChatGeneralModelOverride", s.Mocked(func(dbm *dbmock.MockStore, _ *gofakeit.Faker, check *expects) {
|
||||
dbm.EXPECT().UpsertChatGeneralModelOverride(gomock.Any(), "").Return(nil).AnyTimes()
|
||||
check.Args("").Asserts(rbac.ResourceDeploymentConfig, policy.ActionUpdate)
|
||||
}))
|
||||
s.Run("UpsertChatExploreModelOverride", s.Mocked(func(dbm *dbmock.MockStore, _ *gofakeit.Faker, check *expects) {
|
||||
dbm.EXPECT().UpsertChatExploreModelOverride(gomock.Any(), "").Return(nil).AnyTimes()
|
||||
check.Args("").Asserts(rbac.ResourceDeploymentConfig, policy.ActionUpdate)
|
||||
}))
|
||||
s.Run("UpsertChatTitleGenerationModelOverride", s.Mocked(func(dbm *dbmock.MockStore, _ *gofakeit.Faker, check *expects) {
|
||||
dbm.EXPECT().UpsertChatTitleGenerationModelOverride(gomock.Any(), "").Return(nil).AnyTimes()
|
||||
check.Args("").Asserts(rbac.ResourceDeploymentConfig, policy.ActionUpdate)
|
||||
}))
|
||||
s.Run("UpsertChatCompactionModelOverride", s.Mocked(func(dbm *dbmock.MockStore, _ *gofakeit.Faker, check *expects) {
|
||||
dbm.EXPECT().UpsertChatCompactionModelOverride(gomock.Any(), "").Return(nil).AnyTimes()
|
||||
check.Args("").Asserts(rbac.ResourceDeploymentConfig, policy.ActionUpdate)
|
||||
s.Run("UpsertChatOrganizationModelOverride", s.Mocked(func(dbm *dbmock.MockStore, _ *gofakeit.Faker, check *expects) {
|
||||
orgID := uuid.New()
|
||||
arg := database.UpsertChatOrganizationModelOverrideParams{
|
||||
OrganizationID: orgID,
|
||||
Context: "general",
|
||||
ModelConfigID: uuid.New(),
|
||||
}
|
||||
dbm.EXPECT().UpsertChatOrganizationModelOverride(gomock.Any(), arg).Return(nil).AnyTimes()
|
||||
check.Args(arg).Asserts(rbac.ResourceChatModelConfig.InOrg(orgID), policy.ActionUpdate)
|
||||
}))
|
||||
s.Run("UpsertChatPlanModeInstructions", s.Mocked(func(dbm *dbmock.MockStore, _ *gofakeit.Faker, check *expects) {
|
||||
dbm.EXPECT().UpsertChatPlanModeInstructions(gomock.Any(), "").Return(nil).AnyTimes()
|
||||
@@ -3266,28 +3270,30 @@ func (s *MethodTestSuite) TestUser() {
|
||||
dbm.EXPECT().UpsertUserChatDebugLoggingEnabled(gomock.Any(), arg).Return(nil).AnyTimes()
|
||||
check.Args(arg).Asserts(u, policy.ActionUpdatePersonal)
|
||||
}))
|
||||
s.Run("ListUserChatPersonalModelOverrides", s.Mocked(func(dbm *dbmock.MockStore, faker *gofakeit.Faker, check *expects) {
|
||||
s.Run("GetChatUserModelOverrides", s.Mocked(func(dbm *dbmock.MockStore, faker *gofakeit.Faker, check *expects) {
|
||||
u := testutil.Fake(s.T(), faker, database.User{})
|
||||
key := chatd.ChatPersonalModelOverrideKey(codersdk.ChatPersonalModelOverrideContextRoot)
|
||||
row := database.ListUserChatPersonalModelOverridesRow{Key: key, Value: "chat_default"}
|
||||
arg := database.GetChatUserModelOverridesParams{UserID: u.ID, OrganizationID: uuid.New()}
|
||||
dbm.EXPECT().GetUserByID(gomock.Any(), u.ID).Return(u, nil).AnyTimes()
|
||||
dbm.EXPECT().ListUserChatPersonalModelOverrides(gomock.Any(), u.ID).Return([]database.ListUserChatPersonalModelOverridesRow{row}, nil).AnyTimes()
|
||||
check.Args(u.ID).Asserts(u, policy.ActionReadPersonal).Returns([]database.ListUserChatPersonalModelOverridesRow{row})
|
||||
dbm.EXPECT().GetChatUserModelOverrides(gomock.Any(), arg).Return([]database.ChatUserModelOverride{}, nil).AnyTimes()
|
||||
check.Args(arg).Asserts(u, policy.ActionReadPersonal).Returns([]database.ChatUserModelOverride{})
|
||||
}))
|
||||
s.Run("GetUserChatPersonalModelOverride", s.Mocked(func(dbm *dbmock.MockStore, faker *gofakeit.Faker, check *expects) {
|
||||
s.Run("GetChatUserModelOverride", s.Mocked(func(dbm *dbmock.MockStore, faker *gofakeit.Faker, check *expects) {
|
||||
u := testutil.Fake(s.T(), faker, database.User{})
|
||||
key := chatd.ChatPersonalModelOverrideKey(codersdk.ChatPersonalModelOverrideContextRoot)
|
||||
arg := database.GetUserChatPersonalModelOverrideParams{UserID: u.ID, Key: key}
|
||||
arg := database.GetChatUserModelOverrideParams{UserID: u.ID, OrganizationID: uuid.New(), Context: "root"}
|
||||
dbm.EXPECT().GetUserByID(gomock.Any(), u.ID).Return(u, nil).AnyTimes()
|
||||
dbm.EXPECT().GetUserChatPersonalModelOverride(gomock.Any(), arg).Return("chat_default", nil).AnyTimes()
|
||||
check.Args(arg).Asserts(u, policy.ActionReadPersonal).Returns("chat_default")
|
||||
dbm.EXPECT().GetChatUserModelOverride(gomock.Any(), arg).Return(database.ChatUserModelOverride{}, nil).AnyTimes()
|
||||
check.Args(arg).Asserts(u, policy.ActionReadPersonal).Returns(database.ChatUserModelOverride{})
|
||||
}))
|
||||
s.Run("UpsertUserChatPersonalModelOverride", s.Mocked(func(dbm *dbmock.MockStore, faker *gofakeit.Faker, check *expects) {
|
||||
s.Run("UpsertChatUserModelOverride", s.Mocked(func(dbm *dbmock.MockStore, faker *gofakeit.Faker, check *expects) {
|
||||
u := testutil.Fake(s.T(), faker, database.User{})
|
||||
key := chatd.ChatPersonalModelOverrideKey(codersdk.ChatPersonalModelOverrideContextRoot)
|
||||
arg := database.UpsertUserChatPersonalModelOverrideParams{UserID: u.ID, Key: key, Value: "chat_default"}
|
||||
arg := database.UpsertChatUserModelOverrideParams{
|
||||
UserID: u.ID,
|
||||
OrganizationID: uuid.New(),
|
||||
Context: "root",
|
||||
Mode: "chat_default",
|
||||
}
|
||||
dbm.EXPECT().GetUserByID(gomock.Any(), u.ID).Return(u, nil).AnyTimes()
|
||||
dbm.EXPECT().UpsertUserChatPersonalModelOverride(gomock.Any(), arg).Return(nil).AnyTimes()
|
||||
dbm.EXPECT().UpsertChatUserModelOverride(gomock.Any(), arg).Return(nil).AnyTimes()
|
||||
check.Args(arg).Asserts(u, policy.ActionUpdatePersonal)
|
||||
}))
|
||||
s.Run("UpdateUserChatCustomPrompt", s.Mocked(func(dbm *dbmock.MockStore, faker *gofakeit.Faker, check *expects) {
|
||||
|
||||
+56
-80
@@ -528,6 +528,14 @@ func (m queryMetricsStore) DeleteChatModelConfigByID(ctx context.Context, id uui
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
func (m queryMetricsStore) DeleteChatOrganizationModelOverride(ctx context.Context, arg database.DeleteChatOrganizationModelOverrideParams) error {
|
||||
start := time.Now()
|
||||
r0 := m.s.DeleteChatOrganizationModelOverride(ctx, arg)
|
||||
m.queryLatencies.WithLabelValues("DeleteChatOrganizationModelOverride").Observe(time.Since(start).Seconds())
|
||||
m.queryCounts.WithLabelValues(httpmw.ExtractHTTPRoute(ctx), httpmw.ExtractHTTPMethod(ctx), "DeleteChatOrganizationModelOverride").Inc()
|
||||
return r0
|
||||
}
|
||||
|
||||
func (m queryMetricsStore) DeleteChatQueuedMessage(ctx context.Context, arg database.DeleteChatQueuedMessageParams) error {
|
||||
start := time.Now()
|
||||
r0 := m.s.DeleteChatQueuedMessage(ctx, arg)
|
||||
@@ -1464,14 +1472,6 @@ func (m queryMetricsStore) GetChatByIDForUpdate(ctx context.Context, id uuid.UUI
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
func (m queryMetricsStore) GetChatCompactionModelOverride(ctx context.Context) (string, error) {
|
||||
start := time.Now()
|
||||
r0, r1 := m.s.GetChatCompactionModelOverride(ctx)
|
||||
m.queryLatencies.WithLabelValues("GetChatCompactionModelOverride").Observe(time.Since(start).Seconds())
|
||||
m.queryCounts.WithLabelValues(httpmw.ExtractHTTPRoute(ctx), httpmw.ExtractHTTPMethod(ctx), "GetChatCompactionModelOverride").Inc()
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
func (m queryMetricsStore) GetChatComputerUseProvider(ctx context.Context) (string, error) {
|
||||
start := time.Now()
|
||||
r0, r1 := m.s.GetChatComputerUseProvider(ctx)
|
||||
@@ -1552,14 +1552,6 @@ func (m queryMetricsStore) GetChatDiffStatusesByChatIDs(ctx context.Context, cha
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
func (m queryMetricsStore) GetChatExploreModelOverride(ctx context.Context) (string, error) {
|
||||
start := time.Now()
|
||||
r0, r1 := m.s.GetChatExploreModelOverride(ctx)
|
||||
m.queryLatencies.WithLabelValues("GetChatExploreModelOverride").Observe(time.Since(start).Seconds())
|
||||
m.queryCounts.WithLabelValues(httpmw.ExtractHTTPRoute(ctx), httpmw.ExtractHTTPMethod(ctx), "GetChatExploreModelOverride").Inc()
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
func (m queryMetricsStore) GetChatFamilyIDsByRootID(ctx context.Context, id uuid.UUID) ([]uuid.UUID, error) {
|
||||
start := time.Now()
|
||||
r0, r1 := m.s.GetChatFamilyIDsByRootID(ctx, id)
|
||||
@@ -1608,14 +1600,6 @@ func (m queryMetricsStore) GetChatGatewayAPIKey(ctx context.Context, arg databas
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
func (m queryMetricsStore) GetChatGeneralModelOverride(ctx context.Context) (string, error) {
|
||||
start := time.Now()
|
||||
r0, r1 := m.s.GetChatGeneralModelOverride(ctx)
|
||||
m.queryLatencies.WithLabelValues("GetChatGeneralModelOverride").Observe(time.Since(start).Seconds())
|
||||
m.queryCounts.WithLabelValues(httpmw.ExtractHTTPRoute(ctx), httpmw.ExtractHTTPMethod(ctx), "GetChatGeneralModelOverride").Inc()
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
func (m queryMetricsStore) GetChatHeartbeat(ctx context.Context, arg database.GetChatHeartbeatParams) (database.ChatHeartbeat, error) {
|
||||
start := time.Now()
|
||||
r0, r1 := m.s.GetChatHeartbeat(ctx, arg)
|
||||
@@ -1720,6 +1704,30 @@ func (m queryMetricsStore) GetChatModelConfigsForTelemetry(ctx context.Context)
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
func (m queryMetricsStore) GetChatOrganizationModelOverride(ctx context.Context, arg database.GetChatOrganizationModelOverrideParams) (database.ChatOrganizationModelOverride, error) {
|
||||
start := time.Now()
|
||||
r0, r1 := m.s.GetChatOrganizationModelOverride(ctx, arg)
|
||||
m.queryLatencies.WithLabelValues("GetChatOrganizationModelOverride").Observe(time.Since(start).Seconds())
|
||||
m.queryCounts.WithLabelValues(httpmw.ExtractHTTPRoute(ctx), httpmw.ExtractHTTPMethod(ctx), "GetChatOrganizationModelOverride").Inc()
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
func (m queryMetricsStore) GetChatOrganizationModelOverrides(ctx context.Context, organizationID uuid.UUID) ([]database.ChatOrganizationModelOverride, error) {
|
||||
start := time.Now()
|
||||
r0, r1 := m.s.GetChatOrganizationModelOverrides(ctx, organizationID)
|
||||
m.queryLatencies.WithLabelValues("GetChatOrganizationModelOverrides").Observe(time.Since(start).Seconds())
|
||||
m.queryCounts.WithLabelValues(httpmw.ExtractHTTPRoute(ctx), httpmw.ExtractHTTPMethod(ctx), "GetChatOrganizationModelOverrides").Inc()
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
func (m queryMetricsStore) GetChatOrganizationModelOverridesByContext(ctx context.Context, argContext string) ([]database.GetChatOrganizationModelOverridesByContextRow, error) {
|
||||
start := time.Now()
|
||||
r0, r1 := m.s.GetChatOrganizationModelOverridesByContext(ctx, argContext)
|
||||
m.queryLatencies.WithLabelValues("GetChatOrganizationModelOverridesByContext").Observe(time.Since(start).Seconds())
|
||||
m.queryCounts.WithLabelValues(httpmw.ExtractHTTPRoute(ctx), httpmw.ExtractHTTPMethod(ctx), "GetChatOrganizationModelOverridesByContext").Inc()
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
func (m queryMetricsStore) GetChatPersonalModelOverridesEnabled(ctx context.Context) (bool, error) {
|
||||
start := time.Now()
|
||||
r0, r1 := m.s.GetChatPersonalModelOverridesEnabled(ctx)
|
||||
@@ -1808,11 +1816,19 @@ func (m queryMetricsStore) GetChatSystemPromptConfig(ctx context.Context) (datab
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
func (m queryMetricsStore) GetChatTitleGenerationModelOverride(ctx context.Context) (string, error) {
|
||||
func (m queryMetricsStore) GetChatUserModelOverride(ctx context.Context, arg database.GetChatUserModelOverrideParams) (database.ChatUserModelOverride, error) {
|
||||
start := time.Now()
|
||||
r0, r1 := m.s.GetChatTitleGenerationModelOverride(ctx)
|
||||
m.queryLatencies.WithLabelValues("GetChatTitleGenerationModelOverride").Observe(time.Since(start).Seconds())
|
||||
m.queryCounts.WithLabelValues(httpmw.ExtractHTTPRoute(ctx), httpmw.ExtractHTTPMethod(ctx), "GetChatTitleGenerationModelOverride").Inc()
|
||||
r0, r1 := m.s.GetChatUserModelOverride(ctx, arg)
|
||||
m.queryLatencies.WithLabelValues("GetChatUserModelOverride").Observe(time.Since(start).Seconds())
|
||||
m.queryCounts.WithLabelValues(httpmw.ExtractHTTPRoute(ctx), httpmw.ExtractHTTPMethod(ctx), "GetChatUserModelOverride").Inc()
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
func (m queryMetricsStore) GetChatUserModelOverrides(ctx context.Context, arg database.GetChatUserModelOverridesParams) ([]database.ChatUserModelOverride, error) {
|
||||
start := time.Now()
|
||||
r0, r1 := m.s.GetChatUserModelOverrides(ctx, arg)
|
||||
m.queryLatencies.WithLabelValues("GetChatUserModelOverrides").Observe(time.Since(start).Seconds())
|
||||
m.queryCounts.WithLabelValues(httpmw.ExtractHTTPRoute(ctx), httpmw.ExtractHTTPMethod(ctx), "GetChatUserModelOverrides").Inc()
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
@@ -3312,14 +3328,6 @@ func (m queryMetricsStore) GetUserChatDebugLoggingEnabled(ctx context.Context, u
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
func (m queryMetricsStore) GetUserChatPersonalModelOverride(ctx context.Context, arg database.GetUserChatPersonalModelOverrideParams) (string, error) {
|
||||
start := time.Now()
|
||||
r0, r1 := m.s.GetUserChatPersonalModelOverride(ctx, arg)
|
||||
m.queryLatencies.WithLabelValues("GetUserChatPersonalModelOverride").Observe(time.Since(start).Seconds())
|
||||
m.queryCounts.WithLabelValues(httpmw.ExtractHTTPRoute(ctx), httpmw.ExtractHTTPMethod(ctx), "GetUserChatPersonalModelOverride").Inc()
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
func (m queryMetricsStore) GetUserCodeDiffDisplayMode(ctx context.Context, userID uuid.UUID) (string, error) {
|
||||
start := time.Now()
|
||||
r0, r1 := m.s.GetUserCodeDiffDisplayMode(ctx, userID)
|
||||
@@ -4856,14 +4864,6 @@ func (m queryMetricsStore) ListUserChatCompactionThresholds(ctx context.Context,
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
func (m queryMetricsStore) ListUserChatPersonalModelOverrides(ctx context.Context, userID uuid.UUID) ([]database.ListUserChatPersonalModelOverridesRow, error) {
|
||||
start := time.Now()
|
||||
r0, r1 := m.s.ListUserChatPersonalModelOverrides(ctx, userID)
|
||||
m.queryLatencies.WithLabelValues("ListUserChatPersonalModelOverrides").Observe(time.Since(start).Seconds())
|
||||
m.queryCounts.WithLabelValues(httpmw.ExtractHTTPRoute(ctx), httpmw.ExtractHTTPMethod(ctx), "ListUserChatPersonalModelOverrides").Inc()
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
func (m queryMetricsStore) ListUserSecrets(ctx context.Context, userID uuid.UUID) ([]database.ListUserSecretsRow, error) {
|
||||
start := time.Now()
|
||||
r0, r1 := m.s.ListUserSecrets(ctx, userID)
|
||||
@@ -6288,14 +6288,6 @@ func (m queryMetricsStore) UpsertChatAutoArchiveDays(ctx context.Context, autoAr
|
||||
return r0
|
||||
}
|
||||
|
||||
func (m queryMetricsStore) UpsertChatCompactionModelOverride(ctx context.Context, value string) error {
|
||||
start := time.Now()
|
||||
r0 := m.s.UpsertChatCompactionModelOverride(ctx, value)
|
||||
m.queryLatencies.WithLabelValues("UpsertChatCompactionModelOverride").Observe(time.Since(start).Seconds())
|
||||
m.queryCounts.WithLabelValues(httpmw.ExtractHTTPRoute(ctx), httpmw.ExtractHTTPMethod(ctx), "UpsertChatCompactionModelOverride").Inc()
|
||||
return r0
|
||||
}
|
||||
|
||||
func (m queryMetricsStore) UpsertChatComputerUseProvider(ctx context.Context, provider string) error {
|
||||
start := time.Now()
|
||||
r0 := m.s.UpsertChatComputerUseProvider(ctx, provider)
|
||||
@@ -6344,22 +6336,6 @@ func (m queryMetricsStore) UpsertChatDiffStatusReference(ctx context.Context, ar
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
func (m queryMetricsStore) UpsertChatExploreModelOverride(ctx context.Context, value string) error {
|
||||
start := time.Now()
|
||||
r0 := m.s.UpsertChatExploreModelOverride(ctx, value)
|
||||
m.queryLatencies.WithLabelValues("UpsertChatExploreModelOverride").Observe(time.Since(start).Seconds())
|
||||
m.queryCounts.WithLabelValues(httpmw.ExtractHTTPRoute(ctx), httpmw.ExtractHTTPMethod(ctx), "UpsertChatExploreModelOverride").Inc()
|
||||
return r0
|
||||
}
|
||||
|
||||
func (m queryMetricsStore) UpsertChatGeneralModelOverride(ctx context.Context, value string) error {
|
||||
start := time.Now()
|
||||
r0 := m.s.UpsertChatGeneralModelOverride(ctx, value)
|
||||
m.queryLatencies.WithLabelValues("UpsertChatGeneralModelOverride").Observe(time.Since(start).Seconds())
|
||||
m.queryCounts.WithLabelValues(httpmw.ExtractHTTPRoute(ctx), httpmw.ExtractHTTPMethod(ctx), "UpsertChatGeneralModelOverride").Inc()
|
||||
return r0
|
||||
}
|
||||
|
||||
func (m queryMetricsStore) UpsertChatHeartbeat(ctx context.Context, arg database.UpsertChatHeartbeatParams) error {
|
||||
start := time.Now()
|
||||
r0 := m.s.UpsertChatHeartbeat(ctx, arg)
|
||||
@@ -6376,6 +6352,14 @@ func (m queryMetricsStore) UpsertChatIncludeDefaultSystemPrompt(ctx context.Cont
|
||||
return r0
|
||||
}
|
||||
|
||||
func (m queryMetricsStore) UpsertChatOrganizationModelOverride(ctx context.Context, arg database.UpsertChatOrganizationModelOverrideParams) error {
|
||||
start := time.Now()
|
||||
r0 := m.s.UpsertChatOrganizationModelOverride(ctx, arg)
|
||||
m.queryLatencies.WithLabelValues("UpsertChatOrganizationModelOverride").Observe(time.Since(start).Seconds())
|
||||
m.queryCounts.WithLabelValues(httpmw.ExtractHTTPRoute(ctx), httpmw.ExtractHTTPMethod(ctx), "UpsertChatOrganizationModelOverride").Inc()
|
||||
return r0
|
||||
}
|
||||
|
||||
func (m queryMetricsStore) UpsertChatPersonalModelOverridesEnabled(ctx context.Context, enabled bool) error {
|
||||
start := time.Now()
|
||||
r0 := m.s.UpsertChatPersonalModelOverridesEnabled(ctx, enabled)
|
||||
@@ -6408,11 +6392,11 @@ func (m queryMetricsStore) UpsertChatSystemPrompt(ctx context.Context, value str
|
||||
return r0
|
||||
}
|
||||
|
||||
func (m queryMetricsStore) UpsertChatTitleGenerationModelOverride(ctx context.Context, value string) error {
|
||||
func (m queryMetricsStore) UpsertChatUserModelOverride(ctx context.Context, arg database.UpsertChatUserModelOverrideParams) error {
|
||||
start := time.Now()
|
||||
r0 := m.s.UpsertChatTitleGenerationModelOverride(ctx, value)
|
||||
m.queryLatencies.WithLabelValues("UpsertChatTitleGenerationModelOverride").Observe(time.Since(start).Seconds())
|
||||
m.queryCounts.WithLabelValues(httpmw.ExtractHTTPRoute(ctx), httpmw.ExtractHTTPMethod(ctx), "UpsertChatTitleGenerationModelOverride").Inc()
|
||||
r0 := m.s.UpsertChatUserModelOverride(ctx, arg)
|
||||
m.queryLatencies.WithLabelValues("UpsertChatUserModelOverride").Observe(time.Since(start).Seconds())
|
||||
m.queryCounts.WithLabelValues(httpmw.ExtractHTTPRoute(ctx), httpmw.ExtractHTTPMethod(ctx), "UpsertChatUserModelOverride").Inc()
|
||||
return r0
|
||||
}
|
||||
|
||||
@@ -6608,14 +6592,6 @@ func (m queryMetricsStore) UpsertUserChatDebugLoggingEnabled(ctx context.Context
|
||||
return r0
|
||||
}
|
||||
|
||||
func (m queryMetricsStore) UpsertUserChatPersonalModelOverride(ctx context.Context, arg database.UpsertUserChatPersonalModelOverrideParams) error {
|
||||
start := time.Now()
|
||||
r0 := m.s.UpsertUserChatPersonalModelOverride(ctx, arg)
|
||||
m.queryLatencies.WithLabelValues("UpsertUserChatPersonalModelOverride").Observe(time.Since(start).Seconds())
|
||||
m.queryCounts.WithLabelValues(httpmw.ExtractHTTPRoute(ctx), httpmw.ExtractHTTPMethod(ctx), "UpsertUserChatPersonalModelOverride").Inc()
|
||||
return r0
|
||||
}
|
||||
|
||||
func (m queryMetricsStore) UpsertWebpushVAPIDKeys(ctx context.Context, arg database.UpsertWebpushVAPIDKeysParams) error {
|
||||
start := time.Now()
|
||||
r0 := m.s.UpsertWebpushVAPIDKeys(ctx, arg)
|
||||
|
||||
Generated
+101
-144
@@ -863,6 +863,20 @@ func (mr *MockStoreMockRecorder) DeleteChatModelConfigByID(ctx, id any) *gomock.
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteChatModelConfigByID", reflect.TypeOf((*MockStore)(nil).DeleteChatModelConfigByID), ctx, id)
|
||||
}
|
||||
|
||||
// DeleteChatOrganizationModelOverride mocks base method.
|
||||
func (m *MockStore) DeleteChatOrganizationModelOverride(ctx context.Context, arg database.DeleteChatOrganizationModelOverrideParams) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "DeleteChatOrganizationModelOverride", ctx, arg)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// DeleteChatOrganizationModelOverride indicates an expected call of DeleteChatOrganizationModelOverride.
|
||||
func (mr *MockStoreMockRecorder) DeleteChatOrganizationModelOverride(ctx, arg any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteChatOrganizationModelOverride", reflect.TypeOf((*MockStore)(nil).DeleteChatOrganizationModelOverride), ctx, arg)
|
||||
}
|
||||
|
||||
// DeleteChatQueuedMessage mocks base method.
|
||||
func (m *MockStore) DeleteChatQueuedMessage(ctx context.Context, arg database.DeleteChatQueuedMessageParams) error {
|
||||
m.ctrl.T.Helper()
|
||||
@@ -2745,21 +2759,6 @@ func (mr *MockStoreMockRecorder) GetChatByIDForUpdate(ctx, id any) *gomock.Call
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetChatByIDForUpdate", reflect.TypeOf((*MockStore)(nil).GetChatByIDForUpdate), ctx, id)
|
||||
}
|
||||
|
||||
// GetChatCompactionModelOverride mocks base method.
|
||||
func (m *MockStore) GetChatCompactionModelOverride(ctx context.Context) (string, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetChatCompactionModelOverride", ctx)
|
||||
ret0, _ := ret[0].(string)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetChatCompactionModelOverride indicates an expected call of GetChatCompactionModelOverride.
|
||||
func (mr *MockStoreMockRecorder) GetChatCompactionModelOverride(ctx any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetChatCompactionModelOverride", reflect.TypeOf((*MockStore)(nil).GetChatCompactionModelOverride), ctx)
|
||||
}
|
||||
|
||||
// GetChatComputerUseProvider mocks base method.
|
||||
func (m *MockStore) GetChatComputerUseProvider(ctx context.Context) (string, error) {
|
||||
m.ctrl.T.Helper()
|
||||
@@ -2910,21 +2909,6 @@ func (mr *MockStoreMockRecorder) GetChatDiffStatusesByChatIDs(ctx, chatIds any)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetChatDiffStatusesByChatIDs", reflect.TypeOf((*MockStore)(nil).GetChatDiffStatusesByChatIDs), ctx, chatIds)
|
||||
}
|
||||
|
||||
// GetChatExploreModelOverride mocks base method.
|
||||
func (m *MockStore) GetChatExploreModelOverride(ctx context.Context) (string, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetChatExploreModelOverride", ctx)
|
||||
ret0, _ := ret[0].(string)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetChatExploreModelOverride indicates an expected call of GetChatExploreModelOverride.
|
||||
func (mr *MockStoreMockRecorder) GetChatExploreModelOverride(ctx any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetChatExploreModelOverride", reflect.TypeOf((*MockStore)(nil).GetChatExploreModelOverride), ctx)
|
||||
}
|
||||
|
||||
// GetChatFamilyIDsByRootID mocks base method.
|
||||
func (m *MockStore) GetChatFamilyIDsByRootID(ctx context.Context, id uuid.UUID) ([]uuid.UUID, error) {
|
||||
m.ctrl.T.Helper()
|
||||
@@ -3015,21 +2999,6 @@ func (mr *MockStoreMockRecorder) GetChatGatewayAPIKey(ctx, arg any) *gomock.Call
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetChatGatewayAPIKey", reflect.TypeOf((*MockStore)(nil).GetChatGatewayAPIKey), ctx, arg)
|
||||
}
|
||||
|
||||
// GetChatGeneralModelOverride mocks base method.
|
||||
func (m *MockStore) GetChatGeneralModelOverride(ctx context.Context) (string, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetChatGeneralModelOverride", ctx)
|
||||
ret0, _ := ret[0].(string)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetChatGeneralModelOverride indicates an expected call of GetChatGeneralModelOverride.
|
||||
func (mr *MockStoreMockRecorder) GetChatGeneralModelOverride(ctx any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetChatGeneralModelOverride", reflect.TypeOf((*MockStore)(nil).GetChatGeneralModelOverride), ctx)
|
||||
}
|
||||
|
||||
// GetChatHeartbeat mocks base method.
|
||||
func (m *MockStore) GetChatHeartbeat(ctx context.Context, arg database.GetChatHeartbeatParams) (database.ChatHeartbeat, error) {
|
||||
m.ctrl.T.Helper()
|
||||
@@ -3225,6 +3194,51 @@ func (mr *MockStoreMockRecorder) GetChatModelConfigsForTelemetry(ctx any) *gomoc
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetChatModelConfigsForTelemetry", reflect.TypeOf((*MockStore)(nil).GetChatModelConfigsForTelemetry), ctx)
|
||||
}
|
||||
|
||||
// GetChatOrganizationModelOverride mocks base method.
|
||||
func (m *MockStore) GetChatOrganizationModelOverride(ctx context.Context, arg database.GetChatOrganizationModelOverrideParams) (database.ChatOrganizationModelOverride, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetChatOrganizationModelOverride", ctx, arg)
|
||||
ret0, _ := ret[0].(database.ChatOrganizationModelOverride)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetChatOrganizationModelOverride indicates an expected call of GetChatOrganizationModelOverride.
|
||||
func (mr *MockStoreMockRecorder) GetChatOrganizationModelOverride(ctx, arg any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetChatOrganizationModelOverride", reflect.TypeOf((*MockStore)(nil).GetChatOrganizationModelOverride), ctx, arg)
|
||||
}
|
||||
|
||||
// GetChatOrganizationModelOverrides mocks base method.
|
||||
func (m *MockStore) GetChatOrganizationModelOverrides(ctx context.Context, organizationID uuid.UUID) ([]database.ChatOrganizationModelOverride, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetChatOrganizationModelOverrides", ctx, organizationID)
|
||||
ret0, _ := ret[0].([]database.ChatOrganizationModelOverride)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetChatOrganizationModelOverrides indicates an expected call of GetChatOrganizationModelOverrides.
|
||||
func (mr *MockStoreMockRecorder) GetChatOrganizationModelOverrides(ctx, organizationID any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetChatOrganizationModelOverrides", reflect.TypeOf((*MockStore)(nil).GetChatOrganizationModelOverrides), ctx, organizationID)
|
||||
}
|
||||
|
||||
// GetChatOrganizationModelOverridesByContext mocks base method.
|
||||
func (m *MockStore) GetChatOrganizationModelOverridesByContext(ctx context.Context, argContext string) ([]database.GetChatOrganizationModelOverridesByContextRow, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetChatOrganizationModelOverridesByContext", ctx, argContext)
|
||||
ret0, _ := ret[0].([]database.GetChatOrganizationModelOverridesByContextRow)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetChatOrganizationModelOverridesByContext indicates an expected call of GetChatOrganizationModelOverridesByContext.
|
||||
func (mr *MockStoreMockRecorder) GetChatOrganizationModelOverridesByContext(ctx, argContext any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetChatOrganizationModelOverridesByContext", reflect.TypeOf((*MockStore)(nil).GetChatOrganizationModelOverridesByContext), ctx, argContext)
|
||||
}
|
||||
|
||||
// GetChatPersonalModelOverridesEnabled mocks base method.
|
||||
func (m *MockStore) GetChatPersonalModelOverridesEnabled(ctx context.Context) (bool, error) {
|
||||
m.ctrl.T.Helper()
|
||||
@@ -3390,19 +3404,34 @@ func (mr *MockStoreMockRecorder) GetChatSystemPromptConfig(ctx any) *gomock.Call
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetChatSystemPromptConfig", reflect.TypeOf((*MockStore)(nil).GetChatSystemPromptConfig), ctx)
|
||||
}
|
||||
|
||||
// GetChatTitleGenerationModelOverride mocks base method.
|
||||
func (m *MockStore) GetChatTitleGenerationModelOverride(ctx context.Context) (string, error) {
|
||||
// GetChatUserModelOverride mocks base method.
|
||||
func (m *MockStore) GetChatUserModelOverride(ctx context.Context, arg database.GetChatUserModelOverrideParams) (database.ChatUserModelOverride, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetChatTitleGenerationModelOverride", ctx)
|
||||
ret0, _ := ret[0].(string)
|
||||
ret := m.ctrl.Call(m, "GetChatUserModelOverride", ctx, arg)
|
||||
ret0, _ := ret[0].(database.ChatUserModelOverride)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetChatTitleGenerationModelOverride indicates an expected call of GetChatTitleGenerationModelOverride.
|
||||
func (mr *MockStoreMockRecorder) GetChatTitleGenerationModelOverride(ctx any) *gomock.Call {
|
||||
// GetChatUserModelOverride indicates an expected call of GetChatUserModelOverride.
|
||||
func (mr *MockStoreMockRecorder) GetChatUserModelOverride(ctx, arg any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetChatTitleGenerationModelOverride", reflect.TypeOf((*MockStore)(nil).GetChatTitleGenerationModelOverride), ctx)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetChatUserModelOverride", reflect.TypeOf((*MockStore)(nil).GetChatUserModelOverride), ctx, arg)
|
||||
}
|
||||
|
||||
// GetChatUserModelOverrides mocks base method.
|
||||
func (m *MockStore) GetChatUserModelOverrides(ctx context.Context, arg database.GetChatUserModelOverridesParams) ([]database.ChatUserModelOverride, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetChatUserModelOverrides", ctx, arg)
|
||||
ret0, _ := ret[0].([]database.ChatUserModelOverride)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetChatUserModelOverrides indicates an expected call of GetChatUserModelOverrides.
|
||||
func (mr *MockStoreMockRecorder) GetChatUserModelOverrides(ctx, arg any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetChatUserModelOverrides", reflect.TypeOf((*MockStore)(nil).GetChatUserModelOverrides), ctx, arg)
|
||||
}
|
||||
|
||||
// GetChatUserPromptsByChatID mocks base method.
|
||||
@@ -6240,21 +6269,6 @@ func (mr *MockStoreMockRecorder) GetUserChatDebugLoggingEnabled(ctx, userID any)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetUserChatDebugLoggingEnabled", reflect.TypeOf((*MockStore)(nil).GetUserChatDebugLoggingEnabled), ctx, userID)
|
||||
}
|
||||
|
||||
// GetUserChatPersonalModelOverride mocks base method.
|
||||
func (m *MockStore) GetUserChatPersonalModelOverride(ctx context.Context, arg database.GetUserChatPersonalModelOverrideParams) (string, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetUserChatPersonalModelOverride", ctx, arg)
|
||||
ret0, _ := ret[0].(string)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetUserChatPersonalModelOverride indicates an expected call of GetUserChatPersonalModelOverride.
|
||||
func (mr *MockStoreMockRecorder) GetUserChatPersonalModelOverride(ctx, arg any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetUserChatPersonalModelOverride", reflect.TypeOf((*MockStore)(nil).GetUserChatPersonalModelOverride), ctx, arg)
|
||||
}
|
||||
|
||||
// GetUserCodeDiffDisplayMode mocks base method.
|
||||
func (m *MockStore) GetUserCodeDiffDisplayMode(ctx context.Context, userID uuid.UUID) (string, error) {
|
||||
m.ctrl.T.Helper()
|
||||
@@ -9208,21 +9222,6 @@ func (mr *MockStoreMockRecorder) ListUserChatCompactionThresholds(ctx, userID an
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListUserChatCompactionThresholds", reflect.TypeOf((*MockStore)(nil).ListUserChatCompactionThresholds), ctx, userID)
|
||||
}
|
||||
|
||||
// ListUserChatPersonalModelOverrides mocks base method.
|
||||
func (m *MockStore) ListUserChatPersonalModelOverrides(ctx context.Context, userID uuid.UUID) ([]database.ListUserChatPersonalModelOverridesRow, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "ListUserChatPersonalModelOverrides", ctx, userID)
|
||||
ret0, _ := ret[0].([]database.ListUserChatPersonalModelOverridesRow)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// ListUserChatPersonalModelOverrides indicates an expected call of ListUserChatPersonalModelOverrides.
|
||||
func (mr *MockStoreMockRecorder) ListUserChatPersonalModelOverrides(ctx, userID any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListUserChatPersonalModelOverrides", reflect.TypeOf((*MockStore)(nil).ListUserChatPersonalModelOverrides), ctx, userID)
|
||||
}
|
||||
|
||||
// ListUserSecrets mocks base method.
|
||||
func (m *MockStore) ListUserSecrets(ctx context.Context, userID uuid.UUID) ([]database.ListUserSecretsRow, error) {
|
||||
m.ctrl.T.Helper()
|
||||
@@ -11846,20 +11845,6 @@ func (mr *MockStoreMockRecorder) UpsertChatAutoArchiveDays(ctx, autoArchiveDays
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpsertChatAutoArchiveDays", reflect.TypeOf((*MockStore)(nil).UpsertChatAutoArchiveDays), ctx, autoArchiveDays)
|
||||
}
|
||||
|
||||
// UpsertChatCompactionModelOverride mocks base method.
|
||||
func (m *MockStore) UpsertChatCompactionModelOverride(ctx context.Context, value string) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "UpsertChatCompactionModelOverride", ctx, value)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// UpsertChatCompactionModelOverride indicates an expected call of UpsertChatCompactionModelOverride.
|
||||
func (mr *MockStoreMockRecorder) UpsertChatCompactionModelOverride(ctx, value any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpsertChatCompactionModelOverride", reflect.TypeOf((*MockStore)(nil).UpsertChatCompactionModelOverride), ctx, value)
|
||||
}
|
||||
|
||||
// UpsertChatComputerUseProvider mocks base method.
|
||||
func (m *MockStore) UpsertChatComputerUseProvider(ctx context.Context, provider string) error {
|
||||
m.ctrl.T.Helper()
|
||||
@@ -11946,34 +11931,6 @@ func (mr *MockStoreMockRecorder) UpsertChatDiffStatusReference(ctx, arg any) *go
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpsertChatDiffStatusReference", reflect.TypeOf((*MockStore)(nil).UpsertChatDiffStatusReference), ctx, arg)
|
||||
}
|
||||
|
||||
// UpsertChatExploreModelOverride mocks base method.
|
||||
func (m *MockStore) UpsertChatExploreModelOverride(ctx context.Context, value string) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "UpsertChatExploreModelOverride", ctx, value)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// UpsertChatExploreModelOverride indicates an expected call of UpsertChatExploreModelOverride.
|
||||
func (mr *MockStoreMockRecorder) UpsertChatExploreModelOverride(ctx, value any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpsertChatExploreModelOverride", reflect.TypeOf((*MockStore)(nil).UpsertChatExploreModelOverride), ctx, value)
|
||||
}
|
||||
|
||||
// UpsertChatGeneralModelOverride mocks base method.
|
||||
func (m *MockStore) UpsertChatGeneralModelOverride(ctx context.Context, value string) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "UpsertChatGeneralModelOverride", ctx, value)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// UpsertChatGeneralModelOverride indicates an expected call of UpsertChatGeneralModelOverride.
|
||||
func (mr *MockStoreMockRecorder) UpsertChatGeneralModelOverride(ctx, value any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpsertChatGeneralModelOverride", reflect.TypeOf((*MockStore)(nil).UpsertChatGeneralModelOverride), ctx, value)
|
||||
}
|
||||
|
||||
// UpsertChatHeartbeat mocks base method.
|
||||
func (m *MockStore) UpsertChatHeartbeat(ctx context.Context, arg database.UpsertChatHeartbeatParams) error {
|
||||
m.ctrl.T.Helper()
|
||||
@@ -12002,6 +11959,20 @@ func (mr *MockStoreMockRecorder) UpsertChatIncludeDefaultSystemPrompt(ctx, inclu
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpsertChatIncludeDefaultSystemPrompt", reflect.TypeOf((*MockStore)(nil).UpsertChatIncludeDefaultSystemPrompt), ctx, includeDefaultSystemPrompt)
|
||||
}
|
||||
|
||||
// UpsertChatOrganizationModelOverride mocks base method.
|
||||
func (m *MockStore) UpsertChatOrganizationModelOverride(ctx context.Context, arg database.UpsertChatOrganizationModelOverrideParams) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "UpsertChatOrganizationModelOverride", ctx, arg)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// UpsertChatOrganizationModelOverride indicates an expected call of UpsertChatOrganizationModelOverride.
|
||||
func (mr *MockStoreMockRecorder) UpsertChatOrganizationModelOverride(ctx, arg any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpsertChatOrganizationModelOverride", reflect.TypeOf((*MockStore)(nil).UpsertChatOrganizationModelOverride), ctx, arg)
|
||||
}
|
||||
|
||||
// UpsertChatPersonalModelOverridesEnabled mocks base method.
|
||||
func (m *MockStore) UpsertChatPersonalModelOverridesEnabled(ctx context.Context, enabled bool) error {
|
||||
m.ctrl.T.Helper()
|
||||
@@ -12058,18 +12029,18 @@ func (mr *MockStoreMockRecorder) UpsertChatSystemPrompt(ctx, value any) *gomock.
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpsertChatSystemPrompt", reflect.TypeOf((*MockStore)(nil).UpsertChatSystemPrompt), ctx, value)
|
||||
}
|
||||
|
||||
// UpsertChatTitleGenerationModelOverride mocks base method.
|
||||
func (m *MockStore) UpsertChatTitleGenerationModelOverride(ctx context.Context, value string) error {
|
||||
// UpsertChatUserModelOverride mocks base method.
|
||||
func (m *MockStore) UpsertChatUserModelOverride(ctx context.Context, arg database.UpsertChatUserModelOverrideParams) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "UpsertChatTitleGenerationModelOverride", ctx, value)
|
||||
ret := m.ctrl.Call(m, "UpsertChatUserModelOverride", ctx, arg)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// UpsertChatTitleGenerationModelOverride indicates an expected call of UpsertChatTitleGenerationModelOverride.
|
||||
func (mr *MockStoreMockRecorder) UpsertChatTitleGenerationModelOverride(ctx, value any) *gomock.Call {
|
||||
// UpsertChatUserModelOverride indicates an expected call of UpsertChatUserModelOverride.
|
||||
func (mr *MockStoreMockRecorder) UpsertChatUserModelOverride(ctx, arg any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpsertChatTitleGenerationModelOverride", reflect.TypeOf((*MockStore)(nil).UpsertChatTitleGenerationModelOverride), ctx, value)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpsertChatUserModelOverride", reflect.TypeOf((*MockStore)(nil).UpsertChatUserModelOverride), ctx, arg)
|
||||
}
|
||||
|
||||
// UpsertChatWorkspaceTTL mocks base method.
|
||||
@@ -12417,20 +12388,6 @@ func (mr *MockStoreMockRecorder) UpsertUserChatDebugLoggingEnabled(ctx, arg any)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpsertUserChatDebugLoggingEnabled", reflect.TypeOf((*MockStore)(nil).UpsertUserChatDebugLoggingEnabled), ctx, arg)
|
||||
}
|
||||
|
||||
// UpsertUserChatPersonalModelOverride mocks base method.
|
||||
func (m *MockStore) UpsertUserChatPersonalModelOverride(ctx context.Context, arg database.UpsertUserChatPersonalModelOverrideParams) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "UpsertUserChatPersonalModelOverride", ctx, arg)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// UpsertUserChatPersonalModelOverride indicates an expected call of UpsertUserChatPersonalModelOverride.
|
||||
func (mr *MockStoreMockRecorder) UpsertUserChatPersonalModelOverride(ctx, arg any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpsertUserChatPersonalModelOverride", reflect.TypeOf((*MockStore)(nil).UpsertUserChatPersonalModelOverride), ctx, arg)
|
||||
}
|
||||
|
||||
// UpsertWebpushVAPIDKeys mocks base method.
|
||||
func (m *MockStore) UpsertWebpushVAPIDKeys(ctx context.Context, arg database.UpsertWebpushVAPIDKeysParams) error {
|
||||
m.ctrl.T.Helper()
|
||||
|
||||
Generated
+52
@@ -2094,6 +2094,15 @@ CREATE TABLE chat_model_configs (
|
||||
CONSTRAINT chat_model_configs_user_acl_is_object CHECK ((jsonb_typeof(user_acl) = 'object'::text))
|
||||
);
|
||||
|
||||
CREATE TABLE chat_organization_model_overrides (
|
||||
id uuid DEFAULT gen_random_uuid() NOT NULL,
|
||||
organization_id uuid NOT NULL,
|
||||
context text NOT NULL,
|
||||
model_config_id uuid NOT NULL,
|
||||
reasoning_effort text,
|
||||
CONSTRAINT chat_organization_model_overrides_context_check CHECK ((context = ANY (ARRAY['general'::text, 'explore'::text, 'title_generation'::text, 'compaction'::text, 'advisor'::text])))
|
||||
);
|
||||
|
||||
CREATE SEQUENCE chat_queued_messages_position_seq
|
||||
START WITH 1
|
||||
INCREMENT BY 1
|
||||
@@ -2145,6 +2154,19 @@ CREATE SEQUENCE chat_usage_limit_config_id_seq
|
||||
|
||||
ALTER SEQUENCE chat_usage_limit_config_id_seq OWNED BY chat_usage_limit_config.id;
|
||||
|
||||
CREATE TABLE chat_user_model_overrides (
|
||||
id uuid DEFAULT gen_random_uuid() NOT NULL,
|
||||
user_id uuid NOT NULL,
|
||||
organization_id uuid NOT NULL,
|
||||
context text NOT NULL,
|
||||
mode text NOT NULL,
|
||||
model_config_id uuid,
|
||||
reasoning_effort text,
|
||||
CONSTRAINT chat_user_model_overrides_context_check CHECK ((context = ANY (ARRAY['root'::text, 'general'::text, 'explore'::text]))),
|
||||
CONSTRAINT chat_user_model_overrides_mode_check CHECK ((mode = ANY (ARRAY['model'::text, 'chat_default'::text, 'deployment_default'::text]))),
|
||||
CONSTRAINT chat_user_model_overrides_model_requires_config_check CHECK (((mode = 'model'::text) = (model_config_id IS NOT NULL)))
|
||||
);
|
||||
|
||||
CREATE TABLE chats (
|
||||
id uuid DEFAULT gen_random_uuid() NOT NULL,
|
||||
owner_id uuid NOT NULL,
|
||||
@@ -4400,9 +4422,18 @@ ALTER TABLE ONLY chat_heartbeats
|
||||
ALTER TABLE ONLY chat_messages
|
||||
ADD CONSTRAINT chat_messages_pkey PRIMARY KEY (id);
|
||||
|
||||
ALTER TABLE ONLY chat_model_configs
|
||||
ADD CONSTRAINT chat_model_configs_organization_id_id_key UNIQUE (organization_id, id);
|
||||
|
||||
ALTER TABLE ONLY chat_model_configs
|
||||
ADD CONSTRAINT chat_model_configs_pkey PRIMARY KEY (id);
|
||||
|
||||
ALTER TABLE ONLY chat_organization_model_overrides
|
||||
ADD CONSTRAINT chat_organization_model_overrides_organization_id_context_key UNIQUE (organization_id, context);
|
||||
|
||||
ALTER TABLE ONLY chat_organization_model_overrides
|
||||
ADD CONSTRAINT chat_organization_model_overrides_pkey PRIMARY KEY (id);
|
||||
|
||||
ALTER TABLE ONLY chat_queued_messages
|
||||
ADD CONSTRAINT chat_queued_messages_pkey PRIMARY KEY (id);
|
||||
|
||||
@@ -4412,6 +4443,12 @@ ALTER TABLE ONLY chat_usage_limit_config
|
||||
ALTER TABLE ONLY chat_usage_limit_config
|
||||
ADD CONSTRAINT chat_usage_limit_config_singleton_key UNIQUE (singleton);
|
||||
|
||||
ALTER TABLE ONLY chat_user_model_overrides
|
||||
ADD CONSTRAINT chat_user_model_overrides_pkey PRIMARY KEY (id);
|
||||
|
||||
ALTER TABLE ONLY chat_user_model_overrides
|
||||
ADD CONSTRAINT chat_user_model_overrides_user_organization_context_key UNIQUE (user_id, organization_id, context);
|
||||
|
||||
ALTER TABLE ONLY chats
|
||||
ADD CONSTRAINT chats_pkey PRIMARY KEY (id);
|
||||
|
||||
@@ -5276,9 +5313,24 @@ ALTER TABLE ONLY chat_model_configs
|
||||
ALTER TABLE ONLY chat_model_configs
|
||||
ADD CONSTRAINT chat_model_configs_updated_by_fkey FOREIGN KEY (updated_by) REFERENCES users(id);
|
||||
|
||||
ALTER TABLE ONLY chat_organization_model_overrides
|
||||
ADD CONSTRAINT chat_organization_model_overrides_organization_id_fkey FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE ONLY chat_organization_model_overrides
|
||||
ADD CONSTRAINT chat_organization_model_overrides_organization_model_config_fke FOREIGN KEY (organization_id, model_config_id) REFERENCES chat_model_configs(organization_id, id);
|
||||
|
||||
ALTER TABLE ONLY chat_queued_messages
|
||||
ADD CONSTRAINT chat_queued_messages_chat_id_fkey FOREIGN KEY (chat_id) REFERENCES chats(id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE ONLY chat_user_model_overrides
|
||||
ADD CONSTRAINT chat_user_model_overrides_organization_id_fkey FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE ONLY chat_user_model_overrides
|
||||
ADD CONSTRAINT chat_user_model_overrides_organization_model_config_fkey FOREIGN KEY (organization_id, model_config_id) REFERENCES chat_model_configs(organization_id, id);
|
||||
|
||||
ALTER TABLE ONLY chat_user_model_overrides
|
||||
ADD CONSTRAINT chat_user_model_overrides_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE ONLY chats
|
||||
ADD CONSTRAINT chats_agent_id_fkey FOREIGN KEY (agent_id) REFERENCES workspace_agents(id) ON DELETE SET NULL;
|
||||
|
||||
|
||||
+161
-156
@@ -6,160 +6,165 @@ type ForeignKeyConstraint string
|
||||
|
||||
// ForeignKeyConstraint enums.
|
||||
const (
|
||||
ForeignKeyAIProviderKeysAPIKeyKeyID ForeignKeyConstraint = "ai_provider_keys_api_key_key_id_fkey" // ALTER TABLE ONLY ai_provider_keys ADD CONSTRAINT ai_provider_keys_api_key_key_id_fkey FOREIGN KEY (api_key_key_id) REFERENCES dbcrypt_keys(active_key_digest);
|
||||
ForeignKeyAIProviderKeysProviderID ForeignKeyConstraint = "ai_provider_keys_provider_id_fkey" // ALTER TABLE ONLY ai_provider_keys ADD CONSTRAINT ai_provider_keys_provider_id_fkey FOREIGN KEY (provider_id) REFERENCES ai_providers(id) ON DELETE CASCADE;
|
||||
ForeignKeyAIProvidersSettingsKeyID ForeignKeyConstraint = "ai_providers_settings_key_id_fkey" // ALTER TABLE ONLY ai_providers ADD CONSTRAINT ai_providers_settings_key_id_fkey FOREIGN KEY (settings_key_id) REFERENCES dbcrypt_keys(active_key_digest);
|
||||
ForeignKeyAISeatStateUserID ForeignKeyConstraint = "ai_seat_state_user_id_fkey" // ALTER TABLE ONLY ai_seat_state ADD CONSTRAINT ai_seat_state_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
|
||||
ForeignKeyAibridgeInterceptionsInitiatorID ForeignKeyConstraint = "aibridge_interceptions_initiator_id_fkey" // ALTER TABLE ONLY aibridge_interceptions ADD CONSTRAINT aibridge_interceptions_initiator_id_fkey FOREIGN KEY (initiator_id) REFERENCES users(id);
|
||||
ForeignKeyAPIKeysUserIDUUID ForeignKeyConstraint = "api_keys_user_id_uuid_fkey" // ALTER TABLE ONLY api_keys ADD CONSTRAINT api_keys_user_id_uuid_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
|
||||
ForeignKeyBoundaryLogsOwnerID ForeignKeyConstraint = "boundary_logs_owner_id_fkey" // ALTER TABLE ONLY boundary_logs ADD CONSTRAINT boundary_logs_owner_id_fkey FOREIGN KEY (owner_id) REFERENCES users(id) ON DELETE SET NULL;
|
||||
ForeignKeyBoundarySessionsOwnerID ForeignKeyConstraint = "boundary_sessions_owner_id_fkey" // ALTER TABLE ONLY boundary_sessions ADD CONSTRAINT boundary_sessions_owner_id_fkey FOREIGN KEY (owner_id) REFERENCES users(id) ON DELETE SET NULL;
|
||||
ForeignKeyBoundarySessionsWorkspaceAgentID ForeignKeyConstraint = "boundary_sessions_workspace_agent_id_fkey" // ALTER TABLE ONLY boundary_sessions ADD CONSTRAINT boundary_sessions_workspace_agent_id_fkey FOREIGN KEY (workspace_agent_id) REFERENCES workspace_agents(id);
|
||||
ForeignKeyChatContextResourcesChatID ForeignKeyConstraint = "chat_context_resources_chat_id_fkey" // ALTER TABLE ONLY chat_context_resources ADD CONSTRAINT chat_context_resources_chat_id_fkey FOREIGN KEY (chat_id) REFERENCES chats(id) ON DELETE CASCADE;
|
||||
ForeignKeyChatDebugRunsChatID ForeignKeyConstraint = "chat_debug_runs_chat_id_fkey" // ALTER TABLE ONLY chat_debug_runs ADD CONSTRAINT chat_debug_runs_chat_id_fkey FOREIGN KEY (chat_id) REFERENCES chats(id) ON DELETE CASCADE;
|
||||
ForeignKeyChatDebugStepsChatID ForeignKeyConstraint = "chat_debug_steps_chat_id_fkey" // ALTER TABLE ONLY chat_debug_steps ADD CONSTRAINT chat_debug_steps_chat_id_fkey FOREIGN KEY (chat_id) REFERENCES chats(id) ON DELETE CASCADE;
|
||||
ForeignKeyChatDiffStatusesChatID ForeignKeyConstraint = "chat_diff_statuses_chat_id_fkey" // ALTER TABLE ONLY chat_diff_statuses ADD CONSTRAINT chat_diff_statuses_chat_id_fkey FOREIGN KEY (chat_id) REFERENCES chats(id) ON DELETE CASCADE;
|
||||
ForeignKeyChatFileLinksChatID ForeignKeyConstraint = "chat_file_links_chat_id_fkey" // ALTER TABLE ONLY chat_file_links ADD CONSTRAINT chat_file_links_chat_id_fkey FOREIGN KEY (chat_id) REFERENCES chats(id) ON DELETE CASCADE;
|
||||
ForeignKeyChatFileLinksFileID ForeignKeyConstraint = "chat_file_links_file_id_fkey" // ALTER TABLE ONLY chat_file_links ADD CONSTRAINT chat_file_links_file_id_fkey FOREIGN KEY (file_id) REFERENCES chat_files(id) ON DELETE CASCADE;
|
||||
ForeignKeyChatFilesOrganizationID ForeignKeyConstraint = "chat_files_organization_id_fkey" // ALTER TABLE ONLY chat_files ADD CONSTRAINT chat_files_organization_id_fkey FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE;
|
||||
ForeignKeyChatFilesOwnerID ForeignKeyConstraint = "chat_files_owner_id_fkey" // ALTER TABLE ONLY chat_files ADD CONSTRAINT chat_files_owner_id_fkey FOREIGN KEY (owner_id) REFERENCES users(id) ON DELETE CASCADE;
|
||||
ForeignKeyChatHeartbeatsChatID ForeignKeyConstraint = "chat_heartbeats_chat_id_fkey" // ALTER TABLE ONLY chat_heartbeats ADD CONSTRAINT chat_heartbeats_chat_id_fkey FOREIGN KEY (chat_id) REFERENCES chats(id) ON DELETE CASCADE;
|
||||
ForeignKeyChatMessagesChatID ForeignKeyConstraint = "chat_messages_chat_id_fkey" // ALTER TABLE ONLY chat_messages ADD CONSTRAINT chat_messages_chat_id_fkey FOREIGN KEY (chat_id) REFERENCES chats(id) ON DELETE CASCADE;
|
||||
ForeignKeyChatMessagesModelConfigID ForeignKeyConstraint = "chat_messages_model_config_id_fkey" // ALTER TABLE ONLY chat_messages ADD CONSTRAINT chat_messages_model_config_id_fkey FOREIGN KEY (model_config_id) REFERENCES chat_model_configs(id);
|
||||
ForeignKeyChatModelConfigsAIProviderID ForeignKeyConstraint = "chat_model_configs_ai_provider_id_fkey" // ALTER TABLE ONLY chat_model_configs ADD CONSTRAINT chat_model_configs_ai_provider_id_fkey FOREIGN KEY (ai_provider_id) REFERENCES ai_providers(id);
|
||||
ForeignKeyChatModelConfigsCreatedBy ForeignKeyConstraint = "chat_model_configs_created_by_fkey" // ALTER TABLE ONLY chat_model_configs ADD CONSTRAINT chat_model_configs_created_by_fkey FOREIGN KEY (created_by) REFERENCES users(id);
|
||||
ForeignKeyChatModelConfigsOrganizationID ForeignKeyConstraint = "chat_model_configs_organization_id_fkey" // ALTER TABLE ONLY chat_model_configs ADD CONSTRAINT chat_model_configs_organization_id_fkey FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE;
|
||||
ForeignKeyChatModelConfigsUpdatedBy ForeignKeyConstraint = "chat_model_configs_updated_by_fkey" // ALTER TABLE ONLY chat_model_configs ADD CONSTRAINT chat_model_configs_updated_by_fkey FOREIGN KEY (updated_by) REFERENCES users(id);
|
||||
ForeignKeyChatQueuedMessagesChatID ForeignKeyConstraint = "chat_queued_messages_chat_id_fkey" // ALTER TABLE ONLY chat_queued_messages ADD CONSTRAINT chat_queued_messages_chat_id_fkey FOREIGN KEY (chat_id) REFERENCES chats(id) ON DELETE CASCADE;
|
||||
ForeignKeyChatsAgentID ForeignKeyConstraint = "chats_agent_id_fkey" // ALTER TABLE ONLY chats ADD CONSTRAINT chats_agent_id_fkey FOREIGN KEY (agent_id) REFERENCES workspace_agents(id) ON DELETE SET NULL;
|
||||
ForeignKeyChatsBuildID ForeignKeyConstraint = "chats_build_id_fkey" // ALTER TABLE ONLY chats ADD CONSTRAINT chats_build_id_fkey FOREIGN KEY (build_id) REFERENCES workspace_builds(id) ON DELETE SET NULL;
|
||||
ForeignKeyChatsLastModelConfigID ForeignKeyConstraint = "chats_last_model_config_id_fkey" // ALTER TABLE ONLY chats ADD CONSTRAINT chats_last_model_config_id_fkey FOREIGN KEY (last_model_config_id) REFERENCES chat_model_configs(id);
|
||||
ForeignKeyChatsOrganizationID ForeignKeyConstraint = "chats_organization_id_fkey" // ALTER TABLE ONLY chats ADD CONSTRAINT chats_organization_id_fkey FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE;
|
||||
ForeignKeyChatsOwnerID ForeignKeyConstraint = "chats_owner_id_fkey" // ALTER TABLE ONLY chats ADD CONSTRAINT chats_owner_id_fkey FOREIGN KEY (owner_id) REFERENCES users(id) ON DELETE CASCADE;
|
||||
ForeignKeyChatsParentChatID ForeignKeyConstraint = "chats_parent_chat_id_fkey" // ALTER TABLE ONLY chats ADD CONSTRAINT chats_parent_chat_id_fkey FOREIGN KEY (parent_chat_id) REFERENCES chats(id) ON DELETE SET NULL;
|
||||
ForeignKeyChatsRootChatID ForeignKeyConstraint = "chats_root_chat_id_fkey" // ALTER TABLE ONLY chats ADD CONSTRAINT chats_root_chat_id_fkey FOREIGN KEY (root_chat_id) REFERENCES chats(id) ON DELETE SET NULL;
|
||||
ForeignKeyChatsWorkspaceID ForeignKeyConstraint = "chats_workspace_id_fkey" // ALTER TABLE ONLY chats ADD CONSTRAINT chats_workspace_id_fkey FOREIGN KEY (workspace_id) REFERENCES workspaces(id) ON DELETE SET NULL;
|
||||
ForeignKeyConnectionLogsOrganizationID ForeignKeyConstraint = "connection_logs_organization_id_fkey" // ALTER TABLE ONLY connection_logs ADD CONSTRAINT connection_logs_organization_id_fkey FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE;
|
||||
ForeignKeyConnectionLogsWorkspaceID ForeignKeyConstraint = "connection_logs_workspace_id_fkey" // ALTER TABLE ONLY connection_logs ADD CONSTRAINT connection_logs_workspace_id_fkey FOREIGN KEY (workspace_id) REFERENCES workspaces(id) ON DELETE CASCADE;
|
||||
ForeignKeyConnectionLogsWorkspaceOwnerID ForeignKeyConstraint = "connection_logs_workspace_owner_id_fkey" // ALTER TABLE ONLY connection_logs ADD CONSTRAINT connection_logs_workspace_owner_id_fkey FOREIGN KEY (workspace_owner_id) REFERENCES users(id) ON DELETE CASCADE;
|
||||
ForeignKeyCryptoKeysSecretKeyID ForeignKeyConstraint = "crypto_keys_secret_key_id_fkey" // ALTER TABLE ONLY crypto_keys ADD CONSTRAINT crypto_keys_secret_key_id_fkey FOREIGN KEY (secret_key_id) REFERENCES dbcrypt_keys(active_key_digest);
|
||||
ForeignKeyFkChatDebugStepsRunChat ForeignKeyConstraint = "fk_chat_debug_steps_run_chat" // ALTER TABLE ONLY chat_debug_steps ADD CONSTRAINT fk_chat_debug_steps_run_chat FOREIGN KEY (run_id, chat_id) REFERENCES chat_debug_runs(id, chat_id) ON DELETE CASCADE;
|
||||
ForeignKeyFkOauth2ProviderAppTokensUserID ForeignKeyConstraint = "fk_oauth2_provider_app_tokens_user_id" // ALTER TABLE ONLY oauth2_provider_app_tokens ADD CONSTRAINT fk_oauth2_provider_app_tokens_user_id FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
|
||||
ForeignKeyGitAuthLinksOauthAccessTokenKeyID ForeignKeyConstraint = "git_auth_links_oauth_access_token_key_id_fkey" // ALTER TABLE ONLY external_auth_links ADD CONSTRAINT git_auth_links_oauth_access_token_key_id_fkey FOREIGN KEY (oauth_access_token_key_id) REFERENCES dbcrypt_keys(active_key_digest);
|
||||
ForeignKeyGitAuthLinksOauthRefreshTokenKeyID ForeignKeyConstraint = "git_auth_links_oauth_refresh_token_key_id_fkey" // ALTER TABLE ONLY external_auth_links ADD CONSTRAINT git_auth_links_oauth_refresh_token_key_id_fkey FOREIGN KEY (oauth_refresh_token_key_id) REFERENCES dbcrypt_keys(active_key_digest);
|
||||
ForeignKeyGitSSHKeysPrivateKeyKeyID ForeignKeyConstraint = "gitsshkeys_private_key_key_id_fkey" // ALTER TABLE ONLY gitsshkeys ADD CONSTRAINT gitsshkeys_private_key_key_id_fkey FOREIGN KEY (private_key_key_id) REFERENCES dbcrypt_keys(active_key_digest);
|
||||
ForeignKeyGitSSHKeysUserID ForeignKeyConstraint = "gitsshkeys_user_id_fkey" // ALTER TABLE ONLY gitsshkeys ADD CONSTRAINT gitsshkeys_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id);
|
||||
ForeignKeyGroupAIBudgetsGroupID ForeignKeyConstraint = "group_ai_budgets_group_id_fkey" // ALTER TABLE ONLY group_ai_budgets ADD CONSTRAINT group_ai_budgets_group_id_fkey FOREIGN KEY (group_id) REFERENCES groups(id) ON DELETE CASCADE;
|
||||
ForeignKeyGroupMembersGroupID ForeignKeyConstraint = "group_members_group_id_fkey" // ALTER TABLE ONLY group_members ADD CONSTRAINT group_members_group_id_fkey FOREIGN KEY (group_id) REFERENCES groups(id) ON DELETE CASCADE;
|
||||
ForeignKeyGroupMembersUserID ForeignKeyConstraint = "group_members_user_id_fkey" // ALTER TABLE ONLY group_members ADD CONSTRAINT group_members_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
|
||||
ForeignKeyGroupsOrganizationID ForeignKeyConstraint = "groups_organization_id_fkey" // ALTER TABLE ONLY groups ADD CONSTRAINT groups_organization_id_fkey FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE;
|
||||
ForeignKeyInboxNotificationsTemplateID ForeignKeyConstraint = "inbox_notifications_template_id_fkey" // ALTER TABLE ONLY inbox_notifications ADD CONSTRAINT inbox_notifications_template_id_fkey FOREIGN KEY (template_id) REFERENCES notification_templates(id) ON DELETE CASCADE;
|
||||
ForeignKeyInboxNotificationsUserID ForeignKeyConstraint = "inbox_notifications_user_id_fkey" // ALTER TABLE ONLY inbox_notifications ADD CONSTRAINT inbox_notifications_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
|
||||
ForeignKeyJfrogXrayScansAgentID ForeignKeyConstraint = "jfrog_xray_scans_agent_id_fkey" // ALTER TABLE ONLY jfrog_xray_scans ADD CONSTRAINT jfrog_xray_scans_agent_id_fkey FOREIGN KEY (agent_id) REFERENCES workspace_agents(id) ON DELETE CASCADE;
|
||||
ForeignKeyJfrogXrayScansWorkspaceID ForeignKeyConstraint = "jfrog_xray_scans_workspace_id_fkey" // ALTER TABLE ONLY jfrog_xray_scans ADD CONSTRAINT jfrog_xray_scans_workspace_id_fkey FOREIGN KEY (workspace_id) REFERENCES workspaces(id) ON DELETE CASCADE;
|
||||
ForeignKeyMcpServerConfigsAPIKeyValueKeyID ForeignKeyConstraint = "mcp_server_configs_api_key_value_key_id_fkey" // ALTER TABLE ONLY mcp_server_configs ADD CONSTRAINT mcp_server_configs_api_key_value_key_id_fkey FOREIGN KEY (api_key_value_key_id) REFERENCES dbcrypt_keys(active_key_digest);
|
||||
ForeignKeyMcpServerConfigsCreatedBy ForeignKeyConstraint = "mcp_server_configs_created_by_fkey" // ALTER TABLE ONLY mcp_server_configs ADD CONSTRAINT mcp_server_configs_created_by_fkey FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE SET NULL;
|
||||
ForeignKeyMcpServerConfigsCustomHeadersKeyID ForeignKeyConstraint = "mcp_server_configs_custom_headers_key_id_fkey" // ALTER TABLE ONLY mcp_server_configs ADD CONSTRAINT mcp_server_configs_custom_headers_key_id_fkey FOREIGN KEY (custom_headers_key_id) REFERENCES dbcrypt_keys(active_key_digest);
|
||||
ForeignKeyMcpServerConfigsOauth2ClientSecretKeyID ForeignKeyConstraint = "mcp_server_configs_oauth2_client_secret_key_id_fkey" // ALTER TABLE ONLY mcp_server_configs ADD CONSTRAINT mcp_server_configs_oauth2_client_secret_key_id_fkey FOREIGN KEY (oauth2_client_secret_key_id) REFERENCES dbcrypt_keys(active_key_digest);
|
||||
ForeignKeyMcpServerConfigsOrganizationID ForeignKeyConstraint = "mcp_server_configs_organization_id_fkey" // ALTER TABLE ONLY mcp_server_configs ADD CONSTRAINT mcp_server_configs_organization_id_fkey FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE;
|
||||
ForeignKeyMcpServerConfigsUpdatedBy ForeignKeyConstraint = "mcp_server_configs_updated_by_fkey" // ALTER TABLE ONLY mcp_server_configs ADD CONSTRAINT mcp_server_configs_updated_by_fkey FOREIGN KEY (updated_by) REFERENCES users(id) ON DELETE SET NULL;
|
||||
ForeignKeyMcpServerUserTokensAccessTokenKeyID ForeignKeyConstraint = "mcp_server_user_tokens_access_token_key_id_fkey" // ALTER TABLE ONLY mcp_server_user_tokens ADD CONSTRAINT mcp_server_user_tokens_access_token_key_id_fkey FOREIGN KEY (access_token_key_id) REFERENCES dbcrypt_keys(active_key_digest);
|
||||
ForeignKeyMcpServerUserTokensMcpServerConfigID ForeignKeyConstraint = "mcp_server_user_tokens_mcp_server_config_id_fkey" // ALTER TABLE ONLY mcp_server_user_tokens ADD CONSTRAINT mcp_server_user_tokens_mcp_server_config_id_fkey FOREIGN KEY (mcp_server_config_id) REFERENCES mcp_server_configs(id) ON DELETE CASCADE;
|
||||
ForeignKeyMcpServerUserTokensRefreshTokenKeyID ForeignKeyConstraint = "mcp_server_user_tokens_refresh_token_key_id_fkey" // ALTER TABLE ONLY mcp_server_user_tokens ADD CONSTRAINT mcp_server_user_tokens_refresh_token_key_id_fkey FOREIGN KEY (refresh_token_key_id) REFERENCES dbcrypt_keys(active_key_digest);
|
||||
ForeignKeyMcpServerUserTokensUserID ForeignKeyConstraint = "mcp_server_user_tokens_user_id_fkey" // ALTER TABLE ONLY mcp_server_user_tokens ADD CONSTRAINT mcp_server_user_tokens_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
|
||||
ForeignKeyNotificationMessagesNotificationTemplateID ForeignKeyConstraint = "notification_messages_notification_template_id_fkey" // ALTER TABLE ONLY notification_messages ADD CONSTRAINT notification_messages_notification_template_id_fkey FOREIGN KEY (notification_template_id) REFERENCES notification_templates(id) ON DELETE CASCADE;
|
||||
ForeignKeyNotificationMessagesUserID ForeignKeyConstraint = "notification_messages_user_id_fkey" // ALTER TABLE ONLY notification_messages ADD CONSTRAINT notification_messages_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
|
||||
ForeignKeyNotificationPreferencesNotificationTemplateID ForeignKeyConstraint = "notification_preferences_notification_template_id_fkey" // ALTER TABLE ONLY notification_preferences ADD CONSTRAINT notification_preferences_notification_template_id_fkey FOREIGN KEY (notification_template_id) REFERENCES notification_templates(id) ON DELETE CASCADE;
|
||||
ForeignKeyNotificationPreferencesUserID ForeignKeyConstraint = "notification_preferences_user_id_fkey" // ALTER TABLE ONLY notification_preferences ADD CONSTRAINT notification_preferences_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
|
||||
ForeignKeyOauth2ProviderAppCodesAppID ForeignKeyConstraint = "oauth2_provider_app_codes_app_id_fkey" // ALTER TABLE ONLY oauth2_provider_app_codes ADD CONSTRAINT oauth2_provider_app_codes_app_id_fkey FOREIGN KEY (app_id) REFERENCES oauth2_provider_apps(id) ON DELETE CASCADE;
|
||||
ForeignKeyOauth2ProviderAppCodesUserID ForeignKeyConstraint = "oauth2_provider_app_codes_user_id_fkey" // ALTER TABLE ONLY oauth2_provider_app_codes ADD CONSTRAINT oauth2_provider_app_codes_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
|
||||
ForeignKeyOauth2ProviderAppSecretsAppID ForeignKeyConstraint = "oauth2_provider_app_secrets_app_id_fkey" // ALTER TABLE ONLY oauth2_provider_app_secrets ADD CONSTRAINT oauth2_provider_app_secrets_app_id_fkey FOREIGN KEY (app_id) REFERENCES oauth2_provider_apps(id) ON DELETE CASCADE;
|
||||
ForeignKeyOauth2ProviderAppTokensAPIKeyID ForeignKeyConstraint = "oauth2_provider_app_tokens_api_key_id_fkey" // ALTER TABLE ONLY oauth2_provider_app_tokens ADD CONSTRAINT oauth2_provider_app_tokens_api_key_id_fkey FOREIGN KEY (api_key_id) REFERENCES api_keys(id) ON DELETE CASCADE;
|
||||
ForeignKeyOauth2ProviderAppTokensAppID ForeignKeyConstraint = "oauth2_provider_app_tokens_app_id_fkey" // ALTER TABLE ONLY oauth2_provider_app_tokens ADD CONSTRAINT oauth2_provider_app_tokens_app_id_fkey FOREIGN KEY (app_id) REFERENCES oauth2_provider_apps(id) ON DELETE CASCADE;
|
||||
ForeignKeyOauth2ProviderAppTokensAppSecretID ForeignKeyConstraint = "oauth2_provider_app_tokens_app_secret_id_fkey" // ALTER TABLE ONLY oauth2_provider_app_tokens ADD CONSTRAINT oauth2_provider_app_tokens_app_secret_id_fkey FOREIGN KEY (app_secret_id) REFERENCES oauth2_provider_app_secrets(id) ON DELETE CASCADE;
|
||||
ForeignKeyOrganizationMembersOrganizationIDUUID ForeignKeyConstraint = "organization_members_organization_id_uuid_fkey" // ALTER TABLE ONLY organization_members ADD CONSTRAINT organization_members_organization_id_uuid_fkey FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE;
|
||||
ForeignKeyOrganizationMembersUserIDUUID ForeignKeyConstraint = "organization_members_user_id_uuid_fkey" // ALTER TABLE ONLY organization_members ADD CONSTRAINT organization_members_user_id_uuid_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
|
||||
ForeignKeyParameterSchemasJobID ForeignKeyConstraint = "parameter_schemas_job_id_fkey" // ALTER TABLE ONLY parameter_schemas ADD CONSTRAINT parameter_schemas_job_id_fkey FOREIGN KEY (job_id) REFERENCES provisioner_jobs(id) ON DELETE CASCADE;
|
||||
ForeignKeyProvisionerDaemonsKeyID ForeignKeyConstraint = "provisioner_daemons_key_id_fkey" // ALTER TABLE ONLY provisioner_daemons ADD CONSTRAINT provisioner_daemons_key_id_fkey FOREIGN KEY (key_id) REFERENCES provisioner_keys(id) ON DELETE CASCADE;
|
||||
ForeignKeyProvisionerDaemonsOrganizationID ForeignKeyConstraint = "provisioner_daemons_organization_id_fkey" // ALTER TABLE ONLY provisioner_daemons ADD CONSTRAINT provisioner_daemons_organization_id_fkey FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE;
|
||||
ForeignKeyProvisionerJobLogsJobID ForeignKeyConstraint = "provisioner_job_logs_job_id_fkey" // ALTER TABLE ONLY provisioner_job_logs ADD CONSTRAINT provisioner_job_logs_job_id_fkey FOREIGN KEY (job_id) REFERENCES provisioner_jobs(id) ON DELETE CASCADE;
|
||||
ForeignKeyProvisionerJobTimingsJobID ForeignKeyConstraint = "provisioner_job_timings_job_id_fkey" // ALTER TABLE ONLY provisioner_job_timings ADD CONSTRAINT provisioner_job_timings_job_id_fkey FOREIGN KEY (job_id) REFERENCES provisioner_jobs(id) ON DELETE CASCADE;
|
||||
ForeignKeyProvisionerJobsOrganizationID ForeignKeyConstraint = "provisioner_jobs_organization_id_fkey" // ALTER TABLE ONLY provisioner_jobs ADD CONSTRAINT provisioner_jobs_organization_id_fkey FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE;
|
||||
ForeignKeyProvisionerKeysOrganizationID ForeignKeyConstraint = "provisioner_keys_organization_id_fkey" // ALTER TABLE ONLY provisioner_keys ADD CONSTRAINT provisioner_keys_organization_id_fkey FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE;
|
||||
ForeignKeyTailnetPeersCoordinatorID ForeignKeyConstraint = "tailnet_peers_coordinator_id_fkey" // ALTER TABLE ONLY tailnet_peers ADD CONSTRAINT tailnet_peers_coordinator_id_fkey FOREIGN KEY (coordinator_id) REFERENCES tailnet_coordinators(id) ON DELETE CASCADE;
|
||||
ForeignKeyTailnetTunnelsCoordinatorID ForeignKeyConstraint = "tailnet_tunnels_coordinator_id_fkey" // ALTER TABLE ONLY tailnet_tunnels ADD CONSTRAINT tailnet_tunnels_coordinator_id_fkey FOREIGN KEY (coordinator_id) REFERENCES tailnet_coordinators(id) ON DELETE CASCADE;
|
||||
ForeignKeyTaskSnapshotsTaskID ForeignKeyConstraint = "task_snapshots_task_id_fkey" // ALTER TABLE ONLY task_snapshots ADD CONSTRAINT task_snapshots_task_id_fkey FOREIGN KEY (task_id) REFERENCES tasks(id) ON DELETE CASCADE;
|
||||
ForeignKeyTaskWorkspaceAppsTaskID ForeignKeyConstraint = "task_workspace_apps_task_id_fkey" // ALTER TABLE ONLY task_workspace_apps ADD CONSTRAINT task_workspace_apps_task_id_fkey FOREIGN KEY (task_id) REFERENCES tasks(id) ON DELETE CASCADE;
|
||||
ForeignKeyTaskWorkspaceAppsWorkspaceAgentID ForeignKeyConstraint = "task_workspace_apps_workspace_agent_id_fkey" // ALTER TABLE ONLY task_workspace_apps ADD CONSTRAINT task_workspace_apps_workspace_agent_id_fkey FOREIGN KEY (workspace_agent_id) REFERENCES workspace_agents(id) ON DELETE CASCADE;
|
||||
ForeignKeyTaskWorkspaceAppsWorkspaceAppID ForeignKeyConstraint = "task_workspace_apps_workspace_app_id_fkey" // ALTER TABLE ONLY task_workspace_apps ADD CONSTRAINT task_workspace_apps_workspace_app_id_fkey FOREIGN KEY (workspace_app_id) REFERENCES workspace_apps(id) ON DELETE CASCADE;
|
||||
ForeignKeyTasksOrganizationID ForeignKeyConstraint = "tasks_organization_id_fkey" // ALTER TABLE ONLY tasks ADD CONSTRAINT tasks_organization_id_fkey FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE;
|
||||
ForeignKeyTasksOwnerID ForeignKeyConstraint = "tasks_owner_id_fkey" // ALTER TABLE ONLY tasks ADD CONSTRAINT tasks_owner_id_fkey FOREIGN KEY (owner_id) REFERENCES users(id) ON DELETE CASCADE;
|
||||
ForeignKeyTasksTemplateVersionID ForeignKeyConstraint = "tasks_template_version_id_fkey" // ALTER TABLE ONLY tasks ADD CONSTRAINT tasks_template_version_id_fkey FOREIGN KEY (template_version_id) REFERENCES template_versions(id) ON DELETE CASCADE;
|
||||
ForeignKeyTasksWorkspaceID ForeignKeyConstraint = "tasks_workspace_id_fkey" // ALTER TABLE ONLY tasks ADD CONSTRAINT tasks_workspace_id_fkey FOREIGN KEY (workspace_id) REFERENCES workspaces(id) ON DELETE CASCADE;
|
||||
ForeignKeyTemplateVersionParametersTemplateVersionID ForeignKeyConstraint = "template_version_parameters_template_version_id_fkey" // ALTER TABLE ONLY template_version_parameters ADD CONSTRAINT template_version_parameters_template_version_id_fkey FOREIGN KEY (template_version_id) REFERENCES template_versions(id) ON DELETE CASCADE;
|
||||
ForeignKeyTemplateVersionPresetParametTemplateVersionPresetID ForeignKeyConstraint = "template_version_preset_paramet_template_version_preset_id_fkey" // ALTER TABLE ONLY template_version_preset_parameters ADD CONSTRAINT template_version_preset_paramet_template_version_preset_id_fkey FOREIGN KEY (template_version_preset_id) REFERENCES template_version_presets(id) ON DELETE CASCADE;
|
||||
ForeignKeyTemplateVersionPresetPrebuildSchedulesPresetID ForeignKeyConstraint = "template_version_preset_prebuild_schedules_preset_id_fkey" // ALTER TABLE ONLY template_version_preset_prebuild_schedules ADD CONSTRAINT template_version_preset_prebuild_schedules_preset_id_fkey FOREIGN KEY (preset_id) REFERENCES template_version_presets(id) ON DELETE CASCADE;
|
||||
ForeignKeyTemplateVersionPresetsTemplateVersionID ForeignKeyConstraint = "template_version_presets_template_version_id_fkey" // ALTER TABLE ONLY template_version_presets ADD CONSTRAINT template_version_presets_template_version_id_fkey FOREIGN KEY (template_version_id) REFERENCES template_versions(id) ON DELETE CASCADE;
|
||||
ForeignKeyTemplateVersionTerraformValuesCachedModuleFiles ForeignKeyConstraint = "template_version_terraform_values_cached_module_files_fkey" // ALTER TABLE ONLY template_version_terraform_values ADD CONSTRAINT template_version_terraform_values_cached_module_files_fkey FOREIGN KEY (cached_module_files) REFERENCES files(id);
|
||||
ForeignKeyTemplateVersionTerraformValuesTemplateVersionID ForeignKeyConstraint = "template_version_terraform_values_template_version_id_fkey" // ALTER TABLE ONLY template_version_terraform_values ADD CONSTRAINT template_version_terraform_values_template_version_id_fkey FOREIGN KEY (template_version_id) REFERENCES template_versions(id) ON DELETE CASCADE;
|
||||
ForeignKeyTemplateVersionVariablesTemplateVersionID ForeignKeyConstraint = "template_version_variables_template_version_id_fkey" // ALTER TABLE ONLY template_version_variables ADD CONSTRAINT template_version_variables_template_version_id_fkey FOREIGN KEY (template_version_id) REFERENCES template_versions(id) ON DELETE CASCADE;
|
||||
ForeignKeyTemplateVersionWorkspaceTagsTemplateVersionID ForeignKeyConstraint = "template_version_workspace_tags_template_version_id_fkey" // ALTER TABLE ONLY template_version_workspace_tags ADD CONSTRAINT template_version_workspace_tags_template_version_id_fkey FOREIGN KEY (template_version_id) REFERENCES template_versions(id) ON DELETE CASCADE;
|
||||
ForeignKeyTemplateVersionsCreatedBy ForeignKeyConstraint = "template_versions_created_by_fkey" // ALTER TABLE ONLY template_versions ADD CONSTRAINT template_versions_created_by_fkey FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE RESTRICT;
|
||||
ForeignKeyTemplateVersionsOrganizationID ForeignKeyConstraint = "template_versions_organization_id_fkey" // ALTER TABLE ONLY template_versions ADD CONSTRAINT template_versions_organization_id_fkey FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE;
|
||||
ForeignKeyTemplateVersionsTemplateID ForeignKeyConstraint = "template_versions_template_id_fkey" // ALTER TABLE ONLY template_versions ADD CONSTRAINT template_versions_template_id_fkey FOREIGN KEY (template_id) REFERENCES templates(id) ON DELETE CASCADE;
|
||||
ForeignKeyTemplatesCreatedBy ForeignKeyConstraint = "templates_created_by_fkey" // ALTER TABLE ONLY templates ADD CONSTRAINT templates_created_by_fkey FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE RESTRICT;
|
||||
ForeignKeyTemplatesOrganizationID ForeignKeyConstraint = "templates_organization_id_fkey" // ALTER TABLE ONLY templates ADD CONSTRAINT templates_organization_id_fkey FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE;
|
||||
ForeignKeyUserAIBudgetOverridesGroupID ForeignKeyConstraint = "user_ai_budget_overrides_group_id_fkey" // ALTER TABLE ONLY user_ai_budget_overrides ADD CONSTRAINT user_ai_budget_overrides_group_id_fkey FOREIGN KEY (group_id) REFERENCES groups(id) ON DELETE CASCADE;
|
||||
ForeignKeyUserAIBudgetOverridesUserID ForeignKeyConstraint = "user_ai_budget_overrides_user_id_fkey" // ALTER TABLE ONLY user_ai_budget_overrides ADD CONSTRAINT user_ai_budget_overrides_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
|
||||
ForeignKeyUserAIProviderKeysAIProviderID ForeignKeyConstraint = "user_ai_provider_keys_ai_provider_id_fkey" // ALTER TABLE ONLY user_ai_provider_keys ADD CONSTRAINT user_ai_provider_keys_ai_provider_id_fkey FOREIGN KEY (ai_provider_id) REFERENCES ai_providers(id) ON DELETE CASCADE;
|
||||
ForeignKeyUserAIProviderKeysAPIKeyKeyID ForeignKeyConstraint = "user_ai_provider_keys_api_key_key_id_fkey" // ALTER TABLE ONLY user_ai_provider_keys ADD CONSTRAINT user_ai_provider_keys_api_key_key_id_fkey FOREIGN KEY (api_key_key_id) REFERENCES dbcrypt_keys(active_key_digest);
|
||||
ForeignKeyUserAIProviderKeysUserID ForeignKeyConstraint = "user_ai_provider_keys_user_id_fkey" // ALTER TABLE ONLY user_ai_provider_keys ADD CONSTRAINT user_ai_provider_keys_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
|
||||
ForeignKeyUserConfigsUserID ForeignKeyConstraint = "user_configs_user_id_fkey" // ALTER TABLE ONLY user_configs ADD CONSTRAINT user_configs_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
|
||||
ForeignKeyUserDeletedUserID ForeignKeyConstraint = "user_deleted_user_id_fkey" // ALTER TABLE ONLY user_deleted ADD CONSTRAINT user_deleted_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id);
|
||||
ForeignKeyUserLinksOauthAccessTokenKeyID ForeignKeyConstraint = "user_links_oauth_access_token_key_id_fkey" // ALTER TABLE ONLY user_links ADD CONSTRAINT user_links_oauth_access_token_key_id_fkey FOREIGN KEY (oauth_access_token_key_id) REFERENCES dbcrypt_keys(active_key_digest);
|
||||
ForeignKeyUserLinksOauthRefreshTokenKeyID ForeignKeyConstraint = "user_links_oauth_refresh_token_key_id_fkey" // ALTER TABLE ONLY user_links ADD CONSTRAINT user_links_oauth_refresh_token_key_id_fkey FOREIGN KEY (oauth_refresh_token_key_id) REFERENCES dbcrypt_keys(active_key_digest);
|
||||
ForeignKeyUserLinksUserID ForeignKeyConstraint = "user_links_user_id_fkey" // ALTER TABLE ONLY user_links ADD CONSTRAINT user_links_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
|
||||
ForeignKeyUserSecretsUserID ForeignKeyConstraint = "user_secrets_user_id_fkey" // ALTER TABLE ONLY user_secrets ADD CONSTRAINT user_secrets_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
|
||||
ForeignKeyUserSecretsValueKeyID ForeignKeyConstraint = "user_secrets_value_key_id_fkey" // ALTER TABLE ONLY user_secrets ADD CONSTRAINT user_secrets_value_key_id_fkey FOREIGN KEY (value_key_id) REFERENCES dbcrypt_keys(active_key_digest);
|
||||
ForeignKeyUserSkillsUserID ForeignKeyConstraint = "user_skills_user_id_fkey" // ALTER TABLE ONLY user_skills ADD CONSTRAINT user_skills_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
|
||||
ForeignKeyUserStatusChangesUserID ForeignKeyConstraint = "user_status_changes_user_id_fkey" // ALTER TABLE ONLY user_status_changes ADD CONSTRAINT user_status_changes_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id);
|
||||
ForeignKeyWebpushSubscriptionsUserID ForeignKeyConstraint = "webpush_subscriptions_user_id_fkey" // ALTER TABLE ONLY webpush_subscriptions ADD CONSTRAINT webpush_subscriptions_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
|
||||
ForeignKeyWorkspaceAgentContextResourcesWorkspaceAgentID ForeignKeyConstraint = "workspace_agent_context_resources_workspace_agent_id_fkey" // ALTER TABLE ONLY workspace_agent_context_resources ADD CONSTRAINT workspace_agent_context_resources_workspace_agent_id_fkey FOREIGN KEY (workspace_agent_id) REFERENCES workspace_agents(id) ON DELETE CASCADE;
|
||||
ForeignKeyWorkspaceAgentContextSnapshotsWorkspaceAgentID ForeignKeyConstraint = "workspace_agent_context_snapshots_workspace_agent_id_fkey" // ALTER TABLE ONLY workspace_agent_context_snapshots ADD CONSTRAINT workspace_agent_context_snapshots_workspace_agent_id_fkey FOREIGN KEY (workspace_agent_id) REFERENCES workspace_agents(id) ON DELETE CASCADE;
|
||||
ForeignKeyWorkspaceAgentDevcontainersSubagentID ForeignKeyConstraint = "workspace_agent_devcontainers_subagent_id_fkey" // ALTER TABLE ONLY workspace_agent_devcontainers ADD CONSTRAINT workspace_agent_devcontainers_subagent_id_fkey FOREIGN KEY (subagent_id) REFERENCES workspace_agents(id) ON DELETE CASCADE;
|
||||
ForeignKeyWorkspaceAgentDevcontainersWorkspaceAgentID ForeignKeyConstraint = "workspace_agent_devcontainers_workspace_agent_id_fkey" // ALTER TABLE ONLY workspace_agent_devcontainers ADD CONSTRAINT workspace_agent_devcontainers_workspace_agent_id_fkey FOREIGN KEY (workspace_agent_id) REFERENCES workspace_agents(id) ON DELETE CASCADE;
|
||||
ForeignKeyWorkspaceAgentLogSourcesWorkspaceAgentID ForeignKeyConstraint = "workspace_agent_log_sources_workspace_agent_id_fkey" // ALTER TABLE ONLY workspace_agent_log_sources ADD CONSTRAINT workspace_agent_log_sources_workspace_agent_id_fkey FOREIGN KEY (workspace_agent_id) REFERENCES workspace_agents(id) ON DELETE CASCADE;
|
||||
ForeignKeyWorkspaceAgentMemoryResourceMonitorsAgentID ForeignKeyConstraint = "workspace_agent_memory_resource_monitors_agent_id_fkey" // ALTER TABLE ONLY workspace_agent_memory_resource_monitors ADD CONSTRAINT workspace_agent_memory_resource_monitors_agent_id_fkey FOREIGN KEY (agent_id) REFERENCES workspace_agents(id) ON DELETE CASCADE;
|
||||
ForeignKeyWorkspaceAgentMetadataWorkspaceAgentID ForeignKeyConstraint = "workspace_agent_metadata_workspace_agent_id_fkey" // ALTER TABLE ONLY workspace_agent_metadata ADD CONSTRAINT workspace_agent_metadata_workspace_agent_id_fkey FOREIGN KEY (workspace_agent_id) REFERENCES workspace_agents(id) ON DELETE CASCADE;
|
||||
ForeignKeyWorkspaceAgentPortShareWorkspaceID ForeignKeyConstraint = "workspace_agent_port_share_workspace_id_fkey" // ALTER TABLE ONLY workspace_agent_port_share ADD CONSTRAINT workspace_agent_port_share_workspace_id_fkey FOREIGN KEY (workspace_id) REFERENCES workspaces(id) ON DELETE CASCADE;
|
||||
ForeignKeyWorkspaceAgentScriptTimingsScriptID ForeignKeyConstraint = "workspace_agent_script_timings_script_id_fkey" // ALTER TABLE ONLY workspace_agent_script_timings ADD CONSTRAINT workspace_agent_script_timings_script_id_fkey FOREIGN KEY (script_id) REFERENCES workspace_agent_scripts(id) ON DELETE CASCADE;
|
||||
ForeignKeyWorkspaceAgentScriptsWorkspaceAgentID ForeignKeyConstraint = "workspace_agent_scripts_workspace_agent_id_fkey" // ALTER TABLE ONLY workspace_agent_scripts ADD CONSTRAINT workspace_agent_scripts_workspace_agent_id_fkey FOREIGN KEY (workspace_agent_id) REFERENCES workspace_agents(id) ON DELETE CASCADE;
|
||||
ForeignKeyWorkspaceAgentStartupLogsAgentID ForeignKeyConstraint = "workspace_agent_startup_logs_agent_id_fkey" // ALTER TABLE ONLY workspace_agent_logs ADD CONSTRAINT workspace_agent_startup_logs_agent_id_fkey FOREIGN KEY (agent_id) REFERENCES workspace_agents(id) ON DELETE CASCADE;
|
||||
ForeignKeyWorkspaceAgentVolumeResourceMonitorsAgentID ForeignKeyConstraint = "workspace_agent_volume_resource_monitors_agent_id_fkey" // ALTER TABLE ONLY workspace_agent_volume_resource_monitors ADD CONSTRAINT workspace_agent_volume_resource_monitors_agent_id_fkey FOREIGN KEY (agent_id) REFERENCES workspace_agents(id) ON DELETE CASCADE;
|
||||
ForeignKeyWorkspaceAgentsParentID ForeignKeyConstraint = "workspace_agents_parent_id_fkey" // ALTER TABLE ONLY workspace_agents ADD CONSTRAINT workspace_agents_parent_id_fkey FOREIGN KEY (parent_id) REFERENCES workspace_agents(id) ON DELETE CASCADE;
|
||||
ForeignKeyWorkspaceAgentsResourceID ForeignKeyConstraint = "workspace_agents_resource_id_fkey" // ALTER TABLE ONLY workspace_agents ADD CONSTRAINT workspace_agents_resource_id_fkey FOREIGN KEY (resource_id) REFERENCES workspace_resources(id) ON DELETE CASCADE;
|
||||
ForeignKeyWorkspaceAppAuditSessionsAgentID ForeignKeyConstraint = "workspace_app_audit_sessions_agent_id_fkey" // ALTER TABLE ONLY workspace_app_audit_sessions ADD CONSTRAINT workspace_app_audit_sessions_agent_id_fkey FOREIGN KEY (agent_id) REFERENCES workspace_agents(id) ON DELETE CASCADE;
|
||||
ForeignKeyWorkspaceAppStatsAgentID ForeignKeyConstraint = "workspace_app_stats_agent_id_fkey" // ALTER TABLE ONLY workspace_app_stats ADD CONSTRAINT workspace_app_stats_agent_id_fkey FOREIGN KEY (agent_id) REFERENCES workspace_agents(id);
|
||||
ForeignKeyWorkspaceAppStatsUserID ForeignKeyConstraint = "workspace_app_stats_user_id_fkey" // ALTER TABLE ONLY workspace_app_stats ADD CONSTRAINT workspace_app_stats_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id);
|
||||
ForeignKeyWorkspaceAppStatsWorkspaceID ForeignKeyConstraint = "workspace_app_stats_workspace_id_fkey" // ALTER TABLE ONLY workspace_app_stats ADD CONSTRAINT workspace_app_stats_workspace_id_fkey FOREIGN KEY (workspace_id) REFERENCES workspaces(id);
|
||||
ForeignKeyWorkspaceAppStatusesAgentID ForeignKeyConstraint = "workspace_app_statuses_agent_id_fkey" // ALTER TABLE ONLY workspace_app_statuses ADD CONSTRAINT workspace_app_statuses_agent_id_fkey FOREIGN KEY (agent_id) REFERENCES workspace_agents(id);
|
||||
ForeignKeyWorkspaceAppStatusesAppID ForeignKeyConstraint = "workspace_app_statuses_app_id_fkey" // ALTER TABLE ONLY workspace_app_statuses ADD CONSTRAINT workspace_app_statuses_app_id_fkey FOREIGN KEY (app_id) REFERENCES workspace_apps(id);
|
||||
ForeignKeyWorkspaceAppStatusesWorkspaceID ForeignKeyConstraint = "workspace_app_statuses_workspace_id_fkey" // ALTER TABLE ONLY workspace_app_statuses ADD CONSTRAINT workspace_app_statuses_workspace_id_fkey FOREIGN KEY (workspace_id) REFERENCES workspaces(id);
|
||||
ForeignKeyWorkspaceAppsAgentID ForeignKeyConstraint = "workspace_apps_agent_id_fkey" // ALTER TABLE ONLY workspace_apps ADD CONSTRAINT workspace_apps_agent_id_fkey FOREIGN KEY (agent_id) REFERENCES workspace_agents(id) ON DELETE CASCADE;
|
||||
ForeignKeyWorkspaceBuildOrchestrationsChildBuildWorkspaceID ForeignKeyConstraint = "workspace_build_orchestrations_child_build_workspace_id_fkey" // ALTER TABLE ONLY workspace_build_orchestrations ADD CONSTRAINT workspace_build_orchestrations_child_build_workspace_id_fkey FOREIGN KEY (child_build_id, workspace_id) REFERENCES workspace_builds(id, workspace_id) ON DELETE CASCADE;
|
||||
ForeignKeyWorkspaceBuildOrchestrationsChildPresetID ForeignKeyConstraint = "workspace_build_orchestrations_child_preset_id_fkey" // ALTER TABLE ONLY workspace_build_orchestrations ADD CONSTRAINT workspace_build_orchestrations_child_preset_id_fkey FOREIGN KEY (child_template_version_preset_id) REFERENCES template_version_presets(id) ON DELETE SET NULL;
|
||||
ForeignKeyWorkspaceBuildOrchestrationsChildPresetVersion ForeignKeyConstraint = "workspace_build_orchestrations_child_preset_version_fkey" // ALTER TABLE ONLY workspace_build_orchestrations ADD CONSTRAINT workspace_build_orchestrations_child_preset_version_fkey FOREIGN KEY (child_template_version_preset_id, child_template_version_id) REFERENCES template_version_presets(id, template_version_id);
|
||||
ForeignKeyWorkspaceBuildOrchestrationsChildTemplateVersionID ForeignKeyConstraint = "workspace_build_orchestrations_child_template_version_id_fkey" // ALTER TABLE ONLY workspace_build_orchestrations ADD CONSTRAINT workspace_build_orchestrations_child_template_version_id_fkey FOREIGN KEY (child_template_version_id) REFERENCES template_versions(id) ON DELETE CASCADE;
|
||||
ForeignKeyWorkspaceBuildOrchestrationsParentBuildWorkspaceID ForeignKeyConstraint = "workspace_build_orchestrations_parent_build_workspace_id_fkey" // ALTER TABLE ONLY workspace_build_orchestrations ADD CONSTRAINT workspace_build_orchestrations_parent_build_workspace_id_fkey FOREIGN KEY (parent_build_id, workspace_id) REFERENCES workspace_builds(id, workspace_id) ON DELETE CASCADE;
|
||||
ForeignKeyWorkspaceBuildParametersWorkspaceBuildID ForeignKeyConstraint = "workspace_build_parameters_workspace_build_id_fkey" // ALTER TABLE ONLY workspace_build_parameters ADD CONSTRAINT workspace_build_parameters_workspace_build_id_fkey FOREIGN KEY (workspace_build_id) REFERENCES workspace_builds(id) ON DELETE CASCADE;
|
||||
ForeignKeyWorkspaceBuildsJobID ForeignKeyConstraint = "workspace_builds_job_id_fkey" // ALTER TABLE ONLY workspace_builds ADD CONSTRAINT workspace_builds_job_id_fkey FOREIGN KEY (job_id) REFERENCES provisioner_jobs(id) ON DELETE CASCADE;
|
||||
ForeignKeyWorkspaceBuildsTemplateVersionID ForeignKeyConstraint = "workspace_builds_template_version_id_fkey" // ALTER TABLE ONLY workspace_builds ADD CONSTRAINT workspace_builds_template_version_id_fkey FOREIGN KEY (template_version_id) REFERENCES template_versions(id) ON DELETE CASCADE;
|
||||
ForeignKeyWorkspaceBuildsTemplateVersionPresetID ForeignKeyConstraint = "workspace_builds_template_version_preset_id_fkey" // ALTER TABLE ONLY workspace_builds ADD CONSTRAINT workspace_builds_template_version_preset_id_fkey FOREIGN KEY (template_version_preset_id) REFERENCES template_version_presets(id) ON DELETE SET NULL;
|
||||
ForeignKeyWorkspaceBuildsWorkspaceID ForeignKeyConstraint = "workspace_builds_workspace_id_fkey" // ALTER TABLE ONLY workspace_builds ADD CONSTRAINT workspace_builds_workspace_id_fkey FOREIGN KEY (workspace_id) REFERENCES workspaces(id) ON DELETE CASCADE;
|
||||
ForeignKeyWorkspaceModulesJobID ForeignKeyConstraint = "workspace_modules_job_id_fkey" // ALTER TABLE ONLY workspace_modules ADD CONSTRAINT workspace_modules_job_id_fkey FOREIGN KEY (job_id) REFERENCES provisioner_jobs(id) ON DELETE CASCADE;
|
||||
ForeignKeyWorkspaceResourceMetadataWorkspaceResourceID ForeignKeyConstraint = "workspace_resource_metadata_workspace_resource_id_fkey" // ALTER TABLE ONLY workspace_resource_metadata ADD CONSTRAINT workspace_resource_metadata_workspace_resource_id_fkey FOREIGN KEY (workspace_resource_id) REFERENCES workspace_resources(id) ON DELETE CASCADE;
|
||||
ForeignKeyWorkspaceResourcesJobID ForeignKeyConstraint = "workspace_resources_job_id_fkey" // ALTER TABLE ONLY workspace_resources ADD CONSTRAINT workspace_resources_job_id_fkey FOREIGN KEY (job_id) REFERENCES provisioner_jobs(id) ON DELETE CASCADE;
|
||||
ForeignKeyWorkspacesOrganizationID ForeignKeyConstraint = "workspaces_organization_id_fkey" // ALTER TABLE ONLY workspaces ADD CONSTRAINT workspaces_organization_id_fkey FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE RESTRICT;
|
||||
ForeignKeyWorkspacesOwnerID ForeignKeyConstraint = "workspaces_owner_id_fkey" // ALTER TABLE ONLY workspaces ADD CONSTRAINT workspaces_owner_id_fkey FOREIGN KEY (owner_id) REFERENCES users(id) ON DELETE RESTRICT;
|
||||
ForeignKeyWorkspacesTemplateID ForeignKeyConstraint = "workspaces_template_id_fkey" // ALTER TABLE ONLY workspaces ADD CONSTRAINT workspaces_template_id_fkey FOREIGN KEY (template_id) REFERENCES templates(id) ON DELETE RESTRICT;
|
||||
ForeignKeyAIProviderKeysAPIKeyKeyID ForeignKeyConstraint = "ai_provider_keys_api_key_key_id_fkey" // ALTER TABLE ONLY ai_provider_keys ADD CONSTRAINT ai_provider_keys_api_key_key_id_fkey FOREIGN KEY (api_key_key_id) REFERENCES dbcrypt_keys(active_key_digest);
|
||||
ForeignKeyAIProviderKeysProviderID ForeignKeyConstraint = "ai_provider_keys_provider_id_fkey" // ALTER TABLE ONLY ai_provider_keys ADD CONSTRAINT ai_provider_keys_provider_id_fkey FOREIGN KEY (provider_id) REFERENCES ai_providers(id) ON DELETE CASCADE;
|
||||
ForeignKeyAIProvidersSettingsKeyID ForeignKeyConstraint = "ai_providers_settings_key_id_fkey" // ALTER TABLE ONLY ai_providers ADD CONSTRAINT ai_providers_settings_key_id_fkey FOREIGN KEY (settings_key_id) REFERENCES dbcrypt_keys(active_key_digest);
|
||||
ForeignKeyAISeatStateUserID ForeignKeyConstraint = "ai_seat_state_user_id_fkey" // ALTER TABLE ONLY ai_seat_state ADD CONSTRAINT ai_seat_state_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
|
||||
ForeignKeyAibridgeInterceptionsInitiatorID ForeignKeyConstraint = "aibridge_interceptions_initiator_id_fkey" // ALTER TABLE ONLY aibridge_interceptions ADD CONSTRAINT aibridge_interceptions_initiator_id_fkey FOREIGN KEY (initiator_id) REFERENCES users(id);
|
||||
ForeignKeyAPIKeysUserIDUUID ForeignKeyConstraint = "api_keys_user_id_uuid_fkey" // ALTER TABLE ONLY api_keys ADD CONSTRAINT api_keys_user_id_uuid_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
|
||||
ForeignKeyBoundaryLogsOwnerID ForeignKeyConstraint = "boundary_logs_owner_id_fkey" // ALTER TABLE ONLY boundary_logs ADD CONSTRAINT boundary_logs_owner_id_fkey FOREIGN KEY (owner_id) REFERENCES users(id) ON DELETE SET NULL;
|
||||
ForeignKeyBoundarySessionsOwnerID ForeignKeyConstraint = "boundary_sessions_owner_id_fkey" // ALTER TABLE ONLY boundary_sessions ADD CONSTRAINT boundary_sessions_owner_id_fkey FOREIGN KEY (owner_id) REFERENCES users(id) ON DELETE SET NULL;
|
||||
ForeignKeyBoundarySessionsWorkspaceAgentID ForeignKeyConstraint = "boundary_sessions_workspace_agent_id_fkey" // ALTER TABLE ONLY boundary_sessions ADD CONSTRAINT boundary_sessions_workspace_agent_id_fkey FOREIGN KEY (workspace_agent_id) REFERENCES workspace_agents(id);
|
||||
ForeignKeyChatContextResourcesChatID ForeignKeyConstraint = "chat_context_resources_chat_id_fkey" // ALTER TABLE ONLY chat_context_resources ADD CONSTRAINT chat_context_resources_chat_id_fkey FOREIGN KEY (chat_id) REFERENCES chats(id) ON DELETE CASCADE;
|
||||
ForeignKeyChatDebugRunsChatID ForeignKeyConstraint = "chat_debug_runs_chat_id_fkey" // ALTER TABLE ONLY chat_debug_runs ADD CONSTRAINT chat_debug_runs_chat_id_fkey FOREIGN KEY (chat_id) REFERENCES chats(id) ON DELETE CASCADE;
|
||||
ForeignKeyChatDebugStepsChatID ForeignKeyConstraint = "chat_debug_steps_chat_id_fkey" // ALTER TABLE ONLY chat_debug_steps ADD CONSTRAINT chat_debug_steps_chat_id_fkey FOREIGN KEY (chat_id) REFERENCES chats(id) ON DELETE CASCADE;
|
||||
ForeignKeyChatDiffStatusesChatID ForeignKeyConstraint = "chat_diff_statuses_chat_id_fkey" // ALTER TABLE ONLY chat_diff_statuses ADD CONSTRAINT chat_diff_statuses_chat_id_fkey FOREIGN KEY (chat_id) REFERENCES chats(id) ON DELETE CASCADE;
|
||||
ForeignKeyChatFileLinksChatID ForeignKeyConstraint = "chat_file_links_chat_id_fkey" // ALTER TABLE ONLY chat_file_links ADD CONSTRAINT chat_file_links_chat_id_fkey FOREIGN KEY (chat_id) REFERENCES chats(id) ON DELETE CASCADE;
|
||||
ForeignKeyChatFileLinksFileID ForeignKeyConstraint = "chat_file_links_file_id_fkey" // ALTER TABLE ONLY chat_file_links ADD CONSTRAINT chat_file_links_file_id_fkey FOREIGN KEY (file_id) REFERENCES chat_files(id) ON DELETE CASCADE;
|
||||
ForeignKeyChatFilesOrganizationID ForeignKeyConstraint = "chat_files_organization_id_fkey" // ALTER TABLE ONLY chat_files ADD CONSTRAINT chat_files_organization_id_fkey FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE;
|
||||
ForeignKeyChatFilesOwnerID ForeignKeyConstraint = "chat_files_owner_id_fkey" // ALTER TABLE ONLY chat_files ADD CONSTRAINT chat_files_owner_id_fkey FOREIGN KEY (owner_id) REFERENCES users(id) ON DELETE CASCADE;
|
||||
ForeignKeyChatHeartbeatsChatID ForeignKeyConstraint = "chat_heartbeats_chat_id_fkey" // ALTER TABLE ONLY chat_heartbeats ADD CONSTRAINT chat_heartbeats_chat_id_fkey FOREIGN KEY (chat_id) REFERENCES chats(id) ON DELETE CASCADE;
|
||||
ForeignKeyChatMessagesChatID ForeignKeyConstraint = "chat_messages_chat_id_fkey" // ALTER TABLE ONLY chat_messages ADD CONSTRAINT chat_messages_chat_id_fkey FOREIGN KEY (chat_id) REFERENCES chats(id) ON DELETE CASCADE;
|
||||
ForeignKeyChatMessagesModelConfigID ForeignKeyConstraint = "chat_messages_model_config_id_fkey" // ALTER TABLE ONLY chat_messages ADD CONSTRAINT chat_messages_model_config_id_fkey FOREIGN KEY (model_config_id) REFERENCES chat_model_configs(id);
|
||||
ForeignKeyChatModelConfigsAIProviderID ForeignKeyConstraint = "chat_model_configs_ai_provider_id_fkey" // ALTER TABLE ONLY chat_model_configs ADD CONSTRAINT chat_model_configs_ai_provider_id_fkey FOREIGN KEY (ai_provider_id) REFERENCES ai_providers(id);
|
||||
ForeignKeyChatModelConfigsCreatedBy ForeignKeyConstraint = "chat_model_configs_created_by_fkey" // ALTER TABLE ONLY chat_model_configs ADD CONSTRAINT chat_model_configs_created_by_fkey FOREIGN KEY (created_by) REFERENCES users(id);
|
||||
ForeignKeyChatModelConfigsOrganizationID ForeignKeyConstraint = "chat_model_configs_organization_id_fkey" // ALTER TABLE ONLY chat_model_configs ADD CONSTRAINT chat_model_configs_organization_id_fkey FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE;
|
||||
ForeignKeyChatModelConfigsUpdatedBy ForeignKeyConstraint = "chat_model_configs_updated_by_fkey" // ALTER TABLE ONLY chat_model_configs ADD CONSTRAINT chat_model_configs_updated_by_fkey FOREIGN KEY (updated_by) REFERENCES users(id);
|
||||
ForeignKeyChatOrganizationModelOverridesOrganizationID ForeignKeyConstraint = "chat_organization_model_overrides_organization_id_fkey" // ALTER TABLE ONLY chat_organization_model_overrides ADD CONSTRAINT chat_organization_model_overrides_organization_id_fkey FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE;
|
||||
ForeignKeyChatOrganizationModelOverridesOrganizationModelConfigFke ForeignKeyConstraint = "chat_organization_model_overrides_organization_model_config_fke" // ALTER TABLE ONLY chat_organization_model_overrides ADD CONSTRAINT chat_organization_model_overrides_organization_model_config_fke FOREIGN KEY (organization_id, model_config_id) REFERENCES chat_model_configs(organization_id, id);
|
||||
ForeignKeyChatQueuedMessagesChatID ForeignKeyConstraint = "chat_queued_messages_chat_id_fkey" // ALTER TABLE ONLY chat_queued_messages ADD CONSTRAINT chat_queued_messages_chat_id_fkey FOREIGN KEY (chat_id) REFERENCES chats(id) ON DELETE CASCADE;
|
||||
ForeignKeyChatUserModelOverridesOrganizationID ForeignKeyConstraint = "chat_user_model_overrides_organization_id_fkey" // ALTER TABLE ONLY chat_user_model_overrides ADD CONSTRAINT chat_user_model_overrides_organization_id_fkey FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE;
|
||||
ForeignKeyChatUserModelOverridesOrganizationModelConfig ForeignKeyConstraint = "chat_user_model_overrides_organization_model_config_fkey" // ALTER TABLE ONLY chat_user_model_overrides ADD CONSTRAINT chat_user_model_overrides_organization_model_config_fkey FOREIGN KEY (organization_id, model_config_id) REFERENCES chat_model_configs(organization_id, id);
|
||||
ForeignKeyChatUserModelOverridesUserID ForeignKeyConstraint = "chat_user_model_overrides_user_id_fkey" // ALTER TABLE ONLY chat_user_model_overrides ADD CONSTRAINT chat_user_model_overrides_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
|
||||
ForeignKeyChatsAgentID ForeignKeyConstraint = "chats_agent_id_fkey" // ALTER TABLE ONLY chats ADD CONSTRAINT chats_agent_id_fkey FOREIGN KEY (agent_id) REFERENCES workspace_agents(id) ON DELETE SET NULL;
|
||||
ForeignKeyChatsBuildID ForeignKeyConstraint = "chats_build_id_fkey" // ALTER TABLE ONLY chats ADD CONSTRAINT chats_build_id_fkey FOREIGN KEY (build_id) REFERENCES workspace_builds(id) ON DELETE SET NULL;
|
||||
ForeignKeyChatsLastModelConfigID ForeignKeyConstraint = "chats_last_model_config_id_fkey" // ALTER TABLE ONLY chats ADD CONSTRAINT chats_last_model_config_id_fkey FOREIGN KEY (last_model_config_id) REFERENCES chat_model_configs(id);
|
||||
ForeignKeyChatsOrganizationID ForeignKeyConstraint = "chats_organization_id_fkey" // ALTER TABLE ONLY chats ADD CONSTRAINT chats_organization_id_fkey FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE;
|
||||
ForeignKeyChatsOwnerID ForeignKeyConstraint = "chats_owner_id_fkey" // ALTER TABLE ONLY chats ADD CONSTRAINT chats_owner_id_fkey FOREIGN KEY (owner_id) REFERENCES users(id) ON DELETE CASCADE;
|
||||
ForeignKeyChatsParentChatID ForeignKeyConstraint = "chats_parent_chat_id_fkey" // ALTER TABLE ONLY chats ADD CONSTRAINT chats_parent_chat_id_fkey FOREIGN KEY (parent_chat_id) REFERENCES chats(id) ON DELETE SET NULL;
|
||||
ForeignKeyChatsRootChatID ForeignKeyConstraint = "chats_root_chat_id_fkey" // ALTER TABLE ONLY chats ADD CONSTRAINT chats_root_chat_id_fkey FOREIGN KEY (root_chat_id) REFERENCES chats(id) ON DELETE SET NULL;
|
||||
ForeignKeyChatsWorkspaceID ForeignKeyConstraint = "chats_workspace_id_fkey" // ALTER TABLE ONLY chats ADD CONSTRAINT chats_workspace_id_fkey FOREIGN KEY (workspace_id) REFERENCES workspaces(id) ON DELETE SET NULL;
|
||||
ForeignKeyConnectionLogsOrganizationID ForeignKeyConstraint = "connection_logs_organization_id_fkey" // ALTER TABLE ONLY connection_logs ADD CONSTRAINT connection_logs_organization_id_fkey FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE;
|
||||
ForeignKeyConnectionLogsWorkspaceID ForeignKeyConstraint = "connection_logs_workspace_id_fkey" // ALTER TABLE ONLY connection_logs ADD CONSTRAINT connection_logs_workspace_id_fkey FOREIGN KEY (workspace_id) REFERENCES workspaces(id) ON DELETE CASCADE;
|
||||
ForeignKeyConnectionLogsWorkspaceOwnerID ForeignKeyConstraint = "connection_logs_workspace_owner_id_fkey" // ALTER TABLE ONLY connection_logs ADD CONSTRAINT connection_logs_workspace_owner_id_fkey FOREIGN KEY (workspace_owner_id) REFERENCES users(id) ON DELETE CASCADE;
|
||||
ForeignKeyCryptoKeysSecretKeyID ForeignKeyConstraint = "crypto_keys_secret_key_id_fkey" // ALTER TABLE ONLY crypto_keys ADD CONSTRAINT crypto_keys_secret_key_id_fkey FOREIGN KEY (secret_key_id) REFERENCES dbcrypt_keys(active_key_digest);
|
||||
ForeignKeyFkChatDebugStepsRunChat ForeignKeyConstraint = "fk_chat_debug_steps_run_chat" // ALTER TABLE ONLY chat_debug_steps ADD CONSTRAINT fk_chat_debug_steps_run_chat FOREIGN KEY (run_id, chat_id) REFERENCES chat_debug_runs(id, chat_id) ON DELETE CASCADE;
|
||||
ForeignKeyFkOauth2ProviderAppTokensUserID ForeignKeyConstraint = "fk_oauth2_provider_app_tokens_user_id" // ALTER TABLE ONLY oauth2_provider_app_tokens ADD CONSTRAINT fk_oauth2_provider_app_tokens_user_id FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
|
||||
ForeignKeyGitAuthLinksOauthAccessTokenKeyID ForeignKeyConstraint = "git_auth_links_oauth_access_token_key_id_fkey" // ALTER TABLE ONLY external_auth_links ADD CONSTRAINT git_auth_links_oauth_access_token_key_id_fkey FOREIGN KEY (oauth_access_token_key_id) REFERENCES dbcrypt_keys(active_key_digest);
|
||||
ForeignKeyGitAuthLinksOauthRefreshTokenKeyID ForeignKeyConstraint = "git_auth_links_oauth_refresh_token_key_id_fkey" // ALTER TABLE ONLY external_auth_links ADD CONSTRAINT git_auth_links_oauth_refresh_token_key_id_fkey FOREIGN KEY (oauth_refresh_token_key_id) REFERENCES dbcrypt_keys(active_key_digest);
|
||||
ForeignKeyGitSSHKeysPrivateKeyKeyID ForeignKeyConstraint = "gitsshkeys_private_key_key_id_fkey" // ALTER TABLE ONLY gitsshkeys ADD CONSTRAINT gitsshkeys_private_key_key_id_fkey FOREIGN KEY (private_key_key_id) REFERENCES dbcrypt_keys(active_key_digest);
|
||||
ForeignKeyGitSSHKeysUserID ForeignKeyConstraint = "gitsshkeys_user_id_fkey" // ALTER TABLE ONLY gitsshkeys ADD CONSTRAINT gitsshkeys_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id);
|
||||
ForeignKeyGroupAIBudgetsGroupID ForeignKeyConstraint = "group_ai_budgets_group_id_fkey" // ALTER TABLE ONLY group_ai_budgets ADD CONSTRAINT group_ai_budgets_group_id_fkey FOREIGN KEY (group_id) REFERENCES groups(id) ON DELETE CASCADE;
|
||||
ForeignKeyGroupMembersGroupID ForeignKeyConstraint = "group_members_group_id_fkey" // ALTER TABLE ONLY group_members ADD CONSTRAINT group_members_group_id_fkey FOREIGN KEY (group_id) REFERENCES groups(id) ON DELETE CASCADE;
|
||||
ForeignKeyGroupMembersUserID ForeignKeyConstraint = "group_members_user_id_fkey" // ALTER TABLE ONLY group_members ADD CONSTRAINT group_members_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
|
||||
ForeignKeyGroupsOrganizationID ForeignKeyConstraint = "groups_organization_id_fkey" // ALTER TABLE ONLY groups ADD CONSTRAINT groups_organization_id_fkey FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE;
|
||||
ForeignKeyInboxNotificationsTemplateID ForeignKeyConstraint = "inbox_notifications_template_id_fkey" // ALTER TABLE ONLY inbox_notifications ADD CONSTRAINT inbox_notifications_template_id_fkey FOREIGN KEY (template_id) REFERENCES notification_templates(id) ON DELETE CASCADE;
|
||||
ForeignKeyInboxNotificationsUserID ForeignKeyConstraint = "inbox_notifications_user_id_fkey" // ALTER TABLE ONLY inbox_notifications ADD CONSTRAINT inbox_notifications_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
|
||||
ForeignKeyJfrogXrayScansAgentID ForeignKeyConstraint = "jfrog_xray_scans_agent_id_fkey" // ALTER TABLE ONLY jfrog_xray_scans ADD CONSTRAINT jfrog_xray_scans_agent_id_fkey FOREIGN KEY (agent_id) REFERENCES workspace_agents(id) ON DELETE CASCADE;
|
||||
ForeignKeyJfrogXrayScansWorkspaceID ForeignKeyConstraint = "jfrog_xray_scans_workspace_id_fkey" // ALTER TABLE ONLY jfrog_xray_scans ADD CONSTRAINT jfrog_xray_scans_workspace_id_fkey FOREIGN KEY (workspace_id) REFERENCES workspaces(id) ON DELETE CASCADE;
|
||||
ForeignKeyMcpServerConfigsAPIKeyValueKeyID ForeignKeyConstraint = "mcp_server_configs_api_key_value_key_id_fkey" // ALTER TABLE ONLY mcp_server_configs ADD CONSTRAINT mcp_server_configs_api_key_value_key_id_fkey FOREIGN KEY (api_key_value_key_id) REFERENCES dbcrypt_keys(active_key_digest);
|
||||
ForeignKeyMcpServerConfigsCreatedBy ForeignKeyConstraint = "mcp_server_configs_created_by_fkey" // ALTER TABLE ONLY mcp_server_configs ADD CONSTRAINT mcp_server_configs_created_by_fkey FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE SET NULL;
|
||||
ForeignKeyMcpServerConfigsCustomHeadersKeyID ForeignKeyConstraint = "mcp_server_configs_custom_headers_key_id_fkey" // ALTER TABLE ONLY mcp_server_configs ADD CONSTRAINT mcp_server_configs_custom_headers_key_id_fkey FOREIGN KEY (custom_headers_key_id) REFERENCES dbcrypt_keys(active_key_digest);
|
||||
ForeignKeyMcpServerConfigsOauth2ClientSecretKeyID ForeignKeyConstraint = "mcp_server_configs_oauth2_client_secret_key_id_fkey" // ALTER TABLE ONLY mcp_server_configs ADD CONSTRAINT mcp_server_configs_oauth2_client_secret_key_id_fkey FOREIGN KEY (oauth2_client_secret_key_id) REFERENCES dbcrypt_keys(active_key_digest);
|
||||
ForeignKeyMcpServerConfigsOrganizationID ForeignKeyConstraint = "mcp_server_configs_organization_id_fkey" // ALTER TABLE ONLY mcp_server_configs ADD CONSTRAINT mcp_server_configs_organization_id_fkey FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE;
|
||||
ForeignKeyMcpServerConfigsUpdatedBy ForeignKeyConstraint = "mcp_server_configs_updated_by_fkey" // ALTER TABLE ONLY mcp_server_configs ADD CONSTRAINT mcp_server_configs_updated_by_fkey FOREIGN KEY (updated_by) REFERENCES users(id) ON DELETE SET NULL;
|
||||
ForeignKeyMcpServerUserTokensAccessTokenKeyID ForeignKeyConstraint = "mcp_server_user_tokens_access_token_key_id_fkey" // ALTER TABLE ONLY mcp_server_user_tokens ADD CONSTRAINT mcp_server_user_tokens_access_token_key_id_fkey FOREIGN KEY (access_token_key_id) REFERENCES dbcrypt_keys(active_key_digest);
|
||||
ForeignKeyMcpServerUserTokensMcpServerConfigID ForeignKeyConstraint = "mcp_server_user_tokens_mcp_server_config_id_fkey" // ALTER TABLE ONLY mcp_server_user_tokens ADD CONSTRAINT mcp_server_user_tokens_mcp_server_config_id_fkey FOREIGN KEY (mcp_server_config_id) REFERENCES mcp_server_configs(id) ON DELETE CASCADE;
|
||||
ForeignKeyMcpServerUserTokensRefreshTokenKeyID ForeignKeyConstraint = "mcp_server_user_tokens_refresh_token_key_id_fkey" // ALTER TABLE ONLY mcp_server_user_tokens ADD CONSTRAINT mcp_server_user_tokens_refresh_token_key_id_fkey FOREIGN KEY (refresh_token_key_id) REFERENCES dbcrypt_keys(active_key_digest);
|
||||
ForeignKeyMcpServerUserTokensUserID ForeignKeyConstraint = "mcp_server_user_tokens_user_id_fkey" // ALTER TABLE ONLY mcp_server_user_tokens ADD CONSTRAINT mcp_server_user_tokens_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
|
||||
ForeignKeyNotificationMessagesNotificationTemplateID ForeignKeyConstraint = "notification_messages_notification_template_id_fkey" // ALTER TABLE ONLY notification_messages ADD CONSTRAINT notification_messages_notification_template_id_fkey FOREIGN KEY (notification_template_id) REFERENCES notification_templates(id) ON DELETE CASCADE;
|
||||
ForeignKeyNotificationMessagesUserID ForeignKeyConstraint = "notification_messages_user_id_fkey" // ALTER TABLE ONLY notification_messages ADD CONSTRAINT notification_messages_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
|
||||
ForeignKeyNotificationPreferencesNotificationTemplateID ForeignKeyConstraint = "notification_preferences_notification_template_id_fkey" // ALTER TABLE ONLY notification_preferences ADD CONSTRAINT notification_preferences_notification_template_id_fkey FOREIGN KEY (notification_template_id) REFERENCES notification_templates(id) ON DELETE CASCADE;
|
||||
ForeignKeyNotificationPreferencesUserID ForeignKeyConstraint = "notification_preferences_user_id_fkey" // ALTER TABLE ONLY notification_preferences ADD CONSTRAINT notification_preferences_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
|
||||
ForeignKeyOauth2ProviderAppCodesAppID ForeignKeyConstraint = "oauth2_provider_app_codes_app_id_fkey" // ALTER TABLE ONLY oauth2_provider_app_codes ADD CONSTRAINT oauth2_provider_app_codes_app_id_fkey FOREIGN KEY (app_id) REFERENCES oauth2_provider_apps(id) ON DELETE CASCADE;
|
||||
ForeignKeyOauth2ProviderAppCodesUserID ForeignKeyConstraint = "oauth2_provider_app_codes_user_id_fkey" // ALTER TABLE ONLY oauth2_provider_app_codes ADD CONSTRAINT oauth2_provider_app_codes_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
|
||||
ForeignKeyOauth2ProviderAppSecretsAppID ForeignKeyConstraint = "oauth2_provider_app_secrets_app_id_fkey" // ALTER TABLE ONLY oauth2_provider_app_secrets ADD CONSTRAINT oauth2_provider_app_secrets_app_id_fkey FOREIGN KEY (app_id) REFERENCES oauth2_provider_apps(id) ON DELETE CASCADE;
|
||||
ForeignKeyOauth2ProviderAppTokensAPIKeyID ForeignKeyConstraint = "oauth2_provider_app_tokens_api_key_id_fkey" // ALTER TABLE ONLY oauth2_provider_app_tokens ADD CONSTRAINT oauth2_provider_app_tokens_api_key_id_fkey FOREIGN KEY (api_key_id) REFERENCES api_keys(id) ON DELETE CASCADE;
|
||||
ForeignKeyOauth2ProviderAppTokensAppID ForeignKeyConstraint = "oauth2_provider_app_tokens_app_id_fkey" // ALTER TABLE ONLY oauth2_provider_app_tokens ADD CONSTRAINT oauth2_provider_app_tokens_app_id_fkey FOREIGN KEY (app_id) REFERENCES oauth2_provider_apps(id) ON DELETE CASCADE;
|
||||
ForeignKeyOauth2ProviderAppTokensAppSecretID ForeignKeyConstraint = "oauth2_provider_app_tokens_app_secret_id_fkey" // ALTER TABLE ONLY oauth2_provider_app_tokens ADD CONSTRAINT oauth2_provider_app_tokens_app_secret_id_fkey FOREIGN KEY (app_secret_id) REFERENCES oauth2_provider_app_secrets(id) ON DELETE CASCADE;
|
||||
ForeignKeyOrganizationMembersOrganizationIDUUID ForeignKeyConstraint = "organization_members_organization_id_uuid_fkey" // ALTER TABLE ONLY organization_members ADD CONSTRAINT organization_members_organization_id_uuid_fkey FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE;
|
||||
ForeignKeyOrganizationMembersUserIDUUID ForeignKeyConstraint = "organization_members_user_id_uuid_fkey" // ALTER TABLE ONLY organization_members ADD CONSTRAINT organization_members_user_id_uuid_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
|
||||
ForeignKeyParameterSchemasJobID ForeignKeyConstraint = "parameter_schemas_job_id_fkey" // ALTER TABLE ONLY parameter_schemas ADD CONSTRAINT parameter_schemas_job_id_fkey FOREIGN KEY (job_id) REFERENCES provisioner_jobs(id) ON DELETE CASCADE;
|
||||
ForeignKeyProvisionerDaemonsKeyID ForeignKeyConstraint = "provisioner_daemons_key_id_fkey" // ALTER TABLE ONLY provisioner_daemons ADD CONSTRAINT provisioner_daemons_key_id_fkey FOREIGN KEY (key_id) REFERENCES provisioner_keys(id) ON DELETE CASCADE;
|
||||
ForeignKeyProvisionerDaemonsOrganizationID ForeignKeyConstraint = "provisioner_daemons_organization_id_fkey" // ALTER TABLE ONLY provisioner_daemons ADD CONSTRAINT provisioner_daemons_organization_id_fkey FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE;
|
||||
ForeignKeyProvisionerJobLogsJobID ForeignKeyConstraint = "provisioner_job_logs_job_id_fkey" // ALTER TABLE ONLY provisioner_job_logs ADD CONSTRAINT provisioner_job_logs_job_id_fkey FOREIGN KEY (job_id) REFERENCES provisioner_jobs(id) ON DELETE CASCADE;
|
||||
ForeignKeyProvisionerJobTimingsJobID ForeignKeyConstraint = "provisioner_job_timings_job_id_fkey" // ALTER TABLE ONLY provisioner_job_timings ADD CONSTRAINT provisioner_job_timings_job_id_fkey FOREIGN KEY (job_id) REFERENCES provisioner_jobs(id) ON DELETE CASCADE;
|
||||
ForeignKeyProvisionerJobsOrganizationID ForeignKeyConstraint = "provisioner_jobs_organization_id_fkey" // ALTER TABLE ONLY provisioner_jobs ADD CONSTRAINT provisioner_jobs_organization_id_fkey FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE;
|
||||
ForeignKeyProvisionerKeysOrganizationID ForeignKeyConstraint = "provisioner_keys_organization_id_fkey" // ALTER TABLE ONLY provisioner_keys ADD CONSTRAINT provisioner_keys_organization_id_fkey FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE;
|
||||
ForeignKeyTailnetPeersCoordinatorID ForeignKeyConstraint = "tailnet_peers_coordinator_id_fkey" // ALTER TABLE ONLY tailnet_peers ADD CONSTRAINT tailnet_peers_coordinator_id_fkey FOREIGN KEY (coordinator_id) REFERENCES tailnet_coordinators(id) ON DELETE CASCADE;
|
||||
ForeignKeyTailnetTunnelsCoordinatorID ForeignKeyConstraint = "tailnet_tunnels_coordinator_id_fkey" // ALTER TABLE ONLY tailnet_tunnels ADD CONSTRAINT tailnet_tunnels_coordinator_id_fkey FOREIGN KEY (coordinator_id) REFERENCES tailnet_coordinators(id) ON DELETE CASCADE;
|
||||
ForeignKeyTaskSnapshotsTaskID ForeignKeyConstraint = "task_snapshots_task_id_fkey" // ALTER TABLE ONLY task_snapshots ADD CONSTRAINT task_snapshots_task_id_fkey FOREIGN KEY (task_id) REFERENCES tasks(id) ON DELETE CASCADE;
|
||||
ForeignKeyTaskWorkspaceAppsTaskID ForeignKeyConstraint = "task_workspace_apps_task_id_fkey" // ALTER TABLE ONLY task_workspace_apps ADD CONSTRAINT task_workspace_apps_task_id_fkey FOREIGN KEY (task_id) REFERENCES tasks(id) ON DELETE CASCADE;
|
||||
ForeignKeyTaskWorkspaceAppsWorkspaceAgentID ForeignKeyConstraint = "task_workspace_apps_workspace_agent_id_fkey" // ALTER TABLE ONLY task_workspace_apps ADD CONSTRAINT task_workspace_apps_workspace_agent_id_fkey FOREIGN KEY (workspace_agent_id) REFERENCES workspace_agents(id) ON DELETE CASCADE;
|
||||
ForeignKeyTaskWorkspaceAppsWorkspaceAppID ForeignKeyConstraint = "task_workspace_apps_workspace_app_id_fkey" // ALTER TABLE ONLY task_workspace_apps ADD CONSTRAINT task_workspace_apps_workspace_app_id_fkey FOREIGN KEY (workspace_app_id) REFERENCES workspace_apps(id) ON DELETE CASCADE;
|
||||
ForeignKeyTasksOrganizationID ForeignKeyConstraint = "tasks_organization_id_fkey" // ALTER TABLE ONLY tasks ADD CONSTRAINT tasks_organization_id_fkey FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE;
|
||||
ForeignKeyTasksOwnerID ForeignKeyConstraint = "tasks_owner_id_fkey" // ALTER TABLE ONLY tasks ADD CONSTRAINT tasks_owner_id_fkey FOREIGN KEY (owner_id) REFERENCES users(id) ON DELETE CASCADE;
|
||||
ForeignKeyTasksTemplateVersionID ForeignKeyConstraint = "tasks_template_version_id_fkey" // ALTER TABLE ONLY tasks ADD CONSTRAINT tasks_template_version_id_fkey FOREIGN KEY (template_version_id) REFERENCES template_versions(id) ON DELETE CASCADE;
|
||||
ForeignKeyTasksWorkspaceID ForeignKeyConstraint = "tasks_workspace_id_fkey" // ALTER TABLE ONLY tasks ADD CONSTRAINT tasks_workspace_id_fkey FOREIGN KEY (workspace_id) REFERENCES workspaces(id) ON DELETE CASCADE;
|
||||
ForeignKeyTemplateVersionParametersTemplateVersionID ForeignKeyConstraint = "template_version_parameters_template_version_id_fkey" // ALTER TABLE ONLY template_version_parameters ADD CONSTRAINT template_version_parameters_template_version_id_fkey FOREIGN KEY (template_version_id) REFERENCES template_versions(id) ON DELETE CASCADE;
|
||||
ForeignKeyTemplateVersionPresetParametTemplateVersionPresetID ForeignKeyConstraint = "template_version_preset_paramet_template_version_preset_id_fkey" // ALTER TABLE ONLY template_version_preset_parameters ADD CONSTRAINT template_version_preset_paramet_template_version_preset_id_fkey FOREIGN KEY (template_version_preset_id) REFERENCES template_version_presets(id) ON DELETE CASCADE;
|
||||
ForeignKeyTemplateVersionPresetPrebuildSchedulesPresetID ForeignKeyConstraint = "template_version_preset_prebuild_schedules_preset_id_fkey" // ALTER TABLE ONLY template_version_preset_prebuild_schedules ADD CONSTRAINT template_version_preset_prebuild_schedules_preset_id_fkey FOREIGN KEY (preset_id) REFERENCES template_version_presets(id) ON DELETE CASCADE;
|
||||
ForeignKeyTemplateVersionPresetsTemplateVersionID ForeignKeyConstraint = "template_version_presets_template_version_id_fkey" // ALTER TABLE ONLY template_version_presets ADD CONSTRAINT template_version_presets_template_version_id_fkey FOREIGN KEY (template_version_id) REFERENCES template_versions(id) ON DELETE CASCADE;
|
||||
ForeignKeyTemplateVersionTerraformValuesCachedModuleFiles ForeignKeyConstraint = "template_version_terraform_values_cached_module_files_fkey" // ALTER TABLE ONLY template_version_terraform_values ADD CONSTRAINT template_version_terraform_values_cached_module_files_fkey FOREIGN KEY (cached_module_files) REFERENCES files(id);
|
||||
ForeignKeyTemplateVersionTerraformValuesTemplateVersionID ForeignKeyConstraint = "template_version_terraform_values_template_version_id_fkey" // ALTER TABLE ONLY template_version_terraform_values ADD CONSTRAINT template_version_terraform_values_template_version_id_fkey FOREIGN KEY (template_version_id) REFERENCES template_versions(id) ON DELETE CASCADE;
|
||||
ForeignKeyTemplateVersionVariablesTemplateVersionID ForeignKeyConstraint = "template_version_variables_template_version_id_fkey" // ALTER TABLE ONLY template_version_variables ADD CONSTRAINT template_version_variables_template_version_id_fkey FOREIGN KEY (template_version_id) REFERENCES template_versions(id) ON DELETE CASCADE;
|
||||
ForeignKeyTemplateVersionWorkspaceTagsTemplateVersionID ForeignKeyConstraint = "template_version_workspace_tags_template_version_id_fkey" // ALTER TABLE ONLY template_version_workspace_tags ADD CONSTRAINT template_version_workspace_tags_template_version_id_fkey FOREIGN KEY (template_version_id) REFERENCES template_versions(id) ON DELETE CASCADE;
|
||||
ForeignKeyTemplateVersionsCreatedBy ForeignKeyConstraint = "template_versions_created_by_fkey" // ALTER TABLE ONLY template_versions ADD CONSTRAINT template_versions_created_by_fkey FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE RESTRICT;
|
||||
ForeignKeyTemplateVersionsOrganizationID ForeignKeyConstraint = "template_versions_organization_id_fkey" // ALTER TABLE ONLY template_versions ADD CONSTRAINT template_versions_organization_id_fkey FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE;
|
||||
ForeignKeyTemplateVersionsTemplateID ForeignKeyConstraint = "template_versions_template_id_fkey" // ALTER TABLE ONLY template_versions ADD CONSTRAINT template_versions_template_id_fkey FOREIGN KEY (template_id) REFERENCES templates(id) ON DELETE CASCADE;
|
||||
ForeignKeyTemplatesCreatedBy ForeignKeyConstraint = "templates_created_by_fkey" // ALTER TABLE ONLY templates ADD CONSTRAINT templates_created_by_fkey FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE RESTRICT;
|
||||
ForeignKeyTemplatesOrganizationID ForeignKeyConstraint = "templates_organization_id_fkey" // ALTER TABLE ONLY templates ADD CONSTRAINT templates_organization_id_fkey FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE;
|
||||
ForeignKeyUserAIBudgetOverridesGroupID ForeignKeyConstraint = "user_ai_budget_overrides_group_id_fkey" // ALTER TABLE ONLY user_ai_budget_overrides ADD CONSTRAINT user_ai_budget_overrides_group_id_fkey FOREIGN KEY (group_id) REFERENCES groups(id) ON DELETE CASCADE;
|
||||
ForeignKeyUserAIBudgetOverridesUserID ForeignKeyConstraint = "user_ai_budget_overrides_user_id_fkey" // ALTER TABLE ONLY user_ai_budget_overrides ADD CONSTRAINT user_ai_budget_overrides_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
|
||||
ForeignKeyUserAIProviderKeysAIProviderID ForeignKeyConstraint = "user_ai_provider_keys_ai_provider_id_fkey" // ALTER TABLE ONLY user_ai_provider_keys ADD CONSTRAINT user_ai_provider_keys_ai_provider_id_fkey FOREIGN KEY (ai_provider_id) REFERENCES ai_providers(id) ON DELETE CASCADE;
|
||||
ForeignKeyUserAIProviderKeysAPIKeyKeyID ForeignKeyConstraint = "user_ai_provider_keys_api_key_key_id_fkey" // ALTER TABLE ONLY user_ai_provider_keys ADD CONSTRAINT user_ai_provider_keys_api_key_key_id_fkey FOREIGN KEY (api_key_key_id) REFERENCES dbcrypt_keys(active_key_digest);
|
||||
ForeignKeyUserAIProviderKeysUserID ForeignKeyConstraint = "user_ai_provider_keys_user_id_fkey" // ALTER TABLE ONLY user_ai_provider_keys ADD CONSTRAINT user_ai_provider_keys_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
|
||||
ForeignKeyUserConfigsUserID ForeignKeyConstraint = "user_configs_user_id_fkey" // ALTER TABLE ONLY user_configs ADD CONSTRAINT user_configs_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
|
||||
ForeignKeyUserDeletedUserID ForeignKeyConstraint = "user_deleted_user_id_fkey" // ALTER TABLE ONLY user_deleted ADD CONSTRAINT user_deleted_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id);
|
||||
ForeignKeyUserLinksOauthAccessTokenKeyID ForeignKeyConstraint = "user_links_oauth_access_token_key_id_fkey" // ALTER TABLE ONLY user_links ADD CONSTRAINT user_links_oauth_access_token_key_id_fkey FOREIGN KEY (oauth_access_token_key_id) REFERENCES dbcrypt_keys(active_key_digest);
|
||||
ForeignKeyUserLinksOauthRefreshTokenKeyID ForeignKeyConstraint = "user_links_oauth_refresh_token_key_id_fkey" // ALTER TABLE ONLY user_links ADD CONSTRAINT user_links_oauth_refresh_token_key_id_fkey FOREIGN KEY (oauth_refresh_token_key_id) REFERENCES dbcrypt_keys(active_key_digest);
|
||||
ForeignKeyUserLinksUserID ForeignKeyConstraint = "user_links_user_id_fkey" // ALTER TABLE ONLY user_links ADD CONSTRAINT user_links_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
|
||||
ForeignKeyUserSecretsUserID ForeignKeyConstraint = "user_secrets_user_id_fkey" // ALTER TABLE ONLY user_secrets ADD CONSTRAINT user_secrets_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
|
||||
ForeignKeyUserSecretsValueKeyID ForeignKeyConstraint = "user_secrets_value_key_id_fkey" // ALTER TABLE ONLY user_secrets ADD CONSTRAINT user_secrets_value_key_id_fkey FOREIGN KEY (value_key_id) REFERENCES dbcrypt_keys(active_key_digest);
|
||||
ForeignKeyUserSkillsUserID ForeignKeyConstraint = "user_skills_user_id_fkey" // ALTER TABLE ONLY user_skills ADD CONSTRAINT user_skills_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
|
||||
ForeignKeyUserStatusChangesUserID ForeignKeyConstraint = "user_status_changes_user_id_fkey" // ALTER TABLE ONLY user_status_changes ADD CONSTRAINT user_status_changes_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id);
|
||||
ForeignKeyWebpushSubscriptionsUserID ForeignKeyConstraint = "webpush_subscriptions_user_id_fkey" // ALTER TABLE ONLY webpush_subscriptions ADD CONSTRAINT webpush_subscriptions_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
|
||||
ForeignKeyWorkspaceAgentContextResourcesWorkspaceAgentID ForeignKeyConstraint = "workspace_agent_context_resources_workspace_agent_id_fkey" // ALTER TABLE ONLY workspace_agent_context_resources ADD CONSTRAINT workspace_agent_context_resources_workspace_agent_id_fkey FOREIGN KEY (workspace_agent_id) REFERENCES workspace_agents(id) ON DELETE CASCADE;
|
||||
ForeignKeyWorkspaceAgentContextSnapshotsWorkspaceAgentID ForeignKeyConstraint = "workspace_agent_context_snapshots_workspace_agent_id_fkey" // ALTER TABLE ONLY workspace_agent_context_snapshots ADD CONSTRAINT workspace_agent_context_snapshots_workspace_agent_id_fkey FOREIGN KEY (workspace_agent_id) REFERENCES workspace_agents(id) ON DELETE CASCADE;
|
||||
ForeignKeyWorkspaceAgentDevcontainersSubagentID ForeignKeyConstraint = "workspace_agent_devcontainers_subagent_id_fkey" // ALTER TABLE ONLY workspace_agent_devcontainers ADD CONSTRAINT workspace_agent_devcontainers_subagent_id_fkey FOREIGN KEY (subagent_id) REFERENCES workspace_agents(id) ON DELETE CASCADE;
|
||||
ForeignKeyWorkspaceAgentDevcontainersWorkspaceAgentID ForeignKeyConstraint = "workspace_agent_devcontainers_workspace_agent_id_fkey" // ALTER TABLE ONLY workspace_agent_devcontainers ADD CONSTRAINT workspace_agent_devcontainers_workspace_agent_id_fkey FOREIGN KEY (workspace_agent_id) REFERENCES workspace_agents(id) ON DELETE CASCADE;
|
||||
ForeignKeyWorkspaceAgentLogSourcesWorkspaceAgentID ForeignKeyConstraint = "workspace_agent_log_sources_workspace_agent_id_fkey" // ALTER TABLE ONLY workspace_agent_log_sources ADD CONSTRAINT workspace_agent_log_sources_workspace_agent_id_fkey FOREIGN KEY (workspace_agent_id) REFERENCES workspace_agents(id) ON DELETE CASCADE;
|
||||
ForeignKeyWorkspaceAgentMemoryResourceMonitorsAgentID ForeignKeyConstraint = "workspace_agent_memory_resource_monitors_agent_id_fkey" // ALTER TABLE ONLY workspace_agent_memory_resource_monitors ADD CONSTRAINT workspace_agent_memory_resource_monitors_agent_id_fkey FOREIGN KEY (agent_id) REFERENCES workspace_agents(id) ON DELETE CASCADE;
|
||||
ForeignKeyWorkspaceAgentMetadataWorkspaceAgentID ForeignKeyConstraint = "workspace_agent_metadata_workspace_agent_id_fkey" // ALTER TABLE ONLY workspace_agent_metadata ADD CONSTRAINT workspace_agent_metadata_workspace_agent_id_fkey FOREIGN KEY (workspace_agent_id) REFERENCES workspace_agents(id) ON DELETE CASCADE;
|
||||
ForeignKeyWorkspaceAgentPortShareWorkspaceID ForeignKeyConstraint = "workspace_agent_port_share_workspace_id_fkey" // ALTER TABLE ONLY workspace_agent_port_share ADD CONSTRAINT workspace_agent_port_share_workspace_id_fkey FOREIGN KEY (workspace_id) REFERENCES workspaces(id) ON DELETE CASCADE;
|
||||
ForeignKeyWorkspaceAgentScriptTimingsScriptID ForeignKeyConstraint = "workspace_agent_script_timings_script_id_fkey" // ALTER TABLE ONLY workspace_agent_script_timings ADD CONSTRAINT workspace_agent_script_timings_script_id_fkey FOREIGN KEY (script_id) REFERENCES workspace_agent_scripts(id) ON DELETE CASCADE;
|
||||
ForeignKeyWorkspaceAgentScriptsWorkspaceAgentID ForeignKeyConstraint = "workspace_agent_scripts_workspace_agent_id_fkey" // ALTER TABLE ONLY workspace_agent_scripts ADD CONSTRAINT workspace_agent_scripts_workspace_agent_id_fkey FOREIGN KEY (workspace_agent_id) REFERENCES workspace_agents(id) ON DELETE CASCADE;
|
||||
ForeignKeyWorkspaceAgentStartupLogsAgentID ForeignKeyConstraint = "workspace_agent_startup_logs_agent_id_fkey" // ALTER TABLE ONLY workspace_agent_logs ADD CONSTRAINT workspace_agent_startup_logs_agent_id_fkey FOREIGN KEY (agent_id) REFERENCES workspace_agents(id) ON DELETE CASCADE;
|
||||
ForeignKeyWorkspaceAgentVolumeResourceMonitorsAgentID ForeignKeyConstraint = "workspace_agent_volume_resource_monitors_agent_id_fkey" // ALTER TABLE ONLY workspace_agent_volume_resource_monitors ADD CONSTRAINT workspace_agent_volume_resource_monitors_agent_id_fkey FOREIGN KEY (agent_id) REFERENCES workspace_agents(id) ON DELETE CASCADE;
|
||||
ForeignKeyWorkspaceAgentsParentID ForeignKeyConstraint = "workspace_agents_parent_id_fkey" // ALTER TABLE ONLY workspace_agents ADD CONSTRAINT workspace_agents_parent_id_fkey FOREIGN KEY (parent_id) REFERENCES workspace_agents(id) ON DELETE CASCADE;
|
||||
ForeignKeyWorkspaceAgentsResourceID ForeignKeyConstraint = "workspace_agents_resource_id_fkey" // ALTER TABLE ONLY workspace_agents ADD CONSTRAINT workspace_agents_resource_id_fkey FOREIGN KEY (resource_id) REFERENCES workspace_resources(id) ON DELETE CASCADE;
|
||||
ForeignKeyWorkspaceAppAuditSessionsAgentID ForeignKeyConstraint = "workspace_app_audit_sessions_agent_id_fkey" // ALTER TABLE ONLY workspace_app_audit_sessions ADD CONSTRAINT workspace_app_audit_sessions_agent_id_fkey FOREIGN KEY (agent_id) REFERENCES workspace_agents(id) ON DELETE CASCADE;
|
||||
ForeignKeyWorkspaceAppStatsAgentID ForeignKeyConstraint = "workspace_app_stats_agent_id_fkey" // ALTER TABLE ONLY workspace_app_stats ADD CONSTRAINT workspace_app_stats_agent_id_fkey FOREIGN KEY (agent_id) REFERENCES workspace_agents(id);
|
||||
ForeignKeyWorkspaceAppStatsUserID ForeignKeyConstraint = "workspace_app_stats_user_id_fkey" // ALTER TABLE ONLY workspace_app_stats ADD CONSTRAINT workspace_app_stats_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id);
|
||||
ForeignKeyWorkspaceAppStatsWorkspaceID ForeignKeyConstraint = "workspace_app_stats_workspace_id_fkey" // ALTER TABLE ONLY workspace_app_stats ADD CONSTRAINT workspace_app_stats_workspace_id_fkey FOREIGN KEY (workspace_id) REFERENCES workspaces(id);
|
||||
ForeignKeyWorkspaceAppStatusesAgentID ForeignKeyConstraint = "workspace_app_statuses_agent_id_fkey" // ALTER TABLE ONLY workspace_app_statuses ADD CONSTRAINT workspace_app_statuses_agent_id_fkey FOREIGN KEY (agent_id) REFERENCES workspace_agents(id);
|
||||
ForeignKeyWorkspaceAppStatusesAppID ForeignKeyConstraint = "workspace_app_statuses_app_id_fkey" // ALTER TABLE ONLY workspace_app_statuses ADD CONSTRAINT workspace_app_statuses_app_id_fkey FOREIGN KEY (app_id) REFERENCES workspace_apps(id);
|
||||
ForeignKeyWorkspaceAppStatusesWorkspaceID ForeignKeyConstraint = "workspace_app_statuses_workspace_id_fkey" // ALTER TABLE ONLY workspace_app_statuses ADD CONSTRAINT workspace_app_statuses_workspace_id_fkey FOREIGN KEY (workspace_id) REFERENCES workspaces(id);
|
||||
ForeignKeyWorkspaceAppsAgentID ForeignKeyConstraint = "workspace_apps_agent_id_fkey" // ALTER TABLE ONLY workspace_apps ADD CONSTRAINT workspace_apps_agent_id_fkey FOREIGN KEY (agent_id) REFERENCES workspace_agents(id) ON DELETE CASCADE;
|
||||
ForeignKeyWorkspaceBuildOrchestrationsChildBuildWorkspaceID ForeignKeyConstraint = "workspace_build_orchestrations_child_build_workspace_id_fkey" // ALTER TABLE ONLY workspace_build_orchestrations ADD CONSTRAINT workspace_build_orchestrations_child_build_workspace_id_fkey FOREIGN KEY (child_build_id, workspace_id) REFERENCES workspace_builds(id, workspace_id) ON DELETE CASCADE;
|
||||
ForeignKeyWorkspaceBuildOrchestrationsChildPresetID ForeignKeyConstraint = "workspace_build_orchestrations_child_preset_id_fkey" // ALTER TABLE ONLY workspace_build_orchestrations ADD CONSTRAINT workspace_build_orchestrations_child_preset_id_fkey FOREIGN KEY (child_template_version_preset_id) REFERENCES template_version_presets(id) ON DELETE SET NULL;
|
||||
ForeignKeyWorkspaceBuildOrchestrationsChildPresetVersion ForeignKeyConstraint = "workspace_build_orchestrations_child_preset_version_fkey" // ALTER TABLE ONLY workspace_build_orchestrations ADD CONSTRAINT workspace_build_orchestrations_child_preset_version_fkey FOREIGN KEY (child_template_version_preset_id, child_template_version_id) REFERENCES template_version_presets(id, template_version_id);
|
||||
ForeignKeyWorkspaceBuildOrchestrationsChildTemplateVersionID ForeignKeyConstraint = "workspace_build_orchestrations_child_template_version_id_fkey" // ALTER TABLE ONLY workspace_build_orchestrations ADD CONSTRAINT workspace_build_orchestrations_child_template_version_id_fkey FOREIGN KEY (child_template_version_id) REFERENCES template_versions(id) ON DELETE CASCADE;
|
||||
ForeignKeyWorkspaceBuildOrchestrationsParentBuildWorkspaceID ForeignKeyConstraint = "workspace_build_orchestrations_parent_build_workspace_id_fkey" // ALTER TABLE ONLY workspace_build_orchestrations ADD CONSTRAINT workspace_build_orchestrations_parent_build_workspace_id_fkey FOREIGN KEY (parent_build_id, workspace_id) REFERENCES workspace_builds(id, workspace_id) ON DELETE CASCADE;
|
||||
ForeignKeyWorkspaceBuildParametersWorkspaceBuildID ForeignKeyConstraint = "workspace_build_parameters_workspace_build_id_fkey" // ALTER TABLE ONLY workspace_build_parameters ADD CONSTRAINT workspace_build_parameters_workspace_build_id_fkey FOREIGN KEY (workspace_build_id) REFERENCES workspace_builds(id) ON DELETE CASCADE;
|
||||
ForeignKeyWorkspaceBuildsJobID ForeignKeyConstraint = "workspace_builds_job_id_fkey" // ALTER TABLE ONLY workspace_builds ADD CONSTRAINT workspace_builds_job_id_fkey FOREIGN KEY (job_id) REFERENCES provisioner_jobs(id) ON DELETE CASCADE;
|
||||
ForeignKeyWorkspaceBuildsTemplateVersionID ForeignKeyConstraint = "workspace_builds_template_version_id_fkey" // ALTER TABLE ONLY workspace_builds ADD CONSTRAINT workspace_builds_template_version_id_fkey FOREIGN KEY (template_version_id) REFERENCES template_versions(id) ON DELETE CASCADE;
|
||||
ForeignKeyWorkspaceBuildsTemplateVersionPresetID ForeignKeyConstraint = "workspace_builds_template_version_preset_id_fkey" // ALTER TABLE ONLY workspace_builds ADD CONSTRAINT workspace_builds_template_version_preset_id_fkey FOREIGN KEY (template_version_preset_id) REFERENCES template_version_presets(id) ON DELETE SET NULL;
|
||||
ForeignKeyWorkspaceBuildsWorkspaceID ForeignKeyConstraint = "workspace_builds_workspace_id_fkey" // ALTER TABLE ONLY workspace_builds ADD CONSTRAINT workspace_builds_workspace_id_fkey FOREIGN KEY (workspace_id) REFERENCES workspaces(id) ON DELETE CASCADE;
|
||||
ForeignKeyWorkspaceModulesJobID ForeignKeyConstraint = "workspace_modules_job_id_fkey" // ALTER TABLE ONLY workspace_modules ADD CONSTRAINT workspace_modules_job_id_fkey FOREIGN KEY (job_id) REFERENCES provisioner_jobs(id) ON DELETE CASCADE;
|
||||
ForeignKeyWorkspaceResourceMetadataWorkspaceResourceID ForeignKeyConstraint = "workspace_resource_metadata_workspace_resource_id_fkey" // ALTER TABLE ONLY workspace_resource_metadata ADD CONSTRAINT workspace_resource_metadata_workspace_resource_id_fkey FOREIGN KEY (workspace_resource_id) REFERENCES workspace_resources(id) ON DELETE CASCADE;
|
||||
ForeignKeyWorkspaceResourcesJobID ForeignKeyConstraint = "workspace_resources_job_id_fkey" // ALTER TABLE ONLY workspace_resources ADD CONSTRAINT workspace_resources_job_id_fkey FOREIGN KEY (job_id) REFERENCES provisioner_jobs(id) ON DELETE CASCADE;
|
||||
ForeignKeyWorkspacesOrganizationID ForeignKeyConstraint = "workspaces_organization_id_fkey" // ALTER TABLE ONLY workspaces ADD CONSTRAINT workspaces_organization_id_fkey FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE RESTRICT;
|
||||
ForeignKeyWorkspacesOwnerID ForeignKeyConstraint = "workspaces_owner_id_fkey" // ALTER TABLE ONLY workspaces ADD CONSTRAINT workspaces_owner_id_fkey FOREIGN KEY (owner_id) REFERENCES users(id) ON DELETE RESTRICT;
|
||||
ForeignKeyWorkspacesTemplateID ForeignKeyConstraint = "workspaces_template_id_fkey" // ALTER TABLE ONLY workspaces ADD CONSTRAINT workspaces_template_id_fkey FOREIGN KEY (template_id) REFERENCES templates(id) ON DELETE RESTRICT;
|
||||
)
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
DROP TABLE chat_user_model_overrides;
|
||||
DROP TABLE chat_organization_model_overrides;
|
||||
|
||||
ALTER TABLE chat_model_configs
|
||||
DROP CONSTRAINT chat_model_configs_organization_id_id_key;
|
||||
@@ -0,0 +1,54 @@
|
||||
ALTER TABLE chat_model_configs
|
||||
ADD CONSTRAINT chat_model_configs_organization_id_id_key
|
||||
UNIQUE (organization_id, id);
|
||||
|
||||
CREATE TABLE chat_organization_model_overrides (
|
||||
id uuid NOT NULL DEFAULT gen_random_uuid() PRIMARY KEY,
|
||||
organization_id uuid NOT NULL REFERENCES organizations(id) ON DELETE CASCADE,
|
||||
context text NOT NULL,
|
||||
model_config_id uuid NOT NULL,
|
||||
reasoning_effort text,
|
||||
CONSTRAINT chat_organization_model_overrides_context_check
|
||||
CHECK (context IN ('general', 'explore', 'title_generation', 'compaction', 'advisor')),
|
||||
CONSTRAINT chat_organization_model_overrides_organization_id_context_key
|
||||
UNIQUE (organization_id, context),
|
||||
CONSTRAINT chat_organization_model_overrides_organization_model_config_fkey
|
||||
FOREIGN KEY (organization_id, model_config_id)
|
||||
REFERENCES chat_model_configs (organization_id, id)
|
||||
);
|
||||
|
||||
CREATE TABLE chat_user_model_overrides (
|
||||
id uuid NOT NULL DEFAULT gen_random_uuid() PRIMARY KEY,
|
||||
user_id uuid NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
organization_id uuid NOT NULL REFERENCES organizations(id) ON DELETE CASCADE,
|
||||
context text NOT NULL,
|
||||
mode text NOT NULL,
|
||||
model_config_id uuid,
|
||||
reasoning_effort text,
|
||||
CONSTRAINT chat_user_model_overrides_context_check
|
||||
CHECK (context IN ('root', 'general', 'explore')),
|
||||
CONSTRAINT chat_user_model_overrides_mode_check
|
||||
CHECK (mode IN ('model', 'chat_default', 'deployment_default')),
|
||||
CONSTRAINT chat_user_model_overrides_model_requires_config_check
|
||||
CHECK ((mode = 'model') = (model_config_id IS NOT NULL)),
|
||||
CONSTRAINT chat_user_model_overrides_user_organization_context_key
|
||||
UNIQUE (user_id, organization_id, context),
|
||||
CONSTRAINT chat_user_model_overrides_organization_model_config_fkey
|
||||
FOREIGN KEY (organization_id, model_config_id)
|
||||
REFERENCES chat_model_configs (organization_id, id)
|
||||
);
|
||||
|
||||
-- Legacy serialized overrides are dropped rather than migrated; admins and
|
||||
-- users re-select models in the organization-scoped settings. Stale advisor
|
||||
-- model fields inside agents_advisor_config are left as-is: reads ignore
|
||||
-- unknown JSON keys and the next settings write rewrites the blob.
|
||||
DELETE FROM site_configs
|
||||
WHERE key IN (
|
||||
'agents_chat_general_model_override',
|
||||
'agents_chat_explore_model_override',
|
||||
'agents_chat_title_generation_model_override',
|
||||
'agents_chat_compaction_model_override'
|
||||
);
|
||||
|
||||
DELETE FROM user_configs
|
||||
WHERE key LIKE 'chat\_personal\_model\_override:%';
|
||||
@@ -3255,3 +3255,131 @@ func mustJSON(t *testing.T, v any) []byte {
|
||||
require.NoError(t, err)
|
||||
return raw
|
||||
}
|
||||
|
||||
func TestMigration000583ChatModelOverrideOrgScope(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
const migrationVersion = 583
|
||||
|
||||
db := testSQLDB(t)
|
||||
next, err := migrations.Stepper(db)
|
||||
require.NoError(t, err)
|
||||
last := uint(0)
|
||||
for {
|
||||
version, more, err := next()
|
||||
require.NoError(t, err)
|
||||
if !more {
|
||||
break
|
||||
}
|
||||
last = version
|
||||
}
|
||||
require.GreaterOrEqual(t, last, uint(migrationVersion))
|
||||
|
||||
ctx := testutil.Context(t, testutil.WaitSuperLong)
|
||||
upSQL, err := os.ReadFile("000583_chat_model_override_org_scope.up.sql")
|
||||
require.NoError(t, err)
|
||||
downSQL, err := os.ReadFile("000583_chat_model_override_org_scope.down.sql")
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = db.ExecContext(ctx, string(downSQL))
|
||||
require.NoError(t, err)
|
||||
|
||||
now := time.Now().UTC().Truncate(time.Microsecond)
|
||||
userID := uuid.New()
|
||||
providerID := uuid.New()
|
||||
modelID := uuid.New()
|
||||
|
||||
var orgID uuid.UUID
|
||||
require.NoError(t, db.QueryRowContext(ctx,
|
||||
"SELECT id FROM organizations WHERE is_default = true").Scan(&orgID))
|
||||
|
||||
_, err = db.ExecContext(ctx, `
|
||||
INSERT INTO users (id, username, email, hashed_password, created_at, updated_at, status, rbac_roles, login_type)
|
||||
VALUES ($1, $2, $3, $4, $5, $5, 'active', '{}', 'password')`,
|
||||
userID, "model-override-"+userID.String(), userID.String()+"@example.com", []byte{}, now)
|
||||
require.NoError(t, err)
|
||||
_, err = db.ExecContext(ctx, `
|
||||
INSERT INTO ai_providers (id, type, name, enabled, base_url, created_at, updated_at)
|
||||
VALUES ($1, 'openai', $2, true, 'https://example.com', $3, $3)`,
|
||||
providerID, "model-override-"+providerID.String(), now)
|
||||
require.NoError(t, err)
|
||||
_, err = db.ExecContext(ctx, `
|
||||
INSERT INTO chat_model_configs (
|
||||
id, model, display_name, enabled, is_default, deleted,
|
||||
context_limit, compression_threshold, ai_provider_id, organization_id,
|
||||
group_acl, user_acl, created_at, updated_at
|
||||
) VALUES ($1, $2, $2, true, false, false, 128000, 70, $3, $4, '{}', '{}', $5, $5)`,
|
||||
modelID, "model-override-"+modelID.String(), providerID, orgID, now)
|
||||
require.NoError(t, err)
|
||||
|
||||
advisorConfig := fmt.Sprintf(
|
||||
`{"enabled":true,"max_uses_per_run":2,"model_config_id":%q,"reasoning_effort":"low"}`, modelID)
|
||||
_, err = db.ExecContext(ctx, `
|
||||
INSERT INTO site_configs (key, value) VALUES
|
||||
('agents_chat_general_model_override', $1),
|
||||
('agents_chat_title_generation_model_override', 'not-a-uuid'),
|
||||
('agents_advisor_config', $2)
|
||||
ON CONFLICT (key) DO UPDATE SET value = EXCLUDED.value`,
|
||||
modelID.String()+":high", advisorConfig)
|
||||
require.NoError(t, err)
|
||||
_, err = db.ExecContext(ctx, `
|
||||
INSERT INTO user_configs (user_id, key, value) VALUES
|
||||
($1, 'chat_personal_model_override:root', $2),
|
||||
($1, 'chat_personal_model_override:general', 'chat_default')`,
|
||||
userID, "model:"+modelID.String()+":max")
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = db.ExecContext(ctx, string(upSQL))
|
||||
require.NoError(t, err)
|
||||
|
||||
// Legacy overrides are dropped rather than migrated: the new tables start
|
||||
// empty and the serialized keys are gone.
|
||||
var count int
|
||||
require.NoError(t, db.QueryRowContext(ctx,
|
||||
"SELECT COUNT(*) FROM chat_organization_model_overrides").Scan(&count))
|
||||
require.Zero(t, count)
|
||||
require.NoError(t, db.QueryRowContext(ctx,
|
||||
"SELECT COUNT(*) FROM chat_user_model_overrides").Scan(&count))
|
||||
require.Zero(t, count)
|
||||
require.NoError(t, db.QueryRowContext(ctx, `
|
||||
SELECT COUNT(*) FROM site_configs
|
||||
WHERE key IN (
|
||||
'agents_chat_general_model_override',
|
||||
'agents_chat_explore_model_override',
|
||||
'agents_chat_title_generation_model_override',
|
||||
'agents_chat_compaction_model_override'
|
||||
)`).Scan(&count))
|
||||
require.Zero(t, count)
|
||||
require.NoError(t, db.QueryRowContext(ctx, `
|
||||
SELECT COUNT(*) FROM user_configs
|
||||
WHERE user_id = $1 AND key LIKE 'chat\_personal\_model\_override:%'`, userID).Scan(&count))
|
||||
require.Zero(t, count)
|
||||
|
||||
// The migration does not parse the advisor runtime config; stale model
|
||||
// fields stay in the stored JSON and are ignored by readers.
|
||||
var value string
|
||||
require.NoError(t, db.QueryRowContext(ctx,
|
||||
"SELECT value FROM site_configs WHERE key = 'agents_advisor_config'").Scan(&value))
|
||||
require.Equal(t, advisorConfig, value)
|
||||
|
||||
// The composite foreign key rejects model references from another
|
||||
// organization.
|
||||
otherOrgID := uuid.New()
|
||||
_, err = db.ExecContext(ctx, `
|
||||
INSERT INTO organizations (
|
||||
id, name, display_name, description, created_at, updated_at,
|
||||
is_default, default_org_member_roles
|
||||
) VALUES ($1, $2, $2, '', $3, $3, false, '{}')`,
|
||||
otherOrgID, "model-override-"+otherOrgID.String(), now)
|
||||
require.NoError(t, err)
|
||||
_, err = db.ExecContext(ctx, `
|
||||
INSERT INTO chat_organization_model_overrides (organization_id, context, model_config_id)
|
||||
VALUES ($1, 'explore', $2)`, otherOrgID, modelID)
|
||||
require.Error(t, err)
|
||||
require.True(t, database.IsForeignKeyViolation(err))
|
||||
|
||||
_, err = db.ExecContext(ctx, string(downSQL))
|
||||
require.NoError(t, err)
|
||||
_, err = db.ExecContext(ctx, string(upSQL))
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
INSERT INTO chat_organization_model_overrides (
|
||||
organization_id,
|
||||
context,
|
||||
model_config_id,
|
||||
reasoning_effort
|
||||
)
|
||||
SELECT
|
||||
organization_id,
|
||||
'general',
|
||||
id,
|
||||
'high'
|
||||
FROM chat_model_configs
|
||||
WHERE id = '580c0001-0000-4000-8000-000000000001';
|
||||
|
||||
INSERT INTO chat_user_model_overrides (
|
||||
user_id,
|
||||
organization_id,
|
||||
context,
|
||||
mode
|
||||
)
|
||||
SELECT
|
||||
u.id,
|
||||
o.id,
|
||||
'root',
|
||||
'chat_default'
|
||||
FROM users u
|
||||
CROSS JOIN organizations o
|
||||
WHERE o.is_default
|
||||
ORDER BY u.id
|
||||
LIMIT 1;
|
||||
Generated
+18
@@ -5264,6 +5264,14 @@ type ChatModelConfig struct {
|
||||
UserACL ChatACL `db:"user_acl" json:"user_acl"`
|
||||
}
|
||||
|
||||
type ChatOrganizationModelOverride struct {
|
||||
ID uuid.UUID `db:"id" json:"id"`
|
||||
OrganizationID uuid.UUID `db:"organization_id" json:"organization_id"`
|
||||
Context string `db:"context" json:"context"`
|
||||
ModelConfigID uuid.UUID `db:"model_config_id" json:"model_config_id"`
|
||||
ReasoningEffort sql.NullString `db:"reasoning_effort" json:"reasoning_effort"`
|
||||
}
|
||||
|
||||
type ChatQueuedMessage struct {
|
||||
ID int64 `db:"id" json:"id"`
|
||||
ChatID uuid.UUID `db:"chat_id" json:"chat_id"`
|
||||
@@ -5343,6 +5351,16 @@ type ChatUsageLimitConfig struct {
|
||||
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
|
||||
}
|
||||
|
||||
type ChatUserModelOverride struct {
|
||||
ID uuid.UUID `db:"id" json:"id"`
|
||||
UserID uuid.UUID `db:"user_id" json:"user_id"`
|
||||
OrganizationID uuid.UUID `db:"organization_id" json:"organization_id"`
|
||||
Context string `db:"context" json:"context"`
|
||||
Mode string `db:"mode" json:"mode"`
|
||||
ModelConfigID uuid.NullUUID `db:"model_config_id" json:"model_config_id"`
|
||||
ReasoningEffort sql.NullString `db:"reasoning_effort" json:"reasoning_effort"`
|
||||
}
|
||||
|
||||
type ConnectionLog struct {
|
||||
ID uuid.UUID `db:"id" json:"id"`
|
||||
ConnectTime time.Time `db:"connect_time" json:"connect_time"`
|
||||
|
||||
Generated
+12
-11
@@ -147,6 +147,7 @@ type sqlcQuerier interface {
|
||||
// archive-cleanup retry).
|
||||
DeleteChatDebugDataByChatID(ctx context.Context, arg DeleteChatDebugDataByChatIDParams) (int64, error)
|
||||
DeleteChatModelConfigByID(ctx context.Context, id uuid.UUID) (uuid.UUID, error)
|
||||
DeleteChatOrganizationModelOverride(ctx context.Context, arg DeleteChatOrganizationModelOverrideParams) error
|
||||
DeleteChatQueuedMessage(ctx context.Context, arg DeleteChatQueuedMessageParams) error
|
||||
// Deletes a queued message, scoped to the parent chat. Returns the
|
||||
// number of affected rows so callers can detect missing rows without
|
||||
@@ -419,7 +420,6 @@ type sqlcQuerier interface {
|
||||
GetChatByID(ctx context.Context, id uuid.UUID) (Chat, error)
|
||||
GetChatByIDForShare(ctx context.Context, id uuid.UUID) (Chat, error)
|
||||
GetChatByIDForUpdate(ctx context.Context, id uuid.UUID) (Chat, error)
|
||||
GetChatCompactionModelOverride(ctx context.Context) (string, error)
|
||||
GetChatComputerUseProvider(ctx context.Context) (string, error)
|
||||
// GetChatDebugLoggingAllowUsers returns the runtime admin setting that
|
||||
// allows users to opt into chat debug logging when the deployment does
|
||||
@@ -442,7 +442,6 @@ type sqlcQuerier interface {
|
||||
// intentionally excluded from these aggregates.
|
||||
GetChatDiffStatusSummary(ctx context.Context) (GetChatDiffStatusSummaryRow, error)
|
||||
GetChatDiffStatusesByChatIDs(ctx context.Context, chatIds []uuid.UUID) ([]ChatDiffStatus, error)
|
||||
GetChatExploreModelOverride(ctx context.Context) (string, error)
|
||||
// Returns the chat IDs of every chat in a family (root + all children)
|
||||
// in deterministic order. The id parameter must be the root id; the
|
||||
// query does not walk up from a child.
|
||||
@@ -458,7 +457,6 @@ type sqlcQuerier interface {
|
||||
GetChatFileMetadataByChatID(ctx context.Context, chatID uuid.UUID) ([]GetChatFileMetadataByChatIDRow, error)
|
||||
GetChatFilesByIDs(ctx context.Context, ids []uuid.UUID) ([]ChatFile, error)
|
||||
GetChatGatewayAPIKey(ctx context.Context, arg GetChatGatewayAPIKeyParams) (APIKey, error)
|
||||
GetChatGeneralModelOverride(ctx context.Context) (string, error)
|
||||
GetChatHeartbeat(ctx context.Context, arg GetChatHeartbeatParams) (ChatHeartbeat, error)
|
||||
// GetChatIncludeDefaultSystemPrompt preserves the legacy default
|
||||
// for deployments created before the explicit include-default toggle.
|
||||
@@ -490,6 +488,13 @@ type sqlcQuerier interface {
|
||||
GetChatModelConfigsByOrganization(ctx context.Context, organizationID uuid.UUID) ([]ChatModelConfig, error)
|
||||
// deleted = false guarantees ai_provider_id is non-null, so INNER JOIN is safe.
|
||||
GetChatModelConfigsForTelemetry(ctx context.Context) ([]GetChatModelConfigsForTelemetryRow, error)
|
||||
GetChatOrganizationModelOverride(ctx context.Context, arg GetChatOrganizationModelOverrideParams) (ChatOrganizationModelOverride, error)
|
||||
GetChatOrganizationModelOverrides(ctx context.Context, organizationID uuid.UUID) ([]ChatOrganizationModelOverride, error)
|
||||
// Returns every non-deleted organization's override for one context together
|
||||
// with the resolved model and provider, for bulk consumers such as telemetry.
|
||||
// model_available mirrors GetEnabledChatModelConfigByID: it is false when the
|
||||
// referenced config or its provider is disabled or deleted.
|
||||
GetChatOrganizationModelOverridesByContext(ctx context.Context, argContext string) ([]GetChatOrganizationModelOverridesByContextRow, error)
|
||||
// GetChatPersonalModelOverridesEnabled returns whether users may configure
|
||||
// personal chat model overrides. It defaults to false when unset.
|
||||
GetChatPersonalModelOverridesEnabled(ctx context.Context) (bool, error)
|
||||
@@ -515,7 +520,8 @@ type sqlcQuerier interface {
|
||||
// non-empty custom prompt implied opting out before the explicit toggle
|
||||
// existed.
|
||||
GetChatSystemPromptConfig(ctx context.Context) (GetChatSystemPromptConfigRow, error)
|
||||
GetChatTitleGenerationModelOverride(ctx context.Context) (string, error)
|
||||
GetChatUserModelOverride(ctx context.Context, arg GetChatUserModelOverrideParams) (ChatUserModelOverride, error)
|
||||
GetChatUserModelOverrides(ctx context.Context, arg GetChatUserModelOverridesParams) ([]ChatUserModelOverride, error)
|
||||
// Returns the concatenated text of each user-visible user prompt in a
|
||||
// chat, newest first. Used by the composer to populate the up/down
|
||||
// arrow prompt-history cycle. Non-text parts (tool calls, files,
|
||||
@@ -926,7 +932,6 @@ type sqlcQuerier interface {
|
||||
GetUserChatCompactionThreshold(ctx context.Context, arg GetUserChatCompactionThresholdParams) (string, error)
|
||||
GetUserChatCustomPrompt(ctx context.Context, userID uuid.UUID) (string, error)
|
||||
GetUserChatDebugLoggingEnabled(ctx context.Context, userID uuid.UUID) (bool, error)
|
||||
GetUserChatPersonalModelOverride(ctx context.Context, arg GetUserChatPersonalModelOverrideParams) (string, error)
|
||||
GetUserCodeDiffDisplayMode(ctx context.Context, userID uuid.UUID) (string, error)
|
||||
GetUserCount(ctx context.Context, includeSystem bool) (int64, error)
|
||||
// Returns the "Everyone" group (id == organization_id) to attribute a user's
|
||||
@@ -1288,7 +1293,6 @@ type sqlcQuerier interface {
|
||||
// Used by the usage generator to find missing heartbeat buckets.
|
||||
ListUsageEventCreatedAtsByTypeSince(ctx context.Context, arg ListUsageEventCreatedAtsByTypeSinceParams) ([]time.Time, error)
|
||||
ListUserChatCompactionThresholds(ctx context.Context, userID uuid.UUID) ([]UserConfig, error)
|
||||
ListUserChatPersonalModelOverrides(ctx context.Context, userID uuid.UUID) ([]ListUserChatPersonalModelOverridesRow, error)
|
||||
// Returns metadata only (no value or value_key_id) for the
|
||||
// REST API list and get endpoints.
|
||||
ListUserSecrets(ctx context.Context, userID uuid.UUID) ([]ListUserSecretsRow, error)
|
||||
@@ -1649,7 +1653,6 @@ type sqlcQuerier interface {
|
||||
// to JSON before invoking this query.
|
||||
UpsertChatAdvisorConfig(ctx context.Context, value string) error
|
||||
UpsertChatAutoArchiveDays(ctx context.Context, autoArchiveDays int32) error
|
||||
UpsertChatCompactionModelOverride(ctx context.Context, value string) error
|
||||
UpsertChatComputerUseProvider(ctx context.Context, provider string) error
|
||||
// UpsertChatDebugLoggingAllowUsers updates the runtime admin setting that
|
||||
// allows users to opt into chat debug logging.
|
||||
@@ -1658,19 +1661,18 @@ type sqlcQuerier interface {
|
||||
UpsertChatDesktopEnabled(ctx context.Context, enableDesktop bool) error
|
||||
UpsertChatDiffStatus(ctx context.Context, arg UpsertChatDiffStatusParams) (ChatDiffStatus, error)
|
||||
UpsertChatDiffStatusReference(ctx context.Context, arg UpsertChatDiffStatusReferenceParams) (ChatDiffStatus, error)
|
||||
UpsertChatExploreModelOverride(ctx context.Context, value string) error
|
||||
UpsertChatGeneralModelOverride(ctx context.Context, value string) error
|
||||
// Upserts a heartbeat row for the (chat_id, runner_id) lease. Uses
|
||||
// database time so callers do not depend on a local clock.
|
||||
UpsertChatHeartbeat(ctx context.Context, arg UpsertChatHeartbeatParams) error
|
||||
UpsertChatIncludeDefaultSystemPrompt(ctx context.Context, includeDefaultSystemPrompt bool) error
|
||||
UpsertChatOrganizationModelOverride(ctx context.Context, arg UpsertChatOrganizationModelOverrideParams) error
|
||||
// UpsertChatPersonalModelOverridesEnabled updates whether users may configure
|
||||
// personal chat model overrides.
|
||||
UpsertChatPersonalModelOverridesEnabled(ctx context.Context, enabled bool) error
|
||||
UpsertChatPlanModeInstructions(ctx context.Context, value string) error
|
||||
UpsertChatRetentionDays(ctx context.Context, retentionDays int32) error
|
||||
UpsertChatSystemPrompt(ctx context.Context, value string) error
|
||||
UpsertChatTitleGenerationModelOverride(ctx context.Context, value string) error
|
||||
UpsertChatUserModelOverride(ctx context.Context, arg UpsertChatUserModelOverrideParams) error
|
||||
UpsertChatWorkspaceTTL(ctx context.Context, workspaceTtl string) error
|
||||
// The default proxy is implied and not actually stored in the database.
|
||||
// So we need to store it's configuration here for display purposes.
|
||||
@@ -1706,7 +1708,6 @@ type sqlcQuerier interface {
|
||||
// created_at for the insert path only.
|
||||
UpsertUserAIProviderKey(ctx context.Context, arg UpsertUserAIProviderKeyParams) (UserAIProviderKey, error)
|
||||
UpsertUserChatDebugLoggingEnabled(ctx context.Context, arg UpsertUserChatDebugLoggingEnabledParams) error
|
||||
UpsertUserChatPersonalModelOverride(ctx context.Context, arg UpsertUserChatPersonalModelOverrideParams) error
|
||||
UpsertWebpushVAPIDKeys(ctx context.Context, arg UpsertWebpushVAPIDKeysParams) error
|
||||
UpsertWorkspaceAgentContextResource(ctx context.Context, arg UpsertWorkspaceAgentContextResourceParams) (WorkspaceAgentContextResource, error)
|
||||
UpsertWorkspaceAgentContextSnapshot(ctx context.Context, arg UpsertWorkspaceAgentContextSnapshotParams) (WorkspaceAgentContextSnapshot, error)
|
||||
|
||||
@@ -6491,6 +6491,85 @@ func TestGetUserStatusCounts(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetChatOrganizationModelOverridesByContext(t *testing.T) {
|
||||
t.Parallel()
|
||||
db, _ := dbtestutil.NewDB(t)
|
||||
ctx := testutil.Context(t, testutil.WaitShort)
|
||||
|
||||
availableOrg := dbgen.Organization(t, db, database.Organization{})
|
||||
availableModel := dbgen.ChatModelConfig(t, db, database.ChatModelConfig{
|
||||
Model: "bulk-available-" + uuid.NewString(),
|
||||
Enabled: true,
|
||||
OrganizationID: availableOrg.ID,
|
||||
})
|
||||
require.NoError(t, db.UpsertChatOrganizationModelOverride(ctx, database.UpsertChatOrganizationModelOverrideParams{
|
||||
OrganizationID: availableOrg.ID,
|
||||
Context: "general",
|
||||
ModelConfigID: availableModel.ID,
|
||||
}))
|
||||
|
||||
// An override referencing a disabled model reports the model unavailable.
|
||||
// dbgen coerces Enabled=false to true, so disable it after insertion.
|
||||
disabledOrg := dbgen.Organization(t, db, database.Organization{})
|
||||
disabledModel := dbgen.ChatModelConfig(t, db, database.ChatModelConfig{
|
||||
Model: "bulk-disabled-" + uuid.NewString(),
|
||||
OrganizationID: disabledOrg.ID,
|
||||
})
|
||||
_, err := db.UpdateChatModelConfig(ctx, database.UpdateChatModelConfigParams{
|
||||
ID: disabledModel.ID,
|
||||
Model: disabledModel.Model,
|
||||
DisplayName: disabledModel.DisplayName,
|
||||
Enabled: false,
|
||||
IsDefault: disabledModel.IsDefault,
|
||||
ContextLimit: disabledModel.ContextLimit,
|
||||
CompressionThreshold: disabledModel.CompressionThreshold,
|
||||
Options: disabledModel.Options,
|
||||
AIProviderID: disabledModel.AIProviderID,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, db.UpsertChatOrganizationModelOverride(ctx, database.UpsertChatOrganizationModelOverrideParams{
|
||||
OrganizationID: disabledOrg.ID,
|
||||
Context: "general",
|
||||
ModelConfigID: disabledModel.ID,
|
||||
}))
|
||||
|
||||
// Deleted organizations are excluded from the bulk read.
|
||||
deletedOrg := dbgen.Organization(t, db, database.Organization{})
|
||||
deletedOrgModel := dbgen.ChatModelConfig(t, db, database.ChatModelConfig{
|
||||
Model: "bulk-deleted-org-" + uuid.NewString(),
|
||||
Enabled: true,
|
||||
OrganizationID: deletedOrg.ID,
|
||||
})
|
||||
require.NoError(t, db.UpsertChatOrganizationModelOverride(ctx, database.UpsertChatOrganizationModelOverrideParams{
|
||||
OrganizationID: deletedOrg.ID,
|
||||
Context: "general",
|
||||
ModelConfigID: deletedOrgModel.ID,
|
||||
}))
|
||||
require.NoError(t, db.UpdateOrganizationDeletedByID(ctx, database.UpdateOrganizationDeletedByIDParams{
|
||||
ID: deletedOrg.ID,
|
||||
UpdatedAt: dbtime.Now(),
|
||||
}))
|
||||
|
||||
rows, err := db.GetChatOrganizationModelOverridesByContext(ctx, "general")
|
||||
require.NoError(t, err)
|
||||
require.Len(t, rows, 2)
|
||||
byOrg := make(map[uuid.UUID]database.GetChatOrganizationModelOverridesByContextRow, len(rows))
|
||||
for _, row := range rows {
|
||||
byOrg[row.OrganizationID] = row
|
||||
}
|
||||
available := byOrg[availableOrg.ID]
|
||||
require.True(t, available.ModelAvailable)
|
||||
require.Equal(t, availableModel.Model, available.Model)
|
||||
require.NotEmpty(t, available.ProviderType)
|
||||
unavailable := byOrg[disabledOrg.ID]
|
||||
require.False(t, unavailable.ModelAvailable)
|
||||
require.Empty(t, unavailable.Model)
|
||||
|
||||
otherContext, err := db.GetChatOrganizationModelOverridesByContext(ctx, "advisor")
|
||||
require.NoError(t, err)
|
||||
require.Empty(t, otherContext)
|
||||
}
|
||||
|
||||
func TestOrganizationDeleteTrigger(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
||||
Generated
+268
-159
@@ -6692,6 +6692,274 @@ func (q *sqlQuerier) UpdateChatModelConfigACLByID(ctx context.Context, arg Updat
|
||||
return i, err
|
||||
}
|
||||
|
||||
const deleteChatOrganizationModelOverride = `-- name: DeleteChatOrganizationModelOverride :exec
|
||||
DELETE FROM chat_organization_model_overrides
|
||||
WHERE organization_id = $1
|
||||
AND context = $2
|
||||
`
|
||||
|
||||
type DeleteChatOrganizationModelOverrideParams struct {
|
||||
OrganizationID uuid.UUID `db:"organization_id" json:"organization_id"`
|
||||
Context string `db:"context" json:"context"`
|
||||
}
|
||||
|
||||
func (q *sqlQuerier) DeleteChatOrganizationModelOverride(ctx context.Context, arg DeleteChatOrganizationModelOverrideParams) error {
|
||||
_, err := q.db.ExecContext(ctx, deleteChatOrganizationModelOverride, arg.OrganizationID, arg.Context)
|
||||
return err
|
||||
}
|
||||
|
||||
const getChatOrganizationModelOverride = `-- name: GetChatOrganizationModelOverride :one
|
||||
SELECT id, organization_id, context, model_config_id, reasoning_effort
|
||||
FROM chat_organization_model_overrides
|
||||
WHERE organization_id = $1
|
||||
AND context = $2
|
||||
`
|
||||
|
||||
type GetChatOrganizationModelOverrideParams struct {
|
||||
OrganizationID uuid.UUID `db:"organization_id" json:"organization_id"`
|
||||
Context string `db:"context" json:"context"`
|
||||
}
|
||||
|
||||
func (q *sqlQuerier) GetChatOrganizationModelOverride(ctx context.Context, arg GetChatOrganizationModelOverrideParams) (ChatOrganizationModelOverride, error) {
|
||||
row := q.db.QueryRowContext(ctx, getChatOrganizationModelOverride, arg.OrganizationID, arg.Context)
|
||||
var i ChatOrganizationModelOverride
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.OrganizationID,
|
||||
&i.Context,
|
||||
&i.ModelConfigID,
|
||||
&i.ReasoningEffort,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getChatOrganizationModelOverrides = `-- name: GetChatOrganizationModelOverrides :many
|
||||
SELECT id, organization_id, context, model_config_id, reasoning_effort
|
||||
FROM chat_organization_model_overrides
|
||||
WHERE organization_id = $1
|
||||
ORDER BY context
|
||||
`
|
||||
|
||||
func (q *sqlQuerier) GetChatOrganizationModelOverrides(ctx context.Context, organizationID uuid.UUID) ([]ChatOrganizationModelOverride, error) {
|
||||
rows, err := q.db.QueryContext(ctx, getChatOrganizationModelOverrides, organizationID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []ChatOrganizationModelOverride
|
||||
for rows.Next() {
|
||||
var i ChatOrganizationModelOverride
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.OrganizationID,
|
||||
&i.Context,
|
||||
&i.ModelConfigID,
|
||||
&i.ReasoningEffort,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const getChatOrganizationModelOverridesByContext = `-- name: GetChatOrganizationModelOverridesByContext :many
|
||||
SELECT
|
||||
o.organization_id,
|
||||
(cmc.id IS NOT NULL AND ap.id IS NOT NULL)::boolean AS model_available,
|
||||
COALESCE(cmc.model, '')::text AS model,
|
||||
COALESCE(ap.type::text, '')::text AS provider_type
|
||||
FROM chat_organization_model_overrides o
|
||||
JOIN organizations org ON org.id = o.organization_id AND NOT org.deleted
|
||||
LEFT JOIN chat_model_configs cmc
|
||||
ON cmc.id = o.model_config_id
|
||||
AND cmc.deleted = FALSE
|
||||
AND cmc.enabled = TRUE
|
||||
LEFT JOIN ai_providers ap
|
||||
ON ap.id = cmc.ai_provider_id
|
||||
AND ap.enabled = TRUE
|
||||
AND ap.deleted = FALSE
|
||||
WHERE o.context = $1
|
||||
ORDER BY o.organization_id
|
||||
`
|
||||
|
||||
type GetChatOrganizationModelOverridesByContextRow struct {
|
||||
OrganizationID uuid.UUID `db:"organization_id" json:"organization_id"`
|
||||
ModelAvailable bool `db:"model_available" json:"model_available"`
|
||||
Model string `db:"model" json:"model"`
|
||||
ProviderType string `db:"provider_type" json:"provider_type"`
|
||||
}
|
||||
|
||||
// Returns every non-deleted organization's override for one context together
|
||||
// with the resolved model and provider, for bulk consumers such as telemetry.
|
||||
// model_available mirrors GetEnabledChatModelConfigByID: it is false when the
|
||||
// referenced config or its provider is disabled or deleted.
|
||||
func (q *sqlQuerier) GetChatOrganizationModelOverridesByContext(ctx context.Context, argContext string) ([]GetChatOrganizationModelOverridesByContextRow, error) {
|
||||
rows, err := q.db.QueryContext(ctx, getChatOrganizationModelOverridesByContext, argContext)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []GetChatOrganizationModelOverridesByContextRow
|
||||
for rows.Next() {
|
||||
var i GetChatOrganizationModelOverridesByContextRow
|
||||
if err := rows.Scan(
|
||||
&i.OrganizationID,
|
||||
&i.ModelAvailable,
|
||||
&i.Model,
|
||||
&i.ProviderType,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const getChatUserModelOverride = `-- name: GetChatUserModelOverride :one
|
||||
SELECT id, user_id, organization_id, context, mode, model_config_id, reasoning_effort
|
||||
FROM chat_user_model_overrides
|
||||
WHERE user_id = $1
|
||||
AND organization_id = $2
|
||||
AND context = $3
|
||||
`
|
||||
|
||||
type GetChatUserModelOverrideParams struct {
|
||||
UserID uuid.UUID `db:"user_id" json:"user_id"`
|
||||
OrganizationID uuid.UUID `db:"organization_id" json:"organization_id"`
|
||||
Context string `db:"context" json:"context"`
|
||||
}
|
||||
|
||||
func (q *sqlQuerier) GetChatUserModelOverride(ctx context.Context, arg GetChatUserModelOverrideParams) (ChatUserModelOverride, error) {
|
||||
row := q.db.QueryRowContext(ctx, getChatUserModelOverride, arg.UserID, arg.OrganizationID, arg.Context)
|
||||
var i ChatUserModelOverride
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.UserID,
|
||||
&i.OrganizationID,
|
||||
&i.Context,
|
||||
&i.Mode,
|
||||
&i.ModelConfigID,
|
||||
&i.ReasoningEffort,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getChatUserModelOverrides = `-- name: GetChatUserModelOverrides :many
|
||||
SELECT id, user_id, organization_id, context, mode, model_config_id, reasoning_effort
|
||||
FROM chat_user_model_overrides
|
||||
WHERE user_id = $1
|
||||
AND organization_id = $2
|
||||
ORDER BY context
|
||||
`
|
||||
|
||||
type GetChatUserModelOverridesParams struct {
|
||||
UserID uuid.UUID `db:"user_id" json:"user_id"`
|
||||
OrganizationID uuid.UUID `db:"organization_id" json:"organization_id"`
|
||||
}
|
||||
|
||||
func (q *sqlQuerier) GetChatUserModelOverrides(ctx context.Context, arg GetChatUserModelOverridesParams) ([]ChatUserModelOverride, error) {
|
||||
rows, err := q.db.QueryContext(ctx, getChatUserModelOverrides, arg.UserID, arg.OrganizationID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []ChatUserModelOverride
|
||||
for rows.Next() {
|
||||
var i ChatUserModelOverride
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.UserID,
|
||||
&i.OrganizationID,
|
||||
&i.Context,
|
||||
&i.Mode,
|
||||
&i.ModelConfigID,
|
||||
&i.ReasoningEffort,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const upsertChatOrganizationModelOverride = `-- name: UpsertChatOrganizationModelOverride :exec
|
||||
INSERT INTO chat_organization_model_overrides
|
||||
(organization_id, context, model_config_id, reasoning_effort)
|
||||
VALUES ($1, $2, $3, $4)
|
||||
ON CONFLICT ON CONSTRAINT chat_organization_model_overrides_organization_id_context_key
|
||||
DO UPDATE SET
|
||||
model_config_id = EXCLUDED.model_config_id,
|
||||
reasoning_effort = EXCLUDED.reasoning_effort
|
||||
`
|
||||
|
||||
type UpsertChatOrganizationModelOverrideParams struct {
|
||||
OrganizationID uuid.UUID `db:"organization_id" json:"organization_id"`
|
||||
Context string `db:"context" json:"context"`
|
||||
ModelConfigID uuid.UUID `db:"model_config_id" json:"model_config_id"`
|
||||
ReasoningEffort sql.NullString `db:"reasoning_effort" json:"reasoning_effort"`
|
||||
}
|
||||
|
||||
func (q *sqlQuerier) UpsertChatOrganizationModelOverride(ctx context.Context, arg UpsertChatOrganizationModelOverrideParams) error {
|
||||
_, err := q.db.ExecContext(ctx, upsertChatOrganizationModelOverride,
|
||||
arg.OrganizationID,
|
||||
arg.Context,
|
||||
arg.ModelConfigID,
|
||||
arg.ReasoningEffort,
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
const upsertChatUserModelOverride = `-- name: UpsertChatUserModelOverride :exec
|
||||
INSERT INTO chat_user_model_overrides
|
||||
(user_id, organization_id, context, mode, model_config_id, reasoning_effort)
|
||||
VALUES ($1, $2, $3, $4, $5, $6)
|
||||
ON CONFLICT ON CONSTRAINT chat_user_model_overrides_user_organization_context_key
|
||||
DO UPDATE SET
|
||||
mode = EXCLUDED.mode,
|
||||
model_config_id = EXCLUDED.model_config_id,
|
||||
reasoning_effort = EXCLUDED.reasoning_effort
|
||||
`
|
||||
|
||||
type UpsertChatUserModelOverrideParams struct {
|
||||
UserID uuid.UUID `db:"user_id" json:"user_id"`
|
||||
OrganizationID uuid.UUID `db:"organization_id" json:"organization_id"`
|
||||
Context string `db:"context" json:"context"`
|
||||
Mode string `db:"mode" json:"mode"`
|
||||
ModelConfigID uuid.NullUUID `db:"model_config_id" json:"model_config_id"`
|
||||
ReasoningEffort sql.NullString `db:"reasoning_effort" json:"reasoning_effort"`
|
||||
}
|
||||
|
||||
func (q *sqlQuerier) UpsertChatUserModelOverride(ctx context.Context, arg UpsertChatUserModelOverrideParams) error {
|
||||
_, err := q.db.ExecContext(ctx, upsertChatUserModelOverride,
|
||||
arg.UserID,
|
||||
arg.OrganizationID,
|
||||
arg.Context,
|
||||
arg.Mode,
|
||||
arg.ModelConfigID,
|
||||
arg.ReasoningEffort,
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
const acquireStaleChatDiffStatuses = `-- name: AcquireStaleChatDiffStatuses :many
|
||||
WITH acquired AS (
|
||||
UPDATE
|
||||
@@ -25286,18 +25554,6 @@ func (q *sqlQuerier) GetChatAutoArchiveDays(ctx context.Context, defaultAutoArch
|
||||
return auto_archive_days, err
|
||||
}
|
||||
|
||||
const getChatCompactionModelOverride = `-- name: GetChatCompactionModelOverride :one
|
||||
SELECT
|
||||
COALESCE((SELECT value FROM site_configs WHERE key = 'agents_chat_compaction_model_override'), '') :: text AS model_config_id
|
||||
`
|
||||
|
||||
func (q *sqlQuerier) GetChatCompactionModelOverride(ctx context.Context) (string, error) {
|
||||
row := q.db.QueryRowContext(ctx, getChatCompactionModelOverride)
|
||||
var model_config_id string
|
||||
err := row.Scan(&model_config_id)
|
||||
return model_config_id, err
|
||||
}
|
||||
|
||||
const getChatComputerUseProvider = `-- name: GetChatComputerUseProvider :one
|
||||
SELECT
|
||||
COALESCE((SELECT value FROM site_configs WHERE key = 'agents_computer_use_provider'), '') :: text AS provider
|
||||
@@ -25353,30 +25609,6 @@ func (q *sqlQuerier) GetChatDesktopEnabled(ctx context.Context) (bool, error) {
|
||||
return enable_desktop, err
|
||||
}
|
||||
|
||||
const getChatExploreModelOverride = `-- name: GetChatExploreModelOverride :one
|
||||
SELECT
|
||||
COALESCE((SELECT value FROM site_configs WHERE key = 'agents_chat_explore_model_override'), '') :: text AS model_config_id
|
||||
`
|
||||
|
||||
func (q *sqlQuerier) GetChatExploreModelOverride(ctx context.Context) (string, error) {
|
||||
row := q.db.QueryRowContext(ctx, getChatExploreModelOverride)
|
||||
var model_config_id string
|
||||
err := row.Scan(&model_config_id)
|
||||
return model_config_id, err
|
||||
}
|
||||
|
||||
const getChatGeneralModelOverride = `-- name: GetChatGeneralModelOverride :one
|
||||
SELECT
|
||||
COALESCE((SELECT value FROM site_configs WHERE key = 'agents_chat_general_model_override'), '') :: text AS model_config_id
|
||||
`
|
||||
|
||||
func (q *sqlQuerier) GetChatGeneralModelOverride(ctx context.Context) (string, error) {
|
||||
row := q.db.QueryRowContext(ctx, getChatGeneralModelOverride)
|
||||
var model_config_id string
|
||||
err := row.Scan(&model_config_id)
|
||||
return model_config_id, err
|
||||
}
|
||||
|
||||
const getChatIncludeDefaultSystemPrompt = `-- name: GetChatIncludeDefaultSystemPrompt :one
|
||||
SELECT
|
||||
COALESCE(
|
||||
@@ -25495,18 +25727,6 @@ func (q *sqlQuerier) GetChatSystemPromptConfig(ctx context.Context) (GetChatSyst
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getChatTitleGenerationModelOverride = `-- name: GetChatTitleGenerationModelOverride :one
|
||||
SELECT
|
||||
COALESCE((SELECT value FROM site_configs WHERE key = 'agents_chat_title_generation_model_override'), '') :: text AS model_config_id
|
||||
`
|
||||
|
||||
func (q *sqlQuerier) GetChatTitleGenerationModelOverride(ctx context.Context) (string, error) {
|
||||
row := q.db.QueryRowContext(ctx, getChatTitleGenerationModelOverride)
|
||||
var model_config_id string
|
||||
err := row.Scan(&model_config_id)
|
||||
return model_config_id, err
|
||||
}
|
||||
|
||||
const getChatWorkspaceTTL = `-- name: GetChatWorkspaceTTL :one
|
||||
SELECT
|
||||
COALESCE(
|
||||
@@ -25745,16 +25965,6 @@ func (q *sqlQuerier) UpsertChatAutoArchiveDays(ctx context.Context, autoArchiveD
|
||||
return err
|
||||
}
|
||||
|
||||
const upsertChatCompactionModelOverride = `-- name: UpsertChatCompactionModelOverride :exec
|
||||
INSERT INTO site_configs (key, value) VALUES ('agents_chat_compaction_model_override', $1)
|
||||
ON CONFLICT (key) DO UPDATE SET value = $1 WHERE site_configs.key = 'agents_chat_compaction_model_override'
|
||||
`
|
||||
|
||||
func (q *sqlQuerier) UpsertChatCompactionModelOverride(ctx context.Context, value string) error {
|
||||
_, err := q.db.ExecContext(ctx, upsertChatCompactionModelOverride, value)
|
||||
return err
|
||||
}
|
||||
|
||||
const upsertChatComputerUseProvider = `-- name: UpsertChatComputerUseProvider :exec
|
||||
INSERT INTO site_configs (key, value) VALUES ('agents_computer_use_provider', $1)
|
||||
ON CONFLICT (key) DO UPDATE SET value = $1 WHERE site_configs.key = 'agents_computer_use_provider'
|
||||
@@ -25823,26 +26033,6 @@ func (q *sqlQuerier) UpsertChatDesktopEnabled(ctx context.Context, enableDesktop
|
||||
return err
|
||||
}
|
||||
|
||||
const upsertChatExploreModelOverride = `-- name: UpsertChatExploreModelOverride :exec
|
||||
INSERT INTO site_configs (key, value) VALUES ('agents_chat_explore_model_override', $1)
|
||||
ON CONFLICT (key) DO UPDATE SET value = $1 WHERE site_configs.key = 'agents_chat_explore_model_override'
|
||||
`
|
||||
|
||||
func (q *sqlQuerier) UpsertChatExploreModelOverride(ctx context.Context, value string) error {
|
||||
_, err := q.db.ExecContext(ctx, upsertChatExploreModelOverride, value)
|
||||
return err
|
||||
}
|
||||
|
||||
const upsertChatGeneralModelOverride = `-- name: UpsertChatGeneralModelOverride :exec
|
||||
INSERT INTO site_configs (key, value) VALUES ('agents_chat_general_model_override', $1)
|
||||
ON CONFLICT (key) DO UPDATE SET value = $1 WHERE site_configs.key = 'agents_chat_general_model_override'
|
||||
`
|
||||
|
||||
func (q *sqlQuerier) UpsertChatGeneralModelOverride(ctx context.Context, value string) error {
|
||||
_, err := q.db.ExecContext(ctx, upsertChatGeneralModelOverride, value)
|
||||
return err
|
||||
}
|
||||
|
||||
const upsertChatIncludeDefaultSystemPrompt = `-- name: UpsertChatIncludeDefaultSystemPrompt :exec
|
||||
INSERT INTO site_configs (key, value)
|
||||
VALUES (
|
||||
@@ -25921,16 +26111,6 @@ func (q *sqlQuerier) UpsertChatSystemPrompt(ctx context.Context, value string) e
|
||||
return err
|
||||
}
|
||||
|
||||
const upsertChatTitleGenerationModelOverride = `-- name: UpsertChatTitleGenerationModelOverride :exec
|
||||
INSERT INTO site_configs (key, value) VALUES ('agents_chat_title_generation_model_override', $1)
|
||||
ON CONFLICT (key) DO UPDATE SET value = $1 WHERE site_configs.key = 'agents_chat_title_generation_model_override'
|
||||
`
|
||||
|
||||
func (q *sqlQuerier) UpsertChatTitleGenerationModelOverride(ctx context.Context, value string) error {
|
||||
_, err := q.db.ExecContext(ctx, upsertChatTitleGenerationModelOverride, value)
|
||||
return err
|
||||
}
|
||||
|
||||
const upsertChatWorkspaceTTL = `-- name: UpsertChatWorkspaceTTL :exec
|
||||
INSERT INTO site_configs (key, value)
|
||||
VALUES ('agents_workspace_ttl', $1::text)
|
||||
@@ -31066,24 +31246,6 @@ func (q *sqlQuerier) GetUserChatDebugLoggingEnabled(ctx context.Context, userID
|
||||
return debug_logging_enabled, err
|
||||
}
|
||||
|
||||
const getUserChatPersonalModelOverride = `-- name: GetUserChatPersonalModelOverride :one
|
||||
SELECT value AS personal_model_override FROM user_configs
|
||||
WHERE user_id = $1
|
||||
AND key = $2
|
||||
`
|
||||
|
||||
type GetUserChatPersonalModelOverrideParams struct {
|
||||
UserID uuid.UUID `db:"user_id" json:"user_id"`
|
||||
Key string `db:"key" json:"key"`
|
||||
}
|
||||
|
||||
func (q *sqlQuerier) GetUserChatPersonalModelOverride(ctx context.Context, arg GetUserChatPersonalModelOverrideParams) (string, error) {
|
||||
row := q.db.QueryRowContext(ctx, getUserChatPersonalModelOverride, arg.UserID, arg.Key)
|
||||
var personal_model_override string
|
||||
err := row.Scan(&personal_model_override)
|
||||
return personal_model_override, err
|
||||
}
|
||||
|
||||
const getUserCodeDiffDisplayMode = `-- name: GetUserCodeDiffDisplayMode :one
|
||||
SELECT
|
||||
value AS code_diff_display_mode
|
||||
@@ -31597,41 +31759,6 @@ func (q *sqlQuerier) ListUserChatCompactionThresholds(ctx context.Context, userI
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const listUserChatPersonalModelOverrides = `-- name: ListUserChatPersonalModelOverrides :many
|
||||
SELECT key, value FROM user_configs
|
||||
WHERE user_id = $1
|
||||
AND key LIKE 'chat\_personal\_model\_override:%'
|
||||
ORDER BY key
|
||||
`
|
||||
|
||||
type ListUserChatPersonalModelOverridesRow struct {
|
||||
Key string `db:"key" json:"key"`
|
||||
Value string `db:"value" json:"value"`
|
||||
}
|
||||
|
||||
func (q *sqlQuerier) ListUserChatPersonalModelOverrides(ctx context.Context, userID uuid.UUID) ([]ListUserChatPersonalModelOverridesRow, error) {
|
||||
rows, err := q.db.QueryContext(ctx, listUserChatPersonalModelOverrides, userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []ListUserChatPersonalModelOverridesRow
|
||||
for rows.Next() {
|
||||
var i ListUserChatPersonalModelOverridesRow
|
||||
if err := rows.Scan(&i.Key, &i.Value); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const updateInactiveUsersToDormant = `-- name: UpdateInactiveUsersToDormant :many
|
||||
UPDATE
|
||||
users
|
||||
@@ -32399,24 +32526,6 @@ func (q *sqlQuerier) UpsertUserChatDebugLoggingEnabled(ctx context.Context, arg
|
||||
return err
|
||||
}
|
||||
|
||||
const upsertUserChatPersonalModelOverride = `-- name: UpsertUserChatPersonalModelOverride :exec
|
||||
INSERT INTO user_configs (user_id, key, value)
|
||||
VALUES ($1::uuid, $2::text, $3::text)
|
||||
ON CONFLICT ON CONSTRAINT user_configs_pkey
|
||||
DO UPDATE SET value = $3::text
|
||||
`
|
||||
|
||||
type UpsertUserChatPersonalModelOverrideParams struct {
|
||||
UserID uuid.UUID `db:"user_id" json:"user_id"`
|
||||
Key string `db:"key" json:"key"`
|
||||
Value string `db:"value" json:"value"`
|
||||
}
|
||||
|
||||
func (q *sqlQuerier) UpsertUserChatPersonalModelOverride(ctx context.Context, arg UpsertUserChatPersonalModelOverrideParams) error {
|
||||
_, err := q.db.ExecContext(ctx, upsertUserChatPersonalModelOverride, arg.UserID, arg.Key, arg.Value)
|
||||
return err
|
||||
}
|
||||
|
||||
const validateUserIDs = `-- name: ValidateUserIDs :one
|
||||
WITH input AS (
|
||||
SELECT
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
-- name: GetChatOrganizationModelOverrides :many
|
||||
SELECT id, organization_id, context, model_config_id, reasoning_effort
|
||||
FROM chat_organization_model_overrides
|
||||
WHERE organization_id = @organization_id
|
||||
ORDER BY context;
|
||||
|
||||
-- name: GetChatOrganizationModelOverride :one
|
||||
SELECT id, organization_id, context, model_config_id, reasoning_effort
|
||||
FROM chat_organization_model_overrides
|
||||
WHERE organization_id = @organization_id
|
||||
AND context = @context;
|
||||
|
||||
-- name: GetChatOrganizationModelOverridesByContext :many
|
||||
-- Returns every non-deleted organization's override for one context together
|
||||
-- with the resolved model and provider, for bulk consumers such as telemetry.
|
||||
-- model_available mirrors GetEnabledChatModelConfigByID: it is false when the
|
||||
-- referenced config or its provider is disabled or deleted.
|
||||
SELECT
|
||||
o.organization_id,
|
||||
(cmc.id IS NOT NULL AND ap.id IS NOT NULL)::boolean AS model_available,
|
||||
COALESCE(cmc.model, '')::text AS model,
|
||||
COALESCE(ap.type::text, '')::text AS provider_type
|
||||
FROM chat_organization_model_overrides o
|
||||
JOIN organizations org ON org.id = o.organization_id AND NOT org.deleted
|
||||
LEFT JOIN chat_model_configs cmc
|
||||
ON cmc.id = o.model_config_id
|
||||
AND cmc.deleted = FALSE
|
||||
AND cmc.enabled = TRUE
|
||||
LEFT JOIN ai_providers ap
|
||||
ON ap.id = cmc.ai_provider_id
|
||||
AND ap.enabled = TRUE
|
||||
AND ap.deleted = FALSE
|
||||
WHERE o.context = @context
|
||||
ORDER BY o.organization_id;
|
||||
|
||||
-- name: UpsertChatOrganizationModelOverride :exec
|
||||
INSERT INTO chat_organization_model_overrides
|
||||
(organization_id, context, model_config_id, reasoning_effort)
|
||||
VALUES (@organization_id, @context, @model_config_id, @reasoning_effort)
|
||||
ON CONFLICT ON CONSTRAINT chat_organization_model_overrides_organization_id_context_key
|
||||
DO UPDATE SET
|
||||
model_config_id = EXCLUDED.model_config_id,
|
||||
reasoning_effort = EXCLUDED.reasoning_effort;
|
||||
|
||||
-- name: DeleteChatOrganizationModelOverride :exec
|
||||
DELETE FROM chat_organization_model_overrides
|
||||
WHERE organization_id = @organization_id
|
||||
AND context = @context;
|
||||
|
||||
-- name: GetChatUserModelOverrides :many
|
||||
SELECT id, user_id, organization_id, context, mode, model_config_id, reasoning_effort
|
||||
FROM chat_user_model_overrides
|
||||
WHERE user_id = @user_id
|
||||
AND organization_id = @organization_id
|
||||
ORDER BY context;
|
||||
|
||||
-- name: GetChatUserModelOverride :one
|
||||
SELECT id, user_id, organization_id, context, mode, model_config_id, reasoning_effort
|
||||
FROM chat_user_model_overrides
|
||||
WHERE user_id = @user_id
|
||||
AND organization_id = @organization_id
|
||||
AND context = @context;
|
||||
|
||||
-- name: UpsertChatUserModelOverride :exec
|
||||
INSERT INTO chat_user_model_overrides
|
||||
(user_id, organization_id, context, mode, model_config_id, reasoning_effort)
|
||||
VALUES (@user_id, @organization_id, @context, @mode, @model_config_id, @reasoning_effort)
|
||||
ON CONFLICT ON CONSTRAINT chat_user_model_overrides_user_organization_context_key
|
||||
DO UPDATE SET
|
||||
mode = EXCLUDED.mode,
|
||||
model_config_id = EXCLUDED.model_config_id,
|
||||
reasoning_effort = EXCLUDED.reasoning_effort;
|
||||
@@ -194,38 +194,6 @@ SELECT
|
||||
INSERT INTO site_configs (key, value) VALUES ('agents_chat_plan_mode_instructions', $1)
|
||||
ON CONFLICT (key) DO UPDATE SET value = $1 WHERE site_configs.key = 'agents_chat_plan_mode_instructions';
|
||||
|
||||
-- name: GetChatExploreModelOverride :one
|
||||
SELECT
|
||||
COALESCE((SELECT value FROM site_configs WHERE key = 'agents_chat_explore_model_override'), '') :: text AS model_config_id;
|
||||
|
||||
-- name: UpsertChatExploreModelOverride :exec
|
||||
INSERT INTO site_configs (key, value) VALUES ('agents_chat_explore_model_override', $1)
|
||||
ON CONFLICT (key) DO UPDATE SET value = $1 WHERE site_configs.key = 'agents_chat_explore_model_override';
|
||||
|
||||
-- name: GetChatGeneralModelOverride :one
|
||||
SELECT
|
||||
COALESCE((SELECT value FROM site_configs WHERE key = 'agents_chat_general_model_override'), '') :: text AS model_config_id;
|
||||
|
||||
-- name: UpsertChatGeneralModelOverride :exec
|
||||
INSERT INTO site_configs (key, value) VALUES ('agents_chat_general_model_override', $1)
|
||||
ON CONFLICT (key) DO UPDATE SET value = $1 WHERE site_configs.key = 'agents_chat_general_model_override';
|
||||
|
||||
-- name: GetChatTitleGenerationModelOverride :one
|
||||
SELECT
|
||||
COALESCE((SELECT value FROM site_configs WHERE key = 'agents_chat_title_generation_model_override'), '') :: text AS model_config_id;
|
||||
|
||||
-- name: UpsertChatTitleGenerationModelOverride :exec
|
||||
INSERT INTO site_configs (key, value) VALUES ('agents_chat_title_generation_model_override', $1)
|
||||
ON CONFLICT (key) DO UPDATE SET value = $1 WHERE site_configs.key = 'agents_chat_title_generation_model_override';
|
||||
|
||||
-- name: GetChatCompactionModelOverride :one
|
||||
SELECT
|
||||
COALESCE((SELECT value FROM site_configs WHERE key = 'agents_chat_compaction_model_override'), '') :: text AS model_config_id;
|
||||
|
||||
-- name: UpsertChatCompactionModelOverride :exec
|
||||
INSERT INTO site_configs (key, value) VALUES ('agents_chat_compaction_model_override', $1)
|
||||
ON CONFLICT (key) DO UPDATE SET value = $1 WHERE site_configs.key = 'agents_chat_compaction_model_override';
|
||||
|
||||
-- name: GetChatDesktopEnabled :one
|
||||
SELECT
|
||||
COALESCE((SELECT value = 'true' FROM site_configs WHERE key = 'agents_desktop_enabled'), false) :: boolean AS enable_desktop;
|
||||
|
||||
@@ -284,23 +284,6 @@ END
|
||||
WHERE user_configs.user_id = @user_id
|
||||
AND user_configs.key = 'chat_debug_logging_enabled';
|
||||
|
||||
-- name: ListUserChatPersonalModelOverrides :many
|
||||
SELECT key, value FROM user_configs
|
||||
WHERE user_id = @user_id
|
||||
AND key LIKE 'chat\_personal\_model\_override:%'
|
||||
ORDER BY key;
|
||||
|
||||
-- name: GetUserChatPersonalModelOverride :one
|
||||
SELECT value AS personal_model_override FROM user_configs
|
||||
WHERE user_id = @user_id
|
||||
AND key = @key;
|
||||
|
||||
-- name: UpsertUserChatPersonalModelOverride :exec
|
||||
INSERT INTO user_configs (user_id, key, value)
|
||||
VALUES (@user_id::uuid, @key::text, @value::text)
|
||||
ON CONFLICT ON CONSTRAINT user_configs_pkey
|
||||
DO UPDATE SET value = @value::text;
|
||||
|
||||
-- name: GetUserTaskNotificationAlertDismissed :one
|
||||
SELECT
|
||||
value::boolean as task_notification_alert_dismissed
|
||||
|
||||
Generated
+179
-174
@@ -6,178 +6,183 @@ type UniqueConstraint string
|
||||
|
||||
// UniqueConstraint enums.
|
||||
const (
|
||||
UniqueAgentStatsPkey UniqueConstraint = "agent_stats_pkey" // ALTER TABLE ONLY workspace_agent_stats ADD CONSTRAINT agent_stats_pkey PRIMARY KEY (id);
|
||||
UniqueAIGatewayKeysPkey UniqueConstraint = "ai_gateway_keys_pkey" // ALTER TABLE ONLY ai_gateway_keys ADD CONSTRAINT ai_gateway_keys_pkey PRIMARY KEY (id);
|
||||
UniqueAIModelPricesPkey UniqueConstraint = "ai_model_prices_pkey" // ALTER TABLE ONLY ai_model_prices ADD CONSTRAINT ai_model_prices_pkey PRIMARY KEY (provider, model, source);
|
||||
UniqueAIProviderKeysPkey UniqueConstraint = "ai_provider_keys_pkey" // ALTER TABLE ONLY ai_provider_keys ADD CONSTRAINT ai_provider_keys_pkey PRIMARY KEY (id);
|
||||
UniqueAIProvidersPkey UniqueConstraint = "ai_providers_pkey" // ALTER TABLE ONLY ai_providers ADD CONSTRAINT ai_providers_pkey PRIMARY KEY (id);
|
||||
UniqueAISeatStatePkey UniqueConstraint = "ai_seat_state_pkey" // ALTER TABLE ONLY ai_seat_state ADD CONSTRAINT ai_seat_state_pkey PRIMARY KEY (user_id);
|
||||
UniqueAIUserDailySpendPkey UniqueConstraint = "ai_user_daily_spend_pkey" // ALTER TABLE ONLY ai_user_daily_spend ADD CONSTRAINT ai_user_daily_spend_pkey PRIMARY KEY (user_id, effective_group_id, day);
|
||||
UniqueAibridgeInterceptionsPkey UniqueConstraint = "aibridge_interceptions_pkey" // ALTER TABLE ONLY aibridge_interceptions ADD CONSTRAINT aibridge_interceptions_pkey PRIMARY KEY (id);
|
||||
UniqueAibridgeTokenUsagesPkey UniqueConstraint = "aibridge_token_usages_pkey" // ALTER TABLE ONLY aibridge_token_usages ADD CONSTRAINT aibridge_token_usages_pkey PRIMARY KEY (id);
|
||||
UniqueAibridgeToolUsagesPkey UniqueConstraint = "aibridge_tool_usages_pkey" // ALTER TABLE ONLY aibridge_tool_usages ADD CONSTRAINT aibridge_tool_usages_pkey PRIMARY KEY (id);
|
||||
UniqueAibridgeUserPromptsPkey UniqueConstraint = "aibridge_user_prompts_pkey" // ALTER TABLE ONLY aibridge_user_prompts ADD CONSTRAINT aibridge_user_prompts_pkey PRIMARY KEY (id);
|
||||
UniqueAPIKeysPkey UniqueConstraint = "api_keys_pkey" // ALTER TABLE ONLY api_keys ADD CONSTRAINT api_keys_pkey PRIMARY KEY (id);
|
||||
UniqueAuditLogsPkey UniqueConstraint = "audit_logs_pkey" // ALTER TABLE ONLY audit_logs ADD CONSTRAINT audit_logs_pkey PRIMARY KEY (id);
|
||||
UniqueBoundaryLogsPkey UniqueConstraint = "boundary_logs_pkey" // ALTER TABLE ONLY boundary_logs ADD CONSTRAINT boundary_logs_pkey PRIMARY KEY (id);
|
||||
UniqueBoundarySessionsPkey UniqueConstraint = "boundary_sessions_pkey" // ALTER TABLE ONLY boundary_sessions ADD CONSTRAINT boundary_sessions_pkey PRIMARY KEY (id);
|
||||
UniqueBoundaryUsageStatsPkey UniqueConstraint = "boundary_usage_stats_pkey" // ALTER TABLE ONLY boundary_usage_stats ADD CONSTRAINT boundary_usage_stats_pkey PRIMARY KEY (replica_id);
|
||||
UniqueChatContextResourcesPkey UniqueConstraint = "chat_context_resources_pkey" // ALTER TABLE ONLY chat_context_resources ADD CONSTRAINT chat_context_resources_pkey PRIMARY KEY (chat_id, source);
|
||||
UniqueChatDebugRunsPkey UniqueConstraint = "chat_debug_runs_pkey" // ALTER TABLE ONLY chat_debug_runs ADD CONSTRAINT chat_debug_runs_pkey PRIMARY KEY (id);
|
||||
UniqueChatDebugStepsPkey UniqueConstraint = "chat_debug_steps_pkey" // ALTER TABLE ONLY chat_debug_steps ADD CONSTRAINT chat_debug_steps_pkey PRIMARY KEY (id);
|
||||
UniqueChatDiffStatusesPkey UniqueConstraint = "chat_diff_statuses_pkey" // ALTER TABLE ONLY chat_diff_statuses ADD CONSTRAINT chat_diff_statuses_pkey PRIMARY KEY (chat_id);
|
||||
UniqueChatFileLinksChatIDFileIDKey UniqueConstraint = "chat_file_links_chat_id_file_id_key" // ALTER TABLE ONLY chat_file_links ADD CONSTRAINT chat_file_links_chat_id_file_id_key UNIQUE (chat_id, file_id);
|
||||
UniqueChatFilesPkey UniqueConstraint = "chat_files_pkey" // ALTER TABLE ONLY chat_files ADD CONSTRAINT chat_files_pkey PRIMARY KEY (id);
|
||||
UniqueChatHeartbeatsPkey UniqueConstraint = "chat_heartbeats_pkey" // ALTER TABLE ONLY chat_heartbeats ADD CONSTRAINT chat_heartbeats_pkey PRIMARY KEY (chat_id, runner_id);
|
||||
UniqueChatMessagesPkey UniqueConstraint = "chat_messages_pkey" // ALTER TABLE ONLY chat_messages ADD CONSTRAINT chat_messages_pkey PRIMARY KEY (id);
|
||||
UniqueChatModelConfigsPkey UniqueConstraint = "chat_model_configs_pkey" // ALTER TABLE ONLY chat_model_configs ADD CONSTRAINT chat_model_configs_pkey PRIMARY KEY (id);
|
||||
UniqueChatQueuedMessagesPkey UniqueConstraint = "chat_queued_messages_pkey" // ALTER TABLE ONLY chat_queued_messages ADD CONSTRAINT chat_queued_messages_pkey PRIMARY KEY (id);
|
||||
UniqueChatUsageLimitConfigPkey UniqueConstraint = "chat_usage_limit_config_pkey" // ALTER TABLE ONLY chat_usage_limit_config ADD CONSTRAINT chat_usage_limit_config_pkey PRIMARY KEY (id);
|
||||
UniqueChatUsageLimitConfigSingletonKey UniqueConstraint = "chat_usage_limit_config_singleton_key" // ALTER TABLE ONLY chat_usage_limit_config ADD CONSTRAINT chat_usage_limit_config_singleton_key UNIQUE (singleton);
|
||||
UniqueChatsPkey UniqueConstraint = "chats_pkey" // ALTER TABLE ONLY chats ADD CONSTRAINT chats_pkey PRIMARY KEY (id);
|
||||
UniqueConnectionLogsPkey UniqueConstraint = "connection_logs_pkey" // ALTER TABLE ONLY connection_logs ADD CONSTRAINT connection_logs_pkey PRIMARY KEY (id);
|
||||
UniqueCryptoKeysPkey UniqueConstraint = "crypto_keys_pkey" // ALTER TABLE ONLY crypto_keys ADD CONSTRAINT crypto_keys_pkey PRIMARY KEY (feature, sequence);
|
||||
UniqueCustomRolesUniqueKey UniqueConstraint = "custom_roles_unique_key" // ALTER TABLE ONLY custom_roles ADD CONSTRAINT custom_roles_unique_key UNIQUE (name, organization_id);
|
||||
UniqueDbcryptKeysActiveKeyDigestKey UniqueConstraint = "dbcrypt_keys_active_key_digest_key" // ALTER TABLE ONLY dbcrypt_keys ADD CONSTRAINT dbcrypt_keys_active_key_digest_key UNIQUE (active_key_digest);
|
||||
UniqueDbcryptKeysPkey UniqueConstraint = "dbcrypt_keys_pkey" // ALTER TABLE ONLY dbcrypt_keys ADD CONSTRAINT dbcrypt_keys_pkey PRIMARY KEY (number);
|
||||
UniqueDbcryptKeysRevokedKeyDigestKey UniqueConstraint = "dbcrypt_keys_revoked_key_digest_key" // ALTER TABLE ONLY dbcrypt_keys ADD CONSTRAINT dbcrypt_keys_revoked_key_digest_key UNIQUE (revoked_key_digest);
|
||||
UniqueFilesHashCreatedByKey UniqueConstraint = "files_hash_created_by_key" // ALTER TABLE ONLY files ADD CONSTRAINT files_hash_created_by_key UNIQUE (hash, created_by);
|
||||
UniqueFilesPkey UniqueConstraint = "files_pkey" // ALTER TABLE ONLY files ADD CONSTRAINT files_pkey PRIMARY KEY (id);
|
||||
UniqueGitAuthLinksProviderIDUserIDKey UniqueConstraint = "git_auth_links_provider_id_user_id_key" // ALTER TABLE ONLY external_auth_links ADD CONSTRAINT git_auth_links_provider_id_user_id_key UNIQUE (provider_id, user_id);
|
||||
UniqueGitSSHKeysPkey UniqueConstraint = "gitsshkeys_pkey" // ALTER TABLE ONLY gitsshkeys ADD CONSTRAINT gitsshkeys_pkey PRIMARY KEY (user_id);
|
||||
UniqueGroupAIBudgetsPkey UniqueConstraint = "group_ai_budgets_pkey" // ALTER TABLE ONLY group_ai_budgets ADD CONSTRAINT group_ai_budgets_pkey PRIMARY KEY (group_id);
|
||||
UniqueGroupMembersUserIDGroupIDKey UniqueConstraint = "group_members_user_id_group_id_key" // ALTER TABLE ONLY group_members ADD CONSTRAINT group_members_user_id_group_id_key UNIQUE (user_id, group_id);
|
||||
UniqueGroupsNameOrganizationIDKey UniqueConstraint = "groups_name_organization_id_key" // ALTER TABLE ONLY groups ADD CONSTRAINT groups_name_organization_id_key UNIQUE (name, organization_id);
|
||||
UniqueGroupsPkey UniqueConstraint = "groups_pkey" // ALTER TABLE ONLY groups ADD CONSTRAINT groups_pkey PRIMARY KEY (id);
|
||||
UniqueInboxNotificationsPkey UniqueConstraint = "inbox_notifications_pkey" // ALTER TABLE ONLY inbox_notifications ADD CONSTRAINT inbox_notifications_pkey PRIMARY KEY (id);
|
||||
UniqueJfrogXrayScansPkey UniqueConstraint = "jfrog_xray_scans_pkey" // ALTER TABLE ONLY jfrog_xray_scans ADD CONSTRAINT jfrog_xray_scans_pkey PRIMARY KEY (agent_id, workspace_id);
|
||||
UniqueLicensesJWTKey UniqueConstraint = "licenses_jwt_key" // ALTER TABLE ONLY licenses ADD CONSTRAINT licenses_jwt_key UNIQUE (jwt);
|
||||
UniqueLicensesPkey UniqueConstraint = "licenses_pkey" // ALTER TABLE ONLY licenses ADD CONSTRAINT licenses_pkey PRIMARY KEY (id);
|
||||
UniqueMcpServerConfigsOrganizationIDSlugKey UniqueConstraint = "mcp_server_configs_organization_id_slug_key" // ALTER TABLE ONLY mcp_server_configs ADD CONSTRAINT mcp_server_configs_organization_id_slug_key UNIQUE (organization_id, slug);
|
||||
UniqueMcpServerConfigsPkey UniqueConstraint = "mcp_server_configs_pkey" // ALTER TABLE ONLY mcp_server_configs ADD CONSTRAINT mcp_server_configs_pkey PRIMARY KEY (id);
|
||||
UniqueMcpServerUserTokensMcpServerConfigIDUserIDKey UniqueConstraint = "mcp_server_user_tokens_mcp_server_config_id_user_id_key" // ALTER TABLE ONLY mcp_server_user_tokens ADD CONSTRAINT mcp_server_user_tokens_mcp_server_config_id_user_id_key UNIQUE (mcp_server_config_id, user_id);
|
||||
UniqueMcpServerUserTokensPkey UniqueConstraint = "mcp_server_user_tokens_pkey" // ALTER TABLE ONLY mcp_server_user_tokens ADD CONSTRAINT mcp_server_user_tokens_pkey PRIMARY KEY (id);
|
||||
UniqueNotificationMessagesPkey UniqueConstraint = "notification_messages_pkey" // ALTER TABLE ONLY notification_messages ADD CONSTRAINT notification_messages_pkey PRIMARY KEY (id);
|
||||
UniqueNotificationPreferencesPkey UniqueConstraint = "notification_preferences_pkey" // ALTER TABLE ONLY notification_preferences ADD CONSTRAINT notification_preferences_pkey PRIMARY KEY (user_id, notification_template_id);
|
||||
UniqueNotificationReportGeneratorLogsPkey UniqueConstraint = "notification_report_generator_logs_pkey" // ALTER TABLE ONLY notification_report_generator_logs ADD CONSTRAINT notification_report_generator_logs_pkey PRIMARY KEY (notification_template_id);
|
||||
UniqueNotificationTemplatesNameKey UniqueConstraint = "notification_templates_name_key" // ALTER TABLE ONLY notification_templates ADD CONSTRAINT notification_templates_name_key UNIQUE (name);
|
||||
UniqueNotificationTemplatesPkey UniqueConstraint = "notification_templates_pkey" // ALTER TABLE ONLY notification_templates ADD CONSTRAINT notification_templates_pkey PRIMARY KEY (id);
|
||||
UniqueOauth2ProviderAppCodesPkey UniqueConstraint = "oauth2_provider_app_codes_pkey" // ALTER TABLE ONLY oauth2_provider_app_codes ADD CONSTRAINT oauth2_provider_app_codes_pkey PRIMARY KEY (id);
|
||||
UniqueOauth2ProviderAppCodesSecretPrefixKey UniqueConstraint = "oauth2_provider_app_codes_secret_prefix_key" // ALTER TABLE ONLY oauth2_provider_app_codes ADD CONSTRAINT oauth2_provider_app_codes_secret_prefix_key UNIQUE (secret_prefix);
|
||||
UniqueOauth2ProviderAppSecretsPkey UniqueConstraint = "oauth2_provider_app_secrets_pkey" // ALTER TABLE ONLY oauth2_provider_app_secrets ADD CONSTRAINT oauth2_provider_app_secrets_pkey PRIMARY KEY (id);
|
||||
UniqueOauth2ProviderAppSecretsSecretPrefixKey UniqueConstraint = "oauth2_provider_app_secrets_secret_prefix_key" // ALTER TABLE ONLY oauth2_provider_app_secrets ADD CONSTRAINT oauth2_provider_app_secrets_secret_prefix_key UNIQUE (secret_prefix);
|
||||
UniqueOauth2ProviderAppTokensHashPrefixKey UniqueConstraint = "oauth2_provider_app_tokens_hash_prefix_key" // ALTER TABLE ONLY oauth2_provider_app_tokens ADD CONSTRAINT oauth2_provider_app_tokens_hash_prefix_key UNIQUE (hash_prefix);
|
||||
UniqueOauth2ProviderAppTokensPkey UniqueConstraint = "oauth2_provider_app_tokens_pkey" // ALTER TABLE ONLY oauth2_provider_app_tokens ADD CONSTRAINT oauth2_provider_app_tokens_pkey PRIMARY KEY (id);
|
||||
UniqueOauth2ProviderAppsPkey UniqueConstraint = "oauth2_provider_apps_pkey" // ALTER TABLE ONLY oauth2_provider_apps ADD CONSTRAINT oauth2_provider_apps_pkey PRIMARY KEY (id);
|
||||
UniqueOrganizationMembersPkey UniqueConstraint = "organization_members_pkey" // ALTER TABLE ONLY organization_members ADD CONSTRAINT organization_members_pkey PRIMARY KEY (organization_id, user_id);
|
||||
UniqueOrganizationsPkey UniqueConstraint = "organizations_pkey" // ALTER TABLE ONLY organizations ADD CONSTRAINT organizations_pkey PRIMARY KEY (id);
|
||||
UniqueParameterSchemasJobIDNameKey UniqueConstraint = "parameter_schemas_job_id_name_key" // ALTER TABLE ONLY parameter_schemas ADD CONSTRAINT parameter_schemas_job_id_name_key UNIQUE (job_id, name);
|
||||
UniqueParameterSchemasPkey UniqueConstraint = "parameter_schemas_pkey" // ALTER TABLE ONLY parameter_schemas ADD CONSTRAINT parameter_schemas_pkey PRIMARY KEY (id);
|
||||
UniqueParameterValuesPkey UniqueConstraint = "parameter_values_pkey" // ALTER TABLE ONLY parameter_values ADD CONSTRAINT parameter_values_pkey PRIMARY KEY (id);
|
||||
UniqueParameterValuesScopeIDNameKey UniqueConstraint = "parameter_values_scope_id_name_key" // ALTER TABLE ONLY parameter_values ADD CONSTRAINT parameter_values_scope_id_name_key UNIQUE (scope_id, name);
|
||||
UniqueProvisionerDaemonsPkey UniqueConstraint = "provisioner_daemons_pkey" // ALTER TABLE ONLY provisioner_daemons ADD CONSTRAINT provisioner_daemons_pkey PRIMARY KEY (id);
|
||||
UniqueProvisionerJobLogsPkey UniqueConstraint = "provisioner_job_logs_pkey" // ALTER TABLE ONLY provisioner_job_logs ADD CONSTRAINT provisioner_job_logs_pkey PRIMARY KEY (id);
|
||||
UniqueProvisionerJobsPkey UniqueConstraint = "provisioner_jobs_pkey" // ALTER TABLE ONLY provisioner_jobs ADD CONSTRAINT provisioner_jobs_pkey PRIMARY KEY (id);
|
||||
UniqueProvisionerKeysPkey UniqueConstraint = "provisioner_keys_pkey" // ALTER TABLE ONLY provisioner_keys ADD CONSTRAINT provisioner_keys_pkey PRIMARY KEY (id);
|
||||
UniqueSiteConfigsKeyKey UniqueConstraint = "site_configs_key_key" // ALTER TABLE ONLY site_configs ADD CONSTRAINT site_configs_key_key UNIQUE (key);
|
||||
UniqueTailnetCoordinatorsPkey UniqueConstraint = "tailnet_coordinators_pkey" // ALTER TABLE ONLY tailnet_coordinators ADD CONSTRAINT tailnet_coordinators_pkey PRIMARY KEY (id);
|
||||
UniqueTailnetPeersPkey UniqueConstraint = "tailnet_peers_pkey" // ALTER TABLE ONLY tailnet_peers ADD CONSTRAINT tailnet_peers_pkey PRIMARY KEY (id, coordinator_id);
|
||||
UniqueTailnetTunnelsPkey UniqueConstraint = "tailnet_tunnels_pkey" // ALTER TABLE ONLY tailnet_tunnels ADD CONSTRAINT tailnet_tunnels_pkey PRIMARY KEY (coordinator_id, src_id, dst_id);
|
||||
UniqueTaskSnapshotsPkey UniqueConstraint = "task_snapshots_pkey" // ALTER TABLE ONLY task_snapshots ADD CONSTRAINT task_snapshots_pkey PRIMARY KEY (task_id);
|
||||
UniqueTaskWorkspaceAppsPkey UniqueConstraint = "task_workspace_apps_pkey" // ALTER TABLE ONLY task_workspace_apps ADD CONSTRAINT task_workspace_apps_pkey PRIMARY KEY (task_id, workspace_build_number);
|
||||
UniqueTasksPkey UniqueConstraint = "tasks_pkey" // ALTER TABLE ONLY tasks ADD CONSTRAINT tasks_pkey PRIMARY KEY (id);
|
||||
UniqueTelemetryItemsPkey UniqueConstraint = "telemetry_items_pkey" // ALTER TABLE ONLY telemetry_items ADD CONSTRAINT telemetry_items_pkey PRIMARY KEY (key);
|
||||
UniqueTelemetryLocksPkey UniqueConstraint = "telemetry_locks_pkey" // ALTER TABLE ONLY telemetry_locks ADD CONSTRAINT telemetry_locks_pkey PRIMARY KEY (event_type, period_ending_at);
|
||||
UniqueTemplateUsageStatsPkey UniqueConstraint = "template_usage_stats_pkey" // ALTER TABLE ONLY template_usage_stats ADD CONSTRAINT template_usage_stats_pkey PRIMARY KEY (start_time, template_id, user_id);
|
||||
UniqueTemplateVersionParametersTemplateVersionIDNameKey UniqueConstraint = "template_version_parameters_template_version_id_name_key" // ALTER TABLE ONLY template_version_parameters ADD CONSTRAINT template_version_parameters_template_version_id_name_key UNIQUE (template_version_id, name);
|
||||
UniqueTemplateVersionPresetParametersPkey UniqueConstraint = "template_version_preset_parameters_pkey" // ALTER TABLE ONLY template_version_preset_parameters ADD CONSTRAINT template_version_preset_parameters_pkey PRIMARY KEY (id);
|
||||
UniqueTemplateVersionPresetPrebuildSchedulesPkey UniqueConstraint = "template_version_preset_prebuild_schedules_pkey" // ALTER TABLE ONLY template_version_preset_prebuild_schedules ADD CONSTRAINT template_version_preset_prebuild_schedules_pkey PRIMARY KEY (id);
|
||||
UniqueTemplateVersionPresetsIDTemplateVersionIDKey UniqueConstraint = "template_version_presets_id_template_version_id_key" // ALTER TABLE ONLY template_version_presets ADD CONSTRAINT template_version_presets_id_template_version_id_key UNIQUE (id, template_version_id);
|
||||
UniqueTemplateVersionPresetsPkey UniqueConstraint = "template_version_presets_pkey" // ALTER TABLE ONLY template_version_presets ADD CONSTRAINT template_version_presets_pkey PRIMARY KEY (id);
|
||||
UniqueTemplateVersionTerraformValuesTemplateVersionIDKey UniqueConstraint = "template_version_terraform_values_template_version_id_key" // ALTER TABLE ONLY template_version_terraform_values ADD CONSTRAINT template_version_terraform_values_template_version_id_key UNIQUE (template_version_id);
|
||||
UniqueTemplateVersionVariablesTemplateVersionIDNameKey UniqueConstraint = "template_version_variables_template_version_id_name_key" // ALTER TABLE ONLY template_version_variables ADD CONSTRAINT template_version_variables_template_version_id_name_key UNIQUE (template_version_id, name);
|
||||
UniqueTemplateVersionWorkspaceTagsTemplateVersionIDKeyKey UniqueConstraint = "template_version_workspace_tags_template_version_id_key_key" // ALTER TABLE ONLY template_version_workspace_tags ADD CONSTRAINT template_version_workspace_tags_template_version_id_key_key UNIQUE (template_version_id, key);
|
||||
UniqueTemplateVersionsPkey UniqueConstraint = "template_versions_pkey" // ALTER TABLE ONLY template_versions ADD CONSTRAINT template_versions_pkey PRIMARY KEY (id);
|
||||
UniqueTemplateVersionsTemplateIDNameKey UniqueConstraint = "template_versions_template_id_name_key" // ALTER TABLE ONLY template_versions ADD CONSTRAINT template_versions_template_id_name_key UNIQUE (template_id, name);
|
||||
UniqueTemplatesPkey UniqueConstraint = "templates_pkey" // ALTER TABLE ONLY templates ADD CONSTRAINT templates_pkey PRIMARY KEY (id);
|
||||
UniqueUsageEventsDailyPkey UniqueConstraint = "usage_events_daily_pkey" // ALTER TABLE ONLY usage_events_daily ADD CONSTRAINT usage_events_daily_pkey PRIMARY KEY (day, event_type);
|
||||
UniqueUsageEventsPkey UniqueConstraint = "usage_events_pkey" // ALTER TABLE ONLY usage_events ADD CONSTRAINT usage_events_pkey PRIMARY KEY (id);
|
||||
UniqueUserAIBudgetOverridesPkey UniqueConstraint = "user_ai_budget_overrides_pkey" // ALTER TABLE ONLY user_ai_budget_overrides ADD CONSTRAINT user_ai_budget_overrides_pkey PRIMARY KEY (user_id);
|
||||
UniqueUserAIProviderKeysPkey UniqueConstraint = "user_ai_provider_keys_pkey" // ALTER TABLE ONLY user_ai_provider_keys ADD CONSTRAINT user_ai_provider_keys_pkey PRIMARY KEY (id);
|
||||
UniqueUserAIProviderKeysUserIDAIProviderIDKey UniqueConstraint = "user_ai_provider_keys_user_id_ai_provider_id_key" // ALTER TABLE ONLY user_ai_provider_keys ADD CONSTRAINT user_ai_provider_keys_user_id_ai_provider_id_key UNIQUE (user_id, ai_provider_id);
|
||||
UniqueUserConfigsPkey UniqueConstraint = "user_configs_pkey" // ALTER TABLE ONLY user_configs ADD CONSTRAINT user_configs_pkey PRIMARY KEY (user_id, key);
|
||||
UniqueUserDeletedPkey UniqueConstraint = "user_deleted_pkey" // ALTER TABLE ONLY user_deleted ADD CONSTRAINT user_deleted_pkey PRIMARY KEY (id);
|
||||
UniqueUserLinksPkey UniqueConstraint = "user_links_pkey" // ALTER TABLE ONLY user_links ADD CONSTRAINT user_links_pkey PRIMARY KEY (user_id, login_type);
|
||||
UniqueUserSecretsPkey UniqueConstraint = "user_secrets_pkey" // ALTER TABLE ONLY user_secrets ADD CONSTRAINT user_secrets_pkey PRIMARY KEY (id);
|
||||
UniqueUserSkillsPkey UniqueConstraint = "user_skills_pkey" // ALTER TABLE ONLY user_skills ADD CONSTRAINT user_skills_pkey PRIMARY KEY (id);
|
||||
UniqueUserStatusChangesPkey UniqueConstraint = "user_status_changes_pkey" // ALTER TABLE ONLY user_status_changes ADD CONSTRAINT user_status_changes_pkey PRIMARY KEY (id);
|
||||
UniqueUsersPkey UniqueConstraint = "users_pkey" // ALTER TABLE ONLY users ADD CONSTRAINT users_pkey PRIMARY KEY (id);
|
||||
UniqueWebpushSubscriptionsPkey UniqueConstraint = "webpush_subscriptions_pkey" // ALTER TABLE ONLY webpush_subscriptions ADD CONSTRAINT webpush_subscriptions_pkey PRIMARY KEY (id);
|
||||
UniqueWorkspaceAgentContextResourcesPkey UniqueConstraint = "workspace_agent_context_resources_pkey" // ALTER TABLE ONLY workspace_agent_context_resources ADD CONSTRAINT workspace_agent_context_resources_pkey PRIMARY KEY (workspace_agent_id, source);
|
||||
UniqueWorkspaceAgentContextSnapshotsPkey UniqueConstraint = "workspace_agent_context_snapshots_pkey" // ALTER TABLE ONLY workspace_agent_context_snapshots ADD CONSTRAINT workspace_agent_context_snapshots_pkey PRIMARY KEY (workspace_agent_id);
|
||||
UniqueWorkspaceAgentDevcontainersPkey UniqueConstraint = "workspace_agent_devcontainers_pkey" // ALTER TABLE ONLY workspace_agent_devcontainers ADD CONSTRAINT workspace_agent_devcontainers_pkey PRIMARY KEY (id);
|
||||
UniqueWorkspaceAgentLogSourcesPkey UniqueConstraint = "workspace_agent_log_sources_pkey" // ALTER TABLE ONLY workspace_agent_log_sources ADD CONSTRAINT workspace_agent_log_sources_pkey PRIMARY KEY (workspace_agent_id, id);
|
||||
UniqueWorkspaceAgentMemoryResourceMonitorsPkey UniqueConstraint = "workspace_agent_memory_resource_monitors_pkey" // ALTER TABLE ONLY workspace_agent_memory_resource_monitors ADD CONSTRAINT workspace_agent_memory_resource_monitors_pkey PRIMARY KEY (agent_id);
|
||||
UniqueWorkspaceAgentMetadataPkey UniqueConstraint = "workspace_agent_metadata_pkey" // ALTER TABLE ONLY workspace_agent_metadata ADD CONSTRAINT workspace_agent_metadata_pkey PRIMARY KEY (workspace_agent_id, key);
|
||||
UniqueWorkspaceAgentPortSharePkey UniqueConstraint = "workspace_agent_port_share_pkey" // ALTER TABLE ONLY workspace_agent_port_share ADD CONSTRAINT workspace_agent_port_share_pkey PRIMARY KEY (workspace_id, agent_name, port);
|
||||
UniqueWorkspaceAgentScriptTimingsScriptIDStartedAtKey UniqueConstraint = "workspace_agent_script_timings_script_id_started_at_key" // ALTER TABLE ONLY workspace_agent_script_timings ADD CONSTRAINT workspace_agent_script_timings_script_id_started_at_key UNIQUE (script_id, started_at);
|
||||
UniqueWorkspaceAgentScriptsIDKey UniqueConstraint = "workspace_agent_scripts_id_key" // ALTER TABLE ONLY workspace_agent_scripts ADD CONSTRAINT workspace_agent_scripts_id_key UNIQUE (id);
|
||||
UniqueWorkspaceAgentStartupLogsPkey UniqueConstraint = "workspace_agent_startup_logs_pkey" // ALTER TABLE ONLY workspace_agent_logs ADD CONSTRAINT workspace_agent_startup_logs_pkey PRIMARY KEY (id);
|
||||
UniqueWorkspaceAgentVolumeResourceMonitorsPkey UniqueConstraint = "workspace_agent_volume_resource_monitors_pkey" // ALTER TABLE ONLY workspace_agent_volume_resource_monitors ADD CONSTRAINT workspace_agent_volume_resource_monitors_pkey PRIMARY KEY (agent_id, path);
|
||||
UniqueWorkspaceAgentsPkey UniqueConstraint = "workspace_agents_pkey" // ALTER TABLE ONLY workspace_agents ADD CONSTRAINT workspace_agents_pkey PRIMARY KEY (id);
|
||||
UniqueWorkspaceAppAuditSessionsAgentIDAppIDUserIDIpUseKey UniqueConstraint = "workspace_app_audit_sessions_agent_id_app_id_user_id_ip_use_key" // ALTER TABLE ONLY workspace_app_audit_sessions ADD CONSTRAINT workspace_app_audit_sessions_agent_id_app_id_user_id_ip_use_key UNIQUE (agent_id, app_id, user_id, ip, user_agent, slug_or_port, status_code);
|
||||
UniqueWorkspaceAppAuditSessionsPkey UniqueConstraint = "workspace_app_audit_sessions_pkey" // ALTER TABLE ONLY workspace_app_audit_sessions ADD CONSTRAINT workspace_app_audit_sessions_pkey PRIMARY KEY (id);
|
||||
UniqueWorkspaceAppStatsPkey UniqueConstraint = "workspace_app_stats_pkey" // ALTER TABLE ONLY workspace_app_stats ADD CONSTRAINT workspace_app_stats_pkey PRIMARY KEY (id);
|
||||
UniqueWorkspaceAppStatsUserIDAgentIDSessionIDKey UniqueConstraint = "workspace_app_stats_user_id_agent_id_session_id_key" // ALTER TABLE ONLY workspace_app_stats ADD CONSTRAINT workspace_app_stats_user_id_agent_id_session_id_key UNIQUE (user_id, agent_id, session_id);
|
||||
UniqueWorkspaceAppStatusesPkey UniqueConstraint = "workspace_app_statuses_pkey" // ALTER TABLE ONLY workspace_app_statuses ADD CONSTRAINT workspace_app_statuses_pkey PRIMARY KEY (id);
|
||||
UniqueWorkspaceAppsAgentIDSlugIndex UniqueConstraint = "workspace_apps_agent_id_slug_idx" // ALTER TABLE ONLY workspace_apps ADD CONSTRAINT workspace_apps_agent_id_slug_idx UNIQUE (agent_id, slug);
|
||||
UniqueWorkspaceAppsPkey UniqueConstraint = "workspace_apps_pkey" // ALTER TABLE ONLY workspace_apps ADD CONSTRAINT workspace_apps_pkey PRIMARY KEY (id);
|
||||
UniqueWorkspaceBuildOrchestrationsChildBuildIDKey UniqueConstraint = "workspace_build_orchestrations_child_build_id_key" // ALTER TABLE ONLY workspace_build_orchestrations ADD CONSTRAINT workspace_build_orchestrations_child_build_id_key UNIQUE (child_build_id);
|
||||
UniqueWorkspaceBuildOrchestrationsParentBuildIDKey UniqueConstraint = "workspace_build_orchestrations_parent_build_id_key" // ALTER TABLE ONLY workspace_build_orchestrations ADD CONSTRAINT workspace_build_orchestrations_parent_build_id_key UNIQUE (parent_build_id);
|
||||
UniqueWorkspaceBuildOrchestrationsPkey UniqueConstraint = "workspace_build_orchestrations_pkey" // ALTER TABLE ONLY workspace_build_orchestrations ADD CONSTRAINT workspace_build_orchestrations_pkey PRIMARY KEY (id);
|
||||
UniqueWorkspaceBuildParametersWorkspaceBuildIDNameKey UniqueConstraint = "workspace_build_parameters_workspace_build_id_name_key" // ALTER TABLE ONLY workspace_build_parameters ADD CONSTRAINT workspace_build_parameters_workspace_build_id_name_key UNIQUE (workspace_build_id, name);
|
||||
UniqueWorkspaceBuildsIDWorkspaceIDKey UniqueConstraint = "workspace_builds_id_workspace_id_key" // ALTER TABLE ONLY workspace_builds ADD CONSTRAINT workspace_builds_id_workspace_id_key UNIQUE (id, workspace_id);
|
||||
UniqueWorkspaceBuildsJobIDKey UniqueConstraint = "workspace_builds_job_id_key" // ALTER TABLE ONLY workspace_builds ADD CONSTRAINT workspace_builds_job_id_key UNIQUE (job_id);
|
||||
UniqueWorkspaceBuildsPkey UniqueConstraint = "workspace_builds_pkey" // ALTER TABLE ONLY workspace_builds ADD CONSTRAINT workspace_builds_pkey PRIMARY KEY (id);
|
||||
UniqueWorkspaceBuildsWorkspaceIDBuildNumberKey UniqueConstraint = "workspace_builds_workspace_id_build_number_key" // ALTER TABLE ONLY workspace_builds ADD CONSTRAINT workspace_builds_workspace_id_build_number_key UNIQUE (workspace_id, build_number);
|
||||
UniqueWorkspaceProxiesPkey UniqueConstraint = "workspace_proxies_pkey" // ALTER TABLE ONLY workspace_proxies ADD CONSTRAINT workspace_proxies_pkey PRIMARY KEY (id);
|
||||
UniqueWorkspaceProxiesRegionIDUnique UniqueConstraint = "workspace_proxies_region_id_unique" // ALTER TABLE ONLY workspace_proxies ADD CONSTRAINT workspace_proxies_region_id_unique UNIQUE (region_id);
|
||||
UniqueWorkspaceResourceMetadataName UniqueConstraint = "workspace_resource_metadata_name" // ALTER TABLE ONLY workspace_resource_metadata ADD CONSTRAINT workspace_resource_metadata_name UNIQUE (workspace_resource_id, key);
|
||||
UniqueWorkspaceResourceMetadataPkey UniqueConstraint = "workspace_resource_metadata_pkey" // ALTER TABLE ONLY workspace_resource_metadata ADD CONSTRAINT workspace_resource_metadata_pkey PRIMARY KEY (id);
|
||||
UniqueWorkspaceResourcesPkey UniqueConstraint = "workspace_resources_pkey" // ALTER TABLE ONLY workspace_resources ADD CONSTRAINT workspace_resources_pkey PRIMARY KEY (id);
|
||||
UniqueWorkspacesPkey UniqueConstraint = "workspaces_pkey" // ALTER TABLE ONLY workspaces ADD CONSTRAINT workspaces_pkey PRIMARY KEY (id);
|
||||
UniqueAIGatewayKeysHashedSecretIndex UniqueConstraint = "ai_gateway_keys_hashed_secret_idx" // CREATE UNIQUE INDEX ai_gateway_keys_hashed_secret_idx ON ai_gateway_keys USING btree (hashed_secret);
|
||||
UniqueAIGatewayKeysNameIndex UniqueConstraint = "ai_gateway_keys_name_idx" // CREATE UNIQUE INDEX ai_gateway_keys_name_idx ON ai_gateway_keys USING btree (lower(name));
|
||||
UniqueAIGatewayKeysSecretPrefixIndex UniqueConstraint = "ai_gateway_keys_secret_prefix_idx" // CREATE UNIQUE INDEX ai_gateway_keys_secret_prefix_idx ON ai_gateway_keys USING btree (secret_prefix);
|
||||
UniqueAIProvidersNameUnique UniqueConstraint = "ai_providers_name_unique" // CREATE UNIQUE INDEX ai_providers_name_unique ON ai_providers USING btree (name) WHERE (deleted = false);
|
||||
UniqueIndexAPIKeyName UniqueConstraint = "idx_api_key_name" // CREATE UNIQUE INDEX idx_api_key_name ON api_keys USING btree (user_id, token_name) WHERE (login_type = 'token'::login_type);
|
||||
UniqueIndexChatDebugRunsIDChat UniqueConstraint = "idx_chat_debug_runs_id_chat" // CREATE UNIQUE INDEX idx_chat_debug_runs_id_chat ON chat_debug_runs USING btree (id, chat_id);
|
||||
UniqueIndexChatDebugStepsRunStep UniqueConstraint = "idx_chat_debug_steps_run_step" // CREATE UNIQUE INDEX idx_chat_debug_steps_run_step ON chat_debug_steps USING btree (run_id, step_number);
|
||||
UniqueIndexChatModelConfigsSingleDefault UniqueConstraint = "idx_chat_model_configs_single_default" // CREATE UNIQUE INDEX idx_chat_model_configs_single_default ON chat_model_configs USING btree (organization_id) WHERE ((is_default = true) AND (deleted = false));
|
||||
UniqueIndexConnectionLogsConnectionIDWorkspaceIDAgentName UniqueConstraint = "idx_connection_logs_connection_id_workspace_id_agent_name" // CREATE UNIQUE INDEX idx_connection_logs_connection_id_workspace_id_agent_name ON connection_logs USING btree (connection_id, workspace_id, agent_name);
|
||||
UniqueIndexCustomRolesNameLowerOrganizationID UniqueConstraint = "idx_custom_roles_name_lower_organization_id" // CREATE UNIQUE INDEX idx_custom_roles_name_lower_organization_id ON custom_roles USING btree (lower(name), COALESCE(organization_id, '00000000-0000-0000-0000-000000000000'::uuid));
|
||||
UniqueIndexOrganizationNameLower UniqueConstraint = "idx_organization_name_lower" // CREATE UNIQUE INDEX idx_organization_name_lower ON organizations USING btree (lower(name)) WHERE (deleted = false);
|
||||
UniqueIndexProvisionerDaemonsOrgNameOwnerKey UniqueConstraint = "idx_provisioner_daemons_org_name_owner_key" // CREATE UNIQUE INDEX idx_provisioner_daemons_org_name_owner_key ON provisioner_daemons USING btree (organization_id, name, lower(COALESCE((tags ->> 'owner'::text), ''::text)));
|
||||
UniqueIndexTemplateVersionPresetsDefault UniqueConstraint = "idx_template_version_presets_default" // CREATE UNIQUE INDEX idx_template_version_presets_default ON template_version_presets USING btree (template_version_id) WHERE (is_default = true);
|
||||
UniqueIndexUniquePresetName UniqueConstraint = "idx_unique_preset_name" // CREATE UNIQUE INDEX idx_unique_preset_name ON template_version_presets USING btree (name, template_version_id);
|
||||
UniqueIndexUsageEventsAgentRuntime UniqueConstraint = "idx_usage_events_agent_runtime" // CREATE UNIQUE INDEX idx_usage_events_agent_runtime ON usage_events USING btree (event_type, created_at) WHERE (event_type = 'hb_agent_runtime_v1'::text);
|
||||
UniqueIndexUsersEmail UniqueConstraint = "idx_users_email" // CREATE UNIQUE INDEX idx_users_email ON users USING btree (email) WHERE ((deleted = false) AND (email <> ''::text));
|
||||
UniqueIndexUsersUsername UniqueConstraint = "idx_users_username" // CREATE UNIQUE INDEX idx_users_username ON users USING btree (username) WHERE (deleted = false);
|
||||
UniqueNotificationMessagesDedupeHashIndex UniqueConstraint = "notification_messages_dedupe_hash_idx" // CREATE UNIQUE INDEX notification_messages_dedupe_hash_idx ON notification_messages USING btree (dedupe_hash);
|
||||
UniqueOrganizationsSingleDefaultOrg UniqueConstraint = "organizations_single_default_org" // CREATE UNIQUE INDEX organizations_single_default_org ON organizations USING btree (is_default) WHERE (is_default = true);
|
||||
UniqueProvisionerKeysOrganizationIDNameIndex UniqueConstraint = "provisioner_keys_organization_id_name_idx" // CREATE UNIQUE INDEX provisioner_keys_organization_id_name_idx ON provisioner_keys USING btree (organization_id, lower((name)::text));
|
||||
UniqueTasksOwnerIDNameUniqueIndex UniqueConstraint = "tasks_owner_id_name_unique_idx" // CREATE UNIQUE INDEX tasks_owner_id_name_unique_idx ON tasks USING btree (owner_id, lower(name)) WHERE (deleted_at IS NULL);
|
||||
UniqueTemplateUsageStatsStartTimeTemplateIDUserIDIndex UniqueConstraint = "template_usage_stats_start_time_template_id_user_id_idx" // CREATE UNIQUE INDEX template_usage_stats_start_time_template_id_user_id_idx ON template_usage_stats USING btree (start_time, template_id, user_id);
|
||||
UniqueTemplatesOrganizationIDNameIndex UniqueConstraint = "templates_organization_id_name_idx" // CREATE UNIQUE INDEX templates_organization_id_name_idx ON templates USING btree (organization_id, lower((name)::text)) WHERE (deleted = false);
|
||||
UniqueUserLinksLinkedIDLoginTypeIndex UniqueConstraint = "user_links_linked_id_login_type_idx" // CREATE UNIQUE INDEX user_links_linked_id_login_type_idx ON user_links USING btree (linked_id, login_type) WHERE (linked_id <> ''::text);
|
||||
UniqueUserSecretsUserEnvNameIndex UniqueConstraint = "user_secrets_user_env_name_idx" // CREATE UNIQUE INDEX user_secrets_user_env_name_idx ON user_secrets USING btree (user_id, env_name) WHERE (env_name <> ''::text);
|
||||
UniqueUserSecretsUserFilePathIndex UniqueConstraint = "user_secrets_user_file_path_idx" // CREATE UNIQUE INDEX user_secrets_user_file_path_idx ON user_secrets USING btree (user_id, file_path) WHERE (file_path <> ''::text);
|
||||
UniqueUserSecretsUserNameIndex UniqueConstraint = "user_secrets_user_name_idx" // CREATE UNIQUE INDEX user_secrets_user_name_idx ON user_secrets USING btree (user_id, name);
|
||||
UniqueUserSkillsUserIDNameIndex UniqueConstraint = "user_skills_user_id_name_idx" // CREATE UNIQUE INDEX user_skills_user_id_name_idx ON user_skills USING btree (user_id, name);
|
||||
UniqueUsersEmailLowerIndex UniqueConstraint = "users_email_lower_idx" // CREATE UNIQUE INDEX users_email_lower_idx ON users USING btree (lower(email)) WHERE ((deleted = false) AND (email <> ''::text));
|
||||
UniqueUsersUsernameLowerIndex UniqueConstraint = "users_username_lower_idx" // CREATE UNIQUE INDEX users_username_lower_idx ON users USING btree (lower(username)) WHERE (deleted = false);
|
||||
UniqueWebpushSubscriptionsUserIDEndpointIndex UniqueConstraint = "webpush_subscriptions_user_id_endpoint_idx" // CREATE UNIQUE INDEX webpush_subscriptions_user_id_endpoint_idx ON webpush_subscriptions USING btree (user_id, endpoint);
|
||||
UniqueWorkspaceAppAuditSessionsUniqueIndex UniqueConstraint = "workspace_app_audit_sessions_unique_index" // CREATE UNIQUE INDEX workspace_app_audit_sessions_unique_index ON workspace_app_audit_sessions USING btree (agent_id, app_id, user_id, ip, user_agent, slug_or_port, status_code);
|
||||
UniqueWorkspaceProxiesLowerNameIndex UniqueConstraint = "workspace_proxies_lower_name_idx" // CREATE UNIQUE INDEX workspace_proxies_lower_name_idx ON workspace_proxies USING btree (lower(name)) WHERE (deleted = false);
|
||||
UniqueWorkspacesOwnerIDLowerIndex UniqueConstraint = "workspaces_owner_id_lower_idx" // CREATE UNIQUE INDEX workspaces_owner_id_lower_idx ON workspaces USING btree (owner_id, lower((name)::text)) WHERE (deleted = false);
|
||||
UniqueAgentStatsPkey UniqueConstraint = "agent_stats_pkey" // ALTER TABLE ONLY workspace_agent_stats ADD CONSTRAINT agent_stats_pkey PRIMARY KEY (id);
|
||||
UniqueAIGatewayKeysPkey UniqueConstraint = "ai_gateway_keys_pkey" // ALTER TABLE ONLY ai_gateway_keys ADD CONSTRAINT ai_gateway_keys_pkey PRIMARY KEY (id);
|
||||
UniqueAIModelPricesPkey UniqueConstraint = "ai_model_prices_pkey" // ALTER TABLE ONLY ai_model_prices ADD CONSTRAINT ai_model_prices_pkey PRIMARY KEY (provider, model, source);
|
||||
UniqueAIProviderKeysPkey UniqueConstraint = "ai_provider_keys_pkey" // ALTER TABLE ONLY ai_provider_keys ADD CONSTRAINT ai_provider_keys_pkey PRIMARY KEY (id);
|
||||
UniqueAIProvidersPkey UniqueConstraint = "ai_providers_pkey" // ALTER TABLE ONLY ai_providers ADD CONSTRAINT ai_providers_pkey PRIMARY KEY (id);
|
||||
UniqueAISeatStatePkey UniqueConstraint = "ai_seat_state_pkey" // ALTER TABLE ONLY ai_seat_state ADD CONSTRAINT ai_seat_state_pkey PRIMARY KEY (user_id);
|
||||
UniqueAIUserDailySpendPkey UniqueConstraint = "ai_user_daily_spend_pkey" // ALTER TABLE ONLY ai_user_daily_spend ADD CONSTRAINT ai_user_daily_spend_pkey PRIMARY KEY (user_id, effective_group_id, day);
|
||||
UniqueAibridgeInterceptionsPkey UniqueConstraint = "aibridge_interceptions_pkey" // ALTER TABLE ONLY aibridge_interceptions ADD CONSTRAINT aibridge_interceptions_pkey PRIMARY KEY (id);
|
||||
UniqueAibridgeTokenUsagesPkey UniqueConstraint = "aibridge_token_usages_pkey" // ALTER TABLE ONLY aibridge_token_usages ADD CONSTRAINT aibridge_token_usages_pkey PRIMARY KEY (id);
|
||||
UniqueAibridgeToolUsagesPkey UniqueConstraint = "aibridge_tool_usages_pkey" // ALTER TABLE ONLY aibridge_tool_usages ADD CONSTRAINT aibridge_tool_usages_pkey PRIMARY KEY (id);
|
||||
UniqueAibridgeUserPromptsPkey UniqueConstraint = "aibridge_user_prompts_pkey" // ALTER TABLE ONLY aibridge_user_prompts ADD CONSTRAINT aibridge_user_prompts_pkey PRIMARY KEY (id);
|
||||
UniqueAPIKeysPkey UniqueConstraint = "api_keys_pkey" // ALTER TABLE ONLY api_keys ADD CONSTRAINT api_keys_pkey PRIMARY KEY (id);
|
||||
UniqueAuditLogsPkey UniqueConstraint = "audit_logs_pkey" // ALTER TABLE ONLY audit_logs ADD CONSTRAINT audit_logs_pkey PRIMARY KEY (id);
|
||||
UniqueBoundaryLogsPkey UniqueConstraint = "boundary_logs_pkey" // ALTER TABLE ONLY boundary_logs ADD CONSTRAINT boundary_logs_pkey PRIMARY KEY (id);
|
||||
UniqueBoundarySessionsPkey UniqueConstraint = "boundary_sessions_pkey" // ALTER TABLE ONLY boundary_sessions ADD CONSTRAINT boundary_sessions_pkey PRIMARY KEY (id);
|
||||
UniqueBoundaryUsageStatsPkey UniqueConstraint = "boundary_usage_stats_pkey" // ALTER TABLE ONLY boundary_usage_stats ADD CONSTRAINT boundary_usage_stats_pkey PRIMARY KEY (replica_id);
|
||||
UniqueChatContextResourcesPkey UniqueConstraint = "chat_context_resources_pkey" // ALTER TABLE ONLY chat_context_resources ADD CONSTRAINT chat_context_resources_pkey PRIMARY KEY (chat_id, source);
|
||||
UniqueChatDebugRunsPkey UniqueConstraint = "chat_debug_runs_pkey" // ALTER TABLE ONLY chat_debug_runs ADD CONSTRAINT chat_debug_runs_pkey PRIMARY KEY (id);
|
||||
UniqueChatDebugStepsPkey UniqueConstraint = "chat_debug_steps_pkey" // ALTER TABLE ONLY chat_debug_steps ADD CONSTRAINT chat_debug_steps_pkey PRIMARY KEY (id);
|
||||
UniqueChatDiffStatusesPkey UniqueConstraint = "chat_diff_statuses_pkey" // ALTER TABLE ONLY chat_diff_statuses ADD CONSTRAINT chat_diff_statuses_pkey PRIMARY KEY (chat_id);
|
||||
UniqueChatFileLinksChatIDFileIDKey UniqueConstraint = "chat_file_links_chat_id_file_id_key" // ALTER TABLE ONLY chat_file_links ADD CONSTRAINT chat_file_links_chat_id_file_id_key UNIQUE (chat_id, file_id);
|
||||
UniqueChatFilesPkey UniqueConstraint = "chat_files_pkey" // ALTER TABLE ONLY chat_files ADD CONSTRAINT chat_files_pkey PRIMARY KEY (id);
|
||||
UniqueChatHeartbeatsPkey UniqueConstraint = "chat_heartbeats_pkey" // ALTER TABLE ONLY chat_heartbeats ADD CONSTRAINT chat_heartbeats_pkey PRIMARY KEY (chat_id, runner_id);
|
||||
UniqueChatMessagesPkey UniqueConstraint = "chat_messages_pkey" // ALTER TABLE ONLY chat_messages ADD CONSTRAINT chat_messages_pkey PRIMARY KEY (id);
|
||||
UniqueChatModelConfigsOrganizationIDIDKey UniqueConstraint = "chat_model_configs_organization_id_id_key" // ALTER TABLE ONLY chat_model_configs ADD CONSTRAINT chat_model_configs_organization_id_id_key UNIQUE (organization_id, id);
|
||||
UniqueChatModelConfigsPkey UniqueConstraint = "chat_model_configs_pkey" // ALTER TABLE ONLY chat_model_configs ADD CONSTRAINT chat_model_configs_pkey PRIMARY KEY (id);
|
||||
UniqueChatOrganizationModelOverridesOrganizationIDContextKey UniqueConstraint = "chat_organization_model_overrides_organization_id_context_key" // ALTER TABLE ONLY chat_organization_model_overrides ADD CONSTRAINT chat_organization_model_overrides_organization_id_context_key UNIQUE (organization_id, context);
|
||||
UniqueChatOrganizationModelOverridesPkey UniqueConstraint = "chat_organization_model_overrides_pkey" // ALTER TABLE ONLY chat_organization_model_overrides ADD CONSTRAINT chat_organization_model_overrides_pkey PRIMARY KEY (id);
|
||||
UniqueChatQueuedMessagesPkey UniqueConstraint = "chat_queued_messages_pkey" // ALTER TABLE ONLY chat_queued_messages ADD CONSTRAINT chat_queued_messages_pkey PRIMARY KEY (id);
|
||||
UniqueChatUsageLimitConfigPkey UniqueConstraint = "chat_usage_limit_config_pkey" // ALTER TABLE ONLY chat_usage_limit_config ADD CONSTRAINT chat_usage_limit_config_pkey PRIMARY KEY (id);
|
||||
UniqueChatUsageLimitConfigSingletonKey UniqueConstraint = "chat_usage_limit_config_singleton_key" // ALTER TABLE ONLY chat_usage_limit_config ADD CONSTRAINT chat_usage_limit_config_singleton_key UNIQUE (singleton);
|
||||
UniqueChatUserModelOverridesPkey UniqueConstraint = "chat_user_model_overrides_pkey" // ALTER TABLE ONLY chat_user_model_overrides ADD CONSTRAINT chat_user_model_overrides_pkey PRIMARY KEY (id);
|
||||
UniqueChatUserModelOverridesUserOrganizationContextKey UniqueConstraint = "chat_user_model_overrides_user_organization_context_key" // ALTER TABLE ONLY chat_user_model_overrides ADD CONSTRAINT chat_user_model_overrides_user_organization_context_key UNIQUE (user_id, organization_id, context);
|
||||
UniqueChatsPkey UniqueConstraint = "chats_pkey" // ALTER TABLE ONLY chats ADD CONSTRAINT chats_pkey PRIMARY KEY (id);
|
||||
UniqueConnectionLogsPkey UniqueConstraint = "connection_logs_pkey" // ALTER TABLE ONLY connection_logs ADD CONSTRAINT connection_logs_pkey PRIMARY KEY (id);
|
||||
UniqueCryptoKeysPkey UniqueConstraint = "crypto_keys_pkey" // ALTER TABLE ONLY crypto_keys ADD CONSTRAINT crypto_keys_pkey PRIMARY KEY (feature, sequence);
|
||||
UniqueCustomRolesUniqueKey UniqueConstraint = "custom_roles_unique_key" // ALTER TABLE ONLY custom_roles ADD CONSTRAINT custom_roles_unique_key UNIQUE (name, organization_id);
|
||||
UniqueDbcryptKeysActiveKeyDigestKey UniqueConstraint = "dbcrypt_keys_active_key_digest_key" // ALTER TABLE ONLY dbcrypt_keys ADD CONSTRAINT dbcrypt_keys_active_key_digest_key UNIQUE (active_key_digest);
|
||||
UniqueDbcryptKeysPkey UniqueConstraint = "dbcrypt_keys_pkey" // ALTER TABLE ONLY dbcrypt_keys ADD CONSTRAINT dbcrypt_keys_pkey PRIMARY KEY (number);
|
||||
UniqueDbcryptKeysRevokedKeyDigestKey UniqueConstraint = "dbcrypt_keys_revoked_key_digest_key" // ALTER TABLE ONLY dbcrypt_keys ADD CONSTRAINT dbcrypt_keys_revoked_key_digest_key UNIQUE (revoked_key_digest);
|
||||
UniqueFilesHashCreatedByKey UniqueConstraint = "files_hash_created_by_key" // ALTER TABLE ONLY files ADD CONSTRAINT files_hash_created_by_key UNIQUE (hash, created_by);
|
||||
UniqueFilesPkey UniqueConstraint = "files_pkey" // ALTER TABLE ONLY files ADD CONSTRAINT files_pkey PRIMARY KEY (id);
|
||||
UniqueGitAuthLinksProviderIDUserIDKey UniqueConstraint = "git_auth_links_provider_id_user_id_key" // ALTER TABLE ONLY external_auth_links ADD CONSTRAINT git_auth_links_provider_id_user_id_key UNIQUE (provider_id, user_id);
|
||||
UniqueGitSSHKeysPkey UniqueConstraint = "gitsshkeys_pkey" // ALTER TABLE ONLY gitsshkeys ADD CONSTRAINT gitsshkeys_pkey PRIMARY KEY (user_id);
|
||||
UniqueGroupAIBudgetsPkey UniqueConstraint = "group_ai_budgets_pkey" // ALTER TABLE ONLY group_ai_budgets ADD CONSTRAINT group_ai_budgets_pkey PRIMARY KEY (group_id);
|
||||
UniqueGroupMembersUserIDGroupIDKey UniqueConstraint = "group_members_user_id_group_id_key" // ALTER TABLE ONLY group_members ADD CONSTRAINT group_members_user_id_group_id_key UNIQUE (user_id, group_id);
|
||||
UniqueGroupsNameOrganizationIDKey UniqueConstraint = "groups_name_organization_id_key" // ALTER TABLE ONLY groups ADD CONSTRAINT groups_name_organization_id_key UNIQUE (name, organization_id);
|
||||
UniqueGroupsPkey UniqueConstraint = "groups_pkey" // ALTER TABLE ONLY groups ADD CONSTRAINT groups_pkey PRIMARY KEY (id);
|
||||
UniqueInboxNotificationsPkey UniqueConstraint = "inbox_notifications_pkey" // ALTER TABLE ONLY inbox_notifications ADD CONSTRAINT inbox_notifications_pkey PRIMARY KEY (id);
|
||||
UniqueJfrogXrayScansPkey UniqueConstraint = "jfrog_xray_scans_pkey" // ALTER TABLE ONLY jfrog_xray_scans ADD CONSTRAINT jfrog_xray_scans_pkey PRIMARY KEY (agent_id, workspace_id);
|
||||
UniqueLicensesJWTKey UniqueConstraint = "licenses_jwt_key" // ALTER TABLE ONLY licenses ADD CONSTRAINT licenses_jwt_key UNIQUE (jwt);
|
||||
UniqueLicensesPkey UniqueConstraint = "licenses_pkey" // ALTER TABLE ONLY licenses ADD CONSTRAINT licenses_pkey PRIMARY KEY (id);
|
||||
UniqueMcpServerConfigsOrganizationIDSlugKey UniqueConstraint = "mcp_server_configs_organization_id_slug_key" // ALTER TABLE ONLY mcp_server_configs ADD CONSTRAINT mcp_server_configs_organization_id_slug_key UNIQUE (organization_id, slug);
|
||||
UniqueMcpServerConfigsPkey UniqueConstraint = "mcp_server_configs_pkey" // ALTER TABLE ONLY mcp_server_configs ADD CONSTRAINT mcp_server_configs_pkey PRIMARY KEY (id);
|
||||
UniqueMcpServerUserTokensMcpServerConfigIDUserIDKey UniqueConstraint = "mcp_server_user_tokens_mcp_server_config_id_user_id_key" // ALTER TABLE ONLY mcp_server_user_tokens ADD CONSTRAINT mcp_server_user_tokens_mcp_server_config_id_user_id_key UNIQUE (mcp_server_config_id, user_id);
|
||||
UniqueMcpServerUserTokensPkey UniqueConstraint = "mcp_server_user_tokens_pkey" // ALTER TABLE ONLY mcp_server_user_tokens ADD CONSTRAINT mcp_server_user_tokens_pkey PRIMARY KEY (id);
|
||||
UniqueNotificationMessagesPkey UniqueConstraint = "notification_messages_pkey" // ALTER TABLE ONLY notification_messages ADD CONSTRAINT notification_messages_pkey PRIMARY KEY (id);
|
||||
UniqueNotificationPreferencesPkey UniqueConstraint = "notification_preferences_pkey" // ALTER TABLE ONLY notification_preferences ADD CONSTRAINT notification_preferences_pkey PRIMARY KEY (user_id, notification_template_id);
|
||||
UniqueNotificationReportGeneratorLogsPkey UniqueConstraint = "notification_report_generator_logs_pkey" // ALTER TABLE ONLY notification_report_generator_logs ADD CONSTRAINT notification_report_generator_logs_pkey PRIMARY KEY (notification_template_id);
|
||||
UniqueNotificationTemplatesNameKey UniqueConstraint = "notification_templates_name_key" // ALTER TABLE ONLY notification_templates ADD CONSTRAINT notification_templates_name_key UNIQUE (name);
|
||||
UniqueNotificationTemplatesPkey UniqueConstraint = "notification_templates_pkey" // ALTER TABLE ONLY notification_templates ADD CONSTRAINT notification_templates_pkey PRIMARY KEY (id);
|
||||
UniqueOauth2ProviderAppCodesPkey UniqueConstraint = "oauth2_provider_app_codes_pkey" // ALTER TABLE ONLY oauth2_provider_app_codes ADD CONSTRAINT oauth2_provider_app_codes_pkey PRIMARY KEY (id);
|
||||
UniqueOauth2ProviderAppCodesSecretPrefixKey UniqueConstraint = "oauth2_provider_app_codes_secret_prefix_key" // ALTER TABLE ONLY oauth2_provider_app_codes ADD CONSTRAINT oauth2_provider_app_codes_secret_prefix_key UNIQUE (secret_prefix);
|
||||
UniqueOauth2ProviderAppSecretsPkey UniqueConstraint = "oauth2_provider_app_secrets_pkey" // ALTER TABLE ONLY oauth2_provider_app_secrets ADD CONSTRAINT oauth2_provider_app_secrets_pkey PRIMARY KEY (id);
|
||||
UniqueOauth2ProviderAppSecretsSecretPrefixKey UniqueConstraint = "oauth2_provider_app_secrets_secret_prefix_key" // ALTER TABLE ONLY oauth2_provider_app_secrets ADD CONSTRAINT oauth2_provider_app_secrets_secret_prefix_key UNIQUE (secret_prefix);
|
||||
UniqueOauth2ProviderAppTokensHashPrefixKey UniqueConstraint = "oauth2_provider_app_tokens_hash_prefix_key" // ALTER TABLE ONLY oauth2_provider_app_tokens ADD CONSTRAINT oauth2_provider_app_tokens_hash_prefix_key UNIQUE (hash_prefix);
|
||||
UniqueOauth2ProviderAppTokensPkey UniqueConstraint = "oauth2_provider_app_tokens_pkey" // ALTER TABLE ONLY oauth2_provider_app_tokens ADD CONSTRAINT oauth2_provider_app_tokens_pkey PRIMARY KEY (id);
|
||||
UniqueOauth2ProviderAppsPkey UniqueConstraint = "oauth2_provider_apps_pkey" // ALTER TABLE ONLY oauth2_provider_apps ADD CONSTRAINT oauth2_provider_apps_pkey PRIMARY KEY (id);
|
||||
UniqueOrganizationMembersPkey UniqueConstraint = "organization_members_pkey" // ALTER TABLE ONLY organization_members ADD CONSTRAINT organization_members_pkey PRIMARY KEY (organization_id, user_id);
|
||||
UniqueOrganizationsPkey UniqueConstraint = "organizations_pkey" // ALTER TABLE ONLY organizations ADD CONSTRAINT organizations_pkey PRIMARY KEY (id);
|
||||
UniqueParameterSchemasJobIDNameKey UniqueConstraint = "parameter_schemas_job_id_name_key" // ALTER TABLE ONLY parameter_schemas ADD CONSTRAINT parameter_schemas_job_id_name_key UNIQUE (job_id, name);
|
||||
UniqueParameterSchemasPkey UniqueConstraint = "parameter_schemas_pkey" // ALTER TABLE ONLY parameter_schemas ADD CONSTRAINT parameter_schemas_pkey PRIMARY KEY (id);
|
||||
UniqueParameterValuesPkey UniqueConstraint = "parameter_values_pkey" // ALTER TABLE ONLY parameter_values ADD CONSTRAINT parameter_values_pkey PRIMARY KEY (id);
|
||||
UniqueParameterValuesScopeIDNameKey UniqueConstraint = "parameter_values_scope_id_name_key" // ALTER TABLE ONLY parameter_values ADD CONSTRAINT parameter_values_scope_id_name_key UNIQUE (scope_id, name);
|
||||
UniqueProvisionerDaemonsPkey UniqueConstraint = "provisioner_daemons_pkey" // ALTER TABLE ONLY provisioner_daemons ADD CONSTRAINT provisioner_daemons_pkey PRIMARY KEY (id);
|
||||
UniqueProvisionerJobLogsPkey UniqueConstraint = "provisioner_job_logs_pkey" // ALTER TABLE ONLY provisioner_job_logs ADD CONSTRAINT provisioner_job_logs_pkey PRIMARY KEY (id);
|
||||
UniqueProvisionerJobsPkey UniqueConstraint = "provisioner_jobs_pkey" // ALTER TABLE ONLY provisioner_jobs ADD CONSTRAINT provisioner_jobs_pkey PRIMARY KEY (id);
|
||||
UniqueProvisionerKeysPkey UniqueConstraint = "provisioner_keys_pkey" // ALTER TABLE ONLY provisioner_keys ADD CONSTRAINT provisioner_keys_pkey PRIMARY KEY (id);
|
||||
UniqueSiteConfigsKeyKey UniqueConstraint = "site_configs_key_key" // ALTER TABLE ONLY site_configs ADD CONSTRAINT site_configs_key_key UNIQUE (key);
|
||||
UniqueTailnetCoordinatorsPkey UniqueConstraint = "tailnet_coordinators_pkey" // ALTER TABLE ONLY tailnet_coordinators ADD CONSTRAINT tailnet_coordinators_pkey PRIMARY KEY (id);
|
||||
UniqueTailnetPeersPkey UniqueConstraint = "tailnet_peers_pkey" // ALTER TABLE ONLY tailnet_peers ADD CONSTRAINT tailnet_peers_pkey PRIMARY KEY (id, coordinator_id);
|
||||
UniqueTailnetTunnelsPkey UniqueConstraint = "tailnet_tunnels_pkey" // ALTER TABLE ONLY tailnet_tunnels ADD CONSTRAINT tailnet_tunnels_pkey PRIMARY KEY (coordinator_id, src_id, dst_id);
|
||||
UniqueTaskSnapshotsPkey UniqueConstraint = "task_snapshots_pkey" // ALTER TABLE ONLY task_snapshots ADD CONSTRAINT task_snapshots_pkey PRIMARY KEY (task_id);
|
||||
UniqueTaskWorkspaceAppsPkey UniqueConstraint = "task_workspace_apps_pkey" // ALTER TABLE ONLY task_workspace_apps ADD CONSTRAINT task_workspace_apps_pkey PRIMARY KEY (task_id, workspace_build_number);
|
||||
UniqueTasksPkey UniqueConstraint = "tasks_pkey" // ALTER TABLE ONLY tasks ADD CONSTRAINT tasks_pkey PRIMARY KEY (id);
|
||||
UniqueTelemetryItemsPkey UniqueConstraint = "telemetry_items_pkey" // ALTER TABLE ONLY telemetry_items ADD CONSTRAINT telemetry_items_pkey PRIMARY KEY (key);
|
||||
UniqueTelemetryLocksPkey UniqueConstraint = "telemetry_locks_pkey" // ALTER TABLE ONLY telemetry_locks ADD CONSTRAINT telemetry_locks_pkey PRIMARY KEY (event_type, period_ending_at);
|
||||
UniqueTemplateUsageStatsPkey UniqueConstraint = "template_usage_stats_pkey" // ALTER TABLE ONLY template_usage_stats ADD CONSTRAINT template_usage_stats_pkey PRIMARY KEY (start_time, template_id, user_id);
|
||||
UniqueTemplateVersionParametersTemplateVersionIDNameKey UniqueConstraint = "template_version_parameters_template_version_id_name_key" // ALTER TABLE ONLY template_version_parameters ADD CONSTRAINT template_version_parameters_template_version_id_name_key UNIQUE (template_version_id, name);
|
||||
UniqueTemplateVersionPresetParametersPkey UniqueConstraint = "template_version_preset_parameters_pkey" // ALTER TABLE ONLY template_version_preset_parameters ADD CONSTRAINT template_version_preset_parameters_pkey PRIMARY KEY (id);
|
||||
UniqueTemplateVersionPresetPrebuildSchedulesPkey UniqueConstraint = "template_version_preset_prebuild_schedules_pkey" // ALTER TABLE ONLY template_version_preset_prebuild_schedules ADD CONSTRAINT template_version_preset_prebuild_schedules_pkey PRIMARY KEY (id);
|
||||
UniqueTemplateVersionPresetsIDTemplateVersionIDKey UniqueConstraint = "template_version_presets_id_template_version_id_key" // ALTER TABLE ONLY template_version_presets ADD CONSTRAINT template_version_presets_id_template_version_id_key UNIQUE (id, template_version_id);
|
||||
UniqueTemplateVersionPresetsPkey UniqueConstraint = "template_version_presets_pkey" // ALTER TABLE ONLY template_version_presets ADD CONSTRAINT template_version_presets_pkey PRIMARY KEY (id);
|
||||
UniqueTemplateVersionTerraformValuesTemplateVersionIDKey UniqueConstraint = "template_version_terraform_values_template_version_id_key" // ALTER TABLE ONLY template_version_terraform_values ADD CONSTRAINT template_version_terraform_values_template_version_id_key UNIQUE (template_version_id);
|
||||
UniqueTemplateVersionVariablesTemplateVersionIDNameKey UniqueConstraint = "template_version_variables_template_version_id_name_key" // ALTER TABLE ONLY template_version_variables ADD CONSTRAINT template_version_variables_template_version_id_name_key UNIQUE (template_version_id, name);
|
||||
UniqueTemplateVersionWorkspaceTagsTemplateVersionIDKeyKey UniqueConstraint = "template_version_workspace_tags_template_version_id_key_key" // ALTER TABLE ONLY template_version_workspace_tags ADD CONSTRAINT template_version_workspace_tags_template_version_id_key_key UNIQUE (template_version_id, key);
|
||||
UniqueTemplateVersionsPkey UniqueConstraint = "template_versions_pkey" // ALTER TABLE ONLY template_versions ADD CONSTRAINT template_versions_pkey PRIMARY KEY (id);
|
||||
UniqueTemplateVersionsTemplateIDNameKey UniqueConstraint = "template_versions_template_id_name_key" // ALTER TABLE ONLY template_versions ADD CONSTRAINT template_versions_template_id_name_key UNIQUE (template_id, name);
|
||||
UniqueTemplatesPkey UniqueConstraint = "templates_pkey" // ALTER TABLE ONLY templates ADD CONSTRAINT templates_pkey PRIMARY KEY (id);
|
||||
UniqueUsageEventsDailyPkey UniqueConstraint = "usage_events_daily_pkey" // ALTER TABLE ONLY usage_events_daily ADD CONSTRAINT usage_events_daily_pkey PRIMARY KEY (day, event_type);
|
||||
UniqueUsageEventsPkey UniqueConstraint = "usage_events_pkey" // ALTER TABLE ONLY usage_events ADD CONSTRAINT usage_events_pkey PRIMARY KEY (id);
|
||||
UniqueUserAIBudgetOverridesPkey UniqueConstraint = "user_ai_budget_overrides_pkey" // ALTER TABLE ONLY user_ai_budget_overrides ADD CONSTRAINT user_ai_budget_overrides_pkey PRIMARY KEY (user_id);
|
||||
UniqueUserAIProviderKeysPkey UniqueConstraint = "user_ai_provider_keys_pkey" // ALTER TABLE ONLY user_ai_provider_keys ADD CONSTRAINT user_ai_provider_keys_pkey PRIMARY KEY (id);
|
||||
UniqueUserAIProviderKeysUserIDAIProviderIDKey UniqueConstraint = "user_ai_provider_keys_user_id_ai_provider_id_key" // ALTER TABLE ONLY user_ai_provider_keys ADD CONSTRAINT user_ai_provider_keys_user_id_ai_provider_id_key UNIQUE (user_id, ai_provider_id);
|
||||
UniqueUserConfigsPkey UniqueConstraint = "user_configs_pkey" // ALTER TABLE ONLY user_configs ADD CONSTRAINT user_configs_pkey PRIMARY KEY (user_id, key);
|
||||
UniqueUserDeletedPkey UniqueConstraint = "user_deleted_pkey" // ALTER TABLE ONLY user_deleted ADD CONSTRAINT user_deleted_pkey PRIMARY KEY (id);
|
||||
UniqueUserLinksPkey UniqueConstraint = "user_links_pkey" // ALTER TABLE ONLY user_links ADD CONSTRAINT user_links_pkey PRIMARY KEY (user_id, login_type);
|
||||
UniqueUserSecretsPkey UniqueConstraint = "user_secrets_pkey" // ALTER TABLE ONLY user_secrets ADD CONSTRAINT user_secrets_pkey PRIMARY KEY (id);
|
||||
UniqueUserSkillsPkey UniqueConstraint = "user_skills_pkey" // ALTER TABLE ONLY user_skills ADD CONSTRAINT user_skills_pkey PRIMARY KEY (id);
|
||||
UniqueUserStatusChangesPkey UniqueConstraint = "user_status_changes_pkey" // ALTER TABLE ONLY user_status_changes ADD CONSTRAINT user_status_changes_pkey PRIMARY KEY (id);
|
||||
UniqueUsersPkey UniqueConstraint = "users_pkey" // ALTER TABLE ONLY users ADD CONSTRAINT users_pkey PRIMARY KEY (id);
|
||||
UniqueWebpushSubscriptionsPkey UniqueConstraint = "webpush_subscriptions_pkey" // ALTER TABLE ONLY webpush_subscriptions ADD CONSTRAINT webpush_subscriptions_pkey PRIMARY KEY (id);
|
||||
UniqueWorkspaceAgentContextResourcesPkey UniqueConstraint = "workspace_agent_context_resources_pkey" // ALTER TABLE ONLY workspace_agent_context_resources ADD CONSTRAINT workspace_agent_context_resources_pkey PRIMARY KEY (workspace_agent_id, source);
|
||||
UniqueWorkspaceAgentContextSnapshotsPkey UniqueConstraint = "workspace_agent_context_snapshots_pkey" // ALTER TABLE ONLY workspace_agent_context_snapshots ADD CONSTRAINT workspace_agent_context_snapshots_pkey PRIMARY KEY (workspace_agent_id);
|
||||
UniqueWorkspaceAgentDevcontainersPkey UniqueConstraint = "workspace_agent_devcontainers_pkey" // ALTER TABLE ONLY workspace_agent_devcontainers ADD CONSTRAINT workspace_agent_devcontainers_pkey PRIMARY KEY (id);
|
||||
UniqueWorkspaceAgentLogSourcesPkey UniqueConstraint = "workspace_agent_log_sources_pkey" // ALTER TABLE ONLY workspace_agent_log_sources ADD CONSTRAINT workspace_agent_log_sources_pkey PRIMARY KEY (workspace_agent_id, id);
|
||||
UniqueWorkspaceAgentMemoryResourceMonitorsPkey UniqueConstraint = "workspace_agent_memory_resource_monitors_pkey" // ALTER TABLE ONLY workspace_agent_memory_resource_monitors ADD CONSTRAINT workspace_agent_memory_resource_monitors_pkey PRIMARY KEY (agent_id);
|
||||
UniqueWorkspaceAgentMetadataPkey UniqueConstraint = "workspace_agent_metadata_pkey" // ALTER TABLE ONLY workspace_agent_metadata ADD CONSTRAINT workspace_agent_metadata_pkey PRIMARY KEY (workspace_agent_id, key);
|
||||
UniqueWorkspaceAgentPortSharePkey UniqueConstraint = "workspace_agent_port_share_pkey" // ALTER TABLE ONLY workspace_agent_port_share ADD CONSTRAINT workspace_agent_port_share_pkey PRIMARY KEY (workspace_id, agent_name, port);
|
||||
UniqueWorkspaceAgentScriptTimingsScriptIDStartedAtKey UniqueConstraint = "workspace_agent_script_timings_script_id_started_at_key" // ALTER TABLE ONLY workspace_agent_script_timings ADD CONSTRAINT workspace_agent_script_timings_script_id_started_at_key UNIQUE (script_id, started_at);
|
||||
UniqueWorkspaceAgentScriptsIDKey UniqueConstraint = "workspace_agent_scripts_id_key" // ALTER TABLE ONLY workspace_agent_scripts ADD CONSTRAINT workspace_agent_scripts_id_key UNIQUE (id);
|
||||
UniqueWorkspaceAgentStartupLogsPkey UniqueConstraint = "workspace_agent_startup_logs_pkey" // ALTER TABLE ONLY workspace_agent_logs ADD CONSTRAINT workspace_agent_startup_logs_pkey PRIMARY KEY (id);
|
||||
UniqueWorkspaceAgentVolumeResourceMonitorsPkey UniqueConstraint = "workspace_agent_volume_resource_monitors_pkey" // ALTER TABLE ONLY workspace_agent_volume_resource_monitors ADD CONSTRAINT workspace_agent_volume_resource_monitors_pkey PRIMARY KEY (agent_id, path);
|
||||
UniqueWorkspaceAgentsPkey UniqueConstraint = "workspace_agents_pkey" // ALTER TABLE ONLY workspace_agents ADD CONSTRAINT workspace_agents_pkey PRIMARY KEY (id);
|
||||
UniqueWorkspaceAppAuditSessionsAgentIDAppIDUserIDIpUseKey UniqueConstraint = "workspace_app_audit_sessions_agent_id_app_id_user_id_ip_use_key" // ALTER TABLE ONLY workspace_app_audit_sessions ADD CONSTRAINT workspace_app_audit_sessions_agent_id_app_id_user_id_ip_use_key UNIQUE (agent_id, app_id, user_id, ip, user_agent, slug_or_port, status_code);
|
||||
UniqueWorkspaceAppAuditSessionsPkey UniqueConstraint = "workspace_app_audit_sessions_pkey" // ALTER TABLE ONLY workspace_app_audit_sessions ADD CONSTRAINT workspace_app_audit_sessions_pkey PRIMARY KEY (id);
|
||||
UniqueWorkspaceAppStatsPkey UniqueConstraint = "workspace_app_stats_pkey" // ALTER TABLE ONLY workspace_app_stats ADD CONSTRAINT workspace_app_stats_pkey PRIMARY KEY (id);
|
||||
UniqueWorkspaceAppStatsUserIDAgentIDSessionIDKey UniqueConstraint = "workspace_app_stats_user_id_agent_id_session_id_key" // ALTER TABLE ONLY workspace_app_stats ADD CONSTRAINT workspace_app_stats_user_id_agent_id_session_id_key UNIQUE (user_id, agent_id, session_id);
|
||||
UniqueWorkspaceAppStatusesPkey UniqueConstraint = "workspace_app_statuses_pkey" // ALTER TABLE ONLY workspace_app_statuses ADD CONSTRAINT workspace_app_statuses_pkey PRIMARY KEY (id);
|
||||
UniqueWorkspaceAppsAgentIDSlugIndex UniqueConstraint = "workspace_apps_agent_id_slug_idx" // ALTER TABLE ONLY workspace_apps ADD CONSTRAINT workspace_apps_agent_id_slug_idx UNIQUE (agent_id, slug);
|
||||
UniqueWorkspaceAppsPkey UniqueConstraint = "workspace_apps_pkey" // ALTER TABLE ONLY workspace_apps ADD CONSTRAINT workspace_apps_pkey PRIMARY KEY (id);
|
||||
UniqueWorkspaceBuildOrchestrationsChildBuildIDKey UniqueConstraint = "workspace_build_orchestrations_child_build_id_key" // ALTER TABLE ONLY workspace_build_orchestrations ADD CONSTRAINT workspace_build_orchestrations_child_build_id_key UNIQUE (child_build_id);
|
||||
UniqueWorkspaceBuildOrchestrationsParentBuildIDKey UniqueConstraint = "workspace_build_orchestrations_parent_build_id_key" // ALTER TABLE ONLY workspace_build_orchestrations ADD CONSTRAINT workspace_build_orchestrations_parent_build_id_key UNIQUE (parent_build_id);
|
||||
UniqueWorkspaceBuildOrchestrationsPkey UniqueConstraint = "workspace_build_orchestrations_pkey" // ALTER TABLE ONLY workspace_build_orchestrations ADD CONSTRAINT workspace_build_orchestrations_pkey PRIMARY KEY (id);
|
||||
UniqueWorkspaceBuildParametersWorkspaceBuildIDNameKey UniqueConstraint = "workspace_build_parameters_workspace_build_id_name_key" // ALTER TABLE ONLY workspace_build_parameters ADD CONSTRAINT workspace_build_parameters_workspace_build_id_name_key UNIQUE (workspace_build_id, name);
|
||||
UniqueWorkspaceBuildsIDWorkspaceIDKey UniqueConstraint = "workspace_builds_id_workspace_id_key" // ALTER TABLE ONLY workspace_builds ADD CONSTRAINT workspace_builds_id_workspace_id_key UNIQUE (id, workspace_id);
|
||||
UniqueWorkspaceBuildsJobIDKey UniqueConstraint = "workspace_builds_job_id_key" // ALTER TABLE ONLY workspace_builds ADD CONSTRAINT workspace_builds_job_id_key UNIQUE (job_id);
|
||||
UniqueWorkspaceBuildsPkey UniqueConstraint = "workspace_builds_pkey" // ALTER TABLE ONLY workspace_builds ADD CONSTRAINT workspace_builds_pkey PRIMARY KEY (id);
|
||||
UniqueWorkspaceBuildsWorkspaceIDBuildNumberKey UniqueConstraint = "workspace_builds_workspace_id_build_number_key" // ALTER TABLE ONLY workspace_builds ADD CONSTRAINT workspace_builds_workspace_id_build_number_key UNIQUE (workspace_id, build_number);
|
||||
UniqueWorkspaceProxiesPkey UniqueConstraint = "workspace_proxies_pkey" // ALTER TABLE ONLY workspace_proxies ADD CONSTRAINT workspace_proxies_pkey PRIMARY KEY (id);
|
||||
UniqueWorkspaceProxiesRegionIDUnique UniqueConstraint = "workspace_proxies_region_id_unique" // ALTER TABLE ONLY workspace_proxies ADD CONSTRAINT workspace_proxies_region_id_unique UNIQUE (region_id);
|
||||
UniqueWorkspaceResourceMetadataName UniqueConstraint = "workspace_resource_metadata_name" // ALTER TABLE ONLY workspace_resource_metadata ADD CONSTRAINT workspace_resource_metadata_name UNIQUE (workspace_resource_id, key);
|
||||
UniqueWorkspaceResourceMetadataPkey UniqueConstraint = "workspace_resource_metadata_pkey" // ALTER TABLE ONLY workspace_resource_metadata ADD CONSTRAINT workspace_resource_metadata_pkey PRIMARY KEY (id);
|
||||
UniqueWorkspaceResourcesPkey UniqueConstraint = "workspace_resources_pkey" // ALTER TABLE ONLY workspace_resources ADD CONSTRAINT workspace_resources_pkey PRIMARY KEY (id);
|
||||
UniqueWorkspacesPkey UniqueConstraint = "workspaces_pkey" // ALTER TABLE ONLY workspaces ADD CONSTRAINT workspaces_pkey PRIMARY KEY (id);
|
||||
UniqueAIGatewayKeysHashedSecretIndex UniqueConstraint = "ai_gateway_keys_hashed_secret_idx" // CREATE UNIQUE INDEX ai_gateway_keys_hashed_secret_idx ON ai_gateway_keys USING btree (hashed_secret);
|
||||
UniqueAIGatewayKeysNameIndex UniqueConstraint = "ai_gateway_keys_name_idx" // CREATE UNIQUE INDEX ai_gateway_keys_name_idx ON ai_gateway_keys USING btree (lower(name));
|
||||
UniqueAIGatewayKeysSecretPrefixIndex UniqueConstraint = "ai_gateway_keys_secret_prefix_idx" // CREATE UNIQUE INDEX ai_gateway_keys_secret_prefix_idx ON ai_gateway_keys USING btree (secret_prefix);
|
||||
UniqueAIProvidersNameUnique UniqueConstraint = "ai_providers_name_unique" // CREATE UNIQUE INDEX ai_providers_name_unique ON ai_providers USING btree (name) WHERE (deleted = false);
|
||||
UniqueIndexAPIKeyName UniqueConstraint = "idx_api_key_name" // CREATE UNIQUE INDEX idx_api_key_name ON api_keys USING btree (user_id, token_name) WHERE (login_type = 'token'::login_type);
|
||||
UniqueIndexChatDebugRunsIDChat UniqueConstraint = "idx_chat_debug_runs_id_chat" // CREATE UNIQUE INDEX idx_chat_debug_runs_id_chat ON chat_debug_runs USING btree (id, chat_id);
|
||||
UniqueIndexChatDebugStepsRunStep UniqueConstraint = "idx_chat_debug_steps_run_step" // CREATE UNIQUE INDEX idx_chat_debug_steps_run_step ON chat_debug_steps USING btree (run_id, step_number);
|
||||
UniqueIndexChatModelConfigsSingleDefault UniqueConstraint = "idx_chat_model_configs_single_default" // CREATE UNIQUE INDEX idx_chat_model_configs_single_default ON chat_model_configs USING btree (organization_id) WHERE ((is_default = true) AND (deleted = false));
|
||||
UniqueIndexConnectionLogsConnectionIDWorkspaceIDAgentName UniqueConstraint = "idx_connection_logs_connection_id_workspace_id_agent_name" // CREATE UNIQUE INDEX idx_connection_logs_connection_id_workspace_id_agent_name ON connection_logs USING btree (connection_id, workspace_id, agent_name);
|
||||
UniqueIndexCustomRolesNameLowerOrganizationID UniqueConstraint = "idx_custom_roles_name_lower_organization_id" // CREATE UNIQUE INDEX idx_custom_roles_name_lower_organization_id ON custom_roles USING btree (lower(name), COALESCE(organization_id, '00000000-0000-0000-0000-000000000000'::uuid));
|
||||
UniqueIndexOrganizationNameLower UniqueConstraint = "idx_organization_name_lower" // CREATE UNIQUE INDEX idx_organization_name_lower ON organizations USING btree (lower(name)) WHERE (deleted = false);
|
||||
UniqueIndexProvisionerDaemonsOrgNameOwnerKey UniqueConstraint = "idx_provisioner_daemons_org_name_owner_key" // CREATE UNIQUE INDEX idx_provisioner_daemons_org_name_owner_key ON provisioner_daemons USING btree (organization_id, name, lower(COALESCE((tags ->> 'owner'::text), ''::text)));
|
||||
UniqueIndexTemplateVersionPresetsDefault UniqueConstraint = "idx_template_version_presets_default" // CREATE UNIQUE INDEX idx_template_version_presets_default ON template_version_presets USING btree (template_version_id) WHERE (is_default = true);
|
||||
UniqueIndexUniquePresetName UniqueConstraint = "idx_unique_preset_name" // CREATE UNIQUE INDEX idx_unique_preset_name ON template_version_presets USING btree (name, template_version_id);
|
||||
UniqueIndexUsageEventsAgentRuntime UniqueConstraint = "idx_usage_events_agent_runtime" // CREATE UNIQUE INDEX idx_usage_events_agent_runtime ON usage_events USING btree (event_type, created_at) WHERE (event_type = 'hb_agent_runtime_v1'::text);
|
||||
UniqueIndexUsersEmail UniqueConstraint = "idx_users_email" // CREATE UNIQUE INDEX idx_users_email ON users USING btree (email) WHERE ((deleted = false) AND (email <> ''::text));
|
||||
UniqueIndexUsersUsername UniqueConstraint = "idx_users_username" // CREATE UNIQUE INDEX idx_users_username ON users USING btree (username) WHERE (deleted = false);
|
||||
UniqueNotificationMessagesDedupeHashIndex UniqueConstraint = "notification_messages_dedupe_hash_idx" // CREATE UNIQUE INDEX notification_messages_dedupe_hash_idx ON notification_messages USING btree (dedupe_hash);
|
||||
UniqueOrganizationsSingleDefaultOrg UniqueConstraint = "organizations_single_default_org" // CREATE UNIQUE INDEX organizations_single_default_org ON organizations USING btree (is_default) WHERE (is_default = true);
|
||||
UniqueProvisionerKeysOrganizationIDNameIndex UniqueConstraint = "provisioner_keys_organization_id_name_idx" // CREATE UNIQUE INDEX provisioner_keys_organization_id_name_idx ON provisioner_keys USING btree (organization_id, lower((name)::text));
|
||||
UniqueTasksOwnerIDNameUniqueIndex UniqueConstraint = "tasks_owner_id_name_unique_idx" // CREATE UNIQUE INDEX tasks_owner_id_name_unique_idx ON tasks USING btree (owner_id, lower(name)) WHERE (deleted_at IS NULL);
|
||||
UniqueTemplateUsageStatsStartTimeTemplateIDUserIDIndex UniqueConstraint = "template_usage_stats_start_time_template_id_user_id_idx" // CREATE UNIQUE INDEX template_usage_stats_start_time_template_id_user_id_idx ON template_usage_stats USING btree (start_time, template_id, user_id);
|
||||
UniqueTemplatesOrganizationIDNameIndex UniqueConstraint = "templates_organization_id_name_idx" // CREATE UNIQUE INDEX templates_organization_id_name_idx ON templates USING btree (organization_id, lower((name)::text)) WHERE (deleted = false);
|
||||
UniqueUserLinksLinkedIDLoginTypeIndex UniqueConstraint = "user_links_linked_id_login_type_idx" // CREATE UNIQUE INDEX user_links_linked_id_login_type_idx ON user_links USING btree (linked_id, login_type) WHERE (linked_id <> ''::text);
|
||||
UniqueUserSecretsUserEnvNameIndex UniqueConstraint = "user_secrets_user_env_name_idx" // CREATE UNIQUE INDEX user_secrets_user_env_name_idx ON user_secrets USING btree (user_id, env_name) WHERE (env_name <> ''::text);
|
||||
UniqueUserSecretsUserFilePathIndex UniqueConstraint = "user_secrets_user_file_path_idx" // CREATE UNIQUE INDEX user_secrets_user_file_path_idx ON user_secrets USING btree (user_id, file_path) WHERE (file_path <> ''::text);
|
||||
UniqueUserSecretsUserNameIndex UniqueConstraint = "user_secrets_user_name_idx" // CREATE UNIQUE INDEX user_secrets_user_name_idx ON user_secrets USING btree (user_id, name);
|
||||
UniqueUserSkillsUserIDNameIndex UniqueConstraint = "user_skills_user_id_name_idx" // CREATE UNIQUE INDEX user_skills_user_id_name_idx ON user_skills USING btree (user_id, name);
|
||||
UniqueUsersEmailLowerIndex UniqueConstraint = "users_email_lower_idx" // CREATE UNIQUE INDEX users_email_lower_idx ON users USING btree (lower(email)) WHERE ((deleted = false) AND (email <> ''::text));
|
||||
UniqueUsersUsernameLowerIndex UniqueConstraint = "users_username_lower_idx" // CREATE UNIQUE INDEX users_username_lower_idx ON users USING btree (lower(username)) WHERE (deleted = false);
|
||||
UniqueWebpushSubscriptionsUserIDEndpointIndex UniqueConstraint = "webpush_subscriptions_user_id_endpoint_idx" // CREATE UNIQUE INDEX webpush_subscriptions_user_id_endpoint_idx ON webpush_subscriptions USING btree (user_id, endpoint);
|
||||
UniqueWorkspaceAppAuditSessionsUniqueIndex UniqueConstraint = "workspace_app_audit_sessions_unique_index" // CREATE UNIQUE INDEX workspace_app_audit_sessions_unique_index ON workspace_app_audit_sessions USING btree (agent_id, app_id, user_id, ip, user_agent, slug_or_port, status_code);
|
||||
UniqueWorkspaceProxiesLowerNameIndex UniqueConstraint = "workspace_proxies_lower_name_idx" // CREATE UNIQUE INDEX workspace_proxies_lower_name_idx ON workspace_proxies USING btree (lower(name)) WHERE (deleted = false);
|
||||
UniqueWorkspacesOwnerIDLowerIndex UniqueConstraint = "workspaces_owner_id_lower_idx" // CREATE UNIQUE INDEX workspaces_owner_id_lower_idx ON workspaces USING btree (owner_id, lower((name)::text)) WHERE (deleted = false);
|
||||
)
|
||||
|
||||
+298
-414
@@ -634,42 +634,6 @@ func validateChatPlanMode(mode codersdk.ChatPlanMode) bool {
|
||||
}
|
||||
}
|
||||
|
||||
type parsedChatModelOverride struct {
|
||||
modelConfigID *uuid.UUID
|
||||
reasoningEffort *string
|
||||
}
|
||||
|
||||
func parseChatModelOverride(raw string) (parsedChatModelOverride, error) {
|
||||
trimmed := strings.TrimSpace(raw)
|
||||
if trimmed == "" {
|
||||
return parsedChatModelOverride{}, nil
|
||||
}
|
||||
rawID, rawEffort, hasEffort := strings.Cut(trimmed, ":")
|
||||
modelConfigID, err := uuid.Parse(rawID)
|
||||
if err != nil {
|
||||
return parsedChatModelOverride{}, xerrors.Errorf("parse chat model override: %w", err)
|
||||
}
|
||||
if hasEffort && rawEffort == "" {
|
||||
return parsedChatModelOverride{}, xerrors.New("parse chat model override: reasoning effort is empty")
|
||||
}
|
||||
parsed := parsedChatModelOverride{modelConfigID: &modelConfigID}
|
||||
if hasEffort {
|
||||
parsed.reasoningEffort = &rawEffort
|
||||
}
|
||||
return parsed, nil
|
||||
}
|
||||
|
||||
func formatChatModelOverride(id *uuid.UUID, effort *string) string {
|
||||
if id == nil {
|
||||
return ""
|
||||
}
|
||||
formatted := id.String()
|
||||
if effort != nil {
|
||||
formatted += ":" + *effort
|
||||
}
|
||||
return formatted
|
||||
}
|
||||
|
||||
func lookupEnabledChatModelConfigByID(
|
||||
ctx context.Context,
|
||||
db database.Store,
|
||||
@@ -763,31 +727,6 @@ func validateChatModelOverride(
|
||||
return validateChatModelOverrideEffort(modelConfig, effort)
|
||||
}
|
||||
|
||||
func (api *API) getChatModelOverrideConfig(
|
||||
ctx context.Context,
|
||||
settingName string,
|
||||
getter func(context.Context) (string, error),
|
||||
) (*uuid.UUID, *string, bool, error) {
|
||||
raw, err := getter(ctx)
|
||||
if err != nil {
|
||||
return nil, nil, false, xerrors.Errorf("get %s model override: %w", settingName, err)
|
||||
}
|
||||
parsed, err := parseChatModelOverride(raw)
|
||||
if err != nil {
|
||||
// Degrade malformed values to unset so the admin settings page
|
||||
// remains accessible and the bad value can be cleared.
|
||||
api.Logger.Warn(
|
||||
ctx,
|
||||
"malformed model override in site config, treating as unset",
|
||||
slog.F("setting", settingName),
|
||||
slog.F("raw_value", raw),
|
||||
slog.Error(err),
|
||||
)
|
||||
return nil, nil, true, nil
|
||||
}
|
||||
return parsed.modelConfigID, parsed.reasoningEffort, false, nil
|
||||
}
|
||||
|
||||
func parseChatModelOverrideContext(raw string) (codersdk.ChatModelOverrideContext, error) {
|
||||
overrideContext := codersdk.ChatModelOverrideContext(raw)
|
||||
if overrideContext.Valid() {
|
||||
@@ -796,73 +735,6 @@ func parseChatModelOverrideContext(raw string) (codersdk.ChatModelOverrideContex
|
||||
return "", xerrors.Errorf("unknown chat model override context %q", raw)
|
||||
}
|
||||
|
||||
type chatModelOverrideSiteConfig struct {
|
||||
label string
|
||||
getter func(context.Context) (string, error)
|
||||
upsert func(context.Context, string) error
|
||||
}
|
||||
|
||||
func (api *API) chatModelOverrideSiteConfig(
|
||||
overrideContext codersdk.ChatModelOverrideContext,
|
||||
) (chatModelOverrideSiteConfig, error) {
|
||||
switch overrideContext {
|
||||
case codersdk.ChatModelOverrideContextGeneral:
|
||||
return chatModelOverrideSiteConfig{
|
||||
label: "general",
|
||||
getter: api.Database.GetChatGeneralModelOverride,
|
||||
upsert: api.Database.UpsertChatGeneralModelOverride,
|
||||
}, nil
|
||||
case codersdk.ChatModelOverrideContextExplore:
|
||||
return chatModelOverrideSiteConfig{
|
||||
label: "explore",
|
||||
getter: api.Database.GetChatExploreModelOverride,
|
||||
upsert: api.Database.UpsertChatExploreModelOverride,
|
||||
}, nil
|
||||
case codersdk.ChatModelOverrideContextTitleGeneration:
|
||||
return chatModelOverrideSiteConfig{
|
||||
label: "title generation",
|
||||
getter: api.Database.GetChatTitleGenerationModelOverride,
|
||||
upsert: api.Database.UpsertChatTitleGenerationModelOverride,
|
||||
}, nil
|
||||
case codersdk.ChatModelOverrideContextCompaction:
|
||||
return chatModelOverrideSiteConfig{
|
||||
label: "compaction",
|
||||
getter: api.Database.GetChatCompactionModelOverride,
|
||||
upsert: api.Database.UpsertChatCompactionModelOverride,
|
||||
}, nil
|
||||
default:
|
||||
return chatModelOverrideSiteConfig{}, xerrors.Errorf(
|
||||
"unknown chat model override context %q",
|
||||
overrideContext,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func (api *API) readChatModelOverrideConfig(
|
||||
ctx context.Context,
|
||||
overrideContext codersdk.ChatModelOverrideContext,
|
||||
) (*uuid.UUID, *string, bool, string, error) {
|
||||
siteConfig, err := api.chatModelOverrideSiteConfig(overrideContext)
|
||||
if err != nil {
|
||||
return nil, nil, false, "", err
|
||||
}
|
||||
id, effort, isMalformed, err := api.getChatModelOverrideConfig(ctx, siteConfig.label, siteConfig.getter)
|
||||
return id, effort, isMalformed, siteConfig.label, err
|
||||
}
|
||||
|
||||
func (api *API) upsertChatModelOverrideConfig(
|
||||
ctx context.Context,
|
||||
overrideContext codersdk.ChatModelOverrideContext,
|
||||
modelConfigID *uuid.UUID,
|
||||
reasoningEffort *string,
|
||||
) (string, error) {
|
||||
siteConfig, err := api.chatModelOverrideSiteConfig(overrideContext)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return siteConfig.label, siteConfig.upsert(ctx, formatChatModelOverride(modelConfigID, reasoningEffort))
|
||||
}
|
||||
|
||||
var chatPersonalModelOverrideContexts = []codersdk.ChatPersonalModelOverrideContext{
|
||||
codersdk.ChatPersonalModelOverrideContextRoot,
|
||||
codersdk.ChatPersonalModelOverrideContextGeneral,
|
||||
@@ -891,87 +763,73 @@ func defaultChatPersonalModelOverrideMode(
|
||||
return codersdk.ChatPersonalModelOverrideModeDeploymentDefault
|
||||
}
|
||||
|
||||
func parseChatPersonalModelOverrideValue(
|
||||
raw string,
|
||||
overrideContext codersdk.ChatPersonalModelOverrideContext,
|
||||
) chatd.ParsedChatPersonalModelOverride {
|
||||
defaultMode := defaultChatPersonalModelOverrideMode(overrideContext)
|
||||
parsed := chatd.ParseChatPersonalModelOverride(raw, defaultMode)
|
||||
if overrideContext == codersdk.ChatPersonalModelOverrideContextRoot &&
|
||||
parsed.Mode == codersdk.ChatPersonalModelOverrideModeDeploymentDefault {
|
||||
return chatd.ParsedChatPersonalModelOverride{
|
||||
Mode: defaultMode,
|
||||
Malformed: true,
|
||||
}
|
||||
}
|
||||
return parsed
|
||||
}
|
||||
|
||||
func formatChatPersonalModelOverrideValue(
|
||||
mode codersdk.ChatPersonalModelOverrideMode,
|
||||
modelConfigID string,
|
||||
reasoningEffort *string,
|
||||
) string {
|
||||
if mode == codersdk.ChatPersonalModelOverrideModeModel {
|
||||
value := string(mode) + ":" + strings.TrimSpace(modelConfigID)
|
||||
if reasoningEffort != nil {
|
||||
value += ":" + *reasoningEffort
|
||||
}
|
||||
return value
|
||||
}
|
||||
return string(mode)
|
||||
}
|
||||
|
||||
func chatPersonalModelOverrideResponse(
|
||||
overrideContext codersdk.ChatPersonalModelOverrideContext,
|
||||
raw string,
|
||||
isSet bool,
|
||||
row *database.ChatUserModelOverride,
|
||||
) codersdk.ChatPersonalModelOverride {
|
||||
parsed := parseChatPersonalModelOverrideValue(raw, overrideContext)
|
||||
modelConfigID := ""
|
||||
var reasoningEffort *string
|
||||
if parsed.Mode == codersdk.ChatPersonalModelOverrideModeModel {
|
||||
modelConfigID = parsed.ModelConfigID.String()
|
||||
reasoningEffort = parsed.ReasoningEffort
|
||||
response := codersdk.ChatPersonalModelOverride{
|
||||
Context: overrideContext,
|
||||
Mode: defaultChatPersonalModelOverrideMode(overrideContext),
|
||||
}
|
||||
return codersdk.ChatPersonalModelOverride{
|
||||
Context: overrideContext,
|
||||
Mode: parsed.Mode,
|
||||
ModelConfigID: modelConfigID,
|
||||
ReasoningEffort: reasoningEffort,
|
||||
IsSet: isSet,
|
||||
IsMalformed: parsed.Malformed,
|
||||
if row == nil {
|
||||
return response
|
||||
}
|
||||
response.Mode = codersdk.ChatPersonalModelOverrideMode(row.Mode)
|
||||
response.IsSet = true
|
||||
if row.ModelConfigID.Valid {
|
||||
response.ModelConfigID = row.ModelConfigID.UUID.String()
|
||||
}
|
||||
if row.ReasoningEffort.Valid {
|
||||
response.ReasoningEffort = &row.ReasoningEffort.String
|
||||
}
|
||||
return response
|
||||
}
|
||||
|
||||
func derefOrEmpty(value *string) string {
|
||||
if value == nil {
|
||||
return ""
|
||||
}
|
||||
return *value
|
||||
}
|
||||
|
||||
func chatOrganizationModelOverrideResponse(
|
||||
row database.ChatOrganizationModelOverride,
|
||||
) codersdk.ChatModelOverrideResponse {
|
||||
response := codersdk.ChatModelOverrideResponse{
|
||||
Context: codersdk.ChatModelOverrideContext(row.Context),
|
||||
ModelConfigID: row.ModelConfigID.String(),
|
||||
}
|
||||
if row.ReasoningEffort.Valid {
|
||||
response.ReasoningEffort = &row.ReasoningEffort.String
|
||||
}
|
||||
return response
|
||||
}
|
||||
|
||||
func (api *API) chatPersonalModelOverrideDeploymentDefaultResponse(
|
||||
ctx context.Context,
|
||||
organizationID uuid.UUID,
|
||||
overrideContext codersdk.ChatModelOverrideContext,
|
||||
) (codersdk.ChatModelOverrideResponse, error) {
|
||||
// The deployment defaults are global chat configuration, not user-owned
|
||||
// resources. Users may read these values here because the personal settings
|
||||
// UI must explain what deployment_default resolves to.
|
||||
//nolint:gocritic // System context is required to read deployment config.
|
||||
modelConfigID, reasoningEffort, isMalformed, _, err := api.readChatModelOverrideConfig(
|
||||
dbauthz.AsSystemRestricted(ctx),
|
||||
overrideContext,
|
||||
)
|
||||
row, err := api.Database.GetChatOrganizationModelOverride(ctx, database.GetChatOrganizationModelOverrideParams{
|
||||
OrganizationID: organizationID,
|
||||
Context: string(overrideContext),
|
||||
})
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return codersdk.ChatModelOverrideResponse{Context: overrideContext}, nil
|
||||
}
|
||||
if err != nil {
|
||||
return codersdk.ChatModelOverrideResponse{}, err
|
||||
}
|
||||
return codersdk.ChatModelOverrideResponse{
|
||||
Context: overrideContext,
|
||||
ModelConfigID: formatChatModelOverride(modelConfigID, nil),
|
||||
ReasoningEffort: reasoningEffort,
|
||||
IsMalformed: isMalformed,
|
||||
}, nil
|
||||
return chatOrganizationModelOverrideResponse(row), nil
|
||||
}
|
||||
|
||||
func (api *API) chatPersonalModelOverrideDeploymentDefaults(
|
||||
ctx context.Context,
|
||||
organizationID uuid.UUID,
|
||||
) (codersdk.ChatPersonalModelOverrideDeploymentDefaults, error) {
|
||||
general, err := api.chatPersonalModelOverrideDeploymentDefaultResponse(
|
||||
ctx,
|
||||
organizationID,
|
||||
codersdk.ChatModelOverrideContextGeneral,
|
||||
)
|
||||
if err != nil {
|
||||
@@ -979,6 +837,7 @@ func (api *API) chatPersonalModelOverrideDeploymentDefaults(
|
||||
}
|
||||
explore, err := api.chatPersonalModelOverrideDeploymentDefaultResponse(
|
||||
ctx,
|
||||
organizationID,
|
||||
codersdk.ChatModelOverrideContextExplore,
|
||||
)
|
||||
if err != nil {
|
||||
@@ -1010,18 +869,6 @@ const (
|
||||
chatModelConfigUnavailableOutsideOrganization chatModelConfigUnavailableReason = "outside_organization"
|
||||
)
|
||||
|
||||
func defaultOrganizationID(
|
||||
ctx context.Context,
|
||||
db database.Store,
|
||||
) (uuid.UUID, error) {
|
||||
//nolint:gocritic // Runtime configuration must be independent of caller permissions.
|
||||
organization, err := db.GetDefaultOrganization(dbauthz.AsChatd(ctx))
|
||||
if err != nil {
|
||||
return uuid.Nil, err
|
||||
}
|
||||
return organization.ID, nil
|
||||
}
|
||||
|
||||
// getUserChatProviderAvailability returns the enabled chat providers and models
|
||||
// the user can access in one organization. Provider configuration uses Chatd
|
||||
// access. Model configs and user keys use the caller's authorization context.
|
||||
@@ -4353,9 +4200,10 @@ func (api *API) resolveCreateChatModelConfigID(
|
||||
return id, nil, status, resp
|
||||
}
|
||||
|
||||
raw, err := api.Database.GetUserChatPersonalModelOverride(ctx, database.GetUserChatPersonalModelOverrideParams{
|
||||
UserID: userID,
|
||||
Key: chatd.ChatPersonalModelOverrideKey(codersdk.ChatPersonalModelOverrideContextRoot),
|
||||
override, err := api.Database.GetChatUserModelOverride(ctx, database.GetChatUserModelOverrideParams{
|
||||
UserID: userID,
|
||||
OrganizationID: req.OrganizationID,
|
||||
Context: string(codersdk.ChatPersonalModelOverrideContextRoot),
|
||||
})
|
||||
if err != nil && !errors.Is(err, sql.ErrNoRows) {
|
||||
return uuid.Nil, nil, http.StatusInternalServerError, &codersdk.Response{
|
||||
@@ -4364,50 +4212,43 @@ func (api *API) resolveCreateChatModelConfigID(
|
||||
}
|
||||
}
|
||||
if err == nil {
|
||||
parsed := parseChatPersonalModelOverrideValue(
|
||||
raw,
|
||||
codersdk.ChatPersonalModelOverrideContextRoot,
|
||||
)
|
||||
if parsed.Malformed {
|
||||
api.Logger.Debug(
|
||||
ctx,
|
||||
"unsupported personal root model override mode, using default model",
|
||||
slog.F("user_id", userID),
|
||||
slog.F("raw_value", raw),
|
||||
)
|
||||
}
|
||||
switch parsed.Mode {
|
||||
switch codersdk.ChatPersonalModelOverrideMode(override.Mode) {
|
||||
case codersdk.ChatPersonalModelOverrideModeChatDefault:
|
||||
// Root chat_default uses the chat organization default.
|
||||
case codersdk.ChatPersonalModelOverrideModeModel:
|
||||
_, reason, err := api.userCanUseChatModelConfig(
|
||||
ctx,
|
||||
userID,
|
||||
req.OrganizationID,
|
||||
parsed.ModelConfigID,
|
||||
)
|
||||
if err != nil {
|
||||
return uuid.Nil, nil, http.StatusInternalServerError, &codersdk.Response{
|
||||
Message: "Failed to resolve chat model config.",
|
||||
Detail: err.Error(),
|
||||
if override.ModelConfigID.Valid {
|
||||
_, reason, err := api.userCanUseChatModelConfig(
|
||||
ctx,
|
||||
userID,
|
||||
req.OrganizationID,
|
||||
override.ModelConfigID.UUID,
|
||||
)
|
||||
if err != nil {
|
||||
return uuid.Nil, nil, http.StatusInternalServerError, &codersdk.Response{
|
||||
Message: "Failed to resolve chat model config.",
|
||||
Detail: err.Error(),
|
||||
}
|
||||
}
|
||||
if reason == chatModelConfigAvailable {
|
||||
var effort *string
|
||||
if override.ReasoningEffort.Valid {
|
||||
effort = &override.ReasoningEffort.String
|
||||
}
|
||||
return override.ModelConfigID.UUID, effort, 0, nil
|
||||
}
|
||||
api.Logger.Debug(
|
||||
ctx,
|
||||
"personal root model override is unavailable, using default model",
|
||||
slog.F("user_id", userID),
|
||||
slog.F("model_config_id", override.ModelConfigID.UUID),
|
||||
slog.F("reason", reason),
|
||||
)
|
||||
}
|
||||
if reason == chatModelConfigAvailable {
|
||||
return parsed.ModelConfigID, parsed.ReasoningEffort, 0, nil
|
||||
}
|
||||
api.Logger.Debug(
|
||||
ctx,
|
||||
"personal root model override is unavailable, using default model",
|
||||
slog.F("user_id", userID),
|
||||
slog.F("model_config_id", parsed.ModelConfigID),
|
||||
slog.F("reason", reason),
|
||||
)
|
||||
default:
|
||||
api.Logger.Warn(
|
||||
ctx,
|
||||
"unsupported personal root model override mode, using default model",
|
||||
slog.F("user_id", userID),
|
||||
slog.F("mode", parsed.Mode),
|
||||
slog.F("mode", override.Mode),
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -4856,12 +4697,61 @@ func readChatModelOverrideContext(
|
||||
return "", false
|
||||
}
|
||||
|
||||
// @Summary List organization chat model overrides
|
||||
// @ID list-organization-chat-model-overrides
|
||||
// @Security CoderSessionToken
|
||||
// @Tags Chats
|
||||
// @Produce json
|
||||
// @Param organization path string true "Organization name or ID"
|
||||
// @Success 200 {object} codersdk.ChatModelOverridesResponse
|
||||
// @Router /api/experimental/organizations/{organization}/chats/model-overrides [get]
|
||||
// @x-apidocgen {"skip": true}
|
||||
//
|
||||
// EXPERIMENTAL: this endpoint is experimental and is subject to change.
|
||||
//
|
||||
//nolint:revive // get-return: revive assumes get* must be a getter, but this is an HTTP handler.
|
||||
func (api *API) getChatModelOverride(rw http.ResponseWriter, r *http.Request) {
|
||||
func (api *API) getOrganizationChatModelOverrides(rw http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
if !api.Authorize(r, policy.ActionRead, rbac.ResourceDeploymentConfig) {
|
||||
organization := httpmw.OrganizationParam(r)
|
||||
rows, err := api.Database.GetChatOrganizationModelOverrides(ctx, organization.ID)
|
||||
if err != nil {
|
||||
if httpapi.Is404Error(err) {
|
||||
httpapi.ResourceNotFound(rw)
|
||||
return
|
||||
}
|
||||
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
|
||||
Message: "Internal error fetching model overrides.",
|
||||
Detail: err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
response := codersdk.ChatModelOverridesResponse{
|
||||
Overrides: make([]codersdk.ChatModelOverrideResponse, 0, len(rows)),
|
||||
}
|
||||
for _, row := range rows {
|
||||
response.Overrides = append(response.Overrides, chatOrganizationModelOverrideResponse(row))
|
||||
}
|
||||
httpapi.Write(ctx, rw, http.StatusOK, response)
|
||||
}
|
||||
|
||||
// @Summary Update organization chat model override
|
||||
// @ID update-organization-chat-model-override
|
||||
// @Security CoderSessionToken
|
||||
// @Tags Chats
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param organization path string true "Organization name or ID"
|
||||
// @Param context path string true "Override context" Enums(general,explore,title_generation,compaction,advisor)
|
||||
// @Param request body codersdk.UpdateChatModelOverrideRequest true "Model override"
|
||||
// @Success 200 {object} codersdk.ChatModelOverrideResponse
|
||||
// @Router /api/experimental/organizations/{organization}/chats/model-overrides/{context} [put]
|
||||
// @x-apidocgen {"skip": true}
|
||||
//
|
||||
// EXPERIMENTAL: this endpoint is experimental and is subject to change.
|
||||
func (api *API) putOrganizationChatModelOverride(rw http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
organization := httpmw.OrganizationParam(r)
|
||||
if !api.Authorize(r, policy.ActionUpdate, rbac.ResourceChatModelConfig.InOrg(organization.ID)) {
|
||||
httpapi.ResourceNotFound(rw)
|
||||
return
|
||||
}
|
||||
@@ -4869,38 +4759,9 @@ func (api *API) getChatModelOverride(rw http.ResponseWriter, r *http.Request) {
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
modelConfigID, reasoningEffort, isMalformed, label, err := api.readChatModelOverrideConfig(ctx, overrideContext)
|
||||
if err != nil {
|
||||
if label == "" {
|
||||
label = string(overrideContext)
|
||||
}
|
||||
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
|
||||
Message: fmt.Sprintf("Internal error fetching %s model override.", label),
|
||||
Detail: err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
resp := codersdk.ChatModelOverrideResponse{
|
||||
Context: overrideContext,
|
||||
ModelConfigID: formatChatModelOverride(modelConfigID, nil),
|
||||
ReasoningEffort: reasoningEffort,
|
||||
IsMalformed: isMalformed,
|
||||
}
|
||||
|
||||
httpapi.Write(ctx, rw, http.StatusOK, resp)
|
||||
}
|
||||
|
||||
// EXPERIMENTAL: this endpoint is experimental and is subject to change.
|
||||
func (api *API) putChatModelOverride(rw http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
if !api.Authorize(r, policy.ActionUpdate, rbac.ResourceDeploymentConfig) {
|
||||
httpapi.Forbidden(rw)
|
||||
return
|
||||
}
|
||||
overrideContext, ok := readChatModelOverrideContext(rw, r)
|
||||
if !ok {
|
||||
if overrideContext == codersdk.ChatModelOverrideContextAdvisor &&
|
||||
!api.Experiments.Enabled(codersdk.ExperimentChatAdvisor) {
|
||||
httpapi.ResourceNotFound(rw)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -4909,54 +4770,80 @@ func (api *API) putChatModelOverride(rw http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
var modelConfigID *uuid.UUID
|
||||
response := codersdk.ChatModelOverrideResponse{Context: overrideContext}
|
||||
trimmedModelConfigID := strings.TrimSpace(req.ModelConfigID)
|
||||
if trimmedModelConfigID != "" {
|
||||
if strings.Contains(trimmedModelConfigID, ":") {
|
||||
if trimmedModelConfigID == "" {
|
||||
if req.ReasoningEffort != nil {
|
||||
httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{
|
||||
Message: "Invalid model_config_id.",
|
||||
Detail: fmt.Sprintf("Value %q is not a valid UUID.", req.ModelConfigID),
|
||||
Message: "reasoning_effort requires model_config_id.",
|
||||
})
|
||||
return
|
||||
}
|
||||
parsedModelConfigID, err := uuid.Parse(trimmedModelConfigID)
|
||||
err := api.Database.DeleteChatOrganizationModelOverride(ctx, database.DeleteChatOrganizationModelOverrideParams{
|
||||
OrganizationID: organization.ID,
|
||||
Context: string(overrideContext),
|
||||
})
|
||||
if err != nil {
|
||||
httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{
|
||||
Message: "Invalid model_config_id.",
|
||||
Detail: fmt.Sprintf("Value %q is not a valid UUID.", req.ModelConfigID),
|
||||
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
|
||||
Message: fmt.Sprintf("Internal error clearing %s model override.", overrideContext),
|
||||
Detail: err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
modelConfigID = &parsedModelConfigID
|
||||
httpapi.Write(ctx, rw, http.StatusOK, response)
|
||||
return
|
||||
}
|
||||
|
||||
defaultOrgID, err := defaultOrganizationID(ctx, api.Database)
|
||||
modelConfigID, err := uuid.Parse(trimmedModelConfigID)
|
||||
if err != nil {
|
||||
httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{
|
||||
Message: "Invalid model_config_id.",
|
||||
Detail: fmt.Sprintf("Value %q is not a valid UUID.", req.ModelConfigID),
|
||||
})
|
||||
return
|
||||
}
|
||||
// The explicit ActionUpdate authorization above gates this endpoint. Look
|
||||
// the referenced model up under a system context so a custom role that
|
||||
// grants update without read can still use the endpoint; organization
|
||||
// ownership is enforced inside the validation.
|
||||
//nolint:gocritic // See above.
|
||||
status, validationResponse := validateChatModelOverride(
|
||||
dbauthz.AsSystemRestricted(ctx),
|
||||
api.Database,
|
||||
organization.ID,
|
||||
&modelConfigID,
|
||||
req.ReasoningEffort,
|
||||
)
|
||||
if validationResponse != nil {
|
||||
httpapi.Write(ctx, rw, status, *validationResponse)
|
||||
return
|
||||
}
|
||||
|
||||
row := database.ChatOrganizationModelOverride{
|
||||
OrganizationID: organization.ID,
|
||||
Context: string(overrideContext),
|
||||
ModelConfigID: modelConfigID,
|
||||
ReasoningEffort: sql.NullString{String: derefOrEmpty(req.ReasoningEffort), Valid: req.ReasoningEffort != nil},
|
||||
}
|
||||
err = api.Database.UpsertChatOrganizationModelOverride(ctx, database.UpsertChatOrganizationModelOverrideParams{
|
||||
OrganizationID: row.OrganizationID,
|
||||
Context: row.Context,
|
||||
ModelConfigID: row.ModelConfigID,
|
||||
ReasoningEffort: row.ReasoningEffort,
|
||||
})
|
||||
if database.IsForeignKeyViolation(err) {
|
||||
httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{Message: "Invalid model_config_id."})
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
|
||||
Message: "Internal error validating model config override.",
|
||||
Message: fmt.Sprintf("Internal error updating %s model override.", overrideContext),
|
||||
Detail: err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
status, resp := validateChatModelOverride(ctx, api.Database, defaultOrgID, modelConfigID, req.ReasoningEffort)
|
||||
if resp != nil {
|
||||
httpapi.Write(ctx, rw, status, *resp)
|
||||
return
|
||||
}
|
||||
|
||||
label, err := api.upsertChatModelOverrideConfig(ctx, overrideContext, modelConfigID, req.ReasoningEffort)
|
||||
if err != nil {
|
||||
if label == "" {
|
||||
label = string(overrideContext)
|
||||
}
|
||||
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
|
||||
Message: fmt.Sprintf("Internal error updating %s model override.", label),
|
||||
Detail: err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
rw.WriteHeader(http.StatusNoContent)
|
||||
response = chatOrganizationModelOverrideResponse(row)
|
||||
httpapi.Write(ctx, rw, http.StatusOK, response)
|
||||
}
|
||||
|
||||
func readChatPersonalModelOverrideContext(
|
||||
@@ -5025,12 +4912,24 @@ func (api *API) putChatPersonalModelOverridesAdminSettings(rw http.ResponseWrite
|
||||
rw.WriteHeader(http.StatusNoContent)
|
||||
}
|
||||
|
||||
// @Summary Get organization member chat model overrides
|
||||
// @ID get-organization-member-chat-model-overrides
|
||||
// @Security CoderSessionToken
|
||||
// @Tags Chats
|
||||
// @Produce json
|
||||
// @Param organization path string true "Organization name or ID"
|
||||
// @Param user path string true "User name, ID, or me"
|
||||
// @Success 200 {object} codersdk.UserChatPersonalModelOverridesResponse
|
||||
// @Router /api/experimental/organizations/{organization}/members/{user}/chats/model-overrides [get]
|
||||
// @x-apidocgen {"skip": true}
|
||||
//
|
||||
// EXPERIMENTAL: this endpoint is experimental and is subject to change.
|
||||
//
|
||||
//nolint:revive // get-return: revive assumes get* must be a getter, but this is an HTTP handler.
|
||||
func (api *API) getUserChatPersonalModelOverrides(rw http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
apiKey := httpmw.APIKey(r)
|
||||
organization := httpmw.OrganizationParam(r)
|
||||
member := httpmw.OrganizationMemberParam(r)
|
||||
|
||||
enabled, err := api.Database.GetChatPersonalModelOverridesEnabled(ctx)
|
||||
if err != nil {
|
||||
@@ -5041,32 +4940,30 @@ func (api *API) getUserChatPersonalModelOverrides(rw http.ResponseWriter, r *htt
|
||||
return
|
||||
}
|
||||
|
||||
rows, err := api.Database.ListUserChatPersonalModelOverrides(ctx, apiKey.UserID)
|
||||
rows, err := api.Database.GetChatUserModelOverrides(ctx, database.GetChatUserModelOverridesParams{
|
||||
UserID: member.UserID,
|
||||
OrganizationID: organization.ID,
|
||||
})
|
||||
if err != nil {
|
||||
if httpapi.Is404Error(err) {
|
||||
httpapi.ResourceNotFound(rw)
|
||||
return
|
||||
}
|
||||
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
|
||||
Message: "Internal error fetching user personal model overrides.",
|
||||
Detail: err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
values := make(map[codersdk.ChatPersonalModelOverrideContext]string, len(rows))
|
||||
byContext := make(map[string]database.ChatUserModelOverride, len(rows))
|
||||
for _, row := range rows {
|
||||
rawContext, ok := strings.CutPrefix(row.Key, chatd.ChatPersonalModelOverrideKeyPrefix)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
overrideContext, ok := parseChatPersonalModelOverrideContext(rawContext)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
values[overrideContext] = row.Value
|
||||
byContext[row.Context] = row
|
||||
}
|
||||
|
||||
deploymentDefaults, err := api.chatPersonalModelOverrideDeploymentDefaults(ctx)
|
||||
deploymentDefaults, err := api.chatPersonalModelOverrideDeploymentDefaults(ctx, organization.ID)
|
||||
if err != nil {
|
||||
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
|
||||
Message: "Internal error fetching deployment model defaults.",
|
||||
Message: "Internal error fetching organization model defaults.",
|
||||
Detail: err.Error(),
|
||||
})
|
||||
return
|
||||
@@ -5077,8 +4974,11 @@ func (api *API) getUserChatPersonalModelOverrides(rw http.ResponseWriter, r *htt
|
||||
DeploymentDefaults: deploymentDefaults,
|
||||
}
|
||||
for _, overrideContext := range chatPersonalModelOverrideContexts {
|
||||
raw, isSet := values[overrideContext]
|
||||
override := chatPersonalModelOverrideResponse(overrideContext, raw, isSet)
|
||||
var row *database.ChatUserModelOverride
|
||||
if contextRow, ok := byContext[string(overrideContext)]; ok {
|
||||
row = &contextRow
|
||||
}
|
||||
override := chatPersonalModelOverrideResponse(overrideContext, row)
|
||||
switch overrideContext {
|
||||
case codersdk.ChatPersonalModelOverrideContextRoot:
|
||||
response.Root = override
|
||||
@@ -5091,10 +4991,25 @@ func (api *API) getUserChatPersonalModelOverrides(rw http.ResponseWriter, r *htt
|
||||
httpapi.Write(ctx, rw, http.StatusOK, response)
|
||||
}
|
||||
|
||||
// @Summary Update organization member chat model override
|
||||
// @ID update-organization-member-chat-model-override
|
||||
// @Security CoderSessionToken
|
||||
// @Tags Chats
|
||||
// @Accept json
|
||||
// @Param organization path string true "Organization name or ID"
|
||||
// @Param user path string true "User name, ID, or me"
|
||||
// @Param context path string true "Override context" Enums(root,general,explore)
|
||||
// @Param request body codersdk.UpdateUserChatPersonalModelOverrideRequest true "Personal model override"
|
||||
// @Success 204
|
||||
// @Router /api/experimental/organizations/{organization}/members/{user}/chats/model-overrides/{context} [put]
|
||||
// @x-apidocgen {"skip": true}
|
||||
//
|
||||
// EXPERIMENTAL: this endpoint is experimental and is subject to change.
|
||||
func (api *API) putUserChatPersonalModelOverride(rw http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
apiKey := httpmw.APIKey(r)
|
||||
organization := httpmw.OrganizationParam(r)
|
||||
member := httpmw.OrganizationMemberParam(r)
|
||||
|
||||
enabled, err := api.Database.GetChatPersonalModelOverridesEnabled(ctx)
|
||||
if err != nil {
|
||||
@@ -5104,7 +5019,8 @@ func (api *API) putUserChatPersonalModelOverride(rw http.ResponseWriter, r *http
|
||||
})
|
||||
return
|
||||
}
|
||||
if !enabled {
|
||||
if !enabled && apiKey.UserID == member.UserID &&
|
||||
!api.Authorize(r, policy.ActionUpdate, rbac.ResourceDeploymentConfig) {
|
||||
httpapi.Write(ctx, rw, http.StatusForbidden, codersdk.Response{
|
||||
Message: "An administrator has not enabled user personal model overrides.",
|
||||
})
|
||||
@@ -5121,99 +5037,97 @@ func (api *API) putUserChatPersonalModelOverride(rw http.ResponseWriter, r *http
|
||||
return
|
||||
}
|
||||
|
||||
modelConfigID := ""
|
||||
modelConfigID := uuid.NullUUID{}
|
||||
reasoningEffort := req.ReasoningEffort
|
||||
rawModelConfigID := strings.TrimSpace(req.ModelConfigID)
|
||||
switch req.Mode {
|
||||
case codersdk.ChatPersonalModelOverrideModeChatDefault:
|
||||
if rawModelConfigID != "" {
|
||||
httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{
|
||||
Message: "model_config_id must be empty unless mode is model.",
|
||||
})
|
||||
httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{Message: "model_config_id must be empty unless mode is model."})
|
||||
return
|
||||
}
|
||||
if reasoningEffort != nil {
|
||||
httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{
|
||||
Message: "reasoning_effort requires mode model.",
|
||||
})
|
||||
httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{Message: "reasoning_effort requires mode model."})
|
||||
return
|
||||
}
|
||||
case codersdk.ChatPersonalModelOverrideModeDeploymentDefault:
|
||||
if overrideContext == codersdk.ChatPersonalModelOverrideContextRoot {
|
||||
httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{
|
||||
Message: "deployment_default is not supported for root personal model overrides.",
|
||||
})
|
||||
httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{Message: "deployment_default is not supported for root personal model overrides."})
|
||||
return
|
||||
}
|
||||
if rawModelConfigID != "" {
|
||||
httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{
|
||||
Message: "model_config_id must be empty unless mode is model.",
|
||||
})
|
||||
httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{Message: "model_config_id must be empty unless mode is model."})
|
||||
return
|
||||
}
|
||||
if reasoningEffort != nil {
|
||||
httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{
|
||||
Message: "reasoning_effort requires mode model.",
|
||||
})
|
||||
httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{Message: "reasoning_effort requires mode model."})
|
||||
return
|
||||
}
|
||||
case codersdk.ChatPersonalModelOverrideModeModel:
|
||||
if rawModelConfigID == "" {
|
||||
httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{
|
||||
Message: "model_config_id is required when mode is model.",
|
||||
})
|
||||
httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{Message: "model_config_id is required when mode is model."})
|
||||
return
|
||||
}
|
||||
parsedModelConfigID, err := uuid.Parse(rawModelConfigID)
|
||||
if err != nil {
|
||||
if err != nil || parsedModelConfigID == uuid.Nil {
|
||||
httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{
|
||||
Message: "Invalid model_config_id.",
|
||||
Detail: fmt.Sprintf("Value %q is not a valid UUID.", req.ModelConfigID),
|
||||
})
|
||||
return
|
||||
}
|
||||
if parsedModelConfigID == uuid.Nil {
|
||||
httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{
|
||||
Message: "Invalid model_config_id.",
|
||||
})
|
||||
return
|
||||
// Validate with the target member's ACLs so a model visible only to
|
||||
// an administrator caller is rejected instead of persisted; chatd
|
||||
// resolves the override under the member's actor at runtime.
|
||||
validateCtx := ctx
|
||||
if apiKey.UserID != member.UserID {
|
||||
memberSubject, _, err := httpmw.UserRBACSubject(ctx, api.Database, member.UserID, rbac.ScopeAll)
|
||||
if err != nil {
|
||||
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
|
||||
Message: "Internal error validating model config override.",
|
||||
Detail: err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
validateCtx = dbauthz.As(ctx, memberSubject)
|
||||
}
|
||||
defaultOrgID, err := defaultOrganizationID(ctx, api.Database)
|
||||
if err != nil {
|
||||
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
|
||||
Message: "Failed to resolve default organization.",
|
||||
Detail: err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
modelConfig, status, resp := api.validateUserChatModelConfigAvailable(
|
||||
ctx,
|
||||
apiKey.UserID,
|
||||
defaultOrgID,
|
||||
parsedModelConfigID,
|
||||
modelConfig, status, validationResponse := api.validateUserChatModelConfigAvailable(
|
||||
validateCtx, member.UserID, organization.ID, parsedModelConfigID,
|
||||
)
|
||||
if resp != nil {
|
||||
httpapi.Write(ctx, rw, status, *resp)
|
||||
if validationResponse != nil {
|
||||
httpapi.Write(ctx, rw, status, *validationResponse)
|
||||
return
|
||||
}
|
||||
status, resp = validateChatModelOverrideEffort(modelConfig, reasoningEffort)
|
||||
if resp != nil {
|
||||
httpapi.Write(ctx, rw, status, *resp)
|
||||
status, validationResponse = validateChatModelOverrideEffort(modelConfig, reasoningEffort)
|
||||
if validationResponse != nil {
|
||||
httpapi.Write(ctx, rw, status, *validationResponse)
|
||||
return
|
||||
}
|
||||
modelConfigID = parsedModelConfigID.String()
|
||||
modelConfigID = uuid.NullUUID{UUID: parsedModelConfigID, Valid: true}
|
||||
default:
|
||||
httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{
|
||||
Message: "Invalid personal model override mode.",
|
||||
})
|
||||
httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{Message: "Invalid personal model override mode."})
|
||||
return
|
||||
}
|
||||
|
||||
if err := api.Database.UpsertUserChatPersonalModelOverride(ctx, database.UpsertUserChatPersonalModelOverrideParams{
|
||||
UserID: apiKey.UserID,
|
||||
Key: chatd.ChatPersonalModelOverrideKey(overrideContext),
|
||||
Value: formatChatPersonalModelOverrideValue(req.Mode, modelConfigID, reasoningEffort),
|
||||
}); err != nil {
|
||||
err = api.Database.UpsertChatUserModelOverride(ctx, database.UpsertChatUserModelOverrideParams{
|
||||
UserID: member.UserID,
|
||||
OrganizationID: organization.ID,
|
||||
Context: string(overrideContext),
|
||||
Mode: string(req.Mode),
|
||||
ModelConfigID: modelConfigID,
|
||||
ReasoningEffort: sql.NullString{String: derefOrEmpty(reasoningEffort), Valid: reasoningEffort != nil},
|
||||
})
|
||||
if database.IsForeignKeyViolation(err) {
|
||||
httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{
|
||||
Message: "Invalid model_config_id: model config not found or disabled.",
|
||||
})
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
if httpapi.Is404Error(err) {
|
||||
httpapi.ResourceNotFound(rw)
|
||||
return
|
||||
}
|
||||
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
|
||||
Message: "Internal error updating user personal model override.",
|
||||
Detail: err.Error(),
|
||||
@@ -5433,9 +5347,6 @@ func (api *API) getChatAdvisorConfig(rw http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
resp.MaxUsesPerRun = max(resp.MaxUsesPerRun, 0)
|
||||
resp.MaxOutputTokens = max(resp.MaxOutputTokens, 0)
|
||||
if resp.ModelConfigID == uuid.Nil {
|
||||
resp.ReasoningEffort = nil
|
||||
}
|
||||
resp.Enabled = api.Experiments.Enabled(codersdk.ExperimentChatAdvisor)
|
||||
|
||||
httpapi.Write(ctx, rw, http.StatusOK, resp)
|
||||
@@ -5453,6 +5364,12 @@ func (api *API) putChatAdvisorConfig(rw http.ResponseWriter, r *http.Request) {
|
||||
if !httpapi.Read(ctx, rw, r, &req) {
|
||||
return
|
||||
}
|
||||
if req.DeprecatedModelConfigID != nil || req.DeprecatedReasoningEffort != nil {
|
||||
httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{
|
||||
Message: "Advisor model settings moved to PUT /api/experimental/organizations/{organization}/chats/model-overrides/advisor.",
|
||||
})
|
||||
return
|
||||
}
|
||||
if req.MaxUsesPerRun < 0 {
|
||||
httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{
|
||||
Message: fmt.Sprintf("max_uses_per_run %d must be non-negative.", req.MaxUsesPerRun),
|
||||
@@ -5465,46 +5382,13 @@ func (api *API) putChatAdvisorConfig(rw http.ResponseWriter, r *http.Request) {
|
||||
})
|
||||
return
|
||||
}
|
||||
if req.ModelConfigID == uuid.Nil {
|
||||
if req.ReasoningEffort != nil {
|
||||
httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{
|
||||
Message: "reasoning_effort requires model_config_id.",
|
||||
})
|
||||
return
|
||||
}
|
||||
} else {
|
||||
defaultOrgID, err := defaultOrganizationID(ctx, api.Database)
|
||||
if err != nil {
|
||||
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
|
||||
Message: "Internal error validating advisor model config.",
|
||||
Detail: err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
modelConfig, err := lookupEnabledChatModelConfigByID(ctx, api.Database, req.ModelConfigID)
|
||||
if err == nil && modelConfig.OrganizationID != defaultOrgID {
|
||||
err = sql.ErrNoRows
|
||||
}
|
||||
if err != nil {
|
||||
if errors.Is(err, sql.ErrNoRows) || httpapi.Is404Error(err) {
|
||||
httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{
|
||||
Message: fmt.Sprintf("model_config_id %q does not match any enabled model config.", req.ModelConfigID),
|
||||
})
|
||||
return
|
||||
}
|
||||
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
|
||||
Message: "Internal error validating advisor model config.",
|
||||
Detail: err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
if status, response := validateChatModelOverrideEffort(modelConfig, req.ReasoningEffort); response != nil {
|
||||
httpapi.Write(ctx, rw, status, *response)
|
||||
return
|
||||
}
|
||||
|
||||
runtimeConfig := codersdk.AdvisorConfig{
|
||||
MaxUsesPerRun: req.MaxUsesPerRun,
|
||||
MaxOutputTokens: req.MaxOutputTokens,
|
||||
}
|
||||
|
||||
raw, err := json.Marshal(req)
|
||||
raw, err := json.Marshal(runtimeConfig)
|
||||
if err != nil {
|
||||
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
|
||||
Message: "Internal error encoding advisor configuration.",
|
||||
|
||||
+306
-1068
File diff suppressed because it is too large
Load Diff
@@ -2378,14 +2378,20 @@ type AgentsComputerUseTelemetry struct {
|
||||
ProviderSource string `json:"provider_source"`
|
||||
}
|
||||
|
||||
// AgentsAdvisorOverrideTelemetry describes one organization's advisor model override.
|
||||
type AgentsAdvisorOverrideTelemetry struct {
|
||||
OrganizationID string `json:"organization_id"`
|
||||
Provider string `json:"provider"`
|
||||
Model string `json:"model"`
|
||||
}
|
||||
|
||||
// AgentsAdvisorTelemetry is the value shape for the advisor entry in
|
||||
// Deployment.AgentsExperiments.
|
||||
type AgentsAdvisorTelemetry struct {
|
||||
Enabled bool `json:"enabled"`
|
||||
MaxUsesPerRun int `json:"max_uses_per_run"`
|
||||
MaxOutputTokens int64 `json:"max_output_tokens"`
|
||||
Provider string `json:"provider"`
|
||||
Model string `json:"model"`
|
||||
Enabled bool `json:"enabled"`
|
||||
MaxUsesPerRun int `json:"max_uses_per_run"`
|
||||
MaxOutputTokens int64 `json:"max_output_tokens"`
|
||||
Overrides []AgentsAdvisorOverrideTelemetry `json:"overrides"`
|
||||
}
|
||||
|
||||
// CollectAgentsVirtualDesktop collects the virtual_desktop entry in
|
||||
@@ -2421,9 +2427,8 @@ func CollectAgentsVirtualDesktop(ctx context.Context, opts Options) json.RawMess
|
||||
// Deployment.AgentsExperiments.
|
||||
func CollectAgentsAdvisor(ctx context.Context, opts Options) json.RawMessage {
|
||||
payload := AgentsAdvisorTelemetry{
|
||||
Enabled: opts.Experiments.Enabled(codersdk.ExperimentChatAdvisor),
|
||||
Provider: AgentsExperimentUnknown,
|
||||
Model: AgentsExperimentUnknown,
|
||||
Enabled: opts.Experiments.Enabled(codersdk.ExperimentChatAdvisor),
|
||||
Overrides: []AgentsAdvisorOverrideTelemetry{},
|
||||
}
|
||||
var cfg codersdk.AdvisorConfig
|
||||
raw, err := opts.Database.GetChatAdvisorConfig(ctx)
|
||||
@@ -2434,8 +2439,27 @@ func CollectAgentsAdvisor(ctx context.Context, opts Options) json.RawMessage {
|
||||
} else {
|
||||
payload.MaxUsesPerRun = max(cfg.MaxUsesPerRun, 0)
|
||||
payload.MaxOutputTokens = max(cfg.MaxOutputTokens, 0)
|
||||
payload.Provider, payload.Model = advisorModelTelemetry(ctx, opts.Database, opts.Logger, cfg.ModelConfigID)
|
||||
}
|
||||
|
||||
overrides, err := opts.Database.GetChatOrganizationModelOverridesByContext(ctx, string(codersdk.ChatModelOverrideContextAdvisor))
|
||||
if err != nil {
|
||||
opts.Logger.Warn(ctx, "get chat advisor model overrides for telemetry", slog.Error(err))
|
||||
} else {
|
||||
for _, override := range overrides {
|
||||
// When the override's model is disabled or deleted, the runtime
|
||||
// falls back to the chat model.
|
||||
provider, model := AgentsExperimentAdvisorReuseChatModel, AgentsExperimentAdvisorReuseChatModel
|
||||
if override.ModelAvailable {
|
||||
provider, model = override.ProviderType, override.Model
|
||||
}
|
||||
payload.Overrides = append(payload.Overrides, AgentsAdvisorOverrideTelemetry{
|
||||
OrganizationID: override.OrganizationID.String(),
|
||||
Provider: provider,
|
||||
Model: model,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
val, err := json.Marshal(payload)
|
||||
if err != nil {
|
||||
opts.Logger.Warn(ctx, "marshal agent advisor telemetry", slog.Error(err))
|
||||
@@ -2444,28 +2468,6 @@ func CollectAgentsAdvisor(ctx context.Context, opts Options) json.RawMessage {
|
||||
return val
|
||||
}
|
||||
|
||||
func advisorModelTelemetry(ctx context.Context, db database.Store, log slog.Logger, id uuid.UUID) (provider string, model string) {
|
||||
if id == uuid.Nil {
|
||||
return AgentsExperimentAdvisorReuseChatModel, AgentsExperimentAdvisorReuseChatModel
|
||||
}
|
||||
|
||||
cfg, err := db.GetEnabledChatModelConfigByID(ctx, id)
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
// An inactive override; the runtime falls back to the chat model.
|
||||
return AgentsExperimentAdvisorReuseChatModel, AgentsExperimentAdvisorReuseChatModel
|
||||
}
|
||||
if err != nil {
|
||||
log.Warn(ctx, "resolve chat advisor model config for telemetry", slog.Error(err))
|
||||
return AgentsExperimentUnknown, AgentsExperimentUnknown
|
||||
}
|
||||
providerRow, err := db.GetAIProviderByID(ctx, cfg.AIProviderID.UUID)
|
||||
if err != nil {
|
||||
log.Warn(ctx, "resolve chat advisor model provider for telemetry", slog.Error(err))
|
||||
return AgentsExperimentUnknown, cfg.Model
|
||||
}
|
||||
return string(providerRow.Type), cfg.Model
|
||||
}
|
||||
|
||||
type TelemetryItem struct {
|
||||
Key string `json:"key"`
|
||||
Value string `json:"value"`
|
||||
|
||||
@@ -2382,162 +2382,105 @@ func TestCollectAgentsAdvisor(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
return string(raw)
|
||||
}
|
||||
expectOverrides := func(db *dbmock.MockStore, rows ...database.GetChatOrganizationModelOverridesByContextRow) {
|
||||
db.EXPECT().GetChatOrganizationModelOverridesByContext(gomock.Any(), string(codersdk.ChatModelOverrideContextAdvisor)).Return(rows, nil)
|
||||
}
|
||||
|
||||
t.Run("ReuseChatModel", func(t *testing.T) {
|
||||
t.Run("Defaults", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
db := dbmock.NewMockStore(gomock.NewController(t))
|
||||
db.EXPECT().GetChatAdvisorConfig(gomock.Any()).
|
||||
Return(marshalConfig(t, codersdk.AdvisorConfig{}), nil)
|
||||
db.EXPECT().GetChatAdvisorConfig(gomock.Any()).Return(marshalConfig(t, codersdk.AdvisorConfig{}), nil)
|
||||
expectOverrides(db)
|
||||
|
||||
payload := collect(t, telemetry.Options{Database: db, Logger: testutil.Logger(t)})
|
||||
require.False(t, payload.Enabled)
|
||||
require.Zero(t, payload.MaxUsesPerRun)
|
||||
require.Zero(t, payload.MaxOutputTokens)
|
||||
require.Equal(t, telemetry.AgentsExperimentAdvisorReuseChatModel, payload.Provider)
|
||||
require.Equal(t, telemetry.AgentsExperimentAdvisorReuseChatModel, payload.Model)
|
||||
require.Empty(t, payload.Overrides)
|
||||
})
|
||||
|
||||
t.Run("ModelOverride", func(t *testing.T) {
|
||||
t.Run("ModelOverrides", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
modelID := uuid.New()
|
||||
providerID := uuid.New()
|
||||
org := database.Organization{ID: uuid.New()}
|
||||
db := dbmock.NewMockStore(gomock.NewController(t))
|
||||
db.EXPECT().GetChatAdvisorConfig(gomock.Any()).Return(marshalConfig(t, codersdk.AdvisorConfig{
|
||||
Enabled: true,
|
||||
MaxUsesPerRun: 7,
|
||||
MaxOutputTokens: 2048,
|
||||
ModelConfigID: modelID,
|
||||
}), nil)
|
||||
db.EXPECT().GetEnabledChatModelConfigByID(gomock.Any(), modelID).Return(database.ChatModelConfig{
|
||||
Model: "gpt-6-preview",
|
||||
AIProviderID: uuid.NullUUID{UUID: providerID, Valid: true},
|
||||
}, nil)
|
||||
db.EXPECT().GetAIProviderByID(gomock.Any(), providerID).Return(database.AIProvider{
|
||||
Type: database.AIProviderTypeOpenai,
|
||||
}, nil)
|
||||
db.EXPECT().GetChatAdvisorConfig(gomock.Any()).Return(marshalConfig(t, codersdk.AdvisorConfig{MaxUsesPerRun: 7, MaxOutputTokens: 2048}), nil)
|
||||
expectOverrides(db, database.GetChatOrganizationModelOverridesByContextRow{
|
||||
OrganizationID: org.ID,
|
||||
ModelAvailable: true,
|
||||
Model: "gpt-6-preview",
|
||||
ProviderType: string(database.AIProviderTypeOpenai),
|
||||
})
|
||||
|
||||
payload := collect(t, telemetry.Options{Database: db, Logger: testutil.Logger(t)})
|
||||
// Stored enabled is ignored; the chat-advisor experiment gates it.
|
||||
require.False(t, payload.Enabled)
|
||||
payload := collect(t, telemetry.Options{Database: db, Logger: testutil.Logger(t), Experiments: codersdk.Experiments{codersdk.ExperimentChatAdvisor}})
|
||||
require.True(t, payload.Enabled)
|
||||
require.Equal(t, 7, payload.MaxUsesPerRun)
|
||||
require.Equal(t, int64(2048), payload.MaxOutputTokens)
|
||||
require.Equal(t, string(database.AIProviderTypeOpenai), payload.Provider)
|
||||
require.Equal(t, "gpt-6-preview", payload.Model)
|
||||
require.Equal(t, []telemetry.AgentsAdvisorOverrideTelemetry{{
|
||||
OrganizationID: org.ID.String(), Provider: string(database.AIProviderTypeOpenai), Model: "gpt-6-preview",
|
||||
}}, payload.Overrides)
|
||||
})
|
||||
|
||||
t.Run("ExperimentEnabled", func(t *testing.T) {
|
||||
t.Run("InactiveModel", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
org := database.Organization{ID: uuid.New()}
|
||||
db := dbmock.NewMockStore(gomock.NewController(t))
|
||||
db.EXPECT().GetChatAdvisorConfig(gomock.Any()).
|
||||
Return(marshalConfig(t, codersdk.AdvisorConfig{}), nil)
|
||||
|
||||
payload := collect(t, telemetry.Options{
|
||||
Database: db,
|
||||
Logger: testutil.Logger(t),
|
||||
Experiments: codersdk.Experiments{codersdk.ExperimentChatAdvisor},
|
||||
db.EXPECT().GetChatAdvisorConfig(gomock.Any()).Return("{}", nil)
|
||||
expectOverrides(db, database.GetChatOrganizationModelOverridesByContextRow{
|
||||
OrganizationID: org.ID,
|
||||
ModelAvailable: false,
|
||||
})
|
||||
require.True(t, payload.Enabled)
|
||||
payload := collect(t, telemetry.Options{Database: db, Logger: testutil.Logger(t)})
|
||||
require.Equal(t, []telemetry.AgentsAdvisorOverrideTelemetry{{
|
||||
OrganizationID: org.ID.String(),
|
||||
Provider: telemetry.AgentsExperimentAdvisorReuseChatModel,
|
||||
Model: telemetry.AgentsExperimentAdvisorReuseChatModel,
|
||||
}}, payload.Overrides)
|
||||
})
|
||||
|
||||
t.Run("MalformedJSON", func(t *testing.T) {
|
||||
t.Run("NoOverride", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
db := dbmock.NewMockStore(gomock.NewController(t))
|
||||
db.EXPECT().GetChatAdvisorConfig(gomock.Any()).Return("{}", nil)
|
||||
expectOverrides(db)
|
||||
payload := collect(t, telemetry.Options{Database: db, Logger: testutil.Logger(t)})
|
||||
require.Empty(t, payload.Overrides)
|
||||
})
|
||||
|
||||
t.Run("MalformedConfig", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
db := dbmock.NewMockStore(gomock.NewController(t))
|
||||
db.EXPECT().GetChatAdvisorConfig(gomock.Any()).Return("not-json", nil)
|
||||
|
||||
payload := collect(t, telemetry.Options{Database: db, Logger: testutil.Logger(t)})
|
||||
require.Equal(t, telemetry.AgentsExperimentUnknown, payload.Provider)
|
||||
require.Equal(t, telemetry.AgentsExperimentUnknown, payload.Model)
|
||||
})
|
||||
|
||||
t.Run("PartialParse", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
db := dbmock.NewMockStore(gomock.NewController(t))
|
||||
db.EXPECT().GetChatAdvisorConfig(gomock.Any()).
|
||||
Return(`{"max_uses_per_run": 42, "model_config_id": "not-a-uuid"}`, nil)
|
||||
|
||||
expectOverrides(db)
|
||||
payload := collect(t, telemetry.Options{Database: db, Logger: testutil.Logger(t)})
|
||||
require.Zero(t, payload.MaxUsesPerRun)
|
||||
require.Zero(t, payload.MaxOutputTokens)
|
||||
require.Equal(t, telemetry.AgentsExperimentUnknown, payload.Provider)
|
||||
require.Equal(t, telemetry.AgentsExperimentUnknown, payload.Model)
|
||||
})
|
||||
|
||||
t.Run("ClampsNegativeLimits", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
db := dbmock.NewMockStore(gomock.NewController(t))
|
||||
db.EXPECT().GetChatAdvisorConfig(gomock.Any()).
|
||||
Return(`{"max_uses_per_run": -3, "max_output_tokens": -99}`, nil)
|
||||
|
||||
db.EXPECT().GetChatAdvisorConfig(gomock.Any()).Return(`{"max_uses_per_run":-3,"max_output_tokens":-99}`, nil)
|
||||
expectOverrides(db)
|
||||
payload := collect(t, telemetry.Options{Database: db, Logger: testutil.Logger(t)})
|
||||
require.Zero(t, payload.MaxUsesPerRun)
|
||||
require.Zero(t, payload.MaxOutputTokens)
|
||||
})
|
||||
|
||||
t.Run("InactiveModelConfig", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
modelID := uuid.New()
|
||||
db := dbmock.NewMockStore(gomock.NewController(t))
|
||||
db.EXPECT().GetChatAdvisorConfig(gomock.Any()).
|
||||
Return(marshalConfig(t, codersdk.AdvisorConfig{ModelConfigID: modelID}), nil)
|
||||
db.EXPECT().GetEnabledChatModelConfigByID(gomock.Any(), modelID).
|
||||
Return(database.ChatModelConfig{}, sql.ErrNoRows)
|
||||
|
||||
payload := collect(t, telemetry.Options{Database: db, Logger: testutil.Logger(t)})
|
||||
require.Equal(t, telemetry.AgentsExperimentAdvisorReuseChatModel, payload.Provider)
|
||||
require.Equal(t, telemetry.AgentsExperimentAdvisorReuseChatModel, payload.Model)
|
||||
})
|
||||
|
||||
t.Run("ConfigFetchError", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
db := dbmock.NewMockStore(gomock.NewController(t))
|
||||
db.EXPECT().GetChatAdvisorConfig(gomock.Any()).Return("", sql.ErrConnDone)
|
||||
|
||||
expectOverrides(db)
|
||||
payload := collect(t, telemetry.Options{Database: db, Logger: testutil.Logger(t)})
|
||||
require.Equal(t, telemetry.AgentsExperimentUnknown, payload.Provider)
|
||||
require.Equal(t, telemetry.AgentsExperimentUnknown, payload.Model)
|
||||
require.Empty(t, payload.Overrides)
|
||||
})
|
||||
|
||||
t.Run("ModelResolveError", func(t *testing.T) {
|
||||
t.Run("OverridesFetchError", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
modelID := uuid.New()
|
||||
db := dbmock.NewMockStore(gomock.NewController(t))
|
||||
db.EXPECT().GetChatAdvisorConfig(gomock.Any()).
|
||||
Return(marshalConfig(t, codersdk.AdvisorConfig{ModelConfigID: modelID}), nil)
|
||||
db.EXPECT().GetEnabledChatModelConfigByID(gomock.Any(), modelID).
|
||||
Return(database.ChatModelConfig{}, sql.ErrConnDone)
|
||||
|
||||
db.EXPECT().GetChatAdvisorConfig(gomock.Any()).Return("{}", nil)
|
||||
db.EXPECT().GetChatOrganizationModelOverridesByContext(gomock.Any(), gomock.Any()).Return(nil, sql.ErrConnDone)
|
||||
payload := collect(t, telemetry.Options{Database: db, Logger: testutil.Logger(t)})
|
||||
require.Equal(t, telemetry.AgentsExperimentUnknown, payload.Provider)
|
||||
require.Equal(t, telemetry.AgentsExperimentUnknown, payload.Model)
|
||||
})
|
||||
|
||||
t.Run("ProviderResolveError", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
modelID := uuid.New()
|
||||
providerID := uuid.New()
|
||||
db := dbmock.NewMockStore(gomock.NewController(t))
|
||||
db.EXPECT().GetChatAdvisorConfig(gomock.Any()).
|
||||
Return(marshalConfig(t, codersdk.AdvisorConfig{ModelConfigID: modelID}), nil)
|
||||
db.EXPECT().GetEnabledChatModelConfigByID(gomock.Any(), modelID).Return(database.ChatModelConfig{
|
||||
Model: "gpt-6-preview",
|
||||
AIProviderID: uuid.NullUUID{UUID: providerID, Valid: true},
|
||||
}, nil)
|
||||
db.EXPECT().GetAIProviderByID(gomock.Any(), providerID).
|
||||
Return(database.AIProvider{}, sql.ErrConnDone)
|
||||
|
||||
payload := collect(t, telemetry.Options{Database: db, Logger: testutil.Logger(t)})
|
||||
// The provider is unknown, but the already-resolved model still ships.
|
||||
require.Equal(t, telemetry.AgentsExperimentUnknown, payload.Provider)
|
||||
require.Equal(t, "gpt-6-preview", payload.Model)
|
||||
require.Empty(t, payload.Overrides)
|
||||
})
|
||||
}
|
||||
|
||||
+15
-1
@@ -1,7 +1,11 @@
|
||||
// Package ptr contains some utility methods related to pointers.
|
||||
package ptr
|
||||
|
||||
import "golang.org/x/exp/constraints"
|
||||
import (
|
||||
"database/sql"
|
||||
|
||||
"golang.org/x/exp/constraints"
|
||||
)
|
||||
|
||||
type number interface {
|
||||
constraints.Integer | constraints.Float
|
||||
@@ -38,3 +42,13 @@ func NilToDefault[T any](s *T, def T) T {
|
||||
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
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package ptr_test
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -101,3 +102,18 @@ func Test_NilOrZero(t *testing.T) {
|
||||
assert.False(t, ptr.NilOrZero(&nonZeroFloat64))
|
||||
assert.False(t, ptr.NilOrZero(&nonZeroDuration))
|
||||
}
|
||||
|
||||
func Test_FromNullString(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert.Nil(t, ptr.FromNullString(sql.NullString{}))
|
||||
assert.Nil(t, ptr.FromNullString(sql.NullString{String: "ignored"}))
|
||||
|
||||
valid := ptr.FromNullString(sql.NullString{String: "value", Valid: true})
|
||||
assert.NotNil(t, valid)
|
||||
assert.Equal(t, "value", *valid)
|
||||
|
||||
empty := ptr.FromNullString(sql.NullString{Valid: true})
|
||||
assert.NotNil(t, empty)
|
||||
assert.Equal(t, "", *empty)
|
||||
}
|
||||
|
||||
@@ -864,6 +864,7 @@ The generation goroutine supports:
|
||||
|
||||
Model configs may carry a `reasoning_effort` config (`{default, max}`) inside `chat_model_configs.options`. Users select a per-turn effort when sending or editing a message; the value is stored on `chat_messages.reasoning_effort` and on `chat_queued_messages.reasoning_effort` for queued messages. Queued messages carry the value through promotion, and `chats.last_reasoning_effort` tracks the most recent message that set one, mirroring `last_model_config_id`.
|
||||
|
||||
<!-- TODO(CODAGT-872): Document organization-scoped subagent model overrides (personal and admin overrides are now per-organization rows, not deployment site configs). -->
|
||||
Subagent spawning is a second source of both values. `spawn_agent` accepts optional `model_config_id` and `reasoning_effort` args (discoverable via the `list_subagent_models` tool): an explicit model selection becomes the child chat's `last_model_config_id` and wins over personal and deployment subagent overrides and over parent inheritance, and an explicit effort is stored on the child's initial message and wins over effort carried by those overrides. Both are validated at spawn time (enabled config, enabled provider, usable credentials, effort on the global scale) and rejected with tool errors before the child chat is created; `computer_use` spawns reject both args because their model routing is specialized. Generation-time resolution and clamping below apply to the child unchanged.
|
||||
|
||||
During generation preparation, the effective effort is resolved as the chat's `last_reasoning_effort` if set, else the config's `default`; clamped to the config's `max` on the global scale `none < minimal < low < medium < high < xhigh < max`; and passed through to the provider. The provider verifies whether the configured value is valid for that model at runtime. If the model config has no `reasoning_effort`, any user-selected value is ignored. The resolved value is injected into the provider-native options by `chatprovider.ProviderOptionsForCall`, which converts the model config and applies the effort in one step. For Anthropic, the fantasy provider converts effort into enabled budget thinking on models older than Claude 4.6, which reject adaptive thinking.
|
||||
@@ -921,6 +922,7 @@ The model editor scopes the field to openai-typed providers with a `providers` s
|
||||
|
||||
Compaction is an auxiliary LLM call: when the conversation approaches the context limit, the generation goroutine asks a model to summarize the history, commits the summary as a compressed boundary, and continues the turn on the chat model.
|
||||
|
||||
<!-- TODO(CODAGT-872): Document the organization-scoped compaction override (route moved to /api/experimental/organizations/{organization}/chats/model-overrides/compaction, storage moved to typed chat_organization_model_overrides rows resolved by the chat's organization, and the malformed-string fallback no longer applies). -->
|
||||
By default the summary is generated with the chat model. Admins can override the compaction model deployment-wide via the `compaction` context of the chat model override API (`/api/experimental/chats/config/model-override/{context}`, stored in the `agents_chat_compaction_model_override` site config). The override affects only the summary call; thresholds, compressed-message storage, and the post-compaction assistant generation keep using the chat model.
|
||||
|
||||
Details that follow from the override:
|
||||
|
||||
@@ -31,12 +31,36 @@ import (
|
||||
type advisorOverrideStubStore struct {
|
||||
database.Store
|
||||
|
||||
getEnabledChatModelConfigByID func(context.Context, uuid.UUID) (database.ChatModelConfig, error)
|
||||
getChatModelConfigByID func(context.Context, uuid.UUID) (database.ChatModelConfig, error)
|
||||
getAIProviderByID func(context.Context, uuid.UUID) (database.AIProvider, error)
|
||||
getAIProviders func(context.Context, database.GetAIProvidersParams) ([]database.AIProvider, error)
|
||||
getAIProviderKeysByProviderID func(context.Context, uuid.UUID) ([]database.AIProviderKey, error)
|
||||
getAIProviderKeysByProviderIDs func(context.Context, []uuid.UUID) ([]database.AIProviderKey, error)
|
||||
getChatOrganizationModelOverride func(context.Context, database.GetChatOrganizationModelOverrideParams) (database.ChatOrganizationModelOverride, error)
|
||||
advisorModelConfigID uuid.UUID
|
||||
advisorReasoningEffort *string
|
||||
getEnabledChatModelConfigByID func(context.Context, uuid.UUID) (database.ChatModelConfig, error)
|
||||
getChatModelConfigByID func(context.Context, uuid.UUID) (database.ChatModelConfig, error)
|
||||
getAIProviderByID func(context.Context, uuid.UUID) (database.AIProvider, error)
|
||||
getAIProviders func(context.Context, database.GetAIProvidersParams) ([]database.AIProvider, error)
|
||||
getAIProviderKeysByProviderID func(context.Context, uuid.UUID) ([]database.AIProviderKey, error)
|
||||
getAIProviderKeysByProviderIDs func(context.Context, []uuid.UUID) ([]database.AIProviderKey, error)
|
||||
}
|
||||
|
||||
func (s *advisorOverrideStubStore) GetChatOrganizationModelOverride(
|
||||
ctx context.Context,
|
||||
params database.GetChatOrganizationModelOverrideParams,
|
||||
) (database.ChatOrganizationModelOverride, error) {
|
||||
if s.getChatOrganizationModelOverride != nil {
|
||||
return s.getChatOrganizationModelOverride(ctx, params)
|
||||
}
|
||||
if s.advisorModelConfigID == uuid.Nil {
|
||||
return database.ChatOrganizationModelOverride{}, sql.ErrNoRows
|
||||
}
|
||||
override := database.ChatOrganizationModelOverride{
|
||||
OrganizationID: params.OrganizationID,
|
||||
Context: params.Context,
|
||||
ModelConfigID: s.advisorModelConfigID,
|
||||
}
|
||||
if s.advisorReasoningEffort != nil {
|
||||
override.ReasoningEffort = sql.NullString{String: *s.advisorReasoningEffort, Valid: true}
|
||||
}
|
||||
return override, nil
|
||||
}
|
||||
|
||||
func (s *advisorOverrideStubStore) GetEnabledChatModelConfigByID(
|
||||
@@ -114,6 +138,23 @@ func newAdvisorTestServer(
|
||||
|
||||
const advisorTestMaxOutputTokens = int64(16384)
|
||||
|
||||
func resolveAdvisorModelOverrideForTest(
|
||||
ctx context.Context,
|
||||
p *Server,
|
||||
chat database.Chat,
|
||||
modelConfigID uuid.UUID,
|
||||
reasoningEffort *string,
|
||||
maxOutputTokens int64,
|
||||
modelOpts modelBuildOptions,
|
||||
logger slog.Logger,
|
||||
) (resolvedModelCall, bool, error) {
|
||||
if store, ok := p.db.(*advisorOverrideStubStore); ok {
|
||||
store.advisorModelConfigID = modelConfigID
|
||||
store.advisorReasoningEffort = reasoningEffort
|
||||
}
|
||||
return p.resolveAdvisorModelOverride(ctx, chat, maxOutputTokens, modelOpts, logger)
|
||||
}
|
||||
|
||||
// advisorChatModelFixture wires a chat whose LastModelConfigID resolves
|
||||
// through the config cache to an enabled, provider-linked model config, so
|
||||
// the advisor chat-model path can resolve without an override.
|
||||
@@ -121,22 +162,24 @@ func advisorChatModelFixture(t *testing.T, options json.RawMessage) (database.Ch
|
||||
t.Helper()
|
||||
configID := uuid.New()
|
||||
providerID := uuid.New()
|
||||
organizationID := uuid.New()
|
||||
store := &advisorOverrideStubStore{
|
||||
getEnabledChatModelConfigByID: func(context.Context, uuid.UUID) (database.ChatModelConfig, error) {
|
||||
return database.ChatModelConfig{
|
||||
ID: configID,
|
||||
Model: "gpt-5.2",
|
||||
Enabled: true,
|
||||
Options: options,
|
||||
DisplayName: "gpt-5.2",
|
||||
AIProviderID: uuid.NullUUID{UUID: providerID, Valid: true},
|
||||
ID: configID,
|
||||
Model: "gpt-5.2",
|
||||
Enabled: true,
|
||||
Options: options,
|
||||
DisplayName: "gpt-5.2",
|
||||
AIProviderID: uuid.NullUUID{UUID: providerID, Valid: true},
|
||||
OrganizationID: organizationID,
|
||||
}, nil
|
||||
},
|
||||
getAIProviderByID: func(context.Context, uuid.UUID) (database.AIProvider, error) {
|
||||
return aibridgeTestAIProvider(providerID, "primary-openai", database.AIProviderTypeOpenai), nil
|
||||
},
|
||||
}
|
||||
return database.Chat{LastModelConfigID: configID}, store
|
||||
return database.Chat{LastModelConfigID: configID, OrganizationID: organizationID}, store
|
||||
}
|
||||
|
||||
func advisorTestTransportFactory() *aibridgeTestFactory {
|
||||
@@ -152,13 +195,14 @@ func TestResolveAdvisorModelOverride(t *testing.T) {
|
||||
|
||||
logger := slog.Make()
|
||||
|
||||
requireChatModel := func(t *testing.T, p *Server, advisorCfg codersdk.AdvisorConfig) {
|
||||
requireChatModel := func(t *testing.T, p *Server, modelConfigID uuid.UUID) {
|
||||
t.Helper()
|
||||
ctx := testutil.Context(t, testutil.WaitShort)
|
||||
resolved, ok, err := p.resolveAdvisorModelOverride(
|
||||
ctx,
|
||||
resolved, ok, err := resolveAdvisorModelOverrideForTest(ctx,
|
||||
p,
|
||||
database.Chat{},
|
||||
advisorCfg,
|
||||
modelConfigID,
|
||||
nil,
|
||||
advisorTestMaxOutputTokens,
|
||||
modelBuildOptions{},
|
||||
logger,
|
||||
@@ -175,7 +219,7 @@ func TestResolveAdvisorModelOverride(t *testing.T) {
|
||||
store := &advisorOverrideStubStore{}
|
||||
p := newAdvisorTestServer(ctx, t, store)
|
||||
|
||||
requireChatModel(t, p, codersdk.AdvisorConfig{})
|
||||
requireChatModel(t, p, uuid.Nil)
|
||||
})
|
||||
|
||||
t.Run("ConfigLookupErrorUsesChatModel", func(t *testing.T) {
|
||||
@@ -188,7 +232,7 @@ func TestResolveAdvisorModelOverride(t *testing.T) {
|
||||
}
|
||||
p := newAdvisorTestServer(ctx, t, store)
|
||||
|
||||
requireChatModel(t, p, codersdk.AdvisorConfig{ModelConfigID: uuid.New()})
|
||||
requireChatModel(t, p, uuid.New())
|
||||
})
|
||||
|
||||
// Covers the sql.ErrNoRows branch separately from the generic-error
|
||||
@@ -207,7 +251,7 @@ func TestResolveAdvisorModelOverride(t *testing.T) {
|
||||
}
|
||||
p := newAdvisorTestServer(ctx, t, store)
|
||||
|
||||
requireChatModel(t, p, codersdk.AdvisorConfig{ModelConfigID: uuid.New()})
|
||||
requireChatModel(t, p, uuid.New())
|
||||
})
|
||||
|
||||
t.Run("ForeignOrgConfigUsesChatModel", func(t *testing.T) {
|
||||
@@ -227,10 +271,11 @@ func TestResolveAdvisorModelOverride(t *testing.T) {
|
||||
}
|
||||
p := newAdvisorTestServer(ctx, t, store)
|
||||
|
||||
resolved, ok, err := p.resolveAdvisorModelOverride(
|
||||
ctx,
|
||||
resolved, ok, err := resolveAdvisorModelOverrideForTest(ctx,
|
||||
p,
|
||||
database.Chat{OrganizationID: chatOrgID},
|
||||
codersdk.AdvisorConfig{ModelConfigID: configID},
|
||||
configID,
|
||||
nil,
|
||||
advisorTestMaxOutputTokens,
|
||||
modelBuildOptions{},
|
||||
logger,
|
||||
@@ -259,7 +304,7 @@ func TestResolveAdvisorModelOverride(t *testing.T) {
|
||||
}
|
||||
p := newAdvisorTestServer(ctx, t, store)
|
||||
|
||||
requireChatModel(t, p, codersdk.AdvisorConfig{ModelConfigID: configID})
|
||||
requireChatModel(t, p, configID)
|
||||
})
|
||||
|
||||
t.Run("InvalidOptionsJSONWithLinkedProviderUsesChatModel", func(t *testing.T) {
|
||||
@@ -280,7 +325,7 @@ func TestResolveAdvisorModelOverride(t *testing.T) {
|
||||
}
|
||||
p := newAdvisorTestServer(ctx, t, store)
|
||||
|
||||
requireChatModel(t, p, codersdk.AdvisorConfig{ModelConfigID: configID})
|
||||
requireChatModel(t, p, configID)
|
||||
})
|
||||
|
||||
t.Run("MissingProviderKeyUsesChatModel", func(t *testing.T) {
|
||||
@@ -312,7 +357,7 @@ func TestResolveAdvisorModelOverride(t *testing.T) {
|
||||
}
|
||||
p := newAdvisorTestServer(ctx, t, store)
|
||||
|
||||
requireChatModel(t, p, codersdk.AdvisorConfig{ModelConfigID: configID})
|
||||
requireChatModel(t, p, configID)
|
||||
})
|
||||
|
||||
t.Run("SuccessReturnsOverrideModelAndConfig", func(t *testing.T) {
|
||||
@@ -348,13 +393,11 @@ func TestResolveAdvisorModelOverride(t *testing.T) {
|
||||
p := newAdvisorTestServer(ctx, t, store)
|
||||
p.aibridgeTransportFactory = aibridgeTestFactoryPointer(advisorTestTransportFactory())
|
||||
|
||||
resolved, ok, err := p.resolveAdvisorModelOverride(
|
||||
ctx,
|
||||
resolved, ok, err := resolveAdvisorModelOverrideForTest(ctx,
|
||||
p,
|
||||
database.Chat{},
|
||||
codersdk.AdvisorConfig{
|
||||
ModelConfigID: configID,
|
||||
ReasoningEffort: ptr.Ref(codersdk.ChatModelReasoningEffortHigh),
|
||||
},
|
||||
configID,
|
||||
ptr.Ref(codersdk.ChatModelReasoningEffortHigh),
|
||||
advisorTestMaxOutputTokens,
|
||||
modelBuildOptions{ActiveAPIKeyID: uuid.NewString()},
|
||||
logger,
|
||||
@@ -408,10 +451,11 @@ func TestResolveAdvisorModelOverride(t *testing.T) {
|
||||
p := newAdvisorTestServer(ctx, t, store)
|
||||
p.aibridgeTransportFactory = aibridgeTestFactoryPointer(advisorTestTransportFactory())
|
||||
|
||||
resolved, ok, err := p.resolveAdvisorModelOverride(
|
||||
ctx,
|
||||
resolved, ok, err := resolveAdvisorModelOverrideForTest(ctx,
|
||||
p,
|
||||
database.Chat{},
|
||||
codersdk.AdvisorConfig{ModelConfigID: configID},
|
||||
configID,
|
||||
nil,
|
||||
advisorTestMaxOutputTokens,
|
||||
modelBuildOptions{ActiveAPIKeyID: uuid.NewString()},
|
||||
logger,
|
||||
@@ -453,10 +497,11 @@ func TestResolveAdvisorModelOverridePromotesAIBridgeErrors(t *testing.T) {
|
||||
p := newAdvisorTestServer(ctx, t, store)
|
||||
|
||||
ctx = aibridge.WithDelegatedAPIKeyID(ctx, uuid.NewString())
|
||||
resolved, ok, err := p.resolveAdvisorModelOverride(
|
||||
ctx,
|
||||
resolved, ok, err := resolveAdvisorModelOverrideForTest(ctx,
|
||||
p,
|
||||
database.Chat{ID: uuid.New()},
|
||||
codersdk.AdvisorConfig{ModelConfigID: configID},
|
||||
configID,
|
||||
nil,
|
||||
advisorTestMaxOutputTokens,
|
||||
modelBuildOptions{ActiveAPIKeyID: uuid.NewString()},
|
||||
slog.Make(),
|
||||
@@ -557,7 +602,7 @@ func TestNewAdvisorRuntime(t *testing.T) {
|
||||
|
||||
logger := slog.Make()
|
||||
|
||||
newChatModelRuntime := func(t *testing.T, advisorCfg codersdk.AdvisorConfig, options json.RawMessage) *chatadvisor.Runtime {
|
||||
newChatModelRuntime := func(t *testing.T, advisorCfg advisorRuntimeConfig, options json.RawMessage) *chatadvisor.Runtime {
|
||||
t.Helper()
|
||||
ctx := testutil.Context(t, testutil.WaitShort)
|
||||
chat, store := advisorChatModelFixture(t, options)
|
||||
@@ -578,7 +623,7 @@ func TestNewAdvisorRuntime(t *testing.T) {
|
||||
t.Run("ZeroMaxUsesDefaultsToMaxChatSteps", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
rt := newChatModelRuntime(t, codersdk.AdvisorConfig{
|
||||
rt := newChatModelRuntime(t, advisorRuntimeConfig{
|
||||
Enabled: true,
|
||||
MaxUsesPerRun: 0,
|
||||
MaxOutputTokens: 16384,
|
||||
@@ -599,7 +644,7 @@ func TestNewAdvisorRuntime(t *testing.T) {
|
||||
rt, err := p.newAdvisorRuntime(
|
||||
ctx,
|
||||
database.Chat{},
|
||||
codersdk.AdvisorConfig{
|
||||
advisorRuntimeConfig{
|
||||
Enabled: true,
|
||||
MaxUsesPerRun: -1,
|
||||
MaxOutputTokens: 16384,
|
||||
@@ -614,7 +659,7 @@ func TestNewAdvisorRuntime(t *testing.T) {
|
||||
t.Run("ZeroMaxOutputTokensDefaults", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
rt := newChatModelRuntime(t, codersdk.AdvisorConfig{
|
||||
rt := newChatModelRuntime(t, advisorRuntimeConfig{
|
||||
Enabled: true,
|
||||
MaxUsesPerRun: 3,
|
||||
MaxOutputTokens: 0,
|
||||
@@ -639,7 +684,7 @@ func TestNewAdvisorRuntime(t *testing.T) {
|
||||
rt, err := p.newAdvisorRuntime(
|
||||
ctx,
|
||||
database.Chat{LastModelConfigID: uuid.New()},
|
||||
codersdk.AdvisorConfig{
|
||||
advisorRuntimeConfig{
|
||||
Enabled: true,
|
||||
MaxUsesPerRun: 3,
|
||||
MaxOutputTokens: 16384,
|
||||
@@ -667,7 +712,7 @@ func TestNewAdvisorRuntime(t *testing.T) {
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
rt := newChatModelRuntime(t, codersdk.AdvisorConfig{
|
||||
rt := newChatModelRuntime(t, advisorRuntimeConfig{
|
||||
Enabled: true,
|
||||
MaxUsesPerRun: 3,
|
||||
MaxOutputTokens: 16384,
|
||||
|
||||
+34
-24
@@ -210,11 +210,11 @@ type Server struct {
|
||||
chatHeartbeatInterval time.Duration
|
||||
}
|
||||
|
||||
func (p *Server) loadAdvisorConfig(ctx context.Context, logger slog.Logger) codersdk.AdvisorConfig {
|
||||
func (p *Server) loadAdvisorConfig(ctx context.Context, logger slog.Logger) advisorRuntimeConfig {
|
||||
cfg, err := p.configCache.AdvisorConfig(ctx)
|
||||
if err != nil {
|
||||
logger.Warn(ctx, "failed to load advisor config", slog.Error(err))
|
||||
return codersdk.AdvisorConfig{}
|
||||
return advisorRuntimeConfig{}
|
||||
}
|
||||
return cfg
|
||||
}
|
||||
@@ -245,19 +245,36 @@ func isAdvisorGuidanceMessage(msg fantasy.Message) bool {
|
||||
return strings.TrimSpace(text.Text) == strings.TrimSpace(chatadvisor.ParentGuidanceBlock)
|
||||
}
|
||||
|
||||
// resolveAdvisorModelOverride resolves the configured advisor override
|
||||
// model. ok is false when no override is configured or the override is
|
||||
// unavailable, in which case the advisor uses the chat model. An error is
|
||||
// a hard failure: the override has a linked provider and failed to build.
|
||||
const advisorOverrideContext = "advisor"
|
||||
|
||||
// resolveAdvisorModelOverride resolves the advisor model override for the
|
||||
// chat's organization. Missing or unusable overrides fall back to the chat
|
||||
// model. Linked-provider route and client failures remain hard failures.
|
||||
func (p *Server) resolveAdvisorModelOverride(
|
||||
ctx context.Context,
|
||||
chat database.Chat,
|
||||
advisorCfg codersdk.AdvisorConfig,
|
||||
maxOutputTokens int64,
|
||||
modelOpts modelBuildOptions,
|
||||
logger slog.Logger,
|
||||
) (resolvedModelCall, bool, error) {
|
||||
if advisorCfg.ModelConfigID == uuid.Nil {
|
||||
//nolint:gocritic // Chatd reads organization-scoped runtime configuration.
|
||||
override, err := p.db.GetChatOrganizationModelOverride(
|
||||
dbauthz.AsChatd(ctx),
|
||||
database.GetChatOrganizationModelOverrideParams{
|
||||
OrganizationID: chat.OrganizationID,
|
||||
Context: advisorOverrideContext,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
if xerrors.Is(err, sql.ErrNoRows) {
|
||||
return resolvedModelCall{}, false, nil
|
||||
}
|
||||
logger.Warn(
|
||||
ctx,
|
||||
"failed to load advisor model override, continuing with chat model",
|
||||
slog.F("organization_id", chat.OrganizationID),
|
||||
slog.Error(err),
|
||||
)
|
||||
return resolvedModelCall{}, false, nil
|
||||
}
|
||||
|
||||
@@ -266,17 +283,14 @@ func (p *Server) resolveAdvisorModelOverride(
|
||||
logger.Warn(
|
||||
ctx,
|
||||
"failed to load advisor model authorization, continuing with chat model",
|
||||
slog.F("model_config_id", advisorCfg.ModelConfigID),
|
||||
slog.F("model_config_id", override.ModelConfigID),
|
||||
slog.Error(modelCtxErr),
|
||||
)
|
||||
return resolvedModelCall{}, false, nil
|
||||
}
|
||||
// Re-read the override instead of using the cache so disabled models
|
||||
// or providers stop routing advisor prompts immediately.
|
||||
overrideConfig, err := p.db.GetEnabledChatModelConfigByID(
|
||||
modelCtx,
|
||||
advisorCfg.ModelConfigID,
|
||||
)
|
||||
// Re-read the model row for every runtime so disabled models or providers
|
||||
// stop routing advisor prompts immediately.
|
||||
overrideConfig, err := p.db.GetEnabledChatModelConfigByID(modelCtx, override.ModelConfigID)
|
||||
if err == nil && overrideConfig.OrganizationID != chat.OrganizationID {
|
||||
err = sql.ErrNoRows
|
||||
}
|
||||
@@ -285,14 +299,14 @@ func (p *Server) resolveAdvisorModelOverride(
|
||||
logger.Warn(
|
||||
ctx,
|
||||
"advisor model config is disabled or unavailable, continuing with chat model",
|
||||
slog.F("model_config_id", advisorCfg.ModelConfigID),
|
||||
slog.F("model_config_id", override.ModelConfigID),
|
||||
)
|
||||
return resolvedModelCall{}, false, nil
|
||||
}
|
||||
logger.Warn(
|
||||
ctx,
|
||||
"failed to resolve advisor model config, continuing with chat model",
|
||||
slog.F("model_config_id", advisorCfg.ModelConfigID),
|
||||
slog.F("model_config_id", override.ModelConfigID),
|
||||
slog.Error(err),
|
||||
)
|
||||
return resolvedModelCall{}, false, nil
|
||||
@@ -302,13 +316,11 @@ func (p *Server) resolveAdvisorModelOverride(
|
||||
purpose: "advisor",
|
||||
chat: chat,
|
||||
explicitConfig: &overrideConfig,
|
||||
requestedEffort: advisorCfg.ReasoningEffort,
|
||||
requestedEffort: ptr.FromNullString(override.ReasoningEffort),
|
||||
maxOutputTokens: ptr.Ref(maxOutputTokens),
|
||||
buildOptions: modelOpts,
|
||||
})
|
||||
if err != nil {
|
||||
// Malformed options always fall back; route and client errors are
|
||||
// hard failures only when the config has a linked provider.
|
||||
var parseErr modelCallConfigParseError
|
||||
if overrideConfig.AIProviderID.Valid && !xerrors.As(err, &parseErr) {
|
||||
return resolvedModelCall{}, false, xerrors.Errorf("resolve advisor override model: %w", err)
|
||||
@@ -316,19 +328,18 @@ func (p *Server) resolveAdvisorModelOverride(
|
||||
logger.Warn(
|
||||
ctx,
|
||||
"failed to resolve advisor override model, continuing with chat model",
|
||||
slog.F("model_config_id", advisorCfg.ModelConfigID),
|
||||
slog.F("model_config_id", override.ModelConfigID),
|
||||
slog.Error(err),
|
||||
)
|
||||
return resolvedModelCall{}, false, nil
|
||||
}
|
||||
|
||||
return resolved, true, nil
|
||||
}
|
||||
|
||||
func (p *Server) newAdvisorRuntime(
|
||||
ctx context.Context,
|
||||
chat database.Chat,
|
||||
advisorCfg codersdk.AdvisorConfig,
|
||||
advisorCfg advisorRuntimeConfig,
|
||||
modelOpts modelBuildOptions,
|
||||
logger slog.Logger,
|
||||
) (*chatadvisor.Runtime, error) {
|
||||
@@ -357,7 +368,6 @@ func (p *Server) newAdvisorRuntime(
|
||||
advisor, ok, err := p.resolveAdvisorModelOverride(
|
||||
ctx,
|
||||
chat,
|
||||
advisorCfg,
|
||||
maxOutputTokens,
|
||||
modelOpts,
|
||||
logger,
|
||||
|
||||
@@ -1132,7 +1132,7 @@ func TestRegenerateChatTitle_PersistsAndBroadcasts(t *testing.T) {
|
||||
LimitVal: manualTitleMessageWindowLimit,
|
||||
},
|
||||
).Return(nil, nil)
|
||||
db.EXPECT().GetChatTitleGenerationModelOverride(gomock.Any()).Return("", nil)
|
||||
db.EXPECT().GetChatOrganizationModelOverride(gomock.Any(), titleGenerationOverrideParams(chat)).Return(database.ChatOrganizationModelOverride{}, sql.ErrNoRows)
|
||||
db.EXPECT().GetEnabledChatModelConfigsByOrganization(gomock.Any(), organizationID).Return(nil, nil)
|
||||
|
||||
db.EXPECT().InTx(gomock.Any(), nil).DoAndReturn(
|
||||
@@ -1281,7 +1281,7 @@ func TestRegenerateChatTitle_SkipsPersistWhenTitleChangedConcurrently(t *testing
|
||||
LimitVal: manualTitleMessageWindowLimit,
|
||||
},
|
||||
).Return(nil, nil)
|
||||
db.EXPECT().GetChatTitleGenerationModelOverride(gomock.Any()).Return("", nil)
|
||||
db.EXPECT().GetChatOrganizationModelOverride(gomock.Any(), titleGenerationOverrideParams(chat)).Return(database.ChatOrganizationModelOverride{}, sql.ErrNoRows)
|
||||
db.EXPECT().GetEnabledChatModelConfigsByOrganization(gomock.Any(), organizationID).Return(nil, nil)
|
||||
|
||||
db.EXPECT().InTx(gomock.Any(), nil).DoAndReturn(
|
||||
|
||||
@@ -5775,7 +5775,11 @@ func TestActiveServer_CompactionModelOverride(t *testing.T) {
|
||||
Max: &effort,
|
||||
},
|
||||
})
|
||||
require.NoError(t, db.UpsertChatCompactionModelOverride(ctx, overrideModel.ID.String()))
|
||||
require.NoError(t, db.UpsertChatOrganizationModelOverride(ctx, database.UpsertChatOrganizationModelOverrideParams{
|
||||
OrganizationID: overrideModel.OrganizationID,
|
||||
Context: string(codersdk.ChatModelOverrideContextCompaction),
|
||||
ModelConfigID: overrideModel.ID,
|
||||
}))
|
||||
return overrideModel
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package chatd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"golang.org/x/xerrors"
|
||||
@@ -16,17 +17,21 @@ const compactionOverrideContext = "compaction"
|
||||
func readCompactionModelOverride(
|
||||
ctx context.Context,
|
||||
db database.Store,
|
||||
) (string, error) {
|
||||
organizationID uuid.UUID,
|
||||
) (database.ChatOrganizationModelOverride, error) {
|
||||
//nolint:gocritic // Chatd is internal, not a user, so this read uses AsChatd.
|
||||
chatdCtx := dbauthz.AsChatd(ctx)
|
||||
raw, err := db.GetChatCompactionModelOverride(chatdCtx)
|
||||
override, err := db.GetChatOrganizationModelOverride(chatdCtx, database.GetChatOrganizationModelOverrideParams{
|
||||
OrganizationID: organizationID,
|
||||
Context: compactionOverrideContext,
|
||||
})
|
||||
if err != nil {
|
||||
return "", xerrors.Errorf(
|
||||
return database.ChatOrganizationModelOverride{}, xerrors.Errorf(
|
||||
"get chat compaction model override: %w",
|
||||
err,
|
||||
)
|
||||
}
|
||||
return raw, nil
|
||||
return override, nil
|
||||
}
|
||||
|
||||
// resolvedCompactionOverride is the compaction override resolved at
|
||||
@@ -42,8 +47,8 @@ type resolvedCompactionOverride struct {
|
||||
ResolvedModel string
|
||||
}
|
||||
|
||||
// resolveCompactionOverrideConfig resolves the stored deployment-wide
|
||||
// compaction model override. Unset, malformed, stale, and credential-less
|
||||
// resolveCompactionOverrideConfig resolves the stored organization-scoped
|
||||
// compaction model override. Unset, stale, and credential-less
|
||||
// overrides fall back to the chat model (nil override). This runs on every
|
||||
// generation prepare because the override's context limit feeds the
|
||||
// compaction trigger; the model client is built only when compaction runs.
|
||||
@@ -51,21 +56,24 @@ func (p *Server) resolveCompactionOverrideConfig(
|
||||
ctx context.Context,
|
||||
chat database.Chat,
|
||||
) (*resolvedCompactionOverride, error) {
|
||||
raw, err := readCompactionModelOverride(ctx, p.db)
|
||||
override, err := readCompactionModelOverride(ctx, p.db, chat.OrganizationID)
|
||||
if err != nil {
|
||||
if xerrors.Is(err, sql.ErrNoRows) {
|
||||
return nil, nil //nolint:nilnil // No row means use the chat model.
|
||||
}
|
||||
return nil, xerrors.Errorf(
|
||||
"read compaction model override: %w",
|
||||
err,
|
||||
)
|
||||
}
|
||||
|
||||
modelConfig, providerName, overrideEffort, overrideSet, err := p.resolveConfiguredModelOverride(
|
||||
modelConfig, providerName, overrideEffort, overrideSet, err := p.resolveOrganizationModelOverride(
|
||||
ctx,
|
||||
compactionOverrideContext,
|
||||
raw,
|
||||
override,
|
||||
chat.OwnerID,
|
||||
func(ctx context.Context, modelConfigID uuid.UUID) (database.ChatModelConfig, string, error) {
|
||||
return p.resolveModelConfigForOrganization(ctx, chat.OwnerID, chat.OrganizationID, modelConfigID)
|
||||
return p.resolveModelConfigAndNormalizedProvider(ctx, chat.OwnerID, modelConfigID)
|
||||
},
|
||||
func(ctx context.Context, ownerID uuid.UUID, aiProviderID uuid.UUID) (chatprovider.ProviderAPIKeys, error) {
|
||||
return p.resolveUserProviderAPIKeys(ctx, ownerID, aiProviderID)
|
||||
|
||||
@@ -17,32 +17,23 @@ import (
|
||||
"github.com/coder/coder/v2/testutil"
|
||||
)
|
||||
|
||||
func TestResolveCompactionOverrideConfig_ForeignConfigFallsBack(t *testing.T) {
|
||||
t.Parallel()
|
||||
func compactionOverrideParams(chat database.Chat) database.GetChatOrganizationModelOverrideParams {
|
||||
return database.GetChatOrganizationModelOverrideParams{
|
||||
OrganizationID: chat.OrganizationID,
|
||||
Context: compactionOverrideContext,
|
||||
}
|
||||
}
|
||||
|
||||
ctx := testutil.Context(t, testutil.WaitShort)
|
||||
ctrl := gomock.NewController(t)
|
||||
db := dbmock.NewMockStore(ctrl)
|
||||
logger := slogtest.Make(t, &slogtest.Options{IgnoreErrors: true})
|
||||
chat, _ := titleOverrideTestChatAndMessages(t)
|
||||
chat.OrganizationID = uuid.New()
|
||||
overrideConfig := titleOverrideModelConfig("gpt-4.1", true)
|
||||
overrideConfig.OrganizationID = uuid.New()
|
||||
overrideProviderID := uuid.New()
|
||||
overrideConfig.AIProviderID = uuid.NullUUID{UUID: overrideProviderID, Valid: true}
|
||||
|
||||
db.EXPECT().GetChatCompactionModelOverride(gomock.Any()).Return(overrideConfig.ID.String(), nil)
|
||||
db.EXPECT().GetChatModelConfigByID(gomock.Any(), overrideConfig.ID).Return(overrideConfig, nil)
|
||||
db.EXPECT().GetAIProviderByID(gomock.Any(), overrideProviderID).Return(database.AIProvider{
|
||||
ID: overrideProviderID,
|
||||
Type: database.AIProviderTypeOpenai,
|
||||
Enabled: true,
|
||||
}, nil)
|
||||
|
||||
server := titleOverrideTestServer(db, logger)
|
||||
override, err := server.resolveCompactionOverrideConfig(ctx, chat)
|
||||
require.NoError(t, err)
|
||||
require.Nil(t, override)
|
||||
func orgModelOverride(chat database.Chat, context string, modelConfigID uuid.UUID, effort string) database.ChatOrganizationModelOverride {
|
||||
override := database.ChatOrganizationModelOverride{
|
||||
OrganizationID: chat.OrganizationID,
|
||||
Context: context,
|
||||
ModelConfigID: modelConfigID,
|
||||
}
|
||||
if effort != "" {
|
||||
override.ReasoningEffort = sql.NullString{String: effort, Valid: true}
|
||||
}
|
||||
return override
|
||||
}
|
||||
|
||||
func TestResolveCompactionOverrideConfig_Unset(t *testing.T) {
|
||||
@@ -54,7 +45,7 @@ func TestResolveCompactionOverrideConfig_Unset(t *testing.T) {
|
||||
logger := slogtest.Make(t, &slogtest.Options{IgnoreErrors: true})
|
||||
chat, _ := titleOverrideTestChatAndMessages(t)
|
||||
|
||||
db.EXPECT().GetChatCompactionModelOverride(gomock.Any()).Return("", nil)
|
||||
db.EXPECT().GetChatOrganizationModelOverride(gomock.Any(), compactionOverrideParams(chat)).Return(database.ChatOrganizationModelOverride{}, sql.ErrNoRows)
|
||||
|
||||
server := titleOverrideTestServer(db, logger)
|
||||
override, err := server.resolveCompactionOverrideConfig(ctx, chat)
|
||||
@@ -71,7 +62,7 @@ func TestResolveCompactionOverrideConfig_ReadDBError(t *testing.T) {
|
||||
logger := slogtest.Make(t, &slogtest.Options{IgnoreErrors: true})
|
||||
chat, _ := titleOverrideTestChatAndMessages(t)
|
||||
|
||||
db.EXPECT().GetChatCompactionModelOverride(gomock.Any()).Return("", sql.ErrConnDone)
|
||||
db.EXPECT().GetChatOrganizationModelOverride(gomock.Any(), compactionOverrideParams(chat)).Return(database.ChatOrganizationModelOverride{}, sql.ErrConnDone)
|
||||
|
||||
server := titleOverrideTestServer(db, logger)
|
||||
override, err := server.resolveCompactionOverrideConfig(ctx, chat)
|
||||
@@ -80,23 +71,6 @@ func TestResolveCompactionOverrideConfig_ReadDBError(t *testing.T) {
|
||||
require.Nil(t, override)
|
||||
}
|
||||
|
||||
func TestResolveCompactionOverrideConfig_MalformedFallsBack(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
ctx := testutil.Context(t, testutil.WaitShort)
|
||||
ctrl := gomock.NewController(t)
|
||||
db := dbmock.NewMockStore(ctrl)
|
||||
logger := slogtest.Make(t, &slogtest.Options{IgnoreErrors: true})
|
||||
chat, _ := titleOverrideTestChatAndMessages(t)
|
||||
|
||||
db.EXPECT().GetChatCompactionModelOverride(gomock.Any()).Return("not-a-uuid", nil)
|
||||
|
||||
server := titleOverrideTestServer(db, logger)
|
||||
override, err := server.resolveCompactionOverrideConfig(ctx, chat)
|
||||
require.NoError(t, err)
|
||||
require.Nil(t, override)
|
||||
}
|
||||
|
||||
func TestResolveCompactionOverrideConfig_DeletedConfigFallsBack(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -107,7 +81,7 @@ func TestResolveCompactionOverrideConfig_DeletedConfigFallsBack(t *testing.T) {
|
||||
chat, _ := titleOverrideTestChatAndMessages(t)
|
||||
missingID := uuid.New()
|
||||
|
||||
db.EXPECT().GetChatCompactionModelOverride(gomock.Any()).Return(missingID.String(), nil)
|
||||
db.EXPECT().GetChatOrganizationModelOverride(gomock.Any(), compactionOverrideParams(chat)).Return(orgModelOverride(chat, compactionOverrideContext, missingID, ""), nil)
|
||||
db.EXPECT().GetChatModelConfigByID(gomock.Any(), missingID).Return(database.ChatModelConfig{}, sql.ErrNoRows)
|
||||
|
||||
server := titleOverrideTestServer(db, logger)
|
||||
@@ -126,7 +100,7 @@ func TestResolveCompactionOverrideConfig_DisabledConfigFallsBack(t *testing.T) {
|
||||
chat, _ := titleOverrideTestChatAndMessages(t)
|
||||
overrideConfig := titleOverrideModelConfig("gpt-4.1", false)
|
||||
|
||||
db.EXPECT().GetChatCompactionModelOverride(gomock.Any()).Return(overrideConfig.ID.String(), nil)
|
||||
db.EXPECT().GetChatOrganizationModelOverride(gomock.Any(), compactionOverrideParams(chat)).Return(orgModelOverride(chat, compactionOverrideContext, overrideConfig.ID, ""), nil)
|
||||
db.EXPECT().GetChatModelConfigByID(gomock.Any(), overrideConfig.ID).Return(overrideConfig, nil)
|
||||
|
||||
server := titleOverrideTestServer(db, logger)
|
||||
@@ -147,7 +121,7 @@ func TestResolveCompactionOverrideConfig_MissingCredentialsFallsBack(t *testing.
|
||||
providerID := uuid.New()
|
||||
overrideConfig.AIProviderID = uuid.NullUUID{UUID: providerID, Valid: true}
|
||||
|
||||
db.EXPECT().GetChatCompactionModelOverride(gomock.Any()).Return(overrideConfig.ID.String(), nil)
|
||||
db.EXPECT().GetChatOrganizationModelOverride(gomock.Any(), compactionOverrideParams(chat)).Return(orgModelOverride(chat, compactionOverrideContext, overrideConfig.ID, ""), nil)
|
||||
db.EXPECT().GetChatModelConfigByID(gomock.Any(), overrideConfig.ID).Return(overrideConfig, nil)
|
||||
db.EXPECT().GetAIProviderByID(gomock.Any(), providerID).Return(database.AIProvider{
|
||||
ID: providerID,
|
||||
@@ -182,7 +156,7 @@ func TestCompactionOverride_SetUsable(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
overrideConfig.Options = options
|
||||
|
||||
db.EXPECT().GetChatCompactionModelOverride(gomock.Any()).Return(overrideConfig.ID.String()+":high", nil)
|
||||
db.EXPECT().GetChatOrganizationModelOverride(gomock.Any(), compactionOverrideParams(chat)).Return(orgModelOverride(chat, compactionOverrideContext, overrideConfig.ID, "high"), nil)
|
||||
db.EXPECT().GetChatModelConfigByID(gomock.Any(), overrideConfig.ID).Return(overrideConfig, nil)
|
||||
db.EXPECT().GetAIProviderByID(gomock.Any(), providerID).Return(aibridgeTestAIProvider(providerID, "primary-openai", database.AIProviderTypeOpenai), nil).AnyTimes()
|
||||
db.EXPECT().GetAIProviderKeysByProviderID(gomock.Any(), providerID).Return([]database.AIProviderKey{{
|
||||
|
||||
@@ -15,7 +15,6 @@ import (
|
||||
"tailscale.com/util/singleflight"
|
||||
|
||||
"github.com/coder/coder/v2/coderd/database"
|
||||
"github.com/coder/coder/v2/codersdk"
|
||||
"github.com/coder/quartz"
|
||||
)
|
||||
|
||||
@@ -33,8 +32,14 @@ type cachedProviders struct {
|
||||
expiresAt time.Time
|
||||
}
|
||||
|
||||
type advisorRuntimeConfig struct {
|
||||
Enabled bool `json:"enabled"`
|
||||
MaxUsesPerRun int `json:"max_uses_per_run"`
|
||||
MaxOutputTokens int64 `json:"max_output_tokens"`
|
||||
}
|
||||
|
||||
type cachedAdvisorConfig struct {
|
||||
config codersdk.AdvisorConfig
|
||||
config advisorRuntimeConfig
|
||||
expiresAt time.Time
|
||||
}
|
||||
|
||||
@@ -66,7 +71,7 @@ type chatConfigCache struct {
|
||||
// Advisor configuration (singleton).
|
||||
advisorConfig *cachedAdvisorConfig
|
||||
advisorConfigGeneration uint64
|
||||
advisorConfigFetches singleflight.Group[string, codersdk.AdvisorConfig]
|
||||
advisorConfigFetches singleflight.Group[string, advisorRuntimeConfig]
|
||||
}
|
||||
|
||||
func newChatConfigCache(ctx context.Context, db database.Store, clock quartz.Clock) *chatConfigCache {
|
||||
@@ -262,7 +267,7 @@ func (c *chatConfigCache) InvalidateAdvisorConfig() {
|
||||
// this cache saves a per-turn DB round trip on chats that reference the
|
||||
// advisor. Parse errors and lookup errors are surfaced to the caller;
|
||||
// callers that prefer silent fallback handle that at the call site.
|
||||
func (c *chatConfigCache) AdvisorConfig(ctx context.Context) (codersdk.AdvisorConfig, error) {
|
||||
func (c *chatConfigCache) AdvisorConfig(ctx context.Context) (advisorRuntimeConfig, error) {
|
||||
if config, ok := c.cachedAdvisorConfig(); ok {
|
||||
return config, nil
|
||||
}
|
||||
@@ -272,35 +277,35 @@ func (c *chatConfigCache) AdvisorConfig(ctx context.Context) (codersdk.AdvisorCo
|
||||
ctx,
|
||||
&c.advisorConfigFetches,
|
||||
fmt.Sprintf("%d:advisor", generation),
|
||||
func() (codersdk.AdvisorConfig, error) {
|
||||
func() (advisorRuntimeConfig, error) {
|
||||
if cached, ok := c.cachedAdvisorConfig(); ok {
|
||||
return cached, nil
|
||||
}
|
||||
|
||||
raw, err := c.db.GetChatAdvisorConfig(c.ctx)
|
||||
if err != nil {
|
||||
return codersdk.AdvisorConfig{}, err
|
||||
return advisorRuntimeConfig{}, err
|
||||
}
|
||||
var cfg codersdk.AdvisorConfig
|
||||
var cfg advisorRuntimeConfig
|
||||
if err := json.Unmarshal([]byte(raw), &cfg); err != nil {
|
||||
return codersdk.AdvisorConfig{}, err
|
||||
return advisorRuntimeConfig{}, err
|
||||
}
|
||||
c.storeAdvisorConfig(generation, cfg)
|
||||
return cfg, nil
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return codersdk.AdvisorConfig{}, err
|
||||
return advisorRuntimeConfig{}, err
|
||||
}
|
||||
return config, nil
|
||||
}
|
||||
|
||||
func (c *chatConfigCache) cachedAdvisorConfig() (codersdk.AdvisorConfig, bool) {
|
||||
func (c *chatConfigCache) cachedAdvisorConfig() (advisorRuntimeConfig, bool) {
|
||||
c.mu.RLock()
|
||||
entry := c.advisorConfig
|
||||
c.mu.RUnlock()
|
||||
if entry == nil {
|
||||
return codersdk.AdvisorConfig{}, false
|
||||
return advisorRuntimeConfig{}, false
|
||||
}
|
||||
if c.clock.Now().Before(entry.expiresAt) {
|
||||
return entry.config, true
|
||||
@@ -312,7 +317,7 @@ func (c *chatConfigCache) cachedAdvisorConfig() (codersdk.AdvisorConfig, bool) {
|
||||
}
|
||||
c.mu.Unlock()
|
||||
|
||||
return codersdk.AdvisorConfig{}, false
|
||||
return advisorRuntimeConfig{}, false
|
||||
}
|
||||
|
||||
func (c *chatConfigCache) advisorConfigGenerationSnapshot() uint64 {
|
||||
@@ -322,7 +327,7 @@ func (c *chatConfigCache) advisorConfigGenerationSnapshot() uint64 {
|
||||
return generation
|
||||
}
|
||||
|
||||
func (c *chatConfigCache) storeAdvisorConfig(generation uint64, config codersdk.AdvisorConfig) {
|
||||
func (c *chatConfigCache) storeAdvisorConfig(generation uint64, config advisorRuntimeConfig) {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@ import (
|
||||
"github.com/coder/coder/v2/coderd/database/dbtestutil"
|
||||
coderdpubsub "github.com/coder/coder/v2/coderd/pubsub"
|
||||
"github.com/coder/coder/v2/coderd/x/chatd/chatprovider"
|
||||
"github.com/coder/coder/v2/codersdk"
|
||||
"github.com/coder/coder/v2/testutil"
|
||||
"github.com/coder/quartz"
|
||||
)
|
||||
@@ -777,7 +776,7 @@ func TestConfigCache_AdvisorConfig_EmptyJSONYieldsZeroValue(t *testing.T) {
|
||||
|
||||
cfg, err := cache.AdvisorConfig(ctx)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, codersdk.AdvisorConfig{}, cfg)
|
||||
require.Equal(t, advisorRuntimeConfig{}, cfg)
|
||||
}
|
||||
|
||||
// Guards the pubsub-driven invalidation path. Without this, an admin
|
||||
@@ -842,7 +841,7 @@ func TestConfigCache_InvalidateAdvisorConfig_BlocksStaleInFlight(t *testing.T) {
|
||||
cache := newChatConfigCache(ctx, store, clock)
|
||||
|
||||
type result struct {
|
||||
config codersdk.AdvisorConfig
|
||||
config advisorRuntimeConfig
|
||||
err error
|
||||
}
|
||||
|
||||
|
||||
@@ -1,81 +0,0 @@
|
||||
package chatd
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/google/uuid"
|
||||
|
||||
"github.com/coder/coder/v2/codersdk"
|
||||
)
|
||||
|
||||
// ChatPersonalModelOverrideKeyPrefix is the user config key prefix for
|
||||
// chat personal model overrides. Values under this prefix should be parsed
|
||||
// with ParseChatPersonalModelOverride so malformed values use one fallback.
|
||||
const ChatPersonalModelOverrideKeyPrefix = "chat_personal_model_override:"
|
||||
|
||||
// ChatPersonalModelOverrideKey returns the user config key for a chat
|
||||
// personal model override context. Values stored at the returned key should
|
||||
// use ParseChatPersonalModelOverride so malformed values fall back safely.
|
||||
func ChatPersonalModelOverrideKey(
|
||||
overrideContext codersdk.ChatPersonalModelOverrideContext,
|
||||
) string {
|
||||
return ChatPersonalModelOverrideKeyPrefix + string(overrideContext)
|
||||
}
|
||||
|
||||
// ParsedChatPersonalModelOverride is a parsed personal model override value.
|
||||
// When Malformed is true, Mode is the provided default and ModelConfigID is
|
||||
// uuid.Nil.
|
||||
type ParsedChatPersonalModelOverride struct {
|
||||
Mode codersdk.ChatPersonalModelOverrideMode
|
||||
ModelConfigID uuid.UUID
|
||||
ReasoningEffort *string
|
||||
Malformed bool
|
||||
}
|
||||
|
||||
// ParseChatPersonalModelOverride parses a stored personal model override.
|
||||
// Empty values return defaultMode without marking the value malformed.
|
||||
// Malformed values return defaultMode, uuid.Nil, and Malformed true.
|
||||
func ParseChatPersonalModelOverride(
|
||||
raw string,
|
||||
defaultMode codersdk.ChatPersonalModelOverrideMode,
|
||||
) ParsedChatPersonalModelOverride {
|
||||
trimmed := strings.TrimSpace(raw)
|
||||
if trimmed == "" {
|
||||
return ParsedChatPersonalModelOverride{Mode: defaultMode}
|
||||
}
|
||||
|
||||
switch trimmed {
|
||||
case string(codersdk.ChatPersonalModelOverrideModeChatDefault):
|
||||
return ParsedChatPersonalModelOverride{
|
||||
Mode: codersdk.ChatPersonalModelOverrideModeChatDefault,
|
||||
}
|
||||
case string(codersdk.ChatPersonalModelOverrideModeDeploymentDefault):
|
||||
return ParsedChatPersonalModelOverride{
|
||||
Mode: codersdk.ChatPersonalModelOverrideModeDeploymentDefault,
|
||||
}
|
||||
}
|
||||
|
||||
mode, rawModelConfigID, ok := strings.Cut(trimmed, ":")
|
||||
if !ok || mode != string(codersdk.ChatPersonalModelOverrideModeModel) {
|
||||
return ParsedChatPersonalModelOverride{
|
||||
Mode: defaultMode,
|
||||
Malformed: true,
|
||||
}
|
||||
}
|
||||
rawID, rawEffort, hasEffort := strings.Cut(rawModelConfigID, ":")
|
||||
modelConfigID, err := uuid.Parse(rawID)
|
||||
if err != nil || (hasEffort && rawEffort == "") {
|
||||
return ParsedChatPersonalModelOverride{
|
||||
Mode: defaultMode,
|
||||
Malformed: true,
|
||||
}
|
||||
}
|
||||
parsed := ParsedChatPersonalModelOverride{
|
||||
Mode: codersdk.ChatPersonalModelOverrideModeModel,
|
||||
ModelConfigID: modelConfigID,
|
||||
}
|
||||
if hasEffort {
|
||||
parsed.ReasoningEffort = &rawEffort
|
||||
}
|
||||
return parsed
|
||||
}
|
||||
@@ -1,123 +0,0 @@
|
||||
package chatd_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/coder/coder/v2/coderd/util/ptr"
|
||||
"github.com/coder/coder/v2/coderd/x/chatd"
|
||||
"github.com/coder/coder/v2/codersdk"
|
||||
)
|
||||
|
||||
func TestChatPersonalModelOverrideKey(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
require.Equal(
|
||||
t,
|
||||
"chat_personal_model_override:root",
|
||||
chatd.ChatPersonalModelOverrideKey(codersdk.ChatPersonalModelOverrideContextRoot),
|
||||
)
|
||||
}
|
||||
|
||||
func TestParseChatPersonalModelOverride(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
modelConfigID := uuid.MustParse("11111111-1111-1111-1111-111111111111")
|
||||
tests := []struct {
|
||||
name string
|
||||
raw string
|
||||
defaultMode codersdk.ChatPersonalModelOverrideMode
|
||||
want chatd.ParsedChatPersonalModelOverride
|
||||
}{
|
||||
{
|
||||
name: "EmptyUsesDefault",
|
||||
raw: "",
|
||||
defaultMode: codersdk.ChatPersonalModelOverrideModeDeploymentDefault,
|
||||
want: chatd.ParsedChatPersonalModelOverride{
|
||||
Mode: codersdk.ChatPersonalModelOverrideModeDeploymentDefault,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ChatDefault",
|
||||
raw: string(codersdk.ChatPersonalModelOverrideModeChatDefault),
|
||||
defaultMode: codersdk.ChatPersonalModelOverrideModeDeploymentDefault,
|
||||
want: chatd.ParsedChatPersonalModelOverride{
|
||||
Mode: codersdk.ChatPersonalModelOverrideModeChatDefault,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "DeploymentDefault",
|
||||
raw: string(codersdk.ChatPersonalModelOverrideModeDeploymentDefault),
|
||||
defaultMode: codersdk.ChatPersonalModelOverrideModeChatDefault,
|
||||
want: chatd.ParsedChatPersonalModelOverride{
|
||||
Mode: codersdk.ChatPersonalModelOverrideModeDeploymentDefault,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Model",
|
||||
raw: "model:" + modelConfigID.String(),
|
||||
defaultMode: codersdk.ChatPersonalModelOverrideModeDeploymentDefault,
|
||||
want: chatd.ParsedChatPersonalModelOverride{
|
||||
Mode: codersdk.ChatPersonalModelOverrideModeModel,
|
||||
ModelConfigID: modelConfigID,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ModelWithReasoningEffort",
|
||||
raw: "model:" + modelConfigID.String() + ":high",
|
||||
defaultMode: codersdk.ChatPersonalModelOverrideModeDeploymentDefault,
|
||||
want: chatd.ParsedChatPersonalModelOverride{
|
||||
Mode: codersdk.ChatPersonalModelOverrideModeModel,
|
||||
ModelConfigID: modelConfigID,
|
||||
ReasoningEffort: ptr.Ref("high"),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ModelWithEmptyReasoningEffort",
|
||||
raw: "model:" + modelConfigID.String() + ":",
|
||||
defaultMode: codersdk.ChatPersonalModelOverrideModeDeploymentDefault,
|
||||
want: chatd.ParsedChatPersonalModelOverride{
|
||||
Mode: codersdk.ChatPersonalModelOverrideModeDeploymentDefault,
|
||||
Malformed: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "InvalidModelUUID",
|
||||
raw: "model:not-a-uuid",
|
||||
defaultMode: codersdk.ChatPersonalModelOverrideModeDeploymentDefault,
|
||||
want: chatd.ParsedChatPersonalModelOverride{
|
||||
Mode: codersdk.ChatPersonalModelOverrideModeDeploymentDefault,
|
||||
Malformed: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "UnknownValue",
|
||||
raw: "unknown",
|
||||
defaultMode: codersdk.ChatPersonalModelOverrideModeChatDefault,
|
||||
want: chatd.ParsedChatPersonalModelOverride{
|
||||
Mode: codersdk.ChatPersonalModelOverrideModeChatDefault,
|
||||
Malformed: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "OuterWhitespace",
|
||||
raw: " \tmodel:" + modelConfigID.String() + "\n",
|
||||
defaultMode: codersdk.ChatPersonalModelOverrideModeDeploymentDefault,
|
||||
want: chatd.ParsedChatPersonalModelOverride{
|
||||
Mode: codersdk.ChatPersonalModelOverrideModeModel,
|
||||
ModelConfigID: modelConfigID,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
got := chatd.ParseChatPersonalModelOverride(tt.raw, tt.defaultMode)
|
||||
require.Equal(t, tt.want, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -643,7 +643,7 @@ func TestMaybeGenerateChatTitleAppliesModelConfigReasoningEffort(t *testing.T) {
|
||||
}
|
||||
|
||||
db := dbmock.NewMockStore(gomock.NewController(t))
|
||||
db.EXPECT().GetChatTitleGenerationModelOverride(gomock.Any()).Return("", nil)
|
||||
db.EXPECT().GetChatOrganizationModelOverride(gomock.Any(), titleGenerationOverrideParams(chat)).Return(database.ChatOrganizationModelOverride{}, sql.ErrNoRows)
|
||||
db.EXPECT().UpdateChatTitleByID(gomock.Any(), database.UpdateChatTitleByIDParams{
|
||||
ID: chat.ID,
|
||||
Title: "Reasoning title",
|
||||
|
||||
+155
-63
@@ -20,6 +20,7 @@ import (
|
||||
"github.com/coder/coder/v2/coderd/database/dbauthz"
|
||||
dbpubsub "github.com/coder/coder/v2/coderd/database/pubsub"
|
||||
coderdpubsub "github.com/coder/coder/v2/coderd/pubsub"
|
||||
"github.com/coder/coder/v2/coderd/util/ptr"
|
||||
"github.com/coder/coder/v2/coderd/x/agenthooks/dispatch"
|
||||
"github.com/coder/coder/v2/coderd/x/chatd/chathooks"
|
||||
"github.com/coder/coder/v2/coderd/x/chatd/chatprompt"
|
||||
@@ -72,6 +73,28 @@ type modelOverrideProviderKeysResolver func(
|
||||
uuid.UUID,
|
||||
) (chatprovider.ProviderAPIKeys, error)
|
||||
|
||||
type parsedModelOverride struct {
|
||||
modelConfigID uuid.UUID
|
||||
reasoningEffort *string
|
||||
}
|
||||
|
||||
func parseModelOverride(raw string) (parsedModelOverride, bool) {
|
||||
trimmed := strings.TrimSpace(raw)
|
||||
if trimmed == "" {
|
||||
return parsedModelOverride{}, true
|
||||
}
|
||||
rawID, rawEffort, hasEffort := strings.Cut(trimmed, ":")
|
||||
modelConfigID, err := uuid.Parse(rawID)
|
||||
if err != nil || (hasEffort && rawEffort == "") {
|
||||
return parsedModelOverride{}, false
|
||||
}
|
||||
parsed := parsedModelOverride{modelConfigID: modelConfigID}
|
||||
if hasEffort {
|
||||
parsed.reasoningEffort = &rawEffort
|
||||
}
|
||||
return parsed, true
|
||||
}
|
||||
|
||||
const (
|
||||
subagentAwaitPollInterval = 200 * time.Millisecond
|
||||
subagentAwaitFallbackPoll = 5 * time.Second
|
||||
@@ -136,19 +159,22 @@ func subagentModelOverrideLogLabel(
|
||||
func readSubagentModelOverride(
|
||||
ctx context.Context,
|
||||
db database.Store,
|
||||
organizationID uuid.UUID,
|
||||
overrideContext codersdk.ChatModelOverrideContext,
|
||||
) (string, error) {
|
||||
) (database.ChatOrganizationModelOverride, error) {
|
||||
switch overrideContext {
|
||||
case codersdk.ChatModelOverrideContextGeneral:
|
||||
return db.GetChatGeneralModelOverride(ctx)
|
||||
case codersdk.ChatModelOverrideContextExplore:
|
||||
return db.GetChatExploreModelOverride(ctx)
|
||||
case codersdk.ChatModelOverrideContextGeneral,
|
||||
codersdk.ChatModelOverrideContextExplore:
|
||||
default:
|
||||
return "", xerrors.Errorf(
|
||||
return database.ChatOrganizationModelOverride{}, xerrors.Errorf(
|
||||
"unsupported subagent model override context %q",
|
||||
overrideContext,
|
||||
)
|
||||
}
|
||||
return db.GetChatOrganizationModelOverride(ctx, database.GetChatOrganizationModelOverrideParams{
|
||||
OrganizationID: organizationID,
|
||||
Context: string(overrideContext),
|
||||
})
|
||||
}
|
||||
|
||||
func personalModelOverrideContextForSubagent(
|
||||
@@ -303,6 +329,96 @@ func (p *Server) resolveConfiguredModelOverride(
|
||||
return modelConfig, providerName, parsed.reasoningEffort, true, nil
|
||||
}
|
||||
|
||||
// resolveOrganizationModelOverride resolves an override row whose composite
|
||||
// foreign key already binds the model config to the same organization.
|
||||
func (p *Server) resolveOrganizationModelOverride(
|
||||
ctx context.Context,
|
||||
overrideContext string,
|
||||
override database.ChatOrganizationModelOverride,
|
||||
ownerID uuid.UUID,
|
||||
resolveModelConfig modelOverrideConfigResolver,
|
||||
resolveProviderKeys modelOverrideProviderKeysResolver,
|
||||
failureMode modelOverrideFailureMode,
|
||||
) (database.ChatModelConfig, string, *string, bool, error) {
|
||||
modelConfig, providerName, err := resolveModelConfig(ctx, override.ModelConfigID)
|
||||
if err != nil {
|
||||
if failureMode == modelOverrideFailureModeHard {
|
||||
label := modelOverrideErrorLabel(overrideContext)
|
||||
switch {
|
||||
case errors.Is(err, sql.ErrNoRows):
|
||||
return database.ChatModelConfig{}, "", ptr.FromNullString(override.ReasoningEffort), true, xerrors.Errorf(
|
||||
"%s model override is unavailable: %s",
|
||||
label,
|
||||
override.ModelConfigID,
|
||||
)
|
||||
case errors.Is(err, errInvalidModelOverrideMetadata):
|
||||
return database.ChatModelConfig{}, "", ptr.FromNullString(override.ReasoningEffort), true, xerrors.Errorf(
|
||||
"%s model override metadata is invalid for %s: %w",
|
||||
label,
|
||||
override.ModelConfigID,
|
||||
err,
|
||||
)
|
||||
default:
|
||||
return database.ChatModelConfig{}, "", ptr.FromNullString(override.ReasoningEffort), true, xerrors.Errorf(
|
||||
"resolve %s model override %s: %w",
|
||||
label,
|
||||
override.ModelConfigID,
|
||||
err,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
switch {
|
||||
case errors.Is(err, sql.ErrNoRows):
|
||||
p.logger.Info(ctx,
|
||||
"model override is unavailable, ignoring",
|
||||
slog.F("override_context", overrideContext),
|
||||
slog.F("model_config_id", override.ModelConfigID),
|
||||
)
|
||||
case errors.Is(err, errInvalidModelOverrideMetadata):
|
||||
p.logger.Info(ctx,
|
||||
"model override metadata is invalid, ignoring",
|
||||
slog.F("override_context", overrideContext),
|
||||
slog.F("model_config_id", override.ModelConfigID),
|
||||
slog.Error(err),
|
||||
)
|
||||
default:
|
||||
p.logger.Warn(ctx,
|
||||
"failed to resolve model override, ignoring",
|
||||
slog.F("override_context", overrideContext),
|
||||
slog.F("model_config_id", override.ModelConfigID),
|
||||
slog.Error(err),
|
||||
)
|
||||
}
|
||||
return database.ChatModelConfig{}, "", nil, false, nil
|
||||
}
|
||||
|
||||
providerKeys, err := resolveProviderKeys(ctx, ownerID, modelConfigAIProviderID(modelConfig))
|
||||
if err != nil {
|
||||
return database.ChatModelConfig{}, "", nil, false, xerrors.Errorf(
|
||||
"resolve provider API keys: %w",
|
||||
err,
|
||||
)
|
||||
}
|
||||
if !userCanUseProviderKeys(providerKeys, providerName) {
|
||||
if failureMode == modelOverrideFailureModeHard {
|
||||
return database.ChatModelConfig{}, "", ptr.FromNullString(override.ReasoningEffort), true, xerrors.Errorf(
|
||||
"%s model override credentials are unavailable for provider %q",
|
||||
modelOverrideErrorLabel(overrideContext),
|
||||
providerName,
|
||||
)
|
||||
}
|
||||
p.logger.Info(ctx,
|
||||
"model override credentials are unavailable, ignoring",
|
||||
slog.F("override_context", overrideContext),
|
||||
slog.F("model_config_id", override.ModelConfigID),
|
||||
slog.F("provider", providerName),
|
||||
)
|
||||
return database.ChatModelConfig{}, "", nil, false, nil
|
||||
}
|
||||
return modelConfig, providerName, ptr.FromNullString(override.ReasoningEffort), true, nil
|
||||
}
|
||||
|
||||
func (p *Server) resolvePersonalSubagentModelConfigID(
|
||||
ctx context.Context,
|
||||
ownerID uuid.UUID,
|
||||
@@ -313,13 +429,11 @@ func (p *Server) resolvePersonalSubagentModelConfigID(
|
||||
if err != nil {
|
||||
return uuid.Nil, nil, false, err
|
||||
}
|
||||
raw, err := p.db.GetUserChatPersonalModelOverride(
|
||||
ctx,
|
||||
database.GetUserChatPersonalModelOverrideParams{
|
||||
UserID: ownerID,
|
||||
Key: ChatPersonalModelOverrideKey(personalContext),
|
||||
},
|
||||
)
|
||||
override, err := p.db.GetChatUserModelOverride(ctx, database.GetChatUserModelOverrideParams{
|
||||
UserID: ownerID,
|
||||
OrganizationID: organizationID,
|
||||
Context: string(personalContext),
|
||||
})
|
||||
if err != nil {
|
||||
if !xerrors.Is(err, sql.ErrNoRows) {
|
||||
return uuid.Nil, nil, false, xerrors.Errorf(
|
||||
@@ -328,48 +442,42 @@ func (p *Server) resolvePersonalSubagentModelConfigID(
|
||||
err,
|
||||
)
|
||||
}
|
||||
raw = ""
|
||||
return uuid.Nil, nil, false, nil
|
||||
}
|
||||
|
||||
parsed := ParseChatPersonalModelOverride(
|
||||
raw,
|
||||
codersdk.ChatPersonalModelOverrideModeDeploymentDefault,
|
||||
)
|
||||
if parsed.Malformed {
|
||||
p.logger.Debug(ctx,
|
||||
"personal model override is malformed, using chat organization default",
|
||||
slog.F("override_context", overrideContext),
|
||||
slog.F("owner_id", ownerID),
|
||||
slog.F("raw_model_config_id", strings.TrimSpace(raw)),
|
||||
)
|
||||
}
|
||||
switch parsed.Mode {
|
||||
switch codersdk.ChatPersonalModelOverrideMode(override.Mode) {
|
||||
case codersdk.ChatPersonalModelOverrideModeChatDefault:
|
||||
return uuid.Nil, nil, true, nil
|
||||
case codersdk.ChatPersonalModelOverrideModeDeploymentDefault:
|
||||
case codersdk.ChatPersonalModelOverrideModeModel:
|
||||
if !override.ModelConfigID.Valid {
|
||||
p.logger.Warn(ctx,
|
||||
"personal model override has no model config, using deployment default",
|
||||
slog.F("override_context", overrideContext),
|
||||
slog.F("owner_id", ownerID),
|
||||
)
|
||||
break
|
||||
}
|
||||
modelConfig, ok, err := p.resolvePersonalModelOverride(
|
||||
ctx,
|
||||
overrideContext,
|
||||
ownerID,
|
||||
organizationID,
|
||||
parsed.ModelConfigID,
|
||||
override.ModelConfigID.UUID,
|
||||
)
|
||||
if err != nil {
|
||||
return uuid.Nil, nil, false, err
|
||||
}
|
||||
if ok {
|
||||
return modelConfig.ID, parsed.ReasoningEffort, true, nil
|
||||
return modelConfig.ID, ptr.FromNullString(override.ReasoningEffort), true, nil
|
||||
}
|
||||
default:
|
||||
p.logger.Warn(ctx,
|
||||
"unsupported personal model override mode, using chat organization default",
|
||||
"unsupported personal model override mode, using deployment default",
|
||||
slog.F("override_context", overrideContext),
|
||||
slog.F("owner_id", ownerID),
|
||||
slog.F("mode", parsed.Mode),
|
||||
slog.F("mode", override.Mode),
|
||||
)
|
||||
}
|
||||
|
||||
return uuid.Nil, nil, false, nil
|
||||
}
|
||||
|
||||
@@ -377,34 +485,21 @@ func (p *Server) resolvePersonalModelOverride(
|
||||
ctx context.Context,
|
||||
overrideContext codersdk.ChatModelOverrideContext,
|
||||
ownerID uuid.UUID,
|
||||
organizationID uuid.UUID,
|
||||
modelConfigID uuid.UUID,
|
||||
) (database.ChatModelConfig, bool, error) {
|
||||
modelConfig, providerName, err := p.resolveModelConfigForOrganization(
|
||||
ctx,
|
||||
ownerID,
|
||||
organizationID,
|
||||
modelConfigID,
|
||||
)
|
||||
modelConfig, providerName, err := p.resolveModelConfigAndNormalizedProvider(ctx, ownerID, modelConfigID)
|
||||
if err != nil {
|
||||
switch {
|
||||
case errors.Is(err, errModelConfigOutsideOrganization):
|
||||
p.logger.Debug(ctx,
|
||||
"personal model override belongs to another organization, using chat organization default",
|
||||
slog.F("override_context", overrideContext),
|
||||
slog.F("owner_id", ownerID),
|
||||
slog.F("model_config_id", modelConfigID),
|
||||
)
|
||||
case xerrors.Is(err, sql.ErrNoRows):
|
||||
p.logger.Debug(ctx,
|
||||
"personal model override is unavailable, using chat organization default",
|
||||
"personal model override is unavailable, using deployment default",
|
||||
slog.F("override_context", overrideContext),
|
||||
slog.F("owner_id", ownerID),
|
||||
slog.F("model_config_id", modelConfigID),
|
||||
)
|
||||
case errors.Is(err, errInvalidModelOverrideMetadata):
|
||||
p.logger.Debug(ctx,
|
||||
"personal model override metadata is invalid, using chat organization default",
|
||||
"personal model override metadata is invalid, using deployment default",
|
||||
slog.F("override_context", overrideContext),
|
||||
slog.F("owner_id", ownerID),
|
||||
slog.F("model_config_id", modelConfigID),
|
||||
@@ -412,7 +507,7 @@ func (p *Server) resolvePersonalModelOverride(
|
||||
)
|
||||
default:
|
||||
p.logger.Warn(ctx,
|
||||
"failed to resolve personal model override, using chat organization default",
|
||||
"failed to resolve personal model override, using deployment default",
|
||||
slog.F("override_context", overrideContext),
|
||||
slog.F("owner_id", ownerID),
|
||||
slog.F("model_config_id", modelConfigID),
|
||||
@@ -423,14 +518,11 @@ func (p *Server) resolvePersonalModelOverride(
|
||||
}
|
||||
providerKeys, err := p.resolveUserProviderAPIKeys(ctx, ownerID, modelConfigAIProviderID(modelConfig))
|
||||
if err != nil {
|
||||
return database.ChatModelConfig{}, false, xerrors.Errorf(
|
||||
"resolve provider API keys: %w",
|
||||
err,
|
||||
)
|
||||
return database.ChatModelConfig{}, false, xerrors.Errorf("resolve provider API keys: %w", err)
|
||||
}
|
||||
if !userCanUseProviderKeys(providerKeys, providerName) {
|
||||
p.logger.Debug(ctx,
|
||||
"personal model override credentials are unavailable, using chat organization default",
|
||||
"personal model override credentials are unavailable, using deployment default",
|
||||
slog.F("override_context", overrideContext),
|
||||
slog.F("owner_id", ownerID),
|
||||
slog.F("model_config_id", modelConfigID),
|
||||
@@ -451,10 +543,7 @@ func (p *Server) resolveSubagentModelConfigID(
|
||||
chatdCtx := dbauthz.AsChatd(ctx)
|
||||
personalOverridesEnabled, err := p.db.GetChatPersonalModelOverridesEnabled(chatdCtx)
|
||||
if err != nil {
|
||||
return uuid.Nil, nil, xerrors.Errorf(
|
||||
"get chat personal model overrides enabled: %w",
|
||||
err,
|
||||
)
|
||||
return uuid.Nil, nil, xerrors.Errorf("get chat personal model overrides enabled: %w", err)
|
||||
}
|
||||
if personalOverridesEnabled {
|
||||
modelConfigID, reasoningEffort, resolved, err := p.resolvePersonalSubagentModelConfigID(
|
||||
@@ -471,21 +560,24 @@ func (p *Server) resolveSubagentModelConfigID(
|
||||
}
|
||||
}
|
||||
|
||||
raw, err := readSubagentModelOverride(chatdCtx, p.db, overrideContext)
|
||||
override, err := readSubagentModelOverride(chatdCtx, p.db, organizationID, overrideContext)
|
||||
if err != nil {
|
||||
if xerrors.Is(err, sql.ErrNoRows) {
|
||||
return uuid.Nil, nil, nil
|
||||
}
|
||||
return uuid.Nil, nil, xerrors.Errorf(
|
||||
"get %s model override: %w",
|
||||
subagentModelOverrideLogLabel(overrideContext),
|
||||
err,
|
||||
)
|
||||
}
|
||||
modelConfig, _, reasoningEffort, ok, err := p.resolveConfiguredModelOverride(
|
||||
modelConfig, _, reasoningEffort, ok, err := p.resolveOrganizationModelOverride(
|
||||
chatdCtx,
|
||||
string(overrideContext),
|
||||
raw,
|
||||
override,
|
||||
ownerID,
|
||||
func(ctx context.Context, modelConfigID uuid.UUID) (database.ChatModelConfig, string, error) {
|
||||
return p.resolveModelConfigForOrganization(ctx, ownerID, organizationID, modelConfigID)
|
||||
return p.resolveModelConfigAndNormalizedProvider(ctx, ownerID, modelConfigID)
|
||||
},
|
||||
p.resolveUserProviderAPIKeys,
|
||||
modelOverrideFailureModeSoft,
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
"slices"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
@@ -789,25 +790,57 @@ func enableInternalChatPersonalModelOverrides(
|
||||
)
|
||||
}
|
||||
|
||||
func upsertInternalChatOrganizationModelOverride(
|
||||
t *testing.T,
|
||||
db database.Store,
|
||||
organizationID uuid.UUID,
|
||||
overrideContext codersdk.ChatModelOverrideContext,
|
||||
raw string,
|
||||
) {
|
||||
t.Helper()
|
||||
rawModelConfigID, effort, hasEffort := strings.Cut(raw, ":")
|
||||
modelConfigID, err := uuid.Parse(rawModelConfigID)
|
||||
require.NoError(t, err)
|
||||
params := database.UpsertChatOrganizationModelOverrideParams{
|
||||
OrganizationID: organizationID,
|
||||
Context: string(overrideContext),
|
||||
ModelConfigID: modelConfigID,
|
||||
}
|
||||
if hasEffort {
|
||||
params.ReasoningEffort = sql.NullString{String: effort, Valid: true}
|
||||
}
|
||||
require.NoError(t, db.UpsertChatOrganizationModelOverride(systemRestrictedTestContext(t), params))
|
||||
}
|
||||
|
||||
func upsertInternalUserChatPersonalModelOverride(
|
||||
t *testing.T,
|
||||
db database.Store,
|
||||
userID uuid.UUID,
|
||||
organizationID uuid.UUID,
|
||||
overrideContext codersdk.ChatPersonalModelOverrideContext,
|
||||
raw string,
|
||||
) {
|
||||
t.Helper()
|
||||
require.NoError(
|
||||
t,
|
||||
db.UpsertUserChatPersonalModelOverride(
|
||||
systemRestrictedTestContext(t),
|
||||
database.UpsertUserChatPersonalModelOverrideParams{
|
||||
UserID: userID,
|
||||
Key: ChatPersonalModelOverrideKey(overrideContext),
|
||||
Value: raw,
|
||||
},
|
||||
),
|
||||
)
|
||||
mode, modelConfigID, reasoningEffort := raw, uuid.NullUUID{}, sql.NullString{}
|
||||
if rawMode, remainder, ok := strings.Cut(raw, ":"); ok {
|
||||
mode = rawMode
|
||||
rawModelConfigID, rawEffort, hasEffort := strings.Cut(remainder, ":")
|
||||
modelConfigID = uuid.NullUUID{UUID: uuid.MustParse(rawModelConfigID), Valid: true}
|
||||
if hasEffort {
|
||||
reasoningEffort = sql.NullString{String: rawEffort, Valid: true}
|
||||
}
|
||||
}
|
||||
require.NoError(t, db.UpsertChatUserModelOverride(
|
||||
systemRestrictedTestContext(t),
|
||||
database.UpsertChatUserModelOverrideParams{
|
||||
UserID: userID,
|
||||
OrganizationID: organizationID,
|
||||
Context: string(overrideContext),
|
||||
Mode: mode,
|
||||
ModelConfigID: modelConfigID,
|
||||
ReasoningEffort: reasoningEffort,
|
||||
},
|
||||
))
|
||||
}
|
||||
|
||||
func TestCreateChildSubagentChatInheritsWorkspaceBinding(t *testing.T) {
|
||||
@@ -1052,7 +1085,7 @@ func TestSpawnAgent_GeneralUsesConfiguredModelOverride(t *testing.T) {
|
||||
overrideModel := insertInternalChatModelConfig(
|
||||
t, db, org.ID, "general-override-"+uuid.NewString(), true,
|
||||
)
|
||||
require.NoError(t, db.UpsertChatGeneralModelOverride(ctx, overrideModel.ID.String()))
|
||||
upsertInternalChatOrganizationModelOverride(t, db, org.ID, codersdk.ChatModelOverrideContextGeneral, overrideModel.ID.String())
|
||||
parentChat := createInternalParentChat(
|
||||
ctx, t, server, db, org.ID, user.ID, model.ID, "parent-general-override",
|
||||
)
|
||||
@@ -1193,16 +1226,6 @@ func TestSpawnAgent_GeneralHonorsPersonalModelOverrides(t *testing.T) {
|
||||
return deploymentModel.ID
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "MalformedValueUsesDeploymentOverride",
|
||||
enablePersonalOverride: true,
|
||||
personalRaw: func(database.ChatModelConfig) string {
|
||||
return "model:not-a-uuid"
|
||||
},
|
||||
wantModelID: func(_, deploymentModel, _ database.ChatModelConfig) uuid.UUID {
|
||||
return deploymentModel.ID
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
@@ -1221,7 +1244,7 @@ func TestSpawnAgent_GeneralHonorsPersonalModelOverrides(t *testing.T) {
|
||||
"general-deployment-"+uuid.NewString(),
|
||||
true,
|
||||
)
|
||||
require.NoError(t, db.UpsertChatGeneralModelOverride(ctx, deploymentModel.ID.String()))
|
||||
upsertInternalChatOrganizationModelOverride(t, db, org.ID, codersdk.ChatModelOverrideContextGeneral, deploymentModel.ID.String())
|
||||
personalModel := insertInternalChatModelConfig(
|
||||
t,
|
||||
db,
|
||||
@@ -1240,6 +1263,7 @@ func TestSpawnAgent_GeneralHonorsPersonalModelOverrides(t *testing.T) {
|
||||
t,
|
||||
db,
|
||||
user.ID,
|
||||
org.ID,
|
||||
codersdk.ChatPersonalModelOverrideContextGeneral,
|
||||
tt.personalRaw(personalModel),
|
||||
)
|
||||
@@ -1302,7 +1326,7 @@ func TestSpawnAgent_GeneralOverrideLogsAndFallsBackWhenCredentialsUnavailable(t
|
||||
"gpt-4o-mini",
|
||||
true,
|
||||
)
|
||||
require.NoError(t, db.UpsertChatGeneralModelOverride(ctx, overrideModel.ID.String()))
|
||||
upsertInternalChatOrganizationModelOverride(t, db, org.ID, codersdk.ChatModelOverrideContextGeneral, overrideModel.ID.String())
|
||||
parent, err := server.CreateChat(ctx, CreateOptions{
|
||||
OrganizationID: org.ID,
|
||||
OwnerID: user.ID,
|
||||
@@ -1372,7 +1396,7 @@ func TestSpawnAgent_GeneralOverrideLogsAndFallsBackWhenProviderDisabled(t *testi
|
||||
"gpt-4o-mini",
|
||||
true,
|
||||
)
|
||||
require.NoError(t, db.UpsertChatGeneralModelOverride(ctx, overrideModel.ID.String()))
|
||||
upsertInternalChatOrganizationModelOverride(t, db, org.ID, codersdk.ChatModelOverrideContextGeneral, overrideModel.ID.String())
|
||||
parent, err := server.CreateChat(ctx, CreateOptions{
|
||||
OrganizationID: org.ID,
|
||||
OwnerID: user.ID,
|
||||
@@ -1613,11 +1637,11 @@ type personalOverrideErrorStore struct {
|
||||
database.Store
|
||||
}
|
||||
|
||||
func (*personalOverrideErrorStore) GetUserChatPersonalModelOverride(
|
||||
func (*personalOverrideErrorStore) GetChatUserModelOverride(
|
||||
context.Context,
|
||||
database.GetUserChatPersonalModelOverrideParams,
|
||||
) (string, error) {
|
||||
return "", xerrors.New("unexpected personal override lookup")
|
||||
database.GetChatUserModelOverrideParams,
|
||||
) (database.ChatUserModelOverride, error) {
|
||||
return database.ChatUserModelOverride{}, xerrors.New("unexpected personal override lookup")
|
||||
}
|
||||
|
||||
func TestSpawnAgent_ExplicitModelSkipsConfiguredOverrides(t *testing.T) {
|
||||
@@ -1670,14 +1694,15 @@ func TestSpawnAgent_ExplicitModelBeatsConfiguredOverrides(t *testing.T) {
|
||||
selectedModel := insertInternalChatModelConfig(
|
||||
t, db, org.ID, "general-selected-"+uuid.NewString(), true,
|
||||
)
|
||||
require.NoError(t, db.UpsertChatGeneralModelOverride(
|
||||
ctx, deploymentModel.ID.String()+":medium",
|
||||
))
|
||||
upsertInternalChatOrganizationModelOverride(
|
||||
t, db, org.ID, codersdk.ChatModelOverrideContextGeneral, deploymentModel.ID.String()+":medium",
|
||||
)
|
||||
enableInternalChatPersonalModelOverrides(t, db)
|
||||
upsertInternalUserChatPersonalModelOverride(
|
||||
t,
|
||||
db,
|
||||
user.ID,
|
||||
org.ID,
|
||||
codersdk.ChatPersonalModelOverrideContextGeneral,
|
||||
string(codersdk.ChatPersonalModelOverrideModeModel)+":"+personalModel.ID.String()+":low",
|
||||
)
|
||||
@@ -1781,9 +1806,9 @@ func TestSpawnAgent_ExplicitReasoningEffort(t *testing.T) {
|
||||
deploymentModel := insertInternalChatModelConfig(
|
||||
t, db, org.ID, "general-deployment-"+uuid.NewString(), true,
|
||||
)
|
||||
require.NoError(t, db.UpsertChatGeneralModelOverride(
|
||||
ctx, deploymentModel.ID.String()+":low",
|
||||
))
|
||||
upsertInternalChatOrganizationModelOverride(
|
||||
t, db, org.ID, codersdk.ChatModelOverrideContextGeneral, deploymentModel.ID.String()+":low",
|
||||
)
|
||||
parentChat := createInternalParentChat(
|
||||
ctx, t, server, db, org.ID, user.ID, parentModel.ID, "parent-effort-beats-override",
|
||||
)
|
||||
@@ -2104,7 +2129,7 @@ func TestSpawnAgent_ExploreUsesConfiguredModelOverride(t *testing.T) {
|
||||
overrideModel := insertInternalChatModelConfig(
|
||||
t, db, org.ID, "explore-override-"+uuid.NewString(), true,
|
||||
)
|
||||
require.NoError(t, db.UpsertChatExploreModelOverride(ctx, overrideModel.ID.String()))
|
||||
upsertInternalChatOrganizationModelOverride(t, db, org.ID, codersdk.ChatModelOverrideContextExplore, overrideModel.ID.String())
|
||||
parentChat := createInternalParentChat(
|
||||
ctx, t, server, db, org.ID, user.ID, model.ID, "parent-explore-override",
|
||||
)
|
||||
@@ -2288,16 +2313,6 @@ func TestSpawnAgent_ExploreHonorsPersonalModelOverrides(t *testing.T) {
|
||||
return deploymentModel.ID
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "MalformedValueUsesDeploymentOverride",
|
||||
enablePersonalOverride: true,
|
||||
personalRaw: func(database.ChatModelConfig) string {
|
||||
return "not-a-mode"
|
||||
},
|
||||
wantModelID: func(_, _, deploymentModel, _ database.ChatModelConfig) uuid.UUID {
|
||||
return deploymentModel.ID
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
@@ -2323,7 +2338,7 @@ func TestSpawnAgent_ExploreHonorsPersonalModelOverrides(t *testing.T) {
|
||||
"explore-deployment-"+uuid.NewString(),
|
||||
true,
|
||||
)
|
||||
require.NoError(t, db.UpsertChatExploreModelOverride(ctx, deploymentModel.ID.String()))
|
||||
upsertInternalChatOrganizationModelOverride(t, db, org.ID, codersdk.ChatModelOverrideContextExplore, deploymentModel.ID.String())
|
||||
personalModel := insertInternalChatModelConfig(
|
||||
t,
|
||||
db,
|
||||
@@ -2342,6 +2357,7 @@ func TestSpawnAgent_ExploreHonorsPersonalModelOverrides(t *testing.T) {
|
||||
t,
|
||||
db,
|
||||
user.ID,
|
||||
org.ID,
|
||||
codersdk.ChatPersonalModelOverrideContextExplore,
|
||||
tt.personalRaw(personalModel),
|
||||
)
|
||||
@@ -2615,38 +2631,6 @@ func TestSpawnAgent_ExploreSnapshotsTurnStateParentState(t *testing.T) {
|
||||
"Explore child should keep the turn-start MCP snapshot after parent mutations")
|
||||
}
|
||||
|
||||
func TestSpawnAgent_ExploreFallsBackOnInvalidUUID(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
db, ps := dbtestutil.NewDB(t)
|
||||
server := newInternalTestServer(t, db, ps, chatprovider.ProviderAPIKeys{})
|
||||
|
||||
ctx := chatdTestContext(t)
|
||||
user, org, parentModel := seedInternalChatDeps(t, db)
|
||||
currentTurnModel := insertInternalChatModelConfig(
|
||||
t, db, org.ID, "explore-invalid-override-"+uuid.NewString(), true,
|
||||
)
|
||||
require.NoError(t, db.UpsertChatExploreModelOverride(ctx, "not-a-uuid"))
|
||||
parentChat := createInternalParentChat(
|
||||
ctx, t, server, db, org.ID, user.ID, parentModel.ID, "parent-explore-invalid-override",
|
||||
)
|
||||
|
||||
resp := runSubagentTool(
|
||||
ctx,
|
||||
t,
|
||||
server,
|
||||
parentChat,
|
||||
currentTurnModel.ID,
|
||||
spawnAgentToolName,
|
||||
spawnAgentArgs{Type: subagentTypeExplore, Prompt: "inspect the handler flow"},
|
||||
)
|
||||
childID := requireSpawnAgentChildChatID(t, resp)
|
||||
|
||||
childChat, err := db.GetChatByID(ctx, childID)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, currentTurnModel.ID, childChat.LastModelConfigID)
|
||||
}
|
||||
|
||||
func TestSpawnAgent_ExploreFallsBackWhenOverrideIsUnavailable(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -2661,7 +2645,7 @@ func TestSpawnAgent_ExploreFallsBackWhenOverrideIsUnavailable(t *testing.T) {
|
||||
disabledModel := insertInternalChatModelConfig(
|
||||
t, db, org.ID, "explore-disabled-"+uuid.NewString(), false,
|
||||
)
|
||||
require.NoError(t, db.UpsertChatExploreModelOverride(ctx, disabledModel.ID.String()))
|
||||
upsertInternalChatOrganizationModelOverride(t, db, org.ID, codersdk.ChatModelOverrideContextExplore, disabledModel.ID.String())
|
||||
parentChat := createInternalParentChat(
|
||||
ctx, t, server, db, org.ID, user.ID, parentModel.ID, "parent-explore-disabled",
|
||||
)
|
||||
@@ -2704,11 +2688,12 @@ func TestSpawnAgent_ExploreFallsBackWhenOverrideCredentialsAreUnavailable(t *tes
|
||||
})
|
||||
|
||||
overrideModel := dbgen.ChatModelConfig(t, db, database.ChatModelConfig{
|
||||
AIProviderID: uuid.NullUUID{UUID: overrideProvider.ID, Valid: true},
|
||||
Model: "gpt-4o-mini",
|
||||
DisplayName: "Explore Override Missing User Key",
|
||||
AIProviderID: uuid.NullUUID{UUID: overrideProvider.ID, Valid: true},
|
||||
OrganizationID: org.ID,
|
||||
Model: "gpt-4o-mini",
|
||||
DisplayName: "Explore Override Missing User Key",
|
||||
})
|
||||
require.NoError(t, db.UpsertChatExploreModelOverride(ctx, overrideModel.ID.String()))
|
||||
upsertInternalChatOrganizationModelOverride(t, db, org.ID, codersdk.ChatModelOverrideContextExplore, overrideModel.ID.String())
|
||||
parentChat := createInternalParentChat(
|
||||
ctx, t, server, db, org.ID, user.ID, parentModel.ID, "parent-explore-missing-user-key",
|
||||
)
|
||||
|
||||
@@ -2,8 +2,7 @@ package chatd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"strings"
|
||||
"database/sql"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"golang.org/x/xerrors"
|
||||
@@ -15,81 +14,59 @@ import (
|
||||
|
||||
const titleGenerationOverrideContext = "title_generation"
|
||||
|
||||
type parsedModelOverride struct {
|
||||
modelConfigID uuid.UUID
|
||||
reasoningEffort *string
|
||||
}
|
||||
|
||||
func parseModelOverride(raw string) (parsedModelOverride, bool) {
|
||||
trimmed := strings.TrimSpace(raw)
|
||||
if trimmed == "" {
|
||||
return parsedModelOverride{}, true
|
||||
}
|
||||
rawID, rawEffort, hasEffort := strings.Cut(trimmed, ":")
|
||||
modelConfigID, err := uuid.Parse(rawID)
|
||||
if err != nil || (hasEffort && rawEffort == "") {
|
||||
return parsedModelOverride{}, false
|
||||
}
|
||||
parsed := parsedModelOverride{modelConfigID: modelConfigID}
|
||||
if hasEffort {
|
||||
parsed.reasoningEffort = &rawEffort
|
||||
}
|
||||
return parsed, true
|
||||
}
|
||||
|
||||
func readTitleGenerationModelOverride(
|
||||
ctx context.Context,
|
||||
db database.Store,
|
||||
) (string, error) {
|
||||
organizationID uuid.UUID,
|
||||
) (database.ChatOrganizationModelOverride, error) {
|
||||
//nolint:gocritic // Chatd is internal, not a user, so this read uses AsChatd.
|
||||
chatdCtx := dbauthz.AsChatd(ctx)
|
||||
raw, err := db.GetChatTitleGenerationModelOverride(chatdCtx)
|
||||
override, err := db.GetChatOrganizationModelOverride(chatdCtx, database.GetChatOrganizationModelOverrideParams{
|
||||
OrganizationID: organizationID,
|
||||
Context: titleGenerationOverrideContext,
|
||||
})
|
||||
if err != nil {
|
||||
return "", xerrors.Errorf(
|
||||
return database.ChatOrganizationModelOverride{}, xerrors.Errorf(
|
||||
"get chat title generation model override: %w",
|
||||
err,
|
||||
)
|
||||
}
|
||||
return raw, nil
|
||||
return override, nil
|
||||
}
|
||||
|
||||
// resolveTitleGenerationModelOverride resolves the deployment-wide title
|
||||
// generation model override. overrideSet is true when an override was
|
||||
// configured and resolved; a configured override that does not resolve
|
||||
// because it is unknown or disabled is ignored. Model construction failures
|
||||
// after a successful resolution stay hard failures.
|
||||
// When overrideSet is false, callers may fall back to the default title
|
||||
// model.
|
||||
// resolveTitleGenerationModelOverride resolves the chat organization's title
|
||||
// generation model override. A configured but unusable override is a hard
|
||||
// failure. When no row is configured, callers may use the default title model.
|
||||
func (p *Server) resolveTitleGenerationModelOverride(
|
||||
ctx context.Context,
|
||||
chat database.Chat,
|
||||
modelOpts modelBuildOptions,
|
||||
) (resolvedModelCall, bool, error) {
|
||||
raw, err := readTitleGenerationModelOverride(ctx, p.db)
|
||||
override, err := readTitleGenerationModelOverride(ctx, p.db, chat.OrganizationID)
|
||||
if err != nil {
|
||||
if xerrors.Is(err, sql.ErrNoRows) {
|
||||
return resolvedModelCall{}, false, nil
|
||||
}
|
||||
return resolvedModelCall{}, false, xerrors.Errorf(
|
||||
"read title generation model override: %w",
|
||||
err,
|
||||
)
|
||||
}
|
||||
|
||||
modelConfig, _, overrideEffort, overrideSet, err := p.resolveConfiguredModelOverride(
|
||||
modelConfig, _, overrideEffort, overrideSet, err := p.resolveOrganizationModelOverride(
|
||||
ctx,
|
||||
titleGenerationOverrideContext,
|
||||
raw,
|
||||
override,
|
||||
chat.OwnerID,
|
||||
func(ctx context.Context, modelConfigID uuid.UUID) (database.ChatModelConfig, string, error) {
|
||||
return p.resolveModelConfigForOrganization(ctx, chat.OwnerID, chat.OrganizationID, modelConfigID)
|
||||
return p.resolveModelConfigAndNormalizedProvider(ctx, chat.OwnerID, modelConfigID)
|
||||
},
|
||||
func(ctx context.Context, ownerID uuid.UUID, aiProviderID uuid.UUID) (chatprovider.ProviderAPIKeys, error) {
|
||||
return p.resolveUserProviderAPIKeys(ctx, ownerID, aiProviderID)
|
||||
},
|
||||
modelOverrideFailureModeSoft,
|
||||
modelOverrideFailureModeHard,
|
||||
)
|
||||
if err != nil {
|
||||
if errors.Is(err, errModelConfigOutsideOrganization) {
|
||||
return resolvedModelCall{}, false, err
|
||||
}
|
||||
return resolvedModelCall{}, overrideSet, err
|
||||
}
|
||||
if !overrideSet {
|
||||
|
||||
@@ -34,6 +34,13 @@ import (
|
||||
"github.com/coder/quartz"
|
||||
)
|
||||
|
||||
func titleGenerationOverrideParams(chat database.Chat) database.GetChatOrganizationModelOverrideParams {
|
||||
return database.GetChatOrganizationModelOverrideParams{
|
||||
OrganizationID: chat.OrganizationID,
|
||||
Context: titleGenerationOverrideContext,
|
||||
}
|
||||
}
|
||||
|
||||
func TestMaybeGenerateChatTitle_TitleGenerationOverrideUnset(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -57,7 +64,7 @@ func TestMaybeGenerateChatTitle_TitleGenerationOverrideUnset(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
db.EXPECT().GetChatTitleGenerationModelOverride(gomock.Any()).Return("", nil)
|
||||
db.EXPECT().GetChatOrganizationModelOverride(gomock.Any(), titleGenerationOverrideParams(chat)).Return(database.ChatOrganizationModelOverride{}, sql.ErrNoRows)
|
||||
db.EXPECT().UpdateChatTitleByID(gomock.Any(), database.UpdateChatTitleByIDParams{
|
||||
ID: chat.ID,
|
||||
Title: wantTitle,
|
||||
@@ -107,56 +114,7 @@ func TestMaybeGenerateChatTitle_TitleGenerationOverrideReadDBError(t *testing.T)
|
||||
},
|
||||
}
|
||||
|
||||
db.EXPECT().GetChatTitleGenerationModelOverride(gomock.Any()).Return("", sql.ErrConnDone)
|
||||
db.EXPECT().UpdateChatTitleByID(gomock.Any(), database.UpdateChatTitleByIDParams{
|
||||
ID: chat.ID,
|
||||
Title: wantTitle,
|
||||
}).Return(chatWithTitle(chat, wantTitle), nil)
|
||||
|
||||
generated := &generatedChatTitle{}
|
||||
server := titleOverrideTestServer(db, logger)
|
||||
server.maybeGenerateChatTitle(
|
||||
ctx,
|
||||
chat,
|
||||
messages,
|
||||
nil,
|
||||
resolvedModelCall{
|
||||
model: chatprovider.NewModel(fallbackModel, nil),
|
||||
dbConfig: database.ChatModelConfig{Model: "fallback-chat-model"},
|
||||
},
|
||||
modelBuildOptions{},
|
||||
generated,
|
||||
logger,
|
||||
nil,
|
||||
)
|
||||
|
||||
require.Equal(t, int32(1), fallbackCalls.Load())
|
||||
gotTitle, ok := generated.Load()
|
||||
require.True(t, ok)
|
||||
require.Equal(t, wantTitle, gotTitle)
|
||||
}
|
||||
|
||||
func TestMaybeGenerateChatTitle_TitleGenerationOverrideMalformedFallsThrough(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
ctx := testutil.Context(t, testutil.WaitShort)
|
||||
ctrl := gomock.NewController(t)
|
||||
db := dbmock.NewMockStore(ctrl)
|
||||
logger := slogtest.Make(t, &slogtest.Options{IgnoreErrors: true})
|
||||
chat, messages := titleOverrideTestChatAndMessages(t)
|
||||
wantTitle := "Fallback title"
|
||||
|
||||
var fallbackCalls atomic.Int32
|
||||
fallbackModel := &chattest.FakeModel{
|
||||
GenerateObjectFn: func(context.Context, fantasy.ObjectCall) (*fantasy.ObjectResponse, error) {
|
||||
fallbackCalls.Add(1)
|
||||
return &fantasy.ObjectResponse{
|
||||
Object: map[string]any{"title": wantTitle},
|
||||
}, nil
|
||||
},
|
||||
}
|
||||
|
||||
db.EXPECT().GetChatTitleGenerationModelOverride(gomock.Any()).Return("not-a-uuid", nil)
|
||||
db.EXPECT().GetChatOrganizationModelOverride(gomock.Any(), titleGenerationOverrideParams(chat)).Return(database.ChatOrganizationModelOverride{}, sql.ErrConnDone)
|
||||
db.EXPECT().UpdateChatTitleByID(gomock.Any(), database.UpdateChatTitleByIDParams{
|
||||
ID: chat.ID,
|
||||
Title: wantTitle,
|
||||
@@ -236,7 +194,7 @@ func TestMaybeGenerateChatTitle_TitleGenerationOverrideSetUsable(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
db.EXPECT().GetChatTitleGenerationModelOverride(gomock.Any()).Return(overrideConfig.ID.String()+":xhigh", nil)
|
||||
db.EXPECT().GetChatOrganizationModelOverride(gomock.Any(), titleGenerationOverrideParams(chat)).Return(orgModelOverride(chat, titleGenerationOverrideContext, overrideConfig.ID, "xhigh"), nil)
|
||||
db.EXPECT().GetChatModelConfigByID(gomock.Any(), overrideConfig.ID).Return(overrideConfig, nil)
|
||||
db.EXPECT().GetAIProviderByID(gomock.Any(), providerID).Return(provider, nil).AnyTimes()
|
||||
db.EXPECT().GetAIProviderKeysByProviderID(gomock.Any(), providerID).Return([]database.AIProviderKey{{
|
||||
@@ -272,7 +230,7 @@ func TestMaybeGenerateChatTitle_TitleGenerationOverrideSetUsable(t *testing.T) {
|
||||
require.Equal(t, wantTitle, gotTitle)
|
||||
}
|
||||
|
||||
func TestMaybeGenerateChatTitle_TitleGenerationOverrideSetUnusableSkips(t *testing.T) {
|
||||
func TestMaybeGenerateChatTitle_TitleGenerationOverrideSetUnusableHardFails(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
ctx := testutil.Context(t, testutil.WaitShort)
|
||||
@@ -290,12 +248,8 @@ func TestMaybeGenerateChatTitle_TitleGenerationOverrideSetUnusableSkips(t *testi
|
||||
},
|
||||
}
|
||||
|
||||
db.EXPECT().GetChatTitleGenerationModelOverride(gomock.Any()).Return(overrideConfig.ID.String(), nil)
|
||||
db.EXPECT().GetChatOrganizationModelOverride(gomock.Any(), titleGenerationOverrideParams(chat)).Return(orgModelOverride(chat, titleGenerationOverrideContext, overrideConfig.ID, ""), nil)
|
||||
db.EXPECT().GetChatModelConfigByID(gomock.Any(), overrideConfig.ID).Return(overrideConfig, nil)
|
||||
db.EXPECT().UpdateChatTitleByID(gomock.Any(), database.UpdateChatTitleByIDParams{
|
||||
ID: chat.ID,
|
||||
Title: wantTitle,
|
||||
}).Return(chatWithTitle(chat, wantTitle), nil)
|
||||
|
||||
generated := &generatedChatTitle{}
|
||||
server := titleOverrideTestServer(db, logger)
|
||||
@@ -314,9 +268,8 @@ func TestMaybeGenerateChatTitle_TitleGenerationOverrideSetUnusableSkips(t *testi
|
||||
nil,
|
||||
)
|
||||
|
||||
gotTitle, ok := generated.Load()
|
||||
require.True(t, ok)
|
||||
require.Equal(t, wantTitle, gotTitle)
|
||||
_, ok := generated.Load()
|
||||
require.False(t, ok, "a configured but unusable title override must not fall back")
|
||||
}
|
||||
|
||||
func TestMaybeGenerateChatTitle_TitleGenerationOverrideCallFailureSkipsFallback(t *testing.T) {
|
||||
@@ -343,7 +296,7 @@ func TestMaybeGenerateChatTitle_TitleGenerationOverrideCallFailureSkipsFallback(
|
||||
},
|
||||
}
|
||||
|
||||
db.EXPECT().GetChatTitleGenerationModelOverride(gomock.Any()).Return(overrideConfig.ID.String(), nil)
|
||||
db.EXPECT().GetChatOrganizationModelOverride(gomock.Any(), titleGenerationOverrideParams(chat)).Return(orgModelOverride(chat, titleGenerationOverrideContext, overrideConfig.ID, ""), nil)
|
||||
db.EXPECT().GetChatModelConfigByID(gomock.Any(), overrideConfig.ID).Return(overrideConfig, nil)
|
||||
db.EXPECT().GetAIProviderByID(gomock.Any(), providerID).Return(aibridgeTestAIProvider(providerID, "primary-openai", database.AIProviderTypeOpenai), nil).AnyTimes()
|
||||
db.EXPECT().GetAIProviderKeysByProviderID(gomock.Any(), providerID).Return([]database.AIProviderKey{{
|
||||
@@ -374,56 +327,6 @@ func TestMaybeGenerateChatTitle_TitleGenerationOverrideCallFailureSkipsFallback(
|
||||
require.False(t, ok)
|
||||
}
|
||||
|
||||
func TestResolveManualTitleModel_TitleGenerationOverrideIgnoresForeignConfig(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
ctx := testutil.Context(t, testutil.WaitShort)
|
||||
ctrl := gomock.NewController(t)
|
||||
db := dbmock.NewMockStore(ctrl)
|
||||
logger := slogtest.Make(t, &slogtest.Options{IgnoreErrors: true})
|
||||
chat, _ := titleOverrideTestChatAndMessages(t)
|
||||
chat.OrganizationID = uuid.New()
|
||||
overrideConfig := titleOverrideModelConfig("gpt-4.1", true)
|
||||
overrideConfig.OrganizationID = uuid.New()
|
||||
overrideProviderID := uuid.New()
|
||||
overrideConfig.AIProviderID = uuid.NullUUID{UUID: overrideProviderID, Valid: true}
|
||||
localProviderID := uuid.New()
|
||||
localPreferred := database.ChatModelConfig{
|
||||
ID: uuid.New(),
|
||||
Model: preferredTitleModels[0].model,
|
||||
Enabled: true,
|
||||
OrganizationID: chat.OrganizationID,
|
||||
}
|
||||
localDefault := database.ChatModelConfig{
|
||||
ID: uuid.New(),
|
||||
AIProviderID: uuid.NullUUID{UUID: localProviderID, Valid: true},
|
||||
Model: "local-default-model",
|
||||
Enabled: true,
|
||||
IsDefault: true,
|
||||
OrganizationID: chat.OrganizationID,
|
||||
}
|
||||
|
||||
db.EXPECT().GetChatTitleGenerationModelOverride(gomock.Any()).Return(overrideConfig.ID.String(), nil)
|
||||
db.EXPECT().GetChatModelConfigByID(gomock.Any(), overrideConfig.ID).Return(overrideConfig, nil)
|
||||
db.EXPECT().GetAIProviderByID(gomock.Any(), overrideProviderID).Return(aibridgeTestAIProvider(overrideProviderID, "foreign-openai", database.AIProviderTypeOpenai), nil)
|
||||
db.EXPECT().GetEnabledChatModelConfigsByOrganization(gomock.Any(), chat.OrganizationID).Return([]database.GetEnabledChatModelConfigsByOrganizationRow{
|
||||
{ChatModelConfig: localPreferred, Provider: preferredTitleModels[0].provider},
|
||||
{ChatModelConfig: localDefault, Provider: "openai"},
|
||||
}, nil).AnyTimes()
|
||||
db.EXPECT().GetAIProviderByID(gomock.Any(), localProviderID).Return(aibridgeTestAIProvider(localProviderID, "primary-openai", database.AIProviderTypeOpenai), nil).AnyTimes()
|
||||
|
||||
server := titleOverrideTestServer(db, logger)
|
||||
resolved, err := server.resolveManualTitleModel(
|
||||
ctx,
|
||||
db,
|
||||
chat,
|
||||
modelBuildOptions{ActiveAPIKeyID: uuid.NewString()},
|
||||
)
|
||||
require.NoError(t, err)
|
||||
require.True(t, resolved.model.Valid())
|
||||
require.Equal(t, localDefault, resolved.dbConfig)
|
||||
}
|
||||
|
||||
func TestResolveManualTitleModel_TitleGenerationOverrideUnset(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -440,7 +343,7 @@ func TestResolveManualTitleModel_TitleGenerationOverrideUnset(t *testing.T) {
|
||||
Enabled: true,
|
||||
}
|
||||
|
||||
db.EXPECT().GetChatTitleGenerationModelOverride(gomock.Any()).Return("", nil)
|
||||
db.EXPECT().GetChatOrganizationModelOverride(gomock.Any(), titleGenerationOverrideParams(chat)).Return(database.ChatOrganizationModelOverride{}, sql.ErrNoRows)
|
||||
db.EXPECT().GetEnabledChatModelConfigsByOrganization(gomock.Any(), chat.OrganizationID).Return([]database.GetEnabledChatModelConfigsByOrganizationRow{
|
||||
{ChatModelConfig: database.ChatModelConfig{Model: "gpt-4.1", Enabled: true}, Provider: "openai"},
|
||||
{ChatModelConfig: preferredConfig, Provider: preferredTitleModels[1].provider},
|
||||
@@ -469,7 +372,7 @@ func TestResolveManualTitleModel_NonDefaultOrgDoesNotUseDefaultOrgConfigs(t *tes
|
||||
chat, _ := titleOverrideTestChatAndMessages(t)
|
||||
chat.OrganizationID = uuid.New()
|
||||
|
||||
db.EXPECT().GetChatTitleGenerationModelOverride(gomock.Any()).Return("", nil)
|
||||
db.EXPECT().GetChatOrganizationModelOverride(gomock.Any(), titleGenerationOverrideParams(chat)).Return(database.ChatOrganizationModelOverride{}, sql.ErrNoRows)
|
||||
db.EXPECT().GetEnabledChatModelConfigsByOrganization(gomock.Any(), chat.OrganizationID).Return(nil, nil).AnyTimes()
|
||||
|
||||
server := titleOverrideTestServer(db, logger)
|
||||
@@ -510,7 +413,7 @@ func TestResolveManualTitleModel_TitleGenerationOverrideUnsetAIProvider(t *testi
|
||||
BaseUrl: serverURL,
|
||||
}
|
||||
|
||||
db.EXPECT().GetChatTitleGenerationModelOverride(gomock.Any()).Return("", nil)
|
||||
db.EXPECT().GetChatOrganizationModelOverride(gomock.Any(), titleGenerationOverrideParams(chat)).Return(database.ChatOrganizationModelOverride{}, sql.ErrNoRows)
|
||||
db.EXPECT().GetEnabledChatModelConfigsByOrganization(gomock.Any(), chat.OrganizationID).Return([]database.GetEnabledChatModelConfigsByOrganizationRow{
|
||||
{ChatModelConfig: preferredConfig, Provider: preferredTitleModels[1].provider},
|
||||
}, nil)
|
||||
@@ -548,7 +451,7 @@ func TestResolveManualTitleModel_TitleGenerationOverrideReadDBError(t *testing.T
|
||||
Enabled: true,
|
||||
}
|
||||
|
||||
db.EXPECT().GetChatTitleGenerationModelOverride(gomock.Any()).Return("", sql.ErrConnDone)
|
||||
db.EXPECT().GetChatOrganizationModelOverride(gomock.Any(), titleGenerationOverrideParams(chat)).Return(database.ChatOrganizationModelOverride{}, sql.ErrConnDone)
|
||||
db.EXPECT().GetEnabledChatModelConfigsByOrganization(gomock.Any(), chat.OrganizationID).Return([]database.GetEnabledChatModelConfigsByOrganizationRow{
|
||||
{ChatModelConfig: database.ChatModelConfig{Model: "gpt-4.1", Enabled: true}, Provider: "openai"},
|
||||
{ChatModelConfig: preferredConfig, Provider: preferredTitleModels[1].provider},
|
||||
@@ -579,7 +482,7 @@ func TestResolveManualTitleModel_TitleGenerationOverrideSetUsable(t *testing.T)
|
||||
providerID := uuid.New()
|
||||
overrideConfig.AIProviderID = uuid.NullUUID{UUID: providerID, Valid: true}
|
||||
|
||||
db.EXPECT().GetChatTitleGenerationModelOverride(gomock.Any()).Return(overrideConfig.ID.String(), nil)
|
||||
db.EXPECT().GetChatOrganizationModelOverride(gomock.Any(), titleGenerationOverrideParams(chat)).Return(orgModelOverride(chat, titleGenerationOverrideContext, overrideConfig.ID, ""), nil)
|
||||
db.EXPECT().GetChatModelConfigByID(gomock.Any(), overrideConfig.ID).Return(overrideConfig, nil)
|
||||
db.EXPECT().GetAIProviderByID(gomock.Any(), providerID).Return(aibridgeTestAIProvider(providerID, "primary-openai", database.AIProviderTypeOpenai), nil).AnyTimes()
|
||||
db.EXPECT().GetAIProviderKeysByProviderID(gomock.Any(), providerID).Return([]database.AIProviderKey{{
|
||||
@@ -616,13 +519,11 @@ func TestResolveManualTitleModel_TitleGenerationOverrideMissingCredentials(t *te
|
||||
Enabled: true,
|
||||
}
|
||||
|
||||
db.EXPECT().GetChatTitleGenerationModelOverride(gomock.Any()).Return(overrideConfig.ID.String(), nil)
|
||||
db.EXPECT().GetChatOrganizationModelOverride(gomock.Any(), titleGenerationOverrideParams(chat)).Return(orgModelOverride(chat, titleGenerationOverrideContext, overrideConfig.ID, ""), nil)
|
||||
db.EXPECT().GetChatModelConfigByID(gomock.Any(), overrideConfig.ID).Return(overrideConfig, nil)
|
||||
db.EXPECT().GetAIProviderByID(gomock.Any(), providerID).Return(provider, nil).AnyTimes()
|
||||
db.EXPECT().GetAIProviderKeysByProviderID(gomock.Any(), providerID).Return(nil, nil).AnyTimes()
|
||||
// Missing override credentials soft-fail the override. The local
|
||||
// organization has no usable model, so fallback resolution fails.
|
||||
db.EXPECT().GetEnabledChatModelConfigsByOrganization(gomock.Any(), chat.OrganizationID).Return(nil, nil).Times(2)
|
||||
// Missing override credentials hard-fail the configured override.
|
||||
|
||||
server := titleOverrideTestServer(db, logger)
|
||||
resolved, err := server.resolveManualTitleModel(
|
||||
@@ -631,9 +532,8 @@ func TestResolveManualTitleModel_TitleGenerationOverrideMissingCredentials(t *te
|
||||
chat,
|
||||
modelBuildOptions{},
|
||||
)
|
||||
// The chat has no model config and its org has no default, so
|
||||
// fallback resolution errors with ErrNoDefaultChatModelConfig.
|
||||
require.ErrorIs(t, err, ErrNoDefaultChatModelConfig)
|
||||
require.ErrorContains(t, err, "resolve manual title generation model override")
|
||||
require.ErrorContains(t, err, "credentials are unavailable")
|
||||
require.Equal(t, resolvedModelCall{}, resolved)
|
||||
}
|
||||
|
||||
@@ -695,7 +595,7 @@ func TestGenerateManualTitleCandidate_UsesSyntheticAPIKey(t *testing.T) {
|
||||
UserID: chat.OwnerID,
|
||||
ExpiresAt: time.Now().Add(48 * time.Hour),
|
||||
}, nil)
|
||||
db.EXPECT().GetChatTitleGenerationModelOverride(gomock.Any()).Return(overrideConfig.ID.String(), nil)
|
||||
db.EXPECT().GetChatOrganizationModelOverride(gomock.Any(), titleGenerationOverrideParams(chat)).Return(orgModelOverride(chat, titleGenerationOverrideContext, overrideConfig.ID, ""), nil)
|
||||
db.EXPECT().GetChatModelConfigByID(gomock.Any(), overrideConfig.ID).Return(overrideConfig, nil)
|
||||
db.EXPECT().GetAIProviderByID(gomock.Any(), providerID).Return(provider, nil).AnyTimes()
|
||||
db.EXPECT().GetAIProviderKeysByProviderID(gomock.Any(), providerID).Return([]database.AIProviderKey{{
|
||||
@@ -726,11 +626,9 @@ func TestResolveManualTitleModel_TitleGenerationOverrideSetUnusable(t *testing.T
|
||||
chat, _ := titleOverrideTestChatAndMessages(t)
|
||||
overrideConfig := titleOverrideModelConfig("gpt-4.1", false)
|
||||
|
||||
db.EXPECT().GetChatTitleGenerationModelOverride(gomock.Any()).Return(overrideConfig.ID.String(), nil)
|
||||
db.EXPECT().GetChatOrganizationModelOverride(gomock.Any(), titleGenerationOverrideParams(chat)).Return(orgModelOverride(chat, titleGenerationOverrideContext, overrideConfig.ID, ""), nil)
|
||||
db.EXPECT().GetChatModelConfigByID(gomock.Any(), overrideConfig.ID).Return(overrideConfig, nil)
|
||||
// A disabled override config soft-fails the override. The local
|
||||
// organization has no usable model, so fallback resolution fails.
|
||||
db.EXPECT().GetEnabledChatModelConfigsByOrganization(gomock.Any(), chat.OrganizationID).Return(nil, nil).Times(2)
|
||||
// A disabled configured override is a hard failure.
|
||||
|
||||
server := titleOverrideTestServer(db, logger)
|
||||
resolved, err := server.resolveManualTitleModel(
|
||||
@@ -739,9 +637,8 @@ func TestResolveManualTitleModel_TitleGenerationOverrideSetUnusable(t *testing.T
|
||||
chat,
|
||||
modelBuildOptions{},
|
||||
)
|
||||
// The chat has no model config and its org has no default, so
|
||||
// fallback resolution errors with ErrNoDefaultChatModelConfig.
|
||||
require.ErrorIs(t, err, ErrNoDefaultChatModelConfig)
|
||||
require.ErrorContains(t, err, "resolve manual title generation model override")
|
||||
require.ErrorContains(t, err, "model override is unavailable")
|
||||
require.Equal(t, resolvedModelCall{}, resolved)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user