camel-ai 0.2.65__py3-none-any.whl → 0.2.83a6__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.

Files changed (509) hide show
  1. camel/__init__.py +3 -3
  2. camel/agents/__init__.py +2 -2
  3. camel/agents/_types.py +9 -4
  4. camel/agents/_utils.py +40 -2
  5. camel/agents/base.py +2 -2
  6. camel/agents/chat_agent.py +5107 -995
  7. camel/agents/critic_agent.py +2 -2
  8. camel/agents/deductive_reasoner_agent.py +56 -56
  9. camel/agents/embodied_agent.py +2 -2
  10. camel/agents/knowledge_graph_agent.py +20 -20
  11. camel/agents/mcp_agent.py +35 -36
  12. camel/agents/multi_hop_generator_agent.py +3 -3
  13. camel/agents/programmed_agent_instruction.py +2 -2
  14. camel/agents/repo_agent.py +4 -3
  15. camel/agents/role_assignment_agent.py +2 -2
  16. camel/agents/search_agent.py +2 -2
  17. camel/agents/task_agent.py +2 -2
  18. camel/agents/tool_agents/__init__.py +2 -2
  19. camel/agents/tool_agents/base.py +2 -2
  20. camel/agents/tool_agents/hugging_face_tool_agent.py +3 -3
  21. camel/benchmarks/__init__.py +2 -2
  22. camel/benchmarks/apibank.py +5 -5
  23. camel/benchmarks/apibench.py +2 -2
  24. camel/benchmarks/base.py +2 -2
  25. camel/benchmarks/browsecomp.py +44 -33
  26. camel/benchmarks/gaia.py +17 -13
  27. camel/benchmarks/mock_website/README.md +1 -3
  28. camel/benchmarks/mock_website/mock_web.py +2 -2
  29. camel/benchmarks/mock_website/requirements.txt +1 -1
  30. camel/benchmarks/mock_website/shopping_mall/app.py +2 -2
  31. camel/benchmarks/mock_website/task.json +1 -1
  32. camel/benchmarks/nexus.py +3 -3
  33. camel/benchmarks/ragbench.py +2 -2
  34. camel/bots/__init__.py +2 -2
  35. camel/bots/discord/__init__.py +2 -2
  36. camel/bots/discord/discord_app.py +2 -2
  37. camel/bots/discord/discord_installation.py +2 -2
  38. camel/bots/discord/discord_store.py +3 -3
  39. camel/bots/slack/__init__.py +2 -2
  40. camel/bots/slack/models.py +4 -4
  41. camel/bots/slack/slack_app.py +2 -2
  42. camel/bots/telegram_bot.py +2 -2
  43. camel/configs/__init__.py +29 -2
  44. camel/configs/aihubmix_config.py +90 -0
  45. camel/configs/aiml_config.py +2 -2
  46. camel/configs/amd_config.py +70 -0
  47. camel/configs/anthropic_config.py +2 -2
  48. camel/configs/base_config.py +2 -2
  49. camel/configs/bedrock_config.py +5 -3
  50. camel/configs/cerebras_config.py +98 -0
  51. camel/configs/cohere_config.py +2 -2
  52. camel/configs/cometapi_config.py +106 -0
  53. camel/configs/crynux_config.py +2 -2
  54. camel/configs/deepseek_config.py +9 -8
  55. camel/configs/function_gemma_config.py +59 -0
  56. camel/configs/gemini_config.py +6 -4
  57. camel/configs/groq_config.py +6 -4
  58. camel/configs/internlm_config.py +6 -4
  59. camel/configs/litellm_config.py +2 -2
  60. camel/configs/lmstudio_config.py +6 -4
  61. camel/configs/minimax_config.py +95 -0
  62. camel/configs/mistral_config.py +2 -2
  63. camel/configs/modelscope_config.py +5 -3
  64. camel/configs/moonshot_config.py +2 -2
  65. camel/configs/nebius_config.py +105 -0
  66. camel/configs/netmind_config.py +2 -2
  67. camel/configs/novita_config.py +2 -2
  68. camel/configs/nvidia_config.py +2 -2
  69. camel/configs/ollama_config.py +2 -2
  70. camel/configs/openai_config.py +5 -3
  71. camel/configs/openrouter_config.py +6 -4
  72. camel/configs/ppio_config.py +2 -2
  73. camel/configs/qianfan_config.py +85 -0
  74. camel/configs/qwen_config.py +2 -2
  75. camel/configs/reka_config.py +2 -2
  76. camel/configs/samba_config.py +6 -4
  77. camel/configs/sglang_config.py +2 -2
  78. camel/configs/siliconflow_config.py +2 -2
  79. camel/configs/togetherai_config.py +2 -2
  80. camel/configs/vllm_config.py +4 -2
  81. camel/configs/watsonx_config.py +2 -2
  82. camel/configs/yi_config.py +6 -4
  83. camel/configs/zhipuai_config.py +6 -4
  84. camel/data_collectors/__init__.py +2 -2
  85. camel/data_collectors/alpaca_collector.py +18 -9
  86. camel/data_collectors/base.py +2 -2
  87. camel/data_collectors/sharegpt_collector.py +2 -2
  88. camel/datagen/__init__.py +2 -2
  89. camel/datagen/cot_datagen.py +3 -3
  90. camel/datagen/evol_instruct/__init__.py +2 -2
  91. camel/datagen/evol_instruct/evol_instruct.py +2 -2
  92. camel/datagen/evol_instruct/scorer.py +12 -12
  93. camel/datagen/evol_instruct/templates.py +16 -16
  94. camel/datagen/self_improving_cot.py +5 -5
  95. camel/datagen/self_instruct/__init__.py +2 -2
  96. camel/datagen/self_instruct/filter/__init__.py +2 -2
  97. camel/datagen/self_instruct/filter/filter_function.py +2 -2
  98. camel/datagen/self_instruct/filter/filter_registry.py +2 -2
  99. camel/datagen/self_instruct/filter/instruction_filter.py +2 -2
  100. camel/datagen/self_instruct/self_instruct.py +2 -2
  101. camel/datagen/self_instruct/templates.py +47 -47
  102. camel/datagen/source2synth/__init__.py +2 -2
  103. camel/datagen/source2synth/data_processor.py +2 -2
  104. camel/datagen/source2synth/models.py +2 -2
  105. camel/datagen/source2synth/user_data_processor_config.py +2 -2
  106. camel/datahubs/__init__.py +2 -2
  107. camel/datahubs/base.py +2 -2
  108. camel/datahubs/huggingface.py +2 -2
  109. camel/datahubs/models.py +2 -2
  110. camel/datasets/__init__.py +2 -2
  111. camel/datasets/base_generator.py +41 -12
  112. camel/datasets/few_shot_generator.py +18 -18
  113. camel/datasets/models.py +2 -2
  114. camel/datasets/self_instruct_generator.py +2 -2
  115. camel/datasets/static_dataset.py +2 -2
  116. camel/embeddings/__init__.py +2 -2
  117. camel/embeddings/azure_embedding.py +2 -2
  118. camel/embeddings/base.py +2 -2
  119. camel/embeddings/gemini_embedding.py +2 -2
  120. camel/embeddings/jina_embedding.py +2 -2
  121. camel/embeddings/mistral_embedding.py +2 -2
  122. camel/embeddings/openai_compatible_embedding.py +2 -2
  123. camel/embeddings/openai_embedding.py +2 -2
  124. camel/embeddings/sentence_transformers_embeddings.py +2 -2
  125. camel/embeddings/together_embedding.py +2 -2
  126. camel/embeddings/vlm_embedding.py +2 -2
  127. camel/environments/__init__.py +14 -2
  128. camel/environments/models.py +2 -2
  129. camel/environments/multi_step.py +2 -2
  130. camel/environments/rlcards_env.py +860 -0
  131. camel/environments/single_step.py +30 -5
  132. camel/environments/tic_tac_toe.py +3 -3
  133. camel/extractors/__init__.py +2 -2
  134. camel/extractors/base.py +2 -2
  135. camel/extractors/python_strategies.py +2 -2
  136. camel/generators.py +2 -2
  137. camel/human.py +2 -2
  138. camel/interpreters/__init__.py +4 -2
  139. camel/interpreters/base.py +2 -2
  140. camel/interpreters/docker/Dockerfile +14 -24
  141. camel/interpreters/docker_interpreter.py +5 -4
  142. camel/interpreters/e2b_interpreter.py +36 -3
  143. camel/interpreters/internal_python_interpreter.py +53 -4
  144. camel/interpreters/interpreter_error.py +2 -2
  145. camel/interpreters/ipython_interpreter.py +2 -2
  146. camel/interpreters/microsandbox_interpreter.py +395 -0
  147. camel/interpreters/subprocess_interpreter.py +2 -2
  148. camel/loaders/__init__.py +13 -4
  149. camel/loaders/apify_reader.py +2 -2
  150. camel/loaders/base_io.py +2 -2
  151. camel/loaders/base_loader.py +85 -0
  152. camel/loaders/chunkr_reader.py +11 -2
  153. camel/loaders/crawl4ai_reader.py +2 -2
  154. camel/loaders/firecrawl_reader.py +6 -6
  155. camel/loaders/jina_url_reader.py +2 -2
  156. camel/loaders/markitdown.py +2 -2
  157. camel/loaders/mineru_extractor.py +2 -2
  158. camel/loaders/mistral_reader.py +2 -2
  159. camel/loaders/scrapegraph_reader.py +2 -2
  160. camel/loaders/unstructured_io.py +2 -2
  161. camel/logger.py +5 -5
  162. camel/memories/__init__.py +2 -2
  163. camel/memories/agent_memories.py +86 -3
  164. camel/memories/base.py +36 -2
  165. camel/memories/blocks/__init__.py +2 -2
  166. camel/memories/blocks/chat_history_block.py +125 -7
  167. camel/memories/blocks/vectordb_block.py +10 -3
  168. camel/memories/context_creators/__init__.py +2 -2
  169. camel/memories/context_creators/score_based.py +109 -230
  170. camel/memories/records.py +90 -10
  171. camel/messages/__init__.py +2 -2
  172. camel/messages/base.py +178 -43
  173. camel/messages/conversion/__init__.py +2 -2
  174. camel/messages/conversion/alpaca.py +2 -2
  175. camel/messages/conversion/conversation_models.py +2 -2
  176. camel/messages/conversion/sharegpt/__init__.py +2 -2
  177. camel/messages/conversion/sharegpt/function_call_formatter.py +2 -2
  178. camel/messages/conversion/sharegpt/hermes/__init__.py +2 -2
  179. camel/messages/conversion/sharegpt/hermes/hermes_function_formatter.py +2 -2
  180. camel/messages/func_message.py +54 -17
  181. camel/models/__init__.py +18 -2
  182. camel/models/_utils.py +3 -3
  183. camel/models/aihubmix_model.py +83 -0
  184. camel/models/aiml_model.py +11 -18
  185. camel/models/amd_model.py +101 -0
  186. camel/models/anthropic_model.py +127 -20
  187. camel/models/aws_bedrock_model.py +12 -35
  188. camel/models/azure_openai_model.py +214 -115
  189. camel/models/base_audio_model.py +5 -3
  190. camel/models/base_model.py +378 -31
  191. camel/models/cerebras_model.py +83 -0
  192. camel/models/cohere_model.py +18 -49
  193. camel/models/cometapi_model.py +83 -0
  194. camel/models/crynux_model.py +11 -18
  195. camel/models/deepseek_model.py +20 -84
  196. camel/models/fish_audio_model.py +8 -2
  197. camel/models/function_gemma_model.py +889 -0
  198. camel/models/gemini_model.py +391 -52
  199. camel/models/groq_model.py +11 -19
  200. camel/models/internlm_model.py +11 -18
  201. camel/models/litellm_model.py +57 -49
  202. camel/models/lmstudio_model.py +17 -20
  203. camel/models/minimax_model.py +83 -0
  204. camel/models/mistral_model.py +20 -47
  205. camel/models/model_factory.py +39 -3
  206. camel/models/model_manager.py +26 -8
  207. camel/models/modelscope_model.py +13 -193
  208. camel/models/moonshot_model.py +183 -21
  209. camel/models/nebius_model.py +83 -0
  210. camel/models/nemotron_model.py +19 -9
  211. camel/models/netmind_model.py +11 -18
  212. camel/models/novita_model.py +11 -18
  213. camel/models/nvidia_model.py +11 -18
  214. camel/models/ollama_model.py +14 -21
  215. camel/models/openai_audio_models.py +2 -2
  216. camel/models/openai_compatible_model.py +190 -71
  217. camel/models/openai_model.py +192 -86
  218. camel/models/openrouter_model.py +11 -19
  219. camel/models/ppio_model.py +11 -18
  220. camel/models/qianfan_model.py +89 -0
  221. camel/models/qwen_model.py +13 -193
  222. camel/models/reka_model.py +23 -49
  223. camel/models/reward/__init__.py +2 -2
  224. camel/models/reward/base_reward_model.py +2 -2
  225. camel/models/reward/evaluator.py +2 -2
  226. camel/models/reward/nemotron_model.py +2 -2
  227. camel/models/reward/skywork_model.py +2 -2
  228. camel/models/samba_model.py +50 -75
  229. camel/models/sglang_model.py +90 -68
  230. camel/models/siliconflow_model.py +12 -35
  231. camel/models/stub_model.py +10 -7
  232. camel/models/togetherai_model.py +11 -18
  233. camel/models/vllm_model.py +10 -18
  234. camel/models/volcano_model.py +158 -19
  235. camel/models/watsonx_model.py +9 -47
  236. camel/models/yi_model.py +11 -18
  237. camel/models/zhipuai_model.py +70 -18
  238. camel/parsers/__init__.py +18 -0
  239. camel/parsers/mcp_tool_call_parser.py +176 -0
  240. camel/personas/__init__.py +2 -2
  241. camel/personas/persona.py +2 -2
  242. camel/personas/persona_hub.py +2 -2
  243. camel/prompts/__init__.py +2 -2
  244. camel/prompts/ai_society.py +2 -2
  245. camel/prompts/base.py +2 -2
  246. camel/prompts/code.py +2 -2
  247. camel/prompts/evaluation.py +2 -2
  248. camel/prompts/generate_text_embedding_data.py +2 -2
  249. camel/prompts/image_craft.py +2 -2
  250. camel/prompts/misalignment.py +2 -2
  251. camel/prompts/multi_condition_image_craft.py +2 -2
  252. camel/prompts/object_recognition.py +2 -2
  253. camel/prompts/persona_hub.py +3 -3
  254. camel/prompts/prompt_templates.py +2 -2
  255. camel/prompts/role_description_prompt_template.py +2 -2
  256. camel/prompts/solution_extraction.py +8 -8
  257. camel/prompts/task_prompt_template.py +2 -2
  258. camel/prompts/translation.py +2 -2
  259. camel/prompts/video_description_prompt.py +3 -3
  260. camel/responses/__init__.py +2 -2
  261. camel/responses/agent_responses.py +2 -2
  262. camel/retrievers/__init__.py +2 -2
  263. camel/retrievers/auto_retriever.py +3 -2
  264. camel/retrievers/base.py +2 -2
  265. camel/retrievers/bm25_retriever.py +2 -2
  266. camel/retrievers/cohere_rerank_retriever.py +2 -2
  267. camel/retrievers/hybrid_retrival.py +2 -2
  268. camel/retrievers/vector_retriever.py +2 -2
  269. camel/runtimes/Dockerfile.multi-toolkit +90 -0
  270. camel/runtimes/__init__.py +2 -2
  271. camel/runtimes/api.py +79 -23
  272. camel/runtimes/base.py +2 -2
  273. camel/runtimes/configs.py +13 -13
  274. camel/runtimes/daytona_runtime.py +17 -18
  275. camel/runtimes/docker_runtime.py +12 -12
  276. camel/runtimes/llm_guard_runtime.py +26 -26
  277. camel/runtimes/remote_http_runtime.py +11 -11
  278. camel/runtimes/ubuntu_docker_runtime.py +2 -2
  279. camel/runtimes/utils/__init__.py +2 -2
  280. camel/runtimes/utils/function_risk_toolkit.py +2 -2
  281. camel/runtimes/utils/ignore_risk_toolkit.py +2 -2
  282. camel/schemas/__init__.py +2 -2
  283. camel/schemas/base.py +2 -2
  284. camel/schemas/openai_converter.py +3 -3
  285. camel/schemas/outlines_converter.py +2 -2
  286. camel/services/agent_openapi_server.py +380 -0
  287. camel/societies/__init__.py +4 -2
  288. camel/societies/babyagi_playing.py +2 -2
  289. camel/societies/role_playing.py +201 -80
  290. camel/societies/workforce/__init__.py +10 -3
  291. camel/societies/workforce/base.py +2 -2
  292. camel/societies/workforce/events.py +145 -0
  293. camel/societies/workforce/prompts.py +259 -33
  294. camel/societies/workforce/role_playing_worker.py +88 -31
  295. camel/societies/workforce/single_agent_worker.py +638 -40
  296. camel/societies/workforce/structured_output_handler.py +512 -0
  297. camel/societies/workforce/task_channel.py +182 -38
  298. camel/societies/workforce/utils.py +780 -65
  299. camel/societies/workforce/worker.py +92 -26
  300. camel/societies/workforce/workflow_memory_manager.py +1746 -0
  301. camel/societies/workforce/workforce.py +5354 -372
  302. camel/societies/workforce/workforce_callback.py +103 -0
  303. camel/societies/workforce/workforce_logger.py +647 -0
  304. camel/societies/workforce/workforce_metrics.py +33 -0
  305. camel/storages/__init__.py +6 -2
  306. camel/storages/graph_storages/__init__.py +2 -2
  307. camel/storages/graph_storages/base.py +2 -2
  308. camel/storages/graph_storages/graph_element.py +2 -2
  309. camel/storages/graph_storages/nebula_graph.py +4 -4
  310. camel/storages/graph_storages/neo4j_graph.py +7 -7
  311. camel/storages/key_value_storages/__init__.py +2 -2
  312. camel/storages/key_value_storages/base.py +2 -2
  313. camel/storages/key_value_storages/in_memory.py +2 -2
  314. camel/storages/key_value_storages/json.py +17 -4
  315. camel/storages/key_value_storages/mem0_cloud.py +50 -49
  316. camel/storages/key_value_storages/redis.py +2 -2
  317. camel/storages/object_storages/__init__.py +2 -2
  318. camel/storages/object_storages/amazon_s3.py +2 -2
  319. camel/storages/object_storages/azure_blob.py +2 -2
  320. camel/storages/object_storages/base.py +2 -2
  321. camel/storages/object_storages/google_cloud.py +3 -3
  322. camel/storages/vectordb_storages/__init__.py +8 -2
  323. camel/storages/vectordb_storages/base.py +2 -2
  324. camel/storages/vectordb_storages/chroma.py +731 -0
  325. camel/storages/vectordb_storages/faiss.py +2 -2
  326. camel/storages/vectordb_storages/milvus.py +2 -2
  327. camel/storages/vectordb_storages/oceanbase.py +15 -15
  328. camel/storages/vectordb_storages/pgvector.py +349 -0
  329. camel/storages/vectordb_storages/qdrant.py +6 -6
  330. camel/storages/vectordb_storages/surreal.py +372 -0
  331. camel/storages/vectordb_storages/tidb.py +11 -8
  332. camel/storages/vectordb_storages/weaviate.py +2 -2
  333. camel/tasks/__init__.py +2 -2
  334. camel/tasks/task.py +348 -26
  335. camel/tasks/task_prompt.py +3 -3
  336. camel/terminators/__init__.py +2 -2
  337. camel/terminators/base.py +2 -2
  338. camel/terminators/response_terminator.py +2 -2
  339. camel/terminators/token_limit_terminator.py +2 -2
  340. camel/toolkits/__init__.py +57 -10
  341. camel/toolkits/aci_toolkit.py +66 -21
  342. camel/toolkits/arxiv_toolkit.py +8 -8
  343. camel/toolkits/ask_news_toolkit.py +2 -2
  344. camel/toolkits/async_browser_toolkit.py +4 -4
  345. camel/toolkits/audio_analysis_toolkit.py +3 -3
  346. camel/toolkits/base.py +106 -6
  347. camel/toolkits/bohrium_toolkit.py +2 -2
  348. camel/toolkits/browser_toolkit.py +34 -21
  349. camel/toolkits/browser_toolkit_commons.py +4 -4
  350. camel/toolkits/code_execution.py +31 -4
  351. camel/toolkits/context_summarizer_toolkit.py +684 -0
  352. camel/toolkits/craw4ai_toolkit.py +93 -0
  353. camel/toolkits/dappier_toolkit.py +12 -8
  354. camel/toolkits/data_commons_toolkit.py +2 -2
  355. camel/toolkits/dingtalk.py +1135 -0
  356. camel/toolkits/earth_science_toolkit.py +5367 -0
  357. camel/toolkits/edgeone_pages_mcp_toolkit.py +49 -0
  358. camel/toolkits/excel_toolkit.py +905 -71
  359. camel/toolkits/file_toolkit.py +1402 -0
  360. camel/toolkits/function_tool.py +205 -27
  361. camel/toolkits/github_toolkit.py +109 -22
  362. camel/toolkits/gmail_toolkit.py +1839 -0
  363. camel/toolkits/google_calendar_toolkit.py +40 -6
  364. camel/toolkits/google_drive_mcp_toolkit.py +54 -0
  365. camel/toolkits/google_maps_toolkit.py +2 -2
  366. camel/toolkits/google_scholar_toolkit.py +2 -2
  367. camel/toolkits/human_toolkit.py +36 -12
  368. camel/toolkits/hybrid_browser_toolkit/__init__.py +18 -0
  369. camel/toolkits/hybrid_browser_toolkit/config_loader.py +185 -0
  370. camel/toolkits/hybrid_browser_toolkit/hybrid_browser_toolkit.py +246 -0
  371. camel/toolkits/hybrid_browser_toolkit/hybrid_browser_toolkit_ts.py +1958 -0
  372. camel/toolkits/hybrid_browser_toolkit/installer.py +203 -0
  373. camel/toolkits/hybrid_browser_toolkit/ts/package-lock.json +4589 -0
  374. camel/toolkits/hybrid_browser_toolkit/ts/package.json +33 -0
  375. camel/toolkits/hybrid_browser_toolkit/ts/src/browser-scripts.js +125 -0
  376. camel/toolkits/hybrid_browser_toolkit/ts/src/browser-session.ts +1940 -0
  377. camel/toolkits/hybrid_browser_toolkit/ts/src/config-loader.ts +233 -0
  378. camel/toolkits/hybrid_browser_toolkit/ts/src/hybrid-browser-toolkit.ts +589 -0
  379. camel/toolkits/hybrid_browser_toolkit/ts/src/index.ts +7 -0
  380. camel/toolkits/hybrid_browser_toolkit/ts/src/parent-child-filter.ts +226 -0
  381. camel/toolkits/hybrid_browser_toolkit/ts/src/snapshot-parser.ts +219 -0
  382. camel/toolkits/hybrid_browser_toolkit/ts/src/som-screenshot-injected.ts +543 -0
  383. camel/toolkits/hybrid_browser_toolkit/ts/src/types.ts +129 -0
  384. camel/toolkits/hybrid_browser_toolkit/ts/tsconfig.json +27 -0
  385. camel/toolkits/hybrid_browser_toolkit/ts/websocket-server.js +325 -0
  386. camel/toolkits/hybrid_browser_toolkit/ws_wrapper.py +1037 -0
  387. camel/toolkits/hybrid_browser_toolkit_py/__init__.py +17 -0
  388. camel/toolkits/hybrid_browser_toolkit_py/actions.py +575 -0
  389. camel/toolkits/hybrid_browser_toolkit_py/agent.py +311 -0
  390. camel/toolkits/hybrid_browser_toolkit_py/browser_session.py +787 -0
  391. camel/toolkits/hybrid_browser_toolkit_py/config_loader.py +490 -0
  392. camel/toolkits/hybrid_browser_toolkit_py/hybrid_browser_toolkit.py +2390 -0
  393. camel/toolkits/hybrid_browser_toolkit_py/snapshot.py +233 -0
  394. camel/toolkits/hybrid_browser_toolkit_py/stealth_script.js +0 -0
  395. camel/toolkits/hybrid_browser_toolkit_py/unified_analyzer.js +1043 -0
  396. camel/toolkits/image_analysis_toolkit.py +3 -6
  397. camel/toolkits/image_generation_toolkit.py +390 -0
  398. camel/toolkits/jina_reranker_toolkit.py +5 -6
  399. camel/toolkits/klavis_toolkit.py +7 -3
  400. camel/toolkits/linkedin_toolkit.py +2 -2
  401. camel/toolkits/markitdown_toolkit.py +104 -0
  402. camel/toolkits/math_toolkit.py +66 -12
  403. camel/toolkits/mcp_toolkit.py +412 -36
  404. camel/toolkits/memory_toolkit.py +7 -3
  405. camel/toolkits/meshy_toolkit.py +2 -2
  406. camel/toolkits/message_agent_toolkit.py +608 -0
  407. camel/toolkits/message_integration.py +728 -0
  408. camel/toolkits/microsoft_outlook_mail_toolkit.py +1885 -0
  409. camel/toolkits/mineru_toolkit.py +2 -2
  410. camel/toolkits/minimax_mcp_toolkit.py +195 -0
  411. camel/toolkits/networkx_toolkit.py +2 -2
  412. camel/toolkits/note_taking_toolkit.py +277 -0
  413. camel/toolkits/notion_mcp_toolkit.py +224 -0
  414. camel/toolkits/notion_toolkit.py +2 -2
  415. camel/toolkits/open_api_specs/biztoc/__init__.py +2 -2
  416. camel/toolkits/open_api_specs/biztoc/ai-plugin.json +1 -1
  417. camel/toolkits/open_api_specs/coursera/__init__.py +2 -2
  418. camel/toolkits/open_api_specs/create_qr_code/__init__.py +2 -2
  419. camel/toolkits/open_api_specs/klarna/__init__.py +2 -2
  420. camel/toolkits/open_api_specs/nasa_apod/__init__.py +2 -2
  421. camel/toolkits/open_api_specs/outschool/__init__.py +2 -2
  422. camel/toolkits/open_api_specs/outschool/ai-plugin.json +1 -1
  423. camel/toolkits/open_api_specs/outschool/openapi.yaml +1 -1
  424. camel/toolkits/open_api_specs/outschool/paths/__init__.py +2 -2
  425. camel/toolkits/open_api_specs/outschool/paths/get_classes.py +2 -2
  426. camel/toolkits/open_api_specs/outschool/paths/search_teachers.py +2 -2
  427. camel/toolkits/open_api_specs/security_config.py +2 -2
  428. camel/toolkits/open_api_specs/speak/__init__.py +2 -2
  429. camel/toolkits/open_api_specs/web_scraper/__init__.py +2 -2
  430. camel/toolkits/open_api_specs/web_scraper/ai-plugin.json +1 -1
  431. camel/toolkits/open_api_specs/web_scraper/paths/__init__.py +2 -2
  432. camel/toolkits/open_api_specs/web_scraper/paths/scraper.py +2 -2
  433. camel/toolkits/open_api_toolkit.py +2 -2
  434. camel/toolkits/openbb_toolkit.py +7 -3
  435. camel/toolkits/origene_mcp_toolkit.py +56 -0
  436. camel/toolkits/page_script.js +53 -53
  437. camel/toolkits/playwright_mcp_toolkit.py +13 -31
  438. camel/toolkits/pptx_toolkit.py +36 -23
  439. camel/toolkits/pubmed_toolkit.py +2 -2
  440. camel/toolkits/pulse_mcp_search_toolkit.py +2 -2
  441. camel/toolkits/pyautogui_toolkit.py +2 -2
  442. camel/toolkits/reddit_toolkit.py +2 -2
  443. camel/toolkits/resend_toolkit.py +168 -0
  444. camel/toolkits/retrieval_toolkit.py +2 -2
  445. camel/toolkits/screenshot_toolkit.py +213 -0
  446. camel/toolkits/search_toolkit.py +606 -156
  447. camel/toolkits/searxng_toolkit.py +2 -2
  448. camel/toolkits/semantic_scholar_toolkit.py +2 -2
  449. camel/toolkits/slack_toolkit.py +108 -58
  450. camel/toolkits/sql_toolkit.py +712 -0
  451. camel/toolkits/stripe_toolkit.py +2 -2
  452. camel/toolkits/sympy_toolkit.py +3 -3
  453. camel/toolkits/task_planning_toolkit.py +5 -5
  454. camel/toolkits/terminal_toolkit/__init__.py +18 -0
  455. camel/toolkits/terminal_toolkit/terminal_toolkit.py +1281 -0
  456. camel/toolkits/terminal_toolkit/utils.py +659 -0
  457. camel/toolkits/thinking_toolkit.py +3 -3
  458. camel/toolkits/twitter_toolkit.py +2 -2
  459. camel/toolkits/vertex_ai_veo_toolkit.py +590 -0
  460. camel/toolkits/video_analysis_toolkit.py +109 -29
  461. camel/toolkits/video_download_toolkit.py +19 -16
  462. camel/toolkits/weather_toolkit.py +2 -2
  463. camel/toolkits/web_deploy_toolkit.py +1219 -0
  464. camel/toolkits/wechat_official_toolkit.py +483 -0
  465. camel/toolkits/whatsapp_toolkit.py +2 -2
  466. camel/toolkits/wolfram_alpha_toolkit.py +2 -2
  467. camel/toolkits/zapier_toolkit.py +7 -3
  468. camel/types/__init__.py +4 -4
  469. camel/types/agents/__init__.py +2 -2
  470. camel/types/agents/tool_calling_record.py +6 -3
  471. camel/types/enums.py +381 -41
  472. camel/types/mcp_registries.py +2 -2
  473. camel/types/openai_types.py +4 -4
  474. camel/types/unified_model_type.py +46 -10
  475. camel/utils/__init__.py +5 -2
  476. camel/utils/agent_context.py +41 -0
  477. camel/utils/async_func.py +2 -2
  478. camel/utils/chunker/__init__.py +2 -2
  479. camel/utils/chunker/base.py +2 -2
  480. camel/utils/chunker/code_chunker.py +2 -2
  481. camel/utils/chunker/uio_chunker.py +2 -2
  482. camel/utils/commons.py +38 -7
  483. camel/utils/constants.py +5 -2
  484. camel/utils/context_utils.py +1134 -0
  485. camel/utils/deduplication.py +2 -2
  486. camel/utils/filename.py +2 -2
  487. camel/utils/langfuse.py +18 -10
  488. camel/utils/mcp.py +140 -6
  489. camel/utils/mcp_client.py +48 -38
  490. camel/utils/message_summarizer.py +148 -0
  491. camel/utils/response_format.py +2 -2
  492. camel/utils/token_counting.py +45 -22
  493. camel/utils/tool_result.py +44 -0
  494. camel/verifiers/__init__.py +2 -2
  495. camel/verifiers/base.py +2 -2
  496. camel/verifiers/math_verifier.py +2 -2
  497. camel/verifiers/models.py +2 -2
  498. camel/verifiers/physics_verifier.py +2 -2
  499. camel/verifiers/python_verifier.py +2 -2
  500. {camel_ai-0.2.65.dist-info → camel_ai-0.2.83a6.dist-info}/METADATA +355 -117
  501. camel_ai-0.2.83a6.dist-info/RECORD +511 -0
  502. {camel_ai-0.2.65.dist-info → camel_ai-0.2.83a6.dist-info}/WHEEL +1 -1
  503. {camel_ai-0.2.65.dist-info → camel_ai-0.2.83a6.dist-info}/licenses/LICENSE +1 -1
  504. camel/loaders/pandas_reader.py +0 -368
  505. camel/toolkits/dalle_toolkit.py +0 -175
  506. camel/toolkits/file_write_toolkit.py +0 -444
  507. camel/toolkits/openai_agent_toolkit.py +0 -135
  508. camel/toolkits/terminal_toolkit.py +0 -1037
  509. camel_ai-0.2.65.dist-info/RECORD +0 -426
