@qredence/fleet 0.5.10 → 0.5.11

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 (103) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/dist/web/client/assets/agent-activity-CwMDU7aP.js +1 -0
  3. package/dist/web/client/assets/artifacts-panel-CQmFEF_H.js +1 -0
  4. package/dist/web/client/assets/{chat-command-palette-DfYSPPXI.js → chat-command-palette-CmHTS3rs.js} +1 -1
  5. package/dist/web/client/assets/{chat-C8XDWWXz.js → chat-yh02zgA7.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/{fleet-message-queue-zWM5-y18.js → fleet-message-queue-DUz6Hfrf.js} +1 -1
  8. package/dist/web/client/assets/{fleet-pi-tool-renderer-AJoMbXBa.js → fleet-pi-tool-renderer-BEDIO3al.js} +4 -4
  9. package/dist/web/client/assets/fleet-reasoning-panel-CbkO7u-v.js +1 -0
  10. package/dist/web/client/assets/{fleet-subagent-list-BnRnrWKS.js → fleet-subagent-list-iKUtLJKZ.js} +1 -1
  11. package/dist/web/client/assets/fleet-tool-timeline-C8heL7ae.js +1 -0
  12. package/dist/web/client/assets/{fork-picker-dialog-CkcSekBl.js → fork-picker-dialog-ByBOGVsa.js} +1 -1
  13. package/dist/web/client/assets/globals-B_I1Eq1u.css +2 -0
  14. package/dist/web/client/assets/horizontal-resize-qK6eRhIG.js +1 -0
  15. package/dist/web/client/assets/{index-DlnHLDpx.js → index-C1zOjrMK.js} +3 -3
  16. package/dist/web/client/assets/{ipython-tool-BrMePqD-.js → ipython-tool-ldJ9F1Cw.js} +1 -1
  17. package/dist/web/client/assets/model-selector-list-DsKTuAgS.js +1 -0
  18. package/dist/web/client/assets/{openui-renderer-DwYFJdbe.js → openui-renderer-J3dhPpL4.js} +5 -5
  19. package/dist/web/client/assets/prompt-input-qPIXZ-Rb.js +1 -0
  20. package/dist/web/client/assets/prompt-suggestions-Cc--lSNR.js +1 -0
  21. package/dist/web/client/assets/{provider-label-BCJh04J5.js → provider-label-Dpr7djG9.js} +1 -1
  22. package/dist/web/client/assets/repl-panel-DsPX04Xr.js +1 -0
  23. package/dist/web/client/assets/{resources-panel-Bo8dfUdm.js → resources-panel-D867-goy.js} +1 -1
  24. package/dist/web/client/assets/right-panel-registry-DewpBWHM.js +2 -0
  25. package/dist/web/client/assets/routes-vNkVToAF.js +16 -0
  26. package/dist/web/client/assets/safe-storage-s25GrfpH.js +1 -0
  27. package/dist/web/client/assets/session-insights-panel-YnaXvTpi.js +1 -0
  28. package/dist/web/client/assets/settings-dialog-B-v4me3Y.js +1 -0
  29. package/dist/web/client/assets/skeleton-loaders-C9vHwAYV.js +1 -0
  30. package/dist/web/client/assets/{subagent-chat-panel-DseoO31p.js → subagent-chat-panel-DkVUumrP.js} +1 -1
  31. package/dist/web/client/assets/subagent-transcript-D8wmQxXe.js +1 -0
  32. package/dist/web/client/assets/subagents-panel-BMp2Ego0.js +1 -0
  33. package/dist/web/client/assets/{surfaces-cW-gp56p.js → surfaces-DI-U-_2a.js} +1 -1
  34. package/dist/web/client/assets/tool-result-DfnPN0FQ.js +4 -0
  35. package/dist/web/client/assets/ui-preferences-CImQGZm_.js +1 -0
  36. package/dist/web/client/assets/virtualized-turn-list-DMJENRY0.js +6 -0
  37. package/dist/web/client/assets/{workspace-panel-DI1W3ce9.js → workspace-panel-G6yMpKJ8.js} +1 -1
  38. package/dist/web/client/bundle-budget.json +6 -6
  39. package/dist/web/server/{_tanstack-start-manifest_v-Cdx6hy2i-I7A5YJRU.js → _tanstack-start-manifest_v-po4woX6g-AUGCOEZ2.js} +14 -13
  40. package/dist/web/server/{agent-activity-B-JMvecd-SLE3GGY2.js → agent-activity-CS2rbF_C-A3R26CYH.js} +2 -2
  41. package/dist/web/server/{artifacts-panel-DLMK1O8P-42T45JMA.js → artifacts-panel-8GGUCtOd-X5TNKTY2.js} +12 -12
  42. package/dist/web/server/{chat-command-palette-CdYwoTMe-4LBAZF7K.js → chat-command-palette-Dgl5tqWn-72LLEWUD.js} +2 -2
  43. package/dist/web/server/{chunk-K5ESTT4A.js → chunk-7MDZVLIY.js} +11 -3
  44. package/dist/web/server/{chunk-EBCYJSBR.js → chunk-7SD2ZSEA.js} +3 -3
  45. package/dist/web/server/{chunk-M564UIEY.js → chunk-ABBWBBSS.js} +8 -8
  46. package/dist/web/server/{chunk-KNJUSMBT.js → chunk-BXWAUTTH.js} +2 -2
  47. package/dist/web/server/{chunk-54II5QXQ.js → chunk-ETTDO4UO.js} +6 -3
  48. package/dist/web/server/{chunk-EHNIN245.js → chunk-GETSIVNU.js} +5 -5
  49. package/dist/web/server/{chunk-NRDG2ISJ.js → chunk-GGT2ZKDB.js} +49 -49
  50. package/dist/web/server/{chunk-X2R5YPQZ.js → chunk-IJPCV6DH.js} +3 -2
  51. package/dist/web/server/{chunk-AJJ2S5FF.js → chunk-JQDLJ7KI.js} +20 -20
  52. package/dist/web/server/{chunk-VHBFU4TG.js → chunk-JUROEEWM.js} +43 -14
  53. package/dist/web/server/{chunk-TCH3U26B.js → chunk-MIW4LJTV.js} +2 -2
  54. package/dist/web/server/{chunk-2TRF62K5.js → chunk-N6NOTURM.js} +3 -3
  55. package/dist/web/server/{chunk-5XX7RKJ6.js → chunk-NXJ32VFR.js} +5 -5
  56. package/dist/web/server/{chunk-EOVMHQ2H.js → chunk-O4OTWWPF.js} +7 -7
  57. package/dist/web/server/{chunk-OB5OSYJK.js → chunk-RNOJACWQ.js} +53 -29
  58. package/dist/web/server/chunk-SZJUXVWG.js +40 -0
  59. package/dist/web/server/{chunk-6AW2XFTZ.js → chunk-WILCIZYU.js} +194 -10
  60. package/dist/web/server/{chunk-FED63ZHU.js → chunk-WKV2Z4KO.js} +10 -5
  61. package/dist/web/server/{chunk-ANL4B775.js → chunk-XLNCWZMZ.js} +2 -2
  62. package/dist/web/server/{chunk-GM32R7JW.js → chunk-YKVGQBZA.js} +10 -8
  63. package/dist/web/server/{chunk-3PIUR75R.js → chunk-YXXRP3NS.js} +9 -9
  64. package/dist/web/server/{fleet-message-queue-BxycG26e-2XLOTCLP.js → fleet-message-queue-j0DCU5Xy-5HKBHMPV.js} +2 -2
  65. package/dist/web/server/{fleet-pi-tool-renderer-RIeVlM9J-D6MISCQC.js → fleet-pi-tool-renderer-umKunT3K-O4GBH35V.js} +5 -5
  66. package/dist/web/server/{fleet-reasoning-panel-D_K48UOT-GN2PA6KT.js → fleet-reasoning-panel-BxC2COxi-GPLMQSTT.js} +9 -9
  67. package/dist/web/server/{fleet-subagent-list-5luKtpds-3OTVFHJQ.js → fleet-subagent-list-CpSYzCIq-JDH2LHSS.js} +1 -1
  68. package/dist/web/server/{fleet-tool-timeline-DwRqQgOj-HUFLGMDV.js → fleet-tool-timeline-IB36_PB2-XJENTO6I.js} +1 -1
  69. package/dist/web/server/{fork-picker-dialog-B9yGc8Au-IL63F2DN.js → fork-picker-dialog-DlINz9UQ-UWIXFDJX.js} +3 -3
  70. package/dist/web/server/{model-selector-list-cb2-ewoA-KIVU6LD3.js → model-selector-list-OYnzNbyu-HBGCNF2L.js} +5 -5
  71. package/dist/web/server/{openui-renderer-Czy5Vo2L-BLXPJD65.js → openui-renderer-Cj7kfqyL-EKJ6JTTQ.js} +4 -4
  72. package/dist/web/server/{prompt-suggestions-BOmHi4-J-C563CHFU.js → prompt-suggestions-D4AEEY7K-RZSP7PWV.js} +3 -3
  73. package/dist/web/server/{repl-panel-yyxhwe4c-7U6HXYPS.js → repl-panel-D5KsoJik-BQKO53JO.js} +9 -9
  74. package/dist/web/server/{resources-panel-j4fAIi9g-5C267IXV.js → resources-panel-CE5pD4vy-V5FXBTYC.js} +2 -2
  75. package/dist/web/server/{router-CgSWrAYc-5UBYSZTJ.js → router-Ci1wxI7I-E2AYMNON.js} +253 -76
  76. package/dist/web/server/{routes-CP_BBhD0-BAWQYGKY.js → routes-CRpm9-Sa-IYK6MUJO.js} +705 -537
  77. package/dist/web/server/server.js +2 -2
  78. package/dist/web/server/{session-insights-panel-BHZyKDTo-LRMAMA3O.js → session-insights-panel-CUhdgvRt-VB2HUCQP.js} +4 -4
  79. package/dist/web/server/{settings-dialog-CxHe8nym-KKXDPTIW.js → settings-dialog-BvkgNflv-GPJ6COQO.js} +14 -10
  80. package/dist/web/server/{subagent-chat-panel-DlSsM59d-DBW7DI3T.js → subagent-chat-panel-CMuvW9Sd-M5TEEGQW.js} +11 -11
  81. package/dist/web/server/{subagents-panel-Txzk8oDb-NRKLASYN.js → subagents-panel-DgfB6_Yy-4INEPE3Y.js} +13 -13
  82. package/dist/web/server/{workspace-panel-BOs-58Cv-SWQBMZSB.js → workspace-panel-bpwj-Veu-Q2CEJMN4.js} +4 -3
  83. package/package.json +1 -1
  84. package/dist/web/client/assets/agent-activity-CDcDNVC6.js +0 -1
  85. package/dist/web/client/assets/artifacts-panel-CObI-DMt.js +0 -1
  86. package/dist/web/client/assets/fleet-reasoning-panel-MtbSdoCv.js +0 -1
  87. package/dist/web/client/assets/fleet-tool-timeline-COzPrwr8.js +0 -1
  88. package/dist/web/client/assets/generative-text-renderer-CDKHv-v_.js +0 -6
  89. package/dist/web/client/assets/globals-DisQPFtV.css +0 -2
  90. package/dist/web/client/assets/horizontal-resize-Bl3AyBJg.js +0 -1
  91. package/dist/web/client/assets/model-selector-list-DQaPFUYt.js +0 -1
  92. package/dist/web/client/assets/prompt-input-DZ4cho_e.js +0 -1
  93. package/dist/web/client/assets/prompt-suggestions-CXM6knMK.js +0 -1
  94. package/dist/web/client/assets/repl-panel-BDQ5MEgV.js +0 -1
  95. package/dist/web/client/assets/right-panel-registry-VVRPktV3.js +0 -2
  96. package/dist/web/client/assets/routes-DAikUNzO.js +0 -16
  97. package/dist/web/client/assets/session-insights-panel-CQdT90Op.js +0 -1
  98. package/dist/web/client/assets/settings-dialog-DS64KmwC.js +0 -1
  99. package/dist/web/client/assets/skeleton-loaders-DjGv9LLA.js +0 -1
  100. package/dist/web/client/assets/subagent-transcript-cxVKYnh9.js +0 -1
  101. package/dist/web/client/assets/subagents-panel-CHC96I68.js +0 -1
  102. package/dist/web/client/assets/tool-result-Baj3CdL_.js +0 -4
  103. package/dist/web/client/assets/ui-preferences-DUEFuJFj.js +0 -1
@@ -21,12 +21,12 @@ import {
21
21
  useMutation,
22
22
  useQuery,
23
23
  useQueryClient
24
- } from "./chunk-VHBFU4TG.js";
24
+ } from "./chunk-JUROEEWM.js";
25
25
  import {
26
26
  Library,
27
27
  RIGHT_PANEL_LAUNCHER_DEFINITIONS,
28
28
  getRightPanelDefinition
29
- } from "./chunk-EOVMHQ2H.js";
29
+ } from "./chunk-O4OTWWPF.js";
30
30
  import {
31
31
  AlertDialog,
32
32
  AlertDialogAction,
@@ -51,7 +51,7 @@ import {
51
51
  useHoverFloatingInteraction,
52
52
  useHoverReferenceInteraction,
53
53
  usePopupHandleStore
54
- } from "./chunk-TCH3U26B.js";
54
+ } from "./chunk-MIW4LJTV.js";
55
55
  import {
56
56
  RightPanelProvider,
57
57
  useChatPanelDataContext,
@@ -66,7 +66,7 @@ import {
66
66
  PromptInput,
67
67
  useHydrated,
68
68
  usePopoverPortalPosition
69
- } from "./chunk-GM32R7JW.js";
69
+ } from "./chunk-YKVGQBZA.js";
70
70
  import "./chunk-7CNGNFFK.js";
71
71
  import {
72
72
  Plus
@@ -81,10 +81,11 @@ import {
81
81
  MessageContent,
82
82
  MessageScroller,
83
83
  UserMessage,
84
+ VirtualizedTurnList,
84
85
  buildAssistantElements,
85
86
  groupMessages,
86
87
  normalizeAssistantToolParts
87
- } from "./chunk-6AW2XFTZ.js";
88
+ } from "./chunk-WILCIZYU.js";
88
89
  import "./chunk-FJV6EQDW.js";
