@convai/web-sdk 1.8.0-beta.5 → 1.8.0-beta.7

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.
Files changed (110) hide show
  1. package/README.md +333 -13
  2. package/dist/core/CharacterRoster.d.ts +84 -0
  3. package/dist/core/CharacterRoster.d.ts.map +1 -0
  4. package/dist/core/CharacterRoster.js +348 -0
  5. package/dist/core/CharacterRoster.js.map +1 -0
  6. package/dist/core/ConvaiClient.d.ts +152 -2
  7. package/dist/core/ConvaiClient.d.ts.map +1 -1
  8. package/dist/core/ConvaiClient.js +1036 -49
  9. package/dist/core/ConvaiClient.js.map +1 -1
  10. package/dist/core/ConvaiRoomError.d.ts +48 -0
  11. package/dist/core/ConvaiRoomError.d.ts.map +1 -0
  12. package/dist/core/ConvaiRoomError.js +111 -0
  13. package/dist/core/ConvaiRoomError.js.map +1 -0
  14. package/dist/core/MessageHandler.d.ts +25 -0
  15. package/dist/core/MessageHandler.d.ts.map +1 -1
  16. package/dist/core/MessageHandler.js +431 -30
  17. package/dist/core/MessageHandler.js.map +1 -1
  18. package/dist/core/SSESession.d.ts +15 -0
  19. package/dist/core/SSESession.d.ts.map +1 -1
  20. package/dist/core/SSESession.js +92 -3
  21. package/dist/core/SSESession.js.map +1 -1
  22. package/dist/core/connectRequest.d.ts +38 -2
  23. package/dist/core/connectRequest.d.ts.map +1 -1
  24. package/dist/core/connectRequest.js +57 -0
  25. package/dist/core/connectRequest.js.map +1 -1
  26. package/dist/core/index.d.ts +6 -1
  27. package/dist/core/index.d.ts.map +1 -1
  28. package/dist/core/index.js +5 -1
  29. package/dist/core/index.js.map +1 -1
  30. package/dist/core/logicalTurn.d.ts +4 -1
  31. package/dist/core/logicalTurn.d.ts.map +1 -1
  32. package/dist/core/logicalTurn.js +35 -4
  33. package/dist/core/logicalTurn.js.map +1 -1
  34. package/dist/core/modelOutput.d.ts +40 -0
  35. package/dist/core/modelOutput.d.ts.map +1 -0
  36. package/dist/core/modelOutput.js +187 -0
  37. package/dist/core/modelOutput.js.map +1 -0
  38. package/dist/core/publishedChat.d.ts +9 -0
  39. package/dist/core/publishedChat.d.ts.map +1 -0
  40. package/dist/core/publishedChat.js +13 -0
  41. package/dist/core/publishedChat.js.map +1 -0
  42. package/dist/core/rosterRequest.d.ts +57 -0
  43. package/dist/core/rosterRequest.d.ts.map +1 -0
  44. package/dist/core/rosterRequest.js +210 -0
  45. package/dist/core/rosterRequest.js.map +1 -0
  46. package/dist/core/types.d.ts +667 -10
  47. package/dist/core/types.d.ts.map +1 -1
  48. package/dist/core/types.js.map +1 -1
  49. package/dist/embed/ConvaiChatElement.d.ts +27 -0
  50. package/dist/embed/ConvaiChatElement.d.ts.map +1 -0
  51. package/dist/embed/ConvaiChatElement.js +300 -0
  52. package/dist/embed/ConvaiChatElement.js.map +1 -0
  53. package/dist/embed/browser.d.ts +3 -0
  54. package/dist/embed/browser.d.ts.map +1 -0
  55. package/dist/embed/browser.js +5 -0
  56. package/dist/embed/browser.js.map +1 -0
  57. package/dist/embed/chat-embed-v1.js +100 -0
  58. package/dist/embed/chat-embed-v1.js.map +7 -0
  59. package/dist/embed/index.d.ts +9 -0
  60. package/dist/embed/index.d.ts.map +1 -0
  61. package/dist/embed/index.js +9 -0
  62. package/dist/embed/index.js.map +1 -0
  63. package/dist/embed/publicationApi.d.ts +23 -0
  64. package/dist/embed/publicationApi.d.ts.map +1 -0
  65. package/dist/embed/publicationApi.js +141 -0
  66. package/dist/embed/publicationApi.js.map +1 -0
  67. package/dist/react/components/ConvaiWidget.d.ts +11 -1
  68. package/dist/react/components/ConvaiWidget.d.ts.map +1 -1
  69. package/dist/react/components/ConvaiWidget.js +67 -11
  70. package/dist/react/components/ConvaiWidget.js.map +1 -1
  71. package/dist/react/components/rtc-widget/components/MarkdownRenderer.d.ts.map +1 -1
  72. package/dist/react/components/rtc-widget/components/MarkdownRenderer.js +39 -44
  73. package/dist/react/components/rtc-widget/components/MarkdownRenderer.js.map +1 -1
  74. package/dist/react/components/rtc-widget/components/conviComponents/SettingsTray.d.ts +1 -1
  75. package/dist/react/components/rtc-widget/components/conviComponents/SettingsTray.d.ts.map +1 -1
  76. package/dist/react/components/rtc-widget/components/conviComponents/SettingsTray.js +2 -2
  77. package/dist/react/components/rtc-widget/components/conviComponents/SettingsTray.js.map +1 -1
  78. package/dist/react/hooks/useConvaiClient.d.ts +2 -0
  79. package/dist/react/hooks/useConvaiClient.d.ts.map +1 -1
  80. package/dist/react/hooks/useConvaiClient.js +16 -0
  81. package/dist/react/hooks/useConvaiClient.js.map +1 -1
  82. package/dist/react/index.d.ts +1 -1
  83. package/dist/react/index.d.ts.map +1 -1
  84. package/dist/react/index.js +1 -1
  85. package/dist/react/index.js.map +1 -1
  86. package/dist/utils/inlineMarkdown.d.ts +38 -0
  87. package/dist/utils/inlineMarkdown.d.ts.map +1 -0
  88. package/dist/utils/inlineMarkdown.js +106 -0
  89. package/dist/utils/inlineMarkdown.js.map +1 -0
  90. package/dist/vanilla/AudioRenderer.d.ts.map +1 -1
  91. package/dist/vanilla/AudioRenderer.js +6 -0
  92. package/dist/vanilla/AudioRenderer.js.map +1 -1
  93. package/dist/vanilla/ConvaiWidget.d.ts.map +1 -1
  94. package/dist/vanilla/ConvaiWidget.js +224 -89
  95. package/dist/vanilla/ConvaiWidget.js.map +1 -1
  96. package/dist/vanilla/WidgetEventSubscriptions.d.ts +15 -0
  97. package/dist/vanilla/WidgetEventSubscriptions.d.ts.map +1 -0
  98. package/dist/vanilla/WidgetEventSubscriptions.js +37 -0
  99. package/dist/vanilla/WidgetEventSubscriptions.js.map +1 -0
  100. package/dist/vanilla/index.d.ts +2 -1
  101. package/dist/vanilla/index.d.ts.map +1 -1
  102. package/dist/vanilla/index.js +2 -1
  103. package/dist/vanilla/index.js.map +1 -1
  104. package/dist/vanilla/types.d.ts +8 -1
  105. package/dist/vanilla/types.d.ts.map +1 -1
  106. package/dist/vanilla/types.js.map +1 -1
  107. package/dist/version.d.ts +1 -1
  108. package/dist/version.js +1 -1
  109. package/dist/version.js.map +1 -1
  110. package/package.json +19 -6
