// Probe 08: Responses API (stateless check), endpoints listing, ZDR list, header variants, :batch behaviour, prompt caching on a repeated prompt, reasoning_details round trip on Anthropic. import { raw, rawSSE, save, short } from "./lib.ts"; import { OPENAI, ANTHROPIC, GOOGLE, byId } from "./models.ts"; const results: any = {}; // Responses API { const r = await raw("/responses", { method: "POST", body: JSON.stringify({ model: OPENAI, input: "Say hi in 3 words.", max_output_tokens: 30, reasoning: { effort: "low" } }) }); const b: any = r.body; results.responses_basic = { status: r.status, keys: Object.keys(b ?? {}), outputTypes: b?.output?.map((o: any) => o.type), usage: b?.usage, model: b?.model, provider: b?.provider, store: b?.store, error: b?.error }; console.log(`[responses] ${r.status} keys=${Object.keys(b ?? {})} output=${b?.output?.map((o: any) => o.type)} usage=${JSON.stringify(b?.usage)} ${b?.error ? JSON.stringify(b.error) : ""}`); const r2 = await raw("/responses", { method: "POST", body: JSON.stringify({ model: OPENAI, input: "hi", max_output_tokens: 30, store: true }) }); results.responses_store_true = { status: r2.status, body: r2.body }; console.log(`[responses store:true] ${r2.status} ${short(r2.body, 300)}`); const r3 = await raw("/responses", { method: "POST", body: JSON.stringify({ model: ANTHROPIC, input: "hi", max_output_tokens: 30, previous_response_id: "resp_123" }) }); results.responses_prev_id = { status: r3.status, body: r3.body }; console.log(`[responses previous_response_id] ${r3.status} ${short(r3.body, 300)}`); const s = await rawSSE("/responses", { model: ANTHROPIC, input: "Say hi in 3 words.", max_output_tokens: 30, stream: true }); results.responses_stream = { status: s.status, eventTypes: [...new Set(s.events.map((e) => e.data?.type ?? e.data))], eventNames: [...new Set(s.events.map((e) => e.event))], count: s.events.length, last: s.events[s.events.length - 2]?.data }; console.log(`[responses stream] ${s.status} events=${s.events.length} types=${results.responses_stream.eventTypes} eventNames=${results.responses_stream.eventNames}`); } // Endpoints for a model + ZDR list { const slug = byId.get(ANTHROPIC)?.canonical_slug ?? ANTHROPIC; const r = await raw(`/models/${ANTHROPIC}/endpoints`); const b: any = r.body; results.endpoints = { status: r.status, keys: Object.keys(b?.data ?? {}), endpointKeys: Object.keys(b?.data?.endpoints?.[0] ?? {}), endpoints: b?.data?.endpoints?.map((e: any) => ({ name: e.name, provider_name: e.provider_name, tag: e.tag, context_length: e.context_length, max_completion_tokens: e.max_completion_tokens, pricing: e.pricing, supported_parameters: e.supported_parameters, status: e.status, quantization: e.quantization, uptime_last_30m: e.uptime_last_30m, supports_implicit_caching: e.supports_implicit_caching })) }; console.log(`\n[endpoints ${ANTHROPIC}] ${r.status} keys=${results.endpoints.keys} endpointKeys=${results.endpoints.endpointKeys}`); console.log(" ", short(results.endpoints.endpoints, 800)); const z = await raw("/endpoints/zdr"); const zb: any = z.body; results.zdr = { status: z.status, count: zb?.data?.length, sample: zb?.data?.slice(0, 2), keys: Object.keys(zb ?? {}) }; console.log(`[zdr] ${z.status} count=${zb?.data?.length} sample=${short(zb?.data?.[0], 300)}`); const p = await raw("/providers"); const pb: any = p.body; results.providers = { status: p.status, count: pb?.data?.length, sample: pb?.data?.slice(0, 2) }; console.log(`[providers] ${p.status} count=${pb?.data?.length} sample=${short(pb?.data?.[0], 300)}`); } // Header variants: X-Title vs X-OpenRouter-Title, both accepted? { for (const [name, headers] of Object.entries({ x_title: { "X-Title": "PolyLLM" }, x_openrouter_title: { "X-OpenRouter-Title": "PolyLLM" } })) { const r = await raw("/chat/completions", { method: "POST", headers, body: JSON.stringify({ model: OPENAI, messages: [{ role: "user", content: "hi" }], max_tokens: 5, reasoning: { effort: "none" } }) }); results[`header_${name}`] = { status: r.status, id: (r.body as any)?.id }; console.log(`[header ${name}] ${r.status}`); } } // :batch variant behaviour (what does chat/completions do with it?) { const ctrl = new AbortController(); const t = setTimeout(() => ctrl.abort(), 60_000); const t0 = Date.now(); try { const r = await raw("/chat/completions", { method: "POST", signal: ctrl.signal, body: JSON.stringify({ model: `${OPENAI}:batch`, messages: [{ role: "user", content: "hi" }], max_tokens: 5, usage: { include: true } }) }); results.batch = { status: r.status, ms: Date.now() - t0, body: r.body }; console.log(`\n[batch] ${r.status} ${Date.now() - t0}ms ${short(r.body, 500)}`); } catch (e: any) { results.batch = { error: String(e), ms: Date.now() - t0 }; console.log(`\n[batch] aborted after ${Date.now() - t0}ms: ${e}`); } finally { clearTimeout(t); } } // Prompt caching: Anthropic with cache_control on a ~1200-token system prompt, twice { const big = "You are a helpful assistant. " + "The quick brown fox jumps over the lazy dog near the riverbank while the sun sets slowly. ".repeat(260); const body = { model: ANTHROPIC, messages: [ { role: "system", content: [{ type: "text", text: big, cache_control: { type: "ephemeral" } }] }, { role: "user", content: "Reply with the single word OK." }, ], max_tokens: 5, usage: { include: true }, }; const a = await raw("/chat/completions", { method: "POST", body: JSON.stringify(body) }); const bb = await raw("/chat/completions", { method: "POST", body: JSON.stringify(body) }); results.cache = { first: (a.body as any)?.usage, second: (bb.body as any)?.usage, err: (a.body as any)?.error ?? (bb.body as any)?.error }; console.log(`\n[cache anthropic] first=${JSON.stringify(results.cache.first)}\n second=${JSON.stringify(results.cache.second)} ${results.cache.err ? JSON.stringify(results.cache.err) : ""}`); // OpenAI automatic caching with the same big prompt const body2 = { model: OPENAI, messages: [{ role: "system", content: big }, { role: "user", content: "Reply with the single word OK." }], max_tokens: 5, usage: { include: true }, reasoning: { effort: "none" } }; const c = await raw("/chat/completions", { method: "POST", body: JSON.stringify(body2) }); const d = await raw("/chat/completions", { method: "POST", body: JSON.stringify(body2) }); results.cache_openai = { first: (c.body as any)?.usage, second: (d.body as any)?.usage }; console.log(`[cache openai] first=${JSON.stringify(results.cache_openai.first)}\n second=${JSON.stringify(results.cache_openai.second)}`); } // Reasoning on Anthropic (max_tokens budget) and Google (mandatory reasoning) — reasoning_details shapes, non-streaming { for (const model of [ANTHROPIC, GOOGLE]) { const r = await raw("/chat/completions", { method: "POST", body: JSON.stringify({ model, messages: [{ role: "user", content: "Is 17 prime? One sentence." }], max_tokens: 200, reasoning: { max_tokens: 1024 }, usage: { include: true } }), }); const b: any = r.body; const m = b?.choices?.[0]?.message; results[`reasoning_${model}`] = { status: r.status, provider: b?.provider, reasoning: m?.reasoning, reasoning_details: m?.reasoning_details, usage: b?.usage, error: b?.error }; console.log(`\n[reasoning ${model}] ${r.status} reasoning=${short(m?.reasoning, 100)} details=${short(m?.reasoning_details?.map((d: any) => ({ ...d, text: d.text?.slice(0, 40), data: d.data?.slice(0, 20), signature: d.signature?.slice(0, 20) })), 500)} usage=${JSON.stringify(b?.usage)} ${b?.error ? JSON.stringify(b.error) : ""}`); } } save("08-misc.json", results);