GemmaPoddocs
ReferenceRuntime SDK

RuntimeEventBus

Typed pub/sub for runtime, transport, A2A, UI, and chat-history events.

Type

interface RuntimeEventBus {
  on<T extends RuntimeEvent["type"]>(
    type: T,
    handler: (event: Extract<RuntimeEvent, { type: T }>) => void,
  ): () => void;

  once<T extends RuntimeEvent["type"]>(
    type: T,
    handler: (event: Extract<RuntimeEvent, { type: T }>) => void,
  ): () => void;

  emit(event: RuntimeEvent): void;
}

All three methods are typed — pick a type string and the handler parameter narrows to the matching event payload.

Events emitted

typeWhen
runtime.readyAfter connect() succeeds and a transport is bridged.
runtime.destroyedAfter destroy().
runtime.errorAny runtime-level error (transport failure, UI-event ingestion crash).
transport.connectingConnection attempt started. transport is "auto" for the selector.
transport.readyA transport opened. Payload transport names which one.
transport.updatedInternal transport object mutated (fallback state flipped, etc.).
transport.fallbackSelector fell through. Payload: { from, to, reason }.
transport.dartcStage events from the WebRTC ladder (signaling open, hello, …).
a2a.cardAn A2A Agent Card was discovered (over a2a.discovery or via CUSTOM name="a2a.card").
ui.eventA verified DartcUiEvent. Payload: { event: DartcUiEvent }.
chat.historyChat history changed (after stream/send/clear/setHistory/MESSAGES_SNAPSHOT).
state.changedThe state store emitted a new snapshot.

Subscription pattern

const off = runtime.events.on("transport.ready", (event) => {
  console.log("transport:", event.transport);
});

// Later:
off();

on returns an unsubscribe function. once auto-unsubscribes after the first matching event.

Browser-event bridge

The FallbackTransport republishes every UI event as a browser CustomEvent on window:

window.addEventListener("gemmapod:ui-event", (e) => {
  console.log(e.detail); // DartcUiEvent
});

This is for compatibility with hosts that can't easily attach to the runtime's typed bus (legacy widgets, iframes, dev tooling). Subscribe to runtime.events in normal use.

Emit your own

emit is exposed for adapters and tests. Production code should never emit runtime.* or transport.* events — those come from the runtime itself. Custom events should ride ui.event with type: "CUSTOM" or add their own bus on top.

See also