@flanksource/clicky-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 (445) hide show
  1. package/dist/ai.cjs +26 -0
  2. package/dist/ai.cjs.map +1 -0
  3. package/dist/ai.d.ts +2 -0
  4. package/dist/ai.d.ts.map +1 -0
  5. package/dist/ai.js +26 -0
  6. package/dist/ai.js.map +1 -0
  7. package/dist/chat.cjs +7 -0
  8. package/dist/chat.cjs.map +1 -1
  9. package/dist/chat.js +7 -0
  10. package/dist/chat.js.map +1 -1
  11. package/dist/components/FilterBar.cjs +49 -18
  12. package/dist/components/FilterBar.cjs.map +1 -1
  13. package/dist/components/FilterBar.d.ts +0 -2
  14. package/dist/components/FilterBar.d.ts.map +1 -1
  15. package/dist/components/FilterBar.js +50 -19
  16. package/dist/components/FilterBar.js.map +1 -1
  17. package/dist/components/SearchInput.cjs +63 -0
  18. package/dist/components/SearchInput.cjs.map +1 -0
  19. package/dist/components/SearchInput.d.ts +31 -0
  20. package/dist/components/SearchInput.d.ts.map +1 -0
  21. package/dist/components/SearchInput.js +63 -0
  22. package/dist/components/SearchInput.js.map +1 -0
  23. package/dist/components/SegmentedControl.cjs +88 -0
  24. package/dist/components/SegmentedControl.cjs.map +1 -0
  25. package/dist/components/SegmentedControl.d.ts +38 -0
  26. package/dist/components/SegmentedControl.d.ts.map +1 -0
  27. package/dist/components/SegmentedControl.js +88 -0
  28. package/dist/components/SegmentedControl.js.map +1 -0
  29. package/dist/components/Switch.cjs +51 -0
  30. package/dist/components/Switch.cjs.map +1 -0
  31. package/dist/components/Switch.d.ts +23 -0
  32. package/dist/components/Switch.d.ts.map +1 -0
  33. package/dist/components/Switch.js +51 -0
  34. package/dist/components/Switch.js.map +1 -0
  35. package/dist/components/TimeRange.cjs +53 -45
  36. package/dist/components/TimeRange.cjs.map +1 -1
  37. package/dist/components/TimeRange.d.ts.map +1 -1
  38. package/dist/components/TimeRange.js +53 -45
  39. package/dist/components/TimeRange.js.map +1 -1
  40. package/dist/components/TreePickerField.cjs +5 -1
  41. package/dist/components/TreePickerField.cjs.map +1 -1
  42. package/dist/components/TreePickerField.d.ts.map +1 -1
  43. package/dist/components/TreePickerField.js +5 -1
  44. package/dist/components/TreePickerField.js.map +1 -1
  45. package/dist/components/filter-bar-utils.cjs +5 -0
  46. package/dist/components/filter-bar-utils.cjs.map +1 -1
  47. package/dist/components/filter-bar-utils.d.ts +2 -0
  48. package/dist/components/filter-bar-utils.d.ts.map +1 -1
  49. package/dist/components/filter-bar-utils.js +5 -0
  50. package/dist/components/filter-bar-utils.js.map +1 -1
  51. package/dist/components/json-schema-form-fields.cjs +8 -2
  52. package/dist/components/json-schema-form-fields.cjs.map +1 -1
  53. package/dist/components/json-schema-form-fields.d.ts.map +1 -1
  54. package/dist/components/json-schema-form-fields.js +8 -2
  55. package/dist/components/json-schema-form-fields.js.map +1 -1
  56. package/dist/components/json-schema-form-resolve.cjs +1 -1
  57. package/dist/components/json-schema-form-resolve.cjs.map +1 -1
  58. package/dist/components/json-schema-form-resolve.js +1 -1
  59. package/dist/components/json-schema-form-resolve.js.map +1 -1
  60. package/dist/components.cjs +21 -1
  61. package/dist/components.cjs.map +1 -1
  62. package/dist/components.d.ts +11 -1
  63. package/dist/components.d.ts.map +1 -1
  64. package/dist/components.js +21 -1
  65. package/dist/components.js.map +1 -1
  66. package/dist/data/Clicky.cjs +33 -44
  67. package/dist/data/Clicky.cjs.map +1 -1
  68. package/dist/data/Clicky.d.ts +0 -9
  69. package/dist/data/Clicky.d.ts.map +1 -1
  70. package/dist/data/Clicky.js +31 -42
  71. package/dist/data/Clicky.js.map +1 -1
  72. package/dist/data/DataTable.cjs +73 -50
  73. package/dist/data/DataTable.cjs.map +1 -1
  74. package/dist/data/DataTable.d.ts +4 -0
  75. package/dist/data/DataTable.d.ts.map +1 -1
  76. package/dist/data/DataTable.js +73 -50
  77. package/dist/data/DataTable.js.map +1 -1
  78. package/dist/data/Icon.cjs +2 -5
  79. package/dist/data/Icon.cjs.map +1 -1
  80. package/dist/data/Icon.d.ts +1 -21
  81. package/dist/data/Icon.d.ts.map +1 -1
  82. package/dist/data/Icon.js +3 -6
  83. package/dist/data/Icon.js.map +1 -1
  84. package/dist/data/MatrixTable.cjs +4 -4
  85. package/dist/data/MatrixTable.cjs.map +1 -1
  86. package/dist/data/MatrixTable.js +4 -4
  87. package/dist/data/MatrixTable.js.map +1 -1
  88. package/dist/data/RadialGauge.cjs +76 -0
  89. package/dist/data/RadialGauge.cjs.map +1 -0
  90. package/dist/data/RadialGauge.d.ts +24 -0
  91. package/dist/data/RadialGauge.d.ts.map +1 -0
  92. package/dist/data/RadialGauge.js +76 -0
  93. package/dist/data/RadialGauge.js.map +1 -0
  94. package/dist/data/StatusBreakdown.cjs +0 -4
  95. package/dist/data/StatusBreakdown.cjs.map +1 -1
  96. package/dist/data/StatusBreakdown.d.ts +0 -2
  97. package/dist/data/StatusBreakdown.d.ts.map +1 -1
  98. package/dist/data/StatusBreakdown.js +1 -5
  99. package/dist/data/StatusBreakdown.js.map +1 -1
  100. package/dist/data/TabButton.cjs +17 -2
  101. package/dist/data/TabButton.cjs.map +1 -1
  102. package/dist/data/TabButton.d.ts +5 -1
  103. package/dist/data/TabButton.d.ts.map +1 -1
  104. package/dist/data/TabButton.js +17 -2
  105. package/dist/data/TabButton.js.map +1 -1
  106. package/dist/data/Timeline.cjs +61 -0
  107. package/dist/data/Timeline.cjs.map +1 -0
  108. package/dist/data/Timeline.d.ts +36 -0
  109. package/dist/data/Timeline.d.ts.map +1 -0
  110. package/dist/data/Timeline.js +61 -0
  111. package/dist/data/Timeline.js.map +1 -0
  112. package/dist/data/TimeseriesCoreBars.cjs +2 -25
  113. package/dist/data/TimeseriesCoreBars.cjs.map +1 -1
  114. package/dist/data/TimeseriesCoreBars.d.ts +0 -19
  115. package/dist/data/TimeseriesCoreBars.d.ts.map +1 -1
  116. package/dist/data/TimeseriesCoreBars.js +2 -25
  117. package/dist/data/TimeseriesCoreBars.js.map +1 -1
  118. package/dist/data/TimeseriesCoreBars.model.cjs +27 -0
  119. package/dist/data/TimeseriesCoreBars.model.cjs.map +1 -0
  120. package/dist/data/TimeseriesCoreBars.model.d.ts +20 -0
  121. package/dist/data/TimeseriesCoreBars.model.d.ts.map +1 -0
  122. package/dist/data/TimeseriesCoreBars.model.js +27 -0
  123. package/dist/data/TimeseriesCoreBars.model.js.map +1 -0
  124. package/dist/data/TimeseriesPanel.axes.cjs.map +1 -1
  125. package/dist/data/TimeseriesPanel.axes.d.ts +1 -1
  126. package/dist/data/TimeseriesPanel.axes.d.ts.map +1 -1
  127. package/dist/data/TimeseriesPanel.axes.js.map +1 -1
  128. package/dist/data/TimeseriesPanel.cjs +4 -54
  129. package/dist/data/TimeseriesPanel.cjs.map +1 -1
  130. package/dist/data/TimeseriesPanel.d.ts +2 -138
  131. package/dist/data/TimeseriesPanel.d.ts.map +1 -1
  132. package/dist/data/TimeseriesPanel.js +2 -52
  133. package/dist/data/TimeseriesPanel.js.map +1 -1
  134. package/dist/data/TimeseriesPanel.model.cjs +53 -0
  135. package/dist/data/TimeseriesPanel.model.cjs.map +1 -0
  136. package/dist/data/TimeseriesPanel.model.d.ts +88 -0
  137. package/dist/data/TimeseriesPanel.model.d.ts.map +1 -0
  138. package/dist/data/TimeseriesPanel.model.js +53 -0
  139. package/dist/data/TimeseriesPanel.model.js.map +1 -0
  140. package/dist/data/Tree.cjs +1 -1
  141. package/dist/data/Tree.cjs.map +1 -1
  142. package/dist/data/Tree.js +1 -1
  143. package/dist/data/Tree.js.map +1 -1
  144. package/dist/data/ai/ChatFab.cjs +29 -0
  145. package/dist/data/ai/ChatFab.cjs.map +1 -0
  146. package/dist/data/ai/ChatFab.d.ts +12 -0
  147. package/dist/data/ai/ChatFab.d.ts.map +1 -0
  148. package/dist/data/ai/ChatFab.js +29 -0
  149. package/dist/data/ai/ChatFab.js.map +1 -0
  150. package/dist/data/ai/ChatWindow.cjs +178 -0
  151. package/dist/data/ai/ChatWindow.cjs.map +1 -0
  152. package/dist/data/ai/ChatWindow.d.ts +38 -0
  153. package/dist/data/ai/ChatWindow.d.ts.map +1 -0
  154. package/dist/data/ai/ChatWindow.js +156 -0
  155. package/dist/data/ai/ChatWindow.js.map +1 -0
  156. package/dist/data/ai/ChatWindowManager.cjs +139 -0
  157. package/dist/data/ai/ChatWindowManager.cjs.map +1 -0
  158. package/dist/data/ai/ChatWindowManager.d.ts +12 -0
  159. package/dist/data/ai/ChatWindowManager.d.ts.map +1 -0
  160. package/dist/data/ai/ChatWindowManager.js +139 -0
  161. package/dist/data/ai/ChatWindowManager.js.map +1 -0
  162. package/dist/data/ai/ContextBadges.cjs +74 -0
  163. package/dist/data/ai/ContextBadges.cjs.map +1 -0
  164. package/dist/data/ai/ContextBadges.d.ts +16 -0
  165. package/dist/data/ai/ContextBadges.d.ts.map +1 -0
  166. package/dist/data/ai/ContextBadges.js +74 -0
  167. package/dist/data/ai/ContextBadges.js.map +1 -0
  168. package/dist/data/ai/ThreadPicker.cjs +148 -0
  169. package/dist/data/ai/ThreadPicker.cjs.map +1 -0
  170. package/dist/data/ai/ThreadPicker.d.ts +37 -0
  171. package/dist/data/ai/ThreadPicker.d.ts.map +1 -0
  172. package/dist/data/ai/ThreadPicker.js +148 -0
  173. package/dist/data/ai/ThreadPicker.js.map +1 -0
  174. package/dist/data/ai/ToolPreferences.cjs +80 -0
  175. package/dist/data/ai/ToolPreferences.cjs.map +1 -0
  176. package/dist/data/ai/ToolPreferences.d.ts +19 -0
  177. package/dist/data/ai/ToolPreferences.d.ts.map +1 -0
  178. package/dist/data/ai/ToolPreferences.js +80 -0
  179. package/dist/data/ai/ToolPreferences.js.map +1 -0
  180. package/dist/data/ai/chat-window-context.cjs +78 -0
  181. package/dist/data/ai/chat-window-context.cjs.map +1 -0
  182. package/dist/data/ai/chat-window-context.d.ts +57 -0
  183. package/dist/data/ai/chat-window-context.d.ts.map +1 -0
  184. package/dist/data/ai/chat-window-context.js +78 -0
  185. package/dist/data/ai/chat-window-context.js.map +1 -0
  186. package/dist/data/ai/context.cjs +43 -0
  187. package/dist/data/ai/context.cjs.map +1 -0
  188. package/dist/data/ai/context.d.ts +35 -0
  189. package/dist/data/ai/context.d.ts.map +1 -0
  190. package/dist/data/ai/context.js +43 -0
  191. package/dist/data/ai/context.js.map +1 -0
  192. package/dist/data/ai/index.d.ts +10 -0
  193. package/dist/data/ai/index.d.ts.map +1 -0
  194. package/dist/data/cache-browser/CacheDetailPanel.cjs +15 -0
  195. package/dist/data/cache-browser/CacheDetailPanel.cjs.map +1 -1
  196. package/dist/data/cache-browser/CacheDetailPanel.d.ts.map +1 -1
  197. package/dist/data/cache-browser/CacheDetailPanel.js +15 -0
  198. package/dist/data/cache-browser/CacheDetailPanel.js.map +1 -1
  199. package/dist/data/cache-browser/cache-browser.fixtures.d.ts +10 -0
  200. package/dist/data/cache-browser/cache-browser.fixtures.d.ts.map +1 -0
  201. package/dist/data/cache-browser/download.cjs +13 -0
  202. package/dist/data/cache-browser/download.cjs.map +1 -0
  203. package/dist/data/cache-browser/download.d.ts +3 -0
  204. package/dist/data/cache-browser/download.d.ts.map +1 -0
  205. package/dist/data/cache-browser/download.js +13 -0
  206. package/dist/data/cache-browser/download.js.map +1 -0
  207. package/dist/data/chat/Chat.cjs +40 -2
  208. package/dist/data/chat/Chat.cjs.map +1 -1
  209. package/dist/data/chat/Chat.d.ts +5 -2
  210. package/dist/data/chat/Chat.d.ts.map +1 -1
  211. package/dist/data/chat/Chat.fixtures.cjs +86 -0
  212. package/dist/data/chat/Chat.fixtures.cjs.map +1 -0
  213. package/dist/data/chat/Chat.fixtures.d.ts +4 -0
  214. package/dist/data/chat/Chat.fixtures.d.ts.map +1 -1
  215. package/dist/data/chat/Chat.fixtures.js +86 -0
  216. package/dist/data/chat/Chat.fixtures.js.map +1 -0
  217. package/dist/data/chat/Chat.js +41 -3
  218. package/dist/data/chat/Chat.js.map +1 -1
  219. package/dist/data/chat/ContextUsage.cjs +99 -0
  220. package/dist/data/chat/ContextUsage.cjs.map +1 -0
  221. package/dist/data/chat/ContextUsage.d.ts +19 -0
  222. package/dist/data/chat/ContextUsage.d.ts.map +1 -0
  223. package/dist/data/chat/ContextUsage.js +99 -0
  224. package/dist/data/chat/ContextUsage.js.map +1 -0
  225. package/dist/data/chat/ModelSelector.cjs +28 -14
  226. package/dist/data/chat/ModelSelector.cjs.map +1 -1
  227. package/dist/data/chat/ModelSelector.d.ts +5 -4
  228. package/dist/data/chat/ModelSelector.d.ts.map +1 -1
  229. package/dist/data/chat/ModelSelector.js +28 -14
  230. package/dist/data/chat/ModelSelector.js.map +1 -1
  231. package/dist/data/chat/clickyOperationsToTools.cjs +21 -1
  232. package/dist/data/chat/clickyOperationsToTools.cjs.map +1 -1
  233. package/dist/data/chat/clickyOperationsToTools.d.ts +5 -4
  234. package/dist/data/chat/clickyOperationsToTools.d.ts.map +1 -1
  235. package/dist/data/chat/clickyOperationsToTools.js +21 -1
  236. package/dist/data/chat/clickyOperationsToTools.js.map +1 -1
  237. package/dist/data/chat/index.d.ts +4 -1
  238. package/dist/data/chat/index.d.ts.map +1 -1
  239. package/dist/data/chat/provider-icons.cjs +15 -0
  240. package/dist/data/chat/provider-icons.cjs.map +1 -0
  241. package/dist/data/chat/provider-icons.d.ts +7 -0
  242. package/dist/data/chat/provider-icons.d.ts.map +1 -0
  243. package/dist/data/chat/provider-icons.js +15 -0
  244. package/dist/data/chat/provider-icons.js.map +1 -0
  245. package/dist/data/chat/types.cjs.map +1 -1
  246. package/dist/data/chat/types.d.ts +41 -9
  247. package/dist/data/chat/types.d.ts.map +1 -1
  248. package/dist/data/chat/types.js.map +1 -1
  249. package/dist/data/clicky-parse.cjs +42 -0
  250. package/dist/data/clicky-parse.cjs.map +1 -0
  251. package/dist/data/clicky-parse.d.ts +11 -0
  252. package/dist/data/clicky-parse.d.ts.map +1 -0
  253. package/dist/data/clicky-parse.js +42 -0
  254. package/dist/data/clicky-parse.js.map +1 -0
  255. package/dist/data/diagnostics/FrameSourceWindow.cjs +0 -4
  256. package/dist/data/diagnostics/FrameSourceWindow.cjs.map +1 -1
  257. package/dist/data/diagnostics/FrameSourceWindow.d.ts +1 -11
  258. package/dist/data/diagnostics/FrameSourceWindow.d.ts.map +1 -1
  259. package/dist/data/diagnostics/FrameSourceWindow.js +1 -5
  260. package/dist/data/diagnostics/FrameSourceWindow.js.map +1 -1
  261. package/dist/data/diagnostics/FrameSourceWindow.utils.cjs +7 -0
  262. package/dist/data/diagnostics/FrameSourceWindow.utils.cjs.map +1 -0
  263. package/dist/data/diagnostics/FrameSourceWindow.utils.d.ts +12 -0
  264. package/dist/data/diagnostics/FrameSourceWindow.utils.d.ts.map +1 -0
  265. package/dist/data/diagnostics/FrameSourceWindow.utils.js +7 -0
  266. package/dist/data/diagnostics/FrameSourceWindow.utils.js.map +1 -0
  267. package/dist/data/diagnostics/JvmStackTrace.cjs +2 -1
  268. package/dist/data/diagnostics/JvmStackTrace.cjs.map +1 -1
  269. package/dist/data/diagnostics/JvmStackTrace.d.ts.map +1 -1
  270. package/dist/data/diagnostics/JvmStackTrace.js +2 -1
  271. package/dist/data/diagnostics/JvmStackTrace.js.map +1 -1
  272. package/dist/data/icon-fallback.cjs +12 -0
  273. package/dist/data/icon-fallback.cjs.map +1 -0
  274. package/dist/data/icon-fallback.d.ts +19 -0
  275. package/dist/data/icon-fallback.d.ts.map +1 -0
  276. package/dist/data/icon-fallback.js +12 -0
  277. package/dist/data/icon-fallback.js.map +1 -0
  278. package/dist/data/status-breakdown-utils.cjs +7 -0
  279. package/dist/data/status-breakdown-utils.cjs.map +1 -0
  280. package/dist/data/status-breakdown-utils.d.ts +4 -0
  281. package/dist/data/status-breakdown-utils.d.ts.map +1 -0
  282. package/dist/data/status-breakdown-utils.js +7 -0
  283. package/dist/data/status-breakdown-utils.js.map +1 -0
  284. package/dist/data/test-runner/TestRunSummary.cjs +36 -0
  285. package/dist/data/test-runner/TestRunSummary.cjs.map +1 -1
  286. package/dist/data/test-runner/TestRunSummary.d.ts +7 -1
  287. package/dist/data/test-runner/TestRunSummary.d.ts.map +1 -1
  288. package/dist/data/test-runner/TestRunSummary.js +36 -0
  289. package/dist/data/test-runner/TestRunSummary.js.map +1 -1
  290. package/dist/data/test-runner/TestRunner.cjs +5 -3
  291. package/dist/data/test-runner/TestRunner.cjs.map +1 -1
  292. package/dist/data/test-runner/TestRunner.d.ts +13 -1
  293. package/dist/data/test-runner/TestRunner.d.ts.map +1 -1
  294. package/dist/data/test-runner/TestRunner.js +5 -3
  295. package/dist/data/test-runner/TestRunner.js.map +1 -1
  296. package/dist/data/version-info.cjs +3 -3
  297. package/dist/data/version-info.js +3 -3
  298. package/dist/data.cjs +19 -6
  299. package/dist/data.cjs.map +1 -1
  300. package/dist/data.d.ts +14 -6
  301. package/dist/data.d.ts.map +1 -1
  302. package/dist/data.js +18 -5
  303. package/dist/data.js.map +1 -1
  304. package/dist/index.cjs +57 -7
  305. package/dist/index.cjs.map +1 -1
  306. package/dist/index.js +56 -6
  307. package/dist/index.js.map +1 -1
  308. package/dist/layout/AppShell.cjs +332 -0
  309. package/dist/layout/AppShell.cjs.map +1 -0
  310. package/dist/layout/AppShell.d.ts +75 -0
  311. package/dist/layout/AppShell.d.ts.map +1 -0
  312. package/dist/layout/AppShell.js +332 -0
  313. package/dist/layout/AppShell.js.map +1 -0
  314. package/dist/layout/AppSidebar.cjs +239 -0
  315. package/dist/layout/AppSidebar.cjs.map +1 -0
  316. package/dist/layout/AppSidebar.d.ts +62 -0
  317. package/dist/layout/AppSidebar.d.ts.map +1 -0
  318. package/dist/layout/AppSidebar.js +239 -0
  319. package/dist/layout/AppSidebar.js.map +1 -0
  320. package/dist/layout/Panel.cjs +66 -0
  321. package/dist/layout/Panel.cjs.map +1 -0
  322. package/dist/layout/Panel.d.ts +34 -0
  323. package/dist/layout/Panel.d.ts.map +1 -0
  324. package/dist/layout/Panel.js +66 -0
  325. package/dist/layout/Panel.js.map +1 -0
  326. package/dist/layout/Tabs.cjs +36 -0
  327. package/dist/layout/Tabs.cjs.map +1 -0
  328. package/dist/layout/Tabs.d.ts +36 -0
  329. package/dist/layout/Tabs.d.ts.map +1 -0
  330. package/dist/layout/Tabs.js +36 -0
  331. package/dist/layout/Tabs.js.map +1 -0
  332. package/dist/overlay/DropdownMenu.cjs.map +1 -1
  333. package/dist/overlay/DropdownMenu.d.ts.map +1 -1
  334. package/dist/overlay/DropdownMenu.js.map +1 -1
  335. package/dist/overlay/Modal.cjs +4 -2
  336. package/dist/overlay/Modal.cjs.map +1 -1
  337. package/dist/overlay/Modal.d.ts +1 -1
  338. package/dist/overlay/Modal.d.ts.map +1 -1
  339. package/dist/overlay/Modal.js +4 -2
  340. package/dist/overlay/Modal.js.map +1 -1
  341. package/dist/overlay/Toast.cjs +89 -0
  342. package/dist/overlay/Toast.cjs.map +1 -0
  343. package/dist/overlay/Toast.d.ts +14 -0
  344. package/dist/overlay/Toast.d.ts.map +1 -0
  345. package/dist/overlay/Toast.js +89 -0
  346. package/dist/overlay/Toast.js.map +1 -0
  347. package/dist/overlay/toast-context.cjs +12 -0
  348. package/dist/overlay/toast-context.cjs.map +1 -0
  349. package/dist/overlay/toast-context.d.ts +24 -0
  350. package/dist/overlay/toast-context.d.ts.map +1 -0
  351. package/dist/overlay/toast-context.js +12 -0
  352. package/dist/overlay/toast-context.js.map +1 -0
  353. package/dist/rpc/AcceptPicker.cjs +81 -58
  354. package/dist/rpc/AcceptPicker.cjs.map +1 -1
  355. package/dist/rpc/AcceptPicker.d.ts.map +1 -1
  356. package/dist/rpc/AcceptPicker.js +81 -58
  357. package/dist/rpc/AcceptPicker.js.map +1 -1
  358. package/dist/rpc/CommandForm.cjs +5 -35
  359. package/dist/rpc/CommandForm.cjs.map +1 -1
  360. package/dist/rpc/CommandForm.d.ts +0 -3
  361. package/dist/rpc/CommandForm.d.ts.map +1 -1
  362. package/dist/rpc/CommandForm.js +2 -32
  363. package/dist/rpc/CommandForm.js.map +1 -1
  364. package/dist/rpc/CommandOutput.cjs +2 -1
  365. package/dist/rpc/CommandOutput.cjs.map +1 -1
  366. package/dist/rpc/CommandOutput.d.ts.map +1 -1
  367. package/dist/rpc/CommandOutput.js +2 -1
  368. package/dist/rpc/CommandOutput.js.map +1 -1
  369. package/dist/rpc/EntityExplorerApp.cjs +28 -83
  370. package/dist/rpc/EntityExplorerApp.cjs.map +1 -1
  371. package/dist/rpc/EntityExplorerApp.d.ts +1 -4
  372. package/dist/rpc/EntityExplorerApp.d.ts.map +1 -1
  373. package/dist/rpc/EntityExplorerApp.js +13 -68
  374. package/dist/rpc/EntityExplorerApp.js.map +1 -1
  375. package/dist/rpc/OperationCatalog.cjs +2 -2
  376. package/dist/rpc/OperationCatalog.cjs.map +1 -1
  377. package/dist/rpc/OperationCatalog.d.ts +1 -1
  378. package/dist/rpc/OperationCatalog.d.ts.map +1 -1
  379. package/dist/rpc/OperationCatalog.js +1 -1
  380. package/dist/rpc/OperationCatalog.js.map +1 -1
  381. package/dist/rpc/OperationCommandPage.cjs +6 -4
  382. package/dist/rpc/OperationCommandPage.cjs.map +1 -1
  383. package/dist/rpc/OperationCommandPage.d.ts.map +1 -1
  384. package/dist/rpc/OperationCommandPage.js +3 -1
  385. package/dist/rpc/OperationCommandPage.js.map +1 -1
  386. package/dist/rpc/RouterProvider.cjs +10 -0
  387. package/dist/rpc/RouterProvider.cjs.map +1 -0
  388. package/dist/rpc/RouterProvider.d.ts +10 -0
  389. package/dist/rpc/RouterProvider.d.ts.map +1 -0
  390. package/dist/rpc/RouterProvider.js +10 -0
  391. package/dist/rpc/RouterProvider.js.map +1 -0
  392. package/dist/rpc/apiClient.cjs +4 -4
  393. package/dist/rpc/apiClient.cjs.map +1 -1
  394. package/dist/rpc/apiClient.js +4 -4
  395. package/dist/rpc/apiClient.js.map +1 -1
  396. package/dist/rpc/command-form-utils.cjs +43 -0
  397. package/dist/rpc/command-form-utils.cjs.map +1 -0
  398. package/dist/rpc/command-form-utils.d.ts +5 -0
  399. package/dist/rpc/command-form-utils.d.ts.map +1 -0
  400. package/dist/rpc/command-form-utils.js +43 -0
  401. package/dist/rpc/command-form-utils.js.map +1 -0
  402. package/dist/rpc/commandHref.cjs +62 -0
  403. package/dist/rpc/commandHref.cjs.map +1 -0
  404. package/dist/rpc/commandHref.d.ts +7 -0
  405. package/dist/rpc/commandHref.d.ts.map +1 -0
  406. package/dist/rpc/commandHref.js +62 -0
  407. package/dist/rpc/commandHref.js.map +1 -0
  408. package/dist/rpc/formMetadata.cjs +1 -1
  409. package/dist/rpc/formMetadata.cjs.map +1 -1
  410. package/dist/rpc/formMetadata.js +1 -1
  411. package/dist/rpc/formMetadata.js.map +1 -1
  412. package/dist/rpc/router.cjs +83 -0
  413. package/dist/rpc/router.cjs.map +1 -0
  414. package/dist/rpc/router.d.ts +24 -0
  415. package/dist/rpc/router.d.ts.map +1 -0
  416. package/dist/rpc/router.js +83 -0
  417. package/dist/rpc/router.js.map +1 -0
  418. package/dist/rpc/rpc-story-fixtures/orders.fixture.d.ts +3 -0
  419. package/dist/rpc/rpc-story-fixtures/orders.fixture.d.ts.map +1 -0
  420. package/dist/rpc/rpc-story-fixtures/services.fixture.d.ts +3 -0
  421. package/dist/rpc/rpc-story-fixtures/services.fixture.d.ts.map +1 -0
  422. package/dist/rpc/rpc-story-fixtures/surface-fixture.d.ts +24 -0
  423. package/dist/rpc/rpc-story-fixtures/surface-fixture.d.ts.map +1 -0
  424. package/dist/rpc/rpc-story-fixtures/widgets.fixture.d.ts +3 -0
  425. package/dist/rpc/rpc-story-fixtures/widgets.fixture.d.ts.map +1 -0
  426. package/dist/rpc/rpc-story.fixtures.d.ts +16 -0
  427. package/dist/rpc/rpc-story.fixtures.d.ts.map +1 -0
  428. package/dist/rpc.cjs +17 -0
  429. package/dist/rpc.cjs.map +1 -1
  430. package/dist/rpc.d.ts +5 -0
  431. package/dist/rpc.d.ts.map +1 -1
  432. package/dist/rpc.js +18 -1
  433. package/dist/rpc.js.map +1 -1
  434. package/dist/styles.cjs +1 -0
  435. package/dist/styles.cjs.map +1 -1
  436. package/dist/styles.css +1 -1
  437. package/dist/styles.d.ts.map +1 -1
  438. package/dist/styles.js +1 -0
  439. package/dist/styles.js.map +1 -1
  440. package/dist/tailwind-preset.cjs +36 -19
  441. package/dist/tailwind-preset.cjs.map +1 -1
  442. package/dist/tailwind-preset.d.ts.map +1 -1
  443. package/dist/tailwind-preset.js +36 -19
  444. package/dist/tailwind-preset.js.map +1 -1
  445. package/package.json +11 -1
