Skip to content

Events

AutopilotClient is a typed event emitter. All events live on the AutopilotClientEvents interface.

The on / once / off API

ts
const unsubscribe = client.on('status', (status) => {
  console.log(status);
});

client.once('completionFinished', () => {
  console.log('first turn done');
});

unsubscribe();           // or:
client.off('status', myHandler);

on and once return an unsubscribe function — usually the most ergonomic way to clean up.

Full event catalog

Status

EventPayloadWhen it fires
status'disconnected' | 'connecting' | 'connected'Connection state changes.

Functions

EventPayload
functionRegisteredAutopilotFunctionDescriptor
functionUnregistered{ name }
functionCall{ request } — autopilot is about to invoke a function
functionSuccess{ request, result, durationMs } — the handler settled (the wire response may still be withheld); durationMs is the handler duration
functionError{ request, error, durationMs }durationMs is the time from request to the error decision
functionResponseSent{ id, name?, status, durationMs } — the response actually hit the wire, after any withholding (context resolutions, state-sync gate) cleared; durationMs is the total request→wire duration
functionConfirmationRequired{ request } — sensitive call awaiting the confirmation handler
functionConfirmationResolved{ request, decision }'allow' or 'deny' returned by the handler

Ask user

EventPayload
askUserRequired{ prompts } — the server is waiting on these structured questions (see Ask user)
askUserCleared{} — no prompts remain (all answered, or none were pending)

State sync

EventPayload
stateSynced{ functions, context? } — full snapshot from the server
stateChanged{ functions?, context? } — an authoritative state change from another client in the conversation
stateError{ error } — a state sync (context or functions) was rejected: 64 KB size cap exceeded, 10-level path depth exceeded, or a server-side rejection. See Context: size and depth limits.

Context

EventPayload
contextUpdated{ context, patches } — patches were just sent
contextSyncScheduled{ hasChanges } — debounce timer (re)started
contextResolutionChanged{ pending } — a context resolution was acquired or released; function responses are withheld while pending > 0

Interrupts & join

EventPayload
interruptAck{} — the server acknowledged a streaming interrupt
interruptError{ error } — the interrupt request failed
joinError{ error } — failed to join the conversation channel

Errors

EventPayload
error{ context, error }
connectionError{ error }error is an AutopilotConnectionError (with kind / hint / url / status) when a connect attempt fails, or null when the failure is cleared (a fresh connect started, or a connection succeeded). Mirrored synchronously by getConnectionError(). See Handling connection errors.

Conversation

EventPayload
conversationLoaded{ conversation, messages }
messageAdded{ message, index }
messageUpdated{ message, index }
messageDeleted{ index } — defined in the event interface; reserved for future use (not currently emitted)
conversationCleared{}

Streaming

EventPayload
completionStarted{ input_async? }
completionStream{ chunk }
functionCallBegin{ id, name, arguments }
functionCallEnd{ id, result }
functionCallsCompleted{ function_calls, timestamp? }
functionCallIteration{}
completionEnded{}
completionFinished{ input_async? }
userInput{ content }

TypeScript hint

Each event's payload type is inferred from AutopilotClientEvents:

ts
client.on('messageAdded', ({ message, index }) => {
  // message: ConversationMessage, index: number — typed for you
});

If you store handlers in a variable, type them explicitly:

ts
import type { ConversationMessage } from '@llmor/autopilot-core';

const onAdd = ({ message }: { message: ConversationMessage; index: number }) => {
  /* … */
};
client.on('messageAdded', onAdd);