From 91c5d43c48af4e24685c8c86af40004fe90d1acc Mon Sep 17 00:00:00 2001 From: fengxiangdebaozi <10845145+fengxiangdebaozi@user.noreply.gitee.com> Date: Thu, 23 Jul 2026 15:07:23 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../workspace/messages/message-list-item.tsx | 327 ++++++++++++------ .../workspace/messages/message-list.tsx | 67 ++-- frontend-web/src/core/threads/hooks.ts | 96 ++++- .../components/PositionBuiltinAgentChat.tsx | 46 ++- .../components/PositionIntentInput.tsx | 35 +- .../components/PositionNodeChat.tsx | 108 +++++- .../pages/PositionRoundtablePage.tsx | 104 ++++-- .../hooks/useStep1Intent.ts | 8 + frontend-web/src/styles/globals.css | 11 +- .../backend/app/gateway/routers/threads.py | 164 +++++++++ 10 files changed, 808 insertions(+), 158 deletions(-) diff --git a/frontend-web/src/components/workspace/messages/message-list-item.tsx b/frontend-web/src/components/workspace/messages/message-list-item.tsx index 6ddf0f4a..33c07fff 100644 --- a/frontend-web/src/components/workspace/messages/message-list-item.tsx +++ b/frontend-web/src/components/workspace/messages/message-list-item.tsx @@ -135,11 +135,12 @@ export function MessageListItem({ threadId, tokenUsageEnabled = false, displaySources = [], - extraRehypePlugins, - onEditResubmit, - onMessageDeleted, - turnTime, -}: { + extraRehypePlugins, + onEditResubmit, + onEditSave, + onMessageDeleted, + turnTime, +}: { className?: string; fitRowToContent?: boolean; /** @@ -151,10 +152,11 @@ export function MessageListItem({ isLoading?: boolean; threadId: string; tokenUsageEnabled?: boolean; - displaySources?: RuntimeDisplaySource[]; - extraRehypePlugins?: ReturnType; - onEditResubmit?: (text: string) => void; - onMessageDeleted?: (deletedIds: string[]) => void; + displaySources?: RuntimeDisplaySource[]; + extraRehypePlugins?: ReturnType; + onEditResubmit?: (text: string) => void; + onEditSave?: (messageId: string, text: string) => void | Promise; + onMessageDeleted?: (deletedIds: string[]) => void; /** * Durable ask time of the turn this message belongs to (the preceding * question's `client_ts`). Used to time-stamp the AI answer, which carries no @@ -162,14 +164,102 @@ export function MessageListItem({ * wall clock at render time and appear to "drift" to now on every reload. */ turnTime?: string; -}) { - const isHuman = message.type === 'human'; - const messageMarkdown = - extractContentFromMessage(message) ?? - extractReasoningContentFromMessage(message) ?? - ''; - return ( - { + if (!assistantEditing) { + setAssistantDraft(messageMarkdown); + } + }, [assistantEditing, messageMarkdown]); + + const canSaveAssistantEdit = + !isLoading && + !isHuman && + !!onEditSave && + !!message.id && + !message.id.startsWith('opt-') && + !!messageMarkdown; + const confirmAssistantEdit = useCallback(async () => { + const value = assistantDraft.trim(); + if (!value || !message.id || !onEditSave || assistantSaving) { + return; + } + setAssistantSaving(true); + try { + await onEditSave(message.id, value); + setAssistantEditing(false); + } catch { + // The page-level save callback owns user-facing error toasts. Keep the + // editor open so the user can adjust and retry. + } finally { + setAssistantSaving(false); + } + }, [assistantDraft, assistantSaving, message.id, onEditSave]); + + if (!isHuman && assistantEditing) { + return ( + + +
+