Nirmos
TypeScript SDKGateway

Streaming

Consume normalized chat output as it is generated.

nirmos.gateway.chat.stream starts a streamed chat completion and returns a ChatStream.

const stream = await nirmos.gateway.chat.stream({
  model: "openai/gpt-4.1-mini",
  messages: [{ role: "user", content: "Write a product description." }],
});

for await (const event of stream) {
  if (event.type === "content.delta") {
    process.stdout.write(event.delta ?? "");
  }
}

The SDK parses Server-Sent Events, handles network chunk boundaries, normalizes provider-compatible chunks, and exposes one async iterable.

Event types

TypeMeaning
content.deltaNew text for one choice
toolCall.deltaPartial function tool call
completion.completedFully assembled normalized completion

Event type values are extensible. Ignore unrecognized events unless your application explicitly supports them.

for await (const event of stream) {
  switch (event.type) {
    case "content.delta":
      process.stdout.write(event.delta ?? "");
      break;
    case "toolCall.delta":
      console.log(event.toolCall);
      break;
    case "completion.completed":
      console.log(event.completion?.usage);
      break;
  }
}

Get the final completion

After iteration, call finalResponse() to get the same normalized response shape as chat.create:

const completion = await stream.finalResponse();

console.log(completion.outputText);
console.log(completion.usage.totalTokens);
console.log(completion.metadata.requestId);

If you only need complete text, use text() instead of manually iterating:

const stream = await nirmos.gateway.chat.stream({
  model: "openai/gpt-4.1-mini",
  messages: [{ role: "user", content: "Summarize this incident." }],
});

const text = await stream.text();

A stream has one consumption path. Do not iterate it from multiple tasks. Wait for active iteration to finish before calling finalResponse().

Cancellation

Pass an AbortSignal as the second argument:

const controller = new AbortController();

const stream = await nirmos.gateway.chat.stream(
  {
    model: "openai/gpt-4.1-mini",
    messages: [{ role: "user", content: "Write a long report." }],
  },
  { signal: controller.signal },
);

setTimeout(() => controller.abort(), 5_000);

Cancellation raises RequestAbortedError, including after stream headers arrive. Timeouts raise TimeoutError. Invalid SSE data and server-declared stream failures raise StreamError.

On this page