Skip to content

Chat Events

Defined in: chat/events.ts:222

Chat event bus: a typed event emitter specialized for ChatEvent types with middleware pipeline support.

Events pass through the middleware pipeline before reaching listeners. Middleware can inspect, transform, or suppress events.

const bus = new ChatEventBus();
// Add middleware
bus.use((ctx) => {
console.log(`[${ctx.event.type}]`);
ctx.next();
});
// Listen for events
bus.on("message:delta", (event) => {
console.log(event.text);
});
// Emit events
bus.emit("message:delta", { type: "message:delta", messageId: id, text: "hi" });

new ChatEventBus(): ChatEventBus

ChatEventBus

TypedEventEmitter.constructor

clearMiddleware(): void

Defined in: chat/events.ts:296

Remove all middleware functions.

void

emit<K>(event, payload): void

Defined in: chat/events.ts:246

Emit a chat event through the middleware pipeline, then to listeners.

K extends "heartbeat" | "error" | "done" | "usage" | "message:start" | "message:delta" | "message:complete" | "tool:start" | "tool:complete" | "thinking:start" | "thinking:delta" | "thinking:end" | "permission:request" | "permission:response" | "session:created" | "session:updated" | "typing:start" | "typing:end"

K

ChatEvent type string

ChatEventMap[K]

The full ChatEvent object

void

TypedEventEmitter.emit

eventNames(): ("heartbeat" | "error" | "done" | "usage" | "message:start" | "message:delta" | "message:complete" | "tool:start" | "tool:complete" | "thinking:start" | "thinking:delta" | "thinking:end" | "permission:request" | "permission:response" | "session:created" | "session:updated" | "typing:start" | "typing:end")[]

Defined in: chat/events.ts:138

Get all event names that have at least one listener.

("heartbeat" | "error" | "done" | "usage" | "message:start" | "message:delta" | "message:complete" | "tool:start" | "tool:complete" | "thinking:start" | "thinking:delta" | "thinking:end" | "permission:request" | "permission:response" | "session:created" | "session:updated" | "typing:start" | "typing:end")[]

Array of event names

TypedEventEmitter.eventNames

listenerCount<K>(event): number

Defined in: chat/events.ts:129

Get the number of listeners for a specific event.

K extends "heartbeat" | "error" | "done" | "usage" | "message:start" | "message:delta" | "message:complete" | "tool:start" | "tool:complete" | "thinking:start" | "thinking:delta" | "thinking:end" | "permission:request" | "permission:response" | "session:created" | "session:updated" | "typing:start" | "typing:end"

K

Event name

number

Number of listeners

TypedEventEmitter.listenerCount

middlewareCount(): number

Defined in: chat/events.ts:304

Get the number of registered middleware functions.

number

Number of middleware

off<K>(event, listener): void

Defined in: chat/events.ts:90

Remove a specific listener from an event.

K extends "heartbeat" | "error" | "done" | "usage" | "message:start" | "message:delta" | "message:complete" | "tool:start" | "tool:complete" | "thinking:start" | "thinking:delta" | "thinking:end" | "permission:request" | "permission:response" | "session:created" | "session:updated" | "typing:start" | "typing:end"

K

Event name

Listener<ChatEventMap[K]>

The listener to remove

void

TypedEventEmitter.off

on<K>(event, listener): Unsubscribe

Defined in: chat/events.ts:55

Subscribe to an event.

K extends "heartbeat" | "error" | "done" | "usage" | "message:start" | "message:delta" | "message:complete" | "tool:start" | "tool:complete" | "thinking:start" | "thinking:delta" | "thinking:end" | "permission:request" | "permission:response" | "session:created" | "session:updated" | "typing:start" | "typing:end"

K

Event name

Listener<ChatEventMap[K]>

Callback receiving the event payload

Unsubscribe

Unsubscribe function

TypedEventEmitter.on

once<K>(event, listener): Unsubscribe

Defined in: chat/events.ts:77

Subscribe to an event, firing the listener at most once.

K extends "heartbeat" | "error" | "done" | "usage" | "message:start" | "message:delta" | "message:complete" | "tool:start" | "tool:complete" | "thinking:start" | "thinking:delta" | "thinking:end" | "permission:request" | "permission:response" | "session:created" | "session:updated" | "typing:start" | "typing:end"

K

Event name

Listener<ChatEventMap[K]>

Callback receiving the event payload

Unsubscribe

Unsubscribe function

TypedEventEmitter.once

removeAllListeners<K>(event?): void

Defined in: chat/events.ts:116

Remove all listeners for a specific event, or all events if no event specified.

K extends "heartbeat" | "error" | "done" | "usage" | "message:start" | "message:delta" | "message:complete" | "tool:start" | "tool:complete" | "thinking:start" | "thinking:delta" | "thinking:end" | "permission:request" | "permission:response" | "session:created" | "session:updated" | "typing:start" | "typing:end"

K

Optional event name

void

TypedEventEmitter.removeAllListeners

use(middleware): Unsubscribe

Defined in: chat/events.ts:230

Register a middleware function. Middleware runs in registration order.

EventMiddleware

Middleware function

Unsubscribe

Unsubscribe function to remove the middleware


Defined in: chat/events.ts:46

Generic type-safe event emitter parameterized by an EventMap.

type MyEvents = {
message: string;
count: number;
done: void;
};
const emitter = new TypedEventEmitter<MyEvents>();
emitter.on("message", (text) => console.log(text));
emitter.emit("message", "hello");

