// (d) Function-call round trip with streaming: tool-call event names, function_call item shape, sending function_call_output back. import { client, attempt, save, PROBE_MODELS, summarizeResponse } from "./lib"; const tools: any = [{ type: "function", name: "get_weather", description: "Get current weather for a city", strict: true, parameters: { type: "object", properties: { city: { type: "string" }, unit: { type: "string", enum: ["c", "f"] } }, required: ["city", "unit"], additionalProperties: false } }]; const userMsg = { role: "user", content: "What's the weather in Paris right now in celsius? You must call get_weather." }; const out: any[] = []; for (const model of PROBE_MODELS) { out.push(await attempt(`tools-stream:${model}`, async () => { const stream = await client.responses.create({ model, input: [userMsg], tools, tool_choice: "auto", max_output_tokens: 200, stream: true } as any); const order: string[] = []; const samples: Record = {}; let final: any = null; let args = ""; for await (const ev of stream as any) { if (!samples[ev.type]) { order.push(ev.type); const { response, ...rest } = ev; samples[ev.type] = response ? { ...rest, response: "" } : rest; } if (ev.type === "response.function_call_arguments.delta") args += ev.delta; if (ev.type === "response.completed" || ev.type === "response.incomplete") final = ev.response; } const call = final.output.find((o: any) => o.type === "function_call"); let second: any = null, secondViaPrev: any = null; if (call) { const fco = { type: "function_call_output", call_id: call.call_id, output: JSON.stringify({ city: "Paris", temp_c: 18, sky: "cloudy" }) }; // Stateless pass-back: replay user msg + ALL output items (incl. reasoning items) + tool output. const r2: any = await client.responses.create({ model, input: [userMsg, ...final.output, fco], tools, max_output_tokens: 120 } as any); second = summarizeResponse(r2); if (model === "gpt-5.4-mini") { // stateful variant on one model only const r3: any = await client.responses.create({ model, previous_response_id: final.id, input: [fco], tools, max_output_tokens: 120 } as any); secondViaPrev = summarizeResponse(r3); } } return { event_order: order, samples, streamed_arguments: args, first: summarizeResponse(final), function_call_item: call ?? null, output_items_full: final.output.map((o: any) => ({ ...o, encrypted_content: o.encrypted_content ? `<${o.encrypted_content.length} chars>` : undefined })), second_turn: second, second_turn_via_previous_response_id: secondViaPrev }; })); } save("05-tools-stream", out);