@alexkroman1/aai-ui 5.11.0 → 5.12.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/_colors-CcAi2FOU.js +44 -0
- package/dist/{chat-view-DFBmX5eX.js → chat-view-DadZOvJO.js} +11 -7
- package/dist/client-config.d.ts +29 -0
- package/dist/components/_colors.d.ts +35 -9
- package/dist/components/button.js +31 -15
- package/dist/components/chat-view.js +1 -1
- package/dist/components/controls.js +1 -1
- package/dist/components/message-list.js +1 -1
- package/dist/components/sidebar-layout.js +9 -8
- package/dist/components/start-screen.js +2 -2
- package/dist/components/tool-call-block.js +1 -1
- package/dist/{controls-CoBO6sId.js → controls-DzQEKq9c.js} +8 -7
- package/dist/default-client/assets/{audio-DJF-gC7e.js → audio-Dwj4W2wx.js} +1 -1
- package/dist/default-client/assets/{capture-processor-D_A9RUeB.js → capture-processor-wdpgNZAH.js} +1 -1
- package/dist/default-client/assets/index-Ctjrde3-.css +2 -0
- package/dist/default-client/assets/index-DuE6Ab-l.js +278 -0
- package/dist/default-client/assets/{playback-processor-GPTQTyza.js → playback-processor-D_5OVt9F.js} +1 -1
- package/dist/default-client/index.html +2 -2
- package/dist/define-client.js +3 -3
- package/dist/index.js +5 -5
- package/dist/{message-list-DkAHoB3A.js → message-list-YdLocGoT.js} +11 -9
- package/dist/{session-core-CS37WE1G.js → session-core-OfnXNMuL.js} +182 -39
- package/dist/session-core-handshake.d.ts +25 -0
- package/dist/session-core-reconnect.d.ts +8 -0
- package/dist/session-core.js +1 -1
- package/dist/{tool-call-block-BjemDFB9.js → tool-call-block-CAscLGFy.js} +6 -6
- package/package.json +2 -2
- package/dist/_colors-Bfh3-BVE.js +0 -29
- package/dist/default-client/assets/index-1JIz81CD.css +0 -2
- package/dist/default-client/assets/index-D_RNiTIh.js +0 -278
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
//#region components/_colors.ts
|
|
2
|
+
/**
|
|
3
|
+
* Shared tints used by the default components (AssemblyAI design system,
|
|
4
|
+
* "website refresh": warm neutrals over the cream/white surfaces).
|
|
5
|
+
*
|
|
6
|
+
* These sit on top of the {@link ClientTheme} colors, which own the opaque
|
|
7
|
+
* palette. The neutral text steps are **derived from the theme** rather than
|
|
8
|
+
* hardcoded: `ClientTheme` documents `bg`/`surface`/`text` as free-form
|
|
9
|
+
* colors, so a client is free to hand the components a dark ground — and a
|
|
10
|
+
* fixed warm-grey scale tuned for cream leaves the AGENT/TOOL labels, every
|
|
11
|
+
* tool-call args preview, the chevron and both URL chips below WCAG AA while
|
|
12
|
+
* the prose and bubbles around them follow the theme correctly. Measured on a
|
|
13
|
+
* plausible dark theme before this was derived: 14 text nodes under 4.5:1
|
|
14
|
+
* (the faint step at 3.2–3.5:1, the muted step at 2.5:1), against zero on the
|
|
15
|
+
* default light theme.
|
|
16
|
+
*
|
|
17
|
+
* `ERROR_COLOR` and `THINKING_COLOR` stay fixed: they are *semantic* colors
|
|
18
|
+
* whose hue carries the meaning, so they cannot be re-derived from a theme
|
|
19
|
+
* that knows nothing about severity.
|
|
20
|
+
*/
|
|
21
|
+
/**
|
|
22
|
+
* Blend `text` into `surface` by `pct`, giving a neutral step that stays on
|
|
23
|
+
* the theme's own ink/ground axis. On a light theme this walks *down* from
|
|
24
|
+
* the surface toward the ink; on a dark one it walks *up* from the ground
|
|
25
|
+
* toward the light ink — the same call reads correctly either way, which is
|
|
26
|
+
* the whole reason to derive rather than hardcode.
|
|
27
|
+
*/
|
|
28
|
+
function inkTint(text, surface, pct) {
|
|
29
|
+
return `color-mix(in srgb, ${text} ${pct}%, ${surface})`;
|
|
30
|
+
}
|
|
31
|
+
/** Error red tuned for warm light surfaces. */
|
|
32
|
+
const ERROR_COLOR = "#B3261E";
|
|
33
|
+
/** Amber used by the "thinking" state indicator. */
|
|
34
|
+
const THINKING_COLOR = "#B98900";
|
|
35
|
+
/**
|
|
36
|
+
* Derive the user-bubble fill/edge from the theme primary (the mock's
|
|
37
|
+
* indigo-50 background with an indigo-100 border), so custom themes keep a
|
|
38
|
+
* coherent tinted bubble instead of a hardcoded indigo.
|
|
39
|
+
*/
|
|
40
|
+
function primaryTint(primary, surface, pct) {
|
|
41
|
+
return `color-mix(in srgb, ${primary} ${pct}%, ${surface})`;
|
|
42
|
+
}
|
|
43
|
+
//#endregion
|
|
44
|
+
export { primaryTint as i, THINKING_COLOR as n, inkTint as r, ERROR_COLOR as t };
|
|
@@ -1,26 +1,30 @@
|
|
|
1
1
|
import { useSessionSelector, useTheme } from "./context.js";
|
|
2
|
-
import {
|
|
2
|
+
import { n as THINKING_COLOR, r as inkTint, t as ERROR_COLOR } from "./_colors-CcAi2FOU.js";
|
|
3
3
|
import { t as AaiLogo } from "./aai-logo-B8lDmsut.js";
|
|
4
4
|
import { t as Eyebrow } from "./eyebrow-C6ZFuiz6.js";
|
|
5
|
-
import { t as Controls } from "./controls-
|
|
6
|
-
import { t as MessageList } from "./message-list-
|
|
5
|
+
import { t as Controls } from "./controls-DzQEKq9c.js";
|
|
6
|
+
import { t as MessageList } from "./message-list-YdLocGoT.js";
|
|
7
7
|
import clsx from "clsx";
|
|
8
8
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
9
9
|
//#region components/console-shell.tsx
|
|
10
10
|
/** @jsxImportSource react */
|
|
11
11
|
/**
|
|
12
|
-
* Indicator dot color per state
|
|
12
|
+
* Indicator dot color per state.
|
|
13
|
+
*
|
|
14
|
+
* `idle` is the theme's own faint ink step rather than a fixed warm grey, so
|
|
15
|
+
* the dot stays visible on a dark ground; the thinking amber and error red
|
|
16
|
+
* are semantic and stay fixed.
|
|
13
17
|
*
|
|
14
18
|
* @internal
|
|
15
19
|
*/
|
|
16
|
-
function stateColor(state, primary) {
|
|
20
|
+
function stateColor(state, primary, idle) {
|
|
17
21
|
switch (state) {
|
|
18
22
|
case "listening":
|
|
19
23
|
case "speaking":
|
|
20
24
|
case "ready": return primary;
|
|
21
25
|
case "thinking": return THINKING_COLOR;
|
|
22
26
|
case "error": return ERROR_COLOR;
|
|
23
|
-
default: return
|
|
27
|
+
default: return idle;
|
|
24
28
|
}
|
|
25
29
|
}
|
|
26
30
|
/**
|
|
@@ -56,7 +60,7 @@ function ConsoleShell({ icon, title, state, pulsing, error, children, footer, cl
|
|
|
56
60
|
children: [/* @__PURE__ */ jsx("span", {
|
|
57
61
|
className: "w-[7px] h-[7px] rounded-full",
|
|
58
62
|
style: {
|
|
59
|
-
background: stateColor(state, theme.primary),
|
|
63
|
+
background: stateColor(state, theme.primary, inkTint(theme.text, theme.bg, 65)),
|
|
60
64
|
animation: pulsing ? "aai-pulse 1.6s ease-in-out infinite" : "none"
|
|
61
65
|
}
|
|
62
66
|
}), state]
|
package/dist/client-config.d.ts
CHANGED
|
@@ -21,6 +21,35 @@ export type { ClientConfigResponse } from "@alexkroman1/aai/protocol";
|
|
|
21
21
|
* @internal
|
|
22
22
|
*/
|
|
23
23
|
export declare function buildAgentUrl(platformUrl: string, endpointPath: string): URL;
|
|
24
|
+
/**
|
|
25
|
+
* Per-attempt deadline for the `client-config` lookup.
|
|
26
|
+
*
|
|
27
|
+
* A request issued while the platform is restarting or saturated can HANG
|
|
28
|
+
* rather than fail — the proxy holds the socket open — and a browser fetch
|
|
29
|
+
* has no timeout of its own. Every other failure here is already handled
|
|
30
|
+
* (`null`, then the same-origin fallback), but a hang is not a failure: the
|
|
31
|
+
* promise simply never settles.
|
|
32
|
+
*
|
|
33
|
+
* That is unrecoverable rather than merely slow, because this lookup runs
|
|
34
|
+
* inside the session's WebSocket URL *provider*. partysocket awaits the
|
|
35
|
+
* provider under `_connectLock` and arms its own `connectionTimeout` only
|
|
36
|
+
* AFTER the URL resolves, so a hung lookup means no socket is ever
|
|
37
|
+
* constructed, no `error`/`close` ever fires, and none of the 10 reconnect
|
|
38
|
+
* attempts ever happen — the session sits on "connecting" forever, and stays
|
|
39
|
+
* there long after the server is back. Reproduced: zero sockets opened.
|
|
40
|
+
*
|
|
41
|
+
* A timed-out attempt therefore degrades exactly like any other failed one —
|
|
42
|
+
* `null`, so `serverIsBroker` stays unlatched and the attempt falls through
|
|
43
|
+
* to the same-origin `websocket` path, whose failure re-enters the normal
|
|
44
|
+
* backoff and re-fetches this on the next attempt.
|
|
45
|
+
*
|
|
46
|
+
* Sized well above the real work (one same-origin JSON GET that reads the
|
|
47
|
+
* agent's row) and well under a user's patience — the same 10s the studio's
|
|
48
|
+
* gating reads use for the identical hazard.
|
|
49
|
+
*
|
|
50
|
+
* @internal
|
|
51
|
+
*/
|
|
52
|
+
export declare const CLIENT_CONFIG_ATTEMPT_TIMEOUT_MS = 10000;
|
|
24
53
|
/**
|
|
25
54
|
* Fetch the agent's client config, reporting `null` when the lookup did not
|
|
26
55
|
* produce an answer (network error, non-2xx, unparsable body).
|
|
@@ -2,16 +2,42 @@
|
|
|
2
2
|
* Shared tints used by the default components (AssemblyAI design system,
|
|
3
3
|
* "website refresh": warm neutrals over the cream/white surfaces).
|
|
4
4
|
*
|
|
5
|
-
* These sit on top of the {@link ClientTheme} colors
|
|
6
|
-
* palette
|
|
7
|
-
*
|
|
5
|
+
* These sit on top of the {@link ClientTheme} colors, which own the opaque
|
|
6
|
+
* palette. The neutral text steps are **derived from the theme** rather than
|
|
7
|
+
* hardcoded: `ClientTheme` documents `bg`/`surface`/`text` as free-form
|
|
8
|
+
* colors, so a client is free to hand the components a dark ground — and a
|
|
9
|
+
* fixed warm-grey scale tuned for cream leaves the AGENT/TOOL labels, every
|
|
10
|
+
* tool-call args preview, the chevron and both URL chips below WCAG AA while
|
|
11
|
+
* the prose and bubbles around them follow the theme correctly. Measured on a
|
|
12
|
+
* plausible dark theme before this was derived: 14 text nodes under 4.5:1
|
|
13
|
+
* (the faint step at 3.2–3.5:1, the muted step at 2.5:1), against zero on the
|
|
14
|
+
* default light theme.
|
|
15
|
+
*
|
|
16
|
+
* `ERROR_COLOR` and `THINKING_COLOR` stay fixed: they are *semantic* colors
|
|
17
|
+
* whose hue carries the meaning, so they cannot be re-derived from a theme
|
|
18
|
+
* that knows nothing about severity.
|
|
19
|
+
*/
|
|
20
|
+
/**
|
|
21
|
+
* Blend `text` into `surface` by `pct`, giving a neutral step that stays on
|
|
22
|
+
* the theme's own ink/ground axis. On a light theme this walks *down* from
|
|
23
|
+
* the surface toward the ink; on a dark one it walks *up* from the ground
|
|
24
|
+
* toward the light ink — the same call reads correctly either way, which is
|
|
25
|
+
* the whole reason to derive rather than hardcode.
|
|
26
|
+
*/
|
|
27
|
+
export declare function inkTint(text: string, surface: string, pct: number): string;
|
|
28
|
+
/**
|
|
29
|
+
* Muted text — subtitles, secondary labels, thinking dots (fg-muted).
|
|
30
|
+
* 75% lands within a couple of RGB steps of the design system's `#57534B`
|
|
31
|
+
* on the default theme.
|
|
32
|
+
*/
|
|
33
|
+
export declare const INK_MUTED_PCT = 75;
|
|
34
|
+
/**
|
|
35
|
+
* Faint text — live transcripts, state indicator, start-screen subtitle.
|
|
36
|
+
* 65% reproduces the design system's `#6F6A60` on the default theme.
|
|
8
37
|
*/
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
export declare const TEXT_FAINT = "#6F6A60";
|
|
13
|
-
/** Subtle surface tint — message bubbles, tool-call blocks. */
|
|
14
|
-
export declare const SURFACE_TINT = "rgba(20,18,12,0.03)";
|
|
38
|
+
export declare const INK_FAINT_PCT = 65;
|
|
39
|
+
/** Subtle surface tint — inline code, tool-call chips, message bubbles. */
|
|
40
|
+
export declare const INK_SURFACE_PCT = 3;
|
|
15
41
|
/** Error red tuned for warm light surfaces. */
|
|
16
42
|
export declare const ERROR_COLOR = "#B3261E";
|
|
17
43
|
/** Amber used by the "thinking" state indicator. */
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { useTheme } from "../context.js";
|
|
2
|
+
import { i as primaryTint, r as inkTint } from "../_colors-CcAi2FOU.js";
|
|
2
3
|
import clsx from "clsx";
|
|
3
4
|
import { jsx } from "react/jsx-runtime";
|
|
4
5
|
//#region components/button.tsx
|
|
@@ -32,29 +33,44 @@ import { jsx } from "react/jsx-runtime";
|
|
|
32
33
|
*/
|
|
33
34
|
function Button({ variant = "default", size = "default", className, children, style, ...rest }) {
|
|
34
35
|
const theme = useTheme();
|
|
35
|
-
let
|
|
36
|
-
if (variant === "default")
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
36
|
+
let colors;
|
|
37
|
+
if (variant === "default") colors = {
|
|
38
|
+
bg: theme.primary,
|
|
39
|
+
fg: theme.surface,
|
|
40
|
+
border: "transparent",
|
|
41
|
+
hoverBg: inkTint(theme.text, theme.primary, 14),
|
|
42
|
+
hoverFg: theme.surface,
|
|
43
|
+
hoverBorder: "transparent"
|
|
40
44
|
};
|
|
41
|
-
else if (variant === "secondary")
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
+
else if (variant === "secondary") colors = {
|
|
46
|
+
bg: "transparent",
|
|
47
|
+
fg: theme.primary,
|
|
48
|
+
border: theme.primary,
|
|
49
|
+
hoverBg: primaryTint(theme.primary, theme.surface, 8),
|
|
50
|
+
hoverFg: theme.primary,
|
|
51
|
+
hoverBorder: theme.primary
|
|
45
52
|
};
|
|
46
|
-
else
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
53
|
+
else colors = {
|
|
54
|
+
bg: theme.surface,
|
|
55
|
+
fg: theme.text,
|
|
56
|
+
border: theme.border,
|
|
57
|
+
hoverBg: inkTint(theme.text, theme.surface, 5),
|
|
58
|
+
hoverFg: theme.text,
|
|
59
|
+
hoverBorder: theme.border
|
|
50
60
|
};
|
|
51
61
|
return /* @__PURE__ */ jsx("button", {
|
|
52
62
|
type: "button",
|
|
53
63
|
style: {
|
|
54
|
-
|
|
64
|
+
"--aai-btn-bg": colors.bg,
|
|
65
|
+
"--aai-btn-fg": colors.fg,
|
|
66
|
+
"--aai-btn-bd": colors.border,
|
|
67
|
+
"--aai-btn-bg-hover": colors.hoverBg,
|
|
68
|
+
"--aai-btn-fg-hover": colors.hoverFg,
|
|
69
|
+
"--aai-btn-bd-hover": colors.hoverBorder,
|
|
70
|
+
outlineColor: theme.primary,
|
|
55
71
|
...style
|
|
56
72
|
},
|
|
57
|
-
className: clsx("inline-flex items-center justify-center appearance-none m-0 w-fit whitespace-nowrap", size === "lg" ? "h-11 px-7 text-xs" : "h-9 px-5 text-[11px]", "rounded-aai font-aai font-medium tracking-[1.4px] uppercase leading-none", "cursor-pointer border
|
|
73
|
+
className: clsx("inline-flex items-center justify-center appearance-none m-0 w-fit whitespace-nowrap", size === "lg" ? "h-11 px-7 text-xs" : "h-9 px-5 text-[11px]", "rounded-aai font-aai font-medium tracking-[1.4px] uppercase leading-none", "cursor-pointer border transition-colors duration-150", "bg-(--aai-btn-bg) text-(--aai-btn-fg) border-(--aai-btn-bd)", "enabled:hover:bg-(--aai-btn-bg-hover) enabled:hover:text-(--aai-btn-fg-hover)", "enabled:hover:border-(--aai-btn-bd-hover)", "outline-none focus-visible:[outline:2px_solid] focus-visible:[outline-offset:2px]", "disabled:cursor-not-allowed disabled:opacity-50", className),
|
|
58
74
|
...rest,
|
|
59
75
|
children
|
|
60
76
|
});
|
|
@@ -29,20 +29,21 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
29
29
|
function SidebarLayout({ sidebar, children, sidebarWidth = "18rem", sidebarPosition = "left", className }) {
|
|
30
30
|
const theme = useTheme();
|
|
31
31
|
const sidebarEl = /* @__PURE__ */ jsx("div", {
|
|
32
|
-
className: "shrink-0 flex flex-col overflow-y-auto",
|
|
33
|
-
style: {
|
|
34
|
-
width: sidebarWidth,
|
|
35
|
-
...sidebarPosition === "left" ? { borderRight: `1px solid ${theme.border}` } : { borderLeft: `1px solid ${theme.border}` }
|
|
36
|
-
},
|
|
32
|
+
className: clsx("shrink-0 flex flex-col overflow-y-auto", "w-full max-h-[40vh] md:w-(--aai-sidebar-w) md:max-h-none", sidebarPosition === "left" ? "border-b md:border-b-0 md:border-r" : "border-t md:border-t-0 md:border-l order-last md:order-none"),
|
|
33
|
+
style: { borderColor: theme.border },
|
|
37
34
|
children: sidebar
|
|
38
35
|
});
|
|
36
|
+
const vars = {
|
|
37
|
+
background: theme.bg,
|
|
38
|
+
"--aai-sidebar-w": sidebarWidth
|
|
39
|
+
};
|
|
39
40
|
return /* @__PURE__ */ jsxs("div", {
|
|
40
|
-
className: clsx("flex h-screen", className),
|
|
41
|
-
style:
|
|
41
|
+
className: clsx("flex flex-col md:flex-row min-h-screen md:h-screen", className),
|
|
42
|
+
style: vars,
|
|
42
43
|
children: [
|
|
43
44
|
sidebarPosition === "left" && sidebarEl,
|
|
44
45
|
/* @__PURE__ */ jsx("div", {
|
|
45
|
-
className: "flex-1 min-w-0",
|
|
46
|
+
className: "flex-1 min-w-0 min-h-0",
|
|
46
47
|
children
|
|
47
48
|
}),
|
|
48
49
|
sidebarPosition === "right" && sidebarEl
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useSessionCore, useSessionSelector, useTheme } from "../context.js";
|
|
2
|
+
import { r as inkTint } from "../_colors-CcAi2FOU.js";
|
|
2
3
|
import { Button } from "./button.js";
|
|
3
|
-
import "../_colors-Bfh3-BVE.js";
|
|
4
4
|
import { t as AaiLogo } from "../aai-logo-B8lDmsut.js";
|
|
5
5
|
import { t as Eyebrow } from "../eyebrow-C6ZFuiz6.js";
|
|
6
6
|
import clsx from "clsx";
|
|
@@ -52,7 +52,7 @@ function StartScreen({ children, icon, title, subtitle, buttonText = "Start Conv
|
|
|
52
52
|
}),
|
|
53
53
|
subtitle && /* @__PURE__ */ jsx("p", {
|
|
54
54
|
className: "text-[15px] leading-[22px] m-0 max-w-75",
|
|
55
|
-
style: { color:
|
|
55
|
+
style: { color: inkTint(theme.text, theme.surface, 75) },
|
|
56
56
|
children: subtitle
|
|
57
57
|
}),
|
|
58
58
|
/* @__PURE__ */ jsx(Button, {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useSessionCore, useSessionSelector, useTheme } from "./context.js";
|
|
2
|
+
import { r as inkTint } from "./_colors-CcAi2FOU.js";
|
|
2
3
|
import { Button } from "./components/button.js";
|
|
3
|
-
import { i as TEXT_MUTED, n as SURFACE_TINT, r as TEXT_FAINT } from "./_colors-Bfh3-BVE.js";
|
|
4
4
|
import { t as pageBaseUrl } from "./_utils-CsqbIVGI.js";
|
|
5
5
|
import clsx from "clsx";
|
|
6
6
|
import { memo, useEffect, useRef, useState } from "react";
|
|
@@ -33,16 +33,17 @@ function UrlChip({ label, url, hint, testId, className }) {
|
|
|
33
33
|
type: "button",
|
|
34
34
|
onClick: copy,
|
|
35
35
|
title: `${hint} (click to copy)\n${url}`,
|
|
36
|
-
className: clsx("flex items-center gap-1.5 min-w-0 appearance-none m-0 px-2 py-1 rounded-aai border cursor-pointer
|
|
36
|
+
className: clsx("flex items-center gap-1.5 min-w-0 appearance-none m-0 px-2 py-1 rounded-aai border cursor-pointer text-[11px] leading-none font-aai-mono", "outline-none focus-visible:[outline:2px_solid] focus-visible:[outline-offset:2px]", className),
|
|
37
37
|
style: {
|
|
38
|
-
background:
|
|
38
|
+
background: inkTint(theme.text, theme.surface, 3),
|
|
39
39
|
borderColor: theme.border,
|
|
40
|
-
color:
|
|
40
|
+
color: inkTint(theme.text, theme.surface, 65),
|
|
41
|
+
outlineColor: theme.primary
|
|
41
42
|
},
|
|
42
43
|
"data-testid": testId,
|
|
43
44
|
children: [/* @__PURE__ */ jsx("span", {
|
|
44
45
|
className: "uppercase tracking-wide shrink-0",
|
|
45
|
-
style: { color:
|
|
46
|
+
style: { color: inkTint(theme.text, theme.surface, 75) },
|
|
46
47
|
children: copied ? "Copied" : label
|
|
47
48
|
}), /* @__PURE__ */ jsx("span", {
|
|
48
49
|
className: "truncate",
|
|
@@ -121,7 +122,7 @@ const Controls = memo(function Controls({ className }) {
|
|
|
121
122
|
const running = useSessionSelector((s) => s.running);
|
|
122
123
|
const { toggle, reset } = useSessionCore();
|
|
123
124
|
return /* @__PURE__ */ jsxs("div", {
|
|
124
|
-
className: clsx("flex items-center gap-3 shrink-0", className),
|
|
125
|
+
className: clsx("flex flex-wrap items-center gap-3 shrink-0", className),
|
|
125
126
|
children: [
|
|
126
127
|
/* @__PURE__ */ jsx(Button, {
|
|
127
128
|
variant: "secondary",
|
|
@@ -133,7 +134,7 @@ const Controls = memo(function Controls({ className }) {
|
|
|
133
134
|
onClick: reset,
|
|
134
135
|
children: "New Conversation"
|
|
135
136
|
}),
|
|
136
|
-
/* @__PURE__ */ jsx(SessionUrlChips, { className: "ml-auto max-w-[60%]" })
|
|
137
|
+
/* @__PURE__ */ jsx(SessionUrlChips, { className: "basis-full sm:basis-auto sm:ml-auto sm:max-w-[60%]" })
|
|
137
138
|
]
|
|
138
139
|
});
|
|
139
140
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as e,o as t,t as n}from"./index-
|
|
1
|
+
import{a as e,o as t,t as n}from"./index-DuE6Ab-l.js";function r(e,t,n){if(e!==t)throw Error(`Browser refused the ${n} sample rate: asked for ${t} Hz, got ${e} Hz`)}function i(e){e.then(e=>{for(let t of e.getTracks())t.stop()}).catch(()=>{})}function a(e,t,n){let r=new AudioWorkletNode(e,`capture-processor`,{channelCount:1,channelCountMode:`explicit`}),i=null;return r.port.onmessage=e=>{let r=e.data;r.event===`chunk`&&r.buffer?t(r.buffer):r.event===`silent`?n?.():r.event===`stopped`&&(i?.(),i=null)},{node:r,start(){r.port.postMessage({event:`start`})},stop(){return new Promise(e=>{let t=setTimeout(e,250);i=()=>{clearTimeout(t),e()},r.port.postMessage({event:`stop`})})}}}async function o(o){let{sttSampleRate:s,ttsSampleRate:c,captureWorkletSrc:l,playbackWorkletSrc:u,onMicData:d,onError:f,onPlaybackStats:p,onPlaybackProgress:m,onMicSilent:h}=o,g=new AudioContext({sampleRate:c,latencyHint:`playback`}),_=s===c,v=_?g:new AudioContext({sampleRate:s,latencyHint:`interactive`});async function y(){let e=_?[g]:[g,v];await Promise.all(e.map(e=>e.close().catch(e=>{console.warn(`AudioContext close failed:`,e)})))}let b=navigator.mediaDevices.getUserMedia({audio:{deviceId:{ideal:`default`},...n}}),x;try{[x]=await Promise.all([b,g.resume(),v.resume(),v.audioWorklet.addModule(l),g.audioWorklet.addModule(u)]),r(v.sampleRate,s,`capture`),r(g.sampleRate,c,`playback`)}catch(e){throw i(b),await y(),e}let S=v.createMediaStreamSource(x),C=a(v,d,h);S.connect(C.node),C.node.onprocessorerror=()=>{let e=Error(`Audio capture worklet crashed`);console.error(`[aai-ui]`,e.message),f?.(e)},C.start();let w=null,T=null,E=0,D=null,O=new AbortController;function k(){T?.(),T=null,D=null}function A(e){e.stats&&e.stats.concealedSamples>0&&p?.(e.stats),e.reason!==`interrupt`&&(D!==null&&e.turn!==D||k())}function j(){if(w)return w;let e=new AudioWorkletNode(g,`playback-processor`);return e.connect(g.destination),e.port.onmessage=e=>{e.data.event===`stop`?A(e.data):e.data.event===`progress`&&m?.(e.data.bufferedMs)},e.onprocessorerror=()=>{let e=Error(`Audio playback worklet crashed`);console.error(`[aai-ui]`,e.message),k(),f?.(e)},w=e,e}let M={enqueue(e){O.signal.aborted||e.byteLength!==0&&j().port.postMessage({event:`write`,buffer:new Uint8Array(e)},[e])},done(){if(!w)return Promise.resolve();let n=++E;return w.port.postMessage({event:`done`,turn:n}),g.state===`running`?new Promise(r=>{T?.();let i=()=>{clearInterval(a),clearTimeout(o),T===i&&(T=null,D=null),r()},a=setInterval(()=>{g.state!==`running`&&i()},t),o=setTimeout(i,e);T=i,D=n}):(D=null,Promise.resolve())},flush(){w&&(k(),w.port.postMessage({event:`interrupt`}))},async close(){if(!O.signal.aborted){O.abort(),await C.stop(),S.disconnect(),C.node.disconnect(),w&&w.disconnect();for(let e of x.getTracks())e.stop();await y()}},async[Symbol.asyncDispose](){await M.close()}};return M}export{o as createVoiceIO};
|
package/dist/default-client/assets/{capture-processor-D_A9RUeB.js → capture-processor-wdpgNZAH.js}
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{n as e,r as t}from"./index-
|
|
1
|
+
import{n as e,r as t}from"./index-DuE6Ab-l.js";import{t as n}from"./_module-url-BX0RuRU2.js";var r=n(`
|
|
2
2
|
class CaptureProcessor extends AudioWorkletProcessor {
|
|
3
3
|
constructor(options) {
|
|
4
4
|
super();
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */
|
|
2
|
+
@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-duration:initial;--tw-ease:initial}}}@layer theme{:root,:host{--font-sans:-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--spacing:.25rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--tracking-wide:.025em;--radius-sm:.25rem;--radius-md:.375rem;--radius-lg:.5rem;--radius-xl:.75rem;--ease-in-out:cubic-bezier(.4, 0, .2, 1);--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono);--font-aai:"Monument Grotesk", "ABC Monument Grotesk", ui-sans-serif, system-ui, -apple-system, sans-serif;--font-aai-serif:"Source Serif 4", "Source Serif Pro", Charter, "Iowan Old Style", Georgia, serif;--font-aai-mono:"JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;--radius-aai:4px}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring:where(:not(iframe)){outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}html,body{margin:0;padding:0}}@layer components;@layer utilities{.collapse{visibility:collapse}.invisible{visibility:hidden}.visible{visibility:visible}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.order-last{order:9999}.container{width:100%}@media (width>=40rem){.container{max-width:40rem}}@media (width>=48rem){.container{max-width:48rem}}@media (width>=64rem){.container{max-width:64rem}}@media (width>=80rem){.container{max-width:80rem}}@media (width>=96rem){.container{max-width:96rem}}.m-0{margin:0}.mx-auto{margin-inline:auto}.my-0\.5{margin-block:calc(var(--spacing) * .5)}.my-1\.5{margin-block:calc(var(--spacing) * 1.5)}.my-2\.5{margin-block:calc(var(--spacing) * 2.5)}.mt-2{margin-top:calc(var(--spacing) * 2)}.mt-3{margin-top:calc(var(--spacing) * 3)}.mb-1\.5{margin-bottom:calc(var(--spacing) * 1.5)}.box-border{box-sizing:border-box}.block{display:block}.flex{display:flex}.grid{display:grid}.inline{display:inline}.inline-flex{display:inline-flex}.table{display:table}.h-1\.5{height:calc(var(--spacing) * 1.5)}.h-4{height:calc(var(--spacing) * 4)}.h-9{height:calc(var(--spacing) * 9)}.h-11{height:calc(var(--spacing) * 11)}.h-\[7px\]{height:7px}.h-screen{height:100vh}.max-h-64{max-height:calc(var(--spacing) * 64)}.max-h-\[40vh\]{max-height:40vh}.min-h-0{min-height:0}.min-h-5{min-height:calc(var(--spacing) * 5)}.min-h-screen{min-height:100vh}.w-1\.5{width:calc(var(--spacing) * 1.5)}.w-4{width:calc(var(--spacing) * 4)}.w-\[7px\]{width:7px}.w-fit{width:fit-content}.w-full{width:100%}.max-w-75{max-width:calc(var(--spacing) * 75)}.max-w-105{max-width:calc(var(--spacing) * 105)}.max-w-190{max-width:calc(var(--spacing) * 190)}.max-w-\[82\%\]{max-width:82%}.max-w-\[min\(78\%\,64ch\)\]{max-width:min(78%,64ch)}.min-w-0{min-width:0}.flex-1{flex:1}.shrink{flex-shrink:1}.shrink-0{flex-shrink:0}.grow{flex-grow:1}.basis-full{flex-basis:100%}.border-collapse{border-collapse:collapse}.rotate-90{rotate:90deg}.cursor-pointer{cursor:pointer}.resize{resize:both}.\[scrollbar-width\:none\]{scrollbar-width:none}.list-decimal{list-style-type:decimal}.list-disc{list-style-type:disc}.appearance-none{appearance:none}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.items-end{align-items:flex-end}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.gap-1{gap:var(--spacing)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-2\.5{gap:calc(var(--spacing) * 2.5)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}.gap-5{gap:calc(var(--spacing) * 5)}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.rounded-aai{border-radius:var(--radius-aai)}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.rounded-sm{border-radius:var(--radius-sm)}.rounded-xl{border-radius:var(--radius-xl)}.border{border-style:var(--tw-border-style);border-width:1px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-l-2{border-left-style:var(--tw-border-style);border-left-width:2px}.border-none{--tw-border-style:none;border-style:none}.border-\(--aai-btn-bd\){border-color:var(--aai-btn-bd)}.bg-\(--aai-btn-bg\){background-color:var(--aai-btn-bg)}.bg-transparent{background-color:#0000}.p-2\.5{padding:calc(var(--spacing) * 2.5)}.p-7{padding:calc(var(--spacing) * 7)}.px-1{padding-inline:var(--spacing)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-3\.5{padding-inline:calc(var(--spacing) * 3.5)}.px-5{padding-inline:calc(var(--spacing) * 5)}.px-6{padding-inline:calc(var(--spacing) * 6)}.px-7{padding-inline:calc(var(--spacing) * 7)}.px-10{padding-inline:calc(var(--spacing) * 10)}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1{padding-block:var(--spacing)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-2\.5{padding-block:calc(var(--spacing) * 2.5)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-8{padding-block:calc(var(--spacing) * 8)}.py-12{padding-block:calc(var(--spacing) * 12)}.pl-3{padding-left:calc(var(--spacing) * 3)}.pl-5{padding-left:calc(var(--spacing) * 5)}.text-center{text-align:center}.text-left{text-align:left}.font-aai{font-family:var(--font-aai)}.font-aai-mono{font-family:var(--font-aai-mono)}.font-aai-serif{font-family:var(--font-aai-serif)}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\[9px\]{font-size:9px}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.text-\[12\.5px\]{font-size:12.5px}.text-\[12px\]{font-size:12px}.text-\[13px\]{font-size:13px}.text-\[14px\]{font-size:14px}.text-\[15px\]{font-size:15px}.text-\[16px\]{font-size:16px}.text-\[17px\]{font-size:17px}.text-\[22px\]{font-size:22px}.text-\[32px\]{font-size:32px}.leading-4{--tw-leading:calc(var(--spacing) * 4);line-height:calc(var(--spacing) * 4)}.leading-\[1\.2\]{--tw-leading:1.2;line-height:1.2}.leading-\[1\.15\]{--tw-leading:1.15;line-height:1.15}.leading-\[22px\]{--tw-leading:22px;line-height:22px}.leading-\[23px\]{--tw-leading:23px;line-height:23px}.leading-\[130\%\]{--tw-leading:130%;line-height:130%}.leading-none{--tw-leading:1;line-height:1}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-normal{--tw-font-weight:var(--font-weight-normal);font-weight:var(--font-weight-normal)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-\[-0\.2px\]{--tw-tracking:-.2px;letter-spacing:-.2px}.tracking-\[1\.2px\]{--tw-tracking:1.2px;letter-spacing:1.2px}.tracking-\[1\.4px\]{--tw-tracking:1.4px;letter-spacing:1.4px}.tracking-wide{--tw-tracking:var(--tracking-wide);letter-spacing:var(--tracking-wide)}.text-balance{text-wrap:balance}.wrap-break-word{overflow-wrap:break-word}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.text-\(--aai-btn-fg\){color:var(--aai-btn-fg)}.uppercase{text-transform:uppercase}.underline{text-decoration-line:underline}.underline-offset-2{text-underline-offset:2px}.ring{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.filter{filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-150{--tw-duration:.15s;transition-duration:.15s}.ease-in-out{--tw-ease:var(--ease-in-out);transition-timing-function:var(--ease-in-out)}.outline-none{--tw-outline-style:none;outline-style:none}.select-none{-webkit-user-select:none;user-select:none}.first\:mt-0:first-child{margin-top:0}.last\:mb-0:last-child{margin-bottom:0}.focus-visible\:\[outline\:2px_solid\]:focus-visible{outline:2px solid}.focus-visible\:\[outline-offset\:2px\]:focus-visible{outline-offset:2px}@media (hover:hover){.enabled\:hover\:border-\(--aai-btn-bd-hover\):enabled:hover{border-color:var(--aai-btn-bd-hover)}.enabled\:hover\:bg-\(--aai-btn-bg-hover\):enabled:hover{background-color:var(--aai-btn-bg-hover)}.enabled\:hover\:text-\(--aai-btn-fg-hover\):enabled:hover{color:var(--aai-btn-fg-hover)}}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-50:disabled{opacity:.5}@media (width>=40rem){.sm\:ml-auto{margin-left:auto}.sm\:max-w-\[60\%\]{max-width:60%}.sm\:basis-auto{flex-basis:auto}.sm\:px-16{padding-inline:calc(var(--spacing) * 16)}.sm\:py-14{padding-block:calc(var(--spacing) * 14)}}@media (width>=48rem){.md\:order-none{order:0}.md\:h-screen{height:100vh}.md\:max-h-none{max-height:none}.md\:w-\(--aai-sidebar-w\){width:var(--aai-sidebar-w)}.md\:flex-row{flex-direction:row}.md\:border-t-0{border-top-style:var(--tw-border-style);border-top-width:0}.md\:border-r{border-right-style:var(--tw-border-style);border-right-width:1px}.md\:border-b-0{border-bottom-style:var(--tw-border-style);border-bottom-width:0}.md\:border-l{border-left-style:var(--tw-border-style);border-left-width:1px}}}@keyframes aai-pulse{0%,to{opacity:1;transform:scale(1)}50%{opacity:.45;transform:scale(.82)}}@keyframes aai-bounce{0%,80%,to{opacity:.3;transform:scale(.8)}40%{opacity:1;transform:scale(1)}}@keyframes aai-shimmer{0%{background-position:-200% 0}to{background-position:200% 0}}.tool-shimmer{-webkit-text-fill-color:transparent;background:linear-gradient(90deg,currentColor 25%,#0000 50%,currentColor 75%) 0 0/200% 100%;-webkit-background-clip:text;background-clip:text;animation:2s infinite aai-shimmer}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}
|