@runtypelabs/persona 4.25.0 → 4.26.1

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 (236) hide show
  1. package/dist/animations/glyph-cycle.d.cts +1 -1
  2. package/dist/animations/glyph-cycle.d.ts +1 -1
  3. package/dist/animations/{types-Db61aI9J.d.cts → types-BwKTZhg9.d.cts} +14 -0
  4. package/dist/animations/{types-Db61aI9J.d.ts → types-BwKTZhg9.d.ts} +14 -0
  5. package/dist/animations/wipe.d.cts +1 -1
  6. package/dist/animations/wipe.d.ts +1 -1
  7. package/dist/animations-extra.d.cts +14 -0
  8. package/dist/animations-extra.d.ts +14 -0
  9. package/dist/approval-ui-QAKWNFNM.js +1 -0
  10. package/dist/approval-ui.cjs +2 -2
  11. package/dist/approval-ui.d.cts +186 -8
  12. package/dist/approval-ui.d.ts +186 -8
  13. package/dist/approval-ui.js +2 -2
  14. package/dist/{artifacts-ui-IGB5YKLO.js → artifacts-ui-NJGMM27I.js} +1 -1
  15. package/dist/artifacts-ui.cjs +4 -4
  16. package/dist/artifacts-ui.d.cts +186 -8
  17. package/dist/artifacts-ui.d.ts +186 -8
  18. package/dist/artifacts-ui.js +5 -5
  19. package/dist/chunk-2ANTRKTV.js +1 -0
  20. package/dist/chunk-4HPTPUC6.js +1 -0
  21. package/dist/chunk-6V3MNEKB.js +1 -0
  22. package/dist/chunk-GKPCIQPB.js +1 -0
  23. package/dist/chunk-HGUCGM3K.js +9 -0
  24. package/dist/chunk-IO5VVUKP.js +3 -0
  25. package/dist/chunk-J4J3Y2P2.js +1 -0
  26. package/dist/chunk-K6HKIP5K.js +1 -0
  27. package/dist/chunk-K7NA7G7J.js +1 -0
  28. package/dist/chunk-MXUTS3LB.js +1 -0
  29. package/dist/chunk-PDPVORUF.js +1 -0
  30. package/dist/chunk-QRKGQPU7.js +1 -0
  31. package/dist/chunk-S6PBWE75.js +1 -0
  32. package/dist/chunk-T7QM7YMF.js +1 -0
  33. package/dist/chunk-TR2H475E.js +1 -0
  34. package/dist/chunk-UPO4GUFC.js +1 -0
  35. package/dist/chunk-ZC66NAIR.js +1 -0
  36. package/dist/client-history-GOZWBDA5.js +1 -0
  37. package/dist/client-history.js +1 -0
  38. package/dist/client-stream-42FOI3EC.js +4 -0
  39. package/dist/client-stream.js +5 -0
  40. package/dist/codegen.cjs +1 -1
  41. package/dist/codegen.js +1 -1
  42. package/dist/context-mentions-E7HJYWO6.js +161 -0
  43. package/dist/{context-mentions-inline-I2RDEBAK.js → context-mentions-inline-QVESLW55.js} +1 -1
  44. package/dist/context-mentions.cjs +7 -7
  45. package/dist/context-mentions.d.cts +186 -8
  46. package/dist/context-mentions.d.ts +186 -8
  47. package/dist/context-mentions.js +8 -8
  48. package/dist/event-stream-view-FOIJHFQO.js +1 -0
  49. package/dist/event-stream-view.cjs +1 -1
  50. package/dist/event-stream-view.d.cts +189 -31
  51. package/dist/event-stream-view.d.ts +189 -31
  52. package/dist/event-stream-view.js +1 -1
  53. package/dist/forms-ui.d.cts +227 -667
  54. package/dist/forms-ui.d.ts +227 -667
  55. package/dist/history-shell-QDQ44PSE.js +3 -0
  56. package/dist/history-shell.js +3 -0
  57. package/dist/{history-view-BD6OXLNA.js → history-view-NCFBI5GR.js} +2 -2
  58. package/dist/history-view.cjs +2 -2
  59. package/dist/history-view.d.cts +35 -1
  60. package/dist/history-view.d.ts +35 -1
  61. package/dist/history-view.js +2 -2
  62. package/dist/index.cjs +80 -74
  63. package/dist/index.cjs.map +1 -1
  64. package/dist/index.d.cts +233 -738
  65. package/dist/index.d.ts +233 -738
  66. package/dist/index.global.js +3 -215
  67. package/dist/index.global.js.map +1 -1
  68. package/dist/index.js +81 -75
  69. package/dist/index.js.map +1 -1
  70. package/dist/install.global.js +1 -1
  71. package/dist/install.global.js.map +1 -1
  72. package/dist/launcher.global.js +3 -67
  73. package/dist/launcher.global.js.map +1 -1
  74. package/dist/markdown-parsers.js +22 -22
  75. package/dist/runtype-tts-entry-NFBVWR7N.js +1 -0
  76. package/dist/runtype-tts.js +1 -1
  77. package/dist/session-actions-ISSKSI66.js +1 -0
  78. package/dist/session-actions.js +1 -0
  79. package/dist/session-reconnect.d.cts +186 -8
  80. package/dist/session-reconnect.d.ts +186 -8
  81. package/dist/smart-dom-reader.cjs +13 -13
  82. package/dist/smart-dom-reader.d.cts +186 -8
  83. package/dist/smart-dom-reader.d.ts +186 -8
  84. package/dist/smart-dom-reader.js +11 -11
  85. package/dist/theme-editor-preview.cjs +116 -98
  86. package/dist/theme-editor-preview.d.cts +188 -8
  87. package/dist/theme-editor-preview.d.ts +188 -8
  88. package/dist/theme-editor-preview.js +49 -54
  89. package/dist/theme-editor.cjs +2 -2
  90. package/dist/theme-editor.d.cts +187 -23
  91. package/dist/theme-editor.d.ts +187 -23
  92. package/dist/theme-editor.js +2 -2
  93. package/dist/theme-reference.d.cts +14 -0
  94. package/dist/theme-reference.d.ts +14 -0
  95. package/dist/ui-extras-entry-WAYFKVNW.js +3 -0
  96. package/dist/ui-extras.js +72 -0
  97. package/dist/voice-runtime-XLU6YK2N.js +17 -0
  98. package/dist/voice-runtime.cjs +17 -1
  99. package/dist/voice-runtime.d.cts +11656 -232
  100. package/dist/voice-runtime.d.ts +11656 -232
  101. package/dist/voice-runtime.js +17 -1
  102. package/dist/voice-worklet-player.cjs +19 -4
  103. package/dist/voice-worklet-player.d.cts +9 -10
  104. package/dist/voice-worklet-player.d.ts +9 -10
  105. package/dist/voice-worklet-player.js +19 -4
  106. package/dist/webmcp-polyfill.js +1 -1
  107. package/dist/webmcp-runtime-V6ZWW3PI.js +6 -0
  108. package/dist/webmcp-runtime.cjs +2 -2
  109. package/dist/webmcp-runtime.d.cts +1 -33
  110. package/dist/webmcp-runtime.d.ts +1 -33
  111. package/dist/webmcp-runtime.js +2 -2
  112. package/dist/widget.css +1 -1
  113. package/package.json +11 -5
  114. package/src/approval-paused-tool-settle.test.ts +325 -0
  115. package/src/client-approve.test.ts +311 -0
  116. package/src/client-history-eager.ts +9 -0
  117. package/src/client-history-loader.ts +23 -0
  118. package/src/client-history.ts +579 -0
  119. package/src/client-resume.ts +177 -0
  120. package/src/client-stream-eager.ts +12 -0
  121. package/src/client-stream-loader.ts +25 -0
  122. package/src/client-stream.ts +1880 -0
  123. package/src/client.test.ts +31 -1
  124. package/src/client.ts +293 -2607
  125. package/src/components/approval-actions.test.ts +27 -0
  126. package/src/components/approval-actions.ts +27 -3
  127. package/src/components/message-bubble.test.ts +19 -0
  128. package/src/components/message-bubble.ts +2 -0
  129. package/src/components/registry.ts +6 -6
  130. package/src/components/tool-bubble.test.ts +9 -0
  131. package/src/components/tool-bubble.ts +1 -0
  132. package/src/history-shell-bundle.test.ts +54 -0
  133. package/src/history-shell-eager.ts +12 -0
  134. package/src/history-shell-loader.ts +27 -0
  135. package/src/history-shell.ts +2362 -0
  136. package/src/history-view-loader.ts +2 -0
  137. package/src/history-view.ts +3 -0
  138. package/src/index-core.ts +6 -0
  139. package/src/index-global.ts +90 -248
  140. package/src/index.ts +13 -0
  141. package/src/install.ts +6 -4
  142. package/src/internal/runtype-history-provider.test.ts +1 -0
  143. package/src/internal/runtype-history-provider.ts +28 -13
  144. package/src/plugins/registry.ts +8 -8
  145. package/src/session-actions-chunk.test.ts +55 -0
  146. package/src/session-actions-eager.ts +11 -0
  147. package/src/session-actions-loader.ts +37 -0
  148. package/src/session-actions.ts +909 -0
  149. package/src/session-history.test.ts +3 -1
  150. package/src/session.ts +895 -1538
  151. package/src/session.voice.test.ts +1171 -5
  152. package/src/styles/widget.css +58 -0
  153. package/src/theme-editor/state.ts +91 -91
  154. package/src/types.ts +204 -5
  155. package/src/ui-ask-user-sheet.ts +382 -0
  156. package/src/ui-extras-eager.ts +10 -0
  157. package/src/ui-extras-entry.ts +9 -0
  158. package/src/ui-extras-loader.ts +26 -0
  159. package/src/ui.artifact-rail-resize.test.ts +2 -1
  160. package/src/ui.ask-user-chunk.test.ts +93 -0
  161. package/src/ui.history-chunk.test.ts +2 -1
  162. package/src/ui.history-config-provider.test.ts +2 -1
  163. package/src/ui.history-confirm-fallback.test.ts +142 -0
  164. package/src/ui.history-controller.test.ts +2 -1
  165. package/src/ui.history-lifecycle.test.ts +2 -1
  166. package/src/ui.history-render-hooks.test.ts +2 -1
  167. package/src/ui.history-shell.test.ts +2 -1
  168. package/src/ui.rail-overlay.test.ts +2 -1
  169. package/src/ui.rail-resize.test.ts +2 -1
  170. package/src/ui.rail-trigger-pending.test.ts +2 -1
  171. package/src/ui.ts +340 -2770
  172. package/src/utils/attachment-manager.ts +67 -67
  173. package/src/utils/constants.ts +3 -0
  174. package/src/utils/context-mention-controller.ts +323 -323
  175. package/src/utils/context-mention-manager.ts +40 -40
  176. package/src/utils/context-mention-orchestrator.ts +28 -0
  177. package/src/utils/event-stream-buffer.ts +50 -50
  178. package/src/utils/event-stream-store.ts +43 -43
  179. package/src/utils/throughput-tracker.ts +34 -34
  180. package/src/utils/virtual-scroller.ts +67 -67
  181. package/src/utils/visitor-store.test.ts +50 -0
  182. package/src/utils/visitor-store.ts +23 -5
  183. package/src/voice/__fixtures__/voice-wire/README.md +1 -0
  184. package/src/voice/__fixtures__/voice-wire/client/cancel.json +3 -0
  185. package/src/voice/__fixtures__/voice-wire/client/context.json +4 -0
  186. package/src/voice/__fixtures__/voice-wire/client/delegation_result.json +6 -0
  187. package/src/voice/__fixtures__/voice-wire/client/delegation_update.json +6 -0
  188. package/src/voice/__fixtures__/voice-wire/client/ping.json +3 -0
  189. package/src/voice/__fixtures__/voice-wire/client/playback_progress.json +5 -0
  190. package/src/voice/__fixtures__/voice-wire/client/start.json +3 -0
  191. package/src/voice/__fixtures__/voice-wire/server/artifact.json +11 -0
  192. package/src/voice/__fixtures__/voice-wire/server/attached.json +4 -0
  193. package/src/voice/__fixtures__/voice-wire/server/audio_clear.json +4 -0
  194. package/src/voice/__fixtures__/voice-wire/server/audio_end.json +3 -0
  195. package/src/voice/__fixtures__/voice-wire/server/delegation_cancelled.json +5 -0
  196. package/src/voice/__fixtures__/voice-wire/server/delegation_completed.json +8 -0
  197. package/src/voice/__fixtures__/voice-wire/server/delegation_started.json +15 -0
  198. package/src/voice/__fixtures__/voice-wire/server/error.json +6 -0
  199. package/src/voice/__fixtures__/voice-wire/server/metrics.json +10 -0
  200. package/src/voice/__fixtures__/voice-wire/server/pong.json +3 -0
  201. package/src/voice/__fixtures__/voice-wire/server/session_config.json +16 -0
  202. package/src/voice/__fixtures__/voice-wire/server/transcript_final.json +7 -0
  203. package/src/voice/__fixtures__/voice-wire/server/transcript_interim.json +4 -0
  204. package/src/voice/__fixtures__/voice-wire/server/transcript_partial.json +6 -0
  205. package/src/voice/__fixtures__/voice-wire/server/transcript_update.json +10 -0
  206. package/src/voice/__fixtures__/voice-wire/server/warning.json +5 -0
  207. package/src/voice/audio-playback-manager.test.ts +57 -0
  208. package/src/voice/audio-playback-manager.ts +120 -98
  209. package/src/voice/browser-voice-provider.ts +37 -37
  210. package/src/voice/fallback-speech-engine.ts +22 -16
  211. package/src/voice/keyed-voice-transcript.ts +314 -0
  212. package/src/voice/mic-state-styles.ts +182 -0
  213. package/src/voice/read-aloud-controller.ts +46 -44
  214. package/src/voice/runtype-speech-engine.ts +35 -33
  215. package/src/voice/runtype-voice-provider.ts +680 -189
  216. package/src/voice/session-voice-wiring.ts +266 -0
  217. package/src/voice/voice-delegation.test.ts +71 -0
  218. package/src/voice/voice-delegation.ts +364 -0
  219. package/src/voice/voice-turn-tracker.ts +6 -6
  220. package/src/voice/voice.test.ts +1060 -8
  221. package/src/voice/worklet-playback-engine.test.ts +81 -0
  222. package/src/voice/worklet-playback-engine.ts +21 -3
  223. package/src/voice-runtime-loader.ts +4 -1
  224. package/src/voice-runtime.ts +7 -0
  225. package/src/webmcp-runtime-entry.ts +41 -39
  226. package/dist/approval-ui-3NMYNXBD.js +0 -1
  227. package/dist/chunk-5EIIHQLQ.js +0 -1
  228. package/dist/chunk-7CO4T5KB.js +0 -1
  229. package/dist/chunk-EFJBUH5F.js +0 -1
  230. package/dist/chunk-R2TMIMDI.js +0 -3
  231. package/dist/chunk-UTVLOTWB.js +0 -9
  232. package/dist/context-mentions-45MODWOY.js +0 -161
  233. package/dist/event-stream-view-GL3ADRY2.js +0 -1
  234. package/dist/runtype-tts-entry-UJAEF7NZ.js +0 -1
  235. package/dist/voice-runtime-7DA7MJH4.js +0 -1
  236. package/dist/webmcp-runtime-JI7T4QYF.js +0 -6
