@tutti-os/agent-gui 0.0.73 → 0.0.74

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 (80) hide show
  1. package/README.md +6 -2
  2. package/dist/agent-conversation/index.d.ts +2 -2
  3. package/dist/agent-conversation/index.js +8 -8
  4. package/dist/agent-message-center/index.js +10 -10
  5. package/dist/{agentGuiNodeTypes-aJ3AX7u2.d.ts → agentGuiNodeTypes-C0WUHQzu.d.ts} +2 -1
  6. package/dist/app/renderer/agentactivity.css +6 -9
  7. package/dist/{chunk-C7K3EFGI.js → chunk-4XIHKCWC.js} +2 -2
  8. package/dist/{chunk-3PKRGSMH.js → chunk-6EREXANR.js} +4 -12
  9. package/dist/chunk-6EREXANR.js.map +1 -0
  10. package/dist/{chunk-ATEZXUHK.js → chunk-BT2DT2P7.js} +1 -1
  11. package/dist/chunk-BT2DT2P7.js.map +1 -0
  12. package/dist/{chunk-BHNJN2TR.js → chunk-BTUOROCD.js} +1 -4
  13. package/dist/chunk-BTUOROCD.js.map +1 -0
  14. package/dist/{chunk-XZF4QNT4.js → chunk-D2Z2QZVE.js} +2 -2
  15. package/dist/{chunk-GDFQXJMG.js → chunk-FHWE5SUF.js} +3 -7
  16. package/dist/chunk-FHWE5SUF.js.map +1 -0
  17. package/dist/{chunk-UAAXRSW2.js → chunk-FPODKSSV.js} +4 -4
  18. package/dist/chunk-FPODKSSV.js.map +1 -0
  19. package/dist/{chunk-IVIXKAEH.js → chunk-GLMDAZSQ.js} +3 -3
  20. package/dist/{chunk-466AWJTS.js → chunk-KVS7J7BJ.js} +5 -5
  21. package/dist/{chunk-5H6NINJY.js → chunk-LWFV4PS5.js} +2 -7
  22. package/dist/chunk-LWFV4PS5.js.map +1 -0
  23. package/dist/{chunk-KWQ4N4IZ.js → chunk-NO7WDGST.js} +3 -3
  24. package/dist/{chunk-4US2YHBY.js → chunk-RA3OUR64.js} +1 -3
  25. package/dist/chunk-RA3OUR64.js.map +1 -0
  26. package/dist/{chunk-SZF52NMJ.js → chunk-RF7GK4SM.js} +18 -12
  27. package/dist/chunk-RF7GK4SM.js.map +1 -0
  28. package/dist/{chunk-4I2VCAMW.js → chunk-SL2QSEIE.js} +1 -8
  29. package/dist/chunk-SL2QSEIE.js.map +1 -0
  30. package/dist/{chunk-2I2WRI4F.js → chunk-T5CEU7WH.js} +2 -3
  31. package/dist/chunk-T5CEU7WH.js.map +1 -0
  32. package/dist/{chunk-SVGIWXNK.js → chunk-VERGPY42.js} +2 -2
  33. package/dist/{chunk-G6BVEY7I.js → chunk-W5AJTBA7.js} +1 -15
  34. package/dist/chunk-W5AJTBA7.js.map +1 -0
  35. package/dist/{chunk-Q6AWM3RH.js → chunk-Z72JKSAY.js} +4 -4
  36. package/dist/{chunk-OBJRIQPX.js → chunk-ZSYDFQ4N.js} +38 -25
  37. package/dist/chunk-ZSYDFQ4N.js.map +1 -0
  38. package/dist/context-mention-palette/index.js +9 -9
  39. package/dist/i18n/index.d.ts +0 -14
  40. package/dist/i18n/index.js +2 -2
  41. package/dist/index.d.ts +40 -6
  42. package/dist/index.js +296 -89
  43. package/dist/index.js.map +1 -1
  44. package/dist/queued-prompt-runtime.d.ts +2 -2
  45. package/dist/{types-CrwMqBm1.d.ts → types-DUHHejs2.d.ts} +3 -3
  46. package/dist/workbench/contribution.d.ts +1 -1
  47. package/dist/workbench/contribution.js +6 -6
  48. package/dist/workbench/index.d.ts +1 -1
  49. package/dist/workbench/index.js +9 -9
  50. package/dist/workbench/launch.d.ts +1 -1
  51. package/dist/workbench/launch.js +3 -3
  52. package/dist/workbench/providerCatalog.d.ts +3 -3
  53. package/dist/workbench/providerCatalog.js +1 -1
  54. package/dist/workbench/sessionTitle.d.ts +1 -1
  55. package/dist/workbench/sessionTitle.js +3 -3
  56. package/dist/workbench/state.d.ts +1 -1
  57. package/dist/workbench/state.js +2 -2
  58. package/dist/workbench/types.d.ts +2 -2
  59. package/dist/workbench/types.js +1 -1
  60. package/dist/workspace-agent-generated-files.js +4 -4
  61. package/package.json +12 -12
  62. package/dist/chunk-2I2WRI4F.js.map +0 -1
  63. package/dist/chunk-3PKRGSMH.js.map +0 -1
  64. package/dist/chunk-4I2VCAMW.js.map +0 -1
  65. package/dist/chunk-4US2YHBY.js.map +0 -1
  66. package/dist/chunk-5H6NINJY.js.map +0 -1
  67. package/dist/chunk-ATEZXUHK.js.map +0 -1
  68. package/dist/chunk-BHNJN2TR.js.map +0 -1
  69. package/dist/chunk-G6BVEY7I.js.map +0 -1
  70. package/dist/chunk-GDFQXJMG.js.map +0 -1
  71. package/dist/chunk-OBJRIQPX.js.map +0 -1
  72. package/dist/chunk-SZF52NMJ.js.map +0 -1
  73. package/dist/chunk-UAAXRSW2.js.map +0 -1
  74. /package/dist/{chunk-C7K3EFGI.js.map → chunk-4XIHKCWC.js.map} +0 -0
  75. /package/dist/{chunk-XZF4QNT4.js.map → chunk-D2Z2QZVE.js.map} +0 -0
  76. /package/dist/{chunk-IVIXKAEH.js.map → chunk-GLMDAZSQ.js.map} +0 -0
  77. /package/dist/{chunk-466AWJTS.js.map → chunk-KVS7J7BJ.js.map} +0 -0
  78. /package/dist/{chunk-KWQ4N4IZ.js.map → chunk-NO7WDGST.js.map} +0 -0
  79. /package/dist/{chunk-SVGIWXNK.js.map → chunk-VERGPY42.js.map} +0 -0
  80. /package/dist/{chunk-Q6AWM3RH.js.map → chunk-Z72JKSAY.js.map} +0 -0
