@tutti-os/agent-gui 0.0.15 → 0.0.17

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 (50) hide show
  1. package/dist/AgentMentionSearchController-DqssJ2-b.d.ts +218 -0
  2. package/dist/agent-conversation/index.d.ts +3 -1
  3. package/dist/agent-conversation/index.js +5 -4
  4. package/dist/agent-conversation/index.js.map +1 -1
  5. package/dist/agent-message-center/index.d.ts +6 -2
  6. package/dist/agent-message-center/index.js +714 -291
  7. package/dist/agent-message-center/index.js.map +1 -1
  8. package/dist/app/renderer/agentactivity.css +176 -8
  9. package/dist/{chunk-KJPMZ7G5.js → chunk-65YMY2M3.js} +43 -17
  10. package/dist/chunk-65YMY2M3.js.map +1 -0
  11. package/dist/{chunk-OFGXNXYT.js → chunk-CDTTIUPL.js} +2 -2
  12. package/dist/{chunk-EK5RDKG7.js → chunk-GWR6WGZY.js} +21 -11
  13. package/dist/chunk-GWR6WGZY.js.map +1 -0
  14. package/dist/{chunk-H4HT3FE6.js → chunk-HVOPJU2K.js} +40 -30
  15. package/dist/chunk-HVOPJU2K.js.map +1 -0
  16. package/dist/{chunk-7CBJJNX6.js → chunk-JNGYJ7GM.js} +2 -2
  17. package/dist/{chunk-7CBJJNX6.js.map → chunk-JNGYJ7GM.js.map} +1 -1
  18. package/dist/{chunk-YKDFQADM.js → chunk-K44WER5Z.js} +177 -332
  19. package/dist/chunk-K44WER5Z.js.map +1 -0
  20. package/dist/{chunk-U4F3COKL.js → chunk-KHTIC52P.js} +83 -115
  21. package/dist/chunk-KHTIC52P.js.map +1 -0
  22. package/dist/chunk-O5TUTXHT.js +196 -0
  23. package/dist/chunk-O5TUTXHT.js.map +1 -0
  24. package/dist/{chunk-XHQGCP7A.js → chunk-OJ5WX7SZ.js} +2 -2
  25. package/dist/{chunk-SVOGXWFJ.js → chunk-VNAQ6QFE.js} +562 -468
  26. package/dist/chunk-VNAQ6QFE.js.map +1 -0
  27. package/dist/{chunk-2CA4NPP3.js → chunk-VO2TZNKV.js} +10 -7
  28. package/dist/{chunk-2CA4NPP3.js.map → chunk-VO2TZNKV.js.map} +1 -1
  29. package/dist/context-mention-palette/index.d.ts +5 -104
  30. package/dist/context-mention-palette/index.js +6 -5
  31. package/dist/i18n/index.d.ts +42 -16
  32. package/dist/i18n/index.js +1 -1
  33. package/dist/index.d.ts +22 -2
  34. package/dist/index.js +2002 -1329
  35. package/dist/index.js.map +1 -1
  36. package/dist/workbench/contribution.js +2 -2
  37. package/dist/workbench/index.d.ts +2 -1
  38. package/dist/workbench/index.js +2 -2
  39. package/dist/workbench/launch.js +1 -1
  40. package/dist/workspace-agent-generated-files.js +2 -2
  41. package/package.json +12 -12
  42. package/dist/agentFileMentionExtension-CM1c9bqk.d.ts +0 -86
  43. package/dist/chunk-EK5RDKG7.js.map +0 -1
  44. package/dist/chunk-H4HT3FE6.js.map +0 -1
  45. package/dist/chunk-KJPMZ7G5.js.map +0 -1
  46. package/dist/chunk-SVOGXWFJ.js.map +0 -1
  47. package/dist/chunk-U4F3COKL.js.map +0 -1
  48. package/dist/chunk-YKDFQADM.js.map +0 -1
  49. /package/dist/{chunk-OFGXNXYT.js.map → chunk-CDTTIUPL.js.map} +0 -0
  50. /package/dist/{chunk-XHQGCP7A.js.map → chunk-OJ5WX7SZ.js.map} +0 -0
@@ -3,7 +3,7 @@ import {
3
3
  approvalOptionDisplayLabel,
4
4
  getPromptToolDetails,
5
5
  isPromptRequestIdTitle
6
- } from "../chunk-2CA4NPP3.js";
6
+ } from "../chunk-VO2TZNKV.js";
7
7
  import {
8
8
  PLAN_IMPLEMENTATION_ACTION_IMPLEMENT,
9
9
  PLAN_IMPLEMENTATION_PROMPT,
@@ -16,16 +16,17 @@ import {
16
16
  cn,
17
17
  extractAgentMcpToolTarget,
18
18
  normalizeAskUserQuestions
19
- } from "../chunk-YKDFQADM.js";
19
+ } from "../chunk-K44WER5Z.js";
20
20
  import {
21
21
  managedAgentRoundedIconUrl,
22
22
  userAvatarPlaceholderUrl,
23
23
  workspaceAgentActivityStatusLabel
24
- } from "../chunk-OFGXNXYT.js";
24
+ } from "../chunk-CDTTIUPL.js";
25
25
  import "../chunk-MTFSQWZ6.js";
26
26
  import {
27
27
  resolveWorkspaceAgentSessionSortTimeUnixMs
28
28
  } from "../chunk-IBIMGLCD.js";
29
+ import "../chunk-O5TUTXHT.js";
29
30
  import {
30
31
  workspaceAgentProviderLabel
31
32
  } from "../chunk-TYGL25EL.js";
@@ -35,12 +36,12 @@ import {
35
36
  import {
36
37
  AgentGuiI18nProvider,
37
38
  useTranslation
38
- } from "../chunk-KJPMZ7G5.js";
39
+ } from "../chunk-65YMY2M3.js";
39
40
  import "../chunk-PJP5BUU6.js";
40
41
 
41
42
  // agent-message-center/WorkspaceAgentMessageCenterPanel.tsx
