Skip to Content
Client SDKChat CompletionsStreaming chat completions

Streaming chat completions

Set streamMode to true and pass an onChunk callback to client.streamChat().

Stream a completion

import { ServiceProvider } from '@preternatural-js/client-sdk' const result = await client.streamChat( { messages: [ { role: 'user', content: 'Write a short description of Saturn.' } ], scope: { provider: ServiceProvider.openai, modelIdentifier: 'gpt-4o-mini', productId: 'your-product-id' }, temperature: 0.7, maxTokens: 500, streamMode: true }, chunk => { appendToInterface(chunk) } )

Read the final text

The current return type is string | ChatCompletion. Narrow it before using the value as text:

const result = await client.streamChat(request, chunk => { appendToInterface(chunk) }) if (typeof result !== 'string') { throw new Error('Expected streamed text') } console.log('Complete response:', result)

Cancel the request

Pass an AbortSignal on the request:

import { CustomerStreamCancelledError, ServiceProvider } from '@preternatural-js/client-sdk' const controller = new AbortController() stopButton.addEventListener( 'click', () => controller.abort(), { once: true } ) try { await client.streamChat( { messages: [ { role: 'user', content: 'Write a long essay about Saturn.' } ], scope: { provider: ServiceProvider.openai, modelIdentifier: 'gpt-4o-mini', productId: 'your-product-id' }, temperature: 0.7, maxTokens: 2_000, streamMode: true, signal: controller.signal }, chunk => { appendToInterface(chunk) } ) } catch (error) { if (!(error instanceof CustomerStreamCancelledError)) { throw error } }

A caller-initiated cancellation rejects with CustomerStreamCancelledError.

Return a ReadableStream

Server-side code can use streamServerSideChat() to obtain a web-standard ReadableStream<string>:

const stream = client.streamServerSideChat({ messages: [ { role: 'user', content: 'Write a short description of Saturn.' } ], scope: { provider: ServiceProvider.openai, modelIdentifier: 'gpt-4o-mini', productId: 'your-product-id' }, temperature: 0.7, maxTokens: 500, streamMode: true })

Read it with a stream reader:

const reader = stream.getReader() try { while (true) { const { done, value } = await reader.read() if (done) { break } appendToInterface(value) } } finally { reader.releaseLock() }

Canceling the returned stream aborts the gateway request:

await reader.cancel()

streamServerSideChat() always sends a streaming provider request. Its streamMode input does not change that behavior.

Handle customer access changes

The SDK watches gateway errors while a stream is active.

If the customer becomes revoked, suspended, or deleted, the SDK clears the customer session and terminates any ongoing streams:

import { CustomerAccessInvalidatedError } from '@preternatural-js/client-sdk' try { await client.streamChat(request, handleChunk) } catch (error) { if (error instanceof CustomerAccessInvalidatedError) { console.error(error.reason) redirectToSignIn() } else { throw error } }