@tutti-os/agent-gui 0.0.38 → 0.0.40

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 (62) hide show
  1. package/README.md +40 -0
  2. package/dist/{AgentMessageMarkdown-Cq-7DSV2.d.ts → AgentMessageMarkdown-GDgLA-im.d.ts} +7 -156
  3. package/dist/agent-conversation/index.d.ts +2 -1
  4. package/dist/agent-conversation/index.js +5 -5
  5. package/dist/agent-message-center/index.js +223 -14
  6. package/dist/agent-message-center/index.js.map +1 -1
  7. package/dist/app/renderer/agentactivity.css +67 -0
  8. package/dist/chunk-4K22O34C.js +123 -0
  9. package/dist/chunk-4K22O34C.js.map +1 -0
  10. package/dist/{chunk-7F4M55U3.js → chunk-DO7D7OOL.js} +24 -7
  11. package/dist/chunk-DO7D7OOL.js.map +1 -0
  12. package/dist/{chunk-MUZMBEFO.js → chunk-EFDGMXTB.js} +82 -8
  13. package/dist/chunk-EFDGMXTB.js.map +1 -0
  14. package/dist/{chunk-MKSRP5XS.js → chunk-EQ4RSPQE.js} +5 -5
  15. package/dist/{chunk-JNGYJ7GM.js → chunk-EU7RWKHE.js} +2 -2
  16. package/dist/{chunk-IXIGWLQY.js → chunk-F5DYXCY3.js} +1 -1
  17. package/dist/{chunk-IXIGWLQY.js.map → chunk-F5DYXCY3.js.map} +1 -1
  18. package/dist/{chunk-NCS7X3XY.js → chunk-R7XH3C4Y.js} +16 -4
  19. package/dist/chunk-R7XH3C4Y.js.map +1 -0
  20. package/dist/{chunk-XROBPALT.js → chunk-RE3AHBX6.js} +2 -2
  21. package/dist/{chunk-2ADVHCST.js → chunk-TXXWUG2J.js} +1 -1
  22. package/dist/chunk-TXXWUG2J.js.map +1 -0
  23. package/dist/{chunk-L7FBT3VR.js → chunk-UUM2GZXH.js} +98 -5
  24. package/dist/chunk-UUM2GZXH.js.map +1 -0
  25. package/dist/{chunk-44YASHVW.js → chunk-WC34LVH6.js} +433 -143
  26. package/dist/chunk-WC34LVH6.js.map +1 -0
  27. package/dist/{chunk-JL2WNRYC.js → chunk-WJPEKD3F.js} +17 -1
  28. package/dist/chunk-WJPEKD3F.js.map +1 -0
  29. package/dist/{chunk-WHWZZYBV.js → chunk-Y2DQJPTL.js} +2 -2
  30. package/dist/{chunk-SS5YEVAI.js → chunk-Y5SE2XMU.js} +2 -2
  31. package/dist/context-mention-palette/index.js +6 -6
  32. package/dist/i18n/index.d.ts +16 -0
  33. package/dist/i18n/index.js +1 -1
  34. package/dist/index.d.ts +124 -102
  35. package/dist/index.js +2298 -996
  36. package/dist/index.js.map +1 -1
  37. package/dist/types-xMz0lJWt.d.ts +173 -0
  38. package/dist/workbench/contribution.d.ts +1 -0
  39. package/dist/workbench/contribution.js +5 -4
  40. package/dist/workbench/index.d.ts +3 -1
  41. package/dist/workbench/index.js +5 -4
  42. package/dist/workbench/launch.d.ts +1 -0
  43. package/dist/workbench/launch.js +2 -2
  44. package/dist/workbench/providerCatalog.d.ts +1 -0
  45. package/dist/workbench/state.d.ts +7 -0
  46. package/dist/workbench/state.js +2 -1
  47. package/dist/workbench/types.d.ts +6 -0
  48. package/dist/workbench/types.js +1 -1
  49. package/dist/workspace-agent-generated-files.js +2 -2
  50. package/package.json +13 -12
  51. package/dist/chunk-2ADVHCST.js.map +0 -1
  52. package/dist/chunk-44YASHVW.js.map +0 -1
  53. package/dist/chunk-7F4M55U3.js.map +0 -1
  54. package/dist/chunk-JL2WNRYC.js.map +0 -1
  55. package/dist/chunk-L7FBT3VR.js.map +0 -1
  56. package/dist/chunk-MUZMBEFO.js.map +0 -1
  57. package/dist/chunk-NCS7X3XY.js.map +0 -1
  58. /package/dist/{chunk-MKSRP5XS.js.map → chunk-EQ4RSPQE.js.map} +0 -0
  59. /package/dist/{chunk-JNGYJ7GM.js.map → chunk-EU7RWKHE.js.map} +0 -0
  60. /package/dist/{chunk-XROBPALT.js.map → chunk-RE3AHBX6.js.map} +0 -0
  61. /package/dist/{chunk-WHWZZYBV.js.map → chunk-Y2DQJPTL.js.map} +0 -0
  62. /package/dist/{chunk-SS5YEVAI.js.map → chunk-Y5SE2XMU.js.map} +0 -0
