@larkup/workspace-app 0.0.0-stage → 0.1.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,308 @@
1
+ 'use client';
2
+
3
+ import { useState, useRef, useEffect } from 'react';
4
+ import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from '../../ui/dialog';
5
+ import { Button } from '@larkup/workspace-ui/button';
6
+ import { ChevronLeft, ChevronRight, Loader2, Save } from 'lucide-react';
7
+ import { motion } from 'framer-motion';
8
+ import { toast } from 'sonner';
9
+
10
+ export interface Placement {
11
+ pageIndex: number;
12
+ x: number;
13
+ y: number;
14
+ scale: number;
15
+ }
16
+
17
+ interface VisualPlacementModalProps {
18
+ open: boolean;
19
+ onOpenChange: (open: boolean) => void;
20
+ fileBase64: string;
21
+ totalPages: number;
22
+ placements: Placement[];
23
+ onSave: (placements: Placement[]) => void;
24
+ mode: 'type' | 'draw' | 'upload';
25
+ imagePayload: string | null;
26
+ text: string;
27
+ font: string;
28
+ color: string;
29
+ scale: number;
30
+ }
31
+
32
+ export function VisualPlacementModal({
33
+ open,
34
+ onOpenChange,
35
+ fileBase64,
36
+ totalPages,
37
+ placements,
38
+ onSave,
39
+ mode,
40
+ imagePayload,
41
+ text,
42
+ font,
43
+ color,
44
+ scale,
45
+ }: VisualPlacementModalProps) {
46
+ const [currentPage, setCurrentPage] = useState(0);
47
+ const [isLoading, setIsLoading] = useState(true);
48
+ const [pdfDoc, setPdfDoc] = useState<any>(null);
49
+ const canvasRef = useRef<HTMLCanvasElement>(null);
50
+ const containerRef = useRef<HTMLDivElement>(null);
51
+
52
+ // Keep local track of placements while editing
53
+ const [localPlacements, setLocalPlacements] = useState<Placement[]>([]);
54
+ const [pdfScale, setPdfScale] = useState(1);
55
+
56
+ useEffect(() => {
57
+ if (open) {
58
+ setLocalPlacements([...placements]);
59
+ }
60
+ }, [open, placements]);
61
+
62
+ // Load PDF document
63
+ useEffect(() => {
64
+ if (!open || !fileBase64) return;
65
+
66
+ let isMounted = true;
67
+ const loadPdf = async () => {
68
+ try {
69
+ setIsLoading(true);
70
+ const pdfjsLib = await import('pdfjs-dist');
71
+ pdfjsLib.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjsLib.version}/pdf.worker.mjs`;
72
+
73
+ const pdfData = atob(fileBase64);
74
+ const bytes = new Uint8Array(pdfData.length);
75
+ for (let i = 0; i < pdfData.length; i++) {
76
+ bytes[i] = pdfData.charCodeAt(i);
77
+ }
78
+
79
+ const loadingTask = pdfjsLib.getDocument({ data: bytes });
80
+ const pdf = await loadingTask.promise;
81
+ if (isMounted) {
82
+ setPdfDoc(pdf);
83
+ }
84
+ } catch (err: any) {
85
+ toast.error('Failed to load PDF for visual placement');
86
+ console.error(err);
87
+ }
88
+ };
89
+
90
+ loadPdf();
91
+ return () => {
92
+ isMounted = false;
93
+ };
94
+ }, [open, fileBase64]);
95
+
96
+ // Render current page
97
+ useEffect(() => {
98
+ if (!pdfDoc || !canvasRef.current) return;
99
+
100
+ let isMounted = true;
101
+ const renderPage = async () => {
102
+ try {
103
+ setIsLoading(true);
104
+ const page = await pdfDoc.getPage(currentPage + 1);
105
+
106
+ const viewport = page.getViewport({ scale: 1 });
107
+
108
+ // Let the PDF be as wide as the modal to make it large enough, allow vertical scrolling
109
+ const availableWidth = Math.min(window.innerWidth * 0.95 - 64, 1136); // max-w-1200px minus padding
110
+
111
+ const scaleX = availableWidth / viewport.width;
112
+ const targetScale = Math.min(scaleX, 1.5); // Cap scale at 1.5x so it doesn't get ridiculously large
113
+
114
+ setPdfScale(targetScale);
115
+ const scaledViewport = page.getViewport({ scale: targetScale });
116
+
117
+ const canvas = canvasRef.current;
118
+ if (!canvas) return;
119
+
120
+ const context = canvas.getContext('2d');
121
+ if (!context) return;
122
+
123
+ canvas.height = scaledViewport.height;
124
+ canvas.width = scaledViewport.width;
125
+
126
+ const renderContext = {
127
+ canvasContext: context,
128
+ viewport: scaledViewport,
129
+ };
130
+
131
+ await page.render(renderContext).promise;
132
+ } catch (err) {
133
+ console.error('Error rendering page:', err);
134
+ } finally {
135
+ if (isMounted) setIsLoading(false);
136
+ }
137
+ };
138
+
139
+ renderPage();
140
+ return () => {
141
+ isMounted = false;
142
+ };
143
+ }, [pdfDoc, currentPage]);
144
+
145
+ const currentPlacement = localPlacements.find((p) => p.pageIndex === currentPage);
146
+
147
+ // Default centered position if not set
148
+ const [dragPos, setDragPos] = useState({ x: 150, y: 150 });
149
+
150
+ useEffect(() => {
151
+ if (currentPlacement && containerRef.current) {
152
+ const { width, height } = containerRef.current.getBoundingClientRect();
153
+ setDragPos({
154
+ x: (currentPlacement.x / 100) * width,
155
+ y: (currentPlacement.y / 100) * height,
156
+ });
157
+ } else if (containerRef.current) {
158
+ const { width, height } = containerRef.current.getBoundingClientRect();
159
+ setDragPos({ x: width / 2 - 50, y: height / 2 - 25 });
160
+ }
161
+ }, [currentPlacement, currentPage, isLoading]);
162
+
163
+ const handleDragEnd = (e: any, info: any) => {
164
+ if (!containerRef.current) return;
165
+ const { width, height } = containerRef.current.getBoundingClientRect();
166
+
167
+ // Convert final px position to percentages
168
+ const newX = Math.max(0, Math.min(100, (dragPos.x / width) * 100));
169
+ const newY = Math.max(0, Math.min(100, (dragPos.y / height) * 100));
170
+
171
+ const existingIdx = localPlacements.findIndex((p) => p.pageIndex === currentPage);
172
+ const newPlacement: Placement = {
173
+ pageIndex: currentPage,
174
+ x: newX,
175
+ y: newY,
176
+ scale, // Save the current scale when the user updates placement
177
+ };
178
+
179
+ if (existingIdx >= 0) {
180
+ const copy = [...localPlacements];
181
+ copy[existingIdx] = newPlacement;
182
+ setLocalPlacements(copy);
183
+ } else {
184
+ setLocalPlacements([...localPlacements, newPlacement]);
185
+ }
186
+ };
187
+
188
+ const handleRemoveCurrent = () => {
189
+ setLocalPlacements((prev) => prev.filter((p) => p.pageIndex !== currentPage));
190
+ };
191
+
192
+ const handleSave = () => {
193
+ onSave(localPlacements);
194
+ onOpenChange(false);
195
+ };
196
+
197
+ return (
198
+ <Dialog open={open} onOpenChange={onOpenChange}>
199
+ <DialogContent className="w-[95vw] max-w-250 sm:max-w-250 h-[95vh] max-h-[95vh] bg-white/80 backdrop-blur-md overflow-hidden flex flex-col p-4">
200
+ <DialogHeader className="mb-2 shrink-0">
201
+ <DialogTitle>Visual Signature Placement</DialogTitle>
202
+ <div className="flex items-center justify-between mt-2">
203
+ <div className="flex items-center gap-2">
204
+ <Button
205
+ variant="outline"
206
+ size="icon"
207
+ onClick={() => setCurrentPage((p) => Math.max(0, p - 1))}
208
+ disabled={currentPage === 0 || isLoading}
209
+ >
210
+ <ChevronLeft className="h-4 w-4" />
211
+ </Button>
212
+ <span className="text-sm font-medium">
213
+ Page {currentPage + 1} of {totalPages}
214
+ </span>
215
+ <Button
216
+ variant="outline"
217
+ size="icon"
218
+ onClick={() => setCurrentPage((p) => Math.min(totalPages - 1, p + 1))}
219
+ disabled={currentPage === totalPages - 1 || isLoading}
220
+ >
221
+ <ChevronRight className="h-4 w-4" />
222
+ </Button>
223
+ </div>
224
+
225
+ {currentPlacement && (
226
+ <Button
227
+ variant="ghost"
228
+ size="sm"
229
+ onClick={handleRemoveCurrent}
230
+ className="text-muted-foreground"
231
+ >
232
+ Remove from this page
233
+ </Button>
234
+ )}
235
+ </div>
236
+ </DialogHeader>
237
+
238
+ <div className="relative flex-1 overflow-auto flex items-center justify-center bg-muted/40 border rounded-lg">
239
+ {isLoading && (
240
+ <div className="absolute inset-0 flex items-center justify-center bg-background/50 z-10 backdrop-blur-md">
241
+ <Loader2 className="h-8 w-8 animate-spin text-muted-foreground" />
242
+ </div>
243
+ )}
244
+
245
+ <div ref={containerRef} className="relative 35 bg-white overflow-hidden shrink-0">
246
+ <canvas ref={canvasRef} className="block w-full h-auto" />
247
+
248
+ {!isLoading && (
249
+ <motion.div
250
+ drag
251
+ dragMomentum={false}
252
+ dragConstraints={containerRef}
253
+ onDrag={(e, info) => {
254
+ setDragPos({ x: dragPos.x + info.delta.x, y: dragPos.y + info.delta.y });
255
+ }}
256
+ onDragEnd={handleDragEnd}
257
+ style={{
258
+ x: dragPos.x,
259
+ y: dragPos.y,
260
+ scale: (scale / 100) * pdfScale,
261
+ transformOrigin: 'top left',
262
+ }}
263
+ className="absolute top-0 left-0 cursor-move border border-primary/50 border-dashed hover:border-primary transition-colors w-max"
264
+ >
265
+ {mode === 'type' ? (
266
+ <span
267
+ style={{
268
+ fontFamily: font === 'Cursive' ? 'cursive' : 'sans-serif',
269
+ color: color === 'black' ? '#000' : color === 'blue' ? '#0000ff' : '#ff0000',
270
+ fontSize: '24px',
271
+ lineHeight: 1,
272
+ display: 'block',
273
+ }}
274
+ >
275
+ {text || 'Your Signature'}
276
+ </span>
277
+ ) : imagePayload ? (
278
+ <img
279
+ src={imagePayload}
280
+ alt="Signature"
281
+ className="max-h-15 pointer-events-none"
282
+ />
283
+ ) : (
284
+ <span className="text-muted-foreground text-sm">No signature</span>
285
+ )}
286
+ </motion.div>
287
+ )}
288
+ </div>
289
+ </div>
290
+
291
+ <DialogFooter className="mt-4 shrink-0 flex items-center justify-between">
292
+ <div className="text-xs text-muted-foreground">
293
+ {localPlacements.length} placement(s) set.
294
+ </div>
295
+ <div className="flex gap-2">
296
+ <Button variant="outline" onClick={() => onOpenChange(false)}>
297
+ Cancel
298
+ </Button>
299
+ <Button onClick={handleSave}>
300
+ <Save className="h-4 w-4 mr-2" />
301
+ Save Placements
302
+ </Button>
303
+ </div>
304
+ </DialogFooter>
305
+ </DialogContent>
306
+ </Dialog>
307
+ );
308
+ }
@@ -0,0 +1,209 @@
1
+ import { workspaceUrl, workspaceFetch as fetch } from '../../host';
2
+ import { useState } from 'react';
3
+ import { toast } from 'sonner';
4
+ import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from '../ui/dialog';
5
+ import { Button } from '@larkup/workspace-ui/button';
6
+ import { Input } from '../ui/input';
7
+ import { Label } from '@larkup/workspace-ui/label';
8
+ import { Eye, EyeOff, Loader2, Cloud } from 'lucide-react';
9
+ import type { CustomModelConfig } from '@larkup/core/types';
10
+
11
+ export function CustomModelForm({
12
+ onSave,
13
+ type,
14
+ onCancel,
15
+ }: {
16
+ onSave: (config: CustomModelConfig) => void;
17
+ type: 'embedding' | 'chat' | 'vision';
18
+ onCancel?: () => void;
19
+ }) {
20
+ const [baseUrl, setBaseUrl] = useState('');
21
+ const [apiKey, setApiKey] = useState('');
22
+ const [showApiKey, setShowApiKey] = useState(false);
23
+ const [modelName, setModelName] = useState('');
24
+ const [dimensions, setDimensions] = useState<number | null>(null);
25
+ const [testing, setTesting] = useState(false);
26
+ const [verified, setVerified] = useState(false);
27
+
28
+ const handleTest = async () => {
29
+ if (!baseUrl || !modelName) {
30
+ toast.error('Base URL and Model Name are required');
31
+ return;
32
+ }
33
+ setTesting(true);
34
+ try {
35
+ if (type === 'embedding') {
36
+ const res = await fetch(workspaceUrl('/api/config/test-embedding'), {
37
+ method: 'POST',
38
+ headers: { 'Content-Type': 'application/json' },
39
+ body: JSON.stringify({ baseUrl, apiKey, modelName }),
40
+ });
41
+ const data = await res.json();
42
+ if (!res.ok) throw new Error(data.error || 'Connection failed');
43
+
44
+ setDimensions(data.dimensions);
45
+ setVerified(true);
46
+ toast.success(`Success! Detected ${data.dimensions} dimensions.`);
47
+ } else {
48
+ const res = await fetch(workspaceUrl('/api/config/verify'), {
49
+ method: 'POST',
50
+ headers: { 'Content-Type': 'application/json' },
51
+ body: JSON.stringify(
52
+ type === 'vision'
53
+ ? {
54
+ visionProvider: 'custom',
55
+ visionApiKey: apiKey,
56
+ visionModelId: `custom:${modelName}`,
57
+ customVisionModels: [{ baseUrl, apiKey, modelName }],
58
+ }
59
+ : {
60
+ chatProvider: 'custom',
61
+ chatApiKey: apiKey,
62
+ customChatModels: [{ baseUrl, apiKey, modelName }],
63
+ },
64
+ ),
65
+ });
66
+ const data = await res.json();
67
+ if (!res.ok) throw new Error(data.error || 'Connection failed');
68
+
69
+ setVerified(true);
70
+ toast.success(`Success! ${type === 'vision' ? 'Vision' : 'Chat'} model connected.`);
71
+ }
72
+ } catch (err) {
73
+ toast.error(err instanceof Error ? err.message : 'Test failed');
74
+ setDimensions(null);
75
+ setVerified(false);
76
+ } finally {
77
+ setTesting(false);
78
+ }
79
+ };
80
+
81
+ const handleSave = () => {
82
+ if (!baseUrl || !modelName || !verified) {
83
+ toast.error('Please test the connection first.');
84
+ return;
85
+ }
86
+ onSave({ baseUrl, apiKey, modelName, dimensions: dimensions ?? undefined });
87
+ };
88
+
89
+ return (
90
+ <div className="flex flex-col gap-4">
91
+ <div className="grid gap-4 py-4">
92
+ <div className="grid gap-2">
93
+ <Label htmlFor="baseUrl">Base URL</Label>
94
+ <Input
95
+ id="baseUrl"
96
+ placeholder="https://api.example.com/v1"
97
+ value={baseUrl}
98
+ onChange={(e) => {
99
+ setBaseUrl(e.target.value);
100
+ setVerified(false);
101
+ }}
102
+ />
103
+ </div>
104
+ <div className="grid gap-2">
105
+ <Label htmlFor="apiKey">API Key (Optional)</Label>
106
+ <div className="relative">
107
+ <Input
108
+ id="apiKey"
109
+ type={showApiKey ? 'text' : 'password'}
110
+ placeholder="sk-..."
111
+ value={apiKey}
112
+ onChange={(e) => {
113
+ setApiKey(e.target.value);
114
+ setVerified(false);
115
+ }}
116
+ className="pr-10"
117
+ />
118
+ <button
119
+ type="button"
120
+ onClick={() => setShowApiKey(!showApiKey)}
121
+ className="absolute inset-y-0 right-0 flex items-center pr-3 text-muted-foreground hover:text-foreground"
122
+ >
123
+ {showApiKey ? <EyeOff className="size-4" /> : <Eye className="size-4" />}
124
+ </button>
125
+ </div>
126
+ </div>
127
+ <div className="grid gap-2">
128
+ <Label htmlFor="modelName">Model Name</Label>
129
+ <Input
130
+ id="modelName"
131
+ placeholder={
132
+ type === 'embedding'
133
+ ? 'my-embedding-model'
134
+ : type === 'vision'
135
+ ? 'my-vision-model'
136
+ : 'my-chat-model'
137
+ }
138
+ value={modelName}
139
+ onChange={(e) => {
140
+ setModelName(e.target.value);
141
+ setVerified(false);
142
+ }}
143
+ />
144
+ </div>
145
+ {verified && (
146
+ <div className="text-sm text-green-600 dark:text-green-400 font-medium">
147
+ ✓ Connection verified {dimensions ? `(${dimensions} dimensions)` : ''}
148
+ </div>
149
+ )}
150
+ </div>
151
+ <div className="flex flex-row justify-between sm:justify-between items-center gap-2">
152
+ <Button variant="outline" type="button" onClick={handleTest} disabled={testing}>
153
+ {testing ? (
154
+ <Loader2 className="size-4 animate-spin mr-2" />
155
+ ) : (
156
+ <Cloud className="size-4 mr-2" />
157
+ )}
158
+ Test Connection
159
+ </Button>
160
+ <div className="flex gap-2">
161
+ {onCancel && (
162
+ <Button variant="ghost" type="button" onClick={onCancel}>
163
+ Cancel
164
+ </Button>
165
+ )}
166
+ <Button className="px-5" type="button" onClick={handleSave} disabled={!verified}>
167
+ Add Model
168
+ </Button>
169
+ </div>
170
+ </div>
171
+ </div>
172
+ );
173
+ }
174
+
175
+ export function CustomModelModal({
176
+ open,
177
+ onOpenChange,
178
+ onSave,
179
+ type,
180
+ }: {
181
+ open: boolean;
182
+ onOpenChange: (open: boolean) => void;
183
+ onSave: (config: CustomModelConfig) => void;
184
+ type: 'embedding' | 'chat' | 'vision';
185
+ }) {
186
+ return (
187
+ <Dialog open={open} onOpenChange={onOpenChange}>
188
+ <DialogContent className={'max-w-xl'}>
189
+ <DialogHeader>
190
+ <DialogTitle>
191
+ Custom {type === 'embedding' ? 'Embedding' : type === 'vision' ? 'Vision' : 'Chat'}{' '}
192
+ Model
193
+ </DialogTitle>
194
+ <DialogDescription>
195
+ Connect an OpenAI-compatible{' '}
196
+ {type === 'embedding' ? 'embedding' : type === 'vision' ? 'vision' : 'chat'} model.
197
+ </DialogDescription>
198
+ </DialogHeader>
199
+ <CustomModelForm
200
+ type={type}
201
+ onSave={(cfg) => {
202
+ onSave(cfg);
203
+ onOpenChange(false);
204
+ }}
205
+ />
206
+ </DialogContent>
207
+ </Dialog>
208
+ );
209
+ }
@@ -0,0 +1,129 @@
1
+ 'use client';
2
+
3
+ import { useState } from 'react';
4
+ import { KeyRound, Eye, EyeOff } from 'lucide-react';
5
+ import { Input } from '@larkup/workspace-app/components/ui/input';
6
+ import { Label } from '@larkup/workspace-ui/label';
7
+ import {
8
+ Select,
9
+ SelectContent,
10
+ SelectItem,
11
+ SelectTrigger,
12
+ SelectValue,
13
+ } from '@larkup/workspace-ui/select';
14
+ import { Badge } from '@larkup/workspace-app/components/ui/badge';
15
+ import { cn } from '@larkup/workspace-app/lib/utils';
16
+ import { visibleFields } from '@larkup/vector-stores/registry';
17
+ import type { IndexType, VectorStoreDescriptor } from '@larkup/core/types';
18
+
19
+ interface StoreFieldsProps {
20
+ store: VectorStoreDescriptor;
21
+ values: Record<string, string>;
22
+ errors: Record<string, string>;
23
+ onChange: (key: string, value: string) => void;
24
+ indexType?: IndexType;
25
+ }
26
+
27
+ export function StoreFields({ store, values, errors, onChange, indexType }: StoreFieldsProps) {
28
+ const fields = visibleFields(store, values, indexType);
29
+ const [showPasswords, setShowPasswords] = useState<Record<string, boolean>>({});
30
+
31
+ const togglePassword = (key: string) => {
32
+ setShowPasswords((prev) => ({ ...prev, [key]: !prev[key] }));
33
+ };
34
+
35
+ return (
36
+ <div className="grid gap-5 sm:grid-cols-2">
37
+ {fields.map((field) => {
38
+ const value = values[field.key] ?? field.defaultValue ?? '';
39
+ const error = errors[field.key];
40
+ const fieldId = `store-${field.key}`;
41
+
42
+ return (
43
+ <div
44
+ key={field.key}
45
+ className={cn('space-y-1.5', field.type === 'select' && 'sm:col-span-1')}
46
+ >
47
+ <div className="flex items-center gap-1.5">
48
+ <Label htmlFor={fieldId}>{field.label}</Label>
49
+ {field.required && (
50
+ <span className="text-destructive" aria-hidden>
51
+ *
52
+ </span>
53
+ )}
54
+ {field.secret && (
55
+ <Badge
56
+ variant="outline"
57
+ className="h-4 gap-1 px-1 text-[9px] font-mono uppercase text-muted-foreground"
58
+ >
59
+ <KeyRound className="size-2.5" />
60
+ secret
61
+ </Badge>
62
+ )}
63
+ </div>
64
+
65
+ {field.type === 'select' ? (
66
+ <Select value={value} onValueChange={(v) => onChange(field.key, (v as string) ?? '')}>
67
+ <SelectTrigger id={fieldId} className={cn('w-full', error && 'border-destructive')}>
68
+ <SelectValue placeholder={`Select ${field.label}`} />
69
+ </SelectTrigger>
70
+ <SelectContent>
71
+ {field.options?.map((opt) => (
72
+ <SelectItem key={opt.value} value={opt.value}>
73
+ {opt.label}
74
+ </SelectItem>
75
+ ))}
76
+ </SelectContent>
77
+ </Select>
78
+ ) : field.type === 'password' ? (
79
+ <div className="relative">
80
+ <Input
81
+ id={fieldId}
82
+ type={showPasswords[field.key] ? 'text' : 'password'}
83
+ placeholder={field.placeholder}
84
+ value={value}
85
+ spellCheck={false}
86
+ autoComplete="off"
87
+ className={cn('font-mono text-sm pr-9', error && 'border-destructive')}
88
+ onChange={(e) => onChange(field.key, e.target.value)}
89
+ />
90
+ <button
91
+ type="button"
92
+ onClick={() => togglePassword(field.key)}
93
+ className="absolute right-2.5 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground transition-colors"
94
+ tabIndex={-1}
95
+ >
96
+ {showPasswords[field.key] ? (
97
+ <EyeOff className="size-4" />
98
+ ) : (
99
+ <Eye className="size-4" />
100
+ )}
101
+ </button>
102
+ </div>
103
+ ) : (
104
+ <Input
105
+ id={fieldId}
106
+ type="text"
107
+ placeholder={field.placeholder}
108
+ value={value}
109
+ spellCheck={false}
110
+ autoComplete="off"
111
+ className={cn(
112
+ field.type === 'path' && 'font-mono text-sm',
113
+ error && 'border-destructive',
114
+ )}
115
+ onChange={(e) => onChange(field.key, e.target.value)}
116
+ />
117
+ )}
118
+
119
+ {error ? (
120
+ <p className="text-xs text-destructive">{error}</p>
121
+ ) : field.help ? (
122
+ <p className="text-xs text-muted-foreground leading-relaxed">{field.help}</p>
123
+ ) : null}
124
+ </div>
125
+ );
126
+ })}
127
+ </div>
128
+ );
129
+ }