Intelligence
Artifacts
Browse the repository, read documents, and manage the governance folders. Source, runtime, and infrastructure are read-only.
Repository
repositories/aaf-holdings/hq01/app/sessions/[id]/page.tsx
7.0 KB
import { notFound } from "next/navigation";
import {
Cpu,
FolderGit2,
GitBranch,
Target,
ClipboardList,
Clock,
FileText,
} from "lucide-react";
import { PageHeader } from "@/components/layout/page-header";
import { Card, CardContent } from "@/components/ui/card";
import { Separator } from "@/components/ui/separator";
import { MetaItem } from "@/components/shared/field-list";
import { SessionStatusBadge } from "@/components/sessions/session-status-badge";
import { RuntimeClock } from "@/components/sessions/runtime-clock";
import { StopButton } from "@/components/sessions/stop-button";
import { LogViewer } from "@/components/sessions/log-viewer";
import { AutoRefresh } from "@/components/sessions/auto-refresh";
import { getMetadata, getSession } from "@/lib/sessions/manager";
/**
* Session detail — mission, assignment, working directory, branch, PID, runtime,
* status, and a live read-only log viewer. Server-rendered and kept fresh by
* AutoRefresh (status/runtime) and the LogViewer's own polling (logs).
*/
export const dynamic = "force-dynamic";
export default function SessionDetailPage({
params,
}: {
params: { id: string };
}) {
const session = getSession(params.id);
if (!session) notFound();
const metadata = getMetadata(params.id);
const running = session.status === "running" || session.status === "starting";
return (
<div>
<AutoRefresh intervalMs={5000} />
<PageHeader
eyebrow={session.executive}
title={session.name}
description={metadata?.prompt ?? undefined}
back={{ label: "Sessions", href: "/sessions" }}
actions={
<div className="flex items-center gap-3">
<SessionStatusBadge status={session.status} />
<StopButton id={session.id} running={running} />
</div>
}
/>
<div className="grid grid-cols-1 gap-8 lg:grid-cols-3">
<div className="space-y-6 lg:col-span-2">
<div>
<div className="mb-2 flex items-center gap-2 text-sm font-semibold tracking-tight">
<FileText className="h-4 w-4 text-muted-foreground" />
Logs
</div>
<LogViewer id={session.id} />
</div>
{metadata?.prompt && (
<Card>
<CardContent className="p-6">
<div className="mb-2 text-[11px] font-semibold uppercase tracking-[0.1em] text-muted-foreground">
Assigned Mission
</div>
<p className="whitespace-pre-wrap text-[14px] leading-relaxed text-foreground/90">
{metadata.prompt}
</p>
</CardContent>
</Card>
)}
<Card>
<CardContent className="p-6">
<div className="mb-3 text-[11px] font-semibold uppercase tracking-[0.1em] text-muted-foreground">
Command
</div>
<code className="block overflow-x-auto rounded-md bg-secondary px-3 py-2 font-mono text-[12px] text-foreground">
{session.command} {session.args.join(" ")}
</code>
</CardContent>
</Card>
</div>
<aside className="space-y-6">
<Card>
<CardContent className="space-y-5 p-6">
<MetaItem label="Status">
<SessionStatusBadge status={session.status} />
</MetaItem>
<Separator />
<MetaItem label="Runtime">
<span className="inline-flex items-center gap-1.5">
<Clock className="h-4 w-4 text-muted-foreground" />
<RuntimeClock
startedAt={session.started_at}
endedAt={session.stopped_at}
running={running}
className="tabular-nums"
/>
</span>
</MetaItem>
<Separator />
<MetaItem label="PID">
<span className="inline-flex items-center gap-1.5 font-mono">
<Cpu className="h-4 w-4 text-muted-foreground" />
{session.pid ?? "—"}
</span>
</MetaItem>
<Separator />
<MetaItem label="Mission">
<span className="inline-flex items-center gap-1.5">
<Target className="h-4 w-4 text-muted-foreground" />
{session.mission_id ?? "—"}
</span>
</MetaItem>
<Separator />
<MetaItem label="Assignment">
<span className="inline-flex items-center gap-1.5">
<ClipboardList className="h-4 w-4 text-muted-foreground" />
{session.assignment_id ?? "—"}
</span>
</MetaItem>
<Separator />
<MetaItem label="Branch">
<span className="inline-flex items-center gap-1.5 font-mono text-[13px]">
<GitBranch className="h-4 w-4 text-muted-foreground" />
{session.branch ?? "—"}
</span>
</MetaItem>
</CardContent>
</Card>
<Card>
<CardContent className="space-y-4 p-6">
<div>
<div className="mb-1 flex items-center gap-1.5 text-[11px] font-semibold uppercase tracking-[0.1em] text-muted-foreground">
<FolderGit2 className="h-3.5 w-3.5" />
Working Directory
</div>
<code className="block break-all font-mono text-[12px] text-foreground/90">
{session.working_directory}
</code>
</div>
<Separator />
<div>
<div className="mb-1 text-[11px] font-semibold uppercase tracking-[0.1em] text-muted-foreground">
Runtime Files
</div>
<code className="block break-all font-mono text-[11px] text-muted-foreground">
{session.log_path}
</code>
<code className="mt-1 block break-all font-mono text-[11px] text-muted-foreground">
{session.stderr_path}
</code>
</div>
{session.started_at && (
<>
<Separator />
<div className="text-[11px] text-muted-foreground">
Started{" "}
<span className="font-medium text-foreground/80">
{session.started_at}
</span>
{session.last_activity && (
<>
{" · last activity "}
<span className="font-medium text-foreground/80">
{session.last_activity}
</span>
</>
)}
</div>
</>
)}
</CardContent>
</Card>
</aside>
</div>
</div>
);
}
root · /srv/aaf