@qredence/fleet 0.5.0 → 0.5.1

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 (110) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +8 -1
  3. package/dist/web/client/assets/artifacts-panel-CX62LQ13.js +1 -0
  4. package/dist/web/client/assets/artifacts-utils-N_kUFbz2.js +1 -0
  5. package/dist/web/client/assets/bot-Bs7QWJ2q.js +1 -0
  6. package/dist/web/client/assets/{chat-C64Sv6V-.js → chat-CsepBQwy.js} +5 -5
  7. package/dist/web/client/assets/{chat-command-palette-HpsmKfLO.js → chat-command-palette-C4sSf8Kg.js} +1 -1
  8. package/dist/web/client/assets/collapsible-DmyYcezk.js +1 -0
  9. package/dist/web/client/assets/command-CB6emP8m.js +2 -0
  10. package/dist/web/client/assets/conversation-turns-ByFoWPXe.js +6 -0
  11. package/dist/web/client/assets/ease-vFBiNFNK.js +9 -0
  12. package/dist/web/client/assets/{fleet-pi-tool-renderer-ZKiX6Ob_.js → fleet-pi-tool-renderer-BD_ZAjlG.js} +28 -30
  13. package/dist/web/client/assets/globals-CqqQdk2S.css +2 -0
  14. package/dist/web/client/assets/horizontal-resize-C1TpRLNC.js +1 -0
  15. package/dist/web/client/assets/index-DweoFRMs.js +12 -0
  16. package/dist/web/client/assets/{input-Clyn18XG.js → input-CqC82Agz.js} +1 -1
  17. package/dist/web/client/assets/{input-group-MxDAWX3j.js → input-group-H0TG-mkU.js} +1 -1
  18. package/dist/web/client/assets/ipython-tool-BfeIa0nK.js +3 -0
  19. package/dist/web/client/assets/markdown-DG7pUdsX.js +2 -0
  20. package/dist/web/client/assets/{markdown-code-pIaEVDUU.js → markdown-code-BgMzpy7O.js} +1 -1
  21. package/dist/web/client/assets/notify-Duj26eeZ.js +1 -0
  22. package/dist/web/client/assets/{openui-renderer-NLUpAS3h.js → openui-renderer-DlUo6ehT.js} +5 -5
  23. package/dist/web/client/assets/openui-utils-DawGoQNp.js +1 -0
  24. package/dist/web/client/assets/prime-agent-artifacts-CHGb5V_j.js +5 -0
  25. package/dist/web/client/assets/{provider-catalog-Gx9qaHBM.js → provider-catalog-BZhZuKSz.js} +1 -1
  26. package/dist/web/client/assets/provider-label-jKm8v18u.js +1 -0
  27. package/dist/web/client/assets/range-vSJ7Ux_5.js +2 -0
  28. package/dist/web/client/assets/repl-panel-DiGS6uCw.js +1 -0
  29. package/dist/web/client/assets/resource-helpers-ULlyU8qK.js +2 -0
  30. package/dist/web/client/assets/resources-panel-DSU7VGX2.js +1 -0
  31. package/dist/web/client/assets/routes-CxlNCi_v.js +16 -0
  32. package/dist/web/client/assets/session-insights-panel-DwmwiikS.js +1 -0
  33. package/dist/web/client/assets/settings-dialog-CkfpTKfM.js +1 -0
  34. package/dist/web/client/assets/skeleton-loaders-fStjEeRP.js +1 -0
  35. package/dist/web/client/assets/square-terminal-BYTN_I86.js +1 -0
  36. package/dist/web/client/assets/subagents-panel-DGnsK6Nx.js +1 -0
  37. package/dist/web/client/assets/{switch-ojzdMno9.js → switch-BFEBpUEU.js} +1 -1
  38. package/dist/web/client/assets/{tool-result-QvhjpNGX.js → tool-result-CBzwwUE9.js} +3 -3
  39. package/dist/web/client/assets/ui-preferences-DUEFuJFj.js +1 -0
  40. package/dist/web/client/assets/workspace-panel-CjdXlEvd.js +1 -0
  41. package/dist/web/client/assets/workspace-path-nav-C0AQNZyy.js +1 -0
  42. package/dist/web/server/{_tanstack-start-manifest_v-uZddQetG-MNZGQOSA.js → _tanstack-start-manifest_v-bDUlyKY0-KFW35JRO.js} +23 -16
  43. package/dist/web/server/{artifacts-panel-knpQvJ-q-WJLZ76QB.js → artifacts-panel-D9w1DHAN-FGRDCYU2.js} +37 -70
  44. package/dist/web/server/{chat-command-palette-CPv5GmGJ-22J32S6P.js → chat-command-palette-BaenPkCN-BHSOPGU4.js} +16 -14
  45. package/dist/web/server/{chunk-OADQILSQ.js → chunk-2U7PWSJX.js} +49 -47
  46. package/dist/web/server/{chunk-ZX3XOSYO.js → chunk-3GSFXWL5.js} +2 -2
  47. package/dist/web/server/{chunk-IFV5M33X.js → chunk-3IKSPTYI.js} +12 -26
  48. package/dist/web/server/{chunk-W7LNJCRJ.js → chunk-44IVTHDV.js} +18 -10
  49. package/dist/web/server/{chunk-I3FDTJFO.js → chunk-46VQY7SG.js} +6 -87
  50. package/dist/web/server/{chunk-WTYNN6EV.js → chunk-54II5QXQ.js} +23 -1
  51. package/dist/web/server/{chunk-PRT4QYOB.js → chunk-5AVQZ4AZ.js} +1 -35
  52. package/dist/web/server/chunk-6GMKRR3C.js +161 -0
  53. package/dist/web/server/chunk-74QOI457.js +45 -0
  54. package/dist/web/server/chunk-AQ66E5OW.js +33 -0
  55. package/dist/web/server/{chunk-TTQ75CXC.js → chunk-AZZHUVJR.js} +88 -23
  56. package/dist/web/server/{chunk-KAWYGHDN.js → chunk-B2F6MLVZ.js} +23 -1
  57. package/dist/web/server/{chunk-C7EKOPZU.js → chunk-DO3TVNGA.js} +87 -87
  58. package/dist/web/server/chunk-EIVNRYP3.js +48 -0
  59. package/dist/web/server/{chunk-UBUXV2TW.js → chunk-FBOO3G67.js} +6 -6
  60. package/dist/web/server/{chunk-MK3P3OBZ.js → chunk-FVWDJNXR.js} +5 -5
  61. package/dist/web/server/chunk-G5BCQQ5N.js +34 -0
  62. package/dist/web/server/{chunk-4KFMONRT.js → chunk-H64JLONZ.js} +9 -9
  63. package/dist/web/server/{chunk-KDSISV4P.js → chunk-HBZ6YKRB.js} +2 -50
  64. package/dist/web/server/{chunk-5277VI3D.js → chunk-KPNGZR2R.js} +12 -74
  65. package/dist/web/server/chunk-M2FGGPNA.js +376 -0
  66. package/dist/web/server/{chunk-KVHPE5XH.js → chunk-MDYA4NXK.js} +22 -8
  67. package/dist/web/server/chunk-NFRJDPB3.js +52 -0
  68. package/dist/web/server/chunk-P66QQWUM.js +67 -0
  69. package/dist/web/server/{fleet-pi-tool-renderer-5vYFNeZS-IHKMLT7W.js → chunk-PCJ5EKFE.js} +40 -392
  70. package/dist/web/server/{chunk-APN3LVRT.js → chunk-PWK2HJIV.js} +27 -30
  71. package/dist/web/server/{chunk-XXNFEXDU.js → chunk-QJBEWT4E.js} +2 -70
  72. package/dist/web/server/{chunk-JD6EWZCU.js → chunk-VHCAD46L.js} +48 -48
  73. package/dist/web/server/chunk-Y6LJ4WBI.js +1797 -0
  74. package/dist/web/server/{chunk-NGI44XRR.js → chunk-ZEVZFLIY.js} +1 -1
  75. package/dist/web/server/fleet-pi-tool-renderer-lJvZWmBJ-4M5YI6VS.js +35 -0
  76. package/dist/web/server/{fork-picker-dialog-BZzfxdQd-C6SPHFAW.js → fork-picker-dialog-BZzfxdQd-Y725VJ7G.js} +2 -2
  77. package/dist/web/server/{markdown-Ct_q4D-z-VFWZRBTY.js → markdown-Boni3lHk-AZGKDNAR.js} +1 -1
  78. package/dist/web/server/{markdown-code-C_ih1bX1-5CIWT3CH.js → markdown-code-BrWukbg3-D2GN4Y77.js} +2 -2
  79. package/dist/web/server/{openui-renderer-BT5jL0Yf-XYLLN5U6.js → openui-renderer-Cg4RSE9k-7BTJIYZJ.js} +12 -11
  80. package/dist/web/server/repl-panel-BEQrC2ef-V3YEZ7EO.js +117 -0
  81. package/dist/web/server/{resources-panel-DNCVHTIg-PJYMXVGE.js → resources-panel-CwKh4U9f-D3VDEMDW.js} +6 -6
  82. package/dist/web/server/{router-DDxOMz3K-HRBXILHM.js → router-CEahIUpn-SRG7XKIH.js} +131 -21
  83. package/dist/web/server/{routes-BX4Tv-6R-FHIZYUWW.js → routes-BznemByz-F4DJAYIM.js} +1371 -2499
  84. package/dist/web/server/server.js +2 -2
  85. package/dist/web/server/{session-insights-panel-gYkkAE8H-W4O74Z7H.js → session-insights-panel-JfeTHE0d-3HZB3ZWI.js} +2 -2
  86. package/dist/web/server/{settings-dialog-BTBFLQ1P-ZENQ4KWK.js → settings-dialog-DgeBMORv-7SRSENPM.js} +47 -61
  87. package/dist/web/server/subagents-panel-CzZe3co7-2VZ5JTWF.js +332 -0
  88. package/dist/web/server/{chunk-5SZXUN3Y.js → workspace-panel-y54P79_B-VPIYUXF6.js} +29 -16
  89. package/package.json +11 -3
  90. package/dist/web/client/assets/artifacts-panel-8TyrNBM_.js +0 -1
  91. package/dist/web/client/assets/collapsible-WCSnxhr2.js +0 -1
  92. package/dist/web/client/assets/command-DgfiCKcY.js +0 -2
  93. package/dist/web/client/assets/globals-BmxtUHFx.css +0 -2
  94. package/dist/web/client/assets/horizontal-resize-B76jjn5v.js +0 -1
  95. package/dist/web/client/assets/index-0pBr_bKy.js +0 -12
  96. package/dist/web/client/assets/markdown-BXWmNJo7.js +0 -2
  97. package/dist/web/client/assets/prime-agent-artifacts-k9JiTDZM.js +0 -5
  98. package/dist/web/client/assets/provider-brand-icon-VCebsuTD.js +0 -1
  99. package/dist/web/client/assets/range-KAaLzImH.js +0 -2
  100. package/dist/web/client/assets/resources-panel-BWuKeyrb.js +0 -1
  101. package/dist/web/client/assets/routes-BPRw0UzV.js +0 -20
  102. package/dist/web/client/assets/session-insights-panel-CPymkzZT.js +0 -1
  103. package/dist/web/client/assets/settings-dialog-6p8mjg8t.js +0 -1
  104. package/dist/web/client/assets/shared-DAI9OAw0.js +0 -2
  105. package/dist/web/client/assets/skeleton-loaders-qxIkJKCA.js +0 -1
  106. package/dist/web/client/assets/workspace-panel-C67-fqw4.js +0 -1
  107. package/dist/web/client/assets/workspace-path-nav-BrQHo6es.js +0 -9
  108. package/dist/web/server/chunk-KJ4UUAEU.js +0 -83
  109. package/dist/web/server/workspace-panel-BNAXF57q-EQCBPEG4.js +0 -28
  110. package/dist/web/server/{chunk-AQWTGP35.js → chunk-FE4KN6T2.js} +5 -5
@@ -1,9 +1,49 @@
1
+ import {
2
+ ChatCommandsResponseSchema,
3
+ ChatModelsDiscoverRequestSchema,
4
+ ChatModelsDiscoverResponseSchema,
5
+ ChatModelsResponseSchema,
6
+ ChatProviderOAuthLoginRequestSchema,
7
+ ChatProviderOAuthLoginResponseSchema,
8
+ ChatProviderRemoveRequestSchema,
9
+ ChatProviderUpdateRequestSchema,
10
+ ChatProviderUpdateResponseSchema,
11
+ ChatProvidersResponseSchema,
12
+ ChatResourcesResponseSchema,
13
+ ChatSettingsResponseSchema,
14
+ ChatSettingsUpdateRequestSchema,
15
+ LazyMotion,
16
+ NETWORK_DISCONNECTED_MESSAGE,
17
+ WorkspaceBrowseResponseSchema,
18
+ WorkspaceFileResponseSchema,
19
+ WorkspaceTreeResponseSchema,
20
+ domAnimation,
21
+ useMutation,
22
+ useQuery,
23
+ useQueryClient
24
+ } from "./chunk-H64JLONZ.js";
25
+ import {
26
+ ChevronLeft,
27
+ FileAttachment,
28
+ FleetGenerativeTextRenderer,
29
+ FleetSubagentList,
30
+ FleetToolTimeline,
31
+ Image,
32
+ Message,
33
+ MessageBubble,
34
+ MessageBubbleContent,
35
+ MessageContent,
36
+ MessageScroller,
37
+ UserMessage,
38
+ buildAssistantElements,
39
+ groupMessages,
40
+ normalizeAssistantToolParts
41
+ } from "./chunk-Y6LJ4WBI.js";
1
42
  import {
2
43
  BookOpenText,
3
44
  CitationList,
4
45
  CitationStack,
5
46
  Earth,
6
- LazyMarkdown,
7
47
  ListTodo,
8
48
  LogOut,
9
49
  MessageCircleQuestionMark,
@@ -17,7 +57,28 @@ import {
17
57
  paper,
18
58
  take,
19
59
  useHoverCapable
20
- } from "./chunk-W7LNJCRJ.js";
60
+ } from "./chunk-44IVTHDV.js";
61
+ import {
62
+ DESKTOP_PANEL_ONLY,
63
+ File,
64
+ FolderOpen,
65
+ RESOURCE_CANVAS_VIEWPORT_RATIO,
66
+ SharedLayoutBg,
67
+ availableThinkingLevels,
68
+ clampThinkingLevel,
69
+ normalizeSessionLabel,
70
+ queueLabel,
71
+ readStoredWidth,
72
+ startHorizontalResize,
73
+ storeStoredWidth,
74
+ thinkingLevelLabel,
75
+ toModelOption,
76
+ toModelSelection
77
+ } from "./chunk-FVWDJNXR.js";
78
+ import "./chunk-QK4CHLVV.js";
79
+ import {
80
+ resolveWorkspacePanelTarget
81
+ } from "./chunk-P66QQWUM.js";
21
82
  import {
22
83
  Command,
23
84
  CommandEmpty,
@@ -30,7 +91,10 @@ import {
30
91
  RotateCcwClock,
31
92
  Square,
32
93
  getRightPanelDefinition
33
- } from "./chunk-TTQ75CXC.js";
94
+ } from "./chunk-AZZHUVJR.js";
95
+ import {
96
+ Folder
97
+ } from "./chunk-OLG5DQ7V.js";
34
98
  import {
35
99
  AlertDialog,
36
100
  AlertDialogAction,
@@ -40,7 +104,6 @@ import {
40
104
  AlertDialogFooter,
41
105
  AlertDialogTitle,
42
106
  ArrowLeft,
43
- Bot,
44
107
  CHAT_HEADER_LAYER_CLASS,
45
108
  CHROME_PILL_ACTIVE_CLASS,
46
109
  CHROME_PILL_CLASS,
@@ -48,17 +111,22 @@ import {
48
111
  MessageSquare,
49
112
  PANEL_OVERLAY_CLASS,
50
113
  ProviderBrandIcon,
51
- RefreshCw,
52
114
  Settings,
53
115
  Spinner,
54
116
  Trash2,
55
117
  formatProviderLabel,
56
- notify,
57
118
  safePolygon,
58
119
  useHoverFloatingInteraction,
59
120
  useHoverReferenceInteraction,
60
121
  usePopupHandleStore
61
- } from "./chunk-5277VI3D.js";
122
+ } from "./chunk-KPNGZR2R.js";
123
+ import {
124
+ RefreshCw,
125
+ notify
126
+ } from "./chunk-EIVNRYP3.js";
127
+ import {
128
+ TriangleAlert
129
+ } from "./chunk-WK7CQS2N.js";
62
130
  import {
63
131
  Sparkles
64
132
  } from "./chunk-5WZFFNFY.js";
@@ -67,42 +135,19 @@ import {
67
135
  RightPanelProvider,
68
136
  useChatPanelDataContext,
69
137
  useWorkspaceTreeContext
70
- } from "./chunk-ZX3XOSYO.js";
138
+ } from "./chunk-3GSFXWL5.js";
139
+ import {
140
+ Bot
141
+ } from "./chunk-74QOI457.js";
71
142
  import {
72
143
  Search
73
144
  } from "./chunk-2H6A6Z7F.js";
74
145
  import {
75
- ChatCommandsResponseSchema,
76
- ChatModelsDiscoverRequestSchema,
77
- ChatModelsDiscoverResponseSchema,
78
- ChatModelsResponseSchema,
79
- ChatProviderOAuthLoginRequestSchema,
80
- ChatProviderOAuthLoginResponseSchema,
81
- ChatProviderRemoveRequestSchema,
82
- ChatProviderUpdateRequestSchema,
83
- ChatProviderUpdateResponseSchema,
84
- ChatProvidersResponseSchema,
85
- ChatResourcesResponseSchema,
86
- ChatSettingsResponseSchema,
87
- ChatSettingsUpdateRequestSchema,
88
- LazyMotion,
89
- NETWORK_DISCONNECTED_MESSAGE,
90
- WorkspaceBrowseResponseSchema,
91
- WorkspaceFileResponseSchema,
92
- WorkspaceTreeResponseSchema,
93
- domAnimation,
94
- useMutation,
95
- useQuery,
96
- useQueryClient
97
- } from "./chunk-4KFMONRT.js";
98
- import {
99
- TriangleAlert
100
- } from "./chunk-WK7CQS2N.js";
146
+ collectSessionOpenUIBlocks
147
+ } from "./chunk-AQ66E5OW.js";
101
148
  import {
102
- collectSessionOpenUIBlocks,
103
- derivePrimeAgentArtifactRuns,
104
- getArtifactsScopePath
105
- } from "./chunk-PRT4QYOB.js";
149
+ derivePrimeAgentArtifactRuns
150
+ } from "./chunk-5AVQZ4AZ.js";
106
151
  import {
107
152
  ActionSwapRollText,
108
153
  AgentDisclosure,
@@ -111,20 +156,98 @@ import {
111
156
  CollapsibleTrigger,
112
157
  Copy,
113
158
  FileCodeCorner,
114
- SquareTerminal,
115
159
  Wrench
116
- } from "./chunk-APN3LVRT.js";
160
+ } from "./chunk-PWK2HJIV.js";
161
+ import {
162
+ AnimatePresence,
163
+ EASE_DRAWER,
164
+ EASE_IN_OUT,
165
+ EASE_OUT,
166
+ MotionConfigContext,
167
+ SPRING_GLIDE,
168
+ SPRING_LAYOUT,
169
+ SPRING_MOUSE,
170
+ SPRING_PANEL,
171
+ SPRING_PRESS,
172
+ SPRING_SWAP,
173
+ m,
174
+ motion,
175
+ useConstant,
176
+ useIsomorphicLayoutEffect,
177
+ useReducedMotion
178
+ } from "./chunk-QJBEWT4E.js";
179
+ import {
180
+ HTMLVisualElement,
181
+ JSAnimation,
182
+ LayoutGroupContext,
183
+ SVGVisualElement,
184
+ VisualElement,
185
+ animateSingleValue,
186
+ animateTarget,
187
+ cancelFrame,
188
+ collectMotionValues,
189
+ createBox,
190
+ createGeneratorEasing,
191
+ defaultOffset,
192
+ fillOffset,
193
+ frame,
194
+ interpolate,
195
+ invariant,
196
+ isEasingArray,
197
+ isGenerator,
198
+ isMotionValue,
199
+ isSVGElement,
200
+ isSVGSVGElement,
201
+ mixNumber$1,
202
+ motionValue,
203
+ progress,
204
+ removeItem,
205
+ resolveElements,
206
+ resolveTransition,
207
+ reverseEasing,
208
+ secondsToMilliseconds,
209
+ spring,
210
+ visualElementStore,
211
+ warning
212
+ } from "./chunk-FAGDMGLK.js";
117
213
  import {
118
214
  RotateCcw
119
215
  } from "./chunk-6RJYXDSD.js";
120
216
  import {
121
217
  LoaderCircle
122
218
  } from "./chunk-PKCTG7EW.js";
219
+ import {
220
+ ChevronRight
221
+ } from "./chunk-7QCDOBZ3.js";
123
222
  import {
124
223
  UiErrorBoundary,
125
- decodeOpenPanelActionMessage,
126
- segmentOpenUIContent
127
- } from "./chunk-KDSISV4P.js";
224
+ decodeOpenPanelActionMessage
225
+ } from "./chunk-HBZ6YKRB.js";
226
+ import {
227
+ ChatOpenUIArtifactUpsertRequestSchema,
228
+ ChatOpenUIArtifactUpsertResponseSchema,
229
+ ChatPlanPresentationSchema,
230
+ ChatPlanPresentationUpsertRequestSchema,
231
+ ChatQuestionAnswerResponseSchema,
232
+ ChatQueueMutationRequestSchema,
233
+ ChatQueueMutationResponseSchema,
234
+ ChatSessionMetadataSchema,
235
+ ChatSessionResponseSchema,
236
+ ChatSessionsResponseSchema,
237
+ ChatStreamEventSchema,
238
+ ChatThinkingLevelSchema,
239
+ ProjectCreateRequestSchema,
240
+ ProjectDirectoryBrowseResponseSchema,
241
+ ProjectForkRequestSchema,
242
+ ProjectForkResponseSchema,
243
+ ProjectListResponseSchema,
244
+ ProjectRenameRequestSchema,
245
+ ProjectSummarySchema,
246
+ UploadedAttachmentSchema,
247
+ WorkspaceRelativePathSchema,
248
+ external_exports
249
+ } from "./chunk-B2F6MLVZ.js";
250
+ import "./chunk-NFRJDPB3.js";
128
251
  import {
129
252
  ChevronUp,
130
253
  isSafeExternalUrl
@@ -143,13 +266,14 @@ import {
143
266
  useOpenMethodTriggerProps,
144
267
  usePositioner,
145
268
  useToolbarRootContext
146
- } from "./chunk-C7EKOPZU.js";
269
+ } from "./chunk-DO3TVNGA.js";
270
+ import "./chunk-RJOANOT4.js";
147
271
  import {
148
272
  ChevronDown
149
273
  } from "./chunk-QLY3L4A2.js";
