import type { AgentInfo, AgentInteractionConfig, AgentValidationIssue, } from './types'; export const MAX_WELCOME_MESSAGE_LENGTH = 300; export const MAX_SUGGESTED_QUESTION_COUNT = 6; export const MAX_SUGGESTED_QUESTION_LENGTH = 80; export const MAX_INPUT_PLACEHOLDER_LENGTH = 40; export const DEFAULT_INPUT_PLACEHOLDER = '输入消息'; export function createEmptyInteractionConfig(): AgentInteractionConfig { return { inputPlaceholder: '', suggestedQuestions: [], welcomeMessage: '', }; } export function normalizeInteractionConfig( source?: Partial | Record, ): AgentInteractionConfig { return { inputPlaceholder: typeof source?.inputPlaceholder === 'string' ? source.inputPlaceholder : '', suggestedQuestions: Array.isArray(source?.suggestedQuestions) ? source.suggestedQuestions.filter( (question): question is string => typeof question === 'string', ) : [], welcomeMessage: typeof source?.welcomeMessage === 'string' ? source.welcomeMessage : '', }; } export function buildInteractionConfigPayload( source?: Partial | Record, ): AgentInteractionConfig { const normalized = normalizeInteractionConfig(source); return { inputPlaceholder: normalized.inputPlaceholder.trim(), suggestedQuestions: normalized.suggestedQuestions .map((question) => question.trim()) .filter(Boolean), welcomeMessage: normalized.welcomeMessage.trim(), }; } export function resolveInteractionDisplay( agent?: Pick, ) { const config = buildInteractionConfigPayload(agent?.interactionConfigJson); const agentName = String(agent?.name || '').trim() || '智能体'; return { inputPlaceholder: config.inputPlaceholder || DEFAULT_INPUT_PLACEHOLDER, suggestedQuestions: config.suggestedQuestions, welcomeMessage: config.welcomeMessage || `你好,我是 ${agentName},有什么可以帮你?`, }; } export function validateInteractionConfig( source?: Partial | Record, ): AgentValidationIssue[] { const config = normalizeInteractionConfig(source); const issues: AgentValidationIssue[] = []; if (config.welcomeMessage.trim().length > MAX_WELCOME_MESSAGE_LENGTH) { issues.push({ field: 'interaction.welcomeMessage', message: '欢迎语不能超过 300 个字符', nodeId: 'agent-base', }); } if (/\r|\n/.test(config.inputPlaceholder)) { issues.push({ field: 'interaction.inputPlaceholder', message: '输入提示仅支持单行文本', nodeId: 'agent-base', }); } else if ( config.inputPlaceholder.trim().length > MAX_INPUT_PLACEHOLDER_LENGTH ) { issues.push({ field: 'interaction.inputPlaceholder', message: '输入提示不能超过 40 个字符', nodeId: 'agent-base', }); } const questions = config.suggestedQuestions .map((question, index) => ({ index, value: question.trim() })) .filter((item) => item.value); if (questions.length > MAX_SUGGESTED_QUESTION_COUNT) { issues.push({ field: 'interaction.suggestedQuestions', message: '猜你想问最多配置 6 条', nodeId: 'agent-base', }); } const seenQuestions = new Set(); for (const question of questions) { if (question.value.length > MAX_SUGGESTED_QUESTION_LENGTH) { issues.push({ field: `interaction.suggestedQuestions.${question.index}`, message: `第 ${question.index + 1} 条猜你想问不能超过 80 个字符`, nodeId: 'agent-base', }); } if (seenQuestions.has(question.value)) { issues.push({ field: `interaction.suggestedQuestions.${question.index}`, message: `第 ${question.index + 1} 条猜你想问与已有内容重复`, nodeId: 'agent-base', }); } seenQuestions.add(question.value); } return issues; }