<script lang="ts">
// The record of working: the machine's agent sessions, starting at the ones
// that ran in this worktree and widening to its project or to all of them,
// with plan documents — session by-products — as a collapsible section
// beneath them rather than a container of their own.
import SessionList from "./SessionList.svelte";
import PlansSidebar from "./panels/PlansSidebar.svelte";
import { workbench } from "../../stores/workbench.svelte.js";
import { sync } from "../../stores/sync.svelte.js";
import SidebarHeader from "./SidebarHeader.svelte";
import AppIcon from "../layout/AppIcon.svelte";
let plansOpen = $state(false);
/** The stream-backed sync expressed as the promise the shared header owns. */
function refreshSessions(): Promise<void> {
return new Promise<void>((resolve, reject) => {
const started = sync.triggerSync(resolve, reject);
// The header is already disabled while `sync.syncing`; this only covers
// a sync started between the click and this callback running.
if (!started) resolve();
});
}
</script>
<div class="sessions-panel">
<!--
The same bar every other panel wears. Sessions had none: its one action —
re-reading the transcripts — sat inside the list's filter row, which is
the only place in the workbench that put a refresh anywhere but the top.
-->
<SidebarHeader
title="Sessions"
onrefresh={refreshSessions}
refreshing={sync.syncing}
refreshTitle="Sync sessions (r)"
>
{#snippet actions()}
<!--
The statistics open in the content view. They were on the welcome page —
four charts, a heatmap and a filter bar — which made the first thing
anyone saw a study rather than a glance. They belong to sessions, so the
way in is here, in the bar every panel puts its actions in.
-->
<button
class="panel-action-btn"
title="Session statistics — activity, heatmaps, top sessions"
aria-label="Session statistics"
onclick={() => workbench.openSessionStatistics()}
>
<AppIcon name="chart" size={14} />
</button>
{/snippet}
</SidebarHeader>
<div class="sessions-slot">
<SessionList />
</div>
<div class="plans-section" class:open={plansOpen}>
<button
class="plans-toggle"
onclick={() => (plansOpen = !plansOpen)}
aria-expanded={plansOpen}
>
<span class="plans-caret"><AppIcon name={plansOpen ? "chevron-down" : "chevron-right"} size={11} /></span>
Plans
</button>
{#if plansOpen}
<div class="plans-body">
<PlansSidebar />
</div>
{/if}
</div>
</div>
<style>
.sessions-panel {
display: flex;
flex-direction: column;
min-height: 0;
height: 100%;
}
.sessions-slot {
flex: 1;
min-height: 0;
display: flex;
flex-direction: column;
}
.plans-section {
flex-shrink: 0;
border-top: 1px solid var(--vscode-panel-border);
}
.plans-section.open {
max-height: 40%;
display: flex;
flex-direction: column;
}
.plans-toggle {
display: flex;
align-items: center;
gap: var(--wb-spacing-6);
width: 100%;
text-align: left;
padding: var(--wb-spacing-6) var(--wb-spacing-12);
font-size: var(--wb-font-size-11);
text-transform: uppercase;
letter-spacing: 0.08em;
opacity: 0.7;
color: inherit;
background: none;
border: none;
cursor: pointer;
}
.plans-toggle:hover {
opacity: 1;
}
.plans-caret {
font-size: var(--wb-font-size-9);
}
.plans-body {
min-height: 0;
overflow-y: auto;
}
</style>