106 lines
3.6 KiB
TypeScript
106 lines
3.6 KiB
TypeScript
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<any>(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'
|
|
})
|
|
}
|
|
})
|