@minded-ai/mindedjs 1.0.52 → 1.0.53-patch-alpha
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/dist/agent.d.ts +17 -9
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +75 -5
- package/dist/agent.js.map +1 -1
- package/dist/cli/index.js +0 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/nodes/addPromptNode.d.ts.map +1 -1
- package/dist/nodes/addPromptNode.js +1 -0
- package/dist/nodes/addPromptNode.js.map +1 -1
- package/dist/platform/config.d.ts +3 -0
- package/dist/platform/config.d.ts.map +1 -1
- package/dist/platform/config.js +18 -1
- package/dist/platform/config.js.map +1 -1
- package/dist/platform/mindedConnection.d.ts +4 -4
- package/dist/platform/mindedConnection.d.ts.map +1 -1
- package/dist/platform/mindedConnection.js +8 -5
- package/dist/platform/mindedConnection.js.map +1 -1
- package/dist/platform/mindedConnectionTypes.d.ts +55 -2
- package/dist/platform/mindedConnectionTypes.d.ts.map +1 -1
- package/dist/platform/mindedConnectionTypes.js +11 -2
- package/dist/platform/mindedConnectionTypes.js.map +1 -1
- package/dist/types/Agent.types.d.ts +17 -0
- package/dist/types/Agent.types.d.ts.map +1 -1
- package/dist/types/Agent.types.js.map +1 -1
- package/dist/types/Flows.types.d.ts +12 -3
- package/dist/types/Flows.types.d.ts.map +1 -1
- package/dist/types/Flows.types.js +2 -0
- package/dist/types/Flows.types.js.map +1 -1
- package/dist/types/Voice.types.d.ts +5 -0
- package/dist/types/Voice.types.d.ts.map +1 -0
- package/dist/types/Voice.types.js +3 -0
- package/dist/types/Voice.types.js.map +1 -0
- package/dist/voice/elevenLabsUtils.d.ts +70 -0
- package/dist/voice/elevenLabsUtils.d.ts.map +1 -0
- package/dist/voice/elevenLabsUtils.js +20 -0
- package/dist/voice/elevenLabsUtils.js.map +1 -0
- package/dist/voice/voiceSession.d.ts +47 -0
- package/dist/voice/voiceSession.d.ts.map +1 -0
- package/dist/voice/voiceSession.js +208 -0
- package/dist/voice/voiceSession.js.map +1 -0
- package/package.json +5 -2
- package/src/agent.ts +91 -15
- package/src/index.ts +4 -0
- package/src/nodes/addPromptNode.ts +1 -0
- package/src/platform/config.ts +21 -1
- package/src/platform/mindedConnection.ts +15 -9
- package/src/platform/mindedConnectionTypes.ts +66 -2
- package/src/types/Agent.types.ts +18 -0
- package/src/types/Flows.types.ts +11 -1
- package/src/types/Voice.types.ts +4 -0
- package/src/voice/elevenLabsUtils.ts +101 -0
- package/src/voice/voiceSession.ts +251 -0
package/src/agent.ts
CHANGED
|
@@ -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, MindedConnectionSocketMessageType, OnAppTrigger } from './platform/mindedConnectionTypes';
|
|
14
|
+
import { BaseMindedConnectionSocketMessage, InvokeMessage, 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 { FlowHistoryType, MindedSDKConfig, TriggerInvocationHistory } from './types/Agent.types';
|
|
18
|
+
import { AgentInvokeParams, 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,6 +23,8 @@ 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';
|
|
26
28
|
|
|
27
29
|
type CreateAgentParams<Memory> = {
|
|
28
30
|
memorySchema: z.ZodSchema;
|
|
@@ -55,13 +57,14 @@ export class Agent {
|
|
|
55
57
|
private flows!: Flow[];
|
|
56
58
|
public tools!: Tool<any, any>[];
|
|
57
59
|
private llm!: BaseLanguageModel;
|
|
58
|
-
|
|
60
|
+
public mindedConnection: MindedConnection | null = null;
|
|
59
61
|
// Langgraph memory saver. In memory for local development, Custom for Platform
|
|
60
62
|
private checkpointer!: BaseCheckpointSaver;
|
|
61
63
|
// Langgraph compiled graph
|
|
62
|
-
|
|
64
|
+
public compiledGraph!: CompiledGraph;
|
|
63
65
|
// Cache for secrets to avoid repeated API calls
|
|
64
66
|
private secretsCache: Record<string, string> | null = null;
|
|
67
|
+
public config: MindedSDKConfig;
|
|
65
68
|
|
|
66
69
|
// Event handlers storage keyed by event name. Handlers can optionally return a value.
|
|
67
70
|
private eventHandlers: {
|
|
@@ -73,6 +76,9 @@ export class Agent {
|
|
|
73
76
|
private initialized = false;
|
|
74
77
|
private initPromise: Promise<void> | null = null;
|
|
75
78
|
|
|
79
|
+
// Add the voiceSessions property to the Agent class (place near other class fields)
|
|
80
|
+
public voiceSessions: Map<string, VoiceSession> = new Map();
|
|
81
|
+
|
|
76
82
|
/**
|
|
77
83
|
* Create a new Agent instance.
|
|
78
84
|
*
|
|
@@ -108,6 +114,7 @@ export class Agent {
|
|
|
108
114
|
const { memorySchema } = params;
|
|
109
115
|
this.memorySchema = memorySchema;
|
|
110
116
|
this.initPromise = this.init(params);
|
|
117
|
+
this.config = params.config;
|
|
111
118
|
}
|
|
112
119
|
|
|
113
120
|
private async init(params: CreateAgentParams<z.infer<typeof this.memorySchema>>): Promise<void> {
|
|
@@ -127,6 +134,17 @@ export class Agent {
|
|
|
127
134
|
sessionId: trigger.sessionId,
|
|
128
135
|
});
|
|
129
136
|
});
|
|
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
|
+
});
|
|
130
148
|
}
|
|
131
149
|
const [, flows] = (await Promise.all([this.loadSecrets(), this.loadFlows(config.flows)])) as [Record<string, string>, Flow[]];
|
|
132
150
|
this.flows = flows;
|
|
@@ -139,6 +157,10 @@ export class Agent {
|
|
|
139
157
|
this.llm = createLlmInstance(config.llm);
|
|
140
158
|
this.compiledGraph = this.initializeGraph();
|
|
141
159
|
this.initialized = true;
|
|
160
|
+
|
|
161
|
+
if (params.config.voice) {
|
|
162
|
+
this.setupVoice();
|
|
163
|
+
}
|
|
142
164
|
} catch (error) {
|
|
143
165
|
this.initialized = false;
|
|
144
166
|
throw error;
|
|
@@ -318,16 +340,11 @@ export class Agent {
|
|
|
318
340
|
triggerName,
|
|
319
341
|
sessionId,
|
|
320
342
|
appName,
|
|
321
|
-
}: {
|
|
322
|
-
triggerBody: any;
|
|
323
|
-
triggerName: string;
|
|
324
|
-
sessionId?: string;
|
|
325
|
-
appName?: string;
|
|
326
|
-
}) {
|
|
343
|
+
}: AgentInvokeParams) {
|
|
327
344
|
await this.waitForInitialization();
|
|
328
345
|
let messages: Array<BaseMessage> = [];
|
|
329
346
|
let memoryUpdate = {};
|
|
330
|
-
if (triggerName === KnownTriggerNames.DASHBOARD_MESSAGE) {
|
|
347
|
+
if (triggerName === KnownTriggerNames.DASHBOARD_MESSAGE || triggerName === KnownTriggerNames.VOICE_MESSAGE) {
|
|
331
348
|
messages.push(new HumanMessage(triggerBody.content));
|
|
332
349
|
} else {
|
|
333
350
|
const results = await this.emit(AgentEvents.TRIGGER_EVENT, {
|
|
@@ -362,8 +379,8 @@ export class Agent {
|
|
|
362
379
|
},
|
|
363
380
|
];
|
|
364
381
|
console.log(`Invoking trigger ${triggerName} with session ${sessionId}`);
|
|
365
|
-
const
|
|
366
|
-
const state = await this.compiledGraph.getState(
|
|
382
|
+
const langraphConfig = this.getLangraphConfig(sessionId || uuidv4());
|
|
383
|
+
const state = await this.compiledGraph.getState(langraphConfig);
|
|
367
384
|
// Resume interruption
|
|
368
385
|
if (state.tasks?.[0]?.interrupts?.length > 0) {
|
|
369
386
|
console.log('Resuming interruption');
|
|
@@ -371,13 +388,13 @@ export class Agent {
|
|
|
371
388
|
new Command({
|
|
372
389
|
resume: { memory: memoryUpdate, messages, history, triggerInvocations: [triggerInvocation] },
|
|
373
390
|
}),
|
|
374
|
-
|
|
391
|
+
langraphConfig,
|
|
375
392
|
);
|
|
376
393
|
return res;
|
|
377
394
|
} else {
|
|
378
395
|
const res = await this.compiledGraph.invoke(
|
|
379
396
|
{ messages, memory: memoryUpdate, history, triggerInvocations: [triggerInvocation] },
|
|
380
|
-
|
|
397
|
+
langraphConfig,
|
|
381
398
|
);
|
|
382
399
|
return res;
|
|
383
400
|
}
|
|
@@ -597,4 +614,63 @@ export class Agent {
|
|
|
597
614
|
throw new Error(`Failed to fetch secrets: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
598
615
|
}
|
|
599
616
|
}
|
|
617
|
+
|
|
618
|
+
public getLangraphConfig(sessionId: string): { configurable: { thread_id: string; recursionLimit: number } } {
|
|
619
|
+
return { configurable: { thread_id: sessionId, recursionLimit: 3 } };
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
private setupVoice(): void {
|
|
623
|
+
if (!this.mindedConnection) {
|
|
624
|
+
throw new Error('Minded connection is required');
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
const connection = this.mindedConnection;
|
|
628
|
+
const { dashboardConnected } = getConfig();
|
|
629
|
+
|
|
630
|
+
if (dashboardConnected) {
|
|
631
|
+
// Listen for voice session start
|
|
632
|
+
connection.on(MindedConnectionSocketMessageType.DASHBOARD_VOICE_SESSION_START, async (message) => {
|
|
633
|
+
const sessionStart = message as BaseVoiceMessage;
|
|
634
|
+
await this.startVoiceSession({ sessionId: sessionStart.sessionId });
|
|
635
|
+
});
|
|
636
|
+
|
|
637
|
+
// Listen for incoming audio from the platform
|
|
638
|
+
connection.on(MindedConnectionSocketMessageType.DASHBOARD_VOICE_USER_AUDIO, (message) => {
|
|
639
|
+
const audioMessage = message as OnVoiceAudioOut;
|
|
640
|
+
const voiceSession = this.voiceSessions.get(audioMessage.sessionId);
|
|
641
|
+
if (voiceSession) {
|
|
642
|
+
voiceSession.sendAudio(audioMessage.audioData);
|
|
643
|
+
} else {
|
|
644
|
+
console.warn({ message: 'Voice session not found for sessionId', sessionId: audioMessage.sessionId });
|
|
645
|
+
}
|
|
646
|
+
});
|
|
647
|
+
|
|
648
|
+
// Hangup / end session handler
|
|
649
|
+
connection.on(MindedConnectionSocketMessageType.DASHBOARD_VOICE_SESSION_END, (message) => {
|
|
650
|
+
const hangup = message as BaseVoiceMessage;
|
|
651
|
+
const voiceSession = this.voiceSessions.get(hangup.sessionId);
|
|
652
|
+
if (voiceSession) {
|
|
653
|
+
voiceSession.hangup();
|
|
654
|
+
} else {
|
|
655
|
+
console.warn({ message: 'Voice session not found for sessionId', sessionId: hangup.sessionId });
|
|
656
|
+
}
|
|
657
|
+
});
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
private async startVoiceSession(params: { sessionId: string }): Promise<VoiceSession> {
|
|
663
|
+
if (!this.config.voice) {
|
|
664
|
+
throw new Error('Voice configuration is required');
|
|
665
|
+
}
|
|
666
|
+
const voiceSession = new VoiceSession({
|
|
667
|
+
agent: this,
|
|
668
|
+
sessionId: params.sessionId,
|
|
669
|
+
firstMessage: this.config.voice.firstMessage,
|
|
670
|
+
voiceId: this.config.voice.voiceId,
|
|
671
|
+
});
|
|
672
|
+
await voiceSession.init();
|
|
673
|
+
this.voiceSessions.set(params.sessionId, voiceSession);
|
|
674
|
+
return voiceSession;
|
|
675
|
+
}
|
|
600
676
|
}
|
package/src/index.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Agent } from './agent';
|
|
2
2
|
import events from './events';
|
|
3
3
|
|
|
4
|
+
export type { ElevenLabsContext } from './types/Voice.types';
|
|
4
5
|
export { Agent, events };
|
|
5
6
|
|
|
6
7
|
export type {
|
|
@@ -17,8 +18,11 @@ export type {
|
|
|
17
18
|
JunctionNode,
|
|
18
19
|
ToolNode,
|
|
19
20
|
AppToolNode,
|
|
21
|
+
VoiceTriggerNode,
|
|
22
|
+
WebhookTriggerNode,
|
|
20
23
|
} from './types/Flows.types';
|
|
21
24
|
export { NodeType, TriggerType, EdgeType, AppNodeMetadata, AppNodeMetadataType, NodeMetadata, KnownTriggerNames } from './types/Flows.types';
|
|
22
25
|
export type { Tool } from './types/Tools.types';
|
|
23
26
|
export { FlowHistoryType, FlowHistory, TriggerInvocationHistory, AppActionInvocationHistory } from './types/Agent.types';
|
|
27
|
+
export type { AgentInvokeParams } from './types/Agent.types';
|
|
24
28
|
export type { Environment } from './types/Platform.types';
|
package/src/platform/config.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { resolve } from 'path';
|
|
2
2
|
import { config } from 'dotenv';
|
|
3
3
|
import { Environment } from '../types/Platform.types';
|
|
4
|
-
|
|
4
|
+
const path = resolve(__dirname, '../../.env');
|
|
5
|
+
console.log(`Loading config from ${path}`);
|
|
6
|
+
config({ path });
|
|
5
7
|
|
|
6
8
|
type MindedConfig = {
|
|
7
9
|
baseUrl: string;
|
|
@@ -9,6 +11,9 @@ type MindedConfig = {
|
|
|
9
11
|
token: string | null;
|
|
10
12
|
runLocally: boolean;
|
|
11
13
|
isDeployed: boolean;
|
|
14
|
+
dashboardConnected: boolean;
|
|
15
|
+
elevenLabsKey: string | null;
|
|
16
|
+
elevenLabsAgentId: string | null;
|
|
12
17
|
};
|
|
13
18
|
|
|
14
19
|
export const getConfig = (): MindedConfig => {
|
|
@@ -21,6 +26,9 @@ export const getConfig = (): MindedConfig => {
|
|
|
21
26
|
token: process.env.MINDED_CONNECTION_TOKEN || '',
|
|
22
27
|
runLocally: process.env.RUN_LOCALLY !== 'false',
|
|
23
28
|
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,
|
|
24
32
|
};
|
|
25
33
|
case 'development':
|
|
26
34
|
return {
|
|
@@ -29,6 +37,9 @@ export const getConfig = (): MindedConfig => {
|
|
|
29
37
|
token: process.env.MINDED_CONNECTION_TOKEN || '',
|
|
30
38
|
runLocally: process.env.RUN_LOCALLY === 'true',
|
|
31
39
|
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',
|
|
32
43
|
};
|
|
33
44
|
case 'sandbox-staging':
|
|
34
45
|
return {
|
|
@@ -37,6 +48,9 @@ export const getConfig = (): MindedConfig => {
|
|
|
37
48
|
token: process.env.MINDED_CONNECTION_TOKEN || '',
|
|
38
49
|
runLocally: false,
|
|
39
50
|
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',
|
|
40
54
|
};
|
|
41
55
|
case 'sandbox':
|
|
42
56
|
return {
|
|
@@ -45,6 +59,9 @@ export const getConfig = (): MindedConfig => {
|
|
|
45
59
|
token: process.env.MINDED_CONNECTION_TOKEN || '',
|
|
46
60
|
runLocally: false,
|
|
47
61
|
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',
|
|
48
65
|
};
|
|
49
66
|
case 'production':
|
|
50
67
|
return {
|
|
@@ -53,6 +70,9 @@ export const getConfig = (): MindedConfig => {
|
|
|
53
70
|
token: process.env.MINDED_CONNECTION_TOKEN || '',
|
|
54
71
|
runLocally: false,
|
|
55
72
|
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',
|
|
56
76
|
};
|
|
57
77
|
}
|
|
58
78
|
};
|
|
@@ -1,26 +1,29 @@
|
|
|
1
1
|
import { io, Socket } from 'socket.io-client';
|
|
2
|
-
import { BaseMindedConnectionSocketMessage, MindedConnectionSocketMessageType } from './mindedConnectionTypes';
|
|
2
|
+
import { BaseMindedConnectionSocketMessage, MindedConnectionSocketMessageType, MindedConnectionSocketMessageTypeMap } 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) => void)[];
|
|
9
|
+
[key: string]: ((message: BaseMindedConnectionSocketMessage, callback: (response: any) => void) => 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) => void) => {
|
|
16
|
+
public on = (event: MindedConnectionSocketMessageType, callback: (message: BaseMindedConnectionSocketMessage, callback: (response: any) => void) => 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 =
|
|
23
|
+
public emit = <E extends keyof MindedConnectionSocketMessageTypeMap>(
|
|
24
|
+
event: E,
|
|
25
|
+
message: MindedConnectionSocketMessageTypeMap[E]
|
|
26
|
+
) => {
|
|
24
27
|
if (this.socket) {
|
|
25
28
|
this.socket.emit(event, message);
|
|
26
29
|
}
|
|
@@ -34,7 +37,7 @@ export class MindedConnection {
|
|
|
34
37
|
return new Promise((resolve, reject) => {
|
|
35
38
|
// Set up timeout
|
|
36
39
|
const timeout = setTimeout(() => {
|
|
37
|
-
reject(new Error(`Acknowledgement timeout after ${timeoutMs}ms`));
|
|
40
|
+
reject(new Error(`Acknowledgement timeout after ${timeoutMs}ms; Message: ${message}`));
|
|
38
41
|
}, timeoutMs);
|
|
39
42
|
|
|
40
43
|
// Emit with acknowledgement callback
|
|
@@ -70,8 +73,8 @@ export class MindedConnection {
|
|
|
70
73
|
});
|
|
71
74
|
|
|
72
75
|
this.socket.on('connect_error', () => {
|
|
73
|
-
console.error('
|
|
74
|
-
reject(new Error('
|
|
76
|
+
console.error('Minded connection error');
|
|
77
|
+
reject(new Error('Minded connection error'));
|
|
75
78
|
});
|
|
76
79
|
|
|
77
80
|
this.socket.on('disconnect', () => {
|
|
@@ -96,12 +99,15 @@ export class MindedConnection {
|
|
|
96
99
|
});
|
|
97
100
|
|
|
98
101
|
// Listen for specific message types
|
|
99
|
-
this.socket.onAny((event, message) => {
|
|
102
|
+
this.socket.onAny((event, message, callback) => {
|
|
100
103
|
if (this.listeners[event]) {
|
|
101
104
|
this.listeners[event].forEach((listener) => {
|
|
102
|
-
listener(message);
|
|
105
|
+
listener(message, callback);
|
|
103
106
|
});
|
|
104
107
|
}
|
|
108
|
+
else {
|
|
109
|
+
console.warn({ message: 'No listeners found for event', event });
|
|
110
|
+
}
|
|
105
111
|
});
|
|
106
112
|
|
|
107
113
|
// Handle process termination
|
|
@@ -7,16 +7,43 @@ 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';
|
|
10
11
|
|
|
11
12
|
export enum MindedConnectionSocketMessageType {
|
|
12
13
|
OnAppTrigger = 'on-app-trigger',
|
|
13
14
|
OnAppAction = 'on-app-action',
|
|
15
|
+
GET_SECRETS = 'get-secrets',
|
|
16
|
+
GET_FLOWS = 'get-flows',
|
|
17
|
+
INVOKE = 'invoke',
|
|
18
|
+
// Checkpoints
|
|
14
19
|
CHECKPOINT_GET_TUPLE = 'checkpoint-get-tuple',
|
|
15
20
|
CHECKPOINT_PUT = 'checkpoint-put',
|
|
16
21
|
CHECKPOINT_LIST = 'checkpoint-list',
|
|
17
22
|
CHECKPOINT_PUT_WRITES = 'checkpoint-put-writes',
|
|
18
|
-
|
|
19
|
-
|
|
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;
|
|
20
47
|
}
|
|
21
48
|
|
|
22
49
|
export interface BaseMindedConnectionSocketMessage {
|
|
@@ -66,3 +93,40 @@ export interface OnCheckpointList extends BaseMindedConnectionSocketMessage {
|
|
|
66
93
|
export interface OnCheckpointListResponse extends BaseSdkConnectionSocketMessageResponseCallbackAck {
|
|
67
94
|
checkpoints?: CheckpointTuple[];
|
|
68
95
|
}
|
|
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
|
@@ -7,6 +7,24 @@ export type MindedSDKConfig = {
|
|
|
7
7
|
flows: string[];
|
|
8
8
|
llm: LLMConfig;
|
|
9
9
|
tools: string[];
|
|
10
|
+
voice?: {
|
|
11
|
+
firstMessage: string;
|
|
12
|
+
voiceId?: string;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Parameters for the Agent invoke method
|
|
18
|
+
*/
|
|
19
|
+
export interface AgentInvokeParams {
|
|
20
|
+
/** The payload/data associated with the trigger */
|
|
21
|
+
triggerBody: any;
|
|
22
|
+
/** The name/type of the trigger being invoked */
|
|
23
|
+
triggerName: string;
|
|
24
|
+
/** Optional session identifier for conversation continuity */
|
|
25
|
+
sessionId?: string;
|
|
26
|
+
/** Optional name of the application triggering the agent in case of an app trigger */
|
|
27
|
+
appName?: string;
|
|
10
28
|
}
|
|
11
29
|
|
|
12
30
|
export enum FlowHistoryType {
|
package/src/types/Flows.types.ts
CHANGED
|
@@ -30,6 +30,7 @@ export enum TriggerType {
|
|
|
30
30
|
APP = 'app',
|
|
31
31
|
WEBHOOK = 'webhook',
|
|
32
32
|
MANUAL = 'manual',
|
|
33
|
+
VOICE = 'voice',
|
|
33
34
|
}
|
|
34
35
|
|
|
35
36
|
export interface BaseTriggerNode extends BaseNode {
|
|
@@ -56,6 +57,14 @@ export interface WebhookTriggerNode extends BaseTriggerNode {
|
|
|
56
57
|
triggerType: TriggerType.WEBHOOK;
|
|
57
58
|
}
|
|
58
59
|
|
|
60
|
+
export interface VoiceTriggerNode extends BaseTriggerNode {
|
|
61
|
+
triggerType: TriggerType.VOICE;
|
|
62
|
+
/**
|
|
63
|
+
* Text that will be spoken as the very first message in a voice interaction.
|
|
64
|
+
*/
|
|
65
|
+
firstMessage: string;
|
|
66
|
+
}
|
|
67
|
+
|
|
59
68
|
export interface ManualTriggerNode extends BaseTriggerNode {
|
|
60
69
|
triggerType: TriggerType.MANUAL;
|
|
61
70
|
}
|
|
@@ -66,7 +75,7 @@ export interface PromptNode extends BaseNode {
|
|
|
66
75
|
llmConfig?: LLMConfig;
|
|
67
76
|
}
|
|
68
77
|
|
|
69
|
-
export type TriggerNode = AppTriggerNode | WebhookTriggerNode | ManualTriggerNode;
|
|
78
|
+
export type TriggerNode = AppTriggerNode | WebhookTriggerNode | ManualTriggerNode | VoiceTriggerNode;
|
|
70
79
|
|
|
71
80
|
export interface JunctionNode extends BaseNode {
|
|
72
81
|
type: NodeType.JUNCTION;
|
|
@@ -153,4 +162,5 @@ export interface Flow {
|
|
|
153
162
|
export enum KnownTriggerNames {
|
|
154
163
|
WEBHOOK = 'webhook',
|
|
155
164
|
DASHBOARD_MESSAGE = 'dashboard_message',
|
|
165
|
+
VOICE_MESSAGE = 'voice_message',
|
|
156
166
|
}
|
|
@@ -0,0 +1,101 @@
|
|
|
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
|
+
};
|