@agent-native/core 0.11.0 → 0.11.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/dist/agent/thread-data-builder.d.ts +1 -0
  2. package/dist/agent/thread-data-builder.d.ts.map +1 -1
  3. package/dist/agent/thread-data-builder.js +1 -0
  4. package/dist/agent/thread-data-builder.js.map +1 -1
  5. package/dist/client/AgentPanel.d.ts.map +1 -1
  6. package/dist/client/AgentPanel.js +8 -45
  7. package/dist/client/AgentPanel.js.map +1 -1
  8. package/dist/client/AssistantChat.d.ts.map +1 -1
  9. package/dist/client/AssistantChat.js +76 -16
  10. package/dist/client/AssistantChat.js.map +1 -1
  11. package/dist/client/builder-frame.d.ts.map +1 -1
  12. package/dist/client/builder-frame.js +10 -3
  13. package/dist/client/builder-frame.js.map +1 -1
  14. package/dist/client/components/ui/dropdown-menu.js +2 -2
  15. package/dist/client/components/ui/dropdown-menu.js.map +1 -1
  16. package/dist/client/resources/ResourcesPanel.d.ts.map +1 -1
  17. package/dist/client/resources/ResourcesPanel.js +6 -6
  18. package/dist/client/resources/ResourcesPanel.js.map +1 -1
  19. package/dist/client/settings/useBuilderStatus.d.ts.map +1 -1
  20. package/dist/client/settings/useBuilderStatus.js +6 -2
  21. package/dist/client/settings/useBuilderStatus.js.map +1 -1
  22. package/dist/client/sharing/ShareButton.d.ts +2 -0
  23. package/dist/client/sharing/ShareButton.d.ts.map +1 -1
  24. package/dist/client/sharing/ShareButton.js +84 -24
  25. package/dist/client/sharing/ShareButton.js.map +1 -1
  26. package/dist/client/use-action.d.ts.map +1 -1
  27. package/dist/client/use-action.js +1 -0
  28. package/dist/client/use-action.js.map +1 -1
  29. package/dist/server/action-routes.d.ts.map +1 -1
  30. package/dist/server/action-routes.js +1 -0
  31. package/dist/server/action-routes.js.map +1 -1
  32. package/dist/server/agent-chat-plugin.d.ts +14 -0
  33. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  34. package/dist/server/agent-chat-plugin.js +77 -12
  35. package/dist/server/agent-chat-plugin.js.map +1 -1
  36. package/dist/server/builder-browser.d.ts +8 -6
  37. package/dist/server/builder-browser.d.ts.map +1 -1
  38. package/dist/server/builder-browser.js +54 -32
  39. package/dist/server/builder-browser.js.map +1 -1
  40. package/dist/server/core-routes-plugin.d.ts +7 -0
  41. package/dist/server/core-routes-plugin.d.ts.map +1 -1
  42. package/dist/server/core-routes-plugin.js +100 -74
  43. package/dist/server/core-routes-plugin.js.map +1 -1
  44. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"AssistantChat.d.ts","sourceRoot":"","sources":["../../src/client/AssistantChat.tsx"],"names":[],"mappings":"AACA,OAAO,KAQN,MAAM,OAAO,CAAC;AA6Bf,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAu4DrE,MAAM,WAAW,mBAAmB;IAClC,qDAAqD;IACrD,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,6DAA6D;IAC7D,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,4CAA4C;IAC5C,SAAS,IAAI,OAAO,CAAC;IACrB,+BAA+B;IAC/B,aAAa,IAAI,IAAI,CAAC;CACvB;AAED,MAAM,WAAW,kBAAkB;IACjC,6DAA6D;IAC7D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,wEAAwE;IACxE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,wGAAwG;IACxG,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,uCAAuC;IACvC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gDAAgD;IAChD,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,oDAAoD;IACpD,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,wCAAwC;IACxC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iDAAiD;IACjD,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAC3B,0CAA0C;IAC1C,oBAAoB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/C,8EAA8E;IAC9E,YAAY,CAAC,EAAE,CACb,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE;QACJ,UAAU,EAAE,MAAM,CAAC;QACnB,KAAK,EAAE,MAAM,CAAC;QACd,OAAO,EAAE,MAAM,CAAC;QAChB,YAAY,EAAE,MAAM,CAAC;KACtB,KACE,IAAI,CAAC;IACV,+DAA+D;IAC/D,eAAe,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9D,8DAA8D;IAC9D,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC/B,+FAA+F;IAC/F,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,mEAAmE;IACnE,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C,0CAA0C;IAC1C,QAAQ,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAC5B,wCAAwC;IACxC,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,KAAK,IAAI,CAAC;IACpD,qFAAqF;IACrF,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iFAAiF;IACjF,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,qDAAqD;IACrD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,+DAA+D;IAC/D,cAAc,CAAC,EAAE,eAAe,CAAC;IACjC,uDAAuD;IACvD,eAAe,CAAC,EAAE,KAAK,CAAC;QACtB,MAAM,EAAE,MAAM,CAAC;QACf,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,EAAE,CAAC;QACjB,UAAU,EAAE,OAAO,CAAC;KACrB,CAAC,CAAC;IACH,uDAAuD;IACvD,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACxD,kEAAkE;IAClE,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,eAAe,KAAK,IAAI,CAAC;IACnD,wEAAwE;IACxE,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;CACzB;AAED,eAAO,MAAM,mBAAmB,gBAAgB,CAAC;AAEjD,8DAA8D;AAC9D,wBAAgB,gBAAgB,CAAC,KAAK,CAAC,EAAE,MAAM,QAI9C;AAqCD,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AACpE,OAAO,EAAE,iBAAiB,EAAE,CAAC;AAosC7B,eAAO,MAAM,aAAa,gGA4DxB,CAAC"}
