@qredence/fleet 0.5.10 → 0.6.0

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 (115) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/dist/web/client/assets/agent-activity-CwMDU7aP.js +1 -0
  3. package/dist/web/client/assets/artifacts-panel-CJ75gQub.js +1 -0
  4. package/dist/web/client/assets/chat-Ci2cEQrR.js +52 -0
  5. package/dist/web/client/assets/{chat-command-palette-DfYSPPXI.js → chat-command-palette-CkISHfKE.js} +1 -1
  6. package/dist/web/client/assets/{citations-BQ_pr_9_.js → citations-C_tPOJE_.js} +1 -1
  7. package/dist/web/client/assets/{command-DPfiaYUL.js → command-_WjnervL.js} +1 -1
  8. package/dist/web/client/assets/fleet-message-queue-BCno4XP-.js +1 -0
  9. package/dist/web/client/assets/{fleet-pi-tool-renderer-AJoMbXBa.js → fleet-pi-tool-renderer-BEDIO3al.js} +4 -4
  10. package/dist/web/client/assets/fleet-reasoning-panel-CbkO7u-v.js +1 -0
  11. package/dist/web/client/assets/{fleet-subagent-list-BnRnrWKS.js → fleet-subagent-list-iKUtLJKZ.js} +1 -1
  12. package/dist/web/client/assets/fleet-tool-timeline-C8heL7ae.js +1 -0
  13. package/dist/web/client/assets/{fork-picker-dialog-CkcSekBl.js → fork-picker-dialog-ByBOGVsa.js} +1 -1
  14. package/dist/web/client/assets/globals-B_I1Eq1u.css +2 -0
  15. package/dist/web/client/assets/horizontal-resize-CwoDojST.js +1 -0
  16. package/dist/web/client/assets/{index-DlnHLDpx.js → index-DJ1fFbQu.js} +3 -3
  17. package/dist/web/client/assets/input-group-Tb5TYbzi.js +1 -0
  18. package/dist/web/client/assets/{ipython-tool-BrMePqD-.js → ipython-tool-ldJ9F1Cw.js} +1 -1
  19. package/dist/web/client/assets/model-selector-list-Ch05B2nZ.js +1 -0
  20. package/dist/web/client/assets/{openui-renderer-DwYFJdbe.js → openui-renderer-Bf60nxNi.js} +4 -4
  21. package/dist/web/client/assets/pencil-DcUwsKLn.js +1 -0
  22. package/dist/web/client/assets/prompt-input-qPIXZ-Rb.js +1 -0
  23. package/dist/web/client/assets/prompt-suggestions-Cc--lSNR.js +1 -0
  24. package/dist/web/client/assets/{provider-label-BCJh04J5.js → provider-label-DDLRnZyC.js} +1 -1
  25. package/dist/web/client/assets/repl-panel-DsPX04Xr.js +1 -0
  26. package/dist/web/client/assets/{resources-panel-Bo8dfUdm.js → resources-panel-D867-goy.js} +1 -1
  27. package/dist/web/client/assets/right-panel-registry-Dp8yX-oL.js +2 -0
  28. package/dist/web/client/assets/routes-DpgMJZ5n.js +16 -0
  29. package/dist/web/client/assets/safe-storage-s25GrfpH.js +1 -0
  30. package/dist/web/client/assets/session-insights-panel-YnaXvTpi.js +1 -0
  31. package/dist/web/client/assets/settings-dialog-YJkvt5EB.js +2 -0
  32. package/dist/web/client/assets/skeleton-loaders-C9vHwAYV.js +1 -0
  33. package/dist/web/client/assets/{subagent-chat-panel-DseoO31p.js → subagent-chat-panel-Yujplxpb.js} +1 -1
  34. package/dist/web/client/assets/subagent-transcript-CnI-mqN0.js +1 -0
  35. package/dist/web/client/assets/subagents-panel-CjXEdimj.js +1 -0
  36. package/dist/web/client/assets/{surfaces-cW-gp56p.js → surfaces-DI-U-_2a.js} +1 -1
  37. package/dist/web/client/assets/tool-result-DfnPN0FQ.js +4 -0
  38. package/dist/web/client/assets/ui-preferences-CImQGZm_.js +1 -0
  39. package/dist/web/client/assets/virtualized-turn-list--Vynre4D.js +6 -0
  40. package/dist/web/client/assets/{workspace-panel-DI1W3ce9.js → workspace-panel-CPPIznT9.js} +1 -1
  41. package/dist/web/client/bundle-budget.json +6 -6
  42. package/dist/web/server/{_tanstack-start-manifest_v-Cdx6hy2i-I7A5YJRU.js → _tanstack-start-manifest_v-DS_CSIFQ-WB3VTKF3.js} +15 -13
  43. package/dist/web/server/{agent-activity-B-JMvecd-SLE3GGY2.js → agent-activity-CS2rbF_C-A3R26CYH.js} +2 -2
  44. package/dist/web/server/{artifacts-panel-DLMK1O8P-42T45JMA.js → artifacts-panel-CaKrX2XC-R37I4BHF.js} +12 -12
  45. package/dist/web/server/{chat-command-palette-CdYwoTMe-4LBAZF7K.js → chat-command-palette-7gbqEnm9-6XICQZN7.js} +4 -4
  46. package/dist/web/server/{chunk-EBCYJSBR.js → chunk-7SD2ZSEA.js} +3 -3
  47. package/dist/web/server/{chunk-6AW2XFTZ.js → chunk-BBBS5AS7.js} +194 -10
  48. package/dist/web/server/{chunk-EOVMHQ2H.js → chunk-CNXJN5HN.js} +7 -7
  49. package/dist/web/server/{chunk-XKKXXG6N.js → chunk-DI7XRK2H.js} +2 -2
  50. package/dist/web/server/{chunk-KNJUSMBT.js → chunk-DZ2IC3FH.js} +2 -2
  51. package/dist/web/server/{chunk-K5ESTT4A.js → chunk-EAE2QXRK.js} +11 -3
  52. package/dist/web/server/{chunk-VHBFU4TG.js → chunk-EH4BZ6QM.js} +123 -16
  53. package/dist/web/server/{chunk-54II5QXQ.js → chunk-ETTDO4UO.js} +6 -3
  54. package/dist/web/server/{chunk-EHNIN245.js → chunk-GETSIVNU.js} +5 -5
  55. package/dist/web/server/{chunk-X2R5YPQZ.js → chunk-IJPCV6DH.js} +3 -2
  56. package/dist/web/server/{chunk-AJJ2S5FF.js → chunk-JQDLJ7KI.js} +20 -20
  57. package/dist/web/server/{chunk-M564UIEY.js → chunk-KELEYPVK.js} +8 -8
  58. package/dist/web/server/{chunk-OB5OSYJK.js → chunk-LXJD6IGW.js} +53 -29
  59. package/dist/web/server/chunk-M5RSPNYN.js +22 -0
  60. package/dist/web/server/{chunk-2TRF62K5.js → chunk-N6NOTURM.js} +3 -3
  61. package/dist/web/server/{chunk-5XX7RKJ6.js → chunk-NXJ32VFR.js} +5 -5
  62. package/dist/web/server/{chunk-P7H2OPKF.js → chunk-PIOFZUOU.js} +9 -1
  63. package/dist/web/server/chunk-PTCKOR23.js +39 -0
  64. package/dist/web/server/chunk-SZJUXVWG.js +40 -0
  65. package/dist/web/server/{chunk-TCH3U26B.js → chunk-TWYHHG5N.js} +2 -10
  66. package/dist/web/server/{chunk-FED63ZHU.js → chunk-WHBVQJ4K.js} +11 -6
  67. package/dist/web/server/{chunk-ANL4B775.js → chunk-XLNCWZMZ.js} +2 -2
  68. package/dist/web/server/{chunk-GM32R7JW.js → chunk-YKVGQBZA.js} +10 -8
  69. package/dist/web/server/{chunk-NRDG2ISJ.js → chunk-YNUWKMNQ.js} +59 -52
  70. package/dist/web/server/{chunk-3PIUR75R.js → chunk-YXXRP3NS.js} +9 -9
  71. package/dist/web/server/fleet-message-queue-BS-cZ56r-GLZXUKDF.js +152 -0
  72. package/dist/web/server/{fleet-pi-tool-renderer-RIeVlM9J-D6MISCQC.js → fleet-pi-tool-renderer-umKunT3K-O4GBH35V.js} +5 -5
  73. package/dist/web/server/{fleet-reasoning-panel-D_K48UOT-GN2PA6KT.js → fleet-reasoning-panel-BxC2COxi-GPLMQSTT.js} +9 -9
  74. package/dist/web/server/{fleet-subagent-list-5luKtpds-3OTVFHJQ.js → fleet-subagent-list-CpSYzCIq-JDH2LHSS.js} +1 -1
  75. package/dist/web/server/{fleet-tool-timeline-DwRqQgOj-HUFLGMDV.js → fleet-tool-timeline-IB36_PB2-XJENTO6I.js} +1 -1
  76. package/dist/web/server/{fork-picker-dialog-B9yGc8Au-IL63F2DN.js → fork-picker-dialog-DlINz9UQ-UWIXFDJX.js} +3 -3
  77. package/dist/web/server/{model-selector-list-cb2-ewoA-KIVU6LD3.js → model-selector-list-jBTZc2Mu-OXJOS5NA.js} +7 -7
  78. package/dist/web/server/{openui-renderer-Czy5Vo2L-BLXPJD65.js → openui-renderer-Biyyjhjn-SJOEKPTJ.js} +4 -4
  79. package/dist/web/server/{prompt-suggestions-BOmHi4-J-C563CHFU.js → prompt-suggestions-D4AEEY7K-RZSP7PWV.js} +3 -3
  80. package/dist/web/server/{repl-panel-yyxhwe4c-7U6HXYPS.js → repl-panel-D5KsoJik-BQKO53JO.js} +9 -9
  81. package/dist/web/server/{resources-panel-j4fAIi9g-5C267IXV.js → resources-panel-CE5pD4vy-V5FXBTYC.js} +2 -2
  82. package/dist/web/server/{router-CgSWrAYc-5UBYSZTJ.js → router-DWALoX_M-I5CBL7FQ.js} +1461 -515
  83. package/dist/web/server/{routes-CP_BBhD0-BAWQYGKY.js → routes-BBVirYfL-5WXMOT7M.js} +908 -566
  84. package/dist/web/server/server.js +2 -2
  85. package/dist/web/server/{session-insights-panel-BHZyKDTo-LRMAMA3O.js → session-insights-panel-CUhdgvRt-VB2HUCQP.js} +4 -4
  86. package/dist/web/server/{settings-dialog-CxHe8nym-KKXDPTIW.js → settings-dialog-DndPbM-v-RFNXXEAN.js} +902 -575
  87. package/dist/web/server/{subagent-chat-panel-DlSsM59d-DBW7DI3T.js → subagent-chat-panel-C0RpnXav-J7VYO7QY.js} +11 -11
  88. package/dist/web/server/{subagents-panel-Txzk8oDb-NRKLASYN.js → subagents-panel-jDqIn9Nh-YEV6QLUY.js} +13 -13
  89. package/dist/web/server/{workspace-panel-BOs-58Cv-SWQBMZSB.js → workspace-panel-CX_Vo6As-EWO6AMPI.js} +5 -4
  90. package/package.json +1 -1
  91. package/dist/web/client/assets/agent-activity-CDcDNVC6.js +0 -1
  92. package/dist/web/client/assets/artifacts-panel-CObI-DMt.js +0 -1
  93. package/dist/web/client/assets/chat-C8XDWWXz.js +0 -52
  94. package/dist/web/client/assets/fleet-message-queue-zWM5-y18.js +0 -1
  95. package/dist/web/client/assets/fleet-reasoning-panel-MtbSdoCv.js +0 -1
  96. package/dist/web/client/assets/fleet-tool-timeline-COzPrwr8.js +0 -1
  97. package/dist/web/client/assets/generative-text-renderer-CDKHv-v_.js +0 -6
  98. package/dist/web/client/assets/globals-DisQPFtV.css +0 -2
  99. package/dist/web/client/assets/horizontal-resize-Bl3AyBJg.js +0 -1
  100. package/dist/web/client/assets/input-group-BFDsCVS9.js +0 -1
  101. package/dist/web/client/assets/model-selector-list-DQaPFUYt.js +0 -1
  102. package/dist/web/client/assets/prompt-input-DZ4cho_e.js +0 -1
  103. package/dist/web/client/assets/prompt-suggestions-CXM6knMK.js +0 -1
  104. package/dist/web/client/assets/repl-panel-BDQ5MEgV.js +0 -1
  105. package/dist/web/client/assets/right-panel-registry-VVRPktV3.js +0 -2
  106. package/dist/web/client/assets/routes-DAikUNzO.js +0 -16
  107. package/dist/web/client/assets/session-insights-panel-CQdT90Op.js +0 -1
  108. package/dist/web/client/assets/settings-dialog-DS64KmwC.js +0 -1
  109. package/dist/web/client/assets/skeleton-loaders-DjGv9LLA.js +0 -1
  110. package/dist/web/client/assets/subagent-transcript-cxVKYnh9.js +0 -1
  111. package/dist/web/client/assets/subagents-panel-CHC96I68.js +0 -1
  112. package/dist/web/client/assets/tool-result-Baj3CdL_.js +0 -4
  113. package/dist/web/client/assets/ui-preferences-DUEFuJFj.js +0 -1
  114. package/dist/web/server/chunk-QK4CHLVV.js +0 -17
  115. package/dist/web/server/fleet-message-queue-BxycG26e-2XLOTCLP.js +0 -75
@@ -1,5 +1,10 @@
1
1
  import {
2
2
  ChatCommandsResponseSchema,
3
+ ChatMcpDeleteRequestSchema,
4
+ ChatMcpListResponseSchema,
5
+ ChatMcpOAuthLoginRequestSchema,
6
+ ChatMcpOAuthLoginResponseSchema,
7
+ ChatMcpUpsertRequestSchema,
3
8
  ChatModelsDiscoverRequestSchema,
4
9
  ChatModelsDiscoverResponseSchema,
5
10
  ChatModelsResponseSchema,
@@ -21,12 +26,12 @@ import {
21
26
  useMutation,
22
27
  useQuery,
23
28
  useQueryClient
24
- } from "./chunk-VHBFU4TG.js";
29
+ } from "./chunk-EH4BZ6QM.js";
25
30
  import {
26
31
  Library,
27
32
  RIGHT_PANEL_LAUNCHER_DEFINITIONS,
28
33
  getRightPanelDefinition
29
- } from "./chunk-EOVMHQ2H.js";
34
+ } from "./chunk-CNXJN5HN.js";
30
35
  import {
31
36
  AlertDialog,
32
37
  AlertDialogAction,
@@ -41,7 +46,6 @@ import {
41
46
  CHROME_PILL_CLASS,
42
47
  CHROME_PILL_INACTIVE_CLASS,
43
48
  PANEL_OVERLAY_CLASS,
44
- Pencil,
45
49
  ProviderBrandIcon,
46
50
  Settings,
47
51
  Spinner,
@@ -51,7 +55,10 @@ import {
51
55
  useHoverFloatingInteraction,
52
56
  useHoverReferenceInteraction,
53
57
  usePopupHandleStore
54
- } from "./chunk-TCH3U26B.js";
58
+ } from "./chunk-TWYHHG5N.js";
59
+ import {
60
+ Pencil
61
+ } from "./chunk-M5RSPNYN.js";
55
62
  import {
56
63
  RightPanelProvider,
57
64
  useChatPanelDataContext,
@@ -66,7 +73,7 @@ import {
66
73
  PromptInput,
67
74
  useHydrated,
68
75
  usePopoverPortalPosition
69
- } from "./chunk-GM32R7JW.js";
76
+ } from "./chunk-YKVGQBZA.js";
70
77
  import "./chunk-7CNGNFFK.js";
71
78
  import {
72
79
  Plus
@@ -81,10 +88,11 @@ import {
81
88
  MessageContent,
82
89
  MessageScroller,
83
90
  UserMessage,
91
+ VirtualizedTurnList,
84
92
  buildAssistantElements,
85
93
  groupMessages,
86
94
  normalizeAssistantToolParts
87
- } from "./chunk-6AW2XFTZ.js";
95
+ } from "./chunk-BBBS5AS7.js";
88
96
  import "./chunk-FJV6EQDW.js";
89
97
  import {
90
98
  RefreshCw
@@ -105,14 +113,14 @@ import {
105
113
  MessageCircleQuestionMark,
106
114
  PI_TOOL_RENDERERS,
107
115
  useHoverCapable
108
- } from "./chunk-2TRF62K5.js";
116
+ } from "./chunk-N6NOTURM.js";
109
117
  import "./chunk-QPNUGF3V.js";
110
118
  import {
111
119
  field,
112
120
  floating,
113
121
  mono,
114
122
  paper
115
- } from "./chunk-ANL4B775.js";
123
+ } from "./chunk-XLNCWZMZ.js";
116
124
  import "./chunk-BLSX7WHW.js";
117
125
  import {
118
126
  Sparkles
@@ -136,11 +144,20 @@ import {
136
144
  thinkingLevelLabel,
137
145
  toModelOption,
138
146
  toModelSelection
139
- } from "./chunk-FED63ZHU.js";
140
- import "./chunk-QK4CHLVV.js";
147
+ } from "./chunk-WHBVQJ4K.js";
148
+ import {
149
+ disambiguateSessionLabel,
150
+ fallbackSessionLabel,
151
+ sessionListTitle
152
+ } from "./chunk-PTCKOR23.js";
141
153
  import {
142
154
  Folder
143
155
  } from "./chunk-GS2IZGRC.js";
156
+ import {
157
+ readStoredValue,
158
+ removeStoredValue,
159
+ writeStoredValue
160
+ } from "./chunk-SZJUXVWG.js";
144
161
  import {
145
162
  resolveWorkspacePanelTarget
146
163
  } from "./chunk-P66QQWUM.js";
