@tutti-os/agent-gui 0.0.21 → 0.0.23

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.
@@ -28,6 +28,7 @@ interface AgentConversationFlowProps {
28
28
  onAuthLogin?: (provider?: string | null) => void;
29
29
  availableSkills?: readonly AgentGUIProviderSkillOption[];
30
30
  workspaceAppIcons?: readonly AgentMessageMarkdownWorkspaceAppIcon[];
31
+ previewMode?: boolean;
31
32
  showRawTimelineJson?: boolean;
32
33
  labels: {
33
34
  toolCallsLabel: (count: number) => string;
@@ -45,6 +46,7 @@ interface AgentTranscriptViewProps {
45
46
  onAuthLogin?: (provider?: string | null) => void;
46
47
  availableSkills?: readonly AgentGUIProviderSkillOption[];
47
48
  workspaceAppIcons?: readonly AgentMessageMarkdownWorkspaceAppIcon[];
49
+ previewMode?: boolean;
48
50
  showRawTimelineJson?: boolean;
49
51
  labels: {
50
52
  toolCallsLabel: (count: number) => string;
@@ -6,8 +6,8 @@ import {
6
6
  projectAgentConversationVM,
7
7
  reconcileProjectedAgentConversationVM,
8
8
  useProjectedAgentConversation
9
- } from "../chunk-4NGM7NFL.js";
10
- import "../chunk-BMGCH4JC.js";
9
+ } from "../chunk-MQAGIHYM.js";
10
+ import "../chunk-7Q3JKSQ5.js";
11
11
  import "../chunk-XAQQN6MP.js";
12
12
  import "../chunk-XJ34OIEQ.js";
13
13
  import "../chunk-CCI6EK5W.js";
@@ -165,6 +165,7 @@ interface AgentInteractivePromptSurfaceProps {
165
165
  variant?: AgentInteractivePromptVariant;
166
166
  edgeGlow?: boolean;
167
167
  keyboardShortcuts?: boolean;
168
+ previewMode?: boolean;
168
169
  isSubmitting: boolean;
169
170
  onSubmit: (input: {
170
171
  requestId: string;
@@ -195,7 +196,7 @@ interface AgentInteractivePromptSurfaceProps {
195
196
  planImplementationSkip: string;
196
197
  };
197
198
  }
198
- declare function AgentInteractivePromptSurface({ prompt, variant, edgeGlow, embedded, keyboardShortcuts, isSubmitting, onSubmit, labels }: AgentInteractivePromptSurfaceProps & {
199
+ declare function AgentInteractivePromptSurface({ prompt, variant, edgeGlow, embedded, keyboardShortcuts, previewMode, isSubmitting, onSubmit, labels }: AgentInteractivePromptSurfaceProps & {
199
200
  embedded?: boolean;
200
201
  }): JSX.Element | null;
201
202
 
@@ -3,7 +3,7 @@ import {
3
3
  approvalOptionDisplayLabel,
4
4
  getPromptToolDetails,
5
5
  isPromptRequestIdTitle
6
- } from "../chunk-2BGUS7DE.js";
6
+ } from "../chunk-ZC4E2QJU.js";
7
7
  import {
8
8
  PLAN_IMPLEMENTATION_ACTION_IMPLEMENT,
9
9
  PLAN_IMPLEMENTATION_PROMPT,
@@ -16,7 +16,7 @@ import {
16
16
  cn,
17
17
  extractAgentMcpToolTarget,
18
18
  normalizeAskUserQuestions
19
- } from "../chunk-BMGCH4JC.js";
19
+ } from "../chunk-7Q3JKSQ5.js";
20
20
  import {
21
21
  managedAgentRoundedIconUrl,
22
22
  userAvatarPlaceholderUrl,
@@ -54,6 +54,7 @@ import {
54
54
  cn as cn5,
55
55
  Drawer,
56
56
  DrawerContent,
57
+ StatusDot as StatusDot2,
57
58
  TooltipProvider
58
59
  } from "@tutti-os/ui-system";
59
60
 
@@ -103,16 +104,16 @@ import {
103
104
  } from "@tutti-os/agent-activity-core";
104
105
 
105
106
  // agent-message-center/workspaceAgentMessageCenterDigest.ts
106
- function buildWorkspaceAgentMessageCenterDigest({
107
- fallbackTitle,
108
- messages,
109
- needsAttention,
110
- pendingPrompt,
111
- status
112
- }) {
113
- const latestAgentMessage2 = latestAgentMessageSummary(messages);
107
+ function buildWorkspaceAgentMessageCenterDigest(input) {
108
+ const {
109
+ fallbackTitle,
110
+ latestAgentMessage,
111
+ needsAttention,
112
+ pendingPrompt,
113
+ status
114
+ } = input;
114
115
  const fallbackSummary = firstNonEmptyString(
115
- latestAgentMessage2?.summary ?? null,
116
+ latestAgentMessage?.summary ?? null,
116
117
  needsAttention?.summary ?? null,
117
118
  pendingPromptSummary(pendingPrompt),
118
119
  fallbackTitle
@@ -126,7 +127,7 @@ function buildWorkspaceAgentMessageCenterDigest({
126
127
  needsAttention?.summary ?? null,
127
128
  fallbackSummary
128
129
  ),
129
- occurredAtUnixMs: needsAttention?.occurredAtUnixMs ?? promptTimeUnixMs(pendingPrompt) ?? latestAgentMessage2?.occurredAtUnixMs ?? null
130
+ occurredAtUnixMs: needsAttention?.occurredAtUnixMs ?? promptTimeUnixMs(pendingPrompt) ?? latestAgentMessage?.occurredAtUnixMs ?? null
130
131
  }
131
132
  };
132
133
  }
@@ -135,7 +136,7 @@ function buildWorkspaceAgentMessageCenterDigest({
135
136
  primary: {
136
137
  kind: "error",
137
138
  summary: fallbackSummary,
138
- occurredAtUnixMs: latestAgentMessage2?.occurredAtUnixMs ?? null
139
+ occurredAtUnixMs: latestAgentMessage?.occurredAtUnixMs ?? null
139
140
  }
140
141
  };
141
142
  }
@@ -144,7 +145,7 @@ function buildWorkspaceAgentMessageCenterDigest({
144
145
  primary: {
145
146
  kind: "outcome",
146
147
  summary: fallbackSummary,
147
- occurredAtUnixMs: latestAgentMessage2?.occurredAtUnixMs ?? null
148
+ occurredAtUnixMs: latestAgentMessage?.occurredAtUnixMs ?? null
148
149
  }
149
150
  };
150
151
  }
@@ -153,7 +154,7 @@ function buildWorkspaceAgentMessageCenterDigest({
153
154
  primary: {
154
155
  kind: "progress",
155
156
  summary: fallbackSummary,
156
- occurredAtUnixMs: latestAgentMessage2?.occurredAtUnixMs ?? null
157
+ occurredAtUnixMs: latestAgentMessage?.occurredAtUnixMs ?? null
157
158
  }
158
159
  };
159
160
  }
@@ -161,28 +162,15 @@ function buildWorkspaceAgentMessageCenterDigest({
161
162
  primary: {
162
163
  kind: "summary",
163
164
  summary: fallbackSummary,
164
- occurredAtUnixMs: latestAgentMessage2?.occurredAtUnixMs ?? null
165
+ occurredAtUnixMs: latestAgentMessage?.occurredAtUnixMs ?? null
165
166
  }
166
167
  };
167
168
  }
168
- function latestAgentMessageSummary(messages) {
169
- return messages.reduce(
170
- (latest, message) => {
171
- if (!isAgentMessageRole(message.role)) {
172
- return latest;
173
- }
174
- const summary = meaningfulMessageSummary(message);
175
- if (!summary) {
176
- return latest;
177
- }
178
- const occurredAtUnixMs = messageTimeUnixMs(message);
179
- if (!latest || occurredAtUnixMs >= latest.occurredAtUnixMs) {
180
- return { summary, occurredAtUnixMs };
181
- }
182
- return latest;
183
- },
184
- null
185
- );
169
+ function resolveWorkspaceAgentMessageCenterDigestAgentMessageSummary(message) {
170
+ if (!isAgentMessageRole(message.role)) {
171
+ return "";
172
+ }
173
+ return meaningfulMessageSummary(message);
186
174
  }
187
175
  function pendingPromptSummary(prompt) {
188
176
  if (!prompt) {
@@ -211,36 +199,45 @@ function isAgentMessageRole(role) {
211
199
  return normalized === "assistant" || normalized === "agent";
212
200
  }
213
201
  function meaningfulMessageSummary(message) {
214
- for (const candidate of messageSummaryCandidates(message)) {
215
- if (!isGenericToolLabelSummary(message, candidate)) {
216
- return decorateMessageSummary(message, candidate);
202
+ const payload = recordValue(message.payload);
203
+ const isToolMessage = isToolLikeMessage(message, payload);
204
+ const candidates = messageSummaryCandidates(message, payload, isToolMessage);
205
+ const structuralLabelTokens = isToolMessage ? structuralToolLabelTokens(message, payload) : null;
206
+ const hasToolDigestSignal = isToolMessage && candidates.some(isToolDigestSignalCandidate);
207
+ for (const candidate of candidates) {
208
+ if (!isGenericToolLabelSummary(candidate, {
209
+ hasToolDigestSignal,
210
+ isToolMessage,
211
+ structuralLabelTokens
212
+ })) {
213
+ return decorateMessageSummary(message, candidate, isToolMessage);
217
214
  }
218
215
  }
219
216
  return "";
220
217
  }
221
- function messageSummaryCandidates(message) {
218
+ function messageSummaryCandidates(message, payload, isToolMessage) {
222
219
  const explicitCandidates = [
223
- summaryCandidate("payload.summary", message.payload.summary),
224
- summaryCandidate("payload.displayPrompt", message.payload.displayPrompt),
225
- summaryCandidate("payload.text", message.payload.text),
226
- summaryCandidate("payload.content", message.payload.content),
227
- summaryCandidate("payload.message", message.payload.message),
228
- summaryCandidate("payload.body", message.payload.body)
220
+ summaryCandidate("payload.summary", payload.summary),
221
+ summaryCandidate("payload.displayPrompt", payload.displayPrompt),
222
+ summaryCandidate("payload.text", payload.text),
223
+ summaryCandidate("payload.content", payload.content),
224
+ summaryCandidate("payload.message", payload.message),
225
+ summaryCandidate("payload.body", payload.body)
229
226
  ];
230
- if (!isToolLikeMessage(message)) {
227
+ if (!isToolMessage) {
231
228
  return [
232
229
  ...explicitCandidates,
233
- summaryCandidate("payload.title", message.payload.title)
230
+ summaryCandidate("payload.title", payload.title)
234
231
  ].filter(
235
232
  (candidate) => Boolean(candidate)
236
233
  );
237
234
  }
238
235
  return [
239
236
  ...explicitCandidates,
240
- toolErrorSummaryCandidate(message.payload),
241
- toolOutputSummaryCandidate(message.payload),
242
- toolInputSummaryCandidate(message.payload),
243
- summaryCandidate("payload.title", message.payload.title)
237
+ toolErrorSummaryCandidate(payload),
238
+ toolOutputSummaryCandidate(payload),
239
+ toolInputSummaryCandidate(payload),
240
+ summaryCandidate("payload.title", payload.title)
244
241
  ].filter(
245
242
  (candidate) => Boolean(candidate)
246
243
  );
@@ -328,21 +325,21 @@ function toolInputSummaryCandidate(payload) {
328
325
  )
329
326
  );
330
327
  }
331
- function isGenericToolLabelSummary(message, candidate) {
332
- if (!isToolLikeMessage(message)) {
328
+ function isGenericToolLabelSummary(candidate, context) {
329
+ if (!context.isToolMessage) {
333
330
  return false;
334
331
  }
335
332
  const normalizedSummary = normalizeToken(candidate.summary);
336
333
  if (!normalizedSummary) {
337
334
  return true;
338
335
  }
339
- if (structuralToolLabelTokens(message).has(normalizedSummary)) {
336
+ if (context.structuralLabelTokens?.has(normalizedSummary)) {
340
337
  return true;
341
338
  }
342
- return candidate.source === "payload.title" && !hasToolDigestSignal(message) && looksLikeBareLabel(candidate.summary);
339
+ return candidate.source === "payload.title" && !context.hasToolDigestSignal && looksLikeBareLabel(candidate.summary);
343
340
  }
344
- function decorateMessageSummary(message, candidate) {
345
- if (!isToolLikeMessage(message)) {
341
+ function decorateMessageSummary(message, candidate, isToolMessage) {
342
+ if (!isToolMessage) {
346
343
  return candidate.summary;
347
344
  }
348
345
  const mcpTarget = extractAgentMcpToolTarget({ payload: message.payload });
@@ -354,8 +351,7 @@ function decorateMessageSummary(message, candidate) {
354
351
  }
355
352
  return `${mcpTarget.displayName}: ${candidate.summary}`;
356
353
  }
357
- function isToolLikeMessage(message) {
358
- const payload = recordValue(message.payload);
354
+ function isToolLikeMessage(message, payload = recordValue(message.payload)) {
359
355
  const normalizedKind = normalizeToken(message.kind);
360
356
  const normalizedType = [
361
357
  stringValue(payload.type),
@@ -366,8 +362,7 @@ function isToolLikeMessage(message) {
366
362
  stringValue(payload.callType) || stringValue(payload.toolName) || stringValue(payload.tool) || hasRecordValue(payload.input) || hasRecordValue(payload.output) || hasRecordValue(payload.error)
367
363
  );
368
364
  }
369
- function structuralToolLabelTokens(message) {
370
- const payload = recordValue(message.payload);
365
+ function structuralToolLabelTokens(message, payload = recordValue(message.payload)) {
371
366
  const metadata = recordValue(payload.metadata);
372
367
  return new Set(
373
368
  [
@@ -390,11 +385,8 @@ function structuralToolLabelTokens(message) {
390
385
  function includesAny(value, needles) {
391
386
  return needles.some((needle) => value.includes(normalizeToken(needle)));
392
387
  }
393
- function hasToolDigestSignal(message) {
394
- const payload = recordValue(message.payload);
395
- return Boolean(
396
- toolErrorSummaryCandidate(payload) || toolOutputSummaryCandidate(payload) || toolInputSummaryCandidate(payload)
397
- );
388
+ function isToolDigestSignalCandidate(candidate) {
389
+ return candidate.source === "tool.error" || candidate.source === "tool.output" || candidate.source === "tool.input";
398
390
  }
399
391
  function looksLikeBareLabel(value) {
400
392
  const trimmed = value.trim();
@@ -403,9 +395,6 @@ function looksLikeBareLabel(value) {
403
395
  function normalizeToken(value) {
404
396
  return value.replace(/[_\s.-]+/g, "").toLowerCase();
405
397
  }
406
- function messageTimeUnixMs(message) {
407
- return positiveNumber(message.occurredAtUnixMs) ?? positiveNumber(message.completedAtUnixMs) ?? positiveNumber(message.startedAtUnixMs) ?? positiveNumber(message.version) ?? 0;
408
- }
409
398
  function firstNonEmptyString(...values) {
410
399
  return values.find((value) => value !== null && value.trim().length > 0) ?? "";
411
400
  }
@@ -465,17 +454,24 @@ function buildWorkspaceAgentMessageCenterModel(snapshot, options = {}) {
465
454
  const displayStatuses = selectSessionDisplayStatuses(snapshot);
466
455
  const items = snapshot.sessions.filter((session) => session.visible !== false).map((session) => {
467
456
  const messages = resolveSessionMessages(snapshot, session);
457
+ const messageAnalysis = analyzeMessageCenterSessionMessages(
458
+ session.agentSessionId,
459
+ messages
460
+ );
468
461
  const needsAttention = needsAttentionBySessionId.get(session.agentSessionId) ?? null;
469
462
  const status = displayStatuses.get(session.agentSessionId) ?? "idle";
470
- const lastAgentMessage = latestAgentMessage(messages);
471
- const title = resolveSessionTitle(session, messages);
472
- const pendingPrompt = pendingPromptFromMessages(messages) ?? codexPlanImplementationPrompt(session, status, messages) ?? fallbackPromptFromNeedsAttention(
463
+ const lastAgentMessage = messageAnalysis.latestAgentMessage;
464
+ const title = resolveSessionTitle(
465
+ session,
466
+ messageAnalysis.firstUserMessageSummary
467
+ );
468
+ const pendingPrompt = messageAnalysis.pendingPrompt ?? codexPlanImplementationPrompt(session, status, messages) ?? fallbackPromptFromNeedsAttention(
473
469
  needsAttention,
474
470
  options.promptFallbackLabels
475
471
  );
476
472
  const digest = buildWorkspaceAgentMessageCenterDigest({
477
473
  fallbackTitle: resolveDigestFallbackTitle(session),
478
- messages,
474
+ latestAgentMessage: messageAnalysis.latestDigestAgentMessage,
479
475
  needsAttention,
480
476
  pendingPrompt,
481
477
  status
@@ -504,7 +500,7 @@ function buildWorkspaceAgentMessageCenterModel(snapshot, options = {}) {
504
500
  pendingPrompt,
505
501
  needsAttentionKind: needsAttention?.kind ?? null,
506
502
  needsAttentionSummary: needsAttention?.summary ?? null,
507
- latestTurnOutcome: latestTurnOutcome(session.agentSessionId, messages),
503
+ latestTurnOutcome: messageAnalysis.latestTurnOutcome,
508
504
  sortTimeUnixMs
509
505
  };
510
506
  }).filter(
@@ -576,47 +572,66 @@ function resolveSessionMessages(snapshot, session) {
576
572
  }
577
573
  return [];
578
574
  }
579
- function resolveSessionTitle(session, messages) {
575
+ function resolveSessionTitle(session, firstUserMessageSummary) {
580
576
  const title = session.title.trim();
581
577
  if (title) {
582
578
  return title;
583
579
  }
584
- return firstUserMessageText(messages) || session.provider || session.agentSessionId;
580
+ return firstUserMessageSummary || session.provider || session.agentSessionId;
585
581
  }
586
582
  function resolveDigestFallbackTitle(session) {
587
583
  return session.title.trim() || session.provider || session.agentSessionId;
588
584
  }
589
- function firstUserMessageText(messages) {
585
+ function analyzeMessageCenterSessionMessages(agentSessionId, messages) {
586
+ let firstUserMessageSummary = "";
587
+ let latestAgentMessage = null;
588
+ let latestDigestAgentMessage = null;
589
+ let latestPendingPrompt = null;
590
+ let latestOutcome = null;
590
591
  for (const message of messages) {
591
- if (message.role.trim().toLowerCase() !== "user") {
592
- continue;
593
- }
594
- const summary = messageSummary(message);
595
- if (summary) {
596
- return summary;
597
- }
598
- }
599
- return "";
600
- }
601
- function pendingPromptFromMessages(messages) {
602
- for (const message of [...messages].sort(compareMessagesByRecentTime)) {
603
- if (isTerminalMessageStatus(message.status)) {
604
- continue;
605
- }
606
- const approval = approvalPromptFromMessage(message);
607
- if (approval) {
608
- return approval;
592
+ if (!firstUserMessageSummary && isUserMessageRole(message.role)) {
593
+ firstUserMessageSummary = messageSummary(message);
609
594
  }
610
- const askUser = askUserPromptFromMessage(message);
611
- if (askUser) {
612
- return askUser;
595
+ if (isAgentMessageRole2(message.role)) {
596
+ const summary = messageSummary(message);
597
+ if (summary) {
598
+ const occurredAtUnixMs = messageTimeUnixMs(message);
599
+ if (!latestAgentMessage || occurredAtUnixMs >= latestAgentMessage.occurredAtUnixMs) {
600
+ latestAgentMessage = { summary, occurredAtUnixMs };
601
+ }
602
+ }
603
+ const digestSummary = resolveWorkspaceAgentMessageCenterDigestAgentMessageSummary(message);
604
+ if (digestSummary) {
605
+ const occurredAtUnixMs = messageTimeUnixMs(message);
606
+ if (!latestDigestAgentMessage || occurredAtUnixMs >= latestDigestAgentMessage.occurredAtUnixMs) {
607
+ latestDigestAgentMessage = {
608
+ summary: digestSummary,
609
+ occurredAtUnixMs
610
+ };
611
+ }
612
+ }
613
+ const outcome = turnOutcomeFromMessage(agentSessionId, message);
614
+ if (outcome && (!latestOutcome || compareMessagesByRecentTime(message, latestOutcome.message) < 0)) {
615
+ latestOutcome = { message, outcome };
616
+ }
613
617
  }
614
- const exitPlan = exitPlanPromptFromMessage(message);
615
- if (exitPlan) {
616
- return exitPlan;
618
+ if (!isTerminalMessageStatus(message.status)) {
619
+ const prompt = promptFromMessage(message);
620
+ if (prompt && (!latestPendingPrompt || compareMessagesByRecentTime(message, latestPendingPrompt.message) < 0)) {
621
+ latestPendingPrompt = { message, prompt };
622
+ }
617
623
  }
618
624
  }
619
- return null;
625
+ return {
626
+ firstUserMessageSummary,
627
+ latestDigestAgentMessage,
628
+ latestAgentMessage,
629
+ latestTurnOutcome: latestOutcome?.outcome ?? null,
630
+ pendingPrompt: latestPendingPrompt?.prompt ?? null
631
+ };
632
+ }
633
+ function promptFromMessage(message) {
634
+ return approvalPromptFromMessage(message) ?? askUserPromptFromMessage(message) ?? exitPlanPromptFromMessage(message);
620
635
  }
621
636
  function approvalPromptFromMessage(message) {
622
637
  if (!isPermissionMessage(message)) {
@@ -667,7 +682,7 @@ function approvalPromptFromMessage(message) {
667
682
  input: Object.keys(input).length > 0 ? input : payload,
668
683
  options,
669
684
  output: null,
670
- occurredAtUnixMs: messageTimeUnixMs2(message) || null
685
+ occurredAtUnixMs: messageTimeUnixMs(message) || null
671
686
  };
672
687
  }
673
688
  function askUserPromptFromMessage(message) {
@@ -677,8 +692,7 @@ function askUserPromptFromMessage(message) {
677
692
  const payload = recordValue2(message.payload);
678
693
  const toolState = recordValue2(payload.tool_state);
679
694
  const input = Object.keys(recordValue2(payload.input)).length > 0 ? recordValue2(payload.input) : recordValue2(toolState.input);
680
- const rawQuestions = arrayValue(input.questions).length > 0 ? input.questions : payload.questions;
681
- const questions = normalizeAskUserQuestions(rawQuestions);
695
+ const questions = normalizeAskUserQuestions(input.questions);
682
696
  if (questions.length === 0) {
683
697
  return null;
684
698
  }
@@ -717,52 +731,18 @@ function codexPlanImplementationPrompt(session, status, messages) {
717
731
  const title = planMessage ? messageSummary(planMessage) : "";
718
732
  return planImplementationPromptFromPlanTurn(planTurnId, title);
719
733
  }
720
- function latestAgentMessage(messages) {
721
- return messages.reduce(
722
- (latest, message) => {
723
- if (!isAgentMessageRole2(message.role)) {
724
- return latest;
725
- }
726
- const summary = messageSummary(message);
727
- if (!summary) {
728
- return latest;
729
- }
730
- const occurredAtUnixMs = messageTimeUnixMs2(message);
731
- if (!latest || occurredAtUnixMs >= latest.occurredAtUnixMs) {
732
- return { summary, occurredAtUnixMs };
733
- }
734
- return latest;
735
- },
736
- null
737
- );
738
- }
739
- function latestTurnOutcome(agentSessionId, messages) {
740
- const latest = messages.flatMap((message) => {
741
- const status = outcomeStatusFromMessage(message);
742
- if (!status) {
743
- return [];
744
- }
745
- const turnId = message.turnId?.trim() || null;
746
- const messageId = message.messageId.trim();
747
- const notificationSubject = turnId ? `turn:${turnId}` : `message:${messageId}`;
748
- return [
749
- {
750
- notificationKey: `${agentSessionId}:${notificationSubject}:${status}`,
751
- status,
752
- turnId,
753
- sortMessage: message
754
- }
755
- ];
756
- }).sort(
757
- (left, right) => compareMessagesByRecentTime(left.sortMessage, right.sortMessage)
758
- )[0];
759
- if (!latest) {
734
+ function turnOutcomeFromMessage(agentSessionId, message) {
735
+ const status = outcomeStatusFromMessage(message);
736
+ if (!status) {
760
737
  return null;
761
738
  }
739
+ const turnId = message.turnId?.trim() || null;
740
+ const messageId = message.messageId.trim();
741
+ const notificationSubject = turnId ? `turn:${turnId}` : `message:${messageId}`;
762
742
  return {
763
- notificationKey: latest.notificationKey,
764
- status: latest.status,
765
- turnId: latest.turnId
743
+ notificationKey: `${agentSessionId}:${notificationSubject}:${status}`,
744
+ status,
745
+ turnId
766
746
  };
767
747
  }
768
748
  function outcomeStatusFromMessage(message) {
@@ -847,6 +827,9 @@ function isAgentMessageRole2(role) {
847
827
  const normalized = role.trim().toLowerCase();
848
828
  return normalized === "assistant" || normalized === "agent";
849
829
  }
830
+ function isUserMessageRole(role) {
831
+ return role.trim().toLowerCase() === "user";
832
+ }
850
833
  function isTerminalMessageStatus(status) {
851
834
  switch (status?.trim().toLowerCase()) {
852
835
  case "answered":
@@ -898,7 +881,7 @@ function normalizedMetadataValues(message) {
898
881
  ].join(" ").replace(/[_\s-]+/g, "").toLowerCase();
899
882
  }
900
883
  function compareMessagesByRecentTime(left, right) {
901
- return messageTimeUnixMs2(right) - messageTimeUnixMs2(left) || right.version - left.version || right.messageId.localeCompare(left.messageId);
884
+ return messageTimeUnixMs(right) - messageTimeUnixMs(left) || right.version - left.version || right.messageId.localeCompare(left.messageId);
902
885
  }
903
886
  function includesAny2(value, needles) {
904
887
  return needles.some(
@@ -916,7 +899,7 @@ function messageSummary(message) {
916
899
  stringValue2(message.payload.title)
917
900
  );
918
901
  }
919
- function messageTimeUnixMs2(message) {
902
+ function messageTimeUnixMs(message) {
920
903
  return positiveNumber2(message.occurredAtUnixMs) ?? positiveNumber2(message.completedAtUnixMs) ?? positiveNumber2(message.startedAtUnixMs) ?? positiveNumber2(message.version) ?? 0;
921
904
  }
922
905
  function firstNonEmptyString2(...values) {
@@ -1633,7 +1616,7 @@ function MessageCenterOpenChatButton({
1633
1616
  variant: "ghost",
1634
1617
  size: "default",
1635
1618
  className: cn2(
1636
- "workspace-agent-message-center__open-chat-button h-auto gap-1.5 border-0 bg-transparent p-0 text-[var(--agent-gui-accent)] shadow-none transition-[color,opacity,visibility] hover:bg-transparent hover:text-[var(--agent-gui-accent)] focus-visible:bg-transparent focus-visible:text-[var(--agent-gui-accent)] active:bg-transparent",
1619
+ "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",
1637
1620
  !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"
1638
1621
  ),
1639
1622
  onClick: () => onOpenChat({
@@ -1679,7 +1662,7 @@ function MessageCenterIdentityLabel({
1679
1662
  agentAvatarUrl
1680
1663
  }
1681
1664
  ),
1682
- /* @__PURE__ */ jsxs("span", { className: "workspace-agent-message-center__identity-names flex min-w-0 items-center gap-1 truncate text-[var(--text-secondary)]", children: [
1665
+ /* @__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: [
1683
1666
  /* @__PURE__ */ jsx2("span", { className: "min-w-0 truncate", children: identity.userName }),
1684
1667
  /* @__PURE__ */ jsx2("span", { className: "shrink-0 text-[var(--text-tertiary)]", children: "&" }),
1685
1668
  /* @__PURE__ */ jsx2("span", { className: "min-w-0 truncate", children: identity.agentName })
@@ -1846,7 +1829,7 @@ function AgentProviderLabel({ provider }) {
1846
1829
  "aria-hidden": "true"
1847
1830
  }
1848
1831
  ),
1849
- /* @__PURE__ */ jsx2("span", { className: "workspace-agent-message-center__provider-name min-w-0 truncate text-[var(--text-secondary)]", children: label })
1832
+ /* @__PURE__ */ jsx2("span", { className: "workspace-agent-message-center__provider-name min-w-0 truncate text-[13px] leading-5 text-[var(--text-secondary)]", children: label })
1850
1833
  ] });
1851
1834
  }
1852
1835
  function statusClass(item) {
@@ -3000,6 +2983,7 @@ function MessageCenterGroupHeading({
3000
2983
  group
3001
2984
  }) {
3002
2985
  "use memo";
2986
+ const statusSignal = messageCenterGroupStatusSignal(group.id);
3003
2987
  if (group.provider) {
3004
2988
  return /* @__PURE__ */ jsxs4(
3005
2989
  "h3",
@@ -3033,11 +3017,45 @@ function MessageCenterGroupHeading({
3033
3017
  }
3034
3018
  );
3035
3019
  }
3036
- return /* @__PURE__ */ jsxs4("h3", { className: "truncate text-[11px] font-normal leading-4 text-[var(--text-tertiary)]", children: [
3037
- group.label,
3038
- " \xB7 ",
3039
- group.items.length
3040
- ] });
3020
+ return /* @__PURE__ */ jsxs4(
3021
+ "h3",
3022
+ {
3023
+ className: "flex min-w-0 items-center gap-1.5 text-[11px] font-normal leading-4 text-[var(--text-tertiary)]",
3024
+ title: `${group.label} \xB7 ${group.items.length}`,
3025
+ children: [
3026
+ statusSignal ? /* @__PURE__ */ jsx5(
3027
+ StatusDot2,
3028
+ {
3029
+ tone: statusSignal.tone,
3030
+ pulse: statusSignal.pulse,
3031
+ size: "sm",
3032
+ title: group.label
3033
+ }
3034
+ ) : null,
3035
+ /* @__PURE__ */ jsxs4("span", { className: "min-w-0 truncate", children: [
3036
+ group.label,
3037
+ " \xB7 ",
3038
+ group.items.length
3039
+ ] })
3040
+ ]
3041
+ }
3042
+ );
3043
+ }
3044
+ function messageCenterGroupStatusSignal(groupId) {
3045
+ switch (groupId) {
3046
+ case "needs-attention":
3047
+ case "waiting":
3048
+ return { pulse: true, tone: "amber" };
3049
+ case "working":
3050
+ return { pulse: true, tone: "blue" };
3051
+ case "failed":
3052
+ return { pulse: false, tone: "red" };
3053
+ case "recently-completed":
3054
+ case "completed":
3055
+ return { pulse: false, tone: "green" };
3056
+ default:
3057
+ return null;
3058
+ }
3041
3059
  }
3042
3060
 
3043
3061
  // agent-message-center/workspaceAgentMessageCenterModelStability.ts