@frontera-sdk/chat-ui 1.50.40

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.
Files changed (148) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +348 -0
  3. package/dist/af-DK_CjRn6-OPBHDTNZ.js +197 -0
  4. package/dist/agent-picker.d.ts +38 -0
  5. package/dist/agent-picker.js +8 -0
  6. package/dist/as-BPtSu6VN-O4ZZEAJG.js +11 -0
  7. package/dist/be-CrQ0smca-5HIE5K27.js +11 -0
  8. package/dist/bg-CrQqGwni-3IRVPZQ7.js +11 -0
  9. package/dist/bn-NCLZcWHi-XOZJFNIB.js +11 -0
  10. package/dist/ca-SUf6Y2Om-V6F2EBCA.js +38 -0
  11. package/dist/capture-NO5ZIGP6.js +1652 -0
  12. package/dist/chat.css +3555 -0
  13. package/dist/chat.d.ts +161 -0
  14. package/dist/chat.js +60498 -0
  15. package/dist/chunk-2KEBRV3W.js +191 -0
  16. package/dist/chunk-6BPHEBCF.js +639 -0
  17. package/dist/chunk-6HYPVNVA.js +25 -0
  18. package/dist/chunk-7ADM3CKD.js +10 -0
  19. package/dist/chunk-AFVU5VT6.js +5601 -0
  20. package/dist/chunk-BEJ3HQG4.js +93 -0
  21. package/dist/chunk-CCVPZVFK.js +28 -0
  22. package/dist/chunk-DGDHKMDB.js +10 -0
  23. package/dist/chunk-FXKXDR5K.js +2166 -0
  24. package/dist/chunk-GTQH7MPF.js +129 -0
  25. package/dist/chunk-I7SXWUAN.js +1258 -0
  26. package/dist/chunk-IQRPGFLI.js +234 -0
  27. package/dist/chunk-IXDM5R55.js +23 -0
  28. package/dist/chunk-JD6ETTXC.js +178 -0
  29. package/dist/chunk-OP4MLJDA.js +215 -0
  30. package/dist/chunk-PQZ2CS26.js +2315 -0
  31. package/dist/chunk-PR4QN5HX.js +38 -0
  32. package/dist/chunk-PUIVKDV5.js +271 -0
  33. package/dist/chunk-QSSFBZAS.js +6914 -0
  34. package/dist/chunk-RAKKA3WU.js +5896 -0
  35. package/dist/chunk-RB2Y4NYC.js +681 -0
  36. package/dist/chunk-VDZH5Z3K.js +72 -0
  37. package/dist/chunk-WMN6BPPS.js +49 -0
  38. package/dist/chunk-WO6DJLFE.js +10857 -0
  39. package/dist/chunk-X5E2DJVO.js +47634 -0
  40. package/dist/chunk-XJFTVKLW.js +2687 -0
  41. package/dist/chunk-ZS6PXIZP.js +187 -0
  42. package/dist/client.d.ts +89 -0
  43. package/dist/client.js +20 -0
  44. package/dist/composer.d.ts +23 -0
  45. package/dist/composer.js +89 -0
  46. package/dist/cop-C3sk0IUo-CIZA2H43.js +11 -0
  47. package/dist/credential.d.ts +75 -0
  48. package/dist/credential.js +3 -0
  49. package/dist/cs-CmAteokq-HAKEQPB4.js +17 -0
  50. package/dist/cu-CBUlrW6Y-QTZ6ZLA4.js +32 -0
  51. package/dist/cy-BBPa6z2x-MX6DGDNW.js +11 -0
  52. package/dist/da-CCDXfXtG-5YEOHMG3.js +11 -0
  53. package/dist/de-1901-CWoAOigE-63QFSF2A.js +11 -0
  54. package/dist/de-1996-BL6awyxG-R2PHKMAB.js +11 -0
  55. package/dist/de-ch-1901-hVThVHVb-JSDB53OZ.js +11 -0
  56. package/dist/el-monoton-D3aKqTz2-2V4OOFBB.js +11 -0
  57. package/dist/el-polyton-ogVWcTzh-3U7NGQMT.js +11 -0
  58. package/dist/en-gb-B7Al27b_-UKCBQFSU.js +21 -0
  59. package/dist/es-DcaaHPU_-NOBXSOZK.js +11 -0
  60. package/dist/esm-MHF25KDL.js +3 -0
  61. package/dist/et-B_spaleu-5UAYIW62.js +11 -0
  62. package/dist/eu-Ctv_kq9Z-V5DREOPN.js +11 -0
  63. package/dist/fi-RW5VB8Yp-YSXBK7LW.js +11 -0
  64. package/dist/fr-BC2onEz9-7KH5T76G.js +11 -0
  65. package/dist/frame.d.ts +59 -0
  66. package/dist/frame.js +111 -0
  67. package/dist/fur-AC12wySk-4PD2Y72H.js +11 -0
  68. package/dist/ga-Cn6LkudM-RRAAJT3N.js +58 -0
  69. package/dist/gl-DZGc-K_G-KYSXXTCY.js +11 -0
  70. package/dist/grc-DOlGgO8T-2HXBZVJ5.js +11 -0
  71. package/dist/gu-Bjl0l-cf-4CFSVZHZ.js +11 -0
  72. package/dist/header.d.ts +78 -0
  73. package/dist/header.js +18 -0
  74. package/dist/hi-DsAaTPCC-KMCFBWK7.js +11 -0
  75. package/dist/hr-DT1SBBes-X2TIX6EI.js +11 -0
  76. package/dist/hsb-DC_ITc1e-PXLERA7R.js +46 -0
  77. package/dist/hu-DVk7Y_ka-PJPVU54B.js +11 -0
  78. package/dist/hy-e995ysyO-MZBRFX52.js +11 -0
  79. package/dist/ia-Cr4TJH0c-D3O2FHGP.js +22 -0
  80. package/dist/id-DifDyWg9-MZ2BGHWI.js +58 -0
  81. package/dist/is-BT8UVRze-CZZCKEFI.js +11 -0
  82. package/dist/it-Bt_Meacx-T4Y5JYV6.js +11 -0
  83. package/dist/ka-jyoLzyDE-ES6EXZLW.js +11 -0
  84. package/dist/kmr-Cfwhwuff-TSW2R2KS.js +11 -0
  85. package/dist/kn-C6Lov-DP-B4BL47CE.js +11 -0
  86. package/dist/la-DuvHjUWw-6K7TFU6X.js +11 -0
  87. package/dist/la-x-classic-yTyAOQEt-YWTKMM2L.js +11 -0
  88. package/dist/la-x-liturgic-CXeQb4FY-B772L5E7.js +11 -0
  89. package/dist/lib-3ZKX25RJ.js +4511 -0
  90. package/dist/lt-BBe8DlDF-4YINVOZR.js +11 -0
  91. package/dist/lv-Q2BBHnzp-TMVQ3MX2.js +11 -0
  92. package/dist/message.d.ts +64 -0
  93. package/dist/message.js +18 -0
  94. package/dist/ml-2xLVYkVY-NGZLAPIN.js +11 -0
  95. package/dist/mn-cyrl-lHM4n0oC-DGBYYUT3.js +11 -0
  96. package/dist/mn-cyrl-x-lmc-3aetruI8-QHJABMOO.js +11 -0
  97. package/dist/mr-CjWJPVmH-X5UHV65O.js +11 -0
  98. package/dist/mul-ethi-D_CMSMEq-H7UMQSOQ.js +11 -0
  99. package/dist/nb-DI8u59ch-J4CAVI4Y.js +122 -0
  100. package/dist/new-session-Dw7JOgzu.d.ts +141 -0
  101. package/dist/new-session.d.ts +4 -0
  102. package/dist/new-session.js +10 -0
  103. package/dist/nl-BHQJ6Gvn-7BH55RA7.js +52 -0
  104. package/dist/nn-ntZvarUK-KKNCHHJ4.js +122 -0
  105. package/dist/no-B8ItS0F3-3ZXIRJ6U.js +120 -0
  106. package/dist/oauth-callback.d.ts +35 -0
  107. package/dist/oauth-callback.js +18 -0
  108. package/dist/oc-P_i3-xLA-XZM6E5YZ.js +11 -0
  109. package/dist/or-50rxpoq4-5VELAFMJ.js +11 -0
  110. package/dist/pa-C54UG8eN-WEJPMZ6Z.js +11 -0
  111. package/dist/parts.d.ts +49 -0
  112. package/dist/parts.js +106 -0
  113. package/dist/pdf-cover-thumbnail-inner-4N2Q5AAG.js +36 -0
  114. package/dist/pdf-deck-view-inner-FZVLAEQR.js +575 -0
  115. package/dist/pdf-document-view-inner-6DF54JWK.js +585 -0
  116. package/dist/pdf-viewer-inner-GPES3KG2.js +256 -0
  117. package/dist/pending-cards.d.ts +26 -0
  118. package/dist/pending-cards.js +9 -0
  119. package/dist/pi-B9cgjyG1-GD5ASDDU.js +11 -0
  120. package/dist/pl-9fg-ESVt-UMX7MCJM.js +32 -0
  121. package/dist/platform.css +4013 -0
  122. package/dist/pms-BRGfm5gS-SSE3AUW5.js +11 -0
  123. package/dist/pt-Cum2_NUC-W35JYVR4.js +11 -0
  124. package/dist/rm-C0MIK9N4-IWL4YTNT.js +11 -0
  125. package/dist/ro-0fmdH0HA-46WUTOYH.js +11 -0
  126. package/dist/ru-v4l-ayaq-BUGK6XCN.js +196 -0
  127. package/dist/sa-CKY9c_Vq-4KIJOI5Y.js +11 -0
  128. package/dist/sh-cyrl-BpCRFOmq-DSLQ4UY2.js +128 -0
  129. package/dist/sh-latn-sRy4Tuaj-UNQOR63V.js +128 -0
  130. package/dist/sk-_iOeDNrQ-NCTQKH25.js +17 -0
  131. package/dist/sl-DpiklF-D-6GG5TDVN.js +11 -0
  132. package/dist/sr-cyrl-Dpzrbd0W-4Q5226YJ.js +142 -0
  133. package/dist/sv-CFm5y56M-VTWNPZ7I.js +11 -0
  134. package/dist/ta-BcghgTbD-NRT35DW6.js +11 -0
  135. package/dist/te-B5Spl2Jk-5VE6CLN4.js +11 -0
  136. package/dist/th-DWX5iPSo-N5GMOQOP.js +11 -0
  137. package/dist/theme.d.ts +49 -0
  138. package/dist/theme.js +3 -0
  139. package/dist/tk-BMbKB10q-HGWWY5L3.js +11 -0
  140. package/dist/tr-CIHIuzqc-6ISBNYLV.js +11 -0
  141. package/dist/types-BDqLaBfH.d.ts +60 -0
  142. package/dist/uk-Dir3oxLs-YQ3QZRI4.js +11 -0
  143. package/dist/univer-workbook-BSSUE5TG.css +3555 -0
  144. package/dist/univer-workbook-N5IIN7CH.js +290849 -0
  145. package/dist/vega-chart-block-NQADYNWQ.js +2857 -0
  146. package/dist/zh-latn-pinyin-BdYb-Ey_-RB542AHF.js +11 -0
  147. package/package.json +137 -0
  148. package/src/styles.css +996 -0
