Files
craftvia/scripts/test-lotse-live.ts
T

59 lines
2.8 KiB
TypeScript

// L9 Lotse — optional live test of the Claude report draft and voice summary against a synthetic,
// already minimised input. Runs ONLY when ANTHROPIC_API_KEY is set (costs tokens); otherwise it skips
// with exit 0 so the default gate stays offline.
//
// Lauf: ANTHROPIC_API_KEY=… npx tsx scripts/test-lotse-live.ts
import "dotenv/config";
import { getLotseProvider } from "../src/server/ai/lotse/anthropic";
import type { ReportDraftInput } from "../src/server/ai/providers";
async function main() {
if (!process.env.ANTHROPIC_API_KEY?.trim()) {
console.log("↷ übersprungen: kein ANTHROPIC_API_KEY gesetzt (Live-Berichtsentwurf gegen Claude).");
process.exit(0);
}
const provider = getLotseProvider();
if (!provider) {
console.log("↷ übersprungen: Lotse nicht konfiguriert.");
process.exit(0);
}
let failures = 0;
const ok = (cond: boolean, msg: string) => {
console.log(`${cond ? "✓" : "✗ FEHLER"} ${msg}`);
if (!cond) failures++;
};
const input: ReportDraftInput = {
locale: "de",
addressForm: "neutral",
workOrder: { title: "Heizkörper tauschen", description: "Kundin erreichbar unter [Telefon].", scope: "Heizkörper im Bad ersetzen", orderType: "Reparatur" },
notes: [
{ kind: "work_done", text: "M. M. hat den alten Heizkörper demontiert und den neuen montiert.", at: "2026-09-14T08:30:00+02:00" },
{ kind: "deviation (Sprachnotiz)", text: "Nur ein Heizkörper verbaut, zweiter war beschädigt.", at: "2026-09-14T10:00:00+02:00" },
],
checklist: [{ label: "Anlage entlüftet", checked: false, comment: null }],
materials: [{ name: "Heizkörper 600x1000", planned: "2", actual: "1", unit: "Stk", status: "partially_used", reason: null }],
photos: [{ phase: "after", comment: "Neuer Heizkörper montiert", requirement: null }],
time: [{ type: "work", minutes: 95, user: "M. M." }],
};
const started = Date.now();
const out = await provider.draftReport(input);
console.log(` Modell ${out.meta.model}, Tokens ${out.meta.inputTokens}/${out.meta.outputTokens}, ${Date.now() - started} ms`);
ok(out.workPerformed.trim().length > 0, "workPerformed nicht leer");
ok(Array.isArray(out.missingInformation), "missingInformation ist eine Liste");
ok(!/\[Telefon\]/.test(`${out.workPerformed}${out.hints}`), "Platzhalter nicht in den Bericht übernommen");
ok(!/\b(Sie|du)\b/.test(out.missingInformation.join(" ")), "Neutrale Anrede in missingInformation");
const summary = await provider.summarizeTranscript({ locale: "de", addressForm: "neutral", transcript: "Also, der alte Heizkörper ist raus, der neue hängt, entlüften mach ich morgen." });
ok(summary.summary.trim().length > 0, "Zusammenfassung nicht leer");
process.exit(failures ? 1 : 0);
}
main().catch((err) => {
console.error(err);
process.exit(1);
});