42
43
  import {
43
- memo,
44
+ memo as memo2,
44
45
  useCallback as useCallback2,
45
46
  useEffect as useEffect3,
46
47
  useLayoutEffect as useLayoutEffect2,
@@ -506,7 +507,9 @@ function buildWorkspaceAgentMessageCenterModel(snapshot, options = {}) {
506
507
  latestTurnOutcome: latestTurnOutcome(session.agentSessionId, messages),
507
508
  sortTimeUnixMs
508
509
  };
509
- });
510
+ }).filter(
511
+ (item) => isWithinMessageCenterItemCutoff(item, options.itemCutoffUnixMs)
512
+ );
510
513
  return {
511
514
  waitingCount: items.filter(isWaitingMessageCenterItem).length,
512
515
  items: items.sort(compareMessageCenterItems),
@@ -538,6 +541,16 @@ function isWaitingMessageCenterItem(item) {
538
541
  function isInteractiveMessageCenterItem(item) {
539
542
  return item.pendingPrompt !== null;
540
543
  }
544
+ function isWithinMessageCenterItemCutoff(item, cutoffUnixMs) {
545
+ if (!Number.isFinite(cutoffUnixMs)) {
546
+ return true;
547
+ }
548
+ if (isWaitingMessageCenterItem(item)) {
549
+ return true;
550
+ }
551
+ const timestamp = item.sortTimeUnixMs || item.lastAgentMessageAtUnixMs || 0;
552
+ return timestamp >= Number(cutoffUnixMs);
553
+ }
541
554
  function selectMessageCenterAttentionDeckItems(items) {
542
555
  return items.filter(isInteractiveMessageCenterItem);
543
556
  }
@@ -928,6 +941,8 @@ import { cn as cn3 } from "@tutti-os/ui-system";
928
941
 
929
942
  // agent-message-center/WorkspaceAgentMessageCenterCard.tsx
930
943
  import {
944
+ cloneElement,
945
+ memo,
931
946
  useCallback,
932
947
  useEffect,
933
948
  useLayoutEffect,
@@ -947,122 +962,129 @@ import { jsx as jsx2, jsxs } from "react/jsx-runtime";
947
962
  function stopMessageCenterTextPointerPropagation(event) {
948
963
  event.stopPropagation();
949
964
  }
950
- function WorkspaceAgentMessageCenterCard({
951
- cardRef,
952
- highlighted = false,
953
- interactive = true,
954
- item,
955
- isSubmitting,
956
- onLinkAction,
957
- onOpenChat,
958
- onSubmitPrompt
959
- }) {
960
- "use memo";
961
- const { t } = useTranslation();
962
- const prompt = item.pendingPrompt;
963
- const displayTitle = normalizeAgentTitleText(item.title);
964
- const summary = messageCenterVisibleSummary(item);
965
- const displayStatus = statusClass(item);
966
- const statusLabel = workspaceAgentActivityStatusLabel(displayStatus, t);
967
- return /* @__PURE__ */ jsxs(
968
- "article",
969
- {
970
- ref: cardRef,
971
- className: cn2(
972
- "workspace-agent-message-center__card group/message-card flex min-w-0 flex-col gap-2.5 rounded-lg border border-[var(--line-2)] bg-[var(--background-fronted)] p-3.5 outline outline-0 outline-offset-2 outline-transparent transition-[background-color,border-color,outline-color]",
973
- isWaitingMessageCenterItem(item) && "agent-gui-edge-glow border-[var(--tutti-purple-border)] bg-[var(--tutti-purple-bg)]",
974
- highlighted && "outline-2 outline-[var(--accent)]"
975
- ),
976
- "data-highlighted": highlighted ? "true" : void 0,
977
- "data-message-center-digest-kind": item.digest.primary.kind,
978
- "data-message-center-item-id": item.id,
979
- "data-waiting": isWaitingMessageCenterItem(item) ? "true" : void 0,
980
- "data-status": displayStatus,
981
- tabIndex: highlighted ? -1 : void 0,
982
- children: [
983
- /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 items-center justify-between gap-2.5", children: [
984
- /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 items-center gap-1.5", children: [
985
- /* @__PURE__ */ jsxs(Tooltip, { children: [
986
- /* @__PURE__ */ jsx2(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx2(
987
- "h3",
988
- {
989
- className: "workspace-agent-message-center__copy-text min-w-0 truncate text-[13px] font-bold leading-5 text-[var(--text-secondary)]",
990
- onPointerDown: stopMessageCenterTextPointerPropagation,
991
- children: displayTitle
992
- }
993
- ) }),
965
+ var WorkspaceAgentMessageCenterCard = memo(
966
+ function WorkspaceAgentMessageCenterCard2({
967
+ cardRef,
968
+ highlighted = false,
969
+ interactive = true,
970
+ item,
971
+ isSubmitting,
972
+ lazySummary = false,
973
+ onLinkAction,
974
+ onOpenChat,
975
+ onSubmitPrompt
976
+ }) {
977
+ "use memo";
978
+ const { t } = useTranslation();
979
+ const prompt = item.pendingPrompt;
980
+ const displayTitle = normalizeAgentTitleText(item.title);
981
+ const summary = messageCenterVisibleSummary(item);
982
+ const displayStatus = statusClass(item);
983
+ const statusLabel = workspaceAgentActivityStatusLabel(displayStatus, t);
984
+ return /* @__PURE__ */ jsxs(
985
+ "article",
986
+ {
987
+ ref: cardRef,
988
+ className: cn2(
989
+ "workspace-agent-message-center__card group/message-card flex min-w-0 flex-col gap-2.5 rounded-lg border border-[var(--line-2)] bg-[var(--background-fronted)] p-3.5 outline outline-0 outline-offset-2 outline-transparent transition-[background-color,border-color,outline-color]",
990
+ isWaitingMessageCenterItem(item) && "agent-gui-edge-glow border-[var(--tutti-purple-border)] bg-[var(--tutti-purple-bg)]",
991
+ highlighted && "outline-2 outline-[var(--accent)]"
992
+ ),
993
+ "data-highlighted": highlighted ? "true" : void 0,
994
+ "data-message-center-digest-kind": item.digest.primary.kind,
995
+ "data-message-center-item-id": item.id,
996
+ "data-waiting": isWaitingMessageCenterItem(item) ? "true" : void 0,
997
+ "data-status": displayStatus,
998
+ tabIndex: highlighted ? -1 : void 0,
999
+ children: [
1000
+ /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 items-center justify-between gap-2.5", children: [
1001
+ /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 items-center gap-1.5", children: [
994
1002
  /* @__PURE__ */ jsx2(
995
- TooltipContent,
1003
+ LazyMessageCenterTooltip,
996
1004
  {
1005
+ content: displayTitle,
997
1006
  side: "top",
998
1007
  align: "start",
999
1008
  className: "max-w-[min(360px,calc(100vw-32px))] whitespace-normal text-left [overflow-wrap:anywhere]",
1000
- children: displayTitle
1009
+ children: /* @__PURE__ */ jsx2(
1010
+ "h3",
1011
+ {
1012
+ className: "workspace-agent-message-center__copy-text min-w-0 truncate text-[13px] font-bold leading-5 text-[var(--text-secondary)]",
1013
+ onPointerDown: stopMessageCenterTextPointerPropagation,
1014
+ children: displayTitle
1015
+ }
1016
+ )
1001
1017
  }
1002
- )
1018
+ ),
1019
+ item.cwd ? /* @__PURE__ */ jsx2(ProjectPathInfo, { path: item.cwd }) : null
1003
1020
  ] }),
1004
- item.cwd ? /* @__PURE__ */ jsx2(ProjectPathInfo, { path: item.cwd }) : null
1021
+ /* @__PURE__ */ jsxs(
1022
+ "span",
1023
+ {
1024
+ className: "workspace-agent-message-center__status inline-flex shrink-0 items-center gap-1.5 text-[11px] font-semibold leading-4 text-[var(--text-secondary)]",
1025
+ "data-status": displayStatus,
1026
+ title: statusLabel,
1027
+ children: [
1028
+ /* @__PURE__ */ jsx2(
1029
+ StatusDot,
1030
+ {
1031
+ tone: messageCenterStatusTone(item),
1032
+ pulse: isWaitingMessageCenterItem(item) || item.status === "working",
1033
+ size: "sm",
1034
+ title: statusLabel
1035
+ }
1036
+ ),
1037
+ /* @__PURE__ */ jsx2("span", { children: statusLabel })
1038
+ ]
1039
+ }
1040
+ )
1005
1041
  ] }),
1006
- /* @__PURE__ */ jsxs(
1007
- "span",
1042
+ summary ? /* @__PURE__ */ jsx2(
1043
+ MessageCenterSummary,
1008
1044
  {
1009
- className: "workspace-agent-message-center__status inline-flex shrink-0 items-center gap-1.5 text-[11px] font-semibold leading-4 text-[var(--text-secondary)]",
1010
- "data-status": displayStatus,
1011
- title: statusLabel,
1012
- children: [
1013
- /* @__PURE__ */ jsx2(
1014
- StatusDot,
1015
- {
1016
- tone: messageCenterStatusTone(item),
1017
- pulse: isWaitingMessageCenterItem(item) || item.status === "working",
1018
- size: "sm",
1019
- title: statusLabel
1020
- }
1021
- ),
1022
- /* @__PURE__ */ jsx2("span", { children: statusLabel })
1023
- ]
1045
+ item,
1046
+ lazy: lazySummary,
1047
+ onLinkAction,
1048
+ summary,
1049
+ emptyLabel: t("agentHost.workspaceAgentMessageCenterNoSummary")
1050
+ }
1051
+ ) : null,
1052
+ prompt && interactive ? /* @__PURE__ */ jsx2("div", { className: "min-w-0", children: /* @__PURE__ */ jsx2(
1053
+ AgentInteractivePromptSurface,
1054
+ {
1055
+ embedded: true,
1056
+ variant: "compact",
1057
+ keyboardShortcuts: false,
1058
+ prompt,
1059
+ isSubmitting,
1060
+ onSubmit: onSubmitPrompt,
1061
+ labels: buildWorkspaceAgentInteractivePromptLabels(
1062
+ t,
1063
+ item.provider
1064
+ )
1065
+ }
1066
+ ) }) : null,
1067
+ /* @__PURE__ */ jsx2(
1068
+ MessageCenterOpenChatButton,
1069
+ {
1070
+ provider: item.provider,
1071
+ item,
1072
+ label: t("agentHost.workspaceAgentMessageCenterOpenChat"),
1073
+ onOpenChat,
1074
+ alwaysVisible: interactive && prompt !== null
1024
1075
  }
1025
1076
  )
1026
- ] }),
1027
- summary ? /* @__PURE__ */ jsx2(
1028
- MessageCenterSummary,
1029
- {
1030
- item,
1031
- onLinkAction,
1032
- summary,
1033
- emptyLabel: t("agentHost.workspaceAgentMessageCenterNoSummary")
1034
- }
1035
- ) : null,
1036
- prompt && interactive ? /* @__PURE__ */ jsx2("div", { className: "min-w-0", children: /* @__PURE__ */ jsx2(
1037
- AgentInteractivePromptSurface,
1038
- {
1039
- embedded: true,
1040
- variant: "compact",
1041
- keyboardShortcuts: false,
1042
- prompt,
1043
- isSubmitting,
1044
- onSubmit: onSubmitPrompt,
1045
- labels: buildWorkspaceAgentInteractivePromptLabels(
1046
- t,
1047
- item.provider
1048
- )
1049
- }
1050
- ) }) : null,
1051
- /* @__PURE__ */ jsx2(
1052
- MessageCenterOpenChatButton,
1053
- {
1054
- provider: item.provider,
1055
- item,
1056
- label: t("agentHost.workspaceAgentMessageCenterOpenChat"),
1057
- onOpenChat,
1058
- alwaysVisible: interactive && prompt !== null
1059
- }
1060
- )
1061
- ]
1062
- }
1063
- );
1064
- }
1077
+ ]
1078
+ }
1079
+ );
1080
+ }
1081
+ );
1065
1082
  var STACK_PRESENCE_FALLBACK_MS = 380;
