@agents24/chat-react 0.5.6 → 0.5.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/ui/index.js CHANGED
@@ -299,8 +299,8 @@ function ChatMessage(input) {
299
299
  const messageProps = Object.assign({}, props);
300
300
  messageProps.align = resolvedAlign;
301
301
  messageProps.className = cn(
302
- "a24-chat-message group flex w-full flex-col gap-2",
303
- isUser ? "a24-chat-message--user is-user max-w-full justify-end" : "a24-chat-message--assistant is-assistant max-w-full",
302
+ "a24-chat-message group flex w-full flex-col",
303
+ isUser ? "a24-chat-message--user is-user max-w-full justify-end gap-0" : "a24-chat-message--assistant is-assistant max-w-full gap-2",
304
304
  className
305
305
  );
306
306
  return React.createElement(
@@ -990,6 +990,15 @@ var FEEDBACK_REASONS = [
990
990
  ["citation_issue", "Citation issue"],
991
991
  ["other", "Other"]
992
992
  ];
993
+ function formatSentAt(value) {
994
+ if (!value) return null;
995
+ const date = value instanceof Date ? value : new Date(value);
996
+ if (Number.isNaN(date.getTime())) return null;
997
+ return {
998
+ dateTime: date.toISOString(),
999
+ label: new Intl.DateTimeFormat(void 0, { timeStyle: "short" }).format(date)
1000
+ };
1001
+ }
993
1002
  function AgentChatDefaultActions({
994
1003
  additionalActions,
995
1004
  dir,
@@ -1000,11 +1009,43 @@ function AgentChatDefaultActions({
1000
1009
  const [feedbackTrigger, setFeedbackTrigger] = React3.useState(null);
1001
1010
  const [reason, setReason] = React3.useState(handlers?.feedback?.reason ?? null);
1002
1011
  const [comment, setComment] = React3.useState(handlers?.feedback?.comment ?? "");
1012
+ const [optimisticCopied, setOptimisticCopied] = React3.useState(false);
1013
+ const copyResetTimer = React3.useRef(null);
1003
1014
  React3.useEffect(() => {
1004
1015
  setReason(handlers?.feedback?.reason ?? null);
1005
1016
  setComment(handlers?.feedback?.comment ?? "");
1006
1017
  }, [handlers?.feedback?.comment, handlers?.feedback?.reason]);
1007
- if (!handlers || message.role !== "assistant" || message.isFinal === false) return null;
1018
+ React3.useEffect(() => () => {
1019
+ if (copyResetTimer.current !== null) window.clearTimeout(copyResetTimer.current);
1020
+ }, []);
1021
+ const copied = handlers?.copied ?? optimisticCopied;
1022
+ const copyMessage = () => {
1023
+ handlers?.onCopy?.(message.content || "", message.id);
1024
+ if (handlers?.copied !== void 0) return;
1025
+ setOptimisticCopied(true);
1026
+ if (copyResetTimer.current !== null) window.clearTimeout(copyResetTimer.current);
1027
+ copyResetTimer.current = window.setTimeout(() => {
1028
+ copyResetTimer.current = null;
1029
+ setOptimisticCopied(false);
1030
+ }, 1200);
1031
+ };
1032
+ if (!handlers || message.isFinal === false) return null;
1033
+ if (message.role === "user") {
1034
+ const sentAt = formatSentAt(message.createdAt);
1035
+ return /* @__PURE__ */ jsxs2(ChatMessageActions, { className: "a24-user-message-actions", children: [
1036
+ sentAt ? /* @__PURE__ */ jsx4("time", { dateTime: sentAt.dateTime, children: sentAt.label }) : null,
1037
+ handlers.onCopy ? /* @__PURE__ */ jsx4(
1038
+ ChatMessageAction,
1039
+ {
1040
+ label: "Copy",
1041
+ onClick: copyMessage,
1042
+ tooltip: copied ? "Copied!" : "Copy to clipboard",
1043
+ className: "a24-user-message-copy",
1044
+ children: copied ? /* @__PURE__ */ jsx4(Check, { className: "a24-user-message-copy__check text-green-600" }) : /* @__PURE__ */ jsx4(Copy, { className: "a24-user-message-copy__icon" })
1045
+ }
1046
+ ) : null
1047
+ ] });
1048
+ }
1008
1049
  const canWriteFeedback = Boolean(message.runId && handlers.onSetFeedback);
1009
1050
  return /* @__PURE__ */ jsxs2(ChatMessageActions, { children: [
1010
1051
  handlers.onRetry ? /* @__PURE__ */ jsx4(
@@ -1115,9 +1156,9 @@ function AgentChatDefaultActions({
1115
1156
  ChatMessageAction,
1116
1157
  {
1117
1158
  label: "Copy",
1118
- onClick: () => handlers.onCopy?.(message.content || "", message.id),
1119
- tooltip: handlers.copied ? "Copied!" : "Copy to clipboard",
1120
- children: handlers.copied ? /* @__PURE__ */ jsx4(Check, { className: "size-4 text-green-600" }) : /* @__PURE__ */ jsx4(Copy, { className: "size-4" })
1159
+ onClick: copyMessage,
1160
+ tooltip: copied ? "Copied!" : "Copy to clipboard",
1161
+ children: copied ? /* @__PURE__ */ jsx4(Check, { className: "size-4 text-green-600" }) : /* @__PURE__ */ jsx4(Copy, { className: "size-4" })
1121
1162
  }
1122
1163
  ) : null
1123
1164
  ] });
@@ -1873,10 +1914,9 @@ function ToolDisclosure({
1873
1914
  const [open, setOpen] = React6.useState(false);
1874
1915
  const contentId = React6.useId();
1875
1916
  const expandable = React6.Children.toArray(children).length > 0;
1876
- const textOnlyRoot = Boolean(root && !grouped && !showOrb);
1877
1917
  if (!expandable) {
1878
1918
  const triggerClassName = cn("a24-tool-trigger", root && "a24-tool-trigger--root", root && !showOrb && "a24-tool-trigger--without-orb", error && "a24-tool-trigger--error", loading && "a24-tool-trigger--active");
1879
- return /* @__PURE__ */ jsxs4("div", { className: cn("a24-tool-trigger-row", textOnlyRoot && "a24-tool-trigger-row--text"), children: [
1919
+ return /* @__PURE__ */ jsxs4("div", { className: "a24-tool-trigger-row", children: [
1880
1920
  onSelect && part ? /* @__PURE__ */ jsxs4("button", { className: triggerClassName, onClick: () => onSelect(part), type: "button", children: [
1881
1921
  showOrb ? /* @__PURE__ */ jsx8(ToolActivityOrb, { label: statusLabel }) : null,
1882
1922
  /* @__PURE__ */ jsx8("span", { className: "a24-tool-trigger__label", children: label })
@@ -1888,7 +1928,7 @@ function ToolDisclosure({
1888
1928
  ] });
1889
1929
  }
1890
1930
  return /* @__PURE__ */ jsxs4("div", { className: "a24-tool-disclosure", children: [
1891
- /* @__PURE__ */ jsxs4("div", { className: cn("a24-tool-trigger-row", textOnlyRoot && "a24-tool-trigger-row--text"), children: [
1931
+ /* @__PURE__ */ jsxs4("div", { className: "a24-tool-trigger-row", children: [
1892
1932
  /* @__PURE__ */ jsxs4(
1893
1933
  "button",
1894
1934
  {
@@ -2394,6 +2434,41 @@ function AgentChatUserMessageContent({
2394
2434
  ) : null
2395
2435
  ] });
2396
2436
  }
2437
+ function AgentChatUserMessageActionRow({
2438
+ children,
2439
+ className
2440
+ }) {
2441
+ const rowRef = React8.useRef(null);
2442
+ const [visible, setVisible] = React8.useState(false);
2443
+ React8.useEffect(() => {
2444
+ const message = rowRef.current?.closest('[data-slot="message"]');
2445
+ if (!message) return;
2446
+ const show = () => setVisible(true);
2447
+ const hide = () => setVisible(false);
2448
+ const hideWhenFocusLeaves = (event) => {
2449
+ if (!message.contains(event.relatedTarget)) hide();
2450
+ };
2451
+ message.addEventListener("mouseenter", show);
2452
+ message.addEventListener("mouseleave", hide);
2453
+ message.addEventListener("focusin", show);
2454
+ message.addEventListener("focusout", hideWhenFocusLeaves);
2455
+ return () => {
2456
+ message.removeEventListener("mouseenter", show);
2457
+ message.removeEventListener("mouseleave", hide);
2458
+ message.removeEventListener("focusin", show);
2459
+ message.removeEventListener("focusout", hideWhenFocusLeaves);
2460
+ };
2461
+ }, []);
2462
+ return /* @__PURE__ */ jsx10(
2463
+ "div",
2464
+ {
2465
+ ref: rowRef,
2466
+ className: cn("a24-chat-message-action-row--user", visible && "is-visible", className),
2467
+ style: { opacity: visible ? 1 : 0, pointerEvents: visible ? "auto" : "none" },
2468
+ children
2469
+ }
2470
+ );
2471
+ }
2397
2472
  function AgentChatMessage({
2398
2473
  actionHandlers,
2399
2474
  additionalActions,
@@ -2432,49 +2507,58 @@ function AgentChatMessage({
2432
2507
  message
2433
2508
  }
2434
2509
  ) : null);
2435
- return /* @__PURE__ */ jsxs6(ChatMessage, { className, dir, from: message.role, children: [
2436
- showAttachments ? /* @__PURE__ */ jsx10(
2437
- ChatAttachmentRows,
2438
- {
2439
- attachments: message.attachments || [],
2440
- className: "mb-2",
2441
- dir,
2442
- resolveContent: attachmentContentResolver
2443
- }
2444
- ) : null,
2445
- shouldRenderContent ? /* @__PURE__ */ jsxs6(
2446
- ChatMessageContent,
2447
- {
2448
- className: cn(isAssistant ? "bg-transparent p-0" : void 0, contentClassName),
2449
- dir,
2450
- from: message.role,
2451
- children: [
2452
- isAssistant ? renderAssistantContent ? renderAssistantContent({ isStreaming, message }) : /* @__PURE__ */ jsx10(
2453
- Timeline,
2454
- {
2455
- getHitlActionState,
2456
- isLoading: isStreaming,
2457
- message,
2458
- nodeActivityMode,
2459
- onHitlAction,
2460
- parts: message.parts
2461
- }
2462
- ) : null,
2463
- !isAssistant ? renderUserContent ? renderUserContent({ message }) : resolvedUserContent ? /* @__PURE__ */ jsx10(
2464
- AgentChatUserMessageContent,
2465
- {
2466
- collapsedLines: userMessageCollapsedLines,
2467
- collapseThreshold: userMessageCollapseThreshold,
2468
- content: resolvedUserContent,
2469
- showLessLabel: userMessageShowLessLabel,
2470
- showMoreLabel: userMessageShowMoreLabel
2471
- }
2472
- ) : null : null
2473
- ]
2474
- }
2475
- ) : null,
2476
- renderedActions ? /* @__PURE__ */ jsx10("div", { className: cn(dir === "rtl" ? "mt-1 h-9 w-full" : "mt-1 h-9 w-full -translate-x-2", actionsClassName), children: renderedActions }) : null
2477
- ] });
2510
+ const defaultUserActions = !actions && Boolean(actionHandlers) && !isAssistant;
2511
+ return /* @__PURE__ */ jsxs6(
2512
+ ChatMessage,
2513
+ {
2514
+ className,
2515
+ dir,
2516
+ from: message.role,
2517
+ children: [
2518
+ showAttachments ? /* @__PURE__ */ jsx10(
2519
+ ChatAttachmentRows,
2520
+ {
2521
+ attachments: message.attachments || [],
2522
+ className: "mb-2",
2523
+ dir,
2524
+ resolveContent: attachmentContentResolver
2525
+ }
2526
+ ) : null,
2527
+ shouldRenderContent ? /* @__PURE__ */ jsxs6(
2528
+ ChatMessageContent,
2529
+ {
2530
+ className: cn(isAssistant ? "bg-transparent p-0" : void 0, contentClassName),
2531
+ dir,
2532
+ from: message.role,
2533
+ children: [
2534
+ isAssistant ? renderAssistantContent ? renderAssistantContent({ isStreaming, message }) : /* @__PURE__ */ jsx10(
2535
+ Timeline,
2536
+ {
2537
+ getHitlActionState,
2538
+ isLoading: isStreaming,
2539
+ message,
2540
+ nodeActivityMode,
2541
+ onHitlAction,
2542
+ parts: message.parts
2543
+ }
2544
+ ) : null,
2545
+ !isAssistant ? renderUserContent ? renderUserContent({ message }) : resolvedUserContent ? /* @__PURE__ */ jsx10(
2546
+ AgentChatUserMessageContent,
2547
+ {
2548
+ collapsedLines: userMessageCollapsedLines,
2549
+ collapseThreshold: userMessageCollapseThreshold,
2550
+ content: resolvedUserContent,
2551
+ showLessLabel: userMessageShowLessLabel,
2552
+ showMoreLabel: userMessageShowMoreLabel
2553
+ }
2554
+ ) : null : null
2555
+ ]
2556
+ }
2557
+ ) : null,
2558
+ renderedActions ? defaultUserActions ? /* @__PURE__ */ jsx10(AgentChatUserMessageActionRow, { className: actionsClassName, children: renderedActions }) : /* @__PURE__ */ jsx10("div", { className: cn(dir === "rtl" ? "mt-1 h-9 w-full" : "mt-1 h-9 w-full -translate-x-2", actionsClassName), children: renderedActions }) : null
2559
+ ]
2560
+ }
2561
+ );
2478
2562
  }
2479
2563
 
2480
2564
  // src/ui/agent-chat-context-status.tsx
@@ -2879,6 +2963,7 @@ export {
2879
2963
  AgentChatToolPart,
2880
2964
  AgentChatToolRow,
2881
2965
  AgentChatToolSession,
2966
+ AgentChatUserMessageActionRow,
2882
2967
  AgentChatUserMessageContent,
2883
2968
  AgentResponseTimeline,
2884
2969
  AskUserInteraction,