@@ -1,4 +1,4 @@
1
- # ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========
1
+ # ========= Copyright 2023-2026 @ CAMEL-AI.org. All Rights Reserved. =========
2
2
  # Licensed under the Apache License, Version 2.0 (the "License");
3
3
  # you may not use this file except in compliance with the License.
4
4
  # You may obtain a copy of the License at
@@ -10,20 +10,29 @@
10
10
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
11
  # See the License for the specific language governing permissions and
12
12
  # limitations under the License.
13
- # ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========
13
+ # ========= Copyright 2023-2026 @ CAMEL-AI.org. All Rights Reserved. =========
14
14
 
15
15
  import json
16
16
  import os
17
+ import warnings
17
18
  from contextlib import AsyncExitStack
18
19
  from typing import Any, Dict, List, Optional
19
20
 
21
+ from typing_extensions import TypeGuard
22
+
20
23
  from camel.logger import get_logger
21
- from camel.toolkits import BaseToolkit, FunctionTool
24
+ from camel.toolkits.base import BaseToolkit
25
+ from camel.toolkits.function_tool import FunctionTool
22
26
  from camel.utils.commons import run_async
23
27
  from camel.utils.mcp_client import MCPClient, create_mcp_client
24
28
 
25
29
  logger = get_logger(__name__)
