@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
@@ -1,5 +1,39 @@
1
1
  import { IconNode } from 'lucide';
2
2
 
3
+ type AgentWidgetTransformSuggestionsContext = {
4
+ /**
5
+ * Fresh copy of the suggestions entering this plugin, already normalized:
6
+ * shorthand strings expanded and the effective send/fill behavior resolved.
7
+ */
8
+ suggestions: AgentWidgetResolvedSuggestion[];
9
+ surface: AgentWidgetSuggestionSurface;
10
+ source: AgentWidgetSuggestionSource;
11
+ config: AgentWidgetConfig;
12
+ };
13
+ type AgentWidgetRenderSuggestionContext = {
14
+ /** Fully normalized suggestion, including the effective send/fill behavior. */
15
+ suggestion: AgentWidgetResolvedSuggestion;
16
+ index: number;
17
+ surface: AgentWidgetSuggestionSurface;
18
+ source: AgentWidgetSuggestionSource;
19
+ variant: AgentWidgetSuggestionVariant;
20
+ streaming: boolean;
21
+ config: AgentWidgetConfig;
22
+ /** Build Persona's standard chip, card, or list item. */
23
+ defaultRenderer: () => HTMLElement;
24
+ /**
25
+ * Run the normal selection pipeline: DOM event, plugin selection hooks, then
26
+ * send or fill. Custom renderers should call this instead of sending directly.
27
+ */
28
+ select: () => void;
29
+ };
30
+ type AgentWidgetSuggestionSelectContext = {
31
+ suggestion: AgentWidgetResolvedSuggestion;
32
+ surface: AgentWidgetSuggestionSurface;
33
+ source: AgentWidgetSuggestionSource;
34
+ variant: AgentWidgetSuggestionVariant;
35
+ config: AgentWidgetConfig;
36
+ };
3
37
  /**
4
38
  * Plugin interface for customizing widget components
5
39
  */
@@ -12,6 +46,25 @@ interface AgentWidgetPlugin {
12
46
  * Optional priority (higher = runs first). Default: 0
13
47
  */
14
48
  priority?: number;
49
+ /**
50
+ * Transform, filter, enrich, or reorder suggestions. Hooks receive normalized
51
+ * items and compose in plugin priority order; the return value may use the
52
+ * loose shape (string shorthand included) and is re-normalized before the next
53
+ * hook. A per-item `behavior` set here survives. `maxItems` caps the list
54
+ * after the full chain. Return an empty array to hide the surface.
55
+ */
56
+ transformSuggestions?: (context: AgentWidgetTransformSuggestionsContext) => AgentWidgetSuggestion[];
57
+ /**
58
+ * Render one starter or follow-up suggestion. Return null to use Persona's
59
+ * default chip/card/list renderer. Call `select()` from custom interaction
60
+ * controls to preserve events, selection hooks, and send/fill behavior.
61
+ */
62
+ renderSuggestion?: (context: AgentWidgetRenderSuggestionContext) => HTMLElement | null;
63
+ /**
64
+ * Observe or intercept a suggestion selection. Return false to cancel the
65
+ * built-in send/fill action. Hooks run in plugin priority order.
66
+ */
67
+ onSuggestionSelect?: (context: AgentWidgetSuggestionSelectContext) => void | boolean;
15
68
  /**
16
69
  * Custom renderer for message bubbles
17
70
  * Return null to use default renderer
@@ -607,6 +660,14 @@ interface ReasoningBubbleTokens {
607
660
  interface ComposerChromeTokens {
608
661
  /** Box-shadow on the composer form (raw CSS, e.g. `none`). */
609
662
  shadow: string;
663
+ /** Inner padding of the composer form (raw CSS shorthand). @default "0.75rem 1rem" */
664
+ padding?: string;
665
+ /** Gap between the textarea row and the actions row. @default "0.5rem" */
666
+ gap?: string;
667
+ /** Composer textarea font-size. @default "0.875rem" */
668
+ fontSize?: string;
669
+ /** Composer textarea line-height. @default "1.25rem" */
670
+ lineHeight?: string;
610
671
  }
