Files
Jyotisha/frontend/src/components/chat-message-actions.tsx
T
Jesse_ChenandClaude Opus 5.5 84eb23152a feat(rectification): remove the rectification regenerate button and endpoint (BUG-1056)
T2 of TASK-rectification-grounding-20260927 (product decision P1).
The rectification 「重试(重新生成)」 was a blind agent.generate rewrite that
persisted unchecked text (invented range / fit rate reproduced). Removed:
the regenerate route, regenerate-turn.ts, the regeneration agent and its
read-only tool set, the client regenerate action/state and the
regenerating/canRegenerate props. ChatMessageActions renders the regenerate
button only when onRegenerate is passed; ordinary consultation is unchanged.
The DB function regenerate_agentic_rectification_turn is kept (AGENTS §7.6,
retire in a later round). DESIGN.md / VOICE.md updated; source-contract
tests follow with 原值/新值/原因 notes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017eEAG8HD3mm8gsKXgk8uU8
2026-09-27 03:28:27 +08:00

69 lines
1.9 KiB
TypeScript

"use client";
import { Check, Copy, RotateCcw, ThumbsDown, ThumbsUp } from "lucide-react";
export type ChatMessageFeedback = "up" | "down";
export function toggleChatMessageFeedback(
current: ChatMessageFeedback | undefined,
requested: ChatMessageFeedback,
): ChatMessageFeedback | undefined {
return current === requested ? undefined : requested;
}
export function ChatMessageActions({
feedback,
copied = false,
canRegenerate,
onFeedback,
onCopy,
onRegenerate,
}: Readonly<{
feedback?: ChatMessageFeedback;
copied?: boolean;
/** Without `onRegenerate` the regenerate button is not rendered (rectification, BUG-1056). */
canRegenerate?: boolean;
onFeedback: (value: ChatMessageFeedback) => void;
onCopy: () => void;
onRegenerate?: () => void;
}>) {
return (
<div className="message-actions" aria-label="Agent 回答操作">
<button
aria-label="赞"
aria-pressed={feedback === "up"}
className={feedback === "up" ? "is-active" : ""}
title="赞"
type="button"
onClick={() => onFeedback("up")}
>
<ThumbsUp aria-hidden="true" />
</button>
<button
aria-label="踩"
aria-pressed={feedback === "down"}
className={feedback === "down" ? "is-active" : ""}
title="踩"
type="button"
onClick={() => onFeedback("down")}
>
<ThumbsDown aria-hidden="true" />
</button>
<button aria-label="复制回答" title="复制" type="button" onClick={onCopy}>
{copied ? <Check aria-hidden="true" /> : <Copy aria-hidden="true" />}
</button>
{onRegenerate && (
<button
aria-label="重新生成回答"
disabled={!canRegenerate}
title={canRegenerate ? "重新生成" : "只能重新生成最近一条回答"}
type="button"
onClick={onRegenerate}
>
<RotateCcw aria-hidden="true" />
</button>
)}
</div>
);
}