@minded-ai/mindedjs 1.0.53-patch5 → 1.0.53

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@minded-ai/mindedjs",
3
- "version": "1.0.53-patch5",
3
+ "version": "1.0.53",
4
4
  "description": "MindedJS is a TypeScript library for building agents.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -17,7 +17,6 @@
17
17
  "test": "NODE_ENV=test mocha --parallel --jobs auto --retries 1 -r ts-node/register -r ./test/setup.ts \"test/**/*.test.ts\"",
18
18
  "testFile": "NODE_ENV=test mocha -r ts-node/register -r ./test/setup.ts",
19
19
  "order-refund": "cd examples/orderRefundAgent && nodemon --watch '**/*.ts' --exec 'ts-node' orderRefundAgent.ts",
20
- "example-voice": "cd examples/voice && nodemon --watch '**/*.ts' --exec 'ts-node' voiceAgent.ts",
21
20
  "lint": "eslint .",
22
21
  "lintFix": "eslint --fix .",
23
22
  "generateApiDocs": "typedoc src --out docs/api-reference ./src"
@@ -30,7 +29,6 @@
30
29
  "@types/mocha": "^10.0.6",
31
30
  "@types/node": "^20.11.19",
32
31
  "@types/sinon": "^17.0.4",
33
- "@types/ws": "^8.18.1",
34
32
  "chai": "^4.3.10",
35
33
  "dotenv": "^16.4.5",
36
34
  "eslint": "^9.27.0",
@@ -53,7 +51,6 @@
53
51
  "langchain": "^0.3.25",
54
52
  "socket.io-client": "^4.8.1",
55
53
  "uuid": "^11.1.0",
56
- "ws": "^8.15.1",
57
54
  "zod": "^3.24.4"
58
55
  }
59
56
  }
package/src/agent.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Flow, NodeType, Node, EdgeType, KnownTriggerNames, TriggerType, VoiceTriggerNode } from './types/Flows.types';
1
+ import { Flow, NodeType, Node, EdgeType, KnownTriggerNames } from './types/Flows.types';
2
2
 
3
3
  import { Tool } from './types/Tools.types';
4
4
  import { v4 as uuidv4 } from 'uuid';
@@ -11,11 +11,11 @@ import { edgeFactory } from './edges/edgeFactory';
11
11
  import { AgentEventRequestPayloads, AgentEventResponsePayloads, AgentEvents } from './events/AgentEvents';
12
12
  import { z } from 'zod';
13
13
  import { MindedConnection } from './platform/mindedConnection';
14
- import { BaseMindedConnectionSocketMessage, InvokeMessage, MindedConnectionSocketMessageType, OnAppTrigger } from './platform/mindedConnectionTypes';
14
+ import { BaseMindedConnectionSocketMessage, MindedConnectionSocketMessageType, OnAppTrigger } from './platform/mindedConnectionTypes';
15
15
  import * as fs from 'fs';
16
16
  import * as path from 'path';
17
17
  import * as yaml from 'js-yaml';
18
- import { AgentInvokeParams, FlowHistoryType, MindedSDKConfig, TriggerInvocationHistory } from './types/Agent.types';
18
+ import { FlowHistoryType, MindedSDKConfig, TriggerInvocationHistory } from './types/Agent.types';
19
19
  import { createLlmInstance } from './llm/createLlmInstance';
20
20
  import { createCheckpointSaver } from './checkpointer/checkpointSaverFactory';
21
21
  import { getConfig } from './platform/config';
@@ -23,8 +23,6 @@ import { BaseMessage, HumanMessage } from '@langchain/core/messages';
23
23
  import triggerTypeToDefaultMessage from './triggers/triggerTypeToDefaultMessage';
24
24
  import appActionRunnerToolCreator from './internalTools/appActionRunnerTool';
25
25
  import { wait } from './utils/wait';
26
- import { VoiceSession } from './voice/voiceSession';
27
- import { BaseVoiceMessage, OnVoiceAudioOut } from './platform/mindedConnectionTypes';
28
26
 
