camel-ai 0.2.73a4__py3-none-any.whl → 0.2.80a2__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.
Files changed (173) hide show
  1. camel/__init__.py +1 -1
  2. camel/agents/_utils.py +38 -0
  3. camel/agents/chat_agent.py +2217 -519
  4. camel/agents/mcp_agent.py +30 -27
  5. camel/configs/__init__.py +15 -0
  6. camel/configs/aihubmix_config.py +88 -0
  7. camel/configs/amd_config.py +70 -0
  8. camel/configs/cometapi_config.py +104 -0
  9. camel/configs/minimax_config.py +93 -0
  10. camel/configs/nebius_config.py +103 -0
  11. camel/data_collectors/alpaca_collector.py +15 -6
  12. camel/datasets/base_generator.py +39 -10
  13. camel/environments/single_step.py +28 -3
  14. camel/environments/tic_tac_toe.py +1 -1
  15. camel/interpreters/__init__.py +2 -0
  16. camel/interpreters/docker/Dockerfile +3 -12
  17. camel/interpreters/e2b_interpreter.py +34 -1
  18. camel/interpreters/microsandbox_interpreter.py +395 -0
  19. camel/loaders/__init__.py +11 -2
  20. camel/loaders/chunkr_reader.py +9 -0
  21. camel/memories/agent_memories.py +48 -4
  22. camel/memories/base.py +26 -0
  23. camel/memories/blocks/chat_history_block.py +122 -4
  24. camel/memories/context_creators/score_based.py +25 -384
  25. camel/memories/records.py +88 -8
  26. camel/messages/base.py +153 -34
  27. camel/models/__init__.py +10 -0
  28. camel/models/aihubmix_model.py +83 -0
  29. camel/models/aiml_model.py +1 -16
  30. camel/models/amd_model.py +101 -0
  31. camel/models/anthropic_model.py +6 -19
  32. camel/models/aws_bedrock_model.py +2 -33
  33. camel/models/azure_openai_model.py +114 -89
  34. camel/models/base_audio_model.py +3 -1
  35. camel/models/base_model.py +32 -14
  36. camel/models/cohere_model.py +1 -16
  37. camel/models/cometapi_model.py +83 -0
  38. camel/models/crynux_model.py +1 -16
  39. camel/models/deepseek_model.py +1 -16
  40. camel/models/fish_audio_model.py +6 -0
  41. camel/models/gemini_model.py +36 -18
  42. camel/models/groq_model.py +1 -17
  43. camel/models/internlm_model.py +1 -16
  44. camel/models/litellm_model.py +1 -16
  45. camel/models/lmstudio_model.py +1 -17
  46. camel/models/minimax_model.py +83 -0
  47. camel/models/mistral_model.py +1 -16
  48. camel/models/model_factory.py +27 -1
  49. camel/models/modelscope_model.py +1 -16
  50. camel/models/moonshot_model.py +105 -24
  51. camel/models/nebius_model.py +83 -0
  52. camel/models/nemotron_model.py +0 -5
  53. camel/models/netmind_model.py +1 -16
  54. camel/models/novita_model.py +1 -16
  55. camel/models/nvidia_model.py +1 -16
  56. camel/models/ollama_model.py +4 -19
  57. camel/models/openai_compatible_model.py +62 -41
  58. camel/models/openai_model.py +62 -57
  59. camel/models/openrouter_model.py +1 -17
  60. camel/models/ppio_model.py +1 -16
  61. camel/models/qianfan_model.py +1 -16
  62. camel/models/qwen_model.py +1 -16
  63. camel/models/reka_model.py +1 -16
  64. camel/models/samba_model.py +34 -47
  65. camel/models/sglang_model.py +64 -31
  66. camel/models/siliconflow_model.py +1 -16
  67. camel/models/stub_model.py +0 -4
  68. camel/models/togetherai_model.py +1 -16
  69. camel/models/vllm_model.py +1 -16
  70. camel/models/volcano_model.py +0 -17
  71. camel/models/watsonx_model.py +1 -16
  72. camel/models/yi_model.py +1 -16
  73. camel/models/zhipuai_model.py +60 -16
  74. camel/parsers/__init__.py +18 -0
  75. camel/parsers/mcp_tool_call_parser.py +176 -0
  76. camel/retrievers/auto_retriever.py +1 -0
  77. camel/runtimes/daytona_runtime.py +11 -12
  78. camel/societies/__init__.py +2 -0
  79. camel/societies/workforce/__init__.py +2 -0
  80. camel/societies/workforce/events.py +122 -0
  81. camel/societies/workforce/prompts.py +146 -66
  82. camel/societies/workforce/role_playing_worker.py +15 -11
  83. camel/societies/workforce/single_agent_worker.py +302 -65
  84. camel/societies/workforce/structured_output_handler.py +30 -18
  85. camel/societies/workforce/task_channel.py +163 -27
  86. camel/societies/workforce/utils.py +107 -13
  87. camel/societies/workforce/workflow_memory_manager.py +772 -0
  88. camel/societies/workforce/workforce.py +1949 -579
  89. camel/societies/workforce/workforce_callback.py +74 -0
  90. camel/societies/workforce/workforce_logger.py +168 -145
  91. camel/societies/workforce/workforce_metrics.py +33 -0
  92. camel/storages/key_value_storages/json.py +15 -2
  93. camel/storages/key_value_storages/mem0_cloud.py +48 -47
  94. camel/storages/object_storages/google_cloud.py +1 -1
  95. camel/storages/vectordb_storages/oceanbase.py +13 -13
  96. camel/storages/vectordb_storages/qdrant.py +3 -3
  97. camel/storages/vectordb_storages/tidb.py +8 -6
  98. camel/tasks/task.py +4 -3
  99. camel/toolkits/__init__.py +20 -7
  100. camel/toolkits/aci_toolkit.py +45 -0
  101. camel/toolkits/base.py +6 -4
  102. camel/toolkits/code_execution.py +28 -1
  103. camel/toolkits/context_summarizer_toolkit.py +684 -0
  104. camel/toolkits/dappier_toolkit.py +5 -1
  105. camel/toolkits/dingtalk.py +1135 -0
  106. camel/toolkits/edgeone_pages_mcp_toolkit.py +11 -31
  107. camel/toolkits/excel_toolkit.py +1 -1
  108. camel/toolkits/{file_write_toolkit.py → file_toolkit.py} +430 -36
  109. camel/toolkits/function_tool.py +13 -3
  110. camel/toolkits/github_toolkit.py +104 -17
  111. camel/toolkits/gmail_toolkit.py +1839 -0
  112. camel/toolkits/google_calendar_toolkit.py +38 -4
  113. camel/toolkits/google_drive_mcp_toolkit.py +12 -31
  114. camel/toolkits/hybrid_browser_toolkit/config_loader.py +15 -0
  115. camel/toolkits/hybrid_browser_toolkit/hybrid_browser_toolkit.py +77 -8
  116. camel/toolkits/hybrid_browser_toolkit/hybrid_browser_toolkit_ts.py +884 -88
  117. camel/toolkits/hybrid_browser_toolkit/installer.py +203 -0
  118. camel/toolkits/hybrid_browser_toolkit/ts/package-lock.json +5 -612
  119. camel/toolkits/hybrid_browser_toolkit/ts/package.json +0 -1
  120. camel/toolkits/hybrid_browser_toolkit/ts/src/browser-session.ts +959 -89
  121. camel/toolkits/hybrid_browser_toolkit/ts/src/config-loader.ts +9 -2
  122. camel/toolkits/hybrid_browser_toolkit/ts/src/hybrid-browser-toolkit.ts +281 -213
  123. camel/toolkits/hybrid_browser_toolkit/ts/src/parent-child-filter.ts +226 -0
  124. camel/toolkits/hybrid_browser_toolkit/ts/src/snapshot-parser.ts +219 -0
  125. camel/toolkits/hybrid_browser_toolkit/ts/src/som-screenshot-injected.ts +543 -0
  126. camel/toolkits/hybrid_browser_toolkit/ts/src/types.ts +23 -3
  127. camel/toolkits/hybrid_browser_toolkit/ts/websocket-server.js +72 -7
  128. camel/toolkits/hybrid_browser_toolkit/ws_wrapper.py +582 -132
  129. camel/toolkits/hybrid_browser_toolkit_py/actions.py +158 -0
  130. camel/toolkits/hybrid_browser_toolkit_py/browser_session.py +55 -8
  131. camel/toolkits/hybrid_browser_toolkit_py/config_loader.py +43 -0
  132. camel/toolkits/hybrid_browser_toolkit_py/hybrid_browser_toolkit.py +321 -8
  133. camel/toolkits/hybrid_browser_toolkit_py/snapshot.py +10 -4
  134. camel/toolkits/hybrid_browser_toolkit_py/unified_analyzer.js +45 -4
  135. camel/toolkits/{openai_image_toolkit.py → image_generation_toolkit.py} +151 -53
  136. camel/toolkits/klavis_toolkit.py +5 -1
  137. camel/toolkits/markitdown_toolkit.py +27 -1
  138. camel/toolkits/math_toolkit.py +64 -10
  139. camel/toolkits/mcp_toolkit.py +366 -71
  140. camel/toolkits/memory_toolkit.py +5 -1
  141. camel/toolkits/message_integration.py +18 -13
  142. camel/toolkits/minimax_mcp_toolkit.py +195 -0
  143. camel/toolkits/note_taking_toolkit.py +19 -10
  144. camel/toolkits/notion_mcp_toolkit.py +16 -26
  145. camel/toolkits/openbb_toolkit.py +5 -1
  146. camel/toolkits/origene_mcp_toolkit.py +8 -49
  147. camel/toolkits/playwright_mcp_toolkit.py +12 -31
  148. camel/toolkits/resend_toolkit.py +168 -0
  149. camel/toolkits/search_toolkit.py +264 -91
  150. camel/toolkits/slack_toolkit.py +64 -10
  151. camel/toolkits/terminal_toolkit/__init__.py +18 -0
  152. camel/toolkits/terminal_toolkit/terminal_toolkit.py +957 -0
  153. camel/toolkits/terminal_toolkit/utils.py +532 -0
  154. camel/toolkits/vertex_ai_veo_toolkit.py +590 -0
  155. camel/toolkits/video_analysis_toolkit.py +17 -11
  156. camel/toolkits/wechat_official_toolkit.py +483 -0
  157. camel/toolkits/zapier_toolkit.py +5 -1
  158. camel/types/__init__.py +2 -2
  159. camel/types/enums.py +274 -7
  160. camel/types/openai_types.py +2 -2
  161. camel/types/unified_model_type.py +15 -0
  162. camel/utils/commons.py +36 -5
  163. camel/utils/constants.py +3 -0
  164. camel/utils/context_utils.py +1003 -0
  165. camel/utils/mcp.py +138 -4
  166. camel/utils/token_counting.py +43 -20
  167. {camel_ai-0.2.73a4.dist-info → camel_ai-0.2.80a2.dist-info}/METADATA +223 -83
  168. {camel_ai-0.2.73a4.dist-info → camel_ai-0.2.80a2.dist-info}/RECORD +170 -141
  169. camel/loaders/pandas_reader.py +0 -368
  170. camel/toolkits/openai_agent_toolkit.py +0 -135
  171. camel/toolkits/terminal_toolkit.py +0 -1550
  172. {camel_ai-0.2.73a4.dist-info → camel_ai-0.2.80a2.dist-info}/WHEEL +0 -0
  173. {camel_ai-0.2.73a4.dist-info → camel_ai-0.2.80a2.dist-info}/licenses/LICENSE +0 -0
