import type { TaskType, Complexity, Domain, TaskClassification } from './routing.types.js'; // ─── Pattern Banks ────────────────────────────────────────────────────────── const CODING_PATTERNS: RegExp[] = [ /\bcode\b/i, /\bfunction\b/i, /\bimplement\b/i, /\bdebug\b/i, /\bfix\b/i, /\brefactor\b/i, /\btypescript\b/i, /\bjavascript\b/i, /\bpython\b/i, /\bSQL\b/i, /\bAPI\b/i, /\bendpoint\b/i, /\bclass\b/i, /\bmethod\b/i, /`[^`]*`/, ]; const RESEARCH_PATTERNS: RegExp[] = [ /\bresearch\b/i, /\bfind\b/i, /\bsearch\b/i, /\bwhat is\b/i, /\bexplain\b/i, /\bhow do(es)?\b/i, /\bcompare\b/i, /\banalyze\b/i, ]; const SUMMARIZATION_PATTERNS: RegExp[] = [ /\bsummariz(e|ation)\b/i, /\bsummary\b/i, /\btldr\b/i, /\bcondense\b/i, /\bbrief\b/i, ]; const CREATIVE_PATTERNS: RegExp[] = [ /\bwrite\b/i, /\bstory\b/i, /\bpoem\b/i, /\bgenerate\b/i, /\bcreate content\b/i, /\bblog post\b/i, ]; const ANALYSIS_PATTERNS: RegExp[] = [ /\banalyze\b/i, /\breview\b/i, /\bevaluate\b/i, /\bassess\b/i, /\baudit\b/i, ]; // ─── Complexity Indicators ─────────────────────────────────────────────────── const COMPLEX_KEYWORDS: RegExp[] = [ /\barchitecture\b/i, /\bdesign\b/i, /\bcomplex\b/i, /\bsystem\b/i, ]; const SIMPLE_QUESTION_PATTERN = /^[^.!?]+[?]$/; /** Counts occurrences of triple-backtick code fences in the message */ function countCodeBlocks(message: string): number { return (message.match(/```/g) ?? []).length / 2; } // ─── Domain Indicators ─────────────────────────────────────────────────────── const FRONTEND_PATTERNS: RegExp[] = [ /\breact\b/i, /\bcss\b/i, /\bhtml\b/i, /\bcomponent\b/i, /\bUI\b/, /\btailwind\b/i, /\bnext\.js\b/i, ]; const BACKEND_PATTERNS: RegExp[] = [ /\bAPI\b/i, /\bserver\b/i, /\bdatabase\b/i, /\bendpoint\b/i, /\bnest(js)?\b/i, /\bexpress\b/i, ]; const DEVOPS_PATTERNS: RegExp[] = [ /\bdocker(file|compose|hub)?\b/i, /\bCI\b/, /\bdeploy\b/i, /\bpipeline\b/i, /\bkubernetes\b/i, ]; const DOCS_PATTERNS: RegExp[] = [/\bdocumentation\b/i, /\breadme\b/i, /\bguide\b/i]; // ─── Helpers ───────────────────────────────────────────────────────────────── function matchesAny(message: string, patterns: RegExp[]): boolean { return patterns.some((p) => p.test(message)); } // ─── Classifier ────────────────────────────────────────────────────────────── /** * Classify a task based on the user's message using deterministic regex/keyword matching. * No LLM calls are made — this is a pure, fast, synchronous classification. */ export function classifyTask(message: string): TaskClassification { return { taskType: detectTaskType(message), complexity: estimateComplexity(message), domain: detectDomain(message), requiredCapabilities: [], }; } function detectTaskType(message: string): TaskType { if (matchesAny(message, CODING_PATTERNS)) return 'coding'; if (matchesAny(message, SUMMARIZATION_PATTERNS)) return 'summarization'; if (matchesAny(message, CREATIVE_PATTERNS)) return 'creative'; if (matchesAny(message, ANALYSIS_PATTERNS)) return 'analysis'; if (matchesAny(message, RESEARCH_PATTERNS)) return 'research'; return 'conversation'; } function estimateComplexity(message: string): Complexity { const trimmed = message.trim(); const codeBlocks = countCodeBlocks(trimmed); // Complex: long messages, multiple code blocks, or complexity keywords if (trimmed.length > 500 || codeBlocks > 1 || matchesAny(trimmed, COMPLEX_KEYWORDS)) { return 'complex'; } // Simple: short messages or a single direct question if (trimmed.length < 100 || SIMPLE_QUESTION_PATTERN.test(trimmed)) { return 'simple'; } return 'moderate'; } function detectDomain(message: string): Domain { if (matchesAny(message, DEVOPS_PATTERNS)) return 'devops'; if (matchesAny(message, DOCS_PATTERNS)) return 'docs'; if (matchesAny(message, FRONTEND_PATTERNS)) return 'frontend'; if (matchesAny(message, BACKEND_PATTERNS)) return 'backend'; return 'general'; }