26
30
 
31
+ # Suppress parameter description warnings for MCP tools
32
+ warnings.filterwarnings(
33
+ "ignore", message="Parameter description is missing", category=UserWarning
34
+ )
35
+
27
36
 
28
37
  class MCPConnectionError(Exception):
29
38
  r"""Raised when MCP connection fails."""
@@ -37,6 +46,187 @@ class MCPToolError(Exception):
37
46
  pass
38
47
 
39
48
 
49
+ _EMPTY_SCHEMA = {
50
+ "additionalProperties": False,
51
+ "type": "object",
52
+ "properties": {},
53
+ "required": [],
54
+ }
55
+
56
+
57
+ def ensure_strict_json_schema(schema: dict[str, Any]) -> dict[str, Any]:
58
+ r"""Mutates the given JSON schema to ensure it conforms to the
59
+ `strict` standard that the OpenAI API expects.
60
+ """
61
+ if schema == {}:
62
+ return _EMPTY_SCHEMA
63
+ return _ensure_strict_json_schema(schema, path=(), root=schema)
64
+
65
+
66
+ def _ensure_strict_json_schema(
67
+ json_schema: object,
68
+ *,
69
+ path: tuple[str, ...],
70
+ root: dict[str, object],
71
+ ) -> dict[str, Any]:
72
+ if not is_dict(json_schema):
73
+ raise TypeError(
74
+ f"Expected {json_schema} to be a dictionary; path={path}"
75
+ )
76
+
77
+ defs = json_schema.get("$defs")
78
+ if is_dict(defs):
79
+ for def_name, def_schema in defs.items():
80
+ _ensure_strict_json_schema(
81
+ def_schema, path=(*path, "$defs", def_name), root=root
82
+ )
83
+
84
+ definitions = json_schema.get("definitions")
85
+ if is_dict(definitions):
86
+ for definition_name, definition_schema in definitions.items():
87
+ _ensure_strict_json_schema(
88
+ definition_schema,
89
+ path=(*path, "definitions", definition_name),
90
+ root=root,
91
+ )
92
+
93
+ typ = json_schema.get("type")
94
+ if typ == "object" and "additionalProperties" not in json_schema:
95
+ json_schema["additionalProperties"] = False
96
+ elif (
97
+ typ == "object"
98
+ and "additionalProperties" in json_schema
99
+ and json_schema["additionalProperties"]
100
+ ):
101
+ raise ValueError(
102
+ "additionalProperties should not be set for object types. This "
103
+ "could be because you're using an older version of Pydantic, or "
104
+ "because you configured additional properties to be allowed. If "
105
+ "you really need this, update the function or output tool "
106
+ "to not use a strict schema."
107
+ )
108
+
109
+ # object types
110
+ # { 'type': 'object', 'properties': { 'a': {...} } }
111
+ properties = json_schema.get("properties")
112
+ if is_dict(properties):
113
+ json_schema["required"] = list(properties.keys())
114
+ json_schema["properties"] = {
115
+ key: _ensure_strict_json_schema(
116
+ prop_schema, path=(*path, "properties", key), root=root
117
+ )
118
+ for key, prop_schema in properties.items()
119
+ }
120
+
121
+ # arrays
122
+ # { 'type': 'array', 'items': {...} }
123
+ items = json_schema.get("items")
124
+ if is_dict(items):
125
+ json_schema["items"] = _ensure_strict_json_schema(
126
+ items, path=(*path, "items"), root=root
127
+ )
128
+
129
+ # unions
130
+ any_of = json_schema.get("anyOf")
131
+ if is_list(any_of):
132
+ json_schema["anyOf"] = [
133
+ _ensure_strict_json_schema(
134
+ variant, path=(*path, "anyOf", str(i)), root=root
135
+ )
136
+ for i, variant in enumerate(any_of)
137
+ ]
138
+
139
+ # intersections
140
+ all_of = json_schema.get("allOf")
141
+ if is_list(all_of):
142
+ if len(all_of) == 1:
143
+ json_schema.update(
144
+ _ensure_strict_json_schema(
145
+ all_of[0], path=(*path, "allOf", "0"), root=root
146
+ )
147
+ )
148
+ json_schema.pop("allOf")
149
+ else:
150
+ json_schema["allOf"] = [
151
+ _ensure_strict_json_schema(
152
+ entry, path=(*path, "allOf", str(i)), root=root
153
+ )
154
+ for i, entry in enumerate(all_of)
155
+ ]
156
+
157
+ # strip `None` defaults as there's no meaningful distinction here
158
+ # the schema will still be `nullable` and the model will default
159
+ # to using `None` anyway
160
+ if json_schema.get("default", None) is None:
161
+ json_schema.pop("default", None)
162
+
163
+ # we can't use `$ref`s if there are also other properties defined, e.g.
164
+ # `{"$ref": "...", "description": "my description"}`
165
+ #
166
+ # so we unravel the ref
167
+ # `{"type": "string", "description": "my description"}`
168
+ ref = json_schema.get("$ref")
169
+ if ref and has_more_than_n_keys(json_schema, 1):
170
+ assert isinstance(ref, str), f"Received non-string $ref - {ref}"
171
+
172
+ resolved = resolve_ref(root=root, ref=ref)
173
+ if not is_dict(resolved):
174
+ raise ValueError(
175
+ f"Expected `$ref: {ref}` to resolved to a dictionary but got "
176
+ f"{resolved}"
177
+ )
178
+
179
+ # properties from the json schema take priority
180
+ # over the ones on the `$ref`
181
+ json_schema.update({**resolved, **json_schema})
182
+ json_schema.pop("$ref")
183
+ # Since the schema expanded from `$ref` might not
184
+ # have `additionalProperties: false` applied
185
+ # we call `_ensure_strict_json_schema` again to fix the inlined
186
+ # schema and ensure it's valid
187
+ return _ensure_strict_json_schema(json_schema, path=path, root=root)
188
+
189
+ return json_schema
190
+
191
+
192
+ def resolve_ref(*, root: dict[str, object], ref: str) -> object:
193
+ if not ref.startswith("#/"):
194
+ raise ValueError(
195
+ f"Unexpected $ref format {ref!r}; Does not start with #/"
196
+ )
197
+
198
+ path = ref[2:].split("/")
199
+ resolved = root
200
+ for key in path:
201
+ value = resolved[key]
202
+ assert is_dict(value), (
203
+ f"encountered non-dictionary entry while resolving {ref} - "
204
+ f"{resolved}"
205
+ )
206
+ resolved = value
207
+
208
+ return resolved
209
+
210
+
211
+ def is_dict(obj: object) -> TypeGuard[dict[str, object]]:
212
+ # just pretend that we know there are only `str` keys
213
+ # as that check is not worth the performance cost
214
+ return isinstance(obj, dict)
215
+
216
+
217
+ def is_list(obj: object) -> TypeGuard[list[object]]:
218
+ return isinstance(obj, list)
219
+
220
+
221
+ def has_more_than_n_keys(obj: dict[str, object], n: int) -> bool:
222
+ i = 0
223
+ for _ in obj.keys():
224
+ i += 1
225
+ if i > n:
226
+ return True
227
+ return False
228
+
229
+
40
230
  class MCPToolkit(BaseToolkit):
