Skip to main content

Protocol Types

Protocol types define the message schemas for Server-Sent Events (SSE) communication between the hub and clients.

Message Categories

The protocol is organized into these categories:
  • Room messages - Room lifecycle events (create, join, leave)
  • LLM messages - Request/response streaming for LLM completions
  • TUI messages - Terminal UI registration and state
  • Host messages - Host-specific events
  • List messages - Room listing requests/responses

Room Messages

RoomCreateMessage

Client request to create a new room.
const RoomCreateMessage = z.object({
  type: z.literal("room:create"),
  name: z.string(),
});
type
'room:create'
required
Message type discriminator
name
string
required
Display name for the new room

RoomCreatedMessage

Server response after successfully creating a room.
const RoomCreatedMessage = z.object({
  type: z.literal("room:created"),
  code: z.string(),
  roomId: z.string(),
});
type
'room:created'
required
Message type discriminator
code
string
required
Human-readable room code for joining
roomId
string
required
Unique room identifier

RoomJoinMessage

Client request to join an existing room.
const RoomJoinMessage = z.object({
  type: z.literal("room:join"),
  code: z.string(),
  participant: z.object({
    id: z.string(),
    nickname: z.string(),
    model: z.string(),
    endpoint: z.string().url(),
    specs: MachineSpecs,
    config: GenerationConfig,
  }),
});
type
'room:join'
required
Message type discriminator
code
string
required
Room code to join
participant
object
required
Participant information for registration

RoomJoinedMessage

Server response after successfully joining a room.
const RoomJoinedMessage = z.object({
  type: z.literal("room:joined"),
  roomId: z.string(),
  participants: z.array(ParticipantInfo),
});
type
'room:joined'
required
Message type discriminator
roomId
string
required
Room identifier
participants
ParticipantInfo[]
required
List of all participants currently in the room

RoomParticipantJoinedMessage

Broadcast when a new participant joins the room.
const RoomParticipantJoinedMessage = z.object({
  type: z.literal("room:participant-joined"),
  participant: ParticipantInfo,
});
type
'room:participant-joined'
required
Message type discriminator
participant
ParticipantInfo
required
Information about the participant who joined

RoomParticipantLeftMessage

Broadcast when a participant leaves the room.
const RoomParticipantLeftMessage = z.object({
  type: z.literal("room:participant-left"),
  participantId: z.string(),
});
type
'room:participant-left'
required
Message type discriminator
participantId
string
required
ID of the participant who left

RoomErrorMessage

Server error response for room operations.
const RoomErrorMessage = z.object({
  type: z.literal("room:error"),
  error: z.string(),
});
type
'room:error'
required
Message type discriminator
error
string
required
Error message description

LLM Messages

LlmRequestMessage

Client request to generate LLM completion.
const LlmRequestMessage = z.object({
  type: z.literal("llm:request"),
  requestId: z.string(),
  targetId: z.string(),
  prompt: z.string(),
  options: GenerationConfig.optional(),
});
type
'llm:request'
required
Message type discriminator
requestId
string
required
Unique identifier for tracking this request
targetId
string
required
Target participant ID or routing pattern (e.g., “model:llama3”, ”*”)
prompt
string
required
Input prompt for generation
options
GenerationConfig
Optional generation parameters to override participant defaults

LlmTokenMessage

Streaming token response during generation.
const LlmTokenMessage = z.object({
  type: z.literal("llm:token"),
  requestId: z.string(),
  participantId: z.string(),
  token: z.string(),
  seq: z.number(),
});
type
'llm:token'
required
Message type discriminator
requestId
string
required
Request identifier this token belongs to
participantId
string
required
ID of the participant generating the response
token
string
required
Generated text token
seq
number
required
Sequence number for ordering tokens

LlmCompleteMessage

Completion signal with metrics after generation finishes.
const LlmCompleteMessage = z.object({
  type: z.literal("llm:complete"),
  requestId: z.string(),
  participantId: z.string(),
  metrics: LlmMetrics,
});
type
'llm:complete'
required
Message type discriminator
requestId
string
required
Request identifier
participantId
string
required
ID of the participant who completed the generation
metrics
LlmMetrics
required
Performance metrics for the generation. See LlmMetrics.

LlmErrorMessage

Error response during LLM generation.
const LlmErrorMessage = z.object({
  type: z.literal("llm:error"),
  requestId: z.string(),
  participantId: z.string(),
  error: z.string(),
});
type
'llm:error'
required
Message type discriminator
requestId
string
required
Request identifier
participantId
string
required
ID of the participant that encountered the error
error
string
required
Error message description

