@eka-care/medassist-core 1.0.14 → 1.0.16

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.
@@ -1 +1 @@
1
- {"version":3,"file":"Synapse.d.ts","sourceRoot":"","sources":["../src/Synapse.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAeH,OAAO,EACL,uBAAuB,EAExB,MAAM,kBAAkB,CAAC;AAmB1B,OAAO,EACL,KAAK,eAAe,EACrB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AACnE,OAAO,KAAK,EAAE,sBAAsB,EAAE,kBAAkB,EAAiB,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAI3G,qBAAa,UAAU;IACrB,OAAO,CAAC,UAAU,CAA+B;IACjD,OAAO,CAAC,cAAc,CAAkB;IACxC,OAAO,CAAC,eAAe,CAAkB;IAEzC,OAAO,CAAC,aAAa,CAA8B;IACnD,OAAO,CAAC,MAAM,CAAmB;IACjC,OAAO,CAAC,cAAc,CAAiB;gBAE3B,MAAM,EAAE,gBAAgB;IAapC;;;;;;OAMG;IACU,YAAY,CACvB,eAAe,CAAC,EAAE,sBAAsB,GACvC,OAAO,CAAC,eAAe,CAAC;IAwB3B;;OAEG;IACU,WAAW,CAAC,EACvB,OAAO,EACP,KAAK,EACL,KAAK,EACL,aAAa,EACb,OAAO,EACP,eAAe,EAChB,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC;IAmCrC;;OAEG;IACI,EAAE,CACP,KAAK,EAAE,uBAAuB,EAC9B,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,GACrC,IAAI;IAIP;;OAEG;IACI,GAAG,CACR,KAAK,EAAE,uBAAuB,EAC9B,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,GACrC,IAAI;IAIP;;OAEG;IACI,gBAAgB,IAAI,eAAe;IAU1C;;OAEG;IACU,QAAQ,CAAC,CAAC,SAAS,gBAAgB,GAAG,gBAAgB,EACjE,IAAI,EAAE,MAAM,EACZ,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,OAAO,CAAC,CAAC,CAAC;IA+Cb;;SAEK;IACQ,cAAc,CAAC,EAC1B,QAAQ,EACR,OAAO,GACR,EAAE;QACD,QAAQ,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,IAAI,CAAC;QAC1C,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;KAClC,GAAG,OAAO,CAAC,IAAI,CAAC;IAgCjB;;OAEG;IACI,YAAY,IAAI,IAAI;IAmCpB,WAAW,IAAI,OAAO;IAG7B;;OAEG;IACI,UAAU,IAAI,IAAI;IAUzB,OAAO,CAAC,SAAS;IAIjB,OAAO,CAAC,cAAc;IAYtB;;;OAGG;YACW,oBAAoB;IAwClC;;;OAGG;YACW,aAAa;IA2C3B;;OAEG;YACW,cAAc;IAwB5B;;OAEG;YACW,gBAAgB;IAO9B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAwC1B;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAW/B;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAe9B;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAgD/B;;OAEG;YACW,mBAAmB;IAsCjC,OAAO,CAAC,iBAAiB;CAW1B"}
1
+ {"version":3,"file":"Synapse.d.ts","sourceRoot":"","sources":["../src/Synapse.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAeH,OAAO,EACL,uBAAuB,EAExB,MAAM,kBAAkB,CAAC;AAmB1B,OAAO,EACL,KAAK,eAAe,EACrB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AACnE,OAAO,KAAK,EAAE,sBAAsB,EAAE,kBAAkB,EAAiB,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAI3G,qBAAa,UAAU;IACrB,OAAO,CAAC,UAAU,CAA+B;IACjD,OAAO,CAAC,cAAc,CAAkB;IACxC,OAAO,CAAC,eAAe,CAAkB;IAEzC,OAAO,CAAC,aAAa,CAA8B;IACnD,OAAO,CAAC,MAAM,CAAmB;IACjC,OAAO,CAAC,cAAc,CAAiB;gBAE3B,MAAM,EAAE,gBAAgB;IAcpC;;;;;;OAMG;IACU,YAAY,CACvB,eAAe,CAAC,EAAE,sBAAsB,GACvC,OAAO,CAAC,eAAe,CAAC;IAwB3B;;OAEG;IACU,WAAW,CAAC,EACvB,OAAO,EACP,KAAK,EACL,KAAK,EACL,aAAa,EACb,OAAO,EACP,eAAe,EAChB,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC;IAmCrC;;OAEG;IACI,EAAE,CACP,KAAK,EAAE,uBAAuB,EAC9B,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,GACrC,IAAI;IAIP;;OAEG;IACI,GAAG,CACR,KAAK,EAAE,uBAAuB,EAC9B,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,GACrC,IAAI;IAIP;;OAEG;IACI,gBAAgB,IAAI,eAAe;IAU1C;;OAEG;IACU,QAAQ,CAAC,CAAC,SAAS,gBAAgB,GAAG,gBAAgB,EACjE,IAAI,EAAE,MAAM,EACZ,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,OAAO,CAAC,CAAC,CAAC;IA+Cb;;SAEK;IACQ,cAAc,CAAC,EAC1B,QAAQ,EACR,OAAO,GACR,EAAE;QACD,QAAQ,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,IAAI,CAAC;QAC1C,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;KAClC,GAAG,OAAO,CAAC,IAAI,CAAC;IAgCjB;;OAEG;IACI,YAAY,IAAI,IAAI;IAmCpB,WAAW,IAAI,OAAO;IAG7B;;OAEG;IACI,UAAU,IAAI,IAAI;IAUzB,OAAO,CAAC,SAAS;IAIjB,OAAO,CAAC,cAAc;IAYtB;;;OAGG;YACW,oBAAoB;IAwClC;;;OAGG;YACW,aAAa;IA2C3B;;OAEG;YACW,cAAc;IAwB5B;;OAEG;YACW,gBAAgB;IAO9B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAwC1B;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAW/B;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAe9B;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAgD/B;;OAEG;YACW,mBAAmB;IAsCjC,OAAO,CAAC,iBAAiB;CAW1B"}
package/dist/Synapse.js CHANGED
@@ -33,6 +33,7 @@ class SynapseSDK {
33
33
  this.resourceManager = new resources_1.ResourceManager({
34
34
  agentId: this.config.agentId,
35
35
  serverUrl: this.config.serverUrl || API_ORIGIN, //based on environment
36
+ ...(this.config.auth && { authorization: this.config.auth }),
36
37
  });
37
38
  }
38
39
  /**
@@ -0,0 +1,44 @@
1
+ import { type AudioConfig, type AudioDataCallback, type AudioErrorCallback } from "./types";
2
+ export declare class AudioManager {
3
+ private mediaRecorder;
4
+ private mediaStream;
5
+ private recordingStartTime;
6
+ private autoPauseTimer;
7
+ private config;
8
+ private onAudioData;
9
+ private onAudioError;
10
+ private suppressCallbacks;
11
+ constructor(config?: Partial<AudioConfig>);
12
+ /**
13
+ * Best-effort permission check.
14
+ *
15
+ * NOTE: On some environments (especially iOS Safari / WKWebView),
16
+ * the Permissions API is missing or incomplete for "microphone".
17
+ * In those cases we **skip** the explicit check and rely on
18
+ * `getUserMedia` to trigger the OS permission prompt.
19
+ */
20
+ private checkCurrentPermissionState;
21
+ start(onAudioData: AudioDataCallback, onAudioError?: AudioErrorCallback): Promise<void>;
22
+ private processAudioChunk;
23
+ private toRecordingError;
24
+ private handleError;
25
+ /**
26
+ * Set up auto-pause timer for 15-minute limit
27
+ */
28
+ private setupAutoPauseTimer;
29
+ private setupMediaRecorderEvents;
30
+ /**
31
+ * Convert blob to base64 string
32
+ */
33
+ private blobToBase64;
34
+ /**
35
+ * Stop recording manually
36
+ */
37
+ stop(): void;
38
+ /**
39
+ * Cancel recording (discard data and suppress callbacks)
40
+ */
41
+ cancel(): void;
42
+ destroy(): void;
43
+ }
44
+ //# sourceMappingURL=Audio.copy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Audio.copy.d.ts","sourceRoot":"","sources":["../../../src/media/audio/Audio.copy.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,WAAW,EAChB,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EAExB,MAAM,SAAS,CAAC;AAGjB,qBAAa,YAAY;IACvB,OAAO,CAAC,aAAa,CAA8B;IACnD,OAAO,CAAC,WAAW,CAA4B;IAC/C,OAAO,CAAC,kBAAkB,CAAa;IACvC,OAAO,CAAC,cAAc,CAA8C;IAEpE,OAAO,CAAC,MAAM,CAAc;IAE5B,OAAO,CAAC,WAAW,CAAkC;IACrD,OAAO,CAAC,YAAY,CAAmC;IACvD,OAAO,CAAC,iBAAiB,CAAS;gBAEtB,MAAM,GAAE,OAAO,CAAC,WAAW,CAAM;IAU7C;;;;;;;OAOG;YACW,2BAA2B;IAkD5B,KAAK,CAChB,WAAW,EAAE,iBAAiB,EAC9B,YAAY,CAAC,EAAE,kBAAkB,GAChC,OAAO,CAAC,IAAI,CAAC;YAoIF,iBAAiB;IAuB/B,OAAO,CAAC,gBAAgB;IA0BxB,OAAO,CAAC,WAAW;IAmBnB;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAW3B,OAAO,CAAC,wBAAwB;IAsChC;;OAEG;IACH,OAAO,CAAC,YAAY;IA8BpB;;OAEG;IACH,IAAI,IAAI,IAAI;IA6BZ;;OAEG;IACH,MAAM,IAAI,IAAI;IAgCd,OAAO,IAAI,IAAI;CAiBhB"}
@@ -0,0 +1,374 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AudioManager = void 0;
4
+ const Error_1 = require("../../internal/Error/Error");
5
+ class AudioManager {
6
+ mediaRecorder = null;
7
+ mediaStream = null;
8
+ recordingStartTime = 0;
9
+ autoPauseTimer = null;
10
+ config;
11
+ onAudioData = null;
12
+ onAudioError = null;
13
+ suppressCallbacks = false; //gurad against late recorder events like ondatavaailable after cancel () or cleanup() is called
14
+ constructor(config = {}) {
15
+ this.config = {
16
+ mimeType: "audio/webm;codecs=opus",
17
+ audioBitsPerSecond: 128000,
18
+ maxRecordingDuration: 900000, // 15 minutes
19
+ autoPauseEnabled: true,
20
+ ...config,
21
+ };
22
+ }
23
+ /**
24
+ * Best-effort permission check.
25
+ *
26
+ * NOTE: On some environments (especially iOS Safari / WKWebView),
27
+ * the Permissions API is missing or incomplete for "microphone".
28
+ * In those cases we **skip** the explicit check and rely on
29
+ * `getUserMedia` to trigger the OS permission prompt.
30
+ */
31
+ async checkCurrentPermissionState() {
32
+ try {
33
+ // Guard: Permissions API not supported or not fully implemented
34
+ if (typeof navigator === "undefined" ||
35
+ !("permissions" in navigator) ||
36
+ !navigator.permissions ||
37
+ typeof navigator.permissions.query !== "function") {
38
+ // Treat as "prompt" – let getUserMedia drive the permission flow.
39
+ return "prompt";
40
+ }
41
+ // Try to query microphone permission
42
+ // On iOS WebView, this may throw "query does not support this api"
43
+ const permission = await navigator.permissions.query({
44
+ name: "microphone",
45
+ });
46
+ if (permission.state === "denied") {
47
+ throw new Error_1.RecordingError("Microphone permission denied", {
48
+ context: { permissionState: permission.state },
49
+ hint: "Ensure the browser or device has microphone access enabled for this site/app.",
50
+ });
51
+ }
52
+ return permission.state;
53
+ }
54
+ catch (error) {
55
+ // Some browsers (notably iOS WebKit/WKWebView) throw for unsupported permission names
56
+ // or return errors like "Permission :: query doesnot support" or "query does not support this api".
57
+ // Fall back to letting getUserMedia handle prompting.
58
+ const errorMessage = (error instanceof Error ? error.message : String(error)).toLowerCase();
59
+ if (errorMessage.includes("does not support") ||
60
+ errorMessage.includes("doesnot support") ||
61
+ errorMessage.includes("not supported") ||
62
+ errorMessage.includes("query does not support") ||
63
+ errorMessage.includes("permission::query") ||
64
+ errorMessage.includes("permission :: query doesnot support")) {
65
+ // Silently skip permission check for unsupported APIs - this is expected on iOS WebView
66
+ return "prompt";
67
+ }
68
+ // For other errors, log a warning but still proceed
69
+ console.warn("Permissions API for microphone is unavailable, falling back to getUserMedia-only flow:", error);
70
+ return "prompt";
71
+ }
72
+ }
73
+ async start(onAudioData, onAudioError //Clearly handles the error inside the callback without unhandled rejections
74
+ ) {
75
+ try {
76
+ // Check if mediaDevices is available
77
+ if (!navigator.mediaDevices) {
78
+ throw new Error_1.RecordingError("Media devices API is not available. This usually means the page is not served over HTTPS or there are browser restrictions.", {
79
+ context: { feature: "mediaDevices" },
80
+ hint: "Serve the app over HTTPS and verify browser/device microphone support.",
81
+ displayMessage: "Microphone access is unavailable."
82
+ });
83
+ }
84
+ // Check if MediaRecorder is supported
85
+ if (!window.MediaRecorder) {
86
+ throw new Error_1.RecordingError("MediaRecorder is not supported in this browser", {
87
+ context: { feature: "MediaRecorder" },
88
+ hint: "Use a browser that supports the MediaRecorder API.",
89
+ displayMessage: "Microphone access is unavailable."
90
+ });
91
+ }
92
+ // Check for supported audio formats in order of preference
93
+ const supportedTypes = [
94
+ "audio/mp3",
95
+ "audio/ogg;codecs=opus",
96
+ "audio/mp4",
97
+ "audio/ogg",
98
+ "audio/wav",
99
+ ].filter((type) => MediaRecorder.isTypeSupported(type));
100
+ if (supportedTypes.length === 0) {
101
+ throw new Error_1.RecordingError("No supported audio formats found in this browser", {
102
+ context: { requestedTypes: supportedTypes },
103
+ hint: "Verify codec support or adjust the requested MIME types.",
104
+ displayMessage: "Microphone access is unavailable."
105
+ });
106
+ }
107
+ // Update config with best supported mime type
108
+ this.config.mimeType = supportedTypes[0];
109
+ await this.checkCurrentPermissionState();
110
+ this.onAudioData = onAudioData;
111
+ this.onAudioError = onAudioError ?? null;
112
+ this.suppressCallbacks = false; //reset the guard against late recorder events
113
+ // Get user media with fallback for iOS WebView compatibility
114
+ // iOS WebView may throw "query does not support this api" for specific audio constraints
115
+ try {
116
+ this.mediaStream = await navigator.mediaDevices.getUserMedia({
117
+ audio: {
118
+ echoCancellation: false,
119
+ noiseSuppression: false,
120
+ autoGainControl: false,
121
+ sampleRate: 44100,
122
+ channelCount: 1,
123
+ },
124
+ });
125
+ }
126
+ catch (constraintError) {
127
+ const errorMessage = (constraintError instanceof Error ? constraintError.message : String(constraintError)).toLowerCase();
128
+ // If the error indicates unsupported constraints (common on iOS WebView),
129
+ // fall back to minimal audio constraints
130
+ // Error formats: "Permission :: query doesnot support", "query does not support", etc.
131
+ if (errorMessage.includes("does not support") ||
132
+ errorMessage.includes("doesnot support") ||
133
+ errorMessage.includes("not supported") ||
134
+ errorMessage.includes("query does not support") ||
135
+ errorMessage.includes("permission :: query") ||
136
+ errorMessage.includes("permission::query") ||
137
+ errorMessage.includes("constraintnotsatisfiederror")) {
138
+ // Fall back to simplest audio constraint for iOS WebView compatibility
139
+ this.mediaStream = await navigator.mediaDevices.getUserMedia({
140
+ audio: true,
141
+ });
142
+ }
143
+ else {
144
+ // Re-throw other errors (permission denied, etc.)
145
+ if (errorMessage.includes("permission::query") || errorMessage.includes("permission :: query")) {
146
+ throw new Error_1.RecordingError("Microphone permission denied", {
147
+ context: { permissionState: "denied" },
148
+ hint: `Please grant microphone access to the website. You can change this in the browser settings.`,
149
+ });
150
+ }
151
+ throw constraintError;
152
+ }
153
+ }
154
+ // Create MediaRecorder with fallback if the selected format fails
155
+ this.mediaRecorder = new MediaRecorder(this.mediaStream, {
156
+ mimeType: this.config.mimeType,
157
+ audioBitsPerSecond: this.config.audioBitsPerSecond,
158
+ });
159
+ // Verify MediaRecorder is in a valid state
160
+ if (this.mediaRecorder.state !== "inactive") {
161
+ throw new Error_1.RecordingError("MediaRecorder is in an invalid state for start()", {
162
+ context: { recorderState: this.mediaRecorder.state },
163
+ displayMessage: "Failed to start recording"
164
+ });
165
+ }
166
+ // Set up event handlers
167
+ this.setupMediaRecorderEvents();
168
+ // Start recording
169
+ this.mediaRecorder.start();
170
+ this.recordingStartTime = Date.now();
171
+ // Set up auto-pause timer if enabled
172
+ if (this.config.autoPauseEnabled) {
173
+ this.setupAutoPauseTimer();
174
+ }
175
+ }
176
+ catch (error) {
177
+ throw this.toRecordingError(error, "Failed to start audio recording", {
178
+ stage: "start",
179
+ });
180
+ }
181
+ }
182
+ async processAudioChunk(blob) {
183
+ try {
184
+ const base64Audio = await this.blobToBase64(blob);
185
+ const now = Date.now();
186
+ if (!this.onAudioData) {
187
+ return;
188
+ }
189
+ const audioData = {
190
+ audio: base64Audio,
191
+ format: this.config.mimeType,
192
+ duration: this.recordingStartTime > 0 ? now - this.recordingStartTime : 0,
193
+ timestamp: this.recordingStartTime > 0 ? this.recordingStartTime : now,
194
+ };
195
+ this.onAudioData(audioData);
196
+ }
197
+ catch (error) {
198
+ this.handleError(error, { stage: "process_audio_chunk" });
199
+ }
200
+ }
201
+ toRecordingError(error, fallbackMessage, context) {
202
+ if (error instanceof Error_1.RecordingError) {
203
+ return error;
204
+ }
205
+ if (error instanceof Error_1.SynapseError) {
206
+ return new Error_1.RecordingError(error.message, {
207
+ cause: error,
208
+ context: { ...error.context, ...context },
209
+ hint: error.hint,
210
+ });
211
+ }
212
+ const message = error instanceof Error && error.message ? error.message : fallbackMessage;
213
+ return new Error_1.RecordingError(message, {
214
+ cause: error,
215
+ context,
216
+ });
217
+ }
218
+ handleError(error, context) {
219
+ const recordingError = this.toRecordingError(error, "Unexpected recording error", context);
220
+ if (this.onAudioError) {
221
+ try {
222
+ this.onAudioError(recordingError);
223
+ }
224
+ catch (callbackError) {
225
+ console.error("Audio error callback failed:", callbackError);
226
+ }
227
+ }
228
+ else {
229
+ console.error("AudioManager error:", recordingError);
230
+ }
231
+ }
232
+ /**
233
+ * Set up auto-pause timer for 15-minute limit
234
+ */
235
+ setupAutoPauseTimer() {
236
+ if (this.autoPauseTimer) {
237
+ clearTimeout(this.autoPauseTimer);
238
+ }
239
+ this.autoPauseTimer = setTimeout(() => {
240
+ console.log("Auto-pause timer triggered after 15 minutes");
241
+ this.stop();
242
+ }, this.config.maxRecordingDuration);
243
+ }
244
+ setupMediaRecorderEvents() {
245
+ if (!this.mediaRecorder)
246
+ return;
247
+ this.mediaRecorder.ondataavailable = (event) => {
248
+ if (this.suppressCallbacks || event.data.size <= 0) {
249
+ return;
250
+ }
251
+ this.processAudioChunk(event.data).catch((error) => this.handleError(error, {
252
+ stage: "media_recorder_ondataavailable",
253
+ hasData: event.data.size > 0,
254
+ }));
255
+ };
256
+ this.mediaRecorder.onstop = async () => {
257
+ this.recordingStartTime = 0;
258
+ };
259
+ this.mediaRecorder.onerror = (event) => {
260
+ this.handleError(event.error instanceof Error
261
+ ? event.error
262
+ : new Error("MediaRecorder encountered an unknown error"), { stage: "media_recorder_onerror" });
263
+ };
264
+ this.mediaRecorder.onstart = () => {
265
+ console.log("MediaRecorder started recording");
266
+ if (this.mediaRecorder) {
267
+ console.log("MediaRecorder state:", this.mediaRecorder.state);
268
+ console.log("MediaRecorder MIME type:", this.mediaRecorder.mimeType);
269
+ }
270
+ };
271
+ }
272
+ /**
273
+ * Convert blob to base64 string
274
+ */
275
+ blobToBase64(blob) {
276
+ return new Promise((resolve, reject) => {
277
+ const reader = new FileReader();
278
+ reader.onload = () => {
279
+ if (typeof reader.result === "string") {
280
+ // Remove data URL prefix (e.g., "data:audio/mp3;base64,")
281
+ const base64 = reader.result.split(",")[1];
282
+ resolve(base64);
283
+ }
284
+ else {
285
+ reject(new Error_1.RecordingError("Failed to convert blob to base64", {
286
+ context: { stage: "blob_to_base64" },
287
+ }));
288
+ }
289
+ };
290
+ reader.onerror = () => reject(new Error_1.RecordingError("FileReader error while converting audio chunk to base64", {
291
+ cause: reader.error ?? undefined,
292
+ context: { stage: "blob_to_base64" },
293
+ }));
294
+ reader.readAsDataURL(blob);
295
+ });
296
+ }
297
+ /**
298
+ * Stop recording manually
299
+ */
300
+ stop() {
301
+ if (!this.mediaRecorder)
302
+ return;
303
+ try {
304
+ // Clear auto-pause timer
305
+ if (this.autoPauseTimer) {
306
+ clearTimeout(this.autoPauseTimer);
307
+ this.autoPauseTimer = null;
308
+ }
309
+ // Stop MediaRecorder
310
+ if (this.mediaRecorder.state === "recording") {
311
+ this.mediaRecorder.stop();
312
+ }
313
+ // Stop media stream
314
+ if (this.mediaStream) {
315
+ this.mediaStream.getTracks().forEach((track) => track.stop());
316
+ this.mediaStream = null;
317
+ }
318
+ console.log("Audio recording stopped manually");
319
+ }
320
+ catch (error) {
321
+ throw this.toRecordingError(error, "Failed to stop audio recording", {
322
+ stage: "stop",
323
+ });
324
+ }
325
+ }
326
+ /**
327
+ * Cancel recording (discard data and suppress callbacks)
328
+ */
329
+ cancel() {
330
+ if (!this.mediaRecorder)
331
+ return;
332
+ try {
333
+ this.suppressCallbacks = true;
334
+ if (this.autoPauseTimer) {
335
+ clearTimeout(this.autoPauseTimer);
336
+ this.autoPauseTimer = null;
337
+ }
338
+ // Prevent ondataavailable from pushing chunks
339
+ this.mediaRecorder.ondataavailable = null;
340
+ // Stop MediaRecorder
341
+ if (this.mediaRecorder.state === "recording") {
342
+ this.mediaRecorder.stop();
343
+ }
344
+ // Stop media stream
345
+ if (this.mediaStream) {
346
+ this.mediaStream.getTracks().forEach((track) => track.stop());
347
+ this.mediaStream = null;
348
+ }
349
+ }
350
+ catch (error) {
351
+ throw this.toRecordingError(error, "Failed to cancel audio recording", {
352
+ stage: "cancel",
353
+ });
354
+ }
355
+ }
356
+ destroy() {
357
+ try {
358
+ this.cancel();
359
+ if (this.mediaRecorder) {
360
+ this.mediaRecorder = null;
361
+ }
362
+ if (this.mediaStream) {
363
+ this.mediaStream.getTracks().forEach((track) => track.stop());
364
+ this.mediaStream = null;
365
+ }
366
+ }
367
+ catch (error) {
368
+ throw this.toRecordingError(error, "Failed to destroy audio resources", {
369
+ stage: "destroy",
370
+ });
371
+ }
372
+ }
373
+ }
374
+ exports.AudioManager = AudioManager;
@@ -1 +1 @@
1
- {"version":3,"file":"Audio.d.ts","sourceRoot":"","sources":["../../../src/media/audio/Audio.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,WAAW,EAChB,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EAExB,MAAM,SAAS,CAAC;AAGjB,qBAAa,YAAY;IACvB,OAAO,CAAC,aAAa,CAA8B;IACnD,OAAO,CAAC,WAAW,CAA4B;IAC/C,OAAO,CAAC,kBAAkB,CAAa;IACvC,OAAO,CAAC,cAAc,CAA8C;IAEpE,OAAO,CAAC,MAAM,CAAc;IAE5B,OAAO,CAAC,WAAW,CAAkC;IACrD,OAAO,CAAC,YAAY,CAAmC;IACvD,OAAO,CAAC,iBAAiB,CAAS;gBAEtB,MAAM,GAAE,OAAO,CAAC,WAAW,CAAM;YAU/B,2BAA2B;IAa5B,KAAK,CAChB,WAAW,EAAE,iBAAiB,EAC9B,YAAY,CAAC,EAAE,kBAAkB,GAChC,OAAO,CAAC,IAAI,CAAC;YAoGF,iBAAiB;IAuB/B,OAAO,CAAC,gBAAgB;IA0BxB,OAAO,CAAC,WAAW;IAmBnB;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAW3B,OAAO,CAAC,wBAAwB;IAsChC;;OAEG;IACH,OAAO,CAAC,YAAY;IA8BpB;;OAEG;IACH,IAAI,IAAI,IAAI;IA6BZ;;OAEG;IACH,MAAM,IAAI,IAAI;IAgCd,OAAO,IAAI,IAAI;CAiBhB"}
1
+ {"version":3,"file":"Audio.d.ts","sourceRoot":"","sources":["../../../src/media/audio/Audio.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,WAAW,EAChB,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EAExB,MAAM,SAAS,CAAC;AAGjB,qBAAa,YAAY;IACvB,OAAO,CAAC,aAAa,CAA8B;IACnD,OAAO,CAAC,WAAW,CAA4B;IAC/C,OAAO,CAAC,kBAAkB,CAAa;IACvC,OAAO,CAAC,cAAc,CAA8C;IAEpE,OAAO,CAAC,MAAM,CAAc;IAE5B,OAAO,CAAC,WAAW,CAAkC;IACrD,OAAO,CAAC,YAAY,CAAmC;IACvD,OAAO,CAAC,iBAAiB,CAAS;gBAEtB,MAAM,GAAE,OAAO,CAAC,WAAW,CAAM;YAU/B,2BAA2B;IA0B5B,KAAK,CAChB,WAAW,EAAE,iBAAiB,EAC9B,YAAY,CAAC,EAAE,kBAAkB,GAChC,OAAO,CAAC,IAAI,CAAC;YA6GF,iBAAiB;IAuB/B,OAAO,CAAC,gBAAgB;IA0BxB,OAAO,CAAC,WAAW;IAmBnB;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAW3B,OAAO,CAAC,wBAAwB;IAsChC;;OAEG;IACH,OAAO,CAAC,YAAY;IA8BpB;;OAEG;IACH,IAAI,IAAI,IAAI;IA6BZ;;OAEG;IACH,MAAM,IAAI,IAAI;IAgCd,OAAO,IAAI,IAAI;CAiBhB"}
@@ -21,16 +21,28 @@ class AudioManager {
21
21
  };
22
22
  }
23
23
  async checkCurrentPermissionState() {
24
- const permission = await navigator.permissions.query({
25
- name: "microphone",
26
- });
27
- if (permission.state === "denied") {
28
- throw new Error_1.RecordingError("Microphone permission denied", {
29
- context: { permissionState: permission.state },
30
- hint: "Ensure the browser has microphone access enabled for this site.",
24
+ if (!navigator.permissions || !navigator.permissions.query) {
25
+ return "prompt";
26
+ }
27
+ try {
28
+ const permission = await navigator.permissions.query({
29
+ name: "microphone",
31
30
  });
31
+ if (permission.state === "denied") {
32
+ throw new Error_1.RecordingError("Microphone permission denied", {
33
+ context: { permissionState: permission.state },
34
+ hint: "Ensure the browser has microphone access enabled for this site.",
35
+ });
36
+ }
37
+ console.log("Microphone permission state:", permission.state);
38
+ return permission.state;
32
39
  }
33
- return permission.state;
40
+ catch (error) {
41
+ console.error("Error checking microphone permission:", error);
42
+ if (error instanceof Error && error.name === "NotSupportedError")
43
+ return "prompt";
44
+ }
45
+ return "prompt";
34
46
  }
35
47
  async start(onAudioData, onAudioError //Clearly handles the error inside the callback without unhandled rejections
36
48
  ) {
@@ -72,6 +84,7 @@ class AudioManager {
72
84
  this.onAudioData = onAudioData;
73
85
  this.onAudioError = onAudioError ?? null;
74
86
  this.suppressCallbacks = false; //reset the guard against late recorder events
87
+ console.log("Getting user media");
75
88
  // Get user media
76
89
  this.mediaStream = await navigator.mediaDevices.getUserMedia({
77
90
  audio: {
@@ -82,6 +95,7 @@ class AudioManager {
82
95
  channelCount: 1,
83
96
  },
84
97
  });
98
+ console.log("Got user media");
85
99
  // Create MediaRecorder with fallback if the selected format fails
86
100
  this.mediaRecorder = new MediaRecorder(this.mediaStream, {
87
101
  mimeType: this.config.mimeType,
@@ -105,6 +119,13 @@ class AudioManager {
105
119
  }
106
120
  }
107
121
  catch (error) {
122
+ console.error("Error starting audio recording in media devices:", error);
123
+ if (error instanceof Error && error.name === "NotAllowedError") {
124
+ throw new Error_1.RecordingError("Microphone permission denied", {
125
+ context: { permissionState: "denied" },
126
+ hint: "Ensure the browser or device has microphone access enabled for this site/app.",
127
+ });
128
+ }
108
129
  throw this.toRecordingError(error, "Failed to start audio recording", {
109
130
  stage: "start",
110
131
  });
@@ -1 +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,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,KAAK,EAAwB,QAAQ,EAAE,MAAM,UAAU,CAAC;AAE/D,qBAAa,eAAe;IAC1B,OAAO,CAAC,cAAc,CAAiB;IACvC,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,OAAO,CAAU;IACzB,OAAO,CAAC,QAAQ,CAAyB;gBAE7B,MAAM,EAAE,cAAc;IAgBlC;;OAEG;IACU,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,eAAe,CAAC;IAsCxF;;;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;IAShB;;;OAGG;IACU,QAAQ,CAAC,CAAC,SAAS,gBAAgB,GAAG,gBAAgB,EACjE,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACnC,OAAO,CAAC,CAAC,CAAC;CAMd"}
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,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,KAAK,EAAwB,QAAQ,EAAE,MAAM,UAAU,CAAC;AAE/D,qBAAa,eAAe;IAC1B,OAAO,CAAC,cAAc,CAAiB;IACvC,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,OAAO,CAAU;IACzB,OAAO,CAAC,QAAQ,CAAyB;gBAE7B,MAAM,EAAE,cAAc;IAiBlC;;OAEG;IACU,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,eAAe,CAAC;IAsCxF;;;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;IAShB;;;OAGG;IACU,QAAQ,CAAC,CAAC,SAAS,gBAAgB,GAAG,gBAAgB,EACjE,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACnC,OAAO,CAAC,CAAC,CAAC;CAMd"}
@@ -20,6 +20,7 @@ class ResourceManager {
20
20
  baseUrl: this.resourceConfig.serverUrl,
21
21
  headers: {
22
22
  "X-agent-id": this.resourceConfig.agentId, // This will be included in ALL requests
23
+ ...(this.resourceConfig.authorization && { Authorization: this.resourceConfig.authorization }),
23
24
  },
24
25
  // authorization: config.authorization,
25
26
  });
@@ -40,6 +40,7 @@ export interface SynapseSDKConfig {
40
40
  overrides?: SynapseSDKOverrides;
41
41
  callbacks?: SynapseSDKCallbacks;
42
42
  context?: TContext;
43
+ auth?: string;
43
44
  serverUrl?: string;
44
45
  }
45
46
  export interface SessionConfig {
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,KAAK,EAAE,eAAe,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC7F,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAEtE,cAAc,8BAA8B,CAAC;AAC7C,cAAc,yBAAyB,CAAC;AACxC,cAAc,mBAAmB,CAAC;AAClC,cAAc,4BAA4B,CAAC;AAG3C,MAAM,WAAW,kBAAkB;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC;IACf,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,aAAa,EAAE,CAAA;CAClC;AACD,MAAM,WAAW,mBAAmB;IAClC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,MAAM,eAAe,GAAG,YAAY,GAAG,KAAK,CAAC;AACnD,MAAM,WAAW,mBAAmB;IAClC,kBAAkB,CAAC,EAAE,CAAC,eAAe,EAAE,eAAe,KAAK,IAAI,CAAC;IAGhE,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,CAAC;CAC5C;AACD,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,SAAS,CAAC,EAAE,mBAAmB,CAAC;IAChC,SAAS,CAAC,EAAE,mBAAmB,CAAC;IAChC,OAAO,CAAC,EAAE,QAAQ,CAAC;IAEnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,eAAe,CAAC;CACnC;AACD,MAAM,WAAW,sBAAsB;IACrC,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;CACvB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,KAAK,EAAE,eAAe,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC7F,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAEtE,cAAc,8BAA8B,CAAC;AAC7C,cAAc,yBAAyB,CAAC;AACxC,cAAc,mBAAmB,CAAC;AAClC,cAAc,4BAA4B,CAAC;AAG3C,MAAM,WAAW,kBAAkB;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC;IACf,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,aAAa,EAAE,CAAA;CAClC;AACD,MAAM,WAAW,mBAAmB;IAClC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,MAAM,eAAe,GAAG,YAAY,GAAG,KAAK,CAAC;AACnD,MAAM,WAAW,mBAAmB;IAClC,kBAAkB,CAAC,EAAE,CAAC,eAAe,EAAE,eAAe,KAAK,IAAI,CAAC;IAGhE,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,CAAC;CAC5C;AACD,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,SAAS,CAAC,EAAE,mBAAmB,CAAC;IAChC,SAAS,CAAC,EAAE,mBAAmB,CAAC;IAChC,OAAO,CAAC,EAAE,QAAQ,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,eAAe,CAAC;CACnC;AACD,MAAM,WAAW,sBAAsB;IACrC,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;CACvB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eka-care/medassist-core",
3
- "version": "1.0.14",
3
+ "version": "1.0.16",
4
4
  "description": "TypeScript SDK for real-time medical chatbot experiences with session management, WebSocket connectivity, and media handling",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",