@@ -224,7 +241,7 @@ import {
224
241
  Badge,
225
242
  UiErrorBoundary,
226
243
  decodeOpenPanelActionMessage
227
- } from "./chunk-KNJUSMBT.js";
244
+ } from "./chunk-DZ2IC3FH.js";
228
245
  import {
229
246
  ChatOpenUIArtifactUpsertRequestSchema,
230
247
  ChatOpenUIArtifactUpsertResponseSchema,
@@ -248,7 +265,7 @@ import {
248
265
  UploadedAttachmentSchema,
249
266
  WorkspaceRelativePathSchema,
250
267
  external_exports
251
- } from "./chunk-NRDG2ISJ.js";
268
+ } from "./chunk-YNUWKMNQ.js";
252
269
  import {
253
270
  CompositeList,
254
271
  Select,
@@ -409,7 +426,7 @@ import "./chunk-JDCCC7A7.js";
409
426
  import "./chunk-L547YHC4.js";
410
427
  import "./chunk-MLKGABMK.js";
411
428
 
412
- // web/app/dist/server/assets/routes-CP_BBhD0.js
429
+ // web/app/dist/server/assets/routes-BBVirYfL.js
413
430
  import * as React$1 from "react";
414
431
  import { Suspense, createContext as createContext2, createElement, forwardRef as forwardRef2, isValidElement, lazy, memo, useCallback as useCallback2, useContext as useContext2, useEffect as useEffect2, useEffectEvent, useId, useLayoutEffect, useMemo as useMemo2, useReducer, useRef as useRef2, useState as useState2, useSyncExternalStore } from "react";
415
432
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
@@ -1231,139 +1248,6 @@ function agentTabTriggerId(tabId) {
1231
1248
  function agentTabPanelId(tabId) {
1232
1249
  return `agent-tab-panel-${encodeURIComponent(tabId)}`;
1233
1250
  }
1234
- function statusLabel(status) {
1235
- switch (status) {
1236
- case "queued":
1237
- return "queued";
1238
- case "running":
1239
- case "recovering":
1240
- return "streaming";
1241
- case "error":
1242
- case "failed":
1243
- return "error";
1244
- case "cancelled":
1245
- return "cancelled";
1246
- case "done":
1247
- return "complete";
1248
- default:
1249
- return "ready";
1250
- }
1251
- }
1252
- function statusDotClass(status) {
1253
- switch (status) {
1254
- case "running":
1255
- case "recovering":
1256
- return "bg-emerald-400 motion-safe:animate-pulse";
1257
- case "error":
1258
- case "failed":
1259
- return "bg-destructive";
1260
- case "queued":
1261
- return "bg-amber-300";
1262
- case "cancelled":
1263
- return "bg-foreground/35";
1264
- default:
1265
- return "bg-foreground/35";
1266
- }
1267
- }
1268
- function AgentTabBar({ tabs, value, onValueChange, onClose, onNewSession }) {
1269
- const tabRefs = useRef2(/* @__PURE__ */ new Map());
1270
- const setTabRef = useCallback2((tabId, node) => {
1271
- if (node) tabRefs.current.set(tabId, node);
1272
- else tabRefs.current.delete(tabId);
1273
- }, []);
1274
- useEffect2(() => {
1275
- for (const tabId of tabRefs.current.keys()) if (!tabs.some((tab) => tab.id === tabId)) tabRefs.current.delete(tabId);
1276
- }, [tabs]);
1277
- const focusTab = useCallback2((index) => {
1278
- const tab = tabs[index];
1279
- if (!tab) return;
1280
- tabRefs.current.get(tab.id)?.focus();
1281
- onValueChange(tab.id);
1282
- }, [onValueChange, tabs]);
1283
- const handleKeyDown = useCallback2((event, tabId) => {
1284
- const index = tabs.findIndex((tab) => tab.id === tabId);
1285
- if (index < 0) return;
1286
- let nextIndex;
1287
- if (event.key === "ArrowRight") nextIndex = (index + 1) % tabs.length;
1288
- if (event.key === "ArrowLeft") nextIndex = (index - 1 + tabs.length) % tabs.length;
1289
- if (event.key === "Home") nextIndex = 0;
1290
- if (event.key === "End") nextIndex = tabs.length - 1;
1291
- if (nextIndex === void 0) return;
1292
- event.preventDefault();
1293
- focusTab(nextIndex);
1294
- }, [focusTab, tabs]);
1295
- return /* @__PURE__ */ jsxs("div", {
1296
- className: "flex min-w-0 max-w-full items-center gap-1",
1297
- "data-testid": "agent-tab-bar",
1298
- children: [/* @__PURE__ */ jsx("div", {
1299
- "aria-label": "Agent conversations",
1300
- className: "flex min-w-0 flex-1 items-center gap-1 overflow-x-auto overscroll-contain [scrollbar-width:none] [&::-webkit-scrollbar]:hidden",
1301
- role: "tablist",
1302
- children: tabs.map((tab) => {
1303
- const active = tab.id === value;
1304
- const status = statusLabel(tab.status);
1305
- return /* @__PURE__ */ jsxs("div", {
1306
- className: "group/tab relative min-w-0 shrink-0 basis-[164px] sm:max-w-[164px]",
1307
- "data-tab-id": tab.id,
1308
- children: [/* @__PURE__ */ jsxs(Button, {
1309
- ref: (node) => setTabRef(tab.id, node),
1310
- "aria-controls": agentTabPanelId(tab.id),
1311
- "aria-selected": active,
1312
- "aria-label": `${tab.label}, ${status}`,
1313
- className: cn("h-7 w-full min-w-0 justify-start text-left gap-1.5 rounded-[7px] border border-transparent px-2 text-[12px] font-medium leading-none transition-colors motion-reduce:transition-none", active ? "bg-[#2c2c2c] text-foreground shadow-none" : "bg-transparent text-foreground/45 hover:bg-foreground/5 hover:text-foreground/75", tab.kind === "subagent" && onClose && "pr-7"),
1314
- "data-state": active ? "active" : "inactive",
1315
- id: agentTabTriggerId(tab.id),
1316
- onClick: () => onValueChange(tab.id),
1317
- onKeyDown: (event) => handleKeyDown(event, tab.id),
1318
- role: "tab",
1319
- size: "sm",
1320
- tabIndex: active ? 0 : -1,
1321
- type: "button",
1322
- variant: "ghost",
1323
- children: [tab.kind === "main" ? /* @__PURE__ */ jsx(Bot, {
1324
- "aria-hidden": "true",
1325
- className: "size-3.5 shrink-0"
1326
- }) : /* @__PURE__ */ jsx("span", {
1327
- "aria-hidden": "true",
1328
- className: cn("size-1.5 shrink-0 rounded-full", statusDotClass(tab.status))
1329
- }), /* @__PURE__ */ jsx("span", {
1330
- className: "min-w-0 flex-1 truncate text-left",
1331
- children: tab.label
1332
- })]
1333
- }), tab.kind === "subagent" && onClose ? /* @__PURE__ */ jsx(Button, {
1334
- "aria-label": `Close ${tab.label} tab`,
1335
- className: "absolute top-1/2 right-1 size-5 -translate-y-1/2 rounded-[5px] p-0 text-foreground/35 opacity-0 transition-opacity motion-reduce:transition-none hover:bg-foreground/10 hover:text-foreground/75 focus-visible:opacity-100 group-hover/tab:opacity-100",
1336
- onClick: (event) => {
1337
- event.stopPropagation();
1338
- onClose(tab.id);
1339
- },
1340
- size: "icon-xs",
1341
- title: `Close ${tab.label} tab`,
1342
- type: "button",
1343
- variant: "ghost",
1344
- children: /* @__PURE__ */ jsx(X, {
1345
- "aria-hidden": "true",
1346
- className: "size-3"
1347
- })
1348
- }) : null]
1349
- }, tab.id);
1350
- })
1351
- }), onNewSession ? /* @__PURE__ */ jsx(Button, {
1352
- "aria-label": "New chat",
1353
- className: "size-7 shrink-0 rounded-[7px] text-foreground/50 hover:bg-foreground/7 hover:text-foreground/85",
1354
- "data-testid": "new-chat-tab",
1355
- onClick: onNewSession,
1356
- size: "icon-sm",
1357
- title: "New chat",
1358
- type: "button",
1359
- variant: "ghost",
1360
- children: /* @__PURE__ */ jsx(Plus, {
1361
- "aria-hidden": "true",
1362
- className: "size-3.5"
1363
- })
1364
- }) : null]
1365
- });
1366
- }
1367
1251
  function ResizableCanvas({ children, dataTestid, headerLeading, loading, onClose, onRefresh, onResizeStart, open, headerActions, title, titleIcon: TitleIcon, width }) {
1368
1252
  const reduceMotion = useReducedMotion();
1369
1253
  const panelRef = useRef2(null);
@@ -1418,7 +1302,7 @@ function ResizableCanvas({ children, dataTestid, headerLeading, loading, onClose
1418
1302
  children: [/* @__PURE__ */ jsx("div", {
1419
1303
  className: "min-w-0 flex-1",
1420
1304
  children: headerLeading ?? /* @__PURE__ */ jsxs("div", {
1421
- className: "flex min-w-0 items-center gap-2 text-[13px] font-medium text-foreground/80",
1305
+ className: "flex min-w-0 items-center gap-2 text-[0.8125rem] font-medium text-foreground/80",
1422
1306
  children: [/* @__PURE__ */ jsx(TitleIcon, { className: "size-3.5 shrink-0" }), /* @__PURE__ */ jsx("span", { children: title })]
1423
1307
  })
1424
1308
  }), /* @__PURE__ */ jsxs("div", {
@@ -2426,7 +2310,7 @@ var TabsSubtleItem = forwardRef2(({ icon: Icon, label, index, badge, className,
2426
2310
  const tone = chromeTone(isPill, isActive);
2427
2311
  const ariaLabel = ariaLabelProp ?? (collapseLabel && !showLabel ? label : void 0);
2428
2312
  const labelContent = /* @__PURE__ */ jsxs("span", {
2429
- className: cn("inline-grid whitespace-nowrap", isPill ? "text-[12px] font-medium" : "text-[13px]"),
2313
+ className: cn("inline-grid whitespace-nowrap", isPill ? "text-[0.75rem] font-medium" : "text-[0.8125rem]"),
2430
2314
  children: [/* @__PURE__ */ jsx("span", {
2431
2315
  className: "invisible col-start-1 row-start-1 [text-box:trim-both_cap_alphabetic]",
2432
2316
  style: { fontVariationSettings: fontWeights.semibold },
@@ -2465,7 +2349,7 @@ var TabsSubtleItem = forwardRef2(({ icon: Icon, label, index, badge, className,
2465
2349
  strokeWidth: isActive ? 2 : 1.5,
2466
2350
  className: cn("shrink-0 transition-[color,stroke-width] duration-80", tone)
2467
2351
  }), badge !== void 0 ? /* @__PURE__ */ jsx("span", {
2468
- className: cn("text-[11px] tabular-nums transition-colors duration-80", tone),
2352
+ className: cn("text-[0.6875rem] tabular-nums transition-colors duration-80", tone),
2469
2353
  children: badge
2470
2354
  }) : null]
2471
2355
  }) : null,
@@ -2526,7 +2410,7 @@ function ChromePillButton({ active = false, ariaLabel, className, title, ...prop
2526
2410
  title: title ?? ariaLabel
2527
2411
  });
2528
2412
  }
2529
- var COMPACT_TABS_CLASS = "[&_[data-proximity-index]]:!h-7 [&_[data-proximity-index]]:!px-2 [&_[data-proximity-index]]:!text-[11px]";
2413
+ var COMPACT_TABS_CLASS = "[&_[data-proximity-index]]:!h-7 [&_[data-proximity-index]]:!px-2 [&_[data-proximity-index]]:!text-[0.6875rem]";
2530
2414
  function RightPanelLauncherFromContext({ compact = false } = {}) {
2531
2415
  const { reopenRightPanel, rightPanel } = useChatPanelDataContext();
2532
2416
  return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("div", {
@@ -2686,8 +2570,13 @@ function MobilePanel({ children, dataTestid, headerActions, icon: Icon, onClose,
2686
2570
  const panelTitleId = useId();
2687
2571
  const suppressCloseRef = useRef2(false);
2688
2572
  const onLightDismiss = useEffectEvent((event) => {
2689
- if (panelRef.current && event.target === panelRef.current) onClose?.();
2573
+ if (panelRef.current && event.target === panelRef.current) panelRef.current.close();
2690
2574
  });
2575
+ const handleHeaderClose = () => {
2576
+ const dialog = panelRef.current;
2577
+ if (dialog && dialog.open) dialog.close();
2578
+ else onClose?.();
2579
+ };
2691
2580
  useEffect2(() => {
2692
2581
  if (!open) return;
2693
2582
  const dialog = panelRef.current;
@@ -2749,7 +2638,7 @@ function MobilePanel({ children, dataTestid, headerActions, icon: Icon, onClose,
2749
2638
  title && /* @__PURE__ */ jsxs("div", {
2750
2639
  className: "flex h-10 shrink-0 items-center justify-between gap-2 border-b border-border/60 px-3",
2751
2640
  children: [/* @__PURE__ */ jsxs("div", {
2752
- className: "flex min-w-0 items-center gap-2 text-[13px] font-medium text-foreground/80",
2641
+ className: "flex min-w-0 items-center gap-2 text-[0.8125rem] font-medium text-foreground/80",
2753
2642
  children: [Icon && /* @__PURE__ */ jsx(Icon, { className: "size-3.5 shrink-0" }), /* @__PURE__ */ jsx("span", {
2754
2643
  className: "truncate",
2755
2644
  children: title
@@ -2758,7 +2647,7 @@ function MobilePanel({ children, dataTestid, headerActions, icon: Icon, onClose,
2758
2647
  className: "flex shrink-0 items-center gap-1",
2759
2648
  children: [headerActions, onClose && /* @__PURE__ */ jsx(Button, {
2760
2649
  type: "button",
2761
- onClick: onClose,
2650
+ onClick: handleHeaderClose,
2762
2651
  variant: "ghost",
2763
2652
  size: "icon-sm",
2764
2653
  className: `relative after:absolute after:top-1/2 after:left-1/2 after:size-10 after:-translate-x-1/2 after:-translate-y-1/2 text-foreground/40 hover:text-foreground/70`,
@@ -2779,23 +2668,33 @@ function MobilePanel({ children, dataTestid, headerActions, icon: Icon, onClose,
2779
2668
  })
2780
2669
  });
2781
2670
  }
2671
+ var DESKTOP_PANEL_QUERY = `(min-width: 960px)`;
2672
+ function subscribeToDesktopPanel(onChange) {
2673
+ if (typeof window === "undefined" || typeof window.matchMedia !== "function") return () => void 0;
2674
+ const media = window.matchMedia(DESKTOP_PANEL_QUERY);
2675
+ media.addEventListener("change", onChange);
2676
+ return () => media.removeEventListener("change", onChange);
2677
+ }
2678
+ function getDesktopPanelSnapshot() {
2679
+ return typeof window !== "undefined" && typeof window.matchMedia === "function" ? window.matchMedia(DESKTOP_PANEL_QUERY).matches : false;
2680
+ }
2681
+ function getServerDesktopPanelSnapshot() {
2682
+ return false;
2683
+ }
2684
+ function useIsDesktopPanel() {
2685
+ return useSyncExternalStore(subscribeToDesktopPanel, getDesktopPanelSnapshot, getServerDesktopPanelSnapshot);
2686
+ }
2782
2687
  function RightPanelShell({ handleResourceCanvasResizeStart, onClose, resourceCanvasWidth }) {
2783
2688
  const chat = useChatPanelDataContext();
2784
2689
  const workspace = useWorkspaceTreeContext();
2785
2690
  const { rightPanel } = chat;
2786
2691
  const panelOpen = rightPanel !== null;
2692
+ const isDesktop = useIsDesktopPanel();
2787
2693
  const definition = rightPanel ? getRightPanelDefinition(rightPanel) : null;
2788
2694
  const PanelContent = definition?.component;
2789
2695
  const loading = definition?.loadingSource === "resources" ? chat.resourcesLoading : definition?.loadingSource === "workspace" ? workspace.workspaceLoading : false;
2790
2696
  const onRefresh = definition?.refreshSource === "resources" ? chat.refreshResources : definition?.refreshSource === "workspace" ? workspace.refreshWorkspace : void 0;
2791
- return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(MobilePanel, {
2792
- dataTestid: definition?.mobileDataTestid,
2793
- icon: definition?.icon,
2794
- onClose,
2795
- open: panelOpen,
2796
- title: definition?.title ?? "",
2797
- children: PanelContent ? /* @__PURE__ */ jsx(PanelContent, {}) : null
2798
- }), /* @__PURE__ */ jsx(ResizableCanvas, {
2697
+ return /* @__PURE__ */ jsx(Fragment$1, { children: isDesktop ? /* @__PURE__ */ jsx(ResizableCanvas, {
2799
2698
  dataTestid: definition?.dataTestid,
2800
2699
  headerLeading: /* @__PURE__ */ jsx(RightPanelTabsFromContext, { idPrefix: "right-panel-desktop" }),
2801
2700
  loading,
@@ -2807,7 +2706,14 @@ function RightPanelShell({ handleResourceCanvasResizeStart, onClose, resourceCan
2807
2706
  titleIcon: definition?.icon ?? Library,
2808
2707
  width: resourceCanvasWidth,
2809
2708
  children: PanelContent ? /* @__PURE__ */ jsx(PanelContent, {}) : null
2810
- })] });
2709
+ }) : /* @__PURE__ */ jsx(MobilePanel, {
2710
+ dataTestid: definition?.mobileDataTestid,
2711
+ icon: definition?.icon,
2712
+ onClose,
2713
+ open: panelOpen,
2714
+ title: definition?.title ?? "",
2715
+ children: PanelContent ? /* @__PURE__ */ jsx(PanelContent, {}) : null
2716
+ }) });
2811
2717
  }
2812
2718
  var layoutStyle = {
2813
2719
  "--chat-chrome-top": `52px`,
@@ -2823,7 +2729,7 @@ function ChatWorkspaceLayout({ children, headerCenter, headerLeft, headerRight,
2823
2729
  className: "relative flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden",
2824
2730
  "data-testid": "chat-column",
2825
2731
  children: [/* @__PURE__ */ jsxs("header", {
2826
- className: cn(CHAT_HEADER_LAYER_CLASS, "grid h-[var(--chat-header-height)] min-h-[var(--chat-header-height)] shrink-0 grid-cols-[auto_minmax(0,1fr)_auto] items-center gap-1 border-b border-[#2e3033] px-2 py-2"),
2732
+ className: cn(CHAT_HEADER_LAYER_CLASS, "grid h-[var(--chat-header-height)] min-h-[var(--chat-header-height)] shrink-0 grid-cols-[auto_minmax(0,1fr)_auto] items-center gap-1 border-b border-border/70 px-2 py-2"),
2827
2733
  "data-testid": "chat-header",
2828
2734
  children: [
2829
2735
  /* @__PURE__ */ jsx("div", {
@@ -3277,7 +3183,7 @@ var AnimatedSidebarGroupLabel = forwardRef2(function AnimatedSidebarGroupLabel2(
3277
3183
  ref: forwardedRef,
3278
3184
  "aria-hidden": collapsed,
3279
3185
  "data-slot": "sidebar-group-label",
3280
- className: cn("mb-1 h-7 overflow-hidden px-2 text-[10px] font-medium uppercase tracking-[0.14em] text-muted-foreground transition-opacity", collapsed ? "opacity-0" : "opacity-100", className),
3186
+ className: cn("mb-1 h-7 overflow-hidden px-2 text-[0.625rem] font-medium uppercase tracking-[0.14em] text-muted-foreground transition-opacity", collapsed ? "opacity-0" : "opacity-100", className),
3281
3187
  children
3282
3188
  });
3283
3189
  });
@@ -3370,8 +3276,19 @@ function newSessionResourceId(projectId) {
3370
3276
  function idValue(id, prefix) {
3371
3277
  return id.startsWith(prefix) ? id.slice(prefix.length) : null;
3372
3278
  }
3373
- function sessionLabel(session) {
3374
- return normalizeSessionLabel(session.title || session.firstMessage || session.sessionId.slice(0, 8));
3279
+ function sessionBaseLabel(session) {
3280
+ return normalizeSessionLabel(sessionListTitle({
3281
+ sessionId: session.sessionId,
3282
+ title: session.title,
3283
+ firstMessage: session.firstMessage
3284
+ })) || fallbackSessionLabel(session.sessionId);
3285
+ }
3286
+ function sessionLabel(session, siblings) {
3287
+ const base = sessionBaseLabel(session);
3288
+ if (!siblings) return base;
3289
+ let collidingCount = 0;
3290
+ for (const sibling of siblings) if (sessionBaseLabel(sibling) === base) collidingCount += 1;
3291
+ return disambiguateSessionLabel(base, session.sessionId, collidingCount);
3375
3292
  }
3376
3293
  function sessionDiscoveryMeta(session, projectById) {
3377
3294
  return `${session.projectId ? projectById.get(session.projectId)?.name ?? "Unassigned" : "Unassigned"} \xB7 ${session.status === "idle" ? "Ready" : session.status} \xB7 ${`${String(session.messageCount)} ${session.messageCount === 1 ? "message" : "messages"}`}`;
@@ -3393,8 +3310,7 @@ function directoryErrorMessage(error, fallback) {
3393
3310
  return error instanceof Error && error.message.trim() ? error.message : fallback;
3394
3311
  }
3395
3312
  function readExpandedProjects(activeProjectId) {
3396
- if (typeof window === "undefined") return activeProjectId ? [projectResourceId(activeProjectId)] : [];
3397
- const stored = window.localStorage.getItem(EXPANDED_PROJECTS_STORAGE_KEY);
3313
+ const stored = readStoredValue(EXPANDED_PROJECTS_STORAGE_KEY);
3398
3314
  if (!stored) return activeProjectId ? [projectResourceId(activeProjectId)] : [];
3399
3315
  try {
3400
3316
  const parsed = JSON.parse(stored);
@@ -3602,15 +3518,16 @@ function useFleetSessionSidebarViewModel({ sessions, projects = EMPTY_PROJECTS,
3602
3518
  setExpandedProjectIds((current) => current.includes(resourceId) ? current : [...current, resourceId]);
3603
3519
  }, [activeProjectId, setExpandedProjectIds]);
3604
3520
  useEffect2(() => {
3605
- window.localStorage.setItem(EXPANDED_PROJECTS_STORAGE_KEY, JSON.stringify(expandedProjectIds));
3521
+ writeStoredValue(EXPANDED_PROJECTS_STORAGE_KEY, JSON.stringify(expandedProjectIds));
3606
3522
  }, [expandedProjectIds]);
3607
3523
  const sidebarItems = useMemo2(() => {
3608
3524
  const grouped = sortedProjects.map((project) => {
3609
3525
  const sessionsForProject = displayProjectSessions(projectSessions.filter((session) => session.projectId === project.projectId), activeSessionId);
3610
3526
  const revealed = revealedProjectIds.has(project.projectId);
3611
- const children = visibleProjectSessions(sessionsForProject, activeSessionId, revealed).map((session) => ({
3527
+ const visible = visibleProjectSessions(sessionsForProject, activeSessionId, revealed);
3528
+ const children = visible.map((session) => ({
3612
3529
  id: sessionResourceId(session.sessionId),
3613
- label: sessionLabel(session),
3530
+ label: sessionLabel(session, visible),
3614
3531
  kind: "file",
3615
3532
  ...session.isSubagent ? { indent: 1 } : {}
3616
3533
  }));
@@ -3635,7 +3552,7 @@ function useFleetSessionSidebarViewModel({ sessions, projects = EMPTY_PROJECTS,
3635
3552
  if (unassigned.length > 0) {
3636
3553
  const unassignedChildren = visibleProjectSessions(unassigned, activeSessionId, revealedProjectIds.has("unassigned")).map((session) => ({
3637
3554
  id: sessionResourceId(session.sessionId),
3638
- label: sessionLabel(session),
3555
+ label: sessionLabel(session, unassigned),
3639
3556
  kind: "file",
3640
3557
  ...session.isSubagent ? { indent: 1 } : {}
3641
3558
  }));
@@ -4458,7 +4375,7 @@ function ThreadSearch({ threads, query, activeId, onQueryChange, onSelect, class
4458
4375
  children: [/* @__PURE__ */ jsxs("span", {
4459
4376
  className: "flex items-center gap-1.5",
4460
4377
  children: [thread.pinned && /* @__PURE__ */ jsx(Pin, { className: "text-foreground/30 size-2.5 shrink-0" }), /* @__PURE__ */ jsx("span", {
4461
- className: "min-w-0 flex-1 truncate text-[13px]",
4378
+ className: "min-w-0 flex-1 truncate text-[0.8125rem]",
4462
4379
  children: thread.title
4463
4380
  })]
4464
4381
  }), /* @__PURE__ */ jsx("span", {
@@ -4482,13 +4399,13 @@ function ThreadSearch({ threads, query, activeId, onQueryChange, onSelect, class
4482
4399
  onKeyDown,
4483
4400
  placeholder: "Search threads",
4484
4401
  "aria-label": "Search threads",
4485
- className: "text-foreground/85 placeholder:text-foreground/30 min-w-0 flex-1 bg-transparent text-base outline-none md:text-[13px]"
4402
+ className: "text-foreground/85 placeholder:text-foreground/30 min-w-0 flex-1 bg-transparent text-base outline-none md:text-[0.8125rem]"
4486
4403
  })]
4487
4404
  }),
4488
4405
  pinned.length > 0 && /* @__PURE__ */ jsxs("div", {
4489
4406
  className: "flex flex-col",
4490
4407
  children: [/* @__PURE__ */ jsx("span", {
4491
- className: cn("font-mono text-[11px] tracking-tight", "text-foreground/25 px-2 pb-1"),
4408
+ className: cn("font-mono text-[0.6875rem] tracking-tight", "text-foreground/25 px-2 pb-1"),
4492
4409
  children: "pinned"
4493
4410
  }), pinned.map(row)]
4494
4411
  }),
@@ -4512,7 +4429,7 @@ function ThreadSearch({ threads, query, activeId, onQueryChange, onSelect, class
4512
4429
  }
4513
4430
  function fleetVersion() {
4514
4431
  try {
4515
- return "0.5.10";
4432
+ return "0.6.0";
4516
4433
  } catch {
4517
4434
  return "dev";
4518
4435
  }
@@ -4523,7 +4440,7 @@ function FleetVersionBadge() {
4523
4440
  variant: "secondary",
4524
4441
  title: `Fleet ${version}`,
4525
4442
  "aria-label": `Fleet version ${version}`,
4526
- className: "shrink-0 font-mono text-[10px] font-normal text-muted-foreground",
4443
+ className: "shrink-0 font-mono text-[0.625rem] font-normal text-muted-foreground",
4527
4444
  children: ["v", version]
4528
4445
  });
4529
4446
  }
@@ -4751,7 +4668,7 @@ function ResourceActionMenu({ item, menuOpen, onMenuOpenChange, onRenameStart, r
4751
4668
  });
4752
4669
  }
4753
4670
  function getResourceRowClassName(acceptsChildren, active, containerActive, kind, disabled2) {
4754
- return cn("group/resource relative flex min-h-8 min-w-0 cursor-pointer items-center gap-2 rounded-lg pr-2 text-[13px] outline-none", "text-muted-foreground transition-colors hover:bg-muted hover:text-foreground", "focus-visible:bg-muted/70 focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-inset", "data-[menu-open=true]:bg-muted data-[menu-open=true]:text-foreground", "data-[dragging=true]:opacity-40", "data-[drop=inside]:bg-primary/10 data-[drop=inside]:ring-1 data-[drop=inside]:ring-primary/45", "data-[drop=before]:before:absolute data-[drop=before]:before:-top-0.5 data-[drop=before]:before:right-2 data-[drop=before]:before:left-2 data-[drop=before]:before:h-0.5 data-[drop=before]:before:rounded-full data-[drop=before]:before:bg-primary", "data-[drop=after]:after:absolute data-[drop=after]:after:-bottom-0.5 data-[drop=after]:after:right-2 data-[drop=after]:after:left-2 data-[drop=after]:after:h-0.5 data-[drop=after]:after:rounded-full data-[drop=after]:after:bg-primary", !acceptsChildren && active && "bg-muted text-foreground", acceptsChildren && containerActive && "bg-muted/55 text-foreground ring-1 ring-border/70", kind === "action" && "text-xs text-muted-foreground", disabled2 && "cursor-not-allowed opacity-45");
4671
+ return cn("group/resource relative flex min-h-8 min-w-0 cursor-pointer items-center gap-2 rounded-lg pr-2 text-[0.8125rem] outline-none", "text-muted-foreground transition-colors hover:bg-muted hover:text-foreground", "focus-visible:bg-muted/70 focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-inset", "data-[menu-open=true]:bg-muted data-[menu-open=true]:text-foreground", "data-[dragging=true]:opacity-40", "data-[drop=inside]:bg-primary/10 data-[drop=inside]:ring-1 data-[drop=inside]:ring-primary/45", "data-[drop=before]:before:absolute data-[drop=before]:before:-top-0.5 data-[drop=before]:before:right-2 data-[drop=before]:before:left-2 data-[drop=before]:before:h-0.5 data-[drop=before]:before:rounded-full data-[drop=before]:before:bg-primary", "data-[drop=after]:after:absolute data-[drop=after]:after:-bottom-0.5 data-[drop=after]:after:right-2 data-[drop=after]:after:left-2 data-[drop=after]:after:h-0.5 data-[drop=after]:after:rounded-full data-[drop=after]:after:bg-primary", !acceptsChildren && active && "bg-muted text-foreground", acceptsChildren && containerActive && "bg-muted/55 text-foreground ring-1 ring-border/70", kind === "action" && "text-xs text-muted-foreground", disabled2 && "cursor-not-allowed opacity-45");
4755
4672
  }
4756
4673
  function useResourceRowEvents({ acceptsChildren, allowMove, disabled: disabled2, kind, onContainerSelect, onDragEnd, onDragOver, onDragStart, onDrop, onRenameStart, onSelect, renaming, row }) {
4757
4674
  const draggedRef = useRef2(false);
@@ -4934,7 +4851,7 @@ function ResourceList({ flat, selectedId, activeContainerId, expandedIds, focuse
4934
4851
  }), draggingId ? /* @__PURE__ */ jsx("div", {
4935
4852
  "aria-hidden": "true",
4936
4853
  "data-active": dropTarget?.id === null || void 0,
4937
- className: "absolute inset-x-1 bottom-0 flex h-8 items-center justify-center rounded-lg border border-dashed border-border text-[10px] text-muted-foreground data-[active=true]:border-primary/50 data-[active=true]:bg-primary/10 data-[active=true]:text-foreground",
4854
+ className: "absolute inset-x-1 bottom-0 flex h-8 items-center justify-center rounded-lg border border-dashed border-border text-[0.625rem] text-muted-foreground data-[active=true]:border-primary/50 data-[active=true]:bg-primary/10 data-[active=true]:text-foreground",
4938
4855
  children: "Move to top level"
4939
4856
  }) : null]
4940
4857
  }), /* @__PURE__ */ jsx("span", {
@@ -5507,7 +5424,7 @@ function ProjectFolder({ title, description = "Updated recently", previews = [],
5507
5424
  "aria-hidden": "true",
5508
5425
  className: "pointer-events-none absolute inset-0",
5509
5426
  children: /* @__PURE__ */ jsx("span", {
5510
- className: "absolute left-1/2 top-0 block h-0 w-0",
5427
+ className: "absolute left-1/2 top-0 block size-0",
5511
5428
  children: /* @__PURE__ */ jsx(AnimatePresence, {
5512
5429
  initial: false,
5513
5430
  children: !isExpanded ? previewItems.map((preview, index) => {
@@ -5718,14 +5635,14 @@ function SidebarMenuItem({ icon: Icon, label, onClick, href }) {
5718
5635
  }
5719
5636
  function KbdHint({ children }) {
5720
5637
  return /* @__PURE__ */ jsx("kbd", {
5721
- className: "rounded border border-border/60 bg-muted/60 px-1 font-mono text-[10px] leading-4 text-muted-foreground",
5638
+ className: "rounded border border-border/60 bg-muted/60 px-1 font-mono text-[0.625rem] leading-4 text-muted-foreground",
5722
5639
  children
5723
5640
  });
5724
5641
  }
5725
5642
  function FleetSessionSidebarNavigation({ brandMenuOpen, setBrandMenuOpen, searchOpen, setSearchOpen, query, setQuery, projectActionsOpen, setProjectActionsOpen, expandedProjectIds, setExpandedProjectIds, setCreateOpen, projects, projectSessions, sidebarItems, sortedProjects, projectById, activeProjectId, activeSessionId, onNewSession, onNewSessionInProject, onProjectSelect, onRenameSession, onCreateProject, onOpenSettings, accountMenu, resumeResource, toggleProjectResource, selectSearchResult, renderMenu }) {
5726
5643
  const searchThreads = useMemo2(() => sortSessions(projectSessions).map((session) => ({
5727
5644
  id: session.sessionId,
5728
- title: sessionLabel(session),
5645
+ title: sessionLabel(session, projectSessions),
5729
5646
  preview: sessionDiscoveryMeta(session, projectById),
5730
5647
  group: sessionSearchGroup(session.updatedAt),
5731
5648
  keywords: session.firstMessage ? [normalizeSessionLabel(session.firstMessage)] : []
@@ -5816,7 +5733,7 @@ function FleetSessionSidebarNavigation({ brandMenuOpen, setBrandMenuOpen, search
5816
5733
  /* @__PURE__ */ jsxs("div", {
5817
5734
  className: "border-t border-border/60 px-2 pb-2 pt-1.5",
5818
5735
  children: [/* @__PURE__ */ jsx("span", {
5819
- className: "px-2 pb-1 font-mono text-[10px] uppercase tracking-[0.14em] text-muted-foreground/60",
5736
+ className: "px-2 pb-1 font-mono text-[0.625rem] uppercase tracking-[0.14em] text-muted-foreground/60",
5820
5737
  children: "Projects"
5821
5738
  }), /* @__PURE__ */ jsxs("div", {
5822
5739
  className: "mt-1 flex flex-col gap-0.5",
@@ -5831,12 +5748,12 @@ function FleetSessionSidebarNavigation({ brandMenuOpen, setBrandMenuOpen, search
5831
5748
  children: project.name
5832
5749
  }),
5833
5750
  /* @__PURE__ */ jsx("span", {
5834
- className: "max-w-24 truncate text-[10px] text-muted-foreground/55",
5751
+ className: "max-w-24 truncate text-[0.625rem] text-muted-foreground/55",
5835
5752
  children: project.pathLabel
5836
5753
  })
5837
5754
  ]
5838
5755
  }, project.projectId)), matchingProjects.length === 0 ? /* @__PURE__ */ jsxs("span", {
5839
- className: "px-2 py-2 text-center text-[11px] text-muted-foreground/60",
5756
+ className: "p-2 text-center text-[0.6875rem] text-muted-foreground/60",
5840
5757
  children: [
5841
5758
  "No project matches \u201C",
5842
5759
  query,
@@ -5846,7 +5763,7 @@ function FleetSessionSidebarNavigation({ brandMenuOpen, setBrandMenuOpen, search
5846
5763
  })]
5847
5764
  }),
5848
5765
  /* @__PURE__ */ jsxs("div", {
5849
- className: "flex items-center justify-end gap-3 border-t border-border/60 px-3 py-2 text-[10px] text-muted-foreground/70",
5766
+ className: "flex items-center justify-end gap-3 border-t border-border/60 px-3 py-2 text-[0.625rem] text-muted-foreground/70",
5850
5767
  children: [
5851
5768
  /* @__PURE__ */ jsxs("span", {
5852
5769
  className: "flex items-center gap-1",
@@ -5872,7 +5789,7 @@ function FleetSessionSidebarNavigation({ brandMenuOpen, setBrandMenuOpen, search
5872
5789
  }), /* @__PURE__ */ jsxs("button", {
5873
5790
  type: "button",
5874
5791
  onClick: onNewSession,
5875
- className: "flex h-8 w-full items-center justify-start gap-2 rounded-lg px-2 text-[13px] font-normal text-sidebar-foreground outline-none transition-colors hover:bg-sidebar-accent focus-visible:bg-sidebar-accent focus-visible:ring-2 focus-visible:ring-sidebar-ring",
5792
+ className: "flex h-8 w-full items-center justify-start gap-2 rounded-lg px-2 text-[0.8125rem] font-normal text-sidebar-foreground outline-none transition-colors hover:bg-sidebar-accent focus-visible:bg-sidebar-accent focus-visible:ring-2 focus-visible:ring-sidebar-ring",
5876
5793
  children: [/* @__PURE__ */ jsx(SquarePen, { className: "size-4 shrink-0 text-muted-foreground" }), "New chat"]
5877
5794
  })]
5878
5795
  }),
@@ -5902,7 +5819,7 @@ function FleetSessionSidebarNavigation({ brandMenuOpen, setBrandMenuOpen, search
5902
5819
  /* @__PURE__ */ jsx("div", {
5903
5820
  className: "min-w-0 flex-1",
5904
5821
  children: accountMenu ?? /* @__PURE__ */ jsx("span", {
5905
- className: "flex h-8 items-center px-2 text-[13px]",
5822
+ className: "flex h-8 items-center px-2 text-[0.8125rem]",
5906
5823
  children: "Qredence"
5907
5824
  })
5908
5825
  }),
@@ -6571,12 +6488,12 @@ function FleetSessionSidebarCreateDialog({ createOpen, setCreateOpen, directoryB
6571
6488
  })]
6572
6489
  }),
6573
6490
  /* @__PURE__ */ jsx("span", {
6574
- className: "shrink-0 rounded-full bg-primary/10 px-2 py-1 text-[11px] font-medium text-primary",
6491
+ className: "shrink-0 rounded-full bg-primary/10 px-2 py-1 text-[0.6875rem] font-medium text-primary",
6575
6492
  children: "Selected"
6576
6493
  })
6577
6494
  ]
6578
6495
  }), /* @__PURE__ */ jsxs("div", {
6579
- className: "space-y-2 border-t px-3 py-3",
6496
+ className: "space-y-2 border-t p-3",
6580
6497
  children: [/* @__PURE__ */ jsxs("div", {
6581
6498
  className: "flex items-center justify-between gap-2",
6582
6499
  children: [/* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("p", {
@@ -6632,7 +6549,7 @@ function FleetSessionSidebarCreateDialog({ createOpen, setCreateOpen, directoryB
6632
6549
  className: "block truncate font-medium text-foreground",
6633
6550
  children: pathEntryLabel(entry)
6634
6551
  }), /* @__PURE__ */ jsx("span", {
6635
- className: "block truncate text-[11px] text-muted-foreground",
6552
+ className: "block truncate text-[0.6875rem] text-muted-foreground",
6636
6553
  title: entry.pathLabel,
6637
6554
  children: entry.pathLabel
6638
6555
  })]
@@ -7814,7 +7731,7 @@ function ApprovalCard({ title = "Approval required", description, children, ques
7814
7731
  questions.length
7815
7732
  ]
7816
7733
  }) : /* @__PURE__ */ jsx("span", {
7817
- className: cn("shrink-0 rounded-full border px-2 py-0.5 text-[11px] font-medium transition-colors", getStatusBadgeClass(status)),
7734
+ className: cn("shrink-0 rounded-full border px-2 py-0.5 text-[0.6875rem] font-medium transition-colors", getStatusBadgeClass(status)),
7818
7735
  children: statusLabel2
7819
7736
  }),
7820
7737
  onDismiss ? /* @__PURE__ */ jsx("button", {
@@ -7980,7 +7897,7 @@ function InputQuestionBar({ questionBar, navigation, roundedTop, onDismiss }) {
7980
7897
  className: "flex h-7 items-center justify-between border-b border-border px-3 text-xs text-an-tool-color-muted",
7981
7898
  children: [/* @__PURE__ */ jsxs("div", {
7982
7899
  className: "inline-flex items-center gap-1.5",
7983
- children: [/* @__PURE__ */ jsx(MessageCircleQuestionMark, { className: "h-3.5 w-3.5" }), "Question"]
7900
+ children: [/* @__PURE__ */ jsx(MessageCircleQuestionMark, { className: "size-3.5" }), "Question"]
7984
7901
  }), showQuestionNavigation && /* @__PURE__ */ jsxs("div", {
7985
7902
  className: "inline-flex items-center gap-1",
7986
7903
  children: [
@@ -7990,7 +7907,7 @@ function InputQuestionBar({ questionBar, navigation, roundedTop, onDismiss }) {
7990
7907
  disabled: !canGoPrev,
7991
7908
  className: "relative inline-flex size-5 items-center justify-center rounded-[4px] transition-[background-color,transform] duration-150 after:absolute after:inset-x-0 after:-top-2.5 after:-bottom-2.5 hover:bg-an-background-secondary active:scale-[0.96] disabled:opacity-40 disabled:active:scale-100",
7992
7909
  "aria-label": "Previous question",
7993
- children: /* @__PURE__ */ jsx(ChevronUp, { className: "h-3.5 w-3.5" })
7910
+ children: /* @__PURE__ */ jsx(ChevronUp, { className: "size-3.5" })
7994
7911
  }),
7995
7912
  /* @__PURE__ */ jsxs("span", {
7996
7913
  className: "tabular-nums",
@@ -8006,7 +7923,7 @@ function InputQuestionBar({ questionBar, navigation, roundedTop, onDismiss }) {
8006
7923
  disabled: !canGoNext,
8007
7924
  className: "relative inline-flex size-5 items-center justify-center rounded-[4px] transition-[background-color,transform] duration-150 after:absolute after:inset-x-0 after:-top-2.5 after:-bottom-2.5 hover:bg-an-background-secondary active:scale-[0.96] disabled:opacity-40 disabled:active:scale-100",
8008
7925
  "aria-label": "Next question",
8009
- children: /* @__PURE__ */ jsx(ChevronDown, { className: "h-3.5 w-3.5" })
7926
+ children: /* @__PURE__ */ jsx(ChevronDown, { className: "size-3.5" })
8010
7927
  })
8011
7928
  ]
8012
7929
  })]
@@ -8047,7 +7964,7 @@ var ModeSelector = memo(function ModeSelector2({ modes, value, defaultValue, onC
8047
7964
  const hasMultiple = modes.length > 1;
8048
7965
  const trigger = /* @__PURE__ */ jsxs("button", {
8049
7966
  type: "button",
8050
- className: cn("relative inline-flex h-7 cursor-pointer items-center gap-1.5 rounded-full px-2 text-[12px] leading-4 text-foreground/40 transition-[background-color,transform] duration-150 after:absolute after:inset-x-0 after:-top-1.5 after:-bottom-1.5 hover:bg-foreground/6 active:scale-[0.96]", !hasMultiple && "pointer-events-none", className),
7967
+ className: cn("relative inline-flex h-7 cursor-pointer items-center gap-1.5 rounded-full px-2 text-[0.75rem] leading-4 text-foreground/40 transition-[background-color,transform] duration-150 after:absolute after:inset-x-0 after:-top-1.5 after:-bottom-1.5 hover:bg-foreground/6 active:scale-[0.96]", !hasMultiple && "pointer-events-none", className),
8051
7968
  "aria-label": "Select mode",
8052
7969
  children: [
8053
7970
  ActiveIcon && /* @__PURE__ */ jsx(ActiveIcon, { className: "size-3.5 shrink-0" }),
@@ -8071,7 +7988,7 @@ var ModeSelector = memo(function ModeSelector2({ modes, value, defaultValue, onC
8071
7988
  return /* @__PURE__ */ jsxs("button", {
8072
7989
  type: "button",
8073
7990
  onClick: () => handleSelect(mode.id),
8074
- className: cn("flex w-full cursor-pointer items-start gap-2 rounded-[6px] px-2 py-2 text-left text-[12px] leading-4 text-foreground transition-[background-color,transform] duration-150 hover:bg-foreground/6 active:scale-[0.96]", isActive && "bg-foreground/6"),
7991
+ className: cn("flex w-full cursor-pointer items-start gap-2 rounded-[6px] px-2 py-2 text-left text-[0.75rem] leading-4 text-foreground transition-[background-color,transform] duration-150 hover:bg-foreground/6 active:scale-[0.96]", isActive && "bg-foreground/6"),
8075
7992
  children: [
8076
7993
  Icon && /* @__PURE__ */ jsx(Icon, { className: "mt-0.5 size-3.5 shrink-0" }),
8077
7994
  /* @__PURE__ */ jsxs("span", {
@@ -8127,7 +8044,7 @@ function ComposerMenuItem({ active = false, className, ...props }) {
8127
8044
  type: "button",
8128
8045
  "data-slot": "composer-menu-item",
8129
8046
  "data-active": active || void 0,
8130
- className: cn("flex w-full items-center gap-2.5 rounded-[10px] px-2.5 py-2 text-[13.5px] transition-colors", active ? field : "hover:bg-foreground/[0.04]", className),
8047
+ className: cn("flex w-full items-center gap-2.5 rounded-[10px] px-2.5 py-2 text-[0.84375rem] transition-colors", active ? field : "hover:bg-foreground/[0.04]", className),
8131
8048
  ...props
8132
8049
  });
8133
8050
  }
@@ -8224,7 +8141,7 @@ var ComposerTriggerPopover = memo(function ComposerTriggerPopover2({ open, kind,
8224
8141
  children: title ?? (kind === "slash" ? "Commands" : "Workspace")
8225
8142
  }),
8226
8143
  query ? /* @__PURE__ */ jsx("span", {
8227
- className: "ml-auto max-w-[50%] truncate font-mono text-[11px]",
8144
+ className: "ml-auto max-w-[50%] truncate font-mono text-[0.6875rem]",
8228
8145
  children: query
8229
8146
  }) : null,
8230
8147
  onClose ? /* @__PURE__ */ jsx("button", {
@@ -8250,7 +8167,7 @@ var ComposerTriggerPopover = memo(function ComposerTriggerPopover2({ open, kind,
8250
8167
  role: "group",
8251
8168
  "aria-label": group.label,
8252
8169
  children: [/* @__PURE__ */ jsx("div", {
8253
- className: "px-3 pb-1 pt-2 text-[10px] font-medium uppercase tracking-wide text-muted-foreground",
8170
+ className: "px-3 pb-1 pt-2 text-[0.625rem] font-medium uppercase tracking-wide text-muted-foreground",
8254
8171
  children: group.label
8255
8172
  }), group.items.map((item, index) => renderItem(item, offset + index))]
8256
8173
  }, group.id);
@@ -8258,7 +8175,7 @@ var ComposerTriggerPopover = memo(function ComposerTriggerPopover2({ open, kind,
8258
8175
  })]
8259
8176
  }) : null;
8260
8177
  });
8261
- var LazyModelSelectorList = lazy(() => import("./model-selector-list-cb2-ewoA-KIVU6LD3.js").then(({ ModelSelectorList: ModelSelectorList2 }) => ({ default: ModelSelectorList2 })));
8178
+ var LazyModelSelectorList = lazy(() => import("./model-selector-list-jBTZc2Mu-OXJOS5NA.js").then(({ ModelSelectorList: ModelSelectorList2 }) => ({ default: ModelSelectorList2 })));
8262
8179
  function ModelSelectorList(props) {
8263
8180
  return /* @__PURE__ */ jsx(Suspense, {
8264
8181
  fallback: /* @__PURE__ */ jsx("div", {
@@ -8378,6 +8295,8 @@ function slashCommandName(item) {
8378
8295
  return (item.value ?? item.id).trim().replace(/^\/+/, "").split(/\s+/, 1)[0] ?? item.id;
8379
8296
  }
8380
8297
  function slashArgumentHint(item) {
8298
+ const fromMetadata = item.metadata?.argumentHint?.trim();
8299
+ if (fromMetadata) return fromMetadata;
8381
8300
  return (item.value?.trim() ?? "").match(/^\/\S+\s+(.+)$/)?.[1];
8382
8301
  }
8383
8302
  function useFleetPiInputBarState({ models, status, thinkingLevel, onModelChange, onThinkingLevelChange, onSend, onSlashCommandSelect, onLocalSlashSubmit, modelPickerOpen, onModelPickerOpenChange, effortPickerOpen, onEffortPickerOpenChange, workspaceReferences = EMPTY_WORKSPACE_REFERENCES$1, workspaceSuggestions, onWorkspaceReferenceSelect, onRemoveWorkspaceReference, controlled, disabled: disabled2, questionBar, attachments, slashCommands }) {
@@ -8806,7 +8725,7 @@ function getChatErrorPresentation(error) {
8806
8725
  message: error.message.replace(/\s+(?:Socket|Daemon log):\s*[^\n]*(?:\s+(?:Socket|Daemon log):\s*[^\n]*)*/gi, "")
8807
8726
  };
8808
8727
  }
8809
- var LazyFleetPiToolRenderer = lazy(() => import("./fleet-pi-tool-renderer-RIeVlM9J-D6MISCQC.js").then((n) => n.n).then(({ FleetPiToolRenderer: FleetPiToolRenderer2 }) => ({ default: FleetPiToolRenderer2 })));
8728
+ var LazyFleetPiToolRenderer = lazy(() => import("./fleet-pi-tool-renderer-umKunT3K-O4GBH35V.js").then((n) => n.n).then(({ FleetPiToolRenderer: FleetPiToolRenderer2 }) => ({ default: FleetPiToolRenderer2 })));
8810
8729
  function FleetPiToolRenderer(props) {
8811
8730
  return /* @__PURE__ */ jsx(Suspense, {
8812
8731
  fallback: /* @__PURE__ */ jsx("div", {
@@ -8816,17 +8735,20 @@ function FleetPiToolRenderer(props) {
8816
8735
  children: /* @__PURE__ */ jsx(LazyFleetPiToolRenderer, { ...props })
8817
8736
  });
8818
8737
  }
8819
- var LazyAgentActivity = lazy(() => import("./agent-activity-B-JMvecd-SLE3GGY2.js").then(({ AgentActivity: AgentActivity2 }) => ({ default: AgentActivity2 })));
8738
+ var LazyAgentActivity = lazy(() => import("./agent-activity-CS2rbF_C-A3R26CYH.js").then(({ AgentActivity: AgentActivity2 }) => ({ default: AgentActivity2 })));
8820
8739
  function AgentActivity(props) {
8821
- return /* @__PURE__ */ jsx(Suspense, {
8822
- fallback: /* @__PURE__ */ jsx("div", {
8823
- className: "mt-2 h-8 animate-pulse rounded-md bg-muted/40",
8824
- "aria-label": "Loading activity"
8825
- }),
8826
- children: /* @__PURE__ */ jsx(LazyAgentActivity, { ...props })
8740
+ return /* @__PURE__ */ jsx("div", {
8741
+ className: "mt-2 min-h-8",
8742
+ children: /* @__PURE__ */ jsx(Suspense, {
8743
+ fallback: /* @__PURE__ */ jsx("div", {
8744
+ className: "h-8 animate-pulse rounded-md bg-muted/40",
8745
+ "aria-label": "Loading activity"
8746
+ }),
8747
+ children: /* @__PURE__ */ jsx(LazyAgentActivity, { ...props })
8748
+ })
8827
8749
  });
8828
8750
  }
8829
- var LazyFleetReasoningPanel = lazy(() => import("./fleet-reasoning-panel-D_K48UOT-GN2PA6KT.js").then(({ FleetReasoningPanel: FleetReasoningPanel2 }) => ({ default: FleetReasoningPanel2 })));
8751
+ var LazyFleetReasoningPanel = lazy(() => import("./fleet-reasoning-panel-BxC2COxi-GPLMQSTT.js").then(({ FleetReasoningPanel: FleetReasoningPanel2 }) => ({ default: FleetReasoningPanel2 })));
8830
8752
  function FleetReasoningPanel(props) {
8831
8753
  return /* @__PURE__ */ jsx(Suspense, {
8832
8754
  fallback: /* @__PURE__ */ jsx("div", {
@@ -8836,7 +8758,7 @@ function FleetReasoningPanel(props) {
8836
8758
  children: /* @__PURE__ */ jsx(LazyFleetReasoningPanel, { ...props })
8837
8759
  });
8838
8760
  }
8839
- var LazyFleetToolTimeline = lazy(() => import("./fleet-tool-timeline-DwRqQgOj-HUFLGMDV.js").then((n) => n.n).then(({ FleetToolTimeline: FleetToolTimeline2 }) => ({ default: FleetToolTimeline2 })));
8761
+ var LazyFleetToolTimeline = lazy(() => import("./fleet-tool-timeline-IB36_PB2-XJENTO6I.js").then((n) => n.n).then(({ FleetToolTimeline: FleetToolTimeline2 }) => ({ default: FleetToolTimeline2 })));
8840
8762
  function FleetToolTimeline(props) {
8841
8763
  return /* @__PURE__ */ jsx(Suspense, {
8842
8764
  fallback: /* @__PURE__ */ jsx("div", {
@@ -8846,7 +8768,7 @@ function FleetToolTimeline(props) {
8846
8768
  children: /* @__PURE__ */ jsx(LazyFleetToolTimeline, { ...props })
8847
8769
  });
8848
8770
  }
8849
- var LazyFleetSubagentList = lazy(() => import("./fleet-subagent-list-5luKtpds-3OTVFHJQ.js").then((n) => n.n).then(({ FleetSubagentList: FleetSubagentList2 }) => ({ default: FleetSubagentList2 })));
8771
+ var LazyFleetSubagentList = lazy(() => import("./fleet-subagent-list-CpSYzCIq-JDH2LHSS.js").then((n) => n.n).then(({ FleetSubagentList: FleetSubagentList2 }) => ({ default: FleetSubagentList2 })));
8850
8772
  function FleetSubagentList(props) {
8851
8773
  return /* @__PURE__ */ jsx(Suspense, {
8852
8774
  fallback: /* @__PURE__ */ jsx("div", {
@@ -8856,17 +8778,20 @@ function FleetSubagentList(props) {
8856
8778
  children: /* @__PURE__ */ jsx(LazyFleetSubagentList, { ...props })
8857
8779
  });
8858
8780
  }
8859
- var LazyPromptSuggestions = lazy(() => import("./prompt-suggestions-BOmHi4-J-C563CHFU.js").then(({ PromptSuggestions: PromptSuggestions2 }) => ({ default: PromptSuggestions2 })));
8781
+ var LazyPromptSuggestions = lazy(() => import("./prompt-suggestions-D4AEEY7K-RZSP7PWV.js").then(({ PromptSuggestions: PromptSuggestions2 }) => ({ default: PromptSuggestions2 })));
8860
8782
  function PromptSuggestions(props) {
8861
- return /* @__PURE__ */ jsx(Suspense, {
8862
- fallback: /* @__PURE__ */ jsx("div", {
8863
- className: "h-8 animate-pulse rounded-full bg-muted/40",
8864
- "aria-label": "Loading suggestions"
8865
- }),
8866
- children: /* @__PURE__ */ jsx(LazyPromptSuggestions, { ...props })
8783
+ return /* @__PURE__ */ jsx("div", {
8784
+ className: "min-h-8",
8785
+ children: /* @__PURE__ */ jsx(Suspense, {
8786
+ fallback: /* @__PURE__ */ jsx("div", {
8787
+ className: "h-8 animate-pulse rounded-full bg-muted/40",
8788
+ "aria-label": "Loading suggestions"
8789
+ }),
8790
+ children: /* @__PURE__ */ jsx(LazyPromptSuggestions, { ...props })
8791
+ })
8867
8792
  });
8868
8793
  }
8869
- var LazyFleetMessageQueue = lazy(() => import("./fleet-message-queue-BxycG26e-2XLOTCLP.js").then(({ FleetMessageQueue: FleetMessageQueue2 }) => ({ default: FleetMessageQueue2 })));
8794
+ var LazyFleetMessageQueue = lazy(() => import("./fleet-message-queue-BS-cZ56r-GLZXUKDF.js").then(({ FleetMessageQueue: FleetMessageQueue2 }) => ({ default: FleetMessageQueue2 })));
8870
8795
  function FleetMessageQueue(props) {
8871
8796
  return /* @__PURE__ */ jsx(Suspense, {
8872
8797
  fallback: null,
@@ -9075,8 +9000,8 @@ function AssistantMessage({ messages, isLast, isStreaming, suppressQuestionTool,
9075
9000
  className: "mt-2 max-w-none"
9076
9001
  }) : null,
9077
9002
  isLast && presentation ? /* @__PURE__ */ jsx(FleetSubagentList, {
9078
- children: presentation.rlmChildren,
9079
- tree: presentation.rlmTree
9003
+ tree: presentation.rlmTree,
9004
+ children: presentation.rlmChildren
9080
9005
  }) : null
9081
9006
  ] })
9082
9007
  }) })
@@ -9139,8 +9064,12 @@ function ChatComposerHost({ inputBar, status, suggestions, onSend, onStop, isEmp
9139
9064
  });
9140
9065
  }
9141
9066
  var MemoChatComposerHost = memo(ChatComposerHost);
9142
- function FleetPiAgentChat({ toolRenderers = PI_TOOL_RENDERERS, suggestions, status, onStop, onSend, inputBar, className, messages, error, suppressQuestionTool = false, onOpenUIAction, activityLabel, presentation, artifactRuns, onOpenArtifact, onOpenUIArtifactReady, queue, onDeleteQueuedMessage }) {
9067
+ function getConversationTurnKey(turn, turnIndex) {
9068
+ return turn.user?.id ?? turn.assistants[0]?.id ?? `assistant-turn-${turnIndex}`;
9069
+ }
9070
+ function FleetPiAgentChat({ toolRenderers = PI_TOOL_RENDERERS, suggestions, status, onStop, onSend, inputBar, className, messages, error, suppressQuestionTool = false, onOpenUIAction, activityLabel, presentation, artifactRuns, onOpenArtifact, onOpenUIArtifactReady, queue, onDeleteQueuedMessage, onEditQueuedMessage }) {
9143
9071
  const draftSetterRef = useRef2(null);
9072
+ const viewportRef = useRef2(null);
9144
9073
  const setDraft = useCallback2((value) => draftSetterRef.current?.(value), []);
9145
9074
  const turns = useMemo2(() => groupMessages(messages), [messages]);
9146
9075
  const suggestionItems2 = resolveSuggestions(suggestions);
@@ -9188,6 +9117,22 @@ function FleetPiAgentChat({ toolRenderers = PI_TOOL_RENDERERS, suggestions, stat
9188
9117
  presentation: void 0,
9189
9118
  artifactRuns: void 0
9190
9119
  }), []);
9120
+ const renderTurn = useCallback2((turn, turnIndex) => {
9121
+ const isLast = turnIndex === turns.length - 1;
9122
+ return /* @__PURE__ */ jsx(ConversationTurnView, {
9123
+ turn,
9124
+ state: isLast ? stateForLast : stateForRest,
9125
+ rendering,
9126
+ activity: isLast ? activityForLast : activityForRest
9127
+ });
9128
+ }, [
9129
+ activityForLast,
9130
+ activityForRest,
9131
+ rendering,
9132
+ stateForLast,
9133
+ stateForRest,
9134
+ turns.length
9135
+ ]);
9191
9136
  const isEmpty = turns.length === 0 && !error;
9192
9137
  const errorPresentation = error ? getChatErrorPresentation(error) : null;
9193
9138
  const composerNode = /* @__PURE__ */ jsx(MemoChatComposerHost, {
@@ -9206,6 +9151,7 @@ function FleetPiAgentChat({ toolRenderers = PI_TOOL_RENDERERS, suggestions, stat
9206
9151
  className: "flex-1",
9207
9152
  busy: isStreaming,
9208
9153
  followOutput: true,
9154
+ viewportRef,
9209
9155
  smooth: !isStreaming,
9210
9156
  contentClassName: cn("mx-auto flex w-full max-w-an flex-col gap-5 px-4", isEmpty ? "min-h-full items-center justify-center py-8" : "py-6"),
9211
9157
  children: [
@@ -9214,15 +9160,13 @@ function FleetPiAgentChat({ toolRenderers = PI_TOOL_RENDERERS, suggestions, stat
9214
9160
  onSelect: (item) => setDraft(item.value ?? item.label),
9215
9161
  composer: composerNode
9216
9162
  }) : null,
9217
- turns.map((turn, turnIndex) => {
9218
- const key = turn.user?.id ?? `assistant-turn-${turnIndex}`;
9219
- const isLast = turnIndex === turns.length - 1;
9220
- return /* @__PURE__ */ jsx(ConversationTurnView, {
9221
- turn,
9222
- state: isLast ? stateForLast : stateForRest,
9223
- rendering,
9224
- activity: isLast ? activityForLast : activityForRest
9225
- }, key);
9163
+ /* @__PURE__ */ jsx(VirtualizedTurnList, {
9164
+ estimateSize: 400,
9165
+ getItemKey: getConversationTurnKey,
9166
+ itemGap: 20,
9167
+ items: turns,
9168
+ renderItem: renderTurn,
9169
+ viewportRef
9226
9170
  }),
9227
9171
  errorPresentation ? /* @__PURE__ */ jsxs("div", {
9228
9172
  role: "alert",
@@ -9253,12 +9197,13 @@ function FleetPiAgentChat({ toolRenderers = PI_TOOL_RENDERERS, suggestions, stat
9253
9197
  steering: [],
9254
9198
  followUp: []
9255
9199
  },
9256
- onDelete: onDeleteQueuedMessage
9200
+ onDelete: onDeleteQueuedMessage,
9201
+ onEdit: onEditQueuedMessage
9257
9202
  })
9258
9203
  ]
9259
9204
  });
9260
9205
  }
9261
- function ChatPanel({ messages, status, error, workspaceName, activityLabel, presentation, artifactRuns, queue, onDeleteQueuedMessage, onOpenArtifact, onOpenUIArtifactReady, inputSuggestionItems, suppressQuestionTool, inputBar, onSend, onOpenUIAction, onStop, onQuestionAnswer }) {
9206
+ function ChatPanel({ messages, status, error, workspaceName, activityLabel, presentation, artifactRuns, queue, onDeleteQueuedMessage, onEditQueuedMessage, onOpenArtifact, onOpenUIArtifactReady, inputSuggestionItems, suppressQuestionTool, inputBar, onSend, onOpenUIAction, onStop, onQuestionAnswer }) {
9262
9207
  const handleSend = useCallback2((msg) => {
9263
9208
  onSend(msg.content, msg.altKey);
9264
9209
  }, [onSend]);
@@ -9291,6 +9236,7 @@ function ChatPanel({ messages, status, error, workspaceName, activityLabel, pres
9291
9236
  artifactRuns,
9292
9237
  queue,
9293
9238
  onDeleteQueuedMessage,
9239
+ onEditQueuedMessage,
9294
9240
  onOpenArtifact,
9295
9241
  onOpenUIArtifactReady,
9296
9242
  questionTool,
@@ -9361,175 +9307,26 @@ function buildChatInputBarProps(composer, activeSessionId) {
9361
9307
  onEffortPickerOpenChange: composer.setEffortPickerOpen
9362
9308
  };
9363
9309
  }
9364
- var LazyChatCommandPalette = lazy(() => import("./chat-command-palette-CdYwoTMe-4LBAZF7K.js").then(({ ChatCommandPalette }) => ({ default: ChatCommandPalette })));
9365
- var LazySettingsDialog = lazy(() => import("./settings-dialog-CxHe8nym-KKXDPTIW.js").then(({ SettingsDialog }) => ({ default: SettingsDialog })));
9366
- var LazyForkPickerDialog = lazy(() => import("./fork-picker-dialog-B9yGc8Au-IL63F2DN.js").then(({ ForkPickerDialog }) => ({ default: ForkPickerDialog })));
9367
- function ChatCommandPaletteOverlay({ chrome, conversation, dialogs, panels, session }) {
9368
- return /* @__PURE__ */ jsx(Fragment$1, { children: dialogs.commandPaletteOpen ? /* @__PURE__ */ jsx(Suspense, {
9369
- fallback: null,
9370
- children: /* @__PURE__ */ jsx(LazyChatCommandPalette, {
9371
- open: true,
9372
- onOpenChange: dialogs.setCommandPaletteOpen,
9373
- onNewSession: () => void session.startNewSession(),
9374
- onStop: conversation.stop,
9375
- onResumeSession: (sessionToResume) => void session.resumeSession({ sessionId: sessionToResume.sessionId }),
9376
- onSetRightPanel: panels.setRightPanel,
9377
- onThemeChange: chrome.handleThemePreferenceChange,
9378
- sessions: session.sessions,
9379
- isStreaming: conversation.status === "streaming",
9380
- themePreference: chrome.themePreference
9381
- })
9382
- }) : null });
9310
+ function getChatAuthBearerToken$1() {
9311
+ return null;
9383
9312
  }
9384
- function ChatWorkspaceOverlayDialogs({ dialogs }) {
9385
- const { forkFromEntry, forkPickerEntries, setForkPickerEntries, setSettingsDialogOpen, setSettingsInitialTab, settingsDialogOpen, settingsInitialTab } = dialogs;
9386
- const handleSettingsOpenChange = useCallback2((open) => {
9387
- setSettingsDialogOpen(open);
9388
- if (!open) setSettingsInitialTab(void 0);
9389
- }, [setSettingsDialogOpen, setSettingsInitialTab]);
9390
- return /* @__PURE__ */ jsxs(Fragment$1, { children: [settingsDialogOpen ? /* @__PURE__ */ jsx(Suspense, {
9391
- fallback: null,
9392
- children: /* @__PURE__ */ jsx(LazySettingsDialog, {
9393
- open: true,
9394
- onOpenChange: handleSettingsOpenChange,
9395
- initialTab: settingsInitialTab
9396
- })
9397
- }) : null, forkPickerEntries ? /* @__PURE__ */ jsx(Suspense, {
9398
- fallback: null,
9399
- children: /* @__PURE__ */ jsx(LazyForkPickerDialog, {
9400
- entries: forkPickerEntries,
9401
- onOpenChange: (open) => {
9402
- if (!open) setForkPickerEntries(null);
9403
- },
9404
- onPick: forkFromEntry
9405
- })
9406
- }) : null] });
9407
- }
9408
- var FLEET_PANEL_KEYBINDINGS_STORAGE_KEY = "fleet-prime:v1:panel-keybindings";
9409
- var DEFAULT_FLEET_PANEL_KEYBINDINGS = {
9410
- toggleResources: {
9411
- code: "Digit1",
9412
- ctrlOrMeta: true,
9413
- shift: true
9414
- },
9415
- toggleWorkspace: {
9416
- code: "Digit2",
9417
- ctrlOrMeta: true,
9418
- shift: true
9419
- },
9420
- toggleArtifacts: {
9421
- code: "Digit3",
9422
- ctrlOrMeta: true,
9423
- shift: true
9424
- },
9425
- toggleRepl: {
9426
- code: "Digit4",
9427
- ctrlOrMeta: true,
9428
- shift: true
9429
- },
9430
- toggleSubagents: {
9431
- code: "Digit5",
9432
- ctrlOrMeta: true,
9433
- shift: true
9434
- },
9435
- toggleCommandPalette: {
9436
- code: "KeyK",
9437
- ctrlOrMeta: true
9438
- },
9439
- closePanel: { code: "Escape" },
9440
- focusPanel: {
9441
- code: "KeyP",
9442
- ctrlOrMeta: true,
9443
- shift: true
9444
- },
9445
- focusChat: {
9446
- code: "KeyC",
9447
- ctrlOrMeta: true,
9448
- shift: true
9449
- }
9450
- };
9451
- function readKeybindings() {
9452
- try {
9453
- const value = window.localStorage.getItem(FLEET_PANEL_KEYBINDINGS_STORAGE_KEY);
9454
- if (!value) return DEFAULT_FLEET_PANEL_KEYBINDINGS;
9455
- const overrides = JSON.parse(value);
9456
- return {
9457
- ...DEFAULT_FLEET_PANEL_KEYBINDINGS,
9458
- ...overrides
9459
- };
9460
- } catch {
9461
- return DEFAULT_FLEET_PANEL_KEYBINDINGS;
9462
- }
9463
- }
9464
- function matches(event, binding) {
9465
- return event.code === binding.code && (event.ctrlKey || event.metaKey) === Boolean(binding.ctrlOrMeta) && event.shiftKey === Boolean(binding.shift) && event.altKey === Boolean(binding.alt);
9466
- }
9467
- function focusChatComposer() {
9468
- document.querySelector("[data-fleet-chat-focus] textarea, [data-fleet-chat-focus] [contenteditable='true'], [data-fleet-chat-focus] input")?.focus({ preventScroll: true });
9469
- }
9470
- function usePanelKeybindings({ onCommandPaletteToggle, onClosePanel, rightPanel, setRightPanel }) {
9471
- useEffect2(() => {
9472
- const keybindings = readKeybindings();
9473
- const handleKeyDown = (event) => {
9474
- const match = (action) => matches(event, keybindings[action]);
9475
- let handled = true;
9476
- if (match("toggleResources")) setRightPanel(rightPanel === "resources" ? null : "resources");
9477
- else if (match("toggleWorkspace")) setRightPanel(rightPanel === "workspace" ? null : "workspace");
9478
- else if (match("toggleArtifacts")) setRightPanel(rightPanel === "artifacts" ? null : "artifacts");
9479
- else if (match("toggleRepl")) setRightPanel(rightPanel === "repl" ? null : "repl");
9480
- else if (match("toggleSubagents")) setRightPanel(rightPanel === "subagents" ? null : "subagents");
9481
- else if (onCommandPaletteToggle && match("toggleCommandPalette")) onCommandPaletteToggle();
9482
- else if (rightPanel && match("closePanel")) {
9483
- if (onClosePanel) onClosePanel();
9484
- else {
9485
- setRightPanel(null);
9486
- focusChatComposer();
9487
- }
9488
- } else if (rightPanel && match("focusPanel")) document.querySelector("[data-fleet-panel-focus]")?.focus({ preventScroll: true });
9489
- else if (match("focusChat")) focusChatComposer();
9490
- else handled = false;
9491
- if (handled) {
9492
- event.preventDefault();
9493
- event.stopPropagation();
9494
- }
9495
- };
9496
- document.addEventListener("keydown", handleKeyDown);
9497
- return () => document.removeEventListener("keydown", handleKeyDown);
9498
- }, [
9499
- onCommandPaletteToggle,
9500
- onClosePanel,
9501
- rightPanel,
9502
- setRightPanel
9503
- ]);
9504
- }
9505
- function useOptionalUser() {
9506
- return null;
9507
- }
9508
- function getChatAuthBearerToken$1() {
9509
- return null;
9510
- }
9511
- async function signOut() {
9512
- }
9513
- function getChatAuthBearerToken() {
9514
- return null;
9515
- }
9516
- var ChatRequestError = class extends Error {
9517
- status;
9518
- body;
9519
- code;
9520
- remediation;
9521
- constructor(status, body) {
9522
- super(formatChatRequestErrorMessage(status, body));
9523
- this.name = "ChatRequestError";
9524
- this.status = status;
9525
- this.body = body;
9526
- const envelope = parseErrorEnvelope(body);
9527
- this.code = envelope?.code;
9528
- this.remediation = envelope?.remediation;
9529
- }
9530
- };
9531
- function isFleetErrorRemediation(value) {
9532
- return typeof value === "object" && value !== null && typeof value.action === "string" && typeof value.label === "string";
9313
+ var ChatRequestError = class extends Error {
9314
+ status;
9315
+ body;
9316
+ code;
9317
+ remediation;
9318
+ constructor(status, body) {
9319
+ super(formatChatRequestErrorMessage(status, body));
9320
+ this.name = "ChatRequestError";
9321
+ this.status = status;
9322
+ this.body = body;
9323
+ const envelope = parseErrorEnvelope(body);
9324
+ this.code = envelope?.code;
9325
+ this.remediation = envelope?.remediation;
9326
+ }
9327
+ };
9328
+ function isFleetErrorRemediation(value) {
9329
+ return typeof value === "object" && value !== null && typeof value.action === "string" && typeof value.label === "string";
9533
9330
  }
9534
9331
  function parseErrorEnvelope(body) {
9535
9332
  const trimmed = body.trim();
@@ -9572,7 +9369,7 @@ function chatErrorFromStreamEvent(event) {
9572
9369
  }
9573
9370
  async function withChatRequestHeaders(init) {
9574
9371
  const headers = new Headers(init?.headers);
9575
- const bearer = await getChatAuthBearerToken();
9372
+ const bearer = await getChatAuthBearerToken$1();
9576
9373
  if (bearer) headers.set("Authorization", `Bearer ${bearer}`);
9577
9374
  return headers;
9578
9375
  }
@@ -9672,6 +9469,167 @@ function labelForState(state) {
9672
9469
  return;
9673
9470
  }
9674
9471
  }
9472
+ function notifyChatError(error) {
9473
+ if (isDaemonDisconnectError(error)) return;
9474
+ notify.error(error instanceof Error ? error.message : String(error));
9475
+ }
9476
+ var LazyChatCommandPalette = lazy(() => import("./chat-command-palette-7gbqEnm9-6XICQZN7.js").then(({ ChatCommandPalette }) => ({ default: ChatCommandPalette })));
9477
+ var LazySettingsDialog = lazy(() => import("./settings-dialog-DndPbM-v-RFNXXEAN.js").then(({ SettingsDialog }) => ({ default: SettingsDialog })));
9478
+ var LazyForkPickerDialog = lazy(() => import("./fork-picker-dialog-DlINz9UQ-UWIXFDJX.js").then(({ ForkPickerDialog }) => ({ default: ForkPickerDialog })));
9479
+ function ChatCommandPaletteOverlay({ chrome, conversation, dialogs, panels, session }) {
9480
+ return /* @__PURE__ */ jsx(Fragment$1, { children: dialogs.commandPaletteOpen ? /* @__PURE__ */ jsx(Suspense, {
9481
+ fallback: null,
9482
+ children: /* @__PURE__ */ jsx(LazyChatCommandPalette, {
9483
+ open: true,
9484
+ onOpenChange: dialogs.setCommandPaletteOpen,
9485
+ onNewSession: () => void session.startNewSession(),
9486
+ onStop: conversation.stop,
9487
+ onResumeSession: (sessionToResume) => void session.resumeSession({ sessionId: sessionToResume.sessionId }),
9488
+ onSetRightPanel: panels.setRightPanel,
9489
+ onThemeChange: chrome.handleThemePreferenceChange,
9490
+ sessions: session.sessions,
9491
+ isStreaming: conversation.status === "streaming",
9492
+ themePreference: chrome.themePreference
9493
+ })
9494
+ }) : null });
9495
+ }
9496
+ function ChatWorkspaceOverlayDialogs({ dialogs }) {
9497
+ const { forkFromEntry, forkPickerEntries, setForkPickerEntries, setSettingsDialogOpen, setSettingsInitialTab, settingsDialogOpen, settingsInitialTab } = dialogs;
9498
+ const [hasOpenedSettingsDialog, setHasOpenedSettingsDialog] = useState2(settingsDialogOpen);
9499
+ const [hasOpenedForkPickerDialog, setHasOpenedForkPickerDialog] = useState2(forkPickerEntries !== null);
9500
+ useEffect2(() => {
9501
+ if (settingsDialogOpen) setHasOpenedSettingsDialog(true);
9502
+ }, [settingsDialogOpen]);
9503
+ useEffect2(() => {
9504
+ if (forkPickerEntries !== null) setHasOpenedForkPickerDialog(true);
9505
+ }, [forkPickerEntries]);
9506
+ const handleSettingsOpenChange = useCallback2((open) => {
9507
+ setSettingsDialogOpen(open);
9508
+ if (!open) setSettingsInitialTab(void 0);
9509
+ }, [setSettingsDialogOpen, setSettingsInitialTab]);
9510
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [hasOpenedSettingsDialog ? /* @__PURE__ */ jsx(Suspense, {
9511
+ fallback: null,
9512
+ children: /* @__PURE__ */ jsx(LazySettingsDialog, {
9513
+ open: settingsDialogOpen,
9514
+ onOpenChange: handleSettingsOpenChange,
9515
+ initialTab: settingsInitialTab
9516
+ })
9517
+ }) : null, hasOpenedForkPickerDialog ? /* @__PURE__ */ jsx(Suspense, {
9518
+ fallback: null,
9519
+ children: /* @__PURE__ */ jsx(LazyForkPickerDialog, {
9520
+ entries: forkPickerEntries,
9521
+ onOpenChange: (open) => {
9522
+ if (!open) setForkPickerEntries(null);
9523
+ },
9524
+ onPick: forkFromEntry
9525
+ })
9526
+ }) : null] });
9527
+ }
9528
+ var FLEET_PANEL_KEYBINDINGS_STORAGE_KEY = "fleet-prime:v1:panel-keybindings";
9529
+ var DEFAULT_FLEET_PANEL_KEYBINDINGS = {
9530
+ toggleResources: {
9531
+ code: "Digit1",
9532
+ ctrlOrMeta: true,
9533
+ shift: true
9534
+ },
9535
+ toggleWorkspace: {
9536
+ code: "Digit2",
9537
+ ctrlOrMeta: true,
9538
+ shift: true
9539
+ },
9540
+ toggleArtifacts: {
9541
+ code: "Digit3",
9542
+ ctrlOrMeta: true,
9543
+ shift: true
9544
+ },
9545
+ toggleRepl: {
9546
+ code: "Digit4",
9547
+ ctrlOrMeta: true,
9548
+ shift: true
9549
+ },
9550
+ toggleSubagents: {
9551
+ code: "Digit5",
9552
+ ctrlOrMeta: true,
9553
+ shift: true
9554
+ },
9555
+ toggleCommandPalette: {
9556
+ code: "KeyK",
9557
+ ctrlOrMeta: true
9558
+ },
9559
+ closePanel: { code: "Escape" },
9560
+ focusPanel: {
9561
+ code: "KeyP",
9562
+ ctrlOrMeta: true,
9563
+ shift: true
9564
+ },
9565
+ focusChat: {
9566
+ code: "KeyC",
9567
+ ctrlOrMeta: true,
9568
+ shift: true
9569
+ }
9570
+ };
9571
+ function readKeybindings() {
9572
+ try {
9573
+ const value = readStoredValue(FLEET_PANEL_KEYBINDINGS_STORAGE_KEY);
9574
+ if (!value) return DEFAULT_FLEET_PANEL_KEYBINDINGS;
9575
+ const overrides = JSON.parse(value);
9576
+ return {
9577
+ ...DEFAULT_FLEET_PANEL_KEYBINDINGS,
9578
+ ...overrides
9579
+ };
9580
+ } catch {
9581
+ return DEFAULT_FLEET_PANEL_KEYBINDINGS;
9582
+ }
9583
+ }
9584
+ function matches(event, binding) {
9585
+ return event.code === binding.code && (event.ctrlKey || event.metaKey) === Boolean(binding.ctrlOrMeta) && event.shiftKey === Boolean(binding.shift) && event.altKey === Boolean(binding.alt);
9586
+ }
9587
+ function focusChatComposer() {
9588
+ document.querySelector("[data-fleet-chat-focus] textarea, [data-fleet-chat-focus] [contenteditable='true'], [data-fleet-chat-focus] input")?.focus({ preventScroll: true });
9589
+ }
9590
+ function usePanelKeybindings({ onCommandPaletteToggle, onClosePanel, rightPanel, setRightPanel }) {
9591
+ useEffect2(() => {
9592
+ const keybindings = readKeybindings();
9593
+ const handleKeyDown = (event) => {
9594
+ const match = (action) => matches(event, keybindings[action]);
9595
+ let handled = true;
9596
+ if (match("toggleResources")) setRightPanel(rightPanel === "resources" ? null : "resources");
9597
+ else if (match("toggleWorkspace")) setRightPanel(rightPanel === "workspace" ? null : "workspace");
9598
+ else if (match("toggleArtifacts")) setRightPanel(rightPanel === "artifacts" ? null : "artifacts");
9599
+ else if (match("toggleRepl")) setRightPanel(rightPanel === "repl" ? null : "repl");
9600
+ else if (match("toggleSubagents")) setRightPanel(rightPanel === "subagents" ? null : "subagents");
9601
+ else if (onCommandPaletteToggle && match("toggleCommandPalette")) onCommandPaletteToggle();
9602
+ else if (rightPanel && match("closePanel")) {
9603
+ if (onClosePanel) onClosePanel();
9604
+ else {
9605
+ setRightPanel(null);
9606
+ focusChatComposer();
9607
+ }
9608
+ } else if (rightPanel && match("focusPanel")) document.querySelector("[data-fleet-panel-focus]")?.focus({ preventScroll: true });
9609
+ else if (match("focusChat")) focusChatComposer();
9610
+ else handled = false;
9611
+ if (handled) {
9612
+ event.preventDefault();
9613
+ event.stopPropagation();
9614
+ }
9615
+ };
9616
+ document.addEventListener("keydown", handleKeyDown);
9617
+ return () => document.removeEventListener("keydown", handleKeyDown);
9618
+ }, [
9619
+ onCommandPaletteToggle,
9620
+ onClosePanel,
9621
+ rightPanel,
9622
+ setRightPanel
9623
+ ]);
9624
+ }
9625
+ function useOptionalUser() {
9626
+ return null;
9627
+ }
9628
+ function getChatAuthBearerToken() {
9629
+ return null;
9630
+ }
9631
+ async function signOut() {
9632
+ }
9675
9633
  var ProjectResponseSchema = external_exports.object({ project: ProjectSummarySchema });
9676
9634
  var chatClient = {
9677
9635
  async abortSession(metadata) {
@@ -9688,7 +9646,7 @@ var chatClient = {
9688
9646
  body: JSON.stringify(request)
9689
9647
  });
9690
9648
  },
9691
- async deleteQueuedMessage(request) {
9649
+ async mutateQueuedMessage(request) {
9692
9650
  const body = ChatQueueMutationRequestSchema.parse(request);
9693
9651
  return fetchValidatedJson("/api/chat/session", ChatQueueMutationResponseSchema, {
9694
9652
  method: "PATCH",
@@ -9696,6 +9654,12 @@ var chatClient = {
9696
9654
  body: JSON.stringify(body)
9697
9655
  });
9698
9656
  },
9657
+ async deleteQueuedMessage(request) {
9658
+ return this.mutateQueuedMessage({
9659
+ ...request,
9660
+ mutation: request.mutation ?? { type: "delete" }
9661
+ });
9662
+ },
9699
9663
  async browseWorkspace(path, projectId) {
9700
9664
  const params = new URLSearchParams();
9701
9665
  if (projectId) params.set("projectId", projectId);
@@ -9874,7 +9838,7 @@ var chatClient = {
9874
9838
  async streamMessage(request, onEvent, signal) {
9875
9839
  const attempt = async (allowRetry) => {
9876
9840
  const headers = new Headers({ "Content-Type": "application/json" });
9877
- const bearer = await getChatAuthBearerToken$1();
9841
+ const bearer = await getChatAuthBearerToken();
9878
9842
  if (bearer) headers.set("Authorization", `Bearer ${bearer}`);
9879
9843
  const response = await fetch(resolveChatApiUrl("/api/chat"), {
9880
9844
  method: "POST",
@@ -9891,6 +9855,33 @@ var chatClient = {
9891
9855
  };
9892
9856
  await attempt(true);
9893
9857
  },
9858
+ async getMcpConnections() {
9859
+ return fetchValidatedJson("/api/chat/mcp", ChatMcpListResponseSchema);
9860
+ },
9861
+ async upsertMcpConnection(request) {
9862
+ const body = ChatMcpUpsertRequestSchema.parse(request);
9863
+ return fetchValidatedJson("/api/chat/mcp", ChatMcpListResponseSchema, {
9864
+ method: "POST",
9865
+ headers: { "Content-Type": "application/json" },
9866
+ body: JSON.stringify(body)
9867
+ });
9868
+ },
9869
+ async removeMcpConnection(request) {
9870
+ const body = ChatMcpDeleteRequestSchema.parse(request);
9871
+ return fetchValidatedJson("/api/chat/mcp", ChatMcpListResponseSchema, {
9872
+ method: "DELETE",
9873
+ headers: { "Content-Type": "application/json" },
9874
+ body: JSON.stringify(body)
9875
+ });
9876
+ },
9877
+ async mcpOAuth(request) {
9878
+ const body = ChatMcpOAuthLoginRequestSchema.parse(request);
9879
+ return fetchValidatedJson("/api/chat/mcp/oauth", ChatMcpOAuthLoginResponseSchema, {
9880
+ method: "POST",
9881
+ headers: { "Content-Type": "application/json" },
9882
+ body: JSON.stringify(body)
9883
+ });
9884
+ },
9894
9885
  async getProviders() {
9895
9886
  return fetchValidatedJson("/api/chat/providers", ChatProvidersResponseSchema);
9896
9887
  },
@@ -9919,7 +9910,7 @@ var chatClient = {
9919
9910
  });
9920
9911
  }
9921
9912
  };
9922
- var keys = {
9913
+ var chatQueryKeys = {
9923
9914
  models: (projectId) => [
9924
9915
  "chat",
9925
9916
  "models",
@@ -9932,6 +9923,7 @@ var keys = {
9932
9923
  projectId ?? "default"
9933
9924
  ],
9934
9925
  providers: ["chat", "providers"],
9926
+ mcp: ["chat", "mcp"],
9935
9927
  resources: (projectId) => [
9936
9928
  "chat",
9937
9929
  "resources",
@@ -9954,10 +9946,12 @@ var keys = {
9954
9946
  ],
9955
9947
  projects: ["projects"]
9956
9948
  };
9949
+ var keys = chatQueryKeys;
9957
9950
  function useChatModels(projectId) {
9958
9951
  return useQuery({
9959
9952
  queryKey: keys.models(projectId),
9960
- queryFn: () => chatClient.getModels({ projectId })
9953
+ queryFn: () => chatClient.getModels({ projectId }),
9954
+ enabled: Boolean(projectId)
9961
9955
  });
9962
9956
  }
9963
9957
  function useChatProjects() {
@@ -9974,7 +9968,7 @@ function useChatModelCatalog(options) {
9974
9968
  scope: "all",
9975
9969
  projectId: options?.projectId
9976
9970
  }),
9977
- enabled: options?.enabled
9971
+ enabled: Boolean(options?.projectId) && options?.enabled !== false
9978
9972
  });
9979
9973
  }
9980
9974
  function useDiscoverChatModels() {
@@ -9989,19 +9983,22 @@ function useDiscoverChatModels() {
9989
9983
  function useChatResources(projectId) {
9990
9984
  return useQuery({
9991
9985
  queryKey: keys.resources(projectId),
9992
- queryFn: () => chatClient.getResources(projectId)
9986
+ queryFn: () => chatClient.getResources(projectId),
9987
+ enabled: Boolean(projectId)
9993
9988
  });
9994
9989
  }
9995
9990
  function useChatCommands(projectId) {
9996
9991
  return useQuery({
9997
9992
  queryKey: keys.commands(projectId),
9998
- queryFn: () => chatClient.getCommands(projectId)
9993
+ queryFn: () => chatClient.getCommands(projectId),
9994
+ enabled: Boolean(projectId)
9999
9995
  });
10000
9996
  }
10001
9997
  function useChatSettings(projectId) {
10002
9998
  return useQuery({
10003
9999
  queryKey: keys.settings(projectId),
10004
- queryFn: () => chatClient.getSettings(projectId)
10000
+ queryFn: () => chatClient.getSettings(projectId),
10001
+ enabled: Boolean(projectId)
10005
10002
  });
10006
10003
  }
10007
10004
  function useUpdateChatSettings() {
@@ -10020,7 +10017,44 @@ function useWorkspaceTree(projectId, options) {
10020
10017
  return useQuery({
10021
10018
  queryKey: keys.workspace(projectId),
10022
10019
  queryFn: () => chatClient.getWorkspaceTree(projectId),
10023
- enabled: options?.enabled
10020
+ enabled: Boolean(projectId) && options?.enabled !== false
10021
+ });
10022
+ }
10023
+ function useChatMcpConnections() {
10024
+ return useQuery({
10025
+ queryKey: keys.mcp,
10026
+ queryFn: () => chatClient.getMcpConnections()
10027
+ });
10028
+ }
10029
+ function useUpdateMcpConnection() {
10030
+ const queryClient = useQueryClient();
10031
+ return useMutation({
10032
+ mutationFn: (request) => chatClient.upsertMcpConnection(request),
10033
+ onSuccess: (data) => {
10034
+ queryClient.setQueryData(keys.mcp, data);
10035
+ queryClient.invalidateQueries({ queryKey: ["chat", "resources"] });
10036
+ }
10037
+ });
10038
+ }
10039
+ function useRemoveMcpConnection() {
10040
+ const queryClient = useQueryClient();
10041
+ return useMutation({
10042
+ mutationFn: (request) => chatClient.removeMcpConnection(request),
10043
+ onSuccess: (data) => {
10044
+ queryClient.setQueryData(keys.mcp, data);
10045
+ queryClient.invalidateQueries({ queryKey: ["chat", "resources"] });
10046
+ }
10047
+ });
10048
+ }
10049
+ function useMcpOAuth() {
10050
+ const queryClient = useQueryClient();
10051
+ return useMutation({
10052
+ mutationFn: (request) => chatClient.mcpOAuth(request),
10053
+ onSuccess: (data) => {
10054
+ if (data.status !== "success" || !data.connections) return;
10055
+ queryClient.setQueryData(keys.mcp, { connections: data.connections });
10056
+ queryClient.invalidateQueries({ queryKey: ["chat", "resources"] });
10057
+ }
10024
10058
  });
10025
10059
  }
10026
10060
  function useChatProviders() {
@@ -10450,15 +10484,25 @@ function normalizeSlashCommandName(name) {
10450
10484
  const normalized = name.trim().replace(/\s+/g, "-");
10451
10485
  return /^[\w.-]+$/.test(normalized) ? normalized : "";
10452
10486
  }
10487
+ function slashSuggestionValue(name) {
10488
+ return `/${name} `;
10489
+ }
10453
10490
  function toSlashSuggestion(command) {
10491
+ const argumentHint = command.argumentHint?.trim();
10454
10492
  return {
10455
10493
  id: command.name,
10456
10494
  label: `/${command.name}`,
10457
- value: `/${command.name}${command.argumentHint ? ` ${command.argumentHint}` : ""} `,
10495
+ value: slashSuggestionValue(command.name),
10458
10496
  description: command.description,
10459
- category: command.category ?? "builtin"
10497
+ category: command.category ?? "builtin",
10498
+ ...argumentHint ? { metadata: { argumentHint } } : {}
10460
10499
  };
10461
10500
  }
10501
+ function slashCommandInsertsPrefixOnSelect(item) {
10502
+ if (item.metadata?.argumentHint?.trim()) return true;
10503
+ const builtin = WEB_BUILTIN_SLASH_COMMANDS.find((command) => command.name === item.id);
10504
+ return Boolean(builtin?.argumentHint?.trim());
10505
+ }
10462
10506
  function buildSlashCommands(resources, enabled, commandsData) {
10463
10507
  const byId = /* @__PURE__ */ new Map();
10464
10508
  for (const command of WEB_BUILTIN_SLASH_COMMANDS) byId.set(command.name, toSlashSuggestion(command));
@@ -10471,12 +10515,14 @@ function buildSlashCommands(resources, enabled, commandsData) {
10471
10515
  if (resource.activationStatus && resource.activationStatus !== "active") continue;
10472
10516
  const commandName = normalizeSlashCommandName(resource.name);
10473
10517
  if (!commandName || byId.has(commandName)) continue;
10518
+ const argumentHint = resource.argumentHint?.trim();
10474
10519
  byId.set(commandName, {
10475
10520
  id: commandName,
10476
10521
  label: `/${commandName}`,
10477
- value: `/${commandName} `,
10522
+ value: slashSuggestionValue(commandName),
10478
10523
  description: resource.description,
10479
- category
10524
+ category,
10525
+ ...argumentHint ? { metadata: { argumentHint } } : {}
10480
10526
  });
10481
10527
  }
10482
10528
  return Array.from(byId.values());
@@ -10742,6 +10788,8 @@ function applyChatStreamEvent(transition, event) {
10742
10788
  if (event.type === "rlm") {
10743
10789
  const presentation = transition.snapshot.presentation;
10744
10790
  if (!presentation) return transition;
10791
+ const existingChild = presentation.rlmChildren.find((child) => child.id === event.child.id);
10792
+ if (existingChild && existingChild.timestamp > event.child.timestamp) return transition;
10745
10793
  const rlmChildren = [...presentation.rlmChildren.filter((child) => child.id !== event.child.id), event.child];
10746
10794
  return {
10747
10795
  ...transition,
@@ -10909,13 +10957,12 @@ function isConnectedFrame(value) {
10909
10957
  return typeof value === "object" && value !== null && value.type === "connected" && typeof value.sessionId === "string";
10910
10958
  }
10911
10959
  function readStoredSubagentCursor(key) {
10912
- if (typeof window === "undefined") return void 0;
10913
10960
  try {
10914
- const raw = window.sessionStorage.getItem(key);
10961
+ const raw = readStoredValue(key, "session");
10915
10962
  if (!raw) return void 0;
10916
10963
  const value = JSON.parse(raw);
10917
10964
  if (typeof value.generation !== "string" || value.generation.length === 0 || typeof value.lastEventId !== "number" || !Number.isInteger(value.lastEventId) || value.lastEventId < 0) {
10918
- window.sessionStorage.removeItem(key);
10965
+ removeStoredValue(key, "session");
10919
10966
  return;
10920
10967
  }
10921
10968
  return {
@@ -10923,7 +10970,7 @@ function readStoredSubagentCursor(key) {
10923
10970
  lastEventId: value.lastEventId
10924
10971
  };
10925
10972
  } catch {
10926
- window.sessionStorage.removeItem(key);
10973
+ removeStoredValue(key, "session");
10927
10974
  return;
10928
10975
  }
10929
10976
  }
@@ -11056,18 +11103,14 @@ function useSubagentChat({ client, enabled, child, loadSession, parentSessionId
11056
11103
  lastEventId = storedCursor.lastEventId;
11057
11104
  }
11058
11105
  const persistCursor = () => {
11059
- if (typeof window === "undefined") return;
11060
- try {
11061
- if (!streamGeneration) {
11062
- window.sessionStorage.removeItem(cursorKey);
11063
- return;
11064
- }
11065
- window.sessionStorage.setItem(cursorKey, JSON.stringify({
11066
- generation: streamGeneration,
11067
- lastEventId
11068
- }));
11069
- } catch {
11106
+ if (!streamGeneration) {
11107
+ removeStoredValue(cursorKey, "session");
11108
+ return;
11070
11109
  }
11110
+ writeStoredValue(cursorKey, JSON.stringify({
11111
+ generation: streamGeneration,
11112
+ lastEventId
11113
+ }), "session");
11071
11114
  };
11072
11115
  const clearCursor = () => {
11073
11116
  lastEventId = 0;
@@ -11357,12 +11400,11 @@ function storeResourceCanvasWidth(width) {
11357
11400
  }
11358
11401
  function readStoredThemePreference() {
11359
11402
  if (typeof window === "undefined") return "system";
11360
- const value = window.localStorage.getItem(THEME_PREFERENCE_STORAGE_KEY);
11403
+ const value = readStoredValue(THEME_PREFERENCE_STORAGE_KEY);
11361
11404
  return value === "light" || value === "dark" || value === "system" ? value : "system";
11362
11405
  }
11363
11406
  function storeThemePreference(preference) {
11364
- if (typeof window === "undefined") return;
11365
- window.localStorage.setItem(THEME_PREFERENCE_STORAGE_KEY, preference);
11407
+ writeStoredValue(THEME_PREFERENCE_STORAGE_KEY, preference);
11366
11408
  }
11367
11409
  function applyThemePreference(preference) {
11368
11410
  if (typeof window === "undefined") return;
@@ -11544,18 +11586,16 @@ function useChatStorage() {
11544
11586
  };
11545
11587
  }
11546
11588
  function readStoredBrowserSessions() {
11547
- if (typeof window === "undefined" || !window.localStorage) return {};
11589
+ const raw = readStoredValue(CHAT_SESSION_STORAGE_KEY);
11590
+ if (!raw) return readLegacyScopeStorage();
11548
11591
  try {
11549
- const raw = window.localStorage.getItem(CHAT_SESSION_STORAGE_KEY);
11550
- if (!raw) return readLegacyScopeStorage();
11551
11592
  return parseSessionMetadata(JSON.parse(raw));
11552
11593
  } catch {
11553
11594
  return readLegacyScopeStorage();
11554
11595
  }
11555
11596
  }
11556
11597
  function readLegacyScopeStorage() {
11557
- if (typeof window === "undefined" || !window.localStorage) return {};
11558
- const raw = window.localStorage.getItem("fleet-prime:v1:chat-sessions");
11598
+ const raw = readStoredValue("fleet-prime:v1:chat-sessions");
11559
11599
  if (!raw) return {};
11560
11600
  try {
11561
11601
  return parseSessionMetadata(JSON.parse(raw)?.normal);
@@ -11568,19 +11608,17 @@ function parseSessionMetadata(value) {
11568
11608
  return result.success ? result.data : {};
11569
11609
  }
11570
11610
  function clearBrowserChatSessions() {
11571
- if (typeof window === "undefined" || !window.localStorage) return;
11572
- window.localStorage.removeItem(CHAT_SESSION_STORAGE_KEY);
11573
- window.localStorage.removeItem("fleet-prime:v1:chat-sessions");
11574
- window.localStorage.removeItem("fleet-prime:v1:chat-mode");
11611
+ removeStoredValue(CHAT_SESSION_STORAGE_KEY);
11612
+ removeStoredValue("fleet-prime:v1:chat-sessions");
11613
+ removeStoredValue("fleet-prime:v1:chat-mode");
11575
11614
  }
11576
11615
  function storeBrowserSessions(metadata) {
11577
- if (typeof window === "undefined" || !window.localStorage) return;
11578
11616
  if (!metadata.sessionId && !metadata.projectId) {
11579
- window.localStorage.removeItem(CHAT_SESSION_STORAGE_KEY);
11580
- window.localStorage.removeItem("fleet-prime:v1:chat-sessions");
11617
+ removeStoredValue(CHAT_SESSION_STORAGE_KEY);
11618
+ removeStoredValue("fleet-prime:v1:chat-sessions");
11581
11619
  return;
11582
11620
  }
11583
- window.localStorage.setItem(CHAT_SESSION_STORAGE_KEY, JSON.stringify(metadata));
11621
+ writeStoredValue(CHAT_SESSION_STORAGE_KEY, JSON.stringify(metadata));
11584
11622
  }
11585
11623
  function useChatSuggestions({ messages, resources, workspaceTree }) {
11586
11624
  return useMemo2(() => buildContextSuggestions({
@@ -11725,7 +11763,7 @@ function AccountMenu({ user, onSignOut, onOpenSettings, compact = false, label =
11725
11763
  children: [
11726
11764
  /* @__PURE__ */ jsx(QredenceLogo, { className: "size-3.5 shrink-0" }),
11727
11765
  /* @__PURE__ */ jsx("span", {
11728
- className: compact ? "sr-only" : "text-[13px] font-medium tracking-[-0.01em] whitespace-nowrap",
11766
+ className: compact ? "sr-only" : "text-[0.8125rem] font-medium tracking-[-0.01em] whitespace-nowrap",
11729
11767
  children: label
11730
11768
  }),
11731
11769
  /* @__PURE__ */ jsx(ChevronDown, { className: "size-3.5 shrink-0 text-foreground/35" })
@@ -11793,6 +11831,139 @@ function AccountMenu({ user, onSignOut, onOpenSettings, compact = false, label =
11793
11831
  })
11794
11832
  });
11795
11833
  }
11834
+ function statusLabel(status) {
11835
+ switch (status) {
11836
+ case "queued":
11837
+ return "queued";
11838
+ case "running":
11839
+ case "recovering":
11840
+ return "streaming";
11841
+ case "error":
11842
+ case "failed":
11843
+ return "error";
11844
+ case "cancelled":
11845
+ return "cancelled";
11846
+ case "done":
11847
+ return "complete";
11848
+ default:
11849
+ return "ready";
11850
+ }
11851
+ }
11852
+ function statusDotClass(status) {
11853
+ switch (status) {
11854
+ case "running":
11855
+ case "recovering":
11856
+ return "bg-emerald-400 motion-safe:animate-pulse";
11857
+ case "error":
11858
+ case "failed":
11859
+ return "bg-destructive";
11860
+ case "queued":
11861
+ return "bg-amber-300";
11862
+ case "cancelled":
11863
+ return "bg-foreground/35";
11864
+ default:
11865
+ return "bg-foreground/35";
11866
+ }
11867
+ }
11868
+ function AgentTabBar({ tabs, value, onValueChange, onClose, onNewSession }) {
11869
+ const tabRefs = useRef2(/* @__PURE__ */ new Map());
11870
+ const setTabRef = useCallback2((tabId, node) => {
11871
+ if (node) tabRefs.current.set(tabId, node);
11872
+ else tabRefs.current.delete(tabId);
11873
+ }, []);
11874
+ useEffect2(() => {
11875
+ for (const tabId of tabRefs.current.keys()) if (!tabs.some((tab) => tab.id === tabId)) tabRefs.current.delete(tabId);
11876
+ }, [tabs]);
11877
+ const focusTab = useCallback2((index) => {
11878
+ const tab = tabs[index];
11879
+ if (!tab) return;
11880
+ tabRefs.current.get(tab.id)?.focus();
11881
+ onValueChange(tab.id);
11882
+ }, [onValueChange, tabs]);
11883
+ const handleKeyDown = useCallback2((event, tabId) => {
11884
+ const index = tabs.findIndex((tab) => tab.id === tabId);
11885
+ if (index < 0) return;
11886
+ let nextIndex;
11887
+ if (event.key === "ArrowRight") nextIndex = (index + 1) % tabs.length;
11888
+ if (event.key === "ArrowLeft") nextIndex = (index - 1 + tabs.length) % tabs.length;
11889
+ if (event.key === "Home") nextIndex = 0;
11890
+ if (event.key === "End") nextIndex = tabs.length - 1;
11891
+ if (nextIndex === void 0) return;
11892
+ event.preventDefault();
11893
+ focusTab(nextIndex);
11894
+ }, [focusTab, tabs]);
11895
+ return /* @__PURE__ */ jsxs("div", {
11896
+ className: "flex min-w-0 max-w-full items-center gap-1",
11897
+ "data-testid": "agent-tab-bar",
11898
+ children: [/* @__PURE__ */ jsx("div", {
11899
+ "aria-label": "Agent conversations",
11900
+ className: "flex min-w-0 flex-1 items-center gap-1 overflow-x-auto overscroll-contain [scrollbar-width:none] [&::-webkit-scrollbar]:hidden",
11901
+ role: "tablist",
11902
+ children: tabs.map((tab) => {
11903
+ const active = tab.id === value;
11904
+ const status = statusLabel(tab.status);
11905
+ return /* @__PURE__ */ jsxs("div", {
11906
+ className: "group/tab relative min-w-0 shrink-0 basis-[164px] sm:max-w-[164px]",
11907
+ "data-tab-id": tab.id,
11908
+ children: [/* @__PURE__ */ jsxs(Button, {
11909
+ ref: (node) => setTabRef(tab.id, node),
11910
+ "aria-controls": agentTabPanelId(tab.id),
11911
+ "aria-selected": active,
11912
+ "aria-label": `${tab.label}, ${status}`,
11913
+ className: cn("h-7 w-full min-w-0 justify-start text-left gap-1.5 rounded-[7px] border border-transparent px-2 text-[0.75rem] font-medium leading-none transition-colors motion-reduce:transition-none", active ? "bg-surface-4 text-foreground shadow-none" : "bg-transparent text-foreground/45 hover:bg-foreground/5 hover:text-foreground/75", tab.kind === "subagent" && onClose && "pr-7"),
11914
+ "data-state": active ? "active" : "inactive",
11915
+ id: agentTabTriggerId(tab.id),
11916
+ onClick: () => onValueChange(tab.id),
11917
+ onKeyDown: (event) => handleKeyDown(event, tab.id),
11918
+ role: "tab",
11919
+ size: "sm",
11920
+ tabIndex: active ? 0 : -1,
11921
+ type: "button",
11922
+ variant: "ghost",
11923
+ children: [tab.kind === "main" ? /* @__PURE__ */ jsx(Bot, {
11924
+ "aria-hidden": "true",
11925
+ className: "size-3.5 shrink-0"
11926
+ }) : /* @__PURE__ */ jsx("span", {
11927
+ "aria-hidden": "true",
11928
+ className: cn("size-1.5 shrink-0 rounded-full", statusDotClass(tab.status))
11929
+ }), /* @__PURE__ */ jsx("span", {
11930
+ className: "min-w-0 flex-1 truncate text-left",
11931
+ children: tab.label
11932
+ })]
11933
+ }), tab.kind === "subagent" && onClose ? /* @__PURE__ */ jsx(Button, {
11934
+ "aria-label": `Close ${tab.label} tab`,
11935
+ className: "absolute top-1/2 right-1 size-5 -translate-y-1/2 rounded-[5px] p-0 text-foreground/35 opacity-0 transition-opacity motion-reduce:transition-none hover:bg-foreground/10 hover:text-foreground/75 focus-visible:opacity-100 group-hover/tab:opacity-100",
11936
+ onClick: (event) => {
11937
+ event.stopPropagation();
11938
+ onClose(tab.id);
11939
+ },
11940
+ size: "icon-xs",
11941
+ title: `Close ${tab.label} tab`,
11942
+ type: "button",
11943
+ variant: "ghost",
11944
+ children: /* @__PURE__ */ jsx(X, {
11945
+ "aria-hidden": "true",
11946
+ className: "size-3"
11947
+ })
11948
+ }) : null]
11949
+ }, tab.id);
11950
+ })
11951
+ }), onNewSession ? /* @__PURE__ */ jsx(Button, {
11952
+ "aria-label": "New chat",
11953
+ className: "size-7 shrink-0 rounded-[7px] text-foreground/50 hover:bg-foreground/7 hover:text-foreground/85",
11954
+ "data-testid": "new-chat-tab",
11955
+ onClick: onNewSession,
11956
+ size: "icon-sm",
11957
+ title: "New chat",
11958
+ type: "button",
11959
+ variant: "ghost",
11960
+ children: /* @__PURE__ */ jsx(Plus, {
11961
+ "aria-hidden": "true",
11962
+ className: "size-3.5"
11963
+ })
11964
+ }) : null]
11965
+ });
11966
+ }
11796
11967
  function useChatWorkspaceHeader({ activeTabId, tabs, onCloseTab, onNewSession, onSelectTab, onOpenSettings }) {
11797
11968
  const navigate = useNavigate();
11798
11969
  const user = useOptionalUser();
@@ -11828,6 +11999,7 @@ function useChatWorkspaceHeader({ activeTabId, tabs, onCloseTab, onNewSession, o
11828
11999
  };
11829
12000
  }
11830
12001
  var CHAT_COMMAND_URL = "/api/chat/command";
12002
+ var MCP_USAGE = "MCP usage: /mcp, /mcp list, /mcp login <name>, /mcp logout <name>.";
11831
12003
  function liveSessionId(metadata) {
11832
12004
  const id = metadata.sessionId?.trim();
11833
12005
  return id ? id : void 0;
@@ -11905,6 +12077,7 @@ ${text}`;
11905
12077
  }).join("\n\n---\n\n");
11906
12078
  }
11907
12079
  function useLocalSlashActions({ appendLocalMessage, getMessages, getSessionMetadata, modelKey, models, onForkPicker, openSettings, onOpenUIRequest, resumeSession, sessions, setEffortPickerOpen, setModelKey, setModelPickerOpen, setThinkingLevel, startNewSession }) {
12080
+ const queryClient = useQueryClient();
11908
12081
  const chatCommand = useCallback2(async (command, args = "") => {
11909
12082
  const sessionId = liveSessionId(getSessionMetadata());
11910
12083
  if (!sessionId) return {
@@ -12147,10 +12320,35 @@ ${sessions.map((session) => {
12147
12320
  case "open-logout":
12148
12321
  appendLocalMessage("Provider sign-out is managed by Fleet Prime CLI commands.");
12149
12322
  return true;
12150
- case "open-mcp":
12151
- openSettings("chat");
12152
- if (action.args) appendLocalMessage(`MCP: ${action.args}. Manage MCP connections with Fleet Prime CLI configuration.`);
12323
+ case "open-mcp": {
12324
+ openSettings("mcp");
12325
+ const parts = action.args.trim().split(/\s+/).filter(Boolean);
12326
+ const verb = parts[0];
12327
+ const target = parts.slice(1).join(" ");
12328
+ if (!verb || verb === "list" || (verb === "login" || verb === "reconnect") && !target) return true;
12329
+ if ((verb === "login" || verb === "reconnect") && target) {
12330
+ appendLocalMessage(`Open Settings \u2192 MCP and sign in to "${target}".`);
12331
+ return true;
12332
+ }
12333
+ if (verb === "logout" && target) {
12334
+ (async () => {
12335
+ try {
12336
+ const result = await chatClient.mcpOAuth({
12337
+ name: target,
12338
+ action: "logout"
12339
+ });
12340
+ if (result.connections) queryClient.setQueryData(chatQueryKeys.mcp, { connections: result.connections });
12341
+ queryClient.invalidateQueries({ queryKey: ["chat", "resources"] });
12342
+ appendLocalMessage(`Signed out of MCP connection "${target}".`);
12343
+ } catch (error) {
12344
+ appendLocalMessage(error instanceof Error ? error.message : `Could not sign out of "${target}".`);
12345
+ }
12346
+ })();
12347
+ return true;
12348
+ }
12349
+ appendLocalMessage(MCP_USAGE);
12153
12350
  return true;
12351
+ }
12154
12352
  case "fast-toggle":
12155
12353
  (async () => {
12156
12354
  appendLocalMessage("/fast toggles OpenAI Fast mode. The web port reads this from ~/.prime/agent/settings.json \u2014 flip `fastMode` there or in Settings.");
@@ -12211,6 +12409,7 @@ ${sessions.map((session) => {
12211
12409
  onForkPicker,
12212
12410
  openSettings,
12213
12411
  onOpenUIRequest,
12412
+ queryClient,
12214
12413
  sessions,
12215
12414
  setEffortPickerOpen,
12216
12415
  setModelKey,
@@ -12219,7 +12418,7 @@ ${sessions.map((session) => {
12219
12418
  startNewSession
12220
12419
  ]);
12221
12420
  const handleSlashCommandSelect = useCallback2((item) => {
12222
- if (item.id === "openui") return false;
12421
+ if (slashCommandInsertsPrefixOnSelect(item)) return false;
12223
12422
  const action = resolveLocalSlashAction(item.id);
12224
12423
  if (!action) return false;
12225
12424
  return applyLocalSlashAction(action);
@@ -12347,10 +12546,6 @@ function answerToRecordValue(answer) {
12347
12546
  if (answer.kind === "text") return typeof answer.text === "string" ? answer.text : "";
12348
12547
  return answer.selectedIds?.[0] ?? answer.text ?? "";
12349
12548
  }
12350
- function notifyChatError(error) {
12351
- if (isDaemonDisconnectError(error)) return;
12352
- notify.error(error instanceof Error ? error.message : String(error));
12353
- }
12354
12549
  function cleanStepText(text) {
12355
12550
  let cleaned = text.replace(/\*{1,2}([^*]+)\*{1,2}/g, "$1").replace(/`([^`]+)`/g, "$1").replace(/^(Use|Run|Execute|Create|Write|Read|Check|Verify|Update|Modify|Add|Remove|Delete|Install)\s+(the\s+)?/i, "").replace(/\s+/g, " ").trim();
12356
12551
  if (cleaned.length > 0) cleaned = `${cleaned.charAt(0).toUpperCase()}${cleaned.slice(1)}`;
@@ -12675,23 +12870,34 @@ function usePiChatSessionEvents({ client, presentationRef, sessionId, sessionMet
12675
12870
  if (!sessionId || typeof window === "undefined") return;
12676
12871
  const lastEventIdKey = `pi:sse:last-event-id:${sessionId}`;
12677
12872
  const sseCapabilitiesRef = { current: void 0 };
12678
- let lastEventId = Number.parseInt(window.sessionStorage.getItem(lastEventIdKey) ?? "0", 10);
12873
+ let lastEventId = Number.parseInt(readStoredValue(lastEventIdKey, "session") ?? "0", 10);
12679
12874
  if (Number.isNaN(lastEventId)) lastEventId = 0;
12680
12875
  let source = null;
12681
12876
  let reconnectTimer = null;
12877
+ let reconnectAttempt = 0;
12878
+ let reconnectNoticeShown = false;
12879
+ let lastAppliedRlmSeq = 0;
12682
12880
  let closedByEffect = false;
12683
- const handleEvent = (raw) => {
12881
+ let activeAssistantId;
12882
+ const handleEvent = (raw, seq) => {
12684
12883
  let frame2;
12685
12884
  try {
12686
12885
  frame2 = JSON.parse(raw.data);
12687
12886
  } catch {
12688
12887
  return;
12689
12888
  }
12889
+ if (frame2.type === "start") activeAssistantId = frame2.id;
12890
+ if (frame2.type === "done") activeAssistantId = void 0;
12891
+ const statusAtFrame = statusRef.current;
12690
12892
  if (frame2.type === "presentation") {
12691
12893
  if (frame2.presentation.revision > (presentationRef.current?.revision ?? -1)) setPresentationSynced(frame2.presentation);
12692
12894
  return;
12693
12895
  }
12694
12896
  if (frame2.type === "rlm") {
12897
+ if (!Number.isNaN(seq) && seq > 0) {
12898
+ if (seq <= lastAppliedRlmSeq) return;
12899
+ lastAppliedRlmSeq = seq;
12900
+ }
12695
12901
  const current = presentationRef.current;
12696
12902
  const existing = current.rlmChildren.find((child) => child.id === frame2.child.id);
12697
12903
  if (existing && existing.timestamp > frame2.child.timestamp) return;
@@ -12702,45 +12908,78 @@ function usePiChatSessionEvents({ client, presentationRef, sessionId, sessionMet
12702
12908
  });
12703
12909
  return;
12704
12910
  }
12705
- if (statusRef.current === "streaming" || statusRef.current === "submitted") return;
12706
- const connected = frame2;
12707
- if (connected.type === "connected") {
12708
- sseCapabilitiesRef.current = connected.adapterCapabilities;
12709
- setAdapterCapabilities(connected.adapterCapabilities);
12710
- return;
12711
- }
12712
- if (frame2.type === "reasoning") {
12713
- const messageId = frame2.messageId;
12714
- if (!sseCapabilitiesRef.current?.features.includes("reasoning-summary-v1") || !messageId) return;
12715
- setMessagesSynced((current) => upsertAssistantReasoningPresentation(current, messageId, frame2.presentation));
12716
- return;
12717
- }
12718
12911
  if (frame2.type === "tool" && frame2.part?.type === "tool-Question") {
12719
12912
  setMessagesSynced((current) => {
12720
12913
  const toolCallId = frame2.part.toolCallId ?? "";
12721
- if (current.some((message) => message.parts.some((part) => part.type !== "text" && part.type !== "error" && "toolCallId" in part && part.toolCallId === toolCallId))) return current;
12914
+ if (!toolCallId) return current;
12915
+ const hasToolCall = (message) => message.parts.some((part) => part.type !== "text" && part.type !== "error" && "toolCallId" in part && part.toolCallId === toolCallId);
12916
+ let targetIndex = frame2.messageId ? current.findIndex((message) => message.id === frame2.messageId && message.role === "assistant") : -1;
12917
+ if (targetIndex < 0 && activeAssistantId) targetIndex = current.findIndex((message) => message.id === activeAssistantId && message.role === "assistant");
12918
+ if (targetIndex < 0) {
12919
+ let latestAssistantWithoutToolCall = -1;
12920
+ let latestMatchingToolCall = -1;
12921
+ for (let index = current.length - 1; index >= 0; index -= 1) {
12922
+ const message = current[index];
12923
+ if (message.role !== "assistant") continue;
12924
+ if (hasToolCall(message) && latestMatchingToolCall < 0) latestMatchingToolCall = index;
12925
+ else if (latestAssistantWithoutToolCall < 0) latestAssistantWithoutToolCall = index;
12926
+ }
12927
+ targetIndex = frame2.part.state === "input-streaming" ? latestAssistantWithoutToolCall >= 0 ? latestAssistantWithoutToolCall : latestMatchingToolCall : latestMatchingToolCall >= 0 ? latestMatchingToolCall : latestAssistantWithoutToolCall;
12928
+ }
12722
12929
  const questionPart = {
12723
12930
  ...frame2.part,
12724
12931
  type: "tool-Question"
12725
12932
  };
12726
- return [...current, {
12727
- id: crypto.randomUUID(),
12933
+ if (targetIndex < 0) return [...current, {
12934
+ id: frame2.messageId ?? crypto.randomUUID(),
12728
12935
  role: "assistant",
12729
12936
  parts: [questionPart],
12730
12937
  createdAt: (/* @__PURE__ */ new Date()).toISOString()
12731
12938
  }];
12939
+ return current.flatMap((message, index) => {
12940
+ if (index === targetIndex) return [{
12941
+ ...message,
12942
+ parts: upsertToolPart(message.parts, questionPart)
12943
+ }];
12944
+ if (!hasToolCall(message)) return [message];
12945
+ const parts = message.parts.filter((part) => !(part.type !== "text" && part.type !== "error" && "toolCallId" in part && part.toolCallId === toolCallId));
12946
+ return parts.length > 0 ? [{
12947
+ ...message,
12948
+ parts
12949
+ }] : [];
12950
+ });
12732
12951
  });
12733
12952
  return;
12734
12953
  }
12954
+ if (statusRef.current === "streaming" || statusRef.current === "submitted") return;
12955
+ const connected = frame2;
12956
+ if (connected.type === "connected") {
12957
+ sseCapabilitiesRef.current = connected.adapterCapabilities;
12958
+ setAdapterCapabilities(connected.adapterCapabilities);
12959
+ if (connected.cursorReset) lastAppliedRlmSeq = 0;
12960
+ return;
12961
+ }
12962
+ if (frame2.type === "reasoning") {
12963
+ const messageId = frame2.messageId;
12964
+ if (!sseCapabilitiesRef.current?.features.includes("reasoning-summary-v1") || !messageId) return;
12965
+ setMessagesSynced((current) => upsertAssistantReasoningPresentation(current, messageId, frame2.presentation));
12966
+ return;
12967
+ }
12735
12968
  if (frame2.type === "state") {
12736
12969
  setActivityLabelSynced(typeof frame2.state?.message === "string" ? frame2.state.message : void 0);
12737
- if (frame2.state?.name === "agent_settled") client.loadSession({ sessionId }).then((result) => {
12738
- if (closedByEffect || sessionMetadataRef.current.sessionId !== sessionId) return;
12739
- setMessagesSynced(hydratePlanPresentationMessages(result.messages, result.planPresentations));
12740
- setPresentationSynced(result.presentation);
12741
- setSessionMetadataSynced(result.session);
12742
- setQueueSynced(EMPTY_QUEUE_STATE);
12743
- }).catch(() => void 0);
12970
+ if (frame2.state?.name === "agent_settled") {
12971
+ if (statusAtFrame === "streaming" || statusAtFrame === "submitted") return;
12972
+ const metadataSessionIdAtFrame = sessionMetadataRef.current.sessionId;
12973
+ client.loadSession({ sessionId }).then((result) => {
12974
+ if (closedByEffect || sessionMetadataRef.current.sessionId !== sessionId) return;
12975
+ if (sessionMetadataRef.current.sessionId !== metadataSessionIdAtFrame) return;
12976
+ if (statusRef.current === "streaming" || statusRef.current === "submitted") return;
12977
+ setMessagesSynced(hydratePlanPresentationMessages(result.messages, result.planPresentations));
12978
+ setPresentationSynced(result.presentation);
12979
+ setSessionMetadataSynced(result.session);
12980
+ setQueueSynced(EMPTY_QUEUE_STATE);
12981
+ }).catch(() => void 0);
12982
+ }
12744
12983
  return;
12745
12984
  }
12746
12985
  if (frame2.type === "queue") setQueueSynced({
@@ -12759,15 +12998,27 @@ function usePiChatSessionEvents({ client, presentationRef, sessionId, sessionMet
12759
12998
  const seq = Number.parseInt(event.lastEventId ?? "", 10);
12760
12999
  if (!Number.isNaN(seq) && seq > 0) {
12761
13000
  lastEventId = seq;
12762
- window.sessionStorage.setItem(lastEventIdKey, String(seq));
13001
+ writeStoredValue(lastEventIdKey, String(seq), "session");
13002
+ }
13003
+ if (reconnectAttempt > 0) {
13004
+ reconnectAttempt = 0;
13005
+ if (reconnectNoticeShown) {
13006
+ reconnectNoticeShown = false;
13007
+ if (statusRef.current !== "streaming" && statusRef.current !== "submitted") setActivityLabelSynced(void 0);
13008
+ }
12763
13009
  }
12764
- handleEvent(event);
13010
+ handleEvent(event, seq);
12765
13011
  };
12766
13012
  nextSource.onerror = () => {
12767
13013
  if (closedByEffect || source !== nextSource) return;
12768
13014
  nextSource.close();
13015
+ reconnectAttempt += 1;
13016
+ if (reconnectAttempt > 1 && statusRef.current !== "streaming" && statusRef.current !== "submitted") {
13017
+ reconnectNoticeShown = true;
13018
+ setActivityLabelSynced(reconnectAttempt > 2 ? `Reconnecting\u2026 (attempt ${reconnectAttempt})` : "Reconnecting\u2026");
13019
+ }
12769
13020
  if (reconnectTimer) clearTimeout(reconnectTimer);
12770
- reconnectTimer = setTimeout(connect, 2e3);
13021
+ reconnectTimer = setTimeout(connect, Math.min(2e3, 250 * 2 ** Math.min(reconnectAttempt, 3)));
12771
13022
  };
12772
13023
  };
12773
13024
  connect();
@@ -12819,6 +13070,10 @@ function usePiChatMessaging({ activityLabelRef, client, messagesRef, presentatio
12819
13070
  const streamAdmissionsRef = useRef2(/* @__PURE__ */ new Set());
12820
13071
  const queuedSubmissionTailRef = useRef2(RESOLVED_PROMISE);
12821
13072
  const adapterCapabilitiesRef = useRef2(void 0);
13073
+ const projectIdRef = useRef2(projectId);
13074
+ useEffect2(() => {
13075
+ projectIdRef.current = projectId;
13076
+ }, [projectId]);
12822
13077
  const findStreamAdmission = useCallback2((sessionId) => {
12823
13078
  for (const admission of streamAdmissionsRef.current) if (admission.sessionId === sessionId) return admission;
12824
13079
  }, []);
@@ -12863,7 +13118,7 @@ function usePiChatMessaging({ activityLabelRef, client, messagesRef, presentatio
12863
13118
  if (existing.sessionId) return existing;
12864
13119
  const inFlight = sessionCreatePromiseRef.current;
12865
13120
  if (inFlight) return inFlight;
12866
- const promise = client.createSession(projectId, signal).then((created) => {
13121
+ const promise = client.createSession(projectIdRef.current, signal).then((created) => {
12867
13122
  if (signal?.aborted) throw new Error("Session creation was aborted");
12868
13123
  setSessionMetadataSynced(created.session);
12869
13124
  setPresentationSynced(created.presentation);
@@ -12877,7 +13132,6 @@ function usePiChatMessaging({ activityLabelRef, client, messagesRef, presentatio
12877
13132
  return promise;
12878
13133
  }, [
12879
13134
  client,
12880
- projectId,
12881
13135
  refreshSessions,
12882
13136
  sessionMetadataRef,
12883
13137
  setPresentationSynced,
@@ -13026,22 +13280,21 @@ function usePiChatMessaging({ activityLabelRef, client, messagesRef, presentatio
13026
13280
  resetStreamAdmission,
13027
13281
  sendMessage: useCallback2(async ({ text, attachments, openUI, openUIArtifact, planAction, mode, altKey }) => {
13028
13282
  const trimmed = text.trim();
13029
- if (!trimmed) return;
13030
- if (status === "submitted" || status === "streaming" || findStreamAdmission(sessionMetadataRef.current.sessionId) !== void 0) {
13031
- try {
13032
- await enqueueDuringStream(trimmed, altKey ? "followUp" : "steer", {
13033
- attachments,
13034
- mode,
13035
- openUI,
13036
- openUIArtifact,
13037
- planAction
13038
- });
13039
- } catch (err) {
13040
- const nextError = err instanceof Error ? err : new Error(String(err));
13041
- setError(nextError);
13042
- notifyChatError(nextError);
13043
- }
13044
- return;
13283
+ if (!trimmed) return false;
13284
+ if (status === "submitted" || status === "streaming" || findStreamAdmission(sessionMetadataRef.current.sessionId) !== void 0) try {
13285
+ await enqueueDuringStream(trimmed, altKey ? "followUp" : "steer", {
13286
+ attachments,
13287
+ mode,
13288
+ openUI,
13289
+ openUIArtifact,
13290
+ planAction
13291
+ });
13292
+ return true;
13293
+ } catch (err) {
13294
+ const nextError = err instanceof Error ? err : new Error(String(err));
13295
+ setError(nextError);
13296
+ notifyChatError(nextError);
13297
+ return false;
13045
13298
  }
13046
13299
  setError(null);
13047
13300
  setActivityLabelSynced(void 0);
@@ -13059,7 +13312,7 @@ function usePiChatMessaging({ activityLabelRef, client, messagesRef, presentatio
13059
13312
  let terminalDoneSeen = false;
13060
13313
  try {
13061
13314
  const ensuredSession = await ensureSession(controller.signal);
13062
- if (controller.signal.aborted) return;
13315
+ if (controller.signal.aborted) return false;
13063
13316
  const ensuredStreamSessionId = ensuredSession.sessionId;
13064
13317
  if (!ensuredStreamSessionId) throw new Error("Unable to start a session stream");
13065
13318
  streamSessionId = ensuredStreamSessionId;
@@ -13087,23 +13340,25 @@ function usePiChatMessaging({ activityLabelRef, client, messagesRef, presentatio
13087
13340
  }
13088
13341
  if (sessionMetadataRef.current.sessionId === ensuredStreamSessionId && (terminalDoneSeen || !sessionStillRunning)) setStatus("ready");
13089
13342
  messagesRef.current.length;
13343
+ return true;
13090
13344
  } catch (err) {
13091
13345
  if (streamAdmissionsRef.current.delete(streamAdmission)) streamAdmission.reject(err);
13092
13346
  setMessagesSynced((current) => removeOptimisticUserMessage(current, userMessage.id));
13093
- if (controller.signal.aborted) return;
13347
+ if (controller.signal.aborted) return false;
13094
13348
  if (streamSessionId && sessionMetadataRef.current.sessionId !== streamSessionId) {
13095
13349
  refreshSessions();
13096
- return;
13350
+ return false;
13097
13351
  }
13098
13352
  const recoveryDeps = {
13099
13353
  setError,
13100
13354
  setStatus
13101
13355
  };
13102
- if (await tryRecoverForbiddenSession(err, recoverFromForbiddenSession, recoveryDeps) || await tryRecoverUnknownSession(err, recoverFromForbiddenSession, recoveryDeps)) return;
13356
+ if (await tryRecoverForbiddenSession(err, recoverFromForbiddenSession, recoveryDeps) || await tryRecoverUnknownSession(err, recoverFromForbiddenSession, recoveryDeps)) return false;
13103
13357
  const nextError = err instanceof Error ? err : new Error(String(err));
13104
13358
  setError(nextError);
13105
13359
  setStatus("error");
13106
13360
  notifyChatError(nextError);
13361
+ return false;
13107
13362
  } finally {
13108
13363
  if (streamAdmissionsRef.current.delete(streamAdmission)) streamAdmission.reject(/* @__PURE__ */ new Error("Chat stream ended before admission"));
13109
13364
  if (controller.signal.aborted) setMessagesSynced((current) => removeOptimisticUserMessage(current, userMessage.id));
@@ -13236,19 +13491,22 @@ function usePiChat(model, options) {
13236
13491
  artifactRuns: []
13237
13492
  }));
13238
13493
  const initialSessionMetadataRef = useRef2(initialSessionMetadata);
13494
+ const projectIdRef = useRef2(projectId);
13239
13495
  const messagesRef = useRef2(messages);
13240
13496
  const sessionMetadataRef = useRef2(sessionMetadata);
13241
13497
  const activityLabelRef = useRef2(activityLabel);
13242
13498
  const planLabelRef = useRef2(planLabel);
13243
13499
  const queueRef = useRef2(queue);
13244
13500
  const queueRevisionRef = useRef2(0);
13245
- const queuedDeletionTailRef = useRef2(Promise.resolve());
13501
+ const queuedMutationTailRef = useRef2(null);
13246
13502
  const presentationRef = useRef2(presentation);
13247
13503
  const pendingSendControllerRef = useRef2(null);
13248
13504
  const streamControllersRef = useRef2(/* @__PURE__ */ new Map());
13505
+ const refreshSessionsPromiseRef = useRef2(null);
13506
+ const resumeRequestRef = useRef2(0);
13249
13507
  const statusRef = useRef2(status);
13250
13508
  const initializedRef = useRef2(false);
13251
- const sendMessageRef = useRef2(() => Promise.resolve());
13509
+ const sendMessageRef = useRef2(() => Promise.resolve(false));
13252
13510
  const setMessagesSynced = useCallback2((updater) => {
13253
13511
  const next = typeof updater === "function" ? updater(messagesRef.current) : updater;
13254
13512
  messagesRef.current = next;
@@ -13305,14 +13563,26 @@ function usePiChat(model, options) {
13305
13563
  if (sessionMetadataRef.current.sessionId === sessionId) setPresentationSynced(result.presentation);
13306
13564
  return result.artifact.id;
13307
13565
  }, [client, setPresentationSynced]);
13566
+ useEffect2(() => {
13567
+ projectIdRef.current = projectId;
13568
+ }, [projectId]);
13308
13569
  const refreshSessions = useCallback2(async () => {
13309
- const nextSessions = await client.listSessions();
13310
- setSessions(nextSessions);
13311
- return nextSessions;
13570
+ const pendingRefresh = refreshSessionsPromiseRef.current;
13571
+ if (pendingRefresh) return pendingRefresh;
13572
+ const refreshRequest = client.listSessions().then((nextSessions) => {
13573
+ setSessions(nextSessions);
13574
+ return nextSessions;
13575
+ });
13576
+ refreshSessionsPromiseRef.current = refreshRequest;
13577
+ try {
13578
+ return await refreshRequest;
13579
+ } finally {
13580
+ if (refreshSessionsPromiseRef.current === refreshRequest) refreshSessionsPromiseRef.current = null;
13581
+ }
13312
13582
  }, [client]);
13313
13583
  const recoverFromForbiddenSession = useCallback2((projectIdOverride) => runForbiddenSessionRecovery({
13314
13584
  client,
13315
- projectId: projectIdOverride ?? projectId,
13585
+ projectId: projectIdOverride ?? projectIdRef.current,
13316
13586
  refreshSessions,
13317
13587
  setActivityLabelSynced,
13318
13588
  setError,
@@ -13324,7 +13594,6 @@ function usePiChat(model, options) {
13324
13594
  setStatus
13325
13595
  }), [
13326
13596
  client,
13327
- projectId,
13328
13597
  refreshSessions,
13329
13598
  setActivityLabelSynced,
13330
13599
  setMessagesSynced,
@@ -13422,18 +13691,6 @@ function usePiChat(model, options) {
13422
13691
  controllers.clear();
13423
13692
  };
13424
13693
  }, []);
13425
- useEffect2(() => {
13426
- let cancelled = false;
13427
- refreshSessions().catch((err) => {
13428
- if (cancelled) return;
13429
- const nextError = err instanceof Error ? err : new Error(String(err));
13430
- setError(nextError);
13431
- notifyChatError(nextError);
13432
- });
13433
- return () => {
13434
- cancelled = true;
13435
- };
13436
- }, [refreshSessions]);
13437
13694
  usePiChatBootstrap({
13438
13695
  client,
13439
13696
  initialSessionMetadataRef,
@@ -13494,37 +13751,45 @@ function usePiChat(model, options) {
13494
13751
  setActivityLabelSynced,
13495
13752
  setQueueSynced
13496
13753
  ]);
13497
- const deleteQueuedMessage = useCallback2((lane, index, expectedText) => {
13754
+ const mutateQueuedMessage = useCallback2((lane, index, expectedText, mutation, options2) => {
13498
13755
  const originatingSessionId = sessionMetadataRef.current.sessionId;
13499
13756
  const requestedRevision = queueRevisionRef.current;
13500
13757
  const requestedMatchCount = (lane === "steering" ? queueRef.current.steering : queueRef.current.followUp).filter((item) => item === expectedText).length;
13501
- const deletion = queuedDeletionTailRef.current.catch(() => void 0).then(async () => {
13758
+ const queuedMutation = (queuedMutationTailRef.current ?? Promise.resolve()).catch(() => void 0).then(async () => {
13502
13759
  if (!originatingSessionId || sessionMetadataRef.current.sessionId !== originatingSessionId) return false;
13760
+ const refuseStaleMutation = (expectedRace) => {
13761
+ if (!expectedRace && options2?.staleMessage) notifyChatError(new Error(options2.staleMessage));
13762
+ return false;
13763
+ };
13503
13764
  const current = queueRef.current;
13504
13765
  const items = lane === "steering" ? current.steering : current.followUp;
13505
13766
  let resolvedIndex;
13506
13767
  if (queueRevisionRef.current === requestedRevision) resolvedIndex = items[index] === expectedText ? index : void 0;
13507
13768
  else {
13508
- if (requestedMatchCount !== 1) return false;
13769
+ if (requestedMatchCount !== 1) return refuseStaleMutation(true);
13509
13770
  const currentMatches = items.reduce((matches2, item, itemIndex) => {
13510
13771
  if (item === expectedText) matches2.push(itemIndex);
13511
13772
  return matches2;
13512
13773
  }, []);
13513
13774
  resolvedIndex = currentMatches.length === 1 ? currentMatches[0] : void 0;
13514
13775
  }
13515
- if (resolvedIndex === void 0) return false;
13516
- const optimistic = {
13776
+ if (resolvedIndex === void 0) return refuseStaleMutation(queueRevisionRef.current !== requestedRevision);
13777
+ const optimistic = mutation.type === "delete" ? {
13517
13778
  ...current,
13518
13779
  [lane]: items.filter((_, itemIndex) => itemIndex !== resolvedIndex)
13780
+ } : {
13781
+ ...current,
13782
+ [lane]: items.map((item, itemIndex) => itemIndex === resolvedIndex ? mutation.text : item)
13519
13783
  };
13520
13784
  setQueueSynced(optimistic);
13521
13785
  const requestRevision = queueRevisionRef.current;
13522
13786
  try {
13523
- const result = await client.deleteQueuedMessage({
13787
+ const result = await client.mutateQueuedMessage({
13524
13788
  sessionId: originatingSessionId,
13525
13789
  lane,
13526
13790
  index: resolvedIndex,
13527
- expectedText
13791
+ expectedText,
13792
+ mutation
13528
13793
  });
13529
13794
  if (sessionMetadataRef.current.sessionId !== originatingSessionId || queueRevisionRef.current !== requestRevision) return result.status === "applied";
13530
13795
  setQueueSynced(result.queue);
@@ -13534,16 +13799,22 @@ function usePiChat(model, options) {
13534
13799
  throw queueError;
13535
13800
  }
13536
13801
  });
13537
- queuedDeletionTailRef.current = deletion.then(() => void 0, () => void 0);
13538
- return deletion;
13802
+ queuedMutationTailRef.current = queuedMutation.then(() => void 0, () => void 0);
13803
+ return queuedMutation;
13539
13804
  }, [client, setQueueSynced]);
13805
+ const deleteQueuedMessage = useCallback2((lane, index, expectedText) => mutateQueuedMessage(lane, index, expectedText, { type: "delete" }, { staleMessage: "The queued message changed before it could be deleted." }), [mutateQueuedMessage]);
13806
+ const editQueuedMessage = useCallback2((lane, index, expectedText, nextText) => mutateQueuedMessage(lane, index, expectedText, {
13807
+ type: "replace",
13808
+ text: nextText,
13809
+ lane
13810
+ }, { staleMessage: "The queued message changed before it could be updated." }), [mutateQueuedMessage]);
13540
13811
  const startNewSession = useCallback2(async (options2) => {
13541
13812
  if (options2?.preserveRunning === false) stop();
13542
13813
  else {
13543
13814
  invalidateQueueMutations();
13544
13815
  setStatus("ready");
13545
13816
  }
13546
- const result = await client.createSession(options2?.projectId ?? projectId);
13817
+ const result = await client.createSession(options2?.projectId ?? projectIdRef.current ?? projectId);
13547
13818
  setSessionMetadataSynced(result.session);
13548
13819
  setMessagesSynced([]);
13549
13820
  setPresentationSynced(result.presentation);
@@ -13566,10 +13837,14 @@ function usePiChat(model, options) {
13566
13837
  projectId
13567
13838
  ]);
13568
13839
  const resumeSession = useCallback2(async (metadata, options2) => {
13840
+ const requestId = resumeRequestRef.current + 1;
13841
+ resumeRequestRef.current = requestId;
13842
+ const isCurrent = () => resumeRequestRef.current === requestId;
13569
13843
  invalidateQueueMutations();
13570
13844
  try {
13571
13845
  if (options2?.preserveRunning === false) stop();
13572
13846
  const result = await client.resumeSession(metadata);
13847
+ if (!isCurrent()) return false;
13573
13848
  setSessionMetadataSynced(result.session);
13574
13849
  setMessagesSynced(hydratePlanPresentationMessages(result.messages, result.planPresentations));
13575
13850
  setPresentationSynced(result.presentation);
@@ -13578,14 +13853,18 @@ function usePiChat(model, options) {
13578
13853
  setPlanLabelSynced(void 0);
13579
13854
  setStatus(streamControllersRef.current.has(result.session.sessionId ?? "") ? "streaming" : "ready");
13580
13855
  await refreshSessions();
13856
+ if (!isCurrent()) return false;
13581
13857
  return true;
13582
13858
  } catch (err) {
13859
+ if (!isCurrent()) return false;
13583
13860
  const recoveryDeps = {
13584
13861
  setError,
13585
13862
  setStatus
13586
13863
  };
13587
13864
  const recover = () => recoverFromForbiddenSession(metadata.projectId);
13588
- if (await tryRecoverForbiddenSession(err, recover, recoveryDeps) || await tryRecoverUnknownSession(err, recover, recoveryDeps)) return false;
13865
+ const recovered = await tryRecoverForbiddenSession(err, recover, recoveryDeps) || await tryRecoverUnknownSession(err, recover, recoveryDeps);
13866
+ if (!isCurrent()) return false;
13867
+ if (recovered) return false;
13589
13868
  const nextError = err instanceof Error ? err : new Error(String(err));
13590
13869
  setError(nextError);
13591
13870
  setStatus("error");
@@ -13653,13 +13932,24 @@ function usePiChat(model, options) {
13653
13932
  });
13654
13933
  const enhancedMessages = useMemo2(() => enhanceMessages(messages), [messages, enhanceMessages]);
13655
13934
  const renameSession = useCallback2(async (sessionId, title) => {
13656
- await client.renameSession(sessionId, title);
13657
- await refreshSessions();
13935
+ try {
13936
+ await client.renameSession(sessionId, title);
13937
+ await refreshSessions();
13938
+ return true;
13939
+ } catch (err) {
13940
+ notifyChatError(err);
13941
+ return false;
13942
+ }
13658
13943
  }, [client, refreshSessions]);
13659
13944
  const deleteSession = useCallback2(async (sessionId) => {
13660
13945
  const deletingActive = sessionMetadataRef.current.sessionId === sessionId;
13661
13946
  if (deletingActive) stop();
13662
- await client.deleteSession(sessionId);
13947
+ try {
13948
+ await client.deleteSession(sessionId);
13949
+ } catch (err) {
13950
+ notifyChatError(err);
13951
+ return false;
13952
+ }
13663
13953
  if (deletingActive) {
13664
13954
  setSessionMetadataSynced({});
13665
13955
  setMessagesSynced([]);
@@ -13672,6 +13962,7 @@ function usePiChat(model, options) {
13672
13962
  });
13673
13963
  }
13674
13964
  await refreshSessions();
13965
+ return true;
13675
13966
  }, [
13676
13967
  client,
13677
13968
  refreshSessions,
@@ -13687,6 +13978,7 @@ function usePiChat(model, options) {
13687
13978
  answerQuestion,
13688
13979
  appendLocalMessage,
13689
13980
  deleteQueuedMessage,
13981
+ editQueuedMessage,
13690
13982
  deleteSession,
13691
13983
  error,
13692
13984
  getMessages: useCallback2(() => messagesRef.current, []),
@@ -13709,7 +14001,7 @@ function usePiChat(model, options) {
13709
14001
  switchProject
13710
14002
  };
13711
14003
  }
13712
- function useRightPanelContextValue({ activityLabel, artifactRuns, chatMode, handleThemePreferenceChange, isLoadingProviders, isUpdatingProvider, loadSession, loadSubagentSession, loadWorkspaceFile: loadWorkspaceFile2, messages, onOpenSubagentTab, modelKey, models, modelCatalog, onDiscoverModels, onOAuthLogin, onRemoveProvider, onUpdateProvider, openWorkspacePath, planLabel, presentation, providers, queue, refreshResources, refreshWorkspace, resources, resourcesError, resourcesLoading, rightPanel, reopenRightPanel, saveSettings, selectedArtifactId, sessionId, selectedWorkspacePath, setRightPanel, setSelectedWorkspacePath, settings, settingsError, settingsLoading, status, thinkingLevel, themePreference, workspaceError, workspaceLoading, workspaceTree }) {
14004
+ function useRightPanelContextValue({ activityLabel, artifactRuns, chatMode, handleThemePreferenceChange, isLoadingMcp, isLoadingProviders, isUpdatingMcp, isUpdatingProvider, loadSession, loadSubagentSession, loadWorkspaceFile: loadWorkspaceFile2, messages, onOpenSubagentTab, modelKey, models, modelCatalog, onDiscoverModels, onMcpOAuth, onOAuthLogin, onRemoveMcp, onRemoveProvider, onUpdateMcp, onUpdateProvider, openWorkspacePath, planLabel, presentation, mcpConnections, providers, queue, refreshResources, refreshWorkspace, resources, resourcesError, resourcesLoading, rightPanel, reopenRightPanel, saveSettings, selectedArtifactId, sessionId, selectedWorkspacePath, setRightPanel, setSelectedWorkspacePath, settings, settingsError, settingsLoading, status, thinkingLevel, themePreference, workspaceError, workspaceLoading, workspaceTree }) {
13713
14005
  const chatPanelData = useMemo2(() => ({
13714
14006
  activityLabel,
13715
14007
  artifactRuns,
@@ -13781,13 +14073,19 @@ function useRightPanelContextValue({ activityLabel, artifactRuns, chatMode, hand
13781
14073
  return {
13782
14074
  chatPanelData,
13783
14075
  settingsActions: useMemo2(() => ({
14076
+ isLoadingMcp,
13784
14077
  isLoadingProviders,
14078
+ isUpdatingMcp,
13785
14079
  isUpdatingProvider,
14080
+ mcpConnections,
13786
14081
  modelCatalog,
13787
14082
  onDiscoverModels,
14083
+ onMcpOAuth,
13788
14084
  onOAuthLogin,
14085
+ onRemoveMcp,
13789
14086
  onRemoveProvider,
13790
14087
  onThemePreferenceChange: handleThemePreferenceChange,
14088
+ onUpdateMcp,
13791
14089
  onUpdateProvider,
13792
14090
  providers,
13793
14091
  saveSettings,
@@ -13797,12 +14095,18 @@ function useRightPanelContextValue({ activityLabel, artifactRuns, chatMode, hand
13797
14095
  themePreference
13798
14096
  }), [
13799
14097
  handleThemePreferenceChange,
14098
+ isLoadingMcp,
13800
14099
  isLoadingProviders,
14100
+ isUpdatingMcp,
13801
14101
  isUpdatingProvider,
14102
+ mcpConnections,
13802
14103
  modelCatalog,
13803
14104
  onDiscoverModels,
14105
+ onMcpOAuth,
13804
14106
  onOAuthLogin,
14107
+ onRemoveMcp,
13805
14108
  onRemoveProvider,
14109
+ onUpdateMcp,
13806
14110
  onUpdateProvider,
13807
14111
  providers,
13808
14112
  saveSettings,
@@ -13868,10 +14172,14 @@ function useChatWorkspaceData() {
13868
14172
  if (user) ;
13869
14173
  }, [user]);
13870
14174
  const { data: providersData, isLoading: isLoadingProviders } = useChatProviders();
14175
+ const { data: mcpData, isLoading: isLoadingMcp } = useChatMcpConnections();
13871
14176
  const { data: projectsData, refetch: refetchProjects } = useChatProjects();
13872
14177
  const { mutateAsync: onUpdateProvider, isPending: isUpdatingProvider } = useUpdateChatProvider();
13873
14178
  const { mutateAsync: onOAuthLogin } = useOAuthLoginProvider();
13874
14179
  const { mutateAsync: onRemoveProvider, isPending: isRemovingProvider } = useRemoveChatProvider();
14180
+ const { mutateAsync: onUpdateMcp, isPending: isUpdatingMcp } = useUpdateMcpConnection();
14181
+ const { mutateAsync: onRemoveMcp, isPending: isRemovingMcp } = useRemoveMcpConnection();
14182
+ const { mutateAsync: onMcpOAuth } = useMcpOAuth();
13875
14183
  const { data: modelsData } = useChatModels(activeProjectId);
13876
14184
  const { data: modelCatalogData } = useChatModelCatalog({
13877
14185
  enabled: settingsDialogOpen,
@@ -13898,7 +14206,7 @@ function useChatWorkspaceData() {
13898
14206
  const { data: commandsData } = useChatCommands(activeProjectId);
13899
14207
  const { data: settingsData, isLoading: settingsLoading, error: settingsError } = useChatSettings(activeProjectId);
13900
14208
  const updateSettings = useUpdateChatSettings();
13901
- const { data: workspaceData, isLoading: workspaceLoading, error: workspaceError, refetch: refetchWorkspace } = useWorkspaceTree(activeProjectId, { enabled: true });
14209
+ const { data: workspaceData, isLoading: workspaceLoading, error: workspaceError, refetch: refetchWorkspace } = useWorkspaceTree(activeProjectId, { enabled: rightPanel === "workspace" || rightPanel === "resources" });
13902
14210
  const resources = resourcesData ?? null;
13903
14211
  const workspaceTree = workspaceData ?? null;
13904
14212
  const refreshResources = useCallback2(() => {
@@ -13921,7 +14229,7 @@ function useChatWorkspaceData() {
13921
14229
  const refreshWorkspace = useCallback2(() => {
13922
14230
  refetchWorkspace();
13923
14231
  }, [refetchWorkspace]);
13924
- const { activityLabel, answerQuestion, appendLocalMessage, deleteQueuedMessage, deleteSession, error, getMessages, getSessionMetadata, messages, planLabel, persistOpenUIArtifact, presentation, queue, renameSession, resumeSession, sendMessage, sessionMetadata, sessions, startNewSession, switchProject, status, stop } = usePiChat(modelSelection, {
14232
+ const { activityLabel, answerQuestion, appendLocalMessage, deleteQueuedMessage, editQueuedMessage, deleteSession, error, getMessages, getSessionMetadata, messages, planLabel, persistOpenUIArtifact, presentation, queue, renameSession, resumeSession, sendMessage, sessionMetadata, sessions, startNewSession, switchProject, status, stop } = usePiChat(modelSelection, {
13925
14233
  initialSessionMetadata,
13926
14234
  projectId: activeProjectId,
13927
14235
  persistSession
@@ -13947,15 +14255,29 @@ function useChatWorkspaceData() {
13947
14255
  setUploadedAttachments([]);
13948
14256
  setWorkspaceAttachments([]);
13949
14257
  }, []);
14258
+ const workspaceSessionCreatePromiseRef = useRef2(null);
13950
14259
  const startNewSessionForWorkspace = useCallback2(async (options) => {
13951
- const currentMetadata = getSessionMetadata();
13952
- const targetProjectId = options?.projectId ?? activeProjectId;
13953
- const shouldClear = shouldClearPendingAttachmentsForNewSession({
13954
- ...currentMetadata,
13955
- projectId: currentMetadata.projectId ?? activeProjectId
13956
- }, targetProjectId);
13957
- await startNewSession(options);
13958
- if (shouldClear) clearPendingAttachments();
14260
+ const key = `${options?.projectId ?? ""}::${options?.preserveRunning ?? ""}`;
14261
+ const inFlight = workspaceSessionCreatePromiseRef.current;
14262
+ if (inFlight && inFlight.key === key) return inFlight.promise;
14263
+ const promise = (async () => {
14264
+ const currentMetadata = getSessionMetadata();
14265
+ const targetProjectId = options?.projectId ?? activeProjectId;
14266
+ const shouldClear = shouldClearPendingAttachmentsForNewSession({
14267
+ ...currentMetadata,
14268
+ projectId: currentMetadata.projectId ?? activeProjectId
14269
+ }, targetProjectId);
14270
+ await startNewSession(options);
14271
+ if (shouldClear) clearPendingAttachments();
14272
+ return getSessionMetadata();
14273
+ })().finally(() => {
14274
+ if (workspaceSessionCreatePromiseRef.current?.promise === promise) workspaceSessionCreatePromiseRef.current = null;
14275
+ });
14276
+ workspaceSessionCreatePromiseRef.current = {
14277
+ key,
14278
+ promise
14279
+ };
14280
+ return promise;
13959
14281
  }, [
13960
14282
  activeProjectId,
13961
14283
  clearPendingAttachments,
@@ -14010,8 +14332,7 @@ function useChatWorkspaceData() {
14010
14332
  ]);
14011
14333
  const deleteSessionForWorkspace = useCallback2(async (sessionId) => {
14012
14334
  const deletingActiveSession = getSessionMetadata().sessionId === sessionId;
14013
- await deleteSession(sessionId);
14014
- if (deletingActiveSession) clearPendingAttachments();
14335
+ if (await deleteSession(sessionId) && deletingActiveSession) clearPendingAttachments();
14015
14336
  }, [
14016
14337
  clearPendingAttachments,
14017
14338
  deleteSession,
@@ -14065,8 +14386,7 @@ function useChatWorkspaceData() {
14065
14386
  (async () => {
14066
14387
  const files = Array.from(input.files ?? []);
14067
14388
  if (files.length === 0) return;
14068
- if (!getSessionMetadata().sessionId) await startNewSessionForWorkspace();
14069
- const sessionId = getSessionMetadata().sessionId;
14389
+ const sessionId = getSessionMetadata().sessionId ?? (await startNewSessionForWorkspace()).sessionId;
14070
14390
  if (!sessionId) throw new Error("Unable to create a session for attachments");
14071
14391
  const uploaded = await chatClient.uploadAttachments(sessionId, files);
14072
14392
  setUploadedAttachments((current) => [...current, ...uploaded]);
@@ -14081,6 +14401,10 @@ function useChatWorkspaceData() {
14081
14401
  }, []);
14082
14402
  const clearUploadedAttachments = useCallback2(() => setUploadedAttachments([]), []);
14083
14403
  const clearWorkspaceAttachments = useCallback2(() => setWorkspaceAttachments([]), []);
14404
+ const restoreAttachments = useCallback2((uploaded, workspace) => {
14405
+ if (uploaded.length > 0) setUploadedAttachments((current) => [...uploaded, ...current]);
14406
+ if (workspace.length > 0) setWorkspaceAttachments((current) => [...workspace, ...current]);
14407
+ }, []);
14084
14408
  const addWorkspaceAttachment = useCallback2((item) => {
14085
14409
  const relativePath = workspacePathFromSuggestion(item);
14086
14410
  if (!relativePath) return;
@@ -14156,22 +14480,23 @@ function useChatWorkspaceData() {
14156
14480
  modelKey,
14157
14481
  models,
14158
14482
  onForkPicker: setForkPickerEntries,
14159
- onOpenUIRequest: useCallback2((request) => {
14483
+ onOpenUIRequest: useCallback2(async (request) => {
14160
14484
  const attachments = [...workspaceAttachments, ...uploadedAttachments];
14161
14485
  clearUploadedAttachments();
14162
14486
  clearWorkspaceAttachments();
14163
- return sendMessage({
14487
+ if (!await sendMessage({
14164
14488
  text: request,
14165
14489
  altKey: false,
14166
14490
  mode: chatMode,
14167
14491
  openUI: true,
14168
14492
  openUIArtifact: true,
14169
14493
  attachments
14170
- });
14494
+ })) restoreAttachments(uploadedAttachments, workspaceAttachments);
14171
14495
  }, [
14172
14496
  chatMode,
14173
14497
  clearUploadedAttachments,
14174
14498
  clearWorkspaceAttachments,
14499
+ restoreAttachments,
14175
14500
  sendMessage,
14176
14501
  uploadedAttachments,
14177
14502
  workspaceAttachments
@@ -14203,7 +14528,9 @@ function useChatWorkspaceData() {
14203
14528
  artifactRuns,
14204
14529
  chatMode,
14205
14530
  handleThemePreferenceChange,
14531
+ isLoadingMcp,
14206
14532
  isLoadingProviders,
14533
+ isUpdatingMcp: isUpdatingMcp || isRemovingMcp,
14207
14534
  isUpdatingProvider: isUpdatingProvider || isRemovingProvider,
14208
14535
  loadSession: loadChatSession,
14209
14536
  loadSubagentSession,
@@ -14214,12 +14541,16 @@ function useChatWorkspaceData() {
14214
14541
  models,
14215
14542
  modelCatalog,
14216
14543
  onDiscoverModels,
14544
+ onMcpOAuth,
14217
14545
  onOAuthLogin,
14546
+ onRemoveMcp,
14218
14547
  onRemoveProvider,
14548
+ onUpdateMcp,
14219
14549
  onUpdateProvider,
14220
14550
  openWorkspacePath,
14221
14551
  planLabel,
14222
14552
  presentation,
14553
+ mcpConnections: mcpData?.connections ?? [],
14223
14554
  providers: providersData?.providers ?? [],
14224
14555
  queue,
14225
14556
  refreshResources,
@@ -14277,6 +14608,7 @@ function useChatWorkspaceData() {
14277
14608
  activityLabel,
14278
14609
  artifactRuns,
14279
14610
  deleteQueuedMessage,
14611
+ editQueuedMessage,
14280
14612
  error,
14281
14613
  messages,
14282
14614
  openArtifact,
@@ -14309,6 +14641,7 @@ function useChatWorkspaceData() {
14309
14641
  removeUploadedAttachment,
14310
14642
  removeWorkspaceAttachment,
14311
14643
  addWorkspaceAttachment,
14644
+ restoreAttachments,
14312
14645
  setChatMode,
14313
14646
  setEffortPickerOpen,
14314
14647
  setModelKey,
@@ -14346,7 +14679,7 @@ function useChatWorkspaceData() {
14346
14679
  }
14347
14680
  };
14348
14681
  }
14349
- var LazySubagentChatPanel = lazy(() => import("./subagent-chat-panel-DlSsM59d-DBW7DI3T.js").then(({ SubagentChatPanel }) => ({ default: SubagentChatPanel })));
14682
+ var LazySubagentChatPanel = lazy(() => import("./subagent-chat-panel-C0RpnXav-J7VYO7QY.js").then(({ SubagentChatPanel }) => ({ default: SubagentChatPanel })));
14350
14683
  function ChatWorkspaceShell() {
14351
14684
  const { session, conversation, composer, panels, dialogs, chrome, agentTabs } = useChatWorkspaceData();
14352
14685
  const toggleCommandPalette = useCallback2(() => {
@@ -14364,22 +14697,30 @@ function ChatWorkspaceShell() {
14364
14697
  });
14365
14698
  const activeProjectName = session.projects.find((project) => project.projectId === session.activeProjectId)?.name;
14366
14699
  const handleSend = useCallback2((text, altKey) => {
14367
- const attachments = [...composer.workspaceAttachments, ...composer.uploadedAttachments];
14700
+ const uploaded = [...composer.uploadedAttachments];
14701
+ const workspace = [...composer.workspaceAttachments];
14702
+ const attachments = [...workspace, ...uploaded];
14368
14703
  composer.clearUploadedAttachments();
14369
14704
  composer.clearWorkspaceAttachments();
14370
14705
  (async () => {
14371
- await conversation.sendMessage({
14372
- text,
14373
- altKey,
14374
- mode: composer.chatMode,
14375
- openUI: true,
14376
- attachments
14377
- });
14706
+ try {
14707
+ if (!await conversation.sendMessage({
14708
+ text,
14709
+ altKey,
14710
+ mode: composer.chatMode,
14711
+ openUI: true,
14712
+ attachments
14713
+ })) composer.restoreAttachments(uploaded, workspace);
14714
+ } catch (error) {
14715
+ composer.restoreAttachments(uploaded, workspace);
14716
+ notifyChatError(error);
14717
+ }
14378
14718
  })();
14379
14719
  }, [
14380
14720
  composer.chatMode,
14381
14721
  composer.clearUploadedAttachments,
14382
14722
  composer.clearWorkspaceAttachments,
14723
+ composer.restoreAttachments,
14383
14724
  composer.uploadedAttachments,
14384
14725
  composer.workspaceAttachments,
14385
14726
  conversation.sendMessage
@@ -14419,6 +14760,7 @@ function ChatWorkspaceShell() {
14419
14760
  artifactRuns: conversation.artifactRuns,
14420
14761
  queue: conversation.queue,
14421
14762
  onDeleteQueuedMessage: conversation.deleteQueuedMessage,
14763
+ onEditQueuedMessage: conversation.editQueuedMessage,
14422
14764
  onOpenArtifact: conversation.openArtifact,
14423
14765
  onOpenUIArtifactReady: handleOpenUIArtifactReady,
14424
14766
  inputSuggestionItems: composer.inputSuggestionItems,