mirror of
https://github.com/eigent-ai/eigent.git
synced 2026-05-16 19:50:50 +00:00
Merge branch 'main' into tool_schema_temporary-fix
This commit is contained in:
commit
1f092cfccd
33 changed files with 290 additions and 791 deletions
|
|
@ -323,6 +323,17 @@ class ListenChatAgent(ChatAgent):
|
|||
else:
|
||||
result = raw_result
|
||||
mask_flag = False
|
||||
# Prepare result message with truncation
|
||||
if isinstance(result, str):
|
||||
result_msg = result
|
||||
else:
|
||||
result_str = repr(result)
|
||||
MAX_RESULT_LENGTH = 500
|
||||
if len(result_str) > MAX_RESULT_LENGTH:
|
||||
result_msg = result_str[:MAX_RESULT_LENGTH] + f"... (truncated, total length: {len(result_str)} chars)"
|
||||
else:
|
||||
result_msg = result_str
|
||||
|
||||
asyncio.create_task(
|
||||
task_lock.put_queue(
|
||||
ActionDeactivateToolkitData(
|
||||
|
|
@ -331,7 +342,7 @@ class ListenChatAgent(ChatAgent):
|
|||
"process_task_id": self.process_task_id,
|
||||
"toolkit_name": toolkit_name,
|
||||
"method_name": func_name,
|
||||
"message": result if isinstance(result, str) else repr(result),
|
||||
"message": result_msg,
|
||||
},
|
||||
)
|
||||
)
|
||||
|
|
@ -407,6 +418,17 @@ class ListenChatAgent(ChatAgent):
|
|||
traceroot_logger.error(f"Async tool execution failed for {func_name}: {e}")
|
||||
traceback.print_exc()
|
||||
|
||||
# Prepare result message with truncation
|
||||
if isinstance(result, str):
|
||||
result_msg = result
|
||||
else:
|
||||
result_str = repr(result)
|
||||
MAX_RESULT_LENGTH = 500
|
||||
if len(result_str) > MAX_RESULT_LENGTH:
|
||||
result_msg = result_str[:MAX_RESULT_LENGTH] + f"... (truncated, total length: {len(result_str)} chars)"
|
||||
else:
|
||||
result_msg = result_str
|
||||
|
||||
await task_lock.put_queue(
|
||||
ActionDeactivateToolkitData(
|
||||
data={
|
||||
|
|
@ -414,7 +436,7 @@ class ListenChatAgent(ChatAgent):
|
|||
"process_task_id": self.process_task_id,
|
||||
"toolkit_name": toolkit_name,
|
||||
"method_name": func_name,
|
||||
"message": result if isinstance(result, str) else repr(result),
|
||||
"message": result_msg,
|
||||
},
|
||||
)
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
import asyncio
|
||||
from functools import wraps
|
||||
from inspect import iscoroutinefunction
|
||||
from inspect import iscoroutinefunction, getmembers, ismethod, signature
|
||||
import json
|
||||
from typing import Any, Callable
|
||||
from typing import Any, Callable, Type, TypeVar
|
||||
import threading
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
|
||||
from loguru import logger
|
||||
from app.service.task import (
|
||||
|
|
@ -14,6 +16,39 @@ from app.utils.toolkit.abstract_toolkit import AbstractToolkit
|
|||
from app.service.task import process_task
|
||||
|
||||
|
||||
def _safe_put_queue(task_lock, data):
|
||||
"""Safely put data to the queue, handling both sync and async contexts"""
|
||||
try:
|
||||
# Try to get current event loop
|
||||
loop = asyncio.get_running_loop()
|
||||
# We're in an async context, create a task
|
||||
task = asyncio.create_task(task_lock.put_queue(data))
|
||||
if hasattr(task_lock, "add_background_task"):
|
||||
task_lock.add_background_task(task)
|
||||
except RuntimeError:
|
||||
# No running event loop, we need to handle this differently
|
||||
try:
|
||||
# Create a new event loop in a separate thread to avoid conflicts
|
||||
def run_in_thread():
|
||||
try:
|
||||
# Create a new event loop for this thread
|
||||
new_loop = asyncio.new_event_loop()
|
||||
asyncio.set_event_loop(new_loop)
|
||||
try:
|
||||
new_loop.run_until_complete(task_lock.put_queue(data))
|
||||
logger.debug(f"[listen_toolkit] Successfully sent data to queue using new event loop")
|
||||
finally:
|
||||
new_loop.close()
|
||||
except Exception as e:
|
||||
logger.error(f"[listen_toolkit] Failed to send data in thread: {e}")
|
||||
|
||||
# Run in a separate thread to avoid blocking
|
||||
thread = threading.Thread(target=run_in_thread, daemon=True)
|
||||
thread.start()
|
||||
except Exception as e:
|
||||
logger.error(f"[listen_toolkit] Failed to send data to queue: {e}")
|
||||
|
||||
|
||||
def listen_toolkit(
|
||||
wrap_method: Callable[..., Any] | None = None,
|
||||
inputs: Callable[..., str] | None = None,
|
||||
|
|
@ -27,6 +62,11 @@ def listen_toolkit(
|
|||
@wraps(wrap)
|
||||
async def async_wrapper(*args, **kwargs):
|
||||
toolkit: AbstractToolkit = args[0]
|
||||
# Check if api_task_id exists
|
||||
if not hasattr(toolkit, 'api_task_id'):
|
||||
logger.warning(f"[listen_toolkit] {toolkit.__class__.__name__} missing api_task_id, calling method directly")
|
||||
return await func(*args, **kwargs)
|
||||
|
||||
task_lock = get_task_lock(toolkit.api_task_id)
|
||||
|
||||
if inputs is not None:
|
||||
|
|
@ -40,19 +80,24 @@ def listen_toolkit(
|
|||
kwargs_str = ", ".join(f"{k}={v!r}" for k, v in kwargs.items())
|
||||
args_str = f"{args_str}, {kwargs_str}" if args_str else kwargs_str
|
||||
|
||||
# Truncate args_str if too long
|
||||
MAX_ARGS_LENGTH = 500
|
||||
if len(args_str) > MAX_ARGS_LENGTH:
|
||||
args_str = args_str[:MAX_ARGS_LENGTH] + f"... (truncated, total length: {len(args_str)} chars)"
|
||||
|
||||
toolkit_name = toolkit.toolkit_name()
|
||||
method_name = func.__name__.replace("_", " ")
|
||||
await task_lock.put_queue(
|
||||
ActionActivateToolkitData(
|
||||
data={
|
||||
"agent_name": toolkit.agent_name,
|
||||
"process_task_id": process_task.get(""),
|
||||
"toolkit_name": toolkit_name,
|
||||
"method_name": method_name,
|
||||
"message": args_str,
|
||||
},
|
||||
)
|
||||
activate_data = ActionActivateToolkitData(
|
||||
data={
|
||||
"agent_name": toolkit.agent_name,
|
||||
"process_task_id": process_task.get(""),
|
||||
"toolkit_name": toolkit_name,
|
||||
"method_name": method_name,
|
||||
"message": args_str,
|
||||
},
|
||||
)
|
||||
logger.debug(f"[listen_toolkit] Sending activate data: {activate_data.model_dump()}")
|
||||
await task_lock.put_queue(activate_data)
|
||||
error = None
|
||||
res = None
|
||||
try:
|
||||
|
|
@ -70,21 +115,27 @@ def listen_toolkit(
|
|||
res_msg = json.dumps(res, ensure_ascii=False)
|
||||
except TypeError:
|
||||
# Handle cases where res contains non-serializable objects (like coroutines)
|
||||
res_msg = str(res)
|
||||
res_str = str(res)
|
||||
# Truncate very long outputs to avoid flooding logs
|
||||
MAX_LENGTH = 500
|
||||
if len(res_str) > MAX_LENGTH:
|
||||
res_msg = res_str[:MAX_LENGTH] + f"... (truncated, total length: {len(res_str)} chars)"
|
||||
else:
|
||||
res_msg = res_str
|
||||
else:
|
||||
res_msg = str(error)
|
||||
|
||||
await task_lock.put_queue(
|
||||
ActionDeactivateToolkitData(
|
||||
data={
|
||||
"agent_name": toolkit.agent_name,
|
||||
"process_task_id": process_task.get(""),
|
||||
"toolkit_name": toolkit_name,
|
||||
"method_name": method_name,
|
||||
"message": res_msg,
|
||||
},
|
||||
)
|
||||
deactivate_data = ActionDeactivateToolkitData(
|
||||
data={
|
||||
"agent_name": toolkit.agent_name,
|
||||
"process_task_id": process_task.get(""),
|
||||
"toolkit_name": toolkit_name,
|
||||
"method_name": method_name,
|
||||
"message": res_msg,
|
||||
},
|
||||
)
|
||||
logger.debug(f"[listen_toolkit] Sending deactivate data: {deactivate_data.model_dump()}")
|
||||
await task_lock.put_queue(deactivate_data)
|
||||
if error is not None:
|
||||
raise error
|
||||
return res
|
||||
|
|
@ -96,6 +147,11 @@ def listen_toolkit(
|
|||
@wraps(wrap)
|
||||
def sync_wrapper(*args, **kwargs):
|
||||
toolkit: AbstractToolkit = args[0]
|
||||
# Check if api_task_id exists
|
||||
if not hasattr(toolkit, 'api_task_id'):
|
||||
logger.warning(f"[listen_toolkit] {toolkit.__class__.__name__} missing api_task_id, calling method directly")
|
||||
return func(*args, **kwargs)
|
||||
|
||||
task_lock = get_task_lock(toolkit.api_task_id)
|
||||
|
||||
if inputs is not None:
|
||||
|
|
@ -109,23 +165,24 @@ def listen_toolkit(
|
|||
kwargs_str = ", ".join(f"{k}={v!r}" for k, v in kwargs.items())
|
||||
args_str = f"{args_str}, {kwargs_str}" if args_str else kwargs_str
|
||||
|
||||
# Truncate args_str if too long
|
||||
MAX_ARGS_LENGTH = 500
|
||||
if len(args_str) > MAX_ARGS_LENGTH:
|
||||
args_str = args_str[:MAX_ARGS_LENGTH] + f"... (truncated, total length: {len(args_str)} chars)"
|
||||
|
||||
toolkit_name = toolkit.toolkit_name()
|
||||
method_name = func.__name__.replace("_", " ")
|
||||
task = asyncio.create_task(
|
||||
task_lock.put_queue(
|
||||
ActionActivateToolkitData(
|
||||
data={
|
||||
"agent_name": toolkit.agent_name,
|
||||
"process_task_id": process_task.get(""),
|
||||
"toolkit_name": toolkit_name,
|
||||
"method_name": method_name,
|
||||
"message": args_str,
|
||||
},
|
||||
)
|
||||
)
|
||||
activate_data = ActionActivateToolkitData(
|
||||
data={
|
||||
"agent_name": toolkit.agent_name,
|
||||
"process_task_id": process_task.get(""),
|
||||
"toolkit_name": toolkit_name,
|
||||
"method_name": method_name,
|
||||
"message": args_str,
|
||||
},
|
||||
)
|
||||
if hasattr(task_lock, "add_background_task"):
|
||||
task_lock.add_background_task(task)
|
||||
logger.debug(f"[listen_toolkit sync] Sending activate data: {activate_data.model_dump()}")
|
||||
_safe_put_queue(task_lock, activate_data)
|
||||
error = None
|
||||
res = None
|
||||
try:
|
||||
|
|
@ -150,25 +207,26 @@ def listen_toolkit(
|
|||
res_msg = json.dumps(res, ensure_ascii=False)
|
||||
except TypeError:
|
||||
# Handle cases where res contains non-serializable objects (like coroutines)
|
||||
res_msg = str(res)
|
||||
res_str = str(res)
|
||||
# Truncate very long outputs to avoid flooding logs
|
||||
MAX_LENGTH = 500
|
||||
if len(res_str) > MAX_LENGTH:
|
||||
res_msg = res_str[:MAX_LENGTH] + f"... (truncated, total length: {len(res_str)} chars)"
|
||||
else:
|
||||
res_msg = res_str
|
||||
else:
|
||||
res_msg = str(error)
|
||||
|
||||
task = asyncio.create_task(
|
||||
task_lock.put_queue(
|
||||
ActionDeactivateToolkitData(
|
||||
data={
|
||||
"agent_name": toolkit.agent_name,
|
||||
"process_task_id": process_task.get(""),
|
||||
"toolkit_name": toolkit_name,
|
||||
"method_name": method_name,
|
||||
"message": res_msg,
|
||||
},
|
||||
)
|
||||
)
|
||||
deactivate_data = ActionDeactivateToolkitData(
|
||||
data={
|
||||
"agent_name": toolkit.agent_name,
|
||||
"process_task_id": process_task.get(""),
|
||||
"toolkit_name": toolkit_name,
|
||||
"method_name": method_name,
|
||||
"message": res_msg,
|
||||
},
|
||||
)
|
||||
if hasattr(task_lock, "add_background_task"):
|
||||
task_lock.add_background_task(task)
|
||||
_safe_put_queue(task_lock, deactivate_data)
|
||||
if error is not None:
|
||||
raise error
|
||||
return res
|
||||
|
|
@ -176,3 +234,81 @@ def listen_toolkit(
|
|||
return sync_wrapper
|
||||
|
||||
return decorator
|
||||
|
||||
|
||||
T = TypeVar('T')
|
||||
|
||||
# Methods that should not be wrapped by auto_listen_toolkit
|
||||
# These are utility/helper methods that don't perform actual tool operations
|
||||
EXCLUDED_METHODS = {
|
||||
'get_tools', # Tool enumeration
|
||||
'get_can_use_tools', # Tool filtering
|
||||
'toolkit_name', # Metadata getter
|
||||
'run_mcp_server', # MCP server initialization
|
||||
'model_dump', # Pydantic model serialization
|
||||
'model_dump_json', # Pydantic model serialization
|
||||
'dict', # Pydantic legacy dict method
|
||||
'json', # Pydantic legacy json method
|
||||
'copy', # Object copying
|
||||
'update', # Object update
|
||||
}
|
||||
|
||||
|
||||
def auto_listen_toolkit(base_toolkit_class: Type[T]) -> Callable[[Type[T]], Type[T]]:
|
||||
"""
|
||||
Class decorator that automatically wraps all public methods from the base toolkit
|
||||
with the @listen_toolkit decorator.
|
||||
|
||||
Excluded methods (not wrapped):
|
||||
- get_tools, get_can_use_tools: Tool enumeration/filtering
|
||||
- toolkit_name: Metadata getter
|
||||
- run_mcp_server: MCP server initialization
|
||||
- Pydantic serialization methods: model_dump, model_dump_json, dict, json
|
||||
- Object utility methods: copy, update
|
||||
|
||||
These methods are typically called during initialization or for metadata,
|
||||
and should not trigger activate/deactivate events.
|
||||
|
||||
Usage:
|
||||
@auto_listen_toolkit(BaseNoteTakingToolkit)
|
||||
class NoteTakingToolkit(BaseNoteTakingToolkit, AbstractToolkit):
|
||||
agent_name: str = Agents.document_agent
|
||||
"""
|
||||
def class_decorator(cls: Type[T]) -> Type[T]:
|
||||
|
||||
base_methods = {}
|
||||
for name in dir(base_toolkit_class):
|
||||
# Skip private methods and excluded helper methods
|
||||
if not name.startswith('_') and name not in EXCLUDED_METHODS:
|
||||
attr = getattr(base_toolkit_class, name)
|
||||
if callable(attr):
|
||||
base_methods[name] = attr
|
||||
|
||||
for method_name, base_method in base_methods.items():
|
||||
if method_name in cls.__dict__:
|
||||
continue
|
||||
|
||||
sig = signature(base_method)
|
||||
|
||||
def create_wrapper(method_name: str, base_method: Callable) -> Callable:
|
||||
if iscoroutinefunction(base_method):
|
||||
async def async_method_wrapper(self, *args, **kwargs):
|
||||
return await getattr(super(cls, self), method_name)(*args, **kwargs)
|
||||
async_method_wrapper.__name__ = method_name
|
||||
async_method_wrapper.__signature__ = sig
|
||||
return async_method_wrapper
|
||||
else:
|
||||
def sync_method_wrapper(self, *args, **kwargs):
|
||||
return getattr(super(cls, self), method_name)(*args, **kwargs)
|
||||
sync_method_wrapper.__name__ = method_name
|
||||
sync_method_wrapper.__signature__ = sig
|
||||
return sync_method_wrapper
|
||||
|
||||
wrapper = create_wrapper(method_name, base_method)
|
||||
decorated_method = listen_toolkit(base_method)(wrapper)
|
||||
|
||||
setattr(cls, method_name, decorated_method)
|
||||
|
||||
return cls
|
||||
|
||||
return class_decorator
|
||||
|
|
|
|||
|
|
@ -4,10 +4,11 @@ from camel.toolkits import AudioAnalysisToolkit as BaseAudioAnalysisToolkit
|
|||
|
||||
from app.component.environment import env
|
||||
from app.service.task import Agents
|
||||
from app.utils.listen.toolkit_listen import listen_toolkit
|
||||
from app.utils.listen.toolkit_listen import auto_listen_toolkit
|
||||
from app.utils.toolkit.abstract_toolkit import AbstractToolkit
|
||||
|
||||
|
||||
@auto_listen_toolkit(BaseAudioAnalysisToolkit)
|
||||
class AudioAnalysisToolkit(BaseAudioAnalysisToolkit, AbstractToolkit):
|
||||
agent_name: str = Agents.multi_modal_agent
|
||||
|
||||
|
|
@ -23,14 +24,3 @@ class AudioAnalysisToolkit(BaseAudioAnalysisToolkit, AbstractToolkit):
|
|||
cache_dir = env("file_save_path", os.path.expanduser("~/.eigent/tmp/"))
|
||||
super().__init__(cache_dir, transcribe_model, audio_reasoning_model, timeout)
|
||||
self.api_task_id = api_task_id
|
||||
|
||||
@listen_toolkit(
|
||||
BaseAudioAnalysisToolkit.audio2text,
|
||||
lambda _, audio_path, question: f"transcribe audio from {audio_path} and ask question: {question}",
|
||||
)
|
||||
def ask_question_about_audio(self, audio_path: str, question: str) -> str:
|
||||
return super().ask_question_about_audio(audio_path, question)
|
||||
|
||||
@listen_toolkit(BaseAudioAnalysisToolkit.audio2text)
|
||||
def audio2text(self, audio_path: str) -> str:
|
||||
return super().audio2text(audio_path)
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
from typing import List, Literal
|
||||
from camel.toolkits import CodeExecutionToolkit as BaseCodeExecutionToolkit, FunctionTool
|
||||
from app.service.task import Agents
|
||||
from app.utils.listen.toolkit_listen import listen_toolkit
|
||||
from app.utils.listen.toolkit_listen import auto_listen_toolkit
|
||||
from app.utils.toolkit.abstract_toolkit import AbstractToolkit
|
||||
|
||||
|
||||
@auto_listen_toolkit(BaseCodeExecutionToolkit)
|
||||
class CodeExecutionToolkit(BaseCodeExecutionToolkit, AbstractToolkit):
|
||||
agent_name: str = Agents.developer_agent
|
||||
|
||||
|
|
@ -21,18 +22,6 @@ class CodeExecutionToolkit(BaseCodeExecutionToolkit, AbstractToolkit):
|
|||
self.api_task_id = api_task_id
|
||||
super().__init__(sandbox, verbose, unsafe_mode, import_white_list, require_confirm, timeout)
|
||||
|
||||
@listen_toolkit(
|
||||
BaseCodeExecutionToolkit.execute_code,
|
||||
)
|
||||
def execute_code(self, code: str, code_type: str = "python") -> str:
|
||||
return super().execute_code(code, code_type)
|
||||
|
||||
@listen_toolkit(
|
||||
BaseCodeExecutionToolkit.execute_command,
|
||||
)
|
||||
def execute_command(self, command: str) -> str | tuple[str, str]:
|
||||
return super().execute_command(command)
|
||||
|
||||
def get_tools(self) -> List[FunctionTool]:
|
||||
return [
|
||||
FunctionTool(self.execute_code),
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
from camel.toolkits import Crawl4AIToolkit as BaseCrawl4AIToolkit
|
||||
|
||||
from app.service.task import Agents
|
||||
from app.utils.listen.toolkit_listen import listen_toolkit
|
||||
from app.utils.listen.toolkit_listen import auto_listen_toolkit
|
||||
from app.utils.toolkit.abstract_toolkit import AbstractToolkit
|
||||
|
||||
|
||||
@auto_listen_toolkit(BaseCrawl4AIToolkit)
|
||||
class Crawl4AIToolkit(BaseCrawl4AIToolkit, AbstractToolkit):
|
||||
agent_name: str = Agents.search_agent
|
||||
|
||||
|
|
@ -12,18 +13,5 @@ class Crawl4AIToolkit(BaseCrawl4AIToolkit, AbstractToolkit):
|
|||
self.api_task_id = api_task_id
|
||||
super().__init__(timeout)
|
||||
|
||||
# async def _get_client(self):
|
||||
# r"""Get or create the AsyncWebCrawler client."""
|
||||
# if self._client is None:
|
||||
# from crawl4ai import AsyncWebCrawler
|
||||
|
||||
# self._client = AsyncWebCrawler(use_managed_browser=True)
|
||||
# await self._client.__aenter__()
|
||||
# return self._client
|
||||
|
||||
@listen_toolkit(BaseCrawl4AIToolkit.scrape)
|
||||
async def scrape(self, url: str) -> str:
|
||||
return await super().scrape(url)
|
||||
|
||||
def toolkit_name(self) -> str:
|
||||
return "Crawl Toolkit"
|
||||
|
|
|
|||
|
|
@ -3,10 +3,11 @@ from camel.toolkits import ExcelToolkit as BaseExcelToolkit
|
|||
|
||||
from app.component.environment import env
|
||||
from app.service.task import Agents
|
||||
from app.utils.listen.toolkit_listen import listen_toolkit
|
||||
from app.utils.listen.toolkit_listen import auto_listen_toolkit
|
||||
from app.utils.toolkit.abstract_toolkit import AbstractToolkit
|
||||
|
||||
|
||||
@auto_listen_toolkit(BaseExcelToolkit)
|
||||
class ExcelToolkit(BaseExcelToolkit, AbstractToolkit):
|
||||
agent_name: str = Agents.document_agent
|
||||
|
||||
|
|
@ -20,7 +21,3 @@ class ExcelToolkit(BaseExcelToolkit, AbstractToolkit):
|
|||
if working_directory is None:
|
||||
working_directory = env("file_save_path", os.path.expanduser("~/Downloads"))
|
||||
super().__init__(timeout=timeout, working_directory=working_directory)
|
||||
|
||||
@listen_toolkit(BaseExcelToolkit.extract_excel_content)
|
||||
def extract_excel_content(self, document_path: str) -> str:
|
||||
return super().extract_excel_content(document_path)
|
||||
|
|
|
|||
|
|
@ -5,10 +5,11 @@ from camel.toolkits import FileToolkit as BaseFileToolkit
|
|||
from app.component.environment import env
|
||||
from app.service.task import process_task
|
||||
from app.service.task import ActionWriteFileData, Agents, get_task_lock
|
||||
from app.utils.listen.toolkit_listen import listen_toolkit
|
||||
from app.utils.listen.toolkit_listen import auto_listen_toolkit, listen_toolkit
|
||||
from app.utils.toolkit.abstract_toolkit import AbstractToolkit
|
||||
|
||||
|
||||
@auto_listen_toolkit(BaseFileToolkit)
|
||||
class FileToolkit(BaseFileToolkit, AbstractToolkit):
|
||||
agent_name: str = Agents.document_agent
|
||||
|
||||
|
|
@ -54,15 +55,3 @@ class FileToolkit(BaseFileToolkit, AbstractToolkit):
|
|||
)
|
||||
)
|
||||
return res
|
||||
|
||||
@listen_toolkit(
|
||||
BaseFileToolkit.read_file,
|
||||
)
|
||||
def read_file(self, file_paths: str | list[str]) -> str | dict[str, str]:
|
||||
return super().read_file(file_paths)
|
||||
|
||||
@listen_toolkit(
|
||||
BaseFileToolkit.edit_file,
|
||||
)
|
||||
def edit_file(self, file_path: str, old_content: str, new_content: str) -> str:
|
||||
return super().edit_file(file_path, old_content, new_content)
|
||||
|
|
|
|||
|
|
@ -3,10 +3,11 @@ from camel.toolkits import GithubToolkit as BaseGithubToolkit
|
|||
from camel.toolkits.function_tool import FunctionTool
|
||||
from app.component.environment import env
|
||||
from app.service.task import Agents
|
||||
from app.utils.listen.toolkit_listen import listen_toolkit
|
||||
from app.utils.listen.toolkit_listen import auto_listen_toolkit
|
||||
from app.utils.toolkit.abstract_toolkit import AbstractToolkit
|
||||
|
||||
|
||||
@auto_listen_toolkit(BaseGithubToolkit)
|
||||
class GithubToolkit(BaseGithubToolkit, AbstractToolkit):
|
||||
agent_name: str = Agents.developer_agent
|
||||
|
||||
|
|
@ -19,86 +20,6 @@ class GithubToolkit(BaseGithubToolkit, AbstractToolkit):
|
|||
super().__init__(access_token, timeout)
|
||||
self.api_task_id = api_task_id
|
||||
|
||||
@listen_toolkit(
|
||||
BaseGithubToolkit.create_pull_request,
|
||||
lambda _,
|
||||
repo_name,
|
||||
file_path,
|
||||
new_content,
|
||||
pr_title,
|
||||
body,
|
||||
branch_name: f"Create PR in {repo_name} for {file_path} with title '{pr_title}', branch '{branch_name}', content '{new_content}'",
|
||||
)
|
||||
def create_pull_request(
|
||||
self,
|
||||
repo_name: str,
|
||||
file_path: str,
|
||||
new_content: str,
|
||||
pr_title: str,
|
||||
body: str,
|
||||
branch_name: str,
|
||||
) -> str:
|
||||
return super().create_pull_request(repo_name, file_path, new_content, pr_title, body, branch_name)
|
||||
|
||||
@listen_toolkit(
|
||||
BaseGithubToolkit.get_issue_list,
|
||||
lambda _, repo_name, state="all": f"Get issue list from {repo_name} with state '{state}'",
|
||||
lambda issues: f"Retrieved {len(issues)} issues",
|
||||
)
|
||||
def get_issue_list(
|
||||
self, repo_name: str, state: Literal["open", "closed", "all"] = "all"
|
||||
) -> list[dict[str, object]]:
|
||||
return super().get_issue_list(repo_name, state)
|
||||
|
||||
@listen_toolkit(
|
||||
BaseGithubToolkit.get_issue_content,
|
||||
lambda _, repo_name, issue_number: f"Get content of issue {issue_number} from {repo_name}",
|
||||
)
|
||||
def get_issue_content(self, repo_name: str, issue_number: int) -> str:
|
||||
return super().get_issue_content(repo_name, issue_number)
|
||||
|
||||
@listen_toolkit(
|
||||
BaseGithubToolkit.get_pull_request_list,
|
||||
lambda _, repo_name, state="all": f"Get pull request list from {repo_name} with state '{state}'",
|
||||
lambda prs: f"Retrieved {len(prs)} pull requests",
|
||||
)
|
||||
def get_pull_request_list(
|
||||
self, repo_name: str, state: Literal["open", "closed", "all"] = "all"
|
||||
) -> list[dict[str, object]]:
|
||||
return super().get_pull_request_list(repo_name, state)
|
||||
|
||||
@listen_toolkit(
|
||||
BaseGithubToolkit.get_pull_request_code,
|
||||
lambda _, repo_name, pr_number: f"Get code for pull request {pr_number} in {repo_name}",
|
||||
lambda code: f"Retrieved {len(code)} code files",
|
||||
)
|
||||
def get_pull_request_code(self, repo_name: str, pr_number: int) -> list[dict[str, str]]:
|
||||
return super().get_pull_request_code(repo_name, pr_number)
|
||||
|
||||
@listen_toolkit(
|
||||
BaseGithubToolkit.get_pull_request_comments,
|
||||
lambda _, repo_name, pr_number: f"Get comments for pull request {pr_number} in {repo_name}",
|
||||
lambda comments: f"Retrieved {len(comments)} comments",
|
||||
)
|
||||
def get_pull_request_comments(self, repo_name: str, pr_number: int) -> list[dict[str, str]]:
|
||||
return super().get_pull_request_comments(repo_name, pr_number)
|
||||
|
||||
@listen_toolkit(
|
||||
BaseGithubToolkit.get_all_file_paths,
|
||||
lambda _, repo_name, path="": f"Get all file paths from {repo_name}, path '{path}'",
|
||||
lambda paths: f"Retrieved {len(paths)} file paths",
|
||||
)
|
||||
def get_all_file_paths(self, repo_name: str, path: str = "") -> list[str]:
|
||||
return super().get_all_file_paths(repo_name, path)
|
||||
|
||||
@listen_toolkit(
|
||||
BaseGithubToolkit.retrieve_file_content,
|
||||
lambda _, repo_name, file_path: f"Retrieve content of file {file_path} from {repo_name}",
|
||||
lambda content: f"Retrieved content of length {len(content)}",
|
||||
)
|
||||
def retrieve_file_content(self, repo_name: str, file_path: str) -> str:
|
||||
return super().retrieve_file_content(repo_name, file_path)
|
||||
|
||||
@classmethod
|
||||
def get_can_use_tools(cls, api_task_id: str) -> list[FunctionTool]:
|
||||
if env("GITHUB_ACCESS_TOKEN"):
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
from typing import Any, Dict, List
|
||||
from app.component.environment import env
|
||||
from app.service.task import Agents
|
||||
from app.utils.listen.toolkit_listen import listen_toolkit
|
||||
from app.utils.listen.toolkit_listen import auto_listen_toolkit
|
||||
from app.utils.toolkit.abstract_toolkit import AbstractToolkit
|
||||
from camel.toolkits import GoogleCalendarToolkit as BaseGoogleCalendarToolkit
|
||||
|
||||
|
||||
@auto_listen_toolkit(BaseGoogleCalendarToolkit)
|
||||
class GoogleCalendarToolkit(BaseGoogleCalendarToolkit, AbstractToolkit):
|
||||
agent_name: str = Agents.social_medium_agent
|
||||
|
||||
|
|
@ -13,44 +14,6 @@ class GoogleCalendarToolkit(BaseGoogleCalendarToolkit, AbstractToolkit):
|
|||
self.api_task_id = api_task_id
|
||||
super().__init__(timeout)
|
||||
|
||||
@listen_toolkit(BaseGoogleCalendarToolkit.create_event)
|
||||
def create_event(
|
||||
self,
|
||||
event_title: str,
|
||||
start_time: str,
|
||||
end_time: str,
|
||||
description: str = "",
|
||||
location: str = "",
|
||||
attendees_email: List[str] | None = None,
|
||||
timezone: str = "UTC",
|
||||
) -> Dict[str, Any]:
|
||||
return super().create_event(event_title, start_time, end_time, description, location, attendees_email, timezone)
|
||||
|
||||
@listen_toolkit(BaseGoogleCalendarToolkit.get_events)
|
||||
def get_events(self, max_results: int = 10, time_min: str | None = None) -> List[Dict[str, Any]] | Dict[str, Any]:
|
||||
return super().get_events(max_results, time_min)
|
||||
|
||||
@listen_toolkit(BaseGoogleCalendarToolkit.update_event)
|
||||
def update_event(
|
||||
self,
|
||||
event_id: str,
|
||||
event_title: str | None = None,
|
||||
start_time: str | None = None,
|
||||
end_time: str | None = None,
|
||||
description: str | None = None,
|
||||
location: str | None = None,
|
||||
attendees_email: List[str] | None = None,
|
||||
) -> Dict[str, Any]:
|
||||
return super().update_event(event_id, event_title, start_time, end_time, description, location, attendees_email)
|
||||
|
||||
@listen_toolkit(BaseGoogleCalendarToolkit.delete_event)
|
||||
def delete_event(self, event_id: str) -> str:
|
||||
return super().delete_event(event_id)
|
||||
|
||||
@listen_toolkit(BaseGoogleCalendarToolkit.get_calendar_details)
|
||||
def get_calendar_details(self) -> Dict[str, Any]:
|
||||
return super().get_calendar_details()
|
||||
|
||||
@classmethod
|
||||
def get_can_use_tools(cls, api_task_id: str):
|
||||
if env("GOOGLE_CLIENT_ID") and env("GOOGLE_CLIENT_SECRET"):
|
||||
|
|
|
|||
|
|
@ -3,12 +3,13 @@ from camel.toolkits.base import BaseToolkit
|
|||
from loguru import logger
|
||||
from camel.toolkits.function_tool import FunctionTool
|
||||
from app.service.task import Action, ActionAskData, ActionNoticeData, get_task_lock
|
||||
from app.utils.listen.toolkit_listen import listen_toolkit
|
||||
from app.utils.listen.toolkit_listen import auto_listen_toolkit, listen_toolkit
|
||||
from app.utils.toolkit.abstract_toolkit import AbstractToolkit
|
||||
from app.service.task import process_task
|
||||
# Rewrite HumanToolkit because the system's user interaction was using console, but in electron we cannot use console. Changed to use SSE response to let frontend show dialog for user interaction
|
||||
|
||||
|
||||
@auto_listen_toolkit(BaseToolkit)
|
||||
class HumanToolkit(BaseToolkit, AbstractToolkit):
|
||||
r"""A class representing a toolkit for human interaction.
|
||||
Note:
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ from loguru import logger
|
|||
from app.component.environment import env
|
||||
from app.exception.exception import ProgramException
|
||||
from app.service.task import Agents
|
||||
from app.utils.listen.toolkit_listen import listen_toolkit
|
||||
from app.utils.listen.toolkit_listen import auto_listen_toolkit, listen_toolkit
|
||||
from app.utils.toolkit.abstract_toolkit import AbstractToolkit
|
||||
|
||||
|
||||
|
|
@ -124,6 +124,7 @@ class BrowserSession(BaseHybridBrowserSession):
|
|||
break
|
||||
|
||||
|
||||
@auto_listen_toolkit(BaseHybridBrowserToolkit)
|
||||
class HybridBrowserPythonToolkit(BaseHybridBrowserToolkit, AbstractToolkit):
|
||||
agent_name: str = Agents.search_agent
|
||||
|
||||
|
|
@ -224,14 +225,6 @@ class HybridBrowserPythonToolkit(BaseHybridBrowserToolkit, AbstractToolkit):
|
|||
self._agent: PlaywrightLLMAgent | None = None
|
||||
self._unified_script = self._load_unified_analyzer()
|
||||
|
||||
@listen_toolkit(BaseHybridBrowserToolkit.browser_open)
|
||||
async def browser_open(self) -> Dict[str, str]:
|
||||
return await super().browser_open()
|
||||
|
||||
@listen_toolkit(BaseHybridBrowserToolkit.browser_close)
|
||||
async def browser_close(self) -> str:
|
||||
return await super().browser_close()
|
||||
|
||||
@listen_toolkit(BaseHybridBrowserToolkit.browser_visit_page, lambda _, url: url)
|
||||
async def browser_visit_page(self, url: str) -> Dict[str, Any]:
|
||||
r"""Navigates to a URL.
|
||||
|
|
@ -282,66 +275,6 @@ class HybridBrowserPythonToolkit(BaseHybridBrowserToolkit, AbstractToolkit):
|
|||
|
||||
return {"result": nav_result, "snapshot": snapshot, **tab_info}
|
||||
|
||||
@listen_toolkit(BaseHybridBrowserToolkit.browser_back)
|
||||
async def browser_back(self) -> Dict[str, Any]:
|
||||
return await super().browser_back()
|
||||
|
||||
@listen_toolkit(BaseHybridBrowserToolkit.browser_forward)
|
||||
async def browser_forward(self) -> Dict[str, Any]:
|
||||
return await super().browser_forward()
|
||||
|
||||
@listen_toolkit(BaseHybridBrowserToolkit.browser_click)
|
||||
async def browser_click(self, *, ref: str) -> Dict[str, Any]:
|
||||
return await super().browser_click(ref=ref)
|
||||
|
||||
@listen_toolkit(BaseHybridBrowserToolkit.browser_type)
|
||||
async def browser_type(self, *, ref: str, text: str) -> Dict[str, Any]:
|
||||
return await super().browser_type(ref=ref, text=text)
|
||||
|
||||
@listen_toolkit(BaseHybridBrowserToolkit.browser_switch_tab)
|
||||
async def browser_switch_tab(self, *, tab_id: str) -> Dict[str, Any]:
|
||||
return await super().browser_switch_tab(tab_id=tab_id)
|
||||
|
||||
@listen_toolkit(BaseHybridBrowserToolkit.browser_select)
|
||||
async def browser_select(self, *, ref: str, value: str) -> Dict[str, str]:
|
||||
return await super().browser_select(ref=ref, value=value)
|
||||
|
||||
@listen_toolkit(BaseHybridBrowserToolkit.browser_scroll)
|
||||
async def browser_scroll(self, *, direction: str, amount: int) -> Dict[str, str]:
|
||||
return await super().browser_scroll(direction=direction, amount=amount)
|
||||
|
||||
@listen_toolkit(BaseHybridBrowserToolkit.browser_wait_user)
|
||||
async def browser_wait_user(self, timeout_sec: float | None = None) -> Dict[str, str]:
|
||||
return await super().browser_wait_user(timeout_sec)
|
||||
|
||||
@listen_toolkit(BaseHybridBrowserToolkit.browser_enter)
|
||||
async def browser_enter(self) -> Dict[str, str]:
|
||||
return await super().browser_enter()
|
||||
|
||||
@listen_toolkit(BaseHybridBrowserToolkit.browser_solve_task)
|
||||
async def browser_solve_task(self, task_prompt: str, start_url: str, max_steps: int = 15) -> str:
|
||||
return await super().browser_solve_task(task_prompt, start_url, max_steps)
|
||||
|
||||
@listen_toolkit(BaseHybridBrowserToolkit.browser_get_page_snapshot)
|
||||
async def browser_get_page_snapshot(self) -> str:
|
||||
return await super().browser_get_page_snapshot()
|
||||
|
||||
@listen_toolkit(BaseHybridBrowserToolkit.browser_get_som_screenshot)
|
||||
async def browser_get_som_screenshot(self):
|
||||
return await super().browser_get_som_screenshot()
|
||||
|
||||
@listen_toolkit(BaseHybridBrowserToolkit.browser_get_page_links)
|
||||
async def browser_get_page_links(self, *, ref: List[str]) -> Dict[str, Any]:
|
||||
return await super().browser_get_page_links(ref=ref)
|
||||
|
||||
@listen_toolkit(BaseHybridBrowserToolkit.browser_close_tab)
|
||||
async def browser_close_tab(self, *, tab_id: str) -> Dict[str, Any]:
|
||||
return await super().browser_close_tab(tab_id=tab_id)
|
||||
|
||||
@listen_toolkit(BaseHybridBrowserToolkit.browser_get_tab_info)
|
||||
async def browser_get_tab_info(self) -> Dict[str, Any]:
|
||||
return await super().browser_get_tab_info()
|
||||
|
||||
@classmethod
|
||||
def get_can_use_tools(cls, api_task_id: str) -> list[FunctionTool]:
|
||||
browser = HybridBrowserPythonToolkit(
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ from camel.toolkits.hybrid_browser_toolkit.ws_wrapper import WebSocketBrowserWra
|
|||
from app.component.command import bun, uv
|
||||
from app.component.environment import env
|
||||
from app.service.task import Agents
|
||||
from app.utils.listen.toolkit_listen import listen_toolkit
|
||||
from app.utils.listen.toolkit_listen import auto_listen_toolkit
|
||||
from app.utils.toolkit.abstract_toolkit import AbstractToolkit
|
||||
|
||||
|
||||
|
|
@ -210,6 +210,7 @@ class WebSocketConnectionPool:
|
|||
websocket_connection_pool = WebSocketConnectionPool()
|
||||
|
||||
|
||||
@auto_listen_toolkit(BaseHybridBrowserToolkit)
|
||||
class HybridBrowserToolkit(BaseHybridBrowserToolkit, AbstractToolkit):
|
||||
agent_name: str = Agents.search_agent
|
||||
|
||||
|
|
@ -240,7 +241,10 @@ class HybridBrowserToolkit(BaseHybridBrowserToolkit, AbstractToolkit):
|
|||
cdp_keep_current_page: bool = False,
|
||||
full_visual_mode: bool = False,
|
||||
) -> None:
|
||||
logger.info(f"[HybridBrowserToolkit] Initializing with api_task_id: {api_task_id}")
|
||||
self.api_task_id = api_task_id
|
||||
logger.debug(f"[HybridBrowserToolkit] api_task_id set to: {self.api_task_id}")
|
||||
logger.debug(f"[HybridBrowserToolkit] Calling super().__init__ with session_id: {session_id}")
|
||||
super().__init__(
|
||||
headless=headless,
|
||||
user_data_dir=user_data_dir,
|
||||
|
|
@ -264,16 +268,20 @@ class HybridBrowserToolkit(BaseHybridBrowserToolkit, AbstractToolkit):
|
|||
cdp_keep_current_page=cdp_keep_current_page,
|
||||
full_visual_mode=full_visual_mode,
|
||||
)
|
||||
logger.info(f"[HybridBrowserToolkit] Initialization complete for api_task_id: {self.api_task_id}")
|
||||
|
||||
async def _ensure_ws_wrapper(self):
|
||||
"""Ensure WebSocket wrapper is initialized using connection pool."""
|
||||
logger.debug(f"[HybridBrowserToolkit] _ensure_ws_wrapper called for api_task_id: {getattr(self, 'api_task_id', 'NOT SET')}")
|
||||
global websocket_connection_pool
|
||||
|
||||
# Get session ID from config or use default
|
||||
session_id = self._ws_config.get("session_id", "default")
|
||||
logger.debug(f"[HybridBrowserToolkit] Using session_id: {session_id}")
|
||||
|
||||
# Get or create connection from pool
|
||||
self._ws_wrapper = await websocket_connection_pool.get_connection(session_id, self._ws_config)
|
||||
logger.info(f"[HybridBrowserToolkit] WebSocket wrapper initialized for session: {session_id}")
|
||||
|
||||
# Additional health check
|
||||
if self._ws_wrapper.websocket is None:
|
||||
|
|
@ -336,74 +344,3 @@ class HybridBrowserToolkit(BaseHybridBrowserToolkit, AbstractToolkit):
|
|||
if hasattr(self, "_ws_wrapper") and self._ws_wrapper:
|
||||
session_id = self._ws_config.get("session_id", "default")
|
||||
logger.debug(f"HybridBrowserToolkit for session {session_id} is being garbage collected")
|
||||
|
||||
@listen_toolkit(BaseHybridBrowserToolkit.browser_open)
|
||||
async def browser_open(self) -> Dict[str, Any]:
|
||||
return await super().browser_open()
|
||||
|
||||
@listen_toolkit(BaseHybridBrowserToolkit.browser_close)
|
||||
async def browser_close(self) -> str:
|
||||
return await super().browser_close()
|
||||
|
||||
@listen_toolkit(BaseHybridBrowserToolkit.browser_visit_page)
|
||||
async def browser_visit_page(self, url: str) -> Dict[str, Any]:
|
||||
logger.debug(f"browser_visit_page called with URL: {url}")
|
||||
try:
|
||||
result = await super().browser_visit_page(url)
|
||||
logger.debug(f"browser_visit_page succeeded for URL: {url}")
|
||||
return result
|
||||
except Exception as e:
|
||||
logger.error(f"browser_visit_page failed for URL {url}: {type(e).__name__}: {e}")
|
||||
raise
|
||||
|
||||
@listen_toolkit(BaseHybridBrowserToolkit.browser_back)
|
||||
async def browser_back(self) -> Dict[str, Any]:
|
||||
return await super().browser_back()
|
||||
|
||||
@listen_toolkit(BaseHybridBrowserToolkit.browser_forward)
|
||||
async def browser_forward(self) -> Dict[str, Any]:
|
||||
return await super().browser_forward()
|
||||
|
||||
@listen_toolkit(BaseHybridBrowserToolkit.browser_get_page_snapshot)
|
||||
async def browser_get_page_snapshot(self) -> str:
|
||||
return await super().browser_get_page_snapshot()
|
||||
|
||||
@listen_toolkit(BaseHybridBrowserToolkit.browser_get_som_screenshot)
|
||||
async def browser_get_som_screenshot(self, read_image: bool = False, instruction: str | None = None) -> str:
|
||||
return await super().browser_get_som_screenshot(read_image, instruction)
|
||||
|
||||
@listen_toolkit(BaseHybridBrowserToolkit.browser_click)
|
||||
async def browser_click(self, *, ref: str) -> Dict[str, Any]:
|
||||
return await super().browser_click(ref=ref)
|
||||
|
||||
@listen_toolkit(BaseHybridBrowserToolkit.browser_type)
|
||||
async def browser_type(self, *, ref: str, text: str) -> Dict[str, Any]:
|
||||
return await super().browser_type(ref=ref, text=text)
|
||||
|
||||
@listen_toolkit(BaseHybridBrowserToolkit.browser_select)
|
||||
async def browser_select(self, *, ref: str, value: str) -> Dict[str, Any]:
|
||||
return await super().browser_select(ref=ref, value=value)
|
||||
|
||||
@listen_toolkit(BaseHybridBrowserToolkit.browser_scroll)
|
||||
async def browser_scroll(self, *, direction: str, amount: int = 500) -> Dict[str, Any]:
|
||||
return await super().browser_scroll(direction=direction, amount=amount)
|
||||
|
||||
@listen_toolkit(BaseHybridBrowserToolkit.browser_enter)
|
||||
async def browser_enter(self) -> Dict[str, Any]:
|
||||
return await super().browser_enter()
|
||||
|
||||
@listen_toolkit(BaseHybridBrowserToolkit.browser_wait_user)
|
||||
async def browser_wait_user(self, timeout_sec: float | None = None) -> Dict[str, Any]:
|
||||
return await super().browser_wait_user(timeout_sec)
|
||||
|
||||
@listen_toolkit(BaseHybridBrowserToolkit.browser_switch_tab)
|
||||
async def browser_switch_tab(self, *, tab_id: str) -> Dict[str, Any]:
|
||||
return await super().browser_switch_tab(tab_id=tab_id)
|
||||
|
||||
@listen_toolkit(BaseHybridBrowserToolkit.browser_close_tab)
|
||||
async def browser_close_tab(self, *, tab_id: str) -> Dict[str, Any]:
|
||||
return await super().browser_close_tab(tab_id=tab_id)
|
||||
|
||||
@listen_toolkit(BaseHybridBrowserToolkit.browser_get_tab_info)
|
||||
async def browser_get_tab_info(self) -> Dict[str, Any]:
|
||||
return await super().browser_get_tab_info()
|
||||
|
|
|
|||
|
|
@ -2,10 +2,11 @@ from camel.models import BaseModelBackend
|
|||
from camel.toolkits import ImageAnalysisToolkit as BaseImageAnalysisToolkit
|
||||
|
||||
from app.service.task import Agents
|
||||
from app.utils.listen.toolkit_listen import listen_toolkit
|
||||
from app.utils.listen.toolkit_listen import auto_listen_toolkit
|
||||
from app.utils.toolkit.abstract_toolkit import AbstractToolkit
|
||||
|
||||
|
||||
@auto_listen_toolkit(BaseImageAnalysisToolkit)
|
||||
class ImageAnalysisToolkit(BaseImageAnalysisToolkit, AbstractToolkit):
|
||||
agent_name: str = Agents.multi_modal_agent
|
||||
|
||||
|
|
@ -17,24 +18,3 @@ class ImageAnalysisToolkit(BaseImageAnalysisToolkit, AbstractToolkit):
|
|||
):
|
||||
super().__init__(model, timeout)
|
||||
self.api_task_id = api_task_id
|
||||
|
||||
@listen_toolkit(
|
||||
BaseImageAnalysisToolkit.image_to_text,
|
||||
lambda _,
|
||||
image_path,
|
||||
sys_prompt: f"transcribe image from {image_path} and ask sys_prompt: {sys_prompt}",
|
||||
)
|
||||
def image_to_text(self, image_path: str, sys_prompt: str | None = None) -> str:
|
||||
return super().image_to_text(image_path, sys_prompt)
|
||||
|
||||
@listen_toolkit(
|
||||
BaseImageAnalysisToolkit.ask_question_about_image,
|
||||
lambda _,
|
||||
image_path,
|
||||
question,
|
||||
sys_prompt: f"transcribe image from {image_path} and ask question: {question} with sys_prompt: {sys_prompt}",
|
||||
)
|
||||
def ask_question_about_image(
|
||||
self, image_path: str, question: str, sys_prompt: str | None = None
|
||||
) -> str:
|
||||
return super().ask_question_about_image(image_path, question, sys_prompt)
|
||||
|
|
|
|||
|
|
@ -2,10 +2,11 @@ from camel.toolkits import LinkedInToolkit as BaseLinkedInToolkit
|
|||
from camel.toolkits.function_tool import FunctionTool
|
||||
from app.component.environment import env
|
||||
from app.service.task import Agents
|
||||
from app.utils.listen.toolkit_listen import listen_toolkit
|
||||
from app.utils.listen.toolkit_listen import auto_listen_toolkit
|
||||
from app.utils.toolkit.abstract_toolkit import AbstractToolkit
|
||||
|
||||
|
||||
@auto_listen_toolkit(BaseLinkedInToolkit)
|
||||
class LinkedInToolkit(BaseLinkedInToolkit, AbstractToolkit):
|
||||
agent_name: str = Agents.social_medium_agent
|
||||
|
||||
|
|
@ -13,27 +14,6 @@ class LinkedInToolkit(BaseLinkedInToolkit, AbstractToolkit):
|
|||
super().__init__(timeout)
|
||||
self.api_task_id = api_task_id
|
||||
|
||||
@listen_toolkit(
|
||||
BaseLinkedInToolkit.create_post,
|
||||
lambda _, text: f"create a LinkedIn post with text: {text}",
|
||||
)
|
||||
def create_post(self, text: str) -> dict:
|
||||
return super().create_post(text)
|
||||
|
||||
@listen_toolkit(
|
||||
BaseLinkedInToolkit.delete_post,
|
||||
lambda _, post_id: f"delete LinkedIn post with id: {post_id}",
|
||||
)
|
||||
def delete_post(self, post_id: str) -> str:
|
||||
return super().delete_post(post_id)
|
||||
|
||||
@listen_toolkit(
|
||||
BaseLinkedInToolkit.get_profile,
|
||||
lambda _, include_id: f"get LinkedIn profile with include_id: {include_id}",
|
||||
)
|
||||
def get_profile(self, include_id: bool = False) -> dict:
|
||||
return super().get_profile(include_id)
|
||||
|
||||
@classmethod
|
||||
def get_can_use_tools(cls, api_task_id: str) -> list[FunctionTool]:
|
||||
if env("LINKEDIN_ACCESS_TOKEN"):
|
||||
|
|
|
|||
|
|
@ -2,17 +2,14 @@ from typing import Dict, List
|
|||
from camel.toolkits import MarkItDownToolkit as BaseMarkItDownToolkit
|
||||
|
||||
from app.service.task import Agents
|
||||
from app.utils.listen.toolkit_listen import listen_toolkit
|
||||
from app.utils.listen.toolkit_listen import auto_listen_toolkit
|
||||
from app.utils.toolkit.abstract_toolkit import AbstractToolkit
|
||||
|
||||
|
||||
@auto_listen_toolkit(BaseMarkItDownToolkit)
|
||||
class MarkItDownToolkit(BaseMarkItDownToolkit, AbstractToolkit):
|
||||
agent_name: str = Agents.document_agent
|
||||
|
||||
def __init__(self, api_task_id: str, timeout: float | None = None):
|
||||
self.api_task_id = api_task_id
|
||||
super().__init__(timeout)
|
||||
|
||||
@listen_toolkit(BaseMarkItDownToolkit.read_files)
|
||||
def read_files(self, file_paths: List[str]) -> Dict[str, str]:
|
||||
return super().read_files(file_paths)
|
||||
|
|
|
|||
|
|
@ -5,10 +5,11 @@ from typing import Optional
|
|||
|
||||
from app.component.environment import env
|
||||
from app.service.task import Agents
|
||||
from app.utils.listen.toolkit_listen import listen_toolkit
|
||||
from app.utils.listen.toolkit_listen import auto_listen_toolkit
|
||||
from app.utils.toolkit.abstract_toolkit import AbstractToolkit
|
||||
|
||||
|
||||
@auto_listen_toolkit(BaseNoteTakingToolkit)
|
||||
class NoteTakingToolkit(BaseNoteTakingToolkit, AbstractToolkit):
|
||||
agent_name: str = Agents.document_agent
|
||||
|
||||
|
|
@ -25,19 +26,3 @@ class NoteTakingToolkit(BaseNoteTakingToolkit, AbstractToolkit):
|
|||
if working_directory is None:
|
||||
working_directory = env("file_save_path", os.path.expanduser("~/.eigent/notes")) + "/note.md"
|
||||
super().__init__(working_directory=working_directory, timeout=timeout)
|
||||
|
||||
@listen_toolkit(BaseNoteTakingToolkit.append_note)
|
||||
def append_note(self, note_name: str, content: str) -> str:
|
||||
return super().append_note(note_name=note_name, content=content)
|
||||
|
||||
@listen_toolkit(BaseNoteTakingToolkit.read_note)
|
||||
def read_note(self, note_name: Optional[str] = "all_notes") -> str:
|
||||
return super().read_note(note_name=note_name)
|
||||
|
||||
@listen_toolkit(BaseNoteTakingToolkit.create_note)
|
||||
def create_note(self, note_name: str, content: str, overwrite: bool = False) -> str:
|
||||
return super().create_note(note_name=note_name, content=content, overwrite=overwrite)
|
||||
|
||||
@listen_toolkit(BaseNoteTakingToolkit.list_note)
|
||||
def list_note(self) -> str:
|
||||
return super().list_note()
|
||||
|
|
|
|||
|
|
@ -3,10 +3,11 @@ from camel.toolkits import NotionToolkit as BaseNotionToolkit
|
|||
from camel.toolkits.function_tool import FunctionTool
|
||||
from app.component.environment import env
|
||||
from app.service.task import Agents
|
||||
from app.utils.listen.toolkit_listen import listen_toolkit
|
||||
from app.utils.listen.toolkit_listen import auto_listen_toolkit
|
||||
from app.utils.toolkit.abstract_toolkit import AbstractToolkit
|
||||
|
||||
|
||||
@auto_listen_toolkit(BaseNotionToolkit)
|
||||
class NotionToolkit(BaseNotionToolkit, AbstractToolkit):
|
||||
agent_name: str = Agents.document_agent
|
||||
|
||||
|
|
@ -19,29 +20,6 @@ class NotionToolkit(BaseNotionToolkit, AbstractToolkit):
|
|||
super().__init__(notion_token, timeout)
|
||||
self.api_task_id = api_task_id
|
||||
|
||||
@listen_toolkit(
|
||||
BaseNotionToolkit.list_all_pages,
|
||||
lambda _: "list all pages in Notion workspace",
|
||||
lambda result: f"{len(result)} pages found",
|
||||
)
|
||||
def list_all_pages(self) -> List[dict]:
|
||||
return super().list_all_pages()
|
||||
|
||||
@listen_toolkit(
|
||||
BaseNotionToolkit.list_all_users,
|
||||
lambda _: "list all users in Notion workspace",
|
||||
lambda result: f"{len(result)} users found",
|
||||
)
|
||||
def list_all_users(self) -> List[dict]:
|
||||
return super().list_all_users()
|
||||
|
||||
@listen_toolkit(
|
||||
BaseNotionToolkit.get_notion_block_text_content,
|
||||
lambda _, page_id: f"get text content of page with id: {page_id}",
|
||||
)
|
||||
def get_notion_block_text_content(self, block_id: str) -> str:
|
||||
return super().get_notion_block_text_content(block_id)
|
||||
|
||||
@classmethod
|
||||
def get_can_use_tools(cls, api_task_id: str) -> List[FunctionTool]:
|
||||
if env("NOTION_TOKEN"):
|
||||
|
|
|
|||
|
|
@ -3,11 +3,12 @@ from camel.toolkits import OpenAIImageToolkit as BaseOpenAIImageToolkit
|
|||
|
||||
from app.component.environment import env
|
||||
from app.service.task import Agents
|
||||
from app.utils.listen.toolkit_listen import listen_toolkit
|
||||
from app.utils.listen.toolkit_listen import auto_listen_toolkit, listen_toolkit
|
||||
from app.utils.toolkit.abstract_toolkit import AbstractToolkit
|
||||
from typing import Literal, Optional, Union, List
|
||||
|
||||
|
||||
@auto_listen_toolkit(BaseOpenAIImageToolkit)
|
||||
class OpenAIImageToolkit(BaseOpenAIImageToolkit, AbstractToolkit):
|
||||
agent_name: str = Agents.multi_modal_agent
|
||||
|
||||
|
|
|
|||
|
|
@ -4,11 +4,12 @@ from camel.toolkits import PPTXToolkit as BasePPTXToolkit
|
|||
|
||||
from app.component.environment import env
|
||||
from app.service.task import ActionWriteFileData, Agents, get_task_lock
|
||||
from app.utils.listen.toolkit_listen import listen_toolkit
|
||||
from app.utils.listen.toolkit_listen import auto_listen_toolkit, listen_toolkit
|
||||
from app.utils.toolkit.abstract_toolkit import AbstractToolkit
|
||||
from app.service.task import process_task
|
||||
|
||||
|
||||
@auto_listen_toolkit(BasePPTXToolkit)
|
||||
class PPTXToolkit(BasePPTXToolkit, AbstractToolkit):
|
||||
agent_name: str = Agents.document_agent
|
||||
|
||||
|
|
|
|||
|
|
@ -4,10 +4,11 @@ from camel.toolkits import PyAutoGUIToolkit as BasePyAutoGUIToolkit
|
|||
|
||||
from app.component.environment import env
|
||||
from app.service.task import Agents
|
||||
from app.utils.listen.toolkit_listen import listen_toolkit
|
||||
from app.utils.listen.toolkit_listen import auto_listen_toolkit
|
||||
from app.utils.toolkit.abstract_toolkit import AbstractToolkit
|
||||
|
||||
|
||||
@auto_listen_toolkit(BasePyAutoGUIToolkit)
|
||||
class PyAutoGUIToolkit(BasePyAutoGUIToolkit, AbstractToolkit):
|
||||
agent_name: str = Agents.search_agent
|
||||
|
||||
|
|
@ -21,69 +22,3 @@ class PyAutoGUIToolkit(BasePyAutoGUIToolkit, AbstractToolkit):
|
|||
screenshots_dir = env("file_save_path", os.path.expanduser("~/Downloads"))
|
||||
super().__init__(timeout, screenshots_dir)
|
||||
self.api_task_id = api_task_id
|
||||
|
||||
@listen_toolkit(BasePyAutoGUIToolkit.mouse_move, lambda _, x, y: f"mouse move to {x}, {y}")
|
||||
def mouse_move(self, x: int, y: int) -> str:
|
||||
return super().mouse_move(x, y)
|
||||
|
||||
@listen_toolkit(
|
||||
BasePyAutoGUIToolkit.mouse_click,
|
||||
lambda _, button="left", clicks=1, x=None, y=None: f"mouse click {button} {clicks} times at {x}, {y}",
|
||||
)
|
||||
def mouse_click(
|
||||
self,
|
||||
button: Literal["left", "middle", "right"] = "left",
|
||||
clicks: int = 1,
|
||||
x: int | None = None,
|
||||
y: int | None = None,
|
||||
) -> str:
|
||||
return super().mouse_click(button, clicks, x, y)
|
||||
|
||||
@listen_toolkit(
|
||||
BasePyAutoGUIToolkit.keyboard_type,
|
||||
lambda _, text, interval=0: f"keyboard type {text}, interval {interval}",
|
||||
)
|
||||
def keyboard_type(self, text: str, interval: float = 0) -> str:
|
||||
return super().keyboard_type(text, interval)
|
||||
|
||||
@listen_toolkit(BasePyAutoGUIToolkit.take_screenshot)
|
||||
def take_screenshot(self) -> str:
|
||||
return super().take_screenshot()
|
||||
|
||||
@listen_toolkit(BasePyAutoGUIToolkit.get_mouse_position)
|
||||
def get_mouse_position(self) -> str:
|
||||
return super().get_mouse_position()
|
||||
|
||||
@listen_toolkit(BasePyAutoGUIToolkit.press_key, lambda _, key: f"press key {key}")
|
||||
def press_key(self, key: str | list[str]) -> str:
|
||||
return super().press_key(key)
|
||||
|
||||
@listen_toolkit(BasePyAutoGUIToolkit.hotkey, lambda _, keys: f"hotkey {keys}")
|
||||
def hotkey(self, keys: List[str]) -> str:
|
||||
return super().hotkey(keys)
|
||||
|
||||
@listen_toolkit(
|
||||
BasePyAutoGUIToolkit.mouse_drag,
|
||||
lambda _,
|
||||
start_x,
|
||||
start_y,
|
||||
end_x,
|
||||
end_y,
|
||||
button="left": f"mouse drag from {start_x}, {start_y} to {end_x}, {end_y} with {button} button",
|
||||
)
|
||||
def mouse_drag(
|
||||
self,
|
||||
start_x: int,
|
||||
start_y: int,
|
||||
end_x: int,
|
||||
end_y: int,
|
||||
button: Literal["left", "middle", "right"] = "left",
|
||||
) -> str:
|
||||
return super().mouse_drag(start_x, start_y, end_x, end_y, button)
|
||||
|
||||
@listen_toolkit(
|
||||
BasePyAutoGUIToolkit.scroll,
|
||||
lambda _, scroll_amount, x=None, y=None: f"scroll {scroll_amount} at {x}, {y}",
|
||||
)
|
||||
def scroll(self, scroll_amount: int, x: int | None = None, y: int | None = None) -> str:
|
||||
return super().scroll(scroll_amount, x, y)
|
||||
|
|
|
|||
|
|
@ -3,10 +3,11 @@ from camel.toolkits import RedditToolkit as BaseRedditToolkit
|
|||
from camel.toolkits.function_tool import FunctionTool
|
||||
from app.component.environment import env
|
||||
from app.service.task import Agents
|
||||
from app.utils.listen.toolkit_listen import listen_toolkit
|
||||
from app.utils.listen.toolkit_listen import auto_listen_toolkit
|
||||
from app.utils.toolkit.abstract_toolkit import AbstractToolkit
|
||||
|
||||
|
||||
@auto_listen_toolkit(BaseRedditToolkit)
|
||||
class RedditToolkit(BaseRedditToolkit, AbstractToolkit):
|
||||
agent_name: str = Agents.social_medium_agent
|
||||
|
||||
|
|
@ -20,47 +21,6 @@ class RedditToolkit(BaseRedditToolkit, AbstractToolkit):
|
|||
super().__init__(retries, delay, timeout)
|
||||
self.api_task_id = api_task_id
|
||||
|
||||
@listen_toolkit(
|
||||
BaseRedditToolkit.collect_top_posts,
|
||||
lambda _,
|
||||
subreddit_name,
|
||||
post_limit=5,
|
||||
comment_limit=5: f"collect top posts from subreddit: {subreddit_name} with post limit: {post_limit} and comment limit: {comment_limit}",
|
||||
lambda result: f"top posts collected: {result}",
|
||||
)
|
||||
def collect_top_posts(
|
||||
self, subreddit_name: str, post_limit: int = 5, comment_limit: int = 5
|
||||
) -> List[Dict[str, Any]] | str:
|
||||
return super().collect_top_posts(subreddit_name, post_limit, comment_limit)
|
||||
|
||||
@listen_toolkit(
|
||||
BaseRedditToolkit.perform_sentiment_analysis,
|
||||
lambda _, data: f"perform sentiment analysis on data number: {len(data)}",
|
||||
lambda result: f"perform analysis result: {result}",
|
||||
)
|
||||
def perform_sentiment_analysis(self, data: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
|
||||
return super().perform_sentiment_analysis(data)
|
||||
|
||||
@listen_toolkit(
|
||||
BaseRedditToolkit.track_keyword_discussions,
|
||||
lambda _,
|
||||
subreddits,
|
||||
keywords,
|
||||
post_limit=10,
|
||||
comment_limit=10,
|
||||
sentiment_analysis=False: f"track keyword discussions for subreddits: {subreddits}, keywords: {keywords}",
|
||||
lambda result: f"track keyword discussions result: {result}",
|
||||
)
|
||||
def track_keyword_discussions(
|
||||
self,
|
||||
subreddits: List[str],
|
||||
keywords: List[str],
|
||||
post_limit: int = 10,
|
||||
comment_limit: int = 10,
|
||||
sentiment_analysis: bool = False,
|
||||
) -> List[Dict[str, Any]] | str:
|
||||
return super().track_keyword_discussions(subreddits, keywords, post_limit, comment_limit, sentiment_analysis)
|
||||
|
||||
@classmethod
|
||||
def get_can_use_tools(cls, api_task_id: str) -> list[FunctionTool]:
|
||||
if env("REDDIT_CLIENT_ID") and env("REDDIT_CLIENT_SECRET") and env("REDDIT_USER_AGENT"):
|
||||
|
|
|
|||
|
|
@ -3,10 +3,11 @@ from camel.toolkits import ScreenshotToolkit as BaseScreenshotToolkit
|
|||
|
||||
from app.component.environment import env
|
||||
from app.service.task import Agents
|
||||
from app.utils.listen.toolkit_listen import listen_toolkit
|
||||
from app.utils.listen.toolkit_listen import auto_listen_toolkit
|
||||
from app.utils.toolkit.abstract_toolkit import AbstractToolkit
|
||||
|
||||
|
||||
@auto_listen_toolkit(BaseScreenshotToolkit)
|
||||
class ScreenshotToolkit(BaseScreenshotToolkit, AbstractToolkit):
|
||||
agent_name: str = Agents.developer_agent
|
||||
|
||||
|
|
@ -15,13 +16,3 @@ class ScreenshotToolkit(BaseScreenshotToolkit, AbstractToolkit):
|
|||
if working_directory is None:
|
||||
working_directory = env("file_save_path", os.path.expanduser("~/Downloads"))
|
||||
super().__init__(working_directory, timeout)
|
||||
|
||||
@listen_toolkit(BaseScreenshotToolkit.take_screenshot_and_read_image)
|
||||
def take_screenshot_and_read_image(
|
||||
self, filename: str, save_to_file: bool = True, read_image: bool = True, instruction: str | None = None
|
||||
) -> str:
|
||||
return super().take_screenshot_and_read_image(filename, save_to_file, read_image, instruction)
|
||||
|
||||
@listen_toolkit(BaseScreenshotToolkit.read_image)
|
||||
def read_image(self, image_path: str, instruction: str = "") -> str:
|
||||
return super().read_image(image_path, instruction)
|
||||
|
|
|
|||
|
|
@ -5,10 +5,11 @@ import httpx
|
|||
from loguru import logger
|
||||
from app.component.environment import env, env_not_empty
|
||||
from app.service.task import Agents
|
||||
from app.utils.listen.toolkit_listen import listen_toolkit
|
||||
from app.utils.listen.toolkit_listen import auto_listen_toolkit, listen_toolkit
|
||||
from app.utils.toolkit.abstract_toolkit import AbstractToolkit
|
||||
|
||||
|
||||
@auto_listen_toolkit(BaseSearchToolkit)
|
||||
class SearchToolkit(BaseSearchToolkit, AbstractToolkit):
|
||||
agent_name: str = Agents.search_agent
|
||||
|
||||
|
|
|
|||
|
|
@ -3,10 +3,11 @@ from camel.toolkits.function_tool import FunctionTool
|
|||
from loguru import logger
|
||||
from app.component.environment import env
|
||||
from app.service.task import Agents
|
||||
from app.utils.listen.toolkit_listen import listen_toolkit
|
||||
from app.utils.listen.toolkit_listen import auto_listen_toolkit
|
||||
from app.utils.toolkit.abstract_toolkit import AbstractToolkit
|
||||
|
||||
|
||||
@auto_listen_toolkit(BaseSlackToolkit)
|
||||
class SlackToolkit(BaseSlackToolkit, AbstractToolkit):
|
||||
agent_name: str = Agents.social_medium_agent
|
||||
|
||||
|
|
@ -14,71 +15,6 @@ class SlackToolkit(BaseSlackToolkit, AbstractToolkit):
|
|||
super().__init__(timeout)
|
||||
self.api_task_id = api_task_id
|
||||
|
||||
@listen_toolkit(
|
||||
BaseSlackToolkit.create_slack_channel,
|
||||
lambda _, name, is_private=True: f"create a Slack channel with name: {name} and is_private: {is_private}",
|
||||
)
|
||||
def create_slack_channel(self, name: str, is_private: bool | None = True) -> str:
|
||||
return super().create_slack_channel(name, is_private)
|
||||
|
||||
@listen_toolkit(
|
||||
BaseSlackToolkit.join_slack_channel,
|
||||
lambda _, channel_id: f"join Slack channel with id: {channel_id}",
|
||||
)
|
||||
def join_slack_channel(self, channel_id: str) -> str:
|
||||
return super().join_slack_channel(channel_id)
|
||||
|
||||
@listen_toolkit(
|
||||
BaseSlackToolkit.leave_slack_channel,
|
||||
lambda _, channel_id: f"leave Slack channel with id: {channel_id}",
|
||||
)
|
||||
def leave_slack_channel(self, channel_id: str) -> str:
|
||||
return super().leave_slack_channel(channel_id)
|
||||
|
||||
@listen_toolkit(
|
||||
BaseSlackToolkit.get_slack_channel_information,
|
||||
lambda _: "get Slack channel information",
|
||||
)
|
||||
def get_slack_channel_information(self) -> str:
|
||||
return super().get_slack_channel_information()
|
||||
|
||||
@listen_toolkit(
|
||||
BaseSlackToolkit.get_slack_channel_message,
|
||||
lambda _, channel_id: f"get Slack channel message for channel id: {channel_id}",
|
||||
)
|
||||
def get_slack_channel_message(self, channel_id: str) -> str:
|
||||
return super().get_slack_channel_message(channel_id)
|
||||
|
||||
@listen_toolkit(
|
||||
BaseSlackToolkit.send_slack_message,
|
||||
lambda _, message, channel_id, file_path=None, user=None: f"send Slack message: {message} to channel id: {channel_id}, file: {file_path}, user: {user}",
|
||||
)
|
||||
def send_slack_message(self, message: str, channel_id: str, file_path: str | None = None, user: str | None = None) -> str:
|
||||
return super().send_slack_message(message, channel_id, file_path, user)
|
||||
|
||||
@listen_toolkit(
|
||||
BaseSlackToolkit.delete_slack_message,
|
||||
lambda _,
|
||||
time_stamp,
|
||||
channel_id: f"delete Slack message with timestamp: {time_stamp} in channel id: {channel_id}",
|
||||
)
|
||||
def delete_slack_message(self, time_stamp: str, channel_id: str) -> str:
|
||||
return super().delete_slack_message(time_stamp, channel_id)
|
||||
|
||||
@listen_toolkit(
|
||||
BaseSlackToolkit.get_slack_user_list,
|
||||
lambda _: "get Slack user list",
|
||||
)
|
||||
def get_slack_user_list(self) -> str:
|
||||
return super().get_slack_user_list()
|
||||
|
||||
@listen_toolkit(
|
||||
BaseSlackToolkit.get_slack_user_info,
|
||||
lambda _, user_id: f"get Slack user info with user id: {user_id}",
|
||||
)
|
||||
def get_slack_user_info(self, user_id: str) -> str:
|
||||
return super().get_slack_user_info(user_id)
|
||||
|
||||
@classmethod
|
||||
def get_can_use_tools(cls, api_task_id: str) -> list[FunctionTool]:
|
||||
logger.debug(f"slack===={env('SLACK_BOT_TOKEN')}")
|
||||
|
|
|
|||
|
|
@ -4,11 +4,12 @@ from camel.toolkits.terminal_toolkit import TerminalToolkit as BaseTerminalToolk
|
|||
from camel.toolkits.terminal_toolkit.terminal_toolkit import _to_plain
|
||||
from app.component.environment import env
|
||||
from app.service.task import Action, ActionTerminalData, Agents, get_task_lock
|
||||
from app.utils.listen.toolkit_listen import listen_toolkit
|
||||
from app.utils.listen.toolkit_listen import auto_listen_toolkit
|
||||
from app.utils.toolkit.abstract_toolkit import AbstractToolkit
|
||||
from app.service.task import process_task
|
||||
|
||||
|
||||
@auto_listen_toolkit(BaseTerminalToolkit)
|
||||
class TerminalToolkit(BaseTerminalToolkit, AbstractToolkit):
|
||||
agent_name: str = Agents.developer_agent
|
||||
|
||||
|
|
@ -67,45 +68,3 @@ class TerminalToolkit(BaseTerminalToolkit, AbstractToolkit):
|
|||
)
|
||||
if hasattr(task_lock, "add_background_task"):
|
||||
task_lock.add_background_task(task)
|
||||
|
||||
@listen_toolkit(
|
||||
BaseTerminalToolkit.shell_exec,
|
||||
lambda _, id, command, block=True: f"id: {id}, command: {command}, block: {block}",
|
||||
)
|
||||
def shell_exec(self, id: str, command: str, block: bool = True) -> str:
|
||||
return super().shell_exec(id=id, command=command, block=block)
|
||||
|
||||
@listen_toolkit(
|
||||
BaseTerminalToolkit.shell_view,
|
||||
lambda _, id: f"id: {id}",
|
||||
)
|
||||
def shell_view(self, id: str) -> str:
|
||||
return super().shell_view(id)
|
||||
|
||||
@listen_toolkit(
|
||||
BaseTerminalToolkit.shell_wait,
|
||||
lambda _, id, wait_seconds=None: f"id: {id}, wait_seconds: {wait_seconds}",
|
||||
)
|
||||
def shell_wait(self, id: str, wait_seconds: float = 5.0) -> str:
|
||||
return super().shell_wait(id=id, wait_seconds=wait_seconds)
|
||||
|
||||
@listen_toolkit(
|
||||
BaseTerminalToolkit.shell_write_to_process,
|
||||
lambda _, id, command: f"id: {id}, command: {command}",
|
||||
)
|
||||
def shell_write_to_process(self, id: str, command: str) -> str:
|
||||
return super().shell_write_to_process(id=id, command=command)
|
||||
|
||||
@listen_toolkit(
|
||||
BaseTerminalToolkit.shell_kill_process,
|
||||
lambda _, id: f"id: {id}",
|
||||
)
|
||||
def shell_kill_process(self, id: str) -> str:
|
||||
return super().shell_kill_process(id=id)
|
||||
|
||||
@listen_toolkit(
|
||||
BaseTerminalToolkit.shell_ask_user_for_help,
|
||||
lambda _, id, prompt: f"id: {id}, prompt: {prompt}",
|
||||
)
|
||||
def shell_ask_user_for_help(self, id: str, prompt: str) -> str:
|
||||
return super().shell_ask_user_for_help(id=id, prompt=prompt)
|
||||
|
|
|
|||
|
|
@ -1,40 +1,13 @@
|
|||
from camel.toolkits import ThinkingToolkit as BaseThinkingToolkit
|
||||
|
||||
from app.utils.listen.toolkit_listen import listen_toolkit
|
||||
from app.utils.listen.toolkit_listen import auto_listen_toolkit
|
||||
from app.utils.toolkit.abstract_toolkit import AbstractToolkit
|
||||
|
||||
|
||||
@auto_listen_toolkit(BaseThinkingToolkit)
|
||||
class ThinkingToolkit(BaseThinkingToolkit, AbstractToolkit):
|
||||
|
||||
def __init__(self, api_task_id: str, agent_name: str, timeout: float | None = None):
|
||||
super().__init__(timeout)
|
||||
self.api_task_id = api_task_id
|
||||
self.agent_name = agent_name
|
||||
|
||||
@listen_toolkit(BaseThinkingToolkit.plan)
|
||||
def plan(self, plan: str) -> str:
|
||||
return super().plan(plan)
|
||||
|
||||
@listen_toolkit(BaseThinkingToolkit.hypothesize)
|
||||
def hypothesize(self, hypothesis: str) -> str:
|
||||
return super().hypothesize(hypothesis)
|
||||
|
||||
@listen_toolkit(BaseThinkingToolkit.think)
|
||||
def think(self, thought: str) -> str:
|
||||
return super().think(thought)
|
||||
|
||||
@listen_toolkit(BaseThinkingToolkit.contemplate)
|
||||
def contemplate(self, contemplation: str) -> str:
|
||||
return super().contemplate(contemplation)
|
||||
|
||||
@listen_toolkit(BaseThinkingToolkit.critique)
|
||||
def critique(self, critique: str) -> str:
|
||||
return super().critique(critique)
|
||||
|
||||
@listen_toolkit(BaseThinkingToolkit.synthesize)
|
||||
def synthesize(self, synthesis: str) -> str:
|
||||
return super().synthesize(synthesis)
|
||||
|
||||
@listen_toolkit(BaseThinkingToolkit.reflect)
|
||||
def reflect(self, reflection: str) -> str:
|
||||
return super().reflect(reflection)
|
||||
|
|
|
|||
|
|
@ -9,10 +9,11 @@ from camel.toolkits.twitter_toolkit import (
|
|||
|
||||
from app.component.environment import env
|
||||
from app.service.task import Agents
|
||||
from app.utils.listen.toolkit_listen import listen_toolkit
|
||||
from app.utils.listen.toolkit_listen import auto_listen_toolkit, listen_toolkit
|
||||
from app.utils.toolkit.abstract_toolkit import AbstractToolkit
|
||||
|
||||
|
||||
@auto_listen_toolkit(BaseTwitterToolkit)
|
||||
class TwitterToolkit(BaseTwitterToolkit, AbstractToolkit):
|
||||
agent_name: str = Agents.social_medium_agent
|
||||
|
||||
|
|
|
|||
|
|
@ -4,10 +4,11 @@ from camel.toolkits import VideoAnalysisToolkit as BaseVideoAnalysisToolkit
|
|||
|
||||
from app.component.environment import env
|
||||
from app.service.task import Agents
|
||||
from app.utils.listen.toolkit_listen import listen_toolkit
|
||||
from app.utils.listen.toolkit_listen import auto_listen_toolkit
|
||||
from app.utils.toolkit.abstract_toolkit import AbstractToolkit
|
||||
|
||||
|
||||
@auto_listen_toolkit(BaseVideoAnalysisToolkit)
|
||||
class VideoAnalysisToolkit(BaseVideoAnalysisToolkit, AbstractToolkit):
|
||||
agent_name: str = Agents.multi_modal_agent
|
||||
|
||||
|
|
@ -36,10 +37,3 @@ class VideoAnalysisToolkit(BaseVideoAnalysisToolkit, AbstractToolkit):
|
|||
cookies_path,
|
||||
timeout,
|
||||
)
|
||||
|
||||
@listen_toolkit(
|
||||
BaseVideoAnalysisToolkit.ask_question_about_video,
|
||||
lambda _, video_path, question: f"transcribe video from {video_path} and ask question: {question}",
|
||||
)
|
||||
def ask_question_about_video(self, video_path: str, question: str) -> str:
|
||||
return super().ask_question_about_video(video_path, question)
|
||||
|
|
|
|||
|
|
@ -5,10 +5,11 @@ from camel.toolkits import VideoDownloaderToolkit as BaseVideoDownloaderToolkit
|
|||
|
||||
from app.component.environment import env
|
||||
from app.service.task import Agents
|
||||
from app.utils.listen.toolkit_listen import listen_toolkit
|
||||
from app.utils.listen.toolkit_listen import auto_listen_toolkit
|
||||
from app.utils.toolkit.abstract_toolkit import AbstractToolkit
|
||||
|
||||
|
||||
@auto_listen_toolkit(BaseVideoDownloaderToolkit)
|
||||
class VideoDownloaderToolkit(BaseVideoDownloaderToolkit, AbstractToolkit):
|
||||
agent_name: str = Agents.multi_modal_agent
|
||||
|
||||
|
|
@ -23,23 +24,3 @@ class VideoDownloaderToolkit(BaseVideoDownloaderToolkit, AbstractToolkit):
|
|||
working_directory = env("file_save_path", os.path.expanduser("~/Downloads"))
|
||||
super().__init__(working_directory, cookies_path, timeout)
|
||||
self.api_task_id = api_task_id
|
||||
|
||||
@listen_toolkit(BaseVideoDownloaderToolkit.download_video)
|
||||
def download_video(self, url: str) -> str:
|
||||
return super().download_video(url)
|
||||
|
||||
@listen_toolkit(
|
||||
BaseVideoDownloaderToolkit.get_video_bytes,
|
||||
lambda _, video_path: f"get video bytes from {video_path}",
|
||||
lambda _: "get video bytes",
|
||||
)
|
||||
def get_video_bytes(self, video_path: str) -> bytes:
|
||||
return super().get_video_bytes(video_path)
|
||||
|
||||
@listen_toolkit(
|
||||
BaseVideoDownloaderToolkit.get_video_screenshots,
|
||||
lambda _, video_path, amount: f"get video screenshots from {video_path}, amount: {amount}",
|
||||
lambda results: f"get video screenshots {len(results)}",
|
||||
)
|
||||
def get_video_screenshots(self, video_path: str, amount: int) -> List[Image]:
|
||||
return super().get_video_screenshots(video_path, amount)
|
||||
|
|
|
|||
|
|
@ -3,10 +3,11 @@ from typing import Any, Dict
|
|||
from camel.toolkits import WebDeployToolkit as BaseWebDeployToolkit
|
||||
|
||||
from app.service.task import Agents
|
||||
from app.utils.listen.toolkit_listen import listen_toolkit
|
||||
from app.utils.listen.toolkit_listen import auto_listen_toolkit, listen_toolkit
|
||||
from app.utils.toolkit.abstract_toolkit import AbstractToolkit
|
||||
|
||||
|
||||
@auto_listen_toolkit(BaseWebDeployToolkit)
|
||||
class WebDeployToolkit(BaseWebDeployToolkit, AbstractToolkit):
|
||||
agent_name: str = Agents.developer_agent
|
||||
|
||||
|
|
@ -43,11 +44,3 @@ class WebDeployToolkit(BaseWebDeployToolkit, AbstractToolkit):
|
|||
) -> Dict[str, Any]:
|
||||
subdirectory = str(uuid.uuid4())
|
||||
return super().deploy_folder(folder_path, port, domain, subdirectory)
|
||||
|
||||
@listen_toolkit(BaseWebDeployToolkit.stop_server)
|
||||
def stop_server(self, port: int) -> Dict[str, Any]:
|
||||
return super().stop_server(port)
|
||||
|
||||
@listen_toolkit(BaseWebDeployToolkit.list_running_servers)
|
||||
def list_running_servers(self) -> Dict[str, Any]:
|
||||
return super().list_running_servers()
|
||||
|
|
|
|||
|
|
@ -3,10 +3,11 @@ from camel.toolkits import WhatsAppToolkit as BaseWhatsAppToolkit
|
|||
from camel.toolkits.function_tool import FunctionTool
|
||||
from app.component.environment import env
|
||||
from app.service.task import Agents
|
||||
from app.utils.listen.toolkit_listen import listen_toolkit
|
||||
from app.utils.listen.toolkit_listen import auto_listen_toolkit
|
||||
from app.utils.toolkit.abstract_toolkit import AbstractToolkit
|
||||
|
||||
|
||||
@auto_listen_toolkit(BaseWhatsAppToolkit)
|
||||
class WhatsAppToolkit(BaseWhatsAppToolkit, AbstractToolkit):
|
||||
agent_name: str = Agents.social_medium_agent
|
||||
|
||||
|
|
@ -14,30 +15,6 @@ class WhatsAppToolkit(BaseWhatsAppToolkit, AbstractToolkit):
|
|||
super().__init__(timeout)
|
||||
self.api_task_id = api_task_id
|
||||
|
||||
@listen_toolkit(
|
||||
BaseWhatsAppToolkit.send_message,
|
||||
lambda _, to, message: f"send message to {to}: {message}",
|
||||
lambda result: f"message sent result: {result}",
|
||||
)
|
||||
def send_message(self, to: str, message: str) -> Dict[str, Any] | str:
|
||||
return super().send_message(to, message)
|
||||
|
||||
@listen_toolkit(
|
||||
BaseWhatsAppToolkit.get_message_templates,
|
||||
lambda _: "get message templates",
|
||||
lambda result: f"message templates: {result}",
|
||||
)
|
||||
def get_message_templates(self) -> List[Dict[str, Any]] | str:
|
||||
return super().get_message_templates()
|
||||
|
||||
@listen_toolkit(
|
||||
BaseWhatsAppToolkit.get_business_profile,
|
||||
lambda _: "get business profile",
|
||||
lambda result: f"business profile: {result}",
|
||||
)
|
||||
def get_business_profile(self) -> Dict[str, Any] | str:
|
||||
return super().get_business_profile()
|
||||
|
||||
@classmethod
|
||||
def get_can_use_tools(cls, api_task_id: str) -> list[FunctionTool]:
|
||||
if env("WHATSAPP_ACCESS_TOKEN") and env("WHATSAPP_PHONE_NUMBER_ID"):
|
||||
|
|
|
|||
|
|
@ -609,6 +609,13 @@ function registerIpcHandlers() {
|
|||
return { success: false, error: 'File does not exist' };
|
||||
}
|
||||
|
||||
// Check if it's a directory
|
||||
const stats = await fsp.stat(filePath);
|
||||
if (stats.isDirectory()) {
|
||||
log.error('Path is a directory, not a file:', filePath);
|
||||
return { success: false, error: 'EISDIR: illegal operation on a directory, read' };
|
||||
}
|
||||
|
||||
// Read file content
|
||||
const fileContent = await fsp.readFile(filePath);
|
||||
log.info('File read successfully:', filePath);
|
||||
|
|
|
|||
|
|
@ -727,7 +727,7 @@ const chatStore = create<ChatStore>()(
|
|||
|
||||
if (taskIndex !== -1) {
|
||||
const { toolkit_name, method_name } = agentMessages.data;
|
||||
if (toolkit_name && method_name) {
|
||||
if (toolkit_name && method_name && assigneeAgentIndex !== -1) {
|
||||
|
||||
const task = taskAssigning[assigneeAgentIndex].tasks.find((task: TaskInfo) => task.id === agentMessages.data.process_task_id);
|
||||
const message = filterMessage(agentMessages)
|
||||
|
|
@ -739,7 +739,7 @@ const chatStore = create<ChatStore>()(
|
|||
message: message.data.message as string,
|
||||
toolkitStatus: "running" as AgentStatus,
|
||||
}
|
||||
if (assigneeAgentIndex !== -1 && task) {
|
||||
if (task) {
|
||||
task.toolkits ??= []
|
||||
task.toolkits.push({ ...toolkit });
|
||||
task.status = "running";
|
||||
|
|
@ -887,9 +887,12 @@ const chatStore = create<ChatStore>()(
|
|||
taskId as string
|
||||
);
|
||||
if (!type && import.meta.env.VITE_USE_LOCAL_PROXY !== 'true' && res.length > 0) {
|
||||
// Filter out directories, only upload actual files
|
||||
const files = res.filter((file: any) => !file.isFolder);
|
||||
|
||||
// Upload files sequentially to avoid overwhelming the server
|
||||
const uploadResults = await Promise.allSettled(
|
||||
res.map(async (file: any) => {
|
||||
files.map(async (file: any) => {
|
||||
try {
|
||||
// Read file content using Electron API
|
||||
const result = await window.ipcRenderer.invoke('read-file', file.path);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue