SavvyTelegram / executor.py
StarpowerTechnology's picture
Upload 13 files
a6e3889 verified
"""
Executes tool calls returned by the model.
The `ctx` dict carries runtime state: chat_id, send_fn, etc.
"""
import json
import asyncio
from tools import github_tool, search_tool
async def execute(tool_name: str, tool_args: dict, ctx: dict) -> str:
"""
Run a tool and return its string result.
ctx must contain: chat_id, send_fn (async callable)
"""
try:
match tool_name:
case "web_search":
query = tool_args["query"]
max_results = tool_args.get("max_results", 5)
result = await asyncio.to_thread(
search_tool.search, query, max_results
)
# Auto-save to research/
await asyncio.to_thread(
github_tool.save_research, query, result
)
return result
case "github_read":
path = tool_args["path"]
return await asyncio.to_thread(github_tool.read_file, path)
case "github_write":
path = tool_args["path"]
content = tool_args["content"]
msg = tool_args.get("commit_message", "")
sha = await asyncio.to_thread(
github_tool.write_file, path, content, msg
)
return f"Written to {path} (commit {sha[:7]})"
case "github_list":
folder = tool_args["folder"]
files = await asyncio.to_thread(github_tool.list_files, folder)
return "\n".join(files) if files else "(empty)"
case "quick_reply":
message = tool_args["message"]
send_fn = ctx.get("send_fn")
if send_fn:
await send_fn(f"⚡ {message}")
return f"Quick reply sent: {message}"
case _:
return f"Unknown tool: {tool_name}"
except Exception as e:
return f"Tool error ({tool_name}): {e}"
def parse_tool_calls(response_message) -> list[dict]:
"""
Extract tool calls from a model response message.
Returns list of dicts: {id, name, args}
"""
calls = []
if not hasattr(response_message, "tool_calls") or not response_message.tool_calls:
return calls
for tc in response_message.tool_calls:
try:
args = json.loads(tc.function.arguments)
except (json.JSONDecodeError, AttributeError):
args = {}
calls.append({
"id": tc.id,
"name": tc.function.name,
"args": args
})
return calls
def tool_result_message(call_id: str, tool_name: str, result: str) -> dict:
"""Format a tool result as a message for the model's context."""
return {
"role": "tool",
"tool_call_id": call_id,
"name": tool_name,
"content": result
}