UNPKG

vibe-coder-mcp

Version:

Production-ready MCP server with complete agent integration, multi-transport support, and comprehensive development automation tools for AI-assisted workflows.

350 lines (349 loc) 14.7 kB
import { BaseLanguageHandler } from './base.js'; import { getNodeText } from '../astAnalyzer.js'; import logger from '../../../logger.js'; import path from 'path'; export class YamlHandler extends BaseLanguageHandler { options; getFunctionQueryPatterns() { return [ 'block_mapping_pair', 'flow_mapping', 'block_sequence_item' ]; } getClassQueryPatterns() { return [ 'document', 'block_mapping', 'flow_mapping' ]; } getImportQueryPatterns() { return [ 'block_mapping_pair' ]; } extractFunctionName(node, sourceCode, _options) { try { if (node.type === 'block_mapping_pair') { const keyNode = node.childForFieldName('key'); if (keyNode) { const key = getNodeText(keyNode, sourceCode); if (['run', 'script', 'command', 'exec', 'test', 'build', 'deploy'].includes(key)) { return `${key}_command`; } if (this.isInCiCdContext(node, sourceCode)) { return `step_${key}`; } if (this.isKubernetesResource(node, sourceCode)) { const valueNode = node.childForFieldName('value'); if (valueNode) { const nameNode = this.findNameInMapping(valueNode); if (nameNode) { return `${key}_${getNodeText(nameNode, sourceCode)}`; } } return `${key}_resource`; } return key; } } if (node.type === 'block_sequence_item') { if (this.isInCiCdContext(node, sourceCode)) { const valueNode = node.childForFieldName('value'); if (valueNode) { if (valueNode.type === 'block_mapping') { const nameNode = this.findNameInMapping(valueNode); if (nameNode) { return `step_${getNodeText(nameNode, sourceCode)}`; } } } return 'sequence_step'; } return 'sequence_item'; } return 'configuration_item'; } catch (error) { logger.warn({ err: error, nodeType: node.type }, 'Error extracting YAML/Configuration function name'); return 'configuration_item'; } } isInCiCdContext(node, sourceCode) { try { if (this.options?.filePath) { const filename = path.basename(this.options.filePath).toLowerCase(); if (filename.includes('workflow') || filename.includes('pipeline') || filename.includes('ci') || filename.includes('cd') || filename.includes('travis') || filename.includes('jenkins') || filename.includes('gitlab') || filename.includes('github') || filename.includes('azure-pipelines')) { return true; } } let current = node; while (current.parent) { current = current.parent; if (current.type === 'block_mapping') { for (let i = 0; i < current.childCount; i++) { const child = current.child(i); if (child?.type === 'block_mapping_pair') { const keyNode = child.childForFieldName('key'); if (keyNode) { const key = getNodeText(keyNode, sourceCode); if (['jobs', 'stages', 'steps', 'tasks', 'pipeline', 'workflow'].includes(key)) { return true; } } } } } } return false; } catch (error) { logger.warn({ err: error, nodeType: node.type }, 'Error checking if YAML node is in CI/CD context'); return false; } } isKubernetesResource(node, sourceCode) { try { if (this.options?.filePath) { const filename = path.basename(this.options.filePath).toLowerCase(); if (filename.includes('kube') || filename.includes('k8s') || filename.endsWith('.yaml') || filename.endsWith('.yml')) { let current = node; while (current.parent) { current = current.parent; if (current.type === 'block_mapping') { let hasKind = false; let hasApiVersion = false; for (let i = 0; i < current.childCount; i++) { const child = current.child(i); if (child?.type === 'block_mapping_pair') { const keyNode = child.childForFieldName('key'); if (keyNode) { const key = getNodeText(keyNode, sourceCode); if (key === 'kind') hasKind = true; if (key === 'apiVersion') hasApiVersion = true; } } } if (hasKind && hasApiVersion) { return true; } } } } } return false; } catch (error) { logger.warn({ err: error, nodeType: node.type }, 'Error checking if YAML node is a Kubernetes resource'); return false; } } findNameInMapping(node) { try { if (node.type === 'block_mapping') { for (let i = 0; i < node.childCount; i++) { const child = node.child(i); if (child?.type === 'block_mapping_pair') { const keyNode = child.childForFieldName('key'); if (keyNode && ['name', 'id', 'key', 'title'].includes(keyNode.text)) { return child.childForFieldName('value'); } } } } return null; } catch (error) { logger.warn({ err: error, nodeType: node.type }, 'Error finding name in YAML mapping'); return null; } } extractClassName(node, sourceCode) { try { if (node.type === 'document') { const contentNode = node.childForFieldName('content'); if (contentNode?.type === 'block_mapping') { const mapping = contentNode; let kind = null; for (let i = 0; i < mapping.childCount; i++) { const child = mapping.child(i); if (child?.type === 'block_mapping_pair') { const keyNode = child.childForFieldName('key'); if (keyNode && getNodeText(keyNode, sourceCode) === 'kind') { const valueNode = child.childForFieldName('value'); if (valueNode) { kind = getNodeText(valueNode, sourceCode); break; } } } } if (kind) { return `K8s_${kind}`; } } if (this.options?.filePath) { const filename = path.basename(this.options.filePath, path.extname(this.options.filePath)); if (filename.includes('workflow') || filename.includes('pipeline') || filename.includes('ci') || filename.includes('cd')) { return `CI_${filename}`; } } if (this.options?.filePath) { return path.basename(this.options.filePath, path.extname(this.options.filePath)); } } else if (node.type === 'block_mapping' || node.type === 'flow_mapping') { for (let i = 0; i < node.childCount; i++) { const child = node.child(i); if (child?.type === 'block_mapping_pair') { const keyNode = child.childForFieldName('key'); if (keyNode) { const key = getNodeText(keyNode, sourceCode); if (key === 'kind') { const valueNode = child.childForFieldName('value'); if (valueNode) { return getNodeText(valueNode, sourceCode); } } else if (key === 'name') { const valueNode = child.childForFieldName('value'); if (valueNode) { return `Config_${getNodeText(valueNode, sourceCode)}`; } } } } } } return 'Configuration'; } catch (error) { logger.warn({ err: error, nodeType: node.type }, 'Error extracting YAML/Configuration class name'); return 'Configuration'; } } extractImportPath(node, sourceCode) { try { if (node.type === 'block_mapping_pair') { const keyNode = node.childForFieldName('key'); if (keyNode) { const key = getNodeText(keyNode, sourceCode); if (key === 'include' || key === 'import' || key === '$ref' || key === 'extends') { const valueNode = node.childForFieldName('value'); if (valueNode) { return getNodeText(valueNode, sourceCode); } } } } return 'unknown'; } catch (error) { logger.warn({ err: error, nodeType: node.type }, 'Error extracting YAML/Configuration import path'); return 'unknown'; } } extractFunctionComment(node, sourceCode) { try { const current = node; let prev = current.previousNamedSibling; while (prev && prev.type !== 'comment') { prev = prev.previousNamedSibling; } if (prev && prev.type === 'comment') { const commentText = getNodeText(prev, sourceCode); return commentText .replace(/^#\s*/mg, '') .trim(); } return undefined; } catch (error) { logger.warn({ err: error, nodeType: node.type }, 'Error extracting YAML/Configuration function comment'); return undefined; } } extractClassComment(node, sourceCode) { try { if (node.type === 'document') { let firstChild = node.firstChild; while (firstChild && firstChild.type === 'directive') { firstChild = firstChild.nextNamedSibling; } if (firstChild && firstChild.type === 'comment') { const commentText = getNodeText(firstChild, sourceCode); return commentText .replace(/^#\s*/mg, '') .trim(); } } else { const current = node; let prev = current.previousNamedSibling; while (prev && prev.type !== 'comment') { prev = prev.previousNamedSibling; } if (prev && prev.type === 'comment') { const commentText = getNodeText(prev, sourceCode); return commentText .replace(/^#\s*/mg, '') .trim(); } } return undefined; } catch (error) { logger.warn({ err: error, nodeType: node.type }, 'Error extracting YAML/Configuration class comment'); return undefined; } } detectFramework(sourceCode) { try { if (sourceCode.includes('apiVersion:') && sourceCode.includes('kind:') && (sourceCode.includes('metadata:') || sourceCode.includes('spec:'))) { return 'kubernetes'; } if (sourceCode.includes('name:') && sourceCode.includes('on:') && sourceCode.includes('jobs:')) { return 'github-actions'; } if (sourceCode.includes('version:') && sourceCode.includes('services:') && (sourceCode.includes('image:') || sourceCode.includes('build:'))) { return 'docker-compose'; } if (sourceCode.includes('stages:') && (sourceCode.includes('script:') || sourceCode.includes('image:'))) { return 'gitlab-ci'; } if (sourceCode.includes('language:') && (sourceCode.includes('script:') || sourceCode.includes('before_script:'))) { return 'travis-ci'; } return null; } catch (error) { logger.warn({ err: error }, 'Error detecting YAML/Configuration framework'); return null; } } }