@tutti-os/agent-gui 0.0.53 → 0.0.54

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 (79) hide show
  1. package/dist/{AgentMentionSearchController-CExFPobz.d.ts → AgentMentionSearchController-DzhWr0PN.d.ts} +13 -3
  2. package/dist/agent-conversation/index.d.ts +2 -2
  3. package/dist/agent-conversation/index.js +7 -6
  4. package/dist/agent-conversation/index.js.map +1 -1
  5. package/dist/agent-message-center/index.js +15 -12
  6. package/dist/agent-message-center/index.js.map +1 -1
  7. package/dist/{agentGuiNodeTypes-wzOITHRW.d.ts → agentGuiNodeTypes-DCnsaqJr.d.ts} +16 -2
  8. package/dist/app/renderer/agentactivity.css +136 -2
  9. package/dist/{chunk-ZTSS2NU2.js → chunk-2XVECUTU.js} +25 -1
  10. package/dist/chunk-2XVECUTU.js.map +1 -0
  11. package/dist/{chunk-OBFDA7RG.js → chunk-4PSDYKZQ.js} +20 -3
  12. package/dist/chunk-4PSDYKZQ.js.map +1 -0
  13. package/dist/{chunk-BFIYBPFD.js → chunk-6AXH2BOD.js} +5 -5
  14. package/dist/{chunk-4K22O34C.js → chunk-7GM7UQXD.js} +29 -3
  15. package/dist/chunk-7GM7UQXD.js.map +1 -0
  16. package/dist/{chunk-2OLYX32K.js → chunk-7ZDLFTVL.js} +76 -7
  17. package/dist/chunk-7ZDLFTVL.js.map +1 -0
  18. package/dist/{chunk-FYVVHRLZ.js → chunk-BGZ2OSDQ.js} +2 -2
  19. package/dist/{chunk-DPG2J7N5.js → chunk-CMOGPJ23.js} +2 -2
  20. package/dist/{chunk-3ZVVFQH5.js → chunk-EXZH66UE.js} +180 -88
  21. package/dist/chunk-EXZH66UE.js.map +1 -0
  22. package/dist/{chunk-66EQ6EQO.js → chunk-GL54NRMB.js} +59 -2
  23. package/dist/chunk-GL54NRMB.js.map +1 -0
  24. package/dist/{chunk-Y7ZVTWMZ.js → chunk-H2YWXFYX.js} +2 -2
  25. package/dist/{chunk-UKDC63WG.js → chunk-JRA44NYI.js} +78 -4
  26. package/dist/chunk-JRA44NYI.js.map +1 -0
  27. package/dist/{chunk-EFDGMXTB.js → chunk-OQJSZSYB.js} +48 -48
  28. package/dist/chunk-OQJSZSYB.js.map +1 -0
  29. package/dist/{chunk-GWHPTB4L.js → chunk-PBHTLI3E.js} +2 -2
  30. package/dist/{chunk-GWHPTB4L.js.map → chunk-PBHTLI3E.js.map} +1 -1
  31. package/dist/{chunk-5Y3PC7HP.js → chunk-VOXUYDQF.js} +238 -25
  32. package/dist/chunk-VOXUYDQF.js.map +1 -0
  33. package/dist/{chunk-HDBKB5RA.js → chunk-WMQN7SZC.js} +2 -58
  34. package/dist/chunk-WMQN7SZC.js.map +1 -0
  35. package/dist/{chunk-F5DYXCY3.js → chunk-Z2BTIAOC.js} +1 -1
  36. package/dist/chunk-Z2BTIAOC.js.map +1 -0
  37. package/dist/{chunk-PIKG746A.js → chunk-ZFDO72FE.js} +132 -67
  38. package/dist/chunk-ZFDO72FE.js.map +1 -0
  39. package/dist/context-mention-palette/index.d.ts +2 -2
  40. package/dist/context-mention-palette/index.js +8 -8
  41. package/dist/context-mention-provider.d.ts +1 -0
  42. package/dist/i18n/index.d.ts +24 -0
  43. package/dist/i18n/index.js +2 -2
  44. package/dist/index.d.ts +21 -53
  45. package/dist/index.js +832 -607
  46. package/dist/index.js.map +1 -1
  47. package/dist/queued-prompt-runtime.d.ts +2 -2
  48. package/dist/{types-xMz0lJWt.d.ts → types-B2m7UcBb.d.ts} +8 -0
  49. package/dist/workbench/contribution.d.ts +43 -4
  50. package/dist/workbench/contribution.js +9 -5
  51. package/dist/workbench/index.d.ts +3 -3
  52. package/dist/workbench/index.js +18 -8
  53. package/dist/workbench/launch.d.ts +2 -1
  54. package/dist/workbench/launch.js +2 -2
  55. package/dist/workbench/providerCatalog.d.ts +1 -1
  56. package/dist/workbench/sessionTitle.d.ts +1 -1
  57. package/dist/workbench/sessionTitle.js +3 -3
  58. package/dist/workbench/state.d.ts +1 -1
  59. package/dist/workbench/state.js +2 -2
  60. package/dist/workbench/types.d.ts +8 -8
  61. package/dist/workbench/types.js +1 -1
  62. package/dist/workspace-agent-generated-files.js +3 -3
  63. package/package.json +12 -12
  64. package/dist/chunk-2OLYX32K.js.map +0 -1
  65. package/dist/chunk-3ZVVFQH5.js.map +0 -1
  66. package/dist/chunk-4K22O34C.js.map +0 -1
  67. package/dist/chunk-5Y3PC7HP.js.map +0 -1
  68. package/dist/chunk-66EQ6EQO.js.map +0 -1
  69. package/dist/chunk-EFDGMXTB.js.map +0 -1
  70. package/dist/chunk-F5DYXCY3.js.map +0 -1
  71. package/dist/chunk-HDBKB5RA.js.map +0 -1
  72. package/dist/chunk-OBFDA7RG.js.map +0 -1
  73. package/dist/chunk-PIKG746A.js.map +0 -1
  74. package/dist/chunk-UKDC63WG.js.map +0 -1
  75. package/dist/chunk-ZTSS2NU2.js.map +0 -1
  76. /package/dist/{chunk-BFIYBPFD.js.map → chunk-6AXH2BOD.js.map} +0 -0
  77. /package/dist/{chunk-FYVVHRLZ.js.map → chunk-BGZ2OSDQ.js.map} +0 -0
  78. /package/dist/{chunk-DPG2J7N5.js.map → chunk-CMOGPJ23.js.map} +0 -0
  79. /package/dist/{chunk-Y7ZVTWMZ.js.map → chunk-H2YWXFYX.js.map} +0 -0
package/dist/index.js CHANGED
@@ -18,11 +18,11 @@ import {
18
18
  localAgentGUIProviderTargetId,
19
19
  normalizeAgentGUIProviderTargets,
20
20
  resolveAgentGUIProviderTarget
21
- } from "./chunk-4K22O34C.js";
21
+ } from "./chunk-7GM7UQXD.js";
22
22
  import {
23
23
  AgentInteractivePromptSurface,
24
24
  approvalOptionDisplayLabel
25
- } from "./chunk-BFIYBPFD.js";
25
+ } from "./chunk-6AXH2BOD.js";
26
26
  import {
27
27
  PLAN_IMPLEMENTATION_ACTION_FEEDBACK,
28
28
  PLAN_IMPLEMENTATION_ACTION_IMPLEMENT,
@@ -41,7 +41,7 @@ import {
41
41
  resolveAgentGUIExplicitConversationTitle,
42
42
  resolveAgentGUIProviderDisplayLabel,
43
43
  resolveAgentGUIProviderIdentity
44
- } from "./chunk-DPG2J7N5.js";
44
+ } from "./chunk-CMOGPJ23.js";
45
45
  import {
46
46
  AgentConversationFlow,
47
47
  Button,
@@ -63,13 +63,14 @@ import {
63
63
  skillTriggerForPrefix,
64
64
  toLocalShortDateTime,
65
65
  useProjectedAgentConversation
66
- } from "./chunk-3ZVVFQH5.js";
66
+ } from "./chunk-EXZH66UE.js";
67
67
  import {
68
68
  AgentMessageMarkdown,
69
+ AgentTargetPresentationProvider,
69
70
  ZoomableImage,
70
71
  cn,
71
72
  resolveWorkspaceLinkAction
72
- } from "./chunk-PIKG746A.js";
73
+ } from "./chunk-ZFDO72FE.js";
73
74
  import {
74
75
  AGENT_MENTION_FILTER_TAB_ORDER,
75
76
  AgentFileMentionPalette,
@@ -77,7 +78,7 @@ import {
77
78
  DEFAULT_AGENT_MENTION_FILTER,
78
79
  agentMentionItemKey,
79
80
  preloadAgentMentionBrowse
80
- } from "./chunk-2OLYX32K.js";
81
+ } from "./chunk-7ZDLFTVL.js";
81
82
  import {
82
83
  WORKSPACE_AGENT_ACTIVITY_RUNTIME_SESSION_ORIGIN,
83
84
  buildWorkspaceAgentActivityListViewModel,
@@ -87,17 +88,13 @@ import {
87
88
  isWorkspaceAgentUntitledTask,
88
89
  mergeWorkspaceAgentActivityDurableAndOverlayMessages,
89
90
  selectWorkspaceAgentActivityOverlayMessages
90
- } from "./chunk-GWHPTB4L.js";
91
+ } from "./chunk-PBHTLI3E.js";
91
92
  import {
92
- MANAGED_AGENT_ICON_FALLBACK_URL,
93
- MANAGED_AGENT_ICON_URLS,
94
- Spinner,
95
- normalizeManagedAgentProvider
96
- } from "./chunk-HDBKB5RA.js";
93
+ Spinner
94
+ } from "./chunk-WMQN7SZC.js";
97
95
  import {
98
96
  resolveWorkspaceAgentSessionSortTimeUnixMs
99
97
  } from "./chunk-IBIMGLCD.js";
100
- import "./chunk-MTFSQWZ6.js";
101
98
  import {
102
99
  AGENT_RICH_TEXT_CARET_ANCHOR,
103
100
  exitAgentFileMentionSuggestion,
@@ -105,15 +102,18 @@ import {
105
102
  mentionItemToAttrs,
106
103
  normalizeAgentSessionMentionTitle,
107
104
  parseMentionItemFromHref
108
- } from "./chunk-UKDC63WG.js";
105
+ } from "./chunk-JRA44NYI.js";
109
106
  import "./chunk-Y35GDLP2.js";
110
107
  import "./chunk-LUGELG5V.js";
111
108
  import {
112
109
  AgentActivityHostProvider,
113
110
  AgentActivityRuntimeProvider,
111
+ MANAGED_AGENT_ICON_FALLBACK_URL,
112
+ MANAGED_AGENT_ICON_URLS,
114
113
  getAgentActivityRuntime,
115
114
  getOptionalAgentActivityRuntime,
116
115
  getOptionalAgentHostApi,
116
+ normalizeManagedAgentProvider,
117
117
  resetAgentActivityRuntimeForTests,
118
118
  setAgentActivityRuntimeForTests,
119
119
  useAgentActivityRuntime,
@@ -121,9 +121,10 @@ import {
121
121
  useAgentHostApi,
122
122
  useOptionalAgentActivityRuntime,
123
123
  useOptionalAgentHostApi
124
- } from "./chunk-66EQ6EQO.js";
124
+ } from "./chunk-GL54NRMB.js";
125
125
  import "./chunk-TYGL25EL.js";
126
126
  import "./chunk-PJP5BUU6.js";
127
+ import "./chunk-MTFSQWZ6.js";
127
128
  import {
128
129
  AGENT_CONTEXT_MENTION_PROVIDER_IDS
129
130
  } from "./chunk-JM24HADP.js";
@@ -137,8 +138,8 @@ import {
137
138
  agentGuiI18nResources,
138
139
  translate,
139
140
  useTranslation
140
- } from "./chunk-Y7ZVTWMZ.js";
141
- import "./chunk-ZTSS2NU2.js";
141
+ } from "./chunk-H2YWXFYX.js";
142
+ import "./chunk-2XVECUTU.js";
142
143
 
143
144
  // shared/agentActivitySnapshotProjection.ts
