camel-ai 0.2.75a5__py3-none-any.whl → 0.2.76a0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of camel-ai might be problematic. Click here for more details.
- camel/__init__.py +1 -1
- camel/agents/chat_agent.py +298 -130
- camel/configs/__init__.py +6 -0
- camel/configs/amd_config.py +70 -0
- camel/configs/nebius_config.py +103 -0
- camel/interpreters/__init__.py +2 -0
- camel/interpreters/microsandbox_interpreter.py +395 -0
- camel/models/__init__.py +4 -0
- camel/models/amd_model.py +101 -0
- camel/models/model_factory.py +4 -0
- camel/models/nebius_model.py +83 -0
- camel/models/ollama_model.py +3 -3
- camel/models/openai_model.py +0 -6
- camel/runtimes/daytona_runtime.py +11 -12
- camel/societies/workforce/task_channel.py +120 -27
- camel/societies/workforce/workforce.py +35 -3
- camel/toolkits/__init__.py +5 -3
- camel/toolkits/code_execution.py +28 -1
- camel/toolkits/function_tool.py +6 -1
- camel/toolkits/github_toolkit.py +104 -17
- camel/toolkits/hybrid_browser_toolkit/config_loader.py +8 -0
- camel/toolkits/hybrid_browser_toolkit/hybrid_browser_toolkit.py +12 -0
- camel/toolkits/hybrid_browser_toolkit/hybrid_browser_toolkit_ts.py +33 -14
- camel/toolkits/hybrid_browser_toolkit/ts/src/browser-session.ts +135 -40
- camel/toolkits/hybrid_browser_toolkit/ts/src/config-loader.ts +2 -0
- camel/toolkits/hybrid_browser_toolkit/ts/src/hybrid-browser-toolkit.ts +43 -207
- camel/toolkits/hybrid_browser_toolkit/ts/src/parent-child-filter.ts +226 -0
- camel/toolkits/hybrid_browser_toolkit/ts/src/snapshot-parser.ts +231 -0
- camel/toolkits/hybrid_browser_toolkit/ts/src/som-screenshot-injected.ts +543 -0
- camel/toolkits/hybrid_browser_toolkit/ts/websocket-server.js +39 -6
- camel/toolkits/hybrid_browser_toolkit/ws_wrapper.py +248 -58
- camel/toolkits/hybrid_browser_toolkit_py/hybrid_browser_toolkit.py +5 -1
- camel/toolkits/{openai_image_toolkit.py → image_generation_toolkit.py} +98 -31
- camel/toolkits/math_toolkit.py +64 -10
- camel/toolkits/mcp_toolkit.py +39 -14
- camel/toolkits/minimax_mcp_toolkit.py +195 -0
- camel/toolkits/search_toolkit.py +13 -2
- camel/toolkits/terminal_toolkit.py +12 -2
- camel/toolkits/video_analysis_toolkit.py +16 -10
- camel/types/enums.py +42 -0
- camel/types/unified_model_type.py +5 -0
- camel/utils/commons.py +2 -0
- camel/utils/mcp.py +136 -2
- {camel_ai-0.2.75a5.dist-info → camel_ai-0.2.76a0.dist-info}/METADATA +5 -11
- {camel_ai-0.2.75a5.dist-info → camel_ai-0.2.76a0.dist-info}/RECORD +47 -38
- {camel_ai-0.2.75a5.dist-info → camel_ai-0.2.76a0.dist-info}/WHEEL +0 -0
- {camel_ai-0.2.75a5.dist-info → camel_ai-0.2.76a0.dist-info}/licenses/LICENSE +0 -0
camel/toolkits/code_execution.py
CHANGED
|
@@ -18,6 +18,7 @@ from camel.interpreters import (
|
|
|
18
18
|
E2BInterpreter,
|
|
19
19
|
InternalPythonInterpreter,
|
|
20
20
|
JupyterKernelInterpreter,
|
|
21
|
+
MicrosandboxInterpreter,
|
|
21
22
|
SubprocessInterpreter,
|
|
22
23
|
)
|
|
23
24
|
from camel.logger import get_logger
|
|
@@ -43,18 +44,31 @@ class CodeExecutionToolkit(BaseToolkit):
|
|
|
43
44
|
(default: :obj:`None`)
|
|
44
45
|
require_confirm (bool): Whether to require confirmation before
|
|
45
46
|
executing code. (default: :obj:`False`)
|
|
47
|
+
timeout (Optional[float]): General timeout for toolkit operations.
|
|
48
|
+
(default: :obj:`None`)
|
|
49
|
+
microsandbox_config (Optional[dict]): Configuration for microsandbox
|
|
50
|
+
interpreter. Available keys: 'server_url', 'api_key',
|
|
51
|
+
'namespace', 'sandbox_name', 'timeout'.
|
|
52
|
+
If None, uses default configuration. (default: :obj:`None`)
|
|
46
53
|
"""
|
|
47
54
|
|
|
48
55
|
def __init__(
|
|
49
56
|
self,
|
|
50
57
|
sandbox: Literal[
|
|
51
|
-
"internal_python",
|
|
58
|
+
"internal_python",
|
|
59
|
+
"jupyter",
|
|
60
|
+
"docker",
|
|
61
|
+
"subprocess",
|
|
62
|
+
"e2b",
|
|
63
|
+
"microsandbox",
|
|
52
64
|
] = "subprocess",
|
|
53
65
|
verbose: bool = False,
|
|
54
66
|
unsafe_mode: bool = False,
|
|
55
67
|
import_white_list: Optional[List[str]] = None,
|
|
56
68
|
require_confirm: bool = False,
|
|
57
69
|
timeout: Optional[float] = None,
|
|
70
|
+
# Microsandbox configuration dictionary
|
|
71
|
+
microsandbox_config: Optional[dict] = None,
|
|
58
72
|
) -> None:
|
|
59
73
|
super().__init__(timeout=timeout)
|
|
60
74
|
self.verbose = verbose
|
|
@@ -68,6 +82,7 @@ class CodeExecutionToolkit(BaseToolkit):
|
|
|
68
82
|
DockerInterpreter,
|
|
69
83
|
SubprocessInterpreter,
|
|
70
84
|
E2BInterpreter,
|
|
85
|
+
MicrosandboxInterpreter,
|
|
71
86
|
]
|
|
72
87
|
|
|
73
88
|
if sandbox == "internal_python":
|
|
@@ -95,6 +110,18 @@ class CodeExecutionToolkit(BaseToolkit):
|
|
|
95
110
|
)
|
|
96
111
|
elif sandbox == "e2b":
|
|
97
112
|
self.interpreter = E2BInterpreter(require_confirm=require_confirm)
|
|
113
|
+
elif sandbox == "microsandbox":
|
|
114
|
+
# Extract parameters with proper types for microsandbox
|
|
115
|
+
config = microsandbox_config or {}
|
|
116
|
+
|
|
117
|
+
self.interpreter = MicrosandboxInterpreter(
|
|
118
|
+
require_confirm=require_confirm,
|
|
119
|
+
server_url=config.get("server_url"),
|
|
120
|
+
api_key=config.get("api_key"),
|
|
121
|
+
namespace=config.get("namespace", "default"),
|
|
122
|
+
sandbox_name=config.get("sandbox_name"),
|
|
123
|
+
timeout=config.get("timeout", 30),
|
|
124
|
+
)
|
|
98
125
|
else:
|
|
99
126
|
raise RuntimeError(
|
|
100
127
|
f"The sandbox type `{sandbox}` is not supported."
|
camel/toolkits/function_tool.py
CHANGED
|
@@ -156,7 +156,12 @@ def get_openai_tool_schema(func: Callable) -> Dict[str, Any]:
|
|
|
156
156
|
if (name := param.arg_name) in parameters_dict["properties"] and (
|
|
157
157
|
description := param.description
|
|
158
158
|
):
|
|
159
|
-
|
|
159
|
+
# OpenAI does not allow descriptions on properties that use $ref.
|
|
160
|
+
# To avoid schema errors, we only add the description if "$ref" is
|
|
161
|
+
# not present.
|
|
162
|
+
prop = parameters_dict["properties"][name]
|
|
163
|
+
if "$ref" not in prop:
|
|
164
|
+
prop["description"] = description
|
|
160
165
|
|
|
161
166
|
short_description = docstring.short_description or ""
|
|
162
167
|
long_description = docstring.long_description or ""
|
camel/toolkits/github_toolkit.py
CHANGED
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
import logging
|
|
16
16
|
import os
|
|
17
|
+
import warnings
|
|
17
18
|
from typing import Dict, List, Literal, Optional, Union
|
|
18
19
|
|
|
19
20
|
from camel.toolkits import FunctionTool
|
|
@@ -80,7 +81,7 @@ class GithubToolkit(BaseToolkit):
|
|
|
80
81
|
)
|
|
81
82
|
return GITHUB_ACCESS_TOKEN
|
|
82
83
|
|
|
83
|
-
def
|
|
84
|
+
def github_create_pull_request(
|
|
84
85
|
self,
|
|
85
86
|
repo_name: str,
|
|
86
87
|
file_path: str,
|
|
@@ -150,7 +151,7 @@ class GithubToolkit(BaseToolkit):
|
|
|
150
151
|
else:
|
|
151
152
|
raise ValueError("PRs with multiple files aren't supported yet.")
|
|
152
153
|
|
|
153
|
-
def
|
|
154
|
+
def github_get_issue_list(
|
|
154
155
|
self, repo_name: str, state: Literal["open", "closed", "all"] = "all"
|
|
155
156
|
) -> List[Dict[str, object]]:
|
|
156
157
|
r"""Retrieves all issues from the GitHub repository.
|
|
@@ -177,7 +178,9 @@ class GithubToolkit(BaseToolkit):
|
|
|
177
178
|
|
|
178
179
|
return issues_info
|
|
179
180
|
|
|
180
|
-
def
|
|
181
|
+
def github_get_issue_content(
|
|
182
|
+
self, repo_name: str, issue_number: int
|
|
183
|
+
) -> str:
|
|
181
184
|
r"""Retrieves the content of a specific issue by its number.
|
|
182
185
|
|
|
183
186
|
Args:
|
|
@@ -194,7 +197,7 @@ class GithubToolkit(BaseToolkit):
|
|
|
194
197
|
except Exception as e:
|
|
195
198
|
return f"can't get Issue number {issue_number}: {e!s}"
|
|
196
199
|
|
|
197
|
-
def
|
|
200
|
+
def github_get_pull_request_list(
|
|
198
201
|
self, repo_name: str, state: Literal["open", "closed", "all"] = "all"
|
|
199
202
|
) -> List[Dict[str, object]]:
|
|
200
203
|
r"""Retrieves all pull requests from the GitHub repository.
|
|
@@ -221,7 +224,7 @@ class GithubToolkit(BaseToolkit):
|
|
|
221
224
|
|
|
222
225
|
return pull_requests_info
|
|
223
226
|
|
|
224
|
-
def
|
|
227
|
+
def github_get_pull_request_code(
|
|
225
228
|
self, repo_name: str, pr_number: int
|
|
226
229
|
) -> List[Dict[str, str]]:
|
|
227
230
|
r"""Retrieves the code changes of a specific pull request.
|
|
@@ -253,7 +256,7 @@ class GithubToolkit(BaseToolkit):
|
|
|
253
256
|
|
|
254
257
|
return files_changed
|
|
255
258
|
|
|
256
|
-
def
|
|
259
|
+
def github_get_pull_request_comments(
|
|
257
260
|
self, repo_name: str, pr_number: int
|
|
258
261
|
) -> List[Dict[str, str]]:
|
|
259
262
|
r"""Retrieves the comments from a specific pull request.
|
|
@@ -278,7 +281,9 @@ class GithubToolkit(BaseToolkit):
|
|
|
278
281
|
|
|
279
282
|
return comments
|
|
280
283
|
|
|
281
|
-
def
|
|
284
|
+
def github_get_all_file_paths(
|
|
285
|
+
self, repo_name: str, path: str = ""
|
|
286
|
+
) -> List[str]:
|
|
282
287
|
r"""Recursively retrieves all file paths in the GitHub repository.
|
|
283
288
|
|
|
284
289
|
Args:
|
|
@@ -308,13 +313,15 @@ class GithubToolkit(BaseToolkit):
|
|
|
308
313
|
for content in contents:
|
|
309
314
|
if content.type == "dir":
|
|
310
315
|
# If it's a directory, recursively retrieve its file paths
|
|
311
|
-
files.extend(self.
|
|
316
|
+
files.extend(self.github_get_all_file_paths(content.path))
|
|
312
317
|
else:
|
|
313
318
|
# If it's a file, add its path to the list
|
|
314
319
|
files.append(content.path)
|
|
315
320
|
return files
|
|
316
321
|
|
|
317
|
-
def
|
|
322
|
+
def github_retrieve_file_content(
|
|
323
|
+
self, repo_name: str, file_path: str
|
|
324
|
+
) -> str:
|
|
318
325
|
r"""Retrieves the content of a file from the GitHub repository.
|
|
319
326
|
|
|
320
327
|
Args:
|
|
@@ -343,12 +350,92 @@ class GithubToolkit(BaseToolkit):
|
|
|
343
350
|
the functions in the toolkit.
|
|
344
351
|
"""
|
|
345
352
|
return [
|
|
346
|
-
FunctionTool(self.
|
|
347
|
-
FunctionTool(self.
|
|
348
|
-
FunctionTool(self.
|
|
349
|
-
FunctionTool(self.
|
|
350
|
-
FunctionTool(self.
|
|
351
|
-
FunctionTool(self.
|
|
352
|
-
FunctionTool(self.
|
|
353
|
-
FunctionTool(self.
|
|
353
|
+
FunctionTool(self.github_create_pull_request),
|
|
354
|
+
FunctionTool(self.github_get_issue_list),
|
|
355
|
+
FunctionTool(self.github_get_issue_content),
|
|
356
|
+
FunctionTool(self.github_get_pull_request_list),
|
|
357
|
+
FunctionTool(self.github_get_pull_request_code),
|
|
358
|
+
FunctionTool(self.github_get_pull_request_comments),
|
|
359
|
+
FunctionTool(self.github_get_all_file_paths),
|
|
360
|
+
FunctionTool(self.github_retrieve_file_content),
|
|
354
361
|
]
|
|
362
|
+
|
|
363
|
+
# Deprecated method aliases for backward compatibility
|
|
364
|
+
def create_pull_request(self, *args, **kwargs):
|
|
365
|
+
r"""Deprecated: Use github_create_pull_request instead."""
|
|
366
|
+
warnings.warn(
|
|
367
|
+
"create_pull_request is deprecated. Use "
|
|
368
|
+
"github_create_pull_request instead.",
|
|
369
|
+
DeprecationWarning,
|
|
370
|
+
stacklevel=2,
|
|
371
|
+
)
|
|
372
|
+
return self.github_create_pull_request(*args, **kwargs)
|
|
373
|
+
|
|
374
|
+
def get_issue_list(self, *args, **kwargs):
|
|
375
|
+
r"""Deprecated: Use github_get_issue_list instead."""
|
|
376
|
+
warnings.warn(
|
|
377
|
+
"get_issue_list is deprecated. Use github_get_issue_list instead.",
|
|
378
|
+
DeprecationWarning,
|
|
379
|
+
stacklevel=2,
|
|
380
|
+
)
|
|
381
|
+
return self.github_get_issue_list(*args, **kwargs)
|
|
382
|
+
|
|
383
|
+
def get_issue_content(self, *args, **kwargs):
|
|
384
|
+
r"""Deprecated: Use github_get_issue_content instead."""
|
|
385
|
+
warnings.warn(
|
|
386
|
+
"get_issue_content is deprecated. Use "
|
|
387
|
+
"github_get_issue_content instead.",
|
|
388
|
+
DeprecationWarning,
|
|
389
|
+
stacklevel=2,
|
|
390
|
+
)
|
|
391
|
+
return self.github_get_issue_content(*args, **kwargs)
|
|
392
|
+
|
|
393
|
+
def get_pull_request_list(self, *args, **kwargs):
|
|
394
|
+
r"""Deprecated: Use github_get_pull_request_list instead."""
|
|
395
|
+
warnings.warn(
|
|
396
|
+
"get_pull_request_list is deprecated. "
|
|
397
|
+
"Use github_get_pull_request_list instead.",
|
|
398
|
+
DeprecationWarning,
|
|
399
|
+
stacklevel=2,
|
|
400
|
+
)
|
|
401
|
+
return self.github_get_pull_request_list(*args, **kwargs)
|
|
402
|
+
|
|
403
|
+
def get_pull_request_code(self, *args, **kwargs):
|
|
404
|
+
r"""Deprecated: Use github_get_pull_request_code instead."""
|
|
405
|
+
warnings.warn(
|
|
406
|
+
"get_pull_request_code is deprecated. Use "
|
|
407
|
+
"github_get_pull_request_code instead.",
|
|
408
|
+
DeprecationWarning,
|
|
409
|
+
stacklevel=2,
|
|
410
|
+
)
|
|
411
|
+
return self.github_get_pull_request_code(*args, **kwargs)
|
|
412
|
+
|
|
413
|
+
def get_pull_request_comments(self, *args, **kwargs):
|
|
414
|
+
r"""Deprecated: Use github_get_pull_request_comments instead."""
|
|
415
|
+
warnings.warn(
|
|
416
|
+
"get_pull_request_comments is deprecated. "
|
|
417
|
+
"Use github_get_pull_request_comments instead.",
|
|
418
|
+
DeprecationWarning,
|
|
419
|
+
stacklevel=2,
|
|
420
|
+
)
|
|
421
|
+
return self.github_get_pull_request_comments(*args, **kwargs)
|
|
422
|
+
|
|
423
|
+
def get_all_file_paths(self, *args, **kwargs):
|
|
424
|
+
r"""Deprecated: Use github_get_all_file_paths instead."""
|
|
425
|
+
warnings.warn(
|
|
426
|
+
"get_all_file_paths is deprecated. Use "
|
|
427
|
+
"github_get_all_file_paths instead.",
|
|
428
|
+
DeprecationWarning,
|
|
429
|
+
stacklevel=2,
|
|
430
|
+
)
|
|
431
|
+
return self.github_get_all_file_paths(*args, **kwargs)
|
|
432
|
+
|
|
433
|
+
def retrieve_file_content(self, *args, **kwargs):
|
|
434
|
+
r"""Deprecated: Use github_retrieve_file_content instead."""
|
|
435
|
+
warnings.warn(
|
|
436
|
+
"retrieve_file_content is deprecated. "
|
|
437
|
+
"Use github_retrieve_file_content instead.",
|
|
438
|
+
DeprecationWarning,
|
|
439
|
+
stacklevel=2,
|
|
440
|
+
)
|
|
441
|
+
return self.github_retrieve_file_content(*args, **kwargs)
|
|
@@ -44,6 +44,9 @@ class BrowserConfig:
|
|
|
44
44
|
connect_over_cdp: bool = False
|
|
45
45
|
cdp_url: Optional[str] = None
|
|
46
46
|
|
|
47
|
+
# Full visual mode configuration
|
|
48
|
+
full_visual_mode: bool = False
|
|
49
|
+
|
|
47
50
|
|
|
48
51
|
@dataclass
|
|
49
52
|
class ToolkitConfig:
|
|
@@ -51,6 +54,7 @@ class ToolkitConfig:
|
|
|
51
54
|
|
|
52
55
|
cache_dir: str = "tmp/"
|
|
53
56
|
browser_log_to_file: bool = False
|
|
57
|
+
log_dir: Optional[str] = None
|
|
54
58
|
session_id: Optional[str] = None
|
|
55
59
|
enabled_tools: Optional[list] = None
|
|
56
60
|
|
|
@@ -116,6 +120,8 @@ class ConfigLoader:
|
|
|
116
120
|
toolkit_kwargs["session_id"] = value
|
|
117
121
|
elif key == "enabledTools":
|
|
118
122
|
toolkit_kwargs["enabled_tools"] = value
|
|
123
|
+
elif key == "fullVisualMode":
|
|
124
|
+
browser_kwargs["full_visual_mode"] = value
|
|
119
125
|
|
|
120
126
|
browser_config = BrowserConfig(**browser_kwargs)
|
|
121
127
|
toolkit_config = ToolkitConfig(**toolkit_kwargs)
|
|
@@ -142,10 +148,12 @@ class ConfigLoader:
|
|
|
142
148
|
"screenshotTimeout": self.browser_config.screenshot_timeout,
|
|
143
149
|
"pageStabilityTimeout": self.browser_config.page_stability_timeout,
|
|
144
150
|
"browser_log_to_file": self.toolkit_config.browser_log_to_file,
|
|
151
|
+
"log_dir": self.toolkit_config.log_dir,
|
|
145
152
|
"session_id": self.toolkit_config.session_id,
|
|
146
153
|
"viewport_limit": self.browser_config.viewport_limit,
|
|
147
154
|
"connectOverCdp": self.browser_config.connect_over_cdp,
|
|
148
155
|
"cdpUrl": self.browser_config.cdp_url,
|
|
156
|
+
"fullVisualMode": self.browser_config.full_visual_mode,
|
|
149
157
|
}
|
|
150
158
|
|
|
151
159
|
def get_timeout_config(self) -> Dict[str, Optional[int]]:
|
|
@@ -38,6 +38,7 @@ class HybridBrowserToolkit(BaseToolkit):
|
|
|
38
38
|
cache_dir: str = "tmp/",
|
|
39
39
|
enabled_tools: Optional[List[str]] = None,
|
|
40
40
|
browser_log_to_file: bool = False,
|
|
41
|
+
log_dir: Optional[str] = None,
|
|
41
42
|
session_id: Optional[str] = None,
|
|
42
43
|
default_start_url: str = "https://google.com/",
|
|
43
44
|
default_timeout: Optional[int] = None,
|
|
@@ -50,6 +51,7 @@ class HybridBrowserToolkit(BaseToolkit):
|
|
|
50
51
|
viewport_limit: bool = False,
|
|
51
52
|
connect_over_cdp: bool = False,
|
|
52
53
|
cdp_url: Optional[str] = None,
|
|
54
|
+
full_visual_mode: bool = False,
|
|
53
55
|
**kwargs: Any,
|
|
54
56
|
) -> Any:
|
|
55
57
|
r"""Create a HybridBrowserToolkit instance with the specified mode.
|
|
@@ -72,6 +74,8 @@ class HybridBrowserToolkit(BaseToolkit):
|
|
|
72
74
|
Defaults to None.
|
|
73
75
|
browser_log_to_file (bool): Whether to log browser actions to
|
|
74
76
|
file. Defaults to False.
|
|
77
|
+
log_dir (Optional[str]): Custom directory path for log files.
|
|
78
|
+
If None, defaults to "browser_log". Defaults to None.
|
|
75
79
|
session_id (Optional[str]): Session identifier. Defaults to None.
|
|
76
80
|
default_start_url (str): Default URL to start with. Defaults
|
|
77
81
|
to "https://google.com/".
|
|
@@ -98,6 +102,11 @@ class HybridBrowserToolkit(BaseToolkit):
|
|
|
98
102
|
cdp_url (Optional[str]): WebSocket endpoint URL for CDP
|
|
99
103
|
connection. Required when connect_over_cdp is True.
|
|
100
104
|
Defaults to None. (Only supported in TypeScript mode)
|
|
105
|
+
full_visual_mode (bool): When True, browser actions like click,
|
|
106
|
+
browser_open, visit_page, etc. will return 'full visual mode'
|
|
107
|
+
as snapshot instead of actual page content. The
|
|
108
|
+
browser_get_page_snapshot method will still return the actual
|
|
109
|
+
snapshot. Defaults to False.
|
|
101
110
|
**kwargs: Additional keyword arguments passed to the
|
|
102
111
|
implementation.
|
|
103
112
|
|
|
@@ -117,6 +126,7 @@ class HybridBrowserToolkit(BaseToolkit):
|
|
|
117
126
|
cache_dir=cache_dir,
|
|
118
127
|
enabled_tools=enabled_tools,
|
|
119
128
|
browser_log_to_file=browser_log_to_file,
|
|
129
|
+
log_dir=log_dir,
|
|
120
130
|
session_id=session_id,
|
|
121
131
|
default_start_url=default_start_url,
|
|
122
132
|
default_timeout=default_timeout,
|
|
@@ -129,6 +139,7 @@ class HybridBrowserToolkit(BaseToolkit):
|
|
|
129
139
|
viewport_limit=viewport_limit,
|
|
130
140
|
connect_over_cdp=connect_over_cdp,
|
|
131
141
|
cdp_url=cdp_url,
|
|
142
|
+
full_visual_mode=full_visual_mode,
|
|
132
143
|
**kwargs,
|
|
133
144
|
)
|
|
134
145
|
elif mode == "python":
|
|
@@ -160,6 +171,7 @@ class HybridBrowserToolkit(BaseToolkit):
|
|
|
160
171
|
cache_dir=cache_dir,
|
|
161
172
|
enabled_tools=enabled_tools,
|
|
162
173
|
browser_log_to_file=browser_log_to_file,
|
|
174
|
+
log_dir=log_dir,
|
|
163
175
|
session_id=session_id,
|
|
164
176
|
default_start_url=default_start_url,
|
|
165
177
|
default_timeout=default_timeout,
|
|
@@ -86,6 +86,7 @@ class HybridBrowserToolkit(BaseToolkit, RegisteredAgentToolkit):
|
|
|
86
86
|
cache_dir: str = "tmp/",
|
|
87
87
|
enabled_tools: Optional[List[str]] = None,
|
|
88
88
|
browser_log_to_file: bool = False,
|
|
89
|
+
log_dir: Optional[str] = None,
|
|
89
90
|
session_id: Optional[str] = None,
|
|
90
91
|
default_start_url: str = "https://google.com/",
|
|
91
92
|
default_timeout: Optional[int] = None,
|
|
@@ -98,6 +99,7 @@ class HybridBrowserToolkit(BaseToolkit, RegisteredAgentToolkit):
|
|
|
98
99
|
viewport_limit: bool = False,
|
|
99
100
|
connect_over_cdp: bool = False,
|
|
100
101
|
cdp_url: Optional[str] = None,
|
|
102
|
+
full_visual_mode: bool = False,
|
|
101
103
|
) -> None:
|
|
102
104
|
r"""Initialize the HybridBrowserToolkit.
|
|
103
105
|
|
|
@@ -115,6 +117,8 @@ class HybridBrowserToolkit(BaseToolkit, RegisteredAgentToolkit):
|
|
|
115
117
|
Defaults to None.
|
|
116
118
|
browser_log_to_file (bool): Whether to log browser actions to
|
|
117
119
|
file. Defaults to False.
|
|
120
|
+
log_dir (Optional[str]): Custom directory path for log files.
|
|
121
|
+
If None, defaults to "browser_log". Defaults to None.
|
|
118
122
|
session_id (Optional[str]): Session identifier. Defaults to None.
|
|
119
123
|
default_start_url (str): Default URL to start with. Defaults
|
|
120
124
|
to "https://google.com/".
|
|
@@ -143,6 +147,9 @@ class HybridBrowserToolkit(BaseToolkit, RegisteredAgentToolkit):
|
|
|
143
147
|
cdp_url (Optional[str]): WebSocket endpoint URL for CDP
|
|
144
148
|
connection (e.g., 'ws://localhost:9222/devtools/browser/...').
|
|
145
149
|
Required when connect_over_cdp is True. Defaults to None.
|
|
150
|
+
full_visual_mode (bool): When True, browser actions like click,
|
|
151
|
+
browser_open, visit_page, etc. will not return snapshots.
|
|
152
|
+
Defaults to False.
|
|
146
153
|
"""
|
|
147
154
|
super().__init__()
|
|
148
155
|
RegisteredAgentToolkit.__init__(self)
|
|
@@ -163,10 +170,12 @@ class HybridBrowserToolkit(BaseToolkit, RegisteredAgentToolkit):
|
|
|
163
170
|
viewport_limit=viewport_limit,
|
|
164
171
|
cache_dir=cache_dir,
|
|
165
172
|
browser_log_to_file=browser_log_to_file,
|
|
173
|
+
log_dir=log_dir,
|
|
166
174
|
session_id=session_id,
|
|
167
175
|
enabled_tools=enabled_tools,
|
|
168
176
|
connect_over_cdp=connect_over_cdp,
|
|
169
177
|
cdp_url=cdp_url,
|
|
178
|
+
full_visual_mode=full_visual_mode,
|
|
170
179
|
)
|
|
171
180
|
|
|
172
181
|
# Legacy attribute access for backward compatibility
|
|
@@ -182,6 +191,7 @@ class HybridBrowserToolkit(BaseToolkit, RegisteredAgentToolkit):
|
|
|
182
191
|
self._default_start_url = browser_config.default_start_url
|
|
183
192
|
self._session_id = toolkit_config.session_id or "default"
|
|
184
193
|
self._viewport_limit = browser_config.viewport_limit
|
|
194
|
+
self._full_visual_mode = browser_config.full_visual_mode
|
|
185
195
|
|
|
186
196
|
# Store timeout configuration for backward compatibility
|
|
187
197
|
self._default_timeout = browser_config.default_timeout
|
|
@@ -648,22 +658,29 @@ class HybridBrowserToolkit(BaseToolkit, RegisteredAgentToolkit):
|
|
|
648
658
|
|
|
649
659
|
# Add tab information
|
|
650
660
|
tab_info = await ws_wrapper.get_tab_info()
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
)
|
|
660
|
-
|
|
661
|
+
|
|
662
|
+
response = {
|
|
663
|
+
"result": result.get("result", ""),
|
|
664
|
+
"snapshot": result.get("snapshot", ""),
|
|
665
|
+
"tabs": tab_info,
|
|
666
|
+
"current_tab": next(
|
|
667
|
+
(
|
|
668
|
+
i
|
|
669
|
+
for i, tab in enumerate(tab_info)
|
|
670
|
+
if tab.get("is_current")
|
|
661
671
|
),
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
672
|
+
0,
|
|
673
|
+
),
|
|
674
|
+
"total_tabs": len(tab_info),
|
|
675
|
+
}
|
|
665
676
|
|
|
666
|
-
|
|
677
|
+
if "newTabId" in result:
|
|
678
|
+
response["newTabId"] = result["newTabId"]
|
|
679
|
+
|
|
680
|
+
if "timing" in result:
|
|
681
|
+
response["timing"] = result["timing"]
|
|
682
|
+
|
|
683
|
+
return response
|
|
667
684
|
except Exception as e:
|
|
668
685
|
logger.error(f"Failed to click element: {e}")
|
|
669
686
|
return {
|
|
@@ -1377,6 +1394,8 @@ class HybridBrowserToolkit(BaseToolkit, RegisteredAgentToolkit):
|
|
|
1377
1394
|
screenshot_timeout=self._screenshot_timeout,
|
|
1378
1395
|
page_stability_timeout=self._page_stability_timeout,
|
|
1379
1396
|
dom_content_loaded_timeout=self._dom_content_loaded_timeout,
|
|
1397
|
+
viewport_limit=self._viewport_limit,
|
|
1398
|
+
full_visual_mode=self._full_visual_mode,
|
|
1380
1399
|
)
|
|
1381
1400
|
|
|
1382
1401
|
def get_tools(self) -> List[FunctionTool]:
|