@tutti-os/agent-gui 0.0.94 → 0.0.96

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 (163) hide show
  1. package/README.md +86 -38
  2. package/dist/AgentGUI-DWdvUV4x.d.ts +1038 -0
  3. package/dist/agent-conversation/index.d.ts +6 -7
  4. package/dist/agent-conversation/index.js +15 -10
  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 +2 -57
  8. package/dist/agent-env/index.js.map +1 -1
  9. package/dist/agent-gui.d.ts +21 -0
  10. package/dist/agent-gui.js +39 -0
  11. package/dist/agent-message-center/index.d.ts +156 -124
  12. package/dist/agent-message-center/index.js +1656 -1463
  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-58IjMU-u.d.ts +108 -0
  16. package/dist/{agentGuiNodeTypes-CAioPXK9.d.ts → agentGuiNodeTypes-B9X4aWfv.d.ts} +123 -163
  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 +276 -83
  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-7BUYFVRI.js → chunk-2HJEOO7W.js} +2931 -2946
  24. package/dist/chunk-2HJEOO7W.js.map +1 -0
  25. package/dist/{chunk-E5FOXRUM.js → chunk-3XXBDYAI.js} +293 -258
  26. package/dist/chunk-3XXBDYAI.js.map +1 -0
  27. package/dist/{chunk-ZUW4B5AT.js → chunk-3Y3F7CS5.js} +21 -32
  28. package/dist/chunk-3Y3F7CS5.js.map +1 -0
  29. package/dist/{chunk-SCLLP5DO.js → chunk-4PQPJ5OY.js} +50 -155
  30. package/dist/chunk-4PQPJ5OY.js.map +1 -0
  31. package/dist/chunk-4YG7YK7S.js +23 -0
  32. package/dist/chunk-4YG7YK7S.js.map +1 -0
  33. package/dist/chunk-5X7YDOC6.js +42 -0
  34. package/dist/chunk-5X7YDOC6.js.map +1 -0
  35. package/dist/{chunk-R2EWECUP.js → chunk-7BXWPI4F.js} +17 -2
  36. package/dist/{chunk-R2EWECUP.js.map → chunk-7BXWPI4F.js.map} +1 -1
  37. package/dist/chunk-AGT7MUTV.js +491 -0
  38. package/dist/chunk-AGT7MUTV.js.map +1 -0
  39. package/dist/chunk-C35SNDVZ.js +96 -0
  40. package/dist/chunk-C35SNDVZ.js.map +1 -0
  41. package/dist/{chunk-5FE7M42A.js → chunk-E4HQUTM3.js} +2 -2
  42. package/dist/chunk-FGLQZ6I4.js +9 -0
  43. package/dist/chunk-FGLQZ6I4.js.map +1 -0
  44. package/dist/chunk-H5F3QSCF.js +25 -0
  45. package/dist/chunk-H5F3QSCF.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-45FF4DQU.js → chunk-IYEXLOUE.js} +22 -27
  49. package/dist/chunk-IYEXLOUE.js.map +1 -0
  50. package/dist/{chunk-P72YLKC6.js → chunk-JKIZA7EJ.js} +3573 -3755
  51. package/dist/chunk-JKIZA7EJ.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-XW4CVBUH.js → chunk-L3GMMGRS.js} +25 -16
  55. package/dist/chunk-L3GMMGRS.js.map +1 -0
  56. package/dist/chunk-MASXZENX.js +231 -0
  57. package/dist/chunk-MASXZENX.js.map +1 -0
  58. package/dist/{chunk-BXVPOGYK.js → chunk-O3Q5SIJH.js} +505 -504
  59. package/dist/chunk-O3Q5SIJH.js.map +1 -0
  60. package/dist/{chunk-554VG7ZW.js → chunk-QVBF5BN5.js} +2 -2
  61. package/dist/{chunk-AWAIUYG4.js → chunk-RE4AXS27.js} +532 -565
  62. package/dist/chunk-RE4AXS27.js.map +1 -0
  63. package/dist/{chunk-7LMJXF4R.js → chunk-TVIGLNNI.js} +20 -16
  64. package/dist/chunk-TVIGLNNI.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-GAPTLVII.js → chunk-UHBCM6RO.js} +1 -1
  68. package/dist/chunk-UHBCM6RO.js.map +1 -0
  69. package/dist/{chunk-UBDPV34P.js → chunk-W6WAGPMD.js} +1385 -1305
  70. package/dist/chunk-W6WAGPMD.js.map +1 -0
  71. package/dist/chunk-WKSFPJHZ.js +33054 -0
  72. package/dist/chunk-WKSFPJHZ.js.map +1 -0
  73. package/dist/{chunk-IGY4ASUF.js → chunk-WMNS4MAQ.js} +1288 -1696
  74. package/dist/chunk-WMNS4MAQ.js.map +1 -0
  75. package/dist/{chunk-MATIJPGF.js → chunk-XPFHJMZP.js} +541 -401
  76. package/dist/chunk-XPFHJMZP.js.map +1 -0
  77. package/dist/chunk-YMXYBG7U.js +12 -0
  78. package/dist/chunk-YMXYBG7U.js.map +1 -0
  79. package/dist/context-mention-palette/index.d.ts +3 -2
  80. package/dist/context-mention-palette/index.js +17 -12
  81. package/dist/custom-mention.d.ts +42 -0
  82. package/dist/custom-mention.js +17 -0
  83. package/dist/custom-mention.js.map +1 -0
  84. package/dist/dock-icons.d.ts +4 -0
  85. package/dist/dock-icons.js +11 -0
  86. package/dist/dock-icons.js.map +1 -0
  87. package/dist/i18n/index.d.ts +880 -841
  88. package/dist/i18n/index.js +2 -2
  89. package/dist/index.d.ts +56 -1063
  90. package/dist/index.js +78 -35532
  91. package/dist/index.js.map +1 -1
  92. package/dist/mention-search.d.ts +226 -0
  93. package/dist/mention-search.js +29 -0
  94. package/dist/mention-search.js.map +1 -0
  95. package/dist/open-link-lined-JWEKUKME.svg +4 -0
  96. package/dist/pastedTextKinds-D-XuInaS.d.ts +4 -0
  97. package/dist/provider-icons.d.ts +6 -0
  98. package/dist/provider-icons.js +12 -0
  99. package/dist/provider-icons.js.map +1 -0
  100. package/dist/provider-identity.d.ts +9 -0
  101. package/dist/provider-identity.js +21 -0
  102. package/dist/provider-identity.js.map +1 -0
  103. package/dist/runtime-BBNdWgDU.d.ts +10 -0
  104. package/dist/startup-shell.d.ts +8 -0
  105. package/dist/startup-shell.js +184 -0
  106. package/dist/startup-shell.js.map +1 -0
  107. package/dist/{types-PLFZ8SBX.d.ts → types-CnT8rNUI.d.ts} +43 -87
  108. package/dist/workbench/contribution.d.ts +34 -41
  109. package/dist/workbench/contribution.js +10 -6
  110. package/dist/workbench/index.d.ts +5 -4
  111. package/dist/workbench/index.js +27 -25
  112. package/dist/workbench/launch.d.ts +4 -7
  113. package/dist/workbench/launch.js +4 -3
  114. package/dist/workbench/providerCatalog.d.ts +2 -2
  115. package/dist/workbench/providerCatalog.js +2 -1
  116. package/dist/workbench/sessionTitle.d.ts +11 -14
  117. package/dist/workbench/sessionTitle.js +6 -7
  118. package/dist/workbench/state.d.ts +1 -1
  119. package/dist/workbench/state.js +3 -2
  120. package/dist/workbench/types.d.ts +2 -4
  121. package/dist/workbench/types.js +1 -1
  122. package/dist/workspace-agent-generated-files.d.ts +20 -2
  123. package/dist/workspace-agent-generated-files.js +6 -5
  124. package/dist/workspaceAgentActivityListTypes-C7gPWYiA.d.ts +71 -0
  125. package/package.json +70 -26
  126. package/dist/AgentMentionSearchController-DD_WOred.d.ts +0 -241
  127. package/dist/AgentMessageMarkdown-DeYPURtF.d.ts +0 -7
  128. package/dist/chunk-45FF4DQU.js.map +0 -1
  129. package/dist/chunk-4HP6V2YA.js +0 -207
  130. package/dist/chunk-4HP6V2YA.js.map +0 -1
  131. package/dist/chunk-7BUYFVRI.js.map +0 -1
  132. package/dist/chunk-7LMJXF4R.js.map +0 -1
  133. package/dist/chunk-AWAIUYG4.js.map +0 -1
  134. package/dist/chunk-BXVPOGYK.js.map +0 -1
  135. package/dist/chunk-E5FOXRUM.js.map +0 -1
  136. package/dist/chunk-GAPTLVII.js.map +0 -1
  137. package/dist/chunk-IBIMGLCD.js +0 -66
  138. package/dist/chunk-IBIMGLCD.js.map +0 -1
  139. package/dist/chunk-IGY4ASUF.js.map +0 -1
  140. package/dist/chunk-LR4FA5X6.js +0 -368
  141. package/dist/chunk-LR4FA5X6.js.map +0 -1
  142. package/dist/chunk-MATIJPGF.js.map +0 -1
  143. package/dist/chunk-MKHDRIGN.js +0 -71
  144. package/dist/chunk-MKHDRIGN.js.map +0 -1
  145. package/dist/chunk-P72YLKC6.js.map +0 -1
  146. package/dist/chunk-SCLLP5DO.js.map +0 -1
  147. package/dist/chunk-UBDPV34P.js.map +0 -1
  148. package/dist/chunk-VAKFNNKT.js +0 -410
  149. package/dist/chunk-VAKFNNKT.js.map +0 -1
  150. package/dist/chunk-XDV4ZRVK.js.map +0 -1
  151. package/dist/chunk-XW4CVBUH.js.map +0 -1
  152. package/dist/chunk-ZUW4B5AT.js.map +0 -1
  153. package/dist/plan-decision-ops.d.ts +0 -70
  154. package/dist/plan-decision-ops.js +0 -19
  155. package/dist/queued-prompt-runtime.d.ts +0 -115
  156. package/dist/queued-prompt-runtime.js +0 -9
  157. package/dist/uiSettings-BQS9r2eo.d.ts +0 -6
  158. package/dist/workspaceAgentActivityListViewModel-BzV-cf0D.d.ts +0 -340
  159. package/dist/workspaceLinkActions-DS9LWqzI.d.ts +0 -74
  160. /package/dist/{plan-decision-ops.js.map → agent-gui.js.map} +0 -0
  161. /package/dist/{queued-prompt-runtime.js.map → agents.js.map} +0 -0
  162. /package/dist/{chunk-5FE7M42A.js.map → chunk-E4HQUTM3.js.map} +0 -0
  163. /package/dist/{chunk-554VG7ZW.js.map → chunk-QVBF5BN5.js.map} +0 -0
@@ -1,21 +1,13 @@
1
- import {
2
- formatAgentGuiConversationPlainTitle
3
- } from "../chunk-ZUW4B5AT.js";
4
1
  import {
5
2
  AgentInteractivePromptSurface,
6
- approvalOptionDisplayLabel,
7
- getPromptToolDetails,
8
- isPromptRequestIdTitle
9
- } from "../chunk-MATIJPGF.js";
10
- import {
11
3
  PLAN_IMPLEMENTATION_ACTION_IMPLEMENT,
12
4
  PLAN_IMPLEMENTATION_PROMPT,
13
- latestPlanTurnId,
14
- planImplementationPromptFromPlanTurn
15
- } from "../chunk-MKHDRIGN.js";
16
- import {
17
- formatAgentSessionMentionText
18
- } from "../chunk-SCLLP5DO.js";
5
+ approvalOptionDisplayLabel,
6
+ dispatchAgentPlanPromptAction,
7
+ getPromptToolDetails,
8
+ isPromptRequestIdTitle,
9
+ useEngineSelector
10
+ } from "../chunk-XPFHJMZP.js";
19
11
  import {
20
12
  AgentMessageMarkdown,
21
13
  CustomScrollArea,
@@ -25,48 +17,52 @@ import {
25
17
  extractExitPlanModeOptions,
26
18
  isExitPlanSwitchModeInput,
27
19
  normalizeAskUserQuestions
28
- } from "../chunk-7BUYFVRI.js";
20
+ } from "../chunk-2HJEOO7W.js";
29
21
  import {
30
22
  userAvatarPlaceholderUrl,
31
23
  workspaceAgentActivityStatusLabel
32
- } from "../chunk-554VG7ZW.js";
24
+ } from "../chunk-QVBF5BN5.js";
33
25
  import {
34
26
  resolveWorkspaceAgentSessionSortTimeUnixMs
35
- } from "../chunk-IBIMGLCD.js";
27
+ } from "../chunk-YMXYBG7U.js";
36
28
  import {
37
29
  managedAgentRoundedIconUrl
38
- } from "../chunk-LR4FA5X6.js";
30
+ } from "../chunk-MASXZENX.js";
39
31
  import {
40
32
  workspaceAgentProviderLabel
41
- } from "../chunk-4HP6V2YA.js";
33
+ } from "../chunk-H5F3QSCF.js";
34
+ import "../chunk-PJP5BUU6.js";
35
+ import "../chunk-H6IQ63DQ.js";
36
+ import {
37
+ normalizeAgentTitleText
38
+ } from "../chunk-GCBDIQDX.js";
42
39
  import {
43
40
  AgentGuiI18nProvider,
44
41
  getActiveUiLanguage,
45
42
  useTranslation
46
- } from "../chunk-5FE7M42A.js";
47
- import "../chunk-PJP5BUU6.js";
48
- import "../chunk-XDV4ZRVK.js";
49
- import "../chunk-UBDPV34P.js";
50
- import "../chunk-GCBDIQDX.js";
43
+ } from "../chunk-E4HQUTM3.js";
44
+ import "../chunk-W6WAGPMD.js";
45
+ import "../chunk-5X7YDOC6.js";
46
+ import "../chunk-KJQERFKX.js";
47
+ import "../chunk-UGVI47X6.js";
51
48
 
52
49
  // agent-message-center/WorkspaceAgentMessageCenterPanel.tsx
53
50
  import {
54
51
  memo as memo2,
55
- useCallback as useCallback2,
56
- useEffect as useEffect3,
52
+ useCallback as useCallback3,
53
+ useEffect as useEffect4,
57
54
  useLayoutEffect as useLayoutEffect2,
58
55
  useMemo as useMemo2,
59
56
  useRef as useRef3,
60
- useState as useState3
57
+ useState as useState4
61
58
  } from "react";
62
59
  import {
63
- Button as Button3,
64
- cn as cn5,
60
+ Button as Button4,
61
+ cn as cn7,
65
62
  Drawer,
66
63
  DrawerContent,
67
64
  DrawerDescription,
68
65
  DrawerTitle,
69
- StatusDot as StatusDot2,
70
66
  TooltipProvider
71
67
  } from "@tutti-os/ui-system";
72
68
 
@@ -109,12 +105,6 @@ var AgentVerticalScrollArea = forwardRef(function AgentVerticalScrollArea2({
109
105
  );
110
106
  });
111
107
 
112
- // agent-message-center/workspaceAgentMessageCenterModel.ts
113
- import {
114
- selectNeedsAttentionItems,
115
- selectSessionDisplayStatuses
116
- } from "@tutti-os/agent-activity-core";
117
-
118
108
  // agent-message-center/workspaceAgentMessageCenterDigest.ts
119
109
  var digestAgentMessageSummaryByMessage = /* @__PURE__ */ new WeakMap();