1083
+ var MESSAGE_CENTER_STACK_INITIAL_RENDER_COUNT = 24;
1084
+ var MESSAGE_CENTER_STACK_RENDER_BATCH_SIZE = 24;
1085
+ var MESSAGE_CENTER_STACK_RENDER_BATCH_DELAY_MS = 40;
1086
+ var MESSAGE_CENTER_SUMMARY_LAZY_ROOT_MARGIN = "480px 0px";
1087
+ var MESSAGE_CENTER_SUMMARY_OVERFLOW_MEASURE_DELAY_MS = 80;
1066
1088
  function useStackRegionPresence(visible) {
1067
1089
  const [mounted, setMounted] = useState(visible);
1068
1090
  const closing = mounted && !visible;
@@ -1092,117 +1114,198 @@ function useStackRegionPresence(visible) {
1092
1114
  );
1093
1115
  return { closing, mounted, onAnimationEnd };
1094
1116
  }
1095
- function WorkspaceAgentMessageCenterStack({
1096
- className,
1097
- expanded,
1098
- groupId,
1099
- items,
1100
- renderCard,
1101
- onCollapse,
1102
- onExpand
1103
- }) {
1104
- "use memo";
1105
- const { t } = useTranslation();
1106
- const summaryRegion = useStackRegionPresence(!expanded);
1107
- const cardsRegion = useStackRegionPresence(expanded);
1108
- if (items.length < 2) {
1109
- return null;
1110
- }
1111
- const collapseLabel = t(
1112
- "agentHost.workspaceAgentMessageCenterCollapseStackAria"
1113
- );
1114
- return /* @__PURE__ */ jsxs(
1115
- "div",
1116
- {
1117
- className: cn2("relative flex min-w-0 flex-col", className),
1118
- "data-stack-count": items.length,
1119
- "data-stack-motion": "smooth",
1120
- "data-stack-state": expanded ? "expanded" : "collapsed",
1121
- "data-stack-top-item-id": items[0]?.id,
1122
- "data-testid": `workspace-agent-message-stack-${groupId}`,
1123
- children: [
1124
- summaryRegion.mounted ? /* @__PURE__ */ jsx2(
1125
- "div",
1126
- {
1127
- className: cn2(
1128
- "workspace-agent-message-center__stack-rest min-w-0",
1129
- summaryRegion.closing ? "workspace-agent-message-center__stack-rest--closing" : "workspace-agent-message-center__stack-rest--opening"
1130
- ),
1131
- onAnimationEnd: summaryRegion.onAnimationEnd,
1132
- children: /* @__PURE__ */ jsx2(
1133
- "div",
1134
- {
1135
- className: "min-h-0 min-w-0 overflow-hidden",
1136
- "aria-hidden": summaryRegion.closing ? true : void 0,
1137
- inert: summaryRegion.closing ? true : void 0,
1138
- children: /* @__PURE__ */ jsx2(
1139
- MessageCenterStackSummary,
1140
- {
1141
- groupId,
1142
- items,
1143
- onExpand
1144
- }
1145
- )
1146
- }
1147
- )
1148
- }
1149
- ) : null,
1150
- cardsRegion.mounted ? /* @__PURE__ */ jsx2(
1151
- "div",
1152
- {
1153
- className: cn2(
1154
- "workspace-agent-message-center__stack-rest min-w-0",
1155
- cardsRegion.closing ? "workspace-agent-message-center__stack-rest--closing" : "workspace-agent-message-center__stack-rest--opening"
1156
- ),
1157
- onAnimationEnd: cardsRegion.onAnimationEnd,
1158
- children: /* @__PURE__ */ jsxs(
1159
- "div",
1160
- {
1161
- className: "min-h-0 min-w-0 overflow-hidden",
1162
- "aria-hidden": cardsRegion.closing ? true : void 0,
1163
- inert: cardsRegion.closing ? true : void 0,
1164
- children: [
1165
- /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 items-center justify-between gap-2 px-0.5 pb-1.5", children: [
1166
- /* @__PURE__ */ jsxs("span", { className: "flex min-w-0 items-center gap-1.5 text-[13px] font-semibold leading-4 text-[var(--text-tertiary)]", children: [
1117
+ var WorkspaceAgentMessageCenterStack = memo(
1118
+ function WorkspaceAgentMessageCenterStack2({
1119
+ className,
1120
+ expanded,
1121
+ groupId,
1122
+ highlightedItemId,
1123
+ items,
1124
+ renderCard,
1125
+ onCollapse,
1126
+ onExpand
1127
+ }) {
1128
+ "use memo";
1129
+ const { t } = useTranslation();
1130
+ const summaryRegion = useStackRegionPresence(!expanded);
1131
+ const cardsRegion = useStackRegionPresence(expanded);
1132
+ const visibleItems = useBatchedMessageCenterStackItems({
1133
+ expanded,
1134
+ highlightedItemId,
1135
+ items,
1136
+ mounted: cardsRegion.mounted
1137
+ });
1138
+ if (items.length < 2) {
1139
+ return null;
1140
+ }
1141
+ const collapseLabel = t(
1142
+ "agentHost.workspaceAgentMessageCenterCollapseStackAria"
1143
+ );
1144
+ return /* @__PURE__ */ jsxs(
1145
+ "div",
1146
+ {
1147
+ className: cn2("relative flex min-w-0 flex-col", className),
1148
+ "data-stack-count": items.length,
1149
+ "data-stack-motion": "smooth",
1150
+ "data-stack-state": expanded ? "expanded" : "collapsed",
1151
+ "data-stack-top-item-id": items[0]?.id,
1152
+ "data-testid": `workspace-agent-message-stack-${groupId}`,
1153
+ children: [
1154
+ summaryRegion.mounted ? /* @__PURE__ */ jsx2(
1155
+ "div",
1156
+ {
1157
+ className: cn2(
1158
+ "workspace-agent-message-center__stack-rest min-w-0",
1159
+ summaryRegion.closing ? "workspace-agent-message-center__stack-rest--closing" : "workspace-agent-message-center__stack-rest--opening"
1160
+ ),
1161
+ onAnimationEnd: summaryRegion.onAnimationEnd,
1162
+ children: /* @__PURE__ */ jsx2(
1163
+ "div",
1164
+ {
1165
+ className: "min-h-0 min-w-0 overflow-hidden",
1166
+ "aria-hidden": summaryRegion.closing ? true : void 0,
1167
+ inert: summaryRegion.closing ? true : void 0,
1168
+ children: /* @__PURE__ */ jsx2(
1169
+ MessageCenterStackSummary,
1170
+ {
1171
+ groupId,
1172
+ items,
1173
+ onExpand
1174
+ }
1175
+ )
1176
+ }
1177
+ )
1178
+ }
1179
+ ) : null,
1180
+ cardsRegion.mounted ? /* @__PURE__ */ jsx2(
1181
+ "div",
1182
+ {
1183
+ className: cn2(
1184
+ "workspace-agent-message-center__stack-rest min-w-0",
1185
+ cardsRegion.closing ? "workspace-agent-message-center__stack-rest--closing" : "workspace-agent-message-center__stack-rest--opening"
1186
+ ),
1187
+ onAnimationEnd: cardsRegion.onAnimationEnd,
1188
+ children: /* @__PURE__ */ jsxs(
1189
+ "div",
1190
+ {
1191
+ className: "min-h-0 min-w-0 overflow-hidden",
1192
+ "aria-hidden": cardsRegion.closing ? true : void 0,
1193
+ inert: cardsRegion.closing ? true : void 0,
1194
+ children: [
1195
+ /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 items-center justify-between gap-2 px-0.5 pb-1.5", children: [
1196
+ /* @__PURE__ */ jsxs("span", { className: "flex min-w-0 items-center gap-1.5 text-[13px] font-semibold leading-4 text-[var(--text-tertiary)]", children: [
1197
+ /* @__PURE__ */ jsx2(
1198
+ MessageCenterIdentityAvatarMark,
1199
+ {
1200
+ identity: items[0]?.identity ?? null,
1201
+ provider: items[0]?.provider ?? "",
1202
+ userId: items[0]?.userId ?? null
1203
+ }
1204
+ ),
1205
+ /* @__PURE__ */ jsx2("span", { className: "min-w-0 truncate", children: t(
1206
+ "agentHost.workspaceAgentMessageCenterStackSummaryCount",
1207
+ {
1208
+ count: items.length
1209
+ }
1210
+ ) })
1211
+ ] }),
1167
1212
  /* @__PURE__ */ jsx2(
1168
- MessageCenterIdentityAvatarMark,
1213
+ LazyMessageCenterTooltip,
1169
1214
  {
1170
- identity: items[0]?.identity ?? null,
1171
- provider: items[0]?.provider ?? "",
1172
- userId: items[0]?.userId ?? null
1215
+ content: collapseLabel,
1216
+ side: "top",
1217
+ align: "center",
1218
+ children: /* @__PURE__ */ jsx2(
1219
+ Button,
1220
+ {
1221
+ type: "button",
1222
+ variant: "ghost",
1223
+ size: "icon-sm",
1224
+ "aria-label": collapseLabel,
1225
+ className: "size-6 text-[var(--text-tertiary)] hover:text-[var(--text-primary)]",
1226
+ onClick: () => onCollapse(groupId),
1227
+ children: /* @__PURE__ */ jsx2(ChevronUp, { className: "size-3.5", "aria-hidden": "true" })
1228
+ }
1229
+ )
1173
1230
  }
1174
- ),
1175
- /* @__PURE__ */ jsx2("span", { className: "min-w-0 truncate", children: t("agentHost.workspaceAgentMessageCenterStackSummaryCount", {
1176
- count: items.length
1177
- }) })
1231
+ )
1178
1232
  ] }),
1179
- /* @__PURE__ */ jsxs(Tooltip, { children: [
1180
- /* @__PURE__ */ jsx2(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx2(
1181
- Button,
1182
- {
1183
- type: "button",
1184
- variant: "ghost",
1185
- size: "icon-sm",
1186
- "aria-label": collapseLabel,
1187
- className: "size-6 text-[var(--text-tertiary)] hover:text-[var(--text-primary)]",
1188
- onClick: onCollapse,
1189
- children: /* @__PURE__ */ jsx2(ChevronUp, { className: "size-3.5", "aria-hidden": "true" })
1190
- }
1191
- ) }),
1192
- /* @__PURE__ */ jsx2(TooltipContent, { side: "top", align: "center", children: collapseLabel })
1193
- ] })
1194
- ] }),
1195
- /* @__PURE__ */ jsx2("div", { className: "flex min-w-0 flex-col gap-2.5", children: items.map(
1196
- (item, stackedIndex) => renderCard(item, { stackedIndex })
1197
- ) })
1198
- ]
1199
- }
1200
- )
1201
- }
1202
- ) : null
1203
- ]
1204
- }
1233
+ /* @__PURE__ */ jsx2("div", { className: "flex min-w-0 flex-col gap-2.5", children: visibleItems.map(
1234
+ (item, stackedIndex) => renderCard(item, { stackedIndex })
1235
+ ) })
1236
+ ]
1237
+ }
1238
+ )
1239
+ }
1240
+ ) : null
1241
+ ]
1242
+ }
1243
+ );
1244
+ },
1245
+ areMessageCenterStackPropsEqual
1246
+ );
1247
+ function areMessageCenterStackPropsEqual(previous, next) {
1248
+ if (previous.className !== next.className || previous.expanded !== next.expanded || previous.groupId !== next.groupId || previous.onCollapse !== next.onCollapse || previous.onExpand !== next.onExpand || previous.renderCard !== next.renderCard) {
1249
+ return false;
1250
+ }
1251
+ if (next.expanded) {
1252
+ return previous.highlightedItemId === next.highlightedItemId && previous.items === next.items;
1253
+ }
1254
+ return messageCenterCollapsedStackSignature(previous.items) === messageCenterCollapsedStackSignature(next.items);
1255
+ }
1256
+ function messageCenterCollapsedStackSignature(items) {
1257
+ const firstItem = items[0];
1258
+ if (!firstItem) {
1259
+ return "0";
1260
+ }
1261
+ const hasWaiting = items.some(isWaitingMessageCenterItem) ? "1" : "0";
1262
+ return [
1263
+ items.length,
1264
+ firstItem.id,
1265
+ firstItem.provider,
1266
+ firstItem.userId ?? "",
1267
+ firstItem.identity?.userName ?? "",
1268
+ firstItem.identity?.agentName ?? "",
1269
+ hasWaiting,
1270
+ messageCenterStackPreviewText(firstItem)
1271
+ ].join(":");
1272
+ }
1273
+ function useBatchedMessageCenterStackItems({
1274
+ expanded,
1275
+ highlightedItemId,
1276
+ items,
1277
+ mounted
1278
+ }) {
1279
+ const limit = items.length;
1280
+ const highlightedIndex = highlightedItemId === null || highlightedItemId === void 0 ? -1 : items.findIndex((item) => item.id === highlightedItemId);
1281
+ const initialCount = Math.min(
1282
+ limit,
1283
+ Math.max(MESSAGE_CENTER_STACK_INITIAL_RENDER_COUNT, highlightedIndex + 1)
1205
1284
  );
1285
+ const [renderCount, setRenderCount] = useState(initialCount);
1286
+ useEffect(() => {
1287
+ if (!mounted) {
1288
+ setRenderCount(initialCount);
1289
+ return;
1290
+ }
1291
+ setRenderCount(
1292
+ (current) => Math.min(Math.max(current, initialCount), limit)
1293
+ );
1294
+ }, [initialCount, limit, mounted]);
1295
+ useEffect(() => {
1296
+ if (!expanded || !mounted || renderCount >= limit) {
1297
+ return void 0;
1298
+ }
1299
+ const timeoutId = window.setTimeout(() => {
1300
+ setRenderCount(
1301
+ (current) => Math.min(current + MESSAGE_CENTER_STACK_RENDER_BATCH_SIZE, limit)
1302
+ );
1303
+ }, MESSAGE_CENTER_STACK_RENDER_BATCH_DELAY_MS);
1304
+ return () => {
1305
+ window.clearTimeout(timeoutId);
1306
+ };
1307
+ }, [expanded, limit, mounted, renderCount]);
1308
+ return items.slice(0, Math.min(renderCount, limit));
1206
1309
  }
