@runtypelabs/persona 4.32.1 → 4.33.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 -3
- package/dist/activity-ui.d.ts +3 -3
- package/dist/animations/glyph-cycle.d.cts +1 -1
- package/dist/animations/glyph-cycle.d.ts +1 -1
- package/dist/animations/wipe.d.cts +1 -1
- package/dist/animations/wipe.d.ts +1 -1
- package/dist/approval-ui.d.cts +2 -2
- package/dist/approval-ui.d.ts +2 -2
- package/dist/artifacts-ui.d.cts +3 -3
- package/dist/artifacts-ui.d.ts +3 -3
- package/dist/background-runtime.d.cts +1 -1
- package/dist/background-runtime.d.ts +1 -1
- 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-CEPM3FOp.js +1 -0
- package/dist/{chunk-CumoXK3u.js → chunk-CXQJG7pb.js} +1 -1
- package/dist/{chunk-UWMfWW2a.js → chunk-D1G8tgYc.js} +1 -1
- package/dist/{chunk-BpjtKnGI.js → chunk-D6U0E82p.js} +1 -1
- package/dist/{chunk-2FnmZ9AA.js → chunk-DOZmcve8.js} +1 -1
- package/dist/chunk-DVgzoVCB.js +1 -0
- package/dist/{chunk-C9uOhfk5.js → chunk-DW7Vg_l2.js} +1 -1
- package/dist/{chunk-B3l7TOOv.js → chunk-DbGLjU2P.js} +1 -1
- package/dist/{chunk-DTGvDx8o.js → chunk-Dj2a9f9w.js} +1 -1
- package/dist/{chunk-DgZZqy14.js → chunk-d54BJdKd.js} +1 -1
- package/dist/chunk-dLJWKfOb.js +1 -0
- package/dist/{chunk-DNdeIFJ6.js → chunk-gu34lr-P.js} +1 -1
- package/dist/chunk-i4qGOJAL.js +1 -0
- package/dist/{chunk-DVZ8ri1z.js → chunk-ql5N2I_t.js} +1 -1
- package/dist/client-dispatch.js +1 -1
- package/dist/client-history.js +1 -1
- package/dist/codegen.cjs +1 -1
- package/dist/codegen.js +1 -1
- package/dist/composer-actions-runtime.d.cts +2 -2
- package/dist/composer-actions-runtime.d.ts +2 -2
- package/dist/{composer-input-dwg_o9Z-.d.cts → composer-input-DnqGCXZz.d.cts} +1 -1
- package/dist/{composer-input-dwg_o9Z-.d.ts → composer-input-DnqGCXZz.d.ts} +1 -1
- package/dist/{composer-store-Dw7Zbqxr.d.cts → composer-store-6Iwy6WLI.d.cts} +1 -1
- package/dist/{composer-store-Dw7Zbqxr.d.ts → composer-store-6Iwy6WLI.d.ts} +1 -1
- package/dist/{context-mention-manager-D2p0-JH-.d.cts → context-mention-manager-B-rHF98n.d.cts} +2 -2
- package/dist/{context-mention-manager-D2p0-JH-.d.ts → context-mention-manager-B-rHF98n.d.ts} +2 -2
- package/dist/context-mentions-inline.d.cts +2 -2
- package/dist/context-mentions-inline.d.ts +2 -2
- package/dist/context-mentions.d.cts +3 -3
- package/dist/context-mentions.d.ts +3 -3
- package/dist/{defaults-CjX0kKzb.d.ts → defaults-BuOjqUAG.d.cts} +2 -1
- package/dist/{defaults-CjX0kKzb.d.cts → defaults-BuOjqUAG.d.ts} +2 -1
- package/dist/dictation-runtime.d.cts +2 -2
- package/dist/dictation-runtime.d.ts +2 -2
- package/dist/event-stream-view.d.cts +1 -1
- package/dist/event-stream-view.d.ts +1 -1
- package/dist/{fallback-speech-engine-DmF7MczI.d.cts → fallback-speech-engine-SqEfkGda.d.cts} +1 -1
- package/dist/{fallback-speech-engine-DmF7MczI.d.ts → fallback-speech-engine-SqEfkGda.d.ts} +1 -1
- package/dist/{feature-preferences-CVFDt9Xf.d.cts → feature-preferences-DqAmje-2.d.cts} +1 -1
- package/dist/{feature-preferences-CVFDt9Xf.d.ts → feature-preferences-DqAmje-2.d.ts} +1 -1
- package/dist/forms-ui.d.cts +2 -2
- package/dist/forms-ui.d.ts +2 -2
- package/dist/{history-confirm-dialog-DJEXsTyE.d.cts → history-confirm-dialog-B3L7QNcO.d.cts} +1 -1
- package/dist/{history-confirm-dialog-DJEXsTyE.d.ts → history-confirm-dialog-B3L7QNcO.d.ts} +1 -1
- package/dist/history-shell.cjs +1 -1
- package/dist/history-shell.d.cts +6 -6
- package/dist/history-shell.d.ts +6 -6
- 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/index.cjs +38 -38
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +9 -9
- package/dist/index.d.ts +9 -9
- package/dist/index.global.js +1 -1
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +52 -52
- 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.cts → loading-label-runtime-loader-JecjOfJS.d.cts} +1 -1
- package/dist/{loading-label-runtime-loader-CPxnoaoi.d.ts → loading-label-runtime-loader-JecjOfJS.d.ts} +1 -1
- package/dist/loading-label-runtime.d.cts +1 -1
- package/dist/loading-label-runtime.d.ts +1 -1
- package/dist/{message-bubble-CkZGlCLC.d.ts → message-bubble-CBYtpDsT.d.cts} +2 -2
- package/dist/{message-bubble-CkZGlCLC.d.cts → message-bubble-CBYtpDsT.d.ts} +2 -2
- package/dist/preferences-runtime.d.cts +1 -1
- package/dist/preferences-runtime.d.ts +1 -1
- package/dist/{preview-DdUvoLb4.d.cts → preview-_UJwwt2L.d.cts} +2 -2
- package/dist/{preview-DdUvoLb4.d.ts → preview-_UJwwt2L.d.ts} +2 -2
- package/dist/{registry-Dz4iHNST.d.cts → registry-B5ZV3K-h.d.cts} +1 -1
- package/dist/{registry-Dz4iHNST.d.ts → registry-B5ZV3K-h.d.ts} +1 -1
- package/dist/{session-Baxp9iRK.d.cts → session-Bys8_XuB.d.cts} +10 -9
- package/dist/{session-Baxp9iRK.d.ts → session-Bys8_XuB.d.ts} +10 -9
- package/dist/session-reconnect.d.cts +2 -2
- package/dist/session-reconnect.d.ts +2 -2
- package/dist/smart-dom-reader.d.cts +1 -1
- package/dist/smart-dom-reader.d.ts +1 -1
- package/dist/theme-editor-preview.cjs +31 -31
- package/dist/theme-editor-preview.d.cts +1 -1
- package/dist/theme-editor-preview.d.ts +1 -1
- package/dist/theme-editor-preview.js +19 -19
- package/dist/theme-editor.cjs +1 -1
- package/dist/theme-editor.d.cts +2 -2
- package/dist/theme-editor.d.ts +2 -2
- package/dist/theme-editor.js +1 -1
- package/dist/theme-reference.cjs +1 -1
- package/dist/theme-reference.d.cts +4 -2
- package/dist/theme-reference.d.ts +4 -2
- package/dist/theme-reference.js +1 -1
- package/dist/{tool-loading-animation-un3kA5Ur.d.cts → tool-loading-animation-d5qAQcwv.d.cts} +1 -1
- package/dist/{tool-loading-animation-un3kA5Ur.d.ts → tool-loading-animation-d5qAQcwv.d.ts} +1 -1
- package/dist/{turn-activity-ui-BGNhtMcH.d.cts → turn-activity-ui-q6fHVnx-.d.cts} +2 -2
- package/dist/{turn-activity-ui-BGNhtMcH.d.ts → turn-activity-ui-q6fHVnx-.d.ts} +2 -2
- 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-B_mj21jg.d.cts} +91 -7
- package/dist/{types-BOZHQIk0.d.ts → types-B_mj21jg.d.ts} +91 -7
- package/dist/voice-client-tools.d.cts +1 -1
- package/dist/voice-client-tools.d.ts +1 -1
- package/dist/voice-runtime.cjs +1 -1
- package/dist/voice-runtime.d.cts +2 -2
- package/dist/voice-runtime.d.ts +2 -2
- package/dist/voice-runtime.js +1 -1
- package/dist/voice-worklet-player.d.cts +2 -2
- package/dist/voice-worklet-player.d.ts +2 -2
- package/dist/{webmcp-runtime-entry-DuAG1_yF.d.cts → webmcp-runtime-entry-ClEO3qdI.d.cts} +1 -1
- package/dist/{webmcp-runtime-entry-DuAG1_yF.d.ts → webmcp-runtime-entry-ClEO3qdI.d.ts} +1 -1
- 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 +1 -1
- package/src/client-dispatch.ts +69 -16
- package/src/client.operator-role.test.ts +217 -0
- package/src/components/message-bubble.test.ts +169 -0
- package/src/components/message-bubble.ts +97 -28
- package/src/defaults-parity.test.ts +14 -0
- package/src/index-core.ts +7 -0
- package/src/index-global.ts +2 -1
- package/src/install.test.ts +6 -5
- package/src/install.ts +2 -2
- package/src/launcher-global.ts +2 -1
- package/src/session.resubmit-from.test.ts +27 -0
- package/src/session.test.ts +51 -0
- package/src/session.ts +22 -12
- package/src/styles/widget.css +23 -1
- package/src/theme-reference.ts +3 -1
- package/src/types/theme.ts +21 -0
- package/src/types.ts +71 -6
- package/src/ui.ask-user-question-plugin.test.ts +154 -0
- package/src/ui.operator-role.test.ts +336 -0
- package/src/ui.ts +37 -12
- package/src/utils/__snapshots__/tokens-parity.test.ts.snap +236 -0
- package/src/utils/brand.test.ts +14 -0
- package/src/utils/brand.ts +8 -4
- package/src/utils/cdn-release.test.ts +20 -0
- package/src/utils/cdn-release.ts +14 -0
- 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/tokens.ts +31 -0
- package/src/welcome.test.ts +16 -0
- package/src/welcome.ts +10 -2
- package/dist/chunk-BkOYJ11B.js +0 -1
- package/dist/chunk-Bz9jAgba.js +0 -1
- package/dist/chunk-CdpVP6LZ.js +0 -1
- package/dist/chunk-DM-OJt5q.js +0 -1
package/src/utils/brand.test.ts
CHANGED
|
@@ -58,10 +58,24 @@ describe('brand derivation', () => {
|
|
|
58
58
|
expect(getColorScheme({ brand: { neutral: '#111111' }, colorScheme: 'light' })).toBe('light');
|
|
59
59
|
expect(getColorScheme({ brand: { neutral: '#ffffff' }, colorScheme: 'dark' })).toBe('dark');
|
|
60
60
|
});
|
|
61
|
+
it.each(['light', 'dark'] as const)('outlines the V5 operator bubble instead of filling it in %s mode', (colorScheme) => {
|
|
62
|
+
const stock = getCssVariables(getActiveTheme({ colorScheme, future: { v5Defaults: true } }));
|
|
63
|
+
expect(stock['--persona-components-message-operator-background']).toBe('transparent');
|
|
64
|
+
expect(stock['--persona-components-message-operator-border']).toBe(stock['--persona-border']);
|
|
65
|
+
expect(stock['--persona-components-message-operator-borderWidth']).toBe('1px');
|
|
66
|
+
// A brand accent tints the outline; the bubble stays unfilled.
|
|
67
|
+
const branded = getCssVariables(getActiveTheme({ colorScheme, future: { v5Defaults: true }, brand: { accent: '#4c00ff', density: 'compact' } }));
|
|
68
|
+
expect(branded['--persona-components-message-operator-background']).toBe('transparent');
|
|
69
|
+
expect(branded['--persona-components-message-operator-border']).toBe('color-mix(in srgb, var(--persona-primary) 35%, var(--persona-border))');
|
|
70
|
+
// V4 keeps its primary-tinted fill.
|
|
71
|
+
const v4 = getCssVariables(getActiveTheme({ colorScheme }));
|
|
72
|
+
expect(v4['--persona-components-message-operator-background']).toBe('color-mix(in srgb, var(--persona-primary) 6%, var(--persona-container))');
|
|
73
|
+
});
|
|
61
74
|
it.each([['compact', '13px', '44px'], ['comfortable', '14px', '48px'], ['spacious', '15px', '52px']] as const)('maps %s density', (density, size, height) => {
|
|
62
75
|
const theme = deriveBrandTheme({ density });
|
|
63
76
|
expect(theme.semantic?.typography?.fontSize).toBe(size);
|
|
64
77
|
expect(theme.components?.header?.minHeight).toBe(height);
|
|
78
|
+
expect(theme.components?.message?.operator?.fontSize).toBe(size);
|
|
65
79
|
});
|
|
66
80
|
it.each([['none', '0px'], ['sm', '4px'], ['md', '8px'], ['lg', '16px']] as const)('maps %s radius while preserving circles', (radius, value) => {
|
|
67
81
|
const theme = deriveBrandTheme({ radius });
|
package/src/utils/brand.ts
CHANGED
|
@@ -61,9 +61,13 @@ export const deriveBrandTheme = (brand?: BrandConfig, scheme: 'light' | 'dark' =
|
|
|
61
61
|
? { background: 'semantic.colors.container', foreground: 'semantic.colors.text', iconBackground: 'transparent', iconForeground: 'semantic.colors.text' }
|
|
62
62
|
: { background: ramp[500], foreground: ink, iconBackground: ramp[500], iconForeground: ink },
|
|
63
63
|
approval: { approve: { foreground: ink } },
|
|
64
|
-
message:
|
|
65
|
-
? {
|
|
66
|
-
|
|
64
|
+
message: v5Defaults
|
|
65
|
+
? {
|
|
66
|
+
user: { background: 'color-mix(in srgb, var(--persona-primary) 12%, var(--persona-container))', text: 'semantic.colors.text' },
|
|
67
|
+
// The V5 operator stays outlined; a brand accent tints the outline.
|
|
68
|
+
operator: { border: 'color-mix(in srgb, var(--persona-primary) 35%, var(--persona-border))' },
|
|
69
|
+
}
|
|
70
|
+
: { user: { background: ramp[500], text: ink } },
|
|
67
71
|
};
|
|
68
72
|
}
|
|
69
73
|
const neutral = parseColor(brand.neutral);
|
|
@@ -104,7 +108,7 @@ export const deriveBrandTheme = (brand?: BrandConfig, scheme: 'light' | 'dark' =
|
|
|
104
108
|
if (brand.density && density) {
|
|
105
109
|
const [size, height, gap] = density;
|
|
106
110
|
theme.semantic = { ...theme.semantic, typography: { ...theme.semantic?.typography, fontSize: `${size}px` } };
|
|
107
|
-
theme.components = { ...theme.components, header: { ...theme.components?.header, minHeight: `${height}px`, padding: `${gap}px 16px`, minimalPadding: `${gap}px 16px` }, history: { railHeader: { minHeight: `${height}px` } }, composer: { ...theme.components?.composer, fontSize: `${size}px`, padding: `${gap}px`, gap: `${gap / 2}px` }, message: { ...theme.components?.message, gap: `${gap}px`, user: { ...theme.components?.message?.user, fontSize: `${size}px` }, assistant: { fontSize: `${size}px` } } };
|
|
111
|
+
theme.components = { ...theme.components, header: { ...theme.components?.header, minHeight: `${height}px`, padding: `${gap}px 16px`, minimalPadding: `${gap}px 16px` }, history: { railHeader: { minHeight: `${height}px` } }, composer: { ...theme.components?.composer, fontSize: `${size}px`, padding: `${gap}px`, gap: `${gap / 2}px` }, message: { ...theme.components?.message, gap: `${gap}px`, user: { ...theme.components?.message?.user, fontSize: `${size}px` }, assistant: { fontSize: `${size}px` }, operator: { ...theme.components?.message?.operator, fontSize: `${size}px` } } };
|
|
108
112
|
}
|
|
109
113
|
if (brand.elevation && ['flat', 'subtle', 'raised'].includes(brand.elevation)) {
|
|
110
114
|
const flat = brand.elevation === 'flat';
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { version } from "../../package.json";
|
|
3
|
+
import { pinCdnRelease } from "./cdn-release";
|
|
4
|
+
|
|
5
|
+
describe("pinCdnRelease", () => {
|
|
6
|
+
it.each(["install", "index", "launcher"])("pins the %s entry's dependencies to its embedded release", (entry) => {
|
|
7
|
+
expect(pinCdnRelease(`https://cdn.runtype.com/persona/latest/${entry}.global.js?embed=1`))
|
|
8
|
+
.toBe(`https://cdn.runtype.com/persona/${version}/${entry}.global.js?embed=1`);
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
it.each([
|
|
12
|
+
"https://cdn.runtype.com/persona/4.0.0/index.global.js",
|
|
13
|
+
"https://cdn.example.com/persona/latest/index.global.js",
|
|
14
|
+
"https://cdn.jsdelivr.net/npm/@runtypelabs/persona@4/dist/index.global.js",
|
|
15
|
+
"https://cdn.runtype.com/other/latest/index.global.js",
|
|
16
|
+
"",
|
|
17
|
+
])("preserves explicit versions and other hosting layouts: %s", (src) => {
|
|
18
|
+
expect(pinCdnRelease(src)).toBe(src);
|
|
19
|
+
});
|
|
20
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { version } from "../../package.json";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* A cached /latest/ entry must keep using its own release, even after another
|
|
5
|
+
* release replaces latest. Only rewrite our published CDN layout; custom hosts
|
|
6
|
+
* and explicitly versioned URLs retain their existing sibling resolution.
|
|
7
|
+
* The bundler embeds this package version in each script-tag entry.
|
|
8
|
+
*/
|
|
9
|
+
export function pinCdnRelease(src: string): string {
|
|
10
|
+
return src.replace(
|
|
11
|
+
/^https:\/\/cdn\.runtype\.com\/persona\/latest\//,
|
|
12
|
+
`https://cdn.runtype.com/persona/${version}/`,
|
|
13
|
+
);
|
|
14
|
+
}
|
|
@@ -182,6 +182,17 @@ describe("mapWireMessages: role filtering", () => {
|
|
|
182
182
|
]);
|
|
183
183
|
expect(mapped.map((message) => message.id)).toEqual(["a", "d", "e"]);
|
|
184
184
|
});
|
|
185
|
+
|
|
186
|
+
it("keeps operator messages from a custom history provider", () => {
|
|
187
|
+
const mapped = mapWireMessages([
|
|
188
|
+
{ id: "a", role: "user", content: "hi", displayAvailable: true },
|
|
189
|
+
{ id: "b", role: "operator", content: "Sam from support", displayAvailable: true },
|
|
190
|
+
]);
|
|
191
|
+
expect(mapped.map((message) => [message.id, message.role])).toEqual([
|
|
192
|
+
["a", "user"],
|
|
193
|
+
["b", "operator"],
|
|
194
|
+
]);
|
|
195
|
+
});
|
|
185
196
|
});
|
|
186
197
|
|
|
187
198
|
describe("mapWireMessages: timestamp synthesis", () => {
|
|
@@ -282,3 +293,22 @@ describe("mergeWireMessagesById", () => {
|
|
|
282
293
|
expect(merged.map((message) => message.id)).toEqual(["a", "c", "b"]);
|
|
283
294
|
});
|
|
284
295
|
});
|
|
296
|
+
|
|
297
|
+
describe("custom history human provenance", () => {
|
|
298
|
+
it("discards malformed author fields from a JavaScript history provider", () => {
|
|
299
|
+
const [message] = mapWireMessages([{ id: "human", role: "operator", content: "Hello", displayAvailable: true,
|
|
300
|
+
author: { id: 42, displayName: null, kind: "admin" } as unknown as HistoryWireMessage["author"] }]);
|
|
301
|
+
expect(message.author).toEqual({});
|
|
302
|
+
});
|
|
303
|
+
it("preserves human identity with text and attachment histories", () => {
|
|
304
|
+
const author = { id: "sam", displayName: "Sam", kind: "human" as const };
|
|
305
|
+
const mapped = mapWireMessages([
|
|
306
|
+
{ id: "human", role: "operator", content: "Refund confirmed", displayAvailable: true, author },
|
|
307
|
+
{ id: "photo", role: "operator", content: [{ type: "image", image: "https://example.com/photo.png" }], displayAvailable: true, author },
|
|
308
|
+
]);
|
|
309
|
+
expect(mapped.map(message => message.author)).toEqual([author, author]);
|
|
310
|
+
expect(mapped.map(message => message.role)).toEqual(["operator", "operator"]);
|
|
311
|
+
expect(mapped[1].contentParts).toEqual([{ type: "image", image: "https://example.com/photo.png" }]);
|
|
312
|
+
expect(mapped[0].author).not.toBe(author);
|
|
313
|
+
});
|
|
314
|
+
});
|
|
@@ -11,6 +11,7 @@ import type {
|
|
|
11
11
|
AgentMessageMetadata,
|
|
12
12
|
AgentWidgetMessage,
|
|
13
13
|
AgentWidgetMessageRole,
|
|
14
|
+
AgentWidgetMessageAuthor,
|
|
14
15
|
ContentPart,
|
|
15
16
|
} from "../types";
|
|
16
17
|
import {
|
|
@@ -24,6 +25,8 @@ import {
|
|
|
24
25
|
|
|
25
26
|
/** One message as served by the client conversation history route. */
|
|
26
27
|
export type HistoryWireMessage = {
|
|
28
|
+
/** Optional display provenance from a custom history adapter. */
|
|
29
|
+
author?: AgentWidgetMessageAuthor;
|
|
27
30
|
id: string;
|
|
28
31
|
role: string;
|
|
29
32
|
/** Model content: string (legacy render-safe fallback) or multi-modal parts. */
|
|
@@ -61,7 +64,9 @@ type HistoryAgentMetadata = AgentMessageMetadata & {
|
|
|
61
64
|
historyDisplayUnavailable?: true;
|
|
62
65
|
};
|
|
63
66
|
|
|
64
|
-
|
|
67
|
+
// `operator` never comes from the Runtype API, but a custom history provider
|
|
68
|
+
// may return it for a human-takeover transcript.
|
|
69
|
+
const WIDGET_ROLES: readonly string[] = ["user", "assistant", "system", "operator"];
|
|
65
70
|
|
|
66
71
|
/** Anchor for a page with no real timestamps and no older bound. */
|
|
67
72
|
const SYNTHETIC_EPOCH_MS = 0;
|
|
@@ -187,13 +192,19 @@ export function mapWireMessages(
|
|
|
187
192
|
if (!WIDGET_ROLES.includes(message.role)) return;
|
|
188
193
|
const role = message.role as AgentWidgetMessageRole;
|
|
189
194
|
const createdAt = createdAtByIndex[index];
|
|
195
|
+
const provenance = message.author;
|
|
196
|
+
const author = provenance && typeof provenance === "object" ? {
|
|
197
|
+
...(typeof provenance.id === "string" && { id: provenance.id }),
|
|
198
|
+
...(typeof provenance.displayName === "string" && { displayName: provenance.displayName }),
|
|
199
|
+
...(["human", "ai", "system"].includes(provenance.kind ?? "") && { kind: provenance.kind }),
|
|
200
|
+
} : undefined;
|
|
190
201
|
|
|
191
202
|
// No reconstructable visible form: render nothing, mark the gap.
|
|
192
203
|
if (message.displayAvailable === false) {
|
|
193
204
|
const agentMetadata: HistoryAgentMetadata = {
|
|
194
205
|
historyDisplayUnavailable: true,
|
|
195
206
|
};
|
|
196
|
-
mapped.push({ id: message.id, role, content: "", createdAt, agentMetadata });
|
|
207
|
+
mapped.push({ id: message.id, role, ...(author && { author }), content: "", createdAt, agentMetadata });
|
|
197
208
|
return;
|
|
198
209
|
}
|
|
199
210
|
|
|
@@ -201,6 +212,7 @@ export function mapWireMessages(
|
|
|
201
212
|
mapped.push({
|
|
202
213
|
id: message.id,
|
|
203
214
|
role,
|
|
215
|
+
...(author && { author }),
|
|
204
216
|
content: message.displayContent,
|
|
205
217
|
createdAt,
|
|
206
218
|
});
|
|
@@ -208,7 +220,7 @@ export function mapWireMessages(
|
|
|
208
220
|
}
|
|
209
221
|
|
|
210
222
|
if (typeof message.content === "string") {
|
|
211
|
-
mapped.push({ id: message.id, role, content: message.content, createdAt });
|
|
223
|
+
mapped.push({ id: message.id, role, ...(author && { author }), content: message.content, createdAt });
|
|
212
224
|
return;
|
|
213
225
|
}
|
|
214
226
|
|
|
@@ -220,6 +232,7 @@ export function mapWireMessages(
|
|
|
220
232
|
mapped.push({
|
|
221
233
|
id: message.id,
|
|
222
234
|
role,
|
|
235
|
+
...(author && { author }),
|
|
223
236
|
content:
|
|
224
237
|
text || (hasImages(parts) ? IMAGE_ONLY_MESSAGE_FALLBACK_TEXT : ""),
|
|
225
238
|
createdAt,
|
|
@@ -228,7 +241,7 @@ export function mapWireMessages(
|
|
|
228
241
|
return;
|
|
229
242
|
}
|
|
230
243
|
|
|
231
|
-
mapped.push({ id: message.id, role, content: "", createdAt });
|
|
244
|
+
mapped.push({ id: message.id, role, ...(author && { author }), content: "", createdAt });
|
|
232
245
|
});
|
|
233
246
|
|
|
234
247
|
return mapped;
|
|
@@ -240,12 +253,17 @@ export function mapWireMessages(
|
|
|
240
253
|
* content already IS the projection, so nothing extra needs sending.
|
|
241
254
|
*/
|
|
242
255
|
export function divergentDisplayProjection(
|
|
243
|
-
message: AgentWidgetMessage
|
|
256
|
+
message: AgentWidgetMessage,
|
|
257
|
+
modelContent = message.contentParts ?? message.llmContent ?? message.rawContent ?? message.content
|
|
244
258
|
): string | undefined {
|
|
245
259
|
const display = message.content;
|
|
246
|
-
if (typeof display !== "string"
|
|
247
|
-
const
|
|
248
|
-
|
|
260
|
+
if (typeof display !== "string") return undefined;
|
|
261
|
+
const originalModel = message.contentParts ?? message.llmContent ?? message.rawContent ?? display;
|
|
262
|
+
// Preserve legacy empty-display behavior unless a host conversion introduced
|
|
263
|
+
// new model-only content (for example attribution on a media-only human reply).
|
|
264
|
+
if (display === "" && (modelContent === originalModel ||
|
|
265
|
+
JSON.stringify(modelContent) === JSON.stringify(originalModel))) return undefined;
|
|
266
|
+
const model = modelContent;
|
|
249
267
|
if (typeof model === "string" && model === display) return undefined;
|
|
250
268
|
return display;
|
|
251
269
|
}
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
export type FingerprintableMessage = {
|
|
11
11
|
id: string;
|
|
12
12
|
role: string;
|
|
13
|
+
author?: { id?: string; displayName?: string; kind?: string };
|
|
13
14
|
content: string;
|
|
14
15
|
streaming?: boolean;
|
|
15
16
|
dispatchError?: boolean;
|
|
@@ -65,6 +66,9 @@ export function computeMessageFingerprint(
|
|
|
65
66
|
return [
|
|
66
67
|
message.id,
|
|
67
68
|
message.role,
|
|
69
|
+
message.author?.id ?? "",
|
|
70
|
+
message.author?.displayName ?? "",
|
|
71
|
+
message.author?.kind ?? "",
|
|
68
72
|
message.content?.length ?? 0,
|
|
69
73
|
message.content?.slice(-32) ?? "",
|
|
70
74
|
message.streaming ? "1" : "0",
|
|
@@ -128,3 +128,16 @@ describe("isEditableUserMessage", () => {
|
|
|
128
128
|
expect(isEditableUserMessage({ role: "user", content: "" })).toBe(false);
|
|
129
129
|
});
|
|
130
130
|
});
|
|
131
|
+
|
|
132
|
+
describe("operator retry boundaries", () => {
|
|
133
|
+
it("does not retry an assistant answer followed by a human reply", () => {
|
|
134
|
+
expect(findRetryableAssistantMessageId([
|
|
135
|
+
{ id: "u", role: "user" }, { id: "a", role: "assistant" }, { id: "h", role: "operator" },
|
|
136
|
+
])).toBeNull();
|
|
137
|
+
});
|
|
138
|
+
it("does not cross a human reply to locate the initiating user", () => {
|
|
139
|
+
const messages = [{ id: "u", role: "user" }, { id: "h", role: "operator" }, { id: "a", role: "assistant" }];
|
|
140
|
+
expect(findPrecedingUserMessageId(messages, "a")).toBeNull();
|
|
141
|
+
expect(findRetryableAssistantMessageId(messages)).toBeNull();
|
|
142
|
+
});
|
|
143
|
+
});
|
|
@@ -33,6 +33,16 @@ export function findUserTurnBoundary(
|
|
|
33
33
|
return { start, end };
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
+
/** Destructive resubmission must never remove a human operator contribution. */
|
|
37
|
+
export function canResubmitUserMessage(
|
|
38
|
+
messages: readonly TurnBoundaryMessage[],
|
|
39
|
+
messageId: string
|
|
40
|
+
): boolean {
|
|
41
|
+
const start = messages.findIndex(message => message.id === messageId);
|
|
42
|
+
return start >= 0 && messages[start].role === "user" &&
|
|
43
|
+
!messages.slice(start + 1).some(message => message.role === "operator");
|
|
44
|
+
}
|
|
45
|
+
|
|
36
46
|
/**
|
|
37
47
|
* The user message that a retry of `messageId` (an assistant message) should
|
|
38
48
|
* replay: the nearest preceding user message. Returns null when the assistant
|
|
@@ -45,6 +55,7 @@ export function findPrecedingUserMessageId(
|
|
|
45
55
|
const index = messages.findIndex((message) => message.id === messageId);
|
|
46
56
|
if (index <= 0) return null;
|
|
47
57
|
for (let i = index - 1; i >= 0; i -= 1) {
|
|
58
|
+
if (messages[i].role === "operator") return null;
|
|
48
59
|
if (messages[i].role === "user") return messages[i].id;
|
|
49
60
|
}
|
|
50
61
|
return null;
|
|
@@ -64,7 +75,7 @@ export function findRetryableAssistantMessageId(
|
|
|
64
75
|
): string | null {
|
|
65
76
|
for (let i = messages.length - 1; i >= 0; i -= 1) {
|
|
66
77
|
const message = messages[i];
|
|
67
|
-
if (message.role === "user") return null;
|
|
78
|
+
if (message.role === "user" || message.role === "operator") return null;
|
|
68
79
|
if (message.streaming) return null;
|
|
69
80
|
if (message.role !== "assistant" || message.variant) continue;
|
|
70
81
|
return findPrecedingUserMessageId(messages, message.id) ? message.id : null;
|
package/src/utils/tokens.ts
CHANGED
|
@@ -258,6 +258,11 @@ const DEFAULT_SEMANTIC_BASE: SemanticTokens = {
|
|
|
258
258
|
},
|
|
259
259
|
};
|
|
260
260
|
|
|
261
|
+
/** Operator bubble fill: the container tinted with the theme primary. */
|
|
262
|
+
const OPERATOR_BACKGROUND = 'color-mix(in srgb, var(--persona-primary) 6%, var(--persona-container))';
|
|
263
|
+
/** Operator bubble border: a stronger primary tint than the fill. */
|
|
264
|
+
const OPERATOR_BORDER = 'color-mix(in srgb, var(--persona-primary) 20%, var(--persona-container))';
|
|
265
|
+
|
|
261
266
|
const DEFAULT_COMPONENTS_BASE: ComponentTokens = {
|
|
262
267
|
button: {
|
|
263
268
|
primary: {
|
|
@@ -360,6 +365,16 @@ const DEFAULT_COMPONENTS_BASE: ComponentTokens = {
|
|
|
360
365
|
border: 'semantic.colors.border',
|
|
361
366
|
shadow: 'palette.shadows.sm',
|
|
362
367
|
},
|
|
368
|
+
operator: {
|
|
369
|
+
// Operator role (human takeover): a primary-tinted container, so it
|
|
370
|
+
// reads apart from the assistant on the same side and follows `brand`.
|
|
371
|
+
background: OPERATOR_BACKGROUND,
|
|
372
|
+
text: 'semantic.colors.text',
|
|
373
|
+
borderRadius: 'palette.radius.lg',
|
|
374
|
+
border: OPERATOR_BORDER,
|
|
375
|
+
borderWidth: '1px',
|
|
376
|
+
shadow: 'palette.shadows.sm',
|
|
377
|
+
},
|
|
363
378
|
border: 'semantic.colors.border',
|
|
364
379
|
},
|
|
365
380
|
introCard: {
|
|
@@ -653,6 +668,16 @@ export const DEFAULT_COMPONENTS_V5: ComponentTokens = {
|
|
|
653
668
|
borderRadius: '0px', shadow: 'none', padding: '0px',
|
|
654
669
|
fontSize: '14px', lineHeight: '1.55',
|
|
655
670
|
},
|
|
671
|
+
// The V5 assistant is flat prose, so the operator keeps a bubble with the
|
|
672
|
+
// user bubble's V5 geometry to stay visibly distinct on the same side. It
|
|
673
|
+
// is outlined, not filled: the stock near-black primary tints a fill to
|
|
674
|
+
// the user bubble's gray, so identity never depends on the primary hue.
|
|
675
|
+
operator: {
|
|
676
|
+
...DEFAULT_COMPONENTS_BASE.message.operator,
|
|
677
|
+
background: 'transparent', border: 'semantic.colors.border',
|
|
678
|
+
borderRadius: 'palette.radius.xl', shadow: 'none', padding: '8px 14px',
|
|
679
|
+
fontSize: '14px', lineHeight: '1.5',
|
|
680
|
+
},
|
|
656
681
|
},
|
|
657
682
|
artifact: {
|
|
658
683
|
...DEFAULT_COMPONENTS_BASE.artifact,
|
|
@@ -1513,6 +1538,11 @@ export function themeToCssVariables(theme: PersonaTheme): Record<string, string>
|
|
|
1513
1538
|
['message-assistant-font-size', 'components-message-assistant-fontSize'],
|
|
1514
1539
|
['message-assistant-font-family', 'components-message-assistant-fontFamily'],
|
|
1515
1540
|
['message-assistant-line-height', 'components-message-assistant-lineHeight'],
|
|
1541
|
+
['message-operator-padding', 'components-message-operator-padding'],
|
|
1542
|
+
['message-operator-max-width', 'components-message-operator-maxWidth'],
|
|
1543
|
+
['message-operator-font-size', 'components-message-operator-fontSize'],
|
|
1544
|
+
['message-operator-font-family', 'components-message-operator-fontFamily'],
|
|
1545
|
+
['message-operator-line-height', 'components-message-operator-lineHeight'],
|
|
1516
1546
|
]);
|
|
1517
1547
|
|
|
1518
1548
|
// Icon button tokens
|
|
@@ -1712,6 +1742,7 @@ export const THEME_ZONES = {
|
|
|
1712
1742
|
messages: 'Message list area',
|
|
1713
1743
|
'user-message': 'User message bubble',
|
|
1714
1744
|
'assistant-message': 'Assistant message bubble',
|
|
1745
|
+
'operator-message': 'Operator message bubble',
|
|
1715
1746
|
composer: 'Footer / composer area',
|
|
1716
1747
|
container: 'Main widget container',
|
|
1717
1748
|
'artifact-pane': 'Artifact sidebar',
|
package/src/welcome.test.ts
CHANGED
|
@@ -279,6 +279,22 @@ describe("resolveConversationState", () => {
|
|
|
279
279
|
expect(isWelcomeVisible(resolveWelcomeConfig(config({ welcome: { dismiss: "on-first-message" } })), [message])).toBe(false);
|
|
280
280
|
});
|
|
281
281
|
|
|
282
|
+
it("treats a visible operator message as activity", () => {
|
|
283
|
+
expect(resolveConversationState([{ ...assistantMessage, role: "operator", content: "Sam here" }])).toBe("active");
|
|
284
|
+
expect(resolveConversationState([{ ...assistantMessage, role: "operator", content: " " }])).toBe("empty");
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
it("treats a media-only operator message as activity", () => {
|
|
288
|
+
const operator = { ...assistantMessage, role: "operator" as const, content: "" };
|
|
289
|
+
for (const part of [
|
|
290
|
+
{ type: "image" as const, image: "https://example.com/receipt.png" },
|
|
291
|
+
{ type: "file" as const, data: "https://example.com/receipt.pdf", mimeType: "application/pdf", filename: "receipt.pdf" },
|
|
292
|
+
]) {
|
|
293
|
+
expect(resolveConversationState([{ ...operator, contentParts: [part] }])).toBe("active");
|
|
294
|
+
}
|
|
295
|
+
expect(resolveConversationState([{ ...operator, contentParts: [{ type: "text", text: " " }] }])).toBe("empty");
|
|
296
|
+
});
|
|
297
|
+
|
|
282
298
|
it("flips to active on the first user message", () => {
|
|
283
299
|
expect(resolveConversationState([userMessage])).toBe("active");
|
|
284
300
|
expect(resolveConversationState([assistantMessage, userMessage])).toBe(
|
package/src/welcome.ts
CHANGED
|
@@ -181,14 +181,22 @@ export const resolveWelcomeConfig = (
|
|
|
181
181
|
* system context do not. Configured `welcome.message` is separate UI chrome,
|
|
182
182
|
* so an intentional greeting never activates the conversation by itself.
|
|
183
183
|
*/
|
|
184
|
+
const hasVisibleContent = (message: AgentWidgetMessage): boolean =>
|
|
185
|
+
Boolean(
|
|
186
|
+
message.content.trim() ||
|
|
187
|
+
message.contentParts?.some((part) => part.type !== "text" || part.text.trim())
|
|
188
|
+
);
|
|
189
|
+
|
|
184
190
|
const hasConversationActivity = (
|
|
185
191
|
messages: readonly AgentWidgetMessage[] = []
|
|
186
192
|
): boolean =>
|
|
187
193
|
messages.some((message) =>
|
|
188
194
|
message.role === "user" ||
|
|
195
|
+
// A human operator speaking is conversation, even before any agent turn,
|
|
196
|
+
// including a media-only message (an image, file, audio or video part).
|
|
197
|
+
(message.role === "operator" && hasVisibleContent(message)) ||
|
|
189
198
|
(message.role === "assistant" && (
|
|
190
|
-
message
|
|
191
|
-
message.contentParts?.some((part) => part.type !== "text" || part.text.trim()) ||
|
|
199
|
+
hasVisibleContent(message) ||
|
|
192
200
|
message.toolCall || message.tools?.length || message.reasoning || message.approval
|
|
193
201
|
))
|
|
194
202
|
);
|
package/dist/chunk-BkOYJ11B.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
const e=`4.32.1`;export{e as t};
|
package/dist/chunk-Bz9jAgba.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{a as e,i as t,l as n,r,s as i}from"./chunk-BlTD-Wgn.js";const a=[`user`,`assistant`,`system`];function o(e){if(typeof e!=`string`||e===``)return null;let t=Date.parse(e);return Number.isNaN(t)?null:t}function s(e){return typeof e==`string`?e:void 0}function c(n){if(typeof n!=`object`||!n)return null;let i=n;switch(i.type){case`text`:return typeof i.text==`string`?e(i.text):null;case`image`:return typeof i.image==`string`?t(i.image,{mimeType:s(i.mimeType),alt:s(i.alt)}):null;case`file`:return typeof i.data==`string`&&typeof i.mimeType==`string`&&typeof i.filename==`string`?r(i.data,i.mimeType,i.filename):null;case`audio`:return typeof i.audio==`string`?{type:`audio`,audio:i.audio,...s(i.mimeType)!==void 0&&{mimeType:i.mimeType}}:null;case`video`:return typeof i.video==`string`?{type:`video`,video:i.video,...s(i.mimeType)!==void 0&&{mimeType:i.mimeType}}:null;default:return null}}function l(e,t){let n=o(t),r=e.map(e=>o(e.timestamp)),i=Array(e.length),a=0;for(;a<r.length;){let e=r[a];if(e!==null){i[a]=e,a+=1;continue}let t=a;for(;t+1<r.length&&r[t+1]===null;)t+=1;let o=t-a+1,s=a>0?i[a-1]:null,c=t+1<r.length?r[t+1]:null,l=c!==null&&n!==null?Math.min(c,n):c??n;for(let e=0;e<o;e+=1)i[a+e]=l===null?s===null?0+e:s+e+1:l-(o-e);a=t+1}return i.map(e=>new Date(e).toISOString())}function u(e,t){let r=l(e,t?.beforeCreatedAt),o=[];return e.forEach((e,t)=>{if(typeof e?.id!=`string`||e.id===``||!a.includes(e.role))return;let s=e.role,l=r[t];if(e.displayAvailable===!1)o.push({id:e.id,role:s,content:``,createdAt:l,agentMetadata:{historyDisplayUnavailable:!0}});else if(typeof e.displayContent==`string`)o.push({id:e.id,role:s,content:e.displayContent,createdAt:l});else if(typeof e.content==`string`)o.push({id:e.id,role:s,content:e.content,createdAt:l});else if(Array.isArray(e.content)){let t=e.content.map(c).filter(e=>e!==null),r=i(t);o.push({id:e.id,role:s,content:r||(n(t)?`[Image]`:``),createdAt:l,...t.length>0&&{contentParts:t}})}else o.push({id:e.id,role:s,content:``,createdAt:l})}),o}function d(e){let t=e.content;if(typeof t!=`string`||t===``)return;let n=e.contentParts??e.llmContent??e.rawContent??t;if(typeof n!=`string`||n!==t)return t}function f(e,t){let n=/* @__PURE__ */ new Map;for(let t of e)n.set(t.id,t);for(let e of t)n.set(e.id,e);return[...n.values()].sort((e,t)=>{let n=new Date(e.createdAt).getTime(),r=new Date(t.createdAt).getTime();if(!Number.isNaN(n)&&!Number.isNaN(r)&&n!==r)return n-r;let i=e.sequence??0,a=t.sequence??0;return i===a?e.id.localeCompare(t.id):i-a})}export{u as n,f as r,d as t};
|
package/dist/chunk-CdpVP6LZ.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
const e=Symbol.for(`persona.defaultsProvenance`),t=e=>typeof e==`object`&&!!e&&!Array.isArray(e);function n(e,r=``){return Object.entries(e).flatMap(([e,i])=>{let a=r?`${r}.${e}`:e;return t(i)?n(i,a):[a]})}function r(e,n){let r=n.split(`.`);for(let n=0;n<r.length;n++){let i=r[n];if(!t(e)||!Object.prototype.hasOwnProperty.call(e,i))return`absent`;if(e=e[i],e===void 0||n<r.length-1&&!t(e))return`clear`}return`explicit`}function i(t,n){return t?.[e]??n.filter(e=>r(t,e)===`explicit`)}function a(t,n){return Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0}),t}function o(e,t,r){return a(e,i(t,n(r)))}function s(t,n,a){let o=n[e];if(o)return o;let s=new Set(i(t,a));for(let e of a){let t=r(n,e);t===`clear`&&s.delete(e),t===`explicit`&&s.add(e)}return[...s]}function c(e,n,r){let i={...e};for(let e of n){if(r.includes(e))continue;let n=e.split(`.`),a=i;for(let e of n.slice(0,-1)){let n=a[e];if(!t(n)){a=void 0;break}a[e]={...n},a=a[e]}a&&delete a[n[n.length-1]]}return i}const l=e=>typeof e==`object`&&!!e&&!Array.isArray(e);function u(e,t){if(!e)return t;if(!t)return e;let n={...e};for(let[e,r]of Object.entries(t)){let t=n[e];n[e]=l(t)&&l(r)?u(t,r):r}return n}const d=e=>{if(typeof e!=`string`)return;let t=e.trim(),n=/^#([\da-f]{3}|[\da-f]{6})$/i.exec(t)?.[1];if(n){let e=n.length===3?[...n].map(e=>e+e).join(``):n;return[0,2,4].map(t=>parseInt(e.slice(t,t+2),16))}let r=/^rgba?\(\s*([^)]*)\)$/i.exec(t);if(!r)return;let i=r[1].trim().split(/\s*[,/]\s*|\s+/);if(i.length===4&&/^(?:1(?:\.0+)?|100%)$/.test(i[3])&&i.pop(),i.length!==3)return;let a=i.map(e=>/^\d+(?:\.\d+)?%?$/.test(e)?Number.parseFloat(e)*(e.endsWith(`%`)?2.55:1):NaN);if(!a.some(e=>!Number.isFinite(e)||e<0||e>255))return a},f=e=>e.reduce((e,t,n)=>{let r=t/255;return e+(r<=.04045?r/12.92:((r+.055)/1.055)**2.4)*[.2126,.7152,.0722][n]},0),p=e=>`#`+e.map(e=>Math.round(e).toString(16).padStart(2,`0`)).join(``),m=(e,t,n)=>p(e.map(e=>e+(t-e)*n)),h=e=>f(e)>.179?`#000000`:`#ffffff`,g=e=>{let t=d(e?.neutral);return t?f(t)<.18?`dark`:`light`:void 0},_=(e,t=`light`,n,r=!1)=>{let i={};if(!e)return i;let a=d(e.accent);if(a){let e={};for(let[t,n]of[[50,.96],[100,.9],[200,.75],[300,.55],[400,.25]])e[t]=m(a,255,n);e[500]=p(a);for(let[t,n]of[[600,.15],[700,.3],[800,.45],[900,.6],[950,.75]])e[t]=m(a,0,n);let t=h(a);i.palette={colors:{primary:e,accent:e}},i.semantic={colors:{primary:e[500],accent:e[500],interactive:{default:e[500],hover:e[600],focus:e[500],active:e[700]}}},i.components={button:{primary:{background:e[500],foreground:t}},launcher:{background:e[500],foreground:t},header:r?{background:`semantic.colors.container`,foreground:`semantic.colors.text`,iconBackground:`transparent`,iconForeground:`semantic.colors.text`}:{background:e[500],foreground:t,iconBackground:e[500],iconForeground:t},approval:{approve:{foreground:t}},message:{user:r?{background:`color-mix(in srgb, var(--persona-primary) 12%, var(--persona-container))`,text:`semantic.colors.text`}:{background:e[500],text:t}}}}let o=d(e.neutral);if(o){let e=t===`dark`,n=e===f(o)<.18?o:d(m(o,e?0:255,.9)),r=p(n),a=m(n,e?255:0,e?.06:.025),s=m(n,e?255:0,e?.2:.16),c=h(n),l={};for(let[e,t]of[[50,0],[100,.06],[200,.16],[300,.28],[400,.45],[500,.65],[600,.72],[700,.8],[800,.9],[900,.97],[950,1]])l[e]=m(n,c===`#ffffff`?255:0,t);i.palette={...i.palette,colors:{...i.palette?.colors,gray:l}},i.semantic={...i.semantic,colors:{...i.semantic?.colors,surface:r,background:r,container:a,border:s,divider:s,text:c,textMuted:m(n,c===`#ffffff`?255:0,.65)}},i.components={...i.components,panel:{background:r},header:{...i.components?.header,background:r,foreground:c},composer:{footerBackground:r}}}if(a){let e=d(i.semantic?.colors?.surface)??(t===`dark`?[15,15,16]:[255,255,255]),n=p(a),r=h(e)===`#ffffff`?255:0;for(let t=0;t<=1;t+=.1){n=m(a,r,t);let i=f(d(n)),o=f(e);if((Math.max(i,o)+.05)/(Math.min(i,o)+.05)>=4.5)break}i.components={...i.components,markdown:{link:{foreground:n}},input:{focus:{border:n,ring:n}}}}e.font?.trim()&&(i.semantic={...i.semantic,typography:{fontFamily:e.font}});let s={none:`0px`,sm:`4px`,md:`8px`,lg:`16px`}[e.radius??`none`];e.radius&&s&&(i.palette={...i.palette,radius:{none:`0px`,sm:s,md:s,lg:s,xl:s,"2xl":s}},i.components={...i.components,input:{...i.components?.input,borderRadius:s},header:{...i.components?.header,controlBorderRadius:s}});let c={compact:[13,44,8],comfortable:[14,48,12],spacious:[15,52,16]}[e.density??`comfortable`];if(e.density&&c){let[e,t,n]=c;i.semantic={...i.semantic,typography:{...i.semantic?.typography,fontSize:`${e}px`}},i.components={...i.components,header:{...i.components?.header,minHeight:`${t}px`,padding:`${n}px 16px`,minimalPadding:`${n}px 16px`},history:{railHeader:{minHeight:`${t}px`}},composer:{...i.components?.composer,fontSize:`${e}px`,padding:`${n}px`,gap:`${n/2}px`},message:{...i.components?.message,gap:`${n}px`,user:{...i.components?.message?.user,fontSize:`${e}px`},assistant:{fontSize:`${e}px`}}}}if(e.elevation&&[`flat`,`subtle`,`raised`].includes(e.elevation)){let t=e.elevation===`flat`,a=t?`none`:e.elevation===`subtle`?`0 2px 8px rgba(0, 0, 0, 0.08)`:`0 12px 32px rgba(0, 0, 0, 0.18)`,o=t?`1px solid var(--persona-border)`:`1px solid color-mix(in srgb, var(--persona-border) 65%, transparent)`;i.palette={...i.palette,shadows:{sm:a,md:a,lg:a,xl:a,"2xl":a}};let s=(e,n=``)=>{let i={};if(r&&n===`message.assistant`)return i;for(let[r,c]of Object.entries(e))if(r.toLowerCase().endsWith(`shadow`)){i[r]=a;let n=r===`shadow`?`border`:r.replace(/Shadow$/,`Border`);n in e&&(i[n]=typeof e[n]==`string`&&e[n].includes(`solid`)?o:t?`semantic.colors.border`:`color-mix(in srgb, var(--persona-border) 65%, transparent)`)}else if(c&&typeof c==`object`){let e=s(c,n?`${n}.${r}`:r);Object.keys(e).length&&(i[r]=e)}return i},c=n?s(n):{};i.components=u(i.components,c),i.components={...i.components,panel:{...i.components?.panel,shadow:a,modes:{floating:{shadow:a,border:o},inline:{shadow:a,border:o},docked:{shadow:a,border:o},sidebar:{shadow:a,border:o},mobile:{shadow:a,border:o}}},launcher:{...i.components?.launcher,shadow:a,border:`semantic.colors.border`},composer:{...i.components?.composer,shadow:a,borderColor:`semantic.colors.border`},toolBubble:{shadow:a},reasoningBubble:{shadow:a}}}return i},v=(e,t)=>t.split(` `).map(t=>`${e}.${t}`),y=[...v(`launcher`,`closeButtonSize closeButtonColor closeButtonBackgroundColor closeButtonBorderWidth closeButtonBorderColor closeButtonBorderRadius closeButtonPaddingX closeButtonPaddingY`),...v(`launcher.clearChat`,`size iconColor backgroundColor borderWidth borderColor borderRadius paddingX paddingY`),...v(`sendButton`,`size iconSize iconStrokeWidth backgroundColor textColor borderWidth borderColor paddingX paddingY`),...v(`voiceRecognition`,`iconSize iconColor backgroundColor borderColor borderWidth paddingX paddingY recordingIconColor recordingBackgroundColor recordingBorderColor processingIconColor processingBackgroundColor processingBorderColor speakingIconColor speakingBackgroundColor speakingBorderColor`),...v(`toolCall`,`shadow backgroundColor borderColor borderWidth borderRadius headerBackgroundColor headerTextColor headerPaddingX headerPaddingY contentBackgroundColor contentTextColor contentPaddingX contentPaddingY codeBlockBackgroundColor codeBlockBorderColor codeBlockTextColor toggleTextColor labelTextColor loadingAnimationColor loadingAnimationSecondaryColor loadingAnimationDuration`),...v(`approval`,`backgroundColor borderColor shadow titleColor descriptionColor reasonColor approveButtonColor approveButtonTextColor denyButtonColor denyButtonTextColor parameterBackgroundColor parameterTextColor`),...v(`features.askUserQuestion.styles`,`sheetBackground sheetBorder sheetShadow pillBackground pillBackgroundSelected pillTextColor pillTextColorSelected pillBorderRadius customInputBackground`),...v(`features.artifacts.layout`,`paneBackground panePadding paneBorderRadius paneShadow chatShadow paneBorder paneBorderLeft unifiedSplitOuterRadius documentToolbarIconColor documentToolbarToggleActiveBackground documentToolbarToggleActiveBorderColor documentToolbarToggleActiveColor tabFadeSize`),...v(`suggestionChipsConfig`,`fontWeight paddingX paddingY`)],b=[`voice.recording.border`,`voice.processing.icon`,`voice.processing.background`,`voice.speaking.icon`,`approval.requested.text`,`approval.approve.foreground`,`approval.deny.foreground`,`approval.deny.background`,`reasoningBubble.shadow`,`toolBubble.shadow`],x=[...y,`suggestionChips`,`copy.welcomeTitle`,`copy.welcomeSubtitle`,`copy.showWelcomeCard`,`features.suggestReplies.enabled`,`features.suggestReplies.expose`,...[`theme`,`darkTheme`].flatMap(e=>b.map(t=>`${e}.components.${t}`))],S=Symbol.for(`persona.styleProvenance`),C=e=>e[S]!==void 0,w=(e,t)=>{for(let n of t.split(`.`)){if(typeof e!=`object`||!e)return;e=e[n]}return e},T=e=>{let t=e?.[S];if(!t)return x.filter(t=>r(e,t)===`explicit`);let n=new Set(t.explicit);return x.forEach(i=>{w(e,i)!==t.values[i]&&(r(e,i)===`explicit`?n.add(i):n.delete(i))}),[...n]},E=(e,t)=>(Object.defineProperty(e,S,{value:{explicit:t,values:Object.fromEntries(x.map(t=>[t,w(e,t)]))},enumerable:!0,configurable:!0}),e),D=(e,t)=>E(e,T(t)),O=(e,t)=>{if(t[S])return T(t);let n=new Set(T(e));for(let e of x){let i=r(t,e);i===`clear`&&n.delete(e),i===`explicit`&&n.add(e)}return[...n]},k=(e,t)=>{let n=e?.[S];return!n||!Object.prototype.hasOwnProperty.call(n.values,t)||w(e,t)!==n.values[t]?r(e,t)===`explicit`:n.explicit.includes(t)},A=(e,t)=>k(e,t)?w(e,t):void 0,j=(e,t,n)=>{let r=e,i=n??r?.colorScheme??g(r?.brand)??`light`,a=i===`dark`||i===`auto`&&(typeof document<`u`&&document.documentElement.classList.contains(`dark`)||typeof window<`u`&&window.matchMedia?.(`(prefers-color-scheme: dark)`).matches);return k(e,`theme.components.${t}`)||a&&k(e,`darkTheme.components.${t}`)};export{r as _,j as a,E as c,g as d,u as f,a as g,c as h,k as i,O as l,o as m,b as n,C as o,i as p,A as r,D as s,y as t,_ as u,s as v,n as y};
|
package/dist/chunk-DM-OJt5q.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{n as e}from"./chunk-BAdIgC5d.js";import{t}from"./chunk-BkOYJ11B.js";import{t as n}from"./chunk-Bz9jAgba.js";import{n as r}from"./chunk-DTDHeUsG.js";const i=e=>e.replace(/[^a-zA-Z0-9_]/g,`_`).toLowerCase().replace(/_+/g,`_`).replace(/^_|_$/g,``),a=e=>typeof e==`object`&&!!e&&!Array.isArray(e),o=e=>{if(e.variant!==`tool`)return null;let t=e.agentMetadata?.clientToolAnswer;if(!t||!t.toolCallId||t.result===void 0)return null;let n=i(t.toolName);return n?{call:{toolCallId:t.toolCallId,toolName:n,args:a(t.args)?t.args:{}},result:{toolCallId:t.toolCallId,toolName:n,result:t.result}}:null},s=(e,t)=>{let n=[],r=[],i=[],a=``,s,c=()=>{r.length!==0&&(n.push({role:`assistant`,content:``,createdAt:a,toolCalls:r},{role:`tool`,content:``,createdAt:a,toolResults:i}),r=[],i=[])};for(let l of e){let e=o(l);if(e){let t=l.agentMetadata?.clientToolAnswer?.batch;r.length>0&&(t===void 0||t!==s)&&c(),r.length===0&&(a=l.createdAt,s=t),r.some(t=>t.toolCallId===e.call.toolCallId)||(r.push(e.call),i.push(e.result));continue}let u=t(l);u&&(c(),n.push(u))}return c(),n},c=e=>e.voiceCaption||r(e)?!1:!!(e.contentParts&&e.contentParts.length>0||e.llmContent&&e.llmContent.trim().length>0||e.rawContent&&e.rawContent.trim().length>0||e.content&&e.content.trim().length>0),l=e=>e.slice().sort((e,t)=>new Date(e.createdAt).getTime()-new Date(t.createdAt).getTime()),u=e=>{let t=e.agentMetadata?.providerPhase??e.agentMetadata?.phase;return e.role===`assistant`&&(t===`commentary`||t===`partial_answer`||t===`final_answer`)?{phase:t}:{}},d=e=>({role:e.role,content:e.contentParts??e.llmContent??e.rawContent??e.content,createdAt:e.createdAt,...u(e)});var f=class{constructor(e){this.host=e}async initializeSession(){await this.host.historyInternals.historyBootstrapReady;let e=this.host.config.getStoredConversationId?.()||null,t=this.host.historyInternals.shouldResumeDurableConversation?.()===!0;if(!this.host.isHistoryCapable()&&!t)return this.#e(e,!1);let n=await this.host.readVisitorToken();if(e&&n)try{let n=await this.createClientSession({conversationId:e,durableResume:t});return t&&n.durableRecovery?.enabled!==!0&&this.host.historyInternals.setStoredResumableHandle?.(null),this.host.finishInit(n,e,!1)}catch(n){if(!(n instanceof this.host.HistoryClientError&&n.code===`not_found`)&&!(n instanceof this.host.HistoryClientError&&n.code===`visitor_required`)&&!(n instanceof this.host.HistoryClientError&&n.code===`history_disabled`))throw n;return t&&this.host.historyInternals.setStoredResumableHandle?.(null),this.#e(e,!0)}return this.#e(e,!1)}async#e(e,t){let n=this.host.historyInternals.visitorStore;return n&&!await this.host.readVisitorToken()?n.withFirstInitLock(()=>this.#t(e,t)):this.#t(e,t)}async#t(e,t){let n=this.host.config.getStoredSessionId?.()||null,r=await this.createClientSession({storedSessionId:n}),i=await this.#n(r);return this.host.finishInit(i,e,t)}async#n(e){if(!e.visitor?.token||this.host.claimInFlight||!this.host.isHistoryCapable()&&e.durableRecovery?.enabled!==!0)return e;this.host.claimInFlight=!0;try{return await this.createClientSession({storedSessionId:e.sessionId})}catch{return e}finally{this.host.claimInFlight=!1}}async sendWithClientToolsDiff(t,n,r,i){let a=!!(n&&n.length>0),o=a?e(n):void 0,s=this.host.clientToolsFingerprintSessionId===t,c=a&&s&&this.host.lastSentClientToolsFingerprint===o,l=!a&&i?.emptyMeansReplace===!0&&this.host.sentNonEmptyClientToolsSessionId===t,u=!1,d;for(let e=0;d=await r({...a&&(u||!c)&&n?{clientTools:n}:{},...l?{clientTools:[]}:{},...o?{clientToolsFingerprint:o}:{}}),d.status===409&&e===0&&a&&(await d.clone().json().catch(()=>null))?.error===`client_tools_resend_required`;e++)u=!0,this.host.lastSentClientToolsFingerprint=null;return{response:d,commit:()=>{this.host.lastSentClientToolsFingerprint=o??null,this.host.clientToolsFingerprintSessionId=t,a?this.host.sentNonEmptyClientToolsSessionId=t:l&&(this.host.sentNonEmptyClientToolsSessionId=null)}}}async createClientSession(e){let n=this.host.isHistoryCapable()&&!e.omitVisitorFields,r=!e.omitVisitorFields,i=null;(n||r)&&(await this.host.historyInternals.historyBootstrapReady,i=await this.host.readVisitorToken());let a=this.host.routing(),o=a.agentId??a.flowId,s=n||e.durableResume?e.conversationId:void 0,c={token:this.host.config.clientToken,...o&&{flowId:o},...n&&{visitorHistory:!0},...r&&{durableRecovery:!0},...(n||r)&&i?{visitorToken:i}:{},...n&&e.identityProof?{identityProof:e.identityProof}:{},...s?{conversationId:s}:e.storedSessionId?{sessionId:e.storedSessionId}:{}};e.signal?.throwIfAborted();let l=await fetch(this.host.getClientApiUrl(`init`),{method:`POST`,headers:{"Content-Type":`application/json`,"X-Persona-Version":t},body:JSON.stringify(c),signal:e.signal});if(!l.ok){let t=await l.json().catch(()=>({error:`Session initialization failed`}));if(n&&l.status===403&&t.error===`visitor_history_disabled`){if(this.host.markHistoryUnavailable(),s)throw new this.host.HistoryClientError(`history_disabled`,`Visitor history is disabled for this surface`);return this.createClientSession({...e,omitVisitorFields:!0})}throw l.status===403&&t.error===`durable_recovery_disabled`?new this.host.HistoryClientError(`history_disabled`,`Durable recovery is disabled for this surface`):(n||e.durableResume)&&l.status===401&&t.error===`visitor_required`?new this.host.HistoryClientError(`visitor_required`,`Visitor credential no longer resolves`):s&&l.status===404?new this.host.HistoryClientError(`not_found`,`Conversation not found`):l.status===401?Error(`Invalid client token: ${t.hint||t.error}`):l.status===403?Error(`Origin not allowed: ${t.hint||t.error}`):Error(t.error||`Failed to initialize session`)}let u=await l.json();return u.visitor?.token&&await this.host.historyInternals.visitorStore?.set(u.visitor.token),{sessionId:u.sessionId,expiresAt:new Date(u.expiresAt),flow:u.flow,...u.conversationId?{conversationId:u.conversationId}:{},...u.targetId?{targetId:u.targetId}:{},...u.conversationRevision?{conversationRevision:u.conversationRevision}:{},...u.durableRecovery?{durableRecovery:u.durableRecovery}:{},...u.visitor?{visitor:u.visitor}:{},config:{welcomeMessage:u.config.welcomeMessage,placeholder:u.config.placeholder,theme:u.config.theme}}}async sendFeedback(e){if([`upvote`,`downvote`,`copy`].includes(e.type)&&!e.messageId)throw Error(`messageId is required for ${e.type} feedback type`);if(e.type===`csat`&&(e.rating===void 0||e.rating<1||e.rating>5))throw Error(`CSAT rating must be between 1 and 5`);if(e.type===`nps`&&(e.rating===void 0||e.rating<0||e.rating>10))throw Error(`NPS rating must be between 0 and 10`);this.host.debug&&console.debug(`[AgentWidgetClient] sending feedback`,e);let n={...e,...this.host.config.clientToken&&{token:this.host.config.clientToken}},r=await fetch(`${this.host.clientApiBase()}/v1/client/feedback`,{method:`POST`,headers:{"Content-Type":`application/json`,"X-Persona-Version":t},body:JSON.stringify(n)});if(!r.ok){let e=await r.json().catch(()=>({error:`Feedback submission failed`}));throw r.status===401?(this.host.clientSession=null,this.host.resetSessionWarmLatch(),this.host.config.onSessionExpired?.(),Error(`Session expired. Please refresh to continue.`)):Error(e.error||`Failed to submit feedback`)}}async dispatchClientToken(e,r,i){let{HistoryClientError:a}=this.host,o=()=>this.host.isCurrentTurn(i),s=e=>{o()&&r(e)};try{let r=()=>{if(e.signal?.throwIfAborted(),!o())throw new DOMException(`Turn superseded`,`AbortError`)},l=this.host.clientSession??await this.host.initSession();r();let u=async()=>{r();let t=l,n=t.durableRecovery?.enabled===!0;if(n&&(!t.conversationId||!await this.host.readVisitorToken()))throw Error(`Renewing this conversation requires its visitor credential.`);r();let i=await this.host.createClientSession({...n||this.host.isHistoryCapable()?{conversationId:t.conversationId,durableResume:n}:{storedSessionId:t.sessionId},signal:e.signal});if(r(),t.conversationId&&i.conversationId!==t.conversationId||n&&i.durableRecovery?.enabled!==!0)throw Error(`Session renewal did not preserve this conversation.`);l=this.host.finishInit(i,t.conversationId??null,!1),this.host.clientSession=l,this.host.resetSessionWarmLatch(),this.host.resetClientToolsFingerprint(),this.host.config.onSessionInit?.(l)};Date.now()>=l.expiresAt.getTime()-6e4&&await u();let d=await this.#c(e.messages),f=d.metadata?Object.fromEntries(Object.entries(d.metadata).filter(([e])=>e!==`sessionId`&&e!==`session_id`)):void 0,p=this.host.isHistoryCapable(),m={sessionId:l.sessionId,messages:e.messages.filter(c).map(e=>{let t=p?n(e):void 0;return{id:e.id,role:e.role,content:e.contentParts??e.llmContent??e.rawContent??e.content,...t!==void 0&&{displayContent:t}}}),...e.assistantMessageId&&{assistantMessageId:e.assistantMessageId},...f&&Object.keys(f).length>0&&{metadata:f},...d.inputs&&Object.keys(d.inputs).length>0&&{inputs:d.inputs},...d.context&&{context:d.context},turnId:i,...e.interrupt&&{submitMode:`interrupt`},...e.voiceSpoken&&{voice:{spoken:!0,...e.voicePriorToolResults?.length&&{priorToolResults:e.voicePriorToolResults}}}},h=async()=>{r();let n=l.durableRecovery?.enabled===!0?await this.host.readVisitorToken():null;return r(),this.host.sendWithClientToolsDiff(l.sessionId,d.clientTools,async i=>{r();let a=await this.host.resolveChatIdentityProof(e.signal);r();let o={...m,sessionId:l.sessionId,...i,...a&&{identityProof:a}};return this.host.debug&&console.debug(`[AgentWidgetClient] client token dispatch`,{...o,...a&&{identityProof:{provider:a.provider,token:`[REDACTED]`}}}),fetch(this.host.getClientApiUrl(`chat`),{method:`POST`,headers:{"Content-Type":`application/json`,"X-Persona-Version":t,...n?{"X-Visitor-Token":n}:{}},body:JSON.stringify(o),signal:e.signal})})},g=await h();if(r(),g.response.status===401){let e=await g.response.clone().json().catch(()=>null);r(),e?.error===`Session not found or expired`&&(await u(),g=await h(),r())}let{response:_,commit:v}=g;if(!_.ok){let e=await _.json().catch(()=>({error:`Chat request failed`}));if(_.status===401&&e.error===`invalid_identity_proof`){let e=new a(`invalid_identity_proof`,`The identity proof was rejected`);throw s({type:`error`,error:e}),e}if(_.status===401){this.host.clearClientSession(),this.host.config.onSessionExpired?.();let e=/* @__PURE__ */ Error(`Session expired. Please refresh to continue.`);throw s({type:`error`,error:e}),e}if(_.status===429){let t=Error(e.hint||`Message limit reached for this session.`);throw s({type:`error`,error:t}),t}if(_.status===410&&e.error===`conversation_deleted`){let e=new a(`conversation_deleted`,`This conversation was deleted`);throw s({type:`error`,error:e}),e}let t=Error(e.error||`Failed to send message`);throw s({type:`error`,error:t}),t}if(!_.body){let e=/* @__PURE__ */ Error(`No response body received`);throw s({type:`error`,error:e}),e}v(),s({type:`status`,status:`connected`});try{await this.host.streamResponse(_.body,s,e.assistantMessageId,void 0,e.signal)}finally{s({type:`status`,status:`idle`})}}catch(e){let t=e instanceof Error?e:Error(String(e));throw!(t instanceof a)&&!t.message.includes(`Session expired`)&&!t.message.includes(`Message limit`)&&s({type:`error`,error:t}),t}}async dispatchProxy(e,t){let n=await this.#c(e.messages,e.composerOptions);this.host.debug&&console.debug(`[AgentWidgetClient] dispatch payload`,n);let r={...this.host.headers};if(this.host.getHeaders)try{let e=await this.host.getHeaders();r={...r,...e}}catch(e){typeof console<`u`&&console.error(`[AgentWidget] getHeaders error:`,e)}let i;if(this.host.customFetch)try{i=await this.host.customFetch(this.host.apiUrl,{method:`POST`,headers:r,body:JSON.stringify(n),signal:e.signal},n)}catch(e){let n=e instanceof Error?e:Error(String(e));throw t({type:`error`,error:n}),n}else i=await fetch(this.host.apiUrl,{method:`POST`,headers:r,body:JSON.stringify(n),signal:e.signal});if(!i.ok||!i.body){let e=/* @__PURE__ */ Error(`Chat backend request failed: ${i.status} ${i.statusText}`);throw t({type:`error`,error:e}),e}t({type:`status`,status:`connected`});try{await this.host.streamResponse(i.body,t,void 0,void 0,e.signal)}finally{t({type:`status`,status:`idle`})}}async dispatchAgent(e,t){let n=await this.#s(e.messages,e.composerOptions);this.host.debug&&console.debug(`[AgentWidgetClient] agent dispatch payload`,n);let r={...this.host.headers};if(this.host.getHeaders)try{let e=await this.host.getHeaders();r={...r,...e}}catch(e){typeof console<`u`&&console.error(`[AgentWidget] getHeaders error:`,e)}let i;if(this.host.customFetch)try{i=await this.host.customFetch(this.host.apiUrl,{method:`POST`,headers:r,body:JSON.stringify(n),signal:e.signal},n)}catch(e){let n=e instanceof Error?e:Error(String(e));throw t({type:`error`,error:n}),n}else i=await fetch(this.host.apiUrl,{method:`POST`,headers:r,body:JSON.stringify(n),signal:e.signal});if(!i.ok||!i.body){let e=/* @__PURE__ */ Error(`Agent execution request failed: ${i.status} ${i.statusText}`);throw t({type:`error`,error:e}),e}t({type:`status`,status:`connected`});try{await this.host.streamResponse(i.body,t,e.assistantMessageId,void 0,e.signal)}finally{t({type:`status`,status:`idle`})}}#r(e){for(let t=e.length-1;t>=0;t--){let n=e[t];if(n.role===`user`)return n.mentionContext&&Object.keys(n.mentionContext).length>0?{mentions:n.mentionContext}:null}return null}async#i(e){let t={};this.host.contextProviders.length&&await Promise.all(this.host.contextProviders.map(async n=>{try{let r=await n({messages:e,config:this.host.config});r&&typeof r==`object`&&Object.assign(t,r)}catch(e){typeof console<`u`&&console.warn(`[AgentWidget] Context provider failed:`,e)}}));let n=this.#r(e);return n&&Object.assign(t,n),Object.keys(t).length?t:null}#a(e){if(!e)return;let t={};return e.selectedModelId&&(t.selectedModelId=e.selectedModelId),e.activeModeIds?.length&&(t.activeModeIds=[...e.activeModeIds]),Object.keys(t).length>0?t:void 0}#o(e,t){let n=t?.selectedModelId;return!n||!(`model`in e)?e:this.host.config.composer?.models?.some(e=>e.id===n)?{...e,model:n}:e}async#s(e,t){let n=this.host.routing().agentId;if(!this.host.config.agent&&!n)throw Error(`Agent configuration required for agent mode`);let r=s(l(e),e=>c(e)&&(e.role===`user`||e.role===`assistant`||e.role===`system`)&&(!e.variant||e.variant===`assistant`)?d(e):null),i=this.#a(t),a={agent:this.#o(this.host.config.agent??{agentId:n},i),messages:r,options:{streamResponse:!0,recordMode:`virtual`,...this.host.config.agentOptions}};i&&(a.composerOptions=i);let o=[...this.host.builtInClientTools(this.host.config),...await(await this.host.getWebMcpBridge())?.snapshotForDispatch()??[]];o.length>0&&(a.clientTools=o);let u=await this.#i(e);return u&&(a.context=u),a}async#c(e,t){let n=s(l(e),e=>c(e)?d(e):null),r=this.host.routing(),i={messages:n,...r.agentId?{agent:{agentId:r.agentId}}:r.flowId?{flowId:r.flowId}:{}};if(r.targetPayload)for(let[e,t]of Object.entries(r.targetPayload))e!==`messages`&&(i[e]=t);let a=[...this.host.builtInClientTools(this.host.config),...await(await this.host.getWebMcpBridge())?.snapshotForDispatch()??[]];a.length>0&&(i.clientTools=a);let o=await this.#i(e);o&&(i.context=o);let u=this.#a(t);if(u&&(i.composerOptions=u),this.host.requestMiddleware)try{let e=await this.host.requestMiddleware({payload:{...i},config:this.host.config});if(e&&typeof e==`object`){let t=e;return i.clientTools!==void 0&&!(`clientTools`in t)&&(t.clientTools=i.clientTools),t}}catch(e){typeof console<`u`&&console.error(`[AgentWidget] Request middleware error:`,e)}return i}};export{f as ClientDispatch};
|