87 lines
2.3 KiB
Svelte
87 lines
2.3 KiB
Svelte
<script lang="ts">
|
|
import { fmtTokens } from "$lib/format";
|
|
import { gateway } from "$lib/gateway.svelte";
|
|
import { ui } from "$lib/ui.svelte";
|
|
import { cn } from "$lib/utils";
|
|
import { now } from "./now.svelte";
|
|
|
|
let { class: className = "" }: { class?: string } = $props();
|
|
|
|
const running = $derived(now.running.length);
|
|
const waiting = $derived(now.waiting.length);
|
|
const worst = $derived.by(() => {
|
|
const windows = gateway.limits?.windows ?? [];
|
|
let top: number | null = null;
|
|
for (const w of windows) {
|
|
if (w.utilization !== null && w.utilization !== undefined) {
|
|
top = Math.max(top ?? 0, w.utilization);
|
|
}
|
|
}
|
|
return top;
|
|
});
|
|
const live = $derived(gateway.live.state);
|
|
const dot = $derived.by(() => {
|
|
if (live === "failed") {
|
|
return "bg-destructive";
|
|
}
|
|
if (live !== "open") {
|
|
return "bg-warn";
|
|
}
|
|
return running > 0 ? "bg-signal animate-pulse-dot" : "bg-ok";
|
|
});
|
|
const headline = $derived.by(() => {
|
|
if (live === "failed") {
|
|
return "offline";
|
|
}
|
|
if (live !== "open") {
|
|
return "connecting";
|
|
}
|
|
if (running === 0) {
|
|
return "idle";
|
|
}
|
|
return running === 1 ? "1 in motion" : `${running} in motion`;
|
|
});
|
|
</script>
|
|
|
|
<button
|
|
aria-expanded={ui.island}
|
|
aria-haspopup="dialog"
|
|
aria-label="What is happening now"
|
|
class={cn("island", className)}
|
|
onclick={() => ui.toggleIsland()}
|
|
type="button"
|
|
>
|
|
<span class={cn("size-2 shrink-0 rounded-full", dot)}></span>
|
|
<span class="font-medium">{headline}</span>
|
|
{#if waiting > 0}
|
|
<span class="island-sep"></span>
|
|
<span class="font-medium text-attention-foreground">
|
|
{waiting === 1 ? "1 question" : `${waiting} questions`}
|
|
</span>
|
|
{/if}
|
|
{#if now.contextTokens > 0}
|
|
<span class="island-sep hidden sm:block"></span>
|
|
<span
|
|
class="tabular hidden text-muted-foreground sm:inline"
|
|
title="master context"
|
|
>
|
|
{fmtTokens(now.contextTokens)}
|
|
</span>
|
|
{/if}
|
|
{#if worst !== null}
|
|
<span class="island-sep hidden sm:block"></span>
|
|
<span
|
|
class="tabular hidden text-muted-foreground sm:inline"
|
|
title="highest quota window"
|
|
>
|
|
{Math.round(worst * 100)}%
|
|
</span>
|
|
{/if}
|
|
<kbd
|
|
class="ml-1 hidden rounded border px-1 font-sans text-[10px] text-muted-foreground md:inline"
|
|
title="open the board"
|
|
>
|
|
⌘K
|
|
</kbd>
|
|
</button>
|