med-scribe-alliance-ts-sdk 2.0.30 → 2.0.32
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/dist/index.d.ts +7 -0
- package/dist/index.mjs +93 -46
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -431,6 +431,7 @@ export interface ProcessingError {
|
|
|
431
431
|
export interface PollOptions {
|
|
432
432
|
maxAttempts?: number;
|
|
433
433
|
intervalMs?: number;
|
|
434
|
+
timeoutMs?: number;
|
|
434
435
|
onProgress?: (status: GetSessionStatusResponse) => void;
|
|
435
436
|
/** AbortSignal to cancel polling early. */
|
|
436
437
|
signal?: AbortSignal;
|
|
@@ -1042,6 +1043,7 @@ export declare class RecordingManager {
|
|
|
1042
1043
|
private activeBaseUrl;
|
|
1043
1044
|
private _isRecording;
|
|
1044
1045
|
private _isStarting;
|
|
1046
|
+
private _startGeneration;
|
|
1045
1047
|
private retryContext;
|
|
1046
1048
|
constructor(callbackRegistry: CallbackRegistry, sessionManager: SessionManager, discoveryManager: DiscoveryManager, transport: ITransport, config?: RecordingManagerConfig);
|
|
1047
1049
|
/**
|
|
@@ -1052,6 +1054,11 @@ export declare class RecordingManager {
|
|
|
1052
1054
|
* 4. Start recording
|
|
1053
1055
|
* 5. Dispatch events
|
|
1054
1056
|
*
|
|
1057
|
+
* Race-safety: Uses a generation counter (`_startGeneration`) so that if
|
|
1058
|
+
* clearRecordingState() or reset() is called while this method is suspended
|
|
1059
|
+
* at an `await`, the resumed call detects the mismatch and aborts instead
|
|
1060
|
+
* of creating an orphaned recorder with a leaked mic/VAD.
|
|
1061
|
+
*
|
|
1055
1062
|
* @param baseUrl - Server base URL (from discovery or SDK config)
|
|
1056
1063
|
* @param options - Recording options (templates, model, etc.)
|
|
1057
1064
|
* @param accessToken - Current Bearer token for upload auth headers
|
package/dist/index.mjs
CHANGED
|
@@ -838,21 +838,34 @@ var G = class {
|
|
|
838
838
|
try {
|
|
839
839
|
let r = t ?? this.currentSession?.session_id;
|
|
840
840
|
if (!r) throw new y("No active session. Provide a sessionId or start a session first.");
|
|
841
|
-
let i = n?.maxAttempts ?? 60, a = n?.intervalMs ?? 2e3;
|
|
841
|
+
let i = n?.maxAttempts ?? 60, a = n?.intervalMs ?? 2e3, o = n?.timeoutMs, s = o !== void 0 && o > 0 ? Date.now() + o : void 0;
|
|
842
842
|
this.debug && console.log("[ScribeSDK] Polling for completion:", r, {
|
|
843
843
|
maxAttempts: i,
|
|
844
|
-
intervalMs: a
|
|
844
|
+
intervalMs: a,
|
|
845
|
+
timeoutMs: o
|
|
845
846
|
});
|
|
846
847
|
for (let t = 1; t <= i; t++) {
|
|
847
848
|
if (n?.signal?.aborted) throw new y("Polling was aborted", "polling_aborted", void 0, { session_id: r });
|
|
848
|
-
|
|
849
|
+
if (s !== void 0 && Date.now() >= s) throw new y(`Polling timed out after ${o}ms for session '${r}'`, "polling_timeout", void 0, {
|
|
850
|
+
session_id: r,
|
|
851
|
+
timeout_ms: o
|
|
852
|
+
});
|
|
853
|
+
let c = await this.getSessionStatus(e, r), l = c.data;
|
|
849
854
|
if (n?.onProgress) try {
|
|
850
|
-
n.onProgress(
|
|
855
|
+
n.onProgress(l);
|
|
851
856
|
} catch (e) {
|
|
852
857
|
console.error("[ScribeSDK] Error in poll onProgress callback:", e);
|
|
853
858
|
}
|
|
854
|
-
if (this.isTerminalStatus(
|
|
855
|
-
t < i
|
|
859
|
+
if (this.isTerminalStatus(l.status)) return this.debug && console.log("[ScribeSDK] Poll complete:", r, l.status, `(attempt ${t})`), c;
|
|
860
|
+
if (t < i) {
|
|
861
|
+
let e = a;
|
|
862
|
+
if (s !== void 0) {
|
|
863
|
+
let t = s - Date.now();
|
|
864
|
+
if (t <= 0) continue;
|
|
865
|
+
e = Math.min(a, t);
|
|
866
|
+
}
|
|
867
|
+
await this.sleepWithAbort(e, n?.signal);
|
|
868
|
+
}
|
|
856
869
|
}
|
|
857
870
|
throw new y(`Polling timed out after ${i} attempts for session '${r}'`, "polling_timeout", void 0, {
|
|
858
871
|
session_id: r,
|
|
@@ -957,7 +970,7 @@ var oe = {
|
|
|
957
970
|
} catch (e) {
|
|
958
971
|
console.error("[ScribeSDK] Error destroying VAD:", e);
|
|
959
972
|
}
|
|
960
|
-
this.isRecording = !1;
|
|
973
|
+
this.micVad = null, this.isRecording = !1;
|
|
961
974
|
}
|
|
962
975
|
reset() {
|
|
963
976
|
this.destroy(), this.vadPast = [], this.lastClipIndex = 0, this.silDurationAcc = 0, this.noSpeechStartTime = null, this.lastWarningTime = null, this.isLoading = !0, this.micVad = null;
|
|
@@ -1605,15 +1618,17 @@ var Y = class {
|
|
|
1605
1618
|
}
|
|
1606
1619
|
}, Q = class {
|
|
1607
1620
|
constructor(e, t, n, r, i) {
|
|
1608
|
-
this.recorder = null, this.activeSession = null, this.activeBaseUrl = "", this._isRecording = !1, this._isStarting = !1, this.retryContext = null, this.callbackRegistry = e, this.sessionManager = t, this.discoveryManager = n, this.transport = r, this.config = i ?? {};
|
|
1621
|
+
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 ?? {};
|
|
1609
1622
|
}
|
|
1610
1623
|
async start(e, t, n) {
|
|
1611
1624
|
if (this._isRecording || this._isStarting) throw new y("Recording is already in progress. Stop the current recording first.");
|
|
1612
|
-
this._isStarting = !0
|
|
1613
|
-
let r =
|
|
1625
|
+
this._isStarting = !0;
|
|
1626
|
+
let r = ++this._startGeneration;
|
|
1627
|
+
this.retryContext = null, this.activeBaseUrl = e;
|
|
1628
|
+
let i = t.uploadType ?? "chunked", a = t.communicationProtocol ?? "http", o = {
|
|
1614
1629
|
templates: t.templates,
|
|
1615
|
-
upload_type:
|
|
1616
|
-
communication_protocol:
|
|
1630
|
+
upload_type: i,
|
|
1631
|
+
communication_protocol: a,
|
|
1617
1632
|
model: t.model,
|
|
1618
1633
|
language_hint: t.languageHint,
|
|
1619
1634
|
transcript_language: t.transcriptLanguage,
|
|
@@ -1623,69 +1638,99 @@ var Y = class {
|
|
|
1623
1638
|
session_id: t.sessionId
|
|
1624
1639
|
};
|
|
1625
1640
|
try {
|
|
1626
|
-
let
|
|
1641
|
+
let a, s;
|
|
1627
1642
|
try {
|
|
1628
|
-
let t = await this.sessionManager.createSession(e,
|
|
1629
|
-
|
|
1643
|
+
let t = await this.sessionManager.createSession(e, o);
|
|
1644
|
+
a = t.data, s = t.httpStatus;
|
|
1630
1645
|
} catch (e) {
|
|
1631
|
-
throw this.dispatchStartError(m.TRANSPORT_ERROR, g.SESSION_CREATION_FAILED, e), e;
|
|
1646
|
+
throw r === this._startGeneration && this.dispatchStartError(m.TRANSPORT_ERROR, g.SESSION_CREATION_FAILED, e), e;
|
|
1632
1647
|
}
|
|
1633
|
-
this.
|
|
1648
|
+
if (r !== this._startGeneration) throw new y("Recording start was superseded by a concurrent operation.");
|
|
1649
|
+
this.activeSession = a, this.callbackRegistry.dispatch("onSessionEvent", {
|
|
1634
1650
|
type: p.CREATED,
|
|
1635
1651
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1636
|
-
data:
|
|
1637
|
-
})
|
|
1638
|
-
let
|
|
1652
|
+
data: a
|
|
1653
|
+
});
|
|
1654
|
+
let c = this.createRecorder(i);
|
|
1655
|
+
this.recorder = c;
|
|
1656
|
+
let l = {
|
|
1639
1657
|
accessToken: n,
|
|
1640
|
-
uploadUrl:
|
|
1658
|
+
uploadUrl: a.upload_url,
|
|
1641
1659
|
uploadHeaders: this.buildUploadHeaders(n),
|
|
1642
|
-
sessionId:
|
|
1660
|
+
sessionId: a.session_id
|
|
1643
1661
|
};
|
|
1644
1662
|
try {
|
|
1645
|
-
|
|
1663
|
+
c.initialize(a, l);
|
|
1646
1664
|
} catch (e) {
|
|
1647
|
-
|
|
1665
|
+
try {
|
|
1666
|
+
c.reset();
|
|
1667
|
+
} catch {}
|
|
1668
|
+
throw r === this._startGeneration && (this.cleanupRecordingState(), this.dispatchStartError(m.VALIDATION_ERROR, g.RECORDER_INIT_FAILED, e)), e;
|
|
1648
1669
|
}
|
|
1649
|
-
|
|
1670
|
+
c instanceof X && this.applyDiscoveryOverrides(c);
|
|
1650
1671
|
try {
|
|
1651
|
-
await
|
|
1672
|
+
await c.start(t.deviceId);
|
|
1652
1673
|
} catch (e) {
|
|
1653
|
-
|
|
1674
|
+
try {
|
|
1675
|
+
c.reset();
|
|
1676
|
+
} catch {}
|
|
1677
|
+
throw r === this._startGeneration && (this.cleanupRecordingState(), this.dispatchStartError(m.VAD_ERROR, g.VAD_START_FAILED, e)), e;
|
|
1678
|
+
}
|
|
1679
|
+
if (r !== this._startGeneration) {
|
|
1680
|
+
try {
|
|
1681
|
+
c.reset();
|
|
1682
|
+
} catch {}
|
|
1683
|
+
throw new y("Recording start was superseded by a concurrent operation.");
|
|
1654
1684
|
}
|
|
1655
1685
|
return this._isRecording = !0, this.callbackRegistry.dispatch("onRecordingStateChange", {
|
|
1656
1686
|
type: u.STARTED,
|
|
1657
1687
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
1658
|
-
}), this.config.debug && console.log("[ScribeSDK] Recording started:",
|
|
1659
|
-
data:
|
|
1660
|
-
httpStatus:
|
|
1688
|
+
}), this.config.debug && console.log("[ScribeSDK] Recording started:", a.session_id), {
|
|
1689
|
+
data: a,
|
|
1690
|
+
httpStatus: s
|
|
1661
1691
|
};
|
|
1662
1692
|
} finally {
|
|
1663
|
-
this._isStarting = !1;
|
|
1693
|
+
r === this._startGeneration && (this._isStarting = !1);
|
|
1664
1694
|
}
|
|
1665
1695
|
}
|
|
1666
1696
|
async startWithExistingSession(e, t, n, r) {
|
|
1667
1697
|
if (this._isRecording || this._isStarting) throw new y("Recording is already in progress. Stop the current recording first.");
|
|
1668
|
-
this._isStarting = !0
|
|
1669
|
-
let i =
|
|
1698
|
+
this._isStarting = !0;
|
|
1699
|
+
let i = ++this._startGeneration;
|
|
1700
|
+
this.retryContext = null, this.activeBaseUrl = e;
|
|
1701
|
+
let a = n?.uploadType ?? "chunked";
|
|
1670
1702
|
this.activeSession = t;
|
|
1671
1703
|
try {
|
|
1672
|
-
|
|
1673
|
-
|
|
1704
|
+
let e = this.createRecorder(a);
|
|
1705
|
+
this.recorder = e;
|
|
1706
|
+
let o = {
|
|
1674
1707
|
accessToken: r,
|
|
1675
1708
|
uploadUrl: t.upload_url,
|
|
1676
1709
|
uploadHeaders: this.buildUploadHeaders(r),
|
|
1677
1710
|
sessionId: t.session_id
|
|
1678
1711
|
};
|
|
1679
1712
|
try {
|
|
1680
|
-
|
|
1681
|
-
} catch (
|
|
1682
|
-
|
|
1713
|
+
e.initialize(t, o);
|
|
1714
|
+
} catch (t) {
|
|
1715
|
+
try {
|
|
1716
|
+
e.reset();
|
|
1717
|
+
} catch {}
|
|
1718
|
+
throw i === this._startGeneration && (this.cleanupRecordingState(), this.dispatchStartError(m.VALIDATION_ERROR, g.RECORDER_INIT_FAILED, t)), t;
|
|
1683
1719
|
}
|
|
1684
|
-
|
|
1720
|
+
e instanceof X && this.applyDiscoveryOverrides(e);
|
|
1685
1721
|
try {
|
|
1686
|
-
await
|
|
1687
|
-
} catch (
|
|
1688
|
-
|
|
1722
|
+
await e.start(n?.deviceId);
|
|
1723
|
+
} catch (t) {
|
|
1724
|
+
try {
|
|
1725
|
+
e.reset();
|
|
1726
|
+
} catch {}
|
|
1727
|
+
throw i === this._startGeneration && (this.cleanupRecordingState(), this.dispatchStartError(m.VAD_ERROR, g.VAD_START_FAILED, t)), t;
|
|
1728
|
+
}
|
|
1729
|
+
if (i !== this._startGeneration) {
|
|
1730
|
+
try {
|
|
1731
|
+
e.reset();
|
|
1732
|
+
} catch {}
|
|
1733
|
+
throw new y("Recording start was superseded by a concurrent operation.");
|
|
1689
1734
|
}
|
|
1690
1735
|
return this._isRecording = !0, this.callbackRegistry.dispatch("onRecordingStateChange", {
|
|
1691
1736
|
type: u.STARTED,
|
|
@@ -1695,7 +1740,7 @@ var Y = class {
|
|
|
1695
1740
|
httpStatus: void 0
|
|
1696
1741
|
};
|
|
1697
1742
|
} finally {
|
|
1698
|
-
this._isStarting = !1;
|
|
1743
|
+
i === this._startGeneration && (this._isStarting = !1);
|
|
1699
1744
|
}
|
|
1700
1745
|
}
|
|
1701
1746
|
pause() {
|
|
@@ -1801,9 +1846,11 @@ var Y = class {
|
|
|
1801
1846
|
}
|
|
1802
1847
|
}
|
|
1803
1848
|
forceStop() {
|
|
1804
|
-
if (!(!this.recorder || !this._isRecording)) try {
|
|
1849
|
+
if (++this._startGeneration, !(!this.recorder || !this._isRecording)) try {
|
|
1805
1850
|
this.recorder.reset();
|
|
1806
|
-
} catch
|
|
1851
|
+
} catch (e) {
|
|
1852
|
+
console.error("[ScribeSDK] Error in forceStop:", e);
|
|
1853
|
+
} finally {
|
|
1807
1854
|
this.callbackRegistry.dispatch("onRecordingStateChange", {
|
|
1808
1855
|
type: u.ENDED,
|
|
1809
1856
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -1821,7 +1868,7 @@ var Y = class {
|
|
|
1821
1868
|
this.recorder && this.recorder instanceof X && this.recorder.updateAuthToken(e), this.transport.setAuthToken(e);
|
|
1822
1869
|
}
|
|
1823
1870
|
reset() {
|
|
1824
|
-
this.recorder && this.recorder.reset(), this.retryContext = null, this.cleanupRecordingState();
|
|
1871
|
+
++this._startGeneration, this.recorder && this.recorder.reset(), this.retryContext = null, this.cleanupRecordingState();
|
|
1825
1872
|
}
|
|
1826
1873
|
isRecording() {
|
|
1827
1874
|
return this._isRecording;
|