// Probe 01: (a) tiny non-streaming completion with usage accounting; (b) streaming via raw SSE (comments, delta shapes, final usage). import { raw, rawSSE, save, short } from "./lib.ts"; import { MODELS, byId } from "./models.ts"; const results: any = {}; for (const model of MODELS) { const reasoningCapable = !!byId.get(model)?.reasoning; const body: any = { model, messages: [{ role: "user", content: "What is 2+2? Answer in one short sentence." }], max_tokens: 200, usage: { include: true }, }; if (reasoningCapable) body.reasoning = { effort: "low" }; const t0 = Date.now(); const r = await raw("/chat/completions", { method: "POST", body: JSON.stringify(body) }); const b: any = r.body; results[model] = { status: r.status, ms: Date.now() - t0, headers: r.headers, body: b }; console.log( `\n[${model}] ${r.status} ${Date.now() - t0}ms provider=${b?.provider} model=${b?.model} finish=${b?.choices?.[0]?.finish_reason}/${b?.choices?.[0]?.native_finish_reason}`, ); console.log(" top-level keys:", Object.keys(b ?? {}).join(",")); console.log(" message keys:", Object.keys(b?.choices?.[0]?.message ?? {}).join(",")); console.log(" content:", short(b?.choices?.[0]?.message?.content, 120)); console.log(" reasoning:", short(b?.choices?.[0]?.message?.reasoning, 120), "details:", short(b?.choices?.[0]?.message?.reasoning_details, 300)); console.log(" usage:", JSON.stringify(b?.usage)); if (b?.error) console.log(" ERROR:", JSON.stringify(b.error)); } save("01-chat.json", results); // (b) streaming const streams: any = {}; for (const model of MODELS) { const reasoningCapable = !!byId.get(model)?.reasoning; const body: any = { model, messages: [{ role: "user", content: "Say hello in French, 5 words max." }], max_tokens: 150, stream: true, usage: { include: true }, }; if (reasoningCapable) body.reasoning = { effort: "low" }; const t0 = Date.now(); const s = await rawSSE("/chat/completions", body); const ev = s.events; const deltaKeys = new Set(); let text = ""; let reasoning = ""; let details: any[] = []; for (const e of ev) { if (e.data === "[DONE]") continue; const d = e.data?.choices?.[0]?.delta ?? {}; for (const k of Object.keys(d)) deltaKeys.add(k); if (d.content) text += d.content; if (d.reasoning) reasoning += d.reasoning; if (d.reasoning_details) details.push(...d.reasoning_details); } const withUsage = ev.filter((e) => e.data?.usage); const finishChunks = ev.filter((e) => e.data?.choices?.[0]?.finish_reason); streams[model] = { status: s.status, ms: Date.now() - t0, headers: s.headers, comments: s.comments, count: ev.length, first: ev[0]?.data, second: ev[1]?.data, finishChunks: finishChunks.map((e) => e.data), usageChunk: withUsage.map((e) => e.data), last: ev[ev.length - 1]?.data, deltaKeys: [...deltaKeys], text, reasoning: reasoning.slice(0, 400), reasoningDetailsTypes: [...new Set(details.map((x) => x.type))], reasoningDetailsSample: details.slice(0, 2), error: (s as any).error, }; console.log( `\n[stream ${model}] ${s.status} ${Date.now() - t0}ms events=${ev.length} comments=${JSON.stringify(s.comments)} deltaKeys=${[...deltaKeys]} usageChunks=${withUsage.length} finishChunks=${finishChunks.length}`, ); console.log(" text:", short(text, 100), "| reasoning:", short(reasoning, 100), "| details types:", streams[model].reasoningDetailsTypes); console.log(" first:", short(ev[0]?.data, 400)); console.log(" usage chunk:", short(withUsage[0]?.data, 700)); console.log(" last:", short(ev[ev.length - 1]?.data, 200)); if ((s as any).error) console.log(" ERROR", short((s as any).error)); } save("01-stream.json", streams);