@runtypelabs/persona 4.23.2 → 4.25.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.
Files changed (166) 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-CI7OckWI.d.cts → types-Db61aI9J.d.cts} +2 -0
  4. package/dist/animations/{types-CI7OckWI.d.ts → types-Db61aI9J.d.ts} +2 -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 +2 -0
  8. package/dist/animations-extra.d.ts +2 -0
  9. package/dist/approval-ui-3NMYNXBD.js +1 -0
  10. package/dist/approval-ui.cjs +2 -2
  11. package/dist/approval-ui.d.cts +278 -37
  12. package/dist/approval-ui.d.ts +278 -37
  13. package/dist/approval-ui.js +2 -2
  14. package/dist/{artifacts-ui-F4N6VMKF.js → artifacts-ui-IGB5YKLO.js} +4 -4
  15. package/dist/artifacts-ui.d.cts +273 -25
  16. package/dist/artifacts-ui.d.ts +273 -25
  17. package/dist/{chunk-NIKYKSNZ.js → chunk-7CO4T5KB.js} +1 -1
  18. package/dist/codegen.cjs +11 -11
  19. package/dist/codegen.js +13 -13
  20. package/dist/context-mentions.d.cts +273 -25
  21. package/dist/context-mentions.d.ts +273 -25
  22. package/dist/event-stream-view.d.cts +273 -25
  23. package/dist/event-stream-view.d.ts +273 -25
  24. package/dist/forms-ui.d.cts +319 -27
  25. package/dist/forms-ui.d.ts +319 -27
  26. package/dist/history-view.d.cts +2 -0
  27. package/dist/history-view.d.ts +2 -0
  28. package/dist/index.cjs +70 -69
  29. package/dist/index.cjs.map +1 -1
  30. package/dist/index.d.cts +344 -39
  31. package/dist/index.d.ts +344 -39
  32. package/dist/index.global.js +57 -54
  33. package/dist/index.global.js.map +1 -1
  34. package/dist/index.js +70 -69
  35. package/dist/index.js.map +1 -1
  36. package/dist/install.global.js +1 -1
  37. package/dist/install.global.js.map +1 -1
  38. package/dist/launcher.global.js +2 -2
  39. package/dist/launcher.global.js.map +1 -1
  40. package/dist/session-reconnect.d.cts +273 -25
  41. package/dist/session-reconnect.d.ts +273 -25
  42. package/dist/smart-dom-reader.d.cts +273 -25
  43. package/dist/smart-dom-reader.d.ts +273 -25
  44. package/dist/theme-editor-preview.cjs +74 -73
  45. package/dist/theme-editor-preview.d.cts +280 -25
  46. package/dist/theme-editor-preview.d.ts +280 -25
  47. package/dist/theme-editor-preview.js +51 -50
  48. package/dist/theme-editor.cjs +10 -10
  49. package/dist/theme-editor.d.cts +293 -27
  50. package/dist/theme-editor.d.ts +293 -27
  51. package/dist/theme-editor.js +10 -10
  52. package/dist/theme-reference.cjs +1 -1
  53. package/dist/theme-reference.d.cts +1522 -11
  54. package/dist/theme-reference.d.ts +1522 -11
  55. package/dist/theme-reference.js +1 -1
  56. package/dist/voice-runtime-7DA7MJH4.js +1 -0
  57. package/dist/voice-runtime.cjs +1 -1
  58. package/dist/voice-runtime.d.cts +33 -0
  59. package/dist/voice-runtime.d.ts +33 -0
  60. package/dist/voice-runtime.js +1 -1
  61. package/dist/widget.css +1 -1
  62. package/package.json +3 -2
  63. package/src/__fixtures__/defaults-parity.v4.json +776 -0
  64. package/src/approval-ui-entry.ts +0 -1
  65. package/src/approval-ui-loader.ts +5 -4
  66. package/src/approval-ui.ts +0 -1
  67. package/src/client-identity-proof.test.ts +193 -0
  68. package/src/client-session-warm.test.ts +216 -0
  69. package/src/client-visitor-history.test.ts +6 -0
  70. package/src/client.ts +122 -30
  71. package/src/codegen.test.ts +24 -0
  72. package/src/components/activity-row.test.ts +100 -0
  73. package/src/components/activity-row.ts +136 -0
  74. package/src/components/approval-actions.test.ts +8 -5
  75. package/src/components/approval-actions.ts +19 -6
  76. package/src/components/approval-bubble.test.ts +56 -9
  77. package/src/components/approval-bubble.ts +36 -41
  78. package/src/components/composer-builder.ts +5 -2
  79. package/src/components/composer-parts.ts +10 -2
  80. package/src/components/header-builder.test.ts +32 -0
  81. package/src/components/header-builder.ts +7 -4
  82. package/src/components/header-layouts.test.ts +12 -0
  83. package/src/components/header-layouts.ts +3 -2
  84. package/src/components/launcher.ts +11 -2
  85. package/src/components/message-bubble.test.ts +22 -0
  86. package/src/components/message-bubble.ts +7 -3
  87. package/src/components/panel.test.ts +52 -1
  88. package/src/components/panel.ts +47 -8
  89. package/src/components/pill-composer-builder.test.ts +2 -0
  90. package/src/components/pill-composer-builder.ts +0 -1
  91. package/src/components/reasoning-bubble.ts +29 -17
  92. package/src/components/suggestions.test.ts +1 -0
  93. package/src/components/suggestions.ts +0 -16
  94. package/src/components/tool-bubble.ts +131 -114
  95. package/src/components/tool-details.test.ts +87 -0
  96. package/src/components/tool-details.ts +102 -0
  97. package/src/components/welcome.test.ts +8 -0
  98. package/src/components/welcome.ts +4 -2
  99. package/src/defaults-parity.test.ts +158 -0
  100. package/src/defaults.test.ts +69 -0
  101. package/src/defaults.ts +128 -49
  102. package/src/generated/runtype-openapi-contract.ts +2 -2
  103. package/src/index-core.ts +4 -0
  104. package/src/install.test.ts +24 -0
  105. package/src/install.ts +3 -1
  106. package/src/launcher-global.ts +2 -1
  107. package/src/launcher-variants.test.ts +52 -0
  108. package/src/runtime/init-update-reset.test.ts +21 -0
  109. package/src/session.ts +59 -7
  110. package/src/session.voice.test.ts +72 -1
  111. package/src/styles/widget-styles.test.ts +19 -0
  112. package/src/styles/widget.css +295 -23
  113. package/src/theme-editor/index.ts +2 -0
  114. package/src/theme-editor/preview-utils.test.ts +8 -0
  115. package/src/theme-editor/preview-utils.ts +7 -3
  116. package/src/theme-editor/sections.test.ts +31 -0
  117. package/src/theme-editor/sections.ts +55 -1
  118. package/src/theme-editor/state-preferences.test.ts +49 -0
  119. package/src/theme-editor/state.ts +73 -15
  120. package/src/theme-reference.test.ts +20 -0
  121. package/src/theme-reference.ts +11 -5
  122. package/src/tool-call-display-defaults.test.ts +33 -1
  123. package/src/types/theme.ts +80 -3
  124. package/src/types.ts +207 -22
  125. package/src/ui.activity-row.test.ts +91 -0
  126. package/src/ui.approval-plugin.test.ts +63 -0
  127. package/src/ui.composer-compact.test.ts +24 -2
  128. package/src/ui.composer-placement.test.ts +23 -0
  129. package/src/ui.detached-panel.test.ts +33 -6
  130. package/src/ui.docked.test.ts +19 -0
  131. package/src/ui.header-update-stability.test.ts +25 -0
  132. package/src/ui.identity-proof.test.ts +58 -0
  133. package/src/ui.launcher-teaser.test.ts +25 -0
  134. package/src/ui.message-width.test.ts +17 -2
  135. package/src/ui.reasoning-display.test.ts +92 -0
  136. package/src/ui.rebuild-composer.test.ts +20 -3
  137. package/src/ui.scroll.test.ts +32 -0
  138. package/src/ui.session-init.test.ts +312 -0
  139. package/src/ui.status-indicator.test.ts +82 -0
  140. package/src/ui.suggest-replies.test.ts +11 -0
  141. package/src/ui.ts +422 -74
  142. package/src/ui.v5-defaults.test.ts +144 -0
  143. package/src/ui.voice-prewarm.test.ts +222 -0
  144. package/src/ui.welcome.test.ts +92 -3
  145. package/src/utils/__snapshots__/tokens-parity.test.ts.snap +811 -140
  146. package/src/utils/code-generators.ts +14 -0
  147. package/src/utils/composer-compact.test.ts +0 -2
  148. package/src/utils/composer-compact.ts +2 -4
  149. package/src/utils/composer-placement.ts +2 -3
  150. package/src/utils/config-merge.test.ts +81 -5
  151. package/src/utils/config-merge.ts +13 -3
  152. package/src/utils/defaults-provenance.ts +67 -0
  153. package/src/utils/dock.ts +7 -1
  154. package/src/utils/launcher-variant.ts +16 -0
  155. package/src/utils/panel-config.ts +97 -0
  156. package/src/utils/status-indicator.ts +39 -0
  157. package/src/utils/theme.test.ts +182 -0
  158. package/src/utils/theme.ts +131 -18
  159. package/src/utils/tokens.test.ts +122 -1
  160. package/src/utils/tokens.ts +177 -17
  161. package/src/voice/runtype-voice-provider.ts +238 -27
  162. package/src/voice/voice.test.ts +272 -2
  163. package/src/welcome.test.ts +23 -0
  164. package/src/welcome.ts +16 -9
  165. package/dist/approval-ui-K7R5Q5OC.js +0 -1
  166. package/dist/voice-runtime-EFR3R5ES.js +0 -1
