@runtypelabs/persona 3.34.0 → 3.35.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 (186) hide show
  1. package/README.md +11 -11
  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-CthJFfNx.d.cts → types-DgYsuwXL.d.cts} +15 -14
  5. package/dist/animations/{types-CthJFfNx.d.ts → types-DgYsuwXL.d.ts} +15 -14
  6. package/dist/animations/wipe.d.cts +1 -1
  7. package/dist/animations/wipe.d.ts +1 -1
  8. package/dist/codegen.cjs +11 -11
  9. package/dist/codegen.js +10 -10
  10. package/dist/index.cjs +46 -44
  11. package/dist/index.cjs.map +1 -1
  12. package/dist/index.d.cts +514 -158
  13. package/dist/index.d.ts +514 -158
  14. package/dist/index.global.js +41 -89
  15. package/dist/index.global.js.map +1 -1
  16. package/dist/index.js +46 -44
  17. package/dist/index.js.map +1 -1
  18. package/dist/install.global.js +1 -1
  19. package/dist/install.global.js.map +1 -1
  20. package/dist/launcher.global.js +2 -2
  21. package/dist/launcher.global.js.map +1 -1
  22. package/dist/markdown-parsers.js +53 -0
  23. package/dist/plugin-kit.d.cts +4 -4
  24. package/dist/plugin-kit.d.ts +4 -4
  25. package/dist/runtype-tts.js +1 -0
  26. package/dist/smart-dom-reader.cjs +1 -1
  27. package/dist/smart-dom-reader.d.cts +352 -103
  28. package/dist/smart-dom-reader.d.ts +352 -103
  29. package/dist/smart-dom-reader.js +1 -1
  30. package/dist/theme-editor-preview.cjs +203 -0
  31. package/dist/theme-editor-preview.d.cts +5748 -0
  32. package/dist/theme-editor-preview.d.ts +5748 -0
  33. package/dist/theme-editor-preview.js +203 -0
  34. package/dist/theme-editor.cjs +14 -131
  35. package/dist/theme-editor.d.cts +362 -574
  36. package/dist/theme-editor.d.ts +362 -574
  37. package/dist/theme-editor.js +14 -131
  38. package/dist/theme-reference.cjs +1 -1
  39. package/dist/theme-reference.d.cts +1 -1
  40. package/dist/theme-reference.d.ts +1 -1
  41. package/dist/theme-reference.js +1 -1
  42. package/dist/voice-worklet-player.cjs +80 -0
  43. package/dist/voice-worklet-player.d.cts +215 -0
  44. package/dist/voice-worklet-player.d.ts +215 -0
  45. package/dist/voice-worklet-player.js +80 -0
  46. package/dist/widget.css +54 -36
  47. package/package.json +16 -2
  48. package/src/animations/glyph-cycle.ts +11 -14
  49. package/src/animations/wipe.ts +1 -1
  50. package/src/ask-user-question-tool.test.ts +1 -1
  51. package/src/ask-user-question-tool.ts +6 -8
  52. package/src/client.test.ts +67 -12
  53. package/src/client.ts +40 -32
  54. package/src/codegen.test.ts +1 -1
  55. package/src/codegen.ts +1 -1
  56. package/src/components/approval-bubble.test.ts +1 -1
  57. package/src/components/approval-bubble.ts +3 -3
  58. package/src/components/artifact-pane.ts +3 -3
  59. package/src/components/ask-user-question-bubble.test.ts +14 -14
  60. package/src/components/ask-user-question-bubble.ts +10 -10
  61. package/src/components/composer-builder.ts +17 -16
  62. package/src/components/composer-parts.test.ts +54 -0
  63. package/src/components/composer-parts.ts +95 -126
  64. package/src/components/demo-carousel.ts +1 -1
  65. package/src/components/event-stream-view.test.ts +7 -7
  66. package/src/components/event-stream-view.ts +5 -5
  67. package/src/components/header-builder.ts +33 -27
  68. package/src/components/header-layouts.ts +1 -1
  69. package/src/components/header-parts.test.ts +90 -0
  70. package/src/components/header-parts.ts +62 -93
  71. package/src/components/launcher.test.ts +11 -0
  72. package/src/components/launcher.ts +1 -1
  73. package/src/components/message-bubble.test.ts +74 -2
  74. package/src/components/message-bubble.ts +25 -11
  75. package/src/components/messages.ts +2 -2
  76. package/src/components/panel.test.ts +1 -1
  77. package/src/components/panel.ts +92 -97
  78. package/src/components/pill-composer-builder.ts +28 -24
  79. package/src/components/reasoning-bubble.ts +2 -2
  80. package/src/components/suggestions.ts +1 -1
  81. package/src/components/tool-bubble.ts +1 -1
  82. package/src/components/widget-view.test.ts +181 -0
  83. package/src/components/widget-view.ts +234 -0
  84. package/src/defaults.ts +54 -51
  85. package/src/generated/runtype-openapi-contract.ts +5 -0
  86. package/src/index-core.ts +30 -4
  87. package/src/index-global.ts +73 -6
  88. package/src/index.ts +7 -1
  89. package/src/install.test.ts +11 -11
  90. package/src/install.ts +28 -18
  91. package/src/launcher-global.ts +25 -14
  92. package/src/markdown-parsers-eager.ts +20 -0
  93. package/src/markdown-parsers-entry.ts +4 -0
  94. package/src/markdown-parsers-loader.ts +49 -0
  95. package/src/plugin-kit.test.ts +1 -1
  96. package/src/plugin-kit.ts +7 -7
  97. package/src/plugins/types.ts +5 -5
  98. package/src/postprocessors.ts +27 -14
  99. package/src/runtime/host-layout.test.ts +1 -1
  100. package/src/runtime/host-layout.ts +4 -5
  101. package/src/runtime/init.ts +2 -2
  102. package/src/session.test.ts +5 -6
  103. package/src/session.ts +333 -227
  104. package/src/session.voice.test.ts +146 -0
  105. package/src/session.webmcp.test.ts +24 -25
  106. package/src/smart-dom-reader.ts +3 -4
  107. package/src/styles/widget.css +54 -36
  108. package/src/suggest-replies-tool.test.ts +3 -3
  109. package/src/suggest-replies-tool.ts +5 -5
  110. package/src/testing/index.ts +1 -1
  111. package/src/theme-editor/color-utils.ts +2 -2
  112. package/src/theme-editor/index.ts +4 -13
  113. package/src/theme-editor/presets.ts +1 -1
  114. package/src/theme-editor/preview-utils.ts +22 -20
  115. package/src/theme-editor/preview.ts +4 -1
  116. package/src/theme-editor/role-mappings.ts +3 -3
  117. package/src/theme-editor/sections.ts +21 -20
  118. package/src/theme-editor/types.ts +1 -1
  119. package/src/theme-editor/webmcp/index.ts +1 -1
  120. package/src/theme-editor/webmcp/summary.ts +1 -2
  121. package/src/theme-editor/webmcp/tools.ts +30 -30
  122. package/src/theme-editor/webmcp/types.ts +2 -2
  123. package/src/theme-editor-preview.ts +10 -0
  124. package/src/theme-reference.ts +26 -26
  125. package/src/types.ts +368 -99
  126. package/src/ui.approval-plugin.test.ts +3 -3
  127. package/src/ui.ask-user-question-plugin.test.ts +9 -9
  128. package/src/ui.component-directive.test.ts +4 -4
  129. package/src/ui.composer-bar.test.ts +10 -11
  130. package/src/ui.composer-keyboard.test.ts +5 -5
  131. package/src/ui.header-icon-color.test.ts +59 -0
  132. package/src/ui.scroll.test.ts +5 -6
  133. package/src/ui.stop-button.test.ts +3 -4
  134. package/src/ui.suggest-replies.test.ts +2 -2
  135. package/src/ui.ts +292 -131
  136. package/src/utils/buttons.ts +1 -1
  137. package/src/utils/code-generators.ts +1 -1
  138. package/src/utils/composer-history.ts +3 -3
  139. package/src/utils/dom-context.test.ts +2 -2
  140. package/src/utils/dom-context.ts +7 -7
  141. package/src/utils/dom.test.ts +67 -0
  142. package/src/utils/dom.ts +75 -0
  143. package/src/utils/dropdown.ts +2 -2
  144. package/src/utils/event-stream-buffer.test.ts +2 -2
  145. package/src/utils/message-fingerprint.test.ts +9 -0
  146. package/src/utils/message-fingerprint.ts +5 -0
  147. package/src/utils/morph.ts +1 -1
  148. package/src/utils/sanitize.ts +32 -16
  149. package/src/utils/sequence-buffer.test.ts +8 -8
  150. package/src/utils/sequence-buffer.ts +4 -4
  151. package/src/utils/smart-dom-adapter.test.ts +1 -1
  152. package/src/utils/smart-dom-adapter.ts +4 -5
  153. package/src/utils/speech-text.test.ts +122 -0
  154. package/src/utils/speech-text.ts +101 -0
  155. package/src/utils/stream-animation.test.ts +3 -3
  156. package/src/utils/stream-animation.ts +6 -6
  157. package/src/utils/theme.test.ts +1 -1
  158. package/src/utils/throughput-tracker.test.ts +11 -11
  159. package/src/utils/throughput-tracker.ts +9 -9
  160. package/src/utils/tokens.ts +13 -13
  161. package/src/utils/virtual-scroller.ts +1 -1
  162. package/src/vendor/smart-dom-reader/README.md +4 -4
  163. package/src/vendor/smart-dom-reader/index.d.ts +1 -1
  164. package/src/vendor/smart-dom-reader/index.js +2 -2
  165. package/src/version.ts +1 -1
  166. package/src/voice/audio-playback-manager.test.ts +159 -0
  167. package/src/voice/audio-playback-manager.ts +145 -30
  168. package/src/voice/browser-speech-engine.ts +130 -0
  169. package/src/voice/fallback-speech-engine.ts +89 -0
  170. package/src/voice/index.ts +21 -0
  171. package/src/voice/read-aloud-controller.test.ts +143 -0
  172. package/src/voice/read-aloud-controller.ts +136 -0
  173. package/src/voice/runtype-speech-engine.test.ts +280 -0
  174. package/src/voice/runtype-speech-engine.ts +211 -0
  175. package/src/voice/runtype-tts-entry.ts +10 -0
  176. package/src/voice/runtype-tts-loader.test.ts +47 -0
  177. package/src/voice/runtype-tts-loader.ts +42 -0
  178. package/src/voice/runtype-voice-provider.ts +332 -537
  179. package/src/voice/voice-factory.ts +26 -4
  180. package/src/voice/voice.test.ts +321 -7
  181. package/src/voice/worklet-playback-engine.ts +272 -0
  182. package/src/voice-worklet-player.ts +39 -0
  183. package/src/webmcp-bridge.test.ts +6 -6
  184. package/src/webmcp-bridge.ts +24 -25
  185. package/src/webmcp-polyfill.ts +1 -1
  186. package/src/voice/voice-activity-detector.ts +0 -90
