@tutti-os/agent-gui 0.0.93 → 0.0.95

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 (164) hide show
  1. package/README.md +48 -32
  2. package/dist/AgentGUI-CwBLYtv-.d.ts +992 -0
  3. package/dist/agent-conversation/index.d.ts +5 -7
  4. package/dist/agent-conversation/index.js +13 -9
  5. package/dist/agent-conversation/index.js.map +1 -1
  6. package/dist/agent-env/index.d.ts +14 -38
  7. package/dist/agent-env/index.js +2 -57
  8. package/dist/agent-env/index.js.map +1 -1
  9. package/dist/agent-gui.d.ts +21 -0
  10. package/dist/agent-gui.js +39 -0
  11. package/dist/agent-message-center/index.d.ts +145 -122
  12. package/dist/agent-message-center/index.js +1473 -1398
  13. package/dist/agent-message-center/index.js.map +1 -1
  14. package/dist/{agentConversationVM-CfXN_TQ2.d.ts → agentConversationVM-C335TR6S.d.ts} +112 -7
  15. package/dist/agentFileMentionContracts-Czvz6YMI.d.ts +107 -0
  16. package/dist/{agentGuiNodeTypes-rGaDqxVR.d.ts → agentGuiNodeTypes-DppADPHW.d.ts} +102 -149
  17. package/dist/agentPlanPromptDispatch-C7cCMjve.d.ts +37 -0
  18. package/dist/agents.d.ts +13 -0
  19. package/dist/agents.js +13 -0
  20. package/dist/app/renderer/agentactivity.css +431 -75
  21. package/dist/app/renderer/assets/icons/agent-vinyl-player-chassis.png +0 -0
  22. package/dist/app/renderer/assets/icons/agent-vinyl-tonearm.png +0 -0
  23. package/dist/app/renderer/assets/icons/agent-vinyls/claude-vinyl.png +0 -0
  24. package/dist/app/renderer/assets/icons/agent-vinyls/codex-vinyl.png +0 -0
  25. package/dist/app/renderer/assets/icons/agent-vinyls/cursor-vinyl.png +0 -0
  26. package/dist/app/renderer/assets/icons/agent-vinyls/hermes-vinyl.png +0 -0
  27. package/dist/app/renderer/assets/icons/agent-vinyls/openclaw-vinyl.png +0 -0
  28. package/dist/app/renderer/assets/icons/agent-vinyls/opencode-vinyl.png +0 -0
  29. package/dist/app/renderer/assets/icons/agent-vinyls/tutti-vinyl.png +0 -0
  30. package/dist/app/renderer/assets/icons/open-link-lined.svg +4 -0
  31. package/dist/{chunk-7QHBFRG5.js → chunk-3R2D4E57.js} +3137 -3396
  32. package/dist/chunk-3R2D4E57.js.map +1 -0
  33. package/dist/chunk-4YG7YK7S.js +23 -0
  34. package/dist/chunk-4YG7YK7S.js.map +1 -0
  35. package/dist/chunk-5X7YDOC6.js +42 -0
  36. package/dist/chunk-5X7YDOC6.js.map +1 -0
  37. package/dist/{chunk-IBIMGLCD.js → chunk-7J4K6WKB.js} +1 -1
  38. package/dist/chunk-7J4K6WKB.js.map +1 -0
  39. package/dist/{chunk-KQE5KV2V.js → chunk-7PFDA2HQ.js} +505 -504
  40. package/dist/chunk-7PFDA2HQ.js.map +1 -0
  41. package/dist/{chunk-M2LWH54R.js → chunk-7RDD3EWP.js} +557 -569
  42. package/dist/chunk-7RDD3EWP.js.map +1 -0
  43. package/dist/{chunk-VWXFFSIM.js → chunk-AOS2VWU6.js} +1357 -1301
  44. package/dist/chunk-AOS2VWU6.js.map +1 -0
  45. package/dist/{chunk-3HARXLAZ.js → chunk-BFNJKTDV.js} +295 -255
  46. package/dist/chunk-BFNJKTDV.js.map +1 -0
  47. package/dist/{chunk-U7D7G3UU.js → chunk-BIHBXWK5.js} +2 -2
  48. package/dist/{chunk-XQUUELKF.js → chunk-C5FV4UGI.js} +2921 -2944
  49. package/dist/chunk-C5FV4UGI.js.map +1 -0
  50. package/dist/{chunk-HOSX5C5V.js → chunk-CRO2MV2Y.js} +36 -46
  51. package/dist/chunk-CRO2MV2Y.js.map +1 -0
  52. package/dist/chunk-FGLQZ6I4.js +9 -0
  53. package/dist/chunk-FGLQZ6I4.js.map +1 -0
  54. package/dist/chunk-H6IQ63DQ.js +14 -0
  55. package/dist/chunk-H6IQ63DQ.js.map +1 -0
  56. package/dist/{chunk-4SQNOOJ3.js → chunk-JX2SIXNL.js} +1293 -1702
  57. package/dist/chunk-JX2SIXNL.js.map +1 -0
  58. package/dist/chunk-KAL4XZMA.js +231 -0
  59. package/dist/chunk-KAL4XZMA.js.map +1 -0
  60. package/dist/chunk-KJQERFKX.js +259 -0
  61. package/dist/chunk-KJQERFKX.js.map +1 -0
  62. package/dist/chunk-LQVXBT65.js +491 -0
  63. package/dist/chunk-LQVXBT65.js.map +1 -0
  64. package/dist/{chunk-AOVPGJBC.js → chunk-NITOD7WF.js} +2 -2
  65. package/dist/{chunk-7LMJXF4R.js → chunk-NJAZ7LQM.js} +20 -16
  66. package/dist/chunk-NJAZ7LQM.js.map +1 -0
  67. package/dist/chunk-NX3CZJXW.js +25 -0
  68. package/dist/chunk-NX3CZJXW.js.map +1 -0
  69. package/dist/chunk-O6W72SEP.js +93 -0
  70. package/dist/chunk-O6W72SEP.js.map +1 -0
  71. package/dist/{chunk-PSLAWU25.js → chunk-R2EWECUP.js} +7 -1
  72. package/dist/chunk-R2EWECUP.js.map +1 -0
  73. package/dist/chunk-RY6GIO3K.js +31700 -0
  74. package/dist/chunk-RY6GIO3K.js.map +1 -0
  75. package/dist/{chunk-XDV4ZRVK.js → chunk-UGVI47X6.js} +98 -37
  76. package/dist/chunk-UGVI47X6.js.map +1 -0
  77. package/dist/{chunk-XW4CVBUH.js → chunk-UQJPV6HP.js} +18 -11
  78. package/dist/chunk-UQJPV6HP.js.map +1 -0
  79. package/dist/{chunk-GAPTLVII.js → chunk-VF22EG3F.js} +1 -1
  80. package/dist/{chunk-GAPTLVII.js.map → chunk-VF22EG3F.js.map} +1 -1
  81. package/dist/{chunk-45FF4DQU.js → chunk-WEDMAVX2.js} +22 -24
  82. package/dist/chunk-WEDMAVX2.js.map +1 -0
  83. package/dist/{chunk-SXDLSEHO.js → chunk-XMO45GKA.js} +531 -401
  84. package/dist/chunk-XMO45GKA.js.map +1 -0
  85. package/dist/{chunk-UNO7CEAF.js → chunk-YE25HN6T.js} +6 -9
  86. package/dist/chunk-YE25HN6T.js.map +1 -0
  87. package/dist/context-mention-palette/index.d.ts +3 -2
  88. package/dist/context-mention-palette/index.js +19 -14
  89. package/dist/custom-mention.d.ts +44 -0
  90. package/dist/custom-mention.js +17 -0
  91. package/dist/custom-mention.js.map +1 -0
  92. package/dist/dock-icons.d.ts +6 -0
  93. package/dist/dock-icons.js +11 -0
  94. package/dist/dock-icons.js.map +1 -0
  95. package/dist/i18n/index.d.ts +852 -837
  96. package/dist/i18n/index.js +2 -2
  97. package/dist/index.d.ts +52 -1061
  98. package/dist/index.js +72 -35254
  99. package/dist/index.js.map +1 -1
  100. package/dist/mention-search.d.ts +226 -0
  101. package/dist/mention-search.js +29 -0
  102. package/dist/mention-search.js.map +1 -0
  103. package/dist/open-link-lined-JWEKUKME.svg +4 -0
  104. package/dist/provider-icons.d.ts +6 -0
  105. package/dist/provider-icons.js +12 -0
  106. package/dist/provider-icons.js.map +1 -0
  107. package/dist/provider-identity.d.ts +9 -0
  108. package/dist/provider-identity.js +21 -0
  109. package/dist/provider-identity.js.map +1 -0
  110. package/dist/runtime-BBNdWgDU.d.ts +10 -0
  111. package/dist/{types-PLFZ8SBX.d.ts → types-DX2bxgB8.d.ts} +28 -83
  112. package/dist/workbench/contribution.d.ts +32 -40
  113. package/dist/workbench/contribution.js +10 -6
  114. package/dist/workbench/index.d.ts +6 -2
  115. package/dist/workbench/index.js +24 -20
  116. package/dist/workbench/launch.d.ts +2 -5
  117. package/dist/workbench/launch.js +4 -3
  118. package/dist/workbench/providerCatalog.js +2 -1
  119. package/dist/workbench/sessionTitle.d.ts +4 -3
  120. package/dist/workbench/sessionTitle.js +4 -3
  121. package/dist/workbench/state.d.ts +1 -1
  122. package/dist/workbench/state.js +3 -2
  123. package/dist/workbench/types.d.ts +0 -3
  124. package/dist/workbench/types.js +1 -1
  125. package/dist/workspace-agent-generated-files.d.ts +20 -2
  126. package/dist/workspace-agent-generated-files.js +7 -6
  127. package/dist/workspaceAgentActivityListTypes-C7gPWYiA.d.ts +71 -0
  128. package/package.json +65 -28
  129. package/dist/AgentMentionSearchController-DD_WOred.d.ts +0 -241
  130. package/dist/AgentMessageMarkdown-DeYPURtF.d.ts +0 -7
  131. package/dist/chunk-3HARXLAZ.js.map +0 -1
  132. package/dist/chunk-45FF4DQU.js.map +0 -1
  133. package/dist/chunk-4HP6V2YA.js +0 -207
  134. package/dist/chunk-4HP6V2YA.js.map +0 -1
  135. package/dist/chunk-4SQNOOJ3.js.map +0 -1
  136. package/dist/chunk-7LMJXF4R.js.map +0 -1
  137. package/dist/chunk-7QHBFRG5.js.map +0 -1
  138. package/dist/chunk-HOSX5C5V.js.map +0 -1
  139. package/dist/chunk-IBIMGLCD.js.map +0 -1
  140. package/dist/chunk-KQE5KV2V.js.map +0 -1
  141. package/dist/chunk-LR4FA5X6.js +0 -368
  142. package/dist/chunk-LR4FA5X6.js.map +0 -1
  143. package/dist/chunk-M2LWH54R.js.map +0 -1
  144. package/dist/chunk-MKHDRIGN.js +0 -71
  145. package/dist/chunk-MKHDRIGN.js.map +0 -1
  146. package/dist/chunk-PSLAWU25.js.map +0 -1
  147. package/dist/chunk-SXDLSEHO.js.map +0 -1
  148. package/dist/chunk-UNO7CEAF.js.map +0 -1
  149. package/dist/chunk-VAKFNNKT.js +0 -410
  150. package/dist/chunk-VAKFNNKT.js.map +0 -1
  151. package/dist/chunk-VWXFFSIM.js.map +0 -1
  152. package/dist/chunk-XDV4ZRVK.js.map +0 -1
  153. package/dist/chunk-XQUUELKF.js.map +0 -1
  154. package/dist/chunk-XW4CVBUH.js.map +0 -1
  155. package/dist/plan-decision-ops.d.ts +0 -70
  156. package/dist/plan-decision-ops.js +0 -19
  157. package/dist/queued-prompt-runtime.d.ts +0 -115
  158. package/dist/queued-prompt-runtime.js +0 -9
  159. package/dist/workspaceAgentActivityListViewModel-TXH1VXrk.d.ts +0 -339
  160. package/dist/workspaceLinkActions-DS9LWqzI.d.ts +0 -74
  161. /package/dist/{plan-decision-ops.js.map → agent-gui.js.map} +0 -0
  162. /package/dist/{queued-prompt-runtime.js.map → agents.js.map} +0 -0
  163. /package/dist/{chunk-U7D7G3UU.js.map → chunk-BIHBXWK5.js.map} +0 -0
  164. /package/dist/{chunk-AOVPGJBC.js.map → chunk-NITOD7WF.js.map} +0 -0
@@ -1,21 +1,27 @@
1
1
  import {
2
2
  formatAgentGuiConversationPlainTitle
3
- } from "../chunk-UNO7CEAF.js";
3
+ } from "../chunk-YE25HN6T.js";
4
4
  import {
5
5
  AgentInteractivePromptSurface,
6
- approvalOptionDisplayLabel,
7
- getPromptToolDetails,
8
- isPromptRequestIdTitle
9
- } from "../chunk-SXDLSEHO.js";
10
- import {
11
6
  PLAN_IMPLEMENTATION_ACTION_IMPLEMENT,
12
7
  PLAN_IMPLEMENTATION_PROMPT,
13
- latestPlanTurnId,
14
- planImplementationPromptFromPlanTurn
15
- } from "../chunk-MKHDRIGN.js";
8
+ approvalOptionDisplayLabel,
9
+ dispatchAgentPlanPromptAction,
10
+ getPromptToolDetails,
11
+ isPromptRequestIdTitle,
12
+ useEngineSelector
13
+ } from "../chunk-XMO45GKA.js";
16
14
  import {
17
15
  formatAgentSessionMentionText
18
- } from "../chunk-HOSX5C5V.js";
16
+ } from "../chunk-CRO2MV2Y.js";
17
+ import {
18
+ userAvatarPlaceholderUrl,
19
+ workspaceAgentActivityStatusLabel
20
+ } from "../chunk-NITOD7WF.js";
21
+ import {
22
+ resolveWorkspaceAgentSessionSortTimeUnixMs
23
+ } from "../chunk-7J4K6WKB.js";
24
+ import "../chunk-GCBDIQDX.js";
19
25
  import {
20
26
  AgentMessageMarkdown,
21
27
  CustomScrollArea,
@@ -25,48 +31,42 @@ import {
25
31
  extractExitPlanModeOptions,
26
32
  isExitPlanSwitchModeInput,
27
33
  normalizeAskUserQuestions
28
- } from "../chunk-XQUUELKF.js";
29
- import {
30
- userAvatarPlaceholderUrl,
31
- workspaceAgentActivityStatusLabel
32
- } from "../chunk-AOVPGJBC.js";
33
- import {
34
- resolveWorkspaceAgentSessionSortTimeUnixMs
35
- } from "../chunk-IBIMGLCD.js";
34
+ } from "../chunk-C5FV4UGI.js";
36
35
  import {
37
36
  managedAgentRoundedIconUrl
38
- } from "../chunk-LR4FA5X6.js";
37
+ } from "../chunk-KAL4XZMA.js";
38
+ import "../chunk-H6IQ63DQ.js";
39
39
  import {
40
40
  workspaceAgentProviderLabel
41
- } from "../chunk-4HP6V2YA.js";
41
+ } from "../chunk-NX3CZJXW.js";
42
42
  import {
43
43
  AgentGuiI18nProvider,
44
44
  getActiveUiLanguage,
45
45
  useTranslation
46
- } from "../chunk-U7D7G3UU.js";
46
+ } from "../chunk-BIHBXWK5.js";
47
+ import "../chunk-AOS2VWU6.js";
47
48
  import "../chunk-PJP5BUU6.js";
48
- import "../chunk-XDV4ZRVK.js";
49
- import "../chunk-VWXFFSIM.js";
50
- import "../chunk-GCBDIQDX.js";
49
+ import "../chunk-5X7YDOC6.js";
50
+ import "../chunk-KJQERFKX.js";
51
+ import "../chunk-UGVI47X6.js";
51
52
 
52
53
  // agent-message-center/WorkspaceAgentMessageCenterPanel.tsx
53
54
  import {
54
55
  memo as memo2,
55
- useCallback as useCallback2,
56
- useEffect as useEffect3,
56
+ useCallback as useCallback3,
57
+ useEffect as useEffect4,
57
58
  useLayoutEffect as useLayoutEffect2,
58
59
  useMemo as useMemo2,
59
60
  useRef as useRef3,
60
- useState as useState3
61
+ useState as useState4
61
62
  } from "react";
62
63
  import {
63
- Button as Button3,
64
- cn as cn5,
64
+ Button as Button4,
65
+ cn as cn7,
65
66
  Drawer,
66
67
  DrawerContent,
67
68
  DrawerDescription,
68
69
  DrawerTitle,
69
- StatusDot as StatusDot2,
70
70
  TooltipProvider
71
71
  } from "@tutti-os/ui-system";
72
72
 
@@ -109,12 +109,6 @@ var AgentVerticalScrollArea = forwardRef(function AgentVerticalScrollArea2({
109
109
  );
110
110
  });
111
111
 
112
- // agent-message-center/workspaceAgentMessageCenterModel.ts
113
- import {
114
- selectNeedsAttentionItems,
115
- selectSessionDisplayStatuses
116
- } from "@tutti-os/agent-activity-core";
117
-
118
112
  // agent-message-center/workspaceAgentMessageCenterDigest.ts
119
113
  var digestAgentMessageSummaryByMessage = /* @__PURE__ */ new WeakMap();
