import { CircleCheck, CircleHelp, LoaderCircle, RotateCw, X } from "lucide-react"; import { Button } from "@/shared/ui/button"; import { Checkbox } from "@/shared/ui/checkbox"; import { cn } from "@/shared/ui/cn"; import { Radio } from "@/shared/ui/radio"; import { Textarea } from "@/shared/ui/textarea"; import type { InteractionAnswer } from "../api/interaction-requests"; import type { InteractionRequestEntry, InteractionRequestsController } from "../hooks/use-interaction-requests"; import { AgentUserMessageText } from "./agent-user-message-text"; const statuses = { pending: "等待回答", answered: "答案已保存", skipped: "已跳过", cancelled: "已取消", invalidated: "已失效" }; const deliveries = { queued: "等待继续", dispatching: "正在继续处理", delivered: "已继续处理", blocked: "继续失败,可以重试", cancelled: "已停止继续" }; export function AgentInteractionRequests({ controller, representedMessageIds }: { controller: InteractionRequestsController; representedMessageIds?: ReadonlySet; }) { return
{controller.checking ?

正在核对提问状态,核对后可回答。

: null} {controller.error ?
{controller.error}
: null} {controller.entries.filter(({ record }) => !(record.delivery && ["answered", "skipped"].includes(record.status) && representedMessageIds?.has(record.delivery.native_message_id))).map((entry) => controller.update(entry.record.interaction_id, draft)} onAction={(action) => void controller.act(entry.record.interaction_id, action)} />)}
; } /** Render the stored human answer, independent of the model-facing transcript. */ export function AgentInteractionReply({ entry, checking, onResume }: { entry: InteractionRequestEntry; checking: boolean; onResume: () => void; }) { const { record } = entry; const retryable = record.delivery && ["queued", "dispatching", "blocked"].includes(record.delivery.status); return
{record.status === "skipped" ? "已跳过" : "已回答"}
{record.status === "skipped" ?

已跳过本组可选问题。

:
{record.questions.map((question) => { const answer = record.answers?.find((item) => item.question_id === question.question_id); return
{question.title}
{answer?.selected_options.map((option) =>
)} {answer?.custom_text ?
{answer.selected_options.length ? 补充说明 : null}
: null} {!answer?.selected_options.length && !answer?.custom_text ?

未填写

: null}
; })}
} {entry.error ?

{entry.error}

: null} {entry.conflict ?
查看本窗口未提交的输入,供复制
{JSON.stringify(entry.conflict, null, 2)}
: null} {record.delivery ?
{checking ? "正在核对提问" : deliveries[record.delivery.status]} {retryable ? : null}
: null}
; } export function AgentInteractionRequestCard({ entry, checking, onChange, onAction }: { entry: InteractionRequestEntry; checking: boolean; onChange: (draft: InteractionAnswer[]) => void; onAction: (action: "reply" | "skip" | "cancel" | "resume") => void; }) { const { record } = entry; if (["answered", "skipped"].includes(record.status)) return
onAction("resume")} />
; const pending = record.status === "pending"; const disabled = checking || entry.busy || !pending; const values = entry.draft; const answerFor = (id: string) => values.find((answer) => answer.question_id === id) ?? { question_id: id, selected_option_ids: [], custom_text: "" }; const change = (answer: InteractionAnswer) => onChange(record.questions.map((question) => question.question_id === answer.question_id ? answer : answerFor(question.question_id))); const valid = record.questions.every((question) => !question.required || answerFor(question.question_id).selected_option_ids.length > 0 || (question.allow_custom && answerFor(question.question_id).custom_text.trim().length > 0)); const draftStatus = checking ? "正在核对提问" : entry.saving ? "正在保存草稿" : entry.dirty ? "草稿尚未保存" : entry.draft.some((answer) => answer.selected_option_ids.length || answer.custom_text.trim()) ? "草稿已保存" : "提交后继续处理"; return
{checking ? "核对中" : statuses[record.status]}
{pending ? : null}
{record.questions.map((question) => { const answer = answerFor(question.question_id); const selected = new Set(answer.selected_option_ids); return
{question.title} {pending ? {question.required ? "必填" : "可选"}{question.options.length ? question.mode === "multiple" ? " · 可多选" : " · 单选" : ""} : null} {pending ? <>

{question.body}

{question.options.map((option) => )}
{question.allow_custom ?