@mieweb/ui 0.11.0-dev.49 → 0.11.0-dev.50

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 (77) hide show
  1. package/dist/{chunk-HIYQ3M5V.cjs → chunk-2Y2O2PRZ.cjs} +3 -3
  2. package/dist/chunk-2Y2O2PRZ.cjs.map +1 -0
  3. package/dist/{chunk-O2EAHOXM.cjs → chunk-G56OUIGH.cjs} +482 -29
  4. package/dist/chunk-G56OUIGH.cjs.map +1 -0
  5. package/dist/chunk-GEXYN6AS.cjs +56 -0
  6. package/dist/chunk-GEXYN6AS.cjs.map +1 -0
  7. package/dist/{chunk-OGNADPM4.cjs → chunk-GQONYSGI.cjs} +10 -2
  8. package/dist/chunk-GQONYSGI.cjs.map +1 -0
  9. package/dist/{chunk-IZY4CMOO.js → chunk-H7L45BLY.js} +13 -24
  10. package/dist/chunk-H7L45BLY.js.map +1 -0
  11. package/dist/{chunk-MZA2LDS4.js → chunk-I65QJMFB.js} +4 -4
  12. package/dist/{chunk-MZA2LDS4.js.map → chunk-I65QJMFB.js.map} +1 -1
  13. package/dist/{chunk-NB2C6FSI.js → chunk-L3JA7EDU.js} +20 -3
  14. package/dist/{chunk-NB2C6FSI.js.map → chunk-L3JA7EDU.js.map} +1 -1
  15. package/dist/{chunk-UIFN2LYT.js → chunk-O3MN3TYS.js} +483 -32
  16. package/dist/chunk-O3MN3TYS.js.map +1 -0
  17. package/dist/{chunk-74ENCTIK.js → chunk-R25E7SYN.js} +9 -3
  18. package/dist/chunk-R25E7SYN.js.map +1 -0
  19. package/dist/{chunk-TRZLN32I.cjs → chunk-RDERYV5M.cjs} +14 -25
  20. package/dist/chunk-RDERYV5M.cjs.map +1 -0
  21. package/dist/{chunk-BFVYM6IT.cjs → chunk-TLXQ2E57.cjs} +6 -6
  22. package/dist/{chunk-BFVYM6IT.cjs.map → chunk-TLXQ2E57.cjs.map} +1 -1
  23. package/dist/{chunk-MQOYDQTF.js → chunk-URHUNFFC.js} +3 -3
  24. package/dist/chunk-URHUNFFC.js.map +1 -0
  25. package/dist/chunk-WSLKELR2.js +51 -0
  26. package/dist/chunk-WSLKELR2.js.map +1 -0
  27. package/dist/{chunk-5UKGOBCZ.cjs → chunk-XWGPEIVB.cjs} +20 -3
  28. package/dist/{chunk-5UKGOBCZ.cjs.map → chunk-XWGPEIVB.cjs.map} +1 -1
  29. package/dist/components/DictationButton/index.cjs +5 -5
  30. package/dist/components/DictationButton/index.js +2 -2
  31. package/dist/components/RecordButton/index.cjs +4 -4
  32. package/dist/components/RecordButton/index.d.cts +2 -2
  33. package/dist/components/RecordButton/index.d.ts +2 -2
  34. package/dist/components/RecordButton/index.js +1 -1
  35. package/dist/components/SuperChat/index.cjs +9 -7
  36. package/dist/components/SuperChat/index.cjs.map +1 -1
  37. package/dist/components/SuperChat/index.d.cts +2 -2
  38. package/dist/components/SuperChat/index.d.ts +2 -2
  39. package/dist/components/SuperChat/index.js +3 -1
  40. package/dist/components/SuperChat/index.js.map +1 -1
  41. package/dist/components/SuperChat/plugins/index.d.cts +2 -2
  42. package/dist/components/SuperChat/plugins/index.d.ts +2 -2
  43. package/dist/{hey-buddy-AHUHCDBC.js → hey-buddy-6HXWNHK2.js} +12 -7
  44. package/dist/hey-buddy-6HXWNHK2.js.map +1 -0
  45. package/dist/{hey-buddy-5WOBYZRJ.cjs → hey-buddy-BAS5O4AY.cjs} +12 -7
  46. package/dist/hey-buddy-BAS5O4AY.cjs.map +1 -0
  47. package/dist/index.cjs +2037 -1255
  48. package/dist/index.cjs.map +1 -1
  49. package/dist/index.d.cts +207 -14
  50. package/dist/index.d.ts +207 -14
  51. package/dist/index.js +1851 -1082
  52. package/dist/index.js.map +1 -1
  53. package/dist/{speaker-verify-4NEJAK6C.cjs → speaker-verify-PWTYV4JZ.cjs} +10 -10
  54. package/dist/{speaker-verify-4NEJAK6C.cjs.map → speaker-verify-PWTYV4JZ.cjs.map} +1 -1
  55. package/dist/{speaker-verify-AWSKI6DI.js → speaker-verify-REFWMPTD.js} +3 -3
  56. package/dist/{speaker-verify-AWSKI6DI.js.map → speaker-verify-REFWMPTD.js.map} +1 -1
  57. package/dist/styles.css +1 -1
  58. package/dist/tailwind-preset.cjs +4 -4
  59. package/dist/tailwind-preset.js +1 -1
  60. package/dist/{types-BfVolads.d.ts → types-ByK_dbT7.d.cts} +13 -2
  61. package/dist/{types-BfVolads.d.cts → types-ByK_dbT7.d.ts} +13 -2
  62. package/dist/whisperTranscribe-QV2EQRCD.js +5 -0
  63. package/dist/{whisperTranscribe-UBNUWXUQ.js.map → whisperTranscribe-QV2EQRCD.js.map} +1 -1
  64. package/dist/{whisperTranscribe-AV752TZI.cjs → whisperTranscribe-XL365FM4.cjs} +26 -21
  65. package/dist/{whisperTranscribe-AV752TZI.cjs.map → whisperTranscribe-XL365FM4.cjs.map} +1 -1
  66. package/package.json +2 -2
  67. package/dist/chunk-74ENCTIK.js.map +0 -1
  68. package/dist/chunk-HIYQ3M5V.cjs.map +0 -1
  69. package/dist/chunk-IZY4CMOO.js.map +0 -1
  70. package/dist/chunk-MQOYDQTF.js.map +0 -1
  71. package/dist/chunk-O2EAHOXM.cjs.map +0 -1
  72. package/dist/chunk-OGNADPM4.cjs.map +0 -1
  73. package/dist/chunk-TRZLN32I.cjs.map +0 -1
  74. package/dist/chunk-UIFN2LYT.js.map +0 -1
  75. package/dist/hey-buddy-5WOBYZRJ.cjs.map +0 -1
  76. package/dist/hey-buddy-AHUHCDBC.js.map +0 -1
  77. package/dist/whisperTranscribe-UBNUWXUQ.js +0 -4
