@runtypelabs/persona 4.12.0 → 4.14.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 (68) hide show
  1. package/dist/codegen.cjs +1 -1
  2. package/dist/codegen.js +1 -1
  3. package/dist/context-mentions.d.cts +98 -6
  4. package/dist/context-mentions.d.ts +98 -6
  5. package/dist/index.cjs +64 -64
  6. package/dist/index.cjs.map +1 -1
  7. package/dist/index.d.cts +183 -8
  8. package/dist/index.d.ts +183 -8
  9. package/dist/index.global.js +54 -54
  10. package/dist/index.global.js.map +1 -1
  11. package/dist/index.js +67 -67
  12. package/dist/index.js.map +1 -1
  13. package/dist/launcher.global.js +1 -1
  14. package/dist/launcher.global.js.map +1 -1
  15. package/dist/smart-dom-reader.d.cts +98 -6
  16. package/dist/smart-dom-reader.d.ts +98 -6
  17. package/dist/theme-editor-preview.cjs +66 -66
  18. package/dist/theme-editor-preview.d.cts +100 -6
  19. package/dist/theme-editor-preview.d.ts +100 -6
  20. package/dist/theme-editor-preview.js +75 -75
  21. package/dist/theme-editor.cjs +10 -10
  22. package/dist/theme-editor.d.cts +134 -7
  23. package/dist/theme-editor.d.ts +134 -7
  24. package/dist/theme-editor.js +10 -10
  25. package/dist/theme-reference.cjs +1 -1
  26. package/dist/widget.css +1 -1
  27. package/package.json +1 -1
  28. package/src/artifacts-session.test.ts +106 -0
  29. package/src/client.test.ts +2 -2
  30. package/src/client.ts +4 -1
  31. package/src/components/artifact-card.ts +13 -2
  32. package/src/components/artifact-inline.ts +11 -2
  33. package/src/components/composer-builder.test.ts +2 -0
  34. package/src/components/composer-builder.ts +1 -1
  35. package/src/components/composer-parts.test.ts +2 -0
  36. package/src/components/composer-parts.ts +1 -1
  37. package/src/components/message-bubble.test.ts +7 -1
  38. package/src/components/message-bubble.ts +11 -8
  39. package/src/index-core.ts +34 -0
  40. package/src/session.ts +45 -4
  41. package/src/styles/widget.css +10 -1
  42. package/src/theme-editor/index.ts +5 -0
  43. package/src/theme-editor/presets.test.ts +43 -0
  44. package/src/theme-editor/presets.ts +101 -87
  45. package/src/theme-editor/sections.test.ts +39 -7
  46. package/src/theme-editor/sections.ts +60 -8
  47. package/src/theme-editor/state-preferences.test.ts +15 -0
  48. package/src/theme-editor/state.ts +46 -0
  49. package/src/theme-editor/types.ts +15 -1
  50. package/src/theme-editor/webmcp/tools.test.ts +13 -0
  51. package/src/theme-editor/webmcp/tools.ts +5 -0
  52. package/src/types.ts +139 -9
  53. package/src/ui.artifact-pane-gating.test.ts +5 -5
  54. package/src/ui.config-preferences.test.ts +166 -0
  55. package/src/ui.scroll-additive.test.ts +365 -0
  56. package/src/ui.scroll.test.ts +19 -6
  57. package/src/ui.ts +158 -53
  58. package/src/ui.typing-indicator.test.ts +135 -0
  59. package/src/utils/artifact-display.test.ts +180 -16
  60. package/src/utils/artifact-display.ts +155 -14
  61. package/src/utils/auto-follow.test.ts +38 -0
  62. package/src/utils/auto-follow.ts +35 -0
  63. package/src/utils/config-merge.test.ts +60 -0
  64. package/src/utils/config-merge.ts +6 -1
  65. package/src/utils/feature-preferences.test.ts +326 -0
  66. package/src/utils/feature-preferences.ts +498 -0
  67. package/src/utils/theme.test.ts +92 -0
  68. package/src/utils/tokens.ts +7 -7
