fix(chat): remove regenerate action
Build Push and Deploy / docker-image (push) Successful in 1m7s
Build Push and Deploy / deploy-fallback-log (push) Has been skipped

This commit is contained in:
2026-06-08 19:33:06 +08:00
parent 36cdb1df8d
commit e5f13c3d46
9 changed files with 0 additions and 149 deletions
-15
View File
@@ -15,7 +15,6 @@ import {
useTheme, useTheme,
} from "@mui/material"; } from "@mui/material";
import ContentCopyRounded from "@mui/icons-material/ContentCopyRounded"; import ContentCopyRounded from "@mui/icons-material/ContentCopyRounded";
import RefreshRounded from "@mui/icons-material/RefreshRounded";
import { TbArrowsSplit2 } from "react-icons/tb"; import { TbArrowsSplit2 } from "react-icons/tb";
import type { PermissionReply } from "@/lib/chatStream"; import type { PermissionReply } from "@/lib/chatStream";
import { import {
@@ -46,7 +45,6 @@ type AgentTurnProps = {
onResume: () => void; onResume: () => void;
onStopSpeech: () => void; onStopSpeech: () => void;
isTtsSupported: boolean; isTtsSupported: boolean;
onRegenerate: (messageId: string) => void;
onCreateBranch: (messageId: string) => void; onCreateBranch: (messageId: string) => void;
onReplyPermission: (requestId: string, reply: PermissionReply) => void; onReplyPermission: (requestId: string, reply: PermissionReply) => void;
onReplyQuestion: (requestId: string, answers: string[][]) => void; onReplyQuestion: (requestId: string, answers: string[][]) => void;
@@ -62,7 +60,6 @@ export const AgentTurn = React.memo(
onResume, onResume,
onStopSpeech, onStopSpeech,
isTtsSupported, isTtsSupported,
onRegenerate,
onCreateBranch, onCreateBranch,
onReplyPermission, onReplyPermission,
onReplyQuestion, onReplyQuestion,
@@ -316,18 +313,6 @@ export const AgentTurn = React.memo(
<ContentCopyRounded sx={{ fontSize: 16 }} /> <ContentCopyRounded sx={{ fontSize: 16 }} />
</IconButton> </IconButton>
</Tooltip> </Tooltip>
<Tooltip title="重新生成">
<IconButton
size="small"
aria-label="重新生成"
onClick={() => {
onRegenerate(message.id);
}}
sx={{ width: 28, height: 28, color: "text.secondary", "&:hover": { color: "#00acc1", bgcolor: alpha("#00acc1", 0.1) } }}
>
<RefreshRounded sx={{ fontSize: 16 }} />
</IconButton>
</Tooltip>
<Tooltip title="拆分为新会话"> <Tooltip title="拆分为新会话">
<IconButton <IconButton
size="small" size="small"
@@ -41,7 +41,6 @@ describe("AgentWorkspace", () => {
onResumeSpeech: jest.fn(), onResumeSpeech: jest.fn(),
onStopSpeech: jest.fn(), onStopSpeech: jest.fn(),
isTtsSupported: false, isTtsSupported: false,
onRegenerate: jest.fn(),
onCreateBranch: jest.fn(), onCreateBranch: jest.fn(),
onReplyPermission: jest.fn(), onReplyPermission: jest.fn(),
onReplyQuestion: jest.fn(), onReplyQuestion: jest.fn(),
-8
View File
@@ -28,7 +28,6 @@ type AgentWorkspaceProps = {
onResumeSpeech: () => void; onResumeSpeech: () => void;
onStopSpeech: () => void; onStopSpeech: () => void;
isTtsSupported: boolean; isTtsSupported: boolean;
onRegenerate: (messageId: string) => void;
onCreateBranch: (messageId: string) => void; onCreateBranch: (messageId: string) => void;
onReplyPermission: (requestId: string, reply: PermissionReply) => void; onReplyPermission: (requestId: string, reply: PermissionReply) => void;
onReplyQuestion: (requestId: string, answers: string[][]) => void; onReplyQuestion: (requestId: string, answers: string[][]) => void;
@@ -44,7 +43,6 @@ type TurnListProps = {
onResumeSpeech: () => void; onResumeSpeech: () => void;
onStopSpeech: () => void; onStopSpeech: () => void;
isTtsSupported: boolean; isTtsSupported: boolean;
onRegenerate: (messageId: string) => void;
onCreateBranch: (messageId: string) => void; onCreateBranch: (messageId: string) => void;
onReplyPermission: (requestId: string, reply: PermissionReply) => void; onReplyPermission: (requestId: string, reply: PermissionReply) => void;
onReplyQuestion: (requestId: string, answers: string[][]) => void; onReplyQuestion: (requestId: string, answers: string[][]) => void;
@@ -64,7 +62,6 @@ const TurnListInner = ({
onResumeSpeech, onResumeSpeech,
onStopSpeech, onStopSpeech,
isTtsSupported, isTtsSupported,
onRegenerate,
onCreateBranch, onCreateBranch,
onReplyPermission, onReplyPermission,
onReplyQuestion, onReplyQuestion,
@@ -82,7 +79,6 @@ const TurnListInner = ({
onResume={onResumeSpeech} onResume={onResumeSpeech}
onStopSpeech={onStopSpeech} onStopSpeech={onStopSpeech}
isTtsSupported={isTtsSupported} isTtsSupported={isTtsSupported}
onRegenerate={onRegenerate}
onCreateBranch={onCreateBranch} onCreateBranch={onCreateBranch}
onReplyPermission={onReplyPermission} onReplyPermission={onReplyPermission}
onReplyQuestion={onReplyQuestion} onReplyQuestion={onReplyQuestion}
@@ -104,7 +100,6 @@ const TurnList = React.memo(
prevProps.onResumeSpeech === nextProps.onResumeSpeech && prevProps.onResumeSpeech === nextProps.onResumeSpeech &&
prevProps.onStopSpeech === nextProps.onStopSpeech && prevProps.onStopSpeech === nextProps.onStopSpeech &&
prevProps.isTtsSupported === nextProps.isTtsSupported && prevProps.isTtsSupported === nextProps.isTtsSupported &&
prevProps.onRegenerate === nextProps.onRegenerate &&
prevProps.onCreateBranch === nextProps.onCreateBranch && prevProps.onCreateBranch === nextProps.onCreateBranch &&
prevProps.onReplyPermission === nextProps.onReplyPermission && prevProps.onReplyPermission === nextProps.onReplyPermission &&
prevProps.onReplyQuestion === nextProps.onReplyQuestion && prevProps.onReplyQuestion === nextProps.onReplyQuestion &&
@@ -238,7 +233,6 @@ export const AgentWorkspace = ({
onResumeSpeech, onResumeSpeech,
onStopSpeech, onStopSpeech,
isTtsSupported, isTtsSupported,
onRegenerate,
onCreateBranch, onCreateBranch,
onReplyPermission, onReplyPermission,
onReplyQuestion, onReplyQuestion,
@@ -287,7 +281,6 @@ export const AgentWorkspace = ({
onResumeSpeech={onResumeSpeech} onResumeSpeech={onResumeSpeech}
onStopSpeech={onStopSpeech} onStopSpeech={onStopSpeech}
isTtsSupported={isTtsSupported} isTtsSupported={isTtsSupported}
onRegenerate={onRegenerate}
onCreateBranch={onCreateBranch} onCreateBranch={onCreateBranch}
onReplyPermission={onReplyPermission} onReplyPermission={onReplyPermission}
onReplyQuestion={onReplyQuestion} onReplyQuestion={onReplyQuestion}
@@ -304,7 +297,6 @@ export const AgentWorkspace = ({
onResumeSpeech={onResumeSpeech} onResumeSpeech={onResumeSpeech}
onStopSpeech={onStopSpeech} onStopSpeech={onStopSpeech}
isTtsSupported={isTtsSupported} isTtsSupported={isTtsSupported}
onRegenerate={onRegenerate}
onCreateBranch={onCreateBranch} onCreateBranch={onCreateBranch}
onReplyPermission={onReplyPermission} onReplyPermission={onReplyPermission}
onReplyQuestion={onReplyQuestion} onReplyQuestion={onReplyQuestion}
-2
View File
@@ -71,7 +71,6 @@ export const GlobalChatbox: React.FC<Props> = ({ open, onClose }) => {
isStreaming, isStreaming,
sessionTitle, sessionTitle,
sendPrompt, sendPrompt,
regenerate,
createBranch, createBranch,
abort, abort,
replyPermission, replyPermission,
@@ -352,7 +351,6 @@ export const GlobalChatbox: React.FC<Props> = ({ open, onClose }) => {
onResumeSpeech={handleResumeSpeech} onResumeSpeech={handleResumeSpeech}
onStopSpeech={handleStopSpeech} onStopSpeech={handleStopSpeech}
isTtsSupported={isTtsSupported} isTtsSupported={isTtsSupported}
onRegenerate={regenerate}
onCreateBranch={createBranch} onCreateBranch={createBranch}
onReplyPermission={replyPermission} onReplyPermission={replyPermission}
onReplyQuestion={replyQuestion} onReplyQuestion={replyQuestion}
@@ -359,84 +359,6 @@ describe("useAgentChatSession actions", () => {
); );
}); });
it("asks the backend to undo the previous user turn before regenerating", async () => {
listChatSessions.mockResolvedValue([]);
const { result } = renderHook(() =>
useAgentChatSession({
projectId: "project-1",
onToolCall: jest.fn(),
}),
);
await waitFor(() => expect(result.current.isHydrating).toBe(false));
await act(async () => {
await result.current.sendPrompt("重新分析压力异常");
});
const assistantMessageId = result.current.messages[1]?.id ?? "";
await act(async () => {
await result.current.regenerate(assistantMessageId);
});
expect(streamAgentChat).toHaveBeenNthCalledWith(
2,
expect.objectContaining({
message: "重新分析压力异常",
regenerateFromMessageIndex: 0,
}),
);
});
it("replaces the current chain when regenerating a middle assistant message", async () => {
listChatSessions.mockResolvedValue([]);
const { result } = renderHook(() =>
useAgentChatSession({
projectId: "project-1",
onToolCall: jest.fn(),
}),
);
await waitFor(() => expect(result.current.isHydrating).toBe(false));
await act(async () => {
await result.current.sendPrompt("第一轮");
});
await act(async () => {
await result.current.sendPrompt("第二轮");
});
const firstAssistantMessageId = result.current.messages[1]?.id ?? "";
await act(async () => {
await result.current.regenerate(firstAssistantMessageId);
});
expect(result.current.messages).toHaveLength(2);
expect(result.current.messages[0]).toEqual(
expect.objectContaining({
role: "user",
content: "第一轮",
}),
);
expect(result.current.messages[1]).toEqual(
expect.objectContaining({
role: "assistant",
content: "",
}),
);
expect(streamAgentChat).toHaveBeenNthCalledWith(
3,
expect.objectContaining({
message: "第一轮",
regenerateFromMessageIndex: 0,
}),
);
});
it("forks a copied conversation from an assistant message", async () => { it("forks a copied conversation from an assistant message", async () => {
listChatSessions.mockResolvedValue([]); listChatSessions.mockResolvedValue([]);
@@ -407,7 +407,6 @@ export const useAgentChatSession = ({
async ({ async ({
prompt: rawPrompt, prompt: rawPrompt,
sessionIdOverride, sessionIdOverride,
regenerateFromMessageIndex,
preparedMessages, preparedMessages,
userMessage, userMessage,
assistantMessage, assistantMessage,
@@ -442,7 +441,6 @@ export const useAgentChatSession = ({
sessionId: sessionIdOverride ?? sessionIdRef.current, sessionId: sessionIdOverride ?? sessionIdRef.current,
model: getModel?.(), model: getModel?.(),
approvalMode: getApprovalMode?.(), approvalMode: getApprovalMode?.(),
regenerateFromMessageIndex,
signal: controller.signal, signal: controller.signal,
onEvent: (event) => onEvent: (event) =>
applyStreamEvent(event, { applyStreamEvent(event, {
@@ -893,43 +891,6 @@ export const useAgentChatSession = ({
[isHydrating, messages], [isHydrating, messages],
); );
const regenerate = useCallback(async (messageId: string) => {
if (isHydrating || isStreaming || messages.length === 0) return;
const targetAssistantIndex = messages.findIndex(
(message) => message.id === messageId && message.role === "assistant",
);
if (targetAssistantIndex < 0) {
return;
}
let targetUserIndex = targetAssistantIndex - 1;
while (targetUserIndex >= 0 && messages[targetUserIndex].role !== "user") {
targetUserIndex--;
}
if (targetUserIndex < 0) return;
const targetUser = messages[targetUserIndex];
const targetUserContent = targetUser.content;
const nextMessages = cloneMessages(messages.slice(0, targetUserIndex));
const nextUserMessage = createUserMessage(targetUserContent);
const nextAssistantMessage = createAssistantMessage();
setMessages(nextMessages);
await runPrompt({
prompt: targetUserContent,
regenerateFromMessageIndex: targetUserIndex,
preparedMessages: [
...nextMessages,
nextUserMessage,
nextAssistantMessage,
],
userMessage: nextUserMessage,
assistantMessage: nextAssistantMessage,
});
}, [isHydrating, isStreaming, messages, runPrompt]);
const createBranch = useCallback( const createBranch = useCallback(
async (messageId: string) => { async (messageId: string) => {
if (isHydrating || isStreaming) return; if (isHydrating || isStreaming) return;
@@ -975,7 +936,6 @@ export const useAgentChatSession = ({
sessionTitle, sessionTitle,
sessionId, sessionId,
sendPrompt, sendPrompt,
regenerate,
createBranch, createBranch,
abort, abort,
replyPermission, replyPermission,
@@ -18,7 +18,6 @@ export type UseAgentChatSessionOptions = {
export type PromptRunOptions = { export type PromptRunOptions = {
prompt: string; prompt: string;
sessionIdOverride?: string; sessionIdOverride?: string;
regenerateFromMessageIndex?: number;
preparedMessages?: Message[]; preparedMessages?: Message[];
userMessage?: Message; userMessage?: Message;
assistantMessage?: Message; assistantMessage?: Message;
-1
View File
@@ -75,7 +75,6 @@ describe("streamAgentChat", () => {
session_id: undefined, session_id: undefined,
model: "deepseek/deepseek-v4-pro", model: "deepseek/deepseek-v4-pro",
approval_mode: undefined, approval_mode: undefined,
regenerate_from_message_index: undefined,
}), }),
}), }),
); );
-3
View File
@@ -140,7 +140,6 @@ type StreamOptions = {
sessionId?: string; sessionId?: string;
model?: AgentModel; model?: AgentModel;
approvalMode?: AgentApprovalMode; approvalMode?: AgentApprovalMode;
regenerateFromMessageIndex?: number;
signal?: AbortSignal; signal?: AbortSignal;
onEvent: (event: StreamEvent) => void; onEvent: (event: StreamEvent) => void;
}; };
@@ -460,7 +459,6 @@ export const streamAgentChat = async ({
sessionId, sessionId,
model, model,
approvalMode, approvalMode,
regenerateFromMessageIndex,
signal, signal,
onEvent, onEvent,
}: StreamOptions) => { }: StreamOptions) => {
@@ -480,7 +478,6 @@ export const streamAgentChat = async ({
session_id: sessionId, session_id: sessionId,
model, model,
approval_mode: approvalMode, approval_mode: approvalMode,
regenerate_from_message_index: regenerateFromMessageIndex,
}), }),
projectHeaderMode: "include", projectHeaderMode: "include",
userHeaderMode: "include", userHeaderMode: "include",