@talk2view/sdk 0.18.1 → 0.20.0
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 +71 -103
- package/dist/assistant-ui/index.d.ts.map +1 -1
- package/dist/assistant-ui/index.js +4 -2
- package/dist/assistant-ui/index.js.map +1 -1
- package/dist/auth.d.ts +8 -0
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +27 -11
- package/dist/auth.js.map +1 -1
- package/dist/chat/auth-gate.d.ts +3 -1
- package/dist/chat/auth-gate.d.ts.map +1 -1
- package/dist/chat/auth-gate.js +29 -5
- package/dist/chat/auth-gate.js.map +1 -1
- package/dist/chat/composer-extras.js +2 -2
- package/dist/chat/index.d.ts +1 -0
- package/dist/chat/index.d.ts.map +1 -1
- package/dist/chat/index.js +1 -0
- package/dist/chat/index.js.map +1 -1
- package/dist/chat/launcher.d.ts.map +1 -1
- package/dist/chat/launcher.js +6 -2
- package/dist/chat/launcher.js.map +1 -1
- package/dist/chat/markdown.d.ts +14 -4
- package/dist/chat/markdown.d.ts.map +1 -1
- package/dist/chat/markdown.js +28 -1
- package/dist/chat/markdown.js.map +1 -1
- package/dist/chat/provider.d.ts +7 -0
- package/dist/chat/provider.d.ts.map +1 -1
- package/dist/chat/provider.js +22 -1
- package/dist/chat/provider.js.map +1 -1
- package/dist/chat/vendor/LICENSE +21 -0
- package/dist/chat/vendor/MANIFEST.json +84 -0
- package/dist/chat/vendor/attachment.aui.d.ts.map +1 -1
- package/dist/chat/vendor/attachment.aui.js +8 -0
- package/dist/chat/vendor/attachment.aui.js.map +1 -1
- package/dist/chat/vendor/file.d.ts.map +1 -1
- package/dist/chat/vendor/file.js +8 -0
- package/dist/chat/vendor/file.js.map +1 -1
- package/dist/chat/vendor/follow-up-suggestions.aui.d.ts.map +1 -1
- package/dist/chat/vendor/follow-up-suggestions.aui.js +8 -0
- package/dist/chat/vendor/follow-up-suggestions.aui.js.map +1 -1
- package/dist/chat/vendor/image.d.ts.map +1 -1
- package/dist/chat/vendor/image.js +8 -0
- package/dist/chat/vendor/image.js.map +1 -1
- package/dist/chat/vendor/markdown-text.d.ts.map +1 -1
- package/dist/chat/vendor/markdown-text.js +8 -0
- package/dist/chat/vendor/markdown-text.js.map +1 -1
- package/dist/chat/vendor/reasoning.aui.d.ts.map +1 -1
- package/dist/chat/vendor/reasoning.aui.js +8 -0
- package/dist/chat/vendor/reasoning.aui.js.map +1 -1
- package/dist/chat/vendor/reasoning.d.ts.map +1 -1
- package/dist/chat/vendor/reasoning.js +8 -0
- package/dist/chat/vendor/reasoning.js.map +1 -1
- package/dist/chat/vendor/thread-list.aui.d.ts.map +1 -1
- package/dist/chat/vendor/thread-list.aui.js +8 -0
- package/dist/chat/vendor/thread-list.aui.js.map +1 -1
- package/dist/chat/vendor/thread.aui.d.ts.map +1 -1
- package/dist/chat/vendor/thread.aui.js +8 -0
- package/dist/chat/vendor/thread.aui.js.map +1 -1
- package/dist/chat/vendor/tool-fallback.aui.d.ts.map +1 -1
- package/dist/chat/vendor/tool-fallback.aui.js +8 -0
- package/dist/chat/vendor/tool-fallback.aui.js.map +1 -1
- package/dist/chat/vendor/tool-group.aui.d.ts.map +1 -1
- package/dist/chat/vendor/tool-group.aui.js +8 -0
- package/dist/chat/vendor/tool-group.aui.js.map +1 -1
- package/dist/chat/vendor/tooltip-icon-button.d.ts.map +1 -1
- package/dist/chat/vendor/tooltip-icon-button.js +8 -0
- package/dist/chat/vendor/tooltip-icon-button.js.map +1 -1
- package/dist/chat/views/account.d.ts.map +1 -1
- package/dist/chat/views/account.js +6 -0
- package/dist/chat/views/account.js.map +1 -1
- package/dist/chat/voice-button.d.ts +34 -0
- package/dist/chat/voice-button.d.ts.map +1 -0
- package/dist/chat/voice-button.js +175 -0
- package/dist/chat/voice-button.js.map +1 -0
- package/dist/chat-css.js +1 -1
- package/dist/chat.css +1 -1
- package/dist/chat.isolated.css +176 -3
- package/dist/chat.raw.css +176 -3
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +49 -0
- package/dist/client.js.map +1 -1
- package/dist/event-emitter.d.ts +1 -0
- package/dist/event-emitter.d.ts.map +1 -1
- package/dist/event-emitter.js +3 -0
- package/dist/event-emitter.js.map +1 -1
- package/dist/index.d.ts +24 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +45 -0
- package/dist/index.js.map +1 -1
- package/dist/streaming.d.ts.map +1 -1
- package/dist/streaming.js +5 -1
- package/dist/streaming.js.map +1 -1
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +13 -2
- package/dist/tools.js.map +1 -1
- package/dist/types.d.ts +60 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/ui/components/MarkdownRenderer.d.ts +1 -1
- package/dist/ui/components/MarkdownRenderer.js +1 -1
- package/dist/ui/index.d.ts +10 -0
- package/dist/ui/index.d.ts.map +1 -1
- package/dist/ui/index.js +10 -0
- package/dist/ui/index.js.map +1 -1
- package/dist/ui/safeMarkdown.d.ts.map +1 -1
- package/dist/ui/safeMarkdown.js +4 -2
- package/dist/ui/safeMarkdown.js.map +1 -1
- package/dist/voice-error.d.ts +8 -0
- package/dist/voice-error.d.ts.map +1 -0
- package/dist/voice-error.js +10 -0
- package/dist/voice-error.js.map +1 -0
- package/dist/voice-facade.d.ts +57 -0
- package/dist/voice-facade.d.ts.map +1 -0
- package/dist/voice-facade.js +139 -0
- package/dist/voice-facade.js.map +1 -0
- package/dist/voice.d.ts +157 -0
- package/dist/voice.d.ts.map +1 -0
- package/dist/voice.js +630 -0
- package/dist/voice.js.map +1 -0
- package/docs/chat.md +532 -0
- package/docs/voice.md +88 -0
- package/package.json +22 -9
package/dist/voice.js
ADDED
|
@@ -0,0 +1,630 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Voice controller — the realtime voice agent behind `t2v.voice`.
|
|
3
|
+
*
|
|
4
|
+
* Core never imports this module statically: the `T2VVoice` facade
|
|
5
|
+
* (`voice-facade.ts`) loads it with `import()` on the first `start()`, and it
|
|
6
|
+
* in turn loads the Pipecat libraries, so chat-only partners ship neither.
|
|
7
|
+
*
|
|
8
|
+
* The engine mints a ticket (`POST /v1/voice/sessions`); the Pipecat client
|
|
9
|
+
* libraries are loaded on first `start()` so chat-only partners never ship
|
|
10
|
+
* them; WebRTC audio goes to the voice agent service; client tools the agent
|
|
11
|
+
* calls arrive here over the RTVI data channel and run through the SAME tool
|
|
12
|
+
* registry and permission check as chat, so partners write no new code.
|
|
13
|
+
*/
|
|
14
|
+
import { TypedEventEmitter } from './event-emitter.js';
|
|
15
|
+
import { VoiceStartError } from './voice-error.js';
|
|
16
|
+
/** Dynamic imports: a bundler splits these into their own chunk. */
|
|
17
|
+
export const loadPipecatLibs = async () => {
|
|
18
|
+
const [client, transport] = await Promise.all([
|
|
19
|
+
import('@pipecat-ai/client-js'),
|
|
20
|
+
import('@pipecat-ai/small-webrtc-transport'),
|
|
21
|
+
]);
|
|
22
|
+
return {
|
|
23
|
+
PipecatClient: client.PipecatClient,
|
|
24
|
+
SmallWebRTCTransport: transport.SmallWebRTCTransport,
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Where a call's start spends its time, in ms since the click. Logged only
|
|
29
|
+
* when `localStorage['t2v:debug'] === '1'`: step names and numbers, nothing
|
|
30
|
+
* about the user.
|
|
31
|
+
*/
|
|
32
|
+
function startTimings() {
|
|
33
|
+
const clock = globalThis.performance;
|
|
34
|
+
const started = clock?.now() ?? 0;
|
|
35
|
+
const steps = {};
|
|
36
|
+
const mark = (step) => {
|
|
37
|
+
if (clock)
|
|
38
|
+
steps[step] = Math.round(clock.now() - started);
|
|
39
|
+
};
|
|
40
|
+
return {
|
|
41
|
+
mark,
|
|
42
|
+
done(step) {
|
|
43
|
+
mark(step);
|
|
44
|
+
let enabled = false;
|
|
45
|
+
try {
|
|
46
|
+
enabled = globalThis.localStorage?.getItem('t2v:debug') === '1';
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
// storage blocked: stay quiet
|
|
50
|
+
}
|
|
51
|
+
if (enabled)
|
|
52
|
+
console.debug('[Talk2View] voice start, ms since click', steps);
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
/** Every `VoiceEndReason`; a `t2v-call-ended` reason outside it is reported as `'error'`. */
|
|
57
|
+
const END_REASONS = new Set([
|
|
58
|
+
'stopped',
|
|
59
|
+
'disconnected',
|
|
60
|
+
'session_cap',
|
|
61
|
+
'idle',
|
|
62
|
+
'budget_exhausted',
|
|
63
|
+
'auth_expired',
|
|
64
|
+
'error',
|
|
65
|
+
]);
|
|
66
|
+
const MIC_UNAVAILABLE = {
|
|
67
|
+
type: 'mic_unavailable',
|
|
68
|
+
message: 'Voice needs microphone access. Allow the microphone and try again.',
|
|
69
|
+
};
|
|
70
|
+
const AUTH_EXPIRED = {
|
|
71
|
+
type: 'auth_expired',
|
|
72
|
+
message: 'Your sign-in expired. Sign in again to keep talking.',
|
|
73
|
+
};
|
|
74
|
+
/** The microphone's permission state, or 'unknown' where the browser cannot say. */
|
|
75
|
+
async function queryMicPermission() {
|
|
76
|
+
try {
|
|
77
|
+
const status = await globalThis.navigator?.permissions?.query({ name: 'microphone' });
|
|
78
|
+
return status?.state ?? 'unknown';
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
return 'unknown';
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Release the microphone of a client that may never have connected. Before a
|
|
86
|
+
* peer connection exists client-js's disconnect() returns early and leaves
|
|
87
|
+
* the mic track live, so the track itself is stopped. Safe to repeat.
|
|
88
|
+
*/
|
|
89
|
+
function releaseMic(client) {
|
|
90
|
+
try {
|
|
91
|
+
client.tracks()?.local?.audio?.stop();
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
// no tracks yet, or already released
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
const DEFAULT_APPROVAL_TIMEOUT_MS = 25_000;
|
|
98
|
+
/** What the voice service's refusal statuses mean when its JSON body is unreadable. */
|
|
99
|
+
const OFFER_STATUS = {
|
|
100
|
+
401: { type: 'voice_ticket_invalid', message: 'The voice session expired before it connected. Try again.' },
|
|
101
|
+
502: { type: 'upstream_error', message: 'The voice service could not reach the assistant. Try again.' },
|
|
102
|
+
503: { type: 'voice_at_capacity', message: 'Voice is busy right now. Try again in a minute.' },
|
|
103
|
+
};
|
|
104
|
+
/**
|
|
105
|
+
* Turn a failed start into a `VoiceError`. Engine errors (`T2VError`) and our
|
|
106
|
+
* own `VoiceStartError` carry `.type`. The transport rejects a refused offer
|
|
107
|
+
* with a `TransportStartError` carrying `.status` and, as `.cause`, the
|
|
108
|
+
* service's unread `Response`, whose `{error: {type, message}}` body wins.
|
|
109
|
+
*/
|
|
110
|
+
async function describeStartError(err, connecting) {
|
|
111
|
+
const e = (err ?? {});
|
|
112
|
+
const message = err instanceof Error && err.message ? err.message : 'Could not start voice';
|
|
113
|
+
if (typeof e.type === 'string')
|
|
114
|
+
return { type: e.type, message };
|
|
115
|
+
if (typeof e.status === 'number') {
|
|
116
|
+
const cause = e.cause;
|
|
117
|
+
if (cause && typeof cause.json === 'function' && !cause.bodyUsed) {
|
|
118
|
+
try {
|
|
119
|
+
const body = (await cause.json());
|
|
120
|
+
if (typeof body?.error?.type === 'string') {
|
|
121
|
+
const fallback = OFFER_STATUS[e.status]?.message ?? 'Could not start voice';
|
|
122
|
+
return { type: body.error.type, message: typeof body.error.message === 'string' ? body.error.message : fallback };
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
catch {
|
|
126
|
+
// not JSON: fall back to the status
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return OFFER_STATUS[e.status] ?? { type: 'voice_error', message: 'Could not start voice' };
|
|
130
|
+
}
|
|
131
|
+
return { type: connecting ? 'transport_error' : 'voice_error', message };
|
|
132
|
+
}
|
|
133
|
+
export { VoiceStartError };
|
|
134
|
+
/** The voice controller. Construct the {@link T2VVoice} facade (`t2v.voice`) instead. */
|
|
135
|
+
export class T2VVoiceController {
|
|
136
|
+
deps;
|
|
137
|
+
emitter = new TypedEventEmitter();
|
|
138
|
+
_state = 'idle';
|
|
139
|
+
client = null;
|
|
140
|
+
audio = null;
|
|
141
|
+
libs = null;
|
|
142
|
+
pendingApproval = null;
|
|
143
|
+
/** Ends the open approval without a human answer; the reason goes to the agent. */
|
|
144
|
+
cancelApproval = null;
|
|
145
|
+
alwaysAllowed = new Set();
|
|
146
|
+
/**
|
|
147
|
+
* Bumped by every ending. A `start()` or a client callback from an older
|
|
148
|
+
* epoch belongs to a call that was hung up, and must not touch this one.
|
|
149
|
+
*/
|
|
150
|
+
epoch = 0;
|
|
151
|
+
/** Settles the in-flight `start()`'s connect wait when the call is hung up mid-start. */
|
|
152
|
+
abortStart = null;
|
|
153
|
+
/**
|
|
154
|
+
* The hang-up in progress; a concurrent `stop()` joins it. Tagged with the
|
|
155
|
+
* epoch it ended, so a `stop()` for a call started after it (say, from an
|
|
156
|
+
* `ended` listener) is not mistaken for a second hang-up of the old one.
|
|
157
|
+
*/
|
|
158
|
+
ending = null;
|
|
159
|
+
constructor(deps) {
|
|
160
|
+
this.deps = deps;
|
|
161
|
+
}
|
|
162
|
+
get state() {
|
|
163
|
+
return this._state;
|
|
164
|
+
}
|
|
165
|
+
on(event, callback) {
|
|
166
|
+
return this.emitter.on(event, callback);
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Emit without letting a throwing partner listener break the caller: a hang-up
|
|
170
|
+
* must still release the mic and a tool call must still be answered. Logged
|
|
171
|
+
* by event name only, never the payload (it can carry tool arguments).
|
|
172
|
+
*/
|
|
173
|
+
safeEmit(event, ...args) {
|
|
174
|
+
try {
|
|
175
|
+
this.emitter.emit(event, ...args);
|
|
176
|
+
}
|
|
177
|
+
catch {
|
|
178
|
+
console.error(`[Talk2View] a voice "${event}" listener threw`);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
setState(state) {
|
|
182
|
+
if (this._state === state)
|
|
183
|
+
return;
|
|
184
|
+
this._state = state;
|
|
185
|
+
this.safeEmit('stateChange', state);
|
|
186
|
+
}
|
|
187
|
+
emitError(type, message) {
|
|
188
|
+
this.safeEmit('error', { type, message });
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* @internal Start loading the call libraries before the first `start()`
|
|
192
|
+
* (the button calls this on hover). `start()` reuses the load.
|
|
193
|
+
*/
|
|
194
|
+
preload() {
|
|
195
|
+
this.loadLibs().catch(() => undefined);
|
|
196
|
+
}
|
|
197
|
+
/** The call libraries, loaded once. A failed load is retried next time. */
|
|
198
|
+
loadLibs() {
|
|
199
|
+
const load = (this.libs ??= (this.deps.loadLibs ?? loadPipecatLibs)());
|
|
200
|
+
load.catch(() => {
|
|
201
|
+
if (this.libs === load)
|
|
202
|
+
this.libs = null;
|
|
203
|
+
});
|
|
204
|
+
return load;
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Press the button. Resolves once the microphone is live, or quietly if the
|
|
208
|
+
* call is hung up (`stop()`) before it connects.
|
|
209
|
+
*/
|
|
210
|
+
async start() {
|
|
211
|
+
if (this._state === 'connecting' || this._state === 'listening')
|
|
212
|
+
return;
|
|
213
|
+
const epoch = ++this.epoch;
|
|
214
|
+
const stale = () => epoch !== this.epoch;
|
|
215
|
+
this.setState('connecting');
|
|
216
|
+
const aborted = new Promise((resolve) => {
|
|
217
|
+
this.abortStart = resolve;
|
|
218
|
+
});
|
|
219
|
+
let connecting = false;
|
|
220
|
+
let client = null;
|
|
221
|
+
let connectCall = null;
|
|
222
|
+
// A hang-up while the browser is still asking for the microphone reaches
|
|
223
|
+
// the client before its transport exists: client-js 1.13.1's connect()
|
|
224
|
+
// awaits initDevices() before Transport.connect() makes its AbortController,
|
|
225
|
+
// and the transport's stop() returns early without a peer connection. So
|
|
226
|
+
// that disconnect() cancels nothing, and once the prompt is answered the
|
|
227
|
+
// call comes up anyway. Hang up again when connect() settles (on bot-ready
|
|
228
|
+
// or failure), which closes the peer connection and releases the mic.
|
|
229
|
+
const abandon = () => {
|
|
230
|
+
const orphan = client;
|
|
231
|
+
if (!orphan || !connectCall)
|
|
232
|
+
return;
|
|
233
|
+
connectCall.then(() => orphan.disconnect(), () => undefined).catch(() => undefined);
|
|
234
|
+
};
|
|
235
|
+
const timings = startTimings();
|
|
236
|
+
try {
|
|
237
|
+
// The call libraries load while the session is checked: the same chunk
|
|
238
|
+
// whatever the answer. Awaited before the mint, so a chunk that fails
|
|
239
|
+
// to load still never burns a ticket.
|
|
240
|
+
const libsLoad = this.loadLibs();
|
|
241
|
+
libsLoad.catch(() => undefined); // awaited below; never an unhandled rejection
|
|
242
|
+
if (!(await this.deps.ensureSession())) {
|
|
243
|
+
throw new VoiceStartError('account_required', 'Sign in to use voice');
|
|
244
|
+
}
|
|
245
|
+
timings.mark('session');
|
|
246
|
+
if (stale())
|
|
247
|
+
return;
|
|
248
|
+
const libs = await libsLoad;
|
|
249
|
+
timings.mark('libs');
|
|
250
|
+
if (stale())
|
|
251
|
+
return;
|
|
252
|
+
// The client is built before the mint so the microphone can open while
|
|
253
|
+
// (or before) the ticket is minted; the ICE servers come with the mint.
|
|
254
|
+
const transport = new libs.SmallWebRTCTransport({ iceServers: [] });
|
|
255
|
+
// A refused first offer (503 at capacity, 502) is retried by the transport
|
|
256
|
+
// for several seconds; the ticket cannot succeed on a retry, so allow none
|
|
257
|
+
// until connected, then restore the default for mid-call ICE recovery.
|
|
258
|
+
// `maxReconnectionAttempts` is a public field of the pinned 1.10.8
|
|
259
|
+
// transport that its typings do not declare.
|
|
260
|
+
const retry = transport;
|
|
261
|
+
const retries = retry.maxReconnectionAttempts;
|
|
262
|
+
if (typeof retries === 'number')
|
|
263
|
+
retry.maxReconnectionAttempts = 0;
|
|
264
|
+
const pipecat = new libs.PipecatClient({
|
|
265
|
+
transport,
|
|
266
|
+
enableMic: true,
|
|
267
|
+
enableCam: false,
|
|
268
|
+
callbacks: {
|
|
269
|
+
onConnected: () => {
|
|
270
|
+
// A call that comes up after it was hung up (see `abandon`) is
|
|
271
|
+
// closed at once, not left streaming the mic until bot-ready.
|
|
272
|
+
if (stale()) {
|
|
273
|
+
pipecat.disconnect().catch(() => undefined);
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
if (typeof retries === 'number')
|
|
277
|
+
retry.maxReconnectionAttempts = retries;
|
|
278
|
+
this.setState('listening');
|
|
279
|
+
},
|
|
280
|
+
onDisconnected: () => {
|
|
281
|
+
if (!stale())
|
|
282
|
+
void this.finish('disconnected');
|
|
283
|
+
},
|
|
284
|
+
onError: (msg) => {
|
|
285
|
+
if (!stale())
|
|
286
|
+
this.emitError('transport_error', msg?.data?.message ?? 'Voice connection error');
|
|
287
|
+
},
|
|
288
|
+
onServerMessage: (data) => {
|
|
289
|
+
if (stale())
|
|
290
|
+
return;
|
|
291
|
+
this.handleServerMessage(data).catch(() => {
|
|
292
|
+
if (!stale())
|
|
293
|
+
this.emitError('voice_error', 'Something went wrong in the voice call');
|
|
294
|
+
});
|
|
295
|
+
},
|
|
296
|
+
onUserTranscript: (d) => {
|
|
297
|
+
if (!stale())
|
|
298
|
+
this.safeEmit('transcript', { role: 'user', text: d.text, final: !!d.final });
|
|
299
|
+
},
|
|
300
|
+
onBotTranscript: (d) => {
|
|
301
|
+
if (!stale())
|
|
302
|
+
this.safeEmit('transcript', { role: 'bot', text: d.text, final: true });
|
|
303
|
+
},
|
|
304
|
+
onTrackStarted: (track, participant) => {
|
|
305
|
+
if (stale() || participant?.local || track.kind !== 'audio')
|
|
306
|
+
return;
|
|
307
|
+
(this.deps.attachAudio ?? this.attachAudio)(track);
|
|
308
|
+
},
|
|
309
|
+
onDeviceError: (error) => {
|
|
310
|
+
if (stale())
|
|
311
|
+
return;
|
|
312
|
+
// The call is audio-only: a camera error is not ours to report.
|
|
313
|
+
if (Array.isArray(error?.devices) && !error.devices.includes('mic'))
|
|
314
|
+
return;
|
|
315
|
+
// No microphone means a call that listens to nothing: end it and say why.
|
|
316
|
+
void this.finish('error', MIC_UNAVAILABLE);
|
|
317
|
+
},
|
|
318
|
+
},
|
|
319
|
+
});
|
|
320
|
+
client = pipecat;
|
|
321
|
+
this.client = pipecat;
|
|
322
|
+
// The microphone. A ticket lives 60 s, so while the browser will still
|
|
323
|
+
// ask, the mic opens first: a user reading the prompt must not let the
|
|
324
|
+
// ticket expire (they got "took too long to connect"). Already allowed,
|
|
325
|
+
// it opens alongside the mint and costs no time.
|
|
326
|
+
const micAllowed = (await (this.deps.micPermission ?? queryMicPermission)()) === 'granted';
|
|
327
|
+
if (stale())
|
|
328
|
+
return;
|
|
329
|
+
const devices = pipecat.initDevices();
|
|
330
|
+
devices.catch(() => undefined); // awaited below
|
|
331
|
+
// A hang-up must not wait on the prompt: start() returns at once, and
|
|
332
|
+
// the mic the prompt opens later is released as soon as it opens (the
|
|
333
|
+
// teardown that ran first found none to release).
|
|
334
|
+
const micOpened = async () => {
|
|
335
|
+
await Promise.race([devices, aborted]);
|
|
336
|
+
if (!stale())
|
|
337
|
+
return true;
|
|
338
|
+
devices.then(() => releaseMic(pipecat), () => undefined);
|
|
339
|
+
return false;
|
|
340
|
+
};
|
|
341
|
+
if (!micAllowed) {
|
|
342
|
+
if (!(await micOpened()))
|
|
343
|
+
return;
|
|
344
|
+
timings.mark('mic');
|
|
345
|
+
}
|
|
346
|
+
// The access token is fetched alongside the mint, not after it.
|
|
347
|
+
const tokenFetch = this.deps.getValidAccessToken();
|
|
348
|
+
tokenFetch.catch(() => undefined); // awaited below
|
|
349
|
+
const mint = await this.deps.request('/v1/voice/sessions', { method: 'POST' });
|
|
350
|
+
timings.mark('mint');
|
|
351
|
+
if (stale())
|
|
352
|
+
return;
|
|
353
|
+
const token = await tokenFetch;
|
|
354
|
+
timings.mark('token');
|
|
355
|
+
if (stale())
|
|
356
|
+
return;
|
|
357
|
+
if (!token)
|
|
358
|
+
throw new VoiceStartError('auth_expired', 'Sign in again to use voice');
|
|
359
|
+
if (micAllowed) {
|
|
360
|
+
if (!(await micOpened()))
|
|
361
|
+
return;
|
|
362
|
+
timings.mark('mic');
|
|
363
|
+
}
|
|
364
|
+
transport.iceServers = mint.ice_servers.map((s) => ({
|
|
365
|
+
urls: s.urls,
|
|
366
|
+
...(s.username ? { username: s.username } : {}),
|
|
367
|
+
...(s.credential ? { credential: s.credential } : {}),
|
|
368
|
+
}));
|
|
369
|
+
connecting = true;
|
|
370
|
+
connectCall = pipecat.connect({
|
|
371
|
+
webrtcRequestParams: {
|
|
372
|
+
endpoint: mint.voice_url,
|
|
373
|
+
requestData: { ticket: mint.ticket, partner_key: this.deps.partnerKey, access_token: token },
|
|
374
|
+
},
|
|
375
|
+
});
|
|
376
|
+
// connect() waits for the bot; a hang-up mid-connect settles `aborted`.
|
|
377
|
+
await Promise.race([connectCall, aborted]);
|
|
378
|
+
if (stale())
|
|
379
|
+
abandon();
|
|
380
|
+
else
|
|
381
|
+
timings.done('connected');
|
|
382
|
+
}
|
|
383
|
+
catch (err) {
|
|
384
|
+
// Hung up mid-start: stop() already tore down and reported the ending.
|
|
385
|
+
if (stale()) {
|
|
386
|
+
abandon();
|
|
387
|
+
if (client)
|
|
388
|
+
releaseMic(client);
|
|
389
|
+
return;
|
|
390
|
+
}
|
|
391
|
+
this.abortStart = null;
|
|
392
|
+
this.epoch += 1; // late callbacks from this failed client are not this call's
|
|
393
|
+
await this.teardown();
|
|
394
|
+
const error = await describeStartError(err, connecting);
|
|
395
|
+
this.emitError(error.type, error.message);
|
|
396
|
+
this.setState('error');
|
|
397
|
+
throw typeof err?.type === 'string'
|
|
398
|
+
? err
|
|
399
|
+
: new VoiceStartError(error.type, error.message, { cause: err });
|
|
400
|
+
}
|
|
401
|
+
finally {
|
|
402
|
+
if (!stale())
|
|
403
|
+
this.abortStart = null;
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
/** Hang up. Safe to call in any state. */
|
|
407
|
+
async stop() {
|
|
408
|
+
await this.finish('stopped');
|
|
409
|
+
}
|
|
410
|
+
/**
|
|
411
|
+
* @internal The signed-in session died (not a deliberate sign-out): end any
|
|
412
|
+
* call, starting or live, as `auth_expired` with an `auth_expired` error.
|
|
413
|
+
*/
|
|
414
|
+
async expire() {
|
|
415
|
+
await this.finish('auth_expired');
|
|
416
|
+
}
|
|
417
|
+
finish(reason, error) {
|
|
418
|
+
// A second hang-up while the first is still tearing down joins it: one
|
|
419
|
+
// disconnect, one `ended`. Only the same call's: a call started since
|
|
420
|
+
// (a new epoch) gets its own ending.
|
|
421
|
+
if (this.ending && this.ending.epoch === this.epoch)
|
|
422
|
+
return this.ending.promise;
|
|
423
|
+
if (this._state === 'idle' || this._state === 'ended' || this._state === 'error')
|
|
424
|
+
return Promise.resolve();
|
|
425
|
+
// teardown() nulls the client before disconnecting, so the onDisconnected
|
|
426
|
+
// our own hang-up triggers is not a second, spurious ending.
|
|
427
|
+
if (reason === 'disconnected' && this.client === null)
|
|
428
|
+
return Promise.resolve();
|
|
429
|
+
// A transport that fails to connect fires onDisconnected before connect()
|
|
430
|
+
// rejects; start()'s catch reports that failure as an error, not an ending.
|
|
431
|
+
if (reason === 'disconnected' && this._state === 'connecting')
|
|
432
|
+
return Promise.resolve();
|
|
433
|
+
// endCall() bumps the epoch synchronously, before its first await.
|
|
434
|
+
const promise = this.endCall(reason, error);
|
|
435
|
+
const ending = { epoch: this.epoch, promise };
|
|
436
|
+
this.ending = ending;
|
|
437
|
+
void promise.finally(() => {
|
|
438
|
+
if (this.ending === ending)
|
|
439
|
+
this.ending = null;
|
|
440
|
+
});
|
|
441
|
+
return promise;
|
|
442
|
+
}
|
|
443
|
+
async endCall(reason, error) {
|
|
444
|
+
// Everything from the call being ended (a start still in flight, late
|
|
445
|
+
// callbacks, tool calls mid-relay) is now stale.
|
|
446
|
+
this.epoch += 1;
|
|
447
|
+
const abortStart = this.abortStart;
|
|
448
|
+
this.abortStart = null;
|
|
449
|
+
// Privacy first: the mic is released and the client disconnected before any
|
|
450
|
+
// partner listener runs.
|
|
451
|
+
await this.teardown();
|
|
452
|
+
abortStart?.();
|
|
453
|
+
if (error) {
|
|
454
|
+
this.emitError(error.type, error.message);
|
|
455
|
+
}
|
|
456
|
+
else if (reason === 'budget_exhausted') {
|
|
457
|
+
this.emitError('insufficient_credit', 'You have used up your credits for now.');
|
|
458
|
+
}
|
|
459
|
+
else if (reason === 'auth_expired') {
|
|
460
|
+
this.emitError(AUTH_EXPIRED.type, AUTH_EXPIRED.message);
|
|
461
|
+
}
|
|
462
|
+
this.setState('ended');
|
|
463
|
+
this.safeEmit('ended', reason);
|
|
464
|
+
}
|
|
465
|
+
async teardown() {
|
|
466
|
+
const client = this.client;
|
|
467
|
+
this.client = null;
|
|
468
|
+
this.detachAudio();
|
|
469
|
+
if (client) {
|
|
470
|
+
try {
|
|
471
|
+
await client.disconnect();
|
|
472
|
+
}
|
|
473
|
+
catch {
|
|
474
|
+
// already gone
|
|
475
|
+
}
|
|
476
|
+
// A client that never connected keeps its mic after disconnect().
|
|
477
|
+
releaseMic(client);
|
|
478
|
+
}
|
|
479
|
+
// Last: closing the card emits `approvalChange(null)`. Nothing is sent for
|
|
480
|
+
// it, since the client is gone.
|
|
481
|
+
this.endApproval('The call ended');
|
|
482
|
+
}
|
|
483
|
+
attachAudio = (track) => {
|
|
484
|
+
if (typeof document === 'undefined')
|
|
485
|
+
return;
|
|
486
|
+
// A renegotiation (ICE recovery) fires onTrackStarted again: one sink, not two.
|
|
487
|
+
this.detachAudio();
|
|
488
|
+
const el = document.createElement('audio');
|
|
489
|
+
el.autoplay = true;
|
|
490
|
+
el.srcObject = new MediaStream([track]);
|
|
491
|
+
el.style.display = 'none';
|
|
492
|
+
document.body.appendChild(el);
|
|
493
|
+
this.audio = el;
|
|
494
|
+
};
|
|
495
|
+
detachAudio() {
|
|
496
|
+
if (!this.audio)
|
|
497
|
+
return;
|
|
498
|
+
this.audio.srcObject = null;
|
|
499
|
+
this.audio.remove();
|
|
500
|
+
this.audio = null;
|
|
501
|
+
}
|
|
502
|
+
// ── RTVI relay ──
|
|
503
|
+
async handleServerMessage(data) {
|
|
504
|
+
const msg = data;
|
|
505
|
+
switch (msg?.type) {
|
|
506
|
+
case 't2v-tool-call':
|
|
507
|
+
await this.relayToolCall(msg);
|
|
508
|
+
return;
|
|
509
|
+
case 't2v-token-request': {
|
|
510
|
+
const client = this.client;
|
|
511
|
+
let token;
|
|
512
|
+
try {
|
|
513
|
+
token = await this.deps.getValidAccessToken({ forceRefresh: true });
|
|
514
|
+
}
|
|
515
|
+
catch {
|
|
516
|
+
// The call cannot continue without a fresh token: end it as expired.
|
|
517
|
+
if (this.client === client)
|
|
518
|
+
await this.finish('auth_expired');
|
|
519
|
+
return;
|
|
520
|
+
}
|
|
521
|
+
if (this.client === client)
|
|
522
|
+
client?.sendClientMessage('t2v-token', { access_token: token ?? '' });
|
|
523
|
+
return;
|
|
524
|
+
}
|
|
525
|
+
case 't2v-agent-state':
|
|
526
|
+
this.safeEmit('agentState', msg.state === 'working' ? 'working' : 'idle');
|
|
527
|
+
return;
|
|
528
|
+
case 't2v-call-ended':
|
|
529
|
+
await this.finish(typeof msg.reason === 'string' && END_REASONS.has(msg.reason) ? msg.reason : 'error');
|
|
530
|
+
return;
|
|
531
|
+
default:
|
|
532
|
+
return;
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
async relayToolCall(msg) {
|
|
536
|
+
const toolCallId = msg.tool_call_id;
|
|
537
|
+
const toolName = msg.tool_name;
|
|
538
|
+
const args = msg.arguments ?? {};
|
|
539
|
+
const client = this.client;
|
|
540
|
+
let outcome;
|
|
541
|
+
try {
|
|
542
|
+
// A throwing `toolCall` listener is isolated: the call still runs and is answered.
|
|
543
|
+
this.safeEmit('toolCall', { toolCallId, toolName, arguments: args });
|
|
544
|
+
outcome = await this.runToolCall(toolCallId, toolName, args);
|
|
545
|
+
}
|
|
546
|
+
catch {
|
|
547
|
+
// A throwing permission callback or tool: the agent still gets an answer.
|
|
548
|
+
outcome = { result: JSON.stringify({ error: 'The application could not run this tool' }), isError: true };
|
|
549
|
+
}
|
|
550
|
+
// Only to the call that asked: a result for an ended call goes nowhere.
|
|
551
|
+
if (this.client !== client)
|
|
552
|
+
return;
|
|
553
|
+
client?.sendClientMessage('t2v-tool-result', {
|
|
554
|
+
tool_call_id: toolCallId,
|
|
555
|
+
result: outcome.result,
|
|
556
|
+
is_error: outcome.isError,
|
|
557
|
+
});
|
|
558
|
+
}
|
|
559
|
+
async runToolCall(toolCallId, toolName, args) {
|
|
560
|
+
// Hung up while the partner's permission callback or the card was pending:
|
|
561
|
+
// no card, no tool run. Nothing is sent either (the channel is gone).
|
|
562
|
+
const epoch = this.epoch;
|
|
563
|
+
const CALL_ENDED = { result: JSON.stringify({ error: 'The call ended' }), isError: true };
|
|
564
|
+
let outcome;
|
|
565
|
+
const perm = await this.deps.tools.checkPermission(toolName, args);
|
|
566
|
+
if (epoch !== this.epoch)
|
|
567
|
+
return CALL_ENDED;
|
|
568
|
+
if (perm.action === 'deny') {
|
|
569
|
+
outcome = { result: JSON.stringify({ error: perm.message ?? 'Denied by the application' }), isError: true };
|
|
570
|
+
}
|
|
571
|
+
else if (perm.action === 'require_approval' && !this.alwaysAllowed.has(toolName)) {
|
|
572
|
+
const { decision, endedBecause } = await this.awaitApproval(toolCallId, toolName, args);
|
|
573
|
+
if (epoch !== this.epoch)
|
|
574
|
+
return CALL_ENDED;
|
|
575
|
+
if (endedBecause) {
|
|
576
|
+
outcome = { result: JSON.stringify({ error: endedBecause }), isError: true };
|
|
577
|
+
}
|
|
578
|
+
else if (decision.action === 'deny') {
|
|
579
|
+
const why = decision.feedback ? `The user declined: ${decision.feedback}` : 'The user declined';
|
|
580
|
+
outcome = { result: JSON.stringify({ error: why }), isError: true };
|
|
581
|
+
}
|
|
582
|
+
else {
|
|
583
|
+
if (decision.action === 'always')
|
|
584
|
+
this.alwaysAllowed.add(toolName);
|
|
585
|
+
outcome = await this.deps.tools.executeToolCall(toolName, decision.updatedInput ?? args);
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
else {
|
|
589
|
+
outcome = await this.deps.tools.executeToolCall(toolName, perm.action === 'allow' ? (perm.updatedInput ?? args) : args);
|
|
590
|
+
}
|
|
591
|
+
return outcome;
|
|
592
|
+
}
|
|
593
|
+
/** Close the open card without a human answer, telling the agent why. */
|
|
594
|
+
endApproval(reason) {
|
|
595
|
+
this.cancelApproval?.(reason);
|
|
596
|
+
}
|
|
597
|
+
awaitApproval(toolCallId, toolName, args) {
|
|
598
|
+
// One at a time: a second approval while one waits denies the first.
|
|
599
|
+
this.endApproval('Superseded by a newer request');
|
|
600
|
+
return new Promise((resolve) => {
|
|
601
|
+
const timeoutMs = this.deps.approvalTimeoutMs ?? DEFAULT_APPROVAL_TIMEOUT_MS;
|
|
602
|
+
let settled = false;
|
|
603
|
+
const settle = (decision, endedBecause) => {
|
|
604
|
+
if (settled)
|
|
605
|
+
return;
|
|
606
|
+
settled = true;
|
|
607
|
+
clearTimeout(timer);
|
|
608
|
+
if (this.pendingApproval === pending) {
|
|
609
|
+
this.pendingApproval = null;
|
|
610
|
+
this.cancelApproval = null;
|
|
611
|
+
}
|
|
612
|
+
resolve(endedBecause ? { decision, endedBecause } : { decision });
|
|
613
|
+
this.safeEmit('approvalChange', null);
|
|
614
|
+
};
|
|
615
|
+
const end = (reason) => settle({ action: 'deny' }, reason);
|
|
616
|
+
const timer = setTimeout(() => end('The user did not answer in time'), timeoutMs);
|
|
617
|
+
const pending = {
|
|
618
|
+
toolCallId,
|
|
619
|
+
toolName,
|
|
620
|
+
arguments: args,
|
|
621
|
+
description: this.deps.tools.getDescription(toolName),
|
|
622
|
+
decide: (decision) => settle(decision),
|
|
623
|
+
};
|
|
624
|
+
this.pendingApproval = pending;
|
|
625
|
+
this.cancelApproval = end;
|
|
626
|
+
this.safeEmit('approvalChange', pending);
|
|
627
|
+
});
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
//# sourceMappingURL=voice.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"voice.js","sourceRoot":"","sources":["../src/voice.ts"],"names":[],"mappings":"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"}
|