150
274
  import {
151
275
  Input
152
- } from "./chunk-JD6EWZCU.js";
276
+ } from "./chunk-VHCAD46L.js";
153
277
  import {
154
278
  Check,
155
279
  useControlled
@@ -196,33 +320,7 @@ import {
196
320
  usePopupRootSync,
197
321
  useSurface,
198
322
  useTriggerDataForwarding
199
- } from "./chunk-AQWTGP35.js";
200
- import {
201
- useBaseUiId
202
- } from "./chunk-XYYNYFFD.js";
203
- import {
204
- ChatOpenUIArtifactUpsertRequestSchema,
205
- ChatOpenUIArtifactUpsertResponseSchema,
206
- ChatPlanPresentationSchema,
207
- ChatPlanPresentationUpsertRequestSchema,
208
- ChatQuestionAnswerResponseSchema,
209
- ChatSessionMetadataSchema,
210
- ChatSessionResponseSchema,
211
- ChatSessionsResponseSchema,
212
- ChatStreamEventSchema,
213
- ChatThinkingLevelSchema,
214
- ProjectCreateRequestSchema,
215
- ProjectDirectoryBrowseResponseSchema,
216
- ProjectForkRequestSchema,
217
- ProjectForkResponseSchema,
218
- ProjectListResponseSchema,
219
- ProjectRenameRequestSchema,
220
- ProjectSummarySchema,
221
- UploadedAttachmentSchema,
222
- WorkspaceRelativePathSchema,
223
- external_exports
224
- } from "./chunk-KAWYGHDN.js";
225
- import "./chunk-RJOANOT4.js";
323
+ } from "./chunk-FE4KN6T2.js";
226
324
  import {
227
325
  Button,
228
326
  CLICK_TRIGGER_IDENTIFIER,
@@ -247,6 +345,9 @@ import {
247
345
  isOutsideEvent,
248
346
  ownerDocument
249
347
  } from "./chunk-RPROZ2JC.js";
348
+ import {
349
+ useBaseUiId
350
+ } from "./chunk-XYYNYFFD.js";
250
351
  import {
251
352
  CompositeRootContext,
252
353
  EMPTY_ARRAY,
@@ -272,97 +373,21 @@ import {
272
373
  useStableCallback
273
374
  } from "./chunk-X2TUFLTP.js";
274
375
  import {
275
- DESKTOP_PANEL_ONLY,
276
- File,
277
- FolderOpen,
278
- RESOURCE_CANVAS_VIEWPORT_RATIO,
279
- SharedLayoutBg,
280
- availableThinkingLevels,
281
- clampThinkingLevel,
282
- normalizeSessionLabel,
283
- queueLabel,
284
- readStoredWidth,
285
- startHorizontalResize,
286
- storeStoredWidth,
287
- thinkingLevelLabel,
288
- toModelOption,
289
- toModelSelection
290
- } from "./chunk-MK3P3OBZ.js";
291
- import {
292
- AnimatePresence,
293
- EASE_DRAWER,
294
- EASE_IN_OUT,
295
- EASE_OUT,
296
- MotionConfigContext,
297
- SPRING_GLIDE,
298
- SPRING_LAYOUT,
299
- SPRING_MOUSE,
300
- SPRING_PANEL,
301
- SPRING_PRESS,
302
- SPRING_SWAP,
303
- m,
304
- motion,
305
- resolveWorkspacePanelTarget,
306
- useConstant,
307
- useIsomorphicLayoutEffect,
308
- useReducedMotion
309
- } from "./chunk-XXNFEXDU.js";
310
- import {
311
- Folder
312
- } from "./chunk-OLG5DQ7V.js";
313
- import {
314
- ChevronRight
315
- } from "./chunk-7QCDOBZ3.js";
316
- import "./chunk-QK4CHLVV.js";
317
- import {
318
- HTMLVisualElement,
319
- JSAnimation,
320
- LayoutGroupContext,
321
- SVGVisualElement,
322
- VisualElement,
323
- animateSingleValue,
324
- animateTarget,
325
- cancelFrame,
326
- collectMotionValues,
327
- createBox,
328
- createGeneratorEasing,
329
- defaultOffset,
330
- fillOffset,
331
- frame,
332
- interpolate,
333
- invariant,
334
- isEasingArray,
335
- isGenerator,
336
- isMotionValue,
337
- isSVGElement,
338
- isSVGSVGElement,
339
- mixNumber$1,
340
- motionValue,
341
- progress,
342
- removeItem,
343
- resolveElements,
344
- resolveTransition,
345
- reverseEasing,
346
- secondsToMilliseconds,
347
- spring,
348
- visualElementStore,
349
- warning
350
- } from "./chunk-FAGDMGLK.js";
351
- import "./chunk-BYXBJQAS.js";
352
- import {
353
- countWorkspaceFiles,
354
- findWorkspaceNode,
355
376
  getResourceGroups
356
- } from "./chunk-I3FDTJFO.js";
377
+ } from "./chunk-46VQY7SG.js";
357
378
  import {
358
379
  CircleAlert,
359
380
  FileText
360
381
  } from "./chunk-7APYEQIO.js";
382
+ import "./chunk-BSFYTSN6.js";
383
+ import "./chunk-EAJTWMK5.js";
361
384
  import {
362
385
  Package
363
386
  } from "./chunk-ZGFQ7HIX.js";
364
- import "./chunk-BSFYTSN6.js";
365
- import "./chunk-EAJTWMK5.js";
387
+ import {
388
+ SquareTerminal
389
+ } from "./chunk-G5BCQQ5N.js";
390
+ import "./chunk-BYXBJQAS.js";
366
391
  import {
367
392
  createLucideIcon
368
393
  } from "./chunk-E26EAQIM.js";
@@ -376,7 +401,7 @@ import "./chunk-JDCCC7A7.js";
376
401
  import "./chunk-L547YHC4.js";
377
402
  import "./chunk-MLKGABMK.js";
378
403
 
379
- // web/app/dist/server/assets/routes-BX4Tv-6R.js
404
+ // web/app/dist/server/assets/routes-BznemByz.js
380
405
  import * as React$1 from "react";
381
406
  import { Suspense, cloneElement, createContext as createContext2, createElement, forwardRef as forwardRef2, isValidElement, lazy, memo, useCallback as useCallback2, useContext as useContext2, useEffect as useEffect2, useEffectEvent, useId, useInsertionEffect, useLayoutEffect, useMemo as useMemo2, useReducer, useRef as useRef2, useState as useState2, useSyncExternalStore } from "react";
382
407
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
@@ -1093,10 +1118,6 @@ var Bookmark = createLucideIcon("bookmark", [["path", {
1093
1118
  d: "M17 3a2 2 0 0 1 2 2v15a1 1 0 0 1-1.496.868l-4.512-2.578a2 2 0 0 0-1.984 0l-4.512 2.578A1 1 0 0 1 5 20V5a2 2 0 0 1 2-2z",
1094
1119
  key: "oz39mx"
1095
1120
  }]]);
1096
- var ChevronLeft = createLucideIcon("chevron-left", [["path", {
1097
- d: "m15 18-6-6 6-6",
1098
- key: "1wnfg3"
1099
- }]]);
1100
1121
  var ChevronsUpDown = createLucideIcon("chevrons-up-down", [["path", {
1101
1122
  d: "m7 15 5 5 5-5",
1102
1123
  key: "1hf1tw"
@@ -1172,42 +1193,6 @@ var Ellipsis = createLucideIcon("ellipsis", [
1172
1193
  key: "1pcz8c"
1173
1194
  }]
1174
1195
  ]);
1175
- var FileBraces = createLucideIcon("file-braces", [
1176
- ["path", {
1177
- d: "M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z",
1178
- key: "1oefj6"
1179
- }],
1180
- ["path", {
1181
- d: "M14 2v5a1 1 0 0 0 1 1h5",
1182
- key: "wfsgrz"
1183
- }],
1184
- ["path", {
1185
- d: "M10 12a1 1 0 0 0-1 1v1a1 1 0 0 1-1 1 1 1 0 0 1 1 1v1a1 1 0 0 0 1 1",
1186
- key: "1oajmo"
1187
- }],
1188
- ["path", {
1189
- d: "M14 18a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1 1 1 0 0 1-1-1v-1a1 1 0 0 0-1-1",
1190
- key: "mpwhp6"
1191
- }]
1192
- ]);
1193
- var FileCode = createLucideIcon("file-code", [
1194
- ["path", {
1195
- d: "M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z",
1196
- key: "1oefj6"
1197
- }],
1198
- ["path", {
1199
- d: "M14 2v5a1 1 0 0 0 1 1h5",
1200
- key: "wfsgrz"
1201
- }],
1202
- ["path", {
1203
- d: "M10 12.5 8 15l2 2.5",
1204
- key: "1tg20x"
1205
- }],
1206
- ["path", {
1207
- d: "m14 12.5 2 2.5-2 2.5",
1208
- key: "yinavb"
1209
- }]
1210
- ]);
1211
1196
  var FilePlusCorner = createLucideIcon("file-plus-corner", [
1212
1197
  ["path", {
1213
1198
  d: "M11.35 22H6a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.706.706l3.588 3.588A2.4 2.4 0 0 1 20 8v5.35",
@@ -1265,27 +1250,6 @@ var Gauge = createLucideIcon("gauge", [["path", {
1265
1250
  d: "M3.34 19a10 10 0 1 1 17.32 0",
1266
1251
  key: "19p75a"
1267
1252
  }]]);
1268
- var Image = createLucideIcon("image", [
1269
- ["rect", {
1270
- width: "18",
1271
- height: "18",
1272
- x: "3",
1273
- y: "3",
1274
- rx: "2",
1275
- ry: "2",
1276
- key: "1m3agn"
1277
- }],
1278
- ["circle", {
1279
- cx: "9",
1280
- cy: "9",
1281
- r: "2",
1282
- key: "af1f0g"
1283
- }],
1284
- ["path", {
1285
- d: "m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21",
1286
- key: "1xmnt7"
1287
- }]
1288
- ]);
1289
1253
  var ListRestart = createLucideIcon("list-restart", [
1290
1254
  ["path", {
1291
1255
  d: "M21 5H3",
@@ -2621,14 +2585,16 @@ function RightPanelLauncherFromContext() {
2621
2585
  })] });
2622
2586
  }
2623
2587
  function RightPanelTabsFromContext({ idPrefix = "right-panel" }) {
2624
- const { artifactRuns, messages, rightPanel, setRightPanel, resources } = useChatPanelDataContext();
2588
+ const { artifactRuns, messages, presentation, rightPanel, setRightPanel, resources } = useChatPanelDataContext();
2625
2589
  const { workspaceTree } = useWorkspaceTreeContext();
2626
2590
  return /* @__PURE__ */ jsx(RightPanelLauncher, {
2627
2591
  activePanel: rightPanel,
2628
2592
  onPanelChange: setRightPanel,
2629
2593
  resources,
2594
+ replRuns: artifactRuns.flatMap((run) => run.artifacts).filter((artifact) => artifact.kind === "ipython").length,
2630
2595
  sessionBlocks: collectSessionOpenUIBlocks(messages).length,
2631
- technicalArtifacts: artifactRuns.flatMap((run) => run.artifacts).length,
2596
+ subagents: presentation.rlmChildren.length,
2597
+ openUIArtifacts: artifactRuns.flatMap((run) => run.artifacts).filter((artifact) => artifact.kind === "openui-html").length,
2632
2598
  workspace: workspaceTree,
2633
2599
  idPrefix
2634
2600
  });
@@ -2641,45 +2607,119 @@ function RightPanelTrigger({ onOpen }) {
2641
2607
  children: /* @__PURE__ */ jsx(PanelRight, { className: "size-4" })
2642
2608
  });
2643
2609
  }
2644
- function RightPanelLauncher({ activePanel, onPanelChange, resources, sessionBlocks = 0, technicalArtifacts = 0, workspace, idPrefix = "right-panel" }) {
2610
+ function RightPanelLauncher({ activePanel, onPanelChange, resources, replRuns = 0, sessionBlocks = 0, subagents = 0, openUIArtifacts = 0, workspace, idPrefix = "right-panel" }) {
2645
2611
  const totalResources = getResourceGroups(resources, workspace).reduce((count, group) => count + group.items.length, 0);
2646
2612
  const totalArtifacts = useMemo2(() => {
2647
- const total = (() => {
2648
- if (!workspace) return 0;
2649
- const artifactsRoot = findWorkspaceNode(workspace.nodes, getArtifactsScopePath(workspace.root));
2650
- if (!artifactsRoot?.children?.length) return 0;
2651
- return countWorkspaceFiles(artifactsRoot.children);
2652
- })() + sessionBlocks + technicalArtifacts;
2613
+ const total = sessionBlocks + openUIArtifacts;
2653
2614
  return total > 0 ? total : void 0;
2654
- }, [
2655
- sessionBlocks,
2656
- technicalArtifacts,
2657
- workspace
2658
- ]);
2615
+ }, [openUIArtifacts, sessionBlocks]);
2659
2616
  const tabs = useMemo2(() => RIGHT_PANEL_DEFINITIONS.map((definition) => ({
2660
2617
  ...definition,
2661
- badge: definition.badgeSource === "resources" ? totalResources || void 0 : definition.badgeSource === "artifacts" ? totalArtifacts : void 0
2662
- })), [totalArtifacts, totalResources]);
2618
+ badge: definition.badgeSource === "resources" ? totalResources || void 0 : definition.badgeSource === "artifacts" ? totalArtifacts : definition.badgeSource === "repl" ? replRuns || void 0 : definition.badgeSource === "subagents" ? subagents || void 0 : void 0
2619
+ })), [
2620
+ replRuns,
2621
+ subagents,
2622
+ totalArtifacts,
2623
+ totalResources
2624
+ ]);
2663
2625
  const selectedIndex = tabs.findIndex((tab) => tab.id === activePanel);
2664
- return /* @__PURE__ */ jsx(TabsSubtle, {
2665
- activeLabel: true,
2666
- className: "w-fit max-w-full",
2626
+ const panelOptions = useMemo2(() => tabs.map((tab) => ({
2627
+ value: tab.id,
2628
+ label: tab.title,
2629
+ icon: tab.icon
2630
+ })), [tabs]);
2631
+ return /* @__PURE__ */ jsx(ResponsivePanelLauncher, {
2667
2632
  "data-testid": "right-panel-inline-launcher",
2668
2633
  "data-active-panel": activePanel ?? "closed",
2634
+ activePanel,
2635
+ options: panelOptions,
2636
+ panelOptions: tabs,
2669
2637
  idPrefix,
2670
2638
  selectedIndex,
2671
2639
  onSelect: (index) => {
2672
2640
  const next = tabs.at(index)?.id;
2673
2641
  if (!next) return;
2674
2642
  onPanelChange(next === activePanel ? null : next);
2675
- },
2676
- children: tabs.map((tab, index) => /* @__PURE__ */ jsx(TabsSubtleItem, {
2677
- index,
2678
- icon: tab.icon,
2679
- label: tab.title,
2680
- badge: tab.badge,
2681
- "aria-label": tab.ariaLabel
2682
- }, tab.id))
2643
+ }
2644
+ });
2645
+ }
2646
+ function ResponsivePanelLauncher({ activePanel, className, idPrefix, onSelect, options, panelOptions, selectedIndex, ...props }) {
2647
+ const containerRef = useRef2(null);
2648
+ const measurementRef = useRef2(null);
2649
+ const [isDropdown, setIsDropdown] = useState2(false);
2650
+ const measure = useCallback2(() => {
2651
+ const container = containerRef.current;
2652
+ const measurement = measurementRef.current;
2653
+ if (!container || !measurement) return;
2654
+ const availableWidth = container.parentElement?.clientWidth ?? container.clientWidth;
2655
+ const requiredWidth = measurement.getBoundingClientRect().width;
2656
+ setIsDropdown(requiredWidth > availableWidth + 1);
2657
+ }, []);
2658
+ useLayoutEffect(() => {
2659
+ measure();
2660
+ const container = containerRef.current;
2661
+ const measurement = measurementRef.current;
2662
+ if (!container || !measurement || typeof ResizeObserver === "undefined") return;
2663
+ const observer = new ResizeObserver(measure);
2664
+ if (container.parentElement) observer.observe(container.parentElement);
2665
+ observer.observe(container);
2666
+ observer.observe(measurement);
2667
+ return () => observer.disconnect();
2668
+ }, [
2669
+ measure,
2670
+ panelOptions,
2671
+ selectedIndex
2672
+ ]);
2673
+ const selectPanel = useCallback2((nextPanel) => {
2674
+ const nextIndex = panelOptions.findIndex((panel) => panel.id === nextPanel);
2675
+ if (nextIndex >= 0) onSelect(nextIndex);
2676
+ }, [onSelect, panelOptions]);
2677
+ return /* @__PURE__ */ jsxs("div", {
2678
+ ref: containerRef,
2679
+ className: `relative ${isDropdown ? "w-full" : "w-fit"} min-w-0 max-w-full overflow-hidden ${className ?? ""}`,
2680
+ "data-panel-launcher-mode": isDropdown ? "dropdown" : "tabs",
2681
+ ...props,
2682
+ children: [isDropdown ? /* @__PURE__ */ jsx(Select, {
2683
+ "aria-label": "Select panel",
2684
+ className: "w-full min-w-0 max-w-full rounded-full border-border/70 bg-sidebar",
2685
+ onValueChange: selectPanel,
2686
+ options,
2687
+ placeholder: "Open panel",
2688
+ value: activePanel
2689
+ }) : /* @__PURE__ */ jsx(TabsSubtle, {
2690
+ activeLabel: true,
2691
+ className: "w-fit max-w-full",
2692
+ idPrefix,
2693
+ selectedIndex,
2694
+ onSelect,
2695
+ children: panelOptions.map((panel, index) => /* @__PURE__ */ jsx(TabsSubtleItem, {
2696
+ index,
2697
+ icon: panel.icon,
2698
+ label: panel.title,
2699
+ badge: panel.badge,
2700
+ "aria-label": panel.ariaLabel
2701
+ }, panel.id))
2702
+ }), /* @__PURE__ */ jsx("div", {
2703
+ ref: measurementRef,
2704
+ "aria-hidden": "true",
2705
+ className: "pointer-events-none invisible absolute top-0 left-0 -z-10 h-0 w-max max-w-none overflow-hidden",
2706
+ "data-panel-launcher-measurement": true,
2707
+ inert: true,
2708
+ children: /* @__PURE__ */ jsx(TabsSubtle, {
2709
+ activeLabel: true,
2710
+ className: "w-max max-w-none",
2711
+ idPrefix: `${idPrefix}-measurement`,
2712
+ selectedIndex,
2713
+ onSelect: () => void 0,
2714
+ children: panelOptions.map((panel, index) => /* @__PURE__ */ jsx(TabsSubtleItem, {
2715
+ index,
2716
+ icon: panel.icon,
2717
+ label: panel.title,
2718
+ badge: panel.badge,
2719
+ "aria-label": panel.ariaLabel
2720
+ }, panel.id))
2721
+ })
2722
+ })]
2683
2723
  });
2684
2724
  }
2685
2725
  function MobilePanel({ children, dataTestid, headerActions, icon: Icon, onClose, open, title }) {
@@ -2780,10 +2820,10 @@ function MobilePanel({ children, dataTestid, headerActions, icon: Icon, onClose,
2780
2820
  })
2781
2821
  });
2782
2822
  }
