L16 Lotse-Chat für Monteure: Datenmodell, Provider mit Tool-Schleife, Vorschläge und Bestätigen über bestehende Services
Chatverlauf (LotseConversation/-Message) und Aktionskarten (LotseActionProposal) als Mandantentabellen mit RLS; Schalter lotseChatEnabled. Tool-Use-Schleife mit Runden- und Tokengrenze, Datenminimierung per Platzhalter, Auftragszuordnung im Sichtbarkeits-Scope, Bestätigen/Verwerfen/Alle bestätigen mit Hash, Ablauf und Idempotenz, Transkriptions-API. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -79,6 +79,8 @@ model TenantSettings {
|
||||
lotseAddressForm String? @map("lotse_address_form")
|
||||
// L10b (Spec §31): monthly AI token budget (input + output) per tenant; null = env AI_MONTHLY_TOKEN_LIMIT, 0 = unlimited
|
||||
aiMonthlyTokenLimit Int? @map("ai_monthly_token_limit")
|
||||
// L16 Lotse-Chat für Monteure: switch per tenant (effective only while the Lotse module is on)
|
||||
lotseChatEnabled Boolean @default(true) @map("lotse_chat_enabled")
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
updatedAt DateTime @updatedAt @map("updated_at")
|
||||
|
||||
@@ -1433,3 +1435,85 @@ model BillingRecord {
|
||||
@@index([tenantId, workOrderId])
|
||||
@@map("billing_records")
|
||||
}
|
||||
|
||||
// ---------- L16 Lotse-Chat für Monteure ----------
|
||||
|
||||
enum LotseMessageRole {
|
||||
user
|
||||
assistant
|
||||
tool
|
||||
}
|
||||
|
||||
enum LotseProposalStatus {
|
||||
proposed
|
||||
confirmed
|
||||
discarded
|
||||
expired
|
||||
failed
|
||||
}
|
||||
|
||||
/// Chat of ONE user with the Lotse (only visible to that user). Optional work order context
|
||||
/// (chat opened from the order detail). Deleted by the Lotse retention (services/lotse/retention.ts).
|
||||
model LotseConversation {
|
||||
id String @id @default(cuid())
|
||||
tenantId String @map("tenant_id")
|
||||
userId String @map("user_id")
|
||||
workOrderId String? @map("work_order_id")
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
updatedAt DateTime @updatedAt @map("updated_at")
|
||||
lastMessageAt DateTime @default(now()) @map("last_message_at")
|
||||
|
||||
messages LotseMessage[]
|
||||
proposals LotseActionProposal[]
|
||||
|
||||
@@index([tenantId, userId, lastMessageAt])
|
||||
@@index([tenantId, lastMessageAt])
|
||||
@@map("lotse_conversations")
|
||||
}
|
||||
|
||||
/// One chat message. `text` = what the user sees; `content` = structured parts (chips, proposal ids,
|
||||
/// links, placeholder text sent to the model).
|
||||
model LotseMessage {
|
||||
id String @id @default(cuid())
|
||||
tenantId String @map("tenant_id")
|
||||
conversationId String @map("conversation_id")
|
||||
role LotseMessageRole
|
||||
text String
|
||||
content Json?
|
||||
aiGenerationId String? @map("ai_generation_id")
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
|
||||
conversation LotseConversation @relation(fields: [conversationId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@index([tenantId, conversationId, createdAt])
|
||||
@@map("lotse_messages")
|
||||
}
|
||||
|
||||
/// Action card proposed by the Lotse. Nothing is executed before the owner confirms it
|
||||
/// (services/lotse/chat/confirm.ts runs the existing services with the owner's context).
|
||||
model LotseActionProposal {
|
||||
id String @id @default(cuid())
|
||||
tenantId String @map("tenant_id")
|
||||
conversationId String @map("conversation_id")
|
||||
messageId String? @map("message_id")
|
||||
userId String @map("user_id")
|
||||
workOrderId String? @map("work_order_id")
|
||||
kind String
|
||||
payload Json
|
||||
payloadHash String @map("payload_hash")
|
||||
status LotseProposalStatus @default(proposed)
|
||||
expiresAt DateTime @map("expires_at")
|
||||
result Json?
|
||||
errorCode String? @map("error_code")
|
||||
confirmedAt DateTime? @map("confirmed_at")
|
||||
confirmedById String? @map("confirmed_by_id")
|
||||
decidedAt DateTime? @map("decided_at")
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
updatedAt DateTime @updatedAt @map("updated_at")
|
||||
|
||||
conversation LotseConversation @relation(fields: [conversationId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@index([tenantId, conversationId, createdAt])
|
||||
@@index([tenantId, userId, status])
|
||||
@@map("lotse_action_proposals")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user