@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 +1 -4
- package/src/agent.ts +16 -93
- package/src/index.ts +0 -4
- package/src/nodes/addPromptNode.ts +0 -1
- package/src/platform/config.ts +1 -21
- package/src/platform/mindedConnection.ts +9 -15
- package/src/platform/mindedConnectionTypes.ts +2 -66
- package/src/types/Agent.types.ts +0 -14
- package/src/types/Flows.types.ts +1 -15
- package/dist/types/Voice.types.d.ts +0 -5
- package/dist/types/Voice.types.d.ts.map +0 -1
- package/dist/types/Voice.types.js +0 -3
- package/dist/types/Voice.types.js.map +0 -1
- package/dist/voice/elevenLabsUtils.d.ts +0 -70
- package/dist/voice/elevenLabsUtils.d.ts.map +0 -1
- package/dist/voice/elevenLabsUtils.js +0 -20
- package/dist/voice/elevenLabsUtils.js.map +0 -1
- package/dist/voice/voiceSession.d.ts +0 -47
- package/dist/voice/voiceSession.d.ts.map +0 -1
- package/dist/voice/voiceSession.js +0 -208
- package/dist/voice/voiceSession.js.map +0 -1
- package/src/types/Voice.types.ts +0 -4
- package/src/voice/elevenLabsUtils.ts +0 -101
- package/src/voice/voiceSession.ts +0 -257
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@minded-ai/mindedjs",
|
|
3
|
-
"version": "1.0.53
|
|
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
|
|
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,
|
|
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 {
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
}:
|
|
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
|
|
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
|
|
384
|
-
const state = await this.compiledGraph.getState(
|
|
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
|
-
|
|
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
|
-
|
|
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';
|
package/src/platform/config.ts
CHANGED
|
@@ -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
|
-
|
|
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
|
|
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
|
|
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
|
|
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 =
|
|
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
|
|
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('
|
|
77
|
-
reject(new 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
|
|
99
|
+
this.socket.onAny((event, message) => {
|
|
103
100
|
if (this.listeners[event]) {
|
|
104
101
|
this.listeners[event].forEach((listener) => {
|
|
105
|
-
listener(message
|
|
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
|
-
|
|
24
|
-
|
|
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
|
-
}
|
package/src/types/Agent.types.ts
CHANGED
|
@@ -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',
|
package/src/types/Flows.types.ts
CHANGED
|
@@ -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
|
|
69
|
+
export type TriggerNode = AppTriggerNode | WebhookTriggerNode | ManualTriggerNode;
|
|
84
70
|
|
|
85
71
|
export interface JunctionNode extends BaseNode {
|
|
86
72
|
type: NodeType.JUNCTION;
|
|
@@ -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 +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":";;;AAAA,2BAA+B;AAE/B,6EAE2C;AAC3C,+CAA+C;AAC/C,uDAG2B;AAC3B,uDAAgF;AAEhF;;GAEG;AACH,MAAa,YAAY;IAYvB,YAAY,EAAE,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,OAAO,EAA+E;QAClI,OAAO,CAAC,KAAK,CAAC,wBAAwB,EAAE,EAAE,SAAS,EAAE,YAAY,EAAE,OAAO,EAAE,CAAC,CAAC;QAC9E,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAC3B,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;QACjC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;IAED;;OAEG;IACI,KAAK,CAAC,IAAI;QACf,MAAM,EAAE,aAAa,EAAE,iBAAiB,EAAE,GAAG,IAAA,kBAAS,GAAE,CAAC;QAEzD,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAC;QAC1E,CAAC;QAED,IAAI,CAAC,iBAAiB,EAAE,CAAC;YACvB,MAAM,IAAI,KAAK,CAAC,gEAAgE,CAAC,CAAC;QACpF,CAAC;QAED,MAAM,SAAS,GAAG,MAAM,IAAA,8BAAY,EAAC;YACnC,OAAO,EAAE,iBAAiB;YAC1B,MAAM,EAAE,aAAa;SACtB,CAAC,CAAC;QAEH,IAAI,CAAC,gBAAgB,GAAG,IAAI,cAAS,CAAC,SAAS,CAAC,CAAC;QACjD,IAAI,CAAC,mBAAmB,EAAE,CAAC;IAC7B,CAAC;IAEO,KAAK,CAAC,gBAAgB,CAAC,OAAe;QAC5C,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAC3B,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;QAC5C,CAAC;QACD,MAAM,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;QACpD,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACtC,CAAC;IAEO,KAAK,CAAC,iBAAiB,CAAC,MAAiB;QAC/C,IAAI,MAAM,CAAC,UAAU,KAAK,cAAS,CAAC,IAAI,EAAE,CAAC;YACzC,OAAO;QACT,CAAC;QACD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACrC,MAAM,SAAS,GAAG,KAAK,CAAC;YACxB,MAAM,UAAU,GAAG,GAAG,CAAC;YACvB,IAAI,KAAK,GAAG,CAAC,CAAC;YACd,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,EAAE;gBAChC,IAAI,MAAM,CAAC,UAAU,KAAK,cAAS,CAAC,IAAI,EAAE,CAAC;oBACzC,aAAa,CAAC,QAAQ,CAAC,CAAC;oBACxB,OAAO,EAAE,CAAC;gBACZ,CAAC;gBACD,KAAK,EAAE,CAAC;gBACR,IAAI,KAAK,IAAI,SAAS,EAAE,CAAC;oBACvB,aAAa,CAAC,QAAQ,CAAC,CAAC;oBACxB,MAAM,CAAC,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC,CAAC;gBACvC,CAAC;YACH,CAAC,EAAE,UAAU,CAAC,CAAC;QACjB,CAAC,CAAC,CAAC;IACL,CAAC;IAEO,mBAAmB;QACzB,MAAM,MAAM,GAAG,IAAI,CAAC,gBAAiB,CAAC,CAAC,8DAA8D;QAErG,MAAM,CAAC,MAAM,GAAG,GAAG,EAAE;YACnB,OAAO,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAC;YAC7C,MAAM,cAAc,GAAqC;gBACvD,IAAI,EAAE,qCAAqC;gBAC3C,4BAA4B,EAAE;oBAC5B,KAAK,EAAE;wBACL,aAAa,EAAE,IAAI,CAAC,YAAY;wBAChC,QAAQ,EAAE,IAAI;qBACf;oBACD,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE,QAAQ,EAAE,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;iBACO;aACtE,CAAC;YAEF,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC,CAAC;YACtD,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,mBAAmB,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,WAAW,EAAE,IAAA,kBAAS,GAAE,CAAC,KAAM,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QAC7J,CAAC,CAAC;QAEF,MAAM,CAAC,OAAO,GAAG,GAAG,EAAE;;YACpB,OAAO,CAAC,KAAK,CAAC,kCAAkC,CAAC,CAAC;YAClD,MAAA,IAAI,CAAC,oBAAoB,oDAAI,CAAC;YAC9B,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAClD,CAAC,CAAC;QAEF,MAAM,CAAC,OAAO,GAAG,CAAC,GAAY,EAAE,EAAE;YAChC,OAAO,CAAC,KAAK,CAAC,mCAAmC,EAAE,GAAG,CAAC,CAAC;QAC1D,CAAC,CAAC;QAEF,MAAM,CAAC,SAAS,GAAG,KAAK,EAAE,KAAU,EAAE,EAAE;;YACtC,MAAM,IAAI,GAA6B,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;YAEzE,QAAQ,IAAI,CAAC,IAAI,EAAE,CAAC;gBAClB,KAAK,MAAM;oBACT,UAAU,CAAC,GAAG,EAAE;wBACd,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,CAAC,UAAU,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;oBAC9F,CAAC,EAAE,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;oBAC5B,MAAM;gBACR,KAAK,iBAAiB;oBACpB,OAAO,CAAC,KAAK,CAAC,0BAA0B,EAAE,IAAI,CAAC,wBAAwB,CAAC,eAAe,CAAC,CAAC;oBACzF,IAAI,IAAI,CAAC,iBAAiB,EAAE,CAAC;wBAC3B,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,wBAAwB,CAAC,eAAe,EAAE,IAAI,uBAAY,CAAC,IAAI,CAAC,wBAAwB,CAAC,eAAe,CAAC,CAAC,CAAC;oBACzI,CAAC;oBACD,MAAM;gBACR,KAAK,gBAAgB;oBACnB,IAAI,IAAI,CAAC,iBAAiB,EAAE,CAAC;wBAC3B,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,oBAAoB,CAAC,cAAc,EAAE,IAAI,oBAAS,CAAC,IAAI,CAAC,oBAAoB,CAAC,cAAc,CAAC,CAAC,CAAC;oBAC5H,CAAC;oBACD,MAAM;gBACR,KAAK,cAAc;oBACjB,OAAO,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC;oBACvC,MAAA,IAAI,CAAC,sBAAsB,oDAAI,CAAC;oBAChC,oDAAoD;oBACpD,IAAI,IAAA,kBAAS,GAAE,CAAC,kBAAkB,EAAE,CAAC;wBACnC,IAAI,CAAC;4BACH,MAAA,IAAI,CAAC,KAAK,CAAC,gBAAgB,0CAAE,IAAI,CAAC,yDAAiC,CAAC,4BAA4B,EAAE;gCAChG,IAAI,EAAE,yDAAiC,CAAC,4BAA4B;gCACpE,SAAS,EAAE,IAAI,CAAC,SAAS;gCACzB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;6BACtB,CAAC,CAAC;wBACL,CAAC;wBAAC,OAAO,KAAK,EAAE,CAAC;4BACf,OAAO,CAAC,KAAK,CAAC,2DAA2D,EAAE,KAAK,CAAC,CAAC;wBACpF,CAAC;oBACH,CAAC;oBACD,MAAM;gBACR,KAAK,OAAO;oBACV,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;wBACzB,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC;oBACvD,CAAC;oBACD,IAAI,IAAA,kBAAS,GAAE,CAAC,kBAAkB,EAAE,CAAC;wBACnC,IAAI,CAAC;4BACH,MAAM,CAAA,MAAA,IAAI,CAAC,KAAK,CAAC,gBAAgB,0CAAE,SAAS,CAAC,yDAAiC,CAAC,2BAA2B,EAAE;gCAC1G,SAAS,EAAE,IAAI,CAAC,SAAS;gCACzB,SAAS,EAAE,IAAI,CAAC,WAAW,CAAC,aAAa;6BAC1C,CAAC,CAAA,CAAC;wBACL,CAAC;wBAAC,OAAO,KAAK,EAAE,CAAC;4BACf,OAAO,CAAC,KAAK,CAAC,oDAAoD,EAAE,KAAK,CAAC,CAAC;wBAC7E,CAAC;oBACH,CAAC;oBACD,MAAM;gBACR,KAAK,kCAAkC;oBACrC,OAAO,CAAC,KAAK,CAAC,6CAA6C,EAAE,IAAI,CAAC,CAAC;oBACnE,MAAM;gBACR,KAAK,2BAA2B;oBAC9B,IAAI,CAAC;wBACH,OAAO,CAAC,KAAK,CAAC,oCAAoC,EAAE,IAAI,CAAC,+BAA+B,CAAC,CAAC;wBAC1F,MAAM,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,+BAA+B,CAAC,uBAAuB,EAAE,IAAI,CAAC,+BAA+B,CAAC,wBAAwB,CAAC,CAAC;oBAC9J,CAAC;oBAAC,OAAO,KAAK,EAAE,CAAC;wBACf,OAAO,CAAC,KAAK,CAAC,iDAAiD,EAAE,KAAK,CAAC,CAAC;oBAC1E,CAAC;oBACD,MAAM;gBACR;oBACE,OAAO,CAAC,KAAK,CAAC,0CAA0C,EAAE,IAAI,CAAC,CAAC;oBAChE,MAAM;YACV,CAAC;QACH,CAAC,CAAC;IACJ,CAAC;IAEO,KAAK,CAAC,mBAAmB,CAAC,qBAA6B,EAAE,sBAA8B;QAC7F,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,iBAAiB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;QACzG,MAAM,YAAY,GAAG,UAAU,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAoB,EAAE,EAAE,CAAC,OAAO,CAAC,OAAO,KAAK,qBAAqB,IAAI,OAAO,YAAY,oBAAS,CAAC,CAAC;QAC1J,IAAI,YAAY,EAAE,CAAC;YACjB,YAAY,CAAC,OAAO,GAAG,sBAAsB,CAAC;YAC9C,MAAM,aAAa,GAAG,UAAU,CAAC,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;YACzE,MAAM,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,iBAAiB,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE;gBACvF,QAAQ,EAAE,UAAU,CAAC,MAAM,CAAC,QAAQ;aACrC,EAAE,aAAa,CAAC,CAAC;QACpB,CAAC;aACI,CAAC;YACJ,OAAO,CAAC,IAAI,CAAC,wCAAwC,EAAE,qBAAqB,CAAC,CAAC;QAChF,CAAC;IACH,CAAC;IAEM,MAAM;;QACX,MAAA,IAAI,CAAC,oBAAoB,oDAAI,CAAC;QAC9B,MAAA,IAAI,CAAC,gBAAgB,0CAAE,KAAK,EAAE,CAAC;IACjC,CAAC;IAED;;OAEG;IACH,OAAO,CAAC,QAAgC;QACtC,IAAI,CAAC,eAAe,GAAG,QAAQ,CAAC;IAClC,CAAC;IAED;;OAEG;IACH,cAAc,CAAC,QAAoB;QACjC,IAAI,CAAC,sBAAsB,GAAG,QAAQ,CAAC;IACzC,CAAC;IAED;;OAEG;IACH,YAAY,CAAC,QAAoB;QAC/B,IAAI,CAAC,oBAAoB,GAAG,QAAQ,CAAC;IACvC,CAAC;IAED;;OAEG;IACH,SAAS,CAAC,SAAiB;QACzB,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,gBAAgB,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC;IACzE,CAAC;CACF;AA3ND,oCA2NC"}
|
package/src/types/Voice.types.ts
DELETED
|
@@ -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
|
-
}
|