Architektur: Craftvia-Domänenmodell, Verträge und Team-Schnitte
- Migration 0002_craftvia_domain: 27 Fachtabellen inkl. RLS (enable_tenant_rls) - TENANT_MODELS (db.ts, backup/topology.ts) um alle Fachmodelle ergänzt - moduleGuard liefert DB-autoritative Rechte; ServiceCtx für Domänen-Services - Verträge: Statusmaschine, Events, Nummernkreise, Sichtbarkeits-Scopes, Job-Queues + Worker, KI-Provider-Interfaces, Sync-Envelope - docs/craftvia/ARCHITEKTUR.md mit Lanes, Ownership und DoD Gate: tsc, lint, build, 22/22 Tests grün. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
// Provider abstraction for AI/OCR (spec §31). Concrete implementations:
|
||||
// src/server/ai/extraction/anthropic.ts (imports lane)
|
||||
// src/server/ai/transcription/openai-compatible.ts (lotse lane)
|
||||
// src/server/ai/lotse/anthropic.ts (lotse lane)
|
||||
// Every call must be recorded as AiGeneration. Without configuration the getters return null
|
||||
// and callers degrade gracefully (manual entry).
|
||||
|
||||
export type ExtractedField<T = string> = {
|
||||
value: T | null;
|
||||
/** 0..1 */
|
||||
confidence: number;
|
||||
/** optional source snippet for the review mask */
|
||||
source?: string;
|
||||
};
|
||||
|
||||
export type WorkOrderExtraction = {
|
||||
orderNumber: ExtractedField;
|
||||
offerNumber: ExtractedField;
|
||||
customerNumber: ExtractedField;
|
||||
companyName: ExtractedField;
|
||||
customerFirstName: ExtractedField;
|
||||
customerLastName: ExtractedField;
|
||||
customerAddress: ExtractedField<{ street?: string; houseNumber?: string; postalCode?: string; city?: string; country?: string }>;
|
||||
siteName: ExtractedField;
|
||||
siteAddress: ExtractedField<{ street?: string; houseNumber?: string; postalCode?: string; city?: string; country?: string }>;
|
||||
contactName: ExtractedField;
|
||||
phone: ExtractedField;
|
||||
email: ExtractedField;
|
||||
orderDate: ExtractedField; // ISO date
|
||||
documentDate: ExtractedField; // ISO date
|
||||
plannedStart: ExtractedField; // ISO date
|
||||
plannedEnd: ExtractedField; // ISO date
|
||||
title: ExtractedField;
|
||||
description: ExtractedField;
|
||||
positions: ExtractedField<Array<{ position?: string; name: string; articleNumber?: string; quantity?: number; unit?: string; isMaterial?: boolean }>>;
|
||||
notes: ExtractedField;
|
||||
totalAmount: ExtractedField<number>;
|
||||
references: ExtractedField<string[]>;
|
||||
};
|
||||
|
||||
export type ProviderMeta = { provider: string; model: string; inputTokens?: number; outputTokens?: number };
|
||||
|
||||
export interface DocumentExtractionProvider {
|
||||
readonly name: string;
|
||||
readonly model: string;
|
||||
extract(input: { bytes: Buffer; mimeType: string; fileName: string }): Promise<{
|
||||
text: string;
|
||||
extraction: WorkOrderExtraction;
|
||||
meta: ProviderMeta;
|
||||
}>;
|
||||
}
|
||||
|
||||
export interface TranscriptionProvider {
|
||||
readonly name: string;
|
||||
readonly model: string;
|
||||
transcribe(input: { bytes: Buffer; mimeType: string; language: "de" | "en" }): Promise<{ text: string; meta: ProviderMeta }>;
|
||||
}
|
||||
|
||||
export type ReportDraftInput = {
|
||||
locale: "de" | "en";
|
||||
addressForm: "sie" | "du";
|
||||
workOrder: { title: string; description?: string | null; scope?: string | null; orderType?: string | null };
|
||||
notes: Array<{ kind: string; text: string; at: string }>;
|
||||
checklist: Array<{ label: string; checked: boolean; comment?: string | null }>;
|
||||
materials: Array<{ name: string; planned?: string; actual: string; unit: string; status: string; reason?: string | null }>;
|
||||
photos: Array<{ phase?: string | null; comment?: string | null; requirement?: string | null }>;
|
||||
time: Array<{ type: string; minutes: number; user: string }>;
|
||||
};
|
||||
|
||||
export type ReportDraftOutput = {
|
||||
workPerformed: string;
|
||||
deviations: string;
|
||||
additionalWork: string;
|
||||
openItems: string;
|
||||
nextSteps: string;
|
||||
hints: string;
|
||||
missingInformation: string[];
|
||||
meta: ProviderMeta;
|
||||
};
|
||||
|
||||
export interface LotseProvider {
|
||||
readonly name: string;
|
||||
readonly model: string;
|
||||
draftReport(input: ReportDraftInput): Promise<ReportDraftOutput>;
|
||||
}
|
||||
Reference in New Issue
Block a user