diff --git a/packages/ui/src/components/message-part.tsx b/packages/ui/src/components/message-part.tsx index 4b223bf35..92da5b625 100644 --- a/packages/ui/src/components/message-part.tsx +++ b/packages/ui/src/components/message-part.tsx @@ -104,6 +104,7 @@ export interface MessagePartProps { hideDetails?: boolean defaultOpen?: boolean showAssistantCopyPartID?: string | null + turnDurationMs?: number } export type PartComponent = Component @@ -275,6 +276,7 @@ function renderable(part: PartType) { export function AssistantParts(props: { messages: AssistantMessage[] showAssistantCopyPartID?: string | null + turnDurationMs?: number working?: boolean }) { const data = useData() @@ -365,6 +367,7 @@ export function AssistantParts(props: { part={entry().part} message={entry().message} showAssistantCopyPartID={props.showAssistantCopyPartID} + turnDurationMs={props.turnDurationMs} /> )} @@ -849,6 +852,7 @@ export function Part(props: MessagePartProps) { hideDetails={props.hideDetails} defaultOpen={props.defaultOpen} showAssistantCopyPartID={props.showAssistantCopyPartID} + turnDurationMs={props.turnDurationMs} /> ) @@ -1060,8 +1064,12 @@ PART_MAPPING["text"] = function TextPartDisplay(props) { if (props.message.role !== "assistant") return "" const message = props.message as AssistantMessage const completed = message.time.completed - if (typeof completed !== "number") return "" - const ms = completed - message.time.created + const ms = + typeof props.turnDurationMs === "number" + ? props.turnDurationMs + : typeof completed === "number" + ? completed - message.time.created + : -1 if (!(ms >= 0)) return "" const total = Math.round(ms / 1000) if (total < 60) return `${total}s` diff --git a/packages/ui/src/components/session-turn.tsx b/packages/ui/src/components/session-turn.tsx index 2aed8279e..aa2769280 100644 --- a/packages/ui/src/components/session-turn.tsx +++ b/packages/ui/src/components/session-turn.tsx @@ -247,6 +247,21 @@ export function SessionTurn( if (working()) return null return showAssistantCopyPartID() ?? null }) + const turnDurationMs = createMemo(() => { + const start = message()?.time.created + if (typeof start !== "number") return undefined + + const end = assistantMessages().reduce((max, item) => { + const completed = item.time.completed + if (typeof completed !== "number") return max + if (max === undefined) return completed + return Math.max(max, completed) + }, undefined) + + if (typeof end !== "number") return undefined + if (end < start) return undefined + return end - start + }) const assistantVisible = createMemo(() => assistantMessages().reduce((count, message) => { const parts = list(data.store.part?.[message.id], emptyParts) @@ -290,6 +305,7 @@ export function SessionTurn(