41
231
  r"""MCPToolkit provides a unified interface for managing multiple
42
232
  MCP server connections and their tools.
@@ -98,8 +288,6 @@ class MCPToolkit(BaseToolkit):
98
288
  timeout (Optional[float], optional): Timeout for connection attempts
99
289
  in seconds. This timeout applies to individual client connections.
100
290
  (default: :obj:`None`)
101
- strict (Optional[bool], optional): Flag to indicate strict mode.
102
- (default: :obj:`False`)
103
291
 
104
292
  Note:
105
293
  At least one of :obj:`clients`, :obj:`config_path`, or
@@ -148,7 +336,6 @@ class MCPToolkit(BaseToolkit):
148
336
  config_path: Optional[str] = None,
149
337
  config_dict: Optional[Dict[str, Any]] = None,
150
338
  timeout: Optional[float] = None,
151
- strict: Optional[bool] = False,
152
339
  ):
153
340
  # Call parent constructor first
154
341
  super().__init__(timeout=timeout)
@@ -165,7 +352,6 @@ class MCPToolkit(BaseToolkit):
165
352
  raise ValueError(error_msg)
166
353
 
167
354
  self.clients: List[MCPClient] = clients or []
168
- self.strict = strict # Store strict parameter
169
355
  self._is_connected = False
170
356
  self._exit_stack: Optional[AsyncExitStack] = None
171
357
 
@@ -218,26 +404,34 @@ class MCPToolkit(BaseToolkit):
218
404
  self._exit_stack = AsyncExitStack()
219
405
 
220
406
  try:
221
- # Connect to all clients using AsyncExitStack
222
- for i, client in enumerate(self.clients):
223
- try:
224
- # Use MCPClient directly as async context manager
225
- await self._exit_stack.enter_async_context(client)
226
- msg = f"Connected to client {i+1}/{len(self.clients)}"
227
- logger.debug(msg)
228
- except Exception as e:
229
- logger.error(f"Failed to connect to client {i+1}: {e}")
230
- # AsyncExitStack will handle cleanup of already connected
231
- await self._exit_stack.aclose()
232
- self._exit_stack = None
233
- error_msg = f"Failed to connect to client {i+1}: {e}"
234
- raise MCPConnectionError(error_msg) from e
407
+ # Apply timeout to the entire connection process
408
+ import asyncio
409
+
410
+ timeout_seconds = self.timeout or 30.0
411
+ await asyncio.wait_for(
412
+ self._connect_all_clients(), timeout=timeout_seconds
413
+ )
235
414
 
236
415
  self._is_connected = True
237
416
  msg = f"Successfully connected to {len(self.clients)} MCP servers"
238
417
  logger.info(msg)
239
418
  return self
240
419
 
420
+ except (asyncio.TimeoutError, asyncio.CancelledError):
421
+ self._is_connected = False
422
+ if self._exit_stack:
423
+ await self._exit_stack.aclose()
424
+ self._exit_stack = None
425
+
426
+ timeout_seconds = self.timeout or 30.0
427
+ error_msg = (
428
+ f"Connection timeout after {timeout_seconds}s. "
429
+ f"One or more MCP servers are not responding. "
430
+ f"Please check if the servers are running and accessible."
431
+ )
432
+ logger.error(error_msg)
433
+ raise MCPConnectionError(error_msg)
434
+
241
435
  except Exception:
242
436
  self._is_connected = False
243
437
  if self._exit_stack:
@@ -245,6 +439,23 @@ class MCPToolkit(BaseToolkit):
245
439
  self._exit_stack = None
246
440
  raise
247
441
 
442
+ async def _connect_all_clients(self):
443
+ r"""Connect to all clients sequentially."""
444
+ # Connect to all clients using AsyncExitStack
445
+ for i, client in enumerate(self.clients):
446
+ try:
447
+ # Use MCPClient directly as async context manager
448
+ await self._exit_stack.enter_async_context(client)
449
+ msg = f"Connected to client {i+1}/{len(self.clients)}"
450
+ logger.debug(msg)
451
+ except Exception as e:
452
+ logger.error(f"Failed to connect to client {i+1}: {e}")
453
+ # AsyncExitStack will cleanup already connected clients
454
+ await self._exit_stack.aclose()
455
+ self._exit_stack = None
456
+ error_msg = f"Failed to connect to client {i+1}: {e}"
457
+ raise MCPConnectionError(error_msg) from e
458
+
248
459
  async def disconnect(self):
249
460
  r"""Disconnect from all MCP servers."""
250
461
  if not self._is_connected:
@@ -313,7 +524,6 @@ class MCPToolkit(BaseToolkit):
313
524
  config_path: Optional[str] = None,
314
525
  config_dict: Optional[Dict[str, Any]] = None,
315
526
  timeout: Optional[float] = None,
316
- strict: Optional[bool] = False,
317
527
  ) -> "MCPToolkit":
318
528
  r"""Factory method that creates and connects to all MCP servers.
