@moldable-ai/ui 0.2.18 → 0.2.20

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 (587) hide show
  1. package/dist/catalog/catalog-manifest.d.ts +6 -0
  2. package/dist/catalog/catalog-manifest.d.ts.map +1 -0
  3. package/dist/catalog/catalog-manifest.js +105 -0
  4. package/dist/catalog/catalog-types.d.ts +54 -0
  5. package/dist/catalog/catalog-types.d.ts.map +1 -0
  6. package/dist/catalog/catalog-types.js +14 -0
  7. package/dist/catalog/component-catalog.d.ts +14 -0
  8. package/dist/catalog/component-catalog.d.ts.map +1 -0
  9. package/dist/catalog/component-catalog.js +39 -0
  10. package/dist/catalog/core-catalog.d.ts +6 -0
  11. package/dist/catalog/core-catalog.d.ts.map +1 -0
  12. package/dist/catalog/core-catalog.js +105 -0
  13. package/dist/catalog/index.d.ts +5 -0
  14. package/dist/catalog/index.d.ts.map +1 -0
  15. package/dist/catalog/index.js +4 -0
  16. package/dist/components/app-error-boundary.d.ts +1 -0
  17. package/dist/components/app-error-boundary.d.ts.map +1 -1
  18. package/dist/components/app-error-boundary.js +13 -0
  19. package/dist/components/chat/chat-image-lightbox.d.ts +9 -0
  20. package/dist/components/chat/chat-image-lightbox.d.ts.map +1 -0
  21. package/dist/components/chat/chat-image-lightbox.js +9 -0
  22. package/dist/components/chat/chat-message.d.ts +19 -1
  23. package/dist/components/chat/chat-message.d.ts.map +1 -1
  24. package/dist/components/chat/chat-message.js +66 -16
  25. package/dist/components/chat/chat-messages.d.ts +5 -2
  26. package/dist/components/chat/chat-messages.d.ts.map +1 -1
  27. package/dist/components/chat/chat-messages.js +61 -6
  28. package/dist/components/chat/chat-panel.d.ts +67 -17
  29. package/dist/components/chat/chat-panel.d.ts.map +1 -1
  30. package/dist/components/chat/chat-panel.js +250 -159
  31. package/dist/components/chat/conversation-history.d.ts +39 -5
  32. package/dist/components/chat/conversation-history.d.ts.map +1 -1
  33. package/dist/components/chat/conversation-history.js +192 -26
  34. package/dist/components/chat/index.d.ts +3 -2
  35. package/dist/components/chat/index.d.ts.map +1 -1
  36. package/dist/components/chat/index.js +3 -2
  37. package/dist/components/chat/model-effort-power-effects.d.ts +7 -0
  38. package/dist/components/chat/model-effort-power-effects.d.ts.map +1 -0
  39. package/dist/components/chat/model-effort-power-effects.js +54 -0
  40. package/dist/components/chat/model-effort-selector.d.ts +26 -0
  41. package/dist/components/chat/model-effort-selector.d.ts.map +1 -0
  42. package/dist/components/chat/model-effort-selector.js +179 -0
  43. package/dist/components/chat/model-effort-ultra-effects.d.ts +5 -0
  44. package/dist/components/chat/model-effort-ultra-effects.d.ts.map +1 -0
  45. package/dist/components/chat/model-effort-ultra-effects.js +56 -0
  46. package/dist/components/chat/tool-handlers.d.ts.map +1 -1
  47. package/dist/components/chat/tool-handlers.js +40 -2
  48. package/dist/components/chat/vertical-scroll-fade.d.ts +6 -0
  49. package/dist/components/chat/vertical-scroll-fade.d.ts.map +1 -0
  50. package/dist/components/chat/vertical-scroll-fade.js +12 -0
  51. package/dist/components/hardware/bluetooth-panel-helpers.d.ts +9 -0
  52. package/dist/components/hardware/bluetooth-panel-helpers.d.ts.map +1 -0
  53. package/dist/components/hardware/bluetooth-panel-helpers.js +37 -0
  54. package/dist/components/hardware/bluetooth-panel.d.ts +56 -0
  55. package/dist/components/hardware/bluetooth-panel.d.ts.map +1 -0
  56. package/dist/components/hardware/bluetooth-panel.js +470 -0
  57. package/dist/components/hardware/camera-preview.d.ts +39 -0
  58. package/dist/components/hardware/camera-preview.d.ts.map +1 -0
  59. package/dist/components/hardware/camera-preview.js +228 -0
  60. package/dist/components/hardware/capability-badge.d.ts +23 -0
  61. package/dist/components/hardware/capability-badge.d.ts.map +1 -0
  62. package/dist/components/hardware/capability-badge.js +39 -0
  63. package/dist/components/hardware/capability-matrix.d.ts +14 -0
  64. package/dist/components/hardware/capability-matrix.d.ts.map +1 -0
  65. package/dist/components/hardware/capability-matrix.js +97 -0
  66. package/dist/components/hardware/clipboard-button.d.ts +26 -0
  67. package/dist/components/hardware/clipboard-button.d.ts.map +1 -0
  68. package/dist/components/hardware/clipboard-button.js +114 -0
  69. package/dist/components/hardware/device-io-controls.d.ts +4 -0
  70. package/dist/components/hardware/device-io-controls.d.ts.map +1 -0
  71. package/dist/components/hardware/device-io-controls.js +28 -0
  72. package/dist/components/hardware/device-list.d.ts +20 -0
  73. package/dist/components/hardware/device-list.d.ts.map +1 -0
  74. package/dist/components/hardware/device-list.js +14 -0
  75. package/dist/components/hardware/display-map.d.ts +23 -0
  76. package/dist/components/hardware/display-map.d.ts.map +1 -0
  77. package/dist/components/hardware/display-map.js +114 -0
  78. package/dist/components/hardware/haptic-button.d.ts +26 -0
  79. package/dist/components/hardware/haptic-button.d.ts.map +1 -0
  80. package/dist/components/hardware/haptic-button.js +94 -0
  81. package/dist/components/hardware/hardware-panel.d.ts +11 -0
  82. package/dist/components/hardware/hardware-panel.d.ts.map +1 -0
  83. package/dist/components/hardware/hardware-panel.js +28 -0
  84. package/dist/components/hardware/hid-panel.d.ts +40 -0
  85. package/dist/components/hardware/hid-panel.d.ts.map +1 -0
  86. package/dist/components/hardware/hid-panel.js +373 -0
  87. package/dist/components/hardware/index.d.ts +27 -0
  88. package/dist/components/hardware/index.d.ts.map +1 -0
  89. package/dist/components/hardware/index.js +26 -0
  90. package/dist/components/hardware/live-indicator.d.ts +15 -0
  91. package/dist/components/hardware/live-indicator.d.ts.map +1 -0
  92. package/dist/components/hardware/live-indicator.js +26 -0
  93. package/dist/components/hardware/local-auth-button.d.ts +33 -0
  94. package/dist/components/hardware/local-auth-button.d.ts.map +1 -0
  95. package/dist/components/hardware/local-auth-button.js +115 -0
  96. package/dist/components/hardware/location-panel.d.ts +29 -0
  97. package/dist/components/hardware/location-panel.d.ts.map +1 -0
  98. package/dist/components/hardware/location-panel.js +154 -0
  99. package/dist/components/hardware/microphone-meter.d.ts +35 -0
  100. package/dist/components/hardware/microphone-meter.d.ts.map +1 -0
  101. package/dist/components/hardware/microphone-meter.js +244 -0
  102. package/dist/components/hardware/midi-monitor.d.ts +54 -0
  103. package/dist/components/hardware/midi-monitor.d.ts.map +1 -0
  104. package/dist/components/hardware/midi-monitor.js +534 -0
  105. package/dist/components/hardware/notification-panel.d.ts +24 -0
  106. package/dist/components/hardware/notification-panel.d.ts.map +1 -0
  107. package/dist/components/hardware/notification-panel.js +124 -0
  108. package/dist/components/hardware/power-blocker-controller.d.ts +19 -0
  109. package/dist/components/hardware/power-blocker-controller.d.ts.map +1 -0
  110. package/dist/components/hardware/power-blocker-controller.js +83 -0
  111. package/dist/components/hardware/power-panel.d.ts +67 -0
  112. package/dist/components/hardware/power-panel.d.ts.map +1 -0
  113. package/dist/components/hardware/power-panel.js +309 -0
  114. package/dist/components/hardware/readout.d.ts +10 -0
  115. package/dist/components/hardware/readout.d.ts.map +1 -0
  116. package/dist/components/hardware/readout.js +11 -0
  117. package/dist/components/hardware/screen-share-preview.d.ts +36 -0
  118. package/dist/components/hardware/screen-share-preview.d.ts.map +1 -0
  119. package/dist/components/hardware/screen-share-preview.js +191 -0
  120. package/dist/components/hardware/secure-storage-panel.d.ts +36 -0
  121. package/dist/components/hardware/secure-storage-panel.d.ts.map +1 -0
  122. package/dist/components/hardware/secure-storage-panel.js +193 -0
  123. package/dist/components/hardware/serial-console.d.ts +64 -0
  124. package/dist/components/hardware/serial-console.d.ts.map +1 -0
  125. package/dist/components/hardware/serial-console.js +399 -0
  126. package/dist/components/hardware/shortcut-recorder.d.ts +35 -0
  127. package/dist/components/hardware/shortcut-recorder.d.ts.map +1 -0
  128. package/dist/components/hardware/shortcut-recorder.js +217 -0
  129. package/dist/components/hardware/stream-log.d.ts +35 -0
  130. package/dist/components/hardware/stream-log.d.ts.map +1 -0
  131. package/dist/components/hardware/stream-log.js +65 -0
  132. package/dist/components/hardware/system-audio-monitor.d.ts +34 -0
  133. package/dist/components/hardware/system-audio-monitor.d.ts.map +1 -0
  134. package/dist/components/hardware/system-audio-monitor.js +275 -0
  135. package/dist/components/hardware/usb-panel.d.ts +54 -0
  136. package/dist/components/hardware/usb-panel.d.ts.map +1 -0
  137. package/dist/components/hardware/usb-panel.js +363 -0
  138. package/dist/components/hardware/use-capability.d.ts +20 -0
  139. package/dist/components/hardware/use-capability.d.ts.map +1 -0
  140. package/dist/components/hardware/use-capability.js +61 -0
  141. package/dist/components/native-capabilities/bluetooth-panel-helpers.d.ts +9 -0
  142. package/dist/components/native-capabilities/bluetooth-panel-helpers.d.ts.map +1 -0
  143. package/dist/components/native-capabilities/bluetooth-panel-helpers.js +37 -0
  144. package/dist/components/native-capabilities/bluetooth-panel.d.ts +56 -0
  145. package/dist/components/native-capabilities/bluetooth-panel.d.ts.map +1 -0
  146. package/dist/components/native-capabilities/bluetooth-panel.js +470 -0
  147. package/dist/components/native-capabilities/camera-preview.d.ts +39 -0
  148. package/dist/components/native-capabilities/camera-preview.d.ts.map +1 -0
  149. package/dist/components/native-capabilities/camera-preview.js +228 -0
  150. package/dist/components/native-capabilities/capability-badge.d.ts +23 -0
  151. package/dist/components/native-capabilities/capability-badge.d.ts.map +1 -0
  152. package/dist/components/native-capabilities/capability-badge.js +39 -0
  153. package/dist/components/native-capabilities/capability-matrix.d.ts +14 -0
  154. package/dist/components/native-capabilities/capability-matrix.d.ts.map +1 -0
  155. package/dist/components/native-capabilities/capability-matrix.js +97 -0
  156. package/dist/components/native-capabilities/clipboard-button.d.ts +26 -0
  157. package/dist/components/native-capabilities/clipboard-button.d.ts.map +1 -0
  158. package/dist/components/native-capabilities/clipboard-button.js +99 -0
  159. package/dist/components/native-capabilities/device-io-controls.d.ts +4 -0
  160. package/dist/components/native-capabilities/device-io-controls.d.ts.map +1 -0
  161. package/dist/components/native-capabilities/device-io-controls.js +28 -0
  162. package/dist/components/native-capabilities/device-list.d.ts +20 -0
  163. package/dist/components/native-capabilities/device-list.d.ts.map +1 -0
  164. package/dist/components/native-capabilities/device-list.js +14 -0
  165. package/dist/components/native-capabilities/display-map.d.ts +23 -0
  166. package/dist/components/native-capabilities/display-map.d.ts.map +1 -0
  167. package/dist/components/native-capabilities/display-map.js +114 -0
  168. package/dist/components/native-capabilities/haptic-button.d.ts +26 -0
  169. package/dist/components/native-capabilities/haptic-button.d.ts.map +1 -0
  170. package/dist/components/native-capabilities/haptic-button.js +94 -0
  171. package/dist/components/native-capabilities/hid-panel.d.ts +40 -0
  172. package/dist/components/native-capabilities/hid-panel.d.ts.map +1 -0
  173. package/dist/components/native-capabilities/hid-panel.js +373 -0
  174. package/dist/components/native-capabilities/index.d.ts +27 -0
  175. package/dist/components/native-capabilities/index.d.ts.map +1 -0
  176. package/dist/components/native-capabilities/index.js +26 -0
  177. package/dist/components/native-capabilities/live-indicator.d.ts +15 -0
  178. package/dist/components/native-capabilities/live-indicator.d.ts.map +1 -0
  179. package/dist/components/native-capabilities/live-indicator.js +26 -0
  180. package/dist/components/native-capabilities/local-auth-button.d.ts +33 -0
  181. package/dist/components/native-capabilities/local-auth-button.d.ts.map +1 -0
  182. package/dist/components/native-capabilities/local-auth-button.js +115 -0
  183. package/dist/components/native-capabilities/location-panel.d.ts +29 -0
  184. package/dist/components/native-capabilities/location-panel.d.ts.map +1 -0
  185. package/dist/components/native-capabilities/location-panel.js +146 -0
  186. package/dist/components/native-capabilities/microphone-meter.d.ts +35 -0
  187. package/dist/components/native-capabilities/microphone-meter.d.ts.map +1 -0
  188. package/dist/components/native-capabilities/microphone-meter.js +244 -0
  189. package/dist/components/native-capabilities/midi-monitor.d.ts +54 -0
  190. package/dist/components/native-capabilities/midi-monitor.d.ts.map +1 -0
  191. package/dist/components/native-capabilities/midi-monitor.js +534 -0
  192. package/dist/components/native-capabilities/native-capability-panel.d.ts +11 -0
  193. package/dist/components/native-capabilities/native-capability-panel.d.ts.map +1 -0
  194. package/dist/components/native-capabilities/native-capability-panel.js +28 -0
  195. package/dist/components/native-capabilities/notification-panel.d.ts +24 -0
  196. package/dist/components/native-capabilities/notification-panel.d.ts.map +1 -0
  197. package/dist/components/native-capabilities/notification-panel.js +124 -0
  198. package/dist/components/native-capabilities/power-blocker-controller.d.ts +19 -0
  199. package/dist/components/native-capabilities/power-blocker-controller.d.ts.map +1 -0
  200. package/dist/components/native-capabilities/power-blocker-controller.js +83 -0
  201. package/dist/components/native-capabilities/power-panel.d.ts +67 -0
  202. package/dist/components/native-capabilities/power-panel.d.ts.map +1 -0
  203. package/dist/components/native-capabilities/power-panel.js +309 -0
  204. package/dist/components/native-capabilities/readout.d.ts +10 -0
  205. package/dist/components/native-capabilities/readout.d.ts.map +1 -0
  206. package/dist/components/native-capabilities/readout.js +11 -0
  207. package/dist/components/native-capabilities/screen-share-preview.d.ts +36 -0
  208. package/dist/components/native-capabilities/screen-share-preview.d.ts.map +1 -0
  209. package/dist/components/native-capabilities/screen-share-preview.js +191 -0
  210. package/dist/components/native-capabilities/secure-storage-panel.d.ts +36 -0
  211. package/dist/components/native-capabilities/secure-storage-panel.d.ts.map +1 -0
  212. package/dist/components/native-capabilities/secure-storage-panel.js +193 -0
  213. package/dist/components/native-capabilities/serial-console.d.ts +64 -0
  214. package/dist/components/native-capabilities/serial-console.d.ts.map +1 -0
  215. package/dist/components/native-capabilities/serial-console.js +399 -0
  216. package/dist/components/native-capabilities/shortcut-recorder.d.ts +35 -0
  217. package/dist/components/native-capabilities/shortcut-recorder.d.ts.map +1 -0
  218. package/dist/components/native-capabilities/shortcut-recorder.js +217 -0
  219. package/dist/components/native-capabilities/stream-log.d.ts +35 -0
  220. package/dist/components/native-capabilities/stream-log.d.ts.map +1 -0
  221. package/dist/components/native-capabilities/stream-log.js +65 -0
  222. package/dist/components/native-capabilities/system-audio-monitor.d.ts +34 -0
  223. package/dist/components/native-capabilities/system-audio-monitor.d.ts.map +1 -0
  224. package/dist/components/native-capabilities/system-audio-monitor.js +275 -0
  225. package/dist/components/native-capabilities/usb-panel.d.ts +54 -0
  226. package/dist/components/native-capabilities/usb-panel.d.ts.map +1 -0
  227. package/dist/components/native-capabilities/usb-panel.js +363 -0
  228. package/dist/components/native-capabilities/use-capability.d.ts +20 -0
  229. package/dist/components/native-capabilities/use-capability.d.ts.map +1 -0
  230. package/dist/components/native-capabilities/use-capability.js +61 -0
  231. package/dist/components/ui/app-frame.d.ts +22 -0
  232. package/dist/components/ui/app-frame.d.ts.map +1 -0
  233. package/dist/components/ui/app-frame.js +56 -0
  234. package/dist/components/ui/button-group.d.ts +1 -1
  235. package/dist/components/ui/button.js +1 -1
  236. package/dist/components/ui/color-well.d.ts +13 -0
  237. package/dist/components/ui/color-well.d.ts.map +1 -0
  238. package/dist/components/ui/color-well.js +30 -0
  239. package/dist/components/ui/date-field.d.ts +19 -0
  240. package/dist/components/ui/date-field.d.ts.map +1 -0
  241. package/dist/components/ui/date-field.js +54 -0
  242. package/dist/components/ui/edge-fade.d.ts +11 -0
  243. package/dist/components/ui/edge-fade.d.ts.map +1 -0
  244. package/dist/components/ui/edge-fade.js +41 -0
  245. package/dist/components/ui/empty.js +1 -1
  246. package/dist/components/ui/field.d.ts +1 -1
  247. package/dist/components/ui/grid.d.ts +24 -0
  248. package/dist/components/ui/grid.d.ts.map +1 -0
  249. package/dist/components/ui/grid.js +234 -0
  250. package/dist/components/ui/icon-button.d.ts +15 -0
  251. package/dist/components/ui/icon-button.d.ts.map +1 -0
  252. package/dist/components/ui/icon-button.js +15 -0
  253. package/dist/components/ui/index.d.ts +19 -0
  254. package/dist/components/ui/index.d.ts.map +1 -1
  255. package/dist/components/ui/index.js +19 -0
  256. package/dist/components/ui/inspector.d.ts +15 -0
  257. package/dist/components/ui/inspector.d.ts.map +1 -0
  258. package/dist/components/ui/inspector.js +26 -0
  259. package/dist/components/ui/kbd.d.ts +1 -1
  260. package/dist/components/ui/list.d.ts +24 -0
  261. package/dist/components/ui/list.d.ts.map +1 -0
  262. package/dist/components/ui/list.js +224 -0
  263. package/dist/components/ui/message-scroller-layout-stability.d.ts +33 -0
  264. package/dist/components/ui/message-scroller-layout-stability.d.ts.map +1 -0
  265. package/dist/components/ui/message-scroller-layout-stability.js +153 -0
  266. package/dist/components/ui/message-scroller.d.ts +11 -0
  267. package/dist/components/ui/message-scroller.d.ts.map +1 -0
  268. package/dist/components/ui/message-scroller.js +37 -0
  269. package/dist/components/ui/notification-dot.d.ts +4 -0
  270. package/dist/components/ui/notification-dot.d.ts.map +1 -0
  271. package/dist/components/ui/notification-dot.js +7 -0
  272. package/dist/components/ui/number-input.d.ts +16 -0
  273. package/dist/components/ui/number-input.d.ts.map +1 -0
  274. package/dist/components/ui/number-input.js +56 -0
  275. package/dist/components/ui/panel.d.ts +18 -0
  276. package/dist/components/ui/panel.d.ts.map +1 -0
  277. package/dist/components/ui/panel.js +40 -0
  278. package/dist/components/ui/popover.js +1 -1
  279. package/dist/components/ui/search-field.d.ts +19 -0
  280. package/dist/components/ui/search-field.d.ts.map +1 -0
  281. package/dist/components/ui/search-field.js +64 -0
  282. package/dist/components/ui/segmented-control.d.ts +21 -0
  283. package/dist/components/ui/segmented-control.d.ts.map +1 -0
  284. package/dist/components/ui/segmented-control.js +61 -0
  285. package/dist/components/ui/sidebar.js +1 -1
  286. package/dist/components/ui/slider.d.ts +4 -1
  287. package/dist/components/ui/slider.d.ts.map +1 -1
  288. package/dist/components/ui/slider.js +2 -2
  289. package/dist/components/ui/sonner.d.ts +4 -3
  290. package/dist/components/ui/sonner.d.ts.map +1 -1
  291. package/dist/components/ui/sonner.js +7 -6
  292. package/dist/components/ui/split-view.d.ts +11 -0
  293. package/dist/components/ui/split-view.d.ts.map +1 -0
  294. package/dist/components/ui/split-view.js +13 -0
  295. package/dist/components/ui/status.d.ts +13 -0
  296. package/dist/components/ui/status.d.ts.map +1 -0
  297. package/dist/components/ui/status.js +36 -0
  298. package/dist/components/ui/table.d.ts +11 -2
  299. package/dist/components/ui/table.d.ts.map +1 -1
  300. package/dist/components/ui/table.js +28 -6
  301. package/dist/components/ui/text.d.ts +17 -0
  302. package/dist/components/ui/text.d.ts.map +1 -0
  303. package/dist/components/ui/text.js +55 -0
  304. package/dist/components/ui/toggle.js +1 -1
  305. package/dist/components/ui/toolbar.d.ts +20 -0
  306. package/dist/components/ui/toolbar.d.ts.map +1 -0
  307. package/dist/components/ui/toolbar.js +52 -0
  308. package/dist/index.d.ts +2 -0
  309. package/dist/index.d.ts.map +1 -1
  310. package/dist/index.js +4 -0
  311. package/dist/lib/frame-lifecycle.d.ts +28 -0
  312. package/dist/lib/frame-lifecycle.d.ts.map +1 -1
  313. package/dist/lib/frame-lifecycle.js +84 -0
  314. package/dist/lib/native-capabilities/access.d.ts +13 -0
  315. package/dist/lib/native-capabilities/access.d.ts.map +1 -0
  316. package/dist/lib/native-capabilities/access.js +53 -0
  317. package/dist/lib/native-capabilities/bluetooth-access.d.ts +14 -0
  318. package/dist/lib/native-capabilities/bluetooth-access.d.ts.map +1 -0
  319. package/dist/lib/native-capabilities/bluetooth-access.js +43 -0
  320. package/dist/lib/native-capabilities/bluetooth-connection.d.ts +19 -0
  321. package/dist/lib/native-capabilities/bluetooth-connection.d.ts.map +1 -0
  322. package/dist/lib/native-capabilities/bluetooth-connection.js +88 -0
  323. package/dist/lib/native-capabilities/bluetooth-gatt.d.ts +7 -0
  324. package/dist/lib/native-capabilities/bluetooth-gatt.d.ts.map +1 -0
  325. package/dist/lib/native-capabilities/bluetooth-gatt.js +77 -0
  326. package/dist/lib/native-capabilities/bluetooth-internal.d.ts +10 -0
  327. package/dist/lib/native-capabilities/bluetooth-internal.d.ts.map +1 -0
  328. package/dist/lib/native-capabilities/bluetooth-internal.js +105 -0
  329. package/dist/lib/native-capabilities/bluetooth-native-fallback.d.ts +33 -0
  330. package/dist/lib/native-capabilities/bluetooth-native-fallback.d.ts.map +1 -0
  331. package/dist/lib/native-capabilities/bluetooth-native-fallback.js +214 -0
  332. package/dist/lib/native-capabilities/bluetooth-types.d.ts +85 -0
  333. package/dist/lib/native-capabilities/bluetooth-types.d.ts.map +1 -0
  334. package/dist/lib/native-capabilities/bluetooth-types.js +2 -0
  335. package/dist/lib/native-capabilities/bluetooth.d.ts +7 -0
  336. package/dist/lib/native-capabilities/bluetooth.d.ts.map +1 -0
  337. package/dist/lib/native-capabilities/bluetooth.js +4 -0
  338. package/dist/lib/native-capabilities/bridge.d.ts +23 -0
  339. package/dist/lib/native-capabilities/bridge.d.ts.map +1 -0
  340. package/dist/lib/native-capabilities/bridge.js +266 -0
  341. package/dist/lib/native-capabilities/capabilities.d.ts +7 -0
  342. package/dist/lib/native-capabilities/capabilities.d.ts.map +1 -0
  343. package/dist/lib/native-capabilities/capabilities.js +95 -0
  344. package/dist/lib/native-capabilities/clipboard.d.ts +11 -0
  345. package/dist/lib/native-capabilities/clipboard.d.ts.map +1 -0
  346. package/dist/lib/native-capabilities/clipboard.js +58 -0
  347. package/dist/lib/native-capabilities/device-io-errors.d.ts +11 -0
  348. package/dist/lib/native-capabilities/device-io-errors.d.ts.map +1 -0
  349. package/dist/lib/native-capabilities/device-io-errors.js +82 -0
  350. package/dist/lib/native-capabilities/displays.d.ts +38 -0
  351. package/dist/lib/native-capabilities/displays.d.ts.map +1 -0
  352. package/dist/lib/native-capabilities/displays.js +12 -0
  353. package/dist/lib/native-capabilities/global-shortcuts.d.ts +86 -0
  354. package/dist/lib/native-capabilities/global-shortcuts.d.ts.map +1 -0
  355. package/dist/lib/native-capabilities/global-shortcuts.js +351 -0
  356. package/dist/lib/native-capabilities/haptics.d.ts +25 -0
  357. package/dist/lib/native-capabilities/haptics.d.ts.map +1 -0
  358. package/dist/lib/native-capabilities/haptics.js +18 -0
  359. package/dist/lib/native-capabilities/hid-native.d.ts +26 -0
  360. package/dist/lib/native-capabilities/hid-native.d.ts.map +1 -0
  361. package/dist/lib/native-capabilities/hid-native.js +229 -0
  362. package/dist/lib/native-capabilities/hid.d.ts +52 -0
  363. package/dist/lib/native-capabilities/hid.d.ts.map +1 -0
  364. package/dist/lib/native-capabilities/hid.js +163 -0
  365. package/dist/lib/native-capabilities/index.d.ts +40 -0
  366. package/dist/lib/native-capabilities/index.d.ts.map +1 -0
  367. package/dist/lib/native-capabilities/index.js +21 -0
  368. package/dist/lib/native-capabilities/local-authentication.d.ts +32 -0
  369. package/dist/lib/native-capabilities/local-authentication.d.ts.map +1 -0
  370. package/dist/lib/native-capabilities/local-authentication.js +46 -0
  371. package/dist/lib/native-capabilities/location.d.ts +49 -0
  372. package/dist/lib/native-capabilities/location.d.ts.map +1 -0
  373. package/dist/lib/native-capabilities/location.js +114 -0
  374. package/dist/lib/native-capabilities/media-permissions.d.ts +28 -0
  375. package/dist/lib/native-capabilities/media-permissions.d.ts.map +1 -0
  376. package/dist/lib/native-capabilities/media-permissions.js +37 -0
  377. package/dist/lib/native-capabilities/media.d.ts +17 -0
  378. package/dist/lib/native-capabilities/media.d.ts.map +1 -0
  379. package/dist/lib/native-capabilities/media.js +104 -0
  380. package/dist/lib/native-capabilities/midi-access.d.ts +13 -0
  381. package/dist/lib/native-capabilities/midi-access.d.ts.map +1 -0
  382. package/dist/lib/native-capabilities/midi-access.js +68 -0
  383. package/dist/lib/native-capabilities/midi-internal.d.ts +12 -0
  384. package/dist/lib/native-capabilities/midi-internal.d.ts.map +1 -0
  385. package/dist/lib/native-capabilities/midi-internal.js +88 -0
  386. package/dist/lib/native-capabilities/midi-native-fallback.d.ts +27 -0
  387. package/dist/lib/native-capabilities/midi-native-fallback.d.ts.map +1 -0
  388. package/dist/lib/native-capabilities/midi-native-fallback.js +127 -0
  389. package/dist/lib/native-capabilities/midi-ports.d.ts +6 -0
  390. package/dist/lib/native-capabilities/midi-ports.d.ts.map +1 -0
  391. package/dist/lib/native-capabilities/midi-ports.js +115 -0
  392. package/dist/lib/native-capabilities/midi-types.d.ts +25 -0
  393. package/dist/lib/native-capabilities/midi-types.d.ts.map +1 -0
  394. package/dist/lib/native-capabilities/midi-types.js +1 -0
  395. package/dist/lib/native-capabilities/midi.d.ts +6 -0
  396. package/dist/lib/native-capabilities/midi.d.ts.map +1 -0
  397. package/dist/lib/native-capabilities/midi.js +3 -0
  398. package/dist/lib/native-capabilities/native-device-io.d.ts +28 -0
  399. package/dist/lib/native-capabilities/native-device-io.d.ts.map +1 -0
  400. package/dist/lib/native-capabilities/native-device-io.js +91 -0
  401. package/dist/lib/native-capabilities/native-device-lifecycle.d.ts +13 -0
  402. package/dist/lib/native-capabilities/native-device-lifecycle.d.ts.map +1 -0
  403. package/dist/lib/native-capabilities/native-device-lifecycle.js +40 -0
  404. package/dist/lib/native-capabilities/notifications.d.ts +38 -0
  405. package/dist/lib/native-capabilities/notifications.d.ts.map +1 -0
  406. package/dist/lib/native-capabilities/notifications.js +50 -0
  407. package/dist/lib/native-capabilities/power-session.d.ts +113 -0
  408. package/dist/lib/native-capabilities/power-session.d.ts.map +1 -0
  409. package/dist/lib/native-capabilities/power-session.js +264 -0
  410. package/dist/lib/native-capabilities/secure-storage.d.ts +36 -0
  411. package/dist/lib/native-capabilities/secure-storage.d.ts.map +1 -0
  412. package/dist/lib/native-capabilities/secure-storage.js +64 -0
  413. package/dist/lib/native-capabilities/serial-native.d.ts +23 -0
  414. package/dist/lib/native-capabilities/serial-native.d.ts.map +1 -0
  415. package/dist/lib/native-capabilities/serial-native.js +181 -0
  416. package/dist/lib/native-capabilities/serial.d.ts +76 -0
  417. package/dist/lib/native-capabilities/serial.d.ts.map +1 -0
  418. package/dist/lib/native-capabilities/serial.js +215 -0
  419. package/dist/lib/native-capabilities/system-audio.d.ts +127 -0
  420. package/dist/lib/native-capabilities/system-audio.d.ts.map +1 -0
  421. package/dist/lib/native-capabilities/system-audio.js +330 -0
  422. package/dist/lib/native-capabilities/types.d.ts +62 -0
  423. package/dist/lib/native-capabilities/types.d.ts.map +1 -0
  424. package/dist/lib/native-capabilities/types.js +27 -0
  425. package/dist/lib/native-capabilities/usb-native.d.ts +39 -0
  426. package/dist/lib/native-capabilities/usb-native.d.ts.map +1 -0
  427. package/dist/lib/native-capabilities/usb-native.js +217 -0
  428. package/dist/lib/native-capabilities/usb.d.ts +85 -0
  429. package/dist/lib/native-capabilities/usb.d.ts.map +1 -0
  430. package/dist/lib/native-capabilities/usb.js +225 -0
  431. package/dist/lib/native-hardware/bluetooth-access.d.ts +14 -0
  432. package/dist/lib/native-hardware/bluetooth-access.d.ts.map +1 -0
  433. package/dist/lib/native-hardware/bluetooth-access.js +40 -0
  434. package/dist/lib/native-hardware/bluetooth-connection.d.ts +19 -0
  435. package/dist/lib/native-hardware/bluetooth-connection.d.ts.map +1 -0
  436. package/dist/lib/native-hardware/bluetooth-connection.js +88 -0
  437. package/dist/lib/native-hardware/bluetooth-gatt.d.ts +7 -0
  438. package/dist/lib/native-hardware/bluetooth-gatt.d.ts.map +1 -0
  439. package/dist/lib/native-hardware/bluetooth-gatt.js +77 -0
  440. package/dist/lib/native-hardware/bluetooth-internal.d.ts +10 -0
  441. package/dist/lib/native-hardware/bluetooth-internal.d.ts.map +1 -0
  442. package/dist/lib/native-hardware/bluetooth-internal.js +105 -0
  443. package/dist/lib/native-hardware/bluetooth-native-fallback.d.ts +33 -0
  444. package/dist/lib/native-hardware/bluetooth-native-fallback.d.ts.map +1 -0
  445. package/dist/lib/native-hardware/bluetooth-native-fallback.js +214 -0
  446. package/dist/lib/native-hardware/bluetooth-types.d.ts +85 -0
  447. package/dist/lib/native-hardware/bluetooth-types.d.ts.map +1 -0
  448. package/dist/lib/native-hardware/bluetooth-types.js +2 -0
  449. package/dist/lib/native-hardware/bluetooth.d.ts +7 -0
  450. package/dist/lib/native-hardware/bluetooth.d.ts.map +1 -0
  451. package/dist/lib/native-hardware/bluetooth.js +4 -0
  452. package/dist/lib/native-hardware/bridge.d.ts +23 -0
  453. package/dist/lib/native-hardware/bridge.d.ts.map +1 -0
  454. package/dist/lib/native-hardware/bridge.js +266 -0
  455. package/dist/lib/native-hardware/capabilities.d.ts +7 -0
  456. package/dist/lib/native-hardware/capabilities.d.ts.map +1 -0
  457. package/dist/lib/native-hardware/capabilities.js +95 -0
  458. package/dist/lib/native-hardware/clipboard.d.ts +11 -0
  459. package/dist/lib/native-hardware/clipboard.d.ts.map +1 -0
  460. package/dist/lib/native-hardware/clipboard.js +55 -0
  461. package/dist/lib/native-hardware/device-io-errors.d.ts +11 -0
  462. package/dist/lib/native-hardware/device-io-errors.d.ts.map +1 -0
  463. package/dist/lib/native-hardware/device-io-errors.js +82 -0
  464. package/dist/lib/native-hardware/displays.d.ts +38 -0
  465. package/dist/lib/native-hardware/displays.d.ts.map +1 -0
  466. package/dist/lib/native-hardware/displays.js +12 -0
  467. package/dist/lib/native-hardware/global-shortcuts.d.ts +86 -0
  468. package/dist/lib/native-hardware/global-shortcuts.d.ts.map +1 -0
  469. package/dist/lib/native-hardware/global-shortcuts.js +351 -0
  470. package/dist/lib/native-hardware/haptics.d.ts +25 -0
  471. package/dist/lib/native-hardware/haptics.d.ts.map +1 -0
  472. package/dist/lib/native-hardware/haptics.js +18 -0
  473. package/dist/lib/native-hardware/hid-native.d.ts +26 -0
  474. package/dist/lib/native-hardware/hid-native.d.ts.map +1 -0
  475. package/dist/lib/native-hardware/hid-native.js +229 -0
  476. package/dist/lib/native-hardware/hid.d.ts +52 -0
  477. package/dist/lib/native-hardware/hid.d.ts.map +1 -0
  478. package/dist/lib/native-hardware/hid.js +160 -0
  479. package/dist/lib/native-hardware/index.d.ts +38 -0
  480. package/dist/lib/native-hardware/index.d.ts.map +1 -0
  481. package/dist/lib/native-hardware/index.js +20 -0
  482. package/dist/lib/native-hardware/local-authentication.d.ts +32 -0
  483. package/dist/lib/native-hardware/local-authentication.d.ts.map +1 -0
  484. package/dist/lib/native-hardware/local-authentication.js +46 -0
  485. package/dist/lib/native-hardware/location.d.ts +49 -0
  486. package/dist/lib/native-hardware/location.d.ts.map +1 -0
  487. package/dist/lib/native-hardware/location.js +114 -0
  488. package/dist/lib/native-hardware/media-permissions.d.ts +28 -0
  489. package/dist/lib/native-hardware/media-permissions.d.ts.map +1 -0
  490. package/dist/lib/native-hardware/media-permissions.js +37 -0
  491. package/dist/lib/native-hardware/media.d.ts +17 -0
  492. package/dist/lib/native-hardware/media.d.ts.map +1 -0
  493. package/dist/lib/native-hardware/media.js +99 -0
  494. package/dist/lib/native-hardware/midi-access.d.ts +13 -0
  495. package/dist/lib/native-hardware/midi-access.d.ts.map +1 -0
  496. package/dist/lib/native-hardware/midi-access.js +66 -0
  497. package/dist/lib/native-hardware/midi-internal.d.ts +12 -0
  498. package/dist/lib/native-hardware/midi-internal.d.ts.map +1 -0
  499. package/dist/lib/native-hardware/midi-internal.js +88 -0
  500. package/dist/lib/native-hardware/midi-native-fallback.d.ts +27 -0
  501. package/dist/lib/native-hardware/midi-native-fallback.d.ts.map +1 -0
  502. package/dist/lib/native-hardware/midi-native-fallback.js +127 -0
  503. package/dist/lib/native-hardware/midi-ports.d.ts +6 -0
  504. package/dist/lib/native-hardware/midi-ports.d.ts.map +1 -0
  505. package/dist/lib/native-hardware/midi-ports.js +115 -0
  506. package/dist/lib/native-hardware/midi-types.d.ts +25 -0
  507. package/dist/lib/native-hardware/midi-types.d.ts.map +1 -0
  508. package/dist/lib/native-hardware/midi-types.js +1 -0
  509. package/dist/lib/native-hardware/midi.d.ts +6 -0
  510. package/dist/lib/native-hardware/midi.d.ts.map +1 -0
  511. package/dist/lib/native-hardware/midi.js +3 -0
  512. package/dist/lib/native-hardware/native-device-io.d.ts +28 -0
  513. package/dist/lib/native-hardware/native-device-io.d.ts.map +1 -0
  514. package/dist/lib/native-hardware/native-device-io.js +91 -0
  515. package/dist/lib/native-hardware/native-device-lifecycle.d.ts +13 -0
  516. package/dist/lib/native-hardware/native-device-lifecycle.d.ts.map +1 -0
  517. package/dist/lib/native-hardware/native-device-lifecycle.js +40 -0
  518. package/dist/lib/native-hardware/notifications.d.ts +38 -0
  519. package/dist/lib/native-hardware/notifications.d.ts.map +1 -0
  520. package/dist/lib/native-hardware/notifications.js +50 -0
  521. package/dist/lib/native-hardware/power-session.d.ts +113 -0
  522. package/dist/lib/native-hardware/power-session.d.ts.map +1 -0
  523. package/dist/lib/native-hardware/power-session.js +264 -0
  524. package/dist/lib/native-hardware/secure-storage.d.ts +36 -0
  525. package/dist/lib/native-hardware/secure-storage.d.ts.map +1 -0
  526. package/dist/lib/native-hardware/secure-storage.js +64 -0
  527. package/dist/lib/native-hardware/serial-native.d.ts +23 -0
  528. package/dist/lib/native-hardware/serial-native.d.ts.map +1 -0
  529. package/dist/lib/native-hardware/serial-native.js +181 -0
  530. package/dist/lib/native-hardware/serial.d.ts +76 -0
  531. package/dist/lib/native-hardware/serial.d.ts.map +1 -0
  532. package/dist/lib/native-hardware/serial.js +212 -0
  533. package/dist/lib/native-hardware/system-audio.d.ts +127 -0
  534. package/dist/lib/native-hardware/system-audio.d.ts.map +1 -0
  535. package/dist/lib/native-hardware/system-audio.js +330 -0
  536. package/dist/lib/native-hardware/types.d.ts +62 -0
  537. package/dist/lib/native-hardware/types.d.ts.map +1 -0
  538. package/dist/lib/native-hardware/types.js +27 -0
  539. package/dist/lib/native-hardware/usb-native.d.ts +39 -0
  540. package/dist/lib/native-hardware/usb-native.d.ts.map +1 -0
  541. package/dist/lib/native-hardware/usb-native.js +217 -0
  542. package/dist/lib/native-hardware/usb.d.ts +85 -0
  543. package/dist/lib/native-hardware/usb.d.ts.map +1 -0
  544. package/dist/lib/native-hardware/usb.js +222 -0
  545. package/docs/README.md +37 -0
  546. package/docs/accessibility.md +32 -0
  547. package/docs/app-anatomy.md +72 -0
  548. package/docs/component-catalog.md +59 -0
  549. package/docs/component-guide-template.md +37 -0
  550. package/docs/design-tokens.md +172 -0
  551. package/docs/foundations.md +56 -0
  552. package/docs/native-integration.md +33 -0
  553. package/docs/standalone-app-windows.md +128 -0
  554. package/package.json +9 -3
  555. package/src/components/ui/alert.md +55 -0
  556. package/src/components/ui/app-frame.md +33 -0
  557. package/src/components/ui/badge.md +57 -0
  558. package/src/components/ui/button.md +76 -0
  559. package/src/components/ui/color-well.md +11 -0
  560. package/src/components/ui/combobox.md +43 -0
  561. package/src/components/ui/date-field.md +32 -0
  562. package/src/components/ui/edge-fade.md +7 -0
  563. package/src/components/ui/empty.md +82 -0
  564. package/src/components/ui/field.md +77 -0
  565. package/src/components/ui/grid.md +105 -0
  566. package/src/components/ui/icon-button.md +36 -0
  567. package/src/components/ui/inspector.md +11 -0
  568. package/src/components/ui/item.md +87 -0
  569. package/src/components/ui/list.md +107 -0
  570. package/src/components/ui/notification-dot.md +7 -0
  571. package/src/components/ui/number-input.md +19 -0
  572. package/src/components/ui/panel.md +11 -0
  573. package/src/components/ui/resizable.md +66 -0
  574. package/src/components/ui/scroll-area.md +68 -0
  575. package/src/components/ui/search-field.md +33 -0
  576. package/src/components/ui/segmented-control.md +39 -0
  577. package/src/components/ui/sidebar.md +113 -0
  578. package/src/components/ui/sonner.md +37 -0
  579. package/src/components/ui/split-view.md +15 -0
  580. package/src/components/ui/status.md +12 -0
  581. package/src/components/ui/table.md +35 -0
  582. package/src/components/ui/tabs.md +66 -0
  583. package/src/components/ui/text.md +17 -0
  584. package/src/components/ui/toggle-group.md +80 -0
  585. package/src/components/ui/toggle.md +73 -0
  586. package/src/components/ui/toolbar.md +21 -0
  587. package/src/styles/index.css +868 -3