@@ -103,34 +103,6 @@ class Mem0Storage(BaseKeyValueStorage):
103
103
  }
104
104
  return {k: v for k, v in options.items() if v is not None}
105
105
 
106
- def _prepare_filters(
107
- self,
108
- agent_id: Optional[str] = None,
109
- user_id: Optional[str] = None,
110
- filters: Optional[Dict[str, Any]] = None,
111
- ) -> Dict[str, Any]:
112
- r"""Helper method to prepare filters for Mem0 API calls.
113
-
114
- Args:
115
- agent_id (Optional[str], optional): Agent ID to filter by
116
- (default: :obj:`None`).
117
- user_id (Optional[str], optional): User ID to filter by (default:
118
- :obj:`None`).
119
- filters (Optional[Dict[str, Any]], optional): Additional filters
120
- (default: :obj:`None`).
121
-
122
- Returns:
123
- Dict[str, Any]: Prepared filters dictionary for API calls.
124
- """
125
- base_filters: Dict[str, Any] = {"AND": []}
126
- if filters:
127
- base_filters["AND"].append(filters)
128
- if agent_id or self.agent_id:
129
- base_filters["AND"].append({"agent_id": agent_id or self.agent_id})
130
- if user_id or self.user_id:
131
- base_filters["AND"].append({"user_id": user_id or self.user_id})
132
- return base_filters if base_filters["AND"] else {}
133
-
134
106
  def _prepare_messages(
135
107
  self,
136
108
  records: List[Dict[str, Any]],
@@ -164,11 +136,11 @@ class Mem0Storage(BaseKeyValueStorage):
164
136
  agent_id=self.agent_id,
165
137
  user_id=self.user_id,
166
138
  metadata=self.metadata,
139
+ version="v2",
167
140
  )
