feat(ai): 移除 Excel 导入预检链路

- 删除 preflight_import 工具、预检卡、resolve 接口与 ui.import_preflight 事件
- 删除 imports.preflight 解析器与 PreflightReport 类型
- SYSTEM_PROMPT 改为上传 Excel 后直接确认列映射/策略并调用 start_import_wizard
- 前端同步移除预检类型/组件/测试,保留导入向导
This commit is contained in:
2026-08-06 15:50:38 +08:00
parent 14db28afc6
commit 9048816abc
29 changed files with 14 additions and 2914 deletions

View File

@@ -2,7 +2,6 @@ import {
IMPORT_STEP_KEYS,
type ImportStageRequest,
type ImportStepKey,
type PreflightReport,
} from '../imports/imports.types';
import { permittedStepKeys } from '../imports/imports.access';
import { expandStageSheets } from '../imports/imports.mapping';
@@ -100,76 +99,13 @@ type ImportToolExecutor = (
) => Promise<string>;
function makeImportToolExecutor(
toolName: 'preflight_import' | 'start_import_wizard',
toolName: 'start_import_wizard',
handler: (tool: ImportToolContext) => Promise<string>,
): ImportToolExecutor {
return (context, messageId, call, agentContext, emit) =>
runImportTool(context, messageId, call, agentContext, emit, toolName, handler);
}
export const executePreflightImport = makeImportToolExecutor(
'preflight_import',
async ({ run, parsedArgs, startedAt, assistant, agentContext: ac, context, call, emit, messageId }) => {
const { parsedRecord, attachmentId } = parseAttachmentArgs(parsedArgs);
const headerRow =
parsedRecord.headerRow === undefined ? 1 : Number(parsedRecord.headerRow);
if (!Number.isInteger(headerRow) || headerRow < 1 || headerRow > 1000) {
throw new Error('headerRow 必须是 1-1000 之间的整数');
}
const [attachment] = await context.attachmentService.requireReadyOwned(ac.userId, [
attachmentId as number,
]);
if (!isExcelAttachment(attachment)) {
throw new Error('附件不是 Excel 文件,无法预检导入');
}
if (!context.importsService) throw new Error('导入预检服务未配置');
const buffer = await context.attachmentService.readStoredBuffer(attachment);
const preflight: PreflightReport = await context.importsService.preflightFile({
originalName: attachment.originalName,
mimeType: attachment.mimeType,
size: attachment.size,
buffer,
}, headerRow);
const permittedSteps = permittedStepKeys({
id: ac.userId,
permissions: [...ac.permissions],
isSuperAdmin: ac.isSuperAdmin,
});
const preflightCard: PreflightReport = {
...preflight,
attachmentId: attachment.id,
headerRow,
permittedSteps,
resolved: false,
runId: null,
};
assistant.metadata = {
...assistant.metadata,
a2uiImportPreflight: preflightCard,
};
await context.messages.save(assistant);
await finishToolRun(context, run, call, startedAt, {
status: 'success',
summary: `已完成导入预检:${preflight.stages
.map((stage) => `${stage.label} ${stage.total}`)
.join('、') || '未识别到可导入阶段'}`,
}, emit);
emit('ui.import_preflight', { messageId, preflight: preflightCard });
emit('ui.artifact', {
messageId,
artifact: buildA2uiArtifact({
type: 'import_preflight',
id: `preflight-${attachment.id}`,
status: 'pending',
messageId,
conversationId: assistant.conversationId,
payload: preflightCard,
}),
});
return preflightModelPayload(preflight, permittedSteps);
});
export const executeStartImportWizard = makeImportToolExecutor(
'start_import_wizard',
async ({ run, parsedArgs, startedAt, assistant, agentContext: ac, context, call, emit, messageId }) => {
@@ -219,18 +155,8 @@ export const executeStartImportWizard = makeImportToolExecutor(
settings,
);
const wizard = compactImportWizard(detail);
const preflightMeta = assistant.metadata?.a2uiImportPreflight;
assistant.metadata = {
...assistant.metadata,
...(preflightMeta && typeof preflightMeta === 'object' && !Array.isArray(preflightMeta)
? {
a2uiImportPreflight: {
...(preflightMeta as Record<string, unknown>),
resolved: true,
runId: detail.id,
},
}
: {}),
a2uiImportWizard: wizard,
};
await context.messages.save(assistant);
@@ -242,16 +168,6 @@ export const executeStartImportWizard = makeImportToolExecutor(
.map((step) => step.label)
.join('、')}`,
}, emit);
if (preflightMeta && typeof preflightMeta === 'object' && !Array.isArray(preflightMeta)) {
emit('ui.import_preflight', {
messageId,
preflight: {
...(preflightMeta as Record<string, unknown>),
resolved: true,
runId: detail.id,
},
});
}
emit('ui.import_wizard', { messageId, wizard });
emit('ui.artifact', {
messageId,
@@ -279,46 +195,6 @@ export const executeStartImportWizard = makeImportToolExecutor(
});
});
function preflightModelPayload(
report: PreflightReport,
permittedSteps: ImportStepKey[],
): string {
const guidance =
'预检报告已以卡片展示:请引导用户在卡内确认列映射与策略并点击「生成导入向导」;' +
'仅当用户在聊天文本中显式给出确认时才调用 start_import_wizard';
const fullPayload = JSON.stringify({
status: 'success',
report,
permittedSteps,
message: guidance,
});
if (fullPayload.length <= 32 * 1024) return fullPayload;
return JSON.stringify({
status: 'success',
truncated: true,
report: {
verdict: report.verdict,
stages: report.stages.map((stage) => ({
stepKey: stage.stepKey,
label: stage.label,
sheetNames: stage.sheetNames,
total: stage.total,
create: stage.create,
update: stage.update,
error: stage.error,
skip: stage.skip,
mapping: stage.mapping,
missingRequired: stage.missingRequired,
})),
questions: report.questions,
errorSamples: report.errorSamples.slice(0, 10),
nextSteps: report.nextSteps,
},
permittedSteps,
message: guidance,
});
}
export function compactImportWizard(detail: any): {
runId: string;
fileName: string;