package/README.md CHANGED
@@ -59,3 +59,43 @@ Run this boundary check after changing AgentGUI data flow:
59
59
  ```sh
60
60
  pnpm check:agent-activity-runtime-boundaries
61
61
  ```
62
+
63
+ ## Provider Targets
64
+
65
+ `provider` remains the real provider identity, such as `codex`,
66
+ `claude-code`, or `nexight`. AgentGUI uses that identity for composer options,
67
+ settings, icons, probes, status, and provider-specific UI policy.
68
+
69
+ Hosts may pass `providerTargets` when a real provider has multiple launch
70
+ targets. A target has display metadata plus an opaque `ref`:
71
+
72
+ ```ts
73
+ export interface AgentGUIProviderTargetRef {
74
+ kind: string;
75
+ provider: AgentGUIProvider;
76
+ [key: string]: unknown;
77
+ }
78
+
79
+ export interface AgentGUIProviderTarget {
80
+ targetId: string;
81
+ provider: AgentGUIProvider;
82
+ ref: AgentGUIProviderTargetRef;
83
+ label: string;
84
+ description?: string;
85
+ ownerLabel?: string;
86
+ disabled?: boolean;
87
+ unavailableReason?: string;
88
+ }
89
+ ```
90
+
91
+ AgentGUI does not interpret `ref.kind` and does not treat `targetId` or `ref`
92
+ as authority. It displays `target.label`, keeps provider logic keyed by the
93
+ real `target.provider`, and passes `providerTargetRef` through activation.
94
+ Trusted host code must re-authenticate the current user/workspace and resolve
95
+ any invocation plan before launching.
96
+
97
+ If `providerTargets` is omitted or empty, AgentGUI creates local targets such as
98
+ `local:codex` and `local:claude-code` from the static provider catalog for
99
+ display/backward compatibility. Those fallback local targets are not persisted
100
+ or sent as `providerTargetRef`; legacy hosts continue to receive only the real
101
+ `provider`.
@@ -1,4 +1,5 @@
1
1
  import { AgentActivityUsage } from '@tutti-os/agent-activity-core';
2
+ import { e as AgentHostAgentSessionCommand, f as AgentHostAgentSessionComposerSettings, h as AgentHostAgentSessionReasoningEffort, i as AgentHostAgentSessionSpeed, g as AgentHostAgentSessionPermissionConfig, j as AgentHostAgentSessionState, a as AgentGUIProvider, A as AgentGUINodeData, b as AgentGUIProviderTarget, m as AgentPromptContentBlock } from './types-xMz0lJWt.js';
2
3
  import { A as AgentHostBatchUserInfoInput, a as AgentHostBatchUserInfoResult, b as AgentHostDeleteWorkspaceAgentSessionInput, k as AgentHostWorkspaceAgentSessionSummaryInput, j as AgentHostWorkspaceAgentSessionSummary, e as AgentHostWorkspaceAgentListInput, l as AgentHostWorkspaceAgentSnapshot, i as AgentHostWorkspaceAgentSessionMessagesInput, h as AgentHostWorkspaceAgentSessionMessages, p as WorkspaceAgentActivitySyncState } from './workspaceAgentActivityListViewModel-DLnMBMoh.js';
3
4
  import { A as AgentApprovalItemVM, a as AgentAskUserQuestionVM, b as AgentConversationPromptVM, c as AgentConversationVM, W as WorkspaceAgentSessionDetailViewModel } from './agentConversationVM-1QgRwvwZ.js';
4
5
  import { WorkspaceUserProjectService } from '@tutti-os/workspace-user-project/contracts';
@@ -13,134 +14,6 @@ interface AppErrorDescriptor {
13
14
  debugMessage?: string;
14
15
  }
15
16
 
