/** * Structured outputs + streaming with the Node SDK: JSON arrives as ordinary text_delta chunks; accumulate with * finalMessage() then JSON.parse. Also counts tokens with output_config.format (no grammar compilation). * STATUS: LIVE_VERIFIED 2026-09-18 (claude-haiku-4-5-20251001): parsed {name:'Ada',age:36,city:'Lyon'}; count_tokens 205 (~$0.0003). * Run: node --env-file=.env --experimental-strip-types examples/anthropic/structured-output/json_schema_stream.ts */ import Anthropic from "@anthropic-ai/sdk"; import { appendFileSync } from "node:fs"; const MODEL = process.env.ANTHROPIC_MODEL ?? "claude-haiku-4-5-20251001"; const client = new Anthropic({ maxRetries: 1 }); const log = (path: string, status: number, note: string) => appendFileSync("reports/live-requests.jsonl", JSON.stringify({ ts: new Date().toISOString(), provider: "anthropic", method: "POST", path, status, est_cost_usd: 0.0003, note }) + "\n"); const schema = { type: "object", properties: { name: { type: "string" }, age: { type: "integer" }, city: { type: "string" } }, required: ["name", "age", "city"], additionalProperties: false, }; const params = { model: MODEL, max_tokens: 100, output_config: { format: { type: "json_schema", schema } }, messages: [{ role: "user", content: "Ada is 36 and lives in Lyon. Extract the person." }], } as const; const deltas: string[] = []; const stream = client.messages.stream(params as any).on("text", (t) => deltas.push(t)); const final = await stream.finalMessage(); const text = final.content[0].type === "text" ? final.content[0].text : ""; console.log("chunks:", deltas.length, "parsed:", JSON.parse(text)); log("/v1/messages", 200, `example structured-output/json_schema_stream.ts stream ${MODEL}`); const count = await client.messages.countTokens({ model: MODEL, messages: params.messages as any, output_config: params.output_config } as any); console.log("count_tokens with format:", count.input_tokens); log("/v1/messages/count_tokens", 200, `example structured-output/json_schema_stream.ts count ${MODEL}`);