- 拆分 SSE reducer 到 sseReducer.ts,provider.ts 降至 220 行 - artifact 合并工具抽到 uiArtifacts.ts,去除双重类型断言 - 业务上下文注册表改用 field/relation/entity 构建器收敛重复 - aislop 分数 71 → 81(Healthy),AI Slop 0 告警
92 lines
3.0 KiB
TypeScript
92 lines
3.0 KiB
TypeScript
import type { MessageInfo } from '@ant-design/x-sdk';
|
|
import type {
|
|
AiChatMessage,
|
|
AiChatMessageStatus,
|
|
AiChartSchema,
|
|
AiArtifactSchema,
|
|
AiFormSchema,
|
|
AiMessageRecord,
|
|
AiReviewSchema,
|
|
AiToolRun,
|
|
} from './types';
|
|
import { mergeArtifactIntoMessage } from './uiArtifacts';
|
|
|
|
function mapStatus(record: AiMessageRecord): AiChatMessageStatus {
|
|
if (record.status === 'pending') return 'loading';
|
|
if (record.status === 'failed') return 'error';
|
|
if (record.status === 'cancelled') return 'abort';
|
|
return record.role === 'user' ? 'local' : 'success';
|
|
}
|
|
|
|
function normalizeToolRun(tool: AiToolRun): AiToolRun {
|
|
return {
|
|
...tool,
|
|
status: tool.status === 'error' ? 'failed' : tool.status,
|
|
summary: tool.resultSummary ?? tool.argumentsSummary ?? tool.summary,
|
|
};
|
|
}
|
|
|
|
function historyForms(record: AiMessageRecord): AiFormSchema[] | undefined {
|
|
const a2uiForm = record.metadata?.a2uiForm;
|
|
if (!a2uiForm || typeof a2uiForm !== 'object' || Array.isArray(a2uiForm)) return undefined;
|
|
return [a2uiForm as AiFormSchema];
|
|
}
|
|
|
|
function historyReviews(record: AiMessageRecord): AiReviewSchema[] | undefined {
|
|
const a2uiReview = record.metadata?.a2uiReview;
|
|
if (!a2uiReview || typeof a2uiReview !== 'object' || Array.isArray(a2uiReview)) {
|
|
return undefined;
|
|
}
|
|
return [a2uiReview as AiReviewSchema];
|
|
}
|
|
|
|
function historyCharts(record: AiMessageRecord): AiChartSchema[] | undefined {
|
|
const a2uiChart = record.metadata?.a2uiChart;
|
|
if (Array.isArray(a2uiChart)) {
|
|
return a2uiChart.filter(
|
|
(item): item is AiChartSchema =>
|
|
Boolean(item) && typeof item === 'object' && typeof (item as AiChartSchema).id === 'string',
|
|
);
|
|
}
|
|
if (!a2uiChart || typeof a2uiChart !== 'object') return undefined;
|
|
return [a2uiChart as AiChartSchema];
|
|
}
|
|
|
|
function historyArtifacts(record: AiMessageRecord) {
|
|
const artifacts = record.metadata?.uiArtifacts;
|
|
if (!Array.isArray(artifacts)) return undefined;
|
|
return artifacts.filter(
|
|
(item): item is AiArtifactSchema =>
|
|
Boolean(item) && typeof item === 'object' && typeof (item as AiArtifactSchema).id === 'string',
|
|
);
|
|
}
|
|
|
|
export function mapHistoryMessage(record: AiMessageRecord): MessageInfo<AiChatMessage> {
|
|
const artifacts = historyArtifacts(record);
|
|
const baseMessage = {
|
|
id: record.id,
|
|
role: record.role,
|
|
content: record.content || '',
|
|
reasoningContent: record.reasoningContent || '',
|
|
toolRuns: (record.toolRuns || []).map(normalizeToolRun),
|
|
attachments: record.attachments ?? [],
|
|
forms: historyForms(record),
|
|
reviews: historyReviews(record),
|
|
charts: historyCharts(record),
|
|
replyToMessageId: record.replyToMessageId,
|
|
metadata: record.metadata,
|
|
error: record.status === 'failed' ? record.errorCode || 'AI 回答生成失败' : undefined,
|
|
cancelled: record.status === 'cancelled',
|
|
};
|
|
if (artifacts) {
|
|
for (const artifact of artifacts) {
|
|
mergeArtifactIntoMessage(baseMessage as AiChatMessage, artifact);
|
|
}
|
|
}
|
|
return {
|
|
id: record.id,
|
|
status: mapStatus(record),
|
|
message: baseMessage as AiChatMessage,
|
|
};
|
|
}
|