mirror of
https://github.com/bytedance/deer-flow.git
synced 2026-04-25 19:28:23 +00:00
fix(rebase): restore FeedbackButtons component and enrichment lost during rebase
The FeedbackButtons component (defined inline in message-list-item.tsx) was introduced in commit 95df8d13 but lost during rebase. The previous rebase cleanup commit incorrectly removed the feedback/runId props and enrichment hook as "orphaned code" instead of restoring the missing component. This commit restores: - FeedbackButtons component with thumbs up/down toggle and optimistic state - FeedbackData/upsertFeedback/deleteFeedback imports - feedback and runId props on MessageListItem - useThreadMessageEnrichment hook and entry lookup in message-list.tsx Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
500cdfc8e4
commit
8f7eb28c0d
@ -1,6 +1,6 @@
|
||||
import type { Message } from "@langchain/langgraph-sdk";
|
||||
import { FileIcon, Loader2Icon } from "lucide-react";
|
||||
import { memo, useMemo, type ImgHTMLAttributes } from "react";
|
||||
import { FileIcon, Loader2Icon, ThumbsDownIcon, ThumbsUpIcon } from "lucide-react";
|
||||
import { memo, useCallback, useMemo, useState, type ImgHTMLAttributes } from "react";
|
||||
import rehypeKatex from "rehype-katex";
|
||||
|
||||
import { Loader } from "@/components/ai-elements/loader";
|
||||
@ -17,6 +17,11 @@ import {
|
||||
} from "@/components/ai-elements/reasoning";
|
||||
import { Task, TaskTrigger } from "@/components/ai-elements/task";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import {
|
||||
deleteFeedback,
|
||||
upsertFeedback,
|
||||
type FeedbackData,
|
||||
} from "@/core/api/feedback";
|
||||
import { resolveArtifactURL } from "@/core/artifacts/utils";
|
||||
import { useI18n } from "@/core/i18n/hooks";
|
||||
import {
|
||||
@ -34,16 +39,85 @@ import { CopyButton } from "../copy-button";
|
||||
|
||||
import { MarkdownContent } from "./markdown-content";
|
||||
|
||||
function FeedbackButtons({
|
||||
threadId,
|
||||
runId,
|
||||
initialFeedback,
|
||||
}: {
|
||||
threadId: string;
|
||||
runId: string;
|
||||
initialFeedback: FeedbackData | null;
|
||||
}) {
|
||||
const [feedback, setFeedback] = useState<FeedbackData | null>(initialFeedback);
|
||||
const [isSubmitting, setIsSubmitting] = useState(false);
|
||||
|
||||
const handleClick = useCallback(
|
||||
async (rating: number) => {
|
||||
if (isSubmitting) return;
|
||||
setIsSubmitting(true);
|
||||
try {
|
||||
if (feedback?.rating === rating) {
|
||||
await deleteFeedback(threadId, runId);
|
||||
setFeedback(null);
|
||||
} else {
|
||||
const result = await upsertFeedback(threadId, runId, rating);
|
||||
setFeedback(result);
|
||||
}
|
||||
} catch {
|
||||
// Revert on error — feedback state unchanged on catch
|
||||
} finally {
|
||||
setIsSubmitting(false);
|
||||
}
|
||||
},
|
||||
[threadId, runId, feedback, isSubmitting],
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="flex gap-1">
|
||||
<button
|
||||
type="button"
|
||||
className={cn(
|
||||
"text-muted-foreground hover:text-foreground rounded-md p-1 transition-colors",
|
||||
feedback?.rating === 1 && "text-foreground",
|
||||
)}
|
||||
onClick={() => handleClick(1)}
|
||||
disabled={isSubmitting}
|
||||
>
|
||||
<ThumbsUpIcon
|
||||
className={cn("size-4", feedback?.rating === 1 && "fill-current")}
|
||||
/>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className={cn(
|
||||
"text-muted-foreground hover:text-foreground rounded-md p-1 transition-colors",
|
||||
feedback?.rating === -1 && "text-foreground",
|
||||
)}
|
||||
onClick={() => handleClick(-1)}
|
||||
disabled={isSubmitting}
|
||||
>
|
||||
<ThumbsDownIcon
|
||||
className={cn("size-4", feedback?.rating === -1 && "fill-current")}
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function MessageListItem({
|
||||
className,
|
||||
threadId,
|
||||
message,
|
||||
isLoading,
|
||||
feedback,
|
||||
runId,
|
||||
}: {
|
||||
className?: string;
|
||||
threadId: string;
|
||||
message: Message;
|
||||
isLoading?: boolean;
|
||||
feedback?: FeedbackData | null;
|
||||
runId?: string;
|
||||
}) {
|
||||
const isHuman = message.type === "human";
|
||||
return (
|
||||
@ -72,6 +146,13 @@ export function MessageListItem({
|
||||
""
|
||||
}
|
||||
/>
|
||||
{feedback !== undefined && runId && threadId && (
|
||||
<FeedbackButtons
|
||||
threadId={threadId}
|
||||
runId={runId}
|
||||
initialFeedback={feedback}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</MessageToolbar>
|
||||
)}
|
||||
|
||||
@ -18,6 +18,7 @@ import { useRehypeSplitWordsIntoSpans } from "@/core/rehype";
|
||||
import type { Subtask } from "@/core/tasks";
|
||||
import { useUpdateSubtask } from "@/core/tasks/context";
|
||||
import type { AgentThreadState } from "@/core/threads";
|
||||
import { useThreadMessageEnrichment } from "@/core/threads/hooks";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
import { ArtifactFileList } from "../artifacts/artifact-file-list";
|
||||
@ -47,6 +48,7 @@ export function MessageList({
|
||||
const rehypePlugins = useRehypeSplitWordsIntoSpans(thread.isLoading);
|
||||
const updateSubtask = useUpdateSubtask();
|
||||
const messages = thread.messages;
|
||||
const { data: enrichment } = useThreadMessageEnrichment(threadId);
|
||||
|
||||
if (thread.isThreadLoading && messages.length === 0) {
|
||||
return <MessageListSkeleton />;
|
||||
@ -59,12 +61,15 @@ export function MessageList({
|
||||
{groupMessages(messages, (group) => {
|
||||
if (group.type === "human" || group.type === "assistant") {
|
||||
return group.messages.map((msg) => {
|
||||
const entry = msg.id ? enrichment?.get(msg.id) : undefined;
|
||||
return (
|
||||
<MessageListItem
|
||||
key={`${group.id}/${msg.id}`}
|
||||
threadId={threadId}
|
||||
message={msg}
|
||||
isLoading={thread.isLoading}
|
||||
runId={entry?.run_id}
|
||||
feedback={entry?.feedback}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user