feat(ai): 业务上下文感知与 A2UI 链路统一
- 新增代码内业务上下文元数据层(实体字典 + 三大闭环工作流) - 新增 get_business_context / get_entity_schema / get_pending_tasks 运行时工具 - SYSTEM_PROMPT 与技能目录改为先查业务流程/待办再执行 - A2UI 增加 ai_a2ui_submissions 幂等表、表单过期、ui.artifact 事件 - 提交回灌携带 submissionId / fieldErrors / 下一步建议 - 前端 uiArtifacts 归一化与过期表单禁用
This commit is contained in:
@@ -3,21 +3,35 @@ import type { AiChatServiceContext } from './ai-chat.types';
|
||||
|
||||
export function a2uiSubmitInfo(
|
||||
metadata: Record<string, unknown> | null,
|
||||
): { title: string; values: Record<string, unknown> } | null {
|
||||
): {
|
||||
formId: string;
|
||||
title: string;
|
||||
values: Record<string, unknown>;
|
||||
submissionId?: string;
|
||||
fieldErrors?: Array<{ field: string; message: string }>;
|
||||
} | null {
|
||||
const submit = metadata?.a2uiSubmit;
|
||||
if (!submit || typeof submit !== 'object' || Array.isArray(submit)) return null;
|
||||
const record = submit as Record<string, unknown>;
|
||||
const formId = typeof record.formId === 'string' ? record.formId : '';
|
||||
const title = typeof record.formTitle === 'string' ? record.formTitle : '表单';
|
||||
const values =
|
||||
record.values && typeof record.values === 'object' && !Array.isArray(record.values)
|
||||
? (record.values as Record<string, unknown>)
|
||||
: {};
|
||||
return { title, values };
|
||||
const submissionId =
|
||||
typeof record.submissionId === 'string' ? record.submissionId : undefined;
|
||||
const fieldErrors = Array.isArray(record.fieldErrors)
|
||||
? (record.fieldErrors as Array<{ field: string; message: string }>)
|
||||
: [];
|
||||
return { formId, title, values, submissionId, fieldErrors };
|
||||
}
|
||||
|
||||
export function buildFormSubmitModelContent(submit: {
|
||||
title: string;
|
||||
values: Record<string, unknown>;
|
||||
submissionId?: string;
|
||||
fieldErrors?: Array<{ field: string; message: string }>;
|
||||
}): string {
|
||||
let json: string;
|
||||
try {
|
||||
@@ -25,7 +39,11 @@ export function buildFormSubmitModelContent(submit: {
|
||||
} catch {
|
||||
json = '[无法序列化]';
|
||||
}
|
||||
return `【表单提交:${submit.title}】\n提交值(JSON):${json.slice(0, 32 * 1024)}\n用户已在表单中确认,你可以执行允许的写操作工具。`;
|
||||
const submissionId = submit.submissionId ? `\n提交ID:${submit.submissionId}` : '';
|
||||
const fieldErrors = submit.fieldErrors?.length
|
||||
? `\nfieldErrors: ${JSON.stringify(submit.fieldErrors)}`
|
||||
: '\nfieldErrors: []';
|
||||
return `【表单提交:${submit.title}】${submissionId}\n提交值(JSON):${json.slice(0, 32 * 1024)}${fieldErrors}\n用户已在表单中确认,你可以执行允许的写操作工具。`;
|
||||
}
|
||||
|
||||
export async function markFormSubmittedOnMessage(
|
||||
@@ -48,15 +66,28 @@ export async function markFormSubmittedOnMessage(
|
||||
|
||||
export function a2uiReviewSubmitInfo(
|
||||
metadata: Record<string, unknown> | null,
|
||||
): { reviewId: string; reviewTitle: string; resultMessage: string } | null {
|
||||
): {
|
||||
reviewId: string;
|
||||
reviewTitle: string;
|
||||
resultMessage: string;
|
||||
submissionId?: string;
|
||||
nextSteps?: Array<{ key: string; label: string }>;
|
||||
} | null {
|
||||
const submit = metadata?.a2uiReviewSubmit;
|
||||
if (!submit || typeof submit !== 'object' || Array.isArray(submit)) return null;
|
||||
const record = submit as Record<string, unknown>;
|
||||
if (typeof record.reviewId !== 'string') return null;
|
||||
const submissionId =
|
||||
typeof record.submissionId === 'string' ? record.submissionId : undefined;
|
||||
const nextSteps = Array.isArray(record.nextSteps)
|
||||
? (record.nextSteps as Array<{ key: string; label: string }>)
|
||||
: [];
|
||||
return {
|
||||
reviewId: record.reviewId,
|
||||
reviewTitle: typeof record.reviewTitle === 'string' ? record.reviewTitle : '批量导入',
|
||||
resultMessage: typeof record.resultMessage === 'string' ? record.resultMessage : '导入已完成',
|
||||
submissionId,
|
||||
nextSteps,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -64,8 +95,14 @@ export function buildReviewSubmitModelContent(submit: {
|
||||
reviewId: string;
|
||||
reviewTitle: string;
|
||||
resultMessage: string;
|
||||
submissionId?: string;
|
||||
nextSteps?: Array<{ key: string; label: string }>;
|
||||
}): string {
|
||||
return `【批量导入已确认:${submit.reviewTitle}】\n${submit.resultMessage}\n数据已由系统入库,不要再次调用写入工具,直接向用户汇报导入结果即可。`;
|
||||
const submissionId = submit.submissionId ? `\n提交ID:${submit.submissionId}` : '';
|
||||
const nextSteps = submit.nextSteps?.length
|
||||
? `\n下一步建议:${submit.nextSteps.map((step) => step.label).join(';')}`
|
||||
: '';
|
||||
return `【批量导入已确认:${submit.reviewTitle}】${submissionId}\n${submit.resultMessage}${nextSteps}\n数据已由系统入库,不要再次调用写入工具,直接向用户汇报导入结果即可。`;
|
||||
}
|
||||
|
||||
export async function markReviewSubmittedOnMessage(
|
||||
|
||||
Reference in New Issue
Block a user