@runtypelabs/persona 4.33.0 → 4.35.1
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-DW7Vg_l2.js → chunk-B1P8w9_X.js} +1 -1
- package/dist/{chunk-D6U0E82p.js → chunk-B30Jdgg6.js} +1 -1
- package/dist/{chunk-gu34lr-P.js → chunk-Brdx4NCz.js} +1 -1
- package/dist/{chunk-6CUrH_jm.js → chunk-Bzo9GaAi.js} +1 -1
- 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-CNBMBx-Y.js +2 -0
- package/dist/{chunk-ql5N2I_t.js → chunk-CWzHNuVK.js} +1 -1
- package/dist/{chunk-DbGLjU2P.js → chunk-CYpt7PsO.js} +1 -1
- package/dist/chunk-Cd8mp8Sv.js +1 -0
- package/dist/chunk-CsfE8WRG.js +1 -0
- package/dist/{chunk-DOZmcve8.js → chunk-Csr59G5V.js} +1 -1
- package/dist/{chunk-Co3VVwGe.js → chunk-D2pHRNEq.js} +0 -0
- package/dist/chunk-D3kZO8u-.js +1 -0
- package/dist/chunk-DAthf5H3.js +1 -0
- package/dist/{chunk-CXQJG7pb.js → chunk-DZ_aillY.js} +2 -2
- package/dist/{chunk-6C23QQdP.js → chunk-DgJV9zbK.js} +1 -1
- package/dist/chunk-Dv6KtIT1.js +1 -0
- package/dist/chunk-Dws8IrdR.js +1 -0
- package/dist/chunk-ThxxD8oK.js +1 -0
- package/dist/{chunk-C-EHtpbB.js → chunk-h5aOI_Pa.js} +1 -1
- 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-DnqGCXZz.d.ts → composer-input-BSDNPOqV.d.cts} +1 -7
- package/dist/{composer-input-DnqGCXZz.d.cts → composer-input-BSDNPOqV.d.ts} +1 -7
- package/dist/{composer-store-6Iwy6WLI.d.ts → composer-store-DC-gAjtN.d.cts} +1 -3
- package/dist/{composer-store-6Iwy6WLI.d.cts → composer-store-DC-gAjtN.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-B-rHF98n.d.ts → context-mention-manager-CCpeoGL2.d.cts} +2 -6
- package/dist/{context-mention-manager-B-rHF98n.d.cts → context-mention-manager-CCpeoGL2.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 +2 -2
- package/dist/context-mentions.d.cts +3 -9
- package/dist/context-mentions.d.ts +3 -9
- package/dist/context-mentions.js +1 -1
- package/dist/{defaults-BuOjqUAG.d.ts → defaults-tj5RcN8r.d.cts} +1 -5
- package/dist/{defaults-BuOjqUAG.d.cts → defaults-tj5RcN8r.d.ts} +1 -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.cts → dom-context-Bw-_9Evh.d.cts} +0 -2
- package/dist/{dom-context-DHTabIn7.d.ts → 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-SqEfkGda.d.ts → fallback-speech-engine-gkhbjLiZ.d.cts} +1 -3
- package/dist/{fallback-speech-engine-SqEfkGda.d.cts → fallback-speech-engine-gkhbjLiZ.d.ts} +1 -3
- package/dist/{feature-preferences-DqAmje-2.d.ts → feature-preferences-CerDWGZ7.d.cts} +1 -5
- package/dist/{feature-preferences-DqAmje-2.d.cts → feature-preferences-CerDWGZ7.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-B3L7QNcO.d.cts → history-confirm-dialog-CrkSB3Ra.d.cts} +2 -14
- package/dist/{history-confirm-dialog-B3L7QNcO.d.ts → history-confirm-dialog-CrkSB3Ra.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 +10 -10
- package/dist/index.d.ts +10 -10
- package/dist/index.global.js +1 -1
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +50 -50
- 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-JecjOfJS.d.ts → loading-label-runtime-loader-fWIRrhUF.d.cts} +1 -3
- package/dist/{loading-label-runtime-loader-JecjOfJS.d.cts → loading-label-runtime-loader-fWIRrhUF.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-CBYtpDsT.d.ts → message-bubble-Czc0lOHr.d.cts} +20 -3
- package/dist/{message-bubble-CBYtpDsT.d.cts → message-bubble-Czc0lOHr.d.ts} +20 -3
- package/dist/{plugin-kit-C1mRjLgW.d.cts → plugin-kit-C30jE-cw.d.cts} +3 -3
- package/dist/{plugin-kit-C1mRjLgW.d.ts → plugin-kit-C30jE-cw.d.ts} +3 -3
- package/dist/plugin-kit.cjs +1 -1
- package/dist/plugin-kit.d.cts +1 -1
- package/dist/plugin-kit.d.ts +1 -1
- package/dist/plugin-kit.js +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-_UJwwt2L.d.cts → preview-D-osV3FU.d.cts} +2 -6
- package/dist/{preview-_UJwwt2L.d.ts → preview-D-osV3FU.d.ts} +2 -6
- package/dist/{registry-B5ZV3K-h.d.ts → registry-B6w91tx0.d.cts} +1 -8
- package/dist/{registry-B5ZV3K-h.d.cts → registry-B6w91tx0.d.ts} +1 -8
- package/dist/{session-Bys8_XuB.d.cts → session-BUQrs3Of.d.cts} +10 -93
- package/dist/{session-Bys8_XuB.d.ts → session-BUQrs3Of.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 +50 -50
- 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 +2 -4
- package/dist/theme-reference.d.ts +2 -4
- package/dist/theme-reference.js +1 -1
- package/dist/{tool-loading-animation-d5qAQcwv.d.ts → tool-loading-animation-B7XUf8TN.d.cts} +1 -7
- package/dist/{tool-loading-animation-d5qAQcwv.d.cts → tool-loading-animation-B7XUf8TN.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-q6fHVnx-.d.cts → turn-activity-ui-CohuNMHT.d.cts} +2 -12
- package/dist/{turn-activity-ui-q6fHVnx-.d.ts → turn-activity-ui-CohuNMHT.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-B_mj21jg.d.cts → types-9i0xcAMT.d.cts} +128 -29
- package/dist/{types-B_mj21jg.d.ts → types-9i0xcAMT.d.ts} +128 -29
- 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-ClEO3qdI.d.ts → webmcp-runtime-entry-XNaXa-9h.d.cts} +9 -5
- package/dist/{webmcp-runtime-entry-ClEO3qdI.d.cts → webmcp-runtime-entry-XNaXa-9h.d.ts} +9 -5
- package/dist/webmcp-runtime.cjs +1 -1
- package/dist/webmcp-runtime.d.cts +1 -1
- package/dist/webmcp-runtime.d.ts +1 -1
- package/dist/webmcp-runtime.js +1 -1
- package/dist/widget.css +1 -1
- package/package.json +5 -5
- package/src/client-dispatch.ts +13 -0
- package/src/client.ts +37 -2
- package/src/client.webmcp-require-confirm.test.ts +212 -0
- package/src/components/composer-model-picker.ts +0 -14
- package/src/components/composer-overflow-menu.ts +0 -15
- package/src/components/composer-tokens.ts +0 -20
- package/src/components/event-stream-view.test.ts +5 -0
- package/src/components/message-bubble.ts +26 -6
- 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.ts +6 -0
- package/src/generated/runtype-openapi-contract.ts +13 -0
- package/src/plugin-kit.test.ts +101 -0
- package/src/plugin-kit.ts +29 -1
- package/src/session.ts +6 -2
- package/src/session.webmcp.test.ts +32 -0
- package/src/styles/widget.css +56 -0
- package/src/theme-reference.ts +2 -2
- package/src/types/theme.ts +29 -0
- package/src/types.ts +84 -5
- package/src/ui.composer-models.test.ts +5 -7
- package/src/ui.composer-overflow.test.ts +14 -21
- package/src/ui.scroll-additive.test.ts +219 -117
- package/src/ui.scroll.test.ts +176 -13
- package/src/ui.ts +230 -107
- package/src/ui.turn-activity.test.ts +7 -7
- package/src/ui.user-message-collapse.test.ts +540 -0
- package/src/utils/auto-follow.test.ts +0 -38
- package/src/utils/auto-follow.ts +0 -35
- package/src/utils/context-mention-controller.test.ts +56 -0
- package/src/utils/theme.test.ts +23 -0
- package/src/utils/tokens.ts +16 -0
- package/src/webmcp-bridge.test.ts +102 -0
- package/src/webmcp-runtime-entry.ts +29 -1
- package/dist/chunk-BAkaTZpd.js +0 -1
- package/dist/chunk-BEDTp-dm.js +0 -1
- package/dist/chunk-C7-m0EmI.js +0 -1
- package/dist/chunk-CNhThrLX.js +0 -1
- package/dist/chunk-CVMIncEY.js +0 -1
- package/dist/chunk-CzLEhoB_.js +0 -2
- package/dist/chunk-DVgzoVCB.js +0 -1
- package/dist/chunk-d54BJdKd.js +0 -1
- package/dist/chunk-dLJWKfOb.js +0 -1
|
@@ -1230,3 +1230,35 @@ describe("AgentWidgetSession: WebMCP parallel batched resume (core#3878)", () =>
|
|
|
1230
1230
|
expect(s.webMcpApprovalResolvers.size).toBe(0);
|
|
1231
1231
|
});
|
|
1232
1232
|
});
|
|
1233
|
+
|
|
1234
|
+
describe("WebMCP requireConfirmFor on the default approval UI", () => {
|
|
1235
|
+
const pendingBubbles = (session: AgentWidgetSession) =>
|
|
1236
|
+
(session as unknown as { messages: AgentWidgetMessage[] }).messages.filter(
|
|
1237
|
+
(m) => m.variant === "approval" && m.approval?.status === "pending",
|
|
1238
|
+
);
|
|
1239
|
+
|
|
1240
|
+
it("prompts for a matched tool even when autoApprove returns true", async () => {
|
|
1241
|
+
const autoApprove = vi.fn(() => true);
|
|
1242
|
+
const { session } = makeSession({ webmcp: { autoApprove } });
|
|
1243
|
+
const pending = session.requestWebMcpApproval({
|
|
1244
|
+
toolName: "checkout_submit",
|
|
1245
|
+
args: {},
|
|
1246
|
+
reason: "gate",
|
|
1247
|
+
confirmRequired: true,
|
|
1248
|
+
});
|
|
1249
|
+
expect(autoApprove).not.toHaveBeenCalled();
|
|
1250
|
+
expect(pendingBubbles(session)).toHaveLength(1);
|
|
1251
|
+
session.cancel();
|
|
1252
|
+
await expect(pending).resolves.toBe(false);
|
|
1253
|
+
});
|
|
1254
|
+
|
|
1255
|
+
it("still auto-approves an unmatched tool", async () => {
|
|
1256
|
+
const autoApprove = vi.fn(() => true);
|
|
1257
|
+
const { session } = makeSession({ webmcp: { autoApprove } });
|
|
1258
|
+
await expect(
|
|
1259
|
+
session.requestWebMcpApproval({ toolName: "search", args: {}, reason: "gate" }),
|
|
1260
|
+
).resolves.toBe(true);
|
|
1261
|
+
expect(autoApprove).toHaveBeenCalledTimes(1);
|
|
1262
|
+
expect(pendingBubbles(session)).toHaveLength(0);
|
|
1263
|
+
});
|
|
1264
|
+
});
|
package/src/styles/widget.css
CHANGED
|
@@ -3109,6 +3109,52 @@
|
|
|
3109
3109
|
box-shadow: var(--persona-message-user-shadow);
|
|
3110
3110
|
}
|
|
3111
3111
|
|
|
3112
|
+
/* Long user message collapse (features.userMessageCollapse). The region clips
|
|
3113
|
+
without becoming a scroller (overflow: clip), so the full text stays in the
|
|
3114
|
+
DOM for find, copy and screen readers with no nested scroll area. The fade
|
|
3115
|
+
is a mask rather than a gradient overlay, so it works on any bubble fill in
|
|
3116
|
+
light and dark schemes; the toggle inherits the bubble's text color. */
|
|
3117
|
+
.persona-user-collapse-region[data-persona-user-collapse="collapsed"] {
|
|
3118
|
+
max-height: var(--persona-user-collapse-max-height, 240px);
|
|
3119
|
+
overflow: clip;
|
|
3120
|
+
-webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - var(--persona-user-collapse-fade-height, 48px)), transparent);
|
|
3121
|
+
mask-image: linear-gradient(to bottom, #000 calc(100% - var(--persona-user-collapse-fade-height, 48px)), transparent);
|
|
3122
|
+
}
|
|
3123
|
+
|
|
3124
|
+
.persona-user-collapse-toggle {
|
|
3125
|
+
display: inline-flex;
|
|
3126
|
+
align-items: center;
|
|
3127
|
+
margin-top: 0.25rem;
|
|
3128
|
+
padding: 0.125rem 0;
|
|
3129
|
+
border: 0;
|
|
3130
|
+
background: none;
|
|
3131
|
+
color: var(--persona-user-collapse-toggle-fg, inherit);
|
|
3132
|
+
font-family: inherit;
|
|
3133
|
+
font-size: var(--persona-user-collapse-toggle-font-size, 0.8125rem);
|
|
3134
|
+
font-weight: var(--persona-user-collapse-toggle-font-weight, 600);
|
|
3135
|
+
line-height: 1.25rem;
|
|
3136
|
+
cursor: pointer;
|
|
3137
|
+
text-decoration: underline;
|
|
3138
|
+
text-decoration-color: transparent;
|
|
3139
|
+
text-underline-offset: 2px;
|
|
3140
|
+
transition: text-decoration-color 150ms ease;
|
|
3141
|
+
}
|
|
3142
|
+
|
|
3143
|
+
.persona-user-collapse-toggle:hover {
|
|
3144
|
+
text-decoration-color: currentColor;
|
|
3145
|
+
}
|
|
3146
|
+
|
|
3147
|
+
.persona-user-collapse-toggle:focus-visible {
|
|
3148
|
+
outline: 2px solid currentColor;
|
|
3149
|
+
outline-offset: 2px;
|
|
3150
|
+
}
|
|
3151
|
+
|
|
3152
|
+
@media (prefers-reduced-motion: reduce) {
|
|
3153
|
+
.persona-user-collapse-toggle {
|
|
3154
|
+
transition: none;
|
|
3155
|
+
}
|
|
3156
|
+
}
|
|
3157
|
+
|
|
3112
3158
|
[data-persona-root] .persona-tool-bubble.persona-shadow-sm {
|
|
3113
3159
|
box-shadow: var(--persona-tool-bubble-shadow);
|
|
3114
3160
|
}
|
|
@@ -4869,6 +4915,16 @@
|
|
|
4869
4915
|
text-align: center;
|
|
4870
4916
|
}
|
|
4871
4917
|
|
|
4918
|
+
/* A pending approval below the fold: the control widens to a labelled pill.
|
|
4919
|
+
Unset approval tokens keep the pill's own colors. */
|
|
4920
|
+
[data-persona-root] .persona-scroll-to-bottom-indicator[data-persona-scroll-to-bottom-approval] {
|
|
4921
|
+
border-color: var(--persona-scroll-to-bottom-approval-border, var(--persona-scroll-to-bottom-border, var(--persona-primary, #111827)));
|
|
4922
|
+
background: var(--persona-scroll-to-bottom-approval-bg, var(--persona-scroll-to-bottom-bg, var(--persona-button-primary-bg, var(--persona-accent, #0f0f0f))));
|
|
4923
|
+
color: var(--persona-scroll-to-bottom-approval-fg, var(--persona-scroll-to-bottom-fg, var(--persona-button-primary-fg, var(--persona-text-inverse, #ffffff))));
|
|
4924
|
+
font-weight: var(--persona-scroll-to-bottom-approval-font-weight, 500);
|
|
4925
|
+
white-space: nowrap;
|
|
4926
|
+
}
|
|
4927
|
+
|
|
4872
4928
|
[data-persona-root] .persona-scroll-to-bottom-indicator:hover {
|
|
4873
4929
|
opacity: 0.92;
|
|
4874
4930
|
}
|
package/src/theme-reference.ts
CHANGED
|
@@ -171,7 +171,7 @@ export const THEME_TOKEN_DOCS = {
|
|
|
171
171
|
askUserQuestion: 'sheet (background, border, shadow), pill (background, foreground, borderRadius, selectedBackground, selectedForeground), customInput.background. Local features.askUserQuestion.styles still wins; navigation, labels and slide timing remain feature config.',
|
|
172
172
|
attachment: 'image (background, border).',
|
|
173
173
|
scrollToBottom:
|
|
174
|
-
'Floating scroll-to-bottom affordance shared by transcript and event stream: background, foreground, border, size, borderRadius, shadow, padding, gap, fontSize, iconSize.',
|
|
174
|
+
'Floating scroll-to-bottom affordance shared by transcript and event stream: background, foreground, border, size, borderRadius, shadow, padding, gap, fontSize, iconSize; approval (background, foreground, border, fontWeight) for the labelled "Approval needed" state, falling back to the control colors.',
|
|
175
175
|
toolBubble: 'shadow, background, borderColor, borderWidth, borderRadius; header (background, foreground, padding), content (background, foreground, padding), codeBlock (background, foreground, borderColor), toggleForeground, labelForeground, loading (primary, secondary, duration). Applies to card and activity-row variants without changing their distinct defaults. CSS duration uses ms/s; legacy numeric milliseconds must convert explicitly. Theme content.padding precedes activity.bodyPadding/toolBubble.bodyPadding fallbacks; explicit legacy axes override only their axis.',
|
|
176
176
|
scrollbar:
|
|
177
177
|
'Shared scrollbar appearance for every scroller: thumb (default semantic.colors.border), track (default transparent).',
|
|
@@ -250,7 +250,7 @@ export const THEME_TOKEN_DOCS = {
|
|
|
250
250
|
description:
|
|
251
251
|
'Shared transcript + event-stream jump-to-latest affordance.',
|
|
252
252
|
properties:
|
|
253
|
-
'features.scrollToBottom.enabled, features.scrollToBottom.iconName, features.scrollToBottom.label (empty string renders icon-only). Defaults: enabled=true, iconName="arrow-down", label="".',
|
|
253
|
+
'features.scrollToBottom.enabled, features.scrollToBottom.iconName, features.scrollToBottom.label (empty string renders icon-only), features.scrollToBottom.approvalLabel (shown while a pending approval is below the fold; empty string keeps the regular control). Defaults: enabled=true, iconName="arrow-down", label="", approvalLabel="Approval needed".',
|
|
254
254
|
},
|
|
255
255
|
toolCall: {
|
|
256
256
|
description:
|
package/src/types/theme.ts
CHANGED
|
@@ -530,6 +530,22 @@ export interface MessageActionsTokens {
|
|
|
530
530
|
borderRadius?: TokenReference<'radius'>;
|
|
531
531
|
}
|
|
532
532
|
|
|
533
|
+
/**
|
|
534
|
+
* Long user message collapse (`features.userMessageCollapse`). Every key is
|
|
535
|
+
* optional; unset, the fade and the toggle follow the user bubble's own text
|
|
536
|
+
* color and type, so they already work on any fill in light and dark schemes.
|
|
537
|
+
*/
|
|
538
|
+
export interface UserMessageCollapseTokens {
|
|
539
|
+
/** Height of the bottom fade on a collapsed bubble. @default "48px" */
|
|
540
|
+
fadeHeight?: string;
|
|
541
|
+
/** "Show more" / "Show less" text color. Defaults to the user bubble text color. */
|
|
542
|
+
toggleForeground?: TokenReference<'color'>;
|
|
543
|
+
/** Toggle label type size. @default "0.8125rem" */
|
|
544
|
+
toggleFontSize?: string;
|
|
545
|
+
/** Toggle label weight. @default "600" */
|
|
546
|
+
toggleFontWeight?: string;
|
|
547
|
+
}
|
|
548
|
+
|
|
533
549
|
/**
|
|
534
550
|
* Bubble geometry and type, per role. Every key is unset by default and each
|
|
535
551
|
* one falls back to the value the message layout preset already produced, so
|
|
@@ -1307,6 +1323,17 @@ export interface ScrollToBottomTokens extends ComponentTokenSet {
|
|
|
1307
1323
|
fontSize?: string;
|
|
1308
1324
|
fontWeight?: string;
|
|
1309
1325
|
};
|
|
1326
|
+
/**
|
|
1327
|
+
* The labelled "Approval needed" state shown while a pending approval is
|
|
1328
|
+
* below the fold. Omitted values follow the control's own colors, so it
|
|
1329
|
+
* matches the theme until you give it an accent.
|
|
1330
|
+
*/
|
|
1331
|
+
approval?: {
|
|
1332
|
+
background?: TokenReference<'color'>;
|
|
1333
|
+
foreground?: TokenReference<'color'>;
|
|
1334
|
+
border?: TokenReference<'color'>;
|
|
1335
|
+
fontWeight?: string;
|
|
1336
|
+
};
|
|
1310
1337
|
}
|
|
1311
1338
|
|
|
1312
1339
|
/** Visual tokens shared by one suggestion presentation variant. */
|
|
@@ -1357,6 +1384,8 @@ export interface ComponentTokens {
|
|
|
1357
1384
|
message: MessageTokens;
|
|
1358
1385
|
/** Hover-revealed per-message action row (copy, vote, read aloud). */
|
|
1359
1386
|
messageActions?: MessageActionsTokens;
|
|
1387
|
+
/** Fade and "Show more" toggle on collapsed long user messages. */
|
|
1388
|
+
userMessageCollapse?: UserMessageCollapseTokens;
|
|
1360
1389
|
/** Welcome / intro card shown above the message list. */
|
|
1361
1390
|
introCard?: IntroCardTokens;
|
|
1362
1391
|
/** Markdown surfaces (chat + artifact pane). */
|
package/src/types.ts
CHANGED
|
@@ -886,6 +886,16 @@ export type WebMcpConfirmInfo = {
|
|
|
886
886
|
* callbacks on v6 receive an AbortSignal, not a nested confirmation API.
|
|
887
887
|
*/
|
|
888
888
|
reason: 'gate';
|
|
889
|
+
/**
|
|
890
|
+
* `true` when the tool matches a `requireConfirmFor` pattern (the widget's
|
|
891
|
+
* `webmcp.requireConfirmFor`, or the bound Runtype surface's
|
|
892
|
+
* `behavior.webmcp.requireConfirmFor` from client-token init). The call
|
|
893
|
+
* must be confirmed by the user: Persona never runs `autoApprove` for it,
|
|
894
|
+
* and a custom `onConfirm` should not auto-approve it either. In
|
|
895
|
+
* client-token mode it is also set on every call until the surface policy
|
|
896
|
+
* has loaded (fail closed).
|
|
897
|
+
*/
|
|
898
|
+
confirmRequired?: true;
|
|
889
899
|
/**
|
|
890
900
|
* Aborts when the call no longer needs an answer (its deadline passed, or it
|
|
891
901
|
* was cancelled). A confirm UI should close and resolve `false`; the tool
|
|
@@ -936,8 +946,23 @@ export type AgentWidgetWebMcpConfig = {
|
|
|
936
946
|
* confirmation UI entirely. Use this to auto-allow read-only tools (e.g.
|
|
937
947
|
* a catalog search) while still gating mutating ones. Only consulted on
|
|
938
948
|
* the default-UI path: a custom `onConfirm` takes full control instead.
|
|
949
|
+
* Never consulted for a tool matching `requireConfirmFor`.
|
|
939
950
|
*/
|
|
940
951
|
autoApprove?: (info: WebMcpConfirmInfo) => boolean;
|
|
952
|
+
/**
|
|
953
|
+
* Tool-name patterns that must always be confirmed, even when `autoApprove`
|
|
954
|
+
* would approve them (and even on the voice path's read-only fast tier).
|
|
955
|
+
* Matched against the bare tool name (no `webmcp:` prefix); `*` matches any
|
|
956
|
+
* run of characters, e.g. `["checkout_*", "delete_account"]`. A matched
|
|
957
|
+
* call shows the default approval bubble, or reaches your `onConfirm` with
|
|
958
|
+
* `info.confirmRequired === true`.
|
|
959
|
+
*
|
|
960
|
+
* Merged with the bound surface's `behavior.webmcp.requireConfirmFor`,
|
|
961
|
+
* which Runtype returns from `/v1/client/init` in client-token mode. This
|
|
962
|
+
* is client-side UX, not a security boundary: the server enforces only
|
|
963
|
+
* `webmcp.enabled` and its `allowlist`.
|
|
964
|
+
*/
|
|
965
|
+
requireConfirmFor?: string[];
|
|
941
966
|
/**
|
|
942
967
|
* Confirm gate handler. When omitted, Persona renders its native in-panel
|
|
943
968
|
* approval bubble (the same chrome used for server-driven tool approvals)
|
|
@@ -2228,10 +2253,13 @@ export type AgentWidgetArtifactsFeature = {
|
|
|
2228
2253
|
*
|
|
2229
2254
|
* - `"anchor-top"` (default): on send, scroll the user's message near the top
|
|
2230
2255
|
* of the viewport and hold it there while the response streams in beneath it
|
|
2231
|
-
* (ChatGPT-style).
|
|
2232
|
-
*
|
|
2233
|
-
*
|
|
2234
|
-
*
|
|
2256
|
+
* (ChatGPT-style). The anchor holds for the whole reply, even when the
|
|
2257
|
+
* message is taller than the viewport or tool calls push the answer below
|
|
2258
|
+
* the fold, until the reader scrolls away, jumps to the latest content with
|
|
2259
|
+
* the scroll-to-bottom control, or sends again. When a turn has no user send
|
|
2260
|
+
* to anchor to (a proactive greeting, an injected assistant message, a
|
|
2261
|
+
* resubmit, or first-load streaming), it falls back to `"follow"` for that
|
|
2262
|
+
* turn so content never streams in off-screen.
|
|
2235
2263
|
* - `"follow"`: keep the newest content pinned to the bottom of the viewport,
|
|
2236
2264
|
* pausing when the user scrolls up and resuming when they return to the
|
|
2237
2265
|
* bottom. This was the default before 4.x.
|
|
@@ -2320,7 +2348,8 @@ export type AgentWidgetScrollBehaviorFeature = {
|
|
|
2320
2348
|
|
|
2321
2349
|
/** Decorative glyph state. Hidden glyphs should pause host-owned animation. */
|
|
2322
2350
|
export type AgentWidgetScrollToBottomIconState = {
|
|
2323
|
-
|
|
2351
|
+
/** `"approval-below"`: a pending approval is below the fold and the turn waits on it. */
|
|
2352
|
+
activity: "idle" | "generating-below" | "approval-below";
|
|
2324
2353
|
visible: boolean;
|
|
2325
2354
|
hovered: boolean;
|
|
2326
2355
|
focused: boolean;
|
|
@@ -2360,6 +2389,15 @@ export type AgentWidgetScrollToBottomFeature = {
|
|
|
2360
2389
|
* @default ""
|
|
2361
2390
|
*/
|
|
2362
2391
|
label?: string;
|
|
2392
|
+
/**
|
|
2393
|
+
* Label shown while a pending approval sits below the fold. The control
|
|
2394
|
+
* widens to a labelled pill with the approval's shield glyph, and the turn
|
|
2395
|
+
* stays put until the reader jumps (anchor-top never scrolls them to it).
|
|
2396
|
+
* Styled by `theme.components.scrollToBottom.approval`. Set to an empty
|
|
2397
|
+
* string to keep the regular control.
|
|
2398
|
+
* @default "Approval needed"
|
|
2399
|
+
*/
|
|
2400
|
+
approvalLabel?: string;
|
|
2363
2401
|
/** Glyph while a live response is arriving below. V4 defaults to arrow; V5 to dots. */
|
|
2364
2402
|
streamingIndicator?: "dots" | "arrow";
|
|
2365
2403
|
/** Visibility transition. V4 defaults to none; V5 to fade. Honors reduced motion. */
|
|
@@ -2788,6 +2826,31 @@ export type AgentWidgetStreamAnimationFeature = {
|
|
|
2788
2826
|
plugins?: Record<string, StreamAnimationPlugin>;
|
|
2789
2827
|
};
|
|
2790
2828
|
|
|
2829
|
+
/**
|
|
2830
|
+
* Collapse long user messages behind a "Show more" / "Show less" toggle.
|
|
2831
|
+
* Only the built-in user bubble collapses; `layout.messages.renderUserMessage`
|
|
2832
|
+
* and plugin `renderMessage` output is left untouched.
|
|
2833
|
+
*/
|
|
2834
|
+
export type AgentWidgetUserMessageCollapseFeature = {
|
|
2835
|
+
/**
|
|
2836
|
+
* Clip a user bubble whose rendered content (text, markdown, code,
|
|
2837
|
+
* attachments) is taller than `maxHeight`, with a bottom fade and a real
|
|
2838
|
+
* toggle button. The full message stays in the DOM, so find-in-page, copy,
|
|
2839
|
+
* selection and screen readers still reach it. Interim voice transcripts
|
|
2840
|
+
* stay expanded and collapse once final. A reader's toggle is remembered
|
|
2841
|
+
* per message for the life of the widget.
|
|
2842
|
+
* @default false (`true` under `future.v5Defaults`)
|
|
2843
|
+
*/
|
|
2844
|
+
enabled?: boolean;
|
|
2845
|
+
/**
|
|
2846
|
+
* Collapsed height in px. Content within about two lines (48px) of the
|
|
2847
|
+
* limit is left expanded, so the toggle never hides just a line or two.
|
|
2848
|
+
* The default shows about ten lines of bubble text.
|
|
2849
|
+
* @default 240
|
|
2850
|
+
*/
|
|
2851
|
+
maxHeight?: number;
|
|
2852
|
+
};
|
|
2853
|
+
|
|
2791
2854
|
export type AgentWidgetFeatureFlags = {
|
|
2792
2855
|
showReasoning?: boolean;
|
|
2793
2856
|
showToolCalls?: boolean;
|
|
@@ -2804,6 +2867,8 @@ export type AgentWidgetFeatureFlags = {
|
|
|
2804
2867
|
scrollToBottom?: AgentWidgetScrollToBottomFeature;
|
|
2805
2868
|
/** Transcript scroll behavior during streamed responses. */
|
|
2806
2869
|
scrollBehavior?: AgentWidgetScrollBehaviorFeature;
|
|
2870
|
+
/** "Show more" collapse for long user messages. Off by default; on under `future.v5Defaults`. */
|
|
2871
|
+
userMessageCollapse?: AgentWidgetUserMessageCollapseFeature;
|
|
2807
2872
|
/** Collapsed transcript behavior for tool call rows. */
|
|
2808
2873
|
toolCallDisplay?: AgentWidgetToolCallDisplayFeature;
|
|
2809
2874
|
/** Collapsed transcript behavior for reasoning rows. */
|
|
@@ -6782,6 +6847,11 @@ export type ClientSession = {
|
|
|
6782
6847
|
welcomeMessage: string | null;
|
|
6783
6848
|
placeholder: string;
|
|
6784
6849
|
theme: Record<string, unknown> | null;
|
|
6850
|
+
/**
|
|
6851
|
+
* The bound chat surface's WebMCP confirm policy. Present only when the
|
|
6852
|
+
* surface enables WebMCP and lists `requireConfirmFor` patterns.
|
|
6853
|
+
*/
|
|
6854
|
+
webmcp?: { requireConfirmFor: string[] };
|
|
6785
6855
|
};
|
|
6786
6856
|
};
|
|
6787
6857
|
|
|
@@ -6822,6 +6892,11 @@ export type ClientInitResponse = {
|
|
|
6822
6892
|
welcomeMessage: string | null;
|
|
6823
6893
|
placeholder: string;
|
|
6824
6894
|
theme: Record<string, unknown> | null;
|
|
6895
|
+
/**
|
|
6896
|
+
* The bound chat surface's WebMCP confirm policy. Present only when the
|
|
6897
|
+
* surface enables WebMCP and lists `requireConfirmFor` patterns.
|
|
6898
|
+
*/
|
|
6899
|
+
webmcp?: { requireConfirmFor: string[] };
|
|
6825
6900
|
};
|
|
6826
6901
|
};
|
|
6827
6902
|
|
|
@@ -8433,6 +8508,10 @@ export type AgentWidgetConfig = {
|
|
|
8433
8508
|
sendButtonLabel?: string;
|
|
8434
8509
|
/** Button label shown in text mode while a response is streaming. Default: "Stop". */
|
|
8435
8510
|
stopButtonLabel?: string;
|
|
8511
|
+
/** Toggle label on a collapsed long user message (`features.userMessageCollapse`). @default "Show more" */
|
|
8512
|
+
showMoreLabel?: string;
|
|
8513
|
+
/** Toggle label on an expanded long user message (`features.userMessageCollapse`). @default "Show less" */
|
|
8514
|
+
showLessLabel?: string;
|
|
8436
8515
|
/**
|
|
8437
8516
|
* When false, the welcome / intro card is not shown above the message list.
|
|
8438
8517
|
* @deprecated Use `welcome.variant: "none"`.
|
|
@@ -344,29 +344,27 @@ describe("composer model picker", () => {
|
|
|
344
344
|
},
|
|
345
345
|
});
|
|
346
346
|
expect(mount.style.getPropertyValue(token)).toBe("#1e1f20");
|
|
347
|
-
// The panel is portaled to document.body,
|
|
348
|
-
// mount's theme vars.
|
|
349
|
-
// computed style does not inherit custom properties.
|
|
347
|
+
// The panel is portaled to document.body, outside the mount, so it
|
|
348
|
+
// carries a copy of the mount's theme vars.
|
|
350
349
|
const button = trigger(mount)!;
|
|
351
|
-
button.style.setProperty(token, "#1e1f20");
|
|
352
350
|
|
|
353
351
|
button.click();
|
|
354
352
|
const panel = menu()!;
|
|
353
|
+
expect(mount.contains(panel)).toBe(false);
|
|
355
354
|
expect(panel.style.getPropertyValue(token)).toBe("#1e1f20");
|
|
356
355
|
button.click();
|
|
357
356
|
|
|
358
357
|
// Explicit undefined is the documented reset, so the mount stops
|
|
359
|
-
// carrying the var
|
|
358
|
+
// carrying the var.
|
|
360
359
|
controller.update({
|
|
361
360
|
theme: {
|
|
362
361
|
components: { composer: { modelPicker: { menuBackground: undefined } } },
|
|
363
362
|
},
|
|
364
363
|
});
|
|
365
364
|
expect(mount.style.getPropertyValue(token)).toBe("");
|
|
366
|
-
button.style.removeProperty(token);
|
|
367
365
|
|
|
368
366
|
// The menu outlives the update, so the next open has to clear the value
|
|
369
|
-
// the first one
|
|
367
|
+
// the first one copied; an empty inline value is the fallback state.
|
|
370
368
|
trigger(mount)!.click();
|
|
371
369
|
expect(menu()).toBe(panel);
|
|
372
370
|
expect(panel.style.getPropertyValue(token)).toBe("");
|
|
@@ -103,27 +103,25 @@ describe("composer overflow menu in the live widget", () => {
|
|
|
103
103
|
vi.restoreAllMocks();
|
|
104
104
|
});
|
|
105
105
|
|
|
106
|
-
it("
|
|
106
|
+
it("carries the panel surface tokens onto the portaled menu on open", () => {
|
|
107
107
|
const { mount } = makeController({
|
|
108
108
|
composer: {
|
|
109
109
|
actions: [action("folded", { presentation: "overflow" })],
|
|
110
110
|
actionOverflow: { enabled: true },
|
|
111
111
|
},
|
|
112
|
+
theme: {
|
|
113
|
+
components: {
|
|
114
|
+
composer: {
|
|
115
|
+
overflowMenu: { background: "#353535", borderColor: "rgba(255, 255, 255, 0.08)" },
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
},
|
|
112
119
|
});
|
|
113
|
-
// The panel is portaled to document.body, so it never inherits the mount's
|
|
114
|
-
// theme vars. Stamped on the trigger here because jsdom's computed style
|
|
115
|
-
// does not inherit custom properties.
|
|
116
|
-
const trigger = triggerOf(mount)!;
|
|
117
|
-
trigger.style.setProperty(
|
|
118
|
-
"--persona-components-composer-overflowMenu-background",
|
|
119
|
-
"#353535"
|
|
120
|
-
);
|
|
121
|
-
trigger.style.setProperty(
|
|
122
|
-
"--persona-components-composer-overflowMenu-borderColor",
|
|
123
|
-
"rgba(255, 255, 255, 0.08)"
|
|
124
|
-
);
|
|
125
120
|
|
|
121
|
+
// The panel is portaled to document.body, outside the mount, so it
|
|
122
|
+
// carries a copy of the mount's theme vars.
|
|
126
123
|
const panel = openPanel(mount)!;
|
|
124
|
+
expect(mount.contains(panel)).toBe(false);
|
|
127
125
|
|
|
128
126
|
expect(
|
|
129
127
|
panel.style.getPropertyValue(
|
|
@@ -135,7 +133,7 @@ describe("composer overflow menu in the live widget", () => {
|
|
|
135
133
|
"--persona-components-composer-overflowMenu-borderColor"
|
|
136
134
|
)
|
|
137
135
|
).toBe("rgba(255, 255, 255, 0.08)");
|
|
138
|
-
// Unset keys
|
|
136
|
+
// Unset keys copy nothing, so the stylesheet's fallback still stands.
|
|
139
137
|
expect(
|
|
140
138
|
panel.style.getPropertyValue(
|
|
141
139
|
"--persona-components-composer-overflowMenu-shadow"
|
|
@@ -155,27 +153,22 @@ describe("composer overflow menu in the live widget", () => {
|
|
|
155
153
|
},
|
|
156
154
|
});
|
|
157
155
|
expect(mount.style.getPropertyValue(token)).toBe("#353535");
|
|
158
|
-
// Stamped on the trigger for the same reason as the test above: jsdom's
|
|
159
|
-
// computed style does not inherit custom properties.
|
|
160
|
-
const trigger = triggerOf(mount)!;
|
|
161
|
-
trigger.style.setProperty(token, "#353535");
|
|
162
156
|
|
|
163
157
|
const panel = openPanel(mount)!;
|
|
164
158
|
expect(panel.style.getPropertyValue(token)).toBe("#353535");
|
|
165
159
|
triggerOf(mount)!.click();
|
|
166
160
|
|
|
167
161
|
// Explicit undefined is the documented reset, so the mount stops carrying
|
|
168
|
-
// the var
|
|
162
|
+
// the var.
|
|
169
163
|
controller.update({
|
|
170
164
|
theme: {
|
|
171
165
|
components: { composer: { overflowMenu: { background: undefined } } },
|
|
172
166
|
},
|
|
173
167
|
});
|
|
174
168
|
expect(mount.style.getPropertyValue(token)).toBe("");
|
|
175
|
-
trigger.style.removeProperty(token);
|
|
176
169
|
|
|
177
170
|
// The panel outlives the update, so the next open has to clear the value
|
|
178
|
-
// the first one
|
|
171
|
+
// the first one copied; an empty inline value is the fallback state.
|
|
179
172
|
const reopened = openPanel(mount)!;
|
|
180
173
|
expect(reopened).toBe(panel);
|
|
181
174
|
expect(reopened.style.getPropertyValue(token)).toBe("");
|