larkup 0.1.36 → 0.1.38
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/.next/BUILD_ID +1 -1
- package/.next/build-manifest.json +3 -3
- package/.next/diagnostics/route-bundle-stats.json +12 -12
- package/.next/fallback-build-manifest.json +3 -3
- package/.next/required-server-files.js +1 -1
- package/.next/required-server-files.json +1 -1
- package/.next/server/app/_global-error.html +1 -1
- package/.next/server/app/_global-error.rsc +1 -1
- package/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/server/app/_not-found.html +1 -1
- package/.next/server/app/_not-found.rsc +18 -18
- package/.next/server/app/_not-found.segments/_full.segment.rsc +18 -18
- package/.next/server/app/_not-found.segments/_head.segment.rsc +4 -4
- package/.next/server/app/_not-found.segments/_index.segment.rsc +12 -12
- package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
- package/.next/server/app/_not-found.segments/_not-found.segment.rsc +3 -3
- package/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/analytics/page_client-reference-manifest.js +1 -1
- package/.next/server/app/analytics.html +1 -1
- package/.next/server/app/analytics.rsc +19 -19
- package/.next/server/app/analytics.segments/_full.segment.rsc +19 -19
- package/.next/server/app/analytics.segments/_head.segment.rsc +4 -4
- package/.next/server/app/analytics.segments/_index.segment.rsc +12 -12
- package/.next/server/app/analytics.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/analytics.segments/analytics/__PAGE__.segment.rsc +3 -3
- package/.next/server/app/analytics.segments/analytics.segment.rsc +3 -3
- package/.next/server/app/api/analytics/route.js.nft.json +1 -1
- package/.next/server/app/api/chat/route.js.nft.json +1 -1
- package/.next/server/app/api/chat/status/route.js.nft.json +1 -1
- package/.next/server/app/api/chat/suggestions/route.js.nft.json +1 -1
- package/.next/server/app/api/config/route.js.nft.json +1 -1
- package/.next/server/app/api/config/test/route.js.nft.json +1 -1
- package/.next/server/app/api/connections/route.js.nft.json +1 -1
- package/.next/server/app/api/connections/webhook/route.js.nft.json +1 -1
- package/.next/server/app/api/demo/route.js.nft.json +1 -1
- package/.next/server/app/api/deploy/cloud-project/route.js.nft.json +1 -1
- package/.next/server/app/api/deploy/ssh/route.js.nft.json +1 -1
- package/.next/server/app/api/deployment/blob-setup/route.js.nft.json +1 -1
- package/.next/server/app/api/deployment/config/route.js.nft.json +1 -1
- package/.next/server/app/api/describe-image/route.js.nft.json +1 -1
- package/.next/server/app/api/documents/route.js.nft.json +1 -1
- package/.next/server/app/api/firecrawl/local/route.js.nft.json +1 -1
- package/.next/server/app/api/index/route.js.nft.json +1 -1
- package/.next/server/app/api/jobs/[id]/route.js.nft.json +1 -1
- package/.next/server/app/api/jobs/route.js.nft.json +1 -1
- package/.next/server/app/api/media/[id]/route.js.nft.json +1 -1
- package/.next/server/app/api/media/process/route.js.nft.json +1 -1
- package/.next/server/app/api/media/route.js.nft.json +1 -1
- package/.next/server/app/api/media/stream/route.js.nft.json +1 -1
- package/.next/server/app/api/search/bing/route.js.nft.json +1 -1
- package/.next/server/app/api/search/brave/route.js.nft.json +1 -1
- package/.next/server/app/api/search/exa/route.js.nft.json +1 -1
- package/.next/server/app/api/search/google/route.js.nft.json +1 -1
- package/.next/server/app/api/search/route.js.nft.json +1 -1
- package/.next/server/app/api/search/tavily/route.js.nft.json +1 -1
- package/.next/server/app/api/server/agent/route.js.nft.json +1 -1
- package/.next/server/app/api/server/download/route.js.nft.json +1 -1
- package/.next/server/app/api/server/generate/route.js.nft.json +1 -1
- package/.next/server/app/api/server/local/route.js.nft.json +1 -1
- package/.next/server/app/api/servers/route.js.nft.json +1 -1
- package/.next/server/app/api/tabular/query/route.js.nft.json +1 -1
- package/.next/server/app/api/tabular/route.js.nft.json +1 -1
- package/.next/server/app/chat/page_client-reference-manifest.js +1 -1
- package/.next/server/app/chat.html +1 -1
- package/.next/server/app/chat.rsc +19 -19
- package/.next/server/app/chat.segments/_full.segment.rsc +19 -19
- package/.next/server/app/chat.segments/_head.segment.rsc +4 -4
- package/.next/server/app/chat.segments/_index.segment.rsc +12 -12
- package/.next/server/app/chat.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/chat.segments/chat/__PAGE__.segment.rsc +3 -3
- package/.next/server/app/chat.segments/chat.segment.rsc +3 -3
- package/.next/server/app/data/page_client-reference-manifest.js +1 -1
- package/.next/server/app/data.html +1 -1
- package/.next/server/app/data.rsc +19 -19
- package/.next/server/app/data.segments/_full.segment.rsc +19 -19
- package/.next/server/app/data.segments/_head.segment.rsc +4 -4
- package/.next/server/app/data.segments/_index.segment.rsc +12 -12
- package/.next/server/app/data.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/data.segments/data/__PAGE__.segment.rsc +3 -3
- package/.next/server/app/data.segments/data.segment.rsc +3 -3
- package/.next/server/app/index.html +1 -1
- package/.next/server/app/index.rsc +17 -17
- package/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/.next/server/app/index.segments/_full.segment.rsc +17 -17
- package/.next/server/app/index.segments/_head.segment.rsc +4 -4
- package/.next/server/app/index.segments/_index.segment.rsc +12 -12
- package/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/server/app/settings/page.js.nft.json +1 -1
- package/.next/server/app/settings/page_client-reference-manifest.js +1 -1
- package/.next/server/app/settings.html +1 -1
- package/.next/server/app/settings.rsc +19 -19
- package/.next/server/app/settings.segments/_full.segment.rsc +19 -19
- package/.next/server/app/settings.segments/_head.segment.rsc +4 -4
- package/.next/server/app/settings.segments/_index.segment.rsc +12 -12
- package/.next/server/app/settings.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/settings.segments/settings/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/settings.segments/settings.segment.rsc +3 -3
- package/.next/server/chunks/0598_next_dist_esm_build_templates_app-route_0kbcuk-.js +23 -24
- package/.next/server/chunks/0598_next_dist_esm_build_templates_app-route_0sbf4ny.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__1jc54o2._.js +1 -1
- package/.next/server/chunks/_1twj5f0._.js +3 -3
- package/.next/server/chunks/packages_marketplace_src_125_g2p._.js +1 -1
- package/.next/server/chunks/packages_scraper_src_0kkcv_v._.js +1 -1
- package/.next/server/chunks/ssr/_169pdlf._.js +1 -1
- package/.next/server/chunks/ssr/_18jagqc._.js +2 -2
- package/.next/server/chunks/ssr/_1hetwwu._.js +1 -1
- package/.next/server/chunks/ssr/_1yqlx1m._.js +1 -1
- package/.next/server/middleware-build-manifest.js +3 -3
- package/.next/server/pages/404.html +1 -1
- package/.next/server/pages/500.html +1 -1
- package/.next/standalone/apps/web/.next/BUILD_ID +1 -1
- package/.next/standalone/apps/web/.next/build-manifest.json +3 -3
- package/.next/standalone/apps/web/.next/required-server-files.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/_global-error.html +1 -1
- package/.next/standalone/apps/web/.next/server/app/_global-error.rsc +1 -1
- package/.next/standalone/apps/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/.next/standalone/apps/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/.next/standalone/apps/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/.next/standalone/apps/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/.next/standalone/apps/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/apps/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/standalone/apps/web/.next/server/app/_not-found.html +1 -1
- package/.next/standalone/apps/web/.next/server/app/_not-found.rsc +18 -18
- package/.next/standalone/apps/web/.next/server/app/_not-found.segments/_full.segment.rsc +18 -18
- package/.next/standalone/apps/web/.next/server/app/_not-found.segments/_head.segment.rsc +4 -4
- package/.next/standalone/apps/web/.next/server/app/_not-found.segments/_index.segment.rsc +12 -12
- package/.next/standalone/apps/web/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/apps/web/.next/server/app/_not-found.segments/_not-found.segment.rsc +3 -3
- package/.next/standalone/apps/web/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/apps/web/.next/server/app/analytics/page_client-reference-manifest.js +1 -1
- package/.next/standalone/apps/web/.next/server/app/analytics.html +1 -1
- package/.next/standalone/apps/web/.next/server/app/analytics.rsc +19 -19
- package/.next/standalone/apps/web/.next/server/app/analytics.segments/_full.segment.rsc +19 -19
- package/.next/standalone/apps/web/.next/server/app/analytics.segments/_head.segment.rsc +4 -4
- package/.next/standalone/apps/web/.next/server/app/analytics.segments/_index.segment.rsc +12 -12
- package/.next/standalone/apps/web/.next/server/app/analytics.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/apps/web/.next/server/app/analytics.segments/analytics/__PAGE__.segment.rsc +3 -3
- package/.next/standalone/apps/web/.next/server/app/analytics.segments/analytics.segment.rsc +3 -3
- package/.next/standalone/apps/web/.next/server/app/api/analytics/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/api/chat/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/api/chat/status/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/api/chat/suggestions/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/api/config/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/api/config/test/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/api/connections/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/api/connections/webhook/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/api/demo/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/api/deploy/cloud-project/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/api/deploy/ssh/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/api/deployment/blob-setup/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/api/deployment/config/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/api/describe-image/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/api/documents/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/api/firecrawl/local/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/api/index/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/api/jobs/[id]/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/api/jobs/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/api/media/[id]/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/api/media/process/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/api/media/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/api/media/stream/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/api/search/bing/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/api/search/brave/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/api/search/exa/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/api/search/google/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/api/search/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/api/search/tavily/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/api/server/agent/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/api/server/download/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/api/server/generate/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/api/server/local/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/api/servers/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/api/tabular/query/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/api/tabular/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/chat/page_client-reference-manifest.js +1 -1
- package/.next/standalone/apps/web/.next/server/app/chat.html +1 -1
- package/.next/standalone/apps/web/.next/server/app/chat.rsc +19 -19
- package/.next/standalone/apps/web/.next/server/app/chat.segments/_full.segment.rsc +19 -19
- package/.next/standalone/apps/web/.next/server/app/chat.segments/_head.segment.rsc +4 -4
- package/.next/standalone/apps/web/.next/server/app/chat.segments/_index.segment.rsc +12 -12
- package/.next/standalone/apps/web/.next/server/app/chat.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/apps/web/.next/server/app/chat.segments/chat/__PAGE__.segment.rsc +3 -3
- package/.next/standalone/apps/web/.next/server/app/chat.segments/chat.segment.rsc +3 -3
- package/.next/standalone/apps/web/.next/server/app/data/page_client-reference-manifest.js +1 -1
- package/.next/standalone/apps/web/.next/server/app/data.html +1 -1
- package/.next/standalone/apps/web/.next/server/app/data.rsc +19 -19
- package/.next/standalone/apps/web/.next/server/app/data.segments/_full.segment.rsc +19 -19
- package/.next/standalone/apps/web/.next/server/app/data.segments/_head.segment.rsc +4 -4
- package/.next/standalone/apps/web/.next/server/app/data.segments/_index.segment.rsc +12 -12
- package/.next/standalone/apps/web/.next/server/app/data.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/apps/web/.next/server/app/data.segments/data/__PAGE__.segment.rsc +3 -3
- package/.next/standalone/apps/web/.next/server/app/data.segments/data.segment.rsc +3 -3
- package/.next/standalone/apps/web/.next/server/app/index.html +1 -1
- package/.next/standalone/apps/web/.next/server/app/index.rsc +17 -17
- package/.next/standalone/apps/web/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/apps/web/.next/server/app/index.segments/_full.segment.rsc +17 -17
- package/.next/standalone/apps/web/.next/server/app/index.segments/_head.segment.rsc +4 -4
- package/.next/standalone/apps/web/.next/server/app/index.segments/_index.segment.rsc +12 -12
- package/.next/standalone/apps/web/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/apps/web/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/standalone/apps/web/.next/server/app/settings/page.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/settings/page_client-reference-manifest.js +1 -1
- package/.next/standalone/apps/web/.next/server/app/settings.html +1 -1
- package/.next/standalone/apps/web/.next/server/app/settings.rsc +19 -19
- package/.next/standalone/apps/web/.next/server/app/settings.segments/_full.segment.rsc +19 -19
- package/.next/standalone/apps/web/.next/server/app/settings.segments/_head.segment.rsc +4 -4
- package/.next/standalone/apps/web/.next/server/app/settings.segments/_index.segment.rsc +12 -12
- package/.next/standalone/apps/web/.next/server/app/settings.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/apps/web/.next/server/app/settings.segments/settings/__PAGE__.segment.rsc +4 -4
- package/.next/standalone/apps/web/.next/server/app/settings.segments/settings.segment.rsc +3 -3
- package/.next/standalone/apps/web/.next/server/chunks/0598_next_dist_esm_build_templates_app-route_0kbcuk-.js +23 -24
- package/.next/standalone/apps/web/.next/server/chunks/0598_next_dist_esm_build_templates_app-route_0sbf4ny.js +1 -1
- package/.next/standalone/apps/web/.next/server/chunks/[root-of-the-server]__1jc54o2._.js +1 -1
- package/.next/standalone/apps/web/.next/server/chunks/_1twj5f0._.js +3 -3
- package/.next/standalone/apps/web/.next/server/chunks/packages_marketplace_src_125_g2p._.js +1 -1
- package/.next/standalone/apps/web/.next/server/chunks/packages_scraper_src_0kkcv_v._.js +1 -1
- package/.next/standalone/apps/web/.next/server/chunks/ssr/_169pdlf._.js +1 -1
- package/.next/standalone/apps/web/.next/server/chunks/ssr/_18jagqc._.js +2 -2
- package/.next/standalone/apps/web/.next/server/chunks/ssr/_1hetwwu._.js +1 -1
- package/.next/standalone/apps/web/.next/server/chunks/ssr/_1yqlx1m._.js +1 -1
- package/.next/standalone/apps/web/.next/server/middleware-build-manifest.js +3 -3
- package/.next/standalone/apps/web/.next/server/pages/404.html +1 -1
- package/.next/standalone/apps/web/.next/server/pages/500.html +1 -1
- package/.next/standalone/apps/web/.next/static/chunks/{2-st4vd5971ry.js → 06u04tzgkz4_f.js} +1 -1
- package/.next/standalone/apps/web/.next/static/chunks/{3q4k1i384p4oi.js → 19k_g3af0cf7b.js} +1 -1
- package/.next/standalone/apps/web/.next/static/chunks/{3mp3jya53i-g-.js → 19krxv-ou9c8c.js} +6 -6
- package/.next/standalone/apps/web/.next/static/chunks/1_nk3imchwn8a.css +1 -0
- package/.next/standalone/apps/web/.next/static/chunks/{0qyuw19snetjl.js → 2ljwki2xxnblc.js} +2 -2
- package/.next/standalone/apps/web/CHANGELOG.md +17 -0
- package/.next/standalone/apps/web/app/api/chat/route.ts +62 -33
- package/.next/standalone/apps/web/app/api/media/process/route.ts +6 -0
- package/.next/standalone/apps/web/app/api/media/route.ts +3 -2
- package/.next/standalone/apps/web/app/api/media/stream/route.ts +19 -3
- package/.next/standalone/apps/web/app/settings/page.tsx +8 -17
- package/.next/standalone/apps/web/components/chat/chat-workspace.tsx +11 -4
- package/.next/standalone/apps/web/components/chat/message-item.tsx +18 -6
- package/.next/standalone/apps/web/components/chat/tools/knowledge-base-result.tsx +3 -4
- package/.next/standalone/apps/web/components/data/data-workspace.tsx +6 -2
- package/.next/standalone/apps/web/components/data/jobs-panel.tsx +22 -2
- package/.next/standalone/apps/web/components/data/media-panel.tsx +117 -91
- package/.next/standalone/apps/web/components/settings/marketplace-section.tsx +5 -0
- package/.next/standalone/apps/web/components/settings/prompts-section.tsx +13 -3
- package/.next/standalone/apps/web/package.json +1 -1
- package/.next/standalone/apps/web/server.js +1 -1
- package/.next/standalone/packages/tools/video-audio/CHANGELOG.md +6 -0
- package/.next/standalone/packages/tools/video-audio/dist/url-importer.js +34 -8
- package/.next/standalone/packages/tools/video-audio/package.json +1 -1
- package/.next/standalone/packages/tools/video-audio/src/url-importer.ts +56 -21
- package/.next/static/chunks/{2-st4vd5971ry.js → 06u04tzgkz4_f.js} +1 -1
- package/.next/static/chunks/{3q4k1i384p4oi.js → 19k_g3af0cf7b.js} +1 -1
- package/.next/static/chunks/{3mp3jya53i-g-.js → 19krxv-ou9c8c.js} +6 -6
- package/.next/static/chunks/1_nk3imchwn8a.css +1 -0
- package/.next/static/chunks/{0qyuw19snetjl.js → 2ljwki2xxnblc.js} +2 -2
- package/CHANGELOG.md +17 -0
- package/app/api/chat/route.ts +62 -33
- package/app/api/media/process/route.ts +6 -0
- package/app/api/media/route.ts +3 -2
- package/app/api/media/stream/route.ts +19 -3
- package/app/settings/page.tsx +8 -17
- package/components/chat/chat-workspace.tsx +11 -4
- package/components/chat/message-item.tsx +18 -6
- package/components/chat/tools/knowledge-base-result.tsx +3 -4
- package/components/data/data-workspace.tsx +6 -2
- package/components/data/jobs-panel.tsx +22 -2
- package/components/data/media-panel.tsx +117 -91
- package/components/settings/marketplace-section.tsx +5 -0
- package/components/settings/prompts-section.tsx +13 -3
- package/package.json +6 -6
- package/.next/standalone/apps/web/.next/static/chunks/0fa79dhcoeytz.css +0 -1
- package/.next/static/chunks/0fa79dhcoeytz.css +0 -1
- /package/.next/standalone/apps/web/.next/static/{ZV6fJc5ZoZ_a-UPNhgKZS → IOngxM7BWde96UQMAebFB}/_buildManifest.js +0 -0
- /package/.next/standalone/apps/web/.next/static/{ZV6fJc5ZoZ_a-UPNhgKZS → IOngxM7BWde96UQMAebFB}/_clientMiddlewareManifest.js +0 -0
- /package/.next/standalone/apps/web/.next/static/{ZV6fJc5ZoZ_a-UPNhgKZS → IOngxM7BWde96UQMAebFB}/_ssgManifest.js +0 -0
- /package/.next/static/{ZV6fJc5ZoZ_a-UPNhgKZS → IOngxM7BWde96UQMAebFB}/_buildManifest.js +0 -0
- /package/.next/static/{ZV6fJc5ZoZ_a-UPNhgKZS → IOngxM7BWde96UQMAebFB}/_clientMiddlewareManifest.js +0 -0
- /package/.next/static/{ZV6fJc5ZoZ_a-UPNhgKZS → IOngxM7BWde96UQMAebFB}/_ssgManifest.js +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# larkup
|
|
2
2
|
|
|
3
|
+
## 0.1.38
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Fix 10 production issues: SSE controller-closed error, cleaner system prompt, smarter KB search, one-shot web search, corpus refresh after scrape, minimal KB loading UI, settings sidebar navigation, force-delete processing media, playlist confirmation, image preview in chat, marketplace install progress toast.
|
|
8
|
+
|
|
9
|
+
## 0.1.37
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- c1b12cb: Restore reliable no-Docker local crawler search with a resilient public-search fallback, make current-event chat questions use enabled web search, speed up first-party tool installation, and improve media URL progress handling. Simplify settings and prompt UX, and make failed-crawl URL copying reliable.
|
|
14
|
+
- Updated dependencies [c1b12cb]
|
|
15
|
+
- @larkup/scraper@0.1.27
|
|
16
|
+
- @larkup/marketplace@0.1.10
|
|
17
|
+
- @larkup/tool-video-audio@0.2.3
|
|
18
|
+
- @larkup/tool-doc-editor@0.2.5
|
|
19
|
+
|
|
3
20
|
## 0.1.36
|
|
4
21
|
|
|
5
22
|
### Patch Changes
|
package/app/api/chat/route.ts
CHANGED
|
@@ -64,28 +64,24 @@ function createChatModel(
|
|
|
64
64
|
|
|
65
65
|
const SMART_RETRIEVAL_POLICY = `
|
|
66
66
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
-
|
|
78
|
-
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
- Search
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
-
|
|
85
|
-
- When search results contain images[].imageUrl (an image extracted from a PDF), use presentMedia with that exact imageUrl. When they contain a mediaAssetId, use presentMedia with the exact assetId. This is the ONLY way indexed images can appear in the conversation.
|
|
86
|
-
- For a follow-up such as "show me that part", "play the clip", "show the image", or "let me hear it", reuse the mediaAssetId and timestamps already present in the earlier search result and call presentMedia directly. Do not search again just to rediscover the same media.
|
|
87
|
-
- Use presentMedia to embed exactly one best video, image, or audio citation when the user asks to see/hear it or when one compact preview materially supports the answer. Do not present every search result.
|
|
88
|
-
- Keep the written answer minimal around a media citation. Do not print internal media reference markers.
|
|
67
|
+
TOOL RULES:
|
|
68
|
+
1. searchKnowledgeBase → Use FIRST when the question is about the user's indexed data (documents, files, images, videos, diagrams, anything they uploaded).
|
|
69
|
+
2. webSearch → Use ONLY after searchKnowledgeBase returned nothing relevant AND the question needs current/public facts.
|
|
70
|
+
3. Other tools → Use when the question specifically requires them.
|
|
71
|
+
4. General knowledge → Answer directly for common knowledge unrelated to the user's data.
|
|
72
|
+
5. If nothing helps, say so honestly.
|
|
73
|
+
|
|
74
|
+
DO:
|
|
75
|
+
- Keep answers short and direct. 1–3 sentences unless the task is complex.
|
|
76
|
+
- Search at most ONCE per tool per turn. Never repeat the same search.
|
|
77
|
+
- Use presentMedia to show images/videos/audio from indexed content.
|
|
78
|
+
- For follow-ups like "show me that", reuse the mediaAssetId from earlier results — do not search again.
|
|
79
|
+
|
|
80
|
+
DO NOT:
|
|
81
|
+
- Search for greetings, casual chat, writing help, or general knowledge you already know.
|
|
82
|
+
- Output markdown images like  — the UI blocks them. Always use presentMedia instead.
|
|
83
|
+
- Present every search result. Pick the single best one.
|
|
84
|
+
- Guess or fabricate when results are insufficient.
|
|
89
85
|
`;
|
|
90
86
|
|
|
91
87
|
function latestUserText(messages: UIMessage[]): string {
|
|
@@ -101,8 +97,29 @@ function latestUserText(messages: UIMessage[]): string {
|
|
|
101
97
|
return '';
|
|
102
98
|
}
|
|
103
99
|
|
|
100
|
+
/** Only force KB search when the user explicitly refers to their own data.
|
|
101
|
+
* Matches "my document", "our files", "the uploaded image" etc. but NOT
|
|
102
|
+
* generic uses like "I want to know", "can you tell me", "I think". */
|
|
104
103
|
function requiresKnowledgeBaseSearch(text: string): boolean {
|
|
105
|
-
|
|
104
|
+
// Skip generic conversational patterns
|
|
105
|
+
if (/^(hi|hello|hey|thanks|thank you|ok|sure|yes|no|please|help)\b/i.test(text.trim())) {
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
// Match possessive references to user data
|
|
109
|
+
return (
|
|
110
|
+
/\b(my|our)\s+(document|file|data|image|picture|diagram|video|audio|upload|corpus|knowledge|database|db|pdf|report|spreadsheet|presentation)/i.test(
|
|
111
|
+
text,
|
|
112
|
+
) ||
|
|
113
|
+
/\b(the|this|that)\s+(document|file|diagram|image|picture|upload|pdf|report)/i.test(text) ||
|
|
114
|
+
/\b(uploaded?|indexed|scraped|knowledge base|corpus)\b/i.test(text) ||
|
|
115
|
+
/\bshow\s+me\b/i.test(text)
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/** Questions whose answer is inherently time-sensitive should not rely on the
|
|
120
|
+
* model's training snapshot when Web Search is available. */
|
|
121
|
+
function requiresCurrentWebSearch(text: string): boolean {
|
|
122
|
+
return /\b(who won|winner|final score|match result|latest|current|today|yesterday|breaking news|weather|stock price|exchange rate|election result|schedule)\b/i.test(
|
|
106
123
|
text,
|
|
107
124
|
);
|
|
108
125
|
}
|
|
@@ -364,10 +381,13 @@ ${fieldLines}`;
|
|
|
364
381
|
}
|
|
365
382
|
|
|
366
383
|
const systemPrompt =
|
|
367
|
-
|
|
384
|
+
DEFAULT_SYSTEM_PROMPT +
|
|
385
|
+
(config.systemPrompt && config.systemPrompt !== DEFAULT_SYSTEM_PROMPT
|
|
386
|
+
? `\n\nUSER INSTRUCTIONS:\n${config.systemPrompt}`
|
|
387
|
+
: '') +
|
|
368
388
|
SMART_RETRIEVAL_POLICY +
|
|
369
389
|
(config.webSearchEnabled
|
|
370
|
-
? '\
|
|
390
|
+
? '\nWeb search is available. Use it for current events or public facts not in the knowledge base.\n'
|
|
371
391
|
: '') +
|
|
372
392
|
tabularContext +
|
|
373
393
|
docContext;
|
|
@@ -375,6 +395,10 @@ ${fieldLines}`;
|
|
|
375
395
|
const forceKnowledgeBaseSearch =
|
|
376
396
|
requiresKnowledgeBaseSearch(latestUserText(messagesToProcess)) &&
|
|
377
397
|
Boolean(tools.searchKnowledgeBase);
|
|
398
|
+
const forceWebSearch =
|
|
399
|
+
config.webSearchEnabled === true &&
|
|
400
|
+
requiresCurrentWebSearch(latestUserText(messagesToProcess)) &&
|
|
401
|
+
Boolean(tools.webSearch);
|
|
378
402
|
|
|
379
403
|
// Debug: log payload sizes to console in development
|
|
380
404
|
if (process.env.NODE_ENV === 'development') {
|
|
@@ -386,19 +410,24 @@ ${fieldLines}`;
|
|
|
386
410
|
system: systemPrompt,
|
|
387
411
|
messages: await convertToModelMessages(safeMessages, { tools }),
|
|
388
412
|
maxOutputTokens: 4096,
|
|
389
|
-
//
|
|
390
|
-
|
|
391
|
-
// burn the context window and end with no response.
|
|
392
|
-
stopWhen: stepCountIs(5),
|
|
413
|
+
// Three steps: retrieve → optionally present media → answer.
|
|
414
|
+
stopWhen: stepCountIs(3),
|
|
393
415
|
toolChoice: 'auto',
|
|
394
416
|
prepareStep: ({ stepNumber }) => {
|
|
417
|
+
// Step 0: force KB search if needed
|
|
395
418
|
if (forceKnowledgeBaseSearch && stepNumber === 0) {
|
|
396
419
|
return { toolChoice: { type: 'tool', toolName: 'searchKnowledgeBase' } };
|
|
397
420
|
}
|
|
398
|
-
//
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
421
|
+
// Step 1 (or 0 if no KB): force web search if needed
|
|
422
|
+
if (forceWebSearch && (!forceKnowledgeBaseSearch || stepNumber === 1)) {
|
|
423
|
+
return { toolChoice: { type: 'tool', toolName: 'webSearch' } };
|
|
424
|
+
}
|
|
425
|
+
// After forced tools, remove them so the model cannot loop on them.
|
|
426
|
+
const usedTools: string[] = [];
|
|
427
|
+
if (forceKnowledgeBaseSearch) usedTools.push('searchKnowledgeBase');
|
|
428
|
+
if (forceWebSearch) usedTools.push('webSearch');
|
|
429
|
+
if (usedTools.length > 0) {
|
|
430
|
+
return { activeTools: Object.keys(tools).filter((name) => !usedTools.includes(name)) };
|
|
402
431
|
}
|
|
403
432
|
return undefined;
|
|
404
433
|
},
|
|
@@ -165,6 +165,12 @@ async function enqueueMediaProcessing(
|
|
|
165
165
|
const entries = await tool.importMediaUrl(currentAsset.originalUrl, {
|
|
166
166
|
outputDir: tmpDir,
|
|
167
167
|
playlistMax: 10, // max items
|
|
168
|
+
onProgress: ({ percent, message }: { percent?: number; message: string }) =>
|
|
169
|
+
reportStage('download', {
|
|
170
|
+
status: 'running',
|
|
171
|
+
percent,
|
|
172
|
+
message,
|
|
173
|
+
}),
|
|
168
174
|
});
|
|
169
175
|
|
|
170
176
|
if (!entries || entries.length === 0) {
|
package/app/api/media/route.ts
CHANGED
|
@@ -177,6 +177,7 @@ async function removeMedia(req: Request) {
|
|
|
177
177
|
const url = new URL(req.url);
|
|
178
178
|
const id = url.searchParams.get('id');
|
|
179
179
|
const ids = url.searchParams.get('ids');
|
|
180
|
+
const force = url.searchParams.get('force') === 'true';
|
|
180
181
|
|
|
181
182
|
const storage = createStorageProvider();
|
|
182
183
|
|
|
@@ -184,7 +185,7 @@ async function removeMedia(req: Request) {
|
|
|
184
185
|
const { getMediaAsset } = await import('@larkup/core/media-store');
|
|
185
186
|
const asset = await getMediaAsset(id);
|
|
186
187
|
if (asset) {
|
|
187
|
-
if (isMediaProcessing(asset)) {
|
|
188
|
+
if (!force && isMediaProcessing(asset)) {
|
|
188
189
|
return NextResponse.json(
|
|
189
190
|
{ error: 'Wait for the media indexing job to finish before deleting it.' },
|
|
190
191
|
{ status: 409 },
|
|
@@ -201,7 +202,7 @@ async function removeMedia(req: Request) {
|
|
|
201
202
|
const idList = ids.split(',');
|
|
202
203
|
const assets = await readMediaAssets();
|
|
203
204
|
const selectedAssets = assets.filter((asset) => idList.includes(asset.id));
|
|
204
|
-
if (selectedAssets.some(isMediaProcessing)) {
|
|
205
|
+
if (!force && selectedAssets.some(isMediaProcessing)) {
|
|
205
206
|
return NextResponse.json(
|
|
206
207
|
{ error: 'Wait for all selected media indexing jobs to finish before deleting them.' },
|
|
207
208
|
{ status: 409 },
|
|
@@ -50,14 +50,29 @@ export async function GET(req: Request) {
|
|
|
50
50
|
|
|
51
51
|
let interval: ReturnType<typeof setInterval> | undefined;
|
|
52
52
|
let keepAlive: ReturnType<typeof setInterval> | undefined;
|
|
53
|
+
let closed = false;
|
|
54
|
+
|
|
53
55
|
const stream = new ReadableStream<Uint8Array>({
|
|
54
56
|
async start(controller) {
|
|
55
57
|
let lastPayload = '';
|
|
56
58
|
let checking = false;
|
|
57
59
|
let storageSnapshot = { usedBytes: 0, fileCount: 0 };
|
|
58
60
|
let storageCheckedAt = 0;
|
|
61
|
+
|
|
62
|
+
const safeEnqueue = (data: Uint8Array) => {
|
|
63
|
+
if (closed) return;
|
|
64
|
+
try {
|
|
65
|
+
controller.enqueue(data);
|
|
66
|
+
} catch {
|
|
67
|
+
// Controller already closed — client disconnected.
|
|
68
|
+
closed = true;
|
|
69
|
+
if (interval) clearInterval(interval);
|
|
70
|
+
if (keepAlive) clearInterval(keepAlive);
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
|
|
59
74
|
const publish = async () => {
|
|
60
|
-
if (checking) return;
|
|
75
|
+
if (checking || closed) return;
|
|
61
76
|
checking = true;
|
|
62
77
|
try {
|
|
63
78
|
if (Date.now() - storageCheckedAt > 30_000) {
|
|
@@ -81,7 +96,7 @@ export async function GET(req: Request) {
|
|
|
81
96
|
0,
|
|
82
97
|
...nextSnapshot.assets.map((asset) => asset.processingRevision ?? 0),
|
|
83
98
|
);
|
|
84
|
-
|
|
99
|
+
safeEnqueue(
|
|
85
100
|
encoder.encode(`id: ${revision}\nevent: media-update\ndata: ${payload}\n\n`),
|
|
86
101
|
);
|
|
87
102
|
}
|
|
@@ -94,9 +109,10 @@ export async function GET(req: Request) {
|
|
|
94
109
|
|
|
95
110
|
await publish();
|
|
96
111
|
interval = setInterval(() => void publish(), 1_000);
|
|
97
|
-
keepAlive = setInterval(() =>
|
|
112
|
+
keepAlive = setInterval(() => safeEnqueue(encoder.encode(': keep-alive\n\n')), 15_000);
|
|
98
113
|
},
|
|
99
114
|
cancel() {
|
|
115
|
+
closed = true;
|
|
100
116
|
if (interval) clearInterval(interval);
|
|
101
117
|
if (keepAlive) clearInterval(keepAlive);
|
|
102
118
|
},
|
package/app/settings/page.tsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { useEffect, Suspense } from 'react';
|
|
4
4
|
import { useSearchParams, useRouter, usePathname } from 'next/navigation';
|
|
5
5
|
import { SettingsLayout, type SettingsSection } from '@/components/settings/settings-layout';
|
|
6
6
|
import { GeneralSection } from '@/components/settings/general-section';
|
|
@@ -20,38 +20,29 @@ function SettingsContent() {
|
|
|
20
20
|
const router = useRouter();
|
|
21
21
|
const pathname = usePathname();
|
|
22
22
|
|
|
23
|
-
const
|
|
23
|
+
const resolveSection = (): SettingsSection => {
|
|
24
24
|
if (searchParams.has('ai-models')) return 'models';
|
|
25
25
|
const section = searchParams.get('section') as SettingsSection;
|
|
26
26
|
if (section) return section;
|
|
27
27
|
return 'general';
|
|
28
28
|
};
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
// Always derive the active section from the URL — this ensures navigating
|
|
31
|
+
// away and back never leaves the sidebar stuck on a stale section.
|
|
32
|
+
const activeSection = resolveSection();
|
|
31
33
|
|
|
32
34
|
useEffect(() => {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
if (hasAiModels) {
|
|
35
|
+
// Normalize legacy `?ai-models` param to `?section=models`
|
|
36
|
+
if (searchParams.has('ai-models')) {
|
|
37
37
|
const params = new URLSearchParams(searchParams.toString());
|
|
38
38
|
params.delete('ai-models');
|
|
39
39
|
params.set('section', 'models');
|
|
40
40
|
router.replace(`${pathname}?${params.toString()}`);
|
|
41
|
-
if (activeSection !== 'models') {
|
|
42
|
-
setActiveSection('models');
|
|
43
|
-
}
|
|
44
|
-
} else if (currentSection && currentSection !== activeSection) {
|
|
45
|
-
setActiveSection(currentSection as SettingsSection);
|
|
46
41
|
}
|
|
47
42
|
}, [searchParams, pathname, router]);
|
|
48
43
|
|
|
49
44
|
const handleSectionChange = (newSection: SettingsSection) => {
|
|
50
|
-
|
|
51
|
-
const params = new URLSearchParams(searchParams.toString());
|
|
52
|
-
params.delete('ai-models');
|
|
53
|
-
params.set('section', newSection);
|
|
54
|
-
router.replace(`${pathname}?${params.toString()}`);
|
|
45
|
+
router.replace(`${pathname}?section=${newSection}`, { scroll: false });
|
|
55
46
|
};
|
|
56
47
|
|
|
57
48
|
return (
|
|
@@ -530,12 +530,19 @@ function ChatWorkspaceInner() {
|
|
|
530
530
|
const config = configData?.config;
|
|
531
531
|
if (!config) return;
|
|
532
532
|
|
|
533
|
-
const
|
|
534
|
-
const
|
|
533
|
+
const provider = config.webSearchProvider || 'tavily';
|
|
534
|
+
const apiKeys: Record<string, string | undefined> = {
|
|
535
|
+
tavily: config.tavilyApiKey,
|
|
536
|
+
serper: config.serperApiKey,
|
|
537
|
+
google: config.serperApiKey,
|
|
538
|
+
brave: config.braveApiKey,
|
|
539
|
+
bing: config.bingApiKey,
|
|
540
|
+
exa: config.exaApiKey,
|
|
541
|
+
};
|
|
535
542
|
|
|
536
|
-
if (
|
|
543
|
+
if (provider !== 'local' && !apiKeys[provider]) {
|
|
537
544
|
toast.error('Web Search API key is missing. Please configure it in Settings.');
|
|
538
|
-
router.push('/settings');
|
|
545
|
+
router.push('/settings?section=general');
|
|
539
546
|
return;
|
|
540
547
|
}
|
|
541
548
|
|
|
@@ -382,7 +382,7 @@ function renderToolPart(
|
|
|
382
382
|
<div key={index} className="mb-2 w-full">
|
|
383
383
|
<div className="inline-flex items-center gap-2 px-2 py-1.5 text-xs text-muted-foreground bg-muted/30 rounded-md border border-border/50">
|
|
384
384
|
<Globe className="h-3.5 w-3.5 shrink-0" />
|
|
385
|
-
<span className="truncate max-w-
|
|
385
|
+
<span className="truncate max-w-62.5 sm:max-w-100">
|
|
386
386
|
Searched web for "{input?.query}"
|
|
387
387
|
</span>
|
|
388
388
|
<span className="shrink-0 text-[10px] bg-secondary text-foreground px-1.5 py-0.5 rounded-full font-medium ml-1">
|
|
@@ -395,12 +395,24 @@ function renderToolPart(
|
|
|
395
395
|
|
|
396
396
|
case 'analyzeImageDeeply': {
|
|
397
397
|
if (output.error) return null;
|
|
398
|
+
const imageUrl = input?.imageUrl as string | undefined;
|
|
398
399
|
return (
|
|
399
400
|
<div key={index} className="mb-2 w-full">
|
|
400
401
|
<div className="inline-flex items-center gap-2 px-2 py-1.5 text-xs text-muted-foreground bg-muted/30 rounded-md border border-border/50">
|
|
401
402
|
<Sparkles className="h-3.5 w-3.5 shrink-0" />
|
|
402
|
-
<span className="truncate max-w-
|
|
403
|
+
<span className="truncate max-w-62.5 sm:max-w-100">Analyzed image</span>
|
|
403
404
|
</div>
|
|
405
|
+
{imageUrl ? (
|
|
406
|
+
<div className="mt-1.5 max-w-xs">
|
|
407
|
+
{/* eslint-disable-next-line @next/next/no-img-element */}
|
|
408
|
+
<img
|
|
409
|
+
src={imageUrl}
|
|
410
|
+
alt="Analyzed image"
|
|
411
|
+
className="rounded-lg border border-border/50 object-cover max-h-48 w-auto"
|
|
412
|
+
loading="lazy"
|
|
413
|
+
/>
|
|
414
|
+
</div>
|
|
415
|
+
) : null}
|
|
404
416
|
</div>
|
|
405
417
|
);
|
|
406
418
|
}
|
|
@@ -433,7 +445,7 @@ function renderToolPart(
|
|
|
433
445
|
<div key={index} className="mb-2 w-full">
|
|
434
446
|
<div className="inline-flex items-center gap-2 px-2 py-1.5 text-xs text-muted-foreground bg-muted/30 rounded-md border border-border/50">
|
|
435
447
|
<CheckCircle2 className="h-3.5 w-3.5 shrink-0" />
|
|
436
|
-
<span className="truncate max-w-
|
|
448
|
+
<span className="truncate max-w-62.5 sm:max-w-100">Used {toolName}</span>
|
|
437
449
|
</div>
|
|
438
450
|
</div>
|
|
439
451
|
);
|
|
@@ -714,7 +726,7 @@ export function MessageItem({
|
|
|
714
726
|
<div className="size-7 shrink-0 rounded-md overflow-hidden bg-background border border-border/90 flex items-center justify-center p-1">
|
|
715
727
|
<img src={iconPath} alt={nameStr} className="w-full h-full object-contain" />
|
|
716
728
|
</div>
|
|
717
|
-
<div className="flex flex-col justify-center max-w-
|
|
729
|
+
<div className="flex flex-col justify-center max-w-37.5">
|
|
718
730
|
<span className="text-xs font-medium truncate text-foreground">
|
|
719
731
|
{nameStr}
|
|
720
732
|
</span>
|
|
@@ -932,10 +944,10 @@ function renderMarkdown(text: string): string {
|
|
|
932
944
|
html = html.replace(/\[([^\]]+)\]\(([^)]+)\)/g, (match, label, url) => {
|
|
933
945
|
const lowerUrl = url.toLowerCase();
|
|
934
946
|
if (lowerUrl.match(/\.(mp4|webm|ogg)$/) || lowerUrl.includes('video')) {
|
|
935
|
-
return `<video src="${url}" controls preload="metadata" class="max-w-
|
|
947
|
+
return `<video src="${url}" controls preload="metadata" class="max-w-90 w-full rounded-lg my-2 border border-border bg-card"></video>`;
|
|
936
948
|
}
|
|
937
949
|
if (lowerUrl.match(/\.(mp3|wav|m4a|oga)$/) || lowerUrl.includes('audio')) {
|
|
938
|
-
return `<audio src="${url}" controls preload="metadata" class="max-w-
|
|
950
|
+
return `<audio src="${url}" controls preload="metadata" class="max-w-80 w-full my-2"></audio>`;
|
|
939
951
|
}
|
|
940
952
|
return `<a href="${url}" target="_blank" rel="noreferrer" class="msg-link">${label}</a>`;
|
|
941
953
|
});
|
|
@@ -73,7 +73,7 @@ export function KnowledgeBaseResult({
|
|
|
73
73
|
) : (
|
|
74
74
|
<Database className="h-3.5 w-3.5 shrink-0" />
|
|
75
75
|
)}
|
|
76
|
-
<span className="truncate max-w-
|
|
76
|
+
<span className="truncate max-w-62.5 sm:max-w-100">
|
|
77
77
|
{isRunning ? 'Checking knowledge base…' : 'Checked knowledge base'}
|
|
78
78
|
</span>
|
|
79
79
|
{!isRunning && hits.length > 0 ? (
|
|
@@ -92,9 +92,8 @@ export function KnowledgeBaseResult({
|
|
|
92
92
|
{open && (isRunning || hits.length > 0) ? (
|
|
93
93
|
<div className="mt-2 flex flex-col gap-px border border-border rounded-xl bg-transparent overflow-hidden">
|
|
94
94
|
{isRunning && hits.length === 0 ? (
|
|
95
|
-
<div className="flex items-center gap-2 px-3.5 py-
|
|
96
|
-
<Loader2 className="size-3
|
|
97
|
-
Looking through your Knowledge Base…
|
|
95
|
+
<div className="flex items-center gap-2 px-3.5 py-2.5">
|
|
96
|
+
<Loader2 className="size-3 animate-spin text-muted-foreground" />
|
|
98
97
|
</div>
|
|
99
98
|
) : null}
|
|
100
99
|
{hits.slice(0, 3).map((h, i) => (
|
|
@@ -172,11 +172,15 @@ export function DataWorkspace() {
|
|
|
172
172
|
);
|
|
173
173
|
|
|
174
174
|
if (justCompleted.length > 0) {
|
|
175
|
-
toast.success('
|
|
175
|
+
toast.success('Scraping completed.');
|
|
176
|
+
// Refresh the corpus immediately so new documents appear.
|
|
177
|
+
mutateDocuments();
|
|
178
|
+
// Documents may still be flushing — re-fetch after a short delay.
|
|
179
|
+
setTimeout(() => mutateDocuments(), 2500);
|
|
176
180
|
}
|
|
177
181
|
}
|
|
178
182
|
prevJobsRef.current = jobs;
|
|
179
|
-
}, [jobs]);
|
|
183
|
+
}, [jobs, mutateDocuments]);
|
|
180
184
|
|
|
181
185
|
const docsQuery = useSWR<DocsResponse>('/api/documents', fetcher, {
|
|
182
186
|
refreshInterval: hasActive ? 5000 : 0,
|
|
@@ -119,6 +119,27 @@ export function JobsPanel({ jobs, onChanged }: { jobs: CrawlJob[]; onChanged: ()
|
|
|
119
119
|
setSelected(next);
|
|
120
120
|
}
|
|
121
121
|
|
|
122
|
+
async function copyFailedUrls(urls: string) {
|
|
123
|
+
try {
|
|
124
|
+
if (navigator.clipboard?.writeText) {
|
|
125
|
+
await navigator.clipboard.writeText(urls);
|
|
126
|
+
} else {
|
|
127
|
+
const textarea = document.createElement('textarea');
|
|
128
|
+
textarea.value = urls;
|
|
129
|
+
textarea.style.position = 'fixed';
|
|
130
|
+
textarea.style.opacity = '0';
|
|
131
|
+
document.body.appendChild(textarea);
|
|
132
|
+
textarea.select();
|
|
133
|
+
const copied = document.execCommand('copy');
|
|
134
|
+
textarea.remove();
|
|
135
|
+
if (!copied) throw new Error('The browser denied clipboard access.');
|
|
136
|
+
}
|
|
137
|
+
toast.success('Copied failed URLs to clipboard');
|
|
138
|
+
} catch {
|
|
139
|
+
toast.error('Could not copy URLs. Select them manually and try again.');
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
122
143
|
async function executeCancel(id: string) {
|
|
123
144
|
setCancelling(true);
|
|
124
145
|
try {
|
|
@@ -316,8 +337,7 @@ export function JobsPanel({ jobs, onChanged }: { jobs: CrawlJob[]; onChanged: ()
|
|
|
316
337
|
.filter((t) => t.status === 'failed')
|
|
317
338
|
.map((t) => t.url)
|
|
318
339
|
.join('\n');
|
|
319
|
-
|
|
320
|
-
toast.success('Copied failed URLs to clipboard');
|
|
340
|
+
void copyFailedUrls(failedUrls);
|
|
321
341
|
}}
|
|
322
342
|
className="rounded p-1 text-muted-foreground hover:text-foreground transition-colors"
|
|
323
343
|
title="Copy failed URLs"
|