89
90
  import {
90
91
  RefreshCw
@@ -105,14 +106,14 @@ import {
105
106
  MessageCircleQuestionMark,
106
107
  PI_TOOL_RENDERERS,
107
108
  useHoverCapable
108
- } from "./chunk-2TRF62K5.js";
109
+ } from "./chunk-N6NOTURM.js";
109
110
  import "./chunk-QPNUGF3V.js";
110
111
  import {
111
112
  field,
112
113
  floating,
113
114
  mono,
114
115
  paper
115
- } from "./chunk-ANL4B775.js";
116
+ } from "./chunk-XLNCWZMZ.js";
116
117
  import "./chunk-BLSX7WHW.js";
117
118
  import {
118
119
  Sparkles
@@ -136,11 +137,16 @@ import {
136
137
  thinkingLevelLabel,
137
138
  toModelOption,
138
139
  toModelSelection
139
- } from "./chunk-FED63ZHU.js";
140
+ } from "./chunk-WKV2Z4KO.js";
140
141
  import "./chunk-QK4CHLVV.js";
141
142
  import {
142
143
  Folder
143
144
  } from "./chunk-GS2IZGRC.js";
145
+ import {
146
+ readStoredValue,
147
+ removeStoredValue,
148
+ writeStoredValue
149
+ } from "./chunk-SZJUXVWG.js";
144
150
  import {
145
151
  resolveWorkspacePanelTarget
146
152
  } from "./chunk-P66QQWUM.js";