2783
- function RightPanelShell({ handleResourceCanvasResizeStart, resourceCanvasWidth }) {
2823
+ function RightPanelShell({ handleResourceCanvasResizeStart, onClose, resourceCanvasWidth }) {
2784
2824
  const chat = useChatPanelDataContext();
2785
2825
  const workspace = useWorkspaceTreeContext();
2786
- const { rightPanel, setRightPanel } = chat;
2826
+ const { rightPanel } = chat;
2787
2827
  const panelOpen = rightPanel !== null;
2788
2828
  const definition = rightPanel ? getRightPanelDefinition(rightPanel) : null;
2789
2829
  const PanelContent = definition?.component;
@@ -2792,7 +2832,7 @@ function RightPanelShell({ handleResourceCanvasResizeStart, resourceCanvasWidth
2792
2832
  return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(MobilePanel, {
2793
2833
  dataTestid: definition?.mobileDataTestid,
2794
2834
  icon: definition?.icon,
2795
- onClose: () => setRightPanel(null),
2835
+ onClose,
2796
2836
  open: panelOpen,
2797
2837
  title: definition?.title ?? "",
2798
2838
  children: PanelContent ? /* @__PURE__ */ jsx(PanelContent, {}) : null
@@ -2800,7 +2840,7 @@ function RightPanelShell({ handleResourceCanvasResizeStart, resourceCanvasWidth
2800
2840
  dataTestid: definition?.dataTestid,
2801
2841
  headerLeading: /* @__PURE__ */ jsx(RightPanelTabsFromContext, { idPrefix: "right-panel-desktop" }),
2802
2842
  loading,
2803
- onClose: () => setRightPanel(null),
2843
+ onClose,
2804
2844
  onRefresh,
2805
2845
  onResizeStart: handleResourceCanvasResizeStart,
2806
2846
  open: panelOpen,
@@ -4626,7 +4666,7 @@ function MorphPopover({ children, open: controlledOpen, defaultOpen = false, onO
4626
4666
  })
4627
4667
  });
4628
4668
  }
4629
- function mergeRefs$2(...refs) {
4669
+ function mergeRefs$1(...refs) {
4630
4670
  return (node) => {
4631
4671
  for (const ref of refs) if (typeof ref === "function") ref(node);
4632
4672
  else if (ref && typeof ref === "object") ref.current = node;
@@ -4640,7 +4680,7 @@ function MorphPopoverTrigger({ children }) {
4640
4680
  const childRef = child.props.ref;
4641
4681
  return cloneElement(child, {
4642
4682
  id: ctx.triggerId,
4643
- ref: mergeRefs$2(childRef, (node) => {
4683
+ ref: mergeRefs$1(childRef, (node) => {
4644
4684
  ctx.triggerRef.current = node;
4645
4685
  }),
4646
4686
  onClick: (e) => {
@@ -6051,7 +6091,7 @@ function useComboboxContext(component) {
6051
6091
  if (!context) throw new Error(`${component} must be used within <Combobox>`);
6052
6092
  return context;
6053
6093
  }
6054
- function mergeRefs$1(...refs) {
6094
+ function mergeRefs(...refs) {
6055
6095
  return (node) => {
6056
6096
  for (const ref of refs) if (typeof ref === "function") ref(node);
6057
6097
  else if (ref && typeof ref === "object") ref.current = node;
@@ -6525,7 +6565,7 @@ function ComboboxInput({ ref, className, wrapperClassName, "aria-label": ariaLab
6525
6565
  className: "size-4 shrink-0 text-muted-foreground"
6526
6566
  }), /* @__PURE__ */ jsx("input", {
6527
6567
  ...props,
6528
- ref: mergeRefs$1(ref, context.inputRef),
6568
+ ref: mergeRefs(ref, context.inputRef),
6529
6569
  id: context.inputId,
6530
6570
  role: "combobox",
6531
6571
  "aria-label": ariaLabel,
@@ -7048,907 +7088,246 @@ function FleetSessionSidebar({ data, sessionActions, projectActions = {}, naviga
7048
7088
  submitCreate
7049
7089
  })] });
7050
7090
  }
7051
- var MessageSideContext = createContext2(void 0);
7052
- var MessageBubbleContext = createContext2({
7053
- animateIn: true,
7054
- variant: "soft"
7055
- });
7056
- var MessageBubbleLayoutContext = createContext2(() => {
7057
- });
7058
- function mergeRefs(...refs) {
7059
- return (node) => {
7060
- for (const ref of refs) if (typeof ref === "function") ref(node);
7061
- else if (ref) ref.current = node;
7062
- };
7091
+ var EMPTY_CITATIONS = [];
7092
+ function ResponseAction({ label, active = false, onClick, children }) {
7093
+ const reduce = useReducedMotion() ?? false;
7094
+ return /* @__PURE__ */ jsx(m.button, {
7095
+ type: "button",
7096
+ "aria-label": label,
7097
+ title: label,
7098
+ "aria-pressed": label === "Helpful" || label === "Not helpful" ? active : void 0,
7099
+ onClick,
7100
+ whileTap: reduce ? void 0 : { scale: 0.9 },
7101
+ transition: SPRING_PRESS,
7102
+ className: cn("grid size-7 place-items-center rounded-md text-muted-foreground outline-none transition-colors hover:bg-muted hover:text-foreground focus-visible:ring-2 focus-visible:ring-ring", active && "bg-muted text-foreground"),
7103
+ children
7104
+ });
7063
7105
  }
7064
- var BUBBLE_CONTENT_REVEAL = {
7065
- duration: 0.12,
7066
- ease: EASE_OUT,
7067
- delay: 0.04
7068
- };
7069
- var BUBBLE_POP = {
7070
- type: "spring",
7071
- stiffness: 520,
7072
- damping: 27,
7073
- mass: 0.52
7074
- };
7075
- function MessageBubble({ variant = "soft", align, animateIn = false, className, children, initial: initial2, animate: animate2, exit, transition, layout, ...props }) {
7106
+ function StreamingResponse({ children, status = "streaming", copyText, onCopy, onRetry, sources = EMPTY_CITATIONS, sourcesOpen, defaultSourcesOpen = false, onSourcesOpenChange, sourceIdPrefix, feedback, defaultFeedback = null, onFeedbackChange, announce = true, showActions = true, className, contentClassName, actionsClassName }) {
7076
7107
  const reduce = useReducedMotion() ?? false;
7077
- const messageSide = useContext2(MessageSideContext);
7078
- const resolvedAlign = align ?? messageSide ?? "start";
7079
- const messageBubbleContextValue = useMemo2(() => ({
7080
- align: resolvedAlign,
7081
- animateIn,
7082
- variant
7083
- }), [
7084
- animateIn,
7085
- resolvedAlign,
7086
- variant
7087
- ]);
7088
- return /* @__PURE__ */ jsx(MessageBubbleContext.Provider, {
7089
- value: messageBubbleContextValue,
7090
- children: /* @__PURE__ */ jsx(m.div, {
7091
- "data-slot": "message-bubble",
7092
- "data-align": resolvedAlign,
7093
- "data-variant": variant,
7094
- layout,
7095
- initial: initial2 ?? false,
7096
- animate: animate2,
7097
- exit: exit ?? (reduce ? { opacity: 0 } : {
7098
- opacity: 0,
7099
- y: -3,
7100
- scale: 0.99
7101
- }),
7102
- transition: transition ?? (reduce ? { duration: 0.12 } : SPRING_LAYOUT),
7103
- className: cn("group/bubble flex w-full flex-col", resolvedAlign === "end" ? "items-end" : "items-start", className),
7104
- ...props,
7108
+ const baseId = useId();
7109
+ const [copied, setCopied] = useState2(false);
7110
+ const [internalFeedback, setInternalFeedback] = useState2(defaultFeedback);
7111
+ const [internalSourcesOpen, setInternalSourcesOpen] = useState2(defaultSourcesOpen);
7112
+ const copyTimer = useRef2(void 0);
7113
+ const currentFeedback = feedback ?? internalFeedback;
7114
+ const currentSourcesOpen = sourcesOpen ?? internalSourcesOpen;
7115
+ const streaming = status === "streaming";
7116
+ const complete = status === "complete";
7117
+ const canCopy = Boolean(copyText || onCopy);
7118
+ const hasSources = sources.length > 0;
7119
+ const shouldShowActions = showActions && !streaming && (canCopy || onRetry || complete || hasSources);
7120
+ const sourcesContentId = `${baseId}-sources`;
7121
+ const resolvedSourcePrefix = sourceIdPrefix ?? `response-source-${baseId.replace(/:/g, "")}`;
7122
+ useEffect2(() => () => {
7123
+ if (copyTimer.current) window.clearTimeout(copyTimer.current);
7124
+ }, []);
7125
+ const handleCopy = useCallback2(async () => {
7126
+ if (onCopy) await onCopy();
7127
+ else if (copyText) await navigator.clipboard?.writeText(copyText);
7128
+ setCopied(true);
7129
+ if (copyTimer.current) window.clearTimeout(copyTimer.current);
7130
+ copyTimer.current = window.setTimeout(() => setCopied(false), 1600);
7131
+ }, [copyText, onCopy]);
7132
+ const setFeedback = (next) => {
7133
+ const value = currentFeedback === next ? null : next;
7134
+ if (feedback === void 0) setInternalFeedback(value);
7135
+ onFeedbackChange?.(value);
7136
+ };
7137
+ const setSourcesOpen = useCallback2((next) => {
7138
+ if (sourcesOpen === void 0) setInternalSourcesOpen(next);
7139
+ onSourcesOpenChange?.(next);
7140
+ }, [onSourcesOpenChange, sourcesOpen]);
7141
+ return /* @__PURE__ */ jsxs("div", {
7142
+ "data-state": status,
7143
+ "aria-busy": streaming,
7144
+ className: cn("w-full", className),
7145
+ children: [/* @__PURE__ */ jsx("div", {
7146
+ "aria-live": announce ? "polite" : "off",
7147
+ className: cn("text-sm leading-6 text-foreground/90 [&_a]:font-medium [&_a]:underline [&_a]:underline-offset-4 [&_code]:rounded [&_code]:bg-muted [&_code]:px-1 [&_code]:py-0.5 [&_code]:font-mono [&_code]:text-[0.9em] [&_ol]:my-3 [&_ol]:list-decimal [&_ol]:space-y-1 [&_ol]:pl-5 [&_p+p]:mt-3 [&_pre]:my-3 [&_pre]:overflow-x-auto [&_pre]:rounded-xl [&_pre]:border [&_pre]:border-border [&_pre]:bg-muted/45 [&_pre]:p-3 [&_pre_code]:bg-transparent [&_pre_code]:p-0 [&_ul]:my-3 [&_ul]:list-disc [&_ul]:space-y-1 [&_ul]:pl-5", contentClassName),
7105
7148
  children
7106
- })
7149
+ }), /* @__PURE__ */ jsx(AnimatePresence, {
7150
+ initial: false,
7151
+ children: shouldShowActions ? /* @__PURE__ */ jsxs(m.div, {
7152
+ initial: reduce ? { opacity: 0 } : {
7153
+ opacity: 0,
7154
+ y: 4
7155
+ },
7156
+ animate: {
7157
+ opacity: 1,
7158
+ y: 0
7159
+ },
7160
+ exit: { opacity: 0 },
7161
+ transition: {
7162
+ duration: reduce ? 0.12 : 0.22,
7163
+ ease: EASE_OUT
7164
+ },
7165
+ className: "mt-3",
7166
+ children: [/* @__PURE__ */ jsxs("div", {
7167
+ className: cn("flex items-center gap-0.5", actionsClassName),
7168
+ children: [
7169
+ canCopy ? /* @__PURE__ */ jsx(ResponseAction, {
7170
+ label: copied ? "Copied" : "Copy response",
7171
+ onClick: handleCopy,
7172
+ children: copied ? /* @__PURE__ */ jsx(Check, { className: "size-3.5" }) : /* @__PURE__ */ jsx(Copy, { className: "size-3.5" })
7173
+ }) : null,
7174
+ onRetry ? /* @__PURE__ */ jsx(ResponseAction, {
7175
+ label: "Retry response",
7176
+ onClick: onRetry,
7177
+ children: /* @__PURE__ */ jsx(RotateCcw, { className: "size-3.5" })
7178
+ }) : null,
7179
+ complete ? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(ResponseAction, {
7180
+ label: "Helpful",
7181
+ active: currentFeedback === "up",
7182
+ onClick: () => setFeedback("up"),
7183
+ children: /* @__PURE__ */ jsx(ThumbsUp, { className: "size-3.5" })
7184
+ }), /* @__PURE__ */ jsx(ResponseAction, {
7185
+ label: "Not helpful",
7186
+ active: currentFeedback === "down",
7187
+ onClick: () => setFeedback("down"),
7188
+ children: /* @__PURE__ */ jsx(ThumbsDown, { className: "size-3.5" })
7189
+ })] }) : null,
7190
+ hasSources ? /* @__PURE__ */ jsxs("button", {
7191
+ type: "button",
7192
+ "aria-expanded": currentSourcesOpen,
7193
+ "aria-controls": sourcesContentId,
7194
+ onClick: () => setSourcesOpen(!currentSourcesOpen),
7195
+ className: "group ml-1 inline-flex min-h-7 items-center gap-2 rounded-md px-1.5 text-xs text-muted-foreground outline-none transition-colors hover:text-foreground focus-visible:ring-2 focus-visible:ring-ring",
7196
+ children: [
7197
+ /* @__PURE__ */ jsx(CitationStack, { citations: sources }),
7198
+ /* @__PURE__ */ jsxs("span", {
7199
+ className: "tabular-nums",
7200
+ children: [
7201
+ sources.length,
7202
+ " ",
7203
+ sources.length === 1 ? "source" : "sources"
7204
+ ]
7205
+ }),
7206
+ /* @__PURE__ */ jsx(m.span, {
7207
+ "aria-hidden": "true",
7208
+ animate: { rotate: currentSourcesOpen ? 180 : 0 },
7209
+ transition: reduce ? { duration: 0 } : SPRING_SWAP,
7210
+ className: "text-muted-foreground/50 group-hover:text-muted-foreground",
7211
+ children: /* @__PURE__ */ jsx(ChevronDown, { className: "size-3" })
7212
+ })
7213
+ ]
7214
+ }) : null
7215
+ ]
7216
+ }), hasSources ? /* @__PURE__ */ jsx(AgentDisclosure, {
7217
+ id: sourcesContentId,
7218
+ open: currentSourcesOpen,
7219
+ children: /* @__PURE__ */ jsx(CitationList, {
7220
+ citations: sources,
7221
+ idPrefix: resolvedSourcePrefix,
7222
+ className: "mt-2 rounded-xl bg-muted p-2"
7223
+ })
7224
+ }) : null]
7225
+ }) : null
7226
+ })]
7107
7227
  });
7108
7228
  }
7109
- function bubbleContentClass(variant, interactive) {
7110
- return cn("relative z-0 min-w-9 max-w-[82%] rounded-2xl px-3.5 py-2.5 text-sm leading-6 text-foreground", "[&_a]:font-medium [&_a]:underline [&_a]:underline-offset-4 [&_code]:rounded [&_code]:bg-background/60 [&_code]:px-1 [&_code]:py-0.5 [&_code]:font-mono [&_code]:text-[0.9em] [&_ol]:my-2 [&_ol]:list-decimal [&_ol]:pl-5 [&_p+p]:mt-2 [&_pre]:my-2 [&_pre]:overflow-x-auto [&_pre]:rounded-xl [&_pre]:bg-background/60 [&_pre]:p-3 [&_ul]:my-2 [&_ul]:list-disc [&_ul]:pl-5", variant === "solid" && "text-background", variant === "ghost" && "w-full max-w-none rounded-none px-0 py-0", variant === "danger" && "text-destructive", interactive && "cursor-pointer text-left outline-none transition-[background-color,color,transform] duration-150 hover:brightness-[0.98] focus-visible:ring-2 focus-visible:ring-ring active:scale-[0.99]");
7111
- }
7112
- function bubbleSurfaceClass(variant, align) {
7113
- return cn("pointer-events-none absolute inset-0 -z-10 rounded-[inherit]", align === "end" ? "origin-bottom-right" : "origin-bottom-left", variant === "solid" && "bg-foreground", variant === "soft" && "bg-muted", variant === "tint" && "bg-primary/10", variant === "outline" && "border border-border/70 bg-background", variant === "danger" && "bg-destructive/10");
7229
+ var TEXT_SHIMMER_KEYFRAMES = "@keyframes beui-text-shimmer{from{background-position:200% 0}to{background-position:-200% 0}}@media (prefers-reduced-motion: reduce){.beui-text-shimmer{animation:none !important}}";
7230
+ var TEXT_SHIMMER_CLASS_NAME = "beui-text-shimmer bg-[length:200%_100%] bg-clip-text text-transparent bg-[linear-gradient(110deg,var(--muted-foreground)_30%,var(--foreground)_50%,var(--muted-foreground)_70%)]";
7231
+ function textShimmerStyle(duration) {
7232
+ return { animation: `beui-text-shimmer ${duration}s linear infinite` };
7114
7233
  }
7115
- function MessageBubbleContent({ render, className, children, ref, ...props }) {
7116
- const reduce = useReducedMotion() ?? false;
7117
- const { align = "start", animateIn, variant } = useContext2(MessageBubbleContext);
7118
- const [layoutVersion, setLayoutVersion] = useState2(0);
7119
- const notifyLayout = useCallback2(() => setLayoutVersion((version) => version + 1), []);
7120
- const interactive = render?.type === "button" || render?.type === "a";
7121
- const classes = cn(bubbleContentClass(variant, interactive), className);
7122
- const composedChildren = /* @__PURE__ */ jsxs(Fragment$1, { children: [variant !== "ghost" ? /* @__PURE__ */ jsx(m.span, {
7123
- "aria-hidden": "true",
7124
- layout: reduce ? false : "size",
7125
- layoutDependency: layoutVersion,
7126
- initial: animateIn && !reduce ? {
7127
- opacity: 0,
7128
- scale: 0.92
7129
- } : false,
7130
- animate: {
7131
- opacity: 1,
7132
- scale: 1
7133
- },
7134
- transition: reduce ? { duration: 0 } : {
7135
- opacity: {
7136
- duration: 0.12,
7137
- ease: EASE_OUT
7138
- },
7139
- scale: BUBBLE_POP,
7140
- layout: SPRING_LAYOUT
7141
- },
7142
- className: bubbleSurfaceClass(variant, align)
7143
- }) : null, /* @__PURE__ */ jsx(MessageBubbleLayoutContext.Provider, {
7144
- value: notifyLayout,
7145
- children: /* @__PURE__ */ jsx(m.div, {
7146
- initial: animateIn ? reduce ? { opacity: 0 } : { opacity: 0 } : false,
7147
- animate: { opacity: 1 },
7148
- transition: reduce ? {
7149
- duration: 0.12,
7150
- ease: EASE_OUT
7151
- } : BUBBLE_CONTENT_REVEAL,
7152
- className: "relative",
7153
- children
7154
- })
7234
+ function TextShimmer({ children, as: Comp = "span", duration = 2.5, className }) {
7235
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("style", { children: TEXT_SHIMMER_KEYFRAMES }), /* @__PURE__ */ jsx(Comp, {
7236
+ style: textShimmerStyle(duration),
7237
+ className: cn("inline-block", TEXT_SHIMMER_CLASS_NAME, className),
7238
+ children
7155
7239
  })] });
7156
- if (render) {
7157
- const child = render;
7158
- return cloneElement(child, {
7159
- ...props,
7160
- ref: mergeRefs(child.props.ref, ref),
7161
- className: cn(classes, child.props.className),
7162
- children: composedChildren,
7163
- "data-slot": "message-bubble-content"
7164
- });
7165
- }
7166
- return /* @__PURE__ */ jsx("div", {
7167
- ref,
7168
- "data-slot": "message-bubble-content",
7169
- className: classes,
7170
- ...props,
7171
- children: composedChildren
7172
- });
7173
7240
  }
7174
- function DefaultPreview({ item }) {
7175
- return /* @__PURE__ */ jsxs("div", {
7176
- "data-slot": "preview-rail-card",
7177
- className: "rounded-2xl border border-border bg-card p-4 shadow-sm",
7178
- children: [/* @__PURE__ */ jsx("p", {
7179
- "data-slot": "preview-rail-title",
7180
- className: "font-medium text-card-foreground",
7181
- children: item.label
7182
- }), item.description ? /* @__PURE__ */ jsx("div", {
7183
- "data-slot": "preview-rail-description",
7184
- className: "mt-1 text-sm leading-6 text-muted-foreground",
7185
- children: item.description
7186
- }) : null]
7241
+ function ThinkingShimmer({ children = "Thinking\u2026", duration = 1.8, className }) {
7242
+ return /* @__PURE__ */ jsx(TextShimmer, {
7243
+ as: "span",
7244
+ duration,
7245
+ className: cn("font-medium", className),
7246
+ children
7187
7247
  });
7188
7248
  }
7189
- function PreviewRail({ items, label = "Section navigation", orientation = "vertical", activeId, defaultActiveId, onActiveChange, onItemSelect, renderPreview, showPreview = true, previewSide = "after", highlightActive = false, itemSize = 24, children, className, railClassName, previewContainerClassName, previewClassName }) {
7190
- const uid = useId();
7191
- const reduce = useReducedMotion();
7192
- const canHover = useHoverCapable();
7193
- const [internalActiveId, setInternalActiveId] = useState2(defaultActiveId ?? items[0]?.id ?? "");
7194
- const [hoveredId, setHoveredId] = useState2(null);
7195
- const [focusedId, setFocusedId] = useState2(null);
7196
- const requestedActiveId = activeId ?? internalActiveId;
7197
- const selectedId = items.some((item) => item.id === requestedActiveId) ? requestedActiveId : items[0]?.id ?? "";
7198
- const displayedId = hoveredId ?? focusedId ?? "";
7199
- const highlightedId = displayedId || (highlightActive ? selectedId : "");
7200
- const displayedIndex = items.findIndex((item) => item.id === highlightedId);
7201
- const rowTemplate = items.length ? `repeat(${items.length}, ${itemSize}px)` : void 0;
7202
- const isHorizontal = orientation === "horizontal";
7203
- const selectItem = (id) => {
7204
- if (activeId === void 0) setInternalActiveId(id);
7205
- onActiveChange?.(id);
7206
- };
7207
- return /* @__PURE__ */ jsxs(m.div, {
7208
- layoutRoot: true,
7209
- onBlur: (event) => {
7210
- if (!event.currentTarget.contains(event.relatedTarget)) setFocusedId(null);
7211
- },
7212
- className: cn("isolate relative flex w-full overflow-visible", isHorizontal ? "min-h-64 flex-col items-center justify-center" : "min-h-80", className),
7213
- children: [
7214
- /* @__PURE__ */ jsx("nav", {
7215
- "aria-label": label,
7216
- onPointerLeave: () => setHoveredId(null),
7217
- style: isHorizontal ? { gridTemplateColumns: rowTemplate } : { gridTemplateRows: rowTemplate },
7218
- className: cn("relative z-10 grid shrink-0", isHorizontal ? "h-12 w-fit max-w-full self-center justify-center" : "w-12 content-center", railClassName),
7219
- children: items.map((item, index) => {
7220
- const selected = item.id === selectedId;
7221
- const highlighted = item.id === highlightedId;
7222
- const distance = displayedIndex < 0 ? Number.POSITIVE_INFINITY : Math.abs(index - displayedIndex);
7223
- const scale = highlighted ? 1 : distance === 1 ? 0.68 : distance === 2 ? 0.44 : 0.25;
7224
- const itemContent = /* @__PURE__ */ jsx(Fragment$1, { children: /* @__PURE__ */ jsx(m.span, {
7225
- "data-slot": "preview-rail-tick",
7226
- "aria-hidden": "true",
7227
- animate: isHorizontal ? { scaleY: scale } : { scaleX: scale },
7228
- transition: reduce ? { duration: 0 } : SPRING_LAYOUT,
7229
- className: cn("block bg-current", isHorizontal ? "h-12 w-0.5 origin-bottom" : "h-0.5 w-12 origin-left", highlighted ? "text-foreground" : void 0)
7230
- }) });
7231
- const sharedClassName = cn("relative flex text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background", isHorizontal ? "h-12 w-6 items-end justify-center" : "h-6 w-12 items-center");
7232
- const sharedStyle = isHorizontal ? { width: itemSize } : { height: itemSize };
7233
- const handlePointerEnter = () => {
7234
- if (canHover) setHoveredId(item.id);
7235
- };
7236
- const handleFocus = (currentTarget) => {
7237
- if (currentTarget.matches(":focus-visible")) setFocusedId(item.id);
7238
- };
7239
- const handleSelect = () => {
7240
- selectItem(item.id);
7241
- onItemSelect?.(item);
7242
- };
7243
- return item.href ? /* @__PURE__ */ jsx("a", {
7244
- "data-slot": "preview-rail-item",
7245
- href: item.href,
7246
- target: item.target,
7247
- rel: item.rel ?? (item.target === "_blank" ? "noreferrer noopener" : void 0),
7248
- "aria-label": item.ariaLabel ?? item.label,
7249
- "aria-current": selected ? "page" : void 0,
7250
- onPointerEnter: handlePointerEnter,
7251
- onMouseEnter: handlePointerEnter,
7252
- onPointerDown: () => setFocusedId(null),
7253
- onFocus: (event) => handleFocus(event.currentTarget),
7254
- onClick: handleSelect,
7255
- style: sharedStyle,
7256
- className: sharedClassName,
7257
- children: itemContent
7258
- }, item.id) : /* @__PURE__ */ jsx("button", {
7259
- "data-slot": "preview-rail-item",
7260
- type: "button",
7261
- "aria-label": item.ariaLabel ?? item.label,
7262
- "aria-current": selected ? "location" : void 0,
7263
- onPointerEnter: handlePointerEnter,
7264
- onMouseEnter: handlePointerEnter,
7265
- onPointerDown: () => setFocusedId(null),
7266
- onFocus: (event) => handleFocus(event.currentTarget),
7267
- onClick: handleSelect,
7268
- style: sharedStyle,
7269
- className: sharedClassName,
7270
- children: itemContent
7271
- }, item.id);
7249
+ function StepRow({ item }) {
7250
+ const state = item.status ?? "complete";
7251
+ return /* @__PURE__ */ jsxs("div", {
7252
+ className: "flex min-h-7 items-start gap-2.5 rounded-md px-1.5 py-1",
7253
+ children: [
7254
+ /* @__PURE__ */ jsx("span", {
7255
+ "aria-hidden": "true",
7256
+ className: "mt-0.5 grid size-4 shrink-0 place-items-center text-muted-foreground/70",
7257
+ children: state === "complete" ? /* @__PURE__ */ jsx(Check, {
7258
+ className: "size-4",
7259
+ strokeWidth: 1.8
7260
+ }) : state === "active" ? /* @__PURE__ */ jsxs("span", {
7261
+ className: "relative grid size-3 place-items-center",
7262
+ children: [/* @__PURE__ */ jsx(motion.span, {
7263
+ className: "absolute inset-0 rounded-full bg-foreground/10",
7264
+ animate: { opacity: [
7265
+ 0.35,
7266
+ 0.8,
7267
+ 0.35
7268
+ ] },
7269
+ transition: {
7270
+ duration: 1.5,
7271
+ repeat: Number.POSITIVE_INFINITY
7272
+ }
7273
+ }), /* @__PURE__ */ jsx("span", { className: "size-1.5 rounded-full bg-foreground/60" })]
7274
+ }) : /* @__PURE__ */ jsx(Circle, {
7275
+ className: "size-3",
7276
+ strokeWidth: 1.5
7272
7277
  })
7273
7278
  }),
7274
- showPreview ? /* @__PURE__ */ jsx("div", {
7275
- "aria-hidden": "true",
7276
- style: isHorizontal ? { gridTemplateColumns: rowTemplate } : { gridTemplateRows: rowTemplate },
7277
- className: cn("pointer-events-none absolute z-50 grid", isHorizontal ? "top-1/2 left-1/2 h-5 w-fit max-w-full -translate-x-1/2 -translate-y-1/2 justify-center" : previewSide === "before" ? "inset-y-0 right-16 left-4 content-center" : "inset-y-0 right-4 left-16 content-center", previewContainerClassName),
7278
- children: items.map((item) => /* @__PURE__ */ jsx("div", {
7279
- style: isHorizontal ? { width: itemSize } : { height: itemSize },
7280
- className: cn("relative flex items-center", isHorizontal ? "justify-center" : void 0),
7281
- children: /* @__PURE__ */ jsx(AnimatePresence, {
7282
- mode: "wait",
7283
- initial: false,
7284
- children: item.id === displayedId ? /* @__PURE__ */ jsx(m.div, {
7285
- initial: reduce ? { opacity: 0 } : {
7286
- opacity: 0,
7287
- y: 4,
7288
- filter: "blur(6px)"
7289
- },
7290
- animate: reduce ? { opacity: 1 } : {
7291
- opacity: 1,
7292
- y: 0,
7293
- filter: "blur(0px)"
7294
- },
7295
- exit: reduce ? { opacity: 0 } : {
7296
- opacity: 0,
7297
- y: -2,
7298
- filter: "blur(4px)",
7299
- transition: {
7300
- duration: 0.12,
7301
- ease: EASE_OUT
7302
- }
7303
- },
7304
- transition: {
7305
- duration: reduce ? 0 : 0.18,
7306
- ease: EASE_OUT
7307
- },
7308
- className: cn(isHorizontal ? "absolute bottom-12 left-1/2 w-72 -translate-x-1/2" : cn("w-full max-w-sm", previewSide === "before" && "ml-auto"), previewClassName),
7309
- children: /* @__PURE__ */ jsx(m.div, {
7310
- layoutId: `preview-rail-card-${uid}`,
7311
- transition: reduce ? { duration: 0 } : SPRING_LAYOUT,
7312
- children: renderPreview ? renderPreview(item) : /* @__PURE__ */ jsx(DefaultPreview, { item })
7313
- })
7314
- }, item.id) : null
7315
- })
7316
- }, item.id))
7317
- }) : null,
7318
- children ? /* @__PURE__ */ jsx("div", {
7319
- className: "min-h-0 min-w-0 flex-1",
7320
- children
7279
+ /* @__PURE__ */ jsx("span", {
7280
+ className: cn("min-w-0 flex-1 leading-5", state === "pending" ? "text-muted-foreground/55" : "text-foreground/90"),
7281
+ children: item.label
7282
+ }),
7283
+ item.meta ? /* @__PURE__ */ jsx("span", {
7284
+ className: "shrink-0 leading-5 text-muted-foreground/55",
7285
+ children: item.meta
7321
7286
  }) : null
7322
7287
  ]
7323
7288
  });
7324
7289
  }
7325
- var PREVIEW_TITLE_LENGTH = 56;
7326
- var PREVIEW_DESCRIPTION_LENGTH = 88;
7327
- function truncateMessageText(text, limit) {
7328
- if (text.length <= limit) return text;
7329
- const excerpt = text.slice(0, limit);
7330
- const boundary = excerpt.lastIndexOf(" ");
7331
- return `${excerpt.slice(0, boundary > limit * 0.65 ? boundary : limit).trim()}\u2026`;
7332
- }
7333
- function getMessageText(message) {
7334
- return ((message.querySelector('[data-slot="message-bubble-content"]') ?? message.querySelector('[data-slot="message-content"]') ?? message).textContent ?? "").replace(/\s+/g, " ").trim();
7335
- }
7336
- function getMessagePreview(message, assistantResponse) {
7337
- const text = getMessageText(message);
7338
- if (!text) return {
7339
- label: "Message",
7340
- description: void 0
7341
- };
7342
- if (text.length <= PREVIEW_TITLE_LENGTH) {
7343
- const responseText2 = assistantResponse ? getMessageText(assistantResponse) : "";
7344
- return {
7345
- label: text,
7346
- description: responseText2 ? truncateMessageText(responseText2, PREVIEW_DESCRIPTION_LENGTH) : void 0
7347
- };
7348
- }
7349
- const titleBoundary = text.slice(0, PREVIEW_TITLE_LENGTH).lastIndexOf(" ");
7350
- const titleEnd = titleBoundary > PREVIEW_TITLE_LENGTH * 0.65 ? titleBoundary : PREVIEW_TITLE_LENGTH;
7351
- const label = `${text.slice(0, titleEnd).trim()}\u2026`;
7352
- const responseText = assistantResponse ? getMessageText(assistantResponse) : text.slice(titleEnd).trim();
7353
- return {
7354
- label,
7355
- description: responseText ? truncateMessageText(responseText, PREVIEW_DESCRIPTION_LENGTH) : void 0
7356
- };
7357
- }
7358
- function useMessageScrollerRail({ navigation, followThreshold, contentRef, viewportRef, reduce, smooth, scrollToEnd, setFollowing, markProgrammaticScroll }) {
7359
- const railFrameRef = useRef2(void 0);
7360
- const railIdRef = useRef2(/* @__PURE__ */ new WeakMap());
7361
- const railIdCounterRef = useRef2(0);
7362
- const railTargetsRef = useRef2(/* @__PURE__ */ new Map());
7363
- const [railItems, setRailItems] = useState2([]);
7364
- const [activeRailId, setActiveRailId] = useState2("");
7365
- const [railOverflowing, setRailOverflowing] = useState2(false);
7366
- const updateActiveRailItem = useCallback2(() => {
7367
- if (navigation !== "rail") return;
7368
- const viewport = viewportRef.current;
7369
- const targets = [...railTargetsRef.current.entries()];
7370
- if (!viewport || targets.length === 0) return;
7371
- const viewportRect = viewport.getBoundingClientRect();
7372
- if (viewport.scrollTop <= followThreshold) {
7373
- const firstId = targets[0]?.[0] ?? "";
7374
- setActiveRailId((current) => current === firstId ? current : firstId);
7375
- return;
7376
- }
7377
- if (viewport.scrollHeight - viewport.scrollTop - viewport.clientHeight <= followThreshold) {
7378
- const lastId = targets.at(-1)?.[0] ?? "";
7379
- setActiveRailId((current) => current === lastId ? current : lastId);
7380
- return;
7381
- }
7382
- const viewportCenter = viewportRect.top + viewportRect.height / 2;
7383
- let nearestId = targets[0]?.[0] ?? "";
7384
- let nearestDistance = Number.POSITIVE_INFINITY;
7385
- for (const [id, element] of targets) {
7386
- const rect = element.getBoundingClientRect();
7387
- const distance = Math.abs(rect.top + rect.height / 2 - viewportCenter);
7388
- if (distance < nearestDistance) {
7389
- nearestDistance = distance;
7390
- nearestId = id;
7391
- }
7392
- }
7393
- setActiveRailId((current) => current === nearestId ? current : nearestId);
7394
- }, [
7395
- followThreshold,
7396
- navigation,
7397
- viewportRef
7398
- ]);
7399
- const syncRailItems = useCallback2(() => {
7400
- if (navigation !== "rail") return;
7401
- const content = contentRef.current;
7402
- const viewport = viewportRef.current;
7403
- if (!content || !viewport) return;
7404
- const messages = Array.from(content.querySelectorAll('[data-slot="message"]'));
7405
- const targets = /* @__PURE__ */ new Map();
7406
- const nextItems = messages.map((message, index) => {
7407
- let id = railIdRef.current.get(message);
7408
- if (!id) {
7409
- railIdCounterRef.current += 1;
7410
- id = `message-rail-${railIdCounterRef.current}`;
7411
- railIdRef.current.set(message, id);
7412
- }
7413
- targets.set(id, message);
7414
- const sender = message.dataset.from ?? "conversation";
7415
- const preview = getMessagePreview(message, sender === "user" ? messages.slice(index + 1).find((candidate) => candidate.dataset.from === "assistant") : void 0);
7416
- return {
7417
- id,
7418
- label: preview.label,
7419
- description: preview.description,
7420
- ariaLabel: `Go to ${sender} message ${index + 1} of ${messages.length}`
7421
- };
7422
- });
7423
- railTargetsRef.current = targets;
7424
- setRailItems((current) => {
7425
- return current.length === nextItems.length && current.every((item, index) => item.id === nextItems[index]?.id && item.label === nextItems[index]?.label && item.description === nextItems[index]?.description && item.ariaLabel === nextItems[index]?.ariaLabel) ? current : nextItems;
7426
- });
7427
- setRailOverflowing(viewport.scrollHeight > viewport.clientHeight + 1 && messages.length > 1);
7428
- }, [
7429
- contentRef,
7430
- navigation,
7431
- viewportRef
7432
- ]);
7433
- const scheduleRailSync = useCallback2(() => {
7434
- if (navigation !== "rail") return;
7435
- if (railFrameRef.current) cancelAnimationFrame(railFrameRef.current);
7436
- railFrameRef.current = requestAnimationFrame(() => {
7437
- syncRailItems();
7438
- updateActiveRailItem();
7439
- });
7440
- }, [
7441
- navigation,
7442
- syncRailItems,
7443
- updateActiveRailItem
7444
- ]);
7445
- useEffect2(() => {
7446
- if (navigation !== "rail") {
7447
- railTargetsRef.current.clear();
7448
- setRailItems([]);
7449
- setRailOverflowing(false);
7450
- return;
7451
- }
7452
- const content = contentRef.current;
7453
- const viewport = viewportRef.current;
7454
- if (!content || !viewport) return;
7455
- scheduleRailSync();
7456
- const mutationObserver = typeof MutationObserver === "undefined" ? null : new MutationObserver(scheduleRailSync);
7457
- mutationObserver?.observe(content, {
7458
- childList: true,
7459
- characterData: true,
7460
- subtree: true
7461
- });
7462
- const resizeObserver = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(scheduleRailSync);
7463
- resizeObserver?.observe(content);
7464
- resizeObserver?.observe(viewport);
7465
- return () => {
7466
- mutationObserver?.disconnect();
7467
- resizeObserver?.disconnect();
7468
- };
7469
- }, [
7470
- contentRef,
7471
- navigation,
7472
- scheduleRailSync,
7473
- viewportRef
7474
- ]);
7475
- useEffect2(() => () => {
7476
- if (railFrameRef.current) cancelAnimationFrame(railFrameRef.current);
7477
- }, []);
7478
- return {
7479
- activeRailId,
7480
- railItems,
7481
- railOverflowing,
7482
- scheduleRailSync,
7483
- scrollToRailItem: useCallback2((item) => {
7484
- const viewport = viewportRef.current;
7485
- const target = railTargetsRef.current.get(item.id);
7486
- if (!viewport || !target) return;
7487
- const lastItem = railItems.at(-1)?.id === item.id;
7488
- setActiveRailId(item.id);
7489
- if (lastItem) {
7490
- setFollowing(true);
7491
- scrollToEnd(reduce || !smooth ? "auto" : "smooth");
7492
- return;
7493
- }
7494
- setFollowing(false);
7495
- markProgrammaticScroll(reduce || !smooth ? "auto" : "smooth");
7496
- const viewportRect = viewport.getBoundingClientRect();
7497
- const targetRect = target.getBoundingClientRect();
7498
- const top = viewport.scrollTop + targetRect.top - viewportRect.top - (viewport.clientHeight - targetRect.height) / 2;
7499
- const behavior = reduce || !smooth ? "auto" : "smooth";
7500
- if (typeof viewport.scrollTo === "function") viewport.scrollTo({
7501
- top,
7502
- behavior
7503
- });
7504
- else viewport.scrollTop = top;
7505
- }, [
7506
- markProgrammaticScroll,
7507
- railItems,
7508
- reduce,
7509
- scrollToEnd,
7510
- setFollowing,
7511
- smooth,
7512
- viewportRef
7513
- ])
7514
- };
7515
- }
7516
- function MessageScroller({ followOutput = true, followThreshold = 56, smooth = true, onFollowChange, label = "Conversation", busy, navigation, navigationLabel = "Message navigation", viewportClassName, contentClassName, railClassName, viewportRef: externalViewportRef, viewportProps, contentProps, className, children, ...props }) {
7517
- const reduce = useReducedMotion() ?? false;
7518
- const viewportRef = useRef2(null);
7519
- const contentRef = useRef2(null);
7520
- const followingRef = useRef2(followOutput);
7521
- const programmaticScrollRef = useRef2(false);
7522
- const scrollTimerRef = useRef2(void 0);
7523
- const frameRef = useRef2(void 0);
7524
- const { onScroll: onViewportScroll, onWheel: onViewportWheel, onTouchStart: onViewportTouchStart, onKeyDown: onViewportKeyDown, ...restViewportProps } = viewportProps ?? {};
7525
- const setViewportRef = useCallback2((node) => {
7526
- viewportRef.current = node;
7527
- if (typeof externalViewportRef === "function") externalViewportRef(node);
7528
- else if (externalViewportRef) externalViewportRef.current = node;
7529
- }, [externalViewportRef]);
7530
- const setFollowing = useCallback2((next) => {
7531
- if (followingRef.current === next) return;
7532
- followingRef.current = next;
7533
- onFollowChange?.(next);
7534
- }, [onFollowChange]);
7535
- const markProgrammaticScroll = useCallback2((behavior) => {
7536
- programmaticScrollRef.current = true;
7537
- if (scrollTimerRef.current) window.clearTimeout(scrollTimerRef.current);
7538
- scrollTimerRef.current = window.setTimeout(() => {
7539
- programmaticScrollRef.current = false;
7540
- }, behavior === "smooth" ? 320 : 0);
7541
- }, []);
7542
- const scrollToEnd = useCallback2((behavior) => {
7543
- const viewport2 = viewportRef.current;
7544
- if (!viewport2) return;
7545
- markProgrammaticScroll(behavior);
7546
- if (typeof viewport2.scrollTo === "function") viewport2.scrollTo({
7547
- top: viewport2.scrollHeight,
7548
- behavior
7549
- });
7550
- else viewport2.scrollTop = viewport2.scrollHeight;
7551
- }, [markProgrammaticScroll]);
7552
- const { activeRailId, railItems, railOverflowing, scheduleRailSync, scrollToRailItem } = useMessageScrollerRail({
7553
- navigation,
7554
- followThreshold,
7555
- contentRef,
7556
- viewportRef,
7557
- reduce,
7558
- smooth,
7559
- scrollToEnd,
7560
- setFollowing,
7561
- markProgrammaticScroll
7562
- });
7563
- const scheduleRailSyncEvent = useEffectEvent(scheduleRailSync);
7564
- const scrollToEndEvent = useEffectEvent(scrollToEnd);
7565
- const handleScroll = useCallback2(() => {
7566
- const viewport2 = viewportRef.current;
7567
- if (!viewport2 || programmaticScrollRef.current) return;
7568
- const distance = viewport2.scrollHeight - viewport2.scrollTop - viewport2.clientHeight;
7569
- setFollowing(distance <= followThreshold);
7570
- scheduleRailSync();
7571
- }, [
7572
- followThreshold,
7573
- scheduleRailSync,
7574
- setFollowing
7575
- ]);
7576
- const leaveLiveEdge = useCallback2(() => {
7577
- programmaticScrollRef.current = false;
7578
- }, []);
7579
- useLayoutEffect(() => {
7580
- followingRef.current = followOutput;
7581
- if (!followOutput) return;
7582
- frameRef.current = requestAnimationFrame(() => scrollToEndEvent("auto"));
7583
- return () => {
7584
- if (frameRef.current) cancelAnimationFrame(frameRef.current);
7585
- };
7586
- }, [followOutput]);
7587
- useEffect2(() => {
7588
- const content = contentRef.current;
7589
- if (!content || typeof ResizeObserver === "undefined") return;
7590
- const observer = new ResizeObserver(() => {
7591
- scheduleRailSyncEvent();
7592
- if (!followOutput || !followingRef.current) return;
7593
- scrollToEndEvent(reduce || !smooth ? "auto" : "smooth");
7594
- });
7595
- observer.observe(content);
7596
- return () => observer.disconnect();
7597
- }, [
7598
- followOutput,
7599
- reduce,
7600
- smooth
7601
- ]);
7602
- useEffect2(() => () => {
7603
- if (scrollTimerRef.current) window.clearTimeout(scrollTimerRef.current);
7604
- if (frameRef.current) cancelAnimationFrame(frameRef.current);
7605
- }, []);
7606
- const viewport = /* @__PURE__ */ jsx("section", {
7607
- ref: setViewportRef,
7608
- "aria-label": label,
7609
- ...restViewportProps,
7610
- onScroll: (event) => {
7611
- handleScroll();
7612
- onViewportScroll?.(event);
7613
- },
7614
- onWheel: (event) => {
7615
- leaveLiveEdge();
7616
- onViewportWheel?.(event);
7617
- },
7618
- onTouchStart: (event) => {
7619
- leaveLiveEdge();
7620
- onViewportTouchStart?.(event);
7621
- },
7622
- onKeyDown: (event) => {
7623
- if ([
7624
- "ArrowUp",
7625
- "PageUp",
7626
- "Home"
7627
- ].includes(event.key)) leaveLiveEdge();
7628
- onViewportKeyDown?.(event);
7629
- },
7630
- className: cn("h-full overflow-y-auto overscroll-contain outline-none [overflow-anchor:none] focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring", navigation === "rail" ? "[-ms-overflow-style:none] [scrollbar-width:none] [&::-webkit-scrollbar]:hidden" : "[scrollbar-gutter:stable]", viewportClassName, navigation === "rail" && railOverflowing && "pr-10"),
7631
- children: /* @__PURE__ */ jsx("div", {
7632
- ref: contentRef,
7633
- role: "log",
7634
- "aria-live": "polite",
7635
- "aria-relevant": "additions text",
7636
- "aria-busy": busy,
7637
- className: contentClassName,
7638
- ...contentProps,
7639
- children
7640
- })
7641
- });
7290
+ function TextRow({ item }) {
7642
7291
  return /* @__PURE__ */ jsx("div", {
7643
- "data-slot": "message-scroller",
7644
- className: cn("min-h-0", className),
7645
- ...props,
7646
- children: navigation === "rail" ? /* @__PURE__ */ jsx(PreviewRail, {
7647
- items: railOverflowing ? railItems : [],
7648
- label: navigationLabel,
7649
- activeId: activeRailId,
7650
- onItemSelect: scrollToRailItem,
7651
- previewSide: "before",
7652
- highlightActive: true,
7653
- itemSize: 14,
7654
- className: "h-full min-h-0 overflow-hidden",
7655
- previewContainerClassName: "right-8 left-3",
7656
- previewClassName: "mr-1 w-64 max-w-full [&_[data-slot=preview-rail-card]]:h-20 [&_[data-slot=preview-rail-card]]:overflow-hidden [&_[data-slot=preview-rail-card]]:p-3 [&_[data-slot=preview-rail-title]]:line-clamp-1 [&_[data-slot=preview-rail-title]]:text-xs [&_[data-slot=preview-rail-title]]:leading-4 [&_[data-slot=preview-rail-description]]:line-clamp-2 [&_[data-slot=preview-rail-description]]:text-xs [&_[data-slot=preview-rail-description]]:leading-4",
7657
- railClassName: cn("absolute inset-y-3 right-1 w-7 content-center py-1 [&_[data-slot=preview-rail-item]]:w-7 [&_[data-slot=preview-rail-item]]:justify-end [&_[data-slot=preview-rail-tick]]:h-px [&_[data-slot=preview-rail-tick]]:w-4 [&_[data-slot=preview-rail-tick]]:origin-right", railOverflowing ? "pointer-events-auto opacity-100" : "pointer-events-none opacity-0", railClassName),
7658
- children: viewport
7659
- }) : viewport
7292
+ className: "rounded-md px-1.5 py-1 leading-5 text-muted-foreground",
7293
+ children: item.content
7660
7294
  });
7661
7295
  }
7662
- var MessageContext = createContext2({ from: "assistant" });
7663
- var MESSAGE_POP_UP = {
7664
- type: "spring",
7665
- stiffness: 480,
7666
- damping: 32,
7667
- mass: 0.62
7668
- };
7669
- function Message({ from, animateIn = false, children, className, initial: initial2, animate: animate2, transition, exit, style, ...props }) {
7670
- const reduce = useReducedMotion() ?? false;
7671
- const messageContextValue = useMemo2(() => ({ from }), [from]);
7672
- return /* @__PURE__ */ jsx(MessageSideContext.Provider, {
7673
- value: from === "user" ? "end" : "start",
7674
- children: /* @__PURE__ */ jsx(MessageContext.Provider, {
7675
- value: messageContextValue,
7676
- children: /* @__PURE__ */ jsx(m.article, {
7677
- "data-slot": "message",
7678
- "data-from": from,
7679
- "aria-label": props["aria-label"] ?? `${from} message`,
7680
- initial: initial2 ?? (animateIn && !reduce ? {
7681
- opacity: 0,
7682
- transform: "translateY(8px) scale(0.95)"
7683
- } : false),
7684
- animate: animate2 ?? (animateIn && !reduce ? {
7685
- opacity: 1,
7686
- transform: "translateY(0px) scale(1)"
7687
- } : { opacity: 1 }),
7688
- exit: exit ?? (reduce ? { opacity: 0 } : {
7689
- opacity: 0,
7690
- transform: "translateY(-3px) scale(0.99)"
7691
- }),
7692
- transition: transition ?? (reduce ? { duration: 0.12 } : MESSAGE_POP_UP),
7693
- style: {
7694
- transformOrigin: from === "user" ? "100% 100%" : "0% 100%",
7695
- ...style
7696
- },
7697
- className: cn("group/message flex w-full items-start gap-2", from === "user" ? "flex-row-reverse" : "flex-row", className),
7698
- ...props,
7699
- children
7296
+ function SearchResultRow({ result }) {
7297
+ const safeUrl = result.url && isSafeExternalUrl(result.url) ? result.url : void 0;
7298
+ const content = /* @__PURE__ */ jsxs(Fragment$1, { children: [
7299
+ /* @__PURE__ */ jsx("span", {
7300
+ "aria-hidden": "true",
7301
+ className: "grid size-5 shrink-0 place-items-center text-muted-foreground",
7302
+ children: result.icon ?? /* @__PURE__ */ jsx(Earth, {
7303
+ className: "size-3",
7304
+ strokeWidth: 2
7700
7305
  })
7701
- })
7702
- });
7703
- }
7704
- function MessageContent({ className, ...props }) {
7705
- const { from } = useContext2(MessageContext);
7706
- return /* @__PURE__ */ jsx("div", {
7707
- "data-slot": "message-content",
7708
- className: cn("flex min-w-0 flex-1 flex-col gap-1.5", from === "user" ? "items-end" : "items-start", className),
7709
- ...props
7710
- });
7711
- }
7712
- var EMPTY_CITATIONS = [];
7713
- function ResponseAction({ label, active = false, onClick, children }) {
7714
- const reduce = useReducedMotion() ?? false;
7715
- return /* @__PURE__ */ jsx(m.button, {
7716
- type: "button",
7717
- "aria-label": label,
7718
- title: label,
7719
- "aria-pressed": label === "Helpful" || label === "Not helpful" ? active : void 0,
7720
- onClick,
7721
- whileTap: reduce ? void 0 : { scale: 0.9 },
7722
- transition: SPRING_PRESS,
7723
- className: cn("grid size-7 place-items-center rounded-md text-muted-foreground outline-none transition-colors hover:bg-muted hover:text-foreground focus-visible:ring-2 focus-visible:ring-ring", active && "bg-muted text-foreground"),
7724
- children
7306
+ }),
7307
+ /* @__PURE__ */ jsx("span", {
7308
+ className: "min-w-0 truncate font-medium text-foreground/90",
7309
+ children: result.title
7310
+ }),
7311
+ result.domain ? /* @__PURE__ */ jsx("span", {
7312
+ className: "min-w-0 truncate text-muted-foreground/55",
7313
+ children: result.domain
7314
+ }) : null
7315
+ ] });
7316
+ const className = cn("flex min-h-7 items-center gap-2 rounded-md px-1.5 py-1 text-left outline-none transition-colors", safeUrl && "focus-visible:ring-2 focus-visible:ring-ring");
7317
+ return safeUrl ? /* @__PURE__ */ jsx("a", {
7318
+ href: safeUrl,
7319
+ className,
7320
+ children: content
7321
+ }) : /* @__PURE__ */ jsx("div", {
7322
+ className,
7323
+ children: content
7725
7324
  });
7726
7325
  }
7727
- function StreamingResponse({ children, status = "streaming", copyText, onCopy, onRetry, sources = EMPTY_CITATIONS, sourcesOpen, defaultSourcesOpen = false, onSourcesOpenChange, sourceIdPrefix, feedback, defaultFeedback = null, onFeedbackChange, announce = true, showActions = true, className, contentClassName, actionsClassName }) {
7326
+ function SearchRow({ item }) {
7728
7327
  const reduce = useReducedMotion() ?? false;
7729
- const baseId = useId();
7730
- const [copied, setCopied] = useState2(false);
7731
- const [internalFeedback, setInternalFeedback] = useState2(defaultFeedback);
7732
- const [internalSourcesOpen, setInternalSourcesOpen] = useState2(defaultSourcesOpen);
7733
- const copyTimer = useRef2(void 0);
7734
- const currentFeedback = feedback ?? internalFeedback;
7735
- const currentSourcesOpen = sourcesOpen ?? internalSourcesOpen;
7736
- const streaming = status === "streaming";
7737
- const complete = status === "complete";
7738
- const canCopy = Boolean(copyText || onCopy);
7739
- const hasSources = sources.length > 0;
7740
- const shouldShowActions = showActions && !streaming && (canCopy || onRetry || complete || hasSources);
7741
- const sourcesContentId = `${baseId}-sources`;
7742
- const resolvedSourcePrefix = sourceIdPrefix ?? `response-source-${baseId.replace(/:/g, "")}`;
7743
- useEffect2(() => () => {
7744
- if (copyTimer.current) window.clearTimeout(copyTimer.current);
7745
- }, []);
7746
- const handleCopy = useCallback2(async () => {
7747
- if (onCopy) await onCopy();
7748
- else if (copyText) await navigator.clipboard?.writeText(copyText);
7749
- setCopied(true);
7750
- if (copyTimer.current) window.clearTimeout(copyTimer.current);
7751
- copyTimer.current = window.setTimeout(() => setCopied(false), 1600);
7752
- }, [copyText, onCopy]);
7753
- const setFeedback = (next) => {
7754
- const value = currentFeedback === next ? null : next;
7755
- if (feedback === void 0) setInternalFeedback(value);
7756
- onFeedbackChange?.(value);
7757
- };
7758
- const setSourcesOpen = useCallback2((next) => {
7759
- if (sourcesOpen === void 0) setInternalSourcesOpen(next);
7760
- onSourcesOpenChange?.(next);
7761
- }, [onSourcesOpenChange, sourcesOpen]);
7762
- return /* @__PURE__ */ jsxs("div", {
7763
- "data-state": status,
7764
- "aria-busy": streaming,
7765
- className: cn("w-full", className),
7766
- children: [/* @__PURE__ */ jsx("div", {
7767
- "aria-live": announce ? "polite" : "off",
7768
- className: cn("text-sm leading-6 text-foreground/90 [&_a]:font-medium [&_a]:underline [&_a]:underline-offset-4 [&_code]:rounded [&_code]:bg-muted [&_code]:px-1 [&_code]:py-0.5 [&_code]:font-mono [&_code]:text-[0.9em] [&_ol]:my-3 [&_ol]:list-decimal [&_ol]:space-y-1 [&_ol]:pl-5 [&_p+p]:mt-3 [&_pre]:my-3 [&_pre]:overflow-x-auto [&_pre]:rounded-xl [&_pre]:border [&_pre]:border-border [&_pre]:bg-muted/45 [&_pre]:p-3 [&_pre_code]:bg-transparent [&_pre_code]:p-0 [&_ul]:my-3 [&_ul]:list-disc [&_ul]:space-y-1 [&_ul]:pl-5", contentClassName),
7769
- children
7770
- }), /* @__PURE__ */ jsx(AnimatePresence, {
7771
- initial: false,
7772
- children: shouldShowActions ? /* @__PURE__ */ jsxs(m.div, {
7773
- initial: reduce ? { opacity: 0 } : {
7774
- opacity: 0,
7775
- y: 4
7776
- },
7777
- animate: {
7778
- opacity: 1,
7779
- y: 0
7780
- },
7781
- exit: { opacity: 0 },
7782
- transition: {
7783
- duration: reduce ? 0.12 : 0.22,
7784
- ease: EASE_OUT
7785
- },
7786
- className: "mt-3",
7787
- children: [/* @__PURE__ */ jsxs("div", {
7788
- className: cn("flex items-center gap-0.5", actionsClassName),
7789
- children: [
7790
- canCopy ? /* @__PURE__ */ jsx(ResponseAction, {
7791
- label: copied ? "Copied" : "Copy response",
7792
- onClick: handleCopy,
7793
- children: copied ? /* @__PURE__ */ jsx(Check, { className: "size-3.5" }) : /* @__PURE__ */ jsx(Copy, { className: "size-3.5" })
7794
- }) : null,
7795
- onRetry ? /* @__PURE__ */ jsx(ResponseAction, {
7796
- label: "Retry response",
7797
- onClick: onRetry,
7798
- children: /* @__PURE__ */ jsx(RotateCcw, { className: "size-3.5" })
7799
- }) : null,
7800
- complete ? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(ResponseAction, {
7801
- label: "Helpful",
7802
- active: currentFeedback === "up",
7803
- onClick: () => setFeedback("up"),
7804
- children: /* @__PURE__ */ jsx(ThumbsUp, { className: "size-3.5" })
7805
- }), /* @__PURE__ */ jsx(ResponseAction, {
7806
- label: "Not helpful",
7807
- active: currentFeedback === "down",
7808
- onClick: () => setFeedback("down"),
7809
- children: /* @__PURE__ */ jsx(ThumbsDown, { className: "size-3.5" })
7810
- })] }) : null,
7811
- hasSources ? /* @__PURE__ */ jsxs("button", {
7812
- type: "button",
7813
- "aria-expanded": currentSourcesOpen,
7814
- "aria-controls": sourcesContentId,
7815
- onClick: () => setSourcesOpen(!currentSourcesOpen),
7816
- className: "group ml-1 inline-flex min-h-7 items-center gap-2 rounded-md px-1.5 text-xs text-muted-foreground outline-none transition-colors hover:text-foreground focus-visible:ring-2 focus-visible:ring-ring",
7817
- children: [
7818
- /* @__PURE__ */ jsx(CitationStack, { citations: sources }),
7819
- /* @__PURE__ */ jsxs("span", {
7820
- className: "tabular-nums",
7821
- children: [
7822
- sources.length,
7823
- " ",
7824
- sources.length === 1 ? "source" : "sources"
7825
- ]
7826
- }),
7827
- /* @__PURE__ */ jsx(m.span, {
7828
- "aria-hidden": "true",
7829
- animate: { rotate: currentSourcesOpen ? 180 : 0 },
7830
- transition: reduce ? { duration: 0 } : SPRING_SWAP,
7831
- className: "text-muted-foreground/50 group-hover:text-muted-foreground",
7832
- children: /* @__PURE__ */ jsx(ChevronDown, { className: "size-3" })
7833
- })
7834
- ]
7835
- }) : null
7836
- ]
7837
- }), hasSources ? /* @__PURE__ */ jsx(AgentDisclosure, {
7838
- id: sourcesContentId,
7839
- open: currentSourcesOpen,
7840
- children: /* @__PURE__ */ jsx(CitationList, {
7841
- citations: sources,
7842
- idPrefix: resolvedSourcePrefix,
7843
- className: "mt-2 rounded-xl bg-muted p-2"
7844
- })
7845
- }) : null]
7846
- }) : null
7847
- })]
7848
- });
7849
- }
7850
- var TEXT_SHIMMER_KEYFRAMES = "@keyframes beui-text-shimmer{from{background-position:200% 0}to{background-position:-200% 0}}@media (prefers-reduced-motion: reduce){.beui-text-shimmer{animation:none !important}}";
7851
- var TEXT_SHIMMER_CLASS_NAME = "beui-text-shimmer bg-[length:200%_100%] bg-clip-text text-transparent bg-[linear-gradient(110deg,var(--muted-foreground)_30%,var(--foreground)_50%,var(--muted-foreground)_70%)]";
7852
- function textShimmerStyle(duration) {
7853
- return { animation: `beui-text-shimmer ${duration}s linear infinite` };
7854
- }
7855
- function TextShimmer({ children, as: Comp = "span", duration = 2.5, className }) {
7856
- return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("style", { children: TEXT_SHIMMER_KEYFRAMES }), /* @__PURE__ */ jsx(Comp, {
7857
- style: textShimmerStyle(duration),
7858
- className: cn("inline-block", TEXT_SHIMMER_CLASS_NAME, className),
7859
- children
7860
- })] });
7861
- }
7862
- function ThinkingShimmer({ children = "Thinking\u2026", duration = 1.8, className }) {
7863
- return /* @__PURE__ */ jsx(TextShimmer, {
7864
- as: "span",
7865
- duration,
7866
- className: cn("font-medium", className),
7867
- children
7868
- });
7869
- }
7870
- function StepRow({ item }) {
7871
- const state = item.status ?? "complete";
7872
- return /* @__PURE__ */ jsxs("div", {
7873
- className: "flex min-h-7 items-start gap-2.5 rounded-md px-1.5 py-1",
7874
- children: [
7875
- /* @__PURE__ */ jsx("span", {
7876
- "aria-hidden": "true",
7877
- className: "mt-0.5 grid size-4 shrink-0 place-items-center text-muted-foreground/70",
7878
- children: state === "complete" ? /* @__PURE__ */ jsx(Check, {
7879
- className: "size-4",
7880
- strokeWidth: 1.8
7881
- }) : state === "active" ? /* @__PURE__ */ jsxs("span", {
7882
- className: "relative grid size-3 place-items-center",
7883
- children: [/* @__PURE__ */ jsx(motion.span, {
7884
- className: "absolute inset-0 rounded-full bg-foreground/10",
7885
- animate: { opacity: [
7886
- 0.35,
7887
- 0.8,
7888
- 0.35
7889
- ] },
7890
- transition: {
7891
- duration: 1.5,
7892
- repeat: Number.POSITIVE_INFINITY
7893
- }
7894
- }), /* @__PURE__ */ jsx("span", { className: "size-1.5 rounded-full bg-foreground/60" })]
7895
- }) : /* @__PURE__ */ jsx(Circle, {
7896
- className: "size-3",
7897
- strokeWidth: 1.5
7898
- })
7899
- }),
7900
- /* @__PURE__ */ jsx("span", {
7901
- className: cn("min-w-0 flex-1 leading-5", state === "pending" ? "text-muted-foreground/55" : "text-foreground/90"),
7902
- children: item.label
7903
- }),
7904
- item.meta ? /* @__PURE__ */ jsx("span", {
7905
- className: "shrink-0 leading-5 text-muted-foreground/55",
7906
- children: item.meta
7907
- }) : null
7908
- ]
7909
- });
7910
- }
7911
- function TextRow({ item }) {
7912
- return /* @__PURE__ */ jsx("div", {
7913
- className: "rounded-md px-1.5 py-1 leading-5 text-muted-foreground",
7914
- children: item.content
7915
- });
7916
- }
7917
- function SearchResultRow({ result }) {
7918
- const safeUrl = result.url && isSafeExternalUrl(result.url) ? result.url : void 0;
7919
- const content = /* @__PURE__ */ jsxs(Fragment$1, { children: [
7920
- /* @__PURE__ */ jsx("span", {
7921
- "aria-hidden": "true",
7922
- className: "grid size-5 shrink-0 place-items-center text-muted-foreground",
7923
- children: result.icon ?? /* @__PURE__ */ jsx(Earth, {
7924
- className: "size-3",
7925
- strokeWidth: 2
7926
- })
7927
- }),
7928
- /* @__PURE__ */ jsx("span", {
7929
- className: "min-w-0 truncate font-medium text-foreground/90",
7930
- children: result.title
7931
- }),
7932
- result.domain ? /* @__PURE__ */ jsx("span", {
7933
- className: "min-w-0 truncate text-muted-foreground/55",
7934
- children: result.domain
7935
- }) : null
7936
- ] });
7937
- const className = cn("flex min-h-7 items-center gap-2 rounded-md px-1.5 py-1 text-left outline-none transition-colors", safeUrl && "focus-visible:ring-2 focus-visible:ring-ring");
7938
- return safeUrl ? /* @__PURE__ */ jsx("a", {
7939
- href: safeUrl,
7940
- className,
7941
- children: content
7942
- }) : /* @__PURE__ */ jsx("div", {
7943
- className,
7944
- children: content
7945
- });
7946
- }
7947
- function SearchRow({ item }) {
7948
- const reduce = useReducedMotion() ?? false;
7949
- const enter = reduce ? { opacity: 1 } : {
7950
- opacity: 0,
7951
- y: 6
7328
+ const enter = reduce ? { opacity: 1 } : {
7329
+ opacity: 0,
7330
+ y: 6
7952
7331
  };
7953
7332
  const visible = {
7954
7333
  opacity: 1,
@@ -7984,1047 +7363,310 @@ function SearchRow({ item }) {
7984
7363
  className: "space-y-0.5 pl-4",
7985
7364
  children: /* @__PURE__ */ jsx(AnimatePresence, {
7986
7365
  initial: true,
7987
- mode: "popLayout",
7988
- children: item.results.map((result) => /* @__PURE__ */ jsx(motion.div, {
7989
- layout: "position",
7990
- initial: enter,
7991
- animate: visible,
7992
- exit,
7993
- transition,
7994
- children: /* @__PURE__ */ jsx(SearchResultRow, { result })
7995
- }, result.id))
7996
- })
7997
- }) : null,
7998
- /* @__PURE__ */ jsx(AnimatePresence, {
7999
- initial: true,
8000
- children: item.moreCount ? /* @__PURE__ */ jsxs(motion.div, {
8001
- initial: enter,
8002
- animate: visible,
8003
- exit,
8004
- transition,
8005
- className: "px-1.5 py-1 pl-8 text-muted-foreground/55",
8006
- children: [
8007
- "+",
8008
- item.moreCount,
8009
- " more"
8010
- ]
8011
- }, "more-results") : null
8012
- })
8013
- ]
8014
- });
8015
- }
8016
- function ActionIcon({ action }) {
8017
- if (action === "read") return /* @__PURE__ */ jsx(FileText, { className: "size-4" });
8018
- if (action === "edit" || action === "write") return /* @__PURE__ */ jsx(PencilLine, { className: "size-4" });
8019
- if (action === "run") return /* @__PURE__ */ jsx(SquareTerminal, { className: "size-4" });
8020
- return /* @__PURE__ */ jsx(Wrench, { className: "size-4" });
8021
- }
8022
- function ActivityAction({ action }) {
8023
- return /* @__PURE__ */ jsx("button", {
8024
- type: "button",
8025
- "aria-label": action.ariaLabel ?? action.label,
8026
- onClick: action.onClick,
8027
- className: "shrink-0 rounded-md px-1.5 py-1 text-[10px] font-medium text-primary outline-none hover:bg-primary/10 focus-visible:ring-2 focus-visible:ring-ring",
8028
- children: action.label
8029
- });
8030
- }
8031
- function ToolRow({ item }) {
8032
- const action = item.action.charAt(0).toUpperCase() + item.action.slice(1);
8033
- const hasChanges = typeof item.additions === "number" || typeof item.deletions === "number";
8034
- return /* @__PURE__ */ jsxs("div", {
8035
- className: "grid min-h-8 min-w-0 grid-cols-[1rem_auto_minmax(0,1fr)_auto] items-center gap-2.5 rounded-md px-1.5 py-0.5 leading-5",
8036
- children: [
8037
- /* @__PURE__ */ jsx("span", {
8038
- "aria-hidden": "true",
8039
- className: "grid size-4 shrink-0 place-items-center text-muted-foreground/70",
8040
- children: /* @__PURE__ */ jsx(ActionIcon, { action: item.action })
8041
- }),
8042
- /* @__PURE__ */ jsx("span", {
8043
- className: "shrink-0 font-medium text-foreground/90",
8044
- children: action
8045
- }),
8046
- /* @__PURE__ */ jsx("span", {
8047
- className: "min-w-0 flex-1 truncate rounded-lg bg-muted/80 px-2.5 py-1 font-mono text-xs text-muted-foreground/70",
8048
- children: item.target
8049
- }),
8050
- hasChanges || item.openAction ? /* @__PURE__ */ jsxs("div", {
8051
- className: "flex shrink-0 items-center gap-2",
8052
- children: [hasChanges ? /* @__PURE__ */ jsxs("span", {
8053
- className: "flex items-center gap-2 font-mono tabular-nums",
8054
- children: [typeof item.additions === "number" ? /* @__PURE__ */ jsxs("span", {
8055
- className: "text-emerald-500",
8056
- children: ["+", item.additions]
8057
- }) : null, typeof item.deletions === "number" ? /* @__PURE__ */ jsxs("span", {
8058
- className: "text-rose-500",
8059
- children: ["\u2212", item.deletions]
8060
- }) : null]
8061
- }) : null, item.openAction ? /* @__PURE__ */ jsx(ActivityAction, { action: item.openAction }) : null]
8062
- }) : null
8063
- ]
8064
- });
8065
- }
8066
- function TraceIcon({ kind }) {
8067
- if (kind === "thinking") return /* @__PURE__ */ jsx(Sparkles, { className: "size-4" });
8068
- if (kind === "message") return /* @__PURE__ */ jsx(MessageSquare, { className: "size-4" });
8069
- if (kind === "write") return /* @__PURE__ */ jsx(PencilLine, { className: "size-4" });
8070
- if (kind === "run") return /* @__PURE__ */ jsx(SquareTerminal, { className: "size-4" });
8071
- if (kind === "read") return /* @__PURE__ */ jsx(Image, { className: "size-4" });
8072
- return /* @__PURE__ */ jsx(Wrench, { className: "size-4" });
8073
- }
8074
- function TraceRow({ item }) {
8075
- const thinking = item.kind === "thinking";
8076
- return /* @__PURE__ */ jsxs("div", {
8077
- className: cn("grid min-h-8 grid-cols-[1rem_auto_minmax(0,1fr)_auto] gap-2.5 rounded-md px-1.5 py-0.5", thinking ? "items-start" : "items-center"),
8078
- children: [
8079
- /* @__PURE__ */ jsx("span", {
8080
- "aria-hidden": "true",
8081
- className: "grid size-4 place-items-center text-muted-foreground/70",
8082
- children: item.icon ?? /* @__PURE__ */ jsx(TraceIcon, { kind: item.kind })
8083
- }),
8084
- /* @__PURE__ */ jsx("span", {
8085
- className: "min-w-0 truncate font-medium text-foreground/90",
8086
- children: item.label
8087
- }),
8088
- item.detail ? /* @__PURE__ */ jsx("span", {
8089
- className: cn("min-w-0 rounded-lg bg-muted/80 px-2.5 py-1 font-mono text-xs text-muted-foreground/70", thinking ? "max-h-40 overflow-y-auto whitespace-pre-wrap break-words" : "truncate"),
8090
- children: item.detail
8091
- }) : /* @__PURE__ */ jsx("span", {}),
8092
- item.action ? /* @__PURE__ */ jsx(ActivityAction, { action: item.action }) : null
8093
- ]
8094
- });
8095
- }
8096
- function ActivityRow({ item }) {
8097
- if (item.type === "text") return /* @__PURE__ */ jsx(TextRow, { item });
8098
- if (item.type === "search") return /* @__PURE__ */ jsx(SearchRow, { item });
8099
- if (item.type === "tool") return /* @__PURE__ */ jsx(ToolRow, { item });
8100
- if (item.type === "trace") return /* @__PURE__ */ jsx(TraceRow, { item });
8101
- return /* @__PURE__ */ jsx(StepRow, { item });
8102
- }
8103
- function formatDuration(duration) {
8104
- const seconds = Math.max(0, Math.round(duration));
8105
- if (seconds < 60) return `${seconds}s`;
8106
- const minutes = Math.floor(seconds / 60);
8107
- const remainder = seconds % 60;
8108
- return remainder === 0 ? `${minutes}m` : `${minutes}m ${remainder}s`;
8109
- }
8110
- function useControllableOpen({ open, defaultOpen, onOpenChange }) {
8111
- const [internalOpen, setInternalOpen] = useState2(defaultOpen);
8112
- const controlled = open !== void 0;
8113
- return [open ?? internalOpen, useCallback2((next) => {
8114
- if (!controlled) setInternalOpen(next);
8115
- onOpenChange?.(next);
8116
- }, [controlled, onOpenChange])];
8117
- }
8118
- function getContentType(items) {
8119
- const first = items[0]?.type;
8120
- return first && items.every((item) => item.type === first) ? first : "mixed";
8121
- }
8122
- function getActiveLabel(type) {
8123
- if (type === "search") return "Searching the web\u2026";
8124
- if (type === "tool") return "Running tools\u2026";
8125
- if (type === "trace") return "Working through the run\u2026";
8126
- if (type === "mixed") return "Working through it\u2026";
8127
- return "Thinking\u2026";
8128
- }
8129
- function getSummary(type, items, duration) {
8130
- if (type === "step" || type === "text") return /* @__PURE__ */ jsxs(Fragment$1, { children: ["Thought for ", /* @__PURE__ */ jsx("span", {
8131
- className: "tabular-nums",
8132
- children: formatDuration(duration)
8133
- })] });
8134
- if (type === "search") return "Searched the web";
8135
- if (type === "tool") return `Ran ${items.length} ${items.length === 1 ? "tool" : "tools"}`;
8136
- if (type === "trace") {
8137
- const messages = items.filter((item) => item.type === "trace" && (item.kind === "thinking" || item.kind === "message")).length;
8138
- const tools = items.length - messages;
8139
- return `${tools} ${tools === 1 ? "tool call" : "tool calls"}, ${messages} ${messages === 1 ? "message" : "messages"}`;
8140
- }
8141
- return `Completed ${items.length} ${items.length === 1 ? "step" : "steps"}`;
8142
- }
8143
- function AgentActivity({ items, contentType: initialContentType, status = "working", duration = 0, open, defaultOpen = false, onOpenChange, collapseOnComplete = true, activeLabel, summary, renderWorkingStatus, renderCompletedStatus, maxHeight = 208, className, contentClassName }) {
8144
- const reduce = useReducedMotion() ?? false;
8145
- const baseId = useId();
8146
- const triggerId = `${baseId}-trigger`;
8147
- const contentId = `${baseId}-content`;
8148
- const contentRef = useRef2(null);
8149
- const viewportRef = useRef2(null);
8150
- const previousStatus = useRef2(status);
8151
- const [contentHeight, setContentHeight] = useState2(0);
8152
- const [currentOpen, setOpen] = useControllableOpen({
8153
- open,
8154
- defaultOpen,
8155
- onOpenChange
8156
- });
8157
- const working = status === "working";
8158
- const expanded = working || currentOpen;
8159
- const contentType = items.length ? getContentType(items) : initialContentType ?? "mixed";
8160
- const viewportHeight = working ? Math.max(0, maxHeight) : Math.min(contentHeight, Math.max(0, maxHeight));
8161
- const capped = contentHeight > maxHeight;
8162
- const streamOffset = working ? Math.min(0, viewportHeight - contentHeight) : 0;
8163
- useLayoutEffect(() => {
8164
- const node = contentRef.current;
8165
- if (!node) return;
8166
- const measure = () => setContentHeight(node.offsetHeight);
8167
- measure();
8168
- if (typeof ResizeObserver === "undefined") return;
8169
- const observer = new ResizeObserver(measure);
8170
- observer.observe(node);
8171
- return () => observer.disconnect();
8172
- }, []);
8173
- useEffect2(() => {
8174
- if (previousStatus.current === "working" && status === "complete") setOpen(!collapseOnComplete);
8175
- previousStatus.current = status;
8176
- }, [
8177
- collapseOnComplete,
8178
- setOpen,
8179
- status
8180
- ]);
8181
- const toggle = () => {
8182
- const next = !currentOpen;
8183
- setOpen(next);
8184
- if (next) requestAnimationFrame(() => viewportRef.current?.scrollTo({ top: 0 }));
8185
- };
8186
- const liveLabel = activeLabel ?? getActiveLabel(contentType);
8187
- const completedSummary = summary ?? getSummary(contentType, items, duration);
8188
- const maskImage = capped ? working ? "linear-gradient(to bottom, transparent, black 12px)" : "linear-gradient(to bottom, transparent, black 12px, black calc(100% - 12px), transparent)" : void 0;
8189
- return /* @__PURE__ */ jsxs("div", {
8190
- "data-state": working ? "working" : expanded ? "open" : "closed",
8191
- "data-content": contentType,
8192
- "aria-busy": working,
8193
- className: cn("w-full text-sm", className),
8194
- children: [working ? /* @__PURE__ */ jsx("div", {
8195
- id: triggerId,
8196
- role: "status",
8197
- className: "flex h-7 min-w-0 items-center text-muted-foreground",
8198
- children: renderWorkingStatus ? renderWorkingStatus({
8199
- label: liveLabel,
8200
- duration
8201
- }) : /* @__PURE__ */ jsx(ThinkingShimmer, { children: liveLabel })
8202
- }) : /* @__PURE__ */ jsxs("button", {
8203
- id: triggerId,
8204
- type: "button",
8205
- "aria-expanded": expanded,
8206
- "aria-controls": contentId,
8207
- onClick: toggle,
8208
- className: "group flex h-7 min-w-0 items-center gap-1.5 rounded-md text-left font-medium text-muted-foreground outline-none transition-colors hover:text-foreground focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background",
8209
- children: [/* @__PURE__ */ jsx("span", {
8210
- className: "truncate",
8211
- children: renderCompletedStatus ? renderCompletedStatus({
8212
- summary: completedSummary,
8213
- duration
8214
- }) : completedSummary
8215
- }), /* @__PURE__ */ jsx(motion.span, {
8216
- "aria-hidden": "true",
8217
- animate: { rotate: expanded ? 180 : 0 },
8218
- transition: reduce ? { duration: 0 } : SPRING_SWAP,
8219
- className: "inline-flex shrink-0 text-muted-foreground/70 group-hover:text-foreground",
8220
- children: /* @__PURE__ */ jsx(ChevronDown, { className: "size-3.5" })
8221
- })]
8222
- }), /* @__PURE__ */ jsx(AgentDisclosure, {
8223
- id: contentId,
8224
- role: "region",
8225
- "aria-labelledby": triggerId,
8226
- open: expanded,
8227
- openHeight: viewportHeight,
8228
- children: /* @__PURE__ */ jsx("div", {
8229
- ref: viewportRef,
8230
- className: cn("scrollbar-hide pr-1", capped && expanded && !working ? "overflow-y-auto" : "overflow-y-hidden"),
8231
- style: {
8232
- height: viewportHeight,
8233
- maskImage,
8234
- WebkitMaskImage: maskImage
8235
- },
8236
- children: /* @__PURE__ */ jsx(motion.div, {
8237
- ref: contentRef,
8238
- role: "list",
8239
- initial: false,
8240
- animate: { y: streamOffset },
8241
- transition: reduce ? { duration: 0 } : SPRING_LAYOUT,
8242
- className: cn("space-y-0.5 py-2", contentClassName),
8243
- children: /* @__PURE__ */ jsx(AnimatePresence, {
8244
- mode: "popLayout",
8245
- children: items.map((item) => /* @__PURE__ */ jsx(motion.div, {
8246
- layout: "position",
8247
- role: "listitem",
8248
- initial: reduce ? { opacity: 1 } : {
8249
- opacity: 0,
8250
- y: 6
8251
- },
8252
- animate: {
8253
- opacity: 1,
8254
- y: 0
8255
- },
8256
- exit: reduce ? { opacity: 0 } : {
8257
- opacity: 0,
8258
- y: -3
8259
- },
8260
- transition: reduce ? { duration: 0 } : {
8261
- opacity: {
8262
- duration: 0.18,
8263
- ease: EASE_OUT
8264
- },
8265
- y: SPRING_LAYOUT,
8266
- layout: SPRING_LAYOUT
8267
- },
8268
- children: /* @__PURE__ */ jsx(ActivityRow, { item })
8269
- }, item.id))
8270
- })
8271
- })
8272
- })
8273
- })]
8274
- });
8275
- }
8276
- function PromptSuggestions({ suggestions, selectedSuggestion, cycle, onSuggestion, variant = "pills", className, ...props }) {
8277
- const list = variant === "list";
8278
- return /* @__PURE__ */ jsx("div", {
8279
- "data-slot": "suggestions",
8280
- className: cn(list ? "flex w-full max-w-sm flex-col gap-2" : "flex w-full max-w-xl flex-wrap justify-center gap-1", className),
8281
- ...props,
8282
- children: suggestions.map((suggestion, index) => /* @__PURE__ */ jsx("button", {
8283
- type: "button",
8284
- "aria-pressed": selectedSuggestion === suggestion,
8285
- onClick: () => onSuggestion(suggestion),
8286
- className: cn(paper, "fade-in slide-in-from-bottom-2 animate-in fill-mode-both flex cursor-pointer items-center text-[13px] text-foreground/80 transition-[color,transform] duration-300 hover:-translate-y-px hover:text-foreground focus-visible:text-foreground active:scale-[0.96] motion-reduce:animate-none", list ? "w-full rounded-2xl px-4 py-2.5 text-start" : "rounded-full px-4 py-2", selectedSuggestion === suggestion && "!bg-foreground !text-background hover:!text-background focus-visible:!text-background"),
8287
- style: { animationDelay: `${index * 70}ms` },
8288
- children: suggestion
8289
- }, suggestion))
8290
- }, cycle);
8291
- }
8292
- var ErrorMessage = memo(function ErrorMessage2({ title = "Something went wrong", message, className }) {
8293
- return /* @__PURE__ */ jsx("div", {
8294
- className: cn("flex justify-start", className),
8295
- children: /* @__PURE__ */ jsxs("div", {
8296
- className: "rounded-[8px] border border-red-500/30 bg-red-500/10 px-4 py-2.5 text-sm text-an-foreground",
8297
- children: [/* @__PURE__ */ jsx("div", {
8298
- className: "font-medium text-an-foreground",
8299
- children: title
8300
- }), /* @__PURE__ */ jsx("div", {
8301
- className: "mt-0.5 text-an-foreground-muted",
8302
- children: message
8303
- })]
8304
- })
8305
- });
8306
- });
8307
- function formatPayload(value) {
8308
- if (typeof value === "string") return value;
8309
- if (value === void 0) return "";
8310
- try {
8311
- return JSON.stringify(value, null, 2) ?? "";
8312
- } catch {
8313
- return String(value);
8314
- }
8315
- }
8316
- function PayloadPart({ part }) {
8317
- const payload = formatPayload(part.payload);
8318
- return /* @__PURE__ */ jsxs("section", {
8319
- "data-payload-kind": part.kind,
8320
- className: "w-full min-w-0 overflow-hidden rounded-xl border border-border/60 bg-muted/40 text-sm",
8321
- children: [
8322
- /* @__PURE__ */ jsx("div", {
8323
- className: "border-b border-border/50 px-3 py-2 text-xs font-medium text-muted-foreground",
8324
- children: part.title
8325
- }),
8326
- part.text ? /* @__PURE__ */ jsx("pre", {
8327
- className: "m-0 whitespace-pre-wrap break-words px-3 py-3 font-mono text-xs leading-5 text-foreground/80",
8328
- children: part.text
7366
+ mode: "popLayout",
7367
+ children: item.results.map((result) => /* @__PURE__ */ jsx(motion.div, {
7368
+ layout: "position",
7369
+ initial: enter,
7370
+ animate: visible,
7371
+ exit,
7372
+ transition,
7373
+ children: /* @__PURE__ */ jsx(SearchResultRow, { result })
7374
+ }, result.id))
7375
+ })
8329
7376
  }) : null,
8330
- payload ? /* @__PURE__ */ jsxs("details", {
8331
- open: true,
8332
- className: "border-t border-border/50 px-3 py-2",
8333
- children: [/* @__PURE__ */ jsx("summary", {
8334
- className: "cursor-pointer text-xs font-medium text-muted-foreground",
8335
- children: "Payload"
8336
- }), /* @__PURE__ */ jsx("pre", {
8337
- className: "m-0 mt-2 max-w-full whitespace-pre-wrap break-words font-mono text-xs leading-5 text-foreground/70",
8338
- children: payload
8339
- })]
8340
- }) : null
7377
+ /* @__PURE__ */ jsx(AnimatePresence, {
7378
+ initial: true,
7379
+ children: item.moreCount ? /* @__PURE__ */ jsxs(motion.div, {
7380
+ initial: enter,
7381
+ animate: visible,
7382
+ exit,
7383
+ transition,
7384
+ className: "px-1.5 py-1 pl-8 text-muted-foreground/55",
7385
+ children: [
7386
+ "+",
7387
+ item.moreCount,
7388
+ " more"
7389
+ ]
7390
+ }, "more-results") : null
7391
+ })
8341
7392
  ]
8342
7393
  });
8343
7394
  }
8344
- function isRecord$2(value) {
8345
- return typeof value === "object" && value !== null;
8346
- }
8347
- function parseStructuredJson(value) {
8348
- if (typeof value !== "string") return value;
8349
- const trimmed = value.trim();
8350
- if (!trimmed) return value;
8351
- try {
8352
- const parsed = JSON.parse(trimmed);
8353
- return isRecord$2(parsed) || Array.isArray(parsed) ? parsed : value;
8354
- } catch {
8355
- return value;
8356
- }
8357
- }
8358
- function normalizeToolPart(part) {
8359
- if (!isRecord$2(part)) return part;
8360
- if (typeof part.type !== "string" || !part.type.startsWith("tool-")) return part;
8361
- const normalizedInput = parseStructuredJson(part.input);
8362
- const normalizedOutput = parseStructuredJson(part.output);
8363
- const normalizedResult = parseStructuredJson(part.result);
8364
- const inputChanged = normalizedInput !== part.input;
8365
- const outputChanged = normalizedOutput !== part.output;
8366
- const resultChanged = normalizedResult !== part.result;
8367
- if (!inputChanged && !outputChanged && !resultChanged) return part;
8368
- const normalizedPart = { ...part };
8369
- if (inputChanged) normalizedPart.input = normalizedInput;
8370
- if (outputChanged) normalizedPart.output = normalizedOutput;
8371
- if (resultChanged) normalizedPart.result = normalizedResult;
8372
- return normalizedPart;
8373
- }
8374
- function normalizeAssistantToolParts(parts) {
8375
- let changed = false;
8376
- const normalizedParts = parts.map((part) => {
8377
- const normalizedPart = normalizeToolPart(part);
8378
- if (normalizedPart !== part) changed = true;
8379
- return normalizedPart;
8380
- });
8381
- return changed ? normalizedParts : parts;
8382
- }
8383
- var timeFormatter = new Intl.DateTimeFormat("en-US", {
8384
- hour: "numeric",
8385
- minute: "2-digit",
8386
- hour12: true
8387
- });
8388
- var dateFormatter = new Intl.DateTimeFormat("en-US", {
8389
- month: "short",
8390
- day: "numeric"
8391
- });
8392
- function formatTimestamp(date) {
8393
- const now = /* @__PURE__ */ new Date();
8394
- if (date.getFullYear() === now.getFullYear() && date.getMonth() === now.getMonth() && date.getDate() === now.getDate()) return timeFormatter.format(date);
8395
- return dateFormatter.format(date);
7395
+ function ActionIcon({ action }) {
7396
+ if (action === "read") return /* @__PURE__ */ jsx(FileText, { className: "size-4" });
7397
+ if (action === "edit" || action === "write") return /* @__PURE__ */ jsx(PencilLine, { className: "size-4" });
7398
+ if (action === "run") return /* @__PURE__ */ jsx(SquareTerminal, { className: "size-4" });
7399
+ return /* @__PURE__ */ jsx(Wrench, { className: "size-4" });
8396
7400
  }
8397
- function CopyButton({ text, onCopied }) {
8398
- const [copied, setCopied] = useState2(false);
8399
- const copiedTimerRef = useRef2(null);
8400
- useEffect2(() => {
8401
- return () => {
8402
- if (copiedTimerRef.current) window.clearTimeout(copiedTimerRef.current);
8403
- };
8404
- }, []);
8405
- const handleCopy = async () => {
8406
- try {
8407
- await navigator.clipboard.writeText(text);
8408
- setCopied(true);
8409
- if (copiedTimerRef.current) window.clearTimeout(copiedTimerRef.current);
8410
- copiedTimerRef.current = window.setTimeout(() => {
8411
- setCopied(false);
8412
- copiedTimerRef.current = null;
8413
- }, 2e3);
8414
- notify.success("Copied to clipboard");
8415
- onCopied?.();
8416
- } catch {
8417
- notify.error("Failed to copy to clipboard");
8418
- }
8419
- };
7401
+ function ActivityAction({ action }) {
8420
7402
  return /* @__PURE__ */ jsx("button", {
8421
7403
  type: "button",
8422
- tabIndex: -1,
8423
- "aria-label": copied ? "Copied" : "Copy message",
8424
- onClick: handleCopy,
8425
- onPointerDown: (event) => {
8426
- event.stopPropagation();
8427
- },
8428
- onMouseDown: (event) => event.stopPropagation(),
8429
- className: cn("flex size-6 items-center justify-center rounded-md transition-[background-color,opacity,transform] duration-150 ease-out active:scale-[0.97]", "bg-transparent opacity-50 hover:bg-an-foreground/10 hover:opacity-100"),
8430
- children: /* @__PURE__ */ jsxs("div", {
8431
- className: "relative h-3.5 w-3.5",
8432
- children: [/* @__PURE__ */ jsx(Copy, { className: cn("absolute inset-0 h-3.5 w-3.5 text-an-foreground-muted transition-[opacity,transform] duration-150 ease-out", copied ? "scale-50 opacity-0" : "scale-100 opacity-100") }), /* @__PURE__ */ jsx(Check, { className: cn("absolute inset-0 h-3.5 w-3.5 text-an-foreground-muted transition-[opacity,transform] duration-150 ease-out", copied ? "scale-100 opacity-100" : "scale-50 opacity-0") })]
8433
- })
8434
- });
8435
- }
8436
- function MessageToolbar({ text, timestamp, heightClass, hoverClass, isVisible, alignClass, onCopied }) {
8437
- return /* @__PURE__ */ jsxs("div", {
8438
- className: cn("pointer-events-none flex items-center gap-1 pt-1 text-xs text-an-foreground-muted/70 opacity-0 transition-opacity duration-100", heightClass, alignClass, hoverClass, isVisible && "pointer-events-auto opacity-100"),
8439
- onMouseDown: (event) => event.stopPropagation(),
8440
- onPointerDown: (event) => event.stopPropagation(),
8441
- children: [timestamp && /* @__PURE__ */ jsx("span", { children: timestamp }), text && /* @__PURE__ */ jsx(CopyButton, {
8442
- text,
8443
- onCopied
8444
- })]
7404
+ "aria-label": action.ariaLabel ?? action.label,
7405
+ onClick: action.onClick,
7406
+ className: "shrink-0 rounded-md px-1.5 py-1 text-[10px] font-medium text-primary outline-none hover:bg-primary/10 focus-visible:ring-2 focus-visible:ring-ring",
7407
+ children: action.label
8445
7408
  });
8446
7409
  }
8447
- function isRecord$1(value) {
8448
- return typeof value === "object" && value !== null;
8449
- }
8450
- function isTextPart(part) {
8451
- return isRecord$1(part) && part.type === "text" && typeof part.text === "string";
8452
- }
8453
- function isErrorPart(part) {
8454
- return isRecord$1(part) && part.type === "error" && typeof part.message === "string";
8455
- }
8456
- function isPayloadPart(part) {
8457
- return isRecord$1(part) && part.type === "payload" && typeof part.kind === "string" && typeof part.title === "string";
8458
- }
8459
- function isV5ToolPart(part) {
8460
- if (!isRecord$1(part)) return false;
8461
- const partType = part.type;
8462
- return partType === "dynamic-tool" || typeof partType === "string" && partType.startsWith("tool-");
8463
- }
8464
- function getTextFromParts(parts, joiner) {
8465
- const texts = [];
8466
- for (const part of parts) if (isTextPart(part)) texts.push(part.text);
8467
- return texts.join(joiner);
8468
- }
8469
- memo(function UserTurn(props) {
8470
- const { message, UserMessageComponent, userMessageClassName, onCopied, display } = props;
8471
- const { enableImagePreview, showCopyToolbar, isMounted, isCopyVisible } = display;
8472
- const text = getTextFromParts(message.parts ?? [], "");
8473
- const hasParts = (message.parts ?? []).length > 0;
8474
- if (!text && !hasParts) return null;
8475
- const userCreatedAt = message?.createdAt;
8476
- const userCopyKey = `user-${message.id}`;
8477
- const userTimestamp = isMounted && userCreatedAt ? formatTimestamp(new Date(userCreatedAt)) : void 0;
8478
- return /* @__PURE__ */ jsxs("div", {
8479
- className: "group/user-message",
8480
- children: [/* @__PURE__ */ jsx(UserMessageComponent, {
8481
- message,
8482
- className: userMessageClassName,
8483
- enableImagePreview
8484
- }), (showCopyToolbar && Boolean(text) || Boolean(userTimestamp)) && /* @__PURE__ */ jsx(MessageToolbar, {
8485
- text: showCopyToolbar ? text : "",
8486
- timestamp: userTimestamp,
8487
- heightClass: "h-[28px]",
8488
- hoverClass: "group-hover/user-message:opacity-100 group-hover/user-message:pointer-events-auto",
8489
- isVisible: isCopyVisible,
8490
- alignClass: "justify-end",
8491
- onCopied: () => onCopied(userCopyKey)
8492
- })]
8493
- });
8494
- });
8495
- memo(function AssistantTurn(props) {
8496
- const { assistantMsgs, turnKey, ToolRendererComponent, TextRendererComponent, toolRenderers, onOpenUIAction, onOpenUIArtifactReady, onOpenArtifact, onCopied, stream, copy, display } = props;
8497
- const { isLast: isLastTurn, isStreaming } = stream;
8498
- const { enabled: showCopyToolbar, isVisible: isCopyVisible } = copy;
8499
- const { suppressQuestionTool } = display;
8500
- const assistantText = getTextFromParts(assistantMsgs.flatMap((msg) => msg.parts ?? []), "\n\n");
8501
- const isTurnStreaming = isStreaming && isLastTurn;
8502
- const showToolbar = showCopyToolbar && Boolean(assistantText.trim()) && !isTurnStreaming;
8503
- const copyKey = `assistant-${turnKey}-all`;
8504
- const toolbarText = showCopyToolbar ? assistantText : "";
7410
+ function ToolRow({ item }) {
7411
+ const action = item.action.charAt(0).toUpperCase() + item.action.slice(1);
7412
+ const hasChanges = typeof item.additions === "number" || typeof item.deletions === "number";
8505
7413
  return /* @__PURE__ */ jsxs("div", {
8506
- className: "group/assistant-turn",
8507
- children: [/* @__PURE__ */ jsx("div", {
8508
- className: "flex flex-col gap-3",
8509
- children: assistantMsgs.map((msg, i) => {
8510
- const isLastMsg = isLastTurn && i === assistantMsgs.length - 1;
8511
- return /* @__PURE__ */ jsx(AssistantParts, {
8512
- msg,
8513
- isLast: isLastMsg,
8514
- isStreaming,
8515
- suppressQuestionTool,
8516
- ToolRendererComponent,
8517
- TextRendererComponent,
8518
- toolRenderers,
8519
- onOpenUIAction,
8520
- onOpenUIArtifactReady,
8521
- onOpenArtifact
8522
- }, msg.id);
8523
- })
8524
- }), (showToolbar || isCopyVisible) && /* @__PURE__ */ jsx(MessageToolbar, {
8525
- text: toolbarText,
8526
- heightClass: "h-[48px] flex items-start w-full",
8527
- hoverClass: "group-hover/assistant-turn:opacity-100 group-hover/assistant-turn:pointer-events-auto",
8528
- isVisible: isCopyVisible,
8529
- alignClass: "justify-start",
8530
- onCopied: () => onCopied(copyKey)
8531
- })]
8532
- });
8533
- });
8534
- var TOOL_CALL_KEY_PREFIX = "tool-call:";
8535
- var UNKEYED_TOOL_KEY_PREFIX = "unkeyed-tool:";
8536
- function getAssistantToolElementKey(messageId, part, occurrence) {
8537
- if (part.toolCallId) return `${TOOL_CALL_KEY_PREFIX}${part.toolCallId}`;
8538
- return `${UNKEYED_TOOL_KEY_PREFIX}${messageId}:${part.type}:${occurrence}`;
8539
- }
8540
- function buildAssistantElements(parts, opts) {
8541
- const { messageId, isLast, isStreaming, suppressQuestionTool, suppressTextWhenPlanWrite = false, ToolRendererComponent, TextRendererComponent, toolRenderers, onOpenUIAction, onOpenUIArtifactReady, onOpenArtifact } = opts;
8542
- const elems = [];
8543
- const textChunks = [];
8544
- const hasPlanWritePresentation = suppressTextWhenPlanWrite && parts.some((part) => isV5ToolPart(part) && part.type === "tool-PlanWrite");
8545
- const taskPartIds = new Set(parts.filter((p) => isV5ToolPart(p) && (p.type === "tool-Task" || p.type === "tool-Agent") && typeof p.toolCallId === "string").map((p) => p.toolCallId));
8546
- const nestedToolsMap = /* @__PURE__ */ new Map();
8547
- const nestedToolIds = /* @__PURE__ */ new Set();
8548
- const unkeyedToolOccurrences = /* @__PURE__ */ new Map();
8549
- for (const part of parts) {
8550
- if (!isV5ToolPart(part)) continue;
8551
- if (part.type === "tool-TaskOutput") continue;
8552
- if (!part.toolCallId || !part.toolCallId.includes(":")) continue;
8553
- const parentId = part.toolCallId.split(":")[0];
8554
- if (!taskPartIds.has(parentId)) continue;
8555
- if (!nestedToolsMap.has(parentId)) nestedToolsMap.set(parentId, []);
8556
- nestedToolsMap.get(parentId).push(part);
8557
- nestedToolIds.add(part.toolCallId);
8558
- }
8559
- let i = 0;
8560
- while (i < parts.length) {
8561
- const part = parts[i];
8562
- if (isV5ToolPart(part) && part.type === "tool-TaskOutput") {
8563
- i++;
8564
- continue;
8565
- }
8566
- if (isTextPart(part)) {
8567
- const text2 = part.text;
8568
- if (text2 && !hasPlanWritePresentation) textChunks.push(text2);
8569
- i++;
8570
- continue;
8571
- }
8572
- if (isErrorPart(part)) {
8573
- elems.push(/* @__PURE__ */ jsx(ErrorMessage, {
8574
- title: part.title,
8575
- message: part.message
8576
- }, `${messageId}-error-${part.title}-${part.message}`));
8577
- i++;
8578
- continue;
8579
- }
8580
- if (isPayloadPart(part)) {
8581
- elems.push(/* @__PURE__ */ jsx(PayloadPart, { part }, `${messageId}-payload-${i}`));
8582
- i++;
8583
- continue;
8584
- }
8585
- if (isV5ToolPart(part)) {
8586
- if (suppressQuestionTool && part.type === "tool-Question") {
8587
- i++;
8588
- continue;
8589
- }
8590
- if (part.toolCallId && nestedToolIds.has(part.toolCallId)) {
8591
- i++;
8592
- continue;
8593
- }
8594
- const chatStreamingStatus = isLast && isStreaming ? "streaming" : void 0;
8595
- const toolCallId = part.toolCallId;
8596
- const nestedTools = (part.type === "tool-Task" || part.type === "tool-Agent") && toolCallId ? nestedToolsMap.get(toolCallId) || [] : void 0;
8597
- const occurrence = part.toolCallId ? 0 : unkeyedToolOccurrences.get(part.type) ?? 0;
8598
- if (!part.toolCallId) unkeyedToolOccurrences.set(part.type, occurrence + 1);
8599
- elems.push(/* @__PURE__ */ jsx(ToolRendererComponent, {
8600
- part,
8601
- nestedTools,
8602
- chatStatus: chatStreamingStatus,
8603
- toolRenderers
8604
- }, getAssistantToolElementKey(messageId, part, occurrence)));
8605
- i++;
8606
- continue;
8607
- }
8608
- i++;
8609
- }
8610
- const text = textChunks.join("\n\n");
8611
- if (text) elems.push(/* @__PURE__ */ jsx("div", {
8612
- className: "group/assistant-text text-[14px]",
8613
- children: /* @__PURE__ */ jsx(TextRendererComponent, {
8614
- content: text,
8615
- isStreaming,
8616
- messageId,
8617
- onOpenUIAction,
8618
- onOpenUIArtifactReady,
8619
- onOpenArtifact,
8620
- className: "leading-relaxed [&_p]:leading-relaxed"
8621
- })
8622
- }, `${messageId}-text-final`));
8623
- return elems;
8624
- }
8625
- function AssistantParts({ msg, isLast, isStreaming, suppressQuestionTool, ToolRendererComponent, TextRendererComponent, toolRenderers, onOpenUIAction, onOpenUIArtifactReady, onOpenArtifact }) {
8626
- const parts = useMemo2(() => normalizeAssistantToolParts(msg.parts ?? []), [msg.parts]);
8627
- const elements = useMemo2(() => buildAssistantElements(parts, {
8628
- messageId: msg.id,
8629
- isLast,
8630
- isStreaming,
8631
- suppressQuestionTool,
8632
- ToolRendererComponent,
8633
- TextRendererComponent,
8634
- toolRenderers,
8635
- onOpenUIAction,
8636
- onOpenUIArtifactReady,
8637
- onOpenArtifact
8638
- }), [
8639
- parts,
8640
- msg.id,
8641
- isLast,
8642
- isStreaming,
8643
- suppressQuestionTool,
8644
- ToolRendererComponent,
8645
- TextRendererComponent,
8646
- toolRenderers,
8647
- onOpenUIAction,
8648
- onOpenUIArtifactReady,
8649
- onOpenArtifact
8650
- ]);
8651
- if (elements.length > 1) return /* @__PURE__ */ jsx("div", {
8652
- className: "group/assistant-turn flex flex-col gap-3",
8653
- children: elements
8654
- });
8655
- return /* @__PURE__ */ jsx("div", {
8656
- className: "group/assistant-turn",
8657
- children: elements
8658
- });
8659
- }
8660
- function ImageLightbox({ open, onClose, images, initialIndex = 0 }) {
8661
- const [currentIndex, setCurrentIndex] = useState2(initialIndex);
8662
- const hasMultipleImages = images.length > 1;
8663
- useEffect2(() => {
8664
- if (open) setCurrentIndex(initialIndex);
8665
- }, [open, initialIndex]);
8666
- const goToPrevious = useCallback2((event) => {
8667
- event?.stopPropagation();
8668
- setCurrentIndex((prev) => prev > 0 ? prev - 1 : images.length - 1);
8669
- }, [images.length]);
8670
- const goToNext = useCallback2((event) => {
8671
- event?.stopPropagation();
8672
- setCurrentIndex((prev) => prev < images.length - 1 ? prev + 1 : 0);
8673
- }, [images.length]);
8674
- const onLightboxKeyDown = useEffectEvent((event) => {
8675
- switch (event.key) {
8676
- case "ArrowLeft":
8677
- event.preventDefault();
8678
- if (hasMultipleImages) goToPrevious();
8679
- break;
8680
- case "ArrowRight":
8681
- event.preventDefault();
8682
- if (hasMultipleImages) goToNext();
8683
- }
8684
- });
8685
- useEffect2(() => {
8686
- if (!open) return;
8687
- const handler = (event) => onLightboxKeyDown(event);
8688
- window.addEventListener("keydown", handler, true);
8689
- return () => window.removeEventListener("keydown", handler, true);
8690
- }, [open]);
8691
- useEffect2(() => {
8692
- if (!open) return;
8693
- const previousOverflow = document.body.style.overflow;
8694
- document.body.style.overflow = "hidden";
8695
- return () => {
8696
- document.body.style.overflow = previousOverflow;
8697
- };
8698
- }, [open]);
8699
- const dialogRef = useRef2(null);
8700
- const onLightDismiss = useEffectEvent((event) => {
8701
- if (dialogRef.current && event.target === dialogRef.current) onClose();
8702
- });
8703
- useEffect2(() => {
8704
- if (!open) return;
8705
- const dialog = dialogRef.current;
8706
- if (!dialog) return;
8707
- if (!dialog.open) dialog.showModal();
8708
- const handler = (event) => onLightDismiss(event);
8709
- dialog.addEventListener("click", handler);
8710
- return () => {
8711
- dialog.removeEventListener("click", handler);
8712
- if (dialog.open) dialog.close();
8713
- };
8714
- }, [open]);
8715
- if (typeof document === "undefined") return null;
8716
- if (!open) return null;
8717
- const currentImage = images[currentIndex] ?? images[0];
8718
- if (!currentImage?.url) return null;
8719
- return createPortal(/* @__PURE__ */ jsxs("dialog", {
8720
- ref: dialogRef,
8721
- "aria-label": "Image viewer",
8722
- onClose: () => onClose(),
8723
- className: "fixed inset-0 z-50 m-0 flex h-full max-h-none w-full max-w-none items-center justify-center border-0 bg-black/90 p-0 backdrop:bg-transparent",
7414
+ className: "grid min-h-8 min-w-0 grid-cols-[1rem_auto_minmax(0,1fr)_auto] items-center gap-2.5 rounded-md px-1.5 py-0.5 leading-5",
8724
7415
  children: [
8725
- /* @__PURE__ */ jsx("button", {
8726
- type: "button",
8727
- onClick: onClose,
8728
- "aria-label": "Close fullscreen (Esc)",
8729
- className: "absolute top-4 right-4 z-10 inline-flex size-9 items-center justify-center rounded-full bg-black/50 text-white transition-colors hover:bg-black/70",
8730
- children: /* @__PURE__ */ jsx(X, { className: "size-5" })
8731
- }),
8732
- hasMultipleImages && /* @__PURE__ */ jsx("button", {
8733
- type: "button",
8734
- onClick: goToPrevious,
8735
- "aria-label": "Previous image (\u2190)",
8736
- className: "absolute top-1/2 left-4 z-10 inline-flex size-10 -translate-y-1/2 items-center justify-center rounded-full bg-black/50 text-white transition-colors hover:bg-black/70",
8737
- children: /* @__PURE__ */ jsx(ChevronLeft, { className: "size-6" })
7416
+ /* @__PURE__ */ jsx("span", {
7417
+ "aria-hidden": "true",
7418
+ className: "grid size-4 shrink-0 place-items-center text-muted-foreground/70",
7419
+ children: /* @__PURE__ */ jsx(ActionIcon, { action: item.action })
8738
7420
  }),
8739
- /* @__PURE__ */ jsx("img", {
8740
- src: currentImage.url,
8741
- alt: currentImage.filename ?? "Image preview",
8742
- className: "max-h-[85vh] max-w-[90vw] object-contain select-none",
8743
- onClick: (event) => event.stopPropagation(),
8744
- draggable: false
7421
+ /* @__PURE__ */ jsx("span", {
7422
+ className: "shrink-0 font-medium text-foreground/90",
7423
+ children: action
8745
7424
  }),
8746
- hasMultipleImages && /* @__PURE__ */ jsx("button", {
8747
- type: "button",
8748
- onClick: goToNext,
8749
- "aria-label": "Next image (\u2192)",
8750
- className: "absolute top-1/2 right-4 z-10 inline-flex size-10 -translate-y-1/2 items-center justify-center rounded-full bg-black/50 text-white transition-colors hover:bg-black/70",
8751
- children: /* @__PURE__ */ jsx(ChevronRight, { className: "size-6" })
7425
+ /* @__PURE__ */ jsx("span", {
7426
+ className: "min-w-0 flex-1 truncate rounded-lg bg-muted/80 px-2.5 py-1 font-mono text-xs text-muted-foreground/70",
7427
+ children: item.target
8752
7428
  }),
8753
- hasMultipleImages && /* @__PURE__ */ jsxs("div", {
8754
- className: "absolute bottom-6 left-1/2 flex -translate-x-1/2 flex-col items-center gap-3",
8755
- children: [/* @__PURE__ */ jsx("div", {
8756
- className: "flex gap-2",
8757
- children: images.map((image, idx) => /* @__PURE__ */ jsx("button", {
8758
- type: "button",
8759
- onClick: (event) => {
8760
- event.stopPropagation();
8761
- setCurrentIndex(idx);
8762
- },
8763
- "aria-label": `Go to image ${idx + 1}`,
8764
- className: cn("size-2 rounded-full transition-all", idx === currentIndex ? "scale-125 bg-white" : "bg-white/40 hover:bg-white/60")
8765
- }, image.url))
8766
- }), /* @__PURE__ */ jsxs("span", {
8767
- className: "text-sm text-white/70",
8768
- children: [
8769
- currentIndex + 1,
8770
- " / ",
8771
- images.length
8772
- ]
8773
- })]
8774
- })
7429
+ hasChanges || item.openAction ? /* @__PURE__ */ jsxs("div", {
7430
+ className: "flex shrink-0 items-center gap-2",
7431
+ children: [hasChanges ? /* @__PURE__ */ jsxs("span", {
7432
+ className: "flex items-center gap-2 font-mono tabular-nums",
7433
+ children: [typeof item.additions === "number" ? /* @__PURE__ */ jsxs("span", {
7434
+ className: "text-emerald-500",
7435
+ children: ["+", item.additions]
7436
+ }) : null, typeof item.deletions === "number" ? /* @__PURE__ */ jsxs("span", {
7437
+ className: "text-rose-500",
7438
+ children: ["\u2212", item.deletions]
7439
+ }) : null]
7440
+ }) : null, item.openAction ? /* @__PURE__ */ jsx(ActivityAction, { action: item.openAction }) : null]
7441
+ }) : null
8775
7442
  ]
8776
- }), document.body);
7443
+ });
8777
7444
  }
8778
- function formatFileSize(bytes) {
8779
- if (bytes < 1024) return `${bytes} B`;
8780
- if (bytes < 1048576) return `${(bytes / 1024).toFixed(1)} KB`;
8781
- return `${(bytes / 1048576).toFixed(1)} MB`;
8782
- }
8783
- function getFileIconName(filename, isImage) {
8784
- if (isImage) return "image";
8785
- const ext = filename.split(".").pop()?.toLowerCase();
8786
- if ([
8787
- "js",
8788
- "ts",
8789
- "jsx",
8790
- "tsx",
8791
- "py",
8792
- "rb",
8793
- "go",
8794
- "rs",
8795
- "java",
8796
- "kt",
8797
- "swift",
8798
- "c",
8799
- "cpp",
8800
- "h",
8801
- "hpp",
8802
- "cs",
8803
- "php"
8804
- ].includes(ext || "")) return "code";
8805
- if ([
8806
- "json",
8807
- "yaml",
8808
- "yml",
8809
- "xml"
8810
- ].includes(ext || "")) return "data";
8811
- return "text";
8812
- }
8813
- function renderFileIcon(iconName) {
8814
- switch (iconName) {
8815
- case "image":
8816
- return /* @__PURE__ */ jsx(Image, { className: "size-4 text-muted-foreground" });
8817
- case "code":
8818
- return /* @__PURE__ */ jsx(FileCode, { className: "size-4 text-muted-foreground" });
8819
- case "data":
8820
- return /* @__PURE__ */ jsx(FileBraces, { className: "size-4 text-muted-foreground" });
8821
- default:
8822
- return /* @__PURE__ */ jsx(FileText, { className: "size-4 text-muted-foreground" });
8823
- }
7445
+ function TraceIcon({ kind }) {
7446
+ if (kind === "thinking") return /* @__PURE__ */ jsx(Sparkles, { className: "size-4" });
7447
+ if (kind === "message") return /* @__PURE__ */ jsx(MessageSquare, { className: "size-4" });
7448
+ if (kind === "write") return /* @__PURE__ */ jsx(PencilLine, { className: "size-4" });
7449
+ if (kind === "run") return /* @__PURE__ */ jsx(SquareTerminal, { className: "size-4" });
7450
+ if (kind === "read") return /* @__PURE__ */ jsx(Image, { className: "size-4" });
7451
+ return /* @__PURE__ */ jsx(Wrench, { className: "size-4" });
8824
7452
  }
8825
- function FileAttachment({ id, filename, size, isImage, url, onRemove, className, display = "chip", enableImagePreview = true }) {
8826
- const [isHovered, setIsHovered] = useState2(false);
8827
- const [isLightboxOpen, setIsLightboxOpen] = useState2(false);
8828
- const iconName = getFileIconName(filename, isImage);
8829
- const isImageOnly = display === "image-only" && isImage && !!url;
8830
- const canPreview = Boolean(enableImagePreview && isImage && url);
8831
- const openLightbox = (event) => {
8832
- event?.stopPropagation();
8833
- setIsLightboxOpen(true);
8834
- };
7453
+ function TraceRow({ item }) {
7454
+ const thinking = item.kind === "thinking";
8835
7455
  return /* @__PURE__ */ jsxs("div", {
8836
- className: cn("relative rounded-[calc(var(--an-input-border-radius)-var(--an-context-padding))] bg-muted/50", isImageOnly ? "flex size-10 items-center justify-center" : "flex max-w-[200px] min-w-[120px] items-center gap-2 py-1 pr-2 pl-1", className),
8837
- onMouseEnter: () => setIsHovered(true),
8838
- onMouseLeave: () => setIsHovered(false),
7456
+ className: cn("grid min-h-8 grid-cols-[1rem_auto_minmax(0,1fr)_auto] gap-2.5 rounded-md px-1.5 py-0.5", thinking ? "items-start" : "items-center"),
8839
7457
  children: [
8840
- isImageOnly ? /* @__PURE__ */ jsx("div", {
8841
- className: cn("size-8 shrink-0 overflow-hidden rounded-[calc(var(--an-input-border-radius)-var(--an-context-padding)-2px)]", canPreview && "cursor-pointer"),
8842
- onClick: canPreview ? openLightbox : void 0,
8843
- role: canPreview ? "button" : void 0,
8844
- tabIndex: canPreview ? 0 : void 0,
8845
- "aria-label": canPreview ? `Preview ${filename}` : void 0,
8846
- onKeyDown: canPreview ? (event) => {
8847
- if (event.key === "Enter" || event.key === " ") {
8848
- event.preventDefault();
8849
- openLightbox();
8850
- }
8851
- } : void 0,
8852
- children: /* @__PURE__ */ jsx("img", {
8853
- src: url,
8854
- alt: filename,
8855
- className: "h-full w-full object-cover"
8856
- })
8857
- }) : /* @__PURE__ */ jsxs(Fragment$1, { children: [isImage && url ? /* @__PURE__ */ jsx("div", {
8858
- className: cn("w-8 shrink-0 self-stretch overflow-hidden rounded-[calc(var(--an-input-border-radius)-var(--an-context-padding)-2px)]", canPreview && "cursor-pointer"),
8859
- onClick: canPreview ? openLightbox : void 0,
8860
- role: canPreview ? "button" : void 0,
8861
- tabIndex: canPreview ? 0 : void 0,
8862
- "aria-label": canPreview ? `Preview ${filename}` : void 0,
8863
- onKeyDown: canPreview ? (event) => {
8864
- if (event.key === "Enter" || event.key === " ") {
8865
- event.preventDefault();
8866
- openLightbox();
8867
- }
8868
- } : void 0,
8869
- children: /* @__PURE__ */ jsx("img", {
8870
- src: url,
8871
- alt: filename,
8872
- className: "aspect-square h-full w-full object-cover"
8873
- })
8874
- }) : /* @__PURE__ */ jsx("div", {
8875
- className: "flex w-8 shrink-0 items-center justify-center self-stretch rounded-[calc(var(--an-input-border-radius)-var(--an-context-padding)-2px)] bg-muted",
8876
- children: renderFileIcon(iconName)
8877
- }), /* @__PURE__ */ jsxs("div", {
8878
- className: "flex min-w-0 flex-col",
8879
- children: [/* @__PURE__ */ jsx("span", {
8880
- className: "truncate text-sm font-medium text-foreground",
8881
- title: filename,
8882
- children: filename
8883
- }), size !== void 0 && /* @__PURE__ */ jsx("span", {
8884
- className: "text-[10px] text-muted-foreground",
8885
- children: formatFileSize(size)
8886
- })]
8887
- })] }),
8888
- onRemove && /* @__PURE__ */ jsx("button", {
8889
- onClick: (e) => {
8890
- e.stopPropagation();
8891
- onRemove();
8892
- },
8893
- "aria-label": `Remove ${filename}`,
8894
- className: `absolute -top-1.5 -right-1.5 z-10 flex size-4 items-center justify-center rounded-full border border-border bg-background text-muted-foreground transition-[opacity,transform] duration-150 ease-out hover:text-foreground active:scale-[0.97] ${isHovered ? "opacity-100" : "opacity-0"}`,
8895
- type: "button",
8896
- children: /* @__PURE__ */ jsx(X, { className: "size-3" })
7458
+ /* @__PURE__ */ jsx("span", {
7459
+ "aria-hidden": "true",
7460
+ className: "grid size-4 place-items-center text-muted-foreground/70",
7461
+ children: item.icon ?? /* @__PURE__ */ jsx(TraceIcon, { kind: item.kind })
8897
7462
  }),
8898
- canPreview && url && /* @__PURE__ */ jsx(ImageLightbox, {
8899
- open: isLightboxOpen,
8900
- onClose: () => setIsLightboxOpen(false),
8901
- images: [{
8902
- id,
8903
- url,
8904
- filename
8905
- }]
8906
- })
7463
+ /* @__PURE__ */ jsx("span", {
7464
+ className: "min-w-0 truncate font-medium text-foreground/90",
7465
+ children: item.label
7466
+ }),
7467
+ item.detail ? /* @__PURE__ */ jsx("span", {
7468
+ className: cn("min-w-0 rounded-lg bg-muted/80 px-2.5 py-1 font-mono text-xs text-muted-foreground/70", thinking ? "max-h-40 overflow-y-auto whitespace-pre-wrap break-words" : "truncate"),
7469
+ children: item.detail
7470
+ }) : /* @__PURE__ */ jsx("span", {}),
7471
+ item.action ? /* @__PURE__ */ jsx(ActivityAction, { action: item.action }) : null
8907
7472
  ]
8908
7473
  });
8909
7474
  }
8910
- function isRecord(value) {
8911
- return typeof value === "object" && value !== null;
7475
+ function ActivityRow({ item }) {
7476
+ if (item.type === "text") return /* @__PURE__ */ jsx(TextRow, { item });
7477
+ if (item.type === "search") return /* @__PURE__ */ jsx(SearchRow, { item });
7478
+ if (item.type === "tool") return /* @__PURE__ */ jsx(ToolRow, { item });
7479
+ if (item.type === "trace") return /* @__PURE__ */ jsx(TraceRow, { item });
7480
+ return /* @__PURE__ */ jsx(StepRow, { item });
7481
+ }
7482
+ function formatDuration(duration) {
7483
+ const seconds = Math.max(0, Math.round(duration));
7484
+ if (seconds < 60) return `${seconds}s`;
7485
+ const minutes = Math.floor(seconds / 60);
7486
+ const remainder = seconds % 60;
7487
+ return remainder === 0 ? `${minutes}m` : `${minutes}m ${remainder}s`;
7488
+ }
7489
+ function useControllableOpen({ open, defaultOpen, onOpenChange }) {
7490
+ const [internalOpen, setInternalOpen] = useState2(defaultOpen);
7491
+ const controlled = open !== void 0;
7492
+ return [open ?? internalOpen, useCallback2((next) => {
7493
+ if (!controlled) setInternalOpen(next);
7494
+ onOpenChange?.(next);
7495
+ }, [controlled, onOpenChange])];
7496
+ }
7497
+ function getContentType(items) {
7498
+ const first = items[0]?.type;
7499
+ return first && items.every((item) => item.type === first) ? first : "mixed";
7500
+ }
7501
+ function getActiveLabel(type) {
7502
+ if (type === "search") return "Searching the web\u2026";
7503
+ if (type === "tool") return "Running tools\u2026";
7504
+ if (type === "trace") return "Working through the run\u2026";
7505
+ if (type === "mixed") return "Working through it\u2026";
7506
+ return "Thinking\u2026";
8912
7507
  }
8913
- function getImageUrlFromPart(part) {
8914
- if (!isRecord(part)) return null;
8915
- const type = part.type;
8916
- if (typeof type !== "string") return null;
8917
- if (type === "image") {
8918
- const imagePart = part;
8919
- return imagePart.url ?? imagePart.image ?? null;
8920
- }
8921
- if (type === "data-image") return part.data?.url ?? null;
8922
- if (type === "file") {
8923
- const filePart = part;
8924
- if (filePart.mimeType?.startsWith("image/")) {
8925
- if (filePart.url) return filePart.url;
8926
- if (filePart.data) return `data:${filePart.mimeType};base64,${filePart.data}`;
8927
- }
7508
+ function getSummary(type, items, duration) {
7509
+ if (type === "step" || type === "text") return /* @__PURE__ */ jsxs(Fragment$1, { children: ["Thought for ", /* @__PURE__ */ jsx("span", {
7510
+ className: "tabular-nums",
7511
+ children: formatDuration(duration)
7512
+ })] });
7513
+ if (type === "search") return "Searched the web";
7514
+ if (type === "tool") return `Ran ${items.length} ${items.length === 1 ? "tool" : "tools"}`;
7515
+ if (type === "trace") {
7516
+ const messages = items.filter((item) => item.type === "trace" && (item.kind === "thinking" || item.kind === "message")).length;
7517
+ const tools = items.length - messages;
7518
+ return `${tools} ${tools === 1 ? "tool call" : "tool calls"}, ${messages} ${messages === 1 ? "message" : "messages"}`;
8928
7519
  }
8929
- return null;
7520
+ return `Completed ${items.length} ${items.length === 1 ? "step" : "steps"}`;
8930
7521
  }
8931
- function getFileFromPart(part) {
8932
- if (!isRecord(part)) return null;
8933
- if (part.type !== "file") return null;
8934
- const filePart = part;
8935
- const filename = filePart.filename || filePart.name || filePart.fileName || "Attachment";
8936
- if (filePart.mimeType?.startsWith("image/") ?? false) return null;
8937
- return {
8938
- filename,
8939
- size: filePart.size
7522
+ function AgentActivity({ items, contentType: initialContentType, status = "working", duration = 0, open, defaultOpen = false, onOpenChange, collapseOnComplete = true, activeLabel, summary, renderWorkingStatus, renderCompletedStatus, maxHeight = 208, className, contentClassName }) {
7523
+ const reduce = useReducedMotion() ?? false;
7524
+ const baseId = useId();
7525
+ const triggerId = `${baseId}-trigger`;
7526
+ const contentId = `${baseId}-content`;
7527
+ const contentRef = useRef2(null);
7528
+ const viewportRef = useRef2(null);
7529
+ const previousStatus = useRef2(status);
7530
+ const [contentHeight, setContentHeight] = useState2(0);
7531
+ const [currentOpen, setOpen] = useControllableOpen({
7532
+ open,
7533
+ defaultOpen,
7534
+ onOpenChange
7535
+ });
7536
+ const working = status === "working";
7537
+ const expanded = working || currentOpen;
7538
+ const contentType = items.length ? getContentType(items) : initialContentType ?? "mixed";
7539
+ const viewportHeight = working ? Math.max(0, maxHeight) : Math.min(contentHeight, Math.max(0, maxHeight));
7540
+ const capped = contentHeight > maxHeight;
7541
+ const streamOffset = working ? Math.min(0, viewportHeight - contentHeight) : 0;
7542
+ useLayoutEffect(() => {
7543
+ const node = contentRef.current;
7544
+ if (!node) return;
7545
+ const measure = () => setContentHeight(node.offsetHeight);
7546
+ measure();
7547
+ if (typeof ResizeObserver === "undefined") return;
7548
+ const observer = new ResizeObserver(measure);
7549
+ observer.observe(node);
7550
+ return () => observer.disconnect();
7551
+ }, []);
7552
+ useEffect2(() => {
7553
+ if (previousStatus.current === "working" && status === "complete") setOpen(!collapseOnComplete);
7554
+ previousStatus.current = status;
7555
+ }, [
7556
+ collapseOnComplete,
7557
+ setOpen,
7558
+ status
7559
+ ]);
7560
+ const toggle = () => {
7561
+ const next = !currentOpen;
7562
+ setOpen(next);
7563
+ if (next) requestAnimationFrame(() => viewportRef.current?.scrollTo({ top: 0 }));
8940
7564
  };
8941
- }
8942
- var UserMessage = memo(function UserMessage2({ message, className, enableImagePreview = true }) {
8943
- const [lightboxIndex, setLightboxIndex] = useState2(null);
8944
- const text = (message.parts?.filter(isTextPart) ?? []).map((p) => p.text).join("");
8945
- const images = [];
8946
- const files = [];
8947
- for (const part of message.parts ?? []) {
8948
- const imageUrl = getImageUrlFromPart(part);
8949
- if (imageUrl) images.push(imageUrl);
8950
- const file = getFileFromPart(part);
8951
- if (file) files.push(file);
8952
- }
8953
- if (isRecord(message) && Array.isArray(message.experimental_attachments)) {
8954
- for (const att of message.experimental_attachments) if (att.contentType?.startsWith("image/") && att.url) images.push(att.url);
8955
- }
8956
- if (!text && images.length === 0 && files.length === 0) return null;
8957
- const lightboxImages = images.map((url, i) => ({
8958
- id: `${message.id}-img-${i}`,
8959
- url,
8960
- filename: `image-${i + 1}`
8961
- }));
7565
+ const liveLabel = activeLabel ?? getActiveLabel(contentType);
7566
+ const completedSummary = summary ?? getSummary(contentType, items, duration);
7567
+ const maskImage = capped ? working ? "linear-gradient(to bottom, transparent, black 12px)" : "linear-gradient(to bottom, transparent, black 12px, black calc(100% - 12px), transparent)" : void 0;
8962
7568
  return /* @__PURE__ */ jsxs("div", {
8963
- className: cn("flex flex-col items-end gap-1", className),
8964
- children: [
8965
- images.length > 0 && images.map((url, i) => /* @__PURE__ */ jsx("div", {
8966
- className: cn("max-w-[200px] rounded-an-message bg-an-foreground/4 p-1.5", enableImagePreview && "cursor-pointer"),
8967
- onClick: enableImagePreview ? () => setLightboxIndex(i) : void 0,
8968
- role: enableImagePreview ? "button" : void 0,
8969
- tabIndex: enableImagePreview ? 0 : void 0,
8970
- onKeyDown: enableImagePreview ? (event) => {
8971
- if (event.key === "Enter" || event.key === " ") {
8972
- event.preventDefault();
8973
- setLightboxIndex(i);
8974
- }
8975
- } : void 0,
8976
- children: /* @__PURE__ */ jsx("img", {
8977
- src: url,
8978
- alt: "attachment",
8979
- className: "block max-h-[120px] max-w-[184px] rounded-an-message-inner object-cover"
8980
- })
8981
- }, url)),
8982
- enableImagePreview && lightboxImages.length > 0 && /* @__PURE__ */ jsx(ImageLightbox, {
8983
- open: lightboxIndex !== null,
8984
- onClose: () => setLightboxIndex(null),
8985
- images: lightboxImages,
8986
- initialIndex: lightboxIndex ?? 0
8987
- }),
8988
- files.length > 0 && /* @__PURE__ */ jsx("div", {
8989
- className: "flex flex-col items-end gap-2",
8990
- children: files.map((file, i) => /* @__PURE__ */ jsx(FileAttachment, {
8991
- id: `${file.filename}-${i}`,
8992
- filename: file.filename,
8993
- size: file.size
8994
- }, `${file.filename}-${file.size}`))
8995
- }),
8996
- text && /* @__PURE__ */ jsx("div", {
8997
- className: "ms-[70px] max-w-[calc(95%-40px)]",
8998
- children: /* @__PURE__ */ jsx("div", {
8999
- className: "rounded-an-message bg-an-user-message-bg px-3.5 py-1.5 text-sm text-an-user-message-text transition-colors",
9000
- children: /* @__PURE__ */ jsx("p", {
9001
- className: "leading-5 wrap-break-word whitespace-pre-wrap",
9002
- children: text
7569
+ "data-state": working ? "working" : expanded ? "open" : "closed",
7570
+ "data-content": contentType,
7571
+ "aria-busy": working,
7572
+ className: cn("w-full text-sm", className),
7573
+ children: [working ? /* @__PURE__ */ jsx("div", {
7574
+ id: triggerId,
7575
+ role: "status",
7576
+ className: "flex h-7 min-w-0 items-center text-muted-foreground",
7577
+ children: renderWorkingStatus ? renderWorkingStatus({
7578
+ label: liveLabel,
7579
+ duration
7580
+ }) : /* @__PURE__ */ jsx(ThinkingShimmer, { children: liveLabel })
7581
+ }) : /* @__PURE__ */ jsxs("button", {
7582
+ id: triggerId,
7583
+ type: "button",
7584
+ "aria-expanded": expanded,
7585
+ "aria-controls": contentId,
7586
+ onClick: toggle,
7587
+ className: "group flex h-7 min-w-0 items-center gap-1.5 rounded-md text-left font-medium text-muted-foreground outline-none transition-colors hover:text-foreground focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background",
7588
+ children: [/* @__PURE__ */ jsx("span", {
7589
+ className: "truncate",
7590
+ children: renderCompletedStatus ? renderCompletedStatus({
7591
+ summary: completedSummary,
7592
+ duration
7593
+ }) : completedSummary
7594
+ }), /* @__PURE__ */ jsx(motion.span, {
7595
+ "aria-hidden": "true",
7596
+ animate: { rotate: expanded ? 180 : 0 },
7597
+ transition: reduce ? { duration: 0 } : SPRING_SWAP,
7598
+ className: "inline-flex shrink-0 text-muted-foreground/70 group-hover:text-foreground",
7599
+ children: /* @__PURE__ */ jsx(ChevronDown, { className: "size-3.5" })
7600
+ })]
7601
+ }), /* @__PURE__ */ jsx(AgentDisclosure, {
7602
+ id: contentId,
7603
+ role: "region",
7604
+ "aria-labelledby": triggerId,
7605
+ open: expanded,
7606
+ openHeight: viewportHeight,
7607
+ children: /* @__PURE__ */ jsx("div", {
7608
+ ref: viewportRef,
7609
+ className: cn("scrollbar-hide pr-1", capped && expanded && !working ? "overflow-y-auto" : "overflow-y-hidden"),
7610
+ style: {
7611
+ height: viewportHeight,
7612
+ maskImage,
7613
+ WebkitMaskImage: maskImage
7614
+ },
7615
+ children: /* @__PURE__ */ jsx(motion.div, {
7616
+ ref: contentRef,
7617
+ role: "list",
7618
+ initial: false,
7619
+ animate: { y: streamOffset },
7620
+ transition: reduce ? { duration: 0 } : SPRING_LAYOUT,
7621
+ className: cn("space-y-0.5 py-2", contentClassName),
7622
+ children: /* @__PURE__ */ jsx(AnimatePresence, {
7623
+ mode: "popLayout",
7624
+ children: items.map((item) => /* @__PURE__ */ jsx(motion.div, {
7625
+ layout: "position",
7626
+ role: "listitem",
7627
+ initial: reduce ? { opacity: 1 } : {
7628
+ opacity: 0,
7629
+ y: 6
7630
+ },
7631
+ animate: {
7632
+ opacity: 1,
7633
+ y: 0
7634
+ },
7635
+ exit: reduce ? { opacity: 0 } : {
7636
+ opacity: 0,
7637
+ y: -3
7638
+ },
7639
+ transition: reduce ? { duration: 0 } : {
7640
+ opacity: {
7641
+ duration: 0.18,
7642
+ ease: EASE_OUT
7643
+ },
7644
+ y: SPRING_LAYOUT,
7645
+ layout: SPRING_LAYOUT
7646
+ },
7647
+ children: /* @__PURE__ */ jsx(ActivityRow, { item })
7648
+ }, item.id))
9003
7649
  })
9004
7650
  })
9005
7651
  })
9006
- ]
9007
- });
9008
- });
9009
- var LazyGenerativeTextRenderer = lazy(() => import("./openui-renderer-BT5jL0Yf-XYLLN5U6.js").then((n) => n.n).then(({ GenerativeTextRenderer }) => ({ default: GenerativeTextRenderer })));
9010
- function PlainTextFallback({ className, content }) {
9011
- return /* @__PURE__ */ jsx("div", {
9012
- className: className ? `${className} whitespace-pre-wrap` : "whitespace-pre-wrap",
9013
- children: content
7652
+ })]
9014
7653
  });
9015
7654
  }
9016
- function FleetGenerativeTextRenderer(props) {
9017
- if (!useMemo2(() => segmentOpenUIContent(props.content).some((segment) => segment.type === "openui"), [props.content])) return /* @__PURE__ */ jsx(LazyMarkdown, {
9018
- className: props.className,
9019
- content: props.content
9020
- });
9021
- return /* @__PURE__ */ jsx(Suspense, {
9022
- fallback: /* @__PURE__ */ jsx(PlainTextFallback, {
9023
- className: props.className,
9024
- content: props.content
9025
- }),
9026
- children: /* @__PURE__ */ jsx(LazyGenerativeTextRenderer, { ...props })
9027
- });
7655
+ function PromptSuggestions({ suggestions, selectedSuggestion, cycle, onSuggestion, variant = "pills", className, ...props }) {
7656
+ const list = variant === "list";
7657
+ return /* @__PURE__ */ jsx("div", {
7658
+ "data-slot": "suggestions",
7659
+ className: cn(list ? "flex w-full max-w-sm flex-col gap-2" : "flex w-full max-w-xl flex-wrap justify-center gap-1", className),
7660
+ ...props,
7661
+ children: suggestions.map((suggestion, index) => /* @__PURE__ */ jsx("button", {
7662
+ type: "button",
7663
+ "aria-pressed": selectedSuggestion === suggestion,
7664
+ onClick: () => onSuggestion(suggestion),
7665
+ className: cn(paper, "fade-in slide-in-from-bottom-2 animate-in fill-mode-both flex cursor-pointer items-center text-[13px] text-foreground/80 transition-[color,transform] duration-300 hover:-translate-y-px hover:text-foreground focus-visible:text-foreground active:scale-[0.96] motion-reduce:animate-none", list ? "w-full rounded-2xl px-4 py-2.5 text-start" : "rounded-full px-4 py-2", selectedSuggestion === suggestion && "!bg-foreground !text-background hover:!text-background focus-visible:!text-background"),
7666
+ style: { animationDelay: `${index * 70}ms` },
7667
+ children: suggestion
7668
+ }, suggestion))
7669
+ }, cycle);
9028
7670
  }
9029
7671
  var GRID_CELLS = [
9030
7672
  {
@@ -11544,9 +10186,6 @@ function useFleetPiInputBarState({ models, status, thinkingLevel, onModelChange,
11544
10186
  value
11545
10187
  };
11546
10188
  }
11547
- function withFleetPiSuggestionStyles(suggestions) {
11548
- return suggestions;
11549
- }
11550
10189
  var FLEET_PI_CHAT_MODES = [
11551
10190
  {
11552
10191
  id: "agent",
@@ -11720,6 +10359,16 @@ function FleetPiInputBarContent({ modelKey, models, status, infoDescription, cha
11720
10359
  })
11721
10360
  });
11722
10361
  }
10362
+ function getChatErrorPresentation(error) {
10363
+ if (error.code === "NETWORK_DISCONNECTED" || /Cannot send daemon command/i.test(error.message) || /Prime Agent daemon is not connected/i.test(error.message) || /not connected to the Prime Agent runtime/i.test(error.message)) return {
10364
+ title: "Agent unavailable",
10365
+ message: NETWORK_DISCONNECTED_MESSAGE
10366
+ };
10367
+ return {
10368
+ title: "Request failed",
10369
+ message: error.message.replace(/\s+(?:Socket|Daemon log):\s*[^\n]*(?:\s+(?:Socket|Daemon log):\s*[^\n]*)*/gi, "")
10370
+ };
10371
+ }
11723
10372
  var CELL_SHAPES = {
11724
10373
  dots: "rounded-full",
11725
10374
  squares: "rounded-[1px]",
@@ -11887,7 +10536,58 @@ function formatElapsed(elapsedMs) {
11887
10536
  if (seconds < 60) return String(seconds) + "s";
11888
10537
  return String(Math.floor(seconds / 60)) + "m " + String(seconds % 60) + "s";
11889
10538
  }
11890
- var LazyFleetPiToolRenderer = lazy(() => import("./fleet-pi-tool-renderer-5vYFNeZS-IHKMLT7W.js").then(({ FleetPiToolRenderer: FleetPiToolRenderer2 }) => ({ default: FleetPiToolRenderer2 })));
10539
+ var LANES = [{
10540
+ key: "steering",
10541
+ label: "Next"
10542
+ }, {
10543
+ key: "followUp",
10544
+ label: "After run"
10545
+ }];
10546
+ function FleetMessageQueue({ queue, onDelete, className }) {
10547
+ const count = queue.steering.length + queue.followUp.length;
10548
+ if (count === 0) return null;
10549
+ const handleDelete = async (lane, index, text) => {
10550
+ try {
10551
+ if (await onDelete?.(lane, index, text) === false) notify.error("Unable to remove queued message");
10552
+ } catch {
10553
+ notify.error("Unable to remove queued message");
10554
+ }
10555
+ };
10556
+ return /* @__PURE__ */ jsx("section", {
10557
+ "aria-label": "Queued messages",
10558
+ className: cn("mx-auto mb-2 w-full max-w-an px-3", className),
10559
+ children: /* @__PURE__ */ jsxs("div", {
10560
+ className: "rounded-xl border border-border/60 bg-muted/30 p-2",
10561
+ children: [/* @__PURE__ */ jsxs("div", {
10562
+ className: "mb-1 flex items-baseline justify-between px-1 text-xs text-muted-foreground",
10563
+ children: [/* @__PURE__ */ jsxs("span", { children: [count, " queued"] }), /* @__PURE__ */ jsx("span", { children: "Sent when the run reaches its lane" })]
10564
+ }), /* @__PURE__ */ jsx("div", {
10565
+ className: "space-y-1",
10566
+ children: LANES.flatMap(({ key, label }) => queue[key].map((text, index) => /* @__PURE__ */ jsxs("div", {
10567
+ className: "flex min-w-0 items-center gap-2 rounded-lg bg-background/80 px-2 py-1.5 text-sm",
10568
+ children: [
10569
+ /* @__PURE__ */ jsx("span", {
10570
+ className: "shrink-0 text-[10px] font-medium uppercase tracking-wide text-muted-foreground",
10571
+ children: label
10572
+ }),
10573
+ /* @__PURE__ */ jsx("span", {
10574
+ className: "min-w-0 flex-1 truncate text-foreground/80",
10575
+ children: text
10576
+ }),
10577
+ onDelete ? /* @__PURE__ */ jsx("button", {
10578
+ type: "button",
10579
+ "aria-label": `Remove queued message: ${text}`,
10580
+ onClick: () => void handleDelete(key, index, text),
10581
+ className: "grid size-6 shrink-0 place-items-center rounded-md text-muted-foreground transition-colors hover:bg-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
10582
+ children: /* @__PURE__ */ jsx(X, { className: "size-3.5" })
10583
+ }) : null
10584
+ ]
10585
+ }, `${key}:${index}:${text}`)))
10586
+ })]
10587
+ })
10588
+ });
10589
+ }
10590
+ var LazyFleetPiToolRenderer = lazy(() => import("./fleet-pi-tool-renderer-lJvZWmBJ-4M5YI6VS.js").then(({ FleetPiToolRenderer: FleetPiToolRenderer2 }) => ({ default: FleetPiToolRenderer2 })));
11891
10591
  function FleetPiToolRenderer(props) {
11892
10592
  return /* @__PURE__ */ jsx(Suspense, {
11893
10593
  fallback: /* @__PURE__ */ jsx("div", {
@@ -11897,29 +10597,6 @@ function FleetPiToolRenderer(props) {
11897
10597
  children: /* @__PURE__ */ jsx(LazyFleetPiToolRenderer, { ...props })
11898
10598
  });
11899
10599
  }
11900
- function groupMessages(messages) {
11901
- const turns = [];
11902
- let current;
11903
- for (const message of messages) {
11904
- if (message.role === "user") {
11905
- if (current) turns.push(current);
11906
- current = {
11907
- user: message,
11908
- assistants: []
11909
- };
11910
- continue;
11911
- }
11912
- if (message.role !== "assistant") continue;
11913
- if (!current || message.source === "local") {
11914
- if (current) turns.push(current);
11915
- current = { assistants: [message] };
11916
- continue;
11917
- }
11918
- current.assistants.push(message);
11919
- }
11920
- if (current) turns.push(current);
11921
- return turns;
11922
- }
11923
10600
  function textFromMessage(message) {
11924
10601
  return (message.parts ?? []).flatMap((part) => {
11925
10602
  if (typeof part === "object" && part !== null && "type" in part && part.type === "text" && "text" in part && typeof part.text === "string") return [part.text];
@@ -11945,17 +10622,39 @@ function reasoningPresentationFromMessages(messages) {
11945
10622
  return presentation;
11946
10623
  }
11947
10624
  }
10625
+ function runIdFromAssistantMessageId(messageId) {
10626
+ return /^(.*)-a\d+$/.exec(messageId)?.[1];
10627
+ }
10628
+ function artifactsForCurrentTurn(artifactRuns, messages) {
10629
+ if (!artifactRuns || messages.length === 0) return [];
10630
+ const messageIds = new Set(messages.map((message) => message.id));
10631
+ const toolCallIds = new Set(messages.flatMap((message) => (message.parts ?? []).flatMap((part) => {
10632
+ const source = record(part);
10633
+ return typeof source?.toolCallId === "string" && source.toolCallId ? [source.toolCallId] : [];
10634
+ })));
10635
+ const currentRunIds = new Set(messages.flatMap((message) => {
10636
+ const runId = runIdFromAssistantMessageId(message.id);
10637
+ return runId ? [message.id, runId] : [message.id];
10638
+ }));
10639
+ return artifactRuns.flatMap((run) => run.artifacts).filter((artifact) => {
10640
+ if (artifact.sourceMessageId) return messageIds.has(artifact.sourceMessageId);
10641
+ if (artifact.sourceToolCallId) return toolCallIds.has(artifact.sourceToolCallId) || currentRunIds.has(artifact.runId);
10642
+ return currentRunIds.has(artifact.runId);
10643
+ });
10644
+ }
11948
10645
  function buildActivityItems(messages, presentation, artifactRuns = [], onOpenArtifact) {
11949
10646
  const items = /* @__PURE__ */ new Map();
11950
10647
  const artifacts = artifactRuns.flatMap((run) => run.artifacts);
11951
10648
  const openArtifactAction = (sourceId) => {
11952
10649
  const artifactIndex = artifacts.findIndex((candidate) => candidate.sourceToolCallId === sourceId);
11953
10650
  const artifact = artifactIndex >= 0 ? artifacts[artifactIndex] : void 0;
11954
- return artifact && onOpenArtifact ? {
11955
- label: "Open in Artifacts",
10651
+ const target = artifact?.kind === "ipython" ? "repl" : artifact ? "artifacts" : void 0;
10652
+ if (!artifact || !target || !onOpenArtifact) return void 0;
10653
+ return {
10654
+ label: target === "repl" ? "Open in REPL" : "Open in Artifacts",
11956
10655
  ariaLabel: `Open ${artifact.title || "tool result"} artifact ${artifactIndex + 1}`,
11957
- onClick: () => onOpenArtifact(artifact.id)
11958
- } : void 0;
10656
+ onClick: () => onOpenArtifact(artifact.id, target)
10657
+ };
11959
10658
  };
11960
10659
  for (const message of messages) for (const [partIndex, part] of (message.parts ?? []).entries()) {
11961
10660
  const partRecord = record(part);
@@ -12051,6 +10750,11 @@ function AssistantMessage({ messages, isLast, isStreaming, suppressQuestionTool,
12051
10750
  presentation
12052
10751
  ]);
12053
10752
  const reasoningPresentation = useMemo2(() => reasoningPresentationFromMessages(messages), [messages]);
10753
+ const timelineArtifacts = useMemo2(() => isLast ? artifactsForCurrentTurn(artifactRuns, messages) : [], [
10754
+ artifactRuns,
10755
+ isLast,
10756
+ messages
10757
+ ]);
12054
10758
  const [activityOpen, setActivityOpen] = useState2(turnStreaming);
12055
10759
  const [prevTurnStreaming, setPrevTurnStreaming] = useState2(turnStreaming);
12056
10760
  if (prevTurnStreaming !== turnStreaming) {
@@ -12071,6 +10775,11 @@ function AssistantMessage({ messages, isLast, isStreaming, suppressQuestionTool,
12071
10775
  label: activityLabel,
12072
10776
  className: "mb-2"
12073
10777
  }) : null,
10778
+ /* @__PURE__ */ jsx(FleetToolTimeline, {
10779
+ messages,
10780
+ artifacts: timelineArtifacts,
10781
+ streaming: turnStreaming
10782
+ }),
12074
10783
  /* @__PURE__ */ jsx(StreamingResponse, {
12075
10784
  status: turnStreaming ? "streaming" : "complete",
12076
10785
  copyText: copyText || void 0,
@@ -12088,6 +10797,10 @@ function AssistantMessage({ messages, isLast, isStreaming, suppressQuestionTool,
12088
10797
  collapseOnComplete: true,
12089
10798
  maxHeight: 208,
12090
10799
  className: "mt-2 max-w-none"
10800
+ }) : null,
10801
+ isLast && presentation ? /* @__PURE__ */ jsx(FleetSubagentList, {
10802
+ children: presentation.rlmChildren,
10803
+ tree: presentation.rlmTree
12091
10804
  }) : null
12092
10805
  ] })
12093
10806
  }) })
@@ -12140,16 +10853,6 @@ function resolveSuggestions(suggestions) {
12140
10853
  if (Array.isArray(suggestions)) return suggestions;
12141
10854
  return suggestions?.items ?? [];
12142
10855
  }
12143
- function getChatErrorPresentation(error) {
12144
- if (error.code === "NETWORK_DISCONNECTED" || /Cannot send daemon command/i.test(error.message) || /Prime Agent daemon is not connected/i.test(error.message) || /not connected to the Prime Agent runtime/i.test(error.message)) return {
12145
- title: "Agent unavailable",
12146
- message: NETWORK_DISCONNECTED_MESSAGE
12147
- };
12148
- return {
12149
- title: "Request failed",
12150
- message: error.message.replace(/\s+(?:Socket|Daemon log):\s*[^\n]*(?:\s+(?:Socket|Daemon log):\s*[^\n]*)*/gi, "")
12151
- };
12152
- }
12153
10856
  var WELCOME_TASKS = [
12154
10857
  {
12155
10858
  id: "welcome-explore-codebase",
@@ -12200,11 +10903,10 @@ function WelcomeState({ disabled: disabled2, onSelect, composer }) {
12200
10903
  ]
12201
10904
  });
12202
10905
  }
12203
- function FleetPiAgentChat({ toolRenderers = PI_TOOL_RENDERERS, suggestions, status, onStop, onSend, inputBar, className, messages, error, suppressQuestionTool = false, onOpenUIAction, activityLabel, presentation, artifactRuns, onOpenArtifact, onOpenUIArtifactReady }) {
10906
+ function FleetPiAgentChat({ toolRenderers = PI_TOOL_RENDERERS, suggestions, status, onStop, onSend, inputBar, className, messages, error, suppressQuestionTool = false, onOpenUIAction, activityLabel, presentation, artifactRuns, onOpenArtifact, onOpenUIArtifactReady, queue, onDeleteQueuedMessage }) {
12204
10907
  const [draft, setDraft] = useState2("");
12205
10908
  const turns = useMemo2(() => groupMessages(messages), [messages]);
12206
- const styledSuggestions = withFleetPiSuggestionStyles(suggestions);
12207
- const suggestionItems2 = resolveSuggestions(styledSuggestions);
10909
+ const suggestionItems2 = resolveSuggestions(suggestions);
12208
10910
  const suggestionTexts = useMemo2(() => suggestionItems2.flatMap((item) => item.disabled ? [] : [item.value ?? item.label]), [suggestionItems2]);
12209
10911
  const suggestionCycle = suggestionTexts.join("\0");
12210
10912
  const [selectedSuggestion, setSelectedSuggestion] = useState2(null);
@@ -12214,6 +10916,41 @@ function FleetPiAgentChat({ toolRenderers = PI_TOOL_RENDERERS, suggestions, stat
12214
10916
  setSelectedSuggestion(null);
12215
10917
  }
12216
10918
  const isStreaming = status === "streaming" || status === "submitted";
10919
+ const rendering = useMemo2(() => ({
10920
+ toolRenderers,
10921
+ onOpenUIAction,
10922
+ onOpenUIArtifactReady,
10923
+ onOpenArtifact
10924
+ }), [
10925
+ onOpenArtifact,
10926
+ onOpenUIAction,
10927
+ onOpenUIArtifactReady,
10928
+ toolRenderers
10929
+ ]);
10930
+ const stateForLast = useMemo2(() => ({
10931
+ isLast: true,
10932
+ isStreaming,
10933
+ suppressQuestionTool
10934
+ }), [isStreaming, suppressQuestionTool]);
10935
+ const stateForRest = useMemo2(() => ({
10936
+ isLast: false,
10937
+ isStreaming: false,
10938
+ suppressQuestionTool
10939
+ }), [suppressQuestionTool]);
10940
+ const activityForLast = useMemo2(() => ({
10941
+ label: activityLabel,
10942
+ presentation,
10943
+ artifactRuns
10944
+ }), [
10945
+ activityLabel,
10946
+ artifactRuns,
10947
+ presentation
10948
+ ]);
10949
+ const activityForRest = useMemo2(() => ({
10950
+ label: void 0,
10951
+ presentation: void 0,
10952
+ artifactRuns: void 0
10953
+ }), []);
12217
10954
  const isEmpty = turns.length === 0 && !error;
12218
10955
  const errorPresentation = error ? getChatErrorPresentation(error) : null;
12219
10956
  const inputBarNode = /* @__PURE__ */ jsx(FleetPiInputBar, {
@@ -12225,73 +10962,70 @@ function FleetPiAgentChat({ toolRenderers = PI_TOOL_RENDERERS, suggestions, stat
12225
10962
  onChange: setDraft
12226
10963
  },
12227
10964
  status,
12228
- suggestions: styledSuggestions,
10965
+ suggestions,
12229
10966
  onSend,
12230
10967
  onStop
12231
10968
  });
12232
10969
  return /* @__PURE__ */ jsxs("div", {
12233
10970
  className: cn("fleet-pi-agent-chat flex h-full min-h-0 flex-col bg-background", className),
12234
- children: [/* @__PURE__ */ jsxs(MessageScroller, {
12235
- className: "flex-1",
12236
- busy: isStreaming,
12237
- followOutput: true,
12238
- smooth: isStreaming,
12239
- 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"),
12240
- children: [
12241
- isEmpty ? /* @__PURE__ */ jsx(WelcomeState, {
12242
- disabled: isStreaming,
12243
- onSelect: (item) => setDraft(item.value ?? item.label),
12244
- composer: inputBarNode
12245
- }) : null,
12246
- turns.map((turn, turnIndex) => {
12247
- const key = turn.user?.id ?? `assistant-turn-${turnIndex}`;
12248
- const isLast = turnIndex === turns.length - 1;
12249
- return /* @__PURE__ */ jsx(ConversationTurnView, {
12250
- turn,
12251
- state: {
12252
- isLast,
12253
- isStreaming: isLast && isStreaming,
12254
- suppressQuestionTool
12255
- },
12256
- rendering: {
12257
- toolRenderers,
12258
- onOpenUIAction,
12259
- onOpenUIArtifactReady,
12260
- onOpenArtifact
10971
+ children: [
10972
+ /* @__PURE__ */ jsxs(MessageScroller, {
10973
+ className: "flex-1",
10974
+ busy: isStreaming,
10975
+ followOutput: true,
10976
+ smooth: isStreaming,
10977
+ 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"),
10978
+ children: [
10979
+ isEmpty ? /* @__PURE__ */ jsx(WelcomeState, {
10980
+ disabled: isStreaming,
10981
+ onSelect: (item) => setDraft(item.value ?? item.label),
10982
+ composer: inputBarNode
10983
+ }) : null,
10984
+ turns.map((turn, turnIndex) => {
10985
+ const key = turn.user?.id ?? `assistant-turn-${turnIndex}`;
10986
+ const isLast = turnIndex === turns.length - 1;
10987
+ return /* @__PURE__ */ jsx(ConversationTurnView, {
10988
+ turn,
10989
+ state: isLast ? stateForLast : stateForRest,
10990
+ rendering,
10991
+ activity: isLast ? activityForLast : activityForRest
10992
+ }, key);
10993
+ }),
10994
+ errorPresentation ? /* @__PURE__ */ jsxs("div", {
10995
+ role: "alert",
10996
+ className: "flex items-start gap-2 rounded-xl border border-destructive/30 bg-destructive/10 p-3 text-sm text-destructive",
10997
+ children: [/* @__PURE__ */ jsx(CircleAlert, { className: "mt-0.5 size-4 shrink-0" }), /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("p", {
10998
+ className: "font-medium",
10999
+ children: errorPresentation.title
11000
+ }), /* @__PURE__ */ jsx("p", {
11001
+ className: "mt-1 text-xs opacity-90",
11002
+ children: errorPresentation.message
11003
+ })] })]
11004
+ }) : null,
11005
+ turns.length > 0 && suggestionTexts.length > 0 && !isStreaming && !error ? /* @__PURE__ */ jsx(PromptSuggestions, {
11006
+ suggestions: suggestionTexts,
11007
+ selectedSuggestion,
11008
+ cycle: turns.length,
11009
+ onSuggestion: (suggestion) => {
11010
+ setSelectedSuggestion(suggestion);
11011
+ setDraft(suggestion);
12261
11012
  },
12262
- activity: {
12263
- label: isLast ? activityLabel : void 0,
12264
- presentation: isLast ? presentation : void 0,
12265
- artifactRuns: isLast ? artifactRuns : void 0
12266
- }
12267
- }, key);
12268
- }),
12269
- errorPresentation ? /* @__PURE__ */ jsxs("div", {
12270
- role: "alert",
12271
- className: "flex items-start gap-2 rounded-xl border border-destructive/30 bg-destructive/10 p-3 text-sm text-destructive",
12272
- children: [/* @__PURE__ */ jsx(CircleAlert, { className: "mt-0.5 size-4 shrink-0" }), /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("p", {
12273
- className: "font-medium",
12274
- children: errorPresentation.title
12275
- }), /* @__PURE__ */ jsx("p", {
12276
- className: "mt-1 text-xs opacity-90",
12277
- children: errorPresentation.message
12278
- })] })]
12279
- }) : null,
12280
- turns.length > 0 && suggestionTexts.length > 0 && !isStreaming && !error ? /* @__PURE__ */ jsx(PromptSuggestions, {
12281
- suggestions: suggestionTexts,
12282
- selectedSuggestion,
12283
- cycle: turns.length,
12284
- onSuggestion: (suggestion) => {
12285
- setSelectedSuggestion(suggestion);
12286
- setDraft(suggestion);
12287
- },
12288
- className: "px-0"
12289
- }) : null
12290
- ]
12291
- }), !isEmpty ? inputBarNode : null]
11013
+ className: "px-0"
11014
+ }) : null
11015
+ ]
11016
+ }),
11017
+ !isEmpty ? inputBarNode : null,
11018
+ /* @__PURE__ */ jsx(FleetMessageQueue, {
11019
+ queue: queue ?? {
11020
+ steering: [],
11021
+ followUp: []
11022
+ },
11023
+ onDelete: onDeleteQueuedMessage
11024
+ })
11025
+ ]
12292
11026
  });
12293
11027
  }
12294
- function ChatPanel({ messages, status, error, workspaceName, activityLabel, presentation, artifactRuns, onOpenArtifact, onOpenUIArtifactReady, inputSuggestionItems, suppressQuestionTool, inputBar, onSend, onOpenUIAction, onStop, onQuestionAnswer }) {
11028
+ function ChatPanel({ messages, status, error, workspaceName, activityLabel, presentation, artifactRuns, queue, onDeleteQueuedMessage, onOpenArtifact, onOpenUIArtifactReady, inputSuggestionItems, suppressQuestionTool, inputBar, onSend, onOpenUIAction, onStop, onQuestionAnswer }) {
12295
11029
  const handleSend = useCallback2((msg) => {
12296
11030
  onSend(msg.content, msg.altKey);
12297
11031
  }, [onSend]);
@@ -12322,6 +11056,8 @@ function ChatPanel({ messages, status, error, workspaceName, activityLabel, pres
12322
11056
  activityLabel,
12323
11057
  presentation,
12324
11058
  artifactRuns,
11059
+ queue,
11060
+ onDeleteQueuedMessage,
12325
11061
  onOpenArtifact,
12326
11062
  onOpenUIArtifactReady,
12327
11063
  questionTool,
@@ -12352,6 +11088,187 @@ function resolveChatApiUrl(path) {
12352
11088
  if (!isChatRuntimePath(pathname)) return path;
12353
11089
  return `${base}${path}`;
12354
11090
  }
11091
+ function buildChatInputBarProps(composer, activeSessionId) {
11092
+ return {
11093
+ modelKey: composer.modelKey,
11094
+ models: composer.models,
11095
+ infoDescription: composer.infoDescription,
11096
+ slashCommands: composer.slashCommands,
11097
+ questionBar: composer.pendingQuestionBar,
11098
+ chatMode: composer.chatMode,
11099
+ onChatModeChange: composer.setChatMode,
11100
+ onModelChange: composer.setModelKey,
11101
+ thinkingLevel: composer.thinkingLevel,
11102
+ onThinkingLevelChange: composer.setThinkingLevel,
11103
+ attachments: {
11104
+ onAttach: composer.handleAttach,
11105
+ images: composer.uploadedAttachments.flatMap((attachment) => attachment.mimeType.startsWith("image/") ? [{
11106
+ id: attachment.attachmentId,
11107
+ filename: attachment.name,
11108
+ size: attachment.size,
11109
+ url: resolveChatApiUrl(`/api/chat/session?sessionId=${encodeURIComponent(activeSessionId ?? "")}&attachmentId=${encodeURIComponent(attachment.attachmentId)}`)
11110
+ }] : []),
11111
+ files: composer.uploadedAttachments.flatMap((attachment) => attachment.mimeType.startsWith("image/") ? [] : [{
11112
+ id: attachment.attachmentId,
11113
+ filename: attachment.name,
11114
+ size: attachment.size
11115
+ }]),
11116
+ onRemoveImage: composer.removeUploadedAttachment,
11117
+ onRemoveFile: composer.removeUploadedAttachment
11118
+ },
11119
+ workspaceReferences: composer.workspaceAttachments,
11120
+ workspaceSuggestions: composer.workspaceReferenceSuggestions,
11121
+ onWorkspaceReferenceSelect: composer.addWorkspaceAttachment,
11122
+ onRemoveWorkspaceReference: composer.removeWorkspaceAttachment,
11123
+ onSlashCommandSelect: composer.handleSlashCommandSelect,
11124
+ onLocalSlashSubmit: composer.handleLocalSlashSubmit,
11125
+ modelPickerOpen: composer.modelPickerOpen,
11126
+ onModelPickerOpenChange: composer.setModelPickerOpen,
11127
+ effortPickerOpen: composer.effortPickerOpen,
11128
+ onEffortPickerOpenChange: composer.setEffortPickerOpen
11129
+ };
11130
+ }
11131
+ var LazyChatCommandPalette = lazy(() => import("./chat-command-palette-BaenPkCN-BHSOPGU4.js").then(({ ChatCommandPalette }) => ({ default: ChatCommandPalette })));
11132
+ var LazySettingsDialog = lazy(() => import("./settings-dialog-DgeBMORv-7SRSENPM.js").then(({ SettingsDialog }) => ({ default: SettingsDialog })));
11133
+ var LazyForkPickerDialog = lazy(() => import("./fork-picker-dialog-BZzfxdQd-Y725VJ7G.js").then(({ ForkPickerDialog }) => ({ default: ForkPickerDialog })));
11134
+ function ChatCommandPaletteOverlay({ chrome, conversation, dialogs, panels, session }) {
11135
+ return /* @__PURE__ */ jsx(Fragment$1, { children: dialogs.commandPaletteOpen ? /* @__PURE__ */ jsx(Suspense, {
11136
+ fallback: null,
11137
+ children: /* @__PURE__ */ jsx(LazyChatCommandPalette, {
11138
+ open: true,
11139
+ onOpenChange: dialogs.setCommandPaletteOpen,
11140
+ onNewSession: () => void session.startNewSession(),
11141
+ onStop: conversation.stop,
11142
+ onResumeSession: (sessionToResume) => void session.resumeSession({ sessionId: sessionToResume.sessionId }),
11143
+ onSetRightPanel: panels.setRightPanel,
11144
+ onThemeChange: chrome.handleThemePreferenceChange,
11145
+ sessions: session.sessions,
11146
+ isStreaming: conversation.status === "streaming",
11147
+ themePreference: chrome.themePreference
11148
+ })
11149
+ }) : null });
11150
+ }
11151
+ function ChatWorkspaceOverlayDialogs({ dialogs }) {
11152
+ const { forkFromEntry, forkPickerEntries, setForkPickerEntries, setSettingsDialogOpen, setSettingsInitialTab, settingsDialogOpen, settingsInitialTab } = dialogs;
11153
+ const handleSettingsOpenChange = useCallback2((open) => {
11154
+ setSettingsDialogOpen(open);
11155
+ if (!open) setSettingsInitialTab(void 0);
11156
+ }, [setSettingsDialogOpen, setSettingsInitialTab]);
11157
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [settingsDialogOpen ? /* @__PURE__ */ jsx(Suspense, {
11158
+ fallback: null,
11159
+ children: /* @__PURE__ */ jsx(LazySettingsDialog, {
11160
+ open: true,
11161
+ onOpenChange: handleSettingsOpenChange,
11162
+ initialTab: settingsInitialTab
11163
+ })
11164
+ }) : null, forkPickerEntries ? /* @__PURE__ */ jsx(Suspense, {
11165
+ fallback: null,
11166
+ children: /* @__PURE__ */ jsx(LazyForkPickerDialog, {
11167
+ entries: forkPickerEntries,
11168
+ onOpenChange: (open) => {
11169
+ if (!open) setForkPickerEntries(null);
11170
+ },
11171
+ onPick: forkFromEntry
11172
+ })
11173
+ }) : null] });
11174
+ }
11175
+ var FLEET_PANEL_KEYBINDINGS_STORAGE_KEY = "fleet-prime:v1:panel-keybindings";
11176
+ var DEFAULT_FLEET_PANEL_KEYBINDINGS = {
11177
+ toggleResources: {
11178
+ code: "Digit1",
11179
+ ctrlOrMeta: true,
11180
+ shift: true
11181
+ },
11182
+ toggleWorkspace: {
11183
+ code: "Digit2",
11184
+ ctrlOrMeta: true,
11185
+ shift: true
11186
+ },
11187
+ toggleArtifacts: {
11188
+ code: "Digit3",
11189
+ ctrlOrMeta: true,
11190
+ shift: true
11191
+ },
11192
+ toggleRepl: {
11193
+ code: "Digit4",
11194
+ ctrlOrMeta: true,
11195
+ shift: true
11196
+ },
11197
+ toggleSubagents: {
11198
+ code: "Digit5",
11199
+ ctrlOrMeta: true,
11200
+ shift: true
11201
+ },
11202
+ toggleCommandPalette: {
11203
+ code: "KeyK",
11204
+ ctrlOrMeta: true
11205
+ },
11206
+ closePanel: { code: "Escape" },
11207
+ focusPanel: {
11208
+ code: "KeyP",
11209
+ ctrlOrMeta: true,
11210
+ shift: true
11211
+ },
11212
+ focusChat: {
11213
+ code: "KeyC",
11214
+ ctrlOrMeta: true,
11215
+ shift: true
11216
+ }
11217
+ };
11218
+ function readKeybindings() {
11219
+ try {
11220
+ const value = window.localStorage.getItem(FLEET_PANEL_KEYBINDINGS_STORAGE_KEY);
11221
+ if (!value) return DEFAULT_FLEET_PANEL_KEYBINDINGS;
11222
+ const overrides = JSON.parse(value);
11223
+ return {
11224
+ ...DEFAULT_FLEET_PANEL_KEYBINDINGS,
11225
+ ...overrides
11226
+ };
11227
+ } catch {
11228
+ return DEFAULT_FLEET_PANEL_KEYBINDINGS;
11229
+ }
11230
+ }
11231
+ function matches(event, binding) {
11232
+ return event.code === binding.code && (event.ctrlKey || event.metaKey) === Boolean(binding.ctrlOrMeta) && event.shiftKey === Boolean(binding.shift) && event.altKey === Boolean(binding.alt);
11233
+ }
11234
+ function focusChatComposer() {
11235
+ document.querySelector("[data-fleet-chat-focus] textarea, [data-fleet-chat-focus] [contenteditable='true'], [data-fleet-chat-focus] input")?.focus({ preventScroll: true });
11236
+ }
11237
+ function usePanelKeybindings({ onCommandPaletteToggle, onClosePanel, rightPanel, setRightPanel }) {
11238
+ useEffect2(() => {
11239
+ const keybindings = readKeybindings();
11240
+ const handleKeyDown = (event) => {
11241
+ const match = (action) => matches(event, keybindings[action]);
11242
+ let handled = true;
11243
+ if (match("toggleResources")) setRightPanel(rightPanel === "resources" ? null : "resources");
11244
+ else if (match("toggleWorkspace")) setRightPanel(rightPanel === "workspace" ? null : "workspace");
11245
+ else if (match("toggleArtifacts")) setRightPanel(rightPanel === "artifacts" ? null : "artifacts");
11246
+ else if (match("toggleRepl")) setRightPanel(rightPanel === "repl" ? null : "repl");
11247
+ else if (match("toggleSubagents")) setRightPanel(rightPanel === "subagents" ? null : "subagents");
11248
+ else if (onCommandPaletteToggle && match("toggleCommandPalette")) onCommandPaletteToggle();
11249
+ else if (rightPanel && match("closePanel")) {
11250
+ if (onClosePanel) onClosePanel();
11251
+ else {
11252
+ setRightPanel(null);
11253
+ focusChatComposer();
11254
+ }
11255
+ } else if (rightPanel && match("focusPanel")) document.querySelector("[data-fleet-panel-focus]")?.focus({ preventScroll: true });
11256
+ else if (match("focusChat")) focusChatComposer();
11257
+ else handled = false;
11258
+ if (handled) {
11259
+ event.preventDefault();
11260
+ event.stopPropagation();
11261
+ }
11262
+ };
11263
+ document.addEventListener("keydown", handleKeyDown);
11264
+ return () => document.removeEventListener("keydown", handleKeyDown);
11265
+ }, [
11266
+ onCommandPaletteToggle,
11267
+ onClosePanel,
11268
+ rightPanel,
11269
+ setRightPanel
11270
+ ]);
11271
+ }
12355
11272
  function useOptionalUser() {
12356
11273
  return null;
12357
11274
  }
@@ -12538,6 +11455,14 @@ var chatClient = {
12538
11455
  body: JSON.stringify(request)
12539
11456
  });
12540
11457
  },
11458
+ async deleteQueuedMessage(request) {
11459
+ const body = ChatQueueMutationRequestSchema.parse(request);
11460
+ return fetchValidatedJson("/api/chat/session", ChatQueueMutationResponseSchema, {
11461
+ method: "PATCH",
11462
+ headers: { "Content-Type": "application/json" },
11463
+ body: JSON.stringify(body)
11464
+ });
11465
+ },
12541
11466
  async browseWorkspace(path, projectId) {
12542
11467
  const params = new URLSearchParams();
12543
11468
  if (projectId) params.set("projectId", projectId);
@@ -12664,6 +11589,12 @@ var chatClient = {
12664
11589
  openUI: true
12665
11590
  })}`, ChatSessionResponseSchema);
12666
11591
  },
11592
+ async loadSubagentSession(parentSessionId, childId) {
11593
+ return fetchValidatedJson(`/api/chat/session?${new URLSearchParams({
11594
+ parentSessionId,
11595
+ childId
11596
+ })}`, ChatSessionResponseSchema);
11597
+ },
12667
11598
  async upsertPlanPresentation(request) {
12668
11599
  const body = ChatPlanPresentationUpsertRequestSchema.parse(request);
12669
11600
  return fetchValidatedJson("/api/chat/session", external_exports.object({ presentation: ChatPlanPresentationSchema }), {
@@ -13448,9 +12379,9 @@ function useChatShellState(modelsData, storage) {
13448
12379
  return null;
13449
12380
  });
13450
12381
  }, []);
13451
- const openArtifact = useCallback2((artifactId) => {
12382
+ const openArtifact = useCallback2((artifactId, target = "artifacts") => {
13452
12383
  setSelectedArtifactId(artifactId);
13453
- setRightPanel("artifacts");
12384
+ setRightPanel(target);
13454
12385
  }, [setRightPanel]);
13455
12386
  const openWorkspacePath = useCallback2((rawPath) => {
13456
12387
  const target = resolveWorkspacePanelTarget(rawPath);
@@ -13459,8 +12390,9 @@ function useChatShellState(modelsData, storage) {
13459
12390
  setSelectedWorkspacePath(target.path);
13460
12391
  }, [setRightPanel]);
13461
12392
  const openPanelAction = useCallback2((action) => {
13462
- const isLocationPanel = action.panel === "workspace" || action.panel === "artifacts";
13463
- setRightPanel(action.panel);
12393
+ const panel = action.panel === "artifacts" && action.relativePath ? "workspace" : action.panel;
12394
+ const isLocationPanel = panel === "workspace" || panel === "artifacts";
12395
+ setRightPanel(panel);
13464
12396
  setSelectedWorkspacePath(isLocationPanel ? action.relativePath ?? null : null);
13465
12397
  if (action.focus) window.requestAnimationFrame(() => {
13466
12398
  document.querySelector("[data-fleet-panel-focus]")?.focus({ preventScroll: true });
@@ -15460,6 +14392,8 @@ function usePiChat(model, options) {
15460
14392
  const activityLabelRef = useRef2(activityLabel);
15461
14393
  const planLabelRef = useRef2(planLabel);
15462
14394
  const queueRef = useRef2(queue);
14395
+ const queueRevisionRef = useRef2(0);
14396
+ const queuedDeletionTailRef = useRef2(Promise.resolve());
15463
14397
  const presentationRef = useRef2(presentation);
15464
14398
  const pendingSendControllerRef = useRef2(null);
15465
14399
  const streamControllersRef = useRef2(/* @__PURE__ */ new Map());
@@ -15487,6 +14421,7 @@ function usePiChat(model, options) {
15487
14421
  const current = sessionMetadataRef.current;
15488
14422
  const next = normalizeSessionMetadata(metadata);
15489
14423
  if (current.sessionId === next.sessionId && current.projectId === next.projectId) return;
14424
+ queueRevisionRef.current += 1;
15490
14425
  sessionMetadataRef.current = next;
15491
14426
  setSessionMetadata(next);
15492
14427
  persistSession(next);
@@ -15500,9 +14435,13 @@ function usePiChat(model, options) {
15500
14435
  setPlanLabel(nextLabel);
15501
14436
  }, []);
15502
14437
  const setQueueSynced = useCallback2((nextQueue) => {
14438
+ queueRevisionRef.current += 1;
15503
14439
  queueRef.current = nextQueue;
15504
14440
  setQueue(nextQueue);
15505
14441
  }, []);
14442
+ const invalidateQueueMutations = useCallback2(() => {
14443
+ queueRevisionRef.current += 1;
14444
+ }, []);
15506
14445
  const setPresentationSynced = useCallback2((nextPresentation) => {
15507
14446
  presentationRef.current = nextPresentation;
15508
14447
  setPresentation(nextPresentation);
@@ -15736,18 +14675,66 @@ function usePiChat(model, options) {
15736
14675
  streamControllersRef.current.get(metadata.sessionId)?.abort();
15737
14676
  streamControllersRef.current.delete(metadata.sessionId);
15738
14677
  }
14678
+ invalidateQueueMutations();
15739
14679
  setStatus("ready");
15740
14680
  setQueueSynced(EMPTY_QUEUE_STATE);
15741
14681
  setActivityLabelSynced(void 0);
15742
14682
  }, [
15743
14683
  client,
14684
+ invalidateQueueMutations,
15744
14685
  resetStreamAdmission,
15745
14686
  setActivityLabelSynced,
15746
14687
  setQueueSynced
15747
14688
  ]);
14689
+ const deleteQueuedMessage = useCallback2((lane, index, expectedText) => {
14690
+ const originatingSessionId = sessionMetadataRef.current.sessionId;
14691
+ const requestedRevision = queueRevisionRef.current;
14692
+ const requestedMatchCount = (lane === "steering" ? queueRef.current.steering : queueRef.current.followUp).filter((item) => item === expectedText).length;
14693
+ const deletion = queuedDeletionTailRef.current.catch(() => void 0).then(async () => {
14694
+ if (!originatingSessionId || sessionMetadataRef.current.sessionId !== originatingSessionId) return false;
14695
+ const current = queueRef.current;
14696
+ const items = lane === "steering" ? current.steering : current.followUp;
14697
+ let resolvedIndex;
14698
+ if (queueRevisionRef.current === requestedRevision) resolvedIndex = items[index] === expectedText ? index : void 0;
14699
+ else {
14700
+ if (requestedMatchCount !== 1) return false;
14701
+ const currentMatches = items.reduce((matches2, item, itemIndex) => {
14702
+ if (item === expectedText) matches2.push(itemIndex);
14703
+ return matches2;
14704
+ }, []);
14705
+ resolvedIndex = currentMatches.length === 1 ? currentMatches[0] : void 0;
14706
+ }
14707
+ if (resolvedIndex === void 0) return false;
14708
+ const optimistic = {
14709
+ ...current,
14710
+ [lane]: items.filter((_, itemIndex) => itemIndex !== resolvedIndex)
14711
+ };
14712
+ setQueueSynced(optimistic);
14713
+ const requestRevision = queueRevisionRef.current;
14714
+ try {
14715
+ const result = await client.deleteQueuedMessage({
14716
+ sessionId: originatingSessionId,
14717
+ lane,
14718
+ index: resolvedIndex,
14719
+ expectedText
14720
+ });
14721
+ if (sessionMetadataRef.current.sessionId !== originatingSessionId || queueRevisionRef.current !== requestRevision) return result.status === "applied";
14722
+ setQueueSynced(result.queue);
14723
+ return result.status === "applied";
14724
+ } catch (queueError) {
14725
+ if (sessionMetadataRef.current.sessionId === originatingSessionId && queueRevisionRef.current === requestRevision && queueRef.current === optimistic) setQueueSynced(current);
14726
+ throw queueError;
14727
+ }
14728
+ });
14729
+ queuedDeletionTailRef.current = deletion.then(() => void 0, () => void 0);
14730
+ return deletion;
14731
+ }, [client, setQueueSynced]);
15748
14732
  const startNewSession = useCallback2(async (options2) => {
15749
14733
  if (options2?.preserveRunning === false) stop();
15750
- else setStatus("ready");
14734
+ else {
14735
+ invalidateQueueMutations();
14736
+ setStatus("ready");
14737
+ }
15751
14738
  const result = await client.createSession(options2?.projectId ?? projectId);
15752
14739
  setSessionMetadataSynced(result.session);
15753
14740
  setMessagesSynced([]);
@@ -15766,10 +14753,12 @@ function usePiChat(model, options) {
15766
14753
  setPlanLabelSynced,
15767
14754
  setQueueSynced,
15768
14755
  setSessionMetadataSynced,
14756
+ invalidateQueueMutations,
15769
14757
  stop,
15770
14758
  projectId
15771
14759
  ]);
15772
14760
  const resumeSession = useCallback2(async (metadata, options2) => {
14761
+ invalidateQueueMutations();
15773
14762
  try {
15774
14763
  if (options2?.preserveRunning === false) stop();
15775
14764
  const result = await client.resumeSession(metadata);
@@ -15805,6 +14794,7 @@ function usePiChat(model, options) {
15805
14794
  setPlanLabelSynced,
15806
14795
  setQueueSynced,
15807
14796
  setSessionMetadataSynced,
14797
+ invalidateQueueMutations,
15808
14798
  stop
15809
14799
  ]);
15810
14800
  const switchProject = useCallback2(async (nextProjectId, nextSessionId) => {
@@ -15812,6 +14802,7 @@ function usePiChat(model, options) {
15812
14802
  sessionId: nextSessionId,
15813
14803
  projectId: nextProjectId
15814
14804
  }, { preserveRunning: true });
14805
+ invalidateQueueMutations();
15815
14806
  setSessionMetadataSynced({ projectId: nextProjectId });
15816
14807
  setMessagesSynced([]);
15817
14808
  setPresentationSynced({
@@ -15833,7 +14824,8 @@ function usePiChat(model, options) {
15833
14824
  setPlanLabelSynced,
15834
14825
  setPresentationSynced,
15835
14826
  setQueueSynced,
15836
- setSessionMetadataSynced
14827
+ setSessionMetadataSynced,
14828
+ invalidateQueueMutations
15837
14829
  ]);
15838
14830
  useEffect2(() => {
15839
14831
  sendMessageRef.current = sendMessage;
@@ -15986,6 +14978,7 @@ function usePiChat(model, options) {
15986
14978
  activityLabel,
15987
14979
  answerQuestion,
15988
14980
  appendLocalMessage,
14981
+ deleteQueuedMessage,
15989
14982
  deleteSession,
15990
14983
  error,
15991
14984
  getMessages: useCallback2(() => messagesRef.current, []),
@@ -16008,11 +15001,13 @@ function usePiChat(model, options) {
16008
15001
  switchProject
16009
15002
  };
16010
15003
  }
16011
- function useRightPanelContextValue({ activityLabel, artifactRuns, chatMode, handleThemePreferenceChange, isLoadingProviders, isUpdatingProvider, loadWorkspaceFile: loadWorkspaceFile2, messages, modelKey, models, modelCatalog, onDiscoverModels, onOAuthLogin, onRemoveProvider, onUpdateProvider, openWorkspacePath, planLabel, presentation, providers, queue, refreshResources, refreshWorkspace, resources, resourcesError, resourcesLoading, rightPanel, reopenRightPanel, saveSettings, selectedArtifactId, sessionId, selectedWorkspacePath, setRightPanel, setSelectedWorkspacePath, settings, settingsError, settingsLoading, status, thinkingLevel, themePreference, workspaceError, workspaceLoading, workspaceTree }) {
15004
+ function useRightPanelContextValue({ activityLabel, artifactRuns, chatMode, handleThemePreferenceChange, isLoadingProviders, isUpdatingProvider, loadSession, loadSubagentSession, loadWorkspaceFile: loadWorkspaceFile2, messages, modelKey, models, modelCatalog, onDiscoverModels, onOAuthLogin, onRemoveProvider, onUpdateProvider, openWorkspacePath, planLabel, presentation, providers, queue, refreshResources, refreshWorkspace, resources, resourcesError, resourcesLoading, rightPanel, reopenRightPanel, saveSettings, selectedArtifactId, sessionId, selectedWorkspacePath, setRightPanel, setSelectedWorkspacePath, settings, settingsError, settingsLoading, status, thinkingLevel, themePreference, workspaceError, workspaceLoading, workspaceTree }) {
16012
15005
  const chatPanelData = useMemo2(() => ({
16013
15006
  activityLabel,
16014
15007
  artifactRuns,
16015
15008
  chatMode,
15009
+ loadSession,
15010
+ loadSubagentSession,
16016
15011
  messages,
16017
15012
  models,
16018
15013
  planLabel,
@@ -16034,6 +15029,8 @@ function useRightPanelContextValue({ activityLabel, artifactRuns, chatMode, hand
16034
15029
  activityLabel,
16035
15030
  artifactRuns,
16036
15031
  chatMode,
15032
+ loadSession,
15033
+ loadSubagentSession,
16037
15034
  messages,
16038
15035
  models,
16039
15036
  planLabel,
@@ -16214,7 +15211,7 @@ function useChatWorkspaceData() {
16214
15211
  const refreshWorkspace = useCallback2(() => {
16215
15212
  refetchWorkspace();
16216
15213
  }, [refetchWorkspace]);
16217
- const { activityLabel, answerQuestion, appendLocalMessage, deleteSession, error, getMessages, getSessionMetadata, messages, planLabel, persistOpenUIArtifact, presentation, queue, renameSession, resumeSession, sendMessage, sessionMetadata, sessions, startNewSession, switchProject, status, stop } = usePiChat(modelSelection, {
15214
+ const { activityLabel, answerQuestion, appendLocalMessage, deleteQueuedMessage, deleteSession, error, getMessages, getSessionMetadata, messages, planLabel, persistOpenUIArtifact, presentation, queue, renameSession, resumeSession, sendMessage, sessionMetadata, sessions, startNewSession, switchProject, status, stop } = usePiChat(modelSelection, {
16218
15215
  initialSessionMetadata,
16219
15216
  projectId: activeProjectId,
16220
15217
  persistSession
@@ -16433,6 +15430,17 @@ function useChatWorkspaceData() {
16433
15430
  }
16434
15431
  openPanelAction(action);
16435
15432
  }, [activeProjectId, openPanelAction]);
15433
+ const openSidebarPanelAction = useCallback2((action) => {
15434
+ if (!action.projectId || action.projectId === activeProjectId) {
15435
+ openPanelAction(action);
15436
+ return;
15437
+ }
15438
+ selectProject(action.projectId).then(() => openPanelAction(action)).catch((error2) => notifyChatError(error2));
15439
+ }, [
15440
+ activeProjectId,
15441
+ openPanelAction,
15442
+ selectProject
15443
+ ]);
16436
15444
  const openSettings = useCallback2((tab) => {
16437
15445
  setSettingsInitialTab(tab);
16438
15446
  setSettingsDialogOpen(true);
@@ -16475,6 +15483,8 @@ function useChatWorkspaceData() {
16475
15483
  });
16476
15484
  const modelCatalog = useMemo2(() => modelCatalogData?.models.map(toModelOption) ?? models, [modelCatalogData, models]);
16477
15485
  const loadProjectWorkspaceFile = useCallback2((path) => loadWorkspaceFile(path, activeProjectId), [activeProjectId]);
15486
+ const loadChatSession = useCallback2((metadata) => chatClient.loadSession(metadata), []);
15487
+ const loadSubagentSession = useCallback2((parentSessionId, childId) => chatClient.loadSubagentSession(parentSessionId, childId), []);
16478
15488
  const onDiscoverModels = useCallback2(async (providerId) => {
16479
15489
  return (await discoverModelsMutation.mutateAsync(providerId)).models.map(toModelOption);
16480
15490
  }, [discoverModelsMutation]);
@@ -16485,6 +15495,8 @@ function useChatWorkspaceData() {
16485
15495
  handleThemePreferenceChange,
16486
15496
  isLoadingProviders,
16487
15497
  isUpdatingProvider: isUpdatingProvider || isRemovingProvider,
15498
+ loadSession: loadChatSession,
15499
+ loadSubagentSession,
16488
15500
  loadWorkspaceFile: loadProjectWorkspaceFile,
16489
15501
  messages,
16490
15502
  modelKey,
@@ -16534,6 +15546,7 @@ function useChatWorkspaceData() {
16534
15546
  session: {
16535
15547
  activeSessionId: sessionMetadata.sessionId,
16536
15548
  activeProjectId,
15549
+ openPanelAction: openSidebarPanelAction,
16537
15550
  projects: projectsData?.projects ?? [],
16538
15551
  projectSessions: sessions,
16539
15552
  sessions,
@@ -16552,12 +15565,14 @@ function useChatWorkspaceData() {
16552
15565
  conversation: {
16553
15566
  activityLabel,
16554
15567
  artifactRuns,
15568
+ deleteQueuedMessage,
16555
15569
  error,
16556
15570
  messages,
16557
15571
  openArtifact,
16558
15572
  openPanelAction: openProjectPanelAction,
16559
15573
  persistOpenUIArtifact,
16560
15574
  presentation,
15575
+ queue,
16561
15576
  sendMessage,
16562
15577
  status,
16563
15578
  stop
@@ -16619,287 +15634,144 @@ function useChatWorkspaceData() {
16619
15634
  }
16620
15635
  };
16621
15636
  }
16622
- var FLEET_PANEL_KEYBINDINGS_STORAGE_KEY = "fleet-prime:v1:panel-keybindings";
16623
- var DEFAULT_FLEET_PANEL_KEYBINDINGS = {
16624
- toggleResources: {
16625
- code: "Digit1",
16626
- ctrlOrMeta: true,
16627
- shift: true
16628
- },
16629
- toggleWorkspace: {
16630
- code: "Digit2",
16631
- ctrlOrMeta: true,
16632
- shift: true
16633
- },
16634
- toggleArtifacts: {
16635
- code: "Digit3",
16636
- ctrlOrMeta: true,
16637
- shift: true
16638
- },
16639
- closePanel: { code: "Escape" },
16640
- focusPanel: {
16641
- code: "KeyP",
16642
- ctrlOrMeta: true,
16643
- shift: true
16644
- },
16645
- focusChat: {
16646
- code: "KeyC",
16647
- ctrlOrMeta: true,
16648
- shift: true
16649
- }
16650
- };
16651
- function readKeybindings() {
16652
- try {
16653
- const value = window.localStorage.getItem(FLEET_PANEL_KEYBINDINGS_STORAGE_KEY);
16654
- if (!value) return DEFAULT_FLEET_PANEL_KEYBINDINGS;
16655
- const overrides = JSON.parse(value);
16656
- return {
16657
- ...DEFAULT_FLEET_PANEL_KEYBINDINGS,
16658
- ...overrides
16659
- };
16660
- } catch {
16661
- return DEFAULT_FLEET_PANEL_KEYBINDINGS;
16662
- }
16663
- }
16664
- function matches(event, binding) {
16665
- return event.code === binding.code && (event.ctrlKey || event.metaKey) === Boolean(binding.ctrlOrMeta) && event.shiftKey === Boolean(binding.shift) && event.altKey === Boolean(binding.alt);
16666
- }
16667
- function focusChatComposer() {
16668
- document.querySelector("[data-fleet-chat-focus] textarea, [data-fleet-chat-focus] [contenteditable='true'], [data-fleet-chat-focus] input")?.focus({ preventScroll: true });
16669
- }
16670
- function usePanelKeybindings({ rightPanel, setRightPanel }) {
16671
- useEffect2(() => {
16672
- const keybindings = readKeybindings();
16673
- const handleKeyDown = (event) => {
16674
- const match = (action) => matches(event, keybindings[action]);
16675
- let handled = true;
16676
- if (match("toggleResources")) setRightPanel(rightPanel === "resources" ? null : "resources");
16677
- else if (match("toggleWorkspace")) setRightPanel(rightPanel === "workspace" ? null : "workspace");
16678
- else if (match("toggleArtifacts")) setRightPanel(rightPanel === "artifacts" ? null : "artifacts");
16679
- else if (rightPanel && match("closePanel")) {
16680
- setRightPanel(null);
16681
- focusChatComposer();
16682
- } else if (rightPanel && match("focusPanel")) document.querySelector("[data-fleet-panel-focus]")?.focus({ preventScroll: true });
16683
- else if (match("focusChat")) focusChatComposer();
16684
- else handled = false;
16685
- if (handled) {
16686
- event.preventDefault();
16687
- event.stopPropagation();
16688
- }
16689
- };
16690
- document.addEventListener("keydown", handleKeyDown);
16691
- return () => document.removeEventListener("keydown", handleKeyDown);
16692
- }, [rightPanel, setRightPanel]);
16693
- }
16694
- var LazyChatCommandPalette = lazy(() => import("./chat-command-palette-CPv5GmGJ-22J32S6P.js").then(({ ChatCommandPalette }) => ({ default: ChatCommandPalette })));
16695
- var LazySettingsDialog = lazy(() => import("./settings-dialog-BTBFLQ1P-ZENQ4KWK.js").then(({ SettingsDialog }) => ({ default: SettingsDialog })));
16696
- var LazyForkPickerDialog = lazy(() => import("./fork-picker-dialog-BZzfxdQd-C6SPHFAW.js").then(({ ForkPickerDialog }) => ({ default: ForkPickerDialog })));
16697
15637
  function ChatWorkspaceShell() {
16698
- const { session: { activeSessionId, browseProjectDirectories, createProject, deleteSession, forkSessionIntoProject, activeProjectId, projects, projectSessions, selectProject, renameProject, unregisterProject, renameSession, resumeSession, sessions, startNewSession, startNewSessionInProject }, conversation: { activityLabel, artifactRuns, error, messages, openArtifact, openPanelAction, persistOpenUIArtifact, presentation, sendMessage, status, stop }, composer: { chatMode, clearUploadedAttachments, clearWorkspaceAttachments, effortPickerOpen, handleLocalSlashSubmit, handleAttach, handleQuestionAnswer, handleSlashCommandSelect, infoDescription, inputSuggestionItems, workspaceReferenceSuggestions, modelKey, modelPickerOpen, models, uploadedAttachments, workspaceAttachments, addWorkspaceAttachment, removeUploadedAttachment, removeWorkspaceAttachment, pendingQuestionBar, setChatMode, setEffortPickerOpen, setModelKey, setModelPickerOpen, setThinkingLevel, slashCommands, thinkingLevel }, panels: { chatPanelData, handleResourceCanvasResizeStart, resourceCanvasWidth, rightPanel, setRightPanel, settingsActions, workspaceTreeContext }, dialogs: { commandPaletteOpen, forkFromEntry, forkPickerEntries, setCommandPaletteOpen, setForkPickerEntries, setSettingsDialogOpen, setSettingsInitialTab, settingsDialogOpen, settingsInitialTab }, chrome: { handleThemePreferenceChange, header, themePreference } } = useChatWorkspaceData();
16699
- const onCommandPaletteKeyDown = useEffectEvent((event) => {
16700
- if ((event.metaKey || event.ctrlKey) && event.key.toLowerCase() === "k") {
16701
- event.preventDefault();
16702
- setCommandPaletteOpen(!commandPaletteOpen);
16703
- }
16704
- });
16705
- useEffect2(() => {
16706
- const handleKeyDown = (event) => onCommandPaletteKeyDown(event);
16707
- window.addEventListener("keydown", handleKeyDown);
16708
- return () => window.removeEventListener("keydown", handleKeyDown);
16709
- }, []);
15638
+ const { session, conversation, composer, panels, dialogs, chrome } = useChatWorkspaceData();
15639
+ const toggleCommandPalette = useCallback2(() => {
15640
+ dialogs.setCommandPaletteOpen((open) => !open);
15641
+ }, [dialogs.setCommandPaletteOpen]);
15642
+ const closeRightPanel = useCallback2(() => {
15643
+ panels.setRightPanel(null);
15644
+ window.requestAnimationFrame(() => focusChatComposer());
15645
+ }, [panels.setRightPanel]);
16710
15646
  usePanelKeybindings({
16711
- rightPanel,
16712
- setRightPanel
15647
+ onCommandPaletteToggle: toggleCommandPalette,
15648
+ onClosePanel: closeRightPanel,
15649
+ rightPanel: panels.rightPanel,
15650
+ setRightPanel: panels.setRightPanel
16713
15651
  });
16714
- const activeProjectName = projects.find((project) => project.projectId === activeProjectId)?.name;
15652
+ const activeProjectName = session.projects.find((project) => project.projectId === session.activeProjectId)?.name;
16715
15653
  const handleSend = useCallback2((text, altKey) => {
16716
- const attachments = [...workspaceAttachments, ...uploadedAttachments];
16717
- clearUploadedAttachments();
16718
- clearWorkspaceAttachments();
15654
+ const attachments = [...composer.workspaceAttachments, ...composer.uploadedAttachments];
15655
+ composer.clearUploadedAttachments();
15656
+ composer.clearWorkspaceAttachments();
16719
15657
  (async () => {
16720
- await sendMessage({
15658
+ await conversation.sendMessage({
16721
15659
  text,
16722
15660
  altKey,
16723
- mode: chatMode,
15661
+ mode: composer.chatMode,
16724
15662
  openUI: true,
16725
15663
  attachments
16726
15664
  });
16727
15665
  })();
16728
15666
  }, [
16729
- chatMode,
16730
- clearUploadedAttachments,
16731
- clearWorkspaceAttachments,
16732
- sendMessage,
16733
- uploadedAttachments,
16734
- workspaceAttachments
15667
+ composer.chatMode,
15668
+ composer.clearUploadedAttachments,
15669
+ composer.clearWorkspaceAttachments,
15670
+ composer.uploadedAttachments,
15671
+ composer.workspaceAttachments,
15672
+ conversation.sendMessage
16735
15673
  ]);
16736
15674
  const handleOpenUIAction = useCallback2((message) => {
16737
15675
  const panelAction = decodeOpenPanelActionMessage(message);
16738
15676
  if (panelAction) {
16739
- openPanelAction(panelAction);
15677
+ conversation.openPanelAction(panelAction);
16740
15678
  return;
16741
15679
  }
16742
- sendMessage({
15680
+ conversation.sendMessage({
16743
15681
  text: message,
16744
15682
  altKey: false,
16745
- mode: chatMode,
15683
+ mode: composer.chatMode,
16746
15684
  openUI: true
16747
15685
  });
16748
15686
  }, [
16749
- chatMode,
16750
- openPanelAction,
16751
- sendMessage
15687
+ composer.chatMode,
15688
+ conversation.openPanelAction,
15689
+ conversation.sendMessage
16752
15690
  ]);
16753
15691
  const handleOpenUIArtifactReady = useCallback2(async (candidate) => {
16754
15692
  try {
16755
- return await persistOpenUIArtifact(candidate);
16756
- } catch (error2) {
16757
- notify.error(`Artifact persistence failed: ${error2 instanceof Error ? error2.message : String(error2)}`);
15693
+ return await conversation.persistOpenUIArtifact(candidate);
15694
+ } catch (error) {
15695
+ notify.error(`Artifact persistence failed: ${error instanceof Error ? error.message : String(error)}`);
16758
15696
  return;
16759
15697
  }
16760
- }, [persistOpenUIArtifact]);
16761
- const handleSettingsOpenChange = useCallback2((open) => {
16762
- setSettingsDialogOpen(open);
16763
- if (!open) setSettingsInitialTab(void 0);
16764
- }, [setSettingsDialogOpen, setSettingsInitialTab]);
16765
- return /* @__PURE__ */ jsxs(Fragment$1, { children: [commandPaletteOpen ? /* @__PURE__ */ jsx(Suspense, {
16766
- fallback: null,
16767
- children: /* @__PURE__ */ jsx(LazyChatCommandPalette, {
16768
- open: true,
16769
- onOpenChange: setCommandPaletteOpen,
16770
- onNewSession: () => void startNewSession(),
16771
- onStop: stop,
16772
- onResumeSession: (session) => void resumeSession({ sessionId: session.sessionId }),
16773
- onSetRightPanel: setRightPanel,
16774
- onThemeChange: handleThemePreferenceChange,
16775
- sessions,
16776
- isStreaming: status === "streaming",
16777
- themePreference
16778
- })
16779
- }) : null, /* @__PURE__ */ jsxs(RightPanelProvider, {
16780
- chatPanelData,
15698
+ }, [conversation.persistOpenUIArtifact]);
15699
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(ChatCommandPaletteOverlay, {
15700
+ chrome,
15701
+ conversation,
15702
+ dialogs,
15703
+ panels,
15704
+ session
15705
+ }), /* @__PURE__ */ jsxs(RightPanelProvider, {
15706
+ chatPanelData: panels.chatPanelData,
16781
15707
  onOpenUIAction: handleOpenUIAction,
16782
- settingsActions,
16783
- workspaceTree: workspaceTreeContext,
16784
- children: [
16785
- /* @__PURE__ */ jsxs(ChatApp, {
16786
- className: "h-svh min-h-0 rounded-none border-0",
16787
- sidebarWidth: "17.5rem",
16788
- children: [/* @__PURE__ */ jsx(FleetSessionSidebar, {
16789
- data: {
16790
- sessions,
16791
- projects,
16792
- projectSessions,
16793
- activeProjectId,
16794
- activeSessionId
16795
- },
16796
- sessionActions: {
16797
- onNewSession: () => void startNewSession(),
16798
- onNewSessionInProject: startNewSessionInProject,
16799
- onResumeSession: (session) => void resumeSession({ sessionId: session.sessionId }),
16800
- onRenameSession: (sessionId, title) => void renameSession(sessionId, title),
16801
- onDeleteSession: (sessionId) => void deleteSession(sessionId)
16802
- },
16803
- projectActions: {
16804
- onProjectSelect: selectProject,
16805
- onCreateProject: createProject,
16806
- onRenameProject: renameProject,
16807
- onUnregisterProject: unregisterProject,
16808
- onForkSessionIntoProject: forkSessionIntoProject
16809
- },
16810
- navigationActions: {
16811
- onOpenPanelAction: openPanelAction,
16812
- onBrowseDirectories: browseProjectDirectories,
16813
- onOpenSettings: () => setSettingsDialogOpen(true)
16814
- },
16815
- slots: { accountMenu: header.accountMenu }
16816
- }), /* @__PURE__ */ jsx(AnimatedSidebarInset, {
16817
- className: "h-svh min-h-0 overflow-hidden",
16818
- children: /* @__PURE__ */ jsx(ChatWorkspaceLayout, {
16819
- headerLeft: header.left,
16820
- headerCenter: header.center,
16821
- headerRight: header.right,
16822
- panel: /* @__PURE__ */ jsx(UiErrorBoundary, { children: /* @__PURE__ */ jsx(RightPanelShell, {
16823
- handleResourceCanvasResizeStart,
16824
- resourceCanvasWidth
16825
- }) }),
16826
- children: /* @__PURE__ */ jsx(ChatPanel, {
16827
- messages,
16828
- status,
16829
- error: error ?? void 0,
16830
- workspaceName: activeProjectName,
16831
- activityLabel,
16832
- presentation,
16833
- artifactRuns,
16834
- onOpenArtifact: openArtifact,
16835
- onOpenUIArtifactReady: handleOpenUIArtifactReady,
16836
- inputSuggestionItems,
16837
- suppressQuestionTool: !!pendingQuestionBar,
16838
- inputBar: {
16839
- modelKey,
16840
- models,
16841
- infoDescription,
16842
- slashCommands,
16843
- questionBar: pendingQuestionBar,
16844
- chatMode,
16845
- onChatModeChange: setChatMode,
16846
- onModelChange: setModelKey,
16847
- thinkingLevel,
16848
- onThinkingLevelChange: setThinkingLevel,
16849
- attachments: {
16850
- onAttach: handleAttach,
16851
- images: uploadedAttachments.flatMap((attachment) => attachment.mimeType.startsWith("image/") ? [{
16852
- id: attachment.attachmentId,
16853
- filename: attachment.name,
16854
- size: attachment.size,
16855
- url: resolveChatApiUrl(`/api/chat/session?sessionId=${encodeURIComponent(activeSessionId ?? "")}&attachmentId=${encodeURIComponent(attachment.attachmentId)}`)
16856
- }] : []),
16857
- files: uploadedAttachments.flatMap((attachment) => attachment.mimeType.startsWith("image/") ? [] : [{
16858
- id: attachment.attachmentId,
16859
- filename: attachment.name,
16860
- size: attachment.size
16861
- }]),
16862
- onRemoveImage: removeUploadedAttachment,
16863
- onRemoveFile: removeUploadedAttachment
16864
- },
16865
- workspaceReferences: workspaceAttachments,
16866
- workspaceSuggestions: workspaceReferenceSuggestions,
16867
- onWorkspaceReferenceSelect: addWorkspaceAttachment,
16868
- onRemoveWorkspaceReference: removeWorkspaceAttachment,
16869
- onSlashCommandSelect: handleSlashCommandSelect,
16870
- onLocalSlashSubmit: handleLocalSlashSubmit,
16871
- modelPickerOpen,
16872
- onModelPickerOpenChange: setModelPickerOpen,
16873
- effortPickerOpen,
16874
- onEffortPickerOpenChange: setEffortPickerOpen
16875
- },
16876
- onSend: handleSend,
16877
- onOpenUIAction: handleOpenUIAction,
16878
- onStop: stop,
16879
- onQuestionAnswer: handleQuestionAnswer
16880
- })
15708
+ settingsActions: panels.settingsActions,
15709
+ workspaceTree: panels.workspaceTreeContext,
15710
+ children: [/* @__PURE__ */ jsxs(ChatApp, {
15711
+ className: "h-svh min-h-0 rounded-none border-0",
15712
+ sidebarWidth: "17.5rem",
15713
+ children: [/* @__PURE__ */ jsx(FleetSessionSidebar, {
15714
+ data: {
15715
+ sessions: session.sessions,
15716
+ projects: session.projects,
15717
+ projectSessions: session.projectSessions,
15718
+ activeProjectId: session.activeProjectId,
15719
+ activeSessionId: session.activeSessionId
15720
+ },
15721
+ sessionActions: {
15722
+ onNewSession: () => void session.startNewSession(),
15723
+ onNewSessionInProject: session.startNewSessionInProject,
15724
+ onResumeSession: (sessionToResume) => void session.resumeSession({ sessionId: sessionToResume.sessionId }),
15725
+ onRenameSession: (sessionId, title) => void session.renameSession(sessionId, title),
15726
+ onDeleteSession: (sessionId) => void session.deleteSession(sessionId)
15727
+ },
15728
+ projectActions: {
15729
+ onProjectSelect: session.selectProject,
15730
+ onCreateProject: session.createProject,
15731
+ onRenameProject: session.renameProject,
15732
+ onUnregisterProject: session.unregisterProject,
15733
+ onForkSessionIntoProject: session.forkSessionIntoProject
15734
+ },
15735
+ navigationActions: {
15736
+ onOpenPanelAction: session.openPanelAction,
15737
+ onBrowseDirectories: session.browseProjectDirectories,
15738
+ onOpenSettings: () => dialogs.setSettingsDialogOpen(true)
15739
+ },
15740
+ slots: { accountMenu: chrome.header.accountMenu }
15741
+ }), /* @__PURE__ */ jsx(AnimatedSidebarInset, {
15742
+ className: "h-svh min-h-0 overflow-hidden",
15743
+ children: /* @__PURE__ */ jsx(ChatWorkspaceLayout, {
15744
+ headerLeft: chrome.header.left,
15745
+ headerCenter: chrome.header.center,
15746
+ headerRight: chrome.header.right,
15747
+ panel: /* @__PURE__ */ jsx(UiErrorBoundary, { children: /* @__PURE__ */ jsx(RightPanelShell, {
15748
+ handleResourceCanvasResizeStart: panels.handleResourceCanvasResizeStart,
15749
+ onClose: closeRightPanel,
15750
+ resourceCanvasWidth: panels.resourceCanvasWidth
15751
+ }) }),
15752
+ children: /* @__PURE__ */ jsx(ChatPanel, {
15753
+ messages: conversation.messages,
15754
+ status: conversation.status,
15755
+ error: conversation.error ?? void 0,
15756
+ workspaceName: activeProjectName,
15757
+ activityLabel: conversation.activityLabel,
15758
+ presentation: conversation.presentation,
15759
+ artifactRuns: conversation.artifactRuns,
15760
+ queue: conversation.queue,
15761
+ onDeleteQueuedMessage: conversation.deleteQueuedMessage,
15762
+ onOpenArtifact: conversation.openArtifact,
15763
+ onOpenUIArtifactReady: handleOpenUIArtifactReady,
15764
+ inputSuggestionItems: composer.inputSuggestionItems,
15765
+ suppressQuestionTool: !!composer.pendingQuestionBar,
15766
+ inputBar: buildChatInputBarProps(composer, session.activeSessionId),
15767
+ onSend: handleSend,
15768
+ onOpenUIAction: handleOpenUIAction,
15769
+ onStop: conversation.stop,
15770
+ onQuestionAnswer: composer.handleQuestionAnswer
16881
15771
  })
16882
- })]
16883
- }),
16884
- settingsDialogOpen ? /* @__PURE__ */ jsx(Suspense, {
16885
- fallback: null,
16886
- children: /* @__PURE__ */ jsx(LazySettingsDialog, {
16887
- open: true,
16888
- onOpenChange: handleSettingsOpenChange,
16889
- initialTab: settingsInitialTab
16890
- })
16891
- }) : null,
16892
- forkPickerEntries ? /* @__PURE__ */ jsx(Suspense, {
16893
- fallback: null,
16894
- children: /* @__PURE__ */ jsx(LazyForkPickerDialog, {
16895
- entries: forkPickerEntries,
16896
- onOpenChange: (open) => {
16897
- if (!open) setForkPickerEntries(null);
16898
- },
16899
- onPick: forkFromEntry
16900
15772
  })
16901
- }) : null
16902
- ]
15773
+ })]
15774
+ }), /* @__PURE__ */ jsx(ChatWorkspaceOverlayDialogs, { dialogs })]
16903
15775
  })] });
16904
15776
  }
16905
15777
  var SplitComponent = ChatWorkspaceShell;