@@ -0,0 +1,80 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { useMemo } from "react";
3
+ import { cn } from "../../lib/utils.js";
4
+ import { DropdownMenu } from "../../overlay/DropdownMenu.js";
5
+ import { Button } from "../../components/button.js";
6
+ import { Icon } from "../Icon.js";
7
+ import { UiSliders } from "../../icons/components/UiSliders.js";
8
+ const MODE_CYCLE = ["enabled", "ask", "disabled"];
9
+ const MODE_LABEL = { enabled: "Auto", ask: "Ask", disabled: "Off" };
10
+ function ToolRow({
11
+ meta,
12
+ mode,
13
+ onToggle
14
+ }) {
15
+ return /* @__PURE__ */ jsxs(
16
+ "button",
17
+ {
18
+ type: "button",
19
+ className: "flex w-full items-center justify-between rounded px-2 py-1 text-left hover:bg-accent",
20
+ onClick: () => onToggle(meta.name),
21
+ children: [
22
+ /* @__PURE__ */ jsx("span", { className: cn("text-xs", mode === "disabled" && "text-muted-foreground line-through"), children: meta.label }),
23
+ /* @__PURE__ */ jsx(
24
+ "span",
25
+ {
26
+ className: cn(
27
+ "rounded px-1.5 py-0.5 text-[10px] font-medium",
28
+ mode === "enabled" && "bg-emerald-100 text-emerald-700 dark:bg-emerald-900 dark:text-emerald-300",
29
+ mode === "ask" && "bg-amber-100 text-amber-700 dark:bg-amber-900 dark:text-amber-300",
30
+ mode === "disabled" && "bg-muted text-muted-foreground"
31
+ ),
32
+ children: MODE_LABEL[mode]
33
+ }
34
+ )
35
+ ]
36
+ }
37
+ );
38
+ }
39
+ function ToolPreferences({ tools, value, onChange, className = "" }) {
40
+ const groups = useMemo(() => {
41
+ var _a;
42
+ const g = {};
43
+ for (const meta of tools) (g[_a = meta.group ?? "Tools"] ?? (g[_a] = [])).push(meta);
44
+ return g;
45
+ }, [tools]);
46
+ const handleToggle = (name) => {
47
+ const current = value[name] ?? "enabled";
48
+ const next = MODE_CYCLE[(MODE_CYCLE.indexOf(current) + 1) % MODE_CYCLE.length];
49
+ onChange({ ...value, [name]: next });
50
+ };
51
+ return /* @__PURE__ */ jsx(
52
+ DropdownMenu,
53
+ {
54
+ align: "right",
55
+ className,
56
+ menuClassName: "w-64 max-h-[400px] overflow-y-auto p-3",
57
+ trigger: /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "icon", title: "Tool preferences", "data-testid": "tool-preferences-btn", children: /* @__PURE__ */ jsx(Icon, { icon: UiSliders, className: "size-4" }) }),
58
+ children: () => /* @__PURE__ */ jsxs("div", { children: [
59
+ /* @__PURE__ */ jsx("div", { className: "mb-2 text-xs font-semibold", children: "Tool Preferences" }),
60
+ /* @__PURE__ */ jsx("p", { className: "mb-2 text-[10px] text-muted-foreground", children: "Click to cycle: Auto → Ask → Off" }),
61
+ Object.entries(groups).map(([group, metas]) => /* @__PURE__ */ jsxs("div", { className: "mb-2", children: [
62
+ /* @__PURE__ */ jsx("div", { className: "mb-0.5 px-2 text-[10px] font-semibold uppercase tracking-wider text-muted-foreground", children: group }),
63
+ metas.map((meta) => /* @__PURE__ */ jsx(
64
+ ToolRow,
65
+ {
66
+ meta,
67
+ mode: value[meta.name] ?? "enabled",
68
+ onToggle: handleToggle
69
+ },
70
+ meta.name
71
+ ))
72
+ ] }, group))
73
+ ] })
74
+ }
75
+ );
76
+ }
77
+ export {
78
+ ToolPreferences
79
+ };
80
+ //# sourceMappingURL=ToolPreferences.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ToolPreferences.js","sources":["../../../src/data/ai/ToolPreferences.tsx"],"sourcesContent":["import { useMemo } from \"react\";\nimport { cn } from \"../../lib/utils\";\nimport { DropdownMenu } from \"../../overlay/DropdownMenu\";\nimport { Button } from \"../../components/button\";\nimport { Icon } from \"../Icon\";\nimport { UiSliders } from \"../../icons\";\nimport type { ToolMeta } from \"../chat/types\";\n\nexport type { ToolMeta };\n\n/** How a tool may be invoked: run automatically, pause for approval, or be\n * hidden from the model entirely. */\nexport type ToolMode = \"enabled\" | \"ask\" | \"disabled\";\n\nconst MODE_CYCLE: ToolMode[] = [\"enabled\", \"ask\", \"disabled\"];\nconst MODE_LABEL: Record<ToolMode, string> = { enabled: \"Auto\", ask: \"Ask\", disabled: \"Off\" };\n\nexport type ToolPreferencesProps = {\n /** The tools to list. Replaces ai-financials' global registry — callers pass\n * whatever their backend exposes. */\n tools: ToolMeta[];\n /** Current per-tool mode. Missing entries default to \"enabled\". */\n value: Record<string, ToolMode>;\n onChange: (prefs: Record<string, ToolMode>) => void;\n className?: string;\n};\n\nfunction ToolRow({\n meta,\n mode,\n onToggle,\n}: {\n meta: ToolMeta;\n mode: ToolMode;\n onToggle: (name: string) => void;\n}) {\n return (\n <button\n type=\"button\"\n className=\"flex w-full items-center justify-between rounded px-2 py-1 text-left hover:bg-accent\"\n onClick={() => onToggle(meta.name)}\n >\n <span className={cn(\"text-xs\", mode === \"disabled\" && \"text-muted-foreground line-through\")}>\n {meta.label}\n </span>\n <span\n className={cn(\n \"rounded px-1.5 py-0.5 text-[10px] font-medium\",\n mode === \"enabled\" &&\n \"bg-emerald-100 text-emerald-700 dark:bg-emerald-900 dark:text-emerald-300\",\n mode === \"ask\" && \"bg-amber-100 text-amber-700 dark:bg-amber-900 dark:text-amber-300\",\n mode === \"disabled\" && \"bg-muted text-muted-foreground\",\n )}\n >\n {MODE_LABEL[mode]}\n </span>\n </button>\n );\n}\n\n/** A popover that cycles each tool through Auto → Ask → Off. The resulting\n * `Record<name, ToolMode>` is meant to be forwarded to the backend (e.g. via\n * `<Chat body={{ toolPreferences }}>`). */\nexport function ToolPreferences({ tools, value, onChange, className = \"\" }: ToolPreferencesProps) {\n const groups = useMemo(() => {\n const g: Record<string, ToolMeta[]> = {};\n for (const meta of tools) (g[meta.group ?? \"Tools\"] ??= []).push(meta);\n return g;\n }, [tools]);\n\n const handleToggle = (name: string) => {\n const current = value[name] ?? \"enabled\";\n const next = MODE_CYCLE[(MODE_CYCLE.indexOf(current) + 1) % MODE_CYCLE.length]!;\n onChange({ ...value, [name]: next });\n };\n\n return (\n <DropdownMenu\n align=\"right\"\n className={className}\n menuClassName=\"w-64 max-h-[400px] overflow-y-auto p-3\"\n trigger={\n <Button variant=\"ghost\" size=\"icon\" title=\"Tool preferences\" data-testid=\"tool-preferences-btn\">\n <Icon icon={UiSliders} className=\"size-4\" />\n </Button>\n }\n >\n {() => (\n <div>\n <div className=\"mb-2 text-xs font-semibold\">Tool Preferences</div>\n <p className=\"mb-2 text-[10px] text-muted-foreground\">Click to cycle: Auto → Ask → Off</p>\n {Object.entries(groups).map(([group, metas]) => (\n <div key={group} className=\"mb-2\">\n <div className=\"mb-0.5 px-2 text-[10px] font-semibold uppercase tracking-wider text-muted-foreground\">\n {group}\n </div>\n {metas.map((meta) => (\n <ToolRow\n key={meta.name}\n meta={meta}\n mode={value[meta.name] ?? \"enabled\"}\n onToggle={handleToggle}\n />\n ))}\n </div>\n ))}\n </div>\n )}\n </DropdownMenu>\n );\n}\n"],"names":[],"mappings":";;;;;;;AAcA,MAAM,aAAyB,CAAC,WAAW,OAAO,UAAU;AAC5D,MAAM,aAAuC,EAAE,SAAS,QAAQ,KAAK,OAAO,UAAU,MAAA;AAYtF,SAAS,QAAQ;AAAA,EACf;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,MAAK;AAAA,MACL,WAAU;AAAA,MACV,SAAS,MAAM,SAAS,KAAK,IAAI;AAAA,MAEjC,UAAA;AAAA,QAAA,oBAAC,QAAA,EAAK,WAAW,GAAG,WAAW,SAAS,cAAc,oCAAoC,GACvF,UAAA,KAAK,MAAA,CACR;AAAA,QACA;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,WAAW;AAAA,cACT;AAAA,cACA,SAAS,aACP;AAAA,cACF,SAAS,SAAS;AAAA,cAClB,SAAS,cAAc;AAAA,YAAA;AAAA,YAGxB,qBAAW,IAAI;AAAA,UAAA;AAAA,QAAA;AAAA,MAClB;AAAA,IAAA;AAAA,EAAA;AAGN;AAKO,SAAS,gBAAgB,EAAE,OAAO,OAAO,UAAU,YAAY,MAA4B;AAChG,QAAM,SAAS,QAAQ,MAAM;;AAC3B,UAAM,IAAgC,CAAA;AACtC,eAAW,QAAQ,MAAO,EAAC,OAAE,KAAK,SAAS,aAAhB,QAA6B,KAAI,KAAK,IAAI;AACrE,WAAO;AAAA,EACT,GAAG,CAAC,KAAK,CAAC;AAEV,QAAM,eAAe,CAAC,SAAiB;AACrC,UAAM,UAAU,MAAM,IAAI,KAAK;AAC/B,UAAM,OAAO,YAAY,WAAW,QAAQ,OAAO,IAAI,KAAK,WAAW,MAAM;AAC7E,aAAS,EAAE,GAAG,OAAO,CAAC,IAAI,GAAG,MAAM;AAAA,EACrC;AAEA,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,OAAM;AAAA,MACN;AAAA,MACA,eAAc;AAAA,MACd,SACE,oBAAC,QAAA,EAAO,SAAQ,SAAQ,MAAK,QAAO,OAAM,oBAAmB,eAAY,wBACvE,UAAA,oBAAC,MAAA,EAAK,MAAM,WAAW,WAAU,UAAS,GAC5C;AAAA,MAGD,UAAA,2BACE,OAAA,EACC,UAAA;AAAA,QAAA,oBAAC,OAAA,EAAI,WAAU,8BAA6B,UAAA,oBAAgB;AAAA,QAC5D,oBAAC,KAAA,EAAE,WAAU,0CAAyC,UAAA,oCAAgC;AAAA,QACrF,OAAO,QAAQ,MAAM,EAAE,IAAI,CAAC,CAAC,OAAO,KAAK,MACxC,qBAAC,OAAA,EAAgB,WAAU,QACzB,UAAA;AAAA,UAAA,oBAAC,OAAA,EAAI,WAAU,wFACZ,UAAA,OACH;AAAA,UACC,MAAM,IAAI,CAAC,SACV;AAAA,YAAC;AAAA,YAAA;AAAA,cAEC;AAAA,cACA,MAAM,MAAM,KAAK,IAAI,KAAK;AAAA,cAC1B,UAAU;AAAA,YAAA;AAAA,YAHL,KAAK;AAAA,UAAA,CAKb;AAAA,QAAA,EAAA,GAXO,KAYV,CACD;AAAA,MAAA,EAAA,CACH;AAAA,IAAA;AAAA,EAAA;AAIR;"}
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const react = require("react");
4
+ const ChatWindowManagerContext = react.createContext(null);
5
+ function useChatWindowManager() {
6
+ const ctx = react.useContext(ChatWindowManagerContext);
7
+ if (!ctx) throw new Error("useChatWindowManager must be used within <ChatWindowManagerProvider>");
8
+ return ctx;
9
+ }
10
+ const MAX_PANELS = 6;
11
+ const DEFAULT_WIDTH = 520;
12
+ const DEFAULT_HEIGHT = 700;
13
+ const CASCADE_OFFSET = 30;
14
+ const Z_BASE = 61;
15
+ function storageKey(storageId) {
16
+ return `chat-panels:${storageId}`;
17
+ }
18
+ function loadPanels(storageId) {
19
+ if (typeof window === "undefined") return [];
20
+ try {
21
+ const raw = localStorage.getItem(storageKey(storageId));
22
+ if (!raw) return [];
23
+ const persisted = JSON.parse(raw);
24
+ return persisted.map((p, i) => ({
25
+ ...p,
26
+ initialModel: null,
27
+ zIndex: Z_BASE + i,
28
+ initialPrompt: null,
29
+ contextItems: []
30
+ }));
31
+ } catch {
32
+ return [];
33
+ }
34
+ }
35
+ function savePanels(storageId, panels) {
36
+ const persisted = panels.map((p) => ({
37
+ id: p.id,
38
+ threadId: p.threadId,
39
+ x: p.x,
40
+ y: p.y,
41
+ width: p.width,
42
+ height: p.height,
43
+ maximized: p.maximized
44
+ }));
45
+ localStorage.setItem(storageKey(storageId), JSON.stringify(persisted));
46
+ }
47
+ let _panelId = 0;
48
+ function nextPanelId() {
49
+ return `panel-${++_panelId}-${Date.now()}`;
50
+ }
51
+ let _promptId = 0;
52
+ function nextPromptId() {
53
+ return ++_promptId;
54
+ }
55
+ function reindex(panels, frontId) {
56
+ const sorted = [...panels].sort((a, b) => a.zIndex - b.zIndex);
57
+ if (frontId) {
58
+ const idx = sorted.findIndex((p) => p.id === frontId);
59
+ if (idx >= 0) {
60
+ const [item] = sorted.splice(idx, 1);
61
+ if (item) sorted.push(item);
62
+ }
63
+ }
64
+ return sorted.map((p, i) => ({ ...p, zIndex: Z_BASE + i }));
65
+ }
66
+ exports.CASCADE_OFFSET = CASCADE_OFFSET;
67
+ exports.ChatWindowManagerContext = ChatWindowManagerContext;
68
+ exports.DEFAULT_HEIGHT = DEFAULT_HEIGHT;
69
+ exports.DEFAULT_WIDTH = DEFAULT_WIDTH;
70
+ exports.MAX_PANELS = MAX_PANELS;
71
+ exports.Z_BASE = Z_BASE;
72
+ exports.loadPanels = loadPanels;
73
+ exports.nextPanelId = nextPanelId;
74
+ exports.nextPromptId = nextPromptId;
75
+ exports.reindex = reindex;
76
+ exports.savePanels = savePanels;
77
+ exports.useChatWindowManager = useChatWindowManager;
78
+ //# sourceMappingURL=chat-window-context.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chat-window-context.cjs","sources":["../../../src/data/ai/chat-window-context.ts"],"sourcesContent":["// Non-component half of the chat window manager: the context object, the hook,\n// id helpers, persistence and layout maths. Split from the Provider (a .tsx\n// component) so this file stays JSX-free — matching the repo idiom of keeping\n// context/hooks in a .ts (see hooks/use-theme.ts, data/test-runner/context.ts)\n// and keeping React-Fast-Refresh happy.\nimport { createContext, useContext } from \"react\";\nimport type { ChatContextItem } from \"./context\";\n\n/** Live state of one floating chat window. Position/size/maximized are\n * persisted to localStorage; the rest is session-only. */\nexport interface ChatWindowState {\n id: string;\n threadId: string | null;\n initialModel: string | null;\n x: number;\n y: number;\n width: number;\n height: number;\n zIndex: number;\n maximized: boolean;\n /** A prompt to auto-send when the window mounts (the `id` lets the window\n * detect a fresh request even if the text repeats). */\n initialPrompt: { id: number; text: string } | null;\n contextItems: ChatContextItem[];\n}\n\nexport interface OpenPanelOpts {\n threadId?: string | null;\n initialModel?: string | null;\n initialPrompt?: { id: number; text: string } | null;\n contextItems?: ChatContextItem[];\n}\n\nexport interface ChatWindowManagerValue {\n panels: ChatWindowState[];\n openPanel: (opts?: OpenPanelOpts) => string;\n closePanel: (id: string) => void;\n updatePanel: (id: string, partial: Partial<ChatWindowState>) => void;\n bringToFront: (id: string) => void;\n maximizePanel: (id: string) => void;\n /** Reuses the front-most existing window (merging in any new prompt/context)\n * or opens a fresh one when none exist. */\n findOrCreatePanel: (opts?: OpenPanelOpts) => string;\n}\n\nexport const ChatWindowManagerContext = createContext<ChatWindowManagerValue | null>(null);\n\nexport function useChatWindowManager(): ChatWindowManagerValue {\n const ctx = useContext(ChatWindowManagerContext);\n if (!ctx) throw new Error(\"useChatWindowManager must be used within <ChatWindowManagerProvider>\");\n return ctx;\n}\n\nexport const MAX_PANELS = 6;\nexport const DEFAULT_WIDTH = 520;\nexport const DEFAULT_HEIGHT = 700;\nexport const CASCADE_OFFSET = 30;\nexport const Z_BASE = 61;\n\nfunction storageKey(storageId: string) {\n return `chat-panels:${storageId}`;\n}\n\ninterface PersistedPanel {\n id: string;\n threadId: string | null;\n x: number;\n y: number;\n width: number;\n height: number;\n maximized: boolean;\n}\n\nexport function loadPanels(storageId: string): ChatWindowState[] {\n if (typeof window === \"undefined\") return [];\n try {\n const raw = localStorage.getItem(storageKey(storageId));\n if (!raw) return [];\n const persisted: PersistedPanel[] = JSON.parse(raw);\n return persisted.map((p, i) => ({\n ...p,\n initialModel: null,\n zIndex: Z_BASE + i,\n initialPrompt: null,\n contextItems: [],\n }));\n } catch {\n return [];\n }\n}\n\nexport function savePanels(storageId: string, panels: ChatWindowState[]) {\n const persisted: PersistedPanel[] = panels.map((p) => ({\n id: p.id,\n threadId: p.threadId,\n x: p.x,\n y: p.y,\n width: p.width,\n height: p.height,\n maximized: p.maximized,\n }));\n localStorage.setItem(storageKey(storageId), JSON.stringify(persisted));\n}\n\nlet _panelId = 0;\nexport function nextPanelId(): string {\n return `panel-${++_panelId}-${Date.now()}`;\n}\n\nlet _promptId = 0;\n/** A monotonic id stamped onto an `initialPrompt` so a window re-sends even when\n * the same text is requested twice. */\nexport function nextPromptId(): number {\n return ++_promptId;\n}\n\n/** Re-indexes z so values stay compact (61, 62, …) with `frontId` on top. */\nexport function reindex(panels: ChatWindowState[], frontId?: string): ChatWindowState[] {\n const sorted = [...panels].sort((a, b) => a.zIndex - b.zIndex);\n if (frontId) {\n const idx = sorted.findIndex((p) => p.id === frontId);\n if (idx >= 0) {\n const [item] = sorted.splice(idx, 1);\n if (item) sorted.push(item);\n }\n }\n return sorted.map((p, i) => ({ ...p, zIndex: Z_BASE + i }));\n}\n"],"names":["createContext","useContext"],"mappings":";;;AA6CO,MAAM,2BAA2BA,MAAAA,cAA6C,IAAI;AAElF,SAAS,uBAA+C;AAC7D,QAAM,MAAMC,MAAAA,WAAW,wBAAwB;AAC/C,MAAI,CAAC,IAAK,OAAM,IAAI,MAAM,sEAAsE;AAChG,SAAO;AACT;AAEO,MAAM,aAAa;AACnB,MAAM,gBAAgB;AACtB,MAAM,iBAAiB;AACvB,MAAM,iBAAiB;AACvB,MAAM,SAAS;AAEtB,SAAS,WAAW,WAAmB;AACrC,SAAO,eAAe,SAAS;AACjC;AAYO,SAAS,WAAW,WAAsC;AAC/D,MAAI,OAAO,WAAW,YAAa,QAAO,CAAA;AAC1C,MAAI;AACF,UAAM,MAAM,aAAa,QAAQ,WAAW,SAAS,CAAC;AACtD,QAAI,CAAC,IAAK,QAAO,CAAA;AACjB,UAAM,YAA8B,KAAK,MAAM,GAAG;AAClD,WAAO,UAAU,IAAI,CAAC,GAAG,OAAO;AAAA,MAC9B,GAAG;AAAA,MACH,cAAc;AAAA,MACd,QAAQ,SAAS;AAAA,MACjB,eAAe;AAAA,MACf,cAAc,CAAA;AAAA,IAAC,EACf;AAAA,EACJ,QAAQ;AACN,WAAO,CAAA;AAAA,EACT;AACF;AAEO,SAAS,WAAW,WAAmB,QAA2B;AACvE,QAAM,YAA8B,OAAO,IAAI,CAAC,OAAO;AAAA,IACrD,IAAI,EAAE;AAAA,IACN,UAAU,EAAE;AAAA,IACZ,GAAG,EAAE;AAAA,IACL,GAAG,EAAE;AAAA,IACL,OAAO,EAAE;AAAA,IACT,QAAQ,EAAE;AAAA,IACV,WAAW,EAAE;AAAA,EAAA,EACb;AACF,eAAa,QAAQ,WAAW,SAAS,GAAG,KAAK,UAAU,SAAS,CAAC;AACvE;AAEA,IAAI,WAAW;AACR,SAAS,cAAsB;AACpC,SAAO,SAAS,EAAE,QAAQ,IAAI,KAAK,KAAK;AAC1C;AAEA,IAAI,YAAY;AAGT,SAAS,eAAuB;AACrC,SAAO,EAAE;AACX;AAGO,SAAS,QAAQ,QAA2B,SAAqC;AACtF,QAAM,SAAS,CAAC,GAAG,MAAM,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,SAAS,EAAE,MAAM;AAC7D,MAAI,SAAS;AACX,UAAM,MAAM,OAAO,UAAU,CAAC,MAAM,EAAE,OAAO,OAAO;AACpD,QAAI,OAAO,GAAG;AACZ,YAAM,CAAC,IAAI,IAAI,OAAO,OAAO,KAAK,CAAC;AACnC,UAAI,KAAM,QAAO,KAAK,IAAI;AAAA,IAC5B;AAAA,EACF;AACA,SAAO,OAAO,IAAI,CAAC,GAAG,OAAO,EAAE,GAAG,GAAG,QAAQ,SAAS,EAAA,EAAI;AAC5D;;;;;;;;;;;;;"}
@@ -0,0 +1,57 @@
1
+ import { ChatContextItem } from './context';
2
+ /** Live state of one floating chat window. Position/size/maximized are
3
+ * persisted to localStorage; the rest is session-only. */
4
+ export interface ChatWindowState {
5
+ id: string;
6
+ threadId: string | null;
7
+ initialModel: string | null;
8
+ x: number;
9
+ y: number;
10
+ width: number;
11
+ height: number;
12
+ zIndex: number;
13
+ maximized: boolean;
14
+ /** A prompt to auto-send when the window mounts (the `id` lets the window
15
+ * detect a fresh request even if the text repeats). */
16
+ initialPrompt: {
17
+ id: number;
18
+ text: string;
19
+ } | null;
20
+ contextItems: ChatContextItem[];
21
+ }
22
+ export interface OpenPanelOpts {
23
+ threadId?: string | null;
24
+ initialModel?: string | null;
25
+ initialPrompt?: {
26
+ id: number;
27
+ text: string;
28
+ } | null;
29
+ contextItems?: ChatContextItem[];
30
+ }
31
+ export interface ChatWindowManagerValue {
32
+ panels: ChatWindowState[];
33
+ openPanel: (opts?: OpenPanelOpts) => string;
34
+ closePanel: (id: string) => void;
35
+ updatePanel: (id: string, partial: Partial<ChatWindowState>) => void;
36
+ bringToFront: (id: string) => void;
37
+ maximizePanel: (id: string) => void;
38
+ /** Reuses the front-most existing window (merging in any new prompt/context)
39
+ * or opens a fresh one when none exist. */
40
+ findOrCreatePanel: (opts?: OpenPanelOpts) => string;
41
+ }
42
+ export declare const ChatWindowManagerContext: import('react').Context<ChatWindowManagerValue | null>;
43
+ export declare function useChatWindowManager(): ChatWindowManagerValue;
44
+ export declare const MAX_PANELS = 6;
45
+ export declare const DEFAULT_WIDTH = 520;
46
+ export declare const DEFAULT_HEIGHT = 700;
47
+ export declare const CASCADE_OFFSET = 30;
48
+ export declare const Z_BASE = 61;
49
+ export declare function loadPanels(storageId: string): ChatWindowState[];
50
+ export declare function savePanels(storageId: string, panels: ChatWindowState[]): void;
51
+ export declare function nextPanelId(): string;
52
+ /** A monotonic id stamped onto an `initialPrompt` so a window re-sends even when
53
+ * the same text is requested twice. */
54
+ export declare function nextPromptId(): number;
55
+ /** Re-indexes z so values stay compact (61, 62, …) with `frontId` on top. */
56
+ export declare function reindex(panels: ChatWindowState[], frontId?: string): ChatWindowState[];
57
+ //# sourceMappingURL=chat-window-context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chat-window-context.d.ts","sourceRoot":"","sources":["../../../src/data/ai/chat-window-context.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAEjD;2DAC2D;AAC3D,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,OAAO,CAAC;IACnB;4DACwD;IACxD,aAAa,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACnD,YAAY,EAAE,eAAe,EAAE,CAAC;CACjC;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,aAAa,CAAC,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACpD,YAAY,CAAC,EAAE,eAAe,EAAE,CAAC;CAClC;AAED,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,SAAS,EAAE,CAAC,IAAI,CAAC,EAAE,aAAa,KAAK,MAAM,CAAC;IAC5C,UAAU,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,WAAW,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,eAAe,CAAC,KAAK,IAAI,CAAC;IACrE,YAAY,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,aAAa,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC;gDAC4C;IAC5C,iBAAiB,EAAE,CAAC,IAAI,CAAC,EAAE,aAAa,KAAK,MAAM,CAAC;CACrD;AAED,eAAO,MAAM,wBAAwB,wDAAqD,CAAC;AAE3F,wBAAgB,oBAAoB,IAAI,sBAAsB,CAI7D;AAED,eAAO,MAAM,UAAU,IAAI,CAAC;AAC5B,eAAO,MAAM,aAAa,MAAM,CAAC;AACjC,eAAO,MAAM,cAAc,MAAM,CAAC;AAClC,eAAO,MAAM,cAAc,KAAK,CAAC;AACjC,eAAO,MAAM,MAAM,KAAK,CAAC;AAgBzB,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,eAAe,EAAE,CAgB/D;AAED,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,QAWtE;AAGD,wBAAgB,WAAW,IAAI,MAAM,CAEpC;AAGD;wCACwC;AACxC,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAED,6EAA6E;AAC7E,wBAAgB,OAAO,CAAC,MAAM,EAAE,eAAe,EAAE,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,eAAe,EAAE,CAUtF"}
@@ -0,0 +1,78 @@
1
+ import { useContext, createContext } from "react";
2
+ const ChatWindowManagerContext = createContext(null);
3
+ function useChatWindowManager() {
4
+ const ctx = useContext(ChatWindowManagerContext);
5
+ if (!ctx) throw new Error("useChatWindowManager must be used within <ChatWindowManagerProvider>");
6
+ return ctx;
7
+ }
8
+ const MAX_PANELS = 6;
9
+ const DEFAULT_WIDTH = 520;
10
+ const DEFAULT_HEIGHT = 700;
11
+ const CASCADE_OFFSET = 30;
12
+ const Z_BASE = 61;
13
+ function storageKey(storageId) {
14
+ return `chat-panels:${storageId}`;
15
+ }
16
+ function loadPanels(storageId) {
17
+ if (typeof window === "undefined") return [];
18
+ try {
19
+ const raw = localStorage.getItem(storageKey(storageId));
20
+ if (!raw) return [];
21
+ const persisted = JSON.parse(raw);
22
+ return persisted.map((p, i) => ({
23
+ ...p,
24
+ initialModel: null,
25
+ zIndex: Z_BASE + i,
26
+ initialPrompt: null,
27
+ contextItems: []
28
+ }));
29
+ } catch {
30
+ return [];
31
+ }
32
+ }
33
+ function savePanels(storageId, panels) {
34
+ const persisted = panels.map((p) => ({
35
+ id: p.id,
36
+ threadId: p.threadId,
37
+ x: p.x,
38
+ y: p.y,
39
+ width: p.width,
40
+ height: p.height,
41
+ maximized: p.maximized
42
+ }));
43
+ localStorage.setItem(storageKey(storageId), JSON.stringify(persisted));
44
+ }
45
+ let _panelId = 0;
46
+ function nextPanelId() {
47
+ return `panel-${++_panelId}-${Date.now()}`;
48
+ }
49
+ let _promptId = 0;
50
+ function nextPromptId() {
51
+ return ++_promptId;
52
+ }
53
+ function reindex(panels, frontId) {
54
+ const sorted = [...panels].sort((a, b) => a.zIndex - b.zIndex);
55
+ if (frontId) {
56
+ const idx = sorted.findIndex((p) => p.id === frontId);
57
+ if (idx >= 0) {
58
+ const [item] = sorted.splice(idx, 1);
59
+ if (item) sorted.push(item);
60
+ }
61
+ }
62
+ return sorted.map((p, i) => ({ ...p, zIndex: Z_BASE + i }));
63
+ }
64
+ export {
65
+ CASCADE_OFFSET,
66
+ ChatWindowManagerContext,
67
+ DEFAULT_HEIGHT,
68
+ DEFAULT_WIDTH,
69
+ MAX_PANELS,
70
+ Z_BASE,
71
+ loadPanels,
72
+ nextPanelId,
73
+ nextPromptId,
74
+ reindex,
75
+ savePanels,
76
+ useChatWindowManager
77
+ };
78
+ //# sourceMappingURL=chat-window-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chat-window-context.js","sources":["../../../src/data/ai/chat-window-context.ts"],"sourcesContent":["// Non-component half of the chat window manager: the context object, the hook,\n// id helpers, persistence and layout maths. Split from the Provider (a .tsx\n// component) so this file stays JSX-free — matching the repo idiom of keeping\n// context/hooks in a .ts (see hooks/use-theme.ts, data/test-runner/context.ts)\n// and keeping React-Fast-Refresh happy.\nimport { createContext, useContext } from \"react\";\nimport type { ChatContextItem } from \"./context\";\n\n/** Live state of one floating chat window. Position/size/maximized are\n * persisted to localStorage; the rest is session-only. */\nexport interface ChatWindowState {\n id: string;\n threadId: string | null;\n initialModel: string | null;\n x: number;\n y: number;\n width: number;\n height: number;\n zIndex: number;\n maximized: boolean;\n /** A prompt to auto-send when the window mounts (the `id` lets the window\n * detect a fresh request even if the text repeats). */\n initialPrompt: { id: number; text: string } | null;\n contextItems: ChatContextItem[];\n}\n\nexport interface OpenPanelOpts {\n threadId?: string | null;\n initialModel?: string | null;\n initialPrompt?: { id: number; text: string } | null;\n contextItems?: ChatContextItem[];\n}\n\nexport interface ChatWindowManagerValue {\n panels: ChatWindowState[];\n openPanel: (opts?: OpenPanelOpts) => string;\n closePanel: (id: string) => void;\n updatePanel: (id: string, partial: Partial<ChatWindowState>) => void;\n bringToFront: (id: string) => void;\n maximizePanel: (id: string) => void;\n /** Reuses the front-most existing window (merging in any new prompt/context)\n * or opens a fresh one when none exist. */\n findOrCreatePanel: (opts?: OpenPanelOpts) => string;\n}\n\nexport const ChatWindowManagerContext = createContext<ChatWindowManagerValue | null>(null);\n\nexport function useChatWindowManager(): ChatWindowManagerValue {\n const ctx = useContext(ChatWindowManagerContext);\n if (!ctx) throw new Error(\"useChatWindowManager must be used within <ChatWindowManagerProvider>\");\n return ctx;\n}\n\nexport const MAX_PANELS = 6;\nexport const DEFAULT_WIDTH = 520;\nexport const DEFAULT_HEIGHT = 700;\nexport const CASCADE_OFFSET = 30;\nexport const Z_BASE = 61;\n\nfunction storageKey(storageId: string) {\n return `chat-panels:${storageId}`;\n}\n\ninterface PersistedPanel {\n id: string;\n threadId: string | null;\n x: number;\n y: number;\n width: number;\n height: number;\n maximized: boolean;\n}\n\nexport function loadPanels(storageId: string): ChatWindowState[] {\n if (typeof window === \"undefined\") return [];\n try {\n const raw = localStorage.getItem(storageKey(storageId));\n if (!raw) return [];\n const persisted: PersistedPanel[] = JSON.parse(raw);\n return persisted.map((p, i) => ({\n ...p,\n initialModel: null,\n zIndex: Z_BASE + i,\n initialPrompt: null,\n contextItems: [],\n }));\n } catch {\n return [];\n }\n}\n\nexport function savePanels(storageId: string, panels: ChatWindowState[]) {\n const persisted: PersistedPanel[] = panels.map((p) => ({\n id: p.id,\n threadId: p.threadId,\n x: p.x,\n y: p.y,\n width: p.width,\n height: p.height,\n maximized: p.maximized,\n }));\n localStorage.setItem(storageKey(storageId), JSON.stringify(persisted));\n}\n\nlet _panelId = 0;\nexport function nextPanelId(): string {\n return `panel-${++_panelId}-${Date.now()}`;\n}\n\nlet _promptId = 0;\n/** A monotonic id stamped onto an `initialPrompt` so a window re-sends even when\n * the same text is requested twice. */\nexport function nextPromptId(): number {\n return ++_promptId;\n}\n\n/** Re-indexes z so values stay compact (61, 62, …) with `frontId` on top. */\nexport function reindex(panels: ChatWindowState[], frontId?: string): ChatWindowState[] {\n const sorted = [...panels].sort((a, b) => a.zIndex - b.zIndex);\n if (frontId) {\n const idx = sorted.findIndex((p) => p.id === frontId);\n if (idx >= 0) {\n const [item] = sorted.splice(idx, 1);\n if (item) sorted.push(item);\n }\n }\n return sorted.map((p, i) => ({ ...p, zIndex: Z_BASE + i }));\n}\n"],"names":[],"mappings":";AA6CO,MAAM,2BAA2B,cAA6C,IAAI;AAElF,SAAS,uBAA+C;AAC7D,QAAM,MAAM,WAAW,wBAAwB;AAC/C,MAAI,CAAC,IAAK,OAAM,IAAI,MAAM,sEAAsE;AAChG,SAAO;AACT;AAEO,MAAM,aAAa;AACnB,MAAM,gBAAgB;AACtB,MAAM,iBAAiB;AACvB,MAAM,iBAAiB;AACvB,MAAM,SAAS;AAEtB,SAAS,WAAW,WAAmB;AACrC,SAAO,eAAe,SAAS;AACjC;AAYO,SAAS,WAAW,WAAsC;AAC/D,MAAI,OAAO,WAAW,YAAa,QAAO,CAAA;AAC1C,MAAI;AACF,UAAM,MAAM,aAAa,QAAQ,WAAW,SAAS,CAAC;AACtD,QAAI,CAAC,IAAK,QAAO,CAAA;AACjB,UAAM,YAA8B,KAAK,MAAM,GAAG;AAClD,WAAO,UAAU,IAAI,CAAC,GAAG,OAAO;AAAA,MAC9B,GAAG;AAAA,MACH,cAAc;AAAA,MACd,QAAQ,SAAS;AAAA,MACjB,eAAe;AAAA,MACf,cAAc,CAAA;AAAA,IAAC,EACf;AAAA,EACJ,QAAQ;AACN,WAAO,CAAA;AAAA,EACT;AACF;AAEO,SAAS,WAAW,WAAmB,QAA2B;AACvE,QAAM,YAA8B,OAAO,IAAI,CAAC,OAAO;AAAA,IACrD,IAAI,EAAE;AAAA,IACN,UAAU,EAAE;AAAA,IACZ,GAAG,EAAE;AAAA,IACL,GAAG,EAAE;AAAA,IACL,OAAO,EAAE;AAAA,IACT,QAAQ,EAAE;AAAA,IACV,WAAW,EAAE;AAAA,EAAA,EACb;AACF,eAAa,QAAQ,WAAW,SAAS,GAAG,KAAK,UAAU,SAAS,CAAC;AACvE;AAEA,IAAI,WAAW;AACR,SAAS,cAAsB;AACpC,SAAO,SAAS,EAAE,QAAQ,IAAI,KAAK,KAAK;AAC1C;AAEA,IAAI,YAAY;AAGT,SAAS,eAAuB;AACrC,SAAO,EAAE;AACX;AAGO,SAAS,QAAQ,QAA2B,SAAqC;AACtF,QAAM,SAAS,CAAC,GAAG,MAAM,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,SAAS,EAAE,MAAM;AAC7D,MAAI,SAAS;AACX,UAAM,MAAM,OAAO,UAAU,CAAC,MAAM,EAAE,OAAO,OAAO;AACpD,QAAI,OAAO,GAAG;AACZ,YAAM,CAAC,IAAI,IAAI,OAAO,OAAO,KAAK,CAAC;AACnC,UAAI,KAAM,QAAO,KAAK,IAAI;AAAA,IAC5B;AAAA,EACF;AACA,SAAO,OAAO,IAAI,CAAC,GAAG,OAAO,EAAE,GAAG,GAAG,QAAQ,SAAS,EAAA,EAAI;AAC5D;"}
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ function serializeContext(items) {
4
+ if (items.length === 0) return "";
5
+ const lines = items.map((item) => {
6
+ const entries = Object.entries(item.fields ?? {}).filter(([, v]) => v != null && v !== "").map(([k, v]) => `${k}: ${v}`).join(", ");
7
+ return entries ? `[${item.type}] ${item.label} (${entries})` : `[${item.type}] ${item.label}`;
8
+ });
9
+ return `Context:
10
+ ${lines.join("\n")}
11
+
12
+ `;
13
+ }
14
+ const CONTEXT_LINE_RE = /^\[([^\]]+)\]\s+(.+?)(?:\s+\((.+)\))?$/;
15
+ function parseContextPrefix(text) {
16
+ if (!text.startsWith("Context:\n")) return { items: [], question: text };
17
+ const blockEnd = text.indexOf("\n\n");
18
+ if (blockEnd === -1) return { items: [], question: text };
19
+ const block = text.slice("Context:\n".length, blockEnd);
20
+ const question = text.slice(blockEnd + 2);
21
+ const items = [];
22
+ for (const line of block.split("\n")) {
23
+ const m = line.match(CONTEXT_LINE_RE);
24
+ if (!m) continue;
25
+ const fields = {};
26
+ if (m[3]) {
27
+ for (const pair of m[3].split(/,\s*(?=[A-Za-z0-9_]+:)/)) {
28
+ const idx = pair.indexOf(":");
29
+ if (idx > 0) fields[pair.slice(0, idx).trim()] = pair.slice(idx + 1).trim();
30
+ }
31
+ }
32
+ items.push({ id: `parsed-${items.length}`, type: m[1], label: m[2], fields });
33
+ }
34
+ return { items, question };
35
+ }
36
+ let nextId = 0;
37
+ function makeContextId() {
38
+ return `ctx-${++nextId}-${Date.now()}`;
39
+ }
40
+ exports.makeContextId = makeContextId;
41
+ exports.parseContextPrefix = parseContextPrefix;
42
+ exports.serializeContext = serializeContext;
43
+ //# sourceMappingURL=context.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.cjs","sources":["../../../src/data/ai/context.ts"],"sourcesContent":["import type { StaticIconComponent } from \"../Icon\";\n\n/** A piece of context the user has attached to a chat (a record, a selection,\n * a document…). The `type` is an arbitrary caller-defined string; a\n * {@link ContextTypeConfig} maps it to an icon/colour for display. `fields`\n * are flat key/value details serialized into the prompt and rendered as a\n * compact suffix on the badge. */\nexport interface ChatContextItem {\n id: string;\n type: string;\n label: string;\n fields?: Record<string, string>;\n}\n\n/** Per-type display style for context badges, keyed by `ChatContextItem.type`. */\nexport interface ContextTypeStyle {\n /** Iconify name or an imported icon component. */\n icon?: string | StaticIconComponent;\n /** Tailwind classes for the badge (text + background colour). */\n className?: string;\n}\n\nexport type ContextTypeConfig = Record<string, ContextTypeStyle>;\n\n/** Serializes attached context into a `Context:` block the backend can prepend\n * to (or read alongside) the user's message. Mirrors the format parsed by\n * {@link parseContextPrefix}: `[type] label (k: v, k: v)`. Returns \"\" when\n * there is nothing attached. */\nexport function serializeContext(items: ChatContextItem[]): string {\n if (items.length === 0) return \"\";\n const lines = items.map((item) => {\n const entries = Object.entries(item.fields ?? {})\n .filter(([, v]) => v != null && v !== \"\")\n .map(([k, v]) => `${k}: ${v}`)\n .join(\", \");\n return entries ? `[${item.type}] ${item.label} (${entries})` : `[${item.type}] ${item.label}`;\n });\n return `Context:\\n${lines.join(\"\\n\")}\\n\\n`;\n}\n\nconst CONTEXT_LINE_RE = /^\\[([^\\]]+)\\]\\s+(.+?)(?:\\s+\\((.+)\\))?$/;\n\n/** Splits a message produced with a {@link serializeContext} prefix back into\n * its attached items and the bare question. When no prefix is present the\n * whole text is returned as the question with no items. */\nexport function parseContextPrefix(text: string): { items: ChatContextItem[]; question: string } {\n if (!text.startsWith(\"Context:\\n\")) return { items: [], question: text };\n const blockEnd = text.indexOf(\"\\n\\n\");\n if (blockEnd === -1) return { items: [], question: text };\n const block = text.slice(\"Context:\\n\".length, blockEnd);\n const question = text.slice(blockEnd + 2);\n const items: ChatContextItem[] = [];\n for (const line of block.split(\"\\n\")) {\n const m = line.match(CONTEXT_LINE_RE);\n if (!m) continue;\n const fields: Record<string, string> = {};\n if (m[3]) {\n for (const pair of m[3].split(/,\\s*(?=[A-Za-z0-9_]+:)/)) {\n const idx = pair.indexOf(\":\");\n if (idx > 0) fields[pair.slice(0, idx).trim()] = pair.slice(idx + 1).trim();\n }\n }\n items.push({ id: `parsed-${items.length}`, type: m[1]!, label: m[2]!, fields });\n }\n return { items, question };\n}\n\nlet nextId = 0;\n/** A process-unique id for a newly attached context item. */\nexport function makeContextId(): string {\n return `ctx-${++nextId}-${Date.now()}`;\n}\n"],"names":[],"mappings":";;AA4BO,SAAS,iBAAiB,OAAkC;AACjE,MAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,QAAM,QAAQ,MAAM,IAAI,CAAC,SAAS;AAChC,UAAM,UAAU,OAAO,QAAQ,KAAK,UAAU,CAAA,CAAE,EAC7C,OAAO,CAAC,CAAA,EAAG,CAAC,MAAM,KAAK,QAAQ,MAAM,EAAE,EACvC,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC,EAAE,EAC5B,KAAK,IAAI;AACZ,WAAO,UAAU,IAAI,KAAK,IAAI,KAAK,KAAK,KAAK,KAAK,OAAO,MAAM,IAAI,KAAK,IAAI,KAAK,KAAK,KAAK;AAAA,EAC7F,CAAC;AACD,SAAO;AAAA,EAAa,MAAM,KAAK,IAAI,CAAC;AAAA;AAAA;AACtC;AAEA,MAAM,kBAAkB;AAKjB,SAAS,mBAAmB,MAA8D;AAC/F,MAAI,CAAC,KAAK,WAAW,YAAY,EAAG,QAAO,EAAE,OAAO,CAAA,GAAI,UAAU,KAAA;AAClE,QAAM,WAAW,KAAK,QAAQ,MAAM;AACpC,MAAI,aAAa,GAAI,QAAO,EAAE,OAAO,CAAA,GAAI,UAAU,KAAA;AACnD,QAAM,QAAQ,KAAK,MAAM,aAAa,QAAQ,QAAQ;AACtD,QAAM,WAAW,KAAK,MAAM,WAAW,CAAC;AACxC,QAAM,QAA2B,CAAA;AACjC,aAAW,QAAQ,MAAM,MAAM,IAAI,GAAG;AACpC,UAAM,IAAI,KAAK,MAAM,eAAe;AACpC,QAAI,CAAC,EAAG;AACR,UAAM,SAAiC,CAAA;AACvC,QAAI,EAAE,CAAC,GAAG;AACR,iBAAW,QAAQ,EAAE,CAAC,EAAE,MAAM,wBAAwB,GAAG;AACvD,cAAM,MAAM,KAAK,QAAQ,GAAG;AAC5B,YAAI,MAAM,EAAG,QAAO,KAAK,MAAM,GAAG,GAAG,EAAE,KAAA,CAAM,IAAI,KAAK,MAAM,MAAM,CAAC,EAAE,KAAA;AAAA,MACvE;AAAA,IACF;AACA,UAAM,KAAK,EAAE,IAAI,UAAU,MAAM,MAAM,IAAI,MAAM,EAAE,CAAC,GAAI,OAAO,EAAE,CAAC,GAAI,QAAQ;AAAA,EAChF;AACA,SAAO,EAAE,OAAO,SAAA;AAClB;AAEA,IAAI,SAAS;AAEN,SAAS,gBAAwB;AACtC,SAAO,OAAO,EAAE,MAAM,IAAI,KAAK,KAAK;AACtC;;;;"}
@@ -0,0 +1,35 @@
1
+ import { StaticIconComponent } from '../Icon';
2
+ /** A piece of context the user has attached to a chat (a record, a selection,
3
+ * a document…). The `type` is an arbitrary caller-defined string; a
4
+ * {@link ContextTypeConfig} maps it to an icon/colour for display. `fields`
5
+ * are flat key/value details serialized into the prompt and rendered as a
6
+ * compact suffix on the badge. */
7
+ export interface ChatContextItem {
8
+ id: string;
9
+ type: string;
10
+ label: string;
11
+ fields?: Record<string, string>;
12
+ }
13
+ /** Per-type display style for context badges, keyed by `ChatContextItem.type`. */
14
+ export interface ContextTypeStyle {
15
+ /** Iconify name or an imported icon component. */
16
+ icon?: string | StaticIconComponent;
17
+ /** Tailwind classes for the badge (text + background colour). */
18
+ className?: string;
19
+ }
20
+ export type ContextTypeConfig = Record<string, ContextTypeStyle>;
21
+ /** Serializes attached context into a `Context:` block the backend can prepend
22
+ * to (or read alongside) the user's message. Mirrors the format parsed by
23
+ * {@link parseContextPrefix}: `[type] label (k: v, k: v)`. Returns "" when
24
+ * there is nothing attached. */
25
+ export declare function serializeContext(items: ChatContextItem[]): string;
26
+ /** Splits a message produced with a {@link serializeContext} prefix back into
27
+ * its attached items and the bare question. When no prefix is present the
28
+ * whole text is returned as the question with no items. */
29
+ export declare function parseContextPrefix(text: string): {
30
+ items: ChatContextItem[];
31
+ question: string;
32
+ };
33
+ /** A process-unique id for a newly attached context item. */
34
+ export declare function makeContextId(): string;
35
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../../src/data/ai/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAEnD;;;;mCAImC;AACnC,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjC;AAED,kFAAkF;AAClF,MAAM,WAAW,gBAAgB;IAC/B,kDAAkD;IAClD,IAAI,CAAC,EAAE,MAAM,GAAG,mBAAmB,CAAC;IACpC,iEAAiE;IACjE,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,MAAM,iBAAiB,GAAG,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;AAEjE;;;iCAGiC;AACjC,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,eAAe,EAAE,GAAG,MAAM,CAUjE;AAID;;4DAE4D;AAC5D,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,eAAe,EAAE,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAoB/F;AAGD,6DAA6D;AAC7D,wBAAgB,aAAa,IAAI,MAAM,CAEtC"}
@@ -0,0 +1,43 @@
1
+ function serializeContext(items) {
2
+ if (items.length === 0) return "";
3
+ const lines = items.map((item) => {
4
+ const entries = Object.entries(item.fields ?? {}).filter(([, v]) => v != null && v !== "").map(([k, v]) => `${k}: ${v}`).join(", ");
5
+ return entries ? `[${item.type}] ${item.label} (${entries})` : `[${item.type}] ${item.label}`;
6
+ });
7
+ return `Context:
8
+ ${lines.join("\n")}
9
+
10
+ `;
11
+ }
12
+ const CONTEXT_LINE_RE = /^\[([^\]]+)\]\s+(.+?)(?:\s+\((.+)\))?$/;
13
+ function parseContextPrefix(text) {
14
+ if (!text.startsWith("Context:\n")) return { items: [], question: text };
15
+ const blockEnd = text.indexOf("\n\n");
16
+ if (blockEnd === -1) return { items: [], question: text };
17
+ const block = text.slice("Context:\n".length, blockEnd);
18
+ const question = text.slice(blockEnd + 2);
19
+ const items = [];
20
+ for (const line of block.split("\n")) {
21
+ const m = line.match(CONTEXT_LINE_RE);
22
+ if (!m) continue;
23
+ const fields = {};
24
+ if (m[3]) {
25
+ for (const pair of m[3].split(/,\s*(?=[A-Za-z0-9_]+:)/)) {
26
+ const idx = pair.indexOf(":");
27
+ if (idx > 0) fields[pair.slice(0, idx).trim()] = pair.slice(idx + 1).trim();
28
+ }
29
+ }
30
+ items.push({ id: `parsed-${items.length}`, type: m[1], label: m[2], fields });
31
+ }
32
+ return { items, question };
33
+ }
34
+ let nextId = 0;
35
+ function makeContextId() {
36
+ return `ctx-${++nextId}-${Date.now()}`;
37
+ }
38
+ export {
39
+ makeContextId,
40
+ parseContextPrefix,
41
+ serializeContext
42
+ };
43
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sources":["../../../src/data/ai/context.ts"],"sourcesContent":["import type { StaticIconComponent } from \"../Icon\";\n\n/** A piece of context the user has attached to a chat (a record, a selection,\n * a document…). The `type` is an arbitrary caller-defined string; a\n * {@link ContextTypeConfig} maps it to an icon/colour for display. `fields`\n * are flat key/value details serialized into the prompt and rendered as a\n * compact suffix on the badge. */\nexport interface ChatContextItem {\n id: string;\n type: string;\n label: string;\n fields?: Record<string, string>;\n}\n\n/** Per-type display style for context badges, keyed by `ChatContextItem.type`. */\nexport interface ContextTypeStyle {\n /** Iconify name or an imported icon component. */\n icon?: string | StaticIconComponent;\n /** Tailwind classes for the badge (text + background colour). */\n className?: string;\n}\n\nexport type ContextTypeConfig = Record<string, ContextTypeStyle>;\n\n/** Serializes attached context into a `Context:` block the backend can prepend\n * to (or read alongside) the user's message. Mirrors the format parsed by\n * {@link parseContextPrefix}: `[type] label (k: v, k: v)`. Returns \"\" when\n * there is nothing attached. */\nexport function serializeContext(items: ChatContextItem[]): string {\n if (items.length === 0) return \"\";\n const lines = items.map((item) => {\n const entries = Object.entries(item.fields ?? {})\n .filter(([, v]) => v != null && v !== \"\")\n .map(([k, v]) => `${k}: ${v}`)\n .join(\", \");\n return entries ? `[${item.type}] ${item.label} (${entries})` : `[${item.type}] ${item.label}`;\n });\n return `Context:\\n${lines.join(\"\\n\")}\\n\\n`;\n}\n\nconst CONTEXT_LINE_RE = /^\\[([^\\]]+)\\]\\s+(.+?)(?:\\s+\\((.+)\\))?$/;\n\n/** Splits a message produced with a {@link serializeContext} prefix back into\n * its attached items and the bare question. When no prefix is present the\n * whole text is returned as the question with no items. */\nexport function parseContextPrefix(text: string): { items: ChatContextItem[]; question: string } {\n if (!text.startsWith(\"Context:\\n\")) return { items: [], question: text };\n const blockEnd = text.indexOf(\"\\n\\n\");\n if (blockEnd === -1) return { items: [], question: text };\n const block = text.slice(\"Context:\\n\".length, blockEnd);\n const question = text.slice(blockEnd + 2);\n const items: ChatContextItem[] = [];\n for (const line of block.split(\"\\n\")) {\n const m = line.match(CONTEXT_LINE_RE);\n if (!m) continue;\n const fields: Record<string, string> = {};\n if (m[3]) {\n for (const pair of m[3].split(/,\\s*(?=[A-Za-z0-9_]+:)/)) {\n const idx = pair.indexOf(\":\");\n if (idx > 0) fields[pair.slice(0, idx).trim()] = pair.slice(idx + 1).trim();\n }\n }\n items.push({ id: `parsed-${items.length}`, type: m[1]!, label: m[2]!, fields });\n }\n return { items, question };\n}\n\nlet nextId = 0;\n/** A process-unique id for a newly attached context item. */\nexport function makeContextId(): string {\n return `ctx-${++nextId}-${Date.now()}`;\n}\n"],"names":[],"mappings":"AA4BO,SAAS,iBAAiB,OAAkC;AACjE,MAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,QAAM,QAAQ,MAAM,IAAI,CAAC,SAAS;AAChC,UAAM,UAAU,OAAO,QAAQ,KAAK,UAAU,CAAA,CAAE,EAC7C,OAAO,CAAC,CAAA,EAAG,CAAC,MAAM,KAAK,QAAQ,MAAM,EAAE,EACvC,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC,EAAE,EAC5B,KAAK,IAAI;AACZ,WAAO,UAAU,IAAI,KAAK,IAAI,KAAK,KAAK,KAAK,KAAK,OAAO,MAAM,IAAI,KAAK,IAAI,KAAK,KAAK,KAAK;AAAA,EAC7F,CAAC;AACD,SAAO;AAAA,EAAa,MAAM,KAAK,IAAI,CAAC;AAAA;AAAA;AACtC;AAEA,MAAM,kBAAkB;AAKjB,SAAS,mBAAmB,MAA8D;AAC/F,MAAI,CAAC,KAAK,WAAW,YAAY,EAAG,QAAO,EAAE,OAAO,CAAA,GAAI,UAAU,KAAA;AAClE,QAAM,WAAW,KAAK,QAAQ,MAAM;AACpC,MAAI,aAAa,GAAI,QAAO,EAAE,OAAO,CAAA,GAAI,UAAU,KAAA;AACnD,QAAM,QAAQ,KAAK,MAAM,aAAa,QAAQ,QAAQ;AACtD,QAAM,WAAW,KAAK,MAAM,WAAW,CAAC;AACxC,QAAM,QAA2B,CAAA;AACjC,aAAW,QAAQ,MAAM,MAAM,IAAI,GAAG;AACpC,UAAM,IAAI,KAAK,MAAM,eAAe;AACpC,QAAI,CAAC,EAAG;AACR,UAAM,SAAiC,CAAA;AACvC,QAAI,EAAE,CAAC,GAAG;AACR,iBAAW,QAAQ,EAAE,CAAC,EAAE,MAAM,wBAAwB,GAAG;AACvD,cAAM,MAAM,KAAK,QAAQ,GAAG;AAC5B,YAAI,MAAM,EAAG,QAAO,KAAK,MAAM,GAAG,GAAG,EAAE,KAAA,CAAM,IAAI,KAAK,MAAM,MAAM,CAAC,EAAE,KAAA;AAAA,MACvE;AAAA,IACF;AACA,UAAM,KAAK,EAAE,IAAI,UAAU,MAAM,MAAM,IAAI,MAAM,EAAE,CAAC,GAAI,OAAO,EAAE,CAAC,GAAI,QAAQ;AAAA,EAChF;AACA,SAAO,EAAE,OAAO,SAAA;AAClB;AAEA,IAAI,SAAS;AAEN,SAAS,gBAAwB;AACtC,SAAO,OAAO,EAAE,MAAM,IAAI,KAAK,KAAK;AACtC;"}
@@ -0,0 +1,10 @@
1
+ export { ChatWindowManagerProvider, type ChatWindowManagerProviderProps, } from './ChatWindowManager';
2
+ export { useChatWindowManager, nextPromptId, type ChatWindowManagerValue, type ChatWindowState, type OpenPanelOpts, } from './chat-window-context';
3
+ export { ChatWindow, ChatWindowLayer, type ChatWindowProps } from './ChatWindow';
4
+ export { ChatFab, type ChatFabProps } from './ChatFab';
5
+ export { ThreadPicker, type ThreadPickerProps, type ThreadSummary, type ThreadSource, } from './ThreadPicker';
6
+ export { ContextBadges, ContextBadgesReadonly, type ContextBadgesProps, } from './ContextBadges';
7
+ export { ToolPreferences, type ToolPreferencesProps, type ToolMeta, type ToolMode, } from './ToolPreferences';
8
+ export { ContextUsage, type ContextUsageProps } from '../chat/ContextUsage';
9
+ export { serializeContext, parseContextPrefix, makeContextId, type ChatContextItem, type ContextTypeConfig, type ContextTypeStyle, } from './context';
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/data/ai/index.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,yBAAyB,EACzB,KAAK,8BAA8B,GACpC,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,oBAAoB,EACpB,YAAY,EACZ,KAAK,sBAAsB,EAC3B,KAAK,eAAe,EACpB,KAAK,aAAa,GACnB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,KAAK,eAAe,EAAE,MAAM,cAAc,CAAC;AACjF,OAAO,EAAE,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,WAAW,CAAC;AACvD,OAAO,EACL,YAAY,EACZ,KAAK,iBAAiB,EACtB,KAAK,aAAa,EAClB,KAAK,YAAY,GAClB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,aAAa,EACb,qBAAqB,EACrB,KAAK,kBAAkB,GACxB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,eAAe,EACf,KAAK,oBAAoB,EACzB,KAAK,QAAQ,EACb,KAAK,QAAQ,GACd,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAE5E,OAAO,EACL,gBAAgB,EAChB,kBAAkB,EAClB,aAAa,EACb,KAAK,eAAe,EACpB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,GACtB,MAAM,WAAW,CAAC"}
@@ -12,8 +12,10 @@ const Section = require("../../layout/Section.cjs");
12
12
  const api = require("./api.cjs");