1
+ {"version":3,"file":"AssistantChat.d.ts","sourceRoot":"","sources":["../../src/client/AssistantChat.tsx"],"names":[],"mappings":"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"}
@@ -1,5 +1,4 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { createPortal } from "react-dom";
3
2
  import React, { useState, useRef, useEffect, useCallback, useMemo, forwardRef, useImperativeHandle, } from "react";
4
3
  import { AssistantRuntimeProvider, useLocalRuntime, useThreadRuntime, useThread, useAui, useComposer, useMessageRuntime, ThreadPrimitive, ComposerPrimitive, MessagePrimitive, } from "@assistant-ui/react";
5
4
  import { SimpleImageAttachmentAdapter, SimpleTextAttachmentAdapter, CompositeAttachmentAdapter, } from "@assistant-ui/react";
@@ -14,6 +13,7 @@ import { AgentTaskCard } from "./AgentTaskCard.js";
14
13
  import { ConnectBuilderCard } from "./ConnectBuilderCard.js";
15
14
  import { useBuilderConnectFlow } from "./settings/useBuilderStatus.js";
16
15
  import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from "./components/ui/tooltip.js";
16
+ import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger, } from "./components/ui/dropdown-menu.js";
17
17
  import { IframeEmbed, parseEmbedBody } from "./IframeEmbed.js";
18
18
  import { useDevMode } from "./use-dev-mode.js";
19
19
  import { agentNativePath } from "./api-path.js";
@@ -144,6 +144,67 @@ async function waitForThreadRunToClear(apiUrl, threadId) {
144
144
  await new Promise((resolve) => window.setTimeout(resolve, ACTIVE_RUN_POLL_INTERVAL_MS));
145
145
  }
146
146
  }
