feat(backends,api,ui): process trees with cpu and stderr per session, interrupt, close and kill from the system page
This commit is contained in:
1 parent
9875f08016
commit
712c24de4e
12 files changed
+996
-127
No files matched your search
@@ -0,0 +1,150 @@
|
||||
<script lang="ts">
|
||||
import { onMount, untrack } from "svelte";
|
||||
import { base } from "$app/paths";
|
||||
import type { ApiClient } from "$lib/api/client";
|
||||
import type { ProcessRow, SessionRow } from "$lib/api/types";
|
||||
import { Button } from "$lib/components/ui/button";
|
||||
import { shortId } from "$lib/format";
|
||||
import { ConversationFeed } from "$lib/panel/conversation.svelte";
|
||||
import TurnCard from "$lib/panel/turn-card.svelte";
|
||||
import ProcessTable from "./process-table.svelte";
|
||||
|
||||
let {
|
||||
client,
|
||||
row,
|
||||
busy,
|
||||
note,
|
||||
onInterrupt,
|
||||
onClose,
|
||||
onKill,
|
||||
}: {
|
||||
client: ApiClient;
|
||||
row: SessionRow;
|
||||
busy: boolean;
|
||||
note: string;
|
||||
onInterrupt: (row: SessionRow) => void;
|
||||
onClose: (row: SessionRow) => void;
|
||||
onKill: (process: ProcessRow) => void;
|
||||
} = $props();
|
||||
|
||||
const TICK_MS = 1000;
|
||||
const feed = new ConversationFeed(
|
||||
() => client,
|
||||
untrack(() => row.key)
|
||||
);
|
||||
let stderr = $state<string[] | null>(null);
|
||||
let now = $state(Date.now());
|
||||
|
||||
const turn = $derived(feed.model.running);
|
||||
|
||||
onMount(() => {
|
||||
feed.start();
|
||||
const timer = setInterval(() => {
|
||||
now = Date.now();
|
||||
}, TICK_MS);
|
||||
return () => {
|
||||
feed.stop();
|
||||
clearInterval(timer);
|
||||
};
|
||||
});
|
||||
|
||||
$effect(() => {
|
||||
const { key, idle_seconds: polled } = row;
|
||||
if (polled >= 0) {
|
||||
client
|
||||
.sessionStderr(key)
|
||||
.then((tail) => {
|
||||
stderr = tail.lines;
|
||||
})
|
||||
.catch(() => undefined);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<div class="flex flex-col gap-4 px-3 pt-2 pb-4">
|
||||
<div class="flex flex-wrap items-center gap-x-4 gap-y-2">
|
||||
<p class="tabular min-w-0 flex-1 text-muted-foreground text-xs">
|
||||
session
|
||||
{shortId(row.session_id)}
|
||||
{#if row.pid}
|
||||
· pid {row.pid}
|
||||
{/if}
|
||||
{#if row.pending > 0}
|
||||
· {row.pending}
|
||||
buffered
|
||||
{/if}
|
||||
</p>
|
||||
<div class="flex flex-wrap items-center gap-2">
|
||||
{#if note}
|
||||
<span class="text-muted-foreground text-xs" role="status">{note}</span>
|
||||
{/if}
|
||||
{#if !feed.error}
|
||||
<Button
|
||||
class="max-sm:h-10"
|
||||
href="{base}/conversations/{row.key}"
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
>
|
||||
Open thread
|
||||
</Button>
|
||||
{/if}
|
||||
<Button
|
||||
class="max-sm:h-10"
|
||||
disabled={busy || !row.busy}
|
||||
onclick={() => onInterrupt(row)}
|
||||
size="sm"
|
||||
variant="outline"
|
||||
>
|
||||
Interrupt turn
|
||||
</Button>
|
||||
<Button
|
||||
class="max-sm:h-10"
|
||||
disabled={busy}
|
||||
onclick={() => onClose(row)}
|
||||
size="sm"
|
||||
variant="destructive"
|
||||
>
|
||||
Close session
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<section class="flex flex-col gap-1">
|
||||
<h4 class="label-quiet">Now</h4>
|
||||
{#if turn}
|
||||
<TurnCard {now} {turn} />
|
||||
{:else}
|
||||
<p class="text-muted-foreground text-sm">
|
||||
{row.busy
|
||||
? "A turn is running; its events have not reached this page yet."
|
||||
: "Nothing in flight."}
|
||||
</p>
|
||||
{/if}
|
||||
</section>
|
||||
|
||||
<section class="flex flex-col gap-1">
|
||||
<h4 class="label-quiet">Process tree</h4>
|
||||
{#if row.processes.length === 0}
|
||||
<p class="text-muted-foreground text-sm">
|
||||
The process is not visible to the gateway.
|
||||
</p>
|
||||
{:else}
|
||||
<ProcessTable {onKill} rows={row.processes} />
|
||||
{/if}
|
||||
</section>
|
||||
|
||||
<section class="flex flex-col gap-1">
|
||||
<h4 class="label-quiet">stderr</h4>
|
||||
{#if stderr?.length === 0}
|
||||
<p class="text-muted-foreground text-sm">
|
||||
Nothing on stderr since this process started.
|
||||
</p>
|
||||
{:else if stderr}
|
||||
<pre
|
||||
class="max-h-64 overflow-auto whitespace-pre-wrap break-all rounded-md bg-muted/40 p-2 text-xs"
|
||||
>{stderr.join(
|
||||
"\n"
|
||||
)}</pre>
|
||||
{/if}
|
||||
</section>
|
||||
</div>
|
||||
Reference in new issue
Block a user