@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.
- package/LICENSE +176 -0
- package/README.md +4 -2
- package/assets/github.svg +3 -0
- package/assets/icons/Confluence.png +0 -0
- package/assets/icons/Instagram.png +0 -0
- package/assets/icons/Northflank.png +0 -0
- package/assets/icons/Salesforce.png +0 -0
- package/assets/icons/agentskills.png +0 -0
- package/assets/icons/airtable.png +0 -0
- package/assets/icons/asana.png +0 -0
- package/assets/icons/ashby.png +0 -0
- package/assets/icons/audio.png +0 -0
- package/assets/icons/aws-kendra.png +0 -0
- package/assets/icons/aws.svg +38 -0
- package/assets/icons/azure-ai-search.png +0 -0
- package/assets/icons/azure.svg +1 -0
- package/assets/icons/bigquery.png +0 -0
- package/assets/icons/bing.png +0 -0
- package/assets/icons/bitbucket.png +0 -0
- package/assets/icons/brave.png +0 -0
- package/assets/icons/browserbase.png +0 -0
- package/assets/icons/calendly.png +0 -0
- package/assets/icons/chroma.png +0 -0
- package/assets/icons/cloudflare.png +0 -0
- package/assets/icons/cohere.svg +30 -0
- package/assets/icons/databricks.png +0 -0
- package/assets/icons/daytonaio.png +0 -0
- package/assets/icons/daytonaio2.png +0 -0
- package/assets/icons/deepgram.png +0 -0
- package/assets/icons/deepl.png +0 -0
- package/assets/icons/digital-ocean.webp +0 -0
- package/assets/icons/discord.png +0 -0
- package/assets/icons/e2b-2.png +0 -0
- package/assets/icons/e2b.png +0 -0
- package/assets/icons/elevenlabs.png +0 -0
- package/assets/icons/email.png +0 -0
- package/assets/icons/exa.png +0 -0
- package/assets/icons/excel.png +0 -0
- package/assets/icons/fal.png +0 -0
- package/assets/icons/firecrawl.png +0 -0
- package/assets/icons/firecrawl2.png +0 -0
- package/assets/icons/flyio.jpeg +0 -0
- package/assets/icons/gcp.svg +1 -0
- package/assets/icons/gemini.svg +1 -0
- package/assets/icons/gmail.png +0 -0
- package/assets/icons/google-analytics.png +0 -0
- package/assets/icons/google-calender.png +0 -0
- package/assets/icons/google-docs.png +0 -0
- package/assets/icons/google-drive.png +0 -0
- package/assets/icons/google-maps.png +0 -0
- package/assets/icons/google-meet.png +0 -0
- package/assets/icons/google-sheets.png +0 -0
- package/assets/icons/google-slides.png +0 -0
- package/assets/icons/google-tasks.png +0 -0
- package/assets/icons/google.png +0 -0
- package/assets/icons/grok.png +0 -0
- package/assets/icons/hubspot.png +0 -0
- package/assets/icons/image.png +0 -0
- package/assets/icons/jina.svg +1 -0
- package/assets/icons/jira.png +0 -0
- package/assets/icons/lancedb2.png +0 -0
- package/assets/icons/linear.png +0 -0
- package/assets/icons/linux.png +0 -0
- package/assets/icons/looker.png +0 -0
- package/assets/icons/luma.png +0 -0
- package/assets/icons/mac.png +0 -0
- package/assets/icons/markdown.png +0 -0
- package/assets/icons/mcp.png +0 -0
- package/assets/icons/mcp.svg +1 -0
- package/assets/icons/messenger.svg +1 -0
- package/assets/icons/microsoft-intra.png +0 -0
- package/assets/icons/microsoft-onenote.png +0 -0
- package/assets/icons/microsoft-planner.png +0 -0
- package/assets/icons/microsoft-teams.png +0 -0
- package/assets/icons/miro.png +0 -0
- package/assets/icons/mistral.svg +469 -0
- package/assets/icons/modal.png +0 -0
- package/assets/icons/ngrok.png +0 -0
- package/assets/icons/nomic.png +0 -0
- package/assets/icons/onedrive.png +0 -0
- package/assets/icons/openai.svg +1 -0
- package/assets/icons/outlook-calendar.png +0 -0
- package/assets/icons/outlook-email.png +0 -0
- package/assets/icons/outlook.png +0 -0
- package/assets/icons/pdf.png +0 -0
- package/assets/icons/personio.png +0 -0
- package/assets/icons/pgvector2.png +0 -0
- package/assets/icons/phone.png +0 -0
- package/assets/icons/pinecone.png +0 -0
- package/assets/icons/pipedrive.png +0 -0
- package/assets/icons/power-pi.png +0 -0
- package/assets/icons/pylon.png +0 -0
- package/assets/icons/python.png +0 -0
- package/assets/icons/qdrant.svg +35 -0
- package/assets/icons/revai.png +0 -0
- package/assets/icons/revai.svg +1 -0
- package/assets/icons/sap.png +0 -0
- package/assets/icons/serpapi.svg +34 -0
- package/assets/icons/serper.png +0 -0
- package/assets/icons/servicenow.png +0 -0
- package/assets/icons/sharepoint.png +0 -0
- package/assets/icons/slack.png +0 -0
- package/assets/icons/snowflake.png +0 -0
- package/assets/icons/statistia.png +0 -0
- package/assets/icons/stripe.png +0 -0
- package/assets/icons/supabase.png +0 -0
- package/assets/icons/tableau.png +0 -0
- package/assets/icons/tavily.png +0 -0
- package/assets/icons/telegram.png +0 -0
- package/assets/icons/typescript.png +0 -0
- package/assets/icons/vercel copy.svg +1 -0
- package/assets/icons/vercel.svg +1 -0
- package/assets/icons/vertex-ai.png +0 -0
- package/assets/icons/video.png +0 -0
- package/assets/icons/voyage-light.png +0 -0
- package/assets/icons/weaviate.webp +0 -0
- package/assets/icons/webcontainers.svg +11 -0
- package/assets/icons/webhook.png +0 -0
- package/assets/icons/whatsapp copy.png +0 -0
- package/assets/icons/whatsapp.png +0 -0
- package/assets/icons/windows.png +0 -0
- package/assets/icons/word.png +0 -0
- package/assets/icons/zendesk.png +0 -0
- package/assets/icons/zoom.png +0 -0
- package/assets/notion-white.png +0 -0
- package/assets/notion.png +0 -0
- package/dist-types/asset-server.d.ts +3 -0
- package/dist-types/asset-server.d.ts.map +1 -0
- package/dist-types/components/alerts/generic-alert.d.ts +15 -0
- package/dist-types/components/alerts/generic-alert.d.ts.map +1 -0
- package/dist-types/components/chat/canvas/doc-editor-provider.d.ts +62 -0
- package/dist-types/components/chat/canvas/doc-editor-provider.d.ts.map +1 -0
- package/dist-types/components/chat/canvas/document-canvas.d.ts +7 -0
- package/dist-types/components/chat/canvas/document-canvas.d.ts.map +1 -0
- package/dist-types/components/chat/canvas/document-field.d.ts +13 -0
- package/dist-types/components/chat/canvas/document-field.d.ts.map +1 -0
- package/dist-types/components/chat/canvas/document-viewer.d.ts +2 -0
- package/dist-types/components/chat/canvas/document-viewer.d.ts.map +1 -0
- package/dist-types/components/chat/canvas/file-attachment-button.d.ts +9 -0
- package/dist-types/components/chat/canvas/file-attachment-button.d.ts.map +1 -0
- package/dist-types/components/chat/chat-workspace.d.ts +4 -0
- package/dist-types/components/chat/chat-workspace.d.ts.map +1 -0
- package/dist-types/components/chat/message-actions.d.ts +11 -0
- package/dist-types/components/chat/message-actions.d.ts.map +1 -0
- package/dist-types/components/chat/message-item.d.ts +20 -0
- package/dist-types/components/chat/message-item.d.ts.map +1 -0
- package/dist-types/components/chat/message-queue.d.ts +15 -0
- package/dist-types/components/chat/message-queue.d.ts.map +1 -0
- package/dist-types/components/chat/tools/chat-chart.d.ts +6 -0
- package/dist-types/components/chat/tools/chat-chart.d.ts.map +1 -0
- package/dist-types/components/chat/tools/chat-citations.d.ts +32 -0
- package/dist-types/components/chat/tools/chat-citations.d.ts.map +1 -0
- package/dist-types/components/chat/tools/chat-data-table.d.ts +14 -0
- package/dist-types/components/chat/tools/chat-data-table.d.ts.map +1 -0
- package/dist-types/components/chat/tools/chat-file-export.d.ts +5 -0
- package/dist-types/components/chat/tools/chat-file-export.d.ts.map +1 -0
- package/dist-types/components/chat/tools/chat-media-preview.d.ts +35 -0
- package/dist-types/components/chat/tools/chat-media-preview.d.ts.map +1 -0
- package/dist-types/components/chat/tools/chat-sandbox-result.d.ts +17 -0
- package/dist-types/components/chat/tools/chat-sandbox-result.d.ts.map +1 -0
- package/dist-types/components/chat/tools/chat-signature-request.d.ts +13 -0
- package/dist-types/components/chat/tools/chat-signature-request.d.ts.map +1 -0
- package/dist-types/components/chat/tools/chat-tabs.d.ts +17 -0
- package/dist-types/components/chat/tools/chat-tabs.d.ts.map +1 -0
- package/dist-types/components/chat/tools/corpus-data-result.d.ts +36 -0
- package/dist-types/components/chat/tools/corpus-data-result.d.ts.map +1 -0
- package/dist-types/components/chat/tools/knowledge-base-result.d.ts +14 -0
- package/dist-types/components/chat/tools/knowledge-base-result.d.ts.map +1 -0
- package/dist-types/components/chat/tools/visual-placement-modal.d.ts +23 -0
- package/dist-types/components/chat/tools/visual-placement-modal.d.ts.map +1 -0
- package/dist-types/components/configure/custom-model-modal.d.ts +13 -0
- package/dist-types/components/configure/custom-model-modal.d.ts.map +1 -0
- package/dist-types/components/configure/store-fields.d.ts +11 -0
- package/dist-types/components/configure/store-fields.d.ts.map +1 -0
- package/dist-types/components/data/corpus-panel.d.ts +12 -0
- package/dist-types/components/data/corpus-panel.d.ts.map +1 -0
- package/dist-types/components/data/data-entry-mode-switch.d.ts +13 -0
- package/dist-types/components/data/data-entry-mode-switch.d.ts.map +1 -0
- package/dist-types/components/data/data-primary-action.d.ts +7 -0
- package/dist-types/components/data/data-primary-action.d.ts.map +1 -0
- package/dist-types/components/data/data-workspace.d.ts +6 -0
- package/dist-types/components/data/data-workspace.d.ts.map +1 -0
- package/dist-types/components/data/groups-panel.d.ts +5 -0
- package/dist-types/components/data/groups-panel.d.ts.map +1 -0
- package/dist-types/components/data/integration-resources-panel.d.ts +9 -0
- package/dist-types/components/data/integration-resources-panel.d.ts.map +1 -0
- package/dist-types/components/data/integrations-panel.d.ts +5 -0
- package/dist-types/components/data/integrations-panel.d.ts.map +1 -0
- package/dist-types/components/data/jobs-panel.d.ts +6 -0
- package/dist-types/components/data/jobs-panel.d.ts.map +1 -0
- package/dist-types/components/data/jobs-tracking-button.d.ts +2 -0
- package/dist-types/components/data/jobs-tracking-button.d.ts.map +1 -0
- package/dist-types/components/data/live-media-progress.d.ts +9 -0
- package/dist-types/components/data/live-media-progress.d.ts.map +1 -0
- package/dist-types/components/data/media-indexing-jobs-panel.d.ts +34 -0
- package/dist-types/components/data/media-indexing-jobs-panel.d.ts.map +1 -0
- package/dist-types/components/data/media-panel.d.ts +58 -0
- package/dist-types/components/data/media-panel.d.ts.map +1 -0
- package/dist-types/components/data/notion-panel.d.ts +6 -0
- package/dist-types/components/data/notion-panel.d.ts.map +1 -0
- package/dist-types/components/data/paste-panel.d.ts +7 -0
- package/dist-types/components/data/paste-panel.d.ts.map +1 -0
- package/dist-types/components/data/project-data-page.d.ts +3 -0
- package/dist-types/components/data/project-data-page.d.ts.map +1 -0
- package/dist-types/components/data/scrape-panel.d.ts +9 -0
- package/dist-types/components/data/scrape-panel.d.ts.map +1 -0
- package/dist-types/components/data/tabular-preview.d.ts +10 -0
- package/dist-types/components/data/tabular-preview.d.ts.map +1 -0
- package/dist-types/components/data/tool-indexing-dialog.d.ts +54 -0
- package/dist-types/components/data/tool-indexing-dialog.d.ts.map +1 -0
- package/dist-types/components/data/upload-panel.d.ts +7 -0
- package/dist-types/components/data/upload-panel.d.ts.map +1 -0
- package/dist-types/components/data/web-crawler-status.d.ts +3 -0
- package/dist-types/components/data/web-crawler-status.d.ts.map +1 -0
- package/dist-types/components/projects/project-form-dialog.d.ts +10 -0
- package/dist-types/components/projects/project-form-dialog.d.ts.map +1 -0
- package/dist-types/components/projects/project-provider.d.ts +34 -0
- package/dist-types/components/projects/project-provider.d.ts.map +1 -0
- package/dist-types/components/settings/general/agent-customization-section.d.ts +2 -0
- package/dist-types/components/settings/general/agent-customization-section.d.ts.map +1 -0
- package/dist-types/components/settings/general/mcp-connections-section.d.ts +2 -0
- package/dist-types/components/settings/general/mcp-connections-section.d.ts.map +1 -0
- package/dist-types/components/settings/general/model-combobox.d.ts +24 -0
- package/dist-types/components/settings/general/model-combobox.d.ts.map +1 -0
- package/dist-types/components/settings/general/models-section.d.ts +2 -0
- package/dist-types/components/settings/general/models-section.d.ts.map +1 -0
- package/dist-types/components/settings/general/sandbox-section.d.ts +7 -0
- package/dist-types/components/settings/general/sandbox-section.d.ts.map +1 -0
- package/dist-types/components/settings/general/search-scraping-section.d.ts +2 -0
- package/dist-types/components/settings/general/search-scraping-section.d.ts.map +1 -0
- package/dist-types/components/settings/general/storage-indexing-section.d.ts +2 -0
- package/dist-types/components/settings/general/storage-indexing-section.d.ts.map +1 -0
- package/dist-types/components/ui/alert-dialog.d.ts +19 -0
- package/dist-types/components/ui/alert-dialog.d.ts.map +1 -0
- package/dist-types/components/ui/alert.d.ts +11 -0
- package/dist-types/components/ui/alert.d.ts.map +1 -0
- package/dist-types/components/ui/badge.d.ts +8 -0
- package/dist-types/components/ui/badge.d.ts.map +1 -0
- package/dist-types/components/ui/card.d.ts +2 -0
- package/dist-types/components/ui/card.d.ts.map +1 -0
- package/dist-types/components/ui/checkbox.d.ts +4 -0
- package/dist-types/components/ui/checkbox.d.ts.map +1 -0
- package/dist-types/components/ui/collapsible.d.ts +6 -0
- package/dist-types/components/ui/collapsible.d.ts.map +1 -0
- package/dist-types/components/ui/command.d.ts +20 -0
- package/dist-types/components/ui/command.d.ts.map +1 -0
- package/dist-types/components/ui/dialog.d.ts +18 -0
- package/dist-types/components/ui/dialog.d.ts.map +1 -0
- package/dist-types/components/ui/dropdown-menu.d.ts +30 -0
- package/dist-types/components/ui/dropdown-menu.d.ts.map +1 -0
- package/dist-types/components/ui/input-group.d.ts +19 -0
- package/dist-types/components/ui/input-group.d.ts.map +1 -0
- package/dist-types/components/ui/input.d.ts +4 -0
- package/dist-types/components/ui/input.d.ts.map +1 -0
- package/dist-types/components/ui/line-tabs.d.ts +15 -0
- package/dist-types/components/ui/line-tabs.d.ts.map +1 -0
- package/dist-types/components/ui/popover.d.ts +10 -0
- package/dist-types/components/ui/popover.d.ts.map +1 -0
- package/dist-types/components/ui/progress.d.ts +8 -0
- package/dist-types/components/ui/progress.d.ts.map +1 -0
- package/dist-types/components/ui/scroll-area.d.ts +6 -0
- package/dist-types/components/ui/scroll-area.d.ts.map +1 -0
- package/dist-types/components/ui/sheet.d.ts +15 -0
- package/dist-types/components/ui/sheet.d.ts.map +1 -0
- package/dist-types/components/ui/slider.d.ts +4 -0
- package/dist-types/components/ui/slider.d.ts.map +1 -0
- package/dist-types/components/ui/switch.d.ts +6 -0
- package/dist-types/components/ui/switch.d.ts.map +1 -0
- package/dist-types/components/ui/table.d.ts +2 -0
- package/dist-types/components/ui/table.d.ts.map +1 -0
- package/dist-types/components/ui/tabs.d.ts +11 -0
- package/dist-types/components/ui/tabs.d.ts.map +1 -0
- package/dist-types/components/ui/textarea.d.ts +2 -0
- package/dist-types/components/ui/textarea.d.ts.map +1 -0
- package/dist-types/components/ui/tooltip.d.ts +7 -0
- package/dist-types/components/ui/tooltip.d.ts.map +1 -0
- package/dist-types/hooks/use-copy-to-clipboard.d.ts +5 -0
- package/dist-types/hooks/use-copy-to-clipboard.d.ts.map +1 -0
- package/dist-types/hooks/use-integration-auth.d.ts +10 -0
- package/dist-types/hooks/use-integration-auth.d.ts.map +1 -0
- package/dist-types/hooks/use-live-media-progress.d.ts +14 -0
- package/dist-types/hooks/use-live-media-progress.d.ts.map +1 -0
- package/dist-types/hooks/use-notion-auth.d.ts +9 -0
- package/dist-types/hooks/use-notion-auth.d.ts.map +1 -0
- package/dist-types/host.d.ts +20 -0
- package/dist-types/host.d.ts.map +1 -0
- package/dist-types/lib/browser-cache.d.ts +7 -0
- package/dist-types/lib/browser-cache.d.ts.map +1 -0
- package/dist-types/lib/chat/chart-config.d.ts +2 -0
- package/dist-types/lib/chat/chart-config.d.ts.map +1 -0
- package/dist-types/lib/chat/data-export.d.ts +2 -0
- package/dist-types/lib/chat/data-export.d.ts.map +1 -0
- package/dist-types/lib/chat/live-tool-progress.d.ts +44 -0
- package/dist-types/lib/chat/live-tool-progress.d.ts.map +1 -0
- package/dist-types/lib/chat/message-feedback.d.ts +2 -0
- package/dist-types/lib/chat/message-feedback.d.ts.map +1 -0
- package/dist-types/lib/chat/table-presentation.d.ts +2 -0
- package/dist-types/lib/chat/table-presentation.d.ts.map +1 -0
- package/dist-types/lib/chat/tool-output.d.ts +3 -0
- package/dist-types/lib/chat/tool-output.d.ts.map +1 -0
- package/dist-types/lib/chat-supporting-clip.d.ts +11 -0
- package/dist-types/lib/chat-supporting-clip.d.ts.map +1 -0
- package/dist-types/lib/constants/stores.d.ts +6 -0
- package/dist-types/lib/constants/stores.d.ts.map +1 -0
- package/dist-types/lib/constants/tools.d.ts +27 -0
- package/dist-types/lib/constants/tools.d.ts.map +1 -0
- package/dist-types/lib/error-formatter.d.ts +2 -0
- package/dist-types/lib/error-formatter.d.ts.map +1 -0
- package/dist-types/lib/jobs-client.d.ts +7 -0
- package/dist-types/lib/jobs-client.d.ts.map +1 -0
- package/dist-types/lib/media/pdf.d.ts +6 -0
- package/dist-types/lib/media/pdf.d.ts.map +1 -0
- package/dist-types/lib/media/progress.d.ts +61 -0
- package/dist-types/lib/media/progress.d.ts.map +1 -0
- package/dist-types/lib/media/source-selection.d.ts +10 -0
- package/dist-types/lib/media/source-selection.d.ts.map +1 -0
- package/dist-types/lib/media/tool-indexing-estimate.d.ts +13 -0
- package/dist-types/lib/media/tool-indexing-estimate.d.ts.map +1 -0
- package/dist-types/lib/media/video-intelligence-capacity.d.ts +2 -0
- package/dist-types/lib/media/video-intelligence-capacity.d.ts.map +1 -0
- package/dist-types/lib/media/video-runtime-scope.d.ts +2 -0
- package/dist-types/lib/media/video-runtime-scope.d.ts.map +1 -0
- package/dist-types/lib/shared/error-formatter.d.ts +2 -0
- package/dist-types/lib/shared/error-formatter.d.ts.map +1 -0
- package/dist-types/lib/utils.d.ts +3 -0
- package/dist-types/lib/utils.d.ts.map +1 -0
- package/dist-types/storage.d.ts +5 -0
- package/dist-types/storage.d.ts.map +1 -0
- package/dist-types/store/chat-store.d.ts +19 -0
- package/dist-types/store/chat-store.d.ts.map +1 -0
- package/dist-types/store/scrape-store.d.ts +42 -0
- package/dist-types/store/scrape-store.d.ts.map +1 -0
- package/package.json +579 -3
- package/scripts/build-assets.mjs +12 -0
- package/src/asset-data.json +1 -0
- package/src/asset-server.ts +19 -0
- package/src/components/alerts/generic-alert.tsx +76 -0
- package/src/components/chat/canvas/doc-editor-provider.tsx +338 -0
- package/src/components/chat/canvas/document-canvas.tsx +98 -0
- package/src/components/chat/canvas/document-field.tsx +167 -0
- package/src/components/chat/canvas/document-viewer.tsx +446 -0
- package/src/components/chat/canvas/file-attachment-button.tsx +88 -0
- package/src/components/chat/chat-workspace.tsx +1552 -0
- package/src/components/chat/message-actions.tsx +96 -0
- package/src/components/chat/message-item.tsx +1398 -0
- package/src/components/chat/message-queue.tsx +86 -0
- package/src/components/chat/tools/chat-chart.tsx +558 -0
- package/src/components/chat/tools/chat-citations.tsx +152 -0
- package/src/components/chat/tools/chat-data-table.tsx +373 -0
- package/src/components/chat/tools/chat-file-export.tsx +49 -0
- package/src/components/chat/tools/chat-media-preview.tsx +466 -0
- package/src/components/chat/tools/chat-sandbox-result.tsx +130 -0
- package/src/components/chat/tools/chat-signature-request.tsx +810 -0
- package/src/components/chat/tools/chat-tabs.tsx +59 -0
- package/src/components/chat/tools/corpus-data-result.tsx +194 -0
- package/src/components/chat/tools/knowledge-base-result.tsx +345 -0
- package/src/components/chat/tools/visual-placement-modal.tsx +308 -0
- package/src/components/configure/custom-model-modal.tsx +209 -0
- package/src/components/configure/store-fields.tsx +129 -0
- package/src/components/data/corpus-panel.tsx +1223 -0
- package/src/components/data/data-entry-mode-switch.tsx +53 -0
- package/src/components/data/data-primary-action.ts +6 -0
- package/src/components/data/data-workspace.tsx +623 -0
- package/src/components/data/groups-panel.tsx +530 -0
- package/src/components/data/integration-resources-panel.tsx +282 -0
- package/src/components/data/integrations-panel.tsx +392 -0
- package/src/components/data/jobs-panel.tsx +490 -0
- package/src/components/data/jobs-tracking-button.tsx +224 -0
- package/src/components/data/live-media-progress.tsx +79 -0
- package/src/components/data/media-indexing-jobs-panel.tsx +190 -0
- package/src/components/data/media-panel.tsx +2905 -0
- package/src/components/data/notion-panel.tsx +408 -0
- package/src/components/data/paste-panel.tsx +82 -0
- package/src/components/data/project-data-page.tsx +55 -0
- package/src/components/data/scrape-panel.tsx +1290 -0
- package/src/components/data/tabular-preview.tsx +205 -0
- package/src/components/data/tool-indexing-dialog.tsx +210 -0
- package/src/components/data/upload-panel.tsx +1313 -0
- package/src/components/data/web-crawler-status.tsx +132 -0
- package/src/components/projects/project-form-dialog.tsx +97 -0
- package/src/components/projects/project-provider.tsx +143 -0
- package/src/components/settings/general/agent-customization-section.tsx +620 -0
- package/src/components/settings/general/mcp-connections-section.tsx +907 -0
- package/src/components/settings/general/model-combobox.tsx +235 -0
- package/src/components/settings/general/models-section.tsx +909 -0
- package/src/components/settings/general/sandbox-section.tsx +394 -0
- package/src/components/settings/general/search-scraping-section.tsx +757 -0
- package/src/components/settings/general/storage-indexing-section.tsx +394 -0
- package/src/components/ui/alert-dialog.tsx +162 -0
- package/src/components/ui/alert.tsx +69 -0
- package/src/components/ui/badge.tsx +49 -0
- package/src/components/ui/card.tsx +9 -0
- package/src/components/ui/checkbox.tsx +28 -0
- package/src/components/ui/collapsible.tsx +17 -0
- package/src/components/ui/command.tsx +175 -0
- package/src/components/ui/dialog.tsx +138 -0
- package/src/components/ui/dropdown-menu.tsx +267 -0
- package/src/components/ui/input-group.tsx +146 -0
- package/src/components/ui/input.tsx +19 -0
- package/src/components/ui/line-tabs.tsx +49 -0
- package/src/components/ui/popover.tsx +77 -0
- package/src/components/ui/progress.tsx +66 -0
- package/src/components/ui/scroll-area.tsx +51 -0
- package/src/components/ui/sheet.tsx +125 -0
- package/src/components/ui/slider.tsx +52 -0
- package/src/components/ui/switch.tsx +32 -0
- package/src/components/ui/table.tsx +10 -0
- package/src/components/ui/tabs.tsx +77 -0
- package/src/components/ui/textarea.tsx +1 -0
- package/src/components/ui/tooltip.tsx +54 -0
- package/src/hooks/use-copy-to-clipboard.ts +25 -0
- package/src/hooks/use-integration-auth.ts +39 -0
- package/src/hooks/use-live-media-progress.ts +71 -0
- package/src/hooks/use-notion-auth.ts +66 -0
- package/src/host.ts +55 -0
- package/src/lib/browser-cache.ts +17 -0
- package/src/lib/chat/chart-config.ts +1 -0
- package/src/lib/chat/data-export.ts +1 -0
- package/src/lib/chat/live-tool-progress.ts +69 -0
- package/src/lib/chat/message-feedback.ts +1 -0
- package/src/lib/chat/table-presentation.ts +1 -0
- package/src/lib/chat/tool-output.ts +14 -0
- package/src/lib/chat-supporting-clip.ts +16 -0
- package/src/lib/constants/stores.ts +12 -0
- package/src/lib/constants/tools.ts +178 -0
- package/src/lib/error-formatter.ts +30 -0
- package/src/lib/jobs-client.ts +27 -0
- package/src/lib/media/pdf.ts +57 -0
- package/src/lib/media/progress.ts +209 -0
- package/src/lib/media/source-selection.ts +47 -0
- package/src/lib/media/tool-indexing-estimate.ts +39 -0
- package/src/lib/media/video-intelligence-capacity.ts +1 -0
- package/src/lib/media/video-runtime-scope.ts +1 -0
- package/src/lib/shared/error-formatter.ts +1 -0
- package/src/lib/utils.ts +6 -0
- package/src/source.css +1 -0
- package/src/storage.ts +16 -0
- package/src/store/chat-store.ts +19 -0
- package/src/store/scrape-store.ts +76 -0
- package/src/styles.d.ts +1 -0
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import type { LucideIcon } from 'lucide-react';
|
|
4
|
+
import { cn } from '../../lib/utils';
|
|
5
|
+
|
|
6
|
+
export interface DataEntryModeOption {
|
|
7
|
+
value: string;
|
|
8
|
+
label: string;
|
|
9
|
+
icon: LucideIcon;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function DataEntryModeSwitch({
|
|
13
|
+
value,
|
|
14
|
+
onValueChange,
|
|
15
|
+
options,
|
|
16
|
+
label,
|
|
17
|
+
}: {
|
|
18
|
+
value: string;
|
|
19
|
+
onValueChange: (value: string) => void;
|
|
20
|
+
options: readonly DataEntryModeOption[];
|
|
21
|
+
label: string;
|
|
22
|
+
}) {
|
|
23
|
+
return (
|
|
24
|
+
<div
|
|
25
|
+
role="group"
|
|
26
|
+
aria-label={label}
|
|
27
|
+
className="inline-flex h-10 w-fit items-center gap-1 rounded-lg border border-border/90 bg-muted/60 p-1 text-muted-foreground"
|
|
28
|
+
>
|
|
29
|
+
{options.map((option) => {
|
|
30
|
+
const Icon = option.icon;
|
|
31
|
+
const active = value === option.value;
|
|
32
|
+
return (
|
|
33
|
+
<button
|
|
34
|
+
key={option.value}
|
|
35
|
+
type="button"
|
|
36
|
+
aria-pressed={active}
|
|
37
|
+
data-state={active ? 'active' : 'inactive'}
|
|
38
|
+
onClick={() => onValueChange(option.value)}
|
|
39
|
+
className={cn(
|
|
40
|
+
'inline-flex h-8 items-center justify-center gap-1.5 whitespace-nowrap rounded-md px-3 text-xs font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/50',
|
|
41
|
+
active
|
|
42
|
+
? 'bg-background text-foreground ring-1 ring-border'
|
|
43
|
+
: 'text-muted-foreground hover:bg-background/60 hover:text-foreground',
|
|
44
|
+
)}
|
|
45
|
+
>
|
|
46
|
+
<Icon className="size-3.5" strokeWidth={active ? 2 : 1.75} aria-hidden="true" />
|
|
47
|
+
{option.label}
|
|
48
|
+
</button>
|
|
49
|
+
);
|
|
50
|
+
})}
|
|
51
|
+
</div>
|
|
52
|
+
);
|
|
53
|
+
}
|
|
@@ -0,0 +1,623 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { workspaceUrl, workspaceFetch as fetch } from '../../host';
|
|
4
|
+
import { useState, useEffect, useRef, useCallback } from 'react';
|
|
5
|
+
import { useSearchParams, usePathname } from 'next/navigation';
|
|
6
|
+
import Link from 'next/link';
|
|
7
|
+
import useSWR, { useSWRConfig } from 'swr';
|
|
8
|
+
import { toast } from 'sonner';
|
|
9
|
+
import { cn } from '../../lib/utils';
|
|
10
|
+
import type { CrawlJob, DataGroup, SourceDocument, IndexRun, RagConfig } from '@larkup/core/types';
|
|
11
|
+
import { Globe, FileUp, Type, Image, Plug, History, Loader2, Plus, KeyRound } from 'lucide-react';
|
|
12
|
+
import { ScrapePanel } from './scrape-panel';
|
|
13
|
+
import { WebCrawlerStatus } from './web-crawler-status';
|
|
14
|
+
import { PastePanel } from './paste-panel';
|
|
15
|
+
import { UploadPanel } from './upload-panel';
|
|
16
|
+
import { MediaPanel } from './media-panel';
|
|
17
|
+
import { IntegrationsPanel } from './integrations-panel';
|
|
18
|
+
import { JobsPanel } from './jobs-panel';
|
|
19
|
+
import {
|
|
20
|
+
isActiveMediaIndexing,
|
|
21
|
+
MediaIndexingJobsPanel,
|
|
22
|
+
type MediaIndexingResponse,
|
|
23
|
+
} from './media-indexing-jobs-panel';
|
|
24
|
+
import { CorpusPanel } from './corpus-panel';
|
|
25
|
+
import type { DataPrimaryAction } from './data-primary-action';
|
|
26
|
+
import { useProject } from '../projects/project-provider';
|
|
27
|
+
import { WorkspaceLineTabs, WorkspacePageHeading } from '@larkup/workspace-ui';
|
|
28
|
+
import { Button } from '@larkup/workspace-ui/button';
|
|
29
|
+
import { Select, SelectContent, SelectItem, SelectTrigger } from '@larkup/workspace-ui/select';
|
|
30
|
+
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '../ui/tooltip';
|
|
31
|
+
import { fetchJobsWithSync } from '../../lib/jobs-client';
|
|
32
|
+
import { videoRuntimeScopeFromConfig } from '../../lib/media/video-runtime-scope';
|
|
33
|
+
|
|
34
|
+
const fetcher = async <T,>(url: string): Promise<T> => {
|
|
35
|
+
const response = await fetch(url);
|
|
36
|
+
const payload = await response.json().catch(() => null);
|
|
37
|
+
if (!response.ok) {
|
|
38
|
+
const message =
|
|
39
|
+
payload &&
|
|
40
|
+
typeof payload === 'object' &&
|
|
41
|
+
'error' in payload &&
|
|
42
|
+
typeof payload.error === 'string'
|
|
43
|
+
? payload.error
|
|
44
|
+
: 'Could not load workspace data.';
|
|
45
|
+
throw new Error(message);
|
|
46
|
+
}
|
|
47
|
+
return payload as T;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
interface DocsResponse {
|
|
51
|
+
documents: SourceDocument[];
|
|
52
|
+
groups: DataGroup[];
|
|
53
|
+
stats: {
|
|
54
|
+
docCount: number;
|
|
55
|
+
charCount: number;
|
|
56
|
+
bySource: Record<string, number>;
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const SUB_TABS = [
|
|
61
|
+
{ id: 'files', label: 'Files', icon: FileUp },
|
|
62
|
+
{ id: 'text', label: 'Text', icon: Type },
|
|
63
|
+
{ id: 'website', label: 'Website', icon: Globe },
|
|
64
|
+
{ id: 'media', label: 'Media', icon: Image },
|
|
65
|
+
{ id: 'integrations', label: 'Integrations', icon: Plug },
|
|
66
|
+
] as const;
|
|
67
|
+
|
|
68
|
+
type TopTabId = 'add' | 'corpus';
|
|
69
|
+
type SubTabId = (typeof SUB_TABS)[number]['id'];
|
|
70
|
+
|
|
71
|
+
function normalizeGroupId(value: string | null): string {
|
|
72
|
+
const groupId = value?.split(',')[0]?.trim();
|
|
73
|
+
return !groupId || groupId === 'undefined' || groupId === 'null' ? 'default' : groupId;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const SUB_TAB_INTRO: Record<SubTabId, { title: string; description: string }> = {
|
|
77
|
+
files: {
|
|
78
|
+
title: 'Add Files',
|
|
79
|
+
description: 'Upload PDFs, documents, spreadsheets, CSVs, JSON files, and more.',
|
|
80
|
+
},
|
|
81
|
+
text: {
|
|
82
|
+
title: 'Add Text',
|
|
83
|
+
description: 'Paste notes, documentation, transcripts, or any text you want to search.',
|
|
84
|
+
},
|
|
85
|
+
website: {
|
|
86
|
+
title: 'Add Websites',
|
|
87
|
+
description: 'Add a URL or discover and crawl websites for your knowledge base.',
|
|
88
|
+
},
|
|
89
|
+
media: {
|
|
90
|
+
title: 'Add Media',
|
|
91
|
+
description: 'Upload images, audio, and video, or add media from a URL.',
|
|
92
|
+
},
|
|
93
|
+
integrations: {
|
|
94
|
+
title: 'Add Integrations',
|
|
95
|
+
description: 'Connect your tools and import the data your team already uses.',
|
|
96
|
+
},
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
export function DataWorkspace({ view }: { view?: TopTabId } = {}) {
|
|
100
|
+
const searchParams = useSearchParams();
|
|
101
|
+
const queryGroupId = normalizeGroupId(searchParams.get('groupId'));
|
|
102
|
+
const pathname = usePathname();
|
|
103
|
+
const { activeProject } = useProject();
|
|
104
|
+
const serverId = activeProject?.id;
|
|
105
|
+
|
|
106
|
+
const getInitialTab = (): TopTabId => {
|
|
107
|
+
if (view) return view;
|
|
108
|
+
return 'add';
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
const getInitialSubTab = (): SubTabId => {
|
|
112
|
+
const subtab = searchParams.get('subtab') as SubTabId;
|
|
113
|
+
if (subtab && SUB_TABS.some((t) => t.id === subtab)) return subtab;
|
|
114
|
+
return 'files';
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
const [activeTab, setActiveTabState] = useState<TopTabId>(getInitialTab());
|
|
118
|
+
const [activeSubTab, setActiveSubTabState] = useState<SubTabId>(getInitialSubTab());
|
|
119
|
+
const [selectedGroupId, setSelectedGroupId] = useState(queryGroupId);
|
|
120
|
+
|
|
121
|
+
useEffect(() => {
|
|
122
|
+
if (view) {
|
|
123
|
+
setActiveTabState(view);
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
const subtab = searchParams.get('subtab') as SubTabId;
|
|
127
|
+
if (subtab && subtab !== activeSubTab && SUB_TABS.some((t) => t.id === subtab)) {
|
|
128
|
+
setActiveSubTabState(subtab);
|
|
129
|
+
}
|
|
130
|
+
}, [searchParams, activeTab, activeSubTab, view]);
|
|
131
|
+
|
|
132
|
+
useEffect(() => setSelectedGroupId(queryGroupId), [queryGroupId]);
|
|
133
|
+
|
|
134
|
+
const setActiveSubTab = (subtab: SubTabId) => {
|
|
135
|
+
// The outgoing panel owns the shared primary action. Clear it before changing
|
|
136
|
+
// tabs so the incoming panel can register its action after it mounts.
|
|
137
|
+
// Clearing it in an effect races with that registration on initial render.
|
|
138
|
+
setPrimaryAction(null);
|
|
139
|
+
setActiveSubTabState(subtab);
|
|
140
|
+
const params = new URLSearchParams(searchParams.toString());
|
|
141
|
+
params.set('subtab', subtab);
|
|
142
|
+
window.history.replaceState(null, '', `${pathname}?${params.toString()}`);
|
|
143
|
+
};
|
|
144
|
+
const [showJobsDrawer, setShowJobsDrawer] = useState(false);
|
|
145
|
+
const [primaryAction, setPrimaryAction] = useState<DataPrimaryAction | null>(null);
|
|
146
|
+
const registerPrimaryAction = useCallback((action: DataPrimaryAction | null) => {
|
|
147
|
+
setPrimaryAction(action);
|
|
148
|
+
}, []);
|
|
149
|
+
const prevJobsRef = useRef<CrawlJob[]>([]);
|
|
150
|
+
const pendingIndexRef = useRef(false);
|
|
151
|
+
|
|
152
|
+
const jobsQuery = useSWR(workspaceUrl('/api/jobs'), fetchJobsWithSync, {
|
|
153
|
+
refreshInterval: (data) =>
|
|
154
|
+
data?.jobs?.some((j) => j.status === 'running' || j.status === 'queued') ? 4000 : 0,
|
|
155
|
+
});
|
|
156
|
+
const jobs = jobsQuery.data?.jobs ?? [];
|
|
157
|
+
const hasActiveCrawlJobs = jobs.some((j) => j.status === 'running' || j.status === 'queued');
|
|
158
|
+
|
|
159
|
+
const indexQuery = useSWR<{
|
|
160
|
+
unindexedCount: number;
|
|
161
|
+
running: boolean;
|
|
162
|
+
run: IndexRun | null;
|
|
163
|
+
blockers: string[];
|
|
164
|
+
}>(workspaceUrl('/api/index'), fetcher, {
|
|
165
|
+
refreshInterval: (d) => (d?.running ? 2000 : 0),
|
|
166
|
+
});
|
|
167
|
+
const indexRunning = indexQuery.data?.running ?? false;
|
|
168
|
+
const dataAddBlocked = indexQuery.data?.blockers?.includes('MISSING_EMBEDDING_API_KEY') ?? false;
|
|
169
|
+
const { mutate: mutateIndex } = indexQuery;
|
|
170
|
+
|
|
171
|
+
const mediaQuery = useSWR<MediaIndexingResponse>(
|
|
172
|
+
workspaceUrl(
|
|
173
|
+
`/api/media?type=all${serverId ? `&serverId=${encodeURIComponent(serverId)}` : ''}`,
|
|
174
|
+
),
|
|
175
|
+
fetcher,
|
|
176
|
+
{
|
|
177
|
+
refreshInterval: (data) => (data?.assets?.some(isActiveMediaIndexing) ? 2_000 : 8_000),
|
|
178
|
+
revalidateOnFocus: true,
|
|
179
|
+
},
|
|
180
|
+
);
|
|
181
|
+
const activeMediaAssets = (mediaQuery.data?.assets ?? []).filter(isActiveMediaIndexing);
|
|
182
|
+
const hasActiveMedia = activeMediaAssets.length > 0;
|
|
183
|
+
const hasActive = hasActiveCrawlJobs || hasActiveMedia || indexRunning;
|
|
184
|
+
const activeCrawlTargetCount = jobs
|
|
185
|
+
.filter((job) => job.status === 'running' || job.status === 'queued')
|
|
186
|
+
.reduce((count, job) => count + (job.targets?.length || 1), 0);
|
|
187
|
+
const activeJobCount = activeCrawlTargetCount + activeMediaAssets.length + (indexRunning ? 1 : 0);
|
|
188
|
+
const hasJobsDrawerContent = jobs.length > 0 || hasActiveMedia || indexRunning;
|
|
189
|
+
const activeOrAttentionJobs = jobs.filter((job) => job.status !== 'completed');
|
|
190
|
+
const completedJobs = jobs.filter((job) => job.status === 'completed');
|
|
191
|
+
const [jobsFilterTab, setJobsFilterTab] = useState<'running' | 'all'>('running');
|
|
192
|
+
|
|
193
|
+
const docsQuery = useSWR<DocsResponse>(workspaceUrl('/api/documents'), fetcher, {
|
|
194
|
+
refreshInterval: hasActive ? 5000 : 0,
|
|
195
|
+
});
|
|
196
|
+
const { mutate: mutateDocuments } = docsQuery;
|
|
197
|
+
const documents = docsQuery.data?.documents ?? [];
|
|
198
|
+
const groups = docsQuery.data?.groups ?? [];
|
|
199
|
+
const configQuery = useSWR<{ config: RagConfig }>(
|
|
200
|
+
workspaceUrl(`/api/config${serverId ? `?serverId=${encodeURIComponent(serverId)}` : ''}`),
|
|
201
|
+
fetcher,
|
|
202
|
+
);
|
|
203
|
+
const activeVideoRuntimeScope = videoRuntimeScopeFromConfig(configQuery.data?.config);
|
|
204
|
+
|
|
205
|
+
const selectedGroup = groups.find((group) => group.id === selectedGroupId);
|
|
206
|
+
// Keep the requested destination stable while groups are loading. Resolving
|
|
207
|
+
// through the temporarily empty SWR result used to turn a valid selection
|
|
208
|
+
// into Default during the first render and made fast submissions race.
|
|
209
|
+
const targetGroupId = selectedGroupId;
|
|
210
|
+
const groupSelectionReady =
|
|
211
|
+
docsQuery.data !== undefined &&
|
|
212
|
+
!docsQuery.error &&
|
|
213
|
+
(targetGroupId === 'default' || selectedGroup !== undefined);
|
|
214
|
+
|
|
215
|
+
useEffect(() => {
|
|
216
|
+
if (dataAddBlocked) setPrimaryAction(null);
|
|
217
|
+
}, [dataAddBlocked]);
|
|
218
|
+
|
|
219
|
+
const { mutate: mutateGlobal } = useSWRConfig();
|
|
220
|
+
|
|
221
|
+
const refreshAll = async () => {
|
|
222
|
+
await Promise.all([
|
|
223
|
+
jobsQuery.mutate(),
|
|
224
|
+
mediaQuery.mutate(),
|
|
225
|
+
docsQuery.mutate(),
|
|
226
|
+
indexQuery.mutate(),
|
|
227
|
+
mutateGlobal(workspaceUrl('/api/index')),
|
|
228
|
+
]);
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
const startAutomaticIndex = useCallback(async () => {
|
|
232
|
+
try {
|
|
233
|
+
const res = await fetch(workspaceUrl('/api/index'), {
|
|
234
|
+
method: 'POST',
|
|
235
|
+
headers: { 'Content-Type': 'application/json' },
|
|
236
|
+
body: JSON.stringify({ incremental: Boolean(indexQuery.data?.run) }),
|
|
237
|
+
});
|
|
238
|
+
const body = await res.json();
|
|
239
|
+
if (res.status === 409 || body.queued) {
|
|
240
|
+
pendingIndexRef.current = res.status === 409;
|
|
241
|
+
toast.message('Added to the indexing queue', {
|
|
242
|
+
id: 'document-index-queued',
|
|
243
|
+
description: 'It will start automatically after the current indexing job.',
|
|
244
|
+
});
|
|
245
|
+
void mutateIndex();
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
if (!res.ok) {
|
|
249
|
+
toast.error(body.error || 'Your data was added, but indexing could not start.');
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
toast.success('Making your data searchable', {
|
|
253
|
+
description: 'This runs in the background. You can keep adding files.',
|
|
254
|
+
duration: 7_000,
|
|
255
|
+
});
|
|
256
|
+
pendingIndexRef.current = false;
|
|
257
|
+
void mutateIndex();
|
|
258
|
+
} catch {
|
|
259
|
+
toast.error('Your data was added, but indexing could not start.');
|
|
260
|
+
}
|
|
261
|
+
}, [indexQuery.data?.run, mutateIndex]);
|
|
262
|
+
|
|
263
|
+
const prevIndexRunning = useRef(indexRunning);
|
|
264
|
+
useEffect(() => {
|
|
265
|
+
if (prevIndexRunning.current && !indexRunning) {
|
|
266
|
+
void mutateDocuments();
|
|
267
|
+
// Compatibility with an older local server that still returns 409.
|
|
268
|
+
// Current servers own this queue durably and start the follow-up pass.
|
|
269
|
+
if (pendingIndexRef.current) {
|
|
270
|
+
pendingIndexRef.current = false;
|
|
271
|
+
void startAutomaticIndex();
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
prevIndexRunning.current = indexRunning;
|
|
275
|
+
}, [indexRunning, mutateDocuments, startAutomaticIndex]);
|
|
276
|
+
|
|
277
|
+
useEffect(() => {
|
|
278
|
+
const prevJobs = prevJobsRef.current;
|
|
279
|
+
if (prevJobs.length > 0 && jobs.length > 0) {
|
|
280
|
+
const justCompleted = jobs.filter(
|
|
281
|
+
(j) =>
|
|
282
|
+
j.status === 'completed' &&
|
|
283
|
+
prevJobs.some(
|
|
284
|
+
(pj) => pj.id === j.id && (pj.status === 'running' || pj.status === 'queued'),
|
|
285
|
+
),
|
|
286
|
+
);
|
|
287
|
+
|
|
288
|
+
if (justCompleted.length > 0) {
|
|
289
|
+
toast.success('Scraping completed. Making the new pages searchable…');
|
|
290
|
+
void mutateDocuments();
|
|
291
|
+
setTimeout(() => void mutateDocuments(), 2500);
|
|
292
|
+
void startAutomaticIndex();
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
prevJobsRef.current = jobs;
|
|
296
|
+
}, [jobs, mutateDocuments, startAutomaticIndex]);
|
|
297
|
+
|
|
298
|
+
const handleDataAdded = () => {
|
|
299
|
+
refreshAll();
|
|
300
|
+
void startAutomaticIndex();
|
|
301
|
+
};
|
|
302
|
+
|
|
303
|
+
const handleScrapeStarted = useCallback(
|
|
304
|
+
(job: CrawlJob) => {
|
|
305
|
+
void jobsQuery.mutate(
|
|
306
|
+
(current) => ({
|
|
307
|
+
jobs: [job, ...(current?.jobs ?? []).filter((existing) => existing.id !== job.id)],
|
|
308
|
+
configured: current?.configured ?? true,
|
|
309
|
+
}),
|
|
310
|
+
{ revalidate: true },
|
|
311
|
+
);
|
|
312
|
+
},
|
|
313
|
+
[jobsQuery],
|
|
314
|
+
);
|
|
315
|
+
|
|
316
|
+
const handleMediaIndexed = useCallback(() => {
|
|
317
|
+
void mutateDocuments();
|
|
318
|
+
void mutateIndex();
|
|
319
|
+
toast.success('Media indexed and added to your Knowledge Base.');
|
|
320
|
+
}, [mutateDocuments, mutateIndex]);
|
|
321
|
+
|
|
322
|
+
const handleMediaProcessingStarted = useCallback(() => {
|
|
323
|
+
void mediaQuery.mutate();
|
|
324
|
+
}, [mediaQuery]);
|
|
325
|
+
|
|
326
|
+
const activeSubTabIntro = SUB_TAB_INTRO[activeSubTab];
|
|
327
|
+
|
|
328
|
+
const selectGroup = (groupId: string | null) => {
|
|
329
|
+
const next = normalizeGroupId(groupId);
|
|
330
|
+
setSelectedGroupId(next);
|
|
331
|
+
|
|
332
|
+
const params = new URLSearchParams(searchParams.toString());
|
|
333
|
+
if (next !== 'default') params.set('groupId', next);
|
|
334
|
+
else params.delete('groupId');
|
|
335
|
+
window.history.replaceState(null, '', `${pathname}?${params.toString()}`);
|
|
336
|
+
};
|
|
337
|
+
|
|
338
|
+
return (
|
|
339
|
+
<div className="px-6 md:px-8">
|
|
340
|
+
{view === 'add' && (
|
|
341
|
+
<>
|
|
342
|
+
<WorkspacePageHeading
|
|
343
|
+
className="mb-2"
|
|
344
|
+
title={activeSubTabIntro.title}
|
|
345
|
+
description={activeSubTabIntro.description}
|
|
346
|
+
actions={
|
|
347
|
+
<>
|
|
348
|
+
{activeSubTab === 'website' && <WebCrawlerStatus />}
|
|
349
|
+
{hasJobsDrawerContent && (
|
|
350
|
+
<TooltipProvider delay={150}>
|
|
351
|
+
<Tooltip>
|
|
352
|
+
<TooltipTrigger
|
|
353
|
+
render={
|
|
354
|
+
<button
|
|
355
|
+
type="button"
|
|
356
|
+
onClick={() => setShowJobsDrawer(!showJobsDrawer)}
|
|
357
|
+
className={cn(
|
|
358
|
+
'relative cursor-pointer flex size-9 items-center justify-center rounded-lg border transition-colors',
|
|
359
|
+
hasActive
|
|
360
|
+
? 'border-green-600 bg-green-100/30 text-green-600 hover:bg-green-100/50'
|
|
361
|
+
: 'border-border bg-card text-muted-foreground hover:bg-muted/50 hover:text-foreground',
|
|
362
|
+
showJobsDrawer && 'bg-white hover:bg-white',
|
|
363
|
+
)}
|
|
364
|
+
aria-label="Toggle jobs panel"
|
|
365
|
+
>
|
|
366
|
+
<History className="size-4" />
|
|
367
|
+
{hasActive && (
|
|
368
|
+
<>
|
|
369
|
+
<span className="absolute -top-1 -right-1 z-10 flex h-3.5 min-w-3.5 items-center justify-center rounded-full bg-emerald-500 px-1 text-[9px] font-bold text-white shadow-sm ring-1 ring-white">
|
|
370
|
+
{activeJobCount}
|
|
371
|
+
</span>
|
|
372
|
+
<span className="absolute -top-1 -right-1 z-0 flex h-3.5 w-3.5 animate-ping rounded-full bg-emerald-400 opacity-75"></span>
|
|
373
|
+
</>
|
|
374
|
+
)}
|
|
375
|
+
</button>
|
|
376
|
+
}
|
|
377
|
+
/>
|
|
378
|
+
<TooltipContent>
|
|
379
|
+
<p>{hasActive ? 'Active jobs' : 'Job history'}</p>
|
|
380
|
+
</TooltipContent>
|
|
381
|
+
</Tooltip>
|
|
382
|
+
</TooltipProvider>
|
|
383
|
+
)}
|
|
384
|
+
</>
|
|
385
|
+
}
|
|
386
|
+
/>
|
|
387
|
+
<WorkspaceLineTabs
|
|
388
|
+
className="mb-4 mt-9"
|
|
389
|
+
items={SUB_TABS}
|
|
390
|
+
activeId={activeSubTab}
|
|
391
|
+
onChange={setActiveSubTab}
|
|
392
|
+
trailing={
|
|
393
|
+
<div className="flex items-center gap-2">
|
|
394
|
+
<Select value={targetGroupId} onValueChange={selectGroup}>
|
|
395
|
+
<SelectTrigger
|
|
396
|
+
aria-label="Data group"
|
|
397
|
+
className="h-9 min-w-42 max-w-56 bg-white text-xs"
|
|
398
|
+
>
|
|
399
|
+
<span className="flex flex-1 items-center gap-1.5 truncate text-left">
|
|
400
|
+
{!groupSelectionReady && docsQuery.data === undefined
|
|
401
|
+
? 'Loading group…'
|
|
402
|
+
: targetGroupId === 'default'
|
|
403
|
+
? 'Default group'
|
|
404
|
+
: selectedGroup
|
|
405
|
+
? `${selectedGroup.icon ? `${selectedGroup.icon} ` : ''}${selectedGroup.name}`
|
|
406
|
+
: 'Group unavailable'}
|
|
407
|
+
</span>
|
|
408
|
+
</SelectTrigger>
|
|
409
|
+
<SelectContent>
|
|
410
|
+
<div className="space-y-1 p-1">
|
|
411
|
+
{groups.map((group) => (
|
|
412
|
+
<SelectItem key={group.id} value={group.id} className="px-2 py-1.5 text-sm">
|
|
413
|
+
<span className="truncate">
|
|
414
|
+
{group.icon ? `${group.icon} ` : ''}
|
|
415
|
+
{group.name}
|
|
416
|
+
</span>
|
|
417
|
+
</SelectItem>
|
|
418
|
+
))}
|
|
419
|
+
</div>
|
|
420
|
+
</SelectContent>
|
|
421
|
+
</Select>
|
|
422
|
+
{primaryAction && (
|
|
423
|
+
<Button
|
|
424
|
+
size="default"
|
|
425
|
+
data-ready={
|
|
426
|
+
!dataAddBlocked &&
|
|
427
|
+
groupSelectionReady &&
|
|
428
|
+
!primaryAction.disabled &&
|
|
429
|
+
!primaryAction.loading
|
|
430
|
+
}
|
|
431
|
+
className="h-10 min-w-28 transition-colors"
|
|
432
|
+
onClick={primaryAction.onClick}
|
|
433
|
+
disabled={
|
|
434
|
+
dataAddBlocked ||
|
|
435
|
+
!groupSelectionReady ||
|
|
436
|
+
primaryAction.disabled ||
|
|
437
|
+
primaryAction.loading
|
|
438
|
+
}
|
|
439
|
+
>
|
|
440
|
+
{primaryAction.loading ? (
|
|
441
|
+
<Loader2 className="mr-1.5 size-3.5 animate-spin" />
|
|
442
|
+
) : (
|
|
443
|
+
<Plus className="mr-1.5 size-3.5" />
|
|
444
|
+
)}
|
|
445
|
+
{primaryAction.label}
|
|
446
|
+
</Button>
|
|
447
|
+
)}
|
|
448
|
+
</div>
|
|
449
|
+
}
|
|
450
|
+
/>
|
|
451
|
+
</>
|
|
452
|
+
)}
|
|
453
|
+
|
|
454
|
+
{showJobsDrawer && hasJobsDrawerContent && (
|
|
455
|
+
<div className="mb-6 animate-in slide-in-from-top-2 fade-in duration-200">
|
|
456
|
+
<div
|
|
457
|
+
className={cn(
|
|
458
|
+
'rounded-lg border border-border bg-card/70 p-4',
|
|
459
|
+
jobs?.length == 0 && 'bg-background',
|
|
460
|
+
)}
|
|
461
|
+
>
|
|
462
|
+
<div className="flex items-center justify-end mb-3">
|
|
463
|
+
<button
|
|
464
|
+
type="button"
|
|
465
|
+
onClick={() => setShowJobsDrawer(false)}
|
|
466
|
+
className="text-xs text-muted-foreground hover:text-foreground transition-colors"
|
|
467
|
+
>
|
|
468
|
+
Hide
|
|
469
|
+
</button>
|
|
470
|
+
</div>
|
|
471
|
+
<MediaIndexingJobsPanel assets={activeMediaAssets} />
|
|
472
|
+
{indexRunning && (
|
|
473
|
+
<div
|
|
474
|
+
className={cn(
|
|
475
|
+
'flex items-center gap-3 rounded-lg border border-border bg-background px-3 py-2.5',
|
|
476
|
+
activeMediaAssets.length > 0 && 'mt-3',
|
|
477
|
+
)}
|
|
478
|
+
>
|
|
479
|
+
<Loader2 className="size-4 shrink-0 animate-spin text-emerald-600" />
|
|
480
|
+
<div className="min-w-0">
|
|
481
|
+
<p className="text-xs font-medium">Indexing files</p>
|
|
482
|
+
<p className="text-[11px] text-muted-foreground">
|
|
483
|
+
Running in the background — new files will join the queue.
|
|
484
|
+
</p>
|
|
485
|
+
</div>
|
|
486
|
+
</div>
|
|
487
|
+
)}
|
|
488
|
+
{jobs.length > 0 && (
|
|
489
|
+
<div
|
|
490
|
+
className={cn(activeMediaAssets.length > 0 && 'mt-4 border-t border-border pt-4')}
|
|
491
|
+
>
|
|
492
|
+
<div className="mb-3 flex flex-wrap items-center gap-2">
|
|
493
|
+
{[
|
|
494
|
+
{ id: 'running', label: 'Running' },
|
|
495
|
+
{ id: 'all', label: 'All Jobs' },
|
|
496
|
+
].map((tab) => {
|
|
497
|
+
const isActive = jobsFilterTab === tab.id;
|
|
498
|
+
return (
|
|
499
|
+
<button
|
|
500
|
+
key={tab.id}
|
|
501
|
+
type="button"
|
|
502
|
+
onClick={() => setJobsFilterTab(tab.id as 'running' | 'all')}
|
|
503
|
+
className={cn(
|
|
504
|
+
'rounded-full px-3 py-1 text-xs font-medium transition-colors',
|
|
505
|
+
isActive
|
|
506
|
+
? 'bg-muted text-foreground'
|
|
507
|
+
: 'border border-border bg-transparent text-muted-foreground hover:bg-muted/50',
|
|
508
|
+
)}
|
|
509
|
+
>
|
|
510
|
+
{tab.label}
|
|
511
|
+
</button>
|
|
512
|
+
);
|
|
513
|
+
})}
|
|
514
|
+
</div>
|
|
515
|
+
<JobsPanel
|
|
516
|
+
jobs={
|
|
517
|
+
jobsFilterTab === 'running'
|
|
518
|
+
? jobs.filter((j) => j.status === 'running' || j.status === 'queued')
|
|
519
|
+
: jobs
|
|
520
|
+
}
|
|
521
|
+
onChanged={refreshAll}
|
|
522
|
+
/>
|
|
523
|
+
</div>
|
|
524
|
+
)}
|
|
525
|
+
</div>
|
|
526
|
+
</div>
|
|
527
|
+
)}
|
|
528
|
+
|
|
529
|
+
<div>
|
|
530
|
+
{activeTab === 'add' && (
|
|
531
|
+
<div className="w-full ">
|
|
532
|
+
<div className="relative">
|
|
533
|
+
{dataAddBlocked ? (
|
|
534
|
+
<div className="mx-auto flex min-h-72 max-w-xl mt-5 flex-col items-center justify-center rounded-xl px-6 text-center">
|
|
535
|
+
<div className="mb-4 rounded-full bg-primary/10 p-3 text-primary">
|
|
536
|
+
<KeyRound className="size-5" />
|
|
537
|
+
</div>
|
|
538
|
+
<h2 className="text-base font-semibold">Set an embedding API key first</h2>
|
|
539
|
+
<p className="mt-2 max-w-md text-sm text-muted-foreground">
|
|
540
|
+
Data is kept out of the Knowledge Base until it can be indexed. Configure an
|
|
541
|
+
embedding provider and API key, then return here to add data.
|
|
542
|
+
</p>
|
|
543
|
+
<Link
|
|
544
|
+
href="/settings?section=models"
|
|
545
|
+
className="mt-5 inline-flex h-9 items-center justify-center rounded-md bg-primary px-3 text-sm font-medium text-primary-foreground transition-colors hover:bg-primary/90"
|
|
546
|
+
>
|
|
547
|
+
Open AI model settings
|
|
548
|
+
</Link>
|
|
549
|
+
</div>
|
|
550
|
+
) : (
|
|
551
|
+
<>
|
|
552
|
+
{activeSubTab === 'website' && (
|
|
553
|
+
<div className="w-full flex flex-col gap-8 animate-in fade-in duration-200">
|
|
554
|
+
<div>
|
|
555
|
+
<ScrapePanel
|
|
556
|
+
onStarted={handleScrapeStarted}
|
|
557
|
+
onActionChange={registerPrimaryAction}
|
|
558
|
+
groupId={targetGroupId}
|
|
559
|
+
/>
|
|
560
|
+
</div>
|
|
561
|
+
</div>
|
|
562
|
+
)}
|
|
563
|
+
|
|
564
|
+
{activeSubTab === 'files' && (
|
|
565
|
+
<div className="animate-in fade-in duration-200">
|
|
566
|
+
<UploadPanel
|
|
567
|
+
onAdded={handleDataAdded}
|
|
568
|
+
onActionChange={registerPrimaryAction}
|
|
569
|
+
groupId={targetGroupId}
|
|
570
|
+
/>
|
|
571
|
+
</div>
|
|
572
|
+
)}
|
|
573
|
+
|
|
574
|
+
{activeSubTab === 'text' && (
|
|
575
|
+
<div className=" animate-in fade-in duration-200">
|
|
576
|
+
<PastePanel
|
|
577
|
+
onAdded={handleDataAdded}
|
|
578
|
+
onActionChange={registerPrimaryAction}
|
|
579
|
+
groupId={targetGroupId}
|
|
580
|
+
/>
|
|
581
|
+
</div>
|
|
582
|
+
)}
|
|
583
|
+
|
|
584
|
+
{activeSubTab === 'media' && (
|
|
585
|
+
<div className="animate-in fade-in duration-200">
|
|
586
|
+
<MediaPanel
|
|
587
|
+
onAdded={refreshAll}
|
|
588
|
+
onIndexed={handleMediaIndexed}
|
|
589
|
+
onProcessingStarted={handleMediaProcessingStarted}
|
|
590
|
+
onActionChange={registerPrimaryAction}
|
|
591
|
+
groupId={targetGroupId}
|
|
592
|
+
/>
|
|
593
|
+
</div>
|
|
594
|
+
)}
|
|
595
|
+
|
|
596
|
+
{activeSubTab === 'integrations' && (
|
|
597
|
+
<div className="animate-in fade-in duration-200">
|
|
598
|
+
<IntegrationsPanel onAdded={handleDataAdded} groupId={targetGroupId} />
|
|
599
|
+
</div>
|
|
600
|
+
)}
|
|
601
|
+
</>
|
|
602
|
+
)}
|
|
603
|
+
</div>
|
|
604
|
+
</div>
|
|
605
|
+
)}
|
|
606
|
+
|
|
607
|
+
{activeTab === 'corpus' && (
|
|
608
|
+
<div className="animate-in fade-in duration-300">
|
|
609
|
+
<CorpusPanel
|
|
610
|
+
documents={documents}
|
|
611
|
+
groups={groups}
|
|
612
|
+
onChanged={refreshAll}
|
|
613
|
+
isIndexing={indexRunning}
|
|
614
|
+
activeVideoRuntimeScope={activeVideoRuntimeScope}
|
|
615
|
+
initialGroupId={searchParams.has('groupId') ? queryGroupId : undefined}
|
|
616
|
+
isLoading={docsQuery.isLoading || (docsQuery.data === undefined && !docsQuery.error)}
|
|
617
|
+
/>
|
|
618
|
+
</div>
|
|
619
|
+
)}
|
|
620
|
+
</div>
|
|
621
|
+
</div>
|
|
622
|
+
);
|
|
623
|
+
}
|