Client SDK · Chat

Durable streaming.

Resume an interrupted stream from the last received event.

Durable streaming lets a client disconnect mid-stream and resume from where it left off. The server buffers events in a Redis stream, keyed by a streamId advertised at stream start.

Durable streaming lifecycle

  1. Start a stream — chat.stream() emits a response.created event with a streamId.
  2. Persist the streamId and conversationId immediately.
  3. If disconnected, call chat.activeStream(conversationId) to check if the stream is still live.
  4. Call chat.resume({ streamId, lastEventId }) to replay buffered events from lastEventId onwards.

chat.resume(params, options?)

Resumes a previously detached stream by replaying buffered events from lastEventId. Returns an async generator of MatildaChatStreamEvent.

TypeScript
for await (const event of client.chat.resume({
  streamId: savedStreamId,
  lastEventId: savedLastEventId,
})) {
  if (event.type === 'response.output_text.delta') {
    process.stdout.write(event.delta);
  }
}

ChatResumeParams

Fieldtypedescription
streamIdstringThe stream ID from response.created.
lastEventIdstringThe last Redis stream entry ID received. Omit to replay from the start.

chat.activeStream(conversationId, options?)

Checks whether a conversation has an active stream.

TypeScript
const result = await client.chat.activeStream('conv-123');
// { stream_id: 'abc-123' | null, status: 'active' | 'done' | 'error' | null }

Returns Promise<ActiveStreamLookup>:

TypeScript
interface ActiveStreamLookup {
  stream_id: string | null;
  status: 'active' | 'done' | 'error' | null;
}

chat.notifyOnCompletion(streamId, enabled?, options?)

Request a push notification when a backgrounded stream completes.

TypeScript
await client.chat.notifyOnCompletion(streamId, true);
Fieldtypedescription
streamIdstringThe stream to watch.
enabledbooleanEnable or disable the notification. Defaults to true.

Returns Promise<{ status: string }>.

Full resume example

TypeScript
import Matilda from '@maincode-ai/matilda-client-sdk';

const client = new Matilda({
  baseUrl: 'https://matilda.maincode.com/api',
  accessToken: process.env.MATILDA_ACCESS_TOKEN!,
});

let streamId: string | null = null;
let lastEventId: string | undefined;

// Start streaming
for await (const event of client.chat.stream({
  input: 'Write a long essay about Australia.',
  conversationId: 'conv-123',
})) {
  if (event.type === 'response.created') {
    streamId = event.streamId;
  }
  if (event.type === 'response.cursor') {
    lastEventId = event.lastEventId;
  }
  if (event.type === 'response.output_text.delta') {
    process.stdout.write(event.delta);
  }
}

// Later — check if the stream is still active, then resume
const active = await client.chat.activeStream('conv-123');
if (active.status === 'active' && streamId) {
  console.log('\n--- Resuming ---');
  for await (const event of client.chat.resume({ streamId, lastEventId })) {
    if (event.type === 'response.output_text.delta') {
      process.stdout.write(event.delta);
    }
  }
}