@eka-care/medassist-core 1.0.0
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/README.md +32 -0
- package/dist/Synapse.d.ts +131 -0
- package/dist/Synapse.d.ts.map +1 -0
- package/dist/Synapse.js +479 -0
- package/dist/connection/ConnectionFactory.d.ts +17 -0
- package/dist/connection/ConnectionFactory.d.ts.map +1 -0
- package/dist/connection/ConnectionFactory.js +28 -0
- package/dist/connection/Websocket.d.ts +61 -0
- package/dist/connection/Websocket.d.ts.map +1 -0
- package/dist/connection/Websocket.js +184 -0
- package/dist/constants/index.d.ts +17 -0
- package/dist/constants/index.d.ts.map +1 -0
- package/dist/constants/index.js +28 -0
- package/dist/constants/types.d.ts +2 -0
- package/dist/constants/types.d.ts.map +1 -0
- package/dist/constants/types.js +2 -0
- package/dist/events/Events.d.ts +47 -0
- package/dist/events/Events.d.ts.map +1 -0
- package/dist/events/Events.js +46 -0
- package/dist/events/Incoming.d.ts +2 -0
- package/dist/events/Incoming.d.ts.map +1 -0
- package/dist/events/Incoming.js +2 -0
- package/dist/events/Outgoing.d.ts +2 -0
- package/dist/events/Outgoing.d.ts.map +1 -0
- package/dist/events/Outgoing.js +2 -0
- package/dist/events/index.d.ts +3 -0
- package/dist/events/index.d.ts.map +1 -0
- package/dist/events/index.js +38 -0
- package/dist/events/types.d.ts +86 -0
- package/dist/events/types.d.ts.map +1 -0
- package/dist/events/types.js +6 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +69 -0
- package/dist/internal/Api/BaseResource.d.ts +35 -0
- package/dist/internal/Api/BaseResource.d.ts.map +1 -0
- package/dist/internal/Api/BaseResource.js +54 -0
- package/dist/internal/Api/HttpClient.d.ts +25 -0
- package/dist/internal/Api/HttpClient.d.ts.map +1 -0
- package/dist/internal/Api/HttpClient.js +131 -0
- package/dist/internal/Api/types.d.ts +7 -0
- package/dist/internal/Api/types.d.ts.map +1 -0
- package/dist/internal/Api/types.js +2 -0
- package/dist/internal/Error/Error.d.ts +97 -0
- package/dist/internal/Error/Error.d.ts.map +1 -0
- package/dist/internal/Error/Error.js +243 -0
- package/dist/internal/Error/types.d.ts +17 -0
- package/dist/internal/Error/types.d.ts.map +1 -0
- package/dist/internal/Error/types.js +12 -0
- package/dist/internal/connection/BaseConnection.d.ts +100 -0
- package/dist/internal/connection/BaseConnection.d.ts.map +1 -0
- package/dist/internal/connection/BaseConnection.js +138 -0
- package/dist/internal/connection/types.d.ts +43 -0
- package/dist/internal/connection/types.d.ts.map +1 -0
- package/dist/internal/connection/types.js +20 -0
- package/dist/internal/events/EventEmitter.d.ts +7 -0
- package/dist/internal/events/EventEmitter.d.ts.map +1 -0
- package/dist/internal/events/EventEmitter.js +27 -0
- package/dist/internal/store/index.d.ts +10 -0
- package/dist/internal/store/index.d.ts.map +1 -0
- package/dist/internal/store/index.js +9 -0
- package/dist/media/audio/Audio.d.ts +37 -0
- package/dist/media/audio/Audio.d.ts.map +1 -0
- package/dist/media/audio/Audio.js +310 -0
- package/dist/media/audio/types.d.ts +25 -0
- package/dist/media/audio/types.d.ts.map +1 -0
- package/dist/media/audio/types.js +10 -0
- package/dist/media/file/File.d.ts +54 -0
- package/dist/media/file/File.d.ts.map +1 -0
- package/dist/media/file/File.js +159 -0
- package/dist/messages/MessageManager.d.ts +79 -0
- package/dist/messages/MessageManager.d.ts.map +1 -0
- package/dist/messages/MessageManager.js +420 -0
- package/dist/messages/types.d.ts +74 -0
- package/dist/messages/types.d.ts.map +1 -0
- package/dist/messages/types.js +34 -0
- package/dist/resources/config/Config.d.ts +5 -0
- package/dist/resources/config/Config.d.ts.map +1 -0
- package/dist/resources/config/Config.js +5 -0
- package/dist/resources/index.d.ts +34 -0
- package/dist/resources/index.d.ts.map +1 -0
- package/dist/resources/index.js +108 -0
- package/dist/resources/session/Session.d.ts +21 -0
- package/dist/resources/session/Session.d.ts.map +1 -0
- package/dist/resources/session/Session.js +39 -0
- package/dist/resources/session/types.d.ts +17 -0
- package/dist/resources/session/types.d.ts.map +1 -0
- package/dist/resources/session/types.js +8 -0
- package/dist/resources/types.d.ts +22 -0
- package/dist/resources/types.d.ts.map +1 -0
- package/dist/resources/types.js +5 -0
- package/dist/types/index.d.ts +8 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +24 -0
- package/dist/utils/Error.d.ts +45 -0
- package/dist/utils/Error.d.ts.map +1 -0
- package/dist/utils/Error.js +114 -0
- package/package.json +41 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MessageManager.d.ts","sourceRoot":"","sources":["../../src/messages/MessageManager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,KAAK,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEtD,OAAO,EAIL,KAAK,yBAAyB,EAC9B,KAAK,2BAA2B,EAChC,KAAK,0BAA0B,EAC/B,KAAK,gCAAgC,EACtC,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAEvE,OAAO,EAGL,KAAK,qBAAqB,EAI3B,MAAM,SAAS,CAAC;AAWjB,OAAO,EACL,KAAK,oBAAoB,EAC1B,MAAM,8BAA8B,CAAC;AACtC,qBAAa,cAAc;IACzB,OAAO,CAAC,UAAU,CAA+B;IACjD,OAAO,CAAC,SAAS,CAAoC;IACrD,OAAO,CAAC,WAAW,CAA4B;IAC/C,OAAO,CAAC,YAAY,CAA6B;gBAErC,UAAU,EAAE,cAAc,EAAE,SAAS,CAAC,EAAE,mBAAmB;IAIvE;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAiD/B;;OAEG;IACI,qBAAqB,CAAC,EAC3B,OAAO,EACP,SAAS,EACT,IAAI,EACJ,KAAK,EACL,GAAG,EACH,WAAW,EACX,eAAe,EACf,MAAM,GACP,EAAE,qBAAqB,GAAG,IAAI;IA4C/B;;OAEG;IACI,+BAA+B,CACpC,OAAO,EAAE,yBAAyB,GACjC,IAAI;IAqFP;;OAEG;IACI,iCAAiC,CACtC,OAAO,EAAE,2BAA2B,GACnC,IAAI;IAsDA,gBAAgB,CAAC,OAAO,EAAE,oBAAoB,GAAG,IAAI;IAI5D;;OAEG;IACI,sCAAsC,CAC3C,QAAQ,EAAE,gCAAgC,GACzC,IAAI;IAOP;;OAEG;IACI,gCAAgC,CACrC,OAAO,EAAE,0BAA0B,GAClC,IAAI;IAoBP;;OAEG;IACI,qBAAqB,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI;IAWxD;;OAEG;IACI,qBAAqB,IAAI,IAAI;IAUpC;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAkC/B;;OAEG;IACI,wBAAwB,IAAI,IAAI;IAiCvC;;OAEG;IACI,sBAAsB,IAAI,IAAI;IAsBrC;;OAEG;IACI,qBAAqB,IAAI,IAAI;IAU7B,2BAA2B,IAAI,IAAI;IAM1C;;OAEG;IACI,yBAAyB,IAAI,IAAI;IAWxC;;OAEG;IACH,OAAO,CAAC,UAAU;IAIlB,OAAO,CAAC,SAAS;IAIjB,OAAO,CAAC,WAAW;IAYnB,OAAO,CAAC,gBAAgB;IAYxB,OAAO,CAAC,gBAAgB;CAsCzB"}
|
|
@@ -0,0 +1,420 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MessageManager = void 0;
|
|
4
|
+
const Events_1 = require("../events/Events");
|
|
5
|
+
const File_1 = require("../media/file/File");
|
|
6
|
+
const types_1 = require("./types");
|
|
7
|
+
const Audio_1 = require("../media/audio/Audio");
|
|
8
|
+
const types_2 = require("../media/audio/types");
|
|
9
|
+
const Error_1 = require("../internal/Error/Error");
|
|
10
|
+
class MessageManager {
|
|
11
|
+
connection = null;
|
|
12
|
+
callbacks = null;
|
|
13
|
+
fileManager = null;
|
|
14
|
+
audioManager = null;
|
|
15
|
+
constructor(connection, callbacks) {
|
|
16
|
+
this.connection = connection || null;
|
|
17
|
+
this.callbacks = callbacks || null;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Handle file upload process
|
|
21
|
+
*/
|
|
22
|
+
handleFileUploadProcess({ files, messageId, message, url, }) {
|
|
23
|
+
if (!this.fileManager) {
|
|
24
|
+
this.fileManager = new File_1.Filemanager();
|
|
25
|
+
}
|
|
26
|
+
let fileUploadMessage;
|
|
27
|
+
if (files && files.length > 0) {
|
|
28
|
+
//stage 1. of file upload process
|
|
29
|
+
//--store files temproary in memory
|
|
30
|
+
this.fileManager.setFilesForUpload(files, messageId, message);
|
|
31
|
+
fileUploadMessage = {
|
|
32
|
+
ev: Events_1.SOCKET_EVENTS.CHAT,
|
|
33
|
+
ct: Events_1.SOCKET_CONTENT_TYPES.FILE,
|
|
34
|
+
_id: messageId || Date.now().toString(),
|
|
35
|
+
ts: Date.now(),
|
|
36
|
+
data: {
|
|
37
|
+
extension: this.fileManager.getPendingFileState().format,
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
else if (url) {
|
|
42
|
+
//--stage 3. of file upload process
|
|
43
|
+
//--only requirement is url
|
|
44
|
+
//--send file upload acknowledgement to client
|
|
45
|
+
const text = this.fileManager.getPendingFileState().message;
|
|
46
|
+
fileUploadMessage = {
|
|
47
|
+
ev: Events_1.SOCKET_EVENTS.CHAT,
|
|
48
|
+
ct: Events_1.SOCKET_CONTENT_TYPES.FILE,
|
|
49
|
+
_id: this.fileManager.getPendingFileState().messageId,
|
|
50
|
+
ts: Date.now(),
|
|
51
|
+
data: {
|
|
52
|
+
url: url,
|
|
53
|
+
...(text && { text }),
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
this.fileManager?.clearPendingFilesState();
|
|
57
|
+
}
|
|
58
|
+
return fileUploadMessage;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* send chat message through socket
|
|
62
|
+
*/
|
|
63
|
+
sendSocketChatMessage({ message, messageId, type, files, url, tool_use_id, tool_use_params, hidden, }) {
|
|
64
|
+
const connection = this.assertConnection("sendSocketChatMessage");
|
|
65
|
+
let outMessage;
|
|
66
|
+
switch (type) {
|
|
67
|
+
case Events_1.SOCKET_CONTENT_TYPES.FILE:
|
|
68
|
+
outMessage = this.handleFileUploadProcess({
|
|
69
|
+
files,
|
|
70
|
+
messageId,
|
|
71
|
+
message,
|
|
72
|
+
url,
|
|
73
|
+
});
|
|
74
|
+
break;
|
|
75
|
+
case Events_1.SOCKET_CONTENT_TYPES.TEXT:
|
|
76
|
+
outMessage = {
|
|
77
|
+
ev: Events_1.SOCKET_EVENTS.CHAT,
|
|
78
|
+
ct: type,
|
|
79
|
+
_id: messageId || Date.now().toString(),
|
|
80
|
+
ts: Date.now(),
|
|
81
|
+
data: {
|
|
82
|
+
text: message,
|
|
83
|
+
...(tool_use_id && { tool_use_id }),
|
|
84
|
+
...(tool_use_params && { tool_use_params }),
|
|
85
|
+
...(hidden && { hidden }),
|
|
86
|
+
},
|
|
87
|
+
};
|
|
88
|
+
break;
|
|
89
|
+
default:
|
|
90
|
+
const error = new Error_1.MessageError("Unsupported content type", {
|
|
91
|
+
context: { stage: "sendSocketChatMessage", type },
|
|
92
|
+
hint: "Use SOCKET_CONTENT_TYPES.FILE or SOCKET_CONTENT_TYPES.TEXT.",
|
|
93
|
+
});
|
|
94
|
+
this.emitError(error);
|
|
95
|
+
throw error;
|
|
96
|
+
}
|
|
97
|
+
if (!outMessage) {
|
|
98
|
+
const error = new Error_1.MessageError("No message to send", {
|
|
99
|
+
context: { stage: "sendSocketChatMessage", type },
|
|
100
|
+
});
|
|
101
|
+
this.emitError(error);
|
|
102
|
+
throw error;
|
|
103
|
+
}
|
|
104
|
+
connection.sendMessage(outMessage);
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Handle incoming chat message
|
|
108
|
+
*/
|
|
109
|
+
handleIncomingSocketChatMessage(message) {
|
|
110
|
+
const connection = this.assertConnection("handleIncomingSocketChatMessage");
|
|
111
|
+
switch (message.ct) {
|
|
112
|
+
case Events_1.SOCKET_CONTENT_TYPES.FILE: {
|
|
113
|
+
if (message?.data?.urls && message.data.urls?.length > 0) {
|
|
114
|
+
//stage 2. of file upload process
|
|
115
|
+
this.fileManager
|
|
116
|
+
?.uploadFilesToPresignedUrl(message.data.urls)
|
|
117
|
+
.then(() => {
|
|
118
|
+
this.sendSocketChatMessage({
|
|
119
|
+
type: Events_1.SOCKET_CONTENT_TYPES.FILE,
|
|
120
|
+
url: message.data.urls?.[0],
|
|
121
|
+
});
|
|
122
|
+
})
|
|
123
|
+
.catch((error) => {
|
|
124
|
+
const fileError = this.toFileError(error, "Failed to upload files to presigned URL", {
|
|
125
|
+
stage: "handleIncomingSocketChatMessage",
|
|
126
|
+
urls: message.data?.urls?.length,
|
|
127
|
+
});
|
|
128
|
+
this.emitError(fileError);
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
break;
|
|
132
|
+
}
|
|
133
|
+
case Events_1.SOCKET_CONTENT_TYPES.TEXT:
|
|
134
|
+
if (message.data.text &&
|
|
135
|
+
message.data.text.trim() === "" &&
|
|
136
|
+
message._id) {
|
|
137
|
+
const messageData = {
|
|
138
|
+
data: { text: message.data.text },
|
|
139
|
+
// type: message.ct,
|
|
140
|
+
messageId: message._id,
|
|
141
|
+
timestamp: message.ts,
|
|
142
|
+
};
|
|
143
|
+
connection.emit(types_1.SYNAPSE_REALTIME_EVENTS.MESSAGE_CHUNK, messageData);
|
|
144
|
+
}
|
|
145
|
+
break;
|
|
146
|
+
case Events_1.SOCKET_CONTENT_TYPES.PILL:
|
|
147
|
+
case Events_1.SOCKET_CONTENT_TYPES.MULTI:
|
|
148
|
+
// case SOCKET_CONTENT_TYPES.DOCTOR_CARD:
|
|
149
|
+
if (message?.data?.tool_use_id && message._id) {
|
|
150
|
+
const chatMessageData = {
|
|
151
|
+
data: { ...message.data, type: message.ct },
|
|
152
|
+
// type: message.ct,
|
|
153
|
+
messageId: message._id,
|
|
154
|
+
timestamp: message.ts,
|
|
155
|
+
};
|
|
156
|
+
connection.emit(types_1.SYNAPSE_REALTIME_EVENTS.TOOL_ESCALATION, chatMessageData);
|
|
157
|
+
// this.callbacks?.onElicitationTool?.(chatMessageData, message._id);
|
|
158
|
+
}
|
|
159
|
+
break;
|
|
160
|
+
case Events_1.SOCKET_CONTENT_TYPES.INLINE_TEXT:
|
|
161
|
+
if (message?.data?.text) {
|
|
162
|
+
const messageData = {
|
|
163
|
+
data: { text: message.data.text },
|
|
164
|
+
// type: message.ct,
|
|
165
|
+
messageId: message._id,
|
|
166
|
+
timestamp: message.ts,
|
|
167
|
+
};
|
|
168
|
+
connection.emit(types_1.SYNAPSE_REALTIME_EVENTS.INLINE_TEXT, messageData);
|
|
169
|
+
this.callbacks?.onRecordingStatusChange?.(types_2.AudioRecordingStatus.IDLE);
|
|
170
|
+
// this.callbacks?.onChatmessage?.(message.data.text, message.ct);
|
|
171
|
+
}
|
|
172
|
+
break;
|
|
173
|
+
default:
|
|
174
|
+
const error = new Error_1.MessageError("Unsupported content type", {
|
|
175
|
+
context: {
|
|
176
|
+
stage: "handleIncomingSocketChatMessage",
|
|
177
|
+
contentType: message.ct,
|
|
178
|
+
},
|
|
179
|
+
});
|
|
180
|
+
this.emitError(error);
|
|
181
|
+
throw error;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Handle incoming stream message
|
|
186
|
+
*/
|
|
187
|
+
handleIncomingSocketStreamMessage(message) {
|
|
188
|
+
const connection = this.assertConnection("handleIncomingSocketStreamMessage");
|
|
189
|
+
switch (message.ct) {
|
|
190
|
+
case Events_1.SOCKET_CONTENT_TYPES.TEXT:
|
|
191
|
+
if (message?.data?.progress_msg) {
|
|
192
|
+
const messageData = {
|
|
193
|
+
data: { text: message.data.progress_msg },
|
|
194
|
+
// type: message.ct,
|
|
195
|
+
messageId: message._id,
|
|
196
|
+
timestamp: message.ts,
|
|
197
|
+
};
|
|
198
|
+
connection.emit(types_1.SYNAPSE_REALTIME_EVENTS.PROGRESS_MESSAGE, messageData);
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
if (message?.data?.text) {
|
|
202
|
+
const messageData = {
|
|
203
|
+
data: { text: message.data.text },
|
|
204
|
+
// type: message.ct,
|
|
205
|
+
messageId: message._id,
|
|
206
|
+
timestamp: message.ts,
|
|
207
|
+
};
|
|
208
|
+
//the ui layer will handle the aggregation logic for stream messages
|
|
209
|
+
connection.emit(types_1.SYNAPSE_REALTIME_EVENTS.MESSAGE_CHUNK, messageData);
|
|
210
|
+
}
|
|
211
|
+
break;
|
|
212
|
+
case Events_1.SOCKET_CONTENT_TYPES.TIPS:
|
|
213
|
+
if (message?.data?.tips) {
|
|
214
|
+
const messageData = {
|
|
215
|
+
data: { tips: message.data.tips },
|
|
216
|
+
// type: message.ct,
|
|
217
|
+
messageId: message._id,
|
|
218
|
+
timestamp: message.ts,
|
|
219
|
+
};
|
|
220
|
+
connection.emit(types_1.SYNAPSE_REALTIME_EVENTS.TIPS_MESSAGE, messageData);
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
break;
|
|
224
|
+
default:
|
|
225
|
+
const error = new Error_1.MessageError("Unsupported content type", {
|
|
226
|
+
context: {
|
|
227
|
+
stage: "handleIncomingSocketStreamMessage",
|
|
228
|
+
contentType: message.ct,
|
|
229
|
+
},
|
|
230
|
+
});
|
|
231
|
+
this.emitError(error);
|
|
232
|
+
throw error;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
handleDisconnect(details) {
|
|
236
|
+
this.connection?.emit?.(types_1.SYNAPSE_REALTIME_EVENTS.DISCONNECTED, details);
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Handle incoming end of stream message
|
|
240
|
+
*/
|
|
241
|
+
handleIncomingSocketEndOfStreamMessage(_message) {
|
|
242
|
+
const connection = this.assertConnection("handleIncomingSocketEndOfStreamMessage");
|
|
243
|
+
connection.emit(types_1.SYNAPSE_REALTIME_EVENTS.END_OF_STREAM);
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Handle incoming error message
|
|
247
|
+
*/
|
|
248
|
+
handleIncomingSocketErrorMessage(message) {
|
|
249
|
+
const connection = this.assertConnection("handleIncomingSocketErrorMessage");
|
|
250
|
+
switch (message.code) {
|
|
251
|
+
case types_1.SYNAPSE_REALTIME_ERROR_CODES.SESSION_EXPIRED:
|
|
252
|
+
connection.emit(types_1.SYNAPSE_REALTIME_RESERVED_EVENTS.SESSION_EXPIRED);
|
|
253
|
+
break;
|
|
254
|
+
default:
|
|
255
|
+
const error = new Error_1.MessageError(message.msg || "Socket error received", {
|
|
256
|
+
context: {
|
|
257
|
+
stage: "handleIncomingSocketErrorMessage",
|
|
258
|
+
errorCode: message.code,
|
|
259
|
+
},
|
|
260
|
+
});
|
|
261
|
+
connection.emit(types_1.SYNAPSE_REALTIME_EVENTS.ERROR, error);
|
|
262
|
+
this.emitError(error);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* send authentication message
|
|
267
|
+
*/
|
|
268
|
+
sendSocketAuthMessage(sessionToken) {
|
|
269
|
+
const connection = this.assertConnection("sendSocketAuthMessage");
|
|
270
|
+
const authMessage = {
|
|
271
|
+
ev: Events_1.SOCKET_EVENTS.AUTH,
|
|
272
|
+
_id: Date.now().toString(),
|
|
273
|
+
ts: Date.now(),
|
|
274
|
+
data: { token: sessionToken },
|
|
275
|
+
};
|
|
276
|
+
connection.sendMessage(authMessage);
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* send ping message
|
|
280
|
+
*/
|
|
281
|
+
sendSocketPingMessage() {
|
|
282
|
+
const connection = this.assertConnection("sendSocketPingMessage");
|
|
283
|
+
const pingMessage = {
|
|
284
|
+
ev: Events_1.SOCKET_EVENTS.PING,
|
|
285
|
+
_id: Date.now().toString(),
|
|
286
|
+
ts: Date.now(),
|
|
287
|
+
};
|
|
288
|
+
connection.sendMessage(pingMessage);
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* start recording audio
|
|
292
|
+
*/
|
|
293
|
+
sendSocketStreamMessage({ data, type, messageId, timestamp, }) {
|
|
294
|
+
const connection = this.assertConnection("sendSocketStreamMessage");
|
|
295
|
+
switch (type) {
|
|
296
|
+
case Events_1.SOCKET_CONTENT_TYPES.AUDIO:
|
|
297
|
+
const message = {
|
|
298
|
+
ev: Events_1.SOCKET_EVENTS.STREAM,
|
|
299
|
+
ct: type,
|
|
300
|
+
_id: messageId || this.generateId(),
|
|
301
|
+
ts: timestamp || Date.now(),
|
|
302
|
+
data: {
|
|
303
|
+
audio: data.audio,
|
|
304
|
+
format: data.format,
|
|
305
|
+
},
|
|
306
|
+
};
|
|
307
|
+
connection.sendMessage(message);
|
|
308
|
+
break;
|
|
309
|
+
default:
|
|
310
|
+
const error = new Error_1.MessageError("Unsupported content type", {
|
|
311
|
+
context: { stage: "sendSocketStreamMessage", contentType: type },
|
|
312
|
+
});
|
|
313
|
+
this.emitError(error);
|
|
314
|
+
throw error;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* send audio message
|
|
319
|
+
*/
|
|
320
|
+
startRecordingWithSocket() {
|
|
321
|
+
this.assertConnection("startRecording");
|
|
322
|
+
if (!this.audioManager) {
|
|
323
|
+
this.audioManager = new Audio_1.AudioManager();
|
|
324
|
+
}
|
|
325
|
+
this.audioManager
|
|
326
|
+
.start((audioData) => {
|
|
327
|
+
this.sendSocketStreamMessage({
|
|
328
|
+
data: audioData,
|
|
329
|
+
type: Events_1.SOCKET_CONTENT_TYPES.AUDIO,
|
|
330
|
+
});
|
|
331
|
+
}, this.callbacks?.onRecordingStatusChange ?? undefined, (error) => {
|
|
332
|
+
const recordingError = this.toRecordingError(error, "Audio recording error", { stage: "startRecording" });
|
|
333
|
+
this.emitError(recordingError);
|
|
334
|
+
})
|
|
335
|
+
.catch((error) => {
|
|
336
|
+
const recordingError = this.toRecordingError(error, "Failed to start audio recording", { stage: "startRecording" });
|
|
337
|
+
this.emitError(recordingError);
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* stop recording audio
|
|
342
|
+
*/
|
|
343
|
+
endRecordingWithSocket() {
|
|
344
|
+
if (!this.audioManager) {
|
|
345
|
+
const error = new Error_1.RecordingError("Audio manager not set. Call startRecording() first.", { context: { stage: "stopRecording" } });
|
|
346
|
+
this.emitError(error);
|
|
347
|
+
throw error;
|
|
348
|
+
}
|
|
349
|
+
try {
|
|
350
|
+
this.audioManager.stop();
|
|
351
|
+
}
|
|
352
|
+
catch (error) {
|
|
353
|
+
const recordingError = this.toRecordingError(error, "Failed to stop audio recording", { stage: "stopRecording" });
|
|
354
|
+
this.emitError(recordingError);
|
|
355
|
+
throw recordingError;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* send pong message
|
|
360
|
+
*/
|
|
361
|
+
sendSocketPongMessage() {
|
|
362
|
+
const connection = this.assertConnection("sendSocketPongMessage");
|
|
363
|
+
const pongMessage = {
|
|
364
|
+
ev: Events_1.SOCKET_EVENTS.PONG,
|
|
365
|
+
_id: Date.now().toString(),
|
|
366
|
+
ts: Date.now(),
|
|
367
|
+
};
|
|
368
|
+
connection.sendMessage(pongMessage);
|
|
369
|
+
}
|
|
370
|
+
handleConnectionEstablished() {
|
|
371
|
+
this.connection?.handleConnected(); //this will call the onConnectionStatusChange callback with connected
|
|
372
|
+
this.connection?.emit(types_1.SYNAPSE_REALTIME_EVENTS.CONNECTED);
|
|
373
|
+
// this.connection?.handleConnected();
|
|
374
|
+
}
|
|
375
|
+
/**
|
|
376
|
+
* Cleanup message service
|
|
377
|
+
*/
|
|
378
|
+
cleanupMessageServerState() {
|
|
379
|
+
if (this.fileManager) {
|
|
380
|
+
this.fileManager.clearPendingFilesState();
|
|
381
|
+
this.fileManager = null;
|
|
382
|
+
}
|
|
383
|
+
if (this.audioManager) {
|
|
384
|
+
this.audioManager.destroy();
|
|
385
|
+
this.audioManager = null;
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
/**
|
|
389
|
+
* Generate a unique message ID
|
|
390
|
+
*/
|
|
391
|
+
generateId() {
|
|
392
|
+
return `msg_${Date.now()}_${Math.random().toString(36).substring(2, 15)}`;
|
|
393
|
+
}
|
|
394
|
+
emitError(error) {
|
|
395
|
+
this.callbacks?.onError?.(error);
|
|
396
|
+
}
|
|
397
|
+
toFileError(error, fallbackMessage, context, hint) {
|
|
398
|
+
return (0, Error_1.normalizeError)(error, Error_1.FileError, fallbackMessage, {
|
|
399
|
+
context,
|
|
400
|
+
hint,
|
|
401
|
+
});
|
|
402
|
+
}
|
|
403
|
+
toRecordingError(error, fallbackMessage, context, hint) {
|
|
404
|
+
return (0, Error_1.normalizeError)(error, Error_1.RecordingError, fallbackMessage, {
|
|
405
|
+
context,
|
|
406
|
+
hint,
|
|
407
|
+
});
|
|
408
|
+
}
|
|
409
|
+
assertConnection(stage) {
|
|
410
|
+
if (!this.connection) {
|
|
411
|
+
const error = new Error_1.ConnectionError("Connection not set. Please ensure the connection is established before calling this method.", {
|
|
412
|
+
context: { stage },
|
|
413
|
+
});
|
|
414
|
+
this.emitError(error);
|
|
415
|
+
throw error;
|
|
416
|
+
}
|
|
417
|
+
return this.connection;
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
exports.MessageManager = MessageManager;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Types for message management
|
|
3
|
+
*/
|
|
4
|
+
import { SOCKET_CONTENT_TYPES, type IncomingSocketMessage, type OutgoingSocketMessage, MULTI_SELECT_ADDITIONAL_OPTION } from "../events/Events";
|
|
5
|
+
import { type AudioMetaData } from "../media/audio/types";
|
|
6
|
+
export declare const SYNAPSE_MESSAGE_TYPES: {
|
|
7
|
+
readonly TEXT: "text";
|
|
8
|
+
readonly AUDIO: "audio";
|
|
9
|
+
readonly FILE: "file";
|
|
10
|
+
readonly PILL: "pill";
|
|
11
|
+
readonly MULTI: "multi";
|
|
12
|
+
readonly DOCTOR_CARD: "doctor_card";
|
|
13
|
+
readonly TIPS: "tips";
|
|
14
|
+
readonly INLINE_TEXT: "inline_text";
|
|
15
|
+
readonly MOBILE_VERIFICATION: "mobile_verification";
|
|
16
|
+
};
|
|
17
|
+
export type ContentType = SOCKET_CONTENT_TYPES;
|
|
18
|
+
export type IncomingMessage = IncomingSocketMessage;
|
|
19
|
+
export type OutgoingMessage = OutgoingSocketMessage;
|
|
20
|
+
export interface SocketChatRequestData {
|
|
21
|
+
message?: string;
|
|
22
|
+
messageId?: string;
|
|
23
|
+
type: SOCKET_CONTENT_TYPES;
|
|
24
|
+
files?: File[];
|
|
25
|
+
url?: string;
|
|
26
|
+
tool_use_id?: string;
|
|
27
|
+
tool_use_params?: Record<string, unknown>;
|
|
28
|
+
hidden?: boolean;
|
|
29
|
+
}
|
|
30
|
+
export declare const SYNAPSE_REALTIME_EVENTS: {
|
|
31
|
+
readonly CONNECTED: "connected";
|
|
32
|
+
readonly DISCONNECTED: "disconnected";
|
|
33
|
+
readonly PROGRESS_MESSAGE: "progress_message";
|
|
34
|
+
readonly MESSAGE_CHUNK: "message_chunk";
|
|
35
|
+
readonly TIPS_MESSAGE: "tips_message";
|
|
36
|
+
readonly END_OF_STREAM: "end_of_stream";
|
|
37
|
+
readonly ERROR: "error";
|
|
38
|
+
readonly TOOL_ESCALATION: "tool_escalation";
|
|
39
|
+
readonly INLINE_TEXT: "inline_text";
|
|
40
|
+
};
|
|
41
|
+
export type SYNAPSE_REALTIME_EVENTS = (typeof SYNAPSE_REALTIME_EVENTS)[keyof typeof SYNAPSE_REALTIME_EVENTS];
|
|
42
|
+
export declare const SYNAPSE_REALTIME_ERROR_CODES: {
|
|
43
|
+
readonly SESSION_INACTIVE: "session_not_found";
|
|
44
|
+
readonly SESSION_EXPIRED: "session_expired";
|
|
45
|
+
readonly INVALID_EVENT: "invalid_event";
|
|
46
|
+
readonly INVALID_CONTENT_TYPE: "invalid_content";
|
|
47
|
+
readonly PARSING_ERROR: "parsing";
|
|
48
|
+
readonly FILE_UPLOAD_INPROGRESS: "file_upload_inprogress";
|
|
49
|
+
readonly TIMEOUT: "timeout";
|
|
50
|
+
readonly SERVER_ERROR: "server_error";
|
|
51
|
+
readonly SESSION_TOKEN_MISMATCH: "session_token_mismatch";
|
|
52
|
+
};
|
|
53
|
+
export type SYNAPSE_REALTIME_ERROR_CODES = (typeof SYNAPSE_REALTIME_ERROR_CODES)[keyof typeof SYNAPSE_REALTIME_ERROR_CODES];
|
|
54
|
+
export declare const SYNAPSE_REALTIME_RESERVED_EVENTS: {
|
|
55
|
+
readonly SESSION_EXPIRED: "session_expired";
|
|
56
|
+
};
|
|
57
|
+
export type SYNAPSE_REALTIME_RESERVED_EVENTS = (typeof SYNAPSE_REALTIME_RESERVED_EVENTS)[keyof typeof SYNAPSE_REALTIME_RESERVED_EVENTS];
|
|
58
|
+
export type SOCKET_STREAM_DATA = AudioMetaData;
|
|
59
|
+
export type SynapseRealTimeEventData = {
|
|
60
|
+
data: ToolEscalationData;
|
|
61
|
+
messageId?: string;
|
|
62
|
+
timestamp?: number;
|
|
63
|
+
};
|
|
64
|
+
export type SynapseContentTypes = SOCKET_CONTENT_TYPES;
|
|
65
|
+
export type ToolEscalationData = {
|
|
66
|
+
type?: ContentType;
|
|
67
|
+
choices?: string[];
|
|
68
|
+
callbacks?: Record<string, boolean>;
|
|
69
|
+
additional_option?: typeof MULTI_SELECT_ADDITIONAL_OPTION;
|
|
70
|
+
text?: string;
|
|
71
|
+
tips?: string[];
|
|
72
|
+
[key: string]: unknown;
|
|
73
|
+
};
|
|
74
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/messages/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACL,oBAAoB,EACpB,KAAK,qBAAqB,EAC1B,KAAK,qBAAqB,EAC1B,8BAA8B,EAC/B,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE1D,eAAO,MAAM,qBAAqB;;;;;;;;;;CAAuB,CAAC;AAE1D,MAAM,MAAM,WAAW,GAAG,oBAAoB,CAAC;AAE/C,MAAM,MAAM,eAAe,GAAG,qBAAqB,CAAC;AACpD,MAAM,MAAM,eAAe,GAAG,qBAAqB,CAAC;AAEpD,MAAM,WAAW,qBAAqB;IACpC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,oBAAoB,CAAC;IAC3B,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC1C,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAGD,eAAO,MAAM,uBAAuB;;;;;;;;;;CAU1B,CAAC;AAEX,MAAM,MAAM,uBAAuB,GACjC,CAAC,OAAO,uBAAuB,CAAC,CAAC,MAAM,OAAO,uBAAuB,CAAC,CAAC;AAEzE,eAAO,MAAM,4BAA4B;;;;;;;;;;CAU/B,CAAC;AAEX,MAAM,MAAM,4BAA4B,GACtC,CAAC,OAAO,4BAA4B,CAAC,CAAC,MAAM,OAAO,4BAA4B,CAAC,CAAC;AAEnF,eAAO,MAAM,gCAAgC;;CAEnC,CAAC;AAEX,MAAM,MAAM,gCAAgC,GAC1C,CAAC,OAAO,gCAAgC,CAAC,CAAC,MAAM,OAAO,gCAAgC,CAAC,CAAC;AAG3F,MAAM,MAAM,kBAAkB,GAAG,aAAa,CAAC;AAE/C,MAAM,MAAM,wBAAwB,GAAG;IACrC,IAAI,EAAE,kBAAkB,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG,oBAAoB,CAAC;AACvD,MAAM,MAAM,kBAAkB,GAAG;IAC/B,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,iBAAiB,CAAC,EAAE,OAAO,8BAA8B,CAAC;IAC1D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Types for message management
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.SYNAPSE_REALTIME_RESERVED_EVENTS = exports.SYNAPSE_REALTIME_ERROR_CODES = exports.SYNAPSE_REALTIME_EVENTS = exports.SYNAPSE_MESSAGE_TYPES = void 0;
|
|
7
|
+
const Events_1 = require("../events/Events");
|
|
8
|
+
exports.SYNAPSE_MESSAGE_TYPES = Events_1.SOCKET_CONTENT_TYPES;
|
|
9
|
+
//TOD0: reframe event names
|
|
10
|
+
exports.SYNAPSE_REALTIME_EVENTS = {
|
|
11
|
+
CONNECTED: "connected",
|
|
12
|
+
DISCONNECTED: "disconnected",
|
|
13
|
+
PROGRESS_MESSAGE: "progress_message",
|
|
14
|
+
MESSAGE_CHUNK: "message_chunk",
|
|
15
|
+
TIPS_MESSAGE: "tips_message",
|
|
16
|
+
END_OF_STREAM: "end_of_stream",
|
|
17
|
+
ERROR: "error",
|
|
18
|
+
TOOL_ESCALATION: "tool_escalation",
|
|
19
|
+
INLINE_TEXT: "inline_text",
|
|
20
|
+
};
|
|
21
|
+
exports.SYNAPSE_REALTIME_ERROR_CODES = {
|
|
22
|
+
SESSION_INACTIVE: "session_not_found",
|
|
23
|
+
SESSION_EXPIRED: "session_expired",
|
|
24
|
+
INVALID_EVENT: "invalid_event",
|
|
25
|
+
INVALID_CONTENT_TYPE: "invalid_content",
|
|
26
|
+
PARSING_ERROR: "parsing", // for all LLM related error
|
|
27
|
+
FILE_UPLOAD_INPROGRESS: "file_upload_inprogress",
|
|
28
|
+
TIMEOUT: "timeout",
|
|
29
|
+
SERVER_ERROR: "server_error",
|
|
30
|
+
SESSION_TOKEN_MISMATCH: "session_token_mismatch",
|
|
31
|
+
};
|
|
32
|
+
exports.SYNAPSE_REALTIME_RESERVED_EVENTS = {
|
|
33
|
+
SESSION_EXPIRED: "session_expired", //to be used for session expiry
|
|
34
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Config.d.ts","sourceRoot":"","sources":["../../../src/resources/config/Config.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Init class to fetch agent configuration from the platform
|
|
3
|
+
*/
|
|
4
|
+
import { type ResourceConfig } from "./types";
|
|
5
|
+
import { type SessionResponse, type USER_FEEDBACK } from "./session/types";
|
|
6
|
+
export declare class ResourceManager {
|
|
7
|
+
private resourceConfig;
|
|
8
|
+
private httpClient;
|
|
9
|
+
private session;
|
|
10
|
+
constructor(config: ResourceConfig);
|
|
11
|
+
/**
|
|
12
|
+
* Fetch agent configuration and create session
|
|
13
|
+
*/
|
|
14
|
+
createSession(userId: string): Promise<SessionResponse>;
|
|
15
|
+
/**
|
|
16
|
+
* Validate a session if it's still active or not
|
|
17
|
+
* GET /med-assist/session/:sessionId
|
|
18
|
+
*/
|
|
19
|
+
validateSession(sessionId: string): Promise<{
|
|
20
|
+
expired: boolean;
|
|
21
|
+
active: boolean;
|
|
22
|
+
}>;
|
|
23
|
+
/**
|
|
24
|
+
* Refresh a session
|
|
25
|
+
* POST /med-assist/session/:sessionId/refresh
|
|
26
|
+
*/
|
|
27
|
+
refreshSession(sessionId: string, sessionToken: string): Promise<SessionResponse>;
|
|
28
|
+
/**
|
|
29
|
+
* Feedback on a message
|
|
30
|
+
* PATCH /med-assist/session/:sessionId/:messageId
|
|
31
|
+
*/
|
|
32
|
+
sendFeedback(sessionId: string, messageId: string, feedback: USER_FEEDBACK, feedbackReason?: string): Promise<void>;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/resources/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,SAAS,CAAC;AAG9C,OAAO,EAAE,KAAK,eAAe,EAAE,KAAK,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAG3E,qBAAa,eAAe;IAC1B,OAAO,CAAC,cAAc,CAAiB;IACvC,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,OAAO,CAAU;gBAEb,MAAM,EAAE,cAAc;IAgBlC;;OAEG;IACU,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IAwBpE;;;OAGG;IACU,eAAe,CAC1B,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,OAAO,CAAA;KAAE,CAAC;IAgDjD;;;OAGG;IACU,cAAc,CACzB,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,eAAe,CAAC;IAI3B;;;OAGG;IACU,YAAY,CACvB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,aAAa,EACvB,cAAc,CAAC,EAAE,MAAM,GACtB,OAAO,CAAC,IAAI,CAAC;CAGjB"}
|