@heroui/agent 0.2.0-beta.6 → 0.2.0-beta.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +26 -2
- package/README.md +15 -10
- package/dist/{chart-content-7PZT4YWI.js → chart-content-E4NPTUPR.js} +1 -1
- package/dist/{chunk-MUAFQBVY.js → chunk-CMZDZGUZ.js} +354 -206
- package/dist/chunk-DS4X5K2R.js +56 -0
- package/dist/{chunk-6O3SFXJK.js → chunk-G6GFNSG4.js} +13 -54
- package/dist/chunk-Q7LGTVBL.js +43 -0
- package/dist/chunk-UUPU3MYB.js +42 -0
- package/dist/{chunk-QOCNMON2.js → chunk-W7SCMB3O.js} +561 -362
- package/dist/{component-renderer-PTMCOJHE.js → component-renderer-MDDQMQTU.js} +2107 -1621
- package/dist/composer-draft-DTQAEO5K.js +20 -0
- package/dist/composer-image-draft-IVJ352E6.js +174 -0
- package/dist/contracts.d.ts +50 -19
- package/dist/contracts.js +130 -230
- package/dist/css/index.css +1 -1
- package/dist/{embed-runtime-CR7PQH3Q.js → embed-runtime-VVAGDPYY.js} +3814 -1831
- package/dist/identity-3P8-17km.d.ts +95 -0
- package/dist/index.d.ts +46 -10
- package/dist/index.js +5 -2
- package/dist/next.d.ts +2 -1
- package/dist/next.js +5 -2
- package/dist/server.d.ts +1 -1
- package/dist/server.js +35 -159
- package/package.json +4 -4
- package/dist/identity-Z6i6pL0F.d.ts +0 -166
|
@@ -18,218 +18,27 @@ function resolveDirectToolAction(tools, toolName) {
|
|
|
18
18
|
return tool;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
// src/embed/
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
}
|
|
31
|
-
function readAgentComposerPromptDraft(key, now = Date.now()) {
|
|
32
|
-
if (typeof window === "undefined") return "";
|
|
33
|
-
try {
|
|
34
|
-
const raw = window.localStorage.getItem(key);
|
|
35
|
-
if (!raw) return "";
|
|
36
|
-
const parsed = JSON.parse(raw);
|
|
37
|
-
const isFresh = typeof parsed.savedAt === "number" && now - parsed.savedAt <= AGENT_COMPOSER_DRAFT_MAX_AGE_MS;
|
|
38
|
-
if (!isFresh || typeof parsed.prompt !== "string" || !parsed.prompt.trim()) {
|
|
39
|
-
window.localStorage.removeItem(key);
|
|
40
|
-
return "";
|
|
41
|
-
}
|
|
42
|
-
return parsed.prompt;
|
|
43
|
-
} catch {
|
|
44
|
-
try {
|
|
45
|
-
window.localStorage.removeItem(key);
|
|
46
|
-
} catch {
|
|
47
|
-
}
|
|
48
|
-
return "";
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
function saveAgentComposerPromptDraft(key, prompt, now = Date.now()) {
|
|
52
|
-
if (typeof window === "undefined") return;
|
|
53
|
-
try {
|
|
54
|
-
if (!prompt.trim()) {
|
|
55
|
-
window.localStorage.removeItem(key);
|
|
56
|
-
return;
|
|
57
|
-
}
|
|
58
|
-
window.localStorage.setItem(
|
|
59
|
-
key,
|
|
60
|
-
JSON.stringify({ prompt, savedAt: now })
|
|
61
|
-
);
|
|
62
|
-
} catch {
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
async function readAgentComposerImageDraft(key, now = Date.now()) {
|
|
66
|
-
await pendingImageDraftMutations.get(key);
|
|
67
|
-
const stored = await readImageDraftRecord(key);
|
|
68
|
-
if (!stored) return [];
|
|
69
|
-
const isFresh = now - stored.savedAt <= AGENT_COMPOSER_DRAFT_MAX_AGE_MS;
|
|
70
|
-
const files = stored.files.filter(isPersistableImageFile);
|
|
71
|
-
if (!isFresh || files.length === 0) {
|
|
72
|
-
await queueImageDraftMutation(key, () => deleteImageDraftRecord(key));
|
|
73
|
-
return [];
|
|
74
|
-
}
|
|
75
|
-
return files;
|
|
76
|
-
}
|
|
77
|
-
function saveAgentComposerImageDraft(key, files, now = Date.now()) {
|
|
78
|
-
const images = files.filter(isPersistableImageFile);
|
|
79
|
-
return queueImageDraftMutation(
|
|
80
|
-
key,
|
|
81
|
-
() => images.length > 0 ? writeImageDraftRecord({ files: images, key, savedAt: now }) : deleteImageDraftRecord(key)
|
|
82
|
-
);
|
|
83
|
-
}
|
|
84
|
-
function clearAgentComposerDraft(key) {
|
|
85
|
-
if (typeof window !== "undefined") {
|
|
86
|
-
try {
|
|
87
|
-
window.localStorage.removeItem(key);
|
|
88
|
-
} catch {
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
return queueImageDraftMutation(key, () => deleteImageDraftRecord(key));
|
|
92
|
-
}
|
|
93
|
-
async function clearAgentComposerDraftsForProject(agentId) {
|
|
94
|
-
const prefix = `heroui-agent:conversation:${agentId}:`;
|
|
95
|
-
if (typeof window !== "undefined") {
|
|
96
|
-
try {
|
|
97
|
-
for (let index = window.localStorage.length - 1; index >= 0; index -= 1) {
|
|
98
|
-
const key = window.localStorage.key(index);
|
|
99
|
-
if (key?.startsWith(prefix) && key.includes(AGENT_COMPOSER_DRAFT_MARKER)) {
|
|
100
|
-
window.localStorage.removeItem(key);
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
} catch {
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
const pending = [...pendingImageDraftMutations.entries()].filter(([key]) => key.startsWith(prefix)).map(([, mutation]) => mutation);
|
|
107
|
-
await Promise.all(pending);
|
|
108
|
-
await deleteImageDraftRecordsByPrefix(prefix);
|
|
109
|
-
}
|
|
110
|
-
function isPersistableImageFile(value) {
|
|
111
|
-
return typeof File !== "undefined" && value instanceof File && typeof value.type === "string" && value.type.startsWith("image/");
|
|
112
|
-
}
|
|
113
|
-
function queueImageDraftMutation(key, mutation) {
|
|
114
|
-
const previous = pendingImageDraftMutations.get(key) ?? Promise.resolve();
|
|
115
|
-
const next = previous.catch(() => void 0).then(mutation).catch(() => void 0);
|
|
116
|
-
pendingImageDraftMutations.set(key, next);
|
|
117
|
-
void next.finally(() => {
|
|
118
|
-
if (pendingImageDraftMutations.get(key) === next) pendingImageDraftMutations.delete(key);
|
|
119
|
-
});
|
|
120
|
-
return next;
|
|
121
|
-
}
|
|
122
|
-
function openImageDraftDatabase() {
|
|
123
|
-
if (typeof indexedDB === "undefined") return Promise.resolve(null);
|
|
124
|
-
return new Promise((resolve) => {
|
|
125
|
-
const request = indexedDB.open(AGENT_COMPOSER_DRAFT_DB_NAME, AGENT_COMPOSER_DRAFT_DB_VERSION);
|
|
126
|
-
request.onerror = () => resolve(null);
|
|
127
|
-
request.onupgradeneeded = () => {
|
|
128
|
-
const database = request.result;
|
|
129
|
-
if (!database.objectStoreNames.contains(AGENT_COMPOSER_IMAGE_DRAFT_STORE)) {
|
|
130
|
-
database.createObjectStore(AGENT_COMPOSER_IMAGE_DRAFT_STORE, { keyPath: "key" });
|
|
131
|
-
}
|
|
132
|
-
};
|
|
133
|
-
request.onsuccess = () => resolve(request.result);
|
|
134
|
-
});
|
|
135
|
-
}
|
|
136
|
-
async function withImageDraftStore(mode, run) {
|
|
137
|
-
let database;
|
|
138
|
-
try {
|
|
139
|
-
database = await openImageDraftDatabase();
|
|
140
|
-
} catch {
|
|
141
|
-
return null;
|
|
142
|
-
}
|
|
143
|
-
if (!database) return null;
|
|
144
|
-
try {
|
|
145
|
-
const transaction = database.transaction(AGENT_COMPOSER_IMAGE_DRAFT_STORE, mode);
|
|
146
|
-
const completion = waitForTransaction(transaction);
|
|
147
|
-
const [result] = await Promise.all([
|
|
148
|
-
run(transaction.objectStore(AGENT_COMPOSER_IMAGE_DRAFT_STORE)),
|
|
149
|
-
completion
|
|
150
|
-
]);
|
|
151
|
-
return result;
|
|
152
|
-
} catch {
|
|
153
|
-
return null;
|
|
154
|
-
} finally {
|
|
155
|
-
database.close();
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
async function readImageDraftRecord(key) {
|
|
159
|
-
const result = await withImageDraftStore(
|
|
160
|
-
"readonly",
|
|
161
|
-
(store) => waitForRequest(store.get(key))
|
|
162
|
-
);
|
|
163
|
-
if (typeof result !== "object" || result === null) return null;
|
|
164
|
-
const draft = result;
|
|
165
|
-
if (draft.key !== key || typeof draft.savedAt !== "number" || !Array.isArray(draft.files)) {
|
|
166
|
-
return null;
|
|
167
|
-
}
|
|
168
|
-
return { files: draft.files.filter(isPersistableImageFile), key, savedAt: draft.savedAt };
|
|
169
|
-
}
|
|
170
|
-
async function writeImageDraftRecord(draft) {
|
|
171
|
-
await withImageDraftStore("readwrite", async (store) => {
|
|
172
|
-
await waitForRequest(store.put(draft));
|
|
173
|
-
});
|
|
174
|
-
}
|
|
175
|
-
async function deleteImageDraftRecord(key) {
|
|
176
|
-
await withImageDraftStore("readwrite", async (store) => {
|
|
177
|
-
await waitForRequest(store.delete(key));
|
|
178
|
-
});
|
|
179
|
-
}
|
|
180
|
-
async function deleteImageDraftRecordsByPrefix(prefix) {
|
|
181
|
-
await withImageDraftStore(
|
|
182
|
-
"readwrite",
|
|
183
|
-
(store) => new Promise((resolve, reject) => {
|
|
184
|
-
const request = store.openCursor();
|
|
185
|
-
request.onerror = () => reject(request.error ?? new Error("Unable to clear image drafts"));
|
|
186
|
-
request.onsuccess = () => {
|
|
187
|
-
const cursor = request.result;
|
|
188
|
-
if (!cursor) {
|
|
189
|
-
resolve();
|
|
190
|
-
return;
|
|
191
|
-
}
|
|
192
|
-
if (typeof cursor.key === "string" && cursor.key.startsWith(prefix)) cursor.delete();
|
|
193
|
-
cursor.continue();
|
|
194
|
-
};
|
|
195
|
-
})
|
|
196
|
-
);
|
|
197
|
-
}
|
|
198
|
-
function waitForRequest(request) {
|
|
199
|
-
return new Promise((resolve, reject) => {
|
|
200
|
-
request.onerror = () => reject(request.error ?? new Error("IndexedDB request failed"));
|
|
201
|
-
request.onsuccess = () => resolve(request.result);
|
|
202
|
-
});
|
|
203
|
-
}
|
|
204
|
-
function waitForTransaction(transaction) {
|
|
205
|
-
return new Promise((resolve, reject) => {
|
|
206
|
-
transaction.onabort = () => reject(transaction.error ?? new Error("IndexedDB aborted"));
|
|
207
|
-
transaction.onerror = () => reject(transaction.error ?? new Error("IndexedDB failed"));
|
|
208
|
-
transaction.oncomplete = () => resolve();
|
|
209
|
-
});
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
// src/embed/idle.ts
|
|
213
|
-
function scheduleIdleTask(task, timeoutMs = 3e3) {
|
|
214
|
-
if (typeof window === "undefined") return () => void 0;
|
|
215
|
-
const idle = window.requestIdleCallback;
|
|
216
|
-
if (!idle) {
|
|
217
|
-
const timeout = window.setTimeout(task, Math.min(timeoutMs, 1500));
|
|
218
|
-
return () => window.clearTimeout(timeout);
|
|
219
|
-
}
|
|
220
|
-
const handle = idle(() => task(), { timeout: timeoutMs });
|
|
221
|
-
return () => window.cancelIdleCallback?.(handle);
|
|
21
|
+
// src/embed/agent-loading-state.tsx
|
|
22
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
23
|
+
function AgentLoadingState({
|
|
24
|
+
indicator,
|
|
25
|
+
label = "Loading agent\u2026"
|
|
26
|
+
}) {
|
|
27
|
+
return /* @__PURE__ */ jsxs("div", { "aria-live": "polite", className: "ha-agent-loading", role: "status", children: [
|
|
28
|
+
indicator,
|
|
29
|
+
/* @__PURE__ */ jsx("span", { children: label })
|
|
30
|
+
] });
|
|
222
31
|
}
|
|
223
32
|
|
|
224
33
|
// src/embed/composer-control-tooltip.tsx
|
|
225
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
34
|
+
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
226
35
|
function ComposerControlTooltip({
|
|
227
36
|
children,
|
|
228
37
|
shortcut
|
|
229
38
|
}) {
|
|
230
|
-
return /* @__PURE__ */
|
|
231
|
-
/* @__PURE__ */
|
|
232
|
-
shortcut ? /* @__PURE__ */
|
|
39
|
+
return /* @__PURE__ */ jsxs2("span", { "aria-hidden": "true", className: "ha-control-tooltip", children: [
|
|
40
|
+
/* @__PURE__ */ jsx2("span", { children }),
|
|
41
|
+
shortcut ? /* @__PURE__ */ jsx2("kbd", { className: "ha-control-tooltip__shortcut", children: shortcut }) : null
|
|
233
42
|
] });
|
|
234
43
|
}
|
|
235
44
|
|
|
@@ -265,7 +74,7 @@ function persistSidebarWidth(agentId, width) {
|
|
|
265
74
|
}
|
|
266
75
|
|
|
267
76
|
// src/embed/panel-shell.tsx
|
|
268
|
-
import { jsx as
|
|
77
|
+
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
269
78
|
function PanelShell({
|
|
270
79
|
actionsSlot,
|
|
271
80
|
agentId,
|
|
@@ -275,6 +84,7 @@ function PanelShell({
|
|
|
275
84
|
expandedSidebarSlot,
|
|
276
85
|
expandedTitle,
|
|
277
86
|
historySlot,
|
|
87
|
+
keepMounted = false,
|
|
278
88
|
modal,
|
|
279
89
|
name,
|
|
280
90
|
onClose,
|
|
@@ -351,7 +161,7 @@ function PanelShell({
|
|
|
351
161
|
const first = panel.querySelector(
|
|
352
162
|
"button,textarea,input,[tabindex]:not([tabindex='-1'])"
|
|
353
163
|
);
|
|
354
|
-
first?.focus();
|
|
164
|
+
if (!panel.contains(document.activeElement)) first?.focus();
|
|
355
165
|
const handleKeyDown = (event) => {
|
|
356
166
|
if (!effectiveModal && event.key === "Escape") {
|
|
357
167
|
if (dismissOpenPanelOverlay(panel)) {
|
|
@@ -396,11 +206,11 @@ function PanelShell({
|
|
|
396
206
|
document.body.style.right = previousBodyRight;
|
|
397
207
|
document.body.style.width = previousBodyWidth;
|
|
398
208
|
if (effectiveModal) window.scrollTo(scrollX, scrollY);
|
|
399
|
-
previous?.focus();
|
|
209
|
+
if (document.activeElement === document.body) previous?.focus();
|
|
400
210
|
};
|
|
401
211
|
}, [effectiveModal, open]);
|
|
402
|
-
if (!open) return null;
|
|
403
|
-
return /* @__PURE__ */
|
|
212
|
+
if (!open && !keepMounted) return null;
|
|
213
|
+
return /* @__PURE__ */ jsxs3(
|
|
404
214
|
"dialog",
|
|
405
215
|
{
|
|
406
216
|
ref: panelRef,
|
|
@@ -411,6 +221,7 @@ function PanelShell({
|
|
|
411
221
|
"data-expanded": !isMobileViewport && isExpanded ? "true" : void 0,
|
|
412
222
|
"data-expanded-sidebar": showExpandedSidebar ? "true" : void 0,
|
|
413
223
|
"data-resizing": isResizing ? "true" : void 0,
|
|
224
|
+
hidden: !open,
|
|
414
225
|
onCancel: (event) => {
|
|
415
226
|
event.preventDefault();
|
|
416
227
|
if (Date.now() - overlayEscapeAt.current < 350 || dismissOpenPanelOverlay(panelRef.current)) {
|
|
@@ -420,23 +231,23 @@ function PanelShell({
|
|
|
420
231
|
onClose();
|
|
421
232
|
},
|
|
422
233
|
children: [
|
|
423
|
-
isDesktopSidebar && !isExpanded ? /* @__PURE__ */
|
|
424
|
-
showExpandedSidebar ? /* @__PURE__ */
|
|
425
|
-
/* @__PURE__ */
|
|
426
|
-
/* @__PURE__ */
|
|
427
|
-
showExpandedSidebar ? /* @__PURE__ */
|
|
428
|
-
/* @__PURE__ */
|
|
429
|
-
showExpandedSidebar ? null : actionsSlot ?? (onNewConversation ? /* @__PURE__ */
|
|
234
|
+
isDesktopSidebar && !isExpanded ? /* @__PURE__ */ jsx3(SidebarResizeHandle, { agentId, panelRef }) : null,
|
|
235
|
+
showExpandedSidebar ? /* @__PURE__ */ jsx3("aside", { "aria-label": "Chat history", className: "ha-expanded-sidebar", children: expandedSidebarSlot }) : null,
|
|
236
|
+
/* @__PURE__ */ jsxs3("div", { className: "ha-panel-main", children: [
|
|
237
|
+
/* @__PURE__ */ jsxs3("header", { className: "ha-header", children: [
|
|
238
|
+
showExpandedSidebar ? /* @__PURE__ */ jsx3("span", { className: "ha-session-title ha-expanded-chat-title", children: expandedTitle ?? name }) : historySlot ?? /* @__PURE__ */ jsx3("strong", { children: name }),
|
|
239
|
+
/* @__PURE__ */ jsxs3("div", { className: "ha-header-actions", children: [
|
|
240
|
+
showExpandedSidebar ? null : actionsSlot ?? (onNewConversation ? /* @__PURE__ */ jsx3(
|
|
430
241
|
"button",
|
|
431
242
|
{
|
|
432
243
|
"aria-label": "New chat",
|
|
433
244
|
className: "ha-icon-button ha-new-chat-button",
|
|
434
245
|
type: "button",
|
|
435
246
|
onClick: onNewConversation,
|
|
436
|
-
children: /* @__PURE__ */
|
|
247
|
+
children: /* @__PURE__ */ jsx3(PlusGlyph, {})
|
|
437
248
|
}
|
|
438
249
|
) : null),
|
|
439
|
-
canExpand ? /* @__PURE__ */
|
|
250
|
+
canExpand ? /* @__PURE__ */ jsx3(
|
|
440
251
|
"button",
|
|
441
252
|
{
|
|
442
253
|
"aria-expanded": isExpanded,
|
|
@@ -447,10 +258,10 @@ function PanelShell({
|
|
|
447
258
|
setIsResizing(true);
|
|
448
259
|
setIsExpanded((expanded) => !expanded);
|
|
449
260
|
},
|
|
450
|
-
children: isExpanded ? /* @__PURE__ */
|
|
261
|
+
children: isExpanded ? /* @__PURE__ */ jsx3(ChevronsCollapseUpRight, { "aria-hidden": "true" }) : /* @__PURE__ */ jsx3(ChevronsExpandUpRight, { "aria-hidden": "true" })
|
|
451
262
|
}
|
|
452
263
|
) : null,
|
|
453
|
-
/* @__PURE__ */
|
|
264
|
+
/* @__PURE__ */ jsxs3(
|
|
454
265
|
"button",
|
|
455
266
|
{
|
|
456
267
|
"aria-keyshortcuts": "Escape",
|
|
@@ -461,15 +272,15 @@ function PanelShell({
|
|
|
461
272
|
type: "button",
|
|
462
273
|
onClick: onClose,
|
|
463
274
|
children: [
|
|
464
|
-
/* @__PURE__ */
|
|
465
|
-
/* @__PURE__ */
|
|
275
|
+
/* @__PURE__ */ jsx3(CloseGlyph, {}),
|
|
276
|
+
/* @__PURE__ */ jsx3(ComposerControlTooltip, { shortcut: "ESC", children: "Close assistant" })
|
|
466
277
|
]
|
|
467
278
|
}
|
|
468
279
|
)
|
|
469
280
|
] })
|
|
470
281
|
] }),
|
|
471
282
|
children,
|
|
472
|
-
/* @__PURE__ */
|
|
283
|
+
/* @__PURE__ */ jsx3("div", { className: "ha-overlay-portal", "data-agent-overlay-portal": "" })
|
|
473
284
|
] })
|
|
474
285
|
]
|
|
475
286
|
}
|
|
@@ -496,8 +307,9 @@ function SidebarResizeHandle({
|
|
|
496
307
|
const dragRef = useRef(null);
|
|
497
308
|
const applyWidth = useCallback(
|
|
498
309
|
(nextWidth) => {
|
|
499
|
-
const
|
|
500
|
-
const
|
|
310
|
+
const panel = panelRef.current;
|
|
311
|
+
const root = panel?.getRootNode();
|
|
312
|
+
const host = root instanceof ShadowRoot ? root.host : panel?.closest("[data-heroui-agent]");
|
|
501
313
|
host?.style.setProperty("--ha-sidebar-width", `${nextWidth}px`);
|
|
502
314
|
if (window.innerWidth >= 640) {
|
|
503
315
|
document.documentElement.style.marginRight = `${Math.min(nextWidth, window.innerWidth)}px`;
|
|
@@ -517,7 +329,7 @@ function SidebarResizeHandle({
|
|
|
517
329
|
);
|
|
518
330
|
return (
|
|
519
331
|
// eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions -- A focusable separator is the WAI-ARIA "window splitter" pattern: it is interactive by specification even though jsx-a11y does not model it.
|
|
520
|
-
/* @__PURE__ */
|
|
332
|
+
/* @__PURE__ */ jsx3(
|
|
521
333
|
"div",
|
|
522
334
|
{
|
|
523
335
|
"aria-label": "Resize assistant panel",
|
|
@@ -539,6 +351,7 @@ function SidebarResizeHandle({
|
|
|
539
351
|
if (!drag) return;
|
|
540
352
|
dragRef.current = null;
|
|
541
353
|
delete event.currentTarget.dataset["resizing"];
|
|
354
|
+
if (panelRef.current) delete panelRef.current.dataset["dragResizing"];
|
|
542
355
|
document.documentElement.style.transition = drag.pageTransition;
|
|
543
356
|
resizeTo(drag.startWidth, false);
|
|
544
357
|
},
|
|
@@ -548,32 +361,35 @@ function SidebarResizeHandle({
|
|
|
548
361
|
event.currentTarget.setPointerCapture(event.pointerId);
|
|
549
362
|
event.currentTarget.dataset["resizing"] = "true";
|
|
550
363
|
dragRef.current = {
|
|
364
|
+
currentWidth: width,
|
|
551
365
|
pageTransition: document.documentElement.style.transition,
|
|
552
366
|
startWidth: width,
|
|
553
367
|
startX: event.clientX
|
|
554
368
|
};
|
|
555
369
|
document.documentElement.style.transition = "none";
|
|
370
|
+
if (panelRef.current) panelRef.current.dataset["dragResizing"] = "true";
|
|
556
371
|
},
|
|
557
372
|
onPointerMove: (event) => {
|
|
558
373
|
const drag = dragRef.current;
|
|
559
374
|
if (!drag) return;
|
|
560
|
-
resizeTo(drag.startWidth + (drag.startX - event.clientX), false);
|
|
375
|
+
drag.currentWidth = resizeTo(drag.startWidth + (drag.startX - event.clientX), false);
|
|
561
376
|
},
|
|
562
377
|
onPointerUp: (event) => {
|
|
563
378
|
const drag = dragRef.current;
|
|
564
379
|
if (!drag) return;
|
|
565
380
|
dragRef.current = null;
|
|
566
381
|
delete event.currentTarget.dataset["resizing"];
|
|
382
|
+
if (panelRef.current) delete panelRef.current.dataset["dragResizing"];
|
|
567
383
|
event.currentTarget.releasePointerCapture(event.pointerId);
|
|
568
384
|
document.documentElement.style.transition = drag.pageTransition;
|
|
569
|
-
persistSidebarWidth(agentId,
|
|
385
|
+
persistSidebarWidth(agentId, drag.currentWidth);
|
|
570
386
|
}
|
|
571
387
|
}
|
|
572
388
|
)
|
|
573
389
|
);
|
|
574
390
|
}
|
|
575
391
|
function CloseGlyph() {
|
|
576
|
-
return /* @__PURE__ */
|
|
392
|
+
return /* @__PURE__ */ jsx3("svg", { "aria-hidden": "true", fill: "none", height: "18", viewBox: "0 0 18 18", width: "18", children: /* @__PURE__ */ jsx3(
|
|
577
393
|
"path",
|
|
578
394
|
{
|
|
579
395
|
d: "m4.25 4.25 9.5 9.5m0-9.5-9.5 9.5",
|
|
@@ -584,7 +400,192 @@ function CloseGlyph() {
|
|
|
584
400
|
) });
|
|
585
401
|
}
|
|
586
402
|
function PlusGlyph() {
|
|
587
|
-
return /* @__PURE__ */
|
|
403
|
+
return /* @__PURE__ */ jsx3("svg", { "aria-hidden": "true", fill: "none", height: "18", viewBox: "0 0 18 18", width: "18", children: /* @__PURE__ */ jsx3("path", { d: "M9 4v10M4 9h10", stroke: "currentColor", strokeLinecap: "round", strokeWidth: "1.6" }) });
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
// src/contracts/models.ts
|
|
407
|
+
var AGENT_MODEL_IDS = [
|
|
408
|
+
"moonshotai/Kimi-K3",
|
|
409
|
+
"openai/gpt-5.6-luna",
|
|
410
|
+
"openai/gpt-5.6-terra",
|
|
411
|
+
"openai/gpt-5.6-sol",
|
|
412
|
+
"google/gemini-3.6-flash",
|
|
413
|
+
"anthropic/claude-sonnet-5",
|
|
414
|
+
"anthropic/claude-opus-4.8"
|
|
415
|
+
];
|
|
416
|
+
var LEGACY_AGENT_MODEL_IDS = {
|
|
417
|
+
"google/gemini-3.5-flash": "google/gemini-3.6-flash"
|
|
418
|
+
};
|
|
419
|
+
function resolveAgentModelId(value) {
|
|
420
|
+
return LEGACY_AGENT_MODEL_IDS[value] ?? value;
|
|
421
|
+
}
|
|
422
|
+
var DEFAULT_AGENT_PICKER_MODEL_ID = "openai/gpt-5.6-luna";
|
|
423
|
+
var AGENT_MODEL_OPTIONS = [
|
|
424
|
+
{
|
|
425
|
+
description: "Flagship model for coding, reasoning, and knowledge work",
|
|
426
|
+
id: "moonshotai/Kimi-K3",
|
|
427
|
+
label: "Kimi K3",
|
|
428
|
+
provider: "Moonshot AI",
|
|
429
|
+
tier: "light"
|
|
430
|
+
},
|
|
431
|
+
{
|
|
432
|
+
description: "Fast answers and lightweight agent workflows",
|
|
433
|
+
id: "openai/gpt-5.6-luna",
|
|
434
|
+
label: "GPT-5.6 Luna",
|
|
435
|
+
provider: "OpenAI",
|
|
436
|
+
tier: "light"
|
|
437
|
+
},
|
|
438
|
+
{
|
|
439
|
+
description: "Balanced reasoning for everyday agent tasks",
|
|
440
|
+
id: "openai/gpt-5.6-terra",
|
|
441
|
+
label: "GPT-5.6 Terra",
|
|
442
|
+
provider: "OpenAI",
|
|
443
|
+
tier: "codegen"
|
|
444
|
+
},
|
|
445
|
+
{
|
|
446
|
+
description: "Deep reasoning for complex, multi-step analysis",
|
|
447
|
+
id: "openai/gpt-5.6-sol",
|
|
448
|
+
label: "GPT-5.6 Sol",
|
|
449
|
+
provider: "OpenAI",
|
|
450
|
+
tier: "complex"
|
|
451
|
+
},
|
|
452
|
+
{
|
|
453
|
+
description: "Fast multimodal analysis with a large context window",
|
|
454
|
+
id: "google/gemini-3.6-flash",
|
|
455
|
+
label: "Gemini 3.6 Flash",
|
|
456
|
+
provider: "Google",
|
|
457
|
+
tier: "light"
|
|
458
|
+
},
|
|
459
|
+
{
|
|
460
|
+
description: "Strong agentic reasoning and polished UI decisions",
|
|
461
|
+
id: "anthropic/claude-sonnet-5",
|
|
462
|
+
label: "Claude Sonnet 5",
|
|
463
|
+
provider: "Anthropic",
|
|
464
|
+
tier: "codegen"
|
|
465
|
+
},
|
|
466
|
+
{
|
|
467
|
+
description: "Highest-capability Claude for difficult research and analysis",
|
|
468
|
+
id: "anthropic/claude-opus-4.8",
|
|
469
|
+
label: "Claude Opus 4.8",
|
|
470
|
+
provider: "Anthropic",
|
|
471
|
+
tier: "complex"
|
|
472
|
+
}
|
|
473
|
+
];
|
|
474
|
+
var AGENT_MODEL_ID_SET = new Set(AGENT_MODEL_IDS);
|
|
475
|
+
function isAgentModelId(value) {
|
|
476
|
+
return typeof value === "string" && AGENT_MODEL_ID_SET.has(value);
|
|
477
|
+
}
|
|
478
|
+
function getAgentModelTier(modelId) {
|
|
479
|
+
const resolved = modelId ? resolveAgentModelId(modelId) : void 0;
|
|
480
|
+
return AGENT_MODEL_OPTIONS.find((option) => option.id === resolved)?.tier ?? "light";
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
// src/embed/shell-handoff.ts
|
|
484
|
+
function createSubmittedAgentShellHandoff(prompt) {
|
|
485
|
+
const startedAt = performance.now();
|
|
486
|
+
const startedAtWallClock = Date.now();
|
|
487
|
+
const trimmedPrompt = prompt.trim();
|
|
488
|
+
if (!trimmedPrompt) return null;
|
|
489
|
+
return {
|
|
490
|
+
messageId: crypto.randomUUID(),
|
|
491
|
+
prompt: trimmedPrompt,
|
|
492
|
+
startedAt,
|
|
493
|
+
startedAtWallClock,
|
|
494
|
+
submitted: true
|
|
495
|
+
};
|
|
496
|
+
}
|
|
497
|
+
var handoffs = /* @__PURE__ */ new Map();
|
|
498
|
+
var attachmentHandoffs = /* @__PURE__ */ new Map();
|
|
499
|
+
var SHELL_DRAFT_MAX_AGE_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
500
|
+
var focus = /* @__PURE__ */ new Map();
|
|
501
|
+
function shellDraftStorageKey(agentId) {
|
|
502
|
+
return `heroui-agent:shell-draft:${agentId}:composer-draft:v1`;
|
|
503
|
+
}
|
|
504
|
+
function saveShellDraft(agentId, prompt) {
|
|
505
|
+
try {
|
|
506
|
+
const key = shellDraftStorageKey(agentId);
|
|
507
|
+
if (prompt.trim()) localStorage.setItem(key, JSON.stringify({ prompt, savedAt: Date.now() }));
|
|
508
|
+
else localStorage.removeItem(key);
|
|
509
|
+
} catch {
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
function readShellDraft(agentId) {
|
|
513
|
+
const key = shellDraftStorageKey(agentId);
|
|
514
|
+
try {
|
|
515
|
+
const draft = JSON.parse(localStorage.getItem(key) ?? "null");
|
|
516
|
+
if (draft && typeof draft.prompt === "string" && draft.prompt.trim() && typeof draft.savedAt === "number" && Date.now() - draft.savedAt <= SHELL_DRAFT_MAX_AGE_MS) {
|
|
517
|
+
return draft.prompt;
|
|
518
|
+
}
|
|
519
|
+
localStorage.removeItem(key);
|
|
520
|
+
} catch {
|
|
521
|
+
}
|
|
522
|
+
return "";
|
|
523
|
+
}
|
|
524
|
+
function writeAgentShellHandoff(agentId, handoff) {
|
|
525
|
+
if (!handoff.prompt.trim() && !handoff.submitted) {
|
|
526
|
+
handoffs.delete(agentId);
|
|
527
|
+
saveShellDraft(agentId, "");
|
|
528
|
+
return;
|
|
529
|
+
}
|
|
530
|
+
handoffs.set(agentId, handoff);
|
|
531
|
+
if (!handoff.submitted) {
|
|
532
|
+
saveShellDraft(agentId, handoff.prompt);
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
function readAgentShellHandoff(agentId) {
|
|
536
|
+
const buffered = handoffs.get(agentId);
|
|
537
|
+
if (buffered) return buffered;
|
|
538
|
+
const persisted = readShellDraft(agentId);
|
|
539
|
+
return persisted ? { prompt: persisted, submitted: false } : void 0;
|
|
540
|
+
}
|
|
541
|
+
function markAgentShellFeedbackPainted(agentId, messageId, paintedAt) {
|
|
542
|
+
const handoff = handoffs.get(agentId);
|
|
543
|
+
if (!handoff?.submitted || handoff.messageId !== messageId || handoff.firstFeedbackPaintedAt !== void 0) {
|
|
544
|
+
return;
|
|
545
|
+
}
|
|
546
|
+
handoffs.set(agentId, { ...handoff, firstFeedbackPaintedAt: paintedAt });
|
|
547
|
+
}
|
|
548
|
+
function takeAgentShellHandoff(agentId) {
|
|
549
|
+
const handoff = readAgentShellHandoff(agentId);
|
|
550
|
+
handoffs.delete(agentId);
|
|
551
|
+
saveShellDraft(agentId, "");
|
|
552
|
+
return handoff;
|
|
553
|
+
}
|
|
554
|
+
function setFocus(agentId, focused, textarea) {
|
|
555
|
+
if (focused) {
|
|
556
|
+
focus.set(agentId, [
|
|
557
|
+
textarea?.selectionStart ?? 0,
|
|
558
|
+
textarea?.selectionEnd ?? 0,
|
|
559
|
+
textarea?.selectionDirection ?? "none"
|
|
560
|
+
]);
|
|
561
|
+
} else {
|
|
562
|
+
focus.delete(agentId);
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
function restoreFocus(agentId, textarea) {
|
|
566
|
+
const selection = focus.get(agentId);
|
|
567
|
+
if (!selection || !textarea) return;
|
|
568
|
+
textarea.focus({ preventScroll: true });
|
|
569
|
+
const start = Math.min(selection[0], textarea.value.length);
|
|
570
|
+
const end = Math.min(selection[1], textarea.value.length);
|
|
571
|
+
textarea.setSelectionRange(start, end, selection[2]);
|
|
572
|
+
focus.set(agentId, [start, end, selection[2]]);
|
|
573
|
+
}
|
|
574
|
+
function containsComposerFocus(composer, target) {
|
|
575
|
+
if (!(target instanceof Node)) return false;
|
|
576
|
+
return composer.contains(target) || composer.closest(".ha-composer-wrap")?.querySelector(".ha-footnote")?.contains(target) === true || composer.closest(".ha-root")?.querySelector(".ha-overlay-portal")?.contains(target) === true;
|
|
577
|
+
}
|
|
578
|
+
function writeAgentShellAttachments(agentId, files) {
|
|
579
|
+
if (files.length === 0) attachmentHandoffs.delete(agentId);
|
|
580
|
+
else attachmentHandoffs.set(agentId, files);
|
|
581
|
+
}
|
|
582
|
+
function readAgentShellAttachments(agentId) {
|
|
583
|
+
return attachmentHandoffs.get(agentId) ?? [];
|
|
584
|
+
}
|
|
585
|
+
function takeAgentShellAttachments(agentId) {
|
|
586
|
+
const files = readAgentShellAttachments(agentId);
|
|
587
|
+
attachmentHandoffs.delete(agentId);
|
|
588
|
+
return files;
|
|
588
589
|
}
|
|
589
590
|
|
|
590
591
|
// src/embed/composer-textarea.ts
|
|
@@ -643,10 +644,10 @@ function resizeComposerTextarea(textarea, {
|
|
|
643
644
|
}
|
|
644
645
|
|
|
645
646
|
// src/embed/powered-by-hero.tsx
|
|
646
|
-
import { jsx as
|
|
647
|
+
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
647
648
|
var POWERED_BY_HERO_URL = "https://heroui.pro/?utm_source=heroui-agent&utm_medium=referral&utm_campaign=powered-by-hero";
|
|
648
649
|
function PoweredByHero() {
|
|
649
|
-
return /* @__PURE__ */
|
|
650
|
+
return /* @__PURE__ */ jsxs4(
|
|
650
651
|
"a",
|
|
651
652
|
{
|
|
652
653
|
"aria-label": "Powered by HeroUI Pro (opens in a new tab)",
|
|
@@ -655,16 +656,16 @@ function PoweredByHero() {
|
|
|
655
656
|
rel: "noopener noreferrer",
|
|
656
657
|
target: "_blank",
|
|
657
658
|
children: [
|
|
658
|
-
/* @__PURE__ */
|
|
659
|
-
/* @__PURE__ */
|
|
660
|
-
/* @__PURE__ */
|
|
659
|
+
/* @__PURE__ */ jsx4("span", { children: "Powered by" }),
|
|
660
|
+
/* @__PURE__ */ jsxs4("svg", { "aria-hidden": "true", className: "ha-powered-by-logo", fill: "none", viewBox: "0 0 140 44", children: [
|
|
661
|
+
/* @__PURE__ */ jsx4(
|
|
661
662
|
"path",
|
|
662
663
|
{
|
|
663
664
|
d: "M.678 11.385V24.04c0 .599.307 1.155.813 1.471l8.628 5.396c1.15.719 2.639-.11 2.639-1.47V18.798c0-.612.322-1.18.847-1.491l5.263-3.13v27.267c0 1.355 1.48 2.186 2.63 1.476l8.905-5.497a1.72 1.72 0 0 0 .822-1.476V9.765c0-1.349-1.467-2.18-2.618-1.484l-9.74 5.897V2.556c0-1.345-1.46-2.177-2.61-1.488L1.52 9.897a1.72 1.72 0 0 0-.842 1.488Z",
|
|
664
665
|
fill: "currentColor"
|
|
665
666
|
}
|
|
666
667
|
),
|
|
667
|
-
/* @__PURE__ */
|
|
668
|
+
/* @__PURE__ */ jsx4(
|
|
668
669
|
"path",
|
|
669
670
|
{
|
|
670
671
|
d: "M63.876 24.071c0-3.59-1.468-5.246-4.405-5.246-3.363 0-5.732 2.255-5.732 7.316v11.595h-6.063V5.528h6.063v11.779c1.468-2.393 3.884-3.59 7.2-3.59 5.637 0 8.953 3.451 8.953 9.25v14.769h-6.016V24.071ZM84.9 38.473c-7.533 0-12.317-4.877-12.317-12.378 0-7.408 4.737-12.378 12.317-12.378 8.195 0 12.648 5.798 11.416 13.942H78.647c.331 3.865 2.605 6.075 6.253 6.075 2.984 0 4.784-1.52 5.258-3.037h6.016c-.947 4.509-5.115 7.776-11.274 7.776ZM78.789 23.657h11.653c-.047-3.175-2.132-5.338-5.685-5.338-3.174 0-5.4 1.84-5.968 5.338ZM99.623 20.344c0-3.82 2.131-5.89 6.205-5.89h7.77v4.97h-7.912v18.312h-6.063V20.344ZM126.863 38.473c-7.674 0-12.553-4.924-12.553-12.378 0-7.454 4.879-12.378 12.553-12.378 7.58 0 12.459 4.924 12.459 12.378 0 7.454-4.88 12.378-12.46 12.378Zm0-5.016c3.79 0 6.3-2.898 6.3-7.362 0-4.463-2.51-7.408-6.3-7.408-3.838 0-6.348 2.945-6.348 7.408 0 4.464 2.51 7.362 6.348 7.362Z",
|
|
@@ -677,43 +678,11 @@ function PoweredByHero() {
|
|
|
677
678
|
);
|
|
678
679
|
}
|
|
679
680
|
|
|
680
|
-
// src/embed/shell-handoff.ts
|
|
681
|
-
var handoffs = /* @__PURE__ */ new Map();
|
|
682
|
-
function shellDraftStorageKey(agentId) {
|
|
683
|
-
return `heroui-agent:shell-draft:${agentId}:composer-draft:v1`;
|
|
684
|
-
}
|
|
685
|
-
function writeAgentShellHandoff(agentId, handoff) {
|
|
686
|
-
if (!handoff.prompt.trim() && !handoff.submitted) {
|
|
687
|
-
handoffs.delete(agentId);
|
|
688
|
-
saveAgentComposerPromptDraft(shellDraftStorageKey(agentId), "");
|
|
689
|
-
return;
|
|
690
|
-
}
|
|
691
|
-
handoffs.set(agentId, handoff);
|
|
692
|
-
if (!handoff.submitted) {
|
|
693
|
-
saveAgentComposerPromptDraft(shellDraftStorageKey(agentId), handoff.prompt);
|
|
694
|
-
}
|
|
695
|
-
}
|
|
696
|
-
function readAgentShellHandoff(agentId) {
|
|
697
|
-
const buffered = handoffs.get(agentId);
|
|
698
|
-
if (buffered) return buffered;
|
|
699
|
-
const persisted = readAgentComposerPromptDraft(shellDraftStorageKey(agentId));
|
|
700
|
-
return persisted ? { prompt: persisted, submitted: false } : void 0;
|
|
701
|
-
}
|
|
702
|
-
function takeAgentShellHandoff(agentId) {
|
|
703
|
-
const handoff = readAgentShellHandoff(agentId);
|
|
704
|
-
handoffs.delete(agentId);
|
|
705
|
-
saveAgentComposerPromptDraft(shellDraftStorageKey(agentId), "");
|
|
706
|
-
return handoff;
|
|
707
|
-
}
|
|
708
|
-
|
|
709
681
|
// src/embed/permissions.ts
|
|
710
682
|
var AGENT_PERMISSION_MODES = /* @__PURE__ */ new Set(["ask", "auto", "full"]);
|
|
711
683
|
function resolveAgentPermissionMode(value) {
|
|
712
684
|
return AGENT_PERMISSION_MODES.has(value) ? value : "auto";
|
|
713
685
|
}
|
|
714
|
-
function shouldRestoreActiveAgentPermissionMode(bootstrapStatus, hasUnresolvedClientTool) {
|
|
715
|
-
return hasUnresolvedClientTool || bootstrapStatus === "pending" || bootstrapStatus === "streaming";
|
|
716
|
-
}
|
|
717
686
|
function agentPermissionModeStorageKey(conversationStorageKey, conversationId) {
|
|
718
687
|
return `${conversationStorageKey}:permission-mode:${conversationId}:v1`;
|
|
719
688
|
}
|
|
@@ -838,81 +807,103 @@ function buildThemeStyle(theme) {
|
|
|
838
807
|
return style;
|
|
839
808
|
}
|
|
840
809
|
|
|
841
|
-
// src/contracts/
|
|
842
|
-
var
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
var
|
|
852
|
-
|
|
810
|
+
// src/contracts/runtime.ts
|
|
811
|
+
var HEROUI_AGENT_RUNTIME_TIMING_EVENT = "heroui-agent:runtime-timing";
|
|
812
|
+
var HEROUI_AGENT_TURN_ADMITTED_FRAME_TYPE = "heroui_agent_turn_admitted";
|
|
813
|
+
var HEROUI_AGENT_TURN_ADMISSION_STATUS_METHOD = "getTurnAdmissionStatuses";
|
|
814
|
+
var HEROUI_AGENT_TURN_ADMISSION_STATUS_MAX_IDS = 50;
|
|
815
|
+
|
|
816
|
+
// ../agent-client/src/token-manager.ts
|
|
817
|
+
function anonymousStorageKey(agentId) {
|
|
818
|
+
return `heroui-agent:anonymous:${agentId}`;
|
|
819
|
+
}
|
|
820
|
+
var EmbedSessionManager = class {
|
|
821
|
+
constructor(agentId, getAuthToken) {
|
|
822
|
+
this.agentId = agentId;
|
|
823
|
+
this.getAuthToken = getAuthToken;
|
|
824
|
+
}
|
|
825
|
+
cached = null;
|
|
826
|
+
generation = 0;
|
|
827
|
+
pending = null;
|
|
828
|
+
clear() {
|
|
829
|
+
this.generation += 1;
|
|
830
|
+
this.cached = null;
|
|
831
|
+
this.pending = null;
|
|
832
|
+
}
|
|
833
|
+
/**
|
|
834
|
+
* Forgets both the cached credential and the browser's anonymous id, so the
|
|
835
|
+
* next request represents a brand-new person. Used on logout to stop a
|
|
836
|
+
* shared device from attributing the next visitor to the previous user.
|
|
837
|
+
*/
|
|
838
|
+
reset() {
|
|
839
|
+
this.clear();
|
|
840
|
+
try {
|
|
841
|
+
localStorage.removeItem(anonymousStorageKey(this.agentId));
|
|
842
|
+
} catch {
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
async get() {
|
|
846
|
+
if (this.cached && this.expiresAt(this.cached) > Date.now() + 6e4) {
|
|
847
|
+
return this.cached.token;
|
|
848
|
+
}
|
|
849
|
+
const generation = this.generation;
|
|
850
|
+
const pending = this.pending ?? this.refresh();
|
|
851
|
+
if (!this.pending) this.pending = pending;
|
|
852
|
+
try {
|
|
853
|
+
const result = await pending;
|
|
854
|
+
if (generation !== this.generation) return this.get();
|
|
855
|
+
this.cached = result;
|
|
856
|
+
return result.token;
|
|
857
|
+
} finally {
|
|
858
|
+
if (this.pending === pending) this.pending = null;
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
async subjectHash() {
|
|
862
|
+
const token = await this.get();
|
|
863
|
+
const payload = decodeTokenPayload(token);
|
|
864
|
+
const subject = typeof payload["sub"] === "string" ? payload["sub"] : "anonymous";
|
|
865
|
+
const digest = await crypto.subtle.digest(
|
|
866
|
+
"SHA-256",
|
|
867
|
+
new TextEncoder().encode(`${this.agentId}:${subject}`)
|
|
868
|
+
);
|
|
869
|
+
return Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, "0")).join("").slice(0, 24);
|
|
870
|
+
}
|
|
871
|
+
anonymousId() {
|
|
872
|
+
const key = anonymousStorageKey(this.agentId);
|
|
873
|
+
try {
|
|
874
|
+
const existing = localStorage.getItem(key);
|
|
875
|
+
if (existing) return existing;
|
|
876
|
+
const created = crypto.randomUUID();
|
|
877
|
+
localStorage.setItem(key, created);
|
|
878
|
+
return created;
|
|
879
|
+
} catch {
|
|
880
|
+
return crypto.randomUUID();
|
|
881
|
+
}
|
|
882
|
+
}
|
|
883
|
+
expiresAt(response) {
|
|
884
|
+
return response.expiresAt;
|
|
885
|
+
}
|
|
886
|
+
async refresh() {
|
|
887
|
+
const result = await this.getAuthToken({
|
|
888
|
+
agentId: this.agentId,
|
|
889
|
+
anonymousId: this.anonymousId()
|
|
890
|
+
});
|
|
891
|
+
if (!result || typeof result.token !== "string" || !result.token.trim() || typeof result.expiresAt !== "number" || !Number.isFinite(result.expiresAt) || result.expiresAt <= 0) {
|
|
892
|
+
throw new Error("Auth token callback returned invalid data");
|
|
893
|
+
}
|
|
894
|
+
return { expiresAt: result.expiresAt, token: result.token };
|
|
895
|
+
}
|
|
853
896
|
};
|
|
854
|
-
function
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
provider: "Moonshot AI",
|
|
864
|
-
tier: "light"
|
|
865
|
-
},
|
|
866
|
-
{
|
|
867
|
-
description: "Fast answers and lightweight agent workflows",
|
|
868
|
-
id: "openai/gpt-5.6-luna",
|
|
869
|
-
label: "GPT-5.6 Luna",
|
|
870
|
-
provider: "OpenAI",
|
|
871
|
-
tier: "light"
|
|
872
|
-
},
|
|
873
|
-
{
|
|
874
|
-
description: "Balanced reasoning for everyday agent tasks",
|
|
875
|
-
id: "openai/gpt-5.6-terra",
|
|
876
|
-
label: "GPT-5.6 Terra",
|
|
877
|
-
provider: "OpenAI",
|
|
878
|
-
tier: "codegen"
|
|
879
|
-
},
|
|
880
|
-
{
|
|
881
|
-
description: "Deep reasoning for complex, multi-step analysis",
|
|
882
|
-
id: "openai/gpt-5.6-sol",
|
|
883
|
-
label: "GPT-5.6 Sol",
|
|
884
|
-
provider: "OpenAI",
|
|
885
|
-
tier: "complex"
|
|
886
|
-
},
|
|
887
|
-
{
|
|
888
|
-
description: "Fast multimodal analysis with a large context window",
|
|
889
|
-
id: "google/gemini-3.6-flash",
|
|
890
|
-
label: "Gemini 3.6 Flash",
|
|
891
|
-
provider: "Google",
|
|
892
|
-
tier: "light"
|
|
893
|
-
},
|
|
894
|
-
{
|
|
895
|
-
description: "Strong agentic reasoning and polished UI decisions",
|
|
896
|
-
id: "anthropic/claude-sonnet-5",
|
|
897
|
-
label: "Claude Sonnet 5",
|
|
898
|
-
provider: "Anthropic",
|
|
899
|
-
tier: "codegen"
|
|
900
|
-
},
|
|
901
|
-
{
|
|
902
|
-
description: "Highest-capability Claude for difficult research and analysis",
|
|
903
|
-
id: "anthropic/claude-opus-4.8",
|
|
904
|
-
label: "Claude Opus 4.8",
|
|
905
|
-
provider: "Anthropic",
|
|
906
|
-
tier: "complex"
|
|
897
|
+
function decodeTokenPayload(token) {
|
|
898
|
+
try {
|
|
899
|
+
const payload = token.split(".")[1];
|
|
900
|
+
if (!payload) return {};
|
|
901
|
+
const normalized = payload.replace(/-/g, "+").replace(/_/g, "/");
|
|
902
|
+
const padded = normalized.padEnd(Math.ceil(normalized.length / 4) * 4, "=");
|
|
903
|
+
return JSON.parse(atob(padded));
|
|
904
|
+
} catch {
|
|
905
|
+
return {};
|
|
907
906
|
}
|
|
908
|
-
];
|
|
909
|
-
var AGENT_MODEL_ID_SET = new Set(AGENT_MODEL_IDS);
|
|
910
|
-
function isAgentModelId(value) {
|
|
911
|
-
return typeof value === "string" && AGENT_MODEL_ID_SET.has(value);
|
|
912
|
-
}
|
|
913
|
-
function getAgentModelTier(modelId) {
|
|
914
|
-
const resolved = modelId ? resolveAgentModelId(modelId) : void 0;
|
|
915
|
-
return AGENT_MODEL_OPTIONS.find((option) => option.id === resolved)?.tier ?? "light";
|
|
916
907
|
}
|
|
917
908
|
|
|
918
909
|
// src/contracts/attachments.ts
|
|
@@ -943,9 +934,210 @@ function isHeroUIAgentAttachmentContentType(value) {
|
|
|
943
934
|
return HEROUI_AGENT_ATTACHMENT_CONTENT_TYPE_SET.has(value.trim().toLowerCase());
|
|
944
935
|
}
|
|
945
936
|
|
|
937
|
+
// src/embed/shell-conversation.tsx
|
|
938
|
+
import { useEffect as useEffect2, useLayoutEffect, useRef as useRef2, useState as useState2 } from "react";
|
|
939
|
+
import { Fragment, jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
940
|
+
function ShellConversation({
|
|
941
|
+
agentId,
|
|
942
|
+
composerConnecting = false,
|
|
943
|
+
composerControlsAvailable,
|
|
944
|
+
composerControlsRevealed,
|
|
945
|
+
composerEndSlot,
|
|
946
|
+
composerFooterSlot,
|
|
947
|
+
composerStartSlot,
|
|
948
|
+
greeting,
|
|
949
|
+
onComposerControlsReveal,
|
|
950
|
+
onIntent,
|
|
951
|
+
placeholder,
|
|
952
|
+
suggestedPrompts
|
|
953
|
+
}) {
|
|
954
|
+
const [initialHandoff] = useState2(() => readAgentShellHandoff(agentId));
|
|
955
|
+
const [input, setInput] = useState2(() => initialHandoff?.prompt ?? "");
|
|
956
|
+
const [submission, setSubmission] = useState2(
|
|
957
|
+
() => initialHandoff?.submitted ? initialHandoff : null
|
|
958
|
+
);
|
|
959
|
+
const [locallyRevealedControls, setLocallyRevealedControls] = useState2(false);
|
|
960
|
+
const textareaRef = useRef2(null);
|
|
961
|
+
const controlsAvailable = composerControlsAvailable ?? Boolean(composerStartSlot || composerEndSlot);
|
|
962
|
+
const controlsRevealed = composerControlsRevealed ?? (controlsAvailable && locallyRevealedControls);
|
|
963
|
+
const revealComposerControls = (event) => {
|
|
964
|
+
setFocus(agentId, true, event.currentTarget);
|
|
965
|
+
setLocallyRevealedControls(controlsAvailable);
|
|
966
|
+
if (controlsAvailable) onComposerControlsReveal?.();
|
|
967
|
+
onIntent();
|
|
968
|
+
};
|
|
969
|
+
const handleComposerBlur = (event) => {
|
|
970
|
+
const composer = event.currentTarget.querySelector(".ha-composer");
|
|
971
|
+
if (composer && containsComposerFocus(composer, event.relatedTarget)) return;
|
|
972
|
+
setLocallyRevealedControls(false);
|
|
973
|
+
setFocus(agentId, false);
|
|
974
|
+
};
|
|
975
|
+
useLayoutEffect(() => {
|
|
976
|
+
restoreFocus(agentId, textareaRef.current);
|
|
977
|
+
resizeComposerTextarea(textareaRef.current);
|
|
978
|
+
}, [agentId]);
|
|
979
|
+
useEffect2(() => {
|
|
980
|
+
if (submission) return;
|
|
981
|
+
writeAgentShellHandoff(agentId, { prompt: input, submitted: false });
|
|
982
|
+
}, [input, agentId, submission]);
|
|
983
|
+
useLayoutEffect(() => {
|
|
984
|
+
if (!submission) return;
|
|
985
|
+
const frame = requestAnimationFrame((paintedAt) => {
|
|
986
|
+
markAgentShellFeedbackPainted(agentId, submission.messageId, paintedAt);
|
|
987
|
+
});
|
|
988
|
+
return () => cancelAnimationFrame(frame);
|
|
989
|
+
}, [agentId, submission]);
|
|
990
|
+
const submit = (prompt) => {
|
|
991
|
+
if (submission) return;
|
|
992
|
+
const nextSubmission = createSubmittedAgentShellHandoff(prompt);
|
|
993
|
+
if (!nextSubmission) return;
|
|
994
|
+
setSubmission(nextSubmission);
|
|
995
|
+
setInput("");
|
|
996
|
+
textareaRef.current.style.height = "auto";
|
|
997
|
+
writeAgentShellHandoff(agentId, nextSubmission);
|
|
998
|
+
onIntent();
|
|
999
|
+
};
|
|
1000
|
+
return /* @__PURE__ */ jsxs5(Fragment, { children: [
|
|
1001
|
+
/* @__PURE__ */ jsx5("div", { className: "ha-conversation", children: /* @__PURE__ */ jsx5("div", { "aria-live": "polite", className: "ha-messages", role: "log", children: submission ? /* @__PURE__ */ jsxs5(Fragment, { children: [
|
|
1002
|
+
/* @__PURE__ */ jsx5("div", { className: "ha-message", "data-role": "user", children: /* @__PURE__ */ jsx5("div", { className: "ha-message-body", children: submission.prompt }) }),
|
|
1003
|
+
/* @__PURE__ */ jsx5(
|
|
1004
|
+
"div",
|
|
1005
|
+
{
|
|
1006
|
+
className: "ha-message",
|
|
1007
|
+
"data-role": "assistant",
|
|
1008
|
+
"data-stream-anchor": "true",
|
|
1009
|
+
"data-turn-feedback-id": submission.messageId,
|
|
1010
|
+
children: /* @__PURE__ */ jsx5("div", { className: "ha-message-body", children: /* @__PURE__ */ jsx5(
|
|
1011
|
+
"div",
|
|
1012
|
+
{
|
|
1013
|
+
"aria-label": "Working on your request\u2026",
|
|
1014
|
+
className: "ha-progress ha-activity-status ha-progress-shimmer",
|
|
1015
|
+
role: "status",
|
|
1016
|
+
children: /* @__PURE__ */ jsx5("span", { "aria-hidden": "true", className: "ha-shimmer", children: "Thinking\u2026" })
|
|
1017
|
+
}
|
|
1018
|
+
) })
|
|
1019
|
+
}
|
|
1020
|
+
)
|
|
1021
|
+
] }) : /* @__PURE__ */ jsxs5("div", { className: "ha-empty", children: [
|
|
1022
|
+
/* @__PURE__ */ jsx5("h2", { children: greeting }),
|
|
1023
|
+
/* @__PURE__ */ jsx5("p", { children: "Live answers with charts, metrics, and tables." })
|
|
1024
|
+
] }) }) }),
|
|
1025
|
+
/* @__PURE__ */ jsxs5(
|
|
1026
|
+
"form",
|
|
1027
|
+
{
|
|
1028
|
+
className: "ha-composer-wrap",
|
|
1029
|
+
onBlur: handleComposerBlur,
|
|
1030
|
+
onSubmit: (event) => {
|
|
1031
|
+
event.preventDefault();
|
|
1032
|
+
submit(input);
|
|
1033
|
+
},
|
|
1034
|
+
children: [
|
|
1035
|
+
!submission && suggestedPrompts.length > 0 ? /* @__PURE__ */ jsx5("div", { "aria-label": "Suggested prompts", className: "ha-suggestions", role: "group", children: suggestedPrompts.map((prompt) => /* @__PURE__ */ jsxs5(
|
|
1036
|
+
"button",
|
|
1037
|
+
{
|
|
1038
|
+
className: "ha-suggestion",
|
|
1039
|
+
type: "button",
|
|
1040
|
+
onClick: () => submit(prompt),
|
|
1041
|
+
children: [
|
|
1042
|
+
/* @__PURE__ */ jsx5("span", { children: prompt }),
|
|
1043
|
+
/* @__PURE__ */ jsx5(ArrowUpRightGlyph, {})
|
|
1044
|
+
]
|
|
1045
|
+
},
|
|
1046
|
+
prompt
|
|
1047
|
+
)) }) : null,
|
|
1048
|
+
/* @__PURE__ */ jsxs5(
|
|
1049
|
+
"div",
|
|
1050
|
+
{
|
|
1051
|
+
className: "@container ha-composer",
|
|
1052
|
+
"data-connecting": composerConnecting || void 0,
|
|
1053
|
+
"data-controls-revealed": controlsRevealed || void 0,
|
|
1054
|
+
children: [
|
|
1055
|
+
composerStartSlot,
|
|
1056
|
+
/* @__PURE__ */ jsx5(
|
|
1057
|
+
"textarea",
|
|
1058
|
+
{
|
|
1059
|
+
ref: textareaRef,
|
|
1060
|
+
"aria-label": "Message the assistant",
|
|
1061
|
+
placeholder,
|
|
1062
|
+
readOnly: Boolean(submission),
|
|
1063
|
+
rows: 1,
|
|
1064
|
+
value: input,
|
|
1065
|
+
onFocus: revealComposerControls,
|
|
1066
|
+
onSelect: (event) => setFocus(agentId, true, event.currentTarget),
|
|
1067
|
+
onChange: (event) => {
|
|
1068
|
+
const nextInput = event.currentTarget.value;
|
|
1069
|
+
writeAgentShellHandoff(agentId, { prompt: nextInput, submitted: false });
|
|
1070
|
+
setFocus(agentId, true, event.currentTarget);
|
|
1071
|
+
setInput(nextInput);
|
|
1072
|
+
resizeComposerTextarea(event.currentTarget);
|
|
1073
|
+
onIntent();
|
|
1074
|
+
},
|
|
1075
|
+
onKeyDown: (event) => {
|
|
1076
|
+
if (event.key !== "Enter" || event.shiftKey) return;
|
|
1077
|
+
event.preventDefault();
|
|
1078
|
+
submit(input);
|
|
1079
|
+
}
|
|
1080
|
+
}
|
|
1081
|
+
),
|
|
1082
|
+
composerEndSlot,
|
|
1083
|
+
/* @__PURE__ */ jsxs5(
|
|
1084
|
+
"button",
|
|
1085
|
+
{
|
|
1086
|
+
"aria-label": "Send message",
|
|
1087
|
+
className: "ha-send",
|
|
1088
|
+
disabled: !input.trim() || Boolean(submission),
|
|
1089
|
+
type: "submit",
|
|
1090
|
+
children: [
|
|
1091
|
+
/* @__PURE__ */ jsx5(ArrowUpGlyph, {}),
|
|
1092
|
+
/* @__PURE__ */ jsx5(ComposerControlTooltip, { shortcut: "\u21B5", children: "Send message" })
|
|
1093
|
+
]
|
|
1094
|
+
}
|
|
1095
|
+
)
|
|
1096
|
+
]
|
|
1097
|
+
}
|
|
1098
|
+
),
|
|
1099
|
+
/* @__PURE__ */ jsx5(
|
|
1100
|
+
"div",
|
|
1101
|
+
{
|
|
1102
|
+
className: "ha-composer-footer",
|
|
1103
|
+
"data-revealed": Boolean(composerFooterSlot) || void 0,
|
|
1104
|
+
children: /* @__PURE__ */ jsx5("div", { className: "ha-composer-footer-content", children: composerFooterSlot })
|
|
1105
|
+
}
|
|
1106
|
+
),
|
|
1107
|
+
/* @__PURE__ */ jsx5(PoweredByHero, {})
|
|
1108
|
+
]
|
|
1109
|
+
}
|
|
1110
|
+
)
|
|
1111
|
+
] });
|
|
1112
|
+
}
|
|
1113
|
+
function ArrowUpGlyph() {
|
|
1114
|
+
return /* @__PURE__ */ jsx5("svg", { "aria-hidden": "true", fill: "none", height: "18", viewBox: "0 0 18 18", width: "18", children: /* @__PURE__ */ jsx5(
|
|
1115
|
+
"path",
|
|
1116
|
+
{
|
|
1117
|
+
d: "M9 14.5V3.5m0 0L4.5 8M9 3.5 13.5 8",
|
|
1118
|
+
stroke: "currentColor",
|
|
1119
|
+
strokeLinecap: "round",
|
|
1120
|
+
strokeLinejoin: "round",
|
|
1121
|
+
strokeWidth: "1.6"
|
|
1122
|
+
}
|
|
1123
|
+
) });
|
|
1124
|
+
}
|
|
1125
|
+
function ArrowUpRightGlyph() {
|
|
1126
|
+
return /* @__PURE__ */ jsx5("svg", { "aria-hidden": "true", fill: "none", height: "16", viewBox: "0 0 16 16", width: "16", children: /* @__PURE__ */ jsx5(
|
|
1127
|
+
"path",
|
|
1128
|
+
{
|
|
1129
|
+
d: "M5 11 11 5m0 0H6m5 0v5",
|
|
1130
|
+
stroke: "currentColor",
|
|
1131
|
+
strokeLinecap: "round",
|
|
1132
|
+
strokeLinejoin: "round",
|
|
1133
|
+
strokeWidth: "1.5"
|
|
1134
|
+
}
|
|
1135
|
+
) });
|
|
1136
|
+
}
|
|
1137
|
+
|
|
946
1138
|
// src/embed/types.ts
|
|
947
1139
|
var DEFAULT_MARKDOWN_ANIMATION = {
|
|
948
|
-
animation: "
|
|
1140
|
+
animation: "fadeIn",
|
|
949
1141
|
duration: 160,
|
|
950
1142
|
easing: "ease-out",
|
|
951
1143
|
sep: "word",
|
|
@@ -987,16 +1179,18 @@ function resolveOptions(props) {
|
|
|
987
1179
|
const composerAttachmentContentTypes = resolveComposerAttachmentContentTypes(
|
|
988
1180
|
props.composer?.attachments
|
|
989
1181
|
);
|
|
1182
|
+
const composerDisclaimer = typeof props.composer?.disclaimer === "string" ? props.composer.disclaimer.trim().slice(0, 240) || void 0 : void 0;
|
|
990
1183
|
return {
|
|
991
1184
|
apiBaseUrl: (props._api?.baseUrl ?? "https://api.heroui.com").replace(/\/$/, ""),
|
|
992
1185
|
colorScheme: props.appearance?.theme?.colorScheme ?? "system",
|
|
993
1186
|
componentExportFormats: props.componentExports === false ? [] : props.componentExports ?? ["csv", "svg", "png"],
|
|
994
1187
|
composerAttachmentAccept: composerAttachmentContentTypes.join(","),
|
|
995
1188
|
composerAttachmentContentTypes,
|
|
1189
|
+
composerControlsAvailable: composerAttachmentContentTypes.length > 0 || props.permissions?.showPicker === true && !!props.tools?.length || props.composer?.modelPicker === true || (props.composer?.dictation ?? true),
|
|
996
1190
|
composerDefaultModel: props.composer?.defaultModel,
|
|
997
1191
|
composerDictation: props.composer?.dictation ?? true,
|
|
998
1192
|
designTheme: resolveAgentDesignTheme(props.appearance?.theme?.designTheme),
|
|
999
|
-
...
|
|
1193
|
+
...composerDisclaimer ? { composerDisclaimer } : {},
|
|
1000
1194
|
agentId: props.agentId,
|
|
1001
1195
|
composerModelPicker: props.composer?.modelPicker ?? false,
|
|
1002
1196
|
composerPlaceholder: props.composer?.placeholder?.trim().slice(0, 120) || "Ask anything\u2026",
|
|
@@ -1045,14 +1239,8 @@ export {
|
|
|
1045
1239
|
isZodSchema,
|
|
1046
1240
|
parseClientToolArgs,
|
|
1047
1241
|
resolveDirectToolAction,
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
saveAgentComposerPromptDraft,
|
|
1051
|
-
readAgentComposerImageDraft,
|
|
1052
|
-
saveAgentComposerImageDraft,
|
|
1053
|
-
clearAgentComposerDraft,
|
|
1054
|
-
clearAgentComposerDraftsForProject,
|
|
1055
|
-
scheduleIdleTask,
|
|
1242
|
+
EmbedSessionManager,
|
|
1243
|
+
AgentLoadingState,
|
|
1056
1244
|
ComposerControlTooltip,
|
|
1057
1245
|
readSidebarWidth,
|
|
1058
1246
|
PanelShell,
|
|
@@ -1061,12 +1249,26 @@ export {
|
|
|
1061
1249
|
HEROUI_AGENT_ATTACHMENT_EXTENSION_BY_CONTENT_TYPE,
|
|
1062
1250
|
HEROUI_AGENT_ATTACHMENT_CONTENT_TYPES,
|
|
1063
1251
|
isHeroUIAgentAttachmentContentType,
|
|
1064
|
-
|
|
1065
|
-
|
|
1252
|
+
AGENT_MODEL_IDS,
|
|
1253
|
+
LEGACY_AGENT_MODEL_IDS,
|
|
1254
|
+
resolveAgentModelId,
|
|
1255
|
+
DEFAULT_AGENT_PICKER_MODEL_ID,
|
|
1256
|
+
AGENT_MODEL_OPTIONS,
|
|
1257
|
+
isAgentModelId,
|
|
1258
|
+
getAgentModelTier,
|
|
1259
|
+
createSubmittedAgentShellHandoff,
|
|
1066
1260
|
writeAgentShellHandoff,
|
|
1067
1261
|
readAgentShellHandoff,
|
|
1068
1262
|
takeAgentShellHandoff,
|
|
1069
|
-
|
|
1263
|
+
setFocus,
|
|
1264
|
+
restoreFocus,
|
|
1265
|
+
containsComposerFocus,
|
|
1266
|
+
writeAgentShellAttachments,
|
|
1267
|
+
readAgentShellAttachments,
|
|
1268
|
+
takeAgentShellAttachments,
|
|
1269
|
+
resizeComposerTextarea,
|
|
1270
|
+
PoweredByHero,
|
|
1271
|
+
ShellConversation,
|
|
1070
1272
|
agentPermissionModeStorageKey,
|
|
1071
1273
|
agentActivePermissionModeStorageKey,
|
|
1072
1274
|
readStoredAgentPermissionMode,
|
|
@@ -1076,11 +1278,8 @@ export {
|
|
|
1076
1278
|
AGENT_DESIGN_THEMES,
|
|
1077
1279
|
DEFAULT_MARKDOWN_ANIMATION,
|
|
1078
1280
|
resolveOptions,
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
AGENT_MODEL_OPTIONS,
|
|
1084
|
-
isAgentModelId,
|
|
1085
|
-
getAgentModelTier
|
|
1281
|
+
HEROUI_AGENT_RUNTIME_TIMING_EVENT,
|
|
1282
|
+
HEROUI_AGENT_TURN_ADMITTED_FRAME_TYPE,
|
|
1283
|
+
HEROUI_AGENT_TURN_ADMISSION_STATUS_METHOD,
|
|
1284
|
+
HEROUI_AGENT_TURN_ADMISSION_STATUS_MAX_IDS
|
|
1086
1285
|
};
|