@retrivora-ai/rag-engine 1.9.7 → 1.9.9
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/README.md +136 -136
- package/dist/{ILLMProvider-Bhk6zJOK.d.mts → ILLMProvider-DMxLyTdq.d.mts} +59 -4
- package/dist/{ILLMProvider-Bhk6zJOK.d.ts → ILLMProvider-DMxLyTdq.d.ts} +59 -4
- package/dist/handlers/index.d.mts +2 -2
- package/dist/handlers/index.d.ts +2 -2
- package/dist/handlers/index.js +2327 -474
- package/dist/handlers/index.mjs +2329 -473
- package/dist/{index-B9J_XEh0.d.ts → index-CfkqZd2Y.d.ts} +12 -2
- package/dist/{index-C3SVtPYg.d.mts → index-DXd29KMq.d.mts} +27 -52
- package/dist/{index-Bu7T6xgr.d.ts → index-D_bOdJML.d.ts} +27 -52
- package/dist/{index-BJ4cd-t5.d.mts → index-xygonxpW.d.mts} +12 -2
- package/dist/index.css +783 -550
- package/dist/index.d.mts +35 -7
- package/dist/index.d.ts +35 -7
- package/dist/index.js +419 -282
- package/dist/index.mjs +426 -292
- package/dist/server.d.mts +65 -6
- package/dist/server.d.ts +65 -6
- package/dist/server.js +2185 -317
- package/dist/server.mjs +2185 -317
- package/package.json +13 -8
- package/src/app/constants.tsx +37 -7
- package/src/app/page.tsx +2 -0
- package/src/components/ChatWidget.tsx +2 -1
- package/src/components/ChatWindow.tsx +4 -1
- package/src/components/CodeViewer.tsx +19 -14
- package/src/components/MarkdownComponents.tsx +44 -1
- package/src/components/MessageBubble.tsx +162 -50
- package/src/components/constants.tsx +228 -0
- package/src/config/RagConfig.ts +48 -2
- package/src/config/constants.ts +4 -0
- package/src/config/serverConfig.ts +15 -0
- package/src/core/ConfigResolver.ts +38 -6
- package/src/core/DatabaseStorage.ts +469 -0
- package/src/core/LicenseVerifier.ts +260 -0
- package/src/core/MultiAgentCoordinator.ts +239 -0
- package/src/core/Pipeline.ts +151 -18
- package/src/core/Retrivora.ts +7 -0
- package/src/core/VectorPlugin.ts +12 -3
- package/src/core/mcp.ts +261 -0
- package/src/handlers/index.ts +449 -63
- package/src/hooks/useRagChat.ts +96 -42
- package/src/hooks/useStoredMessages.ts +15 -4
- package/src/index.ts +3 -0
- package/src/llm/LLMFactory.ts +9 -1
- package/src/llm/providers/GroqProvider.ts +176 -0
- package/src/llm/providers/QwenProvider.ts +191 -0
- package/src/server.ts +7 -0
- package/src/types/chat.ts +14 -0
- package/src/types/props.ts +12 -0
- package/.env.example +0 -80
- package/LICENSE.txt +0 -21
- package/src/components/AmbientBackground.tsx +0 -29
- package/src/components/ArchitectureCard.tsx +0 -17
- package/src/components/ArchitectureCardsSection.tsx +0 -15
- package/src/components/DocViewer.tsx +0 -103
- package/src/components/Documentation.tsx +0 -121
- package/src/components/Hero.tsx +0 -59
- package/src/components/Lifecycle.tsx +0 -37
- package/src/components/Navbar.tsx +0 -55
package/src/server.ts
CHANGED
|
@@ -25,6 +25,7 @@ export type { ILLMProvider, EmbedOptions } from './llm/ILLMProvider';
|
|
|
25
25
|
export type { Chunk, ChunkOptions } from './rag/DocumentChunker';
|
|
26
26
|
export type { HealthCheckResult, IProviderValidator, IProviderHealthChecker } from './core/ProviderInterfaces';
|
|
27
27
|
export type { ValidationError } from './core/ConfigValidator';
|
|
28
|
+
export type { LicensePayload } from './core/LicenseVerifier';
|
|
28
29
|
export type { BatchOptions, BatchResult } from './core/BatchProcessor';
|
|
29
30
|
|
|
30
31
|
// ── Core Orchestration ─────────────────────────────────────────
|
|
@@ -34,6 +35,7 @@ export { Pipeline } from './core/Pipeline';
|
|
|
34
35
|
export { ConfigResolver } from './core/ConfigResolver';
|
|
35
36
|
export { ProviderRegistry } from './core/ProviderRegistry';
|
|
36
37
|
export { ConfigValidator } from './core/ConfigValidator';
|
|
38
|
+
export { LicenseVerifier } from './core/LicenseVerifier';
|
|
37
39
|
export { ProviderHealthCheck } from './core/ProviderHealthCheck';
|
|
38
40
|
export { BatchProcessor } from './core/BatchProcessor';
|
|
39
41
|
|
|
@@ -65,6 +67,8 @@ export { LLMFactory } from './llm/LLMFactory';
|
|
|
65
67
|
export { OpenAIProvider } from './llm/providers/OpenAIProvider';
|
|
66
68
|
export { AnthropicProvider } from './llm/providers/AnthropicProvider';
|
|
67
69
|
export { OllamaProvider } from './llm/providers/OllamaProvider';
|
|
70
|
+
export { GroqProvider } from './llm/providers/GroqProvider';
|
|
71
|
+
export { QwenProvider } from './llm/providers/QwenProvider';
|
|
68
72
|
export { UniversalLLMAdapter } from './llm/providers/UniversalLLMAdapter';
|
|
69
73
|
|
|
70
74
|
// ── Next.js Route Handler Factories ───────────────────────────
|
|
@@ -74,6 +78,9 @@ export {
|
|
|
74
78
|
createIngestHandler,
|
|
75
79
|
createHealthHandler,
|
|
76
80
|
createUploadHandler,
|
|
81
|
+
createHistoryHandler,
|
|
82
|
+
createFeedbackHandler,
|
|
83
|
+
createSessionsHandler,
|
|
77
84
|
createRagHandler,
|
|
78
85
|
sseFrame,
|
|
79
86
|
sseTextFrame,
|
package/src/types/chat.ts
CHANGED
|
@@ -41,6 +41,12 @@ export interface ChatOptions {
|
|
|
41
41
|
export interface UseRagChatOptions {
|
|
42
42
|
/** Override the chat API endpoint (default: /api/chat) */
|
|
43
43
|
apiUrl?: string;
|
|
44
|
+
/**
|
|
45
|
+
* Base URL for the Retrivora SDK catch-all route used for history, feedback,
|
|
46
|
+
* and sessions endpoints. Defaults to '/api/retrivora'.
|
|
47
|
+
* e.g. if your catch-all is at /api/retrivora/[[...retrivora]], set this to '/api/retrivora'.
|
|
48
|
+
*/
|
|
49
|
+
retrivoraApiBase?: string;
|
|
44
50
|
/** Override project namespace */
|
|
45
51
|
namespace?: string;
|
|
46
52
|
/** Persist chat history to localStorage (default: true) */
|
|
@@ -51,6 +57,8 @@ export interface UseRagChatOptions {
|
|
|
51
57
|
onError?: (error: string) => void;
|
|
52
58
|
/** Optional custom headers to send with the chat request */
|
|
53
59
|
headers?: Record<string, string>;
|
|
60
|
+
/** Session ID for history and feedback tracking (default: 'default') */
|
|
61
|
+
sessionId?: string;
|
|
54
62
|
}
|
|
55
63
|
|
|
56
64
|
export interface UseRagChatReturn {
|
|
@@ -70,4 +78,10 @@ export interface UseRagChatReturn {
|
|
|
70
78
|
setMessages: React.Dispatch<React.SetStateAction<RagMessage[]>>;
|
|
71
79
|
/** Abort the current active stream request */
|
|
72
80
|
stop: () => void;
|
|
81
|
+
/** Load message history from database storage */
|
|
82
|
+
loadHistory: (sessionId: string) => Promise<void>;
|
|
83
|
+
/** Clear conversation history from database and locally */
|
|
84
|
+
clearHistory: (sessionId: string) => Promise<void>;
|
|
85
|
+
/** Submit rating and optional comment for a specific assistant message */
|
|
86
|
+
submitFeedback: (messageId: string, rating: 'thumbs_up' | 'thumbs_down', comment?: string) => Promise<void>;
|
|
73
87
|
}
|
package/src/types/props.ts
CHANGED
|
@@ -57,6 +57,11 @@ export interface ChatWindowProps {
|
|
|
57
57
|
onAddToCart?: (product: Product) => void;
|
|
58
58
|
/** Optional custom API URL to send chat messages to */
|
|
59
59
|
apiUrl?: string;
|
|
60
|
+
/**
|
|
61
|
+
* Base URL for Retrivora SDK history/feedback/sessions endpoints.
|
|
62
|
+
* Defaults to '/api/retrivora'. Set this to match your catch-all route location.
|
|
63
|
+
*/
|
|
64
|
+
retrivoraApiBase?: string;
|
|
60
65
|
/** Optional custom headers to send with the chat request */
|
|
61
66
|
headers?: Record<string, string>;
|
|
62
67
|
}
|
|
@@ -68,6 +73,11 @@ export interface ChatWidgetProps {
|
|
|
68
73
|
onAddToCart?: (product: Product) => void;
|
|
69
74
|
/** Optional custom API URL to send chat messages to */
|
|
70
75
|
apiUrl?: string;
|
|
76
|
+
/**
|
|
77
|
+
* Base URL for Retrivora SDK history/feedback/sessions endpoints.
|
|
78
|
+
* Defaults to '/api/retrivora'.
|
|
79
|
+
*/
|
|
80
|
+
retrivoraApiBase?: string;
|
|
71
81
|
/** Optional custom headers to send with the chat request */
|
|
72
82
|
headers?: Record<string, string>;
|
|
73
83
|
}
|
|
@@ -80,6 +90,8 @@ export interface MessageBubbleProps {
|
|
|
80
90
|
accentColor: string;
|
|
81
91
|
onAddToCart?: (product: Product) => void;
|
|
82
92
|
viewportSize?: ChatViewportSize;
|
|
93
|
+
/** Called when the user clicks thumbs up or thumbs down on an assistant message */
|
|
94
|
+
onFeedback?: (messageId: string, rating: 'thumbs_up' | 'thumbs_down') => void;
|
|
83
95
|
}
|
|
84
96
|
|
|
85
97
|
export interface ProductCardProps {
|
package/.env.example
DELETED
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
# ─── Project ─────────────────────────────────────────────────
|
|
2
|
-
RAG_PROJECT_ID=my-project
|
|
3
|
-
|
|
4
|
-
# ─── Vector Database ──────────────────────────────────────────
|
|
5
|
-
# Choose: pinecone | pgvector | rest | universal_rest
|
|
6
|
-
VECTOR_DB_PROVIDER=pinecone
|
|
7
|
-
VECTOR_DB_INDEX=rag-index
|
|
8
|
-
|
|
9
|
-
# Pinecone (if provider=pinecone)
|
|
10
|
-
PINECONE_API_KEY=your-pinecone-api-key
|
|
11
|
-
PINECONE_ENVIRONMENT=us-east-1
|
|
12
|
-
|
|
13
|
-
# pgVector (if provider=pgvector)
|
|
14
|
-
PGVECTOR_CONNECTION_STRING=postgresql://user:password@localhost:5432/StagVectorDB
|
|
15
|
-
|
|
16
|
-
# Generic REST (if provider=rest)
|
|
17
|
-
VECTOR_DB_REST_URL=http://localhost:8080
|
|
18
|
-
VECTOR_DB_REST_API_KEY=your-rest-api-key
|
|
19
|
-
# VECTOR_DB_QUERY_PATH=/query
|
|
20
|
-
# VECTOR_DB_UPSERT_PATH=/upsert
|
|
21
|
-
|
|
22
|
-
# ─── LLM ──────────────────────────────────────────────────────
|
|
23
|
-
# Choose: openai | anthropic | ollama | gemini | universal_rest
|
|
24
|
-
LLM_PROVIDER=openai
|
|
25
|
-
LLM_MODEL=gpt-4o
|
|
26
|
-
LLM_MAX_TOKENS=1024
|
|
27
|
-
LLM_TEMPERATURE=0.7
|
|
28
|
-
LLM_SYSTEM_PROMPT=You are a helpful assistant. Use the provided context to answer questions accurately.
|
|
29
|
-
|
|
30
|
-
# OpenAI (if provider=openai)
|
|
31
|
-
OPENAI_API_KEY=sk-...
|
|
32
|
-
|
|
33
|
-
# Anthropic (if provider=anthropic)
|
|
34
|
-
ANTHROPIC_API_KEY=sk-ant-...
|
|
35
|
-
|
|
36
|
-
# Gemini (if provider=gemini)
|
|
37
|
-
GEMINI_API_KEY=AIza...
|
|
38
|
-
|
|
39
|
-
# Ollama (if provider=ollama)
|
|
40
|
-
LLM_BASE_URL=http://localhost:11434
|
|
41
|
-
|
|
42
|
-
# ── Master Universal Provider (LiteLLM, Qdrant, etc.) ─────────
|
|
43
|
-
# Use 'universal_rest' for ANY model or DB via pre-set profiles.
|
|
44
|
-
LLM_PROVIDER=universal_rest
|
|
45
|
-
LLM_MODEL=gpt-4o
|
|
46
|
-
# Profile: litellm | ollama-standard | openai-compatible
|
|
47
|
-
LLM_UNIVERSAL_PROFILE=litellm
|
|
48
|
-
LLM_BASE_URL=https://proxy.example.com/api
|
|
49
|
-
LLM_API_KEY=your-key
|
|
50
|
-
|
|
51
|
-
VECTOR_DB_PROVIDER=universal_rest
|
|
52
|
-
# Profile: qdrant | chromadb
|
|
53
|
-
VECTOR_UNIVERSAL_PROFILE=qdrant
|
|
54
|
-
VECTOR_BASE_URL=http://localhost:6333
|
|
55
|
-
VECTOR_DB_INDEX=my-index
|
|
56
|
-
|
|
57
|
-
# ─── Embedding ────────────────────────────────────────────────
|
|
58
|
-
# Choose: openai | ollama | gemini | custom
|
|
59
|
-
EMBEDDING_PROVIDER=openai
|
|
60
|
-
EMBEDDING_MODEL=text-embedding-3-small
|
|
61
|
-
EMBEDDING_DIMENSIONS=1536
|
|
62
|
-
# EMBEDDING_BASE_URL=http://localhost:11434 # for ollama
|
|
63
|
-
# EMBEDDING_API_KEY=your-embedding-key # for custom embedding endpoints
|
|
64
|
-
|
|
65
|
-
# ─── RAG Pipeline Tuning ──────────────────────────────────────
|
|
66
|
-
RAG_TOP_K=5
|
|
67
|
-
RAG_SCORE_THRESHOLD=0.0
|
|
68
|
-
RAG_CHUNK_SIZE=1000
|
|
69
|
-
RAG_CHUNK_OVERLAP=200
|
|
70
|
-
|
|
71
|
-
# ─── UI Branding (NEXT_PUBLIC_ = safe to expose to browser) ───
|
|
72
|
-
NEXT_PUBLIC_PROJECT_ID=my-project
|
|
73
|
-
NEXT_PUBLIC_UI_TITLE=AI Assistant
|
|
74
|
-
NEXT_PUBLIC_UI_SUBTITLE=Powered by RAG
|
|
75
|
-
NEXT_PUBLIC_PRIMARY_COLOR=#6366f1
|
|
76
|
-
NEXT_PUBLIC_ACCENT_COLOR=#8b5cf6
|
|
77
|
-
NEXT_PUBLIC_PLACEHOLDER=Ask me anything…
|
|
78
|
-
NEXT_PUBLIC_SHOW_SOURCES=true
|
|
79
|
-
NEXT_PUBLIC_WELCOME_MESSAGE=Hello! I'm your AI assistant. Ask me anything about your documents.
|
|
80
|
-
# NEXT_PUBLIC_LOGO_URL=https://your-domain.com/logo.png
|
package/LICENSE.txt
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) [2026] [Abhinav Alkuchi]
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import React from 'react';
|
|
4
|
-
import { useConfig } from '@/components/ConfigProvider';
|
|
5
|
-
|
|
6
|
-
export function AmbientBackground() {
|
|
7
|
-
const { ui } = useConfig();
|
|
8
|
-
|
|
9
|
-
return (
|
|
10
|
-
<div className="absolute inset-0 overflow-hidden pointer-events-none">
|
|
11
|
-
<div
|
|
12
|
-
className="absolute -top-40 -left-40 w-[600px] h-[600px] rounded-full opacity-20 blur-3xl"
|
|
13
|
-
style={{ background: ui.primaryColor }}
|
|
14
|
-
/>
|
|
15
|
-
<div
|
|
16
|
-
className="absolute -bottom-40 -right-40 w-[600px] h-[600px] rounded-full opacity-15 blur-3xl"
|
|
17
|
-
style={{ background: ui.accentColor }}
|
|
18
|
-
/>
|
|
19
|
-
<div
|
|
20
|
-
className="absolute inset-0 opacity-[0.05] dark:opacity-[0.03]"
|
|
21
|
-
style={{
|
|
22
|
-
backgroundImage:
|
|
23
|
-
'linear-gradient(currentColor 1px, transparent 1px), linear-gradient(90deg, currentColor 1px, transparent 1px)',
|
|
24
|
-
backgroundSize: '48px 48px',
|
|
25
|
-
}}
|
|
26
|
-
/>
|
|
27
|
-
</div>
|
|
28
|
-
);
|
|
29
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { ArchitectureCardProps } from '@/app/types';
|
|
3
|
-
|
|
4
|
-
export function ArchitectureCard({ icon, title, description, badge, badgeColor }: ArchitectureCardProps) {
|
|
5
|
-
return (
|
|
6
|
-
<div className="group rounded-2xl border border-slate-200 dark:border-white/10 bg-white dark:bg-white/5 p-6 shadow-sm transition-all duration-300 hover:border-indigo-500/50 dark:hover:border-indigo-500/30 hover:shadow-xl hover:shadow-indigo-500/5">
|
|
7
|
-
<div className="mb-4 flex items-center justify-between">
|
|
8
|
-
<div className="text-3xl transition-transform duration-300 group-hover:scale-110">{icon}</div>
|
|
9
|
-
<span className={`rounded-full border px-3 py-0.5 text-[10px] font-bold uppercase tracking-wider ${badgeColor}`}>
|
|
10
|
-
{badge}
|
|
11
|
-
</span>
|
|
12
|
-
</div>
|
|
13
|
-
<h3 className="mb-2 font-bold text-slate-900 dark:text-white">{title}</h3>
|
|
14
|
-
<p className="text-xs text-slate-500 dark:text-white/40 leading-relaxed font-medium">{description}</p>
|
|
15
|
-
</div>
|
|
16
|
-
);
|
|
17
|
-
}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import React from 'react';
|
|
4
|
-
import { ArchitectureCard } from '@/components/ArchitectureCard';
|
|
5
|
-
import { ARCHITECTURE_CARDS } from '@/app/constants';
|
|
6
|
-
|
|
7
|
-
export function ArchitectureCardsSection() {
|
|
8
|
-
return (
|
|
9
|
-
<div className="relative z-10 mt-24 mb-32 grid gap-6 sm:grid-cols-3 max-w-5xl mx-auto">
|
|
10
|
-
{ARCHITECTURE_CARDS.map((card, i) => (
|
|
11
|
-
<ArchitectureCard key={i} {...card} />
|
|
12
|
-
))}
|
|
13
|
-
</div>
|
|
14
|
-
);
|
|
15
|
-
}
|
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import React from 'react';
|
|
4
|
-
import { Snippet } from '@/app/types';
|
|
5
|
-
import { SNIPPETS } from '@/app/constants';
|
|
6
|
-
import { CodeViewer } from './CodeViewer';
|
|
7
|
-
import { ArrowLeft, ArrowRight } from 'lucide-react';
|
|
8
|
-
|
|
9
|
-
export function DocViewer({ activeSnippet, setActiveSnippet }: { activeSnippet: Snippet, setActiveSnippet: (s: Snippet) => void }) {
|
|
10
|
-
const currentIndex = SNIPPETS.findIndex((s) => s.id === activeSnippet.id);
|
|
11
|
-
const totalSteps = SNIPPETS.length;
|
|
12
|
-
const isFirst = currentIndex === 0;
|
|
13
|
-
const isLast = currentIndex === totalSteps - 1;
|
|
14
|
-
|
|
15
|
-
const handlePrev = () => {
|
|
16
|
-
if (!isFirst) {
|
|
17
|
-
setActiveSnippet(SNIPPETS[currentIndex - 1]);
|
|
18
|
-
}
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
const handleNext = () => {
|
|
22
|
-
if (!isLast) {
|
|
23
|
-
setActiveSnippet(SNIPPETS[currentIndex + 1]);
|
|
24
|
-
}
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
const progressPercent = Math.round(((currentIndex + 1) / totalSteps) * 100);
|
|
28
|
-
|
|
29
|
-
return (
|
|
30
|
-
<>
|
|
31
|
-
<div className="mb-6 flex flex-wrap gap-2 border-b border-slate-100 dark:border-white/5 pb-6">
|
|
32
|
-
{SNIPPETS.map((snippet) => (
|
|
33
|
-
<button
|
|
34
|
-
key={snippet.id}
|
|
35
|
-
onClick={() => setActiveSnippet(snippet)}
|
|
36
|
-
className={`px-5 py-2 rounded-xl text-[10px] font-bold uppercase tracking-wider transition-all border ${activeSnippet.id === snippet.id
|
|
37
|
-
? 'bg-indigo-600 text-white border-indigo-600 shadow-lg shadow-indigo-200 dark:shadow-indigo-500/20 scale-105'
|
|
38
|
-
: 'bg-white dark:bg-white/5 border-slate-200 dark:border-white/10 text-slate-500 dark:text-white/40 hover:text-indigo-600 dark:hover:text-indigo-400 hover:border-indigo-300 dark:hover:border-white/20'
|
|
39
|
-
}`}
|
|
40
|
-
>
|
|
41
|
-
{snippet.title}
|
|
42
|
-
</button>
|
|
43
|
-
))}
|
|
44
|
-
</div>
|
|
45
|
-
|
|
46
|
-
{/* Visual Progress Bar */}
|
|
47
|
-
<div className="mb-6 bg-slate-100 dark:bg-white/5 rounded-full h-2.5 overflow-hidden border border-slate-200/50 dark:border-white/5 relative">
|
|
48
|
-
<div
|
|
49
|
-
className="h-full bg-gradient-to-r from-indigo-500 via-indigo-600 to-violet-600 transition-all duration-500 rounded-full shadow-[0_0_8px_rgba(99,102,241,0.5)]"
|
|
50
|
-
style={{ width: `${progressPercent}%` }}
|
|
51
|
-
/>
|
|
52
|
-
</div>
|
|
53
|
-
|
|
54
|
-
<div className="flex-grow flex flex-col gap-6 animate-in fade-in slide-in-from-bottom-2 duration-500">
|
|
55
|
-
<div className="max-w-2xl flex items-start justify-between gap-4 flex-wrap sm:flex-nowrap">
|
|
56
|
-
<div>
|
|
57
|
-
<h3 className="text-xl font-bold text-slate-900 dark:text-white mb-2 flex items-center gap-3">
|
|
58
|
-
{activeSnippet.title}
|
|
59
|
-
<span className="text-[10px] font-extrabold uppercase px-2 py-0.5 rounded bg-indigo-50 dark:bg-indigo-500/10 border border-indigo-100 dark:border-indigo-500/20 text-indigo-600 dark:text-indigo-400">
|
|
60
|
-
Step {currentIndex + 1} of {totalSteps}
|
|
61
|
-
</span>
|
|
62
|
-
</h3>
|
|
63
|
-
<p className="text-sm text-slate-500 dark:text-white/40 leading-relaxed font-medium italic">
|
|
64
|
-
{activeSnippet.description}
|
|
65
|
-
</p>
|
|
66
|
-
</div>
|
|
67
|
-
<span className="text-xs font-mono font-bold text-indigo-600 dark:text-indigo-400 self-center shrink-0">
|
|
68
|
-
{progressPercent}% Complete
|
|
69
|
-
</span>
|
|
70
|
-
</div>
|
|
71
|
-
|
|
72
|
-
<CodeViewer snippet={activeSnippet} />
|
|
73
|
-
|
|
74
|
-
{/* Next/Prev Navigation */}
|
|
75
|
-
<div className="flex items-center justify-between border-t border-slate-200 dark:border-white/10 pt-6 mt-4">
|
|
76
|
-
<button
|
|
77
|
-
onClick={handlePrev}
|
|
78
|
-
disabled={isFirst}
|
|
79
|
-
className={`flex items-center gap-2 px-5 py-2.5 rounded-xl text-xs font-bold transition-all border ${
|
|
80
|
-
isFirst
|
|
81
|
-
? 'opacity-40 cursor-not-allowed border-slate-200 dark:border-white/5 text-slate-400 dark:text-white/20 bg-slate-50 dark:bg-transparent'
|
|
82
|
-
: 'bg-white dark:bg-white/5 border-slate-200 dark:border-white/10 text-slate-700 dark:text-white/70 hover:border-slate-300 dark:hover:border-white/20 active:scale-95'
|
|
83
|
-
}`}
|
|
84
|
-
>
|
|
85
|
-
<ArrowLeft size={14} /> Previous Step
|
|
86
|
-
</button>
|
|
87
|
-
|
|
88
|
-
<button
|
|
89
|
-
onClick={handleNext}
|
|
90
|
-
disabled={isLast}
|
|
91
|
-
className={`flex items-center gap-2 px-6 py-2.5 rounded-xl text-xs font-bold transition-all border ${
|
|
92
|
-
isLast
|
|
93
|
-
? 'opacity-40 cursor-not-allowed border-slate-200 dark:border-white/5 text-slate-400 dark:text-white/20 bg-slate-50 dark:bg-transparent'
|
|
94
|
-
: 'bg-indigo-600 text-white border-indigo-600 hover:bg-indigo-700 hover:border-indigo-700 active:scale-95 shadow-md shadow-indigo-500/10'
|
|
95
|
-
}`}
|
|
96
|
-
>
|
|
97
|
-
{isLast ? 'Complete!' : 'Next Step'} <ArrowRight size={14} />
|
|
98
|
-
</button>
|
|
99
|
-
</div>
|
|
100
|
-
</div>
|
|
101
|
-
</>
|
|
102
|
-
);
|
|
103
|
-
}
|
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import React from 'react';
|
|
4
|
-
import { FileText, Zap, Package, ExternalLink, Code } from 'lucide-react';
|
|
5
|
-
import { DocViewer } from '@/components/DocViewer';
|
|
6
|
-
import { LANDING_PAGE_CONTENT, QUICK_START_STEPS, ADVANCED_STEPS, API_ENDPOINTS, SNIPPETS } from '@/app/constants';
|
|
7
|
-
import { Snippet } from '@/app/types';
|
|
8
|
-
|
|
9
|
-
export function Documentation() {
|
|
10
|
-
const [activeSnippet, setActiveSnippet] = React.useState<Snippet>(SNIPPETS[0]);
|
|
11
|
-
|
|
12
|
-
return (
|
|
13
|
-
<div className="mt-32 max-w-6xl mx-auto mb-24 relative">
|
|
14
|
-
<div className="text-center mb-16">
|
|
15
|
-
<h2 className="text-3xl font-bold text-slate-900 dark:text-white mb-4">{LANDING_PAGE_CONTENT.guide.title}</h2>
|
|
16
|
-
<p className="text-slate-600 dark:text-white/40 max-w-2xl mx-auto">{LANDING_PAGE_CONTENT.guide.subtitle}</p>
|
|
17
|
-
</div>
|
|
18
|
-
<div className="relative z-10 w-full grid gap-16 lg:grid-cols-[280px_1fr] items-start">
|
|
19
|
-
<aside className="flex flex-col gap-8">
|
|
20
|
-
<section>
|
|
21
|
-
<h2 className="mb-4 text-[10px] font-black text-slate-400 dark:text-white/30 uppercase tracking-[0.3em] flex items-center gap-3">
|
|
22
|
-
<FileText size={14} className="text-indigo-500" /> Quick Start
|
|
23
|
-
</h2>
|
|
24
|
-
<ol className="space-y-2.5">
|
|
25
|
-
{QUICK_START_STEPS.map((step, i) => {
|
|
26
|
-
const isActive = activeSnippet.id === step.id;
|
|
27
|
-
return (
|
|
28
|
-
<li key={step.id}>
|
|
29
|
-
<button
|
|
30
|
-
onClick={() => {
|
|
31
|
-
const snip = SNIPPETS.find((s) => s.id === step.id);
|
|
32
|
-
if (snip) setActiveSnippet(snip);
|
|
33
|
-
}}
|
|
34
|
-
className={`w-full flex items-start gap-4 p-3 rounded-xl border text-left transition-all active:scale-[0.98] ${
|
|
35
|
-
isActive
|
|
36
|
-
? 'bg-indigo-500/10 dark:bg-indigo-500/10 border-indigo-200 dark:border-indigo-500/30'
|
|
37
|
-
: 'bg-white dark:bg-white/3 border-slate-200 dark:border-white/5 hover:border-slate-300 dark:hover:border-white/10 hover:bg-slate-50 dark:hover:bg-white/5 shadow-sm'
|
|
38
|
-
}`}
|
|
39
|
-
>
|
|
40
|
-
<span className={`flex h-6 w-6 shrink-0 items-center justify-center rounded-lg font-mono text-[10px] font-bold border transition-all ${
|
|
41
|
-
isActive
|
|
42
|
-
? 'bg-indigo-600 text-white border-indigo-600 shadow-md shadow-indigo-500/20'
|
|
43
|
-
: 'bg-slate-100 dark:bg-white/5 text-slate-600 dark:text-white/40 border-slate-200 dark:border-white/10'
|
|
44
|
-
}`}>{i + 1}</span>
|
|
45
|
-
<div className="pt-0.5">
|
|
46
|
-
<span className={`text-xs font-semibold block transition-colors ${
|
|
47
|
-
isActive ? 'text-indigo-600 dark:text-indigo-400 font-bold' : 'text-slate-700 dark:text-white/70 font-medium'
|
|
48
|
-
}`}>{step.text}</span>
|
|
49
|
-
<span className="text-[9px] text-slate-400 dark:text-white/30 block mt-0.5">Step {i + 1}</span>
|
|
50
|
-
</div>
|
|
51
|
-
</button>
|
|
52
|
-
</li>
|
|
53
|
-
);
|
|
54
|
-
})}
|
|
55
|
-
</ol>
|
|
56
|
-
</section>
|
|
57
|
-
|
|
58
|
-
<section>
|
|
59
|
-
<h2 className="mb-4 text-[10px] font-black text-slate-400 dark:text-white/30 uppercase tracking-[0.3em] flex items-center gap-3">
|
|
60
|
-
<Code size={14} className="text-violet-500" /> Advanced Options
|
|
61
|
-
</h2>
|
|
62
|
-
<ol className="space-y-2.5">
|
|
63
|
-
{ADVANCED_STEPS.map((step, i) => {
|
|
64
|
-
const isActive = activeSnippet.id === step.id;
|
|
65
|
-
return (
|
|
66
|
-
<li key={step.id}>
|
|
67
|
-
<button
|
|
68
|
-
onClick={() => {
|
|
69
|
-
const snip = SNIPPETS.find((s) => s.id === step.id);
|
|
70
|
-
if (snip) setActiveSnippet(snip);
|
|
71
|
-
}}
|
|
72
|
-
className={`w-full flex items-start gap-4 p-3 rounded-xl border text-left transition-all active:scale-[0.98] ${
|
|
73
|
-
isActive
|
|
74
|
-
? 'bg-violet-500/10 dark:bg-violet-500/10 border-violet-200 dark:border-violet-500/30'
|
|
75
|
-
: 'bg-white dark:bg-white/3 border-slate-200 dark:border-white/5 hover:border-slate-300 dark:hover:border-white/10 hover:bg-slate-50 dark:hover:bg-white/5 shadow-sm'
|
|
76
|
-
}`}
|
|
77
|
-
>
|
|
78
|
-
<span className={`flex h-6 w-6 shrink-0 items-center justify-center rounded-lg font-mono text-[10px] font-bold border transition-all ${
|
|
79
|
-
isActive
|
|
80
|
-
? 'bg-violet-600 text-white border-violet-600 shadow-md shadow-violet-500/20'
|
|
81
|
-
: 'bg-slate-100 dark:bg-white/5 text-slate-600 dark:text-white/40 border-slate-200 dark:border-white/10'
|
|
82
|
-
}`}>{i + 5}</span>
|
|
83
|
-
<div className="pt-0.5">
|
|
84
|
-
<span className={`text-xs font-semibold block transition-colors ${
|
|
85
|
-
isActive ? 'text-violet-600 dark:text-violet-400 font-bold' : 'text-slate-700 dark:text-white/70 font-medium'
|
|
86
|
-
}`}>{step.text}</span>
|
|
87
|
-
<span className="text-[9px] text-slate-400 dark:text-white/30 block mt-0.5">Extension</span>
|
|
88
|
-
</div>
|
|
89
|
-
</button>
|
|
90
|
-
</li>
|
|
91
|
-
);
|
|
92
|
-
})}
|
|
93
|
-
</ol>
|
|
94
|
-
</section>
|
|
95
|
-
|
|
96
|
-
<section className="rounded-2xl border border-slate-200 dark:border-white/10 bg-white dark:bg-white/3 p-6 shadow-sm">
|
|
97
|
-
<h2 className="mb-6 text-[10px] font-black text-slate-400 dark:text-white/30 uppercase tracking-[0.3em] flex items-center gap-3">
|
|
98
|
-
<Zap size={14} className="text-indigo-500" /> API Endpoints
|
|
99
|
-
</h2>
|
|
100
|
-
<div className="grid gap-2.5">
|
|
101
|
-
{API_ENDPOINTS.map((slug) => (
|
|
102
|
-
<div key={slug} className="group flex items-center justify-between p-2 rounded-lg bg-slate-50 dark:bg-white/5 border border-slate-100 dark:border-white/5 hover:border-indigo-200 dark:hover:border-indigo-500/30">
|
|
103
|
-
<span className="text-[10px] font-mono text-slate-500 dark:text-white/30 group-hover:text-indigo-600">/api/{slug}</span>
|
|
104
|
-
<span className="text-[8px] font-bold text-indigo-600 dark:text-indigo-400 bg-indigo-50 dark:bg-indigo-500/10 px-1.5 py-0.5 rounded border border-indigo-100 dark:border-indigo-500/20">POST</span>
|
|
105
|
-
</div>
|
|
106
|
-
))}
|
|
107
|
-
</div>
|
|
108
|
-
</section>
|
|
109
|
-
</aside>
|
|
110
|
-
<section className="flex flex-col h-full min-h-[560px]">
|
|
111
|
-
<DocViewer activeSnippet={activeSnippet} setActiveSnippet={setActiveSnippet} />
|
|
112
|
-
</section>
|
|
113
|
-
</div>
|
|
114
|
-
<div className="mt-16 text-center">
|
|
115
|
-
<a href="https://www.npmjs.com/package/@retrivora-ai/rag-engine" className="inline-flex items-center gap-3 px-8 py-4 rounded-2xl bg-slate-900 dark:bg-white text-white dark:text-slate-900 font-bold shadow-xl shadow-indigo-500/20">
|
|
116
|
-
<Package className="w-5 h-5" /> Get Started on NPM <ExternalLink className="w-4 h-4" />
|
|
117
|
-
</a>
|
|
118
|
-
</div>
|
|
119
|
-
</div>
|
|
120
|
-
);
|
|
121
|
-
}
|
package/src/components/Hero.tsx
DELETED
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import React from 'react';
|
|
4
|
-
import { useConfig } from '@/components/ConfigProvider';
|
|
5
|
-
import { ChatWindow } from '@/components/ChatWindow';
|
|
6
|
-
import { LANDING_PAGE_CONTENT, VECTOR_DATABASES, AI_MODELS } from '@/app/constants';
|
|
7
|
-
|
|
8
|
-
export function Hero() {
|
|
9
|
-
const { ui } = useConfig();
|
|
10
|
-
|
|
11
|
-
return (
|
|
12
|
-
<div className="grid lg:grid-cols-2 gap-12 items-start">
|
|
13
|
-
<div className="flex flex-col gap-6 pt-4">
|
|
14
|
-
<div
|
|
15
|
-
className="inline-flex items-center gap-2 px-4 py-1.5 rounded-full text-xs font-medium border w-fit"
|
|
16
|
-
style={{ borderColor: `${ui.primaryColor}40`, color: ui.primaryColor, background: `${ui.primaryColor}10` }}
|
|
17
|
-
>
|
|
18
|
-
<span className="w-1.5 h-1.5 rounded-full animate-pulse" style={{ background: ui.primaryColor }} />
|
|
19
|
-
{LANDING_PAGE_CONTENT.hero.badge}
|
|
20
|
-
</div>
|
|
21
|
-
<h1 className="text-5xl md:text-7xl font-black text-slate-900 dark:text-white mb-6 tracking-tight">
|
|
22
|
-
{LANDING_PAGE_CONTENT.hero.title.split('for')[0]} <br />
|
|
23
|
-
<span className="text-transparent bg-clip-text" style={{ backgroundImage: `linear-gradient(to right, ${ui.primaryColor}, ${ui.accentColor})` }}>
|
|
24
|
-
for {LANDING_PAGE_CONTENT.hero.title.split('for')[1]}
|
|
25
|
-
</span>
|
|
26
|
-
</h1>
|
|
27
|
-
<p className="text-lg md:text-xl text-slate-600 dark:text-white/40 max-w-2xl leading-relaxed">
|
|
28
|
-
{LANDING_PAGE_CONTENT.hero.subtitle}
|
|
29
|
-
</p>
|
|
30
|
-
<div className="flex flex-col gap-4 mt-4">
|
|
31
|
-
<div className="flex flex-col gap-2">
|
|
32
|
-
<span className="text-[10px] font-black text-slate-400 dark:text-white/30 uppercase tracking-[0.2em] ml-1">Vector Ecosystem</span>
|
|
33
|
-
<div className="flex flex-wrap gap-2">
|
|
34
|
-
{VECTOR_DATABASES.map(({ Icon, label }) => (
|
|
35
|
-
<span key={label} className="flex items-center gap-1.5 px-3 py-1.5 rounded-lg bg-white dark:bg-white/5 border border-slate-200 dark:border-white/10 text-slate-600 dark:text-white/60 text-[11px] font-semibold hover:bg-slate-50 dark:hover:bg-white/8 transition-all shadow-sm group">
|
|
36
|
-
<Icon className="w-3 h-3 transition-transform group-hover:scale-110" style={{ color: ui.primaryColor }} /> {label}
|
|
37
|
-
</span>
|
|
38
|
-
))}
|
|
39
|
-
</div>
|
|
40
|
-
</div>
|
|
41
|
-
|
|
42
|
-
<div className="flex flex-col gap-2">
|
|
43
|
-
<span className="text-[10px] font-black text-slate-400 dark:text-white/30 uppercase tracking-[0.2em] ml-1">AI Model Garden</span>
|
|
44
|
-
<div className="flex flex-wrap gap-2">
|
|
45
|
-
{AI_MODELS.map(({ Icon, label }) => (
|
|
46
|
-
<span key={label} className="flex items-center gap-1.5 px-3 py-1.5 rounded-lg bg-white dark:bg-white/5 border border-slate-200 dark:border-white/10 text-slate-600 dark:text-white/60 text-[11px] font-semibold hover:bg-slate-50 dark:hover:bg-white/8 transition-all shadow-sm group">
|
|
47
|
-
<Icon className="w-3 h-3 transition-transform group-hover:scale-110" style={{ color: ui.accentColor }} /> {label}
|
|
48
|
-
</span>
|
|
49
|
-
))}
|
|
50
|
-
</div>
|
|
51
|
-
</div>
|
|
52
|
-
</div>
|
|
53
|
-
</div>
|
|
54
|
-
<div className="lg:sticky lg:top-6 h-[calc(100vh-3rem)] min-h-[500px] max-h-[800px]">
|
|
55
|
-
<ChatWindow className="w-full h-full" />
|
|
56
|
-
</div>
|
|
57
|
-
</div>
|
|
58
|
-
);
|
|
59
|
-
}
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import React from 'react';
|
|
4
|
-
import { LANDING_PAGE_CONTENT, PIPELINE_STEPS } from '@/app/constants';
|
|
5
|
-
|
|
6
|
-
export function Lifecycle() {
|
|
7
|
-
return (
|
|
8
|
-
<div className="mt-24 mb-12">
|
|
9
|
-
<h2 className="text-2xl font-bold text-slate-900 dark:text-white text-center mb-2">{LANDING_PAGE_CONTENT.lifecycle.title}</h2>
|
|
10
|
-
<div className="relative max-w-5xl mx-auto py-12">
|
|
11
|
-
<div className="absolute left-1/2 top-0 bottom-0 w-0.5 bg-slate-200 dark:bg-white/10 -translate-x-1/2 hidden md:block" />
|
|
12
|
-
<div className="space-y-12 md:space-y-0">
|
|
13
|
-
{PIPELINE_STEPS.map(({ step, Icon, title, desc, colors }, index) => {
|
|
14
|
-
const isLeft = index % 2 === 0;
|
|
15
|
-
return (
|
|
16
|
-
<div key={step} className={`relative flex flex-col md:flex-row items-center gap-8 ${isLeft ? 'md:flex-row' : 'md:flex-row-reverse'}`}>
|
|
17
|
-
<div className={`w-full md:w-1/2 relative flex ${isLeft ? 'justify-end' : 'justify-start'}`}>
|
|
18
|
-
<div className="relative p-6 rounded-2xl border border-slate-200 dark:border-white/10 bg-white dark:bg-white/3 max-w-md text-left overflow-hidden group">
|
|
19
|
-
<div className="absolute -right-2 -bottom-4 text-7xl font-bold opacity-[0.1] italic" style={{ color: colors.from }}>{step}</div>
|
|
20
|
-
<h3 className="font-semibold text-slate-900 dark:text-white mb-2 text-lg flex items-center gap-2">
|
|
21
|
-
<Icon className="w-5 h-5" style={{ color: colors.from }} /> {title}
|
|
22
|
-
</h3>
|
|
23
|
-
<p className="text-slate-600 dark:text-white/40 text-sm leading-relaxed">{desc}</p>
|
|
24
|
-
</div>
|
|
25
|
-
</div>
|
|
26
|
-
<div className="relative z-10 w-12 h-12 rounded-2xl flex items-center justify-center shadow-xl border-4 border-slate-50 dark:border-[#080811]" style={{ background: `linear-gradient(135deg, ${colors.from}, ${colors.to})` }}>
|
|
27
|
-
<Icon className="w-6 h-6 text-white" />
|
|
28
|
-
</div>
|
|
29
|
-
<div className="hidden md:block md:w-1/2" />
|
|
30
|
-
</div>
|
|
31
|
-
);
|
|
32
|
-
})}
|
|
33
|
-
</div>
|
|
34
|
-
</div>
|
|
35
|
-
</div>
|
|
36
|
-
);
|
|
37
|
-
}
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import React from 'react';
|
|
4
|
-
import { Zap, Package, GitBranch, HeartPulse } from 'lucide-react';
|
|
5
|
-
import { ThemeToggle } from '@/components/ThemeToggle';
|
|
6
|
-
import { useConfig } from '@/components/ConfigProvider';
|
|
7
|
-
import pkg from '../../package.json';
|
|
8
|
-
|
|
9
|
-
export function Navbar() {
|
|
10
|
-
const { ui } = useConfig();
|
|
11
|
-
|
|
12
|
-
return (
|
|
13
|
-
<nav className="sticky top-0 z-50 flex items-center justify-between px-8 py-5 border-b border-slate-200 dark:border-white/5 bg-white/80 dark:bg-[#080811]/80 backdrop-blur-md">
|
|
14
|
-
<div className="flex items-center gap-3 group cursor-default">
|
|
15
|
-
<div className="relative">
|
|
16
|
-
<div
|
|
17
|
-
className="w-10 h-10 rounded-xl flex items-center justify-center shadow-lg relative z-10 overflow-hidden transition-transform group-hover:scale-110 duration-500"
|
|
18
|
-
style={{ background: `linear-gradient(135deg, ${ui.primaryColor}, ${ui.accentColor})` }}
|
|
19
|
-
>
|
|
20
|
-
<Zap className="w-5 h-5 text-white animate-pulse" />
|
|
21
|
-
<div className="absolute inset-0 bg-white/20 opacity-0 group-hover:opacity-100 transition-opacity" />
|
|
22
|
-
</div>
|
|
23
|
-
<div
|
|
24
|
-
className="absolute inset-0 blur-lg opacity-40 group-hover:opacity-80 transition-opacity"
|
|
25
|
-
style={{ background: ui.primaryColor }}
|
|
26
|
-
/>
|
|
27
|
-
</div>
|
|
28
|
-
<div className="flex flex-col -gap-0.5">
|
|
29
|
-
<span className="font-black text-transparent bg-clip-text text-xl tracking-tight leading-none"
|
|
30
|
-
style={{ backgroundImage: `linear-gradient(to right, ${ui.primaryColor}, ${ui.accentColor})` }}
|
|
31
|
-
>
|
|
32
|
-
Retrivora AI
|
|
33
|
-
</span>
|
|
34
|
-
<div className="flex items-center gap-1.5">
|
|
35
|
-
<span className="font-bold text-slate-900 dark:text-white text-[10px] tracking-[0.15em] uppercase opacity-70">Accelerator</span>
|
|
36
|
-
<span className="text-[9px] px-1.5 py-0.5 rounded-full bg-slate-100 dark:bg-white/5 text-slate-500 dark:text-white/40 font-mono border border-slate-200/50 dark:border-white/10">v{pkg?.version}</span>
|
|
37
|
-
</div>
|
|
38
|
-
</div>
|
|
39
|
-
</div>
|
|
40
|
-
|
|
41
|
-
<div className="flex items-center gap-3">
|
|
42
|
-
<ThemeToggle />
|
|
43
|
-
<a href="https://www.npmjs.com/package/@retrivora-ai/rag-engine" target="_blank" rel="noreferrer" className="text-slate-500 hover:text-[#CB3837] dark:text-white/40 dark:hover:text-[#CB3837] text-sm transition-colors flex items-center gap-1.5">
|
|
44
|
-
<Package className="w-4 h-4" /> NPM
|
|
45
|
-
</a>
|
|
46
|
-
<a href="https://github.com/abhinav1201/ai-accelerator" target="_blank" rel="noreferrer" className="text-slate-500 hover:text-slate-900 dark:text-white/40 dark:hover:text-white/70 text-sm transition-colors flex items-center gap-1.5">
|
|
47
|
-
<GitBranch className="w-4 h-4" /> GitHub
|
|
48
|
-
</a>
|
|
49
|
-
<a href="/api/health" target="_blank" rel="noreferrer" className="px-3 py-1.5 rounded-lg text-xs border border-slate-200 dark:border-white/10 text-slate-600 dark:text-white/50 hover:text-slate-900 dark:hover:text-white/80 hover:bg-slate-100 dark:hover:bg-white/5 transition-all flex items-center gap-1.5">
|
|
50
|
-
<HeartPulse className="w-3.5 h-3.5" /> Health
|
|
51
|
-
</a>
|
|
52
|
-
</div>
|
|
53
|
-
</nav>
|
|
54
|
-
);
|
|
55
|
-
}
|