package/dist/index.js CHANGED
@@ -11,7 +11,7 @@ import {
11
11
  resolveAgentGuiSessionProviderFlatIconUrl,
12
12
  resolveNextAgentGUIConversationRailWidthPx,
13
13
  shouldAutoCollapseAgentGUIConversationRail
14
- } from "./chunk-SZF52NMJ.js";
14
+ } from "./chunk-RF7GK4SM.js";
15
15
  import {
16
16
  agentGUIDefaultTargetProviders,
17
17
  agentGUIProviderTargetRefsEqual,
@@ -23,16 +23,16 @@ import {
23
23
  localAgentGUIProviderTargetId,
24
24
  normalizeAgentGUIProviderTargets,
25
25
  resolveAgentGUIProviderTarget
26
- } from "./chunk-2I2WRI4F.js";
27
- import "./chunk-UAAXRSW2.js";
28
- import "./chunk-ATEZXUHK.js";
26
+ } from "./chunk-T5CEU7WH.js";
27
+ import "./chunk-FPODKSSV.js";
28
+ import "./chunk-BT2DT2P7.js";
29
29
  import {
30
30
  resolveAgentGuiWorkbenchProviderLabel
31
- } from "./chunk-BHNJN2TR.js";
31
+ } from "./chunk-BTUOROCD.js";
32
32
  import {
33
33
  AgentInteractivePromptSurface,
34
34
  approvalOptionDisplayLabel
35
- } from "./chunk-Q6AWM3RH.js";
35
+ } from "./chunk-Z72JKSAY.js";
36
36
  import {
37
37
  PLAN_IMPLEMENTATION_ACTION_FEEDBACK,
38
38
  PLAN_IMPLEMENTATION_ACTION_IMPLEMENT,
@@ -51,7 +51,7 @@ import {
51
51
  resolveAgentGUIExplicitConversationTitle,
52
52
  resolveAgentGUIProviderDisplayLabel,
53
53
  resolveAgentGUIProviderIdentity
54
- } from "./chunk-5H6NINJY.js";
54
+ } from "./chunk-LWFV4PS5.js";
55
55
  import {
56
56
  AGENT_PASTED_TEXT_BLOCK_KIND,
57
57
  AGENT_PASTED_TEXT_MENTION_KIND,
@@ -88,14 +88,14 @@ import {
88
88
  textPromptContent,
89
89
  toLocalShortDateTime,
90
90
  useProjectedAgentConversation
91
- } from "./chunk-OBJRIQPX.js";
91
+ } from "./chunk-ZSYDFQ4N.js";
92
92
  import {
93
93
  AgentMessageMarkdown,
94
94
  AgentTargetPresentationProvider,
95
95
  ZoomableImage,
96
96
  cn,
97
97
  resolveWorkspaceLinkAction
98
- } from "./chunk-IVIXKAEH.js";
98
+ } from "./chunk-GLMDAZSQ.js";
99
99
  import {
100
100
  openAgentEnvPanel
101
101
  } from "./chunk-PSLAWU25.js";
@@ -106,12 +106,12 @@ import {
106
106
  DEFAULT_AGENT_MENTION_FILTER,
107
107
  agentMentionItemKey,
108
108
  preloadAgentMentionBrowse
109
- } from "./chunk-466AWJTS.js";
109
+ } from "./chunk-KVS7J7BJ.js";
110
110
  import {
111
111
  buildWorkspaceAgentActivityListViewModel,
112
112
  isWorkspaceAgentUntitledTask
113
- } from "./chunk-3PKRGSMH.js";
114
- import "./chunk-SVGIWXNK.js";
113
+ } from "./chunk-6EREXANR.js";
114
+ import "./chunk-VERGPY42.js";
115
115
  import {
116
116
  resolveWorkspaceAgentSessionSortTimeUnixMs
117
117
  } from "./chunk-IBIMGLCD.js";
@@ -124,7 +124,7 @@ import {
124
124
  mentionItemToAttrs,
125
125
  normalizeAgentSessionMentionTitle,
126
126
  parseMentionItemFromHref
127
- } from "./chunk-KWQ4N4IZ.js";
127
+ } from "./chunk-NO7WDGST.js";
128
128
  import "./chunk-Y35GDLP2.js";
129
129
  import "./chunk-LUGELG5V.js";
130
130
  import {
@@ -148,7 +148,7 @@ import {
148
148
  useAgentHostApi,
149
149
  useOptionalAgentActivityRuntime,
150
150
  useOptionalAgentHostApi
151
- } from "./chunk-GDFQXJMG.js";
151
+ } from "./chunk-FHWE5SUF.js";
152
152
  import {
153
153
  WORKSPACE_AGENT_ACTIVITY_RUNTIME_SESSION_ORIGIN,
154
154
  createWorkspaceAgentActivityUserMessageIdFromClientSubmitId,
@@ -156,21 +156,21 @@ import {
156
156
  isWorkspaceAgentActivityRuntimeSessionOrigin,
157
157
  mergeWorkspaceAgentActivityDurableAndOverlayMessages,
158
158
  selectWorkspaceAgentActivityOverlayMessages
159
- } from "./chunk-4US2YHBY.js";
159
+ } from "./chunk-RA3OUR64.js";
160
160
  import {
161
161
  AgentGuiI18nProvider,
162
162
  agentGuiI18nModule,
163
163
  agentGuiI18nResources,
164
164
  translate,
165
165
  useTranslation
166
- } from "./chunk-C7K3EFGI.js";
166
+ } from "./chunk-4XIHKCWC.js";
167
167
  import "./chunk-PJP5BUU6.js";
168
168
  import {
169
169
  agentColorfulUrl,
170
170
  cursorColorfulUrl,
171
171
  normalizeManagedAgentProvider
172
- } from "./chunk-4I2VCAMW.js";
173
- import "./chunk-G6BVEY7I.js";
172
+ } from "./chunk-SL2QSEIE.js";
173
+ import "./chunk-W5AJTBA7.js";
174
174
  import {
175
175
  AGENT_CONTEXT_MENTION_PROVIDER_IDS
176
176
  } from "./chunk-JM24HADP.js";
