@heroui/agent 0.2.0-beta.2 → 0.2.0-beta.4

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 CHANGED
@@ -1,5 +1,25 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.2.0-beta.4
4
+
5
+ - Add `reopenOnRefresh` and `startNewConversationOnOpen` controls for predictable panel and
6
+ conversation startup behavior.
7
+ - Keep the active turn anchored while responses stream, with smoother scrolling and clearer
8
+ startup and tool activity states.
9
+ - Lazy-load generated UI, submit follow-up actions immediately, and add formatted table copying
10
+ alongside existing exports.
11
+ - Route browser messages and answer streams through the HeroUI API while keeping lightweight
12
+ viewer presence on the realtime connection.
13
+ - Update the default Agent model to Luna and align the SDK, examples, dashboard preview, and docs.
14
+
15
+ ## 0.2.0-beta.3
16
+
17
+ - Move comprehensive Agent checks to pull requests so releases only validate versions, build,
18
+ package, publish, and verify `@heroui/agent`.
19
+ - Publish the package tarball directly without rebuilding unrelated applications, including the
20
+ Next.js demo.
21
+ - Retry npm registry and dist-tag verification while newly published versions propagate.
22
+
3
23
  ## 0.2.0-beta.2
4
24
 
5
25
  - Expand data visualization with candlestick, vertical and horizontal funnel, radial and linear
package/README.md CHANGED
@@ -169,16 +169,16 @@ Projects and API keys are managed in the [Agents dashboard](https://heroui.pro/d
169
169
 
170
170
  ## What runs where
171
171
 
172
- The browser sends every message through the HeroUI API, which owns the model,
173
- the durable run, the conversation store, and server-side tools. Answers stream
174
- back over a direct read-only realtime connection so tokens and client-tool
175
- calls arrive without an API proxy hop.
176
-
177
- | In the browser | Behind the HeroUI API |
178
- | -------------------------------------------- | -------------------------------------------- |
179
- | Panel, theme, composer, generated UI | Model orchestration and the durable run |
180
- | Client tools, running as the signed-in user | Server tools, MCP servers, knowledge search |
181
- | A short-lived, read-only answer stream token | Runtime credentials and conversation storage |
172
+ The browser sends every message and receives every answer stream through the HeroUI API, which
173
+ owns the model, the durable run, the conversation store, and server-side tools. Ephemeral
174
+ "watching now" presence remains a direct InstantDB room connection; it carries only conversation
175
+ and pseudonymous viewer identifiers, never messages or tool data.
176
+
177
+ | In the browser | Behind the HeroUI API |
178
+ | ------------------------------------------- | -------------------------------------------- |
179
+ | Panel, theme, composer, generated UI | Model orchestration and the durable run |
180
+ | Client tools, running as the signed-in user | Server tools, MCP servers, knowledge search |
181
+ | A short-lived HeroUI browser credential | Runtime credentials and conversation storage |
182
182
 
183
183
  ## Compatibility
184
184
 
@@ -8,7 +8,7 @@ import {
8
8
  paletteChartColor,
9
9
  resolveChartColor,
10
10
  resolveGaugeBounds
11
- } from "./chunk-AEUPMIPT.js";
11
+ } from "./chunk-FNGGMHVR.js";
12
12
  import {
13
13
  Card
14
14
  } from "./chunk-TOOT6SZ2.js";
@@ -10,7 +10,7 @@ import {
10
10
  resolveOptions,
11
11
  scheduleIdleTask,
12
12
  writeAgentShellHandoff
13
- } from "./chunk-EXFDD3K3.js";
13
+ } from "./chunk-XBYPU7PM.js";
14
14
 
15
15
  // src/embed/provider.tsx