@@ -1,4 +1,4 @@
1
- /** Declarative section/field definitions for the theme editor (pure data no DOM, no render logic) */
1
+ /** Declarative section/field definitions for the theme editor (pure data: no DOM, no render logic) */
2
2
 
3
3
  import type { SectionDef, TabDef, SubGroupDef, FieldDef } from './types';
4
4
  import {
@@ -19,7 +19,7 @@ import {
19
19
  } from './role-mappings';
20
20
 
21
21
  // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
22
- // STYLE TAB brand colors, chat colors, typography, shape, etc.
22
+ // STYLE TAB: brand colors, chat colors, typography, shape, etc.
23
23
  // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
24
24
 
25
25
  const themeModeSectionDef: SectionDef = {
@@ -209,7 +209,7 @@ export const STYLE_SECTIONS: SectionDef[] = [
209
209
  ];
210
210
 
211
211
  // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
212
- // COLORS & STYLE TAB palette scales, semantic tokens
212
+ // COLORS & STYLE TAB: palette scales, semantic tokens
213
213
  // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
214
214
 
215
215
  function buildPaletteSectionDef(): SectionDef {
@@ -269,7 +269,7 @@ export const COLORS_SECTIONS: SectionDef[] = [
269
269
  ];
270
270
 
271
271
  // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
272
- // DESIGN SYSTEM TAB component shapes, colors, layout
272
+ // DESIGN SYSTEM TAB: component shapes, colors, layout
273
273
  // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
274
274
 
275
275
  const panelLayoutSectionDef: SectionDef = {
@@ -510,7 +510,7 @@ export const COMPONENTS_SECTIONS: SectionDef[] = [
510
510
  ];
511
511
 
512
512
  // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
513
- // CONFIGURE TAB content, layout, widget, features, developer
513
+ // CONFIGURE TAB: content, layout, widget, features, developer
514
514
  // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
515
515
 
516
516
  const MB = 1024 * 1024;
@@ -613,6 +613,7 @@ const messageActionsSectionDef: SectionDef = {
613
613
  { id: 'msg-actions-copy', label: 'Show Copy', type: 'toggle', path: 'messageActions.showCopy', defaultValue: true },
614
614
  { id: 'msg-actions-upvote', label: 'Show Upvote', type: 'toggle', path: 'messageActions.showUpvote', defaultValue: true },
615
615
  { id: 'msg-actions-downvote', label: 'Show Downvote', type: 'toggle', path: 'messageActions.showDownvote', defaultValue: true },
616
+ { id: 'msg-actions-read-aloud', label: 'Show Read Aloud', type: 'toggle', path: 'messageActions.showReadAloud', defaultValue: false },
616
617
  { id: 'msg-actions-visibility', label: 'Visibility', type: 'select', path: 'messageActions.visibility', defaultValue: 'hover', options: [{ value: 'hover', label: 'On Hover' }, { value: 'always', label: 'Always Visible' }] },
617
618
  { id: 'msg-actions-align', label: 'Alignment', type: 'select', path: 'messageActions.align', defaultValue: 'right', options: [{ value: 'left', label: 'Left' }, { value: 'right', label: 'Right' }] },
618
619
  { id: 'msg-actions-layout', label: 'Layout', type: 'select', path: 'messageActions.layout', defaultValue: 'pill-inside', options: [{ value: 'pill-inside', label: 'Pill' }, { value: 'row-inside', label: 'Row' }] },
@@ -768,9 +769,9 @@ const streamAnimationSectionDef: SectionDef = {
768
769
  path: 'features.streamAnimation.buffer',
769
770
  defaultValue: 'none',
770
771
  options: [
771
- { value: 'none', label: 'None stream every character' },
772
- { value: 'word', label: 'Word hold until whitespace' },
773
- { value: 'line', label: 'Line hold until newline' },
772
+ { value: 'none', label: 'None: stream every character' },
773
+ { value: 'word', label: 'Word: hold until whitespace' },
774
+ { value: 'line', label: 'Line: hold until newline' },
774
775
  ],
775
776
  },
776
777
  {
@@ -781,12 +782,12 @@ const streamAnimationSectionDef: SectionDef = {
781
782
  path: 'features.streamAnimation.speed',
782
783
  defaultValue: 120,
783
784
  options: [
784
- { value: '40', label: '40ms snappy' },
785
+ { value: '40', label: '40ms: snappy' },
785
786
  { value: '80', label: '80ms' },
786
787
  { value: '120', label: '120ms (default)' },
787
788
  { value: '200', label: '200ms' },
788
789
  { value: '320', label: '320ms' },
789
- { value: '480', label: '480ms slow' },
790
+ { value: '480', label: '480ms: slow' },
790
791
  ],
791
792
  formatValue: (v: unknown) => String(v ?? 120),
792
793
  parseValue: (v: unknown) => Number(v),
@@ -803,7 +804,7 @@ const streamAnimationSectionDef: SectionDef = {
803
804
  { value: '1200', label: '1200ms' },
804
805
  { value: '1800', label: '1800ms (default)' },
805
806
  { value: '2400', label: '2400ms' },
806
- { value: '3600', label: '3600ms slow' },
807
+ { value: '3600', label: '3600ms: slow' },
807
808
  ],
808
809
  formatValue: (v: unknown) => String(v ?? 1800),
809
810
  parseValue: (v: unknown) => Number(v),
@@ -894,10 +895,10 @@ export const CONFIGURE_SUB_GROUPS: SubGroupDef[] = [
894
895
  export const CONFIGURE_SECTIONS: SectionDef[] = CONFIGURE_SUB_GROUPS.flatMap(g => g.sections);
895
896
 
896
897
  // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
897
- // STYLE TAB V2 outcome-oriented editor structure
898
+ // STYLE TAB V2: outcome-oriented editor structure
898
899
  // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
899
900
 
900
- /** Section 1: Theme color mode selection */
901
+ /** Section 1: Theme: color mode selection */
901
902
  export const THEME_SECTION: SectionDef = {
902
903
  id: 'theme-mode-v2',
903
904
  title: 'Theme',
@@ -919,7 +920,7 @@ export const THEME_SECTION: SectionDef = {
919
920
  ],
920
921
  };
921
922
 
922
- /** Section 2: Brand Palette primary colors + collapsed status colors */
923
+ /** Section 2: Brand Palette: primary colors + collapsed status colors */
923
924
  export const BRAND_PALETTE_SECTION: SectionDef = {
924
925
  id: 'brand-palette-v2',
925
926
  title: 'Brand Palette',
@@ -933,7 +934,7 @@ export const BRAND_PALETTE_SECTION: SectionDef = {
933
934
  ],
934
935
  };
935
936
 
936
- /** Section 2b: Status palette collapsed under Brand Palette */
937
+ /** Section 2b: Status palette: collapsed under Brand Palette */
937
938
  export const STATUS_PALETTE_SECTION: SectionDef = {
938
939
  id: 'status-palette',
939
940
  title: 'Status Palette',
@@ -947,7 +948,7 @@ export const STATUS_PALETTE_SECTION: SectionDef = {
947
948
  ],
948
949
  };
949
950
 
950
- /** Section 3: Interface Roles the main theming surface */
951
+ /** Section 3: Interface Roles: the main theming surface */
951
952
  export const INTERFACE_ROLES_SECTION: SectionDef = {
952
953
  id: 'interface-roles',
953
954
  title: 'Interface Roles',
@@ -1020,7 +1021,7 @@ export const INTERFACE_ROLES_SECTION: SectionDef = {
1020
1021
  ],
1021
1022
  };
1022
1023
 
1023
- /** Section 4: Status Colors feedback semantic tokens */
1024
+ /** Section 4: Status Colors: feedback semantic tokens */
1024
1025
  export const STATUS_COLORS_SECTION: SectionDef = {
1025
1026
  id: 'status-colors',
1026
1027
  title: 'Status Colors',
@@ -1034,7 +1035,7 @@ export const STATUS_COLORS_SECTION: SectionDef = {
1034
1035
  ],
1035
1036
  };
1036
1037
 
1037
- /** Section 5: Advanced Tokens entry point for drill-downs (no fields) */
1038
+ /** Section 5: Advanced Tokens: entry point for drill-downs (no fields) */
1038
1039
  export const ADVANCED_TOKENS_SECTION: SectionDef = {
1039
1040
  id: 'advanced-tokens',
1040
1041
  title: 'Advanced Tokens',
@@ -1043,7 +1044,7 @@ export const ADVANCED_TOKENS_SECTION: SectionDef = {
1043
1044
  fields: [],
1044
1045
  };
1045
1046
 
1046
- /** V2 Style tab sections outcome-oriented editor */
1047
+ /** V2 Style tab sections: outcome-oriented editor */
1047
1048
  export const STYLE_SECTIONS_V2: SectionDef[] = [
1048
1049
  THEME_SECTION,
1049
1050
  BRAND_PALETTE_SECTION,
@@ -1064,7 +1065,7 @@ export const ALL_TABS: TabDef[] = [
1064
1065
  ];
1065
1066
 
1066
1067
  // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
1067
- // HELPERS light/dark scoping for dual-mode editing
1068
+ // HELPERS: light/dark scoping for dual-mode editing
1068
1069
  // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
1069
1070
 
1070
1071
  type ThemeScope = 'theme' | 'darkTheme';
@@ -1,4 +1,4 @@
1
- /** Field definition types for the declarative configurator system (headless no DOM) */
1
+ /** Field definition types for the declarative configurator system (headless: no DOM) */
2
2
 
3
3
  import type { DeepPartial, PersonaTheme } from '../types/theme';
4
4
  import type { AgentWidgetConfig } from '../types';
@@ -4,7 +4,7 @@
4
4
  * Transport-agnostic: `createThemeEditorTools(state)` returns plain tool
5
5
  * definitions. Host code (e.g. an example app or a self-styling widget) is
6
6
  * responsible for obtaining a `document.modelContext` and calling
7
- * `registerTool` for each this module has no polyfill dependency.
7
+ * `registerTool` for each: this module has no polyfill dependency.
8
8
  */
9
9
 
10
10
  export { createThemeEditorTools } from './tools';
@@ -49,8 +49,7 @@ const RADIUS_KEYS = ['sm', 'md', 'lg', 'xl', 'full'] as const;
49
49
  /**
50
50
  * Resolve a theme token path to a concrete color, following `palette.*`,
51
51
  * `semantic.*`, and `components.*` references. When resolving the `darkTheme`
52
- * variant, tokens the dark theme doesn't define fall back to the light theme
53
- * mirroring the widget's runtime merge behavior.
52
+ * variant, tokens the dark theme doesn't define fall back to the light theme: * mirroring the widget's runtime merge behavior.
54
53
  */
55
54
  export function resolveColor(
56
55
  state: ThemeEditorLike,
@@ -4,8 +4,8 @@
4
4
  * `createThemeEditorTools(state)` returns transport-agnostic tool definitions
5
5
  * designed for Agent Experience: intent-level operations (set brand colors,
6
6
  * assign a color role, set roundness…) rather than a 1:1 mapping of the ~150
7
- * editor fields. Two altitudes high-level semantic tools plus a low-level
8
- * escape hatch (`set_theme_fields`) keep the catalog small without losing
7
+ * editor fields. Two altitudes: high-level semantic tools plus a low-level
8
+ * escape hatch (`set_theme_fields`): keep the catalog small without losing
9
9
  * coverage. Every mutation returns a compact summary + contrast warnings.
10
10
  */
11
11
 
@@ -176,7 +176,7 @@ export function createThemeEditorTools(
176
176
  name: 'get_theme_overview',
177
177
  title: 'Get current theme & what is editable',
178
178
  description:
179
- 'Read the current widget theme (brand colors, per-role color assignments, typography, roundness, color scheme, undo/redo state), the available presets, and the high-level levers you can change. Call this FIRST before editing.',
179
+ 'Read theme summary, presets, and editable levers. Call before editing.',
180
180
  annotations: { readOnlyHint: true },
181
181
  inputSchema: {
182
182
  type: 'object',
@@ -184,7 +184,7 @@ export function createThemeEditorTools(
184
184
  verbosity: {
185
185
  type: 'string',
186
186
  enum: ['summary', 'full'],
187
- description: "Use 'full' to also include the field-id index for set_theme_fields.",
187
+ description: "'full' includes the field-id index.",
188
188
  },
189
189
  },
190
190
  additionalProperties: false,
@@ -205,16 +205,16 @@ export function createThemeEditorTools(
205
205
  tags: p.tags ?? [],
206
206
  })),
207
207
  tools: [
208
- { tool: 'set_brand_colors', hint: 'Recolor the palette (primary/secondary/accent) auto-generates shade scales.' },
209
- { tool: 'assign_color_role', hint: 'Recolor a region (header, user/assistant messages, actions, input, links, borders, surfaces, scroll) with a family + intensity.' },
208
+ { tool: 'set_brand_colors', hint: 'Recolor primary/secondary/accent and generate shade scales.' },
209
+ { tool: 'assign_color_role', hint: 'Recolor a widget region with family + intensity.' },
210
210
  { tool: 'set_typography', hint: 'Set font family, size, weight, line height.' },
211
- { tool: 'set_roundness', hint: 'Set corner roundness (sharp/default/rounded/pill) or granular radii.' },
212
- { tool: 'set_color_scheme', hint: 'Set light/dark/auto and which variant edits target.' },
213
- { tool: 'apply_preset', hint: 'Apply a complete built-in preset.' },
211
+ { tool: 'set_roundness', hint: 'Set corner roundness or granular radii.' },
212
+ { tool: 'set_color_scheme', hint: 'Set light/dark/auto and edit target.' },
213
+ { tool: 'apply_preset', hint: 'Apply a built-in preset.' },
214
214
  { tool: 'configure_widget', hint: 'Toggle launcher position, features, and layout.' },
215
215
  { tool: 'set_copy_and_suggestions', hint: 'Set welcome copy, placeholder, and suggestion chips.' },
216
- { tool: 'set_theme_fields', hint: 'Advanced escape hatch: set any field by id or dot-path.' },
217
- { tool: 'check_contrast', hint: 'Audit WCAG contrast across key text/background pairs.' },
216
+ { tool: 'set_theme_fields', hint: 'Set any field by id or dot-path.' },
217
+ { tool: 'check_contrast', hint: 'Audit WCAG contrast.' },
218
218
  { tool: 'manage_session', hint: 'Undo, redo, reset, or export the theme.' },
219
219
  ],
220
220
  };
@@ -236,13 +236,13 @@ export function createThemeEditorTools(
236
236
  name: 'set_brand_colors',
237
237
  title: 'Set brand colors',
238
238
  description:
239
- 'Set one or more brand colors (primary, secondary, accent). Each color auto-generates a full 50–950 shade scale and applies to the light and dark themes (per the current edit target). Accepts hex ("#2563eb", "2563eb", "#18f"), rgb()/rgba() ("rgb(37, 99, 235)"), or CSS color names ("blue", "slateblue").',
239
+ 'Set primary, secondary, and/or accent colors. Generates shade scales and accepts hex, rgb/rgba, or CSS names.',
240
240
  inputSchema: {
241
241
  type: 'object',
242
242
  properties: {
243
- primary: { type: 'string', description: 'Hex, rgb()/rgba(), or CSS color name.' },
244
- secondary: { type: 'string', description: 'Hex, rgb()/rgba(), or CSS color name.' },
245
- accent: { type: 'string', description: 'Hex, rgb()/rgba(), or CSS color name.' },
243
+ primary: { type: 'string', description: 'Hex, rgb/rgba, or CSS name.' },
244
+ secondary: { type: 'string', description: 'Hex, rgb/rgba, or CSS name.' },
245
+ accent: { type: 'string', description: 'Hex, rgb/rgba, or CSS name.' },
246
246
  },
247
247
  additionalProperties: false,
248
248
  },
@@ -282,13 +282,13 @@ export function createThemeEditorTools(
282
282
  name: 'assign_color_role',
283
283
  title: 'Assign a color family to an interface role',
284
284
  description:
285
- 'Recolor a semantic region of the widget by choosing a palette family and intensity. One call writes all related tokens (background, text, border, icon) consistently. Roles: header, user-messages, assistant-messages, primary-actions, input, links, borders, surfaces, scroll-to-bottom. Families: primary, secondary, accent, neutral. Intensity: solid (bold) or soft (tinted).',
285
+ 'Recolor a widget region by role, palette family, and intensity.',
286
286
  inputSchema: {
287
287
  type: 'object',
288
288
  properties: {
289
- role: { type: 'string', description: 'Interface role, e.g. "header" or "user-messages".' },
289
+ role: { type: 'string', description: 'Role, e.g. header or user-messages.' },
290
290
  family: { type: 'string', enum: ROLE_FAMILY_NAMES },
291
- intensity: { type: 'string', enum: ['solid', 'soft'], description: "Defaults to 'solid'." },
291
+ intensity: { type: 'string', enum: ['solid', 'soft'], description: 'Default: solid.' },
292
292
  },
293
293
  required: ['role', 'family'],
294
294
  additionalProperties: false,
@@ -315,7 +315,7 @@ export function createThemeEditorTools(
315
315
  name: 'set_typography',
316
316
  title: 'Set typography',
317
317
  description:
318
- 'Set font family, base size, weight, and line height in one call. fontFamily: sans|serif|mono. fontSize: xs|sm|base|lg|xl. fontWeight: normal|medium|semibold|bold (or 400–700). lineHeight: tight|normal|relaxed (or 1.25/1.5/1.625).',
318
+ 'Set font family, size, weight, and line height.',
319
319
  inputSchema: {
320
320
  type: 'object',
321
321
  properties: {
@@ -358,14 +358,14 @@ export function createThemeEditorTools(
358
358
  name: 'set_roundness',
359
359
  title: 'Set corner roundness',
360
360
  description:
361
- 'Set overall corner roundness with a keyword (sharp, default, rounded, pill) which maps the full radius scale, OR pass granular radius values. Provide at least one of `style` or `radius`.',
361
+ 'Set roundness by style or granular radius values.',
362
362
  inputSchema: {
363
363
  type: 'object',
364
364
  properties: {
365
365
  style: { type: 'string', enum: ['sharp', 'default', 'rounded', 'pill'] },
366
366
  radius: {
367
367
  type: 'object',
368
- description: 'Granular overrides (px number or CSS length).',
368
+ description: 'Granular px or CSS length overrides.',
369
369
  properties: {
370
370
  sm: { type: ['string', 'number'] },
371
371
  md: { type: ['string', 'number'] },
@@ -415,7 +415,7 @@ export function createThemeEditorTools(
415
415
  name: 'set_color_scheme',
416
416
  title: 'Set color scheme',
417
417
  description:
418
- 'Set the shipped widget color scheme (light, dark, or auto/follow-system). Optionally set `editTarget` to choose which theme variant subsequent styling edits write to (light, dark, or both — default both).',
418
+ 'Set light/dark/auto color scheme and optional edit target.',
419
419
  inputSchema: {
420
420
  type: 'object',
421
421
  properties: {
@@ -481,7 +481,7 @@ export function createThemeEditorTools(
481
481
  name: 'configure_widget',
482
482
  title: 'Configure launcher, features, and layout',
483
483
  description:
484
- 'Toggle non-theme widget configuration. launcherPosition: bottom-right|bottom-left|top-right|top-left. features: { voice, artifacts, attachments, toolCalls, reasoning, feedback } booleans. layout: { avatars, timestamps, showHeader } booleans and messageStyle: bubble|flat|minimal.',
484
+ 'Toggle launcher position, feature flags, and message layout.',
485
485
  inputSchema: {
486
486
  type: 'object',
487
487
  properties: {
@@ -563,7 +563,7 @@ export function createThemeEditorTools(
563
563
  name: 'set_copy_and_suggestions',
564
564
  title: 'Set welcome copy and suggestion chips',
565
565
  description:
566
- 'Set the widget welcome copy and suggestion chips. title/subtitle are the welcome card text; placeholder is the input placeholder; sendLabel is the send button label; suggestions is an array of suggestion-chip strings (replaces the existing list).',
566
+ 'Set welcome copy, input placeholder, send label, and suggestion chips.',
567
567
  inputSchema: {
568
568
  type: 'object',
569
569
  properties: {
@@ -607,7 +607,7 @@ export function createThemeEditorTools(
607
607
  name: 'set_theme_fields',
608
608
  title: 'Set theme fields by id or path (advanced)',
609
609
  description:
610
- 'Advanced escape hatch: set individual editor fields by field id (see get_theme_overview verbosity:"full") — theme field ids follow the current edit target (light/dark/both) — or by raw dot-path (theme.* / darkTheme.* / a config path), which is written as-is. Use only when a higher-level tool does not cover the need. Values are validated against the field metadata.',
610
+ 'Advanced escape hatch: set fields by id or raw dot-path. Values are validated when metadata exists.',
611
611
  inputSchema: {
612
612
  type: 'object',
613
613
  properties: {
@@ -616,7 +616,7 @@ export function createThemeEditorTools(
616
616
  items: {
617
617
  type: 'object',
618
618
  properties: {
619
- field: { type: 'string', description: 'Field id or dot-path.' },
619
+ field: { type: 'string', description: 'Field id or path.' },
620
620
  value: { type: ['string', 'number', 'boolean'] },
621
621
  },
622
622
  required: ['field', 'value'],
@@ -686,13 +686,13 @@ export function createThemeEditorTools(
686
686
  name: 'check_contrast',
687
687
  title: 'Check accessibility contrast',
688
688
  description:
689
- 'Run WCAG contrast checks over the key text/background pairs (message text, header title, input/body text, primary button). Returns each ratio, whether it passes, and a suggested foreground shade for failures.',
689
+ 'Run WCAG checks over key text/background pairs.',
690
690
  annotations: { readOnlyHint: true },
691
691
  inputSchema: {
692
692
  type: 'object',
693
693
  properties: {
694
- level: { type: 'string', enum: ['AA', 'AAA'], description: "Defaults to 'AA'." },
695
- variant: { type: 'string', enum: ['light', 'dark', 'both'], description: "Defaults to 'both'." },
694
+ level: { type: 'string', enum: ['AA', 'AAA'], description: 'Default: AA.' },
695
+ variant: { type: 'string', enum: ['light', 'dark', 'both'], description: 'Default: both.' },
696
696
  },
697
697
  additionalProperties: false,
698
698
  },
@@ -716,7 +716,7 @@ export function createThemeEditorTools(
716
716
  name: 'manage_session',
717
717
  title: 'Undo, redo, reset, or export the theme',
718
718
  description:
719
- 'Session action. "undo"/"redo" step through edit history; "reset" restores defaults; "export" returns the embeddable theme snapshot (config + theme JSON) with no side effects.',
719
+ 'Undo, redo, reset defaults, or export the theme snapshot.',
720
720
  inputSchema: {
721
721
  type: 'object',
722
722
  properties: { action: { type: 'string', enum: ['undo', 'redo', 'reset', 'export'] } },
@@ -56,7 +56,7 @@ export interface WebMcpTool {
56
56
 
57
57
  /**
58
58
  * Wrap a JSON-serializable payload in the MCP tool-result envelope. Compact
59
- * JSON (no indentation) the text is consumed by a model, where pretty-print
59
+ * JSON (no indentation): the text is consumed by a model, where pretty-print
60
60
  * whitespace is pure token overhead.
61
61
  */
62
62
  export function toolResult(payload: unknown): ToolResult {
@@ -71,7 +71,7 @@ export function toolResult(payload: unknown): ToolResult {
71
71
  /**
72
72
  * Structural subset of `ThemeEditorState` (and the example app's `state`
73
73
  * module) that the tools require. Anything satisfying this shape can be wired
74
- * to the tools the headless `ThemeEditorState`, or a host's stateful wrapper
74
+ * to the tools: the headless `ThemeEditorState`, or a host's stateful wrapper
75
75
  * that also drives a live preview (e.g. a Persona widget styling itself).
76
76
  */
77
77
  export interface ThemeEditorLike {
@@ -0,0 +1,10 @@
1
+ /** Entry point for @runtypelabs/persona/theme-editor/preview */
2
+ export { createThemePreview } from './theme-editor/preview';
3
+ export type {
4
+ ThemePreviewOptions,
5
+ ThemePreviewHandle,
6
+ PreviewLifecycleContext,
7
+ PreviewDevice,
8
+ PreviewShellMode,
9
+ CompareMode,
10
+ } from './theme-editor/preview';
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Theme Reference Structured documentation and examples for the Persona v2 theme system.
2
+ * Theme Reference: Structured documentation and examples for the Persona v2 theme system.
3
3
  *
4
4
  * Exported via the `@runtypelabs/persona/theme-reference` entry point so it stays
5
5
  * out of the IIFE widget bundle. Intended for AI/MCP tool consumption.
@@ -14,7 +14,7 @@ import type { DeepPartial, PersonaTheme } from './types/theme'
14
14
 
15
15
  export const THEME_TOKEN_DOCS = {
16
16
  overview:
17
- 'Persona uses a three-layer design token system: palette → semantic → components. Most themes only need palette.colors overrides semantic and component layers auto-derive from palette values. Config also accepts non-theme appearance options (launcher, sendButton, toolCall, etc.).',
17
+ 'Persona uses a three-layer design token system: palette → semantic → components. Most themes only need palette.colors overrides: semantic and component layers auto-derive from palette values. Config also accepts non-theme appearance options (launcher, sendButton, toolCall, etc.).',
18
18
 
19
19
  layers: {
20
20
  palette: {
@@ -24,9 +24,9 @@ export const THEME_TOKEN_DOCS = {
24
24
  description:
25
25
  '7 color scales, each with shades 50 (lightest) to 950 (darkest). Override only the shades you need.',
26
26
  scales: {
27
- gray: 'Neutrals backgrounds, text, borders. Key shades: 50 (lightest bg), 100 (secondary bg), 200 (borders), 500 (muted text), 900 (primary text).',
27
+ gray: 'Neutrals: backgrounds, text, borders. Key shades: 50 (lightest bg), 100 (secondary bg), 200 (borders), 500 (muted text), 900 (primary text).',
28
28
  primary:
29
- 'Brand color buttons, links, interactive elements. Key shades: 500 (default), 600 (hover).',
29
+ 'Brand color: buttons, links, interactive elements. Key shades: 500 (default), 600 (hover).',
30
30
  accent: 'Secondary highlight. Key shades: 500 (default), 600 (hover).',
31
31
  secondary: 'Tertiary color scale.',
32
32
  success: 'Positive feedback (default: green).',
@@ -65,17 +65,17 @@ export const THEME_TOKEN_DOCS = {
65
65
  description:
66
66
  'Design intent tokens. Auto-derived from palette by default. Override to redirect token resolution. Values are token reference strings like "palette.colors.primary.500".',
67
67
  colors: {
68
- primary: 'palette.colors.primary.500 Primary brand color.',
69
- secondary: 'palette.colors.gray.500 Secondary color.',
70
- accent: 'palette.colors.primary.600 Accent/interactive color.',
71
- surface: 'palette.colors.gray.50 Panel/card backgrounds.',
72
- background: 'palette.colors.gray.50 Page background.',
73
- container: 'palette.colors.gray.100 Container backgrounds.',
74
- text: 'palette.colors.gray.900 Primary text.',
75
- textMuted: 'palette.colors.gray.500 Muted/secondary text.',
76
- textInverse: 'palette.colors.gray.50 Text on dark backgrounds.',
77
- border: 'palette.colors.gray.200 Default border color.',
78
- divider: 'palette.colors.gray.200 Divider lines.',
68
+ primary: 'palette.colors.primary.500: Primary brand color.',
69
+ secondary: 'palette.colors.gray.500: Secondary color.',
70
+ accent: 'palette.colors.primary.600: Accent/interactive color.',
71
+ surface: 'palette.colors.gray.50: Panel/card backgrounds.',
72
+ background: 'palette.colors.gray.50: Page background.',
73
+ container: 'palette.colors.gray.100: Container backgrounds.',
74
+ text: 'palette.colors.gray.900: Primary text.',
75
+ textMuted: 'palette.colors.gray.500: Muted/secondary text.',
76
+ textInverse: 'palette.colors.gray.50: Text on dark backgrounds.',
77
+ border: 'palette.colors.gray.200: Default border color.',
78
+ divider: 'palette.colors.gray.200: Divider lines.',
79
79
  interactive: {
80
80
  default: 'palette.colors.primary.500',
81
81
  hover: 'palette.colors.primary.600',
@@ -93,7 +93,7 @@ export const THEME_TOKEN_DOCS = {
93
93
  spacing:
94
94
  'xs (0.25rem), sm (0.5rem), md (1rem), lg (1.5rem), xl (2rem), 2xl (2.5rem).',
95
95
  typography:
96
- 'fontFamily, fontSize, fontWeight, lineHeight reference palette typography tokens.',
96
+ 'fontFamily, fontSize, fontWeight, lineHeight: reference palette typography tokens.',
97
97
  },
98
98
 
99
99
  components: {
@@ -140,16 +140,16 @@ export const THEME_TOKEN_DOCS = {
140
140
  attachment: 'image (background, border).',
141
141
  scrollToBottom:
142
142
  'Floating scroll-to-bottom affordance shared by transcript and event stream: background, foreground, border, size, borderRadius, shadow, padding, gap, fontSize, iconSize.',
143
- toolBubble: 'shadow tool call row box-shadow.',
144
- reasoningBubble: 'shadow reasoning/thinking row box-shadow.',
145
- composer: 'shadow message input form box-shadow.',
143
+ toolBubble: 'shadow: tool call row box-shadow.',
144
+ reasoningBubble: 'shadow: reasoning/thinking row box-shadow.',
145
+ composer: 'shadow: message input form box-shadow.',
146
146
  artifact:
147
147
  'toolbar (icon styling, copy menu), tab (background, active states), pane (background, toolbarBackground).',
148
148
  },
149
149
  },
150
150
 
151
151
  colorScheme:
152
- '"dark" merges darkTheme overrides on top of theme. "auto" detects system preference or <html class="dark">. "light" is default. colorScheme does NOT auto-invert colors provide dark palette and semantic overrides yourself.',
152
+ '"dark" merges darkTheme overrides on top of theme. "auto" detects system preference or <html class="dark">. "light" is default. colorScheme does NOT auto-invert colors: provide dark palette and semantic overrides yourself.',
153
153
 
154
154
  plugins: {
155
155
  description:
@@ -246,7 +246,7 @@ export const THEME_TOKEN_DOCS = {
246
246
  'enabled, provider ("browser" | "runtype"), browserFallback, voice, rate, pitch.',
247
247
  },
248
248
  suggestionChips:
249
- 'string[] Suggested prompts shown to the user.',
249
+ 'string[]: Suggested prompts shown to the user.',
250
250
  messageActions: {
251
251
  description: 'Message action buttons (copy, upvote, downvote).',
252
252
  properties:
@@ -264,8 +264,8 @@ export const THEME_TOKEN_DOCS = {
264
264
  },
265
265
  layout: {
266
266
  description: 'Layout configuration.',
267
- showHeader: 'boolean show/hide the header section entirely.',
268
- showFooter: 'boolean show/hide the footer/composer section entirely.',
267
+ showHeader: 'boolean: show/hide the header section entirely.',
268
+ showFooter: 'boolean: show/hide the footer/composer section entirely.',
269
269
  contentMaxWidth:
270
270
  'CSS width value for centering content (e.g. "720px", "90ch").',
271
271
  header:
@@ -277,7 +277,7 @@ export const THEME_TOKEN_DOCS = {
277
277
  description: 'Status text shown below the composer.',
278
278
  properties: {
279
279
  visible: 'Show/hide the status indicator.',
280
- align: '"left" | "center" | "right" text alignment (default: "right").',
280
+ align: '"left" | "center" | "right": text alignment (default: "right").',
281
281
  idleText: 'Text shown when idle (default: "Online").',
282
282
  idleLink: 'URL to open when idle text is clicked (wraps text in a link).',
283
283
  connectingText: 'Text shown while connecting (default: "Connecting…").',
@@ -306,7 +306,7 @@ export interface ThemeExample {
306
306
  export const THEME_EXAMPLES: Record<string, ThemeExample> = {
307
307
  darkIndigo: {
308
308
  description:
309
- 'Dark mode with indigo accent override grays for dark backgrounds and semantic tokens for inverted text/surface',
309
+ 'Dark mode with indigo accent: override grays for dark backgrounds and semantic tokens for inverted text/surface',
310
310
  theme: {
311
311
  palette: {
312
312
  colors: {
@@ -359,7 +359,7 @@ export const THEME_EXAMPLES: Record<string, ThemeExample> = {
359
359
  },
360
360
  neonCyberpunk: {
361
361
  description:
362
- 'Neon on dark with monospace font full semantic override for dark background',
362
+ 'Neon on dark with monospace font: full semantic override for dark background',
363
363
  theme: {
364
364
  palette: {
365
365
  colors: {