@runtypelabs/persona 4.13.0 → 4.15.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 (106) hide show
  1. package/README.md +4 -4
  2. package/dist/animations/glyph-cycle.d.cts +1 -1
  3. package/dist/animations/glyph-cycle.d.ts +1 -1
  4. package/dist/animations/{types-DveIaNx6.d.cts → types-BpWGm7_6.d.cts} +17 -0
  5. package/dist/animations/{types-DveIaNx6.d.ts → types-BpWGm7_6.d.ts} +17 -0
  6. package/dist/animations/wipe.d.cts +1 -1
  7. package/dist/animations/wipe.d.ts +1 -1
  8. package/dist/chunk-QJ4LV2KW.js +1 -0
  9. package/dist/codegen.cjs +12 -11
  10. package/dist/codegen.js +14 -13
  11. package/dist/{context-mentions-ONG7A7M6.js → context-mentions-BTSTIBFC.js} +1 -1
  12. package/dist/context-mentions.cjs +11 -8
  13. package/dist/context-mentions.d.cts +339 -22
  14. package/dist/context-mentions.d.ts +339 -22
  15. package/dist/context-mentions.js +11 -8
  16. package/dist/index.cjs +68 -67
  17. package/dist/index.cjs.map +1 -1
  18. package/dist/index.d.cts +483 -48
  19. package/dist/index.d.ts +483 -48
  20. package/dist/index.global.js +61 -58
  21. package/dist/index.global.js.map +1 -1
  22. package/dist/index.js +70 -69
  23. package/dist/index.js.map +1 -1
  24. package/dist/launcher.global.js +5 -2
  25. package/dist/launcher.global.js.map +1 -1
  26. package/dist/smart-dom-reader.d.cts +339 -22
  27. package/dist/smart-dom-reader.d.ts +339 -22
  28. package/dist/theme-editor-preview.cjs +67 -67
  29. package/dist/theme-editor-preview.d.cts +355 -23
  30. package/dist/theme-editor-preview.d.ts +355 -23
  31. package/dist/theme-editor-preview.js +75 -75
  32. package/dist/theme-editor.cjs +10 -10
  33. package/dist/theme-editor.d.cts +376 -24
  34. package/dist/theme-editor.d.ts +376 -24
  35. package/dist/theme-editor.js +10 -10
  36. package/dist/theme-reference.cjs +1 -1
  37. package/dist/theme-reference.d.cts +38 -0
  38. package/dist/theme-reference.d.ts +38 -0
  39. package/dist/theme-reference.js +1 -1
  40. package/dist/widget.css +1 -1
  41. package/package.json +1 -1
  42. package/src/artifacts-session.test.ts +106 -0
  43. package/src/ask-user-question-tool.ts +10 -7
  44. package/src/client.test.ts +2 -2
  45. package/src/client.ts +4 -1
  46. package/src/components/artifact-card.ts +13 -2
  47. package/src/components/artifact-inline.ts +11 -2
  48. package/src/components/artifact-preview.ts +1 -1
  49. package/src/components/composer-builder.test.ts +2 -0
  50. package/src/components/composer-builder.ts +1 -1
  51. package/src/components/composer-parts.test.ts +105 -4
  52. package/src/components/composer-parts.ts +54 -16
  53. package/src/components/message-bubble.test.ts +7 -1
  54. package/src/components/message-bubble.ts +11 -8
  55. package/src/components/messages.ts +5 -2
  56. package/src/components/panel.ts +31 -5
  57. package/src/components/pill-composer-builder.test.ts +18 -0
  58. package/src/components/suggestions.test.ts +233 -0
  59. package/src/components/suggestions.ts +463 -81
  60. package/src/components/widget-view.ts +4 -0
  61. package/src/defaults.ts +5 -3
  62. package/src/generated/runtype-openapi-contract.ts +17 -0
  63. package/src/index-core.ts +52 -2
  64. package/src/launcher-global.ts +1 -1
  65. package/src/plugins/types.ts +71 -3
  66. package/src/presets.ts +3 -3
  67. package/src/session.ts +55 -12
  68. package/src/styles/widget-styles.test.ts +162 -0
  69. package/src/styles/widget.css +440 -1
  70. package/src/suggest-replies-tool.test.ts +233 -2
  71. package/src/suggest-replies-tool.ts +115 -39
  72. package/src/theme-editor/index.ts +5 -0
  73. package/src/theme-editor/presets.test.ts +43 -0
  74. package/src/theme-editor/presets.ts +101 -87
  75. package/src/theme-editor/preview-utils.test.ts +34 -0
  76. package/src/theme-editor/preview-utils.ts +77 -2
  77. package/src/theme-editor/sections.test.ts +72 -7
  78. package/src/theme-editor/sections.ts +113 -13
  79. package/src/theme-editor/state-preferences.test.ts +15 -0
  80. package/src/theme-editor/state.ts +46 -0
  81. package/src/theme-editor/types.ts +15 -1
  82. package/src/theme-editor/webmcp/tools.test.ts +13 -0
  83. package/src/theme-editor/webmcp/tools.ts +5 -0
  84. package/src/theme-reference.ts +9 -2
  85. package/src/types/theme.ts +32 -0
  86. package/src/types.ts +291 -25
  87. package/src/ui.artifact-pane-gating.test.ts +5 -5
  88. package/src/ui.config-preferences.test.ts +166 -0
  89. package/src/ui.detached-panel.test.ts +1 -1
  90. package/src/ui.suggest-replies.test.ts +1066 -1
  91. package/src/ui.ts +311 -45
  92. package/src/ui.typing-indicator.test.ts +135 -0
  93. package/src/utils/artifact-display.test.ts +180 -16
  94. package/src/utils/artifact-display.ts +155 -14
  95. package/src/utils/artifact-file.test.ts +1 -1
  96. package/src/utils/code-generators.test.ts +40 -0
  97. package/src/utils/code-generators.ts +22 -0
  98. package/src/utils/config-merge.test.ts +84 -0
  99. package/src/utils/config-merge.ts +6 -1
  100. package/src/utils/feature-preferences.test.ts +326 -0
  101. package/src/utils/feature-preferences.ts +498 -0
  102. package/src/utils/icons.test.ts +26 -0
  103. package/src/utils/icons.ts +8 -0
  104. package/src/utils/theme.test.ts +171 -0
  105. package/src/utils/tokens.ts +71 -7
  106. package/dist/chunk-MMUPR2JW.js +0 -1
