const CHINESE_MUTATION_ACTIONS = '设计|创建|生成|添加|增加|新增|修改|调整|编辑|删除|移动|旋转|缩放|布置|装修|建造|搭建|修复' const ENGLISH_MUTATION_ACTIONS = 'design|create|generate|add|modify|change|update|edit|delete|remove|move|rotate|scale|furnish|build|repair|fix' const MUTATION_INTENT = new RegExp( `(?:${CHINESE_MUTATION_ACTIONS}|${ENGLISH_MUTATION_ACTIONS})`, 'i', ) const NEGATED_CHINESE_MUTATION = new RegExp( `(?:不要|请勿|勿|无需|不需要|不用|禁止|避免|不(?:再)?)[^,。;;,.!?!?]{0,32}(?:${CHINESE_MUTATION_ACTIONS})`, 'gi', ) const NEGATED_ENGLISH_MUTATION = new RegExp( `(?:do\\s+not|don't|dont|please\\s+do\\s+not|please\\s+don't|without|avoid)\\s+[^,.!?;]{0,48}(?:${ENGLISH_MUTATION_ACTIONS})`, 'gi', ) function actionableIntentText(text: string): string { return text.replace(NEGATED_CHINESE_MUTATION, ' ').replace(NEGATED_ENGLISH_MUTATION, ' ') } export function requiresPascalMutation(messages: unknown[]): boolean { const latestUserMessage = [...messages] .reverse() .find( (message) => Boolean(message) && typeof message === 'object' && (message as { role?: unknown }).role === 'user', ) as { parts?: unknown } | undefined if (!Array.isArray(latestUserMessage?.parts)) return false const text = latestUserMessage.parts .filter((part): part is { text: string; type: 'text' } => Boolean( part && typeof part === 'object' && (part as { type?: unknown }).type === 'text' && typeof (part as { text?: unknown }).text === 'string', ), ) .map((part) => part.text) .join(' ') return MUTATION_INTENT.test(actionableIntentText(text)) } export function pascalAgentStepPolicy(params: { hasMutation: boolean mutationRequired: boolean mutationToolNames: string[] readOnlyToolNames: string[] stepNumber: number }): { activeTools?: string[]; toolChoice: 'auto' | 'required' } { if (!params.mutationRequired) { return { activeTools: params.readOnlyToolNames, toolChoice: 'auto' } } if (!(params.mutationRequired && !params.hasMutation)) return { toolChoice: 'auto' } if (params.stepNumber < 1) return { toolChoice: 'required' } return { activeTools: params.mutationToolNames, toolChoice: 'required', } }