@tutti-os/agent-gui 0.0.94 → 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 (153) 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 +12 -8
  5. package/dist/agent-conversation/index.js.map +1 -1
  6. package/dist/agent-env/index.d.ts +10 -36
  7. package/dist/agent-env/index.js +1 -56
  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 -124
  12. package/dist/agent-message-center/index.js +1374 -1316
  13. package/dist/agent-message-center/index.js.map +1 -1
  14. package/dist/{agentConversationVM-Cl4G0Lln.d.ts → agentConversationVM-C335TR6S.d.ts} +112 -7
  15. package/dist/agentFileMentionContracts-Czvz6YMI.d.ts +107 -0
  16. package/dist/{agentGuiNodeTypes-CAioPXK9.d.ts → agentGuiNodeTypes-DppADPHW.d.ts} +96 -148
  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 +126 -80
  21. package/dist/app/renderer/assets/icons/agent-vinyls/tutti-vinyl.png +0 -0
  22. package/dist/app/renderer/assets/icons/open-link-lined.svg +4 -0
  23. package/dist/{chunk-P72YLKC6.js → chunk-3R2D4E57.js} +3127 -3398
  24. package/dist/chunk-3R2D4E57.js.map +1 -0
  25. package/dist/chunk-4YG7YK7S.js +23 -0
  26. package/dist/chunk-4YG7YK7S.js.map +1 -0
  27. package/dist/chunk-5X7YDOC6.js +42 -0
  28. package/dist/chunk-5X7YDOC6.js.map +1 -0
  29. package/dist/{chunk-IBIMGLCD.js → chunk-7J4K6WKB.js} +1 -1
  30. package/dist/chunk-7J4K6WKB.js.map +1 -0
  31. package/dist/{chunk-BXVPOGYK.js → chunk-7PFDA2HQ.js} +505 -504
  32. package/dist/chunk-7PFDA2HQ.js.map +1 -0
  33. package/dist/{chunk-AWAIUYG4.js → chunk-7RDD3EWP.js} +513 -555
  34. package/dist/chunk-7RDD3EWP.js.map +1 -0
  35. package/dist/{chunk-UBDPV34P.js → chunk-AOS2VWU6.js} +1355 -1305
  36. package/dist/chunk-AOS2VWU6.js.map +1 -0
  37. package/dist/{chunk-E5FOXRUM.js → chunk-BFNJKTDV.js} +295 -255
  38. package/dist/chunk-BFNJKTDV.js.map +1 -0
  39. package/dist/{chunk-5FE7M42A.js → chunk-BIHBXWK5.js} +2 -2
  40. package/dist/{chunk-7BUYFVRI.js → chunk-C5FV4UGI.js} +2921 -2944
  41. package/dist/chunk-C5FV4UGI.js.map +1 -0
  42. package/dist/{chunk-SCLLP5DO.js → chunk-CRO2MV2Y.js} +36 -46
  43. package/dist/chunk-CRO2MV2Y.js.map +1 -0
  44. package/dist/chunk-FGLQZ6I4.js +9 -0
  45. package/dist/chunk-FGLQZ6I4.js.map +1 -0
  46. package/dist/chunk-H6IQ63DQ.js +14 -0
  47. package/dist/chunk-H6IQ63DQ.js.map +1 -0
  48. package/dist/{chunk-IGY4ASUF.js → chunk-JX2SIXNL.js} +1293 -1702
  49. package/dist/chunk-JX2SIXNL.js.map +1 -0
  50. package/dist/chunk-KAL4XZMA.js +231 -0
  51. package/dist/chunk-KAL4XZMA.js.map +1 -0
  52. package/dist/chunk-KJQERFKX.js +259 -0
  53. package/dist/chunk-KJQERFKX.js.map +1 -0
  54. package/dist/chunk-LQVXBT65.js +491 -0
  55. package/dist/chunk-LQVXBT65.js.map +1 -0
  56. package/dist/{chunk-554VG7ZW.js → chunk-NITOD7WF.js} +2 -2
  57. package/dist/{chunk-7LMJXF4R.js → chunk-NJAZ7LQM.js} +20 -16
  58. package/dist/chunk-NJAZ7LQM.js.map +1 -0
  59. package/dist/chunk-NX3CZJXW.js +25 -0
  60. package/dist/chunk-NX3CZJXW.js.map +1 -0
  61. package/dist/chunk-O6W72SEP.js +93 -0
  62. package/dist/chunk-O6W72SEP.js.map +1 -0
  63. package/dist/chunk-RY6GIO3K.js +31700 -0
  64. package/dist/chunk-RY6GIO3K.js.map +1 -0
  65. package/dist/{chunk-XDV4ZRVK.js → chunk-UGVI47X6.js} +98 -37
  66. package/dist/chunk-UGVI47X6.js.map +1 -0
  67. package/dist/{chunk-XW4CVBUH.js → chunk-UQJPV6HP.js} +18 -11
  68. package/dist/chunk-UQJPV6HP.js.map +1 -0
  69. package/dist/{chunk-GAPTLVII.js → chunk-VF22EG3F.js} +1 -1
  70. package/dist/{chunk-GAPTLVII.js.map → chunk-VF22EG3F.js.map} +1 -1
  71. package/dist/{chunk-45FF4DQU.js → chunk-WEDMAVX2.js} +22 -24
  72. package/dist/chunk-WEDMAVX2.js.map +1 -0
  73. package/dist/{chunk-MATIJPGF.js → chunk-XMO45GKA.js} +531 -401
  74. package/dist/chunk-XMO45GKA.js.map +1 -0
  75. package/dist/{chunk-ZUW4B5AT.js → chunk-YE25HN6T.js} +6 -9
  76. package/dist/chunk-YE25HN6T.js.map +1 -0
  77. package/dist/context-mention-palette/index.d.ts +3 -2
  78. package/dist/context-mention-palette/index.js +19 -14
  79. package/dist/custom-mention.d.ts +44 -0
  80. package/dist/custom-mention.js +17 -0
  81. package/dist/custom-mention.js.map +1 -0
  82. package/dist/dock-icons.d.ts +6 -0
  83. package/dist/dock-icons.js +11 -0
  84. package/dist/dock-icons.js.map +1 -0
  85. package/dist/i18n/index.d.ts +850 -841
  86. package/dist/i18n/index.js +2 -2
  87. package/dist/index.d.ts +52 -1061
  88. package/dist/index.js +72 -35530
  89. package/dist/index.js.map +1 -1
  90. package/dist/mention-search.d.ts +226 -0
  91. package/dist/mention-search.js +29 -0
  92. package/dist/mention-search.js.map +1 -0
  93. package/dist/open-link-lined-JWEKUKME.svg +4 -0
  94. package/dist/provider-icons.d.ts +6 -0
  95. package/dist/provider-icons.js +12 -0
  96. package/dist/provider-icons.js.map +1 -0
  97. package/dist/provider-identity.d.ts +9 -0
  98. package/dist/provider-identity.js +21 -0
  99. package/dist/provider-identity.js.map +1 -0
  100. package/dist/runtime-BBNdWgDU.d.ts +10 -0
  101. package/dist/{types-PLFZ8SBX.d.ts → types-DX2bxgB8.d.ts} +28 -83
  102. package/dist/workbench/contribution.d.ts +32 -40
  103. package/dist/workbench/contribution.js +10 -6
  104. package/dist/workbench/index.d.ts +3 -2
  105. package/dist/workbench/index.js +24 -20
  106. package/dist/workbench/launch.d.ts +2 -5
  107. package/dist/workbench/launch.js +4 -3
  108. package/dist/workbench/providerCatalog.js +2 -1
  109. package/dist/workbench/sessionTitle.d.ts +4 -3
  110. package/dist/workbench/sessionTitle.js +4 -3
  111. package/dist/workbench/state.d.ts +1 -1
  112. package/dist/workbench/state.js +3 -2
  113. package/dist/workbench/types.d.ts +0 -3
  114. package/dist/workbench/types.js +1 -1
  115. package/dist/workspace-agent-generated-files.d.ts +20 -2
  116. package/dist/workspace-agent-generated-files.js +7 -6
  117. package/dist/workspaceAgentActivityListTypes-C7gPWYiA.d.ts +71 -0
  118. package/package.json +63 -26
  119. package/dist/AgentMentionSearchController-DD_WOred.d.ts +0 -241
  120. package/dist/AgentMessageMarkdown-DeYPURtF.d.ts +0 -7
  121. package/dist/chunk-45FF4DQU.js.map +0 -1
  122. package/dist/chunk-4HP6V2YA.js +0 -207
  123. package/dist/chunk-4HP6V2YA.js.map +0 -1
  124. package/dist/chunk-7BUYFVRI.js.map +0 -1
  125. package/dist/chunk-7LMJXF4R.js.map +0 -1
  126. package/dist/chunk-AWAIUYG4.js.map +0 -1
  127. package/dist/chunk-BXVPOGYK.js.map +0 -1
  128. package/dist/chunk-E5FOXRUM.js.map +0 -1
  129. package/dist/chunk-IBIMGLCD.js.map +0 -1
  130. package/dist/chunk-IGY4ASUF.js.map +0 -1
  131. package/dist/chunk-LR4FA5X6.js +0 -368
  132. package/dist/chunk-LR4FA5X6.js.map +0 -1
  133. package/dist/chunk-MATIJPGF.js.map +0 -1
  134. package/dist/chunk-MKHDRIGN.js +0 -71
  135. package/dist/chunk-MKHDRIGN.js.map +0 -1
  136. package/dist/chunk-P72YLKC6.js.map +0 -1
  137. package/dist/chunk-SCLLP5DO.js.map +0 -1
  138. package/dist/chunk-UBDPV34P.js.map +0 -1
  139. package/dist/chunk-VAKFNNKT.js +0 -410
  140. package/dist/chunk-VAKFNNKT.js.map +0 -1
  141. package/dist/chunk-XDV4ZRVK.js.map +0 -1
  142. package/dist/chunk-XW4CVBUH.js.map +0 -1
  143. package/dist/chunk-ZUW4B5AT.js.map +0 -1
  144. package/dist/plan-decision-ops.d.ts +0 -70
  145. package/dist/plan-decision-ops.js +0 -19
  146. package/dist/queued-prompt-runtime.d.ts +0 -115
  147. package/dist/queued-prompt-runtime.js +0 -9
  148. package/dist/workspaceAgentActivityListViewModel-BzV-cf0D.d.ts +0 -340
  149. package/dist/workspaceLinkActions-DS9LWqzI.d.ts +0 -74
  150. /package/dist/{plan-decision-ops.js.map → agent-gui.js.map} +0 -0
  151. /package/dist/{queued-prompt-runtime.js.map → agents.js.map} +0 -0
  152. /package/dist/{chunk-5FE7M42A.js.map → chunk-BIHBXWK5.js.map} +0 -0
  153. /package/dist/{chunk-554VG7ZW.js.map → chunk-NITOD7WF.js.map} +0 -0
