251 lines
6.4 KiB
JavaScript
251 lines
6.4 KiB
JavaScript
|
|
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
|
||
|
|
};
|