@@ -1,24 +1,157 @@
1
1
  'use client';
2
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
- import { AlertCircle, ArrowDown, ChevronDown, ClipboardList, Code2, CornerDownRight, GripVertical, Image as ImageIcon, ListPlus, Pencil, Trash2, } from 'lucide-react';
2
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { AlertCircle, ChevronDown, ClipboardList, Code2, CornerDownRight, GripVertical, Image as ImageIcon, ListPlus, Loader2, Maximize2, Minimize2, Pencil, RotateCcw, Trash2, } from 'lucide-react';
4
4
  import { useCallback, useEffect, useMemo, useRef, useState, } from 'react';
5
5
  import { cn } from '../../lib/utils';
6
6
  import { Button } from '../ui/button';
7
- import { ScrollArea } from '../ui/scroll-area';
7
+ import { Dialog, DialogContent, DialogTitle } from '../ui/dialog';
8
+ import { MessageScroller, MessageScrollerButton, MessageScrollerContent, MessageScrollerItem, MessageScrollerProvider, MessageScrollerViewport, useMessageScroller, useMessageScrollerVisibility, } from '../ui/message-scroller';
9
+ import { Popover, PopoverContent, PopoverTrigger } from '../ui/popover';
8
10
  import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from '../ui/tooltip';