29
27
  type CreateAgentParams<Memory> = {
30
28
  memorySchema: z.ZodSchema;
@@ -57,14 +55,13 @@ export class Agent {
57
55
  private flows!: Flow[];
58
56
  public tools!: Tool<any, any>[];
59
57
  private llm!: BaseLanguageModel;
60
- public mindedConnection: MindedConnection | null = null;
58
+ private mindedConnection: MindedConnection | null = null;
61
59
  // Langgraph memory saver. In memory for local development, Custom for Platform
62
60
  private checkpointer!: BaseCheckpointSaver;
63
61
  // Langgraph compiled graph
64
- public compiledGraph!: CompiledGraph;
62
+ private compiledGraph!: CompiledGraph;
65
63
  // Cache for secrets to avoid repeated API calls
66
64
  private secretsCache: Record<string, string> | null = null;
67
- public config: MindedSDKConfig;
68
65
 
69
66
  // Event handlers storage keyed by event name. Handlers can optionally return a value.
70
67
  private eventHandlers: {
@@ -76,9 +73,6 @@ export class Agent {
76
73
  private initialized = false;
77
74
  private initPromise: Promise<void> | null = null;
78
75
 
79
- // Add the voiceSessions property to the Agent class (place near other class fields)
80
- public voiceSessions: Map<string, VoiceSession> = new Map();
81
-
82
76
  /**
83
77
  * Create a new Agent instance.
84
78
  *
@@ -114,7 +108,6 @@ export class Agent {
114
108
  const { memorySchema } = params;
115
109
  this.memorySchema = memorySchema;
116
110
  this.initPromise = this.init(params);
117
- this.config = params.config;
118
111
  }
119
112
 
120
113
  private async init(params: CreateAgentParams<z.infer<typeof this.memorySchema>>): Promise<void> {
@@ -134,17 +127,6 @@ export class Agent {
134
127
  sessionId: trigger.sessionId,
135
128
  });
136
129
  });
137
-
138
- this.mindedConnection.on(MindedConnectionSocketMessageType.INVOKE, async (message, callback) => {
139
- const invokeMessage = message as InvokeMessage;
140
- const result = await this.invoke({
141
- triggerBody: invokeMessage.triggerBody,
142
- triggerName: invokeMessage.triggerName,
143
- appName: invokeMessage.appName,
144
- sessionId: invokeMessage.sessionId,
145
- });
146
- callback(result);
147
- });
148
130
  }
149
131
  const [, flows] = (await Promise.all([this.loadSecrets(), this.loadFlows(config.flows)])) as [Record<string, string>, Flow[]];
150
132
  this.flows = flows;
@@ -157,11 +139,6 @@ export class Agent {
157
139
  this.llm = createLlmInstance(config.llm);
158
140
  this.compiledGraph = this.initializeGraph();
159
141
  this.initialized = true;
160
-
161
- const flowHasVoiceTrigger = this.flows.some((flow) => flow.nodes.some((node) => node.type === NodeType.TRIGGER && node.triggerType === TriggerType.VOICE));
162
- if (flowHasVoiceTrigger) {
163
- this.setupVoice();
164
- }
165
142
  } catch (error) {
166
143
  this.initialized = false;
167
144
  throw error;
@@ -341,11 +318,16 @@ export class Agent {
341
318
  triggerName,
342
319
  sessionId,
343
320
  appName,
344
- }: AgentInvokeParams) {
321
+ }: {
322
+ triggerBody: any;
323
+ triggerName: string;
324
+ sessionId?: string;
325
+ appName?: string;
326
+ }) {
345
327
  await this.waitForInitialization();
346
328
  let messages: Array<BaseMessage> = [];
347
329
  let memoryUpdate = {};
348
- if (triggerName === KnownTriggerNames.DASHBOARD_MESSAGE || triggerName === KnownTriggerNames.VOICE_MESSAGE) {
330
+ if (triggerName === KnownTriggerNames.DASHBOARD_MESSAGE) {
349
331
  messages.push(new HumanMessage(triggerBody.content));
350
332
  } else {
351
333
  const results = await this.emit(AgentEvents.TRIGGER_EVENT, {
@@ -380,8 +362,8 @@ export class Agent {
380
362
  },
381
363
  ];
382
364
  console.log(`Invoking trigger ${triggerName} with session ${sessionId}`);
383
- const langraphConfig = this.getLangraphConfig(sessionId || uuidv4());
384
- const state = await this.compiledGraph.getState(langraphConfig);
365
+ const config = { configurable: { thread_id: sessionId || uuidv4(), recursionLimit: 3 } };
366
+ const state = await this.compiledGraph.getState(config);
385
367
  // Resume interruption
386
368
  if (state.tasks?.[0]?.interrupts?.length > 0) {
387
369
  console.log('Resuming interruption');
@@ -389,13 +371,13 @@ export class Agent {
389
371
  new Command({
390
372
  resume: { memory: memoryUpdate, messages, history, triggerInvocations: [triggerInvocation] },
391
373
  }),
392
- langraphConfig,
374
+ config,
393
375
  );
394
376
  return res;
395
377
  } else {
396
378
  const res = await this.compiledGraph.invoke(
397
379
  { messages, memory: memoryUpdate, history, triggerInvocations: [triggerInvocation] },
398
- langraphConfig,
380
+ config,
399
381
  );
400
382
  return res;
401
383
  }
@@ -615,63 +597,4 @@ export class Agent {
615
597
  throw new Error(`Failed to fetch secrets: ${error instanceof Error ? error.message : 'Unknown error'}`);
616
598
  }
617
599
  }
618
-
619
- public getLangraphConfig(sessionId: string): { configurable: { thread_id: string; recursionLimit: number } } {
620
- return { configurable: { thread_id: sessionId, recursionLimit: 3 } };
621
- }
622
-
623
- private setupVoice(): void {
624
- if (!this.mindedConnection) {
625
- throw new Error('Minded connection is required');
626
- }
627
-
628
- const connection = this.mindedConnection;
629
- const { dashboardConnected } = getConfig();
630
-
631
- if (dashboardConnected) {
632
- // Listen for voice session start
633
- connection.on(MindedConnectionSocketMessageType.DASHBOARD_VOICE_SESSION_START, async (message) => {
634
- const sessionStart = message as BaseVoiceMessage;
635
- await this.startVoiceSession({ sessionId: sessionStart.sessionId });
636
- });
637
-
638
- // Listen for incoming audio from the platform
639
- connection.on(MindedConnectionSocketMessageType.DASHBOARD_VOICE_USER_AUDIO, (message) => {
640
- const audioMessage = message as OnVoiceAudioOut;
641
- const voiceSession = this.voiceSessions.get(audioMessage.sessionId);
642
- if (voiceSession) {
643
- voiceSession.sendAudio(audioMessage.audioData);
644
- } else {
645
- console.warn({ message: 'Voice session not found for sessionId', sessionId: audioMessage.sessionId });
646
- }
647
- });
648
-
649
- // Hangup / end session handler
650
- connection.on(MindedConnectionSocketMessageType.DASHBOARD_VOICE_SESSION_END, (message) => {
651
- const hangup = message as BaseVoiceMessage;
652
- const voiceSession = this.voiceSessions.get(hangup.sessionId);
653
- if (voiceSession) {
654
- voiceSession.hangup();
655
- } else {
656
- console.warn({ message: 'Voice session not found for sessionId', sessionId: hangup.sessionId });
657
- }
658
- });
659
- }
660
-
661
- }
662
-
663
- private async startVoiceSession(params: { sessionId: string }): Promise<VoiceSession> {
664
- const voiceTrigger = this.flows.flatMap((flow) => flow.nodes).find((node) => node.type === NodeType.TRIGGER && node.triggerType === TriggerType.VOICE) as VoiceTriggerNode;
665
- if (!voiceTrigger) {
666
- throw new Error('Voice trigger not found in flows');
667
- }
668
- const voiceSession = new VoiceSession({
669
- agent: this,
670
- sessionId: params.sessionId,
671
- firstMessage: voiceTrigger.firstMessage,
672
- });
673
- await voiceSession.init();
674
- this.voiceSessions.set(params.sessionId, voiceSession);
675
- return voiceSession;
676
- }
677
600
  }
package/src/index.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  import { Agent } from './agent';
2
2
  import events from './events';
3
3
 
4
- export type { ElevenLabsContext } from './types/Voice.types';
5
4
  export { Agent, events };
6
5
 
7
6
  export type {
@@ -18,11 +17,8 @@ export type {
18
17
  JunctionNode,
19
18
  ToolNode,
20
19
  AppToolNode,
21
- VoiceTriggerNode,
22
- WebhookTriggerNode,
23
20
  } from './types/Flows.types';
24
21
  export { NodeType, TriggerType, EdgeType, AppNodeMetadata, AppNodeMetadataType, NodeMetadata, KnownTriggerNames } from './types/Flows.types';
25
22
  export type { Tool } from './types/Tools.types';
26
23
  export { FlowHistoryType, FlowHistory, TriggerInvocationHistory, AppActionInvocationHistory } from './types/Agent.types';
27
- export type { AgentInvokeParams } from './types/Agent.types';
28
24
  export type { Environment } from './types/Platform.types';
@@ -81,7 +81,6 @@ export const addPromptNode = async ({ graph, node, llm, tools, emit }: AddPrompt
81
81
  memory: state.memory,
82
82
  sessionId: configurable.thread_id,
83
83
  });
84
- console.log('AI Message', result.content);
85
84
  }
86
85
 
87
86
  return {
@@ -1,9 +1,7 @@
1
1
  import { resolve } from 'path';
2
2
  import { config } from 'dotenv';
3
3
  import { Environment } from '../types/Platform.types';
4
- const path = resolve(__dirname, '../../.env');
5
- console.log(`Loading config from ${path}`);
6
- config({ path });
4
+ config({ path: resolve(__dirname, '../../.env') });
7
5
 
8
6
  type MindedConfig = {
9
7
  baseUrl: string;
@@ -11,9 +9,6 @@ type MindedConfig = {
11
9
  token: string | null;
12
10
  runLocally: boolean;
13
11
  isDeployed: boolean;
14
- dashboardConnected: boolean;
15
- elevenLabsKey: string | null;
16
- elevenLabsAgentId: string | null;
17
12
  };
18
13
 
19
14
  export const getConfig = (): MindedConfig => {
@@ -26,9 +21,6 @@ export const getConfig = (): MindedConfig => {
26
21
  token: process.env.MINDED_CONNECTION_TOKEN || '',
27
22
  runLocally: process.env.RUN_LOCALLY !== 'false',
28
23
  isDeployed: process.env.IS_DEPLOYED_AGENT === 'true',
29
- dashboardConnected: false,
30
- elevenLabsKey: process.env.ELEVEN_LABS_API_KEY || null,
31
- elevenLabsAgentId: process.env.ELEVEN_LABS_AGENT_ID || null,
32
24
  };
33
25
  case 'development':
34
26
  return {
@@ -37,9 +29,6 @@ export const getConfig = (): MindedConfig => {
37
29
  token: process.env.MINDED_CONNECTION_TOKEN || '',
38
30
  runLocally: process.env.RUN_LOCALLY === 'true',
39
31
  isDeployed: process.env.IS_DEPLOYED_AGENT === 'true',
40
- dashboardConnected: true,
41
- elevenLabsKey: process.env.ELEVEN_LABS_API_KEY || null,
42
- elevenLabsAgentId: process.env.ELEVEN_LABS_AGENT_ID || 'Iyr6DCOj80AdvVEVHSGt',
43
32
  };
44
33
  case 'sandbox-staging':
45
34
  return {
@@ -48,9 +37,6 @@ export const getConfig = (): MindedConfig => {
48
37
  token: process.env.MINDED_CONNECTION_TOKEN || '',
49
38
  runLocally: false,
50
39
  isDeployed: process.env.IS_DEPLOYED_AGENT === 'true',
51
- elevenLabsKey: process.env.ELEVEN_LABS_API_KEY || null,
52
- dashboardConnected: true,
53
- elevenLabsAgentId: process.env.ELEVEN_LABS_AGENT_ID || 'agent_01jye194psezr909nwec27m2t9',
54
40
  };
55
41
  case 'sandbox':
56
42
  return {
@@ -59,9 +45,6 @@ export const getConfig = (): MindedConfig => {
59
45
  token: process.env.MINDED_CONNECTION_TOKEN || '',
60
46
  runLocally: false,
61
47
  isDeployed: process.env.IS_DEPLOYED_AGENT === 'true',
62
- elevenLabsKey: process.env.ELEVEN_LABS_API_KEY || null,
63
- dashboardConnected: true,
64
- elevenLabsAgentId: process.env.ELEVEN_LABS_AGENT_ID || 'agent_01jye194psezr909nwec27m2t9',
65
48
  };
66
49
  case 'production':
67
50
  return {
@@ -70,9 +53,6 @@ export const getConfig = (): MindedConfig => {
70
53
  token: process.env.MINDED_CONNECTION_TOKEN || '',
71
54
  runLocally: false,
72
55
  isDeployed: process.env.IS_DEPLOYED_AGENT === 'true',
73
- elevenLabsKey: process.env.ELEVEN_LABS_API_KEY || null,
74
- dashboardConnected: false,
75
- elevenLabsAgentId: process.env.ELEVEN_LABS_AGENT_ID || 'agent_01jye1ajkaf17axpcxg220qwcm',
76
56
  };
77
57
  }
78
58
  };
@@ -1,29 +1,26 @@
1
1
  import { io, Socket } from 'socket.io-client';
2
- import { BaseMindedConnectionSocketMessage, MindedConnectionSocketMessageType, MindedConnectionSocketMessageTypeMap } from './mindedConnectionTypes';
2
+ import { BaseMindedConnectionSocketMessage, MindedConnectionSocketMessageType } from './mindedConnectionTypes';
3
3
  import { stringify } from 'flatted';
4
4
  import { getConfig } from './config';
5
5
 
6
6
  export class MindedConnection {
7
7
  private socket: Socket | null = null;
8
8
  listeners: {
9
- [key: string]: ((message: BaseMindedConnectionSocketMessage, callback: (response: any) => void) => void)[];
9
+ [key: string]: ((message: BaseMindedConnectionSocketMessage) => void)[];
10
10
  } = {};
11
11
 
12
12
  public get isConnected(): boolean {
13
13
  return this.socket?.connected ?? false;
14
14
  }
15
15
 
16
- public on = (event: MindedConnectionSocketMessageType, callback: (message: BaseMindedConnectionSocketMessage, callback: (response: any) => void) => void) => {
16
+ public on = (event: MindedConnectionSocketMessageType, callback: (message: BaseMindedConnectionSocketMessage) => void) => {
17
17
  if (!this.listeners[event]) {
18
18
  this.listeners[event] = [];
19
19
  }
20
20
  this.listeners[event].push(callback);
21
21
  };
22
22
 
23
- public emit = <E extends keyof MindedConnectionSocketMessageTypeMap>(
24
- event: E,
25
- message: MindedConnectionSocketMessageTypeMap[E]
26
- ) => {
23
+ public emit = (event: MindedConnectionSocketMessageType, message: BaseMindedConnectionSocketMessage) => {
27
24
  if (this.socket) {
28
25
  this.socket.emit(event, message);
29
26
  }
@@ -37,7 +34,7 @@ export class MindedConnection {
37
34
  return new Promise((resolve, reject) => {
38
35
  // Set up timeout
39
36
  const timeout = setTimeout(() => {
40
- reject(new Error(`Acknowledgement timeout after ${timeoutMs}ms; Message: ${message}`));
37
+ reject(new Error(`Acknowledgement timeout after ${timeoutMs}ms`));
41
38
  }, timeoutMs);
42
39
 
43
40
  // Emit with acknowledgement callback
@@ -73,8 +70,8 @@ export class MindedConnection {
73
70
  });
74
71
 
75
72
  this.socket.on('connect_error', () => {
76
- console.error('Minded connection error');
77
- reject(new Error('Minded connection error'));
73
+ console.error('Failed to connect to minded platform');
74
+ reject(new Error('Failed to connect to minded platform'));
78
75
  });
79
76
 
80
77
  this.socket.on('disconnect', () => {
@@ -99,15 +96,12 @@ export class MindedConnection {
99
96
  });
100
97
 
101
98
  // Listen for specific message types
102
- this.socket.onAny((event, message, callback) => {
99
+ this.socket.onAny((event, message) => {
103
100
  if (this.listeners[event]) {
104
101
  this.listeners[event].forEach((listener) => {
105
- listener(message, callback);
102
+ listener(message);
106
103
  });
107
104
  }
108
- else {
109
- console.warn({ message: 'No listeners found for event', event });
110
- }
111
105
  });
112
106
 
113
107
  // Handle process termination
@@ -7,43 +7,16 @@ import type {
7
7
  CheckpointTuple,
8
8
  } from '@langchain/langgraph-checkpoint';
9
9
  import type { RunnableConfig } from '@langchain/core/runnables';
10
- import { AgentInvokeParams } from '../types/Agent.types';
11
10
 
12
11
  export enum MindedConnectionSocketMessageType {
13
12
  OnAppTrigger = 'on-app-trigger',
14
13
  OnAppAction = 'on-app-action',
15
- GET_SECRETS = 'get-secrets',
16
- GET_FLOWS = 'get-flows',
17
- INVOKE = 'invoke',
18
- // Checkpoints
19
14
  CHECKPOINT_GET_TUPLE = 'checkpoint-get-tuple',
20
15
  CHECKPOINT_PUT = 'checkpoint-put',
21
16
  CHECKPOINT_LIST = 'checkpoint-list',
22
17
  CHECKPOINT_PUT_WRITES = 'checkpoint-put-writes',
23
- // Voice
24
- DASHBOARD_VOICE_USER_AUDIO = 'dashboard-voice-user-audio',
25
- DASHBOARD_VOICE_AGENT_AUDIO = 'dashboard-voice-agent-audio',
26
- DASHBOARD_VOICE_SESSION_START = 'dashboard-voice-session-start',
27
- DASHBOARD_VOICE_SESSION_END = 'dashboard-voice-session-end',
28
- DASHBOARD_VOICE_INTERRUPTION = 'dashboard-voice-interruption',
29
- DASHBOARD_VOICE_AGENT_RESPONSE_CORRECTION = 'dashboard-voice-agent-response-correction',
30
- }
31
-
32
- export type MindedConnectionSocketMessageTypeMap = {
33
- [MindedConnectionSocketMessageType.OnAppTrigger]: OnAppTrigger;
34
- [MindedConnectionSocketMessageType.OnAppAction]: BaseMindedConnectionSocketMessage;
35
- [MindedConnectionSocketMessageType.GET_SECRETS]: BaseMindedConnectionSocketMessage;
36
- [MindedConnectionSocketMessageType.GET_FLOWS]: BaseMindedConnectionSocketMessage;
37
- [MindedConnectionSocketMessageType.INVOKE]: InvokeMessage;
38
- [MindedConnectionSocketMessageType.CHECKPOINT_GET_TUPLE]: OnCheckpointGetTuple;
39
- [MindedConnectionSocketMessageType.CHECKPOINT_PUT]: OnCheckpointPut;
40
- [MindedConnectionSocketMessageType.CHECKPOINT_LIST]: OnCheckpointList;
41
- [MindedConnectionSocketMessageType.CHECKPOINT_PUT_WRITES]: OnCheckpointPutWrites;
42
- [MindedConnectionSocketMessageType.DASHBOARD_VOICE_USER_AUDIO]: OnVoiceAudioIn;
43
- [MindedConnectionSocketMessageType.DASHBOARD_VOICE_AGENT_AUDIO]: OnVoiceAudioOut;
44
- [MindedConnectionSocketMessageType.DASHBOARD_VOICE_SESSION_START]: BaseVoiceMessage;
45
- [MindedConnectionSocketMessageType.DASHBOARD_VOICE_SESSION_END]: OnVoiceSessionEnd;
46
- [MindedConnectionSocketMessageType.DASHBOARD_VOICE_INTERRUPTION]: OnVoiceInterruption;
18
+ GET_SECRETS = 'get-secrets',
19
+ GET_FLOWS = 'get-flows',
47
20
  }
48
21
 
49
22
  export interface BaseMindedConnectionSocketMessage {
@@ -93,40 +66,3 @@ export interface OnCheckpointList extends BaseMindedConnectionSocketMessage {
93
66
  export interface OnCheckpointListResponse extends BaseSdkConnectionSocketMessageResponseCallbackAck {
94
67
  checkpoints?: CheckpointTuple[];
95
68
  }
96
-
97
- export interface BaseVoiceMessage extends BaseMindedConnectionSocketMessage {
98
- sessionId: string;
99
- timestamp: number;
100
- }
101
-
102
- // Voice/Audio event interfaces
103
- export interface OnVoiceAudioIn extends BaseVoiceMessage {
104
- audioData: string; // base64 encoded audio data
105
- }
106
-
107
- export interface OnVoiceAudioOut extends BaseVoiceMessage {
108
- audioData: string; // base64 encoded audio data
109
- }
110
-
111
- export interface OnVoiceMessageIn extends BaseVoiceMessage {
112
- text: string;
113
- }
114
-
115
- export interface OnVoiceMessageOut extends BaseMindedConnectionSocketMessage {
116
- sessionId: string;
117
- text: string;
118
- timestamp: number;
119
- }
120
-
121
- export interface OnVoiceInterruption extends BaseMindedConnectionSocketMessage {
122
- sessionId: string;
123
- timestamp: number;
124
- }
125
- export interface OnVoiceSessionEnd extends BaseMindedConnectionSocketMessage {
126
- sessionId: string;
127
- timestamp: number;
128
- }
129
-
130
- export interface InvokeMessage extends BaseMindedConnectionSocketMessage, AgentInvokeParams {
131
- type: MindedConnectionSocketMessageType.INVOKE;
132
- }
@@ -9,20 +9,6 @@ export type MindedSDKConfig = {
9
9
  tools: string[];
10
10
  }
11
11
 
12
- /**
13
- * Parameters for the Agent invoke method
14
- */
15
- export interface AgentInvokeParams {
16
- /** The payload/data associated with the trigger */
17
- triggerBody: any;
18
- /** The name/type of the trigger being invoked */
19
- triggerName: string;
20
- /** Optional session identifier for conversation continuity */
21
- sessionId?: string;
22
- /** Optional name of the application triggering the agent in case of an app trigger */
23
- appName?: string;
24
- }
25
-
26
12
  export enum FlowHistoryType {
27
13
  TRIGGER_INVOCATION = 'triggerInvocation',
28
14
  APP_ACTION_INVOCATION = 'appActionInvocation',
@@ -30,12 +30,10 @@ export enum TriggerType {
30
30
  APP = 'app',
31
31
  WEBHOOK = 'webhook',
32
32
  MANUAL = 'manual',
33
- VOICE = 'voice',
34
33
  }
35
34
 
36
35
  export interface BaseTriggerNode extends BaseNode {
37
36
  type: NodeType.TRIGGER;
38
- triggerType: TriggerType;
39
37
  }
40
38
 
41
39
  export interface BaseAppNode {
@@ -58,18 +56,6 @@ export interface WebhookTriggerNode extends BaseTriggerNode {
58
56
  triggerType: TriggerType.WEBHOOK;
59
57
  }
60
58
 
61
- export interface VoiceTriggerNode extends BaseTriggerNode {
62
- triggerType: TriggerType.VOICE;
63
- /**
64
- * Text that will be spoken as the very first message in a voice interaction.
65
- */
66
- firstMessage: string;
67
- /**
68
- * Optional ElevenLabs voice ID to be used for TTS.
69
- */
70
- voiceId?: string;
71
- }
72
-
73
59
  export interface ManualTriggerNode extends BaseTriggerNode {
74
60
  triggerType: TriggerType.MANUAL;
75
61
  }
@@ -80,7 +66,7 @@ export interface PromptNode extends BaseNode {
80
66
  llmConfig?: LLMConfig;
81
67
  }
82
68
 
83
- export type TriggerNode = AppTriggerNode | WebhookTriggerNode | ManualTriggerNode | VoiceTriggerNode;
69
+ export type TriggerNode = AppTriggerNode | WebhookTriggerNode | ManualTriggerNode;
84
70
 
85
71
  export interface JunctionNode extends BaseNode {
86
72
  type: NodeType.JUNCTION;
@@ -1,5 +0,0 @@
1
- export type ElevenLabsContext = {
2
- sessionId: string;
3
- mindedToken: string;
4
- };
5
- //# sourceMappingURL=Voice.types.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Voice.types.d.ts","sourceRoot":"","sources":["../../src/types/Voice.types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,iBAAiB,GAAG;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;CACrB,CAAA"}
@@ -1,3 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- //# sourceMappingURL=Voice.types.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Voice.types.js","sourceRoot":"","sources":["../../src/types/Voice.types.ts"],"names":[],"mappings":""}
@@ -1,70 +0,0 @@
1
- /** ElevenLabs LLM proxy request body shape */
2
- export interface LLMRequestBody {
3
- messages: Array<{
4
- content: string;
5
- role: string;
6
- tool_call_id?: string;
7
- }>;
8
- model: string;
9
- max_tokens: number;
10
- stream: boolean;
11
- temperature: number;
12
- tools: null;
13
- }
14
- interface BaseEvent {
15
- type: string;
16
- }
17
- interface UserTranscriptEvent extends BaseEvent {
18
- type: 'user_transcript';
19
- user_transcription_event: {
20
- user_transcript: string;
21
- };
22
- }
23
- interface AgentResponseEvent extends BaseEvent {
24
- type: 'agent_response';
25
- agent_response_event: {
26
- agent_response: string;
27
- };
28
- }
29
- interface AudioResponseEvent extends BaseEvent {
30
- type: 'audio';
31
- audio_event: {
32
- audio_base_64: string;
33
- event_id: number;
34
- };
35
- }
36
- interface InterruptionEvent extends BaseEvent {
37
- type: 'interruption';
38
- interruption_event: {
39
- event_id: number;
40
- };
41
- }
42
- interface PingEvent extends BaseEvent {
43
- type: 'ping';
44
- ping_event: {
45
- event_id: number;
46
- ping_ms: number;
47
- };
48
- }
49
- interface ConversationInitiationMetadataEvent extends BaseEvent {
50
- type: 'conversation_initiation_metadata';
51
- conversation_initiation_metadata_event: {
52
- conversation_id: string;
53
- };
54
- }
55
- export interface AgentResponseCorrectionEvent extends BaseEvent {
56
- type: 'agent_response_correction';
57
- agent_response_correction_event: {
58
- corrected_agent_response: string;
59
- original_agent_response: string;
60
- };
61
- }
62
- /** Union of all possible WebSocket events we care about */
63
- export type ElevenLabsWebSocketEvent = UserTranscriptEvent | AgentResponseEvent | AudioResponseEvent | InterruptionEvent | PingEvent | ConversationInitiationMetadataEvent | AgentResponseCorrectionEvent;
64
- /** Fetch signed URL from ElevenLabs API */
65
- export declare const getSignedUrl: ({ agentId, apiKey }: {
66
- agentId: string;
67
- apiKey: string;
68
- }) => Promise<string>;
69
- export {};
70
- //# sourceMappingURL=elevenLabsUtils.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"elevenLabsUtils.d.ts","sourceRoot":"","sources":["../../src/voice/elevenLabsUtils.ts"],"names":[],"mappings":"AAAA,8CAA8C;AAC9C,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,KAAK,CAAC;QACd,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,EAAE,MAAM,CAAC;QACb,YAAY,CAAC,EAAE,MAAM,CAAC;KACvB,CAAC,CAAC;IACH,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,OAAO,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,IAAI,CAAC;CACb;AAID,UAAU,SAAS;IACjB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,UAAU,mBAAoB,SAAQ,SAAS;IAC7C,IAAI,EAAE,iBAAiB,CAAC;IACxB,wBAAwB,EAAE;QACxB,eAAe,EAAE,MAAM,CAAC;KACzB,CAAC;CACH;AAED,UAAU,kBAAmB,SAAQ,SAAS;IAC5C,IAAI,EAAE,gBAAgB,CAAC;IACvB,oBAAoB,EAAE;QACpB,cAAc,EAAE,MAAM,CAAC;KACxB,CAAC;CACH;AAED,UAAU,kBAAmB,SAAQ,SAAS;IAC5C,IAAI,EAAE,OAAO,CAAC;IACd,WAAW,EAAE;QACX,aAAa,EAAE,MAAM,CAAC;QACtB,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC;CACH;AAED,UAAU,iBAAkB,SAAQ,SAAS;IAC3C,IAAI,EAAE,cAAc,CAAC;IACrB,kBAAkB,EAAE;QAClB,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC;CACH;AAED,UAAU,SAAU,SAAQ,SAAS;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE;QACV,QAAQ,EAAE,MAAM,CAAC;QACjB,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;CACH;AAED,UAAU,mCAAoC,SAAQ,SAAS;IAC7D,IAAI,EAAE,kCAAkC,CAAC;IACzC,sCAAsC,EAAE;QACtC,eAAe,EAAE,MAAM,CAAC;KACzB,CAAC;CACH;AAED,MAAM,WAAW,4BAA6B,SAAQ,SAAS;IAC7D,IAAI,EAAE,2BAA2B,CAAC;IAClC,+BAA+B,EAAE;QAC/B,wBAAwB,EAAE,MAAM,CAAC;QACjC,uBAAuB,EAAE,MAAM,CAAC;KACjC,CAAC;CACH;AAED,2DAA2D;AAC3D,MAAM,MAAM,wBAAwB,GAChC,mBAAmB,GACnB,kBAAkB,GAClB,kBAAkB,GAClB,iBAAiB,GACjB,SAAS,GACT,mCAAmC,GACnC,4BAA4B,CAAC;AAIjC,2CAA2C;AAC3C,eAAO,MAAM,YAAY,GAAU,qBAAqB;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,KAAG,OAAO,CAAC,MAAM,CAe3G,CAAC"}
@@ -1,20 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getSignedUrl = void 0;
4
- // ----------------- ElevenLabs Utility Functions -----------------
5
- /** Fetch signed URL from ElevenLabs API */
6
- const getSignedUrl = async ({ agentId, apiKey }) => {
7
- const response = await fetch(`https://api.elevenlabs.io/v1/convai/conversation/get_signed_url?agent_id=${agentId}`, {
8
- method: 'GET',
9
- headers: {
10
- 'xi-api-key': apiKey,
11
- },
12
- });
13
- if (!response.ok) {
14
- throw new Error(`Failed to fetch signed url - status ${response.status}`);
15
- }
16
- const body = await response.json();
17
- return body.signed_url;
18
- };
19
- exports.getSignedUrl = getSignedUrl;
20
- //# sourceMappingURL=elevenLabsUtils.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"elevenLabsUtils.js","sourceRoot":"","sources":["../../src/voice/elevenLabsUtils.ts"],"names":[],"mappings":";;;AAkFA,mEAAmE;AAEnE,2CAA2C;AACpC,MAAM,YAAY,GAAG,KAAK,EAAE,EAAE,OAAO,EAAE,MAAM,EAAuC,EAAmB,EAAE;IAC9G,MAAM,QAAQ,GAAG,MAAM,KAAK,CAC1B,4EAA4E,OAAO,EAAE,EACrF;QACE,MAAM,EAAE,KAAK;QACb,OAAO,EAAE;YACP,YAAY,EAAE,MAAM;SACrB;KACF,CACF,CAAC;IACF,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,uCAAuC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;IAC5E,CAAC;IACD,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IACnC,OAAO,IAAI,CAAC,UAAU,CAAC;AACzB,CAAC,CAAC;AAfW,QAAA,YAAY,gBAevB"}
@@ -1,47 +0,0 @@
1
- import { Agent } from '../agent';
2
- /**
3
- * Voice Conversation class for managing individual ElevenLabs voice conversations
4
- */
5
- export declare class VoiceSession {
6
- private agent;
7
- private sessionId;
8
- private firstMessage;
9
- private voiceId?;
10
- private elevenLabsSocket?;
11
- private onAudioCallback?;
12
- private onInterruptionCallback?;
13
- private onMessageCallback?;
14
- private onDisconnectCallback?;
15
- constructor({ agent, sessionId, firstMessage, voiceId }: {
16
- agent: Agent;
17
- sessionId: string;
18
- firstMessage: string;
19
- voiceId?: string;
20
- });
21
- /**
22
- * Initialize the voice conversation connection
23
- */
24
- init(): Promise<void>;
25
- private sendToElevenLabs;
26
- private waitForSocketOpen;
27
- private setupSocketHandlers;
28
- private updateAgentResponse;
29
- hangup(): void;
30
- /**
31
- * Set callback for audio data in base64 format
32
- */
33
- onAudio(callback: (data: string) => void): void;
34
- /**
35
- * Set callback for interruption events
36
- */
37
- onInterruption(callback: () => void): void;
38
- /**
39
- * Set callback for disconnect events
40
- */
41
- onDisconnect(callback: () => void): void;
42
- /**
43
- * User audio in base64 format
44
- */
45
- sendAudio(audioData: string): void;
46
- }
47
- //# sourceMappingURL=voiceSession.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"voiceSession.d.ts","sourceRoot":"","sources":["../../src/voice/voiceSession.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAWjC;;GAEG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,KAAK,CAAQ;IACrB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,OAAO,CAAC,CAAS;IACzB,OAAO,CAAC,gBAAgB,CAAC,CAAY;IAErC,OAAO,CAAC,eAAe,CAAC,CAAyB;IACjD,OAAO,CAAC,sBAAsB,CAAC,CAAa;IAC5C,OAAO,CAAC,iBAAiB,CAAC,CAA+C;IACzE,OAAO,CAAC,oBAAoB,CAAC,CAAa;gBAE9B,EAAE,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,OAAO,EAAE,EAAE;QAAE,KAAK,EAAE,KAAK,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE;IAQpI;;OAEG;IACU,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;YAoBpB,gBAAgB;YAQhB,iBAAiB;IAsB/B,OAAO,CAAC,mBAAmB;YAmGb,mBAAmB;IAe1B,MAAM,IAAI,IAAI;IAKrB;;OAEG;IACH,OAAO,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI;IAI/C;;OAEG;IACH,cAAc,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI;IAI1C;;OAEG;IACH,YAAY,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI;IAIxC;;OAEG;IACH,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;CAGnC"}
@@ -1,208 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.VoiceSession = void 0;
4
- const ws_1 = require("ws");
5
- const mindedConnectionTypes_1 = require("../platform/mindedConnectionTypes");
6
- const config_1 = require("../platform/config");
7
- const elevenLabsUtils_1 = require("./elevenLabsUtils");
8
- const messages_1 = require("@langchain/core/messages");
9
- /**
10
- * Voice Conversation class for managing individual ElevenLabs voice conversations
11
- */
12
- class VoiceSession {
13
- constructor({ agent, sessionId, firstMessage, voiceId }) {
14
- console.debug('Starting voice session', { sessionId, firstMessage, voiceId });
15
- this.agent = agent;
16
- this.sessionId = sessionId;
17
- this.firstMessage = firstMessage;
18
- this.voiceId = voiceId;
19
- }
20
- /**
21
- * Initialize the voice conversation connection
22
- */
23
- async init() {
24
- const { elevenLabsKey, elevenLabsAgentId } = (0, config_1.getConfig)();
25
- if (!elevenLabsKey) {
26
- throw new Error('Missing ElevenLabs key - set ELEVEN_LABS_KEY env var');
27
- }
28
- if (!elevenLabsAgentId) {
29
- throw new Error('Missing ElevenLabs agent id - set ELEVEN_LABS_AGENT_ID env var');
30
- }
31
- const signedUrl = await (0, elevenLabsUtils_1.getSignedUrl)({
32
- agentId: elevenLabsAgentId,
33
- apiKey: elevenLabsKey
34
- });
35
- this.elevenLabsSocket = new ws_1.WebSocket(signedUrl);
36
- this.setupSocketHandlers();
37
- }
38
- async sendToElevenLabs(message) {
39
- if (!this.elevenLabsSocket) {
40
- throw new Error('Socket not initialized');
41
- }
42
- await this.waitForSocketOpen(this.elevenLabsSocket);
43
- this.elevenLabsSocket.send(message);
44
- }
45
- async waitForSocketOpen(socket) {
46
- if (socket.readyState === ws_1.WebSocket.OPEN) {
47
- return;
48
- }
49
- return new Promise((resolve, reject) => {
50
- const timeoutMs = 10000;
51
- const intervalMs = 100;
52
- let tries = 0;
53
- const interval = setInterval(() => {
54
- if (socket.readyState === ws_1.WebSocket.OPEN) {
55
- clearInterval(interval);
56
- resolve();
57
- }
58
- tries++;
59
- if (tries >= timeoutMs) {
60
- clearInterval(interval);
61
- reject(new Error('Socket not open'));
62
- }
63
- }, intervalMs);
64
- });
65
- }
66
- setupSocketHandlers() {
67
- const socket = this.elevenLabsSocket; // non-null assertion once, we ensured it's assigned in init()
68
- socket.onopen = () => {
69
- console.debug('Connected to voice provider');
70
- const initiationData = {
71
- type: 'conversation_initiation_client_data',
72
- conversation_config_override: {
73
- agent: {
74
- first_message: this.firstMessage,
75
- language: 'en',
76
- },
77
- ...(this.voiceId ? { tts: { voice_id: this.voiceId } } : {}),
78
- },
79
- };
80
- this.sendToElevenLabs(JSON.stringify(initiationData));
81
- this.sendToElevenLabs(JSON.stringify({ type: 'contextual_update', text: JSON.stringify({ sessionId: this.sessionId, mindedToken: (0, config_1.getConfig)().token }) }));
82
- };
83
- socket.onclose = () => {
84
- var _a;
85
- console.debug('Disconnected from voice provider');
86
- (_a = this.onDisconnectCallback) === null || _a === void 0 ? void 0 : _a.call(this);
87
- this.agent.voiceSessions.delete(this.sessionId);
88
- };
89
- socket.onerror = (err) => {
90
- console.error('[ElevenLabsVoice] WebSocket error', err);
91
- };
92
- socket.onmessage = async (event) => {
93
- var _a, _b, _c;
94
- const data = JSON.parse(event.data.toString());
95
- switch (data.type) {
96
- case 'ping':
97
- setTimeout(() => {
98
- this.sendToElevenLabs(JSON.stringify({ type: 'pong', event_id: data.ping_event.event_id }));
99
- }, data.ping_event.ping_ms);
100
- break;
101
- case 'user_transcript':
102
- console.debug('User transcript received', data.user_transcription_event.user_transcript);
103
- if (this.onMessageCallback) {
104
- this.onMessageCallback(data.user_transcription_event.user_transcript, new messages_1.HumanMessage(data.user_transcription_event.user_transcript));
105
- }
106
- break;
107
- case 'agent_response':
108
- if (this.onMessageCallback) {
109
- this.onMessageCallback(data.agent_response_event.agent_response, new messages_1.AIMessage(data.agent_response_event.agent_response));
110
- }
111
- break;
112
- case 'interruption':
113
- console.debug('Interruption received');
114
- (_a = this.onInterruptionCallback) === null || _a === void 0 ? void 0 : _a.call(this);
115
- // Send interruption event to dashboard if connected
116
- if ((0, config_1.getConfig)().dashboardConnected) {
117
- try {
118
- (_b = this.agent.mindedConnection) === null || _b === void 0 ? void 0 : _b.emit(mindedConnectionTypes_1.MindedConnectionSocketMessageType.DASHBOARD_VOICE_INTERRUPTION, {
119
- type: mindedConnectionTypes_1.MindedConnectionSocketMessageType.DASHBOARD_VOICE_INTERRUPTION,
120
- sessionId: this.sessionId,
121
- timestamp: Date.now(),
122
- });
123
- }
124
- catch (error) {
125
- console.error('[ElevenLabsVoice] Error sending interruption to dashboard', error);
126
- }
127
- }
128
- break;
129
- case 'audio':
130
- if (this.onAudioCallback) {
131
- this.onAudioCallback(data.audio_event.audio_base_64);
132
- }
133
- if ((0, config_1.getConfig)().dashboardConnected) {
134
- try {
135
- await ((_c = this.agent.mindedConnection) === null || _c === void 0 ? void 0 : _c.awaitEmit(mindedConnectionTypes_1.MindedConnectionSocketMessageType.DASHBOARD_VOICE_AGENT_AUDIO, {
136
- sessionId: this.sessionId,
137
- audioData: data.audio_event.audio_base_64,
138
- }));
139
- }
140
- catch (error) {
141
- console.error('[ElevenLabsVoice] Error sending audio to dashboard', error);
142
- }
143
- }
144
- break;
145
- case 'conversation_initiation_metadata':
146
- console.debug('ElevenLabs conversation initiation metadata', data);
147
- break;
148
- case 'agent_response_correction':
149
- try {
150
- console.debug('Agent response correction received', data.agent_response_correction_event);
151
- await this.updateAgentResponse(data.agent_response_correction_event.original_agent_response, data.agent_response_correction_event.corrected_agent_response);
152
- }
153
- catch (error) {
154
- console.error('[ElevenLabsVoice] Error updating agent response', error);
155
- }
156
- break;
157
- default:
158
- console.debug('Received unknown message from ElevenLabs', data);
159
- break;
160
- }
161
- };
162
- }
163
- async updateAgentResponse(originalAgentResponse, correctedAgentResponse) {
164
- const graphState = await this.agent.compiledGraph.getState(this.agent.getLangraphConfig(this.sessionId));
165
- const agentMessage = graphState.values.messages.find((message) => message.content === originalAgentResponse && message instanceof messages_1.AIMessage);
166
- if (agentMessage) {
167
- agentMessage.content = correctedAgentResponse;
168
- const currentNodeId = graphState.tasks[graphState.tasks.length - 1].name;
169
- await this.agent.compiledGraph.updateState(this.agent.getLangraphConfig(this.sessionId), {
170
- messages: graphState.values.messages,
171
- }, currentNodeId);
172
- }
173
- else {
174
- console.warn('Agent message not found for correction', originalAgentResponse);
175
- }
176
- }
177
- hangup() {
178
- var _a, _b;
179
- (_a = this.onDisconnectCallback) === null || _a === void 0 ? void 0 : _a.call(this);
180
- (_b = this.elevenLabsSocket) === null || _b === void 0 ? void 0 : _b.close();
181
- }
182
- /**
183
- * Set callback for audio data in base64 format
184
- */
185
- onAudio(callback) {
186
- this.onAudioCallback = callback;
187
- }
188
- /**
189
- * Set callback for interruption events
190
- */
191
- onInterruption(callback) {
192
- this.onInterruptionCallback = callback;
193
- }
194
- /**
195
- * Set callback for disconnect events
196
- */
197
- onDisconnect(callback) {
198
- this.onDisconnectCallback = callback;
199
- }
200
- /**
201
- * User audio in base64 format
202
- */
203
- sendAudio(audioData) {
204
- this.sendToElevenLabs(JSON.stringify({ user_audio_chunk: audioData }));
205
- }
206
- }
207
- exports.VoiceSession = VoiceSession;
208
- //# sourceMappingURL=voiceSession.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"voiceSession.js","sourceRoot":"","sources":["../../src/voice/voiceSession.ts"],"names":[],"mappings":"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"}
@@ -1,4 +0,0 @@
1
- export type ElevenLabsContext = {
2
- sessionId: string;
3
- mindedToken: string;
4
- }
@@ -1,101 +0,0 @@
1
- /** ElevenLabs LLM proxy request body shape */
2
- export interface LLMRequestBody {
3
- messages: Array<{
4
- content: string;
5
- role: string;
6
- tool_call_id?: string;
7
- }>;
8
- model: string;
9
- max_tokens: number;
10
- stream: boolean;
11
- temperature: number;
12
- tools: null;
13
- }
14
-
15
- // ----------------- ElevenLabs WebSocket event types -----------------
16
-
17
- interface BaseEvent {
18
- type: string;
19
- }
20
-
21
- interface UserTranscriptEvent extends BaseEvent {
22
- type: 'user_transcript';
23
- user_transcription_event: {
24
- user_transcript: string;
25
- };
26
- }
27
-
28
- interface AgentResponseEvent extends BaseEvent {
29
- type: 'agent_response';
30
- agent_response_event: {
31
- agent_response: string;
32
- };
33
- }
34
-
35
- interface AudioResponseEvent extends BaseEvent {
36
- type: 'audio';
37
- audio_event: {
38
- audio_base_64: string;
39
- event_id: number;
40
- };
41
- }
42
-
43
- interface InterruptionEvent extends BaseEvent {
44
- type: 'interruption';
45
- interruption_event: {
46
- event_id: number;
47
- };
48
- }
49
-
50
- interface PingEvent extends BaseEvent {
51
- type: 'ping';
52
- ping_event: {
53
- event_id: number;
54
- ping_ms: number;
55
- };
56
- }
57
-
58
- interface ConversationInitiationMetadataEvent extends BaseEvent {
59
- type: 'conversation_initiation_metadata';
60
- conversation_initiation_metadata_event: {
61
- conversation_id: string;
62
- };
63
- }
64
-
65
- export interface AgentResponseCorrectionEvent extends BaseEvent {
66
- type: 'agent_response_correction';
67
- agent_response_correction_event: {
68
- corrected_agent_response: string;
69
- original_agent_response: string;
70
- };
71
- }
72
-
73
- /** Union of all possible WebSocket events we care about */
74
- export type ElevenLabsWebSocketEvent =
75
- | UserTranscriptEvent
76
- | AgentResponseEvent
77
- | AudioResponseEvent
78
- | InterruptionEvent
79
- | PingEvent
80
- | ConversationInitiationMetadataEvent
81
- | AgentResponseCorrectionEvent;
82
-
83
- // ----------------- ElevenLabs Utility Functions -----------------
84
-
85
- /** Fetch signed URL from ElevenLabs API */
86
- export const getSignedUrl = async ({ agentId, apiKey }: { agentId: string; apiKey: string }): Promise<string> => {
87
- const response = await fetch(
88
- `https://api.elevenlabs.io/v1/convai/conversation/get_signed_url?agent_id=${agentId}`,
89
- {
90
- method: 'GET',
91
- headers: {
92
- 'xi-api-key': apiKey,
93
- },
94
- },
95
- );
96
- if (!response.ok) {
97
- throw new Error(`Failed to fetch signed url - status ${response.status}`);
98
- }
99
- const body = await response.json();
100
- return body.signed_url;
101
- };
@@ -1,257 +0,0 @@
1
- import { WebSocket } from 'ws';
2
- import { Agent } from '../agent';
3
- import {
4
- MindedConnectionSocketMessageType,
5
- } from '../platform/mindedConnectionTypes';
6
- import { getConfig } from '../platform/config';
7
- import {
8
- ElevenLabsWebSocketEvent,
9
- getSignedUrl,
10
- } from './elevenLabsUtils';
11
- import { AIMessage, BaseMessage, HumanMessage } from '@langchain/core/messages';
12
-
13
- /**
14
- * Voice Conversation class for managing individual ElevenLabs voice conversations
15
- */
16
- export class VoiceSession {
17
- private agent: Agent;
18
- private sessionId: string;
19
- private firstMessage: string;
20
- private voiceId?: string;
21
- private elevenLabsSocket?: WebSocket;
22
-
23
- private onAudioCallback?: (data: string) => void;
24
- private onInterruptionCallback?: () => void;
25
- private onMessageCallback?: (text: string, message: BaseMessage) => void;
26
- private onDisconnectCallback?: () => void;
27
-
28
- constructor({ agent, sessionId, firstMessage, voiceId }: { agent: Agent; sessionId: string; firstMessage: string; voiceId?: string }) {
29
- console.debug('Starting voice session', { sessionId, firstMessage });
30
- this.agent = agent;
31
- this.sessionId = sessionId;
32
- this.firstMessage = firstMessage;
33
- this.voiceId = voiceId;
34
- }
35
-
36
- /**
37
- * Initialize the voice conversation connection
38
- */
39
- public async init(): Promise<void> {
40
- const { elevenLabsKey, elevenLabsAgentId } = getConfig();
41
-
42
- if (!elevenLabsKey) {
43
- throw new Error('Missing ElevenLabs key - set ELEVEN_LABS_KEY env var');
44
- }
45
-
46
- if (!elevenLabsAgentId) {
47
- throw new Error('Missing ElevenLabs agent id - set ELEVEN_LABS_AGENT_ID env var');
48
- }
49
-
50
- const signedUrl = await getSignedUrl({
51
- agentId: elevenLabsAgentId,
52
- apiKey: elevenLabsKey
53
- });
54
-
55
- this.elevenLabsSocket = new WebSocket(signedUrl);
56
- this.setupSocketHandlers();
57
- }
58
-
59
- private async sendToElevenLabs(message: string): Promise<void> {
60
- if (!this.elevenLabsSocket) {
61
- throw new Error('Socket not initialized');
62
- }
63
- await this.waitForSocketOpen(this.elevenLabsSocket);
64
- this.elevenLabsSocket.send(message);
65
- }
66
-
67
- private async waitForSocketOpen(socket: WebSocket): Promise<void> {
68
- if (socket.readyState === WebSocket.OPEN) {
69
- return;
70
- }
71
- return new Promise((resolve, reject) => {
72
- const timeoutMs = 10000;
73
- const intervalMs = 100;
74
- let tries = 0;
75
- const interval = setInterval(() => {
76
- if (socket.readyState === WebSocket.OPEN) {
77
- clearInterval(interval);
78
- resolve();
79
- }
80
- tries++;
81
- if (tries >= timeoutMs) {
82
- clearInterval(interval);
83
- reject(new Error('Socket not open'));
84
- }
85
- }, intervalMs);
86
- });
87
- }
88
-
89
- private setupSocketHandlers(): void {
90
- const socket = this.elevenLabsSocket!; // non-null assertion once, we ensured it's assigned in init()
91
-
92
- socket.onopen = () => {
93
- console.debug('Connected to voice provider');
94
- const initiationData: ConversationInitiationClientData = {
95
- type: 'conversation_initiation_client_data',
96
- conversation_config_override: {
97
- agent: {
98
- first_message: this.firstMessage,
99
- language: 'en',
100
- },
101
- ...(this.voiceId
102
- ? {
103
- tts: {
104
- voice_id: this.voiceId,
105
- },
106
- }
107
- : {}),
108
- } as ConversationInitiationClientData['conversation_config_override'],
109
- };
110
-
111
- this.sendToElevenLabs(JSON.stringify(initiationData));
112
- this.sendToElevenLabs(JSON.stringify({ type: 'contextual_update', text: JSON.stringify({ sessionId: this.sessionId, mindedToken: getConfig().token! }) }));
113
- };
114
-
115
- socket.onclose = () => {
116
- console.debug('Disconnected from voice provider');
117
- this.onDisconnectCallback?.();
118
- this.agent.voiceSessions.delete(this.sessionId);
119
- };
120
-
121
- socket.onerror = (err: unknown) => {
122
- console.error('[ElevenLabsVoice] WebSocket error', err);
123
- };
124
-
125
- socket.onmessage = async (event: any) => {
126
- const data: ElevenLabsWebSocketEvent = JSON.parse(event.data.toString());
127
-
128
- switch (data.type) {
129
- case 'ping':
130
- setTimeout(() => {
131
- this.sendToElevenLabs(JSON.stringify({ type: 'pong', event_id: data.ping_event.event_id }));
132
- }, data.ping_event.ping_ms);
133
- break;
134
- case 'user_transcript':
135
- console.debug('User transcript received', data.user_transcription_event.user_transcript);
136
- if (this.onMessageCallback) {
137
- this.onMessageCallback(data.user_transcription_event.user_transcript, new HumanMessage(data.user_transcription_event.user_transcript));
138
- }
139
- break;
140
- case 'agent_response':
141
- if (this.onMessageCallback) {
142
- this.onMessageCallback(data.agent_response_event.agent_response, new AIMessage(data.agent_response_event.agent_response));
143
- }
144
- break;
145
- case 'interruption':
146
- console.debug('Interruption received');
147
- this.onInterruptionCallback?.();
148
- // Send interruption event to dashboard if connected
149
- if (getConfig().dashboardConnected) {
150
- try {
151
- this.agent.mindedConnection?.emit(MindedConnectionSocketMessageType.DASHBOARD_VOICE_INTERRUPTION, {
152
- type: MindedConnectionSocketMessageType.DASHBOARD_VOICE_INTERRUPTION,
153
- sessionId: this.sessionId,
154
- timestamp: Date.now(),
155
- });
156
- } catch (error) {
157
- console.error('[ElevenLabsVoice] Error sending interruption to dashboard', error);
158
- }
159
- }
160
- break;
161
- case 'audio':
162
- if (this.onAudioCallback) {
163
- this.onAudioCallback(data.audio_event.audio_base_64);
164
- }
165
- if (getConfig().dashboardConnected) {
166
- try {
167
- await this.agent.mindedConnection?.awaitEmit(MindedConnectionSocketMessageType.DASHBOARD_VOICE_AGENT_AUDIO, {
168
- sessionId: this.sessionId,
169
- audioData: data.audio_event.audio_base_64,
170
- });
171
- } catch (error) {
172
- console.error('[ElevenLabsVoice] Error sending audio to dashboard', error);
173
- }
174
- }
175
- break;
176
- case 'conversation_initiation_metadata':
177
- console.debug('ElevenLabs conversation initiation metadata', data);
178
- break;
179
- case 'agent_response_correction':
180
- try {
181
- console.debug('Agent response correction received', data.agent_response_correction_event);
182
- await this.updateAgentResponse(data.agent_response_correction_event.original_agent_response, data.agent_response_correction_event.corrected_agent_response);
183
- } catch (error) {
184
- console.error('[ElevenLabsVoice] Error updating agent response', error);
185
- }
186
- break;
187
- default:
188
- console.debug('Received unknown message from ElevenLabs', data);
189
- break;
190
- }
191
- };
192
- }
193
-
194
- private async updateAgentResponse(originalAgentResponse: string, correctedAgentResponse: string): Promise<void> {
195
- const graphState = await this.agent.compiledGraph.getState(this.agent.getLangraphConfig(this.sessionId));
196
- const agentMessage = graphState.values.messages.find((message: BaseMessage) => message.content === originalAgentResponse && message instanceof AIMessage);
197
- if (agentMessage) {
198
- agentMessage.content = correctedAgentResponse;
199
- const currentNodeId = graphState.tasks[graphState.tasks.length - 1].name;
200
- await this.agent.compiledGraph.updateState(this.agent.getLangraphConfig(this.sessionId), {
201
- messages: graphState.values.messages,
202
- }, currentNodeId);
203
- }
204
- else {
205
- console.warn('Agent message not found for correction', originalAgentResponse);
206
- }
207
- }
208
-
209
- public hangup(): void {
210
- this.onDisconnectCallback?.();
211
- this.elevenLabsSocket?.close();
212
- }
213
-
214
- /**
215
- * Set callback for audio data in base64 format
216
- */
217
- onAudio(callback: (data: string) => void): void {
218
- this.onAudioCallback = callback;
219
- }
220
-
221
- /**
222
- * Set callback for interruption events
223
- */
224
- onInterruption(callback: () => void): void {
225
- this.onInterruptionCallback = callback;
226
- }
227
-
228
- /**
229
- * Set callback for disconnect events
230
- */
231
- onDisconnect(callback: () => void): void {
232
- this.onDisconnectCallback = callback;
233
- }
234
-
235
- /**
236
- * User audio in base64 format
237
- */
238
- sendAudio(audioData: string): void {
239
- this.sendToElevenLabs(JSON.stringify({ user_audio_chunk: audioData }));
240
- }
241
- }
242
-
243
- // ----------------- Helper Types -----------------
244
-
245
- /** Shape of the message sent to ElevenLabs when starting a conversation */
246
- interface ConversationInitiationClientData {
247
- type: 'conversation_initiation_client_data';
248
- conversation_config_override: {
249
- agent: {
250
- first_message: string;
251
- language: string;
252
- };
253
- tts?: {
254
- voice_id: string;
255
- };
256
- };
257
- }