@runtypelabs/persona 4.7.0 → 4.9.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/README.md +1 -0
- package/dist/animations/glyph-cycle.cjs +2 -2
- package/dist/animations/glyph-cycle.d.cts +1 -1
- package/dist/animations/glyph-cycle.d.ts +1 -1
- package/dist/animations/glyph-cycle.js +2 -2
- package/dist/animations/{types-CSmiKRVa.d.cts → types-4ROVJ1gA.d.cts} +85 -3
- package/dist/animations/{types-CSmiKRVa.d.ts → types-4ROVJ1gA.d.ts} +85 -3
- package/dist/animations/wipe.cjs +2 -2
- package/dist/animations/wipe.d.cts +1 -1
- package/dist/animations/wipe.d.ts +1 -1
- package/dist/chunk-5EIIHQLQ.js +1 -0
- package/dist/chunk-IO5VVUKP.js +3 -0
- package/dist/chunk-IPVK3KOM.js +1 -0
- package/dist/chunk-UPO4GUFC.js +1 -0
- package/dist/codegen.cjs +13 -13
- package/dist/codegen.js +14 -14
- package/dist/context-mentions-7S5KVUTG.js +169 -0
- package/dist/context-mentions-inline-TTCN7ZM2.js +4 -0
- package/dist/context-mentions-inline.cjs +4 -0
- package/dist/context-mentions-inline.d.cts +203 -0
- package/dist/context-mentions-inline.d.ts +203 -0
- package/dist/context-mentions-inline.js +4 -0
- package/dist/context-mentions.cjs +295 -0
- package/dist/context-mentions.d.cts +7025 -0
- package/dist/context-mentions.d.ts +7025 -0
- package/dist/context-mentions.js +295 -0
- package/dist/index.cjs +99 -68
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1507 -182
- package/dist/index.d.ts +1507 -182
- package/dist/index.global.js +88 -56
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +99 -68
- 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 +3 -2
- package/dist/launcher.global.js.map +1 -1
- package/dist/markdown-parsers.js +24 -24
- package/dist/plugin-kit.cjs +1 -1
- package/dist/plugin-kit.d.cts +17 -0
- package/dist/plugin-kit.d.ts +17 -0
- package/dist/plugin-kit.js +1 -1
- package/dist/runtype-tts-entry-UJAEF7NZ.js +1 -0
- package/dist/runtype-tts.js +1 -1
- package/dist/session-reconnect-JKIJBHS5.js +1 -0
- package/dist/smart-dom-reader.cjs +18 -17
- package/dist/smart-dom-reader.d.cts +1260 -16
- package/dist/smart-dom-reader.d.ts +1260 -16
- package/dist/smart-dom-reader.js +18 -17
- package/dist/testing.cjs +3 -3
- package/dist/testing.js +3 -3
- package/dist/theme-editor-preview.cjs +260 -58
- package/dist/theme-editor-preview.d.cts +1234 -15
- package/dist/theme-editor-preview.d.ts +1234 -15
- package/dist/theme-editor-preview.js +87 -58
- package/dist/theme-editor.cjs +10 -10
- package/dist/theme-editor.d.cts +1226 -15
- package/dist/theme-editor.d.ts +1226 -15
- package/dist/theme-editor.js +10 -10
- package/dist/theme-reference.cjs +1 -1
- package/dist/theme-reference.d.cts +76 -0
- package/dist/theme-reference.d.ts +76 -0
- package/dist/theme-reference.js +1 -1
- package/dist/voice-worklet-player.cjs +2 -2
- package/dist/voice-worklet-player.js +2 -2
- package/dist/webmcp-polyfill.js +2 -2
- package/dist/widget.css +1 -1
- package/package.json +16 -5
- package/src/artifacts-session.test.ts +178 -0
- package/src/client.test.ts +255 -1
- package/src/client.ts +157 -60
- package/src/components/artifact-card.test.ts +333 -0
- package/src/components/artifact-card.ts +75 -28
- package/src/components/artifact-inline.test.ts +1328 -0
- package/src/components/artifact-inline.ts +920 -0
- package/src/components/artifact-pane.test.ts +1042 -0
- package/src/components/artifact-pane.ts +440 -131
- package/src/components/artifact-preview.test.ts +1155 -0
- package/src/components/artifact-preview.ts +994 -0
- package/src/components/composer-parts.ts +3 -12
- package/src/components/context-mention-button.test.ts +70 -0
- package/src/components/context-mention-button.ts +82 -0
- package/src/components/context-mention-chip.ts +134 -0
- package/src/components/context-mention-menu.test.ts +508 -0
- package/src/components/context-mention-menu.ts +0 -0
- package/src/components/message-bubble.test.ts +175 -0
- package/src/components/message-bubble.ts +177 -19
- package/src/components/panel.ts +7 -10
- package/src/components/pill-composer-builder.test.ts +6 -2
- package/src/components/pill-composer-builder.ts +6 -6
- package/src/components/reasoning-bubble.ts +1 -13
- package/src/components/registry.ts +38 -3
- package/src/components/tool-bubble.ts +1 -13
- package/src/context-mentions-bundle.test.ts +163 -0
- package/src/context-mentions-entry.ts +185 -0
- package/src/context-mentions-inline-entry.test.ts +136 -0
- package/src/context-mentions-inline-entry.ts +226 -0
- package/src/context-mentions-inline-loader.test.ts +30 -0
- package/src/context-mentions-inline-loader.ts +36 -0
- package/src/context-mentions-inline.ts +15 -0
- package/src/context-mentions-loader.ts +32 -0
- package/src/context-mentions.ts +16 -0
- package/src/defaults.ts +1 -0
- package/src/generated/runtype-openapi-contract.ts +55 -3
- package/src/index-core.ts +46 -1
- package/src/index-global.ts +51 -0
- package/src/index.ts +8 -0
- package/src/markdown-parsers-loader.test.ts +158 -0
- package/src/markdown-parsers-loader.ts +83 -27
- package/src/plugin-kit.test.ts +40 -0
- package/src/plugin-kit.ts +39 -5
- package/src/runtime/host-layout.test.ts +163 -0
- package/src/runtime/host-layout.ts +110 -7
- package/src/runtime/init.ts +18 -61
- package/src/session.mentions.test.ts +175 -0
- package/src/session.test.ts +52 -4
- package/src/session.ts +197 -27
- package/src/smart-dom-reader.test.ts +129 -2
- package/src/smart-dom-reader.ts +127 -1
- package/src/styles/context-mention-menu-css.ts +176 -0
- package/src/styles/widget.css +1002 -152
- package/src/theme-editor/preview.ts +2 -0
- package/src/theme-editor/sections.test.ts +26 -1
- package/src/theme-editor/sections.ts +13 -5
- package/src/theme-reference.ts +2 -2
- package/src/tool-call-display-defaults.test.ts +1 -0
- package/src/types/theme.ts +79 -0
- package/src/types.ts +1041 -17
- package/src/ui.artifact-pane-gating.test.ts +636 -0
- package/src/ui.component-directive.test.ts +104 -0
- package/src/ui.composer-bar.test.ts +60 -2
- package/src/ui.detached-panel.test.ts +1049 -0
- package/src/ui.mention-submit.test.ts +235 -0
- package/src/ui.tool-display.test.ts +51 -0
- package/src/ui.ts +998 -159
- package/src/utils/artifact-custom-actions.ts +128 -0
- package/src/utils/artifact-display.test.ts +42 -0
- package/src/utils/artifact-display.ts +84 -0
- package/src/utils/artifact-file.test.ts +116 -0
- package/src/utils/artifact-file.ts +117 -0
- package/src/utils/artifact-gate.test.ts +112 -5
- package/src/utils/artifact-gate.ts +39 -14
- package/src/utils/artifact-loading-status.ts +55 -0
- package/src/utils/artifact-status-label.ts +190 -0
- package/src/utils/buttons.ts +7 -1
- package/src/utils/chunk-loader.test.ts +97 -0
- package/src/utils/chunk-loader.ts +88 -0
- package/src/utils/code-highlight.test.ts +186 -0
- package/src/utils/code-highlight.ts +400 -0
- package/src/utils/composer-contenteditable.test.ts +507 -0
- package/src/utils/composer-contenteditable.ts +626 -0
- package/src/utils/composer-document.test.ts +280 -0
- package/src/utils/composer-document.ts +293 -0
- package/src/utils/composer-history.test.ts +35 -7
- package/src/utils/composer-history.ts +30 -20
- package/src/utils/composer-input.ts +159 -0
- package/src/utils/context-mention-controller.test.ts +1215 -0
- package/src/utils/context-mention-controller.ts +1186 -0
- package/src/utils/context-mention-manager.test.ts +422 -0
- package/src/utils/context-mention-manager.ts +410 -0
- package/src/utils/context-mention-orchestrator.test.ts +538 -0
- package/src/utils/context-mention-orchestrator.ts +348 -0
- package/src/utils/icons.ts +2 -0
- package/src/utils/live-region.test.ts +108 -0
- package/src/utils/live-region.ts +94 -0
- package/src/utils/mention-channels.ts +63 -0
- package/src/utils/mention-llm-format.test.ts +91 -0
- package/src/utils/mention-llm-format.ts +79 -0
- package/src/utils/mention-matcher.test.ts +86 -0
- package/src/utils/mention-matcher.ts +221 -0
- package/src/utils/mention-token.ts +72 -0
- package/src/utils/mention-trigger.test.ts +155 -0
- package/src/utils/mention-trigger.ts +156 -0
- package/src/utils/roving-tablist.test.ts +152 -0
- package/src/utils/roving-tablist.ts +111 -0
- package/src/utils/spinner.ts +45 -0
- package/src/utils/theme.test.ts +76 -4
- package/src/utils/theme.ts +7 -0
- package/src/utils/tokens.ts +118 -11
- package/src/utils/tool-loading-animation.test.ts +32 -0
- package/src/utils/tool-loading-animation.ts +24 -0
- package/dist/chunk-DFBSCFYN.js +0 -1
- package/dist/runtype-tts-entry-HFUV2UF7.js +0 -1
- package/dist/session-reconnect-U77QFUR7.js +0 -1
package/src/utils/theme.test.ts
CHANGED
|
@@ -169,6 +169,31 @@ describe('theme utils', () => {
|
|
|
169
169
|
expect(customVars['--persona-header-action-icon-fg']).toBe('#9ca3af');
|
|
170
170
|
});
|
|
171
171
|
|
|
172
|
+
it('maps button.ghost tokens to the composer ghost icon-button CSS variables', () => {
|
|
173
|
+
const cssVars = themeToCssVariables(createTheme());
|
|
174
|
+
|
|
175
|
+
// The composer's transparent icon buttons (.persona-mention-button /
|
|
176
|
+
// .persona-attachment-button) read these instead of hardcoded inline styles.
|
|
177
|
+
expect(cssVars['--persona-button-ghost-bg']).toBe('transparent');
|
|
178
|
+
expect(cssVars['--persona-button-ghost-fg']).toBe('#111827'); // semantic.text → gray.900
|
|
179
|
+
expect(cssVars['--persona-button-ghost-radius']).toBe('0.375rem'); // radius.md
|
|
180
|
+
expect(cssVars['--persona-button-ghost-hover-bg']).toBe('rgba(0, 0, 0, 0.05)');
|
|
181
|
+
|
|
182
|
+
const custom = createTheme({
|
|
183
|
+
components: {
|
|
184
|
+
button: {
|
|
185
|
+
ghost: {
|
|
186
|
+
foreground: 'palette.colors.accent.500',
|
|
187
|
+
hoverBackground: 'palette.colors.gray.100',
|
|
188
|
+
},
|
|
189
|
+
},
|
|
190
|
+
},
|
|
191
|
+
} as any);
|
|
192
|
+
const customVars = themeToCssVariables(custom);
|
|
193
|
+
expect(customVars['--persona-button-ghost-fg']).toBe('#06b6d4'); // accent.500
|
|
194
|
+
expect(customVars['--persona-button-ghost-hover-bg']).toBe('#f3f4f6'); // gray.100
|
|
195
|
+
});
|
|
196
|
+
|
|
172
197
|
it('defaults artifact pane fill from semantic container and resolves toolbar background token refs', () => {
|
|
173
198
|
const theme = createTheme();
|
|
174
199
|
const cssVars = themeToCssVariables(theme);
|
|
@@ -192,6 +217,38 @@ describe('theme utils', () => {
|
|
|
192
217
|
expect(surfaceVars['--persona-artifact-toolbar-bg']).toBe('#f9fafb');
|
|
193
218
|
});
|
|
194
219
|
|
|
220
|
+
it('maps artifact inline chrome tokens to dedicated CSS variables (with semantic refs)', () => {
|
|
221
|
+
const theme = createTheme({
|
|
222
|
+
components: {
|
|
223
|
+
artifact: {
|
|
224
|
+
inline: {
|
|
225
|
+
background: 'semantic.colors.surface',
|
|
226
|
+
border: '1px solid #e5e7eb',
|
|
227
|
+
borderRadius: '12px',
|
|
228
|
+
chromeBackground: 'semantic.colors.container',
|
|
229
|
+
chromeBorder: '#e5e7eb',
|
|
230
|
+
titleColor: 'palette.colors.gray.900',
|
|
231
|
+
mutedColor: 'palette.colors.gray.500',
|
|
232
|
+
frameHeight: '400px',
|
|
233
|
+
},
|
|
234
|
+
},
|
|
235
|
+
},
|
|
236
|
+
} as any);
|
|
237
|
+
|
|
238
|
+
const cssVars = themeToCssVariables(theme);
|
|
239
|
+
|
|
240
|
+
// semantic.* refs resolve to concrete colors; plain values pass through.
|
|
241
|
+
// surface and container both default to gray.50.
|
|
242
|
+
expect(cssVars['--persona-artifact-inline-bg']).toBe('#f9fafb');
|
|
243
|
+
expect(cssVars['--persona-artifact-inline-border']).toBe('1px solid #e5e7eb');
|
|
244
|
+
expect(cssVars['--persona-artifact-inline-radius']).toBe('12px');
|
|
245
|
+
expect(cssVars['--persona-artifact-inline-chrome-bg']).toBe('#f9fafb');
|
|
246
|
+
expect(cssVars['--persona-artifact-inline-chrome-border']).toBe('#e5e7eb');
|
|
247
|
+
expect(cssVars['--persona-artifact-inline-title-color']).toBe('#111827');
|
|
248
|
+
expect(cssVars['--persona-artifact-inline-muted-color']).toBe('#6b7280');
|
|
249
|
+
expect(cssVars['--persona-artifact-inline-frame-height']).toBe('400px');
|
|
250
|
+
});
|
|
251
|
+
|
|
195
252
|
it('maps component bubble shadow tokens to consumer CSS variables', () => {
|
|
196
253
|
const cfg = {
|
|
197
254
|
colorScheme: 'light' as const,
|
|
@@ -280,12 +337,11 @@ describe('theme utils', () => {
|
|
|
280
337
|
);
|
|
281
338
|
});
|
|
282
339
|
|
|
283
|
-
it('
|
|
340
|
+
it('defaults the intro card to flat (transparent, no shadow) when no token is set', () => {
|
|
284
341
|
const theme = createTheme({});
|
|
285
342
|
const cssVars = themeToCssVariables(theme);
|
|
286
|
-
expect(cssVars['--persona-intro-card-shadow']).toBe(
|
|
287
|
-
|
|
288
|
-
);
|
|
343
|
+
expect(cssVars['--persona-intro-card-shadow']).toBe('none');
|
|
344
|
+
expect(cssVars['--persona-intro-card-bg']).toBe('transparent');
|
|
289
345
|
});
|
|
290
346
|
|
|
291
347
|
it('drives --persona-tool-bubble-shadow from the theme token (config.toolCall.shadow is applied inline on the bubble, not the root var)', () => {
|
|
@@ -305,4 +361,20 @@ describe('theme utils', () => {
|
|
|
305
361
|
'0 1px 2px rgba(255,0,0,0.5)'
|
|
306
362
|
);
|
|
307
363
|
});
|
|
364
|
+
|
|
365
|
+
it('stamps the resolved color scheme on the root so scheme-scoped CSS (syntax palette) follows the widget, not the OS', () => {
|
|
366
|
+
const el = document.createElement('div');
|
|
367
|
+
applyThemeVariables(el, { colorScheme: 'light' });
|
|
368
|
+
expect(el.getAttribute('data-persona-color-scheme')).toBe('light');
|
|
369
|
+
applyThemeVariables(el, { colorScheme: 'dark' });
|
|
370
|
+
expect(el.getAttribute('data-persona-color-scheme')).toBe('dark');
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
it('maps components.code.background to --persona-code-bg', () => {
|
|
374
|
+
const theme = createTheme({
|
|
375
|
+
components: { code: { background: '#fafafa' } },
|
|
376
|
+
});
|
|
377
|
+
const cssVars = themeToCssVariables(theme);
|
|
378
|
+
expect(cssVars['--persona-code-bg']).toBe('#fafafa');
|
|
379
|
+
});
|
|
308
380
|
});
|
package/src/utils/theme.ts
CHANGED
|
@@ -194,6 +194,13 @@ export const applyThemeVariables = (
|
|
|
194
194
|
for (const [name, value] of Object.entries(cssVars)) {
|
|
195
195
|
element.style.setProperty(name, value);
|
|
196
196
|
}
|
|
197
|
+
|
|
198
|
+
// Stamp the resolved scheme so stylesheet rules can key scheme-specific
|
|
199
|
+
// defaults (e.g. the syntax-highlight palette) off the widget's own color
|
|
200
|
+
// scheme instead of the OS prefers-color-scheme, which diverges whenever a
|
|
201
|
+
// host pins colorScheme. Re-applied on every theme application, so live
|
|
202
|
+
// config updates and theme-observer callbacks keep it current.
|
|
203
|
+
element.setAttribute("data-persona-color-scheme", getColorScheme(config));
|
|
197
204
|
};
|
|
198
205
|
|
|
199
206
|
export const createThemeObserver = (
|
package/src/utils/tokens.ts
CHANGED
|
@@ -13,6 +13,11 @@ import {
|
|
|
13
13
|
DEFAULT_FLOATING_LAUNCHER_WIDTH,
|
|
14
14
|
} from '../defaults';
|
|
15
15
|
|
|
16
|
+
// Detached/docked panel defaults, shared by the panel token defaults, the alias
|
|
17
|
+
// fallbacks below, host-layout, the theme editor, and the artifact gate.
|
|
18
|
+
export const DEFAULT_PANEL_INSET = '16px';
|
|
19
|
+
export const DEFAULT_PANEL_CANVAS_BACKGROUND = 'transparent';
|
|
20
|
+
|
|
16
21
|
export const DEFAULT_PALETTE = {
|
|
17
22
|
colors: {
|
|
18
23
|
primary: {
|
|
@@ -258,6 +263,9 @@ export const DEFAULT_COMPONENTS: ComponentTokens = {
|
|
|
258
263
|
foreground: 'semantic.colors.text',
|
|
259
264
|
borderRadius: 'palette.radius.md',
|
|
260
265
|
padding: 'semantic.spacing.sm',
|
|
266
|
+
// Subtle neutral tint on hover — the composer's transparent icon buttons
|
|
267
|
+
// (attachment, mention) read this via `--persona-button-ghost-hover-bg`.
|
|
268
|
+
hoverBackground: 'rgba(0, 0, 0, 0.05)',
|
|
261
269
|
},
|
|
262
270
|
},
|
|
263
271
|
input: {
|
|
@@ -287,6 +295,8 @@ export const DEFAULT_COMPONENTS: ComponentTokens = {
|
|
|
287
295
|
maxHeight: 'calc(100vh - 80px)',
|
|
288
296
|
borderRadius: 'palette.radius.xl',
|
|
289
297
|
shadow: 'palette.shadows.xl',
|
|
298
|
+
inset: DEFAULT_PANEL_INSET,
|
|
299
|
+
canvasBackground: DEFAULT_PANEL_CANVAS_BACKGROUND,
|
|
290
300
|
},
|
|
291
301
|
header: {
|
|
292
302
|
// Header role: solid primary
|
|
@@ -319,12 +329,12 @@ export const DEFAULT_COMPONENTS: ComponentTokens = {
|
|
|
319
329
|
border: 'semantic.colors.border',
|
|
320
330
|
},
|
|
321
331
|
introCard: {
|
|
322
|
-
//
|
|
323
|
-
//
|
|
324
|
-
background: '
|
|
332
|
+
// Flat by default: the greeting reads as plain text on the transcript
|
|
333
|
+
// background (the industry norm), not an elevated card.
|
|
334
|
+
background: 'transparent',
|
|
325
335
|
borderRadius: 'palette.radius.2xl',
|
|
326
336
|
padding: 'semantic.spacing.lg',
|
|
327
|
-
shadow: '
|
|
337
|
+
shadow: 'palette.shadows.none',
|
|
328
338
|
},
|
|
329
339
|
toolBubble: {
|
|
330
340
|
shadow: 'palette.shadows.sm',
|
|
@@ -732,6 +742,21 @@ export function themeToCssVariables(theme: PersonaTheme): Record<string, string>
|
|
|
732
742
|
cssVars['--persona-components-button-primary-borderRadius'] ??
|
|
733
743
|
cssVars['--persona-palette-radius-full'] ??
|
|
734
744
|
'9999px';
|
|
745
|
+
// Ghost variant: transparent, neutral-foreground icon buttons (the composer's
|
|
746
|
+
// attachment + mention affordances). Wired to `components.button.ghost.*`.
|
|
747
|
+
cssVars['--persona-button-ghost-bg'] =
|
|
748
|
+
cssVars['--persona-components-button-ghost-background'] ??
|
|
749
|
+
'transparent';
|
|
750
|
+
cssVars['--persona-button-ghost-fg'] =
|
|
751
|
+
cssVars['--persona-components-button-ghost-foreground'] ??
|
|
752
|
+
cssVars['--persona-text'];
|
|
753
|
+
cssVars['--persona-button-ghost-radius'] =
|
|
754
|
+
cssVars['--persona-components-button-ghost-borderRadius'] ??
|
|
755
|
+
cssVars['--persona-radius-md'] ??
|
|
756
|
+
'0.375rem';
|
|
757
|
+
cssVars['--persona-button-ghost-hover-bg'] =
|
|
758
|
+
cssVars['--persona-components-button-ghost-hoverBackground'] ??
|
|
759
|
+
'rgba(0, 0, 0, 0.05)';
|
|
735
760
|
cssVars['--persona-panel-radius'] =
|
|
736
761
|
cssVars['--persona-components-panel-borderRadius'] ??
|
|
737
762
|
cssVars['--persona-radius-xl'] ??
|
|
@@ -742,6 +767,10 @@ export function themeToCssVariables(theme: PersonaTheme): Record<string, string>
|
|
|
742
767
|
cssVars['--persona-components-panel-shadow'] ??
|
|
743
768
|
cssVars['--persona-palette-shadows-xl'] ??
|
|
744
769
|
'0 25px 50px -12px rgba(0, 0, 0, 0.25)';
|
|
770
|
+
cssVars['--persona-panel-inset'] =
|
|
771
|
+
cssVars['--persona-components-panel-inset'] ?? DEFAULT_PANEL_INSET;
|
|
772
|
+
cssVars['--persona-panel-canvas-bg'] =
|
|
773
|
+
cssVars['--persona-components-panel-canvasBackground'] ?? DEFAULT_PANEL_CANVAS_BACKGROUND;
|
|
745
774
|
cssVars['--persona-launcher-shadow'] =
|
|
746
775
|
cssVars['--persona-components-launcher-shadow'] ??
|
|
747
776
|
'0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgba(0, 0, 0, 0.1)';
|
|
@@ -780,19 +809,17 @@ export function themeToCssVariables(theme: PersonaTheme): Record<string, string>
|
|
|
780
809
|
if (headerTokens?.borderBottom) cssVars['--persona-header-border-bottom'] = headerTokens.borderBottom;
|
|
781
810
|
|
|
782
811
|
// Intro card aliases: short names the panel inline-styles read directly.
|
|
783
|
-
// The full-path `--persona-components-introCard-*` variables auto-emit above
|
|
784
|
-
//
|
|
785
|
-
|
|
812
|
+
// The full-path `--persona-components-introCard-*` variables auto-emit above.
|
|
813
|
+
// Default is flat (transparent, no shadow): the greeting renders as plain
|
|
814
|
+
// text on the transcript background; set introCard tokens for a card look.
|
|
786
815
|
cssVars['--persona-intro-card-bg'] =
|
|
787
|
-
cssVars['--persona-components-introCard-background'] ??
|
|
816
|
+
cssVars['--persona-components-introCard-background'] ?? 'transparent';
|
|
788
817
|
cssVars['--persona-intro-card-radius'] =
|
|
789
818
|
cssVars['--persona-components-introCard-borderRadius'] ?? '1rem';
|
|
790
819
|
cssVars['--persona-intro-card-padding'] =
|
|
791
820
|
cssVars['--persona-components-introCard-padding'] ?? '1.5rem';
|
|
792
821
|
cssVars['--persona-intro-card-shadow'] =
|
|
793
|
-
|
|
794
|
-
?? cssVars['--persona-components-introCard-shadow']
|
|
795
|
-
?? '0 5px 15px rgba(15, 23, 42, 0.08)';
|
|
822
|
+
cssVars['--persona-components-introCard-shadow'] ?? 'none';
|
|
796
823
|
|
|
797
824
|
cssVars['--persona-input-background'] =
|
|
798
825
|
cssVars['--persona-components-input-background'] ?? cssVars['--persona-surface'];
|
|
@@ -967,6 +994,10 @@ export function themeToCssVariables(theme: PersonaTheme): Record<string, string>
|
|
|
967
994
|
if (t.iconBorder) cssVars['--persona-artifact-toolbar-icon-border'] = t.iconBorder;
|
|
968
995
|
if (t.toggleGroupGap) cssVars['--persona-artifact-toolbar-toggle-group-gap'] = t.toggleGroupGap;
|
|
969
996
|
if (t.toggleBorderRadius) cssVars['--persona-artifact-toolbar-toggle-radius'] = t.toggleBorderRadius;
|
|
997
|
+
if (t.toggleGroupPadding) cssVars['--persona-artifact-toolbar-toggle-group-padding'] = t.toggleGroupPadding;
|
|
998
|
+
if (t.toggleGroupBorder) cssVars['--persona-artifact-toolbar-toggle-group-border'] = t.toggleGroupBorder;
|
|
999
|
+
if (t.toggleGroupBorderRadius) cssVars['--persona-artifact-toolbar-toggle-group-radius'] = t.toggleGroupBorderRadius;
|
|
1000
|
+
if (t.toggleGroupBackground) cssVars['--persona-artifact-toolbar-toggle-group-bg'] = resolveTokenValue(theme, t.toggleGroupBackground) ?? t.toggleGroupBackground;
|
|
970
1001
|
if (t.copyBackground) cssVars['--persona-artifact-toolbar-copy-bg'] = t.copyBackground;
|
|
971
1002
|
if (t.copyBorder) cssVars['--persona-artifact-toolbar-copy-border'] = t.copyBorder;
|
|
972
1003
|
if (t.copyColor) cssVars['--persona-artifact-toolbar-copy-color'] = t.copyColor;
|
|
@@ -1015,6 +1046,80 @@ export function themeToCssVariables(theme: PersonaTheme): Record<string, string>
|
|
|
1015
1046
|
cssVars['--persona-artifact-toolbar-bg'] = toolbarBg;
|
|
1016
1047
|
}
|
|
1017
1048
|
}
|
|
1049
|
+
if (artifact?.card) {
|
|
1050
|
+
const t = artifact.card;
|
|
1051
|
+
if (t.background) cssVars['--persona-artifact-card-bg'] = t.background;
|
|
1052
|
+
if (t.border) cssVars['--persona-artifact-card-border'] = t.border;
|
|
1053
|
+
if (t.borderRadius) cssVars['--persona-artifact-card-radius'] = t.borderRadius;
|
|
1054
|
+
if (t.hoverBackground) cssVars['--persona-artifact-card-hover-bg'] = t.hoverBackground;
|
|
1055
|
+
if (t.hoverBorderColor) cssVars['--persona-artifact-card-hover-border'] = t.hoverBorderColor;
|
|
1056
|
+
}
|
|
1057
|
+
if (artifact?.inline) {
|
|
1058
|
+
const t = artifact.inline;
|
|
1059
|
+
if (t.background) {
|
|
1060
|
+
cssVars['--persona-artifact-inline-bg'] =
|
|
1061
|
+
resolveTokenValue(theme, t.background) ?? t.background;
|
|
1062
|
+
}
|
|
1063
|
+
if (t.border) cssVars['--persona-artifact-inline-border'] = t.border;
|
|
1064
|
+
if (t.borderRadius) cssVars['--persona-artifact-inline-radius'] = t.borderRadius;
|
|
1065
|
+
if (t.chromeBackground) {
|
|
1066
|
+
cssVars['--persona-artifact-inline-chrome-bg'] =
|
|
1067
|
+
resolveTokenValue(theme, t.chromeBackground) ?? t.chromeBackground;
|
|
1068
|
+
}
|
|
1069
|
+
if (t.chromeBorder) {
|
|
1070
|
+
cssVars['--persona-artifact-inline-chrome-border'] =
|
|
1071
|
+
resolveTokenValue(theme, t.chromeBorder) ?? t.chromeBorder;
|
|
1072
|
+
}
|
|
1073
|
+
if (t.titleColor) {
|
|
1074
|
+
cssVars['--persona-artifact-inline-title-color'] =
|
|
1075
|
+
resolveTokenValue(theme, t.titleColor) ?? t.titleColor;
|
|
1076
|
+
}
|
|
1077
|
+
if (t.mutedColor) {
|
|
1078
|
+
cssVars['--persona-artifact-inline-muted-color'] =
|
|
1079
|
+
resolveTokenValue(theme, t.mutedColor) ?? t.mutedColor;
|
|
1080
|
+
}
|
|
1081
|
+
if (t.frameHeight) cssVars['--persona-artifact-inline-frame-height'] = t.frameHeight;
|
|
1082
|
+
}
|
|
1083
|
+
|
|
1084
|
+
// Code (syntax-highlighted artifact source view) tokens.
|
|
1085
|
+
const code = components?.code;
|
|
1086
|
+
if (code) {
|
|
1087
|
+
if (code.keywordColor) cssVars['--persona-code-keyword-color'] = code.keywordColor;
|
|
1088
|
+
if (code.stringColor) cssVars['--persona-code-string-color'] = code.stringColor;
|
|
1089
|
+
if (code.commentColor) cssVars['--persona-code-comment-color'] = code.commentColor;
|
|
1090
|
+
if (code.numberColor) cssVars['--persona-code-number-color'] = code.numberColor;
|
|
1091
|
+
if (code.tagColor) cssVars['--persona-code-tag-color'] = code.tagColor;
|
|
1092
|
+
if (code.attrColor) cssVars['--persona-code-attr-color'] = code.attrColor;
|
|
1093
|
+
if (code.propertyColor) cssVars['--persona-code-property-color'] = code.propertyColor;
|
|
1094
|
+
if (code.lineNumberColor) cssVars['--persona-code-line-number-color'] = code.lineNumberColor;
|
|
1095
|
+
if (code.gutterBorderColor) cssVars['--persona-code-gutter-border-color'] = code.gutterBorderColor;
|
|
1096
|
+
if (code.background)
|
|
1097
|
+
cssVars['--persona-code-bg'] = resolveTokenValue(theme, code.background) ?? code.background;
|
|
1098
|
+
}
|
|
1099
|
+
|
|
1100
|
+
// Interactive-state defaults. The default preset resolves container === surface,
|
|
1101
|
+
// which turns every hover/active rule that falls back to --persona-container
|
|
1102
|
+
// into a visual no-op; anchor those states one gray step down in that case.
|
|
1103
|
+
// Component config emitted above must keep winning, so only fill vars not set.
|
|
1104
|
+
const stateSurface = cssVars['--persona-surface'];
|
|
1105
|
+
const stateContainer = cssVars['--persona-container'];
|
|
1106
|
+
const gray100 = cssVars['--persona-palette-colors-gray-100'] ?? '#f3f4f6';
|
|
1107
|
+
const gray200 = cssVars['--persona-palette-colors-gray-200'] ?? '#e5e7eb';
|
|
1108
|
+
const gray300 = cssVars['--persona-palette-colors-gray-300'] ?? '#d1d5db';
|
|
1109
|
+
const flatTheme = !stateContainer || stateContainer === stateSurface;
|
|
1110
|
+
const hoverBgDefault = flatTheme ? gray100 : stateContainer;
|
|
1111
|
+
const activeBgDefault = flatTheme ? gray200 : stateContainer;
|
|
1112
|
+
cssVars['--persona-icon-btn-hover-bg'] = cssVars['--persona-icon-btn-hover-bg'] ?? hoverBgDefault;
|
|
1113
|
+
cssVars['--persona-icon-btn-active-bg'] = cssVars['--persona-icon-btn-active-bg'] ?? activeBgDefault;
|
|
1114
|
+
if (flatTheme) {
|
|
1115
|
+
cssVars['--persona-icon-btn-active-border'] =
|
|
1116
|
+
cssVars['--persona-icon-btn-active-border'] ?? gray300;
|
|
1117
|
+
}
|
|
1118
|
+
cssVars['--persona-label-btn-hover-bg'] = cssVars['--persona-label-btn-hover-bg'] ?? hoverBgDefault;
|
|
1119
|
+
cssVars['--persona-artifact-tab-hover-bg'] =
|
|
1120
|
+
cssVars['--persona-artifact-tab-hover-bg'] ?? hoverBgDefault;
|
|
1121
|
+
cssVars['--persona-artifact-card-hover-bg'] =
|
|
1122
|
+
cssVars['--persona-artifact-card-hover-bg'] ?? hoverBgDefault;
|
|
1018
1123
|
|
|
1019
1124
|
return cssVars;
|
|
1020
1125
|
}
|
|
@@ -1041,6 +1146,8 @@ export const THEME_ZONES = {
|
|
|
1041
1146
|
container: 'Main widget container',
|
|
1042
1147
|
'artifact-pane': 'Artifact sidebar',
|
|
1043
1148
|
'artifact-toolbar': 'Artifact toolbar',
|
|
1149
|
+
'artifact-inline': 'Inline artifact block',
|
|
1150
|
+
'artifact-inline-chrome': 'Inline artifact title bar',
|
|
1044
1151
|
} as const;
|
|
1045
1152
|
|
|
1046
1153
|
export type ThemeZone = keyof typeof THEME_ZONES;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// @vitest-environment jsdom
|
|
2
|
+
|
|
3
|
+
import { describe, expect, it } from "vitest";
|
|
4
|
+
import { appendCharSpans } from "./tool-loading-animation";
|
|
5
|
+
|
|
6
|
+
const NBSP = String.fromCharCode(0xa0);
|
|
7
|
+
|
|
8
|
+
describe("appendCharSpans", () => {
|
|
9
|
+
it("wraps each character in a persona-tool-char span with a staggered index", () => {
|
|
10
|
+
const container = document.createElement("div");
|
|
11
|
+
const next = appendCharSpans(container, "ab", 0);
|
|
12
|
+
|
|
13
|
+
const spans = container.querySelectorAll(".persona-tool-char");
|
|
14
|
+
expect(spans.length).toBe(2);
|
|
15
|
+
expect((spans[0] as HTMLElement).style.getPropertyValue("--char-index")).toBe("0");
|
|
16
|
+
expect((spans[1] as HTMLElement).style.getPropertyValue("--char-index")).toBe("1");
|
|
17
|
+
expect(spans[0].textContent).toBe("a");
|
|
18
|
+
expect(spans[1].textContent).toBe("b");
|
|
19
|
+
expect(next).toBe(2);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it("renders spaces as non-breaking spaces and honors the start index", () => {
|
|
23
|
+
const container = document.createElement("div");
|
|
24
|
+
const next = appendCharSpans(container, "a b", 5);
|
|
25
|
+
|
|
26
|
+
const spans = container.querySelectorAll(".persona-tool-char");
|
|
27
|
+
expect(spans.length).toBe(3);
|
|
28
|
+
expect((spans[0] as HTMLElement).style.getPropertyValue("--char-index")).toBe("5");
|
|
29
|
+
expect(spans[1].textContent).toBe(NBSP);
|
|
30
|
+
expect(next).toBe(8);
|
|
31
|
+
});
|
|
32
|
+
});
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { createElement } from "./dom";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Append text as individual animated character spans.
|
|
5
|
+
* Each character becomes a `persona-tool-char` span carrying a `--char-index`
|
|
6
|
+
* custom property so the shimmer/rainbow keyframes can stagger their delay.
|
|
7
|
+
* Spaces are rendered as non-breaking spaces so they animate like any other
|
|
8
|
+
* character. Returns the next available character index.
|
|
9
|
+
*/
|
|
10
|
+
export const appendCharSpans = (
|
|
11
|
+
container: HTMLElement,
|
|
12
|
+
text: string,
|
|
13
|
+
startIndex: number
|
|
14
|
+
): number => {
|
|
15
|
+
let idx = startIndex;
|
|
16
|
+
for (const char of text) {
|
|
17
|
+
const span = createElement("span", "persona-tool-char");
|
|
18
|
+
span.style.setProperty("--char-index", String(idx));
|
|
19
|
+
span.textContent = char === " " ? "\u00A0" : char;
|
|
20
|
+
container.appendChild(span);
|
|
21
|
+
idx++;
|
|
22
|
+
}
|
|
23
|
+
return idx;
|
|
24
|
+
};
|
package/dist/chunk-DFBSCFYN.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
var a=class{constructor(e=24e3,t={}){this.ctx=null;this.nextStartTime=0;this.activeSources=[];this.finishedCallbacks=[];this.startedCallbacks=[];this.playing=!1;this.streamEnded=!1;this.pendingCount=0;this.started=!1;this.userPaused=!1;this.pendingBuffers=[];this.pendingSamples=0;this.remainder=null;var s;this.sampleRate=e;let i=Math.max(0,(s=t.prebufferMs)!=null?s:0);this.waterlineSamples=Math.round(e*i/1e3),this.buffering=this.waterlineSamples>0}ensureContext(){if(!this.ctx){let t=typeof window!="undefined"?window:void 0;if(!t)throw new Error("AudioPlaybackManager requires a browser environment");let i=t.AudioContext||t.webkitAudioContext;this.ctx=new i({sampleRate:this.sampleRate})}let e=this.ctx;return e.state==="suspended"&&!this.userPaused&&e.resume(),e}enqueue(e){if(e.length===0)return;let t=e;if(this.remainder){let s=new Uint8Array(this.remainder.length+e.length);s.set(this.remainder),s.set(e,this.remainder.length),t=s,this.remainder=null}if(t.length%2!==0&&(this.remainder=new Uint8Array([t[t.length-1]]),t=t.subarray(0,t.length-1)),t.length===0)return;let i=this.pcmToFloat32(t);i.length!==0&&(this.buffering?(this.pendingBuffers.push(i),this.pendingSamples+=i.length,this.pendingSamples>=this.waterlineSamples&&this.releaseBuffer()):this.scheduleSamples(i))}markStreamEnd(){this.pendingBuffers.length>0&&this.releaseBuffer(),this.streamEnded=!0,this.checkFinished()}flush(){for(let e of this.activeSources)try{e.stop(),e.disconnect()}catch{}this.activeSources=[],this.pendingCount=0,this.nextStartTime=0,this.playing=!1,this.streamEnded=!1,this.finishedCallbacks=[],this.startedCallbacks=[],this.remainder=null,this.pendingBuffers=[],this.pendingSamples=0,this.buffering=this.waterlineSamples>0,this.started=!1}isPlaying(){return this.playing}onFinished(e){this.finishedCallbacks.push(e)}onStarted(e){this.startedCallbacks.push(e)}pause(){this.userPaused=!0,this.ctx&&this.ctx.state==="running"&&this.ctx.suspend()}resume(){this.userPaused=!1,this.ctx&&this.ctx.state==="suspended"&&this.ctx.resume()}async destroy(){this.flush(),this.ctx&&(await this.ctx.close(),this.ctx=null)}releaseBuffer(){this.buffering=!1;let e=this.pendingBuffers;this.pendingBuffers=[],this.pendingSamples=0;for(let t of e)this.scheduleSamples(t)}scheduleSamples(e){if(e.length===0)return;let t=this.ensureContext(),i=t.createBuffer(1,e.length,this.sampleRate);i.getChannelData(0).set(e);let s=t.createBufferSource();s.buffer=i,s.connect(t.destination);let n=t.currentTime;if(this.nextStartTime===0?this.nextStartTime=n:this.nextStartTime<n&&(this.nextStartTime=n,this.waterlineSamples>0&&(this.buffering=!0)),s.start(this.nextStartTime),this.nextStartTime+=i.duration,this.activeSources.push(s),this.pendingCount++,this.playing=!0,!this.started){this.started=!0;let r=this.startedCallbacks.slice();this.startedCallbacks=[];for(let h of r)h()}s.onended=()=>{let r=this.activeSources.indexOf(s);r!==-1&&this.activeSources.splice(r,1),this.pendingCount--,this.checkFinished()}}checkFinished(){if(this.streamEnded&&this.pendingCount<=0&&this.pendingBuffers.length===0){this.playing=!1,this.streamEnded=!1;let e=this.finishedCallbacks.slice();this.finishedCallbacks=[];for(let t of e)t()}}pcmToFloat32(e){let t=Math.floor(e.length/2),i=new Float32Array(t),s=new DataView(e.buffer,e.byteOffset,e.byteLength);for(let n=0;n<t;n++){let r=s.getInt16(n*2,!0);i[n]=r/32768}return i}};export{a};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{a as c}from"./chunk-DFBSCFYN.js";function g(o){return o.replace(/\/+$/,"")}var m=class{constructor(e){this.opts=e;this.id="runtype-tts";this.supportsPause=!0;this.player=null;this.playerPromise=null;this.generation=0}ensurePlayer(){var e,t;return(t=this.playerPromise)!=null?t:this.playerPromise=Promise.resolve(this.opts.createPlaybackEngine?this.opts.createPlaybackEngine():new c(24e3,{prebufferMs:(e=this.opts.prebufferMs)!=null?e:200})).then(r=>this.player=r)}speak(e,t){let r=++this.generation;this.run(r,e,t)}async run(e,t,r){var i,a,p,h;try{let n=await this.ensurePlayer();if(e!==this.generation)return;n.flush(),n.resume(),n.onStarted(()=>{var s;e===this.generation&&((s=r.onStart)==null||s.call(r))}),n.onFinished(()=>{var s;e===this.generation&&((s=r.onEnd)==null||s.call(r))});let u=`${g(this.opts.host)}/v1/agents/${encodeURIComponent(this.opts.agentId)}/speak`,y=await fetch(u,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.opts.clientToken}`},body:JSON.stringify({text:t.text,voice:(i=t.voice)!=null?i:this.opts.voice,format:"pcm"})});if(e!==this.generation)return;if(!y.ok||!y.body)throw new Error(await S(y));let v=y.body.getReader();for(;;){let{done:s,value:d}=await v.read();if(e!==this.generation){await v.cancel().catch(()=>{});return}if(s)break;d&&d.byteLength>0&&n.enqueue(d)}n.markStreamEnd()}catch(n){if(e!==this.generation)return;let u=n instanceof Error?n:new Error(String(n));(p=(a=this.opts).onError)==null||p.call(a,u),(h=r.onError)==null||h.call(r,u)}}pause(){var e;(e=this.player)==null||e.pause()}resume(){var e;(e=this.player)==null||e.resume()}stop(){var e;this.generation++,(e=this.player)==null||e.flush()}destroy(){var e;this.generation++,(e=this.player)==null||e.destroy(),this.player=null,this.playerPromise=null}};async function S(o){var e,t;try{let r=await o.json();return r.detail?`${(e=r.error)!=null?e:`Runtype TTS ${o.status}`}: ${r.detail}`:(t=r.error)!=null?t:`Runtype TTS request failed (${o.status})`}catch{return`Runtype TTS request failed (${o.status})`}}var f=class{constructor(e,t,r={}){this.primary=e;this.fallback=t;this.options=r;this.id="fallback";this.active=e}get supportsPause(){return this.active.supportsPause}speak(e,t){this.active=this.primary;let r=!1;this.primary.speak(e,{onStart:()=>{var i;r=!0,(i=t.onStart)==null||i.call(t)},onEnd:()=>{var i;return(i=t.onEnd)==null?void 0:i.call(t)},onError:i=>{var a,p,h;if(r){(a=t.onError)==null||a.call(t,i);return}(h=(p=this.options).onFallback)==null||h.call(p,i),this.active=this.fallback,this.fallback.speak(e,t)}})}pause(){this.active.pause()}resume(){this.active.resume()}stop(){this.active.stop()}destroy(){var e,t,r,i;(t=(e=this.primary).destroy)==null||t.call(e),(i=(r=this.fallback).destroy)==null||i.call(r)}};export{f as FallbackSpeechEngine,m as RuntypeSpeechEngine};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
var k=[1e3,2e3,4e3,8e3,8e3];function T(e){let t=0,r=null,i=null,g=!1,b=()=>{if(i&&(clearTimeout(i),i=null),r){let n=r;r=null,n()}},v=()=>{let n=e.getStatus();n!=="resuming"&&n!=="paused"||b()},p=()=>{typeof document!="undefined"&&document.visibilityState==="hidden"||v()},R=()=>{v()},C=()=>{g||(typeof document!="undefined"&&document.addEventListener("visibilitychange",p),typeof window!="undefined"&&window.addEventListener("online",R),g=!0)},m=()=>{g&&(typeof document!="undefined"&&document.removeEventListener("visibilitychange",p),typeof window!="undefined"&&window.removeEventListener("online",R),g=!1)},M=n=>new Promise(s=>{r=s,i=setTimeout(()=>{i=null,r=null,s()},n)}),E=()=>{var d;let n=e.getResumable();e.clearResumable(),e.setReconnecting(!1),t=0,m(),e.setAbortController(null);let s=!1;for(let c of e.getMessages())c.streaming&&(c.streaming=!1,s=!0);let l=e.buildErrorContent("Connection lost and the response could not be resumed.");l?e.appendMessage({id:`reconnect-failed-${(d=n==null?void 0:n.executionId)!=null?d:e.nextSequence()}`,role:"assistant",content:l,createdAt:new Date().toISOString(),streaming:!1,sequence:e.nextSequence()}):s&&e.notifyMessagesChanged(),e.setStreaming(!1),e.setStatus("idle"),e.onError(new Error("Durable session reconnect failed."))},x=async()=>{var d,c,y,S,w,A;let n=(c=(d=e.config.reconnect)==null?void 0:d.backoffMs)!=null?c:k,s=(S=(y=e.config.reconnect)==null?void 0:y.maxAttempts)!=null?S:n.length,l=e.config.reconnectStream;if(!l){e.setReconnecting(!1);return}for(;e.getResumable()&&t<s;){t+=1,e.setStatus("resuming");let o=e.getResumable(),I=o.lastEventId,u=new AbortController;e.setAbortController(u),e.emitReconnect({phase:"resuming",handle:o,attempt:t});let f=null;try{let a=await l({executionId:o.executionId,after:o.lastEventId,signal:u.signal});a&&a.ok&&a.body&&(f=a.body)}catch{f=null}if(u.signal.aborted)return;if(f){let a=(w=e.getMessages().find(W=>W.id===o.assistantMessageId))==null?void 0:w.content,L=typeof a=="string"?a:"";try{await e.resumeConnect(f,o.assistantMessageId,L)}catch{}if(u.signal.aborted)return;if(!e.getResumable()){e.setReconnecting(!1),t=0,m(),e.emitReconnect({phase:"resumed",handle:o});return}e.getResumable().lastEventId!==I&&(t=0)}if(e.getResumable()&&t<s&&(e.setStatus("paused"),await M((A=n[Math.min(t-1,n.length-1)])!=null?A:1e3),u.signal.aborted))return}e.getResumable()&&E()};return{begin(){t=0,C(),x()},teardown(){i&&(clearTimeout(i),i=null),r=null,t=0,m()},wake:b}}export{T as createReconnectController};
|