camel-ai 0.2.71a10__py3-none-any.whl → 0.2.71a11__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 CHANGED
@@ -14,7 +14,7 @@
14
14
 
15
15
  from camel.logger import disable_logging, enable_logging, set_log_level
16
16
 
17
- __version__ = '0.2.71a10'
17
+ __version__ = '0.2.71a11'
18
18
 
19
19
  __all__ = [
20
20
  '__version__',
@@ -21,7 +21,10 @@ from typing import TYPE_CHECKING, Any, Dict, List, Optional, Type, Union
21
21
  from pydantic import BaseModel
22
22
 
23
23
  if TYPE_CHECKING:
24
- from cohere.types import ChatMessageV2, ChatResponse
24
+ from cohere.types import ( # type: ignore[attr-defined]
25
+ ChatMessageV2,
26
+ ChatResponse,
27
+ )
25
28
 
26
29
  from camel.configs import COHERE_API_PARAMS, CohereConfig
27
30
  from camel.messages import OpenAIMessage
@@ -29,8 +29,23 @@ from camel.types import (
29
29
  from camel.utils import (
30
30
  BaseTokenCounter,
31
31
  api_keys_required,
32
+ get_current_agent_session_id,
33
+ update_langfuse_trace,
32
34
  )
33
35
 
36
+ if os.environ.get("LANGFUSE_ENABLED", "False").lower() == "true":
37
+ try:
38
+ from langfuse.decorators import observe
39
+ except ImportError:
40
+ from camel.utils import observe
41
+ elif os.environ.get("TRACEROOT_ENABLED", "False").lower() == "true":
42
+ try:
43
+ from traceroot import trace as observe # type: ignore[import]
44
+ except ImportError:
45
+ from camel.utils import observe
46
+ else:
47
+ from camel.utils import observe
48
+
34
49
 
35
50
  class MoonshotModel(OpenAICompatibleModel):
36
51
  r"""Moonshot API in a unified OpenAICompatibleModel interface.
@@ -91,13 +106,51 @@ class MoonshotModel(OpenAICompatibleModel):
91
106
  **kwargs,
92
107
  )
93
108
 
109
+ @observe()
94
110
  async def _arun(
95
111
  self,
96
112
  messages: List[OpenAIMessage],
97
113
  response_format: Optional[Type[BaseModel]] = None,
98
114
  tools: Optional[List[Dict[str, Any]]] = None,
99
115
  ) -> Union[ChatCompletion, AsyncStream[ChatCompletionChunk]]:
100
- raise NotImplementedError("Moonshot does not support async inference.")
116
+ r"""Runs inference of Moonshot chat completion asynchronously.
117
+
118
+ Args:
119
+ messages (List[OpenAIMessage]): Message list with the chat history
120
+ in OpenAI API format.
121
+ response_format (Optional[Type[BaseModel]]): The format of the
122
+ response.
123
+ tools (Optional[List[Dict[str, Any]]]): The schema of the tools to
124
+ use for the request.
125
+
126
+ Returns:
127
+ Union[ChatCompletion, AsyncStream[ChatCompletionChunk]]:
128
+ `ChatCompletion` in the non-stream mode, or
129
+ `AsyncStream[ChatCompletionChunk]` in the stream mode.
130
+ """
131
+
132
+ # Update Langfuse trace with current agent session and metadata
133
+ agent_session_id = get_current_agent_session_id()
134
+ if agent_session_id:
135
+ update_langfuse_trace(
136
+ session_id=agent_session_id,
137
+ metadata={
138
+ "agent_id": agent_session_id,
139
+ "model_type": str(self.model_type),
140
+ },
141
+ tags=["CAMEL-AI", str(self.model_type)],
142
+ )
143
+
144
+ request_config = self.model_config_dict.copy()
145
+
146
+ if tools:
147
+ request_config["tools"] = tools
148
+
149
+ return await self._async_client.chat.completions.create(
150
+ messages=messages,
151
+ model=self.model_type,
152
+ **request_config,
153
+ )
101
154
 
102
155
  def check_model_config(self):
103
156
  r"""Check whether the model configuration contains any
@@ -198,7 +198,7 @@ Now you should summarize the scenario and return the result of the task.
198
198
 
199
199
  TASK_DECOMPOSE_PROMPT = r"""You need to decompose the given task into subtasks according to the workers available in the group, following these important principles to maximize efficiency, parallelism, and clarity for the executing agents:
200
200
 
201
- 1. **Self-Contained Subtasks**: This is the most critical principle. Each subtask's description **must be fully self-sufficient and independently understandable**. The agent executing the subtask has **no knowledge** of the parent task, other subtasks, or the overall workflow.
201
+ 1. **Self-Contained Subtasks**: This is critical principle. Each subtask's description **must be fully self-sufficient and independently understandable**. The agent executing the subtask has **no knowledge** of the parent task, other subtasks, or the overall workflow.
202
202
  * **DO NOT** use relative references like "the first task," "the paper mentioned above," or "the result from the previous step."
203
203
  * **DO** write explicit instructions. For example, instead of "Analyze the document," write "Analyze the document titled 'The Future of AI'." The system will automatically provide the necessary inputs (like the document itself) from previous steps.
204
204
 
@@ -220,23 +220,42 @@ These principles aim to reduce overall completion time by maximizing concurrent
220
220
 
221
221
  **EXAMPLE FORMAT ONLY** (DO NOT use this example content for actual task decomposition):
222
222
 
223
- If given a hypothetical task requiring research, analysis, and reporting with multiple items to process, you should decompose it to maximize parallelism:
223
+ ***
224
+ **Example 1: Sequential Task for a Single Worker**
224
225
 
225
- * Poor decomposition (monolithic and vague):
226
- `<tasks><task>Do all research, analysis, and write final report.</task></tasks>`
227
-
228
- * **Excellent decomposition (self-contained and parallel)**:
226
+ * **Overall Task**: "Create a short blog post about the benefits of Python. First, research the key benefits. Then, write a 300-word article. Finally, find a suitable image to go with it."
227
+ * **Available Workers**:
228
+ * `Document Agent`: A worker that can research topics, write articles, and find images.
229
+ * **Correct Decomposition**:
230
+ ```xml
231
+ <tasks>
232
+ <task>Create a short blog post about the benefits of Python by researching key benefits, writing a 300-word article, and finding a suitable image.</task>
233
+ </tasks>
229
234
  ```
235
+ * **Reasoning**: All steps are sequential and can be handled by the same worker type (`Document Agent`). Grouping them into one subtask is efficient and maintains the workflow, following the "Strategic Grouping" principle.
236
+
237
+ ***
238
+ **Example 2: Parallel Task Across Different Workers**
239
+
240
+ * **Overall Task**: "Write a report on the Q2 performance of Apple (AAPL) and Google (GOOGL). The report needs a financial summary and a market sentiment analysis for each company."
241
+ * **Available Workers**:
242
+ * `financial_analyst_1`: A worker that can analyze financial data and create summaries.
243
+ * `market_researcher_1`: A worker that can perform market sentiment analysis.
244
+ * `report_writer_1`: A worker that compiles information into a final report.
245
+ * **Correct Decomposition**:
246
+ ```xml
230
247
  <tasks>
231
- <task>(ResearchAgent): Gather data and resources on topic X, producing a list of relevant items.</task>
232
- <task>(AnalysisAgent): Analyze the provided document 'Item A'.</task>
233
- <task>(AnalysisAgent): Analyze the provided document 'Item B'.</task>
234
- <task>(AnalysisAgent): Analyze the provided document 'Item N'.</task>
235
- <task>(ReportAgent): Compile the provided analyses of items A, B, and N into a final report.</task>
248
+ <task>Create a financial summary for Apple (AAPL) for Q2.</task>
249
+ <task>Create a financial summary for Google (GOOGL) for Q2.</task>
250
+ <task>Perform market sentiment analysis for Apple (AAPL) for Q2.</task>
251
+ <task>Perform market sentiment analysis for Google (GOOGL) for Q2.</task>
252
+ <task>Compile the provided financial summaries and market sentiment analyses for Apple (AAPL) and Google (GOOGL) into a single Q2 performance report.</task>
236
253
  </tasks>
237
254
  ```
255
+ * **Reasoning**: The financial analysis and market research can be done in parallel for both companies. The final report depends on all previous steps. This decomposition leverages worker specialization and parallelism, following the "Aggressive Parallelization" principle.
256
+ ***
238
257
 
239
- **END OF FORMAT EXAMPLE** - Now apply this structure to your actual task below.
258
+ **END OF EXAMPLES** - Now, apply these principles and examples to decompose the following task.
240
259
 
241
260
  The content of the task is:
242
261
 
@@ -256,11 +256,24 @@ def sanitize_and_enforce_required(parameters_dict):
256
256
  # This field is optional - add null to its type
257
257
  current_type = field_schema.get('type')
258
258
  has_ref = '$ref' in field_schema
259
+ has_any_of = 'anyOf' in field_schema
259
260
 
260
261
  if has_ref:
261
262
  # Fields with $ref shouldn't have additional type field
262
263
  # The $ref itself defines the type structure
263
264
  pass
265
+ elif has_any_of:
266
+ # Field already has anyOf
267
+ any_of_types = field_schema['anyOf']
268
+ has_null_type = any(
269
+ item.get('type') == 'null' for item in any_of_types
270
+ )
271
+ if not has_null_type:
272
+ # Add null type to anyOf
273
+ field_schema['anyOf'].append({'type': 'null'})
274
+ # Remove conflicting type field if it exists
275
+ if 'type' in field_schema:
276
+ del field_schema['type']
264
277
  elif current_type:
265
278
  if isinstance(current_type, str):
266
279
  # Single type - convert to array with null
@@ -1094,25 +1094,19 @@ class HybridBrowserToolkit(BaseToolkit):
1094
1094
  # Public API Methods
1095
1095
 
1096
1096
  async def open_browser(self) -> Dict[str, Any]:
1097
- r"""Launches a new browser session and navigates to the configured
1098
- default page.
1097
+ r"""Starts a new browser session. This must be the first browser
1098
+ action.
1099
1099
 
1100
- This method initializes the underlying browser instance and
1101
- automatically navigates to the default start URL that was configured
1102
- during toolkit initialization in the first tab. Agents cannot specify
1103
- a custom URL - they must use the visit_page tool to open new tabs
1104
- with other URLs.
1100
+ This method initializes the browser and navigates to a default start
1101
+ page. To visit a specific URL, use `visit_page` after this.
1105
1102
 
1106
1103
  Returns:
1107
- Dict[str, Any]: A dictionary containing:
1108
- - "result": A string confirming that the browser session has
1109
- started and the default page has been loaded.
1110
- - "snapshot": A textual representation of the current page's
1111
- interactive elements. This snapshot is crucial for
1112
- identifying elements for subsequent actions.
1113
- - "tabs": List of all open tabs with their information.
1114
- - "current_tab": Index of the currently active tab.
1115
- - "total_tabs": Total number of open tabs.
1104
+ Dict[str, Any]: A dictionary with the result of the action:
1105
+ - "result" (str): Confirmation of the action.
1106
+ - "snapshot" (str): A textual snapshot of interactive elements.
1107
+ - "tabs" (List[Dict]): Information about all open tabs.
1108
+ - "current_tab" (int): Index of the active tab.
1109
+ - "total_tabs" (int): Total number of open tabs.
1116
1110
  """
1117
1111
  # Add logging if enabled
1118
1112
  action_start = time.time()
@@ -1163,14 +1157,12 @@ class HybridBrowserToolkit(BaseToolkit):
1163
1157
 
1164
1158
  @action_logger
1165
1159
  async def close_browser(self) -> str:
1166
- r"""Closes the current browser session and releases all associated
1167
- resources.
1160
+ r"""Closes the browser session, releasing all resources.
1168
1161
 
1169
- This should be called at the end of a web automation task to ensure a
1170
- clean shutdown of the browser instance.
1162
+ This should be called at the end of a task for cleanup.
1171
1163
 
1172
1164
  Returns:
1173
- str: A confirmation message indicating the session is closed.
1165
+ str: A confirmation message.
1174
1166
  """
1175
1167
  if self._agent is not None:
1176
1168
  try:
@@ -1184,17 +1176,19 @@ class HybridBrowserToolkit(BaseToolkit):
1184
1176
 
1185
1177
  @action_logger
1186
1178
  async def visit_page(self, url: str) -> Dict[str, Any]:
1187
- r"""Navigates to a URL.
1188
-
1189
- This method creates a new tab for the URL instead of navigating
1190
- in the current tab, allowing better multi-tab management.
1179
+ r"""Opens a URL in a new browser tab and switches to it.
1191
1180
 
1192
1181
  Args:
1193
- url (str): The web address to load in the browser.
1182
+ url (str): The web address to load. This should be a valid and
1183
+ existing URL.
1194
1184
 
1195
1185
  Returns:
1196
- Dict[str, Any]: A dictionary containing the result, snapshot, and
1197
- tab information.
1186
+ Dict[str, Any]: A dictionary with the result of the action:
1187
+ - "result" (str): Confirmation of the action.
1188
+ - "snapshot" (str): A textual snapshot of the new page.
1189
+ - "tabs" (List[Dict]): Information about all open tabs.
1190
+ - "current_tab" (int): Index of the new active tab.
1191
+ - "total_tabs" (int): Total number of open tabs.
1198
1192
  """
1199
1193
  if not url or not isinstance(url, str):
1200
1194
  return {
@@ -1260,23 +1254,18 @@ class HybridBrowserToolkit(BaseToolkit):
1260
1254
 
1261
1255
  @action_logger
1262
1256
  async def back(self) -> Dict[str, Any]:
1263
- r"""Navigates the browser back to the previous page in history.
1257
+ r"""Goes back to the previous page in the browser history.
1264
1258
 
1265
- This function simulates clicking the browser's back button, taking
1266
- you to the previously visited page if one exists in the browser
1267
- history.
1259
+ This action simulates using the browser's "back" button in the
1260
+ currently active tab.
1268
1261
 
1269
1262
  Returns:
1270
- Dict[str, Any]: A dictionary containing:
1271
- - "result": A message indicating the outcome of the back
1272
- navigation, e.g., "Back navigation successful." or an error
1273
- message if no previous page exists.
1274
- - "snapshot": A new textual snapshot of the page after
1275
- navigation. If the snapshot is unchanged, it will be the
1276
- string "snapshot not changed".
1277
- - "tabs": List of all open tabs with their information.
1278
- - "current_tab": Index of the currently active tab.
1279
- - "total_tabs": Total number of open tabs.
1263
+ Dict[str, Any]: A dictionary with the result of the action:
1264
+ - "result" (str): Confirmation of the action.
1265
+ - "snapshot" (str): A textual snapshot of the previous page.
1266
+ - "tabs" (List[Dict]): Information about all open tabs.
1267
+ - "current_tab" (int): Index of the active tab.
1268
+ - "total_tabs" (int): Total number of open tabs.
1280
1269
  """
1281
1270
  page = await self._require_page()
1282
1271
 
@@ -1329,23 +1318,18 @@ class HybridBrowserToolkit(BaseToolkit):
1329
1318
 
1330
1319
  @action_logger
1331
1320
  async def forward(self) -> Dict[str, Any]:
1332
- r"""Navigates the browser forward to the next page in history.
1321
+ r"""Goes forward to the next page in the browser history.
1333
1322
 
1334
- This function simulates clicking the browser's forward button, taking
1335
- you to the next page in the browser history if one exists (i.e.,
1336
- if you have previously navigated back).
1323
+ This action simulates using the browser's "forward" button in the
1324
+ currently active tab.
1337
1325
 
1338
1326
  Returns:
1339
- Dict[str, Any]: A dictionary containing:
1340
- - "result": A message indicating the outcome of the forward
1341
- navigation, e.g., "Forward navigation successful." or an
1342
- error message if no next page exists.
1343
- - "snapshot": A new textual snapshot of the page after
1344
- navigation. If the snapshot is unchanged, it will be the
1345
- string "snapshot not changed".
1346
- - "tabs": List of all open tabs with their information.
1347
- - "current_tab": Index of the currently active tab.
1348
- - "total_tabs": Total number of open tabs.
1327
+ Dict[str, Any]: A dictionary with the result of the action:
1328
+ - "result" (str): Confirmation of the action.
1329
+ - "snapshot" (str): A textual snapshot of the next page.
1330
+ - "tabs" (List[Dict]): Information about all open tabs.
1331
+ - "current_tab" (int): Index of the active tab.
1332
+ - "total_tabs" (int): Total number of open tabs.
1349
1333
  """
1350
1334
  page = await self._require_page()
1351
1335
 
@@ -1399,20 +1383,16 @@ class HybridBrowserToolkit(BaseToolkit):
1399
1383
 
1400
1384
  @action_logger
1401
1385
  async def get_page_snapshot(self) -> str:
1402
- r"""Captures a textual representation of the current page's content.
1386
+ r"""Gets a textual snapshot of the page's interactive elements.
1403
1387
 
1404
- This "snapshot" provides a simplified view of the DOM, focusing on
1405
- interactive elements like links, buttons, and input fields. Each
1406
- element is assigned a unique reference ID (`ref`) that can be used in
1407
- other actions like `click` or `type`.
1408
-
1409
- The snapshot is useful for understanding the page structure and
1410
- identifying elements to interact with without needing to parse raw
1411
- HTML. A new snapshot is generated on each call.
1388
+ The snapshot lists elements like buttons, links, and inputs, each with
1389
+ a unique `ref` ID. This ID is used by other tools (e.g., `click`,
1390
+ `type`) to interact with a specific element. This tool provides no
1391
+ visual information.
1412
1392
 
1413
1393
  Returns:
1414
- str: A formatted string representing the interactive elements on
1415
- the page. For example:
1394
+ str: A formatted string representing the interactive elements and
1395
+ their `ref` IDs. For example:
1416
1396
  '- link "Sign In" [ref=1]'
1417
1397
  '- textbox "Username" [ref=2]'
1418
1398
  """
@@ -1435,32 +1415,25 @@ class HybridBrowserToolkit(BaseToolkit):
1435
1415
  @dependencies_required('PIL')
1436
1416
  @action_logger
1437
1417
  async def get_som_screenshot(self):
1438
- r"""Captures a screenshot of the current webpage and visually marks all
1439
- interactive elements. "SoM" stands for "Set of Marks".
1440
-
1441
- This method is essential for tasks requiring visual understanding of
1442
- the page layout. It works by:
1443
- 1. Taking a full-page screenshot.
1444
- 2. Identifying all interactive elements (buttons, links, inputs, etc.).
1445
- 3. Drawing colored boxes and reference IDs (`ref`) over these elements
1446
- on the screenshot.
1447
- 4. Saving the annotated image to a cache directory.
1448
- 5. Returning the image as a base64-encoded string along with a summary.
1418
+ r"""Captures a screenshot with interactive elements highlighted.
1449
1419
 
1450
- Use this when the textual snapshot from `get_page_snapshot` is
1451
- insufficient and visual context is needed to decide the next action.
1420
+ "SoM" stands for "Set of Marks". This tool takes a screenshot and draws
1421
+ boxes around clickable elements, overlaying a `ref` ID on each. Use
1422
+ this for a visual understanding of the page, especially when the
1423
+ textual snapshot is not enough.
1452
1424
 
1453
1425
  Returns:
1454
1426
  ToolResult: An object containing:
1455
- - `text`: A summary string, e.g., "Visual webpage screenshot
1427
+ - `text` (str): A summary, e.g., "Visual webpage screenshot
1456
1428
  captured with 42 interactive elements".
1457
- - `images`: A list containing a single base64-encoded PNG image
1458
- as a data URL.
1429
+ - `images` (List[str]): A list containing one base64-encoded
1430
+ PNG image data URL.
1459
1431
  """
1460
1432
  from PIL import Image
1461
1433
 
1462
1434
  from camel.utils.tool_result import ToolResult
1463
1435
 
1436
+ os.makedirs(self._cache_dir, exist_ok=True)
1464
1437
  # Get screenshot and analysis
1465
1438
  page = await self._require_page()
1466
1439
 
@@ -1516,37 +1489,33 @@ class HybridBrowserToolkit(BaseToolkit):
1516
1489
  return ToolResult(text=text_result, images=[img_data_url])
1517
1490
 
1518
1491
  async def click(self, *, ref: str) -> Dict[str, Any]:
1519
- r"""Clicks on an interactive element on the page.
1492
+ r"""Performs a click on an element on the page.
1520
1493
 
1521
1494
  Args:
1522
- ref (str): The reference ID of the element to click. This ID is
1523
- obtained from the page snapshot (see `get_page_snapshot` or
1495
+ ref (str): The `ref` ID of the element to click. This ID is
1496
+ obtained from a page snapshot (`get_page_snapshot` or
1524
1497
  `get_som_screenshot`).
1525
1498
 
1526
1499
  Returns:
1527
- Dict[str, Any]: A dictionary containing:
1528
- - "result": A message confirming the click action.
1529
- - "snapshot": A new textual snapshot of the page after the
1530
- click, which may have changed as a result of the action. If
1531
- the snapshot is unchanged, it will be the string "snapshot
1532
- not changed".
1533
- - "tabs": List of all open tabs with their information.
1534
- - "current_tab": Index of the currently active tab.
1535
- - "total_tabs": Total number of open tabs.
1500
+ Dict[str, Any]: A dictionary with the result of the action:
1501
+ - "result" (str): Confirmation of the action.
1502
+ - "snapshot" (str): A textual snapshot of the page after the
1503
+ click.
1504
+ - "tabs" (List[Dict]): Information about all open tabs.
1505
+ - "current_tab" (int): Index of the active tab.
1506
+ - "total_tabs" (int): Total number of open tabs.
1536
1507
  """
1537
1508
  self._validate_ref(ref, "click")
1538
1509
 
1539
1510
  analysis = await self._get_unified_analysis()
1540
1511
  elements = analysis.get("elements", {})
1541
1512
  if ref not in elements:
1542
- available_refs = list(elements.keys())
1543
1513
  logger.error(f"Error: Element reference '{ref}' not found. ")
1544
1514
  # Added snapshot to give more context on failure
1545
1515
  snapshot = self._format_snapshot_from_analysis(analysis)
1546
1516
  tab_info = await self._get_tab_info_for_output()
1547
1517
  return {
1548
- "result": f"Error: Element reference '{ref}' not found. "
1549
- f"Available refs: {available_refs}",
1518
+ "result": f"Error: Element reference '{ref}' not found. ",
1550
1519
  "snapshot": snapshot,
1551
1520
  **tab_info,
1552
1521
  }
@@ -1564,20 +1533,20 @@ class HybridBrowserToolkit(BaseToolkit):
1564
1533
  return result
1565
1534
 
1566
1535
  async def type(self, *, ref: str, text: str) -> Dict[str, Any]:
1567
- r"""Types text into an input field, such as a textbox or search bar.
1536
+ r"""Types text into an input element on the page.
1568
1537
 
1569
1538
  Args:
1570
- ref (str): The reference ID of the input element.
1571
- text (str): The text to be typed into the element.
1539
+ ref (str): The `ref` ID of the input element, from a snapshot.
1540
+ text (str): The text to type into the element.
1572
1541
 
1573
1542
  Returns:
1574
- Dict[str, Any]: A dictionary containing:
1575
- - "result": A message confirming the type action.
1576
- - "snapshot": A new textual snapshot of the page after the
1577
- text has been entered.
1578
- - "tabs": List of all open tabs with their information.
1579
- - "current_tab": Index of the currently active tab.
1580
- - "total_tabs": Total number of open tabs.
1543
+ Dict[str, Any]: A dictionary with the result of the action:
1544
+ - "result" (str): Confirmation of the action.
1545
+ - "snapshot" (str): A textual snapshot of the page after
1546
+ typing.
1547
+ - "tabs" (List[Dict]): Information about all open tabs.
1548
+ - "current_tab" (int): Index of the active tab.
1549
+ - "total_tabs" (int): Total number of open tabs.
1581
1550
  """
1582
1551
  self._validate_ref(ref, "type")
1583
1552
  await self._get_unified_analysis() # Ensure aria-ref attributes
@@ -1592,21 +1561,21 @@ class HybridBrowserToolkit(BaseToolkit):
1592
1561
  return result
1593
1562
 
1594
1563
  async def select(self, *, ref: str, value: str) -> Dict[str, Any]:
1595
- r"""Selects an option from a dropdown (`<select>`) element.
1564
+ r"""Selects an option in a dropdown (`<select>`) element.
1596
1565
 
1597
1566
  Args:
1598
- ref (str): The reference ID of the `<select>` element.
1599
- value (str): The value of the `<option>` to be selected. This
1600
- should match the `value` attribute of the option, not the
1601
- visible text.
1567
+ ref (str): The `ref` ID of the `<select>` element.
1568
+ value (str): The `value` attribute of the `<option>` to select,
1569
+ not its visible text.
1602
1570
 
1603
1571
  Returns:
1604
- Dict[str, Any]: A dictionary containing:
1605
- - "result": A message confirming the select action.
1606
- - "snapshot": A new snapshot of the page after the selection.
1607
- - "tabs": List of all open tabs with their information.
1608
- - "current_tab": Index of the currently active tab.
1609
- - "total_tabs": Total number of open tabs.
1572
+ Dict[str, Any]: A dictionary with the result of the action:
1573
+ - "result" (str): Confirmation of the action.
1574
+ - "snapshot" (str): A snapshot of the page after the
1575
+ selection.
1576
+ - "tabs" (List[Dict]): Information about all open tabs.
1577
+ - "current_tab" (int): Index of the active tab.
1578
+ - "total_tabs" (int): Total number of open tabs.
1610
1579
  """
1611
1580
  self._validate_ref(ref, "select")
1612
1581
  await self._get_unified_analysis()
@@ -1621,20 +1590,19 @@ class HybridBrowserToolkit(BaseToolkit):
1621
1590
  return result
1622
1591
 
1623
1592
  async def scroll(self, *, direction: str, amount: int) -> Dict[str, Any]:
1624
- r"""Scrolls the page window up or down by a specified amount.
1593
+ r"""Scrolls the current page window.
1625
1594
 
1626
1595
  Args:
1627
- direction (str): The direction to scroll. Must be either 'up' or
1628
- 'down'.
1596
+ direction (str): The direction to scroll: 'up' or 'down'.
1629
1597
  amount (int): The number of pixels to scroll.
1630
1598
 
1631
1599
  Returns:
1632
- Dict[str, Any]: A dictionary containing:
1633
- - "result": A confirmation of the scroll action.
1634
- - "snapshot": A new snapshot of the page after scrolling.
1635
- - "tabs": List of all open tabs with their information.
1636
- - "current_tab": Index of the currently active tab.
1637
- - "total_tabs": Total number of open tabs.
1600
+ Dict[str, Any]: A dictionary with the result of the action:
1601
+ - "result" (str): Confirmation of the action.
1602
+ - "snapshot" (str): A snapshot of the page after scrolling.
1603
+ - "tabs" (List[Dict]): Information about all open tabs.
1604
+ - "current_tab" (int): Index of the active tab.
1605
+ - "total_tabs" (int): Total number of open tabs.
1638
1606
  """
1639
1607
  if direction not in ("up", "down"):
1640
1608
  tab_info = await self._get_tab_info_for_output()
@@ -1656,25 +1624,17 @@ class HybridBrowserToolkit(BaseToolkit):
1656
1624
  async def enter(self) -> Dict[str, Any]:
1657
1625
  r"""Simulates pressing the Enter key on the currently focused element.
1658
1626
 
1659
- This tool is used to execute or confirm an action after interacting
1660
- with
1661
- an element, such as:
1662
- - Submitting a search query after typing in a search box.
1663
- - Confirming a form submission.
1664
- - Executing a command in a text input field.
1665
-
1666
- The common usage pattern is to first use the 'type' tool to input
1667
- text, which sets the focus, and then call 'enter' without any
1668
- parameters to trigger the action.
1627
+ This is useful for submitting forms or search queries after using the
1628
+ `type` tool.
1669
1629
 
1670
1630
  Returns:
1671
- Dict[str, Any]: A dictionary containing:
1672
- - "result": A confirmation of the Enter key action.
1673
- - "snapshot": A new page snapshot, as this action often
1674
- triggers navigation or page updates.
1675
- - "tabs": List of all open tabs with their information.
1676
- - "current_tab": Index of the currently active tab.
1677
- - "total_tabs": Total number of open tabs.
1631
+ Dict[str, Any]: A dictionary with the result of the action:
1632
+ - "result" (str): Confirmation of the action.
1633
+ - "snapshot" (str): A new page snapshot, as this action often
1634
+ triggers navigation.
1635
+ - "tabs" (List[Dict]): Information about all open tabs.
1636
+ - "current_tab" (int): Index of the active tab.
1637
+ - "total_tabs" (int): Total number of open tabs.
1678
1638
  """
1679
1639
  # Always press Enter on the currently focused element
1680
1640
  action = {"type": "enter"}
@@ -1691,25 +1651,22 @@ class HybridBrowserToolkit(BaseToolkit):
1691
1651
  async def wait_user(
1692
1652
  self, timeout_sec: Optional[float] = None
1693
1653
  ) -> Dict[str, Any]:
1694
- r"""Pauses the agent's execution and waits for human intervention.
1654
+ r"""Pauses execution and waits for human input from the console.
1695
1655
 
1696
- This is useful for tasks that require manual steps, like solving a
1697
- CAPTCHA. The agent will print a message to the console and wait
1698
- until the user presses the Enter key.
1656
+ Use this for tasks requiring manual steps, like solving a CAPTCHA. The
1657
+ agent will resume after the user presses Enter in the console.
1699
1658
 
1700
1659
  Args:
1701
- timeout_sec (Optional[float]): The maximum time to wait in
1702
- seconds. If the timeout is reached, the agent will resume
1703
- automatically. If `None`, it will wait indefinitely.
1660
+ timeout_sec (Optional[float]): Max time to wait in seconds. If
1661
+ `None`, it will wait indefinitely.
1704
1662
 
1705
1663
  Returns:
1706
- Dict[str, Any]: A dictionary containing:
1707
- - "result": A message indicating how the wait ended (e.g.,
1708
- "User resumed." or "Timeout... reached, auto-resumed.").
1709
- - "snapshot": The current page snapshot after the wait.
1710
- - "tabs": List of all open tabs with their information.
1711
- - "current_tab": Index of the currently active tab.
1712
- - "total_tabs": Total number of open tabs.
1664
+ Dict[str, Any]: A dictionary with the result of the action:
1665
+ - "result" (str): A message indicating how the wait ended.
1666
+ - "snapshot" (str): The page snapshot after the wait.
1667
+ - "tabs" (List[Dict]): Information about all open tabs.
1668
+ - "current_tab" (int): Index of the active tab.
1669
+ - "total_tabs" (int): Total number of open tabs.
1713
1670
  """
1714
1671
  import asyncio
1715
1672
 
@@ -1756,20 +1713,18 @@ class HybridBrowserToolkit(BaseToolkit):
1756
1713
 
1757
1714
  @action_logger
1758
1715
  async def get_page_links(self, *, ref: List[str]) -> Dict[str, Any]:
1759
- r"""Retrieves the full URLs for a given list of link reference IDs.
1716
+ r"""Gets the destination URLs for a list of link elements.
1760
1717
 
1761
- This is useful when you need to know the destination of a link before
1762
- clicking it.
1718
+ This is useful to know where a link goes before clicking it.
1763
1719
 
1764
1720
  Args:
1765
- ref (List[str]): A list of reference IDs for link elements,
1766
- obtained from a page snapshot.
1721
+ ref (List[str]): A list of `ref` IDs for link elements, obtained
1722
+ from a page snapshot.
1767
1723
 
1768
1724
  Returns:
1769
1725
  Dict[str, Any]: A dictionary containing:
1770
- - "links": A list of dictionaries, where each dictionary
1771
- represents a found link and has "text", "ref", and "url"
1772
- keys.
1726
+ - "links" (List[Dict]): A list of found links, where each
1727
+ link has "text", "ref", and "url" keys.
1773
1728
  """
1774
1729
  if not ref or not isinstance(ref, list):
1775
1730
  return {"links": []}
@@ -1790,26 +1745,25 @@ class HybridBrowserToolkit(BaseToolkit):
1790
1745
  async def solve_task(
1791
1746
  self, task_prompt: str, start_url: str, max_steps: int = 15
1792
1747
  ) -> str:
1793
- r"""Uses a high-level LLM agent to autonomously complete a task.
1748
+ r"""Delegates a complex, high-level task to a specialized web agent.
1794
1749
 
1795
- This function delegates control to another agent that can reason about
1796
- a task, break it down into steps, and execute browser actions to
1797
- achieve the goal. It is suitable for complex, multi-step tasks.
1750
+ Use this for multi-step tasks that can be described in a single prompt
1751
+ (e.g., "log into my account and check for new messages"). The agent
1752
+ will autonomously perform the necessary browser actions.
1798
1753
 
1799
- Note: `web_agent_model` must be provided during the toolkit's
1800
- initialization to use this function.
1754
+ NOTE: This is a high-level action; for simple interactions, use tools
1755
+ like `click` and `type`. `web_agent_model` must be provided during
1756
+ toolkit initialization.
1801
1757
 
1802
1758
  Args:
1803
- task_prompt (str): A natural language description of the task to
1804
- be completed (e.g., "log into my account on example.com").
1805
- start_url (str): The URL to start the task from.
1806
- max_steps (int): The maximum number of steps the agent is allowed
1807
- to take before stopping.
1759
+ task_prompt (str): A natural language description of the task.
1760
+ start_url (str): The URL to start the task from. This should be a
1761
+ valid and existing URL, as agents may generate non-existent
1762
+ ones.
1763
+ max_steps (int): The maximum number of steps the agent can take.
1808
1764
 
1809
1765
  Returns:
1810
- str: A summary message indicating that the task processing has
1811
- finished. The detailed trace of the agent's actions will be
1812
- printed to the standard output.
1766
+ str: A summary message indicating the task has finished.
1813
1767
  """
1814
1768
  agent = self._ensure_agent()
1815
1769
  await agent.navigate(start_url)
@@ -1944,25 +1898,21 @@ class HybridBrowserToolkit(BaseToolkit):
1944
1898
 
1945
1899
  @action_logger
1946
1900
  async def switch_tab(self, *, tab_index: int) -> Dict[str, Any]:
1947
- r"""Switches to a specific browser tab by its index.
1901
+ r"""Switches to a different browser tab using its index.
1948
1902
 
1949
- This allows you to control which tab is currently active. After
1950
- switching, all subsequent browser actions will operate on the newly
1951
- selected tab.
1903
+ After switching, all actions will apply to the new tab. Use
1904
+ `get_tab_info` to find the index of the tab you want to switch to.
1952
1905
 
1953
1906
  Args:
1954
- tab_index (int): The zero-based index of the tab to switch to.
1955
- Use `get_tab_info` to see available tabs and their indices.
1907
+ tab_index (int): The zero-based index of the tab to activate.
1956
1908
 
1957
1909
  Returns:
1958
- Dict[str, Any]: A dictionary containing:
1959
- - "result": A message indicating success or failure of the
1960
- tab switch.
1961
- - "snapshot": A textual snapshot of the newly active tab's
1962
- content.
1963
- - "tabs": List of all open tabs with their information.
1964
- - "current_tab": Index of the currently active tab.
1965
- - "total_tabs": Total number of open tabs.
1910
+ Dict[str, Any]: A dictionary with the result of the action:
1911
+ - "result" (str): Confirmation of the action.
1912
+ - "snapshot" (str): A snapshot of the newly active tab.
1913
+ - "tabs" (List[Dict]): Information about all open tabs.
1914
+ - "current_tab" (int): Index of the new active tab.
1915
+ - "total_tabs" (int): Total number of open tabs.
1966
1916
  """
1967
1917
  await self._ensure_browser()
1968
1918
  session = await self._get_session()
@@ -1993,24 +1943,21 @@ class HybridBrowserToolkit(BaseToolkit):
1993
1943
 
1994
1944
  @action_logger
1995
1945
  async def close_tab(self, *, tab_index: int) -> Dict[str, Any]:
1996
- r"""Closes a specific browser tab by its index.
1946
+ r"""Closes a browser tab using its index.
1997
1947
 
1998
- After closing a tab, the browser will automatically switch to another
1999
- available tab. If the closed tab was the only one open, the browser
2000
- session will remain active but without any pages.
1948
+ Use `get_tab_info` to find the index of the tab to close. After
1949
+ closing, the browser will switch to another tab if available.
2001
1950
 
2002
1951
  Args:
2003
1952
  tab_index (int): The zero-based index of the tab to close.
2004
1953
 
2005
1954
  Returns:
2006
- Dict[str, Any]: A dictionary containing:
2007
- - "result": A message indicating success or failure of the
2008
- tab closure.
2009
- - "snapshot": A textual snapshot of the currently active tab
2010
- after the closure (empty if no tabs remain).
2011
- - "tabs": List of remaining open tabs.
2012
- - "current_tab": Index of the currently active tab.
2013
- - "total_tabs": Total number of remaining open tabs.
1955
+ Dict[str, Any]: A dictionary with the result of the action:
1956
+ - "result" (str): Confirmation of the action.
1957
+ - "snapshot" (str): A snapshot of the active tab after closure.
1958
+ - "tabs" (List[Dict]): Information about remaining tabs.
1959
+ - "current_tab" (int): Index of the new active tab.
1960
+ - "total_tabs" (int): Total number of remaining tabs.
2014
1961
  """
2015
1962
  await self._ensure_browser()
2016
1963
  session = await self._get_session()
@@ -2046,20 +1993,20 @@ class HybridBrowserToolkit(BaseToolkit):
2046
1993
 
2047
1994
  @action_logger
2048
1995
  async def get_tab_info(self) -> Dict[str, Any]:
2049
- r"""Retrieves information about all currently open browser tabs.
1996
+ r"""Gets a list of all open browser tabs and their information.
2050
1997
 
2051
- This provides a comprehensive overview of the browser state, including
2052
- all open tabs, their titles, URLs, and which one is currently active.
1998
+ This includes each tab's index, title, and URL, and indicates which
1999
+ tab is currently active. Use this to manage multiple tabs.
2053
2000
 
2054
2001
  Returns:
2055
- Dict[str, Any]: A dictionary containing:
2056
- - "tabs": A list of dictionaries, each representing a tab with:
2057
- - "index": The zero-based index of the tab
2058
- - "title": The page title
2059
- - "url": The current URL
2060
- - "is_current": Whether this is the currently active tab
2061
- - "current_tab": Index of the currently active tab
2062
- - "total_tabs": Total number of open tabs
2002
+ Dict[str, Any]: A dictionary with tab information:
2003
+ - "tabs" (List[Dict]): A list of open tabs, each with:
2004
+ - "index" (int): The tab's zero-based index.
2005
+ - "title" (str): The page title.
2006
+ - "url" (str): The current URL.
2007
+ - "is_current" (bool): True if the tab is active.
2008
+ - "current_tab" (int): Index of the active tab.
2009
+ - "total_tabs" (int): Total number of open tabs.
2063
2010
  """
2064
2011
  await self._ensure_browser()
2065
2012
  return await self._get_tab_info_for_output()
@@ -735,11 +735,11 @@
735
735
  function renderTree(node, indent = '') {
736
736
  const lines = [];
737
737
  let meaningfulProps = '';
738
- if (node.disabled) meaningfulProps += ' disabled';
739
- if (node.occluded) meaningfulProps += ' occluded';
738
+ if (node.disabled) meaningfulProps += ' [disabled]';
739
+ if (node.occluded) meaningfulProps += ' [occluded]';
740
740
  if (node.checked !== undefined) meaningfulProps += ` checked=${node.checked}`;
741
741
  if (node.expanded !== undefined) meaningfulProps += ` expanded=${node.expanded}`;
742
- if (node.selected) meaningfulProps += ' selected';
742
+ if (node.selected) meaningfulProps += ' [selected]';
743
743
 
744
744
  // Add level attribute following Playwright's format
745
745
  if (node.level !== undefined) meaningfulProps += ` [level=${node.level}]`;
@@ -89,8 +89,8 @@ class SearchToolkit(BaseToolkit):
89
89
  depth (Literal["standard", "deep"]): The depth of the search.
90
90
  "standard" for a straightforward search, "deep" for a more
91
91
  comprehensive search.
92
- output_type (Literal["searchResults", "sourcedAnswer",
93
- "structured"]): The type of output:
92
+ output_type (Literal["searchResults", "sourcedAnswer", "structured"]):
93
+ The type of output:
94
94
  - "searchResults" for raw search results,
95
95
  - "sourcedAnswer" for an answer with supporting sources,
96
96
  - "structured" for output based on a provided schema.
@@ -265,13 +265,18 @@ class SearchToolkit(BaseToolkit):
265
265
  The country string is limited to 2 character country codes of
266
266
  supported countries. For a list of supported values, see
267
267
  Country Codes. (default: :obj:`US `)
268
- search_lang (str): The search language preference. The 2 or more
269
- character language code for which search results are provided.
270
- For a list of possible values, see Language Codes.
268
+ search_lang (str): The search language preference.
269
+ Use ONLY these exact values, NOT standard ISO codes:
270
+ 'ar', 'eu', 'bn', 'bg', 'ca', 'zh-hans', 'zh-hant', 'hr',
271
+ 'cs', 'da', 'nl', 'en', 'en-gb', 'et', 'fi', 'fr', 'gl', 'de',
272
+ 'gu', 'he', 'hi', 'hu', 'is', 'it', 'jp', 'kn', 'ko', 'lv',
273
+ 'lt', 'ms', 'ml', 'mr', 'nb', 'pl', 'pt-br', 'pt-pt', 'pa',
274
+ 'ro', 'ru', 'sr', 'sk', 'sl', 'es', 'sv', 'ta', 'te', 'th',
275
+ 'tr', 'uk', 'vi'.
271
276
  ui_lang (str): User interface language preferred in response.
272
- Usually of the format '<language_code>-<country_code>'. For
273
- more, see RFC 9110. For a list of supported values, see UI
274
- Language Codes.
277
+ Format: '<language_code>-<country_code>'. Common examples:
278
+ 'en-US', 'en-GB', 'jp-JP', 'zh-hans-CN', 'zh-hant-TW',
279
+ 'de-DE', 'fr-FR', 'es-ES', 'pt-BR', 'ru-RU', 'ko-KR'.
275
280
  count (int): The number of search results returned in response.
276
281
  The maximum is 20. The actual number delivered may be less than
277
282
  requested. Combine this parameter with offset to paginate
@@ -375,10 +380,36 @@ class SearchToolkit(BaseToolkit):
375
380
  "extra_snippets": extra_snippets,
376
381
  "summary": summary,
377
382
  }
383
+ params = {k: v for k, v in params.items() if v is not None}
378
384
 
379
385
  response = requests.get(url, headers=headers, params=params)
380
- data = response.json()["web"]
381
- return data
386
+ try:
387
+ response.raise_for_status()
388
+ except requests.HTTPError as e:
389
+ raise RuntimeError(
390
+ f"Brave API HTTP error: {e}, body={response.text!r}"
391
+ )
392
+
393
+ json_data = response.json()
394
+ # Check if response has search results
395
+ content_keys = [
396
+ 'web',
397
+ 'news',
398
+ 'videos',
399
+ 'images',
400
+ 'locations',
401
+ 'discussions',
402
+ 'faq',
403
+ 'infobox',
404
+ ]
405
+ has_results = any(key in json_data for key in content_keys)
406
+
407
+ if not has_results:
408
+ # Return empty results structure if no content found
409
+ json_data['web'] = {'results': []}
410
+ json_data['message'] = 'No search results found for the query'
411
+
412
+ return json_data
382
413
 
383
414
  @api_keys_required(
384
415
  [
@@ -941,11 +972,10 @@ class SearchToolkit(BaseToolkit):
941
972
 
942
973
  Args:
943
974
  query (str): The search query string (length >= 1 and <= 100).
944
- time_range (Literal["OneDay", "OneWeek", "OneMonth", "OneYear",
945
- "NoLimit"]): Time frame filter for search results.
975
+ time_range (Literal["OneDay", "OneWeek", "OneMonth", "OneYear", "NoLimit"]):
976
+ Time frame filter for search results.
946
977
  (default: :obj:`"NoLimit"`)
947
- industry (Optional[Literal["finance", "law", "medical",
948
- "internet", "tax", "news_province", "news_center"]]):
978
+ industry (Optional[Literal["finance", "law", "medical", "internet", "tax", "news_province", "news_center"]]):
949
979
  Industry-specific search filter. When specified, only returns
950
980
  results from sites in the specified industries. Multiple
951
981
  industries can be comma-separated.
@@ -239,6 +239,7 @@ class SlackToolkit(BaseToolkit):
239
239
  self,
240
240
  message: str,
241
241
  channel_id: str,
242
+ file_path: Optional[str] = None,
242
243
  user: Optional[str] = None,
243
244
  ) -> str:
244
245
  r"""Send a message to a Slack channel.
@@ -246,6 +247,8 @@ class SlackToolkit(BaseToolkit):
246
247
  Args:
247
248
  message (str): The message to send.
248
249
  channel_id (str): The ID of the Slack channel to send message.
250
+ file_path (Optional[str]): The path of the file to send.
251
+ Defaults to `None`.
249
252
  user (Optional[str]): The user ID of the recipient.
250
253
  Defaults to `None`.
251
254
 
@@ -257,6 +260,13 @@ class SlackToolkit(BaseToolkit):
257
260
 
258
261
  try:
259
262
  slack_client = self._login_slack()
263
+ if file_path:
264
+ response = slack_client.files_upload_v2(
265
+ channel=channel_id,
266
+ file=file_path,
267
+ initial_comment=message,
268
+ )
269
+ return f"File sent successfully, got response: {response}"
260
270
  if user:
261
271
  response = slack_client.chat_postEphemeral(
262
272
  channel=channel_id, text=message, user=user
camel/types/enums.py CHANGED
@@ -270,6 +270,7 @@ class ModelType(UnifiedModelType, Enum):
270
270
  MOONSHOT_V1_8K = "moonshot-v1-8k"
271
271
  MOONSHOT_V1_32K = "moonshot-v1-32k"
272
272
  MOONSHOT_V1_128K = "moonshot-v1-128k"
273
+ MOONSHOT_KIMI_K2 = "kimi-k2-0711-preview"
273
274
 
274
275
  # SiliconFlow models support tool calling
275
276
  SILICONFLOW_DEEPSEEK_V2_5 = "deepseek-ai/DeepSeek-V2.5"
@@ -833,6 +834,7 @@ class ModelType(UnifiedModelType, Enum):
833
834
  ModelType.MOONSHOT_V1_8K,
834
835
  ModelType.MOONSHOT_V1_32K,
835
836
  ModelType.MOONSHOT_V1_128K,
837
+ ModelType.MOONSHOT_KIMI_K2,
836
838
  }
837
839
 
838
840
  @property
@@ -1205,6 +1207,7 @@ class ModelType(UnifiedModelType, Enum):
1205
1207
  ModelType.MISTRAL_MEDIUM_3,
1206
1208
  ModelType.ERNIE_4_5_TURBO_128K,
1207
1209
  ModelType.DEEPSEEK_V3,
1210
+ ModelType.MOONSHOT_KIMI_K2,
1208
1211
  }:
1209
1212
  return 128_000
1210
1213
  elif self in {
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: camel-ai
3
- Version: 0.2.71a10
3
+ Version: 0.2.71a11
4
4
  Summary: Communicative Agents for AI Society Study
5
5
  Project-URL: Homepage, https://www.camel-ai.org/
6
6
  Project-URL: Repository, https://github.com/camel-ai/camel
@@ -127,7 +127,7 @@ Requires-Dist: sympy<2,>=1.13.3; extra == 'all'
127
127
  Requires-Dist: tabulate>=0.9.0; extra == 'all'
128
128
  Requires-Dist: tavily-python<0.6,>=0.5.0; extra == 'all'
129
129
  Requires-Dist: textblob<0.18,>=0.17.1; extra == 'all'
130
- Requires-Dist: traceroot==0.0.3a2; extra == 'all'
130
+ Requires-Dist: traceroot==0.0.3; extra == 'all'
131
131
  Requires-Dist: transformers<5,>=4; extra == 'all'
132
132
  Requires-Dist: tree-sitter-python<0.24,>=0.23.6; extra == 'all'
133
133
  Requires-Dist: tree-sitter<0.24,>=0.23.2; extra == 'all'
@@ -191,7 +191,7 @@ Requires-Dist: ipykernel<7,>=6.0.0; extra == 'dev-tools'
191
191
  Requires-Dist: jupyter-client<9,>=8.6.2; extra == 'dev-tools'
192
192
  Requires-Dist: langfuse>=2.60.5; extra == 'dev-tools'
193
193
  Requires-Dist: mcp>=1.3.0; extra == 'dev-tools'
194
- Requires-Dist: traceroot==0.0.3a2; extra == 'dev-tools'
194
+ Requires-Dist: traceroot==0.0.3; extra == 'dev-tools'
195
195
  Requires-Dist: tree-sitter-python<0.24,>=0.23.6; extra == 'dev-tools'
196
196
  Requires-Dist: tree-sitter<0.24,>=0.23.2; extra == 'dev-tools'
197
197
  Requires-Dist: typer>=0.15.2; extra == 'dev-tools'
@@ -1,4 +1,4 @@
1
- camel/__init__.py,sha256=SVt5eoUz6dQCW5uOcU6k9K8XET0mIj6RAZBzc9ixhgI,902
1
+ camel/__init__.py,sha256=0_Amq6sz_Pgv__ZMtKiptsrQ5gIku0jlCc0G6Bc1qac,902
2
2
  camel/generators.py,sha256=JRqj9_m1PF4qT6UtybzTQ-KBT9MJQt18OAAYvQ_fr2o,13844
3
3
  camel/human.py,sha256=Xg8x1cS5KK4bQ1SDByiHZnzsRpvRP-KZViNvmu38xo4,5475
4
4
  camel/logger.py,sha256=WgEwael_eT6D-lVAKHpKIpwXSTjvLbny5jbV1Ab8lnA,5760
@@ -180,7 +180,7 @@ camel/models/aws_bedrock_model.py,sha256=bcQBiHVdVuJXyPEkSdymQlGx2zHIVj5d4ouFuF8
180
180
  camel/models/azure_openai_model.py,sha256=-hnzGlV8NJAzR9wVfhe-YDazbGU43ECtw6_uFICKnPU,18393
181
181
  camel/models/base_audio_model.py,sha256=_VUWh1L3rh8mldNvM5R6jBOKtvmTeBKJyRxAdPJmPlY,3324
182
182
  camel/models/base_model.py,sha256=NouoYjMPo2K6KmKCIeU7smyEFnDkqnLL71Dh9SyJoa4,19486
183
- camel/models/cohere_model.py,sha256=V1sL8JpaOAVYOi5hAIXWdEex0Mr36_kx4-BEACQfN5o,17237
183
+ camel/models/cohere_model.py,sha256=6KvYnYxoBZ8kLMmRp5wcJisY65KhCTl6kiG1W3xOkJQ,17292
184
184
  camel/models/crynux_model.py,sha256=leEiFz1RcRtVJLJvYt_Ydyg5jkSk3VEJphgmHFz67bw,4118
185
185
  camel/models/deepseek_model.py,sha256=MXOdmpFQFbxpgh5DiTETzx3qDFUkKiFjnEjTMDeWk2k,11015
186
186
  camel/models/fish_audio_model.py,sha256=RCwORRIdCbjZXWWjjctpksPI2DnS0b68JjxunHBQ1xk,5981
@@ -193,7 +193,7 @@ camel/models/mistral_model.py,sha256=ipOVPk2boGqyGAypgKeQ9syaP0znKFQQSOqeVtockjk
193
193
  camel/models/model_factory.py,sha256=8b-LEXovPnpmD3GFKOdbtcgjCwpa91IPCJxikPxhdMs,12114
194
194
  camel/models/model_manager.py,sha256=ln3bCV_QWM3V5BrwKwjmxIeRN8ojIvPEBMMHun0MliU,9942
195
195
  camel/models/modelscope_model.py,sha256=meO7KCAwZtHpUVgwtuKe0j4jYh0IWsxa8e3mwyhGLvg,10804
196
- camel/models/moonshot_model.py,sha256=ulZYikMe65wFZ-xyo6QMmn1q4vhsodyFjMBOmZu01Xw,4622
196
+ camel/models/moonshot_model.py,sha256=BNkKcEPMieMZwClRT4w-D4crZ5Ovs8tLdK5Kxm41hWg,6465
197
197
  camel/models/nemotron_model.py,sha256=PzRuQoAEmBRZ2wcotQ8-MRz5wYachKa_CUNenMQg-3U,3091
198
198
  camel/models/netmind_model.py,sha256=YKHfntqsKqBxfh6qryn4L7CzHOIAYtyPXwJNK6NxNi4,4276
199
199
  camel/models/novita_model.py,sha256=V-g0Wrf1Zh1il6oPKh1LVy_U0nveOwJq9YBVzGp4GOI,4238
@@ -273,7 +273,7 @@ camel/societies/babyagi_playing.py,sha256=KbTdpHfZ2V8AripVck0bNTOyF-RSaMPCRARz3D
273
273
  camel/societies/role_playing.py,sha256=0XScr3WfxX1QOC71RhBLmrcS5y2c7DMQB_mAFOHU34M,31421
274
274
  camel/societies/workforce/__init__.py,sha256=bkTI-PE-MSK9AQ2V2gR6cR2WY-R7Jqy_NmXRtAoqo8o,920
275
275
  camel/societies/workforce/base.py,sha256=z2DmbTP5LL5-aCAAqglznQqCLfPmnyM5zD3w6jjtsb8,2175
276
- camel/societies/workforce/prompts.py,sha256=46qAt4CZeCqLFMt2EZIeiOWXai4DT9PIpWjkI0VbwGk,15168
276
+ camel/societies/workforce/prompts.py,sha256=AxsznORYV6E31Hcf6CcDbuV4iuUY7EFsu9MTV42P144,16517
277
277
  camel/societies/workforce/role_playing_worker.py,sha256=z5-OcNiaNEaoC206_3HD7xeonuUkD-XTxYbD3AqoNC8,10319
278
278
  camel/societies/workforce/single_agent_worker.py,sha256=fXgAEkDMhvTd-nbwy5Gw3BOaRAiPsL8mf3AW1aaNqKU,19342
279
279
  camel/societies/workforce/structured_output_handler.py,sha256=xr8szFN86hg3jQ825aEkJTjkSFQnTlbinVg4j1vZJVI,17870
@@ -333,7 +333,7 @@ camel/toolkits/data_commons_toolkit.py,sha256=aHZUSL1ACpnYGaf1rE2csVKTmXTmN8lMGR
333
333
  camel/toolkits/edgeone_pages_mcp_toolkit.py,sha256=1TFpAGHUNLggFQeN1OEw7P5laijwnlrCkfxBtgxFuUY,2331
334
334
  camel/toolkits/excel_toolkit.py,sha256=9Uk5GLWl719c4W-NcGPJTNMtodAbEE5gUgLsFkIInbk,32564
335
335
  camel/toolkits/file_write_toolkit.py,sha256=d8N8FfmK1fS13sY58PPhJh6M0vq6yh-s1-ltCZQJObg,37044
336
- camel/toolkits/function_tool.py,sha256=xCDzjxTRCVj_kmbnMFBuwK-3NuzM4JNe_kv9HLtjnIA,33644
336
+ camel/toolkits/function_tool.py,sha256=3_hE-Khqf556CeebchsPpjIDCynC6vKmUJLdh1EO_js,34295
337
337
  camel/toolkits/github_toolkit.py,sha256=iUyRrjWGAW_iljZVfNyfkm1Vi55wJxK6PsDAQs9pOag,13099
338
338
  camel/toolkits/google_calendar_toolkit.py,sha256=E-sdgdbtNBs_CXbhht9t1dsVr4DsTr5NguHkx4fvSmc,15410
339
339
  camel/toolkits/google_drive_mcp_toolkit.py,sha256=NubrRdPV8_t8bM4vP-7eKSVMuVwSEBXLfubWR_Hba7k,2583
@@ -366,10 +366,10 @@ camel/toolkits/pulse_mcp_search_toolkit.py,sha256=uLUpm19uC_4xLJow0gGVS9f-5T5EW2
366
366
  camel/toolkits/pyautogui_toolkit.py,sha256=Q810fm8cFvElRory7B74aqS2YV6BOpdRE6jkewoM8xc,16093
367
367
  camel/toolkits/reddit_toolkit.py,sha256=x0XAT1zQJVNHUr1R1HwWCgIlkamU-kPmbfb_H1WIv-w,8036
368
368
  camel/toolkits/retrieval_toolkit.py,sha256=BKjEyOqW3cGEPTS5yHPYb-Qg795iNNPIs1wjowfuq3U,3825
369
- camel/toolkits/search_toolkit.py,sha256=hqiqF8QJVaghQv36ra36SFzpjZkw7aJWsnMfGYaH_CQ,43996
369
+ camel/toolkits/search_toolkit.py,sha256=qt-g6c563p2pw0I8arXY3K45nvzu8QSKOBRMghdltuI,45161
370
370
  camel/toolkits/searxng_toolkit.py,sha256=a2GtE4FGSrmaIVvX6Yide-abBYD1wsHqitnDlx9fdVg,7664
371
371
  camel/toolkits/semantic_scholar_toolkit.py,sha256=Rh7eA_YPxV5pvPIzhjjvpr3vtlaCniJicrqzkPWW9_I,11634
372
- camel/toolkits/slack_toolkit.py,sha256=4Bj8P2ardLwfiyUz3ha5QobSvziV54E9zipysCg9GuI,11208
372
+ camel/toolkits/slack_toolkit.py,sha256=ZT6Ndlce2qjGsyZaNMfQ54nSEi7DOC9Ro7YqtK-u5O4,11651
373
373
  camel/toolkits/stripe_toolkit.py,sha256=07swo5znGTnorafC1uYLKB4NRcJIOPOx19J7tkpLYWk,10102
374
374
  camel/toolkits/sympy_toolkit.py,sha256=BAQnI8EFJydNUpKQWXBdleQ1Cm-srDBhFlqp9V9pbPQ,33757
375
375
  camel/toolkits/task_planning_toolkit.py,sha256=Ttw9fHae4omGC1SA-6uaeXVHJ1YkwiVloz_hO-fm1gw,4855
@@ -387,10 +387,10 @@ camel/toolkits/hybrid_browser_toolkit/actions.py,sha256=x6X-kEdQx3K1ID-BBwdQEciX
387
387
  camel/toolkits/hybrid_browser_toolkit/agent.py,sha256=0ifwhYUDJ5GLxfdpC5KquPaW1a0QBAutp2Y9y0YFujw,11685
388
388
  camel/toolkits/hybrid_browser_toolkit/browser_session.py,sha256=LdXjF4eBFuqoRnbPU0ErBtR5wtbcv3cv-hBXtiDkgMg,27102
389
389
  camel/toolkits/hybrid_browser_toolkit/config_loader.py,sha256=0zpDq3aFKEva2jc38kgLHnyxypIDk9SOcMjoP26tozo,15414
390
- camel/toolkits/hybrid_browser_toolkit/hybrid_browser_toolkit.py,sha256=Mfr0-1FFCfY9cgzQ5JHD4vimh0Nbu203nwmad3RDwiU,80391
390
+ camel/toolkits/hybrid_browser_toolkit/hybrid_browser_toolkit.py,sha256=5rrwj7H3qKoSUaDBPozWxcGqbdCInUrhhDTPZ6O7ZBU,77550
391
391
  camel/toolkits/hybrid_browser_toolkit/snapshot.py,sha256=3vQaFK5C1P8WnkK2eDMaFOizrZf4uUAW0LxdeoF4F2w,8539
392
392
  camel/toolkits/hybrid_browser_toolkit/stealth_script.js,sha256=z4XRSVUpAS87Sj36s3bY8XXhvRcHBlgsUOyMxV2HI80,27650
393
- camel/toolkits/hybrid_browser_toolkit/unified_analyzer.js,sha256=wVZfG-c6NqqtZnz97yyklvQsqCEeUPLH3XnvgURhIV4,40817
393
+ camel/toolkits/hybrid_browser_toolkit/unified_analyzer.js,sha256=VnzIn0KcEtxuncJi-OPZzdWbLSeSHCH-7sviFAGNM8g,40823
394
394
  camel/toolkits/open_api_specs/security_config.py,sha256=ZVnBa_zEifaE_ao2xsvV5majuJHpn2Tn7feMDOnj-eo,898
395
395
  camel/toolkits/open_api_specs/biztoc/__init__.py,sha256=OKCZrQCDwaWtXIN_2rA9FSqEvgpQRieRoHh7Ek6N16A,702
396
396
  camel/toolkits/open_api_specs/biztoc/ai-plugin.json,sha256=IJinQbLv5MFPGFwdN7PbOhwArFVExSEZdJspe-mOBIo,866
@@ -417,7 +417,7 @@ camel/toolkits/open_api_specs/web_scraper/openapi.yaml,sha256=u_WalQ01e8W1D27VnZ
417
417
  camel/toolkits/open_api_specs/web_scraper/paths/__init__.py,sha256=OKCZrQCDwaWtXIN_2rA9FSqEvgpQRieRoHh7Ek6N16A,702
418
418
  camel/toolkits/open_api_specs/web_scraper/paths/scraper.py,sha256=aWy1_ppV4NVVEZfnbN3tu9XA9yAPAC9bRStJ5JuXMRU,1117
419
419
  camel/types/__init__.py,sha256=pFTg3CWGSCfwFdoxPDTf4dKV8DdJS1x-bBPuEOmtdf0,2549
420
- camel/types/enums.py,sha256=tUTwrEj5-R6EEXxclxiMkrThLL4SotpYX3saXQI01vo,62822
420
+ camel/types/enums.py,sha256=qEPE2r4Np7JgJqSsZmM0SNQ8_hy19aeCn5da3pK93so,62948
421
421
  camel/types/mcp_registries.py,sha256=dl4LgYtSaUhsqAKpz28k_SA9La11qxqBvDLaEuyzrFE,4971
422
422
  camel/types/openai_types.py,sha256=8ZFzLe-zGmKNPfuVZFzxlxAX98lGf18gtrPhOgMmzus,2104
423
423
  camel/types/unified_model_type.py,sha256=ZweHiS4MQ1QbDEX3a3oUc-pvgueYP27Zt0SlAPcYg_4,5623
@@ -446,7 +446,7 @@ camel/verifiers/math_verifier.py,sha256=tA1D4S0sm8nsWISevxSN0hvSVtIUpqmJhzqfbuMo
446
446
  camel/verifiers/models.py,sha256=GdxYPr7UxNrR1577yW4kyroRcLGfd-H1GXgv8potDWU,2471
447
447
  camel/verifiers/physics_verifier.py,sha256=c1grrRddcrVN7szkxhv2QirwY9viIRSITWeWFF5HmLs,30187
448
448
  camel/verifiers/python_verifier.py,sha256=ogTz77wODfEcDN4tMVtiSkRQyoiZbHPY2fKybn59lHw,20558
449
- camel_ai-0.2.71a10.dist-info/METADATA,sha256=QLd0G8GK8Yk3FoOBa6p6kh2oTl-ChEguicXtGpcVEKk,50003
450
- camel_ai-0.2.71a10.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
451
- camel_ai-0.2.71a10.dist-info/licenses/LICENSE,sha256=id0nB2my5kG0xXeimIu5zZrbHLS6EQvxvkKkzIHaT2k,11343
452
- camel_ai-0.2.71a10.dist-info/RECORD,,
449
+ camel_ai-0.2.71a11.dist-info/METADATA,sha256=n_79KNQG4fYZKxJoJxX6E9J1CyXY3pny6PpBLnOZ9lk,49999
450
+ camel_ai-0.2.71a11.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
451
+ camel_ai-0.2.71a11.dist-info/licenses/LICENSE,sha256=id0nB2my5kG0xXeimIu5zZrbHLS6EQvxvkKkzIHaT2k,11343
452
+ camel_ai-0.2.71a11.dist-info/RECORD,,