feat: 添加 reasoning_content 字段到多个消息结构,支持思考过程展示
This commit is contained in:
parent
0ce89a0e4e
commit
6ff5907616
@ -571,7 +571,8 @@ impl OutboundMessage {
|
||||
"assistant" => {
|
||||
if let Some(tool_calls) = &message.tool_calls {
|
||||
let mut outbound = Vec::new();
|
||||
if !message.content.trim().is_empty() {
|
||||
let has_content_or_reasoning = !message.content.trim().is_empty() || message.reasoning_content.is_some();
|
||||
if has_content_or_reasoning {
|
||||
let mut resp = Self::assistant(
|
||||
channel.to_string(),
|
||||
chat_id.to_string(),
|
||||
@ -585,7 +586,7 @@ impl OutboundMessage {
|
||||
}
|
||||
|
||||
outbound.extend(tool_calls.iter().map(|tool_call| {
|
||||
Self::tool_call(
|
||||
let mut tc = Self::tool_call(
|
||||
channel.to_string(),
|
||||
chat_id.to_string(),
|
||||
session_id.clone(),
|
||||
@ -594,7 +595,9 @@ impl OutboundMessage {
|
||||
tool_call.arguments.clone(),
|
||||
reply_to.clone(),
|
||||
metadata.clone(),
|
||||
)
|
||||
);
|
||||
tc.reasoning_content = message.reasoning_content.clone();
|
||||
tc
|
||||
}));
|
||||
outbound
|
||||
} else {
|
||||
|
||||
@ -762,6 +762,7 @@ fn chat_message_to_ws_outbound(msg: &crate::bus::ChatMessage) -> Option<WsOutbou
|
||||
subagent_task_id: None,
|
||||
topic_id: None,
|
||||
timestamp: Some(msg.timestamp / 1000),
|
||||
reasoning_content: msg.reasoning_content.clone(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -156,6 +156,8 @@ pub enum WsOutbound {
|
||||
topic_id: Option<String>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
timestamp: Option<i64>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
reasoning_content: Option<String>,
|
||||
},
|
||||
#[serde(rename = "tool_result")]
|
||||
ToolResult {
|
||||
|
||||
@ -15,7 +15,8 @@ pub(crate) fn ws_outbound_from_chat_message(message: &ChatMessage) -> Vec<WsOutb
|
||||
"assistant" => {
|
||||
if let Some(tool_calls) = &message.tool_calls {
|
||||
let mut outbound = Vec::new();
|
||||
if !message.content.trim().is_empty() {
|
||||
let has_content_or_reasoning = !message.content.trim().is_empty() || message.reasoning_content.is_some();
|
||||
if has_content_or_reasoning {
|
||||
outbound.push(WsOutbound::AssistantResponse {
|
||||
id: message.id.clone(),
|
||||
content: message.content.clone(),
|
||||
@ -38,6 +39,7 @@ pub(crate) fn ws_outbound_from_chat_message(message: &ChatMessage) -> Vec<WsOutb
|
||||
subagent_task_id: None,
|
||||
topic_id: None,
|
||||
timestamp: None,
|
||||
reasoning_content: message.reasoning_content.clone(),
|
||||
}));
|
||||
outbound
|
||||
} else {
|
||||
@ -126,6 +128,7 @@ pub(crate) fn ws_outbound_from_outbound_message(message: &OutboundMessage) -> Ve
|
||||
subagent_task_id: message.metadata.get("subagent_task_id").cloned(),
|
||||
topic_id: message.metadata.get("topic_id").cloned(),
|
||||
timestamp: Some(crate::protocol::now_timestamp()),
|
||||
reasoning_content: message.reasoning_content.clone(),
|
||||
}],
|
||||
OutboundEventKind::ToolResult => vec![WsOutbound::ToolResult {
|
||||
id: message
|
||||
|
||||
@ -125,6 +125,7 @@ fn test_tool_call_outbound_serialization() {
|
||||
subagent_task_id: None,
|
||||
topic_id: None,
|
||||
timestamp: None,
|
||||
reasoning_content: None,
|
||||
};
|
||||
|
||||
let json = serde_json::to_string(&msg).unwrap();
|
||||
|
||||
@ -242,11 +242,11 @@ function ThinkingSection({ content }: { content: string }) {
|
||||
return (
|
||||
<div className="mb-3 rounded-lg border border-purple-500/20 bg-purple-500/5 overflow-hidden">
|
||||
<button
|
||||
onClick={() => setExpanded(!expanded)}
|
||||
onClick={(e) => { e.stopPropagation(); setExpanded(!expanded) }}
|
||||
className="flex items-center gap-2 w-full px-3 py-2 text-xs text-[var(--text-muted)] hover:text-[var(--text-secondary)] hover:bg-purple-500/5 transition-colors cursor-pointer select-none"
|
||||
>
|
||||
<Brain className="h-3.5 w-3.5 text-purple-400 flex-shrink-0" />
|
||||
<span className="font-medium text-purple-300">思考过程</span>
|
||||
<span className="font-medium text-purple-300">Thinking</span>
|
||||
{expanded ? (
|
||||
<ChevronDown className="h-3 w-3 ml-auto flex-shrink-0" />
|
||||
) : (
|
||||
@ -260,7 +260,7 @@ function ThinkingSection({ content }: { content: string }) {
|
||||
</button>
|
||||
{expanded && (
|
||||
<div className="px-3 py-2 border-t border-purple-500/10 animate-thinking-reveal">
|
||||
<div className="text-xs text-purple-200/80 italic whitespace-pre-wrap leading-relaxed max-h-64 overflow-y-auto scrollbar-thin">
|
||||
<div className="text-xs text-purple-200/80 whitespace-pre-wrap leading-relaxed max-h-64 overflow-y-auto scrollbar-thin">
|
||||
{content}
|
||||
</div>
|
||||
</div>
|
||||
@ -437,6 +437,12 @@ export function MessageBubble({ message, onNavigateToSubAgent }: MessageBubblePr
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* 模型思考内容(工具调用时展示) */}
|
||||
{message.reasoningContent && !toolExpanded && (
|
||||
<div className="px-3 pb-1">
|
||||
<ThinkingSection content={message.reasoningContent} />
|
||||
</div>
|
||||
)}
|
||||
{/* Collapsed preview */}
|
||||
{!toolExpanded && (
|
||||
<>
|
||||
@ -495,6 +501,10 @@ export function MessageBubble({ message, onNavigateToSubAgent }: MessageBubblePr
|
||||
{/* Expanded */}
|
||||
{toolExpanded && (
|
||||
<div className="border-t border-[var(--border-color)] px-3 py-2 space-y-2">
|
||||
{/* 模型思考内容(展开时也展示) */}
|
||||
{message.reasoningContent && (
|
||||
<ThinkingSection content={message.reasoningContent} />
|
||||
)}
|
||||
{taskResult ? (
|
||||
<>
|
||||
{taskPrompt && (
|
||||
@ -646,7 +656,7 @@ export function MessageBubble({ message, onNavigateToSubAgent }: MessageBubblePr
|
||||
{!isTool && message.reasoningContent && (
|
||||
<ThinkingSection content={message.reasoningContent} />
|
||||
)}
|
||||
// AI 和工具消息使用 Markdown 渲染
|
||||
{/* AI 和工具消息使用 Markdown 渲染 */}
|
||||
<div className="markdown-content text-sm leading-relaxed">
|
||||
<ReactMarkdown
|
||||
remarkPlugins={[remarkGfm]}
|
||||
|
||||
@ -210,6 +210,7 @@ export function useChat(): UseChatReturn {
|
||||
toolCallId: msg.tool_call_id,
|
||||
arguments: msg.arguments,
|
||||
subagentTaskId: msg.subagent_task_id,
|
||||
reasoningContent: msg.reasoning_content,
|
||||
}
|
||||
}
|
||||
case 'tool_result': {
|
||||
@ -460,6 +461,7 @@ export function useChat(): UseChatReturn {
|
||||
toolCallId: msg.tool_call_id,
|
||||
arguments: msg.arguments,
|
||||
subagentTaskId: msg.subagent_task_id,
|
||||
reasoningContent: msg.reasoning_content,
|
||||
},
|
||||
])
|
||||
break
|
||||
|
||||
@ -59,6 +59,7 @@ export interface ToolCall {
|
||||
subagent_task_id?: string
|
||||
topic_id?: string
|
||||
timestamp?: number
|
||||
reasoning_content?: string
|
||||
}
|
||||
|
||||
export interface ToolResult {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user