@larkup/workspace-app 0.0.0-stage → 0.2.0

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 (440) hide show
  1. package/LICENSE +176 -0
  2. package/README.md +4 -2
  3. package/assets/github.svg +3 -0
  4. package/assets/icons/Confluence.png +0 -0
  5. package/assets/icons/Instagram.png +0 -0
  6. package/assets/icons/Northflank.png +0 -0
  7. package/assets/icons/Salesforce.png +0 -0
  8. package/assets/icons/agentskills.png +0 -0
  9. package/assets/icons/airtable.png +0 -0
  10. package/assets/icons/asana.png +0 -0
  11. package/assets/icons/ashby.png +0 -0
  12. package/assets/icons/audio.png +0 -0
  13. package/assets/icons/aws-kendra.png +0 -0
  14. package/assets/icons/aws.svg +38 -0
  15. package/assets/icons/azure-ai-search.png +0 -0
  16. package/assets/icons/azure.svg +1 -0
  17. package/assets/icons/bigquery.png +0 -0
  18. package/assets/icons/bing.png +0 -0
  19. package/assets/icons/bitbucket.png +0 -0
  20. package/assets/icons/brave.png +0 -0
  21. package/assets/icons/browserbase.png +0 -0
  22. package/assets/icons/calendly.png +0 -0
  23. package/assets/icons/chroma.png +0 -0
  24. package/assets/icons/cloudflare.png +0 -0
  25. package/assets/icons/cohere.svg +30 -0
  26. package/assets/icons/databricks.png +0 -0
  27. package/assets/icons/daytonaio.png +0 -0
  28. package/assets/icons/daytonaio2.png +0 -0
  29. package/assets/icons/deepgram.png +0 -0
  30. package/assets/icons/deepl.png +0 -0
  31. package/assets/icons/digital-ocean.webp +0 -0
  32. package/assets/icons/discord.png +0 -0
  33. package/assets/icons/e2b-2.png +0 -0
  34. package/assets/icons/e2b.png +0 -0
  35. package/assets/icons/elevenlabs.png +0 -0
  36. package/assets/icons/email.png +0 -0
  37. package/assets/icons/exa.png +0 -0
  38. package/assets/icons/excel.png +0 -0
  39. package/assets/icons/fal.png +0 -0
  40. package/assets/icons/firecrawl.png +0 -0
  41. package/assets/icons/firecrawl2.png +0 -0
  42. package/assets/icons/flyio.jpeg +0 -0
  43. package/assets/icons/gcp.svg +1 -0
  44. package/assets/icons/gemini.svg +1 -0
  45. package/assets/icons/gmail.png +0 -0
  46. package/assets/icons/google-analytics.png +0 -0
  47. package/assets/icons/google-calender.png +0 -0
  48. package/assets/icons/google-docs.png +0 -0
  49. package/assets/icons/google-drive.png +0 -0
  50. package/assets/icons/google-maps.png +0 -0
  51. package/assets/icons/google-meet.png +0 -0
  52. package/assets/icons/google-sheets.png +0 -0
  53. package/assets/icons/google-slides.png +0 -0
  54. package/assets/icons/google-tasks.png +0 -0
  55. package/assets/icons/google.png +0 -0
  56. package/assets/icons/grok.png +0 -0
  57. package/assets/icons/hubspot.png +0 -0
  58. package/assets/icons/image.png +0 -0
  59. package/assets/icons/jina.svg +1 -0
  60. package/assets/icons/jira.png +0 -0
  61. package/assets/icons/lancedb2.png +0 -0
  62. package/assets/icons/linear.png +0 -0
  63. package/assets/icons/linux.png +0 -0
  64. package/assets/icons/looker.png +0 -0
  65. package/assets/icons/luma.png +0 -0
  66. package/assets/icons/mac.png +0 -0
  67. package/assets/icons/markdown.png +0 -0
  68. package/assets/icons/mcp.png +0 -0
  69. package/assets/icons/mcp.svg +1 -0
  70. package/assets/icons/messenger.svg +1 -0
  71. package/assets/icons/microsoft-intra.png +0 -0
  72. package/assets/icons/microsoft-onenote.png +0 -0
  73. package/assets/icons/microsoft-planner.png +0 -0
  74. package/assets/icons/microsoft-teams.png +0 -0
  75. package/assets/icons/miro.png +0 -0
  76. package/assets/icons/mistral.svg +469 -0
  77. package/assets/icons/modal.png +0 -0
  78. package/assets/icons/ngrok.png +0 -0
  79. package/assets/icons/nomic.png +0 -0
  80. package/assets/icons/onedrive.png +0 -0
  81. package/assets/icons/openai.svg +1 -0
  82. package/assets/icons/outlook-calendar.png +0 -0
  83. package/assets/icons/outlook-email.png +0 -0
  84. package/assets/icons/outlook.png +0 -0
  85. package/assets/icons/pdf.png +0 -0
  86. package/assets/icons/personio.png +0 -0
  87. package/assets/icons/pgvector2.png +0 -0
  88. package/assets/icons/phone.png +0 -0
  89. package/assets/icons/pinecone.png +0 -0
  90. package/assets/icons/pipedrive.png +0 -0
  91. package/assets/icons/power-pi.png +0 -0
  92. package/assets/icons/pylon.png +0 -0
  93. package/assets/icons/python.png +0 -0
  94. package/assets/icons/qdrant.svg +35 -0
  95. package/assets/icons/revai.png +0 -0
  96. package/assets/icons/revai.svg +1 -0
  97. package/assets/icons/sap.png +0 -0
  98. package/assets/icons/serpapi.svg +34 -0
  99. package/assets/icons/serper.png +0 -0
  100. package/assets/icons/servicenow.png +0 -0
  101. package/assets/icons/sharepoint.png +0 -0
  102. package/assets/icons/slack.png +0 -0
  103. package/assets/icons/snowflake.png +0 -0
  104. package/assets/icons/statistia.png +0 -0
  105. package/assets/icons/stripe.png +0 -0
  106. package/assets/icons/supabase.png +0 -0
  107. package/assets/icons/tableau.png +0 -0
  108. package/assets/icons/tavily.png +0 -0
  109. package/assets/icons/telegram.png +0 -0
  110. package/assets/icons/typescript.png +0 -0
  111. package/assets/icons/vercel copy.svg +1 -0
  112. package/assets/icons/vercel.svg +1 -0
  113. package/assets/icons/vertex-ai.png +0 -0
  114. package/assets/icons/video.png +0 -0
  115. package/assets/icons/voyage-light.png +0 -0
  116. package/assets/icons/weaviate.webp +0 -0
  117. package/assets/icons/webcontainers.svg +11 -0
  118. package/assets/icons/webhook.png +0 -0
  119. package/assets/icons/whatsapp copy.png +0 -0
  120. package/assets/icons/whatsapp.png +0 -0
  121. package/assets/icons/windows.png +0 -0
  122. package/assets/icons/word.png +0 -0
  123. package/assets/icons/zendesk.png +0 -0
  124. package/assets/icons/zoom.png +0 -0
  125. package/assets/notion-white.png +0 -0
  126. package/assets/notion.png +0 -0
  127. package/dist-types/asset-server.d.ts +3 -0
  128. package/dist-types/asset-server.d.ts.map +1 -0
  129. package/dist-types/components/alerts/generic-alert.d.ts +15 -0
  130. package/dist-types/components/alerts/generic-alert.d.ts.map +1 -0
  131. package/dist-types/components/chat/canvas/doc-editor-provider.d.ts +62 -0
  132. package/dist-types/components/chat/canvas/doc-editor-provider.d.ts.map +1 -0
  133. package/dist-types/components/chat/canvas/document-canvas.d.ts +7 -0
  134. package/dist-types/components/chat/canvas/document-canvas.d.ts.map +1 -0
  135. package/dist-types/components/chat/canvas/document-field.d.ts +13 -0
  136. package/dist-types/components/chat/canvas/document-field.d.ts.map +1 -0
  137. package/dist-types/components/chat/canvas/document-viewer.d.ts +2 -0
  138. package/dist-types/components/chat/canvas/document-viewer.d.ts.map +1 -0
  139. package/dist-types/components/chat/canvas/file-attachment-button.d.ts +9 -0
  140. package/dist-types/components/chat/canvas/file-attachment-button.d.ts.map +1 -0
  141. package/dist-types/components/chat/chat-workspace.d.ts +4 -0
  142. package/dist-types/components/chat/chat-workspace.d.ts.map +1 -0
  143. package/dist-types/components/chat/message-actions.d.ts +11 -0
  144. package/dist-types/components/chat/message-actions.d.ts.map +1 -0
  145. package/dist-types/components/chat/message-item.d.ts +20 -0
  146. package/dist-types/components/chat/message-item.d.ts.map +1 -0
  147. package/dist-types/components/chat/message-queue.d.ts +15 -0
  148. package/dist-types/components/chat/message-queue.d.ts.map +1 -0
  149. package/dist-types/components/chat/tools/chat-chart.d.ts +6 -0
  150. package/dist-types/components/chat/tools/chat-chart.d.ts.map +1 -0
  151. package/dist-types/components/chat/tools/chat-citations.d.ts +32 -0
  152. package/dist-types/components/chat/tools/chat-citations.d.ts.map +1 -0
  153. package/dist-types/components/chat/tools/chat-data-table.d.ts +14 -0
  154. package/dist-types/components/chat/tools/chat-data-table.d.ts.map +1 -0
  155. package/dist-types/components/chat/tools/chat-file-export.d.ts +5 -0
  156. package/dist-types/components/chat/tools/chat-file-export.d.ts.map +1 -0
  157. package/dist-types/components/chat/tools/chat-media-preview.d.ts +35 -0
  158. package/dist-types/components/chat/tools/chat-media-preview.d.ts.map +1 -0
  159. package/dist-types/components/chat/tools/chat-sandbox-result.d.ts +17 -0
  160. package/dist-types/components/chat/tools/chat-sandbox-result.d.ts.map +1 -0
  161. package/dist-types/components/chat/tools/chat-signature-request.d.ts +13 -0
  162. package/dist-types/components/chat/tools/chat-signature-request.d.ts.map +1 -0
  163. package/dist-types/components/chat/tools/chat-tabs.d.ts +17 -0
  164. package/dist-types/components/chat/tools/chat-tabs.d.ts.map +1 -0
  165. package/dist-types/components/chat/tools/corpus-data-result.d.ts +36 -0
  166. package/dist-types/components/chat/tools/corpus-data-result.d.ts.map +1 -0
  167. package/dist-types/components/chat/tools/knowledge-base-result.d.ts +14 -0
  168. package/dist-types/components/chat/tools/knowledge-base-result.d.ts.map +1 -0
  169. package/dist-types/components/chat/tools/visual-placement-modal.d.ts +23 -0
  170. package/dist-types/components/chat/tools/visual-placement-modal.d.ts.map +1 -0
  171. package/dist-types/components/configure/custom-model-modal.d.ts +13 -0
  172. package/dist-types/components/configure/custom-model-modal.d.ts.map +1 -0
  173. package/dist-types/components/configure/store-fields.d.ts +11 -0
  174. package/dist-types/components/configure/store-fields.d.ts.map +1 -0
  175. package/dist-types/components/data/corpus-panel.d.ts +12 -0
  176. package/dist-types/components/data/corpus-panel.d.ts.map +1 -0
  177. package/dist-types/components/data/data-entry-mode-switch.d.ts +13 -0
  178. package/dist-types/components/data/data-entry-mode-switch.d.ts.map +1 -0
  179. package/dist-types/components/data/data-primary-action.d.ts +7 -0
  180. package/dist-types/components/data/data-primary-action.d.ts.map +1 -0
  181. package/dist-types/components/data/data-workspace.d.ts +6 -0
  182. package/dist-types/components/data/data-workspace.d.ts.map +1 -0
  183. package/dist-types/components/data/groups-panel.d.ts +5 -0
  184. package/dist-types/components/data/groups-panel.d.ts.map +1 -0
  185. package/dist-types/components/data/integration-resources-panel.d.ts +9 -0
  186. package/dist-types/components/data/integration-resources-panel.d.ts.map +1 -0
  187. package/dist-types/components/data/integrations-panel.d.ts +5 -0
  188. package/dist-types/components/data/integrations-panel.d.ts.map +1 -0
  189. package/dist-types/components/data/jobs-panel.d.ts +6 -0
  190. package/dist-types/components/data/jobs-panel.d.ts.map +1 -0
  191. package/dist-types/components/data/jobs-tracking-button.d.ts +2 -0
  192. package/dist-types/components/data/jobs-tracking-button.d.ts.map +1 -0
  193. package/dist-types/components/data/live-media-progress.d.ts +9 -0
  194. package/dist-types/components/data/live-media-progress.d.ts.map +1 -0
  195. package/dist-types/components/data/media-indexing-jobs-panel.d.ts +34 -0
  196. package/dist-types/components/data/media-indexing-jobs-panel.d.ts.map +1 -0
  197. package/dist-types/components/data/media-panel.d.ts +58 -0
  198. package/dist-types/components/data/media-panel.d.ts.map +1 -0
  199. package/dist-types/components/data/notion-panel.d.ts +6 -0
  200. package/dist-types/components/data/notion-panel.d.ts.map +1 -0
  201. package/dist-types/components/data/paste-panel.d.ts +7 -0
  202. package/dist-types/components/data/paste-panel.d.ts.map +1 -0
  203. package/dist-types/components/data/project-data-page.d.ts +3 -0
  204. package/dist-types/components/data/project-data-page.d.ts.map +1 -0
  205. package/dist-types/components/data/scrape-panel.d.ts +9 -0
  206. package/dist-types/components/data/scrape-panel.d.ts.map +1 -0
  207. package/dist-types/components/data/tabular-preview.d.ts +10 -0
  208. package/dist-types/components/data/tabular-preview.d.ts.map +1 -0
  209. package/dist-types/components/data/tool-indexing-dialog.d.ts +54 -0
  210. package/dist-types/components/data/tool-indexing-dialog.d.ts.map +1 -0
  211. package/dist-types/components/data/upload-panel.d.ts +7 -0
  212. package/dist-types/components/data/upload-panel.d.ts.map +1 -0
  213. package/dist-types/components/data/web-crawler-status.d.ts +3 -0
  214. package/dist-types/components/data/web-crawler-status.d.ts.map +1 -0
  215. package/dist-types/components/projects/project-form-dialog.d.ts +10 -0
  216. package/dist-types/components/projects/project-form-dialog.d.ts.map +1 -0
  217. package/dist-types/components/projects/project-provider.d.ts +34 -0
  218. package/dist-types/components/projects/project-provider.d.ts.map +1 -0
  219. package/dist-types/components/settings/general/agent-customization-section.d.ts +2 -0
  220. package/dist-types/components/settings/general/agent-customization-section.d.ts.map +1 -0
  221. package/dist-types/components/settings/general/mcp-connections-section.d.ts +2 -0
  222. package/dist-types/components/settings/general/mcp-connections-section.d.ts.map +1 -0
  223. package/dist-types/components/settings/general/model-combobox.d.ts +24 -0
  224. package/dist-types/components/settings/general/model-combobox.d.ts.map +1 -0
  225. package/dist-types/components/settings/general/models-section.d.ts +2 -0
  226. package/dist-types/components/settings/general/models-section.d.ts.map +1 -0
  227. package/dist-types/components/settings/general/sandbox-section.d.ts +7 -0
  228. package/dist-types/components/settings/general/sandbox-section.d.ts.map +1 -0
  229. package/dist-types/components/settings/general/search-scraping-section.d.ts +2 -0
  230. package/dist-types/components/settings/general/search-scraping-section.d.ts.map +1 -0
  231. package/dist-types/components/settings/general/storage-indexing-section.d.ts +2 -0
  232. package/dist-types/components/settings/general/storage-indexing-section.d.ts.map +1 -0
  233. package/dist-types/components/ui/alert-dialog.d.ts +19 -0
  234. package/dist-types/components/ui/alert-dialog.d.ts.map +1 -0
  235. package/dist-types/components/ui/alert.d.ts +11 -0
  236. package/dist-types/components/ui/alert.d.ts.map +1 -0
  237. package/dist-types/components/ui/badge.d.ts +8 -0
  238. package/dist-types/components/ui/badge.d.ts.map +1 -0
  239. package/dist-types/components/ui/card.d.ts +2 -0
  240. package/dist-types/components/ui/card.d.ts.map +1 -0
  241. package/dist-types/components/ui/checkbox.d.ts +4 -0
  242. package/dist-types/components/ui/checkbox.d.ts.map +1 -0
  243. package/dist-types/components/ui/collapsible.d.ts +6 -0
  244. package/dist-types/components/ui/collapsible.d.ts.map +1 -0
  245. package/dist-types/components/ui/command.d.ts +20 -0
  246. package/dist-types/components/ui/command.d.ts.map +1 -0
  247. package/dist-types/components/ui/dialog.d.ts +18 -0
  248. package/dist-types/components/ui/dialog.d.ts.map +1 -0
  249. package/dist-types/components/ui/dropdown-menu.d.ts +30 -0
  250. package/dist-types/components/ui/dropdown-menu.d.ts.map +1 -0
  251. package/dist-types/components/ui/input-group.d.ts +19 -0
  252. package/dist-types/components/ui/input-group.d.ts.map +1 -0
  253. package/dist-types/components/ui/input.d.ts +4 -0
  254. package/dist-types/components/ui/input.d.ts.map +1 -0
  255. package/dist-types/components/ui/line-tabs.d.ts +15 -0
  256. package/dist-types/components/ui/line-tabs.d.ts.map +1 -0
  257. package/dist-types/components/ui/popover.d.ts +10 -0
  258. package/dist-types/components/ui/popover.d.ts.map +1 -0
  259. package/dist-types/components/ui/progress.d.ts +8 -0
  260. package/dist-types/components/ui/progress.d.ts.map +1 -0
  261. package/dist-types/components/ui/scroll-area.d.ts +6 -0
  262. package/dist-types/components/ui/scroll-area.d.ts.map +1 -0
  263. package/dist-types/components/ui/sheet.d.ts +15 -0
  264. package/dist-types/components/ui/sheet.d.ts.map +1 -0
  265. package/dist-types/components/ui/slider.d.ts +4 -0
  266. package/dist-types/components/ui/slider.d.ts.map +1 -0
  267. package/dist-types/components/ui/switch.d.ts +6 -0
  268. package/dist-types/components/ui/switch.d.ts.map +1 -0
  269. package/dist-types/components/ui/table.d.ts +2 -0
  270. package/dist-types/components/ui/table.d.ts.map +1 -0
  271. package/dist-types/components/ui/tabs.d.ts +11 -0
  272. package/dist-types/components/ui/tabs.d.ts.map +1 -0
  273. package/dist-types/components/ui/textarea.d.ts +2 -0
  274. package/dist-types/components/ui/textarea.d.ts.map +1 -0
  275. package/dist-types/components/ui/tooltip.d.ts +7 -0
  276. package/dist-types/components/ui/tooltip.d.ts.map +1 -0
  277. package/dist-types/hooks/use-copy-to-clipboard.d.ts +5 -0
  278. package/dist-types/hooks/use-copy-to-clipboard.d.ts.map +1 -0
  279. package/dist-types/hooks/use-integration-auth.d.ts +10 -0
  280. package/dist-types/hooks/use-integration-auth.d.ts.map +1 -0
  281. package/dist-types/hooks/use-live-media-progress.d.ts +14 -0
  282. package/dist-types/hooks/use-live-media-progress.d.ts.map +1 -0
  283. package/dist-types/hooks/use-notion-auth.d.ts +9 -0
  284. package/dist-types/hooks/use-notion-auth.d.ts.map +1 -0
  285. package/dist-types/host.d.ts +20 -0
  286. package/dist-types/host.d.ts.map +1 -0
  287. package/dist-types/lib/browser-cache.d.ts +7 -0
  288. package/dist-types/lib/browser-cache.d.ts.map +1 -0
  289. package/dist-types/lib/chat/chart-config.d.ts +2 -0
  290. package/dist-types/lib/chat/chart-config.d.ts.map +1 -0
  291. package/dist-types/lib/chat/data-export.d.ts +2 -0
  292. package/dist-types/lib/chat/data-export.d.ts.map +1 -0
  293. package/dist-types/lib/chat/live-tool-progress.d.ts +44 -0
  294. package/dist-types/lib/chat/live-tool-progress.d.ts.map +1 -0
  295. package/dist-types/lib/chat/message-feedback.d.ts +2 -0
  296. package/dist-types/lib/chat/message-feedback.d.ts.map +1 -0
  297. package/dist-types/lib/chat/table-presentation.d.ts +2 -0
  298. package/dist-types/lib/chat/table-presentation.d.ts.map +1 -0
  299. package/dist-types/lib/chat/tool-output.d.ts +3 -0
  300. package/dist-types/lib/chat/tool-output.d.ts.map +1 -0
  301. package/dist-types/lib/chat-supporting-clip.d.ts +11 -0
  302. package/dist-types/lib/chat-supporting-clip.d.ts.map +1 -0
  303. package/dist-types/lib/constants/stores.d.ts +6 -0
  304. package/dist-types/lib/constants/stores.d.ts.map +1 -0
  305. package/dist-types/lib/constants/tools.d.ts +27 -0
  306. package/dist-types/lib/constants/tools.d.ts.map +1 -0
  307. package/dist-types/lib/error-formatter.d.ts +2 -0
  308. package/dist-types/lib/error-formatter.d.ts.map +1 -0
  309. package/dist-types/lib/jobs-client.d.ts +7 -0
  310. package/dist-types/lib/jobs-client.d.ts.map +1 -0
  311. package/dist-types/lib/media/pdf.d.ts +6 -0
  312. package/dist-types/lib/media/pdf.d.ts.map +1 -0
  313. package/dist-types/lib/media/progress.d.ts +61 -0
  314. package/dist-types/lib/media/progress.d.ts.map +1 -0
  315. package/dist-types/lib/media/source-selection.d.ts +10 -0
  316. package/dist-types/lib/media/source-selection.d.ts.map +1 -0
  317. package/dist-types/lib/media/tool-indexing-estimate.d.ts +13 -0
  318. package/dist-types/lib/media/tool-indexing-estimate.d.ts.map +1 -0
  319. package/dist-types/lib/media/video-intelligence-capacity.d.ts +2 -0
  320. package/dist-types/lib/media/video-intelligence-capacity.d.ts.map +1 -0
  321. package/dist-types/lib/media/video-runtime-scope.d.ts +2 -0
  322. package/dist-types/lib/media/video-runtime-scope.d.ts.map +1 -0
  323. package/dist-types/lib/shared/error-formatter.d.ts +2 -0
  324. package/dist-types/lib/shared/error-formatter.d.ts.map +1 -0
  325. package/dist-types/lib/utils.d.ts +3 -0
  326. package/dist-types/lib/utils.d.ts.map +1 -0
  327. package/dist-types/storage.d.ts +5 -0
  328. package/dist-types/storage.d.ts.map +1 -0
  329. package/dist-types/store/chat-store.d.ts +19 -0
  330. package/dist-types/store/chat-store.d.ts.map +1 -0
  331. package/dist-types/store/scrape-store.d.ts +42 -0
  332. package/dist-types/store/scrape-store.d.ts.map +1 -0
  333. package/package.json +579 -3
  334. package/scripts/build-assets.mjs +12 -0
  335. package/src/asset-data.json +1 -0
  336. package/src/asset-server.ts +19 -0
  337. package/src/components/alerts/generic-alert.tsx +76 -0
  338. package/src/components/chat/canvas/doc-editor-provider.tsx +338 -0
  339. package/src/components/chat/canvas/document-canvas.tsx +98 -0
  340. package/src/components/chat/canvas/document-field.tsx +167 -0
  341. package/src/components/chat/canvas/document-viewer.tsx +446 -0
  342. package/src/components/chat/canvas/file-attachment-button.tsx +88 -0
  343. package/src/components/chat/chat-workspace.tsx +1552 -0
  344. package/src/components/chat/message-actions.tsx +96 -0
  345. package/src/components/chat/message-item.tsx +1398 -0
  346. package/src/components/chat/message-queue.tsx +86 -0
  347. package/src/components/chat/tools/chat-chart.tsx +558 -0
  348. package/src/components/chat/tools/chat-citations.tsx +152 -0
  349. package/src/components/chat/tools/chat-data-table.tsx +373 -0
  350. package/src/components/chat/tools/chat-file-export.tsx +49 -0
  351. package/src/components/chat/tools/chat-media-preview.tsx +466 -0
  352. package/src/components/chat/tools/chat-sandbox-result.tsx +130 -0
  353. package/src/components/chat/tools/chat-signature-request.tsx +810 -0
  354. package/src/components/chat/tools/chat-tabs.tsx +59 -0
  355. package/src/components/chat/tools/corpus-data-result.tsx +194 -0
  356. package/src/components/chat/tools/knowledge-base-result.tsx +345 -0
  357. package/src/components/chat/tools/visual-placement-modal.tsx +308 -0
  358. package/src/components/configure/custom-model-modal.tsx +209 -0
  359. package/src/components/configure/store-fields.tsx +129 -0
  360. package/src/components/data/corpus-panel.tsx +1223 -0
  361. package/src/components/data/data-entry-mode-switch.tsx +53 -0
  362. package/src/components/data/data-primary-action.ts +6 -0
  363. package/src/components/data/data-workspace.tsx +623 -0
  364. package/src/components/data/groups-panel.tsx +530 -0
  365. package/src/components/data/integration-resources-panel.tsx +282 -0
  366. package/src/components/data/integrations-panel.tsx +392 -0
  367. package/src/components/data/jobs-panel.tsx +490 -0
  368. package/src/components/data/jobs-tracking-button.tsx +224 -0
  369. package/src/components/data/live-media-progress.tsx +79 -0
  370. package/src/components/data/media-indexing-jobs-panel.tsx +190 -0
  371. package/src/components/data/media-panel.tsx +2905 -0
  372. package/src/components/data/notion-panel.tsx +408 -0
  373. package/src/components/data/paste-panel.tsx +82 -0
  374. package/src/components/data/project-data-page.tsx +55 -0
  375. package/src/components/data/scrape-panel.tsx +1290 -0
  376. package/src/components/data/tabular-preview.tsx +205 -0
  377. package/src/components/data/tool-indexing-dialog.tsx +210 -0
  378. package/src/components/data/upload-panel.tsx +1313 -0
  379. package/src/components/data/web-crawler-status.tsx +132 -0
  380. package/src/components/projects/project-form-dialog.tsx +97 -0
  381. package/src/components/projects/project-provider.tsx +143 -0
  382. package/src/components/settings/general/agent-customization-section.tsx +620 -0
  383. package/src/components/settings/general/mcp-connections-section.tsx +907 -0
  384. package/src/components/settings/general/model-combobox.tsx +235 -0
  385. package/src/components/settings/general/models-section.tsx +909 -0
  386. package/src/components/settings/general/sandbox-section.tsx +394 -0
  387. package/src/components/settings/general/search-scraping-section.tsx +757 -0
  388. package/src/components/settings/general/storage-indexing-section.tsx +394 -0
  389. package/src/components/ui/alert-dialog.tsx +162 -0
  390. package/src/components/ui/alert.tsx +69 -0
  391. package/src/components/ui/badge.tsx +49 -0
  392. package/src/components/ui/card.tsx +9 -0
  393. package/src/components/ui/checkbox.tsx +28 -0
  394. package/src/components/ui/collapsible.tsx +17 -0
  395. package/src/components/ui/command.tsx +175 -0
  396. package/src/components/ui/dialog.tsx +138 -0
  397. package/src/components/ui/dropdown-menu.tsx +267 -0
  398. package/src/components/ui/input-group.tsx +146 -0
  399. package/src/components/ui/input.tsx +19 -0
  400. package/src/components/ui/line-tabs.tsx +49 -0
  401. package/src/components/ui/popover.tsx +77 -0
  402. package/src/components/ui/progress.tsx +66 -0
  403. package/src/components/ui/scroll-area.tsx +51 -0
  404. package/src/components/ui/sheet.tsx +125 -0
  405. package/src/components/ui/slider.tsx +52 -0
  406. package/src/components/ui/switch.tsx +32 -0
  407. package/src/components/ui/table.tsx +10 -0
  408. package/src/components/ui/tabs.tsx +77 -0
  409. package/src/components/ui/textarea.tsx +1 -0
  410. package/src/components/ui/tooltip.tsx +54 -0
  411. package/src/hooks/use-copy-to-clipboard.ts +25 -0
  412. package/src/hooks/use-integration-auth.ts +39 -0
  413. package/src/hooks/use-live-media-progress.ts +71 -0
  414. package/src/hooks/use-notion-auth.ts +66 -0
  415. package/src/host.ts +55 -0
  416. package/src/lib/browser-cache.ts +17 -0
  417. package/src/lib/chat/chart-config.ts +1 -0
  418. package/src/lib/chat/data-export.ts +1 -0
  419. package/src/lib/chat/live-tool-progress.ts +69 -0
  420. package/src/lib/chat/message-feedback.ts +1 -0
  421. package/src/lib/chat/table-presentation.ts +1 -0
  422. package/src/lib/chat/tool-output.ts +14 -0
  423. package/src/lib/chat-supporting-clip.ts +16 -0
  424. package/src/lib/constants/stores.ts +12 -0
  425. package/src/lib/constants/tools.ts +178 -0
  426. package/src/lib/error-formatter.ts +30 -0
  427. package/src/lib/jobs-client.ts +27 -0
  428. package/src/lib/media/pdf.ts +57 -0
  429. package/src/lib/media/progress.ts +209 -0
  430. package/src/lib/media/source-selection.ts +47 -0
  431. package/src/lib/media/tool-indexing-estimate.ts +39 -0
  432. package/src/lib/media/video-intelligence-capacity.ts +1 -0
  433. package/src/lib/media/video-runtime-scope.ts +1 -0
  434. package/src/lib/shared/error-formatter.ts +1 -0
  435. package/src/lib/utils.ts +6 -0
  436. package/src/source.css +1 -0
  437. package/src/storage.ts +16 -0
  438. package/src/store/chat-store.ts +19 -0
  439. package/src/store/scrape-store.ts +76 -0
  440. package/src/styles.d.ts +1 -0
