Earlier chapters used result.tokenStream, a flat string iterable of the model's text. The stream gives you raw output, but content and thinking look identical without type tags. The events surface dispatches each by type, so they come through separately.
On a completion run, this surface is the canonical one. Each item carries a payload: a content delta, a thinking block, a tool call, a stats frame, the terminal done, or the raw text.
The previous lesson covered contentDelta and thinkingDelta firing side by side. This one covers the full set, plus the result.final promise that joins them all into one object.
Here's how you'd dispatch the events in a streaming loop:
for await (const event of result.events) {
switch (event.type) {
case "contentDelta":
process.stdout.write(event.text);
break;
case "thinkingDelta":
process.stderr.write(`[think] ${event.text}`);
break;
case "toolCall":
console.log(`▸ tool ${event.call.name}(${JSON.stringify(event.call.arguments)})`);
break;
case "completionStats":
console.log(`▸ ${event.stats.tokensPerSecond?.toFixed(1)} tok/s`);
break;
case "completionDone":
break;
}
}contentDelta is the model's text token-by-token, written to stdout. thinkingDelta is the chain-of-thought stream, written to stderr with a [think] prefix so the reasoning isn't mixed into the user-visible response. toolCall marks a function-call emission in the response stream. completionStats carries throughput numbers.
After the loop, await result.final joins them into one object: contentText, thinkingText, toolCalls, stats, stopReason, raw.fullText. Reading the aggregate would look like this:
console.log();
const final = await result.final;
console.log(`▸ Final contentText: ${final.contentText}`);
console.log(`▸ Stop reason: ${final.stopReason}`);Note:
tokenStreamstill works for simple cases, but new code should consumeeventsfor streaming andfinal.contentTextfor the aggregated result.
Question 1 of 2
What's the difference between result.tokenStream and result.events?
Question 2 of 2
Which event type routes to process.stderr instead of process.stdout in this event loop?
Run your code, check your answer, or ask a question. It all shows up here.