1840 lines · 57.4 KB · TypeScript
RawDownload
import * as Option from "effect/Option";import * as Arr from "effect/Array";import * as Schema from "effect/Schema";import { isBackgroundTaskActivity } from "@t3tools/client-runtime/state/subagentRuntime";import { isWorktreeSetupActivity } from "@t3tools/client-runtime/work-log/presentation";import {  ApprovalRequestId,  isToolLifecycleItemType,  type OrchestrationLatestTurn,  type OrchestrationThreadActivity,  type OrchestrationProposedPlanId,  ProviderDriverKind,  ProviderApprovalOption,  ProviderRequestKind,  type ToolLifecycleItemType,  type UserInputQuestion,  type ThreadId,  type TurnId,} from "@t3tools/contracts"; import type {  ChatMessage,  ProposedPlan,  SessionPhase,  Thread,  ThreadSession,  TurnDiffSummary,} from "./types"; export type ProviderPickerKind = ProviderDriverKind; export const PROVIDER_OPTIONS: Array<{  value: ProviderPickerKind;  label: string;  available: boolean;  /** Shown on the model picker sidebar when relevant */  pickerSidebarBadge?: "new" | "soon";}> = [  { value: ProviderDriverKind.make("codex"), label: "Codex", available: true },  { value: ProviderDriverKind.make("claudeAgent"), label: "Claude", available: true },  {    value: ProviderDriverKind.make("opencode"),    label: "OpenCode",    available: true,    pickerSidebarBadge: "new",  },  {    value: ProviderDriverKind.make("cursor"),    label: "Cursor",    available: true,    pickerSidebarBadge: "new",  },  {    value: ProviderDriverKind.make("grok"),    label: "Grok",    available: true,    pickerSidebarBadge: "new",  },]; export type WorkLogToolLifecycleStatus =  | "inProgress"  | "completed"  | "failed"  | "declined"  | "stopped"; export interface WorkLogEntry {  id: string;  createdAt: string;  turnId?: TurnId | null;  /** Stable provider identity across in-progress and completed lifecycle updates. */  toolCallId?: string;  label: string;  detail?: string;  command?: string;  rawCommand?: string;  changedFiles?: ReadonlyArray<string>;  tone: "thinking" | "tool" | "info" | "error";  toolTitle?: string;  toolData?: unknown;  itemType?: ToolLifecycleItemType;  requestKind?: PendingApproval["requestKind"];  /** From runtime item / task payload `status` when present (e.g. tool.updated). */  toolLifecycleStatus?: WorkLogToolLifecycleStatus;  /** Originating orchestration activity kind (e.g. `user-input.requested`) for row chrome. */  sourceActivityKind?: OrchestrationThreadActivity["kind"];  /** Grouping key for subagent lifecycle rows (one row per agent). */  taskId?: string;  /** Agent role (subagent_type) for labeled timeline rows. */  agentRole?: string;  /**   * Present on agent-spawn CTA rows: one per workflow run or per-turn batch   * of direct spawns. The row renders as a call-to-action ("Kicked off N   * subagents") whose live status is derived from the agent panel model at   * render time; clicking opens the Agents panel.   */  agentSpawn?: {    /** Workflow coordinator taskId, or null for a direct-spawn batch. */    workflowId: string | null;    agentTaskIds: ReadonlyArray<string>;  };} const workLogCollapseKey = Symbol(); interface DerivedWorkLogEntry extends WorkLogEntry {  sourceActivityKind: OrchestrationThreadActivity["kind"];  [workLogCollapseKey]?: string;  toolCallId?: string;  isWorkflowCoordinator?: boolean;  /** Shell/monitor/plan tasks: ordinary work-log rows, never spawn CTAs. */  isBackgroundTask?: boolean;} const derivedWorkLogEntryByActivity = new WeakMap<  OrchestrationThreadActivity,  DerivedWorkLogEntry>(); export interface PendingApproval {  requestId: ApprovalRequestId;  requestKind: ProviderRequestKind;  createdAt: string;  detail?: string;  appName?: string;  options?: ReadonlyArray<ProviderApprovalOption>;} const isProviderRequestKind = Schema.is(ProviderRequestKind);const isProviderApprovalOption = Schema.is(ProviderApprovalOption); export interface PendingUserInput {  requestId: ApprovalRequestId;  createdAt: string;  questions: ReadonlyArray<UserInputQuestion>;} export interface ActivePlanState {  createdAt: string;  turnId: TurnId | null;  explanation?: string | null;  steps: Array<{    durationMs?: number;    step: string;    status: "pending" | "inProgress" | "completed";  }>;} export interface LatestProposedPlanState {  id: OrchestrationProposedPlanId;  createdAt: string;  updatedAt: string;  turnId: TurnId | null;  planMarkdown: string;  implementedAt: string | null;  implementationThreadId: ThreadId | null;} export type TimelineEntry =  | {      id: string;      kind: "message";      createdAt: string;      message: ChatMessage;    }  | {      id: string;      kind: "proposed-plan";      createdAt: string;      proposedPlan: ProposedPlan;    }  | {      id: string;      kind: "work";      createdAt: string;      entry: WorkLogEntry;    }; export function workLogEntryIsToolLike(entry: WorkLogEntry): boolean {  if (entry.tone === "tool" || entry.tone === "thinking" || entry.tone === "error") {    return true;  }  if (entry.command !== undefined && entry.command.trim().length > 0) {    return true;  }  if (entry.requestKind !== undefined) {    return true;  }  return entry.itemType !== undefined && isToolLifecycleItemType(entry.itemType);} /** Heuristic: providers often emit successful lifecycle status while error text lives in `detail` / `command`. */function toolDetailTextLooksLikeFailure(text: string): boolean {  const t = text.toLowerCase();  if (t.includes("file not found")) {    return true;  }  if (t.includes("no files found")) {    return true;  }  if (    t.includes("enoent") ||    t.includes("no such file or directory") ||    t.includes("no such file")  ) {    return true;  }  if (t.includes("cannot find path") && t.includes("because it does not exist")) {    return true;  }  if (t.includes("commandnotfoundexception")) {    return true;  }  if (t.includes("is not recognized as the name of a cmdlet")) {    return true;  }  if (t.includes("is not recognized") && t.includes("the term '")) {    return true;  }  if (t.includes("a parameter cannot be found that matches parameter name")) {    return true;  }  if (t.includes("command not found")) {    return true;  }  if (/<exited with exit code\s+[1-9]\d*\s*>/i.test(text)) {    return true;  }  if (/exit(?:ed)? with exit code\s+[1-9]\d*/i.test(text)) {    return true;  }  if (/exit code\s*[:\s]\s*[1-9]\d*\b/i.test(text)) {    return true;  }  return false;} function workEntryIndicatesToolFailureFromOutput(  entry: WorkLogEntry,  includeCommand: boolean,): boolean {  if (entry.tone === "error") {    return true;  }  const ls = entry.toolLifecycleStatus;  if (ls === "failed" || ls === "declined") {    return true;  }  if (!workLogEntryIsToolLike(entry)) {    return false;  }  const parts: string[] = [];  if (entry.detail) {    parts.push(entry.detail);  }  if (includeCommand && entry.command) {    parts.push(entry.command);  }  const blob = parts.join("\n");  if (blob.length === 0) {    return false;  }  return toolDetailTextLooksLikeFailure(blob);} /** True when a tool failed, including providers that put error output in `command`. */export function workEntryIndicatesToolFailure(entry: WorkLogEntry): boolean {  return workEntryIndicatesToolFailureFromOutput(entry, true);} /** True when the rendered result indicates failure. The command itself is user intent, not output. */export function workEntryDisplayIndicatesToolFailure(entry: WorkLogEntry): boolean {  return workEntryIndicatesToolFailureFromOutput(entry, false);} /** Severe failures keep the red treatment ordinary tool failures lost: runtime *  errors and orchestration `*.failed` activities (provider.turn.start.failed, *  checkpoint.capture.failed, ...) mean the turn or a core side effect broke, *  not that a command exited nonzero. */export function workEntrySignalsSevereFailure(entry: WorkLogEntry): boolean {  return (    entry.sourceActivityKind === "runtime.error" ||    entry.sourceActivityKind?.endsWith(".failed") === true  );} /** Tool/command row completed without failure (blue check affordance). */export function workEntryIndicatesToolSuccess(entry: WorkLogEntry): boolean {  if (!workLogEntryIsToolLike(entry)) {    return false;  }  if (workEntryIndicatesToolFailure(entry)) {    return false;  }  if (entry.tone === "thinking") {    return false;  }  const ls = entry.toolLifecycleStatus;  if (ls === "failed" || ls === "declined") {    return false;  }  if (ls === "inProgress") {    return false;  }  if (ls === "stopped") {    return false;  }  return true;} /** Tool-like row with neither clear success nor failure (empty, incomplete, in progress, etc.). */export function workEntryIndicatesToolNeutralStatus(entry: WorkLogEntry): boolean {  // Spawn CTA rows are never neutral-hidden: mid-run they derive from  // task.progress (tone "thinking") and the neutral filter was swallowing  // them exactly while the fleet ran — the one moment they matter most.  if (entry.agentSpawn !== undefined) {    return false;  }  if (!workLogEntryIsToolLike(entry)) {    return false;  }  if (workEntryIndicatesToolFailure(entry)) {    return false;  }  if (workEntryIndicatesToolSuccess(entry)) {    return false;  }  return true;} export function formatDuration(durationMs: number): string {  if (!Number.isFinite(durationMs) || durationMs < 0) return "0ms";  if (durationMs < 1_000) return `${Math.max(1, Math.round(durationMs))}ms`;  if (durationMs < 10_000) {    const tenths = Math.round(durationMs / 100) / 10;    // 9.95s+ rounds up to the next bucket — render "10s", not "10.0s".    return tenths >= 10 ? "10s" : `${tenths.toFixed(1)}s`;  }  if (durationMs < 60_000) return `${Math.round(durationMs / 1_000)}s`;  const minutes = Math.floor(durationMs / 60_000);  const seconds = Math.round((durationMs % 60_000) / 1_000);  if (seconds === 0) return `${minutes}m`;  if (seconds === 60) return `${minutes + 1}m`;  return `${minutes}m ${seconds}s`;} export function formatElapsed(startIso: string, endIso: string | undefined): string | null {  if (!endIso) return null;  const startedAt = Date.parse(startIso);  const endedAt = Date.parse(endIso);  if (Number.isNaN(startedAt) || Number.isNaN(endedAt) || endedAt < startedAt) {    return null;  }  return formatDuration(endedAt - startedAt);} type LatestTurnTiming = Pick<OrchestrationLatestTurn, "turnId" | "startedAt" | "completedAt">;type SessionActivityState = Pick<NonNullable<Thread["session"]>, "status" | "activeTurnId">; export function isLatestTurnSettled(  latestTurn: LatestTurnTiming | null,  session: SessionActivityState | null,): boolean {  if (!latestTurn?.startedAt) return false;  if (!latestTurn.completedAt) return false;  if (!session) return true;  if (session.status === "running") return false;  return true;} export function deriveActiveWorkStartedAt(  latestTurn: LatestTurnTiming | null,  session: SessionActivityState | null,  sendStartedAt: string | null,  latestUserMessageAt: string | null = null,): string | null {  const runningTurnId = session?.status === "running" ? session.activeTurnId : null;  if (runningTurnId !== null) {    if (latestTurn?.turnId === runningTurnId) {      return latestTurn.startedAt ?? sendStartedAt ?? latestUserMessageAt;    }    return sendStartedAt ?? latestUserMessageAt;  }  if (!isLatestTurnSettled(latestTurn, session)) {    return latestTurn?.startedAt ?? sendStartedAt;  }  return sendStartedAt;} function requestKindFromRequestType(requestType: unknown): PendingApproval["requestKind"] | null {  switch (requestType) {    case "command_execution_approval":    case "exec_command_approval":    case "dynamic_tool_call":      return "command";    case "file_read_approval":      return "file-read";    case "file_change_approval":    case "apply_patch_approval":      return "file-change";    case "mcp_elicitation_approval":      return "mcp-elicitation";    default:      return null;  }} function isStalePendingRequestFailureDetail(detail: string | undefined): boolean {  const normalized = detail?.toLowerCase();  if (!normalized) {    return false;  }  return (    normalized.includes("stale pending approval request") ||    normalized.includes("stale pending user-input request") ||    normalized.includes("unknown pending approval request") ||    normalized.includes("unknown pending permission request") ||    normalized.includes("unknown pending user-input request") ||    normalized.includes("unknown pending user input request") ||    normalized.includes("unknown pending codex user input request")  );} export function derivePendingApprovals(  activities: ReadonlyArray<OrchestrationThreadActivity>,): PendingApproval[] {  const openByRequestId = new Map<ApprovalRequestId, PendingApproval>();  const ordered = [...activities].toSorted(compareActivitiesByOrder);   for (const activity of ordered) {    const payload =      activity.payload && typeof activity.payload === "object"        ? (activity.payload as Record<string, unknown>)        : null;    const requestId =      payload && typeof payload.requestId === "string"        ? ApprovalRequestId.make(payload.requestId)        : null;    const requestKind =      payload && isProviderRequestKind(payload.requestKind)        ? payload.requestKind        : payload          ? requestKindFromRequestType(payload.requestType)          : null;    const detail = payload && typeof payload.detail === "string" ? payload.detail : undefined;    const appName = payload && typeof payload.appName === "string" ? payload.appName : undefined;    const options = Array.isArray(payload?.options)      ? payload.options.filter(isProviderApprovalOption)      : undefined;     if (activity.kind === "approval.requested" && requestId && requestKind) {      openByRequestId.set(requestId, {        requestId,        requestKind,        createdAt: activity.createdAt,        ...(detail ? { detail } : {}),        ...(appName ? { appName } : {}),        ...(options && options.length > 0 ? { options } : {}),      });      continue;    }     if (activity.kind === "approval.resolved" && requestId) {      openByRequestId.delete(requestId);      continue;    }     if (      activity.kind === "provider.approval.respond.failed" &&      requestId &&      isStalePendingRequestFailureDetail(detail)    ) {      openByRequestId.delete(requestId);      continue;    }  }   return [...openByRequestId.values()].toSorted((left, right) =>    left.createdAt.localeCompare(right.createdAt),  );} function parseUserInputQuestions(  payload: Record<string, unknown> | null,): ReadonlyArray<UserInputQuestion> | null {  const questions = payload?.questions;  if (!Array.isArray(questions)) {    return null;  }  const parsed = questions    .map<UserInputQuestion | null>((entry) => {      if (!entry || typeof entry !== "object") return null;      const question = entry as Record<string, unknown>;      if (        typeof question.id !== "string" ||        typeof question.header !== "string" ||        typeof question.question !== "string" ||        !Array.isArray(question.options)      ) {

Lines 1–500 of 1840.