UNPKG

cortexweaver

Version:

CortexWeaver is a command-line interface (CLI) tool that orchestrates a swarm of specialized AI agents, powered by Claude Code and Gemini CLI, to assist in software development. It transforms a high-level project plan (plan.md) into a series of coordinate

137 lines 6.37 kB
"use strict"; /** * Query Optimization and Natural Language Processing for Cognitive Canvas Navigator */ Object.defineProperty(exports, "__esModule", { value: true }); exports.QueryOptimizer = void 0; class QueryOptimizer { constructor() { this.optimizationCount = 0; } optimizeQuery(query) { const optimized = { ...query }; if (!this.isQueryTargeted(query)) { optimized.context = { ...optimized.context, limit: 50 }; console.warn('Query optimized: Added limit due to broad scope'); } if (!optimized.filters?.length) { optimized.filters = this.inferFiltersFromQuery(query.query); } optimized.context = this.optimizeQueryContext(optimized.context || {}); this.optimizationCount++; return optimized; } createQueryPlan(query) { let complexity = 'low'; let estimatedCost = 10; const optimizations = []; if ((query.filters?.length || 0) > 3) complexity = 'medium', estimatedCost += 20; if (query.type === 'temporal' || query.type === 'causal') complexity = 'high', estimatedCost += 50; if (!this.isQueryTargeted(query)) complexity = 'high', estimatedCost += 30; if (complexity === 'low') optimizations.push('fast_path'); if (query.context?.limit < 50) optimizations.push('result_limiting'); if (this.isQueryCacheable(query)) optimizations.push('caching_enabled'); return { executionOrder: ['validate', 'cache_check', 'execute', 'optimize_result'], estimatedCost, optimizations, complexity }; } async translateNaturalLanguageToCypher(nlQuery, context = {}) { const semantics = this.analyzeQuerySemantics(nlQuery); let cypher = this.constructCypherQuery({ ...context, ...semantics }, nlQuery); return this.validateCypherSyntax(cypher) ? this.optimizeCypherQuery(cypher) : this.fallbackCypherGeneration(nlQuery, context); } isQueryTargeted(query) { const vagueTerms = ['everything', 'all', 'any', 'find stuff', 'show me']; const hasVagueTerms = vagueTerms.some(term => query.query.toLowerCase().includes(term.toLowerCase())); const hasSpecificCriteria = (query.filters?.length || 0) > 0 || query.context?.nodeType || query.context?.limit < 100 || query.query.length > 15; return !hasVagueTerms && hasSpecificCriteria; } analyzeQuerySemantics(nlQuery) { return { entities: nlQuery.match(/\b[A-Z][a-z]+(?:\s+[A-Z][a-z]+)*\b/g) || [], intent: /find|search|get|show/i.test(nlQuery) ? 'retrieve' : /connect|relate|path/i.test(nlQuery) ? 'path_finding' : /count|how many/i.test(nlQuery) ? 'aggregation' : 'retrieve', hasRelationships: /related to|connected to|depends on/i.test(nlQuery) }; } constructCypherQuery(context, nlQuery) { const nodePattern = context.nodeType ? `(n:${context.nodeType})` : '(n)'; const relPattern = context.hasRelationships && context.relationshipType ? `-[:${context.relationshipType}]-(m)` : ''; const conditions = this.extractAdvancedConditions(nlQuery); const whereClause = conditions.length > 0 ? ' WHERE ' + conditions.map(c => `n.${c.field} ${c.operator} ${c.value}`).join(' AND ') : ''; const returnClause = context.hasRelationships ? ' RETURN n, m' : ' RETURN n'; const limitClause = this.extractLimitFromQuery(nlQuery) ? ` LIMIT ${this.extractLimitFromQuery(nlQuery)}` : ''; return `MATCH ${nodePattern}${relPattern}${whereClause}${returnClause}${limitClause}`; } extractAdvancedConditions(nlQuery) { const patterns = [ [/name\s+(?:is|equals?)\s+["']([^"']+)["']/i, 'name', '=', 1], [/status\s+(?:is|equals?)\s+["']?(\w+)["']?/i, 'status', '=', 1], [/(\w+)\s+(?:greater than|>)\s+(\d+)/i, 1, '>', 2], [/(\w+)\s+(?:less than|<)\s+(\d+)/i, 1, '<', 2], [/created\s+after\s+(\d{4}-\d{2}-\d{2})/i, 'createdAt', '>', 1] ]; return patterns.map(([regex, field, op, group]) => { const match = nlQuery.match(regex); if (!match) return null; const f = typeof field === 'number' ? match[field] : field; const v = match[group]; return { field: f, operator: op, value: isNaN(Number(v)) ? `"${v}"` : v }; }).filter((item) => item !== null); } inferFiltersFromQuery(query) { const filters = []; const nodeTypes = ['user', 'project', 'task', 'document', 'event']; nodeTypes.forEach(type => { if (query.toLowerCase().includes(type)) { filters.push({ type: 'node', field: 'type', operator: 'equals', value: type }); } }); return filters; } optimizeQueryContext(context) { const optimized = { ...context }; if (!optimized.limit) optimized.limit = 100; if (optimized.limit > 500) optimized.limit = 500; return optimized; } isQueryCacheable(query) { const nonCacheableTerms = ['current', 'now', 'today', 'latest', 'my']; return !nonCacheableTerms.some(term => query.query.toLowerCase().includes(term)); } validateCypherSyntax(cypher) { const required = ['MATCH', 'RETURN']; const hasRequired = required.every(kw => cypher.toUpperCase().includes(kw)); const balancedParens = (cypher.match(/\(/g) || []).length === (cypher.match(/\)/g) || []).length; return hasRequired && balancedParens; } fallbackCypherGeneration(nlQuery, context) { return `MATCH (n) WHERE n.name CONTAINS "${nlQuery.toLowerCase()}" RETURN n LIMIT 10`; } optimizeCypherQuery(cypher) { return cypher.replace(/\s+/g, ' ').trim().replace(/RETURN \*/, 'RETURN n'); } extractLimitFromQuery(nlQuery) { const match = nlQuery.match(/(?:limit|top|first)\s+(\d+)/i); return match ? Math.min(parseInt(match[1]), 500) : null; } getOptimizationCount() { return this.optimizationCount; } } exports.QueryOptimizer = QueryOptimizer; //# sourceMappingURL=query-optimizer.js.map