jblast94 commited on
Commit
7232d5c
·
verified ·
1 Parent(s): 3370f37

Update tool_executor.py

Browse files
Files changed (1) hide show
  1. tool_executor.py +5 -191
tool_executor.py CHANGED
@@ -1,193 +1,7 @@
1
- import os
2
- import requests
3
- import json
4
- from typing import Dict, Optional
5
- import subprocess
6
- import tempfile
7
-
8
  class ToolExecutor:
9
- """Execute various tools like web search, code execution, and N8N workflows."""
10
-
11
  def __init__(self):
12
- """Initialize tool executor with API keys."""
13
- self.tavily_key = os.getenv("TAVILY_API_KEY")
14
- self.n8n_webhook = os.getenv("N8N_WEBHOOK_URL")
15
-
16
- def execute_tools(self, query: str) -> str:
17
- """Determine and execute appropriate tools based on query."""
18
- query_lower = query.lower()
19
- results = []
20
-
21
- # Web search
22
- if any(keyword in query_lower for keyword in ['search', 'find', 'look up', 'what is', 'who is', 'google']):
23
- if self.tavily_key:
24
- search_result = self.web_search(query)
25
- if search_result:
26
- results.append(f"**Web Search Results:**\n{search_result}")
27
- else:
28
- results.append("Web search not configured (missing TAVILY_API_KEY)")
29
-
30
- # Code execution
31
- if any(keyword in query_lower for keyword in ['calculate', 'compute', 'run code', 'execute', 'python']):
32
- # Try to extract code from query
33
- code = self._extract_code(query)
34
- if code:
35
- exec_result = self.execute_code(code)
36
- if exec_result:
37
- results.append(f"**Code Execution Result:**\n{exec_result}")
38
-
39
- # N8N workflow
40
- if any(keyword in query_lower for keyword in ['add task', 'create task', 'workflow', 'automate', 'trigger']):
41
- if self.n8n_webhook:
42
- n8n_result = self.trigger_n8n_workflow({'query': query})
43
- if n8n_result:
44
- results.append(f"**Workflow Triggered:**\n{n8n_result}")
45
- else:
46
- results.append("N8N workflow not configured (missing N8N_WEBHOOK_URL)")
47
-
48
- return '\n\n'.join(results) if results else ""
49
-
50
- def web_search(self, query: str, max_results: int = 3) -> str:
51
- """Search the web using Tavily API."""
52
- if not self.tavily_key:
53
- return "Web search is not configured. Please add TAVILY_API_KEY."
54
-
55
- try:
56
- url = "https://api.tavily.com/search"
57
- payload = {
58
- "api_key": self.tavily_key,
59
- "query": query,
60
- "max_results": max_results,
61
- "search_depth": "basic",
62
- "include_answer": True
63
- }
64
-
65
- response = requests.post(url, json=payload, timeout=10)
66
- response.raise_for_status()
67
- data = response.json()
68
-
69
- # Format results
70
- results = []
71
-
72
- # Include direct answer if available
73
- if data.get('answer'):
74
- results.append(f"**Answer:** {data['answer']}")
75
-
76
- # Include search results
77
- if data.get('results'):
78
- results.append("\n**Sources:**")
79
- for i, result in enumerate(data['results'][:max_results], 1):
80
- title = result.get('title', 'No title')
81
- url = result.get('url', '')
82
- content = result.get('content', '')[:200] # Truncate
83
- results.append(f"{i}. **{title}**\n {content}...\n {url}")
84
-
85
- return '\n'.join(results) if results else "No results found."
86
-
87
- except Exception as e:
88
- return f"Error performing web search: {str(e)}"
89
-
90
- def execute_code(self, code: str, language: str = "python") -> str:
91
- """Execute code safely in a sandboxed environment."""
92
- if language != "python":
93
- return "Only Python code execution is currently supported."
94
-
95
- try:
96
- # Create a temporary file for the code
97
- with tempfile.NamedTemporaryFile(mode='w', suffix='.py', delete=False) as f:
98
- f.write(code)
99
- temp_file = f.name
100
-
101
- # Execute with timeout
102
- result = subprocess.run(
103
- ['python3', temp_file],
104
- capture_output=True,
105
- text=True,
106
- timeout=5
107
- )
108
-
109
- # Clean up
110
- os.unlink(temp_file)
111
-
112
- # Combine stdout and stderr
113
- output = []
114
- if result.stdout:
115
- output.append(f"**Output:**\n{result.stdout}")
116
- if result.stderr:
117
- output.append(f"**Errors:**\n{result.stderr}")
118
-
119
- return '\n'.join(output) if output else "Code executed successfully with no output."
120
-
121
- except subprocess.TimeoutExpired:
122
- return "Code execution timed out (max 5 seconds)."
123
- except Exception as e:
124
- return f"Error executing code: {str(e)}"
125
-
126
- def trigger_n8n_workflow(self, data: Dict) -> str:
127
- """Trigger an N8N workflow via webhook."""
128
- if not self.n8n_webhook:
129
- return "N8N workflow is not configured. Please add N8N_WEBHOOK_URL."
130
-
131
- try:
132
- response = requests.post(self.n8n_webhook, json=data, timeout=10)
133
- response.raise_for_status()
134
-
135
- # Try to parse response
136
- try:
137
- result = response.json()
138
- return f"Workflow executed successfully: {json.dumps(result, indent=2)}"
139
- except:
140
- return f"Workflow executed successfully. Status: {response.status_code}"
141
-
142
- except Exception as e:
143
- return f"Error triggering N8N workflow: {str(e)}"
144
-
145
- def _extract_code(self, query: str) -> Optional[str]:
146
- """Extract code from query if present."""
147
- # Look for code blocks
148
- import re
149
-
150
- # Check for markdown code blocks
151
- code_block_pattern = r'```(?:python)?\n(.*?)```'
152
- matches = re.findall(code_block_pattern, query, re.DOTALL)
153
- if matches:
154
- return matches[0].strip()
155
-
156
- # Check for inline code
157
- if 'print(' in query or 'def ' in query or 'for ' in query:
158
- # Try to extract code-like content
159
- lines = query.split('\n')
160
- code_lines = [line for line in lines if any(kw in line for kw in ['print', 'def', 'for', 'if', 'while', '='])]
161
- if code_lines:
162
- return '\n'.join(code_lines)
163
-
164
- return None
165
-
166
- def calculate(self, expression: str) -> str:
167
- """Safely evaluate mathematical expressions."""
168
- try:
169
- # Use Python's eval but only for safe math operations
170
- allowed_names = {
171
- 'abs': abs, 'round': round, 'min': min, 'max': max,
172
- 'sum': sum, 'pow': pow, 'len': len
173
- }
174
-
175
- # Import math functions
176
- import math
177
- for name in dir(math):
178
- if not name.startswith('_'):
179
- allowed_names[name] = getattr(math, name)
180
-
181
- result = eval(expression, {"__builtins__": {}}, allowed_names)
182
- return f"Result: {result}"
183
- except Exception as e:
184
- return f"Error calculating: {str(e)}"
185
-
186
- def get_available_tools(self) -> Dict[str, bool]:
187
- """Get status of available tools."""
188
- return {
189
- "web_search": bool(self.tavily_key),
190
- "code_execution": True, # Always available
191
- "n8n_workflows": bool(self.n8n_webhook),
192
- "calculator": True # Always available
193
- }
 
 
 
 
 
 
 
 
1
  class ToolExecutor:
 
 
2
  def __init__(self):
3
+ print("ToolExecutor initialized.")
4
+
5
+ def execute_tools(self, message: str) -> str:
6
+ print(f"Placeholder: Executing tools for message: '{message}'")
7
+ return "No tools were executed."