Events
Subscribe with client.on(name, handler); it returns an unsubscribe function. client.off(name, handler) also works. Every payload is typed (VoiceAgentEvents).
const off = client.on("transcript", (e) => { /* … */ });
off(); // unsubscribeReference
| Event | Payload | Notes |
|---|---|---|
appearance | AppearanceConfig | Emitted after init() resolves appearance. |
state | { orb: OrbState; statusLabel: string | null } | orb ∈ idle / connecting / listening / thinking / speaking. statusLabel is the contextual line shown while thinking. |
call:status | { status: string } | Free-form status text (Connecting…, Connected, Muted, errors). |
call:timer | { remainingMs: number | null } | null hides the timer. |
connection | { phase: ConnectionPhase; error?: string } | connecting → connected → disconnected / failed. Map to which screen to show. |
controls | { canStart; canMute; canEnd } | Which call controls to enable. |
transcript | { role: "user"|"agent"; segmentId; text; isFinal } | Coalesce by role:segmentId; interim updates arrive before the final. |
transcript:clear | {} | New call started. |
transcript:system | { text } | A system transcript line (e.g. a handoff transition message). |
mute | { muted: boolean } | Mute state changed. |
audio | AudioStateSnapshot | Prefs + actually-applied settings + noise-filter status. |
data | { data: unknown; topic?: string } | Raw JSON data messages from the agent. |
form:show | { definition; draft; stepIndex; inCall; transcriptionEnabled } | Render this form. |
form:update | { values; stepIndex } | Values merged (agent draft) or step changed — re-render. |
form:validation | { errors: FieldValidationError[] } | Show inline field errors. |
form:submitting | {} | Submit POST in flight. |
form:submitted | { formId; values; successMessage } | Success. |
form:error | { message } | Submit failed. |
form:close | {} | Form dismissed. |
agent:handoff | { agentName } | Mid-call swap to another agent. |
error | { scope; error } | Non-fatal (session / connect / form / audio). |
Key types
OrbState = "idle" | "listening" | "speaking" | "connecting" | "thinking"ConnectionPhase = "connecting" | "connected" | "reconnecting" | "disconnected" | "failed"AppearanceConfig— name, theme, dimensions, layout, labels, languages, forms, …FormDefinition/FormFieldDef— see FormsAudioStateSnapshot—{ prefs: AudioPrefs; applied: {…}; noiseFilter: { engine; status } }FieldValidationError = { name; label; message }
All are exported from @oshara/voice-sdk.
Minimal subscription example
client.on("state", ({ orb, statusLabel }) => renderOrb(orb, statusLabel));
client.on("connection", ({ phase }) => toggleScreen(phase));
client.on("transcript", ({ role, segmentId, text, isFinal }) =>
upsert(`${role}:${segmentId}`, role, text, isFinal),
);
client.on("error", ({ scope, error }) => console.warn(scope, error));Last updated on