@nuancelabs/js-sdk 0.10.0 → 0.11.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/index.d.ts +13 -0
- package/index.js +60 -5
- package/package.json +1 -1
package/index.d.ts
CHANGED
|
@@ -499,6 +499,13 @@ export declare interface SessionPersonality {
|
|
|
499
499
|
export declare interface SessionTokenRequest {
|
|
500
500
|
/** Who the avatar is in the conversation. Leave it out for the default personality. */
|
|
501
501
|
personality?: SessionPersonality;
|
|
502
|
+
/**
|
|
503
|
+
* Your own id for the person this conversation is for, such as a hash of
|
|
504
|
+
* your user id. After repeated policy violations, new conversations pause
|
|
505
|
+
* for this person only, not for your whole app. Letters, digits and
|
|
506
|
+
* `_ . : -`, up to 128 characters: never an email address or a name.
|
|
507
|
+
*/
|
|
508
|
+
end_user_id?: string;
|
|
502
509
|
}
|
|
503
510
|
|
|
504
511
|
/** What `POST /session-tokens` returns. */
|
|
@@ -507,11 +514,17 @@ export declare interface SessionTokenResponse {
|
|
|
507
514
|
token: string;
|
|
508
515
|
/** When the token stops being able to start a conversation (UTC, ISO 8601). */
|
|
509
516
|
expires_at: string;
|
|
517
|
+
/** What to change in how you mint tokens; empty when nothing. */
|
|
518
|
+
warnings?: string[];
|
|
510
519
|
}
|
|
511
520
|
|
|
512
521
|
/** When the avatar starts speaking: see {@link CreateNuanceConversationOptions.startOn}. */
|
|
513
522
|
export declare type StartOn = "first-frame" | "full-quality";
|
|
514
523
|
|
|
524
|
+
|
|
525
|
+
|
|
526
|
+
|
|
527
|
+
|
|
515
528
|
/**
|
|
516
529
|
* The local user participant in a conversation.
|
|
517
530
|
*/
|
package/index.js
CHANGED
|
@@ -4,7 +4,7 @@ function isRecord(value) {
|
|
|
4
4
|
}
|
|
5
5
|
|
|
6
6
|
// src/core/sdk-version.ts
|
|
7
|
-
var SDK_HEADER = `js/${"0.
|
|
7
|
+
var SDK_HEADER = `js/${"0.11.0"}`;
|
|
8
8
|
|
|
9
9
|
// src/utils.ts
|
|
10
10
|
function normalizeHost(host) {
|
|
@@ -1098,6 +1098,17 @@ function parseSessionEvent(payload) {
|
|
|
1098
1098
|
if (decoded.type === "floor") {
|
|
1099
1099
|
return { type: "floor", speaking: decoded.state === "speaking" };
|
|
1100
1100
|
}
|
|
1101
|
+
if (decoded.type === "tool.call" && typeof decoded.call_id === "string" && typeof decoded.name === "string" && isRecord(decoded.arguments)) {
|
|
1102
|
+
return {
|
|
1103
|
+
type: "tool-call",
|
|
1104
|
+
call: {
|
|
1105
|
+
callId: decoded.call_id,
|
|
1106
|
+
name: decoded.name,
|
|
1107
|
+
label: typeof decoded.label === "string" ? decoded.label : "",
|
|
1108
|
+
arguments: decoded.arguments
|
|
1109
|
+
}
|
|
1110
|
+
};
|
|
1111
|
+
}
|
|
1101
1112
|
if (decoded.type === "session.status" && decoded.status === "ended") {
|
|
1102
1113
|
return {
|
|
1103
1114
|
type: "ended",
|
|
@@ -1544,6 +1555,7 @@ class LiveKitUserParticipant {
|
|
|
1544
1555
|
// src/providers/livekit/conversation.ts
|
|
1545
1556
|
var DATA_EVENT_TOPIC = "nuance.data";
|
|
1546
1557
|
var SESSION_TOPIC = "nuance.v1";
|
|
1558
|
+
var PACKET_MAX_BYTES = 14000;
|
|
1547
1559
|
var RUNTIME_TOPIC = "runtime";
|
|
1548
1560
|
var CLOCK_SYNC_TOPIC = "clock-sync";
|
|
1549
1561
|
var STATS_FLUSH_TIMEOUT_MS = 300;
|
|
@@ -1551,6 +1563,7 @@ var SESSION_END_TIMEOUT_MS = 300;
|
|
|
1551
1563
|
var SESSION_END_ID = "client-session-end";
|
|
1552
1564
|
var REFUSAL_REASON_WAIT_MS = 500;
|
|
1553
1565
|
var COMMAND_TIMEOUT_MS = 5000;
|
|
1566
|
+
var STREAM_TIMEOUT_MS = 30000;
|
|
1554
1567
|
var BACKGROUND_ID = /^[a-z0-9][a-z0-9_-]{0,63}$/;
|
|
1555
1568
|
var AVATAR_RETURN_TIMEOUT_MS = 8000;
|
|
1556
1569
|
function isReconnecting(lkState) {
|
|
@@ -1764,9 +1777,24 @@ class LiveKitConversation {
|
|
|
1764
1777
|
async releaseAgent() {
|
|
1765
1778
|
return this.command({ type: "floor.release" });
|
|
1766
1779
|
}
|
|
1780
|
+
async sendToolResult(callId, output, options = {}) {
|
|
1781
|
+
return this.command({
|
|
1782
|
+
type: "tool.result",
|
|
1783
|
+
call_id: callId,
|
|
1784
|
+
output,
|
|
1785
|
+
...options.images?.length && {
|
|
1786
|
+
images: options.images.map(({ mediaType, data }) => ({
|
|
1787
|
+
media_type: mediaType,
|
|
1788
|
+
data
|
|
1789
|
+
}))
|
|
1790
|
+
},
|
|
1791
|
+
is_error: options.isError ?? false,
|
|
1792
|
+
final: options.final ?? true
|
|
1793
|
+
});
|
|
1794
|
+
}
|
|
1767
1795
|
onChange(handler) {
|
|
1768
1796
|
return this.onEvent((event) => {
|
|
1769
|
-
if (event.type !== "data-event" && event.type !== "screen-share-changed")
|
|
1797
|
+
if (event.type !== "data-event" && event.type !== "screen-share-changed" && event.type !== "tool-call")
|
|
1770
1798
|
handler(event);
|
|
1771
1799
|
});
|
|
1772
1800
|
}
|
|
@@ -1783,6 +1811,12 @@ class LiveKitConversation {
|
|
|
1783
1811
|
}
|
|
1784
1812
|
});
|
|
1785
1813
|
}
|
|
1814
|
+
onToolCall(handler) {
|
|
1815
|
+
return this.onEvent((event) => {
|
|
1816
|
+
if (event.type === "tool-call")
|
|
1817
|
+
handler(event.call);
|
|
1818
|
+
});
|
|
1819
|
+
}
|
|
1786
1820
|
async command(command) {
|
|
1787
1821
|
if (this.room.state !== ConnectionState2.Connected) {
|
|
1788
1822
|
throw new Error("Not connected — call connect() first");
|
|
@@ -1794,11 +1828,18 @@ class LiveKitConversation {
|
|
|
1794
1828
|
const answer = Promise.withResolvers();
|
|
1795
1829
|
this.commands.set(id, { type: command.type, settle: answer.resolve });
|
|
1796
1830
|
let timer;
|
|
1831
|
+
const text = JSON.stringify({ ...command, id });
|
|
1832
|
+
const payload = new TextEncoder().encode(text);
|
|
1833
|
+
const streamed = payload.byteLength > PACKET_MAX_BYTES;
|
|
1834
|
+
const sent = streamed ? this.room.localParticipant.sendText(text, { topic: SESSION_TOPIC }) : this.room.localParticipant.publishData(payload, {
|
|
1835
|
+
reliable: true,
|
|
1836
|
+
topic: SESSION_TOPIC
|
|
1837
|
+
});
|
|
1797
1838
|
try {
|
|
1798
1839
|
return await Promise.race([
|
|
1799
|
-
|
|
1840
|
+
sent.then(() => answer.promise),
|
|
1800
1841
|
new Promise((_, reject) => {
|
|
1801
|
-
timer = setTimeout(() => reject(new Error(`The runtime did not answer ${command.type}`)), COMMAND_TIMEOUT_MS);
|
|
1842
|
+
timer = setTimeout(() => reject(new Error(`The runtime did not answer ${command.type}`)), streamed ? STREAM_TIMEOUT_MS : COMMAND_TIMEOUT_MS);
|
|
1802
1843
|
})
|
|
1803
1844
|
]);
|
|
1804
1845
|
} finally {
|
|
@@ -2006,6 +2047,8 @@ class LiveKitConversation {
|
|
|
2006
2047
|
}
|
|
2007
2048
|
} else if (event.type === "floor") {
|
|
2008
2049
|
this.setAvatarSpeaking(event.speaking);
|
|
2050
|
+
} else if (event.type === "tool-call") {
|
|
2051
|
+
this.emit({ type: "tool-call", call: event.call });
|
|
2009
2052
|
} else if (event.type === "ended") {
|
|
2010
2053
|
this.answered?.();
|
|
2011
2054
|
if (!event.byClient)
|
|
@@ -2446,9 +2489,15 @@ class NuanceConversation {
|
|
|
2446
2489
|
}
|
|
2447
2490
|
return this.delegate.releaseAgent();
|
|
2448
2491
|
}
|
|
2492
|
+
async sendToolResult(callId, output, options) {
|
|
2493
|
+
if (!this.delegate) {
|
|
2494
|
+
throw new Error("Not connected — call connect() first");
|
|
2495
|
+
}
|
|
2496
|
+
return this.delegate.sendToolResult(callId, output, options);
|
|
2497
|
+
}
|
|
2449
2498
|
onChange(handler) {
|
|
2450
2499
|
return this.onEvent((event) => {
|
|
2451
|
-
if (event.type !== "data-event" && event.type !== "screen-share-changed")
|
|
2500
|
+
if (event.type !== "data-event" && event.type !== "screen-share-changed" && event.type !== "tool-call")
|
|
2452
2501
|
handler(event);
|
|
2453
2502
|
});
|
|
2454
2503
|
}
|
|
@@ -2465,6 +2514,12 @@ class NuanceConversation {
|
|
|
2465
2514
|
}
|
|
2466
2515
|
});
|
|
2467
2516
|
}
|
|
2517
|
+
onToolCall(handler) {
|
|
2518
|
+
return this.onEvent((event) => {
|
|
2519
|
+
if (event.type === "tool-call")
|
|
2520
|
+
handler(event.call);
|
|
2521
|
+
});
|
|
2522
|
+
}
|
|
2468
2523
|
async waitForSlot(conversationId, attempt) {
|
|
2469
2524
|
const admission = await this.followEvents(conversationId, attempt);
|
|
2470
2525
|
if (admission !== null) {
|