Skip to content
Skip to page content

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.

View as Markdown

Version 0.1.0 · Integration preview

Install the packages

Install the SDK and the browser audio dependency
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:

Install the optional interface
npm install @trellusrelease/dialer-ui

Both packages are ES modules and ship TypeScript declarations.

No account needed for this page. The examples below run against the mock transport. They place no calls. Live calling needs a Trellus account and enablement by Trellus. See Live calling.

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.

A power run against the mock transport
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 as connected or ended.
createMockTransport
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.

Subscribe to snapshots
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 as ready, running, paused or wrap_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.
  • maxLines and lines: 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.

Start a 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.

A parallel run against the mock 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.

A line setting is not an entitlement. For live calling, the supplied Trellus transport accepts 1 to 4 lines. Setting a number in code does not grant it.

Next steps