@@ -6724,6 +6724,45 @@ type AgentWidgetVoiceRecognitionConfig = {
6724
6724
  * @default 30000
6725
6725
  */
6726
6726
  attachIdleMs?: number;
6727
+ /**
6728
+ * Full-duplex (speech-to-speech, e.g. GPT-Live) calls: run the turns the
6729
+ * voice model hands off to the agent through this widget's normal chat
6730
+ * pipeline. The spoken request becomes the user message, and the answer
6731
+ * renders as a regular assistant message (streaming, tool and approval
6732
+ * UI, WebMCP page tools, persistence) that the voice model then reads
6733
+ * aloud. Only takes effect when the server supports it (it confirms in
6734
+ * `session_config`); otherwise the agent turn runs on the server and its
6735
+ * spoken reply is transcribed, as before. Set `false` to always keep the
6736
+ * agent turn on the server.
6737
+ * @default true
6738
+ */
6739
+ clientDelegation?: boolean;
6740
+ /**
6741
+ * Full-duplex calls: extra context for the voice model (for example the
6742
+ * page the visitor is on), sent after the chat history as of call start.
6743
+ * The frame goes out once, when the visitor finishes their first
6744
+ * utterance (or at the first agent hand-off). A function is
6745
+ * called at call start and may be async. This text is capped at 4000 characters and the whole frame
6746
+ * (history included) at 8000. Sent only to servers that accept call
6747
+ * context (they announce it in `session_config`).
6748
+ */
6749
+ callContext?: string | (() => string | Promise<string>);
6750
+ /**
6751
+ * Full-duplex calls with client delegation: how long a tool approval
6752
+ * that a spoken request raised may wait before it is declined as
6753
+ * expired (and the voice model says so). Server-side approval gates
6754
+ * keep their own timeout too. Hanging up never declines it: the
6755
+ * approval card in the chat stays usable. Capped at 540000 (9 minutes),
6756
+ * under the server's 10-minute delegation deadline.
6757
+ * @default 300000
6758
+ */
6759
+ approvalTimeoutMs?: number;
6760
+ /**
6761
+ * Speech-to-speech calls: the one-line notice shown in the composer
6762
+ * status area when the call starts. `false` hides it.
6763
+ * @default "You're talking to an AI assistant. Voice is processed by OpenAI."
6764
+ */
6765
+ disclosureText?: string | false;
6727
6766
  /** @deprecated No-op on the realtime path: the server's STT owns turn-taking. */
6728
6767
  pauseDuration?: number;
6729
6768
  /** @deprecated No-op on the realtime path: the server's STT owns turn-taking. */
@@ -6953,6 +6992,13 @@ interface VoicePlaybackEngine {
6953
6992
  onFinished(callback: () => void): void;
6954
6993
  /** Release all audio resources. */
6955
6994
  destroy(): Promise<void> | void;
6995
+ /**
6996
+ * Optional. Speech-to-speech calls stream reply audio with no end-of-stream
6997
+ * marker, so an engine that holds audio below a prebuffer waterline must, while
6998
+ * continuous, release that held tail on its own (e.g. after a short input gap)
6999
+ * instead of waiting for {@link markStreamEnd}. Engines without a prebuffer can omit it.
7000
+ */
7001
+ setContinuousMode?(enabled: boolean): void;
6956
7002
  }
6957
7003
  /**
6958
7004
  * A {@link VoicePlaybackEngine} that also supports pause/resume. Returned by
@@ -6996,14 +7042,23 @@ interface VoiceProvider {
6996
7042
  * Register a callback for incremental transcript updates during a voice turn.
6997
7043
  * `isFinal=false` is a live interim update (user partials, or assistant deltas
6998
7044
  * on providers that stream them); `isFinal=true` finalizes that role's text.
6999
- * On the realtime `runtype` path, interim updates fire for the `user` only and
7000
- * the `assistant` arrives as a single final. Providers with overlapping turns
7001
- * must include the same turnId on user and assistant finals; without IDs,
7002
- * providers must discard cancelled output before emitting the next user final.
7003
- */
7004
- onTranscript?(callback: (role: 'user' | 'assistant', text: string, isFinal: boolean, metadata?: {
7005
- turnId?: string;
7006
- }) => void): void;
7045
+ * On the classic realtime `runtype` path, interim updates fire for the `user`
7046
+ * only and the `assistant` arrives as a single final; without a turnId the
7047
+ * session assumes strictly alternating turns, and providers must discard
7048
+ * cancelled output before emitting the next user final.
7049
+ *
7050
+ * When `metadata.turnId` is present (full-duplex / speech-to-speech, e.g.
7051
+ * GPT-Live), the session reconciles by `(turnId, role)`: each pair owns one
7052
+ * bubble that later updates replace in place, turns may overlap or arrive in
7053
+ * any order, and no empty assistant placeholder is injected. User and
7054
+ * assistant may share a turnId (a late user bubble then renders above its
7055
+ * reply) or use distinct ones. `metadata.startMs` (call-relative ms when the
7056
+ * utterance began) orders a new bubble among the call's other keyed bubbles;
7057
+ * without it bubbles order by first arrival. After a stop, keyed providers
7058
+ * must drop the cancelled reply's output until the server acknowledges the
7059
+ * cancel: the session renders every reply it receives.
7060
+ */
7061
+ onTranscript?(callback: (role: 'user' | 'assistant', text: string, isFinal: boolean, metadata?: VoiceTranscriptMetadata) => void): void;
7007
7062
  /** Register a callback for per-turn latency metrics (realtime path). */
7008
7063
  onMetrics?(callback: (metrics: VoiceMetrics) => void): void;
7009
7064
  /**
@@ -7031,6 +7086,115 @@ interface VoiceProvider {
7031
7086
  * repeatedly; throttle as needed.
7032
7087
  */
7033
7088
  prewarm?(): void;
7089
+ /**
7090
+ * Called by the session once after construction with the chat-side surface
7091
+ * a full-duplex provider uses to hand agent turns to the chat pipeline
7092
+ * ({@link VoiceSessionBridge}). Providers without client delegation omit it.
7093
+ */
7094
+ setSessionBridge?(bridge: VoiceSessionBridge): void;
7095
+ /** The AI-disclosure notice for the live call, if one should show (speech-to-speech). */
7096
+ getDisclosure?(): string | null;
7097
+ }
7098
+ /** Metadata on a {@link VoiceProvider.onTranscript} update. */
7099
+ type VoiceTranscriptMetadata = {
7100
+ /** Groups updates that belong to one utterance bubble (full duplex). */
7101
+ turnId?: string;
7102
+ /** Call-relative ms when the utterance began; orders late bubbles. */
7103
+ startMs?: number;
7104
+ /** Call-relative ms of the latest audio this update covers. */
7105
+ endMs?: number;
7106
+ /**
7107
+ * The bubble only captions speech (see `AgentWidgetMessage.voiceCaption`).
7108
+ * The chat pipeline owns the conversation, as with client delegation.
7109
+ */
7110
+ caption?: boolean;
7111
+ };
7112
+ /** An agent turn a full-duplex voice model handed to the widget. */
7113
+ type VoiceDelegationRequest = {
7114
+ /** The voice model's delegation id (`delegation_started.delegationId`). */
7115
+ delegationId: string;
7116
+ /** What the visitor asked, as the voice model heard it. */
7117
+ userText: string;
7118
+ /**
7119
+ * The user transcript utterances `userText` joins, oldest first (the last
7120
+ * is the one it came from). May be empty.
7121
+ */
7122
+ userUtteranceIds: string[];
7123
+ /** The voice model's view of the conversation it delegated from. */
7124
+ messages: Array<{
7125
+ role: string;
7126
+ content: unknown;
7127
+ }>;
7128
+ };
7129
+ /**
7130
+ * How a delegated turn ended, or that it waits on an approval (contract
7131
+ * Amendment 5). `pending_approval` is the only non-terminal status. Open:
7132
+ * a receiver treats an unknown terminal status as `failed`.
7133
+ * - `completed`: the work ran.
7134
+ * - `denied`: the visitor said no (Deny tap, or a spoken decline).
7135
+ * - `timeout`: the approval lapsed (`approvalTimeoutMs`, or the server's own timeout).
7136
+ * - `cancelled`: replaced by a newer request, or abandoned by the system.
7137
+ * - `failed`: an error.
7138
+ */
7139
+ type VoiceDelegationStatus = 'completed' | 'pending_approval' | 'denied' | 'timeout' | 'cancelled' | 'failed' | (string & {});
7140
+ /** The terminal result of a turn that parked on approvals. */
7141
+ type VoiceDelegationFollowUp = {
7142
+ status: VoiceDelegationStatus;
7143
+ /** What to read aloud (Markdown allowed). May be empty: nothing more to say. */
7144
+ text: string;
7145
+ };
7146
+ /** The delegated turn's answer, sent back for the voice model to read aloud. */
7147
+ type VoiceDelegationResult = {
7148
+ /** `pending_approval` when `followUp` is set; otherwise terminal. */
7149
+ status: VoiceDelegationStatus;
7150
+ /** The assistant text (Markdown allowed). */
7151
+ text: string;
7152
+ /**
7153
+ * `false` when no chat message carries this answer (it is only spoken), so
7154
+ * the voice model's read-back of it stays visible as a caption.
7155
+ * @default true
7156
+ */
7157
+ inChat?: boolean;
7158
+ /**
7159
+ * Set when the turn parked on approvals (`text` then asks for the decision).
7160
+ * Resolves with the terminal result once the visitor decides (or the
7161
+ * approval is replaced, declined by voice, or unanswered for
7162
+ * `approvalTimeoutMs`) and the resumed turn finishes; `null` only when
7163
+ * `signal` aborts first (hang-up, or the server cancelled the delegation).
7164
+ */
7165
+ followUp?: (options: {
7166
+ signal: AbortSignal;
7167
+ approvalTimeoutMs?: number;
7168
+ /** `false`: run only the approval bookkeeping (expiry, supersede); nothing will be read back. @default true */
7169
+ readBack?: boolean;
7170
+ /** The resumed turn stopped on another approval: ask for it too (`text` is its approval script). */
7171
+ onUpdate?: (text: string) => void;
7172
+ }) => Promise<VoiceDelegationFollowUp | null>;
7173
+ };
7174
+ /**
7175
+ * Chat-side surface the session hands a full-duplex provider: the visible
7176
+ * history (for the call-start context) and a way to run a delegated turn
7177
+ * through the normal chat pipeline.
7178
+ */
7179
+ interface VoiceSessionBridge {
7180
+ /** Visible user/assistant messages, oldest first. */
7181
+ getHistory(): Array<{
7182
+ role: 'user' | 'assistant';
7183
+ content: string;
7184
+ }>;
7185
+ /**
7186
+ * Submit the turn as the visitor's message (reusing its transcript bubble)
7187
+ * and resolve with the assistant's final answer once the turn settles.
7188
+ * Waits for any chat turn already in flight first. Never rejects.
7189
+ */
7190
+ runDelegatedTurn(request: VoiceDelegationRequest): Promise<VoiceDelegationResult>;
7191
+ /**
7192
+ * The server dropped this delegation's result (cancelled it, or refused a
7193
+ * late result): its chat answer is no longer spoken, so browser TTS may read it.
7194
+ * `expired`: the server's deadline passed, so its pending approvals are
7195
+ * declined too, as the approval TTL would.
7196
+ */
7197
+ dropDelegation?(delegationId: string, expired?: boolean): void;
7034
7198
  }
