@runtypelabs/persona 4.17.1 → 4.18.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 (158) hide show
  1. package/dist/chunk-3I2S3I5P.js +1 -0
  2. package/dist/chunk-76IELU7F.js +1 -0
  3. package/dist/chunk-EFJBUH5F.js +1 -0
  4. package/dist/chunk-PDPVORUF.js +1 -0
  5. package/dist/chunk-Q735PSZL.js +1 -0
  6. package/dist/chunk-VK6JOIYJ.js +1 -0
  7. package/dist/codegen.cjs +4 -4
  8. package/dist/codegen.js +4 -4
  9. package/dist/{context-mentions-BTSTIBFC.js → context-mentions-MJL6S6P2.js} +1 -1
  10. package/dist/context-mentions.cjs +9 -8
  11. package/dist/context-mentions.d.cts +1212 -14
  12. package/dist/context-mentions.d.ts +1212 -14
  13. package/dist/context-mentions.js +9 -8
  14. package/dist/event-stream-view-4EZ7BGFK.js +1 -0
  15. package/dist/event-stream-view.cjs +129 -0
  16. package/dist/event-stream-view.d.cts +8384 -0
  17. package/dist/event-stream-view.d.ts +8384 -0
  18. package/dist/event-stream-view.js +129 -0
  19. package/dist/history-view-BD6OXLNA.js +898 -0
  20. package/dist/history-view.cjs +898 -0
  21. package/dist/history-view.d.cts +1461 -0
  22. package/dist/history-view.d.ts +1461 -0
  23. package/dist/history-view.js +898 -0
  24. package/dist/index.cjs +77 -77
  25. package/dist/index.cjs.map +1 -1
  26. package/dist/index.d.cts +1987 -17
  27. package/dist/index.d.ts +1987 -17
  28. package/dist/index.global.js +67 -66
  29. package/dist/index.global.js.map +1 -1
  30. package/dist/index.js +77 -77
  31. package/dist/index.js.map +1 -1
  32. package/dist/launcher.global.js +5 -4
  33. package/dist/launcher.global.js.map +1 -1
  34. package/dist/plugin-kit.cjs +1 -1
  35. package/dist/plugin-kit.d.cts +0 -8
  36. package/dist/plugin-kit.d.ts +0 -8
  37. package/dist/plugin-kit.js +1 -1
  38. package/dist/smart-dom-reader.d.cts +1212 -14
  39. package/dist/smart-dom-reader.d.ts +1212 -14
  40. package/dist/theme-editor-preview.cjs +970 -73
  41. package/dist/theme-editor-preview.d.cts +1331 -15
  42. package/dist/theme-editor-preview.d.ts +1331 -15
  43. package/dist/theme-editor-preview.js +81 -81
  44. package/dist/theme-editor.cjs +7 -7
  45. package/dist/theme-editor.d.cts +1215 -15
  46. package/dist/theme-editor.d.ts +1215 -15
  47. package/dist/theme-editor.js +9 -9
  48. package/dist/theme-reference.cjs +1 -1
  49. package/dist/theme-reference.d.cts +226 -7
  50. package/dist/theme-reference.d.ts +226 -7
  51. package/dist/theme-reference.js +1 -1
  52. package/dist/widget.css +1 -1
  53. package/package.json +16 -4
  54. package/src/client-history-rest.test.ts +1034 -0
  55. package/src/client-visitor-history.test.ts +596 -0
  56. package/src/client.ts +1040 -24
  57. package/src/components/artifact-inline.ts +8 -1
  58. package/src/components/artifact-pane.test.ts +278 -1
  59. package/src/components/artifact-pane.ts +135 -67
  60. package/src/components/artifact-preview.test.ts +14 -1
  61. package/src/components/artifact-preview.ts +9 -0
  62. package/src/components/header-builder.ts +3 -0
  63. package/src/components/header-layouts.test.ts +171 -7
  64. package/src/components/header-layouts.ts +83 -53
  65. package/src/components/header-parts.test.ts +154 -1
  66. package/src/components/header-parts.ts +266 -138
  67. package/src/components/history-confirm-dialog.ts +177 -0
  68. package/src/components/history-shell-copy.ts +99 -0
  69. package/src/components/history-view/announcer.ts +40 -0
  70. package/src/components/history-view/copy.ts +105 -0
  71. package/src/components/history-view/css.ts +1078 -0
  72. package/src/components/history-view/grouping.test.ts +142 -0
  73. package/src/components/history-view/grouping.ts +142 -0
  74. package/src/components/history-view/icons.ts +73 -0
  75. package/src/components/history-view/rows.ts +341 -0
  76. package/src/components/history-view/state.ts +309 -0
  77. package/src/components/history-view.test.ts +2660 -0
  78. package/src/components/history-view.ts +1891 -0
  79. package/src/components/launcher-surface.test.ts +133 -0
  80. package/src/components/launcher.test.ts +18 -0
  81. package/src/components/launcher.ts +7 -7
  82. package/src/components/panel.ts +17 -7
  83. package/src/components/welcome.ts +72 -2
  84. package/src/defaults.ts +36 -3
  85. package/src/event-stream-view-bundle.test.ts +69 -0
  86. package/src/event-stream-view-entry.ts +19 -0
  87. package/src/event-stream-view-loader.ts +31 -0
  88. package/src/event-stream-view.ts +19 -0
  89. package/src/generated/runtype-openapi-contract.ts +1 -0
  90. package/src/history-render.ts +325 -0
  91. package/src/history-view-bundle.test.ts +78 -0
  92. package/src/history-view-entry.ts +41 -0
  93. package/src/history-view-loader.test.ts +30 -0
  94. package/src/history-view-loader.ts +32 -0
  95. package/src/history-view.ts +28 -0
  96. package/src/index-core.ts +50 -2
  97. package/src/index-global.ts +55 -0
  98. package/src/internal/demo-history-provider.test.ts +402 -0
  99. package/src/internal/demo-history-provider.ts +689 -0
  100. package/src/internal/history-provider-registry.ts +25 -0
  101. package/src/internal/history-provider.ts +150 -0
  102. package/src/internal/runtype-history-provider.test.ts +313 -0
  103. package/src/internal/runtype-history-provider.ts +240 -0
  104. package/src/plugin-kit.test.ts +16 -0
  105. package/src/plugin-kit.ts +13 -5
  106. package/src/plugins/types.ts +177 -1
  107. package/src/session-history.test.ts +1397 -0
  108. package/src/session.ts +1200 -26
  109. package/src/styles/widget-styles.test.ts +133 -0
  110. package/src/styles/widget.css +227 -8
  111. package/src/theme-editor/preview-utils.test.ts +19 -0
  112. package/src/theme-editor/preview-utils.ts +15 -1
  113. package/src/theme-editor/preview.ts +7 -1
  114. package/src/theme-editor/role-mappings.ts +4 -1
  115. package/src/theme-editor/sections.test.ts +168 -1
  116. package/src/theme-editor/sections.ts +136 -7
  117. package/src/theme-editor/webmcp/summary.ts +16 -2
  118. package/src/theme-reference.ts +20 -6
  119. package/src/types/theme.ts +213 -7
  120. package/src/types.ts +927 -7
  121. package/src/ui.artifact-rail-resize.test.ts +235 -0
  122. package/src/ui.attachments-drop.test.ts +1 -0
  123. package/src/ui.header-update-stability.test.ts +2 -2
  124. package/src/ui.history-chunk.test.ts +72 -0
  125. package/src/ui.history-config-provider.test.ts +318 -0
  126. package/src/ui.history-controller.test.ts +711 -0
  127. package/src/ui.history-lifecycle.test.ts +456 -0
  128. package/src/ui.history-render-hooks.test.ts +904 -0
  129. package/src/ui.history-shell.test.ts +1887 -0
  130. package/src/ui.rail-overlay.test.ts +573 -0
  131. package/src/ui.rail-resize.test.ts +284 -0
  132. package/src/ui.rebuild-composer.test.ts +21 -0
  133. package/src/ui.render-welcome.test.ts +42 -0
  134. package/src/ui.shortcuts.test.ts +166 -0
  135. package/src/ui.ts +3071 -240
  136. package/src/utils/__fixtures__/client-conversation-history-wire.json +108 -0
  137. package/src/utils/artifact-file.ts +15 -0
  138. package/src/utils/artifact-gate.test.ts +4 -0
  139. package/src/utils/artifact-gate.ts +13 -17
  140. package/src/utils/artifact-resize.test.ts +28 -0
  141. package/src/utils/artifact-resize.ts +9 -2
  142. package/src/utils/buttons.ts +188 -1
  143. package/src/utils/config-merge.test.ts +91 -0
  144. package/src/utils/dropdown.ts +10 -1
  145. package/src/utils/history-messages.test.ts +284 -0
  146. package/src/utils/history-messages.ts +284 -0
  147. package/src/utils/icons.ts +3 -0
  148. package/src/utils/shortcuts.test.ts +288 -0
  149. package/src/utils/shortcuts.ts +221 -0
  150. package/src/utils/theme.test.ts +501 -4
  151. package/src/utils/theme.ts +42 -3
  152. package/src/utils/tokens.ts +153 -15
  153. package/src/utils/tooltip-timing.ts +4 -0
  154. package/src/utils/tooltip.test.ts +249 -7
  155. package/src/utils/tooltip.ts +146 -4
  156. package/src/utils/visitor-store.test.ts +425 -0
  157. package/src/utils/visitor-store.ts +337 -0
  158. package/dist/chunk-QJ4LV2KW.js +0 -1
package/dist/index.d.ts CHANGED
@@ -33,6 +33,8 @@ interface AgentWidgetPluginStorage {
33
33
  remove: (key: string) => void;
34
34
  }
35
35
 
36
+ type ShortcutScope = "widget" | "page";
37
+
36
38
  type AgentWidgetTransformSuggestionsContext = {
37
39
  /**
38
40
  * Fresh copy of the suggestions entering this plugin, already normalized:
@@ -81,6 +83,37 @@ type AgentWidgetRenderWelcomeContext = {
81
83
  /** Teardown for this render; runs before the next one and on destroy. */
82
84
  onCleanup: (fn: () => void) => void;
83
85
  };