16
16
  import {
@@ -508,11 +508,30 @@ function loadAgentWebfont(font) {
508
508
  import { Fragment as Fragment2, jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
509
509
  var REMOTE_CONFIG_PAINT_BUDGET_MS = 600;
510
510
  var RUNTIME_PREFETCH_IDLE_TIMEOUT_MS = 1200;
511
+ var OPEN_STATE_STORAGE_PREFIX = "heroui-agent:open:";
512
+ function openStateStorageKey(agentId) {
513
+ return `${OPEN_STATE_STORAGE_PREFIX}${agentId}`;
514
+ }
515
+ function readOpenState(agentId) {
516
+ if (typeof window === "undefined") return false;
517
+ try {
518
+ return window.sessionStorage.getItem(openStateStorageKey(agentId)) === "true";
519
+ } catch {
520
+ return false;
521
+ }
522
+ }
523
+ function writeOpenState(agentId, open) {
524
+ try {
525
+ if (open) window.sessionStorage.setItem(openStateStorageKey(agentId), "true");
526
+ else window.sessionStorage.removeItem(openStateStorageKey(agentId));
527
+ } catch {
528
+ }
529
+ }
511
530
  var embedRuntimePromise;
512
531
  function loadEmbedRuntime() {
513
532
  embedRuntimePromise ??= import(
514
533
  /* webpackPrefetch: true */
515
- "./embed-runtime-QOATFAS7.js"
534
+ "./embed-runtime-WVXLM2KL.js"
516
535
  ).then(
517
536
  (module) => module.default
518
537
  );
@@ -603,8 +622,10 @@ function HeroUIAgent(props) {
603
622
  permissions,
604
623
  preload: preloadEnabled,
605
624
  remoteConfig: remoteConfigEnabled = true,
625
+ reopenOnRefresh,
606
626
  responseActions,
607
627
  showLauncher,
628
+ startNewConversationOnOpen,
608
629
  startScreen,
609
630
  tools
610
631
  } = props;
@@ -625,8 +646,10 @@ function HeroUIAgent(props) {
625
646
  permissions,
626
647
  preload: preloadEnabled,
627
648
  remote: remoteConfig,
649
+ reopenOnRefresh,
628
650
  responseActions,
629
651
  showLauncher,
652
+ startNewConversationOnOpen,
630
653
  startScreen
631
654
  });
632
655
  const options = useMemo(() => {
@@ -650,12 +673,13 @@ function HeroUIAgent(props) {
650
673
  if (hostFont) return;
651
674
  return loadAgentWebfont(remoteWebfont);
652
675
  }, [hostFont, remoteWebfont]);
653
- const [isOpen, setIsOpen] = useState2(false);
676
+ const [restoredOpenState] = useState2(() => reopenOnRefresh === true && readOpenState(agentId));
677
+ const [isOpen, setIsOpen] = useState2(restoredOpenState);
654
678
  const [conversationEpoch, setConversationEpoch] = useState2(1);
655
679
  const [identityEpoch, setIdentityEpoch] = useState2(1);
656
680
  const [identityReset, setIdentityReset] = useState2(false);
657
681
  const [requestedConversationId, setRequestedConversationId] = useState2(
658
- void 0
682
+ restoredOpenState || options.startNewConversationOnOpen ? null : void 0
659
683
  );
660
684
  const [portalRoot, setPortalRoot] = useState2(null);
661
685
  const [EmbedRuntime, setEmbedRuntime] = useState2(null);
@@ -663,7 +687,7 @@ function HeroUIAgent(props) {
663
687
  const launcherRef = useRef2(null);
664
688
  const portalRootRef = useRef2(null);
665
689
  const readyEpochRef = useRef2(null);
666
- const shouldOpenRef = useRef2(false);
690
+ const shouldOpenRef = useRef2(restoredOpenState);
667
691
  const hostRef = useRef2(null);
668
692
  const embedReactRootRef = useRef2(null);
669
693
  const rootPropertyNamesRef = useRef2([]);
@@ -673,10 +697,14 @@ function HeroUIAgent(props) {
673
697
  () => false
674
698
  );
675
699
  const designThemeClass = options.designTheme === "base" ? null : `${options.designTheme}-${options.colorScheme === "system" ? prefersDark ? "dark" : "light" : options.colorScheme}`;
676
- const [shouldLoadRuntime, setShouldLoadRuntime] = useState2(false);
700
+ const [shouldLoadRuntime, setShouldLoadRuntime] = useState2(restoredOpenState);
677
701
  const requestRuntime = useCallback(() => setShouldLoadRuntime(true), []);
678
702
  const [preloadRequested, setPreloadRequested] = useState2(false);
679
703
  const shouldWarmSession = options.preload || preloadRequested;
704
+ useEffect2(() => {
705
+ if (options.reopenOnRefresh) writeOpenState(options.agentId, isOpen);
706
+ else writeOpenState(options.agentId, false);
707
+ }, [isOpen, options.agentId, options.reopenOnRefresh]);
680
708
  useEffect2(() => {
681
709
  if (!options.preload || shouldLoadRuntime) return;
682
710
  return scheduleIdleTask(requestRuntime, RUNTIME_PREFETCH_IDLE_TIMEOUT_MS);
@@ -797,9 +825,9 @@ function HeroUIAgent(props) {
797
825
  const hide = useCallback(() => {
798
826
  shouldOpenRef.current = false;
799
827
  setIsOpen(false);
800
- prepareNextConversation();
828
+ prepareNextConversation(options.startNewConversationOnOpen ? null : void 0);
801
829
  requestAnimationFrame(() => launcherRef.current?.focus());
802
- }, [prepareNextConversation]);
830
+ }, [options.startNewConversationOnOpen, prepareNextConversation]);
803
831
  const show = useCallback(() => {
804
832
  shouldOpenRef.current = true;
805
833
  requestRuntime();
@@ -843,6 +871,7 @@ function HeroUIAgent(props) {
843
871
  }
844
872
  shouldOpenRef.current = false;
845
873
  setIsOpen(false);
874
+ writeOpenState(options.agentId, false);
846
875
  setIdentityReset(true);
847
876
  setIdentityEpoch((epoch) => epoch + 1);
848
877
  prepareNextConversation();
@@ -906,19 +935,19 @@ function HeroUIAgent(props) {
906
935
  ) : /* @__PURE__ */ jsx4(
907
936
  PanelShell,
908
937
  {
938
+ agentId: options.agentId,
909
939
  defaultExpanded: options.panelExpanded,
910
940
  expandable: options.panelExpandable,
911
941
  modal: options.viewMode !== "sidebar",
912
942
  name: "Data assistant",
913
943
  open: isOpen,
914
- agentId: options.agentId,
915
944
  onClose: hide,
916
945
  children: /* @__PURE__ */ jsx4(
917
946
  ShellConversation,
918
947
  {
948
+ agentId: options.agentId,
919
949
  greeting: options.greeting,
920
950
  placeholder: options.composerPlaceholder,
921
- agentId: options.agentId,
922
951
  suggestedPrompts: options.suggestedPrompts ?? [],
923
952
  onIntent: requestRuntime
924
953
  }
@@ -2,42 +2,9 @@ import {
2
2
  mergeClassNames
3
3
  } from "./chunk-3FG5NRTX.js";
4
4
 
5
- // ../agent-ui/src/components/component-renderer/component-skeleton.tsx
6
- import { jsx, jsxs } from "react/jsx-runtime";
7
- function skeletonCategory(kind) {
8
- if (kind === "dashboard" || kind === "product-signals" || kind === "card" || kind === "col" || kind === "grid" || kind === "item-card" || kind === "item-card-group" || kind === "row")
9
- return "dashboard";
10
- if (kind === "metric-grid" || kind === "kpi-grid") return "metrics";
11
- if (kind === "map") return "map";
12
- if (kind === "data-table") return "table";
13
- if (kind === "record-card" || kind === "channel-message" || kind === "create-event" || kind === "enable-notification" || kind === "event-session" || kind === "flight-tracker" || kind === "player-card" || kind === "playlist" || kind === "purchase-complete" || kind === "purchase-items" || kind === "ride-status" || kind === "view-event" || kind === "weather-current" || kind === "weather-forecast")
14
- return "record";
15
- return "chart";
16
- }
17
- function ComponentSkeleton({ className, kind, title }) {
18
- const category = skeletonCategory(kind);
19
- return /* @__PURE__ */ jsxs(
20
- "section",
21
- {
22
- "aria-busy": "true",
23
- "aria-label": title ? `Loading ${title}` : "Loading data view",
24
- className: mergeClassNames("aui-skeleton", className),
25
- "data-component-kind": kind,
26
- "data-skeleton-category": category,
27
- "data-slot": "agent-ui-skeleton",
28
- role: "status",
29
- children: [
30
- /* @__PURE__ */ jsx("div", { className: "aui-skeleton__header", "data-slot": "agent-ui-skeleton-header" }),
31
- /* @__PURE__ */ jsx("div", { className: "aui-skeleton__content", "data-slot": "agent-ui-skeleton-content", children: category === "metrics" || category === "dashboard" ? Array.from({ length: category === "dashboard" ? 2 : 4 }, (_, index) => /* @__PURE__ */ jsx("span", { className: "aui-skeleton__panel" }, index)) : category === "table" || category === "record" ? Array.from({ length: category === "table" ? 5 : 4 }, (_, index) => /* @__PURE__ */ jsx("span", { className: "aui-skeleton__row" }, index)) : /* @__PURE__ */ jsx("span", { className: "aui-skeleton__chart" }) }),
32
- /* @__PURE__ */ jsx("span", { className: "aui-sr-only", "data-slot": "agent-ui-skeleton-label", children: "Loading data view\u2026" })
33
- ]
34
- }
35
- );
36
- }
37
-
38
5
  // ../agent-ui/src/components/display-information/scroll-shadow/scroll-shadow.tsx
39
6
  import { useCallback, useEffect, useRef } from "react";
40
- import { jsx as jsx2 } from "react/jsx-runtime";
7
+ import { jsx } from "react/jsx-runtime";
41
8
  function ScrollShadow({
42
9
  children,
43
10
  className,
@@ -82,7 +49,7 @@ function ScrollShadow({
82
49
  previousVisibility.current = null;
83
50
  };
84
51
  }, [updateVisibility]);
85
- return /* @__PURE__ */ jsx2(
52
+ return /* @__PURE__ */ jsx(
86
53
  "div",
87
54
  {
88
55
  ref,
@@ -96,7 +63,7 @@ function ScrollShadow({
96
63
  }
97
64
 
98
65
  // ../agent-ui/src/utils/inline-markdown.tsx
99
- import { jsx as jsx3 } from "react/jsx-runtime";
66
+ import { jsx as jsx2 } from "react/jsx-runtime";
100
67
  var INLINE_TOKEN = /(\*\*[^*\n]+\*\*|\*[^*\s][^*\n]*\*|_[^_\s][^_\n]*_|`[^`\n]+`|\[[^\]\n]+\]\([^\s)\n]+\))/g;
101
68
  var LINK_TOKEN = /^\[([^\]]+)\]\(([^\s)]+)\)$/;
102
69
  var BARE_DOMAIN = /^(?:[a-z\d](?:[a-z\d-]{0,61}[a-z\d])?\.)+[a-z]{2,63}(?::\d{1,5})?(?:[/?#][^\s]*)?$/i;
@@ -119,31 +86,31 @@ function renderInlineMarkdown(text) {
119
86
  const key = `${part}:${occurrence}`;
120
87
  occurrences.set(part, occurrence);
121
88
  if (part.startsWith("**") && part.endsWith("**") && part.length > 4)
122
- return /* @__PURE__ */ jsx3("strong", { children: part.slice(2, -2) }, key);
89
+ return /* @__PURE__ */ jsx2("strong", { children: part.slice(2, -2) }, key);
123
90
  if (part.startsWith("*") && part.endsWith("*") && part.length > 2)
124
- return /* @__PURE__ */ jsx3("em", { children: part.slice(1, -1) }, key);
91
+ return /* @__PURE__ */ jsx2("em", { children: part.slice(1, -1) }, key);
125
92
  if (part.startsWith("_") && part.endsWith("_") && part.length > 2)
126
- return /* @__PURE__ */ jsx3("em", { children: part.slice(1, -1) }, key);
93
+ return /* @__PURE__ */ jsx2("em", { children: part.slice(1, -1) }, key);
127
94
  if (part.startsWith("`") && part.endsWith("`") && part.length > 2)
128
- return /* @__PURE__ */ jsx3("code", { children: part.slice(1, -1) }, key);
95
+ return /* @__PURE__ */ jsx2("code", { children: part.slice(1, -1) }, key);
129
96
  const link = LINK_TOKEN.exec(part);
130
97
  const target = link?.[2];
131
98
  const href = target ? resolveLinkHref(target) : void 0;
132
99
  if (link && href)
133
- return /* @__PURE__ */ jsx3("a", { href, rel: "noopener noreferrer", target: "_blank", children: link[1] }, key);
100
+ return /* @__PURE__ */ jsx2("a", { href, rel: "noopener noreferrer", target: "_blank", children: link[1] }, key);
134
101
  return part;
135
102
  });
136
103
  }
137
104
 
138
105
  // ../agent-ui/src/components/actions/action-button.tsx
139
- import { jsx as jsx4 } from "react/jsx-runtime";
106
+ import { jsx as jsx3 } from "react/jsx-runtime";
140
107
  function ActionButton({
141
108
  className,
142
109
  size = "sm",
143
110
  variant = "secondary",
144
111
  ...props
145
112
  }) {
146
- return /* @__PURE__ */ jsx4(
113
+ return /* @__PURE__ */ jsx3(
147
114
  "button",
148
115
  {
149
116
  className: mergeClassNames("aui-button", className),
@@ -159,7 +126,7 @@ function ActionButton({
159
126
  // ../agent-ui/src/components/display-information/code-block.tsx
160
127
  import { Button } from "@heroui/react";
161
128
  import { useEffect as useEffect2, useRef as useRef2, useState } from "react";
162
- import { jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
129
+ import { jsx as jsx4, jsxs } from "react/jsx-runtime";
163
130
  var COPY_RESET_DELAY = 2e3;
164
131
  var DEFAULT_DARK_THEME = "github-dark";
165
132
  var DEFAULT_LIGHT_THEME = "github-light";
@@ -240,7 +207,7 @@ async function copyText(text) {
240
207
  }
241
208
  }
242
209
  function CodeGlyph() {
243
- return /* @__PURE__ */ jsx5("svg", { "aria-hidden": "true", fill: "none", viewBox: "0 0 16 16", children: /* @__PURE__ */ jsx5(
210
+ return /* @__PURE__ */ jsx4("svg", { "aria-hidden": "true", fill: "none", viewBox: "0 0 16 16", children: /* @__PURE__ */ jsx4(
244
211
  "path",
245
212
  {
246
213
  clipRule: "evenodd",
@@ -251,7 +218,7 @@ function CodeGlyph() {
251
218
  ) });
252
219
  }
253
220
  function CopyGlyph() {
254
- return /* @__PURE__ */ jsx5("svg", { "aria-hidden": "true", fill: "none", viewBox: "0 0 16 16", children: /* @__PURE__ */ jsx5(
221
+ return /* @__PURE__ */ jsx4("svg", { "aria-hidden": "true", fill: "none", viewBox: "0 0 16 16", children: /* @__PURE__ */ jsx4(
255
222
  "path",
256
223
  {
257
224
  clipRule: "evenodd",
@@ -262,7 +229,7 @@ function CopyGlyph() {
262
229
  ) });
263
230
  }
264
231
  function CheckGlyph() {
265
- return /* @__PURE__ */ jsx5("svg", { "aria-hidden": "true", fill: "none", viewBox: "0 0 16 16", children: /* @__PURE__ */ jsx5(
232
+ return /* @__PURE__ */ jsx4("svg", { "aria-hidden": "true", fill: "none", viewBox: "0 0 16 16", children: /* @__PURE__ */ jsx4(
266
233
  "path",
267
234
  {
268
235
  clipRule: "evenodd",
@@ -308,13 +275,13 @@ function CodeBlock({ code, language = "text" }) {
308
275
  }, COPY_RESET_DELAY);
309
276
  }
310
277
  };
311
- return /* @__PURE__ */ jsxs2("div", { className: "aui-code", "data-slot": "agent-ui-code-block", children: [
312
- /* @__PURE__ */ jsxs2("header", { className: "aui-code__header", "data-slot": "agent-ui-code-header", children: [
313
- /* @__PURE__ */ jsxs2("span", { className: "aui-code__language", children: [
314
- /* @__PURE__ */ jsx5(CodeGlyph, {}),
315
- /* @__PURE__ */ jsx5("span", { children: language.toUpperCase() })
278
+ return /* @__PURE__ */ jsxs("div", { className: "aui-code", "data-slot": "agent-ui-code-block", children: [
279
+ /* @__PURE__ */ jsxs("header", { className: "aui-code__header", "data-slot": "agent-ui-code-header", children: [
280
+ /* @__PURE__ */ jsxs("span", { className: "aui-code__language", children: [
281
+ /* @__PURE__ */ jsx4(CodeGlyph, {}),
282
+ /* @__PURE__ */ jsx4("span", { children: language.toUpperCase() })
316
283
  ] }),
317
- /* @__PURE__ */ jsx5(
284
+ /* @__PURE__ */ jsx4(
318
285
  Button,
319
286
  {
320
287
  isIconOnly: true,
@@ -324,35 +291,34 @@ function CodeBlock({ code, language = "text" }) {
324
291
  size: "sm",
325
292
  variant: "ghost",
326
293
  onPress: copy,
327
- children: /* @__PURE__ */ jsxs2(
294
+ children: /* @__PURE__ */ jsxs(
328
295
  "span",
329
296
  {
330
297
  className: "aui-code__copy-swap",
331
298
  "data-copied": copied || void 0,
332
299
  "data-slot": "agent-ui-code-copy-icon",
333
300
  children: [
334
- /* @__PURE__ */ jsx5("span", { className: "aui-code__copy-icon aui-code__copy-icon--copy", children: /* @__PURE__ */ jsx5(CopyGlyph, {}) }),
335
- /* @__PURE__ */ jsx5("span", { className: "aui-code__copy-icon aui-code__copy-icon--check", children: /* @__PURE__ */ jsx5(CheckGlyph, {}) })
301
+ /* @__PURE__ */ jsx4("span", { className: "aui-code__copy-icon aui-code__copy-icon--copy", children: /* @__PURE__ */ jsx4(CopyGlyph, {}) }),
302
+ /* @__PURE__ */ jsx4("span", { className: "aui-code__copy-icon aui-code__copy-icon--check", children: /* @__PURE__ */ jsx4(CheckGlyph, {}) })
336
303
  ]
337
304
  }
338
305
  )
339
306
  }
340
307
  )
341
308
  ] }),
342
- highlighted?.key === highlightKey ? /* @__PURE__ */ jsx5(
309
+ highlighted?.key === highlightKey ? /* @__PURE__ */ jsx4(
343
310
  "div",
344
311
  {
345
312
  className: "aui-code__content",
346
313
  dangerouslySetInnerHTML: { __html: highlighted.html },
347
314
  "data-slot": "agent-ui-code"
348
315
  }
349
- ) : /* @__PURE__ */ jsx5("div", { className: "aui-code__content", "data-slot": "agent-ui-code", children: /* @__PURE__ */ jsx5("pre", { children: /* @__PURE__ */ jsx5("code", { children: code }) }) })
316
+ ) : /* @__PURE__ */ jsx4("div", { className: "aui-code__content", "data-slot": "agent-ui-code", children: /* @__PURE__ */ jsx4("pre", { children: /* @__PURE__ */ jsx4("code", { children: code }) }) })
350
317
  ] });
351
318
  }
352
319
 
353
320
  export {
354
321
  ActionButton,
355
- ComponentSkeleton,
356
322
  ScrollShadow,
357
323
  renderInlineMarkdown,
358
324
  CodeBlock
@@ -80,7 +80,15 @@ function formatCell(value, format, locale = "en") {
80
80
  }
81
81
 
82
82
  // ../agent-ui/src/components/component-actions/export-actions.tsx
83
- import { ChartColumn, Ellipsis, FileCode, FileText, LayoutCells, Picture } from "@gravity-ui/icons";
83
+ import {
84
+ ChartColumn,
85
+ Copy,
86
+ Ellipsis,
87
+ FileCode,
88
+ FileText,
89
+ LayoutCells,
90
+ Picture
91
+ } from "@gravity-ui/icons";
84
92
  import { Button, Dropdown, Label } from "@heroui/react";
85
93
  import { useCallback, useRef, useState } from "react";
86
94
 
@@ -268,6 +276,17 @@ function componentToCsv(component) {
268
276
  ...rows.map((row) => keys.map((key) => csvCell(row[key])).join(","))
269
277
  ].join("\n");
270
278
  }
279
+ function tableTextCell(value) {
280
+ return value.replace(/[\t\r\n]+/g, " ");
281
+ }
282
+ function componentToTableText(component) {
283
+ return [
284
+ component.columns.map((column) => tableTextCell(column.label)).join(" "),
285
+ ...component.rows.map(
286
+ (row) => component.columns.map((column) => tableTextCell(formatCell(row[column.key], column.format))).join(" ")
287
+ )
288
+ ].join("\n");
289
+ }
271
290
  var SVG_STYLE_TOKENS = [
272
291
  "--accent",
273
292
  "--border",
@@ -419,6 +438,23 @@ function exportComponent(button, component, format) {
419
438
  void exportPng(button, component.title).catch(() => void 0);
420
439
  }
421
440
  }
441
+ async function copyComponent(component, format) {
442
+ const content = format === "json" ? JSON.stringify(component, null, 2) : component.kind === "data-table" ? componentToTableText(component) : component.kind === "record-card" ? [
443
+ component.title,
444
+ component.description,
445
+ component.status?.label,
446
+ ...component.fields.map((field) => `${field.label}: ${field.value}`)
447
+ ].filter(Boolean).join("\n") : component.kind === "product-card" ? [
448
+ component.title,
449
+ component.description,
450
+ ...component.products.flatMap((product) => [
451
+ [product.name, product.meta].filter(Boolean).join(" \xB7 "),
452
+ `${product.price.currency ?? "USD"} ${product.price.amount}`,
453
+ product.rating ? `Rated ${product.rating.value}/5${product.rating.count === void 0 ? "" : ` (${product.rating.count})`}` : void 0
454
+ ])
455
+ ].filter(Boolean).join("\n") : JSON.stringify(component);
456
+ await navigator.clipboard?.writeText(content);
457
+ }
422
458
 
423
459
  // ../agent-ui/src/components/component-actions/export-actions.tsx
424
460
  import { jsx, jsxs } from "react/jsx-runtime";
@@ -434,6 +470,7 @@ var FORMAT_ICONS = {
434
470
  };
435
471
  function ComponentExportActions({
436
472
  component,
473
+ copyAction,
437
474
  formats = [],
438
475
  onAction,
439
476
  viewAction
@@ -451,8 +488,8 @@ function ComponentExportActions({
451
488
  setPortalContainer(resolveOverlayPortalContainer(node));
452
489
  }, []);
453
490
  const supported = formats.filter((format) => format !== "csv" || componentToCsv(component));
454
- const triggerLabel = viewAction ? `${supported.length > 0 ? "View and export" : "View"} options for ${component.title}` : `Export options for ${component.title}`;
455
- if (supported.length === 0 && !viewAction) return null;
491
+ const triggerLabel = copyAction ? `Table options for ${component.title}` : viewAction ? `${supported.length > 0 ? "View and export" : "View"} options for ${component.title}` : `Export options for ${component.title}`;
492
+ if (supported.length === 0 && !viewAction && !copyAction) return null;
456
493
  return /* @__PURE__ */ jsx("div", { className: "aui-export-actions", "data-slot": "agent-ui-export-actions", children: /* @__PURE__ */ jsxs(Dropdown, { isOpen, onOpenChange: handleOpenChange, children: [
457
494
  /* @__PURE__ */ jsx(
458
495
  Button,
@@ -477,6 +514,12 @@ function ComponentExportActions({
477
514
  setIsOpen(false);
478
515
  return;
479
516
  }
517
+ if (key === "copy") {
518
+ copyAction?.();
519
+ onAction?.({ componentId: component.id, format: "text", type: "copy" });
520
+ setIsOpen(false);
521
+ return;
522
+ }
480
523
  const format = key;
481
524
  if (triggerRef.current) exportComponent(triggerRef.current, component, format);
482
525
  onAction?.({ componentId: component.id, format, type: "export" });
@@ -487,6 +530,10 @@ function ComponentExportActions({
487
530
  viewAction.target === "table" ? /* @__PURE__ */ jsx(LayoutCells, { "aria-hidden": "true", className: "size-4 shrink-0" }) : /* @__PURE__ */ jsx(ChartColumn, { "aria-hidden": "true", className: "size-4 shrink-0" }),
488
531
  /* @__PURE__ */ jsx(Label, { children: viewAction.label })
489
532
  ] }) : null,
533
+ copyAction ? /* @__PURE__ */ jsxs(Dropdown.Item, { id: "copy", textValue: "Copy table", children: [
534
+ /* @__PURE__ */ jsx(Copy, { "aria-hidden": "true", className: "size-4 shrink-0" }),
535
+ /* @__PURE__ */ jsx(Label, { children: "Copy table" })
536
+ ] }) : null,
490
537
  supported.map((format) => {
491
538
  const FormatIcon = FORMAT_ICONS[format];
492
539
  return /* @__PURE__ */ jsxs(Dropdown.Item, { id: format, textValue: FORMAT_LABELS[format], children: [
@@ -569,6 +616,7 @@ export {
569
616
  formatAxisValue,
570
617
  formatCell,
571
618
  chartToDataTable,
619
+ copyComponent,
572
620
  ComponentExportActions,
573
621
  TrendChange,
574
622
  CHART_COLOR_TOKENS,
@@ -420,7 +420,7 @@ function PanelShell({
420
420
  onClose();
421
421
  },
422
422
  children: [
423
- isDesktopSidebar && !isExpanded ? /* @__PURE__ */ jsx2(SidebarResizeHandle, { panelRef, agentId }) : null,
423
+ isDesktopSidebar && !isExpanded ? /* @__PURE__ */ jsx2(SidebarResizeHandle, { agentId, panelRef }) : null,
424
424
  showExpandedSidebar ? /* @__PURE__ */ jsx2("aside", { "aria-label": "Chat history", className: "ha-expanded-sidebar", children: expandedSidebarSlot }) : null,
425
425
  /* @__PURE__ */ jsxs2("div", { className: "ha-panel-main", children: [
426
426
  /* @__PURE__ */ jsxs2("header", { className: "ha-header", children: [
@@ -854,7 +854,7 @@ var LEGACY_AGENT_MODEL_IDS = {
854
854
  function resolveAgentModelId(value) {
855
855
  return LEGACY_AGENT_MODEL_IDS[value] ?? value;
856
856
  }
857
- var DEFAULT_AGENT_PICKER_MODEL_ID = "google/gemini-3.6-flash";
857
+ var DEFAULT_AGENT_PICKER_MODEL_ID = "openai/gpt-5.6-luna";
858
858
  var AGENT_MODEL_OPTIONS = [
859
859
  {
860
860
  description: "Flagship model for coding, reasoning, and knowledge work",
@@ -1015,7 +1015,9 @@ function resolveOptions(props) {
1015
1015
  permissionDefaultMode: resolveAgentPermissionMode(props.permissions?.defaultMode),
1016
1016
  permissionShowPicker: props.permissions?.showPicker === true,
1017
1017
  preload: props.preload ?? true,
1018
+ reopenOnRefresh: props.reopenOnRefresh ?? false,
1018
1019
  showLauncher: props.showLauncher ?? true,
1020
+ startNewConversationOnOpen: props.startNewConversationOnOpen ?? false,
1019
1021
  suggestedPromptShortcuts: props.startScreen?.promptShortcuts ?? false,
1020
1022
  ...props.appearance?.launcher?.icon?.trim() ? { launcherIcon: props.appearance.launcher.icon.trim() } : {},
1021
1023
  ...props.appearance?.launcher?.style ? { launcherStyle: props.appearance.launcher.style } : {},
@@ -1033,8 +1035,7 @@ function resolveOptions(props) {
1033
1035
  },
1034
1036
  tools: props.tools ?? [],
1035
1037
  viewMode: props.appearance?.viewMode ?? "floating",
1036
- webSearch: props.capabilities?.webSearch ?? false,
1037
- ...props._api?.realtimeUrl ? { triggerApiUrl: props._api.realtimeUrl.replace(/\/$/, "") } : {}
1038
+ webSearch: props.capabilities?.webSearch ?? false
1038
1039
  };
1039
1040
  }
1040
1041