@tutti-os/agent-gui 0.0.57 → 0.0.59

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 (58) hide show
  1. package/dist/agent-conversation/index.d.ts +4 -4
  2. package/dist/agent-conversation/index.js +9 -8
  3. package/dist/agent-conversation/index.js.map +1 -1
  4. package/dist/agent-env/index.d.ts +285 -0
  5. package/dist/agent-env/index.js +360 -0
  6. package/dist/agent-env/index.js.map +1 -0
  7. package/dist/agent-message-center/index.d.ts +2 -2
  8. package/dist/agent-message-center/index.js +11 -11
  9. package/dist/{agentConversationVM-Qbz9GBwR.d.ts → agentConversationVM-DPAgUJlR.d.ts} +1 -1
  10. package/dist/{agentGuiNodeTypes-BRU6P22B.d.ts → agentGuiNodeTypes-CupCLd9p.d.ts} +2 -2
  11. package/dist/app/renderer/agentactivity.css +8 -33
  12. package/dist/{chunk-RGVVHF7Q.js → chunk-2WUDORCV.js} +2 -2
  13. package/dist/{chunk-Z3AAQQFD.js → chunk-5SRRKWE4.js} +2 -2
  14. package/dist/{chunk-DZ76JPCV.js → chunk-BEFNWUOZ.js} +95 -154
  15. package/dist/chunk-BEFNWUOZ.js.map +1 -0
  16. package/dist/{chunk-IMZBRUP3.js → chunk-BT5WEZO5.js} +7 -7
  17. package/dist/{chunk-HFZOXSSQ.js → chunk-CEMXB7LA.js} +5 -5
  18. package/dist/{chunk-S6PCOX3S.js → chunk-HVU46DDA.js} +1 -1
  19. package/dist/chunk-HVU46DDA.js.map +1 -0
  20. package/dist/{chunk-33LWYV6O.js → chunk-IS6JUDDY.js} +9 -1
  21. package/dist/chunk-IS6JUDDY.js.map +1 -0
  22. package/dist/{chunk-VOXUYDQF.js → chunk-N756UO52.js} +11 -7
  23. package/dist/chunk-N756UO52.js.map +1 -0
  24. package/dist/{chunk-N37A5CJH.js → chunk-NX6T3DDS.js} +3 -3
  25. package/dist/{chunk-KOR6UVUJ.js → chunk-OFMORNBO.js} +5 -5
  26. package/dist/{chunk-QFHR527D.js → chunk-OLI2A3EM.js} +2 -2
  27. package/dist/chunk-PSLAWU25.js +145 -0
  28. package/dist/chunk-PSLAWU25.js.map +1 -0
  29. package/dist/{chunk-2VHP7KQ5.js → chunk-SLT5Q37C.js} +6 -6
  30. package/dist/{chunk-SZ7JGCS3.js → chunk-UCCUIUGK.js} +4 -4
  31. package/dist/context-mention-palette/index.js +7 -7
  32. package/dist/i18n/index.d.ts +8 -0
  33. package/dist/i18n/index.js +2 -2
  34. package/dist/index.d.ts +56 -4
  35. package/dist/index.js +739 -115
  36. package/dist/index.js.map +1 -1
  37. package/dist/plan-decision-ops.d.ts +2 -2
  38. package/dist/queued-prompt-runtime.d.ts +3 -3
  39. package/dist/workbench/contribution.js +2 -2
  40. package/dist/workbench/index.js +14 -14
  41. package/dist/workbench/sessionTitle.js +3 -3
  42. package/dist/workspace-agent-generated-files.d.ts +1 -1
  43. package/dist/workspace-agent-generated-files.js +3 -3
  44. package/dist/{workspaceAgentActivityListViewModel-B5viw5Da.d.ts → workspaceAgentActivityListViewModel-DJvAqZso.d.ts} +1 -0
  45. package/package.json +19 -12
  46. package/dist/chunk-33LWYV6O.js.map +0 -1
  47. package/dist/chunk-DZ76JPCV.js.map +0 -1
  48. package/dist/chunk-S6PCOX3S.js.map +0 -1
  49. package/dist/chunk-VOXUYDQF.js.map +0 -1
  50. /package/dist/{chunk-RGVVHF7Q.js.map → chunk-2WUDORCV.js.map} +0 -0
  51. /package/dist/{chunk-Z3AAQQFD.js.map → chunk-5SRRKWE4.js.map} +0 -0
  52. /package/dist/{chunk-IMZBRUP3.js.map → chunk-BT5WEZO5.js.map} +0 -0
  53. /package/dist/{chunk-HFZOXSSQ.js.map → chunk-CEMXB7LA.js.map} +0 -0
  54. /package/dist/{chunk-N37A5CJH.js.map → chunk-NX6T3DDS.js.map} +0 -0
  55. /package/dist/{chunk-KOR6UVUJ.js.map → chunk-OFMORNBO.js.map} +0 -0
  56. /package/dist/{chunk-QFHR527D.js.map → chunk-OLI2A3EM.js.map} +0 -0
  57. /package/dist/{chunk-2VHP7KQ5.js.map → chunk-SLT5Q37C.js.map} +0 -0
  58. /package/dist/{chunk-SZ7JGCS3.js.map → chunk-UCCUIUGK.js.map} +0 -0
package/dist/index.js CHANGED
@@ -22,7 +22,7 @@ import {
22
22
  import {
23
23
  AgentInteractivePromptSurface,
24
24
  approvalOptionDisplayLabel
25
- } from "./chunk-KOR6UVUJ.js";
25
+ } from "./chunk-OFMORNBO.js";
26
26
  import {
27
27
  PLAN_IMPLEMENTATION_ACTION_FEEDBACK,
28
28
  PLAN_IMPLEMENTATION_ACTION_IMPLEMENT,
@@ -41,7 +41,7 @@ import {
41
41
  resolveAgentGUIExplicitConversationTitle,
42
42
  resolveAgentGUIProviderDisplayLabel,
43
43
  resolveAgentGUIProviderIdentity
44
- } from "./chunk-SZ7JGCS3.js";
44
+ } from "./chunk-UCCUIUGK.js";
45
45
  import {
46
46
  AgentConversationFlow,
47
47
  Button,
@@ -53,7 +53,6 @@ import {
53
53
  editorToPromptText,
54
54
  getAppErrorCode,
55
55
  labelForProviderSkill,
56
- openAgentEnvPanel,
57
56
  partitionSubAgentTimelineItems,
58
57
  plainTextToAgentRichTextDoc,
59
58
  plainTextToAgentRichTextInlineContent,
@@ -63,14 +62,17 @@ import {
63
62
  skillTriggerForPrefix,
64
63
  toLocalShortDateTime,
65
64
  useProjectedAgentConversation
66
- } from "./chunk-DZ76JPCV.js";
65
+ } from "./chunk-BEFNWUOZ.js";
67
66
  import {
68
67
  AgentMessageMarkdown,
69
68
  AgentTargetPresentationProvider,
70
69
  ZoomableImage,
71
70
  cn,
72
71
  resolveWorkspaceLinkAction
73
- } from "./chunk-2VHP7KQ5.js";
72
+ } from "./chunk-SLT5Q37C.js";
73
+ import {
74
+ openAgentEnvPanel
75
+ } from "./chunk-PSLAWU25.js";
74
76
  import {
75
77
  AGENT_MENTION_FILTER_TAB_ORDER,
76
78
  AgentFileMentionPalette,
@@ -78,7 +80,7 @@ import {
78
80
  DEFAULT_AGENT_MENTION_FILTER,
79
81
  agentMentionItemKey,
80
82
  preloadAgentMentionBrowse
81
- } from "./chunk-IMZBRUP3.js";
83
+ } from "./chunk-BT5WEZO5.js";
82
84
  import {
83
85
  WORKSPACE_AGENT_ACTIVITY_RUNTIME_SESSION_ORIGIN,
84
86
  buildWorkspaceAgentActivityListViewModel,
@@ -88,10 +90,10 @@ import {
88
90
  isWorkspaceAgentUntitledTask,
89
91
  mergeWorkspaceAgentActivityDurableAndOverlayMessages,
90
92
  selectWorkspaceAgentActivityOverlayMessages
91
- } from "./chunk-HFZOXSSQ.js";
93
+ } from "./chunk-CEMXB7LA.js";
92
94
  import {
93
95
  Spinner
94
- } from "./chunk-QFHR527D.js";
96
+ } from "./chunk-OLI2A3EM.js";
95
97
  import {
96
98
  resolveWorkspaceAgentSessionSortTimeUnixMs
97
99
  } from "./chunk-IBIMGLCD.js";
@@ -102,7 +104,7 @@ import {
102
104
  mentionItemToAttrs,
103
105
  normalizeAgentSessionMentionTitle,
104
106
  parseMentionItemFromHref
105
- } from "./chunk-N37A5CJH.js";
107
+ } from "./chunk-NX6T3DDS.js";
106
108
  import "./chunk-Y35GDLP2.js";