@@ -1,21 +1,27 @@
1
1
  import {
2
2
  formatAgentGuiConversationPlainTitle
3
- } from "../chunk-ZUW4B5AT.js";
3
+ } from "../chunk-YE25HN6T.js";
4
4
  import {
5
5
  AgentInteractivePromptSurface,
6
- approvalOptionDisplayLabel,
7
- getPromptToolDetails,
8
- isPromptRequestIdTitle
9
- } from "../chunk-MATIJPGF.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-SCLLP5DO.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-7BUYFVRI.js";
29
- import {
30
- userAvatarPlaceholderUrl,
31
- workspaceAgentActivityStatusLabel
32
- } from "../chunk-554VG7ZW.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-5FE7M42A.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-UBDPV34P.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);
1443
- useEffect(() => {
1444
- if (!mounted) {
1445
- setRenderCount(initialCount);
1446
- return;
1447
- }
1448
- setRenderCount(
1449
- (current) => Math.min(Math.max(current, initialCount), limit)
1450
- );
1451
- }, [initialCount, limit, mounted]);
1065
+ "use memo";
1066
+ const [userAvatarFailed, setUserAvatarFailed] = useState(false);
1067
+ const userAvatarUrl = rawUserAvatarUrl?.trim() ?? "";
1068
+ const userImageUrl = userAvatarUrl.length > 0 && !userAvatarFailed ? userAvatarUrl : userAvatarPlaceholderUrl;
1452
1069
  useEffect(() => {
1453
- if (!expanded || !mounted || renderCount >= limit) {
1454
- return void 0;
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
+ ]
1455
1105
  }
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));
1106
+ );
1466
1107
  }