168
141
  self.client.add(messages, **options)
169
142
  except Exception as e:
170
143
  logger.error(f"Error adding memory: {e}")
171
- logger.error(f"Error: {e}")
172
144
 
173
145
  def load(self) -> List[Dict[str, Any]]:
174
146
  r"""Loads all stored records from the Mem0 storage system.
@@ -178,47 +150,76 @@ class Mem0Storage(BaseKeyValueStorage):
178
150
  represents a stored record.
179
151
  """
180
152
  try:
181
- filters = self._prepare_filters(
182
- agent_id=self.agent_id,
183
- user_id=self.user_id,
184
- )
185
- results = self.client.get_all(version="v2", **filters)
153
+ # Build filters for get_all using proper Mem0 filter format
154
+ filters = {}
155
+ if self.agent_id:
156
+ filters = {"AND": [{"user_id": self.agent_id}]}
157
+ if self.user_id:
158
+ filters = {"AND": [{"user_id": self.user_id}]}
159
+
160
+ results = self.client.get_all(version="v2", filters=filters)
186
161
 
187
162
  # Transform results into MemoryRecord objects
188
163
  transformed_results = []
189
164
  for result in results:
165
+ # Ensure metadata is a dictionary, not None
166
+ metadata = result.get("metadata") or {}
167
+
190
168
  memory_record = MemoryRecord(
191
169
  uuid=UUID(result["id"]),
192
170
  message=BaseMessage(
193
- role_name="user",
171
+ role_name="memory",
194
172
  role_type=RoleType.USER,
195
- meta_dict={},
173
+ meta_dict=metadata,
196
174
  content=result["memory"],
197
175
  ),
198
176
  role_at_backend=OpenAIBackendRole.USER,
199
- extra_info=result.get("metadata", {}),
177
+ extra_info=metadata,
200
178
  timestamp=datetime.fromisoformat(
201
- result["created_at"]
179
+ result["created_at"].replace('Z', '+00:00')
202
180
  ).timestamp(),
203
- agent_id=result.get("agent_id", ""),
181
+ agent_id=result.get("agent_id", self.agent_id or ""),
204
182
  )