86
+ /** Context for one `railSections` entry. Frozen per invocation. */
87
+ type AgentWidgetRailSectionContext = {
88
+ /** Current rail width state. The section re-renders whenever this flips. */
89
+ collapsed: boolean;
90
+ presentation: ResolvedHistoryPresentation;
91
+ /** The same frozen action path the default rows and `renderHistoryView` use. */
92
+ actions: AgentWidgetHistoryRenderActions;
93
+ };
94
+ /** A plugin-contributed navigation section in the history rail. */
95
+ type AgentWidgetRailSection = {
96
+ /** Stable identity, stamped as `data-persona-rail-section`. */
97
+ id: string;
98
+ /** Default `"above-conversations"`. */
99
+ placement?: AgentWidgetHistoryRailSection["placement"];
100
+ /** Optional heading, styled like a conversation date-group heading. */
101
+ title?: string;
102
+ /** Section body. Null renders nothing for the current state. */
103
+ render: (context: AgentWidgetRailSectionContext) => Element | null;
104
+ };
105
+ /** A plugin-contributed keyboard shortcut, bound per widget instance. */
106
+ type AgentWidgetPluginShortcut = {
107
+ /** Stable identity, used in duplicate/throw warnings. */
108
+ id: string;
109
+ /** e.g. `"mod+b"`. "mod" is Command on Apple platforms, Control elsewhere. */
110
+ combo: string;
111
+ /** Default `"widget"`: fires only from inside the widget mount. */
112
+ scope?: ShortcutScope;
113
+ /** Returning false skips the binding for this keypress. */
114
+ when?: () => boolean;
115
+ run: () => void;
116
+ };
84
117
  type AgentWidgetSuggestionSelectContext = {
85
118
  suggestion: AgentWidgetResolvedSuggestion;
86
119
  surface: AgentWidgetSuggestionSurface;
@@ -351,6 +384,10 @@ interface AgentWidgetPlugin {
351
384
  * Custom renderer for loading indicator
352
385
  * Return null to use default renderer (or config-based renderer)
353
386
  *
387
+ * Covers the streaming indicator ('inline', 'standalone') and the transcript
388
+ * skeleton shown while a conversation opened from the Messages list loads
389
+ * ('conversation-open').
390
+ *
354
391
  * @example
355
392
  * ```typescript
356
393
  * renderLoadingIndicator: ({ location, defaultRenderer }) => {
@@ -402,6 +439,118 @@ interface AgentWidgetPlugin {
402
439
  * Return null to use default renderer.
403
440
  */
404
441
  renderEventStreamPayload?: (context: EventStreamPayloadRenderContext) => HTMLElement | null;
442
+ /**
443
+ * Replace the complete history ("Messages") navigation contents in either
444
+ * host. Plugins run by priority and the first non-null element wins; null
445
+ * falls through to the default full view, which then applies the first
446
+ * non-null header/row/state hook at each slot.
447
+ *
448
+ * Calling `defaultRenderer()` bypasses this hook only: the default view is
449
+ * built and its lower-level slots still arbitrate, including this plugin's.
450
+ * Return it (or an element containing it) to compose rather than replace.
451
+ *
452
+ * The hook replaces contents, not orchestration. Persona keeps placement,
453
+ * open/close, responsive rail <-> panel movement, inertness, Escape, the
454
+ * confirmation dialogs, live announcements, and focus fallback. Fetch nothing
455
+ * directly: `actions.refresh()` is the only way to reload the list.
456
+ *
457
+ * @example
458
+ * ```typescript
459
+ * renderHistoryView: ({ conversations, actions, presentation, onCleanup }) => {
460
+ * const rail = document.createElement("nav");
461
+ * rail.dataset.presentation = presentation;
462
+ * for (const conversation of conversations) {
463
+ * const row = document.createElement("button");
464
+ * row.textContent = conversation.title;
465
+ * row.addEventListener("click", () => void actions.openConversation(conversation.id));
466
+ * rail.appendChild(row);
467
+ * }
468
+ * const timer = setInterval(() => void actions.refresh(), 60_000);
469
+ * onCleanup(() => clearInterval(timer));
470
+ * return rail;
471
+ * }
472
+ * ```
473
+ */
474
+ renderHistoryView?: (context: AgentWidgetRenderHistoryViewContext) => HTMLElement | null;
475
+ /**
476
+ * Replace the standard Messages header while retaining its list/state UI.
477
+ * Return null to use the default top bar. A custom header may not remove the
478
+ * keyboard close path or falsify the resolved open state.
479
+ */
480
+ renderHistoryHeader?: (context: AgentWidgetRenderHistoryHeaderContext) => HTMLElement | null;
481
+ /**
482
+ * Replace one conversation row while retaining standard paging/grouping.
483
+ * Return null to use the default row.
484
+ */
485
+ renderHistoryConversation?: (context: AgentWidgetRenderHistoryConversationContext) => HTMLElement | null;
486
+ /**
487
+ * Replace loading, empty, error, authentication, rate-limit, or recovery
488
+ * content in the list region. Return null to use the default block.
489
+ */
490
+ renderHistoryState?: (context: AgentWidgetRenderHistoryStateContext) => HTMLElement | null;
491
+ /**
492
+ * Replace the transcript-level error surface shown when opening a
493
+ * conversation from the Messages list fails. Plugins run by priority and
494
+ * the first non-null element wins; null falls through to the default block.
495
+ *
496
+ * Persona keeps the centered transcript column, the alert role, and the
497
+ * composer gate around the returned element. `retry`/`back` are the only
498
+ * exits: both route through the token-guarded open flow, so do not fetch
499
+ * directly. `back` is absent when there is no Messages surface to return
500
+ * to; do not render a back affordance without it.
501
+ */
502
+ renderHistoryOpenError?: (context: AgentWidgetRenderHistoryOpenErrorContext) => HTMLElement | null;
503
+ /**
504
+ * Contribute navigation sections to the history rail, stacked around the
505
+ * conversation list in `placement` order. Rail only: the panel presentation
506
+ * renders none of them, and `features.history.rail.sections` (config) comes
507
+ * first inside each bucket, then plugins in plugin order.
508
+ *
509
+ * `render` is re-invoked with the new `collapsed` value whenever the rail
510
+ * collapses or expands, and its return replaces the previous content;
511
+ * returning null renders nothing for that state. A throwing `render` warns
512
+ * once and drops that section only, leaving the rest of the rail alone. An id
513
+ * a config section already owns is dropped with a warning.
514
+ *
515
+ * Keep heavy UI in the host bundle: `render` may return a skeleton and
516
+ * hydrate it after the host's own dynamic import resolves.
517
+ *
518
+ * @example
519
+ * ```typescript
520
+ * railSections: [
521
+ * {
522
+ * id: "pinned",
523
+ * title: "Pinned",
524
+ * render: ({ collapsed, actions }) => {
525
+ * if (collapsed) return null;
526
+ * const list = document.createElement("div");
527
+ * const row = document.createElement("button");
528
+ * row.textContent = "Weekly report";
529
+ * row.addEventListener("click", () => void actions.openConversation("c1"));
530
+ * list.appendChild(row);
531
+ * return list;
532
+ * }
533
+ * }
534
+ * ]
535
+ * ```
536
+ */
537
+ railSections?: AgentWidgetRailSection[];
538
+ /**
539
+ * Keyboard shortcuts registered for the lifetime of each widget instance the
540
+ * plugin is active in, and unregistered on its teardown. `combo` is written
541
+ * as `"mod+b"` / `"mod+shift+k"`, where "mod" is Command on Apple platforms
542
+ * and Control elsewhere. `scope` defaults to `"widget"` (only while focus is
543
+ * inside the mount); `when` returning false skips the keypress. A combo
544
+ * another binding already owns warns and is ignored, first registration wins.
545
+ *
546
+ * @example
547
+ * ```typescript
548
+ * shortcuts: [
549
+ * { id: "open-inbox", combo: "mod+shift+i", run: () => openInbox() }
550
+ * ]
551
+ * ```
552
+ */
553
+ shortcuts?: AgentWidgetPluginShortcut[];
405
554
  /**
406
555
  * Called when plugin is registered
407
556
  */
@@ -560,6 +709,10 @@ interface SemanticTokens {
560
709
  }
561
710
  interface ComponentTokenSet {
562
711
  background?: TokenReference<'color'>;
712
+ /**
713
+ * Text and glyph color on `background`. `HeaderTokens` also derives its
714
+ * unset text, icon, and border colors from this pair.
715
+ */
563
716
  foreground?: TokenReference<'color'>;
564
717
  border?: TokenReference<'color'>;
565
718
  borderRadius?: TokenReference<'radius'>;
@@ -587,6 +740,15 @@ interface LauncherTokens extends ComponentTokenSet {
587
740
  size: string;
588
741
  iconSize: string;
589
742
  shadow: TokenReference<'shadow'>;
743
+ /**
744
+ * Stroke weight of the launcher glyphs, the agent icon and the
745
+ * call-to-action arrow alike. Unitless, and must be a STRING (`"1.75"`,
746
+ * never `1.75`: the token resolver silently skips numbers). Applied as CSS,
747
+ * so it beats the attribute the icons render with. Inert for emoji / image
748
+ * launchers, which have no svg.
749
+ * @default "1.5", matching the header's controlStrokeWidth
750
+ */
751
+ iconStrokeWidth?: string;
590
752
  }
591
753
  interface PanelTokens extends ComponentTokenSet {
592
754
  width: string;
@@ -607,28 +769,212 @@ interface TextStyleTokens {
607
769
  letterSpacing?: string;
608
770
  color?: TokenReference<'color'>;
609
771
  }
772
+ /**
773
+ * Header band tokens. `background` plus `foreground` (inherited from
774
+ * `ComponentTokenSet`) is the pair that colors the band: `foreground` anchors
775
+ * the header text, and every text, action-icon, and border color the theme
776
+ * leaves unset derives from the pair. Derivation only fills unset keys, so an
777
+ * explicit key always wins, and `iconBackground` / `iconForeground` (the avatar
778
+ * tile) keep their own defaults rather than deriving.
779
+ */
610
780
  interface HeaderTokens extends ComponentTokenSet {
611
781
  background: TokenReference<'color'>;
612
- border: TokenReference<'color'>;
782
+ /**
783
+ * Hairline under the header. Unset, it derives as
784
+ * `color-mix(in srgb, foreground 14%, background)`, then the divider color.
785
+ */
786
+ border?: TokenReference<'color'>;
613
787
  borderRadius: TokenReference<'radius'>;
614
788
  /** Background of the rounded avatar tile next to the title (Lucide / emoji / image). */
615
789
  iconBackground: TokenReference<'color'>;
616
790
  /** Foreground (glyph stroke or emoji text) on the header avatar tile. */
617
791
  iconForeground: TokenReference<'color'>;
618
- /** Legacy alias of `title.color`; `title.color` wins when both are set. */
619
- titleForeground: TokenReference<'color'>;
620
- /** Legacy alias of `subtitle.color`; `subtitle.color` wins when both are set. */
621
- subtitleForeground: TokenReference<'color'>;
792
+ /**
793
+ * Legacy alias of `title.color`; `title.color` wins when both are set.
794
+ * Unset, the title takes `foreground`, then the primary color.
795
+ */
796
+ titleForeground?: TokenReference<'color'>;
797
+ /**
798
+ * Legacy alias of `subtitle.color`; `subtitle.color` wins when both are set.
799
+ * Unset, the subtitle takes `color-mix(in srgb, foreground 72%, background)`,
800
+ * then the muted text color.
801
+ */
802
+ subtitleForeground?: TokenReference<'color'>;
622
803
  /** Header title typography (next to the icon, or minimal layout title). */
623
804
  title?: TextStyleTokens;
624
805
  /** Header subtitle typography, for the line under the title. */
625
806
  subtitle?: TextStyleTokens;
626
- /** Default color for clear / close icon buttons when launcher overrides are unset. */
627
- actionIconForeground: TokenReference<'color'>;
807
+ /**
808
+ * Default color for clear / close icon buttons when launcher overrides are
809
+ * unset. Itself unset, it takes the same
810
+ * `color-mix(in srgb, foreground 72%, background)` as the subtitle, then the
811
+ * muted text color.
812
+ */
813
+ actionIconForeground?: TokenReference<'color'>;
814
+ /**
815
+ * Edge of every header icon button: close, clear chat, `trailingActions`, and
816
+ * the Messages toggle. Per-control config keys (`launcher.closeButtonSize`,
817
+ * `launcher.clearChat.size`) still win. Coarse pointers floor the hit area at
818
+ * 40px regardless. @default "32px"
819
+ */
820
+ controlSize?: string;
821
+ /** Glyph box inside a header control. @default "20px" */
822
+ controlIconSize?: string;
823
+ /**
824
+ * Stroke weight of the glyph inside a header control. Unitless, as an SVG
825
+ * stroke-width (e.g. `"1.75"`). Sparse-viewBox glyphs (the close X) render
826
+ * at 0.7 of it so their heavier visible weight still matches a dense
827
+ * sibling. @default "1.5"
828
+ */
829
+ controlStrokeWidth?: string;
628
830
  /** Box-shadow on the header (e.g., a fade shadow to replace the default border). */
629
831
  shadow?: string;
630
832
  /** Override the header bottom border (e.g., `none`). */
631
833
  borderBottom?: string;
834
+ /**
835
+ * Floor for the header strip's height (e.g. `"56px"`). Pin it together with
836
+ * `components.history.railHeader.minHeight` so the Messages rail header and
837
+ * the conversation header read as one continuous band.
838
+ */
839
+ minHeight?: string;
840
+ }
841
+ /** Messages (conversation history) surfaces. */
842
+ interface HistoryTokens {
843
+ /**
844
+ * The Messages rail's own top strip, which runs beside the widget header
845
+ * when `features.history.presentation` resolves to `rail`.
846
+ */
847
+ railHeader?: {
848
+ /** Strip background. Defaults to the rail's surface color. */
849
+ background?: TokenReference<'color'>;
850
+ /** Full border-bottom shorthand (raw CSS, e.g. `"1px solid #e5e7eb"`). @default "0" */
851
+ border?: string;
852
+ /** Strip height floor. Defaults to `components.header.minHeight`, then 56px. */
853
+ minHeight?: string;
854
+ /**
855
+ * The strip's view title ("Messages"). 14px/600 in the text color by
856
+ * default; set the type keys to restyle it.
857
+ */
858
+ title?: TextStyleTokens;
859
+ };
860
+ /**
861
+ * The "Conversations" heading over the list block. Visible in rail
862
+ * presentation only (the panel keeps it screen-reader-only). 14px/600 in
863
+ * the text color by default. Every key is pinned in the widget CSS, so
864
+ * host-page heading rules never restyle it.
865
+ */
866
+ listHeading?: TextStyleTokens;
867
+ /**
868
+ * The muted sub-headers inside the Messages surface: date groups ("Today",
869
+ * "Yesterday") and rail nav section titles (`features.history.rail.sections`
870
+ * `title`, e.g. "Workspace"). 13px/500 in the muted text color in the rail
871
+ * (the panel keeps date groups screen-reader-only). Every key is pinned in
872
+ * the widget CSS, so host-page heading rules never restyle them.
873
+ */
874
+ groupHeading?: TextStyleTokens;
875
+ /**
876
+ * The floating rail that a collapsed
877
+ * `features.history.rail.collapsedBehavior: "overlay"` opens on hover. It
878
+ * hangs below the trigger in the conversation header; its width and edge
879
+ * stay `features.history.rail` geometry, not tokens.
880
+ */
881
+ overlay?: {
882
+ /** Gap from the trigger, the docked edge, and the bottom. @default "8px" */
883
+ margin?: string;
884
+ /** Corner radius, on all four corners. @default "16px" */
885
+ borderRadius?: string;
886
+ /** Elevation over the conversation. @default "0 12px 40px rgba(0, 0, 0, 0.25)" */
887
+ shadow?: string;
888
+ /** Surface behind the rail. Defaults to the rail's own surface color. */
889
+ background?: TokenReference<'color'>;
890
+ };
891
+ /**
892
+ * Destructive action text (row Delete, "Delete all conversations").
893
+ * Defaults to `palette.colors.error.600` in light schemes and a lighter
894
+ * red in the built-in dark theme so the 14px labels keep AA contrast.
895
+ */
896
+ dangerForeground?: TokenReference<'color'>;
897
+ /**
898
+ * The delete/forget confirmation dialog the shell shows for destructive
899
+ * history actions. The danger pair is always emitted (`--persona-danger`
900
+ * / `--persona-danger-fg`); scrim and shadow keep the built-in look when
901
+ * unset.
902
+ */
903
+ confirm?: {
904
+ /**
905
+ * Destructive button fill. Defaults to `palette.colors.error.700` in
906
+ * light schemes and `error.600` in the built-in dark theme.
907
+ */
908
+ dangerBackground?: TokenReference<'color'>;
909
+ /** Destructive button label. @default "#ffffff" */
910
+ dangerForeground?: TokenReference<'color'>;
911
+ /** Overlay behind the dialog. @default "rgba(15, 23, 42, 0.45)" */
912
+ scrim?: TokenReference<'color'>;
913
+ /** Card elevation (raw CSS shadow). */
914
+ shadow?: string;
915
+ };
916
+ /** The per-row overflow menu in the Messages list (rail and panel). */
917
+ menu?: {
918
+ /**
919
+ * Menu surface. Defaults to the list surface lifted 8% toward white so
920
+ * the menu reads as elevated in dark schemes.
921
+ */
922
+ background?: TokenReference<'color'>;
923
+ /** Corner radius. @default "12px" */
924
+ borderRadius?: string;
925
+ };
926
+ /**
927
+ * Enter/exit motion of the Messages surface. Only the body slides; the bar
928
+ * is persistent chrome and never animates. Durations are milliseconds and 0
929
+ * disables that leg; `prefers-reduced-motion` always wins over these.
930
+ */
931
+ motion?: {
932
+ /** Entrance slide-and-fade duration: bare ms number, or a CSS time string. @default 180 */
933
+ enterDurationMs?: number | string;
934
+ /** Entrance easing. @default "cubic-bezier(0, 0, 0.2, 1)" */
935
+ enterEasing?: string;
936
+ /** Exit slide-and-fade duration: bare ms number, or a CSS time string. @default 160 */
937
+ exitDurationMs?: number | string;
938
+ /** Exit easing. @default "cubic-bezier(0.4, 0, 1, 1)" */
939
+ exitEasing?: string;
940
+ };
941
+ }
942
+ /**
943
+ * The portaled icon-control tooltip (header controls, composer buttons) and
944
+ * its trailing shortcut hint chip. Unset keys keep the built-in dark look.
945
+ */
946
+ interface TooltipTokens {
947
+ /** Bubble and arrow fill. @default "#111827" */
948
+ background?: TokenReference<'color'>;
949
+ /** Label color. @default "#ffffff" */
950
+ foreground?: TokenReference<'color'>;
951
+ /** Trailing shortcut hint color. @default "rgba(255, 255, 255, 0.55)" */
952
+ hintForeground?: TokenReference<'color'>;
953
+ /** Bubble corner radius. Defaults to `palette.radius.sm`. */
954
+ borderRadius?: TokenReference<'radius'>;
955
+ /** Label type size. @default "12px" */
956
+ fontSize?: string;
957
+ /** Bubble inset, full CSS shorthand. @default "6px 12px" */
958
+ padding?: TokenReference<'spacing'>;
959
+ /** Bubble box-shadow (token ref or raw CSS, e.g. `none`). */
960
+ shadow?: string;
961
+ /** Render the caret pointing at the control. @default true */
962
+ arrow?: boolean;
963
+ /** Wrap width. @default "min(320px, calc(100vw - 16px))" */
964
+ maxWidth?: string;
965
+ }
966
+ /**
967
+ * The hover-revealed action row under a message (copy, vote, read aloud).
968
+ * Unset keys inherit the shared ghost icon-button wash, which is already
969
+ * scheme-aware, so most themes never need this group.
970
+ */
971
+ interface MessageActionsTokens {
972
+ /** Hover fill. Defaults to `components.button.ghost.hoverBackground`. */
973
+ hoverBackground?: TokenReference<'color'>;
974
+ /** Hover icon color. Defaults to `semantic.colors.text`. */
975
+ hoverForeground?: TokenReference<'color'>;
976
+ /** Button corner radius. Defaults to `palette.radius.md`. */
977
+ borderRadius?: TokenReference<'radius'>;
632
978
  }
633
979
  interface MessageTokens {
634
980
  user: {
@@ -974,7 +1320,13 @@ interface ComponentTokens {
974
1320
  launcher: LauncherTokens;
975
1321
  panel: PanelTokens;
976
1322
  header: HeaderTokens;
1323
+ /** Messages rail chrome. */
1324
+ history?: HistoryTokens;
1325
+ /** Portaled icon-control tooltip and its shortcut hint chip. */
1326
+ tooltip?: TooltipTokens;
977
1327
  message: MessageTokens;
1328
+ /** Hover-revealed per-message action row (copy, vote, read aloud). */
1329
+ messageActions?: MessageActionsTokens;
978
1330
  /** Welcome / intro card shown above the message list. */
979
1331
  introCard?: IntroCardTokens;
980
1332
  /** Markdown surfaces (chat + artifact pane). */
@@ -1576,6 +1928,7 @@ type RuntypeClientChatRequest = {
1576
1928
  };
1577
1929
  type RuntypeClientChatStreamEvent = RuntypeExecutionStreamEvent;
1578
1930
  type RuntypeClientResumeRequest = {
1931
+ assistantMessageId?: string;
1579
1932
  clientTools?: Array<{
1580
1933
  description: string;
1581
1934
  name: string;
@@ -1667,6 +2020,64 @@ type ResolvedTarget = {
1667
2020
  payload: Record<string, unknown>;
1668
2021
  };
1669
2022
 
2023
+ /**
2024
+ * Durable visitor-credential store for per-visitor conversation history
2025
+ * (client-token mode only). Holds the raw `cvt_…` secret under a localStorage
2026
+ * key namespaced by a hash of the client token, degrades to memory after the
2027
+ * first storage throw, and observes cross-tab changes through the `storage`
2028
+ * event. One instance is owned by the controller and injected into every
2029
+ * `AgentWidgetClient` it builds; reuse is keyed on the identity tuple
2030
+ * `(clientToken, keyPrefix, persistDisabled)`.
2031
+ */
2032
+ interface VisitorStoreChange {
2033
+ previousToken: string | null;
2034
+ token: string | null;
2035
+ /** "local" = this store's own set/clear; "external" = observed from outside. */
2036
+ source: "local" | "external";
2037
+ revision: number;
2038
+ }
2039
+ interface VisitorStore {
2040
+ /** Resolves once the hashed storage key exists; every op awaits it. */
2041
+ readonly ready: Promise<void>;
2042
+ get(): Promise<string | null>;
2043
+ set(token: string): Promise<void>;
2044
+ clear(): Promise<void>;
2045
+ /** Monotonic per instance; advances on every observed value change. */
2046
+ revision(): number;
2047
+ subscribe(callback: (change: VisitorStoreChange) => void): () => void;
2048
+ /**
2049
+ * Serialize the empty-store first init across same-origin tabs. Web Locks
2050
+ * when available; otherwise a best-effort localStorage lease (collision
2051
+ * reduction, not proof of exclusivity). Callers must re-read the store
2052
+ * inside `fn` and hold the lock through mint + write + immediate claim.
2053
+ */
2054
+ withFirstInitLock<T>(fn: () => Promise<T>): Promise<T>;
2055
+ matches(clientToken: string, keyPrefix: string, persistDisabled: boolean): boolean;
2056
+ destroy(): void;
2057
+ }
2058
+
2059
+ /**
2060
+ * History Wire Message Mapping
2061
+ *
2062
+ * Adapter from the Runtype `/v1/client/conversations` wire shape to widget
2063
+ * messages. The display projection (`displayContent`) is the only visible
2064
+ * authority: model-only content is never rendered and never re-enters the
2065
+ * model channel (`llmContent`/`rawContent` are never fabricated here).
2066
+ */
2067
+
2068
+ /** One message as served by the client conversation history route. */
2069
+ type HistoryWireMessage = {
2070
+ id: string;
2071
+ role: string;
2072
+ /** Model content: string (legacy render-safe fallback) or multi-modal parts. */
2073
+ content?: string | unknown[];
2074
+ /** Server-owned display projection. Absent and empty are distinct states. */
2075
+ displayContent?: string;
2076
+ /** False when no visible form is reconstructable (model content withheld). */
2077
+ displayAvailable: boolean;
2078
+ timestamp?: string;
2079
+ };
2080
+
1670
2081
  /**
1671
2082
  * Curated registry of lucide icons available to `renderLucideIcon`.
1672
2083
  *
@@ -1751,6 +2162,7 @@ declare const LUCIDE_ICONS: {
1751
2162
  readonly "ellipsis-vertical": IconNode;
1752
2163
  readonly menu: IconNode;
1753
2164
  readonly house: IconNode;
2165
+ readonly "panel-left": IconNode;
1754
2166
  readonly plus: IconNode;
1755
2167
  readonly minus: IconNode;
1756
2168
  readonly pencil: IconNode;
@@ -2927,6 +3339,59 @@ type AgentWidgetControllerEventMap = {
2927
3339
  executionId: string;
2928
3340
  after: string;
2929
3341
  };
3342
+ /**
3343
+ * History (Messages) surface events. Payloads are sanitized: never a visitor
3344
+ * token, identity proof, visitor/end-user id, or backend diagnostic string.
3345
+ */
3346
+ "history:opened": {
3347
+ presentation: ResolvedHistoryPresentation;
3348
+ returnSurface: HistoryReturnSurface;
3349
+ timestamp: number;
3350
+ };
3351
+ "history:closed": {
3352
+ returnSurface: HistoryReturnSurface;
3353
+ timestamp: number;
3354
+ };
3355
+ "history:conversationOpened": {
3356
+ conversationId: string;
3357
+ /** List title of the opened conversation; null when not yet known. */
3358
+ title: string | null;
3359
+ scope: HistoryScope;
3360
+ timestamp: number;
3361
+ };
3362
+ /**
3363
+ * A replacement conversation was committed (header action, in-panel "New
3364
+ * conversation", or `startNewConversation()`). `history:closed` alone cannot
3365
+ * distinguish this commit from a plain close.
3366
+ */
3367
+ "history:conversationStarted": {
3368
+ /** `null` when the provider committed without returning a record id. */
3369
+ conversationId: string | null;
3370
+ timestamp: number;
3371
+ };
3372
+ "history:conversationDeleted": {
3373
+ conversationId: string;
3374
+ scope: HistoryScope;
3375
+ /** The deleted record was the open one, so the transcript was replaced. */
3376
+ wasActive: boolean;
3377
+ timestamp: number;
3378
+ };
3379
+ "history:cleared": {
3380
+ deleted: number;
3381
+ scope: HistoryScope;
3382
+ /** `null` is a deliberate headless client-token-wide delete. */
3383
+ targetId: string | null;
3384
+ timestamp: number;
3385
+ };
3386
+ "history:identityReset": {
3387
+ remoteRevocationConfirmed: boolean;
3388
+ timestamp: number;
3389
+ };
3390
+ /** Deduped: emitted only when the discriminated state or reason changes. */
3391
+ "history:identityStatusChanged": {
3392
+ status: HistoryIdentityStatus;
3393
+ timestamp: number;
3394
+ };
2930
3395
  };
2931
3396
  /**
2932
3397
  * Layout for the artifact split / drawer (CSS lengths unless noted).
@@ -3067,6 +3532,8 @@ type AgentWidgetArtifactsLayoutConfig = {
3067
3532
  documentToolbarToggleActiveBackground?: string;
3068
3533
  /** Active view/source toggle border color. Sets `--persona-artifact-doc-toggle-active-border`. */
3069
3534
  documentToolbarToggleActiveBorderColor?: string;
3535
+ /** Active view/source toggle icon color (defaults to `documentToolbarIconColor`). Sets `--persona-artifact-doc-toggle-active-color`. */
3536
+ documentToolbarToggleActiveColor?: string;
3070
3537
  /** Show an expand/collapse toggle in the artifact toolbar (both presets). Expanded fills the widget with the pane and hides the chat column. Default: false. */
3071
3538
  showExpandToggle?: boolean;
3072
3539
  /** Show the copy control in the `default` toolbar preset (the `document` preset always shows it). Default: false. */
@@ -3079,13 +3546,20 @@ type AgentWidgetArtifactsLayoutConfig = {
3079
3546
  /** Tab fade width (CSS length). @default 24px */
3080
3547
  tabFadeSize?: string;
3081
3548
  /**
3082
- * Invoked when the document toolbar Refresh control is used (before the pane re-renders).
3083
- * Use to replay `connectStream`, refetch, etc.
3549
+ * Invoked when the document toolbar Refresh control is used (before the pane
3550
+ * re-renders). The button renders only while this handler is set: the refresh
3551
+ * glyph universally reads "reload this preview" (Claude artifacts, v0), so
3552
+ * keep the handler scoped to refreshing the rendered artifact — regenerating
3553
+ * content or resetting the conversation belongs to message-level or
3554
+ * conversation-level controls, not artifact chrome.
3084
3555
  */
3085
3556
  onDocumentToolbarRefresh?: () => void | Promise<void>;
3086
3557
  /**
3087
3558
  * Optional copy dropdown entries (shown when `documentToolbarShowCopyChevron` is true and this array is non-empty).
3088
3559
  * The main Copy control still performs default copy unless `onDocumentToolbarCopyMenuSelect` handles everything.
3560
+ * Without a handler, built-in ids work out of the box: `download` saves the
3561
+ * artifact (real filename/MIME for file artifacts, `<title>.md` otherwise);
3562
+ * `markdown`/`md` and `json`/`source` copy that form to the clipboard.
3089
3563
  */
3090
3564
  documentToolbarCopyMenuItems?: Array<{
3091
3565
  id: string;
@@ -3093,13 +3567,24 @@ type AgentWidgetArtifactsLayoutConfig = {
3093
3567
  }>;
3094
3568
  /**
3095
3569
  * When set, invoked for the chevron menu (and can override default copy per `actionId`).
3570
+ * Return `false` to fall through to the widget's built-in behavior for that
3571
+ * action id (`download` saves the artifact; copy ids copy); any other return
3572
+ * value keeps the handler's outcome as final.
3096
3573
  */
3097
3574
  onDocumentToolbarCopyMenuSelect?: (payload: {
3098
3575
  actionId: string;
3099
3576
  artifactId: string | null;
3100
3577
  markdown: string;
3101
3578
  jsonPayload: string;
3102
- }) => void | Promise<void>;
3579
+ /** File metadata when the selected artifact is a previewable file. */
3580
+ file?: PersonaArtifactFileMeta;
3581
+ /** Filename the built-in download would use (file basename, or `<title>.md`). */
3582
+ suggestedFilename: string;
3583
+ /** MIME type paired with `suggestedFilename`. */
3584
+ mime: string;
3585
+ /** Raw content the built-in download would write (unfenced source for file artifacts). */
3586
+ content: string;
3587
+ }) => void | boolean | Promise<void | boolean>;
3103
3588
  };
3104
3589
  /**
3105
3590
  * Where the artifact body renders by default. Every mode shows the compact
@@ -3942,6 +4427,11 @@ type AgentWidgetFeatureFlags = {
3942
4427
  * pills + optional free-text input.
3943
4428
  */
3944
4429
  askUserQuestion?: AgentWidgetAskUserQuestionFeature;
4430
+ /**
4431
+ * Per-visitor conversation history. Client token mode only; disabled by
4432
+ * default so no capability flag is sent on init and no UI mounts.
4433
+ */
4434
+ history?: AgentWidgetHistoryFeature;
3945
4435
  /**
3946
4436
  * Built-in `suggest_replies` follow-ups. When the assistant invokes the
3947
4437
  * tool, the widget shows the suggestions using `suggestions.followUps` and
@@ -4139,6 +4629,604 @@ type AgentWidgetAskUserQuestionFeature = {
4139
4629
  /** Style overrides for the sheet and pills. */
4140
4630
  styles?: AgentWidgetAskUserQuestionStyles;
4141
4631
  };
4632
+ /**
4633
+ * Copy overrides for the visitor-facing conversation history surface. These are
4634
+ * the widget's only localization mechanism for history, so every user-visible
4635
+ * history string is listed here.
4636
+ */
4637
+ interface AgentWidgetHistoryCopy {
4638
+ /** Title of the history view. Defaults to "Messages". */
4639
+ viewTitle?: string;
4640
+ /** Heading shown when the visitor has no stored conversations. */
4641
+ emptyTitle?: string;
4642
+ /** Body text shown when the visitor has no stored conversations. */
4643
+ emptyDescription?: string;
4644
+ /** Heading shown when a history request fails. */
4645
+ errorTitle?: string;
4646
+ /** Body text shown when a history request fails. */
4647
+ errorDescription?: string;
4648
+ /** Label for the retry action on the error state. */
4649
+ retryLabel?: string;
4650
+ /** Heading shown after a 429 rate-limited history response. */
4651
+ rateLimitedTitle?: string;
4652
+ /** Body text shown after a 429 rate-limited history response. */
4653
+ rateLimitedDescription?: string;
4654
+ /** Confirmation prompt before deleting a single conversation. */
4655
+ deleteConversationConfirm?: string;
4656
+ /** Confirmation prompt before deleting every conversation in the active scope. */
4657
+ clearHistoryConfirm?: string;
4658
+ /** Confirmation prompt before detaching this browser from its history identity. */
4659
+ resetIdentityConfirm?: string;
4660
+ /** Label for the action that starts a new server conversation. */
4661
+ newConversationLabel?: string;
4662
+ /** Label for the action that prepends the previous transcript page. */
4663
+ showEarlierMessagesLabel?: string;
4664
+ /** Accessible label for the transcript skeleton while a conversation loads. */
4665
+ openConversationLoadingLabel?: string;
4666
+ /** Body text when a selected conversation failed to load. */
4667
+ openConversationErrorTitle?: string;
4668
+ /** Label for the retry action after a conversation failed to load. */
4669
+ openConversationRetryLabel?: string;
4670
+ /** Label for the return-to-messages action after a conversation failed to load. */
4671
+ openConversationBackLabel?: string;
4672
+ /** Status notice after a deleted conversation was recovered into a fresh one. */
4673
+ conversationDeletedNotice?: string;
4674
+ /** Status notice after this browser was detached from its history identity. */
4675
+ identityResetNotice?: string;
4676
+ /** Status notice when a local reset succeeded but server revocation was unconfirmed. */
4677
+ identityResetUnconfirmedNotice?: string;
4678
+ /** Pinned group heading for starred conversations. */
4679
+ groupStarred?: string;
4680
+ /** Time-group heading for conversations updated today. */
4681
+ groupToday?: string;
4682
+ /** Time-group heading for conversations updated yesterday. */
4683
+ groupYesterday?: string;
4684
+ /** Time-group heading for the trailing 7-day window. */
4685
+ groupPrevious7Days?: string;
4686
+ /** Time-group heading for the trailing 30-day window. */
4687
+ groupPrevious30Days?: string;
4688
+ /** Time-group heading for older conversations, grouped by month and year. */
4689
+ groupMonthYear?: string;
4690
+ /** Scope title when history is limited to this browser. */
4691
+ browserOnlyTitle?: string;
4692
+ /** Scope description when history is limited to this browser. */
4693
+ browserOnlyDescription?: string;
4694
+ /** Scope title while an identity proof is being resolved. */
4695
+ verifyingTitle?: string;
4696
+ /** Scope description while an identity proof is being resolved. */
4697
+ verifyingDescription?: string;
4698
+ /** Scope title when history is available across signed-in devices. */
4699
+ verifiedTitle?: string;
4700
+ /** Scope description when history is available across signed-in devices. */
4701
+ verifiedDescription?: string;
4702
+ /** Scope title when the visitor must sign in again to view account history. */
4703
+ authenticationRequiredTitle?: string;
4704
+ /** Scope description when the visitor must sign in again to view account history. */
4705
+ authenticationRequiredDescription?: string;
4706
+ /** Scope title when the host identity provider threw or rejected. */
4707
+ identityProviderFailedTitle?: string;
4708
+ /** Scope description when the host identity provider threw or rejected. */
4709
+ identityProviderFailedDescription?: string;
4710
+ /** Scope title when the server did not admit a supplied identity proof. */
4711
+ proofNotAdmittedTitle?: string;
4712
+ /** Scope description when the server did not admit a supplied identity proof. */
4713
+ proofNotAdmittedDescription?: string;
4714
+ /** Label for the action that retries identity resolution. */
4715
+ retryIdentityLabel?: string;
4716
+ /** Accessible name of the header control that opens history. */
4717
+ openHistoryLabel?: string;
4718
+ /** Accessible name of that control while a turn is streaming or resuming. */
4719
+ openHistoryBusyLabel?: string;
4720
+ /** Least-destructive action in every history confirmation dialog. */
4721
+ confirmCancelLabel?: string;
4722
+ /** Heading of the delete-one confirmation. */
4723
+ deleteConversationConfirmTitle?: string;
4724
+ /** Confirming action of the delete-one confirmation. */
4725
+ deleteConversationConfirmLabel?: string;
4726
+ /** Heading of the delete-all confirmation. */
4727
+ clearHistoryConfirmTitle?: string;
4728
+ /** Confirming action of the delete-all confirmation. */
4729
+ clearHistoryConfirmLabel?: string;
4730
+ /** Delete-all body used when the resolved scope is the signed-in user. */
4731
+ clearHistoryVerifiedConfirm?: string;
4732
+ /** Heading of the forget-this-device confirmation. */
4733
+ resetIdentityConfirmTitle?: string;
4734
+ /** Confirming action of the forget-this-device confirmation. */
4735
+ resetIdentityConfirmLabel?: string;
4736
+ /** Panel back control; returns to the surface that opened Messages. */
4737
+ backLabel?: string;
4738
+ /** Rail close control, shown only when the rail is not collapsible. */
4739
+ closeLabel?: string;
4740
+ /** Rail collapse toggle while the rail is expanded. */
4741
+ collapseLabel?: string;
4742
+ /** Rail collapse toggle while the rail is collapsed to icons. */
4743
+ expandLabel?: string;
4744
+ /** Accessible name of the docked rail's drag-resize handle. */
4745
+ resizeLabel?: string;
4746
+ /** Accessible status while the first page loads. */
4747
+ loadingLabel?: string;
4748
+ /** Label of the paging action below the last group. */
4749
+ loadMoreLabel?: string;
4750
+ /** Label of that action while its page is in flight. */
4751
+ loadingMoreLabel?: string;
4752
+ /**
4753
+ * Heading over the conversation list. Visible in rail presentation, where it
4754
+ * carries the list overflow trigger; sr-only in panel presentation.
4755
+ */
4756
+ conversationsTitle?: string;
4757
+ /** Accessible name of the per-row overflow trigger and its menu. */
4758
+ rowActionsLabel?: string;
4759
+ /** Accessible name of the list-level overflow trigger and its menu. */
4760
+ listOptionsLabel?: string;
4761
+ /** Delete item inside the per-row overflow menu. */
4762
+ deleteConversationLabel?: string;
4763
+ /** Delete-all item inside the list overflow menu. */
4764
+ clearHistoryLabel?: string;
4765
+ /** Forget-this-device item inside the list overflow menu. */
4766
+ resetIdentityLabel?: string;
4767
+ /** Row message count. `{count}` placeholder. */
4768
+ messageCountLabel?: string;
4769
+ /** Row message count for exactly one message. */
4770
+ messageCountLabelOne?: string;
4771
+ /** Announced after a single conversation was deleted. */
4772
+ conversationRemovedNotice?: string;
4773
+ /** Announced after every conversation in scope was deleted. */
4774
+ historyClearedNotice?: string;
4775
+ /** Heading shown when history is unavailable for this surface. */
4776
+ unavailableTitle?: string;
4777
+ /** Body text shown when history is unavailable for this surface. */
4778
+ unavailableDescription?: string;
4779
+ /** Heading of the post-deletion replacement-init recovery state. */
4780
+ newConversationRequiredTitle?: string;
4781
+ /** Body text of the post-deletion replacement-init recovery state. */
4782
+ newConversationRequiredDescription?: string;
4783
+ /** Rate-limited wait guidance. `{seconds}` placeholder. */
4784
+ rateLimitedWaitDescription?: string;
4785
+ /** Row-adjacent error after a failed open. */
4786
+ openFailedLabel?: string;
4787
+ /** Row-adjacent error after a failed delete. */
4788
+ deleteFailedLabel?: string;
4789
+ /** Relative time for the most recent bucket. */
4790
+ relativeNow?: string;
4791
+ /** Relative time in minutes. `{value}` placeholder. */
4792
+ relativeMinutes?: string;
4793
+ /** Relative time in hours. `{value}` placeholder. */
4794
+ relativeHours?: string;
4795
+ /** Relative time in days. `{value}` placeholder. */
4796
+ relativeDays?: string;
4797
+ /** Relative time in weeks. `{value}` placeholder. */
4798
+ relativeWeeks?: string;
4799
+ /** Relative time in years. `{value}` placeholder. */
4800
+ relativeYears?: string;
4801
+ }
4802
+ /**
4803
+ * One row in a `features.history.rail.sections` navigation section. Icon
4804
+ * precedence, highest first: `renderIcon`, then `iconUrl`, then `icon`.
4805
+ * Whichever resolves first is built once and reused for the item's lifetime.
4806
+ */
4807
+ interface AgentWidgetHistoryRailSectionItem {
4808
+ /** Stable identity, stamped as `data-persona-rail-item`. */
4809
+ id: string;
4810
+ /** Visible text, and the default `aria-label` of the button. */
4811
+ label: string;
4812
+ /**
4813
+ * Lucide name from the widget's built-in icon registry (see `IconName`). A
4814
+ * name outside the registry warns once and the row renders label-only.
4815
+ */
4816
+ icon?: IconName | (string & {});
4817
+ /** Image URL or data URI, rendered as a decorative `img` in the icon slot. */
4818
+ iconUrl?: string;
4819
+ /** Full custom icon node. Returning null renders the row label-only. */
4820
+ renderIcon?: () => Element | null;
4821
+ /** Small trailing text chip, for a count or a short status word. */
4822
+ badge?: string;
4823
+ /** Invoked on click. A throw is caught and warned once per section. */
4824
+ onSelect: () => void;
4825
+ }
4826
+ /** One navigation section in the history rail, above or below the list. */
4827
+ interface AgentWidgetHistoryRailSection {
4828
+ /** Stable identity, stamped as `data-persona-rail-section`. */
4829
+ id: string;
4830
+ /** Optional heading, styled like a conversation date-group heading. */
4831
+ title?: string;
4832
+ /** Default `"above-conversations"`. */
4833
+ placement?: "above-conversations" | "below-conversations" | "footer";
4834
+ items: AgentWidgetHistoryRailSectionItem[];
4835
+ }
4836
+ /**
4837
+ * Host-defined item in the list overflow menu (the `…` beside the
4838
+ * conversation-list heading). Rendered above the built-in destructive items.
4839
+ */
4840
+ interface AgentWidgetHistoryListAction {
4841
+ /** Stable identity; keeps menu focus keys stable across re-renders. */
4842
+ id: string;
4843
+ label: string;
4844
+ /** Destructive (red) styling like the built-in delete-all. Default false. */
4845
+ danger?: boolean;
4846
+ /** Receives the conversation summaries loaded at selection time. */
4847
+ onSelect: (context: {
4848
+ conversations: HistoryConversationSummary[];
4849
+ }) => void | Promise<void>;
4850
+ }
4851
+ /**
4852
+ * Feature config for per-visitor conversation history. Without a `provider`,
4853
+ * client token mode only: the built-in Runtype backend needs one, so the UI
4854
+ * never renders for proxy/agent sessions. A `provider` lifts that restriction.
4855
+ */
4856
+ interface AgentWidgetHistoryFeature {
4857
+ /** Master switch. Default false: no capability flag on init, no UI. */
4858
+ enabled?: boolean;
4859
+ /**
4860
+ * Custom conversation-history backend. Supply one to run the history UX
4861
+ * (list, open, delete, delete-all, header title binding) against your own
4862
+ * storage in ANY session mode, including a custom `apiUrl` backend with no
4863
+ * client token. Omitted, history falls back to the built-in Runtype backend,
4864
+ * which requires client token mode.
4865
+ *
4866
+ * Pass either an instance or a factory. The factory form is called once per
4867
+ * widget instance, so a single script-tag config object (assembled before
4868
+ * install) can back several widgets without sharing provider state. Passing a
4869
+ * new factory identity through `update()` rebuilds the provider.
4870
+ *
4871
+ * Failures are signalled by throwing `HistoryProviderError` with a `code` from
4872
+ * `HistoryProviderErrorCode`. The view branches on that code alone: it never
4873
+ * reads message text, and an untyped throw degrades to a generic error state.
4874
+ *
4875
+ * `prepareOpen`/`prepareStartNew` resolve BEFORE anything visible changes:
4876
+ * they return a `PreparedHistoryActivation` whose `commit()` applies the
4877
+ * already-authorized binding and whose `discard()` idempotently abandons a
4878
+ * superseded activation, leaving the active chat untouched. The widget calls
4879
+ * exactly one of the two per prepared activation.
4880
+ *
4881
+ * Optional capabilities hide their affordances when absent: no `update`
4882
+ * removes the rename/star actions (including the built-in title-menu `star`),
4883
+ * and no `resetDevice` removes "forget this device".
4884
+ *
4885
+ * The provider's `capabilities.scopes` is authoritative: the widget derives a
4886
+ * default scope (`"verified-user"` when `getIdentityProof` is configured,
4887
+ * otherwise `"browser"`) and narrows it to what the provider advertises, so a
4888
+ * browser-only provider is never asked for a scope it cannot serve. An
4889
+ * explicit `features.history.scope` is a hard request and still fails closed
4890
+ * with `unsupported_scope`. `getIdentityProof` is never called for a supplied
4891
+ * provider, and `HistoryOperationContext` carries only the resolved scope;
4892
+ * report your own identity through `getIdentityStatus()` /
4893
+ * `subscribeIdentityStatus()`, which is what the scope banner and its retry
4894
+ * affordance read.
4895
+ *
4896
+ * Reopening the last conversation after a page reload is the host's job: the
4897
+ * widget's boot resume runs only on the built-in Runtype path, so with a
4898
+ * supplied provider the transcript is restored by the storage adapter while
4899
+ * `getActiveConversationId()` starts null (no active row, no
4900
+ * conversation-bound header title) until something opens a conversation.
4901
+ * Persist the id yourself and call `controller.openConversation(id)` on ready
4902
+ * if you want the last conversation to come back automatically.
4903
+ *
4904
+ * @example
4905
+ * ```js
4906
+ * features: { history: { enabled: true, provider: () => myProvider } }
4907
+ * ```
4908
+ */
4909
+ provider?: HistoryProvider | (() => HistoryProvider);
4910
+ /** Page size for the conversation list (default 25, server max 100). */
4911
+ pageSize?: number;
4912
+ /**
4913
+ * Default history placement. "panel" replaces the conversation surface;
4914
+ * "rail" requests a side navigation host whenever it is at least 720px wide
4915
+ * and collapses to panel below that; "auto" uses rail only for a wide inline
4916
+ * or docked shell and keeps floating launchers panel-based at every width.
4917
+ * Default "panel".
4918
+ */
4919
+ presentation?: "panel" | "rail" | "auto";
4920
+ /**
4921
+ * Geometry of the rail navigation column. `side` picks the edge it docks to
4922
+ * (default "left", beside the conversation); `width` is its fixed width in
4923
+ * px, clamped to 200-400 (default 260). `collapsible` (default true) puts a
4924
+ * collapse toggle in the rail header that shrinks it to a 52px icon rail, and
4925
+ * `defaultCollapsed` (default false) picks the state a visitor who has never
4926
+ * toggled it starts in. The chosen state is remembered per visitor alongside
4927
+ * the other `persistState` keys. Ignored in panel presentation.
4928
+ */
4929
+ rail?: {
4930
+ side?: "left" | "right";
4931
+ width?: number;
4932
+ collapsible?: boolean;
4933
+ defaultCollapsed?: boolean;
4934
+ /**
4935
+ * Drag handle on the docked rail's divider edge, resizing it live within
4936
+ * the same 200 to 400 clamp `width` takes. Default false. The chosen width
4937
+ * is remembered per visitor alongside the other `persistState` keys and
4938
+ * outranks a later `width` update, the way the collapsed state does; the
4939
+ * floating overlay rail inherits it but is never itself resizable, and a
4940
+ * collapsed icon column ignores it until it expands again.
4941
+ */
4942
+ resizable?: boolean;
4943
+ /**
4944
+ * Shape of the COLLAPSED rail. `"icon-rail"` (default) keeps the 52px icon
4945
+ * column beside the conversation. `"overlay"` removes the column entirely:
4946
+ * a trigger takes the leading edge of the conversation header, hovering or
4947
+ * tapping it floats the expanded rail over the conversation, and clicking
4948
+ * it pins the rail back open. The floating rail is transient, so leaving
4949
+ * it, Escape, a click outside, or selecting a conversation all dismiss it;
4950
+ * its own header toggle docks it instead, being the control the pointer
4951
+ * finds there. Geometry follows `width` and `side`; the collapsed rail's
4952
+ * chunk is not loaded until the first hover. Ignored when `collapsible` is
4953
+ * false or in panel presentation.
4954
+ */
4955
+ collapsedBehavior?: "icon-rail" | "overlay";
4956
+ /**
4957
+ * One brand declaration, placed in both of the rail's identity spots: the
4958
+ * header's heading area when expanded (the mark leading, `copy.viewTitle`
4959
+ * beside it as the wordmark), and the collapse toggle's rest face when the
4960
+ * rail is collapsed, where hover and keyboard focus reveal the panel glyph
4961
+ * under it. A coarse pointer keeps the glyph, having no hover to reveal it
4962
+ * with. Icon precedence, highest first: `render`, then `iconUrl`, then
4963
+ * `icon`. `render` receives the placement through `ctx.collapsed` (`true`
4964
+ * is the collapsed toggle face) and may return null to skip that spot.
4965
+ * `renderHeader` outranks this for the heading area; the collapsed face is
4966
+ * this slot's alone. Decorative either way: the view's accessible name
4967
+ * still comes from `copy.viewTitle`, and the toggle keeps its own label.
4968
+ * Ignored in panel presentation.
4969
+ */
4970
+ brand?: {
4971
+ /** Lucide name from the built-in registry; an unknown one warns once. */
4972
+ icon?: IconName | (string & {});
4973
+ /** Image URL or data URI, rendered as a decorative `img`. */
4974
+ iconUrl?: string;
4975
+ /** Full custom node. A throw warns once and drops the brand. */
4976
+ render?: (context: {
4977
+ collapsed: boolean;
4978
+ }) => Element | null;
4979
+ };
4980
+ /**
4981
+ * Full override of the rail header's identity area, outranking `brand`
4982
+ * there, re-invoked whenever the collapsed state changes. Return null to
4983
+ * leave the area empty, which leaves the collapse toggle standing alone.
4984
+ * The accessible name of the
4985
+ * view comes from `copy.viewTitle` either way: the heading stays in the
4986
+ * DOM, visually hidden, whenever this renders. Ignored in panel
4987
+ * presentation.
4988
+ */
4989
+ renderHeader?: (context: {
4990
+ collapsed: boolean;
4991
+ defaultTitle: string;
4992
+ }) => Element | null;
4993
+ /**
4994
+ * Extra navigation sections stacked around the conversation list, in array
4995
+ * order within each `placement` bucket. Rail-only in this release: a move
4996
+ * into panel presentation removes them and a move back re-renders them.
4997
+ */
4998
+ sections?: AgentWidgetHistoryRailSection[];
4999
+ /**
5000
+ * Keyboard shortcut for the collapse toggle, e.g. `"mod+b"` ("mod" is
5001
+ * Command on Apple platforms, Control elsewhere). Undefined by default, so
5002
+ * an embedded widget never claims a host page's keys. The same declaration
5003
+ * drives the binding, the toggle's tooltip hint chip, and its
5004
+ * `aria-keyshortcuts`.
5005
+ */
5006
+ collapseShortcut?: string | false;
5007
+ /**
5008
+ * Where `collapseShortcut` listens. Default `"widget"`: only while focus is
5009
+ * inside the widget. `"page"` claims the combo document-wide, which suits a
5010
+ * fullscreen widget that IS the app.
5011
+ */
5012
+ collapseShortcutScope?: "widget" | "page";
5013
+ };
5014
+ /**
5015
+ * History scope. Defaults to "verified-user" when getIdentityProof exists,
5016
+ * otherwise "browser". Before this browser has been identity-bound, a null
5017
+ * proof falls back to browser scope for that operation. Once visitor.endUserId
5018
+ * is non-null, a null proof fails closed until the host resets history identity.
5019
+ *
5020
+ * With a `provider`, this is a hard request: the provider must advertise it
5021
+ * in `capabilities.scopes` or every history operation fails with
5022
+ * `unsupported_scope`. Leave it unset to let the provider's advertised scope
5023
+ * win.
5024
+ */
5025
+ scope?: HistoryScope;
5026
+ /** Copy overrides. Every user-visible history string must be here. */
5027
+ copy?: AgentWidgetHistoryCopy;
5028
+ /**
5029
+ * Date bucketing of the conversation list. `"time"` (default) groups rows
5030
+ * under Today, Yesterday, Previous 7 days, Previous 30 days, and month
5031
+ * headings. `"none"` renders one flat list in server order instead, the
5032
+ * recents-style sidebar. Starred conversations keep their pinned group
5033
+ * either way.
5034
+ */
5035
+ grouping?: "time" | "none";
5036
+ /**
5037
+ * Leading avatar on each conversation row. Unset, rows show the launcher's
5038
+ * image mark (`launcher.iconUrl`) when one exists and are text-only
5039
+ * otherwise, the assistant-list default. Pass an image URL or a glyph to
5040
+ * always show a mark, or false to force text-only rows.
5041
+ */
5042
+ rowAvatar?: boolean | string;
5043
+ /** Show the evidence-based history scope/status beneath the Messages heading. Default true. */
5044
+ showScopeStatus?: boolean;
5045
+ /**
5046
+ * Visitor-facing delete of a single conversation via each row's overflow
5047
+ * menu. Default true. False hides the control only: it changes nothing about
5048
+ * what is stored or for how long, and custom row slots still receive
5049
+ * `requestDelete`. Turn off for deployments that treat conversations as
5050
+ * business records.
5051
+ */
5052
+ showDelete?: boolean;
5053
+ /**
5054
+ * The "Delete all conversations" item in the Messages overflow menu. Default
5055
+ * true. False hides the control only; storage and retention are unchanged.
5056
+ * The identity reset item is separate and unaffected.
5057
+ */
5058
+ showDeleteAll?: boolean;
5059
+ /**
5060
+ * Host items appended to the list overflow menu, above the built-in
5061
+ * destructive actions. The trigger renders whenever any item exists, so
5062
+ * these keep the menu alive even with `showDeleteAll: false`.
5063
+ */
5064
+ listActions?: AgentWidgetHistoryListAction[];
5065
+ }
5066
+ /** Resolved scope for a logical history operation. */
5067
+ type HistoryScope = "browser" | "verified-user";
5068
+ /** `presentation` after it has been resolved against the host container width. */
5069
+ type ResolvedHistoryPresentation = "panel" | "rail";
5070
+ /**
5071
+ * The surface Messages returns to on back/Escape. `"home"` only when a Home
5072
+ * Screen composition opened it; the core header button always records
5073
+ * `"conversation"`.
5074
+ */
5075
+ type HistoryReturnSurface = "home" | "conversation";
5076
+ /**
5077
+ * Evidence-based history identity state. Never inferred from the mere presence
5078
+ * of `getIdentityProof`, and never carries token, visitor, or end-user values.
5079
+ */
5080
+ type HistoryIdentityStatus = {
5081
+ state: "browser_only";
5082
+ reason: "configured_browser_scope" | "no_identity_provider" | "proof_unavailable_before_binding";
5083
+ } | {
5084
+ state: "verifying";
5085
+ } | {
5086
+ state: "verified";
5087
+ } | {
5088
+ state: "authentication_required";
5089
+ reason: "proof_unavailable_after_binding" | "invalid_identity_proof";
5090
+ } | {
5091
+ state: "identity_provider_failed";
5092
+ } | {
5093
+ state: "configuration_error";
5094
+ reason: "proof_not_admitted";
5095
+ } | {
5096
+ state: "resetting";
5097
+ } | {
5098
+ state: "unavailable";
5099
+ reason: "history_disabled" | "ineligible_mode";
5100
+ };
5101
+ /** Fully defaulted history copy. Every user-visible history string. */
5102
+ type ResolvedHistoryCopy = Required<AgentWidgetHistoryCopy>;
5103
+ /** List-region state handed to render hooks. */
5104
+ type HistoryViewState = {
5105
+ kind: "loading";
5106
+ phase: "initial" | "refresh" | "load-more";
5107
+ } | {
5108
+ kind: "ready";
5109
+ } | {
5110
+ kind: "empty";
5111
+ } | {
5112
+ kind: "error";
5113
+ reason: "unavailable" | "authentication_failed" | "authentication_required" | "identity_provider_failed" | "proof_not_admitted" | "unsupported_scope" | "unknown";
5114
+ retryable: boolean;
5115
+ } | {
5116
+ kind: "rate_limited";
5117
+ retryAfterSeconds: number;
5118
+ } | {
5119
+ kind: "new_conversation_required";
5120
+ };
5121
+ /** The single in-flight history operation, or `null` when idle. */
5122
+ type HistoryPendingAction = {
5123
+ kind: "refresh" | "load-more" | "start-new" | "clear" | "reset";
5124
+ } | {
5125
+ kind: "open" | "delete";
5126
+ conversationId: string;
5127
+ } | null;
5128
+ /**
5129
+ * Every history operation a render hook may invoke. Each routes through the
5130
+ * same controller/session path as the default renderer, so busy gating,
5131
+ * selection epochs, and confirmations behave identically.
5132
+ */
5133
+ type AgentWidgetHistoryRenderActions = {
5134
+ refresh(): Promise<void>;
5135
+ loadMore(): Promise<void>;
5136
+ openConversation(conversationId: string): Promise<void>;
5137
+ startNewConversation(): Promise<void>;
5138
+ /** Each request method opens Persona's accessible confirmation first. */
5139
+ requestDeleteConversation(conversationId: string): Promise<"deleted" | "cancelled">;
5140
+ requestClearConversationHistory(): Promise<"cleared" | "cancelled">;
5141
+ requestResetHistoryIdentity(): Promise<{
5142
+ outcome: "cancelled";
5143
+ } | {
5144
+ outcome: "reset";
5145
+ remoteRevocationConfirmed: boolean;
5146
+ }>;
5147
+ close(): void;
5148
+ };
5149
+ /** Context for `renderHistoryView`. Frozen snapshot; no provider or credentials. */
5150
+ type AgentWidgetRenderHistoryViewContext = {
5151
+ conversations: readonly HistoryConversationSummary[];
5152
+ activeConversationId: string | null;
5153
+ state: HistoryViewState;
5154
+ pendingAction: HistoryPendingAction;
5155
+ identityStatus: HistoryIdentityStatus;
5156
+ nextCursor: string | null;
5157
+ presentation: ResolvedHistoryPresentation;
5158
+ returnSurface: HistoryReturnSurface;
5159
+ config: AgentWidgetConfig;
5160
+ copy: ResolvedHistoryCopy;
5161
+ actions: AgentWidgetHistoryRenderActions;
5162
+ /** The default full view. Bypasses this hook only; lower slots still apply. */
5163
+ defaultRenderer(): HTMLElement;
5164
+ /** Re-run arbitration with the current snapshot. Inert after close/destroy. */
5165
+ requestRender(): void;
5166
+ /** Teardown for this render; runs before the next one and on close. */
5167
+ onCleanup(callback: () => void): void;
5168
+ };
5169
+ /** Context for `renderHistoryConversation` (one list row). */
5170
+ type AgentWidgetRenderHistoryConversationContext = {
5171
+ conversation: HistoryConversationSummary;
5172
+ active: boolean;
5173
+ pending: "opening" | "deleting" | null;
5174
+ presentation: ResolvedHistoryPresentation;
5175
+ config: AgentWidgetConfig;
5176
+ open(): Promise<void>;
5177
+ requestDelete(): Promise<"deleted" | "cancelled">;
5178
+ defaultRenderer(): HTMLElement;
5179
+ };
5180
+ /** Context for `renderHistoryHeader` (the Messages top bar). */
5181
+ type AgentWidgetRenderHistoryHeaderContext = {
5182
+ presentation: ResolvedHistoryPresentation;
5183
+ returnSurface: HistoryReturnSurface;
5184
+ identityStatus: HistoryIdentityStatus;
5185
+ pendingAction: HistoryPendingAction;
5186
+ config: AgentWidgetConfig;
5187
+ copy: ResolvedHistoryCopy;
5188
+ actions: Pick<AgentWidgetHistoryRenderActions, "close" | "startNewConversation">;
5189
+ defaultRenderer(): HTMLElement;
5190
+ };
5191
+ /**
5192
+ * Context for `renderHistoryState`. Invoked only for non-ready list states;
5193
+ * `retry`/`startNewConversation` are present only where they are safe, so
5194
+ * custom DOM never infers recovery behavior.
5195
+ */
5196
+ type AgentWidgetRenderHistoryStateContext = {
5197
+ state: Exclude<HistoryViewState, {
5198
+ kind: "ready";
5199
+ }>;
5200
+ identityStatus: HistoryIdentityStatus;
5201
+ presentation: ResolvedHistoryPresentation;
5202
+ config: AgentWidgetConfig;
5203
+ copy: ResolvedHistoryCopy;
5204
+ retry?: () => Promise<void>;
5205
+ startNewConversation?: () => Promise<void>;
5206
+ defaultRenderer(): HTMLElement;
5207
+ };
5208
+ /**
5209
+ * Context for `renderHistoryOpenError` (the transcript-level surface shown
5210
+ * when opening a conversation from the Messages list fails). `retry` and
5211
+ * `back` are the only exits: both route through the token-guarded open flow,
5212
+ * so custom DOM must not fetch on its own. `back` is present only when the
5213
+ * Messages surface is available to return to.
5214
+ */
5215
+ type AgentWidgetRenderHistoryOpenErrorContext = {
5216
+ conversationId: string;
5217
+ config: AgentWidgetConfig;
5218
+ /** Resolved shell copy the default surface renders. */
5219
+ copy: {
5220
+ title: string;
5221
+ retryLabel: string;
5222
+ backLabel: string;
5223
+ };
5224
+ /** Re-runs the open through Persona's token-guarded flow. */
5225
+ retry: () => void;
5226
+ /** Returns to the Messages list. Absent when history is unavailable. */
5227
+ back?: () => void;
5228
+ defaultRenderer(): HTMLElement;
5229
+ };
4142
5230
  type SSEEventRecord = {
4143
5231
  id: string;
4144
5232
  type: string;
@@ -4611,6 +5699,24 @@ type AgentWidgetLauncherTeaserConfig = {
4611
5699
  */
4612
5700
  dismissLabel?: string;
4613
5701
  };
5702
+ /**
5703
+ * Timing for the portaled icon-control tooltip (header, composer, rail).
5704
+ * Keyboard focus always opens immediately. Hover waits `delayMs` unless
5705
+ * another tooltip closed within `skipDelayMs` (toolbar scan).
5706
+ */
5707
+ type AgentWidgetTooltipConfig = {
5708
+ /**
5709
+ * Milliseconds to wait on hover before the first tooltip appears.
5710
+ * `0` restores the previous instant-open behavior.
5711
+ * @default 200
5712
+ */
5713
+ delayMs?: number;
5714
+ /**
5715
+ * After a tooltip closes, later hovers in this window skip `delayMs`.
5716
+ * @default 300
5717
+ */
5718
+ skipDelayMs?: number;
5719
+ };
4614
5720
  type AgentWidgetSendButtonConfig = {
4615
5721
  borderWidth?: string;
4616
5722
  borderColor?: string;
@@ -5662,6 +6768,21 @@ type ClientSession = {
5662
6768
  name: string;
5663
6769
  description: string | null;
5664
6770
  };
6771
+ /**
6772
+ * Active conversation record for this session. Optional only for rolling-deploy
6773
+ * compatibility with servers that predate the visitor history contract.
6774
+ */
6775
+ conversationId?: string;
6776
+ /**
6777
+ * Canonical resolved chat target (flow or agent). Normalized from the response
6778
+ * `targetId`, falling back to `flow.id` during rolling deployment. History code
6779
+ * reads this, never widget config.
6780
+ */
6781
+ targetId?: string;
6782
+ /** Opaque change token; differs whenever the conversation transcript mutated. */
6783
+ conversationRevision?: string;
6784
+ /** Visitor grant backing history. `token` appears only at mint. */
6785
+ visitor?: ClientVisitorGrant;
5665
6786
  /** Configuration from the server */
5666
6787
  config: {
5667
6788
  welcomeMessage: string | null;
@@ -5669,6 +6790,20 @@ type ClientSession = {
5669
6790
  theme: Record<string, unknown> | null;
5670
6791
  };
5671
6792
  };
6793
+ /**
6794
+ * Visitor credential and identity acknowledgement returned by /v1/client/init.
6795
+ * `expiresAt` stays the wire string: it is a server-slid idle window the widget
6796
+ * never evaluates locally.
6797
+ */
6798
+ type ClientVisitorGrant = {
6799
+ id: string;
6800
+ /** Replacement secret. Present only at mint; persist it before anything else. */
6801
+ token?: string;
6802
+ expiresAt: string;
6803
+ endUserId: string | null;
6804
+ /** Server acknowledgement of the supplied identity proof. Status metadata only. */
6805
+ identityStatus?: "not_provided" | "admitted" | "ignored";
6806
+ };
5672
6807
  /**
5673
6808
  * Raw API response from /v1/client/init endpoint
5674
6809
  */
@@ -5680,12 +6815,110 @@ type ClientInitResponse = {
5680
6815
  name: string;
5681
6816
  description: string | null;
5682
6817
  };
6818
+ /** Additive visitor history fields; optional for rolling-deploy compatibility. */
6819
+ conversationId?: string;
6820
+ targetId?: string;
6821
+ conversationRevision?: string;
6822
+ visitor?: ClientVisitorGrant;
5683
6823
  config: {
5684
6824
  welcomeMessage: string | null;
5685
6825
  placeholder: string;
5686
6826
  theme: Record<string, unknown> | null;
5687
6827
  };
5688
6828
  };
6829
+ /**
6830
+ * Transactional init handle. `commit()` installs only the client's session
6831
+ * cache; `discard()` is an idempotent no-op. Neither writes persisted ids.
6832
+ */
6833
+ type PreparedClientSession = {
6834
+ session: ClientSession;
6835
+ commit(): void;
6836
+ discard(): void;
6837
+ };
6838
+ /**
6839
+ * One conversation row, normalized at the Runtype boundary. The deprecated wire
6840
+ * `flowId` alias never escapes that boundary: history code reads `targetId`.
6841
+ */
6842
+ type HistoryConversationSummary = {
6843
+ id: string;
6844
+ /** Server-generated; rendered verbatim, never derived locally. */
6845
+ title: string;
6846
+ /** Resolved chat target (flow or agent); `null` when the server omits it. */
6847
+ targetId: string | null;
6848
+ /** Server-produced plain-text preview; `null` when unavailable. */
6849
+ preview: string | null;
6850
+ messageCount: number;
6851
+ createdAt: string;
6852
+ updatedAt: string;
6853
+ /** Visitor-pinned flag. Absent when the provider has no update capability. */
6854
+ starred?: boolean;
6855
+ };
6856
+ /** Visitor-editable conversation metadata. Absent fields are left unchanged. */
6857
+ type HistoryConversationPatch = {
6858
+ title?: string;
6859
+ starred?: boolean;
6860
+ };
6861
+ type HistoryConversationPage = {
6862
+ data: HistoryConversationSummary[];
6863
+ nextCursor: string | null;
6864
+ };
6865
+ /**
6866
+ * Conversation detail. Messages stay on the wire shape: mapping to widget
6867
+ * messages belongs to `utils/history-messages.ts`.
6868
+ */
6869
+ type HistoryConversationDetail = {
6870
+ summary: HistoryConversationSummary;
6871
+ messages: HistoryWireMessage[];
6872
+ nextMessageCursor: string | null;
6873
+ conversationRevision: string | null;
6874
+ };
6875
+ /** One finalized visitor-visible projection for an already-stored message. */
6876
+ type HistoryDisplayProjection = {
6877
+ id: string;
6878
+ displayContent: string;
6879
+ };
6880
+ /**
6881
+ * Pending projection marker. Only ids are stored: the display strings already
6882
+ * live in the persisted messages and are never duplicated.
6883
+ */
6884
+ type PendingDisplayProjections = {
6885
+ conversationId: string;
6886
+ messageIds: string[];
6887
+ };
6888
+ /**
6889
+ * Internal history dependencies the controller injects into the session and
6890
+ * every client it builds. Not part of the public config surface.
6891
+ */
6892
+ interface WidgetHistoryInternals {
6893
+ visitorStore?: VisitorStore;
6894
+ /** Resolves once stored state has been applied; gates history-capable init. */
6895
+ historyBootstrapReady?: Promise<void>;
6896
+ /**
6897
+ * The one production provider is built by the shell from client-token config
6898
+ * (or taken from the internal demo registry). Session/UI history code depends
6899
+ * on this seam, never on `AgentWidgetClient`.
6900
+ */
6901
+ historyProvider?: HistoryProvider;
6902
+ /** Persist the revision beside the active conversation id (internal only). */
6903
+ setStoredConversationRevision?: (revision: string | null) => void;
6904
+ getStoredConversationRevision?: () => string | null;
6905
+ /** "Show earlier messages" cursor for the persisted transcript. */
6906
+ setStoredMessageCursor?: (cursor: string | null) => void;
6907
+ getStoredMessageCursor?: () => string | null;
6908
+ /**
6909
+ * Display projections finalized in the browser but not yet acknowledged by
6910
+ * the server. Absent callbacks mean memory-only (persistence disabled).
6911
+ */
6912
+ setPendingDisplayProjections?: (pending: PendingDisplayProjections | null) => void;
6913
+ getPendingDisplayProjections?: () => PendingDisplayProjections | null;
6914
+ onHistoryAvailabilityChanged?: (available: boolean) => void;
6915
+ /** Deduped status changes; carries no token, proof, or identity value. */
6916
+ onHistoryIdentityStatusChanged?: (status: HistoryIdentityStatus) => void;
6917
+ onHistoryContinuityChanged?: (info: {
6918
+ previousConversationId: string | null;
6919
+ conversationId: string;
6920
+ }) => void;
6921
+ }
5689
6922
  /**
5690
6923
  * Request payload for /v1/client/chat endpoint
5691
6924
  */
@@ -5695,6 +6928,11 @@ type ClientChatRequest = {
5695
6928
  id?: string;
5696
6929
  role: 'user' | 'assistant' | 'system';
5697
6930
  content: MessageContent;
6931
+ /**
6932
+ * Visitor-visible projection, sent only where it diverges from the model
6933
+ * channel above (contract fact #15). Never model input or merge authority.
6934
+ */
6935
+ displayContent?: string;
5698
6936
  }>;
5699
6937
  /** ID for the expected assistant response message */
5700
6938
  assistantMessageId?: string;
@@ -5752,6 +6990,13 @@ type AgentWidgetHeaderTrailingAction = {
5752
6990
  destructive?: boolean;
5753
6991
  dividerBefore?: boolean;
5754
6992
  }>;
6993
+ /**
6994
+ * Keyboard shortcut that activates this action, e.g. `"mod+shift+h"` ("mod"
6995
+ * is Command on Apple platforms, Control elsewhere). Fires only while focus
6996
+ * is inside the widget, and also drives the button's tooltip hint chip and
6997
+ * its `aria-keyshortcuts`.
6998
+ */
6999
+ shortcut?: string;
5755
7000
  };
5756
7001
  /**
5757
7002
  * Context provided to header render functions
@@ -5795,6 +7040,15 @@ type AgentWidgetHeaderLayoutConfig = {
5795
7040
  showIcon?: boolean;
5796
7041
  /** Show/hide the title */
5797
7042
  showTitle?: boolean;
7043
+ /**
7044
+ * What the header title (or `titleMenu` label) displays. `"static"`
7045
+ * (default) always shows `launcher.title`. `"conversation"` shows the active
7046
+ * conversation's title — the Claude-style pairing for a `titleMenu` holding
7047
+ * conversation actions — falling back to `launcher.title` while no titled
7048
+ * conversation is open (fresh chat, cleared history, or before the history
7049
+ * view has loaded titles). Requires `features.history` for titles to exist.
7050
+ */
7051
+ titleSource?: "static" | "conversation";
5798
7052
  /** Show/hide the subtitle */
5799
7053
  showSubtitle?: boolean;
5800
7054
  /** Show/hide the close button */
@@ -5845,8 +7099,16 @@ type AgentWidgetHeaderLayoutConfig = {
5845
7099
  destructive?: boolean;
5846
7100
  dividerBefore?: boolean;
5847
7101
  }>;
5848
- /** Called when a menu item is selected. */
5849
- onSelect: (id: string) => void;
7102
+ /**
7103
+ * Called when a menu item is selected. Returning `false` (sync or via
7104
+ * promise) falls through to the widget built-ins, mirroring the artifact
7105
+ * copy-menu contract: id `star` toggles the active conversation's star and
7106
+ * id `delete` runs the shell's confirm-then-delete on it (both require
7107
+ * `features.history` and, for star, a provider with the update
7108
+ * capability). `rename` has no built-in: hosts own the rename UI and call
7109
+ * `renameConversation()`.
7110
+ */
7111
+ onSelect: (id: string) => void | boolean | Promise<void | boolean>;
5850
7112
  /** Hover pill style. */
5851
7113
  hover?: {
5852
7114
  background?: string;
@@ -6417,15 +7679,20 @@ type LoadingIndicatorRenderContext = {
6417
7679
  */
6418
7680
  config: AgentWidgetConfig;
6419
7681
  /**
6420
- * Current streaming state (always true when indicator is shown)
7682
+ * Current streaming state. Always true for 'inline' and 'standalone';
7683
+ * false for 'conversation-open' (a history fetch, not a stream).
6421
7684
  */
6422
7685
  streaming: boolean;
6423
7686
  /**
6424
7687
  * Location where the indicator is rendered:
6425
7688
  * - 'inline': Inside a streaming assistant message bubble (when content is empty)
6426
7689
  * - 'standalone': Separate bubble while waiting for stream to start
7690
+ * - 'conversation-open': Transcript stand-in while a conversation opened
7691
+ * from the Messages list is being fetched. The returned element is mounted
7692
+ * inside Persona's centered transcript column, which keeps the status
7693
+ * role, announcement label, and composer gating.
6427
7694
  */
6428
- location: 'inline' | 'standalone';
7695
+ location: 'inline' | 'standalone' | 'conversation-open';
6429
7696
  /**
6430
7697
  * Function to render the default 3-dot bouncing indicator.
6431
7698
  * Call this if you want to use the default for certain cases.
@@ -6724,6 +7991,28 @@ type AgentWidgetConfig = {
6724
7991
  * ```
6725
7992
  */
6726
7993
  setStoredSessionId?: (sessionId: string) => void;
7994
+ /**
7995
+ * Called immediately before any cross-device history request and before a
7996
+ * conversationId resume of a conversation discovered on another device.
7997
+ * Return a fresh end-user access token (rt_eu_… / JWT). Null uses exact-browser
7998
+ * scope only for a never-bound visitor; a previously bound visitor fails closed
7999
+ * until resetHistoryIdentity() runs. Never cached by the widget.
8000
+ */
8001
+ getIdentityProof?: () => string | null | Promise<string | null>;
8002
+ /**
8003
+ * Read the persisted active conversation id (client token mode only).
8004
+ * Called only after the internal stored-state bootstrap gate resolves.
8005
+ */
8006
+ getStoredConversationId?: () => string | null;
8007
+ /** Persist the active conversation id so a later boot reopens the same record. */
8008
+ setStoredConversationId?: (conversationId: string) => void;
8009
+ /** Drop the persisted active conversation id (new conversation, deletion, reset). */
8010
+ clearStoredConversationId?: () => void;
8011
+ /**
8012
+ * Drop the persisted session id. Dedicated clear seam: it avoids widening
8013
+ * `setStoredSessionId` and its existing host call sites.
8014
+ */
8015
+ clearStoredSessionId?: () => void;
6727
8016
  /**
6728
8017
  * Static headers to include with each request.
6729
8018
  * For dynamic headers (e.g., auth tokens), use `getHeaders` instead.
@@ -6803,6 +8092,12 @@ type AgentWidgetConfig = {
6803
8092
  * @default false
6804
8093
  */
6805
8094
  autoFocusInput?: boolean;
8095
+ /**
8096
+ * Hover timing for the portaled control tooltip. Keyboard focus is
8097
+ * always immediate. Unset keys keep the ChatGPT/Claude defaults
8098
+ * (`delayMs: 200`, `skipDelayMs: 300`).
8099
+ */
8100
+ tooltip?: AgentWidgetTooltipConfig;
6806
8101
  launcher?: AgentWidgetLauncherConfig;
6807
8102
  initialMessages?: AgentWidgetMessage[];
6808
8103
  /**
@@ -7809,6 +9104,115 @@ type AgentWidgetInitOptions = {
7809
9104
  debugTools?: boolean;
7810
9105
  };
7811
9106
 
9107
+ /**
9108
+ * History provider seam (`docs/visitor-history-implementation-plan.md` D9).
9109
+ * Session/UI history code depends on this interface, never on
9110
+ * `AgentWidgetClient`.
9111
+ *
9112
+ * The module stays under `internal/` but its contract is public: `index-core.ts`
9113
+ * re-exports these declarations so integrators can implement
9114
+ * `features.history.provider`. The provider REGISTRY beside it stays private.
9115
+ */
9116
+
9117
+ /** Fixed for the lifetime of one opened history view/action chain. */
9118
+ interface HistoryOperationContext {
9119
+ scope: HistoryScope;
9120
+ }
9121
+ /**
9122
+ * An authorized-but-not-yet-applied conversation activation. The provider must
9123
+ * not mutate the active chat until `commit()`.
9124
+ */
9125
+ interface PreparedHistoryActivation {
9126
+ conversationId: string;
9127
+ conversationRevision: string;
9128
+ /** Apply the already-authorized provider-specific transport/session binding. */
9129
+ commit(): void | Promise<void>;
9130
+ /** Idempotently abandon a stale/superseded activation without changing chat. */
9131
+ discard(): void;
9132
+ }
9133
+ interface HistoryListOptions {
9134
+ cursor?: string;
9135
+ limit?: number;
9136
+ targetId?: string;
9137
+ context: HistoryOperationContext;
9138
+ }
9139
+ interface HistoryListResult {
9140
+ items: HistoryConversationSummary[];
9141
+ nextCursor: string | null;
9142
+ }
9143
+ interface HistoryPageOptions {
9144
+ cursor?: string;
9145
+ /** Lets the provider synthesize stable timestamps across page boundaries. */
9146
+ beforeCreatedAt?: string;
9147
+ context: HistoryOperationContext;
9148
+ }
9149
+ interface HistoryPageResult {
9150
+ summary: HistoryConversationSummary;
9151
+ /** Already mapped; the visitor-visible projection lives in `content`. */
9152
+ messages: AgentWidgetMessage[];
9153
+ conversationRevision: string;
9154
+ /** Follow for the next older page. `null` at the start of the transcript. */
9155
+ nextCursor: string | null;
9156
+ }
9157
+ interface HistoryDeleteAllOptions {
9158
+ /** Absent means the whole authorized scope, never the UI default. */
9159
+ targetId?: string;
9160
+ context: HistoryOperationContext;
9161
+ }
9162
+ /** The contract a `features.history.provider` implementation satisfies. */
9163
+ interface HistoryProvider {
9164
+ readonly capabilities: {
9165
+ scopes: readonly HistoryScope[];
9166
+ };
9167
+ getIdentityStatus(): HistoryIdentityStatus;
9168
+ subscribeIdentityStatus(callback: (status: HistoryIdentityStatus) => void): () => void;
9169
+ list(opts: HistoryListOptions): Promise<HistoryListResult>;
9170
+ getPage(id: string, opts: HistoryPageOptions): Promise<HistoryPageResult>;
9171
+ prepareOpen(id: string, opts: {
9172
+ context: HistoryOperationContext;
9173
+ }): Promise<PreparedHistoryActivation>;
9174
+ prepareStartNew(opts: {
9175
+ context: HistoryOperationContext;
9176
+ }): Promise<PreparedHistoryActivation>;
9177
+ delete(id: string, opts: {
9178
+ context: HistoryOperationContext;
9179
+ }): Promise<void>;
9180
+ deleteAll(opts: HistoryDeleteAllOptions): Promise<{
9181
+ deleted: number;
9182
+ }>;
9183
+ /**
9184
+ * Optional capability: visitor-scoped rename/star. Absence hides every
9185
+ * update affordance (star glyphs, built-in title-menu actions). A user-set
9186
+ * title pins: the provider must never let a later auto-generated title
9187
+ * overwrite one set through this call.
9188
+ */
9189
+ update?(id: string, patch: HistoryConversationPatch, opts: {
9190
+ context: HistoryOperationContext;
9191
+ }): Promise<HistoryConversationSummary>;
9192
+ /**
9193
+ * Optional capability. Absence hides "forget this device". Resolves (never
9194
+ * rejects) on remote failure; credentials are cleared in `finally` either way.
9195
+ */
9196
+ resetDevice?(): Promise<{
9197
+ remoteRevocationConfirmed: boolean;
9198
+ }>;
9199
+ subscribeAvailability?(callback: (available: boolean) => void): () => void;
9200
+ }
9201
+ /**
9202
+ * The one domain-error vocabulary for provider failures. HTTP strings and
9203
+ * status codes never reach the view. Branch on `code`, never on message text.
9204
+ */
9205
+ type HistoryProviderErrorCode = "not_found" | "rate_limited" | "authentication_failed" | "authentication_required" | "identity_provider_failed" | "proof_not_admitted" | "unsupported_scope" | "unavailable";
9206
+ declare class HistoryProviderError extends Error {
9207
+ readonly code: HistoryProviderErrorCode;
9208
+ /** Meaningful only for `rate_limited`. */
9209
+ readonly retryAfterSeconds?: number;
9210
+ constructor(code: HistoryProviderErrorCode, message: string, options?: {
9211
+ retryAfterSeconds?: number;
9212
+ });
9213
+ }
9214
+ declare function isHistoryProviderError(value: unknown): value is HistoryProviderError;
9215
+
7812
9216
  type DispatchOptions = {
7813
9217
  messages: AgentWidgetMessage[];
7814
9218
  signal?: AbortSignal;
@@ -7819,6 +9223,7 @@ type SSEHandler = (event: AgentWidgetEvent) => void;
7819
9223
  type SSEEventCallback = (eventType: string, payload: unknown) => void;
7820
9224
  declare class AgentWidgetClient {
7821
9225
  private config;
9226
+ private historyInternals;
7822
9227
  private readonly apiUrl;
7823
9228
  private readonly headers;
7824
9229
  private readonly debug;
@@ -7834,8 +9239,14 @@ declare class AgentWidgetClient {
7834
9239
  private lastSentClientToolsFingerprint;
7835
9240
  private clientToolsFingerprintSessionId;
7836
9241
  private sentNonEmptyClientToolsSessionId;
9242
+ private historyUnavailable;
9243
+ private historyUnavailableWarned;
9244
+ private claimInFlight;
9245
+ private historyIdentityStatus;
9246
+ private historyIdentitySubscribers;
9247
+ private historyAvailabilitySubscribers;
7837
9248
  private readonly webMcpBridge;
7838
- constructor(config?: AgentWidgetConfig);
9249
+ constructor(config?: AgentWidgetConfig, historyInternals?: WidgetHistoryInternals);
7839
9250
  /**
7840
9251
  * Refresh config in place WITHOUT tearing down the live connection or the
7841
9252
  * WebMCP bridge. `AgentWidgetSession.updateConfig` calls this when only
@@ -7855,6 +9266,8 @@ declare class AgentWidgetClient {
7855
9266
  * in-flight resolve alive.
7856
9267
  */
7857
9268
  updateConfig(next: AgentWidgetConfig): void;
9269
+ /** Re-thread the controller-owned history dependencies (store rebuild). */
9270
+ setHistoryInternals(internals: WidgetHistoryInternals): void;
7858
9271
  /**
7859
9272
  * Set callback for capturing raw SSE events
7860
9273
  */
@@ -7903,6 +9316,13 @@ declare class AgentWidgetClient {
7903
9316
  * Check if operating in agent execution mode
7904
9317
  */
7905
9318
  isAgentMode(): boolean;
9319
+ /**
9320
+ * Base URL for Runtype client-surface routes (`/v1/client/*`,
9321
+ * `/v1/agents/*`). Strips a configured `/v1/dispatch` suffix so an apiUrl
9322
+ * pointed at the dispatch endpoint still resolves its sibling routes. Not
9323
+ * used for proxy-mode URLs, whose resume route is `${apiUrl}/resume`.
9324
+ */
9325
+ private clientApiBase;
7906
9326
  /**
7907
9327
  * Get the appropriate API URL based on mode
7908
9328
  */
@@ -7916,7 +9336,72 @@ declare class AgentWidgetClient {
7916
9336
  * Called automatically on first message if not already initialized.
7917
9337
  */
7918
9338
  initSession(): Promise<ClientSession>;
9339
+ /** Visitor history rides on client-token init only, and latches off after a 403 degrade. */
9340
+ private isHistoryCapable;
9341
+ private readVisitorToken;
9342
+ /** One-way, client-lifetime latch: chat keeps working without history. */
9343
+ private markHistoryUnavailable;
9344
+ /** Public, secret-free view of the current identity state. */
9345
+ getHistoryIdentityStatus(): HistoryIdentityStatus;
9346
+ /** Deduped status notifications; carries no token, proof, or identity value. */
9347
+ subscribeHistoryIdentityStatus(callback: (status: HistoryIdentityStatus) => void): () => void;
9348
+ /** Fires only on the one-way 403 degrade; availability never returns. */
9349
+ subscribeHistoryAvailability(callback: (available: boolean) => void): () => void;
9350
+ /** Config-derived state before any per-operation evidence exists. */
9351
+ private restingIdentityStatus;
9352
+ /** Keeps an already-observed browser_only reason; otherwise derives one. */
9353
+ private browserOnlyStatus;
9354
+ private derivedBrowserOnly;
9355
+ /** Identical consecutive states are not re-announced. */
9356
+ private setHistoryIdentityStatus;
9357
+ /**
9358
+ * The single uncached init primitive: builds one body, performs one fetch.
9359
+ * `conversationId` and `sessionId` are mutually exclusive on the wire (strict
9360
+ * server union), so a resume never carries the stored session id.
9361
+ */
9362
+ private createClientSession;
7919
9363
  private _doInitSession;
9364
+ /**
9365
+ * An empty store means this init may mint a visitor, so it runs under the
9366
+ * cross-tab first-init lock: a waiter re-reads inside the lock and joins the
9367
+ * winner's visitor instead of minting a second one.
9368
+ */
9369
+ private ordinaryInit;
9370
+ private doOrdinaryInit;
9371
+ /**
9372
+ * Ordinary init carrying an identity proof: binds/rebinds the visitor,
9373
+ * persists any replacement token (inside `createClientSession`), and installs
9374
+ * the result as the live session.
9375
+ */
9376
+ private reinitWithProof;
9377
+ /**
9378
+ * A minted visitor means the record this session just created is still
9379
+ * unowned; one immediate re-init with `{visitorToken, sessionId}` claims it.
9380
+ */
9381
+ private claimFirstConversation;
9382
+ /**
9383
+ * Continuity guard + id persistence. A different record than the persisted
9384
+ * one is a privacy transition, announced before the new id is written.
9385
+ */
9386
+ private finishInit;
9387
+ /** Wrap an uncached init so nothing installs until the winner commits. */
9388
+ private prepared;
9389
+ /**
9390
+ * Transactional reopen of a known conversation. Always bypasses the session
9391
+ * cache, never sends the stored session id, and needs a credential the server
9392
+ * will accept (stored visitor token or a caller-supplied proof).
9393
+ */
9394
+ prepareConversationSession(conversationId: string, opts?: {
9395
+ proof?: string | null;
9396
+ }): Promise<PreparedClientSession>;
9397
+ /** Transactional new conversation: no stored session id, no conversation id. */
9398
+ prepareNewConversationSession(): Promise<PreparedClientSession>;
9399
+ /**
9400
+ * D3 privacy boundary: a sibling tab replaced or revoked the shared visitor
9401
+ * credential. Revoking it does not revoke an already-minted chat session, so
9402
+ * the cache must go, and whatever this visitor was bound to is gone with it.
9403
+ */
9404
+ handleExternalCredentialChange(): void;
7920
9405
  /**
7921
9406
  * Clear the current client session
7922
9407
  */
@@ -7989,6 +9474,83 @@ declare class AgentWidgetClient {
7989
9474
  * @param comment - Optional comment
7990
9475
  */
7991
9476
  submitNPSFeedback(rating: number, comment?: string): Promise<void>;
9477
+ /** `/v1/client/<path>` with a query string; credentials ride in headers. */
9478
+ private historyUrl;
9479
+ /** Explicit per-operation scope wins; otherwise config, then evidence. */
9480
+ private resolveHistoryScope;
9481
+ /**
9482
+ * Resolve the proof for one logical request. `null` is an intentional
9483
+ * browser-scope fallback only while the visitor has never been bound.
9484
+ */
9485
+ private resolveIdentityProof;
9486
+ /** Bind the visitor before the first verified request; admitted proofs only. */
9487
+ private bindIdentity;
9488
+ private readErrorCode;
9489
+ /**
9490
+ * Selective one-shot 401 recovery. Returns the session to retry under;
9491
+ * anything unrecoverable throws typed and is never retried.
9492
+ */
9493
+ private recoverFromUnauthorized;
9494
+ private historyErrorFor;
9495
+ /**
9496
+ * Validate `X-History-Identity-Status` before any body is committed: the
9497
+ * per-operation acknowledgement, not a prior init, is what proves scope.
9498
+ */
9499
+ private commitIdentityAcknowledgement;
9500
+ /**
9501
+ * Shared history transport: live session, `sessionId` query param,
9502
+ * `X-Visitor-Token` header, one resolved proof, one-shot 401 recovery, and a
9503
+ * credential-revision guard that discards a response the store outran.
9504
+ */
9505
+ private historyFetch;
9506
+ private assertHistoryUsable;
9507
+ /** One page of the visitor's conversations, newest first. */
9508
+ listConversations(opts?: {
9509
+ cursor?: string;
9510
+ limit?: number;
9511
+ targetId?: string;
9512
+ scope?: HistoryScope;
9513
+ }): Promise<HistoryConversationPage>;
9514
+ /**
9515
+ * One transcript page (newest first, oldest-first within the page). Messages
9516
+ * stay on the wire shape: `utils/history-messages.ts` owns the mapping.
9517
+ */
9518
+ getConversation(conversationId: string, opts?: {
9519
+ messageCursor?: string;
9520
+ scope?: HistoryScope;
9521
+ }): Promise<HistoryConversationDetail>;
9522
+ /**
9523
+ * Finalize browser-derived visitor-visible projections for the ACTIVE
9524
+ * conversation. Transport op, not a history read: current session + browser
9525
+ * scope, never an identity proof.
9526
+ */
9527
+ finalizeDisplayProjections(conversationId: string, messages: HistoryDisplayProjection[]): Promise<{
9528
+ conversationRevision: string | null;
9529
+ }>;
9530
+ deleteConversation(conversationId: string, opts?: {
9531
+ scope?: HistoryScope;
9532
+ }): Promise<{
9533
+ deleted: number;
9534
+ }>;
9535
+ /**
9536
+ * Delete every conversation matching `targetId`. An omitted filter means the
9537
+ * whole authorized visitor/client-token scope: headless callers own that
9538
+ * choice, the UI always passes the active `ClientSession.targetId`.
9539
+ */
9540
+ deleteAllConversations(opts?: {
9541
+ targetId?: string;
9542
+ scope?: HistoryScope;
9543
+ }): Promise<{
9544
+ deleted: number;
9545
+ }>;
9546
+ /**
9547
+ * Revoke this browser's visitor credential. Always browser scope (the route
9548
+ * accepts no proof) and the local clear is unconditional: a failed remote
9549
+ * revocation still detaches this device.
9550
+ */
9551
+ resetVisitor(): Promise<{
9552
+ reset: true;
9553
+ }>;
7992
9554
  /**
7993
9555
  * Send a message - handles both proxy and client token modes
7994
9556
  */
@@ -8215,10 +9777,43 @@ type SessionCallbacks = {
8215
9777
  handle: ResumableHandle;
8216
9778
  attempt?: number;
8217
9779
  }) => void;
9780
+ /** Active-record/sendability changes the history UI renders. */
9781
+ onHistoryStateChanged?: (state: SessionHistoryState) => void;
9782
+ /** Non-error, secret-free status notices (recovery, continuity, diagnostics). */
9783
+ onHistoryNotice?: (notice: SessionHistoryNotice) => void;
9784
+ };
9785
+ /** Session-owned history state; carries no credential or identity value. */
9786
+ type SessionHistoryState = {
9787
+ activeConversationId: string | null;
9788
+ conversationRevision: string | null;
9789
+ /** Cursor for "show earlier messages"; `null` at the start of the transcript. */
9790
+ nextMessageCursor: string | null;
9791
+ /** Sending is refused until the recoverable state clears. */
9792
+ recovery: "new_conversation_required" | null;
9793
+ sendBlocked: boolean;
9794
+ };
9795
+ /** One prepended history page, plus the cursor for the next older one. */
9796
+ type HistoryOlderPage = {
9797
+ messages: AgentWidgetMessage[];
9798
+ nextMessageCursor: string | null;
9799
+ };
9800
+ type SessionHistoryNoticeCode =
9801
+ /** A 410 was recovered into a fresh conversation carrying only the new turn. */
9802
+ "conversation_deleted_recovered"
9803
+ /** The replacement conversation could not be prepared; Retry is required. */
9804
+ | "new_conversation_required"
9805
+ /** A boot/continuity transition invalidated the local transcript. */
9806
+ | "history_continuity_reset"
9807
+ /** Projection finalization failed after its one retry; the marker is kept. */
9808
+ | "projection_finalization_failed";
9809
+ type SessionHistoryNotice = {
9810
+ code: SessionHistoryNoticeCode;
9811
+ message: string;
8218
9812
  };
8219
9813
  declare class AgentWidgetSession {
8220
9814
  private config;
8221
9815
  private callbacks;
9816
+ private historyInternals;
8222
9817
  private client;
8223
9818
  private messages;
8224
9819
  private status;
@@ -8245,7 +9840,34 @@ declare class AgentWidgetSession {
8245
9840
  private voiceProvider;
8246
9841
  private voiceActive;
8247
9842
  private voiceStatus;
8248
- constructor(config: AgentWidgetConfig | undefined, callbacks: SessionCallbacks);
9843
+ private activeConversationId;
9844
+ private activeConversationRevision;
9845
+ private historyNextMessageCursor;
9846
+ /** Monotonic: a later selection supersedes every earlier fetch/prepare. */
9847
+ private historyOpenEpoch;
9848
+ /** Blocks `setClientSession`'s welcome branch across a reopen re-init. */
9849
+ private suppressWelcomeInjection;
9850
+ private historyRecovery;
9851
+ private historySendBlocked;
9852
+ /** Continuity wipe / boot reconciliation; dispatch waits on it. */
9853
+ private historyGate;
9854
+ /** Deduped by `(id, cursor)` so repeated clicks issue one request. */
9855
+ private olderPageRequests;
9856
+ /** Serializes projection finalization against every other operation. */
9857
+ private projectionFinalizationPromise;
9858
+ /** Message id → projection the server has acknowledged (sent or finalized). */
9859
+ private acknowledgedProjections;
9860
+ private pendingProjections;
9861
+ /** Persisted revision as it stood before boot init overwrote it. */
9862
+ private bootConversationRevision;
9863
+ private bootRevisionCaptured;
9864
+ /** Exactly one visitor-store subscription per instance; re-keyed with the store. */
9865
+ private visitorStoreUnsubscribe;
9866
+ private subscribedVisitorStore;
9867
+ /** An external credential change happened; the next dispatch must re-init. */
9868
+ private credentialReinitPending;
9869
+ private credentialReinitPromise;
9870
+ constructor(config: AgentWidgetConfig | undefined, callbacks: SessionCallbacks, historyInternals?: WidgetHistoryInternals);
8249
9871
  /**
8250
9872
  * Warm the deferred Runtype TTS engine chunk at init so it's resolved before
8251
9873
  * the first "Read aloud" click. Module fetch only — no AudioContext (that
@@ -8343,6 +9965,12 @@ declare class AgentWidgetSession {
8343
9965
  * Set the client session after initialization
8344
9966
  */
8345
9967
  setClientSession(session: ClientSession): void;
9968
+ /**
9969
+ * Welcome injection is skipped while `suppressWelcomeInjection` is latched:
9970
+ * reopening a stored conversation is not a new thread, and the hydrated
9971
+ * transcript would otherwise race a welcome bubble.
9972
+ */
9973
+ private injectWelcomeMessage;
8346
9974
  /**
8347
9975
  * Get current client session
8348
9976
  */
@@ -8383,6 +10011,201 @@ declare class AgentWidgetSession {
8383
10011
  * @param comment - Optional comment
8384
10012
  */
8385
10013
  submitNPSFeedback(rating: number, comment?: string): Promise<void>;
10014
+ /**
10015
+ * Re-thread the controller-owned history dependencies. Called before
10016
+ * `updateConfig` when the visitor-store identity tuple changed, so the live
10017
+ * client and any rebuilt one share the same store.
10018
+ */
10019
+ setHistoryInternals(internals: WidgetHistoryInternals): void;
10020
+ /** Widget teardown: release the visitor-store subscription. */
10021
+ destroy(): void;
10022
+ /**
10023
+ * The session always owns the continuity transition, whether or not the shell
10024
+ * supplied its own observer: a credential/record break must wipe local state
10025
+ * before the replacement session becomes sendable.
10026
+ */
10027
+ private composeHistoryInternals;
10028
+ private get historyProvider();
10029
+ private requireHistoryProvider;
10030
+ /**
10031
+ * One resolved scope per logical action. An explicitly requested scope the
10032
+ * provider cannot serve fails locally rather than silently downgrading.
10033
+ */
10034
+ private historyContext;
10035
+ getHistoryState(): SessionHistoryState;
10036
+ getActiveConversationId(): string | null;
10037
+ private emitHistoryState;
10038
+ private notifyHistory;
10039
+ /** Pending destructive/reconciliation work every other operation waits on. */
10040
+ awaitHistorySettled(): Promise<void>;
10041
+ private assertHistoryIdle;
10042
+ listConversations(opts?: {
10043
+ cursor?: string;
10044
+ limit?: number;
10045
+ targetId?: string;
10046
+ scope?: HistoryScope;
10047
+ }): Promise<HistoryListResult>;
10048
+ /**
10049
+ * Transactional reopen: read the newest page, prepare an authorized
10050
+ * activation, then commit only if this selection still wins. Nothing mutates
10051
+ * the active conversation before `commit()`.
10052
+ */
10053
+ openConversation(id: string, opts?: {
10054
+ scope?: HistoryScope;
10055
+ }): Promise<{
10056
+ summary: HistoryConversationSummary;
10057
+ nextMessageCursor: string | null;
10058
+ }>;
10059
+ /**
10060
+ * Prepend one older page. Deduped by `(id, cursor)`; merges by id and repaints
10061
+ * once (the `injectMessageBatch` single-render pattern).
10062
+ */
10063
+ loadOlderMessages(id: string, cursor?: string | null, opts?: {
10064
+ scope?: HistoryScope;
10065
+ }): Promise<HistoryOlderPage>;
10066
+ private fetchOlderPage;
10067
+ /**
10068
+ * The canonical new-thread operation. A failed prepare leaves the current
10069
+ * conversation completely intact.
10070
+ */
10071
+ startNewConversation(opts?: {
10072
+ scope?: HistoryScope;
10073
+ }): Promise<void>;
10074
+ /**
10075
+ * Clear local + persisted conversation state, then commit the replacement.
10076
+ * Welcome injection is deliberately allowed once the transcript is empty.
10077
+ */
10078
+ private installFreshConversation;
10079
+ /**
10080
+ * Deleting the active record (or everything) is already irreversible: the
10081
+ * transcript is destroyed first, then a replacement session is prepared.
10082
+ */
10083
+ deleteConversation(id: string, opts?: {
10084
+ scope?: HistoryScope;
10085
+ }): Promise<void>;
10086
+ /** Visitor-scoped rename/star. Requires a provider with the update capability. */
10087
+ updateConversation(id: string, patch: HistoryConversationPatch, opts?: {
10088
+ scope?: HistoryScope;
10089
+ }): Promise<HistoryConversationSummary>;
10090
+ /** True when the provider supports visitor-scoped rename/star. */
10091
+ canUpdateConversations(): boolean;
10092
+ clearConversationHistory(opts?: {
10093
+ targetId?: string;
10094
+ scope?: HistoryScope;
10095
+ }): Promise<{
10096
+ deleted: number;
10097
+ }>;
10098
+ /**
10099
+ * Revoke this browser's history credential. Resolves (never rejects) on
10100
+ * remote failure; the local wipe is unconditional either way.
10101
+ */
10102
+ resetHistoryDevice(): Promise<{
10103
+ remoteRevocationConfirmed: boolean;
10104
+ }>;
10105
+ private recoverFromDestroyedConversation;
10106
+ /**
10107
+ * Never reinstalls the deleted session. A failed preparation leaves an
10108
+ * explicit recoverable state instead of the old transcript.
10109
+ */
10110
+ private prepareReplacementConversation;
10111
+ /** The next explicit action retries a failed replacement preparation. */
10112
+ private retryRequiredConversation;
10113
+ /**
10114
+ * Install a prepared activation. The provider's commit also invokes the
10115
+ * session binding (`bindActivatedSession`); the fallback covers a shell that
10116
+ * has not wired that callback yet.
10117
+ */
10118
+ private commitActivation;
10119
+ /**
10120
+ * Session-owned binding for a winning prepared activation. Installs the
10121
+ * client session WITHOUT the ordinary welcome branch while the reopen latch
10122
+ * is set, and persists the replacement ids through the normal storage path.
10123
+ */
10124
+ bindActivatedSession(session: ClientSession): void;
10125
+ private persistConversationMetadata;
10126
+ /** Conversation-scoped caches that must not leak across records. */
10127
+ private resetConversationScopedState;
10128
+ /**
10129
+ * Irreversible local + persisted clear. Used by new-conversation, active
10130
+ * deletion, 410 recovery, reset, and the continuity wipe.
10131
+ */
10132
+ private discardConversationState;
10133
+ /**
10134
+ * D6 continuity wipe (session side): a replacement visitor, identity rebind,
10135
+ * cross-tab convergence, or credential expiry selected a different record.
10136
+ * Invalidate synchronously; dispatch stays blocked until cleanup completes.
10137
+ */
10138
+ private handleHistoryContinuityChanged;
10139
+ /**
10140
+ * One subscription per widget instance, re-keyed when the controller swaps
10141
+ * the store. Owned here so the transition sits beside the continuity wipe it
10142
+ * reuses.
10143
+ */
10144
+ private syncVisitorStoreSubscription;
10145
+ /**
10146
+ * D3 privacy boundary: a sibling tab cleared or replaced the shared visitor
10147
+ * credential. Privacy wins over turn continuity, so a live turn is cancelled.
10148
+ * A "local" change is this tab's own mint/write and owns its init path; a
10149
+ * change out of an empty store is first-init convergence, not a break.
10150
+ */
10151
+ private handleExternalCredentialChange;
10152
+ /**
10153
+ * Dispatch may not proceed until a session exists under the NEW credential.
10154
+ * Deliberately lazy: re-initializing on the storage event itself would hand
10155
+ * an idle tab a fresh credential the visitor just deleted elsewhere.
10156
+ */
10157
+ private completeCredentialReinit;
10158
+ private runCredentialReinit;
10159
+ /**
10160
+ * Authoritative boot reconciliation (D4). Runs after a `conversationId` boot
10161
+ * resume and before chat becomes sendable: an unchanged revision needs no
10162
+ * detail fetch; a changed or absent one refreshes from the server's newest
10163
+ * page under the same scope.
10164
+ */
10165
+ reconcileBootConversation(opts?: {
10166
+ scope?: HistoryScope;
10167
+ }): Promise<void>;
10168
+ private runBootReconciliation;
10169
+ /** Runtype transport op: active session + browser scope, never a proof. */
10170
+ private projectionFinalizationEnabled;
10171
+ private setPendingProjections;
10172
+ private readPendingProjections;
10173
+ /** Record what the dispatch payload carried as each message's projection. */
10174
+ private recordDispatchedProjections;
10175
+ /**
10176
+ * After a terminal assistant message, finalize any browser-derived projection
10177
+ * the server cannot have. Painting is never delayed by this.
10178
+ */
10179
+ private scheduleProjectionFinalization;
10180
+ /** Serialized: operations await this chain instead of racing it. */
10181
+ private enqueueProjectionFinalization;
10182
+ private finalizeProjections;
10183
+ /** Transport-shaped failures only; a contract failure is not retried. */
10184
+ private isTransientProjectionError;
10185
+ private clearFinalizedMarker;
10186
+ /**
10187
+ * Boot replay: rebuild the batch from the persisted ids plus the local
10188
+ * message content, then finalize before display reconciliation completes.
10189
+ */
10190
+ replayPendingProjections(): Promise<void>;
10191
+ /**
10192
+ * A local transcript mutation whose response carries no new revision: clear
10193
+ * the persisted one rather than guessing, so the next boot refreshes safely.
10194
+ */
10195
+ private invalidateConversationRevision;
10196
+ /** Blocks a send until the owning history transition finishes. */
10197
+ private awaitHistorySendable;
10198
+ private static isConversationDeleted;
10199
+ /**
10200
+ * Safe 410 recovery (D5). The old payload would recreate the transcript that
10201
+ * was just deleted, so the retry carries ONLY the just-submitted user turn.
10202
+ */
10203
+ private dispatchWithDeletedRecovery;
10204
+ /**
10205
+ * Capture only the newly submitted user message, destroy the deleted record's
10206
+ * local state, and initialize a fresh owned conversation to retry into.
10207
+ */
10208
+ private recoverFromDeletedConversation;
8386
10209
  updateConfig(next: AgentWidgetConfig): void;
8387
10210
  getMessages(): AgentWidgetMessage[];
8388
10211
  getStatus(): AgentWidgetSessionStatus;
@@ -9104,6 +10927,71 @@ type Controller = {
9104
10927
  * forwarded to `config.approval.onDecision`.
9105
10928
  */
9106
10929
  resolveApproval: (approvalId: string, decision: 'approved' | 'denied', options?: AgentWidgetApprovalDecisionOptions) => Promise<void>;
10930
+ /** Pass-through list, for headless hosts rendering their own navigation. */
10931
+ listConversations: (opts?: {
10932
+ cursor?: string;
10933
+ limit?: number;
10934
+ targetId?: string;
10935
+ scope?: HistoryScope;
10936
+ }) => Promise<{
10937
+ items: HistoryConversationSummary[];
10938
+ nextCursor: string | null;
10939
+ }>;
10940
+ /** The open conversation's record id; null for a fresh unsaved chat. */
10941
+ getActiveConversationId: () => string | null;
10942
+ /**
10943
+ * Full open flow: transactional resume, hydration, and scroll restore.
10944
+ * `focus: true` moves focus to the composer; the programmatic default
10945
+ * leaves focus alone (an embedded widget must not scroll the host page
10946
+ * on a boot-time reopen).
10947
+ */
10948
+ openConversation: (conversationId: string, opts?: {
10949
+ focus?: boolean;
10950
+ }) => Promise<void>;
10951
+ /** Clean local state plus a new owned server conversation. `focus` as on `openConversation`. */
10952
+ startNewConversation: (opts?: {
10953
+ focus?: boolean;
10954
+ }) => Promise<void>;
10955
+ /** Permanently delete one server record; the active one is replaced. */
10956
+ deleteConversation: (conversationId: string) => Promise<void>;
10957
+ /**
10958
+ * Visitor-scoped rename. Requires a provider with the update capability;
10959
+ * a user-set title pins, so a later auto-generated title never overwrites it.
10960
+ */
10961
+ renameConversation: (conversationId: string, title: string) => Promise<HistoryConversationSummary>;
10962
+ /** Visitor-scoped star/unstar. Requires a provider with the update capability. */
10963
+ setConversationStarred: (conversationId: string, starred: boolean) => Promise<HistoryConversationSummary>;
10964
+ /**
10965
+ * Permanently delete every record in the resolved scope. Defaults to the
10966
+ * active target filter; `allTargets` is a deliberate client-token-wide delete.
10967
+ */
10968
+ clearConversationHistory: (opts?: {
10969
+ targetId?: string;
10970
+ allTargets?: boolean;
10971
+ scope?: HistoryScope;
10972
+ }) => Promise<{
10973
+ deleted: number;
10974
+ }>;
10975
+ /**
10976
+ * Revoke this browser's history credential and wipe it locally. Resolves
10977
+ * (never rejects) on remote failure; rejection is reserved for misuse.
10978
+ * Required host logout wiring.
10979
+ */
10980
+ resetHistoryIdentity: () => Promise<{
10981
+ remoteRevocationConfirmed: boolean;
10982
+ }>;
10983
+ /** Latest sanitized identity state; carries no token, proof, or identity id. */
10984
+ getHistoryIdentityStatus: () => HistoryIdentityStatus;
10985
+ /** `focus: false` keeps focus where it is (programmatic/preview opens). */
10986
+ showHistory: (opts?: {
10987
+ returnSurface?: HistoryReturnSurface;
10988
+ focus?: boolean;
10989
+ }) => Promise<void>;
10990
+ /** `restoreFocus: false` leaves focus untouched on close. */
10991
+ hideHistory: (opts?: {
10992
+ restoreFocus?: boolean;
10993
+ }) => void;
10994
+ isHistoryVisible: () => boolean;
9107
10995
  };
9108
10996
  declare const createAgentExperience: (mount: HTMLElement, initialConfig?: AgentWidgetConfig, runtimeOptions?: {
9109
10997
  debugTools?: boolean;
@@ -10179,6 +12067,11 @@ interface CreateDropdownOptions {
10179
12067
  * Use this to escape `overflow: hidden` containers.
10180
12068
  */
10181
12069
  portal?: HTMLElement;
12070
+ /**
12071
+ * Fired on every open/close transition, including outside-click dismissal.
12072
+ * Use to keep a trigger's `aria-expanded` accurate.
12073
+ */
12074
+ onOpenChange?: (open: boolean) => void;
10182
12075
  }
10183
12076
  interface DropdownMenuHandle {
10184
12077
  /** The menu DOM element. */
@@ -10300,6 +12193,83 @@ interface ToggleGroupHandle {
10300
12193
  * can be active at a time.
10301
12194
  */
10302
12195
  declare function createToggleGroup(options: CreateToggleGroupOptions): ToggleGroupHandle;
12196
+ /** Options for {@link createSplitButton}. */
12197
+ interface CreateSplitButtonOptions {
12198
+ /** Primary action text (always the accessible name; hidden visually with `iconOnly`). */
12199
+ label: string;
12200
+ /** Lucide icon for the primary half. */
12201
+ icon?: string;
12202
+ /** Primary icon size in pixels. Default: 14. */
12203
+ iconSize?: number;
12204
+ /** Render the primary half icon-only. */
12205
+ iconOnly?: boolean;
12206
+ /** Menu items behind the chevron half. */
12207
+ menuItems: DropdownMenuItem[];
12208
+ /** Called when a menu item is selected. */
12209
+ onSelect: (id: string) => void;
12210
+ /** Click handler for the primary half. */
12211
+ onPrimary?: (e: MouseEvent) => void;
12212
+ /** Menu alignment relative to the whole control. Default: "bottom-left". */
12213
+ position?: "bottom-left" | "bottom-right";
12214
+ /**
12215
+ * Portal target for the menu (escapes `overflow: hidden` containers). A
12216
+ * thunk is resolved when the menu is first built, so it may depend on the
12217
+ * control being in the DOM.
12218
+ */
12219
+ portal?: HTMLElement | (() => HTMLElement | null | undefined);
12220
+ /** Accessible label of the chevron half. Default: "More options". */
12221
+ chevronLabel?: string;
12222
+ /** Chevron icon size in pixels. Default: 14. */
12223
+ chevronIconSize?: number;
12224
+ /** Extra CSS class(es) on the wrapper. */
12225
+ className?: string;
12226
+ /** Extra CSS class(es) on the primary button. */
12227
+ primaryClassName?: string;
12228
+ /** Extra CSS class(es) on the chevron button. */
12229
+ chevronClassName?: string;
12230
+ }
12231
+ /** Handle returned by {@link createSplitButton}. */
12232
+ interface SplitButtonHandle {
12233
+ /** The bordered wrapper holding both halves. */
12234
+ element: HTMLElement;
12235
+ /** The primary-action half. */
12236
+ primaryButton: HTMLButtonElement;
12237
+ /** The menu-trigger half. */
12238
+ chevronButton: HTMLButtonElement;
12239
+ /** Open the menu. */
12240
+ openMenu: () => void;
12241
+ /** Close the menu. */
12242
+ closeMenu: () => void;
12243
+ /** Toggle the menu. */
12244
+ toggleMenu: () => void;
12245
+ /** Remove from DOM and clean up. */
12246
+ destroy: () => void;
12247
+ }
12248
+ /**
12249
+ * Creates a split button: one bordered control holding two separately
12250
+ * invocable halves — a primary action button and an icon-only chevron that
12251
+ * opens a dropdown menu — divided by an internal hairline. This is the
12252
+ * Primer/Fluent/Material split-button anatomy; for a single button whose whole
12253
+ * surface opens the menu, use {@link createComboButton} instead.
12254
+ *
12255
+ * Both halves are real `button`s (two tab stops). The chevron carries its own
12256
+ * accessible label plus `aria-haspopup`/`aria-expanded`, kept accurate across
12257
+ * outside-click dismissal.
12258
+ *
12259
+ * ```ts
12260
+ * import { createSplitButton } from "@runtypelabs/persona";
12261
+ *
12262
+ * const split = createSplitButton({
12263
+ * label: "Copy",
12264
+ * icon: "copy",
12265
+ * menuItems: [{ id: "download", label: "Download" }],
12266
+ * onPrimary: () => copyToClipboard(),
12267
+ * onSelect: (id) => handleMenuAction(id),
12268
+ * });
12269
+ * toolbar.appendChild(split.element);
12270
+ * ```
12271
+ */
12272
+ declare function createSplitButton(options: CreateSplitButtonOptions): SplitButtonHandle;
10303
12273
  /** Options for {@link createComboButton}. */
10304
12274
  interface CreateComboButtonOptions {
10305
12275
  /** Button text label. */
@@ -11131,4 +13101,4 @@ interface RovingTablistController {
11131
13101
  }
11132
13102
  declare function createRovingTablist(container: HTMLElement, options: RovingTablistOptions): RovingTablistController;
11133
13103
 
11134
- export { ASK_USER_QUESTION_CLIENT_TOOL, ASK_USER_QUESTION_PARAMETERS_SCHEMA, ASK_USER_QUESTION_TOOL_NAME, type AgentConfig, type AgentExecutionState, type AgentLoopConfig, type AgentMessageMetadata, type AgentRequestOptions, type AgentToolsConfig, type AgentWidgetActionContext, type AgentWidgetActionEventPayload, type AgentWidgetActionHandler, type AgentWidgetActionHandlerResult, type AgentWidgetActionParser, type AgentWidgetAgentRequestPayload, type AgentWidgetApproval, type AgentWidgetApprovalConfig, type AgentWidgetApprovalDecisionOptions, type AgentWidgetArtifactsFeature, type AgentWidgetArtifactsLayoutConfig, type AgentWidgetAskUserQuestionFeature, type AgentWidgetAskUserQuestionStyles, type AgentWidgetAttachmentsConfig, type AgentWidgetAvatarConfig, AgentWidgetClient, type AgentWidgetComponentRenderer, type AgentWidgetComposerConfig, type AgentWidgetConfig, type AgentWidgetConfigPatch, type AgentWidgetContextMentionChipRenderContext, type AgentWidgetContextMentionCommandContext, type AgentWidgetContextMentionComposerCapability, type AgentWidgetContextMentionConfig, type AgentWidgetContextMentionItem, type AgentWidgetContextMentionItemRenderContext, type AgentWidgetContextMentionMenuRenderContext, type AgentWidgetContextMentionPayload, type AgentWidgetContextMentionRef, type AgentWidgetContextMentionResolveContext, type AgentWidgetContextMentionSearchContext, type AgentWidgetContextMentionSource, type AgentWidgetContextMentionTokenRenderContext, type AgentWidgetContextProvider, type AgentWidgetContextProviderContext, type AgentWidgetController, type AgentWidgetControllerEventMap, type AgentWidgetCustomFetch, type AgentWidgetDockConfig, type AgentWidgetEvent, type AgentWidgetFeatureFlags, type AgentWidgetFollowUpSuggestionsConfig, type AgentWidgetHeaderLayoutConfig, type AgentWidgetHeadersFunction, type AgentWidgetInitHandle, type AgentWidgetInitOptions, type AgentWidgetLauncherConfig, type AgentWidgetLauncherTeaserConfig, type AgentWidgetLayoutConfig, type AgentWidgetLoadingIndicatorConfig, type AgentWidgetMarkdownConfig, type AgentWidgetMarkdownOptions, type AgentWidgetMarkdownRendererOverrides, type AgentWidgetMentionLlmEntry, type AgentWidgetMentionTriggerChannel, type AgentWidgetMentionTriggerPosition, type AgentWidgetMessage, type AgentWidgetMessageActionsConfig, type AgentWidgetMessageFeedback, type AgentWidgetMessageLayoutConfig, type AgentWidgetMessageRoleLayout, type AgentWidgetParsedAction, type AgentWidgetPlugin, type AgentWidgetPluginStorage, type AgentWidgetReadAloudEvent, type AgentWidgetRenderSuggestionContext, type AgentWidgetRenderWelcomeContext, type AgentWidgetRequestPayload, type AgentWidgetResolvedSuggestion, type AgentWidgetSSEEventParser, type AgentWidgetSSEEventResult, type AgentWidgetScrollBehaviorFeature, type AgentWidgetScrollMode, type AgentWidgetScrollRestorePosition, type AgentWidgetScrollToBottomFeature, AgentWidgetSession, type AgentWidgetSessionStatus, type AgentWidgetStarterSuggestionsConfig, type AgentWidgetStorageAdapter, type AgentWidgetStoredState, type AgentWidgetStreamAnimationBuffer, type AgentWidgetStreamAnimationBuiltinType, type AgentWidgetStreamAnimationFeature, type AgentWidgetStreamAnimationPlaceholder, type AgentWidgetStreamAnimationType, type AgentWidgetStreamParser, type AgentWidgetStreamParserResult, type AgentWidgetSuggestion, type AgentWidgetSuggestionBehavior, type AgentWidgetSuggestionChipsConfig, type AgentWidgetSuggestionSelectContext, type AgentWidgetSuggestionSource, type AgentWidgetSuggestionSurface, type AgentWidgetSuggestionSurfaceConfig, type AgentWidgetSuggestionVariant, type AgentWidgetSuggestionsConfig, type AgentWidgetTimestampConfig, type AgentWidgetTransformSuggestionsContext, type AgentWidgetVoiceStatusEvent, type AgentWidgetWebMcpConfig, type AgentWidgetWelcomeConfig, type AgentWidgetWelcomeDismiss, type AgentWidgetWelcomeIcon, type AgentWidgetWelcomeVariant, type ArtifactConfigPayload, type ArtifactPaneTokens, type ArtifactTabTokens, type ArtifactToolbarTokens, type AskUserQuestionOption, type AskUserQuestionPayload, type AskUserQuestionPrompt, AttachmentManager, type AttachmentManagerConfig, type BorderScale, BrowserSpeechEngine, type BrowserSpeechEngineOptions, type CSATFeedbackOptions, type ClientChatRequest, type ClientFeedbackRequest, type ClientFeedbackType, type ClientInitResponse, type ClientSession, type ClientToolDefinition, type CodeFormat, type CodeGeneratorHooks, type CodeGeneratorOptions, type ColorPalette, type ColorShade, type ComboButtonHandle, type ComponentContext, type ComponentDirective, type ComponentRegistrationOptions, type ComponentRenderer, type ComponentTokens, type ComposerBuildContext, type ComposerElements, type ContentPart, type CreateComboButtonOptions, type CreateDropdownOptions, type CreateIconButtonOptions, type CreateLabelButtonOptions, type CreateStandardBubbleOptions, type CreateThemeOptions, type CreateToggleGroupOptions, DEFAULT_COMPONENTS, DEFAULT_FLOATING_LAUNCHER_MAX_WIDTH, DEFAULT_FLOATING_LAUNCHER_WIDTH, DEFAULT_PALETTE, DEFAULT_SEMANTIC, DEFAULT_WIDGET_CONFIG, type DeepPartial, type DemoCarouselHandle, type DemoCarouselItem, type DemoCarouselOptions, type DomContextMode, type DomContextOptions, type DropdownMenuHandle, type DropdownMenuItem, type EnrichedPageElement, type EventStreamBadgeColor, type EventStreamConfig, type EventStreamPayloadRenderContext, type EventStreamRowRenderContext, type EventStreamToolbarRenderContext, type EventStreamViewRenderContext, type FallbackSpeechEngineOptions, type FormatEnrichedContextOptions, type HeaderBuildContext, type HeaderElements, type HeaderLayoutContext, type HeaderLayoutRenderer, type HeaderRenderContext, type IconButtonTokens, type IconName, type IdleIndicatorRenderContext, type ImageContentPart, type InjectAssistantMessageOptions, type InjectComponentDirectiveOptions, type InjectMessageOptions, type InjectSystemMessageOptions, type InjectUserMessageOptions, type LabelButtonTokens, type LoadingIndicatorRenderContext, type LoadingIndicatorRenderer, type MarkdownParsersModule, type MarkdownProcessorOptions, type MessageActionCallbacks, type MessageContent, type MessageRenderContext, type MessageTransform, type NPSFeedbackOptions, PRESETS, PRESET_FULLSCREEN, PRESET_MINIMAL, PRESET_SHOP, type ParseOptionsConfig, type ParseRule, type PcmStreamPlayer, type PendingAttachment, type PersonaArtifactActionContext, type PersonaArtifactCustomAction, type PersonaArtifactDisplayDescriptor, type PersonaArtifactDisplayMatch, type PersonaArtifactDisplayMode, type PersonaArtifactDisplayModeInput, type PersonaArtifactDisplayResolution, type PersonaArtifactDisplayRules, type PersonaArtifactFilesDisplayRules, type PersonaArtifactKind, type PersonaArtifactManualUpsert, type PersonaArtifactPresentation, type PersonaArtifactRecord, type PersonaArtifactStatusLabelContext, type PersonaTheme, type PersonaThemePlugin, type RadiusScale, ReadAloudController, type ReadAloudListener, type ReadAloudState, type ResolvedTarget, type ResolvedWelcomeConfig, type RovingTablistController, type RovingTablistOptions, type RuleScoringContext, type RuntypeClientChatRequest, type RuntypeClientChatStreamEvent, type RuntypeClientFeedbackRequest, type RuntypeClientFeedbackResponse, type RuntypeClientFeedbackType, type RuntypeClientInitRequest, type RuntypeClientInitResponse, type RuntypeClientResumeRequest, type RuntypeClientResumeStreamEvent, type RuntypeExecutionStreamEvent, type RuntypeFlowSSEEvent, type RuntypeStepCompleteEvent, type RuntypeStopReasonKind, type RuntypeStreamEventOf, type RuntypeTurnCompleteEvent, type SSEEventCallback, type SSEEventRecord, SUGGEST_REPLIES_CLIENT_TOOL, SUGGEST_REPLIES_PARAMETERS_SCHEMA, SUGGEST_REPLIES_TOOL_NAME, type SanitizeFunction, type SemanticColors, type SemanticSpacing, type SemanticTypography, type ShadowScale, type SlashCommandDefinition, type SlotRenderContext, type SlotRenderer, type SpacingScale, type SpeechCallbacks, type SpeechEngine, type SpeechRequest, type StreamAnimationContext, type StreamAnimationPlugin, THEME_ZONES, type TargetResolver, type TextContentPart, type TextStyleTokens, type ThemeValidationError, type ThemeValidationResult, type ThemeZone, type ToggleGroupHandle, type ToggleGroupItem, type ToggleGroupTokens, type TokenReference, type TypographyScale, VERSION, type VoiceConfig, type VoiceMetrics, type VoicePlaybackEngine, type VoiceProvider, type VoiceResult, type VoiceStatus, WEBMCP_TOOL_PREFIX, WebMcpBridge, type WebMcpConfirmHandler, type WebMcpConfirmInfo, type WebMcpToolResult, type WidgetArtifactLayoutPreference, type WidgetHostLayout, type WidgetHostLayoutMode, type WidgetLayoutSlot, type WidgetPreferenceCapabilities, type WidgetPreferenceParseIssue, type WidgetPreferenceParseIssueCode, type WidgetPreferenceParseResult, type WidgetPreferenceSlice, type WidgetPreset, accessibilityPlugin, animationsPlugin, applyFeaturePreferences, applyThemeVariables, attachHeaderToContainer, brandPlugin, buildComposer, buildDefaultHeader, buildHeader, buildHeaderWithLayout, buildMinimalHeader, builtInClientToolsForDispatch, canonicalArtifactDisplayMode, collectEnrichedPageContext, componentRegistry, createActionManager, createAgentExperience, createAskUserQuestionBubble, createBestAvailableVoiceProvider, createBubbleWithLayout, createCSATFeedback, createComboButton, createComponentMiddleware, createComponentStreamParser, createDefaultSanitizer, createDemoCarousel, createDirectivePostprocessor, createDropdownMenu, createFlexibleJsonStreamParser, createIconButton, createImagePart, createJsonStreamParser, createLabelButton, createLocalStorageAdapter, createMarkdownProcessor, createMarkdownProcessorFromConfig, createMessageActions, createNPSFeedback, createPlainTextParser, createPlugin, createRegexJsonParser, createRovingTablist, createSlashCommandsSource, createStandardBubble, createStaticMentionSource, createTextPart, createTheme, createThemeObserver, createToggleGroup, createTypingIndicator, createVoiceProvider, createWidgetHostLayout, createXmlParser, initAgentWidget as default, defaultActionHandlers, defaultJsonActionParser, defaultMentionFilter, defaultParseRules, detectColorScheme, directivePostprocessor, ensureAskUserQuestionSheet, escapeHtml, extractComponentDirectiveFromMessage, fileToImagePart, formatEnrichedContext, generateAssistantMessageId, generateCodeSnippet, generateMessageId, generateStableSelector, generateUserMessageId, getActiveTheme, getColorScheme, getDisplayText, getHeaderLayout, getImageParts, getPreset, hasComponentDirective, hasImages, headerLayouts, highContrastPlugin, initAgentWidget, isAskUserQuestionMessage, isComponentDirectiveType, isDockedMountMode, isSuggestRepliesMessage, isVoiceSupported, isWebMcpToolName, isWelcomeVisible, latestAgentSuggestions, listRegisteredStreamAnimations, loadMarkdownParsers, markdownPostprocessor, mergeWithDefaults, normalizeContent, normalizeMediaType, onMarkdownParsersReady, parseAskUserQuestionPayload, parseSuggestRepliesPayload, parseWidgetPreferenceSlice, pickBestVoice, pluginRegistry, reducedMotionPlugin, registerStreamAnimationPlugin, removeAskUserQuestionSheet, renderComponentDirective, renderLoadingIndicatorWithFallback, renderLucideIcon, resolveArtifactDisplay, resolveArtifactDisplayMode, resolveConfigPreferences, resolveDockConfig, resolveSanitizer, resolveTokens, resolveWelcomeConfig, stripWebMcpPrefix, themeToCssVariables, unregisterStreamAnimationPlugin, validateImageFile, validateTheme };
13104
+ export { ASK_USER_QUESTION_CLIENT_TOOL, ASK_USER_QUESTION_PARAMETERS_SCHEMA, ASK_USER_QUESTION_TOOL_NAME, type AgentConfig, type AgentExecutionState, type AgentLoopConfig, type AgentMessageMetadata, type AgentRequestOptions, type AgentToolsConfig, type AgentWidgetActionContext, type AgentWidgetActionEventPayload, type AgentWidgetActionHandler, type AgentWidgetActionHandlerResult, type AgentWidgetActionParser, type AgentWidgetAgentRequestPayload, type AgentWidgetApproval, type AgentWidgetApprovalConfig, type AgentWidgetApprovalDecisionOptions, type AgentWidgetArtifactsFeature, type AgentWidgetArtifactsLayoutConfig, type AgentWidgetAskUserQuestionFeature, type AgentWidgetAskUserQuestionStyles, type AgentWidgetAttachmentsConfig, type AgentWidgetAvatarConfig, AgentWidgetClient, type AgentWidgetComponentRenderer, type AgentWidgetComposerConfig, type AgentWidgetConfig, type AgentWidgetConfigPatch, type AgentWidgetContextMentionChipRenderContext, type AgentWidgetContextMentionCommandContext, type AgentWidgetContextMentionComposerCapability, type AgentWidgetContextMentionConfig, type AgentWidgetContextMentionItem, type AgentWidgetContextMentionItemRenderContext, type AgentWidgetContextMentionMenuRenderContext, type AgentWidgetContextMentionPayload, type AgentWidgetContextMentionRef, type AgentWidgetContextMentionResolveContext, type AgentWidgetContextMentionSearchContext, type AgentWidgetContextMentionSource, type AgentWidgetContextMentionTokenRenderContext, type AgentWidgetContextProvider, type AgentWidgetContextProviderContext, type AgentWidgetController, type AgentWidgetControllerEventMap, type AgentWidgetCustomFetch, type AgentWidgetDockConfig, type AgentWidgetEvent, type AgentWidgetFeatureFlags, type AgentWidgetFollowUpSuggestionsConfig, type AgentWidgetHeaderLayoutConfig, type AgentWidgetHeadersFunction, type AgentWidgetHistoryCopy, type AgentWidgetHistoryFeature, type AgentWidgetHistoryListAction, type AgentWidgetHistoryRenderActions, type AgentWidgetInitHandle, type AgentWidgetInitOptions, type AgentWidgetLauncherConfig, type AgentWidgetLauncherTeaserConfig, type AgentWidgetLayoutConfig, type AgentWidgetLoadingIndicatorConfig, type AgentWidgetMarkdownConfig, type AgentWidgetMarkdownOptions, type AgentWidgetMarkdownRendererOverrides, type AgentWidgetMentionLlmEntry, type AgentWidgetMentionTriggerChannel, type AgentWidgetMentionTriggerPosition, type AgentWidgetMessage, type AgentWidgetMessageActionsConfig, type AgentWidgetMessageFeedback, type AgentWidgetMessageLayoutConfig, type AgentWidgetMessageRoleLayout, type AgentWidgetParsedAction, type AgentWidgetPlugin, type AgentWidgetPluginStorage, type AgentWidgetRailSection, type AgentWidgetRailSectionContext, type AgentWidgetReadAloudEvent, type AgentWidgetRenderHistoryConversationContext, type AgentWidgetRenderHistoryHeaderContext, type AgentWidgetRenderHistoryOpenErrorContext, type AgentWidgetRenderHistoryStateContext, type AgentWidgetRenderHistoryViewContext, type AgentWidgetRenderSuggestionContext, type AgentWidgetRenderWelcomeContext, type AgentWidgetRequestPayload, type AgentWidgetResolvedSuggestion, type AgentWidgetSSEEventParser, type AgentWidgetSSEEventResult, type AgentWidgetScrollBehaviorFeature, type AgentWidgetScrollMode, type AgentWidgetScrollRestorePosition, type AgentWidgetScrollToBottomFeature, AgentWidgetSession, type AgentWidgetSessionStatus, type AgentWidgetStarterSuggestionsConfig, type AgentWidgetStorageAdapter, type AgentWidgetStoredState, type AgentWidgetStreamAnimationBuffer, type AgentWidgetStreamAnimationBuiltinType, type AgentWidgetStreamAnimationFeature, type AgentWidgetStreamAnimationPlaceholder, type AgentWidgetStreamAnimationType, type AgentWidgetStreamParser, type AgentWidgetStreamParserResult, type AgentWidgetSuggestion, type AgentWidgetSuggestionBehavior, type AgentWidgetSuggestionChipsConfig, type AgentWidgetSuggestionSelectContext, type AgentWidgetSuggestionSource, type AgentWidgetSuggestionSurface, type AgentWidgetSuggestionSurfaceConfig, type AgentWidgetSuggestionVariant, type AgentWidgetSuggestionsConfig, type AgentWidgetTimestampConfig, type AgentWidgetTooltipConfig, type AgentWidgetTransformSuggestionsContext, type AgentWidgetVoiceStatusEvent, type AgentWidgetWebMcpConfig, type AgentWidgetWelcomeConfig, type AgentWidgetWelcomeDismiss, type AgentWidgetWelcomeIcon, type AgentWidgetWelcomeVariant, type ArtifactConfigPayload, type ArtifactPaneTokens, type ArtifactTabTokens, type ArtifactToolbarTokens, type AskUserQuestionOption, type AskUserQuestionPayload, type AskUserQuestionPrompt, AttachmentManager, type AttachmentManagerConfig, type BorderScale, BrowserSpeechEngine, type BrowserSpeechEngineOptions, type CSATFeedbackOptions, type ClientChatRequest, type ClientFeedbackRequest, type ClientFeedbackType, type ClientInitResponse, type ClientSession, type ClientToolDefinition, type ClientVisitorGrant, type CodeFormat, type CodeGeneratorHooks, type CodeGeneratorOptions, type ColorPalette, type ColorShade, type ComboButtonHandle, type ComponentContext, type ComponentDirective, type ComponentRegistrationOptions, type ComponentRenderer, type ComponentTokens, type ComposerBuildContext, type ComposerElements, type ContentPart, type CreateComboButtonOptions, type CreateDropdownOptions, type CreateIconButtonOptions, type CreateLabelButtonOptions, type CreateStandardBubbleOptions, type CreateThemeOptions, type CreateToggleGroupOptions, DEFAULT_COMPONENTS, DEFAULT_FLOATING_LAUNCHER_MAX_WIDTH, DEFAULT_FLOATING_LAUNCHER_WIDTH, DEFAULT_PALETTE, DEFAULT_SEMANTIC, DEFAULT_WIDGET_CONFIG, type DeepPartial, type DemoCarouselHandle, type DemoCarouselItem, type DemoCarouselOptions, type DomContextMode, type DomContextOptions, type DropdownMenuHandle, type DropdownMenuItem, type EnrichedPageElement, type EventStreamBadgeColor, type EventStreamConfig, type EventStreamPayloadRenderContext, type EventStreamRowRenderContext, type EventStreamToolbarRenderContext, type EventStreamViewRenderContext, type FallbackSpeechEngineOptions, type FormatEnrichedContextOptions, type HeaderBuildContext, type HeaderElements, type HeaderLayoutContext, type HeaderLayoutRenderer, type HeaderRenderContext, type HistoryConversationDetail, type HistoryConversationPage, type HistoryConversationPatch, type HistoryConversationSummary, type HistoryDeleteAllOptions, type HistoryDisplayProjection, type HistoryIdentityStatus, type HistoryListOptions, type HistoryListResult, type HistoryOperationContext, type HistoryPageOptions, type HistoryPageResult, type HistoryPendingAction, type HistoryProvider, HistoryProviderError, type HistoryProviderErrorCode, type HistoryReturnSurface, type HistoryScope, type HistoryViewState, type IconButtonTokens, type IconName, type IdleIndicatorRenderContext, type ImageContentPart, type InjectAssistantMessageOptions, type InjectComponentDirectiveOptions, type InjectMessageOptions, type InjectSystemMessageOptions, type InjectUserMessageOptions, type LabelButtonTokens, type LoadingIndicatorRenderContext, type LoadingIndicatorRenderer, type MarkdownParsersModule, type MarkdownProcessorOptions, type MessageActionCallbacks, type MessageContent, type MessageRenderContext, type MessageTransform, type NPSFeedbackOptions, PRESETS, PRESET_FULLSCREEN, PRESET_MINIMAL, PRESET_SHOP, type ParseOptionsConfig, type ParseRule, type PcmStreamPlayer, type PendingAttachment, type PersonaArtifactActionContext, type PersonaArtifactCustomAction, type PersonaArtifactDisplayDescriptor, type PersonaArtifactDisplayMatch, type PersonaArtifactDisplayMode, type PersonaArtifactDisplayModeInput, type PersonaArtifactDisplayResolution, type PersonaArtifactDisplayRules, type PersonaArtifactFilesDisplayRules, type PersonaArtifactKind, type PersonaArtifactManualUpsert, type PersonaArtifactPresentation, type PersonaArtifactRecord, type PersonaArtifactStatusLabelContext, type PersonaTheme, type PersonaThemePlugin, type PreparedClientSession, type PreparedHistoryActivation, type RadiusScale, ReadAloudController, type ReadAloudListener, type ReadAloudState, type ResolvedHistoryCopy, type ResolvedHistoryPresentation, type ResolvedTarget, type ResolvedWelcomeConfig, type RovingTablistController, type RovingTablistOptions, type RuleScoringContext, type RuntypeClientChatRequest, type RuntypeClientChatStreamEvent, type RuntypeClientFeedbackRequest, type RuntypeClientFeedbackResponse, type RuntypeClientFeedbackType, type RuntypeClientInitRequest, type RuntypeClientInitResponse, type RuntypeClientResumeRequest, type RuntypeClientResumeStreamEvent, type RuntypeExecutionStreamEvent, type RuntypeFlowSSEEvent, type RuntypeStepCompleteEvent, type RuntypeStopReasonKind, type RuntypeStreamEventOf, type RuntypeTurnCompleteEvent, type SSEEventCallback, type SSEEventRecord, SUGGEST_REPLIES_CLIENT_TOOL, SUGGEST_REPLIES_PARAMETERS_SCHEMA, SUGGEST_REPLIES_TOOL_NAME, type SanitizeFunction, type SemanticColors, type SemanticSpacing, type SemanticTypography, type ShadowScale, type SlashCommandDefinition, type SlotRenderContext, type SlotRenderer, type SpacingScale, type SpeechCallbacks, type SpeechEngine, type SpeechRequest, type StreamAnimationContext, type StreamAnimationPlugin, THEME_ZONES, type TargetResolver, type TextContentPart, type TextStyleTokens, type ThemeValidationError, type ThemeValidationResult, type ThemeZone, type ToggleGroupHandle, type ToggleGroupItem, type ToggleGroupTokens, type TokenReference, type TypographyScale, VERSION, type VoiceConfig, type VoiceMetrics, type VoicePlaybackEngine, type VoiceProvider, type VoiceResult, type VoiceStatus, WEBMCP_TOOL_PREFIX, WebMcpBridge, type WebMcpConfirmHandler, type WebMcpConfirmInfo, type WebMcpToolResult, type WidgetArtifactLayoutPreference, type WidgetHostLayout, type WidgetHostLayoutMode, type WidgetLayoutSlot, type WidgetPreferenceCapabilities, type WidgetPreferenceParseIssue, type WidgetPreferenceParseIssueCode, type WidgetPreferenceParseResult, type WidgetPreferenceSlice, type WidgetPreset, accessibilityPlugin, animationsPlugin, applyFeaturePreferences, applyThemeVariables, attachHeaderToContainer, brandPlugin, buildComposer, buildDefaultHeader, buildHeader, buildHeaderWithLayout, buildMinimalHeader, builtInClientToolsForDispatch, canonicalArtifactDisplayMode, collectEnrichedPageContext, componentRegistry, createActionManager, createAgentExperience, createAskUserQuestionBubble, createBestAvailableVoiceProvider, createBubbleWithLayout, createCSATFeedback, createComboButton, createComponentMiddleware, createComponentStreamParser, createDefaultSanitizer, createDemoCarousel, createDirectivePostprocessor, createDropdownMenu, createFlexibleJsonStreamParser, createIconButton, createImagePart, createJsonStreamParser, createLabelButton, createLocalStorageAdapter, createMarkdownProcessor, createMarkdownProcessorFromConfig, createMessageActions, createNPSFeedback, createPlainTextParser, createPlugin, createRegexJsonParser, createRovingTablist, createSlashCommandsSource, createSplitButton, createStandardBubble, createStaticMentionSource, createTextPart, createTheme, createThemeObserver, createToggleGroup, createTypingIndicator, createVoiceProvider, createWidgetHostLayout, createXmlParser, initAgentWidget as default, defaultActionHandlers, defaultJsonActionParser, defaultMentionFilter, defaultParseRules, detectColorScheme, directivePostprocessor, ensureAskUserQuestionSheet, escapeHtml, extractComponentDirectiveFromMessage, fileToImagePart, formatEnrichedContext, generateAssistantMessageId, generateCodeSnippet, generateMessageId, generateStableSelector, generateUserMessageId, getActiveTheme, getColorScheme, getDisplayText, getHeaderLayout, getImageParts, getPreset, hasComponentDirective, hasImages, headerLayouts, highContrastPlugin, initAgentWidget, isAskUserQuestionMessage, isComponentDirectiveType, isDockedMountMode, isHistoryProviderError, isSuggestRepliesMessage, isVoiceSupported, isWebMcpToolName, isWelcomeVisible, latestAgentSuggestions, listRegisteredStreamAnimations, loadMarkdownParsers, markdownPostprocessor, mergeWithDefaults, normalizeContent, normalizeMediaType, onMarkdownParsersReady, parseAskUserQuestionPayload, parseSuggestRepliesPayload, parseWidgetPreferenceSlice, pickBestVoice, pluginRegistry, reducedMotionPlugin, registerStreamAnimationPlugin, removeAskUserQuestionSheet, renderComponentDirective, renderLoadingIndicatorWithFallback, renderLucideIcon, resolveArtifactDisplay, resolveArtifactDisplayMode, resolveConfigPreferences, resolveDockConfig, resolveSanitizer, resolveTokens, resolveWelcomeConfig, stripWebMcpPrefix, themeToCssVariables, unregisterStreamAnimationPlugin, validateImageFile, validateTheme };