feature/web-search-and-cron-improvements #2
@ -252,6 +252,7 @@ class CalendarConfig(Base):
|
|||||||
token_file: str = "" # Path to store OAuth2 token (default: ~/.nanobot/calendar_token.json)
|
token_file: str = "" # Path to store OAuth2 token (default: ~/.nanobot/calendar_token.json)
|
||||||
calendar_id: str = "primary" # Calendar ID to use (default: primary calendar)
|
calendar_id: str = "primary" # Calendar ID to use (default: primary calendar)
|
||||||
auto_schedule_from_email: bool = True # Automatically schedule meetings from emails
|
auto_schedule_from_email: bool = True # Automatically schedule meetings from emails
|
||||||
|
timezone: str = "UTC" # Timezone for parsing times (e.g., "America/New_York", "Europe/London", "UTC")
|
||||||
|
|
||||||
|
|
||||||
class ExecToolConfig(Base):
|
class ExecToolConfig(Base):
|
||||||
|
|||||||
@ -62,22 +62,37 @@ class CustomProvider(LLMProvider):
|
|||||||
# If no structured tool calls, try to parse from content (Ollama sometimes returns JSON in content)
|
# If no structured tool calls, try to parse from content (Ollama sometimes returns JSON in content)
|
||||||
# Only parse if content looks like it contains a tool call JSON (to avoid false positives)
|
# Only parse if content looks like it contains a tool call JSON (to avoid false positives)
|
||||||
content = msg.content or ""
|
content = msg.content or ""
|
||||||
if not tool_calls and content and '"name"' in content and '"parameters"' in content:
|
# Check for standard format: {"name": "...", "parameters": {...}}
|
||||||
|
has_standard_format = '"name"' in content and '"parameters"' in content
|
||||||
|
# Check for calendar tool format: {"action": "...", ...}
|
||||||
|
has_calendar_format = '"action"' in content and ("calendar" in content.lower() or any(action in content for action in ["list_events", "create_event", "update_event", "delete_event"]))
|
||||||
|
|
||||||
|
if not tool_calls and content and (has_standard_format or has_calendar_format):
|
||||||
import re
|
import re
|
||||||
# Look for JSON tool call patterns: {"name": "exec", "parameters": {...}}
|
# Look for JSON tool call patterns: {"name": "exec", "parameters": {...}} or {"action": "list_events", ...}
|
||||||
# Find complete JSON objects by matching braces
|
# Find complete JSON objects by matching braces
|
||||||
pattern = r'\{\s*"name"\s*:\s*"(\w+)"'
|
# Try "action" pattern first (for calendar tool), then "name" pattern
|
||||||
|
patterns = [
|
||||||
|
(r'\{\s*"action"\s*:\s*"(\w+)"', "action"), # Calendar tool format
|
||||||
|
(r'\{\s*"name"\s*:\s*"(\w+)"', "name"), # Standard format
|
||||||
|
]
|
||||||
start_pos = 0
|
start_pos = 0
|
||||||
max_iterations = 5 # Safety limit
|
max_iterations = 10 # Increased for multiple patterns
|
||||||
iteration = 0
|
iteration = 0
|
||||||
while iteration < max_iterations:
|
while iteration < max_iterations:
|
||||||
iteration += 1
|
iteration += 1
|
||||||
|
match = None
|
||||||
|
pattern_type = None
|
||||||
|
for pattern, ptype in patterns:
|
||||||
match = re.search(pattern, content[start_pos:])
|
match = re.search(pattern, content[start_pos:])
|
||||||
|
if match:
|
||||||
|
pattern_type = ptype
|
||||||
|
break
|
||||||
if not match:
|
if not match:
|
||||||
break
|
break
|
||||||
|
|
||||||
json_start = start_pos + match.start()
|
json_start = start_pos + match.start()
|
||||||
name = match.group(1)
|
key_value = match.group(1)
|
||||||
|
|
||||||
# Find the matching closing brace by counting braces
|
# Find the matching closing brace by counting braces
|
||||||
brace_count = 0
|
brace_count = 0
|
||||||
@ -98,7 +113,24 @@ class CustomProvider(LLMProvider):
|
|||||||
try:
|
try:
|
||||||
json_str = content[json_start:json_end]
|
json_str = content[json_start:json_end]
|
||||||
tool_obj = json_repair.loads(json_str)
|
tool_obj = json_repair.loads(json_str)
|
||||||
# Only accept if it has both name and parameters, and name is a valid tool name
|
|
||||||
|
# Handle calendar tool format: {"action": "...", ...}
|
||||||
|
if isinstance(tool_obj, dict) and "action" in tool_obj:
|
||||||
|
# This is a calendar tool call in JSON format
|
||||||
|
action = tool_obj.get("action")
|
||||||
|
if action and action in ["list_events", "create_event", "update_event", "delete_event", "delete_events", "check_availability"]:
|
||||||
|
# Convert to calendar tool call format
|
||||||
|
tool_calls.append(ToolCallRequest(
|
||||||
|
id=f"call_{len(tool_calls)}",
|
||||||
|
name="calendar",
|
||||||
|
arguments=tool_obj # Pass the whole object as arguments
|
||||||
|
))
|
||||||
|
# Remove the tool call from content
|
||||||
|
content = content[:json_start] + content[json_end:].strip()
|
||||||
|
start_pos = json_start # Stay at same position since we removed text
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Handle standard format: {"name": "...", "parameters": {...}}
|
||||||
# Note: This list should match tools registered in AgentLoop._register_default_tools()
|
# Note: This list should match tools registered in AgentLoop._register_default_tools()
|
||||||
valid_tools = [
|
valid_tools = [
|
||||||
# File tools
|
# File tools
|
||||||
|
|||||||
@ -46,6 +46,7 @@ dependencies = [
|
|||||||
"google-api-python-client>=2.0.0",
|
"google-api-python-client>=2.0.0",
|
||||||
"google-auth-httplib2>=0.2.0",
|
"google-auth-httplib2>=0.2.0",
|
||||||
"google-auth-oauthlib>=1.0.0",
|
"google-auth-oauthlib>=1.0.0",
|
||||||
|
"pytz>=2024.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[project.optional-dependencies]
|
[project.optional-dependencies]
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user