147
+ function coerceMessageDate(value) {
148
+ if (value instanceof Date) {
149
+ return Number.isNaN(value.getTime()) ? null : value;
150
+ }
151
+ if (typeof value === "string" || typeof value === "number") {
152
+ const date = new Date(value);
153
+ return Number.isNaN(date.getTime()) ? null : date;
154
+ }
155
+ return null;
156
+ }
157
+ function isSameCalendarDay(a, b) {
158
+ return (a.getFullYear() === b.getFullYear() &&
159
+ a.getMonth() === b.getMonth() &&
160
+ a.getDate() === b.getDate());
161
+ }
162
+ function formatMessageTimestamp(value) {
163
+ const date = coerceMessageDate(value);
164
+ if (!date)
165
+ return null;
166
+ const now = new Date();
167
+ const yesterday = new Date(now);
168
+ yesterday.setDate(now.getDate() - 1);
169
+ const time = new Intl.DateTimeFormat(undefined, {
170
+ hour: "numeric",
171
+ minute: "2-digit",
172
+ }).format(date);
173
+ let short;
174
+ if (isSameCalendarDay(date, now)) {
175
+ short = time;
176
+ }
177
+ else if (isSameCalendarDay(date, yesterday)) {
178
+ short = `Yesterday ${time}`;
179
+ }
180
+ else if (date.getFullYear() === now.getFullYear()) {
181
+ short = `${new Intl.DateTimeFormat(undefined, {
182
+ month: "short",
183
+ day: "numeric",
184
+ }).format(date)}, ${time}`;
185
+ }
186
+ else {
187
+ short = `${new Intl.DateTimeFormat(undefined, {
188
+ month: "short",
189
+ day: "numeric",
190
+ year: "numeric",
191
+ }).format(date)}, ${time}`;
192
+ }
193
+ return {
194
+ short,
195
+ full: new Intl.DateTimeFormat(undefined, {
196
+ weekday: "short",
197
+ month: "short",
198
+ day: "numeric",
199
+ year: "numeric",
200
+ hour: "numeric",
201
+ minute: "2-digit",
202
+ }).format(date),
203
+ };
204
+ }
205
+ function MessageTimestamp({ timestamp, className, }) {
206
+ return (_jsx("span", { className: cn("text-[11px] leading-none text-muted-foreground", className), title: timestamp.full, children: timestamp.short }));
207
+ }
147
208
  function SelectionAttachedPill() {
148
209
  const [length, setLength] = useState(null);
149
210
  useEffect(() => {
@@ -589,6 +650,8 @@ function UserMessage() {
589
650
  const [expanded, setExpanded] = useState(false);
590
651
  const [isExpandable, setIsExpandable] = useState(false);
591
652
  const contentRef = useRef(null);
653
+ const messageRuntime = useMessageRuntime();
654
+ const timestamp = formatMessageTimestamp(messageRuntime.getState().createdAt);
592
655
  useEffect(() => {
593
656
  const el = contentRef.current;
594
657
  if (!el)
@@ -601,7 +664,7 @@ function UserMessage() {
601
664
  observer.observe(el);
602
665
  return () => observer.disconnect();
603
666
  }, []);
604
- return (_jsx("div", { className: "flex justify-end", style: { contentVisibility: "auto" }, children: _jsxs("div", { className: "max-w-[85%]", children: [_jsx(UserMessageAttachments, {}), _jsxs("div", { className: "relative rounded-lg bg-accent px-3 py-2 text-sm leading-relaxed text-foreground", onCopy: (e) => {
667
+ return (_jsx("div", { className: "group flex justify-end", style: { contentVisibility: "auto" }, children: _jsxs("div", { className: "max-w-[85%]", children: [_jsx(UserMessageAttachments, {}), _jsxs("div", { className: "relative rounded-lg bg-accent px-3 py-2 text-sm leading-relaxed text-foreground", onCopy: (e) => {
605
668
  const selection = window.getSelection();
606
669
  if (!selection || selection.rangeCount === 0)
607
670
  return;
@@ -618,17 +681,16 @@ function UserMessage() {
618
681
  e.clipboardData.setData("text/plain", div.textContent || "");
619
682
  }, children: [_jsx("div", { ref: contentRef, className: cn("whitespace-pre-wrap break-words", !expanded && isExpandable && "max-h-[200px] overflow-hidden"), children: _jsx(MessagePrimitive.Parts, { components: {
620
683
  Text: UserMessageText,
621
- } }) }), !expanded && isExpandable && (_jsx("div", { className: "pointer-events-none absolute inset-x-0 bottom-0 h-14 rounded-b-lg bg-gradient-to-t from-accent via-accent/90 to-transparent" }))] }), isExpandable && (_jsxs("button", { type: "button", onClick: () => setExpanded((prev) => !prev), className: "mt-1 inline-flex items-center gap-1 rounded-md px-1.5 py-1 text-[11px] font-medium text-muted-foreground hover:text-foreground", children: [_jsx(IconChevronDown, { className: cn("h-3.5 w-3.5 transition-transform", expanded && "rotate-180") }), expanded ? "Collapse" : "Expand"] }))] }) }));
684
+ } }) }), !expanded && isExpandable && (_jsx("div", { className: "pointer-events-none absolute inset-x-0 bottom-0 h-14 rounded-b-lg bg-gradient-to-t from-accent via-accent/90 to-transparent" }))] }), isExpandable && (_jsxs("button", { type: "button", onClick: () => setExpanded((prev) => !prev), className: "mt-1 inline-flex items-center gap-1 rounded-md px-1.5 py-1 text-[11px] font-medium text-muted-foreground hover:text-foreground", children: [_jsx(IconChevronDown, { className: cn("h-3.5 w-3.5 transition-transform", expanded && "rotate-180") }), expanded ? "Collapse" : "Expand"] })), timestamp && (_jsx("div", { className: "mt-1 flex justify-end", children: _jsx(MessageTimestamp, { timestamp: timestamp, className: "opacity-0 transition-opacity duration-150 group-hover:opacity-100 group-focus-within:opacity-100" }) }))] }) }));
622
685
  }
