feat(status-ui): add compact session status strip

This commit is contained in:
2026-08-25 18:32:33 +02:00
parent 166b065ad4
commit 612b146fd6
5 changed files with 332 additions and 105 deletions
+27 -44
View File
@@ -58,6 +58,10 @@ function requestedCommand(command: string, args: Record<string, unknown>) {
: command;
}
function sessionStateLabel(state?: string) {
return !state || state === "idle" ? "Pi ready" : state;
}
function commandProgress(command: string) {
if (command === "restart") return "Restarting Pi and restoring the session…";
if (command === "renew_session")
@@ -563,6 +567,19 @@ export default function App() {
isSubmitting ||
selected?.progress.phase === "working" ||
selected?.progress.phase === "recovering";
const sessionStatusLabel =
state.newSessionLaunch?.phase === "starting"
? "Starting"
: isRenewing
? "Renewing"
: isRestarting
? "Restarting"
: isWorking
? "Working"
: sessionStateLabel(selected?.summary.state);
const sessionStatusPhase = isWorking
? ("working" as const)
: (selected?.progress.phase ?? "idle");
const isStartingSession =
state.newSessionLaunch?.phase === "starting" ||
activeOperations.some((entry) => entry.kind === "creating");
@@ -600,50 +617,9 @@ export default function App() {
void getCurrentWindow().startDragging();
}}
>
<div>
<div className="workspace-heading">
<span className="brand">PI</span>
<h1>{selected?.summary.label ?? "Pi workspace"}</h1>
{selected && (
<span
className={`state-pill ${isWorking ? "working" : selected.progress.phase}`}
>
{isWorking && <span className="working-pulse" aria-hidden="true" />}
{state.newSessionLaunch?.phase === "starting"
? "Starting"
: isRenewing
? "Renewing"
: isRestarting
? "Restarting"
: isWorking
? "Working"
: selected.summary.state}
</span>
)}
</div>
<div className="status-row">
{isWorking && (
<span className="working-banner" role="status">
<span className="working-pulse" aria-hidden="true" />{" "}
{state.newSessionLaunch?.phase === "starting"
? "Starting new session"
: isRenewing
? "Renewing session"
: isRestarting
? "Restarting Pi"
: "Pi is working"}
</span>
)}
<span role="status" aria-live="polite">
{displayedStatus}
</span>
<span>{state.bridge.status}</span>
{Object.values(selected?.extensionStatuses ?? {}).map((entry) => (
<span className="extension-status" key={entry}>
{entry}
</span>
))}
</div>
<div className="workspace-heading">
<span className="brand">PI</span>
<h1>{selected?.summary.label ?? "Pi workspace"}</h1>
</div>
<button
className="quiet"
@@ -876,6 +852,13 @@ export default function App() {
isModelUpdating={modelCommandPending}
locked={isSessionLocked}
lockReason={isRenewing ? "renewing" : "restarting"}
status={{
label: sessionStatusLabel,
detail: displayedStatus,
phase: sessionStatusPhase,
bridge: state.bridge.status,
extensions: Object.values(selected.extensionStatuses),
}}
isSubmitting={isSubmitting}
isAborting={isAborting}
onCommand={(command) => {