@runtypelabs/persona 3.15.1 → 3.17.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 (60) hide show
  1. package/dist/animations/glyph-cycle.cjs +279 -0
  2. package/dist/animations/glyph-cycle.d.cts +5 -0
  3. package/dist/animations/glyph-cycle.d.ts +5 -0
  4. package/dist/animations/glyph-cycle.js +252 -0
  5. package/dist/animations/types-HPZY7oAI.d.cts +282 -0
  6. package/dist/animations/types-HPZY7oAI.d.ts +282 -0
  7. package/dist/animations/wipe.cjs +107 -0
  8. package/dist/animations/wipe.d.cts +5 -0
  9. package/dist/animations/wipe.d.ts +5 -0
  10. package/dist/animations/wipe.js +80 -0
  11. package/dist/index.cjs +49 -48
  12. package/dist/index.cjs.map +1 -1
  13. package/dist/index.d.cts +216 -1
  14. package/dist/index.d.ts +216 -1
  15. package/dist/index.global.js +137 -82
  16. package/dist/index.global.js.map +1 -1
  17. package/dist/index.js +49 -48
  18. package/dist/index.js.map +1 -1
  19. package/dist/testing.cjs +85 -0
  20. package/dist/testing.d.cts +39 -0
  21. package/dist/testing.d.ts +39 -0
  22. package/dist/testing.js +56 -0
  23. package/dist/theme-editor.cjs +847 -127
  24. package/dist/theme-editor.d.cts +225 -2
  25. package/dist/theme-editor.d.ts +225 -2
  26. package/dist/theme-editor.js +845 -127
  27. package/dist/widget.css +133 -0
  28. package/package.json +20 -3
  29. package/src/animations/glyph-cycle.ts +332 -0
  30. package/src/animations/wipe.ts +66 -0
  31. package/src/client.test.ts +141 -0
  32. package/src/client.ts +197 -2
  33. package/src/components/composer-builder.ts +61 -10
  34. package/src/components/header-builder.ts +18 -7
  35. package/src/components/header-layouts.ts +3 -1
  36. package/src/components/message-bubble.test.ts +181 -2
  37. package/src/components/message-bubble.ts +209 -14
  38. package/src/components/panel.ts +4 -1
  39. package/src/defaults.ts +22 -0
  40. package/src/index-global.ts +31 -0
  41. package/src/index.ts +18 -0
  42. package/src/session.test.ts +93 -1
  43. package/src/session.ts +5 -0
  44. package/src/styles/widget.css +133 -0
  45. package/src/testing/index.ts +11 -0
  46. package/src/testing/mock-stream.test.ts +80 -0
  47. package/src/testing/mock-stream.ts +94 -0
  48. package/src/testing.ts +2 -0
  49. package/src/theme-editor/index.ts +4 -0
  50. package/src/theme-editor/preview-utils.test.ts +60 -0
  51. package/src/theme-editor/preview-utils.ts +129 -0
  52. package/src/theme-editor/sections.test.ts +19 -0
  53. package/src/theme-editor/sections.ts +84 -1
  54. package/src/types.ts +221 -0
  55. package/src/ui.stop-button.test.ts +165 -0
  56. package/src/ui.ts +79 -8
  57. package/src/utils/message-fingerprint.ts +2 -0
  58. package/src/utils/morph.ts +7 -0
  59. package/src/utils/stream-animation.test.ts +417 -0
  60. package/src/utils/stream-animation.ts +449 -0
@@ -767,6 +767,17 @@ type AgentMessageMetadata = {
767
767
  iteration?: number;
768
768
  turnId?: string;
769
769
  agentName?: string;
770
+ /**
771
+ * When this message was produced by a step inside a nested flow executed
772
+ * as a tool, identifies the parent tool call id. Enables renderers to
773
+ * visually group or indent nested-flow output under its parent tool.
774
+ */
775
+ parentToolId?: string;
776
+ /**
777
+ * Nested flow step id that produced this message (e.g. a `send-stream`
778
+ * or `prompt` step inside the nested flow). Stable key for that step.
779
+ */
780
+ parentStepId?: string;
770
781
  };
