med-scribe-alliance-ts-sdk 2.0.40 → 2.0.41
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 +1 -1
- package/dist/index.d.ts +23 -6
- package/dist/index.mjs +119 -79
- package/dist/worker.bundle.js +5 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -382,7 +382,7 @@ interface RecordingOptions {
|
|
|
382
382
|
| Method | Returns | Description |
|
|
383
383
|
|---|---|---|
|
|
384
384
|
| `startRecording(options)` | `SDKResult<CreateSessionResponse>` | Create session + start mic + begin upload. |
|
|
385
|
-
| `startRecordingWithSession(session, options?)` | `SDKResult<void>` | Attach recorder to an existing session. |
|
|
385
|
+
| `startRecordingWithSession(session, options?)` | `SDKResult<void>` | Attach recorder to an existing session. `options.version` (the version the session was created with) is reused when refreshing `upload_url` on upload failure. |
|
|
386
386
|
| `pauseRecording()` | `void` | Pause VAD (mic stays open, no chunks created). |
|
|
387
387
|
| `resumeRecording()` | `void` | Resume VAD processing. |
|
|
388
388
|
| `endRecording()` | `SDKResult<StopRecordingResult>` | Stop mic, flush audio, wait for uploads, end session. |
|
package/dist/index.d.ts
CHANGED
|
@@ -503,6 +503,7 @@ export interface RecorderConfig {
|
|
|
503
503
|
storageProvider: string;
|
|
504
504
|
uploadHeaders: Record<string, string>;
|
|
505
505
|
sessionId: string;
|
|
506
|
+
refreshUploadUrl?: () => Promise<SessionUploadInfo | null>;
|
|
506
507
|
}
|
|
507
508
|
export interface IRecorder {
|
|
508
509
|
initialize(session: CreateSessionResponse, config: RecorderConfig): void;
|
|
@@ -699,10 +700,16 @@ export interface WorkerUpdateTokenMessage {
|
|
|
699
700
|
type: "update_auth_token";
|
|
700
701
|
token: string;
|
|
701
702
|
}
|
|
703
|
+
/** Fresh upload payload sent in response to an upload_url_required request. */
|
|
704
|
+
export interface WorkerUpdateUploadUrlMessage {
|
|
705
|
+
type: "update_upload_url";
|
|
706
|
+
/** Provider-specific upload payload from a fresh getSessionStatus call. Null = no refresh available. */
|
|
707
|
+
upload: unknown | null;
|
|
708
|
+
}
|
|
702
709
|
export interface WorkerTerminateMessage {
|
|
703
710
|
type: "terminate";
|
|
704
711
|
}
|
|
705
|
-
export type MainToWorkerMessage = WorkerCompressAndUploadMessage | WorkerWaitForUploadsMessage | WorkerUpdateTokenMessage | WorkerTerminateMessage;
|
|
712
|
+
export type MainToWorkerMessage = WorkerCompressAndUploadMessage | WorkerWaitForUploadsMessage | WorkerUpdateTokenMessage | WorkerUpdateUploadUrlMessage | WorkerTerminateMessage;
|
|
706
713
|
export interface WorkerChunkEncodedMessage {
|
|
707
714
|
type: "chunk_encoded";
|
|
708
715
|
fileName: string;
|
|
@@ -724,7 +731,12 @@ export interface WorkerAllUploadsCompleteMessage {
|
|
|
724
731
|
export interface WorkerTokenRequiredMessage {
|
|
725
732
|
type: "token_required";
|
|
726
733
|
}
|
|
727
|
-
|
|
734
|
+
/** Worker hit an upload error and wants a fresh upload_url before retrying. */
|
|
735
|
+
export interface WorkerUploadUrlRequiredMessage {
|
|
736
|
+
type: "upload_url_required";
|
|
737
|
+
fileName: string;
|
|
738
|
+
}
|
|
739
|
+
export type WorkerToMainMessage = WorkerChunkEncodedMessage | WorkerUploadSuccessMessage | WorkerUploadFailedMessage | WorkerAllUploadsCompleteMessage | WorkerTokenRequiredMessage | WorkerUploadUrlRequiredMessage;
|
|
728
740
|
export declare class ScribeClient {
|
|
729
741
|
private config;
|
|
730
742
|
private transport;
|
|
@@ -756,6 +768,7 @@ export declare class ScribeClient {
|
|
|
756
768
|
startRecordingWithSession(session: CreateSessionResponse, options?: {
|
|
757
769
|
uploadType?: string;
|
|
758
770
|
deviceId?: string;
|
|
771
|
+
version?: string;
|
|
759
772
|
}): Promise<SDKResult<void>>;
|
|
760
773
|
/**
|
|
761
774
|
* Pause the active recording.
|
|
@@ -773,7 +786,7 @@ export declare class ScribeClient {
|
|
|
773
786
|
* the SDK runs one internal retry pass; if files still fail, the session
|
|
774
787
|
* is NOT ended and the result reports `sessionEnded: false`.
|
|
775
788
|
*/
|
|
776
|
-
endRecording(
|
|
789
|
+
endRecording(): Promise<SDKResult<EndRecordingResult>>;
|
|
777
790
|
/**
|
|
778
791
|
* Retry uploading audio files that failed during the last recording.
|
|
779
792
|
*
|
|
@@ -781,7 +794,7 @@ export declare class ScribeClient {
|
|
|
781
794
|
* `hasFailedUploads()` is true). After retrying, call `endSession()` to
|
|
782
795
|
* finalize. Retry context is cleared on `reset()` or the next `startRecording()`.
|
|
783
796
|
*/
|
|
784
|
-
retryFailedUploads(
|
|
797
|
+
retryFailedUploads(): Promise<SDKResult<RetryUploadResult>>;
|
|
785
798
|
/**
|
|
786
799
|
* Check if there are failed uploads from the last recording that can be retried.
|
|
787
800
|
*/
|
|
@@ -1129,6 +1142,7 @@ export declare class RecordingManager {
|
|
|
1129
1142
|
private recorder;
|
|
1130
1143
|
private activeSession;
|
|
1131
1144
|
private activeBaseUrl;
|
|
1145
|
+
private activeUploadUrlRefresher;
|
|
1132
1146
|
private _isRecording;
|
|
1133
1147
|
private _isStarting;
|
|
1134
1148
|
private _startGeneration;
|
|
@@ -1166,6 +1180,7 @@ export declare class RecordingManager {
|
|
|
1166
1180
|
startWithExistingSession(baseUrl: string, session: CreateSessionResponse, options?: {
|
|
1167
1181
|
uploadType?: string;
|
|
1168
1182
|
deviceId?: string;
|
|
1183
|
+
version?: string;
|
|
1169
1184
|
}, accessToken?: string): Promise<ApiCallResult<void>>;
|
|
1170
1185
|
/**
|
|
1171
1186
|
* Pause the active recording.
|
|
@@ -1175,7 +1190,7 @@ export declare class RecordingManager {
|
|
|
1175
1190
|
* Resume a paused recording.
|
|
1176
1191
|
*/
|
|
1177
1192
|
resume(): void;
|
|
1178
|
-
stop(
|
|
1193
|
+
stop(): Promise<ApiCallResult<EndRecordingResult>>;
|
|
1179
1194
|
/**
|
|
1180
1195
|
* End the session, dispatch onSessionEvent, and return the response.
|
|
1181
1196
|
* Called from stop() (auto-finalize) and finalizeAfterExternalEndSession()
|
|
@@ -1225,7 +1240,7 @@ export declare class RecordingManager {
|
|
|
1225
1240
|
* Each file is re-uploaded via transport.request() with retry logic.
|
|
1226
1241
|
* Successfully retried files are removed from the retry context.
|
|
1227
1242
|
*/
|
|
1228
|
-
retryFailedUploads(
|
|
1243
|
+
retryFailedUploads(): Promise<ApiCallResult<RetryUploadResult>>;
|
|
1229
1244
|
/**
|
|
1230
1245
|
* Create the appropriate recorder based on upload type.
|
|
1231
1246
|
*/
|
|
@@ -1238,6 +1253,8 @@ export declare class RecordingManager {
|
|
|
1238
1253
|
* Build upload headers from the current auth state.
|
|
1239
1254
|
*/
|
|
1240
1255
|
private buildUploadHeaders;
|
|
1256
|
+
private buildUploadUrlRefresher;
|
|
1257
|
+
private fetchFreshUploadUrl;
|
|
1241
1258
|
/**
|
|
1242
1259
|
* Apply discovery-driven overrides to ChunkedRecorder's VAD config.
|
|
1243
1260
|
* For example, max_chunk_duration_seconds from discovery overrides the default.
|
package/dist/index.mjs
CHANGED
|
@@ -382,7 +382,7 @@ var I = class {
|
|
|
382
382
|
}
|
|
383
383
|
async request(e) {
|
|
384
384
|
try {
|
|
385
|
-
return await P(() => this.executeRequest(e), this.getRetryOptions(e));
|
|
385
|
+
return e.isUpload ? await P(() => this.executeRequest(e), this.getRetryOptions(e)) : await this.executeRequest(e);
|
|
386
386
|
} catch (t) {
|
|
387
387
|
throw t instanceof v ? t : new T(`Network error: ${t instanceof Error ? t.message : "Unknown error"}`, {
|
|
388
388
|
url: e.url,
|
|
@@ -506,7 +506,7 @@ var I = class {
|
|
|
506
506
|
}
|
|
507
507
|
async request(e) {
|
|
508
508
|
try {
|
|
509
|
-
return await P(() => this.executeRequest(e), this.getRetryOptions(e));
|
|
509
|
+
return e.isUpload ? await P(() => this.executeRequest(e), this.getRetryOptions(e)) : await this.executeRequest(e);
|
|
510
510
|
} catch (t) {
|
|
511
511
|
throw t instanceof v ? t : new T(`IPC error: ${t instanceof Error ? t.message : "Unknown error"}`, {
|
|
512
512
|
url: e.url,
|
|
@@ -1287,7 +1287,7 @@ async function Y(e, t) {
|
|
|
1287
1287
|
//#region src/worker/worker-manager.ts
|
|
1288
1288
|
var Se = class {
|
|
1289
1289
|
constructor(e, t, n, r) {
|
|
1290
|
-
if (this.worker = null, this.port = null, this.useWorker = !1, this.uploadPayload = {}, this.storageProviderName = "", this.uploadHeaders = {}, this.pendingUploads = /* @__PURE__ */ new Set(), this.allUploadsResolver = null, this.callbackRegistry = e, this.fileManager = t, this.transport = n, !r?.forceMainThread && typeof SharedWorker < "u" && r?.workerScriptUrl) try {
|
|
1290
|
+
if (this.worker = null, this.port = null, this.useWorker = !1, this.uploadPayload = {}, this.storageProviderName = "", this.uploadHeaders = {}, this.refreshUploadUrl = null, this.inFlightRefresh = null, this.pendingUploads = /* @__PURE__ */ new Set(), this.allUploadsResolver = null, this.callbackRegistry = e, this.fileManager = t, this.transport = n, !r?.forceMainThread && typeof SharedWorker < "u" && r?.workerScriptUrl) try {
|
|
1291
1291
|
this.worker = new SharedWorker(r.workerScriptUrl, { name: "scribe-sdk-worker" }), this.port = this.worker.port, this.port.onmessage = (e) => {
|
|
1292
1292
|
this.handleWorkerMessage(e.data);
|
|
1293
1293
|
}, this.port.start(), this.useWorker = !0;
|
|
@@ -1295,8 +1295,8 @@ var Se = class {
|
|
|
1295
1295
|
console.warn("[ScribeSDK] SharedWorker failed to initialize, falling back to main thread:", e), this.worker = null, this.port = null, this.useWorker = !1;
|
|
1296
1296
|
}
|
|
1297
1297
|
}
|
|
1298
|
-
setUploadConfig(e, t, n) {
|
|
1299
|
-
this.uploadPayload = e, this.storageProviderName = t, this.uploadHeaders = n, J(t);
|
|
1298
|
+
setUploadConfig(e, t, n, r) {
|
|
1299
|
+
this.uploadPayload = e, this.storageProviderName = t, this.uploadHeaders = n, this.refreshUploadUrl = r ?? null, J(t);
|
|
1300
1300
|
}
|
|
1301
1301
|
compressAndUpload(e, t, n) {
|
|
1302
1302
|
let r = e.length / H;
|
|
@@ -1406,6 +1406,28 @@ var Se = class {
|
|
|
1406
1406
|
this.updateAuthToken(e);
|
|
1407
1407
|
} });
|
|
1408
1408
|
break;
|
|
1409
|
+
case "upload_url_required":
|
|
1410
|
+
this.handleUploadUrlRequired();
|
|
1411
|
+
break;
|
|
1412
|
+
}
|
|
1413
|
+
}
|
|
1414
|
+
async handleUploadUrlRequired() {
|
|
1415
|
+
let e = await this.refreshUploadPayload();
|
|
1416
|
+
this.postToWorker({
|
|
1417
|
+
type: "update_upload_url",
|
|
1418
|
+
upload: e
|
|
1419
|
+
});
|
|
1420
|
+
}
|
|
1421
|
+
async refreshUploadPayload() {
|
|
1422
|
+
if (!this.refreshUploadUrl) return null;
|
|
1423
|
+
try {
|
|
1424
|
+
this.inFlightRefresh ||= this.refreshUploadUrl();
|
|
1425
|
+
let e = await this.inFlightRefresh;
|
|
1426
|
+
return e && (this.uploadPayload = e), e;
|
|
1427
|
+
} catch (e) {
|
|
1428
|
+
return console.error("[ScribeSDK] Failed to refresh upload_url:", e), null;
|
|
1429
|
+
} finally {
|
|
1430
|
+
this.inFlightRefresh = null;
|
|
1409
1431
|
}
|
|
1410
1432
|
}
|
|
1411
1433
|
compressAndUploadOnMainThread(e, t, n) {
|
|
@@ -1435,12 +1457,25 @@ var Se = class {
|
|
|
1435
1457
|
fileName: t,
|
|
1436
1458
|
chunkData: i.chunks
|
|
1437
1459
|
}
|
|
1438
|
-
})
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1460
|
+
});
|
|
1461
|
+
try {
|
|
1462
|
+
await Y(this.transport, {
|
|
1463
|
+
fileName: t,
|
|
1464
|
+
blob: r,
|
|
1465
|
+
upload: this.uploadPayload,
|
|
1466
|
+
storageProvider: this.storageProviderName
|
|
1467
|
+
});
|
|
1468
|
+
} catch (e) {
|
|
1469
|
+
let n = await this.refreshUploadPayload();
|
|
1470
|
+
if (!n) throw e;
|
|
1471
|
+
await Y(this.transport, {
|
|
1472
|
+
fileName: t,
|
|
1473
|
+
blob: r,
|
|
1474
|
+
upload: n,
|
|
1475
|
+
storageProvider: this.storageProviderName
|
|
1476
|
+
});
|
|
1477
|
+
}
|
|
1478
|
+
this.fileManager.markSuccess(n), this.dispatchUploadProgress();
|
|
1444
1479
|
} catch (e) {
|
|
1445
1480
|
this.fileManager.markFailure(n, r ?? new Blob(), e?.message ?? "Upload failed"), this.callbackRegistry.dispatch("onUploadEvent", {
|
|
1446
1481
|
type: f.FAILED,
|
|
@@ -1484,7 +1519,7 @@ var Se = class {
|
|
|
1484
1519
|
initialize(e, t) {
|
|
1485
1520
|
if (!t.upload || typeof t.upload != "object") throw Error("Upload payload is required for chunked recording");
|
|
1486
1521
|
if (!t.storageProvider) throw Error("Storage provider is required for chunked recording");
|
|
1487
|
-
this.workerManager.setUploadConfig(t.upload, t.storageProvider, t.uploadHeaders), this.initialized = !0;
|
|
1522
|
+
this.workerManager.setUploadConfig(t.upload, t.storageProvider, t.uploadHeaders, t.refreshUploadUrl), this.initialized = !0;
|
|
1488
1523
|
}
|
|
1489
1524
|
async start(e) {
|
|
1490
1525
|
if (await this.vadClient.init(e), this.vadClient.isVadLoading() && (await this.vadClient.init(e), this.vadClient.isVadLoading())) throw Error("VAD instance failed to initialize after retry");
|
|
@@ -1706,7 +1741,7 @@ var Se = class {
|
|
|
1706
1741
|
}
|
|
1707
1742
|
}, Q = class {
|
|
1708
1743
|
constructor(e, t, n, r, i) {
|
|
1709
|
-
this.recorder = null, this.activeSession = null, this.activeBaseUrl = "", this._isRecording = !1, this._isStarting = !1, this._startGeneration = 0, this.retryContext = null, this.callbackRegistry = e, this.sessionManager = t, this.discoveryManager = n, this.transport = r, this.config = i ?? {};
|
|
1744
|
+
this.recorder = null, this.activeSession = null, this.activeBaseUrl = "", this.activeUploadUrlRefresher = null, this._isRecording = !1, this._isStarting = !1, this._startGeneration = 0, this.retryContext = null, this.callbackRegistry = e, this.sessionManager = t, this.discoveryManager = n, this.transport = r, this.config = i ?? {};
|
|
1710
1745
|
}
|
|
1711
1746
|
async start(e, t, n) {
|
|
1712
1747
|
if (this._isRecording || this._isStarting) throw new v("Recording is already in progress. Stop the current recording first.");
|
|
@@ -1747,13 +1782,14 @@ var Se = class {
|
|
|
1747
1782
|
data: a
|
|
1748
1783
|
});
|
|
1749
1784
|
let l = this.createRecorder(i);
|
|
1750
|
-
this.recorder = l;
|
|
1785
|
+
this.recorder = l, this.activeUploadUrlRefresher = this.buildUploadUrlRefresher(e, a.session_id, t.version);
|
|
1751
1786
|
let d = {
|
|
1752
1787
|
accessToken: n,
|
|
1753
1788
|
upload: a.upload_url,
|
|
1754
1789
|
storageProvider: c,
|
|
1755
1790
|
uploadHeaders: this.buildUploadHeaders(n),
|
|
1756
|
-
sessionId: a.session_id
|
|
1791
|
+
sessionId: a.session_id,
|
|
1792
|
+
refreshUploadUrl: this.activeUploadUrlRefresher
|
|
1757
1793
|
};
|
|
1758
1794
|
try {
|
|
1759
1795
|
l.initialize(a, d);
|
|
@@ -1797,41 +1833,42 @@ var Se = class {
|
|
|
1797
1833
|
let a = n?.uploadType ?? "chunked";
|
|
1798
1834
|
this.activeSession = t;
|
|
1799
1835
|
try {
|
|
1800
|
-
let
|
|
1836
|
+
let o;
|
|
1801
1837
|
try {
|
|
1802
|
-
|
|
1838
|
+
o = this.resolveStorageProviderName();
|
|
1803
1839
|
} catch (e) {
|
|
1804
1840
|
throw i === this._startGeneration && (this.cleanupRecordingState(), this.dispatchStartError(m.VALIDATION_ERROR, g.UNSUPPORTED_STORAGE_PROVIDER, e)), e;
|
|
1805
1841
|
}
|
|
1806
|
-
let
|
|
1807
|
-
this.recorder =
|
|
1808
|
-
let
|
|
1842
|
+
let s = this.createRecorder(a);
|
|
1843
|
+
this.recorder = s, this.activeUploadUrlRefresher = this.buildUploadUrlRefresher(e, t.session_id, n?.version);
|
|
1844
|
+
let c = {
|
|
1809
1845
|
accessToken: r,
|
|
1810
1846
|
upload: t.upload_url,
|
|
1811
|
-
storageProvider:
|
|
1847
|
+
storageProvider: o,
|
|
1812
1848
|
uploadHeaders: this.buildUploadHeaders(r),
|
|
1813
|
-
sessionId: t.session_id
|
|
1849
|
+
sessionId: t.session_id,
|
|
1850
|
+
refreshUploadUrl: this.activeUploadUrlRefresher
|
|
1814
1851
|
};
|
|
1815
1852
|
try {
|
|
1816
|
-
|
|
1853
|
+
s.initialize(t, c);
|
|
1817
1854
|
} catch (e) {
|
|
1818
1855
|
try {
|
|
1819
|
-
|
|
1856
|
+
s.reset();
|
|
1820
1857
|
} catch {}
|
|
1821
1858
|
throw i === this._startGeneration && (this.cleanupRecordingState(), this.dispatchStartError(m.VALIDATION_ERROR, g.RECORDER_INIT_FAILED, e)), e;
|
|
1822
1859
|
}
|
|
1823
|
-
|
|
1860
|
+
s instanceof X && this.applyDiscoveryOverrides(s);
|
|
1824
1861
|
try {
|
|
1825
|
-
await
|
|
1862
|
+
await s.start(n?.deviceId);
|
|
1826
1863
|
} catch (e) {
|
|
1827
1864
|
try {
|
|
1828
|
-
|
|
1865
|
+
s.reset();
|
|
1829
1866
|
} catch {}
|
|
1830
1867
|
throw i === this._startGeneration && (this.cleanupRecordingState(), this.dispatchStartError(m.VAD_ERROR, g.VAD_START_FAILED, e)), e;
|
|
1831
1868
|
}
|
|
1832
1869
|
if (i !== this._startGeneration) {
|
|
1833
1870
|
try {
|
|
1834
|
-
|
|
1871
|
+
s.reset();
|
|
1835
1872
|
} catch {}
|
|
1836
1873
|
throw new v("Recording start was superseded by a concurrent operation.");
|
|
1837
1874
|
}
|
|
@@ -1858,7 +1895,7 @@ var Se = class {
|
|
|
1858
1895
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
1859
1896
|
}), this.config.debug && console.log("[ScribeSDK] Recording resumed"));
|
|
1860
1897
|
}
|
|
1861
|
-
async stop(
|
|
1898
|
+
async stop() {
|
|
1862
1899
|
if (!this.recorder || !this._isRecording) return {
|
|
1863
1900
|
data: {
|
|
1864
1901
|
failedUploads: [],
|
|
@@ -1867,13 +1904,13 @@ var Se = class {
|
|
|
1867
1904
|
},
|
|
1868
1905
|
httpStatus: void 0
|
|
1869
1906
|
};
|
|
1870
|
-
let
|
|
1907
|
+
let e = !1, t;
|
|
1871
1908
|
try {
|
|
1872
|
-
let
|
|
1909
|
+
let n = await this.recorder.stop();
|
|
1873
1910
|
this.preserveRetryContext(), this._isRecording = !1;
|
|
1874
|
-
let
|
|
1875
|
-
if (
|
|
1876
|
-
|
|
1911
|
+
let r = n.failedUploads;
|
|
1912
|
+
if (r.length > 0) try {
|
|
1913
|
+
r = (await this.retryFailedUploads()).data.stillFailed;
|
|
1877
1914
|
} catch (e) {
|
|
1878
1915
|
console.error("[ScribeSDK] Internal retry pass failed:", e), this.callbackRegistry.dispatch("onError", {
|
|
1879
1916
|
type: m.TRANSPORT_ERROR,
|
|
@@ -1884,26 +1921,26 @@ var Se = class {
|
|
|
1884
1921
|
}
|
|
1885
1922
|
});
|
|
1886
1923
|
}
|
|
1887
|
-
let
|
|
1888
|
-
failedUploads:
|
|
1889
|
-
totalFiles:
|
|
1924
|
+
let i = {
|
|
1925
|
+
failedUploads: r,
|
|
1926
|
+
totalFiles: n.totalFiles,
|
|
1890
1927
|
sessionEnded: !1
|
|
1891
1928
|
};
|
|
1892
|
-
if (
|
|
1893
|
-
let
|
|
1894
|
-
|
|
1929
|
+
if (r.length === 0 && this.activeSession) {
|
|
1930
|
+
let r = await this.finalizeSession(n.totalFiles, n.totalFiles);
|
|
1931
|
+
r && (i.sessionEnded = !0, i.endSessionResponse = r.data, t = r.httpStatus, e = !0);
|
|
1895
1932
|
}
|
|
1896
1933
|
return this.callbackRegistry.dispatch("onRecordingStateChange", {
|
|
1897
1934
|
type: u.ENDED,
|
|
1898
1935
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1899
|
-
data:
|
|
1936
|
+
data: i
|
|
1900
1937
|
}), this.config.debug && console.log("[ScribeSDK] Recording stopped:", {
|
|
1901
|
-
totalFiles:
|
|
1902
|
-
failedUploads:
|
|
1903
|
-
sessionEnded:
|
|
1938
|
+
totalFiles: i.totalFiles,
|
|
1939
|
+
failedUploads: i.failedUploads.length,
|
|
1940
|
+
sessionEnded: i.sessionEnded
|
|
1904
1941
|
}), {
|
|
1905
|
-
data:
|
|
1906
|
-
httpStatus:
|
|
1942
|
+
data: i,
|
|
1943
|
+
httpStatus: t
|
|
1907
1944
|
};
|
|
1908
1945
|
} catch (e) {
|
|
1909
1946
|
return console.error("[ScribeSDK] Error stopping recording:", e), this.callbackRegistry.dispatch("onError", {
|
|
@@ -1922,7 +1959,7 @@ var Se = class {
|
|
|
1922
1959
|
httpStatus: void 0
|
|
1923
1960
|
};
|
|
1924
1961
|
} finally {
|
|
1925
|
-
|
|
1962
|
+
e ? this.cleanupRecordingState() : this.partialCleanupAfterFailedFinalize();
|
|
1926
1963
|
}
|
|
1927
1964
|
}
|
|
1928
1965
|
async finalizeSession(e, t) {
|
|
@@ -1986,9 +2023,9 @@ var Se = class {
|
|
|
1986
2023
|
return (this.retryContext?.failedChunks.length ?? 0) > 0;
|
|
1987
2024
|
}
|
|
1988
2025
|
finalizeAfterExternalEndSession(e) {
|
|
1989
|
-
this.activeSession && this.activeSession.session_id === e && (this.activeSession = null, this.activeBaseUrl = "", this.retryContext = null);
|
|
2026
|
+
this.activeSession && this.activeSession.session_id === e && (this.activeSession = null, this.activeBaseUrl = "", this.activeUploadUrlRefresher = null, this.retryContext = null);
|
|
1990
2027
|
}
|
|
1991
|
-
async retryFailedUploads(
|
|
2028
|
+
async retryFailedUploads() {
|
|
1992
2029
|
if (this._isRecording) throw new v("Cannot retry uploads while recording is active.");
|
|
1993
2030
|
if (!this.retryContext || this.retryContext.failedChunks.length === 0) return {
|
|
1994
2031
|
data: {
|
|
@@ -1998,47 +2035,44 @@ var Se = class {
|
|
|
1998
2035
|
},
|
|
1999
2036
|
httpStatus: void 0
|
|
2000
2037
|
};
|
|
2001
|
-
let { storageProvider:
|
|
2038
|
+
let { storageProvider: e, failedChunks: t } = this.retryContext, n = t.length, r = [], i = 0, a = this.retryContext.upload;
|
|
2002
2039
|
try {
|
|
2003
|
-
let
|
|
2004
|
-
|
|
2005
|
-
let n = await this.sessionManager.getSessionStatus(this.activeBaseUrl, t, void 0, e);
|
|
2006
|
-
n.data.upload_url && (o = n.data.upload_url, this.retryContext.upload = o);
|
|
2007
|
-
}
|
|
2040
|
+
let e = await this.activeUploadUrlRefresher?.();
|
|
2041
|
+
e && (a = e, this.retryContext.upload = e);
|
|
2008
2042
|
} catch (e) {
|
|
2009
2043
|
this.config.debug && console.log("[ScribeSDK] Failed to refresh upload_url, using existing:", e);
|
|
2010
2044
|
}
|
|
2011
|
-
this.config.debug && console.log(`[ScribeSDK] Retrying ${
|
|
2012
|
-
for (let
|
|
2045
|
+
this.config.debug && console.log(`[ScribeSDK] Retrying ${n} failed uploads`);
|
|
2046
|
+
for (let o of t) try {
|
|
2013
2047
|
await Y(this.transport, {
|
|
2014
|
-
fileName:
|
|
2015
|
-
blob:
|
|
2016
|
-
upload:
|
|
2017
|
-
storageProvider:
|
|
2048
|
+
fileName: o.fileName,
|
|
2049
|
+
blob: o.blob,
|
|
2050
|
+
upload: a,
|
|
2051
|
+
storageProvider: e,
|
|
2018
2052
|
maxRetries: 0
|
|
2019
|
-
}),
|
|
2053
|
+
}), i++, this.callbackRegistry.dispatch("onUploadEvent", {
|
|
2020
2054
|
type: f.PROGRESS,
|
|
2021
2055
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2022
2056
|
data: {
|
|
2023
|
-
successCount:
|
|
2024
|
-
totalCount:
|
|
2057
|
+
successCount: i,
|
|
2058
|
+
totalCount: n
|
|
2025
2059
|
}
|
|
2026
|
-
}), this.config.debug && console.log(`[ScribeSDK] Retry succeeded: ${
|
|
2027
|
-
} catch (
|
|
2028
|
-
|
|
2060
|
+
}), this.config.debug && console.log(`[ScribeSDK] Retry succeeded: ${o.fileName}`);
|
|
2061
|
+
} catch (e) {
|
|
2062
|
+
r.push(o.fileName), this.callbackRegistry.dispatch("onUploadEvent", {
|
|
2029
2063
|
type: f.FAILED,
|
|
2030
2064
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2031
2065
|
data: {
|
|
2032
|
-
fileName:
|
|
2033
|
-
error:
|
|
2066
|
+
fileName: o.fileName,
|
|
2067
|
+
error: e instanceof Error ? e.message : "Retry failed"
|
|
2034
2068
|
}
|
|
2035
|
-
}), this.config.debug && console.log(`[ScribeSDK] Retry failed: ${
|
|
2069
|
+
}), this.config.debug && console.log(`[ScribeSDK] Retry failed: ${o.fileName}`, e);
|
|
2036
2070
|
}
|
|
2037
|
-
return
|
|
2071
|
+
return r.length === 0 ? this.retryContext = null : this.retryContext.failedChunks = t.filter((e) => r.includes(e.fileName)), this.config.debug && console.log(`[ScribeSDK] Retry complete: ${i}/${n} succeeded`), {
|
|
2038
2072
|
data: {
|
|
2039
|
-
retried:
|
|
2040
|
-
succeeded:
|
|
2041
|
-
stillFailed:
|
|
2073
|
+
retried: n,
|
|
2074
|
+
succeeded: i,
|
|
2075
|
+
stillFailed: r
|
|
2042
2076
|
},
|
|
2043
2077
|
httpStatus: void 0
|
|
2044
2078
|
};
|
|
@@ -2061,6 +2095,12 @@ var Se = class {
|
|
|
2061
2095
|
let t = {};
|
|
2062
2096
|
return e && (t.Authorization = `Bearer ${e}`), this.config.flavour && (t.flavour = this.config.flavour), t;
|
|
2063
2097
|
}
|
|
2098
|
+
buildUploadUrlRefresher(e, t, n) {
|
|
2099
|
+
return () => this.fetchFreshUploadUrl(e, t, n);
|
|
2100
|
+
}
|
|
2101
|
+
async fetchFreshUploadUrl(e, t, n) {
|
|
2102
|
+
return (await this.sessionManager.getSessionStatus(e, t, void 0, n)).data.upload_url ?? null;
|
|
2103
|
+
}
|
|
2064
2104
|
applyDiscoveryOverrides(e) {
|
|
2065
2105
|
try {
|
|
2066
2106
|
let t = this.discoveryManager.getResolvedConfig();
|
|
@@ -2097,7 +2137,7 @@ var Se = class {
|
|
|
2097
2137
|
}, this.config.debug && console.log(`[ScribeSDK] Preserved ${e.length} failed uploads for retry`);
|
|
2098
2138
|
}
|
|
2099
2139
|
cleanupRecordingState() {
|
|
2100
|
-
this.recorder = null, this.activeSession = null, this.activeBaseUrl = "", this._isRecording = !1, this._isStarting = !1;
|
|
2140
|
+
this.recorder = null, this.activeSession = null, this.activeBaseUrl = "", this.activeUploadUrlRefresher = null, this._isRecording = !1, this._isStarting = !1;
|
|
2101
2141
|
}
|
|
2102
2142
|
partialCleanupAfterFailedFinalize() {
|
|
2103
2143
|
this.recorder = null, this._isRecording = !1, this._isStarting = !1;
|
|
@@ -2156,11 +2196,11 @@ var Se = class {
|
|
|
2156
2196
|
resumeRecording() {
|
|
2157
2197
|
this.recordingManager.resume();
|
|
2158
2198
|
}
|
|
2159
|
-
async endRecording(
|
|
2160
|
-
return this.wrapResult(() => this.recordingManager.stop(
|
|
2199
|
+
async endRecording() {
|
|
2200
|
+
return this.wrapResult(() => this.recordingManager.stop());
|
|
2161
2201
|
}
|
|
2162
|
-
async retryFailedUploads(
|
|
2163
|
-
return this.wrapResult(() => this.recordingManager.retryFailedUploads(
|
|
2202
|
+
async retryFailedUploads() {
|
|
2203
|
+
return this.wrapResult(() => this.recordingManager.retryFailedUploads());
|
|
2164
2204
|
}
|
|
2165
2205
|
hasFailedUploads() {
|
|
2166
2206
|
return this.recordingManager.hasFailedUploads();
|