import type { ThreadPendingApproval, ThreadPendingUserInput, ThreadUserInputQuestion,} from "@t3tools/client-runtime/state/thread-requests";import { turnItemIsWorkspacePreparation } from "@t3tools/client-runtime/state/turn-item-presentation";import { extractToolActivityPresentation } from "@t3tools/client-runtime/work-log/tool-presentation";import { commandProgramName } from "@t3tools/client-runtime/work-log/command-label";import { workEntryDisplayIndicatesToolFailure, liveActivityToolStatus, toolGroupAction, resolveWorkEntryToolPresentation, summarizeToolGroup, toolGroupSummaryKind, type ToolGroupSummaryKind, type WorkLogPresentationEntry, type WorkLogToolLifecycleStatus,} from "@t3tools/client-runtime/work-log/presentation";import { resolveT3McpToolPresentation, type T3McpToolLogo, type T3McpToolPresentation,} from "@t3tools/shared/t3McpToolPresentation";import type { ChatAttachment, MessageId, OrchestrationV2Actor, OrchestrationV2CreationSource, OrchestrationV2ExecutionNode, OrchestrationMessage, OrchestrationV2ProjectedTurnItem, OrchestrationV2RunAttempt, OrchestrationV2RunStatus, OrchestrationV2TurnItem, OrchestrationV2UserMessageInputIntent, RunId, RunAttemptId,} from "@t3tools/contracts";import { ThreadId } from "@t3tools/contracts";import { formatDuration } from "@t3tools/shared/orchestrationTiming";import * as DateTime from "effect/DateTime"; export type PendingApproval = ThreadPendingApproval;export type PendingUserInput = ThreadPendingUserInput; export interface PendingUserInputDraftAnswer { readonly selectedOptionValues?: ReadonlyArray<string>; readonly customAnswer?: string;} export interface ThreadFeedActivity { readonly id: string; readonly createdAt: string; readonly runId: RunId | null; readonly attemptId: RunAttemptId | null; readonly summary: string; readonly detail: string | null; readonly canExpand: boolean; readonly getFullDetail: () => string | null; readonly getCopyText: () => string; readonly icon: | "agent" | "alert" | "browser" | "computer" | "check" | "command" | "edit" | "eye" | "globe" | "hammer" | "message" | "warning" | "wrench" | "zap"; readonly logo: T3McpToolLogo | null; readonly toolLike: boolean; readonly prominent: boolean; readonly status: "success" | "failure" | "neutral" | null; readonly lifecycleStatus: WorkLogToolLifecycleStatus; readonly workEntry: WorkLogPresentationEntry; readonly groupedToolDetail?: boolean; readonly live?: boolean; readonly projectedItem: OrchestrationV2ProjectedTurnItem;} export interface ThreadFeedMessage { readonly id: MessageId; readonly role: "user" | "assistant"; readonly text: string; readonly attachments: ReadonlyArray<ChatAttachment>; readonly runId: RunId | null; readonly streaming: boolean; readonly inputIntent?: OrchestrationV2UserMessageInputIntent; readonly createdBy?: OrchestrationV2Actor; readonly creationSource?: OrchestrationV2CreationSource; readonly visibility: OrchestrationV2ProjectedTurnItem["visibility"]; readonly sourceThreadId: ThreadId; readonly createdAt: string; readonly updatedAt: string; readonly projectedItem?: OrchestrationV2ProjectedTurnItem;} type RawThreadFeedEntry = | { readonly type: "message"; readonly id: string; readonly createdAt: string; readonly message: ThreadFeedMessage; } | { readonly type: "activity"; readonly id: string; readonly createdAt: string; readonly runId: RunId | null; readonly activity: ThreadFeedActivity; }; export type ThreadFeedEntry = | Extract<RawThreadFeedEntry, { type: "message" }> | { readonly type: "activity-group"; readonly id: string; readonly createdAt: string; readonly runId: RunId | null; readonly activities: ReadonlyArray<ThreadFeedActivity>; } | { readonly type: "work-toggle"; readonly id: string; readonly createdAt: string; readonly runId: RunId | null; readonly groupId: string; readonly hiddenCount: number; readonly expanded: boolean; readonly summary: string; readonly summaryKind: ToolGroupSummaryKind; readonly toolSurface?: WorkLogPresentationEntry["toolSurface"]; readonly toolIcon?: WorkLogPresentationEntry["toolIcon"]; readonly summaryToolIcon?: "browser" | "t3-code"; readonly hasFailure: boolean; readonly live: boolean; readonly shimmer: boolean; } | { readonly type: "run-fold"; readonly id: string; readonly createdAt: string; readonly runId: RunId; readonly label: string; readonly expanded: boolean; }; export interface ThreadFeedLatestRun { readonly runId: RunId; readonly status: OrchestrationV2RunStatus; readonly startedAt: string | null; readonly completedAt: string | null;} type ThreadFeedActivityGroup = Extract<ThreadFeedEntry, { readonly type: "activity-group" }>; // Immutable source rows let retained history keep its identities while the active item streams.const projectedEntriesCache = new WeakMap< OrchestrationV2ProjectedTurnItem, { readonly attemptId: RunAttemptId | null; readonly entry: RawThreadFeedEntry; }>();const localMessageEntriesCache = new WeakMap< OrchestrationMessage, Extract<RawThreadFeedEntry, { readonly type: "message" }>>();const activityGroupsCache = new WeakMap<ThreadFeedActivity, ThreadFeedActivityGroup>();const presentedActivityGroupsCache = new WeakMap< ThreadFeedActivityGroup, { readonly activeRunId: RunId | null; readonly isWorking: boolean; readonly activeTail: boolean; readonly rows: ReadonlyArray<ThreadFeedEntry>; }>();const runFoldRowsCache = new WeakMap< ThreadFeedEntry, Extract<ThreadFeedEntry, { readonly type: "run-fold" }>>(); export function isContextCompactionActivityGroup(entry: ThreadFeedActivityGroup): boolean { return ( entry.activities.length === 1 && entry.activities[0]?.projectedItem.item.type === "compaction" );} function normalizeDraftAnswer(value: string | undefined): string | null { if (typeof value !== "string") return null; const trimmed = value.trim(); return trimmed.length > 0 ? trimmed : null;} function resolvePendingUserInputOptionValue( question: ThreadUserInputQuestion, value: string,): string | null { if (question.options.some((option) => option.value === value)) { return value; } const label = value.trim(); return label.length > 0 && question.options.some((option) => option.value === undefined && option.label.trim() === label) ? label : null;} function normalizeSelectedOptionValues( question: ThreadUserInputQuestion, value: ReadonlyArray<string> | undefined,): ReadonlyArray<string> { if (!Array.isArray(value)) { return []; } return Array.from( new Set( value .map((entry) => resolvePendingUserInputOptionValue(question, entry)) .filter((entry): entry is string => entry !== null), ), );} function resolvePendingUserInputAnswer( question: ThreadUserInputQuestion, draft: PendingUserInputDraftAnswer | undefined,): string | ReadonlyArray<string> | null { const customAnswer = question.allowCustomAnswer === false ? null : normalizeDraftAnswer(draft?.customAnswer); if (customAnswer) { return customAnswer; } const selectedOptionValues = normalizeSelectedOptionValues(question, draft?.selectedOptionValues); if (question.multiSelect) { return selectedOptionValues.length > 0 ? selectedOptionValues : null; } return selectedOptionValues[0] ?? null;} function capitalizePhrase(value: string): string { const trimmed = value.trim(); return trimmed.length === 0 ? value : `${trimmed.charAt(0).toUpperCase()}${trimmed.slice(1)}`;} function memoizeValue<T>(build: () => T): () => T { let value: T; let initialized = false; return () => { if (!initialized) { value = build(); initialized = true; } return value; };} function itemIsToolLike(item: OrchestrationV2TurnItem): boolean { return ( item.type === "reasoning" || item.type === "command_execution" || item.type === "file_change" || item.type === "file_search" || item.type === "web_search" || item.type === "approval_request" || item.type === "user_input_request" || item.type === "dynamic_tool" || item.type === "subagent" );} function itemIsProminent(item: OrchestrationV2TurnItem): boolean { return ( item.type === "fork" || item.type === "thread_created" || item.type === "subagent" || item.type === "system_notice" );} function itemStatus(item: OrchestrationV2TurnItem): ThreadFeedActivity["status"] { if (item.type === "error") { if (item.status === "failed") return "failure"; return item.status === "completed" ? "success" : "neutral"; } if (!itemIsToolLike(item)) return null; if (item.status === "failed") return "failure"; return item.status === "completed" ? "success" : "neutral";} function itemLifecycleStatus(item: OrchestrationV2TurnItem): WorkLogToolLifecycleStatus { switch (item.status) { case "pending": case "running": case "waiting": return "inProgress"; case "idle": return "idle"; case "completed": return "completed"; case "failed": return "failed"; case "cancelled": case "interrupted": return "stopped"; }} function itemWorkLogTone(item: OrchestrationV2TurnItem): WorkLogPresentationEntry["tone"] { if (item.type === "error") return "info"; if (item.type === "reasoning") return "thinking"; switch (item.type) { case "command_execution": case "file_change": case "file_search": case "web_search": case "dynamic_tool": case "subagent": return "tool"; default: return "info"; }} function itemIcon(item: OrchestrationV2TurnItem): ThreadFeedActivity["icon"] { switch (item.type) { case "reasoning": return "agent"; case "command_execution": return "command"; case "file_change": return "edit"; case "file_search": return "eye"; case "web_search": return "globe"; case "approval_request": case "user_input_request": case "user_message": case "assistant_message": return "message"; case "dynamic_tool": return "wrench"; case "subagent": return "hammer"; case "run_interrupt_request": case "run_interrupt_result": case "system_notice": return "warning"; case "error": return "alert"; case "checkpoint": case "proposed_plan": case "todo_list": return "check"; case "compaction": case "handoff": case "fork": case "thread_created": return "zap"; }} function itemToolPresentation(item: OrchestrationV2TurnItem): T3McpToolPresentation | null { if (item.type !== "dynamic_tool") { return null; } return resolveT3McpToolPresentation(item.toolName) ?? resolveT3McpToolPresentation(item.title);} function itemSummary( item: OrchestrationV2TurnItem, toolPresentation: T3McpToolPresentation | null = null,): string { if (item.type === "system_notice") return item.message; const title = item.title?.trim(); if (title) return toolPresentation?.displayName ?? capitalizePhrase(title); switch (item.type) { case "reasoning": return "Thinking"; case "command_execution": return "Command"; case "file_change": return `Changed ${item.fileName}`; case "file_search": return "Searched files"; case "web_search": return "Searched the web"; case "approval_request": return "Approval requested"; case "user_input_request": return "Input requested"; case "checkpoint": return "Checkpoint captured"; case "run_interrupt_request": return "Interrupt requested"; case "run_interrupt_result": return "Run interrupted"; case "error": return "Provider error"; case "compaction": return "Context compacted"; case "handoff": return "Context handed off"; case "fork": return "Thread forked"; case "thread_created": return "Thread created"; case "subagent": return "Subagent"; case "dynamic_tool": return toolPresentation?.displayName ?? item.toolName ?? "Tool call"; case "proposed_plan": return "Proposed plan"; case "todo_list": return "Plan updated"; case "user_message": return "User message"; case "assistant_message": return "Assistant message"; }} function itemPreview(item: OrchestrationV2TurnItem): string | null { switch (item.type) { case "reasoning": return item.text || null; case "command_execution": return item.input || null; case "file_change": return item.fileName; case "file_search": return item.pattern ?? null; case "web_search": return item.patterns?.join(", ") ?? null; case "approval_request": return item.prompt ?? null; case "user_input_request": return item.questions.map((question) => question.question).join(" · ") || null; case "checkpoint": return item.files.length === 1 ? (item.files[0]?.path ?? null) : `${item.files.length} changed files`; case "run_interrupt_request": case "run_interrupt_result": case "system_notice": return item.message || null; case "error": return item.failure.message; case "compaction": case "handoff": return item.summary ?? null; case "fork": case "thread_created": return item.targetThreadId; case "subagent": return item.result ?? item.progress ?? item.prompt; case "dynamic_tool": return null; case "proposed_plan": return item.markdown || null; case "todo_list": return `${item.steps.filter((step) => step.status === "completed").length}/${item.steps.length} completed`; case "user_message": case "assistant_message": return item.text || null; }} function toWorkLogEntry( item: OrchestrationV2TurnItem, createdAt: string, summary: string, detail: string | null,): WorkLogPresentationEntry { const title = item.title?.trim() || null; const common = { ...extractToolActivityPresentation(item), id: item.id, createdAt, label: summary, tone: itemWorkLogTone(item), itemType: item.type, toolLifecycleStatus: itemLifecycleStatus(item), structuredPayload: item, } as const; switch (item.type) { case "reasoning":Lines 1–500 of 1361. Load more
import type { ThreadPendingApproval, ThreadPendingUserInput, ThreadUserInputQuestion, } from "@t3tools/client-runtime/state/thread-requests"; import { turnItemIsWorkspacePreparation } from "@t3tools/client-runtime/state/turn-item-presentation"; import { extractToolActivityPresentation } from "@t3tools/client-runtime/work-log/tool-presentation"; import { commandProgramName } from "@t3tools/client-runtime/work-log/command-label"; import { workEntryDisplayIndicatesToolFailure, liveActivityToolStatus, toolGroupAction, resolveWorkEntryToolPresentation, summarizeToolGroup, toolGroupSummaryKind, type ToolGroupSummaryKind, type WorkLogPresentationEntry, type WorkLogToolLifecycleStatus, } from "@t3tools/client-runtime/work-log/presentation"; import { resolveT3McpToolPresentation, type T3McpToolLogo, type T3McpToolPresentation, } from "@t3tools/shared/t3McpToolPresentation"; import type { ChatAttachment, MessageId, OrchestrationV2Actor, OrchestrationV2CreationSource, OrchestrationV2ExecutionNode, OrchestrationMessage, OrchestrationV2ProjectedTurnItem, OrchestrationV2RunAttempt, OrchestrationV2RunStatus, OrchestrationV2TurnItem, OrchestrationV2UserMessageInputIntent, RunId, RunAttemptId, } from "@t3tools/contracts"; import { ThreadId } from "@t3tools/contracts"; import { formatDuration } from "@t3tools/shared/orchestrationTiming"; import * as DateTime from "effect/DateTime"; export type PendingApproval = ThreadPendingApproval; export type PendingUserInput = ThreadPendingUserInput; export interface PendingUserInputDraftAnswer { readonly selectedOptionValues?: ReadonlyArray<string>; readonly customAnswer?: string; } export interface ThreadFeedActivity { readonly id: string; readonly createdAt: string; readonly runId: RunId | null; readonly attemptId: RunAttemptId | null; readonly summary: string; readonly detail: string | null; readonly canExpand: boolean; readonly getFullDetail: () => string | null; readonly getCopyText: () => string; readonly icon: | "agent" | "alert" | "browser" | "computer" | "check" | "command" | "edit" | "eye" | "globe" | "hammer" | "message" | "warning" | "wrench" | "zap"; readonly logo: T3McpToolLogo | null; readonly toolLike: boolean; readonly prominent: boolean; readonly status: "success" | "failure" | "neutral" | null; readonly lifecycleStatus: WorkLogToolLifecycleStatus; readonly workEntry: WorkLogPresentationEntry; readonly groupedToolDetail?: boolean; readonly live?: boolean; readonly projectedItem: OrchestrationV2ProjectedTurnItem; } export interface ThreadFeedMessage { readonly id: MessageId; readonly role: "user" | "assistant"; readonly text: string; readonly attachments: ReadonlyArray<ChatAttachment>; readonly runId: RunId | null; readonly streaming: boolean; readonly inputIntent?: OrchestrationV2UserMessageInputIntent; readonly createdBy?: OrchestrationV2Actor; readonly creationSource?: OrchestrationV2CreationSource; readonly visibility: OrchestrationV2ProjectedTurnItem["visibility"]; readonly sourceThreadId: ThreadId; readonly createdAt: string; readonly updatedAt: string; readonly projectedItem?: OrchestrationV2ProjectedTurnItem; } type RawThreadFeedEntry = | { readonly type: "message"; readonly id: string; readonly createdAt: string; readonly message: ThreadFeedMessage; } | { readonly type: "activity"; readonly id: string; readonly createdAt: string; readonly runId: RunId | null; readonly activity: ThreadFeedActivity; }; export type ThreadFeedEntry = | Extract<RawThreadFeedEntry, { type: "message" }> | { readonly type: "activity-group"; readonly id: string; readonly createdAt: string; readonly runId: RunId | null; readonly activities: ReadonlyArray<ThreadFeedActivity>; } | { readonly type: "work-toggle"; readonly id: string; readonly createdAt: string; readonly runId: RunId | null; readonly groupId: string; readonly hiddenCount: number; readonly expanded: boolean; readonly summary: string; readonly summaryKind: ToolGroupSummaryKind; readonly toolSurface?: WorkLogPresentationEntry["toolSurface"]; readonly toolIcon?: WorkLogPresentationEntry["toolIcon"]; readonly summaryToolIcon?: "browser" | "t3-code"; readonly hasFailure: boolean; readonly live: boolean; readonly shimmer: boolean; } | { readonly type: "run-fold"; readonly id: string; readonly createdAt: string; readonly runId: RunId; readonly label: string; readonly expanded: boolean; }; export interface ThreadFeedLatestRun { readonly runId: RunId; readonly status: OrchestrationV2RunStatus; readonly startedAt: string | null; readonly completedAt: string | null; } type ThreadFeedActivityGroup = Extract<ThreadFeedEntry, { readonly type: "activity-group" }>; // Immutable source rows let retained history keep its identities while the active item streams. const projectedEntriesCache = new WeakMap< OrchestrationV2ProjectedTurnItem, { readonly attemptId: RunAttemptId | null; readonly entry: RawThreadFeedEntry; } >(); const localMessageEntriesCache = new WeakMap< OrchestrationMessage, Extract<RawThreadFeedEntry, { readonly type: "message" }> >(); const activityGroupsCache = new WeakMap<ThreadFeedActivity, ThreadFeedActivityGroup>(); const presentedActivityGroupsCache = new WeakMap< ThreadFeedActivityGroup, { readonly activeRunId: RunId | null; readonly isWorking: boolean; readonly activeTail: boolean; readonly rows: ReadonlyArray<ThreadFeedEntry>; } >(); const runFoldRowsCache = new WeakMap< ThreadFeedEntry, Extract<ThreadFeedEntry, { readonly type: "run-fold" }> >(); export function isContextCompactionActivityGroup(entry: ThreadFeedActivityGroup): boolean { return ( entry.activities.length === 1 && entry.activities[0]?.projectedItem.item.type === "compaction" ); } function normalizeDraftAnswer(value: string | undefined): string | null { if (typeof value !== "string") return null; const trimmed = value.trim(); return trimmed.length > 0 ? trimmed : null; } function resolvePendingUserInputOptionValue( question: ThreadUserInputQuestion, value: string, ): string | null { if (question.options.some((option) => option.value === value)) { return value; } const label = value.trim(); return label.length > 0 && question.options.some((option) => option.value === undefined && option.label.trim() === label) ? label : null; } function normalizeSelectedOptionValues( question: ThreadUserInputQuestion, value: ReadonlyArray<string> | undefined, ): ReadonlyArray<string> { if (!Array.isArray(value)) { return []; } return Array.from( new Set( value .map((entry) => resolvePendingUserInputOptionValue(question, entry)) .filter((entry): entry is string => entry !== null), ), ); } function resolvePendingUserInputAnswer( question: ThreadUserInputQuestion, draft: PendingUserInputDraftAnswer | undefined, ): string | ReadonlyArray<string> | null { const customAnswer = question.allowCustomAnswer === false ? null : normalizeDraftAnswer(draft?.customAnswer); if (customAnswer) { return customAnswer; } const selectedOptionValues = normalizeSelectedOptionValues(question, draft?.selectedOptionValues); if (question.multiSelect) { return selectedOptionValues.length > 0 ? selectedOptionValues : null; } return selectedOptionValues[0] ?? null; } function capitalizePhrase(value: string): string { const trimmed = value.trim(); return trimmed.length === 0 ? value : `${trimmed.charAt(0).toUpperCase()}${trimmed.slice(1)}`; } function memoizeValue<T>(build: () => T): () => T { let value: T; let initialized = false; return () => { if (!initialized) { value = build(); initialized = true; } return value; }; } function itemIsToolLike(item: OrchestrationV2TurnItem): boolean { return ( item.type === "reasoning" || item.type === "command_execution" || item.type === "file_change" || item.type === "file_search" || item.type === "web_search" || item.type === "approval_request" || item.type === "user_input_request" || item.type === "dynamic_tool" || item.type === "subagent" ); } function itemIsProminent(item: OrchestrationV2TurnItem): boolean { return ( item.type === "fork" || item.type === "thread_created" || item.type === "subagent" || item.type === "system_notice" ); } function itemStatus(item: OrchestrationV2TurnItem): ThreadFeedActivity["status"] { if (item.type === "error") { if (item.status === "failed") return "failure"; return item.status === "completed" ? "success" : "neutral"; } if (!itemIsToolLike(item)) return null; if (item.status === "failed") return "failure"; return item.status === "completed" ? "success" : "neutral"; } function itemLifecycleStatus(item: OrchestrationV2TurnItem): WorkLogToolLifecycleStatus { switch (item.status) { case "pending": case "running": case "waiting": return "inProgress"; case "idle": return "idle"; case "completed": return "completed"; case "failed": return "failed"; case "cancelled": case "interrupted": return "stopped"; } } function itemWorkLogTone(item: OrchestrationV2TurnItem): WorkLogPresentationEntry["tone"] { if (item.type === "error") return "info"; if (item.type === "reasoning") return "thinking"; switch (item.type) { case "command_execution": case "file_change": case "file_search": case "web_search": case "dynamic_tool": case "subagent": return "tool"; default: return "info"; } } function itemIcon(item: OrchestrationV2TurnItem): ThreadFeedActivity["icon"] { switch (item.type) { case "reasoning": return "agent"; case "command_execution": return "command"; case "file_change": return "edit"; case "file_search": return "eye"; case "web_search": return "globe"; case "approval_request": case "user_input_request": case "user_message": case "assistant_message": return "message"; case "dynamic_tool": return "wrench"; case "subagent": return "hammer"; case "run_interrupt_request": case "run_interrupt_result": case "system_notice": return "warning"; case "error": return "alert"; case "checkpoint": case "proposed_plan": case "todo_list": return "check"; case "compaction": case "handoff": case "fork": case "thread_created": return "zap"; } } function itemToolPresentation(item: OrchestrationV2TurnItem): T3McpToolPresentation | null { if (item.type !== "dynamic_tool") { return null; } return resolveT3McpToolPresentation(item.toolName) ?? resolveT3McpToolPresentation(item.title); } function itemSummary( item: OrchestrationV2TurnItem, toolPresentation: T3McpToolPresentation | null = null, ): string { if (item.type === "system_notice") return item.message; const title = item.title?.trim(); if (title) return toolPresentation?.displayName ?? capitalizePhrase(title); switch (item.type) { case "reasoning": return "Thinking"; case "command_execution": return "Command"; case "file_change": return `Changed ${item.fileName}`; case "file_search": return "Searched files"; case "web_search": return "Searched the web"; case "approval_request": return "Approval requested"; case "user_input_request": return "Input requested"; case "checkpoint": return "Checkpoint captured"; case "run_interrupt_request": return "Interrupt requested"; case "run_interrupt_result": return "Run interrupted"; case "error": return "Provider error"; case "compaction": return "Context compacted"; case "handoff": return "Context handed off"; case "fork": return "Thread forked"; case "thread_created": return "Thread created"; case "subagent": return "Subagent"; case "dynamic_tool": return toolPresentation?.displayName ?? item.toolName ?? "Tool call"; case "proposed_plan": return "Proposed plan"; case "todo_list": return "Plan updated"; case "user_message": return "User message"; case "assistant_message": return "Assistant message"; } } function itemPreview(item: OrchestrationV2TurnItem): string | null { switch (item.type) { case "reasoning": return item.text || null; case "command_execution": return item.input || null; case "file_change": return item.fileName; case "file_search": return item.pattern ?? null; case "web_search": return item.patterns?.join(", ") ?? null; case "approval_request": return item.prompt ?? null; case "user_input_request": return item.questions.map((question) => question.question).join(" · ") || null; case "checkpoint": return item.files.length === 1 ? (item.files[0]?.path ?? null) : `${item.files.length} changed files`; case "run_interrupt_request": case "run_interrupt_result": case "system_notice": return item.message || null; case "error": return item.failure.message; case "compaction": case "handoff": return item.summary ?? null; case "fork": case "thread_created": return item.targetThreadId; case "subagent": return item.result ?? item.progress ?? item.prompt; case "dynamic_tool": return null; case "proposed_plan": return item.markdown || null; case "todo_list": return `${item.steps.filter((step) => step.status === "completed").length}/${item.steps.length} completed`; case "user_message": case "assistant_message": return item.text || null; } } function toWorkLogEntry( item: OrchestrationV2TurnItem, createdAt: string, summary: string, detail: string | null, ): WorkLogPresentationEntry { const title = item.title?.trim() || null; const common = { ...extractToolActivityPresentation(item), id: item.id, createdAt, label: summary, tone: itemWorkLogTone(item), itemType: item.type, toolLifecycleStatus: itemLifecycleStatus(item), structuredPayload: item, } as const; switch (item.type) { case "reasoning":