claude-desktop/src/routes/+page.svelte
Eddy 120715982b Phasen 12-15: Hooks, VSCodium-Bridge, Programm-Steuerung, Schulungsmodus
Phase 12 Hook-System (hooks.rs + HooksPanel):
- HookManager mit Event-Registry + Ausfuehrungs-Log
- 5 Built-in Hooks (SessionStart, PreToolUse, PostToolUse,
  BeforeCompacting, AfterCompacting)
- Tauri-Commands: list_hooks, set_hook_enabled, get_hook_executions, fire_hook
- HooksPanel.svelte mit Live-Ausfuehrungs-Log

Phase 13 VSCodium-Integration:
- vscode-extension/: WebSocket-Server auf Port 7890
  (Commands: openFile, goToLine, formatDocument, findInFiles,
   openTerminal, getStatus, executeCommand, ping)
- src-tauri/src/ide.rs: WebSocket-Client via tokio-tungstenite
- IdePanel.svelte: Status, Port-Konfig, Ping-Test, Live-Anzeige aktive Datei

Phase 14 Programm-Steuerung (programs.rs + ProgramsPanel):
- D-Bus: dbus_call + dbus_list_services
- Xvfb: start/stop/status + screenshot (scrot)
- Playwright-Info (MCP-Verweis)
- ProgramsPanel mit 4 Sektionen (VSCodium, Playwright, D-Bus, Xvfb)

Phase 15 Schulungsmodus (teaching.rs + presentation/+page.svelte):
- Separates Tauri-Webview-Fenster
- MermaidDiagram.svelte (dynamic import mermaid)
- AnimatedCode.svelte mit WPM-Steuerung
- Tauri-Commands: presentation_open/close/send_slide/clear
- 🎓-Button in der Titelbar
- Capabilities um core:webview:allow-create-webview-window erweitert

Deps:
- Cargo: +tokio-tungstenite 0.23, +futures-util 0.3
- npm: +mermaid ^11.4.0 (npm install erforderlich)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 19:10:41 +02:00

202 lines
5.1 KiB
Svelte