@@ -96,6 +96,15 @@ export interface UploadFileOptions {
96
96
  */
97
97
  onProgress?: (progressPercent: number) => void;
98
98
  }
99
+ /** Options for {@link IConvaiClient.sendUserTextMessage}. */
100
+ export interface SendUserTextMessageOptions {
101
+ /**
102
+ * Client-owned identifier used to correlate every canonical v2 model-output
103
+ * envelope produced for this user turn. The value must be non-empty and at
104
+ * most 128 UTF-8 bytes. It is currently carried by LiveKit/WebRTC sessions.
105
+ */
106
+ logicalTurnId?: string;
107
+ }
99
108
  /**
100
109
  * Extra data returned in a server-response for specific event types.
101
110
  */
@@ -115,6 +124,17 @@ export interface ServerResponseExtras {
115
124
  has_speak_tag?: boolean;
116
125
  text?: string;
117
126
  room_name?: string;
127
+ command_id?: string;
128
+ room_session_id?: string;
129
+ previous_membership_id?: string | null;
130
+ active_membership_id?: string | null;
131
+ previous_active_membership_id?: string | null;
132
+ route_epoch?: number;
133
+ roster_epoch?: number;
134
+ changed?: boolean;
135
+ added?: unknown[];
136
+ removed_membership_ids?: string[];
137
+ code?: string;
118
138
  supported_types?: string[];
119
139
  vision_buffer?: VisionBufferStatus;
120
140
  requested_respond_mode?: RespondMode;
@@ -192,12 +212,131 @@ export interface ConvaiAction {
192
212
  */
193
213
  target?: string;
194
214
  }
215
+ export type JsonPrimitive = string | number | boolean | null;
216
+ export type JsonValue = JsonPrimitive | JsonObject | JsonValue[];
217
+ export interface JsonObject {
218
+ [key: string]: JsonValue;
219
+ }
220
+ /** A client-executed tool declared for action protocol v2. */
221
+ export interface ClientToolDeclaration {
222
+ name: string;
223
+ description: string;
224
+ inputSchema: JsonObject;
225
+ }
226
+ /** A correlated tool call selected by the model. */
227
+ export interface ConvaiToolCall extends ConvaiAction {
228
+ kind: "tool_call";
229
+ id: string;
230
+ arguments: JsonObject;
231
+ }
232
+ export interface ProtocolCapabilitiesConfig {
233
+ /** Opt in to correlated client tool calls. Omitted connections remain v1. */
234
+ actionProtocolVersion?: 1 | 2;
235
+ /** Opt in to canonical typed model output. Omitted connections remain v1. */
236
+ modelOutputVersion?: 1 | 2;
237
+ }
238
+ /** One raw provider-output chunk emitted only by negotiated model output v2. */
239
+ export interface BotLlmTextRawEvent {
240
+ text: string;
241
+ logical_turn_id: string;
242
+ /**
243
+ * Core-owned identifier for the individual model invocation that produced
244
+ * this chunk. Absent when connected to an older v2 Core.
245
+ */
246
+ output_id?: string;
247
+ }
248
+ export interface ModelOutputMessageItem {
249
+ type: "message";
250
+ role: "assistant";
251
+ channel: "final" | "commentary";
252
+ content: string;
253
+ }
254
+ export interface ModelOutputEmotionItem {
255
+ type: "emotion";
256
+ name: string;
257
+ scale: 1 | 2 | 3;
258
+ }
259
+ export interface ModelOutputSemanticActionItem {
260
+ type: "semantic_action";
261
+ id: string;
262
+ name: string;
263
+ target?: string | null;
264
+ }
265
+ export interface ModelOutputToolCallItem {
266
+ type: "tool_call";
267
+ id: string;
268
+ name: string;
269
+ target?: string | null;
270
+ arguments: JsonObject;
271
+ }
272
+ export interface ModelOutputExtensionItem {
273
+ type: "extension";
274
+ schema: string;
275
+ version: number;
276
+ payload: JsonObject;
277
+ fallback?: string | null;
278
+ }
279
+ export type ModelOutputItem = ModelOutputMessageItem | ModelOutputEmotionItem | ModelOutputSemanticActionItem | ModelOutputToolCallItem | ModelOutputExtensionItem;
280
+ export interface ModelOutputMessage {
281
+ type: "model-output";
282
+ version: 2;
283
+ /**
284
+ * Core-owned provider invocation id. Distinct projections from the same
285
+ * invocation can share this value and are emitted in arrival order.
286
+ */
287
+ output_id: string;
288
+ /**
289
+ * Stable identifier shared by every output envelope for one logical turn.
290
+ * Present values are non-empty and at most 128 UTF-8 bytes.
291
+ */
292
+ logical_turn_id?: string;
293
+ format: "text" | "convai-combined-json" | "semantic-actions-json" | "client-tool-calls-json";
294
+ /** Exact provider/runtime output for diagnostics. Never execute this field. */
295
+ raw: string;
296
+ /** Core-validated renderable and executable semantic items. */
297
+ items: ModelOutputItem[];
298
+ final: true;
299
+ }
300
+ export interface ModelOutputProtocolError {
301
+ code: "invalid_model_output";
302
+ message: string;
303
+ }
304
+ export interface ActionResult {
305
+ id: string;
306
+ status: "completed" | "error" | "cancelled";
307
+ output?: JsonValue;
308
+ error?: JsonValue;
309
+ characterSessionId?: string;
310
+ }
311
+ /** Successful server acknowledgement for one correlated action result. */
312
+ export interface ActionResultAck {
313
+ toolCallId: string;
314
+ status: "success";
315
+ message: string | null;
316
+ /** True when Core had already accepted the same terminal result. */
317
+ idempotent: boolean;
318
+ }
319
+ /**
320
+ * Controls acknowledgement waiting for
321
+ * {@link IConvaiClient.sendActionResultAndWait}.
322
+ */
323
+ export interface ActionResultAckOptions {
324
+ /** Maximum wait for Core's acknowledgement. Defaults to 10 seconds. */
325
+ timeoutMs?: number;
326
+ /**
327
+ * Cancels acknowledgement waiting. An already-aborted signal prevents
328
+ * publication.
329
+ */
330
+ signal?: AbortSignal;
331
+ }
332
+ /** Machine-readable reason exposed by `ActionResultAckError`. */
333
+ export type ActionResultAckFailureReason = "server_error" | "publication_error" | "timeout" | "aborted" | "duplicate_in_flight";
195
334
  /**
196
335
  * Payload of the `actionResponse` event. Actions execute sequentially; an
197
336
  * empty array is a valid "no action" turn.
198
337
  */
199
338
  export interface ActionResponseEvent {
200
- actions: ConvaiAction[];
339
+ actions: Array<ConvaiAction | ConvaiToolCall>;
201
340
  }
202
341
  /**
203
342
  * Options for updating the bot's temporary runtime context.
@@ -401,8 +540,12 @@ export interface ConvaiConfig {
401
540
  *
402
541
  * May also carry a version selector suffix (`<uuid>-draft`, `<uuid>-latest`,
403
542
  * `<uuid>-1.2`); `characterVersion` is the clearer way to say the same thing.
543
+ *
544
+ * Optional only because a multi-character room supplies `characters`
545
+ * instead. Exactly one of the two is required, and a version selector is not
546
+ * accepted inside a roster entry.
404
547
  */
405
- characterId: string;
548
+ characterId?: string;
406
549
  /**
407
550
  * Which version of the character to run (optional).
408
551
  *
@@ -431,6 +574,62 @@ export interface ConvaiConfig {
431
574
  * `https://api2-stg.convai.com` to author against staging.
432
575
  */
433
576
  characterApiUrl?: string;
577
+ /**
578
+ * Ordered roster of character instances for a multi-character room. Pass this
579
+ * *instead of* `characterId` -- exactly one of the two is valid.
580
+ *
581
+ * Every entry becomes a distinct membership with its own actor, LiveKit
582
+ * participant, voice, history and lifecycle. The same `characterId` may
583
+ * appear more than once; each copy is an independent clone addressed by its
584
+ * own `membershipId`. `characters[0]` is the initial active member.
585
+ *
586
+ * Roster rooms require the LiveKit transport, a nonblank `endUserId`, and the
587
+ * `MULTI_CHARACTER_V0` entitlement on the publisher.
588
+ *
589
+ * @example
590
+ * ```ts
591
+ * const client = new ConvaiClient({
592
+ * apiKey: 'YOUR_API_KEY',
593
+ * endUserId: 'player-42',
594
+ * characters: [
595
+ * { characterId: GUIDE }, // initial active member
596
+ * { characterId: ASSESSOR },
597
+ * { characterId: GUIDE }, // a second, independent copy of GUIDE
598
+ * ],
599
+ * });
600
+ * ```
601
+ */
602
+ characters?: ConvaiCharacterSpec[];
603
+ /**
604
+ * Publisher-scoped room grouping and topology key (1-128 chars of letters,
605
+ * digits, hyphen or underscore). A matching create request reuses the
606
+ * existing room; reusing the key with a different ordered roster, creator or
607
+ * capacity is rejected with `ROSTER_FINGERPRINT_MISMATCH`. Reordering the
608
+ * same characters counts as different, because it changes the initial member.
609
+ *
610
+ * This does not raise human capacity on its own -- see `maxNumParticipants`.
611
+ */
612
+ sharedSessionKey?: string;
613
+ /**
614
+ * Idempotency key for one logical connect (1-128 chars, same charset as
615
+ * `sharedSessionKey`). Reuse it only when retrying with an identical payload:
616
+ * within the replay window a completed attempt returns its original response
617
+ * and token, while a changed payload or a still-running original is rejected.
618
+ */
619
+ connectAttemptId?: string;
620
+ /**
621
+ * Maximum number of distinct human speakers in a roster room. Characters do
622
+ * not count toward it. Defaults to the server's value of 1, which admits no
623
+ * second human -- raise it before expecting `joinRoom()` to succeed.
624
+ */
625
+ maxNumParticipants?: number;
626
+ /**
627
+ * Bounded retry when a roster room is still provisioning (409
628
+ * `ROSTER_PROVISIONING_IN_PROGRESS`). Defaults to four attempts starting at
629
+ * 500ms and doubling with jitter. Pass `false` to surface the error instead
630
+ * and retry in application code.
631
+ */
632
+ rosterProvisioningRetry?: RosterProvisioningRetry | false;
434
633
  /** Temporary character state of mind sent as `state_of_mind` on connect. */
435
634
  stateOfMind?: string | null;
436
635
  /**
@@ -460,6 +659,8 @@ export interface ConvaiConfig {
460
659
  transport?: "livekit" | "websocket" | "sse";
461
660
  /** SSE interaction endpoint. Supplying this also selects the SSE transport when transport is omitted. */
462
661
  interactionApiUrl?: string;
662
+ /** Explicit protocol opt-ins. Omit to preserve the legacy v1 wire contract. */
663
+ capabilities?: ProtocolCapabilitiesConfig;
463
664
  /**
464
665
  * Character session ID (optional). Pass to resume an existing session;
465
666
  * otherwise populated from the connect API response after first connection.
@@ -488,8 +689,20 @@ export interface ConvaiConfig {
488
689
  * visionInputConfig.enabled=false to opt out while keeping the video channel.
489
690
  */
490
691
  visionInputConfig?: VisionInputConfig;
692
+ /**
693
+ * Controls whether Core injects its vision-state instructions into the model prompt.
694
+ * Omit this option (or use `"auto"`) to preserve the existing runtime behavior.
695
+ * Use `"disabled"` for metadata-only sessions that must not advertise or deny
696
+ * visual perception.
697
+ */
698
+ visionPromptMode?: "auto" | "disabled";
491
699
  /** Connect-time respond-mode defaults by modality. */
492
700
  respondModes?: RespondModesConfig;
701
+ /** Descriptive objects visible in the scene at connection time. */
702
+ sceneDescription?: Array<{
703
+ name: string;
704
+ description: string;
705
+ }>;
493
706
  /**
494
707
  * WebRTC ICE transport policy for the LiveKit connection (default: "relay").
495
708
  * "relay" forces TURN-only (reliable against Convai's hosted LiveKit which
@@ -601,6 +814,8 @@ export interface ConvaiConfig {
601
814
  }>;
602
815
  /** Name of the object the character is currently focused on. Must match one of objects[].name. */
603
816
  current_attention_object?: string;
817
+ /** Client-executed tools available only when action protocol v2 is selected. */
818
+ tools?: ClientToolDeclaration[];
604
819
  };