@@ -1,9 +1,15 @@
1
+ import { Collapsible, CollapsibleTrigger, CollapsibleContent } from './chunk-VSRO4PAI.js';
1
2
  import { AudioPlayer } from './chunk-4IOIDS2Z.js';
3
+ import { Spinner } from './chunk-UA7E7PDS.js';
4
+ import { Badge } from './chunk-522WJIVI.js';
5
+ import { usePrefersReducedMotion } from './chunk-XDU65GLW.js';
6
+ import { Button } from './chunk-WX2XB6FP.js';
7
+ import { AnimatedPresence, Animated } from './chunk-F4N67NAF.js';
2
8
  import { cn } from './chunk-TQONQSJO.js';
3
- import { jsx, jsxs } from 'react/jsx-runtime';
9
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
4
10
  import * as React2 from 'react';
5
11
  import { cva } from 'class-variance-authority';
6
- import { ArrowDown } from 'lucide-react';
12
+ import { Wrench, ChevronDown, ArrowDown } from 'lucide-react';
7
13
 
8
14
  var sizeClasses = {
9
15
  sm: "h-4 w-4",
@@ -273,10 +279,13 @@ var statusIconVariants = cva(
273
279
  variants: {
274
280
  status: {
275
281
  pending: "bg-neutral-200 dark:bg-neutral-700",
282
+ "awaiting-approval": "bg-amber-100 dark:bg-amber-900/50",
276
283
  running: "bg-primary-100 dark:bg-primary-900/50",
277
284
  success: "bg-green-100 dark:bg-green-900/50",
278
285
  error: "bg-red-100 dark:bg-red-900/50",
279
- cancelled: "bg-neutral-200 dark:bg-neutral-700"
286
+ cancelled: "bg-neutral-200 dark:bg-neutral-700",
287
+ denied: "bg-neutral-200 dark:bg-neutral-700",
288
+ expired: "bg-neutral-200 dark:bg-neutral-700"
280
289
  }
281
290
  },
282
291
  defaultVariants: {
@@ -301,6 +310,25 @@ function ToolStatusIcon({ status, className }) {
301
310
  children: /* @__PURE__ */ jsx("circle", { cx: "10", cy: "10", r: "3" })
302
311
  }
303
312
  ),
313
+ status === "awaiting-approval" && /* @__PURE__ */ jsx(
314
+ "svg",
315
+ {
316
+ "aria-hidden": "true",
317
+ className: "h-3 w-3 text-amber-600 dark:text-amber-400",
318
+ fill: "none",
319
+ viewBox: "0 0 24 24",
320
+ stroke: "currentColor",
321
+ strokeWidth: "3",
322
+ children: /* @__PURE__ */ jsx(
323
+ "path",
324
+ {
325
+ strokeLinecap: "round",
326
+ strokeLinejoin: "round",
327
+ d: "M12 7v6m0 4h.01"
328
+ }
329
+ )
330
+ }
331
+ ),
304
332
  status === "running" && /* @__PURE__ */ jsxs(
305
333
  "svg",
306
334
  {
@@ -369,7 +397,7 @@ function ToolStatusIcon({ status, className }) {
369
397
  )
370
398
  }
371
399
  ),
372
- status === "cancelled" && /* @__PURE__ */ jsx(
400
+ (status === "cancelled" || status === "denied" || status === "expired") && /* @__PURE__ */ jsx(
373
401
  "svg",
374
402
  {
375
403
  "aria-hidden": "true",
@@ -750,6 +778,14 @@ function ToolResultDisplay({
750
778
  }
751
779
  return /* @__PURE__ */ jsxs("div", { className: cn("space-y-2", className), children: [
752
780
  result.summary && /* @__PURE__ */ jsx("p", { className: "text-sm text-neutral-700 dark:text-neutral-300", children: result.summary }),
781
+ /* @__PURE__ */ jsx(ToolResultLinks, { result, onLinkClick })
782
+ ] });
783
+ }
784
+ function hasToolResultLinks(result) {
785
+ return Boolean(result?.link || result?.resources?.length);
786
+ }
787
+ function ToolResultLinks({ result, onLinkClick }) {
788
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
753
789
  result.link && /* @__PURE__ */ jsx(ResourceLink, { link: result.link, onClick: onLinkClick }),
754
790
  result.resources && result.resources.length > 0 && /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-2", children: result.resources.map((resource) => /* @__PURE__ */ jsx(
755
791
  ResourceLink,
@@ -831,10 +867,13 @@ function getParameterSummary(toolName, params) {
831
867
  }
832
868
  var statusPillClasses = {
833
869
  pending: "bg-neutral-100 border-neutral-200 text-neutral-600 dark:bg-neutral-800 dark:border-neutral-700 dark:text-neutral-400",
870
+ "awaiting-approval": "bg-amber-50 border-amber-200 text-amber-800 dark:bg-amber-900/20 dark:border-amber-800 dark:text-amber-300",
834
871
  running: "bg-primary-50 border-primary-200 text-primary-800 dark:bg-primary-900/20 dark:border-primary-800 dark:text-primary-300",
835
872
  success: "bg-green-50 border-green-200 text-green-700 dark:bg-green-900/20 dark:border-green-800 dark:text-green-300",
836
873
  error: "bg-red-50 border-red-200 text-red-700 dark:bg-red-900/20 dark:border-red-800 dark:text-red-300",
837
- cancelled: "bg-neutral-100 border-neutral-200 text-neutral-400 opacity-60 dark:bg-neutral-800 dark:border-neutral-700 dark:text-neutral-400"
874
+ cancelled: "bg-neutral-100 border-neutral-200 text-neutral-400 opacity-60 dark:bg-neutral-800 dark:border-neutral-700 dark:text-neutral-400",
875
+ denied: "bg-neutral-100 border-neutral-200 text-neutral-400 opacity-60 dark:bg-neutral-800 dark:border-neutral-700 dark:text-neutral-400",
876
+ expired: "bg-neutral-100 border-neutral-200 text-neutral-400 opacity-60 dark:bg-neutral-800 dark:border-neutral-700 dark:text-neutral-400"
838
877
  };
839
878
  function MCPToolCallDisplay({
840
879
  toolCall,
@@ -937,6 +976,381 @@ function MCPToolCallDisplay({
937
976
  ] })
938
977
  ) });
939
978
  }
979
+ var plural = (count, one, other) => count === 1 ? one : other;
980
+ var defaultMCPToolCallGroupLabels = {
981
+ used: (count) => `Used ${count} ${plural(count, "tool", "tools")}`,
982
+ running: (count) => `Running ${count} ${plural(count, "tool", "tools")}`,
983
+ needsApproval: (count) => `${count} ${plural(count, "needs", "need")} approval`,
984
+ failed: (count) => `${count} failed`,
985
+ announceApproval: (count) => `${count} tool ${plural(count, "call needs", "calls need")} your approval`,
986
+ announceFailed: (count) => `${count} tool ${plural(count, "call", "calls")} failed`,
987
+ status: {
988
+ pending: "Pending",
989
+ "awaiting-approval": "Needs approval",
990
+ running: "Running",
991
+ success: "Done",
992
+ error: "Failed",
993
+ cancelled: "Cancelled",
994
+ denied: "Denied",
995
+ expired: "Expired"
996
+ },
997
+ callLabel: (toolCall) => toolCall.serverName ? `Tool call: ${toolCall.toolName} from ${toolCall.serverName}` : `Tool call: ${toolCall.toolName}`,
998
+ showResult: "Show result",
999
+ showError: "Show error",
1000
+ allowOnce: "Allow once",
1001
+ allowAlways: "Always allow",
1002
+ deny: "Deny"
1003
+ };
1004
+ function resolveLabels(overrides) {
1005
+ if (!overrides) return defaultMCPToolCallGroupLabels;
1006
+ return {
1007
+ ...defaultMCPToolCallGroupLabels,
1008
+ ...overrides,
1009
+ status: { ...defaultMCPToolCallGroupLabels.status, ...overrides.status }
1010
+ };
1011
+ }
1012
+ function needsAttention(toolCall) {
1013
+ return toolCall.status === "awaiting-approval" || toolCall.status === "error";
1014
+ }
1015
+ function summarize(toolCalls) {
1016
+ let failed = 0;
1017
+ let inFlight = 0;
1018
+ const awaitingIds = [];
1019
+ for (const toolCall of toolCalls) {
1020
+ if (toolCall.status === "awaiting-approval") awaitingIds.push(toolCall.id);
1021
+ else if (toolCall.status === "error") failed += 1;
1022
+ else if (toolCall.status === "running" || toolCall.status === "pending")
1023
+ inFlight += 1;
1024
+ }
1025
+ return {
1026
+ total: toolCalls.length,
1027
+ awaitingApproval: awaitingIds.length,
1028
+ failed,
1029
+ isActive: awaitingIds.length + inFlight > 0,
1030
+ signature: toolCalls.map((call) => `${call.id}:${call.status}`).join("|"),
1031
+ approvalKey: awaitingIds.join("|")
1032
+ };
1033
+ }
1034
+ function useAutoCollapse(isActive, signature, focus) {
1035
+ const [state, setState] = React2.useState(() => ({
1036
+ signature,
1037
+ expanded: isActive,
1038
+ deferred: false
1039
+ }));
1040
+ let next = state;
1041
+ if (state.signature !== signature) {
1042
+ const expanded = isActive || focus === "rows";
1043
+ next = { signature, expanded, deferred: expanded !== isActive };
1044
+ } else if (state.deferred && focus === null) {
1045
+ next = { signature, expanded: isActive, deferred: false };
1046
+ }
1047
+ if (next !== state) setState(next);
1048
+ const setExpanded = React2.useCallback(
1049
+ (expanded) => setState((current) => ({ ...current, expanded, deferred: false })),
1050
+ []
1051
+ );
1052
+ return [next.expanded, setExpanded];
1053
+ }
1054
+ function progressAnnouncement(summary, labels) {
1055
+ if (summary.awaitingApproval > 0) {
1056
+ return labels.announceApproval(summary.awaitingApproval);
1057
+ }
1058
+ if (summary.isActive) return labels.running(summary.total);
1059
+ return labels.used(summary.total);
1060
+ }
1061
+ var STATUS_BADGE_VARIANT = {
1062
+ pending: "secondary",
1063
+ "awaiting-approval": "warning",
1064
+ running: "default",
1065
+ success: "success",
1066
+ error: "danger",
1067
+ cancelled: "secondary",
1068
+ denied: "secondary",
1069
+ expired: "secondary"
1070
+ };
1071
+ function formatParameters(toolCall) {
1072
+ return JSON.stringify(
1073
+ Object.fromEntries(toolCall.parameters.map((p) => [p.name, p.value])),
1074
+ null,
1075
+ 2
1076
+ );
1077
+ }
1078
+ function formatData(data) {
1079
+ return typeof data === "string" ? data : JSON.stringify(data, null, 2);
1080
+ }
1081
+ function formatResult(toolCall) {
1082
+ const { result } = toolCall;
1083
+ if (!result) return null;
1084
+ return result.summary || formatData(result.data);
1085
+ }
1086
+ function formatError(toolCall) {
1087
+ if (toolCall.error) return toolCall.error;
1088
+ const { result } = toolCall;
1089
+ if (result?.type !== "error") return null;
1090
+ if (result.data != null && result.data !== "") return formatData(result.data);
1091
+ return result.summary || null;
1092
+ }
1093
+ function OutputDisclosure({ label, text }) {
1094
+ return /* @__PURE__ */ jsxs(Collapsible, { children: [
1095
+ /* @__PURE__ */ jsxs(CollapsibleTrigger, { className: "flex items-center gap-1 text-xs font-medium text-neutral-600 hover:text-neutral-800 dark:text-neutral-400 dark:hover:text-neutral-200", children: [
1096
+ /* @__PURE__ */ jsx(
1097
+ ChevronDown,
1098
+ {
1099
+ "aria-hidden": "true",
1100
+ className: "h-3 w-3 transition-transform motion-reduce:transition-none [[data-state=open]>&]:rotate-180"
1101
+ }
1102
+ ),
1103
+ label
1104
+ ] }),
1105
+ /* @__PURE__ */ jsx(CollapsibleContent, { className: "mt-1", children: /* @__PURE__ */ jsx(
1106
+ "pre",
1107
+ {
1108
+ dir: "auto",
1109
+ className: "max-h-60 overflow-auto rounded bg-neutral-100 p-2 text-xs whitespace-pre-wrap dark:bg-neutral-900",
1110
+ children: text
1111
+ }
1112
+ ) })
1113
+ ] });
1114
+ }
1115
+ function ToolCallRow({
1116
+ toolCall,
1117
+ labels,
1118
+ onApprove,
1119
+ onDeny,
1120
+ onLinkClick
1121
+ }) {
1122
+ const prefersReducedMotion = usePrefersReducedMotion();
1123
+ const [acting, setActing] = React2.useState(false);
1124
+ const triggerRef = React2.useRef(null);
1125
+ const focusInActionsRef = React2.useRef(false);
1126
+ const isAwaitingApproval = toolCall.status === "awaiting-approval";
1127
+ const result = toolCall.result?.type === "error" ? null : formatResult(toolCall);
1128
+ const errorText = formatError(toolCall);
1129
+ const hasLinks = hasToolResultLinks(toolCall.result);
1130
+ const hasDetails = toolCall.parameters.length > 0 || Boolean(result) || hasLinks;
1131
+ const act = async (action) => {
1132
+ setActing(true);
1133
+ try {
1134
+ await action();
1135
+ } catch {
1136
+ } finally {
1137
+ setActing(false);
1138
+ }
1139
+ };
1140
+ React2.useLayoutEffect(() => {
1141
+ if (isAwaitingApproval || !focusInActionsRef.current) return;
1142
+ focusInActionsRef.current = false;
1143
+ if (!document.activeElement || document.activeElement === document.body) {
1144
+ triggerRef.current?.focus();
1145
+ }
1146
+ }, [isAwaitingApproval]);
1147
+ return /* @__PURE__ */ jsx(
1148
+ Animated,
1149
+ {
1150
+ preset: "collapse",
1151
+ mode: "presence",
1152
+ enabled: !prefersReducedMotion,
1153
+ role: "listitem",
1154
+ "data-slot": "ai-tool-call-row",
1155
+ className: "overflow-hidden text-sm",
1156
+ children: /* @__PURE__ */ jsxs("div", { role: "group", "aria-label": labels.callLabel(toolCall), children: [
1157
+ /* @__PURE__ */ jsxs(Collapsible, { defaultOpen: isAwaitingApproval && hasDetails, children: [
1158
+ /* @__PURE__ */ jsxs(
1159
+ CollapsibleTrigger,
1160
+ {
1161
+ ref: triggerRef,
1162
+ className: "focus-visible:ring-primary-500 flex w-full min-w-0 items-center gap-2 rounded px-1.5 py-1 text-start hover:bg-neutral-100 focus-visible:ring-2 focus-visible:outline-none focus-visible:ring-inset dark:hover:bg-neutral-800",
1163
+ children: [
1164
+ /* @__PURE__ */ jsx(
1165
+ "span",
1166
+ {
1167
+ "aria-hidden": "true",
1168
+ className: "flex h-3.5 w-3.5 shrink-0 items-center justify-center text-neutral-500 [&_svg]:h-3.5 [&_svg]:w-3.5",
1169
+ children: toolCall.icon ?? /* @__PURE__ */ jsx(Wrench, {})
1170
+ }
1171
+ ),
1172
+ toolCall.serverName && /* @__PURE__ */ jsx("span", { className: "shrink-0 text-neutral-500 dark:text-neutral-400", children: toolCall.serverName }),
1173
+ /* @__PURE__ */ jsx("code", { className: "min-w-0 truncate font-mono text-xs", children: toolCall.toolName }),
1174
+ toolCall.status === "running" && /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "shrink-0", children: /* @__PURE__ */ jsx(Spinner, { size: "xs" }) }),
1175
+ /* @__PURE__ */ jsx(
1176
+ Badge,
1177
+ {
1178
+ variant: STATUS_BADGE_VARIANT[toolCall.status],
1179
+ size: "sm",
1180
+ className: "ms-auto shrink-0",
1181
+ children: labels.status[toolCall.status]
1182
+ }
1183
+ ),
1184
+ /* @__PURE__ */ jsx(
1185
+ ChevronDown,
1186
+ {
1187
+ "aria-hidden": "true",
1188
+ className: "h-3.5 w-3.5 shrink-0 text-neutral-400 transition-transform motion-reduce:transition-none [[data-state=open]>&]:rotate-180"
1189
+ }
1190
+ )
1191
+ ]
1192
+ }
1193
+ ),
1194
+ /* @__PURE__ */ jsxs(CollapsibleContent, { className: "ms-6 mt-1 space-y-2 pb-1", children: [
1195
+ toolCall.result && hasLinks && /* @__PURE__ */ jsx(
1196
+ ToolResultLinks,
1197
+ {
1198
+ result: toolCall.result,
1199
+ onLinkClick
1200
+ }
1201
+ ),
1202
+ toolCall.parameters.length > 0 && // JSON keeps its left-to-right order in RTL documents.
1203
+ /* @__PURE__ */ jsx(
1204
+ "pre",
1205
+ {
1206
+ dir: "ltr",
1207
+ className: "max-h-40 overflow-auto rounded bg-neutral-100 p-2 text-xs dark:bg-neutral-900",
1208
+ children: formatParameters(toolCall)
1209
+ }
1210
+ ),
1211
+ result && /* @__PURE__ */ jsx(OutputDisclosure, { label: labels.showResult, text: result }),
1212
+ errorText && /* @__PURE__ */ jsx(OutputDisclosure, { label: labels.showError, text: errorText })
1213
+ ] })
1214
+ ] }),
1215
+ toolCall.status === "error" && errorText && /* @__PURE__ */ jsx("p", { className: "ms-6 line-clamp-2 text-xs text-red-600 dark:text-red-400", children: errorText }),
1216
+ isAwaitingApproval && (onApprove || onDeny) && /* @__PURE__ */ jsxs(
1217
+ "div",
1218
+ {
1219
+ className: "ms-6 mt-1 flex flex-wrap gap-2 pb-1",
1220
+ onFocus: () => {
1221
+ focusInActionsRef.current = true;
1222
+ },
1223
+ onBlur: (event) => {
1224
+ if (!event.currentTarget.contains(event.relatedTarget)) {
1225
+ focusInActionsRef.current = false;
1226
+ }
1227
+ },
1228
+ children: [
1229
+ onApprove && /* @__PURE__ */ jsxs(Fragment, { children: [
1230
+ /* @__PURE__ */ jsx(
1231
+ Button,
1232
+ {
1233
+ size: "sm",
1234
+ onClick: () => void act(() => onApprove(toolCall, { always: false })),
1235
+ disabled: acting,
1236
+ isLoading: acting,
1237
+ children: labels.allowOnce
1238
+ }
1239
+ ),
1240
+ /* @__PURE__ */ jsx(
1241
+ Button,
1242
+ {
1243
+ size: "sm",
1244
+ variant: "outline",
1245
+ onClick: () => void act(() => onApprove(toolCall, { always: true })),
1246
+ disabled: acting,
1247
+ children: labels.allowAlways
1248
+ }
1249
+ )
1250
+ ] }),
1251
+ onDeny && /* @__PURE__ */ jsx(
1252
+ Button,
1253
+ {
1254
+ size: "sm",
1255
+ variant: "danger",
1256
+ onClick: () => void act(() => onDeny(toolCall)),
1257
+ disabled: acting,
1258
+ children: labels.deny
1259
+ }
1260
+ )
1261
+ ]
1262
+ }
1263
+ )
1264
+ ] })
1265
+ }
1266
+ );
1267
+ }
1268
+ function MCPToolCallGroup({
1269
+ toolCalls,
1270
+ onApprove,
1271
+ onDeny,
1272
+ onLinkClick,
1273
+ labels: labelOverrides,
1274
+ className
1275
+ }) {
1276
+ const labels = React2.useMemo(
1277
+ () => resolveLabels(labelOverrides),
1278
+ [labelOverrides]
1279
+ );
1280
+ const listId = React2.useId();
1281
+ const summary = summarize(toolCalls);
1282
+ const [focus, setFocus] = React2.useState(null);
1283
+ const [expanded, setExpanded] = useAutoCollapse(
1284
+ summary.isActive,
1285
+ summary.signature,
1286
+ focus
1287
+ );
1288
+ const hasHeader = toolCalls.length > 1;
1289
+ const visibleCalls = !hasHeader || expanded ? toolCalls : toolCalls.filter(needsAttention);
1290
+ return /* @__PURE__ */ jsxs(
1291
+ "div",
1292
+ {
1293
+ "data-slot": "ai-tool-call-group",
1294
+ className,
1295
+ onBlur: (event) => {
1296
+ if (!event.currentTarget.contains(event.relatedTarget)) setFocus(null);
1297
+ },
1298
+ children: [
1299
+ hasHeader && /* @__PURE__ */ jsxs(
1300
+ "button",
1301
+ {
1302
+ type: "button",
1303
+ "aria-expanded": expanded,
1304
+ "aria-controls": listId,
1305
+ onClick: () => setExpanded(!expanded),
1306
+ onFocus: () => setFocus("header"),
1307
+ className: "focus-visible:ring-primary-500 flex max-w-full items-center gap-2 rounded px-1.5 py-1 text-start text-sm text-neutral-600 hover:bg-neutral-100 focus-visible:ring-2 focus-visible:outline-none dark:text-neutral-400 dark:hover:bg-neutral-800",
1308
+ children: [
1309
+ summary.isActive ? /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "shrink-0", children: /* @__PURE__ */ jsx(Spinner, { size: "xs" }) }) : /* @__PURE__ */ jsx(Wrench, { "aria-hidden": "true", className: "h-3.5 w-3.5 shrink-0" }),
1310
+ /* @__PURE__ */ jsx("span", { className: "font-medium", children: summary.isActive ? labels.running(summary.total) : labels.used(summary.total) }),
1311
+ summary.awaitingApproval > 0 && /* @__PURE__ */ jsx(Badge, { variant: "warning", size: "sm", className: "shrink-0", children: labels.needsApproval(summary.awaitingApproval) }),
1312
+ summary.failed > 0 && /* @__PURE__ */ jsx(Badge, { variant: "danger", size: "sm", className: "shrink-0", children: labels.failed(summary.failed) }),
1313
+ /* @__PURE__ */ jsx(
1314
+ ChevronDown,
1315
+ {
1316
+ "aria-hidden": "true",
1317
+ className: cn(
1318
+ "h-3.5 w-3.5 shrink-0 transition-transform motion-reduce:transition-none",
1319
+ expanded && "rotate-180"
1320
+ )
1321
+ }
1322
+ )
1323
+ ]
1324
+ }
1325
+ ),
1326
+ /* @__PURE__ */ jsx(
1327
+ "div",
1328
+ {
1329
+ role: "list",
1330
+ id: listId,
1331
+ onFocus: () => setFocus("rows"),
1332
+ className: cn(
1333
+ hasHeader && "ms-3 border-s border-neutral-200 ps-2 dark:border-neutral-700"
1334
+ ),
1335
+ children: /* @__PURE__ */ jsx(AnimatedPresence, { initial: false, children: visibleCalls.map((toolCall) => /* @__PURE__ */ jsx(
1336
+ ToolCallRow,
1337
+ {
1338
+ toolCall,
1339
+ labels,
1340
+ onApprove,
1341
+ onDeny,
1342
+ onLinkClick
1343
+ },
1344
+ toolCall.id
1345
+ )) })
1346
+ }
1347
+ ),
1348
+ /* @__PURE__ */ jsx("p", { role: "status", className: "sr-only", children: /* @__PURE__ */ jsx("span", { children: progressAnnouncement(summary, labels) }, summary.approvalKey) }),
1349
+ /* @__PURE__ */ jsx("p", { role: "status", className: "sr-only", children: summary.failed > 0 ? labels.announceFailed(summary.failed) : "" })
1350
+ ]
1351
+ }
1352
+ );
1353
+ }
940
1354
  var avatarVariants = cva(
941
1355
  "flex shrink-0 items-center justify-center rounded-full",
942
1356
  {
@@ -1307,6 +1721,54 @@ var ChatBubble = React2.forwardRef(
1307
1721
  }
1308
1722
  );
1309
1723
  ChatBubble.displayName = "ChatBubble";
1724
+ function MessageContentBlocks({
1725
+ message,
1726
+ streaming,
1727
+ onLinkClick,
1728
+ renderTextContent,
1729
+ toolCallGroup
1730
+ }) {
1731
+ const nodes = [];
1732
+ let run = [];
1733
+ const flushRun = () => {
1734
+ if (run.length === 0) return;
1735
+ nodes.push(
1736
+ /* @__PURE__ */ jsx(
1737
+ MCPToolCallGroup,
1738
+ {
1739
+ toolCalls: run,
1740
+ onLinkClick,
1741
+ ...toolCallGroup
1742
+ },
1743
+ `tool-call-group-${run[0].id}`
1744
+ )
1745
+ );
1746
+ run = [];
1747
+ };
1748
+ message.content.forEach((content, index) => {
1749
+ if (toolCallGroup && content.type === "tool_use" && content.toolCall) {
1750
+ run.push(content.toolCall);
1751
+ return;
1752
+ }
1753
+ flushRun();
1754
+ nodes.push(
1755
+ /* @__PURE__ */ jsx(
1756
+ ContentBlock,
1757
+ {
1758
+ content,
1759
+ onLinkClick,
1760
+ messageId: message.id,
1761
+ streaming,
1762
+ role: message.role,
1763
+ renderTextContent
1764
+ },
1765
+ index
1766
+ )
1767
+ );
1768
+ });
1769
+ flushRun();
1770
+ return /* @__PURE__ */ jsx(Fragment, { children: nodes });
1771
+ }
1310
1772
  function AIMessageDisplay({
1311
1773
  message,
1312
1774
  userName,
@@ -1315,11 +1777,22 @@ function AIMessageDisplay({
1315
1777
  onLinkClick,
1316
1778
  renderTextContent,
1317
1779
  renderMessageFooter,
1780
+ toolCallGroup,
1318
1781
  className
1319
1782
  }) {
1320
1783
  const isStreaming = message.status === "streaming";
1321
1784
  const hasContent = message.content.length > 0;
1322
1785
  const messageFooter = renderMessageFooter?.(message);
1786
+ const contentBlocks = /* @__PURE__ */ jsx(
1787
+ MessageContentBlocks,
1788
+ {
1789
+ message,
1790
+ streaming: isStreaming,
1791
+ onLinkClick,
1792
+ renderTextContent,
1793
+ toolCallGroup
1794
+ }
1795
+ );
1323
1796
  const formatTime = (timestamp) => {
1324
1797
  const date = new Date(timestamp);
1325
1798
  return date.toLocaleTimeString(void 0, {
@@ -1333,18 +1806,7 @@ function AIMessageDisplay({
1333
1806
  {
1334
1807
  "data-slot": "ai-message",
1335
1808
  className: cn(messageVariants({ role: message.role }), className),
1336
- children: /* @__PURE__ */ jsx("div", { className: "min-w-0 flex-1 space-y-2", children: message.content.map((content, index) => /* @__PURE__ */ jsx(
1337
- ContentBlock,
1338
- {
1339
- content,
1340
- onLinkClick,
1341
- messageId: message.id,
1342
- streaming: isStreaming,
1343
- role: message.role,
1344
- renderTextContent
1345
- },
1346
- index
1347
- )) })
1809
+ children: /* @__PURE__ */ jsx("div", { className: "min-w-0 flex-1 space-y-2", children: contentBlocks })
1348
1810
  }
1349
1811
  );
1350
1812
  }
@@ -1369,18 +1831,7 @@ function AIMessageDisplay({
1369
1831
  "data-slot": "ai-message-bubble",
1370
1832
  variant: message.role,
1371
1833
  hasError: message.status === "error",
1372
- children: hasContent ? /* @__PURE__ */ jsx("div", { className: "space-y-3", children: message.content.map((content, index) => /* @__PURE__ */ jsx(
1373
- ContentBlock,
1374
- {
1375
- content,
1376
- onLinkClick,
1377
- messageId: message.id,
1378
- streaming: isStreaming,
1379
- role: message.role,
1380
- renderTextContent
1381
- },
1382
- index
1383
- )) }) : isStreaming ? /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx(AITypingIndicator, {}) }) : null
1834
+ children: hasContent ? /* @__PURE__ */ jsx("div", { className: "space-y-3", children: contentBlocks }) : isStreaming ? /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx(AITypingIndicator, {}) }) : null
1384
1835
  }
1385
1836
  ),
1386
1837
  messageFooter != null && messageFooter !== false && /* @__PURE__ */ jsx("div", { "data-slot": "ai-message-footer", className: "w-fit max-w-[85%]", children: messageFooter }),
@@ -1428,6 +1879,6 @@ function JumpToBottomButton({
1428
1879
  );
1429
1880
  }
1430
1881
 
1431
- export { AILogoIcon, AIMessageDisplay, AITypingIndicator, ChatBubble, ChevronIcon, CloseIcon, CollapsiblePill, JumpToBottomButton, MCPToolCallDisplay, MessageAvatar, RefreshIcon, ResourceLink, SendIcon, SparklesIcon, SpinnerIcon, ToolStatusIcon, getToolIcon };
1432
- //# sourceMappingURL=chunk-UIFN2LYT.js.map
1433
- //# sourceMappingURL=chunk-UIFN2LYT.js.map
1882
+ export { AILogoIcon, AIMessageDisplay, AITypingIndicator, ChatBubble, ChevronIcon, CloseIcon, CollapsiblePill, JumpToBottomButton, MCPToolCallDisplay, MCPToolCallGroup, MessageAvatar, RefreshIcon, ResourceLink, SendIcon, SparklesIcon, SpinnerIcon, ToolStatusIcon, defaultMCPToolCallGroupLabels, getToolIcon };
1883
+ //# sourceMappingURL=chunk-O3MN3TYS.js.map
1884
+ //# sourceMappingURL=chunk-O3MN3TYS.js.map