4677caba01
Many models (especially smaller or non-OpenAI-style ones) do not reliably call the structured final_answer tool, even when the system prompt explicitly requires it. Two visible symptoms in the agent UI: 1. The natural-stop path emits the answer as a final_answer event whose content is wrapped in <answer>...</answer>, <final_answer>...</final_answer>, or prefixed with "Final Answer:" / "最终答案:". These wrappers were rendered verbatim into the answer card. 2. When no answer event arrives at all, the trailing thinking event was surfaced via the legacy fallback but kept its collapsed "思考" card styling instead of rendering as a proper answer. This change adds a small unwrap helper and wires it through the answer rendering path: - New util `unwrapFinalAnswerWrappers` strips conservative outer wrappers (XML-style answer tags, fenced ```final_answer code blocks, and leading "Final Answer:" / "最终答案:" prefixes) only when they cover the entire trimmed content, so user markdown that happens to contain similar text is left alone. - `renderAnswerContent` and `getActualContent` apply the unwrap before the markdown renderer / clipboard copy, so users see and copy clean text. - The legacy "promote trailing thinking to final answer" fallback now synthesizes a virtual answer event so it renders with the answer card UI (expanded markdown + copy/add toolbar) instead of the collapsed thinking card. The promoted thinking event is hidden from the intermediate-steps tree to avoid duplication.