107
109
  import "./chunk-LUGELG5V.js";
108
110
  import {
@@ -124,10 +126,18 @@ import {
124
126
  useAgentHostApi,
125
127
  useOptionalAgentActivityRuntime,
126
128
  useOptionalAgentHostApi
127
- } from "./chunk-S6PCOX3S.js";
129
+ } from "./chunk-HVU46DDA.js";
128
130
  import "./chunk-TYGL25EL.js";
131
+ import {
132
+ AgentGuiI18nProvider,
133
+ agentGuiI18nModule,
134
+ agentGuiI18nResources,
135
+ translate,
136
+ useTranslation
137
+ } from "./chunk-5SRRKWE4.js";
129
138
  import "./chunk-PJP5BUU6.js";
130
139
  import "./chunk-MTFSQWZ6.js";
140
+ import "./chunk-IS6JUDDY.js";
131
141
  import {
132
142
  AGENT_CONTEXT_MENTION_PROVIDER_IDS
133
143
  } from "./chunk-JM24HADP.js";
@@ -135,14 +145,6 @@ import "./chunk-GCBDIQDX.js";
135
145
  import {
136
146
  createAgentQueuedPromptRuntime
137
147
  } from "./chunk-TG3ZXLPM.js";
138
- import {
139
- AgentGuiI18nProvider,
140
- agentGuiI18nModule,
141
- agentGuiI18nResources,
142
- translate,
143
- useTranslation
144
- } from "./chunk-Z3AAQQFD.js";
145
- import "./chunk-33LWYV6O.js";
146
148
 
147
149
  // shared/agentActivitySnapshotProjection.ts
148
150
  import {
@@ -4901,6 +4903,13 @@ function conversationFilterKey(filter, provider) {
4901
4903
  }
4902
4904
  return `agent-target:${normalized.agentTargetId}`;
4903
4905
  }
4906
+ function conversationRetainableForQueryFilter(conversation, filter) {
4907
+ if (!conversation || !filter || filter.kind !== "agentTarget") {
4908
+ return true;
4909
+ }
4910
+ const agentTargetId = conversation.agentTargetId?.trim() ?? "";
4911
+ return agentTargetId.length === 0 || agentTargetId === filter.agentTargetId;
4912
+ }
4904
4913
  function createAgentGUIConversationListQueryKey(input) {
4905
4914
  const normalized = normalizeQuery(input);
4906
4915
  if (!normalized) {
@@ -5701,24 +5710,53 @@ async function refreshAgentGUIConversationListQuery(query, reason, options = {})
5701
5710
  ...dirtySessionIds,
5702
5711
  ...baseConversations.map((conversation) => conversation.id)
5703
5712
  ]) : null;