144
145
  import {
@@ -2338,6 +2339,35 @@ var DEFAULT_AGENT_SETTINGS = {
2338
2339
  hideWorktreeMismatchDropWarning: false
2339
2340
  };
2340
2341
 
2342
+ // agent-gui/agentGuiNode/model/agentGuiConversationFilter.ts
2343
+ function createAgentGUIConversationFilterState(filter = { kind: "all" }) {
2344
+ return {
2345
+ filter: normalizeAgentGUIConversationFilter(filter)
2346
+ };
2347
+ }
2348
+ function normalizeAgentGUIConversationFilter(filter) {
2349
+ if (filter?.kind === "agentTarget") {
2350
+ const agentTargetId = filter.agentTargetId?.trim() ?? "";
2351
+ return agentTargetId ? { kind: "agentTarget", agentTargetId } : { kind: "all" };
2352
+ }
2353
+ return { kind: "all" };
2354
+ }
2355
+ function filterAgentGUIConversationSummaries(conversations, filter) {
2356
+ const normalizedFilter = normalizeAgentGUIConversationFilter(filter);
2357
+ return conversations.filter(
2358
+ (conversation) => matchesAgentGUIConversationFilterAgentTarget(
2359
+ conversation.agentTargetId,
2360
+ normalizedFilter
2361
+ )
2362
+ );
2363
+ }
2364
+ function matchesAgentGUIConversationFilterAgentTarget(agentTargetId, filter) {
2365
+ if (filter.kind === "all") {
2366
+ return true;
2367
+ }
2368
+ return (agentTargetId?.trim() ?? "") === filter.agentTargetId;
2369
+ }
2370
+
2341
2371
  // agent-gui/agentGuiNode/model/agentGuiConversationProjectResolver.ts
2342
2372
  import { resolveWorkspaceUserProjectDisplayLabel } from "@tutti-os/workspace-user-project/core";
2343
2373
  var AGENT_GUI_CONVERSATION_PROJECT_SUMMARY_CACHE_LIMIT = 512;
@@ -2470,6 +2500,7 @@ function resolveAgentGUIConversationSortTimeUnixMs(conversation) {
2470
2500
  return conversation.sortTimeUnixMs ?? conversation.updatedAtUnixMs;
2471
2501
  }
2472
2502
  function buildAgentGUIConversationSummaries({
2503
+ conversationFilter,
2473
2504
  isNoProjectPath,
2474
2505
  snapshot: snapshot3,
2475
2506
  provider,
@@ -2484,15 +2515,25 @@ function buildAgentGUIConversationSummaries({
2484
2515
  userProjects,
2485
2516
  { isNoProjectPath }
2486
2517
  );
2487
- return buildWorkspaceAgentActivityListViewModel(runtimeSnapshot, {
2488
- sessionMessagesById
2489
- }).activities.map(
2518
+ const conversations = buildWorkspaceAgentActivityListViewModel(
2519
+ runtimeSnapshot,
2520
+ {
2521
+ sessionMessagesById
2522
+ }
2523
+ ).activities.map(
2490
2524
  (activity) => conversationSummaryFromActivity(
2491
2525
  activity,
2492
2526
  sessionsById.get(activity.sessionId),
2493
2527
  { projectResolver }
2494
2528
  )
2495
- ).filter(
2529
+ );
2530
+ if (conversationFilter) {
2531
+ return filterAgentGUIConversationSummaries(
2532
+ conversations,
2533
+ normalizeAgentGUIConversationFilter(conversationFilter)
2534
+ );
2535
+ }
2536
+ return conversations.filter(
2496
2537
  (conversation) => conversation.provider === provider || conversation.provider === "unknown"
2497
2538
  );
2498
2539
  }
@@ -2588,6 +2629,7 @@ function conversationSummaryFromAgentSession(session, options = {}) {
2588
2629
  return {
2589
2630
  id: session.agentSessionId.trim(),
2590
2631
  userId: "",
2632
+ agentTargetId: session.agentTargetId ?? null,
2591
2633
  provider,
2592
2634
  resumable: session.resumable,
2593
2635
  title,
@@ -2684,6 +2726,7 @@ function conversationSummaryFromActivity(activity, session, options) {
2684
2726
  return {
2685
2727
  id: activity.sessionId,
2686
2728
  userId: session?.userId?.trim() ?? "",
2729
+ agentTargetId: session?.agentTargetId ?? null,
2687
2730
  provider,
2688
2731
  resumable: session?.resumable,
2689
2732
  title,
@@ -2768,6 +2811,7 @@ function timelineSessionFromItems(timelineItems, conversation) {
2768
2811
  cwd: conversation?.cwd?.trim() ?? "",
2769
2812
  lifecycleStatus: sessionLifecycleStatus(conversation?.status ?? "ready"),
2770
2813
  turnPhase: conversation?.status === "working" ? "working" : "idle",
2814
+ turnLifecycle: conversation?.turnLifecycle ?? null,
2771
2815
  effectiveStatus: conversation?.status ?? "ready",
2772
2816
  status: conversation?.status ?? "ready",
2773
2817
  title: conversation?.title,
@@ -3377,6 +3421,7 @@ function projectWorkspaceAgentMessagesToTimelineItems(messages) {
3377
3421
  ...message.status?.trim() ? { status: message.status.trim() } : {}
3378
3422
  });
3379
3423
  mergedToolPayloadByKey.set(toolKey, mergedPayload);
3424
+ const callType = firstNonEmptyString(stringValue(mergedPayload.callType)) || "tool";
3380
3425
  const workspaceId = workspaceIdFromMessage(message);
3381
3426
  return {
3382
3427
  id,
@@ -3389,7 +3434,7 @@ function projectWorkspaceAgentMessagesToTimelineItems(messages) {
3389
3434
  actorId: message.agentSessionId,
3390
3435
  itemType: toolCallItemType(message.status ?? void 0),
3391
3436
  role: "assistant",
3392
- callType: "tool",
3437
+ callType,
3393
3438
  callId,
3394
3439
  name: firstNonEmptyString(toolName, titleToolName) || "Tool",
3395
3440
  ...message.status !== void 0 ? { status: message.status } : {},
@@ -4830,20 +4875,43 @@ function normalizeQuery(input) {
4830
4875
  return null;
4831
4876
  }
4832
4877
  return {
4878
+ conversationFilter: normalizeAgentGUIConversationListFilter(input),
4833
4879
  workspaceId,
4834
4880
  userId,
4835
4881
  provider,
4836
4882
  sessionOrigin
4837
4883
  };
4838
4884
  }
4885
+ function normalizeAgentGUIConversationListFilter(input) {
4886
+ if (input.conversationFilter) {
4887
+ return normalizeAgentGUIConversationFilter(input.conversationFilter);
4888
+ }
4889
+ return null;
4890
+ }
4891
+ function conversationFilterKey(filter, provider) {
4892
+ if (!filter) {
4893
+ return `legacy-provider:${provider}`;
4894
+ }
4895
+ const normalized = normalizeAgentGUIConversationFilter(filter);
4896
+ if (normalized.kind === "all") {
4897
+ return "all";
4898
+ }
4899
+ return `agent-target:${normalized.agentTargetId}`;
4900
+ }
4839
4901
  function createAgentGUIConversationListQueryKey(input) {
4840
4902
  const normalized = normalizeQuery(input);
4841
- return normalized ? [
4903
+ if (!normalized) {
4904
+ return null;
4905
+ }
4906
+ const providerScope = normalized.conversationFilter ? "conversation-filter" : normalized.provider;
4907
+ const queryKey = [
4842
4908
  normalized.workspaceId,
4843
4909
  normalized.userId,
4844
- normalized.provider,
4910
+ providerScope,
4911
+ conversationFilterKey(normalized.conversationFilter, normalized.provider),
4845
4912
  normalized.sessionOrigin
4846
- ].join("::") : null;
4913
+ ].join("::");
4914
+ return queryKey;
4847
4915
  }
4848
4916
  function createEmptyQueryState(query) {
4849
4917
  const normalized = normalizeQuery(query);
@@ -5531,6 +5599,9 @@ function getWorkspaceAgentSnapshotForConversations(input) {
5531
5599
  const snapshot3 = getAgentActivityRuntime().getSnapshot(input.workspaceId);
5532
5600
  return workspaceAgentSnapshotForConversations(snapshot3);
5533
5601
  }
5602
+ function shouldUseCurrentWorkspaceAgentSnapshotForRefresh(reason) {
5603
+ return reason === "workspace-agent-update" || reason === "session-overlay-update";
5604
+ }
5534
5605
  async function refreshAgentGUIConversationListQuery(query, reason, options = {}) {
5535
5606
  const state = ensureQueryState(query);
5536
5607
  if (!state) {
@@ -5558,7 +5629,9 @@ async function refreshAgentGUIConversationListQuery(query, reason, options = {})
5558
5629
  sessionOrigin: state.query.sessionOrigin,
5559
5630
  userId: state.query.userId
5560
5631
  };
5561
- const workspaceAgentSnapshot = reason === "workspace-agent-update" || reason === "session-overlay-update" ? getWorkspaceAgentSnapshotForConversations(workspaceAgentsInput) : await loadWorkspaceAgentSnapshotForConversations(
5632
+ const currentWorkspaceAgentSnapshot = getWorkspaceAgentSnapshotForConversations(workspaceAgentsInput);
5633
+ const canProjectExplicitFilterFromCurrentSnapshot = reason === "projection-sync" && state.query.conversationFilter !== null && currentWorkspaceAgentSnapshot.sessions.length > 0;
5634
+ const workspaceAgentSnapshot = shouldUseCurrentWorkspaceAgentSnapshotForRefresh(reason) || canProjectExplicitFilterFromCurrentSnapshot ? currentWorkspaceAgentSnapshot : await loadWorkspaceAgentSnapshotForConversations(
5562
5635
  workspaceAgentsInput
5563
5636
  );
5564
5637
  if (requestId !== requestIdByQueryKey.get(queryKey)) {
@@ -5613,6 +5686,7 @@ async function refreshAgentGUIConversationListQuery(query, reason, options = {})
5613
5686
  return agentSessionId && dirtySessionIds.has(agentSessionId) || syncSessionId && dirtySessionIds.has(syncSessionId);
5614
5687
  }) : workspaceAgentSnapshot.sessions;
5615
5688
  const baseConversations = buildAgentGUIConversationSummaries({
5689
+ ...state.query.conversationFilter ? { conversationFilter: state.query.conversationFilter } : {},
5616
5690
  snapshot: canApplyDirtySessionProjection ? {
5617
5691
  ...workspaceAgentSnapshot,
5618
5692
  sessions: projectionSessions
@@ -6171,6 +6245,7 @@ function useAgentGUIActivation({
6171
6245
  mode: input.mode,
6172
6246
  workspaceId,
6173
6247
  agentSessionId,
6248
+ agentTargetId: input.agentTargetId,
6174
6249
  provider: input.provider,
6175
6250
  cwd: input.cwd,
6176
6251
  initialContent: input.initialContent,
@@ -6481,7 +6556,8 @@ function buildNodeDefaultComposerSettings(data, options) {
6481
6556
  };
6482
6557
  }
6483
6558
  function nodeComposerOverridesForProvider(data) {
6484
- return data.composerOverridesByProvider?.[data.provider] ?? data.composerOverrides ?? null;
6559
+ const agentTargetId = normalizeOptionalText(data.agentTargetId);
6560
+ return (agentTargetId ? data.composerOverridesByAgentTargetId?.[agentTargetId] : null) ?? data.composerOverridesByProvider?.[data.provider] ?? data.composerOverrides ?? null;
6485
6561
  }
6486
6562
  function composerSupportForProvider(provider) {
6487
6563
  if (provider === "claude-code" || provider === "codex" || provider === "gemini") {
@@ -6513,6 +6589,16 @@ function nodeDataFromComposerSettings(current, settings) {
6513
6589
  computerUse: settings.computerUse,
6514
6590
  permissionModeId: normalizePermissionModeId(settings.permissionModeId)
6515
6591
  };
6592
+ const agentTargetId = normalizeOptionalText(current.agentTargetId);
6593
+ if (agentTargetId) {
6594
+ return {
6595
+ ...current,
6596
+ composerOverridesByAgentTargetId: {
6597
+ ...current.composerOverridesByAgentTargetId ?? {},
6598
+ [agentTargetId]: composerOverrides
6599
+ }
6600
+ };
6601
+ }
6516
6602
  return {
6517
6603
  ...current,
6518
6604
  composerOverrides,
@@ -7734,6 +7820,41 @@ function normalizeAgentGUIOpenSessionRequest(request) {
7734
7820
  function recordValue2(value) {
7735
7821
  return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
7736
7822
  }
7823
+ function numberValue(value) {
7824
+ if (typeof value === "number" && Number.isFinite(value)) {
7825
+ return value;
7826
+ }
7827
+ if (typeof value === "string" && value.trim() !== "") {
7828
+ const parsed = Number(value);
7829
+ return Number.isFinite(parsed) ? parsed : null;
7830
+ }
7831
+ return null;
7832
+ }
7833
+ function activeBackgroundAgentCount(runtimeContext) {
7834
+ const backgroundAgents = recordValue2(runtimeContext?.backgroundAgents);
7835
+ if (!backgroundAgents) {
7836
+ return 0;
7837
+ }
7838
+ const items = Array.isArray(backgroundAgents.items) ? backgroundAgents.items : [];
7839
+ if (items.length === 0) {
7840
+ const count = numberValue(backgroundAgents.count);
7841
+ return count === null ? 0 : Math.max(0, Math.floor(count));
7842
+ }
7843
+ return items.filter((item) => {
7844
+ const record = recordValue2(item);
7845
+ if (!record) {
7846
+ return false;
7847
+ }
7848
+ const status = String(record.status ?? "").trim().toLowerCase();
7849
+ return ![
7850
+ "completed",
7851
+ "failed",
7852
+ "cancelled",
7853
+ "canceled",
7854
+ "stopped"
7855
+ ].includes(status);
7856
+ }).length;
7857
+ }
7737
7858
  function appServerStartupMetadata(runtimeContext) {
7738
7859
  return recordValue2(runtimeContext?.appServerStartup);
7739
7860
  }
@@ -8152,21 +8273,25 @@ function areAgentComposerDraftsEqual(left, right) {
8152
8273
  return file.id === other.id && file.name === other.name && file.mimeType === other.mimeType && file.path === other.path && file.hostPath === other.hostPath && file.assetId === other.assetId && file.sizeBytes === other.sizeBytes && file.uploading === other.uploading && file.uploadError === other.uploadError;
8153
8274
  });
8154
8275
  }
8155
- function nodeDefaultDraftKey(agentProvider) {
8276
+ function nodeDefaultDraftKey(agentProvider, agentTargetId) {
8277
+ const normalizedAgentTargetId = normalizeOptionalText2(agentTargetId);
8278
+ if (normalizedAgentTargetId) {
8279
+ return `${NODE_DEFAULT_DRAFT_KEY}:target:${normalizedAgentTargetId}`;
8280
+ }
8156
8281
  return `${NODE_DEFAULT_DRAFT_KEY}:${agentProvider}`;
8157
8282
  }
8158
- function nodeDefaultDraftContentKey(agentProvider) {
8159
- return nodeDefaultDraftKey(agentProvider);
8283
+ function nodeDefaultDraftContentKey(agentProvider, agentTargetId) {
8284
+ return nodeDefaultDraftKey(agentProvider, agentTargetId);
8160
8285
  }
8161
8286
  function normalizeProjectDraftPath(value) {
8162
8287
  const normalized = value?.trim().replaceAll("\\", "/").replace(/\/+$/, "");
8163
8288
  return normalized ? normalized : null;
8164
8289
  }
8165
8290
  function readNodeDefaultDraftContent(input) {
8166
- return input.drafts[nodeDefaultDraftContentKey(input.data.provider)] ?? input.drafts[NODE_DEFAULT_DRAFT_KEY] ?? EMPTY_AGENT_COMPOSER_DRAFT;
8291
+ return input.drafts[nodeDefaultDraftContentKey(input.data.provider, input.data.agentTargetId)] ?? input.drafts[nodeDefaultDraftContentKey(input.data.provider)] ?? input.drafts[NODE_DEFAULT_DRAFT_KEY] ?? EMPTY_AGENT_COMPOSER_DRAFT;
8167
8292
  }
8168
8293
  function readNodeDefaultDraftSettings(input) {
8169
- return input.drafts[nodeDefaultDraftKey(input.data.provider)] ?? input.drafts[NODE_DEFAULT_DRAFT_KEY] ?? buildNodeDefaultComposerSettings(input.data, {
8294
+ return input.drafts[nodeDefaultDraftKey(input.data.provider, input.data.agentTargetId)] ?? input.drafts[nodeDefaultDraftKey(input.data.provider)] ?? input.drafts[NODE_DEFAULT_DRAFT_KEY] ?? buildNodeDefaultComposerSettings(input.data, {
8170
8295
  defaultReasoningEffort: input.defaultReasoningEffort
8171
8296
  });
8172
8297
  }
@@ -8249,7 +8374,7 @@ function isCompletedOutcomeToken(value) {
8249
8374
  return value?.trim().toLowerCase() === "completed";
8250
8375
  }
8251
8376
  function hasSessionControlStatePatch(patch) {
8252
- return normalizeOptionalText2(patch.permissionModeId) !== null || patch.settings !== void 0 || patch.runtimeContext !== void 0 || patch.submitAvailability !== void 0 || patch.turn?.submitAvailability !== void 0 || patch.turn?.phase !== void 0;
8377
+ return normalizeOptionalText2(patch.permissionModeId) !== null || patch.settings !== void 0 || patch.runtimeContext !== void 0 || patch.submitAvailability !== void 0 || patch.pendingInteractive !== void 0 || patch.turn?.submitAvailability !== void 0 || patch.turn?.phase !== void 0;
8253
8378
  }
8254
8379
  function mergeSessionControlStatePatch(current, patch) {
8255
8380
  if (!current || !hasSessionControlStatePatch(patch)) {
@@ -8313,6 +8438,10 @@ function mergeSessionControlStatePatch(current, patch) {
8313
8438
  next.submitAvailability = submitAvailability;
8314
8439
  changed = true;
8315
8440
  }
8441
+ if (patch.pendingInteractive !== void 0 && !sameJSONValue(current.pendingInteractive ?? null, patch.pendingInteractive)) {
8442
+ next.pendingInteractive = patch.pendingInteractive;
8443
+ changed = true;
8444
+ }
8316
8445
  if (patch.turn?.phase) {
8317
8446
  next.turnLifecycle = {
8318
8447
  activeTurnId: patch.turn.activeTurnId !== void 0 ? patch.turn.activeTurnId : patch.turn.phase === "settled" ? null : patch.turn.turnId,
@@ -8329,6 +8458,9 @@ function mergeSessionControlStatePatch(current, patch) {
8329
8458
  }
8330
8459
  return changed ? next : current;
8331
8460
  }
8461
+ function sameJSONValue(left, right) {
8462
+ return JSON.stringify(left ?? null) === JSON.stringify(right ?? null);
8463
+ }
8332
8464
  function conversationStatusFromSessionState(state) {
8333
8465
  if (state.turnLifecycle?.phase) {
8334
8466
  return conversationStatusFromStatePatch({
@@ -8438,7 +8570,9 @@ function useAgentGUINodeController({
8438
8570
  workspacePath,
8439
8571
  avoidGroupingEdits,
8440
8572
  data,
8573
+ conversationScope = "single-provider",
8441
8574
  providerTargets,
8575
+ providerTargetsLoading = false,
8442
8576
  defaultProviderTargetId = null,
8443
8577
  openSessionRequest = null,
8444
8578
  prefillPromptRequest = null,
@@ -8458,23 +8592,37 @@ function useAgentGUINodeController({
8458
8592
  [providerTargets]
8459
8593
  );
8460
8594
  const normalizedProviderTargets = useMemo4(
8461
- () => normalizedExplicitProviderTargets.length > 0 ? normalizedExplicitProviderTargets : normalizeAgentGUIProviderTargets(null),
8462
- [normalizedExplicitProviderTargets]
8595
+ () => providerTargetsLoading ? [] : providerTargets === void 0 ? normalizeAgentGUIProviderTargets(null) : normalizedExplicitProviderTargets,
8596
+ [normalizedExplicitProviderTargets, providerTargets, providerTargetsLoading]
8463
8597
  );
8464
- const selectedProviderTarget = useMemo4(
8465
- () => resolveAgentGUIProviderTarget({
8598
+ const shouldFallbackToLocalProviderTargets = providerTargets === void 0 && !providerTargetsLoading;
8599
+ const selectedProviderTarget = useMemo4(() => {
8600
+ const resolved = resolveAgentGUIProviderTarget({
8601
+ agentTargetId: data.agentTargetId,
8466
8602
  defaultProviderTargetId,
8603
+ fallbackToLocal: shouldFallbackToLocalProviderTargets,
8467
8604
  provider: data.provider,
8468
8605
  providerTargetId: data.providerTargetId,
8469
8606
  providerTargets: normalizedProviderTargets
8470
- }),
8471
- [
8472
- data.provider,
8473
- data.providerTargetId,
8474
- defaultProviderTargetId,
8475
- normalizedProviderTargets
8476
- ]
8477
- );
8607
+ });
8608
+ return resolved ?? {
8609
+ targetId: data.agentTargetId ?? "__loading__",
8610
+ provider: data.provider,
8611
+ ref: {
8612
+ kind: "loading",
8613
+ provider: data.provider
8614
+ },
8615
+ label: data.provider,
8616
+ disabled: true
8617
+ };
8618
+ }, [
8619
+ data.agentTargetId,
8620
+ data.provider,
8621
+ data.providerTargetId,
8622
+ defaultProviderTargetId,
8623
+ normalizedProviderTargets,
8624
+ shouldFallbackToLocalProviderTargets
8625
+ ]);
8478
8626
  const selectedProviderTargetIsExplicit = useMemo4(
8479
8627
  () => normalizedExplicitProviderTargets.some(
8480
8628
  (target) => target.provider === selectedProviderTarget.provider && target.targetId === selectedProviderTarget.targetId && agentGUIProviderTargetRefsEqual(
@@ -8495,6 +8643,17 @@ function useAgentGUINodeController({
8495
8643
  return stable;
8496
8644
  }, [agentActivitySnapshot]);
8497
8645
  const generatedControllerOwnerKey = useId();
8646
+ const [conversationFilter, setConversationFilter] = useState4(
8647
+ () => createAgentGUIConversationFilterState().filter
8648
+ );
8649
+ const canUseConversationTargetFilter = conversationScope === "multi-provider";
8650
+ const queryConversationFilter = canUseConversationTargetFilter ? conversationFilter : null;
8651
+ useEffect4(() => {
8652
+ if (canUseConversationTargetFilter || conversationFilter.kind === "all") {
8653
+ return;
8654
+ }
8655
+ setConversationFilter({ kind: "all" });
8656
+ }, [canUseConversationTargetFilter, conversationFilter]);
8498
8657
  const conversationListQuery = useMemo4(() => {
8499
8658
  const userId = currentUserId?.trim() ?? "";
8500
8659
  const provider = data.provider?.trim() ?? "";
@@ -8502,12 +8661,13 @@ function useAgentGUINodeController({
8502
8661
  return null;
8503
8662
  }
8504
8663
  return {
8664
+ ...queryConversationFilter ? { conversationFilter: queryConversationFilter } : {},
8505
8665
  workspaceId,
8506
8666
  userId,
8507
8667
  provider: data.provider,
8508
8668
  sessionOrigin: AGENT_GUI_RUNTIME_SESSION_ORIGIN
8509
8669
  };
8510
- }, [currentUserId, data.provider, workspaceId]);
8670
+ }, [currentUserId, data.provider, queryConversationFilter, workspaceId]);
8511
8671
  const conversationListState = useAgentGuiConversationList(
8512
8672
  conversationListQuery
8513
8673
  );
@@ -8601,7 +8761,7 @@ function useAgentGUINodeController({
8601
8761
  sessionViewRef(activeConversationId)
8602
8762
  );
8603
8763
  const activeSessionState = activeSessionView?.controlState ?? null;
8604
- const providerComposerOptions = agentActivitySnapshot.composerOptionsByProvider?.[data.provider] ?? null;
8764
+ const providerComposerOptions = (data.agentTargetId ? agentActivitySnapshot.composerOptionsByAgentTargetId?.[data.agentTargetId] : null) ?? agentActivitySnapshot.composerOptionsByProvider?.[data.provider] ?? null;
8605
8765
  const resolvedPromptImagesSupported = resolveAgentActivityCapability2(
8606
8766
  "imageInput",
8607
8767
  {
@@ -8615,6 +8775,10 @@ function useAgentGUINodeController({
8615
8775
  sessionRuntimeContext: activeSessionState?.runtimeContext
8616
8776
  });
8617
8777
  const activeSessionRuntimeContext = activeSessionState?.runtimeContext;
8778
+ const backgroundAgentCount = useMemo4(
8779
+ () => activeBackgroundAgentCount(activeSessionRuntimeContext),
8780
+ [activeSessionRuntimeContext]
8781
+ );
8618
8782
  const composerSupport = useMemo4(
8619
8783
  () => composerSettingsSupportFromOptions(
8620
8784
  providerComposerOptions,
@@ -9173,7 +9337,17 @@ function useAgentGUINodeController({
9173
9337
  const previousQuery = previousSnapshot.query;
9174
9338
  const previousQueryKey = previousQuery ? createAgentGUIConversationListQueryKey(previousQuery) : null;
9175
9339
  const nextQueryKey = conversationListQuery ? createAgentGUIConversationListQueryKey(conversationListQuery) : null;
9176
- if (previousQuery && conversationListQuery && previousQueryKey !== nextQueryKey && previousQuery.workspaceId === conversationListQuery.workspaceId && previousQuery.provider === conversationListQuery.provider && previousQuery.sessionOrigin === conversationListQuery.sessionOrigin && previousSnapshot.conversations.length > 0) {
9340
+ const previousHasExplicitFilter = previousQuery?.conversationFilter != null;
9341
+ const nextHasExplicitFilter = conversationListQuery?.conversationFilter != null;
9342
+ const previousFilterKey = previousQuery ? JSON.stringify(
9343
+ normalizeAgentGUIConversationFilter(previousQuery.conversationFilter)
9344
+ ) : "";
9345
+ const nextFilterKey = conversationListQuery ? JSON.stringify(
9346
+ normalizeAgentGUIConversationFilter(
9347
+ conversationListQuery.conversationFilter
9348
+ )
9349
+ ) : "";
9350
+ if (previousQuery && conversationListQuery && previousQueryKey !== nextQueryKey && previousQuery.workspaceId === conversationListQuery.workspaceId && previousQuery.provider === conversationListQuery.provider && previousHasExplicitFilter === nextHasExplicitFilter && previousFilterKey === nextFilterKey && previousQuery.sessionOrigin === conversationListQuery.sessionOrigin && previousSnapshot.conversations.length > 0) {
9177
9351
  ensureAgentGUIConversationListQuery(conversationListQuery);
9178
9352
  seedAgentGUIConversationListConversationsIfEmpty({
9179
9353
  query: conversationListQuery,
@@ -10340,6 +10514,7 @@ function useAgentGUINodeController({
10340
10514
  const loadDraftComposerOptions = useCallback4(
10341
10515
  (options) => {
10342
10516
  const provider = dataRef.current.provider;
10517
+ const agentTargetId = dataRef.current.agentTargetId ?? null;
10343
10518
  if (isCreatingConversationRef.current) {
10344
10519
  return;
10345
10520
  }
@@ -10355,6 +10530,7 @@ function useAgentGUINodeController({
10355
10530
  cwd: composerOptionsCwd,
10356
10531
  force: options?.force,
10357
10532
  provider,
10533
+ agentTargetId,
10358
10534
  settings
10359
10535
  })
10360
10536
  ).catch(() => void 0);
@@ -10368,7 +10544,7 @@ function useAgentGUINodeController({
10368
10544
  if (!supports.model && !supports.reasoning && !supports.permission) {
10369
10545
  return;
10370
10546
  }
10371
- const projectKey = `${data.provider}\0${selectedProjectPath ?? ""}`;
10547
+ const projectKey = `${data.agentTargetId ?? data.provider}\0${selectedProjectPath ?? ""}`;
10372
10548
  const previousProjectKey = composerOptionsProjectKeyRef.current;
10373
10549
  composerOptionsProjectKeyRef.current = projectKey;
10374
10550
  if (previousProjectKey === null || previousProjectKey === projectKey) {
@@ -10376,6 +10552,7 @@ function useAgentGUINodeController({
10376
10552
  }
10377
10553
  loadDraftComposerOptions({ force: true });
10378
10554
  }, [
10555
+ data.agentTargetId,
10379
10556
  data.provider,
10380
10557
  loadDraftComposerOptions,
10381
10558
  previewMode,
@@ -10435,6 +10612,7 @@ function useAgentGUINodeController({
10435
10612
  );
10436
10613
  }, [
10437
10614
  activeConversationId,
10615
+ data.agentTargetId,
10438
10616
  data.provider,
10439
10617
  isComposerHome,
10440
10618
  loadDraftComposerOptions,
@@ -11031,6 +11209,11 @@ function useAgentGUINodeController({
11031
11209
  if (isCreatingConversation || target.disabled === true || data.provider === "openclaw" && openclawGateway?.status !== "ready") {
11032
11210
  return;
11033
11211
  }
11212
+ const agentTargetId = target.agentTargetId?.trim() ?? "";
11213
+ if (!agentTargetId && selectedProviderTargetIsExplicitRef.current) {
11214
+ setDetailError(translate("agentHost.agentGui.agentTargetRequired"));
11215
+ return;
11216
+ }
11034
11217
  const normalizedInitialContent = Array.isArray(initialContentInput) ? normalizeAgentPromptContentBlocks(
11035
11218
  initialContentInput
11036
11219
  ) : textPromptContent(normalizeOptionalPrompt(initialContentInput));
@@ -11047,14 +11230,16 @@ function useAgentGUINodeController({
11047
11230
  void (async () => {
11048
11231
  const target2 = selectedProviderTargetRef.current;
11049
11232
  const provider = target2.provider;
11050
- const shouldUseProviderTargetRef = selectedProviderTargetIsExplicitRef.current;
11233
+ const agentTargetId2 = target2.agentTargetId?.trim() ?? "";
11234
+ const shouldUseProviderTargetRef = !agentTargetId2 && selectedProviderTargetIsExplicitRef.current;
11051
11235
  onDataChangeRef.current(
11052
- (current) => current.provider === provider && (current.providerTargetId ?? null) === (shouldUseProviderTargetRef ? target2.targetId : null) && agentGUIProviderTargetRefsEqual(
11236
+ (current) => current.provider === provider && (current.agentTargetId ?? null) === (agentTargetId2 || null) && (current.providerTargetId ?? null) === (shouldUseProviderTargetRef ? target2.targetId : null) && agentGUIProviderTargetRefsEqual(
11053
11237
  current.providerTargetRef,
11054
11238
  shouldUseProviderTargetRef ? target2.ref : null
11055
11239
  ) ? current : {
11056
11240
  ...current,
11057
11241
  provider,
11242
+ agentTargetId: agentTargetId2 || null,
11058
11243
  providerTargetId: shouldUseProviderTargetRef ? target2.targetId : null,
11059
11244
  providerTargetRef: shouldUseProviderTargetRef ? target2.ref : null
11060
11245
  }
@@ -11086,7 +11271,7 @@ function useAgentGUINodeController({
11086
11271
  lastActiveModelByProviderRef.current[provider]
11087
11272
  ) : null;
11088
11273
  const effectiveInitialSettings = inheritedModel === null ? initialSettings : { ...initialSettings, model: inheritedModel };
11089
- const snapshotComposerOptions = agentActivityRuntime.getSnapshot(workspaceId).composerOptionsByProvider?.[provider] ?? null;
11274
+ const snapshotComposerOptions = (agentTargetId2 ? agentActivityRuntime.getSnapshot(workspaceId).composerOptionsByAgentTargetId?.[agentTargetId2] : null) ?? agentActivityRuntime.getSnapshot(workspaceId).composerOptionsByProvider?.[provider] ?? null;
11090
11275
  const snapshotDraftAgentSessionId = normalizedInitialContent.length > 0 && provider === "claude-code" ? draftAgentSessionIdFromComposerOptions(snapshotComposerOptions) : null;
11091
11276
  const draftAgentSessionId = snapshotDraftAgentSessionId && !activatedConversationIdsRef.current.has(
11092
11277
  snapshotDraftAgentSessionId
@@ -11185,6 +11370,7 @@ function useAgentGUINodeController({
11185
11370
  return activation.activate({
11186
11371
  mode: "new",
11187
11372
  agentSessionId,
11373
+ agentTargetId: agentTargetId2 || null,
11188
11374
  provider,
11189
11375
  providerTargetRef: shouldUseProviderTargetRef ? target2.ref : null,
11190
11376
  cwd: selectedProjectPath2 ?? "",
@@ -12472,7 +12658,10 @@ function useAgentGUINodeController({
12472
12658
  };
12473
12659
  const agentSessionId = activeConversationIdRef.current;
12474
12660
  if (!agentSessionId) {
12475
- const defaultDraftKey = nodeDefaultDraftKey(dataRef.current.provider);
12661
+ const defaultDraftKey = nodeDefaultDraftKey(
12662
+ dataRef.current.provider,
12663
+ dataRef.current.agentTargetId
12664
+ );
12476
12665
  const storedDefaults = readNodeDefaultDraftSettings({
12477
12666
  data: dataRef.current,
12478
12667
  defaultReasoningEffort,
@@ -13322,7 +13511,8 @@ function useAgentGUINodeController({
13322
13511
  return null;
13323
13512
  }
13324
13513
  const previous = projectionConversationRef.current;
13325
- if (previous && previous.id === activeConversation.id && previous.userId === activeConversation.userId && previous.provider === activeConversation.provider && previous.title === activeConversation.title && previous.titleFallback === activeConversation.titleFallback && previous.status === activeConversation.status && previous.cwd === activeConversation.cwd) {
13514
+ const turnLifecycle = activeSessionState?.agentSessionId === activeConversation.id ? activeSessionState.turnLifecycle ?? null : null;
13515
+ if (previous && previous.id === activeConversation.id && previous.userId === activeConversation.userId && previous.provider === activeConversation.provider && previous.title === activeConversation.title && previous.titleFallback === activeConversation.titleFallback && previous.status === activeConversation.status && previous.cwd === activeConversation.cwd && (previous.turnLifecycle?.activeTurnId ?? null) === (turnLifecycle?.activeTurnId ?? null) && (previous.turnLifecycle?.phase ?? null) === (turnLifecycle?.phase ?? null) && (previous.turnLifecycle?.settling ?? false) === (turnLifecycle?.settling ?? false)) {
13326
13516
  return previous;
13327
13517
  }
13328
13518
  const next = activeConversation ? {
@@ -13334,7 +13524,8 @@ function useAgentGUINodeController({
13334
13524
  status: activeConversation.status,
13335
13525
  cwd: activeConversation.cwd,
13336
13526
  updatedAtUnixMs: activeConversation.updatedAtUnixMs,
13337
- syncState: activeConversation.syncState
13527
+ syncState: activeConversation.syncState,
13528
+ turnLifecycle
13338
13529
  } : null;
13339
13530
  projectionConversationRef.current = next;
13340
13531
  return next;
@@ -13347,7 +13538,11 @@ function useAgentGUINodeController({
13347
13538
  activeConversation?.status,
13348
13539
  activeConversation?.title,
13349
13540
  activeConversation?.titleFallback,
13350
- activeConversation?.userId
13541
+ activeConversation?.userId,
13542
+ activeSessionState?.agentSessionId,
13543
+ activeSessionState?.turnLifecycle?.activeTurnId,
13544
+ activeSessionState?.turnLifecycle?.phase,
13545
+ activeSessionState?.turnLifecycle?.settling
13351
13546
  ]);
13352
13547
  const draftContent = activeConversationId ? draftBySessionId[activeConversationId] ?? EMPTY_AGENT_COMPOSER_DRAFT : readNodeDefaultDraftContent({
13353
13548
  data,
@@ -13612,7 +13807,7 @@ function useAgentGUINodeController({
13612
13807
  hasProviderSessionNotFoundError,
13613
13808
  pendingApproval
13614
13809
  ]);
13615
- const canSubmit = activeLiveState !== "activating" && activeLiveState !== "failed" && !activeConversationResumeUnavailable && (activeConversationId !== null || selectedProviderTarget.disabled !== true) && (data.provider !== "openclaw" || openclawGateway?.status === "ready") && pendingApproval === null && pendingInteractivePrompt === null && sessionChrome.auth === null && !isCreatingConversation && !isSubmitting && !isInterrupting;
13810
+ const canSubmit = !providerTargetsLoading && activeLiveState !== "activating" && activeLiveState !== "failed" && !activeConversationResumeUnavailable && (activeConversationId !== null || selectedProviderTarget.disabled !== true) && (data.provider !== "openclaw" || openclawGateway?.status === "ready") && pendingApproval === null && pendingInteractivePrompt === null && sessionChrome.auth === null && !isCreatingConversation && !isSubmitting && !isInterrupting;
13616
13811
  const canQueueWhileBusy = Boolean(activeConversationId) && (activeConversationBusy || isSubmitting || Boolean(activeSessionState?.pendingInteractive));
13617
13812
  useEffect4(() => {
13618
13813
  const firstVersion = minFiniteMessageVersion(activeMessages);
@@ -13693,6 +13888,7 @@ function useAgentGUINodeController({
13693
13888
  isSubmitting,
13694
13889
  pendingApproval,
13695
13890
  pendingInteractivePrompt,
13891
+ providerTargetsLoading,
13696
13892
  workspaceId
13697
13893
  ]);
13698
13894
  const activeSessionReasoningSelection = useMemo4(
@@ -13801,7 +13997,115 @@ function useAgentGUINodeController({
13801
13997
  stableComposerSettings.availableModels.length,
13802
13998
  stableComposerSettings.isSettingsLoading
13803
13999
  ]);
14000
+ const updateConversationFilter = useCallback4(
14001
+ (filter) => {
14002
+ if (!canUseConversationTargetFilter) {
14003
+ setConversationFilter({ kind: "all" });
14004
+ return;
14005
+ }
14006
+ setConversationFilter(normalizeAgentGUIConversationFilter(filter));
14007
+ },
14008
+ [canUseConversationTargetFilter]
14009
+ );
14010
+ const selectProvider = useCallback4(
14011
+ (input) => {
14012
+ if (previewMode) {
14013
+ return;
14014
+ }
14015
+ const nextProvider = input.provider;
14016
+ const nextTarget = resolveAgentGUIProviderTarget({
14017
+ defaultProviderTargetId,
14018
+ fallbackToLocal: shouldFallbackToLocalProviderTargets,
14019
+ provider: nextProvider,
14020
+ providerTargetId: input.providerTargetId,
14021
+ providerTargets: normalizedProviderTargets
14022
+ });
14023
+ if (!nextTarget) {
14024
+ return;
14025
+ }
14026
+ if (nextTarget.disabled === true) {
14027
+ return;
14028
+ }
14029
+ const shouldUseProviderTargetRef = normalizedExplicitProviderTargets.some(
14030
+ (target) => target.provider === nextTarget.provider && target.targetId === nextTarget.targetId && agentGUIProviderTargetRefsEqual(target.ref, nextTarget.ref)
14031
+ );
14032
+ const previous = activeConversationIdRef.current;
14033
+ if (previous) {
14034
+ void activation.unactivate(previous);
14035
+ }
14036
+ setIntent({ tag: "home" });
14037
+ isComposerHomeRef.current = true;
14038
+ setIsComposerHome(true);
14039
+ activeConversationIdRef.current = null;
14040
+ setActiveConversationId(null);
14041
+ setIsLoadingMessages(false);
14042
+ setDetailError(null);
14043
+ persistActiveConversation(null);
14044
+ onDataChangeRef.current((current) => {
14045
+ const nextAgentTargetId = shouldUseProviderTargetRef ? nextTarget.agentTargetId ?? null : null;
14046
+ const nextData = {
14047
+ ...current,
14048
+ provider: nextProvider,
14049
+ agentTargetId: nextAgentTargetId,
14050
+ lastActiveAgentSessionId: null,
14051
+ providerTargetId: null,
14052
+ providerTargetRef: null
14053
+ };
14054
+ dataRef.current = nextData;
14055
+ return nextData;
14056
+ });
14057
+ window.setTimeout(() => {
14058
+ loadDraftComposerOptions({ force: true });
14059
+ }, 0);
14060
+ },
14061
+ [
14062
+ activation,
14063
+ defaultProviderTargetId,
14064
+ loadDraftComposerOptions,
14065
+ normalizedExplicitProviderTargets,
14066
+ normalizedProviderTargets,
14067
+ persistActiveConversation,
14068
+ previewMode,
14069
+ shouldFallbackToLocalProviderTargets
14070
+ ]
14071
+ );
14072
+ const selectConversationFilterTarget = useCallback4(
14073
+ (input) => {
14074
+ if (!canUseConversationTargetFilter) {
14075
+ setConversationFilter({ kind: "all" });
14076
+ return;
14077
+ }
14078
+ const nextTarget = resolveAgentGUIProviderTarget({
14079
+ defaultProviderTargetId,
14080
+ fallbackToLocal: shouldFallbackToLocalProviderTargets,
14081
+ provider: input.provider,
14082
+ providerTargetId: input.providerTargetId,
14083
+ providerTargets: normalizedProviderTargets
14084
+ });
14085
+ if (!nextTarget || nextTarget.disabled === true) {
14086
+ return;
14087
+ }
14088
+ const agentTargetId = nextTarget.agentTargetId?.trim() ?? "";
14089
+ const nextFilter = agentTargetId ? { kind: "agentTarget", agentTargetId } : { kind: "all" };
14090
+ setConversationFilter(nextFilter);
14091
+ selectProvider({
14092
+ provider: nextTarget.provider,
14093
+ providerTargetId: nextTarget.targetId
14094
+ });
14095
+ },
14096
+ [
14097
+ canUseConversationTargetFilter,
14098
+ defaultProviderTargetId,
14099
+ normalizedProviderTargets,
14100
+ selectProvider,
14101
+ shouldFallbackToLocalProviderTargets
14102
+ ]
14103
+ );
13804
14104
  const stableCreateConversation = useStableControllerEventCallback(createConversation);
14105
+ const stableSelectProvider = useStableControllerEventCallback(selectProvider);
14106
+ const stableSelectConversationFilterTarget = useStableControllerEventCallback(
14107
+ selectConversationFilterTarget
14108
+ );
13805
14109
  const stableSelectConversation = useStableControllerEventCallback(selectConversation);
13806
14110
  const stableSubmitPrompt = useStableControllerEventCallback(submitPrompt);
13807
14111
  const stableSubmitGuidancePrompt = useStableControllerEventCallback(submitGuidancePrompt);
@@ -13852,8 +14156,14 @@ function useAgentGUINodeController({
13852
14156
  const stableLoadOlderConversationMessages = useStableControllerEventCallback(
13853
14157
  loadOlderConversationMessages
13854
14158
  );
14159
+ const stableUpdateConversationFilter = useStableControllerEventCallback(
14160
+ updateConversationFilter
14161
+ );
13855
14162
  const controllerActions = useMemo4(
13856
14163
  () => ({
14164
+ updateConversationFilter: stableUpdateConversationFilter,
14165
+ selectConversationFilterTarget: stableSelectConversationFilterTarget,
14166
+ selectProvider: stableSelectProvider,
13857
14167
  createConversation: stableCreateConversation,
13858
14168
  selectConversation: stableSelectConversation,
13859
14169
  submitPrompt: stableSubmitPrompt,
@@ -13900,6 +14210,8 @@ function useAgentGUINodeController({
13900
14210
  stableRetryActivation,
13901
14211
  stableRetryOpenclawGateway,
13902
14212
  stableSelectConversation,
14213
+ stableSelectConversationFilterTarget,
14214
+ stableSelectProvider,
13903
14215
  stableSendQueuedPromptNext,
13904
14216
  stableSubmitGuidancePrompt,
13905
14217
  stableShowPromptImagesUnsupported,
@@ -13907,6 +14219,7 @@ function useAgentGUINodeController({
13907
14219
  stableSubmitInteractivePrompt,
13908
14220
  stableSubmitPrompt,
13909
14221
  stableToggleConversationPinned,
14222
+ stableUpdateConversationFilter,
13910
14223
  stableUpdateComposerSettings,
13911
14224
  stableUpdateDraftContent,
13912
14225
  stableUpdateSelectedProjectPath
@@ -13920,6 +14233,10 @@ function useAgentGUINodeController({
13920
14233
  currentUserId,
13921
14234
  data,
13922
14235
  selectedProviderTarget,
14236
+ providerTargets: normalizedProviderTargets,
14237
+ providerTargetsLoading,
14238
+ conversationScope,
14239
+ conversationFilter,
13923
14240
  conversations: visibleConversations,
13924
14241
  userProjects,
13925
14242
  activeConversation,
@@ -13940,6 +14257,7 @@ function useAgentGUINodeController({
13940
14257
  promptImagesSupported,
13941
14258
  compactSupported,
13942
14259
  usage,
14260
+ backgroundAgentCount,
13943
14261
  listError,
13944
14262
  isDeletingConversation,
13945
14263
  isDeletingProjectConversations,
@@ -13981,10 +14299,14 @@ function useAgentGUINodeController({
13981
14299
  canSubmit,
13982
14300
  canQueueWhileBusy,
13983
14301
  conversation,
14302
+ conversationScope,
14303
+ conversationFilter,
13984
14304
  conversationDetail,
13985
14305
  controllerActions,
13986
14306
  data,
13987
14307
  selectedProviderTarget,
14308
+ normalizedProviderTargets,
14309
+ providerTargetsLoading,
13988
14310
  detailError,
13989
14311
  draftContent,
13990
14312
  draftPrompt,
@@ -13993,6 +14315,7 @@ function useAgentGUINodeController({
13993
14315
  promptImagesSupported,
13994
14316
  compactSupported,
13995
14317
  usage,
14318
+ backgroundAgentCount,
13996
14319
  isInterrupting,
13997
14320
  isCancelPending,
13998
14321
  isLoadingConversations,
@@ -14214,7 +14537,13 @@ import {
14214
14537
  } from "react";
14215
14538
  import { useSnapshot } from "valtio";
14216
14539
  import { proxy as proxy2 } from "valtio/vanilla";
14217
- import { ChevronRight as ChevronRight2, ExternalLink, Info as Info2, Wrench } from "lucide-react";
14540
+ import {
14541
+ ChevronRight as ChevronRight2,
14542
+ ExternalLink,
14543
+ Info as Info2,
14544
+ LayoutGrid,
14545
+ Wrench
14546
+ } from "lucide-react";
14218
14547
 
14219
14548
  // app/renderer/components/ui/popover.tsx
14220
14549
  import {
@@ -15015,13 +15344,11 @@ function AgentChromeNotice({
15015
15344
  }) {
15016
15345
  "use memo";
15017
15346
  const fullMessage = description ? `${title} ${description}` : title;
15347
+ const toneClassName = tone === "danger" ? AgentGUIChrome_styles_default.chromeCardDanger : tone === "muted" ? AgentGUIChrome_styles_default.chromeCardMuted : AgentGUIChrome_styles_default.chromeCardWarning;
15018
15348
  return /* @__PURE__ */ jsx19("div", { className: AgentGUIChrome_styles_default.sessionChrome, children: /* @__PURE__ */ jsx19(
15019
15349
  "section",
15020
15350
  {
15021
- className: cn(
15022
- AgentGUIChrome_styles_default.chromeCard,
15023
- tone === "danger" ? AgentGUIChrome_styles_default.chromeCardDanger : AgentGUIChrome_styles_default.chromeCardWarning
15024
- ),
15351
+ className: cn(AgentGUIChrome_styles_default.chromeCard, toneClassName),
15025
15352
  role,
15026
15353
  "data-testid": testId,
15027
15354
  children: /* @__PURE__ */ jsx19("div", { className: AgentGUIChrome_styles_default.chromeMetaRow, children: /* @__PURE__ */ jsxs7("div", { className: AgentGUIChrome_styles_default.chromeMessageSlot, children: [
@@ -15265,7 +15592,15 @@ import {
15265
15592
  useState as useState10
15266
15593
  } from "react";
15267
15594
  import { createPortal as createPortal3 } from "react-dom";
15268
- import { AddIcon, Button as Button3, Select as Select2, SelectTrigger as SelectTrigger2 } from "@tutti-os/ui-system";
15595
+ import {
15596
+ AddIcon,
15597
+ Button as Button3,
15598
+ Select as Select2,
15599
+ SelectContent as SelectContent2,
15600
+ SelectItem as SelectItem2,
15601
+ SelectTrigger as SelectTrigger2,
15602
+ SelectValue
15603
+ } from "@tutti-os/ui-system";
15269
15604
  import { ListChecks as ListChecks2, Target as Target3, X } from "lucide-react";
15270
15605
  import {
15271
15606
  createMentionPaletteStateAdapter,
@@ -15946,6 +16281,7 @@ var styles3 = {
15946
16281
  composerPromptTipText: "agent-gui-node__composer-prompt-tip-text",
15947
16282
  composerPromptTipTooltip: "agent-gui-node__composer-prompt-tip-tooltip",
15948
16283
  composerProjectRow: "agent-gui-node__composer-project-row",
16284
+ composerProviderSelect: "agent-gui-node__composer-provider-select",
15949
16285
  composerQueuedPromptCard: "agent-gui-node__composer-queued-prompt-card",
15950
16286
  composerQueuedPromptHeader: "agent-gui-node__composer-queued-prompt-header",
15951
16287
  composerQueuedPromptExpandCue: "agent-gui-node__composer-queued-prompt-expand-cue",
@@ -16023,6 +16359,12 @@ var styles3 = {
16023
16359
  projectRailAddProjectTrigger: "agent-gui-node__project-rail-add-project-trigger",
16024
16360
  projectRailHeader: "agent-gui-node__project-rail-header",
16025
16361
  projectRailTitle: "agent-gui-node__project-rail-title",
16362
+ providerRail: "agent-gui-node__provider-rail",
16363
+ providerRailAvatar: "agent-gui-node__provider-rail-avatar",
16364
+ providerRailAvatarIcon: "agent-gui-node__provider-rail-avatar-icon",
16365
+ providerRailAvatarImage: "agent-gui-node__provider-rail-avatar-image",
16366
+ providerRailTile: "agent-gui-node__provider-rail-tile",
16367
+ providerRailTileLabel: "agent-gui-node__provider-rail-tile-label",
16026
16368
  rail: "agent-gui-node__rail",
16027
16369
  railPanel: "agent-gui-node__rail-panel",
16028
16370
  railPanelCollapsed: "agent-gui-node__rail-panel--collapsed",
@@ -18875,7 +19217,7 @@ function AgentReviewPickerPanel({
18875
19217
  {
18876
19218
  key: "uncommitted",
18877
19219
  label: labels.uncommitted,
18878
- onSelect: () => submit("/review")
19220
+ onSelect: () => submit("/review uncommitted")
18879
19221
  },
18880
19222
  {
18881
19223
  key: "base",
@@ -19552,11 +19894,21 @@ function hasInlineOverflow(element) {
19552
19894
  }
19553
19895
  return element.scrollWidth > element.clientWidth + 1;
19554
19896
  }
19897
+ function resolveComposerProviderIconUrl(provider) {
19898
+ const normalizedProvider = normalizeManagedAgentProvider(provider);
19899
+ return MANAGED_AGENT_ICON_URLS[normalizedProvider] ?? MANAGED_AGENT_ICON_FALLBACK_URL;
19900
+ }
19901
+ function resolveComposerProviderTargetIconUrl(target) {
19902
+ return target.iconUrl?.trim() || resolveComposerProviderIconUrl(target.provider);
19903
+ }
19555
19904
  function AgentComposer({
19556
19905
  workspaceId,
19557
19906
  workspacePath,
19558
19907
  currentUserId,
19559
19908
  provider,
19909
+ selectedProviderTarget = null,
19910
+ providerTargets = [],
19911
+ providerSelectReadonly = false,
19560
19912
  slashStatus = null,
19561
19913
  usage = null,
19562
19914
  draftContent,
@@ -19575,6 +19927,7 @@ function AgentComposer({
19575
19927
  canQueueWhileBusy,
19576
19928
  showStopButton,
19577
19929
  activePrompt,
19930
+ backgroundAgentStatusText = null,
19578
19931
  activePromptKeyboardShortcutsEnabled = true,
19579
19932
  promptTips = EMPTY_PROMPT_TIPS,
19580
19933
  isInterrupting,
@@ -19592,6 +19945,7 @@ function AgentComposer({
19592
19945
  onProjectPathChange = () => {
19593
19946
  },
19594
19947
  onSettingsChange,
19948
+ onProviderSelect,
19595
19949
  capabilityMenuState,
19596
19950
  onSubmit,
19597
19951
  onSubmitGuidance,
@@ -20705,6 +21059,17 @@ function AgentComposer({
20705
21059
  }
20706
21060
  await applyReferencePickResult(await onRequestWorkspaceReferences());
20707
21061
  }, [applyReferencePickResult, onRequestWorkspaceReferences]);
21062
+ const providerSwitchTargets = useMemo9(
21063
+ () => providerTargets.filter((target) => target.disabled !== true),
21064
+ [providerTargets]
21065
+ );
21066
+ const showProviderSelect = providerSwitchTargets.length > 1;
21067
+ const selectedProviderTargetId = selectedProviderTarget?.targetId ?? `local:${provider}`;
21068
+ const selectedProviderSwitchTarget = providerSwitchTargets.find(
21069
+ (target) => target.targetId === selectedProviderTargetId
21070
+ ) ?? selectedProviderTarget ?? providerSwitchTargets.find((target) => target.provider === provider) ?? null;
21071
+ const selectedProviderLabel = selectedProviderSwitchTarget?.label ?? provider;
21072
+ const providerSelectDisabled = previewMode || providerSelectReadonly || !onProviderSelect;
20708
21073
  const applyDroppedFileReferences = useCallback9(
20709
21074
  async (files) => {
20710
21075
  if (!promptFilesSupported || !resolveDroppedFileReferences || files.length === 0) {
@@ -21355,6 +21720,16 @@ function AgentComposer({
21355
21720
  ),
21356
21721
  "data-edge-glow": showEdgeGlow ? "true" : void 0,
21357
21722
  children: [
21723
+ backgroundAgentStatusText ? /* @__PURE__ */ jsx28(
21724
+ AgentChromeNotice,
21725
+ {
21726
+ tone: "muted",
21727
+ role: "status",
21728
+ testId: "agent-gui-composer-background-agent-status",
21729
+ title: backgroundAgentStatusText,
21730
+ icon: /* @__PURE__ */ jsx28(Spinner, { className: "h-3.5 w-3.5" })
21731
+ }
21732
+ ) : null,
21358
21733
  isSelectedProjectMissing ? /* @__PURE__ */ jsx28(
21359
21734
  AgentChromeNotice,
21360
21735
  {
@@ -21691,6 +22066,68 @@ function AgentComposer({
21691
22066
  )
21692
22067
  }
21693
22068
  ),
22069
+ showProviderSelect && selectedProviderSwitchTarget ? /* @__PURE__ */ jsxs15(
22070
+ Select2,
22071
+ {
22072
+ value: selectedProviderTargetId,
22073
+ disabled: providerSelectDisabled,
22074
+ onValueChange: (nextTargetId) => {
22075
+ const target = providerSwitchTargets.find(
22076
+ (candidate) => candidate.targetId === nextTargetId
22077
+ );
22078
+ if (!target) {
22079
+ return;
22080
+ }
22081
+ onProviderSelect?.({
22082
+ provider: target.provider,
22083
+ providerTargetId: target.targetId
22084
+ });
22085
+ },
22086
+ children: [
22087
+ /* @__PURE__ */ jsx28(
22088
+ SelectTrigger2,
22089
+ {
22090
+ size: "sm",
22091
+ "aria-label": labels.providerSwitchLabel,
22092
+ title: labels.providerSwitchLabel,
22093
+ className: cn(
22094
+ AgentGUINode_styles_default.composerMenuTrigger,
22095
+ AgentGUINode_styles_default.composerProviderSelect,
22096
+ "max-w-[160px] text-[var(--agent-gui-text-secondary)]"
22097
+ ),
22098
+ children: /* @__PURE__ */ jsx28("span", { className: "min-w-0 truncate", children: /* @__PURE__ */ jsx28(SelectValue, { placeholder: selectedProviderLabel }) })
22099
+ }
22100
+ ),
22101
+ /* @__PURE__ */ jsx28(
22102
+ SelectContent2,
22103
+ {
22104
+ align: "start",
22105
+ className: cn(AgentGUINode_styles_default.composerMenuContent, "min-w-[190px]"),
22106
+ children: providerSwitchTargets.map((target) => /* @__PURE__ */ jsx28(
22107
+ SelectItem2,
22108
+ {
22109
+ value: target.targetId,
22110
+ className: cn(AgentGUINode_styles_default.composerMenuItem, "gap-2"),
22111
+ children: /* @__PURE__ */ jsxs15("span", { className: "flex min-w-0 items-center gap-2", children: [
22112
+ /* @__PURE__ */ jsx28(
22113
+ "img",
22114
+ {
22115
+ alt: "",
22116
+ "aria-hidden": "true",
22117
+ className: "size-4 shrink-0 rounded-[4px]",
22118
+ src: resolveComposerProviderTargetIconUrl(target)
22119
+ }
22120
+ ),
22121
+ /* @__PURE__ */ jsx28("span", { className: "min-w-0 truncate", children: target.label })
22122
+ ] })
22123
+ },
22124
+ `${target.provider}:${target.targetId}`
22125
+ ))
22126
+ }
22127
+ )
22128
+ ]
22129
+ }
22130
+ ) : null,
21694
22131
  composerSettings.supportsPlanMode && composerSettings.draftSettings.planMode ? /* @__PURE__ */ jsx28(
21695
22132
  "button",
21696
22133
  {
@@ -22298,7 +22735,7 @@ function groupConversations(conversations, labels, userProjects = [], options =
22298
22735
  }
22299
22736
  groups.push(
22300
22737
  ...[...projectGroups.values()].sort(
22301
- (left, right) => left.sectionOrder - right.sectionOrder || Number(right.items.length > 0) - Number(left.items.length > 0) || right.projectUpdatedAtUnixMs - left.projectUpdatedAtUnixMs || left.projectOrder - right.projectOrder || left.label.localeCompare(right.label) || left.id.localeCompare(right.id)
22738
+ (left, right) => left.sectionOrder - right.sectionOrder || right.projectUpdatedAtUnixMs - left.projectUpdatedAtUnixMs || left.projectOrder - right.projectOrder || left.label.localeCompare(right.label) || left.id.localeCompare(right.id)
22302
22739
  ).map(
22303
22740
  ({
22304
22741
  projectOrder: _projectOrder,
@@ -22508,7 +22945,7 @@ function resolveConversationDetailStatus(detail) {
22508
22945
  function objectRecord(value) {
22509
22946
  return value && typeof value === "object" && !Array.isArray(value) ? value : null;
22510
22947
  }
22511
- function numberValue(value) {
22948
+ function numberValue2(value) {
22512
22949
  if (typeof value === "number" && Number.isFinite(value)) {
22513
22950
  return value;
22514
22951
  }
@@ -22528,8 +22965,8 @@ function resolveSlashStatus({
22528
22965
  }) {
22529
22966
  const usage = objectRecord(rawState?.runtimeContext?.usage);
22530
22967
  const contextWindow = objectRecord(usage?.contextWindow) ?? objectRecord(usage?.context_window) ?? (usage && (usage.used !== void 0 || usage.size !== void 0 || usage.usedTokens !== void 0 || usage.totalTokens !== void 0) ? {
22531
- usedTokens: numberValue(usage.usedTokens) ?? numberValue(usage.used_tokens) ?? numberValue(usage.used),
22532
- totalTokens: numberValue(usage.totalTokens) ?? numberValue(usage.total_tokens) ?? numberValue(usage.size)
22968
+ usedTokens: numberValue2(usage.usedTokens) ?? numberValue2(usage.used_tokens) ?? numberValue2(usage.used),
22969
+ totalTokens: numberValue2(usage.totalTokens) ?? numberValue2(usage.total_tokens) ?? numberValue2(usage.size)
22533
22970
  } : null);
22534
22971
  const providerConfig = objectRecord(rawState?.runtimeContext?.providerConfig);
22535
22972
  return {
@@ -22538,8 +22975,8 @@ function resolveSlashStatus({
22538
22975
  limits,
22539
22976
  limitsLoading: limitsLoading || isAppServerStartupLoading2(rawState, "rateLimits"),
22540
22977
  contextWindow: contextWindow ? {
22541
- usedTokens: numberValue(contextWindow.usedTokens) ?? numberValue(contextWindow.used_tokens),
22542
- totalTokens: numberValue(contextWindow.totalTokens) ?? numberValue(contextWindow.total_tokens)
22978
+ usedTokens: numberValue2(contextWindow.usedTokens) ?? numberValue2(contextWindow.used_tokens),
22979
+ totalTokens: numberValue2(contextWindow.totalTokens) ?? numberValue2(contextWindow.total_tokens)
22543
22980
  } : null
22544
22981
  };
22545
22982
  }
@@ -22974,7 +23411,14 @@ function AgentGUINodeView({
22974
23411
  openclawGateway,
22975
23412
  isCollapsed: conversationRailCollapsed,
22976
23413
  slashStatusLimits,
23414
+ selectedProviderTarget: viewModel.selectedProviderTarget,
23415
+ providerTargets: viewModel.providerTargets,
23416
+ providerTargetsLoading: viewModel.providerTargetsLoading,
23417
+ conversationScope: viewModel.conversationScope,
23418
+ conversationFilter: viewModel.conversationFilter,
22977
23419
  onCreateConversation: requestCreateConversation,
23420
+ onUpdateConversationFilter: actions.updateConversationFilter,
23421
+ onSelectConversationFilterTarget: actions.selectConversationFilterTarget,
22978
23422
  onOpenAgentEnvSetup: openAgentEnvSetup,
22979
23423
  onRetryOpenclawGateway: retryOpenclawGateway,
22980
23424
  onSelectConversation: selectConversation,
@@ -23001,6 +23445,7 @@ function AgentGUINodeView({
23001
23445
  openConversationWindow,
23002
23446
  openProjectFiles,
23003
23447
  openclawGateway,
23448
+ actions.updateConversationFilter,
23004
23449
  previewMode,
23005
23450
  removeProject,
23006
23451
  requestCreateConversation,
@@ -23009,8 +23454,13 @@ function AgentGUINodeView({
23009
23454
  selectConversation,
23010
23455
  selectProjectDirectory,
23011
23456
  slashStatusLimits,
23457
+ viewModel.selectedProviderTarget,
23458
+ viewModel.providerTargets,
23459
+ viewModel.providerTargetsLoading,
23012
23460
  toggleConversationPinned,
23013
23461
  uiLanguage,
23462
+ viewModel.conversationScope,
23463
+ viewModel.conversationFilter,
23014
23464
  viewModel.activeConversationId,
23015
23465
  viewModel.isDeletingConversation,
23016
23466
  viewModel.isDeletingProjectConversations,
@@ -23032,7 +23482,21 @@ function AgentGUINodeView({
23032
23482
  conversationRailStore,
23033
23483
  conversationRailStoreState
23034
23484
  );
23035
- const content = /* @__PURE__ */ jsxs17(Fragment8, { children: [
23485
+ const agentTargetPresentations = useMemo10(
23486
+ () => viewModel.providerTargets.flatMap(
23487
+ (target) => target.agentTargetId ? [
23488
+ {
23489
+ agentTargetId: target.agentTargetId,
23490
+ iconUrl: target.iconUrl ?? null,
23491
+ name: target.label,
23492
+ provider: target.provider,
23493
+ workspaceId: viewModel.workspaceId
23494
+ }
23495
+ ] : []
23496
+ ),
23497
+ [viewModel.providerTargets, viewModel.workspaceId]
23498
+ );
23499
+ const content = /* @__PURE__ */ jsxs17(AgentTargetPresentationProvider, { agentTargets: agentTargetPresentations, children: [
23036
23500
  /* @__PURE__ */ jsxs17(
23037
23501
  "div",
23038
23502
  {
@@ -23054,11 +23518,9 @@ function AgentGUINodeView({
23054
23518
  AgentGUIConversationRailStorePane,
23055
23519
  {
23056
23520
  conversations: viewModel.conversations,
23057
- provider: viewModel.data.provider,
23058
23521
  store: conversationRailStore,
23059
23522
  storeState: conversationRailStoreState,
23060
- userProjects: viewModel.userProjects,
23061
- workspaceId: viewModel.workspaceId
23523
+ userProjects: viewModel.userProjects
23062
23524
  }
23063
23525
  )
23064
23526
  }
@@ -23560,6 +24022,7 @@ var AgentGUIDetailPane = memo(function AgentGUIDetailPane2({
23560
24022
  removeMention: labels.removeMention,
23561
24023
  addReference: labels.addReference,
23562
24024
  referenceWorkspaceFiles: labels.referenceWorkspaceFiles,
24025
+ providerSwitchLabel: labels.providerSwitchLabel,
23563
24026
  projectLocked: labels.projectLocked,
23564
24027
  projectMissingDescription: labels.projectMissingDescription,
23565
24028
  promptTipsPrefix: labels.promptTipsPrefix,
@@ -23600,6 +24063,7 @@ var AgentGUIDetailPane = memo(function AgentGUIDetailPane2({
23600
24063
  labels.queuedLabel,
23601
24064
  labels.queuedPromptMoreActions,
23602
24065
  labels.referenceWorkspaceFiles,
24066
+ labels.providerSwitchLabel,
23603
24067
  labels.removeMention,
23604
24068
  labels.reasoningDegreeLabel,
23605
24069
  labels.reasoningLabel,
@@ -23708,6 +24172,10 @@ var AgentGUIDetailPane = memo(function AgentGUIDetailPane2({
23708
24172
  const submitPromptAndScrollToBottom = useCallback10(
23709
24173
  (content, displayPrompt) => {
23710
24174
  requestSubmittedPromptScrollToBottom();
24175
+ if (displayPrompt === void 0) {
24176
+ submitPrompt(content);
24177
+ return;
24178
+ }
23711
24179
  submitPrompt(content, displayPrompt);
23712
24180
  },
23713
24181
  [requestSubmittedPromptScrollToBottom, submitPrompt]
@@ -23715,6 +24183,10 @@ var AgentGUIDetailPane = memo(function AgentGUIDetailPane2({
23715
24183
  const submitGuidancePromptAndScrollToBottom = useCallback10(
23716
24184
  (content, displayPrompt) => {
23717
24185
  requestSubmittedPromptScrollToBottom();
24186
+ if (displayPrompt === void 0) {
24187
+ submitGuidancePrompt(content);
24188
+ return;
24189
+ }
23718
24190
  submitGuidancePrompt(content, displayPrompt);
23719
24191
  },
23720
24192
  [requestSubmittedPromptScrollToBottom, submitGuidancePrompt]
@@ -23739,6 +24211,7 @@ var AgentGUIDetailPane = memo(function AgentGUIDetailPane2({
23739
24211
  );
23740
24212
  const stableRequestGitBranches = useOptionalStableEventCallback(onRequestGitBranches);
23741
24213
  const authLogin = useOptionalStableEventCallback(onAgentProviderLogin);
24214
+ const backgroundAgentStatusText = viewModel.backgroundAgentCount > 0 ? labels.waitingForBackgroundAgent(viewModel.backgroundAgentCount) : null;
23742
24215
  const submitBottomDockInteractivePrompt = useCallback10(
23743
24216
  (input) => {
23744
24217
  submitInteractivePrompt(input);
@@ -23746,12 +24219,17 @@ var AgentGUIDetailPane = memo(function AgentGUIDetailPane2({
23746
24219
  },
23747
24220
  [submitInteractivePrompt]
23748
24221
  );
24222
+ const canSwitchComposerProvider = viewModel.conversationScope === "multi-provider";
24223
+ const composerProviderTargets = canSwitchComposerProvider ? viewModel.providerTargets : [viewModel.selectedProviderTarget];
23749
24224
  const bottomDockComposerProps = useMemo10(
23750
24225
  () => ({
23751
24226
  workspaceId: viewModel.workspaceId,
23752
24227
  workspacePath: viewModel.workspacePath,
23753
24228
  currentUserId: viewModel.currentUserId,
23754
24229
  provider: viewModel.data.provider,
24230
+ selectedProviderTarget: viewModel.selectedProviderTarget,
24231
+ providerTargets: composerProviderTargets,
24232
+ providerSelectReadonly: !canSwitchComposerProvider || viewModel.activeConversationId !== null,
23755
24233
  slashStatus,
23756
24234
  usage: viewModel.usage,
23757
24235
  draftContent: viewModel.draftContent,
@@ -23773,6 +24251,7 @@ var AgentGUIDetailPane = memo(function AgentGUIDetailPane2({
23773
24251
  // Plan decisions replace the composer via bottomDockReplacementPrompt;
23774
24252
  // approval / ask-user embed here (composerActivePrompt encodes that).
23775
24253
  activePrompt: composerActivePrompt,
24254
+ backgroundAgentStatusText,
23776
24255
  activePromptKeyboardShortcutsEnabled: isActive,
23777
24256
  promptTips: labels.promptTips,
23778
24257
  composerFocusRequestSequence,
@@ -23788,6 +24267,7 @@ var AgentGUIDetailPane = memo(function AgentGUIDetailPane2({
23788
24267
  onDraftContentChange: updateDraftContent,
23789
24268
  onProjectPathChange: updateSelectedProjectPath,
23790
24269
  onSettingsChange: updateComposerSettings,
24270
+ onProviderSelect: canSwitchComposerProvider ? actions.selectProvider : void 0,
23791
24271
  onSubmit: submitPromptAndScrollToBottom,
23792
24272
  onSubmitGuidance: submitGuidancePromptAndScrollToBottom,
23793
24273
  onPromptImagesUnsupported: showPromptImagesUnsupported,
@@ -23806,7 +24286,10 @@ var AgentGUIDetailPane = memo(function AgentGUIDetailPane2({
23806
24286
  }),
23807
24287
  [
23808
24288
  canQueueWhileBusy,
24289
+ backgroundAgentStatusText,
24290
+ canSwitchComposerProvider,
23809
24291
  capabilityMenuState,
24292
+ composerProviderTargets,
23810
24293
  composerDisabled,
23811
24294
  composerDisabledReason,
23812
24295
  composerFocusRequestSequence,
@@ -23838,6 +24321,7 @@ var AgentGUIDetailPane = memo(function AgentGUIDetailPane2({
23838
24321
  stableSelectProjectDirectory,
23839
24322
  stableRequestWorkspaceReferences,
23840
24323
  updateComposerSettings,
24324
+ actions.selectProvider,
23841
24325
  updateDraftContent,
23842
24326
  updateSelectedProjectPath,
23843
24327
  viewModel.availableCommands,
@@ -23846,6 +24330,7 @@ var AgentGUIDetailPane = memo(function AgentGUIDetailPane2({
23846
24330
  viewModel.composerSettings,
23847
24331
  viewModel.currentUserId,
23848
24332
  viewModel.data.provider,
24333
+ viewModel.selectedProviderTarget,
23849
24334
  viewModel.draftContent,
23850
24335
  viewModel.draftPrompt,
23851
24336
  viewModel.drainingQueuedPromptId,
@@ -23899,6 +24384,7 @@ var AgentGUIDetailPane = memo(function AgentGUIDetailPane2({
23899
24384
  sessionChrome.auth?.message ?? "",
23900
24385
  sessionChrome.recovery?.kind ?? "",
23901
24386
  sessionChrome.recovery?.message ?? "",
24387
+ backgroundAgentStatusText ?? "",
23902
24388
  viewModel.queuedPrompts.map((prompt) => prompt.id).join(","),
23903
24389
  viewModel.drainingQueuedPromptId ?? "",
23904
24390
  viewModel.isRespondingApproval ? "1" : "0"
@@ -24380,8 +24866,8 @@ var AgentGUIBottomDockPane = memo(function AgentGUIBottomDockPane2({
24380
24866
  const goal = objectRecord(sessionChrome.rawState?.runtimeContext?.goal);
24381
24867
  const goalObjective = goal ? stringValue2(goal.objective) : "";
24382
24868
  const goalStatus = goal ? stringValue2(goal.status) : "";
24383
- const goalTokenBudget = goal ? numberValue(goal.tokenBudget) : null;
24384
- const goalTokensUsed = goal ? numberValue(goal.tokensUsed) : null;
24869
+ const goalTokenBudget = goal ? numberValue2(goal.tokenBudget) : null;
24870
+ const goalTokensUsed = goal ? numberValue2(goal.tokensUsed) : null;
24385
24871
  const showGoalBanner = isGoalBannerVisible(goalObjective, goalStatus);
24386
24872
  return /* @__PURE__ */ jsxs17(
24387
24873
  "div",
@@ -24478,16 +24964,14 @@ function syncAgentGUIConversationRailStore(store, next) {
24478
24964
  Object.assign(store, next);
24479
24965
  }
24480
24966
  function agentGUIConversationRailStoreSnapshotsEqual(current, next) {
24481
- return current.activeConversationId === next.activeConversationId && current.pendingDeleteConversationId === next.pendingDeleteConversationId && current.isLoadingConversations === next.isLoadingConversations && current.isDeletingConversation === next.isDeletingConversation && current.isDeletingProjectConversations === next.isDeletingProjectConversations && current.labels === next.labels && current.workspaceUserProjectI18n === next.workspaceUserProjectI18n && current.uiLanguage === next.uiLanguage && current.previewMode === next.previewMode && current.createConversationDisabled === next.createConversationDisabled && current.openclawGateway === next.openclawGateway && current.isCollapsed === next.isCollapsed && current.onCreateConversation === next.onCreateConversation && current.onOpenAgentEnvSetup === next.onOpenAgentEnvSetup && current.onRetryOpenclawGateway === next.onRetryOpenclawGateway && current.onSelectConversation === next.onSelectConversation && current.onToggleConversationPinned === next.onToggleConversationPinned && current.onOpenProjectFiles === next.onOpenProjectFiles && current.onOpenConversationWindow === next.onOpenConversationWindow && current.selectProjectDirectory === next.selectProjectDirectory && current.onRemoveProject === next.onRemoveProject && current.onConfirmDeleteProjectConversations === next.onConfirmDeleteProjectConversations && current.onRequestDeleteConversation === next.onRequestDeleteConversation && current.onCancelDeleteConversation === next.onCancelDeleteConversation && current.onConfirmDeleteConversation === next.onConfirmDeleteConversation;
24967
+ return current.activeConversationId === next.activeConversationId && current.pendingDeleteConversationId === next.pendingDeleteConversationId && current.isLoadingConversations === next.isLoadingConversations && current.isDeletingConversation === next.isDeletingConversation && current.isDeletingProjectConversations === next.isDeletingProjectConversations && current.labels === next.labels && current.workspaceUserProjectI18n === next.workspaceUserProjectI18n && current.uiLanguage === next.uiLanguage && current.previewMode === next.previewMode && current.createConversationDisabled === next.createConversationDisabled && current.openclawGateway === next.openclawGateway && current.isCollapsed === next.isCollapsed && current.selectedProviderTarget === next.selectedProviderTarget && current.providerTargets === next.providerTargets && current.providerTargetsLoading === next.providerTargetsLoading && current.conversationScope === next.conversationScope && current.conversationFilter === next.conversationFilter && current.onUpdateConversationFilter === next.onUpdateConversationFilter && current.onSelectConversationFilterTarget === next.onSelectConversationFilterTarget && current.onCreateConversation === next.onCreateConversation && current.onOpenAgentEnvSetup === next.onOpenAgentEnvSetup && current.onRetryOpenclawGateway === next.onRetryOpenclawGateway && current.onSelectConversation === next.onSelectConversation && current.onToggleConversationPinned === next.onToggleConversationPinned && current.onOpenProjectFiles === next.onOpenProjectFiles && current.onOpenConversationWindow === next.onOpenConversationWindow && current.selectProjectDirectory === next.selectProjectDirectory && current.onRemoveProject === next.onRemoveProject && current.onConfirmDeleteProjectConversations === next.onConfirmDeleteProjectConversations && current.onRequestDeleteConversation === next.onRequestDeleteConversation && current.onCancelDeleteConversation === next.onCancelDeleteConversation && current.onConfirmDeleteConversation === next.onConfirmDeleteConversation;
24482
24968
  }
24483
24969
  var AgentGUIConversationRailStorePane = memo(
24484
24970
  function AgentGUIConversationRailStorePane2({
24485
24971
  conversations,
24486
- provider,
24487
24972
  store,
24488
24973
  storeState: _storeState,
24489
- userProjects,
24490
- workspaceId
24974
+ userProjects
24491
24975
  }) {
24492
24976
  "use memo";
24493
24977
  const state = useSnapshot(store);
@@ -24496,9 +24980,7 @@ var AgentGUIConversationRailStorePane = memo(
24496
24980
  {
24497
24981
  ...state,
24498
24982
  conversations,
24499
- provider,
24500
- userProjects,
24501
- workspaceId
24983
+ userProjects
24502
24984
  }
24503
24985
  );
24504
24986
  }
@@ -24510,47 +24992,6 @@ function normalizeConversationRailProjectPath(path) {
24510
24992
  }
24511
24993
  return normalized.replace(/\/+$/, "") || "/";
24512
24994
  }
24513
- function buildRailSessionGroupProjects({
24514
- groups,
24515
- userProjects
24516
- }) {
24517
- const userProjectByPath = new Map(
24518
- userProjects.map((project) => [
24519
- normalizeConversationRailProjectPath(project.path),
24520
- project
24521
- ])
24522
- );
24523
- const groupProjectPaths = /* @__PURE__ */ new Set();
24524
- const groupProjects = [];
24525
- for (const group of groups) {
24526
- const normalizedPath = normalizeConversationRailProjectPath(group.cwd);
24527
- if (!normalizedPath || groupProjectPaths.has(normalizedPath)) {
24528
- continue;
24529
- }
24530
- groupProjectPaths.add(normalizedPath);
24531
- const existingProject = userProjectByPath.get(normalizedPath);
24532
- groupProjects.push({
24533
- ...existingProject ?? {
24534
- id: `agent-session-group:${normalizedPath}`,
24535
- label: labelFromProjectPath(normalizedPath),
24536
- path: group.cwd
24537
- },
24538
- lastUsedAtUnixMs: group.latestSessionUpdatedAtUnixMs,
24539
- updatedAtUnixMs: group.latestSessionUpdatedAtUnixMs
24540
- });
24541
- }
24542
- const emptyUserProjects = userProjects.filter(
24543
- (project) => !groupProjectPaths.has(normalizeConversationRailProjectPath(project.path))
24544
- );
24545
- return [...groupProjects, ...emptyUserProjects];
24546
- }
24547
- function labelFromProjectPath(path) {
24548
- const normalized = normalizeConversationRailProjectPath(path);
24549
- if (!normalized || normalized === "/") {
24550
- return path || "/";
24551
- }
24552
- return normalized.split("/").filter(Boolean).at(-1) ?? normalized;
24553
- }
24554
24995
  function stabilizeConversationSections(previous, next) {
24555
24996
  if (!previous) {
24556
24997
  return [...next];
@@ -24584,37 +25025,6 @@ function stabilizeConversationSections(previous, next) {
24584
25025
  });
24585
25026
  return changed ? stable : previous;
24586
25027
  }
24587
- function mergeRefreshedRailSessionGroups(current, refreshed) {
24588
- const currentByCwd = new Map(current.map((group) => [group.cwd, group]));
24589
- return refreshed.map((group) => {
24590
- const existing = currentByCwd.get(group.cwd);
24591
- if (!existing || existing.sessions.length <= group.sessions.length) {
24592
- return group;
24593
- }
24594
- const sessionIds = new Set(
24595
- group.sessions.map((session) => session.agentSessionId)
24596
- );
24597
- const sessions = [...group.sessions];
24598
- for (const session of existing.sessions) {
24599
- if (sessions.length >= group.sessionCount) {
24600
- break;
24601
- }
24602
- if (sessionIds.has(session.agentSessionId)) {
24603
- continue;
24604
- }
24605
- sessionIds.add(session.agentSessionId);
24606
- sessions.push(session);
24607
- }
24608
- const preservedLoadedPages = sessions.length > group.sessions.length;
24609
- const hasMore = preservedLoadedPages ? existing.hasMore && sessions.length < group.sessionCount : group.hasMore;
24610
- return {
24611
- ...group,
24612
- hasMore,
24613
- nextCursor: hasMore ? preservedLoadedPages ? existing.nextCursor : group.nextCursor : void 0,
24614
- sessions
24615
- };
24616
- });
24617
- }
24618
25028
  function stabilizeConversationSectionItems(previous, next) {
24619
25029
  if (previous.length !== next.length) {
24620
25030
  const previousById = /* @__PURE__ */ new Map();
@@ -24651,11 +25061,163 @@ function conversationSyncStatesRenderEqual(left, right) {
24651
25061
  function conversationProjectsRenderEqual2(left, right) {
24652
25062
  return left === right || (!left || !right ? !left && !right : left.id === right.id && left.path === right.path && left.label === right.label && left.createdAtUnixMs === right.createdAtUnixMs && left.updatedAtUnixMs === right.updatedAtUnixMs && left.lastUsedAtUnixMs === right.lastUsedAtUnixMs);
24653
25063
  }
25064
+ var agentGUIProviderRailOrder = [
25065
+ "nexight",
25066
+ "claude-code",
25067
+ "codex",
25068
+ "openclaw",
25069
+ "hermes",
25070
+ "gemini"
25071
+ ];
25072
+ function agentGUIProviderRailOrderIndex(provider) {
25073
+ const index = agentGUIProviderRailOrder.indexOf(provider);
25074
+ return index < 0 ? agentGUIProviderRailOrder.length : index;
25075
+ }
25076
+ function agentGUIProviderRailLabel(provider, targetLabel, labels) {
25077
+ if (targetLabel.trim() && targetLabel !== provider) {
25078
+ return targetLabel;
25079
+ }
25080
+ if (provider === "codex") {
25081
+ return labels.conversationFilterCodex;
25082
+ }
25083
+ if (provider === "claude-code") {
25084
+ return labels.conversationFilterClaudeCode;
25085
+ }
25086
+ return targetLabel;
25087
+ }
25088
+ function agentGUIProviderTargetMatchesConversationFilter(target, filter) {
25089
+ return filter.kind === "agentTarget" && (target.agentTargetId?.trim() ?? "") === filter.agentTargetId;
25090
+ }
25091
+ var AgentGUIProviderRail = memo(function AgentGUIProviderRail2({
25092
+ conversationFilter,
25093
+ labels,
25094
+ previewMode,
25095
+ providerTargets,
25096
+ providerTargetsLoading,
25097
+ onSelectConversationFilterTarget,
25098
+ onUpdateConversationFilter
25099
+ }) {
25100
+ "use memo";
25101
+ const providerTiles = useMemo10(() => {
25102
+ const enabledTargets = providerTargets.filter(
25103
+ (target) => target.disabled !== true
25104
+ );
25105
+ const targets = [...enabledTargets];
25106
+ const originalIndexByTarget = /* @__PURE__ */ new Map();
25107
+ targets.forEach((target, index) => {
25108
+ originalIndexByTarget.set(
25109
+ `${target.provider}\0${target.targetId}`,
25110
+ index
25111
+ );
25112
+ });
25113
+ return targets.sort((left, right) => {
25114
+ const orderDelta = agentGUIProviderRailOrderIndex(left.provider) - agentGUIProviderRailOrderIndex(right.provider);
25115
+ if (orderDelta !== 0) {
25116
+ return orderDelta;
25117
+ }
25118
+ return (originalIndexByTarget.get(`${left.provider}\0${left.targetId}`) ?? 0) - (originalIndexByTarget.get(
25119
+ `${right.provider}\0${right.targetId}`
25120
+ ) ?? 0);
25121
+ });
25122
+ }, [providerTargets]);
25123
+ const allTileSelected = conversationFilter.kind === "all";
25124
+ const selectAllProviders = useCallback10(() => {
25125
+ onUpdateConversationFilter({ kind: "all" });
25126
+ }, [onUpdateConversationFilter]);
25127
+ const selectProviderTile = useCallback10(
25128
+ (target) => {
25129
+ onSelectConversationFilterTarget({
25130
+ provider: target.provider,
25131
+ providerTargetId: target.targetId
25132
+ });
25133
+ },
25134
+ [onSelectConversationFilterTarget]
25135
+ );
25136
+ return /* @__PURE__ */ jsxs17(
25137
+ "div",
25138
+ {
25139
+ className: AgentGUINode_styles_default.providerRail,
25140
+ role: "tablist",
25141
+ "aria-label": labels.providerSwitchLabel,
25142
+ "aria-busy": providerTargetsLoading,
25143
+ children: [
25144
+ /* @__PURE__ */ jsxs17(
25145
+ "button",
25146
+ {
25147
+ type: "button",
25148
+ role: "tab",
25149
+ "aria-selected": allTileSelected,
25150
+ className: AgentGUINode_styles_default.providerRailTile,
25151
+ "data-selected": allTileSelected ? "true" : "false",
25152
+ disabled: previewMode,
25153
+ onClick: selectAllProviders,
25154
+ children: [
25155
+ /* @__PURE__ */ jsx31("span", { className: AgentGUINode_styles_default.providerRailAvatar, children: /* @__PURE__ */ jsx31(LayoutGrid, { "aria-hidden": true, className: AgentGUINode_styles_default.providerRailAvatarIcon }) }),
25156
+ /* @__PURE__ */ jsx31("span", { className: AgentGUINode_styles_default.providerRailTileLabel, children: labels.conversationFilterAll })
25157
+ ]
25158
+ }
25159
+ ),
25160
+ providerTargetsLoading ? [0, 1, 2].map((index) => /* @__PURE__ */ jsxs17(
25161
+ "button",
25162
+ {
25163
+ type: "button",
25164
+ role: "tab",
25165
+ "aria-selected": "false",
25166
+ className: AgentGUINode_styles_default.providerRailTile,
25167
+ "data-loading": "true",
25168
+ "data-selected": "false",
25169
+ disabled: true,
25170
+ children: [
25171
+ /* @__PURE__ */ jsx31("span", { "aria-hidden": "true", className: AgentGUINode_styles_default.providerRailAvatar }),
25172
+ /* @__PURE__ */ jsx31(
25173
+ "span",
25174
+ {
25175
+ "aria-hidden": "true",
25176
+ className: AgentGUINode_styles_default.providerRailTileLabel
25177
+ }
25178
+ )
25179
+ ]
25180
+ },
25181
+ `provider-target-loading-${index}`
25182
+ )) : null,
25183
+ providerTiles.map((target) => {
25184
+ const providerSelected = agentGUIProviderTargetMatchesConversationFilter(
25185
+ target,
25186
+ conversationFilter
25187
+ );
25188
+ return /* @__PURE__ */ jsxs17(
25189
+ "button",
25190
+ {
25191
+ type: "button",
25192
+ role: "tab",
25193
+ "aria-selected": providerSelected,
25194
+ className: AgentGUINode_styles_default.providerRailTile,
25195
+ "data-selected": providerSelected ? "true" : "false",
25196
+ disabled: previewMode,
25197
+ onClick: () => selectProviderTile(target),
25198
+ children: [
25199
+ /* @__PURE__ */ jsx31("span", { className: AgentGUINode_styles_default.providerRailAvatar, children: /* @__PURE__ */ jsx31(
25200
+ "img",
25201
+ {
25202
+ alt: "",
25203
+ "aria-hidden": "true",
25204
+ className: AgentGUINode_styles_default.providerRailAvatarImage,
25205
+ src: target.iconUrl || resolveAgentGUIHeroIconUrl(target.provider)
25206
+ }
25207
+ ) }),
25208
+ /* @__PURE__ */ jsx31("span", { className: AgentGUINode_styles_default.providerRailTileLabel, children: agentGUIProviderRailLabel(target.provider, target.label, labels) })
25209
+ ]
25210
+ },
25211
+ `${target.provider}:${target.targetId}`
25212
+ );
25213
+ })
25214
+ ]
25215
+ }
25216
+ );
25217
+ });
24654
25218
  var AgentGUIConversationRailPane = memo(
24655
25219
  function AgentGUIConversationRailPane2({
24656
25220
  conversations,
24657
- provider,
24658
- workspaceId,
24659
25221
  userProjects,
24660
25222
  activeConversationId,
24661
25223
  pendingDeleteConversationId,
@@ -24670,6 +25232,12 @@ var AgentGUIConversationRailPane = memo(
24670
25232
  openclawGateway,
24671
25233
  isCollapsed,
24672
25234
  slashStatusLimits,
25235
+ providerTargets,
25236
+ providerTargetsLoading,
25237
+ conversationScope,
25238
+ conversationFilter,
25239
+ onUpdateConversationFilter,
25240
+ onSelectConversationFilterTarget,
24673
25241
  onCreateConversation,
24674
25242
  onOpenAgentEnvSetup,
24675
25243
  onRetryOpenclawGateway,
@@ -24686,21 +25254,14 @@ var AgentGUIConversationRailPane = memo(
24686
25254
  onConfirmDeleteConversation
24687
25255
  }) {
24688
25256
  "use memo";
24689
- const agentActivityRuntime = useAgentActivityRuntime();
25257
+ const showProviderRail = conversationScope === "multi-provider";
24690
25258
  const [conversationQuery, setConversationQuery] = useState11("");
24691
- const [searchConversations, setSearchConversations] = useState11([]);
24692
- const [searchConversationQuery, setSearchConversationQuery] = useState11("");
24693
- const [searchHasMore, setSearchHasMore] = useState11(false);
24694
- const [searchNextCursor, setSearchNextCursor] = useState11(
24695
- null
25259
+ const updateConversationFilter = useStableEventCallback2(
25260
+ onUpdateConversationFilter
25261
+ );
25262
+ const selectConversationFilterTarget = useStableEventCallback2(
25263
+ onSelectConversationFilterTarget
24696
25264
  );
24697
- const [
24698
- isLoadingMoreSearchConversations,
24699
- setIsLoadingMoreSearchConversations
24700
- ] = useState11(false);
24701
- const [railSessionGroups, setRailSessionGroups] = useState11([]);
24702
- const [activeConversationOverlay, setActiveConversationOverlay] = useState11(null);
24703
- const [loadingMoreSectionIds, setLoadingMoreSectionIds] = useState11(() => /* @__PURE__ */ new Set());
24704
25265
  const [collapsedProjectSectionIds, setCollapsedProjectSectionIds] = useState11(() => /* @__PURE__ */ new Set());
24705
25266
  const [currentTimeMs, setCurrentTimeMs] = useState11(() => Date.now());
24706
25267
  const [pendingProjectAction, setPendingProjectAction] = useState11(null);
@@ -24710,7 +25271,6 @@ var AgentGUIConversationRailPane = memo(
24710
25271
  /* @__PURE__ */ new Map()
24711
25272
  );
24712
25273
  const groupedConversationsRef = useRef12(null);
24713
- const wasDeletingConversationRef = useRef12(false);
24714
25274
  useEffect12(() => {
24715
25275
  const timer = window.setInterval(() => {
24716
25276
  setCurrentTimeMs(Date.now());
@@ -24719,217 +25279,25 @@ var AgentGUIConversationRailPane = memo(
24719
25279
  window.clearInterval(timer);
24720
25280
  };
24721
25281
  }, []);
24722
- const trimmedConversationQuery = conversationQuery.trim();
24723
- const hasConversationQuery = trimmedConversationQuery.length > 0;
24724
- const hasRuntimeGroupSource = !previewMode && Boolean(agentActivityRuntime.listSessionGroups);
24725
- const conversationIdentityKey = useMemo10(
24726
- () => conversations.map((conversation) => conversation.id).join("|"),
24727
- [conversations]
24728
- );
24729
- const railSessionGroupProjects = useMemo10(
24730
- () => buildRailSessionGroupProjects({
24731
- groups: railSessionGroups,
24732
- userProjects
24733
- }),
24734
- [railSessionGroups, userProjects]
24735
- );
24736
- const defaultRailGroupConversations = useMemo10(() => {
24737
- const freshConversationById = new Map(
24738
- conversations.map((conversation) => [conversation.id, conversation])
24739
- );
24740
- return buildAgentGUIConversationSummaries({
24741
- provider,
24742
- snapshot: {
24743
- composerOptionsByProvider: {},
24744
- presences: [],
24745
- sessionMessagesById: {},
24746
- sessions: railSessionGroups.flatMap((group) => group.sessions),
24747
- workspaceId
24748
- },
24749
- userProjects: railSessionGroupProjects
24750
- }).map(
24751
- (conversation) => freshConversationById.get(conversation.id) ?? conversation
24752
- );
24753
- }, [
24754
- conversations,
24755
- provider,
24756
- railSessionGroupProjects,
24757
- railSessionGroups,
24758
- workspaceId
24759
- ]);
24760
- const defaultRailSourceConversations = useMemo10(() => {
24761
- const source = hasRuntimeGroupSource ? defaultRailGroupConversations : conversations;
24762
- if (!activeConversationOverlay || source.some((item) => item.id === activeConversationOverlay.id)) {
24763
- return source;
24764
- }
24765
- return [...source, activeConversationOverlay];
24766
- }, [
24767
- activeConversationOverlay,
24768
- conversations,
24769
- defaultRailGroupConversations,
24770
- hasRuntimeGroupSource
24771
- ]);
24772
- const effectiveSearchConversations = searchConversationQuery === trimmedConversationQuery ? searchConversations : [];
24773
- const railSourceConversations = hasConversationQuery ? effectiveSearchConversations : defaultRailSourceConversations;
24774
- const runtimeSearchSessions = agentActivityRuntime.searchSessions;
24775
- useEffect12(() => {
24776
- if (!activeConversationOverlay || activeConversationOverlay.id !== activeConversationId) {
24777
- return;
24778
- }
24779
- if (defaultRailGroupConversations.some(
24780
- (item) => item.id === activeConversationOverlay.id
24781
- )) {
24782
- setActiveConversationOverlay(null);
24783
- }
24784
- }, [
24785
- activeConversationId,
24786
- activeConversationOverlay,
24787
- defaultRailGroupConversations
24788
- ]);
24789
- useEffect12(() => {
24790
- if (!hasConversationQuery) {
24791
- setSearchConversationQuery("");
24792
- setSearchConversations([]);
24793
- setSearchHasMore(false);
24794
- setSearchNextCursor(null);
24795
- return;
24796
- }
24797
- if (!runtimeSearchSessions) {
24798
- return;
24799
- }
24800
- let disposed = false;
24801
- const timer = window.setTimeout(() => {
24802
- void runtimeSearchSessions({
24803
- limit: 100,
24804
- query: trimmedConversationQuery,
24805
- workspaceId
24806
- }).then((result) => {
24807
- if (disposed) {
24808
- return;
24809
- }
24810
- setSearchConversationQuery(trimmedConversationQuery);
24811
- setSearchConversations(
24812
- buildAgentGUIConversationSummaries({
24813
- provider,
24814
- snapshot: {
24815
- composerOptionsByProvider: {},
24816
- presences: [],
24817
- sessionMessagesById: {},
24818
- sessions: result.sessions,
24819
- workspaceId: result.workspaceId
24820
- },
24821
- userProjects
24822
- })
24823
- );
24824
- setSearchHasMore(result.hasMore);
24825
- setSearchNextCursor(result.nextCursor ?? null);
24826
- }).catch(() => {
24827
- if (!disposed) {
24828
- setSearchConversationQuery(trimmedConversationQuery);
24829
- setSearchConversations([]);
24830
- setSearchHasMore(false);
24831
- setSearchNextCursor(null);
24832
- }
24833
- });
24834
- }, 150);
24835
- return () => {
24836
- disposed = true;
24837
- window.clearTimeout(timer);
24838
- };
24839
- }, [
24840
- hasConversationQuery,
24841
- provider,
24842
- runtimeSearchSessions,
24843
- trimmedConversationQuery,
24844
- userProjects,
24845
- workspaceId
24846
- ]);
24847
- useEffect12(() => {
24848
- if (!hasConversationQuery || runtimeSearchSessions) {
24849
- return;
24850
- }
24851
- setSearchConversationQuery(trimmedConversationQuery);
24852
- setSearchConversations(
24853
- conversations.filter(
24854
- (candidate) => conversationPlainTitle(candidate, labels, uiLanguage).toLowerCase().includes(trimmedConversationQuery.toLowerCase())
24855
- )
24856
- );
24857
- setSearchHasMore(false);
24858
- setSearchNextCursor(null);
24859
- }, [
24860
- conversations,
24861
- hasConversationQuery,
24862
- labels,
24863
- runtimeSearchSessions,
24864
- trimmedConversationQuery,
24865
- uiLanguage
24866
- ]);
24867
- useEffect12(() => {
24868
- if (!agentActivityRuntime.listSessionGroups || previewMode) {
24869
- setRailSessionGroups([]);
24870
- return;
24871
- }
24872
- let disposed = false;
24873
- const isDeletingNow = isDeletingConversation || isDeletingProjectConversations;
24874
- const resetLoadedGroups = wasDeletingConversationRef.current && !isDeletingNow;
24875
- wasDeletingConversationRef.current = isDeletingNow;
24876
- void agentActivityRuntime.listSessionGroups({
24877
- sessionLimit: AGENT_GUI_CONVERSATION_RAIL_SECTION_PAGE_SIZE,
24878
- visibleOnly: true,
24879
- workspaceId
24880
- }).then((result) => {
24881
- if (!disposed) {
24882
- setRailSessionGroups(
24883
- (current) => resetLoadedGroups ? result.groups : mergeRefreshedRailSessionGroups(current, result.groups)
24884
- );
24885
- }
24886
- }).catch(() => {
24887
- if (!disposed) {
24888
- setRailSessionGroups([]);
24889
- }
24890
- });
24891
- return () => {
24892
- disposed = true;
24893
- };
24894
- }, [
24895
- agentActivityRuntime,
24896
- conversationIdentityKey,
24897
- isDeletingConversation,
24898
- isDeletingProjectConversations,
24899
- previewMode,
24900
- workspaceId
24901
- ]);
24902
- const groupingProjects = hasConversationQuery ? [] : hasRuntimeGroupSource ? railSessionGroupProjects : userProjects;
24903
- const showEmptyConversationSection = useMemo10(
24904
- () => !hasConversationQuery && (hasRuntimeGroupSource ? railSessionGroups.some((group) => !group.cwd.trim()) : !conversations.some(
24905
- (conversation) => conversation.project == null
24906
- )),
24907
- [
24908
- conversations,
24909
- hasConversationQuery,
24910
- hasRuntimeGroupSource,
24911
- railSessionGroups
24912
- ]
24913
- );
24914
25282
  const filteredConversationResult = useMemo10(() => {
24915
25283
  const startedAtMs = agentGuiPerfNowMs();
24916
- const query = trimmedConversationQuery.toLowerCase();
24917
- const items = !query ? railSourceConversations : railSourceConversations.filter(
25284
+ const query = conversationQuery.trim().toLowerCase();
25285
+ const items = !query ? conversations : conversations.filter(
24918
25286
  (candidate) => conversationPlainTitle(candidate, labels, uiLanguage).toLowerCase().includes(query)
24919
25287
  );
24920
25288
  return {
24921
25289
  items,
24922
25290
  filterMs: roundAgentGuiPerfMs(agentGuiPerfNowMs() - startedAtMs)
24923
25291
  };
24924
- }, [labels, railSourceConversations, trimmedConversationQuery, uiLanguage]);
25292
+ }, [conversationQuery, conversations, labels, uiLanguage]);
24925
25293
  const filteredConversations = filteredConversationResult.items;
24926
25294
  const groupedConversationResult = useMemo10(() => {
24927
25295
  const startedAtMs = agentGuiPerfNowMs();
24928
25296
  const rawGroups = groupConversations(
24929
25297
  filteredConversations,
24930
25298
  labels,
24931
- groupingProjects,
24932
- { includeEmptyConversations: showEmptyConversationSection }
25299
+ conversationQuery.trim() ? [] : userProjects,
25300
+ { includeEmptyConversations: !conversationQuery.trim() }
24933
25301
  );
24934
25302
  const groups = stabilizeConversationSections(
24935
25303
  groupedConversationsRef.current,
@@ -24940,12 +25308,7 @@ var AgentGUIConversationRailPane = memo(
24940
25308
  groups,
24941
25309
  groupMs: roundAgentGuiPerfMs(agentGuiPerfNowMs() - startedAtMs)
24942
25310
  };
24943
- }, [
24944
- filteredConversations,
24945
- groupingProjects,
24946
- labels,
24947
- showEmptyConversationSection
24948
- ]);
25311
+ }, [conversationQuery, filteredConversations, labels, userProjects]);
24949
25312
  const groupedConversations = groupedConversationResult.groups;
24950
25313
  const toggleProjectSectionCollapsed = useCallback10((sectionId) => {
24951
25314
  setCollapsedProjectSectionIds((current) => {
@@ -24966,140 +25329,17 @@ var AgentGUIConversationRailPane = memo(
24966
25329
  );
24967
25330
  const projectConversationCountsByPath = useMemo10(() => {
24968
25331
  const counts = /* @__PURE__ */ new Map();
24969
- const pathsFromGroups = /* @__PURE__ */ new Set();
24970
- for (const group of railSessionGroups) {
24971
- const normalizedPath = normalizeConversationRailProjectPath(group.cwd);
24972
- if (!normalizedPath) {
24973
- continue;
24974
- }
24975
- counts.set(normalizedPath, group.sessionCount);
24976
- pathsFromGroups.add(normalizedPath);
24977
- }
24978
25332
  for (const conversation of conversations) {
24979
25333
  const normalizedPath = normalizeConversationRailProjectPath(
24980
25334
  conversation.project?.path
24981
25335
  );
24982
- if (!normalizedPath || pathsFromGroups.has(normalizedPath)) {
25336
+ if (!normalizedPath) {
24983
25337
  continue;
24984
25338
  }
24985
25339
  counts.set(normalizedPath, (counts.get(normalizedPath) ?? 0) + 1);
24986
25340
  }
24987
25341
  return counts;
24988
- }, [conversations, railSessionGroups]);
24989
- const railSessionGroupBySectionId = useMemo10(() => {
24990
- const groupsBySectionId = /* @__PURE__ */ new Map();
24991
- for (const group of railSessionGroups) {
24992
- const normalizedPath = normalizeConversationRailProjectPath(group.cwd);
24993
- groupsBySectionId.set(
24994
- normalizedPath ? `project:${normalizedPath}` : "conversations",
24995
- group
24996
- );
24997
- }
24998
- return groupsBySectionId;
24999
- }, [railSessionGroups]);
25000
- const loadMoreSectionConversations = useCallback10(
25001
- (sectionId) => {
25002
- const group = railSessionGroupBySectionId.get(sectionId);
25003
- const listSessionsPage = agentActivityRuntime.listSessionsPage;
25004
- if (!group?.hasMore || !group.nextCursor || !listSessionsPage) {
25005
- return;
25006
- }
25007
- setLoadingMoreSectionIds((current) => {
25008
- if (current.has(sectionId)) {
25009
- return current;
25010
- }
25011
- const next = new Set(current);
25012
- next.add(sectionId);
25013
- return next;
25014
- });
25015
- void listSessionsPage({
25016
- cursor: group.nextCursor,
25017
- cwd: group.cwd,
25018
- limit: AGENT_GUI_CONVERSATION_RAIL_SECTION_PAGE_SIZE,
25019
- visibleOnly: true,
25020
- workspaceId
25021
- }).then((page) => {
25022
- setRailSessionGroups(
25023
- (current) => current.map((candidate) => {
25024
- if (candidate.cwd !== group.cwd) {
25025
- return candidate;
25026
- }
25027
- const sessionIds = new Set(
25028
- candidate.sessions.map((session) => session.agentSessionId)
25029
- );
25030
- const nextSessions = [...candidate.sessions];
25031
- for (const session of page.sessions) {
25032
- if (!sessionIds.has(session.agentSessionId)) {
25033
- sessionIds.add(session.agentSessionId);
25034
- nextSessions.push(session);
25035
- }
25036
- }
25037
- return {
25038
- ...candidate,
25039
- hasMore: page.hasMore,
25040
- nextCursor: page.nextCursor,
25041
- sessions: nextSessions
25042
- };
25043
- })
25044
- );
25045
- }).finally(() => {
25046
- setLoadingMoreSectionIds((current) => {
25047
- if (!current.has(sectionId)) {
25048
- return current;
25049
- }
25050
- const next = new Set(current);
25051
- next.delete(sectionId);
25052
- return next;
25053
- });
25054
- });
25055
- },
25056
- [agentActivityRuntime, railSessionGroupBySectionId, workspaceId]
25057
- );
25058
- const loadMoreSearchConversations = useCallback10(() => {
25059
- const searchSessions = agentActivityRuntime.searchSessions;
25060
- if (!searchSessions || !searchHasMore || !searchNextCursor || isLoadingMoreSearchConversations) {
25061
- return;
25062
- }
25063
- setIsLoadingMoreSearchConversations(true);
25064
- void searchSessions({
25065
- cursor: searchNextCursor,
25066
- limit: 100,
25067
- query: trimmedConversationQuery,
25068
- workspaceId
25069
- }).then((result) => {
25070
- const nextConversations = buildAgentGUIConversationSummaries({
25071
- provider,
25072
- snapshot: {
25073
- composerOptionsByProvider: {},
25074
- presences: [],
25075
- sessionMessagesById: {},
25076
- sessions: result.sessions,
25077
- workspaceId: result.workspaceId
25078
- },
25079
- userProjects
25080
- });
25081
- setSearchConversations((current) => {
25082
- const currentIds = new Set(current.map((item) => item.id));
25083
- return [
25084
- ...current,
25085
- ...nextConversations.filter((item) => !currentIds.has(item.id))
25086
- ];
25087
- });
25088
- setSearchHasMore(result.hasMore);
25089
- setSearchNextCursor(result.nextCursor ?? null);
25090
- }).finally(() => {
25091
- setIsLoadingMoreSearchConversations(false);
25092
- });
25093
- }, [
25094
- agentActivityRuntime,
25095
- isLoadingMoreSearchConversations,
25096
- provider,
25097
- searchHasMore,
25098
- searchNextCursor,
25099
- trimmedConversationQuery,
25100
- userProjects,
25101
- workspaceId
25102
- ]);
25342
+ }, [conversations]);
25103
25343
  const registerConversationItemElement = useCallback10(
25104
25344
  (itemId, element) => {
25105
25345
  if (element) {
@@ -25110,46 +25350,6 @@ var AgentGUIConversationRailPane = memo(
25110
25350
  },
25111
25351
  []
25112
25352
  );
25113
- const handleSelectConversation = useCallback10(
25114
- (agentSessionId) => {
25115
- const normalizedAgentSessionId = agentSessionId.trim();
25116
- if (!normalizedAgentSessionId) {
25117
- return;
25118
- }
25119
- const isLoadedConversation = conversations.some(
25120
- (conversation) => conversation.id === normalizedAgentSessionId
25121
- );
25122
- if (!hasConversationQuery || isLoadedConversation) {
25123
- onSelectConversation(normalizedAgentSessionId);
25124
- return;
25125
- }
25126
- void agentActivityRuntime.getSession(workspaceId, normalizedAgentSessionId).then((session) => {
25127
- const [overlay] = buildAgentGUIConversationSummaries({
25128
- provider,
25129
- snapshot: {
25130
- composerOptionsByProvider: {},
25131
- presences: [],
25132
- sessionMessagesById: {},
25133
- sessions: [session],
25134
- workspaceId
25135
- },
25136
- userProjects: railSessionGroupProjects
25137
- });
25138
- setActiveConversationOverlay(overlay ?? null);
25139
- onSelectConversation(normalizedAgentSessionId);
25140
- }).catch(() => {
25141
- });
25142
- },
25143
- [
25144
- agentActivityRuntime,
25145
- conversations,
25146
- hasConversationQuery,
25147
- onSelectConversation,
25148
- provider,
25149
- railSessionGroupProjects,
25150
- workspaceId
25151
- ]
25152
- );
25153
25353
  useLayoutEffect4(() => {
25154
25354
  if (!activeConversationId) {
25155
25355
  return;
@@ -25189,6 +25389,18 @@ var AgentGUIConversationRailPane = memo(
25189
25389
  }
25190
25390
  )
25191
25391
  ] }),
25392
+ showProviderRail ? /* @__PURE__ */ jsx31(
25393
+ AgentGUIProviderRail,
25394
+ {
25395
+ conversationFilter,
25396
+ labels,
25397
+ previewMode,
25398
+ providerTargets,
25399
+ providerTargetsLoading,
25400
+ onSelectConversationFilterTarget: selectConversationFilterTarget,
25401
+ onUpdateConversationFilter: updateConversationFilter
25402
+ }
25403
+ ) : null,
25192
25404
  openclawGateway?.status === "starting" ? /* @__PURE__ */ jsxs17("div", { className: AgentGUINode_styles_default.gatewayStatus, "data-state": "starting", children: [
25193
25405
  /* @__PURE__ */ jsx31(
25194
25406
  StatusDot,
@@ -25232,9 +25444,6 @@ var AgentGUIConversationRailPane = memo(
25232
25444
  const showProjectRailHeader = !conversationQuery.trim() && section.kind !== "pinned" && (sectionIndex === 0 || groupedConversations[sectionIndex - 1]?.kind === "pinned");
25233
25445
  const isSectionCollapsed = isProjectSection && collapsedProjectSectionIds.has(section.id);
25234
25446
  const projectConversationCount = normalizedProjectPath ? projectConversationCountsByPath.get(normalizedProjectPath) ?? 0 : 0;
25235
- const sectionSessionGroup = railSessionGroupBySectionId.get(
25236
- section.id
25237
- );
25238
25447
  return /* @__PURE__ */ jsxs17(Fragment7, { children: [
25239
25448
  showProjectRailHeader ? /* @__PURE__ */ jsx31(
25240
25449
  AgentGUIProjectRailHeader,
@@ -25251,13 +25460,11 @@ var AgentGUIConversationRailPane = memo(
25251
25460
  createConversationDisabled,
25252
25461
  currentTimeMs,
25253
25462
  isDeletingConversation,
25254
- isLoadingMoreConversations: hasConversationQuery ? isLoadingMoreSearchConversations : loadingMoreSectionIds.has(section.id),
25255
25463
  isSectionCollapsed,
25256
25464
  labels,
25257
25465
  pendingDeleteConversationId,
25258
25466
  previewMode,
25259
25467
  projectConversationCount,
25260
- sectionHasMore: hasConversationQuery ? searchHasMore : Boolean(sectionSessionGroup?.hasMore),
25261
25468
  projectLabel,
25262
25469
  projectPath,
25263
25470
  registerItemElement: registerConversationItemElement,
@@ -25267,12 +25474,11 @@ var AgentGUIConversationRailPane = memo(
25267
25474
  onConfirmDeleteConversation,
25268
25475
  onCreateConversation,
25269
25476
  onRequestDeleteConversation,
25270
- onSelectConversation: handleSelectConversation,
25477
+ onSelectConversation,
25271
25478
  setPendingProjectAction,
25272
25479
  onToggleConversationPinned,
25273
25480
  onOpenProjectFiles,
25274
25481
  onOpenConversationWindow,
25275
- onLoadMoreConversations: hasConversationQuery ? loadMoreSearchConversations : loadMoreSectionConversations,
25276
25482
  onToggleProjectSectionCollapsed: toggleProjectSectionCollapsed
25277
25483
  }
25278
25484
  )
@@ -25402,8 +25608,6 @@ var AgentGUIConversationRailSection = memo(
25402
25608
  pendingDeleteConversationId,
25403
25609
  previewMode,
25404
25610
  isDeletingConversation,
25405
- isLoadingMoreConversations,
25406
- sectionHasMore,
25407
25611
  createConversationDisabled,
25408
25612
  currentTimeMs,
25409
25613
  labels,
@@ -25412,7 +25616,6 @@ var AgentGUIConversationRailSection = memo(
25412
25616
  onCreateConversation,
25413
25617
  onToggleProjectSectionCollapsed,
25414
25618
  onSelectConversation,
25415
- onLoadMoreConversations,
25416
25619
  setPendingProjectAction,
25417
25620
  onToggleConversationPinned,
25418
25621
  onOpenProjectFiles,
@@ -25428,29 +25631,16 @@ var AgentGUIConversationRailSection = memo(
25428
25631
  );
25429
25632
  const visibleItemCount = isSectionCollapsed ? 0 : Math.min(visibleItemLimit, section.items.length);
25430
25633
  const visibleItems = isSectionCollapsed ? [] : section.items.slice(0, visibleItemCount);
25431
- const canShowMore = !isSectionCollapsed && (visibleItemCount < section.items.length || sectionHasMore);
25634
+ const canShowMore = !isSectionCollapsed && visibleItemCount < section.items.length;
25432
25635
  const canShowLess = !isSectionCollapsed && visibleItemCount > AGENT_GUI_CONVERSATION_RAIL_SECTION_PAGE_SIZE;
25433
25636
  const showMoreConversations = useCallback10(() => {
25434
- if (visibleItemCount >= section.items.length && sectionHasMore) {
25435
- onLoadMoreConversations(section.id);
25436
- setVisibleItemLimit(
25437
- (current) => current + AGENT_GUI_CONVERSATION_RAIL_SECTION_PAGE_SIZE
25438
- );
25439
- return;
25440
- }
25441
25637
  setVisibleItemLimit(
25442
25638
  (current) => Math.min(
25443
25639
  section.items.length,
25444
25640
  current + AGENT_GUI_CONVERSATION_RAIL_SECTION_PAGE_SIZE
25445
25641
  )
25446
25642
  );
25447
- }, [
25448
- onLoadMoreConversations,
25449
- section.id,
25450
- section.items.length,
25451
- sectionHasMore,
25452
- visibleItemCount
25453
- ]);
25643
+ }, [section.items.length]);
25454
25644
  const showLessConversations = useCallback10(() => {
25455
25645
  setVisibleItemLimit(AGENT_GUI_CONVERSATION_RAIL_SECTION_PAGE_SIZE);
25456
25646
  }, []);
@@ -25743,7 +25933,6 @@ var AgentGUIConversationRailSection = memo(
25743
25933
  {
25744
25934
  type: "button",
25745
25935
  className: AgentGUINode_styles_default.conversationSectionPaginationButton,
25746
- disabled: isLoadingMoreConversations,
25747
25936
  onClick: showMoreConversations,
25748
25937
  children: labels.showMoreConversations
25749
25938
  }
@@ -26196,6 +26385,10 @@ function formatQuotaPrimaryLine(row, t) {
26196
26385
  }
26197
26386
  function appendDockProbeUsageLines(probe, lines, isLoadingUsage, t) {
26198
26387
  if (probe.lastError?.code === "unsupported") {
26388
+ lines.push({
26389
+ label: t("agentHost.workspaceAgentProbeDetailQuota"),
26390
+ primary: t("agentHost.workspaceAgentProbeUsageUnsupported")
26391
+ });
26199
26392
  return;
26200
26393
  }
26201
26394
  if (isLoadingUsage && !probe.usage) {
@@ -26204,6 +26397,12 @@ function appendDockProbeUsageLines(probe, lines, isLoadingUsage, t) {
26204
26397
  }
26205
26398
  const quotas = probe.usage?.quotas ?? [];
26206
26399
  if (quotas.length === 0) {
26400
+ if (probe.usage) {
26401
+ lines.push({
26402
+ label: t("agentHost.workspaceAgentProbeDetailQuota"),
26403
+ primary: t("agentHost.workspaceAgentProbeUsageUnsupported")
26404
+ });
26405
+ }
26207
26406
  return;
26208
26407
  }
26209
26408
  const rows = buildCompactDisplayQuotas(quotas, t);
@@ -26644,11 +26843,11 @@ function slashStatusQuotasFromRuntimeUsage(value) {
26644
26843
  return null;
26645
26844
  }
26646
26845
  const normalized = { quotaType };
26647
- const percentRemaining = numberValue2(record.percentRemaining);
26846
+ const percentRemaining = numberValue3(record.percentRemaining);
26648
26847
  if (percentRemaining !== null) {
26649
26848
  normalized.percentRemaining = percentRemaining;
26650
26849
  }
26651
- const resetsAtUnixMs = numberValue2(record.resetsAtUnixMs);
26850
+ const resetsAtUnixMs = numberValue3(record.resetsAtUnixMs);
26652
26851
  if (resetsAtUnixMs !== null) {
26653
26852
  normalized.resetsAtUnixMs = resetsAtUnixMs;
26654
26853
  }
@@ -26656,7 +26855,7 @@ function slashStatusQuotasFromRuntimeUsage(value) {
26656
26855
  if (resetText) {
26657
26856
  normalized.resetText = resetText;
26658
26857
  }
26659
- const dollarRemaining = numberValue2(record.dollarRemaining);
26858
+ const dollarRemaining = numberValue3(record.dollarRemaining);
26660
26859
  if (dollarRemaining !== null) {
26661
26860
  normalized.dollarRemaining = dollarRemaining;
26662
26861
  }
@@ -26683,7 +26882,7 @@ function agentUsageQuotaTypeValue(value) {
26683
26882
  function objectRecord2(value) {
26684
26883
  return value && typeof value === "object" ? value : null;
26685
26884
  }
26686
- function numberValue2(value) {
26885
+ function numberValue3(value) {
26687
26886
  if (typeof value === "number" && Number.isFinite(value)) {
26688
26887
  return value;
26689
26888
  }
@@ -26711,12 +26910,12 @@ function normalizeSlashStatusModelName(value) {
26711
26910
  return value?.trim().toLowerCase().replace(/[^a-z0-9]+/gu, "-").replace(/^-+|-+$/gu, "") ?? "";
26712
26911
  }
26713
26912
  function agentGuiStateEquals(left, right) {
26714
- return left === right || left.provider === right.provider && (left.providerTargetId ?? null) === (right.providerTargetId ?? null) && agentGUIProviderTargetRefsEqual(
26715
- left.providerTargetRef,
26716
- right.providerTargetRef
26717
- ) && left.lastActiveAgentSessionId === right.lastActiveAgentSessionId && left.conversationRailWidthPx === right.conversationRailWidthPx && left.conversationRailCollapsed === right.conversationRailCollapsed && (left.composerOverrides?.model ?? null) === (right.composerOverrides?.model ?? null) && (left.composerOverrides?.reasoningEffort ?? null) === (right.composerOverrides?.reasoningEffort ?? null) && (left.composerOverrides?.planMode ?? null) === (right.composerOverrides?.planMode ?? null) && (left.composerOverrides?.permissionModeId ?? null) === (right.composerOverrides?.permissionModeId ?? null) && composerOverridesByProviderEqual(
26913
+ return left === right || left.provider === right.provider && (left.agentTargetId ?? null) === (right.agentTargetId ?? null) && left.lastActiveAgentSessionId === right.lastActiveAgentSessionId && left.conversationRailWidthPx === right.conversationRailWidthPx && left.conversationRailCollapsed === right.conversationRailCollapsed && (left.composerOverrides?.model ?? null) === (right.composerOverrides?.model ?? null) && (left.composerOverrides?.reasoningEffort ?? null) === (right.composerOverrides?.reasoningEffort ?? null) && (left.composerOverrides?.planMode ?? null) === (right.composerOverrides?.planMode ?? null) && (left.composerOverrides?.permissionModeId ?? null) === (right.composerOverrides?.permissionModeId ?? null) && composerOverridesByProviderEqual(
26718
26914
  left.composerOverridesByProvider,
26719
26915
  right.composerOverridesByProvider
26916
+ ) && composerOverridesByAgentTargetIdEqual(
26917
+ left.composerOverridesByAgentTargetId,
26918
+ right.composerOverridesByAgentTargetId
26720
26919
  );
26721
26920
  }
26722
26921
  function composerOverridesByProviderEqual(left, right) {
@@ -26734,8 +26933,22 @@ function composerOverridesByProviderEqual(left, right) {
26734
26933
  }
26735
26934
  return true;
26736
26935
  }
26936
+ function composerOverridesByAgentTargetIdEqual(left, right) {
26937
+ const keys = /* @__PURE__ */ new Set([
26938
+ ...Object.keys(left ?? {}),
26939
+ ...Object.keys(right ?? {})
26940
+ ]);
26941
+ for (const key of keys) {
26942
+ const leftSettings = left?.[key] ?? null;
26943
+ const rightSettings = right?.[key] ?? null;
26944
+ if ((leftSettings?.model ?? null) !== (rightSettings?.model ?? null) || (leftSettings?.reasoningEffort ?? null) !== (rightSettings?.reasoningEffort ?? null) || (leftSettings?.planMode ?? null) !== (rightSettings?.planMode ?? null) || (leftSettings?.permissionModeId ?? null) !== (rightSettings?.permissionModeId ?? null)) {
26945
+ return false;
26946
+ }
26947
+ }
26948
+ return true;
26949
+ }
26737
26950
  function areAgentGUINodePropsEqual(previous, next) {
26738
- return previous.nodeId === next.nodeId && previous.workspaceId === next.workspaceId && previous.currentUserId === next.currentUserId && previous.workspacePath === next.workspacePath && previous.workspaceFileReferenceAdapter === next.workspaceFileReferenceAdapter && previous.resolveDroppedFileReferences === next.resolveDroppedFileReferences && previous.selectProjectDirectory === next.selectProjectDirectory && previous.referenceSourceAggregator === next.referenceSourceAggregator && previous.resolveWorkspaceReferenceEntryIconUrl === next.resolveWorkspaceReferenceEntryIconUrl && previous.resolveMentionReferenceTarget === next.resolveMentionReferenceTarget && previous.resolveWorkspaceReferenceInitialTarget === next.resolveWorkspaceReferenceInitialTarget && previous.onWorkspaceFileReferencesAdded === next.onWorkspaceFileReferencesAdded && previous.agentSettings.avoidGroupingEdits === next.agentSettings.avoidGroupingEdits && previous.title === next.title && agentGuiStateEquals(previous.state, next.state) && previous.position.x === next.position.x && previous.position.y === next.position.y && previous.width === next.width && previous.height === next.height && previous.desktopSize.width === next.desktopSize.width && previous.desktopSize.height === next.desktopSize.height && previous.onLinkAction === next.onLinkAction && previous.onCapabilitySettingsRequest === next.onCapabilitySettingsRequest && previous.onAgentProviderLogin === next.onAgentProviderLogin && previous.providerTargets === next.providerTargets && previous.defaultProviderTargetId === next.defaultProviderTargetId && previous.onClose === next.onClose && previous.onResize === next.onResize && previous.onUpdateNode === next.onUpdateNode && previous.onRememberComposerDefaults === next.onRememberComposerDefaults && previous.onOpenConversationWindow === next.onOpenConversationWindow && previous.isMaximized === next.isMaximized && previous.isMuted === next.isMuted && previous.onMinimize === next.onMinimize && previous.onToggleMaximize === next.onToggleMaximize && previous.onShowMessage === next.onShowMessage && workspaceAgentProbeRenderStateEqualsForProvider(
26951
+ return previous.nodeId === next.nodeId && previous.workspaceId === next.workspaceId && previous.currentUserId === next.currentUserId && previous.workspacePath === next.workspacePath && previous.workspaceFileReferenceAdapter === next.workspaceFileReferenceAdapter && previous.resolveDroppedFileReferences === next.resolveDroppedFileReferences && previous.selectProjectDirectory === next.selectProjectDirectory && previous.referenceSourceAggregator === next.referenceSourceAggregator && previous.resolveWorkspaceReferenceEntryIconUrl === next.resolveWorkspaceReferenceEntryIconUrl && previous.resolveMentionReferenceTarget === next.resolveMentionReferenceTarget && previous.resolveWorkspaceReferenceInitialTarget === next.resolveWorkspaceReferenceInitialTarget && previous.onWorkspaceFileReferencesAdded === next.onWorkspaceFileReferencesAdded && previous.agentSettings.avoidGroupingEdits === next.agentSettings.avoidGroupingEdits && previous.title === next.title && agentGuiStateEquals(previous.state, next.state) && previous.position.x === next.position.x && previous.position.y === next.position.y && previous.width === next.width && previous.height === next.height && previous.desktopSize.width === next.desktopSize.width && previous.desktopSize.height === next.desktopSize.height && previous.onLinkAction === next.onLinkAction && previous.onCapabilitySettingsRequest === next.onCapabilitySettingsRequest && previous.onAgentProviderLogin === next.onAgentProviderLogin && previous.providerTargets === next.providerTargets && previous.providerTargetsLoading === next.providerTargetsLoading && previous.defaultProviderTargetId === next.defaultProviderTargetId && previous.conversationScope === next.conversationScope && previous.onClose === next.onClose && previous.onResize === next.onResize && previous.onUpdateNode === next.onUpdateNode && previous.onRememberComposerDefaults === next.onRememberComposerDefaults && previous.onOpenConversationWindow === next.onOpenConversationWindow && previous.isMaximized === next.isMaximized && previous.isMuted === next.isMuted && previous.onMinimize === next.onMinimize && previous.onToggleMaximize === next.onToggleMaximize && previous.onShowMessage === next.onShowMessage && workspaceAgentProbeRenderStateEqualsForProvider(
26739
26952
  previous.workspaceAgentProbes,
26740
26953
  next.workspaceAgentProbes,
26741
26954
  previous.state.provider
@@ -26766,7 +26979,9 @@ var AgentGUINode = memo2(function AgentGUINode2({
26766
26979
  onCapabilitySettingsRequest,
26767
26980
  onAgentProviderLogin,
26768
26981
  providerTargets,
26982
+ providerTargetsLoading = false,
26769
26983
  defaultProviderTargetId = null,
26984
+ conversationScope = "single-provider",
26770
26985
  onWorkspaceFileReferencesAdded,
26771
26986
  onOpenConversationWindow,
26772
26987
  onClose,
@@ -26923,9 +27138,11 @@ var AgentGUINode = memo2(function AgentGUINode2({
26923
27138
  workspacePath,
26924
27139
  avoidGroupingEdits: agentSettings.avoidGroupingEdits,
26925
27140
  data: state,
27141
+ conversationScope,
26926
27142
  openSessionRequest,
26927
27143
  prefillPromptRequest,
26928
27144
  providerTargets,
27145
+ providerTargetsLoading,
26929
27146
  defaultProviderTargetId,
26930
27147
  previewMode,
26931
27148
  onDataChange: handleDataChange,
@@ -26964,6 +27181,36 @@ var AgentGUINode = memo2(function AgentGUINode2({
26964
27181
  fallbackAgentLabel: fallbackAgentTitle,
26965
27182
  language: locale
26966
27183
  }) : null;
27184
+ useEffect14(() => {
27185
+ if (previewMode || !viewModel.activeConversation) {
27186
+ return;
27187
+ }
27188
+ const conversationTitle = activeConversationDockTitle?.trim() ?? "";
27189
+ if (!conversationTitle) {
27190
+ return;
27191
+ }
27192
+ const conversationId = viewModel.activeConversation.id;
27193
+ if (state.lastActiveAgentSessionId === conversationId && state.lastActiveConversationTitle === conversationTitle) {
27194
+ return;
27195
+ }
27196
+ onUpdateNode((current) => {
27197
+ if (current.lastActiveAgentSessionId === conversationId && current.lastActiveConversationTitle === conversationTitle) {
27198
+ return current;
27199
+ }
27200
+ return {
27201
+ ...current,
27202
+ lastActiveAgentSessionId: conversationId,
27203
+ lastActiveConversationTitle: conversationTitle
27204
+ };
27205
+ });
27206
+ }, [
27207
+ activeConversationDockTitle,
27208
+ onUpdateNode,
27209
+ previewMode,
27210
+ state.lastActiveAgentSessionId,
27211
+ state.lastActiveConversationTitle,
27212
+ viewModel.activeConversation
27213
+ ]);
26967
27214
  const labels = useMemo11(
26968
27215
  () => ({
26969
27216
  initialPlaceholder: t("agentHost.agentGui.initialPlaceholder", {
@@ -27094,6 +27341,12 @@ var AgentGUINode = memo2(function AgentGUINode2({
27094
27341
  emptyProjectConversations: t(
27095
27342
  "agentHost.agentGui.emptyProjectConversations"
27096
27343
  ),
27344
+ conversationFilterAll: t("agentHost.agentGui.conversationFilterAll"),
27345
+ conversationFilterCodex: t("agentHost.agentGui.conversationFilterCodex"),
27346
+ conversationFilterClaudeCode: t(
27347
+ "agentHost.agentGui.conversationFilterClaudeCode"
27348
+ ),
27349
+ providerSwitchLabel: t("agentHost.agentGui.providerSwitchLabel"),
27097
27350
  startConversation: t("agentHost.agentGui.startConversation"),
27098
27351
  selectConversation: t("agentHost.agentGui.selectConversation"),
27099
27352
  loadingConversations: t("agentHost.agentGui.loadingConversations"),
@@ -27208,6 +27461,10 @@ var AgentGUINode = memo2(function AgentGUINode2({
27208
27461
  submitAnswers: t("agentHost.agentGui.submitAnswers"),
27209
27462
  answerPlaceholder: t("agentHost.agentGui.answerPlaceholder"),
27210
27463
  waitingForAnswer: t("agentHost.agentGui.waitingForAnswer"),
27464
+ waitingForBackgroundAgent: (count) => {
27465
+ const pluralKey = count === 1 ? "agentHost.agentGui.waitingForBackgroundAgent_one" : "agentHost.agentGui.waitingForBackgroundAgent_other";
27466
+ return t(pluralKey, { count });
27467
+ },
27211
27468
  thinkingLabel: t("agentHost.workspaceAgentSessionDetailThinking"),
27212
27469
  toolCallsLabel: (count) => t("agentHost.workspaceAgentSessionDetailToolCalls", { count }),
27213
27470
  openConversationWindow: t("agentHost.agentGui.openConversationWindow"),
@@ -27418,41 +27675,9 @@ var AgentGUINode = memo2(function AgentGUINode2({
27418
27675
  }),
27419
27676
  [t]
27420
27677
  );
27421
- const collapsedWindowConversationTitle = isConversationRailCollapsed ? activeConversationDockTitle ?? state.lastActiveConversationTitle ?? null : null;
27678
+ const collapsedWindowConversationTitle = isConversationRailCollapsed ? activeConversationDockTitle : null;
27422
27679
  const windowTitle = collapsedWindowConversationTitle || (isConversationRailCollapsed ? activeConversationWindowTitle : null) || windowAgentTitle || title;
27423
27680
  const windowTitleIconUrl = agentGuiDockIconUrls[activeProvider] ?? null;
27424
- useEffect14(() => {
27425
- if (previewMode) {
27426
- return;
27427
- }
27428
- if (!viewModel.activeConversation) {
27429
- return;
27430
- }
27431
- const nextTitle = activeConversationDockTitle;
27432
- const previousTitle = state.lastActiveConversationTitle ?? null;
27433
- if (nextTitle === null && previousTitle !== null && viewModel.activeConversation.id === state.lastActiveAgentSessionId) {
27434
- return;
27435
- }
27436
- if ((state.lastActiveConversationTitle ?? null) === nextTitle) {
27437
- return;
27438
- }
27439
- onUpdateNode((current) => {
27440
- if ((current.lastActiveConversationTitle ?? null) === nextTitle) {
27441
- return current;
27442
- }
27443
- return {
27444
- ...current,
27445
- lastActiveConversationTitle: nextTitle
27446
- };
27447
- });
27448
- }, [
27449
- activeConversationDockTitle,
27450
- onUpdateNode,
27451
- previewMode,
27452
- state.lastActiveAgentSessionId,
27453
- state.lastActiveConversationTitle,
27454
- viewModel.activeConversation
27455
- ]);
27456
27681
  const activeProbeProvider = activeProvider;
27457
27682
  const activeAgentProbe = useMemo11(
27458
27683
  () => findWorkspaceAgentProbeForDockProvider(