React bindings
This page preserves the previous SDK documentation and its existing URL. The generated API reference was produced from SDK 0.1.5, source commit 4db9fbe925bf07a4b95e936a5bb172d6ab5820bb. Handbook behavior and compatibility claims below are historical descriptions, not a newly verified support guarantee. For the reviewed version-specific reference, see the SDK 0.1.5 overview.
The /react sub-path exposes a provider plus a small set of hooks. They share one DelphiClient per tree, deduplicate sessions across components, and subscribe to state via useSyncExternalStore.
Imports
import {
DelphiClientProvider,
DelphiConfigInit,
useDelphiClientContext,
useDelphiClientState,
useDelphiSession,
useBrowserAction,
useSelectionTracking,
} from '@ki-kombinat/delphi-client-js-sdk/react';
Provider
Wrap your tree once. All hooks below resolve the client via context.
<DelphiClientProvider config={{apiDomain, apiKey}}>
<App />
</DelphiClientProvider>
If config is only known after auth, omit it on the provider and push it later deeper in the tree:
<DelphiClientProvider>
<AuthGate>
<DelphiConfigInit config={resolvedConfig} />
<App />
</AuthGate>
</DelphiClientProvider>
useDelphiSession
Find-or-create a session for an endpoint and subscribe to its state. Multiple components asking for the same endpointId + mode share one WebSocket.
function ReadAloudWidget({endpointId}: {endpointId: string}) {
const {connected, sendReadAloud, audioDone, audioRequestPending, audioPlaying} = useDelphiSession(
{
endpointId,
mode: 'audio_playback',
onAudioPlaybackStart: () => console.log('browser playback started'),
onAudioPlaybackEnd: () => console.log('browser playback finished'),
},
);
return (
<button
disabled={!connected || audioRequestPending || audioPlaying}
onClick={async () => {
sendReadAloud('Hello!');
await audioDone();
}}
>
{audioRequestPending ? 'Synthesizing…' : audioPlaying ? 'Playing…' : 'Speak'}
</button>
);
}
The hook returns the full SessionClient surface plus connected, serverReady, audioRequestPending, audioPlaying, and a stable client reference.
useDelphiSession({ endpointId, mode }) is mode-keyed under the hood (SDK 0.1.3+). You can mount two hooks against the same endpoint with different modes and they will not collide — for instance a voice_conversation speaker and a listen subscriber in the same component tree.
useBrowserAction
Compose a BrowserAction handler with sensible defaults plus app-specific custom handlers. Pass it into useDelphiSession via onAction.
function CallButton() {
const handleBrowserAction = useBrowserAction({
onNavigate: (path) => router.push(path),
customHandlers: {
fill_invoice_form: async (params) => ({
success: true,
data: await fillInvoice(params),
}),
},
});
const {sendReadAloud} = useDelphiSession({
endpointId: '24599c70-1e79-4e52-9819-e2d97acf45a5',
mode: 'voice_conversation',
onAction: handleBrowserAction,
});
return <button onClick={() => sendReadAloud('Hi!')}>Read aloud</button>;
}
See Browser actions for the full handler shape and the standard action names.
useSelectionTracking
Tracks window.getSelection() so the user can trigger read-aloud on the currently highlighted text.
const {sendReadAloud, connected} = useDelphiSession({
endpointId: '24599c70-1e79-4e52-9819-e2d97acf45a5',
mode: 'audio_playback',
});
const {selectedText, handleReadAloudSelected, showReadAloudFab} = useSelectionTracking({
sendReadAloud,
channelConnected: connected,
forceEnable: true, // disable the in-call gating
});
return (
<>
<article>…</article>
{showReadAloudFab && <button onClick={handleReadAloudSelected}>Read selected</button>}
</>
);
useDelphiClientState
Read the orchestrator's aggregated state directly (voice-call status, every open session, currently selected text):
const {state, client} = useDelphiClientState();
state.sessions;
// [{ endpointId, sessionId, mode, connected, lastActivityAt }]
state.voiceCall;
// { inCall, calling, registered, telproDomain, ... }
useDelphiClientContext() is the underlying primitive when you need the bare DelphiClient instance.
Cleanup
The provider cleans up the client on unmount. Individual useDelphiSession callers do not end sessions when they unmount — the session map is owned by the client so navigating between components mid-call doesn't drop the call. Use client.endSession(endpointId, mode) (or endAllSessions()) when you explicitly want a session torn down.