9
11
  import { ChatInput, } from './chat-input';
10
- import { CompactingMessage, ThinkingMessage, } from './chat-message';
12
+ import { CompactingMessage, ThinkingMessage, getChatMessageRenderKey, } from './chat-message';
11
13
  import { MessageRow, computeIsThinking, } from './chat-messages';
12
- import { ConversationHistory, } from './conversation-history';
13
- import { ModelSelector } from './model-selector';
14
- import { ReasoningEffortSelector, } from './reasoning-effort-selector';
14
+ import { ConversationHistory, ConversationSidebar, } from './conversation-history';
15
+ import { ModelEffortSelector, } from './model-effort-selector';
15
16
  import { ToolApprovalProvider, } from './tool-approval-context';
16
17
  import { ToolProgressProvider } from './tool-progress-context';
17
18
  import { DndContext, KeyboardSensor, PointerSensor, closestCenter, useSensor, useSensors, } from '@dnd-kit/core';
18
19
  import { SortableContext, sortableKeyboardCoordinates, useSortable, verticalListSortingStrategy, } from '@dnd-kit/sortable';
19
20
  import { CSS } from '@dnd-kit/utilities';
20
21
  import { AnimatePresence, motion } from 'framer-motion';
21
- import { Virtualizer } from 'virtua';
22
+ const CODEX_OAUTH_ERROR_PATTERNS = [
23
+ 'codex oauth',
24
+ 'codex-oauth',
25
+ 'codex_oauth_json',
26
+ 'openai codex authentication',
27
+ 'openai/codex-responses',
28
+ 'chatgpt.com/backend-api/codex',
29
+ 'refresh_token_reused',
30
+ ];
31
+ const MISSING_API_KEY_ERROR_PATTERNS = [
32
+ 'api_key not configured',
33
+ 'api key not found',
34
+ 'api key required',
35
+ 'credential required in vault',
36
+ 'credential not configured in vault',
37
+ ];
38
+ function isToastInteractionTarget(target) {
39
+ return (target instanceof Element &&
40
+ target.closest('[data-sonner-toaster], [data-sonner-toast]') !== null);
41
+ }
42
+ const AUTH_PROMPT_COPY = {
43
+ 'missing-api-key': {
44
+ label: 'Sign in with your ChatGPT account to chat with AI',
45
+ action: 'Connect ChatGPT',
46
+ },
47
+ 'codex-oauth-expired': {
48
+ label: 'Sign in again to refresh your ChatGPT connection',
49
+ action: 'Reconnect ChatGPT',
50
+ },
51
+ };
52
+ export function getChatAuthPromptCopy(issue) {
53
+ return AUTH_PROMPT_COPY[issue];
54
+ }
55
+ function ChatAuthPrompt({ copy, isConnecting, onConnect, onAdvancedSetup, }) {
56
+ return (_jsxs("div", { className: "flex flex-col items-center gap-2 py-3 text-center", "data-chat-auth-prompt": true, children: [_jsx("p", { className: "text-muted-foreground max-w-sm text-sm", children: copy.label }), onConnect && (_jsx(Button, { onClick: onConnect, size: "sm", className: "cursor-pointer", disabled: isConnecting, children: isConnecting ? (_jsxs(_Fragment, { children: [_jsx(Loader2, { className: "mr-2 size-4 animate-spin" }), "Waiting for ChatGPT..."] })) : (copy.action) })), onAdvancedSetup && (_jsx(Button, { variant: "ghost", size: "sm", className: "text-muted-foreground hover:text-foreground h-auto cursor-pointer px-2 py-1 text-xs font-normal", onClick: onAdvancedSetup, disabled: isConnecting, children: "Advanced setup" }))] }));
57
+ }
58
+ function messageIncludesAny(message, patterns) {
59
+ const normalized = message.toLowerCase();
60
+ return patterns.some((pattern) => normalized.includes(pattern));
61
+ }
62
+ export function resolveChatAuthIssue({ missingApiKey, authIssue, error, }) {
63
+ if (authIssue)
64
+ return authIssue;
65
+ const message = error?.message ?? '';
66
+ if (messageIncludesAny(message, CODEX_OAUTH_ERROR_PATTERNS)) {
67
+ return 'codex-oauth-expired';
68
+ }
69
+ if (missingApiKey)
70
+ return 'missing-api-key';
71
+ if (messageIncludesAny(message, MISSING_API_KEY_ERROR_PATTERNS)) {
72
+ return 'missing-api-key';
73
+ }
74
+ return null;
75
+ }
76
+ export function hasPersistedChatError(messages) {
77
+ const lastMessage = messages.at(-1);
78
+ return Boolean(lastMessage?.parts?.some((part) => part.type === 'error'));
79
+ }
80
+ export function getPrependPreservedScrollTop(previousScrollTop, previousScrollHeight, nextScrollHeight) {
81
+ return (previousScrollTop + Math.max(0, nextScrollHeight - previousScrollHeight));
82
+ }
83
+ function MessageScrollerCommandSync({ signal }) {
84
+ const { scrollToEnd } = useMessageScroller();
85
+ const previousSignalRef = useRef(signal);
86
+ useEffect(() => {
87
+ if (previousSignalRef.current === signal)
88
+ return;
89
+ previousSignalRef.current = signal;
90
+ scrollToEnd({ behavior: 'auto' });
91
+ }, [scrollToEnd, signal]);
92
+ return null;
93
+ }
94
+ function getNavigationLabel(message) {
95
+ const text = message.content ??
96
+ message.parts
97
+ ?.flatMap((part) => (part.type === 'text' ? [part.text] : []))
98
+ .join(' ');
99
+ const normalized = text?.replace(/\s+/g, ' ').trim() || 'User message';
100
+ return normalized.length > 56 ? `${normalized.slice(0, 53)}...` : normalized;
101
+ }
102
+ function MessageNavigationTrail({ items }) {
103
+ const { scrollToMessage } = useMessageScroller();
104
+ const { currentAnchorId } = useMessageScrollerVisibility();
105
+ const anchors = useMemo(() => items.flatMap((item) => item.kind === 'message' && item.message.role === 'user'
106
+ ? [{ id: item.key, label: getNavigationLabel(item.message) }]
107
+ : []), [items]);
108
+ if (anchors.length < 2)
109
+ return null;
110
+ return (_jsx("div", { "data-fullscreen-message-navigation": true, className: "absolute bottom-8 left-3 top-8 z-20 flex w-9 items-center", children: _jsx(TooltipProvider, { delayDuration: 250, children: _jsx("nav", { "aria-label": "Conversation turns", className: "flex max-h-full w-full flex-col items-start overflow-y-auto py-2 [scrollbar-width:none]", children: _jsx("div", { "data-message-navigation-list": true, className: "my-auto flex w-full shrink-0 flex-col items-start", children: anchors.map((anchor) => {
111
+ const isCurrent = anchor.id === currentAnchorId;
112
+ return (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { type: "button", "aria-current": isCurrent ? 'location' : undefined, "aria-label": `Jump to: ${anchor.label}`, onClick: () => scrollToMessage(anchor.id, {
113
+ align: 'start',
114
+ behavior: 'smooth',
115
+ scrollMargin: 64,
116
+ }), "data-message-navigation-row": true, className: "flex h-2.5 w-9 shrink-0 cursor-pointer items-center outline-none", children: _jsx("span", { className: "flex h-0.5 w-[30px] items-center", children: _jsx("span", { "data-message-navigation-marker": true, className: cn('bg-muted-foreground h-0.5 w-[26px] origin-left rounded-full opacity-40', isCurrent && 'bg-foreground opacity-60') }) }) }) }), _jsx(TooltipContent, { side: "right", className: "max-w-72", children: anchor.label })] }, anchor.id));
117
+ }) }) }) }) }));
118
+ }
119
+ function ChatMessageViewport({ items, renderItem, toolProgress, onApprovalResponse, currentConversationId, scrollToBottomSignal, isBusy, hasOlderMessages = false, isLoadingOlderMessages = false, onLoadOlderMessages, showNavigationTrail = false, scrollAreaClassName, contentClassName, scrollButtonClassName, }) {
120
+ const viewportRef = useRef(null);
121
+ const loadingOlderRef = useRef(false);
122
+ const handleViewportScroll = useCallback((event) => {
123
+ const viewport = event.currentTarget;
124
+ if (viewport.scrollTop > 64 ||
125
+ !hasOlderMessages ||
126
+ isLoadingOlderMessages ||
127
+ loadingOlderRef.current ||
128
+ !onLoadOlderMessages) {
129
+ return;
130
+ }
131
+ loadingOlderRef.current = true;
132
+ const previousScrollHeight = viewport.scrollHeight;
133
+ const previousScrollTop = viewport.scrollTop;
134
+ void onLoadOlderMessages()
135
+ .then((outcome) => {
136
+ window.requestAnimationFrame(() => {
137
+ if (viewportRef.current !== viewport)
138
+ return;
139
+ if (outcome === 'reset') {
140
+ viewport.scrollTop = viewport.scrollHeight;
141
+ }
142
+ else if (outcome === 'prepended') {
143
+ viewport.scrollTop = getPrependPreservedScrollTop(previousScrollTop, previousScrollHeight, viewport.scrollHeight);
144
+ }
145
+ });
146
+ })
147
+ .finally(() => {
148
+ window.requestAnimationFrame(() => {
149
+ loadingOlderRef.current = false;
150
+ });
151
+ });
152
+ }, [hasOlderMessages, isLoadingOlderMessages, onLoadOlderMessages]);
153
+ return (_jsx(MessageScrollerProvider, { autoScroll: true, defaultScrollPosition: "end", scrollPreviousItemPeek: 64, children: _jsxs(MessageScroller, { className: "relative min-h-0 min-w-0 flex-1", children: [_jsx(MessageScrollerCommandSync, { signal: scrollToBottomSignal }), _jsx(MessageScrollerViewport, { ref: viewportRef, className: scrollAreaClassName, "data-message-scroll-fade": true, "data-has-older-messages": hasOlderMessages ? 'true' : 'false', onScroll: handleViewportScroll, children: _jsx(MessageScrollerContent, { "aria-busy": isBusy || isLoadingOlderMessages, className: contentClassName, children: _jsx(ToolProgressProvider, { value: toolProgress, children: _jsx(ToolApprovalProvider, { onApprovalResponse: onApprovalResponse ?? null, children: items.map((item) => (_jsx(MessageScrollerItem, { messageId: item.key, scrollAnchor: item.kind === 'message' && item.message.role === 'user', children: renderItem(item) }, item.key))) }) }) }) }), items.length > 0 && (_jsx(MessageScrollerButton, { className: scrollButtonClassName })), showNavigationTrail && _jsx(MessageNavigationTrail, { items: items })] }) }, currentConversationId ?? 'new-conversation'));
154
+ }
22
155
  function clampPercent(value) {
23
156
  if (!Number.isFinite(value))
24
157
  return 0;
@@ -32,7 +165,16 @@ function formatTokenCount(tokens) {
32
165
  const millions = tokens / 1_000_000;
33
166
  return `${Number.isInteger(millions) ? millions.toFixed(0) : millions.toFixed(2)}M`;
34
167
  }
35
- function ContextWindowIndicator({ usage }) {
168
+ function formatUsageReset(resetAt) {
169
+ if (!resetAt)
170
+ return null;
171
+ return new Intl.DateTimeFormat(undefined, {
172
+ weekday: 'short',
173
+ hour: 'numeric',
174
+ minute: '2-digit',
175
+ }).format(new Date(resetAt * 1_000));
176
+ }
177
+ function ContextWindowIndicator({ usage, planUsage, }) {
36
178
  if (!usage || usage.maxTokens <= 0)
37
179
  return null;
38
180
  const usedPercent = clampPercent(Math.round((usage.usedTokens / usage.maxTokens) * 100));
@@ -41,9 +183,15 @@ function ContextWindowIndicator({ usage }) {
41
183
  : usedPercent >= 75
42
184
  ? 'var(--warning)'
43
185
  : 'var(--muted-foreground)';
44
- return (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { type: "button", className: "text-muted-foreground hover:text-foreground focus-visible:ring-ring flex size-8 cursor-pointer items-center justify-center rounded-full bg-transparent p-0 focus-visible:outline-none focus-visible:ring-2", "aria-label": `Context window ${usedPercent}% full`, children: _jsx("span", { className: "relative size-4 rounded-full", style: {
186
+ return (_jsxs(Popover, { children: [_jsx(PopoverTrigger, { asChild: true, children: _jsx("button", { type: "button", className: "text-muted-foreground hover:text-foreground focus-visible:ring-ring flex size-8 cursor-pointer items-center justify-center rounded-full bg-transparent p-0 focus-visible:outline-none focus-visible:ring-2", "aria-label": `Context window ${usedPercent}% full`, children: _jsx("span", { className: "relative size-4 rounded-full", style: {
45
187
  background: `conic-gradient(${ringColor} ${usedPercent}%, color-mix(in oklch, var(--muted-foreground) 22%, transparent) 0)`,
46
- }, children: _jsx("span", { className: "bg-background absolute inset-[3px] rounded-full" }) }) }) }), _jsxs(TooltipContent, { align: "end", side: "top", sideOffset: 8, className: "w-56 px-3 py-2.5 text-center shadow-lg", children: [_jsx("div", { className: "opacity-70", children: "Context window:" }), _jsxs("div", { className: "mt-1 text-sm font-medium", children: [usedPercent, "% full"] }), _jsxs("div", { className: "mt-1 text-xs", children: [formatTokenCount(usage.usedTokens), " /", ' ', formatTokenCount(usage.maxTokens), " tokens used"] }), usage.compactsAutomatically && (_jsx("div", { className: "mt-2.5 text-xs font-medium leading-4", children: "Moldable automatically compacts its context" }))] })] }));
188
+ }, children: _jsx("span", { className: "bg-background absolute inset-[3px] rounded-full" }) }) }) }), _jsxs(PopoverContent, { align: "end", side: "top", sideOffset: 8, className: "w-80 p-3 shadow-lg", children: [_jsxs("div", { className: "flex items-center justify-between gap-3 text-sm", children: [_jsx("span", { className: "text-muted-foreground", children: "Context window" }), _jsxs("span", { children: [formatTokenCount(usage.usedTokens), " /", ' ', formatTokenCount(usage.maxTokens), " (", usedPercent, "%)"] })] }), _jsx("div", { className: "bg-muted mt-2 h-1.5 overflow-hidden rounded-full", children: _jsx("div", { className: "bg-primary h-full rounded-full", style: { width: `${usedPercent}%` } }) }), usage.compactsAutomatically && (_jsx("div", { className: "text-muted-foreground mt-2 text-[11px] leading-4", children: "Moldable automatically compacts its context" })), planUsage && planUsage.windows.length > 0 && (_jsxs("div", { className: "border-border mt-3 flex flex-col gap-3 border-t pt-3", children: [_jsxs("div", { children: [_jsxs("div", { className: "text-muted-foreground text-xs", children: ["Plan usage limits", planUsage.planLabel ? ` · ${planUsage.planLabel}` : ''] }), planUsage.accountLabel && (_jsx("div", { className: "mt-0.5 truncate text-xs font-medium", children: planUsage.accountLabel }))] }), planUsage.windows.map((window) => {
189
+ const reset = formatUsageReset(window.resetAt);
190
+ const percent = clampPercent(window.usedPercent);
191
+ return (_jsxs("div", { className: "flex flex-col gap-1", children: [_jsxs("div", { className: "flex items-center justify-between gap-3 text-xs", children: [_jsx("span", { children: window.label }), _jsxs("span", { className: "text-muted-foreground", children: [reset ? `Resets ${reset} · ` : '', percent, "%"] })] }), _jsx("div", { className: "bg-muted h-1.5 overflow-hidden rounded-full", children: _jsx("div", { className: percent >= 90
192
+ ? 'bg-destructive h-full rounded-full'
193
+ : 'bg-primary h-full rounded-full', style: { width: `${percent}%` } }) })] }, window.label));
194
+ })] }))] })] }));
47
195
  }
