@parallelworks/ui 0.18.0 → 0.19.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (349) hide show
  1. package/README.md +86 -6
  2. package/dist/ai/adapter/memoryStore.d.ts +8 -0
  3. package/dist/ai/adapter/memoryStore.js +152 -0
  4. package/dist/ai/adapter/mock/index.d.ts +2 -0
  5. package/dist/ai/adapter/mock/index.js +3 -0
  6. package/dist/ai/adapter/mock/mockAdapter.d.ts +4 -0
  7. package/dist/ai/adapter/mock/mockAdapter.js +81 -0
  8. package/dist/ai/adapter/openai/createOpenAIStream.d.ts +9 -0
  9. package/dist/ai/adapter/openai/createOpenAIStream.js +33 -0
  10. package/dist/ai/adapter/openai/errors.d.ts +3 -0
  11. package/dist/ai/adapter/openai/errors.js +37 -0
  12. package/dist/ai/adapter/openai/index.d.ts +6 -0
  13. package/dist/ai/adapter/openai/index.js +6 -0
  14. package/dist/ai/adapter/openai/openaiAdapter.d.ts +9 -0
  15. package/dist/ai/adapter/openai/openaiAdapter.js +54 -0
  16. package/dist/ai/adapter/openai/responses.d.ts +4 -0
  17. package/dist/ai/adapter/openai/responses.js +108 -0
  18. package/dist/ai/adapter/openai/sse.d.ts +24 -0
  19. package/dist/ai/adapter/openai/sse.js +112 -0
  20. package/dist/ai/adapter/openai/wire.d.ts +40 -0
  21. package/dist/ai/adapter/types.d.ts +131 -0
  22. package/dist/ai/adapter/types.js +11 -0
  23. package/dist/ai/agent/classifier.d.ts +2 -0
  24. package/dist/ai/agent/classifier.js +12 -0
  25. package/dist/ai/agent/diff.d.ts +35 -0
  26. package/dist/ai/agent/diff.js +223 -0
  27. package/dist/ai/agent/diffHighlight.d.ts +6 -0
  28. package/dist/ai/agent/diffHighlight.js +101 -0
  29. package/dist/ai/agent/index.d.ts +6 -0
  30. package/dist/ai/agent/permissions.d.ts +11 -0
  31. package/dist/ai/agent/permissions.js +29 -0
  32. package/dist/ai/agent/toolfmt.d.ts +18 -0
  33. package/dist/ai/agent/toolfmt.js +383 -0
  34. package/dist/ai/agent/transcript.d.ts +38 -0
  35. package/dist/ai/agent/transcript.js +127 -0
  36. package/dist/ai/ai.css +325 -0
  37. package/dist/ai/components/AllocationSelector.d.ts +4 -0
  38. package/dist/ai/components/AllocationSelector.js +56 -0
  39. package/dist/ai/components/AttachmentManager.d.ts +1 -0
  40. package/dist/ai/components/AttachmentManager.js +144 -0
  41. package/dist/ai/components/AttachmentUpload.d.ts +24 -0
  42. package/dist/ai/components/AttachmentUpload.js +179 -0
  43. package/dist/ai/components/BlockedGroupBanner.d.ts +1 -0
  44. package/dist/ai/components/BlockedGroupBanner.js +29 -0
  45. package/dist/ai/components/BranchNavigator.d.ts +8 -0
  46. package/dist/ai/components/BranchNavigator.js +57 -0
  47. package/dist/ai/components/ChatEmptyState.d.ts +3 -0
  48. package/dist/ai/components/ChatEmptyState.js +171 -0
  49. package/dist/ai/components/ChatInput.d.ts +45 -0
  50. package/dist/ai/components/ChatInput.js +265 -0
  51. package/dist/ai/components/ChatLayout.d.ts +5 -0
  52. package/dist/ai/components/ChatLayout.js +15 -0
  53. package/dist/ai/components/ChatMessage.d.ts +24 -0
  54. package/dist/ai/components/ChatMessage.js +338 -0
  55. package/dist/ai/components/ChatMessageList.d.ts +35 -0
  56. package/dist/ai/components/ChatMessageList.js +301 -0
  57. package/dist/ai/components/ChatSidebar.d.ts +5 -0
  58. package/dist/ai/components/ChatSidebar.js +345 -0
  59. package/dist/ai/components/ChatThread.d.ts +3 -0
  60. package/dist/ai/components/ChatThread.js +198 -0
  61. package/dist/ai/components/ComposerChrome.d.ts +18 -0
  62. package/dist/ai/components/ComposerChrome.js +50 -0
  63. package/dist/ai/components/ComposerFrame.d.ts +16 -0
  64. package/dist/ai/components/ComposerFrame.js +33 -0
  65. package/dist/ai/components/DragOverlay.d.ts +5 -0
  66. package/dist/ai/components/DragOverlay.js +20 -0
  67. package/dist/ai/components/ModelSelector.d.ts +6 -0
  68. package/dist/ai/components/ModelSelector.js +343 -0
  69. package/dist/ai/components/ShareDialog.d.ts +11 -0
  70. package/dist/ai/components/ShareDialog.js +260 -0
  71. package/dist/ai/components/SlashMenu.d.ts +28 -0
  72. package/dist/ai/components/SlashMenu.js +91 -0
  73. package/dist/ai/components/agent/ActivityLine.d.ts +21 -0
  74. package/dist/ai/components/agent/ActivityLine.js +151 -0
  75. package/dist/ai/components/agent/AgentMessageParts.d.ts +54 -0
  76. package/dist/ai/components/agent/AgentMessageParts.js +721 -0
  77. package/dist/ai/components/agent/PermissionPicker.d.ts +11 -0
  78. package/dist/ai/components/agent/PermissionPicker.js +38 -0
  79. package/dist/ai/components/attachmentKeys.d.ts +4 -0
  80. package/dist/ai/components/attachmentKeys.js +10 -0
  81. package/dist/ai/core/ChatProvider.d.ts +66 -0
  82. package/dist/ai/core/ChatProvider.js +848 -0
  83. package/dist/ai/core/KeyboardShortcutsProvider.d.ts +5 -0
  84. package/dist/ai/core/KeyboardShortcutsProvider.js +9 -0
  85. package/dist/ai/core/chatReducer.d.ts +114 -0
  86. package/dist/ai/core/chatReducer.js +223 -0
  87. package/dist/ai/core/config.d.ts +47 -0
  88. package/dist/ai/core/config.js +45 -0
  89. package/dist/ai/core/events.d.ts +1 -0
  90. package/dist/ai/core/events.js +4 -0
  91. package/dist/ai/core/exportConversation.d.ts +4 -0
  92. package/dist/ai/core/exportConversation.js +42 -0
  93. package/dist/ai/core/greeting.d.ts +3 -0
  94. package/dist/ai/core/greeting.js +38 -0
  95. package/dist/ai/core/parts.d.ts +11 -0
  96. package/dist/ai/core/parts.js +84 -0
  97. package/dist/ai/core/useDragDrop.d.ts +14 -0
  98. package/dist/ai/core/useDragDrop.js +36 -0
  99. package/dist/ai/core/useKeyboardShortcuts.d.ts +12 -0
  100. package/dist/ai/core/useKeyboardShortcuts.js +77 -0
  101. package/dist/ai/core/useSSEStream.d.ts +34 -0
  102. package/dist/ai/core/useSSEStream.js +98 -0
  103. package/dist/ai/index.d.ts +40 -0
  104. package/dist/ai/index.js +44 -0
  105. package/dist/ai/strings.d.ts +167 -0
  106. package/dist/ai/strings.js +175 -0
  107. package/dist/ai/types.d.ts +236 -0
  108. package/dist/ai/ui/Avatar.d.ts +8 -0
  109. package/dist/ai/ui/Avatar.js +35 -0
  110. package/dist/ai/ui/Dropdown.d.ts +31 -0
  111. package/dist/ai/ui/Dropdown.js +110 -0
  112. package/dist/ai/ui/Markdown.d.ts +8 -0
  113. package/dist/ai/ui/Markdown.js +79 -0
  114. package/dist/ai/ui/Notice.d.ts +21 -0
  115. package/dist/ai/ui/Notice.js +77 -0
  116. package/dist/ai/ui/buttons.d.ts +1 -0
  117. package/dist/ai/ui/codeBreaks.d.ts +16 -0
  118. package/dist/ai/ui/codeBreaks.js +36 -0
  119. package/dist/ai/ui/prose.d.ts +1 -0
  120. package/dist/ai/ui/prose.js +13 -0
  121. package/dist/ai/ui/sidebar.d.ts +81 -0
  122. package/dist/ai/ui/sidebar.js +148 -0
  123. package/dist/ai/utils.d.ts +4 -0
  124. package/dist/ai/utils.js +23 -0
  125. package/dist/assets/{editor.worker-CuBRIwi-.js → editor.worker-BmHUIVG4.js} +194 -163
  126. package/dist/assets/{json.worker-8ytS02vz.js → json.worker-D8bJ92nw.js} +384 -338
  127. package/dist/assets/{yaml.worker-DJC-VUcv.js → yaml.worker-C4gyGAko.js} +15657 -13823
  128. package/dist/components/AddMenu.js +46 -0
  129. package/dist/components/Avatar.d.ts +1 -1
  130. package/dist/components/Avatar.js +46 -0
  131. package/dist/{chunks/BareModal-BtRiQezg.js → components/BareModal.js} +1 -1
  132. package/dist/components/Breadcrumbs.d.ts +1 -1
  133. package/dist/components/Breadcrumbs.js +83 -0
  134. package/dist/components/Button.js +83 -0
  135. package/dist/components/Callout.js +23 -0
  136. package/dist/components/Card.js +31 -0
  137. package/dist/components/CollapsiblePanel.js +77 -0
  138. package/dist/components/ConfirmModal.js +74 -0
  139. package/dist/components/CopyToClipboard.js +81 -0
  140. package/dist/{chunks/CreateModal-BY6DLmur.js → components/CreateModal.js} +10 -189
  141. package/dist/components/DescriptionList.js +42 -0
  142. package/dist/components/Dropdown.d.ts +1 -1
  143. package/dist/components/Dropdown.js +349 -0
  144. package/dist/components/EmptyState.d.ts +1 -1
  145. package/dist/components/EmptyState.js +27 -0
  146. package/dist/components/Filter.js +32 -0
  147. package/dist/components/FilterPill.js +13 -0
  148. package/dist/components/IconButton.js +34 -0
  149. package/dist/components/Indicator.d.ts +2 -2
  150. package/dist/{chunks/Indicator-hBSIxOPK.js → components/Indicator.js} +1 -1
  151. package/dist/components/Input.d.ts +1 -1
  152. package/dist/components/Input.js +88 -0
  153. package/dist/components/LetterBadge.d.ts +1 -1
  154. package/dist/components/LetterBadge.js +13 -0
  155. package/dist/components/Listbox.js +123 -0
  156. package/dist/{chunks/Loader-BXoXTZGc.js → components/Loader.js} +1 -1
  157. package/dist/components/Markdown.js +15 -0
  158. package/dist/components/MarkdownImpl.d.ts +1 -1
  159. package/dist/components/MultiSelect.js +171 -0
  160. package/dist/components/Overview.js +39 -0
  161. package/dist/components/PageHeader.js +194 -0
  162. package/dist/components/Pagination.js +35 -0
  163. package/dist/components/Provider.d.ts +16 -65
  164. package/dist/{chunks/Provider-Ghua9PkN.js → components/Provider.js} +54 -20
  165. package/dist/{chunks/RequiredMark-DfLdYbYZ.js → components/RequiredMark.js} +1 -1
  166. package/dist/components/SectionHeader.js +11 -0
  167. package/dist/components/SettingModeOption.js +30 -0
  168. package/dist/components/SettingRow.d.ts +1 -1
  169. package/dist/components/SettingRow.js +35 -0
  170. package/dist/components/SettingsCard.js +31 -0
  171. package/dist/components/SettingsGroup.d.ts +1 -1
  172. package/dist/components/SettingsGroup.js +17 -0
  173. package/dist/components/Sort.js +42 -0
  174. package/dist/components/StatusBadge.js +63 -0
  175. package/dist/components/SwitchToggle.js +59 -0
  176. package/dist/{chunks/SwitchToggleSmall-FcsaYSTs.js → components/SwitchToggleSmall.js} +1 -1
  177. package/dist/{chunks/Table-4OHjdKdO.js → components/Table.js} +7 -5
  178. package/dist/components/Toggle.js +20 -0
  179. package/dist/{chunks/Tooltip-Crxo_eU_.js → components/Tooltip.js} +6 -4
  180. package/dist/{chunks/StatusBadge-C1Blx_cW.js → components/dropdownUtils.js} +2 -63
  181. package/dist/components/focus.d.ts +2 -0
  182. package/dist/components/focus.js +7 -0
  183. package/dist/components/ghostButton.js +7 -0
  184. package/dist/components/inputClasses.js +4 -0
  185. package/dist/components/keys.d.ts +12 -0
  186. package/dist/components/keys.js +27 -0
  187. package/dist/components/relativeTime.js +32 -0
  188. package/dist/{chunks/useCssIsDark-DHr05dG2.js → components/useCssIsDark.js} +1 -1
  189. package/dist/duration.d.ts +3 -0
  190. package/dist/duration.js +17 -0
  191. package/dist/editor/Editor.js +13 -0
  192. package/dist/editor/EditorField.js +53 -0
  193. package/dist/editor/FormCodePanel.js +173 -0
  194. package/dist/editor/Monaco.d.ts +1 -20
  195. package/dist/editor/Monaco.js +112 -0
  196. package/dist/editor/index.d.ts +2 -1
  197. package/dist/editor/index.js +7 -2
  198. package/dist/editor/themes.js +91 -0
  199. package/dist/editor/workers.js +29 -0
  200. package/dist/editor/yaml.d.ts +5 -0
  201. package/dist/editor/yaml.js +15 -0
  202. package/dist/engine.d.ts +98 -0
  203. package/dist/file-explorer/FileExplorer.d.ts +11 -2
  204. package/dist/file-explorer/FileExplorer.js +1402 -0
  205. package/dist/file-explorer/FileExplorerContext.d.ts +1 -1
  206. package/dist/file-explorer/FileExplorerContext.js +370 -0
  207. package/dist/file-explorer/FilePreview/CodePreviewEditor.d.ts +1 -1
  208. package/dist/{chunks/CodePreviewEditor-4lx3kE-w.js → file-explorer/FilePreview/CodePreviewEditor.js} +3 -2
  209. package/dist/file-explorer/FilePreview/Inline.js +45 -0
  210. package/dist/file-explorer/FilePreview/StreamedBadge.js +16 -0
  211. package/dist/file-explorer/FilePreview/Viewer.js +526 -0
  212. package/dist/file-explorer/FilePreview/index.js +266 -0
  213. package/dist/file-explorer/FilePreview/parse.js +63 -0
  214. package/dist/file-explorer/FilePreview/previewCache.js +98 -0
  215. package/dist/file-explorer/FilePreview/previewType.d.ts +1 -1
  216. package/dist/file-explorer/FilePreview/previewType.js +151 -0
  217. package/dist/file-explorer/FilePreview/readCappedBytes.js +196 -0
  218. package/dist/file-explorer/FilePreview/useObjectBlobUrl.js +95 -0
  219. package/dist/file-explorer/FilePreview/useObjectText.js +109 -0
  220. package/dist/file-explorer/FilePreview/usePresignedUrl.js +73 -0
  221. package/dist/file-explorer/FileRow.d.ts +1 -1
  222. package/dist/file-explorer/FileRow.js +165 -0
  223. package/dist/file-explorer/FileRowsWindow.js +92 -0
  224. package/dist/file-explorer/FileTable.js +172 -0
  225. package/dist/file-explorer/FileTableHeaders.js +49 -0
  226. package/dist/file-explorer/LoadMoreRow.js +46 -0
  227. package/dist/file-explorer/TreeView.js +376 -0
  228. package/dist/file-explorer/helpers.d.ts +4 -4
  229. package/dist/file-explorer/helpers.js +537 -0
  230. package/dist/file-explorer/index.d.ts +3 -3
  231. package/dist/file-explorer/index.js +7 -5705
  232. package/dist/file-explorer/lib/batch.js +39 -0
  233. package/dist/file-explorer/lib/errors.js +9 -0
  234. package/dist/file-explorer/lib/paging.js +124 -0
  235. package/dist/file-explorer/lib/types.d.ts +6 -1
  236. package/dist/file-explorer/lib/utils.d.ts +1 -3
  237. package/dist/file-explorer/lib/utils.js +322 -0
  238. package/dist/file-explorer/toasts.js +400 -0
  239. package/dist/file-explorer/treeRows.js +73 -0
  240. package/dist/file-explorer/useNearEnd.d.ts +1 -1
  241. package/dist/file-explorer/useNearEnd.js +27 -0
  242. package/dist/form/FieldWrapper.d.ts +2 -2
  243. package/dist/form/FieldWrapper.js +54 -0
  244. package/dist/form/Fields/BooleanField.js +51 -0
  245. package/dist/form/Fields/CheckboxGroupField.js +72 -0
  246. package/dist/form/Fields/ColorField.js +33 -0
  247. package/dist/form/Fields/DropdownField.js +49 -0
  248. package/dist/form/Fields/DurationField.js +130 -0
  249. package/dist/form/Fields/LabelField.js +19 -0
  250. package/dist/form/Fields/MultiDropdownField.js +40 -0
  251. package/dist/form/Fields/NumberField.js +51 -0
  252. package/dist/form/Fields/ObjectField.js +54 -0
  253. package/dist/form/Fields/RadioField.js +49 -0
  254. package/dist/form/Fields/RangeField.js +58 -0
  255. package/dist/form/Fields/ResourceOptionIcon.d.ts +1 -1
  256. package/dist/form/Fields/ResourceOptionIcon.js +21 -0
  257. package/dist/form/Fields/StepField.js +6 -0
  258. package/dist/form/Fields/StringField.js +37 -0
  259. package/dist/form/Fields/TextAreaField.js +31 -0
  260. package/dist/form/Fields/durationValidity.js +11 -0
  261. package/dist/form/Form.d.ts +4 -21
  262. package/dist/form/Form.js +643 -0
  263. package/dist/form/SpecialTypes/DropdownWrapper.js +30 -0
  264. package/dist/form/SpecialTypes/FormikCustomDropdown.js +122 -0
  265. package/dist/form/SpecialTypes/FormikCustomInput.js +111 -0
  266. package/dist/form/SpecialTypes/FormikMultiSelectDropdown.js +31 -0
  267. package/dist/form/SpecialTypes/FormikNumericInput.js +60 -0
  268. package/dist/form/Wizard/WizardContainer.js +138 -0
  269. package/dist/form/Wizard/WizardNavigation.js +92 -0
  270. package/dist/form/Wizard/WizardStepContent.js +35 -0
  271. package/dist/form/Wizard/WizardStepIndicator.js +108 -0
  272. package/dist/form/Wizard/useWizardState.js +118 -0
  273. package/dist/form/Wizard/utils.js +34 -0
  274. package/dist/form/fieldContext.js +26 -0
  275. package/dist/form/fieldRegistry.js +50 -0
  276. package/dist/form/index.d.ts +11 -12
  277. package/dist/form/index.js +18 -2445
  278. package/dist/form/lib.d.ts +6 -1
  279. package/dist/{chunks/FieldWrapper-Bef01EWO.js → form/lib.js} +5 -104
  280. package/dist/form/types/fieldComponentTypes.d.ts +3 -2
  281. package/dist/form/types/fieldTypes.d.ts +6 -20
  282. package/dist/form/useParsedOpts.d.ts +1 -1
  283. package/dist/form/useParsedOpts.js +62 -0
  284. package/dist/form/usePrevious.js +11 -0
  285. package/dist/form/utils/checkShowIfObject.js +14 -0
  286. package/dist/form/utils/{slurmDuration.d.ts → duration.d.ts} +2 -2
  287. package/dist/form/utils/duration.js +69 -0
  288. package/dist/form/utils/getParentValue.js +23 -0
  289. package/dist/form/utils/getPlaceholder.js +9 -0
  290. package/dist/form/utils/getValueUsingPath.js +23 -0
  291. package/dist/form/utils/secondaryField.js +22 -0
  292. package/dist/graph/AnnotationBanner.js +141 -0
  293. package/dist/graph/Collapse.js +41 -0
  294. package/dist/{workflow/index.js → graph/DependencyGraph.js} +76 -1163
  295. package/dist/graph/JobSummary.js +104 -0
  296. package/dist/{workflow → graph}/MatrixGroup.d.ts +2 -2
  297. package/dist/graph/MatrixGroup.js +107 -0
  298. package/dist/graph/Reveal.js +57 -0
  299. package/dist/graph/TreeView.js +711 -0
  300. package/dist/{workflow → graph}/index.d.ts +1 -1
  301. package/dist/graph/index.js +2 -0
  302. package/dist/{workflow → graph}/types.d.ts +3 -3
  303. package/dist/graph/types.js +6 -0
  304. package/dist/icons.d.ts +20 -21
  305. package/dist/index.d.ts +38 -40
  306. package/dist/index.js +47 -599
  307. package/dist/list/ActionToolbar.js +184 -0
  308. package/dist/list/HoverCard.js +73 -0
  309. package/dist/list/ListPage.js +145 -0
  310. package/dist/list/ListPager.js +59 -0
  311. package/dist/list/ListTable.d.ts +1 -1
  312. package/dist/list/ListTable.js +163 -0
  313. package/dist/list/ListViewControls.d.ts +2 -2
  314. package/dist/list/ListViewControls.js +372 -0
  315. package/dist/list/RowContextMenu.js +350 -0
  316. package/dist/list/UserHoverCard.js +117 -0
  317. package/dist/list/index.d.ts +9 -9
  318. package/dist/list/index.js +11 -2
  319. package/dist/list/listSearch.js +137 -0
  320. package/dist/list/listView.js +210 -0
  321. package/dist/list/textEntry.js +10 -0
  322. package/dist/logviewer/LogViewer.d.ts +1 -1
  323. package/dist/logviewer/LogViewer.js +750 -0
  324. package/dist/logviewer/index.d.ts +1 -0
  325. package/dist/logviewer/index.js +3 -742
  326. package/dist/logviewer/segments.d.ts +9 -0
  327. package/dist/logviewer/segments.js +80 -0
  328. package/dist/styles/fonts.css +4 -4
  329. package/dist/styles/theme.css +6 -4
  330. package/dist/styles.css +1 -1
  331. package/dist/theme/index.js +2 -2
  332. package/package.json +38 -14
  333. package/LICENSE +0 -202
  334. package/dist/chunks/Monaco-C1POOdVv.js +0 -1046
  335. package/dist/chunks/PageHeader-l49p1nM9.js +0 -690
  336. package/dist/chunks/SwitchToggle-CHPP8uZQ.js +0 -755
  337. package/dist/chunks/editor-9_uVtUyy.js +0 -347
  338. package/dist/chunks/list-qrojZZNv.js +0 -1411
  339. package/dist/editor/usesGitlab.d.ts +0 -97
  340. package/dist/form/Fields/BucketReadOnlyField.d.ts +0 -7
  341. package/dist/form/types/workflow-schema.d.ts +0 -1145
  342. package/dist/form/utils/pwResolver.d.ts +0 -18
  343. package/dist/{chunks/MarkdownImpl-Bq4QhrtA.js → components/MarkdownImpl.js} +1 -1
  344. /package/dist/{workflow → graph}/AnnotationBanner.d.ts +0 -0
  345. /package/dist/{workflow → graph}/Collapse.d.ts +0 -0
  346. /package/dist/{workflow → graph}/DependencyGraph.d.ts +0 -0
  347. /package/dist/{workflow → graph}/JobSummary.d.ts +0 -0
  348. /package/dist/{workflow → graph}/Reveal.d.ts +0 -0
  349. /package/dist/{workflow → graph}/TreeView.d.ts +0 -0
