Beispiel

Streaming in eigene Website / App einbauen

Der Endpunkt /v1/chat/completions streamt mit "stream": true Server-Sent Events im OpenAI-Format. Jeder Frame ist data: <chat.completion.chunk>; die Orchestrierungs-Schritte (Routing, Decomposition, Subtasks, Synthese) kommen live als delta.content, danach die Antwort, ein usage-Chunk und data: [DONE].

Sicherheit: Setze deinen API-Key (enk_…) niemals in Client-/Browser-Code — er wäre für jeden sichtbar. Für die Produktion den Aufruf über deinen eigenen Server proxen (siehe unten). Das Browser-Snippet ist nur zum Prototyping.

Browser (JavaScript) — SSE lesen

Reines fetch + ReadableStream — parst die SSE-Frames und rendert Orchestrierungs-Events und Antwort in dein eigenes Element:

// Prototyping only — see the security note below before shipping.
async function askStream(prompt, onDelta, onEvent) {
  const res = await fetch("https://enigmanet.eu/v1/chat/completions", {
    method: "POST",
    headers: {
      "Authorization": "Bearer enk_…",   // do NOT ship a real key in client code
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      model: "gemma3:4b",
      stream: true,
      messages: [{ role: "user", content: prompt }],
    }),
  });

  const reader = res.body.getReader();
  const decoder = new TextDecoder();
  let buffer = "";

  while (true) {
    const { value, done } = await reader.read();
    if (done) break;
    buffer += decoder.decode(value, { stream: true });

    const frames = buffer.split("\n\n");
    buffer = frames.pop() ?? "";           // keep the last, possibly-partial frame
    for (const frame of frames) {
      const line = frame.replace(/^data: /, "").trim();
      if (!line) continue;
      if (line === "[DONE]") return;
      const chunk = JSON.parse(line);
      const delta = chunk.choices?.[0]?.delta?.content;
      if (delta) onDelta(delta);           // orchestration lines, then the answer
      if (chunk.enigma) onEvent?.(chunk.enigma);   // structured: { event, area, task }
    }
  }
}

// Usage: render into your own element
const out = document.getElementById("answer");
askStream(
  "Vergleiche Rust und Go für Backend-Services.",
  (text) => { out.textContent += text; },
  (ev)   => { console.log("orchestration:", ev.event, ev.area ?? ev.task ?? ""); },
);

Server-Proxy (empfohlen für Produktion)

Dein Backend hält den Key und reicht den Stream durch — der Browser ruft nur deinen eigenen Endpunkt auf:

// Recommended for production: keep the API key on YOUR server and proxy the
// stream, so it never reaches the browser. (Next.js App Router example.)
// app/api/ask/route.ts
export async function POST(req: Request) {
  const body = await req.json();
  const upstream = await fetch("https://enigmanet.eu/v1/chat/completions", {
    method: "POST",
    headers: {
      "Authorization": `Bearer ${process.env.ENIGMA_API_KEY}`,  // server-side env
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ ...body, stream: true }),
  });
  // Pass the SSE stream straight through to the browser.
  return new Response(upstream.body, {
    headers: { "Content-Type": "text/event-stream", "Cache-Control": "no-cache, no-transform" },
  });
}
// The browser then fetches YOUR /api/ask with the same SSE-parsing loop above.

Chunk-Format

Volle Referenz: API-Doku.