Files
reason-flow/server/controllers/toolController.js
T

251 lines
6.4 KiB
JavaScript
Raw Normal View History

2025-11-06 11:08:59 +01:00
const { ToolExecution, Plan, Document, sequelize } = require('../models');
const logger = require('../utils/logger');
const queryModelService = require('../services/queryModelService');
const executeTool = async (req, res) => {
try {
const { planId, toolName, toolType, inputParameters } = req.body;
if (!planId || !toolName || !toolType || !inputParameters) {
return res.status(400).json({
success: false,
error: 'Plan ID, tool name, type, and input parameters are required'
});
}
// Verify plan exists
const plan = await Plan.findByPk(planId);
if (!plan) {
return res.status(404).json({
success: false,
error: 'Plan not found'
});
}
// Execute tool using QUERYMODEL service
const toolExecution = await queryModelService.executeTool(
toolName,
toolType,
inputParameters,
planId
);
logger.info(`Tool executed: ${toolName} for plan ${planId}`);
res.json({
success: true,
data: { toolExecution }
});
} catch (error) {
logger.error('Execute tool error:', error);
res.status(500).json({
success: false,
error: 'Internal server error'
});
}
};
const getToolExecutions = async (req, res) => {
try {
const { planId, toolType, status, page = 1, limit = 10 } = req.query;
const whereClause = {};
if (planId) whereClause.plan_id = planId;
if (toolType) whereClause.tool_type = toolType;
if (status) whereClause.status = status;
const toolExecutions = await ToolExecution.findAndCountAll({
where: whereClause,
include: [
{
model: Plan,
attributes: ['id', 'title', 'status']
},
{
model: Document,
attributes: ['id', 'filename', 'original_filename']
}
],
order: [['created_at', 'DESC']],
limit: parseInt(limit),
offset: (parseInt(page) - 1) * parseInt(limit)
});
res.json({
success: true,
data: {
toolExecutions: toolExecutions.rows,
pagination: {
page: parseInt(page),
limit: parseInt(limit),
total: toolExecutions.count,
pages: Math.ceil(toolExecutions.count / parseInt(limit))
}
}
});
} catch (error) {
logger.error('Get tool executions error:', error);
res.status(500).json({
success: false,
error: 'Internal server error'
});
}
};
const getToolExecution = async (req, res) => {
try {
const { executionId } = req.params;
const toolExecution = await ToolExecution.findByPk(executionId, {
include: [
{
model: Plan,
attributes: ['id', 'title', 'status']
},
{
model: Document,
attributes: ['id', 'filename', 'original_filename']
}
]
});
if (!toolExecution) {
return res.status(404).json({
success: false,
error: 'Tool execution not found'
});
}
res.json({
success: true,
data: { toolExecution }
});
} catch (error) {
logger.error('Get tool execution error:', error);
res.status(500).json({
success: false,
error: 'Internal server error'
});
}
};
const getToolStats = async (req, res) => {
try {
const stats = await ToolExecution.findAll({
attributes: [
'tool_name',
'tool_type',
[sequelize.fn('COUNT', sequelize.col('id')), 'count'],
[sequelize.fn('AVG', sequelize.col('execution_time')), 'avg_execution_time'],
[sequelize.fn('SUM', sequelize.col('tokens_used')), 'total_tokens']
],
group: ['tool_name', 'tool_type'],
raw: true
});
const totalExecutions = await ToolExecution.count();
const successfulExecutions = await ToolExecution.count({ where: { status: 'completed' } });
const failedExecutions = await ToolExecution.count({ where: { status: 'failed' } });
res.json({
success: true,
data: {
stats,
summary: {
total: totalExecutions,
successful: successfulExecutions,
failed: failedExecutions,
successRate: totalExecutions > 0 ? (successfulExecutions / totalExecutions) * 100 : 0
}
}
});
} catch (error) {
logger.error('Get tool stats error:', error);
res.status(500).json({
success: false,
error: 'Internal server error'
});
}
};
const retryToolExecution = async (req, res) => {
try {
const { executionId } = req.params;
const toolExecution = await ToolExecution.findByPk(executionId);
if (!toolExecution) {
return res.status(404).json({
success: false,
error: 'Tool execution not found'
});
}
if (toolExecution.status === 'running') {
return res.status(400).json({
success: false,
error: 'Tool execution is already running'
});
}
// Reset execution status
await toolExecution.update({
status: 'pending',
output_result: null,
execution_time: null,
error_message: null
});
// Retry tool execution using QUERYMODEL service
try {
const retryExecution = await queryModelService.executeTool(
toolExecution.tool_name,
toolExecution.tool_type,
toolExecution.input_parameters,
toolExecution.plan_id
);
// Update the original execution record with retry results
await toolExecution.update({
output_result: retryExecution.output_result,
status: retryExecution.status,
execution_time: retryExecution.execution_time,
tokens_used: retryExecution.tokens_used,
error_message: null
});
logger.info(`Tool execution retried successfully: ${executionId}`);
} catch (retryError) {
logger.error(`Tool execution retry failed: ${executionId}`, retryError);
await toolExecution.update({
status: 'failed',
error_message: retryError.message
});
throw retryError;
}
logger.info(`Tool execution retried: ${executionId}`);
res.json({
success: true,
data: { toolExecution }
});
} catch (error) {
logger.error('Retry tool execution error:', error);
res.status(500).json({
success: false,
error: 'Internal server error'
});
}
};
module.exports = {
executeTool,
getToolExecutions,
getToolExecution,
getToolStats,
retryToolExecution
};