@@ -21,6 +21,7 @@ interface ResolvedWelcomeConfig {
21
21
  * Optional on the interface, always populated by `resolveWelcomeConfig`:
22
22
  * a plugin literal built against an older minor must still type-check.
23
23
  */
24
+ layout?: "top" | "centered";
24
25
  anchor?: AgentWidgetWelcomeAnchor;
25
26
  /** Percentage string; validated, falls back to "44%". */
26
27
  anchorComposerTop?: string;
@@ -792,6 +793,8 @@ interface InputTokens extends ComponentTokenSet {
792
793
  backdropFilter?: string;
793
794
  }
794
795
  interface LauncherTokens extends ComponentTokenSet {
796
+ /** Distance from the viewport edges. Circle default: 20px; pill: 24px. */
797
+ offset?: string;
795
798
  size: string;
796
799
  iconSize: string;
797
800
  shadow: TokenReference<'shadow'>;
@@ -814,6 +817,15 @@ interface PanelTokens extends ComponentTokenSet {
814
817
  inset?: string;
815
818
  /** Background of the region revealed behind a detached panel. */
816
819
  canvasBackground?: string;
820
+ /** Chrome defaults by rendered panel mode. */
821
+ modes?: Partial<Record<'floating' | 'inline' | 'sidebar' | 'docked' | 'mobile', {
822
+ /** Full border shorthand (for example, `"1px solid var(--persona-border)"`). */
823
+ border?: string;
824
+ /** Box-shadow token reference or raw CSS shadow. */
825
+ shadow?: string;
826
+ /** Corner radius token reference or raw CSS radius. */
827
+ borderRadius?: TokenReference<'radius'>;
828
+ }>>;
817
829
  }
818
830
  /** Per-element text styling shared by themable text surfaces. */
819
831
  interface TextStyleTokens {
@@ -840,10 +852,16 @@ interface HeaderTokens extends ComponentTokenSet {
840
852
  */
841
853
  border?: TokenReference<'color'>;
842
854
  borderRadius: TokenReference<'radius'>;
855
+ /** Standard-header padding. @default "20px 24px" */
856
+ padding?: string;
857
+ /** Minimal-header padding. Explicitly wins over `padding`. @default "16px 24px" */
858
+ minimalPadding?: string;
843
859
  /** Background of the rounded avatar tile next to the title (Lucide / emoji / image). */
844
860
  iconBackground: TokenReference<'color'>;
845
861
  /** Foreground (glyph stroke or emoji text) on the header avatar tile. */
846
862
  iconForeground: TokenReference<'color'>;
863
+ /** Header identity glyph size as a fraction of its icon box. @default "0.6" */
864
+ iconScale?: string;
847
865
  /**
848
866
  * Legacy alias of `title.color`; `title.color` wins when both are set.
849
867
  * Unset, the title takes `foreground`, then the primary color.
@@ -882,6 +900,14 @@ interface HeaderTokens extends ComponentTokenSet {
882
900
  * sibling. @default "1.5"
883
901
  */
884
902
  controlStrokeWidth?: string;
903
+ /** Header control corner radius. Per-control radius overrides win. */
904
+ controlBorderRadius?: string;
905
+ /** Default control hover/focus fill. Explicit button backgrounds win. */
906
+ controlHoverBackground?: TokenReference<'color'>;
907
+ /** Default control hover/focus icon color. Explicit button colors win. */
908
+ controlHoverForeground?: TokenReference<'color'>;
909
+ /** Keyboard focus outline; unset preserves the browser default. */
910
+ controlFocusOutline?: string;
885
911
  /** Box-shadow on the header (e.g., a fade shadow to replace the default border). */
886
912
  shadow?: string;
887
913
  /** Override the header bottom border (e.g., `none`). */
@@ -1056,6 +1082,12 @@ interface MessageGeometryTokens {
1056
1082
  lineHeight?: string;
1057
1083
  }
1058
1084
  interface MessageTokens {
1085
+ /** Height of the optional transcript top fade. Default 18px. */
1086
+ topFadeHeight?: string;
1087
+ /** Vertical gap between transcript turns. @default "12px" */
1088
+ gap?: string;
1089
+ /** Gap between turns in fullscreen mode; falls back to `gap`. */
1090
+ fullscreenGap?: string;
1059
1091
  user: MessageGeometryTokens & {
1060
1092
  background: TokenReference<'color'>;
1061
1093
  text: TokenReference<'color'>;
@@ -1069,6 +1101,8 @@ interface MessageTokens {
1069
1101
  borderRadius: TokenReference<'radius'>;
1070
1102
  /** Assistant bubble border color (CSS color). */
1071
1103
  border?: TokenReference<'color'>;
1104
+ /** Border width; set to 0px for a flat assistant response. @default "1px" */
1105
+ borderWidth?: string;
1072
1106
  /** Assistant bubble box-shadow (token ref or raw CSS, e.g. `none`). */
1073
1107
  shadow?: string;
1074
1108
  };
@@ -1187,12 +1221,40 @@ interface AttachmentTokens {
1187
1221
  };
1188
1222
  }
1189
1223
  /** Tool-call row chrome (collapsible tool bubbles). */
1190
- interface ToolBubbleTokens {
1224
+ interface ActivityTokens {
1225
+ /** Minimum activity row height. */
1226
+ rowHeight?: string;
1227
+ /** Group child indentation; falls back to indent when unset. V5: 0px. */
1228
+ groupIndent?: string;
1229
+ /** Extra vertical gap between grouped rows. V5: 0px. */
1230
+ groupGap?: string;
1231
+ /** Padding around expanded group children. V5: 0px. */
1232
+ groupPadding?: string;
1233
+ /** Gap between consecutive activity entries. V5: 0px. */
1234
+ transcriptGap?: string;
1235
+ /** Gap from activity to an assistant response. V5: 12px. */
1236
+ responseGap?: string;
1237
+ /** Expanded body padding. V5: 4px 0. */
1238
+ bodyPadding?: string;
1239
+ /** Expanded reasoning text size. V5: 13px. */
1240
+ bodySize?: string;
1241
+ /** Expanded reasoning line height. V5: 1.5. */
1242
+ bodyLineHeight?: string;
1243
+ /** Expanded reasoning font weight. V5: 400. */
1244
+ bodyFontWeight?: string;
1245
+ /** Gap between expanded detail sections. V5: 8px. */
1246
+ sectionGap?: string;
1247
+ labelSize?: string;
1248
+ iconSize?: string;
1249
+ indent?: string;
1250
+ bodySurface?: TokenReference<'color'>;
1251
+ }
1252
+ interface ToolBubbleTokens extends ActivityTokens {
1191
1253
  /** Box-shadow for tool bubbles (token ref or raw CSS, e.g. `none`). */
1192
1254
  shadow: string;
1193
1255
  }
1194
1256
  /** Reasoning / “thinking” row chrome. */
1195
- interface ReasoningBubbleTokens {
1257
+ interface ReasoningBubbleTokens extends ActivityTokens {
1196
1258
  shadow: string;
1197
1259
  }
1198
1260
  /** One event-stream badge chip: fill + text pair. The chip border derives
@@ -1326,6 +1388,10 @@ interface ComposerChromeTokens {
1326
1388
  shadow: string;
1327
1389
  /** Border color of the composer form. @default semantic.colors.border */
1328
1390
  borderColor?: TokenReference<'color'>;
1391
+ /** Focused form border color; falls back to borderColor. V5: a stronger neutral border. */
1392
+ focusBorderColor?: TokenReference<'color'>;
1393
+ /** Outer focus ring (CSS outline shorthand). V4: none; V5: a thin neutral ring. */
1394
+ focusRing?: string;
1329
1395
  /** Inner padding of the composer form (raw CSS shorthand). @default "0.75rem 1rem" */
1330
1396
  padding?: string;
1331
1397
  /** Gap between the textarea row and the actions row. @default "0.5rem" */
@@ -1344,12 +1410,18 @@ interface ComposerChromeTokens {
1344
1410
  controlSize?: string;
1345
1411
  /** Glyph box inside those controls. @default "24px" */
1346
1412
  controlIconSize?: string;
1413
+ /** Send/stop glyph size. Explicit sendButton.iconSize wins. V5: 18px. */
1414
+ sendIconSize?: string;
1415
+ /** Icon-mode submit button radius. V4 inherits the primary button; V5: 9999px. */
1416
+ sendButtonRadius?: string;
1417
+ /** Footer top border (CSS shorthand). V4: 1px solid divider; V5: none. */
1418
+ footerBorder?: string;
1347
1419
  /**
1348
1420
  * Background painted behind an overlaid composer footer
1349
1421
  * (`composer.placement: "overlay"`). Any CSS `background` value, gradients
1350
1422
  * included — same convention as the shadow tokens. Inert under
1351
1423
  * `placement: "block"`.
1352
- * @default "transparent"
1424
+ * @default "transparent" (V4); a theme-aware 24px fade (V5)
1353
1425
  */
1354
1426
  overlayBand?: string;
1355
1427
  /** Segmented mode-group track. */
@@ -1525,6 +1597,8 @@ interface ScrollToBottomTokens extends ComponentTokenSet {
1525
1597
  }
1526
1598
  /** Visual tokens shared by one suggestion presentation variant. */
1527
1599
  interface SuggestionVariantTokens extends ComponentTokenSet {
1600
+ /** Label weight. V4: 500; V5: 400. */
1601
+ fontWeight?: string;
1528
1602
  /** Space inside one item, between its icon and its copy. */
1529
1603
  gap?: string;
1530
1604
  /** Space between suggestion items in the container. */
@@ -1573,6 +1647,7 @@ interface ComponentTokens {
1573
1647
  voice: VoiceTokens;
1574
1648
  approval: ApprovalTokens;
1575
1649
  attachment: AttachmentTokens;
1650
+ activity?: ActivityTokens;
1576
1651
  toolBubble: ToolBubbleTokens;
1577
1652
  reasoningBubble: ReasoningBubbleTokens;
1578
1653
  /** Event-stream inspector badge chips. */
@@ -4293,6 +4368,14 @@ type AgentWidgetToolCallCollapsedMode = "tool-call" | "tool-name" | "tool-previe
4293
4368
  */
4294
4369
  type AgentWidgetToolCallLoadingAnimation = "none" | "pulse" | "shimmer" | "shimmer-color" | "rainbow";
4295
4370
  type AgentWidgetToolCallDisplayFeature = {
4371
+ /** Activity chrome. Defaults to card in V4 and row with future.v5Defaults. */
4372
+ variant?: "card" | "row";
4373
+ /** Row status icons: always, active/attention-needed only, or never. V5 defaults to active; V4 to always. */
4374
+ iconVisibility?: "always" | "active" | "never";
4375
+ /** Row variant: open when the first content chunk arrives. Default false in V5; true in V4. */
4376
+ autoExpand?: boolean;
4377
+ /** Row variant: collapse once after completion, in ms; false disables. Default 1000. */
4378
+ autoCollapseDelay?: number | false;
4296
4379
  /**
4297
4380
  * Controls what collapsed tool call rows show in their header/summary area.
4298
4381
  * @default "tool-call"
@@ -4323,9 +4406,10 @@ type AgentWidgetToolCallDisplayFeature = {
4323
4406
  * Controls how a grouped tool sequence is rendered.
4324
4407
  * - `"stack"`: show the group summary and each child tool row.
4325
4408
  * - `"summary"`: show one consolidated summary row only.
4409
+ * - `"collapsible"`: expandable activity group (V5 default).
4326
4410
  * @default "stack"
4327
4411
  */
4328
- groupedMode?: "stack" | "summary";
4412
+ groupedMode?: "stack" | "summary" | "collapsible";
4329
4413
  /**
4330
4414
  * What happens to a tool call row once it completes.
4331
4415
  *
@@ -4356,6 +4440,14 @@ type AgentWidgetToolCallDisplayFeature = {
4356
4440
  /** See `features.toolCallDisplay.completedVisibility`. */
4357
4441
  type AgentWidgetToolCallCompletedVisibility = "kept" | "removed";
4358
4442
  type AgentWidgetReasoningDisplayFeature = {
4443
+ /** Activity chrome. Defaults to card in V4 and row with future.v5Defaults. */
4444
+ variant?: "card" | "row";
4445
+ /** Row status icons: always, active/attention-needed only, or never. V5 defaults to active; V4 to always. */
4446
+ iconVisibility?: "always" | "active" | "never";
4447
+ /** Row variant: open when the first content chunk arrives. Default false in V5; true in V4. */
4448
+ autoExpand?: boolean;
4449
+ /** Row variant: collapse once after completion, in ms; false disables. Default 1000. */
4450
+ autoCollapseDelay?: number | false;
4359
4451
  /**
4360
4452
  * When true, active collapsed reasoning rows can render a lightweight preview block.
4361
4453
  * @default false
@@ -5051,8 +5143,8 @@ interface AgentWidgetHistoryFeature {
5051
5143
  * otherwise `"browser"`) and narrows it to what the provider advertises, so a
5052
5144
  * browser-only provider is never asked for a scope it cannot serve. An
5053
5145
  * explicit `features.history.scope` is a hard request and still fails closed
5054
- * with `unsupported_scope`. `getIdentityProof` is never called for a supplied
5055
- * provider, and `HistoryOperationContext` carries only the resolved scope;
5146
+ * with `unsupported_scope`. History operations on a supplied provider never
5147
+ * call `getIdentityProof`, and `HistoryOperationContext` carries only the resolved scope;
5056
5148
  * report your own identity through `getIdentityStatus()` /
5057
5149
  * `subscribeIdentityStatus()`, which is what the scope banner and its retry
5058
5150
  * affordance read.
@@ -5436,7 +5528,7 @@ type EventStreamConfig = {
5436
5528
  /**
5437
5529
  * Fields to extract from event payloads for description text.
5438
5530
  * The first matching field value is displayed after the badge.
5439
- * @default ["flowName", "stepName", "name", "tool", "toolName"]
5531
+ * @default ["flowName", "stepName", "reasoningText", "text", "name", "tool", "toolName"]
5440
5532
  */
5441
5533
  descriptionFields?: string[];
5442
5534
  /**
@@ -5647,6 +5739,8 @@ type AgentWidgetComposerBarPeekConfig = {
5647
5739
  streamAnimation?: AgentWidgetStreamAnimationFeature;
5648
5740
  };
5649
5741
  type AgentWidgetLauncherConfig = {
5742
+ /** Collapsed launcher shape. V4 defaults to pill; V5 defaults to circle. */
5743
+ variant?: "pill" | "circle";
5650
5744
  enabled?: boolean;
5651
5745
  title?: string;
5652
5746
  subtitle?: string;
@@ -6390,9 +6484,9 @@ type AgentWidgetComposerConfig = {
6390
6484
  /**
6391
6485
  * Where the composer footer sits relative to the transcript.
6392
6486
  *
6393
- * - `"block"` (default): the footer is a flex sibling below the scroll body.
6487
+ * - `"block"` (V4 default): the footer is a flex sibling below the scroll body.
6394
6488
  * Nothing scrolls behind it.
6395
- * - `"overlay"`: the footer is absolutely overlaid on the scroll body, so the
6489
+ * - `"overlay"` (V5 default): the footer is absolutely overlaid on the scroll body, so the
6396
6490
  * transcript scrolls behind it (the chatgpt.com / claude.ai model, where the
6397
6491
  * composer is sticky inside the scroller). The widget reserves the footer's
6398
6492
  * live height as bottom padding on the scroll body and on a plugin welcome
@@ -6404,7 +6498,7 @@ type AgentWidgetComposerConfig = {
6404
6498
  * included) and `theme.components.input.backdropFilter`.
6405
6499
  *
6406
6500
  * Ignored in composer-bar mount mode, which owns its own geometry.
6407
- * @default "block"
6501
+ * @default "block" (V4), "overlay" (V5)
6408
6502
  */
6409
6503
  placement?: ComposerPlacement;
6410
6504
  /**
@@ -6418,8 +6512,9 @@ type AgentWidgetComposerConfig = {
6418
6512
  *
6419
6513
  * `"single-row"` describes the IDLE composer only. It composes with the
6420
6514
  * compact state, so a wrapped draft, chips, attachment previews, a quote, a
6421
- * pending card, or live dictation all fall back to the stacked card, exactly
6422
- * as `data-persona-composer-compact` does today.
6515
+ * pending card all fall back to the stacked card, exactly
6516
+ * as `data-persona-composer-compact` does today. Recording alone does not
6517
+ * expand the composer; dictated text expands it when it wraps.
6423
6518
  *
6424
6519
  * Ignored in composer-bar mount mode, whose pill is already one row.
6425
6520
  * @default "stacked"
@@ -6461,7 +6556,14 @@ type AgentWidgetClearChatConfig = {
6461
6556
  showTooltip?: boolean;
6462
6557
  };
6463
6558
  type AgentWidgetStatusIndicatorConfig = {
6559
+ /** Show the indicator. Explicit false also hides transient connection states. */
6464
6560
  visible?: boolean;
6561
+ /**
6562
+ * "always" shows status beneath the composer; "transient" shows connecting,
6563
+ * reconnecting, and error status above it, hiding normal idle/streaming status.
6564
+ * Available in both defaults states. Default: "always" in v4, "transient" in v5.
6565
+ */
6566
+ mode?: "always" | "transient";
6465
6567
  /** Text alignment. Default: 'right'. */
6466
6568
  align?: 'left' | 'center' | 'right';
6467
6569
  idleText?: string;
@@ -6475,6 +6577,22 @@ type AgentWidgetStatusIndicatorConfig = {
6475
6577
  /** Status text while a reconnect attempt is in flight. */
6476
6578
  resumingText?: string;
6477
6579
  };
6580
+ /** Built-in `voiceRecognition.prewarm` triggers. See {@link AgentWidgetVoiceRecognitionConfig.prewarm}. */
6581
+ type AgentWidgetVoicePrewarmTrigger = 'hover';
6582
+ /**
6583
+ * Custom `voiceRecognition.prewarm` trigger. Runs while the composer has a mic
6584
+ * button, and again when the button is rebuilt or `update()` swaps in a
6585
+ * different function. Call `warm()` whenever the visitor shows intent to talk
6586
+ * (it is safe to call repeatedly). Return a cleanup to run on replacement.
6587
+ */
6588
+ type AgentWidgetVoicePrewarmHook = (context: {
6589
+ /** Fire-and-forget voice warm-up; latched and error-swallowing. */
6590
+ warm: () => void;
6591
+ /** The composer's current mic button. */
6592
+ micButton: HTMLButtonElement;
6593
+ /** The widget's mount element. */
6594
+ mount: HTMLElement;
6595
+ }) => void | (() => void);
6478
6596
  type AgentWidgetVoiceRecognitionConfig = {
6479
6597
  /**
6480
6598
  * Enable the mic button and voice input. The mic still only renders when the
@@ -6540,6 +6658,29 @@ type AgentWidgetVoiceRecognitionConfig = {
6540
6658
  * Fires once per turn after the reply completes.
6541
6659
  */
6542
6660
  onMetrics?: (metrics: VoiceMetrics) => void;
6661
+ /**
6662
+ * Warm the voice path when the visitor shows intent to talk, before the mic
6663
+ * click, so the call starts faster.
6664
+ *
6665
+ * - `'hover'`: when the pointer enters the mic button, it receives focus, or
6666
+ * (on touch) the first pointer-down on it.
6667
+ * - `false`: never.
6668
+ * - A function: custom trigger. Called with `{ warm, micButton, mount }`
6669
+ * while the mic button exists (and again when the button is rebuilt or
6670
+ * `update()` swaps in a different function); call `warm()` whenever you
6671
+ * decide, e.g. when the panel opens. May return a cleanup that runs on
6672
+ * destroy, rebuild, or replacement. Replaces the built-in trigger.
6673
+ *
6674
+ * What `warm()` does depends on the provider: `runtype` fires its prewarm
6675
+ * (see `provider.runtype.prewarmMode`), a `custom` provider's optional
6676
+ * {@link VoiceProvider.prewarm} runs, and the browser (Web Speech) path
6677
+ * starts the client-token session init (as `sessionInit` does), since speech
6678
+ * recognition itself cannot start before the click. Warming is
6679
+ * fire-and-forget, latched, and never surfaces an error or UI state.
6680
+ *
6681
+ * @default 'hover' in client token mode, otherwise `false`
6682
+ */
6683
+ prewarm?: AgentWidgetVoicePrewarmTrigger | AgentWidgetVoicePrewarmHook | false;
6543
6684
  provider?: {
6544
6685
  type: 'browser' | 'runtype' | 'custom';
6545
6686
  browser?: {
@@ -6561,6 +6702,23 @@ type AgentWidgetVoiceRecognitionConfig = {
6561
6702
  * `@runtypelabs/persona/voice-worklet-player` for a jitter-buffered engine.
6562
6703
  */
6563
6704
  createPlaybackEngine?: () => VoicePlaybackEngine | Promise<VoicePlaybackEngine>;
6705
+ /**
6706
+ * How `prewarm()` warms the voice path (see `voiceRecognition.prewarm`).
6707
+ *
6708
+ * - `'request'` (default): a fire-and-forget
6709
+ * `POST {host}/v1/client/agents/{agentId}/voice/prewarm`.
6710
+ * - `'attach'`: open the voice WebSocket ahead of the click without
6711
+ * starting a call; the click then starts the call on that socket. It can
6712
+ * create server work before the visitor clicks, so it is opt-in.
6713
+ * @default 'request'
6714
+ */
6715
+ prewarmMode?: 'request' | 'attach';
6716
+ /**
6717
+ * `'attach'` mode: how long (ms) an attached socket waits for the click
6718
+ * before it closes. The server clamps it to 30000..600000.
6719
+ * @default 30000
6720
+ */
6721
+ attachIdleMs?: number;
6564
6722
  /** @deprecated No-op on the realtime path: the server's STT owns turn-taking. */
6565
6723
  pauseDuration?: number;
6566
6724
  /** @deprecated No-op on the realtime path: the server's STT owns turn-taking. */
@@ -6861,6 +7019,13 @@ interface VoiceProvider {
6861
7019
  deactivateBargeIn?(): Promise<void>;
6862
7020
  /** Stop playback / cancel in-flight request without starting recording */
6863
7021
  stopPlayback?(): void;
7022
+ /**
7023
+ * Warm the provider ahead of `startListening()` (the widget calls it on mic
7024
+ * intent, see `voiceRecognition.prewarm`). Must be fire-and-forget: never
7025
+ * throw, emit errors or status, or acquire the microphone. May be called
7026
+ * repeatedly; throttle as needed.
7027
+ */
7028
+ prewarm?(): void;
6864
7029
  }
6865
7030
  /**
6866
7031
  * Extra context for an approval decision, surfaced to `onDecision` and to the
@@ -7236,7 +7401,8 @@ type AgentWidgetResolvedSuggestion = {
7236
7401
  };
7237
7402
  /** Presentation keys shared by every suggestion surface. */
7238
7403
  type AgentWidgetSuggestionSurfaceConfig = {
7239
- /** Item density. Defaults to `card` for starters and `chip` for follow-ups. */
7404
+ /** Item density. V4 starters: card. V5 starters: chip, or card in fullscreen.
7405
+ * Follow-ups default to chip. */
7240
7406
  variant?: AgentWidgetSuggestionVariant;
7241
7407
  /** Default click behavior, overridable per item. Defaults to `send`. */
7242
7408
  behavior?: AgentWidgetSuggestionBehavior;
@@ -7247,7 +7413,7 @@ type AgentWidgetSuggestionSurfaceConfig = {
7247
7413
  * own stacking.
7248
7414
  */
7249
7415
  overflow?: "scroll" | "wrap";
7250
- /** Maximum visible items. Defaults to 4. */
7416
+ /** Maximum visible items. Defaults to 4, or 3 for V5 non-fullscreen starters. */
7251
7417
  maxItems?: number;
7252
7418
  };
7253
7419
  type AgentWidgetStarterSuggestionsConfig = AgentWidgetSuggestionSurfaceConfig & {
@@ -7301,8 +7467,8 @@ type AgentWidgetSuggestionsConfig = {
7301
7467
  type AgentWidgetWelcomeVariant = "card" | "hero" | "none";
7302
7468
  /**
7303
7469
  * When the welcome surface goes away. `"never"` is the default for `"card"`;
7304
- * `"on-first-message"` is the default for `"hero"` and cannot be overridden
7305
- * there.
7470
+ * `"on-first-message"` is forced for legacy V4 `"hero"`. V5 defaults every
7471
+ * variant to `"on-first-message"`. Explicit layout opts into overridable dismissal.
7306
7472
  */
7307
7473
  type AgentWidgetWelcomeDismiss = "never" | "on-first-message";
7308
7474
  /**
@@ -7356,7 +7522,10 @@ type AgentWidgetWelcomeAlign = "start" | "center";
7356
7522
  * host-set value from a filled-in default.
7357
7523
  */
7358
7524
  interface AgentWidgetWelcomeConfig {
7359
- /** Card or hero title. Defaults to "Hello 👋". */
7525
+ /** Vertical placement: V4 defaults to top; V5 to centered. Fullscreen centered
7526
+ * welcomes also raise the empty composer unless `anchor` is explicitly set. */
7527
+ layout?: "top" | "centered";
7528
+ /** Card or hero title. V4: "Hello 👋". V5: "What can I help with?". */
7360
7529
  title?: string;
7361
7530
  /**
7362
7531
  * Small muted line above the title, e.g. a section name. Omitted when unset
@@ -7369,19 +7538,22 @@ interface AgentWidgetWelcomeConfig {
7369
7538
  icon?: AgentWidgetWelcomeIcon;
7370
7539
  /**
7371
7540
  * Horizontal alignment of the kicker, title, subtitle, and starter
7372
- * suggestions. Unset follows the variant: `card` starts, `hero` centers.
7541
+ * suggestions. Centered layouts default to center. Otherwise unset follows
7542
+ * the variant: `card` starts, `hero` centers.
7373
7543
  */
7374
7544
  align?: AgentWidgetWelcomeAlign;
7375
7545
  /** @default "card" */
7376
7546
  variant?: AgentWidgetWelcomeVariant;
7377
- /** @default "never" for `card`, always `"on-first-message"` for `hero`. */
7547
+ /** V4: never for card, forced on-first-message for hero. V5: on-first-message
7548
+ * for all variants; explicit values win. Explicit layout also allows overriding
7549
+ * the legacy hero dismissal in V4. */
7378
7550
  dismiss?: AgentWidgetWelcomeDismiss;
7379
7551
  /**
7380
7552
  * Vertical anchoring of the greeting-plus-composer pair in the EMPTY
7381
7553
  * conversation only. On the first message the pair drops to the bottom
7382
7554
  * (animated; see `data-persona-conversation-state`).
7383
7555
  *
7384
- * - `"bottom"` (default): the composer stays pinned at the bottom.
7556
+ * - `"bottom"`: the composer stays pinned at the bottom.
7385
7557
  * - `"center"`: greeting and composer float together so the composer's top
7386
7558
  * edge lands at `anchorComposerTop` of the panel column, and the welcome
7387
7559
  * surface is end-anchored `composerGap` above it.
@@ -7389,7 +7561,8 @@ interface AgentWidgetWelcomeConfig {
7389
7561
  * Composes with either `composer.placement`. Ignored in composer-bar mount
7390
7562
  * mode. `renderWelcome` plugin content inherits the anchor: the widget
7391
7563
  * positions the overlay host and reserves the composer zone.
7392
- * @default "bottom"
7564
+ * Defaults to bottom, except centered fullscreen layouts, which center the
7565
+ * measured greeting/composer group when no anchor override is supplied.
7393
7566
  */
7394
7567
  anchor?: AgentWidgetWelcomeAnchor;
7395
7568
  /**
@@ -7881,6 +8054,9 @@ type AgentWidgetLayoutConfig = {
7881
8054
  * `launcher.composerBar.contentMaxWidth`)
7882
8055
  */
7883
8056
  contentMaxWidth?: string;
8057
+ /** Fade the transcript's top edge when content is scrolled above it.
8058
+ * Defaults to false in V4 and true with future.v5Defaults. */
8059
+ topFade?: boolean;
7884
8060
  };
7885
8061
  /**
7886
8062
  * Token types for marked renderer methods
@@ -8494,7 +8670,30 @@ type AgentWidgetLoadingIndicatorConfig = {
8494
8670
  */
8495
8671
  renderIdle?: (context: IdleIndicatorRenderContext) => HTMLElement | null;
8496
8672
  };
8673
+ /** Built-in `sessionInit` triggers. See {@link AgentWidgetConfig.sessionInit}. */
8674
+ type AgentWidgetSessionInitTrigger = 'input' | 'focus' | 'mount' | 'send';
8675
+ /**
8676
+ * Custom `sessionInit` trigger. Runs when the widget mounts in client token mode,
8677
+ * and again if `update()` swaps in a different function. Call `warm()` whenever
8678
+ * the visitor shows intent (it is safe to call repeatedly). Return a cleanup to
8679
+ * run when the widget is destroyed or the hook is replaced.
8680
+ */
8681
+ type AgentWidgetSessionInitHook = (context: {
8682
+ /** Fire-and-forget early session init; latched and error-swallowing. */
8683
+ warm: () => void;
8684
+ /** The widget's mount element. */
8685
+ mount: HTMLElement;
8686
+ }) => void | (() => void);
8497
8687
  type AgentWidgetConfig = {
8688
+ /** Opt in to upcoming major-version defaults without changing explicit settings. */
8689
+ future?: {
8690
+ /**
8691
+ * Use the v5 default styling as it rolls out in 4.x. Every affected setting
8692
+ * remains independently configurable. Explicit options and theme tokens win.
8693
+ * @default false
8694
+ */
8695
+ v5Defaults?: boolean;
8696
+ };
8498
8697
  apiUrl?: string;
8499
8698
  flowId?: string;
8500
8699
  /**
@@ -8649,6 +8848,46 @@ type AgentWidgetConfig = {
8649
8848
  * ```
8650
8849
  */
8651
8850
  onSessionExpired?: () => void;
8851
+ /**
8852
+ * When the widget calls `/v1/client/init` in client token mode, ahead of the
8853
+ * first send. Ignored outside client token mode.
8854
+ *
8855
+ * - `'input'` (default): on the composer's first user keystroke that leaves
8856
+ * non-empty text. Programmatic value changes (restored drafts,
8857
+ * `setMessage()`, history recall) do not count.
8858
+ * - `'focus'`: when the visitor focuses the composer by pointer or Tab (and
8859
+ * on first input, as a fallback). Programmatic focus, such as
8860
+ * `autoFocusInput` on open or mount, does not count.
8861
+ * - `'mount'`: as soon as the widget mounts (the behavior before this option
8862
+ * existed). Use it when a server-configured welcome message, which arrives
8863
+ * with the init response, must show before the visitor types.
8864
+ * - `'send'`: no early init; the first send initializes the session.
8865
+ * - A function: custom trigger. Called on mount (and when `update()` swaps
8866
+ * in a different function) with a `warm` callback to call whenever you
8867
+ * decide (e.g. on hover); may return a cleanup that runs on destroy or
8868
+ * replacement. Replaces the built-in triggers.
8869
+ *
8870
+ * The early init is fire-and-forget: it runs at most once per session
8871
+ * lifetime (re-armed after expiry or a new conversation), sends exactly the
8872
+ * same request the send would, and swallows errors. A failure resurfaces
8873
+ * when the send retries init. A send during an in-flight early init reuses
8874
+ * it, so only one `/v1/client/init` is issued. When visitor history is
8875
+ * enabled the widget still initializes on mount to restore the conversation.
8876
+ * Hosts can also trigger it imperatively with `controller.warmSession()`.
8877
+ *
8878
+ * @default 'input'
8879
+ *
8880
+ * @example
8881
+ * ```typescript
8882
+ * config: {
8883
+ * clientToken: 'ct_live_...',
8884
+ * sessionInit: ({ warm, mount }) => {
8885
+ * mount.addEventListener('pointerenter', warm, { once: true });
8886
+ * }
8887
+ * }
8888
+ * ```
8889
+ */
8890
+ sessionInit?: AgentWidgetSessionInitTrigger | AgentWidgetSessionInitHook;
8652
8891
  /**
8653
8892
  * Get stored session ID for session resumption (client token mode only).
8654
8893
  * Called when initializing a new session to check if there's a previous session_id
@@ -8681,13 +8920,20 @@ type AgentWidgetConfig = {
8681
8920
  */
8682
8921
  setStoredSessionId?: (sessionId: string) => void;
8683
8922
  /**
8684
- * Called immediately before any cross-device history request and before a
8923
+ * With identityProvider, called before every client-token chat POST, including retries, independently of history.
8924
+ * Also called immediately before any cross-device history request and before a
8685
8925
  * conversationId resume of a conversation discovered on another device.
8686
- * Return a fresh end-user access token (rt_eu_… / JWT). Null uses exact-browser
8687
- * scope only for a never-bound visitor; a previously bound visitor fails closed
8688
- * until resetHistoryIdentity() runs. Never cached by the widget.
8926
+ * Return a fresh end-user access token (rt_eu_… / JWT). Null stops identity-enabled chat.
8927
+ * For history only, null uses exact-browser scope for a never-bound visitor;
8928
+ * a bound visitor fails closed until resetHistoryIdentity(). Never cached.
8689
8929
  */
8690
8930
  getIdentityProof?: () => string | null | Promise<string | null>;
8931
+ /**
8932
+ * Provider name registered with Runtype, for example "clerk". Enables per-request
8933
+ * chat identity through getIdentityProof without enabling history. A missing or
8934
+ * failed proof stops the turn; omitting this preserves history-only callbacks.
8935
+ */
8936
+ identityProvider?: string;
8691
8937
  /**
8692
8938
  * Read the persisted active conversation id (client token mode only).
8693
8939
  * Called only after the internal stored-state bootstrap gate resolves.
@@ -9361,6 +9607,8 @@ type AgentWidgetReasoning = {
9361
9607
  durationMs?: number;
9362
9608
  };
9363
9609
  type AgentWidgetToolCall = {
9610
+ /** Optional approval state for activity-row status chrome. */
9611
+ approvalStatus?: "pending" | "approved" | "denied" | "timeout";
9364
9612
  id: string;
9365
9613
  name?: string;
9366
9614
  status: "pending" | "running" | "complete";
@@ -9571,13 +9819,6 @@ type PersonaArtifactRecord = {
9571
9819
  presentation?: PersonaArtifactPresentation;
9572
9820
  };
9573
9821
 
9574
- /**
9575
- * Per-message expanded/collapsed state for the technical-details section.
9576
- * Absent means "use the config default" (`approval.detailsDisplay`). Lives at
9577
- * module scope so the choice survives idiomorph re-renders, mirroring
9578
- * `toolExpansionState` in tool-bubble.ts.
9579
- */
9580
- declare const approvalDetailsExpansionState: Map<string, boolean>;
9581
9822
  /**
9582
9823
  * Turn a wire tool name into a user-facing label: strips the `webmcp:`
9583
9824
  * prefix and splits snake_case / kebab-case / camelCase into a sentence
@@ -9587,14 +9828,14 @@ declare const approvalDetailsExpansionState: Map<string, boolean>;
9587
9828
  declare const humanizeToolName: (toolName: string) => string;
9588
9829
  /**
9589
9830
  * Sync the technical-details section (toggle label/chevron + visibility) with
9590
- * `approvalDetailsExpansionState`. Called from the ui.ts expansion event
9831
+ * the widget instance's expansion state. Called from the ui.ts expansion event
9591
9832
  * delegation after a toggle click.
9592
9833
  */
9593
- declare const updateApprovalDetailsUI: (messageId: string, bubble: HTMLElement, config?: AgentWidgetConfig) => void;
9834
+ declare const updateApprovalDetailsUI: (messageId: string, bubble: HTMLElement, config?: AgentWidgetConfig, expansionState?: Map<string, boolean>) => void;
9594
9835
  /**
9595
9836
  * Create an approval bubble element for inline display in the chat.
9596
9837
  */
9597
- declare const createApprovalBubble: (message: AgentWidgetMessage, config?: AgentWidgetConfig) => HTMLElement;
9838
+ declare const createApprovalBubble: (message: AgentWidgetMessage, config?: AgentWidgetConfig, expansionState?: Map<string, boolean>) => HTMLElement;
9598
9839
 
9599
9840
  /**
9600
9841
  * The built-in approval renderer, shaped as a plugin so ui.ts can run it through
@@ -9606,7 +9847,7 @@ declare const createApprovalBubble: (message: AgentWidgetMessage, config?: Agent
9606
9847
  * callbacks — both close over the SAME per-instance state, so destroying one
9607
9848
  * widget never disturbs another widget's open approvals on the same page.
9608
9849
  */
9609
- declare const createBuiltInApprovalPlugin: () => {
9850
+ declare const createBuiltInApprovalPlugin: (expansionState?: Map<string, boolean>) => {
9610
9851
  plugin: AgentWidgetPlugin;
9611
9852
  teardown: () => void;
9612
9853
  };
@@ -9626,4 +9867,4 @@ interface ApprovalUiDeps {
9626
9867
  }
9627
9868
  declare const initApprovalUi: (deps: ApprovalUiDeps) => void;
9628
9869
 
9629
- export { type ApprovalUiDeps, approvalDetailsExpansionState, createApprovalBubble, createBuiltInApprovalPlugin, humanizeToolName, initApprovalUi, updateApprovalDetailsUI };
9870
+ export { type ApprovalUiDeps, createApprovalBubble, createBuiltInApprovalPlugin, humanizeToolName, initApprovalUi, updateApprovalDetailsUI };