med-scribe-alliance-ts-sdk 1.0.13 → 2.0.1

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 (66) hide show
  1. package/dist/index.d.ts +1066 -9
  2. package/dist/index.mjs +1823 -0
  3. package/dist/worker.bundle.js +14 -0
  4. package/package.json +21 -6
  5. package/dist/api/base.d.ts +0 -44
  6. package/dist/api/base.d.ts.map +0 -1
  7. package/dist/api/base.js +0 -119
  8. package/dist/api/discovery.d.ts +0 -30
  9. package/dist/api/discovery.d.ts.map +0 -1
  10. package/dist/api/discovery.js +0 -52
  11. package/dist/api/session.d.ts +0 -61
  12. package/dist/api/session.d.ts.map +0 -1
  13. package/dist/api/session.js +0 -96
  14. package/dist/audio/audio-buffer-manager.d.ts +0 -53
  15. package/dist/audio/audio-buffer-manager.d.ts.map +0 -1
  16. package/dist/audio/audio-buffer-manager.js +0 -109
  17. package/dist/audio/audio-file-manager.d.ts +0 -48
  18. package/dist/audio/audio-file-manager.d.ts.map +0 -1
  19. package/dist/audio/audio-file-manager.js +0 -173
  20. package/dist/audio/chunked-recorder.d.ts +0 -22
  21. package/dist/audio/chunked-recorder.d.ts.map +0 -1
  22. package/dist/audio/chunked-recorder.js +0 -119
  23. package/dist/audio/constants.d.ts +0 -19
  24. package/dist/audio/constants.d.ts.map +0 -1
  25. package/dist/audio/constants.js +0 -22
  26. package/dist/audio/index.d.ts +0 -10
  27. package/dist/audio/index.d.ts.map +0 -1
  28. package/dist/audio/index.js +0 -9
  29. package/dist/audio/recorder.interface.d.ts +0 -17
  30. package/dist/audio/recorder.interface.d.ts.map +0 -1
  31. package/dist/audio/recorder.interface.js +0 -1
  32. package/dist/audio/single-recorder.d.ts +0 -24
  33. package/dist/audio/single-recorder.d.ts.map +0 -1
  34. package/dist/audio/single-recorder.js +0 -97
  35. package/dist/audio/types.d.ts +0 -37
  36. package/dist/audio/types.d.ts.map +0 -1
  37. package/dist/audio/types.js +0 -1
  38. package/dist/audio/utils.d.ts +0 -2
  39. package/dist/audio/utils.d.ts.map +0 -1
  40. package/dist/audio/utils.js +0 -32
  41. package/dist/audio/vad-web.d.ts +0 -61
  42. package/dist/audio/vad-web.d.ts.map +0 -1
  43. package/dist/audio/vad-web.js +0 -288
  44. package/dist/client.d.ts +0 -106
  45. package/dist/client.d.ts.map +0 -1
  46. package/dist/client.js +0 -342
  47. package/dist/constants.d.ts +0 -78
  48. package/dist/constants.d.ts.map +0 -1
  49. package/dist/constants.js +0 -88
  50. package/dist/index.d.ts.map +0 -1
  51. package/dist/index.js +0 -14
  52. package/dist/types/index.d.ts +0 -169
  53. package/dist/types/index.d.ts.map +0 -1
  54. package/dist/types/index.js +0 -5
  55. package/dist/utils/errors.d.ts +0 -35
  56. package/dist/utils/errors.d.ts.map +0 -1
  57. package/dist/utils/errors.js +0 -59
  58. package/dist/utils/events.d.ts +0 -9
  59. package/dist/utils/events.d.ts.map +0 -1
  60. package/dist/utils/events.js +0 -27
  61. package/dist/utils/upload.d.ts +0 -27
  62. package/dist/utils/upload.d.ts.map +0 -1
  63. package/dist/utils/upload.js +0 -75
  64. package/dist/utils/validator.d.ts +0 -21
  65. package/dist/utils/validator.d.ts.map +0 -1
  66. package/dist/utils/validator.js +0 -140