605
820
  /**
606
821
  * Dynamic contextual information about the current situation.
@@ -652,6 +867,37 @@ export interface ConvaiConfig {
652
867
  * Enable debug mode for additional logging and diagnostics (default: false).
653
868
  */
654
869
  debug?: boolean;
870
+ /** Optional per-session response lifecycle contract override. */
871
+ useResponseLifecycleContract?: boolean;
872
+ /**
873
+ * Keep links in the character's text output (default: server-side, currently off).
874
+ *
875
+ * Core-service flattens the LLM's markdown before streaming `bot-llm-text`,
876
+ * which also drops link targets: `[Doc](https://…/a.pdf)` reaches the client
877
+ * as `Doc`. With this on, the session preserves `[text](url)`, `![alt](url)`
878
+ * and bare `http(s)://` URLs verbatim (trailing sentence punctuation stays
879
+ * outside the URL, non-http(s) schemes are still stripped) while bold,
880
+ * headings, tables and code are flattened as before. Speech is unaffected —
881
+ * URLs are never read aloud.
882
+ *
883
+ * Both widgets render the preserved form as clickable links, with inline
884
+ * previews for image and video URLs. If you render `chatMessages` yourself,
885
+ * expect markdown links in `content` once this is on.
886
+ *
887
+ * Sent as `preserve_links_in_output` on `/connect`; omitted when undefined so
888
+ * the server's own default applies. If you build the `/connect` request
889
+ * server-side for `connectWithConnectionData()`, add the field there.
890
+ *
891
+ * @example
892
+ * ```typescript
893
+ * const client = new ConvaiClient({
894
+ * apiKey: 'your-api-key',
895
+ * characterId: 'your-character-id',
896
+ * preserveLinksInOutput: true,
897
+ * });
898
+ * ```
899
+ */
900
+ preserveLinksInOutput?: boolean;
655
901
  /**
656
902
  * Log decoded RTVI data messages to the browser console (default: true).
657
903
  * Set to false to silence incoming and outgoing RTVI message logs.
@@ -676,11 +922,270 @@ export interface SendUserTextMessageOptions {
676
922
  logicalTurnId?: string;
677
923
  /** User-selected temporary emotion to apply before processing the text. */
