From 7da2f1512b5905914bc1f2e1e3732d4cdeef2b8d Mon Sep 17 00:00:00 2001 From: Harry Smaje Date: Wed, 16 Jul 2025 13:59:55 +0100 Subject: [PATCH 1/3] feat: pass through the LLM ID (#121) (#137) --- README.md | 6 +++++- src/modules/CoreApiRestClient.ts | 15 +++++++++++++++ src/types/PersonaConfig.ts | 4 ++-- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 5906af1..b5f69fd 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,10 @@ First, install the SDK in your project npm install @anam-ai/js-sdk ``` +## Deprecation Notice + +**Important**: The `brainType` field in `PersonaConfig` is deprecated and will be removed in a future version. Please use `llmId` instead. If you are currently using `brainType`, you will see a deprecation warning in the console. Both fields are supported during the transition period. + ## Local development The quickest way to start testing the SDK is to use your API key directly with our SDK and the example persona config shown below. @@ -84,7 +88,7 @@ const response = await fetch(`https://api.anam.ai/v1/auth/session-token`, { name: 'Cara', avatarId: '30fa96d0-26c4-4e55-94a0-517025942e18', voiceId: '6bfbe25a-979d-40f3-a92b-5394170af54b', - brainType: 'ANAM_GPT_4O_MINI_V1', + llmId: '', systemPrompt: "[STYLE] Reply in natural speech without formatting. Add pauses using '...' and very occasionally a disfluency. [PERSONALITY] You are Cara, a helpful assistant.", }, diff --git a/src/modules/CoreApiRestClient.ts b/src/modules/CoreApiRestClient.ts index e50abaf..4cb9388 100644 --- a/src/modules/CoreApiRestClient.ts +++ b/src/modules/CoreApiRestClient.ts @@ -47,6 +47,13 @@ export class CoreApiRestClient { this.sessionToken = await this.unsafe_getSessionToken(personaConfig); } + // Check if brainType is being used and log deprecation warning + if (personaConfig && 'brainType' in personaConfig) { + console.warn( + 'Warning: brainType is deprecated and will be removed in a future version. Please use llmId instead.', + ); + } + try { const response = await fetch(`${this.getApiUrl()}/engine/session`, { method: 'POST', @@ -139,6 +146,14 @@ export class CoreApiRestClient { if (!this.apiKey) { throw new Error('No apiKey provided'); } + + // Check if brainType is being used and log deprecation warning + if (personaConfig && 'brainType' in personaConfig) { + console.warn( + 'Warning: brainType is deprecated and will be removed in a future version. Please use llmId instead.', + ); + } + let body: { clientLabel: string; personaConfig?: PersonaConfig } = { clientLabel: 'js-sdk-api-key', }; diff --git a/src/types/PersonaConfig.ts b/src/types/PersonaConfig.ts index c022863..ca49f23 100644 --- a/src/types/PersonaConfig.ts +++ b/src/types/PersonaConfig.ts @@ -5,7 +5,7 @@ export interface CustomPersonaConfig { name: string; avatarId: string; voiceId: string; - brainType: string; + llmId?: string; systemPrompt?: string; maxSessionLengthSeconds?: number; languageCode?: string; @@ -14,5 +14,5 @@ export interface CustomPersonaConfig { export function isCustomPersonaConfig( personaConfig: PersonaConfig, ): personaConfig is CustomPersonaConfig { - return 'brainType' in personaConfig; + return 'brainType' in personaConfig || 'llmId' in personaConfig; } From 59c9b24b8da9648ec561dc23d133ee86105e0b15 Mon Sep 17 00:00:00 2001 From: Harry Smaje Date: Tue, 29 Jul 2025 09:49:43 +0100 Subject: [PATCH 2/3] feat: add sendHumanMessage method to AnamClient - Add sendHumanMessage() method for sending human text messages - Method checks streaming status and active session - Formats message with timestamp, session_id, and message_type - Add JSDoc documentation for talk() and sendDataMessage() methods --- src/AnamClient.ts | 47 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 43 insertions(+), 4 deletions(-) diff --git a/src/AnamClient.ts b/src/AnamClient.ts index 50bc50c..1afb6e0 100644 --- a/src/AnamClient.ts +++ b/src/AnamClient.ts @@ -1,13 +1,14 @@ +import { Buffer } from 'buffer'; import { ClientError, ErrorCode } from './lib/ClientError'; -import { generateCorrelationId } from './lib/correlationId'; import { ClientMetricMeasurement, DEFAULT_ANAM_API_VERSION, DEFAULT_ANAM_METRICS_BASE_URL, - setClientMetricsBaseUrl, sendClientMetric, + setClientMetricsBaseUrl, setMetricsContext, } from './lib/ClientMetrics'; +import { generateCorrelationId } from './lib/correlationId'; import { CoreApiRestClient, InternalEventEmitter, @@ -18,15 +19,14 @@ import { import { AnamClientOptions, AnamEvent, + ConnectionClosedCode, EventCallbacks, InputAudioState, PersonaConfig, StartSessionOptions, StartSessionResponse, - ConnectionClosedCode, } from './types'; import { TalkMessageStream } from './types/TalkMessageStream'; -import { Buffer } from 'buffer'; export default class AnamClient { private publicEventEmitter: PublicEventEmitter; private internalEventEmitter: InternalEventEmitter; @@ -386,6 +386,11 @@ export default class AnamClient { this.streamingClient.startConnection(); } + /** + * Send a talk command to make the persona speak the provided content. + * @param content - The text content for the persona to speak + * @throws Error if session is not started or not currently streaming + */ public async talk(content: string): Promise { if (!this.streamingClient) { throw new Error( @@ -401,6 +406,11 @@ export default class AnamClient { return; } + /** + * Send a raw data message through the WebRTC data channel. + * @param message - The message string to send through the data channel + * @throws Error if session is not started + */ public sendDataMessage(message: string): void { if (this.streamingClient) { this.streamingClient.sendDataMessage(message); @@ -409,6 +419,35 @@ export default class AnamClient { } } + /** + * Send a human text message in the active streaming session. + * @param content - The text message content to send + * @throws Error if not currently streaming or session is not started + */ + public sendHumanMessage(content: string): void { + if (!this._isStreaming) { + console.warn( + 'AnamClient: Not currently streaming. Human message will not be sent.', + ); + throw new Error('Failed to send human message: not currently streaming'); + } + + const sessionId = this.getActiveSessionId(); + if (!sessionId) { + throw new Error('Failed to send human message: no active session'); + } + + const currentTimestamp = new Date().toISOString().replace('Z', ''); + const body = JSON.stringify({ + content, + timestamp: currentTimestamp, + session_id: sessionId, + message_type: 'speech', + }); + + this.sendDataMessage(body); + } + public async stopStreaming(): Promise { if (this.streamingClient) { this.publicEventEmitter.emit( From e679770ab3d733af2c01efd1d670ca444d7ec589 Mon Sep 17 00:00:00 2001 From: Harry Smaje Date: Tue, 29 Jul 2025 10:18:20 +0100 Subject: [PATCH 3/3] refactor: rename sendHumanMessage to sendUserMessage - Rename method from sendHumanMessage() to sendUserMessage() - Update JSDoc documentation to use 'user' instead of 'human' - Update error messages and console warnings accordingly --- src/AnamClient.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/AnamClient.ts b/src/AnamClient.ts index 1afb6e0..b41234d 100644 --- a/src/AnamClient.ts +++ b/src/AnamClient.ts @@ -420,21 +420,21 @@ export default class AnamClient { } /** - * Send a human text message in the active streaming session. + * Send a user text message in the active streaming session. * @param content - The text message content to send * @throws Error if not currently streaming or session is not started */ - public sendHumanMessage(content: string): void { + public sendUserMessage(content: string): void { if (!this._isStreaming) { console.warn( - 'AnamClient: Not currently streaming. Human message will not be sent.', + 'AnamClient: Not currently streaming. User message will not be sent.', ); - throw new Error('Failed to send human message: not currently streaming'); + throw new Error('Failed to send user message: not currently streaming'); } const sessionId = this.getActiveSessionId(); if (!sessionId) { - throw new Error('Failed to send human message: no active session'); + throw new Error('Failed to send user message: no active session'); } const currentTimestamp = new Date().toISOString().replace('Z', '');