319
529
 
@@ -331,8 +541,6 @@ class MCPToolkit(BaseToolkit):
331
541
  config file. (default: :obj:`None`)
332
542
  timeout (Optional[float], optional): Timeout for connection
333
543
  attempts in seconds. (default: :obj:`None`)
334
- strict (Optional[bool], optional): Flag to indicate strict mode.
335
- (default: :obj:`False`)
336
544
 
337
545
  Returns:
338
546
  MCPToolkit: A fully initialized and connected :obj:`MCPToolkit`
@@ -361,7 +569,6 @@ class MCPToolkit(BaseToolkit):
361
569
  config_path=config_path,
362
570
  config_dict=config_dict,
363
571
  timeout=timeout,
364
- strict=strict,
365
572
  )
366
573
  try:
367
574
  await toolkit.connect()
@@ -381,11 +588,10 @@ class MCPToolkit(BaseToolkit):
381
588
  config_path: Optional[str] = None,
382
589
  config_dict: Optional[Dict[str, Any]] = None,
383
590
  timeout: Optional[float] = None,
384
- strict: Optional[bool] = False,
385
591
  ) -> "MCPToolkit":
386
592
  r"""Synchronously create and connect to all MCP servers."""
387
593
  return run_async(cls.create)(
388
- clients, config_path, config_dict, timeout, strict
594
+ clients, config_path, config_dict, timeout
389
595
  )
