TypeScript 97.4%
SQL 1%
JavaScript 0.9%
CSS 0.6%
1import { CHAT_MODELS, post, rawSSE, save, short } from "./lib.ts";23const tools = [4 {5 type: "function",6 function: {7 name: "get_weather",8 description: "Get the current weather for a city",9 parameters: { type: "object", properties: { city: { type: "string", description: "City name" } }, required: ["city"] },10 },11 },12];1314const results: Record<string, any> = {};15for (const model of CHAT_MODELS) {16 console.log(`\n=== ${model}`);17 const messages: any[] = [{ role: "user", content: "What's the weather in Montreal right now? Use the tool." }];18 const s = await rawSSE("/chat/completions", { model, messages, tools, tool_choice: "auto", max_tokens: 200, stream: true });19 const toolDeltas: any[] = [];20 let finish: any;21 let usage: any;22 for (const e of s.events) {23 if (e.data === "[DONE]") continue;24 const ch = e.data?.choices?.[0];25 if (ch?.delta?.tool_calls) toolDeltas.push(ch.delta);26 if (ch?.finish_reason) finish = ch.finish_reason;27 if (e.data?.usage) usage = e.data.usage;28 }29 console.log(`stream ${s.status} events=${s.events.length} finish=${finish} toolDeltaChunks=${toolDeltas.length}`);30 console.log("tool deltas", short(toolDeltas, 900));31 console.log("usage", JSON.stringify(usage));32 // assemble33 const calls: Record<number, any> = {};34 for (const d of toolDeltas)35 for (const tc of d.tool_calls) {36 const idx = tc.index ?? 0;37 calls[idx] ??= { id: tc.id, type: tc.type, function: { name: "", arguments: "" } };38 if (tc.id) calls[idx].id = tc.id;39 if (tc.function?.name) calls[idx].function.name += tc.function.name;40 if (tc.function?.arguments) calls[idx].function.arguments += tc.function.arguments;41 }42 const toolCalls = Object.values(calls);43 console.log("assembled", JSON.stringify(toolCalls));44 let round2: any = null;45 if (toolCalls.length) {46 messages.push({ role: "assistant", content: "", tool_calls: toolCalls });47 for (const tc of toolCalls)48 messages.push({ role: "tool", tool_call_id: tc.id, name: tc.function.name, content: JSON.stringify({ temp_c: -3, sky: "snow" }) });49 round2 = await post("/chat/completions", { model, messages, tools, max_tokens: 100 });50 console.log(`round2 ${round2.status} ${short(round2.body?.choices?.[0]?.message?.content ?? round2.body, 200)}`);51 }52 results[model] = { stream: { status: s.status, events: s.events, toolDeltas }, assembled: toolCalls, round2 };53}54// tool_call_id format constraint: try a long OpenAI-style id in a tool message55const bad = await post("/chat/completions", {56 model: "mistral-small-latest",57 max_tokens: 50,58 messages: [59 { role: "user", content: "Weather in Paris?" },60 { role: "assistant", content: "", tool_calls: [{ id: "call_abc123def456ghi789", type: "function", function: { name: "get_weather", arguments: '{"city":"Paris"}' } }] },61 { role: "tool", tool_call_id: "call_abc123def456ghi789", name: "get_weather", content: '{"temp_c": 12}' },62 ],63 tools,64});65console.log("\nlong tool_call_id round trip", bad.status, short(bad.body, 400));66results.longToolCallId = bad;67save("03-tools-stream.json", results);68