@@ -0,0 +1,2166 @@
1
+ 'use client';
2
+ import { cn } from './chunk-DGDHKMDB.js';
3
+ import { forwardRef, useState, useId, useRef, useMemo, memo, useEffect, useLayoutEffect } from 'react';
4
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
5
+ import { z } from 'zod';
6
+
7
+ // src/vendor/ui/agent-avatar/lab/math.ts
8
+ var TAU = Math.PI * 2;
9
+ var clamp = (value, minimum = 0, maximum = 1) => value < minimum ? minimum : value > maximum ? maximum : value;
10
+ var lerp = (from, to, progress) => from + (to - from) * progress;
11
+ var easings = {
12
+ easeOutCubic: (progress) => 1 - (1 - progress) ** 3,
13
+ easeInOutCubic: (progress) => progress < 0.5 ? 4 * progress ** 3 : 1 - (-2 * progress + 2) ** 3 / 2,
14
+ easeOutQuint: (progress) => 1 - (1 - progress) ** 5
15
+ };
16
+ function loopNoise(time, period, seed = 0) {
17
+ const phase = time / period * TAU;
18
+ return 0.55 * Math.sin(phase + seed) + 0.3 * Math.sin(2 * phase + seed * 1.7 + 1.1) + 0.15 * Math.sin(3 * phase + seed * 2.3 + 2.4);
19
+ }
20
+ function createRng(seed) {
21
+ let value = seed >>> 0;
22
+ return () => {
23
+ value = value + 1831565813 >>> 0;
24
+ let next = Math.imul(value ^ value >>> 15, 1 | value);
25
+ next = next + Math.imul(next ^ next >>> 7, 61 | next) ^ next;
26
+ return ((next ^ next >>> 14) >>> 0) / 4294967296;
27
+ };
28
+ }
29
+ var r2 = (value) => Math.round(value * 100) / 100;
30
+
31
+ // src/vendor/ui/agent-avatar/lab/expressions.ts
32
+ var eye = (width, height, tilt = 0, open = 1) => ({
33
+ width,
34
+ height,
35
+ tilt,
36
+ open
37
+ });
38
+ var pair = (width, height, tilt = 0, open = 1) => [
39
+ eye(width, height, tilt, open),
40
+ eye(width, height, -tilt, open)
41
+ ];
42
+ var EYE_EXPRESSIONS = [
43
+ { id: "neutral", name: "Neutral", description: "Clear and composed", separation: 15.5, gaze: { x: 0, y: 0 }, eyes: pair(0.186, 0.412) },
44
+ { id: "attentive", name: "Attentive", description: "Ready to listen", separation: 16, gaze: { x: 0.04, y: 0.05 }, eyes: pair(0.21, 0.44) },
45
+ { id: "surprised", name: "Surprised", description: "Wide recognition", separation: 19, gaze: { x: 0.03, y: -0.03 }, eyes: pair(0.45, 0.47) },
46
+ { id: "energized", name: "Energized", description: "High momentum", separation: 19.5, gaze: { x: 0.06, y: -0.14 }, eyes: pair(0.4, 0.56, -10) },
47
+ { id: "happy", name: "Happy", description: "Quietly positive", separation: 17, gaze: { x: 0.05, y: 0.09 }, eyes: pair(0.27, 0.17, 14) },
48
+ { id: "delighted", name: "Delighted", description: "Openly positive", separation: 18, gaze: { x: 0.04, y: 0.14 }, eyes: pair(0.34, 0.13, 20) },
49
+ { id: "focused", name: "Focused", description: "Decisive attention", separation: 14.5, gaze: { x: 0.03, y: 0.04 }, eyes: pair(0.19, 0.32) },
50
+ { id: "concerned", name: "Concerned", description: "Careful review", separation: 16, gaze: { x: 0.03, y: -0.13 }, eyes: [eye(0.2, 0.4), eye(0.24, 0.32)] },
51
+ { id: "alert", name: "Alert", description: "Fully engaged", separation: 20.5, gaze: { x: 0.02, y: -0.2 }, eyes: pair(0.4, 0.6) },
52
+ { id: "skeptical", name: "Skeptical", description: "Evaluating closely", separation: 16, gaze: { x: 0.12, y: 0.06 }, eyes: [eye(0.21, 0.4), eye(0.22, 0.15)] },
53
+ { id: "puzzled", name: "Puzzled", description: "Working it through", separation: 16.5, gaze: { x: -0.14, y: 0.03 }, eyes: [eye(0.2, 0.44, -18), eye(0.28, 0.17, 14)] },
54
+ { id: "curious", name: "Curious", description: "Exploring a lead", separation: 16.5, gaze: { x: 0.16, y: -0.09 }, eyes: [eye(0.24, 0.46, -8), eye(0.2, 0.38, -8)] },
55
+ { id: "assured", name: "Assured", description: "Calm confidence", separation: 17, gaze: { x: 0.05, y: 0.14 }, eyes: pair(0.26, 0.2) },
56
+ { id: "reserved", name: "Reserved", description: "Present, understated", separation: 14, gaze: { x: -0.19, y: -0.14 }, eyes: pair(0.17, 0.3) },
57
+ { id: "unimpressed", name: "Unimpressed", description: "Measured restraint", separation: 16, gaze: { x: -0.22, y: 0.02 }, eyes: pair(0.3, 0.12) },
58
+ { id: "sleepy", name: "Sleepy", description: "Low energy", separation: 16, gaze: { x: 0.06, y: -0.09 }, eyes: pair(0.2, 0.42, 0, 0.42) }
59
+ ];
60
+ var EYE_EXPRESSION_BY_ID = new Map(
61
+ EYE_EXPRESSIONS.map((expression) => [expression.id, expression])
62
+ );
63
+ function blendEyeExpressions(from, to, progress) {
64
+ const mix = (a, b) => a + (b - a) * progress;
65
+ const blendEye = (index) => ({
66
+ width: mix(from.eyes[index].width, to.eyes[index].width),
67
+ height: mix(from.eyes[index].height, to.eyes[index].height),
68
+ tilt: mix(from.eyes[index].tilt, to.eyes[index].tilt),
69
+ open: mix(from.eyes[index].open, to.eyes[index].open)
70
+ });
71
+ return {
72
+ ...to,
73
+ separation: mix(from.separation, to.separation),
74
+ gaze: {
75
+ x: mix(from.gaze.x, to.gaze.x),
76
+ y: mix(from.gaze.y, to.gaze.y)
77
+ },
78
+ eyes: [blendEye(0), blendEye(1)]
79
+ };
80
+ }
81
+
82
+ // src/vendor/ui/agent-avatar/lab/eyes.ts
83
+ function clampGaze(gaze) {
84
+ return {
85
+ x: clamp(gaze.x, -1, 1),
86
+ y: clamp(gaze.y, -1, 1),
87
+ active: gaze.active ?? false
88
+ };
89
+ }
90
+ function eyePair(region, gaze, openness, state, expressionInput = "neutral", eyeScale = 1) {
91
+ const target = clampGaze(gaze);
92
+ const expression = typeof expressionInput === "string" ? EYE_EXPRESSION_BY_ID.get(expressionInput) ?? EYE_EXPRESSION_BY_ID.get("neutral") : expressionInput;
93
+ const gazeX = clamp(target.x + expression.gaze.x, -1, 1);
94
+ const gazeY = clamp(target.y + expression.gaze.y, -1, 1);
95
+ const centerX = region.x + region.width / 2 + gazeX * region.width * 0.065;
96
+ const centerY = region.y + region.height / 2 + gazeY * region.height * 0.075;
97
+ const separation = region.width * (expression.separation / 100);
98
+ const depthBias = target.x * 0.055;
99
+ const visibleOpenness = clamp(openness, 0.06, 1.08);
100
+ const buildEye = (side, index) => {
101
+ const geometry = expression.eyes[index];
102
+ const stateHeight = state === "waiting" ? 0.92 : state === "attentive" ? 1.04 : 1;
103
+ const eyeOpenness = visibleOpenness * geometry.open;
104
+ return {
105
+ cx: centerX + separation * side,
106
+ cy: centerY + (state === "working" ? side * 0.5 : 0),
107
+ width: region.height * geometry.width * (1 + depthBias * side) * eyeScale,
108
+ height: Math.max(2.4, region.height * geometry.height * eyeOpenness * stateHeight * eyeScale),
109
+ rotation: geometry.tilt + (state === "working" ? side * 1.5 : target.x * side * 1.8),
110
+ openness: eyeOpenness
111
+ };
112
+ };
113
+ return [buildEye(-1, 0), buildEye(1, 1)];
114
+ }
115
+
116
+ // src/vendor/ui/agent-avatar/lab/shape.ts
117
+ function normalizeProfile(radii, maximum = 1) {
118
+ const peak = Math.max(...radii);
119
+ if (!Number.isFinite(peak) || peak <= 0) return [...radii];
120
+ const factor = maximum / peak;
121
+ return radii.map((radius) => radius * factor);
122
+ }
123
+ function superellipseProfile(samples, exponent, scaleX = 1, scaleY = 1) {
124
+ return Array.from({ length: samples }, (_, index) => {
125
+ const angle = index / samples * TAU;
126
+ const x = Math.abs(Math.cos(angle) / scaleX) ** exponent;
127
+ const y = Math.abs(Math.sin(angle) / scaleY) ** exponent;
128
+ return (x + y) ** (-1 / exponent);
129
+ });
130
+ }
131
+ function unionOfCirclesProfile(samples, circles) {
132
+ return Array.from({ length: samples }, (_, index) => {
133
+ const angle = index / samples * TAU;
134
+ const dx = Math.cos(angle);
135
+ const dy = Math.sin(angle);
136
+ let furthest = 0;
137
+ for (const circle of circles) {
138
+ const projection = dx * circle.x + dy * circle.y;
139
+ const discriminant = projection ** 2 - (circle.x ** 2 + circle.y ** 2 - circle.radius ** 2);
140
+ if (discriminant < 0) continue;
141
+ furthest = Math.max(furthest, projection + Math.sqrt(discriminant));
142
+ }
143
+ return furthest;
144
+ });
145
+ }
146
+ function profileFromPolygon(samples, polygon, centerX = 0, centerY = 0) {
147
+ return Array.from({ length: samples }, (_, sampleIndex) => {
148
+ const angle = sampleIndex / samples * TAU;
149
+ const dx = Math.cos(angle);
150
+ const dy = Math.sin(angle);
151
+ let furthest = 0;
152
+ for (let index = 0; index < polygon.length; index += 1) {
153
+ const from = polygon[index];
154
+ const to = polygon[(index + 1) % polygon.length];
155
+ const edgeX = to.x - from.x;
156
+ const edgeY = to.y - from.y;
157
+ const denominator = dx * edgeY - dy * edgeX;
158
+ if (Math.abs(denominator) < 1e-9) continue;
159
+ const relativeX = from.x - centerX;
160
+ const relativeY = from.y - centerY;
161
+ const rayDistance = (relativeX * edgeY - relativeY * edgeX) / denominator;
162
+ const edgePosition = (relativeX * dy - relativeY * dx) / denominator;
163
+ if (rayDistance > furthest && edgePosition >= 0 && edgePosition <= 1) {
164
+ furthest = rayDistance;
165
+ }
166
+ }
167
+ return furthest;
168
+ });
169
+ }
170
+ function hullOfCircles(x1, y1, radius1, x2, y2, radius2, steps = 96) {
171
+ const dx = x2 - x1;
172
+ const dy = y2 - y1;
173
+ const distance = Math.hypot(dx, dy) || 1e-6;
174
+ const base = Math.atan2(dy, dx);
175
+ const spread = Math.acos(Math.min(1, Math.max(-1, (radius1 - radius2) / distance)));
176
+ const points = [];
177
+ for (let index = 0; index <= steps / 2; index += 1) {
178
+ const angle = base + spread + (TAU - 2 * spread) * index / (steps / 2);
179
+ points.push({ x: x1 + Math.cos(angle) * radius1, y: y1 + Math.sin(angle) * radius1 });
180
+ }
181
+ for (let index = 0; index <= steps / 2; index += 1) {
182
+ const angle = base - spread + 2 * spread * index / (steps / 2);
183
+ points.push({ x: x2 + Math.cos(angle) * radius2, y: y2 + Math.sin(angle) * radius2 });
184
+ }
185
+ return points;
186
+ }
187
+ function roundedPolygon(vertices, cornerRadius, arcSteps = 10) {
188
+ const outwardNormal = (from, to) => {
189
+ const dx = to.x - from.x;
190
+ const dy = to.y - from.y;
191
+ const length = Math.hypot(dx, dy) || 1;
192
+ return Math.atan2(-dx / length, dy / length);
193
+ };
194
+ const points = [];
195
+ for (let index = 0; index < vertices.length; index += 1) {
196
+ const previous = vertices[(index - 1 + vertices.length) % vertices.length];
197
+ const current = vertices[index];
198
+ const next = vertices[(index + 1) % vertices.length];
199
+ const fromAngle = outwardNormal(previous, current);
200
+ const toAngle = outwardNormal(current, next);
201
+ let delta = toAngle - fromAngle;
202
+ while (delta > Math.PI) delta -= TAU;
203
+ while (delta < -Math.PI) delta += TAU;
204
+ for (let step = 0; step <= arcSteps; step += 1) {
205
+ const angle = fromAngle + delta * step / arcSteps;
206
+ points.push({
207
+ x: current.x + Math.cos(angle) * cornerRadius,
208
+ y: current.y + Math.sin(angle) * cornerRadius
209
+ });
210
+ }
211
+ }
212
+ return points;
213
+ }
214
+ function regularPolygonProfile(samples, sides, radius, cornerRadius, rotationDegrees = 0) {
215
+ const rotation = rotationDegrees * Math.PI / 180;
216
+ const vertices = Array.from({ length: sides }, (_, index) => {
217
+ const angle = rotation + index / sides * TAU;
218
+ return {
219
+ x: Math.cos(angle) * (radius - cornerRadius),
220
+ y: Math.sin(angle) * (radius - cornerRadius)
221
+ };
222
+ });
223
+ return profileFromPolygon(samples, roundedPolygon(vertices, cornerRadius));
224
+ }
225
+ function blendProfiles(from, to, progress) {
226
+ const length = Math.min(from.length, to.length);
227
+ return Array.from(
228
+ { length },
229
+ (_, index) => lerp(from[index] ?? 1, to[index] ?? 1, progress)
230
+ );
231
+ }
232
+ function profilePoints(radii, radius = 104, centerX = 128, centerY = 128, pose = {}) {
233
+ const rotation = pose.rotation ?? 0;
234
+ const scaleX = pose.scaleX ?? 1;
235
+ const scaleY = pose.scaleY ?? 1;
236
+ const translateX = pose.translateX ?? 0;
237
+ const translateY = pose.translateY ?? 0;
238
+ const cosine = Math.cos(rotation);
239
+ const sine = Math.sin(rotation);
240
+ return radii.map((profileRadius, index) => {
241
+ const angle = index / radii.length * TAU;
242
+ const x = profileRadius * Math.cos(angle);
243
+ const y = profileRadius * Math.sin(angle);
244
+ const rotatedX = x * cosine - y * sine;
245
+ const rotatedY = x * sine + y * cosine;
246
+ return {
247
+ x: centerX + (rotatedX * scaleX + translateX) * radius,
248
+ y: centerY + (rotatedY * scaleY + translateY) * radius
249
+ };
250
+ });
251
+ }
252
+ function closedPath(points, tension = 1 / 6) {
253
+ const count = points.length;
254
+ if (count < 3) return "";
255
+ const first = points[0];
256
+ let path = `M${r2(first.x)} ${r2(first.y)}`;
257
+ for (let index = 0; index < count; index += 1) {
258
+ const before = points[(index - 1 + count) % count];
259
+ const current = points[index];
260
+ const next = points[(index + 1) % count];
261
+ const after = points[(index + 2) % count];
262
+ const c1x = current.x + (next.x - before.x) * tension;
263
+ const c1y = current.y + (next.y - before.y) * tension;
264
+ const c2x = next.x - (after.x - current.x) * tension;
265
+ const c2y = next.y - (after.y - current.y) * tension;
266
+ path += `C${r2(c1x)} ${r2(c1y)} ${r2(c2x)} ${r2(c2y)} ${r2(next.x)} ${r2(next.y)}`;
267
+ }
268
+ return `${path}Z`;
269
+ }
270
+ function profilePath(radii, pose = {}, tension = 1 / 6) {
271
+ return closedPath(profilePoints(radii, 104, 128, 128, pose), tension);
272
+ }
273
+
274
+ // src/vendor/ui/agent-avatar/lab/profiles.ts
275
+ var PROFILE_SAMPLES = 64;
276
+ var angles = Array.from(
277
+ { length: PROFILE_SAMPLES },
278
+ (_, index) => index / PROFILE_SAMPLES * Math.PI * 2
279
+ );
280
+ var harmonic = (fn, maximum = 1) => normalizeProfile(angles.map(fn), maximum);
281
+ var round = new Array(PROFILE_SAMPLES).fill(1);
282
+ var pebble = harmonic(
283
+ (angle) => 1 + 0.075 * Math.cos(2 * angle + 0.5) + 0.035 * Math.cos(3 * angle + 2.1),
284
+ 1.02
285
+ );
286
+ var squircle = normalizeProfile(superellipseProfile(PROFILE_SAMPLES, 4.2), 1.15);
287
+ var capsule = profileFromPolygon(
288
+ PROFILE_SAMPLES,
289
+ hullOfCircles(-0.42, 0, 0.62, 0.42, 0, 0.62)
290
+ );
291
+ var triangle = regularPolygonProfile(PROFILE_SAMPLES, 3, 1.12, 0.34, -90);
292
+ var hexagon = regularPolygonProfile(PROFILE_SAMPLES, 6, 1.04, 0.26);
293
+ var cloud = normalizeProfile(
294
+ unionOfCirclesProfile(PROFILE_SAMPLES, [
295
+ { x: -0.44, y: 0.2, radius: 0.54 },
296
+ { x: 0.46, y: 0.2, radius: 0.5 },
297
+ { x: 0.02, y: 0.3, radius: 0.6 },
298
+ { x: -0.24, y: -0.3, radius: 0.48 },
299
+ { x: 0.3, y: -0.24, radius: 0.44 }
300
+ ]),
301
+ 1.02
302
+ );
303
+ var sampleCubic = (from, controlA, controlB, to, steps = 32) => Array.from({ length: steps }, (_, index) => {
304
+ const progress = index / steps;
305
+ const inverse = 1 - progress;
306
+ return {
307
+ x: inverse ** 3 * from.x + 3 * inverse ** 2 * progress * controlA.x + 3 * inverse * progress ** 2 * controlB.x + progress ** 3 * to.x,
308
+ y: inverse ** 3 * from.y + 3 * inverse ** 2 * progress * controlA.y + 3 * inverse * progress ** 2 * controlB.y + progress ** 3 * to.y
309
+ };
310
+ });
311
+ var eggTop = { x: 0, y: -0.9 };
312
+ var eggWidest = { x: 0.76, y: 0.15 };
313
+ var eggBottom = { x: 0, y: 0.96 };
314
+ var eggRight = [
315
+ ...sampleCubic(eggTop, { x: 0.4, y: -0.91 }, { x: 0.75, y: -0.43 }, eggWidest),
316
+ ...sampleCubic(eggWidest, { x: 0.77, y: 0.6 }, { x: 0.42, y: 0.96 }, eggBottom),
317
+ eggBottom
318
+ ];
319
+ var eggOutline = [
320
+ ...eggRight,
321
+ ...eggRight.slice(1, -1).reverse().map((point) => ({ x: -point.x, y: point.y }))
322
+ ];
323
+ var egg = normalizeProfile(
324
+ profileFromPolygon(PROFILE_SAMPLES, eggOutline),
325
+ 1.04
326
+ );
327
+ var smoothCircularProfile = (radii, passes = 2) => {
328
+ let current = [...radii];
329
+ for (let pass = 0; pass < passes; pass += 1) {
330
+ current = current.map((radius, index) => {
331
+ const before = current[(index - 1 + current.length) % current.length];
332
+ const after = current[(index + 1) % current.length];
333
+ return before * 0.2 + radius * 0.6 + after * 0.2;
334
+ });
335
+ }
336
+ return current;
337
+ };
338
+ var eary = normalizeProfile(
339
+ smoothCircularProfile(profileFromPolygon(PROFILE_SAMPLES, [
340
+ { x: 0, y: -0.56 },
341
+ { x: 0.25, y: -0.58 },
342
+ { x: 0.68, y: -0.98 },
343
+ { x: 0.84, y: -0.3 },
344
+ { x: 0.86, y: 0.28 },
345
+ { x: 0.68, y: 0.66 },
346
+ { x: 0, y: 0.86 },
347
+ { x: -0.68, y: 0.66 },
348
+ { x: -0.86, y: 0.28 },
349
+ { x: -0.84, y: -0.3 },
350
+ { x: -0.68, y: -0.98 },
351
+ { x: -0.25, y: -0.58 }
352
+ ]), 1),
353
+ 1.04
354
+ );
355
+ var puff = normalizeProfile(
356
+ smoothCircularProfile(unionOfCirclesProfile(PROFILE_SAMPLES, [
357
+ { x: 0, y: -0.1, radius: 0.75 },
358
+ { x: -0.62, y: 0.3, radius: 0.38 },
359
+ { x: 0.62, y: 0.3, radius: 0.38 },
360
+ { x: 0, y: 0.2, radius: 0.66 }
361
+ ]), 1),
362
+ 1.04
363
+ );
364
+ var orb = new Array(PROFILE_SAMPLES).fill(0.99);
365
+ var rolePolygon = (points, minimum = 0.5, maximum = 1.05) => normalizeProfile(
366
+ smoothCircularProfile(
367
+ profileFromPolygon(PROFILE_SAMPLES, points).map((radius) => Math.max(minimum, radius))
368
+ ),
369
+ maximum
370
+ );
371
+ var bolt = rolePolygon([
372
+ { x: -0.18, y: -1 },
373
+ { x: 0.58, y: -1 },
374
+ { x: 0.22, y: -0.25 },
375
+ { x: 0.92, y: -0.25 },
376
+ { x: -0.52, y: 1 },
377
+ { x: -0.26, y: 0.18 },
378
+ { x: -0.92, y: 0.18 }
379
+ ], 0.56, 1.08);
380
+ var briefcase = rolePolygon([
381
+ { x: -0.94, y: -0.48 },
382
+ { x: -0.38, y: -0.48 },
383
+ { x: -0.38, y: -0.82 },
384
+ { x: 0.38, y: -0.82 },
385
+ { x: 0.38, y: -0.48 },
386
+ { x: 0.94, y: -0.48 },
387
+ { x: 0.94, y: 0.78 },
388
+ { x: -0.94, y: 0.78 }
389
+ ], 0.58, 1.04);
390
+ var chart = rolePolygon([
391
+ { x: -0.92, y: 0.84 },
392
+ { x: -0.92, y: 0.12 },
393
+ { x: -0.42, y: 0.12 },
394
+ { x: -0.42, y: -0.3 },
395
+ { x: 0.08, y: -0.3 },
396
+ { x: 0.08, y: -0.78 },
397
+ { x: 0.66, y: -0.78 },
398
+ { x: 0.66, y: 0.84 }
399
+ ], 0.52, 1.04);
400
+ var support = rolePolygon([
401
+ { x: -0.94, y: -0.76 },
402
+ { x: 0.94, y: -0.76 },
403
+ { x: 0.94, y: 0.48 },
404
+ { x: 0.28, y: 0.48 },
405
+ { x: 0, y: 0.94 },
406
+ { x: -0.26, y: 0.48 },
407
+ { x: -0.94, y: 0.48 }
408
+ ], 0.58, 1.04);
409
+ var spark = rolePolygon([
410
+ { x: 0, y: -1.02 },
411
+ { x: 0.25, y: -0.4 },
412
+ { x: 0.92, y: -0.34 },
413
+ { x: 0.42, y: 0.1 },
414
+ { x: 0.58, y: 0.8 },
415
+ { x: 0, y: 0.46 },
416
+ { x: -0.58, y: 0.8 },
417
+ { x: -0.42, y: 0.1 },
418
+ { x: -0.92, y: -0.34 },
419
+ { x: -0.25, y: -0.4 }
420
+ ], 0.58, 1.04);
421
+ var roundedRectPath = (x, y, width, height, radius) => {
422
+ const right = x + width;
423
+ const bottom = y + height;
424
+ return `M${x + radius} ${y}H${right - radius}Q${right} ${y} ${right} ${y + radius}V${bottom - radius}Q${right} ${bottom} ${right - radius} ${bottom}H${x + radius}Q${x} ${bottom} ${x} ${bottom - radius}V${y + radius}Q${x} ${y} ${x + radius} ${y}Z`;
425
+ };
426
+ var ROLE_PATHS = {
427
+ bolt: "M154 38Q164 34 159 48L143 94Q141 101 149 101H194Q210 101 199 113L109 211Q98 223 102 206L118 157Q121 149 111 149H62Q46 149 57 137L143 43Q148 38 154 38Z",
428
+ briefcase: `${roundedRectPath(42, 82, 172, 126, 26)}M78 82V70Q78 45 104 45H152Q178 45 178 70V82H157V70Q157 65 151 65H105Q99 65 99 70V82Z`,
429
+ chart: "M62 207Q45 207 45 190V151Q45 137 59 137H96V105Q96 91 110 91H151V59Q151 45 165 45H194Q208 45 208 59V190Q208 207 191 207Z",
430
+ support: "M63 48H193Q216 48 216 72V149Q216 173 192 173H167L138 201Q127 211 126 196V173H63Q39 173 39 149V72Q39 48 63 48Z",
431
+ spark: "M122 42Q128 27 134 42L151 83Q154 90 162 90L205 91Q221 91 209 103L176 132Q170 138 173 146L184 187Q188 202 175 194L136 171Q128 166 120 171L81 194Q68 202 72 187L83 146Q86 138 80 132L47 103Q35 91 51 91L94 90Q102 90 105 83Z"
432
+ };
433
+ var ROLE_LAYERS = {
434
+ bolt: [
435
+ { path: "M154 38Q164 34 159 48L143 94Q141 101 149 101H162L118 149H62Q46 149 57 137L143 43Q148 38 154 38Z", tone: "highlight", opacity: 0.14 },
436
+ { path: "M118 157Q121 149 111 149H144L199 113Q210 101 194 101H149L137 149L109 211Q98 223 102 206Z", tone: "shade", opacity: 0.12 }
437
+ ],
438
+ briefcase: [
439
+ { path: "M42 106Q42 82 66 82H190Q214 82 214 106V119Q176 142 128 142Q80 142 42 119Z", tone: "highlight", opacity: 0.18 },
440
+ { path: "M42 181Q80 198 128 198Q176 198 214 181V184Q214 208 190 208H66Q42 208 42 184Z", tone: "shade", opacity: 0.09 }
441
+ ],
442
+ chart: [
443
+ { path: "M45 151Q45 137 59 137H96V190Q96 207 79 207H62Q45 207 45 190Z", tone: "highlight", opacity: 0.24 },
444
+ { path: "M151 59Q151 45 165 45H194Q208 45 208 59V190Q208 207 191 207H151Z", tone: "shade", opacity: 0.12 }
445
+ ],
446
+ support: [
447
+ { path: "M63 48H193Q216 48 216 72V88H39V72Q39 48 63 48Z", tone: "highlight", opacity: 0.24 },
448
+ { path: "M39 140Q84 158 128 158Q172 158 216 140V149Q216 173 192 173H167L138 201Q127 211 126 196V173H63Q39 173 39 149Z", tone: "shade", opacity: 0.14 }
449
+ ],
450
+ spark: [
451
+ { path: "M122 42Q128 27 134 42L151 83Q154 90 162 90L177 90L148 116Q141 122 144 132L155 182L136 171Q128 166 120 171L81 194Q68 202 72 187L83 146Q86 138 80 132L47 103Q35 91 51 91L94 90Q102 90 105 83Z", tone: "highlight", opacity: 0.3 },
452
+ { path: "M148 116L177 90L205 91Q221 91 209 103L176 132Q170 138 173 146L184 187Q188 202 175 194L155 182L144 132Q141 122 148 116Z", tone: "shade", opacity: 0.22 }
453
+ ]
454
+ };
455
+ var AVATAR_SHAPES = [
456
+ {
457
+ id: "round",
458
+ name: "Round",
459
+ description: "Balanced and open",
460
+ family: "core",
461
+ faceStyle: "monitor",
462
+ pathTension: 1 / 6,
463
+ radii: round,
464
+ face: { x: 56, y: 70, width: 144, height: 116, radius: 32 }
465
+ },
466
+ {
467
+ id: "pebble",
468
+ name: "Pebble",
469
+ description: "Quietly organic",
470
+ family: "core",
471
+ faceStyle: "monitor",
472
+ pathTension: 1 / 6,
473
+ radii: pebble,
474
+ face: { x: 56, y: 70, width: 144, height: 116, radius: 32 }
475
+ },
476
+ {
477
+ id: "squircle",
478
+ name: "Squircle",
479
+ description: "Precise and neutral",
480
+ family: "core",
481
+ faceStyle: "monitor",
482
+ pathTension: 1 / 6,
483
+ radii: squircle,
484
+ face: { x: 54, y: 68, width: 148, height: 120, radius: 30 }
485
+ },
486
+ {
487
+ id: "capsule",
488
+ name: "Capsule",
489
+ description: "Wide and operational",
490
+ family: "core",
491
+ faceStyle: "monitor",
492
+ pathTension: 1 / 6,
493
+ radii: capsule,
494
+ face: { x: 58, y: 78, width: 140, height: 100, radius: 28 }
495
+ },
496
+ {
497
+ id: "triangle",
498
+ name: "Triangle",
499
+ description: "Directional and clear",
500
+ family: "core",
501
+ faceStyle: "monitor",
502
+ pathTension: 1 / 6,
503
+ radii: triangle,
504
+ face: { x: 73, y: 96, width: 110, height: 94, radius: 25 }
505
+ },
506
+ {
507
+ id: "hexagon",
508
+ name: "Hexagon",
509
+ description: "Structured and assured",
510
+ family: "core",
511
+ faceStyle: "monitor",
512
+ pathTension: 1 / 6,
513
+ radii: hexagon,
514
+ face: { x: 59, y: 78, width: 138, height: 104, radius: 27 }
515
+ },
516
+ {
517
+ id: "cloud",
518
+ name: "Cloud",
519
+ description: "Flexible and collaborative",
520
+ family: "core",
521
+ faceStyle: "monitor",
522
+ pathTension: 1 / 6,
523
+ radii: cloud,
524
+ face: { x: 60, y: 88, width: 136, height: 100, radius: 30 }
525
+ },
526
+ {
527
+ id: "egg",
528
+ name: "Egg",
529
+ description: "Warm and composed",
530
+ family: "core",
531
+ faceStyle: "monitor",
532
+ pathTension: 1 / 6,
533
+ radii: egg,
534
+ face: { x: 68, y: 78, width: 120, height: 106, radius: 30 }
535
+ },
536
+ {
537
+ id: "eary",
538
+ name: "Eary",
539
+ description: "Curious and observant",
540
+ family: "core",
541
+ faceStyle: "monitor",
542
+ pathTension: 0.12,
543
+ radii: eary,
544
+ face: { x: 62, y: 82, width: 132, height: 104, radius: 30 }
545
+ },
546
+ {
547
+ id: "puff",
548
+ name: "Puff",
549
+ description: "Soft and easygoing",
550
+ family: "core",
551
+ faceStyle: "monitor",
552
+ pathTension: 1 / 6,
553
+ radii: puff,
554
+ face: { x: 59, y: 76, width: 138, height: 110, radius: 31 }
555
+ },
556
+ {
557
+ id: "orb",
558
+ name: "Orb",
559
+ description: "Ambient and responsive",
560
+ family: "orb",
561
+ faceStyle: "open",
562
+ pathTension: 1 / 6,
563
+ radii: orb,
564
+ face: { x: 70, y: 84, width: 116, height: 88, radius: 40 }
565
+ },
566
+ {
567
+ id: "bolt",
568
+ name: "Bolt",
569
+ description: "Automation and action",
570
+ family: "role",
571
+ role: "Automation",
572
+ referenceIcon: "bolt",
573
+ faceStyle: "open",
574
+ pathTension: 0.06,
575
+ opticalScale: 1.2,
576
+ restPath: ROLE_PATHS.bolt,
577
+ layers: ROLE_LAYERS.bolt,
578
+ radii: bolt,
579
+ face: { x: 82, y: 98, width: 92, height: 62, radius: 20 }
580
+ },
581
+ {
582
+ id: "briefcase",
583
+ name: "Briefcase",
584
+ description: "Business operations",
585
+ family: "role",
586
+ role: "Business",
587
+ referenceIcon: "suitcase-work",
588
+ faceStyle: "open",
589
+ pathTension: 0.06,
590
+ opticalScale: 1.2,
591
+ restPath: ROLE_PATHS.briefcase,
592
+ layers: ROLE_LAYERS.briefcase,
593
+ radii: briefcase,
594
+ face: { x: 78, y: 108, width: 100, height: 66, radius: 20 }
595
+ },
596
+ {
597
+ id: "chart",
598
+ name: "Chart",
599
+ description: "Analytics and reporting",
600
+ family: "role",
601
+ role: "Analytics",
602
+ referenceIcon: "chart-3",
603
+ faceStyle: "open",
604
+ pathTension: 0.06,
605
+ opticalScale: 1.26,
606
+ restPath: ROLE_PATHS.chart,
607
+ layers: ROLE_LAYERS.chart,
608
+ radii: chart,
609
+ face: { x: 62, y: 125, width: 112, height: 62, radius: 20 }
610
+ },
611
+ {
612
+ id: "support",
613
+ name: "Support",
614
+ description: "Customer service",
615
+ family: "role",
616
+ role: "Customer Support",
617
+ referenceIcon: "bubble-wide",
618
+ faceStyle: "open",
619
+ pathTension: 0.06,
620
+ opticalScale: 1.16,
621
+ restPath: ROLE_PATHS.support,
622
+ layers: ROLE_LAYERS.support,
623
+ radii: support,
624
+ face: { x: 73, y: 80, width: 110, height: 70, radius: 20 }
625
+ },
626
+ {
627
+ id: "spark",
628
+ name: "Spark",
629
+ description: "Initiative and outreach",
630
+ family: "role",
631
+ role: "Outreach",
632
+ referenceIcon: "star",
633
+ faceStyle: "open",
634
+ pathTension: 0.06,
635
+ opticalScale: 1.27,
636
+ restPath: ROLE_PATHS.spark,
637
+ layers: ROLE_LAYERS.spark,
638
+ radii: spark,
639
+ face: { x: 82, y: 97, width: 92, height: 62, radius: 20 }
640
+ }
641
+ ];
642
+ var AVATAR_SHAPE_BY_ID = new Map(AVATAR_SHAPES.map((shape) => [shape.id, shape]));
643
+ var AVATAR_FACE_COLORS = {
644
+ light: { face: "#F7F3E8", eyes: "#202228" },
645
+ dark: { face: "#6B6E78", eyes: "#202228" }
646
+ };
647
+ var AVATAR_EYE_SCALE = {
648
+ small: 0.5,
649
+ normal: 0.64,
650
+ large: 0.82
651
+ };
652
+ var DEFAULT_IDENTITY = {
653
+ color: "#3B93F0"};
654
+ function normalizeColor(value) {
655
+ const compact = value.trim();
656
+ const short = /^#([0-9a-f]{3})$/i.exec(compact);
657
+ if (short) {
658
+ const [red, green, blue] = short[1].split("");
659
+ return `#${red}${red}${green}${green}${blue}${blue}`.toUpperCase();
660
+ }
661
+ if (!/^#[0-9a-f]{6}$/i.test(compact)) return null;
662
+ return compact.toUpperCase();
663
+ }
664
+ function relativeLuminance(hex) {
665
+ const normalized = normalizeColor(hex) ?? DEFAULT_IDENTITY.color;
666
+ const channels = [1, 3, 5].map((index) => {
667
+ const value = Number.parseInt(normalized.slice(index, index + 2), 16) / 255;
668
+ return value <= 0.04045 ? value / 12.92 : ((value + 0.055) / 1.055) ** 2.4;
669
+ });
670
+ return channels[0] * 0.2126 + channels[1] * 0.7152 + channels[2] * 0.0722;
671
+ }
672
+ function contrastRatio(first, second) {
673
+ const light = Math.max(relativeLuminance(first), relativeLuminance(second));
674
+ const dark = Math.min(relativeLuminance(first), relativeLuminance(second));
675
+ return (light + 0.05) / (dark + 0.05);
676
+ }
677
+ function resolveOpenEyeColor(_housingColor) {
678
+ return AVATAR_FACE_COLORS.light.eyes;
679
+ }
680
+ function resolveEyeColorOnBody(bodyColor) {
681
+ const dark = AVATAR_FACE_COLORS.light.eyes;
682
+ const light = AVATAR_FACE_COLORS.light.face;
683
+ return contrastRatio(bodyColor, dark) >= contrastRatio(bodyColor, light) ? dark : light;
684
+ }
685
+ function resolveFaceColors(housingColor, preference) {
686
+ let tone;
687
+ if (preference === "auto") {
688
+ const lightContrast = contrastRatio(housingColor, AVATAR_FACE_COLORS.light.face);
689
+ const darkContrast = contrastRatio(housingColor, AVATAR_FACE_COLORS.dark.face);
690
+ tone = lightContrast >= 2.25 || lightContrast >= darkContrast ? "light" : "dark";
691
+ } else {
692
+ tone = preference;
693
+ }
694
+ return { tone, ...AVATAR_FACE_COLORS[tone] };
695
+ }
696
+
697
+ // src/vendor/ui/agent-avatar/lab/motion.ts
698
+ var BLINK_RNG = createRng(24301);
699
+ var BLINKS = (() => {
700
+ const schedule = [];
701
+ let time = 1.4;
702
+ while (time < 900) {
703
+ schedule.push(time);
704
+ time += 1.9 + BLINK_RNG() * 2.7;
705
+ if (BLINK_RNG() < 0.18) {
706
+ schedule.push(time);
707
+ time += 0.24;
708
+ }
709
+ }
710
+ return schedule;
711
+ })();
712
+ var BLINK_DURATION = 0.18;
713
+ function blinkOpenness(time, _motionKey = "frontera") {
714
+ const wrapped = (time % 900 + 900) % 900;
715
+ for (const start of BLINKS) {
716
+ if (wrapped < start) break;
717
+ const progress = (wrapped - start) / BLINK_DURATION;
718
+ if (progress >= 0 && progress <= 1) {
719
+ const lid = progress < 0.45 ? 1 - progress / 0.45 : (progress - 0.45) / 0.55;
720
+ return 0.06 + 0.94 * clamp(lid);
721
+ }
722
+ }
723
+ return 1;
724
+ }
725
+ var eye2 = (width, height, tilt = 0, open = 1) => ({
726
+ width,
727
+ height,
728
+ tilt,
729
+ open
730
+ });
731
+ var stateExpression = (separation, gaze, eyes) => ({
732
+ id: "neutral",
733
+ name: "State pose",
734
+ description: "Mapped from Bloub",
735
+ separation,
736
+ gaze,
737
+ eyes
738
+ });
739
+ var WIDE_EYES = stateExpression(
740
+ 18.43,
741
+ { x: 0, y: 0 },
742
+ [eye2(0.356, 0.875), eye2(0.356, 0.875)]
743
+ );
744
+ var WINK_EYES = stateExpression(
745
+ 16.25,
746
+ { x: 0, y: 0 },
747
+ [eye2(0.236, 0.464), eye2(0.447, 0.089)]
748
+ );
749
+ var still = () => ({
750
+ gazeX: 0,
751
+ gazeY: 0,
752
+ openness: 1,
753
+ scale: 1,
754
+ rotation: 0,
755
+ translateX: 0,
756
+ translateY: 0,
757
+ faceOpacity: 1,
758
+ eyeOpacity: 1,
759
+ bodyRadius: null,
760
+ eyeExpression: null
761
+ });
762
+ function sampleStateMotion(state, time, _motionKey) {
763
+ if (state === "paused") return still();
764
+ const blink = blinkOpenness(time);
765
+ const driftX = loopNoise(time, 7.9, 1.9) * 6e-3 * 104;
766
+ const driftY = loopNoise(time, 5.3, 0.3) * 7e-3 * 104;
767
+ const breath = 1 + Math.sin(time / 3.4 * Math.PI * 2) * 5e-3;
768
+ const wanderX = loopNoise(time, 11.3, 0.4) * 0.18 + loopNoise(time, 3.7, 2.1) * 0.053;
769
+ const wanderY = loopNoise(time, 9.1, 1.3) * 0.14 + loopNoise(time, 4.3, 0.7) * 0.043;
770
+ if (state === "attentive") {
771
+ return {
772
+ ...still(),
773
+ // Bloub `wide`: yaw 6.92, pitch -21.96, roll 11.6.
774
+ gazeX: 6.92 / 30 + wanderX,
775
+ gazeY: -21.96 / 30 + wanderY,
776
+ openness: blink,
777
+ rotation: 11.6 * Math.PI / 180,
778
+ translateX: driftX,
779
+ translateY: driftY,
780
+ scale: breath,
781
+ eyeExpression: WIDE_EYES
782
+ };
783
+ }
784
+ if (state === "working") {
785
+ const scan = Math.sin(time / 1.8 * TAU);
786
+ const lift = Math.cos(time / 1.8 * TAU);
787
+ return {
788
+ ...still(),
789
+ gazeX: scan * 0.6,
790
+ gazeY: lift * 0.12,
791
+ openness: blink,
792
+ rotation: scan * 0.035,
793
+ translateX: scan * 3.2,
794
+ translateY: lift * 1.4,
795
+ scale: 1 + lift * 6e-3
796
+ };
797
+ }
798
+ if (state === "responding") {
799
+ return {
800
+ ...still(),
801
+ // Bloub `wink`: yaw -5.37, pitch 4.55, roll 6.7.
802
+ gazeX: -5.37 / 30 + wanderX,
803
+ gazeY: 4.55 / 30 + wanderY,
804
+ openness: blink,
805
+ rotation: 6.7 * Math.PI / 180,
806
+ translateX: driftX,
807
+ translateY: driftY,
808
+ scale: breath,
809
+ eyeExpression: WINK_EYES
810
+ };
811
+ }
812
+ if (state === "waiting") {
813
+ const bounce = Math.abs(Math.sin(time / 1.2 * TAU));
814
+ const alternate = 0.5 + 0.5 * Math.sin(time / 1.2 * TAU);
815
+ const loadingEyes = stateExpression(
816
+ 16,
817
+ { x: 0, y: -0.03 },
818
+ [
819
+ eye2(0.2, 0.42, 0, lerp(0.36, 1, alternate)),
820
+ eye2(0.2, 0.42, 0, lerp(1, 0.36, alternate))
821
+ ]
822
+ );
823
+ return {
824
+ ...still(),
825
+ openness: blink,
826
+ rotation: Math.sin(time / 2.4 * TAU) * 0.02,
827
+ translateY: -bounce * 8,
828
+ scale: 1 + bounce * 0.012,
829
+ eyeExpression: loadingEyes
830
+ };
831
+ }
832
+ return {
833
+ ...still(),
834
+ gazeX: wanderX,
835
+ gazeY: wanderY,
836
+ openness: blink,
837
+ scale: breath,
838
+ translateX: driftX,
839
+ translateY: driftY
840
+ };
841
+ }
842
+ function blendMotion(from, to, progress) {
843
+ const mix = clamp(progress);
844
+ return {
845
+ gazeX: lerp(from.gazeX, to.gazeX, mix),
846
+ gazeY: lerp(from.gazeY, to.gazeY, mix),
847
+ openness: lerp(from.openness, to.openness, mix),
848
+ scale: lerp(from.scale, to.scale, mix),
849
+ rotation: lerp(from.rotation, to.rotation, mix),
850
+ translateX: lerp(from.translateX, to.translateX, mix),
851
+ translateY: lerp(from.translateY, to.translateY, mix),
852
+ faceOpacity: lerp(from.faceOpacity, to.faceOpacity, mix),
853
+ eyeOpacity: lerp(from.eyeOpacity, to.eyeOpacity, mix),
854
+ bodyRadius: to.bodyRadius,
855
+ eyeExpression: to.eyeExpression
856
+ };
857
+ }
858
+
859
+ // src/vendor/ui/agent-avatar/lab/engine.ts
860
+ var ROLE_EYE_SCALE = 1.35;
861
+ function sampleAvatarFrame({
862
+ shape: shapeId,
863
+ state,
864
+ time,
865
+ seed = "frontera",
866
+ gaze,
867
+ previousState,
868
+ transition = 1,
869
+ profile,
870
+ face: faceOverride,
871
+ expression = "neutral",
872
+ eyeSize = "normal"
873
+ }) {
874
+ const shape = AVATAR_SHAPE_BY_ID.get(shapeId) ?? AVATAR_SHAPE_BY_ID.get("squircle");
875
+ const face = faceOverride ?? shape.face;
876
+ const current = sampleStateMotion(state, state === "paused" ? 0 : time);
877
+ const previous = previousState ? sampleStateMotion(previousState, state === "paused" ? 0 : time) : current;
878
+ const stateMix = clamp(transition);
879
+ const motion = blendMotion(previous, current, stateMix);
880
+ const externalGaze = gaze ? clampGaze(gaze) : null;
881
+ const resolvedGaze = externalGaze?.active ? externalGaze : { x: motion.gazeX, y: motion.gazeY, active: false };
882
+ const identityProfile = profile ?? shape.radii;
883
+ const profileFor = (radius) => radius === null ? identityProfile : new Array(PROFILE_SAMPLES).fill(radius);
884
+ const bodyProfile = blendProfiles(
885
+ profileFor(previous.bodyRadius),
886
+ profileFor(current.bodyRadius),
887
+ stateMix
888
+ );
889
+ const selectedExpression = EYE_EXPRESSION_BY_ID.get(expression) ?? EYE_EXPRESSION_BY_ID.get("neutral");
890
+ const fromExpression = previous.eyeExpression ?? selectedExpression;
891
+ const toExpression = current.eyeExpression ?? selectedExpression;
892
+ const resolvedExpression = blendEyeExpressions(fromExpression, toExpression, stateMix);
893
+ const usesAuthoredShape = Boolean(shape.restPath);
894
+ return {
895
+ bodyPath: usesAuthoredShape && shape.restPath ? shape.restPath : profilePath(bodyProfile, {}, shape.pathTension),
896
+ body: {
897
+ scale: motion.scale,
898
+ rotation: motion.rotation,
899
+ translateX: motion.translateX,
900
+ translateY: motion.translateY
901
+ },
902
+ face,
903
+ faceOpacity: motion.faceOpacity,
904
+ eyeOpacity: motion.eyeOpacity,
905
+ eyes: eyePair(
906
+ face,
907
+ resolvedGaze,
908
+ motion.openness,
909
+ state,
910
+ resolvedExpression,
911
+ AVATAR_EYE_SCALE[eyeSize] * (shape.faceStyle === "open" ? ROLE_EYE_SCALE : 1)
912
+ ),
913
+ gaze: clampGaze(resolvedGaze),
914
+ usesAuthoredShape
915
+ };
916
+ }
917
+ var BOX_FRAME = { x: 22, y: 22, size: 212, radius: 48 };
918
+ function mixHexColor(hex, target, amount) {
919
+ const digits = hex.replace("#", "");
920
+ const full = digits.length === 3 ? digits.split("").map((d) => d + d).join("") : digits;
921
+ const value = Number.parseInt(full, 16);
922
+ const channels = [value >> 16 & 255, value >> 8 & 255, value & 255];
923
+ const mixed = channels.map(
924
+ (channel) => Math.round(channel + (target * 255 - channel) * amount).toString(16).padStart(2, "0")
925
+ );
926
+ return `#${mixed.join("")}`;
927
+ }
928
+ function glassGradientIds(instanceId) {
929
+ const prefix = `frontera-glass-${instanceId}`;
930
+ return {
931
+ backdrop: `${prefix}-backdrop`,
932
+ rim: `${prefix}-rim`,
933
+ innerBevel: `${prefix}-bevel`,
934
+ surfaceGlare: `${prefix}-glare`,
935
+ screenReflection: `${prefix}-refl`,
936
+ microGrain: `${prefix}-grain`
937
+ };
938
+ }
939
+ function GlassDefs({ ids }) {
940
+ return /* @__PURE__ */ jsxs("defs", { children: [
941
+ /* @__PURE__ */ jsxs("linearGradient", { id: ids.backdrop, x1: "0", y1: "0", x2: "0", y2: "1", children: [
942
+ /* @__PURE__ */ jsx("stop", { offset: "0%", stopColor: "#FFFFFF", stopOpacity: "0.055" }),
943
+ /* @__PURE__ */ jsx("stop", { offset: "55%", stopColor: "#FFFFFF", stopOpacity: "0.012" }),
944
+ /* @__PURE__ */ jsx("stop", { offset: "100%", stopColor: "#000000", stopOpacity: "0.03" })
945
+ ] }),
946
+ /* @__PURE__ */ jsxs("linearGradient", { id: ids.rim, x1: "0", y1: "0", x2: "1", y2: "1", children: [
947
+ /* @__PURE__ */ jsx("stop", { offset: "0%", stopColor: "#FFFFFF", stopOpacity: "0.8" }),
948
+ /* @__PURE__ */ jsx("stop", { offset: "30%", stopColor: "#FFFFFF", stopOpacity: "0.35" }),
949
+ /* @__PURE__ */ jsx("stop", { offset: "70%", stopColor: "#FFFFFF", stopOpacity: "0.1" }),
950
+ /* @__PURE__ */ jsx("stop", { offset: "100%", stopColor: "#FFFFFF", stopOpacity: "0.28" })
951
+ ] }),
952
+ /* @__PURE__ */ jsxs("linearGradient", { id: ids.innerBevel, x1: "0", y1: "0", x2: "0", y2: "1", children: [
953
+ /* @__PURE__ */ jsx("stop", { offset: "0%", stopColor: "#FFFFFF", stopOpacity: "0.45" }),
954
+ /* @__PURE__ */ jsx("stop", { offset: "40%", stopColor: "#FFFFFF", stopOpacity: "0.1" }),
955
+ /* @__PURE__ */ jsx("stop", { offset: "100%", stopColor: "#000000", stopOpacity: "0.08" })
956
+ ] }),
957
+ /* @__PURE__ */ jsxs("linearGradient", { id: ids.surfaceGlare, x1: "0.1", y1: "0", x2: "0.85", y2: "1", children: [
958
+ /* @__PURE__ */ jsx("stop", { offset: "0%", stopColor: "#FFFFFF", stopOpacity: "0.12" }),
959
+ /* @__PURE__ */ jsx("stop", { offset: "25%", stopColor: "#FFFFFF", stopOpacity: "0.04" }),
960
+ /* @__PURE__ */ jsx("stop", { offset: "48%", stopColor: "#FFFFFF", stopOpacity: "0.005" }),
961
+ /* @__PURE__ */ jsx("stop", { offset: "70%", stopColor: "#FFFFFF", stopOpacity: "0" })
962
+ ] }),
963
+ /* @__PURE__ */ jsxs("linearGradient", { id: ids.screenReflection, x1: "0", y1: "0", x2: "0", y2: "1", children: [
964
+ /* @__PURE__ */ jsx("stop", { offset: "0%", stopColor: "#FFFFFF", stopOpacity: "0.15" }),
965
+ /* @__PURE__ */ jsx("stop", { offset: "100%", stopColor: "#FFFFFF", stopOpacity: "0" })
966
+ ] }),
967
+ /* @__PURE__ */ jsxs("filter", { id: ids.microGrain, x: "0%", y: "0%", width: "100%", height: "100%", children: [
968
+ /* @__PURE__ */ jsx(
969
+ "feTurbulence",
970
+ {
971
+ type: "fractalNoise",
972
+ baseFrequency: "0.8",
973
+ numOctaves: "2",
974
+ stitchTiles: "stitch",
975
+ result: "noise"
976
+ }
977
+ ),
978
+ /* @__PURE__ */ jsx(
979
+ "feColorMatrix",
980
+ {
981
+ type: "matrix",
982
+ values: "0 0 0 0 1\n 0 0 0 0 1\n 0 0 0 0 1\n 0.4 0 0 0 0"
983
+ }
984
+ )
985
+ ] })
986
+ ] });
987
+ }
988
+ function GlassBackdrop({ ids }) {
989
+ return /* @__PURE__ */ jsxs("g", { children: [
990
+ /* @__PURE__ */ jsx(
991
+ "rect",
992
+ {
993
+ "data-avatar-glass": true,
994
+ "data-avatar-enclosure": "",
995
+ x: BOX_FRAME.x,
996
+ y: BOX_FRAME.y,
997
+ width: BOX_FRAME.size,
998
+ height: BOX_FRAME.size,
999
+ rx: BOX_FRAME.radius,
1000
+ fill: `url(#${ids.backdrop})`,
1001
+ stroke: `url(#${ids.rim})`,
1002
+ strokeWidth: "2"
1003
+ }
1004
+ ),
1005
+ /* @__PURE__ */ jsx(
1006
+ "rect",
1007
+ {
1008
+ "data-avatar-glass": true,
1009
+ "data-avatar-enclosure-pane": "",
1010
+ x: BOX_FRAME.x + 3,
1011
+ y: BOX_FRAME.y + 3,
1012
+ width: BOX_FRAME.size - 6,
1013
+ height: BOX_FRAME.size - 6,
1014
+ rx: BOX_FRAME.radius - 3,
1015
+ fill: "none",
1016
+ stroke: `url(#${ids.innerBevel})`,
1017
+ strokeWidth: "1.2"
1018
+ }
1019
+ )
1020
+ ] });
1021
+ }
1022
+ function GlassBackground({ ids, color }) {
1023
+ const baseId = `${ids.backdrop}-base`;
1024
+ const glowId = `${ids.backdrop}-glow`;
1025
+ const glowTint = mixHexColor(color, 1, 0.55);
1026
+ return /* @__PURE__ */ jsxs("g", { children: [
1027
+ /* @__PURE__ */ jsxs("defs", { children: [
1028
+ /* @__PURE__ */ jsxs("linearGradient", { id: baseId, x1: "0", y1: "0", x2: "0", y2: "1", children: [
1029
+ /* @__PURE__ */ jsx("stop", { offset: "0%", stopColor: mixHexColor(color, 0, 0.34) }),
1030
+ /* @__PURE__ */ jsx("stop", { offset: "100%", stopColor: mixHexColor(color, 0, 0.54) })
1031
+ ] }),
1032
+ /* @__PURE__ */ jsxs(
1033
+ "linearGradient",
1034
+ {
1035
+ id: glowId,
1036
+ gradientUnits: "userSpaceOnUse",
1037
+ x1: "0",
1038
+ y1: "86",
1039
+ x2: "0",
1040
+ y2: "234",
1041
+ children: [
1042
+ /* @__PURE__ */ jsx("stop", { offset: "0%", stopColor: glowTint, stopOpacity: "0" }),
1043
+ /* @__PURE__ */ jsx("stop", { offset: "45%", stopColor: glowTint, stopOpacity: "0.07" }),
1044
+ /* @__PURE__ */ jsx("stop", { offset: "100%", stopColor: glowTint, stopOpacity: "0.15" })
1045
+ ]
1046
+ }
1047
+ )
1048
+ ] }),
1049
+ /* @__PURE__ */ jsx(
1050
+ "rect",
1051
+ {
1052
+ "data-avatar-glass": true,
1053
+ "data-avatar-enclosure-background": "",
1054
+ x: BOX_FRAME.x,
1055
+ y: BOX_FRAME.y,
1056
+ width: BOX_FRAME.size,
1057
+ height: BOX_FRAME.size,
1058
+ rx: BOX_FRAME.radius,
1059
+ opacity: "0.065",
1060
+ fill: `url(#${baseId})`
1061
+ }
1062
+ ),
1063
+ /* @__PURE__ */ jsx(
1064
+ "path",
1065
+ {
1066
+ "data-avatar-glass": true,
1067
+ "data-avatar-enclosure-glow": "",
1068
+ d: "M22 132C50 102 86 86 128 86C170 86 206 102 234 132V186C234 212.5 212.5 234 186 234H70C43.5 234 22 212.5 22 186Z",
1069
+ fill: `url(#${glowId})`
1070
+ }
1071
+ )
1072
+ ] });
1073
+ }
1074
+ function GlassOverlay({ ids }) {
1075
+ return /* @__PURE__ */ jsxs("g", { children: [
1076
+ /* @__PURE__ */ jsx(
1077
+ "path",
1078
+ {
1079
+ "data-avatar-glass": true,
1080
+ "data-avatar-enclosure-reflection": "",
1081
+ d: "M22 60C22 38 38 22 60 22H196C218 22 234 38 234 60C234 76 180 88 128 88C76 88 22 76 22 60Z",
1082
+ fill: `url(#${ids.screenReflection})`
1083
+ }
1084
+ ),
1085
+ /* @__PURE__ */ jsx(
1086
+ "path",
1087
+ {
1088
+ "data-avatar-glass": true,
1089
+ "data-avatar-enclosure-shine": "",
1090
+ d: "M22 22H140L234 160V234H180L22 76Z",
1091
+ fill: `url(#${ids.surfaceGlare})`
1092
+ }
1093
+ ),
1094
+ /* @__PURE__ */ jsx(
1095
+ "path",
1096
+ {
1097
+ "data-avatar-glass": true,
1098
+ "data-avatar-enclosure-glint": "",
1099
+ d: "M30 78C30 52 52 30 78 30",
1100
+ fill: "none",
1101
+ stroke: "#FFFFFF",
1102
+ strokeOpacity: "0.7",
1103
+ strokeWidth: "3",
1104
+ strokeLinecap: "round"
1105
+ }
1106
+ ),
1107
+ /* @__PURE__ */ jsx(
1108
+ "path",
1109
+ {
1110
+ "data-avatar-glass": true,
1111
+ d: "M86 30H112",
1112
+ fill: "none",
1113
+ stroke: "#FFFFFF",
1114
+ strokeOpacity: "0.35",
1115
+ strokeWidth: "1.8",
1116
+ strokeLinecap: "round"
1117
+ }
1118
+ ),
1119
+ /* @__PURE__ */ jsx(
1120
+ "rect",
1121
+ {
1122
+ "data-avatar-glass": true,
1123
+ "data-avatar-enclosure-grain": "",
1124
+ x: BOX_FRAME.x,
1125
+ y: BOX_FRAME.y,
1126
+ width: BOX_FRAME.size,
1127
+ height: BOX_FRAME.size,
1128
+ opacity: "0.12",
1129
+ filter: `url(#${ids.microGrain})`,
1130
+ style: { mixBlendMode: "screen" }
1131
+ }
1132
+ )
1133
+ ] });
1134
+ }
1135
+ var ORB_FRAME = { cx: 128, cy: 128, radius: 106 };
1136
+ var ORB_ENERGY = {
1137
+ paused: 0,
1138
+ idle: 0.28,
1139
+ attentive: 0.5,
1140
+ working: 0.7,
1141
+ responding: 0.95,
1142
+ waiting: 0.78
1143
+ };
1144
+ function mixHexColor2(hex, target, amount) {
1145
+ const digits = hex.replace("#", "");
1146
+ const full = digits.length === 3 ? digits.split("").map((digit) => digit + digit).join("") : digits;
1147
+ const value = Number.parseInt(full, 16);
1148
+ const channels = [value >> 16 & 255, value >> 8 & 255, value & 255];
1149
+ const mixed = channels.map(
1150
+ (channel) => Math.round(channel + (target * 255 - channel) * amount).toString(16).padStart(2, "0")
1151
+ );
1152
+ return `#${mixed.join("")}`;
1153
+ }
1154
+ function blendHexColors(first, second, amount) {
1155
+ const toChannels = (hex) => {
1156
+ const value = Number.parseInt(hex.replace("#", ""), 16);
1157
+ return [value >> 16 & 255, value >> 8 & 255, value & 255];
1158
+ };
1159
+ const from = toChannels(first);
1160
+ const to = toChannels(second);
1161
+ return `#${from.map(
1162
+ (channel, index) => Math.round(channel + (to[index] - channel) * amount).toString(16).padStart(2, "0")
1163
+ ).join("")}`;
1164
+ }
1165
+ function orbGradientIds(instanceId) {
1166
+ const prefix = `frontera-orb-${instanceId}`;
1167
+ return {
1168
+ rim: `${prefix}-rim`,
1169
+ specular: `${prefix}-specular`,
1170
+ sheen: `${prefix}-sheen`,
1171
+ diffusion: `${prefix}-diffusion`
1172
+ };
1173
+ }
1174
+ function sampleOrbPresence(state, time, reducedMotion = false) {
1175
+ const energy = ORB_ENERGY[state];
1176
+ const wave = reducedMotion ? 0 : 0.5 + 0.5 * Math.sin(time * Math.PI * 1.25);
1177
+ return {
1178
+ scale: 1,
1179
+ lightOpacity: 0.15 + energy * 0.18 + wave * 0.05,
1180
+ coreOpacity: 0.22 + energy * 0.18 + wave * 0.04,
1181
+ fieldOpacity: 0.2 + energy * 0.24 + wave * 0.08
1182
+ };
1183
+ }
1184
+ function OrbDefs({ ids }) {
1185
+ return /* @__PURE__ */ jsxs("defs", { children: [
1186
+ /* @__PURE__ */ jsxs("linearGradient", { id: ids.rim, x1: "0", y1: "0", x2: "1", y2: "1", children: [
1187
+ /* @__PURE__ */ jsx("stop", { offset: "0%", stopColor: "#FFFFFF", stopOpacity: "0.78" }),
1188
+ /* @__PURE__ */ jsx("stop", { offset: "30%", stopColor: "#FFFFFF", stopOpacity: "0.28" }),
1189
+ /* @__PURE__ */ jsx("stop", { offset: "72%", stopColor: "#FFFFFF", stopOpacity: "0.05" }),
1190
+ /* @__PURE__ */ jsx("stop", { offset: "100%", stopColor: "#000000", stopOpacity: "0.24" })
1191
+ ] }),
1192
+ /* @__PURE__ */ jsxs("radialGradient", { id: ids.specular, cx: "32%", cy: "24%", r: "72%", children: [
1193
+ /* @__PURE__ */ jsx("stop", { offset: "0%", stopColor: "#FFFFFF", stopOpacity: "0.68" }),
1194
+ /* @__PURE__ */ jsx("stop", { offset: "38%", stopColor: "#FFFFFF", stopOpacity: "0.12" }),
1195
+ /* @__PURE__ */ jsx("stop", { offset: "100%", stopColor: "#FFFFFF", stopOpacity: "0" })
1196
+ ] }),
1197
+ /* @__PURE__ */ jsxs("linearGradient", { id: ids.sheen, x1: "0.18", y1: "0", x2: "0.82", y2: "1", children: [
1198
+ /* @__PURE__ */ jsx("stop", { offset: "0%", stopColor: "#FFFFFF", stopOpacity: "0.22" }),
1199
+ /* @__PURE__ */ jsx("stop", { offset: "42%", stopColor: "#FFFFFF", stopOpacity: "0.035" }),
1200
+ /* @__PURE__ */ jsx("stop", { offset: "100%", stopColor: "#FFFFFF", stopOpacity: "0" })
1201
+ ] }),
1202
+ /* @__PURE__ */ jsx("filter", { id: ids.diffusion, x: "-28%", y: "-28%", width: "156%", height: "156%", children: /* @__PURE__ */ jsx("feGaussianBlur", { stdDeviation: "15" }) })
1203
+ ] });
1204
+ }
1205
+ function OrbBackdrop({
1206
+ ids,
1207
+ color,
1208
+ state,
1209
+ time,
1210
+ reducedMotion
1211
+ }) {
1212
+ const bodyId = `${ids.rim}-body`;
1213
+ const coreId = `${ids.rim}-core`;
1214
+ const presence = sampleOrbPresence(state, time, reducedMotion);
1215
+ const light = mixHexColor2(color, 1, 0.42);
1216
+ const base = mixHexColor2(color, 0, 0.1);
1217
+ const edge = mixHexColor2(color, 0, 0.5);
1218
+ const cool = blendHexColors(color, "#645CFF", 0.42);
1219
+ const warm = blendHexColors(color, "#FF8A5C", 0.35);
1220
+ const aura = blendHexColors(color, "#67DBFF", 0.28);
1221
+ const clipId = `${ids.rim}-clip`;
1222
+ return /* @__PURE__ */ jsxs(
1223
+ "g",
1224
+ {
1225
+ "data-avatar-orb": "",
1226
+ transform: `translate(128 128) scale(${presence.scale}) translate(-128 -128)`,
1227
+ children: [
1228
+ /* @__PURE__ */ jsxs("defs", { children: [
1229
+ /* @__PURE__ */ jsx("clipPath", { id: clipId, children: /* @__PURE__ */ jsx("circle", { cx: ORB_FRAME.cx, cy: ORB_FRAME.cy, r: ORB_FRAME.radius - 1 }) }),
1230
+ /* @__PURE__ */ jsxs("radialGradient", { id: bodyId, cx: "31%", cy: "24%", r: "84%", children: [
1231
+ /* @__PURE__ */ jsx("stop", { offset: "0%", stopColor: light }),
1232
+ /* @__PURE__ */ jsx("stop", { offset: "34%", stopColor: base }),
1233
+ /* @__PURE__ */ jsx("stop", { offset: "76%", stopColor: mixHexColor2(color, 0, 0.25) }),
1234
+ /* @__PURE__ */ jsx("stop", { offset: "100%", stopColor: edge })
1235
+ ] }),
1236
+ /* @__PURE__ */ jsxs("radialGradient", { id: coreId, cx: "50%", cy: "46%", r: "58%", children: [
1237
+ /* @__PURE__ */ jsx("stop", { offset: "0%", stopColor: blendHexColors(light, aura, 0.4), stopOpacity: "0.92" }),
1238
+ /* @__PURE__ */ jsx("stop", { offset: "54%", stopColor: light, stopOpacity: "0.26" }),
1239
+ /* @__PURE__ */ jsx("stop", { offset: "100%", stopColor: light, stopOpacity: "0" })
1240
+ ] })
1241
+ ] }),
1242
+ /* @__PURE__ */ jsx(
1243
+ "circle",
1244
+ {
1245
+ cx: ORB_FRAME.cx,
1246
+ cy: ORB_FRAME.cy,
1247
+ r: ORB_FRAME.radius,
1248
+ fill: `url(#${bodyId})`
1249
+ }
1250
+ ),
1251
+ /* @__PURE__ */ jsxs(
1252
+ "g",
1253
+ {
1254
+ "data-avatar-orb-field": "",
1255
+ clipPath: `url(#${clipId})`,
1256
+ filter: `url(#${ids.diffusion})`,
1257
+ opacity: presence.fieldOpacity,
1258
+ children: [
1259
+ /* @__PURE__ */ jsx("ellipse", { cx: "84", cy: "92", rx: "48", ry: "42", fill: aura }),
1260
+ /* @__PURE__ */ jsx("ellipse", { cx: "168", cy: "126", rx: "62", ry: "48", fill: warm }),
1261
+ /* @__PURE__ */ jsx("ellipse", { cx: "126", cy: "184", rx: "58", ry: "42", fill: cool })
1262
+ ]
1263
+ }
1264
+ ),
1265
+ /* @__PURE__ */ jsx(
1266
+ "circle",
1267
+ {
1268
+ "data-avatar-orb-core": "",
1269
+ cx: ORB_FRAME.cx,
1270
+ cy: ORB_FRAME.cy + 8,
1271
+ r: ORB_FRAME.radius * 0.78,
1272
+ fill: `url(#${coreId})`,
1273
+ opacity: presence.coreOpacity
1274
+ }
1275
+ ),
1276
+ /* @__PURE__ */ jsx(
1277
+ "circle",
1278
+ {
1279
+ "data-avatar-orb-light": "",
1280
+ cx: ORB_FRAME.cx,
1281
+ cy: ORB_FRAME.cy,
1282
+ r: ORB_FRAME.radius - 6,
1283
+ fill: `url(#${ids.specular})`,
1284
+ opacity: presence.lightOpacity
1285
+ }
1286
+ )
1287
+ ]
1288
+ }
1289
+ );
1290
+ }
1291
+ var ORB_DIAMETER = 212;
1292
+ var VERTEX_SHADER = `
1293
+ attribute vec2 a_position;
1294
+
1295
+ void main() {
1296
+ gl_Position = vec4(a_position, 0.0, 1.0);
1297
+ }
1298
+ `;
1299
+ var FRAGMENT_SHADER = `
1300
+ precision highp float;
1301
+
1302
+ uniform vec2 u_resolution;
1303
+ uniform float u_time;
1304
+ uniform float u_activity;
1305
+ uniform vec3 u_primary;
1306
+
1307
+ float hash(vec2 p) {
1308
+ p = fract(p * vec2(123.34, 456.21));
1309
+ p += dot(p, p + 45.32);
1310
+ return fract(p.x * p.y);
1311
+ }
1312
+
1313
+ float noise(vec2 p) {
1314
+ vec2 i = floor(p);
1315
+ vec2 f = fract(p);
1316
+ vec2 u = f * f * (3.0 - 2.0 * f);
1317
+ return mix(
1318
+ mix(hash(i), hash(i + vec2(1.0, 0.0)), u.x),
1319
+ mix(hash(i + vec2(0.0, 1.0)), hash(i + vec2(1.0, 1.0)), u.x),
1320
+ u.y
1321
+ );
1322
+ }
1323
+
1324
+ float fbm(vec2 p) {
1325
+ float value = 0.0;
1326
+ float amplitude = 0.52;
1327
+ mat2 rotation = mat2(0.80, 0.60, -0.60, 0.80);
1328
+ for (int octave = 0; octave < 5; octave++) {
1329
+ value += amplitude * noise(p);
1330
+ p = rotation * p * 1.92 + vec2(9.7, 4.3);
1331
+ amplitude *= 0.5;
1332
+ }
1333
+ return value;
1334
+ }
1335
+
1336
+ void main() {
1337
+ vec2 uv = gl_FragCoord.xy / u_resolution;
1338
+ vec2 centered = uv - 0.5;
1339
+ vec2 p = centered * 2.0;
1340
+ float t = u_time;
1341
+ vec2 warp = vec2(
1342
+ fbm(p * 1.02 + vec2(t * 0.34, -t * 0.24)),
1343
+ fbm(p * 1.08 + vec2(-t * 0.27, t * 0.32) + vec2(6.7, 2.9))
1344
+ );
1345
+ vec2 curl = vec2(
1346
+ sin(p.y * 2.4 + t * 0.68 + warp.y * 3.2),
1347
+ cos(p.x * 2.1 - t * 0.61 + warp.x * 3.0)
1348
+ );
1349
+ vec2 warped = p +
1350
+ (warp - 0.5) * (1.18 + u_activity * 0.38) +
1351
+ curl * (0.035 + u_activity * 0.07);
1352
+ float broad = fbm(warped * 0.92 + vec2(t * 0.14, -t * 0.18));
1353
+ float folded = fbm(warped * 1.66 + vec2(-t * 0.23, t * 0.19) + 5.2);
1354
+ float field = mix(broad, folded, 0.3 + u_activity * 0.14);
1355
+
1356
+ float horizon = 0.46 +
1357
+ 0.08 * sin((uv.x + warp.x * 0.2) * 5.4 + t * 0.42) +
1358
+ 0.16 * (broad - 0.5);
1359
+ float upper = smoothstep(horizon - 0.12, horizon + 0.08, uv.y);
1360
+ float band = exp(-pow((uv.y - horizon) * (5.2 + u_activity * 0.8), 2.0));
1361
+ float cloud = smoothstep(0.24, 0.79, field);
1362
+
1363
+ vec3 white = vec3(0.98, 0.985, 1.0);
1364
+ vec3 deep = mix(vec3(0.36, 0.39, 0.985), u_primary, 0.84);
1365
+ vec3 upperTint = mix(vec3(0.48, 0.56, 0.985), mix(u_primary, white, 0.34), 0.80);
1366
+ vec3 lowerTint = mix(vec3(0.72, 0.78, 0.975), mix(u_primary, white, 0.78), 0.78);
1367
+ vec3 color = mix(lowerTint, upperTint, upper);
1368
+ float upperDepth = upper * (0.14 + smoothstep(0.42, 0.78, folded) * 0.5);
1369
+ color = mix(color, deep, upperDepth);
1370
+
1371
+ float milkAmount = clamp(band * (0.42 + cloud * 0.62), 0.0, 0.88);
1372
+ color = mix(color, white, milkAmount);
1373
+ float lowerMist = (1.0 - upper) * smoothstep(0.58, 0.9, broad) * 0.18;
1374
+ color = mix(color, white, lowerMist);
1375
+ float grain = (noise(gl_FragCoord.xy * 0.64) - 0.5) / 255.0;
1376
+ gl_FragColor = vec4(color + grain, 1.0);
1377
+ }
1378
+ `;
1379
+ function toOrbCloudState(state) {
1380
+ if (state === "attentive") return "listening";
1381
+ if (state === "working" || state === "responding") return "speaking";
1382
+ if (state === "waiting") return "thinking";
1383
+ return "idle";
1384
+ }
1385
+ function sampleOrbCloudMotion(state) {
1386
+ if (state === "attentive") return { activity: 0.46, speed: 0.98 };
1387
+ if (state === "working") return { activity: 0.86, speed: 2.72 };
1388
+ if (state === "responding") return { activity: 0.62, speed: 1.4 };
1389
+ if (state === "waiting") return { activity: 0.35, speed: 0.54 };
1390
+ return { activity: 0.12, speed: 0.2 };
1391
+ }
1392
+ function parseHexColor(color) {
1393
+ const source = color.replace("#", "");
1394
+ const hex = source.length === 3 ? source.split("").map((channel) => channel + channel).join("") : source;
1395
+ if (!/^[0-9a-f]{6}$/i.test(hex)) return [0.36, 0.39, 0.985];
1396
+ const value = Number.parseInt(hex, 16);
1397
+ return [(value >> 16) / 255, (value >> 8 & 255) / 255, (value & 255) / 255];
1398
+ }
1399
+ function compileShader(gl, type, source) {
1400
+ const shader = gl.createShader(type);
1401
+ if (!shader) return void 0;
1402
+ gl.shaderSource(shader, source);
1403
+ gl.compileShader(shader);
1404
+ if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
1405
+ gl.deleteShader(shader);
1406
+ return void 0;
1407
+ }
1408
+ return shader;
1409
+ }
1410
+ function createCloudRenderer(canvas, color) {
1411
+ let gl;
1412
+ try {
1413
+ gl = canvas.getContext("webgl", {
1414
+ alpha: false,
1415
+ antialias: true
1416
+ });
1417
+ } catch {
1418
+ return void 0;
1419
+ }
1420
+ if (!gl) return void 0;
1421
+ const vertexShader = compileShader(gl, gl.VERTEX_SHADER, VERTEX_SHADER);
1422
+ const fragmentShader = compileShader(gl, gl.FRAGMENT_SHADER, FRAGMENT_SHADER);
1423
+ if (!vertexShader || !fragmentShader) {
1424
+ if (vertexShader) gl.deleteShader(vertexShader);
1425
+ if (fragmentShader) gl.deleteShader(fragmentShader);
1426
+ return void 0;
1427
+ }
1428
+ const program = gl.createProgram();
1429
+ const buffer = gl.createBuffer();
1430
+ if (!program || !buffer) {
1431
+ if (program) gl.deleteProgram(program);
1432
+ if (buffer) gl.deleteBuffer(buffer);
1433
+ gl.deleteShader(vertexShader);
1434
+ gl.deleteShader(fragmentShader);
1435
+ return void 0;
1436
+ }
1437
+ gl.attachShader(program, vertexShader);
1438
+ gl.attachShader(program, fragmentShader);
1439
+ gl.linkProgram(program);
1440
+ if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
1441
+ gl.deleteProgram(program);
1442
+ gl.deleteBuffer(buffer);
1443
+ gl.deleteShader(vertexShader);
1444
+ gl.deleteShader(fragmentShader);
1445
+ return void 0;
1446
+ }
1447
+ const position = gl.getAttribLocation(program, "a_position");
1448
+ const resolution = gl.getUniformLocation(program, "u_resolution");
1449
+ const time = gl.getUniformLocation(program, "u_time");
1450
+ const activity = gl.getUniformLocation(program, "u_activity");
1451
+ const primary = gl.getUniformLocation(program, "u_primary");
1452
+ if (position < 0 || !resolution || !time || !activity || !primary) {
1453
+ gl.deleteProgram(program);
1454
+ gl.deleteBuffer(buffer);
1455
+ gl.deleteShader(vertexShader);
1456
+ gl.deleteShader(fragmentShader);
1457
+ return void 0;
1458
+ }
1459
+ const pixelRatio = Math.min(window.devicePixelRatio || 1, 2);
1460
+ const pixelSize = Math.max(1, Math.round(ORB_DIAMETER * pixelRatio));
1461
+ canvas.width = pixelSize;
1462
+ canvas.height = pixelSize;
1463
+ gl.viewport(0, 0, pixelSize, pixelSize);
1464
+ gl.useProgram(program);
1465
+ gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
1466
+ gl.bufferData(
1467
+ gl.ARRAY_BUFFER,
1468
+ new Float32Array([-1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1]),
1469
+ gl.STATIC_DRAW
1470
+ );
1471
+ gl.enableVertexAttribArray(position);
1472
+ gl.vertexAttribPointer(position, 2, gl.FLOAT, false, 0, 0);
1473
+ gl.uniform2f(resolution, pixelSize, pixelSize);
1474
+ gl.uniform3fv(primary, parseHexColor(color));
1475
+ return {
1476
+ draw(flowTime, flowActivity) {
1477
+ gl.uniform1f(time, flowTime);
1478
+ gl.uniform1f(activity, flowActivity);
1479
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
1480
+ },
1481
+ destroy() {
1482
+ gl.deleteProgram(program);
1483
+ gl.deleteBuffer(buffer);
1484
+ gl.deleteShader(vertexShader);
1485
+ gl.deleteShader(fragmentShader);
1486
+ gl.getExtension("WEBGL_lose_context")?.loseContext();
1487
+ }
1488
+ };
1489
+ }
1490
+ function cloudFallback(color) {
1491
+ return `radial-gradient(circle at 50% 47%, rgba(255,255,255,0.92) 0%, ${color} 42%, rgba(80, 88, 220, 0.9) 100%)`;
1492
+ }
1493
+ function paintCloudSnapshot(canvas, color, state) {
1494
+ const source = document.createElement("canvas");
1495
+ const renderer = createCloudRenderer(source, color);
1496
+ if (!renderer) return false;
1497
+ renderer.draw(0, sampleOrbCloudMotion(state).activity);
1498
+ canvas.width = source.width;
1499
+ canvas.height = source.height;
1500
+ let context;
1501
+ try {
1502
+ context = canvas.getContext("2d");
1503
+ } catch {
1504
+ renderer.destroy();
1505
+ return false;
1506
+ }
1507
+ if (!context) {
1508
+ renderer.destroy();
1509
+ return false;
1510
+ }
1511
+ context.drawImage(source, 0, 0, canvas.width, canvas.height);
1512
+ renderer.destroy();
1513
+ return true;
1514
+ }
1515
+ function OrbCloud({ color, playing, reducedMotion, state }) {
1516
+ const canvasRef = useRef(null);
1517
+ const stateRef = useRef(state);
1518
+ const rendererKey = `${color}:${playing}:${reducedMotion}`;
1519
+ const [unavailableRendererKey, setUnavailableRendererKey] = useState(null);
1520
+ const webglUnavailable = unavailableRendererKey === rendererKey;
1521
+ const continuouslyAnimated = playing && !reducedMotion && !webglUnavailable;
1522
+ const snapshotState = continuouslyAnimated ? null : state;
1523
+ useLayoutEffect(() => {
1524
+ stateRef.current = state;
1525
+ }, [state]);
1526
+ useEffect(() => {
1527
+ const canvas = canvasRef.current;
1528
+ if (!canvas) return;
1529
+ canvas.style.background = cloudFallback(color);
1530
+ if (!continuouslyAnimated) {
1531
+ paintCloudSnapshot(canvas, color, snapshotState ?? stateRef.current);
1532
+ return;
1533
+ }
1534
+ const renderer = createCloudRenderer(canvas, color);
1535
+ if (!renderer) {
1536
+ setUnavailableRendererKey(rendererKey);
1537
+ return;
1538
+ }
1539
+ const handleContextLost = (event) => {
1540
+ event.preventDefault();
1541
+ setUnavailableRendererKey(rendererKey);
1542
+ };
1543
+ canvas.addEventListener("webglcontextlost", handleContextLost);
1544
+ let frame = 0;
1545
+ let previousTime = performance.now();
1546
+ let flowTime = 0;
1547
+ const render = (now) => {
1548
+ const deltaSeconds = Math.min((now - previousTime) / 1e3, 0.05);
1549
+ previousTime = now;
1550
+ const nextState = stateRef.current;
1551
+ const motion = sampleOrbCloudMotion(nextState);
1552
+ if (!reducedMotion) flowTime += deltaSeconds * motion.speed;
1553
+ renderer.draw(flowTime, motion.activity);
1554
+ frame = requestAnimationFrame(render);
1555
+ };
1556
+ render(previousTime);
1557
+ return () => {
1558
+ cancelAnimationFrame(frame);
1559
+ canvas.removeEventListener("webglcontextlost", handleContextLost);
1560
+ renderer.destroy();
1561
+ };
1562
+ }, [color, continuouslyAnimated, rendererKey, snapshotState]);
1563
+ return /* @__PURE__ */ jsx(
1564
+ "foreignObject",
1565
+ {
1566
+ x: "0",
1567
+ y: "0",
1568
+ width: "256",
1569
+ height: "256",
1570
+ "data-avatar-orb-cloud": "",
1571
+ "data-avatar-orb-cloud-state": state,
1572
+ "data-avatar-orb-cloud-theme": toOrbCloudState(state),
1573
+ style: { pointerEvents: "none" },
1574
+ children: /* @__PURE__ */ jsx(
1575
+ "div",
1576
+ {
1577
+ style: {
1578
+ alignItems: "center",
1579
+ display: "flex",
1580
+ height: 256,
1581
+ justifyContent: "center",
1582
+ width: 256
1583
+ },
1584
+ children: /* @__PURE__ */ jsx(
1585
+ "canvas",
1586
+ {
1587
+ ref: canvasRef,
1588
+ "aria-hidden": "true",
1589
+ "data-avatar-orb-cloud-alpha": "opaque",
1590
+ "data-avatar-orb-cloud-canvas": "",
1591
+ "data-avatar-orb-cloud-renderer": continuouslyAnimated ? "animated-webgl" : "snapshot-2d",
1592
+ style: {
1593
+ borderRadius: "50%",
1594
+ clipPath: "circle(50% at 50% 50%)",
1595
+ display: "block",
1596
+ height: ORB_DIAMETER,
1597
+ width: ORB_DIAMETER
1598
+ }
1599
+ },
1600
+ continuouslyAnimated ? "animated-webgl" : "snapshot-2d"
1601
+ )
1602
+ }
1603
+ )
1604
+ }
1605
+ );
1606
+ }
1607
+
1608
+ // src/vendor/ui/agent-avatar/lab/timeline.ts
1609
+ var STATE_TRANSITION_DURATION = {
1610
+ idle: 0.45,
1611
+ attentive: 0.55,
1612
+ working: 0.4,
1613
+ responding: 0.3,
1614
+ waiting: 0.5
1615
+ };
1616
+ var DEFAULT_SEQUENCE = [
1617
+ { state: "idle", duration: 2.4 },
1618
+ { state: "attentive", duration: 1.8 },
1619
+ { state: "working", duration: 2.6 },
1620
+ { state: "responding", duration: 1.6 },
1621
+ { state: "waiting", duration: 2.4 }
1622
+ ];
1623
+ function sequenceDuration(sequence) {
1624
+ return sequence.reduce((total, step) => total + step.duration, 0);
1625
+ }
1626
+ function sampleSequence(sequence, time, speed = 1) {
1627
+ const safeSequence = sequence.length > 0 ? sequence : DEFAULT_SEQUENCE;
1628
+ const total = sequenceDuration(safeSequence);
1629
+ const scaled = time * Math.max(0, speed);
1630
+ const wrapped = total > 0 ? (scaled % total + total) % total : 0;
1631
+ let offset = 0;
1632
+ for (let index = 0; index < safeSequence.length; index += 1) {
1633
+ const step = safeSequence[index];
1634
+ const end = offset + step.duration;
1635
+ if (wrapped < end || index === safeSequence.length - 1) {
1636
+ const elapsed = wrapped - offset;
1637
+ const previous = safeSequence[(index - 1 + safeSequence.length) % safeSequence.length];
1638
+ const transitionWindow = Math.min(STATE_TRANSITION_DURATION[step.state], step.duration * 0.4);
1639
+ return {
1640
+ index,
1641
+ state: step.state,
1642
+ previousState: previous.state,
1643
+ elapsed,
1644
+ progress: clamp(elapsed / step.duration),
1645
+ transition: easings.easeInOutCubic(clamp(elapsed / transitionWindow))
1646
+ };
1647
+ }
1648
+ offset = end;
1649
+ }
1650
+ const fallback = safeSequence[0];
1651
+ return {
1652
+ index: 0,
1653
+ state: fallback.state,
1654
+ previousState: safeSequence[safeSequence.length - 1].state,
1655
+ elapsed: 0,
1656
+ progress: 0,
1657
+ transition: 0
1658
+ };
1659
+ }
1660
+ function useAnimationClock(active, resetKey = 0) {
1661
+ const [time, setTime] = useState(0);
1662
+ const accumulated = useRef(0);
1663
+ const latest = useRef(0);
1664
+ const startedAt = useRef(null);
1665
+ useEffect(() => {
1666
+ accumulated.current = 0;
1667
+ latest.current = 0;
1668
+ startedAt.current = null;
1669
+ setTime(0);
1670
+ }, [resetKey]);
1671
+ useEffect(() => {
1672
+ if (!active) {
1673
+ startedAt.current = null;
1674
+ return;
1675
+ }
1676
+ let frame = 0;
1677
+ const tick = (now) => {
1678
+ if (document.visibilityState === "hidden") {
1679
+ startedAt.current = now;
1680
+ } else {
1681
+ if (startedAt.current === null) startedAt.current = now;
1682
+ const elapsed = (now - startedAt.current) / 1e3;
1683
+ latest.current = accumulated.current + elapsed;
1684
+ setTime(latest.current);
1685
+ }
1686
+ frame = requestAnimationFrame(tick);
1687
+ };
1688
+ frame = requestAnimationFrame(tick);
1689
+ return () => {
1690
+ cancelAnimationFrame(frame);
1691
+ accumulated.current = latest.current;
1692
+ startedAt.current = null;
1693
+ };
1694
+ }, [active]);
1695
+ return time;
1696
+ }
1697
+ function useReducedMotion(force) {
1698
+ const [systemPrefersReducedMotion, setSystemPrefersReducedMotion] = useState(
1699
+ () => typeof window !== "undefined" && typeof window.matchMedia === "function" ? window.matchMedia("(prefers-reduced-motion: reduce)").matches : false
1700
+ );
1701
+ useEffect(() => {
1702
+ if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
1703
+ const media = window.matchMedia("(prefers-reduced-motion: reduce)");
1704
+ const update = () => setSystemPrefersReducedMotion(media.matches);
1705
+ update();
1706
+ media.addEventListener?.("change", update);
1707
+ return () => media.removeEventListener?.("change", update);
1708
+ }, []);
1709
+ return force ?? systemPrefersReducedMotion;
1710
+ }
1711
+ var IDENTITY_MORPH_DURATION_SECONDS = 0.18;
1712
+ var BOX_CHARACTER_SCALE = 0.82;
1713
+ function sampleBoxCharacterOffset(state, time) {
1714
+ if (state === "responding") return -10 + Math.sin(time * Math.PI * 2.4) * 3;
1715
+ if (state === "attentive") return 2 + Math.sin(time * Math.PI * 1.8) * 2;
1716
+ if (state === "working") return 15 + Math.sin(time * Math.PI * 2.2) * 8;
1717
+ if (state === "waiting") return 44 + Math.sin(time * Math.PI * 1.1) * 2;
1718
+ if (state === "paused") return 12;
1719
+ return 12 + Math.sin(time * Math.PI * 0.65) * 2;
1720
+ }
1721
+ function sampleBoxCharacterSway(state, time) {
1722
+ if (state === "waiting") return Math.sin(time * Math.PI * 0.9) * 9;
1723
+ return 0;
1724
+ }
1725
+ function sampleBoxCharacterTilt(state, time) {
1726
+ if (state === "waiting") return Math.sin(time * Math.PI * 0.9) * 2.4;
1727
+ return 0;
1728
+ }
1729
+ function interpolateFace(from, to, progress) {
1730
+ return {
1731
+ x: lerp(from.x, to.x, progress),
1732
+ y: lerp(from.y, to.y, progress),
1733
+ width: lerp(from.width, to.width, progress),
1734
+ height: lerp(from.height, to.height, progress),
1735
+ radius: lerp(from.radius, to.radius, progress)
1736
+ };
1737
+ }
1738
+ var Avatar = forwardRef(function Avatar2({
1739
+ identity,
1740
+ state,
1741
+ sequence,
1742
+ playing = true,
1743
+ speed = 1,
1744
+ followPointer = false,
1745
+ reducedMotion: forceReducedMotion,
1746
+ frozenAt,
1747
+ playbackKey = 0,
1748
+ size = "100%",
1749
+ motionKey = "frontera",
1750
+ label = "Frontera agent avatar",
1751
+ className,
1752
+ style,
1753
+ testId
1754
+ }, forwardedRef) {
1755
+ const reducedMotion = useReducedMotion(forceReducedMotion);
1756
+ const clock = useAnimationClock(playing && !reducedMotion && frozenAt === void 0, playbackKey);
1757
+ const time = reducedMotion ? 0 : frozenAt ?? clock;
1758
+ const [pointer, setPointer] = useState({ x: 0, y: 0, active: false });
1759
+ const instanceId = useId().replace(/:/g, "");
1760
+ const clipId = `frontera-face-${instanceId}`;
1761
+ const boxClipId = `frontera-box-${instanceId}`;
1762
+ const glassIds = glassGradientIds(instanceId);
1763
+ const orbIds = orbGradientIds(instanceId);
1764
+ const currentShape = AVATAR_SHAPE_BY_ID.get(identity.shape) ?? AVATAR_SHAPE_BY_ID.get("squircle");
1765
+ const morph = useRef({
1766
+ id: currentShape.id,
1767
+ resetKey: playbackKey,
1768
+ fromProfile: currentShape.radii,
1769
+ toProfile: currentShape.radii,
1770
+ fromFace: currentShape.face,
1771
+ toFace: currentShape.face,
1772
+ start: 0
1773
+ });
1774
+ if (morph.current.resetKey !== playbackKey) {
1775
+ morph.current = {
1776
+ id: currentShape.id,
1777
+ resetKey: playbackKey,
1778
+ fromProfile: currentShape.radii,
1779
+ toProfile: currentShape.radii,
1780
+ fromFace: currentShape.face,
1781
+ toFace: currentShape.face,
1782
+ start: time - IDENTITY_MORPH_DURATION_SECONDS
1783
+ };
1784
+ } else if (morph.current.id !== currentShape.id) {
1785
+ const previousProgress = playing ? easings.easeOutQuint(clamp((time - morph.current.start) / IDENTITY_MORPH_DURATION_SECONDS)) : 1;
1786
+ morph.current = {
1787
+ id: currentShape.id,
1788
+ resetKey: playbackKey,
1789
+ fromProfile: blendProfiles(morph.current.fromProfile, morph.current.toProfile, previousProgress),
1790
+ toProfile: currentShape.radii,
1791
+ fromFace: interpolateFace(morph.current.fromFace, morph.current.toFace, previousProgress),
1792
+ toFace: currentShape.face,
1793
+ start: time
1794
+ };
1795
+ }
1796
+ const morphProgress = playing ? easings.easeOutQuint(clamp((time - morph.current.start) / IDENTITY_MORPH_DURATION_SECONDS)) : 1;
1797
+ const profile = blendProfiles(morph.current.fromProfile, morph.current.toProfile, morphProgress);
1798
+ const face = interpolateFace(morph.current.fromFace, morph.current.toFace, morphProgress);
1799
+ const sequenceSample = sequence && !state ? sampleSequence(sequence, time, speed) : null;
1800
+ const resolvedState = state ?? sequenceSample?.state ?? "idle";
1801
+ const effectiveState = playing && !reducedMotion ? resolvedState : state === "paused" ? "paused" : resolvedState;
1802
+ const sequenceTime = sequence && !state ? time * Math.max(0, speed) : time;
1803
+ const stateTransition = reducedMotion ? 1 : sequenceSample?.transition ?? 1;
1804
+ const previousSequenceState = reducedMotion ? effectiveState : sequenceSample?.previousState ?? effectiveState;
1805
+ const frame = useMemo(
1806
+ () => sampleAvatarFrame({
1807
+ shape: identity.shape,
1808
+ state: reducedMotion ? "paused" : effectiveState,
1809
+ previousState: previousSequenceState,
1810
+ transition: stateTransition,
1811
+ time: sequenceTime,
1812
+ seed: motionKey,
1813
+ gaze: followPointer ? pointer : void 0,
1814
+ profile,
1815
+ face,
1816
+ expression: identity.expression,
1817
+ eyeSize: identity.eyeSize}),
1818
+ [
1819
+ effectiveState,
1820
+ followPointer,
1821
+ identity.shape,
1822
+ identity.expression,
1823
+ identity.eyeSize,
1824
+ morphProgress,
1825
+ playing,
1826
+ pointer,
1827
+ profile,
1828
+ reducedMotion,
1829
+ previousSequenceState,
1830
+ face,
1831
+ motionKey,
1832
+ sequence,
1833
+ sequenceTime,
1834
+ speed,
1835
+ stateTransition,
1836
+ state,
1837
+ time
1838
+ ]
1839
+ );
1840
+ const onPointerMove = (event) => {
1841
+ if (!followPointer || reducedMotion) return;
1842
+ const bounds = event.currentTarget.getBoundingClientRect();
1843
+ if (bounds.width <= 0 || bounds.height <= 0) return;
1844
+ setPointer({
1845
+ x: (event.clientX - bounds.left) / bounds.width * 2 - 1,
1846
+ y: (event.clientY - bounds.top) / bounds.height * 2 - 1,
1847
+ active: true
1848
+ });
1849
+ };
1850
+ const transform = [
1851
+ `translate(${frame.body.translateX} ${frame.body.translateY})`,
1852
+ "translate(128 128)",
1853
+ `rotate(${frame.body.rotation * 180 / Math.PI})`,
1854
+ `scale(${frame.body.scale})`,
1855
+ "translate(-128 -128)"
1856
+ ].join(" ");
1857
+ const faceColors = resolveFaceColors(identity.color, identity.faceTone);
1858
+ const isOpenFace = currentShape.faceStyle === "open";
1859
+ const showsFacePlate = !isOpenFace && identity.face !== "none";
1860
+ const eyeColor = isOpenFace ? resolveOpenEyeColor(identity.color) : showsFacePlate ? faceColors.eyes : resolveEyeColorOnBody(identity.color);
1861
+ const eyeGlint = eyeColor === "#202228" ? "#F7F3E8" : "#202228";
1862
+ const opticalScale = currentShape.opticalScale ?? 1;
1863
+ const opticalTransform = `translate(128 128) scale(${opticalScale}) translate(-128 -128)`;
1864
+ const isOrbForm = currentShape.id === "orb";
1865
+ const presentation = isOrbForm ? "free" : identity.presentation;
1866
+ const isBox = presentation === "box";
1867
+ const boxOffset = lerp(
1868
+ sampleBoxCharacterOffset(previousSequenceState, sequenceTime),
1869
+ sampleBoxCharacterOffset(effectiveState, sequenceTime),
1870
+ stateTransition
1871
+ );
1872
+ const boxSway = lerp(
1873
+ sampleBoxCharacterSway(previousSequenceState, sequenceTime),
1874
+ sampleBoxCharacterSway(effectiveState, sequenceTime),
1875
+ stateTransition
1876
+ );
1877
+ const boxTilt = lerp(
1878
+ sampleBoxCharacterTilt(previousSequenceState, sequenceTime),
1879
+ sampleBoxCharacterTilt(effectiveState, sequenceTime),
1880
+ stateTransition
1881
+ );
1882
+ const presentationTransform = isBox && !isOrbForm ? `translate(128 128) translate(${boxSway} ${boxOffset}) rotate(${boxTilt}) scale(${BOX_CHARACTER_SCALE}) translate(-128 -128)` : void 0;
1883
+ return /* @__PURE__ */ jsxs(
1884
+ "svg",
1885
+ {
1886
+ ref: forwardedRef,
1887
+ viewBox: "0 0 256 256",
1888
+ width: size,
1889
+ height: size,
1890
+ role: "img",
1891
+ "aria-label": label,
1892
+ className,
1893
+ style,
1894
+ "data-avatar-root": "",
1895
+ "data-avatar-state": effectiveState,
1896
+ "data-avatar-presentation": presentation,
1897
+ "data-testid": testId,
1898
+ onPointerMove,
1899
+ onPointerLeave: () => setPointer({ x: 0, y: 0, active: false }),
1900
+ children: [
1901
+ /* @__PURE__ */ jsxs("defs", { children: [
1902
+ isBox && /* @__PURE__ */ jsx(GlassDefs, { ids: glassIds }),
1903
+ isOrbForm && /* @__PURE__ */ jsx(OrbDefs, { ids: orbIds }),
1904
+ isBox && /* @__PURE__ */ jsx("clipPath", { id: boxClipId, children: /* @__PURE__ */ jsx(
1905
+ "rect",
1906
+ {
1907
+ x: BOX_FRAME.x,
1908
+ y: BOX_FRAME.y,
1909
+ width: BOX_FRAME.size,
1910
+ height: BOX_FRAME.size,
1911
+ rx: BOX_FRAME.radius
1912
+ }
1913
+ ) })
1914
+ ] }),
1915
+ isBox && /* @__PURE__ */ jsx(GlassBackground, { ids: glassIds, color: identity.color }),
1916
+ isBox && /* @__PURE__ */ jsx(GlassBackdrop, { ids: glassIds }),
1917
+ /* @__PURE__ */ jsx("g", { clipPath: isBox ? `url(#${boxClipId})` : void 0, children: /* @__PURE__ */ jsx(
1918
+ "g",
1919
+ {
1920
+ "data-avatar-box-character": isBox ? "" : void 0,
1921
+ "data-avatar-box-offset": isBox && !isOrbForm ? boxOffset : void 0,
1922
+ "data-avatar-box-sway": isBox && !isOrbForm ? boxSway : void 0,
1923
+ "data-avatar-box-tilt": isBox && !isOrbForm ? boxTilt : void 0,
1924
+ transform: presentationTransform,
1925
+ children: /* @__PURE__ */ jsx("g", { transform: isOrbForm ? void 0 : transform, children: /* @__PURE__ */ jsxs(
1926
+ "g",
1927
+ {
1928
+ "data-avatar-artwork": "",
1929
+ "data-avatar-optical-scale": opticalScale,
1930
+ transform: opticalTransform,
1931
+ children: [
1932
+ isOrbForm ? /* @__PURE__ */ jsxs(Fragment, { children: [
1933
+ /* @__PURE__ */ jsx("g", { "data-avatar-orb-export-fallback": "", display: "none", children: /* @__PURE__ */ jsx(
1934
+ OrbBackdrop,
1935
+ {
1936
+ ids: orbIds,
1937
+ color: identity.color,
1938
+ state: effectiveState,
1939
+ time: sequenceTime,
1940
+ reducedMotion
1941
+ }
1942
+ ) }),
1943
+ /* @__PURE__ */ jsx(
1944
+ OrbCloud,
1945
+ {
1946
+ color: identity.color,
1947
+ playing,
1948
+ reducedMotion,
1949
+ state: effectiveState
1950
+ }
1951
+ )
1952
+ ] }) : /* @__PURE__ */ jsx(
1953
+ "path",
1954
+ {
1955
+ "data-avatar-bezel": "",
1956
+ d: frame.bodyPath,
1957
+ fill: identity.color,
1958
+ fillRule: "nonzero"
1959
+ }
1960
+ ),
1961
+ !isOrbForm && frame.usesAuthoredShape && currentShape.layers?.map((layer, index) => /* @__PURE__ */ jsx(
1962
+ "path",
1963
+ {
1964
+ "data-avatar-role-layer": "",
1965
+ d: layer.path,
1966
+ fill: layer.tone === "highlight" ? "#FFFFFF" : "#0A0A0C",
1967
+ fillRule: "evenodd",
1968
+ opacity: layer.opacity
1969
+ },
1970
+ index
1971
+ )),
1972
+ !isOrbForm && /* @__PURE__ */ jsxs(Fragment, { children: [
1973
+ /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsx("clipPath", { id: clipId, children: /* @__PURE__ */ jsx(
1974
+ "rect",
1975
+ {
1976
+ x: frame.face.x,
1977
+ y: frame.face.y,
1978
+ width: frame.face.width,
1979
+ height: frame.face.height,
1980
+ rx: frame.face.radius
1981
+ }
1982
+ ) }) }),
1983
+ /* @__PURE__ */ jsx(
1984
+ "rect",
1985
+ {
1986
+ "data-avatar-face": "",
1987
+ x: frame.face.x,
1988
+ y: frame.face.y,
1989
+ width: frame.face.width,
1990
+ height: frame.face.height,
1991
+ rx: frame.face.radius,
1992
+ fill: faceColors.face,
1993
+ "data-avatar-face-tone": faceColors.tone,
1994
+ "data-avatar-face-style": currentShape.faceStyle,
1995
+ opacity: showsFacePlate ? frame.faceOpacity : 0
1996
+ }
1997
+ ),
1998
+ /* @__PURE__ */ jsx("g", { clipPath: `url(#${clipId})`, opacity: frame.eyeOpacity, children: frame.eyes.map((eye3, index) => {
1999
+ const glintRadius = Math.max(1, Math.min(eye3.width, eye3.height) * 0.16);
2000
+ const eyeTransform = `rotate(${eye3.rotation} ${eye3.cx} ${eye3.cy})`;
2001
+ return /* @__PURE__ */ jsxs("g", { transform: eyeTransform, children: [
2002
+ /* @__PURE__ */ jsx(
2003
+ "rect",
2004
+ {
2005
+ "data-avatar-eye": "",
2006
+ x: eye3.cx - eye3.width / 2,
2007
+ y: eye3.cy - eye3.height / 2,
2008
+ width: eye3.width,
2009
+ height: eye3.height,
2010
+ rx: Math.min(eye3.width, eye3.height) / 2,
2011
+ fill: eyeColor
2012
+ }
2013
+ ),
2014
+ /* @__PURE__ */ jsx(
2015
+ "circle",
2016
+ {
2017
+ "data-avatar-eye-glint": "",
2018
+ cx: eye3.cx - eye3.width * 0.14,
2019
+ cy: eye3.cy - eye3.height * 0.18,
2020
+ r: glintRadius,
2021
+ fill: eyeGlint
2022
+ }
2023
+ )
2024
+ ] }, index);
2025
+ }) })
2026
+ ] })
2027
+ ]
2028
+ }
2029
+ ) })
2030
+ }
2031
+ ) }),
2032
+ isBox && /* @__PURE__ */ jsx("g", { clipPath: `url(#${boxClipId})`, children: /* @__PURE__ */ jsx(GlassOverlay, { ids: glassIds }) })
2033
+ ]
2034
+ }
2035
+ );
2036
+ });
2037
+
2038
+ // src/vendor/service/agent-avatar-seed.ts
2039
+ var SEEDED_AGENT_AVATAR_COLORS = [
2040
+ "#E8483F",
2041
+ "#F08A24",
2042
+ "#F0B429",
2043
+ "#3ECF8E",
2044
+ "#2FBFA0",
2045
+ "#3B93F0",
2046
+ "#2563EB",
2047
+ "#8B5CF6",
2048
+ "#E152B0",
2049
+ "#8B5E3C"
2050
+ ];
2051
+ function pickAgentAvatarColor(seed) {
2052
+ const normalized = seed.trim().toLowerCase();
2053
+ let hash = 2166136261;
2054
+ for (let index = 0; index < normalized.length; index += 1) {
2055
+ hash ^= normalized.charCodeAt(index);
2056
+ hash = Math.imul(hash, 16777619);
2057
+ }
2058
+ return SEEDED_AGENT_AVATAR_COLORS[(hash >>> 0) % SEEDED_AGENT_AVATAR_COLORS.length];
2059
+ }
2060
+
2061
+ // src/vendor/service/agent-avatar-config.ts
2062
+ var AGENT_AVATAR_SHAPES = [
2063
+ "orb",
2064
+ "round",
2065
+ "pebble",
2066
+ "squircle",
2067
+ "capsule",
2068
+ "triangle",
2069
+ "hexagon",
2070
+ "cloud",
2071
+ "egg",
2072
+ "eary",
2073
+ "puff",
2074
+ "bolt",
2075
+ "briefcase",
2076
+ "chart",
2077
+ "support",
2078
+ "spark"
2079
+ ];
2080
+ z.object({
2081
+ version: z.literal(4),
2082
+ shape: z.enum(AGENT_AVATAR_SHAPES),
2083
+ color: z.string().regex(/^#[0-9A-F]{6}$/i),
2084
+ expression: z.enum(["neutral", "focused", "happy", "puzzled"]),
2085
+ faceTone: z.enum(["auto", "light", "dark"]),
2086
+ eyeSize: z.enum(["small", "normal", "large"]),
2087
+ presentation: z.enum(["free", "box"]),
2088
+ face: z.enum(["square", "none"]).optional()
2089
+ }).strict();
2090
+
2091
+ // src/vendor/service/agent-history-contract.ts
2092
+ var HISTORY_CITATION_PREFIX = "/cite/history/";
2093
+ function historyCitationReference(href) {
2094
+ if (!href.startsWith(HISTORY_CITATION_PREFIX)) return null;
2095
+ const reference = href.slice(HISTORY_CITATION_PREFIX.length);
2096
+ return reference.length <= 16e3 && /^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/.test(reference) ? reference : null;
2097
+ }
2098
+
2099
+ // src/vendor/service-types.ts
2100
+ var FORMAT_EXT = {
2101
+ markdown: "md",
2102
+ csv: "csv",
2103
+ sheet: "xlsx",
2104
+ pdf: "pdf",
2105
+ image: "png",
2106
+ htmldeck: "json",
2107
+ file: "bin",
2108
+ canvas: "html"
2109
+ };
2110
+
2111
+ // src/vendor/ui/agent-avatar/types.ts
2112
+ var DEFAULT_AGENT_AVATAR_CONFIG = {
2113
+ version: 4,
2114
+ shape: "orb",
2115
+ color: "#0084FF",
2116
+ expression: "neutral",
2117
+ faceTone: "light",
2118
+ eyeSize: "normal",
2119
+ presentation: "free"
2120
+ };
2121
+ function createSeededAgentAvatarConfig(seed) {
2122
+ const normalizedSeed = seed?.trim();
2123
+ if (!normalizedSeed) return DEFAULT_AGENT_AVATAR_CONFIG;
2124
+ return {
2125
+ ...DEFAULT_AGENT_AVATAR_CONFIG,
2126
+ color: pickAgentAvatarColor(normalizedSeed)
2127
+ };
2128
+ }
2129
+ function normalizeAgentAvatarConfig(value, seed) {
2130
+ if (!value) return createSeededAgentAvatarConfig(seed);
2131
+ if (value.shape === "orb" && value.presentation === "box") {
2132
+ return { ...value, presentation: "free" };
2133
+ }
2134
+ return value;
2135
+ }
2136
+ var AgentAvatarView = memo(function AgentAvatarView2({
2137
+ name,
2138
+ config,
2139
+ seed,
2140
+ size = 40,
2141
+ state = "idle",
2142
+ animated = false,
2143
+ className,
2144
+ label
2145
+ }) {
2146
+ const persistedIdentity = normalizeAgentAvatarConfig(config, seed ?? name);
2147
+ const identity = { ...persistedIdentity, faceTone: "light" };
2148
+ const accessibleLabel = label ?? `${name?.trim() || "Agent"} avatar`;
2149
+ return /* @__PURE__ */ jsx(
2150
+ Avatar,
2151
+ {
2152
+ identity,
2153
+ state,
2154
+ playing: animated,
2155
+ followPointer: animated,
2156
+ reducedMotion: animated ? void 0 : true,
2157
+ size,
2158
+ motionKey: `${identity.shape}:${identity.color}:${identity.expression}`,
2159
+ label: accessibleLabel,
2160
+ className: cn("block shrink-0 overflow-hidden", className)
2161
+ }
2162
+ );
2163
+ });
2164
+ var AgentAvatar = AgentAvatarView;
2165
+
2166
+ export { AgentAvatar, FORMAT_EXT, HISTORY_CITATION_PREFIX, historyCitationReference };