feat: integrate Guide-Tab (Anleitung) for local Vibe Coding and compile frontend

This commit is contained in:
Hitonabi
2026-06-25 22:36:58 +02:00
parent bd6aacf3ed
commit b08e867c1a
10 changed files with 674 additions and 344 deletions
+3 -1
View File
@@ -8,6 +8,7 @@ import { SystemView } from "@/views/SystemView"
import { ConnectView } from "@/views/ConnectView"
import { MemoryView } from "@/views/MemoryView"
import { AgentView } from "@/views/AgentView"
import { GuideView } from "@/views/GuideView"
import { Placeholder } from "@/views/Placeholder"
import { SystemDrawer } from "@/components/SystemDrawer"
import { api, type Health, type UpdatesResp } from "@/lib/api"
@@ -191,7 +192,8 @@ export default function App() {
{view === "connect" && <ConnectView />}
{view === "memory" && <MemoryView />}
{view === "agent" && <AgentView />}
{!["dashboard", "models", "system", "connect", "memory", "agent"].includes(view) && (
{view === "guide" && <GuideView />}
{!["dashboard", "models", "system", "connect", "memory", "agent", "guide"].includes(view) && (
<Placeholder title={active.label} hint={active.hint} />
)}
</main>
+4 -1
View File
@@ -5,10 +5,11 @@ import {
Brain,
Plug,
Bot,
HelpCircle,
type LucideIcon,
} from "lucide-react"
export type ViewId = "dashboard" | "models" | "system" | "memory" | "connect" | "agent"
export type ViewId = "dashboard" | "models" | "system" | "memory" | "connect" | "agent" | "guide"
export interface NavItem {
id: ViewId
@@ -25,5 +26,7 @@ export const NAV: NavItem[] = [
{ id: "memory", label: "Gedächtnis", hint: "Geteiltes Memory verwalten", icon: Brain },
{ id: "connect", label: "Verbinden", hint: "IDE-/Agent-Configs erzeugen", icon: Plug },
{ id: "agent", label: "Hermes", hint: "Agent-Status & WebUI öffnen", icon: Bot },
{ id: "guide", label: "Anleitung", hint: "Einrichten & Vibe-Coding", icon: HelpCircle },
]
+305
View File
@@ -0,0 +1,305 @@
import { useState, useEffect } from "react"
import { BookOpen, Layers, Brain, Terminal, Code, RefreshCw, Cpu, Star } from "lucide-react"
import { api, type Health } from "@/lib/api"
import { cn } from "@/lib/utils"
export function GuideView() {
const [activeTab, setActiveTab] = useState<"roocode" | "cursor" | "opencode">("roocode")
const [health, setHealth] = useState<Health | null>(null)
const [testing, setTesting] = useState(false)
const [testResult, setTestResult] = useState<string | null>(null)
function checkConnection() {
setTesting(true)
api<Health>("/api/health")
.then((h) => {
setHealth(h)
setTestResult(h.engine_reachable ? "success" : "partial")
})
.catch(() => {
setHealth(null)
setTestResult("fail")
})
.finally(() => setTesting(false))
}
useEffect(() => {
checkConnection()
}, [])
return (
<div className="space-y-6">
{/* Title */}
<div>
<h1 className="text-2xl font-space font-bold tracking-tight bg-gradient-to-r from-foreground via-foreground to-primary bg-clip-text text-transparent">
Stack-Anleitung &amp; Vibe-Coding-Guide
</h1>
<p className="text-sm text-muted-foreground">
Einsteigerfreundliche Erklärungen zu deinem Stack und Schritt-für-Schritt-Anleitungen zur Anbindung deiner Editoren.
</p>
</div>
{/* Connection HUD Panel */}
<div className="rounded-2xl border border-border/60 bg-card/45 backdrop-blur-md p-5 shadow-lg shadow-black/10 flex flex-col sm:flex-row justify-between sm:items-center gap-4">
<div className="flex items-center gap-3">
<span className={cn(
"h-3 w-3 rounded-full ring-2 ring-black/40",
testResult === "success" && "bg-emerald-500 animate-pulse",
testResult === "partial" && "bg-amber-500",
testResult === "fail" && "bg-red-500",
!testResult && "bg-muted"
)} />
<div>
<div className="text-xs font-bold uppercase tracking-wider text-foreground">Lokaler Verbindungs-Check</div>
<div className="text-[10px] text-muted-foreground mt-0.5 font-mono">
{testResult === "success" && `Erfolgreich! Dein PC hat Zugriff auf das Box-Gateway (v${health?.version || ""}).`}
{testResult === "partial" && "Gateway erreichbar, aber die llama-cpp-Engine ist offline."}
{testResult === "fail" && "Verbindung fehlgeschlagen. Ist die Box im selben LAN-Netzwerk?"}
{!testResult && "Verbindung wird geprüft..."}
</div>
</div>
</div>
<button
onClick={checkConnection}
disabled={testing}
className="h-8 px-3 flex items-center gap-1.5 text-xs font-semibold rounded-lg border border-border/60 bg-background/20 hover:border-primary/50 transition-colors disabled:opacity-50 cursor-pointer self-start sm:self-auto shrink-0"
>
<RefreshCw className={cn("h-3.5 w-3.5", testing && "animate-spin")} />
<span>Testen</span>
</button>
</div>
{/* Conceptual Explanation Grid */}
<div className="space-y-3">
<div className="flex items-center gap-2 px-1">
<BookOpen className="h-4.5 w-4.5 text-primary" />
<h2 className="text-xs font-bold uppercase tracking-wider text-foreground">Wie funktioniert mein Stack?</h2>
</div>
<div className="grid gap-4 sm:grid-cols-3">
{/* Card 1: Dashboard */}
<div className="p-4 rounded-xl border border-border/60 bg-card/20 space-y-2">
<div className="flex items-center gap-1.5">
<Cpu className="h-4 w-4 text-cyan-400" />
<h3 className="text-xs font-bold text-foreground">1. Die Zentrale</h3>
</div>
<p className="text-[11px] text-muted-foreground leading-relaxed">
Dein Dashboard. Hier siehst du die CPU-/RAM- und GPU-Last der Box und siehst sofort, ob Updates anstehen.
</p>
</div>
{/* Card 2: Llama Swap */}
<div className="p-4 rounded-xl border border-border/60 bg-card/20 space-y-2">
<div className="flex items-center gap-1.5">
<Layers className="h-4 w-4 text-violet-400" />
<h3 className="text-xs font-bold text-foreground">2. Modell-Zentrale</h3>
</div>
<p className="text-[11px] text-muted-foreground leading-relaxed">
Deine GGUF-Datenbank. Gesteuert von <strong>llama-swap</strong>. Lädt dein schnelles Alltags-Hirn (`fast`) oder dein schweres Logik-Hirn (`heavy`) vollautomatisch im VRAM.
</p>
</div>
{/* Card 3: Memory */}
<div className="p-4 rounded-xl border border-border/60 bg-card/20 space-y-2">
<div className="flex items-center gap-1.5">
<Brain className="h-4 w-4 text-indigo-400" />
<h3 className="text-xs font-bold text-foreground">3. Das Gedächtnis</h3>
</div>
<p className="text-[11px] text-muted-foreground leading-relaxed">
Dein geteiltes Langzeitgedächtnis (Memory-Pool). Hier merkt sich dein Agent Regeln, Projekt-Details und Vorlieben.
</p>
</div>
</div>
</div>
{/* Editor Integration Guides */}
<div className="space-y-4">
<div className="flex items-center gap-2 px-1">
<Code className="h-4.5 w-4.5 text-primary" />
<h2 className="text-xs font-bold uppercase tracking-wider text-foreground">Vibe Coding auf dem PC einrichten</h2>
</div>
{/* Editor Selector Tabs */}
<div className="flex gap-1.5 bg-card/20 p-1 border border-border/40 rounded-xl max-w-fit">
<button
onClick={() => setActiveTab("roocode")}
className={cn(
"rounded-lg px-4 py-1.5 text-xs font-semibold tracking-wide uppercase transition-all cursor-pointer flex items-center gap-1.5",
activeTab === "roocode"
? "bg-primary text-primary-foreground shadow-md shadow-primary/10"
: "text-muted-foreground hover:text-foreground"
)}
>
<Star className="h-3.5 w-3.5 fill-amber-400/20" />
Roo Code (VS Code)
</button>
<button
onClick={() => setActiveTab("cursor")}
className={cn(
"rounded-lg px-4 py-1.5 text-xs font-semibold tracking-wide uppercase transition-all cursor-pointer",
activeTab === "cursor"
? "bg-primary text-primary-foreground shadow-md shadow-primary/10"
: "text-muted-foreground hover:text-foreground"
)}
>
Cursor IDE
</button>
<button
onClick={() => setActiveTab("opencode")}
className={cn(
"rounded-lg px-4 py-1.5 text-xs font-semibold tracking-wide uppercase transition-all cursor-pointer",
activeTab === "opencode"
? "bg-primary text-primary-foreground shadow-md shadow-primary/10"
: "text-muted-foreground hover:text-foreground"
)}
>
OpenCode Desktop
</button>
</div>
{/* Guide Content */}
<div className="rounded-2xl border border-border/60 bg-card/45 backdrop-blur-md p-6 space-y-4 shadow-lg shadow-black/10">
{activeTab === "roocode" && (
<div className="space-y-4 text-xs leading-relaxed text-muted-foreground">
<div className="space-y-1">
<h3 className="text-sm font-bold text-foreground">Roo Code Kopplung (Empfohlene Open-Source-Erweiterung)</h3>
<p>Roo Code ist die beliebteste und flexibelste Vibe-Coding-Erweiterung für VS Code im Jahr 2026. Sie ermöglicht vollen Zugriff auf das Terminal und das MCP-Gedächtnis.</p>
</div>
<div className="space-y-3.5 border-t border-border/20 pt-4">
<div className="space-y-1">
<div className="font-semibold text-foreground flex items-center gap-1.5">
<span className="h-4.5 w-4.5 rounded-full bg-primary/20 text-primary flex items-center justify-center font-mono text-[10px]">1</span>
Roo Code installieren
</div>
<p className="pl-6">Suche in VS Code nach der Erweiterung <strong>Roo Code</strong> und installiere sie.</p>
</div>
<div className="space-y-1">
<div className="font-semibold text-foreground flex items-center gap-1.5">
<span className="h-4.5 w-4.5 rounded-full bg-primary/20 text-primary flex items-center justify-center font-mono text-[10px]">2</span>
API-Anbindung konfigurieren
</div>
<p className="pl-6">Klicke auf das Roo-Code-Symbol in der Sidebar, öffne die Einstellungen (Zahnrad) und stelle folgendes ein:</p>
<div className="pl-6 pt-1">
<div className="p-3 bg-background/25 rounded-xl border border-border/30 font-mono text-[10px] space-y-1 text-foreground">
<div><span className="text-muted-foreground/60">API Provider:</span> OpenAI Compatible</div>
<div><span className="text-muted-foreground/60">Base URL:</span> http://192.168.178.151:9001/v1</div>
<div><span className="text-muted-foreground/60">API Key:</span> <span className="italic text-muted-foreground/50">beliebig (z.B. "local")</span></div>
<div><span className="text-muted-foreground/60">Model ID:</span> auto</div>
</div>
</div>
</div>
<div className="space-y-1">
<div className="font-semibold text-foreground flex items-center gap-1.5">
<span className="h-4.5 w-4.5 rounded-full bg-primary/20 text-primary flex items-center justify-center font-mono text-[10px]">3</span>
MCP Gedächtnis verknüpfen (Optional, aber empfohlen)
</div>
<p className="pl-6">Damit Roo Code auf deinen <strong>Gedächtnis-Pool</strong> zugreifen kann, kopiere die MCP-Konfiguration aus dem Reiter <strong>Verbinden</strong> und füge sie in deine lokale Roo-Code-Konfigurationsdatei ein.</p>
</div>
</div>
</div>
)}
{activeTab === "cursor" && (
<div className="space-y-4 text-xs leading-relaxed text-muted-foreground">
<div className="space-y-1">
<h3 className="text-sm font-bold text-foreground">Cursor IDE Kopplung (Proprietäre All-in-One IDE)</h3>
<p>Cursor ist ein polierter, extrem schneller VS-Code-Fork mit hervorragenden, tief integrierten Autovervollständigungen (Tab-Completions).</p>
</div>
<div className="space-y-3.5 border-t border-border/20 pt-4">
<div className="space-y-1">
<div className="font-semibold text-foreground flex items-center gap-1.5">
<span className="h-4.5 w-4.5 rounded-full bg-primary/20 text-primary flex items-center justify-center font-mono text-[10px]">1</span>
Einstellungen öffnen
</div>
<p className="pl-6">Öffne Cursor, klicke oben rechts auf das Zahnrad (Settings) und navigiere zu <strong>Models</strong>.</p>
</div>
<div className="space-y-1">
<div className="font-semibold text-foreground flex items-center gap-1.5">
<span className="h-4.5 w-4.5 rounded-full bg-primary/20 text-primary flex items-center justify-center font-mono text-[10px]">2</span>
OpenAI API überschreiben
</div>
<p className="pl-6">Deaktiviere die Standard-Cloudmodelle, klappe den Bereich <strong>OpenAI API</strong> auf und konfiguriere:</p>
<div className="pl-6 pt-1">
<div className="p-3 bg-background/25 rounded-xl border border-border/30 font-mono text-[10px] space-y-1 text-foreground">
<div><span className="text-muted-foreground/60">Override Base URL:</span> http://192.168.178.151:9001/v1</div>
<div><span className="text-muted-foreground/60">API Key:</span> <span className="italic text-muted-foreground/50">beliebig (z.B. "local")</span></div>
</div>
</div>
</div>
<div className="space-y-1">
<div className="font-semibold text-foreground flex items-center gap-1.5">
<span className="h-4.5 w-4.5 rounded-full bg-primary/20 text-primary flex items-center justify-center font-mono text-[10px]">3</span>
Modell hinzufügen
</div>
<p className="pl-6">Trage in der Modell-Liste ein neues Modell mit dem Namen <strong>auto</strong> ein und wähle es als aktives Modell aus. Cursor leitet ab jetzt alle deine Anfragen an die Box weiter.</p>
</div>
</div>
</div>
)}
{activeTab === "opencode" && (
<div className="space-y-4 text-xs leading-relaxed text-muted-foreground">
<div className="space-y-1">
<h3 className="text-sm font-bold text-foreground">OpenCode Desktop Kopplung (Open-Source Vibe-Coding-App)</h3>
<p>OpenCode ist eine standalone Desktop-App für ein ablenkungsfreies Coden über natürliche Sprache. Es trennt den KI-Prozess von deinem Editor.</p>
</div>
<div className="space-y-3.5 border-t border-border/20 pt-4">
<div className="space-y-1">
<div className="font-semibold text-foreground flex items-center gap-1.5">
<span className="h-4.5 w-4.5 rounded-full bg-primary/20 text-primary flex items-center justify-center font-mono text-[10px]">1</span>
OpenCode Desktop herunterladen
</div>
<p className="pl-6">Lade die Desktop-Anwendung von der offiziellen Website (opencode.ai) herunter und starte sie.</p>
</div>
<div className="space-y-1">
<div className="font-semibold text-foreground flex items-center gap-1.5">
<span className="h-4.5 w-4.5 rounded-full bg-primary/20 text-primary flex items-center justify-center font-mono text-[10px]">2</span>
Endpunkt auf Box-Gateway setzen
</div>
<p className="pl-6">Gehe in den Bereich Einstellungen Provider, deaktiviere die Cloud-Voreinstellungen und trage deinen lokalen Server ein:</p>
<div className="pl-6 pt-1">
<div className="p-3 bg-background/25 rounded-xl border border-border/30 font-mono text-[10px] space-y-1 text-foreground">
<div><span className="text-muted-foreground/60">Base URL:</span> http://192.168.178.151:9001/v1</div>
<div><span className="text-muted-foreground/60">Model:</span> auto</div>
</div>
</div>
</div>
<div className="space-y-1">
<div className="font-semibold text-foreground flex items-center gap-1.5">
<span className="h-4.5 w-4.5 rounded-full bg-primary/20 text-primary flex items-center justify-center font-mono text-[10px]">3</span>
Erster Vibe-Coding Test
</div>
<p className="pl-6">Starte eine neue Session und teste die Verbindung mit einem einfachen Prompt, z. B. *"Erstelle ein einfaches Skript, das die Fibonaccizahlen berechnet"*. Das Box-Gateway tauscht das Modell im Hintergrund vollautomatisch aus.</p>
</div>
</div>
</div>
)}
</div>
</div>
{/* Diagnostic Tips Card */}
<div className="rounded-2xl border border-border/60 bg-card/45 backdrop-blur-md p-5 space-y-3 shadow-lg shadow-black/10">
<div className="flex items-center gap-2">
<Terminal className="h-4.5 w-4.5 text-primary" />
<h3 className="text-xs font-bold uppercase tracking-wider text-foreground">Was tun, wenn das Coden hakt?</h3>
</div>
<ul className="text-[11px] text-muted-foreground space-y-2 list-disc pl-4 leading-relaxed">
<li><strong>Keine Verbindung?</strong> Überprüfe im Live-Verbindungsprüfer oben, ob die Box-IP erreichbar ist. Stelle sicher, dass dein lokaler PC im selben WLAN/LAN-Netzwerk wie die Box eingeloggt ist.</li>
<li><strong>Modell antwortet nicht?</strong> Schaue unter <strong>Diagnose</strong>, ob der Dienst `llama-swap` aktiv (grün) ist. Wenn nicht, klicke daneben auf <strong>Restart</strong>.</li>
<li><strong>Hermes Agent reagiert merkwürdig?</strong> Starte in der Hermes WebUI einfach eine frische Session (neuen Chat). Ältere Chats sammeln Kontext-Müll an.</li>
</ul>
</div>
</div>
)
}