feat: add reminders page, BMad skills upgrade, MCP server refactor

- Add reminders page with navigation support
- Upgrade BMad builder module to skills-based architecture
- Refactor MCP server: extract tools and auth into separate modules
- Add connections cache, custom AI provider support
- Update prisma schema and generated client
- Various UI/UX improvements and i18n updates
- Add service worker for PWA support

Made-with: Cursor
This commit is contained in:
Sepehr Ramezani
2026-04-13 21:02:53 +02:00
parent 18ed116e0d
commit fa7e166f3e
3099 changed files with 397228 additions and 14584 deletions

View File

@@ -64,14 +64,14 @@ export function AI_TESTER({ type }: { type: 'tags' | 'embeddings' }) {
if (data.success) {
toast.success(
`${type === 'tags' ? 'Tags' : 'Embeddings'} Test Successful!`,
`${t('admin.aiTest.testSuccessToast', { type: type === 'tags' ? 'Tags' : 'Embeddings' })}`,
{
description: `Provider: ${data.provider} | Time: ${endTime - startTime}ms`
}
)
} else {
toast.error(
`${type === 'tags' ? 'Tags' : 'Embeddings'} Test Failed`,
`${t('admin.aiTest.testFailedToast', { type: type === 'tags' ? 'Tags' : 'Embeddings' })}`,
{
description: data.error || 'Unknown error'
}
@@ -92,7 +92,7 @@ export function AI_TESTER({ type }: { type: 'tags' | 'embeddings' }) {
}
const getProviderInfo = () => {
if (!config) return { provider: 'Loading...', model: 'Loading...' }
if (!config) return { provider: t('admin.aiTest.testing'), model: t('admin.aiTest.testing') }
if (type === 'tags') {
return {
@@ -232,7 +232,7 @@ export function AI_TESTER({ type }: { type: 'tags' | 'embeddings' }) {
{result.details && (
<details className="mt-2">
<summary className="text-xs cursor-pointer text-red-600 dark:text-red-400">
Technical details
{t('admin.aiTest.technicalDetails')}
</summary>
<pre className="mt-2 text-xs overflow-auto p-2 bg-red-100 dark:bg-red-900/30 rounded">
{JSON.stringify(result.details, null, 2)}
@@ -250,7 +250,7 @@ export function AI_TESTER({ type }: { type: 'tags' | 'embeddings' }) {
<div className="text-center py-4">
<Loader2 className="h-8 w-8 animate-spin mx-auto text-primary" />
<p className="text-sm text-muted-foreground mt-2">
{t('admin.aiTest.testing')} {type === 'tags' ? 'tags generation' : 'embeddings'}...
{t('admin.aiTest.testingType', { type: type === 'tags' ? 'tags generation' : 'embeddings' })}
</p>
</div>
)}

View File

@@ -1,17 +1,14 @@
'use client'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { Button } from '@/components/ui/button'
import { auth } from '@/auth'
import { redirect } from 'next/navigation'
import Link from 'next/link'
import { ArrowLeft, TestTube } from 'lucide-react'
import { AI_TESTER } from './ai-tester'
import { useLanguage } from '@/lib/i18n'
export default async function AITestPage() {
const session = await auth()
if ((session?.user as any)?.role !== 'ADMIN') {
redirect('/')
}
export default function AITestPage() {
const { t } = useLanguage()
return (
<div className="container mx-auto py-10 px-4 max-w-6xl">
@@ -25,10 +22,10 @@ export default async function AITestPage() {
<div>
<h1 className="text-3xl font-bold flex items-center gap-2">
<TestTube className="h-8 w-8" />
AI Provider Testing
{t('admin.aiTest.title')}
</h1>
<p className="text-muted-foreground mt-1">
Test your AI providers for tag generation and semantic search embeddings
{t('admin.aiTest.description')}
</p>
</div>
</div>
@@ -40,10 +37,10 @@ export default async function AITestPage() {
<CardHeader className="bg-primary/5 dark:bg-primary/10">
<CardTitle className="flex items-center gap-2">
<span className="text-2xl">🏷</span>
Tags Generation Test
{t('admin.aiTest.tagsTestTitle')}
</CardTitle>
<CardDescription>
Test the AI provider responsible for automatic tag suggestions
{t('admin.aiTest.tagsTestDescription')}
</CardDescription>
</CardHeader>
<CardContent className="pt-6">
@@ -56,10 +53,10 @@ export default async function AITestPage() {
<CardHeader className="bg-green-50/50 dark:bg-green-950/20">
<CardTitle className="flex items-center gap-2">
<span className="text-2xl">🔍</span>
Embeddings Test
{t('admin.aiTest.embeddingsTestTitle')}
</CardTitle>
<CardDescription>
Test the AI provider responsible for semantic search embeddings
{t('admin.aiTest.embeddingsTestDescription')}
</CardDescription>
</CardHeader>
<CardContent className="pt-6">
@@ -71,32 +68,31 @@ export default async function AITestPage() {
{/* Info Section */}
<Card className="mt-6">
<CardHeader>
<CardTitle> How Testing Works</CardTitle>
<CardTitle> {t('admin.aiTest.howItWorksTitle')}</CardTitle>
</CardHeader>
<CardContent className="space-y-4 text-sm">
<div>
<h4 className="font-semibold mb-2">🏷 Tags Generation Test:</h4>
<h4 className="font-semibold mb-2">{t('admin.aiTest.tagsGenerationTest')}</h4>
<ul className="list-disc list-inside space-y-1 text-muted-foreground">
<li>Sends a sample note to the AI provider</li>
<li>Requests 3-5 relevant tags based on the content</li>
<li>Displays the generated tags with confidence scores</li>
<li>Measures response time</li>
<li>{t('admin.aiTest.tagsStep1')}</li>
<li>{t('admin.aiTest.tagsStep2')}</li>
<li>{t('admin.aiTest.tagsStep3')}</li>
<li>{t('admin.aiTest.tagsStep4')}</li>
</ul>
</div>
<div>
<h4 className="font-semibold mb-2">🔍 Embeddings Test:</h4>
<h4 className="font-semibold mb-2">{t('admin.aiTest.embeddingsTestLabel')}</h4>
<ul className="list-disc list-inside space-y-1 text-muted-foreground">
<li>Sends a sample text to the embedding provider</li>
<li>Generates a vector representation (list of numbers)</li>
<li>Displays embedding dimensions and sample values</li>
<li>Verifies the vector is valid and properly formatted</li>
<li>{t('admin.aiTest.embeddingsStep1')}</li>
<li>{t('admin.aiTest.embeddingsStep2')}</li>
<li>{t('admin.aiTest.embeddingsStep3')}</li>
<li>{t('admin.aiTest.embeddingsStep4')}</li>
</ul>
</div>
<div className="bg-amber-50 dark:bg-amber-950/20 p-4 rounded-lg border border-amber-200 dark:border-amber-900">
<p className="font-semibold text-amber-900 dark:text-amber-100">💡 Tip:</p>
<p className="font-semibold text-amber-900 dark:text-amber-100">💡 {t('admin.aiTest.tipTitle')}</p>
<p className="text-amber-800 dark:text-amber-200 mt-1">
You can use different providers for tags and embeddings! For example, use Ollama (free) for tags
and OpenAI (best quality) for embeddings to optimize costs and performance.
{t('admin.aiTest.tipContent')}
</p>
</div>
</CardContent>