@runtypelabs/persona 3.16.0 → 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 (58) 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 +48 -47
  12. package/dist/index.cjs.map +1 -1
  13. package/dist/index.d.cts +205 -1
  14. package/dist/index.d.ts +205 -1
  15. package/dist/index.global.js +136 -81
  16. package/dist/index.global.js.map +1 -1
  17. package/dist/index.js +48 -47
  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 +714 -99
  24. package/dist/theme-editor.d.cts +214 -2
  25. package/dist/theme-editor.d.ts +214 -2
  26. package/dist/theme-editor.js +712 -99
  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 +28 -0
  33. package/src/components/composer-builder.ts +61 -10
  34. package/src/components/message-bubble.test.ts +181 -2
  35. package/src/components/message-bubble.ts +209 -14
  36. package/src/components/panel.ts +4 -1
  37. package/src/defaults.ts +16 -0
  38. package/src/index-global.ts +31 -0
  39. package/src/index.ts +18 -0
  40. package/src/session.test.ts +93 -1
  41. package/src/session.ts +5 -0
  42. package/src/styles/widget.css +133 -0
  43. package/src/testing/index.ts +11 -0
  44. package/src/testing/mock-stream.test.ts +80 -0
  45. package/src/testing/mock-stream.ts +94 -0
  46. package/src/testing.ts +2 -0
  47. package/src/theme-editor/index.ts +4 -0
  48. package/src/theme-editor/preview-utils.test.ts +60 -0
  49. package/src/theme-editor/preview-utils.ts +129 -0
  50. package/src/theme-editor/sections.test.ts +19 -0
  51. package/src/theme-editor/sections.ts +84 -1
  52. package/src/types.ts +210 -0
  53. package/src/ui.stop-button.test.ts +165 -0
  54. package/src/ui.ts +75 -6
  55. package/src/utils/message-fingerprint.ts +2 -0
  56. package/src/utils/morph.ts +7 -0
  57. package/src/utils/stream-animation.test.ts +417 -0
  58. package/src/utils/stream-animation.ts +449 -0
