@heroui/agent 0.2.0-beta.8 → 0.2.0-beta.9

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 (47) hide show
  1. package/CHANGELOG.md +5 -0
  2. package/dist/chart-content-BBHQVMP4.js +1 -0
  3. package/dist/chunk-2XBFFSW2.js +1 -0
  4. package/dist/chunk-64RI74L5.js +1 -0
  5. package/dist/chunk-6ZJJN322.js +1 -0
  6. package/dist/chunk-7KCGPNEN.js +1 -0
  7. package/dist/chunk-BBB5EHDN.js +5 -0
  8. package/dist/chunk-CR3H7AVI.js +1 -0
  9. package/dist/chunk-HCLXS4HQ.js +1 -0
  10. package/dist/chunk-MXLGM4WV.js +1 -0
  11. package/dist/chunk-OA3TG5CS.js +1 -0
  12. package/dist/chunk-PZJ4NC3J.js +1 -0
  13. package/dist/chunk-RNNGE7KM.js +1 -0
  14. package/dist/chunk-S6OIAJSC.js +1 -0
  15. package/dist/chunk-SUDHJNTJ.js +2 -0
  16. package/dist/chunk-WUAFMD7Z.js +2 -0
  17. package/dist/component-renderer-GG6JVRUG.js +1 -0
  18. package/dist/composer-draft-NSKK65F3.js +1 -0
  19. package/dist/composer-image-draft-KAGTNQR7.js +1 -0
  20. package/dist/contracts.d.ts +1 -1
  21. package/dist/contracts.js +2 -2445
  22. package/dist/embed-runtime-GYXK7V6N.js +5 -0
  23. package/dist/index.js +1 -31
  24. package/dist/interactive-map-surface-WC2LPCR7.js +1 -0
  25. package/dist/internal/client-tools.js +1 -0
  26. package/dist/internal/models.js +1 -0
  27. package/dist/internal/runtime.js +1 -0
  28. package/dist/internal/theme.js +1 -0
  29. package/dist/next.js +1 -25
  30. package/dist/server.js +1 -136
  31. package/package.json +4 -4
  32. package/dist/chart-content-E4NPTUPR.js +0 -2696
  33. package/dist/chunk-3FG5NRTX.js +0 -9
  34. package/dist/chunk-CMZDZGUZ.js +0 -1132
  35. package/dist/chunk-DS4X5K2R.js +0 -56
  36. package/dist/chunk-FNGGMHVR.js +0 -625
  37. package/dist/chunk-G6GFNSG4.js +0 -284
  38. package/dist/chunk-Q7LGTVBL.js +0 -43
  39. package/dist/chunk-TOOT6SZ2.js +0 -74
  40. package/dist/chunk-UUPU3MYB.js +0 -42
  41. package/dist/chunk-VJA52U5P.js +0 -137
  42. package/dist/chunk-W7SCMB3O.js +0 -1285
  43. package/dist/component-renderer-MDDQMQTU.js +0 -10629
  44. package/dist/composer-draft-DTQAEO5K.js +0 -20
  45. package/dist/composer-image-draft-IVJ352E6.js +0 -174
  46. package/dist/embed-runtime-VVAGDPYY.js +0 -9422
  47. package/dist/interactive-map-surface-67KHT3VB.js +0 -362