16
- type AgentHostAgentSessionProvider = "claude-code" | "codex" | "nexight" | "gemini" | "hermes" | "openclaw";
17
- type AgentHostAgentSessionPermissionModeSemantic = "ask-before-write" | "accept-edits" | "locked-down" | "auto" | "full-access" | "unconfigurable";
18
- type AgentHostAgentSessionReasoningEffort = "minimal" | "low" | "medium" | "high" | "xhigh" | string;
19
- type AgentHostAgentSessionSpeed = "standard" | "fast" | string;
20
- interface AgentHostAgentSessionPermissionModeOption {
21
- id: string;
22
- label?: string;
23
- description?: string;
24
- semantic: AgentHostAgentSessionPermissionModeSemantic;
25
- }
26
- interface AgentHostAgentSessionPermissionConfig {
27
- configurable: boolean;
28
- defaultValue?: string | null;
29
- modes: AgentHostAgentSessionPermissionModeOption[];
30
- }
31
- interface AgentHostAgentSessionComposerSettings {
32
- model?: string | null;
33
- reasoningEffort?: AgentHostAgentSessionReasoningEffort | null;
34
- speed?: AgentHostAgentSessionSpeed | null;
35
- planMode?: boolean;
36
- browserUse?: boolean;
37
- computerUse?: boolean;
38
- permissionModeId?: string | null;
39
- }
40
- interface AgentHostAgentSession {
41
- workspaceId: string;
42
- agentSessionId: string;
43
- provider: AgentHostAgentSessionProvider;
44
- providerSessionId: string;
45
- resumable?: boolean;
46
- cwd?: string;
47
- status: "ready" | "working" | "canceled" | "failed" | "completed" | string;
48
- title?: string;
49
- pinnedAtUnixMs?: number | null;
50
- visible?: boolean;
51
- permissionModeId?: string;
52
- permissionConfig?: AgentHostAgentSessionPermissionConfig;
53
- settings?: AgentHostAgentSessionComposerSettings;
54
- createdAtUnixMs: number;
55
- updatedAtUnixMs: number;
56
- }
57
- interface AgentHostAgentSessionInteractivePrompt {
58
- kind: string;
59
- requestId?: string;
60
- toolName?: string;
61
- status?: string;
62
- input?: Record<string, unknown>;
63
- output?: Record<string, unknown>;
64
- error?: Record<string, unknown>;
65
- metadata?: Record<string, unknown>;
66
- }
67
- interface AgentHostAgentSessionState {
68
- workspaceId: string;
69
- agentSessionId: string;
70
- provider: AgentHostAgentSessionProvider;
71
- providerSessionId?: string;
72
- resumable?: boolean;
73
- status: AgentHostAgentSession["status"];
74
- turnLifecycle?: AgentHostAgentActivityTurnLifecycle | null;
75
- submitAvailability?: AgentHostAgentActivitySubmitAvailability | null;
76
- permissionModeId?: string;
77
- permissionConfig?: AgentHostAgentSessionPermissionConfig;
78
- settings?: AgentHostAgentSessionComposerSettings;
79
- authState?: string;
80
- runtimeContext?: Record<string, unknown>;
81
- pinnedAtUnixMs?: number | null;
82
- pendingInteractive?: AgentHostAgentSessionInteractivePrompt | null;
83
- updatedAtUnixMs: number;
84
- }
85
- interface AgentHostAgentActivityCompletedCommand {
86
- kind: string;
87
- status: string;
88
- }
89
- interface AgentHostAgentActivityTurnLifecycle {
90
- activeTurnId: string | null;
91
- phase: string;
92
- settling?: boolean;
93
- outcome?: string | null;
94
- completedCommand?: AgentHostAgentActivityCompletedCommand | null;
95
- }
96
- interface AgentHostAgentActivitySubmitAvailability {
97
- state: string;
98
- reason?: string;
99
- }
100
- type AgentHostAgentSessionActivationMode = "new" | "existing";
101
- type AgentHostAgentSessionActivationStatus = "attached" | "already_attached" | "failed";
102
- interface AgentHostActivateAgentSessionResult {
103
- session: AgentHostAgentSession;
104
- activation: {
105
- mode: AgentHostAgentSessionActivationMode;
106
- status: AgentHostAgentSessionActivationStatus;
107
- };
108
- error?: {
109
- code: string;
110
- message: string;
111
- debugMessage?: string;
112
- };
113
- }
114
- interface AgentHostUnactivateAgentSessionResult {
115
- agentSessionId: string;
116
- buffered: boolean;
117
- }
118
- interface AgentPromptContentBlock {
119
- type: "text" | "image" | "file" | "skill" | "mention";
120
- text?: string;
121
- mimeType?: "image/png" | "image/jpeg" | "image/webp" | string;
122
- data?: string;
123
- url?: string;
124
- attachmentId?: string;
125
- name?: string;
126
- path?: string;
127
- uri?: string;
128
- hostPath?: string;
129
- uploadStatus?: string;
130
- assetId?: string;
131
- kind?: string;
132
- sizeBytes?: number;
133
- }
134
- interface AgentHostUpdateAgentSessionSettingsResult {
135
- agentSessionId: string;
136
- settings: AgentHostAgentSessionComposerSettings;
137
- }
138
- interface AgentHostAgentSessionCommand {
139
- name: string;
140
- description?: string;
141
- inputHint?: string;
142
- }
143
-
144
17
  type AgentAvailabilityStatus = "available" | "unavailable" | "unknown";