205
183
  transformed_results.append(memory_record.to_dict())
206
184
 
207
185
  return transformed_results
208
186
  except Exception as e:
209
- logger.error(f"Error searching memories: {e}")
187
+ logger.error(f"Error loading memories: {e}")
210
188
  return []
211
189
 
212
190
  def clear(
213
191
  self,
192
+ agent_id: Optional[str] = None,
193
+ user_id: Optional[str] = None,
214
194
  ) -> None:
215
- r"""Removes all records from the Mem0 storage system."""
195
+ r"""Removes all records from the Mem0 storage system.
196
+
197
+ Args:
198
+ agent_id (Optional[str]): Specific agent ID to clear memories for.
199
+ user_id (Optional[str]): Specific user ID to clear memories for.
200
+ """
216
201
  try:
217
- filters = self._prepare_filters(
218
- agent_id=self.agent_id,
219
- user_id=self.user_id,
220
- )
221
- self.client.delete_users(**filters)
202
+ # Use provided IDs or fall back to instance defaults
203
+ target_user_id = user_id or self.user_id
204
+ target_agent_id = agent_id or self.agent_id
205
+
206
+ # Build kwargs for delete_users method
207
+ kwargs = {}
208
+ if target_user_id:
209
+ kwargs['user_id'] = target_user_id
210
+ if target_agent_id:
211
+ kwargs['agent_id'] = target_agent_id
212
+
213
+ if kwargs:
214
+ # Use delete_users (plural) - this is the correct method name
215
+ self.client.delete_users(**kwargs)
216
+ logger.info(
217
+ f"Successfully cleared memories with filters: {kwargs}"
218
+ )
219
+ else:
220
+ logger.warning(
221
+ "No user_id or agent_id available for clearing memories"
222
+ )
223
+
222
224
  except Exception as e:
223
225
  logger.error(f"Error deleting memories: {e}")
224
- logger.error(f"Error: {e}")
@@ -46,7 +46,7 @@ class GoogleCloudStorage(BaseObjectStorage):
46
46
  create_if_not_exists: bool = True,
47
47
  anonymous: bool = False,
48
48
  ) -> None:
49
- from google.cloud import storage
49
+ from google.cloud import storage # type: ignore[attr-defined]
50
50
 
51
51
  self.create_if_not_exists = create_if_not_exists
52
52
 
@@ -74,7 +74,6 @@ class OceanBaseStorage(BaseVectorStorage):
74
74
  ObVecClient,
75
75
  )
76
76
  from pyobvector.client.index_param import (
77
- IndexParam,
78
77
  IndexParams,
79
78
  )