7035
7199
  /**
7036
7200
  * Extra context for an approval decision, surfaced to `onDecision` and to the
@@ -9627,6 +9791,11 @@ type AgentWidgetToolCall = {
9627
9791
  startedAt?: number;
9628
9792
  completedAt?: number;
9629
9793
  durationMs?: number;
9794
+ /**
9795
+ * The call paused for an approval that was granted, and the agent re-ran it
9796
+ * as a new tool call: that later call carries the result, this one has none.
9797
+ */
9798
+ superseded?: boolean;
9630
9799
  };
9631
9800
  /**
9632
9801
  * Represents a tool approval request in the chat conversation.
@@ -9648,6 +9817,8 @@ type AgentWidgetApproval = {
9648
9817
  */
9649
9818
  reason?: string;
9650
9819
  parameters?: unknown;
9820
+ /** The paused tool call this approval gates (`approval_start.toolCallId`). */
9821
+ toolCallId?: string;
9651
9822
  resolvedAt?: number;
9652
9823
  };
9653
9824
  type AgentWidgetMessageVariant = "assistant" | "reasoning" | "tool" | "approval";
@@ -9747,6 +9918,13 @@ type AgentWidgetMessage = {
9747
9918
  * }
9748
9919
  */
9749
9920
  voiceProcessing?: boolean;
