larkup 0.1.14

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.
Files changed (141) hide show
  1. package/.env +2 -0
  2. package/app/actions/vercel.ts +417 -0
  3. package/app/api/chat/route.ts +192 -0
  4. package/app/api/chat/status/route.ts +55 -0
  5. package/app/api/chat/suggestions/route.ts +115 -0
  6. package/app/api/config/route.ts +73 -0
  7. package/app/api/config/test/route.ts +67 -0
  8. package/app/api/config/test-embedding/route.ts +40 -0
  9. package/app/api/config/test-llm/route.ts +47 -0
  10. package/app/api/config/test-provider/route.ts +36 -0
  11. package/app/api/demo/route.ts +176 -0
  12. package/app/api/deploy/ssh/route.ts +340 -0
  13. package/app/api/documents/route.ts +90 -0
  14. package/app/api/firecrawl/local/route.ts +46 -0
  15. package/app/api/index/route.ts +113 -0
  16. package/app/api/jobs/[id]/route.ts +44 -0
  17. package/app/api/jobs/route.ts +116 -0
  18. package/app/api/parse-file/route.ts +39 -0
  19. package/app/api/search/google/route.ts +162 -0
  20. package/app/api/search/route.ts +29 -0
  21. package/app/api/server/download/route.ts +112 -0
  22. package/app/api/server/generate/route.ts +46 -0
  23. package/app/api/server/local/route.ts +42 -0
  24. package/app/api/servers/route.ts +137 -0
  25. package/app/api/vector-stores/install/route.ts +65 -0
  26. package/app/api/vector-stores/status/route.ts +26 -0
  27. package/app/chat/page.tsx +15 -0
  28. package/app/configure/page.tsx +53 -0
  29. package/app/data/page.tsx +15 -0
  30. package/app/demo/page.tsx +15 -0
  31. package/app/favicon.ico +0 -0
  32. package/app/globals.css +190 -0
  33. package/app/index-data/page.tsx +15 -0
  34. package/app/layout.tsx +51 -0
  35. package/app/page.tsx +34 -0
  36. package/app/server/page.tsx +22 -0
  37. package/app/simple/chat/page.tsx +17 -0
  38. package/app/simple/docs/page.tsx +21 -0
  39. package/app/simple/layout.tsx +9 -0
  40. package/app/simple/settings/page.tsx +627 -0
  41. package/app/template.tsx +16 -0
  42. package/app/themes.css +733 -0
  43. package/components/alerts/generic-alert.tsx +74 -0
  44. package/components/app-sidebar.tsx +187 -0
  45. package/components/app-topnav.tsx +195 -0
  46. package/components/chat/chat-settings-modal.tsx +209 -0
  47. package/components/chat/chat-workspace.tsx +348 -0
  48. package/components/chat/knowledge-base-result.tsx +97 -0
  49. package/components/chat/message-item.tsx +103 -0
  50. package/components/client-layout-wrapper.tsx +182 -0
  51. package/components/configure/configure-form.tsx +1683 -0
  52. package/components/configure/store-fields.tsx +152 -0
  53. package/components/data/corpus-panel.tsx +499 -0
  54. package/components/data/data-workspace.tsx +272 -0
  55. package/components/data/firecrawl-notice.tsx +236 -0
  56. package/components/data/jobs-panel.tsx +485 -0
  57. package/components/data/paste-panel.tsx +79 -0
  58. package/components/data/scrape-panel.tsx +964 -0
  59. package/components/data/upload-panel.tsx +714 -0
  60. package/components/demo/demo-workspace.tsx +419 -0
  61. package/components/global-settings.tsx +286 -0
  62. package/components/index/index-workspace.tsx +482 -0
  63. package/components/onboarding/simple-setup.tsx +702 -0
  64. package/components/onboarding/tech-setup.tsx +121 -0
  65. package/components/onboarding/welcome-screen.tsx +183 -0
  66. package/components/page-header.tsx +44 -0
  67. package/components/server/code-viewer.tsx +87 -0
  68. package/components/server/deploy-button.tsx +1390 -0
  69. package/components/server/server-workspace.tsx +392 -0
  70. package/components/simple/sdk-connect-dialog.tsx +201 -0
  71. package/components/simple/simple-index-button.tsx +83 -0
  72. package/components/simple/simple-sidebar.tsx +161 -0
  73. package/components/theme-customizer-provider.tsx +171 -0
  74. package/components/theme-switcher.tsx +445 -0
  75. package/components/ui/alert-dialog.tsx +187 -0
  76. package/components/ui/alert.tsx +76 -0
  77. package/components/ui/badge.tsx +52 -0
  78. package/components/ui/button.tsx +59 -0
  79. package/components/ui/card.tsx +103 -0
  80. package/components/ui/checkbox.tsx +28 -0
  81. package/components/ui/collapsible.tsx +21 -0
  82. package/components/ui/dialog.tsx +159 -0
  83. package/components/ui/dropdown-menu.tsx +281 -0
  84. package/components/ui/input.tsx +22 -0
  85. package/components/ui/label.tsx +20 -0
  86. package/components/ui/popover.tsx +90 -0
  87. package/components/ui/progress.tsx +83 -0
  88. package/components/ui/provider-icon.tsx +94 -0
  89. package/components/ui/scroll-area.tsx +55 -0
  90. package/components/ui/select.tsx +248 -0
  91. package/components/ui/separator.tsx +25 -0
  92. package/components/ui/sheet.tsx +138 -0
  93. package/components/ui/skeleton.tsx +13 -0
  94. package/components/ui/sonner.tsx +63 -0
  95. package/components/ui/switch.tsx +32 -0
  96. package/components/ui/table.tsx +116 -0
  97. package/components/ui/tabs.tsx +84 -0
  98. package/components/ui/textarea.tsx +18 -0
  99. package/components/ui/tooltip.tsx +66 -0
  100. package/components/workspace/delete-server-dialog.tsx +71 -0
  101. package/components/workspace/server-form-dialog.tsx +103 -0
  102. package/components/workspace/server-switcher.tsx +163 -0
  103. package/components/workspace/workspace-provider.tsx +177 -0
  104. package/components/workspace/workspace-top-bar.tsx +23 -0
  105. package/components.json +21 -0
  106. package/lib/error-formatter.ts +15 -0
  107. package/lib/utils.ts +6 -0
  108. package/next-env.d.ts +6 -0
  109. package/next.config.mjs +18 -0
  110. package/package.json +65 -0
  111. package/postcss.config.mjs +8 -0
  112. package/public/docker.png +0 -0
  113. package/public/favicon.ico +0 -0
  114. package/public/github.svg +3 -0
  115. package/public/hetzner.svg +1 -0
  116. package/public/icons/aws.svg +38 -0
  117. package/public/icons/azure.svg +1 -0
  118. package/public/icons/chroma.png +0 -0
  119. package/public/icons/cohere.svg +30 -0
  120. package/public/icons/digital-ocean.webp +0 -0
  121. package/public/icons/firecrawl2.png +0 -0
  122. package/public/icons/gcp.svg +1 -0
  123. package/public/icons/gemini.svg +1 -0
  124. package/public/icons/jina.svg +1 -0
  125. package/public/icons/lancedb2.png +0 -0
  126. package/public/icons/mistral.svg +469 -0
  127. package/public/icons/nomic.png +0 -0
  128. package/public/icons/openai.svg +1 -0
  129. package/public/icons/pgvector2.png +0 -0
  130. package/public/icons/pinecone.png +0 -0
  131. package/public/icons/qdrant.svg +35 -0
  132. package/public/icons/supabase.png +0 -0
  133. package/public/icons/vercel copy.svg +1 -0
  134. package/public/icons/vercel.svg +1 -0
  135. package/public/icons/voyage-light.png +0 -0
  136. package/public/icons/weaviate.webp +0 -0
  137. package/public/logo-light.png +0 -0
  138. package/public/logo.png +0 -0
  139. package/public/logo9.png +0 -0
  140. package/public/vercel.svg +1 -0
  141. package/tsconfig.json +33 -0