80
79
  from pyobvector.schema import VECTOR
@@ -112,20 +111,21 @@ class OceanBaseStorage(BaseVectorStorage):
112
111
 
113
112
  # Create vector index
114
113
  index_params: IndexParams = IndexParams()
115
- index_params.add_index_param(
116
- IndexParam(
117
- index_name="embedding_idx",
118
- field_name="embedding",
119
- distance=self.distance,
120
- type="hnsw",
121
- m=16,
122
- ef_construction=256,
123
- )
114
+ index_params.add_index(
115
+ field_name="embedding",
116
+ index_type="hnsw",
117
+ index_name="embedding_idx",
118
+ distance=self.distance,
119
+ m=16,
120
+ ef_construction=256,
124
121
  )
125
122
 
126
- self._client.create_vidx_with_vec_index_param(
127
- table_name=self.table_name, vidx_param=index_params.params[0]
128
- )
123
+ # Get the first index parameter
124
+ first_index_param = next(iter(index_params), None)
125
+ if first_index_param is not None:
126
+ self._client.create_vidx_with_vec_index_param(
127
+ table_name=self.table_name, vidx_param=first_index_param
128
+ )
129
129
 
130
130
  logger.info(f"Created table {self.table_name} with vector index")
131
131
  else:
@@ -14,6 +14,7 @@
14
14
  import logging
15
15
  from datetime import datetime
16
16
  from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple, Union, cast
17
+ from uuid import UUID
17
18
 
18
19
  if TYPE_CHECKING:
19
20
  from qdrant_client import QdrantClient
@@ -251,7 +252,6 @@ class QdrantStorage(BaseVectorStorage):
251
252
  else None,
252
253
  "vector_count": collection_info.points_count,
253
254
  "status": collection_info.status,
254
- "vectors_count": collection_info.vectors_count,
255
255
  "config": collection_info.config,
256
256
  }
257
257
 
@@ -304,7 +304,7 @@ class QdrantStorage(BaseVectorStorage):
304
304
  """
305
305
  from qdrant_client.http.models import PointIdsList, UpdateStatus
306
306
 
307
- points = cast(List[Union[str, int]], ids)
307
+ points = cast(List[Union[int, str, UUID]], ids)
308
308
 
309
309
  op_info = self._client.set_payload(
310
310
  collection_name=self.collection_name,
@@ -376,7 +376,7 @@ class QdrantStorage(BaseVectorStorage):
376
376
  op_info = self._client.delete(
377
377
  collection_name=self.collection_name,
378
378
  points_selector=PointIdsList(
379
- points=cast(List[Union[int, str]], ids)
379
+ points=cast(List[Union[int, str, UUID]], ids)
380
380
  ),
381
381
  **kwargs,
382
382
  )
@@ -44,7 +44,7 @@ class TiDBStorage(BaseVectorStorage):
44
44
  r"""An implementation of the `BaseVectorStorage` for interacting with TiDB.
45
45
 
46
46
  The detailed information about TiDB is available at:
47
- `TiDB Vector Search <https://ai.pingcap.com/>`_
47
+ `TiDB Vector Search <https://pingcap.com/ai>`_
48
48
 
49
49
  Args:
50
50
  vector_dim (int): The dimension of storing vectors.
@@ -107,10 +107,10 @@ class TiDBStorage(BaseVectorStorage):
107
107
  )
108
108
 
109
109
  def _get_table_model(self, collection_name: str) -> Any:
110
+ from pytidb.datatype import JSON
110
111
  from pytidb.schema import Field, TableModel, VectorField
111
- from sqlalchemy import JSON
112
112
 
113
- class VectorDBRecord(TableModel):
113
+ class VectorDBRecordBase(TableModel, table=False):
114
114
  id: Optional[str] = Field(None, primary_key=True)
115
115
  vector: list[float] = VectorField(self.vector_dim)
116
116
  payload: Optional[dict[str, Any]] = Field(None, sa_type=JSON)
@@ -119,7 +119,7 @@ class TiDBStorage(BaseVectorStorage):
119
119
  # class names.
120
120
  return type(
121
121
  f"VectorDBRecord_{collection_name}",
122
- (VectorDBRecord,),
122
+ (VectorDBRecordBase,),
123
123
  {"__tablename__": collection_name},
124
124
  table=True,
125
125
  )
@@ -128,8 +128,9 @@ class TiDBStorage(BaseVectorStorage):
128
128
  r"""Opens an existing table or creates a new table in TiDB."""
129
129
  table = self._client.open_table(self.collection_name)
130
130
  if table is None:
