Web SDKs

Angular

@primoia/vocall-angular -- Services, NgZone, RxJS

Angular SDK

The Angular SDK provides a root-level service with RxJS observables and synchronous getters for integrating Vocall into Angular 18+ applications.

Installation

npm install @primoia/vocall-angular

Peer dependencies: @angular/common ^18 || ^19, rxjs ^7.8


VocallService

VocallService is provided in root and can be injected into any component or service.

import { VocallService } from '@primoia/vocall-angular';

constructor(private vocall: VocallService) {}

Methods

| Method | Signature | Description | |---|---|---| | connect | connect(url: string, token: string, visitorId?: string): void | Opens a WebSocket connection to the Vocall engine. | | disconnect | disconnect(): void | Closes the active connection. | | sendText | sendText(text: string): void | Sends a text message to the engine. | | registerField | registerField(screenId: string, fieldId: string, entry: FieldEntry): void | Registers a DOM element as a bindable field. | | registerAction | registerAction(screenId: string, actionId: string, callback: () => void): void | Registers a callback for an action trigger. |

Observables

| Observable | Type | Description | |---|---|---| | status$ | Observable<VocallStatus> | Current engine status. | | connected$ | Observable<boolean> | Whether the WebSocket is connected. | | messages$ | Observable<Message[]> | Chat message history. | | sessionId$ | Observable<string \| null> | Active session identifier. | | rawMessage$ | Observable<any> | Raw WebSocket frames for advanced use. |

Synchronous Getters

For template guards or imperative code you can read the latest value directly.

| Getter | Type | |---|---| | status | VocallStatus | | connected | boolean | | messages | Message[] | | sessionId | string \| null |

Assign handlers on the service instance to react to engine-driven UI actions.

| Callback | Signature | |---|---| | onNavigate | (path: string) => void | | onToast | (message: string, type?: string) => void | | onConfirm | (message: string) => Promise<boolean> | | onOpenModal | (modalId: string) => void | | onCloseModal | (modalId: string) => void |


FieldEntry

The object passed to registerField describes how the engine reads and writes a form element.

interface FieldEntry {
  element: HTMLElement;
  setValue: (value: string) => void;
  getValue: () => string;
}

VocallStatus

enum VocallStatus {
  disconnected = 'disconnected',
  idle         = 'idle',
  listening    = 'listening',
  recording    = 'recording',
  thinking     = 'thinking',
  speaking     = 'speaking',
  executing    = 'executing',
}

Full Example

import { Component, ViewChild, ElementRef, OnInit, OnDestroy } from '@angular/core';
import { VocallService, VocallStatus } from '@primoia/vocall-angular';
import { Subscription } from 'rxjs';

@Component({
  selector: 'app-invoice',
  standalone: true,
  template: `
    <input #nameInput placeholder="Client name" />
    <p>Status: {{ vocall.status }}</p>
    <button (click)="vocall.sendText('Fill the client name')">Ask</button>
  `,
})
export class InvoiceComponent implements OnInit, OnDestroy {
  @ViewChild('nameInput', { static: true }) nameInput!: ElementRef<HTMLInputElement>;

  private sub = new Subscription();

  constructor(public vocall: VocallService) {}

  ngOnInit(): void {
    this.vocall.connect('wss://engine.example.com/connect', 'my-token');

    this.vocall.registerField('invoice', 'clientName', {
      element: this.nameInput.nativeElement,
      setValue: (v) => (this.nameInput.nativeElement.value = v),
      getValue: () => this.nameInput.nativeElement.value,
    });

    this.vocall.onNavigate = (path) => {
      // integrate with Angular Router
      console.log('Navigate to', path);
    };

    this.sub.add(
      this.vocall.status$.subscribe((s) => {
        if (s === VocallStatus.executing) {
          console.log('Engine is executing commands...');
        }
      })
    );
  }

  ngOnDestroy(): void {
    this.sub.unsubscribe();
    this.vocall.disconnect();
  }
}

Manifest Structure

The field and action identifiers used in registerField and registerAction must match entries defined in your application manifest. See the Manifest Reference for the full schema.