med-scribe-alliance-ts-sdk 2.0.32 → 2.0.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +46 -2
- package/dist/index.d.ts +93 -6
- package/dist/index.mjs +335 -204
- package/dist/worker.bundle.js +67 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -198,6 +198,8 @@ await client.reset(); // stops recording if active, clears all state and caches
|
|
|
198
198
|
- **`cancelSession()` does NOT trigger processing.** It stops the recorder locally, cleans up state, and tells the server the session is cancelled. No `endSession` call is made to the backend.
|
|
199
199
|
- **All async methods return `SDKResult<T>`, never throw.** Always check `result.success` before accessing `result.data`. Errors are in `result.error`.
|
|
200
200
|
- **The SDK validates inputs against the discovery document.** If the server doesn't support an upload type, language, or model you requested, you'll get a `ValidationError` before the API call is made.
|
|
201
|
+
- **Audio uploads go to a server-selected storage backend.** Discovery's `capabilities.storage_provider` (default `aws`) decides the backend; uploads go directly to it (e.g. S3 presigned POST).
|
|
202
|
+
|
|
201
203
|
- **SharedWorker is optional.** If you provide `workerScriptUrl`, the SDK offloads MP3 compression and upload to a SharedWorker. If the worker fails to load, it silently falls back to main-thread processing.
|
|
202
204
|
- **Microphone permission is requested on `startRecording()`.** The browser will prompt the user for mic access. If denied, you'll get an error via `onError` callback.
|
|
203
205
|
- **`reset()` is a full teardown.** It destroys the transport, clears discovery cache, removes all callbacks, and sets the client back to uninitialized state. You'll need to call `init()` (or `startRecording()`) again after reset.
|
|
@@ -273,6 +275,42 @@ if (client.hasFailedUploads()) {
|
|
|
273
275
|
}
|
|
274
276
|
```
|
|
275
277
|
|
|
278
|
+
### Upload a Pre-recorded Audio File
|
|
279
|
+
|
|
280
|
+
For processing an already-recorded file (no mic/VAD). Create a session, then upload the file using the session's `upload_url`, then end the session and poll.
|
|
281
|
+
|
|
282
|
+
```ts
|
|
283
|
+
// 1. Create a session (gives you upload_url)
|
|
284
|
+
const session = await client.createSession({
|
|
285
|
+
templates: ['soap'],
|
|
286
|
+
upload_type: 'single',
|
|
287
|
+
communication_protocol: 'http',
|
|
288
|
+
});
|
|
289
|
+
if (!session.success) return;
|
|
290
|
+
|
|
291
|
+
// 2. Upload the file to storage using the session's upload_url
|
|
292
|
+
const upload = await client.uploadAudioFile(
|
|
293
|
+
myAudioFile,
|
|
294
|
+
'audio_0.mp3', // storage object name
|
|
295
|
+
session.data.upload_url
|
|
296
|
+
);
|
|
297
|
+
if (!upload.success) {
|
|
298
|
+
console.error('Upload failed:', upload.error.message);
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
console.log(upload.data.status, upload.data.headers); // full storage response
|
|
302
|
+
|
|
303
|
+
// 3. End the session to trigger processing, then poll getSessionStatus()
|
|
304
|
+
await client.endSession(
|
|
305
|
+
{ audio_files_sent: 1, audio_files_uploaded: 1 },
|
|
306
|
+
session.data.session_id
|
|
307
|
+
);
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
- `file` is a `File`/`Blob`; `fileName` is the storage object name; `upload` is the `upload_url` object from the create-session response.
|
|
311
|
+
- Returns `UploadAudioFileResult` — `{ fileName, status, headers, response }` (the full storage response; the body is usually empty for an S3 presigned POST).
|
|
312
|
+
- Failures (network, malformed `upload_url`) come back as `UploadError` in `result.error`; an unknown provider as `UnsupportedStorageProviderError`.
|
|
313
|
+
|
|
276
314
|
### Update Auth Token
|
|
277
315
|
|
|
278
316
|
```ts
|
|
@@ -351,6 +389,7 @@ interface RecordingOptions {
|
|
|
351
389
|
| `isRecordingPaused()` | `boolean` | Whether the active recording is paused. |
|
|
352
390
|
| `retryFailedUploads()` | `SDKResult<RetryUploadResult>` | Retry uploads that failed during the last recording. |
|
|
353
391
|
| `hasFailedUploads()` | `boolean` | Whether there are retryable failed uploads. |
|
|
392
|
+
| `uploadAudioFile(file, fileName, upload)` | `SDKResult<UploadAudioFileResult>` | Upload one pre-recorded audio file to storage using a session's `upload_url`. No mic/recorder. |
|
|
354
393
|
|
|
355
394
|
### Session
|
|
356
395
|
|
|
@@ -457,10 +496,12 @@ interface CreateSessionResponse {
|
|
|
457
496
|
status: SessionStatus;
|
|
458
497
|
created_at: string;
|
|
459
498
|
expires_at: string;
|
|
460
|
-
upload_url:
|
|
499
|
+
upload_url: SessionUploadInfo;
|
|
461
500
|
patient_details?: PatientDetails;
|
|
462
501
|
}
|
|
463
502
|
|
|
503
|
+
type SessionUploadInfo = Record<string, unknown>;
|
|
504
|
+
|
|
464
505
|
interface PatchSessionRequest {
|
|
465
506
|
user_status?: string;
|
|
466
507
|
processing_status?: string;
|
|
@@ -585,7 +626,8 @@ console.log(result.data.session_id);
|
|
|
585
626
|
| `DiscoveryError` | — | Discovery fetch/parse failed |
|
|
586
627
|
| `TransportError` | — | Network / IPC failure |
|
|
587
628
|
| `WorkerError` | — | SharedWorker failure |
|
|
588
|
-
| `UploadError` | — | Audio upload failure |
|
|
629
|
+
| `UploadError` | — | Audio upload failure (failed transfer, or malformed `upload_url` payload). Has `failedFiles: string[]`. |
|
|
630
|
+
| `UnsupportedStorageProviderError` | — | Discovery advertised a `storage_provider` this SDK build has no wrapper for. Thrown at `startRecording`. Has `provider: string`. |
|
|
589
631
|
|
|
590
632
|
## SharedWorker Support
|
|
591
633
|
|
|
@@ -648,6 +690,8 @@ const client = new ScribeClient({
|
|
|
648
690
|
|
|
649
691
|
IPC mode always uses main-thread compression (SharedWorker can't access the IPC bridge).
|
|
650
692
|
|
|
693
|
+
> **Presigned uploads over IPC need host support.** The SDK forwards `uploadFormFields` + base64 file (`blobData`) in the `IpcRequest`; your host must build the `multipart/form-data` POST (no `Authorization` header). Browser/HTTP mode works out of the box.
|
|
694
|
+
|
|
651
695
|
## Building from Source
|
|
652
696
|
|
|
653
697
|
```bash
|
package/dist/index.d.ts
CHANGED
|
@@ -98,7 +98,8 @@ export declare enum ErrorCode {
|
|
|
98
98
|
VAD_START_FAILED = "vad_start_failed",
|
|
99
99
|
STOP_FAILED = "stop_failed",
|
|
100
100
|
INTERNAL_RETRY_FAILED = "internal_retry_failed",
|
|
101
|
-
SESSION_END_FAILED = "session_end_failed"
|
|
101
|
+
SESSION_END_FAILED = "session_end_failed",
|
|
102
|
+
UNSUPPORTED_STORAGE_PROVIDER = "unsupported_storage_provider"
|
|
102
103
|
}
|
|
103
104
|
export declare enum HttpStatus {
|
|
104
105
|
OK = 200,
|
|
@@ -155,6 +156,11 @@ export declare class UploadError extends ScribeError {
|
|
|
155
156
|
constructor(message: string, failedFiles: string[], details?: Record<string, any>);
|
|
156
157
|
toJSON(): Record<string, any>;
|
|
157
158
|
}
|
|
159
|
+
/** Thrown when discovery advertises a storage provider the SDK has no wrapper for. */
|
|
160
|
+
export declare class UnsupportedStorageProviderError extends ScribeError {
|
|
161
|
+
readonly provider: string;
|
|
162
|
+
constructor(provider: string);
|
|
163
|
+
}
|
|
158
164
|
export interface ApiError {
|
|
159
165
|
code: ErrorCode | string;
|
|
160
166
|
message: string;
|
|
@@ -201,6 +207,13 @@ export interface TransportRequest {
|
|
|
201
207
|
body?: any;
|
|
202
208
|
isUpload?: boolean;
|
|
203
209
|
uploadBlob?: Blob;
|
|
210
|
+
uploadFileName?: string;
|
|
211
|
+
/** Multipart form fields; when set, the request is multipart/form-data with uploadBlob as the file. */
|
|
212
|
+
uploadFormFields?: Record<string, string>;
|
|
213
|
+
/** Multipart field name for the file part. Defaults to 'file'. */
|
|
214
|
+
uploadFileFieldName?: string;
|
|
215
|
+
/** Attach the service Bearer + flavour header. Defaults to true; false for presigned uploads. */
|
|
216
|
+
attachAuth?: boolean;
|
|
204
217
|
/** Additional HTTP status codes to treat as success (not throw). */
|
|
205
218
|
acceptStatuses?: number[];
|
|
206
219
|
maxRetries?: number;
|
|
@@ -229,8 +242,14 @@ export interface IpcRequest {
|
|
|
229
242
|
url: string;
|
|
230
243
|
headers?: Record<string, string>;
|
|
231
244
|
body?: any;
|
|
232
|
-
/** Base64-encoded
|
|
245
|
+
/** Base64-encoded file bytes for uploads. */
|
|
233
246
|
blobData?: string;
|
|
247
|
+
/** Multipart fields for presigned uploads — host builds multipart from these + blobData (no auth header). */
|
|
248
|
+
uploadFormFields?: Record<string, string>;
|
|
249
|
+
/** Multipart field name for the file part. Defaults to 'file'. */
|
|
250
|
+
uploadFileFieldName?: string;
|
|
251
|
+
/** File name for the multipart file part. */
|
|
252
|
+
uploadFileName?: string;
|
|
234
253
|
}
|
|
235
254
|
export interface IpcResponse {
|
|
236
255
|
correlationId: string;
|
|
@@ -304,6 +323,7 @@ export interface CapabilitiesInfo {
|
|
|
304
323
|
upload_methods?: string[];
|
|
305
324
|
webhook_delivery?: boolean;
|
|
306
325
|
client_sdk_delivery?: boolean;
|
|
326
|
+
storage_provider?: string;
|
|
307
327
|
}
|
|
308
328
|
export interface ModelConfig {
|
|
309
329
|
id: string;
|
|
@@ -332,6 +352,7 @@ export interface ResolvedConfig {
|
|
|
332
352
|
autoDetectLanguage: boolean;
|
|
333
353
|
supportedAudioFormats: string[];
|
|
334
354
|
supportedUploadMethods: string[];
|
|
355
|
+
storageProvider: string;
|
|
335
356
|
maxChunkDurationSeconds: number;
|
|
336
357
|
/** modelId -> max session duration in seconds */
|
|
337
358
|
maxSessionDurationSeconds: Map<string, number>;
|
|
@@ -360,12 +381,14 @@ export interface CreateSessionRequest {
|
|
|
360
381
|
patient_details?: PatientDetails;
|
|
361
382
|
session_id?: string;
|
|
362
383
|
}
|
|
384
|
+
/** Provider-specific upload payload; validated/interpreted by the StorageProvider, not the session schema. */
|
|
385
|
+
export type SessionUploadInfo = Record<string, unknown>;
|
|
363
386
|
export interface CreateSessionResponse {
|
|
364
387
|
session_id: string;
|
|
365
388
|
status: SessionStatus;
|
|
366
389
|
created_at: string;
|
|
367
390
|
expires_at: string;
|
|
368
|
-
upload_url:
|
|
391
|
+
upload_url: SessionUploadInfo;
|
|
369
392
|
patient_details?: PatientDetails;
|
|
370
393
|
}
|
|
371
394
|
export interface EndSessionRequest {
|
|
@@ -472,7 +495,9 @@ export interface RecordingOptions {
|
|
|
472
495
|
}
|
|
473
496
|
export interface RecorderConfig {
|
|
474
497
|
accessToken?: string;
|
|
475
|
-
|
|
498
|
+
/** Provider-specific upload payload from the create-session response. */
|
|
499
|
+
upload: SessionUploadInfo;
|
|
500
|
+
storageProvider: string;
|
|
476
501
|
uploadHeaders: Record<string, string>;
|
|
477
502
|
sessionId: string;
|
|
478
503
|
}
|
|
@@ -527,6 +552,17 @@ export interface RetryUploadResult {
|
|
|
527
552
|
/** File names that still failed after retry */
|
|
528
553
|
stillFailed: string[];
|
|
529
554
|
}
|
|
555
|
+
/** Result of ScribeClient.uploadAudioFile() — the storage backend's full response. */
|
|
556
|
+
export interface UploadAudioFileResult {
|
|
557
|
+
/** The storage object name used. */
|
|
558
|
+
fileName: string;
|
|
559
|
+
/** HTTP status from the storage backend (e.g. 204 for an S3 presigned POST). */
|
|
560
|
+
status: number;
|
|
561
|
+
/** Response headers from the storage backend (e.g. ETag). */
|
|
562
|
+
headers: Record<string, string>;
|
|
563
|
+
/** Raw response body from the storage backend (often empty for S3). */
|
|
564
|
+
response: unknown;
|
|
565
|
+
}
|
|
530
566
|
export interface RecordingStateChangeEvent {
|
|
531
567
|
type: RecordingState$1;
|
|
532
568
|
timestamp: string;
|
|
@@ -648,7 +684,9 @@ export interface WorkerCompressAndUploadMessage {
|
|
|
648
684
|
type: "compress_and_upload";
|
|
649
685
|
audioFrames: Float32Array;
|
|
650
686
|
fileName: string;
|
|
651
|
-
|
|
687
|
+
storageProvider: string;
|
|
688
|
+
/** Provider-specific upload payload from the create-session response. */
|
|
689
|
+
upload: unknown;
|
|
652
690
|
headers: Record<string, string>;
|
|
653
691
|
}
|
|
654
692
|
export interface WorkerWaitForUploadsMessage {
|
|
@@ -758,6 +796,14 @@ export declare class ScribeClient {
|
|
|
758
796
|
* Call this after receiving a 'chunk_limit_reached' error to resume chunk uploads.
|
|
759
797
|
*/
|
|
760
798
|
forceAllowMoreChunks(): void;
|
|
799
|
+
/**
|
|
800
|
+
* Upload a single pre-recorded audio file to storage.
|
|
801
|
+
* @param file - The audio file/blob to upload.
|
|
802
|
+
* @param upload - The `upload_url` payload from the create-session response.
|
|
803
|
+
* @param options.fileName - Storage object name. Defaults to the File's name,
|
|
804
|
+
* else `audio_0.<ext>` derived from the MIME type.
|
|
805
|
+
*/
|
|
806
|
+
uploadAudioFile(file: Blob, fileName: string, upload: SessionUploadInfo): Promise<SDKResult<UploadAudioFileResult>>;
|
|
761
807
|
/**
|
|
762
808
|
* Create a session directly (without starting a recording).
|
|
763
809
|
*/
|
|
@@ -871,12 +917,49 @@ export declare class ScribeClient {
|
|
|
871
917
|
*/
|
|
872
918
|
private createTransport;
|
|
873
919
|
private resolveWorkerConfig;
|
|
920
|
+
/** Storage provider name from discovery; defaults to 'aws'. */
|
|
921
|
+
private getStorageProviderName;
|
|
874
922
|
/**
|
|
875
923
|
* Get the effective base URL — prefer discovery's base_url, fall back to config.
|
|
876
924
|
*/
|
|
877
925
|
private getEffectiveBaseUrl;
|
|
878
926
|
private validateConfig;
|
|
879
927
|
}
|
|
928
|
+
/**
|
|
929
|
+
* Storage provider abstraction — the only part of the upload flow that varies
|
|
930
|
+
* between backends (AWS S3, GCP, ...). A provider is a pure, DOM-free request
|
|
931
|
+
* builder so it runs on the main thread, in the SharedWorker, and over IPC.
|
|
932
|
+
*
|
|
933
|
+
* To add a provider: implement StorageProvider in `<name>-provider.ts` and
|
|
934
|
+
* register it in `storage-provider-factory.ts`. No other changes needed.
|
|
935
|
+
*/
|
|
936
|
+
export interface UploadContext {
|
|
937
|
+
fileName: string;
|
|
938
|
+
blob: Blob;
|
|
939
|
+
upload: unknown;
|
|
940
|
+
}
|
|
941
|
+
export interface PreparedUpload {
|
|
942
|
+
url: string;
|
|
943
|
+
method: "POST" | "PUT";
|
|
944
|
+
bodyMode: "multipart" | "binary";
|
|
945
|
+
formFields?: Record<string, string>;
|
|
946
|
+
fileFieldName?: string;
|
|
947
|
+
headers: Record<string, string>;
|
|
948
|
+
attachAuth: boolean;
|
|
949
|
+
}
|
|
950
|
+
export interface StorageProvider {
|
|
951
|
+
/** Matches discovery's `capabilities.storage_provider`. */
|
|
952
|
+
readonly name: string;
|
|
953
|
+
/** @throws UploadError if the upload payload is malformed. */
|
|
954
|
+
prepareUpload(ctx: UploadContext): PreparedUpload;
|
|
955
|
+
}
|
|
956
|
+
export declare class AwsS3StorageProvider implements StorageProvider {
|
|
957
|
+
readonly name = "aws";
|
|
958
|
+
prepareUpload({ fileName, blob, upload }: UploadContext): PreparedUpload;
|
|
959
|
+
}
|
|
960
|
+
export declare function isStorageProviderSupported(name: string): boolean;
|
|
961
|
+
/** @throws UnsupportedStorageProviderError if no wrapper is registered. */
|
|
962
|
+
export declare function getStorageProvider(name: string): StorageProvider;
|
|
880
963
|
export declare class CallbackRegistry {
|
|
881
964
|
private handlers;
|
|
882
965
|
/**
|
|
@@ -1132,7 +1215,7 @@ export declare class RecordingManager {
|
|
|
1132
1215
|
finalizeAfterExternalEndSession(sessionId: string): void;
|
|
1133
1216
|
/**
|
|
1134
1217
|
* Retry uploading audio files that failed during the last recording.
|
|
1135
|
-
* Uses the stored MP3 blobs and the
|
|
1218
|
+
* Uses the stored MP3 blobs and the same storage provider as the recording.
|
|
1136
1219
|
*
|
|
1137
1220
|
* Each file is re-uploaded via transport.request() with retry logic.
|
|
1138
1221
|
* Successfully retried files are removed from the retry context.
|
|
@@ -1142,6 +1225,10 @@ export declare class RecordingManager {
|
|
|
1142
1225
|
* Create the appropriate recorder based on upload type.
|
|
1143
1226
|
*/
|
|
1144
1227
|
private createRecorder;
|
|
1228
|
+
/** Storage provider name from discovery; defaults to 'aws'. */
|
|
1229
|
+
private getStorageProviderName;
|
|
1230
|
+
/** Validate the provider has a wrapper (throws UnsupportedStorageProviderError) and return its name. */
|
|
1231
|
+
private resolveStorageProviderName;
|
|
1145
1232
|
/**
|
|
1146
1233
|
* Build upload headers from the current auth state.
|
|
1147
1234
|
*/
|