package/dist/codegen.cjs CHANGED
@@ -1,4 +1,4 @@
1
- "use strict";var b=Object.defineProperty;var v=Object.getOwnPropertyDescriptor;var _=Object.getOwnPropertyNames;var T=Object.prototype.hasOwnProperty;var M=(e,i)=>{for(var r in i)b(e,r,{get:i[r],enumerable:!0})},R=(e,i,r,s)=>{if(i&&typeof i=="object"||typeof i=="function")for(let a of _(i))!T.call(e,a)&&a!==r&&b(e,a,{get:()=>i[a],enumerable:!(s=v(i,a))||s.enumerable});return e};var W=e=>R(b({},"__esModule",{value:!0}),e);var U={};M(U,{generateCodeSnippet:()=>P});module.exports=W(U);var S="4.12.0";var x=S;function $(e){return e?.cdnBase?.trim().replace(/\/+$/,"").replace(/[\\'"<>`]/g,r=>`%${r.charCodeAt(0).toString(16).toUpperCase().padStart(2,"0")}`)||`https://cdn.jsdelivr.net/npm/@runtypelabs/persona@${x}/dist`}function u(e){if(e!==void 0)return typeof e=="string"?e:Array.isArray(e)?`[${e.map(i=>i.toString()).join(", ")}]`:e.toString()}function N(e){if(e)return{getHeaders:u(e.getHeaders),onFeedback:u(e.onFeedback),onCopy:u(e.onCopy),requestMiddleware:u(e.requestMiddleware),actionHandlers:u(e.actionHandlers),actionParsers:u(e.actionParsers),postprocessMessage:u(e.postprocessMessage),contextProviders:u(e.contextProviders),streamParser:u(e.streamParser)}}var A=`({ text, message }: any) => {
1
+ "use strict";var b=Object.defineProperty;var v=Object.getOwnPropertyDescriptor;var _=Object.getOwnPropertyNames;var T=Object.prototype.hasOwnProperty;var M=(e,i)=>{for(var r in i)b(e,r,{get:i[r],enumerable:!0})},R=(e,i,r,s)=>{if(i&&typeof i=="object"||typeof i=="function")for(let a of _(i))!T.call(e,a)&&a!==r&&b(e,a,{get:()=>i[a],enumerable:!(s=v(i,a))||s.enumerable});return e};var W=e=>R(b({},"__esModule",{value:!0}),e);var U={};M(U,{generateCodeSnippet:()=>P});module.exports=W(U);var S="4.14.0";var x=S;function $(e){return e?.cdnBase?.trim().replace(/\/+$/,"").replace(/[\\'"<>`]/g,r=>`%${r.charCodeAt(0).toString(16).toUpperCase().padStart(2,"0")}`)||`https://cdn.jsdelivr.net/npm/@runtypelabs/persona@${x}/dist`}function u(e){if(e!==void 0)return typeof e=="string"?e:Array.isArray(e)?`[${e.map(i=>i.toString()).join(", ")}]`:e.toString()}function N(e){if(e)return{getHeaders:u(e.getHeaders),onFeedback:u(e.onFeedback),onCopy:u(e.onCopy),requestMiddleware:u(e.requestMiddleware),actionHandlers:u(e.actionHandlers),actionParsers:u(e.actionParsers),postprocessMessage:u(e.postprocessMessage),contextProviders:u(e.contextProviders),streamParser:u(e.streamParser)}}var A=`({ text, message }: any) => {
2
2
  const jsonSource = (message as any).rawContent || text || message.content;
3
3
  if (!jsonSource || typeof jsonSource !== 'string') return null;
4
4
  let cleanJson = jsonSource
package/dist/codegen.js CHANGED
@@ -1,4 +1,4 @@
1
- var w="4.12.0";var S=w;function b(e){return e?.cdnBase?.trim().replace(/\/+$/,"").replace(/[\\'"<>`]/g,r=>`%${r.charCodeAt(0).toString(16).toUpperCase().padStart(2,"0")}`)||`https://cdn.jsdelivr.net/npm/@runtypelabs/persona@${S}/dist`}function u(e){if(e!==void 0)return typeof e=="string"?e:Array.isArray(e)?`[${e.map(i=>i.toString()).join(", ")}]`:e.toString()}function I(e){if(e)return{getHeaders:u(e.getHeaders),onFeedback:u(e.onFeedback),onCopy:u(e.onCopy),requestMiddleware:u(e.requestMiddleware),actionHandlers:u(e.actionHandlers),actionParsers:u(e.actionParsers),postprocessMessage:u(e.postprocessMessage),contextProviders:u(e.contextProviders),streamParser:u(e.streamParser)}}var x=`({ text, message }: any) => {
1
+ var w="4.14.0";var S=w;function b(e){return e?.cdnBase?.trim().replace(/\/+$/,"").replace(/[\\'"<>`]/g,r=>`%${r.charCodeAt(0).toString(16).toUpperCase().padStart(2,"0")}`)||`https://cdn.jsdelivr.net/npm/@runtypelabs/persona@${S}/dist`}function u(e){if(e!==void 0)return typeof e=="string"?e:Array.isArray(e)?`[${e.map(i=>i.toString()).join(", ")}]`:e.toString()}function I(e){if(e)return{getHeaders:u(e.getHeaders),onFeedback:u(e.onFeedback),onCopy:u(e.onCopy),requestMiddleware:u(e.requestMiddleware),actionHandlers:u(e.actionHandlers),actionParsers:u(e.actionParsers),postprocessMessage:u(e.postprocessMessage),contextProviders:u(e.contextProviders),streamParser:u(e.streamParser)}}var x=`({ text, message }: any) => {
2
2
  const jsonSource = (message as any).rawContent || text || message.content;
3
3
  if (!jsonSource || typeof jsonSource !== 'string') return null;
4
4
  let cleanJson = jsonSource
@@ -1968,6 +1968,14 @@ type AgentToolsConfig = {
1968
1968
  };
1969
1969
  /** Artifact kinds for the Persona sidebar and dispatch payload */
1970
1970
  type PersonaArtifactKind = "markdown" | "component";
1971
+ type PersonaArtifactPresentation = {
1972
+ /**
1973
+ * Producer hint for where this artifact renders (content-disposition
1974
+ * model). Beats configured defaults; loses to explicit `files`/`byKind`
1975
+ * rules. Persona never infers it; the producer or host supplies it.
1976
+ */
1977
+ preferredMode?: PersonaArtifactDisplayModeInput;
1978
+ };
1971
1979
  /**
1972
1980
  * Agent configuration for agent execution mode.
1973
1981
  * When provided in the widget config, enables agent loop execution instead of flow dispatch.
@@ -2496,7 +2504,48 @@ type AgentWidgetArtifactsLayoutConfig = {
2496
2504
  jsonPayload: string;
2497
2505
  }) => void | Promise<void>;
2498
2506
  };
2499
- type PersonaArtifactDisplayMode = "card" | "panel" | "inline";
2507
+ /**
2508
+ * Where the artifact body renders by default. Every mode shows the compact
2509
+ * reference in the transcript; the mode names where the body goes:
2510
+ * nowhere yet (`collapsed`), the side panel (`panel`), or the conversation
2511
+ * itself (`inline`).
2512
+ */
2513
+ type PersonaArtifactDisplayMode = "collapsed" | "panel" | "inline";
2514
+ /**
2515
+ * Accepted wherever a display mode is written. `"card"` is a deprecated
2516
+ * alias of `"collapsed"` (the old name described the reference card, which
2517
+ * every mode shows, instead of where the body renders). Resolution and
2518
+ * parsing always canonicalize to `"collapsed"`.
2519
+ */
2520
+ type PersonaArtifactDisplayModeInput = PersonaArtifactDisplayMode | "card";
2521
+ /**
2522
+ * Display rules for file-backed artifacts. `byMediaType` keys are exact MIME
2523
+ * types (`"text/html"`) or major-type wildcards (`"image/*"`), matched
2524
+ * case-insensitively without parameters; exact beats wildcard.
2525
+ */
2526
+ type PersonaArtifactFilesDisplayRules = {
2527
+ default?: PersonaArtifactDisplayModeInput;
2528
+ byMediaType?: Record<string, PersonaArtifactDisplayModeInput>;
2529
+ };
2530
+ /**
2531
+ * Scoped artifact display rules. Matching resolves from the most specific
2532
+ * selector to `default`; see `resolveArtifactDisplay`.
2533
+ *
2534
+ * Across preference layers, one merge rule applies everywhere: a string value
2535
+ * replaces the whole subtree it names; an object refines it per key. So
2536
+ * `files: "inline"` overrides every lower-layer file rule, while
2537
+ * `files: { default: "inline" }` keeps lower-layer MIME exceptions.
2538
+ */
2539
+ type PersonaArtifactDisplayRules = {
2540
+ default?: PersonaArtifactDisplayModeInput;
2541
+ byKind?: Partial<Record<PersonaArtifactKind, PersonaArtifactDisplayModeInput>>;
2542
+ /**
2543
+ * @deprecated Use `byKind`. When both are present, `byKind` wins.
2544
+ */
2545
+ byType?: Partial<Record<PersonaArtifactKind, PersonaArtifactDisplayModeInput>>;
2546
+ /** Rules for any artifact carrying file metadata. */
2547
+ files?: PersonaArtifactDisplayModeInput | PersonaArtifactFilesDisplayRules;
2548
+ };
2500
2549
  /** 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
2550
  type PersonaArtifactActionContext = {
2502
2551
  artifactId: string | null;
@@ -2553,13 +2602,10 @@ type AgentWidgetArtifactsFeature = {
2553
2602
  allowedTypes?: PersonaArtifactKind[];
2554
2603
  /**
2555
2604
  * Where artifact bodies render. A single mode applies to all artifacts;
2556
- * the object form sets a default plus per-type overrides.
2605
+ * the object form sets a default plus scoped overrides.
2557
2606
  * Defaults to "panel" (current behavior).
2558
2607
  */
2559
- display?: PersonaArtifactDisplayMode | {
2560
- default?: PersonaArtifactDisplayMode;
2561
- byType?: Partial<Record<PersonaArtifactKind, PersonaArtifactDisplayMode>>;
2562
- };
2608
+ display?: PersonaArtifactDisplayModeInput | PersonaArtifactDisplayRules;
2563
2609
  /** Split / drawer dimensions and launcher widen behavior */
2564
2610
  layout?: AgentWidgetArtifactsLayoutConfig;
2565
2611
  /**
@@ -3288,6 +3334,41 @@ type AgentWidgetFeatureFlags = {
3288
3334
  */
3289
3335
  suggestReplies?: AgentWidgetSuggestRepliesFeature;
3290
3336
  };
3337
+ /**
3338
+ * Persistable artifact-layout choices. The full layout config deliberately is
3339
+ * not exposed because it also contains callbacks and embedder-owned chrome.
3340
+ */
3341
+ type WidgetArtifactLayoutPreference = Pick<AgentWidgetArtifactsLayoutConfig, "paneWidth" | "paneMaxWidth" | "paneMinWidth" | "expandLauncherPanelWhenOpen" | "expandedPanelWidth" | "resizable" | "resizableMinWidth" | "resizableMaxWidth">;
3342
+ /**
3343
+ * Curated, JSON-serializable display preferences in native `features` shape.
3344
+ *
3345
+ * Absence means inherit the next preference layer and ultimately Persona's
3346
+ * current default. Persist only explicit choices; resetting a choice deletes
3347
+ * its key.
3348
+ *
3349
+ * Capability facts (`artifacts.enabled`, `allowedTypes`), trusted iframe
3350
+ * security, callbacks, actions, renderers, labels, and theme styling are
3351
+ * intentionally excluded because they remain embedder/code-owned.
3352
+ */
3353
+ type WidgetPreferenceSlice = {
3354
+ showToolCalls?: boolean;
3355
+ showReasoning?: boolean;
3356
+ toolCallDisplay?: Pick<AgentWidgetToolCallDisplayFeature, "collapsedMode" | "expandable" | "grouped" | "groupedMode" | "loadingAnimation">;
3357
+ reasoningDisplay?: Pick<AgentWidgetReasoningDisplayFeature, "expandable" | "activePreview">;
3358
+ artifacts?: {
3359
+ /**
3360
+ * String and object forms are both persistable and mean different things
3361
+ * when layers merge: a string replaces every lower-layer display rule; an
3362
+ * object refines lower layers per selector key (same rule applies to
3363
+ * `display.files`).
3364
+ */
3365
+ display?: PersonaArtifactDisplayModeInput | PersonaArtifactDisplayRules;
3366
+ filePreview?: {
3367
+ enabled?: boolean;
3368
+ };
3369
+ layout?: WidgetArtifactLayoutPreference;
3370
+ };
3371
+ };
3291
3372
  /**
3292
3373
  * Feature config for the built-in `suggest_replies` quick-reply chips.
3293
3374
  * Chips render in the existing suggestions slot above the composer and are
@@ -5729,6 +5810,15 @@ type AgentWidgetConfig = {
5729
5810
  */
5730
5811
  colorScheme?: 'auto' | 'light' | 'dark';
5731
5812
  features?: AgentWidgetFeatureFlags;
5813
+ /**
5814
+ * Per-instance display overrides, applied over `features` through the
5815
+ * preference allowlist (security/capability keys cannot pass). String
5816
+ * `display` values replace the base rule subtree; objects refine it per
5817
+ * key. Each `controller.update({ preferences })` replaces the previous
5818
+ * slice wholesale (dropped keys revert to the base `features`); an
5819
+ * explicit-undefined patch clears it entirely.
5820
+ */
5821
+ preferences?: WidgetPreferenceSlice;
5732
5822
  /**
5733
5823
  * When true, focus the chat input after the panel opens and the open animation completes.
5734
5824
  * Applies to launcher mode (user click, controller.open(), autoExpand) and inline mode (on init).
@@ -6489,6 +6579,8 @@ type PersonaArtifactRecord = {
6489
6579
  props?: Record<string, unknown>;
6490
6580
  /** Present when this markdown artifact is a previewable file (see PersonaArtifactFileMeta). */
6491
6581
  file?: PersonaArtifactFileMeta;
6582
+ /** Optional presentation metadata such as the producer's display-mode hint. */
6583
+ presentation?: PersonaArtifactPresentation;
6492
6584
  };
6493
6585
 
6494
6586
  /** The resolved bundle gathered at submit, merged into the user message. */
@@ -1968,6 +1968,14 @@ type AgentToolsConfig = {
1968
1968
  };
1969
1969
  /** Artifact kinds for the Persona sidebar and dispatch payload */
1970
1970
  type PersonaArtifactKind = "markdown" | "component";
1971
+ type PersonaArtifactPresentation = {
1972
+ /**
1973
+ * Producer hint for where this artifact renders (content-disposition
1974
+ * model). Beats configured defaults; loses to explicit `files`/`byKind`
1975
+ * rules. Persona never infers it; the producer or host supplies it.
1976
+ */
1977
+ preferredMode?: PersonaArtifactDisplayModeInput;
1978
+ };
1971
1979
  /**
1972
1980
  * Agent configuration for agent execution mode.
1973
1981
  * When provided in the widget config, enables agent loop execution instead of flow dispatch.
@@ -2496,7 +2504,48 @@ type AgentWidgetArtifactsLayoutConfig = {
2496
2504
  jsonPayload: string;
2497
2505
  }) => void | Promise<void>;
2498
2506
  };
2499
- type PersonaArtifactDisplayMode = "card" | "panel" | "inline";
2507
+ /**
2508
+ * Where the artifact body renders by default. Every mode shows the compact
2509
+ * reference in the transcript; the mode names where the body goes:
2510
+ * nowhere yet (`collapsed`), the side panel (`panel`), or the conversation
2511
+ * itself (`inline`).
2512
+ */
2513
+ type PersonaArtifactDisplayMode = "collapsed" | "panel" | "inline";
2514
+ /**
2515
+ * Accepted wherever a display mode is written. `"card"` is a deprecated
2516
+ * alias of `"collapsed"` (the old name described the reference card, which
2517
+ * every mode shows, instead of where the body renders). Resolution and
2518
+ * parsing always canonicalize to `"collapsed"`.
2519
+ */
2520
+ type PersonaArtifactDisplayModeInput = PersonaArtifactDisplayMode | "card";
2521
+ /**
2522
+ * Display rules for file-backed artifacts. `byMediaType` keys are exact MIME
2523
+ * types (`"text/html"`) or major-type wildcards (`"image/*"`), matched
2524
+ * case-insensitively without parameters; exact beats wildcard.
2525
+ */
2526
+ type PersonaArtifactFilesDisplayRules = {
2527
+ default?: PersonaArtifactDisplayModeInput;
2528
+ byMediaType?: Record<string, PersonaArtifactDisplayModeInput>;
2529
+ };
2530
+ /**
2531
+ * Scoped artifact display rules. Matching resolves from the most specific
2532
+ * selector to `default`; see `resolveArtifactDisplay`.
2533
+ *
2534
+ * Across preference layers, one merge rule applies everywhere: a string value
2535
+ * replaces the whole subtree it names; an object refines it per key. So
2536
+ * `files: "inline"` overrides every lower-layer file rule, while
2537
+ * `files: { default: "inline" }` keeps lower-layer MIME exceptions.
2538
+ */
2539
+ type PersonaArtifactDisplayRules = {
2540
+ default?: PersonaArtifactDisplayModeInput;
2541
+ byKind?: Partial<Record<PersonaArtifactKind, PersonaArtifactDisplayModeInput>>;
2542
+ /**
2543
+ * @deprecated Use `byKind`. When both are present, `byKind` wins.
2544
+ */
2545
+ byType?: Partial<Record<PersonaArtifactKind, PersonaArtifactDisplayModeInput>>;
2546
+ /** Rules for any artifact carrying file metadata. */
2547
+ files?: PersonaArtifactDisplayModeInput | PersonaArtifactFilesDisplayRules;
2548
+ };
2500
2549
  /** 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
2550
  type PersonaArtifactActionContext = {
2502
2551
  artifactId: string | null;
@@ -2553,13 +2602,10 @@ type AgentWidgetArtifactsFeature = {
2553
2602
  allowedTypes?: PersonaArtifactKind[];
2554
2603
  /**
2555
2604
  * Where artifact bodies render. A single mode applies to all artifacts;
2556
- * the object form sets a default plus per-type overrides.
2605
+ * the object form sets a default plus scoped overrides.
2557
2606
  * Defaults to "panel" (current behavior).
2558
2607
  */
2559
- display?: PersonaArtifactDisplayMode | {
2560
- default?: PersonaArtifactDisplayMode;
2561
- byType?: Partial<Record<PersonaArtifactKind, PersonaArtifactDisplayMode>>;
2562
- };
2608
+ display?: PersonaArtifactDisplayModeInput | PersonaArtifactDisplayRules;
2563
2609
  /** Split / drawer dimensions and launcher widen behavior */
2564
2610
  layout?: AgentWidgetArtifactsLayoutConfig;
2565
2611
  /**
@@ -3288,6 +3334,41 @@ type AgentWidgetFeatureFlags = {
3288
3334
  */
3289
3335
  suggestReplies?: AgentWidgetSuggestRepliesFeature;
3290
3336
  };
3337
+ /**
3338
+ * Persistable artifact-layout choices. The full layout config deliberately is
3339
+ * not exposed because it also contains callbacks and embedder-owned chrome.
3340
+ */
3341
+ type WidgetArtifactLayoutPreference = Pick<AgentWidgetArtifactsLayoutConfig, "paneWidth" | "paneMaxWidth" | "paneMinWidth" | "expandLauncherPanelWhenOpen" | "expandedPanelWidth" | "resizable" | "resizableMinWidth" | "resizableMaxWidth">;
3342
+ /**
3343
+ * Curated, JSON-serializable display preferences in native `features` shape.
3344
+ *
3345
+ * Absence means inherit the next preference layer and ultimately Persona's
3346
+ * current default. Persist only explicit choices; resetting a choice deletes
3347
+ * its key.
3348
+ *
3349
+ * Capability facts (`artifacts.enabled`, `allowedTypes`), trusted iframe
3350
+ * security, callbacks, actions, renderers, labels, and theme styling are
3351
+ * intentionally excluded because they remain embedder/code-owned.
3352
+ */
3353
+ type WidgetPreferenceSlice = {
3354
+ showToolCalls?: boolean;
3355
+ showReasoning?: boolean;
3356
+ toolCallDisplay?: Pick<AgentWidgetToolCallDisplayFeature, "collapsedMode" | "expandable" | "grouped" | "groupedMode" | "loadingAnimation">;
3357
+ reasoningDisplay?: Pick<AgentWidgetReasoningDisplayFeature, "expandable" | "activePreview">;
3358
+ artifacts?: {
3359
+ /**
3360
+ * String and object forms are both persistable and mean different things
3361
+ * when layers merge: a string replaces every lower-layer display rule; an
3362
+ * object refines lower layers per selector key (same rule applies to
3363
+ * `display.files`).
3364
+ */
3365
+ display?: PersonaArtifactDisplayModeInput | PersonaArtifactDisplayRules;
3366
+ filePreview?: {
3367
+ enabled?: boolean;
3368
+ };
3369
+ layout?: WidgetArtifactLayoutPreference;
3370
+ };
3371
+ };
3291
3372
  /**
3292
3373
  * Feature config for the built-in `suggest_replies` quick-reply chips.
3293
3374
  * Chips render in the existing suggestions slot above the composer and are
@@ -5729,6 +5810,15 @@ type AgentWidgetConfig = {
5729
5810
  */
5730
5811
  colorScheme?: 'auto' | 'light' | 'dark';
5731
5812
  features?: AgentWidgetFeatureFlags;
5813
+ /**
5814
+ * Per-instance display overrides, applied over `features` through the
5815
+ * preference allowlist (security/capability keys cannot pass). String
5816
+ * `display` values replace the base rule subtree; objects refine it per
5817
+ * key. Each `controller.update({ preferences })` replaces the previous
5818
+ * slice wholesale (dropped keys revert to the base `features`); an
5819
+ * explicit-undefined patch clears it entirely.
5820
+ */
5821
+ preferences?: WidgetPreferenceSlice;
5732
5822
  /**
5733
5823
  * When true, focus the chat input after the panel opens and the open animation completes.
5734
5824
  * Applies to launcher mode (user click, controller.open(), autoExpand) and inline mode (on init).
@@ -6489,6 +6579,8 @@ type PersonaArtifactRecord = {
6489
6579
  props?: Record<string, unknown>;
6490
6580
  /** Present when this markdown artifact is a previewable file (see PersonaArtifactFileMeta). */
6491
6581
  file?: PersonaArtifactFileMeta;
6582
+ /** Optional presentation metadata such as the producer's display-mode hint. */
6583
+ presentation?: PersonaArtifactPresentation;
6492
6584
  };
6493
6585
 
6494
6586
  /** The resolved bundle gathered at submit, merged into the user message. */