13
13
  const CacheValue = require("./CacheValue.cjs");
14
14
  const types = require("./types.cjs");
15
+ const download = require("./download.cjs");
15
16
  const UiFolder = require("../../icons/components/UiFolder.cjs");
16
17
  const UiRefresh = require("../../icons/components/UiRefresh.cjs");
18
+ const UiDownload = require("../../icons/components/UiDownload.cjs");
17
19
  const UiTrash = require("../../icons/components/UiTrash.cjs");
18
20
  function CacheDetailPanel(props) {
19
21
  return types.isLeaf(props.node) ? /* @__PURE__ */ jsxRuntime.jsx(KeyPanel, { ...props }) : /* @__PURE__ */ jsxRuntime.jsx(PrefixPanel, { ...props });
@@ -42,6 +44,7 @@ function KeyPanel({ client, registry, node, onDeleted, className }) {
42
44
  {
43
45
  title: key,
44
46
  onRefresh: () => detail.refetch(),
47
+ onDownload: detail.data ? () => download.downloadJson(key, detail.data) : void 0,
45
48
  onDelete: remove,
46
49
  deleteLabel: "Delete key"
47
50
  }
@@ -157,6 +160,7 @@ function PrefixPanel({ client, node, onDeleted, onSelect, className }) {
157
160
  function PanelHeader({
158
161
  title,
159
162
  onRefresh,
163
+ onDownload,
160
164
  onDelete,
161
165
  deleteLabel
162
166
  }) {
@@ -173,6 +177,17 @@ function PanelHeader({
173
177
  children: /* @__PURE__ */ jsxRuntime.jsx(Icon.Icon, { icon: UiRefresh.UiRefresh, className: "text-sm" })
174
178
  }
175
179
  ),
180
+ onDownload && /* @__PURE__ */ jsxRuntime.jsx(
181
+ "button",
182
+ {
183
+ type: "button",
184
+ onClick: onDownload,
185
+ "aria-label": "Download JSON",
186
+ title: "Download JSON",
187
+ className: "inline-flex h-6 w-6 items-center justify-center rounded text-muted-foreground hover:bg-accent hover:text-accent-foreground",
188
+ children: /* @__PURE__ */ jsxRuntime.jsx(Icon.Icon, { icon: UiDownload.UiDownload, className: "text-sm" })
189
+ }
190
+ ),
176
191
  /* @__PURE__ */ jsxRuntime.jsx(
177
192
  "button",
178
193
  {
@@ -1 +1 @@
1
- {"version":3,"file":"CacheDetailPanel.cjs","sources":["../../../src/data/cache-browser/CacheDetailPanel.tsx"],"sourcesContent":["import { useState } from \"react\";\nimport { useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport { cn } from \"../../lib/utils\";\nimport { formatBytes, formatDuration, formatShort } from \"../../lib/format\";\nimport { Icon } from \"../Icon\";\nimport { UiFolder, UiRefresh, UiTrash } from \"../../icons\";\nimport { KeyValueList } from \"../KeyValueList\";\nimport { TabButton } from \"../TabButton\";\nimport { Section } from \"../../layout/Section\";\nimport { cacheQueryKeys, type CacheClient } from \"./api\";\nimport type { CacheAdapterRegistry } from \"./adapter\";\nimport { CacheValue } from \"./CacheValue\";\nimport { isLeaf, type CacheTreeNode } from \"./types\";\n\nexport type CacheDetailPanelProps = {\n client: CacheClient;\n registry: CacheAdapterRegistry;\n node: CacheTreeNode;\n /** Called after the node (key or whole prefix) was deleted. */\n onDeleted?: (node: CacheTreeNode) => void;\n /** Drill into a child prefix/key from the subtree overview. */\n onSelect?: (node: CacheTreeNode) => void;\n className?: string;\n};\n\n/**\n * Right-hand pane of the cache browser: full key detail (metadata + adapter\n * or type-aware value rendering) for leaves, an aggregated subtree overview\n * for prefix groups.\n */\nexport function CacheDetailPanel(props: CacheDetailPanelProps) {\n return isLeaf(props.node) ? <KeyPanel {...props} /> : <PrefixPanel {...props} />;\n}\n\nfunction KeyPanel({ client, registry, node, onDeleted, className }: CacheDetailPanelProps) {\n const queryClient = useQueryClient();\n const key = node.key!;\n const detail = useQuery({\n queryKey: cacheQueryKeys.key(client.baseUrl, key),\n queryFn: () => client.key(key),\n });\n const [activeTab, setActiveTab] = useState(\"value\");\n\n const ctx = { node, detail: detail.data ?? null, client };\n const adapter = registry.resolveDetail(node, detail.data ?? null);\n const tabs = registry.resolveTabs(ctx);\n\n const remove = async () => {\n if (!window.confirm(`Delete key ${key}?`)) return;\n await client.deleteKey(key);\n await queryClient.invalidateQueries({ queryKey: cacheQueryKeys.all(client.baseUrl) });\n onDeleted?.(node);\n };\n\n return (\n <div className={cn(\"flex min-h-0 flex-col gap-density-3 overflow-y-auto p-density-3\", className)}>\n <PanelHeader\n title={key}\n onRefresh={() => detail.refetch()}\n onDelete={remove}\n deleteLabel=\"Delete key\"\n />\n {detail.isError && <PanelError error={detail.error} />}\n {detail.data && (\n <>\n <KeyValueList\n items={[\n { key: \"type\", label: \"Type\", value: <code>{detail.data.type}</code> },\n {\n key: \"ttl\",\n label: \"TTL\",\n value:\n detail.data.ttlSeconds < 0\n ? \"none\"\n : formatDuration(detail.data.ttlSeconds, { from: \"s\" }),\n },\n {\n key: \"bytes\",\n label: \"Memory\",\n value: formatBytes(detail.data.bytes),\n hidden: !detail.data.bytes,\n },\n { key: \"length\", label: \"Length\", value: formatShort(detail.data.length) },\n ]}\n />\n {tabs.length > 0 && (\n <div role=\"tablist\" className=\"flex flex-wrap items-center gap-1\">\n <TabButton\n active={activeTab === \"value\"}\n onClick={() => setActiveTab(\"value\")}\n label=\"Value\"\n />\n {tabs.map((tab) => (\n <TabButton\n key={tab.id}\n active={activeTab === tab.id}\n onClick={() => setActiveTab(tab.id)}\n label={tab.label}\n />\n ))}\n </div>\n )}\n {activeTab === \"value\"\n ? (adapter?.renderDetail?.(ctx) ?? <CacheValue detail={detail.data} />)\n : tabs.find((t) => t.id === activeTab)?.render()}\n </>\n )}\n {detail.isLoading && <div className=\"text-sm text-muted-foreground\">Loading key…</div>}\n </div>\n );\n}\n\nfunction PrefixPanel({ client, node, onDeleted, onSelect, className }: CacheDetailPanelProps) {\n const queryClient = useQueryClient();\n const prefix = node.prefix ?? \"\";\n const subtree = useQuery({\n queryKey: cacheQueryKeys.tree(client.baseUrl, prefix),\n queryFn: () => client.tree(prefix),\n });\n\n const remove = async () => {\n const count = subtree.data?.keys ?? node.keys;\n if (!window.confirm(`Delete all ${count} keys under ${prefix}?`)) return;\n await client.deletePrefix(prefix);\n await queryClient.invalidateQueries({ queryKey: cacheQueryKeys.all(client.baseUrl) });\n onDeleted?.(node);\n };\n\n const children = subtree.data?.nodes ?? [];\n const maxKeys = Math.max(1, ...children.map((c) => c.keys));\n\n return (\n <div className={cn(\"flex min-h-0 flex-col gap-density-3 overflow-y-auto p-density-3\", className)}>\n <PanelHeader\n title={\n <span className=\"inline-flex items-center gap-1.5\">\n <Icon icon={UiFolder} className=\"text-muted-foreground\" />\n {prefix}\n </span>\n }\n onRefresh={() => subtree.refetch()}\n onDelete={remove}\n deleteLabel=\"Delete prefix\"\n />\n {subtree.isError && <PanelError error={subtree.error} />}\n {subtree.data && (\n <Section\n title={`${formatShort(subtree.data.keys)} keys${subtree.data.truncated ? \"+\" : \"\"}`}\n summary={`${children.length} children`}\n >\n <div className=\"flex flex-col\">\n {children.map((child) => (\n <button\n key={child.prefix ?? child.key ?? child.name}\n type=\"button\"\n onClick={() => onSelect?.(child)}\n className=\"grid grid-cols-[minmax(0,14rem)_minmax(0,1fr)_4rem] items-center gap-density-3 rounded px-density-2 py-density-1 text-left text-sm hover:bg-accent\"\n >\n <span className=\"truncate font-mono text-xs\">{child.name}</span>\n <span className=\"h-2 overflow-hidden rounded bg-muted\">\n <span\n className=\"block h-full bg-primary/60\"\n style={{ width: `${(child.keys / maxKeys) * 100}%` }}\n />\n </span>\n <span className=\"text-right text-xs text-muted-foreground\">\n {formatShort(child.keys)}\n </span>\n </button>\n ))}\n </div>\n </Section>\n )}\n {subtree.isLoading && <div className=\"text-sm text-muted-foreground\">Loading prefix…</div>}\n </div>\n );\n}\n\nfunction PanelHeader({\n title,\n onRefresh,\n onDelete,\n deleteLabel,\n}: {\n title: React.ReactNode;\n onRefresh: () => void;\n onDelete: () => void;\n deleteLabel: string;\n}) {\n return (\n <div className=\"flex items-center gap-2\">\n <h3 className=\"min-w-0 flex-1 truncate font-mono text-sm font-semibold\">{title}</h3>\n <button\n type=\"button\"\n onClick={onRefresh}\n aria-label=\"Refresh\"\n title=\"Refresh\"\n className=\"inline-flex h-6 w-6 items-center justify-center rounded text-muted-foreground hover:bg-accent hover:text-accent-foreground\"\n >\n <Icon icon={UiRefresh} className=\"text-sm\" />\n </button>\n <button\n type=\"button\"\n onClick={onDelete}\n aria-label={deleteLabel}\n title={deleteLabel}\n className=\"inline-flex h-6 w-6 items-center justify-center rounded text-muted-foreground hover:bg-destructive/10 hover:text-destructive\"\n >\n <Icon icon={UiTrash} className=\"text-sm\" />\n </button>\n </div>\n );\n}\n\nfunction PanelError({ error }: { error: unknown }) {\n return (\n <div className=\"rounded-md border border-red-300 bg-red-50 px-density-3 py-density-2 text-xs text-red-800 dark:border-red-800 dark:bg-red-950 dark:text-red-200\">\n {error instanceof Error ? error.message : String(error)}\n </div>\n );\n}\n"],"names":["isLeaf","jsx","useQueryClient","useQuery","cacheQueryKeys","useState","cn","jsxs","Fragment","KeyValueList","formatDuration","formatBytes","formatShort","TabButton","CacheValue","_a","Icon","UiFolder","Section","UiRefresh","UiTrash"],"mappings":"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"}
1
+ {"version":3,"file":"CacheDetailPanel.cjs","sources":["../../../src/data/cache-browser/CacheDetailPanel.tsx"],"sourcesContent":["import { useState } from \"react\";\nimport { useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport { cn } from \"../../lib/utils\";\nimport { formatBytes, formatDuration, formatShort } from \"../../lib/format\";\nimport { Icon } from \"../Icon\";\nimport { UiDownload, UiFolder, UiRefresh, UiTrash } from \"../../icons\";\nimport { KeyValueList } from \"../KeyValueList\";\nimport { TabButton } from \"../TabButton\";\nimport { Section } from \"../../layout/Section\";\nimport { cacheQueryKeys, type CacheClient } from \"./api\";\nimport type { CacheAdapterRegistry } from \"./adapter\";\nimport { CacheValue } from \"./CacheValue\";\nimport { isLeaf, type CacheTreeNode } from \"./types\";\nimport { downloadJson } from \"./download\";\n\nexport type CacheDetailPanelProps = {\n client: CacheClient;\n registry: CacheAdapterRegistry;\n node: CacheTreeNode;\n /** Called after the node (key or whole prefix) was deleted. */\n onDeleted?: (node: CacheTreeNode) => void;\n /** Drill into a child prefix/key from the subtree overview. */\n onSelect?: (node: CacheTreeNode) => void;\n className?: string;\n};\n\n/**\n * Right-hand pane of the cache browser: full key detail (metadata + adapter\n * or type-aware value rendering) for leaves, an aggregated subtree overview\n * for prefix groups.\n */\nexport function CacheDetailPanel(props: CacheDetailPanelProps) {\n return isLeaf(props.node) ? <KeyPanel {...props} /> : <PrefixPanel {...props} />;\n}\n\nfunction KeyPanel({ client, registry, node, onDeleted, className }: CacheDetailPanelProps) {\n const queryClient = useQueryClient();\n const key = node.key!;\n const detail = useQuery({\n queryKey: cacheQueryKeys.key(client.baseUrl, key),\n queryFn: () => client.key(key),\n });\n const [activeTab, setActiveTab] = useState(\"value\");\n\n const ctx = { node, detail: detail.data ?? null, client };\n const adapter = registry.resolveDetail(node, detail.data ?? null);\n const tabs = registry.resolveTabs(ctx);\n\n const remove = async () => {\n if (!window.confirm(`Delete key ${key}?`)) return;\n await client.deleteKey(key);\n await queryClient.invalidateQueries({ queryKey: cacheQueryKeys.all(client.baseUrl) });\n onDeleted?.(node);\n };\n\n return (\n <div className={cn(\"flex min-h-0 flex-col gap-density-3 overflow-y-auto p-density-3\", className)}>\n <PanelHeader\n title={key}\n onRefresh={() => detail.refetch()}\n onDownload={detail.data ? () => downloadJson(key, detail.data!) : undefined}\n onDelete={remove}\n deleteLabel=\"Delete key\"\n />\n {detail.isError && <PanelError error={detail.error} />}\n {detail.data && (\n <>\n <KeyValueList\n items={[\n { key: \"type\", label: \"Type\", value: <code>{detail.data.type}</code> },\n {\n key: \"ttl\",\n label: \"TTL\",\n value:\n detail.data.ttlSeconds < 0\n ? \"none\"\n : formatDuration(detail.data.ttlSeconds, { from: \"s\" }),\n },\n {\n key: \"bytes\",\n label: \"Memory\",\n value: formatBytes(detail.data.bytes),\n hidden: !detail.data.bytes,\n },\n { key: \"length\", label: \"Length\", value: formatShort(detail.data.length) },\n ]}\n />\n {tabs.length > 0 && (\n <div role=\"tablist\" className=\"flex flex-wrap items-center gap-1\">\n <TabButton\n active={activeTab === \"value\"}\n onClick={() => setActiveTab(\"value\")}\n label=\"Value\"\n />\n {tabs.map((tab) => (\n <TabButton\n key={tab.id}\n active={activeTab === tab.id}\n onClick={() => setActiveTab(tab.id)}\n label={tab.label}\n />\n ))}\n </div>\n )}\n {activeTab === \"value\"\n ? (adapter?.renderDetail?.(ctx) ?? <CacheValue detail={detail.data} />)\n : tabs.find((t) => t.id === activeTab)?.render()}\n </>\n )}\n {detail.isLoading && <div className=\"text-sm text-muted-foreground\">Loading key…</div>}\n </div>\n );\n}\n\nfunction PrefixPanel({ client, node, onDeleted, onSelect, className }: CacheDetailPanelProps) {\n const queryClient = useQueryClient();\n const prefix = node.prefix ?? \"\";\n const subtree = useQuery({\n queryKey: cacheQueryKeys.tree(client.baseUrl, prefix),\n queryFn: () => client.tree(prefix),\n });\n\n const remove = async () => {\n const count = subtree.data?.keys ?? node.keys;\n if (!window.confirm(`Delete all ${count} keys under ${prefix}?`)) return;\n await client.deletePrefix(prefix);\n await queryClient.invalidateQueries({ queryKey: cacheQueryKeys.all(client.baseUrl) });\n onDeleted?.(node);\n };\n\n const children = subtree.data?.nodes ?? [];\n const maxKeys = Math.max(1, ...children.map((c) => c.keys));\n\n return (\n <div className={cn(\"flex min-h-0 flex-col gap-density-3 overflow-y-auto p-density-3\", className)}>\n <PanelHeader\n title={\n <span className=\"inline-flex items-center gap-1.5\">\n <Icon icon={UiFolder} className=\"text-muted-foreground\" />\n {prefix}\n </span>\n }\n onRefresh={() => subtree.refetch()}\n onDelete={remove}\n deleteLabel=\"Delete prefix\"\n />\n {subtree.isError && <PanelError error={subtree.error} />}\n {subtree.data && (\n <Section\n title={`${formatShort(subtree.data.keys)} keys${subtree.data.truncated ? \"+\" : \"\"}`}\n summary={`${children.length} children`}\n >\n <div className=\"flex flex-col\">\n {children.map((child) => (\n <button\n key={child.prefix ?? child.key ?? child.name}\n type=\"button\"\n onClick={() => onSelect?.(child)}\n className=\"grid grid-cols-[minmax(0,14rem)_minmax(0,1fr)_4rem] items-center gap-density-3 rounded px-density-2 py-density-1 text-left text-sm hover:bg-accent\"\n >\n <span className=\"truncate font-mono text-xs\">{child.name}</span>\n <span className=\"h-2 overflow-hidden rounded bg-muted\">\n <span\n className=\"block h-full bg-primary/60\"\n style={{ width: `${(child.keys / maxKeys) * 100}%` }}\n />\n </span>\n <span className=\"text-right text-xs text-muted-foreground\">\n {formatShort(child.keys)}\n </span>\n </button>\n ))}\n </div>\n </Section>\n )}\n {subtree.isLoading && <div className=\"text-sm text-muted-foreground\">Loading prefix…</div>}\n </div>\n );\n}\n\nfunction PanelHeader({\n title,\n onRefresh,\n onDownload,\n onDelete,\n deleteLabel,\n}: {\n title: React.ReactNode;\n onRefresh: () => void;\n onDownload?: (() => void) | undefined;\n onDelete: () => void;\n deleteLabel: string;\n}) {\n return (\n <div className=\"flex items-center gap-2\">\n <h3 className=\"min-w-0 flex-1 truncate font-mono text-sm font-semibold\">{title}</h3>\n <button\n type=\"button\"\n onClick={onRefresh}\n aria-label=\"Refresh\"\n title=\"Refresh\"\n className=\"inline-flex h-6 w-6 items-center justify-center rounded text-muted-foreground hover:bg-accent hover:text-accent-foreground\"\n >\n <Icon icon={UiRefresh} className=\"text-sm\" />\n </button>\n {onDownload && (\n <button\n type=\"button\"\n onClick={onDownload}\n aria-label=\"Download JSON\"\n title=\"Download JSON\"\n className=\"inline-flex h-6 w-6 items-center justify-center rounded text-muted-foreground hover:bg-accent hover:text-accent-foreground\"\n >\n <Icon icon={UiDownload} className=\"text-sm\" />\n </button>\n )}\n <button\n type=\"button\"\n onClick={onDelete}\n aria-label={deleteLabel}\n title={deleteLabel}\n className=\"inline-flex h-6 w-6 items-center justify-center rounded text-muted-foreground hover:bg-destructive/10 hover:text-destructive\"\n >\n <Icon icon={UiTrash} className=\"text-sm\" />\n </button>\n </div>\n );\n}\n\nfunction PanelError({ error }: { error: unknown }) {\n return (\n <div className=\"rounded-md border border-red-300 bg-red-50 px-density-3 py-density-2 text-xs text-red-800 dark:border-red-800 dark:bg-red-950 dark:text-red-200\">\n {error instanceof Error ? error.message : String(error)}\n </div>\n );\n}\n"],"names":["isLeaf","jsx","useQueryClient","useQuery","cacheQueryKeys","useState","cn","downloadJson","jsxs","Fragment","KeyValueList","formatDuration","formatBytes","formatShort","TabButton","CacheValue","_a","Icon","UiFolder","Section","UiRefresh","UiDownload","UiTrash"],"mappings":"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"}