@@ -2266,6 +2266,7 @@ function getTestAgentQueuedPromptRuntime() {
2266
2266
  // agent-gui/agentGuiNode/controller/useAgentGUINodeController.ts
2267
2267
  import {
2268
2268
  resolveSubmitAvailability,
2269
+ isLiveTurnLifecyclePhase,
2269
2270
  resolveAgentActivityCapability as resolveAgentActivityCapability2,
2270
2271
  resolveAgentActivityUsage,
2271
2272
  selectSessionDisplayStatuses
@@ -2279,7 +2280,6 @@ var AGENT_PROVIDERS = [
2279
2280
  "tutti-agent",
2280
2281
  "nexight",
2281
2282
  "opencode",
2282
- "gemini",
2283
2283
  "openclaw",
2284
2284
  "hermes"
2285
2285
  ];
@@ -2323,7 +2323,6 @@ var DEFAULT_AGENT_SETTINGS = {
2323
2323
  cursor: false,
2324
2324
  nexight: false,
2325
2325
  opencode: false,
2326
- gemini: false,
2327
2326
  openclaw: false,
2328
2327
  hermes: false
2329
2328
  },
@@ -2334,7 +2333,6 @@ var DEFAULT_AGENT_SETTINGS = {
2334
2333
  cursor: "",
2335
2334
  nexight: "",
2336
2335
  opencode: "",
2337
- gemini: "",
2338
2336
  openclaw: "",
2339
2337
  hermes: ""
2340
2338
  },
@@ -2345,7 +2343,6 @@ var DEFAULT_AGENT_SETTINGS = {
2345
2343
  cursor: [],
2346
2344
  nexight: [],
2347
2345
  opencode: [],
2348
- gemini: [],
2349
2346
  openclaw: [],
2350
2347
  hermes: []
2351
2348
  },
@@ -4789,12 +4786,9 @@ function normalizeAgentGUIConversationListFilter(input) {
4789
4786
  if (input.conversationFilter) {
4790
4787
  return normalizeAgentGUIConversationFilter(input.conversationFilter);
4791
4788
  }
4792
- return null;
4789
+ return { kind: "all" };
4793
4790
  }
4794
- function conversationFilterKey(filter, provider) {
4795
- if (!filter) {
4796
- return `legacy-provider:${provider}`;
4797
- }
4791
+ function conversationFilterKey(filter) {
4798
4792
  const normalized = normalizeAgentGUIConversationFilter(filter);
4799
4793
  if (normalized.kind === "all") {
4800
4794
  return "all";
@@ -4802,7 +4796,7 @@ function conversationFilterKey(filter, provider) {
4802
4796
  return `agent-target:${normalized.agentTargetId}`;
4803
4797
  }
4804
4798
  function conversationRetainableForQueryFilter(conversation, filter) {
4805
- if (!conversation || !filter || filter.kind !== "agentTarget") {
4799
+ if (!conversation || filter.kind !== "agentTarget") {
4806
4800
  return true;
4807
4801
  }
4808
4802
  return matchesAgentGUIConversationSummaryFilter(conversation, filter);
@@ -4812,12 +4806,11 @@ function createAgentGUIConversationListQueryKey(input) {
4812
4806
  if (!normalized) {
4813
4807
  return null;
4814
4808
  }
4815
- const providerScope = normalized.conversationFilter ? "conversation-filter" : normalized.provider;
4816
4809
  const queryKey = [
4817
4810
  normalized.workspaceId,
4818
4811
  normalized.userId,
4819
- providerScope,
4820
- conversationFilterKey(normalized.conversationFilter, normalized.provider),
4812
+ "conversation-filter",
4813
+ conversationFilterKey(normalized.conversationFilter),
4821
4814
  normalized.sessionOrigin
4822
4815
  ].join("::");
4823
4816
  return queryKey;
@@ -5586,8 +5579,8 @@ async function refreshAgentGUIConversationListQuery(query, reason, options = {})
5586
5579
  userId: state.query.userId
5587
5580
  };
5588
5581
  const currentWorkspaceAgentSnapshot = getWorkspaceAgentSnapshotForConversations(workspaceAgentsInput);
5589
- const canProjectExplicitFilterFromCurrentSnapshot = reason === "projection-sync" && state.query.conversationFilter !== null && currentWorkspaceAgentSnapshot.sessions.length > 0;
5590
- const workspaceAgentSnapshot = shouldUseCurrentWorkspaceAgentSnapshotForRefresh(reason) || canProjectExplicitFilterFromCurrentSnapshot ? currentWorkspaceAgentSnapshot : await loadWorkspaceAgentSnapshotForConversations(
5582
+ const canProjectFilterFromCurrentSnapshot = reason === "projection-sync" && currentWorkspaceAgentSnapshot.sessions.length > 0;
5583
+ const workspaceAgentSnapshot = shouldUseCurrentWorkspaceAgentSnapshotForRefresh(reason) || canProjectFilterFromCurrentSnapshot ? currentWorkspaceAgentSnapshot : await loadWorkspaceAgentSnapshotForConversations(
5591
5584
  workspaceAgentsInput
5592
5585
  );
5593
5586
  if (requestId !== requestIdByQueryKey.get(queryKey)) {
@@ -5643,7 +5636,7 @@ async function refreshAgentGUIConversationListQuery(query, reason, options = {})
5643
5636
  return agentSessionId && dirtySessionIds.has(agentSessionId) || syncSessionId && dirtySessionIds.has(syncSessionId);
5644
5637
  }) : workspaceAgentSnapshot.sessions;
5645
5638
  const baseConversations = buildAgentGUIConversationSummaries({
5646
- ...state.query.conversationFilter ? { conversationFilter: state.query.conversationFilter } : {},
5639
+ conversationFilter: state.query.conversationFilter,
5647
5640
  snapshot: canApplyDirtySessionProjection ? {
5648
5641
  ...workspaceAgentSnapshot,
5649
5642
  sessions: projectionSessions
@@ -5677,7 +5670,7 @@ async function refreshAgentGUIConversationListQuery(query, reason, options = {})
5677
5670
  );
5678
5671
  const retainableForQueryFilter = (agentSessionId) => {
5679
5672
  const filter = state.query.conversationFilter;
5680
- if (!filter || filter.kind !== "agentTarget") {
5673
+ if (filter.kind !== "agentTarget") {
5681
5674
  return true;
5682
5675
  }
5683
5676
  const snapshotAgentTargetId = snapshotSessionAgentTargetIdById.get(agentSessionId);
@@ -6642,7 +6635,7 @@ function nodeComposerOverridesForProvider(data) {
6642
6635
  return data.composerOverridesByProvider?.[data.provider] ?? data.composerOverrides ?? null;
6643
6636
  }
6644
6637
  function composerSupportForProvider(provider) {
6645
- if (provider === "claude-code" || provider === "codex" || provider === "gemini" || provider === "opencode") {
6638
+ if (provider === "claude-code" || provider === "codex" || provider === "opencode") {
6646
6639
  return {
6647
6640
  model: true,
6648
6641
  permission: provider === "claude-code" || provider === "codex",
@@ -8509,6 +8502,14 @@ function conversationBusyStatusFromAgentActivityDisplayStatus(status) {
8509
8502
  }
8510
8503
  return null;
8511
8504
  }
8505
+ function agentActivitySessionHasLiveTurn(session) {
8506
+ const lifecycle = session?.turnLifecycle;
8507
+ if (!lifecycle || lifecycle.settling === true) {
8508
+ return false;
8509
+ }
8510
+ const activeTurnId = lifecycle.activeTurnId?.trim() ?? "";
8511
+ return activeTurnId !== "" || isLiveTurnLifecyclePhase(lifecycle.phase);
8512
+ }
8512
8513
  function reuseAgentActivityDisplayStatusesIfUnchanged(previous, next) {
8513
8514
  if (!previous || previous.size !== next.size) {
8514
8515
  return next;
@@ -8798,7 +8799,7 @@ function mergeSessionControlStatePatch(current, patch) {
8798
8799
  }
8799
8800
  if (patch.turn?.phase) {
8800
8801
  next.turnLifecycle = {
8801
- activeTurnId: patch.turn.activeTurnId !== void 0 ? patch.turn.activeTurnId : patch.turn.phase === "settled" ? null : patch.turn.turnId,
8802
+ activeTurnId: patch.turn.activeTurnId !== void 0 ? patch.turn.activeTurnId : patch.turn.phase === "settled" || patch.turn.phase === "idle" ? null : patch.turn.turnId,
8802
8803
  phase: patch.turn.phase,
8803
8804
  settling: patch.turn.settling,
8804
8805
  outcome: patch.turn.outcome ?? null,
@@ -9334,6 +9335,7 @@ function useAgentGUINodeController({
9334
9335
  ),
9335
9336
  [agentActivitySnapshot.sessions]
9336
9337
  );
9338
+ const activeRuntimeSession = runtimeSessionsBySessionId.get(activeConversationId ?? "") ?? null;
9337
9339
  const stableRuntimeSyncStateBySessionId = useMemo3(() => {
9338
9340
  const current = stableRuntimeSyncStateBySessionIdRef.current;
9339
9341
  let next = current;
@@ -12992,14 +12994,26 @@ function useAgentGUINodeController({
12992
12994
  if (sessionState?.pendingInteractive) {
12993
12995
  return true;
12994
12996
  }
12997
+ const runtimeSession = runtimeSessionsBySessionId.get(normalizedAgentSessionId) ?? null;
12998
+ if (runtimeSession && resolveSubmitAvailability(runtimeSession).state === "blocked") {
12999
+ return true;
13000
+ }
13001
+ const conversationStatus = conversations.find(
13002
+ (conversation2) => conversation2.id === normalizedAgentSessionId
13003
+ )?.status ?? null;
13004
+ if (conversationBusyStatus2(conversationStatus)) {
13005
+ return true;
13006
+ }
12995
13007
  return agentActivityDisplayStatusBusy(
12996
13008
  agentActivityDisplayStatuses.get(normalizedAgentSessionId)
12997
13009
  );
12998
13010
  },
12999
13011
  [
13000
13012
  agentActivityDisplayStatuses,
13013
+ conversations,
13001
13014
  isRespondingApproval,
13002
13015
  isSubmitting,
13016
+ runtimeSessionsBySessionId,
13003
13017
  sessionViewRef
13004
13018
  ]
13005
13019
  );
@@ -13173,7 +13187,7 @@ function useAgentGUINodeController({
13173
13187
  setDetailError(translate("agentHost.agentGui.promptImagesUnsupported"));
13174
13188
  return;
13175
13189
  }
13176
- const activeTurnId = activeSessionState?.turnLifecycle?.activeTurnId?.trim() ?? "";
13190
+ const activeTurnId = activeRuntimeSession?.turnLifecycle?.activeTurnId?.trim() || activeSessionState?.turnLifecycle?.activeTurnId?.trim() || "";
13177
13191
  if (activeTurnId === "") {
13178
13192
  return;
13179
13193
  }
@@ -13185,7 +13199,13 @@ function useAgentGUINodeController({
13185
13199
  { bypassLocalQueue: true, guidance: true }
13186
13200
  );
13187
13201
  },
13188
- [activeSessionState, promptImagesSupported, submitExistingPrompt, translate]
13202
+ [
13203
+ activeRuntimeSession,
13204
+ activeSessionState,
13205
+ promptImagesSupported,
13206
+ submitExistingPrompt,
13207
+ translate
13208
+ ]
13189
13209
  );
13190
13210
  useEffect4(() => {
13191
13211
  if (previewMode) {
@@ -14609,13 +14629,15 @@ function useAgentGUINodeController({
14609
14629
  );
14610
14630
  }, [conversationUserIds, ensureAccountProfiles]);
14611
14631
  const projectionConversationRef = useRef4(null);
14632
+ const activeRuntimeSessionLiveTurn = agentActivitySessionHasLiveTurn(activeRuntimeSession);
14633
+ const activeRuntimeTurnLifecycle = activeRuntimeSessionLiveTurn ? activeRuntimeSession?.turnLifecycle ?? null : null;
14612
14634
  const projectionConversation = useMemo3(() => {
14613
14635
  if (!activeConversation) {
14614
14636
  projectionConversationRef.current = null;
14615
14637
  return null;
14616
14638
  }
14617
14639
  const previous = projectionConversationRef.current;
14618
- const turnLifecycle = activeSessionState?.agentSessionId === activeConversation.id ? activeSessionState.turnLifecycle ?? null : null;
14640
+ const turnLifecycle = activeRuntimeTurnLifecycle ?? (activeSessionState?.agentSessionId === activeConversation.id ? activeSessionState.turnLifecycle ?? null : null);
14619
14641
  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)) {
14620
14642
  return previous;
14621
14643
  }
@@ -14643,6 +14665,9 @@ function useAgentGUINodeController({
14643
14665
  activeConversation?.title,
14644
14666
  activeConversation?.titleFallback,
14645
14667
  activeConversation?.userId,
14668
+ activeRuntimeTurnLifecycle?.activeTurnId,
14669
+ activeRuntimeTurnLifecycle?.phase,
14670
+ activeRuntimeTurnLifecycle?.settling,
14646
14671
  activeSessionState?.agentSessionId,
14647
14672
  activeSessionState?.turnLifecycle?.activeTurnId,
14648
14673
  activeSessionState?.turnLifecycle?.phase,
@@ -14743,7 +14768,7 @@ function useAgentGUINodeController({
14743
14768
  conversation,
14744
14769
  workspaceId
14745
14770
  ]);
14746
- const activeLiveState = activeConversationLiveState;
14771
+ const activeLiveState = activeConversationLiveState === "inactive" && activeRuntimeSessionLiveTurn ? "active" : activeConversationLiveState;
14747
14772
  const activationError = activation.errorFor(activeConversationId);
14748
14773
  const activationErrorCode = activation.codeFor(activeConversationId);
14749
14774
  const hasProviderSessionNotFoundError = isNonRetryableResumeErrorCode(activationErrorCode);
@@ -14891,7 +14916,6 @@ function useAgentGUINodeController({
14891
14916
  activeConversation?.title ?? ""
14892
14917
  ) : null;
14893
14918
  const pendingInteractivePrompt = serverInteractivePrompt ?? planImplementationPromptVM;
14894
- const activeRuntimeSession = runtimeSessionsBySessionId.get(activeConversationId ?? "") ?? null;
14895
14919
  useEffect4(() => {
14896
14920
  const provider = normalizeOptionalText2(
14897
14921
  activeRuntimeSession?.provider ?? activeConversation?.provider
@@ -14915,8 +14939,10 @@ function useAgentGUINodeController({
14915
14939
  ]);
14916
14940
  const activeActivityDisplayStatus = activeConversationId ? agentActivityDisplayStatuses.get(activeConversationId) ?? null : null;
14917
14941
  const activeHasPendingSubmittedTurn = activeConversationId ? Boolean(pendingTurnIdBySessionIdRef.current[activeConversationId]) : false;
14918
- const activeSubmitBlocked = activeSessionState ? resolveSubmitAvailability(activeSessionState).state === "blocked" : false;
14919
- const activeConversationBusy = agentActivityDisplayStatusBusy(activeActivityDisplayStatus) || activeHasPendingSubmittedTurn || activeSubmitBlocked;
14942
+ const activeSessionStateSubmitBlocked = activeSessionState ? resolveSubmitAvailability(activeSessionState).state === "blocked" : false;
14943
+ const activeRuntimeSubmitBlocked = activeRuntimeSession ? resolveSubmitAvailability(activeRuntimeSession).state === "blocked" : false;
14944
+ const activeSubmitBlocked = activeSessionStateSubmitBlocked || activeRuntimeSubmitBlocked;
14945
+ const activeConversationBusy = agentActivityDisplayStatusBusy(activeActivityDisplayStatus) || conversationBusyStatus2(activeConversation?.status ?? null) || activeHasPendingSubmittedTurn || activeSubmitBlocked;
14920
14946
  const activeSessionResumable = activeRuntimeSession?.resumable ?? activeConversation?.resumable ?? activeSessionState?.resumable;
14921
14947
  const normalizedActiveConversationId = activeConversationId ?? "";
14922
14948
  const activeConversationActivationState = activeConversationId ? activation.stateFor(activeConversationId) : null;
@@ -14964,7 +14990,7 @@ function useAgentGUINodeController({
14964
14990
  hasProviderSessionNotFoundError,
14965
14991
  pendingApproval
14966
14992
  ]);
14967
- const canSubmit = !providerTargetsLoading && activeLiveState !== "activating" && activeLiveState !== "failed" && !activeConversationResumeUnavailable && (activeConversationId !== null || effectiveSelectedProviderTarget.disabled !== true) && (composerTargetData.provider !== "openclaw" || openclawGateway?.status === "ready") && pendingApproval === null && pendingInteractivePrompt === null && sessionChrome.auth === null && !isCreatingConversation && !isSubmitting && !isInterrupting;
14993
+ const canSubmit = !providerTargetsLoading && activeLiveState !== "activating" && activeLiveState !== "failed" && !activeConversationResumeUnavailable && (activeConversationId !== null || effectiveSelectedProviderTarget.disabled !== true) && (composerTargetData.provider !== "openclaw" || openclawGateway?.status === "ready") && pendingApproval === null && pendingInteractivePrompt === null && sessionChrome.auth === null && !activeConversationBusy && !isCreatingConversation && !isSubmitting && !isInterrupting;
14968
14994
  const canQueueWhileBusy = Boolean(activeConversationId) && (activeConversationBusy || isSubmitting || Boolean(activeSessionState?.pendingInteractive));
14969
14995
  useEffect4(() => {
14970
14996
  const firstVersion = minFiniteMessageVersion(activeMessages);
@@ -15638,6 +15664,7 @@ function useAgentGUINodeController({
15638
15664
  activeLiveState,
15639
15665
  activationError,
15640
15666
  openclawGateway,
15667
+ activeConversationBusy,
15641
15668
  canSubmit,
15642
15669
  composerSettings: stableComposerSettings,
15643
15670
  queuedPrompts,
@@ -17490,6 +17517,10 @@ var CLAUDE_CODE_FALLBACK_COMMANDS = [
17490
17517
  { name: REVIEW_COMMAND }
17491
17518
  ];
17492
17519
  var CURSOR_FALLBACK_COMMANDS = [];
17520
+ var OPENCODE_FALLBACK_COMMANDS = [
17521
+ { name: "compact" },
17522
+ { name: REVIEW_COMMAND }
17523
+ ];
17493
17524
  var CLAUDE_CODE_SLASH_PALETTE_COMMANDS = /* @__PURE__ */ new Set([
17494
17525
  "compact",
17495
17526
  "context",
@@ -17527,13 +17558,18 @@ var PROVIDER_SLASH_POLICY = {
17527
17558
  immediateCommands: /* @__PURE__ */ new Set(),
17528
17559
  reviewPickerCommands: /* @__PURE__ */ new Set(),
17529
17560
  fallbackCommands: CURSOR_FALLBACK_COMMANDS
17561
+ },
17562
+ opencode: {
17563
+ immediateCommands: /* @__PURE__ */ new Set(),
17564
+ reviewPickerCommands: /* @__PURE__ */ new Set([REVIEW_COMMAND]),
17565
+ fallbackCommands: OPENCODE_FALLBACK_COMMANDS
17530
17566
  }
17531
17567
  };
17532
17568
  function providerSlashPolicy(provider) {
17533
- return provider === "codex" || provider === "claude-code" || provider === "cursor" ? PROVIDER_SLASH_POLICY[provider] : void 0;
17569
+ return provider === "codex" || provider === "claude-code" || provider === "cursor" || provider === "opencode" ? PROVIDER_SLASH_POLICY[provider] : void 0;
17534
17570
  }
17535
17571
  function isACPProvider(provider) {
17536
- return provider === "codex" || provider === "claude-code" || provider === "cursor";
17572
+ return provider === "codex" || provider === "claude-code" || provider === "cursor" || provider === "opencode";
17537
17573
  }
17538
17574
  function resolveSlashCommandsForProvider({
17539
17575
  provider,
@@ -25663,6 +25699,7 @@ function AgentGUINodeView({
25663
25699
  renderSidebarFooter,
25664
25700
  renderProviderRailEmpty,
25665
25701
  renderProviderUnavailableState,
25702
+ renderProviderReadinessGateState,
25666
25703
  providerRailAllPresentation,
25667
25704
  onLinkAction,
25668
25705
  onHandoffConversation,
@@ -26210,6 +26247,17 @@ function AgentGUINodeView({
26210
26247
  onRequestComposerFocus: requestComposerFocus
26211
26248
  }
26212
26249
  ),
26250
+ renderSidebarFooter ? /* @__PURE__ */ jsx34(
26251
+ "div",
26252
+ {
26253
+ className: `${AgentGUINode_styles_default.providerRailFooter} nodrag tsh-desktop-no-drag`,
26254
+ "data-testid": "agent-gui-sidebar-footer-slot",
26255
+ children: renderSidebarFooter({
26256
+ currentUserId: viewModel.currentUserId,
26257
+ activeConversation: viewModel.activeConversation
26258
+ })
26259
+ }
26260
+ ) : null,
26213
26261
  shouldShowProviderRailConfigButton ? /* @__PURE__ */ jsx34(
26214
26262
  "div",
26215
26263
  {
@@ -26251,17 +26299,6 @@ function AgentGUINodeView({
26251
26299
  }
26252
26300
  )
26253
26301
  }
26254
- ) : null,
26255
- renderSidebarFooter ? /* @__PURE__ */ jsx34(
26256
- "div",
26257
- {
26258
- className: `${AgentGUINode_styles_default.providerRailFooter} nodrag tsh-desktop-no-drag`,
26259
- "data-testid": "agent-gui-sidebar-footer-slot",
26260
- children: renderSidebarFooter({
26261
- currentUserId: viewModel.currentUserId,
26262
- activeConversation: viewModel.activeConversation
26263
- })
26264
- }
26265
26302
  ) : null
26266
26303
  ]
26267
26304
  }
@@ -26345,6 +26382,7 @@ function AgentGUINodeView({
26345
26382
  workspaceAppIcons: effectiveWorkspaceAppIcons,
26346
26383
  workspaceUserProjectI18n,
26347
26384
  renderProviderUnavailableState,
26385
+ renderProviderReadinessGateState,
26348
26386
  previewMode
26349
26387
  }
26350
26388
  ) })
@@ -26596,7 +26634,8 @@ var AgentGUIDetailPane = memo2(function AgentGUIDetailPane2({
26596
26634
  onRequestComposerFocus,
26597
26635
  contextMentionProviders,
26598
26636
  workspaceAppIcons = EMPTY_WORKSPACE_APP_ICONS3,
26599
- renderProviderUnavailableState
26637
+ renderProviderUnavailableState,
26638
+ renderProviderReadinessGateState
26600
26639
  }) {
26601
26640
  "use memo";
26602
26641
  const timelineRef = useRef12(null);
@@ -26694,7 +26733,7 @@ var AgentGUIDetailPane = memo2(function AgentGUIDetailPane2({
26694
26733
  detailStatus: activeDetailStatus,
26695
26734
  conversation
26696
26735
  });
26697
- const activeConversationTurnBusy = viewModel.isSubmitting || derivedBusyStatus !== null;
26736
+ const activeConversationTurnBusy = viewModel.isSubmitting || viewModel.activeConversationBusy || derivedBusyStatus !== null;
26698
26737
  const isComposerSending = viewModel.isSubmitting || activeConversationTurnBusy || !hasActiveConversation && viewModel.isCreatingConversation;
26699
26738
  const isCollaboratorConversation = isDifferentKnownConversationOwner({
26700
26739
  conversationUserId: viewModel.activeConversation?.userId,
@@ -27360,6 +27399,7 @@ var AgentGUIDetailPane = memo2(function AgentGUIDetailPane2({
27360
27399
  );
27361
27400
  const disabledProviderTarget = selectedProviderTargetComingSoon ? viewModel.selectedProviderTarget ?? null : null;
27362
27401
  const shouldRenderProviderUnavailableState = !hasActiveConversation && disabledProviderTarget !== null && renderProviderUnavailableState !== void 0;
27402
+ const shouldRenderProviderReadinessGateState = !hasActiveConversation && emptyProviderReadinessGate !== null && renderProviderReadinessGateState !== void 0;
27363
27403
  const bottomDockStoreState = useMemo9(
27364
27404
  () => ({
27365
27405
  // The lifted prompt is rendered from props on the pane; the store still
@@ -27728,7 +27768,14 @@ var AgentGUIDetailPane = memo2(function AgentGUIDetailPane2({
27728
27768
  disabledProviderTarget.provider
27729
27769
  ),
27730
27770
  unavailableReason: disabledProviderTarget.unavailableReason ?? null
27731
- }) }) : emptyProviderReadinessGate ? /* @__PURE__ */ jsx34(
27771
+ }) }) : emptyProviderReadinessGate ? shouldRenderProviderReadinessGateState ? /* @__PURE__ */ jsx34(Fragment9, { children: renderProviderReadinessGateState?.({
27772
+ provider: emptyHeroProvider,
27773
+ providerLabel: emptyHeroProviderLabel || resolveAgentGuiWorkbenchProviderLabel(emptyHeroProvider),
27774
+ target: viewModel.selectedProviderTarget ?? null,
27775
+ iconUrl: resolveAgentGUIHeroIconUrl(emptyHeroProvider),
27776
+ gate: emptyProviderReadinessGate,
27777
+ showAllProviders: viewModel.conversationFilter.kind === "all"
27778
+ }) }) : /* @__PURE__ */ jsx34(
27732
27779
  AgentGUIProviderReadinessGatePane,
27733
27780
  {
27734
27781
  provider: emptyHeroProvider,
@@ -28561,6 +28608,52 @@ function updateConversationSectionsFromSummaries(previous, conversations, option
28561
28608
  let changed = false;
28562
28609
  const nextSections = previous.map((section) => {
28563
28610
  let sectionChanged = false;
28611
+ if (section.kind === "pinned") {
28612
+ const pinnedSummaryItems = conversations.filter(
28613
+ (conversation) => (conversation.pinnedAtUnixMs ?? 0) > 0
28614
+ );
28615
+ const items2 = section.items.map((item) => {
28616
+ seenIds.add(item.id);
28617
+ const summary = summariesById.get(item.id);
28618
+ if (!summary) {
28619
+ return item;
28620
+ }
28621
+ if ((summary.pinnedAtUnixMs ?? 0) <= 0) {
28622
+ sectionChanged = true;
28623
+ return null;
28624
+ }
28625
+ if (conversationSummariesRenderEqual2(item, summary)) {
28626
+ return item;
28627
+ }
28628
+ sectionChanged = true;
28629
+ return summary;
28630
+ }).filter(
28631
+ (item) => item !== null
28632
+ );
28633
+ const existingIds = new Set(items2.map((item) => item.id));
28634
+ const mergedItems2 = [
28635
+ ...items2,
28636
+ ...pinnedSummaryItems.filter((item) => !existingIds.has(item.id))
28637
+ ];
28638
+ if (mergedItems2.length !== items2.length) {
28639
+ sectionChanged = true;
28640
+ }
28641
+ for (const item of pinnedSummaryItems) {
28642
+ seenIds.add(item.id);
28643
+ }
28644
+ const stableItems2 = stabilizeConversationSectionItems(
28645
+ section.items,
28646
+ sortPinnedConversations(mergedItems2)
28647
+ );
28648
+ if (!sectionChanged && stableItems2 === section.items) {
28649
+ return section;
28650
+ }
28651
+ changed = true;
28652
+ return {
28653
+ ...section,
28654
+ items: stableItems2
28655
+ };
28656
+ }
28564
28657
  const summaryItems = summarySectionItemsById.get(section.id) ?? [];
28565
28658
  const summaryIdsForSection = new Set(summaryItems.map((item) => item.id));
28566
28659
  const items = section.items.map((item) => {
@@ -28590,7 +28683,7 @@ function updateConversationSectionsFromSummaries(previous, conversations, option
28590
28683
  ...section,
28591
28684
  items
28592
28685
  } : section;
28593
- if (section.kind === "pinned" || summaryItems.length === 0) {
28686
+ if (summaryItems.length === 0) {
28594
28687
  if (sectionChanged) {
28595
28688
  changed = true;
28596
28689
  }
@@ -28620,13 +28713,25 @@ function updateConversationSectionsFromSummaries(previous, conversations, option
28620
28713
  };
28621
28714
  });
28622
28715
  const existingSectionIds = new Set(nextSections.map((section) => section.id));
28716
+ const newPinnedConversations = existingSectionIds.has("pinned") || !options.sectionPinnedLabel ? [] : conversations.filter(
28717
+ (conversation) => (conversation.pinnedAtUnixMs ?? 0) > 0 && !seenIds.has(conversation.id)
28718
+ );
28623
28719
  const newConversations = [...summarySectionItemsById.entries()].flatMap(
28624
28720
  ([sectionId, items]) => existingSectionIds.has(sectionId) ? [] : items.filter((conversation) => !seenIds.has(conversation.id))
28625
28721
  );
28626
- if (newConversations.length === 0) {
28722
+ if (newPinnedConversations.length === 0 && newConversations.length === 0) {
28627
28723
  return changed ? nextSections : previous;
28628
28724
  }
28629
28725
  const sectionsWithInsertions = [...nextSections];
28726
+ if (newPinnedConversations.length > 0 && options.sectionPinnedLabel) {
28727
+ sectionsWithInsertions.unshift({
28728
+ id: "pinned",
28729
+ kind: "pinned",
28730
+ label: options.sectionPinnedLabel,
28731
+ project: null,
28732
+ items: sortPinnedConversations(newPinnedConversations)
28733
+ });
28734
+ }
28630
28735
  for (const conversation of newConversations) {
28631
28736
  const targetSectionId = conversation.project ? `project:${normalizeConversationProjectPath(conversation.project.path)}` : "conversations";
28632
28737
  const targetIndex = sectionsWithInsertions.findIndex(
@@ -28650,8 +28755,24 @@ function updateConversationSectionsFromSummaries(previous, conversations, option
28650
28755
  }
28651
28756
  return sectionsWithInsertions;
28652
28757
  }
28758
+ function sortPinnedConversations(conversations) {
28759
+ return [...conversations].sort(
28760
+ (left, right) => (right.pinnedAtUnixMs ?? 0) - (left.pinnedAtUnixMs ?? 0) || (right.sortTimeUnixMs ?? right.updatedAtUnixMs) - (left.sortTimeUnixMs ?? left.updatedAtUnixMs) || left.id.localeCompare(right.id)
28761
+ );
28762
+ }
28653
28763
  function projectRuntimeSectionsToConversationSections(input) {
28654
- const pinned = [];
28764
+ const pinned = input.pinned ? buildAgentGUIConversationSummaries({
28765
+ conversationFilter: input.conversationFilter,
28766
+ provider: AGENT_GUI_CONVERSATION_RAIL_PROJECTION_PROVIDER,
28767
+ snapshot: {
28768
+ composerOptionsByProvider: {},
28769
+ presences: [],
28770
+ sessionMessagesById: {},
28771
+ sessions: input.pinned.sessions,
28772
+ workspaceId: input.workspaceId
28773
+ },
28774
+ userProjects: []
28775
+ }).filter((conversation) => (conversation.pinnedAtUnixMs ?? 0) > 0) : [];
28655
28776
  const result = [];
28656
28777
  for (const section of input.sections) {
28657
28778
  const project = section.userProject ? {
@@ -28693,14 +28814,16 @@ function projectRuntimeSectionsToConversationSections(input) {
28693
28814
  });
28694
28815
  }
28695
28816
  if (pinned.length > 0) {
28817
+ const pinnedById = /* @__PURE__ */ new Map();
28818
+ for (const conversation of pinned) {
28819
+ pinnedById.set(conversation.id, conversation);
28820
+ }
28696
28821
  result.unshift({
28697
28822
  id: "pinned",
28698
28823
  kind: "pinned",
28699
28824
  label: input.labels.sectionPinned,
28700
28825
  project: null,
28701
- items: pinned.sort(
28702
- (left, right) => (right.pinnedAtUnixMs ?? 0) - (left.pinnedAtUnixMs ?? 0) || (right.sortTimeUnixMs ?? right.updatedAtUnixMs) - (left.sortTimeUnixMs ?? left.updatedAtUnixMs) || left.id.localeCompare(right.id)
28703
- )
28826
+ items: sortPinnedConversations([...pinnedById.values()])
28704
28827
  });
28705
28828
  }
28706
28829
  return result;
@@ -28718,12 +28841,11 @@ var agentGUIProviderRailOrder = [
28718
28841
  "codex",
28719
28842
  "claude-code",
28720
28843
  "cursor",
28721
- "tutti-agent",
28722
28844
  "opencode",
28845
+ "tutti-agent",
28723
28846
  "nexight",
28724
28847
  "hermes",
28725
- "openclaw",
28726
- "gemini"
28848
+ "openclaw"
28727
28849
  ];
28728
28850
  var agentGUIProviderRailDefaultProviders = [
28729
28851
  "codex",
@@ -29657,6 +29779,7 @@ function useAgentGUIConversationRail({
29657
29779
  const workspaceIdRef = useRef12(workspaceId);
29658
29780
  const runtimeListSessionSections = agentActivityRuntime.listSessionSections;
29659
29781
  const runtimeListSessionSectionPage = agentActivityRuntime.listSessionSectionPage;
29782
+ const runtimeListPinnedSessionsPage = agentActivityRuntime.listPinnedSessionsPage;
29660
29783
  const runtimeSectionsEnabled = !previewMode && Boolean(runtimeListSessionSections) && Boolean(runtimeListSessionSectionPage);
29661
29784
  const sectionAgentTargetId = conversationFilter.kind === "agentTarget" ? conversationFilter.agentTargetId.trim() : sectionAgentTargetFallbackId?.trim() ?? "";
29662
29785
  const userProjectPaths = useMemo9(
@@ -29723,13 +29846,17 @@ function useAgentGUIConversationRail({
29723
29846
  const sections = projectRuntimeSectionsToConversationSections({
29724
29847
  conversationFilter,
29725
29848
  labels: sectionProjectionLabels,
29849
+ pinned: page.pinned,
29726
29850
  sections: page.sections,
29727
29851
  workspaceId: page.workspaceId
29728
29852
  });
29729
29853
  const sectionsWithSummaries = updateConversationSectionsFromSummaries(
29730
29854
  sections,
29731
29855
  conversationsRef.current,
29732
- { sectionConversationsLabel: labels.sectionConversations }
29856
+ {
29857
+ sectionConversationsLabel: labels.sectionConversations,
29858
+ sectionPinnedLabel: labels.sectionPinned
29859
+ }
29733
29860
  );
29734
29861
  setRuntimeRailSections(
29735
29862
  (current) => stabilizeConversationSections(
@@ -29740,6 +29867,13 @@ function useAgentGUIConversationRail({
29740
29867
  setRuntimeRailSectionsPending(false);
29741
29868
  setSectionPageStates(() => {
29742
29869
  const next = /* @__PURE__ */ new Map();
29870
+ if (page.pinned) {
29871
+ next.set("pinned", {
29872
+ hasMore: page.pinned.hasMore,
29873
+ isLoading: false,
29874
+ nextCursor: page.pinned.nextCursor ?? null
29875
+ });
29876
+ }
29743
29877
  for (const section of page.sections) {
29744
29878
  next.set(section.sectionKey, {
29745
29879
  hasMore: section.hasMore,
@@ -29780,27 +29914,32 @@ function useAgentGUIConversationRail({
29780
29914
  );
29781
29915
  setRuntimeRailSections(
29782
29916
  (current) => updateConversationSectionsFromSummaries(current, filteredConversations, {
29783
- sectionConversationsLabel: labels.sectionConversations
29917
+ sectionConversationsLabel: labels.sectionConversations,
29918
+ sectionPinnedLabel: labels.sectionPinned
29784
29919
  })
29785
29920
  );
29786
29921
  }, [
29787
29922
  conversationFilter,
29788
29923
  conversations,
29789
29924
  labels.sectionConversations,
29925
+ labels.sectionPinned,
29790
29926
  runtimeSectionsEnabled
29791
29927
  ]);
29792
29928
  const loadMoreSectionConversations = useCallback10(
29793
29929
  (section) => {
29794
- if (!runtimeListSessionSectionPage || previewMode || conversationQuery.trim()) {
29795
- return;
29796
- }
29797
- if (section.kind === "pinned") {
29930
+ if (previewMode || conversationQuery.trim()) {
29798
29931
  return;
29799
29932
  }
29800
29933
  const currentPageState = sectionPageStates.get(section.id);
29801
29934
  if (currentPageState?.isLoading || currentPageState?.hasMore === false) {
29802
29935
  return;
29803
29936
  }
29937
+ if (section.kind === "pinned" && !runtimeListPinnedSessionsPage) {
29938
+ return;
29939
+ }
29940
+ if (section.kind !== "pinned" && !runtimeListSessionSectionPage) {
29941
+ return;
29942
+ }
29804
29943
  const fallbackCursor = conversationRailPageCursor(section.items);
29805
29944
  const cursor = currentPageState?.nextCursor ?? fallbackCursor;
29806
29945
  const requestSequence = pagingRequestSequenceRef.current;
@@ -29815,7 +29954,82 @@ function useAgentGUIConversationRail({
29815
29954
  });
29816
29955
  return next;
29817
29956
  });
29818
- void runtimeListSessionSectionPage({
29957
+ if (section.kind === "pinned") {
29958
+ const listPinnedSessionsPage = runtimeListPinnedSessionsPage;
29959
+ if (!listPinnedSessionsPage) {
29960
+ return;
29961
+ }
29962
+ void listPinnedSessionsPage({
29963
+ agentTargetId: sectionAgentTargetId || void 0,
29964
+ cursor: cursor || void 0,
29965
+ limit: AGENT_GUI_CONVERSATION_RAIL_SECTION_PAGE_SIZE,
29966
+ signal: abortController.signal,
29967
+ workspaceId
29968
+ }).then((page) => {
29969
+ if (abortController.signal.aborted || requestSequence !== pagingRequestSequenceRef.current) {
29970
+ return;
29971
+ }
29972
+ const pageConversations = buildAgentGUIConversationSummaries({
29973
+ conversationFilter,
29974
+ provider: AGENT_GUI_CONVERSATION_RAIL_PROJECTION_PROVIDER,
29975
+ snapshot: {
29976
+ composerOptionsByProvider: {},
29977
+ presences: [],
29978
+ sessionMessagesById: {},
29979
+ sessions: page.sessions,
29980
+ workspaceId
29981
+ },
29982
+ userProjects: []
29983
+ }).filter((conversation) => (conversation.pinnedAtUnixMs ?? 0) > 0);
29984
+ setRuntimeRailSections((current) => {
29985
+ if (!current) {
29986
+ return current;
29987
+ }
29988
+ return current.map(
29989
+ (candidate) => candidate.id === section.id ? {
29990
+ ...candidate,
29991
+ items: mergeConversationRailPageItems(
29992
+ candidate.items,
29993
+ pageConversations
29994
+ )
29995
+ } : candidate
29996
+ );
29997
+ });
29998
+ setSectionPageStates((current) => {
29999
+ const next = new Map(current);
30000
+ next.set(section.id, {
30001
+ hasMore: page.hasMore,
30002
+ isLoading: false,
30003
+ nextCursor: page.nextCursor ?? null
30004
+ });
30005
+ return next;
30006
+ });
30007
+ }).catch(() => {
30008
+ if (abortController.signal.aborted || requestSequence !== pagingRequestSequenceRef.current) {
30009
+ return;
30010
+ }
30011
+ setSectionPageStates((current) => {
30012
+ const next = new Map(current);
30013
+ const existing = next.get(section.id);
30014
+ next.set(section.id, {
30015
+ hasMore: existing?.hasMore ?? true,
30016
+ isLoading: false,
30017
+ nextCursor: existing?.nextCursor ?? null
30018
+ });
30019
+ return next;
30020
+ });
30021
+ }).finally(() => {
30022
+ if (pagingAbortControllersRef.current.get(section.id) === abortController) {
30023
+ pagingAbortControllersRef.current.delete(section.id);
30024
+ }
30025
+ });
30026
+ return;
30027
+ }
30028
+ const listSessionSectionPage = runtimeListSessionSectionPage;
30029
+ if (!listSessionSectionPage) {
30030
+ return;
30031
+ }
30032
+ void listSessionSectionPage({
29819
30033
  agentTargetId: sectionAgentTargetId || void 0,
29820
30034
  cursor: cursor || void 0,
29821
30035
  limit: AGENT_GUI_CONVERSATION_RAIL_SECTION_PAGE_SIZE,
@@ -29888,6 +30102,7 @@ function useAgentGUIConversationRail({
29888
30102
  conversationFilter,
29889
30103
  conversationQuery,
29890
30104
  previewMode,
30105
+ runtimeListPinnedSessionsPage,
29891
30106
  runtimeListSessionSectionPage,
29892
30107
  sectionAgentTargetId,
29893
30108
  sectionPageStates,
@@ -30158,7 +30373,7 @@ var AgentGUIConversationRailPane = memo2(
30158
30373
  const isSectionCollapsed = isProjectSection && collapsedProjectSectionIds.has(section.id);
30159
30374
  const projectConversationCount = normalizedProjectPath ? projectConversationCountsByPath.get(normalizedProjectPath) ?? 0 : 0;
30160
30375
  const sectionPageState = sectionPageStates.get(section.id);
30161
- const sectionHasMore = !conversationQuery.trim() && section.kind !== "pinned" && sectionPageState?.hasMore === true;
30376
+ const sectionHasMore = !conversationQuery.trim() && sectionPageState?.hasMore === true;
30162
30377
  return /* @__PURE__ */ jsxs21(Fragment8, { children: [
30163
30378
  showProjectRailHeader ? /* @__PURE__ */ jsx34(
30164
30379
  AgentGUIProjectRailHeader,
@@ -31498,16 +31713,6 @@ var AGENT_HOST_MANAGED_TOOLCHAIN_AGENTS = [
31498
31713
  runtimeManaged: true,
31499
31714
  helperProvider: "opencode",
31500
31715
  aliases: ["open code", "open-code", "opencode-ai"]
31501
- },
31502
- {
31503
- id: "gemini",
31504
- // i18n-check-ignore: Provider brand name.
31505
- label: "Gemini CLI",
31506
- toolIds: ["gemini-cli"],
31507
- agentIds: ["gemini"],
31508
- runtimeManaged: true,
31509
- helperProvider: "gemini",
31510
- aliases: ["gemini cli"]
31511
31716
  }
31512
31717
  ];
31513
31718
  var WORKSPACE_DESKTOP_MANAGED_AGENT_DOCK_PROVIDER_ORDER = AGENT_HOST_MANAGED_TOOLCHAIN_AGENTS.map(
@@ -31865,7 +32070,7 @@ function composerOverridesByAgentTargetIdEqual(left, right) {
31865
32070
  return true;
31866
32071
  }
31867
32072
  function areAgentGUINodePropsEqual(previous, next) {
31868
- 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.onHandoffConversation === next.onHandoffConversation && previous.onCapabilitySettingsRequest === next.onCapabilitySettingsRequest && previous.onAgentProviderLogin === next.onAgentProviderLogin && previous.accountMenuState === next.accountMenuState && previous.providerTargets === next.providerTargets && previous.providerTargetsLoading === next.providerTargetsLoading && previous.providerRailAllPresentation?.iconUrl === next.providerRailAllPresentation?.iconUrl && previous.renderSidebarFooter === next.renderSidebarFooter && previous.providerRailMode === next.providerRailMode && previous.renderProviderRailEmpty === next.renderProviderRailEmpty && previous.renderProviderUnavailableState === next.renderProviderUnavailableState && previous.comingSoonProviders === next.comingSoonProviders && previous.providerReadinessGates === next.providerReadinessGates && 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 && previous.workspaceAgentProbes === next.workspaceAgentProbes && previous.onAgentProbeDemandChange === next.onAgentProbeDemandChange && previous.onAgentProbeRefreshRequest === next.onAgentProbeRefreshRequest && previous.providerAuthAccountLabels === next.providerAuthAccountLabels && previous.managedAgentsState === next.managedAgentsState && previous.contextMentionProviders === next.contextMentionProviders && previous.workspaceAppIcons === next.workspaceAppIcons && previous.embedded === next.embedded && previous.previewMode === next.previewMode && previous.isActive === next.isActive && previous.composerFocusRequestSequence === next.composerFocusRequestSequence && previous.newConversationRequestSequence === next.newConversationRequestSequence && previous.openSessionRequest === next.openSessionRequest && previous.prefillPromptRequest === next.prefillPromptRequest;
32073
+ 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.onHandoffConversation === next.onHandoffConversation && previous.onCapabilitySettingsRequest === next.onCapabilitySettingsRequest && previous.onAgentProviderLogin === next.onAgentProviderLogin && previous.accountMenuState === next.accountMenuState && previous.providerTargets === next.providerTargets && previous.providerTargetsLoading === next.providerTargetsLoading && previous.providerRailAllPresentation?.iconUrl === next.providerRailAllPresentation?.iconUrl && previous.renderSidebarFooter === next.renderSidebarFooter && previous.providerRailMode === next.providerRailMode && previous.renderProviderRailEmpty === next.renderProviderRailEmpty && previous.renderProviderUnavailableState === next.renderProviderUnavailableState && previous.renderProviderReadinessGateState === next.renderProviderReadinessGateState && previous.comingSoonProviders === next.comingSoonProviders && previous.providerReadinessGates === next.providerReadinessGates && 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 && previous.workspaceAgentProbes === next.workspaceAgentProbes && previous.onAgentProbeDemandChange === next.onAgentProbeDemandChange && previous.onAgentProbeRefreshRequest === next.onAgentProbeRefreshRequest && previous.providerAuthAccountLabels === next.providerAuthAccountLabels && previous.managedAgentsState === next.managedAgentsState && previous.contextMentionProviders === next.contextMentionProviders && previous.workspaceAppIcons === next.workspaceAppIcons && previous.embedded === next.embedded && previous.previewMode === next.previewMode && previous.isActive === next.isActive && previous.composerFocusRequestSequence === next.composerFocusRequestSequence && previous.newConversationRequestSequence === next.newConversationRequestSequence && previous.openSessionRequest === next.openSessionRequest && previous.prefillPromptRequest === next.prefillPromptRequest;
31869
32074
  }
31870
32075
  var AgentGUINode = memo3(function AgentGUINode2({
31871
32076
  nodeId,
@@ -31899,6 +32104,7 @@ var AgentGUINode = memo3(function AgentGUINode2({
31899
32104
  providerRailMode = "catalog",
31900
32105
  renderProviderRailEmpty,
31901
32106
  renderProviderUnavailableState,
32107
+ renderProviderReadinessGateState,
31902
32108
  renderSidebarFooter,
31903
32109
  comingSoonProviders,
31904
32110
  providerReadinessGates = null,
@@ -32951,6 +33157,7 @@ var AgentGUINode = memo3(function AgentGUINode2({
32951
33157
  renderSidebarFooter,
32952
33158
  renderProviderRailEmpty,
32953
33159
  renderProviderUnavailableState,
33160
+ renderProviderReadinessGateState,
32954
33161
  providerRailAllPresentation,
32955
33162
  actions: viewActions,
32956
33163
  isActive,