1467
- function MessageCenterStackSummary({
1468
- groupId,
1469
- items,
1470
- onExpand
1471
- }) {
1108
+ function ProjectPathInfo({ path }) {
1472
1109
  "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;
1478
- }
1479
1110
  return /* @__PURE__ */ jsx2(
1480
- "button",
1111
+ LazyMessageCenterTooltip,
1481
1112
  {
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",
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",
1497
1119
  {
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
- ]
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" })
1528
1124
  }
1529
1125
  )
1530
1126
  }
1531
1127
  );
1532
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
+ ] });
1190
+ }
1191
+ function statusClass(item) {
1192
+ if (isWaitingMessageCenterItem(item)) {
1193
+ return "waiting";
1194
+ }
1195
+ if (item.status === "idle") {
1196
+ return "completed";
1197
+ }
1198
+ return item.status;
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 "";
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();
1406
+ }
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
+ );
1698
1538
  }
1699
- return summary;
1700
- }
1701
- function isGenericApprovalSummary(summary) {
1702
- const normalized = summary.trim().toLowerCase();
1703
- return normalized === "approval";
1704
- }
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;
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
1564
+ }, [closing]);
1565
+ const onAnimationEnd = useCallback2(
1566
+ (event) => {
1567
+ if (event.target === event.currentTarget && closing) {
1568
+ setMounted(false);
1569
+ }
1570
+ },
1571
+ [closing]
1572
+ );
1573
+ return { closing, mounted, onAnimationEnd };
1574
+ }
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;
1781
1598
  }
1599
+ const collapseLabel = t(
1600
+ "agentHost.workspaceAgentMessageCenterCollapseStackAria"
1601
+ );
1602
+ return /* @__PURE__ */ jsxs3(
1603
+ "div",
1604
+ {
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
+ ]
1700
+ }
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);
1713
+ }
1714
+ function messageCenterCollapsedStackSignature(items) {
1715
+ const firstItem = items[0];
1716
+ if (!firstItem) {
1717
+ return "0";
1718
+ }
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(":");
1730
+ }
1731
+ function useBatchedMessageCenterStackItems({
1732
+ expanded,
1733
+ highlightedItemId,
1734
+ items,
1735
+ mounted
1736
+ }) {
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)
1782
1742
  );
