@heroui/agent 0.2.0-beta.1
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 +64 -0
- package/LICENSE +21 -0
- package/README.md +205 -0
- package/dist/chart-content-VZ66GD22.js +1391 -0
- package/dist/chunk-3FG5NRTX.js +9 -0
- package/dist/chunk-CU6MPKAJ.js +359 -0
- package/dist/chunk-DW4AQRM5.js +297 -0
- package/dist/chunk-GDDNN2XY.js +954 -0
- package/dist/chunk-RQCTC4JB.js +1084 -0
- package/dist/chunk-TOOT6SZ2.js +74 -0
- package/dist/chunk-VJA52U5P.js +137 -0
- package/dist/component-renderer-IBJDNXSO.js +9780 -0
- package/dist/contracts.d.ts +1293 -0
- package/dist/contracts.js +2325 -0
- package/dist/css/index.css +2 -0
- package/dist/embed-runtime-XOPQY7Z5.js +7254 -0
- package/dist/identity-NYCXY1mT.d.ts +164 -0
- package/dist/index.d.ts +594 -0
- package/dist/index.js +28 -0
- package/dist/interactive-map-surface-67KHT3VB.js +362 -0
- package/dist/next.d.ts +4 -0
- package/dist/next.js +22 -0
- package/dist/server.d.ts +31 -0
- package/dist/server.js +256 -0
- package/package.json +133 -0
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import {
|
|
3
|
+
createMapLayout,
|
|
4
|
+
getMapSelectionCenter
|
|
5
|
+
} from "./chunk-VJA52U5P.js";
|
|
6
|
+
import {
|
|
7
|
+
mergeClassNames
|
|
8
|
+
} from "./chunk-3FG5NRTX.js";
|
|
9
|
+
|
|
10
|
+
// ../agent-ui/src/components/display-information/map/interactive-map-surface.tsx
|
|
11
|
+
import { StarFill } from "@gravity-ui/icons";
|
|
12
|
+
|
|
13
|
+
// ../agent-ui/src/components/display-information/map/interactive-map.tsx
|
|
14
|
+
import MapLibreGL from "maplibre-gl";
|
|
15
|
+
import { createContext, useCallback, useContext, useEffect, useRef, useState } from "react";
|
|
16
|
+
import { createPortal } from "react-dom";
|
|
17
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
18
|
+
var InteractiveMapContext = createContext(null);
|
|
19
|
+
function getDocumentTheme() {
|
|
20
|
+
if (typeof document === "undefined") return void 0;
|
|
21
|
+
if (document.documentElement.classList.contains("dark") || document.documentElement.dataset["theme"] === "dark") {
|
|
22
|
+
return "dark";
|
|
23
|
+
}
|
|
24
|
+
if (document.documentElement.classList.contains("light") || document.documentElement.dataset["theme"] === "light") {
|
|
25
|
+
return "light";
|
|
26
|
+
}
|
|
27
|
+
return void 0;
|
|
28
|
+
}
|
|
29
|
+
function getLocalTheme(element) {
|
|
30
|
+
const themeRoot = element?.closest("[data-theme]");
|
|
31
|
+
const theme = themeRoot?.dataset["theme"];
|
|
32
|
+
return theme === "dark" || theme === "light" ? theme : void 0;
|
|
33
|
+
}
|
|
34
|
+
function getSystemTheme() {
|
|
35
|
+
if (typeof window === "undefined") return "light";
|
|
36
|
+
return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
|
|
37
|
+
}
|
|
38
|
+
function useMapTheme(containerRef) {
|
|
39
|
+
const [theme, setTheme] = useState(() => getDocumentTheme() ?? getSystemTheme());
|
|
40
|
+
useEffect(() => {
|
|
41
|
+
const localThemeRoot = containerRef.current?.closest("[data-theme]");
|
|
42
|
+
const updateTheme = () => setTheme(getLocalTheme(containerRef.current) ?? getDocumentTheme() ?? getSystemTheme());
|
|
43
|
+
const observer = new MutationObserver(updateTheme);
|
|
44
|
+
const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
|
|
45
|
+
updateTheme();
|
|
46
|
+
observer.observe(document.documentElement, {
|
|
47
|
+
attributeFilter: ["class", "data-theme"],
|
|
48
|
+
attributes: true
|
|
49
|
+
});
|
|
50
|
+
if (localThemeRoot && localThemeRoot !== document.documentElement) {
|
|
51
|
+
observer.observe(localThemeRoot, {
|
|
52
|
+
attributeFilter: ["data-theme"],
|
|
53
|
+
attributes: true
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
mediaQuery.addEventListener("change", updateTheme);
|
|
57
|
+
return () => {
|
|
58
|
+
observer.disconnect();
|
|
59
|
+
mediaQuery.removeEventListener("change", updateTheme);
|
|
60
|
+
};
|
|
61
|
+
}, [containerRef]);
|
|
62
|
+
return theme;
|
|
63
|
+
}
|
|
64
|
+
function InteractiveMapRoot({
|
|
65
|
+
center,
|
|
66
|
+
children,
|
|
67
|
+
className,
|
|
68
|
+
padding,
|
|
69
|
+
styles,
|
|
70
|
+
zoom,
|
|
71
|
+
...options
|
|
72
|
+
}) {
|
|
73
|
+
const [longitude, latitude] = center;
|
|
74
|
+
const containerRef = useRef(null);
|
|
75
|
+
const initialOptionsRef = useRef({
|
|
76
|
+
...options,
|
|
77
|
+
center: [longitude, latitude],
|
|
78
|
+
zoom
|
|
79
|
+
});
|
|
80
|
+
const [map, setMap] = useState(null);
|
|
81
|
+
const [loadState, setLoadState] = useState("loading");
|
|
82
|
+
const theme = useMapTheme(containerRef);
|
|
83
|
+
const activeStyle = styles[theme];
|
|
84
|
+
const activeStyleRef = useRef(activeStyle);
|
|
85
|
+
const initialPaddingRef = useRef(padding);
|
|
86
|
+
const zoomRef = useRef(zoom);
|
|
87
|
+
useEffect(() => {
|
|
88
|
+
const container = containerRef.current;
|
|
89
|
+
if (!container) return;
|
|
90
|
+
const nextMap = new MapLibreGL.Map({
|
|
91
|
+
attributionControl: false,
|
|
92
|
+
container,
|
|
93
|
+
renderWorldCopies: false,
|
|
94
|
+
style: activeStyleRef.current,
|
|
95
|
+
...initialOptionsRef.current
|
|
96
|
+
});
|
|
97
|
+
const loadTimeout = window.setTimeout(() => setLoadState("error"), 12e3);
|
|
98
|
+
const handleLoad = () => {
|
|
99
|
+
window.clearTimeout(loadTimeout);
|
|
100
|
+
setLoadState("loaded");
|
|
101
|
+
};
|
|
102
|
+
const observer = new ResizeObserver(() => nextMap.resize());
|
|
103
|
+
nextMap.touchZoomRotate.disableRotation();
|
|
104
|
+
if (initialPaddingRef.current) nextMap.setPadding(initialPaddingRef.current);
|
|
105
|
+
nextMap.on("load", handleLoad);
|
|
106
|
+
observer.observe(container);
|
|
107
|
+
setMap(nextMap);
|
|
108
|
+
return () => {
|
|
109
|
+
window.clearTimeout(loadTimeout);
|
|
110
|
+
observer.disconnect();
|
|
111
|
+
nextMap.off("load", handleLoad);
|
|
112
|
+
nextMap.remove();
|
|
113
|
+
setMap(null);
|
|
114
|
+
};
|
|
115
|
+
}, []);
|
|
116
|
+
useEffect(() => {
|
|
117
|
+
if (!map || activeStyleRef.current === activeStyle) return;
|
|
118
|
+
const styleLoadTimeout = window.setTimeout(() => setLoadState("error"), 12e3);
|
|
119
|
+
const handleStyleLoad = () => {
|
|
120
|
+
window.clearTimeout(styleLoadTimeout);
|
|
121
|
+
setLoadState("loaded");
|
|
122
|
+
};
|
|
123
|
+
const handleStyleLoading = () => setLoadState("loading");
|
|
124
|
+
activeStyleRef.current = activeStyle;
|
|
125
|
+
map.once("styledataloading", handleStyleLoading);
|
|
126
|
+
map.setStyle(activeStyle, { diff: false });
|
|
127
|
+
map.once("style.load", handleStyleLoad);
|
|
128
|
+
return () => {
|
|
129
|
+
window.clearTimeout(styleLoadTimeout);
|
|
130
|
+
map.off("style.load", handleStyleLoad);
|
|
131
|
+
map.off("styledataloading", handleStyleLoading);
|
|
132
|
+
};
|
|
133
|
+
}, [activeStyle, map]);
|
|
134
|
+
useEffect(() => {
|
|
135
|
+
if (!map) return;
|
|
136
|
+
const currentCenter = map.getCenter();
|
|
137
|
+
const centerChanged = currentCenter.lng !== longitude || currentCenter.lat !== latitude;
|
|
138
|
+
const zoomChanged = zoomRef.current !== zoom;
|
|
139
|
+
zoomRef.current = zoom;
|
|
140
|
+
if (!centerChanged && !zoomChanged) return;
|
|
141
|
+
map.easeTo({
|
|
142
|
+
center: [longitude, latitude],
|
|
143
|
+
duration: window.matchMedia("(prefers-reduced-motion: reduce)").matches ? 0 : 350,
|
|
144
|
+
...zoomChanged ? { zoom } : {}
|
|
145
|
+
});
|
|
146
|
+
}, [latitude, longitude, map, zoom]);
|
|
147
|
+
return /* @__PURE__ */ jsx(InteractiveMapContext, { value: map, children: /* @__PURE__ */ jsxs(
|
|
148
|
+
"div",
|
|
149
|
+
{
|
|
150
|
+
ref: containerRef,
|
|
151
|
+
className: mergeClassNames("aui-interactive-map", className),
|
|
152
|
+
"data-load-state": loadState,
|
|
153
|
+
"data-slot": "agent-ui-interactive-map",
|
|
154
|
+
children: [
|
|
155
|
+
loadState === "loading" ? /* @__PURE__ */ jsx("div", { "aria-label": "Loading map", className: "aui-interactive-map__loader", role: "status", children: /* @__PURE__ */ jsx("span", {}) }) : null,
|
|
156
|
+
loadState === "error" ? /* @__PURE__ */ jsxs("div", { className: "aui-interactive-map__error", role: "status", children: [
|
|
157
|
+
/* @__PURE__ */ jsx("strong", { children: "Map unavailable" }),
|
|
158
|
+
/* @__PURE__ */ jsx("span", { children: "Location results remain available." })
|
|
159
|
+
] }) : null,
|
|
160
|
+
map ? children : null
|
|
161
|
+
]
|
|
162
|
+
}
|
|
163
|
+
) });
|
|
164
|
+
}
|
|
165
|
+
function InteractiveMapMarker({ children, latitude, longitude }) {
|
|
166
|
+
const map = useContext(InteractiveMapContext);
|
|
167
|
+
const initialPositionRef = useRef({ latitude, longitude });
|
|
168
|
+
const [marker, setMarker] = useState(null);
|
|
169
|
+
useEffect(() => {
|
|
170
|
+
const nextElement = document.createElement("div");
|
|
171
|
+
const initialPosition = initialPositionRef.current;
|
|
172
|
+
const nextMarker = new MapLibreGL.Marker({ element: nextElement }).setLngLat([
|
|
173
|
+
initialPosition.longitude,
|
|
174
|
+
initialPosition.latitude
|
|
175
|
+
]);
|
|
176
|
+
nextElement.className = "aui-interactive-map__marker-host";
|
|
177
|
+
setMarker(nextMarker);
|
|
178
|
+
return () => {
|
|
179
|
+
nextMarker.remove();
|
|
180
|
+
};
|
|
181
|
+
}, []);
|
|
182
|
+
useEffect(() => {
|
|
183
|
+
if (!map || !marker) return;
|
|
184
|
+
marker.addTo(map);
|
|
185
|
+
const markerElement = marker.getElement();
|
|
186
|
+
markerElement.removeAttribute("aria-label");
|
|
187
|
+
markerElement.removeAttribute("role");
|
|
188
|
+
markerElement.removeAttribute("tabindex");
|
|
189
|
+
return () => {
|
|
190
|
+
marker.remove();
|
|
191
|
+
};
|
|
192
|
+
}, [map, marker]);
|
|
193
|
+
useEffect(() => {
|
|
194
|
+
marker?.setLngLat([longitude, latitude]);
|
|
195
|
+
}, [latitude, longitude, marker]);
|
|
196
|
+
return marker ? createPortal(
|
|
197
|
+
/* @__PURE__ */ jsx("div", { className: "aui-interactive-map__marker-content", children }),
|
|
198
|
+
marker.getElement()
|
|
199
|
+
) : null;
|
|
200
|
+
}
|
|
201
|
+
function ControlButton({ children, label, ...props }) {
|
|
202
|
+
return /* @__PURE__ */ jsx(
|
|
203
|
+
"button",
|
|
204
|
+
{
|
|
205
|
+
"aria-label": label,
|
|
206
|
+
className: "aui-interactive-map__control-button",
|
|
207
|
+
type: "button",
|
|
208
|
+
...props,
|
|
209
|
+
children
|
|
210
|
+
}
|
|
211
|
+
);
|
|
212
|
+
}
|
|
213
|
+
function PlusIcon(props) {
|
|
214
|
+
return /* @__PURE__ */ jsx("svg", { "aria-hidden": "true", fill: "none", viewBox: "0 0 16 16", ...props, children: /* @__PURE__ */ jsx("path", { d: "M8 3v10M3 8h10", stroke: "currentColor", strokeLinecap: "round", strokeWidth: "1.5" }) });
|
|
215
|
+
}
|
|
216
|
+
function MinusIcon(props) {
|
|
217
|
+
return /* @__PURE__ */ jsx("svg", { "aria-hidden": "true", fill: "none", viewBox: "0 0 16 16", ...props, children: /* @__PURE__ */ jsx("path", { d: "M3 8h10", stroke: "currentColor", strokeLinecap: "round", strokeWidth: "1.5" }) });
|
|
218
|
+
}
|
|
219
|
+
function CompassIcon(props) {
|
|
220
|
+
return /* @__PURE__ */ jsxs("svg", { "aria-hidden": "true", fill: "none", viewBox: "0 0 24 24", ...props, children: [
|
|
221
|
+
/* @__PURE__ */ jsx("path", { d: "M12 2 16 12h-4V2Z", "data-needle": "north-right" }),
|
|
222
|
+
/* @__PURE__ */ jsx("path", { d: "m12 2-4 10h4V2Z", "data-needle": "north-left" }),
|
|
223
|
+
/* @__PURE__ */ jsx("path", { d: "m12 22 4-10h-4v10Z", "data-needle": "south-right" }),
|
|
224
|
+
/* @__PURE__ */ jsx("path", { d: "m12 22-4-10h4v10Z", "data-needle": "south-left" })
|
|
225
|
+
] });
|
|
226
|
+
}
|
|
227
|
+
function InteractiveMapControls() {
|
|
228
|
+
const map = useContext(InteractiveMapContext);
|
|
229
|
+
const compassRef = useRef(null);
|
|
230
|
+
const updateCompass = useCallback(() => {
|
|
231
|
+
if (!map || !compassRef.current) return;
|
|
232
|
+
compassRef.current.style.transform = `rotateX(${map.getPitch()}deg) rotateZ(${-map.getBearing()}deg)`;
|
|
233
|
+
}, [map]);
|
|
234
|
+
useEffect(() => {
|
|
235
|
+
if (!map) return;
|
|
236
|
+
map.on("pitch", updateCompass);
|
|
237
|
+
map.on("rotate", updateCompass);
|
|
238
|
+
updateCompass();
|
|
239
|
+
return () => {
|
|
240
|
+
map.off("pitch", updateCompass);
|
|
241
|
+
map.off("rotate", updateCompass);
|
|
242
|
+
};
|
|
243
|
+
}, [map, updateCompass]);
|
|
244
|
+
return /* @__PURE__ */ jsxs("div", { className: "aui-interactive-map__controls", "data-slot": "agent-ui-map-controls", children: [
|
|
245
|
+
/* @__PURE__ */ jsxs("div", { className: "aui-interactive-map__control-group", children: [
|
|
246
|
+
/* @__PURE__ */ jsx(
|
|
247
|
+
ControlButton,
|
|
248
|
+
{
|
|
249
|
+
label: "Zoom in",
|
|
250
|
+
onClick: () => map?.zoomTo(map.getZoom() + 1, { duration: 250 }),
|
|
251
|
+
children: /* @__PURE__ */ jsx(PlusIcon, {})
|
|
252
|
+
}
|
|
253
|
+
),
|
|
254
|
+
/* @__PURE__ */ jsx(
|
|
255
|
+
ControlButton,
|
|
256
|
+
{
|
|
257
|
+
label: "Zoom out",
|
|
258
|
+
onClick: () => map?.zoomTo(map.getZoom() - 1, { duration: 250 }),
|
|
259
|
+
children: /* @__PURE__ */ jsx(MinusIcon, {})
|
|
260
|
+
}
|
|
261
|
+
)
|
|
262
|
+
] }),
|
|
263
|
+
/* @__PURE__ */ jsx("div", { className: "aui-interactive-map__control-group", children: /* @__PURE__ */ jsx(
|
|
264
|
+
ControlButton,
|
|
265
|
+
{
|
|
266
|
+
label: "Reset bearing to north",
|
|
267
|
+
onClick: () => map?.resetNorthPitch({ duration: 250 }),
|
|
268
|
+
children: /* @__PURE__ */ jsx(CompassIcon, { ref: compassRef, className: "aui-interactive-map__compass" })
|
|
269
|
+
}
|
|
270
|
+
) })
|
|
271
|
+
] });
|
|
272
|
+
}
|
|
273
|
+
var InteractiveMap = Object.assign(InteractiveMapRoot, {
|
|
274
|
+
Controls: InteractiveMapControls,
|
|
275
|
+
Marker: InteractiveMapMarker
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
// ../agent-ui/src/components/display-information/map/interactive-map-surface.tsx
|
|
279
|
+
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
280
|
+
var mapStyles = {
|
|
281
|
+
dark: "https://basemaps.cartocdn.com/gl/dark-matter-gl-style/style.json",
|
|
282
|
+
light: "https://basemaps.cartocdn.com/gl/voyager-gl-style/style.json"
|
|
283
|
+
};
|
|
284
|
+
var resultRailPadding = { bottom: 132, left: 0, right: 0, top: 0 };
|
|
285
|
+
var ratingFormatter = new Intl.NumberFormat(void 0, {
|
|
286
|
+
maximumFractionDigits: 1,
|
|
287
|
+
minimumFractionDigits: 1
|
|
288
|
+
});
|
|
289
|
+
function InteractiveMapSurface({
|
|
290
|
+
component,
|
|
291
|
+
onSelect,
|
|
292
|
+
selectedLocationId
|
|
293
|
+
}) {
|
|
294
|
+
const layout = createMapLayout(component);
|
|
295
|
+
const center = getMapSelectionCenter(component.locations, selectedLocationId, layout.center);
|
|
296
|
+
return /* @__PURE__ */ jsxs2(
|
|
297
|
+
"div",
|
|
298
|
+
{
|
|
299
|
+
"aria-label": `${component.title} map with ${component.locations.length} locations`,
|
|
300
|
+
className: "aui-map__surface",
|
|
301
|
+
"data-renderer": "interactive",
|
|
302
|
+
"data-slot": "agent-ui-map-surface",
|
|
303
|
+
role: "region",
|
|
304
|
+
children: [
|
|
305
|
+
/* @__PURE__ */ jsxs2(
|
|
306
|
+
InteractiveMap,
|
|
307
|
+
{
|
|
308
|
+
center: [center.longitude, center.latitude],
|
|
309
|
+
className: "aui-map__interactive-map",
|
|
310
|
+
dragRotate: false,
|
|
311
|
+
padding: resultRailPadding,
|
|
312
|
+
pitchWithRotate: false,
|
|
313
|
+
styles: mapStyles,
|
|
314
|
+
zoom: layout.zoom,
|
|
315
|
+
children: [
|
|
316
|
+
component.locations.map((location, index) => {
|
|
317
|
+
const selected = location.id === selectedLocationId;
|
|
318
|
+
const markerLabel = location.rating !== void 0 ? ratingFormatter.format(location.rating) : location.relevance !== void 0 ? `${Math.round(location.relevance * 100)}%` : String(index + 1);
|
|
319
|
+
const accessibleLabel = `Select ${location.title} on map${location.rating === void 0 ? "" : `, rated ${ratingFormatter.format(location.rating)} out of 5`}`;
|
|
320
|
+
return /* @__PURE__ */ jsx2(
|
|
321
|
+
InteractiveMap.Marker,
|
|
322
|
+
{
|
|
323
|
+
latitude: location.latitude,
|
|
324
|
+
longitude: location.longitude,
|
|
325
|
+
children: /* @__PURE__ */ jsxs2(
|
|
326
|
+
"button",
|
|
327
|
+
{
|
|
328
|
+
"aria-label": accessibleLabel,
|
|
329
|
+
"aria-pressed": selected,
|
|
330
|
+
className: "aui-map__marker",
|
|
331
|
+
"data-renderer": "interactive",
|
|
332
|
+
"data-selected": selected,
|
|
333
|
+
"data-slot": "agent-ui-map-marker",
|
|
334
|
+
title: location.title,
|
|
335
|
+
type: "button",
|
|
336
|
+
onClick: () => onSelect(location),
|
|
337
|
+
children: [
|
|
338
|
+
/* @__PURE__ */ jsx2(StarFill, { "aria-hidden": "true" }),
|
|
339
|
+
/* @__PURE__ */ jsx2("span", { children: markerLabel })
|
|
340
|
+
]
|
|
341
|
+
}
|
|
342
|
+
)
|
|
343
|
+
},
|
|
344
|
+
location.id
|
|
345
|
+
);
|
|
346
|
+
}),
|
|
347
|
+
/* @__PURE__ */ jsx2(InteractiveMap.Controls, {})
|
|
348
|
+
]
|
|
349
|
+
}
|
|
350
|
+
),
|
|
351
|
+
/* @__PURE__ */ jsxs2("span", { className: "aui-map__attribution", "data-slot": "agent-ui-map-attribution", children: [
|
|
352
|
+
/* @__PURE__ */ jsx2("a", { href: "https://www.openstreetmap.org/copyright", rel: "noreferrer", target: "_blank", children: "\xA9 OpenStreetMap" }),
|
|
353
|
+
/* @__PURE__ */ jsx2("span", { "aria-hidden": "true", children: " \xB7 " }),
|
|
354
|
+
/* @__PURE__ */ jsx2("a", { href: "https://carto.com/attributions", rel: "noreferrer", target: "_blank", children: "\xA9 CARTO" })
|
|
355
|
+
] })
|
|
356
|
+
]
|
|
357
|
+
}
|
|
358
|
+
);
|
|
359
|
+
}
|
|
360
|
+
export {
|
|
361
|
+
InteractiveMapSurface
|
|
362
|
+
};
|
package/dist/next.d.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { AGENT_MODEL_IDS, AGENT_MODEL_OPTIONS, AgentAttachmentContentType, AgentAuthToken, AgentComposerOptions, AgentContext, AgentController, AgentFeedbackReason, AgentMarkdownAnimation, AgentMarkdownCaret, AgentMarkdownOptions, AgentMarkdownPlugins, AgentMarkdownRenderer, AgentMarkdownRendererProps, AgentModelId, AgentModelOption, AgentModelTier, AgentPermissionMode, AgentPermissionOptions, AgentResponseFeedback, AgentSharedContext, ClientTool, ClientToolIconProps, ClientToolRenderProps, ClientToolStatus, DEFAULT_AGENT_PICKER_MODEL_ID, GetAuthToken, GetAuthTokenContext, HeroUIAgent, HeroUIAgentProps, createToolHelper, getAgentModelTier, isAgentModelId, useAgent } from './index.js';
|
|
2
|
+
import 'react';
|
|
3
|
+
import 'zod';
|
|
4
|
+
import 'streamdown';
|
package/dist/next.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import {
|
|
2
|
+
HeroUIAgent,
|
|
3
|
+
useAgent
|
|
4
|
+
} from "./chunk-GDDNN2XY.js";
|
|
5
|
+
import {
|
|
6
|
+
AGENT_MODEL_IDS,
|
|
7
|
+
AGENT_MODEL_OPTIONS,
|
|
8
|
+
DEFAULT_AGENT_PICKER_MODEL_ID,
|
|
9
|
+
createToolHelper,
|
|
10
|
+
getAgentModelTier,
|
|
11
|
+
isAgentModelId
|
|
12
|
+
} from "./chunk-RQCTC4JB.js";
|
|
13
|
+
export {
|
|
14
|
+
AGENT_MODEL_IDS,
|
|
15
|
+
AGENT_MODEL_OPTIONS,
|
|
16
|
+
DEFAULT_AGENT_PICKER_MODEL_ID,
|
|
17
|
+
HeroUIAgent,
|
|
18
|
+
createToolHelper,
|
|
19
|
+
getAgentModelTier,
|
|
20
|
+
isAgentModelId,
|
|
21
|
+
useAgent
|
|
22
|
+
};
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { a as AgentAuthIdentity, b as AgentAuthProfile, c as AgentAuthToken } from './identity-NYCXY1mT.js';
|
|
2
|
+
import 'zod';
|
|
3
|
+
|
|
4
|
+
type CreateAuthTokenOptions = {
|
|
5
|
+
/**
|
|
6
|
+
* Browser-scoped id from the SDK's `getAuthToken` context. Pass it alongside
|
|
7
|
+
* an identified `identity` so conversations started before login are merged
|
|
8
|
+
* into the identified user.
|
|
9
|
+
*/
|
|
10
|
+
anonymousId?: string;
|
|
11
|
+
/** Optional API origin override for local development or self-hosted gateways. */
|
|
12
|
+
apiBaseUrl?: string;
|
|
13
|
+
/** Secret managed API key. This value must only be used on the server. */
|
|
14
|
+
apiKey: string;
|
|
15
|
+
identity: AgentAuthIdentity;
|
|
16
|
+
/** Optional end-user profile metadata shown in Agent monitoring. */
|
|
17
|
+
profile?: AgentAuthProfile;
|
|
18
|
+
agentId: string;
|
|
19
|
+
};
|
|
20
|
+
declare class HeroUIAgentAuthError extends Error {
|
|
21
|
+
readonly status: number;
|
|
22
|
+
constructor(message: string, status: number, options?: ErrorOptions);
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Exchanges a server-only managed API key for a short-lived browser
|
|
26
|
+
* credential. The API key and upstream response body are never included in
|
|
27
|
+
* thrown error messages.
|
|
28
|
+
*/
|
|
29
|
+
declare function createAuthToken(options: CreateAuthTokenOptions): Promise<AgentAuthToken>;
|
|
30
|
+
|
|
31
|
+
export { type CreateAuthTokenOptions, HeroUIAgentAuthError, createAuthToken };
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
// src/contracts/identity.ts
|
|
2
|
+
import { z as z3 } from "zod";
|
|
3
|
+
|
|
4
|
+
// src/contracts/client-tools.ts
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
var RESERVED_AGENT_TOOL_NAMES = [
|
|
7
|
+
"composeUI",
|
|
8
|
+
"executeSandbox",
|
|
9
|
+
"getComponentSchema",
|
|
10
|
+
"loadUIRenderers",
|
|
11
|
+
"renderComponent",
|
|
12
|
+
"searchKnowledge",
|
|
13
|
+
"searchWeb"
|
|
14
|
+
];
|
|
15
|
+
var RESERVED_AGENT_TOOL_PREFIX = "mcp_";
|
|
16
|
+
var MAX_CLIENT_TOOLS = 20;
|
|
17
|
+
var MAX_CLIENT_TOOLS_BYTES = 16 * 1024;
|
|
18
|
+
var clientToolManifestEntrySchema = z.object({
|
|
19
|
+
description: z.string().trim().min(1).max(1e3),
|
|
20
|
+
inputSchema: z.record(z.string(), z.unknown()),
|
|
21
|
+
name: z.string().regex(/^[a-zA-Z][a-zA-Z0-9_-]{0,63}$/).refine(
|
|
22
|
+
(name) => !RESERVED_AGENT_TOOL_NAMES.includes(name) && !name.toLowerCase().startsWith(RESERVED_AGENT_TOOL_PREFIX),
|
|
23
|
+
"Client tool name is reserved by the HeroUI Agent runtime"
|
|
24
|
+
),
|
|
25
|
+
needsApproval: z.boolean().optional()
|
|
26
|
+
});
|
|
27
|
+
var clientToolsSchema = z.array(clientToolManifestEntrySchema).max(MAX_CLIENT_TOOLS).superRefine((tools, context) => {
|
|
28
|
+
const names = /* @__PURE__ */ new Set();
|
|
29
|
+
for (const entry of tools) {
|
|
30
|
+
if (names.has(entry.name)) {
|
|
31
|
+
context.addIssue({ code: "custom", message: `Duplicate client tool name: ${entry.name}` });
|
|
32
|
+
}
|
|
33
|
+
names.add(entry.name);
|
|
34
|
+
}
|
|
35
|
+
if (new TextEncoder().encode(JSON.stringify(tools)).byteLength > MAX_CLIENT_TOOLS_BYTES) {
|
|
36
|
+
context.addIssue({ code: "custom", message: "Client tool manifest exceeds 16KB" });
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
// src/contracts/models.schema.ts
|
|
41
|
+
import { z as z2 } from "zod";
|
|
42
|
+
|
|
43
|
+
// src/contracts/models.ts
|
|
44
|
+
var AGENT_MODEL_IDS = [
|
|
45
|
+
"moonshotai/Kimi-K3",
|
|
46
|
+
"openai/gpt-5.6-luna",
|
|
47
|
+
"openai/gpt-5.6-terra",
|
|
48
|
+
"openai/gpt-5.6-sol",
|
|
49
|
+
"google/gemini-3.6-flash",
|
|
50
|
+
"anthropic/claude-sonnet-5",
|
|
51
|
+
"anthropic/claude-opus-4.8"
|
|
52
|
+
];
|
|
53
|
+
var LEGACY_AGENT_MODEL_IDS = {
|
|
54
|
+
"google/gemini-3.5-flash": "google/gemini-3.6-flash"
|
|
55
|
+
};
|
|
56
|
+
function resolveAgentModelId(value) {
|
|
57
|
+
return LEGACY_AGENT_MODEL_IDS[value] ?? value;
|
|
58
|
+
}
|
|
59
|
+
var AGENT_MODEL_ID_SET = new Set(AGENT_MODEL_IDS);
|
|
60
|
+
|
|
61
|
+
// src/contracts/models.schema.ts
|
|
62
|
+
var agentModelIdSchema = z2.preprocess(
|
|
63
|
+
(value) => typeof value === "string" ? resolveAgentModelId(value) : value,
|
|
64
|
+
z2.enum(AGENT_MODEL_IDS)
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
// src/contracts/version.ts
|
|
68
|
+
var HEROUI_AGENT_PROTOCOL_VERSION = 5;
|
|
69
|
+
var HEROUI_AGENT_SDK_VERSION = "0.2.0-beta.1";
|
|
70
|
+
|
|
71
|
+
// src/contracts/identity.ts
|
|
72
|
+
var agentThemeSchema = z3.enum(["light", "dark", "system"]);
|
|
73
|
+
var agentSurfaceVariantSchema = z3.enum([
|
|
74
|
+
"outline",
|
|
75
|
+
"plain",
|
|
76
|
+
"surface",
|
|
77
|
+
"surface-secondary"
|
|
78
|
+
]);
|
|
79
|
+
var pageContextSchema = z3.record(z3.string().max(100), z3.unknown());
|
|
80
|
+
var RESERVED_IDENTITY_IDS = /* @__PURE__ */ new Set([
|
|
81
|
+
"[object object]",
|
|
82
|
+
"0",
|
|
83
|
+
"anonymous",
|
|
84
|
+
"distinct_id",
|
|
85
|
+
"distinctid",
|
|
86
|
+
"email",
|
|
87
|
+
"false",
|
|
88
|
+
"guest",
|
|
89
|
+
"id",
|
|
90
|
+
"nan",
|
|
91
|
+
"none",
|
|
92
|
+
"not_authenticated",
|
|
93
|
+
"null",
|
|
94
|
+
"true",
|
|
95
|
+
"undefined"
|
|
96
|
+
]);
|
|
97
|
+
var agentIdentityIdSchema = z3.string().trim().min(1).max(200).refine((value) => !RESERVED_IDENTITY_IDS.has(value.toLowerCase()), {
|
|
98
|
+
message: "Identity id is reserved"
|
|
99
|
+
});
|
|
100
|
+
var agentAuthIdentitySchema = z3.discriminatedUnion("type", [
|
|
101
|
+
z3.object({
|
|
102
|
+
id: agentIdentityIdSchema,
|
|
103
|
+
type: z3.literal("anonymous")
|
|
104
|
+
}),
|
|
105
|
+
z3.object({
|
|
106
|
+
id: agentIdentityIdSchema,
|
|
107
|
+
type: z3.literal("user")
|
|
108
|
+
})
|
|
109
|
+
]);
|
|
110
|
+
var agentAuthProfileSchema = z3.object({
|
|
111
|
+
avatarUrl: z3.string().trim().pipe(z3.url()).optional(),
|
|
112
|
+
email: z3.string().trim().max(320).pipe(z3.email()).optional(),
|
|
113
|
+
name: z3.string().trim().max(120).optional()
|
|
114
|
+
});
|
|
115
|
+
var createAgentAuthTokenRequestSchema = z3.object({
|
|
116
|
+
/**
|
|
117
|
+
* Browser-scoped id the SDK passed to the host callback. Sending it together
|
|
118
|
+
* with an identified `identity` merges that anonymous person's conversations
|
|
119
|
+
* into the identified user, so history survives login.
|
|
120
|
+
*/
|
|
121
|
+
anonymousId: agentIdentityIdSchema.optional(),
|
|
122
|
+
identity: agentAuthIdentitySchema,
|
|
123
|
+
profile: agentAuthProfileSchema.optional()
|
|
124
|
+
});
|
|
125
|
+
var agentAuthTokenSchema = z3.object({
|
|
126
|
+
expiresAt: z3.number().int().positive(),
|
|
127
|
+
token: z3.string().trim().min(1)
|
|
128
|
+
});
|
|
129
|
+
var agentTokenClaimsSchema = z3.object({
|
|
130
|
+
agentId: z3.string().trim().min(1).max(100),
|
|
131
|
+
apiKeyId: z3.string().trim().min(1).max(100),
|
|
132
|
+
aud: z3.literal("heroui-agent"),
|
|
133
|
+
exp: z3.number().int().positive(),
|
|
134
|
+
iat: z3.number().int().positive(),
|
|
135
|
+
iss: z3.literal("https://api.heroui.com"),
|
|
136
|
+
jti: z3.uuid(),
|
|
137
|
+
protocolVersion: z3.literal(HEROUI_AGENT_PROTOCOL_VERSION),
|
|
138
|
+
sub: z3.string().trim().min(1).max(200)
|
|
139
|
+
});
|
|
140
|
+
var trustedAgentClientDataSchema = z3.object({
|
|
141
|
+
agentId: z3.string(),
|
|
142
|
+
billingLicenseId: z3.string().nullable(),
|
|
143
|
+
billingOwnerUserId: z3.string(),
|
|
144
|
+
/**
|
|
145
|
+
* Browser-declared client tools the embed can execute for this turn. The
|
|
146
|
+
* runtime registers them as model-visible tools without an execute function.
|
|
147
|
+
*/
|
|
148
|
+
clientTools: clientToolsSchema.default([]),
|
|
149
|
+
conversationId: z3.uuid(),
|
|
150
|
+
/**
|
|
151
|
+
* Pseudonymous identity used by persisted conversations. This is signed by
|
|
152
|
+
* the API so the runtime can link telemetry without handling a raw identity.
|
|
153
|
+
*/
|
|
154
|
+
endUserKey: z3.string().trim().min(1).max(200).optional(),
|
|
155
|
+
/**
|
|
156
|
+
* When web search is enabled, allow image results via `includeImages`.
|
|
157
|
+
* Defaults to true at the host when omitted; optional here so signed
|
|
158
|
+
* payloads without the field stay valid and keep image search on.
|
|
159
|
+
*/
|
|
160
|
+
imageSearch: z3.boolean().optional(),
|
|
161
|
+
/**
|
|
162
|
+
* Optional browser-selected OpenRouter model. The API accepts only the
|
|
163
|
+
* fixed agent allowlist and signs the value before the runtime sees it.
|
|
164
|
+
*/
|
|
165
|
+
modelId: agentModelIdSchema.optional(),
|
|
166
|
+
pageContext: pageContextSchema.default({}),
|
|
167
|
+
/**
|
|
168
|
+
* Set by the API when the session was authorized by a dashboard preview
|
|
169
|
+
* credential rather than a host API key, so operator traffic can be separated
|
|
170
|
+
* from real visitors. Optional (not defaulted) to keep older signed payloads
|
|
171
|
+
* valid.
|
|
172
|
+
*/
|
|
173
|
+
preview: z3.boolean().optional(),
|
|
174
|
+
protocolVersion: z3.literal(HEROUI_AGENT_PROTOCOL_VERSION),
|
|
175
|
+
requestId: z3.uuid(),
|
|
176
|
+
sdkVersion: z3.string().trim().min(1).max(80),
|
|
177
|
+
signedAt: z3.number(),
|
|
178
|
+
subject: z3.string(),
|
|
179
|
+
/**
|
|
180
|
+
* Host-enabled public web search. When true the runtime registers the
|
|
181
|
+
* `searchWeb` tool (if the search backend is configured) so the agent can
|
|
182
|
+
* look up public information and images. Optional (not defaulted) so schema
|
|
183
|
+
* parsing never injects a field into an already-signed payload.
|
|
184
|
+
*/
|
|
185
|
+
webSearch: z3.boolean().optional()
|
|
186
|
+
});
|
|
187
|
+
var signedTrustedAgentClientDataSchema = trustedAgentClientDataSchema.extend({
|
|
188
|
+
sig: z3.string().min(1)
|
|
189
|
+
});
|
|
190
|
+
var agentProjectConfigSchema = z3.object({
|
|
191
|
+
agentId: z3.string(),
|
|
192
|
+
minimumProtocolVersion: z3.literal(HEROUI_AGENT_PROTOCOL_VERSION),
|
|
193
|
+
name: z3.string().trim().min(1).max(120),
|
|
194
|
+
protocolVersion: z3.literal(HEROUI_AGENT_PROTOCOL_VERSION),
|
|
195
|
+
/**
|
|
196
|
+
* Internal streaming infrastructure endpoint, resolved server-side so
|
|
197
|
+
* customers never configure it. Optional for compatibility with older API
|
|
198
|
+
* deployments; the SDK falls back to Trigger.dev's public endpoint.
|
|
199
|
+
*/
|
|
200
|
+
realtime: z3.object({ url: z3.url() }).optional(),
|
|
201
|
+
sdkVersion: z3.string().default(HEROUI_AGENT_SDK_VERSION),
|
|
202
|
+
suggestedPrompts: z3.array(z3.string().trim().min(1).max(160)).max(5),
|
|
203
|
+
surfaceVariant: agentSurfaceVariantSchema.default("plain"),
|
|
204
|
+
theme: agentThemeSchema
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
// src/server/index.ts
|
|
208
|
+
var DEFAULT_API_BASE_URL = "https://api.heroui.com";
|
|
209
|
+
var HeroUIAgentAuthError = class extends Error {
|
|
210
|
+
status;
|
|
211
|
+
constructor(message, status, options) {
|
|
212
|
+
super(message, options);
|
|
213
|
+
this.name = "HeroUIAgentAuthError";
|
|
214
|
+
this.status = status;
|
|
215
|
+
}
|
|
216
|
+
};
|
|
217
|
+
async function createAuthToken(options) {
|
|
218
|
+
const apiKey = options.apiKey.trim();
|
|
219
|
+
const agentId = options.agentId.trim();
|
|
220
|
+
const request = createAgentAuthTokenRequestSchema.safeParse({
|
|
221
|
+
anonymousId: options.anonymousId,
|
|
222
|
+
identity: options.identity,
|
|
223
|
+
profile: options.profile
|
|
224
|
+
});
|
|
225
|
+
if (!apiKey || !agentId || !request.success) {
|
|
226
|
+
throw new HeroUIAgentAuthError("Invalid HeroUI Agent auth token request", 400);
|
|
227
|
+
}
|
|
228
|
+
const apiBaseUrl = (options.apiBaseUrl?.trim() || DEFAULT_API_BASE_URL).replace(/\/$/, "");
|
|
229
|
+
let response;
|
|
230
|
+
try {
|
|
231
|
+
response = await fetch(`${apiBaseUrl}/v1/agents/${encodeURIComponent(agentId)}/auth-tokens`, {
|
|
232
|
+
body: JSON.stringify(request.data),
|
|
233
|
+
cache: "no-store",
|
|
234
|
+
headers: {
|
|
235
|
+
Accept: "application/json",
|
|
236
|
+
"Content-Type": "application/json",
|
|
237
|
+
"X-HeroUI-Agent-Key": apiKey
|
|
238
|
+
},
|
|
239
|
+
method: "POST"
|
|
240
|
+
});
|
|
241
|
+
} catch (cause) {
|
|
242
|
+
throw new HeroUIAgentAuthError("HeroUI Agent authentication is unavailable", 503, { cause });
|
|
243
|
+
}
|
|
244
|
+
if (!response.ok) {
|
|
245
|
+
throw new HeroUIAgentAuthError("HeroUI Agent authentication failed", response.status);
|
|
246
|
+
}
|
|
247
|
+
const parsed = agentAuthTokenSchema.safeParse(await response.json().catch(() => null));
|
|
248
|
+
if (!parsed.success) {
|
|
249
|
+
throw new HeroUIAgentAuthError("HeroUI Agent authentication returned invalid data", 502);
|
|
250
|
+
}
|
|
251
|
+
return parsed.data;
|
|
252
|
+
}
|
|
253
|
+
export {
|
|
254
|
+
HeroUIAgentAuthError,
|
|
255
|
+
createAuthToken
|
|
256
|
+
};
|