---
sidebar_position: 5
title: Changelog
description: Release history and version notes for the Firetell JavaScript / TypeScript Client SDK (@firetell/firetell-client-sdk).
---

# Changelog

All notable changes to the [`@firetell/firetell-client-sdk`](https://www.npmjs.com/package/@firetell/firetell-client-sdk) package are documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

---

## [1.2.4] - 2026-09-09

### Added

- **Camera Mute/Unmute (Toggle Camera)**:
  - Added `call.muteVideo()`, `call.unmuteVideo()`, and `call.toggleCamera()` methods on `Call`.
  - Added `call.isCameraOff: boolean` property tracking local camera state.
  - Added `ECallEventName.CAMERA` (`"camera"`) event emitted locally and on remote camera state updates via signaling.
- **Native Screen Sharing (`getDisplayMedia` + `replaceTrack`)**:
  - Added `call.startScreenShare()`, `call.stopScreenShare()`, and `call.toggleScreenShare()` on `Call`.
  - Seamlessly replaces video track on the active `RTCRtpSender` without SDP renegotiation or call interruption.
  - Automatically restores the original camera video track when the user stops sharing screen.
  - Added `call.isScreenSharing: boolean` property tracking active screen share state.
  - Added `ECallEventName.SCREEN_SHARE` (`"screenShare"`) event emitted locally and on remote screen share updates.
- **SDP Video Auto-Detection in `call.offer` & `accept()`**:
  - `Call.handleWsMessage`: Automatically falls back to inspecting the remote SDP offer for active video media sections (`/m=video [1-9]/`) if the explicit `is_video` boolean flag is omitted in the `call.offer` payload, ensuring `call.isVideo` is reliably set on the callee side.
  - `Call.accept()`: Evaluates `this.remoteDescription.sdp` to guarantee `this.isVideo` is true before setting up local media, prompting the browser for both Camera and Microphone permissions (`{ video: true, audio: true }`).
- **Resilient Remote Stream Track Assembly**:
  - Improved `RTCPeerConnection.ontrack` in `_setupWebrtcMedia`: Automatically creates a `MediaStream` and attaches tracks incrementally if `event.streams[0]` is missing, ensuring both remote audio and video tracks are emitted via `ECallEventName.REMOTE_STREAM`.
- **Caller Metadata Continuity**:
  - Added support for `from_avatar` and `transfer_reason` fields in `call.offer` event processing so callee avatar and transfer context remain intact through WebRTC session negotiation.

### Fixed

- **Callee Video Negotiation**:
  - Fixed an issue where incoming video calls defaulted to audio-only on the callee side due to missing `is_video` flag in signaling WebSocket payloads.
- **Example Demo Web App**:
  - Fixed `hideIncomingBanner` reference error on call dismissal.
  - Added dynamic `updateVideoUI()` helper to automatically bind and display local/remote video elements when tracks arrive.

---

## [1.2.3] - 2026-09-04

### Changed

- **`call.transfer()` simplified** (**Breaking**):
  - Signature changed from `transfer(targetUsername, teamId?, reason?)` to `transfer(target, reason?)`.
  - `target` now accepts: agent username, extension number (e.g. `"100"`), team ID (`te_...`), or SIP account ID (`si_...`).
  - Removed `teamId` parameter — target type is auto-resolved server-side via prefix-based resolution.
- **`FiretellClient.sendTransfer()` simplified** (**Breaking**):
  - Signature changed from `sendTransfer(callId, targetUsername, teamId?, reason?)` to `sendTransfer(callId, target, reason?)`.
  - HTTP fallback body changed from `{ target_username, team_id, reason }` to `{ target, reason }`.
- **Per-call WebSocket payloads cleaned up**:
  - Removed redundant `call_id` from all WS event payloads (`call.hangup`, `call.answer`, `call.reject`, `call.transfer`, `call.dtmf`, `call.mute`, `call.hold`, `call.unhold`). The per-call WS connection inherently binds the socket to a specific call, making `call_id` unnecessary.
  - `call.transfer` payload field renamed from `to` to `target` for consistency with the HTTP API.

---

## [1.2.2] - 2026-09-03

### Added

- **`getPhoneNumbers()` REST API on `FiretellClient`**:
  - Added `public async getPhoneNumbers(options?: { page?: number; limit?: number }): Promise<IClientPhoneNumbersResponse>` to query phone numbers (DIDs) accessible by the authenticated agent and their shared teams.
  - Automatically sends the agent's JWT to `GET /api/v1/call-center/phone-numbers`.
  - Added `API_ENDPOINTS.PHONE_NUMBERS` (`"/api/v1/call-center/phone-numbers"`).
  - Added `IClientPhoneNumber` and `IClientPhoneNumbersResponse` interfaces exporting phone number details (`id`, `number`, `title`, `country_code`, `dial_code`, `status`, `capabilities`, `enable_outbound`, `shared_teams_id`).
- **Static & Named SDK Version Exports**:
  - Added static `FiretellClient.VERSION` property on the class for direct, synchronous version access without instantiation.
  - Exported `SDK_VERSION` constant directly from package root (`import { SDK_VERSION } from '@firetell/firetell-client-sdk'`).
  - Added `"./package.json": "./package.json"` to the package `exports` map for direct version inspection by package managers and bundlers.

---

## [1.2.1] - 2026-08-22

### Added

- **`transfer_reason` in `call.ring` Event & `Call` Instance**:
  - Added `transfer_reason?: string` to `ICallRingParams` payload in the `call.ring` SSE event.
  - Exposed `call.transferReason?: string` on the `Call` instance when a transferred call session is initialized.
  - Allows frontends, Webphones, and Console agents to display the contextual transfer reason provided by Voice AI agents or human agents during ringing.

---

## [1.2.0] - 2026-08-20

### Added

- **Dedicated Per-Call SSE Event Stream (`Call.connectCallEventStream`)**:
  - Automatically establishes a dedicated SSE connection (`/stream?call_id=<callId>`) for each active call session (`call.start()`, `call.accept()`, `call.joinSession()`, and `client.createCallSession()`).
  - Subscribes to the Per-Call channel for real-time speech-to-text transcriptions and recording events without flooding the global workspace event stream.
  - Automatically disconnects and cleans up the stream upon call termination (`call.destroy()`).
- **Call-Scoped Real-Time Transcription Events & APIs**:
  - Added `ECallEventName.TRANSCRIPTION`, `TRANSCRIPTION_STARTED`, `TRANSCRIPTION_DIALOGUE`, and `TRANSCRIPTION_COMPLETED`.
  - Added ergonomic helper listener methods on `Call`: `call.onDialogue((dialogue) => ...)` and `call.onTranscription((event) => ...)`.
  - Exported TypeScript interfaces: `ITranscriptionStartedEvent`, `ITranscriptionDialogueEvent`, `ITranscriptionCompletedEvent`, and `TranscriptionEvent`.
- **Call-Scoped Real-Time Recording Events & APIs**:
  - Added `ECallEventName.RECORDING`, `RECORDING_STARTED`, `RECORDING_COMPLETED`, and `RECORDING_READY`.
  - Added ergonomic helper listener method on `Call`: `call.onRecording((event) => ...)`.
  - Exported TypeScript interfaces: `ICallRecordingStartedEvent`, `ICallRecordingCompletedEvent`, `ICallRecordingReadyEvent`, and `CallRecordingEvent`.
- **Public Getters on `FiretellClient`**:
  - Added `client.getBaseUrl()` and `client.getJwt()` getters.

### Changed & Improved

- **Strict Single-Emission & Call-Scoped Event Architecture**:
  - Removed duplicate event emissions across `FiretellClient._initEventStream()` and `Call._handleSseMessage()`.
  - Decoupled per-call transcription events from `client.events`, strictly routing all live subtitles, chunks, and summaries directly to the owning `Call` instance (`call.on(...)`).

---

## [1.1.7] - 2026-08-17

### Added

- **`FiretellClient.stopSupervision()`**: Added helper method to terminate an ongoing call supervision session (cleans up WebRTC call session and calls REST API `DELETE /v1/call-center/calls/:id/supervision`).
- **Call State Monotonicity Guard**: Added automatic state ranking guard in `FiretellClient` to prevent late/out-of-order `call.created` events from overriding or regressing active call state machine.

---

## [1.1.6] - 2026-08-17

### Added

- **`SseStreamClient` (Header-Based SSE Streaming)**: Integrated lightweight, zero-dependency SSE stream client with `Authorization: Bearer <jwt>` HTTP header support via `fetch` and `ReadableStream`, completely eliminating JWT token exposure in SSE stream URLs and server access logs.
- **SSE Stream Exports**: Exported `SseStreamClient`, `SseMessageEvent`, and `SseStreamConfig` from SDK entry point.

---

## [1.1.5] - 2026-08-17

### Added

- **`FiretellClient.startSupervision()`**: Added high-level helper method to initiate call supervision (`listen`, `whisper`, `barge`) and automatically establish WebRTC audio session in one call.
- **`Call.joinSession()`**: Added method to connect signaling and send WebRTC offer using pre-generated `call_token` and `ws_url`.
- **`ISupervisionResponse.ws_url`**: Added required `ws_url` field to `ISupervisionResponse` interface to support dedicated per-call WebSocket connections.

---

## [1.1.4] - 2026-08-15

### Fixed

- **Call Creation**: Renamed `_createCallSession` to `createCallSession`.

---

## [1.1.3] - 2026-08-14

### Added

- **Real-Time Call Lifecycle Event Enums**: Added `EClientEventName.CALL_CREATED`, `EClientEventName.CALL_STARTED`, and `EClientEventName.CALL_ANSWERED`.
- **Active Call State Synchronization**: Added automatic transition of active calls to `ECallState.ACTIVE` / `ANSWERED` when receiving `call.answered` over the SSE stream.

---

## [1.1.2] - 2026-08-14

### Added

- **Client Event Enum Values (`CALL_ENDED` & `CALL_CANCELED`)**: Added `EClientEventName.CALL_ENDED` and `EClientEventName.CALL_CANCELED`.
- **SSE Stream Listeners for Early Call Cancellation**: Automatically cleans up `Call` instances and dismisses incoming call ringing UI modals when calls are answered by another agent or canceled before WebSocket connection completion.

---

## [1.1.1] - 2026-08-12

### Fixed

- **Inbound Call DTLS Setup Role Validation**: Fixed `Answerer must use either active or passive value for setup attribute` error during callee-initiated unhold (`Call.unhold()`).
- **Optimized Full ICE Gathering**: Reduced hard safety timeout to 6s, and implemented a 3s fallback timer verifying presence of STUN Public IP (`typ srflx`) or Relay (`typ relay`) candidates.

---

## [1.1.0] - 2026-08-12

### Fixed

- **DTLS SSL Role Preservation on Renegotiation**: Preserves established DTLS `a=setup` role (`active` / `passive`) in `setRemoteDescription()` across renegotiation answers from Media Server.
- **Incoming Call Accept Error Safety**: Added `try...catch` block around `Call.accept()` to guarantee proper media cleanup and `ECallState.ERROR` state emission if microphone access or WebRTC answer creation fails.

---

## [1.0.9] - 2026-08-12

### Fixed

- **Call Unhold Event Signaling**: Fixed WS event name emitted during `Call.unhold()` from `"call.hold"` to `"call.unhold"`.
- **WebRTC Remote SDP Parsing**: Added `extractSdpInit()` helper in `Call.ts` to safely parse SDP payloads received in WebSocket messages.
- **ICE Server Fallback**: Configured `DEFAULT_ICE_SERVERS` (Google STUN + Cloudflare STUN) as default fallback.

---

## [1.0.0] - 2026-01-01

### Added

- Initial release of `@firetell/firetell-client-sdk`.
- WebRTC audio/video calls via native per-call WebSocket signaling.
- JWT-based session authentication (`session.connect`).
- Outbound call support (`Call.start()`) and incoming call handling (`Call.accept()`, `Call.reject()`).
- Call controls: hold/unhold, mute/unmute, DTMF, transfer.
- Auto-reconnect with exponential backoff.
- Agent presence notifications (`workspace.agent.state`).
- Full ICE gathering (non-Trickle) for Media Server compatibility.
- Multi-format builds: CJS, ESM, IIFE with TypeScript declarations.
