import { requireAuth } from '~/server/utils/auth' import { prisma } from '~/server/utils/prisma' import { generateAIResponse } from '~/server/utils/ai' export default defineEventHandler(async (event) => { const user = requireAuth(event) const nodeId = getRouterParam(event, 'id') const body = await readBody(event) const { canvasId, context } = body console.log(`[Execute] nodeId=${nodeId} canvasId=${canvasId} userId=${user.id}`) if (!nodeId || !canvasId) { throw createError({ statusCode: 400, message: 'Node ID and Canvas ID are required' }) } // 1. Найти холст и убедиться в правах доступа const canvas = await prisma.canvas.findUnique({ where: { id: canvasId } }) console.log(`[Execute] Canvas found: ${!!canvas}, nodes count: ${(canvas?.nodes as any[])?.length}`) if (!canvas) { throw createError({ statusCode: 404, message: 'Canvas not found' }) } // Проверка прав (владелец или админ) if (canvas.ownerId !== user.id && user.role !== 'admin') { throw createError({ statusCode: 403, message: 'Access denied' }) } // 2. Найти конкретный узел в JSON холста const nodes = (canvas.nodes as any[]) || [] const nodeIdx = nodes.findIndex(n => n.id === nodeId) console.log(`[Execute] Node found at index: ${nodeIdx}`) if (nodeIdx === -1) { throw createError({ statusCode: 404, message: `Node ${nodeId} not found in canvas ${canvasId}` }) } const node = nodes[nodeIdx] console.log(`[Execute] Node type: ${node.type}`) try { let result = '' if (node.type === 'ai') { // Формируем промпт с учетом контекста от соседей let fullPrompt = node.prompt || node.text || 'Analyze the provided context.' if (context && context.length > 0) { const contextText = context.map((c: any) => `[Node ${c.id}]: ${c.text}`).join('\n\n') fullPrompt = `CONTEXT INFORMATION:\n${contextText}\n\nUSER REQUEST/INSTRUCTION:\n${fullPrompt}` } // Модель можно задать прямо в узле: node.model = 'qwen_coder' | 'llama' | 'gemma' | 'laguna' | 'nemotron' const model = node.model || undefined console.log(`[AI Execute] model=${model || 'default'} nodeId=${nodeId}`) result = await generateAIResponse(fullPrompt, 'You are a helpful assistant.', model) // Сохраняем результат в текст узла nodes[nodeIdx].text = result } else if (node.type === 'webhook') { const url = node.url const method = node.method || 'GET' if (!url) throw new Error('Webhook URL is not configured') console.log(`[Webhook Execute] Calling ${method} ${url}...`) const response = await $fetch(url, { method, ...(method === 'POST' ? { body: { context, timestamp: new Date() } } : {}) }) result = typeof response === 'string' ? response : JSON.stringify(response, null, 2) nodes[nodeIdx].text = `### Response from ${url}\n\n\`\`\`json\n${result}\n\`\`\`` } else { throw createError({ statusCode: 400, message: `Execution not supported for type: ${node.type}` }) } // 3. Сохраняем обновленный холст await prisma.canvas.update({ where: { id: canvasId }, data: { nodes } }) return { success: true, result, message: 'Node executed and canvas updated' } } catch (error: any) { console.error('Node execution error:', error) throw createError({ statusCode: 500, message: error.message || 'Execution failed' }) } })