@@ -1,1132 +0,0 @@
1
- import {
2
- AGENT_MODEL_OPTIONS,
3
- AgentLoadingState,
4
- DEFAULT_AGENT_PICKER_MODEL_ID,
5
- EmbedSessionManager,
6
- PanelShell,
7
- ShellConversation,
8
- containsComposerFocus,
9
- createSubmittedAgentShellHandoff,
10
- isHeroUIAgentAttachmentContentType,
11
- readSidebarWidth,
12
- resolveOptions,
13
- setFocus,
14
- writeAgentShellAttachments,
15
- writeAgentShellHandoff
16
- } from "./chunk-W7SCMB3O.js";
17
- import {
18
- renderInlineMarkdown
19
- } from "./chunk-Q7LGTVBL.js";
20
-
21
- // src/embed/provider.tsx
22
- import {
23
- useCallback,
24
- useEffect as useEffect2,
25
- useEffectEvent,
26
- useLayoutEffect,
27
- useMemo,
28
- useRef as useRef2,
29
- useState,
30
- useSyncExternalStore
31
- } from "react";
32
- import { createRoot } from "react-dom/client";
33
-
34
- // src/embed/launcher-spark-icon.tsx
35
- import { SparklesFill } from "@gravity-ui/icons";
36
- import { jsx } from "react/jsx-runtime";
37
- function LauncherSparkIcon(props) {
38
- return /* @__PURE__ */ jsx(SparklesFill, { ...props });
39
- }
40
-
41
- // src/embed/launcher-icon.tsx
42
- import { jsx as jsx2 } from "react/jsx-runtime";
43
- function isSvgIcon(icon) {
44
- return /\.svg(?:[?#]|$)/i.test(icon) || /^data:image\/svg\+xml[;,]/i.test(icon);
45
- }
46
- function cssUrl(value) {
47
- return `url("${value.replace(/["\\\n\r]/g, encodeURIComponent)}")`;
48
- }
49
- function LauncherIcon({ icon }) {
50
- if (!icon) return /* @__PURE__ */ jsx2(LauncherSparkIcon, {});
51
- if (isSvgIcon(icon)) {
52
- return /* @__PURE__ */ jsx2(
53
- "span",
54
- {
55
- "aria-hidden": "true",
56
- className: "ha-launcher__icon ha-launcher__icon--tinted",
57
- style: { WebkitMaskImage: cssUrl(icon), maskImage: cssUrl(icon) }
58
- }
59
- );
60
- }
61
- return /* @__PURE__ */ jsx2("img", { alt: "", className: "ha-launcher__icon", src: icon });
62
- }
63
-
64
- // src/embed/merge-remote-config.ts
65
- function isPlainObject(value) {
66
- return typeof value === "object" && value !== null && !Array.isArray(value);
67
- }
68
- function deepMerge(base, override) {
69
- if (override === void 0) return base;
70
- if (!isPlainObject(base) || !isPlainObject(override)) return override;
71
- const merged = { ...base };
72
- for (const [key, value] of Object.entries(override)) {
73
- if (value === void 0) continue;
74
- merged[key] = key in base ? deepMerge(base[key], value) : value;
75
- }
76
- return merged;
77
- }
78
- function mergeRemoteConfig(remote, props) {
79
- if (!remote) return props;
80
- const groups = {
81
- appearance: remote.appearance,
82
- capabilities: remote.capabilities,
83
- composer: remote.composer,
84
- markdown: remote.markdown,
85
- permissions: remote.permissions,
86
- responseActions: remote.responseActions,
87
- startScreen: remote.startScreen
88
- };
89
- const merged = deepMerge(groups, {
90
- appearance: props.appearance,
91
- capabilities: props.capabilities,
92
- composer: props.composer,
93
- // Markdown renderer plugins are functions and never survive a JSON
94
- // document, so they are merged back by identity in the provider.
95
- markdown: props.markdown ? { ...props.markdown, plugins: void 0 } : void 0,
96
- permissions: props.permissions,
97
- responseActions: props.responseActions,
98
- startScreen: props.startScreen
99
- });
100
- return { ...props, ...merged };
101
- }
102
- function hostSuppliesFont(props) {
103
- return Boolean(props.appearance?.theme?.typography?.fontFamily?.trim());
104
- }
105
-
106
- // src/contracts/appearance.ts
107
- var HEROUI_AGENT_REMOTE_CONFIG_VERSION = 1;
108
- var INVALID = Symbol("invalid");
109
- function isRecord(value) {
110
- return typeof value === "object" && value !== null && !Array.isArray(value);
111
- }
112
- function optionalString(value) {
113
- if (value === void 0) return void 0;
114
- return typeof value === "string" ? value : INVALID;
115
- }
116
- function optionalBoolean(value) {
117
- if (value === void 0) return void 0;
118
- return typeof value === "boolean" ? value : INVALID;
119
- }
120
- function optionalNumber(value) {
121
- if (value === void 0) return void 0;
122
- return typeof value === "number" && Number.isFinite(value) ? value : INVALID;
123
- }
124
- function optionalEnum(allowed) {
125
- return (value) => {
126
- if (value === void 0) return void 0;
127
- return typeof value === "string" && allowed.includes(value) ? value : INVALID;
128
- };
129
- }
130
- function optionalThemeColor(value) {
131
- if (value === void 0) return void 0;
132
- if (typeof value === "string") return value;
133
- if (!isRecord(value)) return INVALID;
134
- const dark = optionalString(value["dark"]);
135
- const light = optionalString(value["light"]);
136
- if (dark === INVALID || light === INVALID) return INVALID;
137
- return { ...dark === void 0 ? {} : { dark }, ...light === void 0 ? {} : { light } };
138
- }
139
- function optionalStringRecord(value) {
140
- if (value === void 0) return void 0;
141
- if (!isRecord(value)) return INVALID;
142
- const record = {};
143
- for (const [key, entry] of Object.entries(value)) {
144
- if (typeof entry !== "string") return INVALID;
145
- record[key] = entry;
146
- }
147
- return record;
148
- }
149
- function optionalStringArray(value) {
150
- if (value === void 0) return void 0;
151
- if (!Array.isArray(value) || value.some((entry) => typeof entry !== "string")) return INVALID;
152
- return value;
153
- }
154
- function shape(value, validators) {
155
- if (value === void 0) return INVALID;
156
- if (!isRecord(value)) return INVALID;
157
- const result = {};
158
- for (const [key, validate] of Object.entries(validators)) {
159
- const parsed = validate(value[key]);
160
- if (parsed === INVALID) return INVALID;
161
- if (parsed !== void 0) result[key] = parsed;
162
- }
163
- return result;
164
- }
165
- function group(parsed) {
166
- return parsed === INVALID ? void 0 : parsed;
167
- }
168
- var COLOR_KEYS = [
169
- "accent",
170
- "background",
171
- "foreground",
172
- "overlay",
173
- "surface",
174
- "surfaceSecondary",
175
- "tooltip"
176
- ];
177
- function parseAppearance(value) {
178
- return shape(value, {
179
- launcher: (launcher) => launcher === void 0 ? void 0 : shape(launcher, {
180
- background: optionalThemeColor,
181
- icon: optionalString,
182
- position: optionalEnum(["bottom-left", "bottom-right"]),
183
- style: optionalStringRecord
184
- }),
185
- panel: (panel) => panel === void 0 ? void 0 : shape(panel, {
186
- expandable: optionalBoolean,
187
- expanded: optionalBoolean,
188
- initialHeight: (entry) => entry === void 0 || typeof entry === "string" ? entry : optionalNumber(entry),
189
- initialWidth: (entry) => entry === void 0 || typeof entry === "string" ? entry : optionalNumber(entry)
190
- }),
191
- theme: (theme) => theme === void 0 ? void 0 : shape(theme, {
192
- colorScheme: optionalEnum(["dark", "light", "system"]),
193
- colors: (colors) => colors === void 0 ? void 0 : shape(
194
- colors,
195
- Object.fromEntries(COLOR_KEYS.map((key) => [key, optionalThemeColor]))
196
- ),
197
- designTheme: optionalEnum(["base", "brutalism", "glass", "mouve"]),
198
- radius: optionalEnum(["pill", "round", "sharp", "soft"]),
199
- typography: (typography) => typography === void 0 ? void 0 : shape(typography, { baseSize: optionalNumber, fontFamily: optionalString })
200
- }),
201
- viewMode: optionalEnum(["floating", "sidebar"])
202
- });
203
- }
204
- function parseComposer(value) {
205
- return shape(value, {
206
- attachments: (attachments) => {
207
- if (attachments === void 0 || attachments === false) return attachments;
208
- if (!Array.isArray(attachments)) return INVALID;
209
- const types = attachments.filter(
210
- (entry) => typeof entry === "string" && isHeroUIAgentAttachmentContentType(entry)
211
- );
212
- return types.length === attachments.length ? types : INVALID;
213
- },
214
- defaultModel: optionalString,
215
- dictation: optionalBoolean,
216
- disclaimer: (disclaimer) => disclaimer === false ? false : optionalString(disclaimer),
217
- modelPicker: optionalBoolean,
218
- placeholder: optionalString
219
- });
220
- }
221
- function parseMarkdown(value) {
222
- return shape(value, {
223
- animated: (animated) => {
224
- if (animated === void 0 || animated === false) return animated;
225
- if (!isRecord(animated)) return INVALID;
226
- const animation = optionalEnum(["blurIn", "fadeIn", "slideUp"])(
227
- animated["animation"]
228
- );
229
- if (animation === INVALID || animation === void 0) return INVALID;
230
- return { ...animated, animation };
231
- },
232
- caret: (caret) => caret === false ? false : optionalEnum(["block", "circle"])(caret)
233
- });
234
- }
235
- function parseResponseActions(value) {
236
- if (value === void 0 || value === false) return value;
237
- if (!Array.isArray(value)) return INVALID;
238
- const allowed = ["copy", "feedback", "retry"];
239
- const actions = value.filter(
240
- (entry) => typeof entry === "string" && allowed.includes(entry)
241
- );
242
- return actions.length === value.length ? actions : INVALID;
243
- }
244
- function parseAgentRemoteConfig(value) {
245
- if (!isRecord(value)) return null;
246
- if (value["version"] !== HEROUI_AGENT_REMOTE_CONFIG_VERSION) return null;
247
- const revision = value["revision"];
248
- if (typeof revision !== "string" || !revision) return null;
249
- const appearance = group(parseAppearance(value["appearance"]));
250
- const capabilities = group(
251
- shape(value["capabilities"], {
252
- imageSearch: optionalBoolean,
253
- newsSearch: optionalBoolean,
254
- webSearch: optionalBoolean
255
- })
256
- );
257
- const composer = group(parseComposer(value["composer"]));
258
- const markdown = group(parseMarkdown(value["markdown"]));
259
- const permissions = group(
260
- shape(value["permissions"], {
261
- defaultMode: optionalEnum(["ask", "auto", "full"]),
262
- showPicker: optionalBoolean
263
- })
264
- );
265
- const responseActions = group(parseResponseActions(value["responseActions"]));
266
- const startScreen = group(
267
- shape(value["startScreen"], {
268
- greeting: optionalString,
269
- promptShortcuts: optionalBoolean,
270
- prompts: optionalStringArray
271
- })
272
- );
273
- const webfont = group(
274
- shape(value["webfont"], {
275
- familyName: (familyName) => typeof familyName === "string" && familyName ? familyName : INVALID,
276
- fontFaceUrl: optionalString,
277
- stylesheetUrl: optionalString
278
- })
279
- );
280
- return {
281
- ...appearance ? { appearance } : {},
282
- ...capabilities ? { capabilities } : {},
283
- ...composer ? { composer } : {},
284
- ...markdown ? { markdown } : {},
285
- ...permissions ? { permissions } : {},
286
- ...responseActions === void 0 ? {} : { responseActions },
287
- ...startScreen ? { startScreen } : {},
288
- ...webfont ? { webfont } : {},
289
- revision,
290
- version: HEROUI_AGENT_REMOTE_CONFIG_VERSION
291
- };
292
- }
293
-
294
- // src/embed/remote-config.ts
295
- function cacheKey(agentId) {
296
- return `heroui-agent:config:${agentId}`;
297
- }
298
- var REMOTE_CONFIG_CACHE_VERSION = 1;
299
- function readCachedRemoteConfigSnapshot(agentId) {
300
- try {
301
- const raw = window.localStorage.getItem(cacheKey(agentId));
302
- if (!raw) return null;
303
- const value = JSON.parse(raw);
304
- if (typeof value === "object" && value !== null && !Array.isArray(value)) {
305
- const envelope = value;
306
- if (envelope.cacheVersion === REMOTE_CONFIG_CACHE_VERSION && typeof envelope.cachedAt === "number" && Number.isFinite(envelope.cachedAt)) {
307
- const config = parseAgentRemoteConfig(envelope.config);
308
- return config ? { cachedAt: envelope.cachedAt, config, legacy: false } : null;
309
- }
310
- }
311
- const legacyConfig = parseAgentRemoteConfig(value);
312
- return legacyConfig ? { cachedAt: 0, config: legacyConfig, legacy: true } : null;
313
- } catch {
314
- return null;
315
- }
316
- }
317
- function writeCachedRemoteConfig(agentId, config, cachedAt = Date.now()) {
318
- try {
319
- const envelope = {
320
- cacheVersion: REMOTE_CONFIG_CACHE_VERSION,
321
- cachedAt,
322
- config
323
- };
324
- window.localStorage.setItem(cacheKey(agentId), JSON.stringify(envelope));
325
- } catch {
326
- }
327
- }
328
- function clearCachedRemoteConfig(agentId) {
329
- try {
330
- window.localStorage.removeItem(cacheKey(agentId));
331
- } catch {
332
- }
333
- }
334
- async function fetchRemoteConfig(apiBaseUrl, agentId, options = {}) {
335
- try {
336
- const response = await fetch(
337
- `${apiBaseUrl}/v1/agents/${encodeURIComponent(agentId)}/appearance`,
338
- {
339
- headers: options.revision ? { "If-None-Match": `"${options.revision}"` } : {},
340
- ...options.signal ? { signal: options.signal } : {}
341
- }
342
- );
343
- if (response.status === 304) return { status: "not-modified" };
344
- if (response.status === 404 || response.status === 410) return { status: "missing" };
345
- if (!response.ok) return { status: "unavailable" };
346
- const config = parseAgentRemoteConfig(await response.json());
347
- return config ? { config, status: "ok" } : { status: "unavailable" };
348
- } catch {
349
- return { status: "unavailable" };
350
- }
351
- }
352
-
353
- // src/embed/shell-composer-presentation.tsx
354
- import { ChevronDown, Microphone, Plus, ShieldCheck } from "@gravity-ui/icons";
355
- import { useEffect, useRef } from "react";
356
- import { Fragment, jsx as jsx3, jsxs } from "react/jsx-runtime";
357
- var PERMISSION_LABELS = {
358
- ask: "Ask for approval",
359
- auto: "Approve for me",
360
- full: "Full access"
361
- };
362
- function createShellComposerPresentation({
363
- onFileDialogActiveChange,
364
- onIntent,
365
- options
366
- }) {
367
- return {
368
- end: /* @__PURE__ */ jsx3(ShellComposerControls, { options }),
369
- footer: options.composerDisclaimer ? /* @__PURE__ */ jsx3("p", { className: "ha-footnote", children: renderInlineMarkdown(options.composerDisclaimer) }) : null,
370
- start: options.composerAttachmentContentTypes.length > 0 ? /* @__PURE__ */ jsx3(
371
- ShellAttachmentControl,
372
- {
373
- accept: options.composerAttachmentAccept,
374
- agentId: options.agentId,
375
- onFileDialogActiveChange,
376
- onIntent
377
- }
378
- ) : null
379
- };
380
- }
381
- function ShellAttachmentControl({
382
- accept,
383
- agentId,
384
- onFileDialogActiveChange,
385
- onIntent
386
- }) {
387
- const inputRef = useRef(null);
388
- useEffect(() => {
389
- const input = inputRef.current;
390
- let focusTimer;
391
- const release = () => onFileDialogActiveChange(false);
392
- const releaseAfterFocus = () => {
393
- focusTimer = window.setTimeout(release, 0);
394
- };
395
- input?.addEventListener("cancel", release);
396
- window.addEventListener("focus", releaseAfterFocus);
397
- return () => {
398
- input?.removeEventListener("cancel", release);
399
- window.removeEventListener("focus", releaseAfterFocus);
400
- window.clearTimeout(focusTimer);
401
- };
402
- }, [onFileDialogActiveChange]);
403
- return /* @__PURE__ */ jsxs(Fragment, { children: [
404
- /* @__PURE__ */ jsx3(
405
- "input",
406
- {
407
- ref: inputRef,
408
- multiple: true,
409
- accept,
410
- "aria-label": "Choose files to attach",
411
- className: "ha-file-input",
412
- type: "file",
413
- onChange: (event) => {
414
- writeAgentShellAttachments(agentId, Array.from(event.currentTarget.files ?? []));
415
- event.currentTarget.value = "";
416
- onFileDialogActiveChange(false);
417
- onIntent();
418
- }
419
- }
420
- ),
421
- /* @__PURE__ */ jsx3(
422
- "button",
423
- {
424
- "aria-label": "Attach files",
425
- className: "ha-attach",
426
- type: "button",
427
- onClick: () => {
428
- onFileDialogActiveChange(true);
429
- inputRef.current?.click();
430
- },
431
- children: /* @__PURE__ */ jsx3(Plus, { "aria-hidden": "true" })
432
- }
433
- )
434
- ] });
435
- }
436
- function ShellComposerControls({ options }) {
437
- const modelId = options.composerDefaultModel ?? DEFAULT_AGENT_PICKER_MODEL_ID;
438
- const modelLabel = AGENT_MODEL_OPTIONS.find((option) => option.id === modelId)?.label ?? modelId;
439
- return /* @__PURE__ */ jsxs(Fragment, { children: [
440
- options.permissionShowPicker && options.tools.length > 0 ? /* @__PURE__ */ jsx3(
441
- ShellPicker,
442
- {
443
- icon: /* @__PURE__ */ jsx3(ShieldCheck, { "aria-hidden": "true", className: "aui-permission-picker__trigger-icon" }),
444
- kind: "permission",
445
- label: PERMISSION_LABELS[options.permissionDefaultMode],
446
- tone: options.permissionDefaultMode === "full" ? "warning" : void 0
447
- }
448
- ) : null,
449
- options.composerModelPicker ? /* @__PURE__ */ jsx3(ShellPicker, { kind: "model", label: modelLabel }) : null,
450
- options.composerDictation ? /* @__PURE__ */ jsx3("button", { disabled: true, "aria-label": "Dictate message", className: "ha-dictation", type: "button", children: /* @__PURE__ */ jsx3(Microphone, { "aria-hidden": "true" }) }) : null
451
- ] });
452
- }
453
- function ShellPicker({
454
- icon,
455
- kind,
456
- label,
457
- tone
458
- }) {
459
- const name = `aui-${kind}-picker`;
460
- return /* @__PURE__ */ jsx3("div", { className: `${name} ha-${kind}-picker`, "data-tone": tone, children: /* @__PURE__ */ jsxs(
461
- "button",
462
- {
463
- disabled: true,
464
- "aria-label": kind === "model" ? "AI model" : "Tool permissions",
465
- className: `${name}__trigger ha-shell-picker-trigger`,
466
- type: "button",
467
- children: [
468
- icon,
469
- /* @__PURE__ */ jsx3("span", { className: `${name}__value`, children: label }),
470
- /* @__PURE__ */ jsx3(ChevronDown, { "aria-hidden": "true", className: `${name}__indicator` })
471
- ]
472
- }
473
- ) });
474
- }
475
-
476
- // src/embed/webfont.ts
477
- var FONT_FILE_EXTENSIONS = [".woff2", ".woff", ".ttf", ".otf", ".eot"];
478
- function elementId(font) {
479
- return `heroui-agent-font-${font.familyName.toLowerCase().replace(/[^a-z0-9]+/g, "-")}`;
480
- }
481
- function fontFormat(url) {
482
- const isVariable = url.includes(":vf@") || url.includes("-wght-") || url.includes("-opsz-");
483
- if (url.endsWith(".woff")) return "woff";
484
- if (url.endsWith(".ttf")) return "truetype";
485
- if (url.endsWith(".otf")) return "opentype";
486
- return isVariable ? "woff2-variations" : "woff2";
487
- }
488
- function isSafeFontUrl(url, requireFontFile) {
489
- try {
490
- const parsed = new URL(url);
491
- if (parsed.protocol !== "https:") return false;
492
- if (!requireFontFile) return true;
493
- const pathname = parsed.pathname.toLowerCase();
494
- return FONT_FILE_EXTENSIONS.some((extension) => pathname.endsWith(extension));
495
- } catch {
496
- return false;
497
- }
498
- }
499
- function loadAgentWebfont(font) {
500
- if (!font || typeof document === "undefined") return () => void 0;
501
- const id = elementId(font);
502
- if (document.getElementById(id)) return () => void 0;
503
- if (font.stylesheetUrl && isSafeFontUrl(font.stylesheetUrl, false)) {
504
- const link = document.createElement("link");
505
- link.id = id;
506
- link.rel = "stylesheet";
507
- link.href = font.stylesheetUrl;
508
- document.head.append(link);
509
- return () => link.remove();
510
- }
511
- if (font.fontFaceUrl && isSafeFontUrl(font.fontFaceUrl, true)) {
512
- const style = document.createElement("style");
513
- const isVariable = font.fontFaceUrl.includes(":vf@") || font.fontFaceUrl.includes("-wght-") || font.fontFaceUrl.includes("-opsz-");
514
- style.id = id;
515
- style.textContent = [
516
- "@font-face {",
517
- ` font-family: '${font.familyName.replaceAll("'", "")}';`,
518
- " font-style: normal;",
519
- " font-display: swap;",
520
- ` font-weight: ${isVariable ? "100 900" : "400"};`,
521
- ` src: url(${font.fontFaceUrl}) format('${fontFormat(font.fontFaceUrl)}');`,
522
- "}"
523
- ].join("\n");
524
- document.head.append(style);
525
- return () => style.remove();
526
- }
527
- return () => void 0;
528
- }
529
-
530
- // src/embed/provider.tsx
531
- import { Fragment as Fragment2, jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
532
- var REMOTE_CONFIG_RESOLUTION_TIMEOUT_MS = 600;
533
- var REMOTE_CONFIG_PRESENTATION_MAX_AGE_MS = 5 * 6e4;
534
- var OPEN_STATE_STORAGE_PREFIX = "heroui-agent:open:";
535
- function openStateStorageKey(agentId) {
536
- return `${OPEN_STATE_STORAGE_PREFIX}${agentId}`;
537
- }
538
- function readOpenState(agentId) {
539
- if (typeof window === "undefined") return false;
540
- try {
541
- return window.sessionStorage.getItem(openStateStorageKey(agentId)) === "true";
542
- } catch {
543
- return false;
544
- }
545
- }
546
- function writeOpenState(agentId, open) {
547
- try {
548
- if (open) window.sessionStorage.setItem(openStateStorageKey(agentId), "true");
549
- else window.sessionStorage.removeItem(openStateStorageKey(agentId));
550
- } catch {
551
- }
552
- }
553
- var embedRuntimePromise;
554
- function loadEmbedRuntime() {
555
- embedRuntimePromise ??= import(
556
- /* webpackPrefetch: true */
557
- "./embed-runtime-VVAGDPYY.js"
558
- ).then(
559
- (module) => module.default
560
- );
561
- return embedRuntimePromise;
562
- }
563
- var controllers = /* @__PURE__ */ new Map();
564
- var controllerListeners = /* @__PURE__ */ new Set();
565
- function getController(agentId) {
566
- return agentId ? controllers.get(agentId) : [...controllers.values()][controllers.size - 1];
567
- }
568
- function notifyControllerListeners() {
569
- for (const listener of controllerListeners) listener();
570
- }
571
- function subscribeToControllers(listener) {
572
- controllerListeners.add(listener);
573
- return () => controllerListeners.delete(listener);
574
- }
575
- function subscribeToColorScheme(onChange) {
576
- const media = window.matchMedia?.("(prefers-color-scheme: dark)");
577
- media?.addEventListener?.("change", onChange);
578
- return () => media?.removeEventListener?.("change", onChange);
579
- }
580
- function prefersDarkColorScheme() {
581
- return window.matchMedia?.("(prefers-color-scheme: dark)").matches === true;
582
- }
583
- function dispatch(agentId, method, ...args) {
584
- const controller = getController(agentId);
585
- if (!controller) {
586
- console.warn("HeroUI Agent is not mounted yet. Add <HeroUIAgent /> to your layout.");
587
- return;
588
- }
589
- const action = controller[method];
590
- action(...args);
591
- }
592
- function useRemoteConfig(agentId, apiBaseUrl, enabled) {
593
- const [cachedSnapshot] = useState(() => {
594
- if (!enabled || typeof window === "undefined") return null;
595
- return readCachedRemoteConfigSnapshot(agentId);
596
- });
597
- const [state, setState] = useState(() => {
598
- if (!enabled) return { config: null, presentationReady: true };
599
- const cacheAge = cachedSnapshot ? Date.now() - cachedSnapshot.cachedAt : Number.POSITIVE_INFINITY;
600
- const fresh = cachedSnapshot !== null && !cachedSnapshot.legacy && cacheAge >= 0 && cacheAge <= REMOTE_CONFIG_PRESENTATION_MAX_AGE_MS;
601
- return {
602
- config: fresh ? cachedSnapshot.config : null,
603
- presentationReady: fresh
604
- };
605
- });
606
- useEffect2(() => {
607
- if (!enabled) return;
608
- const controller = new AbortController();
609
- let active = true;
610
- const settle = (config) => {
611
- setState(
612
- (current) => current.presentationReady ? current : { config, presentationReady: true }
613
- );
614
- };
615
- const budget = window.setTimeout(() => {
616
- if (!active) return;
617
- controller.abort();
618
- settle(cachedSnapshot?.config ?? null);
619
- }, REMOTE_CONFIG_RESOLUTION_TIMEOUT_MS);
620
- void fetchRemoteConfig(apiBaseUrl, agentId, {
621
- ...cachedSnapshot?.config.revision ? { revision: cachedSnapshot.config.revision } : {},
622
- signal: controller.signal
623
- }).then((result) => {
624
- if (!active || controller.signal.aborted) return;
625
- if (result.status === "ok") {
626
- writeCachedRemoteConfig(agentId, result.config);
627
- settle(result.config);
628
- return;
629
- }
630
- if (result.status === "not-modified") {
631
- if (cachedSnapshot) writeCachedRemoteConfig(agentId, cachedSnapshot.config);
632
- settle(cachedSnapshot?.config ?? null);
633
- return;
634
- }
635
- if (result.status === "missing") {
636
- clearCachedRemoteConfig(agentId);
637
- settle(null);
638
- return;
639
- }
640
- settle(cachedSnapshot?.config ?? null);
641
- }).finally(() => {
642
- if (!active || controller.signal.aborted) return;
643
- window.clearTimeout(budget);
644
- });
645
- return () => {
646
- active = false;
647
- controller.abort();
648
- window.clearTimeout(budget);
649
- };
650
- }, [apiBaseUrl, cachedSnapshot, enabled, agentId]);
651
- return enabled ? state : { config: null, presentationReady: true };
652
- }
653
- function useAgent(agentId) {
654
- const getReadySnapshot = useCallback(() => getController(agentId)?.ready ?? false, [agentId]);
655
- const ready = useSyncExternalStore(subscribeToControllers, getReadySnapshot, () => false);
656
- return useMemo(
657
- () => ({
658
- hide: () => dispatch(agentId, "hide"),
659
- newConversation: (prompt) => dispatch(agentId, "newConversation", prompt),
660
- preload: () => dispatch(agentId, "preload"),
661
- ready,
662
- refreshAuth: () => dispatch(agentId, "refreshAuth"),
663
- show: () => dispatch(agentId, "show"),
664
- shutdown: () => dispatch(agentId, "shutdown"),
665
- toggle: () => dispatch(agentId, "toggle")
666
- }),
667
- [agentId, ready]
668
- );
669
- }
670
- function HeroUIAgent(props) {
671
- const remoteSourceKey = `${props.agentId}\0${props._api?.baseUrl ?? ""}\0${props.remoteConfig !== false}`;
672
- return /* @__PURE__ */ jsx4(HeroUIAgentMount, { ...props }, remoteSourceKey);
673
- }
674
- function HeroUIAgentMount(props) {
675
- const {
676
- _api,
677
- agentId,
678
- appearance,
679
- capabilities,
680
- componentExports,
681
- composer,
682
- context,
683
- getAuthToken,
684
- markdown,
685
- onFeedback,
686
- onReady,
687
- permissions,
688
- preload: preloadEnabled,
689
- remoteConfig: remoteConfigEnabled = true,
690
- reopenOnRefresh,
691
- responseActions,
692
- showLauncher,
693
- startNewConversationOnOpen,
694
- startScreen,
695
- tools
696
- } = props;
697
- const markdownPlugins = markdown?.plugins;
698
- const apiBaseUrl = (_api?.baseUrl ?? "https://api.heroui.com").replace(/\/$/, "");
699
- const { config: remoteConfig, presentationReady: remoteConfigPresentationReady } = useRemoteConfig(
700
- agentId,
701
- apiBaseUrl,
702
- remoteConfigEnabled
703
- );
704
- const serializedConfig = JSON.stringify({
705
- _api,
706
- appearance,
707
- capabilities,
708
- componentExports,
709
- composer,
710
- markdown: markdown ? { ...markdown, plugins: void 0 } : void 0,
711
- permissions,
712
- preload: preloadEnabled,
713
- remote: remoteConfig,
714
- reopenOnRefresh,
715
- responseActions,
716
- showLauncher,
717
- startNewConversationOnOpen,
718
- startScreen
719
- });
720
- const options = useMemo(() => {
721
- const { remote, ...config } = JSON.parse(serializedConfig);
722
- const merged = mergeRemoteConfig(remote, {
723
- ...config,
724
- agentId,
725
- getAuthToken
726
- });
727
- return resolveOptions({
728
- ...merged,
729
- context,
730
- markdown: merged.markdown ? { ...merged.markdown, plugins: markdownPlugins } : markdownPlugins ? { plugins: markdownPlugins } : void 0,
731
- onFeedback,
732
- tools
733
- });
734
- }, [context, getAuthToken, markdownPlugins, onFeedback, agentId, serializedConfig, tools]);
735
- const tokenManager = useMemo(
736
- () => new EmbedSessionManager(agentId, getAuthToken),
737
- [agentId, getAuthToken]
738
- );
739
- const hostFont = hostSuppliesFont(props);
740
- const remoteWebfont = remoteConfig?.webfont;
741
- useEffect2(() => {
742
- if (hostFont) return;
743
- return loadAgentWebfont(remoteWebfont);
744
- }, [hostFont, remoteWebfont]);
745
- const [restoredOpenState] = useState(() => reopenOnRefresh === true && readOpenState(agentId));
746
- const [openRequested, setOpenRequested] = useState(restoredOpenState);
747
- const [conversationEpoch, setConversationEpoch] = useState(1);
748
- const [identityEpoch, setIdentityEpoch] = useState(1);
749
- const [identityReset, setIdentityReset] = useState(false);
750
- const [requestedConversationId, setRequestedConversationId] = useState(
751
- restoredOpenState || options.startNewConversationOnOpen ? null : void 0
752
- );
753
- const [portalRoot, setPortalRoot] = useState(null);
754
- const [EmbedRuntime, setEmbedRuntime] = useState(null);
755
- const [hasCompletedInitialLoad, setHasCompletedInitialLoad] = useState(false);
756
- const [hasUnreadMessages, setHasUnreadMessages] = useState(false);
757
- const [runtimeReadyEpoch, setRuntimeReadyEpoch] = useState(null);
758
- const conversationEpochRef = useRef2(1);
759
- const launcherRef = useRef2(null);
760
- const restoreLauncherFocusRef = useRef2(false);
761
- const portalRootRef = useRef2(null);
762
- const reportedReadyEpochRef = useRef2(null);
763
- const shouldOpenRef = useRef2(restoredOpenState);
764
- const hostRef = useRef2(null);
765
- const embedReactRootRef = useRef2(null);
766
- const rootPropertyNamesRef = useRef2([]);
767
- const prefersDark = useSyncExternalStore(
768
- subscribeToColorScheme,
769
- prefersDarkColorScheme,
770
- () => false
771
- );
772
- const designThemeClass = options.designTheme === "base" ? null : `${options.designTheme}-${options.colorScheme === "system" ? prefersDark ? "dark" : "light" : options.colorScheme}`;
773
- const ready = remoteConfigPresentationReady && runtimeReadyEpoch === conversationEpoch && EmbedRuntime !== null;
774
- const isOpen = remoteConfigPresentationReady && openRequested;
775
- const [shouldLoadRuntime, setShouldLoadRuntime] = useState(restoredOpenState || options.preload);
776
- const requestRuntime = useCallback(() => setShouldLoadRuntime(true), []);
777
- const [composerControlsRevealed, setComposerControlsRevealed] = useState(false);
778
- const [composerFileDialogActive, setComposerFileDialogActive] = useState(false);
779
- const revealComposerControls = useCallback(() => setComposerControlsRevealed(true), []);
780
- useEffect2(() => {
781
- if (!composerControlsRevealed || !portalRoot) return;
782
- const reconcileComposerFocus = () => {
783
- queueMicrotask(() => {
784
- const composer2 = portalRoot.querySelector(".ha-composer:not([hidden] *)");
785
- if (composer2 && containsComposerFocus(composer2, document.activeElement)) return;
786
- setComposerControlsRevealed(false);
787
- });
788
- };
789
- portalRoot.addEventListener("focusout", reconcileComposerFocus);
790
- return () => portalRoot.removeEventListener("focusout", reconcileComposerFocus);
791
- }, [composerControlsRevealed, portalRoot]);
792
- useEffect2(() => {
793
- if (!shouldLoadRuntime) return;
794
- void tokenManager.get().catch(() => void 0);
795
- }, [shouldLoadRuntime, tokenManager]);
796
- useEffect2(() => {
797
- if (options.reopenOnRefresh) writeOpenState(options.agentId, openRequested);
798
- else writeOpenState(options.agentId, false);
799
- }, [openRequested, options.agentId, options.reopenOnRefresh]);
800
- useEffect2(() => {
801
- if (!shouldLoadRuntime) return;
802
- if (!remoteConfigPresentationReady) {
803
- void loadEmbedRuntime().catch(() => void 0);
804
- return;
805
- }
806
- let active = true;
807
- void loadEmbedRuntime().then((runtime) => {
808
- if (active) setEmbedRuntime(() => runtime);
809
- }).catch(() => void 0);
810
- return () => {
811
- active = false;
812
- };
813
- }, [remoteConfigPresentationReady, shouldLoadRuntime]);
814
- useEffect2(() => {
815
- if (!isOpen || options.viewMode !== "sidebar") return;
816
- if (window.innerWidth < 640) return;
817
- const target = document.documentElement;
818
- const previousMargin = target.style.marginRight;
819
- const previousTransition = target.style.transition;
820
- const reducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
821
- const width = Math.min(readSidebarWidth(options.agentId, window.innerWidth), window.innerWidth);
822
- if (!reducedMotion) {
823
- target.style.transition = [previousTransition, "margin-right .28s cubic-bezier(.2,.8,.2,1)"].filter(Boolean).join(", ");
824
- }
825
- target.style.marginRight = `${width}px`;
826
- return () => {
827
- target.style.marginRight = previousMargin;
828
- window.setTimeout(() => {
829
- target.style.transition = previousTransition;
830
- }, 300);
831
- };
832
- }, [isOpen, options.agentId, options.viewMode]);
833
- useEffect2(() => {
834
- const host = document.createElement("div");
835
- const root = document.createElement("div");
836
- host.dataset["herouiAgent"] = options.agentId;
837
- root.className = "ha-root";
838
- hostRef.current = host;
839
- portalRootRef.current = root;
840
- embedReactRootRef.current = createRoot(root);
841
- host.append(root);
842
- document.body.append(host);
843
- let active = true;
844
- queueMicrotask(() => {
845
- if (active) setPortalRoot(root);
846
- });
847
- return () => {
848
- active = false;
849
- setFocus(options.agentId, false);
850
- const reactRoot = embedReactRootRef.current;
851
- portalRootRef.current = null;
852
- hostRef.current = null;
853
- embedReactRootRef.current = null;
854
- rootPropertyNamesRef.current = [];
855
- queueMicrotask(() => {
856
- reactRoot?.unmount();
857
- host.remove();
858
- });
859
- };
860
- }, [options.agentId]);
861
- useLayoutEffect(() => {
862
- const root = portalRootRef.current;
863
- const host = hostRef.current;
864
- if (!root || !host) return;
865
- root.className = designThemeClass ? `ha-root ${designThemeClass}` : "ha-root";
866
- root.dataset["theme"] = options.colorScheme;
867
- root.dataset["viewMode"] = options.viewMode;
868
- root.dataset["position"] = options.launcherPosition;
869
- host.dataset["open"] = isOpen ? "true" : "false";
870
- host.dataset["viewMode"] = options.viewMode;
871
- host.dataset["position"] = options.launcherPosition;
872
- if (options.launcherOffset) {
873
- host.style.setProperty("--ha-launcher-x", `${options.launcherOffset.x}px`);
874
- host.style.setProperty("--ha-launcher-y", `${options.launcherOffset.y}px`);
875
- } else {
876
- host.style.removeProperty("--ha-launcher-x");
877
- host.style.removeProperty("--ha-launcher-y");
878
- }
879
- if (options.viewMode === "sidebar") {
880
- host.style.setProperty(
881
- "--ha-sidebar-width",
882
- `${readSidebarWidth(options.agentId, window.innerWidth)}px`
883
- );
884
- }
885
- const rootProperties = { ...options.themeStyle, ...options.panelStyle };
886
- for (const property of rootPropertyNamesRef.current) {
887
- if (!(property in rootProperties)) root.style.removeProperty(property);
888
- }
889
- for (const [property, value] of Object.entries(rootProperties)) {
890
- root.style.setProperty(property, value);
891
- }
892
- rootPropertyNamesRef.current = Object.keys(rootProperties);
893
- }, [
894
- designThemeClass,
895
- isOpen,
896
- options.colorScheme,
897
- options.agentId,
898
- options.launcherOffset,
899
- options.launcherPosition,
900
- options.panelStyle,
901
- options.themeStyle,
902
- options.viewMode,
903
- portalRoot
904
- ]);
905
- const prepareNextConversation = useCallback(
906
- (conversationId) => {
907
- setFocus(options.agentId, false);
908
- setComposerFileDialogActive(false);
909
- setRuntimeReadyEpoch(null);
910
- setRequestedConversationId(conversationId);
911
- const nextEpoch = conversationEpochRef.current + 1;
912
- conversationEpochRef.current = nextEpoch;
913
- setConversationEpoch(nextEpoch);
914
- },
915
- [options.agentId]
916
- );
917
- const handleRuntimeReady = useCallback((readyEpoch) => {
918
- if (conversationEpochRef.current !== readyEpoch) return;
919
- setHasCompletedInitialLoad(true);
920
- setRuntimeReadyEpoch(readyEpoch);
921
- }, []);
922
- const emitReady = useEffectEvent(() => onReady?.());
923
- useEffect2(() => {
924
- if (!ready || reportedReadyEpochRef.current === conversationEpoch) return;
925
- reportedReadyEpochRef.current = conversationEpoch;
926
- emitReady();
927
- }, [conversationEpoch, ready]);
928
- const hide = useCallback(() => {
929
- shouldOpenRef.current = false;
930
- restoreLauncherFocusRef.current = true;
931
- setOpenRequested(false);
932
- setComposerControlsRevealed(false);
933
- prepareNextConversation(options.startNewConversationOnOpen ? null : void 0);
934
- }, [options.startNewConversationOnOpen, prepareNextConversation]);
935
- useEffect2(() => {
936
- if (isOpen || !ready || !restoreLauncherFocusRef.current) return;
937
- restoreLauncherFocusRef.current = false;
938
- requestAnimationFrame(() => launcherRef.current?.focus());
939
- }, [isOpen, ready]);
940
- const show = useCallback(() => {
941
- shouldOpenRef.current = true;
942
- setOpenRequested(true);
943
- requestRuntime();
944
- }, [requestRuntime]);
945
- const preload = requestRuntime;
946
- const newConversation = useCallback(
947
- (prompt) => {
948
- const submission = prompt ? createSubmittedAgentShellHandoff(prompt) : null;
949
- if (submission) writeAgentShellHandoff(options.agentId, submission);
950
- shouldOpenRef.current = true;
951
- setOpenRequested(true);
952
- setComposerControlsRevealed(false);
953
- requestRuntime();
954
- prepareNextConversation(null);
955
- },
956
- [options.agentId, prepareNextConversation, requestRuntime]
957
- );
958
- const selectConversation = useCallback(
959
- (conversationId) => {
960
- shouldOpenRef.current = true;
961
- setOpenRequested(true);
962
- setComposerControlsRevealed(false);
963
- requestRuntime();
964
- prepareNextConversation(conversationId);
965
- },
966
- [prepareNextConversation, requestRuntime]
967
- );
968
- const toggle = useCallback(() => {
969
- if (isOpen || shouldOpenRef.current) hide();
970
- else show();
971
- }, [hide, isOpen, show]);
972
- const refreshAuth = useCallback(() => {
973
- setHasUnreadMessages(false);
974
- setIdentityReset(false);
975
- setIdentityEpoch((epoch) => epoch + 1);
976
- }, []);
977
- const shutdown = useCallback(() => {
978
- const prefixes = [
979
- `heroui-agent:anonymous:${options.agentId}`,
980
- `heroui-agent:conversation:${options.agentId}:`,
981
- `heroui-agent:history:${options.agentId}:`
982
- ];
983
- for (let index = localStorage.length - 1; index >= 0; index -= 1) {
984
- const key = localStorage.key(index);
985
- if (key && prefixes.some((prefix) => key.startsWith(prefix))) localStorage.removeItem(key);
986
- }
987
- shouldOpenRef.current = false;
988
- setHasUnreadMessages(false);
989
- setOpenRequested(false);
990
- setComposerControlsRevealed(false);
991
- writeOpenState(options.agentId, false);
992
- setIdentityReset(true);
993
- setIdentityEpoch((epoch) => epoch + 1);
994
- prepareNextConversation();
995
- window.setTimeout(() => {
996
- void import("./composer-draft-DTQAEO5K.js").then(
997
- ({ clearAgentComposerDraftsForProject }) => clearAgentComposerDraftsForProject(options.agentId)
998
- ).catch(() => void 0);
999
- }, 0);
1000
- }, [options.agentId, prepareNextConversation]);
1001
- useEffect2(() => {
1002
- const controller = {
1003
- hide,
1004
- newConversation,
1005
- preload,
1006
- ready,
1007
- refreshAuth,
1008
- show,
1009
- shutdown,
1010
- toggle
1011
- };
1012
- controllers.set(options.agentId, controller);
1013
- notifyControllerListeners();
1014
- return () => {
1015
- if (controllers.get(options.agentId) === controller) {
1016
- controllers.delete(options.agentId);
1017
- notifyControllerListeners();
1018
- }
1019
- };
1020
- }, [hide, newConversation, options.agentId, preload, ready, refreshAuth, show, shutdown, toggle]);
1021
- useLayoutEffect(() => {
1022
- const reactRoot = embedReactRootRef.current;
1023
- if (!portalRoot || !reactRoot) return;
1024
- const shellComposer = createShellComposerPresentation({
1025
- onFileDialogActiveChange: setComposerFileDialogActive,
1026
- onIntent: requestRuntime,
1027
- options
1028
- });
1029
- reactRoot.render(
1030
- /* @__PURE__ */ jsxs2(Fragment2, { children: [
1031
- remoteConfigPresentationReady && options.showLauncher && !isOpen ? /* @__PURE__ */ jsxs2(
1032
- "button",
1033
- {
1034
- ref: launcherRef,
1035
- "aria-expanded": false,
1036
- "aria-haspopup": "dialog",
1037
- className: "ha-launcher",
1038
- style: options.launcherStyle,
1039
- type: "button",
1040
- "aria-label": hasUnreadMessages ? "Open data assistant, unread messages" : "Open data assistant",
1041
- onClick: show,
1042
- children: [
1043
- /* @__PURE__ */ jsx4(LauncherIcon, { icon: options.launcherIcon }),
1044
- hasUnreadMessages ? /* @__PURE__ */ jsx4("span", { "aria-hidden": "true", className: "ha-launcher__unread" }) : null
1045
- ]
1046
- }
1047
- ) : null,
1048
- EmbedRuntime && !composerFileDialogActive ? /* @__PURE__ */ jsx4(
1049
- EmbedRuntime,
1050
- {
1051
- composerControlsRevealed,
1052
- conversationEpoch,
1053
- identityEpoch,
1054
- identityReset,
1055
- open: isOpen,
1056
- options,
1057
- requestedConversationId,
1058
- shellComposerEndSlot: shellComposer.end,
1059
- shellComposerFooterSlot: shellComposer.footer,
1060
- showReadyLoader: !hasCompletedInitialLoad && requestedConversationId !== null,
1061
- tokenManager,
1062
- onClose: hide,
1063
- onComposerControlsReveal: revealComposerControls,
1064
- onNewConversation: newConversation,
1065
- onReady: handleRuntimeReady,
1066
- onSelectConversation: selectConversation,
1067
- onUnreadChange: setHasUnreadMessages
1068
- }
1069
- ) : /* @__PURE__ */ jsx4(
1070
- PanelShell,
1071
- {
1072
- agentId: options.agentId,
1073
- defaultExpanded: options.panelExpanded,
1074
- expandable: options.panelExpandable,
1075
- historySlot: /* @__PURE__ */ jsx4(Fragment2, {}),
1076
- modal: options.viewMode !== "sidebar",
1077
- name: "Data assistant",
1078
- open: isOpen,
1079
- onClose: hide,
1080
- children: requestedConversationId === null ? /* @__PURE__ */ jsx4(
1081
- ShellConversation,
1082
- {
1083
- composerConnecting: true,
1084
- agentId: options.agentId,
1085
- composerControlsAvailable: options.composerControlsAvailable,
1086
- composerControlsRevealed,
1087
- composerEndSlot: shellComposer.end,
1088
- composerFooterSlot: shellComposer.footer,
1089
- composerStartSlot: shellComposer.start,
1090
- greeting: options.greeting,
1091
- placeholder: options.composerPlaceholder,
1092
- suggestedPrompts: options.suggestedPrompts ?? [],
1093
- onComposerControlsReveal: revealComposerControls,
1094
- onIntent: requestRuntime
1095
- },
1096
- `shell-${conversationEpoch}`
1097
- ) : /* @__PURE__ */ jsx4(AgentLoadingState, {})
1098
- }
1099
- )
1100
- ] })
1101
- );
1102
- }, [
1103
- EmbedRuntime,
1104
- composerControlsRevealed,
1105
- composerFileDialogActive,
1106
- conversationEpoch,
1107
- handleRuntimeReady,
1108
- hasUnreadMessages,
1109
- hasCompletedInitialLoad,
1110
- hide,
1111
- identityEpoch,
1112
- identityReset,
1113
- isOpen,
1114
- newConversation,
1115
- options,
1116
- portalRoot,
1117
- ready,
1118
- remoteConfigPresentationReady,
1119
- requestedConversationId,
1120
- requestRuntime,
1121
- revealComposerControls,
1122
- selectConversation,
1123
- show,
1124
- tokenManager
1125
- ]);
1126
- return null;
1127
- }
1128
-
1129
- export {
1130
- useAgent,
1131
- HeroUIAgent
1132
- };