390
596
 
391
597
  def _load_clients_from_config(self, config_path: str) -> List[MCPClient]:
@@ -442,12 +648,10 @@ class MCPToolkit(BaseToolkit):
442
648
 
443
649
  try:
444
650
  # Use the new mcp_client factory function
445
- # Pass timeout and strict from toolkit if available
651
+ # Pass timeout from toolkit if available
446
652
  kwargs = {}
447
653
  if hasattr(self, "timeout") and self.timeout is not None:
448
654
  kwargs["timeout"] = self.timeout
449
- if hasattr(self, "strict") and self.strict is not None:
450
- kwargs["strict"] = self.strict
451
655
 
452
656
  client = create_mcp_client(cfg, **kwargs)
453
657
  return client
@@ -455,17 +659,169 @@ class MCPToolkit(BaseToolkit):
455
659
  error_msg = f"Failed to create client for server '{name}': {e}"
456
660
  raise ValueError(error_msg) from e
457
661
 
662
+ def _ensure_strict_tool_schema(self, tool: FunctionTool) -> FunctionTool:
663
+ r"""Ensure a tool has a strict schema compatible with
664
+ OpenAI's requirements.
665
+
666
+ Strategy:
667
+ - Ensure parameters exist with at least an empty properties object
668
+ (OpenAI requirement).
669
+ - Try converting parameters to strict using ensure_strict_json_schema.
670
+ - If conversion fails, mark function.strict = False and
671
+ keep best-effort parameters.
672
+ """
673
+ try:
674
+ schema = tool.get_openai_tool_schema()
675
+
676
+ def _has_strict_mode_incompatible_features(json_schema):
677
+ r"""Check if schema has features incompatible
678
+ with OpenAI strict mode."""
679
+
680
+ def _check_incompatible(obj, path=""):
681
+ if not isinstance(obj, dict):
682
+ return False
683
+
684
+ # Check for allOf in array items (known to cause issues)
685
+ if "items" in obj and isinstance(obj["items"], dict):
686
+ items_schema = obj["items"]
687
+ if "allOf" in items_schema:
688
+ logger.debug(
689
+ f"Found allOf in array items at {path}"
690
+ )
691
+ return True
692
+ # Recursively check items schema
693
+ if _check_incompatible(items_schema, f"{path}.items"):
694
+ return True
695
+
696
+ # Check for other potentially problematic patterns
697
+ # anyOf/oneOf in certain contexts can also cause issues
698
+ if (
699
+ "anyOf" in obj and len(obj["anyOf"]) > 10
700
+ ): # Large unions can be problematic
701
+ return True
702
+
703
+ # Recursively check nested objects
704
+ for key in [
705
+ "properties",
706
+ "additionalProperties",
707
+ "patternProperties",
708
+ ]:
709
+ if key in obj and isinstance(obj[key], dict):
710
+ if key == "properties":
711
+ for prop_name, prop_schema in obj[key].items():
712
+ if isinstance(
713
+ prop_schema, dict
714
+ ) and _check_incompatible(
715
+ prop_schema,
716
+ f"{path}.{key}.{prop_name}",
717
+ ):
718
+ return True
719
+ elif _check_incompatible(
720
+ obj[key], f"{path}.{key}"
721
+ ):
722
+ return True
723
+
724
+ # Check arrays and unions
725
+ for key in ["allOf", "anyOf", "oneOf"]:
726
+ if key in obj and isinstance(obj[key], list):
727
+ for i, item in enumerate(obj[key]):
728
+ if isinstance(
729
+ item, dict
730
+ ) and _check_incompatible(
731
+ item, f"{path}.{key}[{i}]"
732
+ ):
733
+ return True
734
+
735
+ return False
736
+
737
+ return _check_incompatible(json_schema)
738
+
739
+ # Apply sanitization if available
740
+ if "function" in schema:
741
+ try:
742
+ from camel.toolkits.function_tool import (
743
+ sanitize_and_enforce_required,
744
+ )
745
+
746
+ schema = sanitize_and_enforce_required(schema)
747
+ except ImportError:
748
+ logger.debug("sanitize_and_enforce_required not available")
749
+
750
+ parameters = schema["function"].get("parameters", {})
751
+ if not parameters:
752
+ # Empty parameters - use minimal valid schema
753
+ parameters = {
754
+ "type": "object",
755
+ "properties": {},
756
+ "additionalProperties": False,
757
+ }
758
+ schema["function"]["parameters"] = parameters
759
+
760
+ # MCP spec doesn't require 'properties', but OpenAI spec does
761
+ if (
762
+ parameters.get("type") == "object"
763
+ and "properties" not in parameters
764
+ ):
765
+ parameters["properties"] = {}
766
+
767
+ try:
768
+ # _check_schema_limits(parameters)
769
+
770
+ # Check for OpenAI strict mode incompatible features
771
+ if _has_strict_mode_incompatible_features(parameters):
772
+ raise ValueError(
773
+ "Schema contains features "
774
+ "incompatible with strict mode"
775
+ )
776
+
777
+ strict_params = ensure_strict_json_schema(parameters)
778
+ schema["function"]["parameters"] = strict_params
779
+ schema["function"]["strict"] = True
780
+ except Exception as e:
781
+ # Fallback to non-strict mode on any failure
782
+ schema["function"]["strict"] = False
783
+ logger.warning(
784
+ f"Tool '{tool.get_function_name()}' "
785
+ f"cannot use strict mode: {e}"
786
+ )
787
+
788
+ tool.set_openai_tool_schema(schema)
789
+
790
+ except Exception as e:
791
+ # Final fallback - ensure tool still works
792
+ try:
793
+ current_schema = tool.get_openai_tool_schema()
794
+ if "function" in current_schema:
795
+ current_schema["function"]["strict"] = False
796
+ tool.set_openai_tool_schema(current_schema)
797
+ logger.warning(
798
+ f"Error processing schema for tool "
799
+ f"'{tool.get_function_name()}': {str(e)[:100]}. "
800
+ f"Using non-strict mode."
801
+ )
802
+ except Exception as inner_e:
803
+ logger.error(
804
+ f"Critical error processing tool "
805
+ f"'{tool.get_function_name()}': {inner_e}. "
806
+ f"Tool may not function correctly."
807
+ )
808
+
809
+ return tool
810
+
458
811
  def get_tools(self) -> List[FunctionTool]:
