camel-ai 0.2.73a0__py3-none-any.whl → 0.2.73a1__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.73a0'
17
+ __version__ = '0.2.73a1'
18
18
 
19
19
  __all__ = [
20
20
  '__version__',
@@ -88,6 +88,7 @@ from .message_agent_toolkit import AgentCommunicationToolkit
88
88
  from .web_deploy_toolkit import WebDeployToolkit
89
89
  from .screenshot_toolkit import ScreenshotToolkit
90
90
  from .message_integration import ToolkitMessageIntegration
91
+ from .notion_mcp_toolkit import NotionMCPToolkit
91
92
 
92
93
  __all__ = [
93
94
  'BaseToolkit',
@@ -165,4 +166,5 @@ __all__ = [
165
166
  'ScreenshotToolkit',
166
167
  'RegisteredAgentToolkit',
167
168
  'ToolkitMessageIntegration',
169
+ 'NotionMCPToolkit',
168
170
  ]
@@ -518,7 +518,7 @@ class HybridBrowserToolkit(BaseToolkit, RegisteredAgentToolkit):
518
518
 
519
519
  Returns:
520
520
  str: A confirmation message indicating the screenshot was
521
- captured, the file path where it was saved, and optionally the
521
+ captured, the file path where it was saved, and optionally the
522
522
  agent's analysis if `read_image` is `True`.
523
523
  """
524
524
  import base64
@@ -50,20 +50,28 @@ export class HybridBrowserSession {
50
50
  // Handle existing pages
51
51
  const pages = this.context.pages();
52
52
  if (pages.length > 0) {
53
- // Map existing pages
53
+ // Map existing pages - for CDP, only use pages with about:blank URL
54
+ let availablePageFound = false;
54
55
  for (const page of pages) {
55
- const tabId = this.generateTabId();
56
- this.pages.set(tabId, page);
57
- if (!this.currentTabId) {
58
- this.currentTabId = tabId;
56
+ const pageUrl = page.url();
57
+ // In CDP mode, only consider pages with about:blank as available
58
+ if (pageUrl === 'about:blank') {
59
+ const tabId = this.generateTabId();
60
+ this.pages.set(tabId, page);
61
+ if (!this.currentTabId) {
62
+ this.currentTabId = tabId;
63
+ availablePageFound = true;
64
+ }
59
65
  }
60
66
  }
67
+
68
+ // If no available blank pages found in CDP mode, we cannot create new ones
69
+ if (!availablePageFound) {
70
+ throw new Error('No available blank tabs found in CDP mode. The frontend should have pre-created blank tabs.');
71
+ }
61
72
  } else {
62
- // Create initial page if none exist
63
- const initialPage = await this.context.newPage();
64
- const initialTabId = this.generateTabId();
65
- this.pages.set(initialTabId, initialPage);
66
- this.currentTabId = initialTabId;
73
+ // In CDP mode, newPage is not supported
74
+ throw new Error('No pages available in CDP mode and newPage() is not supported. Ensure the frontend has pre-created blank tabs.');
67
75
  }
68
76
  } else {
69
77
  // Original launch logic
@@ -626,18 +634,39 @@ export class HybridBrowserSession {
626
634
  throw new Error('Browser context not initialized');
627
635
  }
628
636
 
629
-
630
637
  const navigationStart = Date.now();
631
638
 
632
- // Create a new page (tab)
633
- const newPage = await this.context.newPage();
639
+ // In CDP mode, find an available blank tab instead of creating new page
640
+ let newPage: Page | null = null;
641
+ let newTabId: string | null = null;
634
642
 
635
- // Generate tab ID for the new page
636
- const newTabId = this.generateTabId();
637
- this.pages.set(newTabId, newPage);
643
+ const browserConfig = this.configLoader.getBrowserConfig();
644
+ if (browserConfig.connectOverCdp) {
645
+ // CDP mode: find an available blank tab
646
+ const allPages = this.context.pages();
647
+ for (const page of allPages) {
648
+ const pageUrl = page.url();
649
+ // Check if this page is not already tracked and is blank
650
+ const isTracked = Array.from(this.pages.values()).includes(page);
651
+ if (!isTracked && pageUrl === 'about:blank') {
652
+ newPage = page;
653
+ newTabId = this.generateTabId();
654
+ this.pages.set(newTabId, newPage);
655
+ break;
656
+ }
657
+ }
658
+
659
+ if (!newPage || !newTabId) {
660
+ throw new Error('No available blank tabs in CDP mode. Frontend should create more blank tabs when half are used.');
661
+ }
662
+ } else {
663
+ // Non-CDP mode: create new page as usual
664
+ newPage = await this.context.newPage();
665
+ newTabId = this.generateTabId();
666
+ this.pages.set(newTabId, newPage);
667
+ }
638
668
 
639
669
  // Set up page properties
640
- const browserConfig = this.configLoader.getBrowserConfig();
641
670
  newPage.setDefaultNavigationTimeout(browserConfig.navigationTimeout);
642
671
  newPage.setDefaultTimeout(browserConfig.navigationTimeout);
643
672
 
@@ -0,0 +1,234 @@
1
+ # ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========
2
+ # Licensed under the Apache License, Version 2.0 (the "License");
3
+ # you may not use this file except in compliance with the License.
4
+ # You may obtain a copy of the License at
5
+ #
6
+ # http://www.apache.org/licenses/LICENSE-2.0
7
+ #
8
+ # Unless required by applicable law or agreed to in writing, software
9
+ # distributed under the License is distributed on an "AS IS" BASIS,
10
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ # See the License for the specific language governing permissions and
12
+ # limitations under the License.
13
+ # ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========
14
+
15
+ from typing import Any, ClassVar, Dict, List, Optional, Set
16
+
17
+ from camel.toolkits import BaseToolkit, FunctionTool
18
+
19
+ from .mcp_toolkit import MCPToolkit
20
+
21
+
22
+ class NotionMCPToolkit(BaseToolkit):
23
+ r"""NotionMCPToolkit provides an interface for interacting with Notion
24
+ through the Model Context Protocol (MCP).
25
+
26
+ Attributes:
27
+ timeout (Optional[float]): Connection timeout in seconds.
28
+ (default: :obj:`None`)
29
+
30
+ Note:
31
+ Currently only supports asynchronous operation mode.
32
+ """
33
+
34
+ # TODO: Create unified method to validate and fix the schema
35
+ SCHEMA_KEYWORDS: ClassVar[Set[str]] = {
36
+ "type",
37
+ "properties",
38
+ "items",
39
+ "required",
40
+ "additionalProperties",
41
+ "description",
42
+ "title",
43
+ "default",
44
+ "enum",
45
+ "const",
46
+ "examples",
47
+ "$ref",
48
+ "$defs",
49
+ "definitions",
50
+ "allOf",
51
+ "oneOf",
52
+ "anyOf",
53
+ "not",
54
+ "if",
55
+ "then",
56
+ "else",
57
+ "format",
58
+ "pattern",
59
+ "minimum",
60
+ "maximum",
61
+ "minLength",
62
+ "maxLength",
63
+ "minItems",
64
+ "maxItems",
65
+ "uniqueItems",
66
+ }
67
+
68
+ def __init__(
69
+ self,
70
+ timeout: Optional[float] = None,
71
+ ) -> None:
72
+ r"""Initializes the NotionMCPToolkit.
73
+
74
+ Args:
75
+ timeout (Optional[float]): Connection timeout in seconds.
76
+ (default: :obj:`None`)
77
+ """
78
+ super().__init__(timeout=timeout)
79
+
80
+ self._mcp_toolkit = MCPToolkit(
81
+ config_dict={
82
+ "mcpServers": {
83
+ "notionMCP": {
84
+ "command": "npx",
85
+ "args": [
86
+ "-y",
87
+ "mcp-remote",
88
+ "https://mcp.notion.com/mcp",
89
+ ],
90
+ }
91
+ }
92
+ },
93
+ timeout=timeout,
94
+ )
95
+
96
+ async def connect(self):
97
+ r"""Explicitly connect to the Notion MCP server."""
98
+ await self._mcp_toolkit.connect()
99
+
100
+ async def disconnect(self):
101
+ r"""Explicitly disconnect from the Notion MCP server."""
102
+ await self._mcp_toolkit.disconnect()
103
+
104
+ def get_tools(self) -> List[FunctionTool]:
105
+ r"""Returns a list of tools provided by the NotionMCPToolkit.
106
+
107
+ Returns:
108
+ List[FunctionTool]: List of available tools.
109
+ """
110
+ all_tools = []
111
+ for client in self._mcp_toolkit.clients:
112
+ try:
113
+ original_build_schema = client._build_tool_schema
114
+
115
+ def create_wrapper(orig_func):
116
+ def wrapper(mcp_tool):
117
+ return self._build_notion_tool_schema(
118
+ mcp_tool, orig_func
119
+ )
120
+
121
+ return wrapper
122
+
123
+ client._build_tool_schema = create_wrapper( # type: ignore[method-assign]
124
+ original_build_schema
125
+ )
126
+
127
+ client_tools = client.get_tools()
128
+ all_tools.extend(client_tools)
129
+
130
+ client._build_tool_schema = original_build_schema # type: ignore[method-assign]
131
+
132
+ except Exception as e:
133
+ from camel.logger import get_logger
134
+
135
+ logger = get_logger(__name__)
136
+ logger.error(f"Failed to get tools from client: {e}")
137
+
138
+ return all_tools
139
+
140
+ def _build_notion_tool_schema(self, mcp_tool, original_build_schema):
141
+ r"""Build tool schema with Notion-specific fixes."""
142
+ schema = original_build_schema(mcp_tool)
143
+ self._fix_notion_schema_recursively(schema)
144
+ return schema
145
+
146
+ def _fix_notion_schema_recursively(self, obj: Any) -> None:
147
+ r"""Recursively fix Notion MCP schema issues."""
148
+ if isinstance(obj, dict):
149
+ self._fix_dict_schema(obj)
150
+ self._process_nested_structures(obj)
151
+ elif isinstance(obj, list):
152
+ for item in obj:
153
+ self._fix_notion_schema_recursively(item)
154
+
155
+ def _fix_dict_schema(self, obj: Dict[str, Any]) -> None:
156
+ r"""Fix dictionary schema issues."""
157
+ if "properties" in obj and "type" not in obj:
158
+ self._fix_missing_type_with_properties(obj)
159
+ elif obj.get("type") == "object" and "properties" in obj:
160
+ self._fix_object_with_properties(obj)
161
+
162
+ def _fix_missing_type_with_properties(self, obj: Dict[str, Any]) -> None:
163
+ r"""Fix objects with properties but missing type field."""
164
+ properties = obj.get("properties", {})
165
+ if properties and isinstance(properties, dict):
166
+ obj["type"] = "object"
167
+ obj["additionalProperties"] = False
168
+
169
+ required_properties = self._get_required_properties(
170
+ properties, conservative=True
171
+ )
172
+ if required_properties:
173
+ obj["required"] = required_properties
174
+
175
+ def _fix_object_with_properties(self, obj: Dict[str, Any]) -> None:
176
+ r"""Fix objects with type="object" and properties."""
177
+ properties = obj.get("properties", {})
178
+ if properties and isinstance(properties, dict):
179
+ existing_required = obj.get("required", [])
180
+
181
+ for prop_name, prop_schema in properties.items():
182
+ if (
183
+ prop_name not in existing_required
184
+ and prop_name not in self.SCHEMA_KEYWORDS
185
+ and self._is_property_required(prop_schema)
186
+ ):
187
+ existing_required.append(prop_name)
188
+
189
+ if existing_required:
190
+ obj["required"] = existing_required
191
+
192
+ if "additionalProperties" not in obj:
193
+ obj["additionalProperties"] = False
194
+
195
+ def _get_required_properties(
196
+ self, properties: Dict[str, Any], conservative: bool = False
197
+ ) -> List[str]:
198
+ r"""Get list of required properties from a properties dict."""
199
+ required = []
200
+ for prop_name, prop_schema in properties.items():
201
+ if (
202
+ prop_name not in self.SCHEMA_KEYWORDS
203
+ and isinstance(prop_schema, dict)
204
+ and self._is_property_required(prop_schema)
205
+ ):
206
+ required.append(prop_name)
207
+ return required
208
+
209
+ def _is_property_required(self, prop_schema: Dict[str, Any]) -> bool:
210
+ r"""Check if a property should be marked as required."""
211
+ prop_type = prop_schema.get("type")
212
+ return (
213
+ prop_type is not None
214
+ and prop_type != "null"
215
+ and "default" not in prop_schema
216
+ and not (isinstance(prop_type, list) and "null" in prop_type)
217
+ )
218
+
219
+ def _process_nested_structures(self, obj: Dict[str, Any]) -> None:
220
+ r"""Process all nested structures in a schema object."""
221
+ for key, value in obj.items():
222
+ if key in ["anyOf", "oneOf", "allOf"] and isinstance(value, list):
223
+ for item in value:
224
+ self._fix_notion_schema_recursively(item)
225
+ elif key == "items" and isinstance(value, dict):
226
+ self._fix_notion_schema_recursively(value)
227
+ elif key == "properties" and isinstance(value, dict):
228
+ for prop_value in value.values():
229
+ self._fix_notion_schema_recursively(prop_value)
230
+ elif key == "$defs" and isinstance(value, dict):
231
+ for def_value in value.values():
232
+ self._fix_notion_schema_recursively(def_value)
233
+ elif isinstance(value, (dict, list)):
234
+ self._fix_notion_schema_recursively(value)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: camel-ai
3
- Version: 0.2.73a0
3
+ Version: 0.2.73a1
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
@@ -128,7 +128,7 @@ Requires-Dist: sympy<2,>=1.13.3; extra == 'all'
128
128
  Requires-Dist: tabulate>=0.9.0; extra == 'all'
129
129
  Requires-Dist: tavily-python<0.6,>=0.5.0; extra == 'all'
130
130
  Requires-Dist: textblob<0.18,>=0.17.1; extra == 'all'
131
- Requires-Dist: traceroot==0.0.4a4; extra == 'all'
131
+ Requires-Dist: traceroot==0.0.4a5; extra == 'all'
132
132
  Requires-Dist: transformers<5,>=4; extra == 'all'
133
133
  Requires-Dist: tree-sitter-python<0.24,>=0.23.6; extra == 'all'
134
134
  Requires-Dist: tree-sitter<0.24,>=0.23.2; extra == 'all'
@@ -193,7 +193,7 @@ Requires-Dist: ipykernel<7,>=6.0.0; extra == 'dev-tools'
193
193
  Requires-Dist: jupyter-client<9,>=8.6.2; extra == 'dev-tools'
194
194
  Requires-Dist: langfuse>=2.60.5; extra == 'dev-tools'
195
195
  Requires-Dist: mcp>=1.3.0; extra == 'dev-tools'
196
- Requires-Dist: traceroot==0.0.4a4; extra == 'dev-tools'
196
+ Requires-Dist: traceroot==0.0.4a5; extra == 'dev-tools'
197
197
  Requires-Dist: tree-sitter-python<0.24,>=0.23.6; extra == 'dev-tools'
198
198
  Requires-Dist: tree-sitter<0.24,>=0.23.2; extra == 'dev-tools'
199
199
  Requires-Dist: typer>=0.15.2; extra == 'dev-tools'
@@ -1,4 +1,4 @@
1
- camel/__init__.py,sha256=LTkqY9-7B4fjQ79FR9WNMAnmrvxJWu3XOfTRTpz2fcU,901
1
+ camel/__init__.py,sha256=wTOL4fY0oWlHviwCNl_t2MQqROlrDeuKQRCvElto5kw,901
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
@@ -317,7 +317,7 @@ camel/terminators/__init__.py,sha256=t8uqrkUnXEOYMXQDgaBkMFJ0EXFKI0kmx4cUimli3Ls
317
317
  camel/terminators/base.py,sha256=xmJzERX7GdSXcxZjAHHODa0rOxRChMSRboDCNHWSscs,1511
318
318
  camel/terminators/response_terminator.py,sha256=n3G5KP6Oj7-7WlRN0yFcrtLpqAJKaKS0bmhrWlFfCgQ,4982
319
319
  camel/terminators/token_limit_terminator.py,sha256=YWv6ZR8R9yI2Qnf_3xES5bEE_O5bb2CxQ0EUXfMh34c,2118
320
- camel/toolkits/__init__.py,sha256=ywXaXZJD8a3lyjNVV6ntVCpBYvgbSMK3N5ULJet-xKw,6013
320
+ camel/toolkits/__init__.py,sha256=ug0QbctUQWLUfVI4fSufMyqvorttPYDKy3cI33-v9Ho,6086
321
321
  camel/toolkits/aci_toolkit.py,sha256=39AsXloBb16hHB7DKi6mFU6NPZ3iVpM2FZgaP4o4eLE,16060
322
322
  camel/toolkits/arxiv_toolkit.py,sha256=mw629nIN_ozaAxNv3nbvhonJKNI2-97ScRCBS3gVqNo,6297
323
323
  camel/toolkits/ask_news_toolkit.py,sha256=WfWaqwEo1Apbil3-Rb5y65Ws43NU4rAFWZu5VHe4los,23448
@@ -355,6 +355,7 @@ camel/toolkits/message_integration.py,sha256=WdcoVoDAPwlvfXK26wHBf2q_IQCH4PQ_gJt
355
355
  camel/toolkits/mineru_toolkit.py,sha256=vRX9LholLNkpbJ6axfEN4pTG85aWb0PDmlVy3rAAXhg,6868
356
356
  camel/toolkits/networkx_toolkit.py,sha256=C7pUCZTzzGkFyqdkrmhRKpAHmHWfLKeuzYHC_BHPtbk,8826
357
357
  camel/toolkits/note_taking_toolkit.py,sha256=cp7uoSBMjiGy331Tdk2Bl6yqKSMGwws7rQJkq8tfTQs,10687
358
+ camel/toolkits/notion_mcp_toolkit.py,sha256=ie_6Z-7DqDhgTiwYX8L3X47rfWGwzgwQH_s2DaK1ckc,8362
358
359
  camel/toolkits/notion_toolkit.py,sha256=jmmVWk_WazRNWnx4r9DAvhFTAL-n_ige0tb32UHJ_ik,9752
359
360
  camel/toolkits/open_api_toolkit.py,sha256=Venfq8JwTMQfzRzzB7AYmYUMEX35hW0BjIv_ozFMiNk,23316
360
361
  camel/toolkits/openai_agent_toolkit.py,sha256=hT2ancdQigngAiY1LNnGJzZeiBDHUxrRGv6BdZTJizc,4696
@@ -389,14 +390,14 @@ camel/toolkits/wolfram_alpha_toolkit.py,sha256=qeIM8ySn5ilcExBWtx-hDOc35bNcebLVn
389
390
  camel/toolkits/zapier_toolkit.py,sha256=A83y1UcfuopH7Fx82pORzypl1StbhBjB2HhyOqYa300,7124
390
391
  camel/toolkits/hybrid_browser_toolkit/__init__.py,sha256=vxjWhq7GjUKE5I9RGQU_GoikZJ-AVK4ertdvEqp9pd0,802
391
392
  camel/toolkits/hybrid_browser_toolkit/config_loader.py,sha256=UwBh7wG4-owoI2VfiNMum0O7dPWMYiEDxQKtq_GazU4,6903
392
- camel/toolkits/hybrid_browser_toolkit/hybrid_browser_toolkit.py,sha256=riORnWhjhqdzYNNKEwANHVxf8WgpIMYK6q7pS7qsav0,45270
393
+ camel/toolkits/hybrid_browser_toolkit/hybrid_browser_toolkit.py,sha256=8ArSGFCx1bIrZR8cdRVUX6axy5Fxgk5ADEgiSrPQ_Bo,45269
393
394
  camel/toolkits/hybrid_browser_toolkit/ws_wrapper.py,sha256=5wssGj2LvREtyl91lC5pTIb0G7DZlFvLT_Pn-7XPESY,18460
394
395
  camel/toolkits/hybrid_browser_toolkit/ts/package-lock.json,sha256=_-YE9S_C1XT59A6upQp9lLuZcC67cV9QlbwAsEKkfyw,156337
395
396
  camel/toolkits/hybrid_browser_toolkit/ts/package.json,sha256=pUQm0xwXR7ZyWNv6O2QtHW00agnfAoX9F_XGXZlAxl4,745
396
397
  camel/toolkits/hybrid_browser_toolkit/ts/tsconfig.json,sha256=SwpQnq4Q-rwRobF2iWrP96mgmgwaVPZEv-nii5QIYEU,523
397
398
  camel/toolkits/hybrid_browser_toolkit/ts/websocket-server.js,sha256=mLjufus1_ugzRtWMTMQmn5xqsph-RNW55jkWrXbGxrg,6752
398
399
  camel/toolkits/hybrid_browser_toolkit/ts/src/browser-scripts.js,sha256=NNwM_H2xaDrlrdac0PJK1iUBwdiuQsg9qKaMhHAvZuI,3160
399
- camel/toolkits/hybrid_browser_toolkit/ts/src/browser-session.ts,sha256=NNjStas8xzOONI1yJIMkeQeSYGZHPRK19ksEu665hwo,31711
400
+ camel/toolkits/hybrid_browser_toolkit/ts/src/browser-session.ts,sha256=csJ6yelay5r0QULBzWybakO3IB7dQ5QpbrSdCxLlrwE,33165
400
401
  camel/toolkits/hybrid_browser_toolkit/ts/src/config-loader.ts,sha256=jYsu9qFuwpFIS5y8rQ5R6aX_HDlDEh2YsvFH6CQLhmg,6181
401
402
  camel/toolkits/hybrid_browser_toolkit/ts/src/hybrid-browser-toolkit.ts,sha256=VLhaKGQ2rz9OMRTluQ4h9kC0MMJz6-y29WxR-DQEu-c,16551
402
403
  camel/toolkits/hybrid_browser_toolkit/ts/src/index.ts,sha256=uJGHmGs640iCrjllqXDXwDE4hGW1VJA2YL6BkFkzYNs,353
@@ -456,7 +457,7 @@ camel/verifiers/math_verifier.py,sha256=tA1D4S0sm8nsWISevxSN0hvSVtIUpqmJhzqfbuMo
456
457
  camel/verifiers/models.py,sha256=GdxYPr7UxNrR1577yW4kyroRcLGfd-H1GXgv8potDWU,2471
457
458
  camel/verifiers/physics_verifier.py,sha256=c1grrRddcrVN7szkxhv2QirwY9viIRSITWeWFF5HmLs,30187
458
459
  camel/verifiers/python_verifier.py,sha256=ogTz77wODfEcDN4tMVtiSkRQyoiZbHPY2fKybn59lHw,20558
459
- camel_ai-0.2.73a0.dist-info/METADATA,sha256=Xl3A8teMGBqoMuxICxwUID9PodwgAwsuCvAE_kkgwjE,50334
460
- camel_ai-0.2.73a0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
461
- camel_ai-0.2.73a0.dist-info/licenses/LICENSE,sha256=id0nB2my5kG0xXeimIu5zZrbHLS6EQvxvkKkzIHaT2k,11343
462
- camel_ai-0.2.73a0.dist-info/RECORD,,
460
+ camel_ai-0.2.73a1.dist-info/METADATA,sha256=fyFGeV9znnEsiURZU0Za6FeAkyzm6_hqzk-GLa53aOQ,50334
461
+ camel_ai-0.2.73a1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
462
+ camel_ai-0.2.73a1.dist-info/licenses/LICENSE,sha256=id0nB2my5kG0xXeimIu5zZrbHLS6EQvxvkKkzIHaT2k,11343
463
+ camel_ai-0.2.73a1.dist-info/RECORD,,