"use client"; import { memo, useMemo } from "react"; import type { ToolCallMessagePartComponent } from "@assistant-ui/react"; import { type OpenCodePermissionRequest, type OpenCodePermissionResponse, type OpenCodeQuestionRequest, type QuestionAnswer, useOpenCodeThreadState, } from "@assistant-ui/react-opencode"; import { CheckCircle2Icon, CircleHelpIcon, LoaderIcon, XCircleIcon, } from "lucide-react"; import { OpenCodePermissionCard } from "@/components/tools/opencode-permission-card"; import { OpenCodeQuestionCard, getQuestionSummary, } from "@/components/tools/opencode-question-card"; type ToolPermissionInteraction = { request: OpenCodePermissionRequest; state: "pending" | "resolved"; reply?: OpenCodePermissionResponse; }; type ToolQuestionInteraction = { request: OpenCodeQuestionRequest; state: "pending" | "answered" | "rejected"; answers?: readonly QuestionAnswer[]; }; const ASK_QUESTION_TOOL_NAMES = [ "ask_question", "request_user_input", "requestUserInput", ] as const; const useOpenCodeToolInteractions = (toolCallId: string) => { const interactions = useOpenCodeThreadState((state) => state.interactions); return useMemo(() => { const permissions: ToolPermissionInteraction[] = []; const questions: ToolQuestionInteraction[] = []; for (const request of Object.values(interactions.permissions.pending)) { if (request.tool?.callID === toolCallId) { permissions.push({ request, state: "pending" }); } } for (const resolved of Object.values(interactions.permissions.resolved)) { if (resolved.request.tool?.callID === toolCallId) { permissions.push({ request: resolved.request, state: "resolved", reply: resolved.reply, }); } } for (const request of Object.values(interactions.questions.pending)) { if (request.tool?.callID === toolCallId) { questions.push({ request, state: "pending" }); } } for (const answered of Object.values(interactions.questions.answered)) { if (answered.request.tool?.callID === toolCallId) { questions.push({ request: answered.request, state: "answered", answers: answered.answers, }); } } for (const rejected of Object.values(interactions.questions.rejected)) { if (rejected.request.tool?.callID === toolCallId) { questions.push({ request: rejected.request, state: "rejected", }); } } return { permissions, questions }; }, [interactions, toolCallId]); }; const ToolInteractionStack = ({ toolCallId }: { toolCallId: string }) => { const { permissions, questions } = useOpenCodeToolInteractions(toolCallId); if (permissions.length === 0 && questions.length === 0) { return null; } return (