118 lines · 3.3 KB · TypeScript
RawDownload
import type { StatusTone } from "../../components/StatusPill";import type { OrchestrationLatestTurn, OrchestrationSession } from "@t3tools/contracts";import { EnvironmentThreadShell } from "@t3tools/client-runtime/state/shell"; export type ThreadStatusKind =  | "pending-approval"  | "awaiting-input"  | "working"  | "connecting"  | "error"  | "plan-ready"; export interface ThreadStatusPresentation extends StatusTone {  readonly kind: ThreadStatusKind;  /** Foreground color for the leading status icon. */  readonly iconColor: string;  /** Background color for the leading status icon circle. */  readonly iconBackground: string;  /** Whether the indicator represents in-flight activity. */  readonly pulse: boolean;} function isLatestTurnSettled(  latestTurn: OrchestrationLatestTurn | null,  session: OrchestrationSession | null,): boolean {  if (!latestTurn?.startedAt) return false;  if (!latestTurn.completedAt) return false;  if (!session) return true;  return session.status !== "running";} /** * Resolves the user-facing status of a thread, in priority order. Returns * `null` for quiescent threads so rows stay free of "Idle"-style noise. * Mirrors `resolveThreadStatusPill` in apps/web/src/components/Sidebar.logic.ts. */export function resolveThreadStatus(  thread: EnvironmentThreadShell,): ThreadStatusPresentation | null {  if (thread.hasPendingApprovals) {    return {      kind: "pending-approval",      label: "Needs Approval",      pillClassName: "bg-warning",      textClassName: "text-warning-foreground",      iconColor: "#ff9f0a",      iconBackground: "rgba(255,159,10,0.22)",      pulse: false,    };  }   if (thread.hasPendingUserInput) {    return {      kind: "awaiting-input",      label: "Awaiting Input",      pillClassName: "bg-primary/10",      textClassName: "text-foreground-secondary",      iconColor: "#5e5ce6",      iconBackground: "rgba(94,92,230,0.22)",      pulse: false,    };  }   if (thread.session?.status === "running") {    return {      kind: "working",      label: "Working",      pillClassName: "bg-primary/10",      textClassName: "text-adaptive-sky-600-400",      iconColor: "#0a84ff",      iconBackground: "rgba(10,132,255,0.22)",      pulse: true,    };  }   if (thread.session?.status === "starting") {    return {      kind: "connecting",      label: "Connecting",      pillClassName: "bg-primary/10",      textClassName: "text-foreground-secondary",      iconColor: "#0a84ff",      iconBackground: "rgba(10,132,255,0.22)",      pulse: true,    };  }   if (thread.session?.status === "error" || thread.latestTurn?.state === "error") {    return {      kind: "error",      label: "Error",      pillClassName: "bg-danger",      textClassName: "text-danger-foreground",      iconColor: "#ff453a",      iconBackground: "rgba(255,69,58,0.22)",      pulse: false,    };  }   const hasPlanReadyPrompt =    thread.interactionMode === "plan" &&    isLatestTurnSettled(thread.latestTurn, thread.session) &&    thread.hasActionableProposedPlan;  if (hasPlanReadyPrompt) {    return {      kind: "plan-ready",      label: "Plan Ready",      pillClassName: "bg-primary/10",      textClassName: "text-foreground-secondary",      iconColor: "#bf5af2",      iconBackground: "rgba(191,90,242,0.22)",      pulse: false,    };  }   return null;}