48
196
  function ContextCompactedDivider() {
49
197
  return (_jsx("div", { "data-testid": "context-compacted-divider", className: "text-muted-foreground/80 w-full px-4 py-2", children: _jsxs("div", { className: "flex items-center gap-3", children: [_jsx("div", { className: "bg-border h-px min-w-8 flex-1" }), _jsxs("div", { className: "flex select-none items-center gap-2 whitespace-nowrap text-[13px] font-medium leading-5", children: [_jsx(ClipboardList, { className: "size-4" }), _jsx("span", { children: "Context automatically compacted" })] }), _jsx("div", { className: "bg-border h-px min-w-8 flex-1" })] }) }));
@@ -73,19 +221,10 @@ function QueuedMessageRow({ message, isResponding, onRetryQueuedMessage, onSteer
73
221
  /**
74
222
  * Floating chat panel with model selector
75
223
  */
76
- export function ChatPanel({ messages, status, isTurnInFlight, input, onInputChange, onSubmit, onStop, onNewChat, models, selectedModel, onModelChange, reasoningEffortOptions, selectedReasoningEffort, onReasoningEffortChange, conversations, currentConversationId, scrollToBottomSignal = 0, onSelectConversation, onDeleteConversation, placeholder = 'Ask anything...', welcomeMessage, isExpanded, onExpandedChange, isMinimized = false, onMinimizedChange, className, error, missingApiKey, onAddApiKey, toolProgress = {}, onApprovalResponse, isEditingApp = true, onEditingAppChange, showEditingAppToggle = false, checkpoints, restoringMessageId, onRestoreCheckpoint, imageAttachments = [], onRemoveImageAttachment, isImageDropActive = false, queuedMessages = [], onRemoveQueuedMessage, onRetryQueuedMessage, onSteerQueuedMessage, onReorderQueuedMessages, onEditQueuedMessage, slashCommands, onSlashCommandSelect, isCompacting = false, compactedHistoryStartIndex, contextUsage, }) {
224
+ export function ChatPanel({ messages, status, isTurnInFlight, input, onInputChange, onSubmit, onStop, onNewChat, modelProviders, modelEffortPresets, selectedModel, selectedReasoningEffort, onModelEffortChange, conversations, currentConversationId, currentAppId, hasMoreConversations = false, isLoadingMoreConversations = false, onLoadMoreConversations, onResolveMessageContent, scrollToBottomSignal = 0, hasOlderMessages = false, isLoadingOlderMessages = false, onLoadOlderMessages, onSelectConversation, onArchiveConversation, onArchiveConversationGroup, placeholder = 'Ask anything...', welcomeMessage, isExpanded, onExpandedChange, isFullScreen = false, onFullScreenChange, isMinimized = false, onMinimizedChange, className, error, onRetryError, missingApiKey, authIssue, onConnectChatGPT, onAdvancedSetup, toolProgress = {}, onApprovalResponse, isEditingApp = true, onEditingAppChange, showEditingAppToggle = false, checkpoints, restoringMessageId, onRestoreCheckpoint, imageAttachments = [], onRemoveImageAttachment, isImageDropActive = false, queuedMessages = [], onRemoveQueuedMessage, onRetryQueuedMessage, onSteerQueuedMessage, onReorderQueuedMessages, onEditQueuedMessage, slashCommands, onSlashCommandSelect, isCompacting = false, compactedHistoryStartIndex, contextUsage, planUsage, }) {
77
225
  const inputRef = useRef(null);
78
- const scrollAreaRef = useRef(null);
79
- const viewportRef = useRef(null);
80
- const virtualizerRef = useRef(null);
81
- const prevMessageCountRef = useRef(messages.length);
82
- const prevConversationIdRef = useRef(currentConversationId ?? null);
83
- const prevScrollToBottomSignalRef = useRef(scrollToBottomSignal);
84
- const pendingConversationScrollIdRef = useRef(null);
85
- const hasPendingScrollToBottomSignalRef = useRef(false);
86
- const scrollRafRef = useRef(null);
87
- const [viewportVersion, setViewportVersion] = useState(0);
88
- const [isAtBottom, setIsAtBottom] = useState(true);
226
+ const fullScreenTriggerRef = useRef(null);
227
+ const [isConnectingChatGPT, setIsConnectingChatGPT] = useState(false);
89
228
  const queuedMessageIds = useMemo(() => queuedMessages.map((message) => message.id), [queuedMessages]);
90
229
  const queueSensors = useSensors(useSensor(PointerSensor, {
91
230
  activationConstraint: {
@@ -96,57 +235,31 @@ export function ChatPanel({ messages, status, isTurnInFlight, input, onInputChan
96
235
  }));
97
236
  const isResponding = status === 'streaming' || status === 'submitted';
98
237
  const controlsDisabled = isTurnInFlight ?? isResponding;
99
- const composerControls = (_jsxs(_Fragment, { children: [_jsx(ContextWindowIndicator, { usage: contextUsage }), _jsx(ModelSelector, { models: models, selectedModel: selectedModel, onModelChange: onModelChange, disabled: controlsDisabled, dropdownAlign: "end", dropdownSide: "top" }), reasoningEffortOptions &&
100
- selectedReasoningEffort &&
101
- onReasoningEffortChange && (_jsx(ReasoningEffortSelector, { options: reasoningEffortOptions, selectedEffort: selectedReasoningEffort, onEffortChange: onReasoningEffortChange, disabled: controlsDisabled, showLabel: true, dropdownAlign: "end", dropdownSide: "top" }))] }));
102
- // Capture the Radix viewport element so virtua can use it as the scroll container
103
- useEffect(() => {
104
- const scrollArea = scrollAreaRef.current;
105
- if (!scrollArea)
106
- return;
107
- const viewport = scrollArea.querySelector('[data-radix-scroll-area-viewport]');
108
- if (!viewport)
109
- return;
110
- viewport.style.overflowAnchor = 'none';
111
- if (viewportRef.current !== viewport) {
112
- viewportRef.current = viewport;
113
- setViewportVersion((version) => version + 1);
114
- }
115
- }, [isExpanded]);
116
- // Track scroll position to detect if user is at bottom
117
- useEffect(() => {
118
- const viewport = viewportRef.current;
119
- if (!viewport)
120
- return;
121
- const handleScroll = () => {
122
- const { scrollTop, scrollHeight, clientHeight } = viewport;
123
- // Consider "at bottom" if within 50px of the bottom
124
- const atBottom = scrollHeight - scrollTop - clientHeight < 50;
125
- setIsAtBottom(atBottom);
126
- };
127
- handleScroll();
128
- viewport.addEventListener('scroll', handleScroll);
129
- return () => viewport.removeEventListener('scroll', handleScroll);
130
- }, [viewportVersion]);
238
+ const isChatOpen = isExpanded || isFullScreen;
239
+ const composerControls = (_jsxs(_Fragment, { children: [_jsx(ContextWindowIndicator, { usage: contextUsage, planUsage: planUsage }), modelProviders.length > 0 && modelEffortPresets.length > 0 ? (_jsx(ModelEffortSelector, { providers: modelProviders, presets: modelEffortPresets, selectedModel: selectedModel, selectedReasoningEffort: selectedReasoningEffort, onSelectionChange: onModelEffortChange, disabled: controlsDisabled })) : null] }));
131
240
  // Focus input when expanded
132
241
  useEffect(() => {
133
- if (isExpanded) {
242
+ if (isChatOpen) {
134
243
  const timer = setTimeout(() => {
135
244
  inputRef.current?.focus();
136
245
  }, 200);
137
246
  return () => clearTimeout(timer);
138
247
  }
139
- }, [isExpanded]);
140
- const showMissingApiKeyPrompt = missingApiKey ||
141
- (error &&
142
- (error.message?.includes('API_KEY not configured') ||
143
- error.message?.includes('credential required in Vault') ||
144
- error.message?.includes('credential not configured in Vault')));
145
- const submitDisabled = Boolean(showMissingApiKeyPrompt);
248
+ }, [isChatOpen]);
249
+ const resolvedAuthIssue = resolveChatAuthIssue({
250
+ missingApiKey,
251
+ authIssue,
252
+ error,
253
+ });
254
+ const authPromptCopy = resolvedAuthIssue
255
+ ? getChatAuthPromptCopy(resolvedAuthIssue)
256
+ : null;
257
+ const showAuthPrompt = Boolean(resolvedAuthIssue);
258
+ const submitDisabled = showAuthPrompt;
146
259
  const handleSubmit = useCallback((e, mode) => {
147
260
  e?.preventDefault();
148
261
  if (submitDisabled) {
149
- if (!isExpanded) {
262
+ if (!isChatOpen) {
150
263
  onExpandedChange(true);
151
264
  }
152
265
  return;
@@ -154,17 +267,15 @@ export function ChatPanel({ messages, status, isTurnInFlight, input, onInputChan
154
267
  if (!input.trim() && imageAttachments.length === 0)
155
268
  return;
156
269
  const submitMode = mode ?? (isResponding ? 'queue' : 'send');
157
- if (!isExpanded) {
270
+ if (!isChatOpen) {
158
271
  onExpandedChange(true);
159
272
  }
160
- // Reset to bottom when user sends a message
161
- setIsAtBottom(true);
162
273
  onSubmit(e, submitMode);
163
274
  }, [
164
275
  imageAttachments.length,
165
276
  input,
166
277
  isResponding,
167
- isExpanded,
278
+ isChatOpen,
168
279
  onExpandedChange,
169
280
  onSubmit,
170
281
  submitDisabled,
@@ -177,50 +288,79 @@ export function ChatPanel({ messages, status, isTurnInFlight, input, onInputChan
177
288
  }, [onReorderQueuedMessages]);
178
289
  const handleEditQueuedMessage = useCallback((id) => {
179
290
  onEditQueuedMessage?.(id);
180
- if (!isExpanded) {
291
+ if (!isChatOpen) {
181
292
  onExpandedChange(true);
182
293
  }
183
294
  window.setTimeout(() => inputRef.current?.focus(), 0);
184
- }, [isExpanded, onEditQueuedMessage, onExpandedChange]);
295
+ }, [isChatOpen, onEditQueuedMessage, onExpandedChange]);
185
296
  const handleNewChat = useCallback(() => {
186
297
  onNewChat?.();
187
298
  inputRef.current?.focus();
188
299
  }, [onNewChat]);
300
+ const handleConnectChatGPT = useCallback(async () => {
301
+ if (!onConnectChatGPT || isConnectingChatGPT)
302
+ return;
303
+ setIsConnectingChatGPT(true);
304
+ try {
305
+ await onConnectChatGPT();
306
+ }
307
+ catch (error) {
308
+ console.error('Failed to connect ChatGPT:', error);
309
+ }
310
+ finally {
311
+ setIsConnectingChatGPT(false);
312
+ }
313
+ }, [isConnectingChatGPT, onConnectChatGPT]);
314
+ const editingAppControl = showEditingAppToggle && onEditingAppChange ? (_jsx(TooltipProvider, { children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx(Button, { type: "button", variant: "ghost", size: "icon-sm", onClick: (event) => {
315
+ event.preventDefault();
316
+ onEditingAppChange(!isEditingApp);
317
+ }, className: cn('cursor-pointer', isEditingApp
318
+ ? 'text-primary bg-primary/10 hover:bg-primary/20'
319
+ : 'text-muted-foreground hover:text-foreground'), children: _jsx(Code2, { className: "size-4" }) }) }), _jsx(TooltipContent, { side: "top", children: _jsx("p", { children: isEditingApp
320
+ ? 'Editing this app (click to disable)'
321
+ : 'Not editing app (click to enable)' }) })] }) })) : null;
189
322
  const composerStartControls = (_jsxs(_Fragment, { children: [conversations &&
190
323
  (conversations.length > 0 || onNewChat) &&
191
- onSelectConversation && (_jsx(ConversationHistory, { conversations: conversations, currentConversationId: currentConversationId, onSelect: onSelectConversation, onDelete: onDeleteConversation, onNewChat: handleNewChat, newChatDisabled: controlsDisabled, disabled: controlsDisabled, dropdownAlign: "start", dropdownSide: "top", tooltipSide: "top" })), showEditingAppToggle && onEditingAppChange && (_jsx(TooltipProvider, { children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx(Button, { type: "button", variant: "ghost", size: "icon-sm", onClick: (event) => {
192
- event.preventDefault();
193
- onEditingAppChange(!isEditingApp);
194
- }, className: cn('cursor-pointer', isEditingApp
195
- ? 'text-primary bg-primary/10 hover:bg-primary/20'
196
- : 'text-muted-foreground hover:text-foreground'), children: _jsx(Code2, { className: "size-4" }) }) }), _jsx(TooltipContent, { side: "top", children: _jsx("p", { children: isEditingApp
197
- ? 'Editing this app (click to disable)'
198
- : 'Not editing app (click to enable)' }) })] }) }))] }));
324
+ onSelectConversation && (_jsx(ConversationHistory, { conversations: conversations, currentConversationId: currentConversationId, currentAppId: currentAppId, onSelect: onSelectConversation, onArchive: onArchiveConversation, onArchiveGroup: onArchiveConversationGroup, onNewChat: handleNewChat, newChatDisabled: false, disabled: false, dropdownAlign: "start", dropdownSide: "top", tooltipSide: "top", hasMoreConversations: hasMoreConversations, isLoadingMoreConversations: isLoadingMoreConversations, onLoadMoreConversations: onLoadMoreConversations })), editingAppControl] }));
199
325
  // Keyboard shortcut: Cmd+Shift+O for new chat
