后端:
- server: 实现完整的 HTTP 会话管理(CRUD)+ SSE 事件流推送,
支持双通道架构(POST 发消息 + GET SSE 接收流式响应)
- runtime: ContentBlock 新增 Thinking / RedactedThinking 变体,
支持思考过程和已编辑思考的序列化/反序列化
- api: 注册 GLM 系列模型(glm-4/5 等)到模型注册表,
扩展 XAI/OpenAI 兼容提供商的请求构建逻辑
前端:
- 基于 Ant Design X 构建完整聊天界面:Bubble.List 消息列表、
Sender 输入框、Conversations 会话管理、Think 思考过程折叠、
ThoughtChain 工具调用链展示
- XMarkdown 集成:代码高亮、Mermaid 图表、LaTeX 公式、
自定义脚注、流式渲染(incomplete 占位符)
- SSE Hook 对接服务端事件流,手动管理 AssistantBuffer 累积 delta
- 深色/浅色主题切换,会话侧边栏(新建/切换/删除)
86 lines
2.2 KiB
TypeScript
86 lines
2.2 KiB
TypeScript
import React from 'react';
|
|
import { ThoughtChain } from '@ant-design/x';
|
|
|
|
interface ToolCall {
|
|
id: string;
|
|
name: string;
|
|
input: string;
|
|
output?: string;
|
|
isError?: boolean;
|
|
}
|
|
|
|
interface ToolChainProps {
|
|
tools: ToolCall[];
|
|
}
|
|
|
|
const ToolChain: React.FC<ToolChainProps> = ({ tools }) => {
|
|
const items = tools.map((tool) => {
|
|
const hasResult = tool.output !== undefined;
|
|
let status: 'loading' | 'success' | 'error' = 'loading';
|
|
if (hasResult) {
|
|
status = tool.isError ? 'error' : 'success';
|
|
}
|
|
|
|
return {
|
|
key: tool.id,
|
|
status,
|
|
title: tool.name,
|
|
description: hasResult ? (tool.isError ? '执行出错' : '执行完成') : '执行中...',
|
|
collapsible: true,
|
|
content: (
|
|
<div style={{ fontSize: 13 }}>
|
|
{tool.input && (
|
|
<div style={{ marginBottom: 8 }}>
|
|
<div style={{ fontWeight: 500, marginBottom: 4 }}>输入</div>
|
|
<pre style={{
|
|
margin: 0,
|
|
padding: 8,
|
|
borderRadius: 6,
|
|
background: 'rgba(0,0,0,0.04)',
|
|
overflow: 'auto',
|
|
maxHeight: 200,
|
|
fontSize: 12,
|
|
}}>
|
|
{tryFormatJSON(tool.input)}
|
|
</pre>
|
|
</div>
|
|
)}
|
|
{tool.output !== undefined && (
|
|
<div>
|
|
<div style={{ fontWeight: 500, marginBottom: 4 }}>
|
|
{tool.isError ? '错误' : '输出'}
|
|
</div>
|
|
<pre style={{
|
|
margin: 0,
|
|
padding: 8,
|
|
borderRadius: 6,
|
|
background: tool.isError ? 'rgba(255,0,0,0.04)' : 'rgba(0,0,0,0.04)',
|
|
overflow: 'auto',
|
|
maxHeight: 300,
|
|
fontSize: 12,
|
|
}}>
|
|
{tool.output}
|
|
</pre>
|
|
</div>
|
|
)}
|
|
</div>
|
|
),
|
|
};
|
|
});
|
|
|
|
if (items.length === 0) return null;
|
|
|
|
return <ThoughtChain items={items} />;
|
|
};
|
|
|
|
function tryFormatJSON(str: string): string {
|
|
try {
|
|
return JSON.stringify(JSON.parse(str), null, 2);
|
|
} catch {
|
|
return str;
|
|
}
|
|
}
|
|
|
|
export default ToolChain;
|
|
export type { ToolCall };
|