@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.
Files changed (98) hide show
  1. package/README.md +32 -0
  2. package/dist/Synapse.d.ts +131 -0
  3. package/dist/Synapse.d.ts.map +1 -0
  4. package/dist/Synapse.js +479 -0
  5. package/dist/connection/ConnectionFactory.d.ts +17 -0
  6. package/dist/connection/ConnectionFactory.d.ts.map +1 -0
  7. package/dist/connection/ConnectionFactory.js +28 -0
  8. package/dist/connection/Websocket.d.ts +61 -0
  9. package/dist/connection/Websocket.d.ts.map +1 -0
  10. package/dist/connection/Websocket.js +184 -0
  11. package/dist/constants/index.d.ts +17 -0
  12. package/dist/constants/index.d.ts.map +1 -0
  13. package/dist/constants/index.js +28 -0
  14. package/dist/constants/types.d.ts +2 -0
  15. package/dist/constants/types.d.ts.map +1 -0
  16. package/dist/constants/types.js +2 -0
  17. package/dist/events/Events.d.ts +47 -0
  18. package/dist/events/Events.d.ts.map +1 -0
  19. package/dist/events/Events.js +46 -0
  20. package/dist/events/Incoming.d.ts +2 -0
  21. package/dist/events/Incoming.d.ts.map +1 -0
  22. package/dist/events/Incoming.js +2 -0
  23. package/dist/events/Outgoing.d.ts +2 -0
  24. package/dist/events/Outgoing.d.ts.map +1 -0
  25. package/dist/events/Outgoing.js +2 -0
  26. package/dist/events/index.d.ts +3 -0
  27. package/dist/events/index.d.ts.map +1 -0
  28. package/dist/events/index.js +38 -0
  29. package/dist/events/types.d.ts +86 -0
  30. package/dist/events/types.d.ts.map +1 -0
  31. package/dist/events/types.js +6 -0
  32. package/dist/index.d.ts +27 -0
  33. package/dist/index.d.ts.map +1 -0
  34. package/dist/index.js +69 -0
  35. package/dist/internal/Api/BaseResource.d.ts +35 -0
  36. package/dist/internal/Api/BaseResource.d.ts.map +1 -0
  37. package/dist/internal/Api/BaseResource.js +54 -0
  38. package/dist/internal/Api/HttpClient.d.ts +25 -0
  39. package/dist/internal/Api/HttpClient.d.ts.map +1 -0
  40. package/dist/internal/Api/HttpClient.js +131 -0
  41. package/dist/internal/Api/types.d.ts +7 -0
  42. package/dist/internal/Api/types.d.ts.map +1 -0
  43. package/dist/internal/Api/types.js +2 -0
  44. package/dist/internal/Error/Error.d.ts +97 -0
  45. package/dist/internal/Error/Error.d.ts.map +1 -0
  46. package/dist/internal/Error/Error.js +243 -0
  47. package/dist/internal/Error/types.d.ts +17 -0
  48. package/dist/internal/Error/types.d.ts.map +1 -0
  49. package/dist/internal/Error/types.js +12 -0
  50. package/dist/internal/connection/BaseConnection.d.ts +100 -0
  51. package/dist/internal/connection/BaseConnection.d.ts.map +1 -0
  52. package/dist/internal/connection/BaseConnection.js +138 -0
  53. package/dist/internal/connection/types.d.ts +43 -0
  54. package/dist/internal/connection/types.d.ts.map +1 -0
  55. package/dist/internal/connection/types.js +20 -0
  56. package/dist/internal/events/EventEmitter.d.ts +7 -0
  57. package/dist/internal/events/EventEmitter.d.ts.map +1 -0
  58. package/dist/internal/events/EventEmitter.js +27 -0
  59. package/dist/internal/store/index.d.ts +10 -0
  60. package/dist/internal/store/index.d.ts.map +1 -0
  61. package/dist/internal/store/index.js +9 -0
  62. package/dist/media/audio/Audio.d.ts +37 -0
  63. package/dist/media/audio/Audio.d.ts.map +1 -0
  64. package/dist/media/audio/Audio.js +310 -0
  65. package/dist/media/audio/types.d.ts +25 -0
  66. package/dist/media/audio/types.d.ts.map +1 -0
  67. package/dist/media/audio/types.js +10 -0
  68. package/dist/media/file/File.d.ts +54 -0
  69. package/dist/media/file/File.d.ts.map +1 -0
  70. package/dist/media/file/File.js +159 -0
  71. package/dist/messages/MessageManager.d.ts +79 -0
  72. package/dist/messages/MessageManager.d.ts.map +1 -0
  73. package/dist/messages/MessageManager.js +420 -0
  74. package/dist/messages/types.d.ts +74 -0
  75. package/dist/messages/types.d.ts.map +1 -0
  76. package/dist/messages/types.js +34 -0
  77. package/dist/resources/config/Config.d.ts +5 -0
  78. package/dist/resources/config/Config.d.ts.map +1 -0
  79. package/dist/resources/config/Config.js +5 -0
  80. package/dist/resources/index.d.ts +34 -0
  81. package/dist/resources/index.d.ts.map +1 -0
  82. package/dist/resources/index.js +108 -0
  83. package/dist/resources/session/Session.d.ts +21 -0
  84. package/dist/resources/session/Session.d.ts.map +1 -0
  85. package/dist/resources/session/Session.js +39 -0
  86. package/dist/resources/session/types.d.ts +17 -0
  87. package/dist/resources/session/types.d.ts.map +1 -0
  88. package/dist/resources/session/types.js +8 -0
  89. package/dist/resources/types.d.ts +22 -0
  90. package/dist/resources/types.d.ts.map +1 -0
  91. package/dist/resources/types.js +5 -0
  92. package/dist/types/index.d.ts +8 -0
  93. package/dist/types/index.d.ts.map +1 -0
  94. package/dist/types/index.js +24 -0
  95. package/dist/utils/Error.d.ts +45 -0
  96. package/dist/utils/Error.d.ts.map +1 -0
  97. package/dist/utils/Error.js +114 -0
  98. package/package.json +41 -0
