larkup 0.1.14 → 0.1.21
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 -0
- package/.next/app-path-routes-manifest.json +69 -0
- package/.next/build/chunks/[root-of-the-server]__0cstldc._.js +206 -0
- package/.next/build/chunks/[root-of-the-server]__0s3ts0r._.js +500 -0
- package/.next/build/chunks/[turbopack-node]_transforms_postcss_ts_0xqnjlz._.js +13 -0
- package/.next/build/chunks/[turbopack]_runtime.js +890 -0
- package/.next/build/chunks/node_modules__pnpm_04zrf.1._.js +7126 -0
- package/.next/build/package.json +1 -0
- package/.next/build/postcss.js +6 -0
- package/.next/build-manifest.json +22 -0
- package/.next/diagnostics/build-diagnostics.json +6 -0
- package/.next/diagnostics/framework.json +1 -0
- package/.next/diagnostics/route-bundle-stats.json +133 -0
- package/.next/export-marker.json +6 -0
- package/.next/fallback-build-manifest.json +13 -0
- package/.next/images-manifest.json +68 -0
- package/.next/next-minimal-server.js.nft.json +1 -0
- package/.next/next-server.js.nft.json +1 -0
- package/.next/package.json +1 -0
- package/.next/prerender-manifest.json +210 -0
- package/.next/required-server-files.js +356 -0
- package/.next/required-server-files.json +356 -0
- package/.next/routes-manifest.json +462 -0
- package/.next/server/app/_global-error/page/app-paths-manifest.json +3 -0
- package/.next/server/app/_global-error/page/build-manifest.json +18 -0
- package/.next/server/app/_global-error/page/next-font-manifest.json +6 -0
- package/.next/server/app/_global-error/page/react-loadable-manifest.json +1 -0
- package/.next/server/app/_global-error/page/server-reference-manifest.json +4 -0
- package/.next/server/app/_global-error/page.js +10 -0
- package/.next/server/app/_global-error/page.js.nft.json +1 -0
- package/.next/server/app/_global-error/page_client-reference-manifest.js +3 -0
- package/.next/server/app/_global-error.html +1 -0
- package/.next/server/app/_global-error.meta +15 -0
- package/.next/server/app/_global-error.rsc +15 -0
- package/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +5 -0
- package/.next/server/app/_global-error.segments/_full.segment.rsc +15 -0
- package/.next/server/app/_global-error.segments/_head.segment.rsc +6 -0
- package/.next/server/app/_global-error.segments/_index.segment.rsc +5 -0
- package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -0
- package/.next/server/app/_not-found/page/app-paths-manifest.json +3 -0
- package/.next/server/app/_not-found/page/build-manifest.json +18 -0
- package/.next/server/app/_not-found/page/next-font-manifest.json +11 -0
- package/.next/server/app/_not-found/page/react-loadable-manifest.json +1 -0
- package/.next/server/app/_not-found/page/server-reference-manifest.json +4 -0
- package/.next/server/app/_not-found/page.js +14 -0
- package/.next/server/app/_not-found/page.js.nft.json +1 -0
- package/.next/server/app/_not-found/page_client-reference-manifest.js +3 -0
- package/.next/server/app/_not-found.html +1 -0
- package/.next/server/app/_not-found.meta +16 -0
- package/.next/server/app/_not-found.rsc +28 -0
- package/.next/server/app/_not-found.segments/_full.segment.rsc +28 -0
- package/.next/server/app/_not-found.segments/_head.segment.rsc +6 -0
- package/.next/server/app/_not-found.segments/_index.segment.rsc +14 -0
- package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +5 -0
- package/.next/server/app/_not-found.segments/_not-found.segment.rsc +5 -0
- package/.next/server/app/_not-found.segments/_tree.segment.rsc +3 -0
- package/.next/server/app/analytics/page/app-paths-manifest.json +3 -0
- package/.next/server/app/analytics/page/build-manifest.json +18 -0
- package/.next/server/app/analytics/page/next-font-manifest.json +11 -0
- package/.next/server/app/analytics/page/react-loadable-manifest.json +1 -0
- package/.next/server/app/analytics/page/server-reference-manifest.json +4 -0
- package/.next/server/app/analytics/page.js +15 -0
- package/.next/server/app/analytics/page.js.nft.json +1 -0
- package/.next/server/app/analytics/page_client-reference-manifest.js +3 -0
- package/.next/server/app/analytics.html +1 -0
- package/.next/server/app/analytics.meta +15 -0
- package/.next/server/app/analytics.rsc +32 -0
- package/.next/server/app/analytics.segments/_full.segment.rsc +32 -0
- package/.next/server/app/analytics.segments/_head.segment.rsc +6 -0
- package/.next/server/app/analytics.segments/_index.segment.rsc +14 -0
- package/.next/server/app/analytics.segments/_tree.segment.rsc +5 -0
- package/.next/server/app/analytics.segments/analytics/__PAGE__.segment.rsc +6 -0
- package/.next/server/app/analytics.segments/analytics.segment.rsc +5 -0
- package/.next/server/app/api/analytics/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/analytics/route/build-manifest.json +9 -0
- package/.next/server/app/api/analytics/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/analytics/route.js +9 -0
- package/.next/server/app/api/analytics/route.js.nft.json +1 -0
- package/.next/server/app/api/analytics/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/chat/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/chat/route/build-manifest.json +9 -0
- package/.next/server/app/api/chat/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/chat/route.js +24 -0
- package/.next/server/app/api/chat/route.js.nft.json +1 -0
- package/.next/server/app/api/chat/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/chat/status/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/chat/status/route/build-manifest.json +9 -0
- package/.next/server/app/api/chat/status/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/chat/status/route.js +9 -0
- package/.next/server/app/api/chat/status/route.js.nft.json +1 -0
- package/.next/server/app/api/chat/status/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/chat/suggestions/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/chat/suggestions/route/build-manifest.json +9 -0
- package/.next/server/app/api/chat/suggestions/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/chat/suggestions/route.js +17 -0
- package/.next/server/app/api/chat/suggestions/route.js.nft.json +1 -0
- package/.next/server/app/api/chat/suggestions/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/config/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/config/route/build-manifest.json +9 -0
- package/.next/server/app/api/config/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/config/route.js +8 -0
- package/.next/server/app/api/config/route.js.nft.json +1 -0
- package/.next/server/app/api/config/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/config/test/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/config/test/route/build-manifest.json +9 -0
- package/.next/server/app/api/config/test/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/config/test/route.js +8 -0
- package/.next/server/app/api/config/test/route.js.nft.json +1 -0
- package/.next/server/app/api/config/test/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/config/test-embedding/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/config/test-embedding/route/build-manifest.json +9 -0
- package/.next/server/app/api/config/test-embedding/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/config/test-embedding/route.js +12 -0
- package/.next/server/app/api/config/test-embedding/route.js.nft.json +1 -0
- package/.next/server/app/api/config/test-embedding/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/config/test-llm/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/config/test-llm/route/build-manifest.json +9 -0
- package/.next/server/app/api/config/test-llm/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/config/test-llm/route.js +12 -0
- package/.next/server/app/api/config/test-llm/route.js.nft.json +1 -0
- package/.next/server/app/api/config/test-llm/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/config/test-provider/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/config/test-provider/route/build-manifest.json +9 -0
- package/.next/server/app/api/config/test-provider/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/config/test-provider/route.js +13 -0
- package/.next/server/app/api/config/test-provider/route.js.nft.json +1 -0
- package/.next/server/app/api/config/test-provider/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/config/verify/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/config/verify/route/build-manifest.json +9 -0
- package/.next/server/app/api/config/verify/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/config/verify/route.js +16 -0
- package/.next/server/app/api/config/verify/route.js.nft.json +1 -0
- package/.next/server/app/api/config/verify/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/connections/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/connections/route/build-manifest.json +9 -0
- package/.next/server/app/api/connections/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/connections/route.js +8 -0
- package/.next/server/app/api/connections/route.js.nft.json +1 -0
- package/.next/server/app/api/connections/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/connections/webhook/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/connections/webhook/route/build-manifest.json +9 -0
- package/.next/server/app/api/connections/webhook/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/connections/webhook/route.js +10 -0
- package/.next/server/app/api/connections/webhook/route.js.nft.json +1 -0
- package/.next/server/app/api/connections/webhook/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/demo/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/demo/route/build-manifest.json +9 -0
- package/.next/server/app/api/demo/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/demo/route.js +15 -0
- package/.next/server/app/api/demo/route.js.nft.json +1 -0
- package/.next/server/app/api/demo/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/deploy/cloud-project/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/deploy/cloud-project/route/build-manifest.json +9 -0
- package/.next/server/app/api/deploy/cloud-project/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/deploy/cloud-project/route.js +13 -0
- package/.next/server/app/api/deploy/cloud-project/route.js.nft.json +1 -0
- package/.next/server/app/api/deploy/cloud-project/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/deploy/ssh/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/deploy/ssh/route/build-manifest.json +9 -0
- package/.next/server/app/api/deploy/ssh/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/deploy/ssh/route.js +8 -0
- package/.next/server/app/api/deploy/ssh/route.js.nft.json +1 -0
- package/.next/server/app/api/deploy/ssh/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/deployment/blob-setup/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/deployment/blob-setup/route/build-manifest.json +9 -0
- package/.next/server/app/api/deployment/blob-setup/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/deployment/blob-setup/route.js +8 -0
- package/.next/server/app/api/deployment/blob-setup/route.js.nft.json +1 -0
- package/.next/server/app/api/deployment/blob-setup/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/deployment/config/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/deployment/config/route/build-manifest.json +9 -0
- package/.next/server/app/api/deployment/config/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/deployment/config/route.js +8 -0
- package/.next/server/app/api/deployment/config/route.js.nft.json +1 -0
- package/.next/server/app/api/deployment/config/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/describe-image/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/describe-image/route/build-manifest.json +9 -0
- package/.next/server/app/api/describe-image/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/describe-image/route.js +15 -0
- package/.next/server/app/api/describe-image/route.js.nft.json +1 -0
- package/.next/server/app/api/describe-image/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/doc-editor/edit/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/doc-editor/edit/route/build-manifest.json +9 -0
- package/.next/server/app/api/doc-editor/edit/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/doc-editor/edit/route.js +11 -0
- package/.next/server/app/api/doc-editor/edit/route.js.nft.json +1 -0
- package/.next/server/app/api/doc-editor/edit/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/doc-editor/export/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/doc-editor/export/route/build-manifest.json +9 -0
- package/.next/server/app/api/doc-editor/export/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/doc-editor/export/route.js +11 -0
- package/.next/server/app/api/doc-editor/export/route.js.nft.json +1 -0
- package/.next/server/app/api/doc-editor/export/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/doc-editor/extract-text/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/doc-editor/extract-text/route/build-manifest.json +9 -0
- package/.next/server/app/api/doc-editor/extract-text/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/doc-editor/extract-text/route.js +11 -0
- package/.next/server/app/api/doc-editor/extract-text/route.js.nft.json +1 -0
- package/.next/server/app/api/doc-editor/extract-text/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/doc-editor/parse/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/doc-editor/parse/route/build-manifest.json +9 -0
- package/.next/server/app/api/doc-editor/parse/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/doc-editor/parse/route.js +12 -0
- package/.next/server/app/api/doc-editor/parse/route.js.nft.json +1 -0
- package/.next/server/app/api/doc-editor/parse/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/doc-editor/restore/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/doc-editor/restore/route/build-manifest.json +9 -0
- package/.next/server/app/api/doc-editor/restore/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/doc-editor/restore/route.js +11 -0
- package/.next/server/app/api/doc-editor/restore/route.js.nft.json +1 -0
- package/.next/server/app/api/doc-editor/restore/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/document/sign/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/document/sign/route/build-manifest.json +9 -0
- package/.next/server/app/api/document/sign/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/document/sign/route.js +12 -0
- package/.next/server/app/api/document/sign/route.js.nft.json +1 -0
- package/.next/server/app/api/document/sign/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/documents/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/documents/route/build-manifest.json +9 -0
- package/.next/server/app/api/documents/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/documents/route.js +8 -0
- package/.next/server/app/api/documents/route.js.nft.json +1 -0
- package/.next/server/app/api/documents/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/firecrawl/local/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/firecrawl/local/route/build-manifest.json +9 -0
- package/.next/server/app/api/firecrawl/local/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/firecrawl/local/route.js +8 -0
- package/.next/server/app/api/firecrawl/local/route.js.nft.json +1 -0
- package/.next/server/app/api/firecrawl/local/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/index/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/index/route/build-manifest.json +9 -0
- package/.next/server/app/api/index/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/index/route.js +14 -0
- package/.next/server/app/api/index/route.js.nft.json +1 -0
- package/.next/server/app/api/index/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/integrations/notion/callback/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/integrations/notion/callback/route/build-manifest.json +9 -0
- package/.next/server/app/api/integrations/notion/callback/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/integrations/notion/callback/route.js +8 -0
- package/.next/server/app/api/integrations/notion/callback/route.js.nft.json +1 -0
- package/.next/server/app/api/integrations/notion/callback/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/integrations/notion/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/integrations/notion/route/build-manifest.json +9 -0
- package/.next/server/app/api/integrations/notion/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/integrations/notion/route.js +8 -0
- package/.next/server/app/api/integrations/notion/route.js.nft.json +1 -0
- package/.next/server/app/api/integrations/notion/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/jobs/[id]/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/jobs/[id]/route/build-manifest.json +9 -0
- package/.next/server/app/api/jobs/[id]/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/jobs/[id]/route.js +8 -0
- package/.next/server/app/api/jobs/[id]/route.js.nft.json +1 -0
- package/.next/server/app/api/jobs/[id]/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/jobs/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/jobs/route/build-manifest.json +9 -0
- package/.next/server/app/api/jobs/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/jobs/route.js +8 -0
- package/.next/server/app/api/jobs/route.js.nft.json +1 -0
- package/.next/server/app/api/jobs/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/marketplace/[toolId]/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/marketplace/[toolId]/route/build-manifest.json +9 -0
- package/.next/server/app/api/marketplace/[toolId]/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/marketplace/[toolId]/route.js +9 -0
- package/.next/server/app/api/marketplace/[toolId]/route.js.nft.json +1 -0
- package/.next/server/app/api/marketplace/[toolId]/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/marketplace/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/marketplace/route/build-manifest.json +9 -0
- package/.next/server/app/api/marketplace/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/marketplace/route.js +9 -0
- package/.next/server/app/api/marketplace/route.js.nft.json +1 -0
- package/.next/server/app/api/marketplace/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/media/[id]/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/media/[id]/route/build-manifest.json +9 -0
- package/.next/server/app/api/media/[id]/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/media/[id]/route.js +8 -0
- package/.next/server/app/api/media/[id]/route.js.nft.json +1 -0
- package/.next/server/app/api/media/[id]/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/media/process/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/media/process/route/build-manifest.json +9 -0
- package/.next/server/app/api/media/process/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/media/process/route.js +17 -0
- package/.next/server/app/api/media/process/route.js.nft.json +1 -0
- package/.next/server/app/api/media/process/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/media/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/media/route/build-manifest.json +9 -0
- package/.next/server/app/api/media/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/media/route.js +9 -0
- package/.next/server/app/api/media/route.js.nft.json +1 -0
- package/.next/server/app/api/media/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/media/stream/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/media/stream/route/build-manifest.json +9 -0
- package/.next/server/app/api/media/stream/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/media/stream/route.js +7 -0
- package/.next/server/app/api/media/stream/route.js.nft.json +1 -0
- package/.next/server/app/api/media/stream/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/models/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/models/route/build-manifest.json +9 -0
- package/.next/server/app/api/models/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/models/route.js +9 -0
- package/.next/server/app/api/models/route.js.nft.json +1 -0
- package/.next/server/app/api/models/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/parse-file/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/parse-file/route/build-manifest.json +9 -0
- package/.next/server/app/api/parse-file/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/parse-file/route.js +11 -0
- package/.next/server/app/api/parse-file/route.js.nft.json +1 -0
- package/.next/server/app/api/parse-file/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/proxy/verify/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/proxy/verify/route/build-manifest.json +9 -0
- package/.next/server/app/api/proxy/verify/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/proxy/verify/route.js +8 -0
- package/.next/server/app/api/proxy/verify/route.js.nft.json +1 -0
- package/.next/server/app/api/proxy/verify/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/sandbox/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/sandbox/route/build-manifest.json +9 -0
- package/.next/server/app/api/sandbox/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/sandbox/route.js +8 -0
- package/.next/server/app/api/sandbox/route.js.nft.json +1 -0
- package/.next/server/app/api/sandbox/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/search/bing/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/search/bing/route/build-manifest.json +9 -0
- package/.next/server/app/api/search/bing/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/search/bing/route.js +8 -0
- package/.next/server/app/api/search/bing/route.js.nft.json +1 -0
- package/.next/server/app/api/search/bing/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/search/brave/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/search/brave/route/build-manifest.json +9 -0
- package/.next/server/app/api/search/brave/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/search/brave/route.js +8 -0
- package/.next/server/app/api/search/brave/route.js.nft.json +1 -0
- package/.next/server/app/api/search/brave/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/search/exa/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/search/exa/route/build-manifest.json +9 -0
- package/.next/server/app/api/search/exa/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/search/exa/route.js +8 -0
- package/.next/server/app/api/search/exa/route.js.nft.json +1 -0
- package/.next/server/app/api/search/exa/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/search/google/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/search/google/route/build-manifest.json +9 -0
- package/.next/server/app/api/search/google/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/search/google/route.js +8 -0
- package/.next/server/app/api/search/google/route.js.nft.json +1 -0
- package/.next/server/app/api/search/google/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/search/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/search/route/build-manifest.json +9 -0
- package/.next/server/app/api/search/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/search/route.js +8 -0
- package/.next/server/app/api/search/route.js.nft.json +1 -0
- package/.next/server/app/api/search/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/search/tavily/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/search/tavily/route/build-manifest.json +9 -0
- package/.next/server/app/api/search/tavily/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/search/tavily/route.js +8 -0
- package/.next/server/app/api/search/tavily/route.js.nft.json +1 -0
- package/.next/server/app/api/search/tavily/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/search/verify/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/search/verify/route/build-manifest.json +9 -0
- package/.next/server/app/api/search/verify/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/search/verify/route.js +8 -0
- package/.next/server/app/api/search/verify/route.js.nft.json +1 -0
- package/.next/server/app/api/search/verify/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/server/agent/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/server/agent/route/build-manifest.json +9 -0
- package/.next/server/app/api/server/agent/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/server/agent/route.js +10 -0
- package/.next/server/app/api/server/agent/route.js.nft.json +1 -0
- package/.next/server/app/api/server/agent/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/server/download/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/server/download/route/build-manifest.json +9 -0
- package/.next/server/app/api/server/download/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/server/download/route.js +9 -0
- package/.next/server/app/api/server/download/route.js.nft.json +1 -0
- package/.next/server/app/api/server/download/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/server/generate/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/server/generate/route/build-manifest.json +9 -0
- package/.next/server/app/api/server/generate/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/server/generate/route.js +10 -0
- package/.next/server/app/api/server/generate/route.js.nft.json +1 -0
- package/.next/server/app/api/server/generate/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/server/local/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/server/local/route/build-manifest.json +9 -0
- package/.next/server/app/api/server/local/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/server/local/route.js +10 -0
- package/.next/server/app/api/server/local/route.js.nft.json +1 -0
- package/.next/server/app/api/server/local/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/servers/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/servers/route/build-manifest.json +9 -0
- package/.next/server/app/api/servers/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/servers/route.js +10 -0
- package/.next/server/app/api/servers/route.js.nft.json +1 -0
- package/.next/server/app/api/servers/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/tabular/query/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/tabular/query/route/build-manifest.json +9 -0
- package/.next/server/app/api/tabular/query/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/tabular/query/route.js +8 -0
- package/.next/server/app/api/tabular/query/route.js.nft.json +1 -0
- package/.next/server/app/api/tabular/query/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/tabular/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/tabular/route/build-manifest.json +9 -0
- package/.next/server/app/api/tabular/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/tabular/route.js +8 -0
- package/.next/server/app/api/tabular/route.js.nft.json +1 -0
- package/.next/server/app/api/tabular/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/upload-file/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/upload-file/route/build-manifest.json +9 -0
- package/.next/server/app/api/upload-file/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/upload-file/route.js +8 -0
- package/.next/server/app/api/upload-file/route.js.nft.json +1 -0
- package/.next/server/app/api/upload-file/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/uploads/[...slug]/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/uploads/[...slug]/route/build-manifest.json +9 -0
- package/.next/server/app/api/uploads/[...slug]/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/uploads/[...slug]/route.js +8 -0
- package/.next/server/app/api/uploads/[...slug]/route.js.nft.json +1 -0
- package/.next/server/app/api/uploads/[...slug]/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/vector-stores/install/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/vector-stores/install/route/build-manifest.json +9 -0
- package/.next/server/app/api/vector-stores/install/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/vector-stores/install/route.js +8 -0
- package/.next/server/app/api/vector-stores/install/route.js.nft.json +1 -0
- package/.next/server/app/api/vector-stores/install/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/vector-stores/status/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/vector-stores/status/route/build-manifest.json +9 -0
- package/.next/server/app/api/vector-stores/status/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/vector-stores/status/route.js +8 -0
- package/.next/server/app/api/vector-stores/status/route.js.nft.json +1 -0
- package/.next/server/app/api/vector-stores/status/route_client-reference-manifest.js +3 -0
- package/.next/server/app/chat/page/app-paths-manifest.json +3 -0
- package/.next/server/app/chat/page/build-manifest.json +18 -0
- package/.next/server/app/chat/page/next-font-manifest.json +11 -0
- package/.next/server/app/chat/page/react-loadable-manifest.json +1 -0
- package/.next/server/app/chat/page/server-reference-manifest.json +4 -0
- package/.next/server/app/chat/page.js +15 -0
- package/.next/server/app/chat/page.js.nft.json +1 -0
- package/.next/server/app/chat/page_client-reference-manifest.js +3 -0
- package/.next/server/app/chat.html +1 -0
- package/.next/server/app/chat.meta +15 -0
- package/.next/server/app/chat.rsc +29 -0
- package/.next/server/app/chat.segments/_full.segment.rsc +29 -0
- package/.next/server/app/chat.segments/_head.segment.rsc +6 -0
- package/.next/server/app/chat.segments/_index.segment.rsc +14 -0
- package/.next/server/app/chat.segments/_tree.segment.rsc +5 -0
- package/.next/server/app/chat.segments/chat/__PAGE__.segment.rsc +6 -0
- package/.next/server/app/chat.segments/chat.segment.rsc +5 -0
- package/.next/server/app/data/page/app-paths-manifest.json +3 -0
- package/.next/server/app/data/page/build-manifest.json +18 -0
- package/.next/server/app/data/page/next-font-manifest.json +11 -0
- package/.next/server/app/data/page/react-loadable-manifest.json +1 -0
- package/.next/server/app/data/page/server-reference-manifest.json +4 -0
- package/.next/server/app/data/page.js +15 -0
- package/.next/server/app/data/page.js.nft.json +1 -0
- package/.next/server/app/data/page_client-reference-manifest.js +3 -0
- package/.next/server/app/data.html +1 -0
- package/.next/server/app/data.meta +15 -0
- package/.next/server/app/data.rsc +32 -0
- package/.next/server/app/data.segments/_full.segment.rsc +32 -0
- package/.next/server/app/data.segments/_head.segment.rsc +6 -0
- package/.next/server/app/data.segments/_index.segment.rsc +14 -0
- package/.next/server/app/data.segments/_tree.segment.rsc +5 -0
- package/.next/server/app/data.segments/data/__PAGE__.segment.rsc +6 -0
- package/.next/server/app/data.segments/data.segment.rsc +5 -0
- package/.next/server/app/favicon.ico/route/app-paths-manifest.json +3 -0
- package/.next/server/app/favicon.ico/route/build-manifest.json +9 -0
- package/.next/server/app/favicon.ico/route.js +8 -0
- package/.next/server/app/favicon.ico/route.js.nft.json +1 -0
- package/.next/server/app/favicon.ico.body +0 -0
- package/.next/server/app/favicon.ico.meta +1 -0
- package/.next/server/app/index.html +1 -0
- package/.next/server/app/index.meta +14 -0
- package/.next/server/app/index.rsc +26 -0
- package/.next/server/app/index.segments/__PAGE__.segment.rsc +6 -0
- package/.next/server/app/index.segments/_full.segment.rsc +26 -0
- package/.next/server/app/index.segments/_head.segment.rsc +6 -0
- package/.next/server/app/index.segments/_index.segment.rsc +14 -0
- package/.next/server/app/index.segments/_tree.segment.rsc +5 -0
- package/.next/server/app/page/app-paths-manifest.json +3 -0
- package/.next/server/app/page/build-manifest.json +18 -0
- package/.next/server/app/page/next-font-manifest.json +11 -0
- package/.next/server/app/page/react-loadable-manifest.json +1 -0
- package/.next/server/app/page/server-reference-manifest.json +4 -0
- package/.next/server/app/page.js +16 -0
- package/.next/server/app/page.js.nft.json +1 -0
- package/.next/server/app/page_client-reference-manifest.js +3 -0
- package/.next/server/app/settings/page/app-paths-manifest.json +3 -0
- package/.next/server/app/settings/page/build-manifest.json +18 -0
- package/.next/server/app/settings/page/next-font-manifest.json +11 -0
- package/.next/server/app/settings/page/react-loadable-manifest.json +1 -0
- package/.next/server/app/settings/page/server-reference-manifest.json +41 -0
- package/.next/server/app/settings/page.js +16 -0
- package/.next/server/app/settings/page.js.nft.json +1 -0
- package/.next/server/app/settings/page_client-reference-manifest.js +3 -0
- package/.next/server/app/settings.html +1 -0
- package/.next/server/app/settings.meta +15 -0
- package/.next/server/app/settings.rsc +31 -0
- package/.next/server/app/settings.segments/_full.segment.rsc +31 -0
- package/.next/server/app/settings.segments/_head.segment.rsc +6 -0
- package/.next/server/app/settings.segments/_index.segment.rsc +14 -0
- package/.next/server/app/settings.segments/_tree.segment.rsc +5 -0
- package/.next/server/app/settings.segments/settings/__PAGE__.segment.rsc +9 -0
- package/.next/server/app/settings.segments/settings.segment.rsc +5 -0
- package/.next/server/app-paths-manifest.json +69 -0
- package/.next/server/chunks/00i._ai_dist_index_mjs_0u4.k1t._.js +34 -0
- package/.next/server/chunks/02dz_web__next-internal_server_app_api_config_test-embedding_route_actions_09--owe.js +3 -0
- package/.next/server/chunks/02dz_web__next-internal_server_app_api_config_test-provider_route_actions_0l6xr0t.js +3 -0
- package/.next/server/chunks/02dz_web__next-internal_server_app_api_deploy_cloud-project_route_actions_0pghds2.js +3 -0
- package/.next/server/chunks/02dz_web__next-internal_server_app_api_deployment_blob-setup_route_actions_0f55gkq.js +3 -0
- package/.next/server/chunks/02dz_web__next-internal_server_app_api_doc-editor_extract-text_route_actions_0dzj6iq.js +3 -0
- package/.next/server/chunks/02dz_web__next-internal_server_app_api_marketplace_[toolId]_route_actions_0cxbtrw.js +3 -0
- package/.next/server/chunks/02dz_web__next-internal_server_app_api_vector-stores_install_route_actions_0_220fs.js +3 -0
- package/.next/server/chunks/02dz_web__next-internal_server_app_api_vector-stores_status_route_actions_0~_~b02.js +3 -0
- package/.next/server/chunks/0gvc_next_03p7xh-._.js +13 -0
- package/.next/server/chunks/0gvc_next_dist_esm_build_templates_app-route_0--xko7.js +24 -0
- package/.next/server/chunks/0gvc_next_dist_esm_build_templates_app-route_0.07y39.js +3 -0
- package/.next/server/chunks/0gvc_next_dist_esm_build_templates_app-route_04i84m2.js +10 -0
- package/.next/server/chunks/0gvc_next_dist_esm_build_templates_app-route_05yqn19.js +3 -0
- package/.next/server/chunks/0gvc_next_dist_esm_build_templates_app-route_0_c4eox.js +3 -0
- package/.next/server/chunks/0m6-_@ai-sdk_anthropic_dist_index_093y5mm.js +10 -0
- package/.next/server/chunks/0nf3_next-internal_server_app_api_integrations_notion_callback_route_actions_0hyfnmw.js +3 -0
- package/.next/server/chunks/0ntz_@ai-sdk_openai_dist_index_mjs_03ljy2u._.js +13 -0
- package/.next/server/chunks/0ozc_@vercel_oidc_dist_token_0m1934l.js +3 -0
- package/.next/server/chunks/0rgj_zod_v4_0ponial._.js +64 -0
- package/.next/server/chunks/0rgj_zod_v4_0zoqna9._.js +64 -0
- package/.next/server/chunks/[externals]__01hpkma._.js +3 -0
- package/.next/server/chunks/[externals]__01tm01i._.js +3 -0
- package/.next/server/chunks/[externals]_chromadb_0goja~y._.js +3 -0
- package/.next/server/chunks/[externals]_fs_0eo4gmu._.js +3 -0
- package/.next/server/chunks/[externals]_path_0.09pfe._.js +3 -0
- package/.next/server/chunks/[externals]_stream_0g9s3ok._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0--6uey._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0.qd1p3._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0.r5yhr._.js +49 -0
- package/.next/server/chunks/[root-of-the-server]__0036943._.js +199 -0
- package/.next/server/chunks/[root-of-the-server]__00a7cyb._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__00nqa2u._.js +59 -0
- package/.next/server/chunks/[root-of-the-server]__0111be7._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__02c_z~9._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__02cpmox._.js +105 -0
- package/.next/server/chunks/[root-of-the-server]__02p-tv7._.js +105 -0
- package/.next/server/chunks/[root-of-the-server]__02p34d7._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__02t_0g7._.js +59 -0
- package/.next/server/chunks/[root-of-the-server]__03-x3no._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__03l~uw5._.js +143 -0
- package/.next/server/chunks/[root-of-the-server]__044l2_f._.js +143 -0
- package/.next/server/chunks/[root-of-the-server]__04kopvt._.js +63 -0
- package/.next/server/chunks/[root-of-the-server]__04l~ip-._.js +59 -0
- package/.next/server/chunks/[root-of-the-server]__04visk8._.js +105 -0
- package/.next/server/chunks/[root-of-the-server]__05wk..v._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__05x8tmf._.js +59 -0
- package/.next/server/chunks/[root-of-the-server]__06l96vc._.js +59 -0
- package/.next/server/chunks/[root-of-the-server]__06ohoeu._.js +59 -0
- package/.next/server/chunks/[root-of-the-server]__072q335._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__07_1411._.js +59 -0
- package/.next/server/chunks/[root-of-the-server]__09kos0n._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__09oyip3._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__09rsmk2._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0_by00t._.js +11 -0
- package/.next/server/chunks/[root-of-the-server]__0a9jp5~._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0acpo9m._.js +59 -0
- package/.next/server/chunks/[root-of-the-server]__0b17yoc._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0cumfx6._.js +9 -0
- package/.next/server/chunks/[root-of-the-server]__0d7p0xo._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0e_itje._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0exyn0q._.js +88 -0
- package/.next/server/chunks/[root-of-the-server]__0fcf_rl._.js +59 -0
- package/.next/server/chunks/[root-of-the-server]__0f~eq1-._.js +59 -0
- package/.next/server/chunks/[root-of-the-server]__0g36cgg._.js +143 -0
- package/.next/server/chunks/[root-of-the-server]__0g4hq1o._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0i9fj76._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0lczaer._.js +143 -0
- package/.next/server/chunks/[root-of-the-server]__0ljy49-._.js +59 -0
- package/.next/server/chunks/[root-of-the-server]__0lk5hkk._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0n0nerw._.js +59 -0
- package/.next/server/chunks/[root-of-the-server]__0np09bv._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0ns~dg6._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0oh5wgp._.js +59 -0
- package/.next/server/chunks/[root-of-the-server]__0oyc7s4._.js +105 -0
- package/.next/server/chunks/[root-of-the-server]__0pg~eys._.js +59 -0
- package/.next/server/chunks/[root-of-the-server]__0qhpl6k._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0qhwzn-._.js +21 -0
- package/.next/server/chunks/[root-of-the-server]__0qs73xp._.js +143 -0
- package/.next/server/chunks/[root-of-the-server]__0qtx78g._.js +59 -0
- package/.next/server/chunks/[root-of-the-server]__0r03jcl._.js +59 -0
- package/.next/server/chunks/[root-of-the-server]__0rdjqpy._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0sb7d93._.js +59 -0
- package/.next/server/chunks/[root-of-the-server]__0t36t5o._.js +60 -0
- package/.next/server/chunks/[root-of-the-server]__0t_hp52._.js +59 -0
- package/.next/server/chunks/[root-of-the-server]__0udlgj6._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0ufk3d0._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0uu6oan._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0v.0gyp._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0v03x56._.js +59 -0
- package/.next/server/chunks/[root-of-the-server]__0v4bbce._.js +59 -0
- package/.next/server/chunks/[root-of-the-server]__0v67rlo._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0vcdpoc._.js +59 -0
- package/.next/server/chunks/[root-of-the-server]__0veqa4o._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0wvxpqf._.js +59 -0
- package/.next/server/chunks/[root-of-the-server]__0wyl7x5._.js +59 -0
- package/.next/server/chunks/[root-of-the-server]__0y5y7tu._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0yo._sm._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0yx8vxp._.js +59 -0
- package/.next/server/chunks/[root-of-the-server]__0zh8t6z._.js +59 -0
- package/.next/server/chunks/[root-of-the-server]__0~q2fro._.js +59 -0
- package/.next/server/chunks/[root-of-the-server]__0~wsw0_._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__100gqj0._.js +143 -0
- package/.next/server/chunks/[root-of-the-server]__10au-r5._.js +13 -0
- package/.next/server/chunks/[root-of-the-server]__10d58x4._.js +59 -0
- package/.next/server/chunks/[root-of-the-server]__10zm06g._.js +143 -0
- package/.next/server/chunks/[root-of-the-server]__12kvuvp._.js +59 -0
- package/.next/server/chunks/[root-of-the-server]__13gq0t2._.js +3 -0
- package/.next/server/chunks/[turbopack]_runtime.js +903 -0
- package/.next/server/chunks/_01kokno._.js +3 -0
- package/.next/server/chunks/_059f-.0._.js +258 -0
- package/.next/server/chunks/_071mhy1._.js +32 -0
- package/.next/server/chunks/apps_web__next-internal_server_app_api_analytics_route_actions_0.uxcnt.js +3 -0
- package/.next/server/chunks/apps_web__next-internal_server_app_api_chat_route_actions_0q6zwqv.js +3 -0
- package/.next/server/chunks/apps_web__next-internal_server_app_api_chat_status_route_actions_0t_21~v.js +3 -0
- package/.next/server/chunks/apps_web__next-internal_server_app_api_chat_suggestions_route_actions_01umx_-.js +3 -0
- package/.next/server/chunks/apps_web__next-internal_server_app_api_config_route_actions_0-4ivvk.js +3 -0
- package/.next/server/chunks/apps_web__next-internal_server_app_api_config_test-llm_route_actions_0z5ew-0.js +3 -0
- package/.next/server/chunks/apps_web__next-internal_server_app_api_config_test_route_actions_08cur6r.js +3 -0
- package/.next/server/chunks/apps_web__next-internal_server_app_api_config_verify_route_actions_0hid6b..js +3 -0
- package/.next/server/chunks/apps_web__next-internal_server_app_api_connections_route_actions_0q3wdg3.js +3 -0
- package/.next/server/chunks/apps_web__next-internal_server_app_api_connections_webhook_route_actions_0wa28~b.js +3 -0
- package/.next/server/chunks/apps_web__next-internal_server_app_api_demo_route_actions_05lntn3.js +3 -0
- package/.next/server/chunks/apps_web__next-internal_server_app_api_deploy_ssh_route_actions_0r44rn0.js +3 -0
- package/.next/server/chunks/apps_web__next-internal_server_app_api_deployment_config_route_actions_0bkon.m.js +3 -0
- package/.next/server/chunks/apps_web__next-internal_server_app_api_describe-image_route_actions_0pmvs8v.js +3 -0
- package/.next/server/chunks/apps_web__next-internal_server_app_api_doc-editor_edit_route_actions_10hrovj.js +3 -0
- package/.next/server/chunks/apps_web__next-internal_server_app_api_doc-editor_export_route_actions_0rff01q.js +3 -0
- package/.next/server/chunks/apps_web__next-internal_server_app_api_doc-editor_parse_route_actions_0fkx6xw.js +3 -0
- package/.next/server/chunks/apps_web__next-internal_server_app_api_doc-editor_restore_route_actions_0g9uodw.js +3 -0
- package/.next/server/chunks/apps_web__next-internal_server_app_api_document_sign_route_actions_0_6rnl_.js +3 -0
- package/.next/server/chunks/apps_web__next-internal_server_app_api_documents_route_actions_0l2znaz.js +3 -0
- package/.next/server/chunks/apps_web__next-internal_server_app_api_firecrawl_local_route_actions_0ubjaim.js +3 -0
- package/.next/server/chunks/apps_web__next-internal_server_app_api_index_route_actions_0~2989e.js +3 -0
- package/.next/server/chunks/apps_web__next-internal_server_app_api_integrations_notion_route_actions_08es~5e.js +3 -0
- package/.next/server/chunks/apps_web__next-internal_server_app_api_jobs_[id]_route_actions_0.l39qd.js +3 -0
- package/.next/server/chunks/apps_web__next-internal_server_app_api_jobs_route_actions_08kx~8-.js +3 -0
- package/.next/server/chunks/apps_web__next-internal_server_app_api_marketplace_route_actions_0z~vymm.js +3 -0
- package/.next/server/chunks/apps_web__next-internal_server_app_api_media_[id]_route_actions_0wsnidd.js +3 -0
- package/.next/server/chunks/apps_web__next-internal_server_app_api_media_process_route_actions_0_j9maz.js +3 -0
- package/.next/server/chunks/apps_web__next-internal_server_app_api_media_route_actions_01szz-1.js +3 -0
- package/.next/server/chunks/apps_web__next-internal_server_app_api_media_stream_route_actions_0h2x_~2.js +3 -0
- package/.next/server/chunks/apps_web__next-internal_server_app_api_models_route_actions_0ervfbf.js +3 -0
- package/.next/server/chunks/apps_web__next-internal_server_app_api_parse-file_route_actions_134wu5p.js +3 -0
- package/.next/server/chunks/apps_web__next-internal_server_app_api_proxy_verify_route_actions_11frmb9.js +3 -0
- package/.next/server/chunks/apps_web__next-internal_server_app_api_sandbox_route_actions_0y9te9y.js +3 -0
- package/.next/server/chunks/apps_web__next-internal_server_app_api_search_bing_route_actions_0pfrdr1.js +3 -0
- package/.next/server/chunks/apps_web__next-internal_server_app_api_search_brave_route_actions_0sij14a.js +3 -0
- package/.next/server/chunks/apps_web__next-internal_server_app_api_search_exa_route_actions_013do9i.js +3 -0
- package/.next/server/chunks/apps_web__next-internal_server_app_api_search_google_route_actions_02aoghr.js +3 -0
- package/.next/server/chunks/apps_web__next-internal_server_app_api_search_route_actions_0_2o9ph.js +3 -0
- package/.next/server/chunks/apps_web__next-internal_server_app_api_search_tavily_route_actions_0z0cnd4.js +3 -0
- package/.next/server/chunks/apps_web__next-internal_server_app_api_search_verify_route_actions_0xtygzs.js +3 -0
- package/.next/server/chunks/apps_web__next-internal_server_app_api_server_agent_route_actions_11xuz1m.js +3 -0
- package/.next/server/chunks/apps_web__next-internal_server_app_api_server_download_route_actions_0vdr_bn.js +3 -0
- package/.next/server/chunks/apps_web__next-internal_server_app_api_server_generate_route_actions_12qf.pa.js +3 -0
- package/.next/server/chunks/apps_web__next-internal_server_app_api_server_local_route_actions_0c~tchb.js +3 -0
- package/.next/server/chunks/apps_web__next-internal_server_app_api_servers_route_actions_0_qimaq.js +3 -0
- package/.next/server/chunks/apps_web__next-internal_server_app_api_tabular_query_route_actions_0m_i8~j.js +3 -0
- package/.next/server/chunks/apps_web__next-internal_server_app_api_tabular_route_actions_06xgjmg.js +3 -0
- package/.next/server/chunks/apps_web__next-internal_server_app_api_upload-file_route_actions_0-df~h8.js +3 -0
- package/.next/server/chunks/apps_web__next-internal_server_app_api_uploads_[___slug]_route_actions_0-6rd8s.js +3 -0
- package/.next/server/chunks/apps_web__next-internal_server_app_favicon_ico_route_actions_0h5n1et.js +3 -0
- package/.next/server/chunks/node_modules__pnpm_00a45hz._.js +15 -0
- package/.next/server/chunks/node_modules__pnpm_01evtue._.js +36 -0
- package/.next/server/chunks/node_modules__pnpm_058qmaf._.js +36 -0
- package/.next/server/chunks/node_modules__pnpm_090g2s3._.js +3 -0
- package/.next/server/chunks/node_modules__pnpm_0of6.x_._.js +3 -0
- package/.next/server/chunks/node_modules__pnpm_0tui34u._.js +5 -0
- package/.next/server/chunks/node_modules__pnpm_11fyqx5._.js +15 -0
- package/.next/server/chunks/node_modules__pnpm_12rdsen._.js +36 -0
- package/.next/server/chunks/packages_070bs61._.js +3 -0
- package/.next/server/chunks/packages_0jmx5.-._.js +3 -0
- package/.next/server/chunks/packages_core_src_analytics-store_ts_03tqnqs._.js +3 -0
- package/.next/server/chunks/packages_core_src_embeddings_providers_ts_05f4_w-._.js +19 -0
- package/.next/server/chunks/packages_core_src_embeddings_registry_ts_031sc7-._.js +3 -0
- package/.next/server/chunks/packages_core_src_generator_generate-server_ts_0mt.je3._.js +1145 -0
- package/.next/server/chunks/packages_core_src_generator_server-runtime_ts_127f0ye._.js +648 -0
- package/.next/server/chunks/packages_core_src_index-store_ts_13sjtkb._.js +3 -0
- package/.next/server/chunks/packages_core_src_indexing_embedder_ts_0h75r~u._.js +20 -0
- package/.next/server/chunks/packages_core_src_media-store_ts_0v0lx36._.js +3 -0
- package/.next/server/chunks/packages_core_src_models-list_ts_03-odl5._.js +3 -0
- package/.next/server/chunks/packages_marketplace_src_0mxp_e3._.js +3 -0
- package/.next/server/chunks/packages_marketplace_src_storage-provider_ts_0mbs32-._.js +3 -0
- package/.next/server/chunks/packages_vector-stores_src_044u_tk._.js +3 -0
- package/.next/server/chunks/ssr/0ay0_framer-motion_dist_es_render_components_motion_proxy_mjs_00idub3._.js +3 -0
- package/.next/server/chunks/ssr/0gvc_next_dist_0e.uypd._.js +6 -0
- package/.next/server/chunks/ssr/0gvc_next_dist_client_components_0mj6fnc._.js +3 -0
- package/.next/server/chunks/ssr/0gvc_next_dist_client_components_builtin_forbidden_10qct8z.js +3 -0
- package/.next/server/chunks/ssr/0gvc_next_dist_client_components_builtin_global-error_0azu6.3.js +3 -0
- package/.next/server/chunks/ssr/0gvc_next_dist_client_components_builtin_unauthorized_03b6_.w.js +3 -0
- package/.next/server/chunks/ssr/0gvc_next_dist_esm_build_templates_app-page_0-imr0z.js +4 -0
- package/.next/server/chunks/ssr/0gvc_next_dist_esm_build_templates_app-page_00l31p..js +4 -0
- package/.next/server/chunks/ssr/0gvc_next_dist_esm_build_templates_app-page_0cjdc2w.js +4 -0
- package/.next/server/chunks/ssr/0gvc_next_dist_esm_build_templates_app-page_0fsrb82.js +4 -0
- package/.next/server/chunks/ssr/0gvc_next_dist_esm_build_templates_app-page_0l3eneq.js +4 -0
- package/.next/server/chunks/ssr/0gvc_next_dist_esm_build_templates_app-page_0l6387r.js +4 -0
- package/.next/server/chunks/ssr/0gvc_next_dist_esm_build_templates_app-page_0pk8tjk.js +4 -0
- package/.next/server/chunks/ssr/0hhw_pdfjs-dist_build_pdf_mjs_0emol.8._.js +47 -0
- package/.next/server/chunks/ssr/0ozc_@vercel_oidc_dist_token_0qkzh69.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__03nybtv._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__061054q._.js +33 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0_lfs3c._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0bxkvem._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0ciwgj6._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0f10~ff._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0l9758p._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0mib-aw._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0o6u8a1._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0q-0ign._.js +33 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0u7t7hm._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0yxrvhy._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0z9yy2_._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0zl.q74._.js +3 -0
- package/.next/server/chunks/ssr/[turbopack]_runtime.js +903 -0
- package/.next/server/chunks/ssr/_0-uky5v._.js +3 -0
- package/.next/server/chunks/ssr/_0007q7_._.js +3 -0
- package/.next/server/chunks/ssr/_003vid-._.js +3 -0
- package/.next/server/chunks/ssr/_03casre._.js +6 -0
- package/.next/server/chunks/ssr/_06imf71._.js +4 -0
- package/.next/server/chunks/ssr/_08uade7._.js +3 -0
- package/.next/server/chunks/ssr/_09~o4f.._.js +13 -0
- package/.next/server/chunks/ssr/_0_aolb-._.js +3 -0
- package/.next/server/chunks/ssr/_0_zom3a._.js +3 -0
- package/.next/server/chunks/ssr/_0erod4k._.js +3 -0
- package/.next/server/chunks/ssr/_0gh6844._.js +3 -0
- package/.next/server/chunks/ssr/_0h9s_hw._.js +3 -0
- package/.next/server/chunks/ssr/_0p1j64v._.js +3 -0
- package/.next/server/chunks/ssr/_0qi5c9~._.js +132 -0
- package/.next/server/chunks/ssr/_0qopd-r._.js +120 -0
- package/.next/server/chunks/ssr/_0s5_0n1._.js +3 -0
- package/.next/server/chunks/ssr/_11.lrfy._.js +6 -0
- package/.next/server/chunks/ssr/_13gucvb._.js +3 -0
- package/.next/server/chunks/ssr/apps_web__next-internal_server_app__global-error_page_actions_0.u5cfa.js +3 -0
- package/.next/server/chunks/ssr/apps_web__next-internal_server_app__not-found_page_actions_0appun9.js +3 -0
- package/.next/server/chunks/ssr/apps_web__next-internal_server_app_analytics_page_actions_04e3dmk.js +3 -0
- package/.next/server/chunks/ssr/apps_web__next-internal_server_app_chat_page_actions_0x9i55t.js +3 -0
- package/.next/server/chunks/ssr/apps_web__next-internal_server_app_data_page_actions_0f9t7xs.js +3 -0
- package/.next/server/chunks/ssr/apps_web__next-internal_server_app_page_actions_0rm5_5w.js +3 -0
- package/.next/server/chunks/ssr/apps_web_app_template_tsx_0.4m7c9._.js +3 -0
- package/.next/server/chunks/ssr/apps_web_app_template_tsx_0j2myib._.js +3 -0
- package/.next/server/chunks/ssr/apps_web_components_analytics_analytics-dashboard_tsx_0lrr85m._.js +3 -0
- package/.next/server/chunks/ssr/apps_web_components_ui_tabs_tsx_0435ww5._.js +3 -0
- package/.next/server/chunks/ssr/apps_web_lib_pdf-images_ts_0nzct~e._.js +3 -0
- package/.next/server/chunks/ssr/node_modules__pnpm_0auud-z._.js +3 -0
- package/.next/server/chunks/ssr/node_modules__pnpm_0efi01o._.js +3 -0
- package/.next/server/chunks/ssr/node_modules__pnpm_0ge5k63._.js +3 -0
- package/.next/server/chunks/ssr/node_modules__pnpm_0j6v-w5._.js +3 -0
- package/.next/server/chunks/ssr/node_modules__pnpm_0jmin55._.js +33 -0
- package/.next/server/chunks/ssr/node_modules__pnpm_0qjmu5-._.js +3 -0
- package/.next/server/chunks/ssr/node_modules__pnpm_0q~5d-e._.js +3 -0
- package/.next/server/chunks/ssr/node_modules__pnpm_0xnq.u3._.js +19 -0
- package/.next/server/chunks/ssr/packages_core_src_generator_generate-server_ts_0o.y7vi._.js +1145 -0
- package/.next/server/functions-config-manifest.json +52 -0
- package/.next/server/interception-route-rewrite-manifest.js +1 -0
- package/.next/server/middleware-build-manifest.js +22 -0
- package/.next/server/middleware-manifest.json +6 -0
- package/.next/server/next-font-manifest.js +1 -0
- package/.next/server/next-font-manifest.json +31 -0
- package/.next/server/pages/404.html +1 -0
- package/.next/server/pages/500.html +1 -0
- package/.next/server/pages-manifest.json +4 -0
- package/.next/server/prefetch-hints.json +1 -0
- package/.next/server/server-reference-manifest.js +1 -0
- package/.next/server/server-reference-manifest.json +42 -0
- package/.next/static/KqIuNxkoeAlhCusoxtMrS/_buildManifest.js +16 -0
- package/.next/static/KqIuNxkoeAlhCusoxtMrS/_clientMiddlewareManifest.js +1 -0
- package/.next/static/KqIuNxkoeAlhCusoxtMrS/_ssgManifest.js +1 -0
- package/.next/static/chunks/0-l-_.e4~p-tu.js +1 -0
- package/.next/static/chunks/00bdh97xa16uo.js +1 -0
- package/.next/static/chunks/00h-ng_jqta-2.js +1 -0
- package/.next/static/chunks/03jot0gqi~a10.js +1 -0
- package/.next/static/chunks/03~yq9q893hmn.js +1 -0
- package/.next/static/chunks/066jf0nk75nic.css +2 -0
- package/.next/static/chunks/06lztj0p4bq9f.js +31 -0
- package/.next/static/chunks/06mvsykkx_ufi.js +1 -0
- package/.next/static/chunks/090nmx8zs_1wf.js +1 -0
- package/.next/static/chunks/0_~l8kd_h3sbq.js +1 -0
- package/.next/static/chunks/0c-2rnxmjsotm.js +118 -0
- package/.next/static/chunks/0ho7lc.x2uknx.js +1 -0
- package/.next/static/chunks/0i-8kxwbvp9.l.js +129 -0
- package/.next/static/chunks/0l27y8_9hhe7s.js +4 -0
- package/.next/static/chunks/0q_qvc60_3aw4.js +1 -0
- package/.next/static/chunks/0r4ctb~yxw0ip.js +45 -0
- package/.next/static/chunks/0rp85cjcakb29.js +1 -0
- package/.next/static/chunks/0uawaqqylt5zw.css +1 -0
- package/.next/static/chunks/0ufxt21gvl.3g.js +1 -0
- package/.next/static/chunks/0vnayejbagbex.js +1 -0
- package/.next/static/chunks/0w6lgn24.0eip.js +1 -0
- package/.next/static/chunks/0wrbyfcre8l1-.js +1 -0
- package/.next/static/chunks/0xil-1~ra.qnv.js +1 -0
- package/.next/static/chunks/0zoh3o_.geqbv.js +1 -0
- package/.next/static/chunks/0~074ua5vk6f8.js +1 -0
- package/.next/static/chunks/0~_-3fik2n4-i.js +1 -0
- package/.next/static/chunks/10a_hianorzj3.js +1 -0
- package/.next/static/chunks/10k--lk9wf4pw.js +1 -0
- package/.next/static/chunks/14x~vj_4i-4bz.js +1 -0
- package/.next/static/chunks/15tyhmsp4jgmc.js +11 -0
- package/.next/static/chunks/16alfqkklv-bt.js +2 -0
- package/.next/static/chunks/176ixsksxtch_.js +1 -0
- package/.next/static/chunks/turbopack-06_~2vs.chjg_.js +1 -0
- package/.next/static/media/4fa387ec64143e14-s.0wkzw~je483f-.woff2 +0 -0
- package/.next/static/media/53b9e256198e5412-s.0-wfv7uh4i7h9.woff2 +0 -0
- package/.next/static/media/5ce348bf30bf5439-s.0zgw-jeven.3w.woff2 +0 -0
- package/.next/static/media/6306c77e7c8268e4-s.0rhz0arwfsn~5.woff2 +0 -0
- package/.next/static/media/7178b3e590c64307-s.0nx0ww8fni_q3.woff2 +0 -0
- package/.next/static/media/797e433ab948586e-s.p.08e28id.o-okb.woff2 +0 -0
- package/.next/static/media/7d817b4c03b0c5f1-s.0l76wvqk9d84w.woff2 +0 -0
- package/.next/static/media/8a480f0b521d4e75-s.0jzbimsg8vl84.woff2 +0 -0
- package/.next/static/media/bbc41e54d2fcbd21-s.0k4k9394f2q-k.woff2 +0 -0
- package/.next/static/media/caa3a2e1cccd8315-s.p.09~u27dqhyhd6.woff2 +0 -0
- package/.next/static/media/favicon.01rzdfen4476b.ico +0 -0
- package/.next/static/media/fef07dbb0973bf53-s.12tyk43_3sh9u.woff2 +0 -0
- package/.next/types/cache-life.d.ts +145 -0
- package/.next/types/routes.d.ts +136 -0
- package/.next/types/validator.ts +637 -0
- package/CHANGELOG.md +24 -0
- package/LICENSE +176 -0
- package/app/actions/vercel.ts +325 -152
- package/app/analytics/page.tsx +19 -0
- package/app/api/analytics/route.ts +31 -0
- package/app/api/chat/route.ts +331 -145
- package/app/api/chat/status/route.ts +73 -22
- package/app/api/chat/suggestions/route.ts +61 -48
- package/app/api/chat/tools.ts +995 -0
- package/app/api/config/route.ts +56 -32
- package/app/api/config/test/route.ts +33 -32
- package/app/api/config/test-llm/route.ts +9 -10
- package/app/api/config/verify/route.ts +315 -0
- package/app/api/connections/route.ts +39 -0
- package/app/api/connections/webhook/route.ts +43 -0
- package/app/api/demo/route.ts +32 -44
- package/app/api/deploy/cloud-project/route.ts +125 -0
- package/app/api/deploy/ssh/route.ts +173 -132
- package/app/api/deployment/blob-setup/route.ts +28 -0
- package/app/api/deployment/config/route.ts +23 -0
- package/app/api/describe-image/route.ts +84 -0
- package/app/api/doc-editor/edit/route.ts +88 -0
- package/app/api/doc-editor/export/route.ts +33 -0
- package/app/api/doc-editor/extract-text/route.ts +41 -0
- package/app/api/doc-editor/parse/route.ts +66 -0
- package/app/api/doc-editor/restore/route.ts +74 -0
- package/app/api/document/sign/route.ts +56 -0
- package/app/api/documents/route.ts +185 -35
- package/app/api/firecrawl/local/route.ts +63 -23
- package/app/api/index/route.ts +73 -59
- package/app/api/integrations/notion/callback/route.ts +121 -0
- package/app/api/integrations/notion/route.ts +304 -0
- package/app/api/jobs/route.ts +45 -47
- package/app/api/marketplace/[toolId]/route.ts +70 -0
- package/app/api/marketplace/route.ts +32 -0
- package/app/api/media/[id]/route.ts +108 -0
- package/app/api/media/process/route.ts +1242 -0
- package/app/api/media/route.ts +284 -0
- package/app/api/media/stream/route.ts +113 -0
- package/app/api/models/route.ts +23 -0
- package/app/api/proxy/verify/route.ts +66 -0
- package/app/api/sandbox/route.ts +59 -0
- package/app/api/search/bing/route.ts +87 -0
- package/app/api/search/brave/route.ts +89 -0
- package/app/api/search/exa/route.ts +101 -0
- package/app/api/search/google/route.ts +16 -29
- package/app/api/search/tavily/route.ts +94 -0
- package/app/api/search/verify/route.ts +28 -0
- package/app/api/server/agent/route.ts +41 -0
- package/app/api/server/download/route.ts +42 -34
- package/app/api/server/generate/route.ts +23 -23
- package/app/api/servers/route.ts +46 -62
- package/app/api/tabular/query/route.ts +26 -0
- package/app/api/tabular/route.ts +63 -0
- package/app/api/upload-file/route.ts +38 -0
- package/app/api/uploads/[...slug]/route.ts +90 -0
- package/app/api/vector-stores/install/route.ts +5 -6
- package/app/api/vector-stores/status/route.ts +9 -7
- package/app/chat/page.tsx +4 -8
- package/app/data/page.tsx +15 -8
- package/app/globals.css +150 -22
- package/app/layout.tsx +19 -17
- package/app/page.tsx +3 -32
- package/app/settings/page.tsx +80 -0
- package/app/themes.css +38 -2
- package/archive/redesign-v2/app/configure/page.tsx +53 -0
- package/archive/redesign-v2/app/demo/page.tsx +15 -0
- package/archive/redesign-v2/app/server/page.tsx +22 -0
- package/archive/redesign-v2/app/simple/chat/page.tsx +17 -0
- package/archive/redesign-v2/app/simple/docs/page.tsx +21 -0
- package/archive/redesign-v2/app/simple/settings/page.tsx +1104 -0
- package/{app → archive/redesign-v2/app-routes}/server/page.tsx +2 -2
- package/archive/redesign-v2/app-routes/simple/settings/page.tsx +1104 -0
- package/archive/redesign-v2/components/app-sidebar.tsx +188 -0
- package/archive/redesign-v2/components/app-topnav.tsx +195 -0
- package/archive/redesign-v2/components/global-settings.tsx +288 -0
- package/archive/redesign-v2/components/simple/simple-sidebar.tsx +171 -0
- package/archive/redesign-v2/components/simple/simple-topnav.tsx +175 -0
- package/bin/larkup.js +28 -0
- package/components/analytics/analytics-dashboard.tsx +504 -0
- package/components/app-sidebar.tsx +46 -57
- package/components/app-topnav.tsx +64 -150
- package/components/chat/canvas/doc-editor-provider.tsx +343 -0
- package/components/chat/canvas/document-canvas.tsx +102 -0
- package/components/chat/canvas/document-field.tsx +171 -0
- package/components/chat/canvas/document-viewer.tsx +453 -0
- package/components/chat/canvas/file-attachment-button.tsx +88 -0
- package/components/chat/canvas/file-chip.tsx +151 -0
- package/components/chat/chat-settings-modal.tsx +253 -149
- package/components/chat/chat-workspace.tsx +961 -149
- package/components/chat/message-item.tsx +935 -71
- package/components/chat/tools/chat-card.tsx +116 -0
- package/components/chat/tools/chat-chart.tsx +548 -0
- package/components/chat/tools/chat-data-table.tsx +370 -0
- package/components/chat/tools/chat-grid.tsx +99 -0
- package/components/chat/tools/chat-media-preview.tsx +246 -0
- package/components/chat/tools/chat-metrics.tsx +76 -0
- package/components/chat/tools/chat-sandbox-result.tsx +175 -0
- package/components/chat/tools/chat-signature-request.tsx +809 -0
- package/components/chat/tools/chat-tabs.tsx +66 -0
- package/components/chat/tools/corpus-data-result.tsx +206 -0
- package/components/chat/tools/knowledge-base-result.tsx +135 -0
- package/components/chat/tools/visual-placement-modal.tsx +316 -0
- package/components/chat/tools/visualization-tabs.tsx +37 -0
- package/components/client-layout-wrapper.tsx +52 -124
- package/components/configure/configure-form.tsx +301 -530
- package/components/configure/custom-model-modal.tsx +205 -0
- package/components/configure/store-fields.tsx +4 -1
- package/components/data/corpus-panel.tsx +329 -137
- package/components/data/data-workspace.tsx +428 -185
- package/components/data/firecrawl-notice.tsx +94 -122
- package/components/data/integrations-panel.tsx +408 -0
- package/components/data/jobs-panel.tsx +83 -105
- package/components/data/media-panel.tsx +1701 -0
- package/components/data/notion-panel.tsx +372 -0
- package/components/data/paste-panel.tsx +4 -3
- package/components/data/scrape-panel.tsx +389 -343
- package/components/data/tabular-preview.tsx +228 -0
- package/components/data/upload-panel.tsx +500 -206
- package/components/demo/demo-workspace.tsx +50 -83
- package/components/global-settings.tsx +71 -108
- package/components/index/global-index-progress.tsx +46 -0
- package/components/index/index-action-dialog.tsx +545 -0
- package/components/index/index-workspace.tsx +138 -219
- package/components/onboarding/simple-setup.tsx +126 -180
- package/components/onboarding/welcome-screen.tsx +428 -157
- package/components/server/deploy-button.tsx +95 -1233
- package/components/server/deploy-sheet.tsx +1061 -0
- package/components/server/server-workspace.tsx +62 -95
- package/components/settings/appearance-section.tsx +300 -0
- package/components/settings/connections-section.tsx +471 -0
- package/components/settings/deploy-section.tsx +24 -0
- package/components/settings/deployment-section.tsx +430 -0
- package/components/settings/general-section.tsx +734 -0
- package/components/settings/marketplace-section.tsx +385 -0
- package/components/settings/marketplace-tools-settings.tsx +436 -0
- package/components/settings/models-section.tsx +810 -0
- package/components/settings/playground-section.tsx +17 -0
- package/components/settings/prompts-section.tsx +384 -0
- package/components/settings/server-section.tsx +808 -0
- package/components/settings/settings-layout.tsx +147 -0
- package/components/settings/storage-section.tsx +394 -0
- package/components/simple/sdk-connect-dialog.tsx +38 -33
- package/components/simple/simple-sidebar.tsx +69 -72
- package/components/simple/simple-topnav.tsx +154 -0
- package/components/theme-customizer-provider.tsx +56 -79
- package/components/theme-switcher.tsx +92 -114
- package/components/ui/button.tsx +11 -13
- package/components/ui/card.tsx +17 -17
- package/components/ui/checkbox.tsx +5 -5
- package/components/ui/dialog.tsx +1 -1
- package/components/ui/dropdown-menu.tsx +24 -38
- package/components/ui/input.tsx +2 -2
- package/components/ui/popover.tsx +21 -34
- package/components/ui/provider-icon.tsx +88 -17
- package/components/ui/select.tsx +44 -61
- package/components/ui/sheet.tsx +33 -46
- package/components/ui/slider.tsx +52 -0
- package/components/ui/sonner.tsx +23 -36
- package/components/ui/table.tsx +19 -19
- package/components/ui/tabs.tsx +17 -24
- package/components/ui/textarea.tsx +4 -4
- package/components/unified-sidebar.tsx +222 -0
- package/components/update-banner.tsx +203 -0
- package/components/workspace/server-form-dialog.tsx +7 -7
- package/components/workspace/server-switcher.tsx +15 -37
- package/hooks/use-notion-auth.ts +60 -0
- package/lib/chat-model-provider.ts +115 -0
- package/lib/deployments.ts +119 -0
- package/lib/env-utils.ts +27 -0
- package/lib/media-knowledge.ts +431 -0
- package/lib/os-concurrency.ts +37 -0
- package/lib/pdf-images.ts +80 -0
- package/lib/search-provider-verification.ts +95 -0
- package/next.config.mjs +19 -2
- package/package.json +37 -20
- package/parse_log.mjs +67 -0
- package/public/icons/Confluence.png +0 -0
- package/public/icons/Salesforce.png +0 -0
- package/public/icons/audio.png +0 -0
- package/public/icons/bing.png +0 -0
- package/public/icons/brave.png +0 -0
- package/public/icons/deepgram.png +0 -0
- package/public/icons/discord.png +0 -0
- package/public/icons/elevenlabs.png +0 -0
- package/public/icons/exa.png +0 -0
- package/public/icons/excel.png +0 -0
- package/public/icons/fal.png +0 -0
- package/public/icons/firecrawl.png +0 -0
- package/public/icons/google-calender.png +0 -0
- package/public/icons/google-drive.png +0 -0
- package/public/icons/google.png +0 -0
- package/public/icons/grok.png +0 -0
- package/public/icons/image.png +0 -0
- package/public/icons/jira.png +0 -0
- package/public/icons/linear.png +0 -0
- package/public/icons/markdown.png +0 -0
- package/public/icons/onedrive.png +0 -0
- package/public/icons/outlook.png +0 -0
- package/public/icons/pdf.png +0 -0
- package/public/icons/revai.png +0 -0
- package/public/icons/revai.svg +1 -0
- package/public/icons/sap.png +0 -0
- package/public/icons/serpapi.svg +34 -0
- package/public/icons/serper.png +0 -0
- package/public/icons/sharepoint.png +0 -0
- package/public/icons/slack.png +0 -0
- package/public/icons/tavily.png +0 -0
- package/public/icons/telegram.png +0 -0
- package/public/icons/video.png +0 -0
- package/public/icons/webhook.png +0 -0
- package/public/icons/whatsapp.png +0 -0
- package/public/icons/word.png +0 -0
- package/public/logo-light2.png +0 -0
- package/public/logo.png +0 -0
- package/public/notion-white.png +0 -0
- package/public/notion.png +0 -0
- package/store/chat-store.ts +19 -0
- package/store/scrape-store.ts +78 -0
- package/tsconfig.json +1 -1
- package/verify-models.mjs +133 -0
- package/.env +0 -2
- package/app/index-data/page.tsx +0 -15
- package/app/simple/settings/page.tsx +0 -627
- package/components/chat/knowledge-base-result.tsx +0 -97
- /package/{app → archive/redesign-v2/app-routes}/configure/page.tsx +0 -0
- /package/{app → archive/redesign-v2/app-routes}/demo/page.tsx +0 -0
- /package/{app → archive/redesign-v2/app-routes}/simple/chat/page.tsx +0 -0
- /package/{app → archive/redesign-v2/app-routes}/simple/docs/page.tsx +0 -0
- /package/{app → archive/redesign-v2/app-routes}/simple/layout.tsx +0 -0
|
@@ -0,0 +1,1242 @@
|
|
|
1
|
+
import { NextResponse } from 'next/server';
|
|
2
|
+
import { randomUUID } from 'node:crypto';
|
|
3
|
+
import {
|
|
4
|
+
claimMediaAsset,
|
|
5
|
+
updateMediaAsset,
|
|
6
|
+
updateMediaStage,
|
|
7
|
+
readMediaAssets,
|
|
8
|
+
type MediaProcessingStepPatch,
|
|
9
|
+
} from '@larkup/core/media-store';
|
|
10
|
+
import { addDocument, addDocuments, deleteDocuments } from '@larkup/core/documents-store';
|
|
11
|
+
import { getInstalledTool, isToolInstalled } from '@larkup/marketplace/installer';
|
|
12
|
+
import { loadTool } from '@larkup/marketplace/loader';
|
|
13
|
+
import { createStorageProvider } from '@larkup/marketplace/storage';
|
|
14
|
+
import { readConfig } from '@larkup/core/config-store';
|
|
15
|
+
import type { MediaAsset, MediaPipelineStage } from '@larkup/core/types';
|
|
16
|
+
import { runWithServer } from '@larkup/core/workspace';
|
|
17
|
+
import { getConcurrencyLimits } from '@/lib/os-concurrency';
|
|
18
|
+
import {
|
|
19
|
+
buildMediaDocumentInputs,
|
|
20
|
+
createFallbackMediaSummary,
|
|
21
|
+
createMediaKnowledgeSummary,
|
|
22
|
+
formatTime,
|
|
23
|
+
type MediaEvidenceSegment,
|
|
24
|
+
} from '@/lib/media-knowledge';
|
|
25
|
+
|
|
26
|
+
export const runtime = 'nodejs';
|
|
27
|
+
export const dynamic = 'force-dynamic';
|
|
28
|
+
|
|
29
|
+
// One lightweight in-process queue per app instance prevents different users
|
|
30
|
+
// from launching several memory-heavy FFmpeg jobs at once.
|
|
31
|
+
let mediaProcessingChain: Promise<void> = Promise.resolve();
|
|
32
|
+
|
|
33
|
+
type StageReporter = (stage: MediaPipelineStage, patch: MediaProcessingStepPatch) => Promise<void>;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* POST → trigger media processing for one or more assets.
|
|
37
|
+
*
|
|
38
|
+
* Body: { assetIds: string[], serverId?: string }
|
|
39
|
+
*
|
|
40
|
+
* Processing is claimed atomically and continues in the background while the
|
|
41
|
+
* client polls persisted asset progress.
|
|
42
|
+
* For images: generates captions via vision LLM.
|
|
43
|
+
* For video/audio: requires the Video & Audio tool to be installed.
|
|
44
|
+
*/
|
|
45
|
+
export async function POST(req: Request) {
|
|
46
|
+
try {
|
|
47
|
+
const { assetIds, serverId } = (await req.json()) as {
|
|
48
|
+
assetIds: string[];
|
|
49
|
+
serverId?: string;
|
|
50
|
+
};
|
|
51
|
+
if (!assetIds?.length) {
|
|
52
|
+
return NextResponse.json({ error: 'assetIds required' }, { status: 400 });
|
|
53
|
+
}
|
|
54
|
+
const enqueue = () => enqueueMediaProcessing(req.url, assetIds, serverId);
|
|
55
|
+
return serverId ? await runWithServer(serverId, enqueue) : await enqueue();
|
|
56
|
+
} catch (err) {
|
|
57
|
+
const message = err instanceof Error ? err.message : 'Failed to trigger processing';
|
|
58
|
+
return NextResponse.json({ error: message }, { status: 500 });
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
async function enqueueMediaProcessing(
|
|
63
|
+
reqUrl: string,
|
|
64
|
+
assetIds: string[],
|
|
65
|
+
serverId?: string,
|
|
66
|
+
): Promise<NextResponse> {
|
|
67
|
+
try {
|
|
68
|
+
const assets = await readMediaAssets();
|
|
69
|
+
const matchingAssets = assets.filter((asset) => assetIds.includes(asset.id));
|
|
70
|
+
const claimedAssets = await Promise.all(
|
|
71
|
+
matchingAssets.map((asset) => claimMediaAsset(asset.id)),
|
|
72
|
+
);
|
|
73
|
+
const toProcess = claimedAssets.filter((asset): asset is MediaAsset => Boolean(asset));
|
|
74
|
+
const sourceTranscripts = new Map<string, any>();
|
|
75
|
+
const queuedAssetIds = new Set(toProcess.map((asset) => asset.id));
|
|
76
|
+
|
|
77
|
+
if (toProcess.length === 0) {
|
|
78
|
+
return NextResponse.json(
|
|
79
|
+
{
|
|
80
|
+
error: matchingAssets.length
|
|
81
|
+
? 'Media is already processing.'
|
|
82
|
+
: 'No matching assets found',
|
|
83
|
+
},
|
|
84
|
+
{ status: matchingAssets.length ? 409 : 404 },
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const touchQueuedAssets = async () => {
|
|
89
|
+
const processingHeartbeatAt = new Date().toISOString();
|
|
90
|
+
await Promise.all(
|
|
91
|
+
[...queuedAssetIds].map((id) =>
|
|
92
|
+
updateMediaAsset(id, { processingHeartbeatAt }).catch(() => undefined),
|
|
93
|
+
),
|
|
94
|
+
);
|
|
95
|
+
};
|
|
96
|
+
const queuedHeartbeat = setInterval(() => {
|
|
97
|
+
const touch = () => touchQueuedAssets();
|
|
98
|
+
void (serverId ? runWithServer(serverId, touch) : touch()).catch(() => {});
|
|
99
|
+
}, 60_000);
|
|
100
|
+
|
|
101
|
+
// Run processing in the background
|
|
102
|
+
const runJob = async () => {
|
|
103
|
+
for (const initialAsset of toProcess) {
|
|
104
|
+
queuedAssetIds.delete(initialAsset.id);
|
|
105
|
+
let currentAsset = initialAsset;
|
|
106
|
+
let heartbeat: ReturnType<typeof setInterval> | undefined;
|
|
107
|
+
const activeStages = new Set<MediaPipelineStage>();
|
|
108
|
+
const lastStageUpdates = new Map<MediaPipelineStage, number>();
|
|
109
|
+
const reportStage: StageReporter = async (stage, patch) => {
|
|
110
|
+
const now = Date.now();
|
|
111
|
+
const isTerminal =
|
|
112
|
+
patch.status === 'completed' || patch.status === 'skipped' || patch.status === 'failed';
|
|
113
|
+
// FFmpeg and providers can report many events per second. Each stage
|
|
114
|
+
// keeps its own throttle so parallel transcription and vision never
|
|
115
|
+
// overwrite or suppress one another.
|
|
116
|
+
if (
|
|
117
|
+
!isTerminal &&
|
|
118
|
+
patch.status === 'running' &&
|
|
119
|
+
now - (lastStageUpdates.get(stage) ?? 0) < 600
|
|
120
|
+
) {
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
lastStageUpdates.set(stage, now);
|
|
124
|
+
if (patch.status === 'running') activeStages.add(stage);
|
|
125
|
+
if (isTerminal) activeStages.delete(stage);
|
|
126
|
+
const updated = await updateMediaStage(currentAsset.id, stage, patch);
|
|
127
|
+
if (!updated) {
|
|
128
|
+
throw new Error('Media asset was deleted during processing');
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
try {
|
|
133
|
+
const startedAsset = await updateMediaAsset(currentAsset.id, {
|
|
134
|
+
processingStatus: 'processing',
|
|
135
|
+
processingError: undefined,
|
|
136
|
+
processingMessage: 'Starting process...',
|
|
137
|
+
processingProgress: 2,
|
|
138
|
+
});
|
|
139
|
+
if (!startedAsset) {
|
|
140
|
+
throw new Error('Media asset was removed before processing started.');
|
|
141
|
+
}
|
|
142
|
+
currentAsset = startedAsset;
|
|
143
|
+
heartbeat = setInterval(() => {
|
|
144
|
+
void updateMediaAsset(currentAsset.id, {
|
|
145
|
+
processingHeartbeatAt: new Date().toISOString(),
|
|
146
|
+
}).catch(() => {});
|
|
147
|
+
}, 60_000);
|
|
148
|
+
|
|
149
|
+
if (currentAsset.storageUri.startsWith('pending://') && currentAsset.originalUrl) {
|
|
150
|
+
await reportStage('download', {
|
|
151
|
+
status: 'running',
|
|
152
|
+
percent: 0,
|
|
153
|
+
message: 'Downloading media from URL...',
|
|
154
|
+
});
|
|
155
|
+
const { addMediaAssets } = await import('@larkup/core/media-store');
|
|
156
|
+
const tool = await loadTool<any>('video-audio');
|
|
157
|
+
if (!tool || !tool.importMediaUrl)
|
|
158
|
+
throw new Error('Video & Audio tool not properly installed.');
|
|
159
|
+
|
|
160
|
+
const { promises: fs } = await import('node:fs');
|
|
161
|
+
const path = await import('node:path');
|
|
162
|
+
const os = await import('node:os');
|
|
163
|
+
const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), 'larkup-url-media-'));
|
|
164
|
+
try {
|
|
165
|
+
const entries = await tool.importMediaUrl(currentAsset.originalUrl, {
|
|
166
|
+
outputDir: tmpDir,
|
|
167
|
+
playlistMax: 10, // max items
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
if (!entries || entries.length === 0) {
|
|
171
|
+
throw new Error('No supported media found at the provided URL.');
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
const storage = createStorageProvider();
|
|
175
|
+
|
|
176
|
+
const storeDownloadedFile = async (
|
|
177
|
+
filePath: string,
|
|
178
|
+
key: string,
|
|
179
|
+
mimeType: string,
|
|
180
|
+
) => {
|
|
181
|
+
const stat = await fs.stat(filePath);
|
|
182
|
+
const storageUri = storage.storeFile
|
|
183
|
+
? await storage.storeFile(key, filePath, mimeType)
|
|
184
|
+
: await storage.store(key, await fs.readFile(filePath), mimeType);
|
|
185
|
+
return { storageUri, fileSize: stat.size };
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
// Process the first entry into the current asset
|
|
189
|
+
const firstEntry = entries[0];
|
|
190
|
+
const mimeType = firstEntry.mimeType || 'application/octet-stream';
|
|
191
|
+
const ext = path.extname(firstEntry.path).slice(1) || 'mp4';
|
|
192
|
+
const key = `videos/${Date.now()}_${Math.random().toString(36).slice(2)}.${ext}`;
|
|
193
|
+
const storedFirstEntry = await storeDownloadedFile(firstEntry.path, key, mimeType);
|
|
194
|
+
|
|
195
|
+
currentAsset =
|
|
196
|
+
(await updateMediaAsset(currentAsset.id, {
|
|
197
|
+
fileName: firstEntry.title || path.basename(firstEntry.path),
|
|
198
|
+
mimeType,
|
|
199
|
+
...storedFirstEntry,
|
|
200
|
+
})) || currentAsset;
|
|
201
|
+
await reportStage('download', {
|
|
202
|
+
status: 'completed',
|
|
203
|
+
message: 'Download complete.',
|
|
204
|
+
});
|
|
205
|
+
if (firstEntry.sourceTranscript?.chunks?.length) {
|
|
206
|
+
sourceTranscripts.set(currentAsset.id, firstEntry.sourceTranscript);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// If playlist, insert the rest as new pending assets and process them later
|
|
210
|
+
if (entries.length > 1) {
|
|
211
|
+
const newInputs: import('@larkup/core/media-store').NewMediaAssetInput[] = [];
|
|
212
|
+
for (let i = 1; i < entries.length; i++) {
|
|
213
|
+
const entry = entries[i];
|
|
214
|
+
const entryMime = entry.mimeType || 'application/octet-stream';
|
|
215
|
+
const entryExt = path.extname(entry.path).slice(1) || 'mp4';
|
|
216
|
+
const entryKey = `videos/${Date.now()}_${Math.random()
|
|
217
|
+
.toString(36)
|
|
218
|
+
.slice(2)}.${entryExt}`;
|
|
219
|
+
const storedEntry = await storeDownloadedFile(entry.path, entryKey, entryMime);
|
|
220
|
+
newInputs.push({
|
|
221
|
+
type: currentAsset.type,
|
|
222
|
+
fileName: entry.title || path.basename(entry.path),
|
|
223
|
+
mimeType: entryMime,
|
|
224
|
+
...storedEntry,
|
|
225
|
+
originalUrl: entry.originalUrl || currentAsset.originalUrl,
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
const extraAssets = await addMediaAssets(newInputs);
|
|
229
|
+
const claimedExtraAssets = (
|
|
230
|
+
await Promise.all(extraAssets.map((extraAsset) => claimMediaAsset(extraAsset.id)))
|
|
231
|
+
).filter((extraAsset): extraAsset is MediaAsset => Boolean(extraAsset));
|
|
232
|
+
claimedExtraAssets.forEach((extraAsset) => {
|
|
233
|
+
const sourceIndex = extraAssets.findIndex(
|
|
234
|
+
(candidate) => candidate.id === extraAsset.id,
|
|
235
|
+
);
|
|
236
|
+
const transcript = entries[sourceIndex + 1]?.sourceTranscript;
|
|
237
|
+
if (transcript?.chunks?.length) sourceTranscripts.set(extraAsset.id, transcript);
|
|
238
|
+
queuedAssetIds.add(extraAsset.id);
|
|
239
|
+
});
|
|
240
|
+
// Push them to the queue to be processed in this loop
|
|
241
|
+
toProcess.push(...claimedExtraAssets);
|
|
242
|
+
}
|
|
243
|
+
} finally {
|
|
244
|
+
await fs.rm(tmpDir, { recursive: true, force: true }).catch(() => {});
|
|
245
|
+
}
|
|
246
|
+
} else {
|
|
247
|
+
await reportStage('download', {
|
|
248
|
+
status: 'skipped',
|
|
249
|
+
message: 'Using uploaded media.',
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
if (currentAsset.type === 'image') {
|
|
254
|
+
await processImageAsset(currentAsset, reqUrl, reportStage, serverId);
|
|
255
|
+
} else if (currentAsset.type === 'video' || currentAsset.type === 'audio') {
|
|
256
|
+
const installed = await isToolInstalled('video-audio');
|
|
257
|
+
if (!installed) {
|
|
258
|
+
throw new Error(
|
|
259
|
+
'Video & Audio tool is not installed. Install it from the Marketplace.',
|
|
260
|
+
);
|
|
261
|
+
}
|
|
262
|
+
await processMediaWithTool(
|
|
263
|
+
currentAsset,
|
|
264
|
+
reqUrl,
|
|
265
|
+
reportStage,
|
|
266
|
+
sourceTranscripts.get(currentAsset.id),
|
|
267
|
+
serverId,
|
|
268
|
+
);
|
|
269
|
+
} else {
|
|
270
|
+
throw new Error('Unsupported media type');
|
|
271
|
+
}
|
|
272
|
+
} catch (err) {
|
|
273
|
+
const message = err instanceof Error ? err.message : 'Processing failed';
|
|
274
|
+
await Promise.all(
|
|
275
|
+
[...activeStages].map((stage) =>
|
|
276
|
+
updateMediaStage(currentAsset.id, stage, {
|
|
277
|
+
status: 'failed',
|
|
278
|
+
message,
|
|
279
|
+
}),
|
|
280
|
+
),
|
|
281
|
+
);
|
|
282
|
+
await updateMediaAsset(currentAsset.id, {
|
|
283
|
+
processingStatus: 'failed',
|
|
284
|
+
processingError: message,
|
|
285
|
+
processingMessage: undefined,
|
|
286
|
+
processingProgress: undefined,
|
|
287
|
+
});
|
|
288
|
+
} finally {
|
|
289
|
+
if (heartbeat) clearInterval(heartbeat);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
};
|
|
293
|
+
const job = mediaProcessingChain
|
|
294
|
+
.then(() => (serverId ? runWithServer(serverId, runJob) : runJob()))
|
|
295
|
+
.finally(() => clearInterval(queuedHeartbeat));
|
|
296
|
+
mediaProcessingChain = job.catch((error) => console.error('Media worker failed:', error));
|
|
297
|
+
|
|
298
|
+
return NextResponse.json(
|
|
299
|
+
{ success: true, message: 'Processing started in background' },
|
|
300
|
+
{ status: 202 },
|
|
301
|
+
);
|
|
302
|
+
} catch (err) {
|
|
303
|
+
const message = err instanceof Error ? err.message : 'Failed to trigger processing';
|
|
304
|
+
return NextResponse.json({ error: message }, { status: 500 });
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/* ------------------------------------------------------------------ */
|
|
309
|
+
/* Image processing (built-in, no tool needed) */
|
|
310
|
+
/* ------------------------------------------------------------------ */
|
|
311
|
+
|
|
312
|
+
async function processImageAsset(
|
|
313
|
+
asset: MediaAsset,
|
|
314
|
+
reqUrl: string,
|
|
315
|
+
reportStage: StageReporter,
|
|
316
|
+
serverId?: string,
|
|
317
|
+
): Promise<void> {
|
|
318
|
+
await cleanupIncompleteMediaPublication(asset);
|
|
319
|
+
let caption = `Image: ${asset.fileName}`;
|
|
320
|
+
await Promise.all([
|
|
321
|
+
reportStage('extract', { status: 'skipped', message: 'No extraction needed.' }),
|
|
322
|
+
reportStage('transcribe', { status: 'skipped', message: 'No audio track.' }),
|
|
323
|
+
reportStage('synthesize', { status: 'skipped', message: 'Caption is the media note.' }),
|
|
324
|
+
]);
|
|
325
|
+
await reportStage('vision', {
|
|
326
|
+
status: 'running',
|
|
327
|
+
percent: 0,
|
|
328
|
+
message: `Understanding image: ${asset.fileName}`,
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
try {
|
|
332
|
+
const storage = createStorageProvider();
|
|
333
|
+
const fileData = await storage.retrieve(asset.storageUri);
|
|
334
|
+
const base64 = fileData.toString('base64');
|
|
335
|
+
|
|
336
|
+
const descRes = await fetch(scopedApiUrl('/api/describe-image', reqUrl, serverId), {
|
|
337
|
+
method: 'POST',
|
|
338
|
+
headers: { 'Content-Type': 'application/json' },
|
|
339
|
+
body: JSON.stringify({ base64 }),
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
if (descRes.ok) {
|
|
343
|
+
const descData = await descRes.json();
|
|
344
|
+
if (descData.description) {
|
|
345
|
+
caption = descData.description;
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
} catch (err) {
|
|
349
|
+
console.error('Failed to describe image asset:', err);
|
|
350
|
+
}
|
|
351
|
+
await reportStage('vision', {
|
|
352
|
+
status: 'completed',
|
|
353
|
+
message: 'Image understanding complete.',
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
const documentId = randomUUID();
|
|
357
|
+
let indexAttempted = false;
|
|
358
|
+
try {
|
|
359
|
+
if (!(await updateMediaAsset(asset.id, { pendingDocumentIds: [documentId] }))) {
|
|
360
|
+
throw new Error('Media asset was removed before its evidence could be published.');
|
|
361
|
+
}
|
|
362
|
+
const doc = await addDocument({
|
|
363
|
+
id: documentId,
|
|
364
|
+
title: asset.fileName,
|
|
365
|
+
content: caption,
|
|
366
|
+
source: 'media',
|
|
367
|
+
url: `/api/media/${asset.id}`,
|
|
368
|
+
metadata: {
|
|
369
|
+
mediaAssetId: asset.id,
|
|
370
|
+
mediaType: 'image',
|
|
371
|
+
fileName: asset.fileName,
|
|
372
|
+
mimeType: asset.mimeType,
|
|
373
|
+
fileSize: asset.fileSize,
|
|
374
|
+
dimensions: asset.dimensions,
|
|
375
|
+
images: [
|
|
376
|
+
{
|
|
377
|
+
imageUrl: `/api/media/${asset.id}`,
|
|
378
|
+
pageNumber: 1,
|
|
379
|
+
index: 0,
|
|
380
|
+
},
|
|
381
|
+
],
|
|
382
|
+
},
|
|
383
|
+
});
|
|
384
|
+
await reportStage('index', {
|
|
385
|
+
status: 'running',
|
|
386
|
+
percent: 0,
|
|
387
|
+
message: 'Building the searchable index...',
|
|
388
|
+
});
|
|
389
|
+
indexAttempted = true;
|
|
390
|
+
await ensureSearchable((current, total, message) =>
|
|
391
|
+
reportStage('index', { status: 'running', current, total, unit: 'chunks', message }),
|
|
392
|
+
);
|
|
393
|
+
await reportStage('index', {
|
|
394
|
+
status: 'completed',
|
|
395
|
+
message: 'Image is searchable.',
|
|
396
|
+
});
|
|
397
|
+
const publishedAsset = await updateMediaAsset(asset.id, {
|
|
398
|
+
processingStatus: 'completed',
|
|
399
|
+
processingProgress: 100,
|
|
400
|
+
processingMessage: undefined,
|
|
401
|
+
caption,
|
|
402
|
+
documentIds: [doc.id],
|
|
403
|
+
pendingDocumentIds: [],
|
|
404
|
+
supersededDocumentIds: asset.documentIds,
|
|
405
|
+
});
|
|
406
|
+
if (!publishedAsset) {
|
|
407
|
+
throw new Error('Media asset was removed before indexing completed.');
|
|
408
|
+
}
|
|
409
|
+
if (await cleanupDocumentRecords(asset.documentIds)) {
|
|
410
|
+
await updateMediaAsset(asset.id, { supersededDocumentIds: [] }).catch((error) =>
|
|
411
|
+
console.error('Failed to clear superseded image document IDs:', error),
|
|
412
|
+
);
|
|
413
|
+
}
|
|
414
|
+
} catch (error) {
|
|
415
|
+
await rollbackPendingDocuments(asset.id, [documentId], indexAttempted);
|
|
416
|
+
throw error;
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
/* ------------------------------------------------------------------ */
|
|
421
|
+
/* Video/Audio processing (requires marketplace tool) */
|
|
422
|
+
/* ------------------------------------------------------------------ */
|
|
423
|
+
|
|
424
|
+
async function processMediaWithTool(
|
|
425
|
+
asset: MediaAsset,
|
|
426
|
+
reqUrl: string,
|
|
427
|
+
reportStage: StageReporter,
|
|
428
|
+
sourceTranscript?: {
|
|
429
|
+
chunks: any[];
|
|
430
|
+
fullText: string;
|
|
431
|
+
durationSecs: number;
|
|
432
|
+
language?: string;
|
|
433
|
+
origin?: { kind?: string; provider?: string; language?: string };
|
|
434
|
+
},
|
|
435
|
+
serverId?: string,
|
|
436
|
+
): Promise<void> {
|
|
437
|
+
const tool = await loadTool<any>('video-audio');
|
|
438
|
+
if (!tool) {
|
|
439
|
+
throw new Error('Failed to load Video & Audio tool');
|
|
440
|
+
}
|
|
441
|
+
await cleanupIncompleteMediaPublication(asset);
|
|
442
|
+
|
|
443
|
+
const storage = createStorageProvider();
|
|
444
|
+
|
|
445
|
+
// Process local media in place so multi-hour files are not duplicated in
|
|
446
|
+
// Node.js memory. Other storage providers retain the buffered fallback.
|
|
447
|
+
const { promises: fs } = await import('node:fs');
|
|
448
|
+
const path = await import('node:path');
|
|
449
|
+
const os = await import('node:os');
|
|
450
|
+
|
|
451
|
+
const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), 'larkup-media-'));
|
|
452
|
+
const ext = asset.fileName.split('.').pop() || 'tmp';
|
|
453
|
+
const localFile = await storage.resolvePath?.(asset.storageUri);
|
|
454
|
+
const tmpFile = localFile || path.join(tmpDir, `input.${ext}`);
|
|
455
|
+
if (!localFile) {
|
|
456
|
+
await fs.writeFile(tmpFile, await storage.retrieve(asset.storageUri));
|
|
457
|
+
}
|
|
458
|
+
const documentIds: string[] = [];
|
|
459
|
+
let published = false;
|
|
460
|
+
let indexAttempted = false;
|
|
461
|
+
|
|
462
|
+
try {
|
|
463
|
+
const installedTool = await getInstalledTool('video-audio');
|
|
464
|
+
const globalConfig = await readConfig();
|
|
465
|
+
const toolConfig = globalConfig.toolConfigs?.['video-audio'] || {};
|
|
466
|
+
const provider = typeof toolConfig.audioProvider === 'string' ? toolConfig.audioProvider : '';
|
|
467
|
+
const apiKey = typeof toolConfig.audioApiKey === 'string' ? toolConfig.audioApiKey : '';
|
|
468
|
+
if (!provider) {
|
|
469
|
+
throw new Error(
|
|
470
|
+
'Choose an Audio Provider in Settings → Marketplace Tools → Video & Audio before indexing media.',
|
|
471
|
+
);
|
|
472
|
+
}
|
|
473
|
+
if (provider !== 'local' && !apiKey) {
|
|
474
|
+
throw new Error(
|
|
475
|
+
'Add the API key for the selected Audio Provider in Settings → Marketplace Tools → Video & Audio.',
|
|
476
|
+
);
|
|
477
|
+
}
|
|
478
|
+
const frameIntervalSecs = Math.max(5, Number(installedTool?.config?.frameInterval ?? 30) || 30);
|
|
479
|
+
const language =
|
|
480
|
+
typeof toolConfig.audioLanguage === 'string' ? toolConfig.audioLanguage : 'auto';
|
|
481
|
+
const effectiveLanguage =
|
|
482
|
+
language.trim().toLowerCase() === 'auto' && sourceTranscript?.language
|
|
483
|
+
? sourceTranscript.language
|
|
484
|
+
: language;
|
|
485
|
+
const localUrl = `/api/media/${asset.id}`;
|
|
486
|
+
|
|
487
|
+
const limits = getConcurrencyLimits();
|
|
488
|
+
|
|
489
|
+
if (asset.type === 'video' && tool.processVideo) {
|
|
490
|
+
const sourceKind = sourceTranscript?.origin?.kind;
|
|
491
|
+
const hasManualSourceTranscript =
|
|
492
|
+
Boolean(sourceTranscript?.chunks?.length) && sourceKind !== 'youtube-auto';
|
|
493
|
+
await reportStage('extract', {
|
|
494
|
+
status: 'running',
|
|
495
|
+
percent: 0,
|
|
496
|
+
message: `Extracting adaptive frames and audio (${limits.ffmpegThreads} FFmpeg threads)...`,
|
|
497
|
+
});
|
|
498
|
+
const result = await tool.processVideo(tmpFile, {
|
|
499
|
+
outputDir: tmpDir,
|
|
500
|
+
frameIntervalSecs,
|
|
501
|
+
maxFrames: 600,
|
|
502
|
+
threads: limits.ffmpegThreads,
|
|
503
|
+
parallelExtraction: limits.canParallelizeFfmpeg,
|
|
504
|
+
// Manual captions can be authoritative. Automatic captions remain a
|
|
505
|
+
// fallback and must not silently bypass the configured audio provider.
|
|
506
|
+
skipAudioExtraction: hasManualSourceTranscript,
|
|
507
|
+
onProgress: (value: number) => {
|
|
508
|
+
void reportStage('extract', {
|
|
509
|
+
status: 'running',
|
|
510
|
+
percent: Math.round(Math.max(0, Math.min(1, value)) * 100),
|
|
511
|
+
message: `Extracting adaptive frames and audio (${Math.round(value * 100)}%)...`,
|
|
512
|
+
}).catch(() => {});
|
|
513
|
+
},
|
|
514
|
+
});
|
|
515
|
+
await reportStage('extract', {
|
|
516
|
+
status: 'completed',
|
|
517
|
+
current: result.frames.length,
|
|
518
|
+
total: result.frames.length,
|
|
519
|
+
unit: 'frames',
|
|
520
|
+
message: `Extracted ${result.frames.length} adaptive frames and the audio track.`,
|
|
521
|
+
});
|
|
522
|
+
|
|
523
|
+
let transcriptPromise: Promise<any | null> = Promise.resolve(
|
|
524
|
+
hasManualSourceTranscript ? sourceTranscript : null,
|
|
525
|
+
);
|
|
526
|
+
|
|
527
|
+
// Process audio transcript
|
|
528
|
+
if (hasManualSourceTranscript) {
|
|
529
|
+
await reportStage('transcribe', {
|
|
530
|
+
status: 'completed',
|
|
531
|
+
current: sourceTranscript?.chunks.length,
|
|
532
|
+
total: sourceTranscript?.chunks.length,
|
|
533
|
+
unit: 'caption sections',
|
|
534
|
+
message: 'Using timestamped manual source captions.',
|
|
535
|
+
});
|
|
536
|
+
} else if (result.audioPath && tool.processAudio) {
|
|
537
|
+
transcriptPromise = (async () => {
|
|
538
|
+
await reportStage('transcribe', {
|
|
539
|
+
status: 'running',
|
|
540
|
+
percent: 0,
|
|
541
|
+
message: `Transcribing with ${formatProviderName(provider)}...`,
|
|
542
|
+
});
|
|
543
|
+
try {
|
|
544
|
+
const providerTranscript = await tool.processAudio(result.audioPath, {
|
|
545
|
+
provider,
|
|
546
|
+
apiKey,
|
|
547
|
+
language: effectiveLanguage,
|
|
548
|
+
context: asset.fileName,
|
|
549
|
+
onProgress: (current: number, total: number, message: string, unit?: string) => {
|
|
550
|
+
void reportStage('transcribe', {
|
|
551
|
+
status: 'running',
|
|
552
|
+
current,
|
|
553
|
+
total,
|
|
554
|
+
unit: unit || 'audio parts',
|
|
555
|
+
message:
|
|
556
|
+
message ||
|
|
557
|
+
`Transcribing part ${Math.min(
|
|
558
|
+
current,
|
|
559
|
+
total,
|
|
560
|
+
)} of ${total} with ${formatProviderName(provider)}...`,
|
|
561
|
+
}).catch(() => {});
|
|
562
|
+
},
|
|
563
|
+
});
|
|
564
|
+
await reportStage('transcribe', {
|
|
565
|
+
status: 'completed',
|
|
566
|
+
message: `Transcription complete with ${formatProviderName(provider)} (${
|
|
567
|
+
providerTranscript.chunks?.length ?? 0
|
|
568
|
+
} timestamped sections).`,
|
|
569
|
+
});
|
|
570
|
+
return providerTranscript;
|
|
571
|
+
} catch (error) {
|
|
572
|
+
if (sourceKind === 'youtube-auto' && sourceTranscript?.chunks?.length) {
|
|
573
|
+
console.warn(
|
|
574
|
+
`Configured ${formatProviderName(
|
|
575
|
+
provider,
|
|
576
|
+
)} transcription failed; using YouTube automatic captions as fallback.`,
|
|
577
|
+
error,
|
|
578
|
+
);
|
|
579
|
+
await reportStage('transcribe', {
|
|
580
|
+
status: 'completed',
|
|
581
|
+
message: `Provider transcription failed; using ${sourceTranscript.chunks.length} YouTube automatic-caption sections as fallback.`,
|
|
582
|
+
});
|
|
583
|
+
return sourceTranscript;
|
|
584
|
+
}
|
|
585
|
+
throw error;
|
|
586
|
+
}
|
|
587
|
+
})();
|
|
588
|
+
} else if (sourceTranscript?.chunks?.length) {
|
|
589
|
+
await reportStage('transcribe', {
|
|
590
|
+
status: 'completed',
|
|
591
|
+
current: sourceTranscript.chunks.length,
|
|
592
|
+
total: sourceTranscript.chunks.length,
|
|
593
|
+
unit: 'caption sections',
|
|
594
|
+
message: 'Using source captions because the video has no extractable audio track.',
|
|
595
|
+
});
|
|
596
|
+
transcriptPromise = Promise.resolve(sourceTranscript);
|
|
597
|
+
} else {
|
|
598
|
+
await reportStage('transcribe', {
|
|
599
|
+
status: 'skipped',
|
|
600
|
+
message: 'No audio track or source captions were available.',
|
|
601
|
+
});
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
// Analyze consecutive frames together so the vision model can infer
|
|
605
|
+
// actions, transitions, and persistent on-screen text rather than seeing
|
|
606
|
+
// every frame as an unrelated image.
|
|
607
|
+
const scenePromise = (async () => {
|
|
608
|
+
const extractedFrames = result.frames as { path: string; timestampSecs: number }[];
|
|
609
|
+
const analysisWindowSecs = visualAnalysisWindow(result.meta.durationSecs);
|
|
610
|
+
const frameGroups = groupFramesByWindow(extractedFrames, analysisWindowSecs, 6);
|
|
611
|
+
if (frameGroups.length === 0) {
|
|
612
|
+
await reportStage('vision', {
|
|
613
|
+
status: 'skipped',
|
|
614
|
+
message: 'No readable video frames were extracted.',
|
|
615
|
+
});
|
|
616
|
+
return [];
|
|
617
|
+
}
|
|
618
|
+
await reportStage('vision', {
|
|
619
|
+
status: 'running',
|
|
620
|
+
current: 0,
|
|
621
|
+
total: frameGroups.length,
|
|
622
|
+
unit: 'sequences',
|
|
623
|
+
message: `Understanding 0 of ${frameGroups.length} visual sequences...`,
|
|
624
|
+
});
|
|
625
|
+
let analyzed = 0;
|
|
626
|
+
const descriptions = await mapConcurrent(
|
|
627
|
+
frameGroups,
|
|
628
|
+
limits.apiConcurrency,
|
|
629
|
+
async (frames: { path: string; timestampSecs: number }[]) => {
|
|
630
|
+
const base64Images = await Promise.all(
|
|
631
|
+
frames.map(async (frame) => (await fs.readFile(frame.path)).toString('base64')),
|
|
632
|
+
);
|
|
633
|
+
const startSecs = frames[0].timestampSecs;
|
|
634
|
+
const endSecs = Math.min(
|
|
635
|
+
result.meta.durationSecs,
|
|
636
|
+
Math.max(startSecs + 1, frames.at(-1)!.timestampSecs + frameIntervalSecs),
|
|
637
|
+
);
|
|
638
|
+
const timestamps = frames.map((frame) => formatTime(frame.timestampSecs)).join(', ');
|
|
639
|
+
const descRes = await fetchWithRetry(
|
|
640
|
+
scopedApiUrl('/api/describe-image', reqUrl, serverId),
|
|
641
|
+
{
|
|
642
|
+
method: 'POST',
|
|
643
|
+
headers: { 'Content-Type': 'application/json' },
|
|
644
|
+
body: JSON.stringify({
|
|
645
|
+
base64Images,
|
|
646
|
+
prompt: `These are chronological frames from "${asset.fileName}" at ${timestamps}.
|
|
647
|
+
Write one evidence note for this time range. Track people, actions, interactions, state changes,
|
|
648
|
+
important objects, and exact meaningful on-screen text. Perform careful OCR, including Arabic and
|
|
649
|
+
other right-to-left text without reversing labels. For scoreboards or result animations, compare
|
|
650
|
+
frames in timestamp order and report the latest visible score as the current/final state; associate
|
|
651
|
+
each number with the correct nearby team/person label. Record a winner or result only when visually
|
|
652
|
+
supported. Omit boilerplate about facts that are not shown. Be factual, information-dense, and
|
|
653
|
+
concise.`,
|
|
654
|
+
}),
|
|
655
|
+
},
|
|
656
|
+
);
|
|
657
|
+
analyzed++;
|
|
658
|
+
const progressStep = Math.max(1, Math.ceil(frameGroups.length / 100));
|
|
659
|
+
if (analyzed % progressStep === 0 || analyzed === frameGroups.length) {
|
|
660
|
+
void reportStage('vision', {
|
|
661
|
+
status: 'running',
|
|
662
|
+
current: analyzed,
|
|
663
|
+
total: frameGroups.length,
|
|
664
|
+
unit: 'sequences',
|
|
665
|
+
message: `Understanding visual sequence ${analyzed} of ${frameGroups.length}...`,
|
|
666
|
+
}).catch(() => {});
|
|
667
|
+
}
|
|
668
|
+
if (!descRes.ok) {
|
|
669
|
+
let detail = '';
|
|
670
|
+
try {
|
|
671
|
+
const errorBody = (await descRes.json()) as { error?: string };
|
|
672
|
+
detail = errorBody.error?.trim() || '';
|
|
673
|
+
} catch {
|
|
674
|
+
// Keep the status-only fallback for non-JSON failures.
|
|
675
|
+
}
|
|
676
|
+
throw new Error(
|
|
677
|
+
`Visual sequence analysis failed (${descRes.status})${
|
|
678
|
+
detail ? `: ${detail}` : '.'
|
|
679
|
+
}`,
|
|
680
|
+
);
|
|
681
|
+
}
|
|
682
|
+
const { description } = (await descRes.json()) as { description?: string };
|
|
683
|
+
return description
|
|
684
|
+
? { text: description, startSecs, endSecs: Math.max(startSecs + 1, endSecs) }
|
|
685
|
+
: null;
|
|
686
|
+
},
|
|
687
|
+
);
|
|
688
|
+
await reportStage('vision', {
|
|
689
|
+
status: 'completed',
|
|
690
|
+
current: frameGroups.length,
|
|
691
|
+
total: frameGroups.length,
|
|
692
|
+
unit: 'sequences',
|
|
693
|
+
message: `Understood ${frameGroups.length} visual sequences with OCR.`,
|
|
694
|
+
});
|
|
695
|
+
return descriptions;
|
|
696
|
+
})();
|
|
697
|
+
|
|
698
|
+
const [transcript, sceneDescriptions] = await Promise.all([transcriptPromise, scenePromise]);
|
|
699
|
+
|
|
700
|
+
const validScenes = sceneDescriptions.filter(
|
|
701
|
+
(scene): scene is NonNullable<typeof scene> => scene !== null,
|
|
702
|
+
);
|
|
703
|
+
const segments = tool.buildMultimodalSegments(
|
|
704
|
+
transcript?.chunks ?? [],
|
|
705
|
+
validScenes,
|
|
706
|
+
result.meta.durationSecs,
|
|
707
|
+
visualAnalysisWindow(result.meta.durationSecs),
|
|
708
|
+
) as MediaEvidenceSegment[];
|
|
709
|
+
|
|
710
|
+
if (segments.length === 0) {
|
|
711
|
+
throw new Error('No searchable speech or visual evidence was produced from this video.');
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
await reportStage('synthesize', {
|
|
715
|
+
status: 'running',
|
|
716
|
+
percent: 0,
|
|
717
|
+
message: 'Creating human-style notes across the complete video...',
|
|
718
|
+
});
|
|
719
|
+
let summary: string;
|
|
720
|
+
try {
|
|
721
|
+
summary = await createMediaKnowledgeSummary({
|
|
722
|
+
title: asset.fileName,
|
|
723
|
+
mediaType: 'video',
|
|
724
|
+
durationSecs: result.meta.durationSecs,
|
|
725
|
+
segments,
|
|
726
|
+
config: globalConfig,
|
|
727
|
+
onProgress: (completed, total, message) =>
|
|
728
|
+
reportStage('synthesize', {
|
|
729
|
+
status: 'running',
|
|
730
|
+
current: completed,
|
|
731
|
+
total,
|
|
732
|
+
unit: 'note passes',
|
|
733
|
+
message,
|
|
734
|
+
}),
|
|
735
|
+
});
|
|
736
|
+
await reportStage('synthesize', {
|
|
737
|
+
status: 'completed',
|
|
738
|
+
message: 'Connected the complete timeline into searchable notes.',
|
|
739
|
+
});
|
|
740
|
+
} catch (error) {
|
|
741
|
+
console.error('Video evidence synthesis failed; preserving timestamped evidence:', error);
|
|
742
|
+
summary = createFallbackMediaSummary(asset.fileName, 'video', segments);
|
|
743
|
+
await reportStage('synthesize', {
|
|
744
|
+
status: 'completed',
|
|
745
|
+
message: 'Saved timeline notes; the optional consolidation pass was unavailable.',
|
|
746
|
+
});
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
const transcriptSource = transcript?.origin?.kind || 'provider-stt';
|
|
750
|
+
const documentInputs = buildMediaDocumentInputs({
|
|
751
|
+
assetId: asset.id,
|
|
752
|
+
title: asset.fileName,
|
|
753
|
+
mediaType: 'video',
|
|
754
|
+
localUrl,
|
|
755
|
+
originalUrl: asset.originalUrl,
|
|
756
|
+
durationSecs: result.meta.durationSecs,
|
|
757
|
+
summary,
|
|
758
|
+
segments,
|
|
759
|
+
fileName: asset.fileName,
|
|
760
|
+
mimeType: asset.mimeType,
|
|
761
|
+
transcriptSource,
|
|
762
|
+
transcriptProvider: transcript?.origin?.provider || provider,
|
|
763
|
+
transcriptLanguage: transcript?.language,
|
|
764
|
+
}).map((input) => ({ ...input, id: randomUUID() }));
|
|
765
|
+
documentIds.push(...documentInputs.map((input) => input.id));
|
|
766
|
+
if (!(await updateMediaAsset(asset.id, { pendingDocumentIds: documentIds }))) {
|
|
767
|
+
throw new Error('Media asset was removed before its evidence could be published.');
|
|
768
|
+
}
|
|
769
|
+
const documents = await addDocuments(documentInputs);
|
|
770
|
+
|
|
771
|
+
await reportStage('index', {
|
|
772
|
+
status: 'running',
|
|
773
|
+
percent: 0,
|
|
774
|
+
message: `Indexing ${documents.length} media documents...`,
|
|
775
|
+
});
|
|
776
|
+
indexAttempted = true;
|
|
777
|
+
await ensureSearchable(
|
|
778
|
+
(current, total, message) =>
|
|
779
|
+
reportStage('index', {
|
|
780
|
+
status: 'running',
|
|
781
|
+
current,
|
|
782
|
+
total,
|
|
783
|
+
unit: 'chunks',
|
|
784
|
+
message,
|
|
785
|
+
}),
|
|
786
|
+
provider,
|
|
787
|
+
);
|
|
788
|
+
await reportStage('index', {
|
|
789
|
+
status: 'completed',
|
|
790
|
+
message: 'Video timeline and notes are searchable.',
|
|
791
|
+
});
|
|
792
|
+
const publishedAsset = await updateMediaAsset(asset.id, {
|
|
793
|
+
processingStatus: 'completed',
|
|
794
|
+
caption: summary.slice(0, 600),
|
|
795
|
+
durationSecs: result.meta.durationSecs,
|
|
796
|
+
dimensions: { width: result.meta.width, height: result.meta.height },
|
|
797
|
+
documentIds,
|
|
798
|
+
pendingDocumentIds: [],
|
|
799
|
+
supersededDocumentIds: asset.documentIds,
|
|
800
|
+
processingProgress: 100,
|
|
801
|
+
processingMessage: undefined,
|
|
802
|
+
});
|
|
803
|
+
if (!publishedAsset) {
|
|
804
|
+
throw new Error('Media asset was removed before indexing completed.');
|
|
805
|
+
}
|
|
806
|
+
published = true;
|
|
807
|
+
if (await cleanupDocumentRecords(asset.documentIds)) {
|
|
808
|
+
await updateMediaAsset(asset.id, { supersededDocumentIds: [] }).catch((error) =>
|
|
809
|
+
console.error('Failed to clear superseded video document IDs:', error),
|
|
810
|
+
);
|
|
811
|
+
}
|
|
812
|
+
await trackMediaProcessing('video', result.meta.durationSecs, result.frames.length, provider);
|
|
813
|
+
} else if (asset.type === 'audio' && tool.processAudio) {
|
|
814
|
+
await Promise.all([
|
|
815
|
+
reportStage('extract', { status: 'skipped', message: 'No video frames to extract.' }),
|
|
816
|
+
reportStage('vision', { status: 'skipped', message: 'Audio-only media.' }),
|
|
817
|
+
]);
|
|
818
|
+
await reportStage('transcribe', {
|
|
819
|
+
status: 'running',
|
|
820
|
+
percent: 0,
|
|
821
|
+
message: `Transcribing with ${formatProviderName(provider)}...`,
|
|
822
|
+
});
|
|
823
|
+
const transcript = await tool.processAudio(tmpFile, {
|
|
824
|
+
provider,
|
|
825
|
+
apiKey,
|
|
826
|
+
language: effectiveLanguage,
|
|
827
|
+
context: asset.fileName,
|
|
828
|
+
onProgress: (current: number, total: number, message: string, unit?: string) =>
|
|
829
|
+
reportStage('transcribe', {
|
|
830
|
+
status: 'running',
|
|
831
|
+
current,
|
|
832
|
+
total,
|
|
833
|
+
unit: unit || 'audio parts',
|
|
834
|
+
message:
|
|
835
|
+
message || `Transcribing audio part ${Math.min(current, total)} of ${total}...`,
|
|
836
|
+
}),
|
|
837
|
+
});
|
|
838
|
+
await reportStage('transcribe', {
|
|
839
|
+
status: 'completed',
|
|
840
|
+
message: `Transcription complete with ${formatProviderName(provider)} (${
|
|
841
|
+
transcript.chunks.length
|
|
842
|
+
} timestamped sections).`,
|
|
843
|
+
});
|
|
844
|
+
const segments = tool.buildMultimodalSegments(
|
|
845
|
+
transcript.chunks,
|
|
846
|
+
[],
|
|
847
|
+
transcript.durationSecs,
|
|
848
|
+
60,
|
|
849
|
+
) as MediaEvidenceSegment[];
|
|
850
|
+
if (segments.length === 0) {
|
|
851
|
+
throw new Error('The transcription completed without searchable speech.');
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
await reportStage('synthesize', {
|
|
855
|
+
status: 'running',
|
|
856
|
+
percent: 0,
|
|
857
|
+
message: 'Creating human-style notes across the complete recording...',
|
|
858
|
+
});
|
|
859
|
+
let summary: string;
|
|
860
|
+
try {
|
|
861
|
+
summary = await createMediaKnowledgeSummary({
|
|
862
|
+
title: asset.fileName,
|
|
863
|
+
mediaType: 'audio',
|
|
864
|
+
durationSecs: transcript.durationSecs,
|
|
865
|
+
segments,
|
|
866
|
+
config: globalConfig,
|
|
867
|
+
onProgress: (completed, total, message) =>
|
|
868
|
+
reportStage('synthesize', {
|
|
869
|
+
status: 'running',
|
|
870
|
+
current: completed,
|
|
871
|
+
total,
|
|
872
|
+
unit: 'note passes',
|
|
873
|
+
message,
|
|
874
|
+
}),
|
|
875
|
+
});
|
|
876
|
+
await reportStage('synthesize', {
|
|
877
|
+
status: 'completed',
|
|
878
|
+
message: 'Connected the complete transcript into searchable notes.',
|
|
879
|
+
});
|
|
880
|
+
} catch (error) {
|
|
881
|
+
console.error('Audio evidence synthesis failed; preserving timestamped evidence:', error);
|
|
882
|
+
summary = createFallbackMediaSummary(asset.fileName, 'audio', segments);
|
|
883
|
+
await reportStage('synthesize', {
|
|
884
|
+
status: 'completed',
|
|
885
|
+
message: 'Saved timeline notes; the optional consolidation pass was unavailable.',
|
|
886
|
+
});
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
const documentInputs = buildMediaDocumentInputs({
|
|
890
|
+
assetId: asset.id,
|
|
891
|
+
title: asset.fileName,
|
|
892
|
+
mediaType: 'audio',
|
|
893
|
+
localUrl,
|
|
894
|
+
originalUrl: asset.originalUrl,
|
|
895
|
+
durationSecs: transcript.durationSecs,
|
|
896
|
+
summary,
|
|
897
|
+
segments,
|
|
898
|
+
fileName: asset.fileName,
|
|
899
|
+
mimeType: asset.mimeType,
|
|
900
|
+
transcriptSource: transcript?.origin?.kind || 'provider-stt',
|
|
901
|
+
transcriptProvider: transcript?.origin?.provider || provider,
|
|
902
|
+
transcriptLanguage: transcript.language,
|
|
903
|
+
}).map((input) => ({ ...input, id: randomUUID() }));
|
|
904
|
+
documentIds.push(...documentInputs.map((input) => input.id));
|
|
905
|
+
if (!(await updateMediaAsset(asset.id, { pendingDocumentIds: documentIds }))) {
|
|
906
|
+
throw new Error('Media asset was removed before its evidence could be published.');
|
|
907
|
+
}
|
|
908
|
+
const documents = await addDocuments(documentInputs);
|
|
909
|
+
|
|
910
|
+
await reportStage('index', {
|
|
911
|
+
status: 'running',
|
|
912
|
+
percent: 0,
|
|
913
|
+
message: `Indexing ${documents.length} media documents...`,
|
|
914
|
+
});
|
|
915
|
+
indexAttempted = true;
|
|
916
|
+
await ensureSearchable(
|
|
917
|
+
(current, total, message) =>
|
|
918
|
+
reportStage('index', {
|
|
919
|
+
status: 'running',
|
|
920
|
+
current,
|
|
921
|
+
total,
|
|
922
|
+
unit: 'chunks',
|
|
923
|
+
message,
|
|
924
|
+
}),
|
|
925
|
+
provider,
|
|
926
|
+
);
|
|
927
|
+
await reportStage('index', {
|
|
928
|
+
status: 'completed',
|
|
929
|
+
message: 'Audio transcript and notes are searchable.',
|
|
930
|
+
});
|
|
931
|
+
const publishedAsset = await updateMediaAsset(asset.id, {
|
|
932
|
+
processingStatus: 'completed',
|
|
933
|
+
caption: summary.slice(0, 600),
|
|
934
|
+
durationSecs: transcript.durationSecs,
|
|
935
|
+
documentIds,
|
|
936
|
+
pendingDocumentIds: [],
|
|
937
|
+
supersededDocumentIds: asset.documentIds,
|
|
938
|
+
processingProgress: 100,
|
|
939
|
+
processingMessage: undefined,
|
|
940
|
+
});
|
|
941
|
+
if (!publishedAsset) {
|
|
942
|
+
throw new Error('Media asset was removed before indexing completed.');
|
|
943
|
+
}
|
|
944
|
+
published = true;
|
|
945
|
+
if (await cleanupDocumentRecords(asset.documentIds)) {
|
|
946
|
+
await updateMediaAsset(asset.id, { supersededDocumentIds: [] }).catch((error) =>
|
|
947
|
+
console.error('Failed to clear superseded audio document IDs:', error),
|
|
948
|
+
);
|
|
949
|
+
}
|
|
950
|
+
await trackMediaProcessing('audio', transcript.durationSecs, 0, provider);
|
|
951
|
+
}
|
|
952
|
+
} catch (error) {
|
|
953
|
+
if (!published) {
|
|
954
|
+
await rollbackPendingDocuments(asset.id, documentIds, indexAttempted);
|
|
955
|
+
}
|
|
956
|
+
throw error;
|
|
957
|
+
} finally {
|
|
958
|
+
// Clean up temp files
|
|
959
|
+
await fs.rm(tmpDir, { recursive: true, force: true }).catch(() => {});
|
|
960
|
+
}
|
|
961
|
+
}
|
|
962
|
+
|
|
963
|
+
function visualAnalysisWindow(durationSecs: number): number {
|
|
964
|
+
if (durationSecs >= 4 * 60 * 60) return 15 * 60;
|
|
965
|
+
if (durationSecs > 60 * 60) return 5 * 60;
|
|
966
|
+
return 60;
|
|
967
|
+
}
|
|
968
|
+
|
|
969
|
+
function scopedApiUrl(pathname: string, requestUrl: string, serverId?: string): string {
|
|
970
|
+
const url = new URL(pathname, requestUrl);
|
|
971
|
+
if (serverId) url.searchParams.set('serverId', serverId);
|
|
972
|
+
return url.toString();
|
|
973
|
+
}
|
|
974
|
+
|
|
975
|
+
async function mapConcurrent<T, R>(
|
|
976
|
+
items: T[],
|
|
977
|
+
limit: number,
|
|
978
|
+
fn: (item: T, index: number) => Promise<R>,
|
|
979
|
+
): Promise<R[]> {
|
|
980
|
+
const results = new Array<R>(items.length);
|
|
981
|
+
let next = 0;
|
|
982
|
+
await Promise.all(
|
|
983
|
+
Array.from({ length: Math.min(limit, items.length) }, async () => {
|
|
984
|
+
while (next < items.length) {
|
|
985
|
+
const index = next++;
|
|
986
|
+
results[index] = await fn(items[index], index);
|
|
987
|
+
}
|
|
988
|
+
}),
|
|
989
|
+
);
|
|
990
|
+
return results;
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
function groupFramesByWindow<T extends { timestampSecs: number }>(
|
|
994
|
+
frames: T[],
|
|
995
|
+
windowSecs: number,
|
|
996
|
+
maxImages: number,
|
|
997
|
+
): T[][] {
|
|
998
|
+
const groups: T[][] = [];
|
|
999
|
+
for (const frame of frames) {
|
|
1000
|
+
const current = groups.at(-1);
|
|
1001
|
+
if (
|
|
1002
|
+
!current ||
|
|
1003
|
+
current.length >= maxImages ||
|
|
1004
|
+
frame.timestampSecs - current[0].timestampSecs >= windowSecs
|
|
1005
|
+
) {
|
|
1006
|
+
groups.push([frame]);
|
|
1007
|
+
} else {
|
|
1008
|
+
current.push(frame);
|
|
1009
|
+
}
|
|
1010
|
+
}
|
|
1011
|
+
return groups;
|
|
1012
|
+
}
|
|
1013
|
+
|
|
1014
|
+
// Serialize index updates from concurrent media workers. This keeps vector
|
|
1015
|
+
// writes bounded and guarantees an asset is only marked complete after its
|
|
1016
|
+
// timeline is actually searchable.
|
|
1017
|
+
let indexChain: Promise<void> = Promise.resolve();
|
|
1018
|
+
|
|
1019
|
+
function ensureSearchable(
|
|
1020
|
+
onProgress?: (current: number, total: number, message: string) => void | Promise<void>,
|
|
1021
|
+
transcriptionProvider?: string,
|
|
1022
|
+
): Promise<void> {
|
|
1023
|
+
const run = indexChain.then(async () => {
|
|
1024
|
+
const { readDocuments } = await import('@larkup/core/documents-store');
|
|
1025
|
+
const { createRun, runIndexer } = await import('@larkup/core/indexing/indexer');
|
|
1026
|
+
const { isRunning, readRun } = await import('@larkup/core/index-store');
|
|
1027
|
+
|
|
1028
|
+
while (await isRunning()) {
|
|
1029
|
+
await onProgress?.(0, 0, 'Waiting for the active search-index job...');
|
|
1030
|
+
await new Promise((resolve) => setTimeout(resolve, 1_000));
|
|
1031
|
+
}
|
|
1032
|
+
|
|
1033
|
+
const documents = await readDocuments();
|
|
1034
|
+
if (!documents.some((document) => document.status !== 'indexed')) {
|
|
1035
|
+
await onProgress?.(1, 1, 'Media is already searchable.');
|
|
1036
|
+
return;
|
|
1037
|
+
}
|
|
1038
|
+
|
|
1039
|
+
const config = await readConfig();
|
|
1040
|
+
const previousRun = await readRun();
|
|
1041
|
+
let nextRun;
|
|
1042
|
+
while (!nextRun) {
|
|
1043
|
+
try {
|
|
1044
|
+
nextRun = await createRun(config);
|
|
1045
|
+
} catch (error) {
|
|
1046
|
+
if (!(error instanceof Error) || !error.message.includes('already in progress'))
|
|
1047
|
+
throw error;
|
|
1048
|
+
await onProgress?.(0, 0, 'Waiting for the active search-index job...');
|
|
1049
|
+
await new Promise((resolve) => setTimeout(resolve, 1_000));
|
|
1050
|
+
}
|
|
1051
|
+
}
|
|
1052
|
+
await onProgress?.(
|
|
1053
|
+
0,
|
|
1054
|
+
0,
|
|
1055
|
+
`Building the searchable index with ${
|
|
1056
|
+
config.embeddingModelId || config.embeddingProvider
|
|
1057
|
+
}...`,
|
|
1058
|
+
);
|
|
1059
|
+
let indexingFinished = false;
|
|
1060
|
+
const indexing = runIndexer(
|
|
1061
|
+
nextRun.id,
|
|
1062
|
+
config,
|
|
1063
|
+
previousRun?.status === 'completed' ? previousRun : null,
|
|
1064
|
+
).finally(() => {
|
|
1065
|
+
indexingFinished = true;
|
|
1066
|
+
});
|
|
1067
|
+
while (!indexingFinished) {
|
|
1068
|
+
const activeRun = await readRun();
|
|
1069
|
+
if (activeRun?.id === nextRun.id) {
|
|
1070
|
+
const total = activeRun.totalChunks ?? 0;
|
|
1071
|
+
const current = activeRun.processedChunks ?? 0;
|
|
1072
|
+
const phase =
|
|
1073
|
+
activeRun.status === 'chunking'
|
|
1074
|
+
? 'Preparing searchable chunks'
|
|
1075
|
+
: activeRun.status === 'upserting'
|
|
1076
|
+
? 'Saving vectors'
|
|
1077
|
+
: 'Embedding media evidence';
|
|
1078
|
+
await onProgress?.(
|
|
1079
|
+
current,
|
|
1080
|
+
total,
|
|
1081
|
+
total > 0 ? `${phase}: ${current} of ${total} chunks...` : `${phase}...`,
|
|
1082
|
+
);
|
|
1083
|
+
}
|
|
1084
|
+
await Promise.race([indexing, new Promise<void>((resolve) => setTimeout(resolve, 750))]);
|
|
1085
|
+
}
|
|
1086
|
+
await indexing;
|
|
1087
|
+
|
|
1088
|
+
const completedRun = await readRun();
|
|
1089
|
+
if (completedRun?.id !== nextRun.id || completedRun.status !== 'completed') {
|
|
1090
|
+
throw describeSearchIndexFailure(
|
|
1091
|
+
completedRun?.error || 'Search indexing did not complete.',
|
|
1092
|
+
config,
|
|
1093
|
+
transcriptionProvider,
|
|
1094
|
+
);
|
|
1095
|
+
}
|
|
1096
|
+
await onProgress?.(
|
|
1097
|
+
completedRun.processedChunks,
|
|
1098
|
+
completedRun.totalChunks,
|
|
1099
|
+
`Media is searchable (${completedRun.processedChunks} chunks).`,
|
|
1100
|
+
);
|
|
1101
|
+
});
|
|
1102
|
+
|
|
1103
|
+
indexChain = run.catch(() => {});
|
|
1104
|
+
return run;
|
|
1105
|
+
}
|
|
1106
|
+
|
|
1107
|
+
function formatProviderName(provider: string): string {
|
|
1108
|
+
return provider === 'deepgram' ? 'Deepgram' : provider.replace(/_/g, ' ');
|
|
1109
|
+
}
|
|
1110
|
+
|
|
1111
|
+
function describeSearchIndexFailure(
|
|
1112
|
+
error: string,
|
|
1113
|
+
config: Awaited<ReturnType<typeof readConfig>>,
|
|
1114
|
+
transcriptionProvider?: string,
|
|
1115
|
+
): Error {
|
|
1116
|
+
const embeddingModel =
|
|
1117
|
+
config.embeddingModelId || config.embeddingProvider || 'your embedding model';
|
|
1118
|
+
if (/quota|billing|insufficient_quota/i.test(error)) {
|
|
1119
|
+
return new Error(
|
|
1120
|
+
`Transcription used ${formatProviderName(
|
|
1121
|
+
transcriptionProvider || 'the selected audio provider',
|
|
1122
|
+
)}. ` +
|
|
1123
|
+
`Semantic search then tried ${embeddingModel}, which has no available quota. ` +
|
|
1124
|
+
'Update the Embedding Model and API key in Settings → Models, then retry.',
|
|
1125
|
+
);
|
|
1126
|
+
}
|
|
1127
|
+
return new Error(error);
|
|
1128
|
+
}
|
|
1129
|
+
|
|
1130
|
+
async function deleteIndexedDocuments(documentIds: string[]): Promise<void> {
|
|
1131
|
+
if (documentIds.length === 0) return;
|
|
1132
|
+
const config = await readConfig();
|
|
1133
|
+
const adapter = await createVectorAdapter(config);
|
|
1134
|
+
await adapter.deleteByDocumentIds(documentIds);
|
|
1135
|
+
}
|
|
1136
|
+
|
|
1137
|
+
async function cleanupDocumentRecords(documentIds: string[]): Promise<boolean> {
|
|
1138
|
+
if (documentIds.length === 0) return true;
|
|
1139
|
+
try {
|
|
1140
|
+
await deleteIndexedDocuments(documentIds);
|
|
1141
|
+
await deleteDocuments(documentIds);
|
|
1142
|
+
return true;
|
|
1143
|
+
} catch (error) {
|
|
1144
|
+
console.error('Failed to remove tracked media documents:', error);
|
|
1145
|
+
return false;
|
|
1146
|
+
}
|
|
1147
|
+
}
|
|
1148
|
+
|
|
1149
|
+
async function cleanupIncompleteMediaPublication(asset: MediaAsset): Promise<void> {
|
|
1150
|
+
const trackedIds = [
|
|
1151
|
+
...new Set([...(asset.pendingDocumentIds ?? []), ...(asset.supersededDocumentIds ?? [])]),
|
|
1152
|
+
];
|
|
1153
|
+
if (trackedIds.length === 0) return;
|
|
1154
|
+
if (!(await cleanupDocumentRecords(trackedIds))) {
|
|
1155
|
+
throw new Error(
|
|
1156
|
+
'A previous media-index generation still needs cleanup. Restore the vector-store connection and retry.',
|
|
1157
|
+
);
|
|
1158
|
+
}
|
|
1159
|
+
await updateMediaAsset(asset.id, {
|
|
1160
|
+
pendingDocumentIds: [],
|
|
1161
|
+
supersededDocumentIds: [],
|
|
1162
|
+
});
|
|
1163
|
+
}
|
|
1164
|
+
|
|
1165
|
+
async function rollbackPendingDocuments(
|
|
1166
|
+
assetId: string,
|
|
1167
|
+
documentIds: string[],
|
|
1168
|
+
indexAttempted: boolean,
|
|
1169
|
+
): Promise<void> {
|
|
1170
|
+
if (documentIds.length === 0) return;
|
|
1171
|
+
if (!indexAttempted) {
|
|
1172
|
+
await deleteDocuments(documentIds).catch((error) =>
|
|
1173
|
+
console.error('Failed to remove unpublished media documents:', error),
|
|
1174
|
+
);
|
|
1175
|
+
await updateMediaAsset(assetId, { pendingDocumentIds: [] }).catch(() => {});
|
|
1176
|
+
return;
|
|
1177
|
+
}
|
|
1178
|
+
|
|
1179
|
+
if (await cleanupDocumentRecords(documentIds)) {
|
|
1180
|
+
await updateMediaAsset(assetId, { pendingDocumentIds: [] }).catch(() => {});
|
|
1181
|
+
} else {
|
|
1182
|
+
// Keep the IDs durably attached to the asset. A retry or deletion can then
|
|
1183
|
+
// remove partial vectors before publishing a new generation.
|
|
1184
|
+
await updateMediaAsset(assetId, { pendingDocumentIds: documentIds }).catch(() => {});
|
|
1185
|
+
}
|
|
1186
|
+
}
|
|
1187
|
+
|
|
1188
|
+
async function createVectorAdapter(config: Awaited<ReturnType<typeof readConfig>>) {
|
|
1189
|
+
const { createAdapter } = await import('@larkup/vector-stores/factory');
|
|
1190
|
+
return createAdapter(config);
|
|
1191
|
+
}
|
|
1192
|
+
|
|
1193
|
+
async function fetchWithRetry(
|
|
1194
|
+
url: string,
|
|
1195
|
+
init: RequestInit,
|
|
1196
|
+
timeoutMs = 90000,
|
|
1197
|
+
): Promise<Response> {
|
|
1198
|
+
let response: Response | undefined;
|
|
1199
|
+
let lastError: unknown;
|
|
1200
|
+
for (let attempt = 0; attempt < 4; attempt++) {
|
|
1201
|
+
const controller = new AbortController();
|
|
1202
|
+
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
|
|
1203
|
+
try {
|
|
1204
|
+
response = await fetch(url, { ...init, signal: controller.signal });
|
|
1205
|
+
clearTimeout(timeoutId);
|
|
1206
|
+
if (response.ok || (response.status !== 429 && response.status < 500)) return response;
|
|
1207
|
+
const retryAfterHeader = response.headers.get('retry-after');
|
|
1208
|
+
const retryAfter = retryAfterHeader ? Number(retryAfterHeader) : Number.NaN;
|
|
1209
|
+
await response.body?.cancel().catch(() => {});
|
|
1210
|
+
await new Promise((resolve) =>
|
|
1211
|
+
setTimeout(
|
|
1212
|
+
resolve,
|
|
1213
|
+
Number.isFinite(retryAfter) ? retryAfter * 1_000 : (attempt + 1) * 1_500,
|
|
1214
|
+
),
|
|
1215
|
+
);
|
|
1216
|
+
} catch (error) {
|
|
1217
|
+
clearTimeout(timeoutId);
|
|
1218
|
+
lastError = error;
|
|
1219
|
+
await new Promise((resolve) => setTimeout(resolve, (attempt + 1) * 1_500));
|
|
1220
|
+
}
|
|
1221
|
+
}
|
|
1222
|
+
if (response) return response;
|
|
1223
|
+
throw lastError instanceof Error ? lastError : new Error('Visual sequence request failed.');
|
|
1224
|
+
}
|
|
1225
|
+
|
|
1226
|
+
async function trackMediaProcessing(
|
|
1227
|
+
mediaType: 'video' | 'audio',
|
|
1228
|
+
durationSecs: number,
|
|
1229
|
+
frameCount: number,
|
|
1230
|
+
provider: string,
|
|
1231
|
+
) {
|
|
1232
|
+
const { trackUsageEvent } = await import('@larkup/core/analytics-store');
|
|
1233
|
+
void trackUsageEvent({
|
|
1234
|
+
type: 'media_processing',
|
|
1235
|
+
mediaType,
|
|
1236
|
+
modelId: provider === 'local' ? 'local-whisper' : provider,
|
|
1237
|
+
durationSecs,
|
|
1238
|
+
frameCount,
|
|
1239
|
+
estimatedCost: provider !== 'local' ? (durationSecs / 60) * 0.006 : 0,
|
|
1240
|
+
timestamp: new Date().toISOString(),
|
|
1241
|
+
});
|
|
1242
|
+
}
|