mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-14 23:01:09 +02:00
feat(matrix-web): add bots page with all 19 Matrix bots
- Add /bots route with bot overview grid - Create BotCard component with expandable details - Implement search and category filtering (AI, Productivity, Media, Lifestyle, Tools) - Add bot data structure with commands, descriptions, and metadata - Support starting chat with bots (creates DM or navigates to existing room) - Add German and English translations - Add robot icon to PillNavigation component Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
aba79f5c16
commit
23852cf605
7 changed files with 793 additions and 0 deletions
166
apps/matrix/apps/web/src/lib/components/bots/BotCard.svelte
Normal file
166
apps/matrix/apps/web/src/lib/components/bots/BotCard.svelte
Normal file
|
|
@ -0,0 +1,166 @@
|
|||
<script lang="ts">
|
||||
import type { BotInfo } from '$lib/data/bots';
|
||||
import {
|
||||
Lock,
|
||||
LockOpen,
|
||||
CaretDown,
|
||||
ChatCircle,
|
||||
// Bot icons
|
||||
Sparkle,
|
||||
Robot,
|
||||
CheckSquare,
|
||||
CalendarBlank,
|
||||
AddressBook,
|
||||
Folders,
|
||||
Image,
|
||||
SpeakerHigh,
|
||||
CloudArrowUp,
|
||||
ForkKnife,
|
||||
Plant,
|
||||
Quotes,
|
||||
TreeStructure,
|
||||
Clock,
|
||||
ChartBar,
|
||||
MagnifyingGlass,
|
||||
Cards,
|
||||
PresentationChart,
|
||||
} from '@manacore/shared-icons';
|
||||
import { slide } from 'svelte/transition';
|
||||
import { _ as t } from 'svelte-i18n';
|
||||
import type { Component } from 'svelte';
|
||||
|
||||
interface Props {
|
||||
bot: BotInfo;
|
||||
onStartChat: () => void;
|
||||
}
|
||||
|
||||
let { bot, onStartChat }: Props = $props();
|
||||
let expanded = $state(false);
|
||||
|
||||
// Map icon names to components
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const iconMap: Record<string, Component<any>> = {
|
||||
Sparkle,
|
||||
ChatCircle,
|
||||
Robot,
|
||||
CheckSquare,
|
||||
CalendarBlank,
|
||||
AddressBook,
|
||||
Folders,
|
||||
Image,
|
||||
SpeakerHigh,
|
||||
CloudArrowUp,
|
||||
ForkKnife,
|
||||
Plant,
|
||||
Quotes,
|
||||
TreeStructure,
|
||||
Clock,
|
||||
ChartBar,
|
||||
MagnifyingGlass,
|
||||
Cards,
|
||||
PresentationChart,
|
||||
};
|
||||
|
||||
let IconComponent = $derived(iconMap[bot.icon] || Robot);
|
||||
</script>
|
||||
|
||||
<div class="glass-card rounded-xl overflow-hidden border border-white/10">
|
||||
<!-- Header (always visible) -->
|
||||
<button
|
||||
class="w-full p-4 text-left hover:bg-white/5 transition-colors cursor-pointer"
|
||||
onclick={() => (expanded = !expanded)}
|
||||
>
|
||||
<div class="flex items-start gap-3">
|
||||
<div class="p-3 rounded-lg bg-gradient-to-br {bot.color} shadow-lg flex-shrink-0">
|
||||
<svelte:component this={IconComponent} size={24} class="text-white" weight="fill" />
|
||||
</div>
|
||||
<div class="flex-1 min-w-0">
|
||||
<div class="flex items-center gap-2">
|
||||
<h3 class="font-semibold text-foreground truncate">{bot.name}</h3>
|
||||
{#if bot.isGateway}
|
||||
<span class="text-xs bg-violet-500/20 text-violet-400 px-2 py-0.5 rounded-full">
|
||||
Gateway
|
||||
</span>
|
||||
{/if}
|
||||
</div>
|
||||
<p class="text-sm text-muted-foreground line-clamp-2 mt-0.5">{bot.description}</p>
|
||||
</div>
|
||||
<CaretDown
|
||||
size={20}
|
||||
class="text-muted-foreground transition-transform flex-shrink-0 {expanded
|
||||
? 'rotate-180'
|
||||
: ''}"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="mt-3 flex items-center gap-2 flex-wrap">
|
||||
{#if bot.requiresAuth}
|
||||
<span
|
||||
class="text-xs bg-amber-500/20 text-amber-400 px-2 py-0.5 rounded-full flex items-center gap-1"
|
||||
>
|
||||
<Lock size={12} /> Login
|
||||
</span>
|
||||
{:else}
|
||||
<span
|
||||
class="text-xs bg-green-500/20 text-green-400 px-2 py-0.5 rounded-full flex items-center gap-1"
|
||||
>
|
||||
<LockOpen size={12} />
|
||||
{$t('bots.free')}
|
||||
</span>
|
||||
{/if}
|
||||
<span class="text-xs bg-primary/20 text-primary px-2 py-0.5 rounded-full">
|
||||
{bot.commands.length}
|
||||
{$t('bots.commands')}
|
||||
</span>
|
||||
</div>
|
||||
</button>
|
||||
|
||||
<!-- Expandable Details -->
|
||||
{#if expanded}
|
||||
<div transition:slide={{ duration: 200 }} class="border-t border-white/10 p-4 space-y-4">
|
||||
<!-- Long Description -->
|
||||
{#if bot.longDescription}
|
||||
<p class="text-sm text-muted-foreground">{bot.longDescription}</p>
|
||||
{/if}
|
||||
|
||||
<!-- Commands -->
|
||||
<div>
|
||||
<h4 class="text-sm font-medium text-foreground mb-2">{$t('bots.commands')}</h4>
|
||||
<div class="space-y-1.5 max-h-48 overflow-y-auto">
|
||||
{#each bot.commands as cmd}
|
||||
<div class="text-xs bg-black/20 rounded px-2 py-1.5">
|
||||
<code class="text-primary font-mono">{cmd.command}</code>
|
||||
{#if cmd.aliases?.length}
|
||||
<span class="text-muted-foreground"> ({cmd.aliases.join(', ')})</span>
|
||||
{/if}
|
||||
<span class="text-muted-foreground ml-2">- {cmd.description}</span>
|
||||
{#if cmd.example}
|
||||
<div class="mt-1 text-muted-foreground/70 italic">
|
||||
{$t('bots.example')}: <code class="text-foreground/60">{cmd.example}</code>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Matrix User ID -->
|
||||
<div class="text-xs text-muted-foreground">
|
||||
<span class="font-medium">Matrix:</span>
|
||||
<code class="ml-1 text-foreground/60">{bot.matrixUserId}</code>
|
||||
</div>
|
||||
|
||||
<!-- Chat Button -->
|
||||
<button
|
||||
class="w-full bg-gradient-to-r from-violet-500 to-purple-600 text-white rounded-lg py-2.5 flex items-center justify-center gap-2 font-medium hover:from-violet-600 hover:to-purple-700 transition-all shadow-lg hover:shadow-xl cursor-pointer"
|
||||
onclick={(e) => {
|
||||
e.stopPropagation();
|
||||
onStartChat();
|
||||
}}
|
||||
>
|
||||
<ChatCircle size={18} weight="fill" />
|
||||
{$t('bots.startChat')}
|
||||
</button>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
424
apps/matrix/apps/web/src/lib/data/bots.ts
Normal file
424
apps/matrix/apps/web/src/lib/data/bots.ts
Normal file
|
|
@ -0,0 +1,424 @@
|
|||
export interface BotCommand {
|
||||
command: string;
|
||||
aliases?: string[];
|
||||
description: string;
|
||||
example?: string;
|
||||
}
|
||||
|
||||
export interface BotInfo {
|
||||
id: string;
|
||||
name: string;
|
||||
matrixUserId: string;
|
||||
description: string;
|
||||
longDescription?: string;
|
||||
icon: string;
|
||||
color: string;
|
||||
commands: BotCommand[];
|
||||
category: 'productivity' | 'ai' | 'media' | 'lifestyle' | 'tools';
|
||||
requiresAuth: boolean;
|
||||
isGateway?: boolean;
|
||||
}
|
||||
|
||||
export const BOTS: BotInfo[] = [
|
||||
// AI & Chat
|
||||
{
|
||||
id: 'mana-bot',
|
||||
name: 'Mana Bot',
|
||||
matrixUserId: '@mana-bot:matrix.mana.how',
|
||||
description: 'All-in-One Gateway zu allen Mana-Services',
|
||||
longDescription:
|
||||
'Der zentrale Hub, der alle anderen Bots vereint. Starte Chats, erstelle Bilder, verwalte Aufgaben und mehr - alles in einem Bot.',
|
||||
icon: 'Sparkle',
|
||||
color: 'from-violet-500 to-purple-600',
|
||||
category: 'ai',
|
||||
requiresAuth: true,
|
||||
isGateway: true,
|
||||
commands: [
|
||||
{ command: '!help', aliases: ['!hilfe'], description: 'Zeigt alle verfügbaren Befehle' },
|
||||
{ command: '!chat', description: 'Startet einen KI-Chat' },
|
||||
{ command: '!image', aliases: ['!bild'], description: 'Generiert ein Bild mit KI' },
|
||||
{ command: '!todo', description: 'Verwaltet Aufgaben' },
|
||||
{ command: '!calendar', aliases: ['!cal'], description: 'Kalender-Operationen' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'chat-bot',
|
||||
name: 'Chat Bot',
|
||||
matrixUserId: '@chat-bot:matrix.mana.how',
|
||||
description: 'KI-Assistent powered by Claude und anderen LLMs',
|
||||
longDescription:
|
||||
'Dein persönlicher KI-Assistent für Fragen, Texterstellung, Zusammenfassungen und kreative Aufgaben. Nutzt verschiedene KI-Modelle.',
|
||||
icon: 'ChatCircle',
|
||||
color: 'from-blue-500 to-cyan-500',
|
||||
category: 'ai',
|
||||
requiresAuth: true,
|
||||
commands: [
|
||||
{
|
||||
command: '!chat',
|
||||
description: 'Startet eine Konversation',
|
||||
example: '!chat Erkläre mir Quantencomputing',
|
||||
},
|
||||
{ command: '!model', description: 'Wechselt das KI-Modell', example: '!model gpt-4' },
|
||||
{ command: '!clear', description: 'Löscht den Chat-Verlauf' },
|
||||
{ command: '!system', description: 'Setzt einen System-Prompt' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'ollama-bot',
|
||||
name: 'Ollama Bot',
|
||||
matrixUserId: '@ollama-bot:matrix.mana.how',
|
||||
description: 'Lokale KI-Modelle via Ollama',
|
||||
longDescription:
|
||||
'Chatte mit lokal gehosteten Open-Source KI-Modellen. Vollständig privat, keine Daten verlassen den Server.',
|
||||
icon: 'Robot',
|
||||
color: 'from-emerald-500 to-teal-600',
|
||||
category: 'ai',
|
||||
requiresAuth: false,
|
||||
commands: [
|
||||
{ command: '!ollama', description: 'Startet einen Chat', example: '!ollama Hallo!' },
|
||||
{ command: '!models', description: 'Listet verfügbare Modelle' },
|
||||
{ command: '!switch', description: 'Wechselt das Modell', example: '!switch llama3' },
|
||||
],
|
||||
},
|
||||
|
||||
// Productivity
|
||||
{
|
||||
id: 'todo-bot',
|
||||
name: 'Todo Bot',
|
||||
matrixUserId: '@todo-bot:matrix.mana.how',
|
||||
description: 'Aufgabenverwaltung und To-Do Listen',
|
||||
longDescription:
|
||||
'Verwalte deine Aufgaben direkt im Chat. Erstelle, bearbeite und erledige Todos mit einfachen Befehlen.',
|
||||
icon: 'CheckSquare',
|
||||
color: 'from-green-500 to-emerald-600',
|
||||
category: 'productivity',
|
||||
requiresAuth: true,
|
||||
commands: [
|
||||
{
|
||||
command: '!add',
|
||||
description: 'Fügt eine neue Aufgabe hinzu',
|
||||
example: '!add Einkaufen gehen',
|
||||
},
|
||||
{ command: '!list', aliases: ['!todos'], description: 'Zeigt alle Aufgaben' },
|
||||
{ command: '!done', description: 'Markiert Aufgabe als erledigt', example: '!done 1' },
|
||||
{
|
||||
command: '!delete',
|
||||
aliases: ['!del'],
|
||||
description: 'Löscht eine Aufgabe',
|
||||
example: '!delete 1',
|
||||
},
|
||||
{ command: '!clear', description: 'Löscht alle erledigten Aufgaben' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'calendar-bot',
|
||||
name: 'Calendar Bot',
|
||||
matrixUserId: '@calendar-bot:matrix.mana.how',
|
||||
description: 'Terminverwaltung und Erinnerungen',
|
||||
longDescription:
|
||||
'Plane Termine, setze Erinnerungen und behalte deinen Zeitplan im Blick - alles per Chat-Befehl.',
|
||||
icon: 'CalendarBlank',
|
||||
color: 'from-orange-500 to-amber-600',
|
||||
category: 'productivity',
|
||||
requiresAuth: true,
|
||||
commands: [
|
||||
{
|
||||
command: '!event',
|
||||
description: 'Erstellt einen Termin',
|
||||
example: '!event Meeting morgen 14:00',
|
||||
},
|
||||
{ command: '!today', description: 'Zeigt heutige Termine' },
|
||||
{ command: '!week', description: 'Zeigt Termine dieser Woche' },
|
||||
{ command: '!remind', description: 'Setzt eine Erinnerung', example: '!remind 30min Anruf' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'contacts-bot',
|
||||
name: 'Contacts Bot',
|
||||
matrixUserId: '@contacts-bot:matrix.mana.how',
|
||||
description: 'Kontaktverwaltung und Adressbuch',
|
||||
longDescription:
|
||||
'Speichere und finde Kontaktinformationen schnell. Durchsuche dein Adressbuch direkt im Chat.',
|
||||
icon: 'AddressBook',
|
||||
color: 'from-indigo-500 to-blue-600',
|
||||
category: 'productivity',
|
||||
requiresAuth: true,
|
||||
commands: [
|
||||
{ command: '!find', description: 'Sucht nach Kontakten', example: '!find Max Mustermann' },
|
||||
{ command: '!add', description: 'Fügt einen Kontakt hinzu' },
|
||||
{ command: '!all', description: 'Listet alle Kontakte' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'project-doc-bot',
|
||||
name: 'Project Doc Bot',
|
||||
matrixUserId: '@project-doc-bot:matrix.mana.how',
|
||||
description: 'Projektdokumentation und Wissensbasis',
|
||||
longDescription:
|
||||
'Durchsuche Projektdokumentationen, finde Code-Beispiele und erhalte Antworten basierend auf deiner Wissensbasis.',
|
||||
icon: 'Folders',
|
||||
color: 'from-purple-500 to-violet-600',
|
||||
category: 'productivity',
|
||||
requiresAuth: true,
|
||||
commands: [
|
||||
{
|
||||
command: '!search',
|
||||
description: 'Durchsucht die Dokumentation',
|
||||
example: '!search API authentication',
|
||||
},
|
||||
{ command: '!projects', description: 'Listet verfügbare Projekte' },
|
||||
{ command: '!select', description: 'Wählt ein Projekt aus', example: '!select manacore' },
|
||||
],
|
||||
},
|
||||
|
||||
// Media
|
||||
{
|
||||
id: 'picture-bot',
|
||||
name: 'Picture Bot',
|
||||
matrixUserId: '@picture-bot:matrix.mana.how',
|
||||
description: 'KI-Bildgenerierung mit verschiedenen Modellen',
|
||||
longDescription:
|
||||
'Erstelle beeindruckende Bilder mit KI. Unterstützt verschiedene Stile und Modelle wie Stable Diffusion und DALL-E.',
|
||||
icon: 'Image',
|
||||
color: 'from-pink-500 to-rose-600',
|
||||
category: 'media',
|
||||
requiresAuth: true,
|
||||
commands: [
|
||||
{
|
||||
command: '!image',
|
||||
aliases: ['!bild'],
|
||||
description: 'Generiert ein Bild',
|
||||
example: '!image Ein Sonnenuntergang am Meer',
|
||||
},
|
||||
{ command: '!style', description: 'Wählt einen Stil', example: '!style anime' },
|
||||
{ command: '!size', description: 'Setzt die Bildgröße', example: '!size 1024x1024' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'tts-bot',
|
||||
name: 'TTS Bot',
|
||||
matrixUserId: '@tts-bot:matrix.mana.how',
|
||||
description: 'Text-to-Speech Sprachausgabe',
|
||||
longDescription:
|
||||
'Wandle Text in natürlich klingende Sprache um. Unterstützt verschiedene Stimmen und Sprachen.',
|
||||
icon: 'SpeakerHigh',
|
||||
color: 'from-cyan-500 to-sky-600',
|
||||
category: 'media',
|
||||
requiresAuth: true,
|
||||
commands: [
|
||||
{
|
||||
command: '!speak',
|
||||
aliases: ['!say'],
|
||||
description: 'Spricht Text vor',
|
||||
example: '!speak Hallo Welt',
|
||||
},
|
||||
{ command: '!voice', description: 'Wählt eine Stimme', example: '!voice nova' },
|
||||
{ command: '!lang', description: 'Setzt die Sprache', example: '!lang de' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'storage-bot',
|
||||
name: 'Storage Bot',
|
||||
matrixUserId: '@storage-bot:matrix.mana.how',
|
||||
description: 'Cloud-Speicher und Dateiverwaltung',
|
||||
longDescription:
|
||||
'Verwalte deine Dateien in der Cloud. Lade hoch, teile und organisiere direkt aus dem Chat.',
|
||||
icon: 'CloudArrowUp',
|
||||
color: 'from-slate-500 to-zinc-600',
|
||||
category: 'media',
|
||||
requiresAuth: true,
|
||||
commands: [
|
||||
{ command: '!upload', description: 'Lädt eine Datei hoch' },
|
||||
{ command: '!files', description: 'Listet deine Dateien' },
|
||||
{ command: '!share', description: 'Teilt eine Datei', example: '!share document.pdf' },
|
||||
{ command: '!delete', description: 'Löscht eine Datei' },
|
||||
],
|
||||
},
|
||||
|
||||
// Lifestyle
|
||||
{
|
||||
id: 'nutriphi-bot',
|
||||
name: 'NutriPhi Bot',
|
||||
matrixUserId: '@nutriphi-bot:matrix.mana.how',
|
||||
description: 'Ernährungstracking und Mahlzeiten-Analyse',
|
||||
longDescription:
|
||||
'Tracke deine Ernährung, analysiere Mahlzeiten per Foto und erhalte Nährwertinformationen.',
|
||||
icon: 'ForkKnife',
|
||||
color: 'from-lime-500 to-green-600',
|
||||
category: 'lifestyle',
|
||||
requiresAuth: true,
|
||||
commands: [
|
||||
{
|
||||
command: '!log',
|
||||
description: 'Protokolliert eine Mahlzeit',
|
||||
example: '!log 2 Äpfel, 1 Sandwich',
|
||||
},
|
||||
{ command: '!today', description: 'Zeigt heutige Kalorien' },
|
||||
{ command: '!analyze', description: 'Analysiert ein Essens-Foto' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'planta-bot',
|
||||
name: 'Planta Bot',
|
||||
matrixUserId: '@planta-bot:matrix.mana.how',
|
||||
description: 'Pflanzenidentifikation und Pflege-Tipps',
|
||||
longDescription:
|
||||
'Identifiziere Pflanzen per Foto und erhalte Pflege-Anleitungen. Perfekt für Hobbygärtner.',
|
||||
icon: 'Plant',
|
||||
color: 'from-green-600 to-emerald-700',
|
||||
category: 'lifestyle',
|
||||
requiresAuth: true,
|
||||
commands: [
|
||||
{ command: '!identify', description: 'Identifiziert eine Pflanze per Foto' },
|
||||
{ command: '!care', description: 'Zeigt Pflegetipps', example: '!care Monstera' },
|
||||
{ command: '!water', description: 'Erinnerung zum Gießen setzen' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'zitare-bot',
|
||||
name: 'Zitare Bot',
|
||||
matrixUserId: '@zitare-bot:matrix.mana.how',
|
||||
description: 'Tägliche Inspiration und Weisheiten',
|
||||
longDescription:
|
||||
'Erhalte inspirierende Zitate und Weisheiten. Perfekt für den täglichen Motivationsschub.',
|
||||
icon: 'Quotes',
|
||||
color: 'from-amber-500 to-orange-600',
|
||||
category: 'lifestyle',
|
||||
requiresAuth: true,
|
||||
commands: [
|
||||
{ command: '!quote', aliases: ['!zitat'], description: 'Zeigt ein zufälliges Zitat' },
|
||||
{ command: '!daily', description: 'Aktiviert tägliche Zitate' },
|
||||
{ command: '!topic', description: 'Zitat zu einem Thema', example: '!topic Erfolg' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'skilltree-bot',
|
||||
name: 'SkillTree Bot',
|
||||
matrixUserId: '@skilltree-bot:matrix.mana.how',
|
||||
description: 'Fähigkeiten-Tracking und Lernfortschritt',
|
||||
longDescription:
|
||||
'Verfolge deinen Lernfortschritt, setze Ziele und entwickle deine Fähigkeiten systematisch weiter.',
|
||||
icon: 'TreeStructure',
|
||||
color: 'from-yellow-500 to-amber-600',
|
||||
category: 'lifestyle',
|
||||
requiresAuth: true,
|
||||
commands: [
|
||||
{ command: '!skills', description: 'Zeigt deine Fähigkeiten' },
|
||||
{ command: '!add', description: 'Fügt eine Fähigkeit hinzu', example: '!add TypeScript' },
|
||||
{
|
||||
command: '!progress',
|
||||
description: 'Protokolliert Fortschritt',
|
||||
example: '!progress TypeScript +2h',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
// Tools
|
||||
{
|
||||
id: 'clock-bot',
|
||||
name: 'Clock Bot',
|
||||
matrixUserId: '@clock-bot:matrix.mana.how',
|
||||
description: 'Zeiterfassung und Zeitzonen',
|
||||
longDescription:
|
||||
'Tracke Arbeitszeiten, konvertiere Zeitzonen und setze Timer für Fokus-Sessions.',
|
||||
icon: 'Clock',
|
||||
color: 'from-blue-600 to-indigo-700',
|
||||
category: 'tools',
|
||||
requiresAuth: true,
|
||||
commands: [
|
||||
{ command: '!start', description: 'Startet Zeiterfassung' },
|
||||
{ command: '!stop', description: 'Stoppt Zeiterfassung' },
|
||||
{ command: '!time', description: 'Zeigt aktuelle Zeit in Zonen', example: '!time NYC' },
|
||||
{ command: '!timer', description: 'Setzt einen Timer', example: '!timer 25m Pomodoro' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'stats-bot',
|
||||
name: 'Stats Bot',
|
||||
matrixUserId: '@stats-bot:matrix.mana.how',
|
||||
description: 'Nutzungsstatistiken und Analytics',
|
||||
longDescription:
|
||||
'Erhalte Einblicke in deine Nutzung der Mana-Services. Statistiken, Trends und Zusammenfassungen.',
|
||||
icon: 'ChartBar',
|
||||
color: 'from-fuchsia-500 to-pink-600',
|
||||
category: 'tools',
|
||||
requiresAuth: true,
|
||||
commands: [
|
||||
{ command: '!stats', description: 'Zeigt Nutzungsstatistiken' },
|
||||
{ command: '!usage', description: 'Credits-Verbrauch diese Woche' },
|
||||
{ command: '!top', description: 'Meistgenutzte Features' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'questions-bot',
|
||||
name: 'Questions Bot',
|
||||
matrixUserId: '@questions-bot:matrix.mana.how',
|
||||
description: 'Websuche und Fakten-Recherche',
|
||||
longDescription:
|
||||
'Durchsuche das Web und erhalte fundierte Antworten mit Quellenangaben. Perfekt für Recherchen.',
|
||||
icon: 'MagnifyingGlass',
|
||||
color: 'from-teal-500 to-cyan-600',
|
||||
category: 'tools',
|
||||
requiresAuth: true,
|
||||
commands: [
|
||||
{
|
||||
command: '!search',
|
||||
aliases: ['!q'],
|
||||
description: 'Sucht im Web',
|
||||
example: '!search Wetter Berlin',
|
||||
},
|
||||
{ command: '!wiki', description: 'Sucht auf Wikipedia', example: '!wiki Photosynthese' },
|
||||
{ command: '!news', description: 'Aktuelle Nachrichten' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'manadeck-bot',
|
||||
name: 'ManaDeck Bot',
|
||||
matrixUserId: '@manadeck-bot:matrix.mana.how',
|
||||
description: 'Lernkarten und Spaced Repetition',
|
||||
longDescription:
|
||||
'Erstelle und lerne mit Karteikarten. Nutzt Spaced Repetition für optimales Lernen.',
|
||||
icon: 'Cards',
|
||||
color: 'from-violet-600 to-purple-700',
|
||||
category: 'tools',
|
||||
requiresAuth: true,
|
||||
commands: [
|
||||
{ command: '!learn', description: 'Startet eine Lernsession' },
|
||||
{ command: '!add', description: 'Fügt eine Karte hinzu', example: '!add Frage | Antwort' },
|
||||
{ command: '!decks', description: 'Listet deine Decks' },
|
||||
{ command: '!stats', description: 'Zeigt Lernfortschritt' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'presi-bot',
|
||||
name: 'Presi Bot',
|
||||
matrixUserId: '@presi-bot:matrix.mana.how',
|
||||
description: 'Präsentationen erstellen mit KI',
|
||||
longDescription:
|
||||
'Erstelle professionelle Präsentationen mit KI-Unterstützung. Generiere Folien aus Text oder Themen.',
|
||||
icon: 'PresentationChart',
|
||||
color: 'from-red-500 to-rose-600',
|
||||
category: 'tools',
|
||||
requiresAuth: true,
|
||||
commands: [
|
||||
{
|
||||
command: '!create',
|
||||
description: 'Erstellt eine Präsentation',
|
||||
example: '!create Thema: KI im Alltag',
|
||||
},
|
||||
{ command: '!slides', description: 'Zeigt deine Präsentationen' },
|
||||
{ command: '!export', description: 'Exportiert als PDF/PPTX' },
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
export const CATEGORIES = [
|
||||
{ id: 'all', label: 'Alle' },
|
||||
{ id: 'productivity', label: 'Produktivität' },
|
||||
{ id: 'ai', label: 'KI & Chat' },
|
||||
{ id: 'media', label: 'Medien' },
|
||||
{ id: 'lifestyle', label: 'Lifestyle' },
|
||||
{ id: 'tools', label: 'Tools' },
|
||||
] as const;
|
||||
|
||||
export type BotCategory = (typeof CATEGORIES)[number]['id'];
|
||||
|
|
@ -5,6 +5,7 @@
|
|||
},
|
||||
"nav": {
|
||||
"chat": "Chat",
|
||||
"bots": "Bots",
|
||||
"settings": "Einstellungen"
|
||||
},
|
||||
"auth": {
|
||||
|
|
@ -21,5 +22,25 @@
|
|||
"typeMessage": "Nachricht schreiben...",
|
||||
"noRooms": "Noch keine Räume",
|
||||
"noMessages": "Noch keine Nachrichten"
|
||||
},
|
||||
"bots": {
|
||||
"title": "Bots",
|
||||
"subtitle": "Entdecke alle verfügbaren Bot-Assistenten",
|
||||
"search": "Bot suchen...",
|
||||
"startChat": "Chat starten",
|
||||
"commands": "Befehle",
|
||||
"example": "Beispiel",
|
||||
"free": "Frei",
|
||||
"requiresLogin": "Erfordert Anmeldung",
|
||||
"noResults": "Keine Bots gefunden",
|
||||
"found": "gefunden",
|
||||
"categories": {
|
||||
"all": "Alle",
|
||||
"productivity": "Produktivität",
|
||||
"ai": "KI & Chat",
|
||||
"media": "Medien",
|
||||
"lifestyle": "Lifestyle",
|
||||
"tools": "Tools"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
},
|
||||
"nav": {
|
||||
"chat": "Chat",
|
||||
"bots": "Bots",
|
||||
"settings": "Settings"
|
||||
},
|
||||
"auth": {
|
||||
|
|
@ -21,5 +22,25 @@
|
|||
"typeMessage": "Type a message...",
|
||||
"noRooms": "No rooms yet",
|
||||
"noMessages": "No messages yet"
|
||||
},
|
||||
"bots": {
|
||||
"title": "Bots",
|
||||
"subtitle": "Discover all available bot assistants",
|
||||
"search": "Search bots...",
|
||||
"startChat": "Start Chat",
|
||||
"commands": "Commands",
|
||||
"example": "Example",
|
||||
"free": "Free",
|
||||
"requiresLogin": "Requires login",
|
||||
"noResults": "No bots found",
|
||||
"found": "found",
|
||||
"categories": {
|
||||
"all": "All",
|
||||
"productivity": "Productivity",
|
||||
"ai": "AI & Chat",
|
||||
"media": "Media",
|
||||
"lifestyle": "Lifestyle",
|
||||
"tools": "Tools"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@
|
|||
// Navigation items for Matrix
|
||||
const navItems: PillNavItem[] = [
|
||||
{ href: '/chat', label: 'Chat', icon: 'home' },
|
||||
{ href: '/bots', label: 'Bots', icon: 'robot' },
|
||||
{ href: '/settings', label: 'Einstellungen', icon: 'settings' },
|
||||
];
|
||||
|
||||
|
|
|
|||
158
apps/matrix/apps/web/src/routes/(app)/bots/+page.svelte
Normal file
158
apps/matrix/apps/web/src/routes/(app)/bots/+page.svelte
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
<script lang="ts">
|
||||
import { BOTS, CATEGORIES, type BotCategory, type BotInfo } from '$lib/data/bots';
|
||||
import { matrixStore } from '$lib/matrix';
|
||||
import { goto } from '$app/navigation';
|
||||
import { _ as t } from 'svelte-i18n';
|
||||
import { MagnifyingGlass, Robot, CircleNotch } from '@manacore/shared-icons';
|
||||
import BotCard from '$lib/components/bots/BotCard.svelte';
|
||||
|
||||
let search = $state('');
|
||||
let selectedCategory = $state<BotCategory>('all');
|
||||
let startingChat = $state<string | null>(null);
|
||||
|
||||
let filteredBots = $derived(
|
||||
BOTS.filter((bot) => {
|
||||
const searchLower = search.toLowerCase();
|
||||
const matchesSearch =
|
||||
bot.name.toLowerCase().includes(searchLower) ||
|
||||
bot.description.toLowerCase().includes(searchLower) ||
|
||||
bot.commands.some((cmd) => cmd.command.toLowerCase().includes(searchLower));
|
||||
const matchesCategory = selectedCategory === 'all' || bot.category === selectedCategory;
|
||||
return matchesSearch && matchesCategory;
|
||||
})
|
||||
);
|
||||
|
||||
let categoryLabels = $derived(
|
||||
CATEGORIES.map((cat) => ({
|
||||
...cat,
|
||||
label: $t(`bots.categories.${cat.id}`),
|
||||
}))
|
||||
);
|
||||
|
||||
async function startChat(bot: BotInfo) {
|
||||
startingChat = bot.id;
|
||||
|
||||
try {
|
||||
// Check if a DM room with this bot already exists
|
||||
const existingRoom = matrixStore.directRooms.find((r) => r.dmUserId === bot.matrixUserId);
|
||||
|
||||
if (existingRoom) {
|
||||
// Select existing room
|
||||
matrixStore.selectRoom(existingRoom.id);
|
||||
} else {
|
||||
// Create new DM room with the bot
|
||||
const roomId = await matrixStore.createRoom({
|
||||
isDirect: true,
|
||||
invite: [bot.matrixUserId],
|
||||
});
|
||||
|
||||
if (roomId) {
|
||||
matrixStore.selectRoom(roomId);
|
||||
}
|
||||
}
|
||||
|
||||
// Navigate to chat
|
||||
goto('/chat');
|
||||
} catch (err) {
|
||||
console.error('Failed to start chat with bot:', err);
|
||||
} finally {
|
||||
startingChat = null;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>{$t('bots.title')} - Manalink</title>
|
||||
</svelte:head>
|
||||
|
||||
<div class="h-full overflow-y-auto bg-background">
|
||||
<div class="max-w-6xl mx-auto px-4 py-6 pb-24 md:pb-6">
|
||||
<!-- Header -->
|
||||
<div class="mb-6">
|
||||
<div class="flex items-center gap-3 mb-2">
|
||||
<div class="p-2.5 rounded-xl bg-gradient-to-br from-violet-500 to-purple-600 shadow-lg">
|
||||
<Robot size={28} class="text-white" weight="fill" />
|
||||
</div>
|
||||
<div>
|
||||
<h1 class="text-2xl font-bold text-foreground">{$t('bots.title')}</h1>
|
||||
<p class="text-muted-foreground text-sm">{$t('bots.subtitle')}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Search -->
|
||||
<div class="mb-4">
|
||||
<div class="relative">
|
||||
<MagnifyingGlass
|
||||
size={20}
|
||||
class="absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground"
|
||||
/>
|
||||
<input
|
||||
type="text"
|
||||
bind:value={search}
|
||||
placeholder={$t('bots.search')}
|
||||
class="w-full pl-10 pr-4 py-2.5 rounded-xl bg-white/5 border border-white/10 text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-primary/50 focus:border-primary/50 transition-all"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Category Tabs -->
|
||||
<div class="mb-6 overflow-x-auto scrollbar-hide">
|
||||
<div class="flex gap-2 min-w-max pb-1">
|
||||
{#each categoryLabels as category}
|
||||
<button
|
||||
class="px-4 py-2 rounded-full text-sm font-medium transition-all whitespace-nowrap cursor-pointer
|
||||
{selectedCategory === category.id
|
||||
? 'bg-gradient-to-r from-violet-500 to-purple-600 text-white shadow-lg'
|
||||
: 'bg-white/5 text-muted-foreground hover:bg-white/10 hover:text-foreground border border-white/10'}"
|
||||
onclick={() => (selectedCategory = category.id as BotCategory)}
|
||||
>
|
||||
{category.label}
|
||||
</button>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Bot Grid -->
|
||||
{#if filteredBots.length === 0}
|
||||
<div class="text-center py-12">
|
||||
<Robot size={48} class="text-muted-foreground/50 mx-auto mb-4" />
|
||||
<p class="text-muted-foreground">{$t('bots.noResults')}</p>
|
||||
</div>
|
||||
{:else}
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
||||
{#each filteredBots as bot (bot.id)}
|
||||
<div class="relative">
|
||||
<BotCard {bot} onStartChat={() => startChat(bot)} />
|
||||
{#if startingChat === bot.id}
|
||||
<div
|
||||
class="absolute inset-0 bg-background/80 backdrop-blur-sm rounded-xl flex items-center justify-center"
|
||||
>
|
||||
<CircleNotch size={32} class="text-primary animate-spin" />
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<!-- Bot Count -->
|
||||
<div class="mt-6 text-center text-sm text-muted-foreground">
|
||||
{filteredBots.length}
|
||||
{filteredBots.length === 1 ? 'Bot' : 'Bots'}
|
||||
{#if selectedCategory !== 'all' || search}
|
||||
{$t('bots.found')}
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.scrollbar-hide {
|
||||
-ms-overflow-style: none;
|
||||
scrollbar-width: none;
|
||||
}
|
||||
.scrollbar-hide::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -54,6 +54,7 @@
|
|||
Buildings,
|
||||
User,
|
||||
Scales,
|
||||
Robot,
|
||||
} from '@manacore/shared-icons';
|
||||
|
||||
// Map icon names to Phosphor components
|
||||
|
|
@ -105,6 +106,7 @@
|
|||
creditCard: CreditCard,
|
||||
building: Buildings,
|
||||
scale: Scales,
|
||||
robot: Robot,
|
||||
};
|
||||
|
||||
// Convert app items to dropdown items (will be computed as derived)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue