datasource client {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

generator client {
  provider = "prisma-client-py"
  binaryTargets = ["native", "debian-openssl-1.1.x", "debian-openssl-3.0.x", "linux-musl", "linux-musl-openssl-3.0.x"]
}

// Budget / Rate Limits for an org
model LiteLLM_BudgetTable {
  budget_id String @id @default(uuid())
  max_budget Float?
  soft_budget Float?
  max_parallel_requests Int?
  tpm_limit     BigInt?
  rpm_limit     BigInt?
  model_max_budget Json?
  budget_duration String?
  budget_reset_at DateTime?
  allowed_models String[] @default([]) // per-member model scope; empty = inherit team models
  created_at    DateTime               @default(now()) @map("created_at")
  created_by String
  updated_at    DateTime               @default(now()) @updatedAt @map("updated_at")
  updated_by String
  organization LiteLLM_OrganizationTable[] // multiple orgs can have the same budget
  projects LiteLLM_ProjectTable[] // multiple projects can have the same budget
  keys LiteLLM_VerificationToken[] // multiple keys can have the same budget
  end_users LiteLLM_EndUserTable[] // multiple end-users can have the same budget
  tags LiteLLM_TagTable[] // multiple tags can have the same budget
  team_membership LiteLLM_TeamMembership[] // budgets of Users within a Team 
  organization_membership LiteLLM_OrganizationMembership[] // budgets of Users within a Organization 
}

// Models on proxy
model LiteLLM_CredentialsTable {
  credential_id String @id @default(uuid())
  credential_name String @unique
  credential_values Json
  credential_info Json? 
  created_at    DateTime               @default(now()) @map("created_at")
  created_by String
  updated_at    DateTime               @default(now()) @updatedAt @map("updated_at")
  updated_by String
}

// Models on proxy
model LiteLLM_ProxyModelTable {
  model_id String @id @default(uuid())
  model_name String
  litellm_params Json
  model_info Json?
  blocked Boolean @default(false)
  created_at    DateTime               @default(now()) @map("created_at")
  created_by String
  updated_at    DateTime               @default(now()) @updatedAt @map("updated_at")
  updated_by String
}


// Agents on proxy
model LiteLLM_AgentsTable {
  agent_id String @id @default(uuid())
  agent_name String @unique
  litellm_params Json?
  agent_card_params Json
  static_headers       Json?          @default("{}")
  extra_headers        String[]       @default([])
  agent_access_groups String[]       @default([])
  object_permission_id String?
  object_permission LiteLLM_ObjectPermissionTable? @relation(fields: [object_permission_id], references: [object_permission_id])
  spend      Float    @default(0.0)
  tpm_limit  Int?
  rpm_limit  Int?
  session_tpm_limit Int?
  session_rpm_limit Int?
  created_at    DateTime               @default(now()) @map("created_at")
  created_by String
  updated_at    DateTime               @default(now()) @updatedAt @map("updated_at")
  updated_by String
}

model LiteLLM_OrganizationTable {
		organization_id String @id @default(uuid())
    organization_alias  String
    budget_id String
    metadata  Json  @default("{}")
    models     String[]
    spend      Float    @default(0.0)
    model_spend      Json @default("{}")
    object_permission_id String?
    created_at    DateTime               @default(now()) @map("created_at")
    created_by String
    updated_at    DateTime               @default(now()) @updatedAt @map("updated_at")
    updated_by String
    litellm_budget_table LiteLLM_BudgetTable?   @relation(fields: [budget_id], references: [budget_id])
    teams LiteLLM_TeamTable[] 
    users LiteLLM_UserTable[]
    keys LiteLLM_VerificationToken[]
    members LiteLLM_OrganizationMembership[] @relation("OrganizationToMembership")
    object_permission LiteLLM_ObjectPermissionTable?   @relation(fields: [object_permission_id], references: [object_permission_id])
}

// Model info for teams, just has model aliases for now.
model LiteLLM_ModelTable {
  id Int @id @default(autoincrement())
  model_aliases Json? @map("aliases")
  created_at    DateTime               @default(now()) @map("created_at")
  created_by String
  updated_at    DateTime               @default(now()) @updatedAt @map("updated_at")
  updated_by String
  team LiteLLM_TeamTable?
}


// Assign prod keys to groups, not individuals 
model LiteLLM_TeamTable {
		team_id    String @id @default(uuid())
    team_alias  String? 
    organization_id String?
    object_permission_id String?
    admins String[]
    members String[]
    members_with_roles Json @default("{}")
    metadata  Json  @default("{}")
    max_budget Float?
    soft_budget Float?
    spend      Float    @default(0.0)
    models     String[]
    max_parallel_requests Int?
    tpm_limit     BigInt?
    rpm_limit     BigInt?
    budget_duration String? 
    budget_reset_at DateTime?
    blocked Boolean @default(false)
    created_at    DateTime               @default(now()) @map("created_at")
    updated_at    DateTime               @default(now()) @updatedAt @map("updated_at")
    model_spend      Json @default("{}")
    model_max_budget Json @default("{}")
    router_settings  Json? @default("{}")
    team_member_permissions String[] @default([])
    access_group_ids String[] @default([])
    policies         String[] @default([])
    default_team_member_models String[] @default([]) // default allowed_models for newly added team members; empty = no per-member restriction
    budget_limits Json? // per-model budget limits for the team
    model_id Int? @unique // id for LiteLLM_ModelTable -> stores team-level model aliases
    allow_team_guardrail_config Boolean @default(false) // if true, team admin can configure guardrails for this team
    litellm_organization_table LiteLLM_OrganizationTable?   @relation(fields: [organization_id], references: [organization_id])
    litellm_model_table LiteLLM_ModelTable? @relation(fields: [model_id], references: [id])
    object_permission LiteLLM_ObjectPermissionTable?   @relation(fields: [object_permission_id], references: [object_permission_id])
    projects LiteLLM_ProjectTable[]

    @@index([organization_id])
    @@index([team_alias])
    @@index([created_at])
}

// Projects sit between teams and keys for use-case management
model LiteLLM_ProjectTable {
  project_id           String   @id @default(uuid())
  project_alias        String?
  description          String?
  team_id              String?
  budget_id            String?
  metadata             Json     @default("{}")
  models               String[]
  spend                Float    @default(0.0)
  model_spend          Json     @default("{}")
  model_rpm_limit      Json     @default("{}")
  model_tpm_limit      Json     @default("{}")
  blocked              Boolean  @default(false)
  object_permission_id String?
  created_at           DateTime @default(now()) @map("created_at")
  created_by           String
  updated_at           DateTime @default(now()) @updatedAt @map("updated_at")
  updated_by           String
  
  // Relations
  litellm_team_table   LiteLLM_TeamTable?   @relation(fields: [team_id], references: [team_id])
  litellm_budget_table LiteLLM_BudgetTable? @relation(fields: [budget_id], references: [budget_id])
  keys                 LiteLLM_VerificationToken[]
  object_permission    LiteLLM_ObjectPermissionTable? @relation(fields: [object_permission_id], references: [object_permission_id])
}

// Audit table for deleted teams - preserves spend and team information for historical tracking
model LiteLLM_DeletedTeamTable {
    id                      String   @id @default(uuid())
    team_id                 String   // Original team_id
    team_alias              String?
    organization_id         String?
    object_permission_id    String?
    admins                  String[]
    members                 String[]
    members_with_roles      Json     @default("{}")
    metadata                Json     @default("{}")
    max_budget              Float?
    soft_budget             Float?
    spend                   Float    @default(0.0)
    models                  String[]
    max_parallel_requests   Int?
    tpm_limit               BigInt?
    rpm_limit               BigInt?
    budget_duration         String?
    budget_reset_at         DateTime?
    blocked                 Boolean  @default(false)
    model_spend             Json     @default("{}")
    model_max_budget        Json     @default("{}")
    router_settings  Json? @default("{}")
    team_member_permissions String[] @default([])
    access_group_ids String[] @default([])
    policies                String[] @default([])
    model_id                Int?     // id for LiteLLM_ModelTable -> stores team-level model aliases
    allow_team_guardrail_config Boolean @default(false)

    // Original timestamps from team creation/updates
    created_at              DateTime? @map("created_at")
    updated_at              DateTime? @map("updated_at")
    
    // Deletion metadata
    deleted_at              DateTime  @default(now()) @map("deleted_at")
    deleted_by              String?   @map("deleted_by") // User who deleted the team
    deleted_by_api_key      String?   @map("deleted_by_api_key") // API key hash that performed the deletion
    litellm_changed_by      String?   @map("litellm_changed_by") // From litellm-changed-by header if provided
    
    @@index([team_id])
    @@index([deleted_at])
    @@index([organization_id])
    @@index([team_alias])
    @@index([created_at])
}

// Track spend, rate limit, budget Users
model LiteLLM_UserTable {
		user_id    String @id
    user_alias String? 
    team_id    String?
    sso_user_id String? @unique
    organization_id String?
    object_permission_id String?
    password  String?
    teams    String[] @default([])
    user_role  String?
		max_budget Float?
    spend      Float    @default(0.0)
    user_email    String?
    models     String[]
    metadata  Json  @default("{}")
    max_parallel_requests Int?
    tpm_limit     BigInt?
    rpm_limit     BigInt?
    budget_duration String? 
    budget_reset_at DateTime?
    allowed_cache_controls String[] @default([])
    policies         String[] @default([])
    model_spend      Json @default("{}")
    model_max_budget Json @default("{}")
    created_at      DateTime?               @default(now()) @map("created_at")
    updated_at      DateTime?               @default(now()) @updatedAt @map("updated_at")

    // relations
    litellm_organization_table LiteLLM_OrganizationTable?                   @relation(fields: [organization_id], references: [organization_id])
    organization_memberships LiteLLM_OrganizationMembership[]
    invitations_created LiteLLM_InvitationLink[] @relation("CreatedBy")
    invitations_updated LiteLLM_InvitationLink[] @relation("UpdatedBy")
    invitations_user    LiteLLM_InvitationLink[] @relation("UserId")
    object_permission LiteLLM_ObjectPermissionTable?   @relation(fields: [object_permission_id], references: [object_permission_id])
}

model LiteLLM_ObjectPermissionTable {
  object_permission_id  String         @id @default(uuid())
  mcp_servers           String[]       @default([])
  mcp_access_groups     String[]       @default([])
  mcp_tool_permissions  Json?          // Tool-level permissions for MCP servers. Format: {"server_id": ["tool_name_1", "tool_name_2"]}
  vector_stores         String[]       @default([])
  agents                String[]       @default([])
  agent_access_groups   String[]       @default([])
  models                String[]       @default([])
  blocked_tools         String[]       @default([]) // Tool names blocked for any key/team/user with this permission
  mcp_toolsets          String[]       @default([]) // Toolset IDs granted to this key/team/user
  search_tools          String[]       @default([]) // search_tool_name values this key/team/user may call
  teams                 LiteLLM_TeamTable[]
  projects              LiteLLM_ProjectTable[]
  verification_tokens   LiteLLM_VerificationToken[]
  organizations         LiteLLM_OrganizationTable[]
  users                 LiteLLM_UserTable[]
  end_users             LiteLLM_EndUserTable[]
  agents_table          LiteLLM_AgentsTable[]
}

// Holds the MCP server configuration 
model LiteLLM_MCPServerTable {
  server_id    String         @id @default(uuid())
  server_name  String?
  alias        String?
  description  String?
  instructions String?
  url          String?
  spec_path    String?
  transport    String         @default("sse")
  auth_type    String?        
  credentials  Json?          @default("{}")
  created_at   DateTime?      @default(now()) @map("created_at")
  created_by   String?
  updated_at   DateTime?      @default(now()) @updatedAt @map("updated_at")
  updated_by   String?
  mcp_info     Json?          @default("{}")
  mcp_access_groups String[]
  allowed_tools String[]      @default([])
  tool_name_to_display_name Json? @default("{}")
  tool_name_to_description   Json? @default("{}")
  extra_headers String[]    @default([])
  static_headers Json?        @default("{}")
  // Admin-configured environment variables interpolated into static_headers
  // via ${NAME} syntax. Stored as an array of
  // {name, value, scope, description}. scope is "global" (value used as-is)
  // or "user" (value supplied per-user via LiteLLM_MCPUserEnvVars).
  env_vars     Json?          @default("[]")
  // Health check status
  status       String?        @default("unknown")
  last_health_check DateTime?
  health_check_error String?
  // Stdio-specific fields
  command      String?
  args         String[]       @default([])
  env          Json?          @default("{}")
  authorization_url  String?
  token_url          String?
  registration_url   String?
  oauth2_flow        String?
  allow_all_keys Boolean @default(false)
  available_on_public_internet Boolean @default(true)
  delegate_auth_to_upstream Boolean @default(false)
  oauth_passthrough Boolean @default(false)
  is_byok               Boolean  @default(false)
  byok_description      String[] @default([])
  byok_api_key_help_url String?
  source_url            String?
  timeout               Float?
  // BYOM submission lifecycle
  approval_status  String?   @default("active")
  submitted_by     String?
  submitted_at     DateTime?
  reviewed_at      DateTime?
  review_notes     String?

  @@index([approval_status])
}

// Named collection of {server_id, tool_name} pairs that can be granted to keys/teams
model LiteLLM_MCPToolsetTable {
  toolset_id   String   @id @default(uuid())
  toolset_name String   @unique
  description  String?
  tools        Json     @default("[]") // [{server_id: string, tool_name: string}]
  created_at   DateTime @default(now())
  created_by   String?
  updated_at   DateTime @default(now()) @updatedAt
  updated_by   String?
}

// Per-user BYOK credentials for MCP servers
model LiteLLM_MCPUserCredentials {
  id             String   @id @default(uuid())
  user_id        String
  server_id      String
  credential_b64 String
  created_at     DateTime @default(now()) @map("created_at")
  updated_at     DateTime @default(now()) @updatedAt @map("updated_at")

  @@unique([user_id, server_id])
}

// Per-user environment variable values for MCP servers.
// values_b64 is an encrypted JSON object: {VAR_NAME: "value", ...}.
model LiteLLM_MCPUserEnvVars {
  id         String   @id @default(uuid())
  user_id    String
  server_id  String
  values_b64 String
  created_at DateTime @default(now())
  updated_at DateTime @default(now()) @updatedAt

  @@unique([user_id, server_id])
  @@index([user_id])
  @@index([server_id])
}

// Generate Tokens for Proxy
model LiteLLM_VerificationToken {
    token      String   @id
    key_name   String?
    key_alias   String?
    soft_budget_cooldown Boolean @default(false) // key-level state on if budget alerts need to be cooled down
    spend      Float    @default(0.0)
    expires    DateTime?
    models     String[]
    aliases    Json  @default("{}")
    config     Json  @default("{}")
    router_settings Json? @default("{}")
    user_id    String?
    team_id    String?
    agent_id   String?
    project_id String?
    permissions Json @default("{}")
    max_parallel_requests Int?
    metadata   Json  @default("{}")
    blocked Boolean?
    tpm_limit     BigInt?
    rpm_limit     BigInt?
    max_budget Float?    
    budget_duration String? 
    budget_reset_at DateTime?
    allowed_cache_controls String[] @default([])
    allowed_routes   String[] @default([])
    policies         String[] @default([])
    access_group_ids String[] @default([])
    model_spend      Json @default("{}")
    model_max_budget Json @default("{}")
    budget_id String?
    organization_id String?
    object_permission_id String?
    created_at      DateTime?               @default(now()) @map("created_at")
    created_by String?
    updated_at      DateTime?               @default(now()) @updatedAt @map("updated_at")
    updated_by String?
    last_active     DateTime?  // When this key was last used
    rotation_count   Int?       @default(0) // Number of times key has been rotated
    auto_rotate      Boolean?   @default(false) // Whether this key should be auto-rotated
    rotation_interval String?   // How often to rotate (e.g., "30d", "90d")
    last_rotation_at DateTime?  // When this key was last rotated
    key_rotation_at  DateTime?  // When this key should next be rotated
    budget_limits Json? // per-model budget limits for the key
    litellm_budget_table LiteLLM_BudgetTable?   @relation(fields: [budget_id], references: [budget_id])
    litellm_organization_table LiteLLM_OrganizationTable?   @relation(fields: [organization_id], references: [organization_id])
    litellm_project_table LiteLLM_ProjectTable?   @relation(fields: [project_id], references: [project_id])
    object_permission LiteLLM_ObjectPermissionTable?   @relation(fields: [object_permission_id], references: [object_permission_id])
    jwt_key_mappings LiteLLM_JWTKeyMapping[]

    // SELECT COUNT(*) FROM (SELECT "public"."LiteLLM_VerificationToken"."token" FROM "public"."LiteLLM_VerificationToken" WHERE ("public"."LiteLLM_VerificationToken"."user_id" = $1 AND ("public"."LiteLLM_VerificationToken"."team_id" IS NULL OR "public"."LiteLLM_VerificationToken"."team_id" <> $2)) OFFSET $3 ) AS "sub"
    // SELECT ... FROM "public"."LiteLLM_VerificationToken" WHERE "public"."LiteLLM_VerificationToken"."user_id" = $1 OFFSET $2
    @@index([user_id, team_id])

    // SELECT ... FROM "public"."LiteLLM_VerificationToken" WHERE "public"."LiteLLM_VerificationToken"."team_id" = $1 OFFSET $2
    @@index([team_id])

    // SELECT ... FROM "public"."LiteLLM_VerificationToken" WHERE (("public"."LiteLLM_VerificationToken"."expires" IS NULL OR "public"."LiteLLM_VerificationToken"."expires" > $1) AND "public"."LiteLLM_VerificationToken"."budget_reset_at" < $2) OFFSET $3
    @@index([budget_reset_at, expires])
}

model LiteLLM_JWTKeyMapping {
    id                String   @id @default(uuid())
    jwt_claim_name    String   // e.g. "sub", "email"
    jwt_claim_value   String   // The claim value to match
    token             String   // Hashed virtual key (FK)
    description       String?
    is_active         Boolean  @default(true)
    created_at        DateTime @default(now())
    created_by        String?
    updated_at        DateTime @default(now()) @updatedAt
    updated_by        String?

    litellm_verification_token LiteLLM_VerificationToken @relation(fields: [token], references: [token])

    @@unique([jwt_claim_name, jwt_claim_value])
    @@index([jwt_claim_name, jwt_claim_value, is_active])
}

// Deprecated keys during grace period - allows old key to work until revoke_at
model LiteLLM_DeprecatedVerificationToken {
    id               String   @id @default(uuid())
    token            String   // Hashed old key
    active_token_id  String   // Current token hash in LiteLLM_VerificationToken
    revoke_at        DateTime // When the old key stops working
    created_at       DateTime @default(now()) @map("created_at")

    @@unique([token])
    @@index([token, revoke_at])
    @@index([revoke_at])
}

// Audit table for deleted keys - preserves spend and key information for historical tracking
model LiteLLM_DeletedVerificationToken {
    id                      String   @id @default(uuid())
    token                   String   // Original token (hashed)
    key_name                String?
    key_alias               String?
    soft_budget_cooldown    Boolean  @default(false)
    spend                   Float    @default(0.0)
    expires                 DateTime?
    models                  String[]
    aliases                 Json     @default("{}")
    config                  Json     @default("{}")
    user_id                 String?
    team_id                 String?
    agent_id   String?
    project_id              String?
    permissions             Json     @default("{}")
    max_parallel_requests   Int?
    metadata                Json     @default("{}")
    blocked                 Boolean?
    tpm_limit               BigInt?
    rpm_limit               BigInt?
    max_budget              Float?
    budget_duration         String?
    budget_reset_at         DateTime?
    allowed_cache_controls  String[] @default([])
    allowed_routes          String[] @default([])
    policies                String[] @default([])
    access_group_ids String[] @default([])
    model_spend             Json     @default("{}")
    model_max_budget        Json     @default("{}")
    router_settings  Json? @default("{}")
    budget_id               String?
    organization_id         String?
    object_permission_id    String?
    created_at              DateTime? // Original creation timestamp
    created_by              String?   // Original creator
    updated_at              DateTime? // Last update timestamp before deletion
    updated_by              String?   // Last user who updated before deletion
    last_active             DateTime? // When this key was last used before deletion
    rotation_count          Int?      @default(0)
    auto_rotate             Boolean?  @default(false)
    rotation_interval       String?
    last_rotation_at        DateTime?
    key_rotation_at         DateTime?
    
    // Deletion metadata
    deleted_at              DateTime  @default(now()) @map("deleted_at")
    deleted_by              String?   @map("deleted_by") // User who deleted the key
    deleted_by_api_key      String?   @map("deleted_by_api_key") // API key hash that performed the deletion
    litellm_changed_by      String?   @map("litellm_changed_by") // From litellm-changed-by header if provided
    
    @@index([token])
    @@index([deleted_at])
    @@index([user_id])
    @@index([team_id])
    @@index([organization_id])
    @@index([key_alias])
    @@index([created_at])
}

model LiteLLM_EndUserTable {
  user_id String @id
  alias    String? // admin-facing alias
  spend      Float    @default(0.0)
  allowed_model_region String? // require all user requests to use models in this specific region
  default_model String? // use along with 'allowed_model_region'. if no available model in region, default to this model.
  budget_id String?
  object_permission_id String?
  litellm_budget_table LiteLLM_BudgetTable?   @relation(fields: [budget_id], references: [budget_id])
  object_permission LiteLLM_ObjectPermissionTable?   @relation(fields: [object_permission_id], references: [object_permission_id])
  blocked Boolean @default(false)
}

// Track tags with budgets and spend
model LiteLLM_TagTable {
  tag_name String @id
  description String?
  models String[]
  model_info Json? // maps model_id to model_name
  spend Float @default(0.0)
  budget_id String?
  litellm_budget_table LiteLLM_BudgetTable? @relation(fields: [budget_id], references: [budget_id])
  created_at DateTime @default(now()) @map("created_at")
  created_by String?
  updated_at DateTime @default(now()) @updatedAt @map("updated_at")
}

// store proxy config.yaml
model LiteLLM_Config {
  param_name String @id
  param_value Json?
}

// View spend, model, api_key per request
model LiteLLM_SpendLogs {
  request_id          String @id
  call_type           String
  api_key             String  @default ("") // Hashed API Token. Not the actual Virtual Key. Equivalent to 'token' column in LiteLLM_VerificationToken
  spend               Float    @default(0.0)
  total_tokens        Int     @default(0)
  prompt_tokens       Int     @default(0)
  completion_tokens   Int     @default(0)
  startTime           DateTime // Assuming start_time is a DateTime field
  endTime             DateTime // Assuming end_time is a DateTime field
  request_duration_ms Int?
  completionStartTime DateTime? // Assuming completionStartTime is a DateTime field
  model               String   @default("")
  model_id            String?   @default("") // the model id stored in proxy model db
  model_group         String?   @default("") // public model_name / model_group
  custom_llm_provider String?   @default("") // litellm used custom_llm_provider
  api_base            String?   @default("")
  user                String?   @default("")
  metadata            Json?     @default("{}") // project_id stored here
  cache_hit           String?   @default("")
  cache_key           String?   @default("")
  request_tags        Json?     @default("[]")
  team_id             String? 
  organization_id     String?
  end_user            String?
  requester_ip_address String?
  messages            Json?     @default("{}")
  response            Json?     @default("{}")
  session_id          String?
  status              String?
  mcp_namespaced_tool_name String? 
  agent_id            String?
  proxy_server_request Json?     @default("{}")
  @@index([startTime])
  @@index([startTime, request_id])
  @@index([end_user])
  @@index([session_id])
}

// View spend, model, api_key per request
model LiteLLM_ErrorLogs {
  request_id          String   @id @default(uuid())
  startTime           DateTime // Assuming start_time is a DateTime field
  endTime             DateTime // Assuming end_time is a DateTime field
  api_base            String   @default("") 
  model_group         String   @default("")      // public model_name / model_group
  litellm_model_name  String   @default("")      // model passed to litellm
  model_id            String   @default("")      // ID of model in ProxyModelTable
  request_kwargs      Json     @default("{}")
  exception_type      String   @default("")
  exception_string    String   @default("")
  status_code         String   @default("")
}

// Beta - allow team members to request access to a model
model LiteLLM_UserNotifications {
  request_id          String @id
  user_id             String 
  models              String[]
  justification       String
  status              String // approved, disapproved, pending
}

model LiteLLM_TeamMembership {
  // Use this table to track the Internal User's Spend within a Team + Set Budgets, rpm limits for the user within the team
  user_id    String
  team_id    String
  spend      Float    @default(0.0)
  total_spend Float @default(0.0)
  budget_id String?
  litellm_budget_table LiteLLM_BudgetTable?   @relation(fields: [budget_id], references: [budget_id])
  @@id([user_id, team_id])
}

model LiteLLM_OrganizationMembership {
  // Use this table to track Internal User and Organization membership. Helps tracking a users role within an Organization
  user_id         String
  organization_id String
  user_role       String?
  spend           Float?    @default(0.0)
  budget_id       String?
  created_at      DateTime?               @default(now()) @map("created_at")
  updated_at      DateTime?               @default(now()) @updatedAt @map("updated_at")

  // relations
  user LiteLLM_UserTable @relation(fields: [user_id], references: [user_id])
  organization LiteLLM_OrganizationTable @relation("OrganizationToMembership", fields: [organization_id], references: [organization_id])
  litellm_budget_table LiteLLM_BudgetTable?   @relation(fields: [budget_id], references: [budget_id])
  
  

  @@id([user_id, organization_id])
  @@unique([user_id, organization_id])
}

model LiteLLM_InvitationLink {
  // use this table to track invite links sent by admin for people to join the proxy
  id String   @id @default(uuid())
  user_id String
  is_accepted Boolean @default(false)
  accepted_at DateTime? // when link is claimed (user successfully onboards via link)
  expires_at  DateTime // till when is link valid
  created_at DateTime // when did admin create the link
  created_by String // who created the link
  updated_at DateTime // when was invite status updated
  updated_by String // who updated the status (admin/user who accepted invite)

  // Relations
  liteLLM_user_table_user    LiteLLM_UserTable  @relation("UserId", fields: [user_id], references: [user_id])
  liteLLM_user_table_created LiteLLM_UserTable  @relation("CreatedBy", fields: [created_by], references: [user_id])
  liteLLM_user_table_updated LiteLLM_UserTable  @relation("UpdatedBy", fields: [updated_by], references: [user_id])
}


model LiteLLM_AuditLog {
  id                 String   @id @default(uuid())
  updated_at         DateTime @default(now())
  changed_by         String   @default("")   // user or system that performed the action
  changed_by_api_key String   @default("")   // api key hash that performed the action
  action             String      // create, update, delete
  table_name         String      // on of  LitellmTableNames.TEAM_TABLE_NAME, LitellmTableNames.USER_TABLE_NAME, LitellmTableNames.PROXY_MODEL_TABLE_NAME,
  object_id          String      // id of the object being audited. This can be the key id, team id, user id, model id
  before_value       Json?       // value of the row 
  updated_values     Json?       // value of the row after change
}

// Track daily user spend metrics per model and key
model LiteLLM_DailyUserSpend {
  id                  String   @id @default(uuid())
  user_id             String? 
  date                String
  api_key             String   
  model               String?
  model_group         String?  
  custom_llm_provider String?
  mcp_namespaced_tool_name String?
  endpoint               String?
  prompt_tokens       BigInt      @default(0)
  completion_tokens   BigInt      @default(0)
  cache_read_input_tokens     BigInt      @default(0)
  cache_creation_input_tokens BigInt      @default(0)
  spend               Float    @default(0.0)
  api_requests        BigInt      @default(0)
  successful_requests BigInt      @default(0)
  failed_requests     BigInt      @default(0)
  created_at          DateTime @default(now())
  updated_at          DateTime @updatedAt

  @@unique([user_id, date, api_key, model, custom_llm_provider, mcp_namespaced_tool_name, endpoint])
  @@index([date])
  @@index([user_id, date])
  @@index([api_key])
  @@index([model])
  @@index([mcp_namespaced_tool_name])
  @@index([endpoint])
}

// Track daily organization spend metrics per model and key
model LiteLLM_DailyOrganizationSpend {
  id                  String   @id @default(uuid())
  organization_id     String?
  date                String
  api_key             String   
  model               String?
  model_group         String?  
  custom_llm_provider String?
  mcp_namespaced_tool_name String?
  endpoint               String?
  prompt_tokens       BigInt      @default(0)
  completion_tokens   BigInt      @default(0)
  cache_read_input_tokens     BigInt      @default(0)
  cache_creation_input_tokens BigInt      @default(0)
  spend               Float    @default(0.0)
  api_requests        BigInt      @default(0)
  successful_requests BigInt      @default(0)
  failed_requests     BigInt      @default(0)
  created_at          DateTime @default(now())
  updated_at          DateTime @updatedAt

  @@unique([organization_id, date, api_key, model, custom_llm_provider, mcp_namespaced_tool_name, endpoint])
  @@index([date])
  @@index([organization_id, date])
  @@index([api_key])
  @@index([model])
  @@index([mcp_namespaced_tool_name])
  @@index([endpoint])
}

// Track daily end user (customer) spend metrics per model and key
model LiteLLM_DailyEndUserSpend {
  id                  String   @id @default(uuid())
  end_user_id         String?
  date                String
  api_key             String   
  model               String?
  model_group         String?  
  custom_llm_provider String?
  mcp_namespaced_tool_name String?
  endpoint               String?
  prompt_tokens       BigInt      @default(0)
  completion_tokens   BigInt      @default(0)
  cache_read_input_tokens     BigInt      @default(0)
  cache_creation_input_tokens BigInt      @default(0)
  spend               Float    @default(0.0)
  api_requests        BigInt      @default(0)
  successful_requests BigInt      @default(0)
  failed_requests     BigInt      @default(0)
  created_at          DateTime @default(now())
  updated_at          DateTime @updatedAt
  @@unique([end_user_id, date, api_key, model, custom_llm_provider, mcp_namespaced_tool_name, endpoint])
  @@index([date])
  @@index([end_user_id, date])
  @@index([api_key])
  @@index([model])
  @@index([mcp_namespaced_tool_name])
  @@index([endpoint])
}

// Track daily agent spend metrics per model and key
model LiteLLM_DailyAgentSpend {
  id                  String   @id @default(uuid())
  agent_id            String?
  date                String
  api_key             String   
  model               String?
  model_group         String?  
  custom_llm_provider String?
  mcp_namespaced_tool_name String?
  endpoint               String?
  prompt_tokens       BigInt      @default(0)
  completion_tokens   BigInt      @default(0)
  cache_read_input_tokens     BigInt      @default(0)
  cache_creation_input_tokens BigInt      @default(0)
  spend               Float    @default(0.0)
  api_requests        BigInt      @default(0)
  successful_requests BigInt      @default(0)
  failed_requests     BigInt      @default(0)
  created_at          DateTime @default(now())
  updated_at          DateTime @updatedAt
  @@unique([agent_id, date, api_key, model, custom_llm_provider, mcp_namespaced_tool_name, endpoint])
  @@index([date])
  @@index([agent_id, date])
  @@index([api_key])
  @@index([model])
  @@index([mcp_namespaced_tool_name])
  @@index([endpoint])
}

// Track daily team spend metrics per model and key
model LiteLLM_DailyTeamSpend {
  id                  String   @id @default(uuid())
  team_id             String?
  date                String
  api_key             String   
  model               String?
  model_group         String?  
  custom_llm_provider String?
  mcp_namespaced_tool_name String?
  endpoint               String?
  prompt_tokens       BigInt      @default(0)
  completion_tokens   BigInt      @default(0)
  cache_read_input_tokens     BigInt      @default(0)
  cache_creation_input_tokens BigInt      @default(0)
  spend               Float    @default(0.0)
  api_requests        BigInt      @default(0)
  successful_requests BigInt      @default(0)
  failed_requests     BigInt      @default(0)
  created_at          DateTime @default(now())
  updated_at          DateTime @updatedAt

  @@unique([team_id, date, api_key, model, custom_llm_provider, mcp_namespaced_tool_name, endpoint])
  @@index([date])
  @@index([team_id, date])
  @@index([api_key])
  @@index([model])
  @@index([mcp_namespaced_tool_name])
  @@index([endpoint])
}

// Track daily team spend metrics per model and key
model LiteLLM_DailyTagSpend {
  id                  String   @id @default(uuid())
  request_id          String?
  tag                 String?   
  date                String
  api_key             String   
  model               String?
  model_group         String?  
  custom_llm_provider String?
  mcp_namespaced_tool_name String?
  endpoint               String?
  prompt_tokens       BigInt      @default(0)
  completion_tokens   BigInt      @default(0)
  cache_read_input_tokens     BigInt      @default(0)
  cache_creation_input_tokens BigInt      @default(0)
  spend               Float    @default(0.0)
  api_requests        BigInt      @default(0)
  successful_requests BigInt      @default(0)
  failed_requests     BigInt      @default(0)
  created_at          DateTime @default(now())
  updated_at          DateTime @updatedAt

  @@unique([tag, date, api_key, model, custom_llm_provider, mcp_namespaced_tool_name, endpoint])
  @@index([date])
  @@index([tag, date])
  @@index([api_key])
  @@index([model])
  @@index([mcp_namespaced_tool_name])
  @@index([endpoint])
}


// Track the status of cron jobs running. Only allow one pod to run the job at a time
model LiteLLM_CronJob {
  cronjob_id            String   @id @default(cuid()) // Unique ID for the record
  pod_id         String   // Unique identifier for the pod acting as the leader
  status        JobStatus @default(INACTIVE) // Status of the cron job (active or inactive)
  last_updated   DateTime @default(now()) // Timestamp for the last update of the cron job record
  ttl           DateTime // Time when the leader's lease expires
}

enum JobStatus {
  ACTIVE
  INACTIVE
}

model LiteLLM_ManagedFileTable {
  id String @id @default(uuid())
  unified_file_id String @unique // The base64 encoded unified file ID
  file_object Json? // Stores the OpenAIFileObject
  model_mappings Json
  flat_model_file_ids String[]  @default([]) // Flat list of model file id's - for faster querying of model id -> unified file id
  storage_backend String? // Storage backend name (e.g., "azure_storage", "gcs", "default")
  storage_url String? // The actual storage URL where the file is stored
  created_at DateTime @default(now())
  created_by String?
  team_id String? // Team that owns the resource; populated for service-account keys without a user_id so listings can isolate by team.
  updated_at DateTime @updatedAt
  updated_by String?

  @@index([unified_file_id])
  @@index([team_id, created_at(sort: Desc)])
}

model LiteLLM_ManagedObjectTable { // for batches or finetuning jobs which use the
  id String @id @default(uuid())
  unified_object_id String @unique // The base64 encoded unified file ID
  model_object_id String @unique // the id returned by the backend API provider
  file_object Json // Stores the OpenAIFileObject
  file_purpose String // either 'batch' or 'fine-tune'
  status String? // check if batch cost has been tracked
  batch_processed Boolean @default(false) // set to true by CheckBatchCost after cost is computed
  created_at DateTime @default(now())
  created_by String?
  team_id String?
  updated_at DateTime @updatedAt
  updated_by String?

  @@index([unified_object_id])
  @@index([model_object_id])
  @@index([team_id, created_at(sort: Desc)])
}

model LiteLLM_ManagedVectorStoreTable {
  id String @id @default(uuid())
  unified_resource_id String @unique // The base64 encoded unified vector store ID
  resource_object Json? // Stores the VectorStoreCreateResponse
  model_mappings Json // Maps model_id -> provider_vector_store_id
  flat_model_resource_ids String[] @default([]) // Flat list of provider vector store IDs for faster querying
  storage_backend String? // Storage backend name (if applicable)
  storage_url String? // Storage URL (if applicable)
  created_at DateTime @default(now())
  created_by String?
  team_id String?
  updated_at DateTime @updatedAt
  updated_by String?

  @@index([unified_resource_id])
  @@index([team_id, created_at(sort: Desc)])
}

model LiteLLM_ManagedVectorStoresTable {
  vector_store_id String @id
  custom_llm_provider String
  vector_store_name String?
  vector_store_description String?
  vector_store_metadata Json?
  created_at DateTime @default(now())
  updated_at DateTime @updatedAt
  litellm_credential_name String?
  litellm_params Json?
  team_id String?
  user_id String?
  
  @@index([team_id])
  @@index([user_id])
}

// Guardrails table for storing guardrail configurations
model LiteLLM_GuardrailsTable {
  guardrail_id String @id @default(uuid())
  guardrail_name String @unique
  litellm_params Json
  guardrail_info Json?
  team_id String?
  created_at DateTime @default(now())
  updated_at DateTime @updatedAt
  // Submission lifecycle. Possible values: pending_review (team-registered, awaiting approval), active (approved), rejected
  status String @default("active")
  submitted_at DateTime?
  reviewed_at DateTime?
  // submitted_by_user_id and submitted_by_email live in guardrail_info JSON

  @@index([status])
}

// Daily guardrail metrics for usage dashboard (one row per guardrail per day)
model LiteLLM_DailyGuardrailMetrics {
  guardrail_id        String   // logical id; may not FK if guardrail from config
  date                String   // YYYY-MM-DD
  requests_evaluated  BigInt   @default(0)
  passed_count        BigInt   @default(0)
  blocked_count       BigInt   @default(0)
  flagged_count       BigInt   @default(0)
  avg_score           Float?
  avg_latency_ms      Float?
  created_at          DateTime @default(now())
  updated_at          DateTime @updatedAt

  @@id([guardrail_id, date])
  @@index([date])
  @@index([guardrail_id])
}

// Daily policy metrics for usage dashboard (one row per policy per day)
model LiteLLM_DailyPolicyMetrics {
  policy_id           String
  date                String   // YYYY-MM-DD
  requests_evaluated  BigInt   @default(0)
  passed_count        BigInt   @default(0)
  blocked_count       BigInt   @default(0)
  flagged_count       BigInt   @default(0)
  avg_score           Float?
  avg_latency_ms      Float?
  created_at          DateTime @default(now())
  updated_at          DateTime @updatedAt

  @@id([policy_id, date])
  @@index([date])
  @@index([policy_id])
}

// Index for fast "last N logs for guardrail/policy" from SpendLogs
model LiteLLM_SpendLogGuardrailIndex {
  request_id   String
  guardrail_id String
  policy_id    String?   // set when run as part of a policy pipeline
  start_time   DateTime

  @@id([request_id, guardrail_id])
  @@index([guardrail_id, start_time])
  @@index([policy_id, start_time])
}

// Index for fast "last N logs for tool" from SpendLogs – see how a tool is called in production
model LiteLLM_SpendLogToolIndex {
  request_id String
  tool_name  String   // matches LiteLLM_ToolTable.tool_name; join for input_policy/output_policy etc.
  start_time DateTime

  @@id([request_id, tool_name])
  @@index([tool_name, start_time])
}

// Prompt table for storing prompt configurations
model LiteLLM_PromptTable {
  id String @id @default(uuid())
  prompt_id String
  version Int @default(1)
  environment String @default("development")
  created_by String?
  litellm_params Json
  prompt_info Json?
  created_at DateTime @default(now())
  updated_at DateTime @updatedAt

  @@unique([prompt_id, version, environment])
  @@index([prompt_id, environment])
  @@index([prompt_id])
}

model LiteLLM_HealthCheckTable {
  health_check_id String @id @default(uuid())
  model_name String
  model_id String?
  status String
  healthy_count Int @default(0)
  unhealthy_count Int @default(0)
  error_message String?
  response_time_ms Float?
  details Json?
  checked_by String?
  checked_at DateTime @default(now())
  created_at DateTime @default(now())
  updated_at DateTime @updatedAt

  @@index([model_name])
  @@index([checked_at])
  @@index([status])
  @@index([model_id, model_name, checked_at(sort: Desc)], map: "LiteLLM_HealthCheckTable_model_id_model_name_checked_at_idx")
}

// Search Tools table for storing search tool configurations
model LiteLLM_SearchToolsTable {
  search_tool_id String @id @default(uuid())
  search_tool_name String @unique
  litellm_params Json
  search_tool_info Json?
  created_at DateTime @default(now())
  updated_at DateTime @updatedAt
}

// SSO configuration table
model LiteLLM_SSOConfig {
  id String @id @default("sso_config")
  sso_settings Json
  created_at DateTime @default(now())
  updated_at DateTime @updatedAt
}

model LiteLLM_ManagedVectorStoreIndexTable {
  id String @id @default(uuid())
  index_name String @unique
  litellm_params Json
  index_info Json?
  created_at DateTime @default(now())
  created_by String?
  updated_at DateTime @updatedAt
  updated_by String?
}

// Cache configuration table
model LiteLLM_CacheConfig {
  id String @id @default("cache_config")
  cache_settings Json
  created_at DateTime @default(now())
  updated_at DateTime @updatedAt
}

// UI Settings configuration table
model LiteLLM_UISettings {
  id String @id @default("ui_settings")
  ui_settings Json
  created_at DateTime @default(now())
  updated_at DateTime @updatedAt
}

// Generic config overrides table - one row per config_type
model LiteLLM_ConfigOverrides {
  config_type  String   @id
  config_value Json
  created_at   DateTime @default(now())
  updated_at   DateTime @updatedAt
}

// Skills table for storing LiteLLM-managed skills
model LiteLLM_SkillsTable {
  skill_id       String   @id @default(uuid())
  display_title  String?
  description    String?
  instructions   String?  // The skill instructions/prompt (from SKILL.md)
  source         String   @default("custom")  // "custom" or "anthropic"
  latest_version String?
  file_content   Bytes?   // Binary content of the skill files (zip)
  file_name      String?  // Original filename
  file_type      String?  // MIME type (e.g., "application/zip")
  metadata       Json?    @default("{}")
  created_at     DateTime @default(now())
  created_by     String?
  updated_at     DateTime @default(now()) @updatedAt
  updated_by     String?
}

// Policy table for storing guardrail policies (versioned)
model LiteLLM_PolicyTable {
  policy_id          String    @id @default(uuid())
  policy_name        String    // No longer @unique; use @@unique([policy_name, version_number])
  version_number     Int       @default(1)
  version_status     String    @default("production")  // "draft" | "published" | "production"
  parent_version_id  String?
  is_latest          Boolean   @default(true)
  published_at       DateTime?
  production_at      DateTime?
  inherit            String?   // Name of parent policy to inherit from
  description        String?
  guardrails_add     String[]  @default([])
  guardrails_remove  String[]  @default([])
  condition          Json?     @default("{}")  // Policy conditions (e.g., model matching)
  pipeline           Json?     // Optional guardrail pipeline (mode + steps[])
  created_at         DateTime  @default(now())
  created_by         String?
  updated_at         DateTime  @default(now()) @updatedAt
  updated_by         String?

  @@unique([policy_name, version_number])
  @@index([policy_name, version_status])
}

// Policy attachment table for defining where policies apply
model LiteLLM_PolicyAttachmentTable {
  attachment_id    String    @id @default(uuid())
  policy_name      String    // Name of the policy to attach
  scope            String?   // Use '*' for global scope
  teams            String[]  @default([])  // Team aliases or patterns
  keys             String[]  @default([])  // Key aliases or patterns
  models           String[]  @default([])  // Model names or patterns
  tags             String[]  @default([])  // Tag patterns (e.g., ["healthcare", "prod-*"])
  created_at       DateTime  @default(now())
  created_by       String?
  updated_at       DateTime  @default(now()) @updatedAt
  updated_by       String?
}

// Global tool registry - auto-discovered from LLM responses; admins set input/output policies here
model LiteLLM_ToolTable {
  tool_id        String   @id @default(uuid())
  tool_name      String   @unique   // e.g. "huggingface_remote-mcp__dynamic_space"
  origin         String?            // MCP server name or "user_defined"
  input_policy   String   @default("untrusted")  // "trusted" | "untrusted" | "blocked"
  output_policy  String   @default("untrusted")  // "trusted" | "untrusted"
  call_count     Int      @default(0)            // cumulative number of times this tool was seen
  assignments    Json?    @default("{}")
  key_hash       String?            // hash of the virtual key that first called this tool
  team_id        String?            // team that first called this tool
  key_alias      String?            // human-readable alias of the virtual key
  user_agent     String?            // user-agent of the first request that discovered this tool
  last_used_at   DateTime?          // timestamp of the most recent call
  created_at     DateTime @default(now())
  created_by     String?
  updated_at     DateTime @default(now()) @updatedAt
  updated_by     String?

  @@index([input_policy])
  @@index([output_policy])
  @@index([team_id])
}

// Per-(tool, team/key) policy overrides. When present, override replaces global tool policy for that scope.
//Unified Access Groups table for storing unified access groups
model LiteLLM_AccessGroupTable {
  access_group_id    String   @id @default(uuid())
  access_group_name  String   @unique
  description        String?
  
  // Resource memberships - explicit arrays per type
  access_model_names        String[] @default([])
  access_mcp_server_ids   String[] @default([])
  access_agent_ids        String[] @default([])

  assigned_team_ids         String[] @default([])
  assigned_key_ids          String[] @default([])

  created_at         DateTime @default(now())
  created_by         String?
  updated_at         DateTime @default(now()) @updatedAt
  updated_by         String?
}
// Claude Code Plugin Marketplace table
model LiteLLM_ClaudeCodePluginTable {
  id            String    @id @default(uuid())
  name          String    @unique
  version       String?
  description   String?
  manifest_json String?
  files_json    String?   @default("{}")
  enabled       Boolean   @default(true)
  created_at    DateTime? @default(now())
  updated_at    DateTime? @default(now()) @updatedAt
  created_by    String?

  @@map("LiteLLM_ClaudeCodePluginTable")
}

// User/team-scoped memory store with a GLOBAL unique key.
// `value` is a string (typically markdown/text meant for LLM context);
// `metadata` is an optional JSON envelope for structured tags without schema changes.
// Note: `key` is globally unique across all users/teams — callers should
// namespace their keys (e.g. `user:123:notes`) if they need per-user isolation.
// `user_id` / `team_id` stamp ownership for visibility filtering, but do NOT
// participate in the unique constraint.
model LiteLLM_MemoryTable {
  memory_id   String   @id @default(uuid())
  key         String   @unique
  value       String
  metadata    Json?
  user_id     String?
  team_id     String?
  created_at  DateTime @default(now())
  created_by  String?
  updated_at  DateTime @default(now()) @updatedAt
  updated_by  String?

  @@index([user_id])
  @@index([team_id])
}

// Per-(router, request_type, model) Beta posterior for the adaptive router.
model LiteLLM_AdaptiveRouterState {
  router_name     String
  request_type    String
  model_name      String
  alpha           Float
  beta            Float
  total_samples   Int      @default(0)
  last_updated_at DateTime @default(now()) @updatedAt

  @@id([router_name, request_type, model_name])
}

// Per-(session, router, model) signal counters for the adaptive router.
model LiteLLM_AdaptiveRouterSession {
  session_id             String
  router_name            String
  model_name             String
  classified_type        String

  misalignment_count     Int      @default(0)
  stagnation_count       Int      @default(0)
  disengagement_count    Int      @default(0)
  satisfaction_count     Int      @default(0)
  failure_count          Int      @default(0)
  loop_count             Int      @default(0)
  exhaustion_count       Int      @default(0)

  last_user_content      String?
  last_assistant_content String?
  tool_call_history      Json     @default("[]")
  pending_tool_calls     Json     @default("{}")

  turn_count             Int      @default(0)
  last_processed_turn    Int      @default(-1)
  clean_credit_awarded   Boolean  @default(false)
  terminal_status        Int?
  last_activity_at       DateTime @default(now()) @updatedAt

  @@id([session_id, router_name, model_name])
  @@index([last_activity_at], map: "idx_adaptive_router_session_activity")
}

// ---------------------------------------------------------------------------
// Workflow Run Tracking
//
// Generic durable state tracking for any agent or automated workflow.
// Design: three tables — run (header + materialized status), event (append-only
// source of truth for state transitions), message (conversation inbox/outbox).
//
// Usage:
//   - Set `workflow_type` to identify the owning system (e.g. "shin-builder").
//   - Store domain-specific fields in `metadata` (worktree_path, pr_url, etc.).
//   - `session_id` on WorkflowRun matches `x-litellm-session-id` header sent to
//     the proxy — all spend logs for this run are automatically tagged.
// ---------------------------------------------------------------------------

// One instance of work being done. `status` is a materialized cache of the
// latest event; the event log is the authoritative source of truth.
model LiteLLM_WorkflowRun {
  run_id        String   @id @default(uuid())
  session_id    String   @unique @default(uuid())
  workflow_type String
  status        String   @default("pending")
  created_by    String?  // user_id of the key that created this run; null = created by master key
  created_at    DateTime @default(now())
  updated_at    DateTime @updatedAt
  input         Json?
  output        Json?
  metadata      Json?

  events   LiteLLM_WorkflowEvent[]
  messages LiteLLM_WorkflowMessage[]

  @@index([workflow_type, status])
  @@index([session_id])
  @@index([created_at])
  @@index([created_by])
}

// Append-only log of state transitions. Never mutate rows here.
// `step_name` and `event_type` are caller-defined strings — no hardcoded enums.
// Status auto-update rules (applied by the append endpoint):
//   step.started   → run.status = running
//   step.failed    → run.status = failed
//   hook.waiting   → run.status = paused
//   hook.received  → run.status = running
model LiteLLM_WorkflowEvent {
  event_id        String   @id @default(uuid())
  run_id          String
  event_type      String
  step_name       String
  sequence_number Int
  data            Json?
  created_at      DateTime @default(now())

  run LiteLLM_WorkflowRun @relation(fields: [run_id], references: [run_id])

  @@unique([run_id, sequence_number])
  @@index([run_id])
}

// Conversation inbox/outbox — full message content, separate from the durable
// event log. Spend logs truncate messages; this table stores them in full.
// `session_id` here is the Claude --resume session ID (or similar).
model LiteLLM_WorkflowMessage {
  message_id      String   @id @default(uuid())
  run_id          String
  role            String
  content         String
  sequence_number Int
  session_id      String?
  created_at      DateTime @default(now())

  run LiteLLM_WorkflowRun @relation(fields: [run_id], references: [run_id])

  @@unique([run_id, sequence_number])
  @@index([run_id])
}
