@craftedxp/voice-js 0.9.0 → 0.12.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 +25 -20
- package/dist/assistant.d.mts +3 -3
- package/dist/assistant.d.ts +3 -3
- package/dist/assistant.js +210 -22
- package/dist/assistant.js.map +1 -1
- package/dist/assistant.mjs +2 -1
- package/dist/browser.d.mts +3 -3
- package/dist/browser.d.ts +3 -3
- package/dist/browser.js +201 -34
- package/dist/browser.js.map +1 -1
- package/dist/browser.mjs +3 -2
- package/dist/browser.mjs.map +1 -1
- package/dist/{chunk-ZW22Y67M.mjs → chunk-C2U6V5NI.mjs} +191 -23
- package/dist/chunk-C2U6V5NI.mjs.map +1 -0
- package/dist/chunk-OS2GZAR7.mjs +18 -0
- package/dist/chunk-OS2GZAR7.mjs.map +1 -0
- package/dist/{chunk-LV7JGPYW.mjs → chunk-VSY43NGD.mjs} +6 -13
- package/dist/chunk-VSY43NGD.mjs.map +1 -0
- package/dist/{config-D2TbvIqT.d.mts → config-DfbPB1Tq.d.mts} +22 -3
- package/dist/{config-D2TbvIqT.d.ts → config-DfbPB1Tq.d.ts} +22 -3
- package/dist/embed.iife.js +42 -5
- package/dist/{incomingCall-CfRRzj2P.d.ts → incomingCall-2B3XB8pM.d.mts} +3 -1
- package/dist/{incomingCall-CfRRzj2P.d.mts → incomingCall-CYmeQkIw.d.ts} +3 -1
- package/dist/node.d.mts +37 -4
- package/dist/node.d.ts +37 -4
- package/dist/node.js +31 -2
- package/dist/node.js.map +1 -1
- package/dist/node.mjs +31 -2
- package/dist/node.mjs.map +1 -1
- package/dist/room.js +15 -12
- package/dist/room.js.map +1 -1
- package/dist/room.mjs +2 -1
- package/dist/transcribe.d.mts +2 -2
- package/dist/transcribe.d.ts +2 -2
- package/dist/transcribe.js +209 -21
- package/dist/transcribe.js.map +1 -1
- package/dist/transcribe.mjs +2 -1
- package/dist/transcribe.mjs.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-LV7JGPYW.mjs.map +0 -1
- package/dist/chunk-ZW22Y67M.mjs.map +0 -1
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { g as CallTransport } from './config-DfbPB1Tq.mjs';
|
|
2
|
+
|
|
1
3
|
type OnChunk = (pcm: ArrayBuffer) => void;
|
|
2
4
|
type OnVolume$1 = (rms01: number) => void;
|
|
3
5
|
type OnError = (err: Error) => void;
|
|
@@ -87,7 +89,7 @@ type ReconnectingWebSocket = ReturnType<typeof createReconnectingWebSocket>;
|
|
|
87
89
|
interface IncomingCallPayload {
|
|
88
90
|
token: string;
|
|
89
91
|
agentId: string;
|
|
90
|
-
transport:
|
|
92
|
+
transport: CallTransport;
|
|
91
93
|
webrtcGatewayBase?: string;
|
|
92
94
|
expiresAt?: number;
|
|
93
95
|
agentName?: string;
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { g as CallTransport } from './config-DfbPB1Tq.js';
|
|
2
|
+
|
|
1
3
|
type OnChunk = (pcm: ArrayBuffer) => void;
|
|
2
4
|
type OnVolume$1 = (rms01: number) => void;
|
|
3
5
|
type OnError = (err: Error) => void;
|
|
@@ -87,7 +89,7 @@ type ReconnectingWebSocket = ReturnType<typeof createReconnectingWebSocket>;
|
|
|
87
89
|
interface IncomingCallPayload {
|
|
88
90
|
token: string;
|
|
89
91
|
agentId: string;
|
|
90
|
-
transport:
|
|
92
|
+
transport: CallTransport;
|
|
91
93
|
webrtcGatewayBase?: string;
|
|
92
94
|
expiresAt?: number;
|
|
93
95
|
agentName?: string;
|
package/dist/node.d.mts
CHANGED
|
@@ -76,6 +76,8 @@ interface BuildWsUrlArgs {
|
|
|
76
76
|
agentId: string;
|
|
77
77
|
token: string;
|
|
78
78
|
bargeIn?: boolean;
|
|
79
|
+
/** Phase 35 — request LiveKit media on the same call socket. */
|
|
80
|
+
media?: 'livekit';
|
|
79
81
|
}
|
|
80
82
|
declare function buildWsUrl(args: BuildWsUrlArgs): string;
|
|
81
83
|
|
|
@@ -153,6 +155,19 @@ interface FetchTokenArgs {
|
|
|
153
155
|
*/
|
|
154
156
|
metadata?: Record<string, string>;
|
|
155
157
|
}
|
|
158
|
+
/** Media transports the server can select per call. `livekit` since 0.12.0 (phase 35). */
|
|
159
|
+
type CallTransport = 'ws' | 'webrtc' | 'livekit';
|
|
160
|
+
/**
|
|
161
|
+
* Fired once per call when the transport actually used differs from the one
|
|
162
|
+
* the server asked for (e.g. `livekit` requested, `livekit-client` not
|
|
163
|
+
* installed or the room join failed → `ws`). `reason` is free-form diagnostic
|
|
164
|
+
* text, never a stable code — match on `actual !== requested`.
|
|
165
|
+
*/
|
|
166
|
+
interface TransportChangeEvent {
|
|
167
|
+
requested: CallTransport;
|
|
168
|
+
actual: CallTransport;
|
|
169
|
+
reason?: string;
|
|
170
|
+
}
|
|
156
171
|
/**
|
|
157
172
|
* What `fetchToken` may return. The rich object form lets the server
|
|
158
173
|
* choose the transport per call. Returning a bare string is backwards-
|
|
@@ -161,8 +176,10 @@ interface FetchTokenArgs {
|
|
|
161
176
|
interface FetchTokenResult {
|
|
162
177
|
/** Raw `ct_` to feed into the WS open / WebRTC offer. */
|
|
163
178
|
token: string;
|
|
164
|
-
/** Server-selected transport. Default `'ws'` if absent.
|
|
165
|
-
|
|
179
|
+
/** Server-selected transport. Default `'ws'` if absent. `'livekit'` =
|
|
180
|
+
* audio on LiveKit tracks, control on the call WS; needs the optional
|
|
181
|
+
* peer 'livekit-client', otherwise the SDK falls back to 'ws'. */
|
|
182
|
+
transport?: CallTransport;
|
|
166
183
|
/** Required when `transport === 'webrtc'` AND the server uses a
|
|
167
184
|
* separate signaling gateway. When omitted on a webrtc result, the
|
|
168
185
|
* SDK falls back to the API base's Phase-1 routes (local dev). */
|
|
@@ -257,6 +274,8 @@ interface StartCallOptions {
|
|
|
257
274
|
* without diffing state.
|
|
258
275
|
*/
|
|
259
276
|
onAgentTurnStart?: () => void;
|
|
277
|
+
/** See `TransportChangeEvent`. Browser only; Node always uses `ws`. */
|
|
278
|
+
onTransportChange?: (e: TransportChangeEvent) => void;
|
|
260
279
|
}
|
|
261
280
|
interface Call {
|
|
262
281
|
/** Current state. Snapshot — subscribe via onStateChange for live updates. */
|
|
@@ -368,7 +387,7 @@ interface NodeCall extends Call {
|
|
|
368
387
|
sendClientEvent: (text: string) => boolean;
|
|
369
388
|
/**
|
|
370
389
|
* Send a typed user turn (text/multimodal sessions — token minted
|
|
371
|
-
* with `channel:'text'`). Sends `{type:'user_text', text}`. The
|
|
390
|
+
* with `channel:'text'` OR `channel:'multimodal'`). Sends `{type:'user_text', text}`. The
|
|
372
391
|
* server accepts `user_text` only on text-channel sessions and
|
|
373
392
|
* rejects it on voice (anti-injection), so this is a no-op in
|
|
374
393
|
* practice on voice calls beyond the frame being ignored
|
|
@@ -376,6 +395,20 @@ interface NodeCall extends Call {
|
|
|
376
395
|
* if the WS isn't open or text is empty/whitespace. Never throws.
|
|
377
396
|
*/
|
|
378
397
|
sendText: (text: string) => boolean;
|
|
398
|
+
/**
|
|
399
|
+
* Send an image for multimodal sessions (token minted with
|
|
400
|
+
* `channel:'multimodal'`). Sends `{type:'user_image', mimeType, data}`.
|
|
401
|
+
* `data` can be a base64 string (treated as-is) or a buffer
|
|
402
|
+
* (base64-encoded by the SDK). Returns `false` (and sends nothing)
|
|
403
|
+
* if: the WS isn't open, data is empty, mimeType is not
|
|
404
|
+
* png/jpeg/webp/gif, or the base64-encoded length exceeds 5 MB.
|
|
405
|
+
* Never throws.
|
|
406
|
+
*/
|
|
407
|
+
sendImage: (data: ArrayBuffer | ArrayBufferView | string, mimeType: string) => boolean;
|
|
408
|
+
/** Trusted, structured operator directive (vterm workflow buttons).
|
|
409
|
+
* Carries only an allow-listed action + a workflow name — no free text —
|
|
410
|
+
* so the server accepts it on voice and drives an agent turn from it. */
|
|
411
|
+
sendDirective: (action: 'observe_workflow' | 'run_workflow', workflow: string) => boolean;
|
|
379
412
|
}
|
|
380
413
|
/**
|
|
381
414
|
* Node bundle's analog of `VoiceClientFactory`. Same shape but
|
|
@@ -401,7 +434,7 @@ interface NodeVoiceClientFactory {
|
|
|
401
434
|
interface IncomingCallPayload {
|
|
402
435
|
token: string;
|
|
403
436
|
agentId: string;
|
|
404
|
-
transport:
|
|
437
|
+
transport: CallTransport;
|
|
405
438
|
webrtcGatewayBase?: string;
|
|
406
439
|
expiresAt?: number;
|
|
407
440
|
agentName?: string;
|
package/dist/node.d.ts
CHANGED
|
@@ -76,6 +76,8 @@ interface BuildWsUrlArgs {
|
|
|
76
76
|
agentId: string;
|
|
77
77
|
token: string;
|
|
78
78
|
bargeIn?: boolean;
|
|
79
|
+
/** Phase 35 — request LiveKit media on the same call socket. */
|
|
80
|
+
media?: 'livekit';
|
|
79
81
|
}
|
|
80
82
|
declare function buildWsUrl(args: BuildWsUrlArgs): string;
|
|
81
83
|
|
|
@@ -153,6 +155,19 @@ interface FetchTokenArgs {
|
|
|
153
155
|
*/
|
|
154
156
|
metadata?: Record<string, string>;
|
|
155
157
|
}
|
|
158
|
+
/** Media transports the server can select per call. `livekit` since 0.12.0 (phase 35). */
|
|
159
|
+
type CallTransport = 'ws' | 'webrtc' | 'livekit';
|
|
160
|
+
/**
|
|
161
|
+
* Fired once per call when the transport actually used differs from the one
|
|
162
|
+
* the server asked for (e.g. `livekit` requested, `livekit-client` not
|
|
163
|
+
* installed or the room join failed → `ws`). `reason` is free-form diagnostic
|
|
164
|
+
* text, never a stable code — match on `actual !== requested`.
|
|
165
|
+
*/
|
|
166
|
+
interface TransportChangeEvent {
|
|
167
|
+
requested: CallTransport;
|
|
168
|
+
actual: CallTransport;
|
|
169
|
+
reason?: string;
|
|
170
|
+
}
|
|
156
171
|
/**
|
|
157
172
|
* What `fetchToken` may return. The rich object form lets the server
|
|
158
173
|
* choose the transport per call. Returning a bare string is backwards-
|
|
@@ -161,8 +176,10 @@ interface FetchTokenArgs {
|
|
|
161
176
|
interface FetchTokenResult {
|
|
162
177
|
/** Raw `ct_` to feed into the WS open / WebRTC offer. */
|
|
163
178
|
token: string;
|
|
164
|
-
/** Server-selected transport. Default `'ws'` if absent.
|
|
165
|
-
|
|
179
|
+
/** Server-selected transport. Default `'ws'` if absent. `'livekit'` =
|
|
180
|
+
* audio on LiveKit tracks, control on the call WS; needs the optional
|
|
181
|
+
* peer 'livekit-client', otherwise the SDK falls back to 'ws'. */
|
|
182
|
+
transport?: CallTransport;
|
|
166
183
|
/** Required when `transport === 'webrtc'` AND the server uses a
|
|
167
184
|
* separate signaling gateway. When omitted on a webrtc result, the
|
|
168
185
|
* SDK falls back to the API base's Phase-1 routes (local dev). */
|
|
@@ -257,6 +274,8 @@ interface StartCallOptions {
|
|
|
257
274
|
* without diffing state.
|
|
258
275
|
*/
|
|
259
276
|
onAgentTurnStart?: () => void;
|
|
277
|
+
/** See `TransportChangeEvent`. Browser only; Node always uses `ws`. */
|
|
278
|
+
onTransportChange?: (e: TransportChangeEvent) => void;
|
|
260
279
|
}
|
|
261
280
|
interface Call {
|
|
262
281
|
/** Current state. Snapshot — subscribe via onStateChange for live updates. */
|
|
@@ -368,7 +387,7 @@ interface NodeCall extends Call {
|
|
|
368
387
|
sendClientEvent: (text: string) => boolean;
|
|
369
388
|
/**
|
|
370
389
|
* Send a typed user turn (text/multimodal sessions — token minted
|
|
371
|
-
* with `channel:'text'`). Sends `{type:'user_text', text}`. The
|
|
390
|
+
* with `channel:'text'` OR `channel:'multimodal'`). Sends `{type:'user_text', text}`. The
|
|
372
391
|
* server accepts `user_text` only on text-channel sessions and
|
|
373
392
|
* rejects it on voice (anti-injection), so this is a no-op in
|
|
374
393
|
* practice on voice calls beyond the frame being ignored
|
|
@@ -376,6 +395,20 @@ interface NodeCall extends Call {
|
|
|
376
395
|
* if the WS isn't open or text is empty/whitespace. Never throws.
|
|
377
396
|
*/
|
|
378
397
|
sendText: (text: string) => boolean;
|
|
398
|
+
/**
|
|
399
|
+
* Send an image for multimodal sessions (token minted with
|
|
400
|
+
* `channel:'multimodal'`). Sends `{type:'user_image', mimeType, data}`.
|
|
401
|
+
* `data` can be a base64 string (treated as-is) or a buffer
|
|
402
|
+
* (base64-encoded by the SDK). Returns `false` (and sends nothing)
|
|
403
|
+
* if: the WS isn't open, data is empty, mimeType is not
|
|
404
|
+
* png/jpeg/webp/gif, or the base64-encoded length exceeds 5 MB.
|
|
405
|
+
* Never throws.
|
|
406
|
+
*/
|
|
407
|
+
sendImage: (data: ArrayBuffer | ArrayBufferView | string, mimeType: string) => boolean;
|
|
408
|
+
/** Trusted, structured operator directive (vterm workflow buttons).
|
|
409
|
+
* Carries only an allow-listed action + a workflow name — no free text —
|
|
410
|
+
* so the server accepts it on voice and drives an agent turn from it. */
|
|
411
|
+
sendDirective: (action: 'observe_workflow' | 'run_workflow', workflow: string) => boolean;
|
|
379
412
|
}
|
|
380
413
|
/**
|
|
381
414
|
* Node bundle's analog of `VoiceClientFactory`. Same shape but
|
|
@@ -401,7 +434,7 @@ interface NodeVoiceClientFactory {
|
|
|
401
434
|
interface IncomingCallPayload {
|
|
402
435
|
token: string;
|
|
403
436
|
agentId: string;
|
|
404
|
-
transport:
|
|
437
|
+
transport: CallTransport;
|
|
405
438
|
webrtcGatewayBase?: string;
|
|
406
439
|
expiresAt?: number;
|
|
407
440
|
agentName?: string;
|
package/dist/node.js
CHANGED
|
@@ -299,7 +299,8 @@ function buildWsUrl(args) {
|
|
|
299
299
|
const base = new URL(args.apiBase);
|
|
300
300
|
const proto = base.protocol === "https:" ? "wss:" : "ws:";
|
|
301
301
|
const bargeQS = args.bargeIn === false ? "&barge=off" : "";
|
|
302
|
-
|
|
302
|
+
const mediaQS = args.media === "livekit" ? "&media=livekit" : "";
|
|
303
|
+
return `${proto}//${base.host}/v1/agents/${encodeURIComponent(args.agentId)}/call?token=${encodeURIComponent(args.token)}${bargeQS}${mediaQS}`;
|
|
303
304
|
}
|
|
304
305
|
|
|
305
306
|
// src/clientTools.ts
|
|
@@ -503,6 +504,34 @@ var NodeVoiceClient = class {
|
|
|
503
504
|
this.rws.send(JSON.stringify({ type: "user_text", text: t }));
|
|
504
505
|
return true;
|
|
505
506
|
};
|
|
507
|
+
this.sendDirective = (action, workflow) => {
|
|
508
|
+
if (!this.rws || this.rws.readyState() !== READYSTATE_OPEN2) return false;
|
|
509
|
+
if (action !== "observe_workflow" && action !== "run_workflow") return false;
|
|
510
|
+
const w = workflow.trim().slice(0, 64);
|
|
511
|
+
if (!w) return false;
|
|
512
|
+
this.rws.send(JSON.stringify({ type: "client_directive", action, workflow: w }));
|
|
513
|
+
return true;
|
|
514
|
+
};
|
|
515
|
+
// Send an image for multimodal sessions (channel:'multimodal').
|
|
516
|
+
// Data can be a base64 string (used as-is) or a buffer (base64-encoded).
|
|
517
|
+
// Allowed mimes: png, jpeg, webp, gif. Max 5 MB base64-encoded size.
|
|
518
|
+
this.sendImage = (data, mimeType) => {
|
|
519
|
+
if (!this.rws || this.rws.readyState() !== READYSTATE_OPEN2) return false;
|
|
520
|
+
const allowedMimes = ["image/png", "image/jpeg", "image/webp", "image/gif"];
|
|
521
|
+
if (!allowedMimes.includes(mimeType)) return false;
|
|
522
|
+
let base64Data;
|
|
523
|
+
if (typeof data === "string") {
|
|
524
|
+
base64Data = data;
|
|
525
|
+
} else {
|
|
526
|
+
const buffer = ArrayBuffer.isView(data) ? Buffer.from(data.buffer, data.byteOffset, data.byteLength) : Buffer.from(data);
|
|
527
|
+
base64Data = buffer.toString("base64");
|
|
528
|
+
}
|
|
529
|
+
if (!base64Data) return false;
|
|
530
|
+
const maxSize = 5 * 1024 * 1024;
|
|
531
|
+
if (base64Data.length > maxSize) return false;
|
|
532
|
+
this.rws.send(JSON.stringify({ type: "user_image", mimeType, data: base64Data }));
|
|
533
|
+
return true;
|
|
534
|
+
};
|
|
506
535
|
// ---------------------------------------------------------------
|
|
507
536
|
// Internal
|
|
508
537
|
// ---------------------------------------------------------------
|
|
@@ -649,7 +678,7 @@ var parseIncomingCall = (raw) => {
|
|
|
649
678
|
if (typeof p.agentId !== "string" || p.agentId.length === 0) {
|
|
650
679
|
throw new Error("parseIncomingCall: missing `agentId`");
|
|
651
680
|
}
|
|
652
|
-
const transport = p.transport === "webrtc" ? "webrtc" : "ws";
|
|
681
|
+
const transport = p.transport === "webrtc" ? "webrtc" : p.transport === "livekit" ? "livekit" : "ws";
|
|
653
682
|
const out = { token: p.token, agentId: p.agentId, transport };
|
|
654
683
|
if (transport === "webrtc" && typeof p.webrtcGatewayBase === "string") {
|
|
655
684
|
out.webrtcGatewayBase = p.webrtcGatewayBase;
|