- context.rs: Drei-Schichten-Gedächtnis (Sticky, Projekt, Wissens-Hints) - StickyContext für kritische Infos (User, Credentials, Regeln) - ProjectContext für Entscheidungen und TODOs nach Compacting - DB-Schema: sticky_context, compacting_archive, context_failures - ContextPanel.svelte: UI zur Verwaltung des Sticky Context - Neuer Tab "Context" im rechten Panel Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
190 lines
4.6 KiB
Svelte
190 lines
4.6 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';
|
|
|
|
let activeMiddleTab = 'activity';
|
|
let activeRightTab = 'agents';
|
|
|
|
const middleTabs = [
|
|
{ id: 'activity', label: 'Aktivität', icon: '📋' },
|
|
{ id: 'monitor', label: 'Monitor', icon: '📊' },
|
|
{ id: 'knowledge', label: 'Wissen', icon: '📚' },
|
|
{ id: 'memory', label: 'Gedächtnis', icon: '🧠' },
|
|
{ id: 'audit', label: 'Historie', icon: '📝' },
|
|
];
|
|
|
|
const rightTabs = [
|
|
{ id: 'agents', label: 'Agents', icon: '🤖' },
|
|
{ id: 'context', label: 'Context', 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 === 'knowledge'}
|
|
<KnowledgePanel />
|
|
{:else if activeMiddleTab === 'memory'}
|
|
<MemoryPanel />
|
|
{:else if activeMiddleTab === 'audit'}
|
|
<AuditLog />
|
|
{/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 === '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>
|