611
672
  /** Artifact toolbar chrome. */
612
673
  interface ArtifactToolbarTokens {
@@ -756,6 +817,26 @@ interface ScrollToBottomTokens extends ComponentTokenSet {
756
817
  fontSize?: string;
757
818
  iconSize?: string;
758
819
  }
820
+ /** Visual tokens shared by one suggestion presentation variant. */
821
+ interface SuggestionVariantTokens extends ComponentTokenSet {
822
+ gap?: string;
823
+ minHeight?: string;
824
+ fontSize?: string;
825
+ lineHeight?: string;
826
+ iconSize?: string;
827
+ hoverBackground?: TokenReference<'color'>;
828
+ hoverForeground?: TokenReference<'color'>;
829
+ hoverBorder?: TokenReference<'color'>;
830
+ pressedBackground?: TokenReference<'color'>;
831
+ focusRing?: TokenReference<'color'>;
832
+ disabledOpacity?: string;
833
+ }
834
+ /** Starter and follow-up suggestion chrome. */
835
+ interface SuggestionTokens {
836
+ chip: SuggestionVariantTokens;
837
+ card: SuggestionVariantTokens;
838
+ list: SuggestionVariantTokens;
839
+ }
759
840
  /** Toggle group chrome (used by createToggleGroup). */
760
841
  interface ToggleGroupTokens {
761
842
  /** Gap between toggle buttons. Default: 0 (connected). */
@@ -786,6 +867,8 @@ interface ComponentTokens {
786
867
  labelButton?: LabelButtonTokens;
787
868
  /** Scroll-to-bottom indicator styling tokens. */
788
869
  scrollToBottom?: ScrollToBottomTokens;
870
+ /** Starter prompt and follow-up suggestion styling tokens. */
871
+ suggestion?: SuggestionTokens;
789
872
  /** Toggle group styling tokens. */
790
873
  toggleGroup?: ToggleGroupTokens;
791
874
  /** Artifact toolbar, tab strip, and pane chrome. */
@@ -1080,7 +1163,24 @@ type RuntypeExecutionStreamEvent = ({
1080
1163
  type: "source";
1081
1164
  url?: string;
1082
1165
  [key: string]: unknown;
1166
+ } | {
1167
+ executionId: string;
1168
+ iteration?: number;
1169
+ seq: number;
1170
+ state: Record<string, unknown>;
1171
+ type: "state_snapshot";
1083
1172
  } | ({
1173
+ executionId: string;
1174
+ iteration?: number;
1175
+ patch: Array<{
1176
+ from?: string;
1177
+ op: "add" | "remove" | "replace" | "move" | "copy" | "test";
1178
+ path: string;
1179
+ value?: unknown;
1180
+ }>;
1181
+ seq: number;
1182
+ type: "state_delta";
1183
+ }) | ({
1084
1184
  executionId: string;
1085
1185
  hiddenParameterNames?: Array<string>;
1086
1186
  iteration?: number;
@@ -1322,6 +1422,7 @@ declare const LUCIDE_ICONS: {
1322
1422
  readonly plus: IconNode;
1323
1423
  readonly minus: IconNode;
1324
1424
  readonly pencil: IconNode;
1425
+ readonly "pen-line": IconNode;
1325
1426
  readonly trash: IconNode;
1326
1427
  readonly "trash-2": IconNode;
1327
1428
  readonly save: IconNode;
@@ -1364,11 +1465,13 @@ declare const LUCIDE_ICONS: {
1364
1465
  readonly folder: IconNode;
1365
1466
  readonly "folder-open": IconNode;
1366
1467
  readonly files: IconNode;
1468
+ readonly "chart-column": IconNode;
1367
1469
  readonly sparkles: IconNode;
1368
1470
  readonly zap: IconNode;
1369
1471
  readonly sun: IconNode;
1370
1472
  readonly moon: IconNode;
1371
1473
  readonly flag: IconNode;
1474
+ readonly lightbulb: IconNode;
1372
1475
  readonly monitor: IconNode;
1373
1476
  readonly smartphone: IconNode;
1374
1477
  };
@@ -1968,6 +2071,14 @@ type AgentToolsConfig = {
1968
2071
  };
1969
2072
  /** Artifact kinds for the Persona sidebar and dispatch payload */
1970
2073
  type PersonaArtifactKind = "markdown" | "component";
2074
+ type PersonaArtifactPresentation = {
2075
+ /**
2076
+ * Producer hint for where this artifact renders (content-disposition
2077
+ * model). Beats configured defaults; loses to explicit `files`/`byKind`
2078
+ * rules. Persona never infers it; the producer or host supplies it.
2079
+ */
2080
+ preferredMode?: PersonaArtifactDisplayModeInput;
2081
+ };
1971
2082
  /**
1972
2083
  * Agent configuration for agent execution mode.
1973
2084
  * When provided in the widget config, enables agent loop execution instead of flow dispatch.
@@ -2496,7 +2607,48 @@ type AgentWidgetArtifactsLayoutConfig = {
2496
2607
  jsonPayload: string;
2497
2608
  }) => void | Promise<void>;
2498
2609
  };
2499
- type PersonaArtifactDisplayMode = "card" | "panel" | "inline";
2610
+ /**
2611
+ * Where the artifact body renders by default. Every mode shows the compact
2612
+ * reference in the transcript; the mode names where the body goes:
2613
+ * nowhere yet (`collapsed`), the side panel (`panel`), or the conversation
2614
+ * itself (`inline`).
2615
+ */
2616
+ type PersonaArtifactDisplayMode = "collapsed" | "panel" | "inline";
2617
+ /**
2618
+ * Accepted wherever a display mode is written. `"card"` is a deprecated
2619
+ * alias of `"collapsed"` (the old name described the reference card, which
2620
+ * every mode shows, instead of where the body renders). Resolution and
2621
+ * parsing always canonicalize to `"collapsed"`.
2622
+ */
2623
+ type PersonaArtifactDisplayModeInput = PersonaArtifactDisplayMode | "card";
2624
+ /**
2625
+ * Display rules for file-backed artifacts. `byMediaType` keys are exact MIME
2626
+ * types (`"text/html"`) or major-type wildcards (`"image/*"`), matched
2627
+ * case-insensitively without parameters; exact beats wildcard.
2628
+ */
2629
+ type PersonaArtifactFilesDisplayRules = {
2630
+ default?: PersonaArtifactDisplayModeInput;
2631
+ byMediaType?: Record<string, PersonaArtifactDisplayModeInput>;
2632
+ };
2633
+ /**
2634
+ * Scoped artifact display rules. Matching resolves from the most specific
2635
+ * selector to `default`; see `resolveArtifactDisplay`.
2636
+ *
2637
+ * Across preference layers, one merge rule applies everywhere: a string value
2638
+ * replaces the whole subtree it names; an object refines it per key. So
2639
+ * `files: "inline"` overrides every lower-layer file rule, while
2640
+ * `files: { default: "inline" }` keeps lower-layer MIME exceptions.
2641
+ */
2642
+ type PersonaArtifactDisplayRules = {
2643
+ default?: PersonaArtifactDisplayModeInput;
2644
+ byKind?: Partial<Record<PersonaArtifactKind, PersonaArtifactDisplayModeInput>>;
2645
+ /**
2646
+ * @deprecated Use `byKind`. When both are present, `byKind` wins.
2647
+ */
2648
+ byType?: Partial<Record<PersonaArtifactKind, PersonaArtifactDisplayModeInput>>;
2649
+ /** Rules for any artifact carrying file metadata. */
2650
+ files?: PersonaArtifactDisplayModeInput | PersonaArtifactFilesDisplayRules;
2651
+ };
2500
2652
  /** 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. */
2501
2653
  type PersonaArtifactActionContext = {
2502
2654
  artifactId: string | null;
@@ -2553,13 +2705,10 @@ type AgentWidgetArtifactsFeature = {
2553
2705
  allowedTypes?: PersonaArtifactKind[];
2554
2706
  /**
2555
2707
  * Where artifact bodies render. A single mode applies to all artifacts;
2556
- * the object form sets a default plus per-type overrides.
2708
+ * the object form sets a default plus scoped overrides.
2557
2709
  * Defaults to "panel" (current behavior).
2558
2710
  */
2559
- display?: PersonaArtifactDisplayMode | {
2560
- default?: PersonaArtifactDisplayMode;
2561
- byType?: Partial<Record<PersonaArtifactKind, PersonaArtifactDisplayMode>>;
2562
- };
2711
+ display?: PersonaArtifactDisplayModeInput | PersonaArtifactDisplayRules;
2563
2712
  /** Split / drawer dimensions and launcher widen behavior */
2564
2713
  layout?: AgentWidgetArtifactsLayoutConfig;
2565
2714
  /**
@@ -3281,19 +3430,58 @@ type AgentWidgetFeatureFlags = {
3281
3430
  */
3282
3431
  askUserQuestion?: AgentWidgetAskUserQuestionFeature;
3283
3432
  /**
3284
- * Built-in `suggest_replies` quick-reply chips. When the assistant invokes
3285
- * the tool, the widget shows the suggestions as tappable chips above the
3286
- * composer (reusing the suggestion-chips surface) and immediately resumes
3287
- * the execution: fire-and-forget, no user input awaited.
3433
+ * Built-in `suggest_replies` follow-ups. When the assistant invokes the
3434
+ * tool, the widget shows the suggestions using `suggestions.followUps` and
3435
+ * immediately resumes the execution: fire-and-forget, no user input awaited.
3436
+ *
3437
+ * @deprecated Both keys moved to `suggestions.followUps`: use
3438
+ * `suggestions.followUps.enabled` and `suggestions.followUps.expose`. This
3439
+ * alias keeps working per key, with `suggestions.followUps` winning.
3288
3440
  */
3289
3441
  suggestReplies?: AgentWidgetSuggestRepliesFeature;
3290
3442
  };
3291
3443
  /**
3292
- * Feature config for the built-in `suggest_replies` quick-reply chips.
3293
- * Chips render in the existing suggestions slot above the composer and are
3294
- * styled by the widget-level `suggestionChipsConfig`. A tapped chip is sent
3295
- * verbatim as the user's next message; chips clear once any user message
3296
- * follows them.
3444
+ * Persistable artifact-layout choices. The full layout config deliberately is
3445
+ * not exposed because it also contains callbacks and embedder-owned chrome.
3446
+ */
3447
+ type WidgetArtifactLayoutPreference = Pick<AgentWidgetArtifactsLayoutConfig, "paneWidth" | "paneMaxWidth" | "paneMinWidth" | "expandLauncherPanelWhenOpen" | "expandedPanelWidth" | "resizable" | "resizableMinWidth" | "resizableMaxWidth">;
3448
+ /**
3449
+ * Curated, JSON-serializable display preferences in native `features` shape.
3450
+ *
3451
+ * Absence means inherit the next preference layer and ultimately Persona's
3452
+ * current default. Persist only explicit choices; resetting a choice deletes
3453
+ * its key.
3454
+ *
3455
+ * Capability facts (`artifacts.enabled`, `allowedTypes`), trusted iframe
3456
+ * security, callbacks, actions, renderers, labels, and theme styling are
3457
+ * intentionally excluded because they remain embedder/code-owned.
3458
+ */
3459
+ type WidgetPreferenceSlice = {
3460
+ showToolCalls?: boolean;
3461
+ showReasoning?: boolean;
3462
+ toolCallDisplay?: Pick<AgentWidgetToolCallDisplayFeature, "collapsedMode" | "expandable" | "grouped" | "groupedMode" | "loadingAnimation">;
3463
+ reasoningDisplay?: Pick<AgentWidgetReasoningDisplayFeature, "expandable" | "activePreview">;
3464
+ artifacts?: {
3465
+ /**
3466
+ * String and object forms are both persistable and mean different things
3467
+ * when layers merge: a string replaces every lower-layer display rule; an
3468
+ * object refines lower layers per selector key (same rule applies to
3469
+ * `display.files`).
3470
+ */
3471
+ display?: PersonaArtifactDisplayModeInput | PersonaArtifactDisplayRules;
3472
+ filePreview?: {
3473
+ enabled?: boolean;
3474
+ };
3475
+ layout?: WidgetArtifactLayoutPreference;
3476
+ };
3477
+ };
3478
+ /**
3479
+ * Feature config for the built-in `suggest_replies` follow-ups.
3480
+ *
3481
+ * @deprecated Both keys moved to `suggestions.followUps`
3482
+ * (`suggestions.followUps.enabled` / `suggestions.followUps.expose`), which
3483
+ * also owns presentation, placement, and send/fill behavior. Resolution is
3484
+ * per key with `suggestions.followUps` winning; removal waits for 5.0.
3297
3485
  */
3298
3486
  type AgentWidgetSuggestRepliesFeature = {
3299
3487
  /**
@@ -3301,14 +3489,18 @@ type AgentWidgetSuggestRepliesFeature = {
3301
3489
  * renders as a regular tool bubble and is NOT auto-resumed: only set this
3302
3490
  * with no server-side `suggest_replies` declaration, or the execution
3303
3491
  * parks awaiting a resume that never comes.
3492
+ * @deprecated Use `suggestions.followUps.enabled`.
3304
3493
  */
3305
3494
  enabled?: boolean;
3306
3495
  /**
3307
3496
  * Advertise the built-in `suggest_replies` tool to the agent on every
3308
3497
  * dispatch via `clientTools[]`: no server-side `runtimeTools` declaration
3309
- * needed. Defaults to `false`: flows that already declare the tool via
3310
- * `runtimeTools` would otherwise present it to the model twice. Ignored
3311
- * when `enabled` is `false`.
3498
+ * needed. Defaults to `false`. Declare the tool in one place: the API
3499
+ * dedupes a double declaration by name with `clientTools[]` winning, so the
3500
+ * model still sees exactly one tool, but the widget's description and schema
3501
+ * win and the effective tool type becomes `local` (the execution pauses and
3502
+ * the widget auto-resumes it). Ignored when `enabled` is `false`.
3503
+ * @deprecated Use `suggestions.followUps.expose`.
3312
3504
  */
3313
3505
  expose?: boolean;
3314
3506
  };
@@ -3378,10 +3570,13 @@ type AgentWidgetAskUserQuestionFeature = {
3378
3570
  * matching {@link AskUserQuestionPayload}; when the model calls it, the
3379
3571
  * existing answer-pill sheet renders and the answer resumes the execution.
3380
3572
  *
3381
- * Defaults to `false`: flows that already declare `ask_user_question` via
3382
- * `runtimeTools` would otherwise present the tool to the model twice.
3383
- * Ignored when `enabled` is `false`: never offer the agent a question
3384
- * tool the widget can't render an answer UI for.
3573
+ * Defaults to `false`. Declare the tool in one place: the API dedupes a
3574
+ * double declaration by name with `clientTools[]` winning, so the model
3575
+ * still sees exactly one tool, but the widget's description and schema win
3576
+ * and the effective tool type becomes `local` (the execution pauses and the
3577
+ * widget resumes it with the user's answer). Ignored when `enabled` is
3578
+ * `false`: never offer the agent a question tool the widget can't render an
3579
+ * answer UI for.
3385
3580
  */
3386
3581
  expose?: boolean;
3387
3582
  /** Slide-in animation duration in ms. Defaults to 180. */
@@ -3854,6 +4049,10 @@ type AgentWidgetSendButtonConfig = {
3854
4049
  paddingY?: string;
3855
4050
  iconText?: string;
3856
4051
  iconName?: string;
4052
+ /** Icon glyph box in icon mode, e.g. "20px". Defaults to half of `size`. */
4053
+ iconSize?: string;
4054
+ /** Stroke width for the icon glyph, in viewBox units. Default 2. */
4055
+ iconStrokeWidth?: number;
3857
4056
  useIcon?: boolean;
3858
4057
  tooltipText?: string;
3859
4058
  showTooltip?: boolean;
@@ -4577,6 +4776,109 @@ type AgentWidgetSuggestionChipsConfig = {
4577
4776
  paddingX?: string;
4578
4777
  paddingY?: string;
4579
4778
  };
4779
+ /** A suggested next action shown to the user. Strings remain supported as shorthand. */
4780
+ type AgentWidgetSuggestion = string | {
4781
+ /** Stable analytics / DOM identity. Falls back to the prompt or label. */
4782
+ id?: string;
4783
+ /** Concise visible action label. */
4784
+ label: string;
4785
+ /** Text placed in the composer or sent. Defaults to `label`. */
4786
+ prompt?: string;
4787
+ /** Optional supporting copy, most useful with the `card` variant. */
4788
+ description?: string;
4789
+ /** Optional icon from Persona's bundled Lucide registry. */
4790
+ icon?: IconName;
4791
+ /**
4792
+ * CSS color for this item's glyph. Tints the icon only: label, border,
4793
+ * and background stay neutral. Ignored without an `icon`.
4794
+ */
4795
+ iconColor?: string;
4796
+ /** Override the surface's click behavior for this item. */
4797
+ behavior?: AgentWidgetSuggestionBehavior;
4798
+ /** Visually promote one high-confidence action. */
4799
+ emphasis?: "default" | "primary";
4800
+ };
4801
+ type AgentWidgetSuggestionBehavior = "send" | "fill";
4802
+ type AgentWidgetSuggestionVariant = "chip" | "card" | "list";
4803
+ type AgentWidgetSuggestionSurface = "starter" | "followUp";
4804
+ /**
4805
+ * Who produced the rendered suggestions: static config, the agent's
4806
+ * `suggest_replies` tool, or `controller.setFollowUpSuggestions`.
4807
+ */
4808
+ type AgentWidgetSuggestionSource = "config" | "agent" | "host";
4809
+ /**
4810
+ * A suggestion after Persona has normalized shorthand strings and resolved the
4811
+ * effective click behavior. Plugin hooks receive this stable shape.
4812
+ */
4813
+ type AgentWidgetResolvedSuggestion = {
4814
+ id: string;
4815
+ label: string;
4816
+ prompt: string;
4817
+ description?: string;
4818
+ icon?: IconName;
4819
+ /** CSS color for the glyph only; never the label, border, or background. */
4820
+ iconColor?: string;
4821
+ behavior: AgentWidgetSuggestionBehavior;
4822
+ emphasis: "default" | "primary";
4823
+ };
4824
+ /** Presentation keys shared by every suggestion surface. */
4825
+ type AgentWidgetSuggestionSurfaceConfig = {
4826
+ /** Item density. Defaults to `card` for starters and `chip` for follow-ups. */
4827
+ variant?: AgentWidgetSuggestionVariant;
4828
+ /** Default click behavior, overridable per item. Defaults to `send`. */
4829
+ behavior?: AgentWidgetSuggestionBehavior;
4830
+ /**
4831
+ * Layout for items past the surface width. Defaults to `wrap` for starters
4832
+ * and `scroll` for follow-ups. Applies to the `chip` variant only; the
4833
+ * `card` and `list` layouts manage their own stacking.
4834
+ */
4835
+ overflow?: "scroll" | "wrap";
4836
+ /** Maximum visible items. Defaults to 4. */
4837
+ maxItems?: number;
4838
+ };
4839
+ type AgentWidgetStarterSuggestionsConfig = AgentWidgetSuggestionSurfaceConfig & {
4840
+ /** Suggestions shown before the first user message. */
4841
+ items?: AgentWidgetSuggestion[];
4842
+ /**
4843
+ * `auto` uses the welcome surface when the welcome card renders and the
4844
+ * composer otherwise. Explicit values are literal: `welcome` renders
4845
+ * nothing when the welcome card is hidden. Defaults to `auto`.
4846
+ */
4847
+ placement?: "auto" | "welcome" | "composer";
4848
+ };
4849
+ type AgentWidgetFollowUpSuggestionsConfig = AgentWidgetSuggestionSurfaceConfig & {
4850
+ /**
4851
+ * Enable the built-in `suggest_replies` follow-ups. Defaults to true. When
4852
+ * false, `suggest_replies` renders as a regular tool bubble and is NOT
4853
+ * auto-resumed: only set this with no server-side `suggest_replies`
4854
+ * declaration, or the execution parks awaiting a resume that never comes.
4855
+ */
4856
+ enabled?: boolean;
4857
+ /**
4858
+ * Advertise the built-in `suggest_replies` tool to the agent on every
4859
+ * dispatch via `clientTools[]`: no server-side `runtimeTools` declaration
4860
+ * needed. Defaults to `false`. Declare the tool in one place: the API
4861
+ * dedupes a double declaration by name with `clientTools[]` winning, so
4862
+ * the model still sees exactly one tool, but the widget's description and
4863
+ * schema win and the effective tool type becomes `local` (the execution
4864
+ * pauses and the widget auto-resumes it). Ignored when `enabled` is
4865
+ * `false`.
4866
+ */
4867
+ expose?: boolean;
4868
+ /**
4869
+ * `auto` places follow-ups after the transcript in regular panels and above
4870
+ * the composer in composer-bar mode. Defaults to `auto`.
4871
+ */
4872
+ placement?: "auto" | "after-message" | "composer";
4873
+ };
4874
+ /**
4875
+ * Structured suggestions configuration. The legacy `suggestionChips` and
4876
+ * `suggestionChipsConfig` fields remain supported for backwards compatibility.
4877
+ */
4878
+ type AgentWidgetSuggestionsConfig = {
4879
+ starters?: AgentWidgetStarterSuggestionsConfig;
4880
+ followUps?: AgentWidgetFollowUpSuggestionsConfig;
4881
+ };
4580
4882
  /**
4581
4883
  * Interface for pluggable stream parsers that extract text from streaming responses.
4582
4884
  * Parsers handle incremental parsing to extract text values from structured formats (JSON, XML, etc.).
@@ -5729,6 +6031,15 @@ type AgentWidgetConfig = {
5729
6031
  */
5730
6032
  colorScheme?: 'auto' | 'light' | 'dark';
5731
6033
  features?: AgentWidgetFeatureFlags;
6034
+ /**
6035
+ * Per-instance display overrides, applied over `features` through the
6036
+ * preference allowlist (security/capability keys cannot pass). String
6037
+ * `display` values replace the base rule subtree; objects refine it per
6038
+ * key. Each `controller.update({ preferences })` replaces the previous
6039
+ * slice wholesale (dropped keys revert to the base `features`); an
6040
+ * explicit-undefined patch clears it entirely.
6041
+ */
6042
+ preferences?: WidgetPreferenceSlice;
5732
6043
  /**
5733
6044
  * When true, focus the chat input after the panel opens and the open animation completes.
5734
6045
  * Applies to launcher mode (user click, controller.open(), autoExpand) and inline mode (on init).
@@ -5749,7 +6060,11 @@ type AgentWidgetConfig = {
5749
6060
  * with `initialArtifacts`.
5750
6061
  */
5751
6062
  initialSelectedArtifactId?: string | null;
6063
+ /** Rich starter and follow-up suggestion surfaces. */
6064
+ suggestions?: AgentWidgetSuggestionsConfig;
6065
+ /** @deprecated Prefer `suggestions.starters.items`. */
5752
6066
  suggestionChips?: string[];
6067
+ /** @deprecated Prefer semantic tokens under `theme.components.suggestion`. */
5753
6068
  suggestionChipsConfig?: AgentWidgetSuggestionChipsConfig;
5754
6069
  debug?: boolean;
5755
6070
  formEndpoint?: string;
@@ -6489,6 +6804,8 @@ type PersonaArtifactRecord = {
6489
6804
  props?: Record<string, unknown>;
6490
6805
  /** Present when this markdown artifact is a previewable file (see PersonaArtifactFileMeta). */
6491
6806
  file?: PersonaArtifactFileMeta;
6807
+ /** Optional presentation metadata such as the producer's display-mode hint. */
6808
+ presentation?: PersonaArtifactPresentation;
6492
6809
  };
6493
6810
 
6494
6811
  /** The resolved bundle gathered at submit, merged into the user message. */