1783
- }
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;
1743
+ const [renderCount, setRenderCount] = useState2(initialCount);
1744
+ useEffect2(() => {
1745
+ if (!mounted) {
1746
+ setRenderCount(initialCount);
1747
+ return;
1800
1748
  }
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 }
1749
+ setRenderCount(
1750
+ (current) => Math.min(Math.max(current, initialCount), limit)
1809
1751
  );
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) {
1752
+ }, [initialCount, limit, mounted]);
1753
+ useEffect2(() => {
1754
+ if (!expanded || !mounted || renderCount >= limit) {
1823
1755
  return void 0;
1824
1756
  }
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
1757
+ const timeoutId = window.setTimeout(() => {
1758
+ setRenderCount(
1759
+ (current) => Math.min(current + MESSAGE_CENTER_STACK_RENDER_BATCH_SIZE, limit)
1830
1760
  );
1831
- return () => {
1832
- window.clearTimeout(timeoutId2);
1833
- };
1834
- }
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 }
1848
- );
1849
- observer.observe(element);
1761
+ }, MESSAGE_CENTER_STACK_RENDER_BATCH_DELAY_MS);
1850
1762
  return () => {
1851
- observer.disconnect();
1852
- if (timeoutId !== null) {
1853
- window.clearTimeout(timeoutId);
1854
- }
1763
+ window.clearTimeout(timeoutId);
1855
1764
  };
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,
1871
- {
1872
- identity: item.identity,
1873
- provider
1874
- }
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
- ] });
1907
- }
1908
- function MessageCenterIdentityLabel({
1909
- identity,
1910
- provider
1911
- }) {
1912
- "use memo";
1913
- if (!identity) {
1914
- return /* @__PURE__ */ jsx2(AgentProviderLabel, { provider });
1915
- }
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
- );
1765
+ }, [expanded, limit, mounted, renderCount]);
1766
+ return items.slice(0, Math.min(renderCount, limit));
1940
1767
  }
