@tutti-os/agent-gui 0.0.72 → 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 +9 -0
  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 +58 -6
  42. package/dist/index.js +317 -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,14 +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";
29
- import "./chunk-BHNJN2TR.js";
26
+ } from "./chunk-T5CEU7WH.js";
27
+ import "./chunk-FPODKSSV.js";
28
+ import "./chunk-BT2DT2P7.js";
29
+ import {
30
+ resolveAgentGuiWorkbenchProviderLabel
31
+ } from "./chunk-BTUOROCD.js";
30
32
  import {
31
33
  AgentInteractivePromptSurface,
32
34
  approvalOptionDisplayLabel
33
- } from "./chunk-Q6AWM3RH.js";
35
+ } from "./chunk-Z72JKSAY.js";
34
36
  import {
35
37
  PLAN_IMPLEMENTATION_ACTION_FEEDBACK,
36
38
  PLAN_IMPLEMENTATION_ACTION_IMPLEMENT,
@@ -49,7 +51,7 @@ import {
49
51
  resolveAgentGUIExplicitConversationTitle,
50
52
  resolveAgentGUIProviderDisplayLabel,
51
53
  resolveAgentGUIProviderIdentity
52
- } from "./chunk-5H6NINJY.js";
54
+ } from "./chunk-LWFV4PS5.js";
53
55
  import {
54
56
  AGENT_PASTED_TEXT_BLOCK_KIND,
55
57
  AGENT_PASTED_TEXT_MENTION_KIND,
@@ -86,14 +88,14 @@ import {
86
88
  textPromptContent,
87
89
  toLocalShortDateTime,
88
90
  useProjectedAgentConversation
89
- } from "./chunk-OBJRIQPX.js";
91
+ } from "./chunk-ZSYDFQ4N.js";
90
92
  import {
91
93
  AgentMessageMarkdown,
92
94
  AgentTargetPresentationProvider,
93
95
  ZoomableImage,
94
96
  cn,
95
97
  resolveWorkspaceLinkAction
96
- } from "./chunk-IVIXKAEH.js";
98
+ } from "./chunk-GLMDAZSQ.js";
97
99
  import {
98
100
  openAgentEnvPanel
99
101
  } from "./chunk-PSLAWU25.js";
@@ -104,12 +106,12 @@ import {
104
106
  DEFAULT_AGENT_MENTION_FILTER,
105
107
  agentMentionItemKey,
106
108
  preloadAgentMentionBrowse
107
- } from "./chunk-466AWJTS.js";
109
+ } from "./chunk-KVS7J7BJ.js";
108
110
  import {
109
111
  buildWorkspaceAgentActivityListViewModel,
110
112
  isWorkspaceAgentUntitledTask
111
- } from "./chunk-3PKRGSMH.js";
112
- import "./chunk-SVGIWXNK.js";
113
+ } from "./chunk-6EREXANR.js";
114
+ import "./chunk-VERGPY42.js";
113
115
  import {
114
116
  resolveWorkspaceAgentSessionSortTimeUnixMs
115
117
  } from "./chunk-IBIMGLCD.js";
@@ -122,7 +124,7 @@ import {
122
124
  mentionItemToAttrs,
123
125
  normalizeAgentSessionMentionTitle,
124
126
  parseMentionItemFromHref
125
- } from "./chunk-KWQ4N4IZ.js";
127
+ } from "./chunk-NO7WDGST.js";
126
128
  import "./chunk-Y35GDLP2.js";
127
129
  import "./chunk-LUGELG5V.js";
128
130
  import {
@@ -146,7 +148,7 @@ import {
146
148
  useAgentHostApi,
147
149
  useOptionalAgentActivityRuntime,
148
150
  useOptionalAgentHostApi
149
- } from "./chunk-GDFQXJMG.js";
151
+ } from "./chunk-FHWE5SUF.js";
150
152
  import {
151
153
  WORKSPACE_AGENT_ACTIVITY_RUNTIME_SESSION_ORIGIN,
152
154
  createWorkspaceAgentActivityUserMessageIdFromClientSubmitId,
@@ -154,21 +156,21 @@ import {
154
156
  isWorkspaceAgentActivityRuntimeSessionOrigin,
155
157
  mergeWorkspaceAgentActivityDurableAndOverlayMessages,
156
158
  selectWorkspaceAgentActivityOverlayMessages
157
- } from "./chunk-4US2YHBY.js";
159
+ } from "./chunk-RA3OUR64.js";
158
160
  import {
159
161
  AgentGuiI18nProvider,
160
162
  agentGuiI18nModule,
161
163
  agentGuiI18nResources,
162
164
  translate,
163
165
  useTranslation
164
- } from "./chunk-C7K3EFGI.js";
166
+ } from "./chunk-4XIHKCWC.js";
165
167
  import "./chunk-PJP5BUU6.js";