9921
+ /**
9922
+ * Display-only caption of full-duplex voice speech, such as the voice
9923
+ * model's own words, or something the visitor said that wasn't submitted
9924
+ * as a chat turn. It renders in the transcript but is never sent to the
9925
+ * model as conversation.
9926
+ */
9927
+ voiceCaption?: boolean;
9750
9928
  /**
9751
9929
  * Raw structured payload for this message (e.g., JSON action response).
9752
9930
  * Populated automatically when structured parsers run.
@@ -9977,16 +10155,9 @@ type OnChangeCallback = (path: string, value: unknown) => void;
9977
10155
  /** Headless state management for the theme editor (no DOM, no localStorage, no side effects) */
9978
10156
 
9979
10157
  declare class ThemeEditorState {
10158
+ #private;
9980
10159
  private config;
9981
10160
  private theme;
9982
- private listeners;
9983
- private history;
9984
- private historyIndex;
9985
- private suppressHistory;
9986
- private authoredConfig;
9987
- private authoredTheme;
9988
- private mergeDefaults;
9989
- private snapshotIntent;
9990
10161
  constructor(initialTheme?: DeepPartial<PersonaTheme>, initialConfig?: Partial<AgentWidgetConfig>, options?: {
9991
10162
  mergeDefaults?: boolean;
9992
10163
  });
@@ -10026,13 +10197,6 @@ declare class ThemeEditorState {
10026
10197
  redo(): void;
10027
10198
  exportSnapshot(): ConfiguratorSnapshot;
10028
10199
  onChange(listener: ConfigChangeListener): () => void;
10029
- private recordIntent;
10030
- private rebaseDefaults;
10031
- private syncThemeIntoConfig;
10032
- private notifyListeners;
10033
- private recordHistory;
10034
- private pushHistorySnapshot;
10035
- private restoreSnapshot;
10036
10200
  }
10037
10201
 
10038
10202
  /** Declarative section/field definitions for the theme editor (pure data: no DOM, no render logic) */
@@ -6724,6 +6724,45 @@ type AgentWidgetVoiceRecognitionConfig = {
6724
6724
  * @default 30000
6725
6725
  */
6726
6726
  attachIdleMs?: number;
6727
+ /**
6728
+ * Full-duplex (speech-to-speech, e.g. GPT-Live) calls: run the turns the
6729
+ * voice model hands off to the agent through this widget's normal chat
6730
+ * pipeline. The spoken request becomes the user message, and the answer
6731
+ * renders as a regular assistant message (streaming, tool and approval
6732
+ * UI, WebMCP page tools, persistence) that the voice model then reads
6733
+ * aloud. Only takes effect when the server supports it (it confirms in
6734
+ * `session_config`); otherwise the agent turn runs on the server and its
6735
+ * spoken reply is transcribed, as before. Set `false` to always keep the
6736
+ * agent turn on the server.
6737
+ * @default true
6738
+ */
6739
+ clientDelegation?: boolean;
6740
+ /**
6741
+ * Full-duplex calls: extra context for the voice model (for example the
6742
+ * page the visitor is on), sent after the chat history as of call start.
6743
+ * The frame goes out once, when the visitor finishes their first
6744
+ * utterance (or at the first agent hand-off). A function is
6745
+ * called at call start and may be async. This text is capped at 4000 characters and the whole frame
6746
+ * (history included) at 8000. Sent only to servers that accept call
6747
+ * context (they announce it in `session_config`).
6748
+ */
6749
+ callContext?: string | (() => string | Promise<string>);
6750
+ /**
6751
+ * Full-duplex calls with client delegation: how long a tool approval
6752
+ * that a spoken request raised may wait before it is declined as
6753
+ * expired (and the voice model says so). Server-side approval gates
6754
+ * keep their own timeout too. Hanging up never declines it: the
6755
+ * approval card in the chat stays usable. Capped at 540000 (9 minutes),
6756
+ * under the server's 10-minute delegation deadline.
6757
+ * @default 300000
6758
+ */
6759
+ approvalTimeoutMs?: number;
6760
+ /**
6761
+ * Speech-to-speech calls: the one-line notice shown in the composer
6762
+ * status area when the call starts. `false` hides it.
6763
+ * @default "You're talking to an AI assistant. Voice is processed by OpenAI."
6764
+ */
6765
+ disclosureText?: string | false;
6727
6766
  /** @deprecated No-op on the realtime path: the server's STT owns turn-taking. */
6728
6767
  pauseDuration?: number;
6729
6768
  /** @deprecated No-op on the realtime path: the server's STT owns turn-taking. */
@@ -6953,6 +6992,13 @@ interface VoicePlaybackEngine {
6953
6992
  onFinished(callback: () => void): void;
6954
6993
  /** Release all audio resources. */
6955
6994
  destroy(): Promise<void> | void;
6995
+ /**
6996
+ * Optional. Speech-to-speech calls stream reply audio with no end-of-stream
6997
+ * marker, so an engine that holds audio below a prebuffer waterline must, while
6998
+ * continuous, release that held tail on its own (e.g. after a short input gap)
6999
+ * instead of waiting for {@link markStreamEnd}. Engines without a prebuffer can omit it.
7000
+ */
7001
+ setContinuousMode?(enabled: boolean): void;
6956
7002
  }
6957
7003
  /**
6958
7004
  * A {@link VoicePlaybackEngine} that also supports pause/resume. Returned by
@@ -6996,14 +7042,23 @@ interface VoiceProvider {
6996
7042
  * Register a callback for incremental transcript updates during a voice turn.
6997
7043
  * `isFinal=false` is a live interim update (user partials, or assistant deltas
6998
7044
  * on providers that stream them); `isFinal=true` finalizes that role's text.
6999
- * On the realtime `runtype` path, interim updates fire for the `user` only and
7000
- * the `assistant` arrives as a single final. Providers with overlapping turns
7001
- * must include the same turnId on user and assistant finals; without IDs,
7002
- * providers must discard cancelled output before emitting the next user final.
7003
- */
7004
- onTranscript?(callback: (role: 'user' | 'assistant', text: string, isFinal: boolean, metadata?: {
7005
- turnId?: string;
7006
- }) => void): void;
7045
+ * On the classic realtime `runtype` path, interim updates fire for the `user`
7046
+ * only and the `assistant` arrives as a single final; without a turnId the
7047
+ * session assumes strictly alternating turns, and providers must discard
7048
+ * cancelled output before emitting the next user final.
7049
+ *
7050
+ * When `metadata.turnId` is present (full-duplex / speech-to-speech, e.g.
7051
+ * GPT-Live), the session reconciles by `(turnId, role)`: each pair owns one
7052
+ * bubble that later updates replace in place, turns may overlap or arrive in
7053
+ * any order, and no empty assistant placeholder is injected. User and
7054
+ * assistant may share a turnId (a late user bubble then renders above its
7055
+ * reply) or use distinct ones. `metadata.startMs` (call-relative ms when the
7056
+ * utterance began) orders a new bubble among the call's other keyed bubbles;
7057
+ * without it bubbles order by first arrival. After a stop, keyed providers
7058
+ * must drop the cancelled reply's output until the server acknowledges the
7059
+ * cancel: the session renders every reply it receives.
7060
+ */
7061
+ onTranscript?(callback: (role: 'user' | 'assistant', text: string, isFinal: boolean, metadata?: VoiceTranscriptMetadata) => void): void;
7007
7062
  /** Register a callback for per-turn latency metrics (realtime path). */
7008
7063
  onMetrics?(callback: (metrics: VoiceMetrics) => void): void;
7009
7064
  /**
@@ -7031,6 +7086,115 @@ interface VoiceProvider {
7031
7086
  * repeatedly; throttle as needed.
7032
7087
  */
7033
7088
  prewarm?(): void;
7089
+ /**
7090
+ * Called by the session once after construction with the chat-side surface
7091
+ * a full-duplex provider uses to hand agent turns to the chat pipeline
7092
+ * ({@link VoiceSessionBridge}). Providers without client delegation omit it.
7093
+ */
7094
+ setSessionBridge?(bridge: VoiceSessionBridge): void;
7095
+ /** The AI-disclosure notice for the live call, if one should show (speech-to-speech). */
7096
+ getDisclosure?(): string | null;
7097
+ }
7098
+ /** Metadata on a {@link VoiceProvider.onTranscript} update. */
7099
+ type VoiceTranscriptMetadata = {
7100
+ /** Groups updates that belong to one utterance bubble (full duplex). */
7101
+ turnId?: string;
7102
+ /** Call-relative ms when the utterance began; orders late bubbles. */
7103
+ startMs?: number;
7104
+ /** Call-relative ms of the latest audio this update covers. */
7105
+ endMs?: number;
7106
+ /**
7107
+ * The bubble only captions speech (see `AgentWidgetMessage.voiceCaption`).
7108
+ * The chat pipeline owns the conversation, as with client delegation.
7109
+ */
7110
+ caption?: boolean;
7111
+ };
7112
+ /** An agent turn a full-duplex voice model handed to the widget. */
7113
+ type VoiceDelegationRequest = {
7114
+ /** The voice model's delegation id (`delegation_started.delegationId`). */
7115
+ delegationId: string;
7116
+ /** What the visitor asked, as the voice model heard it. */
7117
+ userText: string;
7118
+ /**
7119
+ * The user transcript utterances `userText` joins, oldest first (the last
7120
+ * is the one it came from). May be empty.
7121
+ */
7122
+ userUtteranceIds: string[];
7123
+ /** The voice model's view of the conversation it delegated from. */
7124
+ messages: Array<{
7125
+ role: string;
7126
+ content: unknown;
7127
+ }>;
7128
+ };
7129
+ /**
7130
+ * How a delegated turn ended, or that it waits on an approval (contract
7131
+ * Amendment 5). `pending_approval` is the only non-terminal status. Open:
7132
+ * a receiver treats an unknown terminal status as `failed`.
7133
+ * - `completed`: the work ran.
7134
+ * - `denied`: the visitor said no (Deny tap, or a spoken decline).
7135
+ * - `timeout`: the approval lapsed (`approvalTimeoutMs`, or the server's own timeout).
7136
+ * - `cancelled`: replaced by a newer request, or abandoned by the system.
7137
+ * - `failed`: an error.
7138
+ */
7139
+ type VoiceDelegationStatus = 'completed' | 'pending_approval' | 'denied' | 'timeout' | 'cancelled' | 'failed' | (string & {});
7140
+ /** The terminal result of a turn that parked on approvals. */
7141
+ type VoiceDelegationFollowUp = {
7142
+ status: VoiceDelegationStatus;
7143
+ /** What to read aloud (Markdown allowed). May be empty: nothing more to say. */
7144
+ text: string;
7145
+ };
7146
+ /** The delegated turn's answer, sent back for the voice model to read aloud. */
7147
+ type VoiceDelegationResult = {
7148
+ /** `pending_approval` when `followUp` is set; otherwise terminal. */
7149
+ status: VoiceDelegationStatus;
7150
+ /** The assistant text (Markdown allowed). */
7151
+ text: string;
7152
+ /**
7153
+ * `false` when no chat message carries this answer (it is only spoken), so
7154
+ * the voice model's read-back of it stays visible as a caption.
7155
+ * @default true
7156
+ */
7157
+ inChat?: boolean;
7158
+ /**
7159
+ * Set when the turn parked on approvals (`text` then asks for the decision).
7160
+ * Resolves with the terminal result once the visitor decides (or the
7161
+ * approval is replaced, declined by voice, or unanswered for
7162
+ * `approvalTimeoutMs`) and the resumed turn finishes; `null` only when
7163
+ * `signal` aborts first (hang-up, or the server cancelled the delegation).
7164
+ */
7165
+ followUp?: (options: {
7166
+ signal: AbortSignal;
7167
+ approvalTimeoutMs?: number;
7168
+ /** `false`: run only the approval bookkeeping (expiry, supersede); nothing will be read back. @default true */
7169
+ readBack?: boolean;
7170
+ /** The resumed turn stopped on another approval: ask for it too (`text` is its approval script). */
7171
+ onUpdate?: (text: string) => void;
7172
+ }) => Promise<VoiceDelegationFollowUp | null>;
7173
+ };
7174
+ /**
7175
+ * Chat-side surface the session hands a full-duplex provider: the visible
7176
+ * history (for the call-start context) and a way to run a delegated turn
7177
+ * through the normal chat pipeline.
7178
+ */
7179
+ interface VoiceSessionBridge {
7180
+ /** Visible user/assistant messages, oldest first. */
7181
+ getHistory(): Array<{
7182
+ role: 'user' | 'assistant';
7183
+ content: string;
7184
+ }>;
7185
+ /**
7186
+ * Submit the turn as the visitor's message (reusing its transcript bubble)
7187
+ * and resolve with the assistant's final answer once the turn settles.
7188
+ * Waits for any chat turn already in flight first. Never rejects.
7189
+ */
7190
+ runDelegatedTurn(request: VoiceDelegationRequest): Promise<VoiceDelegationResult>;
7191
+ /**
7192
+ * The server dropped this delegation's result (cancelled it, or refused a
7193
+ * late result): its chat answer is no longer spoken, so browser TTS may read it.
7194
+ * `expired`: the server's deadline passed, so its pending approvals are
7195
+ * declined too, as the approval TTL would.
7196
+ */
7197
+ dropDelegation?(delegationId: string, expired?: boolean): void;
7034
7198
  }
7035
7199
  /**
7036
7200
  * Extra context for an approval decision, surfaced to `onDecision` and to the
@@ -9627,6 +9791,11 @@ type AgentWidgetToolCall = {
9627
9791
  startedAt?: number;
9628
9792
  completedAt?: number;
9629
9793
  durationMs?: number;
9794
+ /**
9795
+ * The call paused for an approval that was granted, and the agent re-ran it
9796
+ * as a new tool call: that later call carries the result, this one has none.
9797
+ */
9798
+ superseded?: boolean;
9630
9799
  };