200
326
  useEffect(() => {
201
327
  const handleKeyDown = (e) => {
202
328
  if (e.key === 'o' && e.metaKey && e.shiftKey) {
203
329
  e.preventDefault();
204
330
  // Only create new chat if conversation controls are currently available.
205
- if (!controlsDisabled && isExpanded) {
331
+ if (isChatOpen) {
206
332
  handleNewChat();
207
333
  }
208
334
  }
209
335
  };
210
336
  document.addEventListener('keydown', handleKeyDown);
211
337
  return () => document.removeEventListener('keydown', handleKeyDown);
212
- }, [controlsDisabled, isExpanded, handleNewChat]);
338
+ }, [isChatOpen, handleNewChat]);
213
339
  // Handle minimize button - now goes to minimized state
214
340
  const handleMinimize = useCallback(() => {
341
+ if (isFullScreen) {
342
+ onFullScreenChange?.(false);
343
+ }
215
344
  if (isExpanded) {
216
345
  onExpandedChange(false);
217
346
  }
218
347
  onMinimizedChange?.(true);
219
- }, [isExpanded, onExpandedChange, onMinimizedChange]);
348
+ }, [
349
+ isExpanded,
350
+ isFullScreen,
351
+ onExpandedChange,
352
+ onFullScreenChange,
353
+ onMinimizedChange,
354
+ ]);
220
355
  const isStreaming = status === 'streaming' || status === 'submitted';