@@ -269,6 +269,40 @@ interface SmartDomAdapterOptions {
269
269
  */
270
270
  declare function smartDomResultToEnriched(result: SmartDOMResult, opts?: SmartDomAdapterOptions): EnrichedPageElement[];
271
271
 
272
+ type AgentWidgetTransformSuggestionsContext = {
273
+ /**
274
+ * Fresh copy of the suggestions entering this plugin, already normalized:
275
+ * shorthand strings expanded and the effective send/fill behavior resolved.
276
+ */
277
+ suggestions: AgentWidgetResolvedSuggestion[];
278
+ surface: AgentWidgetSuggestionSurface;
279
+ source: AgentWidgetSuggestionSource;
280
+ config: AgentWidgetConfig;
281
+ };
282
+ type AgentWidgetRenderSuggestionContext = {
283
+ /** Fully normalized suggestion, including the effective send/fill behavior. */
284
+ suggestion: AgentWidgetResolvedSuggestion;
285
+ index: number;
286
+ surface: AgentWidgetSuggestionSurface;
287
+ source: AgentWidgetSuggestionSource;
288
+ variant: AgentWidgetSuggestionVariant;
289
+ streaming: boolean;
290
+ config: AgentWidgetConfig;
291
+ /** Build Persona's standard chip, card, or list item. */
292
+ defaultRenderer: () => HTMLElement;
293
+ /**
294
+ * Run the normal selection pipeline: DOM event, plugin selection hooks, then
295
+ * send or fill. Custom renderers should call this instead of sending directly.
296
+ */
297
+ select: () => void;
298
+ };
299
+ type AgentWidgetSuggestionSelectContext = {
300
+ suggestion: AgentWidgetResolvedSuggestion;
301
+ surface: AgentWidgetSuggestionSurface;
302
+ source: AgentWidgetSuggestionSource;
303
+ variant: AgentWidgetSuggestionVariant;
304
+ config: AgentWidgetConfig;
305
+ };
272
306
  /**
273
307
  * Plugin interface for customizing widget components
274
308
  */
@@ -281,6 +315,25 @@ interface AgentWidgetPlugin {
281
315
  * Optional priority (higher = runs first). Default: 0
282
316
  */
283
317
  priority?: number;
318
+ /**
319
+ * Transform, filter, enrich, or reorder suggestions. Hooks receive normalized
320
+ * items and compose in plugin priority order; the return value may use the
321
+ * loose shape (string shorthand included) and is re-normalized before the next
322
+ * hook. A per-item `behavior` set here survives. `maxItems` caps the list
323
+ * after the full chain. Return an empty array to hide the surface.
324
+ */
325
+ transformSuggestions?: (context: AgentWidgetTransformSuggestionsContext) => AgentWidgetSuggestion[];
326
+ /**
327
+ * Render one starter or follow-up suggestion. Return null to use Persona's
328
+ * default chip/card/list renderer. Call `select()` from custom interaction
329
+ * controls to preserve events, selection hooks, and send/fill behavior.
330
+ */
331
+ renderSuggestion?: (context: AgentWidgetRenderSuggestionContext) => HTMLElement | null;
332
+ /**
333
+ * Observe or intercept a suggestion selection. Return false to cancel the
334
+ * built-in send/fill action. Hooks run in plugin priority order.
335
+ */
336
+ onSuggestionSelect?: (context: AgentWidgetSuggestionSelectContext) => void | boolean;
284
337
  /**
285
338
  * Custom renderer for message bubbles
286
339
  * Return null to use default renderer
@@ -876,6 +929,14 @@ interface ReasoningBubbleTokens {
876
929
  interface ComposerChromeTokens {
877
930
  /** Box-shadow on the composer form (raw CSS, e.g. `none`). */
878
931
  shadow: string;
932
+ /** Inner padding of the composer form (raw CSS shorthand). @default "0.75rem 1rem" */
933
+ padding?: string;
934
+ /** Gap between the textarea row and the actions row. @default "0.5rem" */
935
+ gap?: string;
936
+ /** Composer textarea font-size. @default "0.875rem" */
937
+ fontSize?: string;
938
+ /** Composer textarea line-height. @default "1.25rem" */
939
+ lineHeight?: string;
879
940
  }
880
941
  /** Artifact toolbar chrome. */
881
942
  interface ArtifactToolbarTokens {
@@ -1025,6 +1086,26 @@ interface ScrollToBottomTokens extends ComponentTokenSet {
1025
1086
  fontSize?: string;
1026
1087
  iconSize?: string;
1027
1088
  }
1089
+ /** Visual tokens shared by one suggestion presentation variant. */
1090
+ interface SuggestionVariantTokens extends ComponentTokenSet {
1091
+ gap?: string;
1092
+ minHeight?: string;
1093
+ fontSize?: string;
1094
+ lineHeight?: string;
1095
+ iconSize?: string;
1096
+ hoverBackground?: TokenReference<'color'>;
1097
+ hoverForeground?: TokenReference<'color'>;
1098
+ hoverBorder?: TokenReference<'color'>;
1099
+ pressedBackground?: TokenReference<'color'>;
1100
+ focusRing?: TokenReference<'color'>;
1101
+ disabledOpacity?: string;
1102
+ }
1103
+ /** Starter and follow-up suggestion chrome. */
1104
+ interface SuggestionTokens {
1105
+ chip: SuggestionVariantTokens;
1106
+ card: SuggestionVariantTokens;
1107
+ list: SuggestionVariantTokens;
1108
+ }
1028
1109
  /** Toggle group chrome (used by createToggleGroup). */
1029
1110
  interface ToggleGroupTokens {
1030
1111
  /** Gap between toggle buttons. Default: 0 (connected). */
@@ -1055,6 +1136,8 @@ interface ComponentTokens {
1055
1136
  labelButton?: LabelButtonTokens;
1056
1137
  /** Scroll-to-bottom indicator styling tokens. */
1057
1138
  scrollToBottom?: ScrollToBottomTokens;
1139
+ /** Starter prompt and follow-up suggestion styling tokens. */
1140
+ suggestion?: SuggestionTokens;
1058
1141
  /** Toggle group styling tokens. */
1059
1142
  toggleGroup?: ToggleGroupTokens;
1060
1143
  /** Artifact toolbar, tab strip, and pane chrome. */
@@ -1349,7 +1432,24 @@ type RuntypeExecutionStreamEvent = ({
1349
1432
  type: "source";
1350
1433
  url?: string;
1351
1434
  [key: string]: unknown;
1435
+ } | {
1436
+ executionId: string;
1437
+ iteration?: number;
1438
+ seq: number;
1439
+ state: Record<string, unknown>;
1440
+ type: "state_snapshot";
1352
1441
  } | ({
1442
+ executionId: string;
1443
+ iteration?: number;
1444
+ patch: Array<{
1445
+ from?: string;
1446
+ op: "add" | "remove" | "replace" | "move" | "copy" | "test";
1447
+ path: string;
1448
+ value?: unknown;
1449
+ }>;
1450
+ seq: number;
1451
+ type: "state_delta";
1452
+ }) | ({
1353
1453
  executionId: string;
1354
1454
  hiddenParameterNames?: Array<string>;
1355
1455
  iteration?: number;
@@ -1591,6 +1691,7 @@ declare const LUCIDE_ICONS: {
1591
1691
  readonly plus: IconNode;
1592
1692
  readonly minus: IconNode;
1593
1693
  readonly pencil: IconNode;
1694
+ readonly "pen-line": IconNode;
1594
1695
  readonly trash: IconNode;
1595
1696
  readonly "trash-2": IconNode;
1596
1697
  readonly save: IconNode;
@@ -1633,11 +1734,13 @@ declare const LUCIDE_ICONS: {
1633
1734
  readonly folder: IconNode;
1634
1735
  readonly "folder-open": IconNode;
1635
1736
  readonly files: IconNode;
1737
+ readonly "chart-column": IconNode;
1636
1738
  readonly sparkles: IconNode;
1637
1739
  readonly zap: IconNode;
1638
1740
  readonly sun: IconNode;
1639
1741
  readonly moon: IconNode;
1640
1742
  readonly flag: IconNode;
1743
+ readonly lightbulb: IconNode;
1641
1744
  readonly monitor: IconNode;
1642
1745
  readonly smartphone: IconNode;
1643
1746
  };
@@ -2237,6 +2340,14 @@ type AgentToolsConfig = {
2237
2340
  };
2238
2341
  /** Artifact kinds for the Persona sidebar and dispatch payload */
2239
2342
  type PersonaArtifactKind = "markdown" | "component";
2343
+ type PersonaArtifactPresentation = {
2344
+ /**
2345
+ * Producer hint for where this artifact renders (content-disposition
2346
+ * model). Beats configured defaults; loses to explicit `files`/`byKind`
2347
+ * rules. Persona never infers it; the producer or host supplies it.
2348
+ */
2349
+ preferredMode?: PersonaArtifactDisplayModeInput;
2350
+ };
2240
2351
  /**
2241
2352
  * Agent configuration for agent execution mode.
2242
2353
  * When provided in the widget config, enables agent loop execution instead of flow dispatch.
@@ -2765,7 +2876,48 @@ type AgentWidgetArtifactsLayoutConfig = {
2765
2876
  jsonPayload: string;
2766
2877
  }) => void | Promise<void>;
2767
2878
  };
2768
- type PersonaArtifactDisplayMode = "card" | "panel" | "inline";
2879
+ /**
2880
+ * Where the artifact body renders by default. Every mode shows the compact
2881
+ * reference in the transcript; the mode names where the body goes:
2882
+ * nowhere yet (`collapsed`), the side panel (`panel`), or the conversation
2883
+ * itself (`inline`).
2884
+ */
2885
+ type PersonaArtifactDisplayMode = "collapsed" | "panel" | "inline";
2886
+ /**
2887
+ * Accepted wherever a display mode is written. `"card"` is a deprecated
2888
+ * alias of `"collapsed"` (the old name described the reference card, which
2889
+ * every mode shows, instead of where the body renders). Resolution and
2890
+ * parsing always canonicalize to `"collapsed"`.
2891
+ */
2892
+ type PersonaArtifactDisplayModeInput = PersonaArtifactDisplayMode | "card";
2893
+ /**
2894
+ * Display rules for file-backed artifacts. `byMediaType` keys are exact MIME
2895
+ * types (`"text/html"`) or major-type wildcards (`"image/*"`), matched
2896
+ * case-insensitively without parameters; exact beats wildcard.
2897
+ */
2898
+ type PersonaArtifactFilesDisplayRules = {
2899
+ default?: PersonaArtifactDisplayModeInput;
2900
+ byMediaType?: Record<string, PersonaArtifactDisplayModeInput>;
2901
+ };
2902
+ /**
2903
+ * Scoped artifact display rules. Matching resolves from the most specific
2904
+ * selector to `default`; see `resolveArtifactDisplay`.
2905
+ *
2906
+ * Across preference layers, one merge rule applies everywhere: a string value
2907
+ * replaces the whole subtree it names; an object refines it per key. So
2908
+ * `files: "inline"` overrides every lower-layer file rule, while
2909
+ * `files: { default: "inline" }` keeps lower-layer MIME exceptions.
2910
+ */
2911
+ type PersonaArtifactDisplayRules = {
2912
+ default?: PersonaArtifactDisplayModeInput;
2913
+ byKind?: Partial<Record<PersonaArtifactKind, PersonaArtifactDisplayModeInput>>;
2914
+ /**
2915
+ * @deprecated Use `byKind`. When both are present, `byKind` wins.
2916
+ */
2917
+ byType?: Partial<Record<PersonaArtifactKind, PersonaArtifactDisplayModeInput>>;
2918
+ /** Rules for any artifact carrying file metadata. */
2919
+ files?: PersonaArtifactDisplayModeInput | PersonaArtifactFilesDisplayRules;
2920
+ };
2769
2921
  /** Context handed to custom artifact actions. Content fields are best-effort: resolved from live session state or, after a refresh, from the persisted reference-card payload. */
2770
2922
  type PersonaArtifactActionContext = {
2771
2923
  artifactId: string | null;
@@ -2822,13 +2974,10 @@ type AgentWidgetArtifactsFeature = {
2822
2974
  allowedTypes?: PersonaArtifactKind[];
2823
2975
  /**
2824
2976
  * Where artifact bodies render. A single mode applies to all artifacts;
2825
- * the object form sets a default plus per-type overrides.
2977
+ * the object form sets a default plus scoped overrides.
2826
2978
  * Defaults to "panel" (current behavior).
2827
2979
  */
2828
- display?: PersonaArtifactDisplayMode | {
2829
- default?: PersonaArtifactDisplayMode;
2830
- byType?: Partial<Record<PersonaArtifactKind, PersonaArtifactDisplayMode>>;
2831
- };
2980
+ display?: PersonaArtifactDisplayModeInput | PersonaArtifactDisplayRules;
2832
2981
  /** Split / drawer dimensions and launcher widen behavior */
2833
2982
  layout?: AgentWidgetArtifactsLayoutConfig;
2834
2983
  /**
@@ -3550,19 +3699,58 @@ type AgentWidgetFeatureFlags = {
3550
3699
  */
3551
3700
  askUserQuestion?: AgentWidgetAskUserQuestionFeature;
3552
3701
  /**
3553
- * Built-in `suggest_replies` quick-reply chips. When the assistant invokes
3554
- * the tool, the widget shows the suggestions as tappable chips above the
3555
- * composer (reusing the suggestion-chips surface) and immediately resumes
3556
- * the execution: fire-and-forget, no user input awaited.
3702
+ * Built-in `suggest_replies` follow-ups. When the assistant invokes the
3703
+ * tool, the widget shows the suggestions using `suggestions.followUps` and
3704
+ * immediately resumes the execution: fire-and-forget, no user input awaited.
3705
+ *
3706
+ * @deprecated Both keys moved to `suggestions.followUps`: use
3707
+ * `suggestions.followUps.enabled` and `suggestions.followUps.expose`. This
3708
+ * alias keeps working per key, with `suggestions.followUps` winning.
3557
3709
  */
3558
3710
  suggestReplies?: AgentWidgetSuggestRepliesFeature;
3559
3711
  };
3560
3712
  /**
3561
- * Feature config for the built-in `suggest_replies` quick-reply chips.
3562
- * Chips render in the existing suggestions slot above the composer and are
3563
- * styled by the widget-level `suggestionChipsConfig`. A tapped chip is sent
3564
- * verbatim as the user's next message; chips clear once any user message
3565
- * follows them.
3713
+ * Persistable artifact-layout choices. The full layout config deliberately is
3714
+ * not exposed because it also contains callbacks and embedder-owned chrome.
3715
+ */
3716
+ type WidgetArtifactLayoutPreference = Pick<AgentWidgetArtifactsLayoutConfig, "paneWidth" | "paneMaxWidth" | "paneMinWidth" | "expandLauncherPanelWhenOpen" | "expandedPanelWidth" | "resizable" | "resizableMinWidth" | "resizableMaxWidth">;
3717
+ /**
3718
+ * Curated, JSON-serializable display preferences in native `features` shape.
3719
+ *
3720
+ * Absence means inherit the next preference layer and ultimately Persona's
3721
+ * current default. Persist only explicit choices; resetting a choice deletes
3722
+ * its key.
3723
+ *
3724
+ * Capability facts (`artifacts.enabled`, `allowedTypes`), trusted iframe
3725
+ * security, callbacks, actions, renderers, labels, and theme styling are
3726
+ * intentionally excluded because they remain embedder/code-owned.
3727
+ */
3728
+ type WidgetPreferenceSlice = {
3729
+ showToolCalls?: boolean;
3730
+ showReasoning?: boolean;
3731
+ toolCallDisplay?: Pick<AgentWidgetToolCallDisplayFeature, "collapsedMode" | "expandable" | "grouped" | "groupedMode" | "loadingAnimation">;
3732
+ reasoningDisplay?: Pick<AgentWidgetReasoningDisplayFeature, "expandable" | "activePreview">;
3733
+ artifacts?: {
3734
+ /**
3735
+ * String and object forms are both persistable and mean different things
3736
+ * when layers merge: a string replaces every lower-layer display rule; an
3737
+ * object refines lower layers per selector key (same rule applies to
3738
+ * `display.files`).
3739
+ */
3740
+ display?: PersonaArtifactDisplayModeInput | PersonaArtifactDisplayRules;
3741
+ filePreview?: {
3742
+ enabled?: boolean;
3743
+ };
3744
+ layout?: WidgetArtifactLayoutPreference;
3745
+ };
3746
+ };
3747
+ /**
3748
+ * Feature config for the built-in `suggest_replies` follow-ups.
3749
+ *
3750
+ * @deprecated Both keys moved to `suggestions.followUps`
3751
+ * (`suggestions.followUps.enabled` / `suggestions.followUps.expose`), which
3752
+ * also owns presentation, placement, and send/fill behavior. Resolution is
3753
+ * per key with `suggestions.followUps` winning; removal waits for 5.0.
3566
3754
  */
3567
3755
  type AgentWidgetSuggestRepliesFeature = {
3568
3756
  /**
@@ -3570,14 +3758,18 @@ type AgentWidgetSuggestRepliesFeature = {
3570
3758
  * renders as a regular tool bubble and is NOT auto-resumed: only set this
3571
3759
  * with no server-side `suggest_replies` declaration, or the execution
3572
3760
  * parks awaiting a resume that never comes.
3761
+ * @deprecated Use `suggestions.followUps.enabled`.
3573
3762
  */
3574
3763
  enabled?: boolean;
3575
3764
  /**
3576
3765
  * Advertise the built-in `suggest_replies` tool to the agent on every
3577
3766
  * dispatch via `clientTools[]`: no server-side `runtimeTools` declaration
3578
- * needed. Defaults to `false`: flows that already declare the tool via
3579
- * `runtimeTools` would otherwise present it to the model twice. Ignored
3580
- * when `enabled` is `false`.
3767
+ * needed. Defaults to `false`. Declare the tool in one place: the API
3768
+ * dedupes a double declaration by name with `clientTools[]` winning, so the
3769
+ * model still sees exactly one tool, but the widget's description and schema
3770
+ * win and the effective tool type becomes `local` (the execution pauses and
3771
+ * the widget auto-resumes it). Ignored when `enabled` is `false`.
3772
+ * @deprecated Use `suggestions.followUps.expose`.
3581
3773
  */
3582
3774
  expose?: boolean;
3583
3775
  };
@@ -3647,10 +3839,13 @@ type AgentWidgetAskUserQuestionFeature = {
3647
3839
  * matching {@link AskUserQuestionPayload}; when the model calls it, the
3648
3840
  * existing answer-pill sheet renders and the answer resumes the execution.
3649
3841
  *
3650
- * Defaults to `false`: flows that already declare `ask_user_question` via
3651
- * `runtimeTools` would otherwise present the tool to the model twice.
3652
- * Ignored when `enabled` is `false`: never offer the agent a question
3653
- * tool the widget can't render an answer UI for.
3842
+ * Defaults to `false`. Declare the tool in one place: the API dedupes a
3843
+ * double declaration by name with `clientTools[]` winning, so the model
3844
+ * still sees exactly one tool, but the widget's description and schema win
3845
+ * and the effective tool type becomes `local` (the execution pauses and the
3846
+ * widget resumes it with the user's answer). Ignored when `enabled` is
3847
+ * `false`: never offer the agent a question tool the widget can't render an
3848
+ * answer UI for.
3654
3849
  */
3655
3850
  expose?: boolean;
3656
3851
  /** Slide-in animation duration in ms. Defaults to 180. */
@@ -4123,6 +4318,10 @@ type AgentWidgetSendButtonConfig = {
4123
4318
  paddingY?: string;
4124
4319
  iconText?: string;
4125
4320
  iconName?: string;
4321
+ /** Icon glyph box in icon mode, e.g. "20px". Defaults to half of `size`. */
4322
+ iconSize?: string;
4323
+ /** Stroke width for the icon glyph, in viewBox units. Default 2. */
4324
+ iconStrokeWidth?: number;
4126
4325
  useIcon?: boolean;
4127
4326
  tooltipText?: string;
4128
4327
  showTooltip?: boolean;
@@ -4846,6 +5045,109 @@ type AgentWidgetSuggestionChipsConfig = {
4846
5045
  paddingX?: string;
4847
5046
  paddingY?: string;
4848
5047
  };
5048
+ /** A suggested next action shown to the user. Strings remain supported as shorthand. */
5049
+ type AgentWidgetSuggestion = string | {
5050
+ /** Stable analytics / DOM identity. Falls back to the prompt or label. */
5051
+ id?: string;
5052
+ /** Concise visible action label. */
5053
+ label: string;
5054
+ /** Text placed in the composer or sent. Defaults to `label`. */
5055
+ prompt?: string;
5056
+ /** Optional supporting copy, most useful with the `card` variant. */
5057
+ description?: string;
5058
+ /** Optional icon from Persona's bundled Lucide registry. */
5059
+ icon?: IconName;
5060
+ /**
5061
+ * CSS color for this item's glyph. Tints the icon only: label, border,
5062
+ * and background stay neutral. Ignored without an `icon`.
5063
+ */
5064
+ iconColor?: string;
5065
+ /** Override the surface's click behavior for this item. */
5066
+ behavior?: AgentWidgetSuggestionBehavior;
5067
+ /** Visually promote one high-confidence action. */
5068
+ emphasis?: "default" | "primary";
5069
+ };
5070
+ type AgentWidgetSuggestionBehavior = "send" | "fill";
5071
+ type AgentWidgetSuggestionVariant = "chip" | "card" | "list";
5072
+ type AgentWidgetSuggestionSurface = "starter" | "followUp";
5073
+ /**
5074
+ * Who produced the rendered suggestions: static config, the agent's
5075
+ * `suggest_replies` tool, or `controller.setFollowUpSuggestions`.
5076
+ */
5077
+ type AgentWidgetSuggestionSource = "config" | "agent" | "host";
5078
+ /**
5079
+ * A suggestion after Persona has normalized shorthand strings and resolved the
5080
+ * effective click behavior. Plugin hooks receive this stable shape.
5081
+ */
5082
+ type AgentWidgetResolvedSuggestion = {
5083
+ id: string;
5084
+ label: string;
5085
+ prompt: string;
5086
+ description?: string;
5087
+ icon?: IconName;
5088
+ /** CSS color for the glyph only; never the label, border, or background. */
5089
+ iconColor?: string;
5090
+ behavior: AgentWidgetSuggestionBehavior;
5091
+ emphasis: "default" | "primary";
5092
+ };
5093
+ /** Presentation keys shared by every suggestion surface. */
5094
+ type AgentWidgetSuggestionSurfaceConfig = {
5095
+ /** Item density. Defaults to `card` for starters and `chip` for follow-ups. */
5096
+ variant?: AgentWidgetSuggestionVariant;
5097
+ /** Default click behavior, overridable per item. Defaults to `send`. */
5098
+ behavior?: AgentWidgetSuggestionBehavior;
5099
+ /**
5100
+ * Layout for items past the surface width. Defaults to `wrap` for starters
5101
+ * and `scroll` for follow-ups. Applies to the `chip` variant only; the
5102
+ * `card` and `list` layouts manage their own stacking.
5103
+ */
5104
+ overflow?: "scroll" | "wrap";
5105
+ /** Maximum visible items. Defaults to 4. */
5106
+ maxItems?: number;
5107
+ };
5108
+ type AgentWidgetStarterSuggestionsConfig = AgentWidgetSuggestionSurfaceConfig & {
5109
+ /** Suggestions shown before the first user message. */
5110
+ items?: AgentWidgetSuggestion[];
5111
+ /**
5112
+ * `auto` uses the welcome surface when the welcome card renders and the
5113
+ * composer otherwise. Explicit values are literal: `welcome` renders
5114
+ * nothing when the welcome card is hidden. Defaults to `auto`.
5115
+ */
5116
+ placement?: "auto" | "welcome" | "composer";
5117
+ };
5118
+ type AgentWidgetFollowUpSuggestionsConfig = AgentWidgetSuggestionSurfaceConfig & {
5119
+ /**
5120
+ * Enable the built-in `suggest_replies` follow-ups. Defaults to true. When
5121
+ * false, `suggest_replies` renders as a regular tool bubble and is NOT
5122
+ * auto-resumed: only set this with no server-side `suggest_replies`
5123
+ * declaration, or the execution parks awaiting a resume that never comes.
5124
+ */
5125
+ enabled?: boolean;
5126
+ /**
5127
+ * Advertise the built-in `suggest_replies` tool to the agent on every
5128
+ * dispatch via `clientTools[]`: no server-side `runtimeTools` declaration
5129
+ * needed. Defaults to `false`. Declare the tool in one place: the API
5130
+ * dedupes a double declaration by name with `clientTools[]` winning, so
5131
+ * the model still sees exactly one tool, but the widget's description and
5132
+ * schema win and the effective tool type becomes `local` (the execution
5133
+ * pauses and the widget auto-resumes it). Ignored when `enabled` is
5134
+ * `false`.
5135
+ */
5136
+ expose?: boolean;
5137
+ /**
5138
+ * `auto` places follow-ups after the transcript in regular panels and above
5139
+ * the composer in composer-bar mode. Defaults to `auto`.
5140
+ */
5141
+ placement?: "auto" | "after-message" | "composer";
5142
+ };
5143
+ /**
5144
+ * Structured suggestions configuration. The legacy `suggestionChips` and
5145
+ * `suggestionChipsConfig` fields remain supported for backwards compatibility.
5146
+ */
5147
+ type AgentWidgetSuggestionsConfig = {
5148
+ starters?: AgentWidgetStarterSuggestionsConfig;
5149
+ followUps?: AgentWidgetFollowUpSuggestionsConfig;
5150
+ };
4849
5151
  /**
4850
5152
  * Interface for pluggable stream parsers that extract text from streaming responses.
4851
5153
  * Parsers handle incremental parsing to extract text values from structured formats (JSON, XML, etc.).
@@ -5998,6 +6300,15 @@ type AgentWidgetConfig = {
5998
6300
  */
5999
6301
  colorScheme?: 'auto' | 'light' | 'dark';
6000
6302
  features?: AgentWidgetFeatureFlags;
6303
+ /**
6304
+ * Per-instance display overrides, applied over `features` through the
6305
+ * preference allowlist (security/capability keys cannot pass). String
6306
+ * `display` values replace the base rule subtree; objects refine it per
6307
+ * key. Each `controller.update({ preferences })` replaces the previous
6308
+ * slice wholesale (dropped keys revert to the base `features`); an
6309
+ * explicit-undefined patch clears it entirely.
6310
+ */
6311
+ preferences?: WidgetPreferenceSlice;
6001
6312
  /**
6002
6313
  * When true, focus the chat input after the panel opens and the open animation completes.
6003
6314
  * Applies to launcher mode (user click, controller.open(), autoExpand) and inline mode (on init).
@@ -6018,7 +6329,11 @@ type AgentWidgetConfig = {
6018
6329
  * with `initialArtifacts`.
6019
6330
  */
6020
6331
  initialSelectedArtifactId?: string | null;
6332
+ /** Rich starter and follow-up suggestion surfaces. */
6333
+ suggestions?: AgentWidgetSuggestionsConfig;
6334
+ /** @deprecated Prefer `suggestions.starters.items`. */
6021
6335
  suggestionChips?: string[];
6336
+ /** @deprecated Prefer semantic tokens under `theme.components.suggestion`. */
6022
6337
  suggestionChipsConfig?: AgentWidgetSuggestionChipsConfig;
6023
6338
  debug?: boolean;
6024
6339
  formEndpoint?: string;
@@ -6758,6 +7073,8 @@ type PersonaArtifactRecord = {
6758
7073
  props?: Record<string, unknown>;
6759
7074
  /** Present when this markdown artifact is a previewable file (see PersonaArtifactFileMeta). */
6760
7075
  file?: PersonaArtifactFileMeta;
7076
+ /** Optional presentation metadata such as the producer's display-mode hint. */
7077
+ presentation?: PersonaArtifactPresentation;
6761
7078
  };
6762
7079
 
6763
7080
  /**