131
+ table_model = self._get_table_model(self.collection_name)
131
132
  table = self._client.create_table(
132
- schema=self._get_table_model(self.collection_name)
133
+ schema=table_model, if_exists="skip"
133
134
  )
134
135
  return table
135
136
 
@@ -166,6 +167,7 @@ class TiDBStorage(BaseVectorStorage):
166
167
  table.
167
168
  """
168
169
  vector_count = self._table.rows()
170
+
169
171
  # Get vector dimension from table schema
170
172
  columns = self._table.columns()
171
173
  dim_value = None
@@ -303,7 +305,7 @@ class TiDBStorage(BaseVectorStorage):
303
305
  for row in rows:
304
306
  query_results.append(
305
307
  VectorDBQueryResult.create(
306
- similarity=float(row['similarity_score']),
308
+ similarity=float(row['_score']),
307
309
  id=str(row['id']),
308
310
  payload=row['payload'],
309
311
  vector=row['vector'],
camel/tasks/task.py CHANGED
@@ -237,8 +237,9 @@ class Task(BaseModel):
237
237
  (default: :obj:`[]`)
238
238
  additional_info (Optional[Dict[str, Any]]): Additional information for
239
239
  the task. (default: :obj:`None`)
240
- image_list (Optional[List[Image.Image]]): Optional list of PIL Image
241
- objects associated with the task. (default: :obj:`None`)
240
+ image_list (Optional[List[Union[Image.Image, str]]]): Optional list
241
+ of PIL Image objects or image URLs (strings) associated with the
242
+ task. (default: :obj:`None`)
242
243
  image_detail (Literal["auto", "low", "high"]): Detail level of the
243
244
  images associated with the task. (default: :obj:`auto`)
244
245
  video_bytes (Optional[bytes]): Optional bytes of a video associated
@@ -271,7 +272,7 @@ class Task(BaseModel):
271
272
 
272
273
  additional_info: Optional[Dict[str, Any]] = None
273
274
 
274
- image_list: Optional[List[Image.Image]] = None
275
+ image_list: Optional[List[Union[Image.Image, str]]] = None
275
276
 
276
277
  image_detail: Literal["auto", "low", "high"] = "auto"
277
278
 
@@ -23,7 +23,7 @@ from .open_api_specs.security_config import openapi_security_config
23
23
  from .math_toolkit import MathToolkit
24
24
  from .search_toolkit import SearchToolkit
25
25
  from .weather_toolkit import WeatherToolkit
26
- from .openai_image_toolkit import OpenAIImageToolkit
26
+ from .image_generation_toolkit import ImageGenToolkit, OpenAIImageToolkit
27
27
  from .ask_news_toolkit import AskNewsToolkit, AsyncAskNewsToolkit
28
28
  from .linkedin_toolkit import LinkedInToolkit
29
29
  from .reddit_toolkit import RedditToolkit
@@ -37,9 +37,12 @@ from .code_execution import CodeExecutionToolkit
37
37
  from .github_toolkit import GithubToolkit
38
38
  from .google_scholar_toolkit import GoogleScholarToolkit
39
39
  from .google_calendar_toolkit import GoogleCalendarToolkit
40
+ from .gmail_toolkit import GmailToolkit
40
41
  from .arxiv_toolkit import ArxivToolkit
41
42
  from .slack_toolkit import SlackToolkit
42
43
  from .whatsapp_toolkit import WhatsAppToolkit
44
+ from .wechat_official_toolkit import WeChatOfficialToolkit
45
+ from .dingtalk import DingtalkToolkit
43
46
  from .twitter_toolkit import TwitterToolkit
44
47
  from .open_api_toolkit import OpenAPIToolkit
45
48
  from .retrieval_toolkit import RetrievalToolkit
@@ -61,14 +64,13 @@ from .image_analysis_toolkit import ImageAnalysisToolkit
61
64
  from .mcp_toolkit import MCPToolkit
62
65
  from .browser_toolkit import BrowserToolkit
63
66
  from .async_browser_toolkit import AsyncBrowserToolkit
64
- from .file_write_toolkit import FileWriteToolkit
67
+ from .file_toolkit import FileToolkit, FileWriteToolkit
65
68
  from .pptx_toolkit import PPTXToolkit
66
69
  from .terminal_toolkit import TerminalToolkit
67
70
  from .pubmed_toolkit import PubMedToolkit
68
71
  from .data_commons_toolkit import DataCommonsToolkit
69
72
  from .thinking_toolkit import ThinkingToolkit
70
73
  from .pyautogui_toolkit import PyAutoGUIToolkit
71
- from .openai_agent_toolkit import OpenAIAgentToolkit
72
74
  from .searxng_toolkit import SearxNGToolkit
73
75
  from .jina_reranker_toolkit import JinaRerankerToolkit
74
76
  from .pulse_mcp_search_toolkit import PulseMCPSearchToolkit
@@ -76,6 +78,7 @@ from .klavis_toolkit import KlavisToolkit
76
78
  from .aci_toolkit import ACIToolkit
77
79
  from .origene_mcp_toolkit import OrigeneToolkit
78
80
  from .playwright_mcp_toolkit import PlaywrightMCPToolkit
81
+ from .resend_toolkit import ResendToolkit
79
82
  from .wolfram_alpha_toolkit import WolframAlphaToolkit
80
83
  from .task_planning_toolkit import TaskPlanningToolkit
81
84
  from .hybrid_browser_toolkit import HybridBrowserToolkit
@@ -88,7 +91,10 @@ from .message_agent_toolkit import AgentCommunicationToolkit
88
91
  from .web_deploy_toolkit import WebDeployToolkit
89
92
  from .screenshot_toolkit import ScreenshotToolkit
90
93
  from .message_integration import ToolkitMessageIntegration
94
+ from .context_summarizer_toolkit import ContextSummarizerToolkit
91
95
  from .notion_mcp_toolkit import NotionMCPToolkit
96
+ from .vertex_ai_veo_toolkit import VertexAIVeoToolkit
97
+ from .minimax_mcp_toolkit import MinimaxMCPToolkit
92
98
 
93
99
  __all__ = [
94
100
  'BaseToolkit',
@@ -103,7 +109,9 @@ __all__ = [
103
109
  'SearchToolkit',
104
110
  'SlackToolkit',
105
111
  'WhatsAppToolkit',
106
- 'OpenAIImageToolkit',
112
+ 'WeChatOfficialToolkit',
113
+ 'DingtalkToolkit',
114
+ 'ImageGenToolkit',
107
115
  'TwitterToolkit',
108
116
  'WeatherToolkit',
109
117
  'RetrievalToolkit',
@@ -115,6 +123,7 @@ __all__ = [
115
123
  'AsyncAskNewsToolkit',
116
124
  'GoogleScholarToolkit',
117
125
  'GoogleCalendarToolkit',
126
+ 'GmailToolkit',
118
127
  'NotionToolkit',
119
128
  'ArxivToolkit',
120
129
  'HumanToolkit',
@@ -136,14 +145,14 @@ __all__ = [
136
145
  'ImageAnalysisToolkit',
137
146
  'BrowserToolkit',
138
147
  'AsyncBrowserToolkit',
139
- 'FileWriteToolkit',
148
+ 'FileToolkit',
149
+ 'FileWriteToolkit', # Deprecated, use FileToolkit instead
140
150
  'PPTXToolkit',
141
151
  'TerminalToolkit',
142
152
  'PubMedToolkit',
143
153
  'DataCommonsToolkit',
144
154
  'ThinkingToolkit',
145
155
  'PyAutoGUIToolkit',
146
- 'OpenAIAgentToolkit',
147
156
  'SearxNGToolkit',
148
157
  'JinaRerankerToolkit',
149
158
  'OrigeneToolkit',
@@ -151,9 +160,10 @@ __all__ = [
151
160
  'KlavisToolkit',
152
161
  'ACIToolkit',
153
162
  'PlaywrightMCPToolkit',
163
+ 'ResendToolkit',
154
164
  'WolframAlphaToolkit',
155
165
  'BohriumToolkit',
156
- 'OpenAIImageToolkit',
166
+ 'OpenAIImageToolkit', # Backward compatibility
157
167
  'TaskPlanningToolkit',
158
168
  'HybridBrowserToolkit',
159
169
  'EdgeOnePagesMCPToolkit',
@@ -166,5 +176,8 @@ __all__ = [
166
176
  'ScreenshotToolkit',
167
177
  'RegisteredAgentToolkit',
168
178
  'ToolkitMessageIntegration',
179
+ 'ContextSummarizerToolkit',
169
180
  'NotionMCPToolkit',
181
+ 'VertexAIVeoToolkit',
182
+ 'MinimaxMCPToolkit',
170
183
  ]
@@ -12,6 +12,7 @@
12
12
  # limitations under the License.
13
13
  # ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========
14
14
 
15
+ import asyncio
15
16
  import os
16
17
  from typing import TYPE_CHECKING, Dict, List, Optional, Union
17
18
 
@@ -408,6 +409,38 @@ class ACIToolkit(BaseToolkit):
408
409
  )
409
410
  return result
410
411
 
412
+ async def aexecute_function(
413
+ self,
414
+ function_name: str,
415
+ function_arguments: Dict,
416
+ linked_account_owner_id: str,
417
+ allowed_apps_only: bool = False,
418
+ ) -> Dict:
419
+ r"""Execute a function call asynchronously.
420
+
421
+ Args:
422
+ function_name (str): Name of the function to execute.
423
+ function_arguments (Dict): Arguments to pass to the function.
424
+ linked_account_owner_id (str): To specify the end-user (account
425
+ owner) on behalf of whom you want to execute functions
426
+ You need to first link corresponding account with the same
427
+ owner id in the ACI dashboard (https://platform.aci.dev).
428
+ allowed_apps_only (bool): If true, only returns functions/apps
429
+ that are allowed to be used by the agent/accessor, identified
430
+ by the api key. (default: :obj:`False`)
431
+
432
+ Returns:
433
+ Dict: Result of the function execution
434
+ """
435
+ result = await asyncio.to_thread(
436
+ self.client.handle_function_call,
437
+ function_name,
438
+ function_arguments,
439
+ linked_account_owner_id,
440
+ allowed_apps_only,
441
+ )
442
+ return result
443
+
411
444
  def get_tools(self) -> List[FunctionTool]:
412
445
  r"""Get a list of tools (functions) available in the configured apps.
413
446
 
@@ -434,6 +467,8 @@ class ACIToolkit(BaseToolkit):
434
467
  FunctionTool(self.delete_linked_account),
435
468
  FunctionTool(self.function_definition),
436
469
  FunctionTool(self.search_function),
470
+ FunctionTool(self.execute_function),
471
+ FunctionTool(self.aexecute_function),
437
472
  ]