package/README.md ADDED
@@ -0,0 +1,32 @@
1
+ # @synapse/core
2
+
3
+ TypeScript SDK for real-time medical chatbot experiences with session management, WebSocket connectivity, and media handling.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @synapse/core
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ```typescript
14
+ import { SynapseSDK } from "@synapse/core";
15
+
16
+ const sdk = new SynapseSDK({
17
+ agentId: "agent-123",
18
+ environment: "production",
19
+ userId: "user-456",
20
+ callbacks: {
21
+ onSessionRefreshed: (session) => console.log("session refreshed", session),
22
+ onConnectionStatusChange: (status) => console.log("status", status),
23
+ onRecordingStatusChange: (status) => console.log("recording", status),
24
+ onError: (error) => console.error("synapse error", error),
25
+ },
26
+ });
27
+
28
+ const session = await sdk.startSession();
29
+ sdk.sendMessage({ message: "Hello, doctor!" });
30
+ ```
31
+
32
+ For more details, see the [main README](../../README.md).
@@ -0,0 +1,131 @@
1
+ /**
2
+ * High-level SynapseSDK API
3
+ * Provides a simple interface for managing chat sessions
4
+ */
5
+ import { ConnectionType } from "./connection/ConnectionFactory";
6
+ import { ConnectionStatus } from "./internal/connection/types";
7
+ import { type Environment } from "./constants";
8
+ import { SYNAPSE_REALTIME_EVENTS } from "./messages/types";
9
+ import { SynapseError } from "./internal/Error/Error";
10
+ import { type SessionResponse } from "./resources/session/types";
11
+ import { AudioRecordingStatus } from "./media/audio/types";
12
+ export interface SendMessageOptions {
13
+ message?: string;
14
+ messageId?: string;
15
+ files?: File[];
16
+ tool_use_id?: string;
17
+ tool_use_params?: Record<string, unknown>;
18
+ hidden?: boolean;
19
+ }
20
+ export interface SynapseSDKOverrides {
21
+ prompt?: string;
22
+ firstMessage?: string;
23
+ language?: string;
24
+ }
25
+ export type SynapseSDKError = SynapseError | Error;
26
+ export interface SynapseSDKCallbacks {
27
+ onSessionRefreshed?: (sessionResponse: SessionResponse) => void;
28
+ onConnectionStatusChange?: (status: ConnectionStatus) => void;
29
+ onRecordingStatusChange?: (status: AudioRecordingStatus) => void;
30
+ onError?: (error: SynapseSDKError) => void;
31
+ }
32
+ export interface SynapseSDKConfig {
33
+ agentId: string;
34
+ environment?: Environment;
35
+ userId?: string;
36
+ connectionType?: ConnectionType;
37
+ overrides?: SynapseSDKOverrides;
38
+ callbacks?: SynapseSDKCallbacks;
39
+ }
40
+ export interface ExistingSessionOptions {
41
+ session_id: string;
42
+ session_token: string;
43
+ }
44
+ export declare class SynapseSDK {
45
+ private connection;
46
+ private messageManager;
47
+ private resourceManager;
48
+ private sessionToken;
49
+ private sessionId;
50
+ private config;
51
+ private connectionType;
52
+ constructor(config: SynapseSDKConfig);
53
+ /**
54
+ * Start the session
55
+ * if existing session is provided, it will be validated and refreshed
56
+ * if no existing session is provided, a new session will be created
57
+ * then the connection will be initialized and event handlers will be setup
58
+ * return the session response
59
+ */
60
+ startSession(existingSession?: ExistingSessionOptions): Promise<SessionResponse>;
61
+ /**
62
+ * Send a message conetnt will be text always
63
+ */
64
+ sendMessage({ message, messageId, files, tool_use_id, tool_use_params, hidden, }: SendMessageOptions): Promise<void>;
65
+ /**
66
+ * Register a listener for a specific event
67
+ */
68
+ on(event: SYNAPSE_REALTIME_EVENTS, listener: (...args: unknown[]) => void): void;
69
+ /**
70
+ * Remove a listener for a specific event
71
+ */
72
+ off(event: SYNAPSE_REALTIME_EVENTS, listener: (...args: unknown[]) => void): void;
73
+ /**
74
+ * Get the session ID
75
+ */
76
+ getSessionConfig(): SessionResponse;
77
+ /**
78
+ * Send audio
79
+ * */
80
+ startRecording(): void;
81
+ /**
82
+ * Stop recording audio
83
+ */
84
+ endRecording(): void;
85
+ /**
86
+ * End the session
87
+ */
88
+ endSession(): void;
89
+ private emitError;
90
+ private toSessionError;
91
+ /**
92
+ * Initialize the connection
93
+ * eg: socket connection or polling connection
94
+ */
95
+ private initializeConnection;
96
+ /**
97
+ * Resolve the session
98
+ * function to decide whether to create a new session or refresh the existing session
99
+ */
100
+ private manageSession;
101
+ /**
102
+ * Refresh the session
103
+ */
104
+ private refreshSession;
105
+ /**
106
+ * Create a new session
107
+ */
108
+ private createNewSession;
109
+ /**
110
+ * Set up event handlers for connection and messages
111
+ */
112
+ private setupEventHandlers;
113
+ /**
114
+ * Handle socket error
115
+ */
116
+ private onSocketConnectionError;
117
+ /**
118
+ * Handle socket connection open
119
+ */
120
+ private onSocketConnectionOpen;
121
+ /**
122
+ * Handle incoming socket messages
123
+ */
124
+ private onIncomingSocketMessage;
125
+ /**
126
+ * Handle session expired
127
+ */
128
+ private handleSessionExpiry;
129
+ private toConnectionError;
130
+ }
131
+ //# sourceMappingURL=Synapse.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Synapse.d.ts","sourceRoot":"","sources":["../src/Synapse.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,479 @@
1
+ "use strict";
2
+ /**
3
+ * High-level SynapseSDK API
4
+ * Provides a simple interface for managing chat sessions
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.SynapseSDK = void 0;
8
+ const ConnectionFactory_1 = require("./connection/ConnectionFactory");
9
+ const types_1 = require("./internal/connection/types");
10
+ const constants_1 = require("./constants");
11
+ const resources_1 = require("./resources");
12
+ // import { type AgentConfig } from "./resources/types";
13
+ const MessageManager_1 = require("./messages/MessageManager");
14
+ const types_2 = require("./messages/types");
15
+ const Error_1 = require("./utils/Error");
16
+ const Error_2 = require("./internal/Error/Error");
17
+ const Events_1 = require("./events/Events");
18
+ class SynapseSDK {
19
+ connection = null;
20
+ messageManager;
21
+ resourceManager;
22
+ // private agentConfig: AgentConfig | null = null;
23
+ sessionToken = null;
24
+ sessionId = null;
25
+ config;
26
+ connectionType;
27
+ constructor(config) {
28
+ this.config = {
29
+ ...config,
30
+ environment: config.environment || "production",
31
+ };
32
+ this.connectionType = config.connectionType || ConnectionFactory_1.ConnectionType.SOCKET;
33
+ const API_ORIGIN = (0, constants_1.getConfig)(this.config?.environment).BASE_API_URL;
34
+ this.resourceManager = new resources_1.ResourceManager({
35
+ agentId: this.config.agentId,
36
+ serverUrl: API_ORIGIN, //based on environment
37
+ });
38
+ }
39
+ /**
40
+ * Start the session
41
+ * if existing session is provided, it will be validated and refreshed
42
+ * if no existing session is provided, a new session will be created
43
+ * then the connection will be initialized and event handlers will be setup
44
+ * return the session response
45
+ */
46
+ async startSession(existingSession) {
47
+ try {
48
+ const sessionResponse = await this.manageSession(existingSession);
49
+ await this.initializeConnection(sessionResponse);
50
+ this.setupEventHandlers();
51
+ return sessionResponse;
52
+ }
53
+ catch (error) {
54
+ const userFriendlyMessage = Error_1.ErrorUtils.getUserFriendlyMessage(error);
55
+ const errorDetails = Error_1.ErrorUtils.getErrorDetails(error);
56
+ const sessionError = this.toSessionError(error, userFriendlyMessage || "Failed to start session", {
57
+ stage: "startSession",
58
+ details: errorDetails,
59
+ }, "Check network connectivity or refresh credentials before retrying.");
60
+ this.emitError(sessionError);
61
+ throw sessionError;
62
+ }
63
+ }
64
+ /**
65
+ * Send a message conetnt will be text always
66
+ */
67
+ async sendMessage({ message, messageId, files, tool_use_id, tool_use_params, hidden, }) {
68
+ if (!this.connection) {
69
+ const error = new Error_2.ConnectionError("Connection not established. Session may not be initialized.", {
70
+ context: { stage: "sendChatMessage" },
71
+ hint: "Call startSession() and wait for connection before sending messages.",
72
+ });
73
+ this.emitError(error);
74
+ throw error;
75
+ }
76
+ switch (this.connectionType) {
77
+ case ConnectionFactory_1.ConnectionType.SOCKET:
78
+ this.messageManager.sendSocketChatMessage({
79
+ message: message,
80
+ files: files,
81
+ messageId: messageId,
82
+ type: Events_1.SOCKET_CONTENT_TYPES.TEXT,
83
+ tool_use_id: tool_use_id,
84
+ tool_use_params: tool_use_params,
85
+ hidden: hidden,
86
+ });
87
+ break;
88
+ default:
89
+ const error = new Error_2.ConnectionError("Unsupported connection type", {
90
+ context: {
91
+ stage: "sendChatMessage",
92
+ connectionType: this.connectionType,
93
+ },
94
+ });
95
+ this.emitError(error);
96
+ throw error;
97
+ }
98
+ }
99
+ // /**
100
+ // * upload files
101
+ // */
102
+ // public uploadFiles(
103
+ // files: File[],
104
+ // message?: string,
105
+ // messageId?: string
106
+ // ): void {
107
+ // if (!this.connection) {
108
+ // //TODO: use onError instead of throw error
109
+ // const error = new ConnectionError(
110
+ // "Connection not established. Session may not be initialized.",
111
+ // {
112
+ // context: { stage: "uploadFiles" },
113
+ // hint: "Call startSession() before attempting uploads.",
114
+ // }
115
+ // );
116
+ // this.emitError(error);
117
+ // throw error;
118
+ // }
119
+ // switch (this.connectionType) {
120
+ // case ConnectionType.SOCKET:
121
+ // this.messageManager.sendSocketChatMessage({
122
+ // files,
123
+ // message,
124
+ // messageId: messageId,
125
+ // type: SOCKET_CONTENT_TYPES.FILE,
126
+ // });
127
+ // break;
128
+ // default:
129
+ // const error = new ConnectionError("Unsupported connection type", {
130
+ // context: {
131
+ // stage: "uploadFiles",
132
+ // connectionType: this.connectionType,
133
+ // },
134
+ // });
135
+ // this.emitError(error);
136
+ // throw error;
137
+ // }
138
+ // }
139
+ /**
140
+ * Register a listener for a specific event
141
+ */
142
+ on(event, listener) {
143
+ this.connection?.on(event, listener);
144
+ }
145
+ /**
146
+ * Remove a listener for a specific event
147
+ */
148
+ off(event, listener) {
149
+ this.connection?.off(event, listener);
150
+ }
151
+ /**
152
+ * Get the session ID
153
+ */
154
+ getSessionConfig() {
155
+ if (!this.sessionId || !this.sessionToken) {
156
+ throw new Error_2.SessionError("Session ID or token not found", {
157
+ context: { stage: "getSessionConfig" },
158
+ hint: "Ensure the session API returns both identifiers.",
159
+ });
160
+ }
161
+ return {
162
+ session_id: this.sessionId,
163
+ session_token: this.sessionToken,
164
+ };
165
+ }
166
+ /**
167
+ * Send audio
168
+ * */
169
+ startRecording() {
170
+ if (!this.connection) {
171
+ const error = new Error_2.ConnectionError("Connection not established. Session may not be initialized.", {
172
+ context: { stage: "sendAudio" },
173
+ hint: "Call startSession() before attempting to send audio.",
174
+ });
175
+ this.emitError(error);
176
+ throw error;
177
+ }
178
+ switch (this.connectionType) {
179
+ case ConnectionFactory_1.ConnectionType.SOCKET:
180
+ this.messageManager.startRecordingWithSocket();
181
+ break;
182
+ default:
183
+ const error = new Error_2.ConnectionError("Unsupported connection type", {
184
+ context: { stage: "sendAudio", connectionType: this.connectionType },
185
+ });
186
+ this.emitError(error);
187
+ throw error;
188
+ }
189
+ }
190
+ /**
191
+ * Stop recording audio
192
+ */
193
+ endRecording() {
194
+ if (!this.connection) {
195
+ const error = new Error_2.ConnectionError("Connection not established. Session may not be initialized.", {
196
+ context: { stage: "endRecording" },
197
+ hint: "Call startRecording() before attempting to stop recording.",
198
+ });
199
+ this.emitError(error);
200
+ throw error;
201
+ }
202
+ switch (this.connectionType) {
203
+ case ConnectionFactory_1.ConnectionType.SOCKET:
204
+ this.messageManager.endRecordingWithSocket();
205
+ break;
206
+ default:
207
+ const error = new Error_2.ConnectionError("Unsupported connection type", {
208
+ context: {
209
+ stage: "endRecording",
210
+ connectionType: this.connectionType,
211
+ },
212
+ });
213
+ this.emitError(error);
214
+ throw error;
215
+ }
216
+ }
217
+ // /**
218
+ // * Get the agent configuration
219
+ // */
220
+ // public getAgentConfig(): AgentConfig | null {
221
+ // return this.agentConfig;
222
+ // }
223
+ /**
224
+ * End the session
225
+ */
226
+ endSession() {
227
+ if (this.connection) {
228
+ this.connection.close();
229
+ this.connection = null;
230
+ }
231
+ if (this.messageManager) {
232
+ this.messageManager.cleanupMessageServerState();
233
+ }
234
+ }
235
+ emitError(error) {
236
+ this.config.callbacks?.onError?.(error);
237
+ }
238
+ toSessionError(error, fallbackMessage, context, hint) {
239
+ return (0, Error_2.normalizeError)(error, Error_2.SessionError, fallbackMessage, {
240
+ context,
241
+ hint,
242
+ });
243
+ }
244
+ /**
245
+ * Initialize the connection
246
+ * eg: socket connection or polling connection
247
+ */
248
+ async initializeConnection(sessionResponse) {
249
+ if (this.connection) {
250
+ this.connection.close();
251
+ this.connection = null;
252
+ }
253
+ if (!sessionResponse.session_id || !sessionResponse.session_token) {
254
+ throw new Error_2.SessionError("Session ID or token not found", {
255
+ context: { stage: "initializeConnection" },
256
+ hint: "Ensure the session API returns both identifiers.",
257
+ });
258
+ }
259
+ this.sessionId = sessionResponse.session_id;
260
+ this.sessionToken = sessionResponse.session_token;
261
+ const serverUrl = (0, constants_1.getConfig)(this.config?.environment).WEBSOCKET_URL;
262
+ const connectionType = this.config.connectionType === "socket"
263
+ ? ConnectionFactory_1.ConnectionType.SOCKET
264
+ : ConnectionFactory_1.ConnectionType.SOCKET;
265
+ this.connection = await ConnectionFactory_1.ConnectionFactory.createConnection(connectionType, {
266
+ serverUrl,
267
+ auth: {
268
+ sessionId: sessionResponse.session_id,
269
+ sessionToken: sessionResponse.session_token,
270
+ },
271
+ agentId: this.config.agentId,
272
+ userId: this.config.userId,
273
+ // authorization: this.config?.authorization,
274
+ overrides: this.config.overrides,
275
+ });
276
+ this.messageManager = new MessageManager_1.MessageManager(this.connection, this.config?.callbacks);
277
+ }
278
+ /**
279
+ * Resolve the session
280
+ * function to decide whether to create a new session or refresh the existing session
281
+ */
282
+ async manageSession(existingSession) {
283
+ if (!existingSession?.session_id) {
284
+ return this.createNewSession();
285
+ }
286
+ this.config.callbacks?.onConnectionStatusChange?.(types_1.ConnectionStatus.CONNECTING);
287
+ try {
288
+ const result = await this.resourceManager.validateSession(existingSession.session_id);
289
+ if (result.active) {
290
+ return existingSession;
291
+ }
292
+ if (result.expired) {
293
+ return this.refreshSession(existingSession.session_id, existingSession.session_token);
294
+ }
295
+ return this.createNewSession();
296
+ }
297
+ catch (error) {
298
+ this.config.callbacks?.onConnectionStatusChange?.(types_1.ConnectionStatus.NOT_CONNECTED);
299
+ if (error instanceof Error_2.APIError) {
300
+ const status = error.status;
301
+ if (status === 404 || status === 500) {
302
+ return this.createNewSession();
303
+ }
304
+ }
305
+ throw this.toSessionError(error, "Failed to resolve session", {
306
+ stage: "resolveSession",
307
+ });
308
+ }
309
+ }
310
+ /**
311
+ * Refresh the session
312
+ */
313
+ async refreshSession(sessionId, sessionToken) {
314
+ try {
315
+ return await this.resourceManager.refreshSession(sessionId, sessionToken);
316
+ }
317
+ catch (error) {
318
+ if (error instanceof Error_2.APIError) {
319
+ const status = error.status;
320
+ if (status === 404 || status === 500) {
321
+ return this.createNewSession();
322
+ }
323
+ }
324
+ throw this.toSessionError(error, "Failed to refresh session", {
325
+ stage: "refreshSession",
326
+ sessionId,
327
+ });
328
+ }
329
+ }
330
+ /**
331
+ * Create a new session
332
+ */
333
+ async createNewSession() {
334
+ return await this.resourceManager.createSession(this.config.userId || Date.now().toString());
335
+ }
336
+ /**
337
+ * Set up event handlers for connection and messages
338
+ */
339
+ setupEventHandlers() {
340
+ if (!this.connection)
341
+ return;
342
+ switch (this.connectionType) {
343
+ case ConnectionFactory_1.ConnectionType.SOCKET:
344
+ this.connection.onOpen(() => {
345
+ this.onSocketConnectionOpen();
346
+ });
347
+ this.connection.onMessage((message) => {
348
+ this.onIncomingSocketMessage(message);
349
+ });
350
+ this.connection.onError((error) => {
351
+ this.onSocketConnectionError(error);
352
+ });
353
+ this.connection.onStatusChange((status) => {
354
+ this.config.callbacks?.onConnectionStatusChange?.(status);
355
+ });
356
+ this.connection.on(types_2.SYNAPSE_REALTIME_RESERVED_EVENTS.SESSION_EXPIRED, () => {
357
+ this.handleSessionExpiry();
358
+ });
359
+ break;
360
+ default:
361
+ throw new Error_2.ConnectionError("Unsupported connection type", {
362
+ context: {
363
+ stage: "setupEventHandlers",
364
+ connectionType: this.connectionType,
365
+ },
366
+ hint: "Use ConnectionType.SOCKET or provide a custom handler.",
367
+ });
368
+ }
369
+ //common handler for all connection types
370
+ this.connection.onDisconnect((details) => {
371
+ this.messageManager.handleDisconnect(details);
372
+ // this.endSession();
373
+ });
374
+ }
375
+ /**
376
+ * Handle socket error
377
+ */
378
+ onSocketConnectionError(error) {
379
+ const connectionError = this.toConnectionError(error, "WebSocket connection error", { stage: "onSocketConnectionError" }, "Verify network connectivity or attempt to reconnect.");
380
+ this.emitError(connectionError);
381
+ }
382
+ /**
383
+ * Handle socket connection open
384
+ */
385
+ onSocketConnectionOpen() {
386
+ if (!this.sessionToken) {
387
+ const error = new Error_2.SessionError("Session token not set. Call startSession() first.", {
388
+ context: { stage: "onSocketConnectionOpen" },
389
+ hint: "Ensure startSession() completes successfully before socket opens.",
390
+ });
391
+ this.emitError(error);
392
+ throw error;
393
+ }
394
+ this.messageManager.sendSocketAuthMessage(this.sessionToken);
395
+ }
396
+ /**
397
+ * Handle incoming socket messages
398
+ */
399
+ onIncomingSocketMessage(message) {
400
+ // this.config.callbacks?.onMessage?.(message.content, message.messageId);
401
+ switch (message.ev) {
402
+ case Events_1.SOCKET_EVENTS.CHAT:
403
+ this.messageManager.handleIncomingSocketChatMessage(message);
404
+ // this.config.callbacks?.onMessage?.(message.data.content, message.data.messageId);
405
+ break;
406
+ case Events_1.SOCKET_EVENTS.CONNECTION_ESTABLISHED: //emit after internal handlings
407
+ this.messageManager.handleConnectionEstablished();
408
+ break;
409
+ case Events_1.SOCKET_EVENTS.STREAM:
410
+ this.messageManager.handleIncomingSocketStreamMessage(message);
411
+ break;
412
+ case Events_1.SOCKET_EVENTS.END_OF_STREAM: //emit
413
+ this.messageManager.handleIncomingSocketEndOfStreamMessage(message);
414
+ break;
415
+ case Events_1.SOCKET_EVENTS.PING:
416
+ this.messageManager.sendSocketPongMessage();
417
+ break;
418
+ case Events_1.SOCKET_EVENTS.PONG:
419
+ this.messageManager.sendSocketPingMessage();
420
+ break;
421
+ case Events_1.SOCKET_EVENTS.SYNC:
422
+ break;
423
+ case Events_1.SOCKET_EVENTS.ERROR:
424
+ this.messageManager.handleIncomingSocketErrorMessage(message);
425
+ break;
426
+ default:
427
+ const error = new Error_2.MessageError("Unsupported message type", {
428
+ context: {
429
+ stage: "onIncomingSocketMessage",
430
+ event: message.ev ?? "unknown",
431
+ },
432
+ hint: "Ensure the server is sending supported socket events.",
433
+ });
434
+ this.emitError(error);
435
+ return;
436
+ }
437
+ }
438
+ /**
439
+ * Handle session expired
440
+ */
441
+ async handleSessionExpiry() {
442
+ try {
443
+ this.endSession();
444
+ this.config.callbacks?.onConnectionStatusChange?.(types_1.ConnectionStatus.CONNECTING);
445
+ if (!this.sessionId || !this.sessionToken) {
446
+ const error = new Error_2.SessionError("Session ID or token not found", {
447
+ context: { stage: "handleSessionExpiry" },
448
+ });
449
+ this.emitError(error);
450
+ throw error;
451
+ }
452
+ const refreshed = await this.refreshSession(this.sessionId, this.sessionToken);
453
+ if (!refreshed.session_id || !refreshed.session_token) {
454
+ throw new Error_2.SessionError("Session refresh failed", {
455
+ context: { stage: "handleSessionExpiry" },
456
+ });
457
+ }
458
+ this.sessionId = refreshed.session_id;
459
+ this.sessionToken = refreshed.session_token;
460
+ await this.initializeConnection(refreshed);
461
+ this.setupEventHandlers();
462
+ this.config.callbacks?.onSessionRefreshed?.(refreshed);
463
+ }
464
+ catch (error) {
465
+ this.config.callbacks?.onConnectionStatusChange?.(types_1.ConnectionStatus.NOT_CONNECTED);
466
+ const sessionError = this.toSessionError(error, "Session expired", {
467
+ stage: "handleSessionExpiry",
468
+ });
469
+ this.emitError(sessionError);
470
+ }
471
+ }
472
+ toConnectionError(error, fallbackMessage, context, hint) {
473
+ return (0, Error_2.normalizeError)(error, Error_2.ConnectionError, fallbackMessage, {
474
+ context,
475
+ hint,
476
+ });
477
+ }
478
+ }
479
+ exports.SynapseSDK = SynapseSDK;
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Factory class to create the appropriate connection type
3
+ */
4
+ import { BaseConnection } from "../internal/connection/BaseConnection";
5
+ import { type WebSocketConnectionConfig } from "./Websocket";
6
+ export declare const ConnectionType: {
7
+ readonly SOCKET: "socket";
8
+ };
9
+ export type ConnectionType = (typeof ConnectionType)[keyof typeof ConnectionType];
10
+ export type ConnectionConfig = WebSocketConnectionConfig;
11
+ export declare class ConnectionFactory {
12
+ /**
13
+ * Create a connection based on the specified type
14
+ */
15
+ static createConnection(type: ConnectionType, config: ConnectionConfig): Promise<BaseConnection>;
16
+ }
17
+ //# sourceMappingURL=ConnectionFactory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConnectionFactory.d.ts","sourceRoot":"","sources":["../../src/connection/ConnectionFactory.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AACvE,OAAO,EAEL,KAAK,yBAAyB,EAC/B,MAAM,aAAa,CAAC;AAGrB,eAAO,MAAM,cAAc;;CAGjB,CAAC;AAEX,MAAM,MAAM,cAAc,GACxB,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,OAAO,cAAc,CAAC,CAAC;AAEvD,MAAM,MAAM,gBAAgB,GAAG,yBAAyB,CAAC;AAEzD,qBAAa,iBAAiB;IAC5B;;OAEG;WACiB,gBAAgB,CAClC,IAAI,EAAE,cAAc,EACpB,MAAM,EAAE,gBAAgB,GACvB,OAAO,CAAC,cAAc,CAAC;CAU3B"}