1941
- function MessageCenterIdentityAvatarMark({
1942
- identity,
1943
- provider,
1944
- userId
1768
+ function MessageCenterStackSummary({
1769
+ groupId,
1770
+ items,
1771
+ onExpand
1945
1772
  }) {
1946
1773
  "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
- }
1960
- );
1774
+ const { t } = useTranslation();
1775
+ const firstItem = items[0];
1776
+ const hasWaiting = items.some((item) => isWaitingMessageCenterItem(item));
1777
+ if (!firstItem) {
1778
+ return null;
1961
1779
  }
1962
- return /* @__PURE__ */ jsx2(
1963
- MessageCenterIdentityAvatarStack,
1964
- {
1965
- userAvatarUrl: identity?.userAvatarUrl,
1966
- userName,
1967
- agentAvatarUrl: identity?.agentAvatarUrl?.trim() || managedAgentRoundedIconUrl(provider)
1968
- }
1969
- );
1970
- }
1971
- function MessageCenterIdentityAvatarStack({
1972
- agentAvatarUrl,
1973
- userAvatarUrl: rawUserAvatarUrl,
1974
- userName
1975
- }) {
1976
- "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,
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(
@@ -2867,13 +2808,14 @@ var WorkspaceAgentMessageCenterPanel = memo2(
2867
2808
  onLinkAction,
2868
2809
  onNotificationActioned,
2869
2810
  onOpenChat,
2811
+ promptStatus = () => "idle",
2870
2812
  onSubmitPrompt
2871
2813
  }) {
2872
2814
  "use memo";
2873
2815
  if (!open) {
2874
2816
  return null;
2875
2817
  }
2876
- return /* @__PURE__ */ jsx5(AgentGuiI18nProvider, { runtime: i18n, locale, children: /* @__PURE__ */ jsx5(
2818
+ return /* @__PURE__ */ jsx8(AgentGuiI18nProvider, { runtime: i18n, locale, children: /* @__PURE__ */ jsx8(
2877
2819
  WorkspaceAgentMessageCenterPanelContent,
2878
2820
  {
2879
2821
  open,
@@ -2886,6 +2828,7 @@ var WorkspaceAgentMessageCenterPanel = memo2(
2886
2828
  onLinkAction,
2887
2829
  onNotificationActioned,
2888
2830
  onOpenChat,
2831
+ promptStatus,
2889
2832
  onSubmitPrompt
2890
2833
  }
2891
2834
  ) });
@@ -2902,33 +2845,31 @@ function WorkspaceAgentMessageCenterPanelContent({
2902
2845
  onLinkAction,
2903
2846
  onNotificationActioned,
2904
2847
  onOpenChat,
2848
+ promptStatus = () => "idle",
2905
2849
  onSubmitPrompt
2906
2850
  }) {
2907
2851
  "use memo";
2908
2852
  const { t } = useTranslation();
2909
- const [initialFilters] = useState3(readMessageCenterFilterPreferences);
2910
- const [groupBy, setGroupBy] = useState3(
2853
+ const [initialFilters] = useState4(readMessageCenterFilterPreferences);
2854
+ const [groupBy, setGroupBy] = useState4(
2911
2855
  initialFilters.groupBy
2912
2856
  );
2913
- const [statusFilters, setStatusFilters] = useState3(
2857
+ const [statusFilters, setStatusFilters] = useState4(
2914
2858
  initialFilters.statusFilters
2915
2859
  );
2916
- const [providerFilters, setProviderFilters] = useState3(
2860
+ const [providerFilters, setProviderFilters] = useState4(
2917
2861
  initialFilters.providerFilters
2918
2862
  );
2919
- useEffect3(() => {
2863
+ useEffect4(() => {
2920
2864
  writeMessageCenterFilterPreferences({
2921
2865
  groupBy,
2922
2866
  statusFilters,
2923
2867
  providerFilters
2924
2868
  });
2925
2869
  }, [groupBy, statusFilters, providerFilters]);
2926
- const [expandedStackIds, setExpandedStackIds] = useState3(
2870
+ const [expandedStackIds, setExpandedStackIds] = useState4(
2927
2871
  () => /* @__PURE__ */ new Set()
2928
2872
  );
2929
- const [submittingPromptKey, setSubmittingPromptKey] = useState3(
2930
- null
2931
- );
2932
2873
  const itemNodesRef = useRef3(/* @__PURE__ */ new Map());
2933
2874
  const lastScrolledHighlightedItemIdRef = useRef3(null);
2934
2875
  const lastFilterResetHighlightedItemIdRef = useRef3(null);
@@ -3023,35 +2964,27 @@ function WorkspaceAgentMessageCenterPanelContent({
3023
2964
  t,
3024
2965
  visibleItems.length
3025
2966
  ]);
3026
- const submitPrompt = useCallback2(
2967
+ const submitPrompt = useCallback3(
3027
2968
  async (item, input) => {
3028
- const promptKey = `${item.agentSessionId}:${input.requestId}`;
3029
- setSubmittingPromptKey(promptKey);
3030
- try {
3031
- const notificationAction = resolveMessageCenterNotificationAction(
3032
- item,
3033
- input
3034
- );
3035
- if (notificationAction) {
3036
- onNotificationActioned?.({
3037
- action: notificationAction,
3038
- provider: item.provider
3039
- });
3040
- }
3041
- await onSubmitPrompt({
3042
- ...input,
3043
- agentSessionId: item.agentSessionId,
3044
- 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
3045
2977
  });
3046
- } finally {
3047
- setSubmittingPromptKey(
3048
- (current) => current === promptKey ? null : current
3049
- );
3050
2978
  }
2979
+ await onSubmitPrompt({
2980
+ ...input,
2981
+ agentSessionId: item.agentSessionId,
2982
+ promptKind: item.pendingPrompt?.kind
2983
+ });
3051
2984
  },
3052
2985
  [onNotificationActioned, onSubmitPrompt]
3053
2986
  );
3054
- const setItemNode = useCallback2(
2987
+ const setItemNode = useCallback3(
3055
2988
  (itemId, node) => {
3056
2989
  if (node) {
3057
2990
  itemNodesRef.current.set(itemId, node);
@@ -3061,7 +2994,7 @@ function WorkspaceAgentMessageCenterPanelContent({
3061
2994
  },
3062
2995
  []
3063
2996
  );
3064
- const toggleStatusFilter = useCallback2(
2997
+ const toggleStatusFilter = useCallback3(
3065
2998
  (status) => {
3066
2999
  setStatusFilters((current) => {
3067
3000
  const next = new Set(
@@ -3077,7 +3010,7 @@ function WorkspaceAgentMessageCenterPanelContent({
3077
3010
  },
3078
3011
  [statusOptions]
3079
3012
  );
3080
- const toggleProviderFilter = useCallback2(
3013
+ const toggleProviderFilter = useCallback3(
3081
3014
  (provider) => {
3082
3015
  setProviderFilters((current) => {
3083
3016
  const next = new Set(
@@ -3093,11 +3026,11 @@ function WorkspaceAgentMessageCenterPanelContent({
3093
3026
  },
3094
3027
  [providerOptions]
3095
3028
  );
3096
- const clearFilters = useCallback2(() => {
3029
+ const clearFilters = useCallback3(() => {
3097
3030
  setStatusFilters(null);
3098
3031
  setProviderFilters(null);
3099
3032
  }, []);
3100
- const expandStack = useCallback2((groupId) => {
3033
+ const expandStack = useCallback3((groupId) => {
3101
3034
  setExpandedStackIds((current) => {
3102
3035
  if (current.has(groupId)) {
3103
3036
  return current;
@@ -3107,7 +3040,7 @@ function WorkspaceAgentMessageCenterPanelContent({
3107
3040
  return next;
3108
3041
  });
3109
3042
  }, []);
3110
- const collapseStack = useCallback2((groupId) => {
3043
+ const collapseStack = useCallback3((groupId) => {
3111
3044
  setExpandedStackIds((current) => {
3112
3045
  if (!current.has(groupId)) {
3113
3046
  return current;
@@ -3179,7 +3112,7 @@ function WorkspaceAgentMessageCenterPanelContent({
3179
3112
  statusFilters,
3180
3113
  visibleItems
3181
3114
  ]);
3182
- useEffect3(() => {
3115
+ useEffect4(() => {
3183
3116
  if (!open || !highlightedItemId) {
3184
3117
  return void 0;
3185
3118
  }
@@ -3190,16 +3123,16 @@ function WorkspaceAgentMessageCenterPanelContent({
3190
3123
  window.clearTimeout(timeoutId);
3191
3124
  };
3192
3125
  }, [highlightedItemId, onHighlightedItemSettled, open]);
3193
- const renderMessageCenterCard = useCallback2(
3126
+ const renderMessageCenterCard = useCallback3(
3194
3127
  (item, options = {}) => {
3195
3128
  const highlighted = item.id === highlightedItemId;
3196
3129
  const stackedIndex = options.stackedIndex;
3197
- const card = /* @__PURE__ */ jsx5(
3130
+ const card = /* @__PURE__ */ jsx8(
3198
3131
  MessageCenterRenderedCard,
3199
3132
  {
3200
3133
  highlighted,
3201
3134
  item,
3202
- isSubmitting: submittingPromptKey === `${item.agentSessionId}:${item.pendingPrompt?.requestId}`,
3135
+ isSubmitting: promptStatus(item) === "responding" || promptStatus(item) === "unknown",
3203
3136
  lazySummary: stackedIndex !== void 0 && stackedIndex >= MESSAGE_CENTER_STACK_EAGER_SUMMARY_COUNT,
3204
3137
  registerNode: setItemNode,
3205
3138
  onLinkAction,
@@ -3211,7 +3144,7 @@ function WorkspaceAgentMessageCenterPanelContent({
3211
3144
  if (stackedIndex === void 0) {
3212
3145
  return card;
3213
3146
  }
3214
- return /* @__PURE__ */ jsx5(
3147
+ return /* @__PURE__ */ jsx8(
3215
3148
  "div",
3216
3149
  {
3217
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",
@@ -3227,18 +3160,18 @@ function WorkspaceAgentMessageCenterPanelContent({
3227
3160
  highlightedItemId,
3228
3161
  onLinkAction,
3229
3162
  onOpenChat,
3163
+ promptStatus,
3230
3164
  setItemNode,
3231
- submitPrompt,
3232
- submittingPromptKey
3165
+ submitPrompt
3233
3166
  ]
3234
3167
  );
3235
- const panelContents = /* @__PURE__ */ jsxs4(TooltipProvider, { delayDuration: MESSAGE_CENTER_TOOLTIP_DELAY_MS, children: [
3236
- /* @__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: [
3237
- presentation === "drawer" ? /* @__PURE__ */ jsxs4("div", { className: "min-w-0", children: [
3238
- /* @__PURE__ */ jsx5(DrawerTitle, { className: "truncate text-[13px] font-semibold leading-5 text-[var(--text-primary)]", children: t("agentHost.workspaceAgentMessageCenterTitle") }),
3239
- /* @__PURE__ */ jsx5(DrawerDescription, { className: "truncate text-[11px] leading-4 text-[var(--text-tertiary)]", children: headerSummary })
3240
- ] }) : /* @__PURE__ */ jsx5("p", { className: "min-w-0 truncate text-[11px] leading-4 text-[var(--text-tertiary)]", children: headerSummary }),
3241
- /* @__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(
3242
3175
  MessageCenterViewMenu,
3243
3176
  {
3244
3177
  filtersActive: hasActiveFilters,
@@ -3254,33 +3187,33 @@ function WorkspaceAgentMessageCenterPanelContent({
3254
3187
  }
3255
3188
  )
3256
3189
  ] }) }),
3257
- /* @__PURE__ */ jsx5(
3190
+ /* @__PURE__ */ jsx8(
3258
3191
  AgentVerticalScrollArea,
3259
3192
  {
3260
3193
  className: "min-h-0 flex-1",
3261
3194
  viewportClassName: "flex h-full w-full flex-col px-3.5 pt-4 pb-4",
3262
3195
  scrollbarClassName: "top-4 bottom-4",
3263
3196
  syncKey: scrollSyncKey,
3264
- children: deckItems.length > 0 || listItems.length > 0 ? /* @__PURE__ */ jsxs4("div", { className: "flex w-full min-w-0 flex-col gap-4", children: [
3265
- deckItems.length > 0 ? /* @__PURE__ */ jsx5(
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(
3266
3199
  WorkspaceAgentMessageCenterAttentionDeck,
3267
3200
  {
3268
3201
  items: deckItems,
3269
3202
  highlightedItemId,
3270
- submittingPromptKey,
3203
+ isPromptSubmitting: (item) => promptStatus(item) === "responding" || promptStatus(item) === "unknown",
3271
3204
  registerNode: setItemNode,
3272
3205
  onLinkAction,
3273
3206
  onOpenChat,
3274
3207
  onSubmitPrompt: (item, input) => void submitPrompt(item, input)
3275
3208
  }
3276
3209
  ) : null,
3277
- itemGroupStacks.map((group) => /* @__PURE__ */ jsxs4(
3210
+ itemGroupStacks.map((group) => /* @__PURE__ */ jsxs7(
3278
3211
  "section",
3279
3212
  {
3280
3213
  className: "flex min-w-0 flex-col gap-2.5",
3281
3214
  "aria-label": `${group.label} ${group.items.length}`,
3282
3215
  children: [
3283
- /* @__PURE__ */ jsx5("div", { className: "flex min-w-0 items-center justify-between gap-3 px-0.5", children: /* @__PURE__ */ jsx5(MessageCenterGroupHeading, { group }) }),
3216
+ /* @__PURE__ */ jsx8("div", { className: "flex min-w-0 items-center justify-between gap-3 px-0.5", children: /* @__PURE__ */ jsx8(MessageCenterGroupHeading, { group }) }),
3284
3217
  (() => {
3285
3218
  return group.stacks.map((stack) => {
3286
3219
  const firstItem = stack.items[0];
@@ -3294,7 +3227,7 @@ function WorkspaceAgentMessageCenterPanelContent({
3294
3227
  group.id,
3295
3228
  stack.id
3296
3229
  );
3297
- return /* @__PURE__ */ jsx5(
3230
+ return /* @__PURE__ */ jsx8(
3298
3231
  MessageCenterStack,
3299
3232
  {
3300
3233
  expanded: expandedStackIds.has(stackId),
@@ -3313,10 +3246,10 @@ function WorkspaceAgentMessageCenterPanelContent({
3313
3246
  },
3314
3247
  group.id
3315
3248
  ))
3316
- ] }) : 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: [
3317
- /* @__PURE__ */ jsx5("span", { children: t("agentHost.workspaceAgentMessageCenterFilteredEmpty") }),
3318
- /* @__PURE__ */ jsx5(
3319
- Button3,
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,
3320
3253
  {
3321
3254
  type: "button",
3322
3255
  variant: "ghost",
@@ -3326,12 +3259,12 @@ function WorkspaceAgentMessageCenterPanelContent({
3326
3259
  children: t("agentHost.workspaceAgentMessageCenterClearFilters")
3327
3260
  }
3328
3261
  )
3329
- ] }) : /* @__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") })
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") })
3330
3263
  }
3331
3264
  )
3332
3265
  ] });
3333
3266
  if (presentation === "embedded") {
3334
- return /* @__PURE__ */ jsx5(
3267
+ return /* @__PURE__ */ jsx8(
3335
3268
  "section",
3336
3269
  {
3337
3270
  "aria-label": t("agentHost.workspaceAgentMessageCenterTitle"),
@@ -3342,7 +3275,7 @@ function WorkspaceAgentMessageCenterPanelContent({
3342
3275
  }
3343
3276
  );
3344
3277
  }
3345
- return /* @__PURE__ */ jsx5(
3278
+ return /* @__PURE__ */ jsx8(
3346
3279
  Drawer,
3347
3280
  {
3348
3281
  open,
@@ -3353,10 +3286,10 @@ function WorkspaceAgentMessageCenterPanelContent({
3353
3286
  onClose();
3354
3287
  }
3355
3288
  },
3356
- children: /* @__PURE__ */ jsx5(
3289
+ children: /* @__PURE__ */ jsx8(
3357
3290
  DrawerContent,
3358
3291
  {
3359
- className: cn5(
3292
+ className: cn7(
3360
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",
3361
3294
  "[-webkit-app-region:no-drag]"
3362
3295
  ),
@@ -3383,19 +3316,19 @@ var MessageCenterRenderedCard = memo2(function MessageCenterRenderedCard2({
3383
3316
  onSubmitPrompt,
3384
3317
  registerNode
3385
3318
  }) {
3386
- const cardRef = useCallback2(
3319
+ const cardRef = useCallback3(
3387
3320
  (node) => {
3388
3321
  registerNode(item.id, node);
3389
3322
  },
3390
3323
  [item.id, registerNode]
3391
3324
  );
3392
- const handleSubmitPrompt = useCallback2(
3325
+ const handleSubmitPrompt = useCallback3(
3393
3326
  (input) => {
3394
3327
  onSubmitPrompt(item, input);
3395
3328
  },
3396
3329
  [item, onSubmitPrompt]
3397
3330
  );
3398
- return /* @__PURE__ */ jsx5(
3331
+ return /* @__PURE__ */ jsx8(
3399
3332
  MessageCenterCard,
3400
3333
  {
3401
3334
  cardRef,
@@ -3409,86 +3342,203 @@ var MessageCenterRenderedCard = memo2(function MessageCenterRenderedCard2({
3409
3342
  }
3410
3343
  );
3411
3344
  });
3412
- function MessageCenterGroupHeading({
3413
- group
3414
- }) {
3415
- "use memo";
3416
- const statusSignal = messageCenterGroupStatusSignal(group.id);
3417
- if (group.provider) {
3418
- return /* @__PURE__ */ jsxs4(
3419
- "h3",
3420
- {
3421
- "aria-label": `${group.label} \xB7 ${group.items.length}`,
3422
- className: "flex min-w-0 items-center gap-1.5 text-[11px] font-normal leading-4 text-[var(--text-tertiary)]",
3423
- title: `${group.label} \xB7 ${group.items.length}`,
3424
- children: [
3425
- group.identity ? /* @__PURE__ */ jsx5(
3426
- MessageCenterIdentityLabel,
3427
- {
3428
- identity: group.identity,
3429
- provider: group.provider
3430
- }
3431
- ) : /* @__PURE__ */ jsxs4("span", { className: "inline-flex min-w-0 items-center gap-1.5", children: [
3432
- /* @__PURE__ */ jsx5(
3433
- MessageCenterIdentityAvatarMark,
3434
- {
3435
- identity: null,
3436
- provider: group.provider,
3437
- userId: group.userId ?? null
3438
- }
3439
- ),
3440
- /* @__PURE__ */ jsx5("span", { className: "min-w-0 truncate", children: group.label })
3441
- ] }),
3442
- /* @__PURE__ */ jsxs4("span", { className: "shrink-0", children: [
3443
- "\xB7 ",
3444
- group.items.length
3445
- ] })
3446
- ]
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;
3447
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)
3448
3412
  );
3413
+ if (submit) {
3414
+ promptStatusByKey[promptStatusKey(sessionId, turnId)] = submit.status === "failed" ? "failed" : submit.status === "uncertain" ? "unknown" : "responding";
3415
+ }
3449
3416
  }
3450
- return /* @__PURE__ */ jsxs4(
3451
- "h3",
3452
- {
3453
- className: cn5(
3454
- "flex min-w-0 items-center gap-1.5 text-[11px] font-normal leading-4",
3455
- statusSignal ? messageCenterStatusToneClass(statusSignal.tone) : "text-[var(--text-tertiary)]"
3456
- ),
3457
- title: `${group.label} \xB7 ${group.items.length}`,
3458
- children: [
3459
- statusSignal ? /* @__PURE__ */ jsx5(
3460
- StatusDot2,
3461
- {
3462
- tone: statusSignal.tone,
3463
- pulse: statusSignal.pulse,
3464
- size: "sm",
3465
- title: group.label
3466
- }
3467
- ) : null,
3468
- /* @__PURE__ */ jsxs4("span", { className: "min-w-0 truncate", children: [
3469
- group.label,
3470
- " \xB7 ",
3471
- group.items.length
3472
- ] })
3473
- ]
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];
3474
3450
  }
3475
- );
3451
+ }
3452
+ return [];
3476
3453
  }
3477
- function messageCenterGroupStatusSignal(groupId) {
3478
- switch (groupId) {
3479
- case "needs-attention":
3480
- case "waiting":
3481
- return { pulse: true, tone: "amber" };
3482
- case "working":
3483
- return { pulse: true, tone: "blue" };
3484
- case "failed":
3485
- return { pulse: false, tone: "red" };
3486
- case "recently-completed":
3487
- case "completed":
3488
- return { pulse: false, tone: "green" };
3489
- default:
3490
- 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;
3491
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 : [];
3492
3542
  }
3493
3543
 
3494
3544
  // agent-message-center/workspaceAgentMessageCenterModelStability.ts
@@ -3648,7 +3698,8 @@ export {
3648
3698
  buildMessageCenterProviderOptions,
3649
3699
  buildMessageCenterStatusOptions,
3650
3700
  buildWorkspaceAgentInteractivePromptLabels,
3651
- buildWorkspaceAgentMessageCenterModel,
3701
+ buildWorkspaceAgentMessageCenterModelFromEngine,
3702
+ dispatchAgentPlanPromptAction,
3652
3703
  getPromptToolDetails,
3653
3704
  groupMessageCenterItems,
3654
3705
  isInteractiveMessageCenterItem,
@@ -3671,10 +3722,17 @@ export {
3671
3722
  readMessageCenterFilterPreferences,
3672
3723
  resolveMessageCenterNotificationAction,
3673
3724
  selectMessageCenterAttentionDeckItems,
3725
+ selectWorkspaceAgentConsumerCounts,
3726
+ selectWorkspaceAgentConsumerSession,
3727
+ selectWorkspaceAgentConsumerSessions,
3728
+ selectWorkspaceAgentMessageCenterPresentation,
3674
3729
  stabilizeWorkspaceAgentMessageCenterModel,
3675
3730
  statusFilterSummary,
3731
+ useEngineSelector,
3676
3732
  userAvatarPlaceholderUrl,
3677
3733
  workspaceAgentActivityStatusLabel,
3734
+ workspaceAgentMessageCenterPresentationEqual,
3735
+ workspaceAgentMessageCenterPromptStatus,
3678
3736
  writeMessageCenterFilterPreferences
3679
3737
  };
3680
3738
  //# sourceMappingURL=index.js.map