145
18
  type AgentQuotaType = "session" | "weekly" | "monthly" | "daily" | "model" | "cost";
146
19
  interface AgentAvailabilityCheck {
@@ -252,6 +125,10 @@ type AgentHostWorkspaceAgentSessionMessagesRuntimeInput = AgentHostWorkspaceScop
252
125
  type AgentHostWorkspaceAgentSessionSummaryRuntimeInput = AgentHostWorkspaceScopedInput<AgentHostWorkspaceAgentSessionSummaryInput>;
253
126
  type AgentHostDeleteWorkspaceAgentSessionRuntimeInput = AgentHostWorkspaceScopedInput<AgentHostDeleteWorkspaceAgentSessionInput>;
254
127
  type AgentHostClipboardApi = {
128
+ writeImage?: (input: {
129
+ data: string;
130
+ mimeType: "image/png";
131
+ }) => AgentHostAsyncResult<void>;
255
132
  writeText: (text: string) => AgentHostAsyncResult<void>;
256
133
  };
257
134
  type AgentHostDebugApi = {
@@ -477,33 +354,6 @@ interface AgentHostRuntimeApi {
477
354
  workspaceAgentProbes?: AgentHostWorkspaceAgentProbesApi;
478
355
  }
479
356
 
480
- declare const AGENT_PROVIDERS: readonly ["claude-code", "codex", "nexight", "opencode", "gemini", "openclaw", "hermes"];
481
- type AgentProvider = (typeof AGENT_PROVIDERS)[number];
482
-
483
- interface AgentGUINodeData {
484
- provider: AgentGUIProvider;
485
- lastActiveAgentSessionId: string | null;
486
- lastActiveConversationTitle?: string | null;
487
- conversationCount?: number | null;
488
- conversationRailWidthPx?: number | null;
489
- conversationRailCollapsed?: boolean | null;
490
- composerOverrides?: AgentHostAgentSessionComposerSettings | null;
491
- composerOverridesByProvider?: Partial<Record<AgentGUIProvider, AgentHostAgentSessionComposerSettings | null>> | null;
492
- }
493
- type AgentGUIProvider = Extract<AgentProvider, "claude-code" | "codex" | "nexight" | "gemini" | "hermes" | "openclaw">;
494
- interface Size {
495
- width: number;
496
- height: number;
497
- }
498
- interface Point {
499
- x: number;
500
- y: number;
501
- }
502
- interface NodeFrame {
503
- position: Point;
504
- size: Size;
505
- }
506
-
507
357
  type AgentSessionCommand = AgentHostAgentSessionCommand;
508
358
  type AgentSessionComposerSettings = AgentHostAgentSessionComposerSettings;
509
359
  type AgentSessionPermissionConfig = AgentHostAgentSessionPermissionConfig;
@@ -675,6 +525,7 @@ interface AgentGUINodeViewModel {
675
525
  workspacePath?: string | null;
676
526
  currentUserId?: string | null;
677
527
  data: AgentGUINodeData;
528
+ selectedProviderTarget: AgentGUIProviderTarget;
678
529
  conversations: AgentGUIConversationSummary[];
679
530
  userProjects: AgentGUIConversationUserProject[];
680
531
  activeConversation: AgentGUIConversationSummary | null;
@@ -725,4 +576,4 @@ interface AgentMessageMarkdownWorkspaceAppIcon {
725
576
  workspaceId?: string | null;
726
577
  }
727
578
 
728
- export type { AgentGUINodeData as A, NodeFrame as N, PersistWriteResult as P, ReadWorkspaceAgentReadStateInput as R, WorkspaceAgentReadStateSnapshot as W, AgentGUINodeViewModel as a, AgentGUIProviderSkillOption as b, AgentHostActivateAgentSessionResult as c, AgentHostAgentSessionComposerSettings as d, AgentHostAgentSessionState as e, AgentHostApi as f, AgentHostInputApi as g, AgentHostRuntimeApi as h, AgentHostSelectFilesInput as i, AgentHostUnactivateAgentSessionResult as j, AgentHostUpdateAgentSessionSettingsResult as k, AgentMessageMarkdownWorkspaceAppIcon as l, AgentProbeProvider as m, AgentProbeSnapshot as n, AgentProvider as o, AgentProviderProbeListInput as p, AgentProviderProbeListResult as q, AgentUsageQuota as r, AgentUsageSnapshot as s, Point as t, WriteWorkspaceAgentReadStateInput as u };
579
+ export type { AgentGUINodeViewModel as A, PersistWriteResult as P, ReadWorkspaceAgentReadStateInput as R, WorkspaceAgentReadStateSnapshot as W, AgentGUIProviderSkillOption as a, AgentHostApi as b, AgentHostInputApi as c, AgentHostRuntimeApi as d, AgentHostSelectFilesInput as e, AgentMessageMarkdownWorkspaceAppIcon as f, AgentProbeProvider as g, AgentProbeSnapshot as h, AgentProviderProbeListInput as i, AgentProviderProbeListResult as j, AgentUsageQuota as k, AgentUsageSnapshot as l, WriteWorkspaceAgentReadStateInput as m };
@@ -1,12 +1,13 @@
1
1
  import * as react from 'react';
2
2
  import { ReactNode, JSX } from 'react';
3
3
  import { W as WorkspaceLinkAction } from '../workspaceLinkActions-C6POH38D.js';
4
- import { b as AgentGUIProviderSkillOption, l as AgentMessageMarkdownWorkspaceAppIcon } from '../AgentMessageMarkdown-Cq-7DSV2.js';
4
+ import { a as AgentGUIProviderSkillOption, f as AgentMessageMarkdownWorkspaceAppIcon } from '../AgentMessageMarkdown-GDgLA-im.js';
5
5
  import { c as AgentConversationVM, W as WorkspaceAgentSessionDetailViewModel } from '../agentConversationVM-1QgRwvwZ.js';
6
6
  export { B as BuildWorkspaceAgentSessionDetailInput, d as buildWorkspaceAgentSessionDetailViewModel } from '../agentConversationVM-1QgRwvwZ.js';
7
7
  export { W as WorkspaceAgentActivityCard, n as WorkspaceAgentActivitySession, q as WorkspaceAgentActivityTimelineItem } from '../workspaceAgentActivityListViewModel-DLnMBMoh.js';
8
8
  import '@tutti-os/workspace-issue-manager/core';
9
9
  import '@tutti-os/agent-activity-core';
10
+ import '../types-xMz0lJWt.js';
10
11
  import '@tutti-os/workspace-user-project/contracts';
11
12
 
12
13
  interface AgentConversationFlowProps {
@@ -6,15 +6,15 @@ import {
6
6
  projectAgentConversationVM,
7
7
  reconcileProjectedAgentConversationVM,
8
8
  useProjectedAgentConversation
9
- } from "../chunk-7F4M55U3.js";
10
- import "../chunk-44YASHVW.js";
11
- import "../chunk-XROBPALT.js";
9
+ } from "../chunk-DO7D7OOL.js";
10
+ import "../chunk-WC34LVH6.js";
11
+ import "../chunk-RE3AHBX6.js";
12
12
  import "../chunk-Y35GDLP2.js";
13
- import "../chunk-2ADVHCST.js";
13
+ import "../chunk-TXXWUG2J.js";
14
14
  import "../chunk-TYGL25EL.js";
15
15
  import {
16
16
  translate
17
- } from "../chunk-JL2WNRYC.js";
17
+ } from "../chunk-WJPEKD3F.js";
18
18
  import "../chunk-LUGELG5V.js";
19
19
  import "../chunk-PJP5BUU6.js";
20
20
 
@@ -1,9 +1,10 @@
1
1
  import {
2
2
  AgentInteractivePromptSurface,
3
3
  approvalOptionDisplayLabel,
4
+ formatAgentSessionMentionText,
4
5
  getPromptToolDetails,
5
6
  isPromptRequestIdTitle
6
- } from "../chunk-L7FBT3VR.js";
7
+ } from "../chunk-UUM2GZXH.js";
7
8
  import {
8
9
  PLAN_IMPLEMENTATION_ACTION_IMPLEMENT,
9
10
  PLAN_IMPLEMENTATION_PROMPT,
@@ -16,17 +17,17 @@ import {
16
17
  cn,
17
18
  extractAgentMcpToolTarget,
18
19
  normalizeAskUserQuestions
19
- } from "../chunk-44YASHVW.js";
20
+ } from "../chunk-WC34LVH6.js";
20
21
  import {
21
22
  managedAgentRoundedIconUrl,
22
23
  userAvatarPlaceholderUrl,
23
24
  workspaceAgentActivityStatusLabel
24
- } from "../chunk-WHWZZYBV.js";
25
+ } from "../chunk-Y2DQJPTL.js";
25
26
  import "../chunk-MTFSQWZ6.js";