TUI Messages

TuiRegisterMessage

Terminal UI client registration.
const TuiRegisterMessage = z.object({
  type: z.literal("tui:register"),
  roomCode: z.string().optional(),
});
type
'tui:register'
required
Message type discriminator
roomCode
string
Optional room code to focus on

TuiRegisteredMessage

Server response with initial TUI state.
const TuiRegisteredMessage = z.object({
  type: z.literal("tui:registered"),
  rooms: z.array(RoomInfoPublic),
  participants: z.array(ParticipantInfo),
});
type
'tui:registered'
required
Message type discriminator
rooms
RoomInfoPublic[]
required
List of all active rooms
participants
ParticipantInfo[]
required
List of all active participants

Host Messages

HostRegisterMessage

Host registration for receiving room-specific events.
const HostRegisterMessage = z.object({
  type: z.literal("host:register"),
  roomId: z.string(),
});
type
'host:register'
required
Message type discriminator
roomId
string
required
Room identifier to monitor

HostRegisteredMessage

Server response with room state for host.
const HostRegisteredMessage = z.object({
  type: z.literal("host:registered"),
  room: RoomInfoPublic,
  participants: z.array(ParticipantInfo),
});
type
'host:registered'
required
Message type discriminator
room
RoomInfoPublic
required
Room information
participants
ParticipantInfo[]
required
Current participants in the room

List Messages

ListRoomsMessage

Client request to list all rooms.
const ListRoomsMessage = z.object({
  type: z.literal("list:rooms"),
});
type
'list:rooms'
required
Message type discriminator

ListRoomsResponseMessage

Server response with room list.
const ListRoomsResponseMessage = z.object({
  type: z.literal("list:rooms-response"),
  rooms: z.array(
    RoomInfoPublic.extend({
      participantCount: z.number(),
    })
  ),
});
type
'list:rooms-response'
required
Message type discriminator
rooms
(RoomInfoPublic & { participantCount: number })[]
required
Array of rooms with participant counts

Supporting Types

LlmMetrics

Performance metrics for LLM generation.
const LlmMetrics = z.object({
  tokens: z.number(),
  latencyFirstTokenMs: z.number(),
  durationMs: z.number(),
  tokensPerSecond: z.number(),
});

type LlmMetrics = z.infer<typeof LlmMetrics>;
tokens
number
required
Total number of tokens generated
latencyFirstTokenMs
number
required
Time in milliseconds until the first token was generated
durationMs
number
required
Total generation duration in milliseconds
tokensPerSecond
number
required
Throughput rate (tokens/second)

Message Unions

ClientMessage

Discriminated union of all client-to-server messages.
const ClientMessage = z.discriminatedUnion("type", [
  RoomCreateMessage,
  RoomJoinMessage,
  LlmRequestMessage,
  TuiRegisterMessage,
  HostRegisterMessage,
  ListRoomsMessage,
]);

type ClientMessage = z.infer<typeof ClientMessage>;

ServerMessage

Discriminated union of all server-to-client messages.
const ServerMessage = z.discriminatedUnion("type", [
  RoomCreatedMessage,
  RoomJoinedMessage,
  RoomParticipantJoinedMessage,
  RoomParticipantLeftMessage,
  RoomErrorMessage,
  LlmTokenMessage,
  LlmCompleteMessage,
  LlmErrorMessage,
  TuiRegisteredMessage,
  HostRegisteredMessage,
  ListRoomsResponseMessage,
]);

type ServerMessage = z.infer<typeof ServerMessage>;

Usage Example

import { ServerMessage } from "@gambiarra/core";

// Connect to SSE endpoint
const eventSource = new EventSource("/rooms/swift-eagle-42/events");

eventSource.onmessage = (event) => {
  const message = JSON.parse(event.data);
  const parsed = ServerMessage.parse(message);

  switch (parsed.type) {
    case "room:participant-joined":
      console.log(`${parsed.participant.nickname} joined`);
      break;

    case "llm:token":
      process.stdout.write(parsed.token);
      break;

    case "llm:complete":
      console.log(`\nGenerated ${parsed.metrics.tokens} tokens in ${parsed.metrics.durationMs}ms`);
      break;

    case "llm:error":
      console.error(`Error: ${parsed.error}`);
      break;
  }
};

Build docs developers (and LLMs) love