package/dist/index.d.ts CHANGED
@@ -1,12 +1,1069 @@
1
+ export declare enum SessionStatus {
2
+ CREATED = "created",
3
+ RECORDING = "recording",
4
+ INITIALIZED = "initialized",
5
+ PROCESSING = "processing",
6
+ COMPLETED = "completed",
7
+ PARTIAL = "partial",
8
+ FAILED = "failed",
9
+ EXPIRED = "expired"
10
+ }
11
+ export declare enum TemplateStatus {
12
+ SUCCESS = "success",
13
+ FAILED = "failed",
14
+ PROCESSING = "processing"
15
+ }
16
+ export declare enum UploadType {
17
+ CHUNKED = "chunked",
18
+ SINGLE = "single"
19
+ }
20
+ export declare enum CommunicationProtocol {
21
+ WEBSOCKET = "websocket",
22
+ HTTP = "http",
23
+ RPC = "rpc"
24
+ }
25
+ export declare enum TransportMode {
26
+ DIRECT = "direct",
27
+ IPC = "ipc"
28
+ }
29
+ export declare enum ErrorCode {
30
+ AUTHENTICATION_FAILED = "authentication_failed",
31
+ TOKEN_EXPIRED = "token_expired",
32
+ INVALID_API_KEY = "invalid_api_key",
33
+ FORBIDDEN = "forbidden",
34
+ RATE_LIMIT_EXCEEDED = "rate_limit_exceeded",
35
+ SESSION_NOT_FOUND = "session_not_found",
36
+ TEMPLATE_NOT_FOUND = "template_not_found",
37
+ SESSION_EXPIRED = "session_expired",
38
+ INVALID_REQUEST = "invalid_request",
39
+ INVALID_AUDIO_FORMAT = "invalid_audio_format",
40
+ CHUNK_TOO_LARGE = "chunk_too_large",
41
+ INVALID_TEMPLATE = "invalid_template",
42
+ MISSING_REQUIRED_FIELD = "missing_required_field",
43
+ PROCESSING_FAILED = "processing_failed",
44
+ AUDIO_QUALITY_POOR = "audio_quality_poor",
45
+ AUDIO_TOO_SHORT = "audio_too_short",
46
+ LANGUAGE_UNSUPPORTED = "language_unsupported",
47
+ INTERNAL_ERROR = "internal_error",
48
+ SERVICE_UNAVAILABLE = "service_unavailable",
49
+ DISCOVERY_FAILED = "discovery_failed",
50
+ TRANSPORT_ERROR = "transport_error",
51
+ WORKER_ERROR = "worker_error",
52
+ UPLOAD_FAILED = "upload_failed",
53
+ VAD_ERROR = "vad_error"
54
+ }
55
+ export declare enum HttpStatus {
56
+ OK = 200,
57
+ CREATED = 201,
58
+ ACCEPTED = 202,
59
+ BAD_REQUEST = 400,
60
+ UNAUTHORIZED = 401,
61
+ FORBIDDEN = 403,
62
+ NOT_FOUND = 404,
63
+ GONE = 410,
64
+ PAYLOAD_TOO_LARGE = 413,
65
+ UNPROCESSABLE_ENTITY = 422,
66
+ TOO_MANY_REQUESTS = 429,
67
+ INTERNAL_SERVER_ERROR = 500,
68
+ SERVICE_UNAVAILABLE = 503
69
+ }
70
+ export declare class ScribeError extends Error {
71
+ readonly code: ErrorCode | string;
72
+ readonly httpStatus?: number;
73
+ readonly details?: Record<string, any>;
74
+ constructor(message: string, code?: ErrorCode | string, httpStatus?: number, details?: Record<string, any>);
75
+ static fromApiError(apiError: ApiError, httpStatus?: number): ScribeError;
76
+ toJSON(): Record<string, any>;
77
+ }
78
+ export declare class ValidationError extends ScribeError {
79
+ constructor(message: string, details?: Record<string, any>);
80
+ }
81
+ export declare class DiscoveryError extends ScribeError {
82
+ constructor(message: string, details?: Record<string, any>);
83
+ }
84
+ export declare class AuthenticationError extends ScribeError {
85
+ constructor(message: string, details?: Record<string, any>);
86
+ }
87
+ export declare class ForbiddenError extends ScribeError {
88
+ constructor(message: string, details?: Record<string, any>);
89
+ }
90
+ export declare class SessionNotFoundError extends ScribeError {
91
+ constructor(sessionId: string);
92
+ }
93
+ export declare class SessionExpiredError extends ScribeError {
94
+ constructor(sessionId: string, expiredAt?: string);
95
+ }
96
+ export declare class RateLimitError extends ScribeError {
97
+ constructor(retryAfter?: number);
98
+ }
99
+ export declare class TransportError extends ScribeError {
100
+ constructor(message: string, details?: Record<string, any>);
101
+ }
102
+ export declare class WorkerError extends ScribeError {
103
+ constructor(message: string, details?: Record<string, any>);
104
+ }
105
+ export declare class UploadError extends ScribeError {
106
+ readonly failedFiles: string[];
107
+ constructor(message: string, failedFiles: string[], details?: Record<string, any>);
108
+ toJSON(): Record<string, any>;
109
+ }
110
+ export interface ApiError {
111
+ code: ErrorCode | string;
112
+ message: string;
113
+ details?: Record<string, any>;
114
+ }
115
+ export interface ErrorResponse {
116
+ error: ApiError;
117
+ }
1
118
  /**
2
- * Scribe EMR Protocol SDK
3
- * TypeScript SDK for the MedScribe Alliance Protocol
119
+ * Result type for all public SDK methods.
120
+ * Expected errors (API failures, auth, validation) are returned — not thrown.
121
+ */
122
+ export type SDKResult<T = void> = {
123
+ success: true;
124
+ data: T;
125
+ } | {
126
+ success: false;
127
+ error: ScribeError;
128
+ };
129
+ /**
130
+ * Transport layer types
131
+ */
132
+ export interface TransportRequest {
133
+ method: "GET" | "POST" | "PUT" | "DELETE";
134
+ url: string;
135
+ headers?: Record<string, string>;
136
+ body?: any;
137
+ isUpload?: boolean;
138
+ uploadBlob?: Blob;
139
+ /** Additional HTTP status codes to treat as success (not throw). */
140
+ acceptStatuses?: number[];
141
+ }
142
+ export interface TransportResponse<T = any> {
143
+ status: number;
144
+ headers: Record<string, string>;
145
+ data: T;
146
+ }
147
+ export interface ITransport {
148
+ request<T = any>(config: TransportRequest): Promise<TransportResponse<T>>;
149
+ setAuthToken(token: string): void;
150
+ /** Clean up pending requests and resources. */
151
+ destroy?(): void;
152
+ }
153
+ /**
154
+ * IPC bridge provided by the consumer (e.g. Electron host)
155
+ */
156
+ export interface IpcBridge {
157
+ send: (request: IpcRequest) => void;
158
+ onResponse: (handler: (response: IpcResponse) => void) => void;
159
+ }
160
+ export interface IpcRequest {
161
+ correlationId: string;
162
+ method: string;
163
+ url: string;
164
+ headers?: Record<string, string>;
165
+ body?: any;
166
+ /** Base64-encoded blob data for uploads */
167
+ blobData?: string;
168
+ }
169
+ export interface IpcResponse {
170
+ correlationId: string;
171
+ status: number;
172
+ headers: Record<string, string>;
173
+ body: any;
174
+ error?: string;
175
+ }
176
+ export interface ScribeSDKConfig {
177
+ /** Base URL of the scribe service (required) */
178
+ baseUrl: string;
179
+ /** Bearer token authentication */
180
+ accessToken?: string;
181
+ /** Transport mode: 'direct' (HTTP fetch) or 'ipc' (Electron IPC). Default: 'direct' */
182
+ mode?: TransportMode;
183
+ /** IPC bridge — required when mode is 'ipc' */
184
+ ipcTransport?: IpcBridge;
185
+ /** SharedWorker config: true (require), false (disable), 'auto' (detect). Default: 'auto' */
186
+ useWorker?: boolean | "auto";
187
+ /** URL to the worker.bundle.js file. Use getWorkerUrl() or createWorkerBlobUrl() to resolve. */
188
+ workerScriptUrl?: string;
189
+ /** Enable debug logging. Default: false */
190
+ debug?: boolean;
191
+ /** Auto-fetch discovery document on init. Default: true */
192
+ autoDiscovery?: boolean;
193
+ }
194
+ /**
195
+ * Discovery document types (MedScribe Alliance Protocol)
196
+ */
197
+ export interface DiscoveryDocument {
198
+ protocol: string;
199
+ protocol_version: string;
200
+ supported_versions?: string[];
201
+ service?: ServiceInfo;
202
+ endpoints: EndpointsInfo;
203
+ authentication: AuthenticationInfo;
204
+ capabilities: CapabilitiesInfo;
205
+ models?: ModelConfig[];
206
+ languages: LanguagesInfo;
207
+ }
208
+ export interface ServiceInfo {
209
+ name?: string;
210
+ documentation_url?: string;
211
+ support_email?: string;
212
+ }
213
+ export interface EndpointsInfo {
214
+ base_url: string;
215
+ webhooks_url?: string;
216
+ authorization_endpoint?: string;
217
+ token_endpoint?: string;
218
+ }
219
+ export interface AuthenticationInfo {
220
+ supported_methods: string[];
221
+ oidc?: {
222
+ issuer: string;
223
+ authorization_endpoint: string;
224
+ token_endpoint: string;
225
+ scopes_supported: string[];
226
+ };
227
+ }
228
+ export interface CapabilitiesInfo {
229
+ audio_formats: string[];
230
+ max_chunk_duration_seconds: number;
231
+ upload_methods?: string[];
232
+ webhook_delivery?: boolean;
233
+ client_sdk_delivery?: boolean;
234
+ }
235
+ export interface ModelConfig {
236
+ id: string;
237
+ display_name?: string;
238
+ languages?: string[];
239
+ max_session_duration_seconds: number;
240
+ response_speed?: string;
241
+ features?: {
242
+ realtime_transcription?: boolean;
243
+ speaker_diarization?: boolean;
244
+ custom_templates?: boolean;
245
+ };
246
+ }
247
+ export interface LanguagesInfo {
248
+ supported: string[];
249
+ auto_detection?: boolean;
250
+ }
251
+ /**
252
+ * Parsed runtime configuration derived from DiscoveryDocument.
253
+ * Used by all layers at runtime for validation and configuration.
254
+ */
255
+ export interface ResolvedConfig {
256
+ baseUrl: string;
257
+ webhooksUrl?: string;
258
+ supportedLanguages: string[];
259
+ autoDetectLanguage: boolean;
260
+ supportedAudioFormats: string[];
261
+ supportedUploadMethods: string[];
262
+ maxChunkDurationSeconds: number;
263
+ /** modelId -> max session duration in seconds */
264
+ maxSessionDurationSeconds: Map<string, number>;
265
+ supportedAuthMethods: string[];
266
+ availableModels: ModelConfig[];
267
+ webhookDelivery: boolean;
268
+ clientSdkDelivery: boolean;
269
+ }
270
+ export interface CreateSessionRequest {
271
+ templates: string[];
272
+ model?: string;
273
+ language_hint?: string[];
274
+ transcript_language?: string[];
275
+ upload_type: string;
276
+ communication_protocol: string;
277
+ additional_data?: Record<string, any>;
278
+ }
279
+ export interface CreateSessionResponse {
280
+ session_id: string;
281
+ status: SessionStatus;
282
+ created_at: string;
283
+ expires_at: string;
284
+ upload_url: string;
285
+ }
286
+ export interface EndSessionRequest {
287
+ audio_files_sent: number;
288
+ }
289
+ export interface EndSessionResponse {
290
+ session_id: string;
291
+ status: SessionStatus;
292
+ message: string;
293
+ audio_files_received: number;
294
+ audio_files: string[];
295
+ }
296
+ export interface GetSessionStatusResponse {
297
+ session_id: string;
298
+ status: SessionStatus;
299
+ created_at: string;
300
+ expires_at?: string;
301
+ completed_at?: string;
302
+ model_used?: string;
303
+ language_detected?: string;
304
+ audio_files_received?: number;
305
+ audio_files?: string[];
306
+ audio_files_processed?: number;
307
+ additional_data?: Record<string, any>;
308
+ templates?: TemplatesOutput;
309
+ transcript?: string;
310
+ processing_errors?: ProcessingError[];
311
+ error?: {
312
+ code: string;
313
+ message: string;
314
+ details?: Record<string, any>;
315
+ };
316
+ }
317
+ export interface TemplatesOutput {
318
+ [templateId: string]: TemplateEntry;
319
+ }
320
+ export interface TemplateEntry {
321
+ status: TemplateStatus;
322
+ data?: any;
323
+ fhir?: any;
324
+ error?: TemplateError;
325
+ }
326
+ export interface TemplateError {
327
+ code: string;
328
+ message: string;
329
+ }
330
+ export interface ProcessingError {
331
+ type: string;
332
+ message: string;
333
+ file?: string;
334
+ }
335
+ export interface PollOptions {
336
+ maxAttempts?: number;
337
+ intervalMs?: number;
338
+ onProgress?: (status: GetSessionStatusResponse) => void;
339
+ }
340
+ export interface RecordingOptions {
341
+ templates: string[];
342
+ model?: string;
343
+ languageHint?: string[];
344
+ transcriptLanguage?: string[];
345
+ uploadType?: string;
346
+ communicationProtocol?: string;
347
+ additionalData?: Record<string, any>;
348
+ deviceId?: string;
349
+ }
350
+ export interface RecorderConfig {
351
+ accessToken?: string;
352
+ uploadUrl: string;
353
+ uploadHeaders: Record<string, string>;
354
+ sessionId: string;
355
+ }
356
+ export interface IRecorder {
357
+ initialize(session: CreateSessionResponse, config: RecorderConfig): void;
358
+ start(deviceId?: string): Promise<void>;
359
+ pause(): void;
360
+ resume(): void;
361
+ stop(): Promise<StopRecordingResult>;
362
+ reset(): void;
363
+ isPaused(): boolean;
364
+ }
365
+ export interface StopRecordingResult {
366
+ failedUploads: string[];
367
+ totalFiles: number;
368
+ }
369
+ /**
370
+ * Audio chunk metadata tracked by AudioFileManager
371
+ */
372
+ export type AudioChunkInfo = {
373
+ fileName: string;
374
+ timestamp: {
375
+ st: string;
376
+ et: string;
377
+ };
378
+ response?: string;
379
+ } & ({
380
+ status: "pending";
381
+ audioFrames: Float32Array;
382
+ fileBlob?: undefined;
383
+ } | {
384
+ status: "success";
385
+ audioFrames?: undefined;
386
+ fileBlob?: undefined;
387
+ } | {
388
+ status: "failure";
389
+ fileBlob: Blob;
390
+ audioFrames?: undefined;
391
+ });
392
+ export interface RetryUploadResult {
393
+ /** Number of files retried */
394
+ retried: number;
395
+ /** Number that succeeded on retry */
396
+ succeeded: number;
397
+ /** File names that still failed after retry */
398
+ stillFailed: string[];
399
+ }
400
+ type RecordingState$1 = "started" | "paused" | "resumed" | "ended";
401
+ export interface RecordingStateChangeEvent {
402
+ type: RecordingState$1;
403
+ timestamp: string;
404
+ data?: any;
405
+ }
406
+ export type AudioEventType = "user_speech" | "silence_warning" | "chunk_ready" | "frame_processed";
407
+ export interface AudioEventUserSpeech {
408
+ type: "user_speech";
409
+ timestamp: string;
410
+ data: {
411
+ isSpeaking: boolean;
412
+ };
413
+ }
414
+ export interface AudioEventSilenceWarning {
415
+ type: "silence_warning";
416
+ timestamp: string;
417
+ data: {
418
+ durationMs: number;
419
+ };
420
+ }
421
+ export interface AudioEventChunkReady {
422
+ type: "chunk_ready";
423
+ timestamp: string;
424
+ data: {
425
+ chunkIndex: number;
426
+ fileName: string;
427
+ };
428
+ }
429
+ export interface AudioEventFrameProcessed {
430
+ type: "frame_processed";
431
+ timestamp: string;
432
+ data: {
433
+ isSpeech: number;
434
+ notSpeech: number;
435
+ };
436
+ }
437
+ export type AudioEvent = AudioEventUserSpeech | AudioEventSilenceWarning | AudioEventChunkReady | AudioEventFrameProcessed;
438
+ export type UploadEventType = "progress" | "failed" | "retry";
439
+ export interface UploadEventProgress {
440
+ type: "progress";
441
+ timestamp: string;
442
+ data: {
443
+ successCount: number;
444
+ totalCount: number;
445
+ };
446
+ }
447
+ export interface UploadEventFailed {
448
+ type: "failed";
449
+ timestamp: string;
450
+ data: {
451
+ fileName: string;
452
+ error: string;
453
+ };
454
+ }
455
+ export interface UploadEventRetry {
456
+ type: "retry";
457
+ timestamp: string;
458
+ data: {
459
+ fileName: string;
460
+ attempt: number;
461
+ };
462
+ }
463
+ export type UploadEvent = UploadEventProgress | UploadEventFailed | UploadEventRetry;
464
+ export type SessionEventType = "created" | "ended" | "status_update" | "partial_result";
465
+ export interface SessionEventCreated {
466
+ type: "created";
467
+ timestamp: string;
468
+ data: CreateSessionResponse;
469
+ }
470
+ export interface SessionEventEnded {
471
+ type: "ended";
472
+ timestamp: string;
473
+ data: EndSessionResponse;
474
+ }
475
+ export interface SessionEventStatusUpdate {
476
+ type: "status_update";
477
+ timestamp: string;
478
+ data: GetSessionStatusResponse;
479
+ }
480
+ export interface SessionEventPartialResult {
481
+ type: "partial_result";
482
+ timestamp: string;
483
+ data: any;
484
+ }
485
+ export type SessionEvent = SessionEventCreated | SessionEventEnded | SessionEventStatusUpdate | SessionEventPartialResult;
486
+ export type ErrorEventType = "vad_error" | "worker_error" | "transport_error" | "validation_error";
487
+ interface ErrorEvent$1 {
488
+ type: ErrorEventType;
489
+ timestamp: string;
490
+ error: {
491
+ code: string;
492
+ message: string;
493
+ details?: any;
494
+ };
495
+ }
496
+ export interface TokenRequiredEvent {
497
+ resolve: (newToken: string) => void;
498
+ }
499
+ export interface CallbackMap {
500
+ onRecordingStateChange: (event: RecordingStateChangeEvent) => void;
501
+ onAudioEvent: (event: AudioEvent) => void;
502
+ onUploadEvent: (event: UploadEvent) => void;
503
+ onSessionEvent: (event: SessionEvent) => void;
504
+ onError: (event: ErrorEvent$1) => void;
505
+ onTokenRequired: (event: TokenRequiredEvent) => void;
506
+ }
507
+ export type CallbackName = keyof CallbackMap;
508
+ /**
509
+ * SharedWorker message protocol types
510
+ */
511
+ export interface WorkerCompressAndUploadMessage {
512
+ type: "compress_and_upload";
513
+ audioFrames: Float32Array;
514
+ fileName: string;
515
+ uploadUrl: string;
516
+ headers: Record<string, string>;
517
+ }
518
+ export interface WorkerWaitForUploadsMessage {
519
+ type: "wait_for_all_uploads";
520
+ }
521
+ export interface WorkerUpdateTokenMessage {
522
+ type: "update_auth_token";
523
+ token: string;
524
+ }
525
+ export interface WorkerTerminateMessage {
526
+ type: "terminate";
527
+ }
528
+ export type MainToWorkerMessage = WorkerCompressAndUploadMessage | WorkerWaitForUploadsMessage | WorkerUpdateTokenMessage | WorkerTerminateMessage;
529
+ export interface WorkerUploadSuccessMessage {
530
+ type: "upload_success";
531
+ fileName: string;
532
+ }
533
+ export interface WorkerUploadFailedMessage {
534
+ type: "upload_failed";
535
+ fileName: string;
536
+ error: string;
537
+ blob?: Blob;
538
+ }
539
+ export interface WorkerAllUploadsCompleteMessage {
540
+ type: "all_uploads_complete";
541
+ }
542
+ export interface WorkerTokenRequiredMessage {
543
+ type: "token_required";
544
+ }
545
+ export type WorkerToMainMessage = WorkerUploadSuccessMessage | WorkerUploadFailedMessage | WorkerAllUploadsCompleteMessage | WorkerTokenRequiredMessage;
546
+ export declare class ScribeClient {
547
+ private config;
548
+ private transport;
549
+ private callbackRegistry;
550
+ private validator;
551
+ private discoveryManager;
552
+ private sessionManager;
553
+ private recordingManager;
554
+ private isInitialized;
555
+ constructor(config: ScribeSDKConfig);
556
+ /**
557
+ * Initialize the SDK — fetches the discovery document if autoDiscovery is enabled.
558
+ * Must be called before starting a recording.
559
+ */
560
+ init(): Promise<SDKResult<void>>;
561
+ /**
562
+ * Start a recording session.
563
+ * Calls init() automatically if not already initialized.
564
+ */
565
+ startRecording(options: RecordingOptions): Promise<SDKResult<CreateSessionResponse>>;
566
+ /**
567
+ * Start recording for an already-created session.
568
+ * Use this when the session was created via createSession() and you want
569
+ * to attach a recorder to it.
570
+ *
571
+ * @param session - The session response from createSession()
572
+ * @param options - Upload type ('chunked' | 'single') and optional deviceId
573
+ */
574
+ startRecordingWithSession(session: CreateSessionResponse, options?: {
575
+ uploadType?: string;
576
+ deviceId?: string;
577
+ }): Promise<SDKResult<void>>;
578
+ /**
579
+ * Pause the active recording.
580
+ */
581
+ pauseRecording(): void;
582
+ /**
583
+ * Resume a paused recording.
584
+ */
585
+ resumeRecording(): void;
586
+ /**
587
+ * End the active recording — stops recorder, waits for uploads, ends session.
588
+ */
589
+ endRecording(): Promise<SDKResult<StopRecordingResult>>;
590
+ /**
591
+ * Retry uploading audio files that failed during the last recording.
592
+ * Only available after endRecording() returned failed uploads.
593
+ * Cleared on reset() or next startRecording().
594
+ */
595
+ retryFailedUploads(): Promise<SDKResult<RetryUploadResult>>;
596
+ /**
597
+ * Check if there are failed uploads from the last recording that can be retried.
598
+ */
599
+ hasFailedUploads(): boolean;
600
+ /**
601
+ * Check if a recording is currently active.
602
+ */
603
+ isRecording(): boolean;
604
+ /**
605
+ * Check if the active recording is paused.
606
+ */
607
+ isRecordingPaused(): boolean;
608
+ /**
609
+ * Create a session directly (without starting a recording).
610
+ */
611
+ createSession(sessionRequest: CreateSessionRequest): Promise<SDKResult<CreateSessionResponse>>;
612
+ /**
613
+ * Get the status of a session.
614
+ * Uses the current active session if no sessionId is provided.
615
+ *
616
+ * Pass `poll` options to keep checking until the session reaches a
617
+ * terminal state (completed, partial, failed, expired) or times out.
618
+ *
619
+ */
620
+ getSessionStatus(sessionId?: string, options?: {
621
+ poll?: PollOptions;
622
+ }): Promise<SDKResult<GetSessionStatusResponse>>;
623
+ /**
624
+ * Get the current active session, if any.
625
+ */
626
+ getCurrentSession(): CreateSessionResponse | null;
627
+ /**
628
+ * Get the resolved discovery config.
629
+ * Returns error if discovery hasn't been fetched yet.
630
+ */
631
+ getDiscoveryConfig(): SDKResult<ResolvedConfig>;
632
+ /**
633
+ * Get the raw discovery document.
634
+ */
635
+ getDiscoveryDocument(): DiscoveryDocument | null;
636
+ /**
637
+ * Force refresh the discovery document.
638
+ */
639
+ refreshDiscovery(): Promise<SDKResult<ResolvedConfig>>;
640
+ /**
641
+ * Register a callback handler.
642
+ *
643
+ * @example
644
+ * client.registerCallback('onAudioEvent', (event) => {
645
+ * if (event.type === 'user_speech') console.log('Speaking:', event.data.isSpeaking);
646
+ * });
647
+ */
648
+ registerCallback<K extends CallbackName>(name: K, handler: CallbackMap[K]): void;
649
+ /**
650
+ * Remove a previously registered callback handler.
651
+ */
652
+ removeCallback<K extends CallbackName>(name: K, handler: CallbackMap[K]): void;
653
+ /**
654
+ * Update the Bearer token. Propagates to transport, active recorder, and worker.
655
+ */
656
+ setAccessToken(token: string): void;
657
+ /**
658
+ * Full reset — stops recording if active, clears all caches and state.
659
+ */
660
+ reset(): Promise<void>;
661
+ /**
662
+ * Wraps an async operation into SDKResult.
663
+ * Internal layers throw — this converts to { success, data/error }.
664
+ */
665
+ private wrapResult;
666
+ /**
667
+ * Ensures any error is a ScribeError instance.
668
+ */
669
+ private toScribeError;
670
+ /**
671
+ * Create the transport layer (HTTP or IPC) with 401 auto-retry wiring.
672
+ *
673
+ * How 401 auto-retry works:
674
+ * 1. Transport gets a 401 response → calls onUnauthorized()
675
+ * 2. onUnauthorized dispatches the 'onTokenRequired' callback to the consumer
676
+ * 3. Consumer calls resolve(newToken) → token is propagated via setAccessToken()
677
+ * 4. Promise resolves with the new token → transport retries the request once
678
+ *
679
+ * Deduplication: Transport holds a single tokenRefreshPromise — if multiple
680
+ * requests get 401 concurrently, they all await the same promise, so only
681
+ * ONE onTokenRequired callback fires regardless of how many requests failed.
682
+ *
683
+ * Timeout: If no handler is registered or the consumer never calls resolve(),
684
+ * the promise resolves with undefined after 10s → transport skips retry.
685
+ */
686
+ private createTransport;
687
+ private resolveWorkerConfig;
688
+ /**
689
+ * Get the effective base URL — prefer discovery's base_url, fall back to config.
690
+ */
691
+ private getEffectiveBaseUrl;
692
+ private validateConfig;
693
+ }
694
+ export declare class CallbackRegistry {
695
+ private handlers;
696
+ /**
697
+ * Register a handler for a callback name.
698
+ * The same handler reference won't be added twice.
699
+ */
700
+ register<K extends CallbackName>(name: K, handler: CallbackMap[K]): void;
701
+ /**
702
+ * Remove a previously registered handler.
703
+ */
704
+ remove<K extends CallbackName>(name: K, handler: CallbackMap[K]): void;
705
+ /**
706
+ * Remove all handlers for a specific callback name,
707
+ * or all handlers entirely if no name is provided.
708
+ */
709
+ removeAll(name?: CallbackName): void;
710
+ /**
711
+ * Dispatch an event to all registered handlers for the given callback name.
712
+ * Each handler is invoked in a try/catch — one failing handler does not
713
+ * prevent other handlers from executing.
714
+ */
715
+ dispatch<K extends CallbackName>(name: K, event: Parameters<CallbackMap[K]>[0]): void;
716
+ /**
717
+ * Check if any handlers are registered for a callback name.
718
+ */
719
+ hasHandlers(name: CallbackName): boolean;
720
+ }
721
+ export declare class Validator {
722
+ validateDiscoveryResponse(data: unknown): void;
723
+ validateCreateSessionRequest(data: unknown): void;
724
+ validateEndSessionRequest(data: unknown): void;
725
+ validateCreateSessionResponse(data: unknown): void;
726
+ validateEndSessionResponse(data: unknown): void;
727
+ validateGetSessionStatusResponse(data: unknown): void;
728
+ validateSessionId(sessionId: unknown): void;
729
+ validateRecordingOptions(data: unknown): void;
730
+ /**
731
+ * Cross-validates recording options against the server's declared capabilities.
732
+ * Throws ValidationError with a descriptive message if any check fails.
733
+ */
734
+ validateAgainstDiscovery(options: RecordingOptions, config: ResolvedConfig): void;
735
+ /**
736
+ * Parses data against a Zod schema. On failure, converts ZodError
737
+ * into our ValidationError with a human-readable message.
738
+ */
739
+ private parseWithValidationError;
740
+ private formatZodIssues;
741
+ private checkUploadType;
742
+ private checkLanguageHint;
743
+ private checkModel;
744
+ }
745
+ export declare class DiscoveryManager {
746
+ private transport;
747
+ private validator;
748
+ private debug;
749
+ private cachedDocument;
750
+ private resolvedConfig;
751
+ private cacheTimestamp;
752
+ private cacheTtlMs;
753
+ constructor(transport: ITransport, validator: Validator, debug?: boolean);
754
+ /**
755
+ * Fetch and validate the discovery document from the well-known endpoint.
756
+ * Caches the result for 1 hour (configurable).
757
+ */
758
+ fetchDiscovery(baseUrl: string, forceRefresh?: boolean): Promise<ResolvedConfig>;
759
+ /**
760
+ * Get the resolved runtime config. Throws if discovery hasn't been fetched.
761
+ */
762
+ getResolvedConfig(): ResolvedConfig;
763
+ /**
764
+ * Get the raw discovery document as received from the server.
765
+ */
766
+ getDiscoveryDocument(): DiscoveryDocument | null;
767
+ getSupportedLanguages(): string[];
768
+ getSupportedAudioFormats(): string[];
769
+ getSupportedUploadMethods(): string[];
770
+ getAvailableModels(): ModelConfig[];
771
+ getMaxChunkDuration(): number;
772
+ getMaxSessionDuration(modelId?: string): number;
773
+ getServiceInfo(): ServiceInfo | undefined;
774
+ getCapabilities(): CapabilitiesInfo | undefined;
775
+ isFeatureSupported(feature: "realtime_transcription" | "speaker_diarization" | "custom_templates"): boolean;
776
+ clearCache(): void;
777
+ private isCacheValid;
778
+ }
779
+ export declare class SessionManager {
780
+ private transport;
781
+ private validator;
782
+ private debug;
783
+ private currentSession;
784
+ constructor(transport: ITransport, validator: Validator, debug?: boolean);
785
+ /**
786
+ * Create a new scribe session.
787
+ * Validates the request structure, sends to server, validates response.
788
+ */
789
+ createSession(baseUrl: string, request: CreateSessionRequest): Promise<CreateSessionResponse>;
790
+ /**
791
+ * End an active session.
792
+ * If no sessionId is provided, ends the current session.
793
+ */
794
+ endSession(baseUrl: string, request: EndSessionRequest, sessionId?: string): Promise<EndSessionResponse>;
795
+ /**
796
+ * Get the status of a session.
797
+ * If no sessionId is provided, queries the current session.
798
+ */
799
+ getSessionStatus(baseUrl: string, sessionId?: string): Promise<GetSessionStatusResponse>;
800
+ /**
801
+ * Poll for session completion.
802
+ * Keeps checking getSessionStatus until the session reaches a terminal state
803
+ * (completed, partial, or failed) or the max attempts are exhausted.
804
+ */
805
+ pollForCompletion(baseUrl: string, sessionId?: string, options?: PollOptions): Promise<GetSessionStatusResponse>;
806
+ /**
807
+ * Get the current active session, if any.
808
+ */
809
+ getCurrentSession(): CreateSessionResponse | null;
810
+ /**
811
+ * Clear the current session reference.
812
+ * Used when recording is stopped or session is explicitly cleared.
813
+ */
814
+ clearCurrentSession(): void;
815
+ /**
816
+ * Check if a session status is terminal (no more processing will happen).
817
+ */
818
+ private isTerminalStatus;
819
+ private sleep;
820
+ }
821
+ export interface WorkerManagerConfig {
822
+ /** Path to the compiled shared-worker.js bundle. Required for SharedWorker mode. */
823
+ workerScriptUrl?: string;
824
+ /** If true, skip SharedWorker and always run on main thread via ITransport. */
825
+ forceMainThread?: boolean;
826
+ }
827
+ export interface RecordingManagerConfig {
828
+ workerConfig?: WorkerManagerConfig;
829
+ debug?: boolean;
830
+ }
831
+ export declare class RecordingManager {
832
+ private callbackRegistry;
833
+ private sessionManager;
834
+ private discoveryManager;
835
+ private transport;
836
+ private config;
837
+ private recorder;
838
+ private activeSession;
839
+ private activeBaseUrl;
840
+ private _isRecording;
841
+ private _isStarting;
842
+ private retryContext;
843
+ constructor(callbackRegistry: CallbackRegistry, sessionManager: SessionManager, discoveryManager: DiscoveryManager, transport: ITransport, config?: RecordingManagerConfig);
844
+ /**
845
+ * Start a recording session:
846
+ * 1. Map RecordingOptions → CreateSessionRequest
847
+ * 2. Create session via SessionManager
848
+ * 3. Create and initialize the appropriate recorder
849
+ * 4. Start recording
850
+ * 5. Dispatch events
851
+ *
852
+ * @param baseUrl - Server base URL (from discovery or SDK config)
853
+ * @param options - Recording options (templates, model, etc.)
854
+ * @param accessToken - Current Bearer token for upload auth headers
855
+ * @returns The created session response
856
+ */
857
+ start(baseUrl: string, options: RecordingOptions, accessToken?: string): Promise<CreateSessionResponse>;
858
+ /**
859
+ * Start recording for an already-created session.
860
+ * Use this when the session was created externally (e.g. via createSession())
861
+ * and you want to attach a recorder to it.
862
+ *
863
+ * @param baseUrl - Server base URL for ending session later
864
+ * @param session - The existing session response (must have upload_url)
865
+ * @param options - Upload type and optional device ID
866
+ * @param accessToken - Current Bearer token for upload auth headers
867
+ */
868
+ startWithExistingSession(baseUrl: string, session: CreateSessionResponse, options?: {
869
+ uploadType?: string;
870
+ deviceId?: string;
871
+ }, accessToken?: string): Promise<void>;
872
+ /**
873
+ * Pause the active recording.
874
+ */
875
+ pause(): void;
876
+ /**
877
+ * Resume a paused recording.
878
+ */
879
+ resume(): void;
880
+ /**
881
+ * Stop the active recording:
882
+ * 1. Stop recorder (flushes remaining audio, waits for uploads)
883
+ * 2. End session via SessionManager (sends audio_files_sent count)
884
+ * 3. Clean up state
885
+ * 4. Dispatch events
886
+ *
887
+ * @returns Stop result with failed uploads and total files
888
+ */
889
+ stop(): Promise<StopRecordingResult>;
890
+ /**
891
+ * Update the auth token for the active recording.
892
+ * Forwards to the active recorder (which updates WorkerManager/transport).
893
+ */
894
+ updateAuthToken(token: string): void;
895
+ /**
896
+ * Reset everything — force-stops if recording, clears state.
897
+ */
898
+ reset(): void;
899
+ isRecording(): boolean;
900
+ isPaused(): boolean;
901
+ getActiveSession(): CreateSessionResponse | null;
902
+ /**
903
+ * Check if there are failed uploads from the last recording that can be retried.
904
+ */
905
+ hasFailedUploads(): boolean;
906
+ /**
907
+ * Retry uploading audio files that failed during the last recording.
908
+ * Uses the stored MP3 blobs and the original upload URL.
909
+ *
910
+ * Each file is re-uploaded via transport.request() with retry logic.
911
+ * Successfully retried files are removed from the retry context.
912
+ */
913
+ retryFailedUploads(): Promise<RetryUploadResult>;
914
+ /**
915
+ * Create the appropriate recorder based on upload type.
916
+ */
917
+ private createRecorder;
918
+ /**
919
+ * Build upload headers from the current auth state.
920
+ */
921
+ private buildUploadHeaders;
922
+ /**
923
+ * Apply discovery-driven overrides to ChunkedRecorder's VAD config.
924
+ * For example, max_chunk_duration_seconds from discovery overrides the default.
925
+ */
926
+ private applyDiscoveryOverrides;
927
+ /**
928
+ * Dispatch an error event for a specific start() step failure.
929
+ */
930
+ private dispatchStartError;
931
+ /**
932
+ * Extract failed chunks with their MP3 blobs from the recorder's FileManager
933
+ * before cleanup destroys the recorder state.
934
+ */
935
+ private preserveRetryContext;
936
+ /**
937
+ * Clean up recording state after stop or error.
938
+ */
939
+ private cleanupRecordingState;
940
+ }
941
+ export declare class HttpTransport implements ITransport {
942
+ private accessToken?;
943
+ private debug;
944
+ private onUnauthorized?;
945
+ private tokenRefreshPromise;
946
+ constructor(options: {
947
+ accessToken?: string;
948
+ debug?: boolean;
949
+ onUnauthorized?: () => Promise<string | undefined>;
950
+ });
951
+ setAuthToken(token: string): void;
952
+ request<T = any>(config: TransportRequest): Promise<TransportResponse<T>>;
953
+ private executeRequest;
954
+ /**
955
+ * Execute a single fetch call with current auth headers.
956
+ */
957
+ private doFetch;
958
+ /**
959
+ * Deduplicated token refresh.
960
+ * If multiple requests get 401 simultaneously, only one onTokenRequired
961
+ * callback fires — the rest await the same promise.
962
+ */
963
+ private refreshToken;
964
+ private buildHeaders;
965
+ private buildRequestInit;
966
+ private buildSuccessResponse;
967
+ /**
968
+ * Maps HTTP error responses to typed SDK errors and throws.
969
+ * 401 is NOT handled here — it's handled in executeRequest with auto-retry.
970
+ */
971
+ private handleErrorResponse;
972
+ private extractHeaders;
973
+ private getRetryOptions;
974
+ }
975
+ export declare class IpcTransport implements ITransport {
976
+ private bridge;
977
+ private pendingRequests;
978
+ private accessToken?;
979
+ private debug;
980
+ private correlationCounter;
981
+ private onUnauthorized?;
982
+ private tokenRefreshPromise;
983
+ constructor(options: {
984
+ bridge: IpcBridge;
985
+ accessToken?: string;
986
+ debug?: boolean;
987
+ onUnauthorized?: () => Promise<string | undefined>;
988
+ });
989
+ setAuthToken(token: string): void;
990
+ request<T = any>(config: TransportRequest): Promise<TransportResponse<T>>;
991
+ private executeRequest;
992
+ /**
993
+ * Execute a single IPC request with current auth headers.
994
+ */
995
+ private doIpcRequest;
996
+ /**
997
+ * Deduplicated token refresh.
998
+ * If multiple requests get 401 simultaneously, only one onTokenRequired
999
+ * callback fires — the rest await the same promise.
1000
+ */
1001
+ private refreshToken;
1002
+ private buildHeaders;
1003
+ private buildIpcRequest;
1004
+ private sendAndWait;
1005
+ private handleResponse;
1006
+ /**
1007
+ * Maps IPC error responses to typed SDK errors and throws.
1008
+ * 401 is NOT handled here — it's handled in executeRequest with auto-retry.
1009
+ */
1010
+ private handleErrorResponse;
1011
+ private generateCorrelationId;
1012
+ private uint8ArrayToBase64;
1013
+ private getRetryOptions;
1014
+ /**
1015
+ * Clean up pending requests (e.g. on SDK reset).
1016
+ */
1017
+ destroy(): void;
1018
+ }
1019
+ /**
1020
+ * Returns the best-guess URL for the SharedWorker bundle.
1021
+ *
1022
+ * @example
1023
+ * ```ts
1024
+ * import { ScribeClient, getWorkerUrl } from 'med-scribe-alliance-ts-sdk';
1025
+ *
1026
+ * const client = new ScribeClient({
1027
+ * baseUrl: 'https://api.example.com',
1028
+ * workerScriptUrl: getWorkerUrl(),
1029
+ * });
1030
+ * ```
1031
+ *
1032
+ * @example
1033
+ * ```ts
1034
+ * // Global override (set before SDK loads)
1035
+ * window.__MEDSCRIBE_WORKER_URL__ = '/assets/worker.bundle.js';
1036
+ * ```
1037
+ *
1038
+ * @example
1039
+ * ```ts
1040
+ * // CDN blob URL (works around CORS restrictions on SharedWorker)
1041
+ * const workerUrl = await createWorkerBlobUrl();
1042
+ * ```
1043
+ */
1044
+ export declare function getWorkerUrl(): string;
1045
+ /**
1046
+ * Fetches the worker script from a URL and creates a blob URL.
1047
+ * Useful when the worker file is on a CDN (SharedWorker requires same-origin).
1048
+ *
1049
+ * @param url - URL to fetch the worker script from.
1050
+ * Defaults to jsDelivr CDN for this package.
1051
+ * @returns A blob URL that can be used as workerScriptUrl
4
1052
  *
5
- * @packageDocumentation
1053
+ * @example
1054
+ * ```ts
1055
+ * const workerUrl = await createWorkerBlobUrl();
1056
+ * const client = new ScribeClient({
1057
+ * baseUrl: 'https://api.example.com',
1058
+ * workerScriptUrl: workerUrl,
1059
+ * });
1060
+ * ```
6
1061
  */
7
- export { ScribeClient, getScribeInstance } from './client';
8
- export type { ScribeSDKConfig, RecordingOptions, DiscoveryDocument, CreateSessionResponse, GetSessionStatusResponse, EndSessionResponse, TemplatesOutput, TemplateEntry, ApiError, SDKEvent, SDKEventType, ServiceInfo, EndpointsInfo, AuthenticationInfo, CapabilitiesInfo, ModelConfig, LanguagesInfo, CreateSessionRequest, TemplateError, ProcessingError, ErrorResponse, } from './types';
9
- export { SessionStatus, TemplateStatus, UploadType, ErrorCode, HttpStatus } from './constants';
10
- export { ScribeError, AuthenticationError, SessionNotFoundError, SessionExpiredError, RateLimitError, ValidationError, } from './utils/errors';
11
- export { schemaValidator } from './utils/validator';
12
- //# sourceMappingURL=index.d.ts.map
1062
+ export declare function createWorkerBlobUrl(url?: string): Promise<string>;
1063
+
1064
+ export {
1065
+ ErrorEvent$1 as ErrorEvent,
1066
+ RecordingState$1 as RecordingState,
1067
+ };
1068
+
1069
+ export {};