feat(electrobun): fixes + 7 new features (terminal input, file browser, memory, toasts)

Fixes:
- Terminal accepts keyboard input (echo mode with prompt)
- Terminal drawer collapses properly (display:none preserves xterm state)

Features:
- 6 project tabs: Model | Docs | Context | Files | SSH | Memory
- FileBrowser.svelte: recursive tree with expand/collapse + file preview
- MemoryTab.svelte: memory cards with trust badges (human/agent/auto)
- Subagent tree in AgentPane (demo: search-agent, test-runner)
- Drag resize handle between agent pane and terminal
- Theme dropdown in Settings (4 Catppuccin flavors)
- ToastContainer.svelte: auto-dismiss notifications
This commit is contained in:
Hibryda 2026-03-20 02:07:18 +01:00
parent b11a856b72
commit 4ae558af17
14 changed files with 1168 additions and 196 deletions

View file

@ -0,0 +1,208 @@
<script lang="ts">
type TrustLevel = 'human' | 'agent' | 'auto';
interface MemoryFragment {
id: number;
title: string;
body: string;
tags: string[];
trust: TrustLevel;
updatedAt: string;
}
const MEMORIES: MemoryFragment[] = [
{
id: 1,
title: 'Agent Orchestrator — Tech Stack',
body: 'Tauri 2.x + Svelte 5 frontend. Rust backend with rusqlite (WAL mode). Agent sessions via @anthropic-ai/claude-agent-sdk query(). Sidecar uses stdio NDJSON.',
tags: ['agor', 'tech-stack', 'architecture'],
trust: 'human',
updatedAt: '2026-03-20',
},
{
id: 2,
title: 'btmsg SQLite conventions',
body: 'All queries use named column access (row.get("column_name")) — never positional indices. Rust structs use #[serde(rename_all = "camelCase")].',
tags: ['agor', 'database', 'btmsg'],
trust: 'agent',
updatedAt: '2026-03-19',
},
{
id: 3,
title: 'Wake Scheduler — 3 strategies',
body: 'persistent=resume prompt, on-demand=fresh session, smart=threshold-gated on-demand. 6 wake signals from S-3 hybrid tribunal. Pure scorer in wake-scorer.ts (24 tests).',
tags: ['agor', 'wake-scheduler', 'agents'],
trust: 'agent',
updatedAt: '2026-03-18',
},
{
id: 4,
title: 'Svelte 5 runes file extension rule',
body: 'Store files using Svelte 5 runes ($state, $derived) MUST have .svelte.ts extension. Plain .ts compiles but fails at runtime with "rune_outside_svelte".',
tags: ['agor', 'svelte', 'conventions'],
trust: 'auto',
updatedAt: '2026-03-17',
},
];
const TRUST_LABELS: Record<TrustLevel, string> = {
human: 'Human',
agent: 'Agent',
auto: 'Auto',
};
</script>
<div class="memory-tab">
<div class="memory-header">
<span class="memory-count">{MEMORIES.length} fragments</span>
<span class="memory-hint">via Memora</span>
</div>
<div class="memory-list">
{#each MEMORIES as mem (mem.id)}
<article class="memory-card">
<div class="memory-card-top">
<span class="memory-title">{mem.title}</span>
<span class="trust-badge trust-{mem.trust}" title="Source: {TRUST_LABELS[mem.trust]}">
{TRUST_LABELS[mem.trust]}
</span>
</div>
<p class="memory-body">{mem.body}</p>
<div class="memory-footer">
<div class="memory-tags">
{#each mem.tags as tag}
<span class="tag">{tag}</span>
{/each}
</div>
<span class="memory-date">{mem.updatedAt}</span>
</div>
</article>
{/each}
</div>
</div>
<style>
.memory-tab {
display: flex;
flex-direction: column;
height: 100%;
overflow: hidden;
}
.memory-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0.375rem 0.625rem;
border-bottom: 1px solid var(--ctp-surface0);
background: var(--ctp-mantle);
flex-shrink: 0;
font-size: 0.75rem;
}
.memory-count { color: var(--ctp-text); font-weight: 500; }
.memory-hint { color: var(--ctp-overlay0); font-style: italic; }
.memory-list {
flex: 1;
overflow-y: auto;
padding: 0.375rem;
display: flex;
flex-direction: column;
gap: 0.375rem;
}
.memory-list::-webkit-scrollbar { width: 0.25rem; }
.memory-list::-webkit-scrollbar-track { background: transparent; }
.memory-list::-webkit-scrollbar-thumb { background: var(--ctp-surface1); border-radius: 0.25rem; }
.memory-card {
background: var(--ctp-surface0);
border: 1px solid var(--ctp-surface1);
border-radius: 0.375rem;
padding: 0.5rem 0.625rem;
display: flex;
flex-direction: column;
gap: 0.3rem;
transition: border-color 0.12s;
}
.memory-card:hover { border-color: var(--ctp-surface2); }
.memory-card-top {
display: flex;
align-items: flex-start;
gap: 0.5rem;
}
.memory-title {
flex: 1;
font-size: 0.8125rem;
font-weight: 600;
color: var(--ctp-text);
line-height: 1.3;
}
.trust-badge {
flex-shrink: 0;
padding: 0.1rem 0.35rem;
border-radius: 0.25rem;
font-size: 0.6rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.04em;
}
.trust-human {
background: color-mix(in srgb, var(--ctp-green) 15%, transparent);
color: var(--ctp-green);
}
.trust-agent {
background: color-mix(in srgb, var(--ctp-blue) 15%, transparent);
color: var(--ctp-blue);
}
.trust-auto {
background: color-mix(in srgb, var(--ctp-overlay1) 15%, transparent);
color: var(--ctp-overlay1);
}
.memory-body {
margin: 0;
font-size: 0.75rem;
color: var(--ctp-subtext1);
line-height: 1.45;
font-family: var(--ui-font-family);
}
.memory-footer {
display: flex;
align-items: center;
gap: 0.5rem;
margin-top: 0.1rem;
}
.memory-tags {
display: flex;
flex-wrap: wrap;
gap: 0.25rem;
flex: 1;
}
.tag {
padding: 0.05rem 0.3rem;
background: var(--ctp-surface1);
border-radius: 0.2rem;
font-size: 0.625rem;
color: var(--ctp-overlay1);
font-family: var(--term-font-family);
}
.memory-date {
font-size: 0.625rem;
color: var(--ctp-overlay0);
white-space: nowrap;
flex-shrink: 0;
}
</style>