623
686
  const CheckpointContext = React.createContext(null);
624
687
  const MessageActionsContext = React.createContext(null);
625
688
  function MessageActionsMenu({ showRevert, onRevert, } = {}) {
626
689
  const [open, setOpen] = useState(false);
627
- const [menuPos, setMenuPos] = useState(null);
628
690
  const [copied, setCopied] = useState(null);
629
691
  const messageRuntime = useMessageRuntime();
630
692
  const actionsCtx = React.useContext(MessageActionsContext);
631
- const buttonRef = useRef(null);
693
+ const timestamp = formatMessageTimestamp(messageRuntime.getState().createdAt);
632
694
  const handleCopyMessage = useCallback(() => {
633
695
  const m = messageRuntime.getState();
634
696
  const text = m.content
@@ -670,16 +732,13 @@ function MessageActionsMenu({ showRevert, onRevert, } = {}) {
670
732
  setOpen(false);
671
733
  onRevert?.();
672
734
  }, [onRevert]);
673
- const handleToggle = useCallback(() => {
674
- if (!open && buttonRef.current) {
675
- const rect = buttonRef.current.getBoundingClientRect();
676
- setMenuPos({ top: rect.bottom + 4, left: rect.left });
677
- }
678
- setOpen((v) => !v);
679
- }, [open]);
680
- return (_jsxs("div", { className: "relative", children: [_jsx("button", { ref: buttonRef, onClick: handleToggle, className: cn("flex h-6 w-6 items-center justify-center rounded-md text-muted-foreground/70 hover:bg-accent hover:text-foreground", open && "bg-accent text-foreground"), children: _jsx(IconDots, { className: "h-3.5 w-3.5" }) }), open &&
681
- menuPos &&
682
- createPortal(_jsxs(_Fragment, { children: [_jsx("div", { className: "fixed inset-0", style: { zIndex: 9998 }, onClick: () => setOpen(false) }), _jsxs("div", { className: "fixed w-44 rounded-md border border-border bg-popover py-1 shadow-lg", style: { top: menuPos.top, left: menuPos.left, zIndex: 9999 }, children: [actionsCtx?.onForkChat && (_jsxs("button", { className: "flex w-full items-center gap-2 px-3 py-1.5 text-xs text-foreground hover:bg-accent", onClick: handleForkChat, children: [_jsx(IconGitFork, { className: "h-3.5 w-3.5" }), "Fork Chat"] })), _jsxs("button", { className: "flex w-full items-center gap-2 px-3 py-1.5 text-xs text-foreground hover:bg-accent", onClick: handleCopyMessage, children: [copied === "message" ? (_jsx(IconCheck, { className: "h-3.5 w-3.5" })) : (_jsx(IconCopy, { className: "h-3.5 w-3.5" })), copied === "message" ? "Copied!" : "Copy Message"] }), _jsxs("button", { className: "flex w-full items-center gap-2 px-3 py-1.5 text-xs text-foreground hover:bg-accent", onClick: handleCopyRequestId, children: [copied === "id" ? (_jsx(IconCheck, { className: "h-3.5 w-3.5" })) : (_jsx(IconId, { className: "h-3.5 w-3.5" })), copied === "id" ? "Copied!" : "Copy Request ID"] }), showRevert && (_jsxs("button", { className: "flex w-full items-center gap-2 px-3 py-1.5 text-xs text-foreground hover:bg-accent", onClick: handleRevert, children: [_jsx(IconArrowBackUp, { className: "h-3.5 w-3.5" }), "Revert to here"] }))] })] }), document.body)] }));
735
+ return (_jsxs(DropdownMenu, { open: open, onOpenChange: setOpen, children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx("button", { "aria-label": "Message actions", className: cn("flex h-6 w-6 items-center justify-center rounded-md text-muted-foreground/70 transition-colors duration-150 hover:bg-accent hover:text-foreground", open && "bg-accent text-foreground"), children: _jsx(IconDots, { className: "h-3.5 w-3.5" }) }) }), _jsxs(DropdownMenuContent, { align: "start", sideOffset: 6, className: "w-48 rounded-lg border-border p-1.5 shadow-xl", children: [actionsCtx?.onForkChat && (_jsxs(DropdownMenuItem, { onSelect: handleForkChat, children: [_jsx(IconGitFork, { className: "h-3.5 w-3.5" }), "Fork Chat"] })), _jsxs(DropdownMenuItem, { onSelect: (e) => {
736
+ e.preventDefault();
737
+ handleCopyMessage();
738
+ }, children: [copied === "message" ? (_jsx(IconCheck, { className: "h-3.5 w-3.5" })) : (_jsx(IconCopy, { className: "h-3.5 w-3.5" })), copied === "message" ? "Copied!" : "Copy Message"] }), _jsxs(DropdownMenuItem, { onSelect: (e) => {
739
+ e.preventDefault();
740
+ handleCopyRequestId();
741
+ }, children: [copied === "id" ? (_jsx(IconCheck, { className: "h-3.5 w-3.5" })) : (_jsx(IconId, { className: "h-3.5 w-3.5" })), copied === "id" ? "Copied!" : "Copy Request ID"] }), showRevert && (_jsxs(DropdownMenuItem, { onSelect: handleRevert, children: [_jsx(IconArrowBackUp, { className: "h-3.5 w-3.5" }), "Revert to here"] })), timestamp && (_jsxs(_Fragment, { children: [_jsx(DropdownMenuSeparator, {}), _jsxs(DropdownMenuLabel, { className: "px-2 py-1 text-[11px] font-normal text-muted-foreground", children: ["Sent ", timestamp.short] })] }))] })] }));
683
742
  }