120
110
  function buildWorkspaceAgentMessageCenterDigest(input) {
@@ -476,7 +466,7 @@ function positiveNumber(value) {
476
466
  return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : null;
477
467
  }
478
468
 
479
- // agent-message-center/workspaceAgentMessageCenterModel.ts
469
+ // agent-message-center/workspaceAgentMessageCenterCollection.ts
480
470
  var EMPTY_COUNTS = {
481
471
  all: 0,
482
472
  working: 0,
@@ -484,72 +474,133 @@ var EMPTY_COUNTS = {
484
474
  completed: 0,
485
475
  failed: 0
486
476
  };
487
- function buildWorkspaceAgentMessageCenterModel(snapshot, options = {}) {
488
- const needsAttentionBySessionId = latestNeedsAttentionBySessionId(
489
- selectNeedsAttentionItems(snapshot)
477
+ function buildWorkspaceAgentMessageCenterModelFromItems(sourceItems, itemCutoffUnixMs) {
478
+ const items = sourceItems.filter((item) => isWithinItemCutoff(item, itemCutoffUnixMs)).sort(compareItems);
479
+ return {
480
+ waitingCount: items.filter(isWaitingMessageCenterItem).length,
481
+ items,
482
+ counts: countItems(items)
483
+ };
484
+ }
485
+ function isWaitingMessageCenterItem(item) {
486
+ return item.pendingPrompt !== null || item.needsAttentionKind !== null;
487
+ }
488
+ function isInteractiveMessageCenterItem(item) {
489
+ return item.pendingPrompt !== null;
490
+ }
491
+ function selectMessageCenterAttentionDeckItems(items) {
492
+ return items.filter(isInteractiveMessageCenterItem);
493
+ }
494
+ function isCompletedMessageCenterItem(item) {
495
+ return item.status === "completed" || item.status === "canceled" || item.status === "idle";
496
+ }
497
+ function isWithinItemCutoff(item, cutoffUnixMs) {
498
+ if (!Number.isFinite(cutoffUnixMs)) return true;
499
+ if (isWaitingMessageCenterItem(item)) return true;
500
+ const timestamp = item.sortTimeUnixMs || item.lastAgentMessageAtUnixMs || 0;
501
+ return timestamp >= Number(cutoffUnixMs);
502
+ }
503
+ function countItems(items) {
504
+ return items.reduce(
505
+ (counts, item) => {
506
+ counts.all += 1;
507
+ if (isWaitingMessageCenterItem(item)) {
508
+ counts.waiting += 1;
509
+ } else if (isCompletedMessageCenterItem(item)) {
510
+ counts.completed += 1;
511
+ } else if (item.status === "working") {
512
+ counts.working += 1;
513
+ } else if (item.status === "failed") {
514
+ counts.failed += 1;
515
+ }
516
+ return counts;
517
+ },
518
+ { ...EMPTY_COUNTS }
519
+ );
520
+ }
521
+ function compareItems(left, right) {
522
+ const leftWaiting = isWaitingMessageCenterItem(left);
523
+ const rightWaiting = isWaitingMessageCenterItem(right);
524
+ if (leftWaiting !== rightWaiting) return leftWaiting ? -1 : 1;
525
+ return right.sortTimeUnixMs - left.sortTimeUnixMs || left.agentSessionId.localeCompare(right.agentSessionId);
526
+ }
527
+
528
+ // agent-message-center/workspaceAgentMessageCenterModel.ts
529
+ function buildWorkspaceAgentMessageCenterItem({
530
+ session,
531
+ latestTurn,
532
+ messages,
533
+ status,
534
+ needsAttention,
535
+ pendingPrompt,
536
+ latestTurnOutcome,
537
+ options = {}
538
+ }) {
539
+ const messageAnalysis = analyzeMessageCenterSessionMessages(
540
+ session.agentSessionId,
541
+ messages
542
+ );
543
+ const lastAgentMessage = messageAnalysis.latestAgentMessage;
544
+ const title = resolveSessionTitle(
545
+ session,
546
+ messageAnalysis.latestUserMessageSummary,
547
+ messageAnalysis.firstUserMessageSummary
548
+ );
549
+ const digest = buildWorkspaceAgentMessageCenterDigest({
550
+ fallbackTitle: resolveDigestFallbackTitle(session),
551
+ latestAgentMessage: messageAnalysis.latestDigestAgentMessage,
552
+ needsAttention,
553
+ pendingPrompt,
554
+ status
555
+ });
556
+ const agentPresentation = resolveMessageCenterAgentPresentation(
557
+ session.agentTargetId,
558
+ options.agentPresentations
490
559
  );
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(
560
+ return {
561
+ id: `message-center-${session.agentSessionId}`,
562
+ agentSessionId: session.agentSessionId,
563
+ agentTargetId: session.agentTargetId?.trim() || null,
564
+ agentName: agentPresentation?.name ?? null,
565
+ agentAvatarUrl: agentPresentation?.iconUrl ?? null,
566
+ provider: session.provider,
567
+ userId: session.userId?.trim() || null,
568
+ title,
569
+ ...isImportedMessageCenterSession(session) ? { imported: true } : {},
570
+ identity: resolveMessageCenterIdentity(
495
571
  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
521
- }
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)
572
+ options.identityBySessionId
573
+ ),
574
+ cwd: session.cwd,
575
+ status,
576
+ digest,
577
+ lastAgentMessageSummary: lastAgentMessage?.summary ?? needsAttention?.summary ?? title,
578
+ lastAgentMessageAtUnixMs: lastAgentMessage?.occurredAtUnixMs ?? null,
579
+ pendingPrompt,
580
+ needsAttentionKind: needsAttention?.kind ?? null,
581
+ needsAttentionSummary: needsAttention?.summary ?? null,
582
+ latestTurnOutcome,
583
+ sortTimeUnixMs: resolveWorkspaceAgentSessionSortTimeUnixMs({
584
+ ...session,
585
+ latestTurn
586
+ })
587
+ };
588
+ }
589
+ function resolveMessageCenterAgentPresentation(agentTargetId, presentations) {
590
+ const targetId = agentTargetId?.trim() ?? "";
591
+ if (!targetId) {
592
+ return null;
593
+ }
594
+ const presentation = presentations?.find(
595
+ (candidate) => candidate.agentTargetId.trim() === targetId
548
596
  );
597
+ const name = presentation?.name.trim() ?? "";
598
+ if (!presentation || !name) {
599
+ return null;
600
+ }
549
601
  return {
550
- waitingCount: items.filter(isWaitingMessageCenterItem).length,
551
- items: items.sort(compareMessageCenterItems),
552
- counts: countMessageCenterItems(items)
602
+ iconUrl: presentation.iconUrl?.trim() || null,
603
+ name
553
604
  };
554
605
  }
555
606
  function resolveMessageCenterIdentity(agentSessionId, identityBySessionId) {
@@ -572,86 +623,23 @@ function resolveMessageCenterIdentity(agentSessionId, identityBySessionId) {
572
623
  };
573
624
  }
574
625
  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 [];
626
+ return "imported" in session && session.imported === true;
617
627
  }
618
628
  function resolveSessionTitle(session, latestUserMessageSummary, firstUserMessageSummary) {
619
- const latest = latestUserMessageSummary.trim();
620
- if (latest) {
621
- return latest;
622
- }
623
629
  const title = session.title.trim();
624
630
  if (title) {
625
631
  return title;
626
632
  }
633
+ const latest = latestUserMessageSummary.trim();
634
+ if (latest) {
635
+ return latest;
636
+ }
627
637
  return firstUserMessageSummary || session.provider || session.agentSessionId;
628
638
  }
629
639
  function resolveDigestFallbackTitle(session) {
630
640
  return session.title.trim() || session.provider || session.agentSessionId;
631
641
  }
632
- var messageAnalysisByMessages = /* @__PURE__ */ new WeakMap();
633
- var codexPlanImplementationPromptByMessages = /* @__PURE__ */ new WeakMap();
634
642
  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
643
  let firstUserMessageSummary = "";
656
644
  let latestUserMessageSummary = "";
657
645
  let latestUserMessageAtUnixMs = Number.NEGATIVE_INFINITY;
@@ -810,67 +798,6 @@ function isExitPlanMessage(message, input = recordValue2(
810
798
  )) {
811
799
  return includesAny2(normalizedMetadataValues(message), ["exitplanmode"]) || isExitPlanSwitchModeInput(input);
812
800
  }
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
801
  function turnOutcomeFromMessage(agentSessionId, message) {
875
802
  const status = outcomeStatusFromMessage(message);
876
803
  if (!status) {
@@ -904,65 +831,6 @@ function outcomeStatusFromMessage(message) {
904
831
  return null;
905
832
  }
906
833
  }
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
834
  function isAgentMessageRole2(role) {
967
835
  const normalized = role.trim().toLowerCase();
968
836
  return normalized === "assistant" || normalized === "agent";
@@ -1063,1093 +931,1207 @@ function positiveNumber2(value) {
1063
931
 
1064
932
  // agent-message-center/WorkspaceAgentMessageCenterAttentionDeck.tsx
1065
933
  import {
1066
- useEffect as useEffect2,
934
+ useEffect as useEffect3,
1067
935
  useMemo,
1068
936
  useRef as useRef2,
1069
- useState as useState2
937
+ useState as useState3
1070
938
  } from "react";
1071
- import { cn as cn3 } from "@tutti-os/ui-system";
939
+ import { cn as cn4 } from "@tutti-os/ui-system";
1072
940
 
1073
941
  // agent-message-center/WorkspaceAgentMessageCenterCard.tsx
1074
942
  import {
1075
- cloneElement,
1076
943
  memo,
1077
- useCallback,
1078
- useEffect,
944
+ useCallback as useCallback2,
945
+ useEffect as useEffect2,
1079
946
  useLayoutEffect,
1080
947
  useRef,
1081
- useState
948
+ useState as useState2
1082
949
  } from "react";
950
+ import { ChevronDown, ChevronUp } from "lucide-react";
951
+ import { Button as Button2, cn as cn3, StatusDot } from "@tutti-os/ui-system";
952
+
953
+ // agent-message-center/WorkspaceAgentMessageCenterIdentity.tsx
1083
954
  import {
1084
- AppWindow,
1085
- ChevronDown,
1086
- ChevronUp,
1087
- ExternalLink,
1088
- Info
1089
- } from "lucide-react";
955
+ cloneElement,
956
+ useCallback,
957
+ useEffect,
958
+ useState
959
+ } from "react";
960
+ import { ExternalLink, Info } from "lucide-react";
1090
961
  import {
1091
962
  Button,
1092
963
  cn as cn2,
1093
- StatusDot,
1094
964
  Tooltip,
1095
965
  TooltipContent,
1096
966
  TooltipTrigger
1097
967
  } from "@tutti-os/ui-system";
1098
- import {
1099
- isRichTextMentionHref,
1100
- parseRichTextMentionHref
1101
- } from "@tutti-os/ui-rich-text/core";
1102
968
  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",
969
+ function MessageCenterOpenChatButton({
970
+ actionsAccessory,
971
+ alwaysVisible = false,
972
+ item,
973
+ label,
974
+ onOpenChat,
975
+ provider
976
+ }) {
977
+ "use memo";
978
+ return /* @__PURE__ */ jsxs("div", { className: "workspace-agent-message-center__footer flex min-w-0 items-center justify-between gap-2", children: [
979
+ /* @__PURE__ */ jsx2(
980
+ MessageCenterIdentityLabel,
1134
981
  {
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
- ]
1235
- }
1236
- );
1237
- }
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;
1256
- }
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
- );
1272
- return { closing, mounted, onAnimationEnd };
1273
- }
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",
1303
- {
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
- ]
982
+ agentAvatarUrl: item.agentAvatarUrl,
983
+ agentName: item.agentName,
984
+ identity: item.identity,
985
+ provider
1399
986
  }
1400
- );
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
- }
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(":");
1429
- }
1430
- function useBatchedMessageCenterStackItems({
1431
- expanded,
1432
- highlightedItemId,
1433
- items,
1434
- mounted
1435
- }) {
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]);
1452
- useEffect(() => {
1453
- if (!expanded || !mounted || renderCount >= limit) {
1454
- return void 0;
1455
- }
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));
1466
- }
1467
- function MessageCenterStackSummary({
1468
- groupId,
1469
- items,
1470
- onExpand
1471
- }) {
1472
- "use memo";
1473
- const { t } = useTranslation();
1474
- const firstItem = items[0];
1475
- const hasWaiting = items.some((item) => isWaitingMessageCenterItem(item));
1476
- if (!firstItem) {
1477
- return null;
1478
- }
1479
- return /* @__PURE__ */ jsx2(
1480
- "button",
1481
- {
1482
- type: "button",
1483
- "aria-label": t("agentHost.workspaceAgentMessageCenterExpandStackAria", {
1484
- count: items.length
1485
- }),
1486
- className: cn2(
1487
- "group/stack-peek relative block w-full min-w-0 rounded-lg text-left outline-none focus-visible:ring-2 focus-visible:ring-[var(--accent)]",
1488
- items.length > 2 ? "pb-[18px]" : "pb-[10px]"
1489
- ),
1490
- "data-stack-summary-count": items.length,
1491
- "data-stack-provider": firstItem.provider,
1492
- "data-stack-user-id": firstItem.userId ?? "",
1493
- "data-testid": `workspace-agent-message-stack-summary-${groupId}`,
1494
- onClick: () => onExpand(groupId),
1495
- children: /* @__PURE__ */ jsxs(
1496
- "span",
987
+ ),
988
+ /* @__PURE__ */ jsxs("span", { className: "inline-flex shrink-0 items-center gap-2", children: [
989
+ actionsAccessory,
990
+ /* @__PURE__ */ jsxs(
991
+ Button,
1497
992
  {
993
+ type: "button",
994
+ variant: "ghost",
995
+ size: "default",
1498
996
  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)]"
997
+ "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",
998
+ !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"
1502
999
  ),
1000
+ onClick: () => onOpenChat({
1001
+ agentSessionId: item.agentSessionId,
1002
+ provider: item.provider
1003
+ }),
1503
1004
  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) }) })
1005
+ /* @__PURE__ */ jsx2(
1006
+ ExternalLink,
1007
+ {
1008
+ className: "size-[15px]",
1009
+ strokeWidth: 2.2,
1010
+ "aria-hidden": "true"
1011
+ }
1012
+ ),
1013
+ label
1527
1014
  ]
1528
1015
  }
1529
1016
  )
1530
- }
1531
- );
1532
- }
1533
- function messageCenterStackRawPreviewText(item) {
1534
- return item.digest.primary.summary.trim() || item.lastAgentMessageSummary.trim() || item.title;
1535
- }
1536
- function messageCenterStackPreviewText(item) {
1537
- return formatAgentSessionMentionText(messageCenterStackRawPreviewText(item), {
1538
- language: getActiveUiLanguage()
1539
- });
1017
+ ] })
1018
+ ] });
1540
1019
  }
1541
- var MESSAGE_CENTER_PREVIEW_MARKDOWN_LINK_PATTERN = /\[((?:\\.|[^\]\\])*)\]\(([^)\s]+)\)/g;
1542
- var MESSAGE_CENTER_PREVIEW_LABEL_ESCAPE_PATTERN = /\\([\\[\]()])/g;
1543
- function messageCenterStackPreviewNodes(item) {
1544
- const text = messageCenterStackRawPreviewText(item);
1545
- const nodes = [];
1546
- let lastIndex = 0;
1547
- let mentionIndex = 0;
1548
- for (const match of text.matchAll(
1549
- MESSAGE_CENTER_PREVIEW_MARKDOWN_LINK_PATTERN
1550
- )) {
1551
- const [fullMatch, rawLabel = "", href = ""] = match;
1552
- const matchStart = match.index ?? 0;
1553
- if (matchStart > lastIndex) {
1554
- nodes.push(text.slice(lastIndex, matchStart));
1555
- }
1556
- const label = rawLabel.replace(
1557
- MESSAGE_CENTER_PREVIEW_LABEL_ESCAPE_PATTERN,
1558
- "$1"
1020
+ function MessageCenterIdentityLabel({
1021
+ agentAvatarUrl,
1022
+ agentName,
1023
+ identity,
1024
+ provider
1025
+ }) {
1026
+ "use memo";
1027
+ if (!identity) {
1028
+ return /* @__PURE__ */ jsx2(
1029
+ AgentProviderLabel,
1030
+ {
1031
+ agentAvatarUrl,
1032
+ agentName,
1033
+ provider
1034
+ }
1559
1035
  );
1560
- const mention = parseRichTextMentionHref(href, label);
1561
- if (!mention) {
1562
- nodes.push(isRichTextMentionHref(href) ? label : fullMatch);
1563
- } else {
1564
- const kind = messageCenterPreviewMentionKind(mention.providerId);
1565
- const displayLabel = label || mention.label;
1566
- nodes.push(
1567
- kind ? /* @__PURE__ */ jsx2(
1568
- MessageCenterPreviewMentionChip,
1036
+ }
1037
+ const resolvedAgentAvatarUrl = identity.agentAvatarUrl?.trim() || agentAvatarUrl?.trim() || managedAgentRoundedIconUrl(provider);
1038
+ const title = `${identity.userName} & ${identity.agentName}`;
1039
+ return /* @__PURE__ */ jsxs(
1040
+ "span",
1041
+ {
1042
+ className: "workspace-agent-message-center__identity inline-flex min-w-0 max-w-full items-center gap-2",
1043
+ title,
1044
+ children: [
1045
+ /* @__PURE__ */ jsx2(
1046
+ MessageCenterIdentityAvatarStack,
1569
1047
  {
1570
- kind,
1571
- label: displayLabel
1572
- },
1573
- `mention-${mentionIndex}`
1574
- ) : displayLabel
1575
- );
1576
- mentionIndex += 1;
1048
+ userAvatarUrl: identity.userAvatarUrl,
1049
+ userName: identity.userName,
1050
+ agentAvatarUrl: resolvedAgentAvatarUrl
1051
+ }
1052
+ ),
1053
+ /* @__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: [
1054
+ /* @__PURE__ */ jsx2("span", { className: "min-w-0 truncate", children: identity.userName }),
1055
+ /* @__PURE__ */ jsx2("span", { className: "shrink-0 text-[var(--text-tertiary)]", children: "&" }),
1056
+ /* @__PURE__ */ jsx2("span", { className: "min-w-0 truncate", children: identity.agentName })
1057
+ ] })
1058
+ ]
1577
1059
  }
1578
- lastIndex = matchStart + fullMatch.length;
1579
- }
1580
- if (lastIndex < text.length) {
1581
- nodes.push(text.slice(lastIndex));
1582
- }
1583
- return nodes;
1060
+ );
1584
1061
  }
