feat: Implement Trillium notes executor for searching and creating notes via ETAPI
- Added `trillium.py` for searching and creating notes with Trillium's ETAPI. - Implemented `search_notes` and `create_note` functions with appropriate error handling and validation. feat: Add web search functionality using DuckDuckGo - Introduced `web_search.py` for performing web searches without API keys. - Implemented `search_web` function with result handling and validation. feat: Create provider-agnostic function caller for iterative tool calling - Developed `function_caller.py` to manage LLM interactions with tools. - Implemented iterative calling logic with error handling and tool execution. feat: Establish a tool registry for managing available tools - Created `registry.py` to define and manage tool availability and execution. - Integrated feature flags for enabling/disabling tools based on environment variables. feat: Implement event streaming for tool calling processes - Added `stream_events.py` to manage Server-Sent Events (SSE) for tool calling. - Enabled real-time updates during tool execution for enhanced user experience. test: Add tests for tool calling system components - Created `test_tools.py` to validate functionality of code execution, web search, and tool registry. - Implemented asynchronous tests to ensure proper execution and result handling. chore: Add Dockerfile for sandbox environment setup - Created `Dockerfile` to set up a Python environment with necessary dependencies for code execution. chore: Add debug regex script for testing XML parsing - Introduced `debug_regex.py` to validate regex patterns against XML tool calls. chore: Add HTML template for displaying thinking stream events - Created `test_thinking_stream.html` for visualizing tool calling events in a user-friendly format. test: Add tests for OllamaAdapter XML parsing - Developed `test_ollama_parser.py` to validate XML parsing with various test cases, including malformed XML.
This commit is contained in:
134
cortex/autonomy/tools/executors/trillium.py
Normal file
134
cortex/autonomy/tools/executors/trillium.py
Normal file
@@ -0,0 +1,134 @@
|
||||
"""
|
||||
Trillium notes executor for searching and creating notes via ETAPI.
|
||||
|
||||
This module provides integration with Trillium notes through the ETAPI HTTP API.
|
||||
"""
|
||||
|
||||
import os
|
||||
import aiohttp
|
||||
from typing import Dict
|
||||
|
||||
|
||||
TRILLIUM_URL = os.getenv("TRILLIUM_URL", "http://localhost:8080")
|
||||
TRILLIUM_TOKEN = os.getenv("TRILLIUM_ETAPI_TOKEN", "")
|
||||
|
||||
|
||||
async def search_notes(args: Dict) -> Dict:
|
||||
"""Search Trillium notes via ETAPI.
|
||||
|
||||
Args:
|
||||
args: Dictionary containing:
|
||||
- query (str): Search query
|
||||
- limit (int, optional): Maximum notes to return (default: 5, max: 20)
|
||||
|
||||
Returns:
|
||||
dict: Search results containing:
|
||||
- notes (list): List of notes with noteId, title, content, type
|
||||
- count (int): Number of notes returned
|
||||
OR
|
||||
- error (str): Error message if search failed
|
||||
"""
|
||||
query = args.get("query")
|
||||
limit = args.get("limit", 5)
|
||||
|
||||
# Validation
|
||||
if not query:
|
||||
return {"error": "No query provided"}
|
||||
|
||||
if not TRILLIUM_TOKEN:
|
||||
return {"error": "TRILLIUM_ETAPI_TOKEN not configured in environment"}
|
||||
|
||||
# Cap limit
|
||||
limit = min(max(limit, 1), 20)
|
||||
|
||||
try:
|
||||
async with aiohttp.ClientSession() as session:
|
||||
async with session.get(
|
||||
f"{TRILLIUM_URL}/etapi/search-notes",
|
||||
params={"search": query, "limit": limit},
|
||||
headers={"Authorization": TRILLIUM_TOKEN}
|
||||
) as resp:
|
||||
if resp.status == 200:
|
||||
data = await resp.json()
|
||||
return {
|
||||
"notes": data,
|
||||
"count": len(data)
|
||||
}
|
||||
elif resp.status == 401:
|
||||
return {"error": "Authentication failed. Check TRILLIUM_ETAPI_TOKEN"}
|
||||
else:
|
||||
error_text = await resp.text()
|
||||
return {"error": f"HTTP {resp.status}: {error_text}"}
|
||||
|
||||
except aiohttp.ClientConnectorError:
|
||||
return {"error": f"Cannot connect to Trillium at {TRILLIUM_URL}"}
|
||||
except Exception as e:
|
||||
return {"error": f"Search failed: {str(e)}"}
|
||||
|
||||
|
||||
async def create_note(args: Dict) -> Dict:
|
||||
"""Create a note in Trillium via ETAPI.
|
||||
|
||||
Args:
|
||||
args: Dictionary containing:
|
||||
- title (str): Note title
|
||||
- content (str): Note content in markdown or HTML
|
||||
- parent_note_id (str, optional): Parent note ID to nest under
|
||||
|
||||
Returns:
|
||||
dict: Creation result containing:
|
||||
- noteId (str): ID of created note
|
||||
- title (str): Title of created note
|
||||
- success (bool): True if created successfully
|
||||
OR
|
||||
- error (str): Error message if creation failed
|
||||
"""
|
||||
title = args.get("title")
|
||||
content = args.get("content")
|
||||
parent_note_id = args.get("parent_note_id")
|
||||
|
||||
# Validation
|
||||
if not title:
|
||||
return {"error": "No title provided"}
|
||||
|
||||
if not content:
|
||||
return {"error": "No content provided"}
|
||||
|
||||
if not TRILLIUM_TOKEN:
|
||||
return {"error": "TRILLIUM_ETAPI_TOKEN not configured in environment"}
|
||||
|
||||
# Prepare payload
|
||||
payload = {
|
||||
"title": title,
|
||||
"content": content,
|
||||
"type": "text",
|
||||
"mime": "text/html"
|
||||
}
|
||||
|
||||
if parent_note_id:
|
||||
payload["parentNoteId"] = parent_note_id
|
||||
|
||||
try:
|
||||
async with aiohttp.ClientSession() as session:
|
||||
async with session.post(
|
||||
f"{TRILLIUM_URL}/etapi/create-note",
|
||||
json=payload,
|
||||
headers={"Authorization": TRILLIUM_TOKEN}
|
||||
) as resp:
|
||||
if resp.status in [200, 201]:
|
||||
data = await resp.json()
|
||||
return {
|
||||
"noteId": data.get("noteId"),
|
||||
"title": title,
|
||||
"success": True
|
||||
}
|
||||
elif resp.status == 401:
|
||||
return {"error": "Authentication failed. Check TRILLIUM_ETAPI_TOKEN"}
|
||||
else:
|
||||
error_text = await resp.text()
|
||||
return {"error": f"HTTP {resp.status}: {error_text}"}
|
||||
|
||||
except aiohttp.ClientConnectorError:
|
||||
return {"error": f"Cannot connect to Trillium at {TRILLIUM_URL}"}
|
||||
except Exception as e:
|
||||
return {"error": f"Note creation failed: {str(e)}"}
|
||||
Reference in New Issue
Block a user