Version: 0.8.1.dev.260326

后端:
1.获取agent聊天历史记录接口做了如下更改:
(1)对reasoning_content也做了存储,同步更改了mysql和redis缓存的读写逻辑
(2)为了承接前端的重试/修改消息的逻辑,进行了一些代码和表单上的改动
前端:
1.agent页面新增了很多小组件,改善交互体验
2.新增重试消息/修改消息并重新发送功能,前者有bug,可能前后端都有问题,待修复。
This commit is contained in:
Losita
2026-03-26 22:15:16 +08:00
parent ddf4c09f69
commit ddb0d9cc17
13 changed files with 1828 additions and 322 deletions

View File

@@ -10,7 +10,11 @@ export interface ConversationHistoryMessage {
role: 'user' | 'assistant' | 'system'
content: string
created_at?: string | null
reasoning_content?: string
reasoning_content?: string | null
reasoning_duration_seconds?: number | null
retry_group_id?: string | null
retry_index?: number | null
retry_total?: number | null
}
export interface ConversationListQuery {
@@ -19,9 +23,46 @@ export interface ConversationListQuery {
status?: 'active' | 'archived'
}
function normalizeConversationHistoryMessage(raw: unknown): ConversationHistoryMessage | null {
if (!raw || typeof raw !== 'object') {
return null
}
const candidate = raw as Record<string, unknown>
const role = candidate.role
const content = candidate.content
if ((role !== 'user' && role !== 'assistant' && role !== 'system') || typeof content !== 'string') {
return null
}
// 1. 按 openapi 优先读取 reasoning_content兼容后端历史接口新增的思考存储字段。
// 2. 若后端灰度期间仍返回 legacy reasoning 字段,这里也做一次前端兜底兼容。
// 3. 统一归一化成 string/null避免页面层反复做类型分支判断。
const normalizedReasoning =
typeof candidate.reasoning_content === 'string'
? candidate.reasoning_content
: typeof candidate.reasoning === 'string'
? candidate.reasoning
: null
return {
id: typeof candidate.id === 'string' || typeof candidate.id === 'number' ? candidate.id : undefined,
role,
content,
created_at: typeof candidate.created_at === 'string' ? candidate.created_at : null,
reasoning_content: normalizedReasoning,
reasoning_duration_seconds:
typeof candidate.reasoning_duration_seconds === 'number' ? candidate.reasoning_duration_seconds : null,
retry_group_id: typeof candidate.retry_group_id === 'string' ? candidate.retry_group_id : null,
retry_index: typeof candidate.retry_index === 'number' ? candidate.retry_index : null,
retry_total: typeof candidate.retry_total === 'number' ? candidate.retry_total : null,
}
}
// getConversationList 负责按 openapi 约定读取会话列表分页。
// 职责边界:
// 1. 负责把前端分页参数映射为后端要求的 page/limit
// 1. 负责把前端分页参数映射为后端要求的 page/page_size
// 2. 不负责前端滚动懒加载时的合并、去重和选中逻辑。
// 3. 接口失败时统一抛出中文错误,便于页面层直接提示。
export async function getConversationList(options: ConversationListQuery = {}) {
@@ -31,6 +72,7 @@ export async function getConversationList(options: ConversationListQuery = {}) {
const response = await http.get<ApiResponse<ConversationListResponse>>('/agent/conversation-list', {
params: {
page,
page_size: pageSize,
limit: pageSize,
status,
},
@@ -61,7 +103,9 @@ export async function getConversationHistory(conversationId: string) {
conversation_id: conversationId,
},
})
return response.data.data ?? []
return (response.data.data ?? [])
.map(normalizeConversationHistoryMessage)
.filter((message): message is ConversationHistoryMessage => Boolean(message))
} catch (error) {
throw new Error(extractErrorMessage(error, '会话消息加载失败,请稍后重试'))
}