@convai/web-sdk 1.8.0-beta.7 → 1.8.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 +44 -194
- package/dist/core/ConvaiClient.d.ts +1 -190
- package/dist/core/ConvaiClient.d.ts.map +1 -1
- package/dist/core/ConvaiClient.js +286 -1306
- package/dist/core/ConvaiClient.js.map +1 -1
- package/dist/core/MessageHandler.d.ts +1 -19
- package/dist/core/MessageHandler.d.ts.map +1 -1
- package/dist/core/MessageHandler.js +27 -378
- package/dist/core/MessageHandler.js.map +1 -1
- package/dist/core/connectRequest.d.ts +4 -17
- package/dist/core/connectRequest.d.ts.map +1 -1
- package/dist/core/connectRequest.js +17 -28
- package/dist/core/connectRequest.js.map +1 -1
- package/dist/core/index.d.ts +1 -6
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +1 -7
- package/dist/core/index.js.map +1 -1
- package/dist/core/logicalTurn.d.ts +6 -4
- package/dist/core/logicalTurn.d.ts.map +1 -1
- package/dist/core/logicalTurn.js +4 -29
- package/dist/core/logicalTurn.js.map +1 -1
- package/dist/core/modelOutput.d.ts.map +1 -1
- package/dist/core/modelOutput.js +2 -2
- package/dist/core/modelOutput.js.map +1 -1
- package/dist/core/types.d.ts +22 -860
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/embed/chat-embed-v1.js +9 -10
- package/dist/embed/chat-embed-v1.js.map +4 -4
- package/dist/react/components/ConvaiWidget.d.ts.map +1 -1
- package/dist/react/components/ConvaiWidget.js +1 -6
- package/dist/react/components/ConvaiWidget.js.map +1 -1
- package/dist/react/components/rtc-widget/components/AudioVisualizer.d.ts.map +1 -1
- package/dist/react/components/rtc-widget/components/AudioVisualizer.js +1 -28
- package/dist/react/components/rtc-widget/components/AudioVisualizer.js.map +1 -1
- package/dist/react/components/rtc-widget/components/MarkdownRenderer.d.ts.map +1 -1
- package/dist/react/components/rtc-widget/components/MarkdownRenderer.js +44 -39
- package/dist/react/components/rtc-widget/components/MarkdownRenderer.js.map +1 -1
- package/dist/react/components/rtc-widget/components/conviComponents/VoiceModeOverlay.d.ts.map +1 -1
- package/dist/react/components/rtc-widget/components/conviComponents/VoiceModeOverlay.js +49 -93
- package/dist/react/components/rtc-widget/components/conviComponents/VoiceModeOverlay.js.map +1 -1
- package/dist/react/hooks/useConvaiClient.d.ts.map +1 -1
- package/dist/react/hooks/useConvaiClient.js +2 -17
- package/dist/react/hooks/useConvaiClient.js.map +1 -1
- package/dist/react/index.d.ts +1 -1
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react/index.js +1 -1
- package/dist/react/index.js.map +1 -1
- package/dist/vanilla/AudioRenderer.d.ts +1 -3
- package/dist/vanilla/AudioRenderer.d.ts.map +1 -1
- package/dist/vanilla/AudioRenderer.js +2 -8
- package/dist/vanilla/AudioRenderer.js.map +1 -1
- package/dist/vanilla/ConvaiWidget.d.ts.map +1 -1
- package/dist/vanilla/ConvaiWidget.js +300 -994
- package/dist/vanilla/ConvaiWidget.js.map +1 -1
- package/dist/vanilla/WidgetEventSubscriptions.d.ts +1 -1
- package/dist/vanilla/WidgetEventSubscriptions.d.ts.map +1 -1
- package/dist/vanilla/WidgetEventSubscriptions.js +0 -5
- package/dist/vanilla/WidgetEventSubscriptions.js.map +1 -1
- package/dist/vanilla/icons.d.ts.map +1 -1
- package/dist/vanilla/icons.js +15 -62
- package/dist/vanilla/icons.js.map +1 -1
- package/dist/vanilla/index.d.ts +2 -4
- package/dist/vanilla/index.d.ts.map +1 -1
- package/dist/vanilla/index.js +1 -3
- package/dist/vanilla/index.js.map +1 -1
- package/dist/vanilla/styles.d.ts +1 -18
- package/dist/vanilla/styles.d.ts.map +1 -1
- package/dist/vanilla/styles.js +29 -129
- package/dist/vanilla/styles.js.map +1 -1
- package/dist/vanilla/types.d.ts +0 -74
- package/dist/vanilla/types.d.ts.map +1 -1
- package/dist/vanilla/types.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/package.json +8 -13
- package/dist/core/CharacterRoster.d.ts +0 -84
- package/dist/core/CharacterRoster.d.ts.map +0 -1
- package/dist/core/CharacterRoster.js +0 -348
- package/dist/core/CharacterRoster.js.map +0 -1
- package/dist/core/CharacterVersionManager.d.ts +0 -100
- package/dist/core/CharacterVersionManager.d.ts.map +0 -1
- package/dist/core/CharacterVersionManager.js +0 -227
- package/dist/core/CharacterVersionManager.js.map +0 -1
- package/dist/core/ConvaiRoomError.d.ts +0 -48
- package/dist/core/ConvaiRoomError.d.ts.map +0 -1
- package/dist/core/ConvaiRoomError.js +0 -111
- package/dist/core/ConvaiRoomError.js.map +0 -1
- package/dist/core/SSESession.d.ts +0 -59
- package/dist/core/SSESession.d.ts.map +0 -1
- package/dist/core/SSESession.js +0 -289
- package/dist/core/SSESession.js.map +0 -1
- package/dist/core/characterReference.d.ts +0 -40
- package/dist/core/characterReference.d.ts.map +0 -1
- package/dist/core/characterReference.js +0 -72
- package/dist/core/characterReference.js.map +0 -1
- package/dist/core/rosterRequest.d.ts +0 -57
- package/dist/core/rosterRequest.d.ts.map +0 -1
- package/dist/core/rosterRequest.js +0 -210
- package/dist/core/rosterRequest.js.map +0 -1
- package/dist/utils/inlineMarkdown.d.ts +0 -38
- package/dist/utils/inlineMarkdown.d.ts.map +0 -1
- package/dist/utils/inlineMarkdown.js +0 -106
- package/dist/utils/inlineMarkdown.js.map +0 -1
package/dist/core/SSESession.js
DELETED
|
@@ -1,289 +0,0 @@
|
|
|
1
|
-
import { buildActionConnectConfig, buildEmotionConnectConfig, serializeProtocolCapabilities, } from "./connectRequest.js";
|
|
2
|
-
/** Text-only interaction transport. One POST/SSE stream is used per message. */
|
|
3
|
-
export class SSESession {
|
|
4
|
-
constructor(options) {
|
|
5
|
-
this.options = options;
|
|
6
|
-
this.connected = false;
|
|
7
|
-
this.abortController = null;
|
|
8
|
-
this.queue = Promise.resolve();
|
|
9
|
-
this.pendingBotLlmText = "";
|
|
10
|
-
this.botLlmTextFlushTimer = null;
|
|
11
|
-
this.pendingMessages = [];
|
|
12
|
-
}
|
|
13
|
-
get isConnected() {
|
|
14
|
-
return this.connected;
|
|
15
|
-
}
|
|
16
|
-
connect() {
|
|
17
|
-
this.connected = true;
|
|
18
|
-
}
|
|
19
|
-
sendMessage(type, data, id) {
|
|
20
|
-
this.sendMessages([{ type, data, ...(id !== undefined ? { id } : {}) }]);
|
|
21
|
-
}
|
|
22
|
-
sendMessages(messages) {
|
|
23
|
-
if (messages.length === 0)
|
|
24
|
-
return;
|
|
25
|
-
this.queue = this.queue
|
|
26
|
-
.then(() => {
|
|
27
|
-
if (!this.connected)
|
|
28
|
-
return;
|
|
29
|
-
const pending = this.pendingMessages;
|
|
30
|
-
this.pendingMessages = [];
|
|
31
|
-
const context = messages.filter((message) => message.type === "update-dynamic-info");
|
|
32
|
-
const rest = messages.filter((message) => message.type !== "update-dynamic-info");
|
|
33
|
-
return this.sendInteraction([...context, ...pending, ...rest], this.options.takeStateOfMind());
|
|
34
|
-
})
|
|
35
|
-
.catch((error) => {
|
|
36
|
-
if (!isAbortError(error))
|
|
37
|
-
this.options.onError(error);
|
|
38
|
-
});
|
|
39
|
-
}
|
|
40
|
-
/** Update request-scoped dynamic context without opening a control-only request. */
|
|
41
|
-
updateDynamicInfo(dynamicInfo) {
|
|
42
|
-
this.options.dynamicInfo = dynamicInfo;
|
|
43
|
-
}
|
|
44
|
-
getDynamicInfo() {
|
|
45
|
-
return this.options.dynamicInfo;
|
|
46
|
-
}
|
|
47
|
-
/** Carry a silent control update into the next stateless interaction request. */
|
|
48
|
-
queueMessage(type, data) {
|
|
49
|
-
this.pendingMessages.push({ type, data });
|
|
50
|
-
}
|
|
51
|
-
async disconnect() {
|
|
52
|
-
this.connected = false;
|
|
53
|
-
this.abortController?.abort();
|
|
54
|
-
await this.queue;
|
|
55
|
-
this.clearPendingBotLlmText();
|
|
56
|
-
this.abortController = null;
|
|
57
|
-
this.pendingMessages = [];
|
|
58
|
-
}
|
|
59
|
-
async sendInteraction(messages, stateOfMind) {
|
|
60
|
-
const controller = new AbortController();
|
|
61
|
-
this.abortController = controller;
|
|
62
|
-
try {
|
|
63
|
-
const characterSessionId = this.options.getCharacterSessionId();
|
|
64
|
-
const response = await fetch(this.options.interactionApiUrl, {
|
|
65
|
-
method: "POST",
|
|
66
|
-
headers: {
|
|
67
|
-
Authorization: `Bearer ${this.options.authorization}`,
|
|
68
|
-
Accept: "text/event-stream",
|
|
69
|
-
"Content-Type": "application/json",
|
|
70
|
-
},
|
|
71
|
-
body: JSON.stringify({
|
|
72
|
-
character_id: this.options.characterId,
|
|
73
|
-
...(stateOfMind ? { state_of_mind: stateOfMind } : {}),
|
|
74
|
-
...(characterSessionId && characterSessionId !== "-1"
|
|
75
|
-
? { character_session_id: characterSessionId }
|
|
76
|
-
: {}),
|
|
77
|
-
...(this.options.endUserId
|
|
78
|
-
? { end_user_id: this.options.endUserId }
|
|
79
|
-
: {}),
|
|
80
|
-
...(this.options.endUserMetadata
|
|
81
|
-
? { end_user_metadata: this.options.endUserMetadata }
|
|
82
|
-
: {}),
|
|
83
|
-
...(buildEmotionConnectConfig(this.options) && {
|
|
84
|
-
emotion_config: buildEmotionConnectConfig(this.options),
|
|
85
|
-
}),
|
|
86
|
-
...(buildActionConnectConfig(this.options) && {
|
|
87
|
-
action_config: buildActionConnectConfig(this.options),
|
|
88
|
-
}),
|
|
89
|
-
...(this.options.capabilities && {
|
|
90
|
-
capabilities: serializeProtocolCapabilities(this.options.capabilities),
|
|
91
|
-
}),
|
|
92
|
-
...(this.options.dynamicInfo && {
|
|
93
|
-
dynamic_info: {
|
|
94
|
-
text: this.options.dynamicInfo,
|
|
95
|
-
...(this.options.keepInContext !== undefined && {
|
|
96
|
-
keep_in_context: this.options.keepInContext,
|
|
97
|
-
}),
|
|
98
|
-
},
|
|
99
|
-
}),
|
|
100
|
-
...(this.options.narrativeTemplateKeys &&
|
|
101
|
-
Object.keys(this.options.narrativeTemplateKeys).length > 0 && {
|
|
102
|
-
narrative_template_keys: this.options.narrativeTemplateKeys,
|
|
103
|
-
}),
|
|
104
|
-
...(this.options.sceneDescription && {
|
|
105
|
-
scene_description: this.options.sceneDescription,
|
|
106
|
-
}),
|
|
107
|
-
...(this.options.respondModes && {
|
|
108
|
-
respond_modes: serializeRespondModes(this.options.respondModes),
|
|
109
|
-
}),
|
|
110
|
-
...(this.options.debug !== undefined
|
|
111
|
-
? { debug: this.options.debug }
|
|
112
|
-
: {}),
|
|
113
|
-
...(this.options.useResponseLifecycleContract !== undefined
|
|
114
|
-
? {
|
|
115
|
-
use_response_lifecycle_contract: this.options.useResponseLifecycleContract,
|
|
116
|
-
}
|
|
117
|
-
: {}),
|
|
118
|
-
...(this.options.invocationMetadata && {
|
|
119
|
-
invocation_metadata: {
|
|
120
|
-
source: this.options.invocationMetadata.source ?? "web_sdk",
|
|
121
|
-
...(this.options.invocationMetadata.clientVersion && {
|
|
122
|
-
client_version: this.options.invocationMetadata.clientVersion,
|
|
123
|
-
}),
|
|
124
|
-
...(this.options.invocationMetadata.extraMetadata && {
|
|
125
|
-
extra_metadata: this.options.invocationMetadata.extraMetadata,
|
|
126
|
-
}),
|
|
127
|
-
},
|
|
128
|
-
}),
|
|
129
|
-
messages: messages.map(({ type, data, id }) => ({
|
|
130
|
-
label: "rtvi-ai",
|
|
131
|
-
type,
|
|
132
|
-
...(id !== undefined ? { id } : {}),
|
|
133
|
-
data,
|
|
134
|
-
})),
|
|
135
|
-
}),
|
|
136
|
-
signal: controller.signal,
|
|
137
|
-
});
|
|
138
|
-
if (!response.ok) {
|
|
139
|
-
const text = await response.text();
|
|
140
|
-
throw new Error(`Interaction API HTTP ${response.status}${text ? `: ${text}` : ""}`);
|
|
141
|
-
}
|
|
142
|
-
if (!response.body)
|
|
143
|
-
throw new Error("Interaction API returned no SSE body");
|
|
144
|
-
await this.readEvents(response.body, controller.signal);
|
|
145
|
-
}
|
|
146
|
-
finally {
|
|
147
|
-
if (this.abortController === controller)
|
|
148
|
-
this.abortController = null;
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
async readEvents(body, signal) {
|
|
152
|
-
const reader = body.getReader();
|
|
153
|
-
try {
|
|
154
|
-
await this.consumeReader(reader, signal);
|
|
155
|
-
}
|
|
156
|
-
finally {
|
|
157
|
-
// A spec-compliant fetch errors the body when its signal aborts, and the
|
|
158
|
-
// read loop exits on that rejection. Not every runtime the SDK now
|
|
159
|
-
// targets (Node, SSR shims, polyfills) does, and with no cancel the
|
|
160
|
-
// loop would await a read that never settles -- so disconnect() would
|
|
161
|
-
// hang forever. Cancelling is idempotent on an already-closed stream.
|
|
162
|
-
await reader.cancel().catch(() => { });
|
|
163
|
-
reader.releaseLock();
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
async consumeReader(reader, signal) {
|
|
167
|
-
const decoder = new TextDecoder();
|
|
168
|
-
let buffer = "";
|
|
169
|
-
let eventType = "message";
|
|
170
|
-
let eventData = [];
|
|
171
|
-
const dispatch = () => {
|
|
172
|
-
if (eventData.length === 0) {
|
|
173
|
-
// Per the SSE spec a frame with no data is not dispatched, but its
|
|
174
|
-
// event-type buffer is still reset. Leaving it set would hand the type
|
|
175
|
-
// to the next frame that omits its own `event:` line -- so a bare
|
|
176
|
-
// `event: done` marker would retype the frame after it as `done`, and
|
|
177
|
-
// that frame would be swallowed as a session-id lookup.
|
|
178
|
-
eventType = "message";
|
|
179
|
-
return;
|
|
180
|
-
}
|
|
181
|
-
const dataText = eventData.join("\n");
|
|
182
|
-
let data = dataText;
|
|
183
|
-
try {
|
|
184
|
-
data = JSON.parse(dataText);
|
|
185
|
-
}
|
|
186
|
-
catch {
|
|
187
|
-
// SSE data is JSON for the interaction API; preserve malformed data for diagnostics.
|
|
188
|
-
}
|
|
189
|
-
if (eventType === "bot-llm-text" &&
|
|
190
|
-
typeof data === "object" &&
|
|
191
|
-
data !== null &&
|
|
192
|
-
typeof data.text === "string") {
|
|
193
|
-
this.queueBotLlmText(data.text);
|
|
194
|
-
eventType = "message";
|
|
195
|
-
eventData = [];
|
|
196
|
-
return;
|
|
197
|
-
}
|
|
198
|
-
this.flushBotLlmText();
|
|
199
|
-
if (eventType === "session" || eventType === "done") {
|
|
200
|
-
const sessionId = data
|
|
201
|
-
?.character_session_id;
|
|
202
|
-
if (typeof sessionId === "string")
|
|
203
|
-
this.options.onCharacterSessionId(sessionId);
|
|
204
|
-
}
|
|
205
|
-
else {
|
|
206
|
-
if (eventType === "error")
|
|
207
|
-
this.options.onError(data);
|
|
208
|
-
this.options.onMessage(new TextEncoder().encode(JSON.stringify({ type: eventType, data })));
|
|
209
|
-
}
|
|
210
|
-
eventType = "message";
|
|
211
|
-
eventData = [];
|
|
212
|
-
};
|
|
213
|
-
while (!signal.aborted) {
|
|
214
|
-
const { done, value } = await reader.read();
|
|
215
|
-
buffer += decoder.decode(value, { stream: !done });
|
|
216
|
-
const lines = buffer.split(/\r?\n/);
|
|
217
|
-
buffer = lines.pop() ?? "";
|
|
218
|
-
for (const line of lines) {
|
|
219
|
-
if (!line)
|
|
220
|
-
dispatch();
|
|
221
|
-
else if (line.startsWith("event:"))
|
|
222
|
-
eventType = line.slice(6).trim();
|
|
223
|
-
else if (line.startsWith("data:")) {
|
|
224
|
-
eventData.push(line.slice(5).trimStart());
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
if (done) {
|
|
228
|
-
if (buffer) {
|
|
229
|
-
if (buffer.startsWith("event:"))
|
|
230
|
-
eventType = buffer.slice(6).trim();
|
|
231
|
-
else if (buffer.startsWith("data:"))
|
|
232
|
-
eventData.push(buffer.slice(5).trimStart());
|
|
233
|
-
}
|
|
234
|
-
dispatch();
|
|
235
|
-
this.flushBotLlmText();
|
|
236
|
-
return;
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
queueBotLlmText(text) {
|
|
241
|
-
this.pendingBotLlmText += text;
|
|
242
|
-
if (this.botLlmTextFlushTimer !== null)
|
|
243
|
-
return;
|
|
244
|
-
this.botLlmTextFlushTimer = setTimeout(() => {
|
|
245
|
-
this.botLlmTextFlushTimer = null;
|
|
246
|
-
this.flushBotLlmText();
|
|
247
|
-
}, SSESession.BOT_LLM_TEXT_FLUSH_MS);
|
|
248
|
-
}
|
|
249
|
-
flushBotLlmText() {
|
|
250
|
-
if (this.botLlmTextFlushTimer !== null) {
|
|
251
|
-
clearTimeout(this.botLlmTextFlushTimer);
|
|
252
|
-
this.botLlmTextFlushTimer = null;
|
|
253
|
-
}
|
|
254
|
-
if (!this.pendingBotLlmText)
|
|
255
|
-
return;
|
|
256
|
-
const text = this.pendingBotLlmText;
|
|
257
|
-
this.pendingBotLlmText = "";
|
|
258
|
-
this.options.onMessage(new TextEncoder().encode(JSON.stringify({ type: "bot-llm-text", data: { text } })));
|
|
259
|
-
}
|
|
260
|
-
clearPendingBotLlmText() {
|
|
261
|
-
if (this.botLlmTextFlushTimer !== null) {
|
|
262
|
-
clearTimeout(this.botLlmTextFlushTimer);
|
|
263
|
-
this.botLlmTextFlushTimer = null;
|
|
264
|
-
}
|
|
265
|
-
this.pendingBotLlmText = "";
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
SSESession.BOT_LLM_TEXT_FLUSH_MS = 16;
|
|
269
|
-
function serializeRespondModes(config) {
|
|
270
|
-
return {
|
|
271
|
-
...(config.text !== undefined && { text: config.text }),
|
|
272
|
-
...(config.audio !== undefined && { audio: config.audio }),
|
|
273
|
-
...(config.vision !== undefined && { vision: config.vision }),
|
|
274
|
-
...(config.contextUpdate !== undefined && {
|
|
275
|
-
context_update: config.contextUpdate,
|
|
276
|
-
}),
|
|
277
|
-
...(config.trigger !== undefined && { trigger: config.trigger }),
|
|
278
|
-
...(config.sceneMetadata !== undefined && {
|
|
279
|
-
scene_metadata: config.sceneMetadata,
|
|
280
|
-
}),
|
|
281
|
-
};
|
|
282
|
-
}
|
|
283
|
-
function isAbortError(error) {
|
|
284
|
-
return (typeof error === "object" &&
|
|
285
|
-
error !== null &&
|
|
286
|
-
"name" in error &&
|
|
287
|
-
error.name === "AbortError");
|
|
288
|
-
}
|
|
289
|
-
//# sourceMappingURL=SSESession.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"SSESession.js","sourceRoot":"","sources":["../../src/core/SSESession.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ConvaiConfig } from \"./types\";\nimport {\n buildActionConnectConfig,\n buildEmotionConnectConfig,\n serializeProtocolCapabilities,\n} from \"./connectRequest\";\n\nexport interface SSESessionOptions {\n interactionApiUrl: string;\n authorization: string;\n characterId: string;\n getCharacterSessionId: () => string | null;\n onCharacterSessionId: (characterSessionId: string) => void;\n endUserId?: string;\n endUserMetadata?: Record<string, unknown>;\n takeStateOfMind: () => string | null;\n enableEmotion?: ConvaiConfig[\"enableEmotion\"];\n emotionConfig?: ConvaiConfig[\"emotionConfig\"];\n actionConfig?: ConvaiConfig[\"actionConfig\"];\n capabilities?: ConvaiConfig[\"capabilities\"];\n dynamicInfo?: ConvaiConfig[\"dynamicInfo\"];\n keepInContext?: ConvaiConfig[\"keepInContext\"];\n narrativeTemplateKeys?: ConvaiConfig[\"narrativeTemplateKeys\"];\n sceneDescription?: ConvaiConfig[\"sceneDescription\"];\n respondModes?: ConvaiConfig[\"respondModes\"];\n debug?: boolean;\n useResponseLifecycleContract?: boolean;\n invocationMetadata?: ConvaiConfig[\"invocationMetadata\"];\n onMessage: (payload: Uint8Array) => void;\n onError: (error: unknown) => void;\n}\n\nexport interface SSEMessage {\n type: string;\n data: unknown;\n id?: string;\n}\n\n/** Text-only interaction transport. One POST/SSE stream is used per message. */\nexport class SSESession {\n private static readonly BOT_LLM_TEXT_FLUSH_MS = 16;\n private connected = false;\n private abortController: AbortController | null = null;\n private queue: Promise<void> = Promise.resolve();\n private pendingBotLlmText = \"\";\n private botLlmTextFlushTimer: ReturnType<typeof setTimeout> | null = null;\n private pendingMessages: SSEMessage[] = [];\n\n constructor(private readonly options: SSESessionOptions) {}\n\n get isConnected(): boolean {\n return this.connected;\n }\n\n connect(): void {\n this.connected = true;\n }\n\n sendMessage(type: string, data: unknown, id?: string): void {\n this.sendMessages([{ type, data, ...(id !== undefined ? { id } : {}) }]);\n }\n\n sendMessages(messages: SSEMessage[]): void {\n if (messages.length === 0) return;\n this.queue = this.queue\n .then(() => {\n if (!this.connected) return;\n const pending = this.pendingMessages;\n this.pendingMessages = [];\n const context = messages.filter((message) => message.type === \"update-dynamic-info\");\n const rest = messages.filter((message) => message.type !== \"update-dynamic-info\");\n return this.sendInteraction(\n [...context, ...pending, ...rest],\n this.options.takeStateOfMind(),\n );\n })\n .catch((error: unknown) => {\n if (!isAbortError(error)) this.options.onError(error);\n });\n }\n\n /** Update request-scoped dynamic context without opening a control-only request. */\n updateDynamicInfo(dynamicInfo: string): void {\n this.options.dynamicInfo = dynamicInfo;\n }\n\n getDynamicInfo(): string | undefined {\n return this.options.dynamicInfo;\n }\n\n /** Carry a silent control update into the next stateless interaction request. */\n queueMessage(type: string, data: unknown): void {\n this.pendingMessages.push({ type, data });\n }\n\n async disconnect(): Promise<void> {\n this.connected = false;\n this.abortController?.abort();\n await this.queue;\n this.clearPendingBotLlmText();\n this.abortController = null;\n this.pendingMessages = [];\n }\n\n private async sendInteraction(\n messages: SSEMessage[],\n stateOfMind: string | null,\n ): Promise<void> {\n const controller = new AbortController();\n this.abortController = controller;\n try {\n const characterSessionId = this.options.getCharacterSessionId();\n const response = await fetch(this.options.interactionApiUrl, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${this.options.authorization}`,\n Accept: \"text/event-stream\",\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n character_id: this.options.characterId,\n ...(stateOfMind ? { state_of_mind: stateOfMind } : {}),\n ...(characterSessionId && characterSessionId !== \"-1\"\n ? { character_session_id: characterSessionId }\n : {}),\n ...(this.options.endUserId\n ? { end_user_id: this.options.endUserId }\n : {}),\n ...(this.options.endUserMetadata\n ? { end_user_metadata: this.options.endUserMetadata }\n : {}),\n ...(buildEmotionConnectConfig(this.options) && {\n emotion_config: buildEmotionConnectConfig(this.options),\n }),\n ...(buildActionConnectConfig(this.options) && {\n action_config: buildActionConnectConfig(this.options),\n }),\n ...(this.options.capabilities && {\n capabilities: serializeProtocolCapabilities(this.options.capabilities),\n }),\n ...(this.options.dynamicInfo && {\n dynamic_info: {\n text: this.options.dynamicInfo,\n ...(this.options.keepInContext !== undefined && {\n keep_in_context: this.options.keepInContext,\n }),\n },\n }),\n ...(this.options.narrativeTemplateKeys &&\n Object.keys(this.options.narrativeTemplateKeys).length > 0 && {\n narrative_template_keys: this.options.narrativeTemplateKeys,\n }),\n ...(this.options.sceneDescription && {\n scene_description: this.options.sceneDescription,\n }),\n ...(this.options.respondModes && {\n respond_modes: serializeRespondModes(this.options.respondModes),\n }),\n ...(this.options.debug !== undefined\n ? { debug: this.options.debug }\n : {}),\n ...(this.options.useResponseLifecycleContract !== undefined\n ? {\n use_response_lifecycle_contract:\n this.options.useResponseLifecycleContract,\n }\n : {}),\n ...(this.options.invocationMetadata && {\n invocation_metadata: {\n source: this.options.invocationMetadata.source ?? \"web_sdk\",\n ...(this.options.invocationMetadata.clientVersion && {\n client_version: this.options.invocationMetadata.clientVersion,\n }),\n ...(this.options.invocationMetadata.extraMetadata && {\n extra_metadata: this.options.invocationMetadata.extraMetadata,\n }),\n },\n }),\n messages: messages.map(({ type, data, id }) => ({\n label: \"rtvi-ai\",\n type,\n ...(id !== undefined ? { id } : {}),\n data,\n })),\n }),\n signal: controller.signal,\n });\n\n if (!response.ok) {\n const text = await response.text();\n throw new Error(\n `Interaction API HTTP ${response.status}${text ? `: ${text}` : \"\"}`,\n );\n }\n if (!response.body) throw new Error(\"Interaction API returned no SSE body\");\n\n await this.readEvents(response.body, controller.signal);\n } finally {\n if (this.abortController === controller) this.abortController = null;\n }\n }\n\n private async readEvents(\n body: ReadableStream<Uint8Array>,\n signal: AbortSignal,\n ): Promise<void> {\n const reader = body.getReader();\n try {\n await this.consumeReader(reader, signal);\n } finally {\n // A spec-compliant fetch errors the body when its signal aborts, and the\n // read loop exits on that rejection. Not every runtime the SDK now\n // targets (Node, SSR shims, polyfills) does, and with no cancel the\n // loop would await a read that never settles -- so disconnect() would\n // hang forever. Cancelling is idempotent on an already-closed stream.\n await reader.cancel().catch(() => {});\n reader.releaseLock();\n }\n }\n\n private async consumeReader(\n reader: ReadableStreamDefaultReader<Uint8Array>,\n signal: AbortSignal,\n ): Promise<void> {\n const decoder = new TextDecoder();\n let buffer = \"\";\n let eventType = \"message\";\n let eventData: string[] = [];\n\n const dispatch = () => {\n if (eventData.length === 0) {\n // Per the SSE spec a frame with no data is not dispatched, but its\n // event-type buffer is still reset. Leaving it set would hand the type\n // to the next frame that omits its own `event:` line -- so a bare\n // `event: done` marker would retype the frame after it as `done`, and\n // that frame would be swallowed as a session-id lookup.\n eventType = \"message\";\n return;\n }\n const dataText = eventData.join(\"\\n\");\n let data: unknown = dataText;\n try {\n data = JSON.parse(dataText);\n } catch {\n // SSE data is JSON for the interaction API; preserve malformed data for diagnostics.\n }\n if (\n eventType === \"bot-llm-text\" &&\n typeof data === \"object\" &&\n data !== null &&\n typeof (data as { text?: unknown }).text === \"string\"\n ) {\n this.queueBotLlmText((data as { text: string }).text);\n eventType = \"message\";\n eventData = [];\n return;\n }\n this.flushBotLlmText();\n if (eventType === \"session\" || eventType === \"done\") {\n const sessionId = (data as { character_session_id?: unknown })\n ?.character_session_id;\n if (typeof sessionId === \"string\") this.options.onCharacterSessionId(sessionId);\n } else {\n if (eventType === \"error\") this.options.onError(data);\n this.options.onMessage(\n new TextEncoder().encode(JSON.stringify({ type: eventType, data })),\n );\n }\n eventType = \"message\";\n eventData = [];\n };\n\n while (!signal.aborted) {\n const { done, value } = await reader.read();\n buffer += decoder.decode(value, { stream: !done });\n const lines = buffer.split(/\\r?\\n/);\n buffer = lines.pop() ?? \"\";\n for (const line of lines) {\n if (!line) dispatch();\n else if (line.startsWith(\"event:\")) eventType = line.slice(6).trim();\n else if (line.startsWith(\"data:\")) {\n eventData.push(line.slice(5).trimStart());\n }\n }\n if (done) {\n if (buffer) {\n if (buffer.startsWith(\"event:\")) eventType = buffer.slice(6).trim();\n else if (buffer.startsWith(\"data:\")) eventData.push(buffer.slice(5).trimStart());\n }\n dispatch();\n this.flushBotLlmText();\n return;\n }\n }\n }\n\n private queueBotLlmText(text: string): void {\n this.pendingBotLlmText += text;\n if (this.botLlmTextFlushTimer !== null) return;\n this.botLlmTextFlushTimer = setTimeout(() => {\n this.botLlmTextFlushTimer = null;\n this.flushBotLlmText();\n }, SSESession.BOT_LLM_TEXT_FLUSH_MS);\n }\n\n private flushBotLlmText(): void {\n if (this.botLlmTextFlushTimer !== null) {\n clearTimeout(this.botLlmTextFlushTimer);\n this.botLlmTextFlushTimer = null;\n }\n if (!this.pendingBotLlmText) return;\n const text = this.pendingBotLlmText;\n this.pendingBotLlmText = \"\";\n this.options.onMessage(\n new TextEncoder().encode(\n JSON.stringify({ type: \"bot-llm-text\", data: { text } }),\n ),\n );\n }\n\n private clearPendingBotLlmText(): void {\n if (this.botLlmTextFlushTimer !== null) {\n clearTimeout(this.botLlmTextFlushTimer);\n this.botLlmTextFlushTimer = null;\n }\n this.pendingBotLlmText = \"\";\n }\n}\n\nfunction serializeRespondModes(\n config: NonNullable<ConvaiConfig[\"respondModes\"]>,\n): Record<string, unknown> {\n return {\n ...(config.text !== undefined && { text: config.text }),\n ...(config.audio !== undefined && { audio: config.audio }),\n ...(config.vision !== undefined && { vision: config.vision }),\n ...(config.contextUpdate !== undefined && {\n context_update: config.contextUpdate,\n }),\n ...(config.trigger !== undefined && { trigger: config.trigger }),\n ...(config.sceneMetadata !== undefined && {\n scene_metadata: config.sceneMetadata,\n }),\n };\n}\n\nfunction isAbortError(error: unknown): boolean {\n return (\n typeof error === \"object\" &&\n error !== null &&\n \"name\" in error &&\n error.name === \"AbortError\"\n );\n}\n"]}
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Character references.
|
|
3
|
-
*
|
|
4
|
-
* The runtime accepts a bare character UUID or a UUID followed by a version
|
|
5
|
-
* selector: `<uuid>-draft`, `<uuid>-latest`, or `<uuid>-1.2[.3]`. The SDK
|
|
6
|
-
* keeps the two halves apart — the bare UUID still names the character for
|
|
7
|
-
* memory, character info and analytics, while the joined reference is what
|
|
8
|
-
* goes on the wire to `/connect` and the interaction API.
|
|
9
|
-
*/
|
|
10
|
-
/** A version selector: the editable draft, the promoted latest, or an immutable tag. */
|
|
11
|
-
export type CharacterVersionSelector = "draft" | "latest" | (string & {});
|
|
12
|
-
export interface CharacterReference {
|
|
13
|
-
/** The bare character UUID, lower-cased. */
|
|
14
|
-
characterId: string;
|
|
15
|
-
/** The selector, or null for a bare reference. */
|
|
16
|
-
version: CharacterVersionSelector | null;
|
|
17
|
-
/** What goes on the wire: the UUID, or `<uuid>-<selector>`. */
|
|
18
|
-
reference: string;
|
|
19
|
-
}
|
|
20
|
-
/** True when `value` is `draft`, `latest`, or a `major.minor[.patch]` tag. */
|
|
21
|
-
export declare function isCharacterVersionSelector(value: unknown): value is CharacterVersionSelector;
|
|
22
|
-
/**
|
|
23
|
-
* Split a character id that may already carry a selector suffix. Returns null
|
|
24
|
-
* when the value is neither a UUID nor a versioned reference — callers that
|
|
25
|
-
* accept opaque ids (legacy non-UUID characters) fall back to the raw string.
|
|
26
|
-
*/
|
|
27
|
-
export declare function parseCharacterReference(value: string): CharacterReference | null;
|
|
28
|
-
/**
|
|
29
|
-
* Combine a `characterId` and an optional `characterVersion` config field into
|
|
30
|
-
* the reference sent to the runtime.
|
|
31
|
-
*
|
|
32
|
-
* - `characterId` may be a bare UUID or already carry a selector.
|
|
33
|
-
* - `characterVersion` must be a valid selector when provided.
|
|
34
|
-
* - Supplying both is allowed only when they agree.
|
|
35
|
-
* - A non-UUID `characterId` cannot be versioned.
|
|
36
|
-
*/
|
|
37
|
-
export declare function resolveCharacterReference(characterId: string, characterVersion?: CharacterVersionSelector | null): CharacterReference;
|
|
38
|
-
/** True when `value` is a bare character UUID. */
|
|
39
|
-
export declare function isCharacterUuid(value: string): boolean;
|
|
40
|
-
//# sourceMappingURL=characterReference.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"characterReference.d.ts","sourceRoot":"","sources":["../../src/core/characterReference.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,wFAAwF;AACxF,MAAM,MAAM,wBAAwB,GAAG,OAAO,GAAG,QAAQ,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;AAY1E,MAAM,WAAW,kBAAkB;IACjC,4CAA4C;IAC5C,WAAW,EAAE,MAAM,CAAC;IACpB,kDAAkD;IAClD,OAAO,EAAE,wBAAwB,GAAG,IAAI,CAAC;IACzC,+DAA+D;IAC/D,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,8EAA8E;AAC9E,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,wBAAwB,CAE5F;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,kBAAkB,GAAG,IAAI,CAUhF;AAED;;;;;;;;GAQG;AACH,wBAAgB,yBAAyB,CACvC,WAAW,EAAE,MAAM,EACnB,gBAAgB,CAAC,EAAE,wBAAwB,GAAG,IAAI,GACjD,kBAAkB,CA8BpB;AAED,kDAAkD;AAClD,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAEtD"}
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Character references.
|
|
3
|
-
*
|
|
4
|
-
* The runtime accepts a bare character UUID or a UUID followed by a version
|
|
5
|
-
* selector: `<uuid>-draft`, `<uuid>-latest`, or `<uuid>-1.2[.3]`. The SDK
|
|
6
|
-
* keeps the two halves apart — the bare UUID still names the character for
|
|
7
|
-
* memory, character info and analytics, while the joined reference is what
|
|
8
|
-
* goes on the wire to `/connect` and the interaction API.
|
|
9
|
-
*/
|
|
10
|
-
const UUID_PATTERN = "[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}";
|
|
11
|
-
const VERSION_TAG_PATTERN = "(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)(?:\\.(?:0|[1-9]\\d*))?";
|
|
12
|
-
const UUID_RE = new RegExp(`^${UUID_PATTERN}$`);
|
|
13
|
-
const SELECTOR_RE = new RegExp(`^(?:draft|latest|${VERSION_TAG_PATTERN})$`);
|
|
14
|
-
const REFERENCE_RE = new RegExp(`^(${UUID_PATTERN})(?:-(draft|latest|${VERSION_TAG_PATTERN}))?$`);
|
|
15
|
-
/** True when `value` is `draft`, `latest`, or a `major.minor[.patch]` tag. */
|
|
16
|
-
export function isCharacterVersionSelector(value) {
|
|
17
|
-
return typeof value === "string" && SELECTOR_RE.test(value);
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* Split a character id that may already carry a selector suffix. Returns null
|
|
21
|
-
* when the value is neither a UUID nor a versioned reference — callers that
|
|
22
|
-
* accept opaque ids (legacy non-UUID characters) fall back to the raw string.
|
|
23
|
-
*/
|
|
24
|
-
export function parseCharacterReference(value) {
|
|
25
|
-
const match = REFERENCE_RE.exec(value.trim());
|
|
26
|
-
if (!match)
|
|
27
|
-
return null;
|
|
28
|
-
const characterId = match[1].toLowerCase();
|
|
29
|
-
const version = match[2] ?? null;
|
|
30
|
-
return {
|
|
31
|
-
characterId,
|
|
32
|
-
version,
|
|
33
|
-
reference: version ? `${characterId}-${version}` : characterId,
|
|
34
|
-
};
|
|
35
|
-
}
|
|
36
|
-
/**
|
|
37
|
-
* Combine a `characterId` and an optional `characterVersion` config field into
|
|
38
|
-
* the reference sent to the runtime.
|
|
39
|
-
*
|
|
40
|
-
* - `characterId` may be a bare UUID or already carry a selector.
|
|
41
|
-
* - `characterVersion` must be a valid selector when provided.
|
|
42
|
-
* - Supplying both is allowed only when they agree.
|
|
43
|
-
* - A non-UUID `characterId` cannot be versioned.
|
|
44
|
-
*/
|
|
45
|
-
export function resolveCharacterReference(characterId, characterVersion) {
|
|
46
|
-
const parsed = parseCharacterReference(characterId);
|
|
47
|
-
if (characterVersion != null && characterVersion !== "") {
|
|
48
|
-
if (!isCharacterVersionSelector(characterVersion)) {
|
|
49
|
-
throw new Error(`characterVersion must be "draft", "latest", or a major.minor[.patch] tag; received ${JSON.stringify(characterVersion)}`);
|
|
50
|
-
}
|
|
51
|
-
if (!parsed) {
|
|
52
|
-
throw new Error("characterVersion requires characterId to be a character UUID");
|
|
53
|
-
}
|
|
54
|
-
if (parsed.version && parsed.version !== characterVersion) {
|
|
55
|
-
throw new Error(`characterId already selects version "${parsed.version}" but characterVersion is "${characterVersion}"`);
|
|
56
|
-
}
|
|
57
|
-
return {
|
|
58
|
-
characterId: parsed.characterId,
|
|
59
|
-
version: characterVersion,
|
|
60
|
-
reference: `${parsed.characterId}-${characterVersion}`,
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
|
-
if (parsed)
|
|
64
|
-
return parsed;
|
|
65
|
-
// Not a UUID: pass through untouched so legacy ids keep working.
|
|
66
|
-
return { characterId, version: null, reference: characterId };
|
|
67
|
-
}
|
|
68
|
-
/** True when `value` is a bare character UUID. */
|
|
69
|
-
export function isCharacterUuid(value) {
|
|
70
|
-
return UUID_RE.test(value);
|
|
71
|
-
}
|
|
72
|
-
//# sourceMappingURL=characterReference.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"characterReference.js","sourceRoot":"","sources":["../../src/core/characterReference.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,MAAM,YAAY,GAChB,6EAA6E,CAAC;AAChF,MAAM,mBAAmB,GAAG,0DAA0D,CAAC;AAEvF,MAAM,OAAO,GAAG,IAAI,MAAM,CAAC,IAAI,YAAY,GAAG,CAAC,CAAC;AAChD,MAAM,WAAW,GAAG,IAAI,MAAM,CAAC,oBAAoB,mBAAmB,IAAI,CAAC,CAAC;AAC5E,MAAM,YAAY,GAAG,IAAI,MAAM,CAC7B,KAAK,YAAY,sBAAsB,mBAAmB,MAAM,CACjE,CAAC;AAWF,8EAA8E;AAC9E,MAAM,UAAU,0BAA0B,CAAC,KAAc;IACvD,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC9D,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,uBAAuB,CAAC,KAAa;IACnD,MAAM,KAAK,GAAG,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;IAC9C,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IACxB,MAAM,WAAW,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;IAC3C,MAAM,OAAO,GAAI,KAAK,CAAC,CAAC,CAA0C,IAAI,IAAI,CAAC;IAC3E,OAAO;QACL,WAAW;QACX,OAAO;QACP,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,WAAW,IAAI,OAAO,EAAE,CAAC,CAAC,CAAC,WAAW;KAC/D,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,yBAAyB,CACvC,WAAmB,EACnB,gBAAkD;IAElD,MAAM,MAAM,GAAG,uBAAuB,CAAC,WAAW,CAAC,CAAC;IAEpD,IAAI,gBAAgB,IAAI,IAAI,IAAI,gBAAgB,KAAK,EAAE,EAAE,CAAC;QACxD,IAAI,CAAC,0BAA0B,CAAC,gBAAgB,CAAC,EAAE,CAAC;YAClD,MAAM,IAAI,KAAK,CACb,sFAAsF,IAAI,CAAC,SAAS,CAAC,gBAAgB,CAAC,EAAE,CACzH,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CACb,8DAA8D,CAC/D,CAAC;QACJ,CAAC;QACD,IAAI,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,OAAO,KAAK,gBAAgB,EAAE,CAAC;YAC1D,MAAM,IAAI,KAAK,CACb,wCAAwC,MAAM,CAAC,OAAO,8BAA8B,gBAAgB,GAAG,CACxG,CAAC;QACJ,CAAC;QACD,OAAO;YACL,WAAW,EAAE,MAAM,CAAC,WAAW;YAC/B,OAAO,EAAE,gBAAgB;YACzB,SAAS,EAAE,GAAG,MAAM,CAAC,WAAW,IAAI,gBAAgB,EAAE;SACvD,CAAC;IACJ,CAAC;IAED,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC;IAE1B,iEAAiE;IACjE,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,CAAC;AAChE,CAAC;AAED,kDAAkD;AAClD,MAAM,UAAU,eAAe,CAAC,KAAa;IAC3C,OAAO,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC7B,CAAC","sourcesContent":["/**\n * Character references.\n *\n * The runtime accepts a bare character UUID or a UUID followed by a version\n * selector: `<uuid>-draft`, `<uuid>-latest`, or `<uuid>-1.2[.3]`. The SDK\n * keeps the two halves apart — the bare UUID still names the character for\n * memory, character info and analytics, while the joined reference is what\n * goes on the wire to `/connect` and the interaction API.\n */\n\n/** A version selector: the editable draft, the promoted latest, or an immutable tag. */\nexport type CharacterVersionSelector = \"draft\" | \"latest\" | (string & {});\n\nconst UUID_PATTERN =\n \"[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}\";\nconst VERSION_TAG_PATTERN = \"(?:0|[1-9]\\\\d*)\\\\.(?:0|[1-9]\\\\d*)(?:\\\\.(?:0|[1-9]\\\\d*))?\";\n\nconst UUID_RE = new RegExp(`^${UUID_PATTERN}$`);\nconst SELECTOR_RE = new RegExp(`^(?:draft|latest|${VERSION_TAG_PATTERN})$`);\nconst REFERENCE_RE = new RegExp(\n `^(${UUID_PATTERN})(?:-(draft|latest|${VERSION_TAG_PATTERN}))?$`,\n);\n\nexport interface CharacterReference {\n /** The bare character UUID, lower-cased. */\n characterId: string;\n /** The selector, or null for a bare reference. */\n version: CharacterVersionSelector | null;\n /** What goes on the wire: the UUID, or `<uuid>-<selector>`. */\n reference: string;\n}\n\n/** True when `value` is `draft`, `latest`, or a `major.minor[.patch]` tag. */\nexport function isCharacterVersionSelector(value: unknown): value is CharacterVersionSelector {\n return typeof value === \"string\" && SELECTOR_RE.test(value);\n}\n\n/**\n * Split a character id that may already carry a selector suffix. Returns null\n * when the value is neither a UUID nor a versioned reference — callers that\n * accept opaque ids (legacy non-UUID characters) fall back to the raw string.\n */\nexport function parseCharacterReference(value: string): CharacterReference | null {\n const match = REFERENCE_RE.exec(value.trim());\n if (!match) return null;\n const characterId = match[1].toLowerCase();\n const version = (match[2] as CharacterVersionSelector | undefined) ?? null;\n return {\n characterId,\n version,\n reference: version ? `${characterId}-${version}` : characterId,\n };\n}\n\n/**\n * Combine a `characterId` and an optional `characterVersion` config field into\n * the reference sent to the runtime.\n *\n * - `characterId` may be a bare UUID or already carry a selector.\n * - `characterVersion` must be a valid selector when provided.\n * - Supplying both is allowed only when they agree.\n * - A non-UUID `characterId` cannot be versioned.\n */\nexport function resolveCharacterReference(\n characterId: string,\n characterVersion?: CharacterVersionSelector | null,\n): CharacterReference {\n const parsed = parseCharacterReference(characterId);\n\n if (characterVersion != null && characterVersion !== \"\") {\n if (!isCharacterVersionSelector(characterVersion)) {\n throw new Error(\n `characterVersion must be \"draft\", \"latest\", or a major.minor[.patch] tag; received ${JSON.stringify(characterVersion)}`,\n );\n }\n if (!parsed) {\n throw new Error(\n \"characterVersion requires characterId to be a character UUID\",\n );\n }\n if (parsed.version && parsed.version !== characterVersion) {\n throw new Error(\n `characterId already selects version \"${parsed.version}\" but characterVersion is \"${characterVersion}\"`,\n );\n }\n return {\n characterId: parsed.characterId,\n version: characterVersion,\n reference: `${parsed.characterId}-${characterVersion}`,\n };\n }\n\n if (parsed) return parsed;\n\n // Not a UUID: pass through untouched so legacy ids keep working.\n return { characterId, version: null, reference: characterId };\n}\n\n/** True when `value` is a bare character UUID. */\nexport function isCharacterUuid(value: string): boolean {\n return UUID_RE.test(value);\n}\n"]}
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import type { ConvaiConfig, JoinRoomOptions } from "./types.js";
|
|
2
|
-
/**
|
|
3
|
-
* Validation and request-body construction for multi-character rooms.
|
|
4
|
-
*
|
|
5
|
-
* Pure: no transport, no client state. Every rule below runs before a request
|
|
6
|
-
* is built, so an illegal topology costs nothing and reports the rule it broke
|
|
7
|
-
* rather than a 422 from the runtime.
|
|
8
|
-
*/
|
|
9
|
-
/**
|
|
10
|
-
* Server-wide roster cap. Checked client-side only to fail fast with a clear
|
|
11
|
-
* message — the server stays authoritative, and a plan may configure a lower
|
|
12
|
-
* `max_characters` that surfaces as 403 `MULTI_CHARACTER_ROSTER_LIMIT_EXCEEDED`.
|
|
13
|
-
* This is an operational limit, not a protocol maximum, so it must not leak
|
|
14
|
-
* into any public type.
|
|
15
|
-
*/
|
|
16
|
-
export declare const MULTI_CHARACTER_MAX_CHARACTERS = 50;
|
|
17
|
-
/** True when this config asks for a multi-character room. */
|
|
18
|
-
export declare function isRosterConfig(config: Pick<ConvaiConfig, "characters">): boolean;
|
|
19
|
-
/**
|
|
20
|
-
* Validate a roster create config.
|
|
21
|
-
*
|
|
22
|
-
* Throws on the first broken rule. Ordered so the most structural problems
|
|
23
|
-
* (which topology did you mean?) report before the detail ones.
|
|
24
|
-
*/
|
|
25
|
-
export declare function validateRosterConfig(config: ConvaiConfig): void;
|
|
26
|
-
/**
|
|
27
|
-
* Reject a config that negotiates v2 output protocols alongside room options
|
|
28
|
-
* the runtime cannot combine them with.
|
|
29
|
-
*
|
|
30
|
-
* Verified against staging 2026-09-08: `capabilities.actionProtocolVersion: 2`
|
|
31
|
-
* or `modelOutputVersion: 2` is answered with 422
|
|
32
|
-
* `unsupported_action_protocol_topology` / `unsupported_model_output_topology`
|
|
33
|
-
* unless the request uses `mode='create'`, a singular `characterId`, no
|
|
34
|
-
* `sharedSessionKey`, and `maxNumParticipants` of 1. Version 1 carries no such
|
|
35
|
-
* constraint.
|
|
36
|
-
*
|
|
37
|
-
* The published contract mentions only the multi-character half of this. The
|
|
38
|
-
* `sharedSessionKey` and `maxNumParticipants` constraints bite in
|
|
39
|
-
* single-character sessions too, which is why this runs on every connect
|
|
40
|
-
* rather than only the roster path.
|
|
41
|
-
*/
|
|
42
|
-
export declare function validateProtocolTopology(config: ConvaiConfig): void;
|
|
43
|
-
/** Validate join options. */
|
|
44
|
-
export declare function validateJoinOptions(options: JoinRoomOptions): void;
|
|
45
|
-
/**
|
|
46
|
-
* The roster half of a create request. Merged into the existing single-character
|
|
47
|
-
* body by the caller, so every current option (blendshape, TTS/STT, dynamic
|
|
48
|
-
* info, action, scene, VAD, vision) continues to apply to every member.
|
|
49
|
-
*/
|
|
50
|
-
export declare function buildRosterConnectFields(config: ConvaiConfig): Record<string, unknown>;
|
|
51
|
-
/**
|
|
52
|
-
* The complete join request body. A join carries a locator and the human, and
|
|
53
|
-
* nothing else — the roster is loaded from persisted room state, and resending
|
|
54
|
-
* topology is rejected.
|
|
55
|
-
*/
|
|
56
|
-
export declare function buildJoinRequestBody(options: JoinRoomOptions): Record<string, unknown>;
|
|
57
|
-
//# sourceMappingURL=rosterRequest.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"rosterRequest.d.ts","sourceRoot":"","sources":["../../src/core/rosterRequest.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,YAAY,EACZ,eAAe,EAChB,MAAM,SAAS,CAAC;AAGjB;;;;;;GAMG;AAEH;;;;;;GAMG;AACH,eAAO,MAAM,8BAA8B,KAAK,CAAC;AAKjD,6DAA6D;AAC7D,wBAAgB,cAAc,CAC5B,MAAM,EAAE,IAAI,CAAC,YAAY,EAAE,YAAY,CAAC,GACvC,OAAO,CAET;AAeD;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,CA8E/D;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,CA+BnE;AAED,6BAA6B;AAC7B,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,eAAe,GAAG,IAAI,CAuBlE;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,YAAY,GACnB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CA0BzB;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,eAAe,GACvB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAezB"}
|