larkup 0.1.29 → 0.1.30
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 +5 -5
- package/.next/diagnostics/route-bundle-stats.json +35 -35
- package/.next/fallback-build-manifest.json +3 -3
- package/.next/next-minimal-server.js.nft.json +1 -1
- package/.next/next-server.js.nft.json +1 -1
- package/.next/prerender-manifest.json +3 -3
- package/.next/required-server-files.js +4 -4
- package/.next/required-server-files.json +4 -4
- package/.next/server/app/_global-error/page/build-manifest.json +2 -2
- package/.next/server/app/_global-error/page.js.nft.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/build-manifest.json +2 -2
- package/.next/server/app/_not-found/page.js.nft.json +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 +16 -16
- package/.next/server/app/_not-found.segments/_full.segment.rsc +16 -16
- package/.next/server/app/_not-found.segments/_head.segment.rsc +4 -4
- package/.next/server/app/_not-found.segments/_index.segment.rsc +11 -11
- 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 +1 -1
- package/.next/server/app/analytics/page/build-manifest.json +2 -2
- package/.next/server/app/analytics/page.js.nft.json +1 -1
- 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 +17 -17
- package/.next/server/app/analytics.segments/_full.segment.rsc +17 -17
- package/.next/server/app/analytics.segments/_head.segment.rsc +4 -4
- package/.next/server/app/analytics.segments/_index.segment.rsc +11 -11
- package/.next/server/app/analytics.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/analytics.segments/analytics/__PAGE__.segment.rsc +3 -3
- package/.next/server/app/analytics.segments/analytics.segment.rsc +3 -3
- package/.next/server/app/api/analytics/route.js.nft.json +1 -1
- package/.next/server/app/api/chat/route.js.nft.json +1 -1
- package/.next/server/app/api/chat/status/route.js.nft.json +1 -1
- package/.next/server/app/api/chat/suggestions/route.js.nft.json +1 -1
- package/.next/server/app/api/config/route.js.nft.json +1 -1
- package/.next/server/app/api/config/test/route.js.nft.json +1 -1
- package/.next/server/app/api/config/test-embedding/route.js.nft.json +1 -1
- package/.next/server/app/api/config/test-llm/route.js.nft.json +1 -1
- package/.next/server/app/api/config/test-provider/route.js +4 -4
- package/.next/server/app/api/config/test-provider/route.js.nft.json +1 -1
- package/.next/server/app/api/config/verify/route.js +3 -3
- package/.next/server/app/api/config/verify/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/doc-editor/edit/route.js.nft.json +1 -1
- package/.next/server/app/api/doc-editor/export/route.js.nft.json +1 -1
- package/.next/server/app/api/doc-editor/extract-text/route.js.nft.json +1 -1
- package/.next/server/app/api/doc-editor/parse/route.js.nft.json +1 -1
- package/.next/server/app/api/doc-editor/restore/route.js.nft.json +1 -1
- package/.next/server/app/api/document/sign/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/integrations/notion/callback/route.js.nft.json +1 -1
- package/.next/server/app/api/integrations/notion/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/marketplace/[toolId]/route.js.nft.json +1 -1
- package/.next/server/app/api/marketplace/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/models/route.js.nft.json +1 -1
- package/.next/server/app/api/parse-file/route.js.nft.json +1 -1
- package/.next/server/app/api/proxy/verify/route.js.nft.json +1 -1
- package/.next/server/app/api/sandbox/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/search/verify/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/api/vector-stores/install/route.js.nft.json +1 -1
- package/.next/server/app/api/vector-stores/status/route.js.nft.json +1 -1
- package/.next/server/app/chat/page/build-manifest.json +2 -2
- package/.next/server/app/chat/page.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 +17 -17
- package/.next/server/app/chat.segments/_full.segment.rsc +17 -17
- package/.next/server/app/chat.segments/_head.segment.rsc +4 -4
- package/.next/server/app/chat.segments/_index.segment.rsc +11 -11
- package/.next/server/app/chat.segments/_tree.segment.rsc +1 -1
- 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/build-manifest.json +2 -2
- 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 +17 -17
- package/.next/server/app/data.segments/_full.segment.rsc +17 -17
- package/.next/server/app/data.segments/_head.segment.rsc +4 -4
- package/.next/server/app/data.segments/_index.segment.rsc +11 -11
- package/.next/server/app/data.segments/_tree.segment.rsc +1 -1
- 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/favicon.ico/route.js.nft.json +1 -1
- package/.next/server/app/index.html +1 -1
- package/.next/server/app/index.rsc +16 -16
- package/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/.next/server/app/index.segments/_full.segment.rsc +16 -16
- package/.next/server/app/index.segments/_head.segment.rsc +4 -4
- package/.next/server/app/index.segments/_index.segment.rsc +11 -11
- package/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/page/build-manifest.json +2 -2
- package/.next/server/app/page.js.nft.json +1 -1
- package/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/server/app/settings/page/build-manifest.json +2 -2
- package/.next/server/app/settings/page/server-reference-manifest.json +3 -3
- 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 +18 -18
- package/.next/server/app/settings.segments/_full.segment.rsc +18 -18
- package/.next/server/app/settings.segments/_head.segment.rsc +4 -4
- package/.next/server/app/settings.segments/_index.segment.rsc +11 -11
- package/.next/server/app/settings.segments/_tree.segment.rsc +1 -1
- 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 +4 -3
- package/.next/server/chunks/0598_next_dist_esm_build_templates_app-route_1f4h7rr.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__067hiof._.js +18 -6
- package/.next/server/chunks/[root-of-the-server]__0a_0ywc._.js +18 -6
- package/.next/server/chunks/[root-of-the-server]__0u17zp8._.js +18 -6
- package/.next/server/chunks/{[root-of-the-server]__1xuhh_i._.js → [root-of-the-server]__16jk_se._.js} +2 -2
- package/.next/server/chunks/[root-of-the-server]__1ahdfq9._.js +19 -7
- package/.next/server/chunks/[root-of-the-server]__1o3rcbz._.js +2 -1
- package/.next/server/chunks/{[root-of-the-server]__10gcb7d._.js → [root-of-the-server]__1qh2h5v._.js} +2 -2
- package/.next/server/chunks/[root-of-the-server]__1s9is1o._.js +2 -1
- package/.next/server/chunks/[root-of-the-server]__1vsvck0._.js +18 -6
- package/.next/server/chunks/[root-of-the-server]__1wy6wes._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__1zptg4z._.js +2 -1
- package/.next/server/chunks/packages_core_src_generator_server-runtime_ts_1_68l7t._.js +4 -4
- package/.next/server/chunks/packages_marketplace_src_125_g2p._.js +1 -1
- package/.next/server/chunks/ssr/{[root-of-the-server]__0wdatpx._.js → [root-of-the-server]__0m21fli._.js} +1 -1
- package/.next/server/chunks/ssr/{[root-of-the-server]__1r9ap67._.js → [root-of-the-server]__0t8ud_u._.js} +1 -1
- package/.next/server/chunks/ssr/{[root-of-the-server]__046ldu_._.js → [root-of-the-server]__0xyo3ni._.js} +1 -1
- package/.next/server/chunks/ssr/{_0k81--x._.js → _0ckxy33._.js} +2 -2
- package/.next/server/chunks/ssr/_169pdlf._.js +6 -6
- package/.next/server/chunks/ssr/_1hetwwu._.js +4 -3
- package/.next/server/chunks/ssr/_1iff9ia._.js +1 -1
- package/.next/server/chunks/ssr/_1yqlx1m._.js +1 -1
- package/.next/server/chunks/ssr/apps_web_components_analytics_analytics-dashboard_tsx_1056-z3._.js +1 -1
- package/.next/server/functions-config-manifest.json +3 -1
- package/.next/server/middleware-build-manifest.js +5 -5
- package/.next/server/pages/404.html +1 -1
- package/.next/server/pages/500.html +1 -1
- package/.next/server/server-reference-manifest.js +1 -1
- package/.next/server/server-reference-manifest.json +4 -4
- package/.next/static/chunks/{1z4nte07k3dt6.js → 1-afr-snks55m.js} +1 -1
- package/.next/static/chunks/{1dykihoo_1ae5.js → 1fz_0-qb5r5wd.js} +1 -1
- package/.next/static/chunks/{1sh7d5tt49x8b.js → 1uzf7x2okeuab.js} +6 -6
- package/.next/static/chunks/{3g_wl1fri6jb-.js → 21_6-9hjj2i68.js} +1 -1
- package/.next/static/chunks/{13kyiy7q3of41.js → 2jqjx4-rh414_.js} +1 -1
- package/.next/static/chunks/2jrpgzxyrmuqp.js +121 -0
- package/.next/static/chunks/390ds7l_plpmd.js +1 -0
- package/.next/static/chunks/{3een1tiktxr6a.js → 3zw6tgf7mxo39.js} +1 -1
- package/.next/static/chunks/{turbopack-2qt7vn_ocj4ao.js → turbopack-2gu-fmc6o5wkn.js} +1 -1
- package/CHANGELOG.md +12 -0
- package/app/api/chat/route.ts +1 -0
- package/app/api/chat/tools.ts +5 -1
- package/app/api/config/test-provider/route.ts +16 -18
- package/app/api/config/verify/route.ts +5 -7
- package/app/api/firecrawl/local/route.ts +1 -1
- package/app/api/jobs/route.ts +1 -2
- package/app/api/marketplace/[toolId]/route.ts +1 -0
- 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/archive/redesign-v2/app-routes/configure/page.tsx +53 -0
- package/archive/redesign-v2/app-routes/demo/page.tsx +15 -0
- package/archive/redesign-v2/app-routes/server/page.tsx +22 -0
- package/archive/redesign-v2/app-routes/simple/chat/page.tsx +17 -0
- package/archive/redesign-v2/app-routes/simple/docs/page.tsx +21 -0
- package/archive/redesign-v2/app-routes/simple/layout.tsx +9 -0
- 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/components/analytics/analytics-dashboard.tsx +1 -1
- package/components/data/firecrawl-notice.tsx +49 -98
- package/components/data/media-panel.tsx +0 -3
- package/components/data/scrape-panel.tsx +17 -1
- package/components/onboarding/welcome-screen.tsx +45 -15
- package/components/settings/general-section.tsx +15 -10
- package/components/settings/server-section.tsx +3 -3
- package/lib/error-formatter.ts +19 -4
- package/package.json +7 -7
- package/.next/static/chunks/01qmngac69n9j.js +0 -1
- package/.next/static/chunks/102b8vinedggz.js +0 -120
- /package/.next/static/{W6QdudzTPo_OVPpNt29f7 → Laf7YhpONHOZXSCw6POiL}/_buildManifest.js +0 -0
- /package/.next/static/{W6QdudzTPo_OVPpNt29f7 → Laf7YhpONHOZXSCw6POiL}/_clientMiddlewareManifest.js +0 -0
- /package/.next/static/{W6QdudzTPo_OVPpNt29f7 → Laf7YhpONHOZXSCw6POiL}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import Link from "next/link";
|
|
4
|
+
import { usePathname } from "next/navigation";
|
|
5
|
+
import {
|
|
6
|
+
MessageCircle,
|
|
7
|
+
FileStack,
|
|
8
|
+
SlidersHorizontal,
|
|
9
|
+
type LucideIcon,
|
|
10
|
+
} from "lucide-react";
|
|
11
|
+
import { cn } from "@/lib/utils";
|
|
12
|
+
import {
|
|
13
|
+
Tooltip,
|
|
14
|
+
TooltipContent,
|
|
15
|
+
TooltipProvider,
|
|
16
|
+
TooltipTrigger,
|
|
17
|
+
} from "@/components/ui/tooltip";
|
|
18
|
+
import {
|
|
19
|
+
useThemeCustomizer,
|
|
20
|
+
type PanelBgVariant,
|
|
21
|
+
} from "@/components/theme-customizer-provider";
|
|
22
|
+
import { ThemeSwitcher } from "@/components/theme-switcher";
|
|
23
|
+
|
|
24
|
+
const NAV_BG_COLORS: Record<PanelBgVariant, string | undefined> = {
|
|
25
|
+
"panel-default": undefined,
|
|
26
|
+
"panel-white": "#FFFFFF",
|
|
27
|
+
"panel-fafafa": "#F4F4F4",
|
|
28
|
+
"panel-warm": "#F7F1EA",
|
|
29
|
+
"panel-soft": "#FBFAF8",
|
|
30
|
+
"panel-silver": "#F8F8F8",
|
|
31
|
+
"panel-stone": "#F5F5F2",
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
interface NavItem {
|
|
35
|
+
id: string;
|
|
36
|
+
label: string;
|
|
37
|
+
href: string;
|
|
38
|
+
icon: LucideIcon;
|
|
39
|
+
description: string;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const SIMPLE_NAV: NavItem[] = [
|
|
43
|
+
{
|
|
44
|
+
id: "chat",
|
|
45
|
+
label: "Chat",
|
|
46
|
+
href: "/simple/chat",
|
|
47
|
+
icon: MessageCircle,
|
|
48
|
+
description: "Chat with your knowledge base using AI.",
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
id: "docs",
|
|
52
|
+
label: "Docs",
|
|
53
|
+
href: "/simple/docs",
|
|
54
|
+
icon: FileStack,
|
|
55
|
+
description: "Upload, paste, or manage your documents.",
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
id: "settings",
|
|
59
|
+
label: "Settings",
|
|
60
|
+
href: "/simple/settings",
|
|
61
|
+
icon: SlidersHorizontal,
|
|
62
|
+
description: "Configure provider, API keys, and advanced settings.",
|
|
63
|
+
},
|
|
64
|
+
];
|
|
65
|
+
|
|
66
|
+
export function SimpleSidebar() {
|
|
67
|
+
const pathname = usePathname();
|
|
68
|
+
const { pageStyle, navBg } = useThemeCustomizer();
|
|
69
|
+
|
|
70
|
+
const navColor = navBg ? NAV_BG_COLORS[navBg] : undefined;
|
|
71
|
+
const navStyle = navColor ? { backgroundColor: navColor } : undefined;
|
|
72
|
+
|
|
73
|
+
return (
|
|
74
|
+
<TooltipProvider delay={150}>
|
|
75
|
+
<aside
|
|
76
|
+
className={cn(
|
|
77
|
+
"sticky top-0 hidden h-screen w-[84px] shrink-0 flex-col items-center gap-1 self-start py-3 md:flex",
|
|
78
|
+
!navColor ? "bg-background" : "",
|
|
79
|
+
pageStyle === "fused" ? "border-r border-border" : "",
|
|
80
|
+
)}
|
|
81
|
+
style={navStyle}
|
|
82
|
+
>
|
|
83
|
+
{/* Brand */}
|
|
84
|
+
<Tooltip>
|
|
85
|
+
<TooltipTrigger
|
|
86
|
+
render={
|
|
87
|
+
<Link
|
|
88
|
+
href="/simple/chat"
|
|
89
|
+
aria-label="larkup home"
|
|
90
|
+
className="mb-2 flex size-11 items-center justify-center rounded-xl bg-primary text-primary-foreground shadow-sm transition-transform hover:scale-105"
|
|
91
|
+
/>
|
|
92
|
+
}
|
|
93
|
+
>
|
|
94
|
+
<img src={"/logo9.png"} className="size-6.5" alt="logo" />
|
|
95
|
+
</TooltipTrigger>
|
|
96
|
+
<TooltipContent side="right" sideOffset={10}>
|
|
97
|
+
Larkup
|
|
98
|
+
</TooltipContent>
|
|
99
|
+
</Tooltip>
|
|
100
|
+
|
|
101
|
+
{/* Navigation */}
|
|
102
|
+
<nav className="flex flex-1 flex-col items-center gap-2.5">
|
|
103
|
+
{SIMPLE_NAV.map((item) => {
|
|
104
|
+
const Icon = item.icon;
|
|
105
|
+
const active = pathname?.startsWith(item.href);
|
|
106
|
+
|
|
107
|
+
return (
|
|
108
|
+
<Tooltip key={item.id}>
|
|
109
|
+
<TooltipTrigger
|
|
110
|
+
render={
|
|
111
|
+
<Link
|
|
112
|
+
href={item.href}
|
|
113
|
+
aria-current={active ? "page" : undefined}
|
|
114
|
+
className="group relative flex w-16 flex-col items-center gap-0.5 rounded-2xl py-1 outline-none focus-visible:ring-2 focus-visible:ring-ring"
|
|
115
|
+
/>
|
|
116
|
+
}
|
|
117
|
+
>
|
|
118
|
+
{/* Active accent bar */}
|
|
119
|
+
<span
|
|
120
|
+
className={cn(
|
|
121
|
+
"absolute left-0 top-1/2 h-6 w-1 -translate-y-1/2 rounded-r-full bg-primary transition-opacity",
|
|
122
|
+
active ? "opacity-100" : "opacity-0",
|
|
123
|
+
)}
|
|
124
|
+
/>
|
|
125
|
+
<span
|
|
126
|
+
className={cn(
|
|
127
|
+
"relative flex size-9 items-center justify-center rounded-xl transition-colors",
|
|
128
|
+
active
|
|
129
|
+
? "bg-white border text-primary"
|
|
130
|
+
: "text-foreground/70 group-hover:bg-white/90 group-hover:text-foreground",
|
|
131
|
+
)}
|
|
132
|
+
>
|
|
133
|
+
<Icon
|
|
134
|
+
className="size-[19px]"
|
|
135
|
+
strokeWidth={active ? 2.25 : 2}
|
|
136
|
+
/>
|
|
137
|
+
</span>
|
|
138
|
+
<span
|
|
139
|
+
className={cn(
|
|
140
|
+
"text-[10px] leading-none tracking-tight",
|
|
141
|
+
active
|
|
142
|
+
? "font-semibold text-primary"
|
|
143
|
+
: "text-muted-foreground",
|
|
144
|
+
)}
|
|
145
|
+
>
|
|
146
|
+
{item.label}
|
|
147
|
+
</span>
|
|
148
|
+
</TooltipTrigger>
|
|
149
|
+
<TooltipContent
|
|
150
|
+
side="right"
|
|
151
|
+
sideOffset={10}
|
|
152
|
+
className="max-w-56"
|
|
153
|
+
>
|
|
154
|
+
<div className="flex flex-col gap-0.5">
|
|
155
|
+
<span className="font-medium">{item.label}</span>
|
|
156
|
+
<span className="text-[11px] leading-snug opacity-80">
|
|
157
|
+
{item.description}
|
|
158
|
+
</span>
|
|
159
|
+
</div>
|
|
160
|
+
</TooltipContent>
|
|
161
|
+
</Tooltip>
|
|
162
|
+
);
|
|
163
|
+
})}
|
|
164
|
+
</nav>
|
|
165
|
+
|
|
166
|
+
{/* Footer */}
|
|
167
|
+
<ThemeSwitcher floating={false} />
|
|
168
|
+
</aside>
|
|
169
|
+
</TooltipProvider>
|
|
170
|
+
);
|
|
171
|
+
}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import Link from "next/link";
|
|
4
|
+
import { usePathname } from "next/navigation";
|
|
5
|
+
import { cn } from "@/lib/utils";
|
|
6
|
+
import {
|
|
7
|
+
Tooltip,
|
|
8
|
+
TooltipContent,
|
|
9
|
+
TooltipProvider,
|
|
10
|
+
TooltipTrigger,
|
|
11
|
+
} from "@/components/ui/tooltip";
|
|
12
|
+
import { useWorkspace } from "@/components/workspace/workspace-provider";
|
|
13
|
+
import { ThemeSwitcher } from "@/components/theme-switcher";
|
|
14
|
+
import { useThemeCustomizer, type PanelBgVariant } from "@/components/theme-customizer-provider";
|
|
15
|
+
import { MessageCircle, FileStack, SlidersHorizontal, type LucideIcon } from "lucide-react";
|
|
16
|
+
|
|
17
|
+
const NAV_BG_COLORS: Record<PanelBgVariant, string | undefined> = {
|
|
18
|
+
"panel-default": undefined,
|
|
19
|
+
"panel-white": "#FFFFFF",
|
|
20
|
+
"panel-fafafa": "#F4F4F4",
|
|
21
|
+
"panel-warm": "#F7F1EA",
|
|
22
|
+
"panel-soft": "#FBFAF8",
|
|
23
|
+
"panel-silver": "#F8F8F8",
|
|
24
|
+
"panel-stone": "#F5F5F2",
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
interface NavItem {
|
|
28
|
+
id: string;
|
|
29
|
+
label: string;
|
|
30
|
+
href: string;
|
|
31
|
+
icon: LucideIcon;
|
|
32
|
+
description: string;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const SIMPLE_NAV: NavItem[] = [
|
|
36
|
+
{
|
|
37
|
+
id: "chat",
|
|
38
|
+
label: "Chat",
|
|
39
|
+
href: "/simple/chat",
|
|
40
|
+
icon: MessageCircle,
|
|
41
|
+
description: "Chat with your knowledge base using AI.",
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
id: "docs",
|
|
45
|
+
label: "Docs",
|
|
46
|
+
href: "/simple/docs",
|
|
47
|
+
icon: FileStack,
|
|
48
|
+
description: "Upload, paste, or manage your documents.",
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
id: "settings",
|
|
52
|
+
label: "Settings",
|
|
53
|
+
href: "/simple/settings",
|
|
54
|
+
icon: SlidersHorizontal,
|
|
55
|
+
description: "Configure provider, API keys, and advanced settings.",
|
|
56
|
+
},
|
|
57
|
+
];
|
|
58
|
+
|
|
59
|
+
export function SimpleTopNav() {
|
|
60
|
+
const pathname = usePathname();
|
|
61
|
+
const { username } = useWorkspace();
|
|
62
|
+
const { navBg } = useThemeCustomizer();
|
|
63
|
+
|
|
64
|
+
const navColor = navBg ? NAV_BG_COLORS[navBg] : undefined;
|
|
65
|
+
const navStyle = navColor ? { backgroundColor: navColor } : undefined;
|
|
66
|
+
|
|
67
|
+
return (
|
|
68
|
+
<TooltipProvider delay={150}>
|
|
69
|
+
<header
|
|
70
|
+
className={cn(
|
|
71
|
+
"sticky top-0 z-50 flex h-16 shrink-0 items-center gap-4 border-b border-border px-4 md:px-6",
|
|
72
|
+
!navColor ? "bg-white" : "",
|
|
73
|
+
)}
|
|
74
|
+
style={navStyle}
|
|
75
|
+
>
|
|
76
|
+
{/* Brand */}
|
|
77
|
+
<Link
|
|
78
|
+
href="/simple/chat"
|
|
79
|
+
aria-label="larkup home"
|
|
80
|
+
className="flex size-10 shrink-0 items-center justify-center rounded-xl bg-primary text-primary-foreground shadow-sm transition-transform hover:scale-105"
|
|
81
|
+
>
|
|
82
|
+
<img src={"/logo9.png"} className="size-5" alt="logo" />
|
|
83
|
+
</Link>
|
|
84
|
+
<span className="font-semibold tracking-tight hidden sm:inline-block">
|
|
85
|
+
Larkup
|
|
86
|
+
</span>
|
|
87
|
+
|
|
88
|
+
{/* Navigation */}
|
|
89
|
+
<nav className="flex flex-1 h-full items-end pb-0 gap-2 md:gap-4 ml-4">
|
|
90
|
+
{SIMPLE_NAV.map((item, index) => {
|
|
91
|
+
const Icon = item.icon;
|
|
92
|
+
const active = pathname?.startsWith(item.href);
|
|
93
|
+
|
|
94
|
+
return (
|
|
95
|
+
<Tooltip key={item.id}>
|
|
96
|
+
<TooltipTrigger
|
|
97
|
+
render={
|
|
98
|
+
<Link
|
|
99
|
+
href={item.href}
|
|
100
|
+
aria-current={active ? "page" : undefined}
|
|
101
|
+
className={cn(
|
|
102
|
+
"group relative flex items-center gap-2 h-10 px-3 rounded-md transition-colors outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
103
|
+
active ? "bg-muted/0" : "hover:bg-muted/30",
|
|
104
|
+
)}
|
|
105
|
+
/>
|
|
106
|
+
}
|
|
107
|
+
>
|
|
108
|
+
<div className="flex items-center">
|
|
109
|
+
<span
|
|
110
|
+
className={cn(
|
|
111
|
+
"flex size-9 items-center justify-center rounded-lg transition-colors",
|
|
112
|
+
active
|
|
113
|
+
? "text-primary"
|
|
114
|
+
: "text-muted-foreground group-hover:text-foreground",
|
|
115
|
+
)}
|
|
116
|
+
>
|
|
117
|
+
<Icon
|
|
118
|
+
className="size-[18px]"
|
|
119
|
+
strokeWidth={active ? 2.25 : 2}
|
|
120
|
+
/>
|
|
121
|
+
</span>
|
|
122
|
+
<span
|
|
123
|
+
className={cn(
|
|
124
|
+
"hidden md:block text-[13px] tracking-tight",
|
|
125
|
+
active
|
|
126
|
+
? "font-semibold text-primary"
|
|
127
|
+
: "text-muted-foreground group-hover:text-foreground",
|
|
128
|
+
)}
|
|
129
|
+
>
|
|
130
|
+
{item.label}
|
|
131
|
+
</span>
|
|
132
|
+
{/* active accent bar (bottom) */}
|
|
133
|
+
<span
|
|
134
|
+
className={cn(
|
|
135
|
+
"absolute bottom-0 left-0 h-0.5 w-full bg-primary transition-opacity",
|
|
136
|
+
active
|
|
137
|
+
? "opacity-100"
|
|
138
|
+
: "opacity-0 group-hover:opacity-100",
|
|
139
|
+
)}
|
|
140
|
+
/>
|
|
141
|
+
</div>
|
|
142
|
+
</TooltipTrigger>
|
|
143
|
+
<TooltipContent
|
|
144
|
+
side="bottom"
|
|
145
|
+
sideOffset={10}
|
|
146
|
+
className="max-w-56"
|
|
147
|
+
>
|
|
148
|
+
<div className="flex flex-col gap-0.5">
|
|
149
|
+
<span className="font-medium">
|
|
150
|
+
{item.label}
|
|
151
|
+
</span>
|
|
152
|
+
<span className="text-[11px] leading-snug opacity-80">
|
|
153
|
+
{item.description}
|
|
154
|
+
</span>
|
|
155
|
+
</div>
|
|
156
|
+
</TooltipContent>
|
|
157
|
+
</Tooltip>
|
|
158
|
+
);
|
|
159
|
+
})}
|
|
160
|
+
</nav>
|
|
161
|
+
|
|
162
|
+
{/* Right side: Workspace & Theme Customizer */}
|
|
163
|
+
<div className="flex items-center gap-3">
|
|
164
|
+
{username && (
|
|
165
|
+
<span className="hidden text-sm text-muted-foreground md:block">
|
|
166
|
+
Hi,{" "}
|
|
167
|
+
<span className="font-medium text-foreground">{username}</span>
|
|
168
|
+
</span>
|
|
169
|
+
)}
|
|
170
|
+
<ThemeSwitcher floating={false} />
|
|
171
|
+
</div>
|
|
172
|
+
</header>
|
|
173
|
+
</TooltipProvider>
|
|
174
|
+
);
|
|
175
|
+
}
|
|
@@ -74,7 +74,7 @@ function formatCost(cost: number): string {
|
|
|
74
74
|
}
|
|
75
75
|
|
|
76
76
|
export function AnalyticsDashboard() {
|
|
77
|
-
const [activeTab, setActiveTab] = useState('
|
|
77
|
+
const [activeTab, setActiveTab] = useState('indexing');
|
|
78
78
|
const [timeframe, setTimeframe] = useState('14d');
|
|
79
79
|
|
|
80
80
|
const {
|
|
@@ -1,21 +1,12 @@
|
|
|
1
|
-
|
|
1
|
+
'use client';
|
|
2
2
|
|
|
3
|
-
import { useState, useEffect } from
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
Server,
|
|
11
|
-
Square,
|
|
12
|
-
TriangleAlert,
|
|
13
|
-
} from "lucide-react";
|
|
14
|
-
import { toast } from "sonner";
|
|
15
|
-
import { formatErrorMessage } from "@/lib/error-formatter";
|
|
16
|
-
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
|
|
17
|
-
import { Button } from "@/components/ui/button";
|
|
18
|
-
import { Badge } from "@/components/ui/badge";
|
|
3
|
+
import { useState, useEffect } from 'react';
|
|
4
|
+
import { useRouter } from 'next/navigation';
|
|
5
|
+
import useSWR from 'swr';
|
|
6
|
+
import { Loader2, Play, Square } from 'lucide-react';
|
|
7
|
+
import { toast } from 'sonner';
|
|
8
|
+
import { formatErrorMessage } from '@/lib/error-formatter';
|
|
9
|
+
import { Button } from '@/components/ui/button';
|
|
19
10
|
|
|
20
11
|
interface LocalState {
|
|
21
12
|
running: boolean;
|
|
@@ -33,7 +24,7 @@ interface DockerState {
|
|
|
33
24
|
interface LocalResponse {
|
|
34
25
|
state: LocalState;
|
|
35
26
|
docker: DockerState;
|
|
36
|
-
runtimeEnv?:
|
|
27
|
+
runtimeEnv?: 'web' | 'desktop' | 'docker';
|
|
37
28
|
}
|
|
38
29
|
|
|
39
30
|
const fetcher = (url: string) => fetch(url).then((r) => r.json());
|
|
@@ -57,19 +48,15 @@ export function FirecrawlNotice({
|
|
|
57
48
|
onChange?: () => void;
|
|
58
49
|
onErrorChange?: (hasError: boolean) => void;
|
|
59
50
|
}) {
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
d?.state.running || d?.state.startedAt ? 8000 : 0,
|
|
66
|
-
},
|
|
67
|
-
);
|
|
68
|
-
const [busy, setBusy] = useState<"start" | "stop" | null>(null);
|
|
51
|
+
const router = useRouter();
|
|
52
|
+
const { data, mutate, isLoading } = useSWR<LocalResponse>('/api/firecrawl/local', fetcher, {
|
|
53
|
+
refreshInterval: (d) => (d?.state.running || d?.state.startedAt ? 8000 : 0),
|
|
54
|
+
});
|
|
55
|
+
const [busy, setBusy] = useState<'start' | 'stop' | null>(null);
|
|
69
56
|
|
|
70
57
|
const state = data?.state;
|
|
71
58
|
const docker = data?.docker;
|
|
72
|
-
const runtimeEnv = data?.runtimeEnv ??
|
|
59
|
+
const runtimeEnv = data?.runtimeEnv ?? 'web';
|
|
73
60
|
const running = state?.running ?? false;
|
|
74
61
|
const dockerReady = docker?.compose ?? false;
|
|
75
62
|
const hasError = !cloudConfigured && (!dockerReady || !!state?.lastError);
|
|
@@ -80,49 +67,45 @@ export function FirecrawlNotice({
|
|
|
80
67
|
}
|
|
81
68
|
}, [hasError, isLoading, onErrorChange]);
|
|
82
69
|
|
|
83
|
-
async function control(action:
|
|
70
|
+
async function control(action: 'start' | 'stop') {
|
|
84
71
|
setBusy(action);
|
|
85
|
-
if (action ===
|
|
72
|
+
if (action === 'start') {
|
|
86
73
|
toast.info(
|
|
87
|
-
runtimeEnv ===
|
|
88
|
-
? "Connecting to crawler service…"
|
|
89
|
-
: "Launching web crawler…",
|
|
74
|
+
runtimeEnv === 'docker' ? 'Connecting to crawler service…' : 'Launching web crawler…',
|
|
90
75
|
{
|
|
91
76
|
description:
|
|
92
|
-
runtimeEnv ===
|
|
93
|
-
?
|
|
94
|
-
:
|
|
77
|
+
runtimeEnv === 'docker'
|
|
78
|
+
? 'Checking if the crawler service is available on the network.'
|
|
79
|
+
: 'Pulling images and starting containers. This can take a minute on first run.',
|
|
95
80
|
},
|
|
96
81
|
);
|
|
97
82
|
}
|
|
98
83
|
try {
|
|
99
|
-
const res = await fetch(
|
|
100
|
-
method:
|
|
101
|
-
headers: {
|
|
84
|
+
const res = await fetch('/api/firecrawl/local', {
|
|
85
|
+
method: 'POST',
|
|
86
|
+
headers: { 'Content-Type': 'application/json' },
|
|
102
87
|
body: JSON.stringify({ action }),
|
|
103
88
|
});
|
|
104
89
|
const json = (await res.json()) as { state?: LocalState; error?: string };
|
|
105
|
-
if (!res.ok) throw new Error(json.error ||
|
|
90
|
+
if (!res.ok) throw new Error(json.error || 'Request failed');
|
|
106
91
|
|
|
107
|
-
if (action ===
|
|
92
|
+
if (action === 'start') {
|
|
108
93
|
if (json.state?.running) {
|
|
109
|
-
toast.success(
|
|
110
|
-
description:
|
|
94
|
+
toast.success('Web crawler is running', {
|
|
95
|
+
description: 'Web scraping is now active.',
|
|
111
96
|
});
|
|
112
97
|
} else {
|
|
113
|
-
toast.warning(
|
|
114
|
-
description:
|
|
115
|
-
json.state?.lastError ??
|
|
116
|
-
"Waiting for the service to become healthy.",
|
|
98
|
+
toast.warning('Web crawler is starting', {
|
|
99
|
+
description: 'It may take a moment to become available. Try again shortly.',
|
|
117
100
|
});
|
|
118
101
|
}
|
|
119
102
|
} else {
|
|
120
|
-
toast.success(
|
|
103
|
+
toast.success('Web crawler stopped');
|
|
121
104
|
}
|
|
122
105
|
await mutate();
|
|
123
106
|
onChange?.();
|
|
124
107
|
} catch (err) {
|
|
125
|
-
toast.error(
|
|
108
|
+
toast.error('Could not connect to the web crawler', {
|
|
126
109
|
description: formatErrorMessage(err),
|
|
127
110
|
});
|
|
128
111
|
} finally {
|
|
@@ -130,31 +113,16 @@ export function FirecrawlNotice({
|
|
|
130
113
|
}
|
|
131
114
|
}
|
|
132
115
|
|
|
133
|
-
// Both cloud and local options are kept available.
|
|
134
|
-
|
|
135
|
-
// Description text based on environment
|
|
136
|
-
const idleDescription = (() => {
|
|
137
|
-
if (runtimeEnv === "docker") {
|
|
138
|
-
return dockerReady
|
|
139
|
-
? "A crawler service was found on the network. Click to connect."
|
|
140
|
-
: "Start your deployment with the crawler profile to enable web scraping: docker compose --profile crawler up";
|
|
141
|
-
}
|
|
142
|
-
if (cloudConfigured) {
|
|
143
|
-
return "You have a cloud key set. You can also run the crawler locally via Docker.";
|
|
144
|
-
}
|
|
145
|
-
return "Launch a self-hosted web crawler via Docker. A key is generated automatically — no signup required. Pasting and uploading work without it.";
|
|
146
|
-
})();
|
|
147
|
-
|
|
148
116
|
return (
|
|
149
117
|
<div className="flex items-center gap-2">
|
|
150
118
|
{running ? (
|
|
151
119
|
<Button
|
|
152
120
|
variant="outline"
|
|
153
121
|
className="h-10 gap-1.5 rounded-md bg-red-500 hover:bg-red-600 text-white hover:text-white hover:border-red-200 text-sm px-4 shadow-none"
|
|
154
|
-
onClick={() => control(
|
|
122
|
+
onClick={() => control('stop')}
|
|
155
123
|
disabled={busy !== null}
|
|
156
124
|
>
|
|
157
|
-
{busy ===
|
|
125
|
+
{busy === 'stop' ? (
|
|
158
126
|
<Loader2 className="size-3 animate-spin" />
|
|
159
127
|
) : (
|
|
160
128
|
<Square className="size-3" />
|
|
@@ -164,45 +132,28 @@ export function FirecrawlNotice({
|
|
|
164
132
|
) : (
|
|
165
133
|
<Button
|
|
166
134
|
variant="outline"
|
|
167
|
-
onClick={() =>
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
135
|
+
onClick={() => {
|
|
136
|
+
if (runtimeEnv === 'docker' && !dockerReady) {
|
|
137
|
+
router.push('/settings?section=general#web-crawler');
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
control('start');
|
|
141
|
+
}}
|
|
142
|
+
disabled={busy !== null || isLoading}
|
|
173
143
|
className="h-10 gap-1.5 rounded-md text-sm px-4 shadow-none bg-orange-500 text-white hover:bg-orange-600 hover:text-white"
|
|
174
144
|
>
|
|
175
|
-
{busy ===
|
|
145
|
+
{busy === 'start' ? (
|
|
176
146
|
<Loader2 className="size-3 animate-spin text-muted-foreground" />
|
|
177
147
|
) : (
|
|
178
|
-
<img
|
|
179
|
-
src="/icons/firecrawl2.png"
|
|
180
|
-
alt=""
|
|
181
|
-
className="size-3 object-contain"
|
|
182
|
-
/>
|
|
148
|
+
<img src="/icons/firecrawl2.png" alt="" className="size-3 object-contain" />
|
|
183
149
|
)}
|
|
184
|
-
{runtimeEnv ===
|
|
150
|
+
{runtimeEnv === 'docker' && !dockerReady
|
|
151
|
+
? 'Crawler settings'
|
|
152
|
+
: runtimeEnv === 'docker'
|
|
153
|
+
? 'Connect Crawler'
|
|
154
|
+
: 'Launch Crawler'}
|
|
185
155
|
</Button>
|
|
186
156
|
)}
|
|
187
|
-
|
|
188
|
-
{state?.lastError && !running && (
|
|
189
|
-
<span
|
|
190
|
-
className="text-[10px] text-destructive flex items-center gap-1 max-w-[200px] truncate"
|
|
191
|
-
title={state.lastError}
|
|
192
|
-
>
|
|
193
|
-
<TriangleAlert className="size-3 shrink-0" />
|
|
194
|
-
<span className="truncate">Error starting crawler</span>
|
|
195
|
-
</span>
|
|
196
|
-
)}
|
|
197
|
-
{!isLoading && !dockerReady && !running && docker?.message && (
|
|
198
|
-
<span
|
|
199
|
-
className="text-[10px] text-destructive flex items-center gap-1 max-w-[200px] truncate"
|
|
200
|
-
title={docker.message}
|
|
201
|
-
>
|
|
202
|
-
<TriangleAlert className="size-3 shrink-0" />
|
|
203
|
-
<span className="truncate">Docker issue</span>
|
|
204
|
-
</span>
|
|
205
|
-
)}
|
|
206
157
|
</div>
|
|
207
158
|
);
|
|
208
159
|
}
|
|
@@ -1634,9 +1634,6 @@ function ActiveIndexingList({
|
|
|
1634
1634
|
{asset.processingMessage || 'Preparing media indexing...'}
|
|
1635
1635
|
</p>
|
|
1636
1636
|
</div>
|
|
1637
|
-
{asset.processingSteps?.length ? (
|
|
1638
|
-
<PipelineSteps steps={asset.processingSteps} />
|
|
1639
|
-
) : null}
|
|
1640
1637
|
</div>
|
|
1641
1638
|
);
|
|
1642
1639
|
})}
|
|
@@ -36,6 +36,7 @@ import { GenericAlert } from '@/components/alerts/generic-alert';
|
|
|
36
36
|
import { cn } from '@/lib/utils';
|
|
37
37
|
import { Tabs, TabsList, TabsTrigger } from '@/components/ui/tabs';
|
|
38
38
|
import useSWR from 'swr';
|
|
39
|
+
import { useRouter } from 'next/navigation';
|
|
39
40
|
import type { RagConfig } from '@larkup/core/types';
|
|
40
41
|
|
|
41
42
|
const fetcher = (url: string) => fetch(url).then((r) => r.json() as Promise<{ config: RagConfig }>);
|
|
@@ -85,6 +86,7 @@ export function ScrapePanel({
|
|
|
85
86
|
onStarted: () => void;
|
|
86
87
|
crawlerControl?: React.ReactNode;
|
|
87
88
|
}) {
|
|
89
|
+
const router = useRouter();
|
|
88
90
|
const {
|
|
89
91
|
query,
|
|
90
92
|
setQuery,
|
|
@@ -124,6 +126,15 @@ export function ScrapePanel({
|
|
|
124
126
|
const inputRef = useRef<HTMLInputElement>(null);
|
|
125
127
|
const dropdownRef = useRef<HTMLDivElement>(null);
|
|
126
128
|
|
|
129
|
+
function showCrawlerSettings() {
|
|
130
|
+
toast.error('Web crawler is not available. Choose a crawler provider in Settings.', {
|
|
131
|
+
action: {
|
|
132
|
+
label: 'Open settings',
|
|
133
|
+
onClick: () => router.push('/settings?section=general#web-crawler'),
|
|
134
|
+
},
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
|
|
127
138
|
useEffect(() => {
|
|
128
139
|
function handleClickOutside(event: MouseEvent) {
|
|
129
140
|
if (
|
|
@@ -222,7 +233,12 @@ export function ScrapePanel({
|
|
|
222
233
|
fetchProviderTotalCount(q, activeProvider);
|
|
223
234
|
}
|
|
224
235
|
} catch (err) {
|
|
225
|
-
|
|
236
|
+
const message = formatErrorMessage(err);
|
|
237
|
+
if (/crawler|firecrawl|not running|api key/i.test(message)) {
|
|
238
|
+
showCrawlerSettings();
|
|
239
|
+
} else {
|
|
240
|
+
toast.error(message);
|
|
241
|
+
}
|
|
226
242
|
}
|
|
227
243
|
}
|
|
228
244
|
|