459
812
  r"""Aggregates all tools from the managed MCP client instances.
460
813
 
461
814
  Collects and combines tools from all connected MCP clients into a
462
815
  single unified list. Each tool is converted to a CAMEL-compatible
463
- :obj:`FunctionTool` that can be used with CAMEL agents.
816
+ :obj:`FunctionTool` that can be used with CAMEL agents. All tools
817
+ are ensured to have strict schemas compatible with OpenAI's
818
+ requirements.
464
819
 
465
820
  Returns:
466
821
  List[FunctionTool]: Combined list of all available function tools
467
- from all connected MCP servers. Returns an empty list if no
468
- clients are connected or if no tools are available.
822
+ from all connected MCP servers with strict schemas. Returns an
823
+ empty list if no clients are connected or if no tools are
824
+ available.
469
825
 
470
826
  Note:
471
827
  This method can be called even when the toolkit is not connected,
@@ -489,17 +845,37 @@ class MCPToolkit(BaseToolkit):
489
845
  )
490
846
 
491
847
  all_tools = []
848
+ seen_names: set[str] = set()
492
849
  for i, client in enumerate(self.clients):
493
850
  try:
494
851
  client_tools = client.get_tools()
495
- all_tools.extend(client_tools)
852
+
853
+ # Ensure all tools have strict schemas
854
+ strict_tools = []
855
+ for tool in client_tools:
856
+ strict_tool = self._ensure_strict_tool_schema(tool)
857
+ name = strict_tool.get_function_name()
858
+ if name in seen_names:
859
+ logger.warning(
860
+ f"Duplicate tool name detected and "
861
+ f"skipped: '{name}' from client {i+1}"
862
+ )
863
+ continue
864
+ seen_names.add(name)
865
+ strict_tools.append(strict_tool)
866
+
867
+ all_tools.extend(strict_tools)
496
868
  logger.debug(
497
- f"Client {i+1} contributed {len(client_tools)} tools"
869
+ f"Client {i+1} contributed {len(strict_tools)} "
870
+ f"tools (strict mode enabled)"
498
871
  )
499
872
  except Exception as e:
500
873
  logger.error(f"Failed to get tools from client {i+1}: {e}")
501
874
 
502
- logger.info(f"Total tools available: {len(all_tools)}")
875
+ logger.info(
876
+ f"Total tools available: {len(all_tools)} (all with strict "
877
+ f"schemas)"
878
+ )
503
879
  return all_tools
504
880
 
505
881
  def get_text_tools(self) -> str:
@@ -1,4 +1,4 @@
1
- # ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========
1
+ # ========= Copyright 2023-2026 @ CAMEL-AI.org. All Rights Reserved. =========
2
2
  # Licensed under the Apache License, Version 2.0 (the "License");
3
3
  # you may not use this file except in compliance with the License.
4
4
  # You may obtain a copy of the License at
@@ -10,7 +10,7 @@
10
10
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
11
  # See the License for the specific language governing permissions and
12
12
  # limitations under the License.
13
- # ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========
13
+ # ========= Copyright 2023-2026 @ CAMEL-AI.org. All Rights Reserved. =========
14
14
  import json
15
15
  from typing import TYPE_CHECKING, Optional
16
16
 
@@ -43,7 +43,11 @@ class MemoryToolkit(BaseToolkit):
43
43
  (default: :obj:`None`)
44
44
  """
45
45
 
46
- def __init__(self, agent: 'ChatAgent', timeout: Optional[float] = None):
46
+ def __init__(
47
+ self,
48
+ agent: 'ChatAgent',
49
+ timeout: Optional[float] = None,
50
+ ):
47
51
  super().__init__(timeout=timeout)
48
52
  self.agent = agent
49
53
 
@@ -1,4 +1,4 @@
1
- # ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========
1
+ # ========= Copyright 2023-2026 @ CAMEL-AI.org. All Rights Reserved. =========
2
2
  # Licensed under the Apache License, Version 2.0 (the "License");
3
3
  # you may not use this file except in compliance with the License.
4
4
  # You may obtain a copy of the License at
@@ -10,7 +10,7 @@
10
10
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
11
  # See the License for the specific language governing permissions and
12
12
  # limitations under the License.
13
- # ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========
13
+ # ========= Copyright 2023-2026 @ CAMEL-AI.org. All Rights Reserved. =========
14
14
 
15
15
  import os
16
16
  from typing import Any, Dict, List, Optional