<script lang="ts">
import { PaneGroup, Pane, PaneResizer } from 'paneforge';
import SessionList from '$lib/components/SessionList.svelte';
import ChatPanel from '$lib/components/ChatPanel.svelte';
import ActivityPanel from '$lib/components/ActivityPanel.svelte';
import AgentView from '$lib/components/AgentView.svelte';
import MemoryPanel from '$lib/components/MemoryPanel.svelte';
import KnowledgePanel from '$lib/components/KnowledgePanel.svelte';
import ContextPanel from '$lib/components/ContextPanel.svelte';
import AuditLog from '$lib/components/AuditLog.svelte';
import GuardRailsPanel from '$lib/components/GuardRailsPanel.svelte';
import SettingsPanel from '$lib/components/SettingsPanel.svelte';
import MonitorPanel from '$lib/components/MonitorPanel.svelte';
import PerformancePanel from '$lib/components/PerformancePanel.svelte';
import HooksPanel from '$lib/components/HooksPanel.svelte';
import ProgramsPanel from '$lib/components/ProgramsPanel.svelte';
let activeMiddleTab = 'activity';
let activeRightTab = 'agents';
const middleTabs = [
{ id: 'activity', label: 'Aktivität', icon: '📋' },
{ id: 'monitor', label: 'Monitor', icon: '📊' },
{ id: 'perf', label: 'Kosten', icon: '📈' },
{ id: 'knowledge', label: 'Wissen', icon: '📚' },
{ id: 'memory', label: 'Gedächtnis', icon: '🧠' },
{ id: 'audit', label: 'Historie', icon: '📝' },
{ id: 'programs', label: 'Programme', icon: '🖥️' },
];
const rightTabs = [
{ id: 'agents', label: 'Agents', icon: '🤖' },
{ id: 'context', label: 'Context', icon: '📌' },
{ id: 'hooks', label: 'Hooks', icon: '🪝' },
{ id: 'guards', label: 'Guard-Rails', icon: '🛡️' },
{ id: 'settings', label: 'Settings', icon: '⚙️' },
];
</script>
<PaneGroup direction="horizontal" autoSaveId="claude-desktop-panels" class="pane-group">
<!-- Sessions -->
<Pane defaultSize={15} minSize={8} maxSize={30} class="panel">
<SessionList />
</Pane>
<PaneResizer class="resizer">
<div class="resizer-line"></div>
</PaneResizer>
<!-- Chat -->
<Pane defaultSize={35} minSize={15} class="panel">
<ChatPanel />
</Pane>
<PaneResizer class="resizer">
<div class="resizer-line"></div>
</PaneResizer>
<!-- Aktivität / Memory / Audit -->
<Pane defaultSize={25} minSize={10} class="panel">
<div class="panel-tabs">
{#each middleTabs as tab}
<button
class="tab"
class:active={activeMiddleTab === tab.id}
on:click={() => activeMiddleTab = tab.id}
>
{tab.icon} {tab.label}
</button>
{/each}
</div>
<div class="panel-content">
{#if activeMiddleTab === 'activity'}
<ActivityPanel />
{:else if activeMiddleTab === 'monitor'}
<MonitorPanel />
{:else if activeMiddleTab === 'perf'}
<PerformancePanel />
{:else if activeMiddleTab === 'knowledge'}
<KnowledgePanel />
{:else if activeMiddleTab === 'memory'}
<MemoryPanel />
{:else if activeMiddleTab === 'audit'}
<AuditLog />
{:else if activeMiddleTab === 'programs'}
<ProgramsPanel />
{/if}
</div>
</Pane>
<PaneResizer class="resizer">
<div class="resizer-line"></div>
</PaneResizer>
<!-- Agents / Guard-Rails -->
<Pane defaultSize={25} minSize={10} class="panel">
<div class="panel-tabs">
{#each rightTabs as tab}
<button
class="tab"
class:active={activeRightTab === tab.id}
on:click={() => activeRightTab = tab.id}
>
{tab.icon} {tab.label}
</button>
{/each}
</div>
<div class="panel-content">
{#if activeRightTab === 'agents'}
<AgentView />
{:else if activeRightTab === 'context'}
<ContextPanel />
{:else if activeRightTab === 'hooks'}
<HooksPanel />
{:else if activeRightTab === 'guards'}
<GuardRailsPanel />
{:else if activeRightTab === 'settings'}
<SettingsPanel />
{/if}
</div>
</Pane>
</PaneGroup>
<style>
/* PaneForge Container */
:global(.pane-group) {
height: 100%;
}
:global(.panel) {
display: flex;
flex-direction: column;
background: var(--bg-primary);
overflow: hidden;
}
/* Resizer Handle */
:global(.resizer) {
width: 8px;
background: var(--border);
display: flex;
align-items: center;
justify-content: center;
cursor: col-resize;
transition: background 0.15s ease;
}
:global(.resizer:hover),
:global(.resizer[data-state="drag"]) {
background: var(--accent);
}
.resizer-line {
width: 2px;
height: 24px;
border-radius: 1px;
background: var(--text-secondary);
opacity: 0;
transition: opacity 0.15s;
}
:global(.resizer:hover) .resizer-line,
:global(.resizer[data-state="drag"]) .resizer-line {
opacity: 0.5;
}
/* Tabs */
.panel-tabs {
display: flex;
background: var(--bg-secondary);
border-bottom: 1px solid var(--border);
flex-shrink: 0;
}
.tab {
flex: 1;
padding: var(--spacing-sm);
font-size: 0.75rem;
color: var(--text-secondary);
background: transparent;
border: none;
border-bottom: 2px solid transparent;
cursor: pointer;
transition: all 0.15s ease;
white-space: nowrap;
}
.tab:hover {
color: var(--text-primary);
background: var(--bg-hover);
}
.tab.active {
color: var(--accent);
border-bottom-color: var(--accent);
}
.panel-content {
flex: 1;
overflow: auto;
}
</style>