- Developers
- Dialer SDK
- Quickstart
Dialer SDK quickstart
Install the packages, run the dialer against the mock transport, render snapshots, then start a power or parallel run. No account is needed and no calls are placed.
Version 0.1.0 · Integration preview
Install the packages
npm install @trellusrelease/dialer-sdk @twilio/voice-sdk
@twilio/voice-sdk is the browser audio dependency for live calling. The SDK declares it as an optional peer dependency, version >=2.18.0 <3. The mock transport in this guide does not contact Trellus or Twilio.
The optional interface is a separate package:
npm install @trellusrelease/dialer-ui
Both packages are ES modules and ship TypeScript declarations.
Start with the mock transport
Create a mock transport, pass it to createDialer, load two tasks and start a power run. Then simulate one conversation.
import { createDialer } from '@trellusrelease/dialer-sdk';
import { createMockTransport } from '@trellusrelease/dialer-sdk/testing';
const transport = createMockTransport();
const dialer = createDialer({ transport });
const render = snapshot => {
console.log(snapshot.status, snapshot.calls);
};
const unsubscribe = dialer.subscribe(render, { emitCurrent: true });
await dialer.connect();
dialer.setTasks([
{ id: 'task-1', name: 'Alex Example', phoneNumber: '+12025550123' },
{ id: 'task-2', name: 'Sam Example', phoneNumber: '+12025550124' },
]);
await dialer.start({ mode: 'power' });
// Explicitly simulate one conversation; the mock makes no telephone calls.
const { attemptId } = transport.getRequests()[0];
transport.emit(attemptId, { type: 'connected' });
transport.emit(attemptId, { type: 'ended' });
await dialer.completeWrapUp(attemptId, { disposition: 'Connected', notes: 'Example' });
// On final teardown:
// unsubscribe();
// await dialer.destroy();
start() resolves after the current scheduling pass. It does not wait for the whole list to finish. Subscribe to snapshots to follow the run.
The mock transport adds two methods for tests and interface work:
getRequests()returns the calls the dialer has asked the transport to place.emit(attemptId, event)simulates an event on one of those calls, such asconnectedorended.
function createMockTransport(options?: { maxLines?: number; autoEndMs?: number | null }): DialerTransport<{ id: string }> & {
emit(attemptId: string, event: TransportEvent): void;
getRequests(): { attemptId: string; task: DialTask; mode: DialMode; lines: number }[];
};
Render snapshots
Render dialer.getSnapshot() once, then apply each later snapshot from dialer.subscribe(listener). Pass emitCurrent: true to receive the current state right away.
const render = snapshot => {
console.log(snapshot.status, snapshot.calls);
};
const unsubscribe = dialer.subscribe(render, { emitCurrent: true });
render is your own function. Each snapshot is detached, so editing it cannot change the dialer. The fields you will use most:
status: the dialer state, such asready,running,pausedorwrap_up.tasks: the queue, each task with its own status.calls: the calls, each with its status, mute state and transcript.pendingWrapUp: the attempt IDs that are waiting for wrap-up.maxLinesandlines: the effective line limit and the width of the current run.
Call SDK methods from user actions. Do not advance the queue from a second timer in your application. The full shape is in the API reference.
Start a power run
Power and parallel runs use the same task shape. Load the tasks, then start the run.
dialer.setTasks(tasks);
await dialer.start({ mode: 'power' });
// Or, for an authorized parallel window:
// await dialer.start({ mode: 'parallel', lines: 3 });
Power mode places one queued call at a time. When a conversation ends, the attempt ID appears in pendingWrapUp. The dialer waits for completeWrapUp, then continues down the list. A call that ends without a conversation frees its slot automatically.
Start a parallel run
Parallel mode needs at least two lines and cannot exceed the effective line limit. The headless default is one line, so set maxLines on both the dialer and the transport.
const transport = createMockTransport({ maxLines: 3 });
const dialer = createDialer({ transport, maxLines: 3 });
await dialer.connect();
dialer.setTasks(tasks);
await dialer.start({ mode: 'parallel', lines: 3 });
The first call that connects to the rep wins the window. The dialer stops filling slots and ends the other calls. Their tasks become skipped with the reason parallel_loser. They are not redialed automatically within the same queue.
Next steps
- API reference: every method, the task shape, the snapshot and error codes.
- Events and sessions: typed events, session lookups and transcript finality.
- Call lifecycle: wrap-up, pause, teardown and uncertain outcomes.
- Optional interface: mount ready-made calling controls.
- Live calling: what you need before the SDK places a real call.