438
473
 
439
474
  for function in _all_function:
@@ -448,6 +483,16 @@ class ACIToolkit(BaseToolkit):
448
483
  linked_account_owner_id=self.linked_account_owner_id,
449
484
  )
450
485
 
486
+ async def async_dummy_func(*, schema=schema, **kwargs):
487
+ return await self.aexecute_function(
488
+ function_name=schema['function']['name'],
489
+ function_arguments=kwargs,
490
+ linked_account_owner_id=self.linked_account_owner_id,
491
+ )
492
+
493
+ # Add async_call method to the sync function for compatibility
494
+ dummy_func.async_call = async_dummy_func # type: ignore[attr-defined]
495
+
451
496
  tool = FunctionTool(
452
497
  func=dummy_func,
453
498
  openai_tool_schema=schema,
camel/toolkits/base.py CHANGED
@@ -16,7 +16,7 @@ from typing import TYPE_CHECKING, List, Literal, Optional
16
16
 
17
17
  from camel.logger import get_logger
18
18
  from camel.toolkits import FunctionTool
19
- from camel.utils import AgentOpsMeta, with_timeout
19
+ from camel.utils import AgentOpsMeta, Constants, with_timeout
20
20
 
21
21
  if TYPE_CHECKING:
22
22
  from camel.agents import ChatAgent
@@ -35,9 +35,9 @@ class BaseToolkit(metaclass=AgentOpsMeta):
35
35
  from mcp.server import FastMCP
36
36
 
37
37
  mcp: FastMCP
38
- timeout: Optional[float] = None
38
+ timeout: Optional[float] = Constants.TIMEOUT_THRESHOLD
39
39
 
40
- def __init__(self, timeout: Optional[float] = None):
40
+ def __init__(self, timeout: Optional[float] = Constants.TIMEOUT_THRESHOLD):
41
41
  # check if timeout is a positive number
42
42
  if timeout is not None and timeout <= 0:
43
43
  raise ValueError("Timeout must be a positive number.")
@@ -48,7 +48,9 @@ class BaseToolkit(metaclass=AgentOpsMeta):
48
48
  super().__init_subclass__(**kwargs)
49
49
  for attr_name, attr_value in cls.__dict__.items():
50
50
  if callable(attr_value) and not attr_name.startswith("__"):
51
- setattr(cls, attr_name, with_timeout(attr_value))
51
+ # Skip methods that have manual timeout management
52
+ if not getattr(attr_value, '_manual_timeout', False):
53
+ setattr(cls, attr_name, with_timeout(attr_value))
52
54
 
53
55
  def get_tools(self) -> List[FunctionTool]:
54
56
  r"""Returns a list of FunctionTool objects representing the
@@ -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", "jupyter", "docker", "subprocess", "e2b"
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."