JavaScript/TypeScript SDK for the Polyphon JSON-RPC API.
Connect to a running Polyphon instance, manage compositions and sessions, send messages to voices, and stream responses — all from Node.js or any bundler-based project.
This repository is auto-synced from polyphon-ai/polyphon. All source files in
src/are generated — do not open pull requests here. To contribute to the SDK, submit PRs topolyphon-ai/polyphontargeting the files undersrc/sdk/andsrc/shared/.
- Node.js ≥ 18
- A running Polyphon instance (the SDK connects to it over TCP)
npm install @polyphon-ai/jsThe SDK version always matches the Polyphon app version. Install the version that matches your Polyphon install (e.g. Polyphon 0.12.0 → @polyphon-ai/js@0.12.0).
import { PolyphonClient, readLocalToken } from '@polyphon-ai/js';
const client = new PolyphonClient({
host: '127.0.0.1', // default
port: 7432, // default
token: readLocalToken(), // reads from ~/Library/Application Support/Polyphon/api.key
});
await client.connect();
// List compositions
const compositions = await client.compositions();
const comp = compositions[0];
// Create a session
const session = await client.createSession(comp.id, 'my-app');
// Broadcast a message to all voices, streaming the response
const result = await client.broadcast(
{ sessionId: session.id, content: 'What is the capital of France?' },
(chunk) => process.stdout.write(chunk.delta),
);
console.log('\nFinal messages:', result.messages);
client.disconnect();Polyphon authenticates via a token stored in ~/Library/Application Support/Polyphon/api.key (macOS). The SDK provides helpers to read it:
import { readLocalToken, defaultTokenPath } from '@polyphon-ai/js';
// Read the token from the default location
const token = readLocalToken();
// Or get the path and read it yourself
const path = defaultTokenPath(); // respects POLYPHON_DATA_DIR env var| Option | Type | Default | Description |
|---|---|---|---|
token |
string |
required | API token |
host |
string |
'127.0.0.1' |
Polyphon host |
port |
number |
7432 |
Polyphon TCP port |
await client.connect() // connects and authenticates; throws RpcError on auth failure
client.disconnect() // closes the socket
client.getState() // 'idle' | 'connecting' | 'connected' | 'disconnected'
// EventEmitter events
client.on('disconnect', () => { /* reconnect or clean up */ })
client.on('error', (err: Error) => { /* socket error */ })client.compositions() // → Composition[]
client.getComposition({ id }) // → Composition
client.createComposition(params) // → Composition
client.updateComposition(params) // → Composition
client.deleteComposition({ id }) // → void
client.archiveComposition({ id, archived }) // → Compositionclient.sessions() // → Session[]
client.getSession({ id }) // → Session
client.createSession(compositionId, source, extra?) // → Session
client.deleteSession({ id }) // → void
client.renameSession({ id, name }) // → Session
client.archiveSession({ id, archived }) // → Session
client.getMessages({ sessionId }) // → Message[]
client.exportSession({ sessionId, format }) // → { content, format }// Broadcast to all voices in the session
client.broadcast({ sessionId, content }, onChunk?) // → { messages }
// Ask a single voice
client.ask({ sessionId, voiceId, content }, onChunk?) // → { message }
// Abort an in-progress response
client.abort({ sessionId }) // → { aborted }The optional onChunk callback receives streaming deltas as they arrive:
client.broadcast(
{ sessionId: session.id, content: 'Hello' },
({ voiceId, voiceName, delta }) => {
process.stdout.write(delta);
},
);client.searchMessages({ query }) // → SearchMessagesResult[]client.getUserProfile() // → { conductorName, pronouns, conductorColor, conductorAvatar }
client.getApiStatus() // → ApiGetStatusResult
client.getDebugInfo() // → SettingsGetDebugInfoResult
client.getProviderStatus() // → SettingsGetProviderStatusResult[]
client.getMcpStatus() // → McpGetStatusResult
client.setMcpEnabled(params) // → McpGetStatusResultAll API errors are thrown as RpcError:
import { RpcError } from '@polyphon-ai/js';
try {
await client.connect();
} catch (err) {
if (err instanceof RpcError) {
console.error(`RPC error ${err.code}: ${err.message}`);
}
}Common error codes are available as RPC_ERROR constants in @polyphon-ai/js/api:
import { RPC_ERROR } from '@polyphon-ai/js/api';
// RPC_ERROR.UNAUTHORIZED, RPC_ERROR.NOT_FOUND, RPC_ERROR.PARSE_ERROR, …Import MockPolyphonServer from @polyphon-ai/js/testing to test your integration without a running Polyphon instance. It speaks the full JSON-RPC wire protocol and streams responses word-by-word.
import { MockPolyphonServer } from '@polyphon-ai/js/testing';
import { PolyphonClient } from '@polyphon-ai/js';
const server = new MockPolyphonServer({ token: 'test-token', streamingDelayMs: 0 });
await server.start();
const client = new PolyphonClient({ port: server.port, token: 'test-token' });
await client.connect();
const sessions = await client.sessions();
const result = await client.broadcast({ sessionId: sessions[0].id, content: 'Hi' });
// result.messages contains voice responses from DEFAULT_COMPOSITION voices
await server.stop();| Option | Type | Default | Description |
|---|---|---|---|
token |
string |
'test-token' |
Required token for authentication |
streamingDelayMs |
number |
20 |
Delay between streamed words (ms) |
responseTemplate |
(voiceName, content) => string |
"<name>: <first 50 chars>" |
Generates voice response text |
server.calls('voice.broadcast') // → array of params from every call to that method
server.clearCalls() // reset call log between testsserver.simulateError('compositions.list', -32000, 'something went wrong');
// Next call to compositions.list will reject with that error (single-use)The server starts with DEFAULT_COMPOSITION (two voices: Claude and GPT-4o) and DEFAULT_SESSION. Import fixtures directly if you need them in assertions:
import { DEFAULT_COMPOSITION, DEFAULT_SESSION, DEFAULT_MESSAGES } from '@polyphon-ai/js/testing';All domain types and API shapes are exported from the main package:
import type {
Composition, CompositionVoice, Session, Message,
PolyphonClientOptions, ClientState,
VoiceBroadcastParams, VoiceBroadcastResult,
StreamChunkNotification,
// … and more
} from '@polyphon-ai/js';The SDK version always matches the Polyphon app version. This makes API compatibility unambiguous: install the version that matches your Polyphon install.
npm install @polyphon-ai/js@0.12.0 # for Polyphon 0.12.0