@@ -0,0 +1,5 @@
1
+ interface KeyboardShortcutsProviderProps {
2
+ children: React.ReactNode;
3
+ }
4
+ export declare function KeyboardShortcutsProvider({ children }: KeyboardShortcutsProviderProps): import("react").JSX.Element;
5
+ export {};
@@ -0,0 +1,9 @@
1
+ import { useKeyboardShortcuts } from "./useKeyboardShortcuts.js";
2
+ import { Fragment, jsx } from "react/jsx-runtime";
3
+ //#region src/ai/core/KeyboardShortcutsProvider.tsx
4
+ function KeyboardShortcutsProvider({ children }) {
5
+ useKeyboardShortcuts({ enabled: true });
6
+ return /* @__PURE__ */ jsx(Fragment, { children });
7
+ }
8
+ //#endregion
9
+ export { KeyboardShortcutsProvider };
@@ -0,0 +1,114 @@
1
+ import type { PartDelta } from '../adapter/types.js';
2
+ import type { ChatMessage, ChatModel, Conversation, ConversationSummary, MessagePart, ProviderInfo, UnreachableSession } from '../types.js';
3
+ export interface ChatState {
4
+ conversations: ConversationSummary[];
5
+ currentConversation: Conversation | null;
6
+ providers: ProviderInfo[];
7
+ models: ChatModel[];
8
+ unreachableSessions: UnreachableSession[];
9
+ selectedProvider: string | null;
10
+ selectedAllocation: string | null;
11
+ isLoading: boolean;
12
+ isLoadingConversation: boolean;
13
+ isLoadingModels: boolean;
14
+ hasLoadedModels: boolean;
15
+ modelsError: string | null;
16
+ isStreaming: boolean;
17
+ isThinking: boolean;
18
+ streamingContent: string;
19
+ streamingReasoning: string;
20
+ streamingParts: MessagePart[];
21
+ thinkingStartTime: number | null;
22
+ sidebarCollapsed: boolean;
23
+ queuedMessages: ChatMessage[];
24
+ }
25
+ export type ChatAction = {
26
+ type: 'SET_CONVERSATIONS';
27
+ conversations: ConversationSummary[];
28
+ } | {
29
+ type: 'SET_CURRENT_CONVERSATION';
30
+ conversation: Conversation | null;
31
+ } | {
32
+ type: 'UPDATE_CURRENT_CONVERSATION_TITLE';
33
+ title: string;
34
+ } | {
35
+ type: 'SET_PROVIDERS';
36
+ providers: ProviderInfo[];
37
+ } | {
38
+ type: 'SET_MODELS';
39
+ models: ChatModel[];
40
+ unreachableSessions?: UnreachableSession[];
41
+ } | {
42
+ type: 'SET_SELECTED_PROVIDER';
43
+ providerId: string | null;
44
+ } | {
45
+ type: 'SET_SELECTED_ALLOCATION';
46
+ allocation: string | null;
47
+ } | {
48
+ type: 'SET_LOADING';
49
+ isLoading: boolean;
50
+ } | {
51
+ type: 'SET_LOADING_MODELS';
52
+ isLoadingModels: boolean;
53
+ } | {
54
+ type: 'SET_MODELS_ERROR';
55
+ error: string | null;
56
+ } | {
57
+ type: 'SET_STREAMING';
58
+ isStreaming: boolean;
59
+ conversationId?: string;
60
+ } | {
61
+ type: 'SET_THINKING';
62
+ isThinking: boolean;
63
+ } | {
64
+ type: 'APPEND_STREAMING_CONTENT';
65
+ content: string;
66
+ conversationId: string;
67
+ } | {
68
+ type: 'APPEND_STREAMING_REASONING';
69
+ reasoning: string;
70
+ conversationId: string;
71
+ } | {
72
+ type: 'APPLY_STREAMING_PART';
73
+ delta: PartDelta;
74
+ conversationId: string;
75
+ } | {
76
+ type: 'CLEAR_STREAMING_CONTENT';
77
+ conversationId?: string;
78
+ } | {
79
+ type: 'ADD_MESSAGE';
80
+ message: ChatMessage;
81
+ conversationId: string;
82
+ } | {
83
+ type: 'UPDATE_MESSAGE';
84
+ messageId: string;
85
+ updates: Partial<ChatMessage>;
86
+ conversationId: string;
87
+ } | {
88
+ type: 'TOGGLE_SIDEBAR';
89
+ } | {
90
+ type: 'ADD_CONVERSATION';
91
+ conversation: ConversationSummary;
92
+ } | {
93
+ type: 'REMOVE_CONVERSATION';
94
+ conversationId: string;
95
+ } | {
96
+ type: 'SET_LOADING_CONVERSATION';
97
+ isLoadingConversation: boolean;
98
+ } | {
99
+ type: 'RESTORE_BACKGROUND_STREAM';
100
+ content: string;
101
+ reasoning: string;
102
+ parts?: MessagePart[];
103
+ } | {
104
+ type: 'ADD_QUEUED_MESSAGE';
105
+ message: ChatMessage;
106
+ conversationId?: string;
107
+ } | {
108
+ type: 'REMOVE_QUEUED_MESSAGE';
109
+ id: string;
110
+ } | {
111
+ type: 'CLEAR_QUEUED_MESSAGES';
112
+ };
113
+ export declare const initialState: ChatState;
114
+ export declare function chatReducer(state: ChatState, action: ChatAction): ChatState;
@@ -0,0 +1,223 @@
1
+ import { applyPartDelta } from "./parts.js";
2
+ //#region src/ai/core/chatReducer.ts
3
+ var initialState = {
4
+ conversations: [],
5
+ currentConversation: null,
6
+ providers: [],
7
+ models: [],
8
+ unreachableSessions: [],
9
+ selectedProvider: null,
10
+ selectedAllocation: null,
11
+ isLoading: false,
12
+ isLoadingConversation: false,
13
+ isLoadingModels: false,
14
+ hasLoadedModels: false,
15
+ modelsError: null,
16
+ isStreaming: false,
17
+ isThinking: false,
18
+ streamingContent: "",
19
+ streamingReasoning: "",
20
+ streamingParts: [],
21
+ thinkingStartTime: null,
22
+ sidebarCollapsed: false,
23
+ queuedMessages: []
24
+ };
25
+ function chatReducer(state, action) {
26
+ switch (action.type) {
27
+ case "SET_CONVERSATIONS": return {
28
+ ...state,
29
+ conversations: action.conversations
30
+ };
31
+ case "SET_CURRENT_CONVERSATION":
32
+ if (action.conversation) {
33
+ const isNewConversation = state.currentConversation?.id !== action.conversation.id;
34
+ let restoredProvider = state.selectedProvider;
35
+ if (isNewConversation) {
36
+ const messages = action.conversation.messages || [];
37
+ for (let i = messages.length - 1; i >= 0; i--) {
38
+ const msg = messages[i];
39
+ if (msg.role === "assistant" && msg.model) {
40
+ if (!state.hasLoadedModels || state.models.some((m) => m.id === msg.model)) restoredProvider = msg.model;
41
+ break;
42
+ }
43
+ }
44
+ }
45
+ return {
46
+ ...state,
47
+ currentConversation: {
48
+ ...action.conversation,
49
+ messages: action.conversation.messages || []
50
+ },
51
+ selectedProvider: restoredProvider,
52
+ ...isNewConversation && {
53
+ streamingContent: "",
54
+ streamingReasoning: "",
55
+ streamingParts: [],
56
+ isStreaming: false,
57
+ isThinking: false,
58
+ thinkingStartTime: null,
59
+ queuedMessages: []
60
+ }
61
+ };
62
+ }
63
+ return {
64
+ ...state,
65
+ currentConversation: null,
66
+ isLoadingConversation: false,
67
+ streamingContent: "",
68
+ streamingReasoning: "",
69
+ streamingParts: [],
70
+ isStreaming: false,
71
+ isThinking: false,
72
+ thinkingStartTime: null,
73
+ queuedMessages: []
74
+ };
75
+ case "UPDATE_CURRENT_CONVERSATION_TITLE":
76
+ if (!state.currentConversation) return state;
77
+ return {
78
+ ...state,
79
+ currentConversation: {
80
+ ...state.currentConversation,
81
+ title: action.title
82
+ }
83
+ };
84
+ case "SET_PROVIDERS": return {
85
+ ...state,
86
+ providers: action.providers
87
+ };
88
+ case "SET_MODELS": return {
89
+ ...state,
90
+ models: action.models,
91
+ unreachableSessions: action.unreachableSessions || [],
92
+ hasLoadedModels: true,
93
+ modelsError: null
94
+ };
95
+ case "SET_SELECTED_PROVIDER": return {
96
+ ...state,
97
+ selectedProvider: action.providerId
98
+ };
99
+ case "SET_SELECTED_ALLOCATION": return {
100
+ ...state,
101
+ selectedAllocation: action.allocation
102
+ };
103
+ case "SET_LOADING": return {
104
+ ...state,
105
+ isLoading: action.isLoading
106
+ };
107
+ case "SET_LOADING_MODELS": return {
108
+ ...state,
109
+ isLoadingModels: action.isLoadingModels
110
+ };
111
+ case "SET_MODELS_ERROR": return {
112
+ ...state,
113
+ modelsError: action.error,
114
+ hasLoadedModels: true
115
+ };
116
+ case "SET_STREAMING":
117
+ if (action.conversationId && state.currentConversation?.id !== action.conversationId) return state;
118
+ return {
119
+ ...state,
120
+ isStreaming: action.isStreaming
121
+ };
122
+ case "SET_THINKING": return {
123
+ ...state,
124
+ isThinking: action.isThinking,
125
+ thinkingStartTime: action.isThinking ? Date.now() : state.thinkingStartTime
126
+ };
127
+ case "APPEND_STREAMING_CONTENT":
128
+ if (state.currentConversation?.id !== action.conversationId) return state;
129
+ return {
130
+ ...state,
131
+ streamingContent: state.streamingContent + action.content,
132
+ isThinking: false
133
+ };
134
+ case "APPEND_STREAMING_REASONING":
135
+ if (state.currentConversation?.id !== action.conversationId) return state;
136
+ return {
137
+ ...state,
138
+ streamingReasoning: state.streamingReasoning + action.reasoning,
139
+ isThinking: true,
140
+ thinkingStartTime: state.thinkingStartTime || Date.now()
141
+ };
142
+ case "APPLY_STREAMING_PART":
143
+ if (state.currentConversation?.id !== action.conversationId) return state;
144
+ return {
145
+ ...state,
146
+ streamingParts: applyPartDelta(state.streamingParts, action.delta)
147
+ };
148
+ case "CLEAR_STREAMING_CONTENT":
149
+ if (action.conversationId && state.currentConversation?.id !== action.conversationId) return state;
150
+ return {
151
+ ...state,
152
+ streamingContent: "",
153
+ streamingReasoning: "",
154
+ streamingParts: [],
155
+ isThinking: false,
156
+ thinkingStartTime: null
157
+ };
158
+ case "ADD_MESSAGE":
159
+ if (!state.currentConversation || state.currentConversation.id !== action.conversationId) return state;
160
+ return {
161
+ ...state,
162
+ currentConversation: {
163
+ ...state.currentConversation,
164
+ messages: [...state.currentConversation.messages || [], action.message],
165
+ activeBranchId: action.message.id
166
+ }
167
+ };
168
+ case "UPDATE_MESSAGE":
169
+ if (!state.currentConversation || state.currentConversation.id !== action.conversationId) return state;
170
+ return {
171
+ ...state,
172
+ currentConversation: {
173
+ ...state.currentConversation,
174
+ messages: (state.currentConversation.messages || []).map((msg) => msg.id === action.messageId ? {
175
+ ...msg,
176
+ ...action.updates
177
+ } : msg)
178
+ }
179
+ };
180
+ case "TOGGLE_SIDEBAR": return {
181
+ ...state,
182
+ sidebarCollapsed: !state.sidebarCollapsed
183
+ };
184
+ case "ADD_CONVERSATION":
185
+ if (state.conversations.some((c) => c.id === action.conversation.id)) return state;
186
+ return {
187
+ ...state,
188
+ conversations: [action.conversation, ...state.conversations]
189
+ };
190
+ case "REMOVE_CONVERSATION": return {
191
+ ...state,
192
+ conversations: state.conversations.filter((c) => c.id !== action.conversationId)
193
+ };
194
+ case "SET_LOADING_CONVERSATION": return {
195
+ ...state,
196
+ isLoadingConversation: action.isLoadingConversation
197
+ };
198
+ case "RESTORE_BACKGROUND_STREAM": return {
199
+ ...state,
200
+ streamingContent: action.content,
201
+ streamingReasoning: action.reasoning,
202
+ streamingParts: action.parts ?? [],
203
+ isStreaming: true
204
+ };
205
+ case "ADD_QUEUED_MESSAGE":
206
+ if (action.conversationId && state.currentConversation?.id !== action.conversationId) return state;
207
+ return {
208
+ ...state,
209
+ queuedMessages: [...state.queuedMessages, action.message]
210
+ };
211
+ case "REMOVE_QUEUED_MESSAGE": return {
212
+ ...state,
213
+ queuedMessages: state.queuedMessages.filter((m) => m.id !== action.id)
214
+ };
215
+ case "CLEAR_QUEUED_MESSAGES": return {
216
+ ...state,
217
+ queuedMessages: []
218
+ };
219
+ default: return state;
220
+ }
221
+ }
222
+ //#endregion
223
+ export { chatReducer, initialState };
@@ -0,0 +1,47 @@
1
+ import { type ComponentType, type MouseEventHandler, type ReactNode } from 'react';
2
+ import type { Components } from 'streamdown';
3
+ import { type ChatStrings } from '../strings.js';
4
+ import type { ApprovalAnswerValue, ChatLinkTarget, ChatMessage, CspKind, MessagePart, MessagePartKind } from '../types.js';
5
+ export interface PartRendererProps {
6
+ part: MessagePart;
7
+ message: ChatMessage;
8
+ isStreaming?: boolean;
9
+ onApprovalAnswer?: (id: string, answer: ApprovalAnswerValue) => void;
10
+ }
11
+ export interface ChatLinkProps {
12
+ target: ChatLinkTarget;
13
+ className?: string;
14
+ title?: string;
15
+ onClick?: MouseEventHandler;
16
+ children: ReactNode;
17
+ }
18
+ export interface ChatUIConfig {
19
+ LinkComponent?: ComponentType<ChatLinkProps>;
20
+ extraLinks?: {
21
+ connectTools?: string;
22
+ manageProviders?: string;
23
+ addProvider?: string;
24
+ providerSettings?: (owner: string, name: string) => string;
25
+ };
26
+ slots?: {
27
+ composerUsage?: ReactNode;
28
+ providerIcon?: (cspKind: CspKind, className?: string) => ReactNode;
29
+ partRenderers?: Partial<Record<MessagePartKind, ComponentType<PartRendererProps>>>;
30
+ };
31
+ strings?: {
32
+ [S in keyof ChatStrings]?: Partial<ChatStrings[S]>;
33
+ };
34
+ markdownComponents?: Components;
35
+ suggestedPrompts?: string[];
36
+ }
37
+ export interface ResolvedChatConfig {
38
+ LinkComponent: ComponentType<ChatLinkProps>;
39
+ extraLinks: NonNullable<ChatUIConfig['extraLinks']>;
40
+ slots: NonNullable<ChatUIConfig['slots']>;
41
+ strings: ChatStrings;
42
+ markdownComponents?: Components;
43
+ suggestedPrompts?: string[];
44
+ }
45
+ export declare function resolveChatConfig(config?: ChatUIConfig): ResolvedChatConfig;
46
+ export declare const ChatConfigProvider: import("react").Provider<ResolvedChatConfig>;
47
+ export declare function useChatConfig(): ResolvedChatConfig;
@@ -0,0 +1,45 @@
1
+ import { defaultChatStrings } from "../strings.js";
2
+ import { createContext, useContext } from "react";
3
+ import { jsx } from "react/jsx-runtime";
4
+ //#region src/ai/core/config.tsx
5
+ function hrefFor(target) {
6
+ switch (target.kind) {
7
+ case "conversation": return `/chat/${target.id}`;
8
+ case "attachments": return "/chat/attachments";
9
+ case "external": return target.href;
10
+ }
11
+ }
12
+ function DefaultLink({ target, className, title, onClick, children }) {
13
+ return /* @__PURE__ */ jsx("a", {
14
+ href: hrefFor(target),
15
+ className,
16
+ title,
17
+ onClick,
18
+ children
19
+ });
20
+ }
21
+ function resolveStrings(overrides) {
22
+ const merged = {};
23
+ for (const key of Object.keys(defaultChatStrings)) merged[key] = {
24
+ ...defaultChatStrings[key],
25
+ ...overrides?.[key]
26
+ };
27
+ return merged;
28
+ }
29
+ function resolveChatConfig(config) {
30
+ return {
31
+ LinkComponent: config?.LinkComponent ?? DefaultLink,
32
+ extraLinks: config?.extraLinks ?? {},
33
+ slots: config?.slots ?? {},
34
+ strings: resolveStrings(config?.strings),
35
+ ...config?.markdownComponents ? { markdownComponents: config.markdownComponents } : {},
36
+ ...config?.suggestedPrompts ? { suggestedPrompts: config.suggestedPrompts } : {}
37
+ };
38
+ }
39
+ var ChatConfigContext = createContext(resolveChatConfig());
40
+ var ChatConfigProvider = ChatConfigContext.Provider;
41
+ function useChatConfig() {
42
+ return useContext(ChatConfigContext);
43
+ }
44
+ //#endregion
45
+ export { ChatConfigProvider, resolveChatConfig, useChatConfig };
@@ -0,0 +1 @@
1
+ export declare const FOCUS_SIDEBAR_SEARCH_EVENT = "aichat:focus-sidebar-search";
@@ -0,0 +1,4 @@
1
+ //#region src/ai/core/events.ts
2
+ var FOCUS_SIDEBAR_SEARCH_EVENT = "aichat:focus-sidebar-search";
3
+ //#endregion
4
+ export { FOCUS_SIDEBAR_SEARCH_EVENT };
@@ -0,0 +1,4 @@
1
+ import type { Conversation } from '../types.js';
2
+ export declare function conversationToMarkdown(conversation: Conversation): string;
3
+ export declare function exportFilename(title?: string | null): string;
4
+ export declare function downloadText(filename: string, text: string): void;
@@ -0,0 +1,42 @@
1
+ import { DateTime } from "luxon";
2
+ //#region src/ai/core/exportConversation.ts
3
+ function conversationToMarkdown(conversation) {
4
+ const lines = [];
5
+ lines.push(`# ${conversation.title?.trim() || "Conversation"}`);
6
+ if (conversation.createdAt) {
7
+ const dt = DateTime.fromISO(conversation.createdAt);
8
+ if (dt.isValid) {
9
+ lines.push("");
10
+ lines.push(`> Started ${dt.toLocaleString(DateTime.DATETIME_MED)}`);
11
+ }
12
+ }
13
+ for (const message of conversation.messages) {
14
+ if (message.role !== "user" && message.role !== "assistant") continue;
15
+ const hasAttachments = (message.attachments?.length ?? 0) > 0;
16
+ if (!message.content?.trim() && !hasAttachments && !message.error) continue;
17
+ lines.push("");
18
+ lines.push(message.role === "user" ? "## User" : "## Assistant");
19
+ lines.push("");
20
+ if (message.content?.trim()) lines.push(message.content.trim());
21
+ for (const attachment of message.attachments ?? []) lines.push(`> Attached: ${attachment.filename}`);
22
+ if (message.error) lines.push(`> Error: ${message.error}`);
23
+ }
24
+ lines.push("");
25
+ return lines.join("\n");
26
+ }
27
+ function exportFilename(title) {
28
+ return `${(title ?? "").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 64) || "conversation"}.md`;
29
+ }
30
+ function downloadText(filename, text) {
31
+ const blob = new Blob([text], { type: "text/markdown;charset=utf-8" });
32
+ const url = URL.createObjectURL(blob);
33
+ const anchor = document.createElement("a");
34
+ anchor.href = url;
35
+ anchor.download = filename;
36
+ document.body.appendChild(anchor);
37
+ anchor.click();
38
+ anchor.remove();
39
+ URL.revokeObjectURL(url);
40
+ }
41
+ //#endregion
42
+ export { conversationToMarkdown, downloadText, exportFilename };
@@ -0,0 +1,3 @@
1
+ export declare function getGreeting(user: {
2
+ name?: string | null;
3
+ } | null): string;
@@ -0,0 +1,38 @@
1
+ //#region src/ai/core/greeting.ts
2
+ function getGreeting(user) {
3
+ const hour = (/* @__PURE__ */ new Date()).getHours();
4
+ let timeOfDay;
5
+ if (hour >= 5 && hour < 12) timeOfDay = "morning";
6
+ else if (hour >= 12 && hour < 18) timeOfDay = "afternoon";
7
+ else timeOfDay = "evening";
8
+ const greetings = {
9
+ morning: [
10
+ `Good morning[name]! How can I help you today?`,
11
+ `Morning[name]! What can I assist you with?`,
12
+ `Rise and shine[name]! What's on your mind this morning?`,
13
+ `Good morning[name]! How can I make your day easier?`
14
+ ],
15
+ afternoon: [
16
+ `Good afternoon[name]! What can I help you with today?`,
17
+ `Hello[name]! How can I assist you this afternoon?`,
18
+ `What can I help you accomplish today[name]?`,
19
+ `Afternoon[name]! What questions do you have?`
20
+ ],
21
+ evening: [
22
+ `Good evening[name]! How can I assist you?`,
23
+ `Evening[name]! What's on your mind?`,
24
+ `How can I help you tonight[name]?`,
25
+ `What can I do for you this evening[name]?`
26
+ ]
27
+ };
28
+ const randomIndex = Math.floor(Math.random() * greetings[timeOfDay].length);
29
+ let greeting = greetings[timeOfDay][randomIndex] ?? "";
30
+ if (user?.name) {
31
+ const firstName = user.name.split(" ")[0];
32
+ if (Math.random() > .5) greeting = greeting.replace("[name]", `, ${firstName}`);
33
+ }
34
+ greeting = greeting.replace("[name]", "");
35
+ return greeting;
36
+ }
37
+ //#endregion
38
+ export { getGreeting };
@@ -0,0 +1,11 @@
1
+ import type { PartDelta } from '../adapter/types.js';
2
+ import type { MessagePart } from '../types.js';
3
+ /** Fold one streamed PartDelta into a parts timeline. Pure: returns a new
4
+ * array, leaving the input untouched, so it works for both reducer state
5
+ * and the provider's local accumulation. Unknown target ids are dropped
6
+ * rather than invented — an end without a start has nothing to render. */
7
+ export declare function applyPartDelta(parts: MessagePart[], delta: PartDelta): MessagePart[];
8
+ /** A turn can end (completed or stopped) with tool calls still marked
9
+ * running — the transport died before their tool_end arrived. A stored
10
+ * message must not spin forever, so close them out as interrupted. */
11
+ export declare function finalizeParts(parts: MessagePart[]): MessagePart[];
@@ -0,0 +1,84 @@
1
+ //#region src/ai/core/parts.ts
2
+ /** Fold one streamed PartDelta into a parts timeline. Pure: returns a new
3
+ * array, leaving the input untouched, so it works for both reducer state
4
+ * and the provider's local accumulation. Unknown target ids are dropped
5
+ * rather than invented — an end without a start has nothing to render. */
6
+ function applyPartDelta(parts, delta) {
7
+ switch (delta.type) {
8
+ case "tool_start": return [...parts, {
9
+ kind: "tool_call",
10
+ id: delta.id,
11
+ name: delta.name,
12
+ args: delta.args,
13
+ status: "running",
14
+ ...delta.startLine !== void 0 ? { startLine: delta.startLine } : {}
15
+ }];
16
+ case "tool_update": return parts.map((p) => p.kind === "tool_call" && p.id === delta.id ? {
17
+ ...p,
18
+ args: p.args + delta.args
19
+ } : p);
20
+ case "tool_end": return parts.map((p) => p.kind === "tool_call" && p.id === delta.id ? {
21
+ ...p,
22
+ status: delta.isError ? "error" : "ok",
23
+ result: delta.result
24
+ } : p);
25
+ case "subagent_start": {
26
+ const part = {
27
+ kind: "subagent",
28
+ id: delta.id,
29
+ status: "running",
30
+ actions: [],
31
+ ...delta.agentType !== void 0 ? { agentType: delta.agentType } : {},
32
+ ...delta.color !== void 0 ? { color: delta.color } : {},
33
+ ...delta.background !== void 0 ? { background: delta.background } : {},
34
+ ...delta.description !== void 0 ? { description: delta.description } : {}
35
+ };
36
+ return [...parts, part];
37
+ }
38
+ case "subagent_action": return parts.map((p) => p.kind === "subagent" && p.id === delta.id ? {
39
+ ...p,
40
+ actions: [...p.actions ?? [], delta.action]
41
+ } : p);
42
+ case "subagent_end": return parts.map((p) => p.kind === "subagent" && p.id === delta.id ? {
43
+ ...p,
44
+ status: delta.ok ? "done" : "failed",
45
+ ...delta.summary !== void 0 ? { summary: delta.summary } : {},
46
+ ...delta.report !== void 0 ? { report: delta.report } : {}
47
+ } : p);
48
+ case "approval_request": return [...parts, delta.approval];
49
+ case "approval_resolved": return parts.map((p) => p.kind === "approval" && p.id === delta.id ? {
50
+ ...p,
51
+ resolved: true,
52
+ ...delta.answer !== void 0 ? { answer: delta.answer } : {}
53
+ } : p);
54
+ case "notice":
55
+ case "warning": return [...parts, {
56
+ kind: delta.type,
57
+ text: delta.text
58
+ }];
59
+ case "todo_snapshot": {
60
+ const idx = parts.findLastIndex((p) => p.kind === "todo_snapshot");
61
+ if (idx === -1) return [...parts, {
62
+ kind: "todo_snapshot",
63
+ todos: delta.todos
64
+ }];
65
+ return parts.map((p, i) => i === idx ? {
66
+ kind: "todo_snapshot",
67
+ todos: delta.todos
68
+ } : p);
69
+ }
70
+ default: return parts;
71
+ }
72
+ }
73
+ /** A turn can end (completed or stopped) with tool calls still marked
74
+ * running — the transport died before their tool_end arrived. A stored
75
+ * message must not spin forever, so close them out as interrupted. */
76
+ function finalizeParts(parts) {
77
+ return parts.map((p) => p.kind === "tool_call" && p.status === "running" ? {
78
+ ...p,
79
+ status: "error",
80
+ result: p.result ?? "interrupted"
81
+ } : p);
82
+ }
83
+ //#endregion
84
+ export { applyPartDelta, finalizeParts };
@@ -0,0 +1,14 @@
1
+ import { type DragEvent } from 'react';
2
+ interface UseDragDropOptions {
3
+ onFilesDropped: (files: FileList) => void;
4
+ }
5
+ export default function useDragDrop({ onFilesDropped }: UseDragDropOptions): {
6
+ isDragging: boolean;
7
+ dragHandlers: {
8
+ onDragEnter: (e: DragEvent) => void;
9
+ onDragLeave: (e: DragEvent) => void;
10
+ onDragOver: (e: DragEvent) => void;
11
+ onDrop: (e: DragEvent) => void;
12
+ };
13
+ };
14
+ export {};