<script lang="ts">
import { onMount } from 'svelte';
import { layoutStore } from '$lib/stores/layout.svelte.js';
import { appStore } from '$lib/store.svelte.js';
import SwarmGraph from '$lib/components/swarm/SwarmGraph.svelte';
import AgentDetailPanel from '$lib/components/swarm/AgentDetailPanel.svelte';
let { isMobile = false }: { isMobile?: boolean } = $props();
let mcpServers = $state<string[]>([]);
onMount(() => {
mcpServers = deriveMcpServers();
});
// Watch for tool updates
$effect(() => {
mcpServers = deriveMcpServers();
});
function deriveMcpServers(): string[] {
const seen = new Set<string>();
for (const tool of appStore.tools) {
if (tool.name.startsWith('mcp__')) {
const server = tool.name.slice(5).split('__')[0];
if (server) seen.add(server);
}
}
return [...seen].sort();
}
function formatTokens(n: number): string {
if (n >= 1000) return `${(n / 1000).toFixed(1)}k`;
return String(n);
}
function contextPercent(): string {
const s = appStore.status;
if (!s || !s.context_tokens) return '0%';
return Math.round((s.context_tokens / 128000) * 100) + '%';
}
function contextTokens(): string {
const s = appStore.status;
if (!s || !s.context_tokens) return '0';
return formatTokens(s.context_tokens);
}
function lspServers(): { name: string; available: boolean }[] {
// TODO: Derive from appStore.tools when LSP tools are available
return [];
}
</script>
{#if layoutStore.rightSidebarOpen}
<aside class="right-sidebar" class:mobile={isMobile}>
{#if isMobile}
<div class="mobile-header">
<span class="mobile-title">Panels</span>
<button class="close-btn" onclick={() => layoutStore.rightSidebarOpen = false} aria-label="Close panels">x</button>
</div>
{/if}
<div class="sections">
<!-- Swarm Graph -->
{#if appStore.showSwarmGraph}
<div class="section swarm-section">
<SwarmGraph />
<AgentDetailPanel />
</div>
{/if}
<!-- Context -->
<div class="section">
<div class="section-header">Context</div>
<div class="section-body">
<span class="item dim">{contextTokens()} tokens</span>
<span class="item dim">{contextPercent()} used</span>
</div>
</div>
<!-- MCP -->
<div class="section">
<div class="section-header">MCP</div>
<div class="section-body">
{#each mcpServers as server}
<span class="item">
<span class="dot cyan">•</span> {server}
</span>
{:else}
<span class="item dim">No servers</span>
{/each}
</div>
</div>
<!-- LSP -->
<div class="section">
<div class="section-header">LSP</div>
<div class="section-body">
{#each lspServers() as server}
<span class="item" class:dim={!server.available}>
<span class="dot magenta">▪</span> {server.name}
</span>
{:else}
<span class="item dim">None detected</span>
{/each}
</div>
</div>
<!-- Changed Files -->
<div class="section">
<div class="section-header">Changed Files</div>
<div class="section-body">
{#each appStore.modifiedFiles as file}
<span class="item"><span class="dot green">•</span> {file.split('/').pop()}</span>
{:else}
<span class="item dim">No changes yet</span>
{/each}
</div>
</div>
</div>
</aside>
{/if}
<style>
.right-sidebar {
width: var(--right-w, 240px);
flex-shrink: 0;
background: var(--bg-surface);
border-left: 1px solid var(--border);
display: flex;
flex-direction: column;
overflow: hidden;
font-family: var(--font-mono);
}
.right-sidebar.mobile {
position: fixed;
top: 0;
right: 0;
bottom: 0;
z-index: 100;
width: 280px;
box-shadow: -4px 0 24px rgba(0, 0, 0, 0.4);
}
.mobile-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0.375rem 0.5rem;
border-bottom: 1px solid var(--border);
flex-shrink: 0;
}
.mobile-title {
font-size: 0.8125rem;
font-weight: 700;
color: var(--fg);
}
.close-btn {
all: unset;
cursor: pointer;
color: var(--fg-dim);
padding: 0.125rem 0.25rem;
}
.close-btn:hover {
color: var(--fg);
}
.sections {
flex: 1;
overflow-y: auto;
padding: 0.25rem 0;
}
.section {
padding: 0.375rem 0.5rem;
}
.section-header {
font-size: 0.75rem;
font-weight: 700;
color: var(--fg-bright);
text-transform: uppercase;
letter-spacing: 0.04em;
margin-bottom: 0.25rem;
}
.section-body {
display: flex;
flex-direction: column;
gap: 0.0625rem;
}
.item {
font-size: 0.8125rem;
color: var(--fg);
line-height: 1.4;
padding-left: 0.25rem;
}
.item.dim {
color: var(--fg-dim);
}
.dot {
margin-right: 0.25rem;
}
.dot.cyan {
color: var(--cyan);
}
.dot.magenta {
color: var(--magenta);
}
.dot.green {
color: var(--green);
}
.swarm-section {
padding: 0.375rem !important;
}
</style>