import * as Option from "effect/Option";import * as Arr from "effect/Array";import { ApprovalRequestId, isToolLifecycleItemType, type OrchestrationLatestTurn, type OrchestrationThreadActivity, type OrchestrationProposedPlanId, ProviderDriverKind, 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", },]; export interface WorkLogEntry { id: string; createdAt: string; label: string; detail?: string; command?: string; rawCommand?: string; changedFiles?: ReadonlyArray<string>; tone: "thinking" | "tool" | "info" | "error"; toolTitle?: string; itemType?: ToolLifecycleItemType; requestKind?: PendingApproval["requestKind"];} interface DerivedWorkLogEntry extends WorkLogEntry { activityKind: OrchestrationThreadActivity["kind"]; collapseKey?: string; toolCallId?: string;} export interface PendingApproval { requestId: ApprovalRequestId; requestKind: "command" | "file-read" | "file-change"; createdAt: string; detail?: string;} export interface PendingUserInput { requestId: ApprovalRequestId; createdAt: string; questions: ReadonlyArray<UserInputQuestion>;} export interface ActivePlanState { createdAt: string; turnId: TurnId | null; explanation?: string | null; steps: Array<{ 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 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) return `${(durationMs / 1_000).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<ThreadSession, "orchestrationStatus" | "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.orchestrationStatus === "running") return false; return true;} export function deriveActiveWorkStartedAt( latestTurn: LatestTurnTiming | null, session: SessionActivityState | null, sendStartedAt: string | null,): string | null { const runningTurnId = session?.orchestrationStatus === "running" ? (session.activeTurnId ?? null) : null; if (runningTurnId !== null) { if (latestTurn?.turnId === runningTurnId) { return latestTurn.startedAt ?? sendStartedAt; } return sendStartedAt; } 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"; 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") );} 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 && (payload.requestKind === "command" || payload.requestKind === "file-read" || payload.requestKind === "file-change") ? payload.requestKind : payload ? requestKindFromRequestType(payload.requestType) : null; const detail = payload && typeof payload.detail === "string" ? payload.detail : undefined; if (activity.kind === "approval.requested" && requestId && requestKind) { openByRequestId.set(requestId, { requestId, requestKind, createdAt: activity.createdAt, ...(detail ? { detail } : {}), }); 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) ) { return null; } const options = question.options .map<UserInputQuestion["options"][number] | null>((option) => { if (!option || typeof option !== "object") return null; const optionRecord = option as Record<string, unknown>; if ( typeof optionRecord.label !== "string" || typeof optionRecord.description !== "string" ) { return null; } return { label: optionRecord.label, description: optionRecord.description, }; }) .filter((option): option is UserInputQuestion["options"][number] => option !== null); if (options.length === 0) { return null; } return { id: question.id, header: question.header, question: question.question, options, multiSelect: question.multiSelect === true, }; }) .filter((question): question is UserInputQuestion => question !== null); return parsed.length > 0 ? parsed : null;} export function derivePendingUserInputs( activities: ReadonlyArray<OrchestrationThreadActivity>,): PendingUserInput[] { const openByRequestId = new Map<ApprovalRequestId, PendingUserInput>(); 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 detail = payload && typeof payload.detail === "string" ? payload.detail : undefined; if (activity.kind === "user-input.requested" && requestId) { const questions = parseUserInputQuestions(payload); if (!questions) { continue; } openByRequestId.set(requestId, { requestId, createdAt: activity.createdAt, questions, }); continue; } if (activity.kind === "user-input.resolved" && requestId) { openByRequestId.delete(requestId); continue; } if ( activity.kind === "provider.user-input.respond.failed" && requestId && isStalePendingRequestFailureDetail(detail) ) { openByRequestId.delete(requestId); } } return [...openByRequestId.values()].toSorted((left, right) => left.createdAt.localeCompare(right.createdAt), );} export function deriveActivePlanState( activities: ReadonlyArray<OrchestrationThreadActivity>, latestTurnId: TurnId | undefined,): ActivePlanState | null { const ordered = [...activities].toSorted(compareActivitiesByOrder); const allPlanActivities = ordered.filter((activity) => activity.kind === "turn.plan.updated"); // Prefer plan from the current turn; fall back to the most recent plan from any turn // so that TodoWrite tasks persist across follow-up messages. const latest = Option.firstSomeOf([ ...(latestTurnId ? Arr.findLast(allPlanActivities, (activity) => activity.turnId === latestTurnId) : Option.none()), Arr.last(allPlanActivities), ]).pipe(Option.getOrNull); if (!latest) { return null; } const payload = latest.payload && typeof latest.payload === "object" ? (latest.payload as Record<string, unknown>) : null; const rawPlan = payload?.plan; if (!Array.isArray(rawPlan)) { return null; } const steps = rawPlan .map((entry) => { if (!entry || typeof entry !== "object") return null; const record = entry as Record<string, unknown>; if (typeof record.step !== "string") { return null; } const status = record.status === "completed" || record.status === "inProgress" ? record.status : "pending"; return { step: record.step, status, }; }) .filter( ( step, ): step is { step: string; status: "pending" | "inProgress" | "completed"; } => step !== null, ); if (steps.length === 0) { return null; } return { createdAt: latest.createdAt, turnId: latest.turnId, ...(payload && "explanation" in payload ? { explanation: payload.explanation as string | null } : {}), steps, };} export function findLatestProposedPlan( proposedPlans: ReadonlyArray<ProposedPlan>, latestTurnId: TurnId | string | null | undefined,): LatestProposedPlanState | null { if (latestTurnId) { const matchingTurnPlan = [...proposedPlans] .filter((proposedPlan) => proposedPlan.turnId === latestTurnId) .toSorted( (left, right) => left.updatedAt.localeCompare(right.updatedAt) || left.id.localeCompare(right.id), ) .at(-1); if (matchingTurnPlan) { return toLatestProposedPlanState(matchingTurnPlan); } } const latestPlan = [...proposedPlans] .toSorted( (left, right) => left.updatedAt.localeCompare(right.updatedAt) || left.id.localeCompare(right.id), ) .at(-1); if (!latestPlan) { return null; } return toLatestProposedPlanState(latestPlan);} export function findSidebarProposedPlan(input: { threads: ReadonlyArray<Pick<Thread, "id" | "proposedPlans">>; latestTurn: Pick<OrchestrationLatestTurn, "turnId" | "sourceProposedPlan"> | null; latestTurnSettled: boolean; threadId: ThreadId | string | null | undefined;}): LatestProposedPlanState | null { const activeThreadPlans = input.threads.find((thread) => thread.id === input.threadId)?.proposedPlans ?? []; if (!input.latestTurnSettled) { const sourceProposedPlan = input.latestTurn?.sourceProposedPlan; if (sourceProposedPlan) { const sourcePlan = input.threads .find((thread) => thread.id === sourceProposedPlan.threadId) ?.proposedPlans.find((plan) => plan.id === sourceProposedPlan.planId); if (sourcePlan) { return toLatestProposedPlanState(sourcePlan); } } } return findLatestProposedPlan(activeThreadPlans, input.latestTurn?.turnId ?? null);} export function hasActionableProposedPlan( proposedPlan: LatestProposedPlanState | Pick<ProposedPlan, "implementedAt"> | null,): boolean { return proposedPlan !== null && proposedPlan.implementedAt === null;} export function deriveWorkLogEntries( activities: ReadonlyArray<OrchestrationThreadActivity>, latestTurnId: TurnId | undefined,): WorkLogEntry[] { const ordered = [...activities].toSorted(compareActivitiesByOrder); const entries = ordered .filter((activity) => (latestTurnId ? activity.turnId === latestTurnId : true)) .filter((activity) => activity.kind !== "tool.started") .filter((activity) => activity.kind !== "task.started") .filter((activity) => activity.kind !== "context-window.updated") .filter((activity) => activity.summary !== "Checkpoint captured") .filter((activity) => !isPlanBoundaryToolActivity(activity)) .map(toDerivedWorkLogEntry); return collapseDerivedWorkLogEntries(entries).map( ({ activityKind: _activityKind, collapseKey: _collapseKey, ...entry }) => entry, );} Lines 1–500 of 1252. Load more
import * as Option from "effect/Option"; import * as Arr from "effect/Array"; import { ApprovalRequestId, isToolLifecycleItemType, type OrchestrationLatestTurn, type OrchestrationThreadActivity, type OrchestrationProposedPlanId, ProviderDriverKind, 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", }, ]; export interface WorkLogEntry { id: string; createdAt: string; label: string; detail?: string; command?: string; rawCommand?: string; changedFiles?: ReadonlyArray<string>; tone: "thinking" | "tool" | "info" | "error"; toolTitle?: string; itemType?: ToolLifecycleItemType; requestKind?: PendingApproval["requestKind"]; } interface DerivedWorkLogEntry extends WorkLogEntry { activityKind: OrchestrationThreadActivity["kind"]; collapseKey?: string; toolCallId?: string; } export interface PendingApproval { requestId: ApprovalRequestId; requestKind: "command" | "file-read" | "file-change"; createdAt: string; detail?: string; } export interface PendingUserInput { requestId: ApprovalRequestId; createdAt: string; questions: ReadonlyArray<UserInputQuestion>; } export interface ActivePlanState { createdAt: string; turnId: TurnId | null; explanation?: string | null; steps: Array<{ 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 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) return `${(durationMs / 1_000).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<ThreadSession, "orchestrationStatus" | "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.orchestrationStatus === "running") return false; return true; } export function deriveActiveWorkStartedAt( latestTurn: LatestTurnTiming | null, session: SessionActivityState | null, sendStartedAt: string | null, ): string | null { const runningTurnId = session?.orchestrationStatus === "running" ? (session.activeTurnId ?? null) : null; if (runningTurnId !== null) { if (latestTurn?.turnId === runningTurnId) { return latestTurn.startedAt ?? sendStartedAt; } return sendStartedAt; } 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"; 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") ); } 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 && (payload.requestKind === "command" || payload.requestKind === "file-read" || payload.requestKind === "file-change") ? payload.requestKind : payload ? requestKindFromRequestType(payload.requestType) : null; const detail = payload && typeof payload.detail === "string" ? payload.detail : undefined; if (activity.kind === "approval.requested" && requestId && requestKind) { openByRequestId.set(requestId, { requestId, requestKind, createdAt: activity.createdAt, ...(detail ? { detail } : {}), }); 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) ) { return null; } const options = question.options .map<UserInputQuestion["options"][number] | null>((option) => { if (!option || typeof option !== "object") return null; const optionRecord = option as Record<string, unknown>; if ( typeof optionRecord.label !== "string" || typeof optionRecord.description !== "string" ) { return null; } return { label: optionRecord.label, description: optionRecord.description, }; }) .filter((option): option is UserInputQuestion["options"][number] => option !== null); if (options.length === 0) { return null; } return { id: question.id, header: question.header, question: question.question, options, multiSelect: question.multiSelect === true, }; }) .filter((question): question is UserInputQuestion => question !== null); return parsed.length > 0 ? parsed : null; } export function derivePendingUserInputs( activities: ReadonlyArray<OrchestrationThreadActivity>, ): PendingUserInput[] { const openByRequestId = new Map<ApprovalRequestId, PendingUserInput>(); 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 detail = payload && typeof payload.detail === "string" ? payload.detail : undefined; if (activity.kind === "user-input.requested" && requestId) { const questions = parseUserInputQuestions(payload); if (!questions) { continue; } openByRequestId.set(requestId, { requestId, createdAt: activity.createdAt, questions, }); continue; } if (activity.kind === "user-input.resolved" && requestId) { openByRequestId.delete(requestId); continue; } if ( activity.kind === "provider.user-input.respond.failed" && requestId && isStalePendingRequestFailureDetail(detail) ) { openByRequestId.delete(requestId); } } return [...openByRequestId.values()].toSorted((left, right) => left.createdAt.localeCompare(right.createdAt), ); } export function deriveActivePlanState( activities: ReadonlyArray<OrchestrationThreadActivity>, latestTurnId: TurnId | undefined, ): ActivePlanState | null { const ordered = [...activities].toSorted(compareActivitiesByOrder); const allPlanActivities = ordered.filter((activity) => activity.kind === "turn.plan.updated"); // Prefer plan from the current turn; fall back to the most recent plan from any turn // so that TodoWrite tasks persist across follow-up messages. const latest = Option.firstSomeOf([ ...(latestTurnId ? Arr.findLast(allPlanActivities, (activity) => activity.turnId === latestTurnId) : Option.none()), Arr.last(allPlanActivities), ]).pipe(Option.getOrNull); if (!latest) { return null; } const payload = latest.payload && typeof latest.payload === "object" ? (latest.payload as Record<string, unknown>) : null; const rawPlan = payload?.plan; if (!Array.isArray(rawPlan)) { return null; } const steps = rawPlan .map((entry) => { if (!entry || typeof entry !== "object") return null; const record = entry as Record<string, unknown>; if (typeof record.step !== "string") { return null; } const status = record.status === "completed" || record.status === "inProgress" ? record.status : "pending"; return { step: record.step, status, }; }) .filter( ( step, ): step is { step: string; status: "pending" | "inProgress" | "completed"; } => step !== null, ); if (steps.length === 0) { return null; } return { createdAt: latest.createdAt, turnId: latest.turnId, ...(payload && "explanation" in payload ? { explanation: payload.explanation as string | null } : {}), steps, }; } export function findLatestProposedPlan( proposedPlans: ReadonlyArray<ProposedPlan>, latestTurnId: TurnId | string | null | undefined, ): LatestProposedPlanState | null { if (latestTurnId) { const matchingTurnPlan = [...proposedPlans] .filter((proposedPlan) => proposedPlan.turnId === latestTurnId) .toSorted( (left, right) => left.updatedAt.localeCompare(right.updatedAt) || left.id.localeCompare(right.id), ) .at(-1); if (matchingTurnPlan) { return toLatestProposedPlanState(matchingTurnPlan); } } const latestPlan = [...proposedPlans] .toSorted( (left, right) => left.updatedAt.localeCompare(right.updatedAt) || left.id.localeCompare(right.id), ) .at(-1); if (!latestPlan) { return null; } return toLatestProposedPlanState(latestPlan); } export function findSidebarProposedPlan(input: { threads: ReadonlyArray<Pick<Thread, "id" | "proposedPlans">>; latestTurn: Pick<OrchestrationLatestTurn, "turnId" | "sourceProposedPlan"> | null; latestTurnSettled: boolean; threadId: ThreadId | string | null | undefined; }): LatestProposedPlanState | null { const activeThreadPlans = input.threads.find((thread) => thread.id === input.threadId)?.proposedPlans ?? []; if (!input.latestTurnSettled) { const sourceProposedPlan = input.latestTurn?.sourceProposedPlan; if (sourceProposedPlan) { const sourcePlan = input.threads .find((thread) => thread.id === sourceProposedPlan.threadId) ?.proposedPlans.find((plan) => plan.id === sourceProposedPlan.planId); if (sourcePlan) { return toLatestProposedPlanState(sourcePlan); } } } return findLatestProposedPlan(activeThreadPlans, input.latestTurn?.turnId ?? null); } export function hasActionableProposedPlan( proposedPlan: LatestProposedPlanState | Pick<ProposedPlan, "implementedAt"> | null, ): boolean { return proposedPlan !== null && proposedPlan.implementedAt === null; } export function deriveWorkLogEntries( activities: ReadonlyArray<OrchestrationThreadActivity>, latestTurnId: TurnId | undefined, ): WorkLogEntry[] { const ordered = [...activities].toSorted(compareActivitiesByOrder); const entries = ordered .filter((activity) => (latestTurnId ? activity.turnId === latestTurnId : true)) .filter((activity) => activity.kind !== "tool.started") .filter((activity) => activity.kind !== "task.started") .filter((activity) => activity.kind !== "context-window.updated") .filter((activity) => activity.summary !== "Checkpoint captured") .filter((activity) => !isPlanBoundaryToolActivity(activity)) .map(toDerivedWorkLogEntry); return collapseDerivedWorkLogEntries(entries).map( ({ activityKind: _activityKind, collapseKey: _collapseKey, ...entry }) => entry, ); }