@@ -0,0 +1,408 @@
1
+ 'use client';
2
+
3
+ import { workspaceUrl, workspaceFetch as fetch } from '../../host';
4
+ import { useState } from 'react';
5
+ import useSWR from 'swr';
6
+ import { toast } from 'sonner';
7
+ import { useNotionAuth } from '../../hooks/use-notion-auth';
8
+ import { formatErrorMessage } from '../../lib/shared/error-formatter';
9
+ import {
10
+ ExternalLink,
11
+ Loader2,
12
+ CheckCircle2,
13
+ Database,
14
+ FileText,
15
+ RefreshCw,
16
+ AlertCircle,
17
+ } from 'lucide-react';
18
+ import { Button } from '@larkup/workspace-ui/button';
19
+ import { Input } from '../ui/input';
20
+ import { Checkbox } from '../ui/checkbox';
21
+ import { DialogFooter } from '../ui/dialog';
22
+ import { cn } from '../../lib/utils';
23
+
24
+ interface NotionPage {
25
+ id: string;
26
+ title: string;
27
+ icon: string | null;
28
+ url: string;
29
+ lastEdited: string;
30
+ parentType: string;
31
+ }
32
+
33
+ interface NotionDatabase {
34
+ id: string;
35
+ title: string;
36
+ icon: string | null;
37
+ url: string;
38
+ lastEdited: string;
39
+ type: 'database';
40
+ }
41
+
42
+ interface NotionStatus {
43
+ connected: boolean;
44
+ configured: boolean;
45
+ pages: NotionPage[];
46
+ databases?: NotionDatabase[];
47
+ error?: string;
48
+ }
49
+
50
+ function NotionResourceIcon({ icon, isDatabase }: { icon: string | null; isDatabase: boolean }) {
51
+ if (icon?.startsWith('http')) {
52
+ return <img src={icon} alt="" className="size-5 rounded-sm object-contain" />;
53
+ }
54
+
55
+ return (
56
+ <span aria-hidden="true" className="block max-w-5 truncate text-base leading-none">
57
+ {icon || (isDatabase ? '📊' : '📄')}
58
+ </span>
59
+ );
60
+ }
61
+
62
+ export function NotionPanel({
63
+ onAdded,
64
+ onClose,
65
+ groupId,
66
+ }: {
67
+ onAdded: () => void;
68
+ onClose?: () => void;
69
+ groupId: string;
70
+ }) {
71
+ const {
72
+ data: statusData,
73
+ error: swrError,
74
+ isLoading,
75
+ mutate,
76
+ } = useSWR<NotionStatus>(workspaceUrl('/api/integrations/notion'), (url: string) =>
77
+ fetch(url).then((res) => {
78
+ if (!res.ok) throw new Error('Failed to fetch');
79
+ return res.json();
80
+ }),
81
+ );
82
+
83
+ const status = statusData || {
84
+ connected: false,
85
+ configured: false,
86
+ pages: [],
87
+ error: swrError ? formatErrorMessage(swrError) : undefined,
88
+ };
89
+
90
+ const loading = isLoading && !statusData;
91
+
92
+ const fetchStatus = () => mutate();
93
+
94
+ const [selected, setSelected] = useState<Set<string>>(new Set());
95
+ const [importing, setImporting] = useState(false);
96
+ const [disconnecting, setDisconnecting] = useState(false);
97
+ const [search, setSearch] = useState('');
98
+ const [showType, setShowType] = useState<'all' | 'pages' | 'databases'>('all');
99
+
100
+ const { connectToNotion } = useNotionAuth({
101
+ onSuccess: () => {
102
+ mutate();
103
+ toast.success('Successfully connected to Notion');
104
+ },
105
+ });
106
+
107
+ function togglePage(id: string) {
108
+ setSelected((prev) => {
109
+ const next = new Set(prev);
110
+ if (next.has(id)) next.delete(id);
111
+ else next.add(id);
112
+ return next;
113
+ });
114
+ }
115
+
116
+ function toggleAll(items: { id: string }[]) {
117
+ const allSelected = items.every((p) => selected.has(p.id));
118
+ if (allSelected) {
119
+ setSelected((prev) => {
120
+ const next = new Set(prev);
121
+ items.forEach((p) => next.delete(p.id));
122
+ return next;
123
+ });
124
+ } else {
125
+ setSelected((prev) => {
126
+ const next = new Set(prev);
127
+ items.forEach((p) => next.add(p.id));
128
+ return next;
129
+ });
130
+ }
131
+ }
132
+
133
+ async function importSelected() {
134
+ if (selected.size === 0) {
135
+ toast.error('Select at least one page to import.');
136
+ return;
137
+ }
138
+
139
+ setImporting(true);
140
+ try {
141
+ const res = await fetch(workspaceUrl('/api/integrations/notion'), {
142
+ method: 'POST',
143
+ headers: { 'Content-Type': 'application/json' },
144
+ body: JSON.stringify({ pageIds: Array.from(selected), groupId }),
145
+ });
146
+ const data = await res.json();
147
+
148
+ if (!res.ok) throw new Error(data.error ?? 'Import failed');
149
+
150
+ toast.success(
151
+ `${data.imported} of ${data.total} page${
152
+ data.total !== 1 ? 's' : ''
153
+ } imported successfully`,
154
+ );
155
+ setSelected(new Set());
156
+ onAdded();
157
+ } catch (err) {
158
+ toast.error(formatErrorMessage(err));
159
+ } finally {
160
+ setImporting(false);
161
+ }
162
+ }
163
+
164
+ if (loading) {
165
+ return (
166
+ <div className="flex flex-col items-center justify-center gap-3 p-4 py-16">
167
+ <Loader2 className="size-6 animate-spin text-muted-foreground" />
168
+ <p className="text-sm text-muted-foreground">Checking Notion connection…</p>
169
+ </div>
170
+ );
171
+ }
172
+
173
+ if (!status?.connected) {
174
+ return (
175
+ <div className="flex flex-col items-center justify-center gap-4 p-4 py-12">
176
+ <div className="flex h-14 w-14 items-center justify-center rounded-2xl border bg-background/30">
177
+ <img src="/notion.png" alt="Notion" className="size-6 opacity-100" />
178
+ </div>
179
+ <div className="text-center max-w-md">
180
+ <h3 className="text-lg font-semibold text-foreground">Notion Not Connected</h3>
181
+ <p className="mt-1.5 text-sm text-muted-foreground leading-relaxed">
182
+ Please connect Notion from the integrations panel.
183
+ </p>
184
+
185
+ <div className="mt-4">
186
+ <Button size="sm" onClick={() => connectToNotion()}>
187
+ Connect Notion
188
+ </Button>
189
+ </div>
190
+
191
+ {status?.error && (
192
+ <div className="mt-3 flex items-center gap-2 rounded-lg border border-destructive/20 bg-destructive/5 px-3 py-2 text-xs text-destructive">
193
+ <AlertCircle className="size-3.5 shrink-0" />
194
+ {status.error}
195
+ </div>
196
+ )}
197
+ </div>
198
+ </div>
199
+ );
200
+ }
201
+
202
+ const allPages = status.pages || [];
203
+ const allDatabases = status.databases || [];
204
+ const query = search.toLowerCase().trim();
205
+
206
+ const filteredPages = query
207
+ ? allPages.filter((p) => p.title.toLowerCase().includes(query))
208
+ : allPages;
209
+
210
+ const filteredDatabases = query
211
+ ? allDatabases.filter((d) => d.title.toLowerCase().includes(query))
212
+ : allDatabases;
213
+
214
+ const visibleItems =
215
+ showType === 'pages'
216
+ ? filteredPages
217
+ : showType === 'databases'
218
+ ? filteredDatabases
219
+ : [...filteredPages, ...filteredDatabases];
220
+
221
+ return (
222
+ <div className="flex w-full min-w-0 flex-col">
223
+ <div className="flex flex-col gap-4 p-4">
224
+ {/* Connection status */}
225
+ <div className="flex items-center justify-between gap-3">
226
+ <div className="flex items-center gap-2 text-sm font-medium">
227
+ <CheckCircle2 className="size-4 text-green-600" />
228
+ <span>Notion Connected</span>
229
+ <span className="text-muted-foreground">
230
+ · {allPages.length} pages, {allDatabases.length} databases
231
+ </span>
232
+ </div>
233
+ <Button
234
+ variant="ghost"
235
+ size="sm"
236
+ onClick={fetchStatus}
237
+ className="h-7 shrink-0 gap-1.5 text-xs"
238
+ >
239
+ <RefreshCw className="size-3" />
240
+ Refresh
241
+ </Button>
242
+ </div>
243
+
244
+ {/* Search + filter */}
245
+ <div className="flex flex-col sm:flex-row sm:items-center gap-2 px-0">
246
+ <Input
247
+ placeholder="Search pages…"
248
+ value={search}
249
+ onChange={(e) => setSearch(e.target.value)}
250
+ className="flex-1 w-full"
251
+ />
252
+ <div className="flex h-10 w-full min-w-0 rounded-lg border border-border p-1 sm:w-auto">
253
+ {(['all', 'pages', 'databases'] as const).map((t) => (
254
+ <button
255
+ key={t}
256
+ type="button"
257
+ onClick={() => setShowType(t)}
258
+ className={cn(
259
+ 'h-full flex-1 sm:flex-none rounded-md px-3 text-xs font-medium transition-colors capitalize',
260
+ showType === t
261
+ ? 'bg-background text-foreground '
262
+ : 'text-muted-foreground hover:text-foreground',
263
+ )}
264
+ >
265
+ {t}
266
+ </button>
267
+ ))}
268
+ </div>
269
+ </div>
270
+
271
+ {/* Pages list */}
272
+ {visibleItems.length > 0 ? (
273
+ <div className="w-full min-w-0 overflow-hidden rounded-lg border border-border">
274
+ <div className="flex items-center justify-between border-b border-border px-3 py-2">
275
+ <span className="text-xs font-medium text-muted-foreground">
276
+ {visibleItems.length} item{visibleItems.length !== 1 ? 's' : ''} · {selected.size}{' '}
277
+ selected
278
+ </span>
279
+ <button
280
+ type="button"
281
+ className="text-xs text-primary hover:underline"
282
+ onClick={() => toggleAll(visibleItems)}
283
+ >
284
+ {visibleItems.every((p) => selected.has(p.id)) ? 'Clear all' : 'Select all'}
285
+ </button>
286
+ </div>
287
+ <ul
288
+ data-testid="notion-resource-list"
289
+ className="max-h-80 divide-y divide-border overflow-x-hidden overflow-y-auto"
290
+ >
291
+ {visibleItems.map((item) => {
292
+ const checked = selected.has(item.id);
293
+ const isDb = 'type' in item && item.type === 'database';
294
+ return (
295
+ <li key={item.id} className="min-w-0 max-w-full overflow-hidden">
296
+ <label
297
+ className={cn(
298
+ 'flex w-full min-w-0 max-w-full cursor-pointer items-center gap-3 overflow-hidden px-3 py-2.5 transition-colors hover:bg-muted/50',
299
+ checked && 'bg-accent/50',
300
+ )}
301
+ >
302
+ <Checkbox
303
+ className="shrink-0"
304
+ checked={checked}
305
+ onCheckedChange={() => togglePage(item.id)}
306
+ />
307
+ <span className="flex size-5 shrink-0 items-center justify-center overflow-hidden">
308
+ <NotionResourceIcon icon={item.icon} isDatabase={isDb} />
309
+ </span>
310
+ <div className="min-w-0 flex-1">
311
+ <span
312
+ title={item.title}
313
+ className="block max-w-full truncate text-sm font-medium text-foreground"
314
+ >
315
+ {item.title}
316
+ </span>
317
+ <span className="flex min-w-0 items-center gap-1.5 truncate text-[10px] text-muted-foreground">
318
+ {isDb ? (
319
+ <Database className="size-2.5" />
320
+ ) : (
321
+ <FileText className="size-2.5" />
322
+ )}
323
+ {isDb ? 'Database' : 'Page'}
324
+ {item.lastEdited && (
325
+ <>
326
+ <span>·</span>
327
+ {new Date(item.lastEdited).toLocaleDateString()}
328
+ </>
329
+ )}
330
+ </span>
331
+ </div>
332
+ <a
333
+ href={item.url}
334
+ target="_blank"
335
+ rel="noopener noreferrer"
336
+ onClick={(e) => e.stopPropagation()}
337
+ className="shrink-0 text-muted-foreground transition-colors hover:text-foreground"
338
+ >
339
+ <ExternalLink className="size-3 shrink-0" />
340
+ </a>
341
+ </label>
342
+ </li>
343
+ );
344
+ })}
345
+ </ul>
346
+ </div>
347
+ ) : (
348
+ <div className="flex flex-col items-center justify-center rounded-lg py-12 text-center">
349
+ <FileText className="size-8 text-muted-foreground/30 mb-3" />
350
+ <p className="text-sm font-medium text-foreground">
351
+ {search ? 'No pages match your search.' : 'No pages found.'}
352
+ </p>
353
+ {!search && (
354
+ <p className="text-xs text-muted-foreground mt-1 max-w-87.5">
355
+ Make sure your integration has access to pages in Notion.
356
+ </p>
357
+ )}
358
+ </div>
359
+ )}
360
+ </div>
361
+
362
+ {/* Import actions */}
363
+ <DialogFooter className="m-0! flex flex-row items-center justify-between space-x-0 gap-2 border-t border-border/70 bg-muted/50 p-4 sm:justify-between">
364
+ <Button
365
+ variant="destructive"
366
+ onClick={async () => {
367
+ setDisconnecting(true);
368
+ try {
369
+ const res = await fetch(workspaceUrl('/api/integrations/notion'), {
370
+ method: 'DELETE',
371
+ });
372
+ if (!res.ok) {
373
+ const data = await res.json();
374
+ throw new Error(data.error || 'Failed to disconnect');
375
+ }
376
+ toast.success('Disconnected from Notion');
377
+ fetchStatus();
378
+ } catch (err) {
379
+ toast.error(formatErrorMessage(err));
380
+ } finally {
381
+ setDisconnecting(false);
382
+ }
383
+ }}
384
+ disabled={importing || disconnecting}
385
+ >
386
+ {disconnecting ? <Loader2 className="size-4 mr-2 animate-spin" /> : null}
387
+ Disconnect
388
+ </Button>
389
+ <div className="flex items-center space-x-2">
390
+ <Button variant="outline" onClick={onClose} disabled={importing || disconnecting}>
391
+ Cancel
392
+ </Button>
393
+ <Button
394
+ onClick={importSelected}
395
+ disabled={importing || disconnecting || selected.size === 0}
396
+ >
397
+ {importing ? (
398
+ <Loader2 className="size-4 mr-2 animate-spin" />
399
+ ) : (
400
+ <img src="/notion-white.png" alt="Notion" className="size-4 mr-2" />
401
+ )}
402
+ Import {selected.size} page{selected.size !== 1 ? 's' : ''}
403
+ </Button>
404
+ </div>
405
+ </DialogFooter>
406
+ </div>
407
+ );
408
+ }
@@ -0,0 +1,82 @@
1
+ 'use client';
2
+
3
+ import { workspaceUrl, workspaceFetch as fetch } from '../../host';
4
+ import { useEffect, useRef, useState } from 'react';
5
+ import { toast } from 'sonner';
6
+ import { formatErrorMessage } from '../../lib/shared/error-formatter';
7
+ import { Plus, Loader2 } from 'lucide-react';
8
+ import { Button } from '@larkup/workspace-ui/button';
9
+ import { TextSourceFields } from '@larkup/workspace-ui';
10
+ import type { DataPrimaryAction } from './data-primary-action';
11
+
12
+ export function PastePanel({
13
+ onAdded,
14
+ onActionChange,
15
+ groupId,
16
+ }: {
17
+ onAdded: () => void;
18
+ onActionChange?: (action: DataPrimaryAction | null) => void;
19
+ groupId?: string;
20
+ }) {
21
+ const [title, setTitle] = useState('');
22
+ const [content, setContent] = useState('');
23
+ const [saving, setSaving] = useState(false);
24
+ const groupIdRef = useRef(groupId ?? 'default');
25
+ groupIdRef.current = groupId ?? 'default';
26
+
27
+ async function submit() {
28
+ if (!content.trim()) {
29
+ toast.error('Nothing to add — paste some text first.');
30
+ return;
31
+ }
32
+ setSaving(true);
33
+ try {
34
+ const res = await fetch(workspaceUrl('/api/documents'), {
35
+ method: 'POST',
36
+ headers: { 'Content-Type': 'application/json' },
37
+ body: JSON.stringify({
38
+ title: title.trim() || 'Pasted text',
39
+ content: content,
40
+ source: 'text',
41
+ groupId: groupIdRef.current,
42
+ }),
43
+ });
44
+ if (!res.ok) throw new Error((await res.json()).error ?? 'Failed');
45
+ toast.success('Added to corpus');
46
+ setTitle('');
47
+ setContent('');
48
+ onAdded();
49
+ } catch (err) {
50
+ toast.error(formatErrorMessage(err));
51
+ } finally {
52
+ setSaving(false);
53
+ }
54
+ }
55
+
56
+ useEffect(() => {
57
+ onActionChange?.({
58
+ label: 'Add text',
59
+ onClick: submit,
60
+ disabled: !content.trim(),
61
+ loading: saving,
62
+ });
63
+ return () => onActionChange?.(null);
64
+ }, [title, content, saving, groupId, onActionChange]);
65
+
66
+ return (
67
+ <div className="space-y-4 w-full">
68
+ <TextSourceFields
69
+ title={title}
70
+ content={content}
71
+ onTitleChange={setTitle}
72
+ onContentChange={setContent}
73
+ />
74
+ {!onActionChange && (
75
+ <Button onClick={submit} disabled={saving}>
76
+ {saving ? <Loader2 className="size-4 animate-spin" /> : <Plus className="size-4" />}
77
+ Add text
78
+ </Button>
79
+ )}
80
+ </div>
81
+ );
82
+ }
@@ -0,0 +1,55 @@
1
+ 'use client';
2
+
3
+ import { workspaceUrl, workspaceFetch as fetch } from '../../host';
4
+ import { useState } from 'react';
5
+ import useSWR from 'swr';
6
+ import { useRouter } from 'next/navigation';
7
+ import { Database, FolderOpen } from 'lucide-react';
8
+ import { WorkspaceLineTabs, WorkspacePageHeading } from '@larkup/workspace-ui';
9
+ import type { DataGroup } from '@larkup/core/types';
10
+ import { DataWorkspace } from './data-workspace';
11
+ import { GroupsPanel } from './groups-panel';
12
+
13
+ const fetcher = (url: string) => fetch(url).then((response) => response.json());
14
+
15
+ /** Simple, tab-first source management for the active Project. */
16
+ export function ProjectDataPage() {
17
+ const router = useRouter();
18
+ const [activeView, setActiveView] = useState<'all' | 'groups'>('all');
19
+ const { data } = useSWR<{ groups: DataGroup[] }>(workspaceUrl('/api/groups'), fetcher);
20
+ const groups = data?.groups ?? [];
21
+
22
+ return (
23
+ <div className="flex h-full flex-col">
24
+ <div className="pt-6 px-6 md:px-8">
25
+ <WorkspacePageHeading
26
+ title="Data"
27
+ description="Add sources, organize groups, and manage indexing."
28
+ />
29
+ <WorkspaceLineTabs
30
+ className="mt-6"
31
+ items={[
32
+ { id: 'all', label: 'All Data', icon: Database },
33
+ { id: 'groups', label: 'Groups', icon: FolderOpen },
34
+ ]}
35
+ activeId={activeView}
36
+ onChange={setActiveView}
37
+ />
38
+ </div>
39
+
40
+ <div className="min-h-0 flex-1 mt-4">
41
+ {activeView === 'all' ? (
42
+ <DataWorkspace view="corpus" />
43
+ ) : (
44
+ <GroupsPanel
45
+ onAddToGroup={(groupId) => router.push(`/add?groupId=${encodeURIComponent(groupId)}`)}
46
+ onView={(groupId) => {
47
+ router.replace(`/data?groupId=${groupId}`);
48
+ setActiveView('all');
49
+ }}
50
+ />
51
+ )}
52
+ </div>
53
+ </div>
54
+ );
55
+ }