@@ -0,0 +1,282 @@
1
+ /**
2
+ * Text content part for multi-modal messages
3
+ */
4
+ type TextContentPart = {
5
+ type: 'text';
6
+ text: string;
7
+ };
8
+ /**
9
+ * Image content part for multi-modal messages
10
+ * Supports base64 data URIs or URLs
11
+ */
12
+ type ImageContentPart = {
13
+ type: 'image';
14
+ image: string;
15
+ mimeType?: string;
16
+ alt?: string;
17
+ };
18
+ /**
19
+ * File content part for multi-modal messages
20
+ * Supports PDF, TXT, DOCX, and other document types
21
+ */
22
+ type FileContentPart = {
23
+ type: 'file';
24
+ data: string;
25
+ mimeType: string;
26
+ filename: string;
27
+ };
28
+ /**
29
+ * Union type for all content part types
30
+ */
31
+ type ContentPart = TextContentPart | ImageContentPart | FileContentPart;
32
+ /**
33
+ * Metadata attached to messages created during agent execution.
34
+ */
35
+ type AgentMessageMetadata = {
36
+ executionId?: string;
37
+ iteration?: number;
38
+ turnId?: string;
39
+ agentName?: string;
40
+ /**
41
+ * When this message was produced by a step inside a nested flow executed
42
+ * as a tool, identifies the parent tool call id. Enables renderers to
43
+ * visually group or indent nested-flow output under its parent tool.
44
+ */
45
+ parentToolId?: string;
46
+ /**
47
+ * Nested flow step id that produced this message (e.g. a `send-stream`
48
+ * or `prompt` step inside the nested flow). Stable key for that step.
49
+ */
50
+ parentStepId?: string;
51
+ };
52
+ /**
53
+ * Context passed to plugin lifecycle hooks. Carries the live DOM references
54
+ * and resolved animation settings for the currently-streaming message.
55
+ */
56
+ type StreamAnimationContext = {
57
+ /** The `.persona-message-content` element owning the streamed text. */
58
+ container: HTMLElement;
59
+ /** The outer message bubble element. */
60
+ bubble: HTMLElement;
61
+ /** ID of the streaming message. */
62
+ messageId: string;
63
+ /** Read-only reference to the message being streamed. */
64
+ message: AgentWidgetMessage;
65
+ /** Effective `speed` from `streamAnimation.speed`. */
66
+ speed: number;
67
+ /** Effective `duration` from `streamAnimation.duration`. */
68
+ duration: number;
69
+ };
70
+ /**
71
+ * Pluggable stream animation. Third-party packages and inline registrations
72
+ * implement this interface to add custom reveal effects.
73
+ *
74
+ * Lifecycle:
75
+ * - When the widget mounts and detects a plugin (either passed via config or
76
+ * auto-registered in the IIFE bundle), it injects `styles` once into the
77
+ * widget's style host.
78
+ * - For each streaming assistant message whose `type` matches `name`, the
79
+ * widget applies `containerClass` / `bubbleClass`, wraps text per `wrap`,
80
+ * and — if `useCaret` is true — appends a blinking caret.
81
+ * - Hooks fire after the live DOM is morphed; plugins use stable element IDs
82
+ * and `data-preserve-animation` to safely mutate per-char or per-word spans
83
+ * without idiomorph clobbering in-flight work.
84
+ */
85
+ type StreamAnimationPlugin = {
86
+ /** Plugin identifier. Matches the `type` field in `streamAnimation`. */
87
+ name: string;
88
+ /** Class added to `.persona-message-content` while streaming. */
89
+ containerClass?: string;
90
+ /** Class added to the bubble element (e.g. a one-shot scale animation). */
91
+ bubbleClass?: string;
92
+ /** Wrap mode applied to text nodes during streaming. @default "none" */
93
+ wrap?: "none" | "char" | "word";
94
+ /**
95
+ * HTML tags whose descendant text is skipped during wrapping. Defaults to
96
+ * `["pre", "code", "a", "script", "style"]` — useful for keeping code
97
+ * blocks legible and link click-targets intact. Plugins that want to
98
+ * animate characters inside inline code (e.g. `glyph-cycle`) can narrow
99
+ * the list.
100
+ */
101
+ skipTags?: string[];
102
+ /** Append a blinking caret after the last rendered char/word. */
103
+ useCaret?: boolean;
104
+ /** CSS string injected into the widget style host on first activation. */
105
+ styles?: string;
106
+ /**
107
+ * Optional custom buffering strategy. Returns the portion of `content`
108
+ * that should be rendered during streaming. Use this for buffering
109
+ * schemes beyond the built-in `word` / `line` strategies.
110
+ */
111
+ bufferContent?: (content: string, message: AgentWidgetMessage) => string;
112
+ /**
113
+ * Fires once when the plugin is first activated inside a widget instance.
114
+ * Use this to set up MutationObservers or other long-lived listeners.
115
+ * Return an optional cleanup function that runs on widget destroy.
116
+ */
117
+ onAttach?: (root: HTMLElement | ShadowRoot) => (() => void) | void;
118
+ /** Fires after each render that reaches the live DOM. */
119
+ onAfterRender?: (ctx: StreamAnimationContext) => void;
120
+ /** Fires when a streamed message's `streaming` flag flips to false. */
121
+ onStreamComplete?: (ctx: StreamAnimationContext) => void;
122
+ /**
123
+ * Report whether the plugin still has in-flight animation work for a
124
+ * message. When `true`, the widget keeps rendering the message in its
125
+ * "streaming-animated" mode even after `message.streaming` flips false —
126
+ * preventing the final non-animated render from yanking the rug out from
127
+ * under unfinished per-char cycles or reveals.
128
+ */
129
+ isAnimating?: (message: AgentWidgetMessage) => boolean;
130
+ };
131
+ type AgentWidgetMessageRole = "user" | "assistant" | "system";
132
+ type AgentWidgetReasoning = {
133
+ id: string;
134
+ status: "pending" | "streaming" | "complete";
135
+ chunks: string[];
136
+ startedAt?: number;
137
+ completedAt?: number;
138
+ durationMs?: number;
139
+ };
140
+ type AgentWidgetToolCall = {
141
+ id: string;
142
+ name?: string;
143
+ status: "pending" | "running" | "complete";
144
+ args?: unknown;
145
+ chunks?: string[];
146
+ result?: unknown;
147
+ duration?: number;
148
+ startedAt?: number;
149
+ completedAt?: number;
150
+ durationMs?: number;
151
+ };
152
+ /**
153
+ * Represents a tool approval request in the chat conversation.
154
+ * Created when the agent requires human approval before executing a tool.
155
+ */
156
+ type AgentWidgetApproval = {
157
+ id: string;
158
+ status: "pending" | "approved" | "denied" | "timeout";
159
+ agentId: string;
160
+ executionId: string;
161
+ toolName: string;
162
+ toolType?: string;
163
+ description: string;
164
+ parameters?: unknown;
165
+ resolvedAt?: number;
166
+ };
167
+ type AgentWidgetMessageVariant = "assistant" | "reasoning" | "tool" | "approval";
168
+ /**
169
+ * Per-turn / per-step stop reason emitted by the runtime on
170
+ * `agent_turn_complete` and `step_complete` SSE events. The vocabulary is
171
+ * owned by the upstream Runtype API — do not extend without coordination.
172
+ *
173
+ * - `end_turn` — natural completion (no affordance needed)
174
+ * - `max_tool_calls` — agent loop tripped the configured tool-call ceiling
175
+ * - `length` — provider hit max output tokens
176
+ * - `content_filter` — provider content filter intervened
177
+ * - `error` — provider/runtime error (prefer existing error rendering)
178
+ * - `unknown` — explicitly reported but uninformative
179
+ *
180
+ * Absent (`undefined`) means "not reported" — distinct from `'unknown'`.
181
+ */
182
+ type StopReasonKind = 'end_turn' | 'max_tool_calls' | 'length' | 'content_filter' | 'error' | 'unknown';
183
+ /**
184
+ * Represents a message in the chat conversation.
185
+ *
186
+ * @property id - Unique message identifier
187
+ * @property role - Message role: "user", "assistant", or "system"
188
+ * @property content - Message text content (for display)
189
+ * @property contentParts - Original multi-modal content parts (for API requests)
190
+ * @property createdAt - ISO timestamp when message was created
191
+ * @property streaming - Whether message is still streaming (for assistant messages)
192
+ * @property variant - Message variant for assistant messages: "assistant", "reasoning", or "tool"
193
+ * @property sequence - Message ordering number
194
+ * @property reasoning - Reasoning data for assistant reasoning messages
195
+ * @property toolCall - Tool call data for assistant tool messages
196
+ * @property tools - Array of tool calls
197
+ * @property viaVoice - Set to `true` when a user message is sent via voice recognition.
198
+ * Useful for implementing voice-specific behaviors like auto-reactivation.
199
+ */
200
+ type AgentWidgetMessage = {
201
+ id: string;
202
+ role: AgentWidgetMessageRole;
203
+ content: string;
204
+ createdAt: string;
205
+ /**
206
+ * Original multi-modal content parts for this message.
207
+ * When present, this is sent to the API instead of `content`.
208
+ * The `content` field contains the text-only representation for display.
209
+ */
210
+ contentParts?: ContentPart[];
211
+ streaming?: boolean;
212
+ variant?: AgentWidgetMessageVariant;
213
+ sequence?: number;
214
+ reasoning?: AgentWidgetReasoning;
215
+ toolCall?: AgentWidgetToolCall;
216
+ tools?: AgentWidgetToolCall[];
217
+ /** Approval data for messages with variant "approval" */
218
+ approval?: AgentWidgetApproval;
219
+ viaVoice?: boolean;
220
+ /**
221
+ * Set to `true` on placeholder messages injected during Runtype voice processing.
222
+ * Use this in `messageTransform` to detect and customize voice processing placeholders.
223
+ *
224
+ * @example
225
+ * messageTransform: ({ text, message }) => {
226
+ * if (message.voiceProcessing && message.role === 'user') {
227
+ * return '<div class="my-voice-spinner">Transcribing...</div>';
228
+ * }
229
+ * return text;
230
+ * }
231
+ */
232
+ voiceProcessing?: boolean;
233
+ /**
234
+ * Raw structured payload for this message (e.g., JSON action response).
235
+ * Populated automatically when structured parsers run.
236
+ */
237
+ rawContent?: string;
238
+ /**
239
+ * LLM-specific content for API requests.
240
+ * When present, this is sent to the LLM instead of `content`.
241
+ *
242
+ * Priority for API payload:
243
+ * 1. `contentParts` (if present, used as-is for multi-modal)
244
+ * 2. `llmContent` (if present, sent as string)
245
+ * 3. `rawContent` (backward compatibility with structured parsers)
246
+ * 4. `content` (fallback - display content)
247
+ *
248
+ * The `content` field is always used for UI display.
249
+ *
250
+ * @example
251
+ * // Show full details to user, send summary to LLM
252
+ * {
253
+ * content: "**Product:** iPhone 15 Pro\n**Price:** $1,199\n**SKU:** IP15P-256",
254
+ * llmContent: "[Product search: iPhone 15 Pro, $1199]"
255
+ * }
256
+ */
257
+ llmContent?: string;
258
+ /**
259
+ * Text segment identity for chronological ordering.
260
+ * When present, identifies which text segment this message represents
261
+ * (e.g., "text_0", "text_1") for messages split at tool boundaries.
262
+ */
263
+ partId?: string;
264
+ /**
265
+ * Metadata for messages created during agent loop execution.
266
+ * Contains execution context like iteration number and turn ID.
267
+ */
268
+ agentMetadata?: AgentMessageMetadata;
269
+ /**
270
+ * Per-turn stop reason reported by the runtime on `agent_turn_complete`
271
+ * (agent-loop path) or the last `step_complete` for a prompt step
272
+ * (dispatch / flow path). Absent when the API did not report a value.
273
+ *
274
+ * When set to a non-natural value (`max_tool_calls`, `length`,
275
+ * `content_filter`, `error`), the widget renders an inline notice on
276
+ * the assistant bubble. See `config.copy.stopReasonNotice` to override
277
+ * the default copy.
278
+ */
279
+ stopReason?: StopReasonKind;
280
+ };
281
+
282
+ export type { StreamAnimationPlugin as S };
@@ -0,0 +1,282 @@
1
+ /**
2
+ * Text content part for multi-modal messages
3
+ */
4
+ type TextContentPart = {
5
+ type: 'text';
6
+ text: string;
7
+ };
8
+ /**
9
+ * Image content part for multi-modal messages
10
+ * Supports base64 data URIs or URLs
11
+ */
12
+ type ImageContentPart = {
13
+ type: 'image';
14
+ image: string;
15
+ mimeType?: string;
16
+ alt?: string;
17
+ };
18
+ /**
19
+ * File content part for multi-modal messages
20
+ * Supports PDF, TXT, DOCX, and other document types
21
+ */
22
+ type FileContentPart = {
23
+ type: 'file';
24
+ data: string;
25
+ mimeType: string;
26
+ filename: string;
27
+ };
28
+ /**
29
+ * Union type for all content part types
30
+ */
31
+ type ContentPart = TextContentPart | ImageContentPart | FileContentPart;
32
+ /**
33
+ * Metadata attached to messages created during agent execution.
34
+ */
35
+ type AgentMessageMetadata = {
36
+ executionId?: string;
37
+ iteration?: number;
38
+ turnId?: string;
39
+ agentName?: string;
40
+ /**
41
+ * When this message was produced by a step inside a nested flow executed
42
+ * as a tool, identifies the parent tool call id. Enables renderers to
43
+ * visually group or indent nested-flow output under its parent tool.
44
+ */
45
+ parentToolId?: string;
46
+ /**
47
+ * Nested flow step id that produced this message (e.g. a `send-stream`
48
+ * or `prompt` step inside the nested flow). Stable key for that step.
49
+ */
50
+ parentStepId?: string;
51
+ };
52
+ /**
53
+ * Context passed to plugin lifecycle hooks. Carries the live DOM references
54
+ * and resolved animation settings for the currently-streaming message.
55
+ */
56
+ type StreamAnimationContext = {
57
+ /** The `.persona-message-content` element owning the streamed text. */
58
+ container: HTMLElement;
59
+ /** The outer message bubble element. */
60
+ bubble: HTMLElement;
61
+ /** ID of the streaming message. */
62
+ messageId: string;
63
+ /** Read-only reference to the message being streamed. */
64
+ message: AgentWidgetMessage;
65
+ /** Effective `speed` from `streamAnimation.speed`. */
66
+ speed: number;
67
+ /** Effective `duration` from `streamAnimation.duration`. */
68
+ duration: number;
69
+ };
70
+ /**
71
+ * Pluggable stream animation. Third-party packages and inline registrations
72
+ * implement this interface to add custom reveal effects.
73
+ *
74
+ * Lifecycle:
75
+ * - When the widget mounts and detects a plugin (either passed via config or
76
+ * auto-registered in the IIFE bundle), it injects `styles` once into the
77
+ * widget's style host.
78
+ * - For each streaming assistant message whose `type` matches `name`, the
79
+ * widget applies `containerClass` / `bubbleClass`, wraps text per `wrap`,
80
+ * and — if `useCaret` is true — appends a blinking caret.
81
+ * - Hooks fire after the live DOM is morphed; plugins use stable element IDs
82
+ * and `data-preserve-animation` to safely mutate per-char or per-word spans
83
+ * without idiomorph clobbering in-flight work.
84
+ */
85
+ type StreamAnimationPlugin = {
86
+ /** Plugin identifier. Matches the `type` field in `streamAnimation`. */
87
+ name: string;
88
+ /** Class added to `.persona-message-content` while streaming. */
89
+ containerClass?: string;
90
+ /** Class added to the bubble element (e.g. a one-shot scale animation). */
91
+ bubbleClass?: string;
92
+ /** Wrap mode applied to text nodes during streaming. @default "none" */
93
+ wrap?: "none" | "char" | "word";
94
+ /**
95
+ * HTML tags whose descendant text is skipped during wrapping. Defaults to
96
+ * `["pre", "code", "a", "script", "style"]` — useful for keeping code
97
+ * blocks legible and link click-targets intact. Plugins that want to
98
+ * animate characters inside inline code (e.g. `glyph-cycle`) can narrow
99
+ * the list.
100
+ */
101
+ skipTags?: string[];
102
+ /** Append a blinking caret after the last rendered char/word. */
103
+ useCaret?: boolean;
104
+ /** CSS string injected into the widget style host on first activation. */
105
+ styles?: string;
106
+ /**
107
+ * Optional custom buffering strategy. Returns the portion of `content`
108
+ * that should be rendered during streaming. Use this for buffering
109
+ * schemes beyond the built-in `word` / `line` strategies.
110
+ */
111
+ bufferContent?: (content: string, message: AgentWidgetMessage) => string;
112
+ /**
113
+ * Fires once when the plugin is first activated inside a widget instance.
114
+ * Use this to set up MutationObservers or other long-lived listeners.
115
+ * Return an optional cleanup function that runs on widget destroy.
116
+ */
117
+ onAttach?: (root: HTMLElement | ShadowRoot) => (() => void) | void;
118
+ /** Fires after each render that reaches the live DOM. */
119
+ onAfterRender?: (ctx: StreamAnimationContext) => void;
120
+ /** Fires when a streamed message's `streaming` flag flips to false. */
121
+ onStreamComplete?: (ctx: StreamAnimationContext) => void;
122
+ /**
123
+ * Report whether the plugin still has in-flight animation work for a
124
+ * message. When `true`, the widget keeps rendering the message in its
125
+ * "streaming-animated" mode even after `message.streaming` flips false —
126
+ * preventing the final non-animated render from yanking the rug out from
127
+ * under unfinished per-char cycles or reveals.
128
+ */
129
+ isAnimating?: (message: AgentWidgetMessage) => boolean;
130
+ };
131
+ type AgentWidgetMessageRole = "user" | "assistant" | "system";
132
+ type AgentWidgetReasoning = {
133
+ id: string;
134
+ status: "pending" | "streaming" | "complete";
135
+ chunks: string[];
136
+ startedAt?: number;
137
+ completedAt?: number;
138
+ durationMs?: number;
139
+ };
140
+ type AgentWidgetToolCall = {
141
+ id: string;
142
+ name?: string;
143
+ status: "pending" | "running" | "complete";
144
+ args?: unknown;
145
+ chunks?: string[];
146
+ result?: unknown;
147
+ duration?: number;
148
+ startedAt?: number;
149
+ completedAt?: number;
150
+ durationMs?: number;
151
+ };
152
+ /**
153
+ * Represents a tool approval request in the chat conversation.
154
+ * Created when the agent requires human approval before executing a tool.
155
+ */
156
+ type AgentWidgetApproval = {
157
+ id: string;
158
+ status: "pending" | "approved" | "denied" | "timeout";
159
+ agentId: string;
160
+ executionId: string;
161
+ toolName: string;
162
+ toolType?: string;
163
+ description: string;
164
+ parameters?: unknown;
165
+ resolvedAt?: number;
166
+ };
167
+ type AgentWidgetMessageVariant = "assistant" | "reasoning" | "tool" | "approval";
168
+ /**
169
+ * Per-turn / per-step stop reason emitted by the runtime on
170
+ * `agent_turn_complete` and `step_complete` SSE events. The vocabulary is
171
+ * owned by the upstream Runtype API — do not extend without coordination.
172
+ *
173
+ * - `end_turn` — natural completion (no affordance needed)
174
+ * - `max_tool_calls` — agent loop tripped the configured tool-call ceiling
175
+ * - `length` — provider hit max output tokens
176
+ * - `content_filter` — provider content filter intervened
177
+ * - `error` — provider/runtime error (prefer existing error rendering)
178
+ * - `unknown` — explicitly reported but uninformative
179
+ *
180
+ * Absent (`undefined`) means "not reported" — distinct from `'unknown'`.
181
+ */
182
+ type StopReasonKind = 'end_turn' | 'max_tool_calls' | 'length' | 'content_filter' | 'error' | 'unknown';
183
+ /**
184
+ * Represents a message in the chat conversation.
185
+ *
186
+ * @property id - Unique message identifier
187
+ * @property role - Message role: "user", "assistant", or "system"
188
+ * @property content - Message text content (for display)
189
+ * @property contentParts - Original multi-modal content parts (for API requests)
190
+ * @property createdAt - ISO timestamp when message was created
191
+ * @property streaming - Whether message is still streaming (for assistant messages)
192
+ * @property variant - Message variant for assistant messages: "assistant", "reasoning", or "tool"
193
+ * @property sequence - Message ordering number
194
+ * @property reasoning - Reasoning data for assistant reasoning messages
195
+ * @property toolCall - Tool call data for assistant tool messages
196
+ * @property tools - Array of tool calls
197
+ * @property viaVoice - Set to `true` when a user message is sent via voice recognition.
198
+ * Useful for implementing voice-specific behaviors like auto-reactivation.
199
+ */
200
+ type AgentWidgetMessage = {
201
+ id: string;
202
+ role: AgentWidgetMessageRole;
203
+ content: string;
204
+ createdAt: string;
205
+ /**
206
+ * Original multi-modal content parts for this message.
207
+ * When present, this is sent to the API instead of `content`.
208
+ * The `content` field contains the text-only representation for display.
209
+ */
210
+ contentParts?: ContentPart[];
211
+ streaming?: boolean;
212
+ variant?: AgentWidgetMessageVariant;
213
+ sequence?: number;
214
+ reasoning?: AgentWidgetReasoning;
215
+ toolCall?: AgentWidgetToolCall;
216
+ tools?: AgentWidgetToolCall[];
217
+ /** Approval data for messages with variant "approval" */
218
+ approval?: AgentWidgetApproval;
219
+ viaVoice?: boolean;
220
+ /**
221
+ * Set to `true` on placeholder messages injected during Runtype voice processing.
222
+ * Use this in `messageTransform` to detect and customize voice processing placeholders.
223
+ *
224
+ * @example
225
+ * messageTransform: ({ text, message }) => {
226
+ * if (message.voiceProcessing && message.role === 'user') {
227
+ * return '<div class="my-voice-spinner">Transcribing...</div>';
228
+ * }
229
+ * return text;
230
+ * }
231
+ */
232
+ voiceProcessing?: boolean;
233
+ /**
234
+ * Raw structured payload for this message (e.g., JSON action response).
235
+ * Populated automatically when structured parsers run.
236
+ */
237
+ rawContent?: string;
238
+ /**
239
+ * LLM-specific content for API requests.
240
+ * When present, this is sent to the LLM instead of `content`.
241
+ *
242
+ * Priority for API payload:
243
+ * 1. `contentParts` (if present, used as-is for multi-modal)
244
+ * 2. `llmContent` (if present, sent as string)
245
+ * 3. `rawContent` (backward compatibility with structured parsers)
246
+ * 4. `content` (fallback - display content)
247
+ *
248
+ * The `content` field is always used for UI display.
249
+ *
250
+ * @example
251
+ * // Show full details to user, send summary to LLM
252
+ * {
253
+ * content: "**Product:** iPhone 15 Pro\n**Price:** $1,199\n**SKU:** IP15P-256",
254
+ * llmContent: "[Product search: iPhone 15 Pro, $1199]"
255
+ * }
256
+ */
257
+ llmContent?: string;
258
+ /**
259
+ * Text segment identity for chronological ordering.
260
+ * When present, identifies which text segment this message represents
261
+ * (e.g., "text_0", "text_1") for messages split at tool boundaries.
262
+ */
263
+ partId?: string;
264
+ /**
265
+ * Metadata for messages created during agent loop execution.
266
+ * Contains execution context like iteration number and turn ID.
267
+ */
268
+ agentMetadata?: AgentMessageMetadata;
269
+ /**
270
+ * Per-turn stop reason reported by the runtime on `agent_turn_complete`
271
+ * (agent-loop path) or the last `step_complete` for a prompt step
272
+ * (dispatch / flow path). Absent when the API did not report a value.
273
+ *
274
+ * When set to a non-natural value (`max_tool_calls`, `length`,
275
+ * `content_filter`, `error`), the widget renders an inline notice on
276
+ * the assistant bubble. See `config.copy.stopReasonNotice` to override
277
+ * the default copy.
278
+ */
279
+ stopReason?: StopReasonKind;
280
+ };
281
+
282
+ export type { StreamAnimationPlugin as S };
@@ -0,0 +1,107 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/animations/wipe.ts
21
+ var wipe_exports = {};
22
+ __export(wipe_exports, {
23
+ default: () => wipe_default,
24
+ wipe: () => wipe
25
+ });
26
+ module.exports = __toCommonJS(wipe_exports);
27
+
28
+ // src/utils/stream-animation.ts
29
+ var BUILTIN_PLUGINS = [
30
+ {
31
+ name: "typewriter",
32
+ containerClass: "persona-stream-typewriter",
33
+ wrap: "char",
34
+ useCaret: true
35
+ },
36
+ {
37
+ name: "pop-bubble",
38
+ bubbleClass: "persona-stream-pop",
39
+ wrap: "none"
40
+ },
41
+ {
42
+ name: "letter-rise",
43
+ containerClass: "persona-stream-letter-rise",
44
+ wrap: "char"
45
+ },
46
+ {
47
+ name: "word-fade",
48
+ containerClass: "persona-stream-word-fade",
49
+ wrap: "word"
50
+ }
51
+ ];
52
+ var globalRegistry = /* @__PURE__ */ new Map();
53
+ for (const plugin of BUILTIN_PLUGINS) globalRegistry.set(plugin.name, plugin);
54
+ var registerStreamAnimationPlugin = (plugin) => {
55
+ globalRegistry.set(plugin.name, plugin);
56
+ };
57
+
58
+ // src/animations/wipe.ts
59
+ var STYLES = `
60
+ @keyframes persona-stream-wipe {
61
+ from { -webkit-mask-position: 100% 0; mask-position: 100% 0; }
62
+ to { -webkit-mask-position: 0% 0; mask-position: 0% 0; }
63
+ }
64
+ [data-persona-root] .persona-stream-wipe .persona-stream-word {
65
+ -webkit-mask-image: linear-gradient(
66
+ 90deg,
67
+ black 0%,
68
+ black 45%,
69
+ transparent 55%,
70
+ transparent 100%
71
+ );
72
+ mask-image: linear-gradient(
73
+ 90deg,
74
+ black 0%,
75
+ black 45%,
76
+ transparent 55%,
77
+ transparent 100%
78
+ );
79
+ -webkit-mask-size: 200% 100%;
80
+ mask-size: 200% 100%;
81
+ -webkit-mask-position: 100% 0;
82
+ mask-position: 100% 0;
83
+ -webkit-mask-repeat: no-repeat;
84
+ mask-repeat: no-repeat;
85
+ animation: persona-stream-wipe calc(var(--persona-stream-step, 120ms) * 3)
86
+ ease-out forwards;
87
+ }
88
+ @media (prefers-reduced-motion: reduce) {
89
+ [data-persona-root] .persona-stream-wipe .persona-stream-word {
90
+ animation: none !important;
91
+ -webkit-mask-image: none !important;
92
+ mask-image: none !important;
93
+ }
94
+ }
95
+ `.trim();
96
+ var wipe = {
97
+ name: "wipe",
98
+ containerClass: "persona-stream-wipe",
99
+ wrap: "word",
100
+ styles: STYLES
101
+ };
102
+ registerStreamAnimationPlugin(wipe);
103
+ var wipe_default = wipe;
104
+ // Annotate the CommonJS export names for ESM import in node:
105
+ 0 && (module.exports = {
106
+ wipe
107
+ });
@@ -0,0 +1,5 @@
1
+ import { S as StreamAnimationPlugin } from './types-HPZY7oAI.cjs';
2
+
3
+ declare const wipe: StreamAnimationPlugin;
4
+
5
+ export { wipe as default, wipe };
@@ -0,0 +1,5 @@
1
+ import { S as StreamAnimationPlugin } from './types-HPZY7oAI.js';
2
+
3
+ declare const wipe: StreamAnimationPlugin;
4
+
5
+ export { wipe as default, wipe };