Files
reason-flow/client/src/pages/ToolsPage.jsx
T
2025-11-06 11:08:59 +01:00

262 lines
9.0 KiB
React
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import React, { useState, useEffect } from 'react';
import axios from 'axios';
import './ToolsPage.css';
const ToolsPage = () => {
const [toolExecutions, setToolExecutions] = useState([]);
const [selectedTool, setSelectedTool] = useState('');
const [toolInput, setToolInput] = useState('');
const [executing, setExecuting] = useState(false);
const [message, setMessage] = useState('');
const tools = [
{
id: 'query_expander',
name: 'Query Expander',
description: 'Expands and refines engineering queries for better understanding',
icon: '🔍',
color: 'blue'
},
{
id: 'extraction',
name: 'Document Extraction',
description: 'Extracts relevant information from uploaded documents',
icon: '📄',
color: 'green'
},
{
id: 'report1',
name: 'Report Generator',
description: 'Generates structured engineering reports',
icon: '📊',
color: 'purple'
},
{
id: 'report2',
name: 'File Generator',
description: 'Creates downloadable engineering files',
icon: '📁',
color: 'orange'
},
{
id: 'web_search',
name: 'Web Search',
description: 'Searches the web for current engineering information',
icon: '🌐',
color: 'cyan'
},
{
id: 'encyclopedia_pdf',
name: 'Encyclopedia Search',
description: 'Searches internal PDF knowledge base',
icon: '📚',
color: 'red'
}
];
useEffect(() => {
loadToolExecutions();
}, []);
const loadToolExecutions = async () => {
try {
const response = await axios.get('/api/tools/executions');
setToolExecutions(response.data.data.executions || []);
} catch (error) {
console.error('Error loading tool executions:', error);
}
};
const executeTool = async () => {
setMessage('⚠️ **Manual tool execution is disabled.** Tools can only be executed as part of an approved engineering plan. Please use the Chat page to create and execute plans.');
setSelectedTool('');
setToolInput('');
};
const retryExecution = async (executionId) => {
try {
await axios.post(`/api/tools/executions/${executionId}/retry`);
setMessage('✅ Tool execution retried');
loadToolExecutions();
} catch (error) {
console.error('Retry error:', error);
setMessage(`❌ Retry failed: ${error.response?.data?.error || error.message}`);
}
};
const getStatusColor = (status) => {
switch (status) {
case 'completed': return 'success';
case 'failed': return 'error';
case 'running': return 'warning';
default: return 'info';
}
};
const formatDate = (dateString) => {
return new Date(dateString).toLocaleString();
};
return (
<div className="tools-page">
<div className="page-header">
<h1>🔧 Engineering Tools</h1>
<p>View tool execution history and results from approved engineering plans</p>
</div>
{message && (
<div className={`message ${message.includes('✅') ? 'success' : message.includes('⚠️') ? 'warning' : 'error'}`}>
{message}
</div>
)}
{/* Tool Selection */}
<div className="tool-selection">
<div className="section-header">
<h2>🛠 Tool Information</h2>
<p>Available engineering tools (execution requires approved plan)</p>
</div>
<div className="tool-selector">
<div className="tool-grid">
{tools.map((tool) => (
<button
key={tool.id}
className={`tool-card ${selectedTool === tool.id ? 'selected' : ''} ${tool.color}`}
onClick={() => setSelectedTool(tool.id)}
>
<div className="tool-icon">{tool.icon}</div>
<div className="tool-info">
<h3>{tool.name}</h3>
<p>{tool.description}</p>
</div>
</button>
))}
</div>
</div>
{selectedTool && (
<div className="execution-panel">
<div className="panel-header">
<h3>{tools.find(t => t.id === selectedTool)?.name} Information</h3>
</div>
<div className="panel-content">
<div className="tool-info">
<p><strong>Description:</strong> {tools.find(t => t.id === selectedTool)?.description}</p>
<p><strong>Usage:</strong> This tool is automatically executed as part of approved engineering plans.</p>
<p><strong>To use this tool:</strong></p>
<ol>
<li>Go to the Chat page</li>
<li>Ask an engineering question</li>
<li>Review the generated plan</li>
<li>Approve the plan</li>
<li>The system will automatically execute the appropriate tools</li>
</ol>
</div>
<div className="execution-actions">
<button
className="execute-btn disabled"
onClick={executeTool}
disabled={true}
>
🔒 Manual Execution Disabled
</button>
</div>
</div>
</div>
)}
</div>
{/* Execution History */}
<div className="execution-history">
<div className="section-header">
<h2>📋 Execution History</h2>
<p>View past tool executions and their results</p>
</div>
<div className="history-container">
{toolExecutions.length > 0 ? (
<div className="executions-list">
{toolExecutions.map((execution) => (
<div key={execution.id} className="execution-card">
<div className="execution-header">
<div className="execution-info">
<h4>
{tools.find(t => t.id === execution.tool_name)?.icon}
{tools.find(t => t.id === execution.tool_name)?.name || execution.tool_name}
</h4>
<div className="execution-meta">
<span className="execution-id">ID: {execution.id}</span>
<span className="execution-time">{formatDate(execution.created_at)}</span>
</div>
</div>
<div className="execution-status">
<span className={`status-badge ${getStatusColor(execution.status)}`}>
{execution.status}
</span>
{execution.status === 'failed' && (
<button
className="retry-btn"
onClick={() => retryExecution(execution.id)}
>
🔄 Retry
</button>
)}
</div>
</div>
<div className="execution-details">
<div className="detail-section">
<h5>Input Parameters</h5>
<pre className="code-block">
{JSON.stringify(execution.input_parameters, null, 2)}
</pre>
</div>
{execution.output_result && (
<div className="detail-section">
<h5>Output Result</h5>
<pre className="code-block">
{JSON.stringify(execution.output_result, null, 2)}
</pre>
</div>
)}
{execution.error_message && (
<div className="detail-section error">
<h5>Error Message</h5>
<pre className="error-block">
{execution.error_message}
</pre>
</div>
)}
<div className="execution-metrics">
<div className="metric">
<span className="metric-label">Duration:</span>
<span className="metric-value">{execution.duration || 'N/A'}ms</span>
</div>
<div className="metric">
<span className="metric-label">Tokens Used:</span>
<span className="metric-value">{execution.tokens_used || 'N/A'}</span>
</div>
</div>
</div>
</div>
))}
</div>
) : (
<div className="empty-state">
<div className="empty-icon">🔧</div>
<h3>No tool executions yet</h3>
<p>Execute your first tool to see the results here</p>
</div>
)}
</div>
</div>
</div>
);
};
export default ToolsPage;