221
356
  const isThinking = useMemo(() => computeIsThinking(messages, status), [messages, status]);
222
- const showErrorMessage = Boolean(error) && status === 'error' && !showMissingApiKeyPrompt;
223
- const lastMessageId = messages[messages.length - 1]?.id;
357
+ const showErrorMessage = Boolean(error) &&
358
+ status === 'error' &&
359
+ !showAuthPrompt &&
360
+ !hasPersistedChatError(messages);
361
+ const lastMessageKey = messages.length > 0
362
+ ? getChatMessageRenderKey(messages[messages.length - 1], messages.length - 1)
363
+ : null;
224
364
  const listItems = useMemo(() => {
225
365
  const items = [];
226
366
  if (messages.length === 0 && welcomeMessage) {
@@ -236,7 +376,11 @@ export function ChatPanel({ messages, status, isTurnInFlight, input, onInputChan
236
376
  kind: 'context-compacted-divider',
237
377
  });
238
378
  }
239
- items.push({ key: message.id, kind: 'message', message });
379
+ items.push({
380
+ key: getChatMessageRenderKey(message, index),
381
+ kind: 'message',
382
+ message,
383
+ });
240
384
  }
241
385
  if (isThinking && !isCompacting) {
242
386
  items.push({ key: 'thinking', kind: 'thinking' });
@@ -244,9 +388,6 @@ export function ChatPanel({ messages, status, isTurnInFlight, input, onInputChan
244
388
  if (isCompacting) {
245
389
  items.push({ key: 'compacting', kind: 'compacting' });
246
390
  }
247
- if (showMissingApiKeyPrompt) {
248
- items.push({ key: 'missing-api-key', kind: 'missing-api-key' });
249
- }
250
391
  if (showErrorMessage) {
251
392
  items.push({ key: 'error', kind: 'error' });
252
393
  }
@@ -257,7 +398,6 @@ export function ChatPanel({ messages, status, isTurnInFlight, input, onInputChan
257
398
  compactedHistoryStartIndex,
258
399
  messages,
259
400
  showErrorMessage,
260
- showMissingApiKeyPrompt,
261
401
  welcomeMessage,
262
402
  ]);
263
403
  const renderVirtualItem = useCallback((item) => {
@@ -268,92 +408,43 @@ export function ChatPanel({ messages, status, isTurnInFlight, input, onInputChan
268
408
  return (_jsx("div", { className: "px-2 pb-3", children: _jsx(ContextCompactedDivider, {}) }));
269
409
  case 'message': {
270
410
  const checkpoint = checkpoints?.get(item.message.id);
271
- return (_jsx("div", { className: "px-2 pb-3", children: _jsx(MessageRow, { message: item.message, isLast: item.message.id === lastMessageId, isStreaming: isStreaming, checkpoint: checkpoint, restoringMessageId: restoringMessageId, onRestoreCheckpoint: onRestoreCheckpoint }) }));
411
+ return (_jsx("div", { className: "px-2 pb-3", children: _jsx(MessageRow, { message: item.message, isLast: item.key === lastMessageKey, isStreaming: isStreaming, checkpoint: checkpoint, restoringMessageId: restoringMessageId, onRestoreCheckpoint: onRestoreCheckpoint, onResolveMessageContent: onResolveMessageContent, onRetryError: item.key === lastMessageKey ? onRetryError : undefined }) }));
272
412
  }
273
413
  case 'thinking':
274
414
  return (_jsx("div", { className: "px-2 pb-3", children: _jsx(ThinkingMessage, {}) }));
275
415
  case 'compacting':
276
416
  return (_jsx("div", { className: "px-2 pb-3", children: _jsx(CompactingMessage, {}) }));
277
- case 'missing-api-key':
278
- return (_jsx("div", { className: "px-2 pb-4", children: _jsxs("div", { className: "border-primary/30 bg-primary/5 mx-2 flex flex-col items-center gap-3 rounded-lg border p-4 text-center", children: [_jsx("div", { className: "bg-primary/10 flex size-10 items-center justify-center rounded-full", children: _jsx(AlertCircle, { className: "text-primary size-5" }) }), _jsxs("div", { children: [_jsx("p", { className: "text-foreground font-medium", children: "API key required" }), _jsx("p", { className: "text-muted-foreground mt-1 text-sm", children: "Add an API key to Vault to start chatting with AI" })] }), onAddApiKey && (_jsx(Button, { onClick: onAddApiKey, size: "sm", className: "cursor-pointer", children: "Add API key" }))] }) }));
279
417
  case 'error':
280
- return (_jsx("div", { className: "px-2 pb-4", children: error && (_jsxs("div", { className: "border-destructive/30 bg-destructive/10 text-destructive mx-2 flex items-start gap-2 rounded-lg border p-3 text-sm", children: [_jsx(AlertCircle, { className: "mt-0.5 size-4 shrink-0" }), _jsxs("div", { className: "min-w-0", children: [_jsx("p", { className: "font-medium", children: "Request failed" }), _jsx("p", { className: "text-destructive/80 mt-0.5 break-words", children: error.message || 'An unknown error occurred' })] })] })) }));
418
+ return (_jsx("div", { className: "px-2 pb-4", children: error && (_jsxs("div", { className: "border-destructive/30 bg-destructive/10 text-destructive mx-2 flex items-start gap-2 rounded-lg border p-3 text-sm", children: [_jsx(AlertCircle, { className: "mt-0.5 size-4 shrink-0" }), _jsxs("div", { className: "min-w-0", children: [_jsx("p", { className: "font-medium", children: "Request failed" }), _jsx("p", { className: "text-destructive/80 mt-0.5 break-words", children: error.message || 'An unknown error occurred' }), onRetryError && (_jsxs("button", { type: "button", onClick: onRetryError, className: "border-destructive/30 hover:bg-destructive/10 mt-2 inline-flex h-7 cursor-pointer items-center gap-1.5 rounded-md border px-2.5 text-xs font-medium transition-colors", children: [_jsx(RotateCcw, { className: "size-3.5" }), "Retry"] }))] })] })) }));
281
419
  }
282
420
  }, [
283
421
  checkpoints,
284
422
  error,
285
423
  isStreaming,
286
- lastMessageId,
424
+ lastMessageKey,
287
425
  messages.length,
288
- onAddApiKey,
289
426
  onRestoreCheckpoint,
427
+ onResolveMessageContent,
428
+ onRetryError,
290
429
  restoringMessageId,
291
430
  welcomeMessage,
292
431
  ]);
293
- const scrollToBottom = useCallback((smooth = true) => {
294
- const lastIndex = listItems.length - 1;
295
- if (lastIndex < 0)
296
- return;
297
- if (scrollRafRef.current !== null) {
298
- cancelAnimationFrame(scrollRafRef.current);
299
- }
300
- setIsAtBottom(true);
301
- scrollRafRef.current = requestAnimationFrame(() => {
302
- virtualizerRef.current?.scrollToIndex(lastIndex, {
303
- align: 'end',
304
- smooth,
305
- });
306
- scrollRafRef.current = null;
307
- });
308
- }, [listItems.length]);
309
- // New conversations loaded from history should start at the latest message.
310
- useEffect(() => {
311
- const previousConversationId = prevConversationIdRef.current;
312
- const nextConversationId = currentConversationId ?? null;
313
- prevConversationIdRef.current = nextConversationId;
314
- if (previousConversationId !== nextConversationId) {
315
- pendingConversationScrollIdRef.current = nextConversationId;
316
- setIsAtBottom(true);
317
- }
318
- if (!nextConversationId ||
319
- pendingConversationScrollIdRef.current !== nextConversationId ||
320
- !isExpanded ||
321
- listItems.length === 0) {
322
- return;
323
- }
324
- scrollToBottom(false);
325
- pendingConversationScrollIdRef.current = null;
326
- }, [currentConversationId, isExpanded, listItems.length, scrollToBottom]);
327
- useEffect(() => {
328
- if (prevScrollToBottomSignalRef.current !== scrollToBottomSignal) {
329
- prevScrollToBottomSignalRef.current = scrollToBottomSignal;
330
- hasPendingScrollToBottomSignalRef.current = true;
331
- setIsAtBottom(true);
332
- }
333
- if (!hasPendingScrollToBottomSignalRef.current ||
334
- !isExpanded ||
335
- listItems.length === 0) {
336
- return;
337
- }
338
- scrollToBottom(false);
339
- hasPendingScrollToBottomSignalRef.current = false;
340
- }, [isExpanded, listItems.length, scrollToBottom, scrollToBottomSignal]);
341
- // Scroll to bottom on new messages if the user is already at bottom
342
- useEffect(() => {
343
- const previousMessageCount = prevMessageCountRef.current;
344
- const hasNewMessage = messages.length > previousMessageCount;
345
- prevMessageCountRef.current = messages.length;
346
- if (!isExpanded || !isAtBottom) {
347
- return;
348
- }
349
- scrollToBottom(hasNewMessage);
350
- return () => {
351
- if (scrollRafRef.current !== null) {
352
- cancelAnimationFrame(scrollRafRef.current);
353
- scrollRafRef.current = null;
354
- }
355
- };
356
- }, [isAtBottom, isExpanded, messages.length, scrollToBottom]);
432
+ if (isFullScreen && !isMinimized) {
433
+ const selectedConversation = conversations?.find((conversation) => conversation.id === currentConversationId);
434
+ return (_jsx(Dialog, { open: true, onOpenChange: () => undefined, children: _jsxs(DialogContent, { "data-moldable-chat-fullscreen": true, "data-chat-drop-target": true, showCloseButton: false, "aria-describedby": undefined, onInteractOutside: (event) => {
435
+ if (isToastInteractionTarget(event.target)) {
436
+ event.preventDefault();
437
+ }
438
+ }, onEscapeKeyDown: (event) => {
439
+ event.preventDefault();
440
+ onFullScreenChange?.(false);
441
+ }, onCloseAutoFocus: (event) => {
442
+ event.preventDefault();
443
+ window.requestAnimationFrame(() => {
444
+ fullScreenTriggerRef.current?.focus();
445
+ });
446
+ }, className: "bottom-1 left-1 right-1 top-1 z-50 flex h-auto w-auto max-w-none translate-x-0 translate-y-0 gap-0 overflow-hidden rounded-lg border-0 p-0 sm:max-w-none", children: [_jsx("div", { "data-tauri-drag-region": true, className: "absolute inset-x-0 top-0 z-20 h-9", "aria-hidden": "true" }), isImageDropActive && (_jsxs("div", { className: "bg-background/90 border-primary/50 text-foreground absolute inset-0 z-50 flex flex-col items-center justify-center gap-2 rounded-[inherit] border-2 border-dashed backdrop-blur-sm", children: [_jsx(ImageIcon, { className: "text-primary size-7" }), _jsxs("div", { className: "text-center", children: [_jsx("p", { className: "text-sm font-medium", children: "Drop images to attach" }), _jsx("p", { className: "text-muted-foreground text-xs", children: "They stay on disk and are read when sent" })] })] })), _jsxs("aside", { className: "border-border bg-muted/50 relative z-10 flex w-[280px] shrink-0 flex-col overflow-hidden rounded-r-lg border-r px-3 pb-4 pt-11", children: [_jsxs("button", { type: "button", onClick: () => onFullScreenChange?.(false), className: "text-muted-foreground hover:text-foreground mb-4 flex h-8 cursor-pointer items-center gap-2 rounded-lg px-2 text-sm transition-colors", children: [_jsx(Minimize2, { className: "size-4" }), "Back to app"] }), _jsx(ConversationSidebar, { conversations: conversations ?? [], currentConversationId: currentConversationId, currentAppId: currentAppId, onSelect: onSelectConversation ?? (() => undefined), onArchive: onArchiveConversation, onArchiveGroup: onArchiveConversationGroup, onNewChat: handleNewChat, newChatDisabled: false, hideScrollbar: true, disabled: false, hasMoreConversations: hasMoreConversations, isLoadingMoreConversations: isLoadingMoreConversations, onLoadMoreConversations: onLoadMoreConversations, className: "min-h-0 flex-1" })] }), _jsxs("section", { className: "relative flex min-w-0 flex-1 flex-col", children: [_jsxs("header", { className: "border-border flex h-14 shrink-0 items-center justify-between border-b px-5", children: [_jsx(DialogTitle, { className: "truncate text-sm font-medium", children: selectedConversation?.title ?? 'New conversation' }), _jsx(TooltipProvider, { children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx(Button, { variant: "ghost", size: "icon-sm", onClick: () => onFullScreenChange?.(false), "aria-label": "Exit full screen", className: "text-muted-foreground hover:text-foreground relative z-30 cursor-pointer", children: _jsx(Minimize2, { className: "size-4" }) }) }), _jsx(TooltipContent, { children: "Exit full screen" })] }) })] }), _jsx(ChatMessageViewport, { items: listItems, renderItem: renderVirtualItem, toolProgress: toolProgress, onApprovalResponse: onApprovalResponse, currentConversationId: currentConversationId, scrollToBottomSignal: scrollToBottomSignal, isBusy: isResponding, hasOlderMessages: hasOlderMessages, isLoadingOlderMessages: isLoadingOlderMessages, onLoadOlderMessages: onLoadOlderMessages, showNavigationTrail: true, contentClassName: "mx-auto w-full min-w-0 max-w-3xl overflow-hidden px-6 py-6", scrollButtonClassName: "absolute bottom-3 left-1/2 z-20 size-8 -translate-x-1/2 cursor-pointer rounded-full shadow-lg" }), authPromptCopy && (_jsx("div", { className: "mx-auto w-full max-w-3xl shrink-0 px-6 pb-2", children: _jsx(ChatAuthPrompt, { copy: authPromptCopy, isConnecting: isConnectingChatGPT, onConnect: onConnectChatGPT ? handleConnectChatGPT : undefined, onAdvancedSetup: onAdvancedSetup }) })), _jsxs("div", { className: "mx-auto w-full max-w-3xl shrink-0 px-6 pb-2", children: [queuedMessages.length > 0 && (_jsxs("div", { className: "border-border bg-muted/30 mb-2 rounded-xl border p-3", children: [_jsxs("div", { className: "text-muted-foreground mb-2 flex items-center gap-2 text-xs font-medium", children: [_jsx(ListPlus, { className: "size-3.5" }), _jsx("span", { children: "Queued follow-ups" })] }), _jsx(DndContext, { sensors: queueSensors, collisionDetection: closestCenter, onDragEnd: handleQueuedDragEnd, children: _jsx(SortableContext, { items: queuedMessageIds, strategy: verticalListSortingStrategy, children: _jsx("div", { className: "space-y-1.5", children: queuedMessages.map((message) => (_jsx(QueuedMessageRow, { message: message, isResponding: isResponding, onRetryQueuedMessage: onRetryQueuedMessage, onSteerQueuedMessage: onSteerQueuedMessage, onRemoveQueuedMessage: onRemoveQueuedMessage, onEditQueuedMessage: handleEditQueuedMessage }, message.id))) }) }) })] })), _jsx("div", { className: "bg-background overflow-hidden rounded-[24px] shadow-[0_8px_40px_-12px_rgba(0,0,0,0.2)]", children: _jsx(ChatInput, { input: input, onInputChange: onInputChange, onSubmit: handleSubmit, isResponding: isResponding, placeholder: placeholder, inputRef: inputRef, onStop: onStop, imageAttachments: imageAttachments, onRemoveImageAttachment: onRemoveImageAttachment, footerStartControls: editingAppControl, footerControls: composerControls, submitDisabled: submitDisabled, slashCommands: slashCommands, onSlashCommandSelect: onSlashCommandSelect }) })] })] })] }) }));
447
+ }
357
448
  return (_jsxs(_Fragment, { children: [_jsx(AnimatePresence, { children: isExpanded && !isMinimized && (_jsx(motion.div, { "data-moldable-chat-backdrop": true, initial: { opacity: 0 }, animate: { opacity: 1 }, exit: { opacity: 0 }, transition: { duration: 0.2 }, className: "fixed inset-0 z-40 bg-black/20", onClick: () => onExpandedChange(false) })) }), _jsx(motion.div, { "data-moldable-chat-panel": true, initial: false, animate: {
358
449
  width: isExpanded ? 'min(90vw, 640px)' : '400px',
359
450
  y: isMinimized ? 'calc(100% + 24px)' : 0,
@@ -383,7 +474,7 @@ export function ChatPanel({ messages, status, isTurnInFlight, input, onInputChan
383
474
  } })), _jsxs("div", { className: "relative z-10 overflow-hidden rounded-[inherit]", children: [_jsxs(motion.div, { initial: false, animate: {
384
475
  height: isExpanded ? 'min(60vh, 480px)' : '0px',
385
476
  opacity: isExpanded ? 1 : 0,
386
- }, transition: { type: 'tween', duration: 0.2, ease: 'easeOut' }, className: "flex flex-col overflow-hidden", style: { pointerEvents: isExpanded ? 'auto' : 'none' }, children: [_jsx("div", { className: "absolute right-3 top-3 z-20", children: _jsx(TooltipProvider, { children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx(Button, { variant: "ghost", size: "icon-sm", onClick: handleMinimize, className: "text-muted-foreground hover:text-foreground cursor-pointer", children: _jsx(ChevronDown, { className: "size-4" }) }) }), _jsx(TooltipContent, { side: "bottom", children: _jsx("p", { children: "Minimize" }) })] }) }) }), _jsxs("div", { className: "relative min-h-0 min-w-0 flex-1", children: [_jsx(ScrollArea, { ref: scrollAreaRef, className: "h-full px-2", children: _jsx("div", { className: "min-w-0 max-w-full overflow-hidden py-4 pr-10", children: _jsx(ToolProgressProvider, { value: toolProgress, children: _jsx(ToolApprovalProvider, { onApprovalResponse: onApprovalResponse ?? null, children: viewportVersion > 0 ? (_jsx(Virtualizer, { ref: virtualizerRef, data: listItems, scrollRef: viewportRef, bufferSize: 300, children: (item) => renderVirtualItem(item) }, viewportVersion)) : (listItems.map((item) => (_jsx("div", { children: renderVirtualItem(item) }, item.key)))) }) }) }) }), !isAtBottom && listItems.length > 0 && (_jsx(TooltipProvider, { children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx(Button, { type: "button", variant: "secondary", size: "icon-sm", onClick: () => scrollToBottom(true), className: "absolute bottom-3 right-4 z-20 size-8 cursor-pointer rounded-full shadow-lg", children: _jsx(ArrowDown, { className: "size-4" }) }) }), _jsx(TooltipContent, { side: "top", children: "Scroll to bottom" })] }) }))] })] }), _jsxs("div", { className: "relative z-10", onClick: () => {
477
+ }, transition: { type: 'tween', duration: 0.2, ease: 'easeOut' }, className: "flex flex-col overflow-hidden", style: { pointerEvents: isExpanded ? 'auto' : 'none' }, children: [isExpanded && !isMinimized && (_jsxs("div", { className: "absolute right-2 top-2 z-20 grid grid-cols-1 gap-0.5", "data-moldable-chat-panel-controls": true, role: "toolbar", "aria-label": "Chat view controls", "aria-orientation": "vertical", children: [onFullScreenChange && (_jsx(TooltipProvider, { children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx(Button, { ref: fullScreenTriggerRef, "data-moldable-chat-enter-fullscreen": true, variant: "ghost", size: "icon-sm", onClick: () => onFullScreenChange(true), "aria-label": "Enter full screen", className: "text-muted-foreground hover:text-foreground cursor-pointer", children: _jsx(Maximize2, { className: "size-4" }) }) }), _jsx(TooltipContent, { side: "bottom", children: "Full screen" })] }) })), _jsx(TooltipProvider, { children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx(Button, { variant: "ghost", size: "icon-sm", onClick: handleMinimize, className: "text-muted-foreground hover:text-foreground cursor-pointer", children: _jsx(ChevronDown, { className: "size-4" }) }) }), _jsx(TooltipContent, { side: "bottom", children: _jsx("p", { children: "Minimize" }) })] }) })] })), _jsx(ChatMessageViewport, { items: listItems, renderItem: renderVirtualItem, toolProgress: toolProgress, onApprovalResponse: onApprovalResponse, currentConversationId: currentConversationId, scrollToBottomSignal: scrollToBottomSignal, isBusy: isResponding, hasOlderMessages: hasOlderMessages, isLoadingOlderMessages: isLoadingOlderMessages, onLoadOlderMessages: onLoadOlderMessages, scrollAreaClassName: "px-2", contentClassName: "w-full min-w-0 max-w-full overflow-hidden py-4 pr-12", scrollButtonClassName: "absolute bottom-3 left-auto right-4 z-20 size-8 translate-x-0 cursor-pointer rounded-full shadow-lg" }), authPromptCopy && (_jsx("div", { className: "shrink-0 px-4 pb-2", children: _jsx(ChatAuthPrompt, { copy: authPromptCopy, isConnecting: isConnectingChatGPT, onConnect: onConnectChatGPT ? handleConnectChatGPT : undefined, onAdvancedSetup: onAdvancedSetup }) }))] }), _jsxs("div", { className: "relative z-10", onClick: () => {
387
478
  if (!isExpanded) {
388
479
  onExpandedChange(true);
389
480
  }