Files
gongxue-base/apps/admin/src/components/AiChat/message-mappers.ts
wangziqi c72ff2cb8a fix(ai): 清理 aislop 扫描告警
- 拆分 SSE reducer 到 sseReducer.ts,provider.ts 降至 220 行
- artifact 合并工具抽到 uiArtifacts.ts,去除双重类型断言
- 业务上下文注册表改用 field/relation/entity 构建器收敛重复
- aislop 分数 71 → 81(Healthy),AI Slop 0 告警
2026-08-06 15:35:12 +08:00

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,
};
}