1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
import * as express from 'express';
import * as fs from 'fs';
import * as path from 'path';
// Define handler types to match project patterns
type RouteHandler = (req: express.Request, res: express.Response) => any;
/**
* Handles API endpoints for dynamic tools created by the agent
*/
export function setupDynamicToolsAPI(app: express.Express): void {
// Directory where dynamic tools will be stored
const dynamicToolsDir = path.join(process.cwd(), 'src', 'client', 'views', 'nodes', 'chatbot', 'tools', 'dynamic');
console.log(`Dynamic tools directory path: ${dynamicToolsDir}`);
// Ensure directory exists
if (!fs.existsSync(dynamicToolsDir)) {
try {
fs.mkdirSync(dynamicToolsDir, { recursive: true });
console.log(`Created dynamic tools directory at ${dynamicToolsDir}`);
} catch (error) {
console.error(`Failed to create dynamic tools directory: ${error}`);
}
}
/**
* Save a dynamic tool to the server
*/
const saveDynamicTool: RouteHandler = (req, res) => {
try {
const { toolName, toolCode } = req.body;
if (!toolName || !toolCode) {
return res.status(400).json({
success: false,
error: 'Missing toolName or toolCode in request body',
});
}
// Validate the tool name (should be PascalCase)
if (!/^[A-Z][a-zA-Z0-9]*$/.test(toolName)) {
return res.status(400).json({
success: false,
error: 'Tool name must be in PascalCase format',
});
}
// Create the file path
const filePath = path.join(dynamicToolsDir, `${toolName}.ts`);
// Check if file already exists and is different
let existingCode = '';
if (fs.existsSync(filePath)) {
existingCode = fs.readFileSync(filePath, 'utf8');
}
// Only write if the file doesn't exist or the content is different
if (existingCode !== toolCode) {
fs.writeFileSync(filePath, toolCode, 'utf8');
console.log(`Saved dynamic tool: ${toolName}`);
} else {
console.log(`Dynamic tool ${toolName} already exists with the same content`);
}
return res.json({ success: true, toolName });
} catch (error) {
console.error('Error saving dynamic tool:', error);
return res.status(500).json({
success: false,
error: error instanceof Error ? error.message : 'Unknown error',
});
}
};
/**
* Get a list of all available dynamic tools
*/
const getDynamicTools: RouteHandler = (req, res) => {
try {
// Get all TypeScript files in the dynamic tools directory
const files = fs
.readdirSync(dynamicToolsDir)
.filter(file => file.endsWith('.ts'))
.map(file => ({
name: path.basename(file, '.ts'),
path: path.join('dynamic', file),
}));
return res.json({ success: true, tools: files });
} catch (error) {
console.error('Error getting dynamic tools:', error);
return res.status(500).json({
success: false,
error: error instanceof Error ? error.message : 'Unknown error',
});
}
};
/**
* Get the code for a specific dynamic tool
*/
const getDynamicTool: RouteHandler = (req, res) => {
try {
const { toolName } = req.params;
const filePath = path.join(dynamicToolsDir, `${toolName}.ts`);
if (!fs.existsSync(filePath)) {
return res.status(404).json({
success: false,
error: `Tool ${toolName} not found`,
});
}
const toolCode = fs.readFileSync(filePath, 'utf8');
return res.json({ success: true, toolName, toolCode });
} catch (error) {
console.error('Error getting dynamic tool:', error);
return res.status(500).json({
success: false,
error: error instanceof Error ? error.message : 'Unknown error',
});
}
};
// Register routes
app.post('/saveDynamicTool', saveDynamicTool);
app.get('/getDynamicTools', getDynamicTools);
app.get('/getDynamicTool/:toolName', getDynamicTool);
}
|