166
168
  import {
167
169
  agentColorfulUrl,
168
170
  cursorColorfulUrl,
169
171
  normalizeManagedAgentProvider
170
- } from "./chunk-4I2VCAMW.js";
171
- import "./chunk-G6BVEY7I.js";
172
+ } from "./chunk-SL2QSEIE.js";
173
+ import "./chunk-W5AJTBA7.js";
172
174
  import {
173
175
  AGENT_CONTEXT_MENTION_PROVIDER_IDS
174
176
  } from "./chunk-JM24HADP.js";
@@ -2264,6 +2266,7 @@ function getTestAgentQueuedPromptRuntime() {
2264
2266
  // agent-gui/agentGuiNode/controller/useAgentGUINodeController.ts
2265
2267
  import {
2266
2268
  resolveSubmitAvailability,
2269
+ isLiveTurnLifecyclePhase,
2267
2270
  resolveAgentActivityCapability as resolveAgentActivityCapability2,
2268
2271
  resolveAgentActivityUsage,
2269
2272
  selectSessionDisplayStatuses
@@ -2277,7 +2280,6 @@ var AGENT_PROVIDERS = [
2277
2280
  "tutti-agent",
2278
2281
  "nexight",
2279
2282
  "opencode",
2280
- "gemini",
2281
2283
  "openclaw",
2282
2284
  "hermes"
2283
2285
  ];
@@ -2321,7 +2323,6 @@ var DEFAULT_AGENT_SETTINGS = {
2321
2323
  cursor: false,
2322
2324
  nexight: false,
2323
2325
  opencode: false,
2324
- gemini: false,
2325
2326
  openclaw: false,
2326
2327
  hermes: false
2327
2328
  },
@@ -2332,7 +2333,6 @@ var DEFAULT_AGENT_SETTINGS = {
2332
2333
  cursor: "",
2333
2334
  nexight: "",
2334
2335
  opencode: "",
2335
- gemini: "",
2336
2336
  openclaw: "",
2337
2337
  hermes: ""
2338
2338
  },
@@ -2343,7 +2343,6 @@ var DEFAULT_AGENT_SETTINGS = {
2343
2343
  cursor: [],
2344
2344
  nexight: [],
2345
2345
  opencode: [],
2346
- gemini: [],
2347
2346
  openclaw: [],
2348
2347
  hermes: []
2349
2348
  },
@@ -4787,12 +4786,9 @@ function normalizeAgentGUIConversationListFilter(input) {
4787
4786
  if (input.conversationFilter) {
4788
4787
  return normalizeAgentGUIConversationFilter(input.conversationFilter);
4789
4788
  }
4790
- return null;
4789
+ return { kind: "all" };
4791
4790
  }
4792
- function conversationFilterKey(filter, provider) {
4793
- if (!filter) {
4794
- return `legacy-provider:${provider}`;
4795
- }
4791
+ function conversationFilterKey(filter) {
4796
4792
  const normalized = normalizeAgentGUIConversationFilter(filter);
4797
4793
  if (normalized.kind === "all") {
4798
4794
  return "all";
@@ -4800,7 +4796,7 @@ function conversationFilterKey(filter, provider) {
4800
4796
  return `agent-target:${normalized.agentTargetId}`;
4801
4797
  }
4802
4798
  function conversationRetainableForQueryFilter(conversation, filter) {
4803
- if (!conversation || !filter || filter.kind !== "agentTarget") {
4799
+ if (!conversation || filter.kind !== "agentTarget") {
4804
4800
  return true;
4805
4801
  }
4806
4802
  return matchesAgentGUIConversationSummaryFilter(conversation, filter);
@@ -4810,12 +4806,11 @@ function createAgentGUIConversationListQueryKey(input) {
4810
4806
  if (!normalized) {
4811
4807
  return null;
4812
4808
  }
4813
- const providerScope = normalized.conversationFilter ? "conversation-filter" : normalized.provider;
4814
4809
  const queryKey = [
4815
4810
  normalized.workspaceId,
4816
4811
  normalized.userId,
4817
- providerScope,
4818
- conversationFilterKey(normalized.conversationFilter, normalized.provider),
4812
+ "conversation-filter",
4813
+ conversationFilterKey(normalized.conversationFilter),
4819
4814
  normalized.sessionOrigin
4820
4815
  ].join("::");
4821
4816
  return queryKey;
@@ -5584,8 +5579,8 @@ async function refreshAgentGUIConversationListQuery(query, reason, options = {})
5584
5579
  userId: state.query.userId
5585
5580
  };
5586
5581
  const currentWorkspaceAgentSnapshot = getWorkspaceAgentSnapshotForConversations(workspaceAgentsInput);
5587
- const canProjectExplicitFilterFromCurrentSnapshot = reason === "projection-sync" && state.query.conversationFilter !== null && currentWorkspaceAgentSnapshot.sessions.length > 0;
5588
- 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(
5589
5584
  workspaceAgentsInput
5590
5585
  );
5591
5586
  if (requestId !== requestIdByQueryKey.get(queryKey)) {
@@ -5641,7 +5636,7 @@ async function refreshAgentGUIConversationListQuery(query, reason, options = {})
5641
5636
  return agentSessionId && dirtySessionIds.has(agentSessionId) || syncSessionId && dirtySessionIds.has(syncSessionId);
5642
5637
  }) : workspaceAgentSnapshot.sessions;
5643
5638
  const baseConversations = buildAgentGUIConversationSummaries({
5644
- ...state.query.conversationFilter ? { conversationFilter: state.query.conversationFilter } : {},
5639
+ conversationFilter: state.query.conversationFilter,
5645
5640
  snapshot: canApplyDirtySessionProjection ? {
5646
5641
  ...workspaceAgentSnapshot,
5647
5642
  sessions: projectionSessions
@@ -5675,7 +5670,7 @@ async function refreshAgentGUIConversationListQuery(query, reason, options = {})
5675
5670
  );
5676
5671
  const retainableForQueryFilter = (agentSessionId) => {
5677
5672
  const filter = state.query.conversationFilter;
5678
- if (!filter || filter.kind !== "agentTarget") {
5673
+ if (filter.kind !== "agentTarget") {
5679
5674
  return true;
5680
5675
  }
5681
5676
  const snapshotAgentTargetId = snapshotSessionAgentTargetIdById.get(agentSessionId);
@@ -6640,7 +6635,7 @@ function nodeComposerOverridesForProvider(data) {
6640
6635
  return data.composerOverridesByProvider?.[data.provider] ?? data.composerOverrides ?? null;
6641
6636
  }
6642
6637
  function composerSupportForProvider(provider) {
6643
- if (provider === "claude-code" || provider === "codex" || provider === "gemini" || provider === "opencode") {
6638
+ if (provider === "claude-code" || provider === "codex" || provider === "opencode") {
6644
6639
  return {
6645
6640
  model: true,
6646
6641
  permission: provider === "claude-code" || provider === "codex",
@@ -8507,6 +8502,14 @@ function conversationBusyStatusFromAgentActivityDisplayStatus(status) {
8507
8502
  }
8508
8503
  return null;
8509
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
+ }
8510
8513
  function reuseAgentActivityDisplayStatusesIfUnchanged(previous, next) {
8511
8514
  if (!previous || previous.size !== next.size) {
8512
8515
  return next;
@@ -8796,7 +8799,7 @@ function mergeSessionControlStatePatch(current, patch) {
8796
8799
  }
8797
8800
  if (patch.turn?.phase) {
8798
8801
  next.turnLifecycle = {
8799
- 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,
8800
8803
  phase: patch.turn.phase,
8801
8804
  settling: patch.turn.settling,
8802
8805
  outcome: patch.turn.outcome ?? null,
@@ -9332,6 +9335,7 @@ function useAgentGUINodeController({
9332
9335
  ),
9333
9336
  [agentActivitySnapshot.sessions]
9334
9337
  );
9338
+ const activeRuntimeSession = runtimeSessionsBySessionId.get(activeConversationId ?? "") ?? null;
9335
9339
  const stableRuntimeSyncStateBySessionId = useMemo3(() => {
9336
9340
  const current = stableRuntimeSyncStateBySessionIdRef.current;
9337
9341
  let next = current;
@@ -12990,14 +12994,26 @@ function useAgentGUINodeController({
12990
12994
  if (sessionState?.pendingInteractive) {
12991
12995
  return true;
12992
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
+ }
12993
13007
  return agentActivityDisplayStatusBusy(
12994
13008
  agentActivityDisplayStatuses.get(normalizedAgentSessionId)
12995
13009
  );
12996
13010
  },
12997
13011
  [
12998
13012
  agentActivityDisplayStatuses,
13013
+ conversations,
12999
13014
  isRespondingApproval,
13000
13015
  isSubmitting,
13016
+ runtimeSessionsBySessionId,
13001
13017
  sessionViewRef
13002
13018
  ]
13003
13019
  );
@@ -13171,7 +13187,7 @@ function useAgentGUINodeController({
13171
13187
  setDetailError(translate("agentHost.agentGui.promptImagesUnsupported"));
13172
13188
  return;
13173
13189
  }
13174
- const activeTurnId = activeSessionState?.turnLifecycle?.activeTurnId?.trim() ?? "";
13190
+ const activeTurnId = activeRuntimeSession?.turnLifecycle?.activeTurnId?.trim() || activeSessionState?.turnLifecycle?.activeTurnId?.trim() || "";
13175
13191
  if (activeTurnId === "") {
13176
13192
  return;
13177
13193
  }
@@ -13183,7 +13199,13 @@ function useAgentGUINodeController({
13183
13199
  { bypassLocalQueue: true, guidance: true }
13184
13200
  );
13185
13201
  },
13186
- [activeSessionState, promptImagesSupported, submitExistingPrompt, translate]
13202
+ [
13203
+ activeRuntimeSession,
13204
+ activeSessionState,
13205
+ promptImagesSupported,
13206
+ submitExistingPrompt,
13207
+ translate
13208
+ ]
13187
13209
  );
13188
13210
  useEffect4(() => {
13189
13211
  if (previewMode) {
@@ -14607,13 +14629,15 @@ function useAgentGUINodeController({
14607
14629
  );
14608
14630
  }, [conversationUserIds, ensureAccountProfiles]);
14609
14631
  const projectionConversationRef = useRef4(null);
14632
+ const activeRuntimeSessionLiveTurn = agentActivitySessionHasLiveTurn(activeRuntimeSession);
14633
+ const activeRuntimeTurnLifecycle = activeRuntimeSessionLiveTurn ? activeRuntimeSession?.turnLifecycle ?? null : null;
14610
14634
  const projectionConversation = useMemo3(() => {
14611
14635
  if (!activeConversation) {
14612
14636
  projectionConversationRef.current = null;
14613
14637
  return null;
14614
14638
  }
14615
14639
  const previous = projectionConversationRef.current;
14616
- const turnLifecycle = activeSessionState?.agentSessionId === activeConversation.id ? activeSessionState.turnLifecycle ?? null : null;
14640
+ const turnLifecycle = activeRuntimeTurnLifecycle ?? (activeSessionState?.agentSessionId === activeConversation.id ? activeSessionState.turnLifecycle ?? null : null);
14617
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)) {
14618
14642
  return previous;
14619
14643
  }
@@ -14641,6 +14665,9 @@ function useAgentGUINodeController({
14641
14665
  activeConversation?.title,
14642
14666
  activeConversation?.titleFallback,
14643
14667
  activeConversation?.userId,
14668
+ activeRuntimeTurnLifecycle?.activeTurnId,
14669
+ activeRuntimeTurnLifecycle?.phase,
14670
+ activeRuntimeTurnLifecycle?.settling,
14644
14671
  activeSessionState?.agentSessionId,
14645
14672
  activeSessionState?.turnLifecycle?.activeTurnId,
14646
14673
  activeSessionState?.turnLifecycle?.phase,
@@ -14741,7 +14768,7 @@ function useAgentGUINodeController({
14741
14768
  conversation,
14742
14769
  workspaceId
14743
14770
  ]);
14744
- const activeLiveState = activeConversationLiveState;
14771
+ const activeLiveState = activeConversationLiveState === "inactive" && activeRuntimeSessionLiveTurn ? "active" : activeConversationLiveState;
14745
14772
  const activationError = activation.errorFor(activeConversationId);
14746
14773
  const activationErrorCode = activation.codeFor(activeConversationId);
14747
14774
  const hasProviderSessionNotFoundError = isNonRetryableResumeErrorCode(activationErrorCode);
@@ -14889,7 +14916,6 @@ function useAgentGUINodeController({
14889
14916
  activeConversation?.title ?? ""
14890
14917
  ) : null;
14891
14918
  const pendingInteractivePrompt = serverInteractivePrompt ?? planImplementationPromptVM;
14892
- const activeRuntimeSession = runtimeSessionsBySessionId.get(activeConversationId ?? "") ?? null;
14893
14919
  useEffect4(() => {
14894
14920
  const provider = normalizeOptionalText2(
14895
14921
  activeRuntimeSession?.provider ?? activeConversation?.provider
@@ -14913,8 +14939,10 @@ function useAgentGUINodeController({
14913
14939
  ]);
14914
14940
  const activeActivityDisplayStatus = activeConversationId ? agentActivityDisplayStatuses.get(activeConversationId) ?? null : null;
14915
14941
  const activeHasPendingSubmittedTurn = activeConversationId ? Boolean(pendingTurnIdBySessionIdRef.current[activeConversationId]) : false;
14916
- const activeSubmitBlocked = activeSessionState ? resolveSubmitAvailability(activeSessionState).state === "blocked" : false;
14917
- 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;
14918
14946
  const activeSessionResumable = activeRuntimeSession?.resumable ?? activeConversation?.resumable ?? activeSessionState?.resumable;
14919
14947
  const normalizedActiveConversationId = activeConversationId ?? "";
14920
14948
  const activeConversationActivationState = activeConversationId ? activation.stateFor(activeConversationId) : null;
@@ -14962,7 +14990,7 @@ function useAgentGUINodeController({
14962
14990
  hasProviderSessionNotFoundError,
14963
14991
  pendingApproval
14964
14992
  ]);
14965
- 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;
14966
14994
  const canQueueWhileBusy = Boolean(activeConversationId) && (activeConversationBusy || isSubmitting || Boolean(activeSessionState?.pendingInteractive));
14967
14995
  useEffect4(() => {
14968
14996
  const firstVersion = minFiniteMessageVersion(activeMessages);
@@ -15636,6 +15664,7 @@ function useAgentGUINodeController({
15636
15664
  activeLiveState,
15637
15665
  activationError,
15638
15666
  openclawGateway,
15667
+ activeConversationBusy,
15639
15668
  canSubmit,
15640
15669
  composerSettings: stableComposerSettings,
15641
15670
  queuedPrompts,
@@ -17488,6 +17517,10 @@ var CLAUDE_CODE_FALLBACK_COMMANDS = [
17488
17517
  { name: REVIEW_COMMAND }
17489
17518
  ];
17490
17519
  var CURSOR_FALLBACK_COMMANDS = [];
17520
+ var OPENCODE_FALLBACK_COMMANDS = [
17521
+ { name: "compact" },
17522
+ { name: REVIEW_COMMAND }
17523
+ ];
17491
17524
  var CLAUDE_CODE_SLASH_PALETTE_COMMANDS = /* @__PURE__ */ new Set([
17492
17525
  "compact",
17493
17526
  "context",
@@ -17525,13 +17558,18 @@ var PROVIDER_SLASH_POLICY = {
17525
17558
  immediateCommands: /* @__PURE__ */ new Set(),
17526
17559
  reviewPickerCommands: /* @__PURE__ */ new Set(),
17527
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
17528
17566
  }
17529
17567
  };
17530
17568
  function providerSlashPolicy(provider) {
17531
- 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;
17532
17570
  }
17533
17571
  function isACPProvider(provider) {
17534
- return provider === "codex" || provider === "claude-code" || provider === "cursor";
17572
+ return provider === "codex" || provider === "claude-code" || provider === "cursor" || provider === "opencode";
17535
17573
  }
17536
17574
  function resolveSlashCommandsForProvider({
17537
17575
  provider,
@@ -25660,6 +25698,8 @@ function AgentGUINodeView({
25660
25698
  viewModel,
25661
25699
  renderSidebarFooter,
25662
25700
  renderProviderRailEmpty,
25701
+ renderProviderUnavailableState,
25702
+ renderProviderReadinessGateState,
25663
25703
  providerRailAllPresentation,
25664
25704
  onLinkAction,
25665
25705
  onHandoffConversation,
@@ -26207,6 +26247,17 @@ function AgentGUINodeView({
26207
26247
  onRequestComposerFocus: requestComposerFocus
26208
26248
  }
26209
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,
26210
26261
  shouldShowProviderRailConfigButton ? /* @__PURE__ */ jsx34(
26211
26262
  "div",
26212
26263
  {
@@ -26248,17 +26299,6 @@ function AgentGUINodeView({
26248
26299
  }
26249
26300
  )
26250
26301
  }
26251
- ) : null,
26252
- renderSidebarFooter ? /* @__PURE__ */ jsx34(
26253
- "div",
26254
- {
26255
- className: `${AgentGUINode_styles_default.providerRailFooter} nodrag tsh-desktop-no-drag`,
26256
- "data-testid": "agent-gui-sidebar-footer-slot",
26257
- children: renderSidebarFooter({
26258
- currentUserId: viewModel.currentUserId,
26259
- activeConversation: viewModel.activeConversation
26260
- })
26261
- }
26262
26302
  ) : null
26263
26303
  ]
26264
26304
  }
@@ -26341,6 +26381,8 @@ function AgentGUINodeView({
26341
26381
  contextMentionProviders,
26342
26382
  workspaceAppIcons: effectiveWorkspaceAppIcons,
26343
26383
  workspaceUserProjectI18n,
26384
+ renderProviderUnavailableState,
26385
+ renderProviderReadinessGateState,
26344
26386
  previewMode
26345
26387
  }
26346
26388
  ) })
@@ -26591,7 +26633,9 @@ var AgentGUIDetailPane = memo2(function AgentGUIDetailPane2({
26591
26633
  onRequestGitBranches,
26592
26634
  onRequestComposerFocus,
26593
26635
  contextMentionProviders,
26594
- workspaceAppIcons = EMPTY_WORKSPACE_APP_ICONS3
26636
+ workspaceAppIcons = EMPTY_WORKSPACE_APP_ICONS3,
26637
+ renderProviderUnavailableState,
26638
+ renderProviderReadinessGateState
26595
26639
  }) {
26596
26640
  "use memo";
26597
26641
  const timelineRef = useRef12(null);
@@ -26689,7 +26733,7 @@ var AgentGUIDetailPane = memo2(function AgentGUIDetailPane2({
26689
26733
  detailStatus: activeDetailStatus,
26690
26734
  conversation
26691
26735
  });
26692
- const activeConversationTurnBusy = viewModel.isSubmitting || derivedBusyStatus !== null;
26736
+ const activeConversationTurnBusy = viewModel.isSubmitting || viewModel.activeConversationBusy || derivedBusyStatus !== null;
26693
26737
  const isComposerSending = viewModel.isSubmitting || activeConversationTurnBusy || !hasActiveConversation && viewModel.isCreatingConversation;
26694
26738
  const isCollaboratorConversation = isDifferentKnownConversationOwner({
26695
26739
  conversationUserId: viewModel.activeConversation?.userId,
@@ -27353,6 +27397,9 @@ var AgentGUIDetailPane = memo2(function AgentGUIDetailPane2({
27353
27397
  () => viewModel.conversationFilter.kind === "all" ? agentGUILaunchpadIconPresentations() : [agentGUIProviderIconPresentation(emptyHeroProvider)],
27354
27398
  [emptyHeroProvider, viewModel.conversationFilter]
27355
27399
  );
27400
+ const disabledProviderTarget = selectedProviderTargetComingSoon ? viewModel.selectedProviderTarget ?? null : null;
27401
+ const shouldRenderProviderUnavailableState = !hasActiveConversation && disabledProviderTarget !== null && renderProviderUnavailableState !== void 0;
27402
+ const shouldRenderProviderReadinessGateState = !hasActiveConversation && emptyProviderReadinessGate !== null && renderProviderReadinessGateState !== void 0;
27356
27403
  const bottomDockStoreState = useMemo9(
27357
27404
  () => ({
27358
27405
  // The lifted prompt is rendered from props on the pane; the store still
@@ -27709,7 +27756,26 @@ var AgentGUIDetailPane = memo2(function AgentGUIDetailPane2({
27709
27756
  viewportTestId: "agent-gui-timeline",
27710
27757
  viewportClassName: `${AgentGUINode_styles_default.timeline} ${hasActiveConversation ? AgentGUINode_styles_default.timelineWithComposer : AgentGUINode_styles_default.timelineCentered} ${!isTimelineScrolledToTop ? AgentGUINode_styles_default.timelineScrolledFromTop : ""} ${showUnavailableChatEmpty ? AgentGUINode_styles_default.timelineUnavailableChatEmpty : ""}`.trim(),
27711
27758
  viewportContentStyle: AGENT_GUI_TIMELINE_SCROLL_AREA_CONTENT_STYLE,
27712
- children: !hasActiveConversation ? emptyProviderReadinessGate ? /* @__PURE__ */ jsx34(
27759
+ children: !hasActiveConversation ? shouldRenderProviderUnavailableState && disabledProviderTarget ? /* @__PURE__ */ jsx34(Fragment9, { children: renderProviderUnavailableState?.({
27760
+ provider: disabledProviderTarget.provider,
27761
+ providerLabel: labels.emptyProviderForProvider?.(
27762
+ disabledProviderTarget.provider
27763
+ ) ?? resolveAgentGuiWorkbenchProviderLabel(
27764
+ disabledProviderTarget.provider
27765
+ ),
27766
+ target: disabledProviderTarget,
27767
+ iconUrl: resolveAgentGUIHeroIconUrl(
27768
+ disabledProviderTarget.provider
27769
+ ),
27770
+ unavailableReason: disabledProviderTarget.unavailableReason ?? null
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(
27713
27779
  AgentGUIProviderReadinessGatePane,
27714
27780
  {
27715
27781
  provider: emptyHeroProvider,
@@ -28542,6 +28608,52 @@ function updateConversationSectionsFromSummaries(previous, conversations, option
28542
28608
  let changed = false;
28543
28609
  const nextSections = previous.map((section) => {
28544
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
+ }
28545
28657
  const summaryItems = summarySectionItemsById.get(section.id) ?? [];
28546
28658
  const summaryIdsForSection = new Set(summaryItems.map((item) => item.id));
28547
28659
  const items = section.items.map((item) => {
@@ -28571,7 +28683,7 @@ function updateConversationSectionsFromSummaries(previous, conversations, option
28571
28683
  ...section,
28572
28684
  items
28573
28685
  } : section;
28574
- if (section.kind === "pinned" || summaryItems.length === 0) {
28686
+ if (summaryItems.length === 0) {
28575
28687
  if (sectionChanged) {
28576
28688
  changed = true;
28577
28689
  }
@@ -28601,13 +28713,25 @@ function updateConversationSectionsFromSummaries(previous, conversations, option
28601
28713
  };
28602
28714
  });
28603
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
+ );
28604
28719
  const newConversations = [...summarySectionItemsById.entries()].flatMap(
28605
28720
  ([sectionId, items]) => existingSectionIds.has(sectionId) ? [] : items.filter((conversation) => !seenIds.has(conversation.id))
28606
28721
  );
28607
- if (newConversations.length === 0) {
28722
+ if (newPinnedConversations.length === 0 && newConversations.length === 0) {
28608
28723
  return changed ? nextSections : previous;
28609
28724
  }
28610
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
+ }
28611
28735
  for (const conversation of newConversations) {
28612
28736
  const targetSectionId = conversation.project ? `project:${normalizeConversationProjectPath(conversation.project.path)}` : "conversations";
28613
28737
  const targetIndex = sectionsWithInsertions.findIndex(
@@ -28631,8 +28755,24 @@ function updateConversationSectionsFromSummaries(previous, conversations, option
28631
28755
  }
28632
28756
  return sectionsWithInsertions;
28633
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
+ }
28634
28763
  function projectRuntimeSectionsToConversationSections(input) {
28635
- 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) : [];
28636
28776
  const result = [];
28637
28777
  for (const section of input.sections) {
28638
28778
  const project = section.userProject ? {
@@ -28674,14 +28814,16 @@ function projectRuntimeSectionsToConversationSections(input) {
28674
28814
  });
28675
28815
  }
28676
28816
  if (pinned.length > 0) {
28817
+ const pinnedById = /* @__PURE__ */ new Map();
28818
+ for (const conversation of pinned) {
28819
+ pinnedById.set(conversation.id, conversation);
28820
+ }
28677
28821
  result.unshift({
28678
28822
  id: "pinned",
28679
28823
  kind: "pinned",
28680
28824
  label: input.labels.sectionPinned,
28681
28825
  project: null,
28682
- items: pinned.sort(
28683
- (left, right) => (right.pinnedAtUnixMs ?? 0) - (left.pinnedAtUnixMs ?? 0) || (right.sortTimeUnixMs ?? right.updatedAtUnixMs) - (left.sortTimeUnixMs ?? left.updatedAtUnixMs) || left.id.localeCompare(right.id)
28684
- )
28826
+ items: sortPinnedConversations([...pinnedById.values()])
28685
28827
  });
28686
28828
  }
28687
28829
  return result;
@@ -28699,12 +28841,11 @@ var agentGUIProviderRailOrder = [
28699
28841
  "codex",
28700
28842
  "claude-code",
28701
28843
  "cursor",
28702
- "tutti-agent",
28703
28844
  "opencode",
28845
+ "tutti-agent",
28704
28846
  "nexight",
28705
28847
  "hermes",
28706
- "openclaw",
28707
- "gemini"
28848
+ "openclaw"
28708
28849
  ];
28709
28850
  var agentGUIProviderRailDefaultProviders = [
28710
28851
  "codex",
@@ -29638,6 +29779,7 @@ function useAgentGUIConversationRail({
29638
29779
  const workspaceIdRef = useRef12(workspaceId);
29639
29780
  const runtimeListSessionSections = agentActivityRuntime.listSessionSections;
29640
29781
  const runtimeListSessionSectionPage = agentActivityRuntime.listSessionSectionPage;
29782
+ const runtimeListPinnedSessionsPage = agentActivityRuntime.listPinnedSessionsPage;
29641
29783
  const runtimeSectionsEnabled = !previewMode && Boolean(runtimeListSessionSections) && Boolean(runtimeListSessionSectionPage);
29642
29784
  const sectionAgentTargetId = conversationFilter.kind === "agentTarget" ? conversationFilter.agentTargetId.trim() : sectionAgentTargetFallbackId?.trim() ?? "";
29643
29785
  const userProjectPaths = useMemo9(
@@ -29704,13 +29846,17 @@ function useAgentGUIConversationRail({
29704
29846
  const sections = projectRuntimeSectionsToConversationSections({
29705
29847
  conversationFilter,
29706
29848
  labels: sectionProjectionLabels,
29849
+ pinned: page.pinned,
29707
29850
  sections: page.sections,
29708
29851
  workspaceId: page.workspaceId
29709
29852
  });
29710
29853
  const sectionsWithSummaries = updateConversationSectionsFromSummaries(
29711
29854
  sections,
29712
29855
  conversationsRef.current,
29713
- { sectionConversationsLabel: labels.sectionConversations }
29856
+ {
29857
+ sectionConversationsLabel: labels.sectionConversations,
29858
+ sectionPinnedLabel: labels.sectionPinned
29859
+ }
29714
29860
  );
29715
29861
  setRuntimeRailSections(
29716
29862
  (current) => stabilizeConversationSections(
@@ -29721,6 +29867,13 @@ function useAgentGUIConversationRail({
29721
29867
  setRuntimeRailSectionsPending(false);
29722
29868
  setSectionPageStates(() => {
29723
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
+ }
29724
29877
  for (const section of page.sections) {
29725
29878
  next.set(section.sectionKey, {
29726
29879
  hasMore: section.hasMore,
@@ -29761,27 +29914,32 @@ function useAgentGUIConversationRail({
29761
29914
  );
29762
29915
  setRuntimeRailSections(
29763
29916
  (current) => updateConversationSectionsFromSummaries(current, filteredConversations, {
29764
- sectionConversationsLabel: labels.sectionConversations
29917
+ sectionConversationsLabel: labels.sectionConversations,
29918
+ sectionPinnedLabel: labels.sectionPinned
29765
29919
  })
29766
29920
  );
29767
29921
  }, [
29768
29922
  conversationFilter,
29769
29923
  conversations,
29770
29924
  labels.sectionConversations,
29925
+ labels.sectionPinned,
29771
29926
  runtimeSectionsEnabled
29772
29927
  ]);
29773
29928
  const loadMoreSectionConversations = useCallback10(
29774
29929
  (section) => {
29775
- if (!runtimeListSessionSectionPage || previewMode || conversationQuery.trim()) {
29776
- return;
29777
- }
29778
- if (section.kind === "pinned") {
29930
+ if (previewMode || conversationQuery.trim()) {
29779
29931
  return;
29780
29932
  }
29781
29933
  const currentPageState = sectionPageStates.get(section.id);
29782
29934
  if (currentPageState?.isLoading || currentPageState?.hasMore === false) {
29783
29935
  return;
29784
29936
  }
29937
+ if (section.kind === "pinned" && !runtimeListPinnedSessionsPage) {
29938
+ return;
29939
+ }
29940
+ if (section.kind !== "pinned" && !runtimeListSessionSectionPage) {
29941
+ return;
29942
+ }
29785
29943
  const fallbackCursor = conversationRailPageCursor(section.items);
29786
29944
  const cursor = currentPageState?.nextCursor ?? fallbackCursor;
29787
29945
  const requestSequence = pagingRequestSequenceRef.current;
@@ -29796,7 +29954,82 @@ function useAgentGUIConversationRail({
29796
29954
  });
29797
29955
  return next;
29798
29956
  });
29799
- 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({
29800
30033
  agentTargetId: sectionAgentTargetId || void 0,
29801
30034
  cursor: cursor || void 0,
29802
30035
  limit: AGENT_GUI_CONVERSATION_RAIL_SECTION_PAGE_SIZE,
@@ -29869,6 +30102,7 @@ function useAgentGUIConversationRail({
29869
30102
  conversationFilter,
29870
30103
  conversationQuery,
29871
30104
  previewMode,
30105
+ runtimeListPinnedSessionsPage,
29872
30106
  runtimeListSessionSectionPage,
29873
30107
  sectionAgentTargetId,
29874
30108
  sectionPageStates,
@@ -30139,7 +30373,7 @@ var AgentGUIConversationRailPane = memo2(
30139
30373
  const isSectionCollapsed = isProjectSection && collapsedProjectSectionIds.has(section.id);
30140
30374
  const projectConversationCount = normalizedProjectPath ? projectConversationCountsByPath.get(normalizedProjectPath) ?? 0 : 0;
30141
30375
  const sectionPageState = sectionPageStates.get(section.id);
30142
- const sectionHasMore = !conversationQuery.trim() && section.kind !== "pinned" && sectionPageState?.hasMore === true;
30376
+ const sectionHasMore = !conversationQuery.trim() && sectionPageState?.hasMore === true;
30143
30377
  return /* @__PURE__ */ jsxs21(Fragment8, { children: [
30144
30378
  showProjectRailHeader ? /* @__PURE__ */ jsx34(
30145
30379
  AgentGUIProjectRailHeader,
@@ -31479,16 +31713,6 @@ var AGENT_HOST_MANAGED_TOOLCHAIN_AGENTS = [
31479
31713
  runtimeManaged: true,
31480
31714
  helperProvider: "opencode",
31481
31715
  aliases: ["open code", "open-code", "opencode-ai"]
31482
- },
31483
- {
31484
- id: "gemini",
31485
- // i18n-check-ignore: Provider brand name.
31486
- label: "Gemini CLI",
31487
- toolIds: ["gemini-cli"],
31488
- agentIds: ["gemini"],
31489
- runtimeManaged: true,
31490
- helperProvider: "gemini",
31491
- aliases: ["gemini cli"]
31492
31716
  }
31493
31717
  ];
31494
31718
  var WORKSPACE_DESKTOP_MANAGED_AGENT_DOCK_PROVIDER_ORDER = AGENT_HOST_MANAGED_TOOLCHAIN_AGENTS.map(
@@ -31846,7 +32070,7 @@ function composerOverridesByAgentTargetIdEqual(left, right) {
31846
32070
  return true;
31847
32071
  }
31848
32072
  function areAgentGUINodePropsEqual(previous, next) {
31849
- 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.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;
31850
32074
  }
31851
32075
  var AgentGUINode = memo3(function AgentGUINode2({
31852
32076
  nodeId,
@@ -31879,6 +32103,8 @@ var AgentGUINode = memo3(function AgentGUINode2({
31879
32103
  providerRailAllPresentation = null,
31880
32104
  providerRailMode = "catalog",
31881
32105
  renderProviderRailEmpty,
32106
+ renderProviderUnavailableState,
32107
+ renderProviderReadinessGateState,
31882
32108
  renderSidebarFooter,
31883
32109
  comingSoonProviders,
31884
32110
  providerReadinessGates = null,
@@ -32930,6 +33156,8 @@ var AgentGUINode = memo3(function AgentGUINode2({
32930
33156
  viewModel,
32931
33157
  renderSidebarFooter,
32932
33158
  renderProviderRailEmpty,
33159
+ renderProviderUnavailableState,
33160
+ renderProviderReadinessGateState,
32933
33161
  providerRailAllPresentation,
32934
33162
  actions: viewActions,
32935
33163
  isActive,