1207
1310
  function MessageCenterStackSummary({
1208
1311
  groupId,
@@ -1231,7 +1334,7 @@ function MessageCenterStackSummary({
1231
1334
  "data-stack-provider": firstItem.provider,
1232
1335
  "data-stack-user-id": firstItem.userId ?? "",
1233
1336
  "data-testid": `workspace-agent-message-stack-summary-${groupId}`,
1234
- onClick: onExpand,
1337
+ onClick: () => onExpand(groupId),
1235
1338
  children: /* @__PURE__ */ jsxs(
1236
1339
  "span",
1237
1340
  {
@@ -1357,12 +1460,21 @@ function isGenericApprovalSummary(summary) {
1357
1460
  function MessageCenterSummary({
1358
1461
  emptyLabel,
1359
1462
  item,
1463
+ lazy,
1360
1464
  onLinkAction,
1361
1465
  summary
1362
1466
  }) {
1363
1467
  "use memo";
1364
1468
  const summaryRef = useRef(null);
1365
1469
  const [isOverflowing, setIsOverflowing] = useState(false);
1470
+ const shouldRenderRichSummary = useLazyMessageCenterSummaryReady(
1471
+ summaryRef,
1472
+ lazy
1473
+ );
1474
+ const shouldMeasureOverflow = useDeferredMessageCenterSummaryMeasureReady(
1475
+ summaryRef,
1476
+ shouldRenderRichSummary
1477
+ );
1366
1478
  const handleLinkAction = useCallback(
1367
1479
  (action) => {
1368
1480
  onLinkAction?.(
@@ -1371,21 +1483,29 @@ function MessageCenterSummary({
1371
1483
  },
1372
1484
  [item.provider, onLinkAction]
1373
1485
  );
1374
- useLayoutEffect(() => {
1486
+ useEffect(() => {
1487
+ if (!shouldMeasureOverflow) {
1488
+ setIsOverflowing(false);
1489
+ return void 0;
1490
+ }
1375
1491
  const element = summaryRef.current;
1376
1492
  if (!element) {
1377
- return;
1493
+ return void 0;
1378
1494
  }
1379
1495
  const updateOverflowState = () => {
1380
1496
  setIsOverflowing(element.scrollHeight > element.clientHeight + 1);
1381
1497
  };
1382
- updateOverflowState();
1383
- const resizeObserver = new ResizeObserver(updateOverflowState);
1384
- resizeObserver.observe(element);
1498
+ let resizeObserver = null;
1499
+ const timeoutId = window.setTimeout(() => {
1500
+ updateOverflowState();
1501
+ resizeObserver = new ResizeObserver(updateOverflowState);
1502
+ resizeObserver.observe(element);
1503
+ }, MESSAGE_CENTER_SUMMARY_OVERFLOW_MEASURE_DELAY_MS);
1385
1504
  return () => {
1386
- resizeObserver.disconnect();
1505
+ window.clearTimeout(timeoutId);
1506
+ resizeObserver?.disconnect();
1387
1507
  };
1388
- }, [summary]);
1508
+ }, [shouldMeasureOverflow, summary]);
1389
1509
  return /* @__PURE__ */ jsx2(
1390
1510
  AgentVerticalScrollArea,
1391
1511
  {
@@ -1398,7 +1518,7 @@ function MessageCenterSummary({
1398
1518
  onPointerDown: stopMessageCenterTextPointerPropagation,
1399
1519
  scrollbarClassName: "top-2 bottom-2 right-1.5",
1400
1520
  syncKey: summary,
1401
- children: summary ? /* @__PURE__ */ jsx2(
1521
+ children: summary && shouldRenderRichSummary ? /* @__PURE__ */ jsx2(
1402
1522
  AgentMessageMarkdown,
1403
1523
  {
1404
1524
  content: summary,
@@ -1411,10 +1531,85 @@ function MessageCenterSummary({
1411
1531
  },
1412
1532
  enableImageZoom: true
1413
1533
  }
1414
- ) : emptyLabel
1534
+ ) : summary ? /* @__PURE__ */ jsx2("div", { className: "whitespace-pre-wrap [overflow-wrap:anywhere]", children: summary }) : emptyLabel
1415
1535
  }
1416
1536
  );
1417
1537
  }
1538
+ function useLazyMessageCenterSummaryReady(ref, lazy) {
1539
+ const [ready, setReady] = useState(!lazy);
1540
+ useEffect(() => {
1541
+ setReady(!lazy);
1542
+ }, [lazy]);
1543
+ useEffect(() => {
1544
+ if (!lazy) {
1545
+ return void 0;
1546
+ }
1547
+ if (ready) {
1548
+ return void 0;
1549
+ }
1550
+ const element = ref.current;
1551
+ if (!element || typeof IntersectionObserver === "undefined") {
1552
+ setReady(true);
1553
+ return void 0;
1554
+ }
1555
+ const observer = new IntersectionObserver(
1556
+ (entries) => {
1557
+ if (entries.some((entry) => entry.isIntersecting)) {
1558
+ setReady(true);
1559
+ observer.disconnect();
1560
+ }
1561
+ },
1562
+ { rootMargin: MESSAGE_CENTER_SUMMARY_LAZY_ROOT_MARGIN }
1563
+ );
1564
+ observer.observe(element);
1565
+ return () => observer.disconnect();
1566
+ }, [lazy, ready, ref]);
1567
+ return ready;
1568
+ }
1569
+ function useDeferredMessageCenterSummaryMeasureReady(ref, enabled) {
1570
+ const [ready, setReady] = useState(false);
1571
+ useEffect(() => {
1572
+ if (!enabled) {
1573
+ setReady(false);
1574
+ return void 0;
1575
+ }
1576
+ if (ready) {
1577
+ return void 0;
1578
+ }
1579
+ const element = ref.current;
1580
+ if (!element || typeof IntersectionObserver === "undefined") {
1581
+ const timeoutId2 = window.setTimeout(
1582
+ () => setReady(true),
1583
+ MESSAGE_CENTER_SUMMARY_OVERFLOW_MEASURE_DELAY_MS
1584
+ );
1585
+ return () => {
1586
+ window.clearTimeout(timeoutId2);
1587
+ };
1588
+ }
1589
+ let timeoutId = null;
1590
+ const observer = new IntersectionObserver(
1591
+ (entries) => {
1592
+ if (!entries.some((entry) => entry.isIntersecting)) {
1593
+ return;
1594
+ }
1595
+ observer.disconnect();
1596
+ timeoutId = window.setTimeout(
1597
+ () => setReady(true),
1598
+ MESSAGE_CENTER_SUMMARY_OVERFLOW_MEASURE_DELAY_MS
1599
+ );
1600
+ },
1601
+ { rootMargin: MESSAGE_CENTER_SUMMARY_LAZY_ROOT_MARGIN }
1602
+ );
1603
+ observer.observe(element);
1604
+ return () => {
1605
+ observer.disconnect();
1606
+ if (timeoutId !== null) {
1607
+ window.clearTimeout(timeoutId);
1608
+ }
1609
+ };
1610
+ }, [enabled, ready, ref]);
1611
+ return ready;
1612
+ }
1418
1613
  function MessageCenterOpenChatButton({
1419
1614
  alwaysVisible = false,
1420
1615
  item,
@@ -1573,25 +1768,66 @@ function MessageCenterIdentityAvatarStack({
1573
1768
  }
1574
1769
  function ProjectPathInfo({ path }) {
1575
1770
  "use memo";
1576
- return /* @__PURE__ */ jsxs(Tooltip, { children: [
1577
- /* @__PURE__ */ jsx2(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx2(
1578
- "button",
1579
- {
1580
- type: "button",
1581
- className: "workspace-agent-message-center__project-info-button invisible inline-flex size-5 shrink-0 items-center justify-center rounded-sm text-[var(--text-secondary)] opacity-0 transition-[background-color,color,opacity,visibility] group-hover/message-card:visible group-hover/message-card:opacity-100 group-focus-within/message-card:visible group-focus-within/message-card:opacity-100 hover:bg-[var(--transparency-hover)] hover:text-[var(--text-primary)] focus-visible:bg-[var(--transparency-hover)] focus-visible:text-[var(--text-primary)] focus-visible:outline-none",
1582
- "aria-label": path,
1583
- children: /* @__PURE__ */ jsx2(Info, { className: "size-3.5", strokeWidth: 2, "aria-hidden": "true" })
1584
- }
1585
- ) }),
1586
- /* @__PURE__ */ jsx2(
1587
- TooltipContent,
1588
- {
1589
- side: "top",
1590
- align: "start",
1591
- className: "max-w-[320px] text-[11px] [overflow-wrap:anywhere]",
1592
- children: path
1593
- }
1594
- )
1771
+ return /* @__PURE__ */ jsx2(
1772
+ LazyMessageCenterTooltip,
1773
+ {
1774
+ content: path,
1775
+ side: "top",
1776
+ align: "start",
1777
+ className: "max-w-[320px] text-[11px] [overflow-wrap:anywhere]",
1778
+ children: /* @__PURE__ */ jsx2(
1779
+ "button",
1780
+ {
1781
+ type: "button",
1782
+ className: "workspace-agent-message-center__project-info-button invisible inline-flex size-5 shrink-0 items-center justify-center rounded-sm text-[var(--text-secondary)] opacity-0 transition-[background-color,color,opacity,visibility] group-hover/message-card:visible group-hover/message-card:opacity-100 group-focus-within/message-card:visible group-focus-within/message-card:opacity-100 hover:bg-[var(--transparency-hover)] hover:text-[var(--text-primary)] focus-visible:bg-[var(--transparency-hover)] focus-visible:text-[var(--text-primary)] focus-visible:outline-none",
1783
+ "aria-label": path,
1784
+ children: /* @__PURE__ */ jsx2(Info, { className: "size-3.5", strokeWidth: 2, "aria-hidden": "true" })
1785
+ }
1786
+ )
1787
+ }
1788
+ );
1789
+ }
1790
+ function LazyMessageCenterTooltip({
1791
+ align,
1792
+ children,
1793
+ className,
1794
+ content,
1795
+ side
1796
+ }) {
1797
+ "use memo";
1798
+ const [hydrated, setHydrated] = useState(false);
1799
+ const [open, setOpen] = useState(false);
1800
+ const showTooltip = useCallback(() => {
1801
+ setHydrated(true);
1802
+ setOpen(true);
1803
+ }, []);
1804
+ const hideTooltip = useCallback(() => {
1805
+ setOpen(false);
1806
+ }, []);
1807
+ const trigger = cloneElement(children, {
1808
+ onBlur: (event) => {
1809
+ children.props.onBlur?.(event);
1810
+ hideTooltip();
1811
+ },
1812
+ onFocus: (event) => {
1813
+ children.props.onFocus?.(event);
1814
+ showTooltip();
1815
+ },
1816
+ onPointerEnter: (event) => {
1817
+ children.props.onPointerEnter?.(event);
1818
+ showTooltip();
1819
+ },
1820
+ onPointerLeave: (event) => {
1821
+ children.props.onPointerLeave?.(event);
1822
+ hideTooltip();
1823
+ }
1824
+ });
1825
+ if (!hydrated) {
1826
+ return trigger;
1827
+ }
1828
+ return /* @__PURE__ */ jsxs(Tooltip, { open, onOpenChange: setOpen, children: [
1829
+ /* @__PURE__ */ jsx2(TooltipTrigger, { asChild: true, children: trigger }),
1830
+ /* @__PURE__ */ jsx2(TooltipContent, { side, align, className, children: content })
1595
1831
  ] });
1596
1832
  }
1597
1833
  function AgentProviderLabel({ provider }) {
@@ -1846,6 +2082,40 @@ function messageCenterAgentUserStackId(item) {
1846
2082
  const userId = item.userId?.trim() || "unknown-user";
1847
2083
  return `agent-user:${provider}:${userId}`;
1848
2084
  }
2085
+ function messageCenterStackRenderId(groupId, stackId) {
2086
+ return groupId === stackId ? stackId : `${groupId}:${stackId}`;
2087
+ }
2088
+ function messageCenterStackScrollSyncSegment({
2089
+ expanded,
2090
+ groupId,
2091
+ stack
2092
+ }) {
2093
+ const stackId = messageCenterStackRenderId(groupId, stack.id);
2094
+ if (expanded) {
2095
+ return `expanded:${stackId}:${stack.items.map((item) => item.id).join("|")}`;
2096
+ }
2097
+ return `collapsed:${stackId}:${messageCenterCollapsedStackSignature2(
2098
+ stack.items
2099
+ )}`;
2100
+ }
2101
+ function messageCenterCollapsedStackSignature2(items) {
2102
+ const firstItem = items[0];
2103
+ if (!firstItem) {
2104
+ return "0";
2105
+ }
2106
+ const hasWaiting = items.some(isWaitingMessageCenterItem) ? "1" : "0";
2107
+ const summary = firstItem.digest.primary.summary.trim() || firstItem.lastAgentMessageSummary.trim() || firstItem.title.trim();
2108
+ return [
2109
+ items.length,
2110
+ firstItem.id,
2111
+ firstItem.provider,
2112
+ firstItem.userId ?? "",
2113
+ firstItem.identity?.userName ?? "",
2114
+ firstItem.identity?.agentName ?? "",
2115
+ hasWaiting,
2116
+ summary
2117
+ ].join(":");
2118
+ }
1849
2119
  function buildMessageCenterStatusOptions(counts, t) {
1850
2120
  return [
1851
2121
  {
@@ -1971,7 +2241,12 @@ function groupMessageCenterItems(items, groupBy, t) {
1971
2241
  {
1972
2242
  id: "needs-attention",
1973
2243
  label: t("agentHost.workspaceAgentMessageCenterGroupNeedsAttention"),
1974
- match: (item) => messageCenterStatusFilterValue(item) === "waiting" || messageCenterStatusFilterValue(item) === "failed"
2244
+ match: (item) => messageCenterStatusFilterValue(item) === "waiting"
2245
+ },
2246
+ {
2247
+ id: "failed",
2248
+ label: t("agentHost.workspaceAgentMessageCenterFilterFailed"),
2249
+ match: (item) => messageCenterStatusFilterValue(item) === "failed"
1975
2250
  },
1976
2251
  {
1977
2252
  id: "working",
@@ -2193,7 +2468,8 @@ function MessageCenterOptionWithCount({
2193
2468
  // agent-message-center/WorkspaceAgentMessageCenterPanel.tsx
2194
2469
  import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
2195
2470
  var MESSAGE_CENTER_TOOLTIP_DELAY_MS = 300;
2196
- var WorkspaceAgentMessageCenterPanel = memo(
2471
+ var MESSAGE_CENTER_STACK_EAGER_SUMMARY_COUNT = 8;
2472
+ var WorkspaceAgentMessageCenterPanel = memo2(
2197
2473
  function WorkspaceAgentMessageCenterPanel2({
2198
2474
  open,
2199
2475
  i18n,
@@ -2209,6 +2485,9 @@ var WorkspaceAgentMessageCenterPanel = memo(
2209
2485
  onSubmitPrompt
2210
2486
  }) {
2211
2487
  "use memo";
2488
+ if (!open) {
2489
+ return null;
2490
+ }
2212
2491
  return /* @__PURE__ */ jsx5(AgentGuiI18nProvider, { runtime: i18n, locale, children: /* @__PURE__ */ jsx5(
2213
2492
  WorkspaceAgentMessageCenterPanelContent,
2214
2493
  {
@@ -2284,11 +2563,36 @@ function WorkspaceAgentMessageCenterPanelContent({
2284
2563
  () => groupMessageCenterItems(listItems, groupBy, t),
2285
2564
  [groupBy, t, listItems]
2286
2565
  );
2566
+ const itemGroupStacks = useMemo2(
2567
+ () => itemGroups.map((group) => ({
2568
+ ...group,
2569
+ stacks: partitionMessageCenterItemsByAgentUser(group.items)
2570
+ })),
2571
+ [itemGroups]
2572
+ );
2287
2573
  const highlightedItem = useMemo2(
2288
2574
  () => highlightedItemId ? model.items.find((item) => item.id === highlightedItemId) ?? null : null,
2289
2575
  [highlightedItemId, model.items]
2290
2576
  );
2291
2577
  const activeStatusSummary = statusFilterSummary(statusFilters, statusOptions);
2578
+ const scrollSyncKey = useMemo2(
2579
+ () => [
2580
+ groupBy,
2581
+ activeStatusSummary,
2582
+ ...deckItems.map((item) => `deck:${item.id}`),
2583
+ ...itemGroupStacks.flatMap(
2584
+ (group) => group.stacks.map((stack) => {
2585
+ const stackId = messageCenterStackRenderId(group.id, stack.id);
2586
+ return messageCenterStackScrollSyncSegment({
2587
+ expanded: expandedStackIds.has(stackId),
2588
+ groupId: group.id,
2589
+ stack
2590
+ });
2591
+ })
2592
+ )
2593
+ ].join("|"),
2594
+ [activeStatusSummary, deckItems, expandedStackIds, groupBy, itemGroupStacks]
2595
+ );
2292
2596
  const hasActiveFilters = statusFilters !== null || providerFilters !== null;
2293
2597
  const headerSummary = useMemo2(() => {
2294
2598
  if (hasActiveFilters) {
@@ -2436,15 +2740,15 @@ function WorkspaceAgentMessageCenterPanelContent({
2436
2740
  if (!open || !highlightedItemId) {
2437
2741
  return;
2438
2742
  }
2439
- for (const group of itemGroups) {
2440
- for (const stack of partitionMessageCenterItemsByAgentUser(group.items)) {
2743
+ for (const group of itemGroupStacks) {
2744
+ for (const stack of group.stacks) {
2441
2745
  if (stack.items.length > 1 && stack.items.some((item) => item.id === highlightedItemId)) {
2442
- expandStack(`${group.id}:${stack.id}`);
2746
+ expandStack(messageCenterStackRenderId(group.id, stack.id));
2443
2747
  return;
2444
2748
  }
2445
2749
  }
2446
2750
  }
2447
- }, [expandStack, highlightedItemId, itemGroups, open]);
2751
+ }, [expandStack, highlightedItemId, itemGroupStacks, open]);
2448
2752
  useLayoutEffect2(() => {
2449
2753
  if (!open || !highlightedItemId) {
2450
2754
  lastScrolledHighlightedItemIdRef.current = null;
@@ -2487,6 +2791,48 @@ function WorkspaceAgentMessageCenterPanelContent({
2487
2791
  window.clearTimeout(timeoutId);
2488
2792
  };
2489
2793
  }, [highlightedItemId, onHighlightedItemSettled, open]);
2794
+ const renderMessageCenterCard = useCallback2(
2795
+ (item, options = {}) => {
2796
+ const highlighted = item.id === highlightedItemId;
2797
+ const stackedIndex = options.stackedIndex;
2798
+ const card = /* @__PURE__ */ jsx5(
2799
+ MessageCenterRenderedCard,
2800
+ {
2801
+ highlighted,
2802
+ item,
2803
+ isSubmitting: submittingPromptKey === `${item.agentSessionId}:${item.pendingPrompt?.requestId}`,
2804
+ lazySummary: stackedIndex !== void 0 && stackedIndex >= MESSAGE_CENTER_STACK_EAGER_SUMMARY_COUNT,
2805
+ registerNode: setItemNode,
2806
+ onLinkAction,
2807
+ onOpenChat,
2808
+ onSubmitPrompt: submitPrompt
2809
+ },
2810
+ item.agentSessionId
2811
+ );
2812
+ if (stackedIndex === void 0) {
2813
+ return card;
2814
+ }
2815
+ return /* @__PURE__ */ jsx5(
2816
+ "div",
2817
+ {
2818
+ className: "min-w-0 motion-safe:animate-in motion-safe:fade-in-0 motion-safe:slide-in-from-top-1 motion-safe:duration-200 motion-safe:ease-[cubic-bezier(0.22,1,0.36,1)] motion-reduce:animate-none",
2819
+ style: {
2820
+ animationDelay: `${Math.min(stackedIndex * 24, 96)}ms`
2821
+ },
2822
+ children: card
2823
+ },
2824
+ item.agentSessionId
2825
+ );
2826
+ },
2827
+ [
2828
+ highlightedItemId,
2829
+ onLinkAction,
2830
+ onOpenChat,
2831
+ setItemNode,
2832
+ submitPrompt,
2833
+ submittingPromptKey
2834
+ ]
2835
+ );
2490
2836
  return /* @__PURE__ */ jsx5(
2491
2837
  Drawer,
2492
2838
  {
@@ -2537,7 +2883,7 @@ function WorkspaceAgentMessageCenterPanelContent({
2537
2883
  className: "min-h-0 flex-1",
2538
2884
  viewportClassName: "flex h-full w-full flex-col px-3.5 pt-4 pb-4",
2539
2885
  scrollbarClassName: "top-4 bottom-4",
2540
- syncKey: `${groupBy}:${activeStatusSummary}:${[...deckItems, ...visibleItems].map((item) => item.id).join("|")}`,
2886
+ syncKey: scrollSyncKey,
2541
2887
  children: deckItems.length > 0 || listItems.length > 0 ? /* @__PURE__ */ jsxs4("div", { className: "flex w-full min-w-0 flex-col gap-4", children: [
2542
2888
  deckItems.length > 0 ? /* @__PURE__ */ jsx5(
2543
2889
  WorkspaceAgentMessageCenterAttentionDeck,
@@ -2551,7 +2897,7 @@ function WorkspaceAgentMessageCenterPanelContent({
2551
2897
  onSubmitPrompt: (item, input) => void submitPrompt(item, input)
2552
2898
  }
2553
2899
  ) : null,
2554
- itemGroups.map((group) => /* @__PURE__ */ jsxs4(
2900
+ itemGroupStacks.map((group) => /* @__PURE__ */ jsxs4(
2555
2901
  "section",
2556
2902
  {
2557
2903
  className: "flex min-w-0 flex-col gap-2.5",
@@ -2559,56 +2905,28 @@ function WorkspaceAgentMessageCenterPanelContent({
2559
2905
  children: [
2560
2906
  /* @__PURE__ */ jsx5("div", { className: "flex min-w-0 items-center justify-between gap-3 px-0.5", children: /* @__PURE__ */ jsx5(MessageCenterGroupHeading, { group }) }),
2561
2907
  (() => {
2562
- const renderCard = (item, options = {}) => {
2563
- const highlighted = item.id === highlightedItemId;
2564
- const card = /* @__PURE__ */ jsx5(
2565
- MessageCenterCard,
2566
- {
2567
- cardRef: (node) => setItemNode(item.id, node),
2568
- highlighted,
2569
- item,
2570
- isSubmitting: submittingPromptKey === `${item.agentSessionId}:${item.pendingPrompt?.requestId}`,
2571
- onLinkAction,
2572
- onOpenChat,
2573
- onSubmitPrompt: (input) => void submitPrompt(item, input)
2574
- },
2575
- item.agentSessionId
2576
- );
2577
- if (options.stackedIndex === void 0) {
2578
- return card;
2579
- }
2580
- return /* @__PURE__ */ jsx5(
2581
- "div",
2582
- {
2583
- className: "min-w-0 motion-safe:animate-in motion-safe:fade-in-0 motion-safe:slide-in-from-top-1 motion-safe:duration-200 motion-safe:ease-[cubic-bezier(0.22,1,0.36,1)] motion-reduce:animate-none",
2584
- style: {
2585
- animationDelay: `${Math.min(options.stackedIndex * 24, 96)}ms`
2586
- },
2587
- children: card
2588
- },
2589
- item.agentSessionId
2590
- );
2591
- };
2592
- return partitionMessageCenterItemsByAgentUser(
2593
- group.items
2594
- ).map((stack) => {
2908
+ return group.stacks.map((stack) => {
2595
2909
  const firstItem = stack.items[0];
2596
2910
  if (!firstItem) {
2597
2911
  return null;
2598
2912
  }
2599
2913
  if (stack.items.length === 1) {
2600
- return renderCard(firstItem);
2914
+ return renderMessageCenterCard(firstItem);
2601
2915
  }
2602
- const stackId = group.id === stack.id ? stack.id : `${group.id}:${stack.id}`;
2916
+ const stackId = messageCenterStackRenderId(
2917
+ group.id,
2918
+ stack.id
2919
+ );
2603
2920
  return /* @__PURE__ */ jsx5(
2604
2921
  MessageCenterStack,
2605
2922
  {
2606
2923
  expanded: expandedStackIds.has(stackId),
2607
2924
  groupId: stackId,
2925
+ highlightedItemId,
2608
2926
  items: stack.items,
2609
- renderCard,
2610
- onCollapse: () => collapseStack(stackId),
2611
- onExpand: () => expandStack(stackId)
2927
+ renderCard: renderMessageCenterCard,
2928
+ onCollapse: collapseStack,
2929
+ onExpand: expandStack
2612
2930
  },
2613
2931
  stackId
2614
2932
  );
@@ -2642,6 +2960,42 @@ function WorkspaceAgentMessageCenterPanelContent({
2642
2960
  }
2643
2961
  var MessageCenterCard = WorkspaceAgentMessageCenterCard;
2644
2962
  var MessageCenterStack = WorkspaceAgentMessageCenterStack;
2963
+ var MessageCenterRenderedCard = memo2(function MessageCenterRenderedCard2({
2964
+ highlighted,
2965
+ isSubmitting,
2966
+ item,
2967
+ lazySummary,
2968
+ onLinkAction,
2969
+ onOpenChat,
2970
+ onSubmitPrompt,
2971
+ registerNode
2972
+ }) {
2973
+ const cardRef = useCallback2(
2974
+ (node) => {
2975
+ registerNode(item.id, node);
2976
+ },
2977
+ [item.id, registerNode]
2978
+ );
2979
+ const handleSubmitPrompt = useCallback2(
2980
+ (input) => {
2981
+ onSubmitPrompt(item, input);
2982
+ },
2983
+ [item, onSubmitPrompt]
2984
+ );
2985
+ return /* @__PURE__ */ jsx5(
2986
+ MessageCenterCard,
2987
+ {
2988
+ cardRef,
2989
+ highlighted,
2990
+ item,
2991
+ isSubmitting,
2992
+ lazySummary,
2993
+ onLinkAction,
2994
+ onOpenChat,
2995
+ onSubmitPrompt: handleSubmitPrompt
2996
+ }
2997
+ );
2998
+ });
2645
2999
  function MessageCenterGroupHeading({
2646
3000
  group
2647
3001
  }) {
@@ -2685,6 +3039,74 @@ function MessageCenterGroupHeading({
2685
3039
  group.items.length
2686
3040
  ] });
2687
3041
  }
3042
+
3043
+ // agent-message-center/workspaceAgentMessageCenterModelStability.ts
3044
+ function stabilizeWorkspaceAgentMessageCenterModel(previous, next) {
3045
+ if (!previous) {
3046
+ return next;
3047
+ }
3048
+ const previousItemsById = new Map(
3049
+ previous.items.map((item) => [item.id, item])
3050
+ );
3051
+ let itemsChanged = previous.items.length !== next.items.length;
3052
+ const items = next.items.map((nextItem, index) => {
3053
+ const previousItem = previousItemsById.get(nextItem.id);
3054
+ const stableItem = previousItem && messageCenterItemsEqual(previousItem, nextItem) ? previousItem : nextItem;
3055
+ if (stableItem !== previous.items[index]) {
3056
+ itemsChanged = true;
3057
+ }
3058
+ return stableItem;
3059
+ });
3060
+ const stableItems = itemsChanged ? items : previous.items;
3061
+ const stableCounts = messageCenterCountsEqual(previous.counts, next.counts) ? previous.counts : next.counts;
3062
+ if (previous.waitingCount === next.waitingCount && stableItems === previous.items && stableCounts === previous.counts) {
3063
+ return previous;
3064
+ }
3065
+ return {
3066
+ ...next,
3067
+ counts: stableCounts,
3068
+ items: stableItems
3069
+ };
3070
+ }
3071
+ function messageCenterItemsEqual(left, right) {
3072
+ return left.id === right.id && left.agentSessionId === right.agentSessionId && left.provider === right.provider && left.userId === right.userId && left.title === right.title && left.cwd === right.cwd && left.status === right.status && left.lastAgentMessageSummary === right.lastAgentMessageSummary && left.lastAgentMessageAtUnixMs === right.lastAgentMessageAtUnixMs && left.needsAttentionKind === right.needsAttentionKind && left.needsAttentionSummary === right.needsAttentionSummary && left.sortTimeUnixMs === right.sortTimeUnixMs && messageCenterIdentityEqual(left.identity, right.identity) && messageCenterDigestEqual(left.digest, right.digest) && messageCenterPromptEqual(left.pendingPrompt, right.pendingPrompt) && messageCenterTurnOutcomeEqual(
3073
+ left.latestTurnOutcome ?? null,
3074
+ right.latestTurnOutcome ?? null
3075
+ );
3076
+ }
3077
+ function messageCenterCountsEqual(left, right) {
3078
+ return left.all === right.all && left.working === right.working && left.waiting === right.waiting && left.completed === right.completed && left.failed === right.failed;
3079
+ }
3080
+ function messageCenterIdentityEqual(left, right) {
3081
+ if (left === right) {
3082
+ return true;
3083
+ }
3084
+ if (!left || !right) {
3085
+ return false;
3086
+ }
3087
+ return left.userName === right.userName && left.userAvatarUrl === right.userAvatarUrl && left.agentName === right.agentName && left.agentAvatarUrl === right.agentAvatarUrl;
3088
+ }
3089
+ function messageCenterDigestEqual(left, right) {
3090
+ return left.primary.kind === right.primary.kind && left.primary.summary === right.primary.summary && left.primary.occurredAtUnixMs === right.primary.occurredAtUnixMs;
3091
+ }
3092
+ function messageCenterTurnOutcomeEqual(left, right) {
3093
+ if (left === right) {
3094
+ return true;
3095
+ }
3096
+ if (!left || !right) {
3097
+ return false;
3098
+ }
3099
+ return left.notificationKey === right.notificationKey && left.status === right.status && left.turnId === right.turnId;
3100
+ }
3101
+ function messageCenterPromptEqual(left, right) {
3102
+ if (left === right) {
3103
+ return true;
3104
+ }
3105
+ if (!left || !right || left.kind !== right.kind) {
3106
+ return false;
3107
+ }
3108
+ return JSON.stringify(left) === JSON.stringify(right);
3109
+ }
2688
3110
  export {
2689
3111
  AgentInteractivePromptSurface,
2690
3112
  PLAN_IMPLEMENTATION_ACTION_IMPLEMENT,
@@ -2698,6 +3120,7 @@ export {
2698
3120
  isPromptRequestIdTitle,
2699
3121
  isWaitingMessageCenterItem,
2700
3122
  managedAgentRoundedIconUrl,
3123
+ stabilizeWorkspaceAgentMessageCenterModel,
2701
3124
  userAvatarPlaceholderUrl,
2702
3125
  workspaceAgentActivityStatusLabel
2703
3126
  };