feat: Auswertung der Sprachnotizen mit Claude (T7 L4 Tasks 14, 15)
Task 14: Port StructuredModel mit Anthropic-Adapter (@anthropic-ai/sdk 0.131.0 exakt, Lieferkette geprüft), fester Endpunkt https://api.anthropic.com (Umgebungs-Header werden entfernt), feste Systemregeln ohne Datum/Volk/Person, Transkript als Daten in Tags, strukturierte Ausgabe per JSON-Schema mit effort low, serverseitiger Fallback per VOICE_SERVER_FALLBACK abschaltbar. Jeder Vorschlag wird geprüft: bekanntes Feld, Wert in den Formulargrenzen, Zitat steht wörtlich im Gesagten (Dezimalzahl als ein Wort), Korrektur gewinnt. Netzwächter: nur die Worker-Verdrahtung erreicht den Adapter (transitiv geprüft). Task 15: Worker-Schleife voice-extractions (LISTEN + 15-s-Abfrage, ein Lauf zugleich, höchstens 20 Notizen je Lauf), Modellaufruf außerhalb jeder Transaktion mit 240-s-Obergrenze, Ergebnis versiegelt mit Ereignis nur bei gehaltenem Claim; ohne Schlüssel EXTRACT_DISABLED ohne Versuch, Tageslimit zählt jeden bezahlten Aufruf über das neue Journal VoiceExtractionCall (nur IDs, Modell, Tokens, Ergebnis; 90 Tage, nicht im Backup). Nur der Worker-Container erhält ANTHROPIC_API_KEY aus dem Secret apicore-anthropic (optional); API- und Job-Rollen warnen, wenn der Schlüssel bei ihnen gesetzt ist. Gates: Backend lint, typecheck, 4589 Unit-Tests, build; e2e 104 Suites (nur der Wetter-Test gegen die echte API schwankt); Manifest-Policy 55. Refs #27 Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
1 parent
89a1546f15
commit
6a915aad9c
38 files changed
+3612
-33
No files matched your search
@@ -45,6 +45,7 @@ describe('CleanupJob', () => {
|
||||
inactiveOwnersWiped: 3,
|
||||
});
|
||||
jest.spyOn(voiceRetention, 'deleteOldVoiceRows').mockResolvedValue(4);
|
||||
jest.spyOn(voiceRetention, 'deleteOldVoiceCalls').mockResolvedValue(6);
|
||||
jest.spyOn(voiceRetention, 'deleteIdleVoiceRuns').mockResolvedValue(21);
|
||||
let count = 10;
|
||||
executeRaw = jest.fn<Promise<number>, RawCall>(() =>
|
||||
@@ -76,6 +77,7 @@ describe('CleanupJob', () => {
|
||||
|
||||
expect(voiceRetention.expireVoiceContent).toHaveBeenCalledTimes(1);
|
||||
expect(voiceRetention.deleteOldVoiceRows).toHaveBeenCalledTimes(1);
|
||||
expect(voiceRetention.deleteOldVoiceCalls).toHaveBeenCalledTimes(1);
|
||||
expect(voiceRetention.deleteIdleVoiceRuns).toHaveBeenCalledWith(
|
||||
expect.anything(),
|
||||
VOICE_IDLE_RUN_RETENTION_HOURS,
|
||||
@@ -118,6 +120,7 @@ describe('CleanupJob', () => {
|
||||
'voice.contentExpired': 2,
|
||||
'voice.inactiveOwnersWiped': 3,
|
||||
'voice.rowsDeleted': 4,
|
||||
'voice.callsDeleted': 6,
|
||||
'jobRuns.voiceIdle': 21,
|
||||
});
|
||||
});
|
||||
|
||||
@@ -4,6 +4,7 @@ import { PrismaService } from '../prisma/prisma.service';
|
||||
import { JobRunService } from '../system/job-run.service';
|
||||
import {
|
||||
deleteIdleVoiceRuns,
|
||||
deleteOldVoiceCalls,
|
||||
deleteOldVoiceRows,
|
||||
expireVoiceContent,
|
||||
} from '../voice/voice-retention';
|
||||
@@ -112,6 +113,7 @@ export class CleanupJob implements Job {
|
||||
// after 90 days.
|
||||
const voiceRetention = await expireVoiceContent(this.prisma);
|
||||
const voiceRowsDeleted = await deleteOldVoiceRows(this.prisma);
|
||||
const voiceCallsDeleted = await deleteOldVoiceCalls(this.prisma);
|
||||
// 1440 runs a day, nearly all without work: keep only runs that did
|
||||
// something (a counter above 0) or failed, for the usual 90 days.
|
||||
const voiceIdleRuns = await deleteIdleVoiceRuns(
|
||||
@@ -137,6 +139,7 @@ export class CleanupJob implements Job {
|
||||
'voice.contentExpired': voiceRetention.contentExpired,
|
||||
'voice.inactiveOwnersWiped': voiceRetention.inactiveOwnersWiped,
|
||||
'voice.rowsDeleted': voiceRowsDeleted,
|
||||
'voice.callsDeleted': voiceCallsDeleted,
|
||||
'jobRuns.voiceIdle': voiceIdleRuns,
|
||||
};
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user