# Streaming

> Full event streaming from the chat API.

Source: https://maincode.com/docs/client-sdk-streaming
Section: Client SDK · Matilda documentation

---

## `chat.stream(params, options?)`

Returns an async generator that yields `MatildaChatStreamEvent` objects as they arrive over SSE. This is the full event stream — tool calls, usage, status changes, safety replacements, and more.

```ts title="stream.ts"
for await (const event of client.chat.stream({ input: 'Explain quantum computing.' })) {
  switch (event.type) {
    case 'response.created':
      console.log(`Stream started: ${event.streamId}`);
      break;
    case 'response.output_text.delta':
      process.stdout.write(event.delta);
      break;
    case 'response.tool_call.started':
      console.log(`\nTool: ${event.tool}`);
      break;
    case 'response.usage':
      console.log(`\nTokens: ${event.usage.output_tokens}`);
      break;
    case 'response.completed':
      console.log('\n--- Done ---');
      break;
    case 'response.error':
      console.error(`Error: ${event.code} — ${event.message}`);
      break;
  }
}
```

## `MatildaChatStreamEvent`

A discriminated union of 14 event types:

### `response.created`

Emitted once at stream start with the durable stream ID.

```ts
{ type: 'response.created'; streamId: string }
```

### `response.output_text.delta`

A text chunk from the assistant.

```ts
{ type: 'response.output_text.delta'; delta: string }
```

### `response.output_text.replace`

The server replaced the output (e.g. safety filter). The `content` field holds the replacement text; `categories` lists the safety categories that triggered the replacement.

```ts
{ type: 'response.output_text.replace'; content?: string; categories?: string[] }
```

### `response.status`

Stream lifecycle status change.

```ts
{ type: 'response.status'; status: 'thinking' | 'streaming' | 'queued' | 'idle' | 'done' | 'error' | string }
```

### `response.queued`

Queue position update while waiting for a free slot.

```ts
{ type: 'response.queued'; state: string; position: number; estimatedWaitSeconds: number }
```

### `response.tool_call.started`

A server-side tool invocation began.

```ts
{ type: 'response.tool_call.started'; tool: string; inputOrArgs?: string | Record<string, unknown>; output?: string }
```

### `response.tool_call.progress`

Progress update from a running tool.

```ts
{ type: 'response.tool_call.progress'; tool: string; message: string }
```

### `response.tool_call.completed`

A tool invocation finished.

```ts
{ type: 'response.tool_call.completed'; tool: string; status: 'success' | 'error'; input?: string; output?: string }
```

### `response.generation_status`

Generation phase update.

```ts
{ type: 'response.generation_status'; phase: string }
```

### `response.usage`

Token usage data for the turn.

```ts
{ type: 'response.usage'; usage: UsageEvent }
```

Where `UsageEvent` is:

```ts
interface UsageEvent {
  output_tokens: number;
  context_pct?: number;              // context window usage (0-100)
  context_messages_trimmed?: number; // messages trimmed to fit context budget
  context_budget_tokens?: number;    // total context budget in tokens
}
```

### `response.cursor`

Durable stream cursor (Redis stream entry ID). Persist this to resume from this point.

```ts
{ type: 'response.cursor'; lastEventId: string }
```

### `response.truncated`

The response was cut short.

```ts
{ type: 'response.truncated'; reason: string }
```

### `response.completed`

The stream finished successfully.

```ts
{ type: 'response.completed' }
```

### `response.error`

An error occurred during the stream.

```ts
{ type: 'response.error'; code: ChatErrorCode; message: string }
```
