larkup 0.1.41 → 0.1.42
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.next/BUILD_ID +1 -1
- package/.next/build-manifest.json +3 -3
- package/.next/diagnostics/route-bundle-stats.json +21 -21
- package/.next/fallback-build-manifest.json +3 -3
- package/.next/required-server-files.js +1 -1
- package/.next/required-server-files.json +1 -1
- package/.next/server/app/_global-error.html +1 -1
- package/.next/server/app/_global-error.rsc +1 -1
- package/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/server/app/_not-found.html +1 -1
- package/.next/server/app/_not-found.rsc +18 -18
- package/.next/server/app/_not-found.segments/_full.segment.rsc +18 -18
- package/.next/server/app/_not-found.segments/_head.segment.rsc +4 -4
- package/.next/server/app/_not-found.segments/_index.segment.rsc +12 -12
- package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
- package/.next/server/app/_not-found.segments/_not-found.segment.rsc +3 -3
- package/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/analytics/page_client-reference-manifest.js +1 -1
- package/.next/server/app/analytics.html +1 -1
- package/.next/server/app/analytics.rsc +19 -19
- package/.next/server/app/analytics.segments/_full.segment.rsc +19 -19
- package/.next/server/app/analytics.segments/_head.segment.rsc +4 -4
- package/.next/server/app/analytics.segments/_index.segment.rsc +12 -12
- package/.next/server/app/analytics.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/analytics.segments/analytics/__PAGE__.segment.rsc +3 -3
- package/.next/server/app/analytics.segments/analytics.segment.rsc +3 -3
- package/.next/server/app/api/analytics/route.js.nft.json +1 -1
- package/.next/server/app/api/chat/route.js +1 -1
- package/.next/server/app/api/chat/route.js.nft.json +1 -1
- package/.next/server/app/api/chat/status/route.js.nft.json +1 -1
- package/.next/server/app/api/chat/suggestions/route.js.nft.json +1 -1
- package/.next/server/app/api/config/route.js.nft.json +1 -1
- package/.next/server/app/api/config/test/route.js.nft.json +1 -1
- package/.next/server/app/api/connections/route.js.nft.json +1 -1
- package/.next/server/app/api/connections/webhook/route.js.nft.json +1 -1
- package/.next/server/app/api/demo/route.js.nft.json +1 -1
- package/.next/server/app/api/deploy/cloud-project/route.js.nft.json +1 -1
- package/.next/server/app/api/deploy/ssh/route.js.nft.json +1 -1
- package/.next/server/app/api/deployment/blob-setup/route.js.nft.json +1 -1
- package/.next/server/app/api/deployment/config/route.js.nft.json +1 -1
- package/.next/server/app/api/describe-image/route.js.nft.json +1 -1
- package/.next/server/app/api/documents/route.js.nft.json +1 -1
- package/.next/server/app/api/firecrawl/local/route.js.nft.json +1 -1
- package/.next/server/app/api/index/route.js.nft.json +1 -1
- package/.next/server/app/api/jobs/[id]/route.js.nft.json +1 -1
- package/.next/server/app/api/jobs/route.js.nft.json +1 -1
- package/.next/server/app/api/media/[id]/route.js.nft.json +1 -1
- package/.next/server/app/api/media/process/route.js.nft.json +1 -1
- package/.next/server/app/api/media/route.js.nft.json +1 -1
- package/.next/server/app/api/media/stream/route.js.nft.json +1 -1
- package/.next/server/app/api/search/bing/route.js.nft.json +1 -1
- package/.next/server/app/api/search/brave/route.js.nft.json +1 -1
- package/.next/server/app/api/search/exa/route.js.nft.json +1 -1
- package/.next/server/app/api/search/google/route.js.nft.json +1 -1
- package/.next/server/app/api/search/route.js.nft.json +1 -1
- package/.next/server/app/api/search/tavily/route.js.nft.json +1 -1
- package/.next/server/app/api/server/agent/route.js.nft.json +1 -1
- package/.next/server/app/api/server/download/route.js.nft.json +1 -1
- package/.next/server/app/api/server/generate/route.js.nft.json +1 -1
- package/.next/server/app/api/server/local/route.js.nft.json +1 -1
- package/.next/server/app/api/servers/route.js.nft.json +1 -1
- package/.next/server/app/api/tabular/query/route.js.nft.json +1 -1
- package/.next/server/app/api/tabular/route.js.nft.json +1 -1
- package/.next/server/app/api/upload-file/route.js.nft.json +1 -1
- package/.next/server/app/api/uploads/[...slug]/route.js.nft.json +1 -1
- package/.next/server/app/chat/page_client-reference-manifest.js +1 -1
- package/.next/server/app/chat.html +1 -1
- package/.next/server/app/chat.rsc +19 -19
- package/.next/server/app/chat.segments/_full.segment.rsc +19 -19
- package/.next/server/app/chat.segments/_head.segment.rsc +4 -4
- package/.next/server/app/chat.segments/_index.segment.rsc +12 -12
- package/.next/server/app/chat.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/chat.segments/chat/__PAGE__.segment.rsc +3 -3
- package/.next/server/app/chat.segments/chat.segment.rsc +3 -3
- package/.next/server/app/data/page.js.nft.json +1 -1
- package/.next/server/app/data/page_client-reference-manifest.js +1 -1
- package/.next/server/app/data.html +1 -1
- package/.next/server/app/data.rsc +19 -19
- package/.next/server/app/data.segments/_full.segment.rsc +19 -19
- package/.next/server/app/data.segments/_head.segment.rsc +4 -4
- package/.next/server/app/data.segments/_index.segment.rsc +12 -12
- package/.next/server/app/data.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/data.segments/data/__PAGE__.segment.rsc +3 -3
- package/.next/server/app/data.segments/data.segment.rsc +3 -3
- package/.next/server/app/index.html +1 -1
- package/.next/server/app/index.rsc +17 -17
- package/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/.next/server/app/index.segments/_full.segment.rsc +17 -17
- package/.next/server/app/index.segments/_head.segment.rsc +4 -4
- package/.next/server/app/index.segments/_index.segment.rsc +12 -12
- package/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/server/app/settings/page.js.nft.json +1 -1
- package/.next/server/app/settings/page_client-reference-manifest.js +1 -1
- package/.next/server/app/settings.html +1 -1
- package/.next/server/app/settings.rsc +19 -19
- package/.next/server/app/settings.segments/_full.segment.rsc +19 -19
- package/.next/server/app/settings.segments/_head.segment.rsc +4 -4
- package/.next/server/app/settings.segments/_index.segment.rsc +12 -12
- package/.next/server/app/settings.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/settings.segments/settings/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/settings.segments/settings.segment.rsc +3 -3
- package/.next/server/chunks/0598_next_dist_esm_build_templates_app-route_0kbcuk-.js +9 -7
- package/.next/server/chunks/0598_next_dist_esm_build_templates_app-route_0sbf4ny.js +2 -2
- package/.next/server/chunks/[root-of-the-server]__06gca-c._.js +1 -1
- package/.next/server/chunks/{[root-of-the-server]__1idgvjh._.js → [root-of-the-server]__0pmypq8._.js} +3 -3
- package/.next/server/chunks/[root-of-the-server]__0tlfusr._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__0x_a1jw._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__1-f7u-_._.js +1 -1
- package/.next/{standalone/apps/web/.next/server/chunks/[root-of-the-server]__1lhls88._.js → server/chunks/[root-of-the-server]__13xnq6l._.js} +1 -1
- package/.next/server/chunks/[root-of-the-server]__16jk_se._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__1s_l1di._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__1u4frv-._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__1w00ho9._.js +1 -1
- package/.next/server/chunks/_1ncm_ks._.js +1 -1
- package/.next/server/chunks/_1sx94ue._.js +1 -1
- package/.next/server/chunks/_20il040._.js +1 -1
- package/.next/server/chunks/packages_0cc5bxf._.js +1 -1
- package/.next/server/chunks/packages_1ggqion._.js +1 -1
- package/.next/server/chunks/packages_core_src_embeddings_registry_ts_05dafmb._.js +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__1k1mxo2._.js +1 -1
- package/.next/server/chunks/ssr/_0ffb2sn._.js +1 -1
- package/.next/server/chunks/ssr/_169pdlf._.js +2 -2
- package/.next/server/chunks/ssr/_18jagqc._.js +1 -1
- package/.next/server/chunks/ssr/_1b5ufkw._.js +3 -0
- package/.next/server/chunks/ssr/_1yqlx1m._.js +1 -1
- package/.next/server/chunks/ssr/packages_core_src_generator_generate-server_ts_15zzrn2._.js +1 -1
- package/.next/server/middleware-build-manifest.js +3 -3
- package/.next/server/pages/404.html +1 -1
- package/.next/server/pages/500.html +1 -1
- package/.next/standalone/apps/web/.next/BUILD_ID +1 -1
- package/.next/standalone/apps/web/.next/build-manifest.json +3 -3
- package/.next/standalone/apps/web/.next/required-server-files.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/_global-error.html +1 -1
- package/.next/standalone/apps/web/.next/server/app/_global-error.rsc +1 -1
- package/.next/standalone/apps/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/.next/standalone/apps/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/.next/standalone/apps/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/.next/standalone/apps/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/.next/standalone/apps/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/apps/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/standalone/apps/web/.next/server/app/_not-found.html +1 -1
- package/.next/standalone/apps/web/.next/server/app/_not-found.rsc +18 -18
- package/.next/standalone/apps/web/.next/server/app/_not-found.segments/_full.segment.rsc +18 -18
- package/.next/standalone/apps/web/.next/server/app/_not-found.segments/_head.segment.rsc +4 -4
- package/.next/standalone/apps/web/.next/server/app/_not-found.segments/_index.segment.rsc +12 -12
- package/.next/standalone/apps/web/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/apps/web/.next/server/app/_not-found.segments/_not-found.segment.rsc +3 -3
- package/.next/standalone/apps/web/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/apps/web/.next/server/app/analytics/page_client-reference-manifest.js +1 -1
- package/.next/standalone/apps/web/.next/server/app/analytics.html +1 -1
- package/.next/standalone/apps/web/.next/server/app/analytics.rsc +19 -19
- package/.next/standalone/apps/web/.next/server/app/analytics.segments/_full.segment.rsc +19 -19
- package/.next/standalone/apps/web/.next/server/app/analytics.segments/_head.segment.rsc +4 -4
- package/.next/standalone/apps/web/.next/server/app/analytics.segments/_index.segment.rsc +12 -12
- package/.next/standalone/apps/web/.next/server/app/analytics.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/apps/web/.next/server/app/analytics.segments/analytics/__PAGE__.segment.rsc +3 -3
- package/.next/standalone/apps/web/.next/server/app/analytics.segments/analytics.segment.rsc +3 -3
- package/.next/standalone/apps/web/.next/server/app/api/analytics/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/api/chat/route.js +1 -1
- package/.next/standalone/apps/web/.next/server/app/api/chat/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/api/chat/status/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/api/chat/suggestions/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/api/config/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/api/config/test/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/api/connections/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/api/connections/webhook/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/api/demo/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/api/deploy/cloud-project/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/api/deploy/ssh/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/api/deployment/blob-setup/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/api/deployment/config/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/api/describe-image/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/api/documents/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/api/firecrawl/local/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/api/index/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/api/jobs/[id]/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/api/jobs/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/api/media/[id]/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/api/media/process/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/api/media/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/api/media/stream/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/api/search/bing/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/api/search/brave/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/api/search/exa/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/api/search/google/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/api/search/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/api/search/tavily/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/api/server/agent/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/api/server/download/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/api/server/generate/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/api/server/local/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/api/servers/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/api/tabular/query/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/api/tabular/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/api/upload-file/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/api/uploads/[...slug]/route.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/chat/page_client-reference-manifest.js +1 -1
- package/.next/standalone/apps/web/.next/server/app/chat.html +1 -1
- package/.next/standalone/apps/web/.next/server/app/chat.rsc +19 -19
- package/.next/standalone/apps/web/.next/server/app/chat.segments/_full.segment.rsc +19 -19
- package/.next/standalone/apps/web/.next/server/app/chat.segments/_head.segment.rsc +4 -4
- package/.next/standalone/apps/web/.next/server/app/chat.segments/_index.segment.rsc +12 -12
- package/.next/standalone/apps/web/.next/server/app/chat.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/apps/web/.next/server/app/chat.segments/chat/__PAGE__.segment.rsc +3 -3
- package/.next/standalone/apps/web/.next/server/app/chat.segments/chat.segment.rsc +3 -3
- package/.next/standalone/apps/web/.next/server/app/data/page.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/data/page_client-reference-manifest.js +1 -1
- package/.next/standalone/apps/web/.next/server/app/data.html +1 -1
- package/.next/standalone/apps/web/.next/server/app/data.rsc +19 -19
- package/.next/standalone/apps/web/.next/server/app/data.segments/_full.segment.rsc +19 -19
- package/.next/standalone/apps/web/.next/server/app/data.segments/_head.segment.rsc +4 -4
- package/.next/standalone/apps/web/.next/server/app/data.segments/_index.segment.rsc +12 -12
- package/.next/standalone/apps/web/.next/server/app/data.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/apps/web/.next/server/app/data.segments/data/__PAGE__.segment.rsc +3 -3
- package/.next/standalone/apps/web/.next/server/app/data.segments/data.segment.rsc +3 -3
- package/.next/standalone/apps/web/.next/server/app/index.html +1 -1
- package/.next/standalone/apps/web/.next/server/app/index.rsc +17 -17
- package/.next/standalone/apps/web/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/apps/web/.next/server/app/index.segments/_full.segment.rsc +17 -17
- package/.next/standalone/apps/web/.next/server/app/index.segments/_head.segment.rsc +4 -4
- package/.next/standalone/apps/web/.next/server/app/index.segments/_index.segment.rsc +12 -12
- package/.next/standalone/apps/web/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/apps/web/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/standalone/apps/web/.next/server/app/settings/page.js.nft.json +1 -1
- package/.next/standalone/apps/web/.next/server/app/settings/page_client-reference-manifest.js +1 -1
- package/.next/standalone/apps/web/.next/server/app/settings.html +1 -1
- package/.next/standalone/apps/web/.next/server/app/settings.rsc +19 -19
- package/.next/standalone/apps/web/.next/server/app/settings.segments/_full.segment.rsc +19 -19
- package/.next/standalone/apps/web/.next/server/app/settings.segments/_head.segment.rsc +4 -4
- package/.next/standalone/apps/web/.next/server/app/settings.segments/_index.segment.rsc +12 -12
- package/.next/standalone/apps/web/.next/server/app/settings.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/apps/web/.next/server/app/settings.segments/settings/__PAGE__.segment.rsc +4 -4
- package/.next/standalone/apps/web/.next/server/app/settings.segments/settings.segment.rsc +3 -3
- package/.next/standalone/apps/web/.next/server/chunks/0598_next_dist_esm_build_templates_app-route_0kbcuk-.js +9 -7
- package/.next/standalone/apps/web/.next/server/chunks/0598_next_dist_esm_build_templates_app-route_0sbf4ny.js +2 -2
- package/.next/standalone/apps/web/.next/server/chunks/[root-of-the-server]__06gca-c._.js +1 -1
- package/.next/standalone/apps/web/.next/server/chunks/{[root-of-the-server]__1idgvjh._.js → [root-of-the-server]__0pmypq8._.js} +3 -3
- package/.next/standalone/apps/web/.next/server/chunks/[root-of-the-server]__0tlfusr._.js +1 -1
- package/.next/standalone/apps/web/.next/server/chunks/[root-of-the-server]__0x_a1jw._.js +1 -1
- package/.next/standalone/apps/web/.next/server/chunks/[root-of-the-server]__1-f7u-_._.js +1 -1
- package/.next/{server/chunks/[root-of-the-server]__1lhls88._.js → standalone/apps/web/.next/server/chunks/[root-of-the-server]__13xnq6l._.js} +1 -1
- package/.next/standalone/apps/web/.next/server/chunks/[root-of-the-server]__16jk_se._.js +1 -1
- package/.next/standalone/apps/web/.next/server/chunks/[root-of-the-server]__1s_l1di._.js +1 -1
- package/.next/standalone/apps/web/.next/server/chunks/[root-of-the-server]__1u4frv-._.js +1 -1
- package/.next/standalone/apps/web/.next/server/chunks/[root-of-the-server]__1w00ho9._.js +1 -1
- package/.next/standalone/apps/web/.next/server/chunks/_1ncm_ks._.js +1 -1
- package/.next/standalone/apps/web/.next/server/chunks/_1sx94ue._.js +1 -1
- package/.next/standalone/apps/web/.next/server/chunks/_20il040._.js +1 -1
- package/.next/standalone/apps/web/.next/server/chunks/packages_0cc5bxf._.js +1 -1
- package/.next/standalone/apps/web/.next/server/chunks/packages_1ggqion._.js +1 -1
- package/.next/standalone/apps/web/.next/server/chunks/packages_core_src_embeddings_registry_ts_05dafmb._.js +1 -1
- package/.next/standalone/apps/web/.next/server/chunks/ssr/[root-of-the-server]__1k1mxo2._.js +1 -1
- package/.next/standalone/apps/web/.next/server/chunks/ssr/_0ffb2sn._.js +1 -1
- package/.next/standalone/apps/web/.next/server/chunks/ssr/_169pdlf._.js +2 -2
- package/.next/standalone/apps/web/.next/server/chunks/ssr/_18jagqc._.js +1 -1
- package/.next/standalone/apps/web/.next/server/chunks/ssr/_1b5ufkw._.js +3 -0
- package/.next/standalone/apps/web/.next/server/chunks/ssr/_1yqlx1m._.js +1 -1
- package/.next/standalone/apps/web/.next/server/chunks/ssr/packages_core_src_generator_generate-server_ts_15zzrn2._.js +1 -1
- package/.next/standalone/apps/web/.next/server/middleware-build-manifest.js +3 -3
- package/.next/standalone/apps/web/.next/server/pages/404.html +1 -1
- package/.next/standalone/apps/web/.next/server/pages/500.html +1 -1
- package/.next/standalone/apps/web/.next/static/chunks/1_knu6c2q82r_.js +1 -0
- package/.next/{static/chunks/37j20in7beze4.js → standalone/apps/web/.next/static/chunks/1gl22nlyonq0i.js} +1 -1
- package/.next/standalone/apps/web/.next/static/chunks/1xr94e4n5c_m_.css +1 -0
- package/.next/standalone/apps/web/.next/static/chunks/{2h-80z3n8mi3d.js → 2diknd81m_z55.js} +1 -1
- package/.next/standalone/apps/web/.next/static/chunks/2iog7bwy_5c7e.js +1 -0
- package/.next/standalone/apps/web/.next/static/chunks/{2dvtyg2k2op4x.js → 2q_4eq7-dkww2.js} +2 -2
- package/.next/standalone/apps/web/.next/static/chunks/{2x1t8sqst0ipu.js → 2t0il37i0nvoo.js} +1 -1
- package/.next/standalone/apps/web/.next/static/media/pdf.worker.min.43wid0v0nfx-f.mjs +29 -0
- package/.next/standalone/apps/web/CHANGELOG.md +12 -0
- package/.next/standalone/apps/web/app/api/chat/route.ts +22 -63
- package/.next/standalone/apps/web/app/api/chat/tools.ts +66 -11
- package/.next/standalone/apps/web/app/api/media/process/route.ts +88 -40
- package/.next/standalone/apps/web/components/chat/chat-workspace.tsx +10 -10
- package/.next/standalone/apps/web/components/chat/message-item.tsx +1 -8
- package/.next/standalone/apps/web/components/data/media-panel.tsx +1 -2
- package/.next/standalone/apps/web/components/data/upload-panel.tsx +7 -4
- package/.next/standalone/apps/web/lib/pdf-images.ts +30 -1
- package/.next/standalone/apps/web/lib/retrieval-routing.ts +72 -0
- package/.next/standalone/apps/web/package.json +1 -1
- package/.next/standalone/apps/web/server.js +1 -1
- package/.next/standalone/packages/tools/doc-editor/CHANGELOG.md +7 -0
- package/.next/standalone/packages/tools/doc-editor/package.json +1 -1
- package/.next/static/chunks/1_knu6c2q82r_.js +1 -0
- package/.next/{standalone/apps/web/.next/static/chunks/37j20in7beze4.js → static/chunks/1gl22nlyonq0i.js} +1 -1
- package/.next/static/chunks/1xr94e4n5c_m_.css +1 -0
- package/.next/static/chunks/{2h-80z3n8mi3d.js → 2diknd81m_z55.js} +1 -1
- package/.next/static/chunks/2iog7bwy_5c7e.js +1 -0
- package/.next/static/chunks/{2dvtyg2k2op4x.js → 2q_4eq7-dkww2.js} +2 -2
- package/.next/static/chunks/{2x1t8sqst0ipu.js → 2t0il37i0nvoo.js} +1 -1
- package/.next/static/media/pdf.worker.min.43wid0v0nfx-f.mjs +29 -0
- package/CHANGELOG.md +12 -0
- package/app/api/chat/route.ts +22 -63
- package/app/api/chat/tools.ts +66 -11
- package/app/api/media/process/route.ts +88 -40
- package/components/chat/chat-workspace.tsx +10 -10
- package/components/chat/message-item.tsx +1 -8
- package/components/data/media-panel.tsx +1 -2
- package/components/data/upload-panel.tsx +7 -4
- package/lib/pdf-images.ts +30 -1
- package/lib/retrieval-routing.ts +72 -0
- package/package.json +6 -6
- package/.next/server/chunks/ssr/apps_web_lib_pdf-images_ts_13-l5wa._.js +0 -3
- package/.next/standalone/apps/web/.next/server/chunks/ssr/apps_web_lib_pdf-images_ts_13-l5wa._.js +0 -3
- package/.next/standalone/apps/web/.next/static/chunks/2ib3e0xrrdait.js +0 -1
- package/.next/standalone/apps/web/.next/static/chunks/38f3p67a1uufx.js +0 -1
- package/.next/standalone/apps/web/.next/static/chunks/3fe06cefiv690.css +0 -1
- package/.next/static/chunks/2ib3e0xrrdait.js +0 -1
- package/.next/static/chunks/38f3p67a1uufx.js +0 -1
- package/.next/static/chunks/3fe06cefiv690.css +0 -1
- /package/.next/standalone/apps/web/.next/static/{whR5PvI0kapiCtaze5Lb0 → YT7FJOJe86DX-Sa61-JJz}/_buildManifest.js +0 -0
- /package/.next/standalone/apps/web/.next/static/{whR5PvI0kapiCtaze5Lb0 → YT7FJOJe86DX-Sa61-JJz}/_clientMiddlewareManifest.js +0 -0
- /package/.next/standalone/apps/web/.next/static/{whR5PvI0kapiCtaze5Lb0 → YT7FJOJe86DX-Sa61-JJz}/_ssgManifest.js +0 -0
- /package/.next/static/{whR5PvI0kapiCtaze5Lb0 → YT7FJOJe86DX-Sa61-JJz}/_buildManifest.js +0 -0
- /package/.next/static/{whR5PvI0kapiCtaze5Lb0 → YT7FJOJe86DX-Sa61-JJz}/_clientMiddlewareManifest.js +0 -0
- /package/.next/static/{whR5PvI0kapiCtaze5Lb0 → YT7FJOJe86DX-Sa61-JJz}/_ssgManifest.js +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# larkup
|
|
2
2
|
|
|
3
|
+
## 0.1.42
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Improve smart RAG and web fallback, PDF visual retrieval, and resilient video indexing.
|
|
8
|
+
- Updated dependencies
|
|
9
|
+
- @larkup/core@0.2.6
|
|
10
|
+
- @larkup/marketplace@0.1.12
|
|
11
|
+
- @larkup/scraper@0.1.30
|
|
12
|
+
- @larkup/tool-doc-editor@0.2.7
|
|
13
|
+
- @larkup/tool-video-audio@0.2.4
|
|
14
|
+
|
|
3
15
|
## 0.1.41
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
package/app/api/chat/route.ts
CHANGED
|
@@ -16,6 +16,11 @@ import type { CustomModelConfig } from '@larkup/core/types';
|
|
|
16
16
|
import { DEFAULT_SYSTEM_PROMPT } from '@larkup/core/types';
|
|
17
17
|
|
|
18
18
|
import { getChatTools } from './tools';
|
|
19
|
+
import {
|
|
20
|
+
requiresCurrentWebSearch,
|
|
21
|
+
requiresKnowledgeBaseSearch,
|
|
22
|
+
retrievalToolsForStep,
|
|
23
|
+
} from '@/lib/retrieval-routing';
|
|
19
24
|
|
|
20
25
|
export const maxDuration = 60;
|
|
21
26
|
|
|
@@ -66,7 +71,7 @@ const SMART_RETRIEVAL_POLICY = `
|
|
|
66
71
|
|
|
67
72
|
TOOL RULES:
|
|
68
73
|
1. searchKnowledgeBase → Use FIRST when the question is about the user's indexed data (documents, files, images, videos, diagrams, anything they uploaded).
|
|
69
|
-
2. webSearch → Use
|
|
74
|
+
2. webSearch → Use for clearly current/public facts. If a prior local search was not relevant or failed, use it as the one permitted fallback. If web search fails, use the knowledge base as the one permitted fallback.
|
|
70
75
|
3. Other tools → Use when the question specifically requires them.
|
|
71
76
|
4. General knowledge → Answer directly for common knowledge unrelated to the user's data.
|
|
72
77
|
5. If nothing helps, say so honestly.
|
|
@@ -75,6 +80,8 @@ DO:
|
|
|
75
80
|
- Keep answers short and direct. 1–3 sentences unless the task is complex.
|
|
76
81
|
- Search at most ONCE per tool per turn. Never repeat the same search.
|
|
77
82
|
- For questions about the user's own facts or preferences (for example, "what is my favourite fruit?"), searchKnowledgeBase is required before answering.
|
|
83
|
+
- If a knowledge-base result contains PDF images and the question asks what is shown, named, counted, or connected in that visual, call analyzeImageDeeply before answering. Call presentMedia when the user asks to see the image.
|
|
84
|
+
- For an indexed video outcome question, inspect endingContext before saying that a winner or final score is unavailable. Use only explicitly supported evidence.
|
|
78
85
|
- Use presentMedia to show images/videos/audio from indexed content.
|
|
79
86
|
- For follow-ups like "show me that", reuse the mediaAssetId from earlier results — do not search again.
|
|
80
87
|
|
|
@@ -103,37 +110,6 @@ function latestUserText(messages: UIMessage[]): string {
|
|
|
103
110
|
return '';
|
|
104
111
|
}
|
|
105
112
|
|
|
106
|
-
/** Only force KB search when the user explicitly refers to their own data.
|
|
107
|
-
* Matches "my document", "our files", "the uploaded image" etc. but NOT
|
|
108
|
-
* generic uses like "I want to know", "can you tell me", "I think". */
|
|
109
|
-
function requiresKnowledgeBaseSearch(text: string): boolean {
|
|
110
|
-
// Skip generic conversational patterns
|
|
111
|
-
if (/^(hi|hello|hey|thanks|thank you|ok|sure|yes|no|please|help)\b/i.test(text.trim())) {
|
|
112
|
-
return false;
|
|
113
|
-
}
|
|
114
|
-
// Match possessive references to user data
|
|
115
|
-
return (
|
|
116
|
-
/\b(my|our)\s+(favo(?:u)?rite|preference|choice|answer|name|result|score|winner)\b/i.test(
|
|
117
|
-
text,
|
|
118
|
-
) ||
|
|
119
|
-
/\b(?:what|which|who|where|when|how)\b[\s\S]{0,80}\b(my|our)\b/i.test(text) ||
|
|
120
|
-
/\b(my|our)\s+(document|file|data|image|picture|diagram|video|audio|upload|corpus|knowledge|database|db|pdf|report|spreadsheet|presentation)/i.test(
|
|
121
|
-
text,
|
|
122
|
-
) ||
|
|
123
|
-
/\b(the|this|that)\s+(document|file|diagram|image|picture|upload|pdf|report)/i.test(text) ||
|
|
124
|
-
/\b(uploaded?|indexed|scraped|knowledge base|corpus)\b/i.test(text) ||
|
|
125
|
-
/\bshow\s+me\b/i.test(text)
|
|
126
|
-
);
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
/** Questions whose answer is inherently time-sensitive should not rely on the
|
|
130
|
-
* model's training snapshot when Web Search is available. */
|
|
131
|
-
function requiresCurrentWebSearch(text: string): boolean {
|
|
132
|
-
return /\b(who won|winner|final score|match result|latest|current|today|yesterday|breaking news|weather|stock price|exchange rate|election result|schedule)\b/i.test(
|
|
133
|
-
text,
|
|
134
|
-
);
|
|
135
|
-
}
|
|
136
|
-
|
|
137
113
|
export async function POST(req: Request) {
|
|
138
114
|
const {
|
|
139
115
|
messages,
|
|
@@ -401,7 +377,12 @@ ${fieldLines}`;
|
|
|
401
377
|
: '') +
|
|
402
378
|
tabularContext +
|
|
403
379
|
docContext;
|
|
404
|
-
const tools = await getChatTools({
|
|
380
|
+
const tools = await getChatTools({
|
|
381
|
+
serverId,
|
|
382
|
+
docSessionId,
|
|
383
|
+
config,
|
|
384
|
+
origin: new URL(req.url).origin,
|
|
385
|
+
});
|
|
405
386
|
const userText = latestUserText(messagesToProcess);
|
|
406
387
|
const forceKnowledgeBaseSearch =
|
|
407
388
|
requiresKnowledgeBaseSearch(userText) && Boolean(tools.searchKnowledgeBase);
|
|
@@ -420,38 +401,16 @@ ${fieldLines}`;
|
|
|
420
401
|
system: systemPrompt,
|
|
421
402
|
messages: await convertToModelMessages(safeMessages, { tools }),
|
|
422
403
|
maxOutputTokens: 4096,
|
|
423
|
-
// Three steps: retrieve → optionally present media → answer.
|
|
404
|
+
// Three steps: retrieve → optionally inspect/present media → answer.
|
|
424
405
|
stopWhen: stepCountIs(3),
|
|
425
406
|
toolChoice: 'auto',
|
|
426
|
-
prepareStep: ({ stepNumber }) =>
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
// enabled web search override a perfectly relevant local answer.
|
|
434
|
-
if (forceWebSearch && !forceKnowledgeBaseSearch && stepNumber === 0) {
|
|
435
|
-
return { toolChoice: { type: 'tool', toolName: 'webSearch' } };
|
|
436
|
-
}
|
|
437
|
-
// After a forced tool, and after the optional KB → web fallback, remove
|
|
438
|
-
// search tools. This guarantees one concise search surface rather than
|
|
439
|
-
// a chain of near-identical web queries.
|
|
440
|
-
if (stepNumber >= 2) {
|
|
441
|
-
return {
|
|
442
|
-
activeTools: Object.keys(tools).filter(
|
|
443
|
-
(name) => name !== 'webSearch' && name !== 'searchKnowledgeBase',
|
|
444
|
-
),
|
|
445
|
-
};
|
|
446
|
-
}
|
|
447
|
-
if (forceKnowledgeBaseSearch && stepNumber >= 1) {
|
|
448
|
-
return { activeTools: Object.keys(tools).filter((name) => name !== 'searchKnowledgeBase') };
|
|
449
|
-
}
|
|
450
|
-
if (forceWebSearch && stepNumber >= 1) {
|
|
451
|
-
return { activeTools: Object.keys(tools).filter((name) => name !== 'webSearch') };
|
|
452
|
-
}
|
|
453
|
-
return undefined;
|
|
454
|
-
},
|
|
407
|
+
prepareStep: ({ stepNumber }) =>
|
|
408
|
+
retrievalToolsForStep({
|
|
409
|
+
stepNumber,
|
|
410
|
+
forceKnowledgeBaseSearch,
|
|
411
|
+
forceWebSearch: forceWebSearch && !forceKnowledgeBaseSearch,
|
|
412
|
+
toolNames: Object.keys(tools),
|
|
413
|
+
}),
|
|
455
414
|
onFinish: async ({ usage, response }) => {
|
|
456
415
|
const { trackUsageEvent, estimateCost } = await import('@larkup/core/analytics-store');
|
|
457
416
|
const u = usage as any;
|
package/app/api/chat/tools.ts
CHANGED
|
@@ -166,15 +166,21 @@ async function formatKnowledgeHits(query: string, rawHits: any[], topK: number)
|
|
|
166
166
|
const trailingDocuments = timestampedDocuments.filter(
|
|
167
167
|
(document) => Number(document.metadata?.endSecs ?? 0) >= mediaDuration - trailingHorizonSecs,
|
|
168
168
|
);
|
|
169
|
+
// Result announcements can occur shortly before the literal final minutes
|
|
170
|
+
// (for example during a trophy or score recap). Preserve the latest explicit
|
|
171
|
+
// outcome evidence from the whole indexed timeline, not only the trailing
|
|
172
|
+
// window returned by a semantic match.
|
|
173
|
+
const timelineOutcomeDocuments = isOutcomeQuery(query)
|
|
174
|
+
? timestampedDocuments.filter((document) => isOutcomeEvidence(document.content)).slice(-3)
|
|
175
|
+
: [];
|
|
169
176
|
const signaledEndingDocuments = isOutcomeQuery(query)
|
|
170
177
|
? trailingDocuments.filter((document) => isOutcomeEvidence(document.content)).slice(-2)
|
|
171
178
|
: [];
|
|
172
179
|
const timestampedEnding = [
|
|
173
180
|
...new Map(
|
|
174
|
-
[...signaledEndingDocuments, ...trailingDocuments.slice(-4)].map(
|
|
175
|
-
document.id,
|
|
176
|
-
|
|
177
|
-
]),
|
|
181
|
+
[...timelineOutcomeDocuments, ...signaledEndingDocuments, ...trailingDocuments.slice(-4)].map(
|
|
182
|
+
(document) => [document.id, document],
|
|
183
|
+
),
|
|
178
184
|
).values(),
|
|
179
185
|
].sort(
|
|
180
186
|
(left, right) => Number(left.metadata?.endSecs ?? 0) - Number(right.metadata?.endSecs ?? 0),
|
|
@@ -287,7 +293,18 @@ async function formatKnowledgeHits(query: string, rawHits: any[], topK: number)
|
|
|
287
293
|
// document, rather than creating media-library assets. Expose those
|
|
288
294
|
// URLs explicitly so the presentation tool can validate and render
|
|
289
295
|
// them in chat.
|
|
290
|
-
images:
|
|
296
|
+
images:
|
|
297
|
+
hit.metadata?.images ??
|
|
298
|
+
(hit.metadata?.isImage && hit.metadata?.imageUrl
|
|
299
|
+
? [
|
|
300
|
+
{
|
|
301
|
+
imageUrl: hit.metadata.imageUrl,
|
|
302
|
+
pageNumber: hit.metadata.pageNumber,
|
|
303
|
+
index: hit.metadata.index,
|
|
304
|
+
description: hit.metadata.description,
|
|
305
|
+
},
|
|
306
|
+
]
|
|
307
|
+
: undefined),
|
|
291
308
|
metadata: hit.metadata,
|
|
292
309
|
timelineContext,
|
|
293
310
|
endingContext: hitIndex === 0 ? endingContext : undefined,
|
|
@@ -312,13 +329,15 @@ export async function getChatTools(context: {
|
|
|
312
329
|
serverId?: string;
|
|
313
330
|
docSessionId?: string;
|
|
314
331
|
config?: any;
|
|
332
|
+
/** Public origin of the incoming chat request, used for local media URLs. */
|
|
333
|
+
origin?: string;
|
|
315
334
|
}) {
|
|
316
335
|
const { serverId, docSessionId, config } = context;
|
|
317
336
|
|
|
318
337
|
const builtInTools: Record<string, any> = {
|
|
319
338
|
searchKnowledgeBase: tool({
|
|
320
339
|
description:
|
|
321
|
-
"HIGHEST PRIORITY TOOL — Search the user's private RAG knowledge base. ALWAYS use this FIRST before webSearch or any other tool when the question may relate to the user's indexed data. This includes questions about documents, files, images, diagrams, videos, or anything the user may have uploaded. Do not use for general knowledge, casual conversation, or writing tasks. Search once with a focused query. For media, inspect the returned timeline and endingContext, and reuse exact mediaAssetId/startSecs/endSecs values with presentMedia when a preview is useful. Never guess timestamps.",
|
|
340
|
+
"HIGHEST PRIORITY TOOL — Search the user's private RAG knowledge base. ALWAYS use this FIRST before webSearch or any other tool when the question may relate to the user's indexed data. This includes questions about documents, files, images, diagrams, videos, or anything the user may have uploaded. Do not use for general knowledge, casual conversation, or writing tasks. Search once with a focused query. If it returns no relevant evidence or an error and the question asks for public/current information, webSearch is available once as a fallback. For media, inspect the returned timeline and endingContext, and reuse exact mediaAssetId/startSecs/endSecs values with presentMedia when a preview is useful. Never guess timestamps.",
|
|
322
341
|
inputSchema: z.object({
|
|
323
342
|
query: z.string().describe('The search query for the knowledge base.'),
|
|
324
343
|
}),
|
|
@@ -620,7 +639,10 @@ export async function getChatTools(context: {
|
|
|
620
639
|
// Fetch the image to base64
|
|
621
640
|
// Handle both absolute URLs and relative local uploads
|
|
622
641
|
const fetchUrl = imageUrl.startsWith('/')
|
|
623
|
-
?
|
|
642
|
+
? new URL(
|
|
643
|
+
imageUrl,
|
|
644
|
+
context.origin ?? `http://127.0.0.1:${process.env.PORT || 3000}`,
|
|
645
|
+
).toString()
|
|
624
646
|
: imageUrl;
|
|
625
647
|
const res = await fetch(fetchUrl);
|
|
626
648
|
if (!res.ok) throw new Error(`Failed to fetch image: ${res.statusText}`);
|
|
@@ -631,7 +653,10 @@ export async function getChatTools(context: {
|
|
|
631
653
|
|
|
632
654
|
// Post to our describe-image endpoint which handles model setup
|
|
633
655
|
const descRes = await fetch(
|
|
634
|
-
|
|
656
|
+
new URL(
|
|
657
|
+
'/api/describe-image',
|
|
658
|
+
context.origin ?? `http://127.0.0.1:${process.env.PORT || 3000}`,
|
|
659
|
+
).toString(),
|
|
635
660
|
{
|
|
636
661
|
method: 'POST',
|
|
637
662
|
headers: { 'Content-Type': 'application/json' },
|
|
@@ -936,11 +961,35 @@ export async function getChatTools(context: {
|
|
|
936
961
|
|
|
937
962
|
webSearch: tool({
|
|
938
963
|
description:
|
|
939
|
-
|
|
964
|
+
'Search the public internet for current information, news, or facts. Use it first for clearly current/public requests, or once after an irrelevant local search. If it fails or returns no useful results, searchKnowledgeBase is available once as a fallback. Never repeat either search tool in the same turn.',
|
|
940
965
|
inputSchema: z.object({
|
|
941
966
|
query: z.string().describe('The search query.'),
|
|
942
967
|
}),
|
|
943
968
|
execute: async ({ query }) => {
|
|
969
|
+
const knowledgeBaseFallback = async (error: string) => {
|
|
970
|
+
try {
|
|
971
|
+
const knowledge = await queryKnowledgeBase(query, 5, serverId ?? null);
|
|
972
|
+
return {
|
|
973
|
+
error,
|
|
974
|
+
results: [],
|
|
975
|
+
fallback: {
|
|
976
|
+
source: 'knowledge-base',
|
|
977
|
+
attemptedBecause: 'Public web search failed or returned no results.',
|
|
978
|
+
...knowledge,
|
|
979
|
+
},
|
|
980
|
+
};
|
|
981
|
+
} catch (fallbackError: any) {
|
|
982
|
+
return {
|
|
983
|
+
error,
|
|
984
|
+
results: [],
|
|
985
|
+
fallback: {
|
|
986
|
+
source: 'knowledge-base',
|
|
987
|
+
error: fallbackError?.message || 'Knowledge-base fallback failed.',
|
|
988
|
+
hits: [],
|
|
989
|
+
},
|
|
990
|
+
};
|
|
991
|
+
}
|
|
992
|
+
};
|
|
944
993
|
const provider = config?.webSearchProvider || 'tavily';
|
|
945
994
|
const req = new Request('http://localhost/api/search', {
|
|
946
995
|
method: 'POST',
|
|
@@ -980,11 +1029,14 @@ export async function getChatTools(context: {
|
|
|
980
1029
|
|
|
981
1030
|
if (res.status >= 400) {
|
|
982
1031
|
const err = await res.json();
|
|
983
|
-
return
|
|
1032
|
+
return knowledgeBaseFallback(err.error || 'Search failed');
|
|
984
1033
|
}
|
|
985
1034
|
|
|
986
1035
|
const data = await res.json();
|
|
987
1036
|
const items = data.items || data.results || [];
|
|
1037
|
+
if (items.length === 0) {
|
|
1038
|
+
return knowledgeBaseFallback('Public search returned no results.');
|
|
1039
|
+
}
|
|
988
1040
|
return {
|
|
989
1041
|
results: items.slice(0, 10).map((i: any) => ({
|
|
990
1042
|
title: i.title,
|
|
@@ -993,7 +1045,7 @@ export async function getChatTools(context: {
|
|
|
993
1045
|
})),
|
|
994
1046
|
};
|
|
995
1047
|
} catch (e: any) {
|
|
996
|
-
return
|
|
1048
|
+
return knowledgeBaseFallback(e.message || 'Search failed');
|
|
997
1049
|
}
|
|
998
1050
|
},
|
|
999
1051
|
}),
|
|
@@ -1016,6 +1068,9 @@ export async function getChatTools(context: {
|
|
|
1016
1068
|
// Keeping it available prevents an enabled web-search configuration
|
|
1017
1069
|
// from silently removing the user's local knowledge base.
|
|
1018
1070
|
'searchKnowledgeBase',
|
|
1071
|
+
// PDF/image hits can require one visual pass after retrieval. This is
|
|
1072
|
+
// available only to a follow-up tool step, never auto-run on chat.
|
|
1073
|
+
'analyzeImageDeeply',
|
|
1019
1074
|
'presentMedia',
|
|
1020
1075
|
'fillDocumentForm',
|
|
1021
1076
|
'editDocument',
|
|
@@ -646,7 +646,9 @@ async function processMediaWithTool(
|
|
|
646
646
|
const scenePromise = (async () => {
|
|
647
647
|
const extractedFrames = result.frames as { path: string; timestampSecs: number }[];
|
|
648
648
|
const analysisWindowSecs = visualAnalysisWindow(result.meta.durationSecs);
|
|
649
|
-
|
|
649
|
+
// Chronological batches preserve visual context while keeping a
|
|
650
|
+
// long recording within a practical vision-request budget.
|
|
651
|
+
const frameGroups = groupFramesByWindow(extractedFrames, analysisWindowSecs, 12);
|
|
650
652
|
if (frameGroups.length === 0) {
|
|
651
653
|
await reportStage('vision', {
|
|
652
654
|
status: 'skipped',
|
|
@@ -662,10 +664,37 @@ async function processMediaWithTool(
|
|
|
662
664
|
message: `Understanding 0 of ${frameGroups.length} visual sequences...`,
|
|
663
665
|
});
|
|
664
666
|
let analyzed = 0;
|
|
667
|
+
let skipped = 0;
|
|
668
|
+
let visionThrottled = false;
|
|
669
|
+
let lastVisionRequestAt = 0;
|
|
670
|
+
const visionProvider = globalConfig.chatProvider || globalConfig.embeddingProvider;
|
|
671
|
+
// Providers commonly rate-limit visual generation much more tightly
|
|
672
|
+
// than text generation. Serializing and pacing Google requests avoids
|
|
673
|
+
// turning a temporary 429 into a failed video index.
|
|
674
|
+
const visionConcurrency = visionProvider === 'google' ? 1 : limits.apiConcurrency;
|
|
675
|
+
const visionMinIntervalMs = visionProvider === 'google' ? 4_250 : 0;
|
|
676
|
+
const recordProgress = () => {
|
|
677
|
+
analyzed++;
|
|
678
|
+
const progressStep = Math.max(1, Math.ceil(frameGroups.length / 100));
|
|
679
|
+
if (analyzed % progressStep === 0 || analyzed === frameGroups.length) {
|
|
680
|
+
void reportStage('vision', {
|
|
681
|
+
status: 'running',
|
|
682
|
+
current: analyzed,
|
|
683
|
+
total: frameGroups.length,
|
|
684
|
+
unit: 'sequences',
|
|
685
|
+
message: `Understanding visual sequence ${analyzed} of ${frameGroups.length}...`,
|
|
686
|
+
}).catch(() => {});
|
|
687
|
+
}
|
|
688
|
+
};
|
|
665
689
|
const descriptions = await mapConcurrent(
|
|
666
690
|
frameGroups,
|
|
667
|
-
|
|
691
|
+
visionConcurrency,
|
|
668
692
|
async (frames: { path: string; timestampSecs: number }[]) => {
|
|
693
|
+
if (visionThrottled) {
|
|
694
|
+
skipped++;
|
|
695
|
+
recordProgress();
|
|
696
|
+
return null;
|
|
697
|
+
}
|
|
669
698
|
const base64Images = await Promise.all(
|
|
670
699
|
frames.map(async (frame) => (await fs.readFile(frame.path)).toString('base64')),
|
|
671
700
|
);
|
|
@@ -675,14 +704,20 @@ async function processMediaWithTool(
|
|
|
675
704
|
Math.max(startSecs + 1, frames.at(-1)!.timestampSecs + frameIntervalSecs),
|
|
676
705
|
);
|
|
677
706
|
const timestamps = frames.map((frame) => formatTime(frame.timestampSecs)).join(', ');
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
707
|
+
if (visionMinIntervalMs > 0) {
|
|
708
|
+
const remaining = visionMinIntervalMs - (Date.now() - lastVisionRequestAt);
|
|
709
|
+
if (remaining > 0) await new Promise((resolve) => setTimeout(resolve, remaining));
|
|
710
|
+
}
|
|
711
|
+
lastVisionRequestAt = Date.now();
|
|
712
|
+
try {
|
|
713
|
+
const descRes = await fetchWithRetry(
|
|
714
|
+
scopedApiUrl('/api/describe-image', reqUrl, serverId),
|
|
715
|
+
{
|
|
716
|
+
method: 'POST',
|
|
717
|
+
headers: { 'Content-Type': 'application/json' },
|
|
718
|
+
body: JSON.stringify({
|
|
719
|
+
base64Images,
|
|
720
|
+
prompt: `These are chronological frames from "${asset.fileName}" at ${timestamps}.
|
|
686
721
|
Write one evidence note for this time range. Track people, actions, interactions, state changes,
|
|
687
722
|
important objects, and exact meaningful on-screen text. Perform careful OCR, including Arabic and
|
|
688
723
|
other right-to-left text without reversing labels. For scoreboards or result animations, compare
|
|
@@ -690,38 +725,44 @@ frames in timestamp order and report the latest visible score as the current/fin
|
|
|
690
725
|
each number with the correct nearby team/person label. Record a winner or result only when visually
|
|
691
726
|
supported. Omit boilerplate about facts that are not shown. Be factual, information-dense, and
|
|
692
727
|
concise.`,
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
728
|
+
}),
|
|
729
|
+
},
|
|
730
|
+
);
|
|
731
|
+
if (!descRes.ok) {
|
|
732
|
+
let detail = '';
|
|
733
|
+
try {
|
|
734
|
+
const errorBody = (await descRes.json()) as { error?: string };
|
|
735
|
+
detail = errorBody.error?.trim() || '';
|
|
736
|
+
} catch {
|
|
737
|
+
// Keep the status-only fallback for non-JSON failures.
|
|
738
|
+
}
|
|
739
|
+
if (/quota|rate limit|resource_exhausted|too many requests/i.test(detail)) {
|
|
740
|
+
visionThrottled = true;
|
|
741
|
+
}
|
|
742
|
+
skipped++;
|
|
743
|
+
console.warn(
|
|
744
|
+
`Visual sequence ${formatTime(startSecs)}–${formatTime(endSecs)} was skipped: ${
|
|
745
|
+
detail || `HTTP ${descRes.status}`
|
|
746
|
+
}`,
|
|
747
|
+
);
|
|
748
|
+
return null;
|
|
714
749
|
}
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
750
|
+
const { description } = (await descRes.json()) as { description?: string };
|
|
751
|
+
return description
|
|
752
|
+
? { text: description, startSecs, endSecs: Math.max(startSecs + 1, endSecs) }
|
|
753
|
+
: null;
|
|
754
|
+
} catch (error) {
|
|
755
|
+
skipped++;
|
|
756
|
+
console.warn(
|
|
757
|
+
`Visual sequence ${formatTime(startSecs)}–${formatTime(
|
|
758
|
+
endSecs,
|
|
759
|
+
)} failed; preserving the remaining transcript evidence.`,
|
|
760
|
+
error,
|
|
719
761
|
);
|
|
762
|
+
return null;
|
|
763
|
+
} finally {
|
|
764
|
+
recordProgress();
|
|
720
765
|
}
|
|
721
|
-
const { description } = (await descRes.json()) as { description?: string };
|
|
722
|
-
return description
|
|
723
|
-
? { text: description, startSecs, endSecs: Math.max(startSecs + 1, endSecs) }
|
|
724
|
-
: null;
|
|
725
766
|
},
|
|
726
767
|
);
|
|
727
768
|
await reportStage('vision', {
|
|
@@ -729,7 +770,12 @@ concise.`,
|
|
|
729
770
|
current: frameGroups.length,
|
|
730
771
|
total: frameGroups.length,
|
|
731
772
|
unit: 'sequences',
|
|
732
|
-
message:
|
|
773
|
+
message:
|
|
774
|
+
skipped > 0
|
|
775
|
+
? `Understood ${
|
|
776
|
+
frameGroups.length - skipped
|
|
777
|
+
} visual sequences; ${skipped} were skipped while the vision provider was unavailable. Speech evidence remains searchable.`
|
|
778
|
+
: `Understood ${frameGroups.length} visual sequences with OCR.`,
|
|
733
779
|
});
|
|
734
780
|
return descriptions;
|
|
735
781
|
})();
|
|
@@ -1002,6 +1048,8 @@ concise.`,
|
|
|
1002
1048
|
function visualAnalysisWindow(durationSecs: number): number {
|
|
1003
1049
|
if (durationSecs >= 4 * 60 * 60) return 15 * 60;
|
|
1004
1050
|
if (durationSecs > 60 * 60) return 5 * 60;
|
|
1051
|
+
if (durationSecs > 30 * 60) return 3 * 60;
|
|
1052
|
+
if (durationSecs > 10 * 60) return 2 * 60;
|
|
1005
1053
|
return 60;
|
|
1006
1054
|
}
|
|
1007
1055
|
|
|
@@ -107,7 +107,7 @@ function AttachmentCard({
|
|
|
107
107
|
<div className="size-7 shrink-0 rounded-md overflow-hidden bg-background border border-border/90 flex items-center justify-center p-1">
|
|
108
108
|
<img src={iconPath} alt={file.name} className="w-full h-full object-contain" />
|
|
109
109
|
</div>
|
|
110
|
-
<div className="flex flex-col justify-center max-w-
|
|
110
|
+
<div className="flex flex-col justify-center max-w-30">
|
|
111
111
|
<span className="text-xs font-medium truncate text-foreground">{file.name}</span>
|
|
112
112
|
<span className="text-[10px] text-muted-foreground">
|
|
113
113
|
{(file.size / 1024).toFixed(0)} KB
|
|
@@ -684,7 +684,7 @@ function ChatWorkspaceInner() {
|
|
|
684
684
|
<button
|
|
685
685
|
type="button"
|
|
686
686
|
onClick={() => setShowModelSelect((o) => !o)}
|
|
687
|
-
className="flex w-
|
|
687
|
+
className="flex w-75 justify-between items-center gap-1.5 rounded-lg border border-border bg-white dark:bg-card px-3 py-1.5 text-xs text-foreground transition hover:bg-muted"
|
|
688
688
|
>
|
|
689
689
|
<span className="flex items-center gap-2 truncate">
|
|
690
690
|
{selectedModelData && (
|
|
@@ -709,7 +709,7 @@ function ChatWorkspaceInner() {
|
|
|
709
709
|
{showModelSelect && (
|
|
710
710
|
<>
|
|
711
711
|
<div className="fixed inset-0 z-40" onClick={() => setShowModelSelect(false)} />
|
|
712
|
-
<div className="absolute right-0 top-full z-50 mt-1 w-
|
|
712
|
+
<div className="absolute right-0 top-full z-50 mt-1 w-75 rounded-lg border border-border bg-card ">
|
|
713
713
|
{/* Search input */}
|
|
714
714
|
<div className="flex items-center gap-2 border-b border-border px-3 py-2">
|
|
715
715
|
<Search className="size-3.5 shrink-0 text-muted-foreground" />
|
|
@@ -815,7 +815,7 @@ function ChatWorkspaceInner() {
|
|
|
815
815
|
type="button"
|
|
816
816
|
className="flex h-8 w-8 items-center justify-center rounded-lg text-muted-foreground transition hover:bg-secondary hover:text-foreground"
|
|
817
817
|
>
|
|
818
|
-
<History className="h-
|
|
818
|
+
<History className="h-4 w-4" />
|
|
819
819
|
</button>
|
|
820
820
|
}
|
|
821
821
|
/>
|
|
@@ -823,7 +823,7 @@ function ChatWorkspaceInner() {
|
|
|
823
823
|
/>
|
|
824
824
|
<TooltipContent>Chat History</TooltipContent>
|
|
825
825
|
</Tooltip>
|
|
826
|
-
<SheetContent side="left" className="w-
|
|
826
|
+
<SheetContent side="left" className="w-75 sm:w-87.5 p-0 flex flex-col">
|
|
827
827
|
<SheetHeader className="p-4 border-b">
|
|
828
828
|
<SheetTitle className="text-sm font-semibold">Chat History</SheetTitle>
|
|
829
829
|
</SheetHeader>
|
|
@@ -890,7 +890,7 @@ function ChatWorkspaceInner() {
|
|
|
890
890
|
onClick={newChat}
|
|
891
891
|
className="flex h-8 w-8 items-center justify-center rounded-lg text-muted-foreground transition hover:bg-secondary hover:text-foreground"
|
|
892
892
|
>
|
|
893
|
-
<SquarePen className="h-
|
|
893
|
+
<SquarePen className="h-4 w-4" />
|
|
894
894
|
</button>
|
|
895
895
|
}
|
|
896
896
|
/>
|
|
@@ -1016,7 +1016,7 @@ function ChatWorkspaceInner() {
|
|
|
1016
1016
|
type="button"
|
|
1017
1017
|
className="flex h-9 w-9 shrink-0 items-center justify-center rounded-xl text-muted-foreground transition hover:bg-secondary hover:text-foreground"
|
|
1018
1018
|
>
|
|
1019
|
-
<Plus className="h-
|
|
1019
|
+
<Plus className="h-4.5 w-4.5" />
|
|
1020
1020
|
</button>
|
|
1021
1021
|
}
|
|
1022
1022
|
/>
|
|
@@ -1143,7 +1143,7 @@ function ChatWorkspaceInner() {
|
|
|
1143
1143
|
rows={1}
|
|
1144
1144
|
disabled={!ready}
|
|
1145
1145
|
placeholder="How can I help you…"
|
|
1146
|
-
className="max-h-48 min-h-
|
|
1146
|
+
className="max-h-48 min-h-11 w-full resize-none bg-transparent px-2 py-3 text-[15px] leading-relaxed text-foreground outline-none placeholder:text-muted-foreground [&::-webkit-scrollbar]:hidden disabled:opacity-50"
|
|
1147
1147
|
/>
|
|
1148
1148
|
</div>
|
|
1149
1149
|
|
|
@@ -1153,9 +1153,9 @@ function ChatWorkspaceInner() {
|
|
|
1153
1153
|
className="flex h-9 w-9 shrink-0 items-center justify-center rounded-xl bg-primary text-primary-foreground transition hover:opacity-90 disabled:opacity-40"
|
|
1154
1154
|
>
|
|
1155
1155
|
{isBusy || isDocLoading ? (
|
|
1156
|
-
<Loader2 className="h-
|
|
1156
|
+
<Loader2 className="h-4.5 w-4.5 animate-spin" />
|
|
1157
1157
|
) : (
|
|
1158
|
-
<ArrowUp className="h-
|
|
1158
|
+
<ArrowUp className="h-4.5 w-4.5" />
|
|
1159
1159
|
)}
|
|
1160
1160
|
</button>
|
|
1161
1161
|
</div>
|
|
@@ -538,13 +538,9 @@ export function MessageItem({
|
|
|
538
538
|
const editor = useDocEditor();
|
|
539
539
|
updateFromToolResult = editor.updateFromToolResult;
|
|
540
540
|
openCanvas = editor.openCanvas;
|
|
541
|
-
} catch {
|
|
542
|
-
// Not wrapped in DocEditorProvider in some contexts
|
|
543
|
-
}
|
|
541
|
+
} catch {}
|
|
544
542
|
|
|
545
543
|
const anyMessage = message as any;
|
|
546
|
-
|
|
547
|
-
// Stabilize the parts array to prevent re-renders from creating new array refs each time
|
|
548
544
|
const parts: any[] = useMemo(() => {
|
|
549
545
|
const p: any[] = message.parts ? [...message.parts] : [];
|
|
550
546
|
if (anyMessage.toolInvocations && Array.isArray(anyMessage.toolInvocations)) {
|
|
@@ -563,11 +559,8 @@ export function MessageItem({
|
|
|
563
559
|
return p;
|
|
564
560
|
}, [message.parts, anyMessage.toolInvocations]);
|
|
565
561
|
|
|
566
|
-
// Track which tool call IDs have already been applied to prevent re-application
|
|
567
562
|
const appliedToolCallsRef = useRef<Set<string>>(new Set());
|
|
568
563
|
|
|
569
|
-
// Effect to apply document edits to the Canvas context
|
|
570
|
-
// Uses a stable fingerprint to avoid re-triggering on every render
|
|
571
564
|
const docToolFingerprint = useMemo(() => {
|
|
572
565
|
if (!isLast) return '';
|
|
573
566
|
return parts
|
|
@@ -731,8 +731,7 @@ function MediaContent({
|
|
|
731
731
|
if (!res.ok) throw new Error(data.error ?? 'Media import failed');
|
|
732
732
|
const ids = (data.assets as MediaAsset[]).map((asset) => asset.id);
|
|
733
733
|
toast.success(`${mediaType === 'video' ? 'Video' : 'Audio'} import started`, {
|
|
734
|
-
description:
|
|
735
|
-
'Queued for download and indexing. Live progress will appear once the source starts responding; you can safely leave in the meantime.',
|
|
734
|
+
description: 'Queued for download and indexing. You can safely leave in the meantime.',
|
|
736
735
|
duration: 8_000,
|
|
737
736
|
});
|
|
738
737
|
await processAssets(ids);
|
|
@@ -219,7 +219,10 @@ export function UploadPanel({ onAdded }: { onAdded: () => void }) {
|
|
|
219
219
|
format: 'plain',
|
|
220
220
|
rawContent: text,
|
|
221
221
|
fileObject: file,
|
|
222
|
-
|
|
222
|
+
// PDF diagrams are often embedded alongside ordinary text. Keep
|
|
223
|
+
// visual indexing on by default, with the existing per-file toggle
|
|
224
|
+
// available for users who only want text extraction.
|
|
225
|
+
indexImages: true,
|
|
223
226
|
});
|
|
224
227
|
} else {
|
|
225
228
|
const content = await file.text();
|
|
@@ -572,7 +575,7 @@ export function UploadPanel({ onAdded }: { onAdded: () => void }) {
|
|
|
572
575
|
</button>
|
|
573
576
|
</div>
|
|
574
577
|
</div>
|
|
575
|
-
<ul className="space-y-1.5 max-h-
|
|
578
|
+
<ul className="space-y-1.5 max-h-87.5 overflow-y-auto pr-1">
|
|
576
579
|
{staged.map((f) => (
|
|
577
580
|
<li
|
|
578
581
|
key={f.id}
|
|
@@ -782,7 +785,7 @@ export function UploadPanel({ onAdded }: { onAdded: () => void }) {
|
|
|
782
785
|
<p className="text-[11px] text-muted-foreground mb-2 -mt-1">
|
|
783
786
|
Selected columns will be combined to form the searchable content.
|
|
784
787
|
</p>
|
|
785
|
-
<div className="max-h-
|
|
788
|
+
<div className="max-h-30 overflow-y-auto space-y-2 pr-2">
|
|
786
789
|
{editingFile.keys?.map((k) => {
|
|
787
790
|
const isSelected = editingFile.contentKeys?.includes(k);
|
|
788
791
|
return (
|
|
@@ -871,7 +874,7 @@ export function UploadPanel({ onAdded }: { onAdded: () => void }) {
|
|
|
871
874
|
<p className="text-[11px] text-muted-foreground mb-2 -mt-1">
|
|
872
875
|
These columns will be stored as searchable metadata.
|
|
873
876
|
</p>
|
|
874
|
-
<div className="max-h-
|
|
877
|
+
<div className="max-h-30 overflow-y-auto space-y-2 pr-2">
|
|
875
878
|
{editingFile.keys?.map((k) => {
|
|
876
879
|
const isSelected = editingFile.metadataKeys?.includes(k);
|
|
877
880
|
const disabled = k === editingFile.titleKey;
|