9631
9800
  /**
9632
9801
  * Represents a tool approval request in the chat conversation.
@@ -9648,6 +9817,8 @@ type AgentWidgetApproval = {
9648
9817
  */
9649
9818
  reason?: string;
9650
9819
  parameters?: unknown;
9820
+ /** The paused tool call this approval gates (`approval_start.toolCallId`). */
9821
+ toolCallId?: string;
9651
9822
  resolvedAt?: number;
9652
9823
  };
9653
9824
  type AgentWidgetMessageVariant = "assistant" | "reasoning" | "tool" | "approval";
@@ -9747,6 +9918,13 @@ type AgentWidgetMessage = {
9747
9918
  * }
9748
9919
  */
9749
9920
  voiceProcessing?: boolean;
9921
+ /**
9922
+ * Display-only caption of full-duplex voice speech, such as the voice
9923
+ * model's own words, or something the visitor said that wasn't submitted
9924
+ * as a chat turn. It renders in the transcript but is never sent to the
9925
+ * model as conversation.
9926
+ */
9927
+ voiceCaption?: boolean;
9750
9928
  /**
9751
9929
  * Raw structured payload for this message (e.g., JSON action response).
9752
9930
  * Populated automatically when structured parsers run.
@@ -9977,16 +10155,9 @@ type OnChangeCallback = (path: string, value: unknown) => void;
9977
10155
  /** Headless state management for the theme editor (no DOM, no localStorage, no side effects) */
