@invergent/agent-chat-react 2.8.5 → 2.8.7

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/dist/index.cjs CHANGED
@@ -553,6 +553,13 @@ function BrowserControlBar({
553
553
  )
554
554
  ] });
555
555
  }
556
+ var MIN_ZOOM = 1;
557
+ var MAX_ZOOM = 3;
558
+ var ZOOM_STEP = 0.5;
559
+ function clampZoom(zoom) {
560
+ const bounded = Math.min(MAX_ZOOM, Math.max(MIN_ZOOM, zoom));
561
+ return Math.round(bounded * 100) / 100;
562
+ }
556
563
  function toWsUrl(src) {
557
564
  const url = new URL(src, window.location.href);
558
565
  if (url.protocol === "http:") {
@@ -571,10 +578,12 @@ function BrowserLiveView({
571
578
  const onDisconnectRef = react.useRef(onDisconnect);
572
579
  onDisconnectRef.current = onDisconnect;
573
580
  const [state, setState] = react.useState("connecting");
581
+ const [zoom, setZoom] = react.useState(MIN_ZOOM);
574
582
  react.useEffect(() => {
575
583
  const container = containerRef.current;
576
584
  if (!container) return;
577
585
  setState("connecting");
586
+ setZoom(MIN_ZOOM);
578
587
  let rfb;
579
588
  let disposed = false;
580
589
  const handleConnect = () => setState("connected");
@@ -605,8 +614,68 @@ function BrowserLiveView({
605
614
  }
606
615
  };
607
616
  }, [src]);
617
+ const keepCanvasFocus = (event) => event.preventDefault();
618
+ const zoomTo = (next) => setZoom((current) => clampZoom(next || current));
608
619
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative h-full w-full bg-black", children: [
609
- /* @__PURE__ */ jsxRuntime.jsx("div", { ref: containerRef, "data-testid": testId, className: "h-full w-full" }),
620
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 overflow-auto", children: /* @__PURE__ */ jsxRuntime.jsx(
621
+ "div",
622
+ {
623
+ ref: containerRef,
624
+ "data-testid": testId,
625
+ style: { width: `${zoom * 100}%`, height: `${zoom * 100}%` }
626
+ }
627
+ ) }),
628
+ state === "connected" && /* @__PURE__ */ jsxRuntime.jsxs(
629
+ "div",
630
+ {
631
+ "data-testid": "browser-rfb-zoom",
632
+ className: "absolute bottom-3 right-3 flex items-center gap-0.5 rounded-md border border-line bg-card/90 p-0.5 text-muted-foreground shadow-sm backdrop-blur",
633
+ children: [
634
+ /* @__PURE__ */ jsxRuntime.jsx(
635
+ "button",
636
+ {
637
+ type: "button",
638
+ tabIndex: -1,
639
+ "aria-label": "Zoom out",
640
+ disabled: zoom <= MIN_ZOOM,
641
+ onMouseDown: keepCanvasFocus,
642
+ onClick: () => zoomTo(zoom - ZOOM_STEP),
643
+ className: "flex size-6 items-center justify-center rounded text-sm leading-none hover:bg-accent hover:text-accent-foreground disabled:pointer-events-none disabled:opacity-40",
644
+ children: "\u2212"
645
+ }
646
+ ),
647
+ /* @__PURE__ */ jsxRuntime.jsxs(
648
+ "button",
649
+ {
650
+ type: "button",
651
+ tabIndex: -1,
652
+ "aria-label": "Reset zoom",
653
+ disabled: zoom === MIN_ZOOM,
654
+ onMouseDown: keepCanvasFocus,
655
+ onClick: () => setZoom(MIN_ZOOM),
656
+ className: "min-w-10 rounded px-1 text-center text-xs tabular-nums hover:bg-accent hover:text-accent-foreground disabled:pointer-events-none",
657
+ children: [
658
+ Math.round(zoom * 100),
659
+ "%"
660
+ ]
661
+ }
662
+ ),
663
+ /* @__PURE__ */ jsxRuntime.jsx(
664
+ "button",
665
+ {
666
+ type: "button",
667
+ tabIndex: -1,
668
+ "aria-label": "Zoom in",
669
+ disabled: zoom >= MAX_ZOOM,
670
+ onMouseDown: keepCanvasFocus,
671
+ onClick: () => zoomTo(zoom + ZOOM_STEP),
672
+ className: "flex size-6 items-center justify-center rounded text-sm leading-none hover:bg-accent hover:text-accent-foreground disabled:pointer-events-none disabled:opacity-40",
673
+ children: "+"
674
+ }
675
+ )
676
+ ]
677
+ }
678
+ ),
610
679
  state !== "connected" && /* @__PURE__ */ jsxRuntime.jsx(
611
680
  "div",
612
681
  {
@@ -6694,6 +6763,8 @@ function ChatComposerInner({
6694
6763
  showWorkspace = false,
6695
6764
  onToggleWorkspace,
6696
6765
  canShowBrowser = false,
6766
+ browserProfileId,
6767
+ onSelectBrowserProfile,
6697
6768
  canShowWorkspace = false,
6698
6769
  deepResearchEnabled = false,
6699
6770
  researchEnabled = false,
@@ -6706,6 +6777,20 @@ function ChatComposerInner({
6706
6777
  onViewModeChange
6707
6778
  }) {
6708
6779
  const { adapter } = useAgentChatAdapterContext();
6780
+ const [profileMenuOpen, setProfileMenuOpen] = react.useState(false);
6781
+ const [browserProfiles, setBrowserProfiles] = react.useState([]);
6782
+ react.useEffect(() => {
6783
+ if (!profileMenuOpen || !adapter.listBrowserProfiles) return;
6784
+ let cancelled = false;
6785
+ void adapter.listBrowserProfiles().then((p) => {
6786
+ if (!cancelled) setBrowserProfiles(p);
6787
+ }).catch(() => {
6788
+ if (!cancelled) setBrowserProfiles([]);
6789
+ });
6790
+ return () => {
6791
+ cancelled = true;
6792
+ };
6793
+ }, [profileMenuOpen, adapter]);
6709
6794
  const { textInput, attachments } = usePromptInputController();
6710
6795
  const status = isRunning ? "streaming" : disabled ? "error" : "ready";
6711
6796
  const [adapterCommands, setAdapterCommands] = react.useState([]);
@@ -7045,6 +7130,60 @@ function ChatComposerInner({
7045
7130
  children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.GlobeIcon, { className: "size-4" })
7046
7131
  }
7047
7132
  ),
7133
+ canShowBrowser && onSelectBrowserProfile && adapter.listBrowserProfiles && /* @__PURE__ */ jsxRuntime.jsxs(
7134
+ Popover,
7135
+ {
7136
+ open: profileMenuOpen,
7137
+ onOpenChange: setProfileMenuOpen,
7138
+ children: [
7139
+ /* @__PURE__ */ jsxRuntime.jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
7140
+ PromptInputButton,
7141
+ {
7142
+ "aria-label": "Select browser profile",
7143
+ "aria-pressed": !!browserProfileId,
7144
+ className: browserProfileId ? "bg-accent text-foreground" : void 0,
7145
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.IdCardIcon, { className: "size-4" })
7146
+ }
7147
+ ) }),
7148
+ /* @__PURE__ */ jsxRuntime.jsx(
7149
+ PopoverContent,
7150
+ {
7151
+ side: "top",
7152
+ align: "start",
7153
+ className: "w-64 overflow-hidden rounded-xl p-1",
7154
+ children: /* @__PURE__ */ jsxRuntime.jsx(Command, { children: /* @__PURE__ */ jsxRuntime.jsxs(CommandList, { children: [
7155
+ /* @__PURE__ */ jsxRuntime.jsx(
7156
+ CommandItem,
7157
+ {
7158
+ onSelect: () => {
7159
+ setProfileMenuOpen(false);
7160
+ onSelectBrowserProfile(null);
7161
+ },
7162
+ className: "gap-3 rounded-md px-3 py-2",
7163
+ children: "No profile"
7164
+ }
7165
+ ),
7166
+ browserProfiles.map((p) => /* @__PURE__ */ jsxRuntime.jsxs(
7167
+ CommandItem,
7168
+ {
7169
+ onSelect: () => {
7170
+ setProfileMenuOpen(false);
7171
+ onSelectBrowserProfile(p.id);
7172
+ },
7173
+ className: "gap-3 rounded-md px-3 py-2",
7174
+ children: [
7175
+ p.name,
7176
+ browserProfileId === p.id && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-auto text-xs text-muted-foreground", children: "Active" })
7177
+ ]
7178
+ },
7179
+ p.id
7180
+ ))
7181
+ ] }) })
7182
+ }
7183
+ )
7184
+ ]
7185
+ }
7186
+ ),
7048
7187
  canShowWorkspace && onToggleWorkspace && /* @__PURE__ */ jsxRuntime.jsx(
7049
7188
  PromptInputButton,
7050
7189
  {
@@ -7764,9 +7903,9 @@ function ArtifactTable({ spec }) {
7764
7903
  init_utils();
7765
7904
  var DEFAULT_HEIGHT_PX = 480;
7766
7905
  var EXPANDED_HEIGHT_PX = 800;
7767
- var MIN_ZOOM = 0.5;
7768
- var MAX_ZOOM = 2;
7769
- var ZOOM_STEP = 0.1;
7906
+ var MIN_ZOOM2 = 0.5;
7907
+ var MAX_ZOOM2 = 2;
7908
+ var ZOOM_STEP2 = 0.1;
7770
7909
  var SAFETY_STYLE_PREAMBLE = "<style>html,body{max-height:100vh}canvas{max-height:80vh!important}</style>";
7771
7910
  function injectSafetyStyle(html) {
7772
7911
  const headCloseIdx = html.search(/<\/head\s*>/i);
@@ -7783,7 +7922,7 @@ function ArtifactHtml({
7783
7922
  const [zoom, setZoom] = react.useState(1);
7784
7923
  const safeSrcdoc = react.useMemo(() => injectSafetyStyle(spec.html), [spec.html]);
7785
7924
  const viewportHeight = expanded ? EXPANDED_HEIGHT_PX : DEFAULT_HEIGHT_PX;
7786
- const clamp = (v) => Math.round(Math.min(MAX_ZOOM, Math.max(MIN_ZOOM, v)) * 100) / 100;
7925
+ const clamp = (v) => Math.round(Math.min(MAX_ZOOM2, Math.max(MIN_ZOOM2, v)) * 100) / 100;
7787
7926
  return /* @__PURE__ */ jsxRuntime.jsxs(
7788
7927
  "div",
7789
7928
  {
@@ -7829,8 +7968,8 @@ function ArtifactHtml({
7829
7968
  "button",
7830
7969
  {
7831
7970
  type: "button",
7832
- onClick: () => setZoom((z) => clamp(z - ZOOM_STEP)),
7833
- disabled: zoom <= MIN_ZOOM,
7971
+ onClick: () => setZoom((z) => clamp(z - ZOOM_STEP2)),
7972
+ disabled: zoom <= MIN_ZOOM2,
7834
7973
  className: "hover:text-foreground disabled:opacity-40 cursor-pointer",
7835
7974
  "aria-label": "zoom out",
7836
7975
  children: "\u2212"
@@ -7853,8 +7992,8 @@ function ArtifactHtml({
7853
7992
  "button",
7854
7993
  {
7855
7994
  type: "button",
7856
- onClick: () => setZoom((z) => clamp(z + ZOOM_STEP)),
7857
- disabled: zoom >= MAX_ZOOM,
7995
+ onClick: () => setZoom((z) => clamp(z + ZOOM_STEP2)),
7996
+ disabled: zoom >= MAX_ZOOM2,
7858
7997
  className: "hover:text-foreground disabled:opacity-40",
7859
7998
  "aria-label": "zoom in",
7860
7999
  children: "+"
@@ -10231,6 +10370,8 @@ function ChatThread({
10231
10370
  showWorkspace = false,
10232
10371
  onToggleWorkspace,
10233
10372
  canShowBrowser = false,
10373
+ browserProfileId,
10374
+ onSelectBrowserProfile,
10234
10375
  canShowWorkspace = false,
10235
10376
  viewMode = "simple",
10236
10377
  onViewModeChange,
@@ -10302,6 +10443,8 @@ function ChatThread({
10302
10443
  showWorkspace,
10303
10444
  onToggleWorkspace,
10304
10445
  canShowBrowser,
10446
+ browserProfileId,
10447
+ onSelectBrowserProfile,
10305
10448
  canShowWorkspace,
10306
10449
  viewMode,
10307
10450
  onViewModeChange,
@@ -12819,6 +12962,8 @@ function AgentChat({
12819
12962
  onMessagesChange,
12820
12963
  disabled,
12821
12964
  onComposerError,
12965
+ browserProfileId,
12966
+ onSelectBrowserProfile,
12822
12967
  deepResearchEnabled = false,
12823
12968
  researchEnabled = false,
12824
12969
  codeAgentsEnabled = false,
@@ -12968,6 +13113,8 @@ function AgentChat({
12968
13113
  tokenUsage: runtime.tokenUsage,
12969
13114
  retryIndicator: runtime.retryIndicator,
12970
13115
  onComposerError,
13116
+ browserProfileId,
13117
+ onSelectBrowserProfile,
12971
13118
  showBrowser,
12972
13119
  onToggleBrowser: handleToggleBrowser,
12973
13120
  showWorkspace,
@@ -13743,7 +13890,7 @@ function InboxDetailActions({
13743
13890
  {
13744
13891
  type: "button",
13745
13892
  size: "sm",
13746
- onClick: () => onSessionSelect?.(item.sessionId),
13893
+ onClick: () => onSessionSelect?.(item.sessionId, item),
13747
13894
  "aria-label": "Open session",
13748
13895
  children: [
13749
13896
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ExternalLinkIcon, { className: "size-3.5" }),
@@ -16671,11 +16818,16 @@ function SessionTreePanel({
16671
16818
  limit: sessionListLimit
16672
16819
  }) : Promise.resolve(null);
16673
16820
  const sessionTreePromise = sessionId && adapter.getSessionTree ? adapter.getSessionTree({ sessionId }) : Promise.resolve(null);
16674
- const [sessionList, sessionTree] = await Promise.all([
16821
+ const [listResult, treeResult] = await Promise.allSettled([
16675
16822
  sessionListPromise,
16676
16823
  sessionTreePromise
16677
16824
  ]);
16678
16825
  if (!mounted.current || currentRequestId !== requestId.current) return;
16826
+ if (loadList && listResult.status === "rejected") {
16827
+ throw listResult.reason;
16828
+ }
16829
+ const sessionList = listResult.status === "fulfilled" ? listResult.value : null;
16830
+ const sessionTree = treeResult.status === "fulfilled" ? treeResult.value : null;
16679
16831
  let nextNodes = mergeTreeNodes([
16680
16832
  sessionList?.sessions.map(sessionToTreeNode) ?? [],
16681
16833
  sessionTree?.nodes ?? []
@@ -16833,6 +16985,7 @@ function SessionTreePanel({
16833
16985
  exports.ACTIVE_MISSION_STATUSES = ACTIVE_MISSION_STATUSES;
16834
16986
  exports.AgentChat = AgentChat;
16835
16987
  exports.AgentChatAdapterProvider = AgentChatAdapterProvider;
16988
+ exports.BrowserLiveView = BrowserLiveView;
16836
16989
  exports.CitationText = CitationText;
16837
16990
  exports.CodingAgentsPanel = CodingAgentsPanel;
16838
16991
  exports.ComposioConnectCard = ComposioConnectCard;