From 4e2d7ffaa7e7d0236f5acc29fff3c5d3a1433685 Mon Sep 17 00:00:00 2001 From: Mathias Fredriksson Date: Tue, 17 Mar 2026 14:10:08 +0200 Subject: [PATCH] refactor(site/src/pages/AgentsPage): use ChatMessagePart for editingFileBlocks (#23151) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the ad-hoc camelCase file block shape ({ mediaType, fileId, data }) with snake_case fields matching ChatMessagePart from the API types. The RenderBlock file variant now uses media_type/file_id instead of mediaType/fileId. The parsers in messageParsing.ts and streamState.ts pass validated ChatMessagePart objects through directly instead of destructuring and reassembling with renamed fields. This eliminates the needless API → camelCase → snake_case roundtrip that the edit flow previously required. Refs #22735 --- site/src/pages/AgentsPage/AgentChatInput.tsx | 8 ++--- site/src/pages/AgentsPage/AgentDetail.tsx | 19 +++--------- .../AgentDetail/ConversationTimeline.tsx | 30 ++++++++---------- .../AgentDetail/messageParsing.test.ts | 8 ++--- .../AgentsPage/AgentDetail/messageParsing.ts | 18 ++++------- .../AgentsPage/AgentDetail/streamState.ts | 15 ++------- .../src/pages/AgentsPage/AgentDetail/types.ts | 4 +-- .../pages/AgentsPage/AgentDetailContent.tsx | 31 +++++++------------ .../AgentsPage/AgentDetailView.stories.tsx | 8 ++--- site/src/pages/AgentsPage/AgentDetailView.tsx | 20 +++--------- .../AgentsPage/QueuedMessagesList.stories.tsx | 6 ++-- .../AgentsPage/QueuedMessagesList.test.ts | 24 +++++++------- .../pages/AgentsPage/QueuedMessagesList.tsx | 24 +++++--------- 13 files changed, 74 insertions(+), 141 deletions(-) diff --git a/site/src/pages/AgentsPage/AgentChatInput.tsx b/site/src/pages/AgentsPage/AgentChatInput.tsx index 8e7e6588b8..c21db17eb4 100644 --- a/site/src/pages/AgentsPage/AgentChatInput.tsx +++ b/site/src/pages/AgentsPage/AgentChatInput.tsx @@ -1,4 +1,4 @@ -import type { ChatQueuedMessage } from "api/typesGenerated"; +import type { ChatMessagePart, ChatQueuedMessage } from "api/typesGenerated"; import { ModelSelector, type ModelSelectorOption, @@ -94,11 +94,7 @@ interface AgentChatInputProps { onStartQueueEdit?: ( id: number, text: string, - fileBlocks: readonly { - mediaType: string; - data?: string; - fileId?: string; - }[], + fileBlocks: readonly ChatMessagePart[], ) => void; onCancelQueueEdit?: () => void; // History editing state, owned by the parent. diff --git a/site/src/pages/AgentsPage/AgentDetail.tsx b/site/src/pages/AgentsPage/AgentDetail.tsx index bb2badf4a6..be0201bb3f 100644 --- a/site/src/pages/AgentsPage/AgentDetail.tsx +++ b/site/src/pages/AgentsPage/AgentDetail.tsx @@ -15,6 +15,7 @@ import { import { deploymentSSHConfig } from "api/queries/deployment"; import { workspaceById, workspaceByIdKey } from "api/queries/workspaces"; import type * as TypesGen from "api/typesGenerated"; +import type { ChatMessagePart } from "api/typesGenerated"; import { useProxy } from "contexts/ProxyContext"; import { getTerminalHref, @@ -102,18 +103,14 @@ export function useConversationEditingState(deps: { string | null >(null); const [editingFileBlocks, setEditingFileBlocks] = useState< - readonly { mediaType: string; data?: string; fileId?: string }[] + readonly ChatMessagePart[] >([]); const handleEditUserMessage = useCallback( ( messageId: number, text: string, - fileBlocks?: readonly { - mediaType: string; - data?: string; - fileId?: string; - }[], + fileBlocks?: readonly ChatMessagePart[], ) => { setDraftBeforeHistoryEdit((prev) => editingMessageId !== null ? prev : inputValueRef.current, @@ -143,15 +140,7 @@ export function useConversationEditingState(deps: { >(null); const handleStartQueueEdit = useCallback( - ( - id: number, - text: string, - fileBlocks: readonly { - mediaType: string; - data?: string; - fileId?: string; - }[], - ) => { + (id: number, text: string, fileBlocks: readonly ChatMessagePart[]) => { setDraftBeforeQueueEdit((prev) => editingQueuedMessageID === null ? inputValueRef.current : prev, ); diff --git a/site/src/pages/AgentsPage/AgentDetail/ConversationTimeline.tsx b/site/src/pages/AgentsPage/AgentDetail/ConversationTimeline.tsx index bb879f5e55..1d5449299d 100644 --- a/site/src/pages/AgentsPage/AgentDetail/ConversationTimeline.tsx +++ b/site/src/pages/AgentsPage/AgentDetail/ConversationTimeline.tsx @@ -246,10 +246,10 @@ function renderBlockList({ ); } case "file": - if (block.mediaType.startsWith("image/")) { - const src = block.fileId - ? `/api/experimental/chats/files/${block.fileId}` - : `data:${block.mediaType};base64,${block.data}`; + if (block.media_type.startsWith("image/")) { + const src = block.file_id + ? `/api/experimental/chats/files/${block.file_id}` + : `data:${block.media_type};base64,${block.data}`; return (