fix(web): keep thinking off the spoken consult and rectification answer
Enumerate evidence kinds so education cannot be proposed as a kind, and stream Chinese thinking on a separate channel that collapses when the reply arrives. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useLayoutEffect, useRef } from "react";
|
||||
import { useEffect, useLayoutEffect, useRef, useState } from "react";
|
||||
|
||||
import { AgentActivityStatus } from "@/components/agent-activity-status";
|
||||
import { prefetchOnIdle } from "@/components/chat-chunk-prefetch";
|
||||
@@ -31,6 +31,30 @@ function motionPreferred() {
|
||||
|
||||
if (motionPreferred()) prefetchOnIdle(loadGsap);
|
||||
|
||||
function MessageThinkingTrace({
|
||||
text,
|
||||
hasAnswer,
|
||||
}: Readonly<{
|
||||
text: string;
|
||||
hasAnswer: boolean;
|
||||
}>) {
|
||||
const [userOpen, setUserOpen] = useState<boolean | null>(null);
|
||||
const open = userOpen ?? !hasAnswer;
|
||||
if (!text.trim()) return null;
|
||||
return (
|
||||
<details
|
||||
className="message-thinking"
|
||||
open={open}
|
||||
onToggle={(event) => {
|
||||
setUserOpen((event.currentTarget as HTMLDetailsElement).open);
|
||||
}}
|
||||
>
|
||||
<summary>思考过程</summary>
|
||||
<div className="message-thinking-body">{text}</div>
|
||||
</details>
|
||||
);
|
||||
}
|
||||
|
||||
export function AgentAvatar() {
|
||||
return <span className="agent-avatar" aria-hidden="true" />;
|
||||
}
|
||||
@@ -104,6 +128,12 @@ export function ChatMessageRow({
|
||||
completedTrail={message.activity?.completedTrail}
|
||||
/>
|
||||
)}
|
||||
{message.thinkingText && (
|
||||
<MessageThinkingTrace
|
||||
text={message.thinkingText}
|
||||
hasAnswer={Boolean(message.text.trim())}
|
||||
/>
|
||||
)}
|
||||
{message.text && (
|
||||
<ChatMessageContent
|
||||
text={message.text}
|
||||
|
||||
@@ -382,6 +382,7 @@ export function RectificationAgenticChat(props: RectificationAgenticChatProps) {
|
||||
setDraft("");
|
||||
|
||||
let raw = "";
|
||||
let thinkingRaw = "";
|
||||
let activityReceiptState = createRectificationActivityReceiptState();
|
||||
let completedReceipt = receiptFromRectificationActivityState(activityReceiptState);
|
||||
let completedTurnId: string | undefined;
|
||||
@@ -465,8 +466,18 @@ export function RectificationAgenticChat(props: RectificationAgenticChatProps) {
|
||||
}),
|
||||
}
|
||||
: message));
|
||||
} else if (event.type === "thinking.delta" && typeof event.text === "string") {
|
||||
thinkingRaw += event.text;
|
||||
setMessages((current) => current.map((message) => message.renderKey === assistantRenderKey
|
||||
? {
|
||||
...message,
|
||||
thinkingText: thinkingRaw,
|
||||
state: raw ? "streaming" : "thinking",
|
||||
}
|
||||
: message));
|
||||
} else if (event.type === "attempt.reset") {
|
||||
raw = "";
|
||||
thinkingRaw = "";
|
||||
activityReceiptState = createRectificationActivityReceiptState();
|
||||
completedReceipt = receiptFromRectificationActivityState(activityReceiptState);
|
||||
completedTurnId = undefined;
|
||||
@@ -474,6 +485,7 @@ export function RectificationAgenticChat(props: RectificationAgenticChatProps) {
|
||||
? {
|
||||
...message,
|
||||
text: "",
|
||||
thinkingText: undefined,
|
||||
state: "thinking",
|
||||
completedReceipt: undefined,
|
||||
failed: false,
|
||||
@@ -806,6 +818,7 @@ export function RectificationAgenticChat(props: RectificationAgenticChatProps) {
|
||||
? {
|
||||
...message,
|
||||
text: "",
|
||||
thinkingText: undefined,
|
||||
state: "thinking" as const,
|
||||
activity: nextActivityView(undefined, {
|
||||
phase: "answer-composition",
|
||||
|
||||
Reference in New Issue
Block a user