120
114
  function buildWorkspaceAgentMessageCenterDigest(input) {
@@ -476,7 +470,7 @@ function positiveNumber(value) {
476
470
  return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : null;
477
471
  }
478
472
 
479
- // agent-message-center/workspaceAgentMessageCenterModel.ts
473
+ // agent-message-center/workspaceAgentMessageCenterCollection.ts
480
474
  var EMPTY_COUNTS = {
481
475
  all: 0,
482
476
  working: 0,
@@ -484,72 +478,108 @@ var EMPTY_COUNTS = {
484
478
  completed: 0,
485
479
  failed: 0
486
480
  };
487
- function buildWorkspaceAgentMessageCenterModel(snapshot, options = {}) {
488
- const needsAttentionBySessionId = latestNeedsAttentionBySessionId(
489
- selectNeedsAttentionItems(snapshot)
490
- );
491
- const displayStatuses = selectSessionDisplayStatuses(snapshot);
492
- const items = snapshot.sessions.filter((session) => session.visible !== false).map((session) => {
493
- const messages = resolveSessionMessages(snapshot, session);
494
- const messageAnalysis = analyzeMessageCenterSessionMessages(
495
- session.agentSessionId,
496
- messages
497
- );
498
- const needsAttention = needsAttentionBySessionId.get(session.agentSessionId) ?? null;
499
- const status = displayStatuses.get(session.agentSessionId) ?? "idle";
500
- const lastAgentMessage = messageAnalysis.latestAgentMessage;
501
- const title = resolveSessionTitle(
502
- session,
503
- messageAnalysis.latestUserMessageSummary,
504
- messageAnalysis.firstUserMessageSummary
505
- );
506
- const pendingPrompt = messageAnalysis.pendingPrompt ?? codexPlanImplementationPrompt(session, status, messages) ?? fallbackPromptFromNeedsAttention(
507
- needsAttention,
508
- options.promptFallbackLabels
509
- );
510
- const digest = buildWorkspaceAgentMessageCenterDigest({
511
- fallbackTitle: resolveDigestFallbackTitle(session),
512
- latestAgentMessage: messageAnalysis.latestDigestAgentMessage,
513
- needsAttention,
514
- pendingPrompt,
515
- status
516
- });
517
- const sortTimeUnixMs = resolveWorkspaceAgentSessionSortTimeUnixMs(
518
- session,
519
- {
520
- messages
481
+ function buildWorkspaceAgentMessageCenterModelFromItems(sourceItems, itemCutoffUnixMs) {
482
+ const items = sourceItems.filter((item) => isWithinItemCutoff(item, itemCutoffUnixMs)).sort(compareItems);
483
+ return {
484
+ waitingCount: items.filter(isWaitingMessageCenterItem).length,
485
+ items,
486
+ counts: countItems(items)
487
+ };
488
+ }
489
+ function isWaitingMessageCenterItem(item) {
490
+ return item.pendingPrompt !== null || item.needsAttentionKind !== null;
491
+ }
492
+ function isInteractiveMessageCenterItem(item) {
493
+ return item.pendingPrompt !== null;
494
+ }
495
+ function selectMessageCenterAttentionDeckItems(items) {
496
+ return items.filter(isInteractiveMessageCenterItem);
497
+ }
498
+ function isCompletedMessageCenterItem(item) {
499
+ return item.status === "completed" || item.status === "canceled" || item.status === "idle";
500
+ }
501
+ function isWithinItemCutoff(item, cutoffUnixMs) {
502
+ if (!Number.isFinite(cutoffUnixMs)) return true;
503
+ if (isWaitingMessageCenterItem(item)) return true;
504
+ const timestamp = item.sortTimeUnixMs || item.lastAgentMessageAtUnixMs || 0;
505
+ return timestamp >= Number(cutoffUnixMs);
506
+ }
507
+ function countItems(items) {
508
+ return items.reduce(
509
+ (counts, item) => {
510
+ counts.all += 1;
511
+ if (isWaitingMessageCenterItem(item)) {
512
+ counts.waiting += 1;
513
+ } else if (isCompletedMessageCenterItem(item)) {
514
+ counts.completed += 1;
515
+ } else if (item.status === "working") {
516
+ counts.working += 1;
517
+ } else if (item.status === "failed") {
518
+ counts.failed += 1;
521
519
  }
522
- );
523
- return {
524
- id: `message-center-${session.agentSessionId}`,
525
- agentSessionId: session.agentSessionId,
526
- agentTargetId: session.agentTargetId?.trim() || null,
527
- provider: session.provider,
528
- userId: session.userId?.trim() || null,
529
- title,
530
- ...isImportedMessageCenterSession(session) ? { imported: true } : {},
531
- identity: resolveMessageCenterIdentity(
532
- session.agentSessionId,
533
- options.identityBySessionId
534
- ),
535
- cwd: session.cwd,
536
- status,
537
- digest,
538
- lastAgentMessageSummary: lastAgentMessage?.summary ?? needsAttention?.summary ?? title,
539
- lastAgentMessageAtUnixMs: lastAgentMessage?.occurredAtUnixMs ?? null,
540
- pendingPrompt,
541
- needsAttentionKind: needsAttention?.kind ?? null,
542
- needsAttentionSummary: needsAttention?.summary ?? null,
543
- latestTurnOutcome: messageAnalysis.latestTurnOutcome,
544
- sortTimeUnixMs
545
- };
546
- }).filter(
547
- (item) => isWithinMessageCenterItemCutoff(item, options.itemCutoffUnixMs)
520
+ return counts;
521
+ },
522
+ { ...EMPTY_COUNTS }
523
+ );
524
+ }
525
+ function compareItems(left, right) {
526
+ const leftWaiting = isWaitingMessageCenterItem(left);
527
+ const rightWaiting = isWaitingMessageCenterItem(right);
528
+ if (leftWaiting !== rightWaiting) return leftWaiting ? -1 : 1;
529
+ return right.sortTimeUnixMs - left.sortTimeUnixMs || left.agentSessionId.localeCompare(right.agentSessionId);
530
+ }
531
+
532
+ // agent-message-center/workspaceAgentMessageCenterModel.ts
533
+ function buildWorkspaceAgentMessageCenterItem({
534
+ session,
535
+ messages,
536
+ status,
537
+ needsAttention,
538
+ pendingPrompt,
539
+ latestTurnOutcome,
540
+ options = {}
541
+ }) {
542
+ const messageAnalysis = analyzeMessageCenterSessionMessages(
543
+ session.agentSessionId,
544
+ messages
545
+ );
546
+ const lastAgentMessage = messageAnalysis.latestAgentMessage;
547
+ const title = resolveSessionTitle(
548
+ session,
549
+ messageAnalysis.latestUserMessageSummary,
550
+ messageAnalysis.firstUserMessageSummary
548
551
  );
552
+ const digest = buildWorkspaceAgentMessageCenterDigest({
553
+ fallbackTitle: resolveDigestFallbackTitle(session),
554
+ latestAgentMessage: messageAnalysis.latestDigestAgentMessage,
555
+ needsAttention,
556
+ pendingPrompt,
557
+ status
558
+ });
549
559
  return {
550
- waitingCount: items.filter(isWaitingMessageCenterItem).length,
551
- items: items.sort(compareMessageCenterItems),
552
- counts: countMessageCenterItems(items)
560
+ id: `message-center-${session.agentSessionId}`,
561
+ agentSessionId: session.agentSessionId,
562
+ agentTargetId: session.agentTargetId?.trim() || null,
563
+ provider: session.provider,
564
+ userId: session.userId?.trim() || null,
565
+ title,
566
+ ...isImportedMessageCenterSession(session) ? { imported: true } : {},
567
+ identity: resolveMessageCenterIdentity(
568
+ session.agentSessionId,
569
+ options.identityBySessionId
570
+ ),
571
+ cwd: session.cwd,
572
+ status,
573
+ digest,
574
+ lastAgentMessageSummary: lastAgentMessage?.summary ?? needsAttention?.summary ?? title,
575
+ lastAgentMessageAtUnixMs: lastAgentMessage?.occurredAtUnixMs ?? null,
576
+ pendingPrompt,
577
+ needsAttentionKind: needsAttention?.kind ?? null,
578
+ needsAttentionSummary: needsAttention?.summary ?? null,
579
+ latestTurnOutcome,
580
+ sortTimeUnixMs: resolveWorkspaceAgentSessionSortTimeUnixMs(session, {
581
+ messages
582
+ })
553
583
  };
554
584
  }
555
585
  function resolveMessageCenterIdentity(agentSessionId, identityBySessionId) {
@@ -572,48 +602,7 @@ function resolveMessageCenterIdentity(agentSessionId, identityBySessionId) {
572
602
  };
573
603
  }
574
604
  function isImportedMessageCenterSession(session) {
575
- return session.runtimeContext?.imported === true;
576
- }
577
- function isWaitingMessageCenterItem(item) {
578
- return item.pendingPrompt !== null || item.needsAttentionKind !== null;
579
- }
580
- function isInteractiveMessageCenterItem(item) {
581
- return item.pendingPrompt !== null;
582
- }
583
- function isWithinMessageCenterItemCutoff(item, cutoffUnixMs) {
584
- if (!Number.isFinite(cutoffUnixMs)) {
585
- return true;
586
- }
587
- if (isWaitingMessageCenterItem(item)) {
588
- return true;
589
- }
590
- const timestamp = item.sortTimeUnixMs || item.lastAgentMessageAtUnixMs || 0;
591
- return timestamp >= Number(cutoffUnixMs);
592
- }
593
- function selectMessageCenterAttentionDeckItems(items) {
594
- return items.filter(isInteractiveMessageCenterItem);
595
- }
596
- function isCompletedMessageCenterItem(item) {
597
- return item.status === "completed" || item.status === "canceled" || item.status === "idle";
598
- }
599
- function latestNeedsAttentionBySessionId(items) {
600
- const bySessionId = /* @__PURE__ */ new Map();
601
- for (const item of items) {
602
- const previous = bySessionId.get(item.agentSessionId);
603
- if (!previous || item.occurredAtUnixMs > previous.occurredAtUnixMs) {
604
- bySessionId.set(item.agentSessionId, item);
605
- }
606
- }
607
- return bySessionId;
608
- }
609
- function resolveSessionMessages(snapshot, session) {
610
- for (const sessionId of [session.agentSessionId, session.providerSessionId]) {
611
- const normalized = sessionId?.trim() ?? "";
612
- if (normalized && snapshot.sessionMessagesById[normalized]) {
613
- return snapshot.sessionMessagesById[normalized];
614
- }
615
- }
616
- return [];
605
+ return "imported" in session && session.imported === true;
617
606
  }
618
607
  function resolveSessionTitle(session, latestUserMessageSummary, firstUserMessageSummary) {
619
608
  const latest = latestUserMessageSummary.trim();
@@ -629,29 +618,7 @@ function resolveSessionTitle(session, latestUserMessageSummary, firstUserMessage
629
618
  function resolveDigestFallbackTitle(session) {
630
619
  return session.title.trim() || session.provider || session.agentSessionId;
631
620
  }
632
- var messageAnalysisByMessages = /* @__PURE__ */ new WeakMap();
633
- var codexPlanImplementationPromptByMessages = /* @__PURE__ */ new WeakMap();
634
621
  function analyzeMessageCenterSessionMessages(agentSessionId, messages) {
635
- let bySessionId = messageAnalysisByMessages.get(messages);
636
- if (!bySessionId) {
637
- bySessionId = /* @__PURE__ */ new Map();
638
- messageAnalysisByMessages.set(messages, bySessionId);
639
- }
640
- const cached = bySessionId.get(agentSessionId);
641
- if (cached && isMessageArrayCacheEntryCurrent(cached, messages)) {
642
- return cached.result;
643
- }
644
- const result = analyzeMessageCenterSessionMessagesUncached(
645
- agentSessionId,
646
- messages
647
- );
648
- bySessionId.set(agentSessionId, {
649
- messages: messageCenterMessageCacheKeys(messages),
650
- result
651
- });
652
- return result;
653
- }
654
- function analyzeMessageCenterSessionMessagesUncached(agentSessionId, messages) {
655
622
  let firstUserMessageSummary = "";
656
623
  let latestUserMessageSummary = "";
657
624
  let latestUserMessageAtUnixMs = Number.NEGATIVE_INFINITY;
@@ -810,67 +777,6 @@ function isExitPlanMessage(message, input = recordValue2(
810
777
  )) {
811
778
  return includesAny2(normalizedMetadataValues(message), ["exitplanmode"]) || isExitPlanSwitchModeInput(input);
812
779
  }
813
- function codexPlanImplementationPrompt(session, status, messages) {
814
- const cached = codexPlanImplementationPromptByMessages.get(messages);
815
- if (cached && cached.provider === session.provider && cached.status === status && isMessageArrayCacheEntryCurrent(cached, messages)) {
816
- return cached.result;
817
- }
818
- const result = codexPlanImplementationPromptUncached(
819
- session,
820
- status,
821
- messages
822
- );
823
- codexPlanImplementationPromptByMessages.set(messages, {
824
- messages: messageCenterMessageCacheKeys(messages),
825
- provider: session.provider,
826
- result,
827
- status
828
- });
829
- return result;
830
- }
831
- function codexPlanImplementationPromptUncached(session, status, messages) {
832
- if (session.provider.trim().toLowerCase() !== "codex") {
833
- return null;
834
- }
835
- if (status !== "completed" && status !== "idle") {
836
- return null;
837
- }
838
- const planTurnId = latestPlanTurnId(messages);
839
- if (!planTurnId) {
840
- return null;
841
- }
842
- const planMessage = messages.find(
843
- (item) => item.turnId?.trim() === planTurnId && recordValue2(item.payload).messageKind === "plan"
844
- );
845
- const title = planMessage ? messageSummary(planMessage) : "";
846
- return planImplementationPromptFromPlanTurn(planTurnId, title);
847
- }
848
- function isMessageArrayCacheEntryCurrent(entry, messages) {
849
- if (entry.messages.length !== messages.length) {
850
- return false;
851
- }
852
- return entry.messages.every(
853
- (key, index) => messageCenterMessageCacheKeyMatches(key, messages[index])
854
- );
855
- }
856
- function messageCenterMessageCacheKeys(messages) {
857
- return messages.map((message) => ({
858
- completedAtUnixMs: message.completedAtUnixMs,
859
- kind: message.kind,
860
- message,
861
- messageId: message.messageId,
862
- occurredAtUnixMs: message.occurredAtUnixMs,
863
- payload: message.payload,
864
- role: message.role,
865
- startedAtUnixMs: message.startedAtUnixMs,
866
- status: message.status,
867
- turnId: message.turnId,
868
- version: message.version
869
- }));
870
- }
871
- function messageCenterMessageCacheKeyMatches(key, message) {
872
- return message !== void 0 && key.message === message && key.messageId === message.messageId && key.version === message.version && key.turnId === message.turnId && key.role === message.role && key.kind === message.kind && key.status === message.status && key.payload === message.payload && key.occurredAtUnixMs === message.occurredAtUnixMs && key.startedAtUnixMs === message.startedAtUnixMs && key.completedAtUnixMs === message.completedAtUnixMs;
873
- }
874
780
  function turnOutcomeFromMessage(agentSessionId, message) {
875
781
  const status = outcomeStatusFromMessage(message);
876
782
  if (!status) {
@@ -904,65 +810,6 @@ function outcomeStatusFromMessage(message) {
904
810
  return null;
905
811
  }
906
812
  }
907
- function fallbackPromptFromNeedsAttention(item, labels) {
908
- if (!item || item.kind === "permission" || !labels) {
909
- return null;
910
- }
911
- return {
912
- kind: "ask-user",
913
- requestId: requestIdFromNeedsAttentionItem(item),
914
- title: item.summary || item.title || labels.title,
915
- questions: [
916
- {
917
- id: "response",
918
- header: item.kind === "constraint" ? labels.constraintHeader : labels.inputHeader,
919
- question: item.summary || item.title || labels.question,
920
- options: [],
921
- multiSelect: false,
922
- answer: null
923
- }
924
- ]
925
- };
926
- }
927
- function requestIdFromNeedsAttentionItem(item) {
928
- const [, messageId] = item.id.split(":", 2);
929
- return messageId?.trim() || item.id;
930
- }
931
- function countMessageCenterItems(items) {
932
- return items.reduce(
933
- (counts, item) => {
934
- counts.all += 1;
935
- if (isWaitingMessageCenterItem(item)) {
936
- counts.waiting += 1;
937
- return counts;
938
- }
939
- if (isCompletedMessageCenterItem(item)) {
940
- counts.completed += 1;
941
- return counts;
942
- }
943
- switch (item.status) {
944
- case "working":
945
- counts.working += 1;
946
- break;
947
- case "failed":
948
- counts.failed += 1;
949
- break;
950
- default:
951
- break;
952
- }
953
- return counts;
954
- },
955
- { ...EMPTY_COUNTS }
956
- );
957
- }
958
- function compareMessageCenterItems(left, right) {
959
- const leftWaiting = isWaitingMessageCenterItem(left);
960
- const rightWaiting = isWaitingMessageCenterItem(right);
961
- if (leftWaiting !== rightWaiting) {
962
- return leftWaiting ? -1 : 1;
963
- }
964
- return right.sortTimeUnixMs - left.sortTimeUnixMs || left.agentSessionId.localeCompare(right.agentSessionId);
965
- }
966
813
  function isAgentMessageRole2(role) {
967
814
  const normalized = role.trim().toLowerCase();
968
815
  return normalized === "assistant" || normalized === "agent";
@@ -1063,473 +910,333 @@ function positiveNumber2(value) {
1063
910
 
1064
911
  // agent-message-center/WorkspaceAgentMessageCenterAttentionDeck.tsx
1065
912
  import {
1066
- useEffect as useEffect2,
913
+ useEffect as useEffect3,
1067
914
  useMemo,
1068
915
  useRef as useRef2,
1069
- useState as useState2
916
+ useState as useState3
1070
917
  } from "react";
1071
- import { cn as cn3 } from "@tutti-os/ui-system";
918
+ import { cn as cn4 } from "@tutti-os/ui-system";
1072
919
 
1073
920
  // agent-message-center/WorkspaceAgentMessageCenterCard.tsx
1074
921
  import {
1075
- cloneElement,
1076
922
  memo,
1077
- useCallback,
1078
- useEffect,
923
+ useCallback as useCallback2,
924
+ useEffect as useEffect2,
1079
925
  useLayoutEffect,
1080
926
  useRef,
1081
- useState
927
+ useState as useState2
1082
928
  } from "react";
929
+ import { ChevronDown, ChevronUp } from "lucide-react";
930
+ import { Button as Button2, cn as cn3, StatusDot } from "@tutti-os/ui-system";
931
+
932
+ // agent-message-center/WorkspaceAgentMessageCenterIdentity.tsx
1083
933
  import {
1084
- AppWindow,
1085
- ChevronDown,
1086
- ChevronUp,
1087
- ExternalLink,
1088
- Info
1089
- } from "lucide-react";
934
+ cloneElement,
935
+ useCallback,
936
+ useEffect,
937
+ useState
938
+ } from "react";
939
+ import { ExternalLink, Info } from "lucide-react";
1090
940
  import {
1091
941
  Button,
1092
942
  cn as cn2,
1093
- StatusDot,
1094
943
  Tooltip,
1095
944
  TooltipContent,
1096
945
  TooltipTrigger
1097
946
  } from "@tutti-os/ui-system";
1098
- import {
1099
- isRichTextMentionHref,
1100
- parseRichTextMentionHref
1101
- } from "@tutti-os/ui-rich-text/core";
1102
947
  import { jsx as jsx2, jsxs } from "react/jsx-runtime";
1103
- function stopMessageCenterTextPointerPropagation(event) {
1104
- event.stopPropagation();
1105
- }
1106
- var WorkspaceAgentMessageCenterCard = memo(
1107
- function WorkspaceAgentMessageCenterCard2({
1108
- cardRef,
1109
- actionsAccessory,
1110
- footerAccessory,
1111
- headerAccessory,
1112
- highlighted = false,
1113
- interactive = true,
1114
- item,
1115
- isSubmitting,
1116
- lazySummary = false,
1117
- summaryAccessory,
1118
- onLinkAction,
1119
- onOpenChat,
1120
- onSubmitPrompt
1121
- }) {
1122
- "use memo";
1123
- const { t } = useTranslation();
1124
- const prompt = item.pendingPrompt;
1125
- const displayTitle = formatAgentGuiConversationPlainTitle(item, {
1126
- language: getActiveUiLanguage()
1127
- });
1128
- const summary = messageCenterVisibleSummary(item);
1129
- const displayStatus = statusClass(item);
1130
- const statusTone = messageCenterStatusTone(item);
1131
- const statusLabel = workspaceAgentActivityStatusLabel(displayStatus, t);
1132
- return /* @__PURE__ */ jsxs(
1133
- "article",
948
+ function MessageCenterOpenChatButton({
949
+ actionsAccessory,
950
+ alwaysVisible = false,
951
+ item,
952
+ label,
953
+ onOpenChat,
954
+ provider
955
+ }) {
956
+ "use memo";
957
+ return /* @__PURE__ */ jsxs("div", { className: "workspace-agent-message-center__footer flex min-w-0 items-center justify-between gap-2", children: [
958
+ /* @__PURE__ */ jsx2(
959
+ MessageCenterIdentityLabel,
1134
960
  {
1135
- ref: cardRef,
1136
- className: cn2(
1137
- "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]",
1138
- isWaitingMessageCenterItem(item) && "agent-gui-edge-glow border-[var(--tutti-purple-border)] bg-[var(--tutti-purple-bg)]",
1139
- highlighted && "outline-2 outline-[var(--accent)]"
1140
- ),
1141
- "data-highlighted": highlighted ? "true" : void 0,
1142
- "data-message-center-digest-kind": item.digest.primary.kind,
1143
- "data-message-center-item-id": item.id,
1144
- "data-waiting": isWaitingMessageCenterItem(item) ? "true" : void 0,
1145
- "data-status": displayStatus,
1146
- tabIndex: highlighted ? -1 : void 0,
1147
- children: [
1148
- /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 items-center justify-between gap-2.5", children: [
1149
- /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 items-center gap-1.5", children: [
1150
- /* @__PURE__ */ jsx2(
1151
- LazyMessageCenterTooltip,
1152
- {
1153
- content: displayTitle,
1154
- side: "top",
1155
- align: "start",
1156
- className: "max-w-[min(360px,calc(100vw-32px))] whitespace-normal text-left [overflow-wrap:anywhere]",
1157
- children: /* @__PURE__ */ jsx2(
1158
- "h3",
1159
- {
1160
- className: "workspace-agent-message-center__copy-text min-w-0 truncate text-[13px] font-bold leading-5 text-[var(--text-secondary)]",
1161
- onPointerDown: stopMessageCenterTextPointerPropagation,
1162
- children: displayTitle
1163
- }
1164
- )
1165
- }
1166
- ),
1167
- item.cwd ? /* @__PURE__ */ jsx2(ProjectPathInfo, { path: item.cwd }) : null
1168
- ] }),
1169
- /* @__PURE__ */ jsxs("span", { className: "flex shrink-0 items-center gap-2", children: [
1170
- headerAccessory,
1171
- /* @__PURE__ */ jsxs(
1172
- "span",
1173
- {
1174
- className: cn2(
1175
- "workspace-agent-message-center__status inline-flex shrink-0 items-center gap-1.5 text-[11px] font-semibold leading-4",
1176
- messageCenterStatusToneClass(statusTone)
1177
- ),
1178
- "data-status": displayStatus,
1179
- title: statusLabel,
1180
- children: [
1181
- /* @__PURE__ */ jsx2(
1182
- StatusDot,
1183
- {
1184
- tone: statusTone,
1185
- pulse: isWaitingMessageCenterItem(item) || item.status === "working",
1186
- size: "sm",
1187
- title: statusLabel
1188
- }
1189
- ),
1190
- /* @__PURE__ */ jsx2("span", { children: statusLabel })
1191
- ]
1192
- }
1193
- )
1194
- ] })
1195
- ] }),
1196
- summary ? /* @__PURE__ */ jsx2(
1197
- MessageCenterSummary,
1198
- {
1199
- item,
1200
- lazy: lazySummary,
1201
- onLinkAction,
1202
- summary,
1203
- emptyLabel: t("agentHost.workspaceAgentMessageCenterNoSummary")
1204
- }
1205
- ) : null,
1206
- summaryAccessory,
1207
- prompt && interactive ? /* @__PURE__ */ jsx2("div", { className: "min-w-0", children: /* @__PURE__ */ jsx2(
1208
- AgentInteractivePromptSurface,
1209
- {
1210
- embedded: true,
1211
- variant: "compact",
1212
- keyboardShortcuts: false,
1213
- prompt,
1214
- isSubmitting,
1215
- onSubmit: onSubmitPrompt,
1216
- labels: buildWorkspaceAgentInteractivePromptLabels(
1217
- t,
1218
- item.provider
1219
- )
1220
- }
1221
- ) }) : null,
1222
- footerAccessory,
1223
- /* @__PURE__ */ jsx2(
1224
- MessageCenterOpenChatButton,
1225
- {
1226
- actionsAccessory,
1227
- provider: item.provider,
1228
- item,
1229
- label: t("agentHost.workspaceAgentMessageCenterOpenChat"),
1230
- onOpenChat,
1231
- alwaysVisible: interactive && prompt !== null
1232
- }
1233
- )
1234
- ]
961
+ identity: item.identity,
962
+ provider
1235
963
  }
1236
- );
964
+ ),
965
+ /* @__PURE__ */ jsxs("span", { className: "inline-flex shrink-0 items-center gap-2", children: [
966
+ actionsAccessory,
967
+ /* @__PURE__ */ jsxs(
968
+ Button,
969
+ {
970
+ type: "button",
971
+ variant: "ghost",
972
+ size: "default",
973
+ className: cn2(
974
+ "workspace-agent-message-center__open-chat-button h-auto gap-1.5 border-0 bg-transparent p-0 text-[var(--accent-codex)] shadow-none transition-[color,opacity,visibility] hover:bg-transparent hover:text-[var(--accent-codex)] focus-visible:bg-transparent focus-visible:text-[var(--accent-codex)] active:bg-transparent",
975
+ !alwaysVisible && "invisible opacity-0 group-hover/message-card:visible group-hover/message-card:opacity-100 group-focus-within/message-card:visible group-focus-within/message-card:opacity-100"
976
+ ),
977
+ onClick: () => onOpenChat({
978
+ agentSessionId: item.agentSessionId,
979
+ provider: item.provider
980
+ }),
981
+ children: [
982
+ /* @__PURE__ */ jsx2(
983
+ ExternalLink,
984
+ {
985
+ className: "size-[15px]",
986
+ strokeWidth: 2.2,
987
+ "aria-hidden": "true"
988
+ }
989
+ ),
990
+ label
991
+ ]
992
+ }
993
+ )
994
+ ] })
995
+ ] });
996
+ }
997
+ function MessageCenterIdentityLabel({
998
+ identity,
999
+ provider
1000
+ }) {
1001
+ "use memo";
1002
+ if (!identity) {
1003
+ return /* @__PURE__ */ jsx2(AgentProviderLabel, { provider });
1237
1004
  }
1238
- );
1239
- var STACK_PRESENCE_FALLBACK_MS = 380;
1240
- var MESSAGE_CENTER_STACK_INITIAL_RENDER_COUNT = 24;
1241
- var MESSAGE_CENTER_STACK_RENDER_BATCH_SIZE = 24;
1242
- var MESSAGE_CENTER_STACK_RENDER_BATCH_DELAY_MS = 40;
1243
- var MESSAGE_CENTER_SUMMARY_LAZY_ROOT_MARGIN = "480px 0px";
1244
- var MESSAGE_CENTER_SUMMARY_OVERFLOW_MEASURE_DELAY_MS = 80;
1245
- function useStackRegionPresence(visible) {
1246
- const [mounted, setMounted] = useState(visible);
1247
- const closing = mounted && !visible;
1248
- useLayoutEffect(() => {
1249
- if (visible) {
1250
- setMounted(true);
1251
- }
1252
- }, [visible]);
1253
- useEffect(() => {
1254
- if (!closing) {
1255
- return void 0;
1005
+ const agentAvatarUrl = identity.agentAvatarUrl?.trim() || managedAgentRoundedIconUrl(provider);
1006
+ const title = `${identity.userName} & ${identity.agentName}`;
1007
+ return /* @__PURE__ */ jsxs(
1008
+ "span",
1009
+ {
1010
+ className: "workspace-agent-message-center__identity inline-flex min-w-0 max-w-full items-center gap-2",
1011
+ title,
1012
+ children: [
1013
+ /* @__PURE__ */ jsx2(
1014
+ MessageCenterIdentityAvatarStack,
1015
+ {
1016
+ userAvatarUrl: identity.userAvatarUrl,
1017
+ userName: identity.userName,
1018
+ agentAvatarUrl
1019
+ }
1020
+ ),
1021
+ /* @__PURE__ */ jsxs("span", { className: "workspace-agent-message-center__identity-names flex min-w-0 items-center gap-1 truncate text-[13px] leading-5 text-[var(--text-secondary)]", children: [
1022
+ /* @__PURE__ */ jsx2("span", { className: "min-w-0 truncate", children: identity.userName }),
1023
+ /* @__PURE__ */ jsx2("span", { className: "shrink-0 text-[var(--text-tertiary)]", children: "&" }),
1024
+ /* @__PURE__ */ jsx2("span", { className: "min-w-0 truncate", children: identity.agentName })
1025
+ ] })
1026
+ ]
1256
1027
  }
1257
- const timeoutId = window.setTimeout(() => {
1258
- setMounted(false);
1259
- }, STACK_PRESENCE_FALLBACK_MS);
1260
- return () => {
1261
- window.clearTimeout(timeoutId);
1262
- };
1263
- }, [closing]);
1264
- const onAnimationEnd = useCallback(
1265
- (event) => {
1266
- if (event.target === event.currentTarget && closing) {
1267
- setMounted(false);
1268
- }
1269
- },
1270
- [closing]
1271
1028
  );
1272
- return { closing, mounted, onAnimationEnd };
1273
1029
  }
1274
- var WorkspaceAgentMessageCenterStack = memo(
1275
- function WorkspaceAgentMessageCenterStack2({
1276
- className,
1277
- expanded,
1278
- groupId,
1279
- highlightedItemId,
1280
- items,
1281
- renderCard,
1282
- onCollapse,
1283
- onExpand
1284
- }) {
1285
- "use memo";
1286
- const { t } = useTranslation();
1287
- const summaryRegion = useStackRegionPresence(!expanded);
1288
- const cardsRegion = useStackRegionPresence(expanded);
1289
- const visibleItems = useBatchedMessageCenterStackItems({
1290
- expanded,
1291
- highlightedItemId,
1292
- items,
1293
- mounted: cardsRegion.mounted
1294
- });
1295
- if (items.length < 2) {
1296
- return null;
1297
- }
1298
- const collapseLabel = t(
1299
- "agentHost.workspaceAgentMessageCenterCollapseStackAria"
1300
- );
1301
- return /* @__PURE__ */ jsxs(
1302
- "div",
1030
+ function MessageCenterIdentityAvatarMark({
1031
+ identity,
1032
+ provider,
1033
+ userId
1034
+ }) {
1035
+ "use memo";
1036
+ const userName = identity?.userName.trim() || userId?.trim() || "";
1037
+ if (!userName) {
1038
+ return /* @__PURE__ */ jsx2(
1039
+ "img",
1303
1040
  {
1304
- className: cn2("relative flex min-w-0 flex-col", className),
1305
- "data-stack-count": items.length,
1306
- "data-stack-motion": "smooth",
1307
- "data-stack-state": expanded ? "expanded" : "collapsed",
1308
- "data-stack-top-item-id": items[0]?.id,
1309
- "data-testid": `workspace-agent-message-stack-${groupId}`,
1310
- children: [
1311
- summaryRegion.mounted ? /* @__PURE__ */ jsx2(
1312
- "div",
1313
- {
1314
- className: cn2(
1315
- "workspace-agent-message-center__stack-rest min-w-0",
1316
- summaryRegion.closing ? "workspace-agent-message-center__stack-rest--closing" : "workspace-agent-message-center__stack-rest--opening"
1317
- ),
1318
- onAnimationEnd: summaryRegion.onAnimationEnd,
1319
- children: /* @__PURE__ */ jsx2(
1320
- "div",
1321
- {
1322
- className: "min-h-0 min-w-0 overflow-hidden",
1323
- "aria-hidden": summaryRegion.closing ? true : void 0,
1324
- inert: summaryRegion.closing ? true : void 0,
1325
- children: /* @__PURE__ */ jsx2(
1326
- MessageCenterStackSummary,
1327
- {
1328
- groupId,
1329
- items,
1330
- onExpand
1331
- }
1332
- )
1333
- }
1334
- )
1335
- }
1336
- ) : null,
1337
- cardsRegion.mounted ? /* @__PURE__ */ jsx2(
1338
- "div",
1339
- {
1340
- className: cn2(
1341
- "workspace-agent-message-center__stack-rest min-w-0",
1342
- cardsRegion.closing ? "workspace-agent-message-center__stack-rest--closing" : "workspace-agent-message-center__stack-rest--opening"
1343
- ),
1344
- onAnimationEnd: cardsRegion.onAnimationEnd,
1345
- children: /* @__PURE__ */ jsxs(
1346
- "div",
1347
- {
1348
- className: "min-h-0 min-w-0 overflow-hidden",
1349
- "aria-hidden": cardsRegion.closing ? true : void 0,
1350
- inert: cardsRegion.closing ? true : void 0,
1351
- children: [
1352
- /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 items-center justify-between gap-2 px-0.5 pb-1.5", children: [
1353
- /* @__PURE__ */ jsxs("span", { className: "flex min-w-0 items-center gap-1.5 text-[13px] font-semibold leading-4 text-[var(--text-tertiary)]", children: [
1354
- /* @__PURE__ */ jsx2(
1355
- MessageCenterIdentityAvatarMark,
1356
- {
1357
- identity: items[0]?.identity ?? null,
1358
- provider: items[0]?.provider ?? "",
1359
- userId: items[0]?.userId ?? null
1360
- }
1361
- ),
1362
- /* @__PURE__ */ jsx2("span", { className: "min-w-0 truncate", children: t(
1363
- "agentHost.workspaceAgentMessageCenterStackSummaryCount",
1364
- {
1365
- count: items.length
1366
- }
1367
- ) })
1368
- ] }),
1369
- /* @__PURE__ */ jsx2(
1370
- LazyMessageCenterTooltip,
1371
- {
1372
- content: collapseLabel,
1373
- side: "top",
1374
- align: "center",
1375
- children: /* @__PURE__ */ jsx2(
1376
- Button,
1377
- {
1378
- type: "button",
1379
- variant: "ghost",
1380
- size: "icon-sm",
1381
- "aria-label": collapseLabel,
1382
- className: "size-6 text-[var(--text-tertiary)] hover:text-[var(--text-primary)]",
1383
- onClick: () => onCollapse(groupId),
1384
- children: /* @__PURE__ */ jsx2(ChevronUp, { className: "size-3.5", "aria-hidden": "true" })
1385
- }
1386
- )
1387
- }
1388
- )
1389
- ] }),
1390
- /* @__PURE__ */ jsx2("div", { className: "flex min-w-0 flex-col gap-2.5", children: visibleItems.map(
1391
- (item, stackedIndex) => renderCard(item, { stackedIndex })
1392
- ) })
1393
- ]
1394
- }
1395
- )
1396
- }
1397
- ) : null
1398
- ]
1041
+ src: managedAgentRoundedIconUrl(provider),
1042
+ alt: "",
1043
+ className: "size-5 shrink-0 rounded-full",
1044
+ decoding: "async",
1045
+ loading: "lazy",
1046
+ draggable: false,
1047
+ "aria-hidden": "true"
1399
1048
  }
1400
1049
  );
1401
- },
1402
- areMessageCenterStackPropsEqual
1403
- );
1404
- function areMessageCenterStackPropsEqual(previous, next) {
1405
- 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) {
1406
- return false;
1407
- }
1408
- if (next.expanded) {
1409
- return previous.highlightedItemId === next.highlightedItemId && previous.items === next.items;
1410
- }
1411
- return messageCenterCollapsedStackSignature(previous.items) === messageCenterCollapsedStackSignature(next.items);
1412
- }
1413
- function messageCenterCollapsedStackSignature(items) {
1414
- const firstItem = items[0];
1415
- if (!firstItem) {
1416
- return "0";
1417
1050
  }
1418
- const hasWaiting = items.some(isWaitingMessageCenterItem) ? "1" : "0";
1419
- return [
1420
- items.length,
1421
- firstItem.id,
1422
- firstItem.provider,
1423
- firstItem.userId ?? "",
1424
- firstItem.identity?.userName ?? "",
1425
- firstItem.identity?.agentName ?? "",
1426
- hasWaiting,
1427
- messageCenterStackPreviewText(firstItem)
1428
- ].join(":");
1051
+ return /* @__PURE__ */ jsx2(
1052
+ MessageCenterIdentityAvatarStack,
1053
+ {
1054
+ userAvatarUrl: identity?.userAvatarUrl,
1055
+ userName,
1056
+ agentAvatarUrl: identity?.agentAvatarUrl?.trim() || managedAgentRoundedIconUrl(provider)
1057
+ }
1058
+ );
1429
1059
  }
1430
- function useBatchedMessageCenterStackItems({
1431
- expanded,
1432
- highlightedItemId,
1433
- items,
1434
- mounted
1060
+ function MessageCenterIdentityAvatarStack({
1061
+ agentAvatarUrl,
1062
+ userAvatarUrl: rawUserAvatarUrl,
1063
+ userName
1435
1064
  }) {
1436
- const limit = items.length;
1437
- const highlightedIndex = highlightedItemId === null || highlightedItemId === void 0 ? -1 : items.findIndex((item) => item.id === highlightedItemId);
1438
- const initialCount = Math.min(
1439
- limit,
1440
- Math.max(MESSAGE_CENTER_STACK_INITIAL_RENDER_COUNT, highlightedIndex + 1)
1441
- );
1442
- const [renderCount, setRenderCount] = useState(initialCount);
1065
+ "use memo";
1066
+ const [userAvatarFailed, setUserAvatarFailed] = useState(false);
1067
+ const userAvatarUrl = rawUserAvatarUrl?.trim() ?? "";
1068
+ const userImageUrl = userAvatarUrl.length > 0 && !userAvatarFailed ? userAvatarUrl : userAvatarPlaceholderUrl;
1443
1069
  useEffect(() => {
1444
- if (!mounted) {
1445
- setRenderCount(initialCount);
1446
- return;
1070
+ setUserAvatarFailed(false);
1071
+ }, [userAvatarUrl]);
1072
+ return /* @__PURE__ */ jsxs(
1073
+ "span",
1074
+ {
1075
+ className: "workspace-agent-message-center__identity-avatar-stack inline-flex w-9 shrink-0 items-center",
1076
+ "aria-hidden": "true",
1077
+ children: [
1078
+ /* @__PURE__ */ jsx2("span", { className: "inline-flex size-5 shrink-0 overflow-hidden rounded-full bg-[var(--transparency-block)] ring-2 ring-[var(--background-fronted)]", children: /* @__PURE__ */ jsx2(
1079
+ "img",
1080
+ {
1081
+ src: userImageUrl,
1082
+ alt: userName,
1083
+ className: "size-full object-cover",
1084
+ decoding: "async",
1085
+ loading: "lazy",
1086
+ referrerPolicy: "no-referrer",
1087
+ draggable: false,
1088
+ onError: () => {
1089
+ setUserAvatarFailed(true);
1090
+ }
1091
+ }
1092
+ ) }),
1093
+ /* @__PURE__ */ jsx2("span", { className: "-ml-1.5 inline-flex size-5 shrink-0 overflow-hidden rounded-full bg-[var(--transparency-block)] ring-2 ring-[var(--background-fronted)]", children: /* @__PURE__ */ jsx2(
1094
+ "img",
1095
+ {
1096
+ src: agentAvatarUrl,
1097
+ alt: "",
1098
+ className: "size-full object-cover",
1099
+ decoding: "async",
1100
+ loading: "lazy",
1101
+ draggable: false
1102
+ }
1103
+ ) })
1104
+ ]
1447
1105
  }
1448
- setRenderCount(
1449
- (current) => Math.min(Math.max(current, initialCount), limit)
1450
- );
1451
- }, [initialCount, limit, mounted]);
1452
- useEffect(() => {
1453
- if (!expanded || !mounted || renderCount >= limit) {
1454
- return void 0;
1106
+ );
1107
+ }
1108
+ function ProjectPathInfo({ path }) {
1109
+ "use memo";
1110
+ return /* @__PURE__ */ jsx2(
1111
+ LazyMessageCenterTooltip,
1112
+ {
1113
+ content: path,
1114
+ side: "top",
1115
+ align: "start",
1116
+ className: "max-w-[320px] text-[11px] [overflow-wrap:anywhere]",
1117
+ children: /* @__PURE__ */ jsx2(
1118
+ "button",
1119
+ {
1120
+ type: "button",
1121
+ 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",
1122
+ "aria-label": path,
1123
+ children: /* @__PURE__ */ jsx2(Info, { className: "size-3.5", strokeWidth: 2, "aria-hidden": "true" })
1124
+ }
1125
+ )
1455
1126
  }
1456
- const timeoutId = window.setTimeout(() => {
1457
- setRenderCount(
1458
- (current) => Math.min(current + MESSAGE_CENTER_STACK_RENDER_BATCH_SIZE, limit)
1459
- );
1460
- }, MESSAGE_CENTER_STACK_RENDER_BATCH_DELAY_MS);
1461
- return () => {
1462
- window.clearTimeout(timeoutId);
1463
- };
1464
- }, [expanded, limit, mounted, renderCount]);
1465
- return items.slice(0, Math.min(renderCount, limit));
1127
+ );
1128
+ }
1129
+ function LazyMessageCenterTooltip({
1130
+ align,
1131
+ children,
1132
+ className,
1133
+ content,
1134
+ side
1135
+ }) {
1136
+ "use memo";
1137
+ const [hydrated, setHydrated] = useState(false);
1138
+ const [open, setOpen] = useState(false);
1139
+ const showTooltip = useCallback(() => {
1140
+ setHydrated(true);
1141
+ setOpen(true);
1142
+ }, []);
1143
+ const hideTooltip = useCallback(() => {
1144
+ setOpen(false);
1145
+ }, []);
1146
+ const trigger = cloneElement(children, {
1147
+ onBlur: (event) => {
1148
+ children.props.onBlur?.(event);
1149
+ hideTooltip();
1150
+ },
1151
+ onFocus: (event) => {
1152
+ children.props.onFocus?.(event);
1153
+ showTooltip();
1154
+ },
1155
+ onPointerEnter: (event) => {
1156
+ children.props.onPointerEnter?.(event);
1157
+ showTooltip();
1158
+ },
1159
+ onPointerLeave: (event) => {
1160
+ children.props.onPointerLeave?.(event);
1161
+ hideTooltip();
1162
+ }
1163
+ });
1164
+ if (!hydrated) {
1165
+ return trigger;
1166
+ }
1167
+ return /* @__PURE__ */ jsxs(Tooltip, { open, onOpenChange: setOpen, children: [
1168
+ /* @__PURE__ */ jsx2(TooltipTrigger, { asChild: true, children: trigger }),
1169
+ /* @__PURE__ */ jsx2(TooltipContent, { side, align, className, children: content })
1170
+ ] });
1171
+ }
1172
+ function AgentProviderLabel({ provider }) {
1173
+ "use memo";
1174
+ const label = workspaceAgentProviderLabel(provider);
1175
+ return /* @__PURE__ */ jsxs("span", { className: "workspace-agent-message-center__provider inline-flex min-w-0 max-w-full items-center gap-1.5", children: [
1176
+ /* @__PURE__ */ jsx2(
1177
+ "img",
1178
+ {
1179
+ src: managedAgentRoundedIconUrl(provider),
1180
+ alt: "",
1181
+ className: "workspace-agent-message-center__provider-icon size-5 shrink-0 rounded-full",
1182
+ decoding: "async",
1183
+ loading: "lazy",
1184
+ draggable: false,
1185
+ "aria-hidden": "true"
1186
+ }
1187
+ ),
1188
+ /* @__PURE__ */ jsx2("span", { className: "workspace-agent-message-center__provider-name min-w-0 truncate text-[13px] leading-5 text-[var(--text-secondary)]", children: label })
1189
+ ] });
1466
1190
  }
1467
- function MessageCenterStackSummary({
1468
- groupId,
1469
- items,
1470
- onExpand
1471
- }) {
1472
- "use memo";
1473
- const { t } = useTranslation();
1474
- const firstItem = items[0];
1475
- const hasWaiting = items.some((item) => isWaitingMessageCenterItem(item));
1476
- if (!firstItem) {
1477
- return null;
1191
+ function statusClass(item) {
1192
+ if (isWaitingMessageCenterItem(item)) {
1193
+ return "waiting";
1478
1194
  }
1479
- return /* @__PURE__ */ jsx2(
1480
- "button",
1481
- {
1482
- type: "button",
1483
- "aria-label": t("agentHost.workspaceAgentMessageCenterExpandStackAria", {
1484
- count: items.length
1485
- }),
1486
- className: cn2(
1487
- "group/stack-peek relative block w-full min-w-0 rounded-lg text-left outline-none focus-visible:ring-2 focus-visible:ring-[var(--accent)]",
1488
- items.length > 2 ? "pb-[18px]" : "pb-[10px]"
1489
- ),
1490
- "data-stack-summary-count": items.length,
1491
- "data-stack-provider": firstItem.provider,
1492
- "data-stack-user-id": firstItem.userId ?? "",
1493
- "data-testid": `workspace-agent-message-stack-summary-${groupId}`,
1494
- onClick: () => onExpand(groupId),
1495
- children: /* @__PURE__ */ jsxs(
1496
- "span",
1497
- {
1498
- className: cn2(
1499
- "relative z-10 flex min-w-0 flex-col gap-2 rounded-lg border border-[var(--line-2)] bg-[var(--background-fronted)] p-3.5 transition-[background-color,border-color] duration-200 group-hover/stack-peek:bg-[var(--transparency-hover)]",
1500
- items.length > 2 ? "shadow-[0_7px_0_-4px_var(--background-fronted),0_7px_0_-3px_var(--line-2),0_14px_0_-8px_var(--background-fronted),0_14px_0_-7px_var(--line-2)]" : "shadow-[0_7px_0_-4px_var(--background-fronted),0_7px_0_-3px_var(--line-2)]",
1501
- hasWaiting && "border-[var(--tutti-purple-border)] bg-[var(--tutti-purple-bg)]"
1502
- ),
1503
- children: [
1504
- /* @__PURE__ */ jsxs("span", { className: "flex min-w-0 items-center justify-between gap-2.5", children: [
1505
- /* @__PURE__ */ jsxs("span", { className: "flex min-w-0 items-center gap-2", children: [
1506
- /* @__PURE__ */ jsx2(
1507
- MessageCenterIdentityAvatarMark,
1508
- {
1509
- identity: firstItem.identity,
1510
- provider: firstItem.provider,
1511
- userId: firstItem.userId
1512
- }
1513
- ),
1514
- /* @__PURE__ */ jsx2("span", { className: "min-w-0 truncate text-[13px] font-bold leading-5 text-[var(--text-secondary)]", children: t("agentHost.workspaceAgentMessageCenterStackSummaryCount", {
1515
- count: items.length
1516
- }) })
1517
- ] }),
1518
- /* @__PURE__ */ jsx2(
1519
- ChevronDown,
1520
- {
1521
- className: "size-4 shrink-0 text-[var(--text-tertiary)] transition-transform duration-200 group-hover/stack-peek:translate-y-0.5 motion-reduce:transition-none",
1522
- "aria-hidden": "true"
1523
- }
1524
- )
1525
- ] }),
1526
- /* @__PURE__ */ jsx2("span", { className: "min-w-0 rounded-md bg-transparency-block p-2.5 text-[13px] leading-[1.45] text-[var(--text-primary)]", children: /* @__PURE__ */ jsx2("span", { className: "line-clamp-2 min-w-0 [overflow-wrap:anywhere]", children: messageCenterStackPreviewNodes(firstItem) }) })
1527
- ]
1528
- }
1529
- )
1530
- }
1531
- );
1195
+ if (item.status === "idle") {
1196
+ return "completed";
1197
+ }
1198
+ return item.status;
1532
1199
  }
1200
+ function messageCenterStatusTone(item) {
1201
+ if (isWaitingMessageCenterItem(item)) {
1202
+ return "amber";
1203
+ }
1204
+ if (item.status === "completed" || item.status === "idle") {
1205
+ return "green";
1206
+ }
1207
+ if (item.status === "canceled") {
1208
+ return "amber";
1209
+ }
1210
+ if (item.status === "failed") {
1211
+ return "red";
1212
+ }
1213
+ if (item.status === "working") {
1214
+ return "blue";
1215
+ }
1216
+ return "neutral";
1217
+ }
1218
+ function messageCenterStatusToneClass(tone) {
1219
+ switch (tone) {
1220
+ case "amber":
1221
+ return "text-[var(--state-warning)]";
1222
+ case "blue":
1223
+ return "text-[var(--status-running)]";
1224
+ case "green":
1225
+ return "text-[var(--state-success)]";
1226
+ case "red":
1227
+ return "text-[var(--state-danger)]";
1228
+ case "neutral":
1229
+ return "text-[var(--text-secondary)]";
1230
+ }
1231
+ }
1232
+
1233
+ // agent-message-center/workspaceAgentMessageCenterPreview.tsx
1234
+ import { AppWindow } from "lucide-react";
1235
+ import {
1236
+ isRichTextMentionHref,
1237
+ parseRichTextMentionHref
1238
+ } from "@tutti-os/ui-rich-text/core";
1239
+ import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
1533
1240
  function messageCenterStackRawPreviewText(item) {
1534
1241
  return item.digest.primary.summary.trim() || item.lastAgentMessageSummary.trim() || item.title;
1535
1242
  }
@@ -1564,7 +1271,7 @@ function messageCenterStackPreviewNodes(item) {
1564
1271
  const kind = messageCenterPreviewMentionKind(mention.providerId);
1565
1272
  const displayLabel = label || mention.label;
1566
1273
  nodes.push(
1567
- kind ? /* @__PURE__ */ jsx2(
1274
+ kind ? /* @__PURE__ */ jsx3(
1568
1275
  MessageCenterPreviewMentionChip,
1569
1276
  {
1570
1277
  kind,
@@ -1598,20 +1305,20 @@ function MessageCenterPreviewMentionChip({
1598
1305
  kind,
1599
1306
  label
1600
1307
  }) {
1601
- return /* @__PURE__ */ jsxs(
1308
+ return /* @__PURE__ */ jsxs2(
1602
1309
  "span",
1603
1310
  {
1604
1311
  className: "tsh-agent-object-token tsh-agent-object-token--entity",
1605
1312
  "data-agent-mention-kind": kind,
1606
1313
  children: [
1607
- /* @__PURE__ */ jsx2("span", { className: "tsh-agent-object-token__kind", "aria-hidden": "true", children: kind === "workspace-app" ? /* @__PURE__ */ jsx2(AppWindow, { className: "size-3.5", "aria-hidden": "true" }) : /* @__PURE__ */ jsx2(
1314
+ /* @__PURE__ */ jsx3("span", { className: "tsh-agent-object-token__kind", "aria-hidden": "true", children: kind === "workspace-app" ? /* @__PURE__ */ jsx3(AppWindow, { className: "size-3.5", "aria-hidden": "true" }) : /* @__PURE__ */ jsx3(
1608
1315
  "span",
1609
1316
  {
1610
1317
  className: "tsh-agent-object-token__kind-icon",
1611
1318
  "aria-hidden": "true"
1612
1319
  }
1613
1320
  ) }),
1614
- /* @__PURE__ */ jsx2("span", { className: "tsh-agent-object-token__main", children: label })
1321
+ /* @__PURE__ */ jsx3("span", { className: "tsh-agent-object-token__main", children: label })
1615
1322
  ]
1616
1323
  }
1617
1324
  );
@@ -1691,465 +1398,614 @@ function normalizeMessageCenterNotificationAction(action) {
1691
1398
  return action;
1692
1399
  }
1693
1400
  }
1694
- function messageCenterVisibleSummary(item) {
1695
- const summary = item.digest.primary.summary.trim();
1696
- if (item.pendingPrompt?.kind === "approval" && isGenericApprovalSummary(summary)) {
1697
- return "";
1698
- }
1699
- return summary;
1700
- }
1701
- function isGenericApprovalSummary(summary) {
1702
- const normalized = summary.trim().toLowerCase();
1703
- return normalized === "approval";
1401
+
1402
+ // agent-message-center/WorkspaceAgentMessageCenterCard.tsx
1403
+ import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
1404
+ function stopMessageCenterTextPointerPropagation(event) {
1405
+ event.stopPropagation();
1704
1406
  }
1705
- function MessageCenterSummary({
1706
- emptyLabel,
1707
- item,
1708
- lazy,
1709
- onLinkAction,
1710
- summary
1711
- }) {
1712
- "use memo";
1713
- const summaryRef = useRef(null);
1714
- const [isOverflowing, setIsOverflowing] = useState(false);
1715
- const shouldRenderRichSummary = useLazyMessageCenterSummaryReady(
1716
- summaryRef,
1717
- lazy
1718
- );
1719
- const shouldMeasureOverflow = useDeferredMessageCenterSummaryMeasureReady(
1720
- summaryRef,
1721
- shouldRenderRichSummary
1722
- );
1723
- const handleLinkAction = useCallback(
1724
- (action) => {
1725
- const agentTargetId = item.agentTargetId?.trim() || null;
1726
- onLinkAction?.(
1727
- action.type === "open-agent-session" && !action.agentTargetId && agentTargetId ? { ...action, agentTargetId } : action
1728
- );
1729
- },
1730
- [item.agentTargetId, onLinkAction]
1731
- );
1732
- useEffect(() => {
1733
- if (!shouldMeasureOverflow) {
1734
- setIsOverflowing(false);
1735
- return void 0;
1407
+ var WorkspaceAgentMessageCenterCard = memo(
1408
+ function WorkspaceAgentMessageCenterCard2({
1409
+ cardRef,
1410
+ actionsAccessory,
1411
+ footerAccessory,
1412
+ headerAccessory,
1413
+ highlighted = false,
1414
+ interactive = true,
1415
+ item,
1416
+ isSubmitting,
1417
+ lazySummary = false,
1418
+ summaryAccessory,
1419
+ onLinkAction,
1420
+ onOpenChat,
1421
+ onSubmitPrompt
1422
+ }) {
1423
+ "use memo";
1424
+ const { t } = useTranslation();
1425
+ const prompt = item.pendingPrompt;
1426
+ const displayTitle = formatAgentGuiConversationPlainTitle(item, {
1427
+ language: getActiveUiLanguage()
1428
+ });
1429
+ const summary = messageCenterVisibleSummary(item);
1430
+ const displayStatus = statusClass(item);
1431
+ const statusTone = messageCenterStatusTone(item);
1432
+ const statusLabel = workspaceAgentActivityStatusLabel(displayStatus, t);
1433
+ return /* @__PURE__ */ jsxs3(
1434
+ "article",
1435
+ {
1436
+ ref: cardRef,
1437
+ className: cn3(
1438
+ "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]",
1439
+ isWaitingMessageCenterItem(item) && "agent-gui-edge-glow border-[var(--tutti-purple-border)] bg-[var(--tutti-purple-bg)]",
1440
+ highlighted && "outline-2 outline-[var(--accent)]"
1441
+ ),
1442
+ "data-highlighted": highlighted ? "true" : void 0,
1443
+ "data-message-center-digest-kind": item.digest.primary.kind,
1444
+ "data-message-center-item-id": item.id,
1445
+ "data-waiting": isWaitingMessageCenterItem(item) ? "true" : void 0,
1446
+ "data-status": displayStatus,
1447
+ tabIndex: highlighted ? -1 : void 0,
1448
+ children: [
1449
+ /* @__PURE__ */ jsxs3("div", { className: "flex min-w-0 items-center justify-between gap-2.5", children: [
1450
+ /* @__PURE__ */ jsxs3("div", { className: "flex min-w-0 items-center gap-1.5", children: [
1451
+ /* @__PURE__ */ jsx4(
1452
+ LazyMessageCenterTooltip,
1453
+ {
1454
+ content: displayTitle,
1455
+ side: "top",
1456
+ align: "start",
1457
+ className: "max-w-[min(360px,calc(100vw-32px))] whitespace-normal text-left [overflow-wrap:anywhere]",
1458
+ children: /* @__PURE__ */ jsx4(
1459
+ "h3",
1460
+ {
1461
+ className: "workspace-agent-message-center__copy-text min-w-0 truncate text-[13px] font-bold leading-5 text-[var(--text-secondary)]",
1462
+ onPointerDown: stopMessageCenterTextPointerPropagation,
1463
+ children: displayTitle
1464
+ }
1465
+ )
1466
+ }
1467
+ ),
1468
+ item.cwd ? /* @__PURE__ */ jsx4(ProjectPathInfo, { path: item.cwd }) : null
1469
+ ] }),
1470
+ /* @__PURE__ */ jsxs3("span", { className: "flex shrink-0 items-center gap-2", children: [
1471
+ headerAccessory,
1472
+ /* @__PURE__ */ jsxs3(
1473
+ "span",
1474
+ {
1475
+ className: cn3(
1476
+ "workspace-agent-message-center__status inline-flex shrink-0 items-center gap-1.5 text-[11px] font-semibold leading-4",
1477
+ messageCenterStatusToneClass(statusTone)
1478
+ ),
1479
+ "data-status": displayStatus,
1480
+ title: statusLabel,
1481
+ children: [
1482
+ /* @__PURE__ */ jsx4(
1483
+ StatusDot,
1484
+ {
1485
+ tone: statusTone,
1486
+ pulse: isWaitingMessageCenterItem(item) || item.status === "working",
1487
+ size: "sm",
1488
+ title: statusLabel
1489
+ }
1490
+ ),
1491
+ /* @__PURE__ */ jsx4("span", { children: statusLabel })
1492
+ ]
1493
+ }
1494
+ )
1495
+ ] })
1496
+ ] }),
1497
+ summary ? /* @__PURE__ */ jsx4(
1498
+ MessageCenterSummary,
1499
+ {
1500
+ item,
1501
+ lazy: lazySummary,
1502
+ onLinkAction,
1503
+ summary,
1504
+ emptyLabel: t("agentHost.workspaceAgentMessageCenterNoSummary")
1505
+ }
1506
+ ) : null,
1507
+ summaryAccessory,
1508
+ prompt && interactive ? /* @__PURE__ */ jsx4("div", { className: "min-w-0", children: /* @__PURE__ */ jsx4(
1509
+ AgentInteractivePromptSurface,
1510
+ {
1511
+ embedded: true,
1512
+ variant: "compact",
1513
+ keyboardShortcuts: false,
1514
+ prompt,
1515
+ isSubmitting,
1516
+ onSubmit: onSubmitPrompt,
1517
+ labels: buildWorkspaceAgentInteractivePromptLabels(
1518
+ t,
1519
+ item.provider
1520
+ )
1521
+ }
1522
+ ) }) : null,
1523
+ footerAccessory,
1524
+ /* @__PURE__ */ jsx4(
1525
+ MessageCenterOpenChatButton,
1526
+ {
1527
+ actionsAccessory,
1528
+ provider: item.provider,
1529
+ item,
1530
+ label: t("agentHost.workspaceAgentMessageCenterOpenChat"),
1531
+ onOpenChat,
1532
+ alwaysVisible: interactive && prompt !== null
1533
+ }
1534
+ )
1535
+ ]
1536
+ }
1537
+ );
1538
+ }
1539
+ );
1540
+ var STACK_PRESENCE_FALLBACK_MS = 380;
1541
+ var MESSAGE_CENTER_STACK_INITIAL_RENDER_COUNT = 24;
1542
+ var MESSAGE_CENTER_STACK_RENDER_BATCH_SIZE = 24;
1543
+ var MESSAGE_CENTER_STACK_RENDER_BATCH_DELAY_MS = 40;
1544
+ var MESSAGE_CENTER_SUMMARY_LAZY_ROOT_MARGIN = "480px 0px";
1545
+ var MESSAGE_CENTER_SUMMARY_OVERFLOW_MEASURE_DELAY_MS = 80;
1546
+ function useStackRegionPresence(visible) {
1547
+ const [mounted, setMounted] = useState2(visible);
1548
+ const closing = mounted && !visible;
1549
+ useLayoutEffect(() => {
1550
+ if (visible) {
1551
+ setMounted(true);
1736
1552
  }
1737
- const element = summaryRef.current;
1738
- if (!element) {
1553
+ }, [visible]);
1554
+ useEffect2(() => {
1555
+ if (!closing) {
1739
1556
  return void 0;
1740
1557
  }
1741
- const updateOverflowState = () => {
1742
- setIsOverflowing(element.scrollHeight > element.clientHeight + 1);
1743
- };
1744
- let resizeObserver = null;
1745
1558
  const timeoutId = window.setTimeout(() => {
1746
- updateOverflowState();
1747
- resizeObserver = new ResizeObserver(updateOverflowState);
1748
- resizeObserver.observe(element);
1749
- }, MESSAGE_CENTER_SUMMARY_OVERFLOW_MEASURE_DELAY_MS);
1559
+ setMounted(false);
1560
+ }, STACK_PRESENCE_FALLBACK_MS);
1750
1561
  return () => {
1751
1562
  window.clearTimeout(timeoutId);
1752
- resizeObserver?.disconnect();
1753
1563
  };
1754
- }, [shouldMeasureOverflow, summary]);
1755
- return /* @__PURE__ */ jsx2(
1756
- AgentVerticalScrollArea,
1757
- {
1758
- ref: summaryRef,
1759
- className: cn2(
1760
- "workspace-agent-message-center__summary workspace-agent-message-center__copy-text max-h-[160px] min-w-0 rounded-md bg-transparency-block text-[13px] leading-[1.45] text-[var(--text-primary)] [overflow-wrap:anywhere]",
1761
- isOverflowing && "workspace-agent-message-center__summary--overflowing"
1762
- ),
1763
- viewportClassName: "workspace-agent-message-center__copy-text max-h-[160px] p-2.5 pr-4",
1764
- onPointerDown: stopMessageCenterTextPointerPropagation,
1765
- scrollbarClassName: "top-2 bottom-2 right-1.5",
1766
- syncKey: summary,
1767
- children: summary && shouldRenderRichSummary ? /* @__PURE__ */ jsx2(
1768
- AgentMessageMarkdown,
1769
- {
1770
- content: summary,
1771
- className: "[&_a]:text-[var(--tutti-purple)] [&_code]:text-[var(--text-secondary)] [&_hr]:border-t-[color-mix(in_srgb,var(--text-primary)_14%,transparent)] [&_ol]:!bg-transparent [&_p]:m-0 [&_th]:bg-[color-mix(in_srgb,var(--background-panel)_94%,var(--text-primary))] [&_th]:text-[var(--text-primary)] [&_ul]:!bg-transparent text-[var(--text-primary)]",
1772
- onLinkAction: handleLinkAction,
1773
- workspaceLinkContext: {
1774
- workspaceRoot: item.cwd || null,
1775
- basePath: item.cwd,
1776
- source: "agent-markdown"
1777
- },
1778
- enableImageZoom: true
1779
- }
1780
- ) : summary ? /* @__PURE__ */ jsx2("div", { className: "whitespace-pre-wrap [overflow-wrap:anywhere]", children: summary }) : emptyLabel
1781
- }
1564
+ }, [closing]);
1565
+ const onAnimationEnd = useCallback2(
1566
+ (event) => {
1567
+ if (event.target === event.currentTarget && closing) {
1568
+ setMounted(false);
1569
+ }
1570
+ },
1571
+ [closing]
1782
1572
  );
1573
+ return { closing, mounted, onAnimationEnd };
1783
1574
  }
1784
- function useLazyMessageCenterSummaryReady(ref, lazy) {
1785
- const [ready, setReady] = useState(!lazy);
1786
- useEffect(() => {
1787
- setReady(!lazy);
1788
- }, [lazy]);
1789
- useEffect(() => {
1790
- if (!lazy) {
1791
- return void 0;
1792
- }
1793
- if (ready) {
1794
- return void 0;
1795
- }
1796
- const element = ref.current;
1797
- if (!element || typeof IntersectionObserver === "undefined") {
1798
- setReady(true);
1799
- return void 0;
1800
- }
1801
- const observer = new IntersectionObserver(
1802
- (entries) => {
1803
- if (entries.some((entry) => entry.isIntersecting)) {
1804
- setReady(true);
1805
- observer.disconnect();
1806
- }
1807
- },
1808
- { rootMargin: MESSAGE_CENTER_SUMMARY_LAZY_ROOT_MARGIN }
1809
- );
1810
- observer.observe(element);
1811
- return () => observer.disconnect();
1812
- }, [lazy, ready, ref]);
1813
- return ready;
1814
- }
1815
- function useDeferredMessageCenterSummaryMeasureReady(ref, enabled) {
1816
- const [ready, setReady] = useState(false);
1817
- useEffect(() => {
1818
- if (!enabled) {
1819
- setReady(false);
1820
- return void 0;
1821
- }
1822
- if (ready) {
1823
- return void 0;
1824
- }
1825
- const element = ref.current;
1826
- if (!element || typeof IntersectionObserver === "undefined") {
1827
- const timeoutId2 = window.setTimeout(
1828
- () => setReady(true),
1829
- MESSAGE_CENTER_SUMMARY_OVERFLOW_MEASURE_DELAY_MS
1830
- );
1831
- return () => {
1832
- window.clearTimeout(timeoutId2);
1833
- };
1575
+ var WorkspaceAgentMessageCenterStack = memo(
1576
+ function WorkspaceAgentMessageCenterStack2({
1577
+ className,
1578
+ expanded,
1579
+ groupId,
1580
+ highlightedItemId,
1581
+ items,
1582
+ renderCard,
1583
+ onCollapse,
1584
+ onExpand
1585
+ }) {
1586
+ "use memo";
1587
+ const { t } = useTranslation();
1588
+ const summaryRegion = useStackRegionPresence(!expanded);
1589
+ const cardsRegion = useStackRegionPresence(expanded);
1590
+ const visibleItems = useBatchedMessageCenterStackItems({
1591
+ expanded,
1592
+ highlightedItemId,
1593
+ items,
1594
+ mounted: cardsRegion.mounted
1595
+ });
1596
+ if (items.length < 2) {
1597
+ return null;
1834
1598
  }
1835
- let timeoutId = null;
1836
- const observer = new IntersectionObserver(
1837
- (entries) => {
1838
- if (!entries.some((entry) => entry.isIntersecting)) {
1839
- return;
1840
- }
1841
- observer.disconnect();
1842
- timeoutId = window.setTimeout(
1843
- () => setReady(true),
1844
- MESSAGE_CENTER_SUMMARY_OVERFLOW_MEASURE_DELAY_MS
1845
- );
1846
- },
1847
- { rootMargin: MESSAGE_CENTER_SUMMARY_LAZY_ROOT_MARGIN }
1599
+ const collapseLabel = t(
1600
+ "agentHost.workspaceAgentMessageCenterCollapseStackAria"
1848
1601
  );
1849
- observer.observe(element);
1850
- return () => {
1851
- observer.disconnect();
1852
- if (timeoutId !== null) {
1853
- window.clearTimeout(timeoutId);
1854
- }
1855
- };
1856
- }, [enabled, ready, ref]);
1857
- return ready;
1858
- }
1859
- function MessageCenterOpenChatButton({
1860
- actionsAccessory,
1861
- alwaysVisible = false,
1862
- item,
1863
- label,
1864
- onOpenChat,
1865
- provider
1866
- }) {
1867
- "use memo";
1868
- return /* @__PURE__ */ jsxs("div", { className: "workspace-agent-message-center__footer flex min-w-0 items-center justify-between gap-2", children: [
1869
- /* @__PURE__ */ jsx2(
1870
- MessageCenterIdentityLabel,
1602
+ return /* @__PURE__ */ jsxs3(
1603
+ "div",
1871
1604
  {
1872
- identity: item.identity,
1873
- provider
1605
+ className: cn3("relative flex min-w-0 flex-col", className),
1606
+ "data-stack-count": items.length,
1607
+ "data-stack-motion": "smooth",
1608
+ "data-stack-state": expanded ? "expanded" : "collapsed",
1609
+ "data-stack-top-item-id": items[0]?.id,
1610
+ "data-testid": `workspace-agent-message-stack-${groupId}`,
1611
+ children: [
1612
+ summaryRegion.mounted ? /* @__PURE__ */ jsx4(
1613
+ "div",
1614
+ {
1615
+ className: cn3(
1616
+ "workspace-agent-message-center__stack-rest min-w-0",
1617
+ summaryRegion.closing ? "workspace-agent-message-center__stack-rest--closing" : "workspace-agent-message-center__stack-rest--opening"
1618
+ ),
1619
+ onAnimationEnd: summaryRegion.onAnimationEnd,
1620
+ children: /* @__PURE__ */ jsx4(
1621
+ "div",
1622
+ {
1623
+ className: "min-h-0 min-w-0 overflow-hidden",
1624
+ "aria-hidden": summaryRegion.closing ? true : void 0,
1625
+ inert: summaryRegion.closing ? true : void 0,
1626
+ children: /* @__PURE__ */ jsx4(
1627
+ MessageCenterStackSummary,
1628
+ {
1629
+ groupId,
1630
+ items,
1631
+ onExpand
1632
+ }
1633
+ )
1634
+ }
1635
+ )
1636
+ }
1637
+ ) : null,
1638
+ cardsRegion.mounted ? /* @__PURE__ */ jsx4(
1639
+ "div",
1640
+ {
1641
+ className: cn3(
1642
+ "workspace-agent-message-center__stack-rest min-w-0",
1643
+ cardsRegion.closing ? "workspace-agent-message-center__stack-rest--closing" : "workspace-agent-message-center__stack-rest--opening"
1644
+ ),
1645
+ onAnimationEnd: cardsRegion.onAnimationEnd,
1646
+ children: /* @__PURE__ */ jsxs3(
1647
+ "div",
1648
+ {
1649
+ className: "min-h-0 min-w-0 overflow-hidden",
1650
+ "aria-hidden": cardsRegion.closing ? true : void 0,
1651
+ inert: cardsRegion.closing ? true : void 0,
1652
+ children: [
1653
+ /* @__PURE__ */ jsxs3("div", { className: "flex min-w-0 items-center justify-between gap-2 px-0.5 pb-1.5", children: [
1654
+ /* @__PURE__ */ jsxs3("span", { className: "flex min-w-0 items-center gap-1.5 text-[13px] font-semibold leading-4 text-[var(--text-tertiary)]", children: [
1655
+ /* @__PURE__ */ jsx4(
1656
+ MessageCenterIdentityAvatarMark,
1657
+ {
1658
+ identity: items[0]?.identity ?? null,
1659
+ provider: items[0]?.provider ?? "",
1660
+ userId: items[0]?.userId ?? null
1661
+ }
1662
+ ),
1663
+ /* @__PURE__ */ jsx4("span", { className: "min-w-0 truncate", children: t(
1664
+ "agentHost.workspaceAgentMessageCenterStackSummaryCount",
1665
+ {
1666
+ count: items.length
1667
+ }
1668
+ ) })
1669
+ ] }),
1670
+ /* @__PURE__ */ jsx4(
1671
+ LazyMessageCenterTooltip,
1672
+ {
1673
+ content: collapseLabel,
1674
+ side: "top",
1675
+ align: "center",
1676
+ children: /* @__PURE__ */ jsx4(
1677
+ Button2,
1678
+ {
1679
+ type: "button",
1680
+ variant: "ghost",
1681
+ size: "icon-sm",
1682
+ "aria-label": collapseLabel,
1683
+ className: "size-6 text-[var(--text-tertiary)] hover:text-[var(--text-primary)]",
1684
+ onClick: () => onCollapse(groupId),
1685
+ children: /* @__PURE__ */ jsx4(ChevronUp, { className: "size-3.5", "aria-hidden": "true" })
1686
+ }
1687
+ )
1688
+ }
1689
+ )
1690
+ ] }),
1691
+ /* @__PURE__ */ jsx4("div", { className: "flex min-w-0 flex-col gap-2.5", children: visibleItems.map(
1692
+ (item, stackedIndex) => renderCard(item, { stackedIndex })
1693
+ ) })
1694
+ ]
1695
+ }
1696
+ )
1697
+ }
1698
+ ) : null
1699
+ ]
1874
1700
  }
1875
- ),
1876
- /* @__PURE__ */ jsxs("span", { className: "inline-flex shrink-0 items-center gap-2", children: [
1877
- actionsAccessory,
1878
- /* @__PURE__ */ jsxs(
1879
- Button,
1880
- {
1881
- type: "button",
1882
- variant: "ghost",
1883
- size: "default",
1884
- className: cn2(
1885
- "workspace-agent-message-center__open-chat-button h-auto gap-1.5 border-0 bg-transparent p-0 text-[var(--accent-codex)] shadow-none transition-[color,opacity,visibility] hover:bg-transparent hover:text-[var(--accent-codex)] focus-visible:bg-transparent focus-visible:text-[var(--accent-codex)] active:bg-transparent",
1886
- !alwaysVisible && "invisible opacity-0 group-hover/message-card:visible group-hover/message-card:opacity-100 group-focus-within/message-card:visible group-focus-within/message-card:opacity-100"
1887
- ),
1888
- onClick: () => onOpenChat({
1889
- agentSessionId: item.agentSessionId,
1890
- provider: item.provider
1891
- }),
1892
- children: [
1893
- /* @__PURE__ */ jsx2(
1894
- ExternalLink,
1895
- {
1896
- className: "size-[15px]",
1897
- strokeWidth: 2.2,
1898
- "aria-hidden": "true"
1899
- }
1900
- ),
1901
- label
1902
- ]
1903
- }
1904
- )
1905
- ] })
1906
- ] });
1701
+ );
1702
+ },
1703
+ areMessageCenterStackPropsEqual
1704
+ );
1705
+ function areMessageCenterStackPropsEqual(previous, next) {
1706
+ 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) {
1707
+ return false;
1708
+ }
1709
+ if (next.expanded) {
1710
+ return previous.highlightedItemId === next.highlightedItemId && previous.items === next.items;
1711
+ }
1712
+ return messageCenterCollapsedStackSignature(previous.items) === messageCenterCollapsedStackSignature(next.items);
1907
1713
  }
1908
- function MessageCenterIdentityLabel({
1909
- identity,
1910
- provider
1911
- }) {
1912
- "use memo";
1913
- if (!identity) {
1914
- return /* @__PURE__ */ jsx2(AgentProviderLabel, { provider });
1714
+ function messageCenterCollapsedStackSignature(items) {
1715
+ const firstItem = items[0];
1716
+ if (!firstItem) {
1717
+ return "0";
1915
1718
  }
1916
- const agentAvatarUrl = identity.agentAvatarUrl?.trim() || managedAgentRoundedIconUrl(provider);
1917
- const title = `${identity.userName} & ${identity.agentName}`;
1918
- return /* @__PURE__ */ jsxs(
1919
- "span",
1920
- {
1921
- className: "workspace-agent-message-center__identity inline-flex min-w-0 max-w-full items-center gap-2",
1922
- title,
1923
- children: [
1924
- /* @__PURE__ */ jsx2(
1925
- MessageCenterIdentityAvatarStack,
1926
- {
1927
- userAvatarUrl: identity.userAvatarUrl,
1928
- userName: identity.userName,
1929
- agentAvatarUrl
1930
- }
1931
- ),
1932
- /* @__PURE__ */ jsxs("span", { className: "workspace-agent-message-center__identity-names flex min-w-0 items-center gap-1 truncate text-[13px] leading-5 text-[var(--text-secondary)]", children: [
1933
- /* @__PURE__ */ jsx2("span", { className: "min-w-0 truncate", children: identity.userName }),
1934
- /* @__PURE__ */ jsx2("span", { className: "shrink-0 text-[var(--text-tertiary)]", children: "&" }),
1935
- /* @__PURE__ */ jsx2("span", { className: "min-w-0 truncate", children: identity.agentName })
1936
- ] })
1937
- ]
1938
- }
1939
- );
1719
+ const hasWaiting = items.some(isWaitingMessageCenterItem) ? "1" : "0";
1720
+ return [
1721
+ items.length,
1722
+ firstItem.id,
1723
+ firstItem.provider,
1724
+ firstItem.userId ?? "",
1725
+ firstItem.identity?.userName ?? "",
1726
+ firstItem.identity?.agentName ?? "",
1727
+ hasWaiting,
1728
+ messageCenterStackPreviewText(firstItem)
1729
+ ].join(":");
1940
1730
  }
1941
- function MessageCenterIdentityAvatarMark({
1942
- identity,
1943
- provider,
1944
- userId
1731
+ function useBatchedMessageCenterStackItems({
1732
+ expanded,
1733
+ highlightedItemId,
1734
+ items,
1735
+ mounted
1945
1736
  }) {
1946
- "use memo";
1947
- const userName = identity?.userName.trim() || userId?.trim() || "";
1948
- if (!userName) {
1949
- return /* @__PURE__ */ jsx2(
1950
- "img",
1951
- {
1952
- src: managedAgentRoundedIconUrl(provider),
1953
- alt: "",
1954
- className: "size-5 shrink-0 rounded-full",
1955
- decoding: "async",
1956
- loading: "lazy",
1957
- draggable: false,
1958
- "aria-hidden": "true"
1959
- }
1737
+ const limit = items.length;
1738
+ const highlightedIndex = highlightedItemId === null || highlightedItemId === void 0 ? -1 : items.findIndex((item) => item.id === highlightedItemId);
1739
+ const initialCount = Math.min(
1740
+ limit,
1741
+ Math.max(MESSAGE_CENTER_STACK_INITIAL_RENDER_COUNT, highlightedIndex + 1)
1742
+ );
1743
+ const [renderCount, setRenderCount] = useState2(initialCount);
1744
+ useEffect2(() => {
1745
+ if (!mounted) {
1746
+ setRenderCount(initialCount);
1747
+ return;
1748
+ }
1749
+ setRenderCount(
1750
+ (current) => Math.min(Math.max(current, initialCount), limit)
1960
1751
  );
1961
- }
1962
- return /* @__PURE__ */ jsx2(
1963
- MessageCenterIdentityAvatarStack,
1964
- {
1965
- userAvatarUrl: identity?.userAvatarUrl,
1966
- userName,
1967
- agentAvatarUrl: identity?.agentAvatarUrl?.trim() || managedAgentRoundedIconUrl(provider)
1752
+ }, [initialCount, limit, mounted]);
1753
+ useEffect2(() => {
1754
+ if (!expanded || !mounted || renderCount >= limit) {
1755
+ return void 0;
1968
1756
  }
1969
- );
1757
+ const timeoutId = window.setTimeout(() => {
1758
+ setRenderCount(
1759
+ (current) => Math.min(current + MESSAGE_CENTER_STACK_RENDER_BATCH_SIZE, limit)
1760
+ );
1761
+ }, MESSAGE_CENTER_STACK_RENDER_BATCH_DELAY_MS);
1762
+ return () => {
1763
+ window.clearTimeout(timeoutId);
1764
+ };
1765
+ }, [expanded, limit, mounted, renderCount]);
1766
+ return items.slice(0, Math.min(renderCount, limit));
1970
1767
  }
1971
- function MessageCenterIdentityAvatarStack({
1972
- agentAvatarUrl,
1973
- userAvatarUrl: rawUserAvatarUrl,
1974
- userName
1768
+ function MessageCenterStackSummary({
1769
+ groupId,
1770
+ items,
1771
+ onExpand
1975
1772
  }) {
1976
1773
  "use memo";
1977
- const [userAvatarFailed, setUserAvatarFailed] = useState(false);
1978
- const userAvatarUrl = rawUserAvatarUrl?.trim() ?? "";
1979
- const userImageUrl = userAvatarUrl.length > 0 && !userAvatarFailed ? userAvatarUrl : userAvatarPlaceholderUrl;
1980
- useEffect(() => {
1981
- setUserAvatarFailed(false);
1982
- }, [userAvatarUrl]);
1983
- return /* @__PURE__ */ jsxs(
1984
- "span",
1985
- {
1986
- className: "workspace-agent-message-center__identity-avatar-stack inline-flex w-9 shrink-0 items-center",
1987
- "aria-hidden": "true",
1988
- children: [
1989
- /* @__PURE__ */ jsx2("span", { className: "inline-flex size-5 shrink-0 overflow-hidden rounded-full bg-[var(--transparency-block)] ring-2 ring-[var(--background-fronted)]", children: /* @__PURE__ */ jsx2(
1990
- "img",
1991
- {
1992
- src: userImageUrl,
1993
- alt: userName,
1994
- className: "size-full object-cover",
1995
- decoding: "async",
1996
- loading: "lazy",
1997
- referrerPolicy: "no-referrer",
1998
- draggable: false,
1999
- onError: () => {
2000
- setUserAvatarFailed(true);
2001
- }
2002
- }
2003
- ) }),
2004
- /* @__PURE__ */ jsx2("span", { className: "-ml-1.5 inline-flex size-5 shrink-0 overflow-hidden rounded-full bg-[var(--transparency-block)] ring-2 ring-[var(--background-fronted)]", children: /* @__PURE__ */ jsx2(
2005
- "img",
2006
- {
2007
- src: agentAvatarUrl,
2008
- alt: "",
2009
- className: "size-full object-cover",
2010
- decoding: "async",
2011
- loading: "lazy",
2012
- draggable: false
2013
- }
2014
- ) })
2015
- ]
2016
- }
2017
- );
2018
- }
2019
- function ProjectPathInfo({ path }) {
2020
- "use memo";
2021
- return /* @__PURE__ */ jsx2(
2022
- LazyMessageCenterTooltip,
1774
+ const { t } = useTranslation();
1775
+ const firstItem = items[0];
1776
+ const hasWaiting = items.some((item) => isWaitingMessageCenterItem(item));
1777
+ if (!firstItem) {
1778
+ return null;
1779
+ }
1780
+ return /* @__PURE__ */ jsx4(
1781
+ "button",
2023
1782
  {
2024
- content: path,
2025
- side: "top",
2026
- align: "start",
2027
- className: "max-w-[320px] text-[11px] [overflow-wrap:anywhere]",
2028
- children: /* @__PURE__ */ jsx2(
2029
- "button",
1783
+ type: "button",
1784
+ "aria-label": t("agentHost.workspaceAgentMessageCenterExpandStackAria", {
1785
+ count: items.length
1786
+ }),
1787
+ className: cn3(
1788
+ "group/stack-peek relative block w-full min-w-0 rounded-lg text-left outline-none focus-visible:ring-2 focus-visible:ring-[var(--accent)]",
1789
+ items.length > 2 ? "pb-[18px]" : "pb-[10px]"
1790
+ ),
1791
+ "data-stack-summary-count": items.length,
1792
+ "data-stack-provider": firstItem.provider,
1793
+ "data-stack-user-id": firstItem.userId ?? "",
1794
+ "data-testid": `workspace-agent-message-stack-summary-${groupId}`,
1795
+ onClick: () => onExpand(groupId),
1796
+ children: /* @__PURE__ */ jsxs3(
1797
+ "span",
2030
1798
  {
2031
- type: "button",
2032
- 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",
2033
- "aria-label": path,
2034
- children: /* @__PURE__ */ jsx2(Info, { className: "size-3.5", strokeWidth: 2, "aria-hidden": "true" })
1799
+ className: cn3(
1800
+ "relative z-10 flex min-w-0 flex-col gap-2 rounded-lg border border-[var(--line-2)] bg-[var(--background-fronted)] p-3.5 transition-[background-color,border-color] duration-200 group-hover/stack-peek:bg-[var(--transparency-hover)]",
1801
+ items.length > 2 ? "shadow-[0_7px_0_-4px_var(--background-fronted),0_7px_0_-3px_var(--line-2),0_14px_0_-8px_var(--background-fronted),0_14px_0_-7px_var(--line-2)]" : "shadow-[0_7px_0_-4px_var(--background-fronted),0_7px_0_-3px_var(--line-2)]",
1802
+ hasWaiting && "border-[var(--tutti-purple-border)] bg-[var(--tutti-purple-bg)]"
1803
+ ),
1804
+ children: [
1805
+ /* @__PURE__ */ jsxs3("span", { className: "flex min-w-0 items-center justify-between gap-2.5", children: [
1806
+ /* @__PURE__ */ jsxs3("span", { className: "flex min-w-0 items-center gap-2", children: [
1807
+ /* @__PURE__ */ jsx4(
1808
+ MessageCenterIdentityAvatarMark,
1809
+ {
1810
+ identity: firstItem.identity,
1811
+ provider: firstItem.provider,
1812
+ userId: firstItem.userId
1813
+ }
1814
+ ),
1815
+ /* @__PURE__ */ jsx4("span", { className: "min-w-0 truncate text-[13px] font-bold leading-5 text-[var(--text-secondary)]", children: t("agentHost.workspaceAgentMessageCenterStackSummaryCount", {
1816
+ count: items.length
1817
+ }) })
1818
+ ] }),
1819
+ /* @__PURE__ */ jsx4(
1820
+ ChevronDown,
1821
+ {
1822
+ className: "size-4 shrink-0 text-[var(--text-tertiary)] transition-transform duration-200 group-hover/stack-peek:translate-y-0.5 motion-reduce:transition-none",
1823
+ "aria-hidden": "true"
1824
+ }
1825
+ )
1826
+ ] }),
1827
+ /* @__PURE__ */ jsx4("span", { className: "min-w-0 rounded-md bg-transparency-block p-2.5 text-[13px] leading-[1.45] text-[var(--text-primary)]", children: /* @__PURE__ */ jsx4("span", { className: "line-clamp-2 min-w-0 [overflow-wrap:anywhere]", children: messageCenterStackPreviewNodes(firstItem) }) })
1828
+ ]
2035
1829
  }
2036
1830
  )
2037
1831
  }
2038
1832
  );
2039
1833
  }
2040
- function LazyMessageCenterTooltip({
2041
- align,
2042
- children,
2043
- className,
2044
- content,
2045
- side
1834
+ function messageCenterVisibleSummary(item) {
1835
+ const summary = item.digest.primary.summary.trim();
1836
+ if (item.pendingPrompt?.kind === "approval" && isGenericApprovalSummary(summary)) {
1837
+ return "";
1838
+ }
1839
+ return summary;
1840
+ }
1841
+ function isGenericApprovalSummary(summary) {
1842
+ const normalized = summary.trim().toLowerCase();
1843
+ return normalized === "approval";
1844
+ }
1845
+ function MessageCenterSummary({
1846
+ emptyLabel,
1847
+ item,
1848
+ lazy,
1849
+ onLinkAction,
1850
+ summary
2046
1851
  }) {
2047
1852
  "use memo";
2048
- const [hydrated, setHydrated] = useState(false);
2049
- const [open, setOpen] = useState(false);
2050
- const showTooltip = useCallback(() => {
2051
- setHydrated(true);
2052
- setOpen(true);
2053
- }, []);
2054
- const hideTooltip = useCallback(() => {
2055
- setOpen(false);
2056
- }, []);
2057
- const trigger = cloneElement(children, {
2058
- onBlur: (event) => {
2059
- children.props.onBlur?.(event);
2060
- hideTooltip();
2061
- },
2062
- onFocus: (event) => {
2063
- children.props.onFocus?.(event);
2064
- showTooltip();
2065
- },
2066
- onPointerEnter: (event) => {
2067
- children.props.onPointerEnter?.(event);
2068
- showTooltip();
1853
+ const summaryRef = useRef(null);
1854
+ const [isOverflowing, setIsOverflowing] = useState2(false);
1855
+ const shouldRenderRichSummary = useLazyMessageCenterSummaryReady(
1856
+ summaryRef,
1857
+ lazy
1858
+ );
1859
+ const shouldMeasureOverflow = useDeferredMessageCenterSummaryMeasureReady(
1860
+ summaryRef,
1861
+ shouldRenderRichSummary
1862
+ );
1863
+ const handleLinkAction = useCallback2(
1864
+ (action) => {
1865
+ const agentTargetId = item.agentTargetId?.trim() || null;
1866
+ onLinkAction?.(
1867
+ action.type === "open-agent-session" && !action.agentTargetId && agentTargetId ? { ...action, agentTargetId } : action
1868
+ );
2069
1869
  },
2070
- onPointerLeave: (event) => {
2071
- children.props.onPointerLeave?.(event);
2072
- hideTooltip();
1870
+ [item.agentTargetId, onLinkAction]
1871
+ );
1872
+ useEffect2(() => {
1873
+ if (!shouldMeasureOverflow) {
1874
+ setIsOverflowing(false);
1875
+ return void 0;
2073
1876
  }
2074
- });
2075
- if (!hydrated) {
2076
- return trigger;
2077
- }
2078
- return /* @__PURE__ */ jsxs(Tooltip, { open, onOpenChange: setOpen, children: [
2079
- /* @__PURE__ */ jsx2(TooltipTrigger, { asChild: true, children: trigger }),
2080
- /* @__PURE__ */ jsx2(TooltipContent, { side, align, className, children: content })
2081
- ] });
2082
- }
2083
- function AgentProviderLabel({ provider }) {
2084
- "use memo";
2085
- const label = workspaceAgentProviderLabel(provider);
2086
- return /* @__PURE__ */ jsxs("span", { className: "workspace-agent-message-center__provider inline-flex min-w-0 max-w-full items-center gap-1.5", children: [
2087
- /* @__PURE__ */ jsx2(
2088
- "img",
2089
- {
2090
- src: managedAgentRoundedIconUrl(provider),
2091
- alt: "",
2092
- className: "workspace-agent-message-center__provider-icon size-5 shrink-0 rounded-full",
2093
- decoding: "async",
2094
- loading: "lazy",
2095
- draggable: false,
2096
- "aria-hidden": "true"
2097
- }
2098
- ),
2099
- /* @__PURE__ */ jsx2("span", { className: "workspace-agent-message-center__provider-name min-w-0 truncate text-[13px] leading-5 text-[var(--text-secondary)]", children: label })
2100
- ] });
2101
- }
2102
- function statusClass(item) {
2103
- if (isWaitingMessageCenterItem(item)) {
2104
- return "waiting";
2105
- }
2106
- if (item.status === "idle") {
2107
- return "completed";
2108
- }
2109
- return item.status;
1877
+ const element = summaryRef.current;
1878
+ if (!element) {
1879
+ return void 0;
1880
+ }
1881
+ const updateOverflowState = () => {
1882
+ setIsOverflowing(element.scrollHeight > element.clientHeight + 1);
1883
+ };
1884
+ let resizeObserver = null;
1885
+ const timeoutId = window.setTimeout(() => {
1886
+ updateOverflowState();
1887
+ resizeObserver = new ResizeObserver(updateOverflowState);
1888
+ resizeObserver.observe(element);
1889
+ }, MESSAGE_CENTER_SUMMARY_OVERFLOW_MEASURE_DELAY_MS);
1890
+ return () => {
1891
+ window.clearTimeout(timeoutId);
1892
+ resizeObserver?.disconnect();
1893
+ };
1894
+ }, [shouldMeasureOverflow, summary]);
1895
+ return /* @__PURE__ */ jsx4(
1896
+ AgentVerticalScrollArea,
1897
+ {
1898
+ ref: summaryRef,
1899
+ className: cn3(
1900
+ "workspace-agent-message-center__summary workspace-agent-message-center__copy-text max-h-[160px] min-w-0 rounded-md bg-transparency-block text-[13px] leading-[1.45] text-[var(--text-primary)] [overflow-wrap:anywhere]",
1901
+ isOverflowing && "workspace-agent-message-center__summary--overflowing"
1902
+ ),
1903
+ viewportClassName: "workspace-agent-message-center__copy-text max-h-[160px] p-2.5 pr-4",
1904
+ onPointerDown: stopMessageCenterTextPointerPropagation,
1905
+ scrollbarClassName: "top-2 bottom-2 right-1.5",
1906
+ syncKey: summary,
1907
+ children: summary && shouldRenderRichSummary ? /* @__PURE__ */ jsx4(
1908
+ AgentMessageMarkdown,
1909
+ {
1910
+ content: summary,
1911
+ className: "[&_a]:text-[var(--tutti-purple)] [&_code]:text-[var(--text-secondary)] [&_hr]:border-t-[color-mix(in_srgb,var(--text-primary)_14%,transparent)] [&_ol]:!bg-transparent [&_p]:m-0 [&_th]:bg-[color-mix(in_srgb,var(--background-panel)_94%,var(--text-primary))] [&_th]:text-[var(--text-primary)] [&_ul]:!bg-transparent text-[var(--text-primary)]",
1912
+ onLinkAction: handleLinkAction,
1913
+ workspaceLinkContext: {
1914
+ workspaceRoot: item.cwd || null,
1915
+ basePath: item.cwd,
1916
+ source: "agent-markdown"
1917
+ },
1918
+ enableImageZoom: true
1919
+ }
1920
+ ) : summary ? /* @__PURE__ */ jsx4("div", { className: "whitespace-pre-wrap [overflow-wrap:anywhere]", children: summary }) : emptyLabel
1921
+ }
1922
+ );
2110
1923
  }
2111
- function messageCenterStatusTone(item) {
2112
- if (isWaitingMessageCenterItem(item)) {
2113
- return "amber";
2114
- }
2115
- if (item.status === "completed" || item.status === "idle") {
2116
- return "green";
2117
- }
2118
- if (item.status === "canceled") {
2119
- return "amber";
2120
- }
2121
- if (item.status === "failed") {
2122
- return "red";
2123
- }
2124
- if (item.status === "working") {
2125
- return "blue";
2126
- }
2127
- return "neutral";
1924
+ function useLazyMessageCenterSummaryReady(ref, lazy) {
1925
+ const [ready, setReady] = useState2(!lazy);
1926
+ useEffect2(() => {
1927
+ setReady(!lazy);
1928
+ }, [lazy]);
1929
+ useEffect2(() => {
1930
+ if (!lazy) {
1931
+ return void 0;
1932
+ }
1933
+ if (ready) {
1934
+ return void 0;
1935
+ }
1936
+ const element = ref.current;
1937
+ if (!element || typeof IntersectionObserver === "undefined") {
1938
+ setReady(true);
1939
+ return void 0;
1940
+ }
1941
+ const observer = new IntersectionObserver(
1942
+ (entries) => {
1943
+ if (entries.some((entry) => entry.isIntersecting)) {
1944
+ setReady(true);
1945
+ observer.disconnect();
1946
+ }
1947
+ },
1948
+ { rootMargin: MESSAGE_CENTER_SUMMARY_LAZY_ROOT_MARGIN }
1949
+ );
1950
+ observer.observe(element);
1951
+ return () => observer.disconnect();
1952
+ }, [lazy, ready, ref]);
1953
+ return ready;
2128
1954
  }
2129
- function messageCenterStatusToneClass(tone) {
2130
- switch (tone) {
2131
- case "amber":
2132
- return "text-[var(--state-warning)]";
2133
- case "blue":
2134
- return "text-[var(--status-running)]";
2135
- case "green":
2136
- return "text-[var(--state-success)]";
2137
- case "red":
2138
- return "text-[var(--state-danger)]";
2139
- case "neutral":
2140
- return "text-[var(--text-secondary)]";
2141
- }
1955
+ function useDeferredMessageCenterSummaryMeasureReady(ref, enabled) {
1956
+ const [ready, setReady] = useState2(false);
1957
+ useEffect2(() => {
1958
+ if (!enabled) {
1959
+ setReady(false);
1960
+ return void 0;
1961
+ }
1962
+ if (ready) {
1963
+ return void 0;
1964
+ }
1965
+ const element = ref.current;
1966
+ if (!element || typeof IntersectionObserver === "undefined") {
1967
+ const timeoutId2 = window.setTimeout(
1968
+ () => setReady(true),
1969
+ MESSAGE_CENTER_SUMMARY_OVERFLOW_MEASURE_DELAY_MS
1970
+ );
1971
+ return () => {
1972
+ window.clearTimeout(timeoutId2);
1973
+ };
1974
+ }
1975
+ let timeoutId = null;
1976
+ const observer = new IntersectionObserver(
1977
+ (entries) => {
1978
+ if (!entries.some((entry) => entry.isIntersecting)) {
1979
+ return;
1980
+ }
1981
+ observer.disconnect();
1982
+ timeoutId = window.setTimeout(
1983
+ () => setReady(true),
1984
+ MESSAGE_CENTER_SUMMARY_OVERFLOW_MEASURE_DELAY_MS
1985
+ );
1986
+ },
1987
+ { rootMargin: MESSAGE_CENTER_SUMMARY_LAZY_ROOT_MARGIN }
1988
+ );
1989
+ observer.observe(element);
1990
+ return () => {
1991
+ observer.disconnect();
1992
+ if (timeoutId !== null) {
1993
+ window.clearTimeout(timeoutId);
1994
+ }
1995
+ };
1996
+ }, [enabled, ready, ref]);
1997
+ return ready;
2142
1998
  }
2143
1999
 
2144
2000
  // agent-message-center/WorkspaceAgentMessageCenterAttentionDeck.tsx
2145
- import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
2001
+ import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
2146
2002
  var DECK_MAX_PEEK = 2;
2147
2003
  var DECK_NEW_CARD_COOLDOWN_MS = 500;
2148
2004
  var DECK_LEAVE_ANIMATION_FALLBACK_MS = 420;
2149
2005
  function WorkspaceAgentMessageCenterAttentionDeck({
2150
2006
  items,
2151
2007
  highlightedItemId = null,
2152
- submittingPromptKey,
2008
+ isPromptSubmitting,
2153
2009
  registerNode,
2154
2010
  renderCard,
2155
2011
  onLinkAction,
@@ -2165,10 +2021,10 @@ function WorkspaceAgentMessageCenterAttentionDeck({
2165
2021
  const topRequestId = ordered[0]?.pendingPrompt?.requestId ?? null;
2166
2022
  const topPromotedByHighlight = ordered[0]?.id === highlightedItemId && highlightedItemId !== null;
2167
2023
  const previousTopRequestIdRef = useRef2(null);
2168
- const [cooldownRequestId, setCooldownRequestId] = useState2(
2024
+ const [cooldownRequestId, setCooldownRequestId] = useState3(
2169
2025
  null
2170
2026
  );
2171
- useEffect2(() => {
2027
+ useEffect3(() => {
2172
2028
  const previousTopRequestId = previousTopRequestIdRef.current;
2173
2029
  previousTopRequestIdRef.current = topRequestId;
2174
2030
  if (!topRequestId || topPromotedByHighlight || previousTopRequestId === null || previousTopRequestId === topRequestId) {
@@ -2188,8 +2044,8 @@ function WorkspaceAgentMessageCenterAttentionDeck({
2188
2044
  const previousTopItemRef = useRef2(
2189
2045
  null
2190
2046
  );
2191
- const [leavingItem, setLeavingItem] = useState2(null);
2192
- useEffect2(() => {
2047
+ const [leavingItem, setLeavingItem] = useState3(null);
2048
+ useEffect3(() => {
2193
2049
  const previousTopItem = previousTopItemRef.current;
2194
2050
  previousTopItemRef.current = ordered[0] ?? null;
2195
2051
  if (previousTopItem && previousTopItem.id !== (ordered[0]?.id ?? null) && !items.some((item) => item.id === previousTopItem.id)) {
@@ -2210,23 +2066,23 @@ function WorkspaceAgentMessageCenterAttentionDeck({
2210
2066
  return null;
2211
2067
  }
2212
2068
  const peekCount = Math.min(ordered.length - 1, DECK_MAX_PEEK);
2213
- const topIsSubmitting = submittingPromptKey === `${topItem.agentSessionId}:${topItem.pendingPrompt?.requestId}`;
2214
- return /* @__PURE__ */ jsxs2(
2069
+ const topIsSubmitting = isPromptSubmitting(topItem);
2070
+ return /* @__PURE__ */ jsxs4(
2215
2071
  "section",
2216
2072
  {
2217
2073
  className: "flex min-w-0 flex-col gap-2.5",
2218
2074
  "aria-label": t("agentHost.workspaceAgentMessageCenterGroupNeedsAttention"),
2219
2075
  children: [
2220
- /* @__PURE__ */ jsx3("div", { className: "flex min-w-0 items-center justify-between gap-3 px-0.5", children: /* @__PURE__ */ jsxs2("div", { className: "truncate text-xs font-bold leading-4 text-[var(--text-tertiary)]", children: [
2076
+ /* @__PURE__ */ jsx5("div", { className: "flex min-w-0 items-center justify-between gap-3 px-0.5", children: /* @__PURE__ */ jsxs4("div", { className: "truncate text-xs font-bold leading-4 text-[var(--text-tertiary)]", children: [
2221
2077
  t("agentHost.workspaceAgentMessageCenterGroupNeedsAttention"),
2222
2078
  " \xB7",
2223
2079
  " ",
2224
2080
  ordered.length
2225
2081
  ] }) }),
2226
- /* @__PURE__ */ jsxs2(
2082
+ /* @__PURE__ */ jsxs4(
2227
2083
  "div",
2228
2084
  {
2229
- className: cn3(
2085
+ className: cn4(
2230
2086
  "relative min-w-0",
2231
2087
  peekCount > 1 ? "pb-[18px]" : peekCount > 0 && "pb-[10px]"
2232
2088
  ),
@@ -2235,7 +2091,7 @@ function WorkspaceAgentMessageCenterAttentionDeck({
2235
2091
  "data-deck-peek-count": peekCount,
2236
2092
  "data-deck-top-item-id": topItem.id,
2237
2093
  children: [
2238
- leavingItem ? /* @__PURE__ */ jsx3(
2094
+ leavingItem ? /* @__PURE__ */ jsx5(
2239
2095
  "div",
2240
2096
  {
2241
2097
  "aria-hidden": "true",
@@ -2256,7 +2112,7 @@ function WorkspaceAgentMessageCenterAttentionDeck({
2256
2112
  item: leavingItem,
2257
2113
  onSubmitPrompt: () => {
2258
2114
  }
2259
- }) : /* @__PURE__ */ jsx3(
2115
+ }) : /* @__PURE__ */ jsx5(
2260
2116
  WorkspaceAgentMessageCenterCard,
2261
2117
  {
2262
2118
  interactive: false,
@@ -2270,10 +2126,10 @@ function WorkspaceAgentMessageCenterAttentionDeck({
2270
2126
  },
2271
2127
  `leaving-${leavingItem.agentSessionId}`
2272
2128
  ) : null,
2273
- /* @__PURE__ */ jsx3(
2129
+ /* @__PURE__ */ jsx5(
2274
2130
  "div",
2275
2131
  {
2276
- className: cn3(
2132
+ className: cn4(
2277
2133
  "relative min-w-0 rounded-lg motion-safe:animate-in motion-safe:fade-in-0 motion-safe:slide-in-from-top-1 motion-safe:duration-300 motion-reduce:animate-none",
2278
2134
  peekCount > 1 ? "shadow-[0_7px_0_-4px_var(--background-fronted),0_7px_0_-3px_var(--line-2),0_14px_0_-8px_var(--background-fronted),0_14px_0_-7px_var(--line-2)]" : peekCount > 0 && "shadow-[0_7px_0_-4px_var(--background-fronted),0_7px_0_-3px_var(--line-2)]"
2279
2135
  ),
@@ -2284,7 +2140,7 @@ function WorkspaceAgentMessageCenterAttentionDeck({
2284
2140
  isSubmitting: topIsSubmitting || isTopCoolingDown,
2285
2141
  item: topItem,
2286
2142
  onSubmitPrompt: (input) => onSubmitPrompt(topItem, input)
2287
- }) : /* @__PURE__ */ jsx3(
2143
+ }) : /* @__PURE__ */ jsx5(
2288
2144
  WorkspaceAgentMessageCenterCard,
2289
2145
  {
2290
2146
  cardRef: registerNode ? (node) => registerNode(topItem.id, node) : void 0,
@@ -2323,8 +2179,8 @@ function orderDeckItems(items, highlightedItemId) {
2323
2179
  // agent-message-center/WorkspaceAgentMessageCenterViewControls.tsx
2324
2180
  import { ListFilter } from "lucide-react";
2325
2181
  import {
2326
- Button as Button2,
2327
- cn as cn4,
2182
+ Button as Button3,
2183
+ cn as cn5,
2328
2184
  DropdownMenu,
2329
2185
  DropdownMenuCheckboxItem,
2330
2186
  DropdownMenuContent,
@@ -2631,7 +2487,7 @@ function messageCenterTimeGroup(item) {
2631
2487
  }
2632
2488
 
2633
2489
  // agent-message-center/WorkspaceAgentMessageCenterViewControls.tsx
2634
- import { Fragment, jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
2490
+ import { Fragment, jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
2635
2491
  function MessageCenterViewMenu({
2636
2492
  filtersActive = false,
2637
2493
  groupBy,
@@ -2646,16 +2502,16 @@ function MessageCenterViewMenu({
2646
2502
  }) {
2647
2503
  "use memo";
2648
2504
  const { t } = useTranslation();
2649
- return /* @__PURE__ */ jsxs3(DropdownMenu, { modal: false, children: [
2650
- /* @__PURE__ */ jsx4(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs3(
2651
- Button2,
2505
+ return /* @__PURE__ */ jsxs5(DropdownMenu, { modal: false, children: [
2506
+ /* @__PURE__ */ jsx6(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs5(
2507
+ Button3,
2652
2508
  {
2653
2509
  type: "button",
2654
2510
  variant: "ghost",
2655
2511
  size: "icon",
2656
2512
  "aria-label": t("agentHost.workspaceAgentMessageCenterViewOptions"),
2657
2513
  title: t("agentHost.workspaceAgentMessageCenterViewOptions"),
2658
- className: cn4(
2514
+ className: cn5(
2659
2515
  "relative size-8 shrink-0 rounded-md border bg-[var(--background-fronted)] shadow-none",
2660
2516
  filtersActive ? "border-[var(--border-focus)] text-[var(--accent)]" : "border-[var(--line-2)] text-[var(--text-secondary)] hover:text-[var(--text-primary)]"
2661
2517
  ),
@@ -2666,8 +2522,8 @@ function MessageCenterViewMenu({
2666
2522
  event.stopPropagation();
2667
2523
  },
2668
2524
  children: [
2669
- /* @__PURE__ */ jsx4(ListFilter, { className: "size-4", strokeWidth: 2.1, "aria-hidden": "true" }),
2670
- filtersActive ? /* @__PURE__ */ jsx4(
2525
+ /* @__PURE__ */ jsx6(ListFilter, { className: "size-4", strokeWidth: 2.1, "aria-hidden": "true" }),
2526
+ filtersActive ? /* @__PURE__ */ jsx6(
2671
2527
  "span",
2672
2528
  {
2673
2529
  "aria-label": t(
@@ -2679,7 +2535,7 @@ function MessageCenterViewMenu({
2679
2535
  ]
2680
2536
  }
2681
2537
  ) }),
2682
- /* @__PURE__ */ jsxs3(
2538
+ /* @__PURE__ */ jsxs5(
2683
2539
  DropdownMenuContent,
2684
2540
  {
2685
2541
  align: "end",
@@ -2699,25 +2555,25 @@ function MessageCenterViewMenu({
2699
2555
  event.stopPropagation();
2700
2556
  },
2701
2557
  children: [
2702
- /* @__PURE__ */ jsx4(DropdownMenuLabel, { children: t("agentHost.workspaceAgentMessageCenterGroupBy") }),
2703
- /* @__PURE__ */ jsx4(
2558
+ /* @__PURE__ */ jsx6(DropdownMenuLabel, { children: t("agentHost.workspaceAgentMessageCenterGroupBy") }),
2559
+ /* @__PURE__ */ jsx6(
2704
2560
  DropdownMenuRadioGroup,
2705
2561
  {
2706
2562
  value: groupBy,
2707
2563
  onValueChange: (value) => onGroupByChange(value),
2708
- children: ["priority", "status", "agent", "time"].map((value) => /* @__PURE__ */ jsx4(DropdownMenuRadioItem, { value, children: messageCenterGroupLabel(value, t) }, value))
2564
+ children: ["priority", "status", "agent", "time"].map((value) => /* @__PURE__ */ jsx6(DropdownMenuRadioItem, { value, children: messageCenterGroupLabel(value, t) }, value))
2709
2565
  }
2710
2566
  ),
2711
- /* @__PURE__ */ jsx4(DropdownMenuSeparator, {}),
2712
- /* @__PURE__ */ jsx4(DropdownMenuLabel, { children: t("agentHost.workspaceAgentMessageCenterFilterStatus") }),
2713
- /* @__PURE__ */ jsx4(DropdownMenuGroup, { children: statusOptions.map((option) => /* @__PURE__ */ jsx4(
2567
+ /* @__PURE__ */ jsx6(DropdownMenuSeparator, {}),
2568
+ /* @__PURE__ */ jsx6(DropdownMenuLabel, { children: t("agentHost.workspaceAgentMessageCenterFilterStatus") }),
2569
+ /* @__PURE__ */ jsx6(DropdownMenuGroup, { children: statusOptions.map((option) => /* @__PURE__ */ jsx6(
2714
2570
  DropdownMenuCheckboxItem,
2715
2571
  {
2716
2572
  "aria-label": `${option.label} ${option.count}`,
2717
2573
  checked: statusFilters === null || statusFilters.has(option.value),
2718
2574
  onCheckedChange: () => onStatusToggle(option.value),
2719
2575
  onSelect: (event) => event.preventDefault(),
2720
- children: /* @__PURE__ */ jsx4(
2576
+ children: /* @__PURE__ */ jsx6(
2721
2577
  MessageCenterOptionWithCount,
2722
2578
  {
2723
2579
  count: option.count,
@@ -2727,17 +2583,17 @@ function MessageCenterViewMenu({
2727
2583
  },
2728
2584
  option.value
2729
2585
  )) }),
2730
- providerOptions.length > 0 ? /* @__PURE__ */ jsxs3(Fragment, { children: [
2731
- /* @__PURE__ */ jsx4(DropdownMenuSeparator, {}),
2732
- /* @__PURE__ */ jsx4(DropdownMenuLabel, { children: t("agentHost.workspaceAgentMessageCenterFilterAgent") }),
2733
- /* @__PURE__ */ jsx4(DropdownMenuGroup, { children: providerOptions.map((option) => /* @__PURE__ */ jsx4(
2586
+ providerOptions.length > 0 ? /* @__PURE__ */ jsxs5(Fragment, { children: [
2587
+ /* @__PURE__ */ jsx6(DropdownMenuSeparator, {}),
2588
+ /* @__PURE__ */ jsx6(DropdownMenuLabel, { children: t("agentHost.workspaceAgentMessageCenterFilterAgent") }),
2589
+ /* @__PURE__ */ jsx6(DropdownMenuGroup, { children: providerOptions.map((option) => /* @__PURE__ */ jsx6(
2734
2590
  DropdownMenuCheckboxItem,
2735
2591
  {
2736
2592
  "aria-label": `${option.label} ${option.count}`,
2737
2593
  checked: providerFilters === null || providerFilters.has(option.value),
2738
2594
  onCheckedChange: () => onProviderToggle(option.value),
2739
2595
  onSelect: (event) => event.preventDefault(),
2740
- children: /* @__PURE__ */ jsx4(
2596
+ children: /* @__PURE__ */ jsx6(
2741
2597
  MessageCenterOptionWithCount,
2742
2598
  {
2743
2599
  count: option.count,
@@ -2748,8 +2604,8 @@ function MessageCenterViewMenu({
2748
2604
  option.value
2749
2605
  )) })
2750
2606
  ] }) : null,
2751
- /* @__PURE__ */ jsx4(DropdownMenuSeparator, {}),
2752
- /* @__PURE__ */ jsx4(DropdownMenuGroup, { children: /* @__PURE__ */ jsx4(DropdownMenuItem, { onClick: onClearFilters, children: t("agentHost.workspaceAgentMessageCenterClearFilters") }) })
2607
+ /* @__PURE__ */ jsx6(DropdownMenuSeparator, {}),
2608
+ /* @__PURE__ */ jsx6(DropdownMenuGroup, { children: /* @__PURE__ */ jsx6(DropdownMenuItem, { onClick: onClearFilters, children: t("agentHost.workspaceAgentMessageCenterClearFilters") }) })
2753
2609
  ]
2754
2610
  }
2755
2611
  )
@@ -2759,12 +2615,97 @@ function MessageCenterOptionWithCount({
2759
2615
  count,
2760
2616
  label
2761
2617
  }) {
2762
- return /* @__PURE__ */ jsxs3("span", { className: "flex min-w-0 flex-1 items-center gap-3", children: [
2763
- /* @__PURE__ */ jsx4("span", { className: "min-w-0 flex-1 truncate", children: label }),
2764
- /* @__PURE__ */ jsx4("span", { className: "shrink-0 tabular-nums text-[11px] text-[var(--text-tertiary)]", children: count })
2618
+ return /* @__PURE__ */ jsxs5("span", { className: "flex min-w-0 flex-1 items-center gap-3", children: [
2619
+ /* @__PURE__ */ jsx6("span", { className: "min-w-0 flex-1 truncate", children: label }),
2620
+ /* @__PURE__ */ jsx6("span", { className: "shrink-0 tabular-nums text-[11px] text-[var(--text-tertiary)]", children: count })
2765
2621
  ] });
2766
2622
  }
2767
2623
 
2624
+ // agent-message-center/WorkspaceAgentMessageCenterGroupHeading.tsx
2625
+ import { cn as cn6, StatusDot as StatusDot2 } from "@tutti-os/ui-system";
2626
+ import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
2627
+ function MessageCenterGroupHeading({
2628
+ group
2629
+ }) {
2630
+ "use memo";
2631
+ const statusSignal = messageCenterGroupStatusSignal(group.id);
2632
+ if (group.provider) {
2633
+ return /* @__PURE__ */ jsxs6(
2634
+ "h3",
2635
+ {
2636
+ "aria-label": `${group.label} \xB7 ${group.items.length}`,
2637
+ className: "flex min-w-0 items-center gap-1.5 text-[11px] font-normal leading-4 text-[var(--text-tertiary)]",
2638
+ title: `${group.label} \xB7 ${group.items.length}`,
2639
+ children: [
2640
+ group.identity ? /* @__PURE__ */ jsx7(
2641
+ MessageCenterIdentityLabel,
2642
+ {
2643
+ identity: group.identity,
2644
+ provider: group.provider
2645
+ }
2646
+ ) : /* @__PURE__ */ jsxs6("span", { className: "inline-flex min-w-0 items-center gap-1.5", children: [
2647
+ /* @__PURE__ */ jsx7(
2648
+ MessageCenterIdentityAvatarMark,
2649
+ {
2650
+ identity: null,
2651
+ provider: group.provider,
2652
+ userId: group.userId ?? null
2653
+ }
2654
+ ),
2655
+ /* @__PURE__ */ jsx7("span", { className: "min-w-0 truncate", children: group.label })
2656
+ ] }),
2657
+ /* @__PURE__ */ jsxs6("span", { className: "shrink-0", children: [
2658
+ "\xB7 ",
2659
+ group.items.length
2660
+ ] })
2661
+ ]
2662
+ }
2663
+ );
2664
+ }
2665
+ return /* @__PURE__ */ jsxs6(
2666
+ "h3",
2667
+ {
2668
+ className: cn6(
2669
+ "flex min-w-0 items-center gap-1.5 text-[11px] font-normal leading-4",
2670
+ statusSignal ? messageCenterStatusToneClass(statusSignal.tone) : "text-[var(--text-tertiary)]"
2671
+ ),
2672
+ title: `${group.label} \xB7 ${group.items.length}`,
2673
+ children: [
2674
+ statusSignal ? /* @__PURE__ */ jsx7(
2675
+ StatusDot2,
2676
+ {
2677
+ tone: statusSignal.tone,
2678
+ pulse: statusSignal.pulse,
2679
+ size: "sm",
2680
+ title: group.label
2681
+ }
2682
+ ) : null,
2683
+ /* @__PURE__ */ jsxs6("span", { className: "min-w-0 truncate", children: [
2684
+ group.label,
2685
+ " \xB7 ",
2686
+ group.items.length
2687
+ ] })
2688
+ ]
2689
+ }
2690
+ );
2691
+ }
2692
+ function messageCenterGroupStatusSignal(groupId) {
2693
+ switch (groupId) {
2694
+ case "needs-attention":
2695
+ case "waiting":
2696
+ return { pulse: true, tone: "amber" };
2697
+ case "working":
2698
+ return { pulse: true, tone: "blue" };
2699
+ case "failed":
2700
+ return { pulse: false, tone: "red" };
2701
+ case "recently-completed":
2702
+ case "completed":
2703
+ return { pulse: false, tone: "green" };
2704
+ default:
2705
+ return null;
2706
+ }
2707
+ }
2708
+
2768
2709
  // agent-message-center/messageCenterFilterPreferences.ts
2769
2710
  var messageCenterFiltersStorageKey = "tutti.agent-message-center.filters";
2770
2711
  var messageCenterGroupByValues = /* @__PURE__ */ new Set([
@@ -2850,7 +2791,7 @@ function resolveStoredProviderFilters(value) {
2850
2791
  }
2851
2792
 
2852
2793
  // agent-message-center/WorkspaceAgentMessageCenterPanel.tsx
2853
- import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
2794
+ import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
2854
2795
  var MESSAGE_CENTER_TOOLTIP_DELAY_MS = 300;
2855
2796
  var MESSAGE_CENTER_STACK_EAGER_SUMMARY_COUNT = 8;
2856
2797
  var WorkspaceAgentMessageCenterPanel = memo2(
@@ -2861,29 +2802,33 @@ var WorkspaceAgentMessageCenterPanel = memo2(
2861
2802
  model,
2862
2803
  highlightedItemId = null,
2863
2804
  portalContainer = null,
2805
+ presentation = "drawer",
2864
2806
  onClose,
2865
2807
  onHighlightedItemSettled,
2866
2808
  onLinkAction,
2867
2809
  onNotificationActioned,
2868
2810
  onOpenChat,
2811
+ promptStatus = () => "idle",
2869
2812
  onSubmitPrompt
2870
2813
  }) {
2871
2814
  "use memo";
2872
2815
  if (!open) {
2873
2816
  return null;
2874
2817
  }
2875
- return /* @__PURE__ */ jsx5(AgentGuiI18nProvider, { runtime: i18n, locale, children: /* @__PURE__ */ jsx5(
2818
+ return /* @__PURE__ */ jsx8(AgentGuiI18nProvider, { runtime: i18n, locale, children: /* @__PURE__ */ jsx8(
2876
2819
  WorkspaceAgentMessageCenterPanelContent,
2877
2820
  {
2878
2821
  open,
2879
2822
  model,
2880
2823
  highlightedItemId,
2881
2824
  portalContainer,
2825
+ presentation,
2882
2826
  onClose,
2883
2827
  onHighlightedItemSettled,
2884
2828
  onLinkAction,
2885
2829
  onNotificationActioned,
2886
2830
  onOpenChat,
2831
+ promptStatus,
2887
2832
  onSubmitPrompt
2888
2833
  }
2889
2834
  ) });
@@ -2894,38 +2839,37 @@ function WorkspaceAgentMessageCenterPanelContent({
2894
2839
  model,
2895
2840
  highlightedItemId = null,
2896
2841
  portalContainer = null,
2842
+ presentation = "drawer",
2897
2843
  onClose,
2898
2844
  onHighlightedItemSettled,
2899
2845
  onLinkAction,
2900
2846
  onNotificationActioned,
2901
2847
  onOpenChat,
2848
+ promptStatus = () => "idle",
2902
2849
  onSubmitPrompt
2903
2850
  }) {
2904
2851
  "use memo";
2905
2852
  const { t } = useTranslation();
2906
- const [initialFilters] = useState3(readMessageCenterFilterPreferences);
2907
- const [groupBy, setGroupBy] = useState3(
2853
+ const [initialFilters] = useState4(readMessageCenterFilterPreferences);
2854
+ const [groupBy, setGroupBy] = useState4(
2908
2855
  initialFilters.groupBy
2909
2856
  );
2910
- const [statusFilters, setStatusFilters] = useState3(
2857
+ const [statusFilters, setStatusFilters] = useState4(
2911
2858
  initialFilters.statusFilters
2912
2859
  );
2913
- const [providerFilters, setProviderFilters] = useState3(
2860
+ const [providerFilters, setProviderFilters] = useState4(
2914
2861
  initialFilters.providerFilters
2915
2862
  );
2916
- useEffect3(() => {
2863
+ useEffect4(() => {
2917
2864
  writeMessageCenterFilterPreferences({
2918
2865
  groupBy,
2919
2866
  statusFilters,
2920
2867
  providerFilters
2921
2868
  });
2922
2869
  }, [groupBy, statusFilters, providerFilters]);
2923
- const [expandedStackIds, setExpandedStackIds] = useState3(
2870
+ const [expandedStackIds, setExpandedStackIds] = useState4(
2924
2871
  () => /* @__PURE__ */ new Set()
2925
2872
  );
2926
- const [submittingPromptKey, setSubmittingPromptKey] = useState3(
2927
- null
2928
- );
2929
2873
  const itemNodesRef = useRef3(/* @__PURE__ */ new Map());
2930
2874
  const lastScrolledHighlightedItemIdRef = useRef3(null);
2931
2875
  const lastFilterResetHighlightedItemIdRef = useRef3(null);
@@ -3020,35 +2964,27 @@ function WorkspaceAgentMessageCenterPanelContent({
3020
2964
  t,
3021
2965
  visibleItems.length
3022
2966
  ]);
3023
- const submitPrompt = useCallback2(
2967
+ const submitPrompt = useCallback3(
3024
2968
  async (item, input) => {
3025
- const promptKey = `${item.agentSessionId}:${input.requestId}`;
3026
- setSubmittingPromptKey(promptKey);
3027
- try {
3028
- const notificationAction = resolveMessageCenterNotificationAction(
3029
- item,
3030
- input
3031
- );
3032
- if (notificationAction) {
3033
- onNotificationActioned?.({
3034
- action: notificationAction,
3035
- provider: item.provider
3036
- });
3037
- }
3038
- await onSubmitPrompt({
3039
- ...input,
3040
- agentSessionId: item.agentSessionId,
3041
- promptKind: item.pendingPrompt?.kind
2969
+ const notificationAction = resolveMessageCenterNotificationAction(
2970
+ item,
2971
+ input
2972
+ );
2973
+ if (notificationAction) {
2974
+ onNotificationActioned?.({
2975
+ action: notificationAction,
2976
+ provider: item.provider
3042
2977
  });
3043
- } finally {
3044
- setSubmittingPromptKey(
3045
- (current) => current === promptKey ? null : current
3046
- );
3047
2978
  }
2979
+ await onSubmitPrompt({
2980
+ ...input,
2981
+ agentSessionId: item.agentSessionId,
2982
+ promptKind: item.pendingPrompt?.kind
2983
+ });
3048
2984
  },
3049
2985
  [onNotificationActioned, onSubmitPrompt]
3050
2986
  );
3051
- const setItemNode = useCallback2(
2987
+ const setItemNode = useCallback3(
3052
2988
  (itemId, node) => {
3053
2989
  if (node) {
3054
2990
  itemNodesRef.current.set(itemId, node);
@@ -3058,7 +2994,7 @@ function WorkspaceAgentMessageCenterPanelContent({
3058
2994
  },
3059
2995
  []
3060
2996
  );
3061
- const toggleStatusFilter = useCallback2(
2997
+ const toggleStatusFilter = useCallback3(
3062
2998
  (status) => {
3063
2999
  setStatusFilters((current) => {
3064
3000
  const next = new Set(
@@ -3074,7 +3010,7 @@ function WorkspaceAgentMessageCenterPanelContent({
3074
3010
  },
3075
3011
  [statusOptions]
3076
3012
  );
3077
- const toggleProviderFilter = useCallback2(
3013
+ const toggleProviderFilter = useCallback3(
3078
3014
  (provider) => {
3079
3015
  setProviderFilters((current) => {
3080
3016
  const next = new Set(
@@ -3090,11 +3026,11 @@ function WorkspaceAgentMessageCenterPanelContent({
3090
3026
  },
3091
3027
  [providerOptions]
3092
3028
  );
3093
- const clearFilters = useCallback2(() => {
3029
+ const clearFilters = useCallback3(() => {
3094
3030
  setStatusFilters(null);
3095
3031
  setProviderFilters(null);
3096
3032
  }, []);
3097
- const expandStack = useCallback2((groupId) => {
3033
+ const expandStack = useCallback3((groupId) => {
3098
3034
  setExpandedStackIds((current) => {
3099
3035
  if (current.has(groupId)) {
3100
3036
  return current;
@@ -3104,7 +3040,7 @@ function WorkspaceAgentMessageCenterPanelContent({
3104
3040
  return next;
3105
3041
  });
3106
3042
  }, []);
3107
- const collapseStack = useCallback2((groupId) => {
3043
+ const collapseStack = useCallback3((groupId) => {
3108
3044
  setExpandedStackIds((current) => {
3109
3045
  if (!current.has(groupId)) {
3110
3046
  return current;
@@ -3176,7 +3112,7 @@ function WorkspaceAgentMessageCenterPanelContent({
3176
3112
  statusFilters,
3177
3113
  visibleItems
3178
3114
  ]);
3179
- useEffect3(() => {
3115
+ useEffect4(() => {
3180
3116
  if (!open || !highlightedItemId) {
3181
3117
  return void 0;
3182
3118
  }
@@ -3187,16 +3123,16 @@ function WorkspaceAgentMessageCenterPanelContent({
3187
3123
  window.clearTimeout(timeoutId);
3188
3124
  };
3189
3125
  }, [highlightedItemId, onHighlightedItemSettled, open]);
3190
- const renderMessageCenterCard = useCallback2(
3126
+ const renderMessageCenterCard = useCallback3(
3191
3127
  (item, options = {}) => {
3192
3128
  const highlighted = item.id === highlightedItemId;
3193
3129
  const stackedIndex = options.stackedIndex;
3194
- const card = /* @__PURE__ */ jsx5(
3130
+ const card = /* @__PURE__ */ jsx8(
3195
3131
  MessageCenterRenderedCard,
3196
3132
  {
3197
3133
  highlighted,
3198
3134
  item,
3199
- isSubmitting: submittingPromptKey === `${item.agentSessionId}:${item.pendingPrompt?.requestId}`,
3135
+ isSubmitting: promptStatus(item) === "responding" || promptStatus(item) === "unknown",
3200
3136
  lazySummary: stackedIndex !== void 0 && stackedIndex >= MESSAGE_CENTER_STACK_EAGER_SUMMARY_COUNT,
3201
3137
  registerNode: setItemNode,
3202
3138
  onLinkAction,
@@ -3208,7 +3144,7 @@ function WorkspaceAgentMessageCenterPanelContent({
3208
3144
  if (stackedIndex === void 0) {
3209
3145
  return card;
3210
3146
  }
3211
- return /* @__PURE__ */ jsx5(
3147
+ return /* @__PURE__ */ jsx8(
3212
3148
  "div",
3213
3149
  {
3214
3150
  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",
@@ -3224,12 +3160,122 @@ function WorkspaceAgentMessageCenterPanelContent({
3224
3160
  highlightedItemId,
3225
3161
  onLinkAction,
3226
3162
  onOpenChat,
3163
+ promptStatus,
3227
3164
  setItemNode,
3228
- submitPrompt,
3229
- submittingPromptKey
3165
+ submitPrompt
3230
3166
  ]
3231
3167
  );
3232
- return /* @__PURE__ */ jsx5(
3168
+ const panelContents = /* @__PURE__ */ jsxs7(TooltipProvider, { delayDuration: MESSAGE_CENTER_TOOLTIP_DELAY_MS, children: [
3169
+ /* @__PURE__ */ jsx8("div", { className: "flex-none border-b border-[var(--border-1)] px-3.5 pt-3 pb-3", children: /* @__PURE__ */ jsxs7("div", { className: "flex min-w-0 items-center justify-between gap-3", children: [
3170
+ presentation === "drawer" ? /* @__PURE__ */ jsxs7("div", { className: "min-w-0", children: [
3171
+ /* @__PURE__ */ jsx8(DrawerTitle, { className: "truncate text-[13px] font-semibold leading-5 text-[var(--text-primary)]", children: t("agentHost.workspaceAgentMessageCenterTitle") }),
3172
+ /* @__PURE__ */ jsx8(DrawerDescription, { className: "truncate text-[11px] leading-4 text-[var(--text-tertiary)]", children: headerSummary })
3173
+ ] }) : /* @__PURE__ */ jsx8("p", { className: "min-w-0 truncate text-[11px] leading-4 text-[var(--text-tertiary)]", children: headerSummary }),
3174
+ /* @__PURE__ */ jsx8(
3175
+ MessageCenterViewMenu,
3176
+ {
3177
+ filtersActive: hasActiveFilters,
3178
+ groupBy,
3179
+ providerFilters,
3180
+ providerOptions,
3181
+ statusFilters,
3182
+ statusOptions,
3183
+ onClearFilters: clearFilters,
3184
+ onGroupByChange: setGroupBy,
3185
+ onProviderToggle: toggleProviderFilter,
3186
+ onStatusToggle: toggleStatusFilter
3187
+ }
3188
+ )
3189
+ ] }) }),
3190
+ /* @__PURE__ */ jsx8(
3191
+ AgentVerticalScrollArea,
3192
+ {
3193
+ className: "min-h-0 flex-1",
3194
+ viewportClassName: "flex h-full w-full flex-col px-3.5 pt-4 pb-4",
3195
+ scrollbarClassName: "top-4 bottom-4",
3196
+ syncKey: scrollSyncKey,
3197
+ children: deckItems.length > 0 || listItems.length > 0 ? /* @__PURE__ */ jsxs7("div", { className: "flex w-full min-w-0 flex-col gap-4", children: [
3198
+ deckItems.length > 0 ? /* @__PURE__ */ jsx8(
3199
+ WorkspaceAgentMessageCenterAttentionDeck,
3200
+ {
3201
+ items: deckItems,
3202
+ highlightedItemId,
3203
+ isPromptSubmitting: (item) => promptStatus(item) === "responding" || promptStatus(item) === "unknown",
3204
+ registerNode: setItemNode,
3205
+ onLinkAction,
3206
+ onOpenChat,
3207
+ onSubmitPrompt: (item, input) => void submitPrompt(item, input)
3208
+ }
3209
+ ) : null,
3210
+ itemGroupStacks.map((group) => /* @__PURE__ */ jsxs7(
3211
+ "section",
3212
+ {
3213
+ className: "flex min-w-0 flex-col gap-2.5",
3214
+ "aria-label": `${group.label} ${group.items.length}`,
3215
+ children: [
3216
+ /* @__PURE__ */ jsx8("div", { className: "flex min-w-0 items-center justify-between gap-3 px-0.5", children: /* @__PURE__ */ jsx8(MessageCenterGroupHeading, { group }) }),
3217
+ (() => {
3218
+ return group.stacks.map((stack) => {
3219
+ const firstItem = stack.items[0];
3220
+ if (!firstItem) {
3221
+ return null;
3222
+ }
3223
+ if (stack.items.length === 1) {
3224
+ return renderMessageCenterCard(firstItem);
3225
+ }
3226
+ const stackId = messageCenterStackRenderId(
3227
+ group.id,
3228
+ stack.id
3229
+ );
3230
+ return /* @__PURE__ */ jsx8(
3231
+ MessageCenterStack,
3232
+ {
3233
+ expanded: expandedStackIds.has(stackId),
3234
+ groupId: stackId,
3235
+ highlightedItemId,
3236
+ items: stack.items,
3237
+ renderCard: renderMessageCenterCard,
3238
+ onCollapse: collapseStack,
3239
+ onExpand: expandStack
3240
+ },
3241
+ stackId
3242
+ );
3243
+ });
3244
+ })()
3245
+ ]
3246
+ },
3247
+ group.id
3248
+ ))
3249
+ ] }) : model.items.length > 0 ? /* @__PURE__ */ jsxs7("div", { className: "flex min-h-0 flex-1 flex-col items-center justify-center gap-2.5 px-6 py-8 text-center text-[13px] text-[var(--text-tertiary)]", children: [
3250
+ /* @__PURE__ */ jsx8("span", { children: t("agentHost.workspaceAgentMessageCenterFilteredEmpty") }),
3251
+ /* @__PURE__ */ jsx8(
3252
+ Button4,
3253
+ {
3254
+ type: "button",
3255
+ variant: "ghost",
3256
+ size: "sm",
3257
+ className: "border border-[var(--line-2)] bg-[var(--background-fronted)] text-[var(--text-secondary)] hover:text-[var(--text-primary)]",
3258
+ onClick: clearFilters,
3259
+ children: t("agentHost.workspaceAgentMessageCenterClearFilters")
3260
+ }
3261
+ )
3262
+ ] }) : /* @__PURE__ */ jsx8("div", { className: "flex min-h-0 flex-1 items-center justify-center px-6 py-8 text-center text-[13px] text-[var(--text-tertiary)]", children: t("agentHost.workspaceAgentMessageCenterEmpty") })
3263
+ }
3264
+ )
3265
+ ] });
3266
+ if (presentation === "embedded") {
3267
+ return /* @__PURE__ */ jsx8(
3268
+ "section",
3269
+ {
3270
+ "aria-label": t("agentHost.workspaceAgentMessageCenterTitle"),
3271
+ className: "t-modal nodrag flex h-full min-h-0 w-full flex-col overflow-hidden bg-[var(--background-panel)] text-[var(--text-primary)] [-webkit-app-region:no-drag]",
3272
+ "data-presentation": "embedded",
3273
+ "data-testid": "workspace-agent-message-center",
3274
+ children: panelContents
3275
+ }
3276
+ );
3277
+ }
3278
+ return /* @__PURE__ */ jsx8(
3233
3279
  Drawer,
3234
3280
  {
3235
3281
  open,
@@ -3240,115 +3286,19 @@ function WorkspaceAgentMessageCenterPanelContent({
3240
3286
  onClose();
3241
3287
  }
3242
3288
  },
3243
- children: /* @__PURE__ */ jsx5(
3289
+ children: /* @__PURE__ */ jsx8(
3244
3290
  DrawerContent,
3245
3291
  {
3246
- className: cn5(
3292
+ className: cn7(
3247
3293
  "t-modal nodrag min-h-0 w-[min(440px,calc(100vw-16px))] max-w-none overflow-hidden rounded-none border-y-0 border-r-0 bg-[var(--background-panel)] text-[var(--text-primary)] shadow-side-panel data-[vaul-drawer-direction=right]:rounded-none",
3248
3294
  "[-webkit-app-region:no-drag]"
3249
3295
  ),
3296
+ "data-presentation": "drawer",
3250
3297
  "data-testid": "workspace-agent-message-center",
3251
3298
  portalContainer: portalContainer ?? void 0,
3252
3299
  showOverlay: false,
3253
3300
  "aria-label": t("agentHost.workspaceAgentMessageCenterTitle"),
3254
- children: /* @__PURE__ */ jsxs4(TooltipProvider, { delayDuration: MESSAGE_CENTER_TOOLTIP_DELAY_MS, children: [
3255
- /* @__PURE__ */ jsx5("div", { className: "flex-none border-b border-[var(--border-1)] px-3.5 pt-3 pb-3", children: /* @__PURE__ */ jsxs4("div", { className: "flex min-w-0 items-center justify-between gap-3", children: [
3256
- /* @__PURE__ */ jsxs4("div", { className: "min-w-0", children: [
3257
- /* @__PURE__ */ jsx5(DrawerTitle, { className: "truncate text-[13px] font-semibold leading-5 text-[var(--text-primary)]", children: t("agentHost.workspaceAgentMessageCenterTitle") }),
3258
- /* @__PURE__ */ jsx5(DrawerDescription, { className: "truncate text-[11px] leading-4 text-[var(--text-tertiary)]", children: headerSummary })
3259
- ] }),
3260
- /* @__PURE__ */ jsx5(
3261
- MessageCenterViewMenu,
3262
- {
3263
- filtersActive: hasActiveFilters,
3264
- groupBy,
3265
- providerFilters,
3266
- providerOptions,
3267
- statusFilters,
3268
- statusOptions,
3269
- onClearFilters: clearFilters,
3270
- onGroupByChange: setGroupBy,
3271
- onProviderToggle: toggleProviderFilter,
3272
- onStatusToggle: toggleStatusFilter
3273
- }
3274
- )
3275
- ] }) }),
3276
- /* @__PURE__ */ jsx5(
3277
- AgentVerticalScrollArea,
3278
- {
3279
- className: "min-h-0 flex-1",
3280
- viewportClassName: "flex h-full w-full flex-col px-3.5 pt-4 pb-4",
3281
- scrollbarClassName: "top-4 bottom-4",
3282
- syncKey: scrollSyncKey,
3283
- children: deckItems.length > 0 || listItems.length > 0 ? /* @__PURE__ */ jsxs4("div", { className: "flex w-full min-w-0 flex-col gap-4", children: [
3284
- deckItems.length > 0 ? /* @__PURE__ */ jsx5(
3285
- WorkspaceAgentMessageCenterAttentionDeck,
3286
- {
3287
- items: deckItems,
3288
- highlightedItemId,
3289
- submittingPromptKey,
3290
- registerNode: setItemNode,
3291
- onLinkAction,
3292
- onOpenChat,
3293
- onSubmitPrompt: (item, input) => void submitPrompt(item, input)
3294
- }
3295
- ) : null,
3296
- itemGroupStacks.map((group) => /* @__PURE__ */ jsxs4(
3297
- "section",
3298
- {
3299
- className: "flex min-w-0 flex-col gap-2.5",
3300
- "aria-label": `${group.label} ${group.items.length}`,
3301
- children: [
3302
- /* @__PURE__ */ jsx5("div", { className: "flex min-w-0 items-center justify-between gap-3 px-0.5", children: /* @__PURE__ */ jsx5(MessageCenterGroupHeading, { group }) }),
3303
- (() => {
3304
- return group.stacks.map((stack) => {
3305
- const firstItem = stack.items[0];
3306
- if (!firstItem) {
3307
- return null;
3308
- }
3309
- if (stack.items.length === 1) {
3310
- return renderMessageCenterCard(firstItem);
3311
- }
3312
- const stackId = messageCenterStackRenderId(
3313
- group.id,
3314
- stack.id
3315
- );
3316
- return /* @__PURE__ */ jsx5(
3317
- MessageCenterStack,
3318
- {
3319
- expanded: expandedStackIds.has(stackId),
3320
- groupId: stackId,
3321
- highlightedItemId,
3322
- items: stack.items,
3323
- renderCard: renderMessageCenterCard,
3324
- onCollapse: collapseStack,
3325
- onExpand: expandStack
3326
- },
3327
- stackId
3328
- );
3329
- });
3330
- })()
3331
- ]
3332
- },
3333
- group.id
3334
- ))
3335
- ] }) : model.items.length > 0 ? /* @__PURE__ */ jsxs4("div", { className: "flex min-h-0 flex-1 flex-col items-center justify-center gap-2.5 px-6 py-8 text-center text-[13px] text-[var(--text-tertiary)]", children: [
3336
- /* @__PURE__ */ jsx5("span", { children: t("agentHost.workspaceAgentMessageCenterFilteredEmpty") }),
3337
- /* @__PURE__ */ jsx5(
3338
- Button3,
3339
- {
3340
- type: "button",
3341
- variant: "ghost",
3342
- size: "sm",
3343
- className: "border border-[var(--line-2)] bg-[var(--background-fronted)] text-[var(--text-secondary)] hover:text-[var(--text-primary)]",
3344
- onClick: clearFilters,
3345
- children: t("agentHost.workspaceAgentMessageCenterClearFilters")
3346
- }
3347
- )
3348
- ] }) : /* @__PURE__ */ jsx5("div", { className: "flex min-h-0 flex-1 items-center justify-center px-6 py-8 text-center text-[13px] text-[var(--text-tertiary)]", children: t("agentHost.workspaceAgentMessageCenterEmpty") })
3349
- }
3350
- )
3351
- ] })
3301
+ children: panelContents
3352
3302
  }
3353
3303
  )
3354
3304
  }
@@ -3366,19 +3316,19 @@ var MessageCenterRenderedCard = memo2(function MessageCenterRenderedCard2({
3366
3316
  onSubmitPrompt,
3367
3317
  registerNode
3368
3318
  }) {
3369
- const cardRef = useCallback2(
3319
+ const cardRef = useCallback3(
3370
3320
  (node) => {
3371
3321
  registerNode(item.id, node);
3372
3322
  },
3373
3323
  [item.id, registerNode]
3374
3324
  );
3375
- const handleSubmitPrompt = useCallback2(
3325
+ const handleSubmitPrompt = useCallback3(
3376
3326
  (input) => {
3377
3327
  onSubmitPrompt(item, input);
3378
3328
  },
3379
3329
  [item, onSubmitPrompt]
3380
3330
  );
3381
- return /* @__PURE__ */ jsx5(
3331
+ return /* @__PURE__ */ jsx8(
3382
3332
  MessageCenterCard,
3383
3333
  {
3384
3334
  cardRef,
@@ -3392,86 +3342,203 @@ var MessageCenterRenderedCard = memo2(function MessageCenterRenderedCard2({
3392
3342
  }
3393
3343
  );
3394
3344
  });
3395
- function MessageCenterGroupHeading({
3396
- group
3397
- }) {
3398
- "use memo";
3399
- const statusSignal = messageCenterGroupStatusSignal(group.id);
3400
- if (group.provider) {
3401
- return /* @__PURE__ */ jsxs4(
3402
- "h3",
3403
- {
3404
- "aria-label": `${group.label} \xB7 ${group.items.length}`,
3405
- className: "flex min-w-0 items-center gap-1.5 text-[11px] font-normal leading-4 text-[var(--text-tertiary)]",
3406
- title: `${group.label} \xB7 ${group.items.length}`,
3407
- children: [
3408
- group.identity ? /* @__PURE__ */ jsx5(
3409
- MessageCenterIdentityLabel,
3410
- {
3411
- identity: group.identity,
3412
- provider: group.provider
3413
- }
3414
- ) : /* @__PURE__ */ jsxs4("span", { className: "inline-flex min-w-0 items-center gap-1.5", children: [
3415
- /* @__PURE__ */ jsx5(
3416
- MessageCenterIdentityAvatarMark,
3417
- {
3418
- identity: null,
3419
- provider: group.provider,
3420
- userId: group.userId ?? null
3421
- }
3422
- ),
3423
- /* @__PURE__ */ jsx5("span", { className: "min-w-0 truncate", children: group.label })
3424
- ] }),
3425
- /* @__PURE__ */ jsxs4("span", { className: "shrink-0", children: [
3426
- "\xB7 ",
3427
- group.items.length
3428
- ] })
3429
- ]
3345
+
3346
+ // agent-message-center/workspaceAgentMessageCenterEngineModel.ts
3347
+ import {
3348
+ selectEngineInteractionResponse,
3349
+ selectPendingSubmitsForSession,
3350
+ selectPlanDecisionForTurn
3351
+ } from "@tutti-os/agent-activity-core";
3352
+
3353
+ // agent-message-center/workspaceAgentConsumerSelectors.ts
3354
+ import {
3355
+ selectWorkspaceAgentConsumerCounts,
3356
+ selectWorkspaceAgentConsumerSession,
3357
+ selectWorkspaceAgentConsumerSessions
3358
+ } from "@tutti-os/agent-activity-core";
3359
+
3360
+ // agent-message-center/workspaceAgentMessageCenterEngineModel.ts
3361
+ function buildWorkspaceAgentMessageCenterModelFromEngine(presentation, snapshot, options = {}) {
3362
+ const items = presentation.consumers.filter((consumer) => consumer.session.visible !== false).map((consumer) => {
3363
+ const interaction = latestPendingInteraction(consumer);
3364
+ const needsAttention = interaction ? needsAttentionFromInteraction(consumer, interaction) : null;
3365
+ return buildWorkspaceAgentMessageCenterItem({
3366
+ session: consumer.session,
3367
+ messages: sessionMessages(snapshot.sessionMessagesById, consumer),
3368
+ status: consumer.displayStatus,
3369
+ needsAttention,
3370
+ pendingPrompt: interaction ? promptFromInteraction(interaction) : null,
3371
+ latestTurnOutcome: turnOutcome(consumer),
3372
+ options
3373
+ });
3374
+ });
3375
+ return buildWorkspaceAgentMessageCenterModelFromItems(
3376
+ items,
3377
+ options.itemCutoffUnixMs
3378
+ );
3379
+ }
3380
+ function selectWorkspaceAgentMessageCenterPresentation(state) {
3381
+ const consumers = selectWorkspaceAgentConsumerSessions(state);
3382
+ const promptStatusByKey = {};
3383
+ for (const consumer of consumers) {
3384
+ const sessionId = consumer.session.agentSessionId;
3385
+ for (const interaction of consumer.pendingInteractions) {
3386
+ const response = selectEngineInteractionResponse(
3387
+ state,
3388
+ sessionId,
3389
+ interaction.turnId,
3390
+ interaction.requestId
3391
+ );
3392
+ if (response) {
3393
+ promptStatusByKey[promptStatusKey(sessionId, interaction.requestId)] = response.status;
3430
3394
  }
3395
+ }
3396
+ const turnId = consumer.latestTurn?.turnId ?? "";
3397
+ if (!turnId) continue;
3398
+ const decision = selectPlanDecisionForTurn(state, sessionId, turnId);
3399
+ if (decision) {
3400
+ promptStatusByKey[promptStatusKey(sessionId, turnId)] = decision.status === "requested" ? "responding" : decision.status;
3401
+ continue;
3402
+ }
3403
+ const feedbackPrefix = [
3404
+ "plan-implementation",
3405
+ consumer.session.workspaceId,
3406
+ sessionId,
3407
+ turnId,
3408
+ "feedback"
3409
+ ].join(":");
3410
+ const submit = selectPendingSubmitsForSession(state, sessionId).find(
3411
+ (record) => record.clientSubmitId.startsWith(feedbackPrefix)
3431
3412
  );
3413
+ if (submit) {
3414
+ promptStatusByKey[promptStatusKey(sessionId, turnId)] = submit.status === "failed" ? "failed" : submit.status === "uncertain" ? "unknown" : "responding";
3415
+ }
3432
3416
  }
3433
- return /* @__PURE__ */ jsxs4(
3434
- "h3",
3435
- {
3436
- className: cn5(
3437
- "flex min-w-0 items-center gap-1.5 text-[11px] font-normal leading-4",
3438
- statusSignal ? messageCenterStatusToneClass(statusSignal.tone) : "text-[var(--text-tertiary)]"
3439
- ),
3440
- title: `${group.label} \xB7 ${group.items.length}`,
3441
- children: [
3442
- statusSignal ? /* @__PURE__ */ jsx5(
3443
- StatusDot2,
3444
- {
3445
- tone: statusSignal.tone,
3446
- pulse: statusSignal.pulse,
3447
- size: "sm",
3448
- title: group.label
3449
- }
3450
- ) : null,
3451
- /* @__PURE__ */ jsxs4("span", { className: "min-w-0 truncate", children: [
3452
- group.label,
3453
- " \xB7 ",
3454
- group.items.length
3455
- ] })
3456
- ]
3417
+ return {
3418
+ consumers,
3419
+ promptStatusByKey
3420
+ };
3421
+ }
3422
+ function workspaceAgentMessageCenterPresentationEqual(left, right) {
3423
+ return promptStatusMapsEqual(left.promptStatusByKey, right.promptStatusByKey) && left.consumers.length === right.consumers.length && left.consumers.every((item, index) => {
3424
+ const candidate = right.consumers[index];
3425
+ return candidate !== void 0 && item.session === candidate.session && item.activeTurn === candidate.activeTurn && item.latestTurn === candidate.latestTurn && item.displayStatus === candidate.displayStatus && item.pendingInteractions.length === candidate.pendingInteractions.length && item.pendingInteractions.every(
3426
+ (interaction, interactionIndex) => interaction === candidate.pendingInteractions[interactionIndex]
3427
+ );
3428
+ });
3429
+ }
3430
+ function workspaceAgentMessageCenterPromptStatus(presentation, item) {
3431
+ const prompt = item.pendingPrompt;
3432
+ if (!prompt) return "idle";
3433
+ return presentation.promptStatusByKey[promptStatusKey(item.agentSessionId, prompt.requestId)] ?? "idle";
3434
+ }
3435
+ function promptStatusKey(agentSessionId, requestId) {
3436
+ return `${agentSessionId}\0${requestId}`;
3437
+ }
3438
+ function promptStatusMapsEqual(left, right) {
3439
+ const keys = Object.keys(left);
3440
+ return keys.length === Object.keys(right).length && keys.every((key) => left[key] === right[key]);
3441
+ }
3442
+ function sessionMessages(sessionMessagesById, consumer) {
3443
+ for (const id of [
3444
+ consumer.session.agentSessionId,
3445
+ consumer.session.providerSessionId
3446
+ ]) {
3447
+ const normalized = id?.trim() ?? "";
3448
+ if (normalized && sessionMessagesById[normalized]) {
3449
+ return sessionMessagesById[normalized];
3457
3450
  }
3458
- );
3451
+ }
3452
+ return [];
3459
3453
  }
3460
- function messageCenterGroupStatusSignal(groupId) {
3461
- switch (groupId) {
3462
- case "needs-attention":
3463
- case "waiting":
3464
- return { pulse: true, tone: "amber" };
3465
- case "working":
3466
- return { pulse: true, tone: "blue" };
3467
- case "failed":
3468
- return { pulse: false, tone: "red" };
3469
- case "recently-completed":
3470
- case "completed":
3471
- return { pulse: false, tone: "green" };
3472
- default:
3473
- return null;
3454
+ function latestPendingInteraction(consumer) {
3455
+ return consumer.pendingInteractions.at(-1) ?? null;
3456
+ }
3457
+ function needsAttentionFromInteraction(consumer, interaction) {
3458
+ const summary = interactionSummary(interaction);
3459
+ return {
3460
+ id: `interaction:${interaction.requestId}`,
3461
+ workspaceId: consumer.session.workspaceId,
3462
+ agentSessionId: consumer.session.agentSessionId,
3463
+ provider: consumer.session.provider,
3464
+ title: summary,
3465
+ cwd: consumer.session.cwd,
3466
+ kind: interaction.kind === "approval" ? "permission" : interaction.kind === "question" ? "question" : "constraint",
3467
+ summary,
3468
+ occurredAtUnixMs: interaction.createdAtUnixMs
3469
+ };
3470
+ }
3471
+ function promptFromInteraction(interaction) {
3472
+ const input = interaction.input ?? {};
3473
+ if (interaction.kind === "question") {
3474
+ const questions = normalizeAskUserQuestions(input.questions);
3475
+ return {
3476
+ kind: "ask-user",
3477
+ requestId: interaction.requestId,
3478
+ title: interactionSummary(interaction),
3479
+ questions: questions.length > 0 ? questions : [
3480
+ {
3481
+ id: "response",
3482
+ header: "",
3483
+ question: interactionSummary(interaction),
3484
+ options: [],
3485
+ multiSelect: false,
3486
+ answer: null
3487
+ }
3488
+ ]
3489
+ };
3490
+ }
3491
+ if (interaction.kind !== "approval") {
3492
+ return null;
3474
3493
  }
3494
+ const options = arrayValue2(input.options).flatMap((value) => {
3495
+ const option = recordValue3(value);
3496
+ const id = textValue(option.optionId) ?? textValue(option.id);
3497
+ return id ? [
3498
+ {
3499
+ id,
3500
+ label: textValue(option.label) ?? textValue(option.name) ?? id,
3501
+ kind: textValue(option.kind) ?? id
3502
+ }
3503
+ ] : [];
3504
+ });
3505
+ return {
3506
+ kind: "approval",
3507
+ id: `approval:${interaction.requestId}`,
3508
+ turnId: interaction.turnId,
3509
+ requestId: interaction.requestId,
3510
+ callId: textValue(input.callId) ?? interaction.requestId,
3511
+ title: interactionSummary(interaction),
3512
+ toolName: interaction.toolName ?? null,
3513
+ status: interaction.status,
3514
+ input,
3515
+ options,
3516
+ output: interaction.output ?? null,
3517
+ occurredAtUnixMs: interaction.createdAtUnixMs
3518
+ };
3519
+ }
3520
+ function turnOutcome(consumer) {
3521
+ const turn = consumer.latestTurn;
3522
+ if (!turn || turn.phase !== "settled") return null;
3523
+ const status = turn.outcome === "completed" ? "completed" : turn.outcome === "failed" ? "failed" : null;
3524
+ return status ? {
3525
+ notificationKey: `${consumer.session.agentSessionId}:turn:${turn.turnId}:${status}`,
3526
+ status,
3527
+ turnId: turn.turnId
3528
+ } : null;
3529
+ }
3530
+ function interactionSummary(interaction) {
3531
+ const input = interaction.input ?? {};
3532
+ return textValue(input.question) ?? textValue(input.title) ?? textValue(input.summary) ?? interaction.toolName?.trim() ?? interaction.kind;
3533
+ }
3534
+ function textValue(value) {
3535
+ return typeof value === "string" && value.trim() ? value.trim() : null;
3536
+ }
3537
+ function recordValue3(value) {
3538
+ return value && typeof value === "object" && !Array.isArray(value) ? value : {};
3539
+ }
3540
+ function arrayValue2(value) {
3541
+ return Array.isArray(value) ? value : [];
3475
3542
  }
3476
3543
 
3477
3544
  // agent-message-center/workspaceAgentMessageCenterModelStability.ts
@@ -3631,7 +3698,8 @@ export {
3631
3698
  buildMessageCenterProviderOptions,
3632
3699
  buildMessageCenterStatusOptions,
3633
3700
  buildWorkspaceAgentInteractivePromptLabels,
3634
- buildWorkspaceAgentMessageCenterModel,
3701
+ buildWorkspaceAgentMessageCenterModelFromEngine,
3702
+ dispatchAgentPlanPromptAction,
3635
3703
  getPromptToolDetails,
3636
3704
  groupMessageCenterItems,
3637
3705
  isInteractiveMessageCenterItem,
@@ -3654,10 +3722,17 @@ export {
3654
3722
  readMessageCenterFilterPreferences,
3655
3723
  resolveMessageCenterNotificationAction,
3656
3724
  selectMessageCenterAttentionDeckItems,
3725
+ selectWorkspaceAgentConsumerCounts,
3726
+ selectWorkspaceAgentConsumerSession,
3727
+ selectWorkspaceAgentConsumerSessions,
3728
+ selectWorkspaceAgentMessageCenterPresentation,
3657
3729
  stabilizeWorkspaceAgentMessageCenterModel,
3658
3730
  statusFilterSummary,
3731
+ useEngineSelector,
3659
3732
  userAvatarPlaceholderUrl,
3660
3733
  workspaceAgentActivityStatusLabel,
3734
+ workspaceAgentMessageCenterPresentationEqual,
3735
+ workspaceAgentMessageCenterPromptStatus,
3661
3736
  writeMessageCenterFilterPreferences
3662
3737
  };
3663
3738
  //# sourceMappingURL=index.js.map