feat(#133): add workspace-scoped LLM configuration
Implement per-workspace LLM provider and personality configuration with proper hierarchy (workspace > user > system fallback). Schema: - Add WorkspaceLlmSettings model with provider/personality FKs - One-to-one relation with Workspace - JSON settings field for extensibility Service: - getSettings: Retrieves/creates workspace settings - updateSettings: Updates with null value support - getEffectiveLlmProvider: Hierarchy-based provider selection - getEffectivePersonality: Hierarchy-based personality selection Endpoints: - GET /workspaces/:id/settings/llm - Get settings - PATCH /workspaces/:id/settings/llm - Update settings - GET /workspaces/:id/settings/llm/effective-provider - GET /workspaces/:id/settings/llm/effective-personality Configuration hierarchy: 1. Workspace-configured provider/personality 2. User-specific provider (for providers) 3. System default fallback Tests: 34 passing with 100% coverage Fixes #133 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -214,6 +214,7 @@ model Workspace {
|
||||
knowledgeTags KnowledgeTag[]
|
||||
cronSchedules CronSchedule[]
|
||||
personalities Personality[]
|
||||
llmSettings WorkspaceLlmSettings?
|
||||
|
||||
@@index([ownerId])
|
||||
@@map("workspaces")
|
||||
@@ -942,7 +943,8 @@ model Personality {
|
||||
updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamptz
|
||||
|
||||
// Relations
|
||||
llmProviderInstance LlmProviderInstance? @relation("PersonalityLlmProvider", fields: [llmProviderInstanceId], references: [id], onDelete: SetNull)
|
||||
llmProviderInstance LlmProviderInstance? @relation("PersonalityLlmProvider", fields: [llmProviderInstanceId], references: [id], onDelete: SetNull)
|
||||
workspaceLlmSettings WorkspaceLlmSettings[] @relation("WorkspacePersonality")
|
||||
|
||||
@@unique([id, workspaceId])
|
||||
@@unique([workspaceId, name])
|
||||
@@ -969,8 +971,9 @@ model LlmProviderInstance {
|
||||
updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamptz
|
||||
|
||||
// Relations
|
||||
user User? @relation("UserLlmProviders", fields: [userId], references: [id], onDelete: Cascade)
|
||||
personalities Personality[] @relation("PersonalityLlmProvider")
|
||||
user User? @relation("UserLlmProviders", fields: [userId], references: [id], onDelete: Cascade)
|
||||
personalities Personality[] @relation("PersonalityLlmProvider")
|
||||
workspaceLlmSettings WorkspaceLlmSettings[] @relation("WorkspaceLlmProvider")
|
||||
|
||||
@@index([userId])
|
||||
@@index([providerType])
|
||||
@@ -978,3 +981,25 @@ model LlmProviderInstance {
|
||||
@@index([isEnabled])
|
||||
@@map("llm_provider_instances")
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// WORKSPACE LLM SETTINGS
|
||||
// ============================================
|
||||
|
||||
model WorkspaceLlmSettings {
|
||||
id String @id @default(uuid()) @db.Uuid
|
||||
workspaceId String @unique @map("workspace_id") @db.Uuid
|
||||
workspace Workspace @relation(fields: [workspaceId], references: [id], onDelete: Cascade)
|
||||
defaultLlmProviderId String? @map("default_llm_provider_id") @db.Uuid
|
||||
defaultLlmProvider LlmProviderInstance? @relation("WorkspaceLlmProvider", fields: [defaultLlmProviderId], references: [id], onDelete: SetNull)
|
||||
defaultPersonalityId String? @map("default_personality_id") @db.Uuid
|
||||
defaultPersonality Personality? @relation("WorkspacePersonality", fields: [defaultPersonalityId], references: [id], onDelete: SetNull)
|
||||
settings Json? @default("{}")
|
||||
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz
|
||||
updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamptz
|
||||
|
||||
@@index([workspaceId])
|
||||
@@index([defaultLlmProviderId])
|
||||
@@index([defaultPersonalityId])
|
||||
@@map("workspace_llm_settings")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user