5704
- const retainedSessionIds = new Set(retainedSnapshotSessionIds);
5713
+ const currentConversationsById = new Map(
5714
+ currentConversations.map((conversation) => [
5715
+ conversation.id,
5716
+ conversation
5717
+ ])
5718
+ );
5719
+ const snapshotSessionAgentTargetIdById = new Map(
5720
+ workspaceAgentSnapshot.sessions.flatMap((session) => {
5721
+ const agentSessionId = session.agentSessionId.trim();
5722
+ const agentTargetId = session.agentTargetId?.trim() ?? "";
5723
+ return agentSessionId && agentTargetId ? [[agentSessionId, agentTargetId]] : [];
5724
+ })
5725
+ );
5726
+ const retainableForQueryFilter = (agentSessionId) => {
5727
+ const filter = state.query.conversationFilter;
5728
+ if (!filter || filter.kind !== "agentTarget") {
5729
+ return true;
5730
+ }
5731
+ const snapshotAgentTargetId = snapshotSessionAgentTargetIdById.get(agentSessionId);
5732
+ if (snapshotAgentTargetId) {
5733
+ return snapshotAgentTargetId === filter.agentTargetId;
5734
+ }
5735
+ return conversationRetainableForQueryFilter(
5736
+ currentConversationsById.get(agentSessionId),
5737
+ filter
5738
+ );
5739
+ };
5740
+ const retainedSessionIds = new Set(
5741
+ [...retainedSnapshotSessionIds].filter(retainableForQueryFilter)
5742
+ );
5705
5743
  if (reason === "workspace-agent-update") {
5706
5744
  for (const conversation of currentConversations) {
5707
- if (!nextDeletedConversationIds.has(conversation.id)) {
5745
+ if (!nextDeletedConversationIds.has(conversation.id) && retainableForQueryFilter(conversation.id)) {
5708
5746
  retainedSessionIds.add(conversation.id);
5709
5747
  }
5710
5748
  }
5711
5749
  }
5712
5750
  if (retainedSnapshotSessionIds.size > 0) {
5713
5751
  for (const agentSessionId of localCreatedConversationIds) {
5714
- if (!nextDeletedConversationIds.has(agentSessionId)) {
5752
+ if (!nextDeletedConversationIds.has(agentSessionId) && retainableForQueryFilter(agentSessionId)) {
5715
5753
  retainedSessionIds.add(agentSessionId);
5716
5754
  }
5717
5755
  }
5718
5756
  }
5719
5757
  if (canApplyDirtySessionProjection) {
5720
5758
  for (const conversation of currentConversations) {
5721
- if (!nextDeletedConversationIds.has(conversation.id)) {
5759
+ if (!nextDeletedConversationIds.has(conversation.id) && retainableForQueryFilter(conversation.id)) {
5722
5760
  retainedSessionIds.add(conversation.id);
5723
5761
  }
5724
5762
  }
@@ -6787,6 +6825,30 @@ function reportAgentGUIRuntimeError(input) {
6787
6825
  } catch {
6788
6826
  }
6789
6827
  }
6828
+ function reportAgentGUIConversationFilterTargetUnresolved(input) {
6829
+ const reportDiagnostic = input.runtime.reportDiagnostic;
6830
+ if (!reportDiagnostic) {
6831
+ return;
6832
+ }
6833
+ try {
6834
+ void Promise.resolve(
6835
+ reportDiagnostic.call(input.runtime, {
6836
+ details: {
6837
+ provider: input.provider,
6838
+ providerTargetCount: input.providerTargetCount,
6839
+ providerTargetId: input.providerTargetId,
6840
+ reason: input.reason
6841
+ },
6842
+ event: "agent.gui.conversation_filter.target_unresolved",
6843
+ level: "warn",
6844
+ source: "agent-gui",
6845
+ workspaceId: input.workspaceId
6846
+ })
6847
+ ).catch(() => {
6848
+ });
6849
+ } catch {
6850
+ }
6851
+ }
6790
6852
  function reportAgentGUIMessagePageDiagnostic(input) {
6791
6853
  const reportDiagnostic = input.runtime.reportDiagnostic;
6792
6854
  if (!reportDiagnostic) {
@@ -8806,6 +8868,8 @@ function useAgentGUINodeController({
8806
8868
  const [conversationFilter, setConversationFilter] = useState4(
8807
8869
  () => createAgentGUIConversationFilterState().filter
8808
8870
  );
8871
+ const conversationFilterRef = useRef4(conversationFilter);
8872
+ conversationFilterRef.current = conversationFilter;
8809
8873
  const canUseConversationTargetFilter = conversationScope === "multi-provider";
8810
8874
  const queryConversationFilter = canUseConversationTargetFilter ? conversationFilter : null;
8811
8875
  useEffect4(() => {
@@ -11667,14 +11731,25 @@ function useAgentGUINodeController({
11667
11731
  activatedConversationIdsRef.current.add(conversation2.id);
11668
11732
  setTransientConversation(conversation2);
11669
11733
  if (conversationListQuery) {
11734
+ const createdAgentTargetId = normalizeOptionalText2(conversation2.agentTargetId) ?? targetData.agentTargetId;
11735
+ const currentQueryFilter = conversationListQuery.conversationFilter;
11736
+ const filterExcludesCreatedConversation = currentQueryFilter?.kind === "agentTarget" && currentQueryFilter.agentTargetId !== (createdAgentTargetId ?? "");
11737
+ const createdConversationFilter = createdAgentTargetId ? { kind: "agentTarget", agentTargetId: createdAgentTargetId } : { kind: "all" };
11738
+ const createdConversationQuery = filterExcludesCreatedConversation ? {
11739
+ ...conversationListQuery,
11740
+ conversationFilter: createdConversationFilter
11741
+ } : conversationListQuery;
11670
11742
  upsertLocalCreatedAgentGUIConversation({
11671
- query: conversationListQuery,
11743
+ query: createdConversationQuery,
11672
11744
  conversation: conversation2
11673
11745
  });
11674
11746
  scheduleAgentGUIConversationListProjection(
11675
- conversationListQuery,
11747
+ createdConversationQuery,
11676
11748
  "local-create"
11677
11749
  );
11750
+ if (filterExcludesCreatedConversation) {
11751
+ setConversationFilter(createdConversationFilter);
11752
+ }
11678
11753
  }
11679
11754
  setAgentSessionViewMessagesLoading(
11680
11755
  sessionViewRef(conversation2.id),
@@ -11848,12 +11923,28 @@ function useAgentGUINodeController({
11848
11923
  setIsLoadingMessages(false);
11849
11924
  setDetailError(null);
11850
11925
  persistActiveConversation(null);
11926
+ const filter = conversationFilterRef.current;
11927
+ if (canUseConversationTargetFilter && filter.kind === "agentTarget") {
11928
+ const filterTarget = resolveAgentGUIProviderTarget({
11929
+ agentTargetId: filter.agentTargetId,
11930
+ defaultProviderTargetId,
11931
+ fallbackToLocal: false,
11932
+ provider: dataRef.current.provider,
11933
+ providerTargets: normalizedProviderTargets
11934
+ });
11935
+ if (filterTarget && filterTarget.disabled !== true && (filterTarget.agentTargetId?.trim() ?? "") === filter.agentTargetId) {
11936
+ setHomeComposerTargetOverride(filterTarget);
11937
+ }
11938
+ }
11851
11939
  loadDraftComposerOptions();
11852
11940
  },
11853
11941
  [
11854
11942
  activation,
11855
11943
  agentActivityRuntime,
11944
+ canUseConversationTargetFilter,
11945
+ defaultProviderTargetId,
11856
11946
  loadDraftComposerOptions,
11947
+ normalizedProviderTargets,
11857
11948
  persistActiveConversation,
11858
11949
  workspaceId
11859
11950
  ]
@@ -13675,6 +13766,66 @@ function useAgentGUINodeController({
13675
13766
  userProjects,
13676
13767
  workspacePath
13677
13768
  ]);
13769
+ useEffect4(() => {
13770
+ if (previewMode || providerTargetsLoading || !activeConversationId) {
13771
+ return;
13772
+ }
13773
+ const summary = resolveConversationSummaryById(
13774
+ conversations,
13775
+ activeConversationId,
13776
+ transientConversationRef.current
13777
+ );
13778
+ if (!summary || summary.provider === "unknown") {
13779
+ return;
13780
+ }
13781
+ const summaryAgentTargetId = normalizeOptionalText2(summary.agentTargetId);
13782
+ const providerMismatch = dataRef.current.provider !== summary.provider;
13783
+ const agentTargetMismatch = summaryAgentTargetId !== null && normalizeOptionalText2(dataRef.current.agentTargetId) !== summaryAgentTargetId;
13784
+ if (!providerMismatch && !agentTargetMismatch) {
13785
+ return;
13786
+ }
13787
+ const sessionTarget = resolveAgentGUIProviderTarget({
13788
+ agentTargetId: summaryAgentTargetId,
13789
+ defaultProviderTargetId,
13790
+ fallbackToLocal: shouldFallbackToLocalProviderTargets,
13791
+ provider: summary.provider,
13792
+ providerTargets: normalizedProviderTargets
13793
+ });
13794
+ if (!sessionTarget || sessionTarget.provider !== summary.provider) {
13795
+ return;
13796
+ }
13797
+ if (!providerMismatch && summaryAgentTargetId !== null && (sessionTarget.agentTargetId?.trim() ?? "") !== summaryAgentTargetId) {
13798
+ return;
13799
+ }
13800
+ setHomeComposerTargetOverride(null);
13801
+ const sessionTargetIsExplicit = normalizedExplicitProviderTargets.some(
13802
+ (target) => target.provider === sessionTarget.provider && target.targetId === sessionTarget.targetId && agentGUIProviderTargetRefsEqual(target.ref, sessionTarget.ref)
13803
+ );
13804
+ onDataChangeRef.current((current) => {
13805
+ const targetData = composerTargetDataFromProviderTarget({
13806
+ current,
13807
+ isExplicit: sessionTargetIsExplicit,
13808
+ target: sessionTarget
13809
+ });
13810
+ if (current.provider === targetData.provider && normalizeOptionalText2(current.agentTargetId) === targetData.agentTargetId && (current.providerTargetId ?? null) === targetData.providerTargetId && agentGUIProviderTargetRefsEqual(
13811
+ current.providerTargetRef,
13812
+ targetData.providerTargetRef
13813
+ )) {
13814
+ return current;
13815
+ }
13816
+ dataRef.current = targetData.data;
13817
+ return targetData.data;
13818
+ });
13819
+ }, [
13820
+ activeConversationId,
13821
+ conversations,
13822
+ defaultProviderTargetId,
13823
+ normalizedExplicitProviderTargets,
13824
+ normalizedProviderTargets,
13825
+ previewMode,
13826
+ providerTargetsLoading,
13827
+ shouldFallbackToLocalProviderTargets
13828
+ ]);
13678
13829
  const visibleConversationsRef = useRef4(
13679
13830
  null
13680
13831
  );
@@ -14357,17 +14508,30 @@ function useAgentGUINodeController({
14357
14508
  providerTargets: normalizedProviderTargets
14358
14509
  });
14359
14510
  if (!nextTarget || nextTarget.disabled === true) {
14511
+ reportAgentGUIConversationFilterTargetUnresolved({
14512
+ provider: input.provider,
14513
+ providerTargetId: input.providerTargetId ?? null,
14514
+ providerTargetCount: normalizedProviderTargets.length,
14515
+ reason: nextTarget ? "disabled" : "unresolved",
14516
+ runtime: agentActivityRuntime,
14517
+ workspaceId
14518
+ });
14360
14519
  return;
14361
14520
  }
14521
+ if (activeConversationIdRef.current === null) {
14522
+ setHomeComposerTargetOverride(nextTarget);
14523
+ }
14362
14524
  const agentTargetId = nextTarget.agentTargetId?.trim() ?? "";
14363
14525
  const nextFilter = agentTargetId ? { kind: "agentTarget", agentTargetId } : { kind: "all" };
14364
14526
  setConversationFilter(nextFilter);
14365
14527
  },
14366
14528
  [
14529
+ agentActivityRuntime,
14367
14530
  canUseConversationTargetFilter,
14368
14531
  defaultProviderTargetId,
14369
14532
  normalizedProviderTargets,
14370
- shouldFallbackToLocalProviderTargets
14533
+ shouldFallbackToLocalProviderTargets,
14534
+ workspaceId
14371
14535
  ]
14372
14536
  );
14373
14537
  const stableCreateConversation = useStableControllerEventCallback(createConversation);
@@ -15865,7 +16029,7 @@ import {
15865
16029
  useRef as useRef11,
15866
16030
  useState as useState10
15867
16031
  } from "react";
15868
- import { createPortal as createPortal3 } from "react-dom";
16032
+ import { createPortal as createPortal3, flushSync } from "react-dom";
15869
16033
  import {
15870
16034
  AddIcon,
15871
16035
  Button as Button3,
@@ -20006,6 +20170,7 @@ function AgentUsageChip({
20006
20170
  "use memo";
20007
20171
  const [usagePopoverOpen, setUsagePopoverOpen] = useState10(false);
20008
20172
  const usagePopoverHoverTimerRef = useRef11(null);
20173
+ const usagePopoverContentRef = useRef11(null);
20009
20174
  const clampedPercent = Math.max(0, Math.min(100, percentUsed));
20010
20175
  const chipLabel = labels.usageChipLabel({ percent: clampedPercent });
20011
20176
  const showTokens = usedTokens !== null && totalTokens !== null;
@@ -20060,6 +20225,22 @@ function AgentUsageChip({
20060
20225
  },
20061
20226
  [closeUsagePopover, openUsagePopover]
20062
20227
  );
20228
+ const handleUsageTriggerBlur = useCallback9(
20229
+ (event) => {
20230
+ const nextFocusTarget = event.relatedTarget;
20231
+ if (nextFocusTarget instanceof Node && usagePopoverContentRef.current?.contains(nextFocusTarget)) {
20232
+ clearUsagePopoverHoverTimer();
20233
+ clearUsagePopoverCloseTimer();
20234
+ return;
20235
+ }
20236
+ closeUsagePopover();
20237
+ },
20238
+ [
20239
+ clearUsagePopoverCloseTimer,
20240
+ clearUsagePopoverHoverTimer,
20241
+ closeUsagePopover
20242
+ ]
20243
+ );
20063
20244
  useEffect11(
20064
20245
  () => () => {
20065
20246
  clearUsagePopoverHoverTimer();
@@ -20078,8 +20259,7 @@ function AgentUsageChip({
20078
20259
  ),
20079
20260
  "data-testid": "agent-gui-usage-chip",
20080
20261
  "data-usage-level": usageLevel,
20081
- onBlur: tooltipsEnabled ? closeUsagePopover : void 0,
20082
- onClick: tooltipsEnabled ? openUsagePopover : void 0,
20262
+ onBlur: tooltipsEnabled ? handleUsageTriggerBlur : void 0,
20083
20263
  onFocus: tooltipsEnabled ? openUsagePopoverAfterHoverDelay : void 0,
20084
20264
  onPointerEnter: (event) => {
20085
20265
  if (tooltipsEnabled && event.pointerType !== "touch") {
@@ -20109,10 +20289,11 @@ function AgentUsageChip({
20109
20289
  open: usagePopoverOpen,
20110
20290
  onOpenChange: handleUsagePopoverOpenChange,
20111
20291
  children: [
20112
- /* @__PURE__ */ jsx28(PopoverTrigger, { asChild: true, children: trigger }),
20292
+ /* @__PURE__ */ jsx28(PopoverAnchor, { asChild: true, children: trigger }),
20113
20293
  usagePopoverOpen ? /* @__PURE__ */ jsx28(
20114
20294
  PopoverContent,
20115
20295
  {
20296
+ ref: usagePopoverContentRef,
20116
20297
  side: "bottom",
20117
20298
  align: "end",
20118
20299
  className: "w-[320px] max-w-[calc(100vw-32px)] gap-3 text-xs",
@@ -20254,6 +20435,7 @@ function AgentComposer({
20254
20435
  uiLanguage = "en",
20255
20436
  isActive = true,
20256
20437
  previewMode = false,
20438
+ workspaceReferencePickerOpen = false,
20257
20439
  promptImagesSupported = true,
20258
20440
  composerFocusRequestSequence = null,
20259
20441
  layoutMode = "dock",
@@ -21061,7 +21243,7 @@ function AgentComposer({
21061
21243
  (event) => handleFileMentionKeyDown(event) || handleSlashPaletteKeyDown(event) || handleSlashCommandMenuKeyDown(event) || handlePlanModeToggleKeyDown(event)
21062
21244
  );
21063
21245
  useEffect11(() => {
21064
- if (!showPalette) {
21246
+ if (!showPalette || workspaceReferencePickerOpen) {
21065
21247
  return;
21066
21248
  }
21067
21249
  const handleDocumentKeyDown = (event) => {
@@ -21089,7 +21271,7 @@ function AgentComposer({
21089
21271
  capture: true
21090
21272
  });
21091
21273
  };
21092
- }, [handlePaletteKeyDown, showPalette]);
21274
+ }, [handlePaletteKeyDown, showPalette, workspaceReferencePickerOpen]);
21093
21275
  const handleFileMentionSuggestionChange = useCallback9(
21094
21276
  (state) => {
21095
21277
  setFileMentionSuggestion(state);
@@ -21407,18 +21589,18 @@ function AgentComposer({
21407
21589
  );
21408
21590
  const handleOpenReferencesForEntity = useCallback9(
21409
21591
  (entity) => {
21410
- clearActiveFileMentionTrigger();
21411
- closeFileMentionPalette();
21412
21592
  if (!onRequestWorkspaceReferences) {
21413
21593
  return;
21414
21594
  }
21415
- void onRequestWorkspaceReferences(entity).then(
21416
- (result) => applyReferencePickResult(result)
21417
- );
21595
+ void onRequestWorkspaceReferences(entity).then((result) => {
21596
+ if (result.files.length > 0 || result.mentionItems.length > 0) {
21597
+ flushSync(clearActiveFileMentionTrigger);
21598
+ }
21599
+ return applyReferencePickResult(result);
21600
+ });
21418
21601
  },
21419
21602
  [
21420
21603
  clearActiveFileMentionTrigger,
21421
- closeFileMentionPalette,
21422
21604
  applyReferencePickResult,
21423
21605
  onRequestWorkspaceReferences
21424
21606
  ]
@@ -22332,65 +22514,69 @@ function AgentComposer({
22332
22514
  /* @__PURE__ */ jsxs15("div", { className: AgentGUINode_styles_default.composerFooter, children: [
22333
22515
  /* @__PURE__ */ jsxs15("div", { className: composerStyles.footerGroup, children: [
22334
22516
  /* @__PURE__ */ jsxs15("div", { className: "inline-flex shrink-0 items-center gap-1", children: [
22335
- previewMode ? /* @__PURE__ */ jsx28(
22336
- "button",
22337
- {
22338
- type: "button",
22339
- "aria-label": labels.referenceWorkspaceFiles,
22340
- title: labels.referenceWorkspaceFiles,
22341
- className: cn(
22342
- AgentGUINode_styles_default.composerMenuTrigger,
22343
- AgentGUINode_styles_default.composerReferenceTrigger,
22344
- "w-auto justify-center text-[var(--agent-gui-text-secondary)] [&_svg]:shrink-0"
22345
- ),
22346
- children: /* @__PURE__ */ jsx28(
22347
- AddIcon,
22348
- {
22349
- "aria-hidden": true,
22350
- className: "size-3.5",
22351
- "data-agent-reference-add-icon": "true"
22352
- }
22353
- )
22354
- }
22355
- ) : /* @__PURE__ */ jsx28(
22356
- Select2,
22357
- {
22358
- open: false,
22359
- value: workspaceReferenceSelectValue,
22360
- disabled: !onRequestWorkspaceReferences || composerControlsHardDisabled,
22361
- onOpenChange: (isOpen) => {
22362
- if (isOpen) {
22363
- void handleWorkspaceReferencePicker();
22364
- }
22365
- },
22366
- onValueChange: (nextValue) => {
22367
- if (nextValue === workspaceReferenceOptionValue) {
22368
- void handleWorkspaceReferencePicker();
22369
- }
22370
- },
22371
- children: /* @__PURE__ */ jsx28(
22372
- SelectTrigger2,
22373
- {
22374
- size: "sm",
22375
- "aria-label": labels.referenceWorkspaceFiles,
22376
- title: labels.referenceWorkspaceFiles,
22377
- className: cn(
22378
- AgentGUINode_styles_default.composerMenuTrigger,
22379
- AgentGUINode_styles_default.composerReferenceTrigger,
22380
- "w-auto justify-center text-[var(--agent-gui-text-secondary)] [&>svg:last-child]:hidden [&_svg]:shrink-0"
22381
- ),
22382
- children: /* @__PURE__ */ jsx28(
22383
- AddIcon,
22384
- {
22385
- "aria-hidden": true,
22386
- className: "size-3.5",
22387
- "data-agent-reference-add-icon": "true"
22388
- }
22389
- )
22390
- }
22391
- )
22392
- }
22393
- ),
22517
+ previewMode ? /* @__PURE__ */ jsx28(TooltipProvider, { delayDuration: 120, children: /* @__PURE__ */ jsxs15(Tooltip, { children: [
22518
+ /* @__PURE__ */ jsx28(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx28(
22519
+ "button",
22520
+ {
22521
+ type: "button",
22522
+ "aria-label": labels.referenceWorkspaceFiles,
22523
+ className: cn(
22524
+ AgentGUINode_styles_default.composerMenuTrigger,
22525
+ AgentGUINode_styles_default.composerReferenceTrigger,
22526
+ "w-auto justify-center text-[var(--agent-gui-text-secondary)] [&_svg]:shrink-0"
22527
+ ),
22528
+ children: /* @__PURE__ */ jsx28(
22529
+ AddIcon,
22530
+ {
22531
+ "aria-hidden": true,
22532
+ className: "size-3.5",
22533
+ "data-agent-reference-add-icon": "true"
22534
+ }
22535
+ )
22536
+ }
22537
+ ) }),
22538
+ /* @__PURE__ */ jsx28(TooltipContent, { side: "top", children: labels.addContent })
22539
+ ] }) }) : /* @__PURE__ */ jsx28(TooltipProvider, { delayDuration: 120, children: /* @__PURE__ */ jsxs15(Tooltip, { children: [
22540
+ /* @__PURE__ */ jsx28(
22541
+ Select2,
22542
+ {
22543
+ open: false,
22544
+ value: workspaceReferenceSelectValue,
22545
+ disabled: !onRequestWorkspaceReferences || composerControlsHardDisabled,
22546
+ onOpenChange: (isOpen) => {
22547
+ if (isOpen) {
22548
+ void handleWorkspaceReferencePicker();
22549
+ }
22550
+ },
22551
+ onValueChange: (nextValue) => {
22552
+ if (nextValue === workspaceReferenceOptionValue) {
22553
+ void handleWorkspaceReferencePicker();
22554
+ }
22555
+ },
22556
+ children: /* @__PURE__ */ jsx28(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx28(
22557
+ SelectTrigger2,
22558
+ {
22559
+ size: "sm",
22560
+ "aria-label": labels.referenceWorkspaceFiles,
22561
+ className: cn(
22562
+ AgentGUINode_styles_default.composerMenuTrigger,
22563
+ AgentGUINode_styles_default.composerReferenceTrigger,
22564
+ "w-auto justify-center text-[var(--agent-gui-text-secondary)] [&>svg:last-child]:hidden [&_svg]:shrink-0"
22565
+ ),
22566
+ children: /* @__PURE__ */ jsx28(
22567
+ AddIcon,
22568
+ {
22569
+ "aria-hidden": true,
22570
+ className: "size-3.5",
22571
+ "data-agent-reference-add-icon": "true"
22572
+ }
22573
+ )
22574
+ }
22575
+ ) })
22576
+ }
22577
+ ),
22578
+ /* @__PURE__ */ jsx28(TooltipContent, { side: "top", children: labels.addContent })
22579
+ ] }) }),
22394
22580
  /* @__PURE__ */ jsx28(
22395
22581
  "button",
22396
22582
  {
@@ -23203,6 +23389,7 @@ var AGENT_GUI_STICK_TO_BOTTOM_THRESHOLD_PX = 24;
23203
23389
  var AGENT_GUI_TOP_HISTORY_PREFETCH_THRESHOLD_PX = 240;
23204
23390
  var AGENT_GUI_TOP_MASK_SCROLL_EPSILON_PX = 1;
23205
23391
  var AGENT_GUI_CONVERSATION_RAIL_SECTION_PAGE_SIZE = 5;
23392
+ var AGENT_GUI_CONVERSATION_RAIL_PROJECTION_PROVIDER = "codex";
23206
23393
  var AGENT_GUI_TIMELINE_SCROLL_AREA_CONTENT_STYLE = {
23207
23394
  width: "100%",
23208
23395
  minWidth: "100%",
@@ -23888,7 +24075,8 @@ function AgentGUINodeView({
23888
24075
  conversations: viewModel.conversations,
23889
24076
  store: conversationRailStore,
23890
24077
  storeState: conversationRailStoreState,
23891
- userProjects: viewModel.userProjects
24078
+ userProjects: viewModel.userProjects,
24079
+ workspaceId: viewModel.workspaceId
23892
24080
  }
23893
24081
  )
23894
24082
  }
@@ -23926,6 +24114,7 @@ function AgentGUINodeView({
23926
24114
  uiLanguage,
23927
24115
  hideDetailHeader: conversationRailCollapsed,
23928
24116
  isActive,
24117
+ workspaceReferencePickerOpen,
23929
24118
  composerFocusRequestSequence: detailComposerFocusRequestSequence,
23930
24119
  isAgentProviderReady,
23931
24120
  slashStatusLimits,
@@ -24045,6 +24234,7 @@ var AgentGUIDetailPane = memo(function AgentGUIDetailPane2({
24045
24234
  hideDetailHeader,
24046
24235
  isActive,
24047
24236
  previewMode,
24237
+ workspaceReferencePickerOpen,
24048
24238
  composerFocusRequestSequence,
24049
24239
  isAgentProviderReady,
24050
24240
  slashStatusLimits,
@@ -24391,6 +24581,7 @@ var AgentGUIDetailPane = memo(function AgentGUIDetailPane2({
24391
24581
  mentionPalette: labels.mentionPalette,
24392
24582
  removeMention: labels.removeMention,
24393
24583
  addReference: labels.addReference,
24584
+ addContent: labels.addContent,
24394
24585
  referenceWorkspaceFiles: labels.referenceWorkspaceFiles,
24395
24586
  providerSwitchLabel: labels.providerSwitchLabel,
24396
24587
  projectLocked: labels.projectLocked,
@@ -24403,6 +24594,7 @@ var AgentGUIDetailPane = memo(function AgentGUIDetailPane2({
24403
24594
  interactivePromptLabels,
24404
24595
  labels.defaultModel,
24405
24596
  labels.addReference,
24597
+ labels.addContent,
24406
24598
  labels.deleteQueuedPrompt,
24407
24599
  labels.editQueuedPrompt,
24408
24600
  labels.fileMentionEmpty,
@@ -24618,6 +24810,7 @@ var AgentGUIDetailPane = memo(function AgentGUIDetailPane2({
24618
24810
  placeholder: viewModel.hasSentUserMessage ? labels.followupPlaceholder : labels.initialPlaceholder,
24619
24811
  showStopButton,
24620
24812
  previewMode,
24813
+ workspaceReferencePickerOpen,
24621
24814
  // Plan decisions replace the composer via bottomDockReplacementPrompt;
24622
24815
  // approval / ask-user embed here (composerActivePrompt encodes that).
24623
24816
  activePrompt: composerActivePrompt,
@@ -24671,6 +24864,7 @@ var AgentGUIDetailPane = memo(function AgentGUIDetailPane2({
24671
24864
  labels.initialPlaceholder,
24672
24865
  labels.promptTips,
24673
24866
  previewMode,
24867
+ workspaceReferencePickerOpen,
24674
24868
  composerActivePrompt,
24675
24869
  editQueuedPrompt,
24676
24870
  onCapabilitySettingsRequest,
@@ -25456,7 +25650,8 @@ var AgentGUIConversationRailStorePane = memo(
25456
25650
  conversations,
25457
25651
  store,
25458
25652
  storeState: _storeState,
25459
- userProjects
25653
+ userProjects,
25654
+ workspaceId
25460
25655
  }) {
25461
25656
  "use memo";
25462
25657
  const state = useSnapshot(store);
@@ -25465,7 +25660,8 @@ var AgentGUIConversationRailStorePane = memo(
25465
25660
  {
25466
25661
  ...state,
25467
25662
  conversations,
25468
- userProjects
25663
+ userProjects,
25664
+ workspaceId
25469
25665
  }
25470
25666
  );
25471
25667
  }
@@ -25477,6 +25673,40 @@ function normalizeConversationRailProjectPath(path) {
25477
25673
  }
25478
25674
  return normalized.replace(/\/+$/, "") || "/";
25479
25675
  }
25676
+ function conversationRailPageCursor(conversations) {
25677
+ let boundary = null;
25678
+ for (const conversation of conversations) {
25679
+ if (!conversation.id.trim()) {
25680
+ continue;
25681
+ }
25682
+ if (!boundary) {
25683
+ boundary = conversation;
25684
+ continue;
25685
+ }
25686
+ if (conversation.updatedAtUnixMs < boundary.updatedAtUnixMs || conversation.updatedAtUnixMs === boundary.updatedAtUnixMs && conversation.id.trim() > boundary.id.trim()) {
25687
+ boundary = conversation;
25688
+ }
25689
+ }
25690
+ if (!boundary) {
25691
+ return null;
25692
+ }
25693
+ return `${boundary.updatedAtUnixMs}|${boundary.id.trim()}`;
25694
+ }
25695
+ function mergeConversationRailPageItems(base, loaded) {
25696
+ if (loaded.length === 0) {
25697
+ return base;
25698
+ }
25699
+ const ids = new Set(base.map((conversation) => conversation.id));
25700
+ const merged = [...base];
25701
+ for (const conversation of loaded) {
25702
+ if (ids.has(conversation.id)) {
25703
+ continue;
25704
+ }
25705
+ ids.add(conversation.id);
25706
+ merged.push(conversation);
25707
+ }
25708
+ return merged;
25709
+ }
25480
25710
  function stabilizeConversationSections(previous, next) {
25481
25711
  if (!previous) {
25482
25712
  return [...next];
@@ -25537,6 +25767,97 @@ function stabilizeConversationSectionItems(previous, next) {
25537
25767
  });
25538
25768
  return changed ? stable : previous;
25539
25769
  }
25770
+ function updateConversationSectionsFromSummaries(previous, conversations) {
25771
+ if (!previous || conversations.length === 0) {
25772
+ return previous;
25773
+ }
25774
+ const summariesById = new Map(
25775
+ conversations.map((conversation) => [conversation.id, conversation])
25776
+ );
25777
+ let changed = false;
25778
+ const nextSections = previous.map((section) => {
25779
+ let sectionChanged = false;
25780
+ const items = section.items.map((item) => {
25781
+ const summary = summariesById.get(item.id);
25782
+ if (!summary) {
25783
+ return item;
25784
+ }
25785
+ const nextItem = {
25786
+ ...summary,
25787
+ project: item.project
25788
+ };
25789
+ if (conversationSummariesRenderEqual2(item, nextItem)) {
25790
+ return item;
25791
+ }
25792
+ sectionChanged = true;
25793
+ return nextItem;
25794
+ });
25795
+ if (!sectionChanged) {
25796
+ return section;
25797
+ }
25798
+ changed = true;
25799
+ return {
25800
+ ...section,
25801
+ items
25802
+ };
25803
+ });
25804
+ return changed ? nextSections : previous;
25805
+ }
25806
+ function projectRuntimeSectionsToConversationSections(input) {
25807
+ const pinned = [];
25808
+ const result = [];
25809
+ for (const section of input.sections) {
25810
+ const project = section.userProject ? {
25811
+ createdAtUnixMs: section.userProject.createdAtUnixMs,
25812
+ id: section.userProject.id,
25813
+ label: section.userProject.label,
25814
+ lastUsedAtUnixMs: section.userProject.lastUsedAtUnixMs,
25815
+ path: section.userProject.path,
25816
+ updatedAtUnixMs: section.userProject.updatedAtUnixMs
25817
+ } : null;
25818
+ const conversations = buildAgentGUIConversationSummaries({
25819
+ conversationFilter: input.conversationFilter,
25820
+ provider: AGENT_GUI_CONVERSATION_RAIL_PROJECTION_PROVIDER,
25821
+ snapshot: {
25822
+ composerOptionsByProvider: {},
25823
+ presences: [],
25824
+ sessionMessagesById: {},
25825
+ sessions: section.sessions,
25826
+ workspaceId: input.workspaceId
25827
+ },
25828
+ userProjects: []
25829
+ }).map((conversation) => ({
25830
+ ...conversation,
25831
+ project: section.kind === "project" ? project : null
25832
+ }));
25833
+ const items = conversations.filter((conversation) => {
25834
+ if ((conversation.pinnedAtUnixMs ?? 0) > 0) {
25835
+ pinned.push(conversation);
25836
+ return false;
25837
+ }
25838
+ return true;
25839
+ });
25840
+ result.push({
25841
+ id: section.sectionKey,
25842
+ kind: section.kind,
25843
+ label: section.kind === "project" ? section.userProject?.label ?? section.sectionKey : input.labels.sectionConversations,
25844
+ project,
25845
+ items
25846
+ });
25847
+ }
25848
+ if (pinned.length > 0) {
25849
+ result.unshift({
25850
+ id: "pinned",
25851
+ kind: "pinned",
25852
+ label: input.labels.sectionPinned,
25853
+ project: null,
25854
+ items: pinned.sort(
25855
+ (left, right) => (right.pinnedAtUnixMs ?? 0) - (left.pinnedAtUnixMs ?? 0) || (right.sortTimeUnixMs ?? right.updatedAtUnixMs) - (left.sortTimeUnixMs ?? left.updatedAtUnixMs) || left.id.localeCompare(right.id)
25856
+ )
25857
+ });
25858
+ }
25859
+ return result;
25860
+ }
25540
25861
  function conversationSummariesRenderEqual2(left, right) {
25541
25862
  return left.id === right.id && left.provider === right.provider && left.title === right.title && left.titleFallback === right.titleFallback && left.status === right.status && left.cwd === right.cwd && left.pinnedAtUnixMs === right.pinnedAtUnixMs && left.sortTimeUnixMs === right.sortTimeUnixMs && left.updatedAtUnixMs === right.updatedAtUnixMs && left.isImported === right.isImported && left.hasUnreadCompletion === right.hasUnreadCompletion && left.unreadCompletionKey === right.unreadCompletionKey && conversationProjectsRenderEqual2(left.project, right.project) && conversationSyncStatesRenderEqual(left.syncState, right.syncState);
25542
25863
  }
@@ -25700,9 +26021,239 @@ var AgentGUIProviderRail = memo(function AgentGUIProviderRail2({
25700
26021
  }
25701
26022
  );
25702
26023
  });
26024
+ function useAgentGUIConversationRail({
26025
+ conversationFilter,
26026
+ conversationQuery,
26027
+ conversations,
26028
+ labels,
26029
+ previewMode,
26030
+ userProjects,
26031
+ workspaceId
26032
+ }) {
26033
+ const agentActivityRuntime = useAgentActivityRuntime();
26034
+ const [runtimeRailSections, setRuntimeRailSections] = useState11(null);
26035
+ const [sectionPageStates, setSectionPageStates] = useState11(() => /* @__PURE__ */ new Map());
26036
+ const pagingRequestSequenceRef = useRef12(0);
26037
+ const pagingAbortControllersRef = useRef12(/* @__PURE__ */ new Map());
26038
+ const runtimeListSessionSections = agentActivityRuntime.listSessionSections;
26039
+ const runtimeListSessionSectionPage = agentActivityRuntime.listSessionSectionPage;
26040
+ const runtimeSectionsEnabled = !previewMode && Boolean(runtimeListSessionSections) && Boolean(runtimeListSessionSectionPage);
26041
+ const sectionAgentTargetId = conversationFilter.kind === "agentTarget" ? conversationFilter.agentTargetId.trim() : "";
26042
+ const userProjectPaths = useMemo10(
26043
+ () => userProjects.map((project) => project.path.trim()).filter((path) => path.length > 0),
26044
+ [userProjects]
26045
+ );
26046
+ const userProjectPathKey = useMemo10(
26047
+ () => JSON.stringify(userProjectPaths),
26048
+ [userProjectPaths]
26049
+ );
26050
+ const sectionProjectionLabels = useMemo10(
26051
+ () => ({
26052
+ sectionConversations: labels.sectionConversations,
26053
+ sectionPinned: labels.sectionPinned
26054
+ }),
26055
+ [labels.sectionConversations, labels.sectionPinned]
26056
+ );
26057
+ useEffect12(() => {
26058
+ pagingRequestSequenceRef.current += 1;
26059
+ for (const controller of pagingAbortControllersRef.current.values()) {
26060
+ controller.abort();
26061
+ }
26062
+ pagingAbortControllersRef.current.clear();
26063
+ setRuntimeRailSections(null);
26064
+ setSectionPageStates(/* @__PURE__ */ new Map());
26065
+ return () => {
26066
+ pagingRequestSequenceRef.current += 1;
26067
+ for (const controller of pagingAbortControllersRef.current.values()) {
26068
+ controller.abort();
26069
+ }
26070
+ pagingAbortControllersRef.current.clear();
26071
+ };
26072
+ }, [conversationFilter, userProjectPathKey, workspaceId]);
26073
+ const conversationMembershipKey = useMemo10(
26074
+ () => conversations.map(
26075
+ (conversation) => `${conversation.id}:${conversation.pinnedAtUnixMs ?? 0}`
26076
+ ).join("|"),
26077
+ [conversations]
26078
+ );
26079
+ useEffect12(() => {
26080
+ if (!runtimeSectionsEnabled || !runtimeListSessionSections) {
26081
+ return;
26082
+ }
26083
+ const requestSequence = pagingRequestSequenceRef.current;
26084
+ const abortController = new AbortController();
26085
+ void runtimeListSessionSections({
26086
+ agentTargetId: sectionAgentTargetId || void 0,
26087
+ limitPerSection: AGENT_GUI_CONVERSATION_RAIL_SECTION_PAGE_SIZE,
26088
+ signal: abortController.signal,
26089
+ workspaceId
26090
+ }).then((page) => {
26091
+ if (abortController.signal.aborted || requestSequence !== pagingRequestSequenceRef.current) {
26092
+ return;
26093
+ }
26094
+ const sections = projectRuntimeSectionsToConversationSections({
26095
+ conversationFilter,
26096
+ labels: sectionProjectionLabels,
26097
+ sections: page.sections,
26098
+ workspaceId: page.workspaceId
26099
+ });
26100
+ setRuntimeRailSections(
26101
+ (current) => stabilizeConversationSections(current, sections)
26102
+ );
26103
+ setSectionPageStates(() => {
26104
+ const next = /* @__PURE__ */ new Map();
26105
+ for (const section of page.sections) {
26106
+ next.set(section.sectionKey, {
26107
+ hasMore: section.hasMore,
26108
+ isLoading: false,
26109
+ nextCursor: section.nextCursor ?? null
26110
+ });
26111
+ }
26112
+ return next;
26113
+ });
26114
+ }).catch(() => {
26115
+ if (abortController.signal.aborted || requestSequence !== pagingRequestSequenceRef.current) {
26116
+ return;
26117
+ }
26118
+ setRuntimeRailSections([]);
26119
+ });
26120
+ return () => {
26121
+ abortController.abort();
26122
+ };
26123
+ }, [
26124
+ conversationFilter,
26125
+ conversationMembershipKey,
26126
+ runtimeListSessionSections,
26127
+ runtimeSectionsEnabled,
26128
+ sectionProjectionLabels,
26129
+ sectionAgentTargetId,
26130
+ userProjectPathKey,
26131
+ workspaceId
26132
+ ]);
26133
+ useEffect12(() => {
26134
+ if (!runtimeSectionsEnabled) {
26135
+ return;
26136
+ }
26137
+ setRuntimeRailSections(
26138
+ (current) => updateConversationSectionsFromSummaries(current, conversations)
26139
+ );
26140
+ }, [conversations, runtimeSectionsEnabled]);
26141
+ const loadMoreSectionConversations = useCallback10(
26142
+ (section) => {
26143
+ if (!runtimeListSessionSectionPage || previewMode || conversationQuery.trim()) {
26144
+ return;
26145
+ }
26146
+ if (section.kind === "pinned") {
26147
+ return;
26148
+ }
26149
+ const currentPageState = sectionPageStates.get(section.id);
26150
+ if (currentPageState?.isLoading || currentPageState?.hasMore === false) {
26151
+ return;
26152
+ }
26153
+ const fallbackCursor = conversationRailPageCursor(section.items);
26154
+ const cursor = currentPageState?.nextCursor ?? fallbackCursor;
26155
+ const requestSequence = pagingRequestSequenceRef.current;
26156
+ const abortController = new AbortController();
26157
+ pagingAbortControllersRef.current.set(section.id, abortController);
26158
+ setSectionPageStates((current) => {
26159
+ const next = new Map(current);
26160
+ next.set(section.id, {
26161
+ hasMore: currentPageState?.hasMore ?? true,
26162
+ isLoading: true,
26163
+ nextCursor: currentPageState?.nextCursor ?? null
26164
+ });
26165
+ return next;
26166
+ });
26167
+ void runtimeListSessionSectionPage({
26168
+ agentTargetId: sectionAgentTargetId || void 0,
26169
+ cursor: cursor || void 0,
26170
+ limit: AGENT_GUI_CONVERSATION_RAIL_SECTION_PAGE_SIZE,
26171
+ sectionKey: section.id,
26172
+ signal: abortController.signal,
26173
+ workspaceId
26174
+ }).then((pageSection) => {
26175
+ if (abortController.signal.aborted || requestSequence !== pagingRequestSequenceRef.current) {
26176
+ return;
26177
+ }
26178
+ const pageConversations = buildAgentGUIConversationSummaries({
26179
+ conversationFilter,
26180
+ provider: AGENT_GUI_CONVERSATION_RAIL_PROJECTION_PROVIDER,
26181
+ snapshot: {
26182
+ composerOptionsByProvider: {},
26183
+ presences: [],
26184
+ sessionMessagesById: {},
26185
+ sessions: pageSection.sessions,
26186
+ workspaceId
26187
+ },
26188
+ userProjects: []
26189
+ }).map((conversation) => ({
26190
+ ...conversation,
26191
+ project: section.kind === "project" ? section.project : null
26192
+ }));
26193
+ setRuntimeRailSections((current) => {
26194
+ if (!current) {
26195
+ return current;
26196
+ }
26197
+ return current.map(
26198
+ (candidate) => candidate.id === section.id ? {
26199
+ ...candidate,
26200
+ items: mergeConversationRailPageItems(
26201
+ candidate.items,
26202
+ pageConversations
26203
+ )
26204
+ } : candidate
26205
+ );
26206
+ });
26207
+ setSectionPageStates((current) => {
26208
+ const next = new Map(current);
26209
+ next.set(section.id, {
26210
+ hasMore: pageSection.hasMore,
26211
+ isLoading: false,
26212
+ nextCursor: pageSection.nextCursor ?? null
26213
+ });
26214
+ return next;
26215
+ });
26216
+ }).catch(() => {
26217
+ if (abortController.signal.aborted || requestSequence !== pagingRequestSequenceRef.current) {
26218
+ return;
26219
+ }
26220
+ setSectionPageStates((current) => {
26221
+ const next = new Map(current);
26222
+ const existing = next.get(section.id);
26223
+ next.set(section.id, {
26224
+ hasMore: existing?.hasMore ?? true,
26225
+ isLoading: false,
26226
+ nextCursor: existing?.nextCursor ?? null
26227
+ });
26228
+ return next;
26229
+ });
26230
+ }).finally(() => {
26231
+ if (pagingAbortControllersRef.current.get(section.id) === abortController) {
26232
+ pagingAbortControllersRef.current.delete(section.id);
26233
+ }
26234
+ });
26235
+ },
26236
+ [
26237
+ conversationFilter,
26238
+ conversationQuery,
26239
+ previewMode,
26240
+ runtimeListSessionSectionPage,
26241
+ sectionAgentTargetId,
26242
+ sectionPageStates,
26243
+ workspaceId
26244
+ ]
26245
+ );
26246
+ return {
26247
+ loadMoreSectionConversations,
26248
+ runtimeSectionsEnabled,
26249
+ runtimeRailSections,
26250
+ sectionPageStates
26251
+ };
26252
+ }
25703
26253
  var AgentGUIConversationRailPane = memo(
25704
26254
  function AgentGUIConversationRailPane2({
25705
26255
  conversations,
26256
+ workspaceId,
25706
26257
  userProjects,
25707
26258
  activeConversationId,
25708
26259
  pendingDeleteConversationId,
@@ -25756,7 +26307,23 @@ var AgentGUIConversationRailPane = memo(
25756
26307
  const conversationItemElementsRef = useRef12(
25757
26308
  /* @__PURE__ */ new Map()
25758
26309
  );
26310
+ const activeConversationScrollCompletedRef = useRef12(null);
26311
+ const previousActiveConversationIdRef = useRef12(null);
25759
26312
  const groupedConversationsRef = useRef12(null);
26313
+ const {
26314
+ loadMoreSectionConversations,
26315
+ runtimeSectionsEnabled,
26316
+ runtimeRailSections,
26317
+ sectionPageStates
26318
+ } = useAgentGUIConversationRail({
26319
+ conversationFilter,
26320
+ conversationQuery,
26321
+ conversations,
26322
+ labels,
26323
+ previewMode,
26324
+ userProjects,
26325
+ workspaceId
26326
+ });
25760
26327
  useEffect12(() => {
25761
26328
  const timer = window.setInterval(() => {
25762
26329
  setCurrentTimeMs(Date.now());
@@ -25765,26 +26332,37 @@ var AgentGUIConversationRailPane = memo(
25765
26332
  window.clearInterval(timer);
25766
26333
  };
25767
26334
  }, []);
26335
+ const displayConversations = useMemo10(
26336
+ () => runtimeSectionsEnabled ? runtimeRailSections?.flatMap((section) => section.items) ?? [] : runtimeRailSections ? runtimeRailSections.flatMap((section) => section.items) : conversations,
26337
+ [conversations, runtimeRailSections, runtimeSectionsEnabled]
26338
+ );
25768
26339
  const filteredConversationResult = useMemo10(() => {
25769
26340
  const startedAtMs = agentGuiPerfNowMs();
25770
26341
  const query = conversationQuery.trim().toLowerCase();
25771
- const items = !query ? conversations : conversations.filter(
26342
+ const items = !query ? displayConversations : displayConversations.filter(
25772
26343
  (candidate) => conversationPlainTitle(candidate, labels, uiLanguage).toLowerCase().includes(query)
25773
26344
  );
25774
26345
  return {
25775
26346
  items,
25776
26347
  filterMs: roundAgentGuiPerfMs(agentGuiPerfNowMs() - startedAtMs)
25777
26348
  };
25778
- }, [conversationQuery, conversations, labels, uiLanguage]);
26349
+ }, [conversationQuery, displayConversations, labels, uiLanguage]);
25779
26350
  const filteredConversations = filteredConversationResult.items;
25780
26351
  const groupedConversationResult = useMemo10(() => {
25781
26352
  const startedAtMs = agentGuiPerfNowMs();
25782
- const rawGroups = groupConversations(
25783
- filteredConversations,
25784
- labels,
25785
- conversationQuery.trim() ? [] : userProjects,
25786
- { includeEmptyConversations: !conversationQuery.trim() }
25787
- );
26353
+ const query = conversationQuery.trim();
26354
+ const rawGroups = runtimeSectionsEnabled || runtimeRailSections ? runtimeRailSections ? !query ? runtimeRailSections : runtimeRailSections.map((section) => ({
26355
+ ...section,
26356
+ items: section.items.filter(
26357
+ (item) => filteredConversations.some(
26358
+ (conversation) => conversation.id === item.id
26359
+ )
26360
+ )
26361
+ })).filter(
26362
+ (section) => section.kind !== "pinned" || section.items.length > 0
26363
+ ) : [] : groupConversations(filteredConversations, labels, userProjects, {
26364
+ includeEmptyConversations: !query
26365
+ });
25788
26366
  const groups = stabilizeConversationSections(
25789
26367
  groupedConversationsRef.current,
25790
26368
  rawGroups
@@ -25794,7 +26372,14 @@ var AgentGUIConversationRailPane = memo(
25794
26372
  groups,
25795
26373
  groupMs: roundAgentGuiPerfMs(agentGuiPerfNowMs() - startedAtMs)
25796
26374
  };
25797
- }, [conversationQuery, filteredConversations, labels, userProjects]);
26375
+ }, [
26376
+ conversationQuery,
26377
+ filteredConversations,
26378
+ labels,
26379
+ runtimeRailSections,
26380
+ runtimeSectionsEnabled,
26381
+ userProjects
26382
+ ]);
25798
26383
  const groupedConversations = groupedConversationResult.groups;
25799
26384
  const toggleProjectSectionCollapsed = useCallback10((sectionId) => {
25800
26385
  setCollapsedProjectSectionIds((current) => {
@@ -25815,7 +26400,7 @@ var AgentGUIConversationRailPane = memo(
25815
26400
  );
25816
26401
  const projectConversationCountsByPath = useMemo10(() => {
25817
26402
  const counts = /* @__PURE__ */ new Map();
25818
- for (const conversation of conversations) {
26403
+ for (const conversation of displayConversations) {
25819
26404
  const normalizedPath = normalizeConversationRailProjectPath(
25820
26405
  conversation.project?.path
25821
26406
  );
@@ -25825,7 +26410,8 @@ var AgentGUIConversationRailPane = memo(
25825
26410
  counts.set(normalizedPath, (counts.get(normalizedPath) ?? 0) + 1);
25826
26411
  }
25827
26412
  return counts;
25828
- }, [conversations]);
26413
+ }, [displayConversations]);
26414
+ const isRuntimeRailLoading = runtimeSectionsEnabled && runtimeRailSections === null;
25829
26415
  const registerConversationItemElement = useCallback10(
25830
26416
  (itemId, element) => {
25831
26417
  if (element) {
@@ -25837,10 +26423,25 @@ var AgentGUIConversationRailPane = memo(
25837
26423
  []
25838
26424
  );
25839
26425
  useLayoutEffect4(() => {
25840
- if (!activeConversationId) {
26426
+ const activeId = activeConversationId?.trim() ?? "";
26427
+ if (!activeId) {
26428
+ previousActiveConversationIdRef.current = null;
26429
+ activeConversationScrollCompletedRef.current = null;
26430
+ return;
26431
+ }
26432
+ if (previousActiveConversationIdRef.current !== activeId) {
26433
+ previousActiveConversationIdRef.current = activeId;
26434
+ activeConversationScrollCompletedRef.current = null;
26435
+ }
26436
+ if (activeConversationScrollCompletedRef.current === activeId) {
25841
26437
  return;
25842
26438
  }
25843
- conversationItemElementsRef.current.get(activeConversationId)?.scrollIntoView({ block: "nearest" });
26439
+ const activeElement = conversationItemElementsRef.current.get(activeId);
26440
+ if (!activeElement) {
26441
+ return;
26442
+ }
26443
+ activeElement.scrollIntoView({ block: "nearest" });
26444
+ activeConversationScrollCompletedRef.current = activeId;
25844
26445
  }, [activeConversationId, groupedConversationIdentityKey]);
25845
26446
  return /* @__PURE__ */ jsxs17(
25846
26447
  "aside",
@@ -25917,7 +26518,7 @@ var AgentGUIConversationRailPane = memo(
25917
26518
  className: "min-h-0 flex-1 [&_[data-orientation=vertical][data-slot=scroll-area-scrollbar]]:opacity-100",
25918
26519
  viewportRef: conversationListRef,
25919
26520
  viewportClassName: AgentGUINode_styles_default.conversationList,
25920
- children: isLoadingConversations && conversations.length === 0 ? /* @__PURE__ */ jsx31(
26521
+ children: isRuntimeRailLoading || isLoadingConversations && conversations.length === 0 ? /* @__PURE__ */ jsx31(
25921
26522
  AgentConversationListSkeleton,
25922
26523
  {
25923
26524
  label: labels.loadingConversations
@@ -25930,6 +26531,8 @@ var AgentGUIConversationRailPane = memo(
25930
26531
  const showProjectRailHeader = !conversationQuery.trim() && section.kind !== "pinned" && (sectionIndex === 0 || groupedConversations[sectionIndex - 1]?.kind === "pinned");
25931
26532
  const isSectionCollapsed = isProjectSection && collapsedProjectSectionIds.has(section.id);
25932
26533
  const projectConversationCount = normalizedProjectPath ? projectConversationCountsByPath.get(normalizedProjectPath) ?? 0 : 0;
26534
+ const sectionPageState = sectionPageStates.get(section.id);
26535
+ const sectionHasMore = !conversationQuery.trim() && section.kind !== "pinned" && sectionPageState?.hasMore === true;
25933
26536
  return /* @__PURE__ */ jsxs17(Fragment7, { children: [
25934
26537
  showProjectRailHeader ? /* @__PURE__ */ jsx31(
25935
26538
  AgentGUIProjectRailHeader,
@@ -25946,6 +26549,7 @@ var AgentGUIConversationRailPane = memo(
25946
26549
  createConversationDisabled,
25947
26550
  currentTimeMs,
25948
26551
  isDeletingConversation,
26552
+ isLoadingMoreConversations: sectionPageState?.isLoading ?? false,
25949
26553
  isSectionCollapsed,
25950
26554
  labels,
25951
26555
  pendingDeleteConversationId,
@@ -25955,10 +26559,12 @@ var AgentGUIConversationRailPane = memo(
25955
26559
  projectPath,
25956
26560
  registerItemElement: registerConversationItemElement,
25957
26561
  section,
26562
+ sectionHasMore,
25958
26563
  uiLanguage,
25959
26564
  onCancelDeleteConversation,
25960
26565
  onConfirmDeleteConversation,
25961
26566
  onCreateConversation,
26567
+ onLoadMoreConversations: loadMoreSectionConversations,
25962
26568
  onRequestDeleteConversation,
25963
26569
  onSelectConversation,
25964
26570
  setPendingProjectAction,
@@ -26094,6 +26700,8 @@ var AgentGUIConversationRailSection = memo(
26094
26700
  pendingDeleteConversationId,
26095
26701
  previewMode,
26096
26702
  isDeletingConversation,
26703
+ isLoadingMoreConversations,
26704
+ sectionHasMore,
26097
26705
  createConversationDisabled,
26098
26706
  currentTimeMs,
26099
26707
  labels,
@@ -26102,6 +26710,7 @@ var AgentGUIConversationRailSection = memo(
26102
26710
  onCreateConversation,
26103
26711
  onToggleProjectSectionCollapsed,
26104
26712
  onSelectConversation,
26713
+ onLoadMoreConversations,
26105
26714
  setPendingProjectAction,
26106
26715
  onToggleConversationPinned,
26107
26716
  onOpenProjectFiles,
@@ -26117,16 +26726,29 @@ var AgentGUIConversationRailSection = memo(
26117
26726
  );
26118
26727
  const visibleItemCount = isSectionCollapsed ? 0 : Math.min(visibleItemLimit, section.items.length);
26119
26728
  const visibleItems = isSectionCollapsed ? [] : section.items.slice(0, visibleItemCount);
26120
- const canShowMore = !isSectionCollapsed && visibleItemCount < section.items.length;
26729
+ const canShowMore = !isSectionCollapsed && (visibleItemCount < section.items.length || sectionHasMore);
26121
26730
  const canShowLess = !isSectionCollapsed && visibleItemCount > AGENT_GUI_CONVERSATION_RAIL_SECTION_PAGE_SIZE;
26122
26731
  const showMoreConversations = useCallback10(() => {
26732
+ if (visibleItemCount >= section.items.length && sectionHasMore) {
26733
+ onLoadMoreConversations(section);
26734
+ setVisibleItemLimit(
26735
+ (current) => current + AGENT_GUI_CONVERSATION_RAIL_SECTION_PAGE_SIZE
26736
+ );
26737
+ return;
26738
+ }
26123
26739
  setVisibleItemLimit(
26124
26740
  (current) => Math.min(
26125
26741
  section.items.length,
26126
26742
  current + AGENT_GUI_CONVERSATION_RAIL_SECTION_PAGE_SIZE
26127
26743
  )
26128
26744
  );
26129
- }, [section.items.length]);
26745
+ }, [
26746
+ onLoadMoreConversations,
26747
+ section,
26748
+ section.items.length,
26749
+ sectionHasMore,
26750
+ visibleItemCount
26751
+ ]);
26130
26752
  const showLessConversations = useCallback10(() => {
26131
26753
  setVisibleItemLimit(AGENT_GUI_CONVERSATION_RAIL_SECTION_PAGE_SIZE);
26132
26754
  }, []);
@@ -26419,6 +27041,7 @@ var AgentGUIConversationRailSection = memo(
26419
27041
  {
26420
27042
  type: "button",
26421
27043
  className: AgentGUINode_styles_default.conversationSectionPaginationButton,
27044
+ disabled: isLoadingMoreConversations,
26422
27045
  onClick: showMoreConversations,
26423
27046
  children: labels.showMoreConversations
26424
27047
  }
@@ -28212,6 +28835,7 @@ var AgentGUINode = memo2(function AgentGUINode2({
28212
28835
  mentionPalette: t("agentHost.agentGui.mentionPalette"),
28213
28836
  removeMention: t("common.remove"),
28214
28837
  addReference: t("agentHost.agentGui.addReference"),
28838
+ addContent: t("agentHost.agentGui.addContent"),
28215
28839
  referenceWorkspaceFiles: t("agentHost.issue.referenceWorkspaceFiles")
28216
28840
  }),
28217
28841
  [displayProviderLabel, fallbackAgentTitle, t]