claude-desktop/src/lib/components/ActivityPanel.svelte
Eddy 2822796c7a Initial Commit: Claude Desktop Grundgerüst
- Tauri 2.0 + SvelteKit Projekt aufgesetzt
- Basis-UI mit 3 Panels (Chat, Aktivität, Präsentation)
- Roter STOPP-Button Footer
- Autonomes Gedächtnis-System (memory.rs)
- Änderungs-Log / Audit Trail (audit.rs)
- Multi-Agent-View Komponenten
- NixOS Entwicklungsumgebung (shell.nix)

Phase 1 abgeschlossen, Claude SDK Integration folgt.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-04-13 12:16:20 +02:00

166 lines
3.6 KiB
Svelte

<script lang="ts">
import { recentToolCalls, agents } from '$lib/stores/app';
// Tool-Icons
const toolIcons: Record<string, string> = {
Read: '📖',
Write: '✏️',
Edit: '✏️',
Bash: '🖥️',
Grep: '🔍',
Glob: '📂',
Task: '🤖',
WebFetch: '🌐',
WebSearch: '🔎'
};
function getToolIcon(tool: string): string {
return toolIcons[tool] || '🔧';
}
function formatTime(date: Date): string {
return date.toLocaleTimeString('de-DE', {
hour: '2-digit',
minute: '2-digit',
second: '2-digit'
});
}
function getAgentName(agentId: string): string {
const agent = $agents.find((a) => a.id === agentId);
if (!agent) return 'Main';
return agent.type.charAt(0).toUpperCase() + agent.type.slice(1);
}
function formatArgs(args: Record<string, unknown>): string {
// Versuche sinnvolle Info zu extrahieren
if (args.file_path) return String(args.file_path).split('/').pop() || '';
if (args.pattern) return `"${args.pattern}"`;
if (args.command) {
const cmd = String(args.command);
return cmd.length > 30 ? cmd.substring(0, 30) + '...' : cmd;
}
if (args.url) return String(args.url);
return '';
}
</script>
<div class="activity-panel">
{#if $recentToolCalls.length === 0}
<div class="empty-state">
<p>Noch keine Aktivität.</p>
<p class="hint">Tool-Aufrufe erscheinen hier in Echtzeit.</p>
</div>
{:else}
<div class="activity-list">
{#each $recentToolCalls as call}
<div class="activity-item" class:running={call.status === 'running'} class:failed={call.status === 'failed'}>
<span class="activity-time">{formatTime(call.startedAt)}</span>
<span class="activity-icon">{getToolIcon(call.tool)}</span>
<span class="activity-agent">{getAgentName(call.agentId)}</span>
<span class="activity-tool">{call.tool}</span>
<span class="activity-args">{formatArgs(call.args)}</span>
<span class="activity-status">
{#if call.status === 'running'}
<span class="status-dot running"></span>
{:else if call.status === 'completed'}
{:else}
{/if}
</span>
</div>
{/each}
</div>
{/if}
</div>
<style>
.activity-panel {
height: 100%;
overflow: hidden;
display: flex;
flex-direction: column;
}
.empty-state {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100%;
color: var(--text-secondary);
text-align: center;
padding: var(--spacing-md);
}
.empty-state .hint {
font-size: 0.75rem;
margin-top: var(--spacing-sm);
}
.activity-list {
flex: 1;
overflow-y: auto;
font-family: var(--font-mono);
font-size: 0.75rem;
}
.activity-item {
display: grid;
grid-template-columns: 70px 24px 60px 80px 1fr 24px;
gap: var(--spacing-xs);
align-items: center;
padding: var(--spacing-xs) var(--spacing-sm);
border-bottom: 1px solid var(--bg-secondary);
transition: background 0.2s ease;
}
.activity-item:hover {
background: var(--bg-secondary);
}
.activity-item.running {
background: rgba(74, 222, 128, 0.1);
}
.activity-item.failed {
background: rgba(239, 68, 68, 0.1);
}
.activity-time {
color: var(--text-secondary);
}
.activity-icon {
text-align: center;
}
.activity-agent {
color: var(--accent);
}
.activity-tool {
font-weight: 600;
}
.activity-args {
color: var(--text-secondary);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.activity-status {
text-align: center;
}
.status-dot {
display: inline-block;
width: 8px;
height: 8px;
border-radius: 50%;
background: var(--success);
animation: pulse 1s ease-in-out infinite;
}
</style>