26
27
  import {
27
28
  resolveWorkspaceAgentSessionSortTimeUnixMs
28
29
  } from "../chunk-IBIMGLCD.js";
29
- import "../chunk-2ADVHCST.js";
30
+ import "../chunk-TXXWUG2J.js";
30
31
  import {
31
32
  workspaceAgentProviderLabel
32
33
  } from "../chunk-TYGL25EL.js";
@@ -35,8 +36,9 @@ import {
35
36
  } from "../chunk-GCBDIQDX.js";
36
37
  import {
37
38
  AgentGuiI18nProvider,
39
+ getActiveUiLanguage,
38
40
  useTranslation
39
- } from "../chunk-JL2WNRYC.js";
41
+ } from "../chunk-WJPEKD3F.js";
40
42
  import "../chunk-PJP5BUU6.js";
41
43
 
42
44
  // agent-message-center/WorkspaceAgentMessageCenterPanel.tsx
@@ -463,6 +465,7 @@ function buildWorkspaceAgentMessageCenterModel(snapshot, options = {}) {
463
465
  const lastAgentMessage = messageAnalysis.latestAgentMessage;
464
466
  const title = resolveSessionTitle(
465
467
  session,
468
+ messageAnalysis.latestUserMessageSummary,
466
469
  messageAnalysis.firstUserMessageSummary
467
470
  );
468
471
  const pendingPrompt = messageAnalysis.pendingPrompt ?? codexPlanImplementationPrompt(session, status, messages) ?? fallbackPromptFromNeedsAttention(
@@ -576,7 +579,11 @@ function resolveSessionMessages(snapshot, session) {
576
579
  }
577
580
  return [];
578
581
  }
579
- function resolveSessionTitle(session, firstUserMessageSummary) {
582
+ function resolveSessionTitle(session, latestUserMessageSummary, firstUserMessageSummary) {
583
+ const latest = latestUserMessageSummary.trim();
584
+ if (latest) {
585
+ return latest;
586
+ }
580
587
  const title = session.title.trim();
581
588
  if (title) {
582
589
  return title;
@@ -588,13 +595,25 @@ function resolveDigestFallbackTitle(session) {
588
595
  }
589
596
  function analyzeMessageCenterSessionMessages(agentSessionId, messages) {
590
597
  let firstUserMessageSummary = "";
598
+ let latestUserMessageSummary = "";
599
+ let latestUserMessageAtUnixMs = Number.NEGATIVE_INFINITY;
591
600
  let latestAgentMessage = null;
592
601
  let latestDigestAgentMessage = null;
593
602
  let latestPendingPrompt = null;
594
603
  let latestOutcome = null;
595
604
  for (const message of messages) {
596
- if (!firstUserMessageSummary && isUserMessageRole(message.role)) {
597
- firstUserMessageSummary = messageSummary(message);
605
+ if (isUserMessageRole(message.role)) {
606
+ const summary = messageSummary(message);
607
+ if (!firstUserMessageSummary && summary) {
608
+ firstUserMessageSummary = summary;
609
+ }
610
+ if (summary) {
611
+ const occurredAtUnixMs = messageTimeUnixMs(message);
612
+ if (occurredAtUnixMs >= latestUserMessageAtUnixMs) {
613
+ latestUserMessageSummary = summary;
614
+ latestUserMessageAtUnixMs = occurredAtUnixMs;
615
+ }
616
+ }
598
617
  }
599
618
  if (isAgentMessageRole2(message.role)) {
600
619
  const summary = messageSummary(message);
@@ -628,6 +647,7 @@ function analyzeMessageCenterSessionMessages(agentSessionId, messages) {
628
647
  }
629
648
  return {
630
649
  firstUserMessageSummary,
650
+ latestUserMessageSummary,
631
651
  latestDigestAgentMessage,
632
652
  latestAgentMessage,
633
653
  latestTurnOutcome: latestOutcome?.outcome ?? null,
@@ -936,7 +956,13 @@ import {
936
956
  useRef,
937
957
  useState
938
958
  } from "react";
939
- import { ChevronDown, ChevronUp, ExternalLink, Info } from "lucide-react";
959
+ import {
960
+ AppWindow,
961
+ ChevronDown,
962
+ ChevronUp,
963
+ ExternalLink,
964
+ Info
965
+ } from "lucide-react";
940
966
  import {
941
967
  Button,
942
968
  cn as cn2,
@@ -945,6 +971,10 @@ import {
945
971
  TooltipContent,
946
972
  TooltipTrigger
947
973
  } from "@tutti-os/ui-system";
974
+ import {
975
+ isRichTextMentionHref,
976
+ parseRichTextMentionHref
977
+ } from "@tutti-os/ui-rich-text/core";
948
978
  import { jsx as jsx2, jsxs } from "react/jsx-runtime";
949
979
  function stopMessageCenterTextPointerPropagation(event) {
950
980
  event.stopPropagation();
@@ -1357,16 +1387,99 @@ function MessageCenterStackSummary({
1357
1387
  }
1358
1388
  )
1359
1389
  ] }),
1360
- /* @__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: messageCenterStackPreviewText(firstItem) }) })
1390
+ /* @__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) }) })
1361
1391
  ]
1362
1392
  }
1363
1393
  )
1364
1394
  }
1365
1395
  );
1366
1396
  }
1367
- function messageCenterStackPreviewText(item) {
1397
+ function messageCenterStackRawPreviewText(item) {
1368
1398
  return item.digest.primary.summary.trim() || item.lastAgentMessageSummary.trim() || normalizeAgentTitleText(item.title);
1369
1399
  }
1400
+ function messageCenterStackPreviewText(item) {
1401
+ return formatAgentSessionMentionText(messageCenterStackRawPreviewText(item), {
1402
+ language: getActiveUiLanguage()
1403
+ });
1404
+ }
1405
+ var MESSAGE_CENTER_PREVIEW_MARKDOWN_LINK_PATTERN = /\[((?:\\.|[^\]\\])*)\]\(([^)\s]+)\)/g;
1406
+ var MESSAGE_CENTER_PREVIEW_LABEL_ESCAPE_PATTERN = /\\([\\[\]()])/g;
1407
+ function messageCenterStackPreviewNodes(item) {
1408
+ const text = messageCenterStackRawPreviewText(item);
1409
+ const nodes = [];
1410
+ let lastIndex = 0;
1411
+ let mentionIndex = 0;
1412
+ for (const match of text.matchAll(
1413
+ MESSAGE_CENTER_PREVIEW_MARKDOWN_LINK_PATTERN
1414
+ )) {
1415
+ const [fullMatch, rawLabel = "", href = ""] = match;
1416
+ const matchStart = match.index ?? 0;
1417
+ if (matchStart > lastIndex) {
1418
+ nodes.push(text.slice(lastIndex, matchStart));
1419
+ }
1420
+ const label = rawLabel.replace(
1421
+ MESSAGE_CENTER_PREVIEW_LABEL_ESCAPE_PATTERN,
1422
+ "$1"
1423
+ );
1424
+ const mention = parseRichTextMentionHref(href, label);
1425
+ if (!mention) {
1426
+ nodes.push(isRichTextMentionHref(href) ? label : fullMatch);
1427
+ } else {
1428
+ const kind = messageCenterPreviewMentionKind(mention.providerId);
1429
+ const displayLabel = label || mention.label;
1430
+ nodes.push(
1431
+ kind ? /* @__PURE__ */ jsx2(
1432
+ MessageCenterPreviewMentionChip,
1433
+ {
1434
+ kind,
1435
+ label: displayLabel
1436
+ },
1437
+ `mention-${mentionIndex}`
1438
+ ) : displayLabel
1439
+ );
1440
+ mentionIndex += 1;
1441
+ }
1442
+ lastIndex = matchStart + fullMatch.length;
1443
+ }
1444
+ if (lastIndex < text.length) {
1445
+ nodes.push(text.slice(lastIndex));
1446
+ }
1447
+ return nodes;
1448
+ }
1449
+ function messageCenterPreviewMentionKind(providerId) {
1450
+ switch (providerId.trim().toLowerCase()) {
1451
+ case "agent-session":
1452
+ return "session";
1453
+ case "workspace-app":
1454
+ return "workspace-app";
1455
+ case "workspace-issue":
1456
+ return "workspace-issue";
1457
+ default:
1458
+ return null;
1459
+ }
1460
+ }
1461
+ function MessageCenterPreviewMentionChip({
1462
+ kind,
1463
+ label
1464
+ }) {
1465
+ return /* @__PURE__ */ jsxs(
1466
+ "span",
1467
+ {
1468
+ className: "tsh-agent-object-token tsh-agent-object-token--entity",
1469
+ "data-agent-mention-kind": kind,
1470
+ children: [
1471
+ /* @__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(
1472
+ "span",
1473
+ {
1474
+ className: "tsh-agent-object-token__kind-icon",
1475
+ "aria-hidden": "true"
1476
+ }
1477
+ ) }),
1478
+ /* @__PURE__ */ jsx2("span", { className: "tsh-agent-object-token__main", children: label })
1479
+ ]
1480
+ }
1481
+ );
1482
+ }
1370
1483
  function resolveMessageCenterNotificationAction(item, input) {
1371
1484
  if (input.action) {
1372
1485
  return normalizeMessageCenterNotificationAction(input.action);
@@ -2473,6 +2586,90 @@ function MessageCenterOptionWithCount({
2473
2586
  ] });
2474
2587
  }
2475
2588
 
2589
+ // agent-message-center/messageCenterFilterPreferences.ts
2590
+ var messageCenterFiltersStorageKey = "tutti.agent-message-center.filters";
2591
+ var messageCenterGroupByValues = /* @__PURE__ */ new Set([
2592
+ "priority",
2593
+ "status",
2594
+ "agent",
2595
+ "time"
2596
+ ]);
2597
+ var messageCenterStatusFilterValues = /* @__PURE__ */ new Set([
2598
+ "waiting",
2599
+ "working",
2600
+ "completed",
2601
+ "failed"
2602
+ ]);
2603
+ var defaultMessageCenterFilterPreferences = {
2604
+ groupBy: "priority",
2605
+ statusFilters: null,
2606
+ providerFilters: null
2607
+ };
2608
+ function readMessageCenterFilterPreferences() {
2609
+ if (typeof window === "undefined") {
2610
+ return defaultMessageCenterFilterPreferences;
2611
+ }
2612
+ let raw;
2613
+ try {
2614
+ raw = window.localStorage.getItem(messageCenterFiltersStorageKey);
2615
+ } catch {
2616
+ return defaultMessageCenterFilterPreferences;
2617
+ }
2618
+ if (raw === null) {
2619
+ return defaultMessageCenterFilterPreferences;
2620
+ }
2621
+ let parsed;
2622
+ try {
2623
+ parsed = JSON.parse(raw);
2624
+ } catch {
2625
+ return defaultMessageCenterFilterPreferences;
2626
+ }
2627
+ if (typeof parsed !== "object" || parsed === null) {
2628
+ return defaultMessageCenterFilterPreferences;
2629
+ }
2630
+ const record = parsed;
2631
+ return {
2632
+ groupBy: resolveStoredGroupBy(record.groupBy),
2633
+ statusFilters: resolveStoredStatusFilters(record.statusFilters),
2634
+ providerFilters: resolveStoredProviderFilters(record.providerFilters)
2635
+ };
2636
+ }
2637
+ function writeMessageCenterFilterPreferences(preferences) {
2638
+ if (typeof window === "undefined") {
2639
+ return;
2640
+ }
2641
+ const serialized = JSON.stringify({
2642
+ groupBy: preferences.groupBy,
2643
+ statusFilters: preferences.statusFilters ? [...preferences.statusFilters] : null,
2644
+ providerFilters: preferences.providerFilters ? [...preferences.providerFilters] : null
2645
+ });
2646
+ try {
2647
+ window.localStorage.setItem(messageCenterFiltersStorageKey, serialized);
2648
+ } catch {
2649
+ }
2650
+ }
2651
+ function resolveStoredGroupBy(value) {
2652
+ return typeof value === "string" && messageCenterGroupByValues.has(value) ? value : "priority";
2653
+ }
2654
+ function resolveStoredStatusFilters(value) {
2655
+ if (!Array.isArray(value)) {
2656
+ return null;
2657
+ }
2658
+ return new Set(
2659
+ value.filter(
2660
+ (entry) => typeof entry === "string" && messageCenterStatusFilterValues.has(entry)
2661
+ )
2662
+ );
2663
+ }
2664
+ function resolveStoredProviderFilters(value) {
2665
+ if (!Array.isArray(value)) {
2666
+ return null;
2667
+ }
2668
+ return new Set(
2669
+ value.filter((entry) => typeof entry === "string")
2670
+ );
2671
+ }
2672
+
2476
2673
  // agent-message-center/WorkspaceAgentMessageCenterPanel.tsx
2477
2674
  import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
2478
2675
  var MESSAGE_CENTER_TOOLTIP_DELAY_MS = 300;
@@ -2527,11 +2724,23 @@ function WorkspaceAgentMessageCenterPanelContent({
2527
2724
  }) {
2528
2725
  "use memo";
2529
2726
  const { t } = useTranslation();
2530
- const [groupBy, setGroupBy] = useState3("priority");
2531
- const [statusFilters, setStatusFilters] = useState3(null);
2727
+ const [initialFilters] = useState3(readMessageCenterFilterPreferences);
2728
+ const [groupBy, setGroupBy] = useState3(
2729
+ initialFilters.groupBy
2730
+ );
2731
+ const [statusFilters, setStatusFilters] = useState3(
2732
+ initialFilters.statusFilters
2733
+ );
2532
2734
  const [providerFilters, setProviderFilters] = useState3(
2533
- null
2735
+ initialFilters.providerFilters
2534
2736
  );
2737
+ useEffect3(() => {
2738
+ writeMessageCenterFilterPreferences({
2739
+ groupBy,
2740
+ statusFilters,
2741
+ providerFilters
2742
+ });
2743
+ }, [groupBy, statusFilters, providerFilters]);
2535
2744
  const [expandedStackIds, setExpandedStackIds] = useState3(
2536
2745
  () => /* @__PURE__ */ new Set()
2537
2746
  );