684
743
  function AssistantMessage() {
685
744
  const [restoreState, setRestoreState] = useState("idle");
@@ -687,6 +746,7 @@ function AssistantMessage() {
687
746
  const thread = useThread();
688
747
  const chatRunning = React.useContext(ChatRunningContext);
689
748
  const msg = messageRuntime.getState();
749
+ const timestamp = formatMessageTimestamp(msg.createdAt);
690
750
  const isLast = thread.messages.length > 0 &&
691
751
  thread.messages[thread.messages.length - 1].id === msg.id;
692
752
  const isComplete = !isLast || !chatRunning;
@@ -742,7 +802,7 @@ function AssistantMessage() {
742
802
  tools: {
743
803
  Fallback: ToolCallFallback,
744
804
  },
745
- } }) }), isComplete && (_jsxs("div", { className: "mt-1 flex items-center justify-between", children: [_jsx(MessageActionsMenu, { showRevert: showRestore && restoreState === "idle", onRevert: handleRestore }), showRestore && restoreState === "confirming" ? (_jsxs("div", { className: "flex items-center gap-1 text-xs", children: [_jsx("button", { onClick: handleRestore, className: "rounded-md bg-destructive px-1.5 py-0.5 text-destructive-foreground hover:bg-destructive/90", children: "Restore to here?" }), _jsx("button", { onClick: cancelRestore, className: "rounded-md px-1.5 py-0.5 text-muted-foreground hover:bg-accent", children: "Cancel" })] })) : showRestore && restoreState === "restoring" ? (_jsxs("span", { className: "flex items-center gap-1 text-xs text-muted-foreground", children: [_jsx(IconLoader2, { className: "h-3 w-3 animate-spin" }), "Restoring..."] })) : (_jsx(React.Suspense, { fallback: null, children: _jsx(ThumbsFeedbackLazy, { threadId: cpCtx?.threadId ?? "", runId: (() => {
805
+ } }) }), isComplete && (_jsxs("div", { className: "mt-1 flex items-center justify-between", children: [_jsxs("div", { className: "flex min-w-0 items-center gap-2", children: [_jsx(MessageActionsMenu, { showRevert: showRestore && restoreState === "idle", onRevert: handleRestore }), timestamp && (_jsx(MessageTimestamp, { timestamp: timestamp, className: "opacity-0 transition-opacity duration-150 group-hover:opacity-100 group-focus-within:opacity-100" }))] }), showRestore && restoreState === "confirming" ? (_jsxs("div", { className: "flex items-center gap-1 text-xs", children: [_jsx("button", { onClick: handleRestore, className: "rounded-md bg-destructive px-1.5 py-0.5 text-destructive-foreground hover:bg-destructive/90", children: "Restore to here?" }), _jsx("button", { onClick: cancelRestore, className: "rounded-md px-1.5 py-0.5 text-muted-foreground hover:bg-accent", children: "Cancel" })] })) : showRestore && restoreState === "restoring" ? (_jsxs("span", { className: "flex items-center gap-1 text-xs text-muted-foreground", children: [_jsx(IconLoader2, { className: "h-3 w-3 animate-spin" }), "Restoring..."] })) : (_jsx(React.Suspense, { fallback: null, children: _jsx(ThumbsFeedbackLazy, { threadId: cpCtx?.threadId ?? "", runId: (() => {
746
806
  const meta = messageRuntime.getState().metadata;
747
807
  return ((typeof meta?.custom?.runId === "string" &&
748
808
  meta.custom.runId) ||