@agimon-ai/doompi-voice 0.0.1-alpha.77 → 0.0.1-alpha.78
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 +2 -2
- package/dist/extensions/web.mjs +162 -44
- package/dist/extensions/web.mjs.map +1 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/root.server.cjs +6 -5
- package/dist/src/extensions/workspaces/sessions/(backend)/root.server.cjs.map +1 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/root.server.mjs +2 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/root.server.mjs.map +1 -1
- package/dist/src/schemas/apiContracts.cjs +87 -5
- package/dist/src/schemas/apiContracts.cjs.map +1 -1
- package/dist/src/schemas/apiContracts.d.cts.map +1 -1
- package/dist/src/schemas/apiContracts.d.mts.map +1 -1
- package/dist/src/schemas/apiContracts.mjs +87 -5
- package/dist/src/schemas/apiContracts.mjs.map +1 -1
- package/dist/src/schemas/voiceControl.cjs +5 -1
- package/dist/src/schemas/voiceControl.cjs.map +1 -1
- package/dist/src/schemas/voiceControl.mjs +5 -1
- package/dist/src/schemas/voiceControl.mjs.map +1 -1
- package/dist/src/services/sessionVoiceOwnership/index.cjs +51 -11
- package/dist/src/services/sessionVoiceOwnership/index.cjs.map +1 -1
- package/dist/src/services/sessionVoiceOwnership/index.d.cts.map +1 -1
- package/dist/src/services/sessionVoiceOwnership/index.d.mts.map +1 -1
- package/dist/src/services/sessionVoiceOwnership/index.mjs +51 -11
- package/dist/src/services/sessionVoiceOwnership/index.mjs.map +1 -1
- package/dist/src/services/transferVoiceTool/index.cjs +20 -11
- package/dist/src/services/transferVoiceTool/index.cjs.map +1 -1
- package/dist/src/services/transferVoiceTool/index.mjs +20 -11
- package/dist/src/services/transferVoiceTool/index.mjs.map +1 -1
- package/dist/src/services/voiceMediaHubChannel/index.cjs +42 -4
- package/dist/src/services/voiceMediaHubChannel/index.cjs.map +1 -1
- package/dist/src/services/voiceMediaHubChannel/index.mjs +40 -2
- package/dist/src/services/voiceMediaHubChannel/index.mjs.map +1 -1
- package/dist/src/services/voiceOwnershipCoordinator/index.cjs +86 -21
- package/dist/src/services/voiceOwnershipCoordinator/index.cjs.map +1 -1
- package/dist/src/services/voiceOwnershipCoordinator/index.mjs +86 -21
- package/dist/src/services/voiceOwnershipCoordinator/index.mjs.map +1 -1
- package/dist/src/services/voicePeerRelay/index.cjs +335 -0
- package/dist/src/services/voicePeerRelay/index.cjs.map +1 -0
- package/dist/src/services/voicePeerRelay/index.mjs +331 -0
- package/dist/src/services/voicePeerRelay/index.mjs.map +1 -0
- package/dist/src/services/voiceReadinessApi/index.cjs +8 -4
- package/dist/src/services/voiceReadinessApi/index.cjs.map +1 -1
- package/dist/src/services/voiceReadinessApi/index.mjs +6 -2
- package/dist/src/services/voiceReadinessApi/index.mjs.map +1 -1
- package/dist/src/services/voiceServer/index.cjs +23 -11
- package/dist/src/services/voiceServer/index.cjs.map +1 -1
- package/dist/src/services/voiceServer/index.mjs +23 -11
- package/dist/src/services/voiceServer/index.mjs.map +1 -1
- package/dist/src/types/voiceOwnership.cjs +30 -11
- package/dist/src/types/voiceOwnership.cjs.map +1 -1
- package/dist/src/types/voiceOwnership.d.cts +9 -2
- package/dist/src/types/voiceOwnership.d.cts.map +1 -1
- package/dist/src/types/voiceOwnership.d.mts +9 -2
- package/dist/src/types/voiceOwnership.d.mts.map +1 -1
- package/dist/src/types/voiceOwnership.mjs +30 -11
- package/dist/src/types/voiceOwnership.mjs.map +1 -1
- package/package.json +10 -9
- package/src/types/voiceOwnership.ts +67 -10
package/README.md
CHANGED
|
@@ -22,7 +22,7 @@ Voice owns these authenticated server endpoints:
|
|
|
22
22
|
| same | `POST /control` | Send `{action, target?}` |
|
|
23
23
|
|
|
24
24
|
Control actions are `status`, `manual`, `activate`, `deactivate`, `mute`, `unmute`, `interrupt`,
|
|
25
|
-
and `transfer` (with a target catalog order). The typed session method `voice.control` uses the
|
|
25
|
+
and `transfer` (with a target catalog order and its catalog revision). The typed session method `voice.control` uses the
|
|
26
26
|
same operations as commands and minor-mode actions. Browser recording uploads continue to use
|
|
27
27
|
`/api/sessions/:sessionId/plugin/voice-media/manual/transcribe`.
|
|
28
28
|
|
|
@@ -204,7 +204,7 @@ limited to 4,096 characters and returns `completed`, `interrupted`, `superseded`
|
|
|
204
204
|
Once confirmed user speech begins, new narration waits in memory until that turn is synchronously delivered to Pi. Multiple waiting requests use the configured `autoCapture.model` to become one bounded spoken update, with one bounded deterministic utterance if compaction fails. Narration that was already playing is not stopped by this queue gate; the existing ranked barge-in policy remains responsible for interruption.
|
|
205
205
|
Narration fails closed while Voice is starting or draining, during shutdown, reload, or
|
|
206
206
|
deactivation, and when the request belongs to a stale session.
|
|
207
|
-
Only the currently active TUI session receives Voice-owned tools.
|
|
207
|
+
Only the currently active TUI session receives Voice-owned tools. Paired-host targets are discovered through authenticated Voice grants and appear in the same revision-bound transfer catalog. A handoff prepares the target, releases the source, activates the target, and waits for usable media readiness. It does not transfer agent context, transcripts, pending work, or buffered source audio.
|
|
208
208
|
|
|
209
209
|
If no `narrate` attempt is made before a final response, the active Voice session can produce one
|
|
210
210
|
bounded fallback utterance. Short final responses use deterministic text; longer ones may use
|
package/dist/extensions/web.mjs
CHANGED
|
@@ -224,7 +224,7 @@ function parseBrowserVoiceOwnershipPayload(value) {
|
|
|
224
224
|
"type",
|
|
225
225
|
"version",
|
|
226
226
|
"activeSessionId"
|
|
227
|
-
]) || input.type !== "browser-media-session" || input.version !==
|
|
227
|
+
]) || input.type !== "browser-media-session" || input.version !== 3 || input.activeSessionId !== null && (typeof input.activeSessionId !== "string" || !id(input.activeSessionId, 200) && !/^peer\/[A-Za-z0-9][A-Za-z0-9._-]{0,127}\/[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/u.test(input.activeSessionId))) return void 0;
|
|
228
228
|
return input;
|
|
229
229
|
}
|
|
230
230
|
//#endregion
|
|
@@ -893,6 +893,17 @@ var apiRoutes_default = defineApiRoutes({
|
|
|
893
893
|
path: "/readiness",
|
|
894
894
|
response: apiResponse()
|
|
895
895
|
},
|
|
896
|
+
relayBinding: {
|
|
897
|
+
method: "POST",
|
|
898
|
+
path: "/relay-binding",
|
|
899
|
+
response: apiResponse()
|
|
900
|
+
},
|
|
901
|
+
relay: {
|
|
902
|
+
method: "POST",
|
|
903
|
+
path: "/relay",
|
|
904
|
+
query: ["binding"],
|
|
905
|
+
response: apiResponse()
|
|
906
|
+
},
|
|
896
907
|
clientConnect: {
|
|
897
908
|
method: "POST",
|
|
898
909
|
path: VOICE_MEDIA_ROUTES.clientConnect,
|
|
@@ -972,7 +983,7 @@ var apiRoutes_default = defineApiRoutes({
|
|
|
972
983
|
response: apiResponse()
|
|
973
984
|
}
|
|
974
985
|
});
|
|
975
|
-
createApiClient(apiRoutes_default, {
|
|
986
|
+
const voice = createApiClient(apiRoutes_default, {
|
|
976
987
|
scopes: [
|
|
977
988
|
"global",
|
|
978
989
|
"workspace",
|
|
@@ -2720,12 +2731,17 @@ function jsonBody(value) {
|
|
|
2720
2731
|
body: JSON.stringify(value)
|
|
2721
2732
|
};
|
|
2722
2733
|
}
|
|
2734
|
+
function route(path, query = {}) {
|
|
2735
|
+
const url = new URL(path, "http://doompi.local");
|
|
2736
|
+
for (const [name, value] of Object.entries(query)) if (value !== void 0) url.searchParams.set(name, String(value));
|
|
2737
|
+
return `${url.pathname}${url.search}`;
|
|
2738
|
+
}
|
|
2723
2739
|
function cancelResponseBody(response) {
|
|
2724
2740
|
try {
|
|
2725
2741
|
response?.body?.cancel().catch(() => void 0);
|
|
2726
2742
|
} catch {}
|
|
2727
2743
|
}
|
|
2728
|
-
async function boundedControlRequest(input, init, deadlineMs, consume, parentSignal) {
|
|
2744
|
+
async function boundedControlRequest(input, init, deadlineMs, consume, parentSignal, transport = (input, init) => sealedTransport.fetch(input, init)) {
|
|
2729
2745
|
const deadlineController = new AbortController();
|
|
2730
2746
|
const signal = parentSignal ?? deadlineController.signal;
|
|
2731
2747
|
let response;
|
|
@@ -2748,7 +2764,7 @@ async function boundedControlRequest(input, init, deadlineMs, consume, parentSig
|
|
|
2748
2764
|
parentSignal?.addEventListener("abort", abortParent, { once: true });
|
|
2749
2765
|
let fetched;
|
|
2750
2766
|
try {
|
|
2751
|
-
fetched =
|
|
2767
|
+
fetched = transport(input, {
|
|
2752
2768
|
...init,
|
|
2753
2769
|
signal
|
|
2754
2770
|
});
|
|
@@ -2777,6 +2793,7 @@ var BrowserVoiceMediaTransport = class {
|
|
|
2777
2793
|
sessionId;
|
|
2778
2794
|
push;
|
|
2779
2795
|
controlLocation;
|
|
2796
|
+
binding;
|
|
2780
2797
|
constructor(sessionId) {
|
|
2781
2798
|
this.sessionId = sessionId;
|
|
2782
2799
|
}
|
|
@@ -2789,6 +2806,79 @@ var BrowserVoiceMediaTransport = class {
|
|
|
2789
2806
|
media() {
|
|
2790
2807
|
return voiceMedia.session(this.sessionId);
|
|
2791
2808
|
}
|
|
2809
|
+
remote() {
|
|
2810
|
+
return /^peer\/[A-Za-z0-9][A-Za-z0-9._-]{0,127}\/[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/u.test(this.sessionId);
|
|
2811
|
+
}
|
|
2812
|
+
async fetch(path, directUrl, init = {}) {
|
|
2813
|
+
if (!this.remote()) return sealedTransport.fetch(directUrl, init);
|
|
2814
|
+
const request = new Request(new URL(path, "http://doompi.local"), init);
|
|
2815
|
+
const bytes = new Uint8Array(await request.arrayBuffer());
|
|
2816
|
+
let connectionId = new URL(request.url).searchParams.get("connectionId") ?? void 0;
|
|
2817
|
+
if (!connectionId && bytes.byteLength > 0) try {
|
|
2818
|
+
const value = JSON.parse(new TextDecoder().decode(bytes));
|
|
2819
|
+
if (typeof value.connectionId === "string") connectionId = value.connectionId;
|
|
2820
|
+
} catch {
|
|
2821
|
+
connectionId = void 0;
|
|
2822
|
+
}
|
|
2823
|
+
if (!connectionId) throw new Error("Paired Voice request has no connection binding.");
|
|
2824
|
+
if (!this.binding || this.binding.connectionId !== connectionId || this.binding.expiresAt <= Date.now() + CONTROL_REQUEST_DEADLINE_MS) {
|
|
2825
|
+
const issued = await voice.global.relayBinding({ body: {
|
|
2826
|
+
target: this.sessionId,
|
|
2827
|
+
connectionId
|
|
2828
|
+
} });
|
|
2829
|
+
if (!issued.ok) throw resultError(issued);
|
|
2830
|
+
const value = issued.data;
|
|
2831
|
+
if (typeof value.binding !== "string" || !Number.isSafeInteger(value.expiresAt)) throw new Error("Paired Voice media binding is invalid.");
|
|
2832
|
+
this.binding = {
|
|
2833
|
+
id: value.binding,
|
|
2834
|
+
connectionId,
|
|
2835
|
+
expiresAt: value.expiresAt
|
|
2836
|
+
};
|
|
2837
|
+
}
|
|
2838
|
+
let binary = "";
|
|
2839
|
+
for (const byte of bytes) binary += String.fromCharCode(byte);
|
|
2840
|
+
const result = await voice.global.relay({
|
|
2841
|
+
query: { binding: this.binding.id },
|
|
2842
|
+
body: {
|
|
2843
|
+
targetSessionId: "",
|
|
2844
|
+
method: request.method === "GET" ? "GET" : "POST",
|
|
2845
|
+
path,
|
|
2846
|
+
headers: [...request.headers.entries()],
|
|
2847
|
+
body: btoa(binary)
|
|
2848
|
+
}
|
|
2849
|
+
});
|
|
2850
|
+
if (!result.ok) throw resultError(result);
|
|
2851
|
+
const envelope = result.data;
|
|
2852
|
+
if (!Number.isSafeInteger(envelope.status) || !Array.isArray(envelope.headers) || typeof envelope.body !== "string") throw new Error("Paired Voice relay response is invalid.");
|
|
2853
|
+
const decoded = atob(envelope.body);
|
|
2854
|
+
const body = Uint8Array.from(decoded, (character) => character.charCodeAt(0));
|
|
2855
|
+
return new Response(body.byteLength === 0 ? null : body, {
|
|
2856
|
+
status: envelope.status,
|
|
2857
|
+
headers: envelope.headers
|
|
2858
|
+
});
|
|
2859
|
+
}
|
|
2860
|
+
async remoteResult(path, directUrl, init) {
|
|
2861
|
+
const response = await this.fetch(path, directUrl, init);
|
|
2862
|
+
let data;
|
|
2863
|
+
try {
|
|
2864
|
+
data = response.status === 204 ? void 0 : await response.json();
|
|
2865
|
+
} catch {
|
|
2866
|
+
data = void 0;
|
|
2867
|
+
}
|
|
2868
|
+
if (response.ok) return {
|
|
2869
|
+
ok: true,
|
|
2870
|
+
status: response.status,
|
|
2871
|
+
data,
|
|
2872
|
+
response
|
|
2873
|
+
};
|
|
2874
|
+
return {
|
|
2875
|
+
ok: false,
|
|
2876
|
+
status: response.status,
|
|
2877
|
+
error: typeof data === "object" && data !== null && "error" in data && typeof data.error === "string" ? data.error : `Voice media request failed with status ${String(response.status)}.`,
|
|
2878
|
+
data,
|
|
2879
|
+
response
|
|
2880
|
+
};
|
|
2881
|
+
}
|
|
2792
2882
|
async connect(clientId, connectionId, capabilities) {
|
|
2793
2883
|
this.push = void 0;
|
|
2794
2884
|
const controlLocation = sealedTransport.active() ? "remote" : "local";
|
|
@@ -2807,14 +2897,16 @@ var BrowserVoiceMediaTransport = class {
|
|
|
2807
2897
|
}
|
|
2808
2898
|
async disconnect(clientId, connectionId) {
|
|
2809
2899
|
try {
|
|
2810
|
-
const
|
|
2900
|
+
const body = {
|
|
2811
2901
|
clientId,
|
|
2812
2902
|
connectionId
|
|
2813
|
-
}
|
|
2903
|
+
};
|
|
2904
|
+
const result = this.remote() ? await this.remoteResult(VOICE_MEDIA_ROUTES.clientDisconnect, "", jsonBody(body)) : await this.media().clientDisconnect({ body });
|
|
2814
2905
|
if (!result.ok && result.status !== 409) throw resultError(result);
|
|
2815
2906
|
} finally {
|
|
2816
2907
|
this.push = void 0;
|
|
2817
2908
|
this.controlLocation = void 0;
|
|
2909
|
+
this.binding = void 0;
|
|
2818
2910
|
}
|
|
2819
2911
|
}
|
|
2820
2912
|
async nextEvent(clientId, connectionId, after, signal) {
|
|
@@ -2832,29 +2924,39 @@ var BrowserVoiceMediaTransport = class {
|
|
|
2832
2924
|
}
|
|
2833
2925
|
}
|
|
2834
2926
|
declareClient(clientId, connectionId, capabilities, controlLocation) {
|
|
2835
|
-
|
|
2927
|
+
const body = {
|
|
2836
2928
|
version: 6,
|
|
2837
2929
|
clientId,
|
|
2838
2930
|
connectionId,
|
|
2839
2931
|
clientKind: "browser",
|
|
2840
2932
|
controlLocation,
|
|
2841
2933
|
capabilities
|
|
2842
|
-
}
|
|
2934
|
+
};
|
|
2935
|
+
return this.remote() ? this.remoteResult(VOICE_MEDIA_ROUTES.clientConnect, "", jsonBody(body)) : this.media().clientConnect({ body });
|
|
2843
2936
|
}
|
|
2844
2937
|
async fetchEvent(clientId, connectionId, after, signal, nonblocking) {
|
|
2845
|
-
|
|
2938
|
+
const path = route(VOICE_MEDIA_ROUTES.clientEvents, {
|
|
2939
|
+
clientId,
|
|
2940
|
+
connectionId,
|
|
2941
|
+
after,
|
|
2942
|
+
...nonblocking ? { wait: "0" } : {}
|
|
2943
|
+
});
|
|
2944
|
+
const directUrl = this.remote() ? "" : this.media().clientEvents.url({ query: {
|
|
2846
2945
|
clientId,
|
|
2847
2946
|
connectionId,
|
|
2848
2947
|
after,
|
|
2849
2948
|
...nonblocking ? { wait: "0" } : {}
|
|
2850
|
-
} })
|
|
2949
|
+
} });
|
|
2950
|
+
return boundedControlRequest(directUrl, {}, CONTROL_REQUEST_DEADLINE_MS, async (response) => {
|
|
2851
2951
|
if (response.status === 204) return void 0;
|
|
2852
2952
|
if (!response.ok) throw await responseError(response);
|
|
2853
2953
|
return await response.json();
|
|
2854
|
-
}, signal);
|
|
2954
|
+
}, signal, (_input, init) => this.fetch(path, directUrl, init));
|
|
2855
2955
|
}
|
|
2856
2956
|
heartbeat(clientId, connectionId) {
|
|
2857
|
-
|
|
2957
|
+
const path = VOICE_MEDIA_ROUTES.clientHeartbeat;
|
|
2958
|
+
const directUrl = this.remote() ? "" : this.media().clientHeartbeat.url();
|
|
2959
|
+
return boundedControlRequest(directUrl, jsonBody({
|
|
2858
2960
|
clientId,
|
|
2859
2961
|
connectionId
|
|
2860
2962
|
}), CONTROL_REQUEST_DEADLINE_MS, async (response) => {
|
|
@@ -2862,37 +2964,45 @@ var BrowserVoiceMediaTransport = class {
|
|
|
2862
2964
|
const wake = parseVoiceMediaWakePayload(await response.json());
|
|
2863
2965
|
if (wake === null) throw new Error("Voice media heartbeat response is invalid.");
|
|
2864
2966
|
return wake;
|
|
2865
|
-
});
|
|
2967
|
+
}, void 0, (_input, init) => this.fetch(path, directUrl, init));
|
|
2866
2968
|
}
|
|
2867
2969
|
async sendAudio(clientId, connectionId, captureId, pcm, activity) {
|
|
2868
|
-
const
|
|
2869
|
-
|
|
2870
|
-
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
|
|
2874
|
-
|
|
2875
|
-
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
|
|
2970
|
+
const query = {
|
|
2971
|
+
clientId,
|
|
2972
|
+
connectionId,
|
|
2973
|
+
captureId
|
|
2974
|
+
};
|
|
2975
|
+
const headers = {
|
|
2976
|
+
"content-type": VOICE_MEDIA_CONTENT_TYPE,
|
|
2977
|
+
...activity === void 0 ? {} : {
|
|
2978
|
+
[VOICE_MEDIA_ACTIVITY_STATE_HEADER]: activity.state,
|
|
2979
|
+
[VOICE_MEDIA_ACTIVITY_LEVEL_HEADER]: String(activity.levelDbfs),
|
|
2980
|
+
[VOICE_MEDIA_ACTIVITY_ELAPSED_HEADER]: String(activity.elapsedMs),
|
|
2981
|
+
...activity.epoch === void 0 ? {} : { [VOICE_MEDIA_ACTIVITY_EPOCH_HEADER]: String(activity.epoch) },
|
|
2982
|
+
...activity.classifiedSpeechMs === void 0 ? {} : { [VOICE_MEDIA_ACTIVITY_SPEECH_MS_HEADER]: String(activity.classifiedSpeechMs) },
|
|
2983
|
+
...activity.echoDiscriminatedSpeechMs === void 0 ? {} : { [VOICE_MEDIA_ACTIVITY_ECHO_SPEECH_MS_HEADER]: String(activity.echoDiscriminatedSpeechMs) }
|
|
2984
|
+
}
|
|
2985
|
+
};
|
|
2986
|
+
const body = new Blob([new Uint8Array(pcm)], { type: VOICE_MEDIA_CONTENT_TYPE });
|
|
2987
|
+
const result = this.remote() ? await this.remoteResult(route(VOICE_MEDIA_ROUTES.clientAudio, query), "", {
|
|
2988
|
+
method: "POST",
|
|
2989
|
+
headers,
|
|
2990
|
+
body
|
|
2991
|
+
}) : await this.media().clientAudio({
|
|
2992
|
+
query,
|
|
2993
|
+
headers,
|
|
2994
|
+
body
|
|
2886
2995
|
});
|
|
2887
2996
|
if (!result.ok) throw resultError(result);
|
|
2888
2997
|
}
|
|
2889
2998
|
async captureStopped(clientId, connectionId, captureId, error) {
|
|
2890
|
-
const
|
|
2999
|
+
const body = {
|
|
2891
3000
|
clientId,
|
|
2892
3001
|
connectionId,
|
|
2893
3002
|
captureId,
|
|
2894
3003
|
...error === void 0 ? {} : { error }
|
|
2895
|
-
}
|
|
3004
|
+
};
|
|
3005
|
+
const result = this.remote() ? await this.remoteResult(VOICE_MEDIA_ROUTES.clientCaptureStopped, "", jsonBody(body)) : await this.media().clientCaptureStopped({ body });
|
|
2896
3006
|
if (!result.ok) throw resultError(result);
|
|
2897
3007
|
}
|
|
2898
3008
|
/**
|
|
@@ -2906,13 +3016,18 @@ var BrowserVoiceMediaTransport = class {
|
|
|
2906
3016
|
async receivePlaybackAudio(clientId, connectionId, playbackId, signal) {
|
|
2907
3017
|
const chunks = [];
|
|
2908
3018
|
let byteLength = 0;
|
|
2909
|
-
const
|
|
3019
|
+
const path = route(VOICE_MEDIA_ROUTES.clientPlaybackAudio, {
|
|
3020
|
+
clientId,
|
|
3021
|
+
connectionId,
|
|
3022
|
+
playbackId
|
|
3023
|
+
});
|
|
3024
|
+
const url = this.remote() ? "" : this.media().clientPlaybackAudio.url({ query: {
|
|
2910
3025
|
clientId,
|
|
2911
3026
|
connectionId,
|
|
2912
3027
|
playbackId
|
|
2913
3028
|
} });
|
|
2914
3029
|
while (!signal.aborted) {
|
|
2915
|
-
const response = await
|
|
3030
|
+
const response = await this.fetch(path, url, { signal });
|
|
2916
3031
|
if (response.status === 200 && response.headers.get("content-type")?.startsWith("application/vnd.doompi.pcm-s16le")) {
|
|
2917
3032
|
const chunk = new Uint8Array(await response.arrayBuffer());
|
|
2918
3033
|
chunks.push(chunk);
|
|
@@ -2934,15 +3049,18 @@ var BrowserVoiceMediaTransport = class {
|
|
|
2934
3049
|
throw new DOMException("Voice playback audio was aborted.", "AbortError");
|
|
2935
3050
|
}
|
|
2936
3051
|
async playbackFinished(clientId, connectionId, result) {
|
|
2937
|
-
const
|
|
3052
|
+
const body = {
|
|
2938
3053
|
clientId,
|
|
2939
3054
|
connectionId,
|
|
2940
3055
|
...result
|
|
2941
|
-
}
|
|
3056
|
+
};
|
|
3057
|
+
const answer = this.remote() ? await this.remoteResult(VOICE_MEDIA_ROUTES.clientPlaybackResult, "", jsonBody(body)) : await this.media().clientPlaybackResult({ body });
|
|
2942
3058
|
if (!answer.ok) throw resultError(answer);
|
|
2943
3059
|
}
|
|
2944
3060
|
async realtimeNegotiate(clientId, connectionId, activationId, sdp, signal) {
|
|
2945
|
-
|
|
3061
|
+
const path = REALTIME_ROUTES.clientNegotiate;
|
|
3062
|
+
const directUrl = this.remote() ? "" : this.media().realtimeNegotiate.url();
|
|
3063
|
+
return boundedControlRequest(directUrl, jsonBody({
|
|
2946
3064
|
clientId,
|
|
2947
3065
|
connectionId,
|
|
2948
3066
|
activationId,
|
|
@@ -2952,10 +3070,10 @@ var BrowserVoiceMediaTransport = class {
|
|
|
2952
3070
|
const body = await response.json();
|
|
2953
3071
|
if (typeof body !== "object" || body === null || typeof body.sdp !== "string") throw new Error("Realtime negotiation response is invalid.");
|
|
2954
3072
|
return body.sdp;
|
|
2955
|
-
}, signal);
|
|
3073
|
+
}, signal, (_input, init) => this.fetch(path, directUrl, init));
|
|
2956
3074
|
}
|
|
2957
3075
|
async realtimeEvent(clientId, connectionId, activationId, event) {
|
|
2958
|
-
await this.postRealtime(this.media().realtimeEvent.url(), {
|
|
3076
|
+
await this.postRealtime(REALTIME_ROUTES.clientEvent, this.remote() ? "" : this.media().realtimeEvent.url(), {
|
|
2959
3077
|
clientId,
|
|
2960
3078
|
connectionId,
|
|
2961
3079
|
activationId,
|
|
@@ -2963,17 +3081,17 @@ var BrowserVoiceMediaTransport = class {
|
|
|
2963
3081
|
});
|
|
2964
3082
|
}
|
|
2965
3083
|
async realtimeState(clientId, connectionId, activationId, state) {
|
|
2966
|
-
await this.postRealtime(this.media().realtimeState.url(), {
|
|
3084
|
+
await this.postRealtime(REALTIME_ROUTES.clientState, this.remote() ? "" : this.media().realtimeState.url(), {
|
|
2967
3085
|
clientId,
|
|
2968
3086
|
connectionId,
|
|
2969
3087
|
activationId,
|
|
2970
3088
|
state
|
|
2971
3089
|
});
|
|
2972
3090
|
}
|
|
2973
|
-
postRealtime(
|
|
2974
|
-
return boundedControlRequest(
|
|
3091
|
+
postRealtime(path, directUrl, body) {
|
|
3092
|
+
return boundedControlRequest(directUrl, jsonBody(body), CONTROL_REQUEST_DEADLINE_MS, async (response) => {
|
|
2975
3093
|
if (!response.ok) throw await responseError(response);
|
|
2976
|
-
});
|
|
3094
|
+
}, void 0, (_input, init) => this.fetch(path, directUrl, init));
|
|
2977
3095
|
}
|
|
2978
3096
|
};
|
|
2979
3097
|
//#endregion
|