import type { EngineChatTool } from '../engine'; import { AGENT_TOOLS, HTML_ARTIFACT_TOOL } from './agent-tools'; import { DEFAULT_MAX_TOKENS } from './runtime-defaults'; export const HTML_ARTIFACT_MIN_TOKENS = DEFAULT_MAX_TOKENS; const CREATION_VERB = /(?:\b(?:build|code|create|design|develop|generate|implement|make|write)\b|(?:созда(?:й|йте)|сдела(?:й|йте)|напиш(?:и|ите)|сгенерир(?:уй|уйте)|сверста(?:й|йте)|реализ(?:уй|уйте)|разработа(?:й|йте)|собер(?:и|ите)|постро(?:й|йте)))/iu; const HTML_PRODUCT_TARGET = /(?:\bweb[\s-]?(?:app|application|page|site)\b|\bwebsite\b|\blanding[\s-]?page\b|(?:веб|html)[\s-]?(?:приложени\w*|страниц\w*|сайт\w*|интерфейс\w*)|(?:^|[\s,.:;!?])(?:сайт\w*|лендинг\w*))/iu; const HTML_LANGUAGE_TARGET = /\bhtml\b/iu; const DISCUSSION_REQUEST = /(?:\b(?:about|article|describe|discuss|explain|review|standard)\b|(?:объясн\w*|расскаж\w*|что\s+такое|кратко\s+о|о\s+стандарт\w*|обзор\w*|стать\w*))/iu; export interface ClientToolPlan { tools?: EngineChatTool[]; toolChoice: 'none' | 'auto' | 'required'; minimumMaxTokens: number; requiredToolName?: string; systemInstruction?: string; } export function requestsHtmlArtifact(prompt: string): boolean { if (!CREATION_VERB.test(prompt)) return false; if (HTML_PRODUCT_TARGET.test(prompt)) return true; return HTML_LANGUAGE_TARGET.test(prompt) && !DISCUSSION_REQUEST.test(prompt); } export function planClientTools(prompt: string, enabled: boolean, completedToolRounds: number): ClientToolPlan { if (!enabled) { return { toolChoice: 'none', minimumMaxTokens: 0 }; } if (!requestsHtmlArtifact(prompt)) { return { tools: AGENT_TOOLS, toolChoice: 'auto', minimumMaxTokens: 0 }; } if (completedToolRounds > 0) { return { toolChoice: 'none', minimumMaxTokens: 0 }; } return { tools: [HTML_ARTIFACT_TOOL], toolChoice: 'required', minimumMaxTokens: HTML_ARTIFACT_MIN_TOKENS, requiredToolName: HTML_ARTIFACT_TOOL.function.name, systemInstruction: 'The user explicitly requested an HTML artifact. Call html_artifact exactly once with complete, self-contained HTML and CSS. Keep the source compact enough to finish within the completion budget. Do not answer with a Markdown code block instead.', }; }