1585
- function messageCenterPreviewMentionKind(providerId) {
1586
- switch (providerId.trim().toLowerCase()) {
1587
- case "agent-session":
1588
- return "session";
1589
- case "workspace-app":
1590
- return "workspace-app";
1591
- case "workspace-issue":
1592
- return "workspace-issue";
1593
- default:
1594
- return null;
1062
+ function MessageCenterIdentityAvatarMark({
1063
+ agentAvatarUrl,
1064
+ identity,
1065
+ provider,
1066
+ userId
1067
+ }) {
1068
+ "use memo";
1069
+ const userName = identity?.userName.trim() || userId?.trim() || "";
1070
+ if (!userName) {
1071
+ return /* @__PURE__ */ jsx2(
1072
+ "img",
1073
+ {
1074
+ src: agentAvatarUrl?.trim() || managedAgentRoundedIconUrl(provider),
1075
+ alt: "",
1076
+ className: "size-5 shrink-0 rounded-full",
1077
+ decoding: "async",
1078
+ loading: "lazy",
1079
+ draggable: false,
1080
+ "aria-hidden": "true"
1081
+ }
1082
+ );
1595
1083
  }
1084
+ return /* @__PURE__ */ jsx2(
1085
+ MessageCenterIdentityAvatarStack,
1086
+ {
1087
+ userAvatarUrl: identity?.userAvatarUrl,
1088
+ userName,
1089
+ agentAvatarUrl: identity?.agentAvatarUrl?.trim() || agentAvatarUrl?.trim() || managedAgentRoundedIconUrl(provider)
1090
+ }
1091
+ );
1596
1092
  }
1597
- function MessageCenterPreviewMentionChip({
1598
- kind,
1599
- label
1093
+ function MessageCenterIdentityAvatarStack({
1094
+ agentAvatarUrl,
1095
+ userAvatarUrl: rawUserAvatarUrl,
1096
+ userName
1600
1097
  }) {
1098
+ "use memo";
1099
+ const [userAvatarFailed, setUserAvatarFailed] = useState(false);
1100
+ const userAvatarUrl = rawUserAvatarUrl?.trim() ?? "";
1101
+ const userImageUrl = userAvatarUrl.length > 0 && !userAvatarFailed ? userAvatarUrl : userAvatarPlaceholderUrl;
1102
+ useEffect(() => {
1103
+ setUserAvatarFailed(false);
1104
+ }, [userAvatarUrl]);
1601
1105
  return /* @__PURE__ */ jsxs(
1602
1106
  "span",
1603
1107
  {
1604
- className: "tsh-agent-object-token tsh-agent-object-token--entity",
1605
- "data-agent-mention-kind": kind,
1108
+ className: "workspace-agent-message-center__identity-avatar-stack inline-flex w-9 shrink-0 items-center",
1109
+ "aria-hidden": "true",
1606
1110
  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(
1608
- "span",
1111
+ /* @__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(
1112
+ "img",
1609
1113
  {
1610
- className: "tsh-agent-object-token__kind-icon",
1611
- "aria-hidden": "true"
1114
+ src: userImageUrl,
1115
+ alt: userName,
1116
+ className: "size-full object-cover",
1117
+ decoding: "async",
1118
+ loading: "lazy",
1119
+ referrerPolicy: "no-referrer",
1120
+ draggable: false,
1121
+ onError: () => {
1122
+ setUserAvatarFailed(true);
1123
+ }
1612
1124
  }
1613
1125
  ) }),
1614
- /* @__PURE__ */ jsx2("span", { className: "tsh-agent-object-token__main", children: label })
1126
+ /* @__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(
1127
+ "img",
1128
+ {
1129
+ src: agentAvatarUrl,
1130
+ alt: "",
1131
+ className: "size-full object-cover",
1132
+ decoding: "async",
1133
+ loading: "lazy",
1134
+ draggable: false
1135
+ }
1136
+ ) })
1615
1137
  ]
1616
1138
  }
1617
1139
  );
1618
1140
  }
1619
- function resolveMessageCenterNotificationAction(item, input) {
1620
- if (input.action) {
1621
- return normalizeMessageCenterNotificationAction(input.action);
1622
- }
1623
- if (!input.optionId) {
1624
- return null;
1625
- }
1626
- const prompt = item.pendingPrompt;
1627
- const option = prompt && "options" in prompt ? prompt.options.find((candidate) => candidate.id === input.optionId) : null;
1628
- const optionToken = `${option?.kind ?? ""}:${input.optionId}`.toLowerCase();
1629
- if (optionToken.includes("allow") || optionToken.includes("accept")) {
1630
- return "accept";
1631
- }
1632
- if (optionToken.includes("deny") || optionToken.includes("reject") || optionToken.includes("disallow")) {
1633
- return "reject";
1634
- }
1635
- return input.optionId;
1636
- }
1637
- function buildWorkspaceAgentInteractivePromptLabels(t, provider) {
1638
- return {
1639
- approvalLead: t("agentHost.agentGui.approvalRequired", {
1640
- provider: provider ? workspaceAgentProviderLabel(provider) : t("agentHost.workspaceAgentsGenericAgentName")
1641
- }),
1642
- planLead: t("agentHost.agentGui.planLead"),
1643
- planModes: [
1644
- {
1645
- id: "acceptEdits",
1646
- label: t("agentHost.agentGui.planModes.acceptEdits.label"),
1647
- description: t("agentHost.agentGui.planModes.acceptEdits.description")
1648
- },
1649
- {
1650
- id: "default",
1651
- label: t("agentHost.agentGui.planModes.askFirst.label"),
1652
- description: t("agentHost.agentGui.planModes.askFirst.description")
1653
- },
1654
- {
1655
- id: "bypassPermissions",
1656
- label: t("agentHost.agentGui.planModes.allowAll.label"),
1657
- description: t("agentHost.agentGui.planModes.allowAll.description")
1658
- },
1659
- {
1660
- id: "auto",
1661
- label: t("agentHost.agentGui.planModes.auto.label"),
1662
- description: t("agentHost.agentGui.planModes.auto.description")
1663
- }
1664
- ],
1665
- stayInPlan: t("agentHost.agentGui.stayInPlan"),
1666
- sendFeedback: t("agentHost.agentGui.sendFeedback"),
1667
- feedbackPlaceholder: t("agentHost.agentGui.feedbackPlaceholder"),
1668
- previousQuestion: t("agentHost.agentGui.previousQuestion"),
1669
- nextQuestion: t("agentHost.agentGui.nextQuestion"),
1670
- submitAnswers: t("agentHost.agentGui.submitAnswers"),
1671
- answerPlaceholder: t("agentHost.agentGui.answerPlaceholder"),
1672
- waitingForAnswer: t("agentHost.agentGui.waitingForAnswer"),
1673
- planImplementationLead: t("agentHost.agentGui.planImplementationLead"),
1674
- planImplementationConfirm: t(
1675
- "agentHost.agentGui.planImplementationConfirm"
1676
- ),
1677
- planImplementationFeedbackPlaceholder: t(
1678
- "agentHost.agentGui.planImplementationFeedbackPlaceholder"
1679
- ),
1680
- planImplementationSend: t("agentHost.agentGui.planImplementationSend"),
1681
- planImplementationSkip: t("agentHost.agentGui.planImplementationSkip")
1682
- };
1683
- }
1684
- function normalizeMessageCenterNotificationAction(action) {
1685
- switch (action) {
1686
- case "allow":
1687
- return "accept";
1688
- case "deny":
1689
- return "reject";
1690
- default:
1691
- return action;
1692
- }
1693
- }
1694
- function messageCenterVisibleSummary(item) {
1695
- const summary = item.digest.primary.summary.trim();
1696
- if (item.pendingPrompt?.kind === "approval" && isGenericApprovalSummary(summary)) {
1697
- return "";
1698
- }
1699
- return summary;
1700
- }
1701
- function isGenericApprovalSummary(summary) {
1702
- const normalized = summary.trim().toLowerCase();
1703
- return normalized === "approval";
1704
- }
1705
- function MessageCenterSummary({
1706
- emptyLabel,
1707
- item,
1708
- lazy,
1709
- onLinkAction,
1710
- summary
1711
- }) {
1141
+ function ProjectPathInfo({ path }) {
1712
1142
  "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;
1736
- }
1737
- const element = summaryRef.current;
1738
- if (!element) {
1739
- return void 0;
1740
- }
1741
- const updateOverflowState = () => {
1742
- setIsOverflowing(element.scrollHeight > element.clientHeight + 1);
1743
- };
1744
- let resizeObserver = null;
1745
- const timeoutId = window.setTimeout(() => {
1746
- updateOverflowState();
1747
- resizeObserver = new ResizeObserver(updateOverflowState);
1748
- resizeObserver.observe(element);
1749
- }, MESSAGE_CENTER_SUMMARY_OVERFLOW_MEASURE_DELAY_MS);
1750
- return () => {
1751
- window.clearTimeout(timeoutId);
1752
- resizeObserver?.disconnect();
1753
- };
1754
- }, [shouldMeasureOverflow, summary]);
1755
1143
  return /* @__PURE__ */ jsx2(
1756
- AgentVerticalScrollArea,
1144
+ LazyMessageCenterTooltip,
1757
1145
  {
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,
1146
+ content: path,
1147
+ side: "top",
1148
+ align: "start",
1149
+ className: "max-w-[320px] text-[11px] [overflow-wrap:anywhere]",
1150
+ children: /* @__PURE__ */ jsx2(
1151
+ "button",
1769
1152
  {
1770
- content: summary,
1771
- className: "[&_a]:text-[var(--tutti-purple)] [&_code]:text-[var(--text-secondary)] [&_hr]:border-t-[color-mix(in_srgb,var(--text-primary)_14%,transparent)] [&_ol]:!bg-transparent [&_p]:m-0 [&_th]:bg-[color-mix(in_srgb,var(--background-panel)_94%,var(--text-primary))] [&_th]:text-[var(--text-primary)] [&_ul]:!bg-transparent text-[var(--text-primary)]",
1772
- onLinkAction: handleLinkAction,
1773
- workspaceLinkContext: {
1774
- workspaceRoot: item.cwd || null,
1775
- basePath: item.cwd,
1776
- source: "agent-markdown"
1777
- },
1778
- enableImageZoom: true
1779
- }
1780
- ) : summary ? /* @__PURE__ */ jsx2("div", { className: "whitespace-pre-wrap [overflow-wrap:anywhere]", children: summary }) : emptyLabel
1781
- }
1782
- );
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;
1800
- }
1801
- const observer = new IntersectionObserver(
1802
- (entries) => {
1803
- if (entries.some((entry) => entry.isIntersecting)) {
1804
- setReady(true);
1805
- observer.disconnect();
1153
+ type: "button",
1154
+ 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",
1155
+ "aria-label": path,
1156
+ children: /* @__PURE__ */ jsx2(Info, { className: "size-3.5", strokeWidth: 2, "aria-hidden": "true" })
1806
1157
  }
1807
- },
1808
- { rootMargin: MESSAGE_CENTER_SUMMARY_LAZY_ROOT_MARGIN }
1809
- );
1810
- observer.observe(element);
1811
- return () => observer.disconnect();
1812
- }, [lazy, ready, ref]);
1813
- return ready;
1814
- }
1815
- function useDeferredMessageCenterSummaryMeasureReady(ref, enabled) {
1816
- const [ready, setReady] = useState(false);
1817
- useEffect(() => {
1818
- if (!enabled) {
1819
- setReady(false);
1820
- return void 0;
1821
- }
1822
- if (ready) {
1823
- return void 0;
1158
+ )
1824
1159
  }
1825
- const element = ref.current;
1826
- if (!element || typeof IntersectionObserver === "undefined") {
1827
- const timeoutId2 = window.setTimeout(
1828
- () => setReady(true),
1829
- MESSAGE_CENTER_SUMMARY_OVERFLOW_MEASURE_DELAY_MS
1830
- );
1831
- return () => {
1832
- window.clearTimeout(timeoutId2);
1833
- };
1160
+ );
1161
+ }
1162
+ function LazyMessageCenterTooltip({
1163
+ align,
1164
+ children,
1165
+ className,
1166
+ content,
1167
+ side
1168
+ }) {
1169
+ "use memo";
1170
+ const [hydrated, setHydrated] = useState(false);
1171
+ const [open, setOpen] = useState(false);
1172
+ const showTooltip = useCallback(() => {
1173
+ setHydrated(true);
1174
+ setOpen(true);
1175
+ }, []);
1176
+ const hideTooltip = useCallback(() => {
1177
+ setOpen(false);
1178
+ }, []);
1179
+ const trigger = cloneElement(children, {
1180
+ onBlur: (event) => {
1181
+ children.props.onBlur?.(event);
1182
+ hideTooltip();
1183
+ },
1184
+ onFocus: (event) => {
1185
+ children.props.onFocus?.(event);
1186
+ showTooltip();
1187
+ },
1188
+ onPointerEnter: (event) => {
1189
+ children.props.onPointerEnter?.(event);
1190
+ showTooltip();
1191
+ },
1192
+ onPointerLeave: (event) => {
1193
+ children.props.onPointerLeave?.(event);
1194
+ hideTooltip();
1834
1195
  }
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);
1850
- return () => {
1851
- observer.disconnect();
1852
- if (timeoutId !== null) {
1853
- window.clearTimeout(timeoutId);
1854
- }
1855
- };
1856
- }, [enabled, ready, ref]);
1857
- return ready;
1196
+ });
1197
+ if (!hydrated) {
1198
+ return trigger;
1199
+ }
1200
+ return /* @__PURE__ */ jsxs(Tooltip, { open, onOpenChange: setOpen, children: [
1201
+ /* @__PURE__ */ jsx2(TooltipTrigger, { asChild: true, children: trigger }),
1202
+ /* @__PURE__ */ jsx2(TooltipContent, { side, align, className, children: content })
1203
+ ] });
1858
1204
  }
1859
- function MessageCenterOpenChatButton({
1860
- actionsAccessory,
1861
- alwaysVisible = false,
1862
- item,
1863
- label,
1864
- onOpenChat,
1205
+ function AgentProviderLabel({
1206
+ agentAvatarUrl,
1207
+ agentName,
1865
1208
  provider
1866
1209
  }) {
1867
1210
  "use memo";
1868
- return /* @__PURE__ */ jsxs("div", { className: "workspace-agent-message-center__footer flex min-w-0 items-center justify-between gap-2", children: [
1211
+ const label = agentName?.trim() || workspaceAgentProviderLabel(provider);
1212
+ return /* @__PURE__ */ jsxs("span", { className: "workspace-agent-message-center__provider inline-flex min-w-0 max-w-full items-center gap-1.5", children: [
1869
1213
  /* @__PURE__ */ jsx2(
1870
- MessageCenterIdentityLabel,
1214
+ "img",
1871
1215
  {
1872
- identity: item.identity,
1873
- provider
1216
+ src: agentAvatarUrl?.trim() || managedAgentRoundedIconUrl(provider),
1217
+ alt: "",
1218
+ className: "workspace-agent-message-center__provider-icon size-5 shrink-0 rounded-full",
1219
+ decoding: "async",
1220
+ loading: "lazy",
1221
+ draggable: false,
1222
+ "aria-hidden": "true"
1874
1223
  }
1875
1224
  ),
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
- ] })
1225
+ /* @__PURE__ */ jsx2("span", { className: "workspace-agent-message-center__provider-name min-w-0 truncate text-[13px] leading-5 text-[var(--text-secondary)]", children: label })
1906
1226
  ] });
1907
1227
  }
1908
- function MessageCenterIdentityLabel({
1909
- identity,
1910
- provider
1228
+ function statusClass(item) {
1229
+ if (isWaitingMessageCenterItem(item)) {
1230
+ return "waiting";
1231
+ }
1232
+ if (item.status === "idle") {
1233
+ return "completed";
1234
+ }
1235
+ return item.status;
1236
+ }
1237
+ function messageCenterStatusTone(item) {
1238
+ if (isWaitingMessageCenterItem(item)) {
1239
+ return "amber";
1240
+ }
1241
+ if (item.status === "completed" || item.status === "idle") {
1242
+ return "green";
1243
+ }
1244
+ if (item.status === "canceled") {
1245
+ return "amber";
1246
+ }
1247
+ if (item.status === "failed") {
1248
+ return "red";
1249
+ }
1250
+ if (item.status === "working") {
1251
+ return "blue";
1252
+ }
1253
+ return "neutral";
1254
+ }
1255
+ function messageCenterStatusToneClass(tone) {
1256
+ switch (tone) {
1257
+ case "amber":
1258
+ return "text-[var(--state-warning)]";
1259
+ case "blue":
1260
+ return "text-[var(--status-running)]";
1261
+ case "green":
1262
+ return "text-[var(--state-success)]";
1263
+ case "red":
1264
+ return "text-[var(--state-danger)]";
1265
+ case "neutral":
1266
+ return "text-[var(--text-secondary)]";
1267
+ }
1268
+ }
1269
+
1270
+ // agent-message-center/workspaceAgentMessageCenterPreview.tsx
1271
+ import { AppWindow } from "lucide-react";
1272
+ import {
1273
+ isRichTextMentionHref as isRichTextMentionHref2,
1274
+ parseRichTextMentionHref as parseRichTextMentionHref2
1275
+ } from "@tutti-os/ui-rich-text/core";
1276
+
1277
+ // shared/utils/agentSessionMentionText.ts
1278
+ import {
1279
+ isRichTextMentionHref,
1280
+ parseRichTextMentionHref
1281
+ } from "@tutti-os/ui-rich-text/core";
1282
+ var MARKDOWN_LINK_PATTERN = /\[((?:\\.|[^\]\\])*)\]\(([^)\s]+)\)/g;
1283
+ var MARKDOWN_LABEL_ESCAPE_PATTERN = /\\([\\[\]()])/g;
1284
+ var SESSION_MENTION_DISPLAY_PREFIX_BY_LANGUAGE = {
1285
+ "zh-CN": "@\u4F1A\u8BDD \xB7 ",
1286
+ en: "@session \xB7 "
1287
+ };
1288
+ var PLAIN_SESSION_AGENT_LABELS = [
1289
+ "Claude Code",
1290
+ "Hermes Agent",
1291
+ "OpenClaw",
1292
+ "Nexight",
1293
+ "Hermes",
1294
+ "Codex"
1295
+ ];
1296
+ function formatAgentSessionMentionText(value, options = {}) {
1297
+ const trimmed = value?.trim() ?? "";
1298
+ if (!trimmed) {
1299
+ return "";
1300
+ }
1301
+ const sessionMentionDisplayPrefix = sessionMentionDisplayPrefixForLanguage(
1302
+ options.language
1303
+ );
1304
+ const withSessionMentionsNormalized = trimmed.replace(
1305
+ MARKDOWN_LINK_PATTERN,
1306
+ (fullMatch, rawLabel, href) => {
1307
+ const label = unescapeMarkdownLabel(rawLabel);
1308
+ const mention = parseRichTextMentionHref(href, label);
1309
+ if (!mention) {
1310
+ return isRichTextMentionHref(href) ? label : fullMatch;
1311
+ }
1312
+ const providerId = mention.providerId.trim().toLowerCase();
1313
+ const displayLabel = label || mention.label;
1314
+ if (providerId === "agent-session") {
1315
+ return formatSessionLabel(displayLabel, sessionMentionDisplayPrefix);
1316
+ }
1317
+ if (providerId === "workspace-issue") {
1318
+ return formatIssueLabel(displayLabel);
1319
+ }
1320
+ return displayLabel;
1321
+ }
1322
+ );
1323
+ const normalized = normalizeAgentTitleText(withSessionMentionsNormalized);
1324
+ if (isPlainSessionMentionText(normalized, sessionMentionDisplayPrefix)) {
1325
+ return formatSessionLabel(normalized, sessionMentionDisplayPrefix);
1326
+ }
1327
+ return normalized;
1328
+ }
1329
+ function isPlainSessionMentionText(value, sessionMentionDisplayPrefix) {
1330
+ const trimmed = value.trim();
1331
+ if (!trimmed.startsWith("@") || trimmed.startsWith(sessionMentionDisplayPrefix)) {
1332
+ return false;
1333
+ }
1334
+ return PLAIN_SESSION_AGENT_LABELS.some((agentLabel) => {
1335
+ const ampersandSeparator = ` & ${agentLabel}`;
1336
+ const ampersandIndex = trimmed.indexOf(ampersandSeparator);
1337
+ if (ampersandIndex > 1) {
1338
+ const trailing = trimmed.slice(
1339
+ ampersandIndex + ampersandSeparator.length
1340
+ );
1341
+ if (trailing === "" || trailing.startsWith(" ")) {
1342
+ return true;
1343
+ }
1344
+ }
1345
+ const dottedSeparator = ` \xB7 ${agentLabel} \xB7 `;
1346
+ return trimmed.indexOf(dottedSeparator) > 1;
1347
+ });
1348
+ }
1349
+ function sessionMentionDisplayPrefixForLanguage(language) {
1350
+ return SESSION_MENTION_DISPLAY_PREFIX_BY_LANGUAGE[language ?? "en"];
1351
+ }
1352
+ function formatSessionLabel(label, sessionMentionDisplayPrefix) {
1353
+ const normalizedLabel = label.trim().replace(/^@+/, "").trim();
1354
+ return normalizedLabel ? `${sessionMentionDisplayPrefix}${normalizedLabel}` : label.trim();
1355
+ }
1356
+ function formatIssueLabel(label) {
1357
+ const normalizedLabel = label.trim().replace(/^@+/, "").trim();
1358
+ return normalizedLabel ? `@Task \xB7 ${normalizedLabel}` : label.trim();
1359
+ }
1360
+ function unescapeMarkdownLabel(label) {
1361
+ return label.replace(MARKDOWN_LABEL_ESCAPE_PATTERN, "$1");
1362
+ }
1363
+
1364
+ // agent-message-center/workspaceAgentMessageCenterPreview.tsx
1365
+ import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
1366
+ function messageCenterStackRawPreviewText(item) {
1367
+ return item.digest.primary.summary.trim() || item.lastAgentMessageSummary.trim() || item.title;
1368
+ }
1369
+ function messageCenterStackPreviewText(item) {
1370
+ return formatAgentSessionMentionText(messageCenterStackRawPreviewText(item), {
1371
+ language: getActiveUiLanguage()
1372
+ });
1373
+ }
1374
+ var MESSAGE_CENTER_PREVIEW_MARKDOWN_LINK_PATTERN = /\[((?:\\.|[^\]\\])*)\]\(([^)\s]+)\)/g;
1375
+ var MESSAGE_CENTER_PREVIEW_LABEL_ESCAPE_PATTERN = /\\([\\[\]()])/g;
1376
+ function messageCenterStackPreviewNodes(item) {
1377
+ const text = messageCenterStackRawPreviewText(item);
1378
+ const nodes = [];
1379
+ let lastIndex = 0;
1380
+ let mentionIndex = 0;
1381
+ for (const match of text.matchAll(
1382
+ MESSAGE_CENTER_PREVIEW_MARKDOWN_LINK_PATTERN
1383
+ )) {
1384
+ const [fullMatch, rawLabel = "", href = ""] = match;
1385
+ const matchStart = match.index ?? 0;
1386
+ if (matchStart > lastIndex) {
1387
+ nodes.push(text.slice(lastIndex, matchStart));
1388
+ }
1389
+ const label = rawLabel.replace(
1390
+ MESSAGE_CENTER_PREVIEW_LABEL_ESCAPE_PATTERN,
1391
+ "$1"
1392
+ );
1393
+ const mention = parseRichTextMentionHref2(href, label);
1394
+ if (!mention) {
1395
+ nodes.push(isRichTextMentionHref2(href) ? label : fullMatch);
1396
+ } else {
1397
+ const kind = messageCenterPreviewMentionKind(mention.providerId);
1398
+ const displayLabel = label || mention.label;
1399
+ nodes.push(
1400
+ kind ? /* @__PURE__ */ jsx3(
1401
+ MessageCenterPreviewMentionChip,
1402
+ {
1403
+ kind,
1404
+ label: displayLabel
1405
+ },
1406
+ `mention-${mentionIndex}`
1407
+ ) : displayLabel
1408
+ );
1409
+ mentionIndex += 1;
1410
+ }
1411
+ lastIndex = matchStart + fullMatch.length;
1412
+ }
1413
+ if (lastIndex < text.length) {
1414
+ nodes.push(text.slice(lastIndex));
1415
+ }
1416
+ return nodes;
1417
+ }
1418
+ function messageCenterPreviewMentionKind(providerId) {
1419
+ switch (providerId.trim().toLowerCase()) {
1420
+ case "agent-session":
1421
+ return "session";
1422
+ case "workspace-app":
1423
+ return "workspace-app";
1424
+ case "workspace-issue":
1425
+ return "workspace-issue";
1426
+ default:
1427
+ return null;
1428
+ }
1429
+ }
1430
+ function MessageCenterPreviewMentionChip({
1431
+ kind,
1432
+ label
1911
1433
  }) {
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(
1434
+ return /* @__PURE__ */ jsxs2(
1919
1435
  "span",
1920
1436
  {
1921
- className: "workspace-agent-message-center__identity inline-flex min-w-0 max-w-full items-center gap-2",
1922
- title,
1437
+ className: "tsh-agent-object-token tsh-agent-object-token--entity",
1438
+ "data-agent-mention-kind": kind,
1923
1439
  children: [
1924
- /* @__PURE__ */ jsx2(
1925
- MessageCenterIdentityAvatarStack,
1440
+ /* @__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(
1441
+ "span",
1926
1442
  {
1927
- userAvatarUrl: identity.userAvatarUrl,
1928
- userName: identity.userName,
1929
- agentAvatarUrl
1443
+ className: "tsh-agent-object-token__kind-icon",
1444
+ "aria-hidden": "true"
1930
1445
  }
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
- ] })
1446
+ ) }),
1447
+ /* @__PURE__ */ jsx3("span", { className: "tsh-agent-object-token__main", children: label })
1937
1448
  ]
1938
1449
  }
1939
1450
  );
1940
1451
  }
1941
- function MessageCenterIdentityAvatarMark({
1942
- identity,
1943
- provider,
1944
- userId
1945
- }) {
1946
- "use memo";
1947
- const userName = identity?.userName.trim() || userId?.trim() || "";
1948
- if (!userName) {
1949
- return /* @__PURE__ */ jsx2(
1950
- "img",
1452
+ function resolveMessageCenterNotificationAction(item, input) {
1453
+ if (input.action) {
1454
+ return normalizeMessageCenterNotificationAction(input.action);
1455
+ }
1456
+ if (!input.optionId) {
1457
+ return null;
1458
+ }
1459
+ const prompt = item.pendingPrompt;
1460
+ const option = prompt && "options" in prompt ? prompt.options.find((candidate) => candidate.id === input.optionId) : null;
1461
+ const optionToken = `${option?.kind ?? ""}:${input.optionId}`.toLowerCase();
1462
+ if (optionToken.includes("allow") || optionToken.includes("accept")) {
1463
+ return "accept";
1464
+ }
1465
+ if (optionToken.includes("deny") || optionToken.includes("reject") || optionToken.includes("disallow")) {
1466
+ return "reject";
1467
+ }
1468
+ return input.optionId;
1469
+ }
1470
+ function buildWorkspaceAgentInteractivePromptLabels(t, provider) {
1471
+ return {
1472
+ approvalLead: t("agentHost.agentGui.approvalRequired", {
1473
+ provider: provider ? workspaceAgentProviderLabel(provider) : t("agentHost.workspaceAgentsGenericAgentName")
1474
+ }),
1475
+ planLead: t("agentHost.agentGui.planLead"),
1476
+ planModes: [
1477
+ {
1478
+ id: "acceptEdits",
1479
+ label: t("agentHost.agentGui.planModes.acceptEdits.label"),
1480
+ description: t("agentHost.agentGui.planModes.acceptEdits.description")
1481
+ },
1482
+ {
1483
+ id: "default",
1484
+ label: t("agentHost.agentGui.planModes.askFirst.label"),
1485
+ description: t("agentHost.agentGui.planModes.askFirst.description")
1486
+ },
1487
+ {
1488
+ id: "bypassPermissions",
1489
+ label: t("agentHost.agentGui.planModes.allowAll.label"),
1490
+ description: t("agentHost.agentGui.planModes.allowAll.description")
1491
+ },
1492
+ {
1493
+ id: "auto",
1494
+ label: t("agentHost.agentGui.planModes.auto.label"),
1495
+ description: t("agentHost.agentGui.planModes.auto.description")
1496
+ }
1497
+ ],
1498
+ stayInPlan: t("agentHost.agentGui.stayInPlan"),
1499
+ sendFeedback: t("agentHost.agentGui.sendFeedback"),
1500
+ feedbackPlaceholder: t("agentHost.agentGui.feedbackPlaceholder"),
1501
+ previousQuestion: t("agentHost.agentGui.previousQuestion"),
1502
+ nextQuestion: t("agentHost.agentGui.nextQuestion"),
1503
+ submitAnswers: t("agentHost.agentGui.submitAnswers"),
1504
+ answerPlaceholder: t("agentHost.agentGui.answerPlaceholder"),
1505
+ waitingForAnswer: t("agentHost.agentGui.waitingForAnswer"),
1506
+ planImplementationLead: t("agentHost.agentGui.planImplementationLead"),
1507
+ planImplementationConfirm: t(
1508
+ "agentHost.agentGui.planImplementationConfirm"
1509
+ ),
1510
+ planImplementationFeedbackPlaceholder: t(
1511
+ "agentHost.agentGui.planImplementationFeedbackPlaceholder"
1512
+ ),
1513
+ planImplementationSend: t("agentHost.agentGui.planImplementationSend"),
1514
+ planImplementationSkip: t("agentHost.agentGui.planImplementationSkip")
1515
+ };
1516
+ }
1517
+ function normalizeMessageCenterNotificationAction(action) {
1518
+ switch (action) {
1519
+ case "allow":
1520
+ return "accept";
1521
+ case "deny":
1522
+ return "reject";
1523
+ default:
1524
+ return action;
1525
+ }
1526
+ }
1527
+
1528
+ // agent-message-center/WorkspaceAgentMessageCenterCard.tsx
1529
+ import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
1530
+ function stopMessageCenterTextPointerPropagation(event) {
1531
+ event.stopPropagation();
1532
+ }
1533
+ var WorkspaceAgentMessageCenterCard = memo(
1534
+ function WorkspaceAgentMessageCenterCard2({
1535
+ cardRef,
1536
+ actionsAccessory,
1537
+ footerAccessory,
1538
+ headerAccessory,
1539
+ highlighted = false,
1540
+ interactive = true,
1541
+ item,
1542
+ isSubmitting,
1543
+ lazySummary = false,
1544
+ summaryAccessory,
1545
+ onLinkAction,
1546
+ onOpenChat,
1547
+ onSubmitPrompt
1548
+ }) {
1549
+ "use memo";
1550
+ const { t } = useTranslation();
1551
+ const prompt = item.pendingPrompt;
1552
+ const displayTitle = item.title.trim();
1553
+ const summary = messageCenterVisibleSummary(item);
1554
+ const displayStatus = statusClass(item);
1555
+ const statusTone = messageCenterStatusTone(item);
1556
+ const statusLabel = workspaceAgentActivityStatusLabel(displayStatus, t);
1557
+ return /* @__PURE__ */ jsxs3(
1558
+ "article",
1559
+ {
1560
+ ref: cardRef,
1561
+ className: cn3(
1562
+ "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]",
1563
+ isWaitingMessageCenterItem(item) && "agent-gui-edge-glow border-[var(--tutti-purple-border)] bg-[var(--tutti-purple-bg)]",
1564
+ highlighted && "outline-2 outline-[var(--accent)]"
1565
+ ),
1566
+ "data-highlighted": highlighted ? "true" : void 0,
1567
+ "data-message-center-digest-kind": item.digest.primary.kind,
1568
+ "data-message-center-item-id": item.id,
1569
+ "data-waiting": isWaitingMessageCenterItem(item) ? "true" : void 0,
1570
+ "data-status": displayStatus,
1571
+ tabIndex: highlighted ? -1 : void 0,
1572
+ children: [
1573
+ /* @__PURE__ */ jsxs3("div", { className: "flex min-w-0 items-center justify-between gap-2.5", children: [
1574
+ /* @__PURE__ */ jsxs3("div", { className: "flex min-w-0 items-center gap-1.5", children: [
1575
+ /* @__PURE__ */ jsx4(
1576
+ LazyMessageCenterTooltip,
1577
+ {
1578
+ content: displayTitle,
1579
+ side: "top",
1580
+ align: "start",
1581
+ className: "max-w-[min(360px,calc(100vw-32px))] whitespace-normal text-left [overflow-wrap:anywhere]",
1582
+ children: /* @__PURE__ */ jsx4(
1583
+ "h3",
1584
+ {
1585
+ className: "workspace-agent-message-center__copy-text min-w-0 truncate text-[13px] font-bold leading-5 text-[var(--text-secondary)]",
1586
+ onPointerDown: stopMessageCenterTextPointerPropagation,
1587
+ children: displayTitle
1588
+ }
1589
+ )
1590
+ }
1591
+ ),
1592
+ item.cwd ? /* @__PURE__ */ jsx4(ProjectPathInfo, { path: item.cwd }) : null
1593
+ ] }),
1594
+ /* @__PURE__ */ jsxs3("span", { className: "flex shrink-0 items-center gap-2", children: [
1595
+ headerAccessory,
1596
+ /* @__PURE__ */ jsxs3(
1597
+ "span",
1598
+ {
1599
+ className: cn3(
1600
+ "workspace-agent-message-center__status inline-flex shrink-0 items-center gap-1.5 text-[11px] font-semibold leading-4",
1601
+ messageCenterStatusToneClass(statusTone)
1602
+ ),
1603
+ "data-status": displayStatus,
1604
+ title: statusLabel,
1605
+ children: [
1606
+ /* @__PURE__ */ jsx4(
1607
+ StatusDot,
1608
+ {
1609
+ tone: statusTone,
1610
+ pulse: isWaitingMessageCenterItem(item) || item.status === "working",
1611
+ size: "sm",
1612
+ title: statusLabel
1613
+ }
1614
+ ),
1615
+ /* @__PURE__ */ jsx4("span", { children: statusLabel })
1616
+ ]
1617
+ }
1618
+ )
1619
+ ] })
1620
+ ] }),
1621
+ summary ? /* @__PURE__ */ jsx4(
1622
+ MessageCenterSummary,
1623
+ {
1624
+ item,
1625
+ lazy: lazySummary,
1626
+ onLinkAction,
1627
+ summary,
1628
+ emptyLabel: t("agentHost.workspaceAgentMessageCenterNoSummary")
1629
+ }
1630
+ ) : null,
1631
+ summaryAccessory,
1632
+ prompt && interactive ? /* @__PURE__ */ jsx4("div", { className: "min-w-0", children: /* @__PURE__ */ jsx4(
1633
+ AgentInteractivePromptSurface,
1634
+ {
1635
+ embedded: true,
1636
+ variant: "compact",
1637
+ keyboardShortcuts: false,
1638
+ prompt,
1639
+ isSubmitting,
1640
+ onSubmit: onSubmitPrompt,
1641
+ labels: buildWorkspaceAgentInteractivePromptLabels(
1642
+ t,
1643
+ item.provider
1644
+ )
1645
+ }
1646
+ ) }) : null,
1647
+ footerAccessory,
1648
+ /* @__PURE__ */ jsx4(
1649
+ MessageCenterOpenChatButton,
1650
+ {
1651
+ actionsAccessory,
1652
+ provider: item.provider,
1653
+ item,
1654
+ label: t("agentHost.workspaceAgentMessageCenterOpenChat"),
1655
+ onOpenChat,
1656
+ alwaysVisible: interactive && prompt !== null
1657
+ }
1658
+ )
1659
+ ]
1660
+ }
1661
+ );
1662
+ }
1663
+ );
1664
+ var STACK_PRESENCE_FALLBACK_MS = 380;
1665
+ var MESSAGE_CENTER_STACK_INITIAL_RENDER_COUNT = 24;
1666
+ var MESSAGE_CENTER_STACK_RENDER_BATCH_SIZE = 24;
1667
+ var MESSAGE_CENTER_STACK_RENDER_BATCH_DELAY_MS = 40;
1668
+ var MESSAGE_CENTER_SUMMARY_LAZY_ROOT_MARGIN = "480px 0px";
1669
+ var MESSAGE_CENTER_SUMMARY_OVERFLOW_MEASURE_DELAY_MS = 80;
1670
+ function useStackRegionPresence(visible) {
1671
+ const [mounted, setMounted] = useState2(visible);
1672
+ const closing = mounted && !visible;
1673
+ useLayoutEffect(() => {
1674
+ if (visible) {
1675
+ setMounted(true);
1676
+ }
1677
+ }, [visible]);
1678
+ useEffect2(() => {
1679
+ if (!closing) {
1680
+ return void 0;
1681
+ }
1682
+ const timeoutId = window.setTimeout(() => {
1683
+ setMounted(false);
1684
+ }, STACK_PRESENCE_FALLBACK_MS);
1685
+ return () => {
1686
+ window.clearTimeout(timeoutId);
1687
+ };
1688
+ }, [closing]);
1689
+ const onAnimationEnd = useCallback2(
1690
+ (event) => {
1691
+ if (event.target === event.currentTarget && closing) {
1692
+ setMounted(false);
1693
+ }
1694
+ },
1695
+ [closing]
1696
+ );
1697
+ return { closing, mounted, onAnimationEnd };
1698
+ }
1699
+ var WorkspaceAgentMessageCenterStack = memo(
1700
+ function WorkspaceAgentMessageCenterStack2({
1701
+ className,
1702
+ expanded,
1703
+ groupId,
1704
+ highlightedItemId,
1705
+ items,
1706
+ renderCard,
1707
+ onCollapse,
1708
+ onExpand
1709
+ }) {
1710
+ "use memo";
1711
+ const { t } = useTranslation();
1712
+ const summaryRegion = useStackRegionPresence(!expanded);
1713
+ const cardsRegion = useStackRegionPresence(expanded);
1714
+ const visibleItems = useBatchedMessageCenterStackItems({
1715
+ expanded,
1716
+ highlightedItemId,
1717
+ items,
1718
+ mounted: cardsRegion.mounted
1719
+ });
1720
+ if (items.length < 2) {
1721
+ return null;
1722
+ }
1723
+ const collapseLabel = t(
1724
+ "agentHost.workspaceAgentMessageCenterCollapseStackAria"
1725
+ );
1726
+ return /* @__PURE__ */ jsxs3(
1727
+ "div",
1951
1728
  {
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"
1729
+ className: cn3("relative flex min-w-0 flex-col", className),
1730
+ "data-stack-count": items.length,
1731
+ "data-stack-motion": "smooth",
1732
+ "data-stack-state": expanded ? "expanded" : "collapsed",
1733
+ "data-stack-top-item-id": items[0]?.id,
1734
+ "data-testid": `workspace-agent-message-stack-${groupId}`,
1735
+ children: [
1736
+ summaryRegion.mounted ? /* @__PURE__ */ jsx4(
1737
+ "div",
1738
+ {
1739
+ className: cn3(
1740
+ "workspace-agent-message-center__stack-rest min-w-0",
1741
+ summaryRegion.closing ? "workspace-agent-message-center__stack-rest--closing" : "workspace-agent-message-center__stack-rest--opening"
1742
+ ),
1743
+ onAnimationEnd: summaryRegion.onAnimationEnd,
1744
+ children: /* @__PURE__ */ jsx4(
1745
+ "div",
1746
+ {
1747
+ className: "min-h-0 min-w-0 overflow-hidden",
1748
+ "aria-hidden": summaryRegion.closing ? true : void 0,
1749
+ inert: summaryRegion.closing ? true : void 0,
1750
+ children: /* @__PURE__ */ jsx4(
1751
+ MessageCenterStackSummary,
1752
+ {
1753
+ groupId,
1754
+ items,
1755
+ onExpand
1756
+ }
1757
+ )
1758
+ }
1759
+ )
1760
+ }
1761
+ ) : null,
1762
+ cardsRegion.mounted ? /* @__PURE__ */ jsx4(
1763
+ "div",
1764
+ {
1765
+ className: cn3(
1766
+ "workspace-agent-message-center__stack-rest min-w-0",
1767
+ cardsRegion.closing ? "workspace-agent-message-center__stack-rest--closing" : "workspace-agent-message-center__stack-rest--opening"
1768
+ ),
1769
+ onAnimationEnd: cardsRegion.onAnimationEnd,
1770
+ children: /* @__PURE__ */ jsxs3(
1771
+ "div",
1772
+ {
1773
+ className: "min-h-0 min-w-0 overflow-hidden",
1774
+ "aria-hidden": cardsRegion.closing ? true : void 0,
1775
+ inert: cardsRegion.closing ? true : void 0,
1776
+ children: [
1777
+ /* @__PURE__ */ jsxs3("div", { className: "flex min-w-0 items-center justify-between gap-2 px-0.5 pb-1.5", children: [
1778
+ /* @__PURE__ */ jsxs3("span", { className: "flex min-w-0 items-center gap-1.5 text-[13px] font-semibold leading-4 text-[var(--text-tertiary)]", children: [
1779
+ /* @__PURE__ */ jsx4(
1780
+ MessageCenterIdentityAvatarMark,
1781
+ {
1782
+ agentAvatarUrl: items[0]?.agentAvatarUrl,
1783
+ identity: items[0]?.identity ?? null,
1784
+ provider: items[0]?.provider ?? "",
1785
+ userId: items[0]?.userId ?? null
1786
+ }
1787
+ ),
1788
+ /* @__PURE__ */ jsx4("span", { className: "min-w-0 truncate", children: t(
1789
+ "agentHost.workspaceAgentMessageCenterStackSummaryCount",
1790
+ {
1791
+ count: items.length
1792
+ }
1793
+ ) })
1794
+ ] }),
1795
+ /* @__PURE__ */ jsx4(
1796
+ LazyMessageCenterTooltip,
1797
+ {
1798
+ content: collapseLabel,
1799
+ side: "top",
1800
+ align: "center",
1801
+ children: /* @__PURE__ */ jsx4(
1802
+ Button2,
1803
+ {
1804
+ type: "button",
1805
+ variant: "ghost",
1806
+ size: "icon-sm",
1807
+ "aria-label": collapseLabel,
1808
+ className: "size-6 text-[var(--text-tertiary)] hover:text-[var(--text-primary)]",
1809
+ onClick: () => onCollapse(groupId),
1810
+ children: /* @__PURE__ */ jsx4(ChevronUp, { className: "size-3.5", "aria-hidden": "true" })
1811
+ }
1812
+ )
1813
+ }
1814
+ )
1815
+ ] }),
1816
+ /* @__PURE__ */ jsx4("div", { className: "flex min-w-0 flex-col gap-2.5", children: visibleItems.map(
1817
+ (item, stackedIndex) => renderCard(item, { stackedIndex })
1818
+ ) })
1819
+ ]
1820
+ }
1821
+ )
1822
+ }
1823
+ ) : null
1824
+ ]
1959
1825
  }
1960
1826
  );
1827
+ },
1828
+ areMessageCenterStackPropsEqual
1829
+ );
1830
+ function areMessageCenterStackPropsEqual(previous, next) {
1831
+ 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) {
1832
+ return false;
1961
1833
  }
1962
- return /* @__PURE__ */ jsx2(
1963
- MessageCenterIdentityAvatarStack,
1964
- {
1965
- userAvatarUrl: identity?.userAvatarUrl,
1966
- userName,
1967
- agentAvatarUrl: identity?.agentAvatarUrl?.trim() || managedAgentRoundedIconUrl(provider)
1968
- }
1969
- );
1834
+ if (next.expanded) {
1835
+ return previous.highlightedItemId === next.highlightedItemId && previous.items === next.items;
1836
+ }
1837
+ return messageCenterCollapsedStackSignature(previous.items) === messageCenterCollapsedStackSignature(next.items);
1970
1838
  }
1971
- function MessageCenterIdentityAvatarStack({
1972
- agentAvatarUrl,
1973
- userAvatarUrl: rawUserAvatarUrl,
1974
- userName
1839
+ function messageCenterCollapsedStackSignature(items) {
1840
+ const firstItem = items[0];
1841
+ if (!firstItem) {
1842
+ return "0";
1843
+ }
1844
+ const hasWaiting = items.some(isWaitingMessageCenterItem) ? "1" : "0";
1845
+ return [
1846
+ items.length,
1847
+ firstItem.id,
1848
+ firstItem.provider,
1849
+ firstItem.userId ?? "",
1850
+ firstItem.identity?.userName ?? "",
1851
+ firstItem.identity?.agentName ?? "",
1852
+ hasWaiting,
1853
+ messageCenterStackPreviewText(firstItem)
1854
+ ].join(":");
1855
+ }
1856
+ function useBatchedMessageCenterStackItems({
1857
+ expanded,
1858
+ highlightedItemId,
1859
+ items,
1860
+ mounted
1975
1861
  }) {
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
- }
1862
+ const limit = items.length;
1863
+ const highlightedIndex = highlightedItemId === null || highlightedItemId === void 0 ? -1 : items.findIndex((item) => item.id === highlightedItemId);
1864
+ const initialCount = Math.min(
1865
+ limit,
1866
+ Math.max(MESSAGE_CENTER_STACK_INITIAL_RENDER_COUNT, highlightedIndex + 1)
2017
1867
  );
1868
+ const [renderCount, setRenderCount] = useState2(initialCount);
1869
+ useEffect2(() => {
1870
+ if (!mounted) {
1871
+ setRenderCount(initialCount);
1872
+ return;
1873
+ }
1874
+ setRenderCount(
1875
+ (current) => Math.min(Math.max(current, initialCount), limit)
1876
+ );
1877
+ }, [initialCount, limit, mounted]);
1878
+ useEffect2(() => {
1879
+ if (!expanded || !mounted || renderCount >= limit) {
1880
+ return void 0;
1881
+ }
1882
+ const timeoutId = window.setTimeout(() => {
1883
+ setRenderCount(
1884
+ (current) => Math.min(current + MESSAGE_CENTER_STACK_RENDER_BATCH_SIZE, limit)
1885
+ );
1886
+ }, MESSAGE_CENTER_STACK_RENDER_BATCH_DELAY_MS);
1887
+ return () => {
1888
+ window.clearTimeout(timeoutId);
1889
+ };
1890
+ }, [expanded, limit, mounted, renderCount]);
1891
+ return items.slice(0, Math.min(renderCount, limit));
2018
1892
  }
2019
- function ProjectPathInfo({ path }) {
1893
+ function MessageCenterStackSummary({
1894
+ groupId,
1895
+ items,
1896
+ onExpand
1897
+ }) {
2020
1898
  "use memo";
2021
- return /* @__PURE__ */ jsx2(
2022
- LazyMessageCenterTooltip,
1899
+ const { t } = useTranslation();
1900
+ const firstItem = items[0];
1901
+ const hasWaiting = items.some((item) => isWaitingMessageCenterItem(item));
1902
+ if (!firstItem) {
1903
+ return null;
1904
+ }
1905
+ return /* @__PURE__ */ jsx4(
1906
+ "button",
2023
1907
  {
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",
1908
+ type: "button",
1909
+ "aria-label": t("agentHost.workspaceAgentMessageCenterExpandStackAria", {
1910
+ count: items.length
1911
+ }),
1912
+ className: cn3(
1913
+ "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)]",
1914
+ items.length > 2 ? "pb-[18px]" : "pb-[10px]"
1915
+ ),
1916
+ "data-stack-summary-count": items.length,
1917
+ "data-stack-provider": firstItem.provider,
1918
+ "data-stack-user-id": firstItem.userId ?? "",
1919
+ "data-testid": `workspace-agent-message-stack-summary-${groupId}`,
1920
+ onClick: () => onExpand(groupId),
1921
+ children: /* @__PURE__ */ jsxs3(
1922
+ "span",
2030
1923
  {
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" })
1924
+ className: cn3(
1925
+ "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)]",
1926
+ 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)]",
1927
+ hasWaiting && "border-[var(--tutti-purple-border)] bg-[var(--tutti-purple-bg)]"
1928
+ ),
1929
+ children: [
1930
+ /* @__PURE__ */ jsxs3("span", { className: "flex min-w-0 items-center justify-between gap-2.5", children: [
1931
+ /* @__PURE__ */ jsxs3("span", { className: "flex min-w-0 items-center gap-2", children: [
1932
+ /* @__PURE__ */ jsx4(
1933
+ MessageCenterIdentityAvatarMark,
1934
+ {
1935
+ agentAvatarUrl: firstItem.agentAvatarUrl,
1936
+ identity: firstItem.identity,
1937
+ provider: firstItem.provider,
1938
+ userId: firstItem.userId
1939
+ }
1940
+ ),
1941
+ /* @__PURE__ */ jsx4("span", { className: "min-w-0 truncate text-[13px] font-bold leading-5 text-[var(--text-secondary)]", children: t("agentHost.workspaceAgentMessageCenterStackSummaryCount", {
1942
+ count: items.length
1943
+ }) })
1944
+ ] }),
1945
+ /* @__PURE__ */ jsx4(
1946
+ ChevronDown,
1947
+ {
1948
+ 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",
1949
+ "aria-hidden": "true"
1950
+ }
1951
+ )
1952
+ ] }),
1953
+ /* @__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) }) })
1954
+ ]
2035
1955
  }
2036
1956
  )
2037
1957
  }
2038
1958
  );
2039
1959
  }
2040
- function LazyMessageCenterTooltip({
2041
- align,
2042
- children,
2043
- className,
2044
- content,
2045
- side
1960
+ function messageCenterVisibleSummary(item) {
1961
+ const summary = item.digest.primary.summary.trim();
1962
+ if (item.pendingPrompt?.kind === "approval" && isGenericApprovalSummary(summary)) {
1963
+ return "";
1964
+ }
1965
+ return summary;
1966
+ }
1967
+ function isGenericApprovalSummary(summary) {
1968
+ const normalized = summary.trim().toLowerCase();
1969
+ return normalized === "approval";
1970
+ }
1971
+ function MessageCenterSummary({
1972
+ emptyLabel,
1973
+ item,
1974
+ lazy,
1975
+ onLinkAction,
1976
+ summary
2046
1977
  }) {
2047
1978
  "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();
1979
+ const summaryRef = useRef(null);
1980
+ const [isOverflowing, setIsOverflowing] = useState2(false);
1981
+ const shouldRenderRichSummary = useLazyMessageCenterSummaryReady(
1982
+ summaryRef,
1983
+ lazy
1984
+ );
1985
+ const shouldMeasureOverflow = useDeferredMessageCenterSummaryMeasureReady(
1986
+ summaryRef,
1987
+ shouldRenderRichSummary
1988
+ );
1989
+ const handleLinkAction = useCallback2(
1990
+ (action) => {
1991
+ const agentTargetId = item.agentTargetId?.trim() || null;
1992
+ onLinkAction?.(
1993
+ action.type === "open-agent-session" && !action.agentTargetId && agentTargetId ? { ...action, agentTargetId } : action
1994
+ );
2069
1995
  },
2070
- onPointerLeave: (event) => {
2071
- children.props.onPointerLeave?.(event);
2072
- hideTooltip();
1996
+ [item.agentTargetId, onLinkAction]
1997
+ );
1998
+ useEffect2(() => {
1999
+ if (!shouldMeasureOverflow) {
2000
+ setIsOverflowing(false);
2001
+ return void 0;
2073
2002
  }
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;
2003
+ const element = summaryRef.current;
2004
+ if (!element) {
2005
+ return void 0;
2006
+ }
2007
+ const updateOverflowState = () => {
2008
+ setIsOverflowing(element.scrollHeight > element.clientHeight + 1);
2009
+ };
2010
+ let resizeObserver = null;
2011
+ const timeoutId = window.setTimeout(() => {
2012
+ updateOverflowState();
2013
+ resizeObserver = new ResizeObserver(updateOverflowState);
2014
+ resizeObserver.observe(element);
2015
+ }, MESSAGE_CENTER_SUMMARY_OVERFLOW_MEASURE_DELAY_MS);
2016
+ return () => {
2017
+ window.clearTimeout(timeoutId);
2018
+ resizeObserver?.disconnect();
2019
+ };
2020
+ }, [shouldMeasureOverflow, summary]);
2021
+ return /* @__PURE__ */ jsx4(
2022
+ AgentVerticalScrollArea,
2023
+ {
2024
+ ref: summaryRef,
2025
+ className: cn3(
2026
+ "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]",
2027
+ isOverflowing && "workspace-agent-message-center__summary--overflowing"
2028
+ ),
2029
+ viewportClassName: "workspace-agent-message-center__copy-text max-h-[160px] p-2.5 pr-4",
2030
+ onPointerDown: stopMessageCenterTextPointerPropagation,
2031
+ scrollbarClassName: "top-2 bottom-2 right-1.5",
2032
+ syncKey: summary,
2033
+ children: summary && shouldRenderRichSummary ? /* @__PURE__ */ jsx4(
2034
+ AgentMessageMarkdown,
2035
+ {
2036
+ content: summary,
2037
+ 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)]",
2038
+ onLinkAction: handleLinkAction,
2039
+ workspaceLinkContext: {
2040
+ workspaceRoot: item.cwd || null,
2041
+ basePath: item.cwd,
2042
+ source: "agent-markdown"
2043
+ },
2044
+ enableImageZoom: true
2045
+ }
2046
+ ) : summary ? /* @__PURE__ */ jsx4("div", { className: "whitespace-pre-wrap [overflow-wrap:anywhere]", children: summary }) : emptyLabel
2047
+ }
2048
+ );
2110
2049
  }
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";
2050
+ function useLazyMessageCenterSummaryReady(ref, lazy) {
2051
+ const [ready, setReady] = useState2(!lazy);
2052
+ useEffect2(() => {
2053
+ setReady(!lazy);
2054
+ }, [lazy]);
2055
+ useEffect2(() => {
2056
+ if (!lazy) {
2057
+ return void 0;
2058
+ }
2059
+ if (ready) {
2060
+ return void 0;
2061
+ }
2062
+ const element = ref.current;
2063
+ if (!element || typeof IntersectionObserver === "undefined") {
2064
+ setReady(true);
2065
+ return void 0;
2066
+ }
2067
+ const observer = new IntersectionObserver(
2068
+ (entries) => {
2069
+ if (entries.some((entry) => entry.isIntersecting)) {
2070
+ setReady(true);
2071
+ observer.disconnect();
2072
+ }
2073
+ },
2074
+ { rootMargin: MESSAGE_CENTER_SUMMARY_LAZY_ROOT_MARGIN }
2075
+ );
2076
+ observer.observe(element);
2077
+ return () => observer.disconnect();
2078
+ }, [lazy, ready, ref]);
2079
+ return ready;
2128
2080
  }
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
- }
2081
+ function useDeferredMessageCenterSummaryMeasureReady(ref, enabled) {
2082
+ const [ready, setReady] = useState2(false);
2083
+ useEffect2(() => {
2084
+ if (!enabled) {
2085
+ setReady(false);
2086
+ return void 0;
2087
+ }
2088
+ if (ready) {
2089
+ return void 0;
2090
+ }
2091
+ const element = ref.current;
2092
+ if (!element || typeof IntersectionObserver === "undefined") {
2093
+ const timeoutId2 = window.setTimeout(
2094
+ () => setReady(true),
2095
+ MESSAGE_CENTER_SUMMARY_OVERFLOW_MEASURE_DELAY_MS
2096
+ );
2097
+ return () => {
2098
+ window.clearTimeout(timeoutId2);
2099
+ };
2100
+ }
2101
+ let timeoutId = null;
2102
+ const observer = new IntersectionObserver(
2103
+ (entries) => {
2104
+ if (!entries.some((entry) => entry.isIntersecting)) {
2105
+ return;
2106
+ }
2107
+ observer.disconnect();
2108
+ timeoutId = window.setTimeout(
2109
+ () => setReady(true),
2110
+ MESSAGE_CENTER_SUMMARY_OVERFLOW_MEASURE_DELAY_MS
2111
+ );
2112
+ },
2113
+ { rootMargin: MESSAGE_CENTER_SUMMARY_LAZY_ROOT_MARGIN }
2114
+ );
2115
+ observer.observe(element);
2116
+ return () => {
2117
+ observer.disconnect();
2118
+ if (timeoutId !== null) {
2119
+ window.clearTimeout(timeoutId);
2120
+ }
2121
+ };
2122
+ }, [enabled, ready, ref]);
2123
+ return ready;
2142
2124
  }
2143
2125
 
2144
2126
  // agent-message-center/WorkspaceAgentMessageCenterAttentionDeck.tsx
2145
- import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
2127
+ import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
2146
2128
  var DECK_MAX_PEEK = 2;
2147
2129
  var DECK_NEW_CARD_COOLDOWN_MS = 500;
2148
2130
  var DECK_LEAVE_ANIMATION_FALLBACK_MS = 420;
2149
2131
  function WorkspaceAgentMessageCenterAttentionDeck({
2150
2132
  items,
2151
2133
  highlightedItemId = null,
2152
- submittingPromptKey,
2134
+ isPromptSubmitting,
2153
2135
  registerNode,
2154
2136
  renderCard,
2155
2137
  onLinkAction,
@@ -2165,10 +2147,10 @@ function WorkspaceAgentMessageCenterAttentionDeck({
2165
2147
  const topRequestId = ordered[0]?.pendingPrompt?.requestId ?? null;
2166
2148
  const topPromotedByHighlight = ordered[0]?.id === highlightedItemId && highlightedItemId !== null;
2167
2149
  const previousTopRequestIdRef = useRef2(null);
2168
- const [cooldownRequestId, setCooldownRequestId] = useState2(
2150
+ const [cooldownRequestId, setCooldownRequestId] = useState3(
2169
2151
  null
2170
2152
  );
2171
- useEffect2(() => {
2153
+ useEffect3(() => {
2172
2154
  const previousTopRequestId = previousTopRequestIdRef.current;
2173
2155
  previousTopRequestIdRef.current = topRequestId;
2174
2156
  if (!topRequestId || topPromotedByHighlight || previousTopRequestId === null || previousTopRequestId === topRequestId) {
@@ -2188,8 +2170,8 @@ function WorkspaceAgentMessageCenterAttentionDeck({
2188
2170
  const previousTopItemRef = useRef2(
2189
2171
  null
2190
2172
  );
2191
- const [leavingItem, setLeavingItem] = useState2(null);
2192
- useEffect2(() => {
2173
+ const [leavingItem, setLeavingItem] = useState3(null);
2174
+ useEffect3(() => {
2193
2175
  const previousTopItem = previousTopItemRef.current;
2194
2176
  previousTopItemRef.current = ordered[0] ?? null;
2195
2177
  if (previousTopItem && previousTopItem.id !== (ordered[0]?.id ?? null) && !items.some((item) => item.id === previousTopItem.id)) {
@@ -2210,23 +2192,23 @@ function WorkspaceAgentMessageCenterAttentionDeck({
2210
2192
  return null;
2211
2193
  }
2212
2194
  const peekCount = Math.min(ordered.length - 1, DECK_MAX_PEEK);
2213
- const topIsSubmitting = submittingPromptKey === `${topItem.agentSessionId}:${topItem.pendingPrompt?.requestId}`;
2214
- return /* @__PURE__ */ jsxs2(
2195
+ const topIsSubmitting = isPromptSubmitting(topItem);
2196
+ return /* @__PURE__ */ jsxs4(
2215
2197
  "section",
2216
2198
  {
2217
2199
  className: "flex min-w-0 flex-col gap-2.5",
2218
2200
  "aria-label": t("agentHost.workspaceAgentMessageCenterGroupNeedsAttention"),
2219
2201
  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: [
2202
+ /* @__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
2203
  t("agentHost.workspaceAgentMessageCenterGroupNeedsAttention"),
2222
2204
  " \xB7",
2223
2205
  " ",
2224
2206
  ordered.length
2225
2207
  ] }) }),
2226
- /* @__PURE__ */ jsxs2(
2208
+ /* @__PURE__ */ jsxs4(
2227
2209
  "div",
2228
2210
  {
2229
- className: cn3(
2211
+ className: cn4(
2230
2212
  "relative min-w-0",
2231
2213
  peekCount > 1 ? "pb-[18px]" : peekCount > 0 && "pb-[10px]"
2232
2214
  ),
@@ -2235,7 +2217,7 @@ function WorkspaceAgentMessageCenterAttentionDeck({
2235
2217
  "data-deck-peek-count": peekCount,
2236
2218
  "data-deck-top-item-id": topItem.id,
2237
2219
  children: [
2238
- leavingItem ? /* @__PURE__ */ jsx3(
2220
+ leavingItem ? /* @__PURE__ */ jsx5(
2239
2221
  "div",
2240
2222
  {
2241
2223
  "aria-hidden": "true",
@@ -2256,7 +2238,7 @@ function WorkspaceAgentMessageCenterAttentionDeck({
2256
2238
  item: leavingItem,
2257
2239
  onSubmitPrompt: () => {
2258
2240
  }
2259
- }) : /* @__PURE__ */ jsx3(
2241
+ }) : /* @__PURE__ */ jsx5(
2260
2242
  WorkspaceAgentMessageCenterCard,
2261
2243
  {
2262
2244
  interactive: false,
@@ -2270,10 +2252,10 @@ function WorkspaceAgentMessageCenterAttentionDeck({
2270
2252
  },
2271
2253
  `leaving-${leavingItem.agentSessionId}`
2272
2254
  ) : null,
2273
- /* @__PURE__ */ jsx3(
2255
+ /* @__PURE__ */ jsx5(
2274
2256
  "div",
2275
2257
  {
2276
- className: cn3(
2258
+ className: cn4(
2277
2259
  "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
2260
  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
2261
  ),
@@ -2284,7 +2266,7 @@ function WorkspaceAgentMessageCenterAttentionDeck({
2284
2266
  isSubmitting: topIsSubmitting || isTopCoolingDown,
2285
2267
  item: topItem,
2286
2268
  onSubmitPrompt: (input) => onSubmitPrompt(topItem, input)
2287
- }) : /* @__PURE__ */ jsx3(
2269
+ }) : /* @__PURE__ */ jsx5(
2288
2270
  WorkspaceAgentMessageCenterCard,
2289
2271
  {
2290
2272
  cardRef: registerNode ? (node) => registerNode(topItem.id, node) : void 0,
@@ -2323,8 +2305,8 @@ function orderDeckItems(items, highlightedItemId) {
2323
2305
  // agent-message-center/WorkspaceAgentMessageCenterViewControls.tsx
2324
2306
  import { ListFilter } from "lucide-react";
2325
2307
  import {
2326
- Button as Button2,
2327
- cn as cn4,
2308
+ Button as Button3,
2309
+ cn as cn5,
2328
2310
  DropdownMenu,
2329
2311
  DropdownMenuCheckboxItem,
2330
2312
  DropdownMenuContent,
@@ -2422,11 +2404,15 @@ function buildMessageCenterStatusOptions(counts, t) {
2422
2404
  function buildMessageCenterProviderOptions(items) {
2423
2405
  const counts = /* @__PURE__ */ new Map();
2424
2406
  for (const item of items) {
2425
- counts.set(item.provider, (counts.get(item.provider) ?? 0) + 1);
2407
+ const current = counts.get(item.provider);
2408
+ counts.set(item.provider, {
2409
+ count: (current?.count ?? 0) + 1,
2410
+ label: current?.label || item.agentName?.trim() || workspaceAgentProviderLabel(item.provider)
2411
+ });
2426
2412
  }
2427
- return [...counts.entries()].map(([value, count]) => ({
2428
- count,
2429
- label: workspaceAgentProviderLabel(value),
2413
+ return [...counts.entries()].map(([value, option]) => ({
2414
+ count: option.count,
2415
+ label: option.label,
2430
2416
  value
2431
2417
  })).sort((left, right) => left.label.localeCompare(right.label));
2432
2418
  }
@@ -2552,7 +2538,7 @@ function messageCenterAgentUserGroupLabel(item) {
2552
2538
  if (item.identity) {
2553
2539
  return `${item.identity.userName} & ${item.identity.agentName}`;
2554
2540
  }
2555
- return workspaceAgentProviderLabel(item.provider);
2541
+ return item.agentName?.trim() || workspaceAgentProviderLabel(item.provider);
2556
2542
  }
2557
2543
  var RECENTLY_COMPLETED_WINDOW_MS = 10 * 60 * 1e3;
2558
2544
  function isRecentlyCompletedMessageCenterItem(item, nowUnixMs) {
@@ -2631,7 +2617,7 @@ function messageCenterTimeGroup(item) {
2631
2617
  }
2632
2618
 
2633
2619
  // agent-message-center/WorkspaceAgentMessageCenterViewControls.tsx
2634
- import { Fragment, jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
2620
+ import { Fragment, jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
2635
2621
  function MessageCenterViewMenu({
2636
2622
  filtersActive = false,
2637
2623
  groupBy,
@@ -2646,16 +2632,16 @@ function MessageCenterViewMenu({
2646
2632
  }) {
2647
2633
  "use memo";
2648
2634
  const { t } = useTranslation();
2649
- return /* @__PURE__ */ jsxs3(DropdownMenu, { modal: false, children: [
2650
- /* @__PURE__ */ jsx4(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs3(
2651
- Button2,
2635
+ return /* @__PURE__ */ jsxs5(DropdownMenu, { modal: false, children: [
2636
+ /* @__PURE__ */ jsx6(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs5(
2637
+ Button3,
2652
2638
  {
2653
2639
  type: "button",
2654
2640
  variant: "ghost",
2655
2641
  size: "icon",
2656
2642
  "aria-label": t("agentHost.workspaceAgentMessageCenterViewOptions"),
2657
2643
  title: t("agentHost.workspaceAgentMessageCenterViewOptions"),
2658
- className: cn4(
2644
+ className: cn5(
2659
2645
  "relative size-8 shrink-0 rounded-md border bg-[var(--background-fronted)] shadow-none",
2660
2646
  filtersActive ? "border-[var(--border-focus)] text-[var(--accent)]" : "border-[var(--line-2)] text-[var(--text-secondary)] hover:text-[var(--text-primary)]"
2661
2647
  ),
@@ -2666,8 +2652,8 @@ function MessageCenterViewMenu({
2666
2652
  event.stopPropagation();
2667
2653
  },
2668
2654
  children: [
2669
- /* @__PURE__ */ jsx4(ListFilter, { className: "size-4", strokeWidth: 2.1, "aria-hidden": "true" }),
2670
- filtersActive ? /* @__PURE__ */ jsx4(
2655
+ /* @__PURE__ */ jsx6(ListFilter, { className: "size-4", strokeWidth: 2.1, "aria-hidden": "true" }),
2656
+ filtersActive ? /* @__PURE__ */ jsx6(
2671
2657
  "span",
2672
2658
  {
2673
2659
  "aria-label": t(
@@ -2679,7 +2665,7 @@ function MessageCenterViewMenu({
2679
2665
  ]
2680
2666
  }
2681
2667
  ) }),
2682
- /* @__PURE__ */ jsxs3(
2668
+ /* @__PURE__ */ jsxs5(
2683
2669
  DropdownMenuContent,
2684
2670
  {
2685
2671
  align: "end",
@@ -2699,25 +2685,25 @@ function MessageCenterViewMenu({
2699
2685
  event.stopPropagation();
2700
2686
  },
2701
2687
  children: [
2702
- /* @__PURE__ */ jsx4(DropdownMenuLabel, { children: t("agentHost.workspaceAgentMessageCenterGroupBy") }),
2703
- /* @__PURE__ */ jsx4(
2688
+ /* @__PURE__ */ jsx6(DropdownMenuLabel, { children: t("agentHost.workspaceAgentMessageCenterGroupBy") }),
2689
+ /* @__PURE__ */ jsx6(
2704
2690
  DropdownMenuRadioGroup,
2705
2691
  {
2706
2692
  value: groupBy,
2707
2693
  onValueChange: (value) => onGroupByChange(value),
2708
- children: ["priority", "status", "agent", "time"].map((value) => /* @__PURE__ */ jsx4(DropdownMenuRadioItem, { value, children: messageCenterGroupLabel(value, t) }, value))
2694
+ children: ["priority", "status", "agent", "time"].map((value) => /* @__PURE__ */ jsx6(DropdownMenuRadioItem, { value, children: messageCenterGroupLabel(value, t) }, value))
2709
2695
  }
2710
2696
  ),
2711
- /* @__PURE__ */ jsx4(DropdownMenuSeparator, {}),
2712
- /* @__PURE__ */ jsx4(DropdownMenuLabel, { children: t("agentHost.workspaceAgentMessageCenterFilterStatus") }),
2713
- /* @__PURE__ */ jsx4(DropdownMenuGroup, { children: statusOptions.map((option) => /* @__PURE__ */ jsx4(
2697
+ /* @__PURE__ */ jsx6(DropdownMenuSeparator, {}),
2698
+ /* @__PURE__ */ jsx6(DropdownMenuLabel, { children: t("agentHost.workspaceAgentMessageCenterFilterStatus") }),
2699
+ /* @__PURE__ */ jsx6(DropdownMenuGroup, { children: statusOptions.map((option) => /* @__PURE__ */ jsx6(
2714
2700
  DropdownMenuCheckboxItem,
2715
2701
  {
2716
2702
  "aria-label": `${option.label} ${option.count}`,
2717
2703
  checked: statusFilters === null || statusFilters.has(option.value),
2718
2704
  onCheckedChange: () => onStatusToggle(option.value),
2719
2705
  onSelect: (event) => event.preventDefault(),
2720
- children: /* @__PURE__ */ jsx4(
2706
+ children: /* @__PURE__ */ jsx6(
2721
2707
  MessageCenterOptionWithCount,
2722
2708
  {
2723
2709
  count: option.count,
@@ -2727,17 +2713,17 @@ function MessageCenterViewMenu({
2727
2713
  },
2728
2714
  option.value
2729
2715
  )) }),
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(
2716
+ providerOptions.length > 0 ? /* @__PURE__ */ jsxs5(Fragment, { children: [
2717
+ /* @__PURE__ */ jsx6(DropdownMenuSeparator, {}),
2718
+ /* @__PURE__ */ jsx6(DropdownMenuLabel, { children: t("agentHost.workspaceAgentMessageCenterFilterAgent") }),
2719
+ /* @__PURE__ */ jsx6(DropdownMenuGroup, { children: providerOptions.map((option) => /* @__PURE__ */ jsx6(
2734
2720
  DropdownMenuCheckboxItem,
2735
2721
  {
2736
2722
  "aria-label": `${option.label} ${option.count}`,
2737
2723
  checked: providerFilters === null || providerFilters.has(option.value),
2738
2724
  onCheckedChange: () => onProviderToggle(option.value),
2739
2725
  onSelect: (event) => event.preventDefault(),
2740
- children: /* @__PURE__ */ jsx4(
2726
+ children: /* @__PURE__ */ jsx6(
2741
2727
  MessageCenterOptionWithCount,
2742
2728
  {
2743
2729
  count: option.count,
@@ -2748,8 +2734,8 @@ function MessageCenterViewMenu({
2748
2734
  option.value
2749
2735
  )) })
2750
2736
  ] }) : null,
2751
- /* @__PURE__ */ jsx4(DropdownMenuSeparator, {}),
2752
- /* @__PURE__ */ jsx4(DropdownMenuGroup, { children: /* @__PURE__ */ jsx4(DropdownMenuItem, { onClick: onClearFilters, children: t("agentHost.workspaceAgentMessageCenterClearFilters") }) })
2737
+ /* @__PURE__ */ jsx6(DropdownMenuSeparator, {}),
2738
+ /* @__PURE__ */ jsx6(DropdownMenuGroup, { children: /* @__PURE__ */ jsx6(DropdownMenuItem, { onClick: onClearFilters, children: t("agentHost.workspaceAgentMessageCenterClearFilters") }) })
2753
2739
  ]
2754
2740
  }
2755
2741
  )
@@ -2759,12 +2745,101 @@ function MessageCenterOptionWithCount({
2759
2745
  count,
2760
2746
  label
2761
2747
  }) {
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 })
2748
+ return /* @__PURE__ */ jsxs5("span", { className: "flex min-w-0 flex-1 items-center gap-3", children: [
2749
+ /* @__PURE__ */ jsx6("span", { className: "min-w-0 flex-1 truncate", children: label }),
2750
+ /* @__PURE__ */ jsx6("span", { className: "shrink-0 tabular-nums text-[11px] text-[var(--text-tertiary)]", children: count })
2765
2751
  ] });
2766
2752
  }
2767
2753
 
2754
+ // agent-message-center/WorkspaceAgentMessageCenterGroupHeading.tsx
2755
+ import { cn as cn6, StatusDot as StatusDot2 } from "@tutti-os/ui-system";
2756
+ import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
2757
+ function MessageCenterGroupHeading({
2758
+ group
2759
+ }) {
2760
+ "use memo";
2761
+ const statusSignal = messageCenterGroupStatusSignal(group.id);
2762
+ const firstItem = group.items[0];
2763
+ if (group.provider) {
2764
+ return /* @__PURE__ */ jsxs6(
2765
+ "h3",
2766
+ {
2767
+ "aria-label": `${group.label} \xB7 ${group.items.length}`,
2768
+ className: "flex min-w-0 items-center gap-1.5 text-[11px] font-normal leading-4 text-[var(--text-tertiary)]",
2769
+ title: `${group.label} \xB7 ${group.items.length}`,
2770
+ children: [
2771
+ group.identity ? /* @__PURE__ */ jsx7(
2772
+ MessageCenterIdentityLabel,
2773
+ {
2774
+ agentAvatarUrl: firstItem?.agentAvatarUrl,
2775
+ agentName: firstItem?.agentName,
2776
+ identity: group.identity,
2777
+ provider: group.provider
2778
+ }
2779
+ ) : /* @__PURE__ */ jsxs6("span", { className: "inline-flex min-w-0 items-center gap-1.5", children: [
2780
+ /* @__PURE__ */ jsx7(
2781
+ MessageCenterIdentityAvatarMark,
2782
+ {
2783
+ agentAvatarUrl: firstItem?.agentAvatarUrl,
2784
+ identity: null,
2785
+ provider: group.provider,
2786
+ userId: group.userId ?? null
2787
+ }
2788
+ ),
2789
+ /* @__PURE__ */ jsx7("span", { className: "min-w-0 truncate", children: group.label })
2790
+ ] }),
2791
+ /* @__PURE__ */ jsxs6("span", { className: "shrink-0", children: [
2792
+ "\xB7 ",
2793
+ group.items.length
2794
+ ] })
2795
+ ]
2796
+ }
2797
+ );
2798
+ }
2799
+ return /* @__PURE__ */ jsxs6(
2800
+ "h3",
2801
+ {
2802
+ className: cn6(
2803
+ "flex min-w-0 items-center gap-1.5 text-[11px] font-normal leading-4",
2804
+ statusSignal ? messageCenterStatusToneClass(statusSignal.tone) : "text-[var(--text-tertiary)]"
2805
+ ),
2806
+ title: `${group.label} \xB7 ${group.items.length}`,
2807
+ children: [
2808
+ statusSignal ? /* @__PURE__ */ jsx7(
2809
+ StatusDot2,
2810
+ {
2811
+ tone: statusSignal.tone,
2812
+ pulse: statusSignal.pulse,
2813
+ size: "sm",
2814
+ title: group.label
2815
+ }
2816
+ ) : null,
2817
+ /* @__PURE__ */ jsxs6("span", { className: "min-w-0 truncate", children: [
2818
+ group.label,
2819
+ " \xB7 ",
2820
+ group.items.length
2821
+ ] })
2822
+ ]
2823
+ }
2824
+ );
2825
+ }
2826
+ function messageCenterGroupStatusSignal(groupId) {
2827
+ switch (groupId) {
2828
+ case "needs-attention":
2829
+ case "waiting":
2830
+ return { pulse: true, tone: "amber" };
2831
+ case "working":
2832
+ return { pulse: true, tone: "blue" };
2833
+ case "failed":
2834
+ return { pulse: false, tone: "red" };
2835
+ case "recently-completed":
2836
+ case "completed":
2837
+ return { pulse: false, tone: "green" };
2838
+ default:
2839
+ return null;
2840
+ }
2841
+ }
2842
+
2768
2843
  // agent-message-center/messageCenterFilterPreferences.ts
2769
2844
  var messageCenterFiltersStorageKey = "tutti.agent-message-center.filters";
2770
2845
  var messageCenterGroupByValues = /* @__PURE__ */ new Set([
@@ -2850,7 +2925,7 @@ function resolveStoredProviderFilters(value) {
2850
2925
  }
2851
2926
 
2852
2927
  // agent-message-center/WorkspaceAgentMessageCenterPanel.tsx
2853
- import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
2928
+ import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
2854
2929
  var MESSAGE_CENTER_TOOLTIP_DELAY_MS = 300;
2855
2930
  var MESSAGE_CENTER_STACK_EAGER_SUMMARY_COUNT = 8;
2856
2931
  var WorkspaceAgentMessageCenterPanel = memo2(
@@ -2867,13 +2942,14 @@ var WorkspaceAgentMessageCenterPanel = memo2(
2867
2942
  onLinkAction,
2868
2943
  onNotificationActioned,
2869
2944
  onOpenChat,
2945
+ promptStatus = () => "idle",
2870
2946
  onSubmitPrompt
2871
2947
  }) {
2872
2948
  "use memo";
2873
2949
  if (!open) {
2874
2950
  return null;
2875
2951
  }
2876
- return /* @__PURE__ */ jsx5(AgentGuiI18nProvider, { runtime: i18n, locale, children: /* @__PURE__ */ jsx5(
2952
+ return /* @__PURE__ */ jsx8(AgentGuiI18nProvider, { runtime: i18n, locale, children: /* @__PURE__ */ jsx8(
2877
2953
  WorkspaceAgentMessageCenterPanelContent,
2878
2954
  {
2879
2955
  open,
@@ -2886,6 +2962,7 @@ var WorkspaceAgentMessageCenterPanel = memo2(
2886
2962
  onLinkAction,
2887
2963
  onNotificationActioned,
2888
2964
  onOpenChat,
2965
+ promptStatus,
2889
2966
  onSubmitPrompt
2890
2967
  }
2891
2968
  ) });
@@ -2902,33 +2979,31 @@ function WorkspaceAgentMessageCenterPanelContent({
2902
2979
  onLinkAction,
2903
2980
  onNotificationActioned,
2904
2981
  onOpenChat,
2982
+ promptStatus = () => "idle",
2905
2983
  onSubmitPrompt
2906
2984
  }) {
2907
2985
  "use memo";
2908
2986
  const { t } = useTranslation();
2909
- const [initialFilters] = useState3(readMessageCenterFilterPreferences);
2910
- const [groupBy, setGroupBy] = useState3(
2987
+ const [initialFilters] = useState4(readMessageCenterFilterPreferences);
2988
+ const [groupBy, setGroupBy] = useState4(
2911
2989
  initialFilters.groupBy
2912
2990
  );
2913
- const [statusFilters, setStatusFilters] = useState3(
2991
+ const [statusFilters, setStatusFilters] = useState4(
2914
2992
  initialFilters.statusFilters
2915
2993
  );
2916
- const [providerFilters, setProviderFilters] = useState3(
2994
+ const [providerFilters, setProviderFilters] = useState4(
2917
2995
  initialFilters.providerFilters
2918
2996
  );
2919
- useEffect3(() => {
2997
+ useEffect4(() => {
2920
2998
  writeMessageCenterFilterPreferences({
2921
2999
  groupBy,
2922
3000
  statusFilters,
2923
3001
  providerFilters
2924
3002
  });
2925
3003
  }, [groupBy, statusFilters, providerFilters]);
2926
- const [expandedStackIds, setExpandedStackIds] = useState3(
3004
+ const [expandedStackIds, setExpandedStackIds] = useState4(
2927
3005
  () => /* @__PURE__ */ new Set()
2928
3006
  );
2929
- const [submittingPromptKey, setSubmittingPromptKey] = useState3(
2930
- null
2931
- );
2932
3007
  const itemNodesRef = useRef3(/* @__PURE__ */ new Map());
2933
3008
  const lastScrolledHighlightedItemIdRef = useRef3(null);
2934
3009
  const lastFilterResetHighlightedItemIdRef = useRef3(null);
@@ -3023,35 +3098,27 @@ function WorkspaceAgentMessageCenterPanelContent({
3023
3098
  t,
3024
3099
  visibleItems.length
3025
3100
  ]);
3026
- const submitPrompt = useCallback2(
3101
+ const submitPrompt = useCallback3(
3027
3102
  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
3103
+ const notificationAction = resolveMessageCenterNotificationAction(
3104
+ item,
3105
+ input
3106
+ );
3107
+ if (notificationAction) {
3108
+ onNotificationActioned?.({
3109
+ action: notificationAction,
3110
+ provider: item.provider
3045
3111
  });
3046
- } finally {
3047
- setSubmittingPromptKey(
3048
- (current) => current === promptKey ? null : current
3049
- );
3050
3112
  }
3113
+ await onSubmitPrompt({
3114
+ ...input,
3115
+ agentSessionId: item.agentSessionId,
3116
+ promptKind: item.pendingPrompt?.kind
3117
+ });
3051
3118
  },
3052
3119
  [onNotificationActioned, onSubmitPrompt]
3053
3120
  );
3054
- const setItemNode = useCallback2(
3121
+ const setItemNode = useCallback3(
3055
3122
  (itemId, node) => {
3056
3123
  if (node) {
3057
3124
  itemNodesRef.current.set(itemId, node);
@@ -3061,7 +3128,7 @@ function WorkspaceAgentMessageCenterPanelContent({
3061
3128
  },
3062
3129
  []
3063
3130
  );
3064
- const toggleStatusFilter = useCallback2(
3131
+ const toggleStatusFilter = useCallback3(
3065
3132
  (status) => {
3066
3133
  setStatusFilters((current) => {
3067
3134
  const next = new Set(
@@ -3077,7 +3144,7 @@ function WorkspaceAgentMessageCenterPanelContent({
3077
3144
  },
3078
3145
  [statusOptions]
3079
3146
  );
3080
- const toggleProviderFilter = useCallback2(
3147
+ const toggleProviderFilter = useCallback3(
3081
3148
  (provider) => {
3082
3149
  setProviderFilters((current) => {
3083
3150
  const next = new Set(
@@ -3093,11 +3160,11 @@ function WorkspaceAgentMessageCenterPanelContent({
3093
3160
  },
3094
3161
  [providerOptions]
3095
3162
  );
3096
- const clearFilters = useCallback2(() => {
3163
+ const clearFilters = useCallback3(() => {
3097
3164
  setStatusFilters(null);
3098
3165
  setProviderFilters(null);
3099
3166
  }, []);
3100
- const expandStack = useCallback2((groupId) => {
3167
+ const expandStack = useCallback3((groupId) => {
3101
3168
  setExpandedStackIds((current) => {
3102
3169
  if (current.has(groupId)) {
3103
3170
  return current;
@@ -3107,7 +3174,7 @@ function WorkspaceAgentMessageCenterPanelContent({
3107
3174
  return next;
3108
3175
  });
3109
3176
  }, []);
3110
- const collapseStack = useCallback2((groupId) => {
3177
+ const collapseStack = useCallback3((groupId) => {
3111
3178
  setExpandedStackIds((current) => {
3112
3179
  if (!current.has(groupId)) {
3113
3180
  return current;
@@ -3179,7 +3246,7 @@ function WorkspaceAgentMessageCenterPanelContent({
3179
3246
  statusFilters,
3180
3247
  visibleItems
3181
3248
  ]);
3182
- useEffect3(() => {
3249
+ useEffect4(() => {
3183
3250
  if (!open || !highlightedItemId) {
3184
3251
  return void 0;
3185
3252
  }
@@ -3190,16 +3257,16 @@ function WorkspaceAgentMessageCenterPanelContent({
3190
3257
  window.clearTimeout(timeoutId);
3191
3258
  };
3192
3259
  }, [highlightedItemId, onHighlightedItemSettled, open]);
3193
- const renderMessageCenterCard = useCallback2(
3260
+ const renderMessageCenterCard = useCallback3(
3194
3261
  (item, options = {}) => {
3195
3262
  const highlighted = item.id === highlightedItemId;
3196
3263
  const stackedIndex = options.stackedIndex;
3197
- const card = /* @__PURE__ */ jsx5(
3264
+ const card = /* @__PURE__ */ jsx8(
3198
3265
  MessageCenterRenderedCard,
3199
3266
  {
3200
3267
  highlighted,
3201
3268
  item,
3202
- isSubmitting: submittingPromptKey === `${item.agentSessionId}:${item.pendingPrompt?.requestId}`,
3269
+ isSubmitting: promptStatus(item) === "responding" || promptStatus(item) === "unknown",
3203
3270
  lazySummary: stackedIndex !== void 0 && stackedIndex >= MESSAGE_CENTER_STACK_EAGER_SUMMARY_COUNT,
3204
3271
  registerNode: setItemNode,
3205
3272
  onLinkAction,
@@ -3211,7 +3278,7 @@ function WorkspaceAgentMessageCenterPanelContent({
3211
3278
  if (stackedIndex === void 0) {
3212
3279
  return card;
3213
3280
  }
3214
- return /* @__PURE__ */ jsx5(
3281
+ return /* @__PURE__ */ jsx8(
3215
3282
  "div",
3216
3283
  {
3217
3284
  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 +3294,18 @@ function WorkspaceAgentMessageCenterPanelContent({
3227
3294
  highlightedItemId,
3228
3295
  onLinkAction,
3229
3296
  onOpenChat,
3297
+ promptStatus,
3230
3298
  setItemNode,
3231
- submitPrompt,
3232
- submittingPromptKey
3299
+ submitPrompt
3233
3300
  ]
3234
3301
  );
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(
3302
+ const panelContents = /* @__PURE__ */ jsxs7(TooltipProvider, { delayDuration: MESSAGE_CENTER_TOOLTIP_DELAY_MS, children: [
3303
+ /* @__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: [
3304
+ presentation === "drawer" ? /* @__PURE__ */ jsxs7("div", { className: "min-w-0", children: [
3305
+ /* @__PURE__ */ jsx8(DrawerTitle, { className: "truncate text-[13px] font-semibold leading-5 text-[var(--text-primary)]", children: t("agentHost.workspaceAgentMessageCenterTitle") }),
3306
+ /* @__PURE__ */ jsx8(DrawerDescription, { className: "truncate text-[11px] leading-4 text-[var(--text-tertiary)]", children: headerSummary })
3307
+ ] }) : /* @__PURE__ */ jsx8("p", { className: "min-w-0 truncate text-[11px] leading-4 text-[var(--text-tertiary)]", children: headerSummary }),
3308
+ /* @__PURE__ */ jsx8(
3242
3309
  MessageCenterViewMenu,
3243
3310
  {
3244
3311
  filtersActive: hasActiveFilters,
@@ -3254,33 +3321,33 @@ function WorkspaceAgentMessageCenterPanelContent({
3254
3321
  }
3255
3322
  )
3256
3323
  ] }) }),
3257
- /* @__PURE__ */ jsx5(
3324
+ /* @__PURE__ */ jsx8(
3258
3325
  AgentVerticalScrollArea,
3259
3326
  {
3260
3327
  className: "min-h-0 flex-1",
3261
3328
  viewportClassName: "flex h-full w-full flex-col px-3.5 pt-4 pb-4",
3262
3329
  scrollbarClassName: "top-4 bottom-4",
3263
3330
  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(
3331
+ children: deckItems.length > 0 || listItems.length > 0 ? /* @__PURE__ */ jsxs7("div", { className: "flex w-full min-w-0 flex-col gap-4", children: [
3332
+ deckItems.length > 0 ? /* @__PURE__ */ jsx8(
3266
3333
  WorkspaceAgentMessageCenterAttentionDeck,
3267
3334
  {
3268
3335
  items: deckItems,
3269
3336
  highlightedItemId,
3270
- submittingPromptKey,
3337
+ isPromptSubmitting: (item) => promptStatus(item) === "responding" || promptStatus(item) === "unknown",
3271
3338
  registerNode: setItemNode,
3272
3339
  onLinkAction,
3273
3340
  onOpenChat,
3274
3341
  onSubmitPrompt: (item, input) => void submitPrompt(item, input)
3275
3342
  }
3276
3343
  ) : null,
3277
- itemGroupStacks.map((group) => /* @__PURE__ */ jsxs4(
3344
+ itemGroupStacks.map((group) => /* @__PURE__ */ jsxs7(
3278
3345
  "section",
3279
3346
  {
3280
3347
  className: "flex min-w-0 flex-col gap-2.5",
3281
3348
  "aria-label": `${group.label} ${group.items.length}`,
3282
3349
  children: [
3283
- /* @__PURE__ */ jsx5("div", { className: "flex min-w-0 items-center justify-between gap-3 px-0.5", children: /* @__PURE__ */ jsx5(MessageCenterGroupHeading, { group }) }),
3350
+ /* @__PURE__ */ jsx8("div", { className: "flex min-w-0 items-center justify-between gap-3 px-0.5", children: /* @__PURE__ */ jsx8(MessageCenterGroupHeading, { group }) }),
3284
3351
  (() => {
3285
3352
  return group.stacks.map((stack) => {
3286
3353
  const firstItem = stack.items[0];
@@ -3294,7 +3361,7 @@ function WorkspaceAgentMessageCenterPanelContent({
3294
3361
  group.id,
3295
3362
  stack.id
3296
3363
  );
3297
- return /* @__PURE__ */ jsx5(
3364
+ return /* @__PURE__ */ jsx8(
3298
3365
  MessageCenterStack,
3299
3366
  {
3300
3367
  expanded: expandedStackIds.has(stackId),
@@ -3313,10 +3380,10 @@ function WorkspaceAgentMessageCenterPanelContent({
3313
3380
  },
3314
3381
  group.id
3315
3382
  ))
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,
3383
+ ] }) : 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: [
3384
+ /* @__PURE__ */ jsx8("span", { children: t("agentHost.workspaceAgentMessageCenterFilteredEmpty") }),
3385
+ /* @__PURE__ */ jsx8(
3386
+ Button4,
3320
3387
  {
3321
3388
  type: "button",
3322
3389
  variant: "ghost",
@@ -3326,12 +3393,12 @@ function WorkspaceAgentMessageCenterPanelContent({
3326
3393
  children: t("agentHost.workspaceAgentMessageCenterClearFilters")
3327
3394
  }
3328
3395
  )
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") })
3396
+ ] }) : /* @__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
3397
  }
3331
3398
  )
3332
3399
  ] });
3333
3400
  if (presentation === "embedded") {
3334
- return /* @__PURE__ */ jsx5(
3401
+ return /* @__PURE__ */ jsx8(
3335
3402
  "section",
3336
3403
  {
3337
3404
  "aria-label": t("agentHost.workspaceAgentMessageCenterTitle"),
@@ -3342,7 +3409,7 @@ function WorkspaceAgentMessageCenterPanelContent({
3342
3409
  }
3343
3410
  );
3344
3411
  }
3345
- return /* @__PURE__ */ jsx5(
3412
+ return /* @__PURE__ */ jsx8(
3346
3413
  Drawer,
3347
3414
  {
3348
3415
  open,
@@ -3353,10 +3420,10 @@ function WorkspaceAgentMessageCenterPanelContent({
3353
3420
  onClose();
3354
3421
  }
3355
3422
  },
3356
- children: /* @__PURE__ */ jsx5(
3423
+ children: /* @__PURE__ */ jsx8(
3357
3424
  DrawerContent,
3358
3425
  {
3359
- className: cn5(
3426
+ className: cn7(
3360
3427
  "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
3428
  "[-webkit-app-region:no-drag]"
3362
3429
  ),
@@ -3383,19 +3450,19 @@ var MessageCenterRenderedCard = memo2(function MessageCenterRenderedCard2({
3383
3450
  onSubmitPrompt,
3384
3451
  registerNode
3385
3452
  }) {
3386
- const cardRef = useCallback2(
3453
+ const cardRef = useCallback3(
3387
3454
  (node) => {
3388
3455
  registerNode(item.id, node);
3389
3456
  },
3390
3457
  [item.id, registerNode]
3391
3458
  );
3392
- const handleSubmitPrompt = useCallback2(
3459
+ const handleSubmitPrompt = useCallback3(
3393
3460
  (input) => {
3394
3461
  onSubmitPrompt(item, input);
3395
3462
  },
3396
3463
  [item, onSubmitPrompt]
3397
3464
  );
3398
- return /* @__PURE__ */ jsx5(
3465
+ return /* @__PURE__ */ jsx8(
3399
3466
  MessageCenterCard,
3400
3467
  {
3401
3468
  cardRef,
@@ -3409,86 +3476,204 @@ var MessageCenterRenderedCard = memo2(function MessageCenterRenderedCard2({
3409
3476
  }
3410
3477
  );
3411
3478
  });
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
- ]
3479
+
3480
+ // agent-message-center/workspaceAgentMessageCenterEngineModel.ts
3481
+ import {
3482
+ selectEngineInteractionResponse,
3483
+ selectPendingSubmitsForSession,
3484
+ selectPlanDecisionForTurn
3485
+ } from "@tutti-os/agent-activity-core";
3486
+
3487
+ // agent-message-center/workspaceAgentConsumerSelectors.ts
3488
+ import {
3489
+ selectWorkspaceAgentConsumerCounts,
3490
+ selectWorkspaceAgentConsumerSession,
3491
+ selectWorkspaceAgentConsumerSessions
3492
+ } from "@tutti-os/agent-activity-core";
3493
+
3494
+ // agent-message-center/workspaceAgentMessageCenterEngineModel.ts
3495
+ function buildWorkspaceAgentMessageCenterModelFromEngine(presentation, snapshot, options = {}) {
3496
+ const items = presentation.consumers.filter((consumer) => consumer.session.visible !== false).map((consumer) => {
3497
+ const interaction = latestPendingInteraction(consumer);
3498
+ const needsAttention = interaction ? needsAttentionFromInteraction(consumer, interaction) : null;
3499
+ return buildWorkspaceAgentMessageCenterItem({
3500
+ session: consumer.session,
3501
+ latestTurn: consumer.latestTurn,
3502
+ messages: sessionMessages(snapshot.sessionMessagesById, consumer),
3503
+ status: consumer.displayStatus,
3504
+ needsAttention,
3505
+ pendingPrompt: interaction ? promptFromInteraction(interaction) : null,
3506
+ latestTurnOutcome: turnOutcome(consumer),
3507
+ options
3508
+ });
3509
+ });
3510
+ return buildWorkspaceAgentMessageCenterModelFromItems(
3511
+ items,
3512
+ options.itemCutoffUnixMs
3513
+ );
3514
+ }
3515
+ function selectWorkspaceAgentMessageCenterPresentation(state) {
3516
+ const consumers = selectWorkspaceAgentConsumerSessions(state);
3517
+ const promptStatusByKey = {};
3518
+ for (const consumer of consumers) {
3519
+ const sessionId = consumer.session.agentSessionId;
3520
+ for (const interaction of consumer.pendingInteractions) {
3521
+ const response = selectEngineInteractionResponse(
3522
+ state,
3523
+ sessionId,
3524
+ interaction.turnId,
3525
+ interaction.requestId
3526
+ );
3527
+ if (response) {
3528
+ promptStatusByKey[promptStatusKey(sessionId, interaction.requestId)] = response.status;
3447
3529
  }
3530
+ }
3531
+ const turnId = consumer.latestTurn?.turnId ?? "";
3532
+ if (!turnId) continue;
3533
+ const decision = selectPlanDecisionForTurn(state, sessionId, turnId);
3534
+ if (decision) {
3535
+ promptStatusByKey[promptStatusKey(sessionId, turnId)] = decision.status === "requested" ? "responding" : decision.status;
3536
+ continue;
3537
+ }
3538
+ const feedbackPrefix = [
3539
+ "plan-implementation",
3540
+ consumer.session.workspaceId,
3541
+ sessionId,
3542
+ turnId,
3543
+ "feedback"
3544
+ ].join(":");
3545
+ const submit = selectPendingSubmitsForSession(state, sessionId).find(
3546
+ (record) => record.clientSubmitId.startsWith(feedbackPrefix)
3448
3547
  );
3548
+ if (submit) {
3549
+ promptStatusByKey[promptStatusKey(sessionId, turnId)] = submit.status === "failed" ? "failed" : submit.status === "uncertain" ? "unknown" : "responding";
3550
+ }
3449
3551
  }
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
- ]
3552
+ return {
3553
+ consumers,
3554
+ promptStatusByKey
3555
+ };
3556
+ }
3557
+ function workspaceAgentMessageCenterPresentationEqual(left, right) {
3558
+ return promptStatusMapsEqual(left.promptStatusByKey, right.promptStatusByKey) && left.consumers.length === right.consumers.length && left.consumers.every((item, index) => {
3559
+ const candidate = right.consumers[index];
3560
+ 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(
3561
+ (interaction, interactionIndex) => interaction === candidate.pendingInteractions[interactionIndex]
3562
+ );
3563
+ });
3564
+ }
3565
+ function workspaceAgentMessageCenterPromptStatus(presentation, item) {
3566
+ const prompt = item.pendingPrompt;
3567
+ if (!prompt) return "idle";
3568
+ return presentation.promptStatusByKey[promptStatusKey(item.agentSessionId, prompt.requestId)] ?? "idle";
3569
+ }
3570
+ function promptStatusKey(agentSessionId, requestId) {
3571
+ return `${agentSessionId}\0${requestId}`;
3572
+ }
3573
+ function promptStatusMapsEqual(left, right) {
3574
+ const keys = Object.keys(left);
3575
+ return keys.length === Object.keys(right).length && keys.every((key) => left[key] === right[key]);
3576
+ }
3577
+ function sessionMessages(sessionMessagesById, consumer) {
3578
+ for (const id of [
3579
+ consumer.session.agentSessionId,
3580
+ consumer.session.providerSessionId
3581
+ ]) {
3582
+ const normalized = id?.trim() ?? "";
3583
+ if (normalized && sessionMessagesById[normalized]) {
3584
+ return sessionMessagesById[normalized];
3474
3585
  }
3475
- );
3586
+ }
3587
+ return [];
3476
3588
  }
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;
3589
+ function latestPendingInteraction(consumer) {
3590
+ return consumer.pendingInteractions.at(-1) ?? null;
3591
+ }
3592
+ function needsAttentionFromInteraction(consumer, interaction) {
3593
+ const summary = interactionSummary(interaction);
3594
+ return {
3595
+ id: `interaction:${interaction.requestId}`,
3596
+ workspaceId: consumer.session.workspaceId,
3597
+ agentSessionId: consumer.session.agentSessionId,
3598
+ provider: consumer.session.provider,
3599
+ title: summary,
3600
+ cwd: consumer.session.cwd,
3601
+ kind: interaction.kind === "approval" ? "permission" : interaction.kind === "question" ? "question" : "constraint",
3602
+ summary,
3603
+ occurredAtUnixMs: interaction.createdAtUnixMs
3604
+ };
3605
+ }
3606
+ function promptFromInteraction(interaction) {
3607
+ const input = interaction.input ?? {};
3608
+ if (interaction.kind === "question") {
3609
+ const questions = normalizeAskUserQuestions(input.questions);
3610
+ return {
3611
+ kind: "ask-user",
3612
+ requestId: interaction.requestId,
3613
+ title: interactionSummary(interaction),
3614
+ questions: questions.length > 0 ? questions : [
3615
+ {
3616
+ id: "response",
3617
+ header: "",
3618
+ question: interactionSummary(interaction),
3619
+ options: [],
3620
+ multiSelect: false,
3621
+ answer: null
3622
+ }
3623
+ ]
3624
+ };
3625
+ }
3626
+ if (interaction.kind !== "approval") {
3627
+ return null;
3491
3628
  }
3629
+ const options = arrayValue2(input.options).flatMap((value) => {
3630
+ const option = recordValue3(value);
3631
+ const id = textValue(option.optionId) ?? textValue(option.id);
3632
+ return id ? [
3633
+ {
3634
+ id,
3635
+ label: textValue(option.label) ?? textValue(option.name) ?? id,
3636
+ kind: textValue(option.kind) ?? id
3637
+ }
3638
+ ] : [];
3639
+ });
3640
+ return {
3641
+ kind: "approval",
3642
+ id: `approval:${interaction.requestId}`,
3643
+ turnId: interaction.turnId,
3644
+ requestId: interaction.requestId,
3645
+ callId: textValue(input.callId) ?? interaction.requestId,
3646
+ title: interactionSummary(interaction),
3647
+ toolName: interaction.toolName ?? null,
3648
+ status: interaction.status,
3649
+ input,
3650
+ options,
3651
+ output: interaction.output ?? null,
3652
+ occurredAtUnixMs: interaction.createdAtUnixMs
3653
+ };
3654
+ }
3655
+ function turnOutcome(consumer) {
3656
+ const turn = consumer.latestTurn;
3657
+ if (!turn || turn.phase !== "settled") return null;
3658
+ const status = turn.outcome === "completed" ? "completed" : turn.outcome === "failed" ? "failed" : null;
3659
+ return status ? {
3660
+ notificationKey: `${consumer.session.agentSessionId}:turn:${turn.turnId}:${status}`,
3661
+ status,
3662
+ turnId: turn.turnId
3663
+ } : null;
3664
+ }
3665
+ function interactionSummary(interaction) {
3666
+ const input = interaction.input ?? {};
3667
+ return textValue(input.question) ?? textValue(input.title) ?? textValue(input.summary) ?? interaction.toolName?.trim() ?? interaction.kind;
3668
+ }
3669
+ function textValue(value) {
3670
+ return typeof value === "string" && value.trim() ? value.trim() : null;
3671
+ }
3672
+ function recordValue3(value) {
3673
+ return value && typeof value === "object" && !Array.isArray(value) ? value : {};
3674
+ }
3675
+ function arrayValue2(value) {
3676
+ return Array.isArray(value) ? value : [];
3492
3677
  }
3493
3678
 
3494
3679
  // agent-message-center/workspaceAgentMessageCenterModelStability.ts
@@ -3520,7 +3705,7 @@ function stabilizeWorkspaceAgentMessageCenterModel(previous, next) {
3520
3705
  };
3521
3706
  }
3522
3707
  function messageCenterItemsEqual(left, right) {
3523
- return left.id === right.id && left.agentSessionId === right.agentSessionId && left.provider === right.provider && left.userId === right.userId && left.title === right.title && left.imported === right.imported && left.cwd === right.cwd && left.status === right.status && left.lastAgentMessageSummary === right.lastAgentMessageSummary && left.lastAgentMessageAtUnixMs === right.lastAgentMessageAtUnixMs && left.needsAttentionKind === right.needsAttentionKind && left.needsAttentionSummary === right.needsAttentionSummary && left.sortTimeUnixMs === right.sortTimeUnixMs && messageCenterIdentityEqual(left.identity, right.identity) && messageCenterDigestEqual(left.digest, right.digest) && messageCenterPromptEqual(left.pendingPrompt, right.pendingPrompt) && messageCenterTurnOutcomeEqual(
3708
+ return left.id === right.id && left.agentSessionId === right.agentSessionId && left.agentTargetId === right.agentTargetId && left.agentName === right.agentName && left.agentAvatarUrl === right.agentAvatarUrl && left.provider === right.provider && left.userId === right.userId && left.title === right.title && left.imported === right.imported && left.cwd === right.cwd && left.status === right.status && left.lastAgentMessageSummary === right.lastAgentMessageSummary && left.lastAgentMessageAtUnixMs === right.lastAgentMessageAtUnixMs && left.needsAttentionKind === right.needsAttentionKind && left.needsAttentionSummary === right.needsAttentionSummary && left.sortTimeUnixMs === right.sortTimeUnixMs && messageCenterIdentityEqual(left.identity, right.identity) && messageCenterDigestEqual(left.digest, right.digest) && messageCenterPromptEqual(left.pendingPrompt, right.pendingPrompt) && messageCenterTurnOutcomeEqual(
3524
3709
  left.latestTurnOutcome ?? null,
3525
3710
  right.latestTurnOutcome ?? null
3526
3711
  );
@@ -3648,7 +3833,8 @@ export {
3648
3833
  buildMessageCenterProviderOptions,
3649
3834
  buildMessageCenterStatusOptions,
3650
3835
  buildWorkspaceAgentInteractivePromptLabels,
3651
- buildWorkspaceAgentMessageCenterModel,
3836
+ buildWorkspaceAgentMessageCenterModelFromEngine,
3837
+ dispatchAgentPlanPromptAction,
3652
3838
  getPromptToolDetails,
3653
3839
  groupMessageCenterItems,
3654
3840
  isInteractiveMessageCenterItem,
@@ -3671,10 +3857,17 @@ export {
3671
3857
  readMessageCenterFilterPreferences,
3672
3858
  resolveMessageCenterNotificationAction,
3673
3859
  selectMessageCenterAttentionDeckItems,
3860
+ selectWorkspaceAgentConsumerCounts,
3861
+ selectWorkspaceAgentConsumerSession,
3862
+ selectWorkspaceAgentConsumerSessions,
3863
+ selectWorkspaceAgentMessageCenterPresentation,
3674
3864
  stabilizeWorkspaceAgentMessageCenterModel,
3675
3865
  statusFilterSummary,
3866
+ useEngineSelector,
3676
3867
  userAvatarPlaceholderUrl,
3677
3868
  workspaceAgentActivityStatusLabel,
3869
+ workspaceAgentMessageCenterPresentationEqual,
3870
+ workspaceAgentMessageCenterPromptStatus,
3678
3871
  writeMessageCenterFilterPreferences
3679
3872
  };
3680
3873
  //# sourceMappingURL=index.js.map