@@ -224,7 +230,7 @@ import {
224
230
  Badge,
225
231
  UiErrorBoundary,
226
232
  decodeOpenPanelActionMessage
227
- } from "./chunk-KNJUSMBT.js";
233
+ } from "./chunk-BXWAUTTH.js";
228
234
  import {
229
235
  ChatOpenUIArtifactUpsertRequestSchema,
230
236
  ChatOpenUIArtifactUpsertResponseSchema,
@@ -248,7 +254,7 @@ import {
248
254
  UploadedAttachmentSchema,
249
255
  WorkspaceRelativePathSchema,
250
256
  external_exports
251
- } from "./chunk-NRDG2ISJ.js";
257
+ } from "./chunk-GGT2ZKDB.js";
252
258
  import {
253
259
  CompositeList,
254
260
  Select,
@@ -409,7 +415,7 @@ import "./chunk-JDCCC7A7.js";
409
415
  import "./chunk-L547YHC4.js";
410
416
  import "./chunk-MLKGABMK.js";
411
417
 
412
- // web/app/dist/server/assets/routes-CP_BBhD0.js
418
+ // web/app/dist/server/assets/routes-CRpm9-Sa.js
413
419
  import * as React$1 from "react";
414
420
  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
421
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
@@ -1231,139 +1237,6 @@ function agentTabTriggerId(tabId) {
1231
1237
  function agentTabPanelId(tabId) {
1232
1238
  return `agent-tab-panel-${encodeURIComponent(tabId)}`;
1233
1239
  }
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
1240
  function ResizableCanvas({ children, dataTestid, headerLeading, loading, onClose, onRefresh, onResizeStart, open, headerActions, title, titleIcon: TitleIcon, width }) {
1368
1241
  const reduceMotion = useReducedMotion();
1369
1242
  const panelRef = useRef2(null);
@@ -1418,7 +1291,7 @@ function ResizableCanvas({ children, dataTestid, headerLeading, loading, onClose
1418
1291
  children: [/* @__PURE__ */ jsx("div", {
1419
1292
  className: "min-w-0 flex-1",
1420
1293
  children: headerLeading ?? /* @__PURE__ */ jsxs("div", {
1421
- className: "flex min-w-0 items-center gap-2 text-[13px] font-medium text-foreground/80",
1294
+ className: "flex min-w-0 items-center gap-2 text-[0.8125rem] font-medium text-foreground/80",
1422
1295
  children: [/* @__PURE__ */ jsx(TitleIcon, { className: "size-3.5 shrink-0" }), /* @__PURE__ */ jsx("span", { children: title })]
1423
1296
  })
1424
1297
  }), /* @__PURE__ */ jsxs("div", {
@@ -2426,7 +2299,7 @@ var TabsSubtleItem = forwardRef2(({ icon: Icon, label, index, badge, className,
2426
2299
  const tone = chromeTone(isPill, isActive);
2427
2300
  const ariaLabel = ariaLabelProp ?? (collapseLabel && !showLabel ? label : void 0);
2428
2301
  const labelContent = /* @__PURE__ */ jsxs("span", {
2429
- className: cn("inline-grid whitespace-nowrap", isPill ? "text-[12px] font-medium" : "text-[13px]"),
2302
+ className: cn("inline-grid whitespace-nowrap", isPill ? "text-[0.75rem] font-medium" : "text-[0.8125rem]"),
2430
2303
  children: [/* @__PURE__ */ jsx("span", {
2431
2304
  className: "invisible col-start-1 row-start-1 [text-box:trim-both_cap_alphabetic]",
2432
2305
  style: { fontVariationSettings: fontWeights.semibold },
@@ -2465,7 +2338,7 @@ var TabsSubtleItem = forwardRef2(({ icon: Icon, label, index, badge, className,
2465
2338
  strokeWidth: isActive ? 2 : 1.5,
2466
2339
  className: cn("shrink-0 transition-[color,stroke-width] duration-80", tone)
2467
2340
  }), badge !== void 0 ? /* @__PURE__ */ jsx("span", {
2468
- className: cn("text-[11px] tabular-nums transition-colors duration-80", tone),
2341
+ className: cn("text-[0.6875rem] tabular-nums transition-colors duration-80", tone),
2469
2342
  children: badge
2470
2343
  }) : null]
2471
2344
  }) : null,
@@ -2526,7 +2399,7 @@ function ChromePillButton({ active = false, ariaLabel, className, title, ...prop
2526
2399
  title: title ?? ariaLabel
2527
2400
  });
2528
2401
  }
2529
- var COMPACT_TABS_CLASS = "[&_[data-proximity-index]]:!h-7 [&_[data-proximity-index]]:!px-2 [&_[data-proximity-index]]:!text-[11px]";
2402
+ var COMPACT_TABS_CLASS = "[&_[data-proximity-index]]:!h-7 [&_[data-proximity-index]]:!px-2 [&_[data-proximity-index]]:!text-[0.6875rem]";
2530
2403
  function RightPanelLauncherFromContext({ compact = false } = {}) {
2531
2404
  const { reopenRightPanel, rightPanel } = useChatPanelDataContext();
2532
2405
  return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("div", {
@@ -2686,8 +2559,13 @@ function MobilePanel({ children, dataTestid, headerActions, icon: Icon, onClose,
2686
2559
  const panelTitleId = useId();
2687
2560
  const suppressCloseRef = useRef2(false);
2688
2561
  const onLightDismiss = useEffectEvent((event) => {
2689
- if (panelRef.current && event.target === panelRef.current) onClose?.();
2562
+ if (panelRef.current && event.target === panelRef.current) panelRef.current.close();
2690
2563
  });
2564
+ const handleHeaderClose = () => {
2565
+ const dialog = panelRef.current;
2566
+ if (dialog && dialog.open) dialog.close();
2567
+ else onClose?.();
2568
+ };
2691
2569
  useEffect2(() => {
2692
2570
  if (!open) return;
2693
2571
  const dialog = panelRef.current;
@@ -2749,7 +2627,7 @@ function MobilePanel({ children, dataTestid, headerActions, icon: Icon, onClose,
2749
2627
  title && /* @__PURE__ */ jsxs("div", {
2750
2628
  className: "flex h-10 shrink-0 items-center justify-between gap-2 border-b border-border/60 px-3",
2751
2629
  children: [/* @__PURE__ */ jsxs("div", {
2752
- className: "flex min-w-0 items-center gap-2 text-[13px] font-medium text-foreground/80",
2630
+ className: "flex min-w-0 items-center gap-2 text-[0.8125rem] font-medium text-foreground/80",
2753
2631
  children: [Icon && /* @__PURE__ */ jsx(Icon, { className: "size-3.5 shrink-0" }), /* @__PURE__ */ jsx("span", {
2754
2632
  className: "truncate",
2755
2633
  children: title
@@ -2758,7 +2636,7 @@ function MobilePanel({ children, dataTestid, headerActions, icon: Icon, onClose,
2758
2636
  className: "flex shrink-0 items-center gap-1",
2759
2637
  children: [headerActions, onClose && /* @__PURE__ */ jsx(Button, {
2760
2638
  type: "button",
2761
- onClick: onClose,
2639
+ onClick: handleHeaderClose,
2762
2640
  variant: "ghost",
2763
2641
  size: "icon-sm",
2764
2642
  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 +2657,33 @@ function MobilePanel({ children, dataTestid, headerActions, icon: Icon, onClose,
2779
2657
  })
2780
2658
  });
2781
2659
  }
2660
+ var DESKTOP_PANEL_QUERY = `(min-width: 960px)`;
2661
+ function subscribeToDesktopPanel(onChange) {
2662
+ if (typeof window === "undefined" || typeof window.matchMedia !== "function") return () => void 0;
2663
+ const media = window.matchMedia(DESKTOP_PANEL_QUERY);
2664
+ media.addEventListener("change", onChange);
2665
+ return () => media.removeEventListener("change", onChange);
2666
+ }
2667
+ function getDesktopPanelSnapshot() {
2668
+ return typeof window !== "undefined" && typeof window.matchMedia === "function" ? window.matchMedia(DESKTOP_PANEL_QUERY).matches : false;
2669
+ }
2670
+ function getServerDesktopPanelSnapshot() {
2671
+ return false;
2672
+ }
2673
+ function useIsDesktopPanel() {
2674
+ return useSyncExternalStore(subscribeToDesktopPanel, getDesktopPanelSnapshot, getServerDesktopPanelSnapshot);
2675
+ }
2782
2676
  function RightPanelShell({ handleResourceCanvasResizeStart, onClose, resourceCanvasWidth }) {
2783
2677
  const chat = useChatPanelDataContext();
2784
2678
  const workspace = useWorkspaceTreeContext();
2785
2679
  const { rightPanel } = chat;
2786
2680
  const panelOpen = rightPanel !== null;
2681
+ const isDesktop = useIsDesktopPanel();
2787
2682
  const definition = rightPanel ? getRightPanelDefinition(rightPanel) : null;
2788
2683
  const PanelContent = definition?.component;
2789
2684
  const loading = definition?.loadingSource === "resources" ? chat.resourcesLoading : definition?.loadingSource === "workspace" ? workspace.workspaceLoading : false;
2790
2685
  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, {
2686
+ return /* @__PURE__ */ jsx(Fragment$1, { children: isDesktop ? /* @__PURE__ */ jsx(ResizableCanvas, {
2799
2687
  dataTestid: definition?.dataTestid,
2800
2688
  headerLeading: /* @__PURE__ */ jsx(RightPanelTabsFromContext, { idPrefix: "right-panel-desktop" }),
2801
2689
  loading,
@@ -2807,7 +2695,14 @@ function RightPanelShell({ handleResourceCanvasResizeStart, onClose, resourceCan
2807
2695
  titleIcon: definition?.icon ?? Library,
2808
2696
  width: resourceCanvasWidth,
2809
2697
  children: PanelContent ? /* @__PURE__ */ jsx(PanelContent, {}) : null
2810
- })] });
2698
+ }) : /* @__PURE__ */ jsx(MobilePanel, {
2699
+ dataTestid: definition?.mobileDataTestid,
2700
+ icon: definition?.icon,
2701
+ onClose,
2702
+ open: panelOpen,
2703
+ title: definition?.title ?? "",
2704
+ children: PanelContent ? /* @__PURE__ */ jsx(PanelContent, {}) : null
2705
+ }) });
2811
2706
  }
2812
2707
  var layoutStyle = {
2813
2708
  "--chat-chrome-top": `52px`,
@@ -2823,7 +2718,7 @@ function ChatWorkspaceLayout({ children, headerCenter, headerLeft, headerRight,
2823
2718
  className: "relative flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden",
2824
2719
  "data-testid": "chat-column",
2825
2720
  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"),
2721
+ 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
2722
  "data-testid": "chat-header",
2828
2723
  children: [
2829
2724
  /* @__PURE__ */ jsx("div", {
@@ -3277,7 +3172,7 @@ var AnimatedSidebarGroupLabel = forwardRef2(function AnimatedSidebarGroupLabel2(
3277
3172
  ref: forwardedRef,
3278
3173
  "aria-hidden": collapsed,
3279
3174
  "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),
3175
+ 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
3176
  children
3282
3177
  });
3283
3178
  });
@@ -3393,8 +3288,7 @@ function directoryErrorMessage(error, fallback) {
3393
3288
  return error instanceof Error && error.message.trim() ? error.message : fallback;
3394
3289
  }
3395
3290
  function readExpandedProjects(activeProjectId) {
3396
- if (typeof window === "undefined") return activeProjectId ? [projectResourceId(activeProjectId)] : [];
3397
- const stored = window.localStorage.getItem(EXPANDED_PROJECTS_STORAGE_KEY);
3291
+ const stored = readStoredValue(EXPANDED_PROJECTS_STORAGE_KEY);
3398
3292
  if (!stored) return activeProjectId ? [projectResourceId(activeProjectId)] : [];
3399
3293
  try {
3400
3294
  const parsed = JSON.parse(stored);
@@ -3602,7 +3496,7 @@ function useFleetSessionSidebarViewModel({ sessions, projects = EMPTY_PROJECTS,
3602
3496
  setExpandedProjectIds((current) => current.includes(resourceId) ? current : [...current, resourceId]);
3603
3497
  }, [activeProjectId, setExpandedProjectIds]);
3604
3498
  useEffect2(() => {
3605
- window.localStorage.setItem(EXPANDED_PROJECTS_STORAGE_KEY, JSON.stringify(expandedProjectIds));
3499
+ writeStoredValue(EXPANDED_PROJECTS_STORAGE_KEY, JSON.stringify(expandedProjectIds));
3606
3500
  }, [expandedProjectIds]);
3607
3501
  const sidebarItems = useMemo2(() => {
3608
3502
  const grouped = sortedProjects.map((project) => {
@@ -4458,7 +4352,7 @@ function ThreadSearch({ threads, query, activeId, onQueryChange, onSelect, class
4458
4352
  children: [/* @__PURE__ */ jsxs("span", {
4459
4353
  className: "flex items-center gap-1.5",
4460
4354
  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]",
4355
+ className: "min-w-0 flex-1 truncate text-[0.8125rem]",
4462
4356
  children: thread.title
4463
4357
  })]
4464
4358
  }), /* @__PURE__ */ jsx("span", {
@@ -4482,13 +4376,13 @@ function ThreadSearch({ threads, query, activeId, onQueryChange, onSelect, class
4482
4376
  onKeyDown,
4483
4377
  placeholder: "Search threads",
4484
4378
  "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]"
4379
+ className: "text-foreground/85 placeholder:text-foreground/30 min-w-0 flex-1 bg-transparent text-base outline-none md:text-[0.8125rem]"
4486
4380
  })]
4487
4381
  }),
4488
4382
  pinned.length > 0 && /* @__PURE__ */ jsxs("div", {
4489
4383
  className: "flex flex-col",
4490
4384
  children: [/* @__PURE__ */ jsx("span", {
4491
- className: cn("font-mono text-[11px] tracking-tight", "text-foreground/25 px-2 pb-1"),
4385
+ className: cn("font-mono text-[0.6875rem] tracking-tight", "text-foreground/25 px-2 pb-1"),
4492
4386
  children: "pinned"
4493
4387
  }), pinned.map(row)]
4494
4388
  }),
@@ -4512,7 +4406,7 @@ function ThreadSearch({ threads, query, activeId, onQueryChange, onSelect, class
4512
4406
  }
4513
4407
  function fleetVersion() {
4514
4408
  try {
4515
- return "0.5.10";
4409
+ return "0.5.11";
4516
4410
  } catch {
4517
4411
  return "dev";
4518
4412
  }
@@ -4523,7 +4417,7 @@ function FleetVersionBadge() {
4523
4417
  variant: "secondary",
4524
4418
  title: `Fleet ${version}`,
4525
4419
  "aria-label": `Fleet version ${version}`,
4526
- className: "shrink-0 font-mono text-[10px] font-normal text-muted-foreground",
4420
+ className: "shrink-0 font-mono text-[0.625rem] font-normal text-muted-foreground",
4527
4421
  children: ["v", version]
4528
4422
  });
4529
4423
  }
@@ -4751,7 +4645,7 @@ function ResourceActionMenu({ item, menuOpen, onMenuOpenChange, onRenameStart, r
4751
4645
  });
4752
4646
  }
4753
4647
  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");
4648
+ 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
4649
  }
4756
4650
  function useResourceRowEvents({ acceptsChildren, allowMove, disabled: disabled2, kind, onContainerSelect, onDragEnd, onDragOver, onDragStart, onDrop, onRenameStart, onSelect, renaming, row }) {
4757
4651
  const draggedRef = useRef2(false);
@@ -4934,7 +4828,7 @@ function ResourceList({ flat, selectedId, activeContainerId, expandedIds, focuse
4934
4828
  }), draggingId ? /* @__PURE__ */ jsx("div", {
4935
4829
  "aria-hidden": "true",
4936
4830
  "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",
4831
+ 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
4832
  children: "Move to top level"
4939
4833
  }) : null]
4940
4834
  }), /* @__PURE__ */ jsx("span", {
@@ -5507,7 +5401,7 @@ function ProjectFolder({ title, description = "Updated recently", previews = [],
5507
5401
  "aria-hidden": "true",
5508
5402
  className: "pointer-events-none absolute inset-0",
5509
5403
  children: /* @__PURE__ */ jsx("span", {
5510
- className: "absolute left-1/2 top-0 block h-0 w-0",
5404
+ className: "absolute left-1/2 top-0 block size-0",
5511
5405
  children: /* @__PURE__ */ jsx(AnimatePresence, {
5512
5406
  initial: false,
5513
5407
  children: !isExpanded ? previewItems.map((preview, index) => {
@@ -5718,7 +5612,7 @@ function SidebarMenuItem({ icon: Icon, label, onClick, href }) {
5718
5612
  }
5719
5613
  function KbdHint({ children }) {
5720
5614
  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",
5615
+ className: "rounded border border-border/60 bg-muted/60 px-1 font-mono text-[0.625rem] leading-4 text-muted-foreground",
5722
5616
  children
5723
5617
  });
5724
5618
  }
@@ -5816,7 +5710,7 @@ function FleetSessionSidebarNavigation({ brandMenuOpen, setBrandMenuOpen, search
5816
5710
  /* @__PURE__ */ jsxs("div", {
5817
5711
  className: "border-t border-border/60 px-2 pb-2 pt-1.5",
5818
5712
  children: [/* @__PURE__ */ jsx("span", {
5819
- className: "px-2 pb-1 font-mono text-[10px] uppercase tracking-[0.14em] text-muted-foreground/60",
5713
+ className: "px-2 pb-1 font-mono text-[0.625rem] uppercase tracking-[0.14em] text-muted-foreground/60",
5820
5714
  children: "Projects"
5821
5715
  }), /* @__PURE__ */ jsxs("div", {
5822
5716
  className: "mt-1 flex flex-col gap-0.5",
@@ -5831,12 +5725,12 @@ function FleetSessionSidebarNavigation({ brandMenuOpen, setBrandMenuOpen, search
5831
5725
  children: project.name
5832
5726
  }),
5833
5727
  /* @__PURE__ */ jsx("span", {
5834
- className: "max-w-24 truncate text-[10px] text-muted-foreground/55",
5728
+ className: "max-w-24 truncate text-[0.625rem] text-muted-foreground/55",
5835
5729
  children: project.pathLabel
5836
5730
  })
5837
5731
  ]
5838
5732
  }, project.projectId)), matchingProjects.length === 0 ? /* @__PURE__ */ jsxs("span", {
5839
- className: "px-2 py-2 text-center text-[11px] text-muted-foreground/60",
5733
+ className: "p-2 text-center text-[0.6875rem] text-muted-foreground/60",
5840
5734
  children: [
5841
5735
  "No project matches \u201C",
5842
5736
  query,
@@ -5846,7 +5740,7 @@ function FleetSessionSidebarNavigation({ brandMenuOpen, setBrandMenuOpen, search
5846
5740
  })]
5847
5741
  }),
5848
5742
  /* @__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",
5743
+ 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
5744
  children: [
5851
5745
  /* @__PURE__ */ jsxs("span", {
5852
5746
  className: "flex items-center gap-1",
@@ -5872,7 +5766,7 @@ function FleetSessionSidebarNavigation({ brandMenuOpen, setBrandMenuOpen, search
5872
5766
  }), /* @__PURE__ */ jsxs("button", {
5873
5767
  type: "button",
5874
5768
  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",
5769
+ 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
5770
  children: [/* @__PURE__ */ jsx(SquarePen, { className: "size-4 shrink-0 text-muted-foreground" }), "New chat"]
5877
5771
  })]
5878
5772
  }),
@@ -5902,7 +5796,7 @@ function FleetSessionSidebarNavigation({ brandMenuOpen, setBrandMenuOpen, search
5902
5796
  /* @__PURE__ */ jsx("div", {
5903
5797
  className: "min-w-0 flex-1",
5904
5798
  children: accountMenu ?? /* @__PURE__ */ jsx("span", {
5905
- className: "flex h-8 items-center px-2 text-[13px]",
5799
+ className: "flex h-8 items-center px-2 text-[0.8125rem]",
5906
5800
  children: "Qredence"
5907
5801
  })
5908
5802
  }),
@@ -6571,12 +6465,12 @@ function FleetSessionSidebarCreateDialog({ createOpen, setCreateOpen, directoryB
6571
6465
  })]
6572
6466
  }),
6573
6467
  /* @__PURE__ */ jsx("span", {
6574
- className: "shrink-0 rounded-full bg-primary/10 px-2 py-1 text-[11px] font-medium text-primary",
6468
+ className: "shrink-0 rounded-full bg-primary/10 px-2 py-1 text-[0.6875rem] font-medium text-primary",
6575
6469
  children: "Selected"
6576
6470
  })
6577
6471
  ]
6578
6472
  }), /* @__PURE__ */ jsxs("div", {
6579
- className: "space-y-2 border-t px-3 py-3",
6473
+ className: "space-y-2 border-t p-3",
6580
6474
  children: [/* @__PURE__ */ jsxs("div", {
6581
6475
  className: "flex items-center justify-between gap-2",
6582
6476
  children: [/* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("p", {
@@ -6632,7 +6526,7 @@ function FleetSessionSidebarCreateDialog({ createOpen, setCreateOpen, directoryB
6632
6526
  className: "block truncate font-medium text-foreground",
6633
6527
  children: pathEntryLabel(entry)
6634
6528
  }), /* @__PURE__ */ jsx("span", {
6635
- className: "block truncate text-[11px] text-muted-foreground",
6529
+ className: "block truncate text-[0.6875rem] text-muted-foreground",
6636
6530
  title: entry.pathLabel,
6637
6531
  children: entry.pathLabel
6638
6532
  })]
@@ -7814,7 +7708,7 @@ function ApprovalCard({ title = "Approval required", description, children, ques
7814
7708
  questions.length
7815
7709
  ]
7816
7710
  }) : /* @__PURE__ */ jsx("span", {
7817
- className: cn("shrink-0 rounded-full border px-2 py-0.5 text-[11px] font-medium transition-colors", getStatusBadgeClass(status)),
7711
+ className: cn("shrink-0 rounded-full border px-2 py-0.5 text-[0.6875rem] font-medium transition-colors", getStatusBadgeClass(status)),
7818
7712
  children: statusLabel2
7819
7713
  }),
7820
7714
  onDismiss ? /* @__PURE__ */ jsx("button", {
@@ -7980,7 +7874,7 @@ function InputQuestionBar({ questionBar, navigation, roundedTop, onDismiss }) {
7980
7874
  className: "flex h-7 items-center justify-between border-b border-border px-3 text-xs text-an-tool-color-muted",
7981
7875
  children: [/* @__PURE__ */ jsxs("div", {
7982
7876
  className: "inline-flex items-center gap-1.5",
7983
- children: [/* @__PURE__ */ jsx(MessageCircleQuestionMark, { className: "h-3.5 w-3.5" }), "Question"]
7877
+ children: [/* @__PURE__ */ jsx(MessageCircleQuestionMark, { className: "size-3.5" }), "Question"]
7984
7878
  }), showQuestionNavigation && /* @__PURE__ */ jsxs("div", {
7985
7879
  className: "inline-flex items-center gap-1",
7986
7880
  children: [
@@ -7990,7 +7884,7 @@ function InputQuestionBar({ questionBar, navigation, roundedTop, onDismiss }) {
7990
7884
  disabled: !canGoPrev,
7991
7885
  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
7886
  "aria-label": "Previous question",
7993
- children: /* @__PURE__ */ jsx(ChevronUp, { className: "h-3.5 w-3.5" })
7887
+ children: /* @__PURE__ */ jsx(ChevronUp, { className: "size-3.5" })
7994
7888
  }),
7995
7889
  /* @__PURE__ */ jsxs("span", {
7996
7890
  className: "tabular-nums",
@@ -8006,7 +7900,7 @@ function InputQuestionBar({ questionBar, navigation, roundedTop, onDismiss }) {
8006
7900
  disabled: !canGoNext,
8007
7901
  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
7902
  "aria-label": "Next question",
8009
- children: /* @__PURE__ */ jsx(ChevronDown, { className: "h-3.5 w-3.5" })
7903
+ children: /* @__PURE__ */ jsx(ChevronDown, { className: "size-3.5" })
8010
7904
  })
8011
7905
  ]
8012
7906
  })]
@@ -8047,7 +7941,7 @@ var ModeSelector = memo(function ModeSelector2({ modes, value, defaultValue, onC
8047
7941
  const hasMultiple = modes.length > 1;
8048
7942
  const trigger = /* @__PURE__ */ jsxs("button", {
8049
7943
  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),
7944
+ 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
7945
  "aria-label": "Select mode",
8052
7946
  children: [
8053
7947
  ActiveIcon && /* @__PURE__ */ jsx(ActiveIcon, { className: "size-3.5 shrink-0" }),
@@ -8071,7 +7965,7 @@ var ModeSelector = memo(function ModeSelector2({ modes, value, defaultValue, onC
8071
7965
  return /* @__PURE__ */ jsxs("button", {
8072
7966
  type: "button",
8073
7967
  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"),
7968
+ 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
7969
  children: [
8076
7970
  Icon && /* @__PURE__ */ jsx(Icon, { className: "mt-0.5 size-3.5 shrink-0" }),
8077
7971
  /* @__PURE__ */ jsxs("span", {
@@ -8127,7 +8021,7 @@ function ComposerMenuItem({ active = false, className, ...props }) {
8127
8021
  type: "button",
8128
8022
  "data-slot": "composer-menu-item",
8129
8023
  "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),
8024
+ 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
8025
  ...props
8132
8026
  });
8133
8027
  }
@@ -8224,7 +8118,7 @@ var ComposerTriggerPopover = memo(function ComposerTriggerPopover2({ open, kind,
8224
8118
  children: title ?? (kind === "slash" ? "Commands" : "Workspace")
8225
8119
  }),
8226
8120
  query ? /* @__PURE__ */ jsx("span", {
8227
- className: "ml-auto max-w-[50%] truncate font-mono text-[11px]",
8121
+ className: "ml-auto max-w-[50%] truncate font-mono text-[0.6875rem]",
8228
8122
  children: query
8229
8123
  }) : null,
8230
8124
  onClose ? /* @__PURE__ */ jsx("button", {
@@ -8250,7 +8144,7 @@ var ComposerTriggerPopover = memo(function ComposerTriggerPopover2({ open, kind,
8250
8144
  role: "group",
8251
8145
  "aria-label": group.label,
8252
8146
  children: [/* @__PURE__ */ jsx("div", {
8253
- className: "px-3 pb-1 pt-2 text-[10px] font-medium uppercase tracking-wide text-muted-foreground",
8147
+ className: "px-3 pb-1 pt-2 text-[0.625rem] font-medium uppercase tracking-wide text-muted-foreground",
8254
8148
  children: group.label
8255
8149
  }), group.items.map((item, index) => renderItem(item, offset + index))]
8256
8150
  }, group.id);
@@ -8258,7 +8152,7 @@ var ComposerTriggerPopover = memo(function ComposerTriggerPopover2({ open, kind,
8258
8152
  })]
8259
8153
  }) : null;
8260
8154
  });
8261
- var LazyModelSelectorList = lazy(() => import("./model-selector-list-cb2-ewoA-KIVU6LD3.js").then(({ ModelSelectorList: ModelSelectorList2 }) => ({ default: ModelSelectorList2 })));
8155
+ var LazyModelSelectorList = lazy(() => import("./model-selector-list-OYnzNbyu-HBGCNF2L.js").then(({ ModelSelectorList: ModelSelectorList2 }) => ({ default: ModelSelectorList2 })));
8262
8156
  function ModelSelectorList(props) {
8263
8157
  return /* @__PURE__ */ jsx(Suspense, {
8264
8158
  fallback: /* @__PURE__ */ jsx("div", {
@@ -8806,7 +8700,7 @@ function getChatErrorPresentation(error) {
8806
8700
  message: error.message.replace(/\s+(?:Socket|Daemon log):\s*[^\n]*(?:\s+(?:Socket|Daemon log):\s*[^\n]*)*/gi, "")
8807
8701
  };
8808
8702
  }
8809
- var LazyFleetPiToolRenderer = lazy(() => import("./fleet-pi-tool-renderer-RIeVlM9J-D6MISCQC.js").then((n) => n.n).then(({ FleetPiToolRenderer: FleetPiToolRenderer2 }) => ({ default: FleetPiToolRenderer2 })));
8703
+ var LazyFleetPiToolRenderer = lazy(() => import("./fleet-pi-tool-renderer-umKunT3K-O4GBH35V.js").then((n) => n.n).then(({ FleetPiToolRenderer: FleetPiToolRenderer2 }) => ({ default: FleetPiToolRenderer2 })));
8810
8704
  function FleetPiToolRenderer(props) {
8811
8705
  return /* @__PURE__ */ jsx(Suspense, {
8812
8706
  fallback: /* @__PURE__ */ jsx("div", {
@@ -8816,17 +8710,20 @@ function FleetPiToolRenderer(props) {
8816
8710
  children: /* @__PURE__ */ jsx(LazyFleetPiToolRenderer, { ...props })
8817
8711
  });
8818
8712
  }
8819
- var LazyAgentActivity = lazy(() => import("./agent-activity-B-JMvecd-SLE3GGY2.js").then(({ AgentActivity: AgentActivity2 }) => ({ default: AgentActivity2 })));
8713
+ var LazyAgentActivity = lazy(() => import("./agent-activity-CS2rbF_C-A3R26CYH.js").then(({ AgentActivity: AgentActivity2 }) => ({ default: AgentActivity2 })));
8820
8714
  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 })
8715
+ return /* @__PURE__ */ jsx("div", {
8716
+ className: "mt-2 min-h-8",
8717
+ children: /* @__PURE__ */ jsx(Suspense, {
8718
+ fallback: /* @__PURE__ */ jsx("div", {
8719
+ className: "h-8 animate-pulse rounded-md bg-muted/40",
8720
+ "aria-label": "Loading activity"
8721
+ }),
8722
+ children: /* @__PURE__ */ jsx(LazyAgentActivity, { ...props })
8723
+ })
8827
8724
  });
8828
8725
  }
8829
- var LazyFleetReasoningPanel = lazy(() => import("./fleet-reasoning-panel-D_K48UOT-GN2PA6KT.js").then(({ FleetReasoningPanel: FleetReasoningPanel2 }) => ({ default: FleetReasoningPanel2 })));
8726
+ var LazyFleetReasoningPanel = lazy(() => import("./fleet-reasoning-panel-BxC2COxi-GPLMQSTT.js").then(({ FleetReasoningPanel: FleetReasoningPanel2 }) => ({ default: FleetReasoningPanel2 })));
8830
8727
  function FleetReasoningPanel(props) {
8831
8728
  return /* @__PURE__ */ jsx(Suspense, {
8832
8729
  fallback: /* @__PURE__ */ jsx("div", {
@@ -8836,7 +8733,7 @@ function FleetReasoningPanel(props) {
8836
8733
  children: /* @__PURE__ */ jsx(LazyFleetReasoningPanel, { ...props })
8837
8734
  });
8838
8735
  }
8839
- var LazyFleetToolTimeline = lazy(() => import("./fleet-tool-timeline-DwRqQgOj-HUFLGMDV.js").then((n) => n.n).then(({ FleetToolTimeline: FleetToolTimeline2 }) => ({ default: FleetToolTimeline2 })));
8736
+ var LazyFleetToolTimeline = lazy(() => import("./fleet-tool-timeline-IB36_PB2-XJENTO6I.js").then((n) => n.n).then(({ FleetToolTimeline: FleetToolTimeline2 }) => ({ default: FleetToolTimeline2 })));
8840
8737
  function FleetToolTimeline(props) {
8841
8738
  return /* @__PURE__ */ jsx(Suspense, {
8842
8739
  fallback: /* @__PURE__ */ jsx("div", {
@@ -8846,7 +8743,7 @@ function FleetToolTimeline(props) {
8846
8743
  children: /* @__PURE__ */ jsx(LazyFleetToolTimeline, { ...props })
8847
8744
  });
8848
8745
  }
8849
- var LazyFleetSubagentList = lazy(() => import("./fleet-subagent-list-5luKtpds-3OTVFHJQ.js").then((n) => n.n).then(({ FleetSubagentList: FleetSubagentList2 }) => ({ default: FleetSubagentList2 })));
8746
+ var LazyFleetSubagentList = lazy(() => import("./fleet-subagent-list-CpSYzCIq-JDH2LHSS.js").then((n) => n.n).then(({ FleetSubagentList: FleetSubagentList2 }) => ({ default: FleetSubagentList2 })));
8850
8747
  function FleetSubagentList(props) {
8851
8748
  return /* @__PURE__ */ jsx(Suspense, {
8852
8749
  fallback: /* @__PURE__ */ jsx("div", {
@@ -8856,17 +8753,20 @@ function FleetSubagentList(props) {
8856
8753
  children: /* @__PURE__ */ jsx(LazyFleetSubagentList, { ...props })
8857
8754
  });
8858
8755
  }
8859
- var LazyPromptSuggestions = lazy(() => import("./prompt-suggestions-BOmHi4-J-C563CHFU.js").then(({ PromptSuggestions: PromptSuggestions2 }) => ({ default: PromptSuggestions2 })));
8756
+ var LazyPromptSuggestions = lazy(() => import("./prompt-suggestions-D4AEEY7K-RZSP7PWV.js").then(({ PromptSuggestions: PromptSuggestions2 }) => ({ default: PromptSuggestions2 })));
8860
8757
  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 })
8758
+ return /* @__PURE__ */ jsx("div", {
8759
+ className: "min-h-8",
8760
+ children: /* @__PURE__ */ jsx(Suspense, {
8761
+ fallback: /* @__PURE__ */ jsx("div", {
8762
+ className: "h-8 animate-pulse rounded-full bg-muted/40",
8763
+ "aria-label": "Loading suggestions"
8764
+ }),
8765
+ children: /* @__PURE__ */ jsx(LazyPromptSuggestions, { ...props })
8766
+ })
8867
8767
  });
8868
8768
  }
8869
- var LazyFleetMessageQueue = lazy(() => import("./fleet-message-queue-BxycG26e-2XLOTCLP.js").then(({ FleetMessageQueue: FleetMessageQueue2 }) => ({ default: FleetMessageQueue2 })));
8769
+ var LazyFleetMessageQueue = lazy(() => import("./fleet-message-queue-j0DCU5Xy-5HKBHMPV.js").then(({ FleetMessageQueue: FleetMessageQueue2 }) => ({ default: FleetMessageQueue2 })));
8870
8770
  function FleetMessageQueue(props) {
8871
8771
  return /* @__PURE__ */ jsx(Suspense, {
8872
8772
  fallback: null,
@@ -9075,8 +8975,8 @@ function AssistantMessage({ messages, isLast, isStreaming, suppressQuestionTool,
9075
8975
  className: "mt-2 max-w-none"
9076
8976
  }) : null,
9077
8977
  isLast && presentation ? /* @__PURE__ */ jsx(FleetSubagentList, {
9078
- children: presentation.rlmChildren,
9079
- tree: presentation.rlmTree
8978
+ tree: presentation.rlmTree,
8979
+ children: presentation.rlmChildren
9080
8980
  }) : null
9081
8981
  ] })
9082
8982
  }) })
@@ -9139,8 +9039,12 @@ function ChatComposerHost({ inputBar, status, suggestions, onSend, onStop, isEmp
9139
9039
  });
9140
9040
  }
9141
9041
  var MemoChatComposerHost = memo(ChatComposerHost);
9042
+ function getConversationTurnKey(turn, turnIndex) {
9043
+ return turn.user?.id ?? turn.assistants[0]?.id ?? `assistant-turn-${turnIndex}`;
9044
+ }
9142
9045
  function FleetPiAgentChat({ toolRenderers = PI_TOOL_RENDERERS, suggestions, status, onStop, onSend, inputBar, className, messages, error, suppressQuestionTool = false, onOpenUIAction, activityLabel, presentation, artifactRuns, onOpenArtifact, onOpenUIArtifactReady, queue, onDeleteQueuedMessage }) {
9143
9046
  const draftSetterRef = useRef2(null);
9047
+ const viewportRef = useRef2(null);
9144
9048
  const setDraft = useCallback2((value) => draftSetterRef.current?.(value), []);
9145
9049
  const turns = useMemo2(() => groupMessages(messages), [messages]);
9146
9050
  const suggestionItems2 = resolveSuggestions(suggestions);
@@ -9188,6 +9092,22 @@ function FleetPiAgentChat({ toolRenderers = PI_TOOL_RENDERERS, suggestions, stat
9188
9092
  presentation: void 0,
9189
9093
  artifactRuns: void 0
9190
9094
  }), []);
9095
+ const renderTurn = useCallback2((turn, turnIndex) => {
9096
+ const isLast = turnIndex === turns.length - 1;
9097
+ return /* @__PURE__ */ jsx(ConversationTurnView, {
9098
+ turn,
9099
+ state: isLast ? stateForLast : stateForRest,
9100
+ rendering,
9101
+ activity: isLast ? activityForLast : activityForRest
9102
+ });
9103
+ }, [
9104
+ activityForLast,
9105
+ activityForRest,
9106
+ rendering,
9107
+ stateForLast,
9108
+ stateForRest,
9109
+ turns.length
9110
+ ]);
9191
9111
  const isEmpty = turns.length === 0 && !error;
9192
9112
  const errorPresentation = error ? getChatErrorPresentation(error) : null;
9193
9113
  const composerNode = /* @__PURE__ */ jsx(MemoChatComposerHost, {
@@ -9206,6 +9126,7 @@ function FleetPiAgentChat({ toolRenderers = PI_TOOL_RENDERERS, suggestions, stat
9206
9126
  className: "flex-1",
9207
9127
  busy: isStreaming,
9208
9128
  followOutput: true,
9129
+ viewportRef,
9209
9130
  smooth: !isStreaming,
9210
9131
  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
9132
  children: [
@@ -9214,15 +9135,13 @@ function FleetPiAgentChat({ toolRenderers = PI_TOOL_RENDERERS, suggestions, stat
9214
9135
  onSelect: (item) => setDraft(item.value ?? item.label),
9215
9136
  composer: composerNode
9216
9137
  }) : 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);
9138
+ /* @__PURE__ */ jsx(VirtualizedTurnList, {
9139
+ estimateSize: 400,
9140
+ getItemKey: getConversationTurnKey,
9141
+ itemGap: 20,
9142
+ items: turns,
9143
+ renderItem: renderTurn,
9144
+ viewportRef
9226
9145
  }),
9227
9146
  errorPresentation ? /* @__PURE__ */ jsxs("div", {
9228
9147
  role: "alert",
@@ -9361,175 +9280,26 @@ function buildChatInputBarProps(composer, activeSessionId) {
9361
9280
  onEffortPickerOpenChange: composer.setEffortPickerOpen
9362
9281
  };
9363
9282
  }
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 });
9283
+ function getChatAuthBearerToken$1() {
9284
+ return null;
9383
9285
  }
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";
9286
+ var ChatRequestError = class extends Error {
9287
+ status;
9288
+ body;
9289
+ code;
9290
+ remediation;
9291
+ constructor(status, body) {
9292
+ super(formatChatRequestErrorMessage(status, body));
9293
+ this.name = "ChatRequestError";
9294
+ this.status = status;
9295
+ this.body = body;
9296
+ const envelope = parseErrorEnvelope(body);
9297
+ this.code = envelope?.code;
9298
+ this.remediation = envelope?.remediation;
9299
+ }
9300
+ };
9301
+ function isFleetErrorRemediation(value) {
9302
+ return typeof value === "object" && value !== null && typeof value.action === "string" && typeof value.label === "string";
9533
9303
  }
9534
9304
  function parseErrorEnvelope(body) {
9535
9305
  const trimmed = body.trim();
@@ -9572,7 +9342,7 @@ function chatErrorFromStreamEvent(event) {
9572
9342
  }
9573
9343
  async function withChatRequestHeaders(init) {
9574
9344
  const headers = new Headers(init?.headers);
9575
- const bearer = await getChatAuthBearerToken();
9345
+ const bearer = await getChatAuthBearerToken$1();
9576
9346
  if (bearer) headers.set("Authorization", `Bearer ${bearer}`);
9577
9347
  return headers;
9578
9348
  }
@@ -9672,6 +9442,167 @@ function labelForState(state) {
9672
9442
  return;
9673
9443
  }
9674
9444
  }
9445
+ function notifyChatError(error) {
9446
+ if (isDaemonDisconnectError(error)) return;
9447
+ notify.error(error instanceof Error ? error.message : String(error));
9448
+ }
9449
+ var LazyChatCommandPalette = lazy(() => import("./chat-command-palette-Dgl5tqWn-72LLEWUD.js").then(({ ChatCommandPalette }) => ({ default: ChatCommandPalette })));
9450
+ var LazySettingsDialog = lazy(() => import("./settings-dialog-BvkgNflv-GPJ6COQO.js").then(({ SettingsDialog }) => ({ default: SettingsDialog })));
9451
+ var LazyForkPickerDialog = lazy(() => import("./fork-picker-dialog-DlINz9UQ-UWIXFDJX.js").then(({ ForkPickerDialog }) => ({ default: ForkPickerDialog })));
9452
+ function ChatCommandPaletteOverlay({ chrome, conversation, dialogs, panels, session }) {
9453
+ return /* @__PURE__ */ jsx(Fragment$1, { children: dialogs.commandPaletteOpen ? /* @__PURE__ */ jsx(Suspense, {
9454
+ fallback: null,
9455
+ children: /* @__PURE__ */ jsx(LazyChatCommandPalette, {
9456
+ open: true,
9457
+ onOpenChange: dialogs.setCommandPaletteOpen,
9458
+ onNewSession: () => void session.startNewSession(),
9459
+ onStop: conversation.stop,
9460
+ onResumeSession: (sessionToResume) => void session.resumeSession({ sessionId: sessionToResume.sessionId }),
9461
+ onSetRightPanel: panels.setRightPanel,
9462
+ onThemeChange: chrome.handleThemePreferenceChange,
9463
+ sessions: session.sessions,
9464
+ isStreaming: conversation.status === "streaming",
9465
+ themePreference: chrome.themePreference
9466
+ })
9467
+ }) : null });
9468
+ }
9469
+ function ChatWorkspaceOverlayDialogs({ dialogs }) {
9470
+ const { forkFromEntry, forkPickerEntries, setForkPickerEntries, setSettingsDialogOpen, setSettingsInitialTab, settingsDialogOpen, settingsInitialTab } = dialogs;
9471
+ const [hasOpenedSettingsDialog, setHasOpenedSettingsDialog] = useState2(settingsDialogOpen);
9472
+ const [hasOpenedForkPickerDialog, setHasOpenedForkPickerDialog] = useState2(forkPickerEntries !== null);
9473
+ useEffect2(() => {
9474
+ if (settingsDialogOpen) setHasOpenedSettingsDialog(true);
9475
+ }, [settingsDialogOpen]);
9476
+ useEffect2(() => {
9477
+ if (forkPickerEntries !== null) setHasOpenedForkPickerDialog(true);
9478
+ }, [forkPickerEntries]);
9479
+ const handleSettingsOpenChange = useCallback2((open) => {
9480
+ setSettingsDialogOpen(open);
9481
+ if (!open) setSettingsInitialTab(void 0);
9482
+ }, [setSettingsDialogOpen, setSettingsInitialTab]);
9483
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [hasOpenedSettingsDialog ? /* @__PURE__ */ jsx(Suspense, {
9484
+ fallback: null,
9485
+ children: /* @__PURE__ */ jsx(LazySettingsDialog, {
9486
+ open: settingsDialogOpen,
9487
+ onOpenChange: handleSettingsOpenChange,
9488
+ initialTab: settingsInitialTab
9489
+ })
9490
+ }) : null, hasOpenedForkPickerDialog ? /* @__PURE__ */ jsx(Suspense, {
9491
+ fallback: null,
9492
+ children: /* @__PURE__ */ jsx(LazyForkPickerDialog, {
9493
+ entries: forkPickerEntries,
9494
+ onOpenChange: (open) => {
9495
+ if (!open) setForkPickerEntries(null);
9496
+ },
9497
+ onPick: forkFromEntry
9498
+ })
9499
+ }) : null] });
9500
+ }
9501
+ var FLEET_PANEL_KEYBINDINGS_STORAGE_KEY = "fleet-prime:v1:panel-keybindings";
9502
+ var DEFAULT_FLEET_PANEL_KEYBINDINGS = {
9503
+ toggleResources: {
9504
+ code: "Digit1",
9505
+ ctrlOrMeta: true,
9506
+ shift: true
9507
+ },
9508
+ toggleWorkspace: {
9509
+ code: "Digit2",
9510
+ ctrlOrMeta: true,
9511
+ shift: true
9512
+ },
9513
+ toggleArtifacts: {
9514
+ code: "Digit3",
9515
+ ctrlOrMeta: true,
9516
+ shift: true
9517
+ },
9518
+ toggleRepl: {
9519
+ code: "Digit4",
9520
+ ctrlOrMeta: true,
9521
+ shift: true
9522
+ },
9523
+ toggleSubagents: {
9524
+ code: "Digit5",
9525
+ ctrlOrMeta: true,
9526
+ shift: true
9527
+ },
9528
+ toggleCommandPalette: {
9529
+ code: "KeyK",
9530
+ ctrlOrMeta: true
9531
+ },
9532
+ closePanel: { code: "Escape" },
9533
+ focusPanel: {
9534
+ code: "KeyP",
9535
+ ctrlOrMeta: true,
9536
+ shift: true
9537
+ },
9538
+ focusChat: {
9539
+ code: "KeyC",
9540
+ ctrlOrMeta: true,
9541
+ shift: true
9542
+ }
9543
+ };
9544
+ function readKeybindings() {
9545
+ try {
9546
+ const value = readStoredValue(FLEET_PANEL_KEYBINDINGS_STORAGE_KEY);
9547
+ if (!value) return DEFAULT_FLEET_PANEL_KEYBINDINGS;
9548
+ const overrides = JSON.parse(value);
9549
+ return {
9550
+ ...DEFAULT_FLEET_PANEL_KEYBINDINGS,
9551
+ ...overrides
9552
+ };
9553
+ } catch {
9554
+ return DEFAULT_FLEET_PANEL_KEYBINDINGS;
9555
+ }
9556
+ }
9557
+ function matches(event, binding) {
9558
+ return event.code === binding.code && (event.ctrlKey || event.metaKey) === Boolean(binding.ctrlOrMeta) && event.shiftKey === Boolean(binding.shift) && event.altKey === Boolean(binding.alt);
9559
+ }
9560
+ function focusChatComposer() {
9561
+ document.querySelector("[data-fleet-chat-focus] textarea, [data-fleet-chat-focus] [contenteditable='true'], [data-fleet-chat-focus] input")?.focus({ preventScroll: true });
9562
+ }
9563
+ function usePanelKeybindings({ onCommandPaletteToggle, onClosePanel, rightPanel, setRightPanel }) {
9564
+ useEffect2(() => {
9565
+ const keybindings = readKeybindings();
9566
+ const handleKeyDown = (event) => {
9567
+ const match = (action) => matches(event, keybindings[action]);
9568
+ let handled = true;
9569
+ if (match("toggleResources")) setRightPanel(rightPanel === "resources" ? null : "resources");
9570
+ else if (match("toggleWorkspace")) setRightPanel(rightPanel === "workspace" ? null : "workspace");
9571
+ else if (match("toggleArtifacts")) setRightPanel(rightPanel === "artifacts" ? null : "artifacts");
9572
+ else if (match("toggleRepl")) setRightPanel(rightPanel === "repl" ? null : "repl");
9573
+ else if (match("toggleSubagents")) setRightPanel(rightPanel === "subagents" ? null : "subagents");
9574
+ else if (onCommandPaletteToggle && match("toggleCommandPalette")) onCommandPaletteToggle();
9575
+ else if (rightPanel && match("closePanel")) {
9576
+ if (onClosePanel) onClosePanel();
9577
+ else {
9578
+ setRightPanel(null);
9579
+ focusChatComposer();
9580
+ }
9581
+ } else if (rightPanel && match("focusPanel")) document.querySelector("[data-fleet-panel-focus]")?.focus({ preventScroll: true });
9582
+ else if (match("focusChat")) focusChatComposer();
9583
+ else handled = false;
9584
+ if (handled) {
9585
+ event.preventDefault();
9586
+ event.stopPropagation();
9587
+ }
9588
+ };
9589
+ document.addEventListener("keydown", handleKeyDown);
9590
+ return () => document.removeEventListener("keydown", handleKeyDown);
9591
+ }, [
9592
+ onCommandPaletteToggle,
9593
+ onClosePanel,
9594
+ rightPanel,
9595
+ setRightPanel
9596
+ ]);
9597
+ }
9598
+ function useOptionalUser() {
9599
+ return null;
9600
+ }
9601
+ function getChatAuthBearerToken() {
9602
+ return null;
9603
+ }
9604
+ async function signOut() {
9605
+ }
9675
9606
  var ProjectResponseSchema = external_exports.object({ project: ProjectSummarySchema });
9676
9607
  var chatClient = {
9677
9608
  async abortSession(metadata) {
@@ -9874,7 +9805,7 @@ var chatClient = {
9874
9805
  async streamMessage(request, onEvent, signal) {
9875
9806
  const attempt = async (allowRetry) => {
9876
9807
  const headers = new Headers({ "Content-Type": "application/json" });
9877
- const bearer = await getChatAuthBearerToken$1();
9808
+ const bearer = await getChatAuthBearerToken();
9878
9809
  if (bearer) headers.set("Authorization", `Bearer ${bearer}`);
9879
9810
  const response = await fetch(resolveChatApiUrl("/api/chat"), {
9880
9811
  method: "POST",
@@ -9957,7 +9888,8 @@ var keys = {
9957
9888
  function useChatModels(projectId) {
9958
9889
  return useQuery({
9959
9890
  queryKey: keys.models(projectId),
9960
- queryFn: () => chatClient.getModels({ projectId })
9891
+ queryFn: () => chatClient.getModels({ projectId }),
9892
+ enabled: Boolean(projectId)
9961
9893
  });
9962
9894
  }
9963
9895
  function useChatProjects() {
@@ -9974,7 +9906,7 @@ function useChatModelCatalog(options) {
9974
9906
  scope: "all",
9975
9907
  projectId: options?.projectId
9976
9908
  }),
9977
- enabled: options?.enabled
9909
+ enabled: Boolean(options?.projectId) && options?.enabled !== false
9978
9910
  });
9979
9911
  }
9980
9912
  function useDiscoverChatModels() {
@@ -9989,19 +9921,22 @@ function useDiscoverChatModels() {
9989
9921
  function useChatResources(projectId) {
9990
9922
  return useQuery({
9991
9923
  queryKey: keys.resources(projectId),
9992
- queryFn: () => chatClient.getResources(projectId)
9924
+ queryFn: () => chatClient.getResources(projectId),
9925
+ enabled: Boolean(projectId)
9993
9926
  });
9994
9927
  }
9995
9928
  function useChatCommands(projectId) {
9996
9929
  return useQuery({
9997
9930
  queryKey: keys.commands(projectId),
9998
- queryFn: () => chatClient.getCommands(projectId)
9931
+ queryFn: () => chatClient.getCommands(projectId),
9932
+ enabled: Boolean(projectId)
9999
9933
  });
10000
9934
  }
10001
9935
  function useChatSettings(projectId) {
10002
9936
  return useQuery({
10003
9937
  queryKey: keys.settings(projectId),
10004
- queryFn: () => chatClient.getSettings(projectId)
9938
+ queryFn: () => chatClient.getSettings(projectId),
9939
+ enabled: Boolean(projectId)
10005
9940
  });
10006
9941
  }
10007
9942
  function useUpdateChatSettings() {
@@ -10020,7 +9955,7 @@ function useWorkspaceTree(projectId, options) {
10020
9955
  return useQuery({
10021
9956
  queryKey: keys.workspace(projectId),
10022
9957
  queryFn: () => chatClient.getWorkspaceTree(projectId),
10023
- enabled: options?.enabled
9958
+ enabled: Boolean(projectId) && options?.enabled !== false
10024
9959
  });
10025
9960
  }
10026
9961
  function useChatProviders() {
@@ -10742,6 +10677,8 @@ function applyChatStreamEvent(transition, event) {
10742
10677
  if (event.type === "rlm") {
10743
10678
  const presentation = transition.snapshot.presentation;
10744
10679
  if (!presentation) return transition;
10680
+ const existingChild = presentation.rlmChildren.find((child) => child.id === event.child.id);
10681
+ if (existingChild && existingChild.timestamp > event.child.timestamp) return transition;
10745
10682
  const rlmChildren = [...presentation.rlmChildren.filter((child) => child.id !== event.child.id), event.child];
10746
10683
  return {
10747
10684
  ...transition,
@@ -10909,13 +10846,12 @@ function isConnectedFrame(value) {
10909
10846
  return typeof value === "object" && value !== null && value.type === "connected" && typeof value.sessionId === "string";
10910
10847
  }
10911
10848
  function readStoredSubagentCursor(key) {
10912
- if (typeof window === "undefined") return void 0;
10913
10849
  try {
10914
- const raw = window.sessionStorage.getItem(key);
10850
+ const raw = readStoredValue(key, "session");
10915
10851
  if (!raw) return void 0;
10916
10852
  const value = JSON.parse(raw);
10917
10853
  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);
10854
+ removeStoredValue(key, "session");
10919
10855
  return;
10920
10856
  }
10921
10857
  return {
@@ -10923,7 +10859,7 @@ function readStoredSubagentCursor(key) {
10923
10859
  lastEventId: value.lastEventId
10924
10860
  };
10925
10861
  } catch {
10926
- window.sessionStorage.removeItem(key);
10862
+ removeStoredValue(key, "session");
10927
10863
  return;
10928
10864
  }
10929
10865
  }
@@ -11056,18 +10992,14 @@ function useSubagentChat({ client, enabled, child, loadSession, parentSessionId
11056
10992
  lastEventId = storedCursor.lastEventId;
11057
10993
  }
11058
10994
  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 {
10995
+ if (!streamGeneration) {
10996
+ removeStoredValue(cursorKey, "session");
10997
+ return;
11070
10998
  }
10999
+ writeStoredValue(cursorKey, JSON.stringify({
11000
+ generation: streamGeneration,
11001
+ lastEventId
11002
+ }), "session");
11071
11003
  };
11072
11004
  const clearCursor = () => {
11073
11005
  lastEventId = 0;
@@ -11357,12 +11289,11 @@ function storeResourceCanvasWidth(width) {
11357
11289
  }
11358
11290
  function readStoredThemePreference() {
11359
11291
  if (typeof window === "undefined") return "system";
11360
- const value = window.localStorage.getItem(THEME_PREFERENCE_STORAGE_KEY);
11292
+ const value = readStoredValue(THEME_PREFERENCE_STORAGE_KEY);
11361
11293
  return value === "light" || value === "dark" || value === "system" ? value : "system";
11362
11294
  }
11363
11295
  function storeThemePreference(preference) {
11364
- if (typeof window === "undefined") return;
11365
- window.localStorage.setItem(THEME_PREFERENCE_STORAGE_KEY, preference);
11296
+ writeStoredValue(THEME_PREFERENCE_STORAGE_KEY, preference);
11366
11297
  }
11367
11298
  function applyThemePreference(preference) {
11368
11299
  if (typeof window === "undefined") return;
@@ -11544,18 +11475,16 @@ function useChatStorage() {
11544
11475
  };
11545
11476
  }
11546
11477
  function readStoredBrowserSessions() {
11547
- if (typeof window === "undefined" || !window.localStorage) return {};
11478
+ const raw = readStoredValue(CHAT_SESSION_STORAGE_KEY);
11479
+ if (!raw) return readLegacyScopeStorage();
11548
11480
  try {
11549
- const raw = window.localStorage.getItem(CHAT_SESSION_STORAGE_KEY);
11550
- if (!raw) return readLegacyScopeStorage();
11551
11481
  return parseSessionMetadata(JSON.parse(raw));
11552
11482
  } catch {
11553
11483
  return readLegacyScopeStorage();
11554
11484
  }
11555
11485
  }
11556
11486
  function readLegacyScopeStorage() {
11557
- if (typeof window === "undefined" || !window.localStorage) return {};
11558
- const raw = window.localStorage.getItem("fleet-prime:v1:chat-sessions");
11487
+ const raw = readStoredValue("fleet-prime:v1:chat-sessions");
11559
11488
  if (!raw) return {};
11560
11489
  try {
11561
11490
  return parseSessionMetadata(JSON.parse(raw)?.normal);
@@ -11568,19 +11497,17 @@ function parseSessionMetadata(value) {
11568
11497
  return result.success ? result.data : {};
11569
11498
  }
11570
11499
  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");
11500
+ removeStoredValue(CHAT_SESSION_STORAGE_KEY);
11501
+ removeStoredValue("fleet-prime:v1:chat-sessions");
11502
+ removeStoredValue("fleet-prime:v1:chat-mode");
11575
11503
  }
11576
11504
  function storeBrowserSessions(metadata) {
11577
- if (typeof window === "undefined" || !window.localStorage) return;
11578
11505
  if (!metadata.sessionId && !metadata.projectId) {
11579
- window.localStorage.removeItem(CHAT_SESSION_STORAGE_KEY);
11580
- window.localStorage.removeItem("fleet-prime:v1:chat-sessions");
11506
+ removeStoredValue(CHAT_SESSION_STORAGE_KEY);
11507
+ removeStoredValue("fleet-prime:v1:chat-sessions");
11581
11508
  return;
11582
11509
  }
11583
- window.localStorage.setItem(CHAT_SESSION_STORAGE_KEY, JSON.stringify(metadata));
11510
+ writeStoredValue(CHAT_SESSION_STORAGE_KEY, JSON.stringify(metadata));
11584
11511
  }
11585
11512
  function useChatSuggestions({ messages, resources, workspaceTree }) {
11586
11513
  return useMemo2(() => buildContextSuggestions({
@@ -11725,7 +11652,7 @@ function AccountMenu({ user, onSignOut, onOpenSettings, compact = false, label =
11725
11652
  children: [
11726
11653
  /* @__PURE__ */ jsx(QredenceLogo, { className: "size-3.5 shrink-0" }),
11727
11654
  /* @__PURE__ */ jsx("span", {
11728
- className: compact ? "sr-only" : "text-[13px] font-medium tracking-[-0.01em] whitespace-nowrap",
11655
+ className: compact ? "sr-only" : "text-[0.8125rem] font-medium tracking-[-0.01em] whitespace-nowrap",
11729
11656
  children: label
11730
11657
  }),
11731
11658
  /* @__PURE__ */ jsx(ChevronDown, { className: "size-3.5 shrink-0 text-foreground/35" })
@@ -11793,6 +11720,139 @@ function AccountMenu({ user, onSignOut, onOpenSettings, compact = false, label =
11793
11720
  })
11794
11721
  });
11795
11722
  }
11723
+ function statusLabel(status) {
11724
+ switch (status) {
11725
+ case "queued":
11726
+ return "queued";
11727
+ case "running":
11728
+ case "recovering":
11729
+ return "streaming";
11730
+ case "error":
11731
+ case "failed":
11732
+ return "error";
11733
+ case "cancelled":
11734
+ return "cancelled";
11735
+ case "done":
11736
+ return "complete";
11737
+ default:
11738
+ return "ready";
11739
+ }
11740
+ }
11741
+ function statusDotClass(status) {
11742
+ switch (status) {
11743
+ case "running":
11744
+ case "recovering":
11745
+ return "bg-emerald-400 motion-safe:animate-pulse";
11746
+ case "error":
11747
+ case "failed":
11748
+ return "bg-destructive";
11749
+ case "queued":
11750
+ return "bg-amber-300";
11751
+ case "cancelled":
11752
+ return "bg-foreground/35";
11753
+ default:
11754
+ return "bg-foreground/35";
11755
+ }
11756
+ }
11757
+ function AgentTabBar({ tabs, value, onValueChange, onClose, onNewSession }) {
11758
+ const tabRefs = useRef2(/* @__PURE__ */ new Map());
11759
+ const setTabRef = useCallback2((tabId, node) => {
11760
+ if (node) tabRefs.current.set(tabId, node);
11761
+ else tabRefs.current.delete(tabId);
11762
+ }, []);
11763
+ useEffect2(() => {
11764
+ for (const tabId of tabRefs.current.keys()) if (!tabs.some((tab) => tab.id === tabId)) tabRefs.current.delete(tabId);
11765
+ }, [tabs]);
11766
+ const focusTab = useCallback2((index) => {
11767
+ const tab = tabs[index];
11768
+ if (!tab) return;
11769
+ tabRefs.current.get(tab.id)?.focus();
11770
+ onValueChange(tab.id);
11771
+ }, [onValueChange, tabs]);
11772
+ const handleKeyDown = useCallback2((event, tabId) => {
11773
+ const index = tabs.findIndex((tab) => tab.id === tabId);
11774
+ if (index < 0) return;
11775
+ let nextIndex;
11776
+ if (event.key === "ArrowRight") nextIndex = (index + 1) % tabs.length;
11777
+ if (event.key === "ArrowLeft") nextIndex = (index - 1 + tabs.length) % tabs.length;
11778
+ if (event.key === "Home") nextIndex = 0;
11779
+ if (event.key === "End") nextIndex = tabs.length - 1;
11780
+ if (nextIndex === void 0) return;
11781
+ event.preventDefault();
11782
+ focusTab(nextIndex);
11783
+ }, [focusTab, tabs]);
11784
+ return /* @__PURE__ */ jsxs("div", {
11785
+ className: "flex min-w-0 max-w-full items-center gap-1",
11786
+ "data-testid": "agent-tab-bar",
11787
+ children: [/* @__PURE__ */ jsx("div", {
11788
+ "aria-label": "Agent conversations",
11789
+ className: "flex min-w-0 flex-1 items-center gap-1 overflow-x-auto overscroll-contain [scrollbar-width:none] [&::-webkit-scrollbar]:hidden",
11790
+ role: "tablist",
11791
+ children: tabs.map((tab) => {
11792
+ const active = tab.id === value;
11793
+ const status = statusLabel(tab.status);
11794
+ return /* @__PURE__ */ jsxs("div", {
11795
+ className: "group/tab relative min-w-0 shrink-0 basis-[164px] sm:max-w-[164px]",
11796
+ "data-tab-id": tab.id,
11797
+ children: [/* @__PURE__ */ jsxs(Button, {
11798
+ ref: (node) => setTabRef(tab.id, node),
11799
+ "aria-controls": agentTabPanelId(tab.id),
11800
+ "aria-selected": active,
11801
+ "aria-label": `${tab.label}, ${status}`,
11802
+ 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"),
11803
+ "data-state": active ? "active" : "inactive",
11804
+ id: agentTabTriggerId(tab.id),
11805
+ onClick: () => onValueChange(tab.id),
11806
+ onKeyDown: (event) => handleKeyDown(event, tab.id),
11807
+ role: "tab",
11808
+ size: "sm",
11809
+ tabIndex: active ? 0 : -1,
11810
+ type: "button",
11811
+ variant: "ghost",
11812
+ children: [tab.kind === "main" ? /* @__PURE__ */ jsx(Bot, {
11813
+ "aria-hidden": "true",
11814
+ className: "size-3.5 shrink-0"
11815
+ }) : /* @__PURE__ */ jsx("span", {
11816
+ "aria-hidden": "true",
11817
+ className: cn("size-1.5 shrink-0 rounded-full", statusDotClass(tab.status))
11818
+ }), /* @__PURE__ */ jsx("span", {
11819
+ className: "min-w-0 flex-1 truncate text-left",
11820
+ children: tab.label
11821
+ })]
11822
+ }), tab.kind === "subagent" && onClose ? /* @__PURE__ */ jsx(Button, {
11823
+ "aria-label": `Close ${tab.label} tab`,
11824
+ 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",
11825
+ onClick: (event) => {
11826
+ event.stopPropagation();
11827
+ onClose(tab.id);
11828
+ },
11829
+ size: "icon-xs",
11830
+ title: `Close ${tab.label} tab`,
11831
+ type: "button",
11832
+ variant: "ghost",
11833
+ children: /* @__PURE__ */ jsx(X, {
11834
+ "aria-hidden": "true",
11835
+ className: "size-3"
11836
+ })
11837
+ }) : null]
11838
+ }, tab.id);
11839
+ })
11840
+ }), onNewSession ? /* @__PURE__ */ jsx(Button, {
11841
+ "aria-label": "New chat",
11842
+ className: "size-7 shrink-0 rounded-[7px] text-foreground/50 hover:bg-foreground/7 hover:text-foreground/85",
11843
+ "data-testid": "new-chat-tab",
11844
+ onClick: onNewSession,
11845
+ size: "icon-sm",
11846
+ title: "New chat",
11847
+ type: "button",
11848
+ variant: "ghost",
11849
+ children: /* @__PURE__ */ jsx(Plus, {
11850
+ "aria-hidden": "true",
11851
+ className: "size-3.5"
11852
+ })
11853
+ }) : null]
11854
+ });
11855
+ }
11796
11856
  function useChatWorkspaceHeader({ activeTabId, tabs, onCloseTab, onNewSession, onSelectTab, onOpenSettings }) {
11797
11857
  const navigate = useNavigate();
11798
11858
  const user = useOptionalUser();
@@ -12347,10 +12407,6 @@ function answerToRecordValue(answer) {
12347
12407
  if (answer.kind === "text") return typeof answer.text === "string" ? answer.text : "";
12348
12408
  return answer.selectedIds?.[0] ?? answer.text ?? "";
12349
12409
  }
12350
- function notifyChatError(error) {
12351
- if (isDaemonDisconnectError(error)) return;
12352
- notify.error(error instanceof Error ? error.message : String(error));
12353
- }
12354
12410
  function cleanStepText(text) {
12355
12411
  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
12412
  if (cleaned.length > 0) cleaned = `${cleaned.charAt(0).toUpperCase()}${cleaned.slice(1)}`;
@@ -12675,23 +12731,34 @@ function usePiChatSessionEvents({ client, presentationRef, sessionId, sessionMet
12675
12731
  if (!sessionId || typeof window === "undefined") return;
12676
12732
  const lastEventIdKey = `pi:sse:last-event-id:${sessionId}`;
12677
12733
  const sseCapabilitiesRef = { current: void 0 };
12678
- let lastEventId = Number.parseInt(window.sessionStorage.getItem(lastEventIdKey) ?? "0", 10);
12734
+ let lastEventId = Number.parseInt(readStoredValue(lastEventIdKey, "session") ?? "0", 10);
12679
12735
  if (Number.isNaN(lastEventId)) lastEventId = 0;
12680
12736
  let source = null;
12681
12737
  let reconnectTimer = null;
12738
+ let reconnectAttempt = 0;
12739
+ let reconnectNoticeShown = false;
12740
+ let lastAppliedRlmSeq = 0;
12682
12741
  let closedByEffect = false;
12683
- const handleEvent = (raw) => {
12742
+ let activeAssistantId;
12743
+ const handleEvent = (raw, seq) => {
12684
12744
  let frame2;
12685
12745
  try {
12686
12746
  frame2 = JSON.parse(raw.data);
12687
12747
  } catch {
12688
12748
  return;
12689
12749
  }
12750
+ if (frame2.type === "start") activeAssistantId = frame2.id;
12751
+ if (frame2.type === "done") activeAssistantId = void 0;
12752
+ const statusAtFrame = statusRef.current;
12690
12753
  if (frame2.type === "presentation") {
12691
12754
  if (frame2.presentation.revision > (presentationRef.current?.revision ?? -1)) setPresentationSynced(frame2.presentation);
12692
12755
  return;
12693
12756
  }
12694
12757
  if (frame2.type === "rlm") {
12758
+ if (!Number.isNaN(seq) && seq > 0) {
12759
+ if (seq <= lastAppliedRlmSeq) return;
12760
+ lastAppliedRlmSeq = seq;
12761
+ }
12695
12762
  const current = presentationRef.current;
12696
12763
  const existing = current.rlmChildren.find((child) => child.id === frame2.child.id);
12697
12764
  if (existing && existing.timestamp > frame2.child.timestamp) return;
@@ -12702,45 +12769,78 @@ function usePiChatSessionEvents({ client, presentationRef, sessionId, sessionMet
12702
12769
  });
12703
12770
  return;
12704
12771
  }
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
12772
  if (frame2.type === "tool" && frame2.part?.type === "tool-Question") {
12719
12773
  setMessagesSynced((current) => {
12720
12774
  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;
12775
+ if (!toolCallId) return current;
12776
+ const hasToolCall = (message) => message.parts.some((part) => part.type !== "text" && part.type !== "error" && "toolCallId" in part && part.toolCallId === toolCallId);
12777
+ let targetIndex = frame2.messageId ? current.findIndex((message) => message.id === frame2.messageId && message.role === "assistant") : -1;
12778
+ if (targetIndex < 0 && activeAssistantId) targetIndex = current.findIndex((message) => message.id === activeAssistantId && message.role === "assistant");
12779
+ if (targetIndex < 0) {
12780
+ let latestAssistantWithoutToolCall = -1;
12781
+ let latestMatchingToolCall = -1;
12782
+ for (let index = current.length - 1; index >= 0; index -= 1) {
12783
+ const message = current[index];
12784
+ if (message.role !== "assistant") continue;
12785
+ if (hasToolCall(message) && latestMatchingToolCall < 0) latestMatchingToolCall = index;
12786
+ else if (latestAssistantWithoutToolCall < 0) latestAssistantWithoutToolCall = index;
12787
+ }
12788
+ targetIndex = frame2.part.state === "input-streaming" ? latestAssistantWithoutToolCall >= 0 ? latestAssistantWithoutToolCall : latestMatchingToolCall : latestMatchingToolCall >= 0 ? latestMatchingToolCall : latestAssistantWithoutToolCall;
12789
+ }
12722
12790
  const questionPart = {
12723
12791
  ...frame2.part,
12724
12792
  type: "tool-Question"
12725
12793
  };
12726
- return [...current, {
12727
- id: crypto.randomUUID(),
12794
+ if (targetIndex < 0) return [...current, {
12795
+ id: frame2.messageId ?? crypto.randomUUID(),
12728
12796
  role: "assistant",
12729
12797
  parts: [questionPart],
12730
12798
  createdAt: (/* @__PURE__ */ new Date()).toISOString()
12731
12799
  }];
12800
+ return current.flatMap((message, index) => {
12801
+ if (index === targetIndex) return [{
12802
+ ...message,
12803
+ parts: upsertToolPart(message.parts, questionPart)
12804
+ }];
12805
+ if (!hasToolCall(message)) return [message];
12806
+ const parts = message.parts.filter((part) => !(part.type !== "text" && part.type !== "error" && "toolCallId" in part && part.toolCallId === toolCallId));
12807
+ return parts.length > 0 ? [{
12808
+ ...message,
12809
+ parts
12810
+ }] : [];
12811
+ });
12732
12812
  });
12733
12813
  return;
12734
12814
  }
12815
+ if (statusRef.current === "streaming" || statusRef.current === "submitted") return;
12816
+ const connected = frame2;
12817
+ if (connected.type === "connected") {
12818
+ sseCapabilitiesRef.current = connected.adapterCapabilities;
12819
+ setAdapterCapabilities(connected.adapterCapabilities);
12820
+ if (connected.cursorReset) lastAppliedRlmSeq = 0;
12821
+ return;
12822
+ }
12823
+ if (frame2.type === "reasoning") {
12824
+ const messageId = frame2.messageId;
12825
+ if (!sseCapabilitiesRef.current?.features.includes("reasoning-summary-v1") || !messageId) return;
12826
+ setMessagesSynced((current) => upsertAssistantReasoningPresentation(current, messageId, frame2.presentation));
12827
+ return;
12828
+ }
12735
12829
  if (frame2.type === "state") {
12736
12830
  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);
12831
+ if (frame2.state?.name === "agent_settled") {
12832
+ if (statusAtFrame === "streaming" || statusAtFrame === "submitted") return;
12833
+ const metadataSessionIdAtFrame = sessionMetadataRef.current.sessionId;
12834
+ client.loadSession({ sessionId }).then((result) => {
12835
+ if (closedByEffect || sessionMetadataRef.current.sessionId !== sessionId) return;
12836
+ if (sessionMetadataRef.current.sessionId !== metadataSessionIdAtFrame) return;
12837
+ if (statusRef.current === "streaming" || statusRef.current === "submitted") return;
12838
+ setMessagesSynced(hydratePlanPresentationMessages(result.messages, result.planPresentations));
12839
+ setPresentationSynced(result.presentation);
12840
+ setSessionMetadataSynced(result.session);
12841
+ setQueueSynced(EMPTY_QUEUE_STATE);
12842
+ }).catch(() => void 0);
12843
+ }
12744
12844
  return;
12745
12845
  }
12746
12846
  if (frame2.type === "queue") setQueueSynced({
@@ -12759,15 +12859,27 @@ function usePiChatSessionEvents({ client, presentationRef, sessionId, sessionMet
12759
12859
  const seq = Number.parseInt(event.lastEventId ?? "", 10);
12760
12860
  if (!Number.isNaN(seq) && seq > 0) {
12761
12861
  lastEventId = seq;
12762
- window.sessionStorage.setItem(lastEventIdKey, String(seq));
12862
+ writeStoredValue(lastEventIdKey, String(seq), "session");
12863
+ }
12864
+ if (reconnectAttempt > 0) {
12865
+ reconnectAttempt = 0;
12866
+ if (reconnectNoticeShown) {
12867
+ reconnectNoticeShown = false;
12868
+ if (statusRef.current !== "streaming" && statusRef.current !== "submitted") setActivityLabelSynced(void 0);
12869
+ }
12763
12870
  }
12764
- handleEvent(event);
12871
+ handleEvent(event, seq);
12765
12872
  };
12766
12873
  nextSource.onerror = () => {
12767
12874
  if (closedByEffect || source !== nextSource) return;
12768
12875
  nextSource.close();
12876
+ reconnectAttempt += 1;
12877
+ if (reconnectAttempt > 1 && statusRef.current !== "streaming" && statusRef.current !== "submitted") {
12878
+ reconnectNoticeShown = true;
12879
+ setActivityLabelSynced(reconnectAttempt > 2 ? `Reconnecting\u2026 (attempt ${reconnectAttempt})` : "Reconnecting\u2026");
12880
+ }
12769
12881
  if (reconnectTimer) clearTimeout(reconnectTimer);
12770
- reconnectTimer = setTimeout(connect, 2e3);
12882
+ reconnectTimer = setTimeout(connect, Math.min(2e3, 250 * 2 ** Math.min(reconnectAttempt, 3)));
12771
12883
  };
12772
12884
  };
12773
12885
  connect();
@@ -12819,6 +12931,10 @@ function usePiChatMessaging({ activityLabelRef, client, messagesRef, presentatio
12819
12931
  const streamAdmissionsRef = useRef2(/* @__PURE__ */ new Set());
12820
12932
  const queuedSubmissionTailRef = useRef2(RESOLVED_PROMISE);
12821
12933
  const adapterCapabilitiesRef = useRef2(void 0);
12934
+ const projectIdRef = useRef2(projectId);
12935
+ useEffect2(() => {
12936
+ projectIdRef.current = projectId;
12937
+ }, [projectId]);
12822
12938
  const findStreamAdmission = useCallback2((sessionId) => {
12823
12939
  for (const admission of streamAdmissionsRef.current) if (admission.sessionId === sessionId) return admission;
12824
12940
  }, []);
@@ -12863,7 +12979,7 @@ function usePiChatMessaging({ activityLabelRef, client, messagesRef, presentatio
12863
12979
  if (existing.sessionId) return existing;
12864
12980
  const inFlight = sessionCreatePromiseRef.current;
12865
12981
  if (inFlight) return inFlight;
12866
- const promise = client.createSession(projectId, signal).then((created) => {
12982
+ const promise = client.createSession(projectIdRef.current, signal).then((created) => {
12867
12983
  if (signal?.aborted) throw new Error("Session creation was aborted");
12868
12984
  setSessionMetadataSynced(created.session);
12869
12985
  setPresentationSynced(created.presentation);
@@ -12877,7 +12993,6 @@ function usePiChatMessaging({ activityLabelRef, client, messagesRef, presentatio
12877
12993
  return promise;
12878
12994
  }, [
12879
12995
  client,
12880
- projectId,
12881
12996
  refreshSessions,
12882
12997
  sessionMetadataRef,
12883
12998
  setPresentationSynced,
@@ -13026,22 +13141,21 @@ function usePiChatMessaging({ activityLabelRef, client, messagesRef, presentatio
13026
13141
  resetStreamAdmission,
13027
13142
  sendMessage: useCallback2(async ({ text, attachments, openUI, openUIArtifact, planAction, mode, altKey }) => {
13028
13143
  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;
13144
+ if (!trimmed) return false;
13145
+ if (status === "submitted" || status === "streaming" || findStreamAdmission(sessionMetadataRef.current.sessionId) !== void 0) try {
13146
+ await enqueueDuringStream(trimmed, altKey ? "followUp" : "steer", {
13147
+ attachments,
13148
+ mode,
13149
+ openUI,
13150
+ openUIArtifact,
13151
+ planAction
13152
+ });
13153
+ return true;
13154
+ } catch (err) {
13155
+ const nextError = err instanceof Error ? err : new Error(String(err));
13156
+ setError(nextError);
13157
+ notifyChatError(nextError);
13158
+ return false;
13045
13159
  }
13046
13160
  setError(null);
13047
13161
  setActivityLabelSynced(void 0);
@@ -13059,7 +13173,7 @@ function usePiChatMessaging({ activityLabelRef, client, messagesRef, presentatio
13059
13173
  let terminalDoneSeen = false;
13060
13174
  try {
13061
13175
  const ensuredSession = await ensureSession(controller.signal);
13062
- if (controller.signal.aborted) return;
13176
+ if (controller.signal.aborted) return false;
13063
13177
  const ensuredStreamSessionId = ensuredSession.sessionId;
13064
13178
  if (!ensuredStreamSessionId) throw new Error("Unable to start a session stream");
13065
13179
  streamSessionId = ensuredStreamSessionId;
@@ -13087,23 +13201,25 @@ function usePiChatMessaging({ activityLabelRef, client, messagesRef, presentatio
13087
13201
  }
13088
13202
  if (sessionMetadataRef.current.sessionId === ensuredStreamSessionId && (terminalDoneSeen || !sessionStillRunning)) setStatus("ready");
13089
13203
  messagesRef.current.length;
13204
+ return true;
13090
13205
  } catch (err) {
13091
13206
  if (streamAdmissionsRef.current.delete(streamAdmission)) streamAdmission.reject(err);
13092
13207
  setMessagesSynced((current) => removeOptimisticUserMessage(current, userMessage.id));
13093
- if (controller.signal.aborted) return;
13208
+ if (controller.signal.aborted) return false;
13094
13209
  if (streamSessionId && sessionMetadataRef.current.sessionId !== streamSessionId) {
13095
13210
  refreshSessions();
13096
- return;
13211
+ return false;
13097
13212
  }
13098
13213
  const recoveryDeps = {
13099
13214
  setError,
13100
13215
  setStatus
13101
13216
  };
13102
- if (await tryRecoverForbiddenSession(err, recoverFromForbiddenSession, recoveryDeps) || await tryRecoverUnknownSession(err, recoverFromForbiddenSession, recoveryDeps)) return;
13217
+ if (await tryRecoverForbiddenSession(err, recoverFromForbiddenSession, recoveryDeps) || await tryRecoverUnknownSession(err, recoverFromForbiddenSession, recoveryDeps)) return false;
13103
13218
  const nextError = err instanceof Error ? err : new Error(String(err));
13104
13219
  setError(nextError);
13105
13220
  setStatus("error");
13106
13221
  notifyChatError(nextError);
13222
+ return false;
13107
13223
  } finally {
13108
13224
  if (streamAdmissionsRef.current.delete(streamAdmission)) streamAdmission.reject(/* @__PURE__ */ new Error("Chat stream ended before admission"));
13109
13225
  if (controller.signal.aborted) setMessagesSynced((current) => removeOptimisticUserMessage(current, userMessage.id));
@@ -13236,19 +13352,22 @@ function usePiChat(model, options) {
13236
13352
  artifactRuns: []
13237
13353
  }));
13238
13354
  const initialSessionMetadataRef = useRef2(initialSessionMetadata);
13355
+ const projectIdRef = useRef2(projectId);
13239
13356
  const messagesRef = useRef2(messages);
13240
13357
  const sessionMetadataRef = useRef2(sessionMetadata);
13241
13358
  const activityLabelRef = useRef2(activityLabel);
13242
13359
  const planLabelRef = useRef2(planLabel);
13243
13360
  const queueRef = useRef2(queue);
13244
13361
  const queueRevisionRef = useRef2(0);
13245
- const queuedDeletionTailRef = useRef2(Promise.resolve());
13362
+ const queuedDeletionTailRef = useRef2(null);
13246
13363
  const presentationRef = useRef2(presentation);
13247
13364
  const pendingSendControllerRef = useRef2(null);
13248
13365
  const streamControllersRef = useRef2(/* @__PURE__ */ new Map());
13366
+ const refreshSessionsPromiseRef = useRef2(null);
13367
+ const resumeRequestRef = useRef2(0);
13249
13368
  const statusRef = useRef2(status);
13250
13369
  const initializedRef = useRef2(false);
13251
- const sendMessageRef = useRef2(() => Promise.resolve());
13370
+ const sendMessageRef = useRef2(() => Promise.resolve(false));
13252
13371
  const setMessagesSynced = useCallback2((updater) => {
13253
13372
  const next = typeof updater === "function" ? updater(messagesRef.current) : updater;
13254
13373
  messagesRef.current = next;
@@ -13305,14 +13424,26 @@ function usePiChat(model, options) {
13305
13424
  if (sessionMetadataRef.current.sessionId === sessionId) setPresentationSynced(result.presentation);
13306
13425
  return result.artifact.id;
13307
13426
  }, [client, setPresentationSynced]);
13427
+ useEffect2(() => {
13428
+ projectIdRef.current = projectId;
13429
+ }, [projectId]);
13308
13430
  const refreshSessions = useCallback2(async () => {
13309
- const nextSessions = await client.listSessions();
13310
- setSessions(nextSessions);
13311
- return nextSessions;
13431
+ const pendingRefresh = refreshSessionsPromiseRef.current;
13432
+ if (pendingRefresh) return pendingRefresh;
13433
+ const refreshRequest = client.listSessions().then((nextSessions) => {
13434
+ setSessions(nextSessions);
13435
+ return nextSessions;
13436
+ });
13437
+ refreshSessionsPromiseRef.current = refreshRequest;
13438
+ try {
13439
+ return await refreshRequest;
13440
+ } finally {
13441
+ if (refreshSessionsPromiseRef.current === refreshRequest) refreshSessionsPromiseRef.current = null;
13442
+ }
13312
13443
  }, [client]);
13313
13444
  const recoverFromForbiddenSession = useCallback2((projectIdOverride) => runForbiddenSessionRecovery({
13314
13445
  client,
13315
- projectId: projectIdOverride ?? projectId,
13446
+ projectId: projectIdOverride ?? projectIdRef.current,
13316
13447
  refreshSessions,
13317
13448
  setActivityLabelSynced,
13318
13449
  setError,
@@ -13324,7 +13455,6 @@ function usePiChat(model, options) {
13324
13455
  setStatus
13325
13456
  }), [
13326
13457
  client,
13327
- projectId,
13328
13458
  refreshSessions,
13329
13459
  setActivityLabelSynced,
13330
13460
  setMessagesSynced,
@@ -13422,18 +13552,6 @@ function usePiChat(model, options) {
13422
13552
  controllers.clear();
13423
13553
  };
13424
13554
  }, []);
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
13555
  usePiChatBootstrap({
13438
13556
  client,
13439
13557
  initialSessionMetadataRef,
@@ -13498,21 +13616,25 @@ function usePiChat(model, options) {
13498
13616
  const originatingSessionId = sessionMetadataRef.current.sessionId;
13499
13617
  const requestedRevision = queueRevisionRef.current;
13500
13618
  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 () => {
13619
+ const deletion = (queuedDeletionTailRef.current ?? Promise.resolve()).catch(() => void 0).then(async () => {
13502
13620
  if (!originatingSessionId || sessionMetadataRef.current.sessionId !== originatingSessionId) return false;
13621
+ const refuseStaleDeletion = (expectedRace) => {
13622
+ if (!expectedRace) notifyChatError(/* @__PURE__ */ new Error("The queued message changed before it could be deleted."));
13623
+ return false;
13624
+ };
13503
13625
  const current = queueRef.current;
13504
13626
  const items = lane === "steering" ? current.steering : current.followUp;
13505
13627
  let resolvedIndex;
13506
13628
  if (queueRevisionRef.current === requestedRevision) resolvedIndex = items[index] === expectedText ? index : void 0;
13507
13629
  else {
13508
- if (requestedMatchCount !== 1) return false;
13630
+ if (requestedMatchCount !== 1) return refuseStaleDeletion(true);
13509
13631
  const currentMatches = items.reduce((matches2, item, itemIndex) => {
13510
13632
  if (item === expectedText) matches2.push(itemIndex);
13511
13633
  return matches2;
13512
13634
  }, []);
13513
13635
  resolvedIndex = currentMatches.length === 1 ? currentMatches[0] : void 0;
13514
13636
  }
13515
- if (resolvedIndex === void 0) return false;
13637
+ if (resolvedIndex === void 0) return refuseStaleDeletion(queueRevisionRef.current !== requestedRevision);
13516
13638
  const optimistic = {
13517
13639
  ...current,
13518
13640
  [lane]: items.filter((_, itemIndex) => itemIndex !== resolvedIndex)
@@ -13543,7 +13665,7 @@ function usePiChat(model, options) {
13543
13665
  invalidateQueueMutations();
13544
13666
  setStatus("ready");
13545
13667
  }
13546
- const result = await client.createSession(options2?.projectId ?? projectId);
13668
+ const result = await client.createSession(options2?.projectId ?? projectIdRef.current ?? projectId);
13547
13669
  setSessionMetadataSynced(result.session);
13548
13670
  setMessagesSynced([]);
13549
13671
  setPresentationSynced(result.presentation);
@@ -13566,10 +13688,14 @@ function usePiChat(model, options) {
13566
13688
  projectId
13567
13689
  ]);
13568
13690
  const resumeSession = useCallback2(async (metadata, options2) => {
13691
+ const requestId = resumeRequestRef.current + 1;
13692
+ resumeRequestRef.current = requestId;
13693
+ const isCurrent = () => resumeRequestRef.current === requestId;
13569
13694
  invalidateQueueMutations();
13570
13695
  try {
13571
13696
  if (options2?.preserveRunning === false) stop();
13572
13697
  const result = await client.resumeSession(metadata);
13698
+ if (!isCurrent()) return false;
13573
13699
  setSessionMetadataSynced(result.session);
13574
13700
  setMessagesSynced(hydratePlanPresentationMessages(result.messages, result.planPresentations));
13575
13701
  setPresentationSynced(result.presentation);
@@ -13578,14 +13704,18 @@ function usePiChat(model, options) {
13578
13704
  setPlanLabelSynced(void 0);
13579
13705
  setStatus(streamControllersRef.current.has(result.session.sessionId ?? "") ? "streaming" : "ready");
13580
13706
  await refreshSessions();
13707
+ if (!isCurrent()) return false;
13581
13708
  return true;
13582
13709
  } catch (err) {
13710
+ if (!isCurrent()) return false;
13583
13711
  const recoveryDeps = {
13584
13712
  setError,
13585
13713
  setStatus
13586
13714
  };
13587
13715
  const recover = () => recoverFromForbiddenSession(metadata.projectId);
13588
- if (await tryRecoverForbiddenSession(err, recover, recoveryDeps) || await tryRecoverUnknownSession(err, recover, recoveryDeps)) return false;
13716
+ const recovered = await tryRecoverForbiddenSession(err, recover, recoveryDeps) || await tryRecoverUnknownSession(err, recover, recoveryDeps);
13717
+ if (!isCurrent()) return false;
13718
+ if (recovered) return false;
13589
13719
  const nextError = err instanceof Error ? err : new Error(String(err));
13590
13720
  setError(nextError);
13591
13721
  setStatus("error");
@@ -13653,13 +13783,24 @@ function usePiChat(model, options) {
13653
13783
  });
13654
13784
  const enhancedMessages = useMemo2(() => enhanceMessages(messages), [messages, enhanceMessages]);
13655
13785
  const renameSession = useCallback2(async (sessionId, title) => {
13656
- await client.renameSession(sessionId, title);
13657
- await refreshSessions();
13786
+ try {
13787
+ await client.renameSession(sessionId, title);
13788
+ await refreshSessions();
13789
+ return true;
13790
+ } catch (err) {
13791
+ notifyChatError(err);
13792
+ return false;
13793
+ }
13658
13794
  }, [client, refreshSessions]);
13659
13795
  const deleteSession = useCallback2(async (sessionId) => {
13660
13796
  const deletingActive = sessionMetadataRef.current.sessionId === sessionId;
13661
13797
  if (deletingActive) stop();
13662
- await client.deleteSession(sessionId);
13798
+ try {
13799
+ await client.deleteSession(sessionId);
13800
+ } catch (err) {
13801
+ notifyChatError(err);
13802
+ return false;
13803
+ }
13663
13804
  if (deletingActive) {
13664
13805
  setSessionMetadataSynced({});
13665
13806
  setMessagesSynced([]);
@@ -13672,6 +13813,7 @@ function usePiChat(model, options) {
13672
13813
  });
13673
13814
  }
13674
13815
  await refreshSessions();
13816
+ return true;
13675
13817
  }, [
13676
13818
  client,
13677
13819
  refreshSessions,
@@ -13898,7 +14040,7 @@ function useChatWorkspaceData() {
13898
14040
  const { data: commandsData } = useChatCommands(activeProjectId);
13899
14041
  const { data: settingsData, isLoading: settingsLoading, error: settingsError } = useChatSettings(activeProjectId);
13900
14042
  const updateSettings = useUpdateChatSettings();
13901
- const { data: workspaceData, isLoading: workspaceLoading, error: workspaceError, refetch: refetchWorkspace } = useWorkspaceTree(activeProjectId, { enabled: true });
14043
+ const { data: workspaceData, isLoading: workspaceLoading, error: workspaceError, refetch: refetchWorkspace } = useWorkspaceTree(activeProjectId, { enabled: rightPanel === "workspace" || rightPanel === "resources" });
13902
14044
  const resources = resourcesData ?? null;
13903
14045
  const workspaceTree = workspaceData ?? null;
13904
14046
  const refreshResources = useCallback2(() => {
@@ -13947,15 +14089,29 @@ function useChatWorkspaceData() {
13947
14089
  setUploadedAttachments([]);
13948
14090
  setWorkspaceAttachments([]);
13949
14091
  }, []);
14092
+ const workspaceSessionCreatePromiseRef = useRef2(null);
13950
14093
  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();
14094
+ const key = `${options?.projectId ?? ""}::${options?.preserveRunning ?? ""}`;
14095
+ const inFlight = workspaceSessionCreatePromiseRef.current;
14096
+ if (inFlight && inFlight.key === key) return inFlight.promise;
14097
+ const promise = (async () => {
14098
+ const currentMetadata = getSessionMetadata();
14099
+ const targetProjectId = options?.projectId ?? activeProjectId;
14100
+ const shouldClear = shouldClearPendingAttachmentsForNewSession({
14101
+ ...currentMetadata,
14102
+ projectId: currentMetadata.projectId ?? activeProjectId
14103
+ }, targetProjectId);
14104
+ await startNewSession(options);
14105
+ if (shouldClear) clearPendingAttachments();
14106
+ return getSessionMetadata();
14107
+ })().finally(() => {
14108
+ if (workspaceSessionCreatePromiseRef.current?.promise === promise) workspaceSessionCreatePromiseRef.current = null;
14109
+ });
14110
+ workspaceSessionCreatePromiseRef.current = {
14111
+ key,
14112
+ promise
14113
+ };
14114
+ return promise;
13959
14115
  }, [
13960
14116
  activeProjectId,
13961
14117
  clearPendingAttachments,
@@ -14010,8 +14166,7 @@ function useChatWorkspaceData() {
14010
14166
  ]);
14011
14167
  const deleteSessionForWorkspace = useCallback2(async (sessionId) => {
14012
14168
  const deletingActiveSession = getSessionMetadata().sessionId === sessionId;
14013
- await deleteSession(sessionId);
14014
- if (deletingActiveSession) clearPendingAttachments();
14169
+ if (await deleteSession(sessionId) && deletingActiveSession) clearPendingAttachments();
14015
14170
  }, [
14016
14171
  clearPendingAttachments,
14017
14172
  deleteSession,
@@ -14065,8 +14220,7 @@ function useChatWorkspaceData() {
14065
14220
  (async () => {
14066
14221
  const files = Array.from(input.files ?? []);
14067
14222
  if (files.length === 0) return;
14068
- if (!getSessionMetadata().sessionId) await startNewSessionForWorkspace();
14069
- const sessionId = getSessionMetadata().sessionId;
14223
+ const sessionId = getSessionMetadata().sessionId ?? (await startNewSessionForWorkspace()).sessionId;
14070
14224
  if (!sessionId) throw new Error("Unable to create a session for attachments");
14071
14225
  const uploaded = await chatClient.uploadAttachments(sessionId, files);
14072
14226
  setUploadedAttachments((current) => [...current, ...uploaded]);
@@ -14081,6 +14235,10 @@ function useChatWorkspaceData() {
14081
14235
  }, []);
14082
14236
  const clearUploadedAttachments = useCallback2(() => setUploadedAttachments([]), []);
14083
14237
  const clearWorkspaceAttachments = useCallback2(() => setWorkspaceAttachments([]), []);
14238
+ const restoreAttachments = useCallback2((uploaded, workspace) => {
14239
+ if (uploaded.length > 0) setUploadedAttachments((current) => [...uploaded, ...current]);
14240
+ if (workspace.length > 0) setWorkspaceAttachments((current) => [...workspace, ...current]);
14241
+ }, []);
14084
14242
  const addWorkspaceAttachment = useCallback2((item) => {
14085
14243
  const relativePath = workspacePathFromSuggestion(item);
14086
14244
  if (!relativePath) return;
@@ -14156,22 +14314,23 @@ function useChatWorkspaceData() {
14156
14314
  modelKey,
14157
14315
  models,
14158
14316
  onForkPicker: setForkPickerEntries,
14159
- onOpenUIRequest: useCallback2((request) => {
14317
+ onOpenUIRequest: useCallback2(async (request) => {
14160
14318
  const attachments = [...workspaceAttachments, ...uploadedAttachments];
14161
14319
  clearUploadedAttachments();
14162
14320
  clearWorkspaceAttachments();
14163
- return sendMessage({
14321
+ if (!await sendMessage({
14164
14322
  text: request,
14165
14323
  altKey: false,
14166
14324
  mode: chatMode,
14167
14325
  openUI: true,
14168
14326
  openUIArtifact: true,
14169
14327
  attachments
14170
- });
14328
+ })) restoreAttachments(uploadedAttachments, workspaceAttachments);
14171
14329
  }, [
14172
14330
  chatMode,
14173
14331
  clearUploadedAttachments,
14174
14332
  clearWorkspaceAttachments,
14333
+ restoreAttachments,
14175
14334
  sendMessage,
14176
14335
  uploadedAttachments,
14177
14336
  workspaceAttachments
@@ -14309,6 +14468,7 @@ function useChatWorkspaceData() {
14309
14468
  removeUploadedAttachment,
14310
14469
  removeWorkspaceAttachment,
14311
14470
  addWorkspaceAttachment,
14471
+ restoreAttachments,
14312
14472
  setChatMode,
14313
14473
  setEffortPickerOpen,
14314
14474
  setModelKey,
@@ -14346,7 +14506,7 @@ function useChatWorkspaceData() {
14346
14506
  }
14347
14507
  };
14348
14508
  }
14349
- var LazySubagentChatPanel = lazy(() => import("./subagent-chat-panel-DlSsM59d-DBW7DI3T.js").then(({ SubagentChatPanel }) => ({ default: SubagentChatPanel })));
14509
+ var LazySubagentChatPanel = lazy(() => import("./subagent-chat-panel-CMuvW9Sd-M5TEEGQW.js").then(({ SubagentChatPanel }) => ({ default: SubagentChatPanel })));
14350
14510
  function ChatWorkspaceShell() {
14351
14511
  const { session, conversation, composer, panels, dialogs, chrome, agentTabs } = useChatWorkspaceData();
14352
14512
  const toggleCommandPalette = useCallback2(() => {
@@ -14364,22 +14524,30 @@ function ChatWorkspaceShell() {
14364
14524
  });
14365
14525
  const activeProjectName = session.projects.find((project) => project.projectId === session.activeProjectId)?.name;
14366
14526
  const handleSend = useCallback2((text, altKey) => {
14367
- const attachments = [...composer.workspaceAttachments, ...composer.uploadedAttachments];
14527
+ const uploaded = [...composer.uploadedAttachments];
14528
+ const workspace = [...composer.workspaceAttachments];
14529
+ const attachments = [...workspace, ...uploaded];
14368
14530
  composer.clearUploadedAttachments();
14369
14531
  composer.clearWorkspaceAttachments();
14370
14532
  (async () => {
14371
- await conversation.sendMessage({
14372
- text,
14373
- altKey,
14374
- mode: composer.chatMode,
14375
- openUI: true,
14376
- attachments
14377
- });
14533
+ try {
14534
+ if (!await conversation.sendMessage({
14535
+ text,
14536
+ altKey,
14537
+ mode: composer.chatMode,
14538
+ openUI: true,
14539
+ attachments
14540
+ })) composer.restoreAttachments(uploaded, workspace);
14541
+ } catch (error) {
14542
+ composer.restoreAttachments(uploaded, workspace);
14543
+ notifyChatError(error);
14544
+ }
14378
14545
  })();
14379
14546
  }, [
14380
14547
  composer.chatMode,
14381
14548
  composer.clearUploadedAttachments,
14382
14549
  composer.clearWorkspaceAttachments,
14550
+ composer.restoreAttachments,
14383
14551
  composer.uploadedAttachments,
14384
14552
  composer.workspaceAttachments,
14385
14553
  conversation.sendMessage