@runtypelabs/persona 4.32.2 → 4.34.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.
- package/dist/activity-ui.d.cts +3 -15
- package/dist/activity-ui.d.ts +3 -15
- package/dist/animations/glyph-cycle.d.cts +1 -3
- package/dist/animations/glyph-cycle.d.ts +1 -3
- package/dist/animations/wipe.d.cts +1 -3
- package/dist/animations/wipe.d.ts +1 -3
- package/dist/approval-ui.cjs +2 -2
- package/dist/approval-ui.d.cts +3 -15
- package/dist/approval-ui.d.ts +3 -15
- package/dist/approval-ui.js +1 -1
- package/dist/artifacts-ui.cjs +1 -1
- package/dist/artifacts-ui.d.cts +3 -21
- package/dist/artifacts-ui.d.ts +3 -21
- package/dist/background-runtime.d.cts +2 -3
- package/dist/background-runtime.d.ts +2 -3
- package/dist/{chunk-BbXc58OA.js → chunk-6CUrH_jm.js} +1 -1
- package/dist/{chunk-B_H0l3u2.js → chunk-BRM3bHcJ.js} +1 -1
- package/dist/{chunk-DNdeIFJ6.js → chunk-Brdx4NCz.js} +1 -1
- package/dist/chunk-C-rux8Q9.js +1 -0
- package/dist/{chunk-Ds_twaZn.js → chunk-C4v-HNhS.js} +1 -1
- package/dist/{chunk-Bkma5hIU.js → chunk-CE4seJxF.js} +1 -1
- package/dist/chunk-CEPM3FOp.js +1 -0
- package/dist/{chunk-BpjtKnGI.js → chunk-CV8EPIhT.js} +1 -1
- package/dist/{chunk-DVZ8ri1z.js → chunk-CWzHNuVK.js} +1 -1
- package/dist/{chunk-B3l7TOOv.js → chunk-CYpt7PsO.js} +1 -1
- package/dist/{chunk-2FnmZ9AA.js → chunk-Csr59G5V.js} +1 -1
- package/dist/{chunk-B9Zu-wrk.js → chunk-CxNPSY-b.js} +1 -1
- package/dist/{chunk-UWMfWW2a.js → chunk-D1G8tgYc.js} +1 -1
- package/dist/{chunk-DTGvDx8o.js → chunk-Dj2a9f9w.js} +1 -1
- package/dist/chunk-Dqa_GOcj.js +1 -0
- package/dist/chunk-DsWv3EGF.js +1 -0
- package/dist/{chunk-C7-m0EmI.js → chunk-NUNdcnAZ.js} +1 -1
- package/dist/{chunk-D0tcIZJM.js → chunk-YMkMvAsa.js} +2 -2
- package/dist/{chunk-C-EHtpbB.js → chunk-h5aOI_Pa.js} +1 -1
- package/dist/chunk-i4qGOJAL.js +1 -0
- package/dist/chunk-kizhspe5.js +1 -0
- package/dist/client-dispatch.js +1 -1
- package/dist/client-history.js +1 -1
- package/dist/client-stream.js +1 -1
- package/dist/{code-generators-DqauYyfX.d.cts → code-generators-DPAqTcAz.d.cts} +0 -2
- package/dist/{code-generators-DqauYyfX.d.ts → code-generators-DPAqTcAz.d.ts} +0 -2
- package/dist/codegen.cjs +1 -1
- package/dist/codegen.d.cts +1 -1
- package/dist/codegen.d.ts +1 -1
- package/dist/codegen.js +1 -1
- package/dist/composer-actions-runtime.cjs +1 -1
- package/dist/composer-actions-runtime.d.cts +4 -20
- package/dist/composer-actions-runtime.d.ts +4 -20
- package/dist/composer-actions-runtime.js +1 -1
- package/dist/{composer-input-dwg_o9Z-.d.ts → composer-input-i_FiUp6J.d.cts} +1 -7
- package/dist/{composer-input-dwg_o9Z-.d.cts → composer-input-i_FiUp6J.d.ts} +1 -7
- package/dist/{composer-store-Dw7Zbqxr.d.ts → composer-store-DhGNgG7Z.d.cts} +1 -3
- package/dist/{composer-store-Dw7Zbqxr.d.cts → composer-store-DhGNgG7Z.d.ts} +1 -3
- package/dist/config-diagnostics.d.cts +0 -2
- package/dist/config-diagnostics.d.ts +0 -2
- package/dist/{context-mention-manager-D2p0-JH-.d.ts → context-mention-manager-DL-xwGfL.d.cts} +2 -6
- package/dist/{context-mention-manager-D2p0-JH-.d.cts → context-mention-manager-DL-xwGfL.d.ts} +2 -6
- package/dist/context-mentions-inline.cjs +1 -1
- package/dist/context-mentions-inline.d.cts +2 -4
- package/dist/context-mentions-inline.d.ts +2 -4
- package/dist/context-mentions-inline.js +1 -1
- package/dist/context-mentions.cjs +1 -1
- package/dist/context-mentions.d.cts +3 -9
- package/dist/context-mentions.d.ts +3 -9
- package/dist/{defaults-CjX0kKzb.d.ts → defaults-Bga2Xrsp.d.cts} +2 -5
- package/dist/{defaults-CjX0kKzb.d.cts → defaults-Bga2Xrsp.d.ts} +2 -5
- package/dist/dictation-runtime.cjs +1 -1
- package/dist/dictation-runtime.d.cts +4 -13
- package/dist/dictation-runtime.d.ts +4 -13
- package/dist/dictation-runtime.js +1 -1
- package/dist/{dom-context-DHTabIn7.d.ts → dom-context-Bw-_9Evh.d.cts} +0 -2
- package/dist/{dom-context-DHTabIn7.d.cts → dom-context-Bw-_9Evh.d.ts} +0 -2
- package/dist/event-stream-view.cjs +1 -1
- package/dist/event-stream-view.d.cts +3 -16
- package/dist/event-stream-view.d.ts +3 -16
- package/dist/{fallback-speech-engine-DmF7MczI.d.ts → fallback-speech-engine-kLdyPcmk.d.cts} +1 -3
- package/dist/{fallback-speech-engine-DmF7MczI.d.cts → fallback-speech-engine-kLdyPcmk.d.ts} +1 -3
- package/dist/{feature-preferences-CVFDt9Xf.d.ts → feature-preferences-CmwZGKrf.d.cts} +1 -5
- package/dist/{feature-preferences-CVFDt9Xf.d.cts → feature-preferences-CmwZGKrf.d.ts} +1 -5
- package/dist/forms-ui.d.cts +2 -4
- package/dist/forms-ui.d.ts +2 -4
- package/dist/{history-confirm-dialog-DJEXsTyE.d.cts → history-confirm-dialog-i46-lPN_.d.cts} +2 -14
- package/dist/{history-confirm-dialog-DJEXsTyE.d.ts → history-confirm-dialog-i46-lPN_.d.ts} +2 -14
- package/dist/history-shell.cjs +1 -1
- package/dist/history-shell.d.cts +8 -27
- package/dist/history-shell.d.ts +8 -27
- package/dist/history-shell.js +1 -1
- package/dist/history-view.d.cts +1 -1
- package/dist/history-view.d.ts +1 -1
- package/dist/icons-extra.cjs +1 -1
- package/dist/icons-extra.d.cts +0 -2
- package/dist/icons-extra.d.ts +0 -2
- package/dist/index.cjs +44 -44
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +11 -11
- package/dist/index.d.ts +11 -11
- package/dist/index.global.js +1 -1
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +46 -46
- package/dist/index.js.map +1 -1
- package/dist/install.global.js +1 -1
- package/dist/install.global.js.map +1 -1
- package/dist/launcher.global.js +2 -2
- package/dist/launcher.global.js.map +1 -1
- package/dist/{loading-label-runtime-loader-CPxnoaoi.d.ts → loading-label-runtime-loader-Ccr3ETd3.d.cts} +1 -3
- package/dist/{loading-label-runtime-loader-CPxnoaoi.d.cts → loading-label-runtime-loader-Ccr3ETd3.d.ts} +1 -3
- package/dist/loading-label-runtime.cjs +1 -1
- package/dist/loading-label-runtime.d.cts +1 -1
- package/dist/loading-label-runtime.d.ts +1 -1
- package/dist/loading-label-runtime.js +1 -1
- package/dist/markdown-parsers.js +1 -1
- package/dist/{message-bubble-CkZGlCLC.d.ts → message-bubble-C6AVaH7f.d.cts} +21 -4
- package/dist/{message-bubble-CkZGlCLC.d.cts → message-bubble-C6AVaH7f.d.ts} +21 -4
- package/dist/{plugin-kit-C1mRjLgW.d.cts → plugin-kit-BVggqE3C.d.cts} +0 -2
- package/dist/{plugin-kit-C1mRjLgW.d.ts → plugin-kit-BVggqE3C.d.ts} +0 -2
- package/dist/plugin-kit.d.cts +1 -1
- package/dist/plugin-kit.d.ts +1 -1
- package/dist/preferences-runtime.cjs +1 -1
- package/dist/preferences-runtime.d.cts +1 -1
- package/dist/preferences-runtime.d.ts +1 -1
- package/dist/preferences-runtime.js +1 -1
- package/dist/{preview-DdUvoLb4.d.cts → preview-BMdRffo4.d.cts} +2 -6
- package/dist/{preview-DdUvoLb4.d.ts → preview-BMdRffo4.d.ts} +2 -6
- package/dist/{registry-Dz4iHNST.d.ts → registry-B16l8s1b.d.cts} +1 -8
- package/dist/{registry-Dz4iHNST.d.cts → registry-B16l8s1b.d.ts} +1 -8
- package/dist/{session-Baxp9iRK.d.cts → session-CtZHe7fc.d.cts} +10 -93
- package/dist/{session-Baxp9iRK.d.ts → session-CtZHe7fc.d.ts} +10 -93
- package/dist/session-reconnect.d.cts +2 -4
- package/dist/session-reconnect.d.ts +2 -4
- package/dist/smart-dom-reader.d.cts +2 -8
- package/dist/smart-dom-reader.d.ts +2 -8
- package/dist/testing.d.cts +0 -2
- package/dist/testing.d.ts +0 -2
- package/dist/theme-editor-preview.cjs +42 -42
- package/dist/theme-editor-preview.d.cts +1 -1
- package/dist/theme-editor-preview.d.ts +1 -1
- package/dist/theme-editor-preview.js +25 -25
- package/dist/theme-editor.cjs +25 -5
- package/dist/theme-editor.d.cts +2 -22
- package/dist/theme-editor.d.ts +2 -22
- package/dist/theme-editor.js +1 -1
- package/dist/theme-reference.cjs +1 -1
- package/dist/theme-reference.d.cts +4 -4
- package/dist/theme-reference.d.ts +4 -4
- package/dist/theme-reference.js +1 -1
- package/dist/{tool-loading-animation-un3kA5Ur.d.ts → tool-loading-animation-D2cyFvmM.d.cts} +1 -7
- package/dist/{tool-loading-animation-un3kA5Ur.d.cts → tool-loading-animation-D2cyFvmM.d.ts} +1 -7
- package/dist/{tooltip-BkW-8MnD.d.cts → tooltip-DbXkAuJL.d.cts} +0 -2
- package/dist/{tooltip-BkW-8MnD.d.ts → tooltip-DbXkAuJL.d.ts} +0 -2
- package/dist/{turn-activity-ui-BGNhtMcH.d.cts → turn-activity-ui-Do1Nd-Ow.d.cts} +2 -12
- package/dist/{turn-activity-ui-BGNhtMcH.d.ts → turn-activity-ui-Do1Nd-Ow.d.ts} +2 -12
- package/dist/turn-activity-ui.d.cts +1 -1
- package/dist/turn-activity-ui.d.ts +1 -1
- package/dist/{types-BOZHQIk0.d.cts → types-BC7MRxO5.d.cts} +167 -36
- package/dist/{types-BOZHQIk0.d.ts → types-BC7MRxO5.d.ts} +167 -36
- package/dist/ui-extras.js +3 -3
- package/dist/voice-client-tools.d.cts +1 -3
- package/dist/voice-client-tools.d.ts +1 -3
- package/dist/voice-runtime.cjs +1 -1
- package/dist/voice-runtime.d.cts +2 -12
- package/dist/voice-runtime.d.ts +2 -12
- package/dist/voice-runtime.js +2 -2
- package/dist/voice-worklet-player.d.cts +2 -6
- package/dist/voice-worklet-player.d.ts +2 -6
- package/dist/{webmcp-runtime-entry-DuAG1_yF.d.ts → webmcp-runtime-entry-B8g46vS0.d.cts} +1 -5
- package/dist/{webmcp-runtime-entry-DuAG1_yF.d.cts → webmcp-runtime-entry-B8g46vS0.d.ts} +1 -5
- package/dist/webmcp-runtime.d.cts +1 -1
- package/dist/webmcp-runtime.d.ts +1 -1
- package/dist/widget.css +1 -1
- package/package.json +4 -4
- package/src/client-dispatch.ts +69 -16
- package/src/client.operator-role.test.ts +217 -0
- package/src/components/event-stream-view.test.ts +5 -0
- package/src/components/message-bubble.test.ts +169 -0
- package/src/components/message-bubble.ts +123 -34
- package/src/components/scroll-to-bottom.test.ts +135 -0
- package/src/components/scroll-to-bottom.ts +50 -13
- package/src/components/user-message-collapse.ts +117 -0
- package/src/defaults-parity.test.ts +14 -0
- package/src/defaults.ts +6 -0
- package/src/index-core.ts +7 -0
- package/src/session.resubmit-from.test.ts +27 -0
- package/src/session.test.ts +10 -0
- package/src/session.ts +8 -5
- package/src/styles/widget.css +79 -1
- package/src/theme-reference.ts +5 -3
- package/src/types/theme.ts +50 -0
- package/src/types.ts +120 -11
- package/src/ui.ask-user-question-plugin.test.ts +154 -0
- package/src/ui.operator-role.test.ts +336 -0
- package/src/ui.scroll-additive.test.ts +219 -117
- package/src/ui.scroll.test.ts +176 -13
- package/src/ui.ts +267 -119
- package/src/ui.turn-activity.test.ts +7 -7
- package/src/ui.user-message-collapse.test.ts +540 -0
- package/src/utils/__snapshots__/tokens-parity.test.ts.snap +236 -0
- package/src/utils/auto-follow.test.ts +0 -38
- package/src/utils/auto-follow.ts +0 -35
- package/src/utils/brand.test.ts +14 -0
- package/src/utils/brand.ts +8 -4
- package/src/utils/history-messages.test.ts +30 -0
- package/src/utils/history-messages.ts +26 -8
- package/src/utils/message-fingerprint.ts +4 -0
- package/src/utils/resubmit-turn.test.ts +13 -0
- package/src/utils/resubmit-turn.ts +12 -1
- package/src/utils/theme.test.ts +23 -0
- package/src/utils/tokens.ts +47 -0
- package/src/welcome.test.ts +16 -0
- package/src/welcome.ts +10 -2
- package/dist/chunk-BNE40cEG.js +0 -1
- package/dist/chunk-Bz9jAgba.js +0 -1
- package/dist/chunk-CVMIncEY.js +0 -1
- package/dist/chunk-CdpVP6LZ.js +0 -1
- package/dist/chunk-CjkechxR.js +0 -1
- package/dist/chunk-DgZZqy14.js +0 -1
package/src/types.ts
CHANGED
|
@@ -616,7 +616,7 @@ export type AgentWidgetReplayedToolResult = {
|
|
|
616
616
|
* from its own stored transcript there.
|
|
617
617
|
*/
|
|
618
618
|
export type AgentWidgetRequestPayloadMessage = {
|
|
619
|
-
role:
|
|
619
|
+
role: AgentWidgetModelMessageRole | "tool";
|
|
620
620
|
content: MessageContent;
|
|
621
621
|
createdAt: string;
|
|
622
622
|
/** Optional assistant phase for backend adapters that replay provider history. */
|
|
@@ -1123,6 +1123,21 @@ export type AgentMessageMetadata = {
|
|
|
1123
1123
|
};
|
|
1124
1124
|
};
|
|
1125
1125
|
|
|
1126
|
+
/** Ordinary model context only; the serializer owns tool-call/result pairing. */
|
|
1127
|
+
export type AgentWidgetModelMessageProjection = Pick<AgentWidgetRequestPayloadMessage, "content" | "createdAt" | "phase"> & {
|
|
1128
|
+
role: AgentWidgetModelMessageRole;
|
|
1129
|
+
};
|
|
1130
|
+
|
|
1131
|
+
/** Synchronous, per-message conversion before any dispatch transport serializes history. */
|
|
1132
|
+
export type AgentWidgetModelMessageTransform = (context: {
|
|
1133
|
+
/** Full UI transcript entry, including identity and human provenance. */
|
|
1134
|
+
message: Readonly<AgentWidgetMessage>;
|
|
1135
|
+
/** Resolved model content: contentParts > llmContent > rawContent > content. */
|
|
1136
|
+
content: MessageContent;
|
|
1137
|
+
/** Normal model projection; null for operator messages. Return null to omit. */
|
|
1138
|
+
modelMessage: AgentWidgetModelMessageProjection | null;
|
|
1139
|
+
}) => AgentWidgetModelMessageProjection | null;
|
|
1140
|
+
|
|
1126
1141
|
export type AgentWidgetRequestMiddlewareContext = {
|
|
1127
1142
|
payload: AgentWidgetRequestPayload;
|
|
1128
1143
|
config: AgentWidgetConfig;
|
|
@@ -1391,7 +1406,7 @@ export type AgentWidgetMessageActionsConfig = {
|
|
|
1391
1406
|
};
|
|
1392
1407
|
|
|
1393
1408
|
/** Which roles a custom message action appears on. */
|
|
1394
|
-
export type AgentWidgetCustomMessageActionRole = "user" | "assistant";
|
|
1409
|
+
export type AgentWidgetCustomMessageActionRole = "user" | "assistant" | "operator";
|
|
1395
1410
|
|
|
1396
1411
|
/** One host-contributed message action. */
|
|
1397
1412
|
export type AgentWidgetCustomMessageAction = {
|
|
@@ -2213,10 +2228,13 @@ export type AgentWidgetArtifactsFeature = {
|
|
|
2213
2228
|
*
|
|
2214
2229
|
* - `"anchor-top"` (default): on send, scroll the user's message near the top
|
|
2215
2230
|
* of the viewport and hold it there while the response streams in beneath it
|
|
2216
|
-
* (ChatGPT-style).
|
|
2217
|
-
*
|
|
2218
|
-
*
|
|
2219
|
-
*
|
|
2231
|
+
* (ChatGPT-style). The anchor holds for the whole reply, even when the
|
|
2232
|
+
* message is taller than the viewport or tool calls push the answer below
|
|
2233
|
+
* the fold, until the reader scrolls away, jumps to the latest content with
|
|
2234
|
+
* the scroll-to-bottom control, or sends again. When a turn has no user send
|
|
2235
|
+
* to anchor to (a proactive greeting, an injected assistant message, a
|
|
2236
|
+
* resubmit, or first-load streaming), it falls back to `"follow"` for that
|
|
2237
|
+
* turn so content never streams in off-screen.
|
|
2220
2238
|
* - `"follow"`: keep the newest content pinned to the bottom of the viewport,
|
|
2221
2239
|
* pausing when the user scrolls up and resuming when they return to the
|
|
2222
2240
|
* bottom. This was the default before 4.x.
|
|
@@ -2305,7 +2323,8 @@ export type AgentWidgetScrollBehaviorFeature = {
|
|
|
2305
2323
|
|
|
2306
2324
|
/** Decorative glyph state. Hidden glyphs should pause host-owned animation. */
|
|
2307
2325
|
export type AgentWidgetScrollToBottomIconState = {
|
|
2308
|
-
|
|
2326
|
+
/** `"approval-below"`: a pending approval is below the fold and the turn waits on it. */
|
|
2327
|
+
activity: "idle" | "generating-below" | "approval-below";
|
|
2309
2328
|
visible: boolean;
|
|
2310
2329
|
hovered: boolean;
|
|
2311
2330
|
focused: boolean;
|
|
@@ -2345,6 +2364,15 @@ export type AgentWidgetScrollToBottomFeature = {
|
|
|
2345
2364
|
* @default ""
|
|
2346
2365
|
*/
|
|
2347
2366
|
label?: string;
|
|
2367
|
+
/**
|
|
2368
|
+
* Label shown while a pending approval sits below the fold. The control
|
|
2369
|
+
* widens to a labelled pill with the approval's shield glyph, and the turn
|
|
2370
|
+
* stays put until the reader jumps (anchor-top never scrolls them to it).
|
|
2371
|
+
* Styled by `theme.components.scrollToBottom.approval`. Set to an empty
|
|
2372
|
+
* string to keep the regular control.
|
|
2373
|
+
* @default "Approval needed"
|
|
2374
|
+
*/
|
|
2375
|
+
approvalLabel?: string;
|
|
2348
2376
|
/** Glyph while a live response is arriving below. V4 defaults to arrow; V5 to dots. */
|
|
2349
2377
|
streamingIndicator?: "dots" | "arrow";
|
|
2350
2378
|
/** Visibility transition. V4 defaults to none; V5 to fade. Honors reduced motion. */
|
|
@@ -2773,6 +2801,31 @@ export type AgentWidgetStreamAnimationFeature = {
|
|
|
2773
2801
|
plugins?: Record<string, StreamAnimationPlugin>;
|
|
2774
2802
|
};
|
|
2775
2803
|
|
|
2804
|
+
/**
|
|
2805
|
+
* Collapse long user messages behind a "Show more" / "Show less" toggle.
|
|
2806
|
+
* Only the built-in user bubble collapses; `layout.messages.renderUserMessage`
|
|
2807
|
+
* and plugin `renderMessage` output is left untouched.
|
|
2808
|
+
*/
|
|
2809
|
+
export type AgentWidgetUserMessageCollapseFeature = {
|
|
2810
|
+
/**
|
|
2811
|
+
* Clip a user bubble whose rendered content (text, markdown, code,
|
|
2812
|
+
* attachments) is taller than `maxHeight`, with a bottom fade and a real
|
|
2813
|
+
* toggle button. The full message stays in the DOM, so find-in-page, copy,
|
|
2814
|
+
* selection and screen readers still reach it. Interim voice transcripts
|
|
2815
|
+
* stay expanded and collapse once final. A reader's toggle is remembered
|
|
2816
|
+
* per message for the life of the widget.
|
|
2817
|
+
* @default false (`true` under `future.v5Defaults`)
|
|
2818
|
+
*/
|
|
2819
|
+
enabled?: boolean;
|
|
2820
|
+
/**
|
|
2821
|
+
* Collapsed height in px. Content within about two lines (48px) of the
|
|
2822
|
+
* limit is left expanded, so the toggle never hides just a line or two.
|
|
2823
|
+
* The default shows about ten lines of bubble text.
|
|
2824
|
+
* @default 240
|
|
2825
|
+
*/
|
|
2826
|
+
maxHeight?: number;
|
|
2827
|
+
};
|
|
2828
|
+
|
|
2776
2829
|
export type AgentWidgetFeatureFlags = {
|
|
2777
2830
|
showReasoning?: boolean;
|
|
2778
2831
|
showToolCalls?: boolean;
|
|
@@ -2789,6 +2842,8 @@ export type AgentWidgetFeatureFlags = {
|
|
|
2789
2842
|
scrollToBottom?: AgentWidgetScrollToBottomFeature;
|
|
2790
2843
|
/** Transcript scroll behavior during streamed responses. */
|
|
2791
2844
|
scrollBehavior?: AgentWidgetScrollBehaviorFeature;
|
|
2845
|
+
/** "Show more" collapse for long user messages. Off by default; on under `future.v5Defaults`. */
|
|
2846
|
+
userMessageCollapse?: AgentWidgetUserMessageCollapseFeature;
|
|
2792
2847
|
/** Collapsed transcript behavior for tool call rows. */
|
|
2793
2848
|
toolCallDisplay?: AgentWidgetToolCallDisplayFeature;
|
|
2794
2849
|
/** Collapsed transcript behavior for reasoning rows. */
|
|
@@ -7191,6 +7246,11 @@ export type AgentWidgetAvatarConfig = {
|
|
|
7191
7246
|
userAvatar?: string;
|
|
7192
7247
|
/** URL or emoji for assistant avatar */
|
|
7193
7248
|
assistantAvatar?: string;
|
|
7249
|
+
/**
|
|
7250
|
+
* URL or emoji for operator (human takeover) avatar. Defaults to the letter
|
|
7251
|
+
* "O" on a neutral fill.
|
|
7252
|
+
*/
|
|
7253
|
+
operatorAvatar?: string;
|
|
7194
7254
|
};
|
|
7195
7255
|
|
|
7196
7256
|
/**
|
|
@@ -7246,7 +7306,10 @@ export type AgentWidgetMessageLayoutConfig = {
|
|
|
7246
7306
|
groupConsecutive?: boolean;
|
|
7247
7307
|
/** Width behavior for user-authored message rows */
|
|
7248
7308
|
user?: AgentWidgetMessageRoleLayout;
|
|
7249
|
-
/**
|
|
7309
|
+
/**
|
|
7310
|
+
* Width behavior for assistant-authored message rows and assistant UI
|
|
7311
|
+
* variants. Operator rows sit on the same side and use it too.
|
|
7312
|
+
*/
|
|
7250
7313
|
assistant?: AgentWidgetMessageRoleLayout;
|
|
7251
7314
|
/**
|
|
7252
7315
|
* Custom renderer for user messages
|
|
@@ -8398,6 +8461,8 @@ export type AgentWidgetConfig = {
|
|
|
8398
8461
|
*/
|
|
8399
8462
|
getHeaders?: AgentWidgetHeadersFunction;
|
|
8400
8463
|
copy?: {
|
|
8464
|
+
/** Visible and accessible label for human operator replies. @default "Human operator" */
|
|
8465
|
+
operatorLabel?: string;
|
|
8401
8466
|
/** @deprecated Use `welcome.title`. */
|
|
8402
8467
|
welcomeTitle?: string;
|
|
8403
8468
|
/** @deprecated Use `welcome.subtitle`. */
|
|
@@ -8408,6 +8473,10 @@ export type AgentWidgetConfig = {
|
|
|
8408
8473
|
sendButtonLabel?: string;
|
|
8409
8474
|
/** Button label shown in text mode while a response is streaming. Default: "Stop". */
|
|
8410
8475
|
stopButtonLabel?: string;
|
|
8476
|
+
/** Toggle label on a collapsed long user message (`features.userMessageCollapse`). @default "Show more" */
|
|
8477
|
+
showMoreLabel?: string;
|
|
8478
|
+
/** Toggle label on an expanded long user message (`features.userMessageCollapse`). @default "Show less" */
|
|
8479
|
+
showLessLabel?: string;
|
|
8411
8480
|
/**
|
|
8412
8481
|
* When false, the welcome / intro card is not shown above the message list.
|
|
8413
8482
|
* @deprecated Use `welcome.variant: "none"`.
|
|
@@ -8590,6 +8659,16 @@ export type AgentWidgetConfig = {
|
|
|
8590
8659
|
* See `docs/context-mentions-plan.md`.
|
|
8591
8660
|
*/
|
|
8592
8661
|
contextMentions?: AgentWidgetContextMentionConfig;
|
|
8662
|
+
/**
|
|
8663
|
+
* Synchronous model-context conversion for each nonempty conversation entry.
|
|
8664
|
+
* Runs on proxy, agent and client-token dispatch, after local-only notices and
|
|
8665
|
+
* voice captions are excluded. By default operator messages are omitted;
|
|
8666
|
+
* stateless adapters can explicitly map their historical human contributions
|
|
8667
|
+
* into supported model roles. Do not replay contributions already owned by
|
|
8668
|
+
* server history. This does not authorize steering, takeover or tool approval.
|
|
8669
|
+
* Invalid return values fail dispatch. See docs/MESSAGE-INJECTION.md.
|
|
8670
|
+
*/
|
|
8671
|
+
modelMessageTransform?: AgentWidgetModelMessageTransform;
|
|
8593
8672
|
requestMiddleware?: AgentWidgetRequestMiddleware;
|
|
8594
8673
|
actionParsers?: AgentWidgetActionParser[];
|
|
8595
8674
|
actionHandlers?: AgentWidgetActionHandler[];
|
|
@@ -9093,7 +9172,25 @@ type ConfigPatch<T> = T extends (...args: never[]) => unknown
|
|
|
9093
9172
|
? { [K in keyof T]?: ConfigPatch<T[K]> }
|
|
9094
9173
|
: T;
|
|
9095
9174
|
|
|
9096
|
-
|
|
9175
|
+
/**
|
|
9176
|
+
* Who authored a message.
|
|
9177
|
+
*
|
|
9178
|
+
* - `user`: the end user.
|
|
9179
|
+
* - `assistant`: the agent (model output).
|
|
9180
|
+
* - `system`: context for the model, rendered like an assistant row.
|
|
9181
|
+
* - `operator`: a human speaking on the agent's side of the conversation, such
|
|
9182
|
+
* as a support agent who has taken over the thread. It renders on the
|
|
9183
|
+
* assistant's side with its own bubble style (`theme.components.message.operator`).
|
|
9184
|
+
* Operator messages are omitted from model requests by default. A stateless
|
|
9185
|
+
* adapter can explicitly convert them with `modelMessageTransform`.
|
|
9186
|
+
*/
|
|
9187
|
+
export type AgentWidgetMessageRole = "user" | "assistant" | "system" | "operator";
|
|
9188
|
+
|
|
9189
|
+
/**
|
|
9190
|
+
* Roles that reach a model request. Human operator UI entries must be explicitly
|
|
9191
|
+
* converted to a supported model role by an adapter.
|
|
9192
|
+
*/
|
|
9193
|
+
export type AgentWidgetModelMessageRole = Exclude<AgentWidgetMessageRole, "operator">;
|
|
9097
9194
|
|
|
9098
9195
|
export type AgentWidgetReasoning = {
|
|
9099
9196
|
id: string;
|
|
@@ -9216,11 +9313,18 @@ export type AgentWidgetTurnActivityConfig = {
|
|
|
9216
9313
|
}) => HTMLElement | string | null | undefined;
|
|
9217
9314
|
};
|
|
9218
9315
|
|
|
9316
|
+
/** Display provenance, supplied by the host; never an authorization credential. */
|
|
9317
|
+
export type AgentWidgetMessageAuthor = {
|
|
9318
|
+
id?: string;
|
|
9319
|
+
displayName?: string;
|
|
9320
|
+
kind?: "human" | "ai" | "system";
|
|
9321
|
+
};
|
|
9322
|
+
|
|
9219
9323
|
/**
|
|
9220
9324
|
* Represents a message in the chat conversation.
|
|
9221
9325
|
*
|
|
9222
9326
|
* @property id - Unique message identifier
|
|
9223
|
-
* @property role - Message role: "user", "assistant", or "
|
|
9327
|
+
* @property role - Message role: "user", "assistant", "system", or "operator"
|
|
9224
9328
|
* @property content - Message text content (for display)
|
|
9225
9329
|
* @property contentParts - Original multi-modal content parts (for API requests)
|
|
9226
9330
|
* @property createdAt - ISO timestamp when message was created
|
|
@@ -9234,6 +9338,8 @@ export type AgentWidgetTurnActivityConfig = {
|
|
|
9234
9338
|
* Useful for implementing voice-specific behaviors like auto-reactivation.
|
|
9235
9339
|
*/
|
|
9236
9340
|
export type AgentWidgetMessage = {
|
|
9341
|
+
/** Preserved by injection, history and persistence; not sent to models automatically. */
|
|
9342
|
+
author?: AgentWidgetMessageAuthor;
|
|
9237
9343
|
/** Opt-in whole-turn presentation metadata. Does not change model-visible content. */
|
|
9238
9344
|
turnActivity?: AgentWidgetTurnActivity;
|
|
9239
9345
|
id: string;
|
|
@@ -9388,10 +9494,13 @@ export type AgentWidgetMessage = {
|
|
|
9388
9494
|
* }
|
|
9389
9495
|
*/
|
|
9390
9496
|
export type InjectMessageOptions = {
|
|
9497
|
+
/** Host-supplied display provenance. Does not grant model or backend authority. */
|
|
9498
|
+
author?: AgentWidgetMessageAuthor;
|
|
9391
9499
|
/** Mark assistant content as dispatch failure detail for `errorDisplay`. */
|
|
9392
9500
|
dispatchError?: boolean;
|
|
9393
9501
|
/**
|
|
9394
|
-
* Message role: "assistant", "user", or "
|
|
9502
|
+
* Message role: "assistant", "user", "system", or "operator". Operator
|
|
9503
|
+
* messages are omitted from requests unless modelMessageTransform converts them.
|
|
9395
9504
|
*/
|
|
9396
9505
|
role: AgentWidgetMessageRole;
|
|
9397
9506
|
|
|
@@ -689,3 +689,157 @@ describe("renderAskUserQuestion plugin hook", () => {
|
|
|
689
689
|
controller.destroy();
|
|
690
690
|
});
|
|
691
691
|
});
|
|
692
|
+
|
|
693
|
+
describe("typing indicator while ask_user_question arguments stream", () => {
|
|
694
|
+
afterEach(() => {
|
|
695
|
+
document.body.innerHTML = "";
|
|
696
|
+
if (typeof localStorage !== "undefined") localStorage.clear();
|
|
697
|
+
vi.restoreAllMocks();
|
|
698
|
+
vi.unstubAllGlobals();
|
|
699
|
+
});
|
|
700
|
+
|
|
701
|
+
// Streaming transcript updates render once per animation frame; queue the
|
|
702
|
+
// frames so each injection can be rendered synchronously.
|
|
703
|
+
let frames = new Map<number, (time: number) => void>();
|
|
704
|
+
let nextFrameId = 1;
|
|
705
|
+
const renderFrame = () => {
|
|
706
|
+
const pending = [...frames.values()];
|
|
707
|
+
frames.clear();
|
|
708
|
+
pending.forEach((callback) => callback(0));
|
|
709
|
+
};
|
|
710
|
+
|
|
711
|
+
const mountStreaming = async (config: Record<string, unknown> = {}) => {
|
|
712
|
+
frames = new Map();
|
|
713
|
+
vi.stubGlobal("requestAnimationFrame", (callback: (time: number) => void) => {
|
|
714
|
+
const id = nextFrameId++;
|
|
715
|
+
frames.set(id, callback);
|
|
716
|
+
return id;
|
|
717
|
+
});
|
|
718
|
+
vi.stubGlobal("cancelAnimationFrame", (id: number) => frames.delete(id));
|
|
719
|
+
global.fetch = vi.fn().mockImplementation(
|
|
720
|
+
() => new Promise(() => {})
|
|
721
|
+
) as unknown as typeof fetch;
|
|
722
|
+
|
|
723
|
+
const mount = createMount();
|
|
724
|
+
const controller = createAgentExperience(mount, {
|
|
725
|
+
apiUrl: "https://api.example.com/chat",
|
|
726
|
+
launcher: { enabled: false },
|
|
727
|
+
...config,
|
|
728
|
+
} as unknown as Parameters<typeof createAgentExperience>[1]);
|
|
729
|
+
|
|
730
|
+
controller.submitMessage("hello");
|
|
731
|
+
await Promise.resolve();
|
|
732
|
+
await Promise.resolve();
|
|
733
|
+
return { mount, controller };
|
|
734
|
+
};
|
|
735
|
+
|
|
736
|
+
// Stamped in the future so the rows sort after the submitted user message.
|
|
737
|
+
const sequence = Date.now() + 60_000;
|
|
738
|
+
const createdAt = new Date(sequence).toISOString();
|
|
739
|
+
const fullArgs = {
|
|
740
|
+
questions: [
|
|
741
|
+
{ question: "Which audience?", options: [{ label: "Hobbyists" }, { label: "Pros" }] },
|
|
742
|
+
],
|
|
743
|
+
};
|
|
744
|
+
|
|
745
|
+
const injectStreamingAsk = (
|
|
746
|
+
controller: ReturnType<typeof createAgentExperience>,
|
|
747
|
+
{ chunks = [], args }: { chunks?: string[]; args?: unknown } = {}
|
|
748
|
+
) => {
|
|
749
|
+
controller.injectTestMessage({
|
|
750
|
+
type: "message",
|
|
751
|
+
message: {
|
|
752
|
+
id: "ask-1",
|
|
753
|
+
role: "assistant",
|
|
754
|
+
content: "",
|
|
755
|
+
createdAt,
|
|
756
|
+
sequence,
|
|
757
|
+
streaming: true,
|
|
758
|
+
variant: "tool",
|
|
759
|
+
toolCall: { id: "ask-1", name: "ask_user_question", status: "running", chunks, args },
|
|
760
|
+
},
|
|
761
|
+
});
|
|
762
|
+
renderFrame();
|
|
763
|
+
};
|
|
764
|
+
|
|
765
|
+
const injectAwaitingAsk = (controller: ReturnType<typeof createAgentExperience>) => {
|
|
766
|
+
controller.injectTestMessage({
|
|
767
|
+
type: "message",
|
|
768
|
+
message: {
|
|
769
|
+
id: "ask-1",
|
|
770
|
+
role: "assistant",
|
|
771
|
+
content: "",
|
|
772
|
+
createdAt,
|
|
773
|
+
sequence,
|
|
774
|
+
streaming: false,
|
|
775
|
+
variant: "tool",
|
|
776
|
+
toolCall: { id: "ask-1", name: "ask_user_question", status: "complete", chunks: [], args: fullArgs },
|
|
777
|
+
agentMetadata: { executionId: "exec_123", awaitingLocalTool: true },
|
|
778
|
+
},
|
|
779
|
+
});
|
|
780
|
+
renderFrame();
|
|
781
|
+
};
|
|
782
|
+
|
|
783
|
+
const typingIndicator = (mount: HTMLElement) =>
|
|
784
|
+
mount.querySelector('[data-typing-indicator="true"]');
|
|
785
|
+
const askSheet = (mount: HTMLElement) => mount.querySelector("[data-persona-ask-sheet-for]");
|
|
786
|
+
|
|
787
|
+
it("keeps the dots until the built-in sheet mounts when no plugin renders the question", async () => {
|
|
788
|
+
const { mount, controller } = await mountStreaming();
|
|
789
|
+
|
|
790
|
+
injectStreamingAsk(controller);
|
|
791
|
+
expect(askSheet(mount)).toBeNull();
|
|
792
|
+
expect(typingIndicator(mount)).not.toBeNull();
|
|
793
|
+
|
|
794
|
+
injectAwaitingAsk(controller);
|
|
795
|
+
expect(askSheet(mount)).not.toBeNull();
|
|
796
|
+
expect(typingIndicator(mount)).toBeNull();
|
|
797
|
+
|
|
798
|
+
controller.destroy();
|
|
799
|
+
});
|
|
800
|
+
|
|
801
|
+
it("keeps the dots while the plugin returns null for a partial payload", async () => {
|
|
802
|
+
const plugin: AgentWidgetPlugin = {
|
|
803
|
+
id: "partial-asker",
|
|
804
|
+
renderAskUserQuestion: ({ payload }) => {
|
|
805
|
+
if (!payload?.questions?.[0]?.options?.length) return null;
|
|
806
|
+
const root = document.createElement("div");
|
|
807
|
+
root.setAttribute("data-test-id", "partial-ask");
|
|
808
|
+
return root;
|
|
809
|
+
},
|
|
810
|
+
};
|
|
811
|
+
const { mount, controller } = await mountStreaming({ plugins: [plugin] });
|
|
812
|
+
|
|
813
|
+
injectStreamingAsk(controller, { chunks: ['{"questions":[{"question":"Which'] });
|
|
814
|
+
expect(mount.querySelector('[data-test-id="partial-ask"]')).toBeNull();
|
|
815
|
+
expect(askSheet(mount)).toBeNull();
|
|
816
|
+
expect(typingIndicator(mount)).not.toBeNull();
|
|
817
|
+
|
|
818
|
+
injectStreamingAsk(controller, { args: fullArgs });
|
|
819
|
+
expect(mount.querySelector('[data-test-id="partial-ask"]')).not.toBeNull();
|
|
820
|
+
expect(typingIndicator(mount)).toBeNull();
|
|
821
|
+
|
|
822
|
+
controller.destroy();
|
|
823
|
+
});
|
|
824
|
+
|
|
825
|
+
it.each([true, false])("hides the dots as soon as the plugin renders a bubble (showToolCalls=%s)", async (showToolCalls) => {
|
|
826
|
+
const plugin: AgentWidgetPlugin = {
|
|
827
|
+
id: "eager-asker",
|
|
828
|
+
renderAskUserQuestion: () => {
|
|
829
|
+
const root = document.createElement("div");
|
|
830
|
+
root.setAttribute("data-test-id", "eager-ask");
|
|
831
|
+
return root;
|
|
832
|
+
},
|
|
833
|
+
};
|
|
834
|
+
const { mount, controller } = await mountStreaming({
|
|
835
|
+
plugins: [plugin],
|
|
836
|
+
features: { showToolCalls },
|
|
837
|
+
});
|
|
838
|
+
|
|
839
|
+
injectStreamingAsk(controller);
|
|
840
|
+
expect(mount.querySelector('[data-test-id="eager-ask"]')).not.toBeNull();
|
|
841
|
+
expect(typingIndicator(mount)).toBeNull();
|
|
842
|
+
|
|
843
|
+
controller.destroy();
|
|
844
|
+
});
|
|
845
|
+
});
|