T extends EventMap

Map of event names to payload types

new TypedEventEmitter<T>(): TypedEventEmitter<T>

TypedEventEmitter<T>

emit<K>(event, payload): void

Defined in: chat/events.ts:104

Emit an event, calling all registered listeners synchronously.

K extends string | number | symbol

K

Event name

T[K]

Event payload

void

eventNames(): keyof T[]

Defined in: chat/events.ts:138

Get all event names that have at least one listener.

keyof T[]

Array of event names

listenerCount<K>(event): number

Defined in: chat/events.ts:129

Get the number of listeners for a specific event.

K extends string | number | symbol

K

Event name

number

Number of listeners

off<K>(event, listener): void

Defined in: chat/events.ts:90

Remove a specific listener from an event.

K extends string | number | symbol

K

Event name

Listener<T[K]>

The listener to remove

void

on<K>(event, listener): Unsubscribe

Defined in: chat/events.ts:55

Subscribe to an event.

K extends string | number | symbol

K

Event name

Listener<T[K]>

Callback receiving the event payload

Unsubscribe

Unsubscribe function

once<K>(event, listener): Unsubscribe

Defined in: chat/events.ts:77

Subscribe to an event, firing the listener at most once.

K extends string | number | symbol

K

Event name

Listener<T[K]>

Callback receiving the event payload

Unsubscribe

Unsubscribe function

removeAllListeners<K>(event?): void

Defined in: chat/events.ts:116

Remove all listeners for a specific event, or all events if no event specified.

K extends string | number | symbol

K

Optional event name

void

Defined in: chat/events.ts:159

Context passed to middleware functions. Contains the event and control methods for the middleware pipeline.

event: ChatEvent

Defined in: chat/events.ts:161

The current event (may be transformed by prior middleware)

next: () => void

Defined in: chat/events.ts:163

Call the next middleware in the chain, or deliver to listeners if last

void

suppress: () => void

Defined in: chat/events.ts:165

Suppress the event — do not deliver to listeners or subsequent middleware

void

ChatEventMap = { [K in ChatEventType]: Extract<ChatEvent, { type: K }> }

Defined in: chat/events.ts:149

Map of ChatEvent type strings to their corresponding ChatEvent payloads. Used to parameterize TypedEventEmitter for chat events.


EventMap = Record<string, any>

Defined in: chat/events.ts:17

Constraint for event maps: keys are strings, values are payloads


EventMiddleware = (ctx) => void

Defined in: chat/events.ts:192

Middleware function for intercepting, transforming, or suppressing events. EventMiddleware operates at the ChatEventBus level.

MiddlewareContext

Middleware context with event, next(), and suppress()

void

// Logging middleware
const logger: EventMiddleware = (ctx) => {
console.log(`Event: ${ctx.event.type}`);
ctx.next();
};
// Suppressing middleware
const filter: EventMiddleware = (ctx) => {
if (ctx.event.type === "heartbeat") {
ctx.suppress();
} else {
ctx.next();
}
};

Listener<T> = (payload) => void

Defined in: chat/events.ts:22

Listener callback for a specific event

T

T

void


Unsubscribe = () => void

Defined in: chat/events.ts:25

Unsubscribe function returned by on/once

void

collectText(source): Promise<string>

Defined in: chat/events.ts:396

Collect text from message:delta events into a single string.

AsyncIterable<ChatEvent>

Async iterable of ChatEvents

Promise<string>

Complete text assembled from message:delta payloads

const fullText = await collectText(stream);

eventFilter(…types): (event) => boolean

Defined in: chat/events.ts:323

Create a filter function that passes only events of specified types.

…("heartbeat" | "error" | "done" | "usage" | "message:start" | "message:delta" | "message:complete" | "tool:start" | "tool:complete" | "thinking:start" | "thinking:delta" | "thinking:end" | "permission:request" | "permission:response" | "session:created" | "session:updated" | "typing:start" | "typing:end")[]

Event types to allow through

Predicate function for filtering ChatEvents

(event): boolean

ChatEvent

boolean

const isTextEvent = eventFilter("message:start", "message:delta", "message:complete");
const textEvents = allEvents.filter(isTextEvent);

filterEvents(source, …types): AsyncIterable<ChatEvent>

Defined in: chat/events.ts:344

Filter an async iterable of ChatEvents to only specified types.

AsyncIterable<ChatEvent>

Async iterable of ChatEvents

…("heartbeat" | "error" | "done" | "usage" | "message:start" | "message:delta" | "message:complete" | "tool:start" | "tool:complete" | "thinking:start" | "thinking:delta" | "thinking:end" | "permission:request" | "permission:response" | "session:created" | "session:updated" | "typing:start" | "typing:end")[]

Event types to keep

AsyncIterable<ChatEvent>

Async iterable of filtered ChatEvents

for await (const event of filterEvents(stream, "message:delta", "message:complete")) {
// only message:delta and message:complete events
}

mapEvents<R>(source, transform): AsyncIterable<R>

Defined in: chat/events.ts:373

Map/transform events from an async iterable.

R

AsyncIterable<ChatEvent>

Async iterable of ChatEvents

(event) => R | null

Function to transform each event (return null to skip)

AsyncIterable<R>

Async iterable of transformed values

// Extract text from message:delta events
const texts = mapEvents(stream, (event) =>
event.type === "message:delta" ? event.text : null
);