678
924
  stateOfMind?: string | null;
925
+ /** Latest request-scoped dynamic context to include in this same interaction. */
926
+ dynamicInfo?: DynamicInfo;
679
927
  }
680
928
  /**
681
929
  * The body returned by POST /connect. The embed receives this from a
682
930
  * customer-hosted proxy route rather than fetching it directly.
683
931
  */
932
+ /**
933
+ * One ordered character instance requested for a multi-character room.
934
+ *
935
+ * Repeating a `characterId` is legal and intentional: each entry becomes an
936
+ * independent clone with its own membership, session, participant and voice.
937
+ */
938
+ export interface ConvaiCharacterSpec {
939
+ /**
940
+ * Bare character UUID. Version selectors (`<uuid>-draft`, `<uuid>-1.2`) are
941
+ * accepted by single-character `characterId` but rejected inside a roster --
942
+ * the runtime types roster entries as plain UUIDs.
943
+ */
944
+ characterId: string;
945
+ /**
946
+ * Resume this instance's prior conversation history. Must be unique across
947
+ * the roster, and must belong to the same publisher, speaker and character.
948
+ */
949
+ characterSessionId?: string;
950
+ }
951
+ /**
952
+ * Dispatch state of one roster member, as reported by `/connect`.
953
+ *
954
+ * These describe provisioning only and never readiness. A member becomes
955
+ * usable when its own `bot-ready` arrives -- `dispatch_accepted` is not
956
+ * `bot-ready`. The union deliberately has no member that could be mistaken for
957
+ * a ready state; the separate `character-status` event carries those.
958
+ */
959
+ export type CharacterProvisioningStatus = "dispatch_queued" | "dispatch_accepted" | "dispatch_failed";
960
+ /** One concrete character instance in a roster room. */
961
+ export interface ConvaiCharacterInstance {
962
+ /** Primary key for this instance. Address members by this, never by `characterId`. */
963
+ membershipId: string;
964
+ /** The authored character this instance runs. Not unique across a roster. */
965
+ characterId: string;
966
+ /** Backend session for support correlation. */
967
+ sessionId: string | null;
968
+ /** This instance's conversation/history session. */
969
+ characterSessionId: string | null;
970
+ /** Stable LiveKit identity, always `character:{membershipId}`. */
971
+ participantIdentity: string;
972
+ /** True for `characters[0]`, the initially active member. */
973
+ isInitial: boolean;
974
+ provisioningStatus: CharacterProvisioningStatus;
975
+ /**
976
+ * The character's display name, when the runtime sends one. Saves a separate
977
+ * `character/get` call just to label a member in the UI. Undocumented in the
978
+ * published contract but returned by the live API, so treat it as optional.
979
+ */
980
+ displayName: string | null;
981
+ /** Character description, when the runtime sends one. */
982
+ description: string | null;
983
+ /** Populated when `provisioningStatus` is `dispatch_failed`. */
984
+ failureCode: string | null;
985
+ /** True once this member's own `bot-ready` has arrived. */
986
+ isReady: boolean;
987
+ }
988
+ /**
989
+ * Server-owned snapshot of a multi-character room. Null for single-character
990
+ * sessions.
991
+ */
992
+ export interface ConvaiRoomSession {
993
+ /** Durable room identity. Use it to join, and to correlate with support. */
994
+ roomSessionId: string;
995
+ roomName: string | null;
996
+ /** Trace id of the `/connect` that produced this room. Quote it in bug reports. */
997
+ requestTraceId: string | null;
998
+ /** Membership currently authorised to consume user turns. */
999
+ activeMembershipId: string | null;
1000
+ /** Monotonic version of the active target; fences target switches. */
1001
+ routeEpoch: number;
1002
+ /** Monotonic version of roster composition; fences add/remove. */
1003
+ rosterEpoch: number;
1004
+ /** True when at least one member already failed dispatch. */
1005
+ partialDispatch: boolean;
1006
+ characters: ConvaiCharacterInstance[];
1007
+ }
1008
+ /** Result of a successful target switch. */
1009
+ export interface ActiveCharacterChange {
1010
+ /** Membership that was active before, or null. */
1011
+ previous: string | null;
1012
+ /** Membership now authorised to consume user turns, or null when all gates are closed. */
1013
+ active: string | null;
1014
+ routeEpoch: number;
1015
+ }
1016
+ /** Result of a successful roster mutation. */
1017
+ export interface CharacterRosterChange {
1018
+ added: ConvaiCharacterInstance[];
1019
+ removed: ConvaiCharacterInstance[];
1020
+ /** The roster after the change. */
1021
+ characters: ConvaiCharacterInstance[];
1022
+ rosterEpoch: number;
1023
+ routeEpoch: number;
1024
+ activeMembershipId: string | null;
1025
+ }
1026
+ /** Options for adding and removing roster members on a live room. */
1027
+ export interface UpdateCharacterRosterOptions {
1028
+ /** Members to add. Repeating an existing characterId creates another clone. */
1029
+ add?: ConvaiCharacterSpec[];
1030
+ /** Membership ids to remove. Never characterIds -- clones make those ambiguous. */
1031
+ remove?: string[];
1032
+ /**
1033
+ * Member to take over routing when the active one is removed. Must be a ready
1034
+ * member that survives the change. Chosen automatically when omitted.
1035
+ */
1036
+ replacementTarget?: string;
1037
+ }
1038
+ /** Options for joining an existing multi-character room. */
1039
+ export interface JoinRoomOptions {
1040
+ /** Preferred locator. Exactly one of this or `sharedSessionKey`. */
1041
+ roomSessionId?: string;
1042
+ /** Publisher-scoped alternative locator. */
1043
+ sharedSessionKey?: string;
1044
+ /** Required and nonblank; identifies the joining human. */
1045
+ endUserId: string;
1046
+ endUserMetadata?: Record<string, unknown>;
1047
+ /** Idempotency key for retrying this join. */
1048
+ connectAttemptId?: string;
1049
+ }
1050
+ /**
1051
+ * Lifecycle transition of one roster member, after `/connect` has returned.
1052
+ *
1053
+ * `bot-ready` remains the readiness authority: do not enable interaction from a
1054
+ * `ready` status alone. This event's real job is reporting a member that was
1055
+ * added at runtime, or one whose dispatch failed in the background.
1056
+ */
1057
+ export interface CharacterStatusEvent {
1058
+ status: "starting" | "ready" | "failed";
1059
+ membershipId: string;
1060
+ characterId: string;
1061
+ characterSessionId: string | null;
1062
+ participantIdentity: string;
1063
+ roomSessionId: string | null;
1064
+ rosterEpoch: number | null;
1065
+ /** Set when `status` is `failed`, e.g. `ACTOR_ASSIGNMENT_FAILED`. */
1066
+ failureCode: string | null;
1067
+ }
1068
+ /**
1069
+ * An audio track bound to the character instance that publishes it.
1070
+ *
1071
+ * In a multi-character room `membershipId` is always set -- a track that
1072
+ * cannot be attributed to a roster member is dropped, never surfaced against
1073
+ * the active character. In a single-character room it is null.
1074
+ */
1075
+ export interface CharacterAudioTrackEvent {
1076
+ membershipId: string | null;
1077
+ characterId: string | null;
1078
+ /** LiveKit participant identity; `character:{membershipId}` in a roster. */
1079
+ participantIdentity: string;
1080
+ track: MediaStreamTrack;
1081
+ }
1082
+ /**
1083
+ * A finalized turn's usage/cost breakdown, streamed by the server after
1084
+ * {@link IConvaiClient.toggleUsageUpdates} enables it. The shape is
1085
+ * server-defined and informational; treat unknown fields as opaque.
1086
+ */
1087
+ export type UsageUpdate = Record<string, unknown>;
1088
+ /**
1089
+ * Every event the client emits, with its payload.
1090
+ *
1091
+ * `on()` is typed against this map, so a listener for a known event gets its
1092
+ * payload inferred instead of `any`. The plain-string signature is kept so
1093
+ * existing callers and dynamic event names keep compiling, which also means a
1094
+ * misspelt literal is not a compile error. Payloads the server defines as
1095
+ * opaque blobs (blendshape frames, metrics, usage) are left as records rather
1096
+ * than guessed at.
1097
+ */
1098
+ export interface ConvaiEventMap {
1099
+ connect: [];
1100
+ connected: [];
1101
+ disconnect: [reason: DisconnectReason | null];
1102
+ disconnected: [];
1103
+ error: [error: unknown];
1104
+ stateChange: [state: ConvaiClientState];
1105
+ botReady: [];
1106
+ characterSessionId: [characterSessionId: string];
1107
+ interactionCreated: [data: InteractionCreated];
1108
+ message: [message: ChatMessage];
1109
+ messagesChange: [messages: ChatMessage[]];
1110
+ userTranscriptionChange: [transcription: string];
1111
+ speakingChange: [isSpeaking: boolean];
1112
+ listeningChange: [isListening: boolean];
1113
+ botRespondingChange: [isResponding: boolean];
1114
+ turnEnd: [turn: {
1115
+ sessionId: number;
1116
+ duration: number;
1117
+ timestamp: number;
1118
+ }];
1119
+ conversationStart: [
1120
+ start: {
1121
+ sessionId: number;
1122
+ userMessage: string;
1123
+ timestamp: number;
1124
+ }
1125
+ ];
1126
+ emotionChange: [emotion: {
1127
+ emotion: string;
1128
+ scale?: number;
1129
+ } | null];
1130
+ actionResponse: [data: ActionResponseEvent];
1131
+ serverResponse: [response: ServerResponse];
1132
+ botOutput: [data: {
1133
+ text: string;
1134
+ spoken: boolean;
1135
+ aggregatedBy: string;
1136
+ }];
1137
+ botTtsText: [data: {
1138
+ text: string;
1139
+ }];
1140
+ botTtsStarted: [];
1141
+ botTtsStopped: [];
1142
+ botTurnCompleted: [data: unknown];
1143
+ userMuteStarted: [];
1144
+ userMuteStopped: [];
1145
+ idleWarning: [data: {
1146
+ remainingSeconds: number | null;
1147
+ }];
1148
+ llmNoResponse: [];
1149
+ metrics: [data: Record<string, unknown>];
1150
+ usageUpdate: [data: UsageUpdate];
1151
+ blendshapes: [data: Record<string, unknown>];
1152
+ blendshapeCancel: [data: Record<string, unknown>];
1153
+ blendshapeStatsReceived: [stats: Record<string, unknown>];
1154
+ botAudioTrack: [track: MediaStreamTrack];
1155
+ audioStateChange: [enabled: boolean];
1156
+ videoStateChange: [enabled: boolean];
1157
+ screenShareStateChange: [active: boolean];
1158
+ characterReady: [instance: ConvaiCharacterInstance | undefined];
1159
+ characterStatus: [status: CharacterStatusEvent];
1160
+ activeCharacterChange: [change: ActiveCharacterChange];
1161
+ rosterChange: [change: CharacterRosterChange];
1162
+ characterAudioTrack: [event: CharacterAudioTrackEvent];
1163
+ actionResultAck: [ack: ActionResultAck];
1164
+ modelOutputProtocolError: [data: ModelOutputProtocolError];
1165
+ modelOutput: [data: ModelOutputMessage];
1166
+ botLlmTextRaw: [data: BotLlmTextRawEvent];
1167
+ }
1168
+ /**
1169
+ * Preserve typed callbacks for known events while permitting callers that
1170
+ * intentionally enumerate runtime event names. A string literal outside the
1171
+ * map resolves to `never`, so misspellings still fail at compile time.
1172
+ */
1173
+ export type ConvaiEventCallback<E extends string> = E extends keyof ConvaiEventMap ? (...args: ConvaiEventMap[E]) => void : string extends E ? (...args: any[]) => void : never;
1174
+ /** A transcript line inserted locally by {@link IConvaiClient.appendMessage}. */
1175
+ export interface AppendMessageOptions {
1176
+ sender: "user" | "bot";
1177
+ content: string;
1178
+ /** Attribute the line to a roster member, in a multi-character room. */
1179
+ membershipId?: string;
1180
+ characterId?: string;
1181
+ }
1182
+ /** Bounded retry for a roster room that is still provisioning. */
1183
+ export interface RosterProvisioningRetry {
1184
+ /** Total attempts including the first. Default 4. */
1185
+ attempts?: number;
1186
+ /** Delay before the second attempt; doubles with jitter. Default 500. */
1187
+ initialDelayMs?: number;
1188
+ }
684
1189
  export interface ConnectionData {
685
1190
  /** LiveKit room URL, or the WebSocket URL when the transport is websocket. */
686
1191
  room_url: string;
@@ -690,6 +1195,23 @@ export interface ConnectionData {
690
1195
  end_user_id?: string;
691
1196
  end_user_metadata?: Record<string, unknown>;
692
1197
  }
1198
+ /** Options for connecting to a published text-chat session. */
1199
+ export interface PublishedChatConnectOptions {
1200
+ /** Core API origin (defaults to the production realtime API). */
1201
+ url?: string;
1202
+ /**
1203
+ * WebRTC ICE transport policy (defaults to "relay" for Convai-hosted
1204
+ * LiveKit). Set "all" for a deployment that has no TURN server.
1205
+ */
1206
+ iceTransportPolicy?: RTCIceTransportPolicy;
1207
+ /** Cancels the grant exchange and tears down an in-progress connection. */
1208
+ signal?: AbortSignal;
1209
+ /**
1210
+ * Idempotency key for one logical connect. Reuse it only when retrying the
1211
+ * same launch token. The SDK generates one when this is omitted.
1212
+ */
1213
+ connectAttemptId?: string;
1214
+ }
693
1215
  /**
694
1216
  * Represents a single message in the chat conversation.
695
1217
  * Different message types are used for various parts of the conversation flow.
@@ -697,6 +1219,16 @@ export interface ConnectionData {
697
1219
  export interface ChatMessage {
698
1220
  /** Unique identifier for the message */
699
1221
  id: string;
1222
+ /**
1223
+ * Core-owned identifier for the individual model invocation that produced
1224
+ * this bot row. Absent for legacy sessions and older v2 Core versions.
1225
+ */
1226
+ outputId?: string;
1227
+ /**
1228
+ * Immutable logical turn id for correlated v2 user speech and bot text.
1229
+ * Absent for legacy sessions and uncorrelated messages.
1230
+ */
1231
+ logicalTurnId?: string;
700
1232
  /**
701
1233
  * Type of message:
702
1234
  * - `user`: User's sent message
@@ -714,6 +1246,14 @@ export interface ChatMessage {
714
1246
  * - `llm-no-response`: LLM deliberately did not respond (abstain); `content` is always `""`
715
1247
  */
716
1248
  type: 'user' | 'convai' | 'emotion' | 'behavior-tree' | 'action' | 'user-transcription' | 'bot-llm-text' | 'bot-output' | 'bot-emotion' | 'user-llm-text' | 'interrupt-bot' | 'idle-warning' | 'llm-no-response';
1249
+ /**
1250
+ * Which character instance produced this message, in a multi-character room.
1251
+ * Undefined in single-character sessions. Attribute UI to this, never to
1252
+ * `characterId` -- two clones of one character share a `characterId`.
1253
+ */
1254
+ membershipId?: string;
1255
+ /** The authored character behind {@link membershipId}. Not unique across a roster. */
1256
+ characterId?: string;
717
1257
  /** The text content of the message */
718
1258
  content: string;
719
1259
  /** ISO timestamp string of when the message was created */
@@ -819,6 +1359,16 @@ export interface ConvaiClientState {
819
1359
  * @see DisconnectReason
820
1360
  */
821
1361
  disconnectReason: DisconnectReason | null;
1362
+ /**
1363
+ * Character instances in a multi-character room, in roster order. Empty for
1364
+ * single-character sessions, so a check on `length` distinguishes the two.
1365
+ */
1366
+ characters: ConvaiCharacterInstance[];
1367
+ /**
1368
+ * Membership currently receiving user turns, or null. Only this member
1369
+ * consumes interaction input.
1370
+ */
1371
+ activeMembershipId: string | null;
822
1372
  }
823
1373
  /**
824
1374
  * Audio control interface for managing microphone
@@ -836,7 +1386,10 @@ export interface AudioControls {
836
1386
  getAudioDevices: () => Promise<MediaDeviceInfo[]>;
837
1387
  startAudioLevelMonitoring: () => void;
838
1388
  stopAudioLevelMonitoring: () => void;
839
- on: (event: string, callback: (...args: any[]) => void) => () => void;
1389
+ on: {
1390
+ <E extends keyof ConvaiEventMap>(event: E, callback: (...args: ConvaiEventMap[E]) => void): () => void;
1391
+ (event: string, callback: (...args: any[]) => void): () => void;
1392
+ };
840
1393
  off: (event: string, callback: (...args: any[]) => void) => void;
841
1394
  }
842
1395
  /**
@@ -859,7 +1412,10 @@ export interface VideoControls {
859
1412
  publishCanvas: (canvas: HTMLCanvasElement, options?: PublishCanvasOptions) => Promise<VisionSourceHandle>;
860
1413
  publishVideoTrack: (track: MediaStreamTrack, options?: PublishVideoTrackOptions) => Promise<VisionSourceHandle>;
861
1414
  unpublishVisionSource: (source?: VisionSourceHandle | MediaStreamTrack) => Promise<void>;
862
- on: (event: string, callback: (...args: any[]) => void) => () => void;
1415
+ on: {
1416
+ <E extends keyof ConvaiEventMap>(event: E, callback: (...args: ConvaiEventMap[E]) => void): () => void;
1417
+ (event: string, callback: (...args: any[]) => void): () => void;
1418
+ };
863
1419
  off: (event: string, callback: (...args: any[]) => void) => void;
864
1420
  }
865
1421
  /**
@@ -873,7 +1429,10 @@ export interface ScreenShareControls {
873
1429
  toggleScreenShare: () => Promise<void>;
874
1430
  enableScreenShareWithAudio: () => Promise<void>;
875
1431
  getScreenShareTracks: () => Promise<any[]>;
876
- on: (event: string, callback: (...args: any[]) => void) => () => void;
1432
+ on: {
1433
+ <E extends keyof ConvaiEventMap>(event: E, callback: (...args: ConvaiEventMap[E]) => void): () => void;
1434
+ (event: string, callback: (...args: any[]) => void): () => void;
1435
+ };
877
1436
  off: (event: string, callback: (...args: any[]) => void) => void;
878
1437
  }
879
1438
  /**
@@ -1247,10 +1806,12 @@ export interface IConvaiClient {
1247
1806
  /** Current connection and activity state of the client */
1248
1807
  readonly state: ConvaiClientState;
1249
1808
  /**
1250
- * Connection type: "audio" (audio only) or "video" (audio + video + screenshare).
1251
- * Set based on enableVideo in connect config.
1809
+ * Connection type: "text" (no local media), "audio" (audio only), or
1810
+ * "video" (audio + video + screenshare).
1252
1811
  */
1253
- readonly connectionType: 'audio' | 'video' | null;
1812
+ readonly connectionType: 'audio' | 'video' | 'text' | null;
1813
+ /** Whether this client was last connected through a single-use publication grant. */
1814
+ readonly isPublishedChatSession?: boolean;
1254
1815
  /** API key used for the current connection, if apiKey was used (null otherwise) */
1255
1816
  readonly apiKey?: string | null;
1256
1817
  /** Auth token used for the current connection, if authToken was used (null otherwise) */
@@ -1269,6 +1830,8 @@ export interface IConvaiClient {
1269
1830
  readonly userTranscription: string;
1270
1831
  /** Unique session ID for the current character conversation */
1271
1832
  readonly characterSessionId: string | null;
1833
+ /** Server trace ID for the most recent connection request, when provided. */
1834
+ readonly requestTraceId?: string | null;
1272
1835
  /** Whether the bot is ready to receive messages (true after bot-ready message) */
1273
1836
  readonly isBotReady: boolean;
1274
1837
  /** Audio control methods for managing microphone mute/unmute */
@@ -1316,6 +1879,29 @@ export interface IConvaiClient {
1316
1879
  * Connect to a Convai character.
1317
1880
  */
1318
1881
  connect: (config?: ConvaiConfig) => Promise<void>;
1882
+ /**
1883
+ * Connect to a published text chat with a short-lived, single-use grant.
1884
+ *
1885
+ * Obtain the grant from the public publication endpoint immediately before
1886
+ * connecting. This path needs no API key or character ID in the browser and
1887
+ * creates a data-only, text-chat session. Request a fresh grant for every
1888
+ * later session or reconnect attempt.
1889
+ *
1890
+ * @example
1891
+ * ```ts
1892
+ * import { ConvaiClient } from '@convai/web-sdk/core'
1893
+ * import { requestPublishedChatGrant } from '@convai/web-sdk/embed'
1894
+ *
1895
+ * const client = new ConvaiClient()
1896
+ * const launchToken = await requestPublishedChatGrant(
1897
+ * 'https://character-api.example.com/chat-publications/PUBLICATION_ID/launch-grants',
1898
+ * )
1899
+ * await client.connectWithPublicationGrant(launchToken, {
1900
+ * url: 'https://realtime.example.com',
1901
+ * })
1902
+ * ```
1903
+ */
1904
+ connectWithPublicationGrant?: (launchToken: string, options?: PublishedChatConnectOptions) => Promise<void>;
1319
1905
  /**
1320
1906
  * Complete a connection from an already-fetched /connect response body.
1321
1907
  *
@@ -1336,6 +1922,70 @@ export interface IConvaiClient {
1336
1922
  * await client.connectWithConnectionData(data)
1337
1923
  */
1338
1924
  connectWithConnectionData: (data: ConnectionData, config?: ConvaiConfig) => Promise<void>;
1925
+ /**
1926
+ * Join an existing multi-character room by `roomSessionId` or
1927
+ * `sharedSessionKey`. The roster is server-owned, so no character topology is
1928
+ * sent; joining never spawns, removes or repairs a character.
1929
+ *
1930
+ * @example
1931
+ * ```ts
1932
+ * await client.joinRoom({ roomSessionId: 'the-room-id', endUserId: 'player-99' })
1933
+ * ```
1934
+ */
1935
+ joinRoom: (options: JoinRoomOptions) => Promise<void>;
1936
+ /** Server-owned snapshot of a multi-character room (null when single-character) */
1937
+ readonly roomSession: ConvaiRoomSession | null;
1938
+ /** Character instances in roster order; empty for a single-character session */
1939
+ readonly characters: ConvaiCharacterInstance[];
1940
+ /** Membership currently receiving user turns, or null */
1941
+ readonly activeMembershipId: string | null;
1942
+ /**
1943
+ * Insert a message into the transcript locally, without sending it to the
1944
+ * character. Use it for client-side lines -- a greeting, a system notice,
1945
+ * replayed history -- that must appear in the chat but must never reach
1946
+ * the LLM or be billed as a turn. Not `sendUserTextMessage`: nothing is
1947
+ * transmitted. Returns the message that was added.
1948
+ *
1949
+ * @example
1950
+ * ```ts
1951
+ * client.appendMessage({ sender: 'bot', content: 'Welcome back!' })
1952
+ * ```
1953
+ */
1954
+ appendMessage: (message: AppendMessageOptions) => ChatMessage;
1955
+ /**
1956
+ * Opt in or out of `usageUpdate` events -- the server's per-turn usage and
1957
+ * cost breakdown. Informational only; billing is unaffected.
1958
+ *
1959
+ * @example
1960
+ * ```ts
1961
+ * client.toggleUsageUpdates(true)
1962
+ * client.on('usageUpdate', (u) => console.log(u))
1963
+ * ```
1964
+ */
1965
+ toggleUsageUpdates: (enabled: boolean) => void;
1966
+ /**
1967
+ * Route subsequent user turns to a different character instance. Pass null to
1968
+ * close every input gate so no member hears the user.
1969
+ *
1970
+ * Resolves on the server's acknowledgement. Retries once against the
1971
+ * server's authoritative epoch when another participant switched first.
1972
+ *
1973
+ * @example
1974
+ * ```ts
1975
+ * await client.setInteractionTarget(assessor.membershipId)
1976
+ * client.sendUserTextMessage('Now grade me.')
1977
+ * ```
1978
+ */
1979
+ setInteractionTarget: (membershipId: string | null) => Promise<ActiveCharacterChange>;
1980
+ /**
1981
+ * Add or remove character instances on a live room, without reconnecting.
1982
+ *
1983
+ * @example
1984
+ * ```ts
1985
+ * await client.updateCharacterRoster({ add: [{ characterId: NARRATOR }] })
1986
+ * ```
1987
+ */
1988
+ updateCharacterRoster: (options: UpdateCharacterRosterOptions) => Promise<CharacterRosterChange>;
1339
1989
  /** Disconnect from the current character session */
1340
1990
  disconnect: () => Promise<void>;
1341
1991
  /** Reconnect - disconnect and connect again using stored config */
@@ -1344,6 +1994,13 @@ export interface IConvaiClient {
1344
1994
  resetSession: () => void;
1345
1995
  /** Send a text message to the character */
1346
1996
  sendUserTextMessage: (text: string, options?: SendUserTextMessageOptions) => void;
1997
+ /** Return a correlated terminal result for a v2 client tool call. */
1998
+ sendActionResult: (result: ActionResult) => void;
1999
+ /**
2000
+ * Publish one correlated terminal result and wait for Core's matching
2001
+ * `server-response` acknowledgement.
2002
+ */
2003
+ sendActionResultAndWait: (result: ActionResult, options?: ActionResultAckOptions) => Promise<ActionResultAck>;
1347
2004
  /**
1348
2005
  * Send a trigger message to invoke specific character actions or responses.
1349
2006
  * @param triggerName - Name of the trigger to invoke
@@ -1472,12 +2129,12 @@ export interface IConvaiClient {
1472
2129
  * @param callback Callback function
1473
2130
  * @returns Unsubscribe function
1474
2131
  */
1475
- on: (event: string, callback: (...args: any[]) => void) => () => void;
2132
+ on: <E extends string>(event: E, callback: ConvaiEventCallback<E>) => () => void;
1476
2133
  /**
1477
2134
  * Unsubscribe from an event
1478
2135
  * @param event Event name
1479
2136
  * @param callback Callback function to remove
1480
2137
  */
1481
- off: (event: string, callback: (...args: any[]) => void) => void;
2138
+ off: <E extends string>(event: E, callback: ConvaiEventCallback<E>) => void;
1482
2139
  }
1483
2140
  //# sourceMappingURL=types.d.ts.map