@@ -0,0 +1,121 @@
1
+ "use client";
2
+
3
+ import { useState } from "react";
4
+ import { toast } from "sonner";
5
+ import { ArrowLeft, ArrowRight, Loader2, Boxes } from "lucide-react";
6
+ import { Button } from "@/components/ui/button";
7
+ import { Input } from "@/components/ui/input";
8
+ import { Label } from "@/components/ui/label";
9
+ import { useWorkspace } from "@/components/workspace/workspace-provider";
10
+
11
+ interface TechSetupProps {
12
+ onBack: () => void;
13
+ }
14
+
15
+ export function TechSetup({ onBack }: TechSetupProps) {
16
+ const { setUsername, createServer, setMode } = useWorkspace();
17
+ const [username, setName] = useState("");
18
+ const [serverName, setServerName] = useState("my-first-rag");
19
+ const [busy, setBusy] = useState(false);
20
+
21
+ async function start() {
22
+ const who = username.trim();
23
+ const srv = serverName.trim();
24
+ if (!who) {
25
+ toast.error("Tell us your name first.");
26
+ return;
27
+ }
28
+ if (!srv) {
29
+ toast.error("Name your first server.");
30
+ return;
31
+ }
32
+ setBusy(true);
33
+ try {
34
+ await setUsername(who);
35
+ await createServer(srv);
36
+ await setMode("tech");
37
+ toast.success(`Welcome, ${who}! "${srv}" is ready.`);
38
+ } catch {
39
+ toast.error("Setup failed. Please try again.");
40
+ setBusy(false);
41
+ }
42
+ }
43
+
44
+ return (
45
+ <div className="fixed inset-0 z-50 flex items-center justify-center" style={{ backgroundColor: '#FCFCFB' }}>
46
+ {/* Background blobs */}
47
+ <div className="pointer-events-none absolute inset-0 overflow-hidden">
48
+ <div className="absolute -left-20 -top-20 h-[500px] w-[500px] rounded-full bg-stone-200/40 blur-3xl animate-pulse" />
49
+ <div className="absolute -bottom-32 -right-32 h-[600px] w-[600px] rounded-full bg-amber-100/30 blur-3xl animate-pulse [animation-delay:1s]" />
50
+ </div>
51
+
52
+ <div className="relative z-10 flex w-full max-w-md flex-col items-center gap-8 px-6">
53
+ {/* Back button */}
54
+ <button
55
+ type="button"
56
+ onClick={onBack}
57
+ className="absolute left-6 top-8 flex items-center gap-1.5 text-sm text-muted-foreground hover:text-foreground transition-colors sm:left-0 sm:top-0 sm:relative sm:self-start sm:-mt-4"
58
+ >
59
+ <ArrowLeft className="size-4" />
60
+ Back
61
+ </button>
62
+
63
+ {/* Header */}
64
+ <div className="flex flex-col items-center gap-3 text-center">
65
+ <div className="flex size-14 items-center justify-center rounded-2xl bg-primary text-primary-foreground">
66
+ <img src="/logo9.png" className="size-7" alt="Larkup" />
67
+ </div>
68
+ <div>
69
+ <h1 className="text-2xl font-bold tracking-tight text-foreground">
70
+ Set up your workspace
71
+ </h1>
72
+ <p className="mt-1.5 text-sm text-muted-foreground text-pretty">
73
+ Build, index, and serve your own RAG pipelines. Let&apos;s create
74
+ your first server.
75
+ </p>
76
+ </div>
77
+ </div>
78
+
79
+ {/* Form */}
80
+ <div className="w-full rounded-2xl border bg-transparent p-6 space-y-5">
81
+ <div className="grid gap-2">
82
+ <Label htmlFor="tech-name">What should we call you?</Label>
83
+ <Input
84
+ id="tech-name"
85
+ autoFocus
86
+ value={username}
87
+ placeholder="Your name"
88
+ onChange={(e) => setName(e.target.value)}
89
+ />
90
+ </div>
91
+ <div className="grid gap-2">
92
+ <Label htmlFor="tech-server">Name your first server</Label>
93
+ <Input
94
+ id="tech-server"
95
+ value={serverName}
96
+ placeholder="my-first-rag"
97
+ onChange={(e) => setServerName(e.target.value)}
98
+ onKeyDown={(e) => {
99
+ if (e.key === "Enter") void start();
100
+ }}
101
+ />
102
+ </div>
103
+
104
+ <Button
105
+ className="w-full"
106
+ size="lg"
107
+ onClick={() => void start()}
108
+ disabled={busy}
109
+ >
110
+ {busy ? (
111
+ <Loader2 className="size-4 animate-spin" />
112
+ ) : (
113
+ <ArrowRight className="size-4" />
114
+ )}
115
+ Create my first server
116
+ </Button>
117
+ </div>
118
+ </div>
119
+ </div>
120
+ );
121
+ }
@@ -0,0 +1,183 @@
1
+ "use client";
2
+
3
+ import { useState } from "react";
4
+ import { Code2, Sparkles, ArrowRight, Boxes } from "lucide-react";
5
+ import { cn } from "@/lib/utils";
6
+
7
+ interface WelcomeScreenProps {
8
+ onSelectTech: () => void;
9
+ onSelectSimple: () => void;
10
+ }
11
+
12
+ export function WelcomeScreen({
13
+ onSelectTech,
14
+ onSelectSimple,
15
+ }: WelcomeScreenProps) {
16
+ const [hovered, setHovered] = useState<"tech" | "simple" | null>(null);
17
+
18
+ return (
19
+ <div className="fixed inset-0 z-50 flex items-center justify-center" style={{ backgroundColor: '#FCFCFB' }}>
20
+ {/* Subtle animated background pattern */}
21
+ <div className="pointer-events-none absolute inset-0 overflow-hidden">
22
+ <div className="absolute -left-20 -top-20 h-[500px] w-[500px] rounded-full bg-stone-200/40 blur-3xl animate-pulse" />
23
+ <div className="absolute -bottom-32 -right-32 h-[600px] w-[600px] rounded-full bg-amber-100/30 blur-3xl animate-pulse [animation-delay:1s]" />
24
+ <div className="absolute left-1/2 top-1/3 h-[300px] w-[300px] -translate-x-1/2 rounded-full bg-stone-100/50 blur-3xl animate-pulse [animation-delay:2s]" />
25
+ </div>
26
+
27
+ <div className="relative z-10 flex w-full max-w-4xl flex-col items-center gap-10 px-6">
28
+ {/* Header */}
29
+ <div className="flex flex-col items-center gap-4 text-center">
30
+ <div className="flex size-16 items-center justify-center rounded-2xl bg-primary text-primary-foreground">
31
+ <img src="/logo9.png" className="size-8" alt="Larkup" />
32
+ </div>
33
+ <div>
34
+ <h1 className="text-3xl font-bold tracking-tight text-foreground sm:text-4xl">
35
+ Welcome to Larkup
36
+ </h1>
37
+ <p className="mt-2 text-base text-muted-foreground max-w-md mx-auto text-pretty">
38
+ Build, index, and query your knowledge base with AI. How would you
39
+ like to get started?
40
+ </p>
41
+ </div>
42
+ </div>
43
+
44
+ {/* Cards */}
45
+ <div className="grid w-full gap-5 sm:grid-cols-2">
46
+ {/* Tech Card */}
47
+ <button
48
+ type="button"
49
+ onClick={onSelectTech}
50
+ onMouseEnter={() => setHovered("tech")}
51
+ onMouseLeave={() => setHovered(null)}
52
+ className={cn(
53
+ "group relative flex flex-col items-start gap-5 rounded-2xl border-2 bg-transparent p-7 text-left transition-all duration-300 cursor-pointer outline-none focus-visible:ring-2 focus-visible:ring-primary",
54
+ hovered === "tech"
55
+ ? "border-primary scale-[1.02]"
56
+ : hovered === "simple"
57
+ ? "border-border/60 opacity-70"
58
+ : "border-border hover:border-primary/40",
59
+ )}
60
+ >
61
+ <div className="flex w-full items-start justify-between">
62
+ <div
63
+ className={cn(
64
+ "flex size-12 items-center justify-center rounded-xl transition-colors duration-300",
65
+ hovered === "tech"
66
+ ? "bg-primary text-primary-foreground"
67
+ : "bg-slate-100 text-slate-600",
68
+ )}
69
+ >
70
+ <Code2 className="size-6" />
71
+ </div>
72
+ <ArrowRight
73
+ className={cn(
74
+ "size-5 text-muted-foreground transition-all duration-300",
75
+ hovered === "tech" ? "translate-x-1 text-primary" : "",
76
+ )}
77
+ />
78
+ </div>
79
+
80
+ <div className="space-y-2">
81
+ <h2 className="text-xl font-semibold text-foreground">
82
+ Developer Mode
83
+ </h2>
84
+ <p className="text-sm leading-relaxed text-muted-foreground">
85
+ Full control over your RAG pipeline, configure embeddings,
86
+ vector stores, indexing strategies, and deploy a custom server.
87
+ </p>
88
+ </div>
89
+
90
+ <div className="flex flex-wrap gap-2">
91
+ {[
92
+ "Pipeline Control",
93
+ "Custom Vector Stores",
94
+ "Server Deploy",
95
+ ].map((tag) => (
96
+ <span
97
+ key={tag}
98
+ className="rounded-full border border-border bg-slate-50 px-2.5 py-0.5 text-[11px] font-medium text-muted-foreground"
99
+ >
100
+ {tag}
101
+ </span>
102
+ ))}
103
+ </div>
104
+
105
+ <span
106
+ className={cn(
107
+ "text-xs font-medium transition-colors",
108
+ hovered === "tech"
109
+ ? "text-primary"
110
+ : "text-muted-foreground/60",
111
+ )}
112
+ >
113
+ I know what I&apos;m doing →
114
+ </span>
115
+ </button>
116
+
117
+ {/* Simple Card */}
118
+ <button
119
+ type="button"
120
+ onClick={onSelectSimple}
121
+ onMouseEnter={() => setHovered("simple")}
122
+ onMouseLeave={() => setHovered(null)}
123
+ className={cn(
124
+ "group relative flex flex-col items-start gap-5 rounded-2xl border-2 bg-transparent p-7 text-left transition-all duration-300 cursor-pointer outline-none focus-visible:ring-2 focus-visible:ring-primary",
125
+ hovered === "simple"
126
+ ? "border-primary scale-[1.02]"
127
+ : hovered === "tech"
128
+ ? "border-border/60 opacity-70"
129
+ : "border-border hover:border-primary/30",
130
+ )}
131
+ >
132
+ <div className="flex w-full items-start justify-between">
133
+ <div
134
+ className={cn(
135
+ "flex size-12 items-center justify-center rounded-xl transition-colors duration-300",
136
+ hovered === "simple"
137
+ ? "bg-primary text-primary-foreground"
138
+ : "bg-primary/10 text-primary",
139
+ )}
140
+ >
141
+ <Sparkles className="size-6" />
142
+ </div>
143
+ <ArrowRight
144
+ className={cn(
145
+ "size-5 text-muted-foreground transition-all duration-300",
146
+ hovered === "simple" ? "translate-x-1 text-primary" : "",
147
+ )}
148
+ />
149
+ </div>
150
+
151
+ <div className="space-y-2">
152
+ <h2 className="text-xl font-semibold text-foreground">
153
+ Simple Mode
154
+ </h2>
155
+ <p className="text-sm leading-relaxed text-muted-foreground">
156
+ Just upload your documents and start chatting. we&apos;ll handle
157
+ the rest. Perfect for getting quick answers from your knowledge
158
+ base.
159
+ </p>
160
+ </div>
161
+
162
+ <div className="flex flex-wrap gap-2">
163
+ {["Upload & Chat", "Auto Setup", "Instant RAG"].map((tag) => (
164
+ <span key={tag} className="rounded-full border border-primary/20 bg-primary/5 px-2.5 py-0.5 text-[11px] font-medium text-primary">
165
+ {tag}
166
+ </span>
167
+ ))}
168
+ </div>
169
+
170
+ <span
171
+ className={cn(
172
+ "text-xs font-medium transition-colors",
173
+ hovered === "simple" ? "text-primary" : "text-muted-foreground/60",
174
+ )}
175
+ >
176
+ Just let my LLM know my docs →
177
+ </span>
178
+ </button>
179
+ </div>
180
+ </div>
181
+ </div>
182
+ );
183
+ }
@@ -0,0 +1,44 @@
1
+ import { cn } from "@/lib/utils";
2
+ import type { ReactNode } from "react";
3
+
4
+ interface PageHeaderProps {
5
+ eyebrow?: string;
6
+ title: string;
7
+ description?: string;
8
+ actions?: ReactNode;
9
+ className?: string;
10
+ }
11
+
12
+ export function PageHeader({
13
+ eyebrow,
14
+ title,
15
+ description,
16
+ actions,
17
+ className,
18
+ }: PageHeaderProps) {
19
+ return (
20
+ <div
21
+ className={cn(
22
+ "flex flex-col gap-4 px-6 py-4 sm:flex-row sm:items-center sm:justify-between md:px-8",
23
+ className,
24
+ )}
25
+ >
26
+ <div className="space-y-1">
27
+ {eyebrow && (
28
+ <p className="text-[11px] font-medium uppercase tracking-wider text-primary font-mono">
29
+ {eyebrow}
30
+ </p>
31
+ )}
32
+ <h1 className="text-2xl font-semibold tracking-tight text-balance">
33
+ {title}
34
+ </h1>
35
+ {description && (
36
+ <p className="max-w-2xl text-sm leading-relaxed text-muted-foreground text-pretty">
37
+ {description}
38
+ </p>
39
+ )}
40
+ </div>
41
+ {actions && <div className="flex items-center gap-2">{actions}</div>}
42
+ </div>
43
+ );
44
+ }
@@ -0,0 +1,87 @@
1
+ "use client"
2
+
3
+ import { useMemo } from "react"
4
+ import CodeMirror, { EditorView, type Extension } from "@uiw/react-codemirror"
5
+ import { javascript } from "@codemirror/lang-javascript"
6
+ import { json } from "@codemirror/lang-json"
7
+ import { markdown } from "@codemirror/lang-markdown"
8
+ import { yaml } from "@codemirror/lang-yaml"
9
+ import { python } from "@codemirror/lang-python"
10
+ import { githubLight, githubDark } from "@uiw/codemirror-theme-github"
11
+
12
+ /** Map a generated file's language hint to a CodeMirror language extension. */
13
+ function languageExtension(language: string): Extension[] {
14
+ switch (language) {
15
+ case "javascript":
16
+ return [javascript({ jsx: true })]
17
+ case "json":
18
+ return [json()]
19
+ case "markdown":
20
+ return [markdown()]
21
+ case "yaml":
22
+ return [yaml()]
23
+ case "python":
24
+ return [python()]
25
+ default:
26
+ return []
27
+ }
28
+ }
29
+
30
+ /** Blend CodeMirror into the card surface instead of its own white sheet. */
31
+ const surfaceTheme = EditorView.theme({
32
+ "&": {
33
+ backgroundColor: "transparent",
34
+ fontSize: "12px",
35
+ },
36
+ ".cm-gutters": {
37
+ backgroundColor: "transparent",
38
+ border: "none",
39
+ color: "var(--muted-foreground)",
40
+ },
41
+ ".cm-activeLine": { backgroundColor: "transparent" },
42
+ ".cm-activeLineGutter": { backgroundColor: "transparent" },
43
+ ".cm-scroller": {
44
+ fontFamily: "var(--font-mono), ui-monospace, monospace",
45
+ lineHeight: "1.6",
46
+ },
47
+ })
48
+
49
+ /**
50
+ * Read-only, syntax-highlighted file viewer used by the Server stage. Replaces
51
+ * the plain <pre> preview with proper tokenized highlighting.
52
+ */
53
+ export function CodeViewer({
54
+ value,
55
+ language,
56
+ height = "26rem",
57
+ theme = "light",
58
+ }: {
59
+ value: string
60
+ language: string
61
+ height?: string
62
+ theme?: "light" | "dark"
63
+ }) {
64
+ const extensions = useMemo(
65
+ () => [...languageExtension(language), surfaceTheme, EditorView.lineWrapping],
66
+ [language],
67
+ )
68
+
69
+ return (
70
+ <CodeMirror
71
+ value={value}
72
+ height={height}
73
+ readOnly
74
+ editable={false}
75
+ theme={theme === "dark" ? githubDark : githubLight}
76
+ extensions={extensions}
77
+ basicSetup={{
78
+ lineNumbers: true,
79
+ foldGutter: false,
80
+ highlightActiveLine: false,
81
+ highlightActiveLineGutter: false,
82
+ highlightSelectionMatches: false,
83
+ searchKeymap: false,
84
+ }}
85
+ />
86
+ )
87
+ }