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
@@ -5,6 +5,7 @@ import { AllInOneModule } from '../all-in-one.module';
|
||||
import { AppModule } from '../app.module';
|
||||
import { ThrottlerStorageModule } from '../common/throttler/throttler-storage.module';
|
||||
import { DomainEventRegistry } from '../domain-events/domain-event-registry';
|
||||
import { VoiceWorkerModule } from '../voice/voice-worker.module';
|
||||
import { WorkerModule } from '../worker/worker.module';
|
||||
import { WorkerRuntimeModule } from '../worker/worker-runtime.module';
|
||||
import { isHttpRole, rootModuleFor } from './root-module';
|
||||
@@ -76,6 +77,8 @@ describe('rootModuleFor', () => {
|
||||
const reachable = await reachableModules(AppModule);
|
||||
|
||||
expect(reachable).not.toContain(WorkerRuntimeModule);
|
||||
// The Anthropic adapter (and so the key) exists in the worker only.
|
||||
expect(reachable).not.toContain(VoiceWorkerModule);
|
||||
// The walk really goes deep: into feature modules and dynamic modules.
|
||||
expect(reachable).toContain(DiscoveryModule);
|
||||
expect(reachable).toContain(ThrottlerStorageModule);
|
||||
@@ -94,6 +97,7 @@ describe('rootModuleFor', () => {
|
||||
const reachable = await reachableModules(WorkerModule);
|
||||
|
||||
expect(reachable).toContain(WorkerRuntimeModule);
|
||||
expect(reachable).toContain(VoiceWorkerModule);
|
||||
expect(reachable).not.toContain(AppModule);
|
||||
});
|
||||
|
||||
@@ -110,6 +114,10 @@ describe('rootModuleFor', () => {
|
||||
const worker = await discoveredHandlerIds(WorkerModule);
|
||||
|
||||
expect(api).toContain('webhooks.forward');
|
||||
// voice handlers are registered in the worker
|
||||
expect(worker).toEqual(
|
||||
expect.arrayContaining(['voice.notify-ready', 'voice.notify-failed']),
|
||||
);
|
||||
expect(worker).toEqual(api);
|
||||
} finally {
|
||||
if (previousSecret === undefined) {
|
||||
|
||||
Reference in new issue
Block a user