771
782
  type AgentWidgetRequestMiddlewareContext = {
772
783
  payload: AgentWidgetRequestPayload;
@@ -1210,6 +1221,151 @@ type AgentWidgetReasoningDisplayFeature = {
1210
1221
  */
1211
1222
  loadingAnimation?: AgentWidgetToolCallLoadingAnimation;
1212
1223
  };
1224
+ /**
1225
+ * Reveal animation applied to assistant message text while it is streaming.
1226
+ *
1227
+ * Built-in types always available:
1228
+ * - `none` — text appears as tokens arrive (default).
1229
+ * - `typewriter` — characters fade in with a blinking caret.
1230
+ * - `pop-bubble` — the bubble scales in; text streams normally afterward.
1231
+ * - `letter-rise` — per-char translateY + fade reveal.
1232
+ * - `word-fade` — per-word blur + translateY fade-in.
1233
+ *
1234
+ * Subpath plugins (import from `@runtypelabs/persona/animations/*` to register):
1235
+ * - `wipe`, `glyph-cycle`.
1236
+ *
1237
+ * Custom types are allowed — register a plugin with any string name and
1238
+ * reference it by that name in `type`.
1239
+ */
1240
+ type AgentWidgetStreamAnimationBuiltinType = "none" | "typewriter" | "word-fade" | "letter-rise" | "glyph-cycle" | "wipe" | "pop-bubble";
1241
+ type AgentWidgetStreamAnimationType = AgentWidgetStreamAnimationBuiltinType | (string & {});
1242
+ /**
1243
+ * Placeholder shown inside a streaming assistant bubble before the first token arrives.
1244
+ * - `none` — use the default typing-dots indicator (existing behavior).
1245
+ * - `skeleton` — shimmer bars, replaced by streaming content once it starts.
1246
+ */
1247
+ type AgentWidgetStreamAnimationPlaceholder = "none" | "skeleton";
1248
+ /**
1249
+ * How much of the accumulated streaming content to display while tokens are
1250
+ * still arriving. Trimming to a boundary means in-progress words or lines
1251
+ * stay hidden until they complete — useful for animations that benefit from
1252
+ * unit-complete reveals (e.g. wipe, glyph-cycle).
1253
+ * - `none` — show every character as it arrives (default).
1254
+ * - `word` — trim to the last whitespace boundary.
1255
+ * - `line` — trim to the last newline boundary.
1256
+ */
1257
+ type AgentWidgetStreamAnimationBuffer = "none" | "word" | "line";
1258
+ /**
1259
+ * Context passed to plugin lifecycle hooks. Carries the live DOM references
1260
+ * and resolved animation settings for the currently-streaming message.
1261
+ */
1262
+ type StreamAnimationContext = {
1263
+ /** The `.persona-message-content` element owning the streamed text. */
1264
+ container: HTMLElement;
1265
+ /** The outer message bubble element. */
1266
+ bubble: HTMLElement;
1267
+ /** ID of the streaming message. */
1268
+ messageId: string;
1269
+ /** Read-only reference to the message being streamed. */
1270
+ message: AgentWidgetMessage;
1271
+ /** Effective `speed` from `streamAnimation.speed`. */
1272
+ speed: number;
1273
+ /** Effective `duration` from `streamAnimation.duration`. */
1274
+ duration: number;
1275
+ };
1276
+ /**
1277
+ * Pluggable stream animation. Third-party packages and inline registrations
1278
+ * implement this interface to add custom reveal effects.
1279
+ *
1280
+ * Lifecycle:
1281
+ * - When the widget mounts and detects a plugin (either passed via config or
1282
+ * auto-registered in the IIFE bundle), it injects `styles` once into the
1283
+ * widget's style host.
1284
+ * - For each streaming assistant message whose `type` matches `name`, the
1285
+ * widget applies `containerClass` / `bubbleClass`, wraps text per `wrap`,
1286
+ * and — if `useCaret` is true — appends a blinking caret.
1287
+ * - Hooks fire after the live DOM is morphed; plugins use stable element IDs
1288
+ * and `data-preserve-animation` to safely mutate per-char or per-word spans
1289
+ * without idiomorph clobbering in-flight work.
1290
+ */
1291
+ type StreamAnimationPlugin = {
1292
+ /** Plugin identifier. Matches the `type` field in `streamAnimation`. */
1293
+ name: string;
1294
+ /** Class added to `.persona-message-content` while streaming. */
1295
+ containerClass?: string;
1296
+ /** Class added to the bubble element (e.g. a one-shot scale animation). */
1297
+ bubbleClass?: string;
1298
+ /** Wrap mode applied to text nodes during streaming. @default "none" */
1299
+ wrap?: "none" | "char" | "word";
1300
+ /**
1301
+ * HTML tags whose descendant text is skipped during wrapping. Defaults to
1302
+ * `["pre", "code", "a", "script", "style"]` — useful for keeping code
1303
+ * blocks legible and link click-targets intact. Plugins that want to
1304
+ * animate characters inside inline code (e.g. `glyph-cycle`) can narrow
1305
+ * the list.
1306
+ */
1307
+ skipTags?: string[];
1308
+ /** Append a blinking caret after the last rendered char/word. */
1309
+ useCaret?: boolean;
1310
+ /** CSS string injected into the widget style host on first activation. */
1311
+ styles?: string;
1312
+ /**
1313
+ * Optional custom buffering strategy. Returns the portion of `content`
1314
+ * that should be rendered during streaming. Use this for buffering
1315
+ * schemes beyond the built-in `word` / `line` strategies.
1316
+ */
1317
+ bufferContent?: (content: string, message: AgentWidgetMessage) => string;
1318
+ /**
1319
+ * Fires once when the plugin is first activated inside a widget instance.
1320
+ * Use this to set up MutationObservers or other long-lived listeners.
1321
+ * Return an optional cleanup function that runs on widget destroy.
1322
+ */
1323
+ onAttach?: (root: HTMLElement | ShadowRoot) => (() => void) | void;
1324
+ /** Fires after each render that reaches the live DOM. */
1325
+ onAfterRender?: (ctx: StreamAnimationContext) => void;
1326
+ /** Fires when a streamed message's `streaming` flag flips to false. */
1327
+ onStreamComplete?: (ctx: StreamAnimationContext) => void;
1328
+ /**
1329
+ * Report whether the plugin still has in-flight animation work for a
1330
+ * message. When `true`, the widget keeps rendering the message in its
1331
+ * "streaming-animated" mode even after `message.streaming` flips false —
1332
+ * preventing the final non-animated render from yanking the rug out from
1333
+ * under unfinished per-char cycles or reveals.
1334
+ */
1335
+ isAnimating?: (message: AgentWidgetMessage) => boolean;
1336
+ };
1337
+ type AgentWidgetStreamAnimationFeature = {
1338
+ /** Reveal animation to apply while streaming. @default "none" */
1339
+ type?: AgentWidgetStreamAnimationType;
1340
+ /** Pre-first-token placeholder. @default "none" */
1341
+ placeholder?: AgentWidgetStreamAnimationPlaceholder;
1342
+ /**
1343
+ * Per-unit animation duration (ms) for `typewriter`, `letter-rise`, `word-fade`,
1344
+ * and per-unit plugin animations. Each arriving character/word animates from
1345
+ * invisible to visible over this duration, independent of its position — the
1346
+ * streaming cadence itself provides the visible stagger.
1347
+ * @default 120
1348
+ */
1349
+ speed?: number;
1350
+ /**
1351
+ * Total duration of container-level animations (`pop-bubble` and custom
1352
+ * plugin animations), in milliseconds.
1353
+ * @default 1800
1354
+ */
1355
+ duration?: number;
1356
+ /**
1357
+ * Trim the accumulated streaming content to a word or line boundary before
1358
+ * rendering. Hides in-progress units until they complete.
1359
+ * @default "none"
1360
+ */
1361
+ buffer?: AgentWidgetStreamAnimationBuffer;
1362
+ /**
1363
+ * Extra animation plugins available to this widget instance. Keys are
1364
+ * plugin names; the matching plugin activates when `type` is set to that
1365
+ * name. Built-in types (`typewriter`, `pop-bubble`) are always registered.
1366
+ */
1367
+ plugins?: Record<string, StreamAnimationPlugin>;
1368
+ };
1213
1369
  type AgentWidgetFeatureFlags = {
1214
1370
  showReasoning?: boolean;
1215
1371
  showToolCalls?: boolean;
@@ -1224,6 +1380,8 @@ type AgentWidgetFeatureFlags = {
1224
1380
  eventStream?: EventStreamConfig;
1225
1381
  /** Optional artifact sidebar (split pane / mobile drawer) */
1226
1382
  artifacts?: AgentWidgetArtifactsFeature;
1383
+ /** Reveal animation for streaming assistant text. */
1384
+ streamAnimation?: AgentWidgetStreamAnimationFeature;
1227
1385
  };
1228
1386
  type SSEEventRecord = {
1229
1387
  id: string;
@@ -1512,6 +1670,10 @@ type AgentWidgetSendButtonConfig = {
1512
1670
  backgroundColor?: string;
1513
1671
  textColor?: string;
1514
1672
  size?: string;
1673
+ /** Lucide icon name shown while a response is streaming. Clicking the button in this state aborts the stream. Default: "square". */
1674
+ stopIconName?: string;
1675
+ /** Tooltip text shown while streaming. Default: "Stop generating". */
1676
+ stopTooltipText?: string;
1515
1677
  };
1516
1678
  /** Optional composer UI state for custom `renderComposer` implementations. */
1517
1679
  type AgentWidgetComposerConfig = {
@@ -2911,11 +3073,21 @@ type AgentWidgetConfig = {
2911
3073
  welcomeSubtitle?: string;
2912
3074
  inputPlaceholder?: string;
2913
3075
  sendButtonLabel?: string;
3076
+ /** Button label shown in text mode while a response is streaming. Default: "Stop". */
3077
+ stopButtonLabel?: string;
2914
3078
  /**
2915
3079
  * When false, the welcome / intro card is not shown above the message list.
2916
3080
  * @default true
2917
3081
  */
2918
3082
  showWelcomeCard?: boolean;
3083
+ /**
3084
+ * Per-stop-reason copy for the inline notice rendered on assistant
3085
+ * bubbles when the runtime reports a non-natural stop (e.g. the agent
3086
+ * loop hit `max_tool_calls` and was cut off mid-loop). Each key is
3087
+ * optional — keys you omit fall back to the built-in defaults. Set a
3088
+ * key to an empty string to suppress the notice for that reason.
3089
+ */
3090
+ stopReasonNotice?: Partial<Record<StopReasonKind, string>>;
2919
3091
  };
2920
3092
  /**
2921
3093
  * Semantic design tokens (`palette`, `semantic`, `components`).
@@ -3413,6 +3585,21 @@ type AgentWidgetApproval = {
3413
3585
  resolvedAt?: number;
3414
3586
  };
3415
3587
  type AgentWidgetMessageVariant = "assistant" | "reasoning" | "tool" | "approval";
3588
+ /**
3589
+ * Per-turn / per-step stop reason emitted by the runtime on
3590
+ * `agent_turn_complete` and `step_complete` SSE events. The vocabulary is
3591
+ * owned by the upstream Runtype API — do not extend without coordination.
3592
+ *
3593
+ * - `end_turn` — natural completion (no affordance needed)
3594
+ * - `max_tool_calls` — agent loop tripped the configured tool-call ceiling
3595
+ * - `length` — provider hit max output tokens
3596
+ * - `content_filter` — provider content filter intervened
3597
+ * - `error` — provider/runtime error (prefer existing error rendering)
3598
+ * - `unknown` — explicitly reported but uninformative
3599
+ *
3600
+ * Absent (`undefined`) means "not reported" — distinct from `'unknown'`.
3601
+ */
3602
+ type StopReasonKind = 'end_turn' | 'max_tool_calls' | 'length' | 'content_filter' | 'error' | 'unknown';
3416
3603
  /**
3417
3604
  * Represents a message in the chat conversation.
3418
3605
  *
@@ -3499,6 +3686,17 @@ type AgentWidgetMessage = {
3499
3686
  * Contains execution context like iteration number and turn ID.
3500
3687
  */
3501
3688
  agentMetadata?: AgentMessageMetadata;
3689
+ /**
3690
+ * Per-turn stop reason reported by the runtime on `agent_turn_complete`
3691
+ * (agent-loop path) or the last `step_complete` for a prompt step
3692
+ * (dispatch / flow path). Absent when the API did not report a value.
3693
+ *
3694
+ * When set to a non-natural value (`max_tool_calls`, `length`,
3695
+ * `content_filter`, `error`), the widget renders an inline notice on
3696
+ * the assistant bubble. See `config.copy.stopReasonNotice` to override
3697
+ * the default copy.
3698
+ */
3699
+ stopReason?: StopReasonKind;
3502
3700
  };
3503
3701
  /**
3504
3702
  * Options for injecting a message into the conversation.
@@ -4050,10 +4248,35 @@ declare const MOCK_WORKSPACE_CONTENT = "\n <div class=\"preview-workspace-con
4050
4248
  */
4051
4249
  declare function buildSrcdoc(mountId: string, shellMode: 'light' | 'dark', docked: boolean, widgetCssPath: string): string;
4052
4250
  type PreviewScene = 'home' | 'conversation' | 'minimized' | 'artifact';
4053
- type PreviewTranscriptEntryPreset = 'user-message' | 'assistant-message' | 'reasoning-streaming' | 'reasoning-complete' | 'tool-running' | 'tool-complete';
4251
+ type PreviewTranscriptEntryPreset = 'user-message' | 'assistant-message' | 'assistant-code-block' | 'assistant-markdown-table' | 'assistant-image' | 'reasoning-streaming' | 'reasoning-complete' | 'tool-running' | 'tool-complete';
4054
4252
  declare function getPreviewTranscriptPresetLabel(preset: PreviewTranscriptEntryPreset): string;
4055
4253
  declare function createPreviewTranscriptEntry(preset: PreviewTranscriptEntryPreset, index?: number): AgentWidgetMessage;
4056
4254
  declare function appendPreviewTranscriptEntry(messages: AgentWidgetMessage[], preset: PreviewTranscriptEntryPreset): AgentWidgetMessage[];
4255
+ /** Presets whose assistant content should stream in so Stream Animation settings engage. */
4256
+ declare function presetStreamsText(preset: PreviewTranscriptEntryPreset): boolean;
4257
+ interface TranscriptStreamFrame {
4258
+ /** Message to upsert into the session. */
4259
+ message: AgentWidgetMessage;
4260
+ /** Delay from the previous frame in ms. The first frame uses 0. */
4261
+ delayMs: number;
4262
+ /** True when this is the final frame (message is no longer streaming). */
4263
+ done: boolean;
4264
+ }
4265
+ interface BuildTranscriptStreamFramesOptions {
4266
+ /** Characters per progressive chunk. Default: 24. */
4267
+ chunkSize?: number;
4268
+ /** Delay between chunks in ms. Default: 42. */
4269
+ delayMs?: number;
4270
+ }
4271
+ /**
4272
+ * Builds progressive snapshots for a transcript preset suitable for feeding into
4273
+ * `injectTestMessage({ type: 'message', message })` on a timer. Each frame upserts
4274
+ * the same message id with more content, ending with `streaming: false`.
4275
+ *
4276
+ * - Streaming-capable presets (assistant text) yield many frames.
4277
+ * - All other presets yield a single `done` frame matching `createPreviewTranscriptEntry`.
4278
+ */
4279
+ declare function buildTranscriptStreamFrames(preset: PreviewTranscriptEntryPreset, suffix: number, options?: BuildTranscriptStreamFramesOptions): TranscriptStreamFrame[];
4057
4280
  declare function createPreviewMessages(scene: PreviewScene, config?: Partial<AgentWidgetConfig>, appendedMessages?: AgentWidgetMessage[]): AgentWidgetMessage[];
4058
4281
  declare function applySceneConfig(base: AgentWidgetConfig, scene: PreviewScene, appendedMessages?: AgentWidgetMessage[]): AgentWidgetConfig;
4059
4282
 
@@ -4230,4 +4453,4 @@ declare function paletteColorPath(family: string, shade: string): string;
4230
4453
  declare function resolveThemeColorPath(get: (path: string) => unknown, path: string, depth?: number): string;
4231
4454
  declare function tokenRefDisplayName(path: string): string;
4232
4455
 
4233
- export { ADVANCED_TOKENS_SECTION, ALL_ROLES, ALL_TABS, BRAND_PALETTE_SECTION, BUILT_IN_PRESETS, COLORS_SECTIONS, COLOR_FAMILIES, COMPONENTS_SECTIONS, COMPONENT_COLOR_SECTIONS, COMPONENT_SHAPE_SECTIONS, CONFIGURE_SECTIONS, CONFIGURE_SUB_GROUPS, type ColorScaleOptions, type CompareMode, type ConfigChangeListener, type ConfiguratorSnapshot, DEVICE_DIMENSIONS, type DetectedRoleAssignment, type FieldDef, type FieldType, HOME_SUGGESTION_CHIPS, INTERFACE_ROLES_SECTION, MOCK_BROWSER_CONTENT, MOCK_WORKSPACE_CONTENT, type OnChangeCallback, PALETTE_SECTION, PREVIEW_STORAGE_ADAPTER, type PreviewConfigOptions, type PreviewDevice, type PreviewLifecycleContext, type PreviewScene, type PreviewShellMode, type PreviewShellPalette, type PreviewTranscriptEntryPreset, ROLE_ASSISTANT_MESSAGES, ROLE_BORDERS, ROLE_FAMILIES, ROLE_FAMILY_LABELS, ROLE_HEADER, ROLE_INPUT, ROLE_INTENSITIES, ROLE_LINKS_FOCUS, ROLE_PRIMARY_ACTIONS, ROLE_SCROLL_TO_BOTTOM, ROLE_SURFACES, ROLE_USER_MESSAGES, type RoleAssignmentOptions, type RoleFamily, type RoleIntensity, type RoleTarget, type RoleTargetKind, SEMANTIC_COLORS_SECTION, SHADE_KEYS, SHELL_STYLE_ID, STATUS_COLORS_SECTION, STATUS_PALETTE_SECTION, STYLE_SECTIONS, STYLE_SECTIONS_V2, type SectionDef, type SectionPreset, type SelectOption, type SliderOptions, type SubGroupDef, THEME_EDITOR_PRESETS, THEME_SECTION, type TabDef, type ThemeEditorPreset, ThemeEditorState, type ThemePreviewHandle, type ThemePreviewOptions, type TokenRefOptions, ZOOM_MAX, ZOOM_MIN, appendPreviewTranscriptEntry, applySceneConfig, applyShellTheme, buildPreviewConfig, buildPreviewConfigWithMessages, buildShellCss, buildSrcdoc, convertFromPx, convertToPx, createPreviewMessages, createPreviewTranscriptEntry, createThemePreview, detectRoleAssignment, escapeHtml, findSection, formatCssValue, generateColorScale, getPreviewTranscriptPresetLabel, getShellPalette, getThemeEditorPreset, hexToHsl, hslToHex, isValidHex, normalizeColorValue, paletteColorPath, parseCssValue, resolveRoleAssignment, resolveThemeColorPath, scopeSection, tokenRefDisplayName, wcagContrastRatio };
4456
+ export { ADVANCED_TOKENS_SECTION, ALL_ROLES, ALL_TABS, BRAND_PALETTE_SECTION, BUILT_IN_PRESETS, type BuildTranscriptStreamFramesOptions, COLORS_SECTIONS, COLOR_FAMILIES, COMPONENTS_SECTIONS, COMPONENT_COLOR_SECTIONS, COMPONENT_SHAPE_SECTIONS, CONFIGURE_SECTIONS, CONFIGURE_SUB_GROUPS, type ColorScaleOptions, type CompareMode, type ConfigChangeListener, type ConfiguratorSnapshot, DEVICE_DIMENSIONS, type DetectedRoleAssignment, type FieldDef, type FieldType, HOME_SUGGESTION_CHIPS, INTERFACE_ROLES_SECTION, MOCK_BROWSER_CONTENT, MOCK_WORKSPACE_CONTENT, type OnChangeCallback, PALETTE_SECTION, PREVIEW_STORAGE_ADAPTER, type PreviewConfigOptions, type PreviewDevice, type PreviewLifecycleContext, type PreviewScene, type PreviewShellMode, type PreviewShellPalette, type PreviewTranscriptEntryPreset, ROLE_ASSISTANT_MESSAGES, ROLE_BORDERS, ROLE_FAMILIES, ROLE_FAMILY_LABELS, ROLE_HEADER, ROLE_INPUT, ROLE_INTENSITIES, ROLE_LINKS_FOCUS, ROLE_PRIMARY_ACTIONS, ROLE_SCROLL_TO_BOTTOM, ROLE_SURFACES, ROLE_USER_MESSAGES, type RoleAssignmentOptions, type RoleFamily, type RoleIntensity, type RoleTarget, type RoleTargetKind, SEMANTIC_COLORS_SECTION, SHADE_KEYS, SHELL_STYLE_ID, STATUS_COLORS_SECTION, STATUS_PALETTE_SECTION, STYLE_SECTIONS, STYLE_SECTIONS_V2, type SectionDef, type SectionPreset, type SelectOption, type SliderOptions, type SubGroupDef, THEME_EDITOR_PRESETS, THEME_SECTION, type TabDef, type ThemeEditorPreset, ThemeEditorState, type ThemePreviewHandle, type ThemePreviewOptions, type TokenRefOptions, type TranscriptStreamFrame, ZOOM_MAX, ZOOM_MIN, appendPreviewTranscriptEntry, applySceneConfig, applyShellTheme, buildPreviewConfig, buildPreviewConfigWithMessages, buildShellCss, buildSrcdoc, buildTranscriptStreamFrames, convertFromPx, convertToPx, createPreviewMessages, createPreviewTranscriptEntry, createThemePreview, detectRoleAssignment, escapeHtml, findSection, formatCssValue, generateColorScale, getPreviewTranscriptPresetLabel, getShellPalette, getThemeEditorPreset, hexToHsl, hslToHex, isValidHex, normalizeColorValue, paletteColorPath, parseCssValue, presetStreamsText, resolveRoleAssignment, resolveThemeColorPath, scopeSection, tokenRefDisplayName, wcagContrastRatio };
@@ -767,6 +767,17 @@ type AgentMessageMetadata = {
767
767
  iteration?: number;
768
768
  turnId?: string;
769
769
  agentName?: string;
770
+ /**
771
+ * When this message was produced by a step inside a nested flow executed
772
+ * as a tool, identifies the parent tool call id. Enables renderers to
773
+ * visually group or indent nested-flow output under its parent tool.
774
+ */
775
+ parentToolId?: string;
776
+ /**
777
+ * Nested flow step id that produced this message (e.g. a `send-stream`
778
+ * or `prompt` step inside the nested flow). Stable key for that step.
779
+ */
780
+ parentStepId?: string;
770
781
  };
771
782
  type AgentWidgetRequestMiddlewareContext = {
772
783
  payload: AgentWidgetRequestPayload;
@@ -1210,6 +1221,151 @@ type AgentWidgetReasoningDisplayFeature = {
1210
1221
  */
1211
1222
  loadingAnimation?: AgentWidgetToolCallLoadingAnimation;
1212
1223
  };
1224
+ /**
1225
+ * Reveal animation applied to assistant message text while it is streaming.
1226
+ *
1227
+ * Built-in types always available:
1228
+ * - `none` — text appears as tokens arrive (default).
1229
+ * - `typewriter` — characters fade in with a blinking caret.
1230
+ * - `pop-bubble` — the bubble scales in; text streams normally afterward.
1231
+ * - `letter-rise` — per-char translateY + fade reveal.
1232
+ * - `word-fade` — per-word blur + translateY fade-in.
1233
+ *
1234
+ * Subpath plugins (import from `@runtypelabs/persona/animations/*` to register):
1235
+ * - `wipe`, `glyph-cycle`.
1236
+ *
1237
+ * Custom types are allowed — register a plugin with any string name and
1238
+ * reference it by that name in `type`.
1239
+ */
1240
+ type AgentWidgetStreamAnimationBuiltinType = "none" | "typewriter" | "word-fade" | "letter-rise" | "glyph-cycle" | "wipe" | "pop-bubble";
1241
+ type AgentWidgetStreamAnimationType = AgentWidgetStreamAnimationBuiltinType | (string & {});
1242
+ /**
1243
+ * Placeholder shown inside a streaming assistant bubble before the first token arrives.
1244
+ * - `none` — use the default typing-dots indicator (existing behavior).
1245
+ * - `skeleton` — shimmer bars, replaced by streaming content once it starts.
1246
+ */
1247
+ type AgentWidgetStreamAnimationPlaceholder = "none" | "skeleton";
1248
+ /**
1249
+ * How much of the accumulated streaming content to display while tokens are
1250
+ * still arriving. Trimming to a boundary means in-progress words or lines
1251
+ * stay hidden until they complete — useful for animations that benefit from
1252
+ * unit-complete reveals (e.g. wipe, glyph-cycle).
1253
+ * - `none` — show every character as it arrives (default).
1254
+ * - `word` — trim to the last whitespace boundary.
1255
+ * - `line` — trim to the last newline boundary.
1256
+ */
1257
+ type AgentWidgetStreamAnimationBuffer = "none" | "word" | "line";
1258
+ /**
1259
+ * Context passed to plugin lifecycle hooks. Carries the live DOM references
1260
+ * and resolved animation settings for the currently-streaming message.
1261
+ */
1262
+ type StreamAnimationContext = {
1263
+ /** The `.persona-message-content` element owning the streamed text. */
1264
+ container: HTMLElement;
1265
+ /** The outer message bubble element. */
1266
+ bubble: HTMLElement;
1267
+ /** ID of the streaming message. */
1268
+ messageId: string;
1269
+ /** Read-only reference to the message being streamed. */
1270
+ message: AgentWidgetMessage;
1271
+ /** Effective `speed` from `streamAnimation.speed`. */
1272
+ speed: number;
1273
+ /** Effective `duration` from `streamAnimation.duration`. */
1274
+ duration: number;
1275
+ };
1276
+ /**
1277
+ * Pluggable stream animation. Third-party packages and inline registrations
1278
+ * implement this interface to add custom reveal effects.
1279
+ *
1280
+ * Lifecycle:
1281
+ * - When the widget mounts and detects a plugin (either passed via config or
1282
+ * auto-registered in the IIFE bundle), it injects `styles` once into the
1283
+ * widget's style host.
1284
+ * - For each streaming assistant message whose `type` matches `name`, the
1285
+ * widget applies `containerClass` / `bubbleClass`, wraps text per `wrap`,
1286
+ * and — if `useCaret` is true — appends a blinking caret.
1287
+ * - Hooks fire after the live DOM is morphed; plugins use stable element IDs
1288
+ * and `data-preserve-animation` to safely mutate per-char or per-word spans
1289
+ * without idiomorph clobbering in-flight work.
1290
+ */
1291
+ type StreamAnimationPlugin = {
1292
+ /** Plugin identifier. Matches the `type` field in `streamAnimation`. */
1293
+ name: string;
1294
+ /** Class added to `.persona-message-content` while streaming. */
1295
+ containerClass?: string;
1296
+ /** Class added to the bubble element (e.g. a one-shot scale animation). */
1297
+ bubbleClass?: string;
1298
+ /** Wrap mode applied to text nodes during streaming. @default "none" */
1299
+ wrap?: "none" | "char" | "word";
1300
+ /**
1301
+ * HTML tags whose descendant text is skipped during wrapping. Defaults to
1302
+ * `["pre", "code", "a", "script", "style"]` — useful for keeping code
1303
+ * blocks legible and link click-targets intact. Plugins that want to
1304
+ * animate characters inside inline code (e.g. `glyph-cycle`) can narrow
1305
+ * the list.
1306
+ */
1307
+ skipTags?: string[];
1308
+ /** Append a blinking caret after the last rendered char/word. */
1309
+ useCaret?: boolean;
1310
+ /** CSS string injected into the widget style host on first activation. */
1311
+ styles?: string;
1312
+ /**
1313
+ * Optional custom buffering strategy. Returns the portion of `content`
1314
+ * that should be rendered during streaming. Use this for buffering
1315
+ * schemes beyond the built-in `word` / `line` strategies.
1316
+ */
1317
+ bufferContent?: (content: string, message: AgentWidgetMessage) => string;
1318
+ /**
1319
+ * Fires once when the plugin is first activated inside a widget instance.
1320
+ * Use this to set up MutationObservers or other long-lived listeners.
1321
+ * Return an optional cleanup function that runs on widget destroy.
1322
+ */
1323
+ onAttach?: (root: HTMLElement | ShadowRoot) => (() => void) | void;
1324
+ /** Fires after each render that reaches the live DOM. */
1325
+ onAfterRender?: (ctx: StreamAnimationContext) => void;
1326
+ /** Fires when a streamed message's `streaming` flag flips to false. */
1327
+ onStreamComplete?: (ctx: StreamAnimationContext) => void;
1328
+ /**
1329
+ * Report whether the plugin still has in-flight animation work for a
1330
+ * message. When `true`, the widget keeps rendering the message in its
1331
+ * "streaming-animated" mode even after `message.streaming` flips false —
1332
+ * preventing the final non-animated render from yanking the rug out from
1333
+ * under unfinished per-char cycles or reveals.
1334
+ */
1335
+ isAnimating?: (message: AgentWidgetMessage) => boolean;
1336
+ };
1337
+ type AgentWidgetStreamAnimationFeature = {
1338
+ /** Reveal animation to apply while streaming. @default "none" */
1339
+ type?: AgentWidgetStreamAnimationType;
1340
+ /** Pre-first-token placeholder. @default "none" */
1341
+ placeholder?: AgentWidgetStreamAnimationPlaceholder;
1342
+ /**
1343
+ * Per-unit animation duration (ms) for `typewriter`, `letter-rise`, `word-fade`,
1344
+ * and per-unit plugin animations. Each arriving character/word animates from
1345
+ * invisible to visible over this duration, independent of its position — the
1346
+ * streaming cadence itself provides the visible stagger.
1347
+ * @default 120
1348
+ */
1349
+ speed?: number;
1350
+ /**
1351
+ * Total duration of container-level animations (`pop-bubble` and custom
1352
+ * plugin animations), in milliseconds.
1353
+ * @default 1800
1354
+ */
1355
+ duration?: number;
1356
+ /**
1357
+ * Trim the accumulated streaming content to a word or line boundary before
1358
+ * rendering. Hides in-progress units until they complete.
1359
+ * @default "none"
1360
+ */
1361
+ buffer?: AgentWidgetStreamAnimationBuffer;
1362
+ /**
1363
+ * Extra animation plugins available to this widget instance. Keys are
1364
+ * plugin names; the matching plugin activates when `type` is set to that
1365
+ * name. Built-in types (`typewriter`, `pop-bubble`) are always registered.
1366
+ */
1367
+ plugins?: Record<string, StreamAnimationPlugin>;
1368
+ };
1213
1369
  type AgentWidgetFeatureFlags = {
1214
1370
  showReasoning?: boolean;
1215
1371
  showToolCalls?: boolean;
@@ -1224,6 +1380,8 @@ type AgentWidgetFeatureFlags = {
1224
1380
  eventStream?: EventStreamConfig;
1225
1381
  /** Optional artifact sidebar (split pane / mobile drawer) */
1226
1382
  artifacts?: AgentWidgetArtifactsFeature;
1383
+ /** Reveal animation for streaming assistant text. */
1384
+ streamAnimation?: AgentWidgetStreamAnimationFeature;
1227
1385
  };
1228
1386
  type SSEEventRecord = {
1229
1387
  id: string;
@@ -1512,6 +1670,10 @@ type AgentWidgetSendButtonConfig = {
1512
1670
  backgroundColor?: string;
1513
1671
  textColor?: string;
1514
1672
  size?: string;
1673
+ /** Lucide icon name shown while a response is streaming. Clicking the button in this state aborts the stream. Default: "square". */
1674
+ stopIconName?: string;
1675
+ /** Tooltip text shown while streaming. Default: "Stop generating". */
1676
+ stopTooltipText?: string;
1515
1677
  };
1516
1678
  /** Optional composer UI state for custom `renderComposer` implementations. */
1517
1679
  type AgentWidgetComposerConfig = {
@@ -2911,11 +3073,21 @@ type AgentWidgetConfig = {
2911
3073
  welcomeSubtitle?: string;
2912
3074
  inputPlaceholder?: string;
2913
3075
  sendButtonLabel?: string;
3076
+ /** Button label shown in text mode while a response is streaming. Default: "Stop". */
3077
+ stopButtonLabel?: string;
2914
3078
  /**
2915
3079
  * When false, the welcome / intro card is not shown above the message list.
2916
3080
  * @default true
2917
3081
  */
2918
3082
  showWelcomeCard?: boolean;
3083
+ /**
3084
+ * Per-stop-reason copy for the inline notice rendered on assistant
3085
+ * bubbles when the runtime reports a non-natural stop (e.g. the agent
3086
+ * loop hit `max_tool_calls` and was cut off mid-loop). Each key is
3087
+ * optional — keys you omit fall back to the built-in defaults. Set a
3088
+ * key to an empty string to suppress the notice for that reason.
3089
+ */
3090
+ stopReasonNotice?: Partial<Record<StopReasonKind, string>>;
2919
3091
  };
2920
3092
  /**
2921
3093
  * Semantic design tokens (`palette`, `semantic`, `components`).
@@ -3413,6 +3585,21 @@ type AgentWidgetApproval = {
3413
3585
  resolvedAt?: number;
3414
3586
  };
3415
3587
  type AgentWidgetMessageVariant = "assistant" | "reasoning" | "tool" | "approval";
3588
+ /**
3589
+ * Per-turn / per-step stop reason emitted by the runtime on
3590
+ * `agent_turn_complete` and `step_complete` SSE events. The vocabulary is
3591
+ * owned by the upstream Runtype API — do not extend without coordination.
3592
+ *
3593
+ * - `end_turn` — natural completion (no affordance needed)
3594
+ * - `max_tool_calls` — agent loop tripped the configured tool-call ceiling
3595
+ * - `length` — provider hit max output tokens
3596
+ * - `content_filter` — provider content filter intervened
3597
+ * - `error` — provider/runtime error (prefer existing error rendering)
3598
+ * - `unknown` — explicitly reported but uninformative
3599
+ *
3600
+ * Absent (`undefined`) means "not reported" — distinct from `'unknown'`.
3601
+ */
3602
+ type StopReasonKind = 'end_turn' | 'max_tool_calls' | 'length' | 'content_filter' | 'error' | 'unknown';
3416
3603
  /**
3417
3604
  * Represents a message in the chat conversation.
3418
3605
  *
@@ -3499,6 +3686,17 @@ type AgentWidgetMessage = {
3499
3686
  * Contains execution context like iteration number and turn ID.
3500
3687
  */
3501
3688
  agentMetadata?: AgentMessageMetadata;
3689
+ /**
3690
+ * Per-turn stop reason reported by the runtime on `agent_turn_complete`
3691
+ * (agent-loop path) or the last `step_complete` for a prompt step
3692
+ * (dispatch / flow path). Absent when the API did not report a value.
3693
+ *
3694
+ * When set to a non-natural value (`max_tool_calls`, `length`,
3695
+ * `content_filter`, `error`), the widget renders an inline notice on
3696
+ * the assistant bubble. See `config.copy.stopReasonNotice` to override
3697
+ * the default copy.
3698
+ */
3699
+ stopReason?: StopReasonKind;
3502
3700
  };
3503
3701
  /**
3504
3702
  * Options for injecting a message into the conversation.
@@ -4050,10 +4248,35 @@ declare const MOCK_WORKSPACE_CONTENT = "\n <div class=\"preview-workspace-con
4050
4248
  */
4051
4249
  declare function buildSrcdoc(mountId: string, shellMode: 'light' | 'dark', docked: boolean, widgetCssPath: string): string;
4052
4250
  type PreviewScene = 'home' | 'conversation' | 'minimized' | 'artifact';
4053
- type PreviewTranscriptEntryPreset = 'user-message' | 'assistant-message' | 'reasoning-streaming' | 'reasoning-complete' | 'tool-running' | 'tool-complete';
4251
+ type PreviewTranscriptEntryPreset = 'user-message' | 'assistant-message' | 'assistant-code-block' | 'assistant-markdown-table' | 'assistant-image' | 'reasoning-streaming' | 'reasoning-complete' | 'tool-running' | 'tool-complete';
4054
4252
  declare function getPreviewTranscriptPresetLabel(preset: PreviewTranscriptEntryPreset): string;
4055
4253
  declare function createPreviewTranscriptEntry(preset: PreviewTranscriptEntryPreset, index?: number): AgentWidgetMessage;
4056
4254
  declare function appendPreviewTranscriptEntry(messages: AgentWidgetMessage[], preset: PreviewTranscriptEntryPreset): AgentWidgetMessage[];
4255
+ /** Presets whose assistant content should stream in so Stream Animation settings engage. */
4256
+ declare function presetStreamsText(preset: PreviewTranscriptEntryPreset): boolean;
4257
+ interface TranscriptStreamFrame {
4258
+ /** Message to upsert into the session. */
4259
+ message: AgentWidgetMessage;
4260
+ /** Delay from the previous frame in ms. The first frame uses 0. */
4261
+ delayMs: number;
4262
+ /** True when this is the final frame (message is no longer streaming). */
4263
+ done: boolean;
4264
+ }
4265
+ interface BuildTranscriptStreamFramesOptions {
4266
+ /** Characters per progressive chunk. Default: 24. */
4267
+ chunkSize?: number;
4268
+ /** Delay between chunks in ms. Default: 42. */
4269
+ delayMs?: number;
4270
+ }
4271
+ /**
4272
+ * Builds progressive snapshots for a transcript preset suitable for feeding into
4273
+ * `injectTestMessage({ type: 'message', message })` on a timer. Each frame upserts
4274
+ * the same message id with more content, ending with `streaming: false`.
4275
+ *
4276
+ * - Streaming-capable presets (assistant text) yield many frames.
4277
+ * - All other presets yield a single `done` frame matching `createPreviewTranscriptEntry`.
4278
+ */
4279
+ declare function buildTranscriptStreamFrames(preset: PreviewTranscriptEntryPreset, suffix: number, options?: BuildTranscriptStreamFramesOptions): TranscriptStreamFrame[];
4057
4280
  declare function createPreviewMessages(scene: PreviewScene, config?: Partial<AgentWidgetConfig>, appendedMessages?: AgentWidgetMessage[]): AgentWidgetMessage[];
4058
4281
  declare function applySceneConfig(base: AgentWidgetConfig, scene: PreviewScene, appendedMessages?: AgentWidgetMessage[]): AgentWidgetConfig;
4059
4282
 
@@ -4230,4 +4453,4 @@ declare function paletteColorPath(family: string, shade: string): string;
4230
4453
  declare function resolveThemeColorPath(get: (path: string) => unknown, path: string, depth?: number): string;
4231
4454
  declare function tokenRefDisplayName(path: string): string;
4232
4455
 
4233
- export { ADVANCED_TOKENS_SECTION, ALL_ROLES, ALL_TABS, BRAND_PALETTE_SECTION, BUILT_IN_PRESETS, COLORS_SECTIONS, COLOR_FAMILIES, COMPONENTS_SECTIONS, COMPONENT_COLOR_SECTIONS, COMPONENT_SHAPE_SECTIONS, CONFIGURE_SECTIONS, CONFIGURE_SUB_GROUPS, type ColorScaleOptions, type CompareMode, type ConfigChangeListener, type ConfiguratorSnapshot, DEVICE_DIMENSIONS, type DetectedRoleAssignment, type FieldDef, type FieldType, HOME_SUGGESTION_CHIPS, INTERFACE_ROLES_SECTION, MOCK_BROWSER_CONTENT, MOCK_WORKSPACE_CONTENT, type OnChangeCallback, PALETTE_SECTION, PREVIEW_STORAGE_ADAPTER, type PreviewConfigOptions, type PreviewDevice, type PreviewLifecycleContext, type PreviewScene, type PreviewShellMode, type PreviewShellPalette, type PreviewTranscriptEntryPreset, ROLE_ASSISTANT_MESSAGES, ROLE_BORDERS, ROLE_FAMILIES, ROLE_FAMILY_LABELS, ROLE_HEADER, ROLE_INPUT, ROLE_INTENSITIES, ROLE_LINKS_FOCUS, ROLE_PRIMARY_ACTIONS, ROLE_SCROLL_TO_BOTTOM, ROLE_SURFACES, ROLE_USER_MESSAGES, type RoleAssignmentOptions, type RoleFamily, type RoleIntensity, type RoleTarget, type RoleTargetKind, SEMANTIC_COLORS_SECTION, SHADE_KEYS, SHELL_STYLE_ID, STATUS_COLORS_SECTION, STATUS_PALETTE_SECTION, STYLE_SECTIONS, STYLE_SECTIONS_V2, type SectionDef, type SectionPreset, type SelectOption, type SliderOptions, type SubGroupDef, THEME_EDITOR_PRESETS, THEME_SECTION, type TabDef, type ThemeEditorPreset, ThemeEditorState, type ThemePreviewHandle, type ThemePreviewOptions, type TokenRefOptions, ZOOM_MAX, ZOOM_MIN, appendPreviewTranscriptEntry, applySceneConfig, applyShellTheme, buildPreviewConfig, buildPreviewConfigWithMessages, buildShellCss, buildSrcdoc, convertFromPx, convertToPx, createPreviewMessages, createPreviewTranscriptEntry, createThemePreview, detectRoleAssignment, escapeHtml, findSection, formatCssValue, generateColorScale, getPreviewTranscriptPresetLabel, getShellPalette, getThemeEditorPreset, hexToHsl, hslToHex, isValidHex, normalizeColorValue, paletteColorPath, parseCssValue, resolveRoleAssignment, resolveThemeColorPath, scopeSection, tokenRefDisplayName, wcagContrastRatio };
4456
+ export { ADVANCED_TOKENS_SECTION, ALL_ROLES, ALL_TABS, BRAND_PALETTE_SECTION, BUILT_IN_PRESETS, type BuildTranscriptStreamFramesOptions, COLORS_SECTIONS, COLOR_FAMILIES, COMPONENTS_SECTIONS, COMPONENT_COLOR_SECTIONS, COMPONENT_SHAPE_SECTIONS, CONFIGURE_SECTIONS, CONFIGURE_SUB_GROUPS, type ColorScaleOptions, type CompareMode, type ConfigChangeListener, type ConfiguratorSnapshot, DEVICE_DIMENSIONS, type DetectedRoleAssignment, type FieldDef, type FieldType, HOME_SUGGESTION_CHIPS, INTERFACE_ROLES_SECTION, MOCK_BROWSER_CONTENT, MOCK_WORKSPACE_CONTENT, type OnChangeCallback, PALETTE_SECTION, PREVIEW_STORAGE_ADAPTER, type PreviewConfigOptions, type PreviewDevice, type PreviewLifecycleContext, type PreviewScene, type PreviewShellMode, type PreviewShellPalette, type PreviewTranscriptEntryPreset, ROLE_ASSISTANT_MESSAGES, ROLE_BORDERS, ROLE_FAMILIES, ROLE_FAMILY_LABELS, ROLE_HEADER, ROLE_INPUT, ROLE_INTENSITIES, ROLE_LINKS_FOCUS, ROLE_PRIMARY_ACTIONS, ROLE_SCROLL_TO_BOTTOM, ROLE_SURFACES, ROLE_USER_MESSAGES, type RoleAssignmentOptions, type RoleFamily, type RoleIntensity, type RoleTarget, type RoleTargetKind, SEMANTIC_COLORS_SECTION, SHADE_KEYS, SHELL_STYLE_ID, STATUS_COLORS_SECTION, STATUS_PALETTE_SECTION, STYLE_SECTIONS, STYLE_SECTIONS_V2, type SectionDef, type SectionPreset, type SelectOption, type SliderOptions, type SubGroupDef, THEME_EDITOR_PRESETS, THEME_SECTION, type TabDef, type ThemeEditorPreset, ThemeEditorState, type ThemePreviewHandle, type ThemePreviewOptions, type TokenRefOptions, type TranscriptStreamFrame, ZOOM_MAX, ZOOM_MIN, appendPreviewTranscriptEntry, applySceneConfig, applyShellTheme, buildPreviewConfig, buildPreviewConfigWithMessages, buildShellCss, buildSrcdoc, buildTranscriptStreamFrames, convertFromPx, convertToPx, createPreviewMessages, createPreviewTranscriptEntry, createThemePreview, detectRoleAssignment, escapeHtml, findSection, formatCssValue, generateColorScale, getPreviewTranscriptPresetLabel, getShellPalette, getThemeEditorPreset, hexToHsl, hslToHex, isValidHex, normalizeColorValue, paletteColorPath, parseCssValue, presetStreamsText, resolveRoleAssignment, resolveThemeColorPath, scopeSection, tokenRefDisplayName, wcagContrastRatio };