import assert from "node:assert/strict"; import { mkdir, mkdtemp, readFile, writeFile } from "node:fs/promises"; import { createServer } from "node:http"; import { tmpdir } from "node:os"; import { join } from "node:path"; import test from "node:test"; import { createApp, sessionConfiguration } from "../server.mjs"; const origin = "https://intent.example.test"; const conversationId = "2026-09-15-123e4567-e89b-12d3-a456-426614174000"; async function withApp(options, run) { const server = createServer(createApp({ origin, apiKey: "test-key", ...options })); await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve)); const { port } = server.address(); try { await run(`http://127.0.0.1:${port}`); } finally { await new Promise((resolve) => server.close(resolve)); } } function post(url, path, payload, headers = {}) { return fetch(`${url}${path}`, { method: "POST", headers: { Origin: origin, "Content-Type": "application/json", ...headers }, body: JSON.stringify(payload), }); } function payload(overrides = {}) { return { conversationId, finalization: "confirmed", transcript: [{ speaker: "Nutzer", text: "Bitte halte dieses Gespräch fest." }], ...overrides, }; } test("creates a Live WebRTC session through the server only", async () => { let received; await withApp({ fetchImpl: async (_url, options) => { received = JSON.parse(options.body); return Response.json({ session: { id: "live_test" }, transport: { type: "webrtc", sdp: "answer" } }, { status: 201 }); }, }, async (url) => { const response = await post(url, "/api/session", { sdp: "offer" }); assert.equal(response.status, 201); assert.equal((await response.json()).session.id, "live_test"); }); assert.equal(received.session.model, "gpt-live-1"); assert.equal(received.transport.type, "webrtc"); assert.equal(received.session.store, false); }); test("rejects cross-origin state-changing requests", async () => { await withApp({}, async (url) => { const response = await fetch(`${url}/api/transcripts`, { method: "POST", headers: { Origin: "https://wrong.example", "Content-Type": "application/json" }, body: JSON.stringify(payload()), }); assert.equal(response.status, 403); }); }); test("saves a transcript without an API call, retries idempotently, and downloads it", async () => { const directory = await mkdtemp(join(tmpdir(), "live-intent-test-")); let calls = 0; await withApp({ apiKey: "", transcriptsDirectory: directory, fetchImpl: async () => { calls += 1; throw new Error("must not call API"); } }, async (url) => { const first = await post(url, "/api/transcripts", payload()); assert.equal(first.status, 201); const saved = await first.json(); assert.equal(saved.created, true); const retry = await post(url, "/api/transcripts", payload()); assert.equal(retry.status, 200); assert.equal((await retry.json()).created, false); const stored = await fetch(`${url}${saved.url}`); assert.equal(stored.status, 200); assert.match(await stored.text(), /Session-Abschluss: bestätigt/); }); assert.equal(calls, 0); assert.match(await readFile(join(directory, conversationId, "transcript.md"), "utf8"), /Gesprächstranskript/); }); test("rejects a collision without overwriting the original transcript", async () => { const directory = await mkdtemp(join(tmpdir(), "live-intent-test-")); await withApp({ transcriptsDirectory: directory }, async (url) => { assert.equal((await post(url, "/api/transcripts", payload({ finalization: "unconfirmed" }))).status, 201); const collision = await post(url, "/api/transcripts", payload({ transcript: [{ speaker: "Nutzer", text: "Anderer Inhalt." }] })); assert.equal(collision.status, 409); }); assert.match(await readFile(join(directory, conversationId, "transcript.md"), "utf8"), /Session-Abschluss: unbestätigt/); }); test("preserves existing intents while storing new transcripts", async () => { const stateDirectory = await mkdtemp(join(tmpdir(), "live-intent-test-")); const oldIntent = join(stateDirectory, "intents", "old-conversation", "intent.md"); await mkdir(join(stateDirectory, "intents", "old-conversation"), { recursive: true }); await writeFile(oldIntent, "# Alter Intent\n", "utf8"); await withApp({ transcriptsDirectory: join(stateDirectory, "transcripts") }, async (url) => { assert.equal((await post(url, "/api/transcripts", payload())).status, 201); }); assert.equal(await readFile(oldIntent, "utf8"), "# Alter Intent\n"); }); test("session configuration preserves the documented model and in-conversation delegation", () => { const body = sessionConfiguration({ liveModel: "gpt-live-1", backendModel: "gpt-5.6-luna" }, "offer"); assert.equal(body.session.model, "gpt-live-1"); assert.equal(body.transport.type, "webrtc"); assert.equal(body.session.delegation.type, "responses"); assert.match(body.session.instructions, /kein Intent erzeugt/); });