9978
10156
 
9979
10157
  declare class ThemeEditorState {
10158
+ #private;
9980
10159
  private config;
9981
10160
  private theme;
9982
- private listeners;
9983
- private history;
9984
- private historyIndex;
9985
- private suppressHistory;
9986
- private authoredConfig;
9987
- private authoredTheme;
9988
- private mergeDefaults;
9989
- private snapshotIntent;
9990
10161
  constructor(initialTheme?: DeepPartial<PersonaTheme>, initialConfig?: Partial<AgentWidgetConfig>, options?: {
9991
10162
  mergeDefaults?: boolean;
9992
10163
  });
@@ -10026,13 +10197,6 @@ declare class ThemeEditorState {
10026
10197
  redo(): void;
10027
10198
  exportSnapshot(): ConfiguratorSnapshot;
10028
10199
  onChange(listener: ConfigChangeListener): () => void;
10029
- private recordIntent;
10030
- private rebaseDefaults;
10031
- private syncThemeIntoConfig;
10032
- private notifyListeners;
10033
- private recordHistory;
10034
- private pushHistorySnapshot;
10035
- private restoreSnapshot;
10036
10200
  }
10037
10201
 
10038
10202
  /** Declarative section/field definitions for the theme editor (pure data: no DOM, no render logic) */