Something went wrong. Try again.
small gleam coding and persistent agent daemon with a detachable cli and a canvas ui forked from okami.mom/albedo
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105<script lang="ts"> import type { NodeProps } from '@xyflow/svelte'; import type { PtyWindow } from '../board.svelte'; import { place } from '../format'; import { deleteTerminal, type TerminalReady } from '../terminals.svelte'; import PtyView from '../views/PtyView.svelte'; import WindowFrame from './WindowFrame.svelte';
let { id, data, selected }: NodeProps<PtyWindow> = $props();
let ready = $state<TerminalReady | null>(null); let exitCode = $state<number | null>(null); let view = $state<PtyView>();
const cwd = $derived(ready?.cwd ?? data.cwd ?? ''); const shell = $derived(ready?.shell ?? 'sh'); const running = $derived(ready ? ready.state === 'running' : true); const title = $derived(data.title ? `terminal · ${data.title}` : cwd ? `terminal · ${place(cwd)}` : `terminal · ${shell}`);
$effect(() => { return () => { // Clean up backend terminal when window is removed deleteTerminal(data.terminalId); }; });</script>
<WindowFrame {id} selected={!!selected} {title} minWidth={420} minHeight={260}> {#snippet meta()} {#if cwd} <span class="place" title={cwd}><span class="place-text">{place(cwd)}</span></span> {/if} <span class="status-badge" class:running class:exited={!running} title={running ? `${shell} running` : `exited with code ${exitCode ?? 0}`}> <span class="dot"></span> <span class="label">{running ? shell : `exit ${exitCode ?? 0}`}</span> </span> {/snippet}
<PtyView bind:this={view} terminalId={data.terminalId} cwd={data.cwd} sessionId={data.sessionId} onready={(found) => (ready = found)} onexit={(code) => (exitCode = code)} /></WindowFrame>
<style> .place { display: inline-flex; flex: 0 1 auto; min-width: 40px; max-width: 160px; align-items: center; height: 22px; padding: 0 8px; color: var(--muted); font-size: calc(11px * var(--ui-scale)); line-height: 1; background: var(--well); border-radius: 6px; }
.place-text { min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.status-badge { display: inline-flex; align-items: center; gap: 5px; height: 22px; padding: 0 7px; font-family: var(--mono); font-size: calc(10.5px * var(--ui-scale)); color: var(--muted); background: var(--well); border-radius: 6px; }
.status-badge .dot { width: 6px; height: 6px; border-radius: 50%; background: var(--muted); }
.status-badge.running .dot { background: var(--added); box-shadow: 0 0 5px color-mix(in oklab, var(--added) 70%, transparent); }
.status-badge.exited { color: var(--danger); }
.status-badge.exited .dot { background: var(--danger); }</style>