camel-ai 0.2.73a6__py3-none-any.whl → 0.2.73a9__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of camel-ai might be problematic. Click here for more details.
- camel/__init__.py +1 -1
- camel/societies/__init__.py +2 -0
- camel/storages/key_value_storages/mem0_cloud.py +47 -46
- camel/toolkits/file_write_toolkit.py +67 -0
- camel/toolkits/mcp_toolkit.py +341 -46
- camel/toolkits/terminal_toolkit.py +201 -20
- camel/types/enums.py +6 -0
- {camel_ai-0.2.73a6.dist-info → camel_ai-0.2.73a9.dist-info}/METADATA +1 -1
- {camel_ai-0.2.73a6.dist-info → camel_ai-0.2.73a9.dist-info}/RECORD +11 -11
- {camel_ai-0.2.73a6.dist-info → camel_ai-0.2.73a9.dist-info}/WHEEL +0 -0
- {camel_ai-0.2.73a6.dist-info → camel_ai-0.2.73a9.dist-info}/licenses/LICENSE +0 -0
camel/__init__.py
CHANGED
camel/societies/__init__.py
CHANGED
|
@@ -13,8 +13,10 @@
|
|
|
13
13
|
# ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========
|
|
14
14
|
from .babyagi_playing import BabyAGI
|
|
15
15
|
from .role_playing import RolePlaying
|
|
16
|
+
from .workforce import Workforce
|
|
16
17
|
|
|
17
18
|
__all__ = [
|
|
18
19
|
'RolePlaying',
|
|
19
20
|
'BabyAGI',
|
|
21
|
+
'Workforce',
|
|
20
22
|
]
|
|
@@ -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]],
|
|
@@ -168,7 +140,6 @@ class Mem0Storage(BaseKeyValueStorage):
|
|
|
168
140
|
self.client.add(messages, **options)
|
|
169
141
|
except Exception as e:
|
|
170
142
|
logger.error(f"Error adding memory: {e}")
|
|
171
|
-
logger.error(f"Error: {e}")
|
|
172
143
|
|
|
173
144
|
def load(self) -> List[Dict[str, Any]]:
|
|
174
145
|
r"""Loads all stored records from the Mem0 storage system.
|
|
@@ -178,11 +149,18 @@ class Mem0Storage(BaseKeyValueStorage):
|
|
|
178
149
|
represents a stored record.
|
|
179
150
|
"""
|
|
180
151
|
try:
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
152
|
+
# Build kwargs for get_all
|
|
153
|
+
kwargs = {}
|
|
154
|
+
if self.agent_id:
|
|
155
|
+
kwargs['agent_id'] = self.agent_id
|
|
156
|
+
if self.user_id:
|
|
157
|
+
kwargs['user_id'] = self.user_id
|
|
158
|
+
|
|
159
|
+
# If no filters available, return empty list
|
|
160
|
+
if not kwargs:
|
|
161
|
+
return []
|
|
162
|
+
|
|
163
|
+
results = self.client.get_all(**kwargs)
|
|
186
164
|
|
|
187
165
|
# Transform results into MemoryRecord objects
|
|
188
166
|
transformed_results = []
|
|
@@ -190,35 +168,58 @@ class Mem0Storage(BaseKeyValueStorage):
|
|
|
190
168
|
memory_record = MemoryRecord(
|
|
191
169
|
uuid=UUID(result["id"]),
|
|
192
170
|
message=BaseMessage(
|
|
193
|
-
role_name="
|
|
171
|
+
role_name="memory",
|
|
194
172
|
role_type=RoleType.USER,
|
|
195
|
-
meta_dict={},
|
|
173
|
+
meta_dict=result.get("metadata", {}),
|
|
196
174
|
content=result["memory"],
|
|
197
175
|
),
|
|
198
176
|
role_at_backend=OpenAIBackendRole.USER,
|
|
199
177
|
extra_info=result.get("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
|
|
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
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
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}")
|
|
@@ -840,6 +840,69 @@ class FileWriteToolkit(BaseToolkit):
|
|
|
840
840
|
|
|
841
841
|
return text
|
|
842
842
|
|
|
843
|
+
def _ensure_html_utf8_meta(self, content: str) -> str:
|
|
844
|
+
r"""Ensure HTML content has UTF-8 meta tag.
|
|
845
|
+
|
|
846
|
+
Args:
|
|
847
|
+
content (str): The HTML content.
|
|
848
|
+
|
|
849
|
+
Returns:
|
|
850
|
+
str: HTML content with UTF-8 meta tag.
|
|
851
|
+
"""
|
|
852
|
+
# Check if content already has a charset meta tag
|
|
853
|
+
has_charset = re.search(
|
|
854
|
+
r'<meta[^>]*charset[^>]*>', content, re.IGNORECASE
|
|
855
|
+
)
|
|
856
|
+
|
|
857
|
+
# UTF-8 meta tag
|
|
858
|
+
utf8_meta = '<meta charset="utf-8">'
|
|
859
|
+
|
|
860
|
+
if has_charset:
|
|
861
|
+
# Replace existing charset with UTF-8
|
|
862
|
+
content = re.sub(
|
|
863
|
+
r'<meta[^>]*charset[^>]*>',
|
|
864
|
+
utf8_meta,
|
|
865
|
+
content,
|
|
866
|
+
flags=re.IGNORECASE,
|
|
867
|
+
)
|
|
868
|
+
else:
|
|
869
|
+
# Add UTF-8 meta tag
|
|
870
|
+
# Try to find <head> tag
|
|
871
|
+
head_match = re.search(r'<head[^>]*>', content, re.IGNORECASE)
|
|
872
|
+
if head_match:
|
|
873
|
+
# Insert after <head> tag
|
|
874
|
+
insert_pos = head_match.end()
|
|
875
|
+
content = (
|
|
876
|
+
content[:insert_pos]
|
|
877
|
+
+ '\n '
|
|
878
|
+
+ utf8_meta
|
|
879
|
+
+ content[insert_pos:]
|
|
880
|
+
)
|
|
881
|
+
else:
|
|
882
|
+
# No <head> tag found, check if there's <html> tag
|
|
883
|
+
html_match = re.search(r'<html[^>]*>', content, re.IGNORECASE)
|
|
884
|
+
if html_match:
|
|
885
|
+
# Insert <head> with meta tag after <html>
|
|
886
|
+
insert_pos = html_match.end()
|
|
887
|
+
content = (
|
|
888
|
+
content[:insert_pos]
|
|
889
|
+
+ '\n<head>\n '
|
|
890
|
+
+ utf8_meta
|
|
891
|
+
+ '\n</head>'
|
|
892
|
+
+ content[insert_pos:]
|
|
893
|
+
)
|
|
894
|
+
else:
|
|
895
|
+
# No proper HTML structure, wrap content
|
|
896
|
+
content = (
|
|
897
|
+
'<!DOCTYPE html>\n<html>\n<head>\n '
|
|
898
|
+
+ utf8_meta
|
|
899
|
+
+ '\n</head>\n<body>\n'
|
|
900
|
+
+ content
|
|
901
|
+
+ '\n</body>\n</html>'
|
|
902
|
+
)
|
|
903
|
+
|
|
904
|
+
return content
|
|
905
|
+
|
|
843
906
|
def _write_csv_file(
|
|
844
907
|
self,
|
|
845
908
|
file_path: Path,
|
|
@@ -901,6 +964,10 @@ class FileWriteToolkit(BaseToolkit):
|
|
|
901
964
|
content (str): The content to write.
|
|
902
965
|
encoding (str): Character encoding to use. (default: :obj:`utf-8`)
|
|
903
966
|
"""
|
|
967
|
+
# For HTML files, ensure UTF-8 meta tag is present
|
|
968
|
+
if file_path.suffix.lower() in ['.html', '.htm']:
|
|
969
|
+
content = self._ensure_html_utf8_meta(content)
|
|
970
|
+
|
|
904
971
|
with file_path.open("w", encoding=encoding) as f:
|
|
905
972
|
f.write(content)
|
|
906
973
|
|
camel/toolkits/mcp_toolkit.py
CHANGED
|
@@ -14,6 +14,7 @@
|
|
|
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
|
|
|
@@ -24,6 +25,11 @@ from camel.utils.mcp_client import MCPClient, create_mcp_client
|
|
|
24
25
|
|
|
25
26
|
logger = get_logger(__name__)
|
|
26
27
|
|
|
28
|
+
# Suppress parameter description warnings for MCP tools
|
|
29
|
+
warnings.filterwarnings(
|
|
30
|
+
"ignore", message="Parameter description is missing", category=UserWarning
|
|
31
|
+
)
|
|
32
|
+
|
|
27
33
|
|
|
28
34
|
class MCPConnectionError(Exception):
|
|
29
35
|
r"""Raised when MCP connection fails."""
|
|
@@ -446,7 +452,7 @@ class MCPToolkit(BaseToolkit):
|
|
|
446
452
|
|
|
447
453
|
def _ensure_strict_tool_schema(self, tool: FunctionTool) -> FunctionTool:
|
|
448
454
|
r"""Ensure a tool has a strict schema compatible with OpenAI's
|
|
449
|
-
requirements.
|
|
455
|
+
requirements according to the structured outputs specification.
|
|
450
456
|
|
|
451
457
|
Args:
|
|
452
458
|
tool (FunctionTool): The tool to check and update if necessary.
|
|
@@ -457,60 +463,333 @@ class MCPToolkit(BaseToolkit):
|
|
|
457
463
|
try:
|
|
458
464
|
schema = tool.get_openai_tool_schema()
|
|
459
465
|
|
|
460
|
-
#
|
|
461
|
-
def
|
|
462
|
-
r"""Recursively
|
|
466
|
+
# Helper functions for validation and transformation
|
|
467
|
+
def _validate_and_fix_schema(obj, path="", in_root=True):
|
|
468
|
+
r"""Recursively validate and fix schema to meet strict
|
|
469
|
+
requirements.
|
|
470
|
+
"""
|
|
463
471
|
if isinstance(obj, dict):
|
|
464
|
-
if
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
if
|
|
468
|
-
|
|
472
|
+
# Check if this is the root object
|
|
473
|
+
if in_root and path == "":
|
|
474
|
+
# Root must be an object, not anyOf
|
|
475
|
+
if "anyOf" in obj and "type" not in obj:
|
|
476
|
+
raise ValueError(
|
|
477
|
+
"Root object must not be anyOf and must "
|
|
478
|
+
"be an object"
|
|
479
|
+
)
|
|
480
|
+
if obj.get("type") and obj["type"] != "object":
|
|
481
|
+
raise ValueError(
|
|
482
|
+
"Root object must have type 'object'"
|
|
483
|
+
)
|
|
484
|
+
|
|
485
|
+
# Handle object types
|
|
486
|
+
if obj.get("type") == "object":
|
|
487
|
+
# Ensure additionalProperties is false
|
|
488
|
+
obj["additionalProperties"] = False
|
|
489
|
+
|
|
490
|
+
# Process properties
|
|
491
|
+
if "properties" in obj:
|
|
492
|
+
props = obj["properties"]
|
|
493
|
+
# Only set required if it doesn't exist or needs
|
|
494
|
+
# updating
|
|
495
|
+
if "required" not in obj:
|
|
496
|
+
# If no required field exists, make all fields
|
|
497
|
+
# required
|
|
498
|
+
obj["required"] = list(props.keys())
|
|
499
|
+
else:
|
|
500
|
+
# Ensure required field only contains valid
|
|
501
|
+
# property names
|
|
502
|
+
existing_required = obj.get("required", [])
|
|
503
|
+
valid_required = [
|
|
504
|
+
req
|
|
505
|
+
for req in existing_required
|
|
506
|
+
if req in props
|
|
507
|
+
]
|
|
508
|
+
# Add any missing properties to required
|
|
509
|
+
for prop_name in props:
|
|
510
|
+
if prop_name not in valid_required:
|
|
511
|
+
valid_required.append(prop_name)
|
|
512
|
+
obj["required"] = valid_required
|
|
513
|
+
|
|
514
|
+
# Recursively process each property
|
|
515
|
+
for prop_name, prop_schema in props.items():
|
|
516
|
+
_validate_and_fix_schema(
|
|
517
|
+
prop_schema, f"{path}.{prop_name}", False
|
|
518
|
+
)
|
|
519
|
+
|
|
520
|
+
# Handle arrays
|
|
521
|
+
elif obj.get("type") == "array":
|
|
522
|
+
if "items" in obj:
|
|
523
|
+
_validate_and_fix_schema(
|
|
524
|
+
obj["items"], f"{path}.items", False
|
|
525
|
+
)
|
|
526
|
+
|
|
527
|
+
# Handle anyOf
|
|
528
|
+
elif "anyOf" in obj:
|
|
529
|
+
# Validate anyOf schemas
|
|
530
|
+
for i, schema in enumerate(obj["anyOf"]):
|
|
531
|
+
_validate_and_fix_schema(
|
|
532
|
+
schema, f"{path}.anyOf[{i}]", False
|
|
533
|
+
)
|
|
534
|
+
|
|
535
|
+
# Handle string format validation
|
|
536
|
+
elif obj.get("type") == "string":
|
|
537
|
+
if "format" in obj:
|
|
538
|
+
allowed_formats = [
|
|
539
|
+
"date-time",
|
|
540
|
+
"time",
|
|
541
|
+
"date",
|
|
542
|
+
"duration",
|
|
543
|
+
"email",
|
|
544
|
+
"hostname",
|
|
545
|
+
"ipv4",
|
|
546
|
+
"ipv6",
|
|
547
|
+
"uuid",
|
|
548
|
+
]
|
|
549
|
+
if obj["format"] not in allowed_formats:
|
|
550
|
+
del obj["format"] # Remove unsupported format
|
|
551
|
+
|
|
552
|
+
# Handle number/integer validation
|
|
553
|
+
elif obj.get("type") in ["number", "integer"]:
|
|
554
|
+
# These properties are supported
|
|
555
|
+
supported_props = [
|
|
556
|
+
"multipleOf",
|
|
557
|
+
"maximum",
|
|
558
|
+
"exclusiveMaximum",
|
|
559
|
+
"minimum",
|
|
560
|
+
"exclusiveMinimum",
|
|
561
|
+
]
|
|
562
|
+
# Remove any unsupported properties
|
|
563
|
+
for key in list(obj.keys()):
|
|
564
|
+
if key not in [
|
|
565
|
+
*supported_props,
|
|
566
|
+
"type",
|
|
567
|
+
"description",
|
|
568
|
+
"default",
|
|
569
|
+
]:
|
|
570
|
+
del obj[key]
|
|
571
|
+
|
|
572
|
+
# Process nested structures
|
|
573
|
+
for key in ["allOf", "oneOf", "$defs", "definitions"]:
|
|
574
|
+
if key in obj:
|
|
575
|
+
if isinstance(obj[key], list):
|
|
576
|
+
for i, item in enumerate(obj[key]):
|
|
577
|
+
_validate_and_fix_schema(
|
|
578
|
+
item, f"{path}.{key}[{i}]", False
|
|
579
|
+
)
|
|
580
|
+
elif isinstance(obj[key], dict):
|
|
581
|
+
for def_name, def_schema in obj[key].items():
|
|
582
|
+
_validate_and_fix_schema(
|
|
583
|
+
def_schema,
|
|
584
|
+
f"{path}.{key}.{def_name}",
|
|
585
|
+
False,
|
|
586
|
+
)
|
|
587
|
+
|
|
469
588
|
elif isinstance(obj, list):
|
|
470
|
-
for item in obj:
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
589
|
+
for i, item in enumerate(obj):
|
|
590
|
+
_validate_and_fix_schema(item, f"{path}[{i}]", False)
|
|
591
|
+
|
|
592
|
+
def _check_schema_limits(obj, counts=None):
|
|
593
|
+
r"""Check if schema exceeds OpenAI limits."""
|
|
594
|
+
if counts is None:
|
|
595
|
+
counts = {
|
|
596
|
+
"properties": 0,
|
|
597
|
+
"depth": 0,
|
|
598
|
+
"enums": 0,
|
|
599
|
+
"string_length": 0,
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
def _count_properties(o, depth=0):
|
|
603
|
+
if isinstance(o, dict):
|
|
604
|
+
if depth > 5:
|
|
605
|
+
raise ValueError(
|
|
606
|
+
"Schema exceeds maximum nesting depth of 5"
|
|
607
|
+
)
|
|
608
|
+
|
|
609
|
+
if o.get("type") == "object" and "properties" in o:
|
|
610
|
+
counts["properties"] += len(o["properties"])
|
|
611
|
+
for prop in o["properties"].values():
|
|
612
|
+
_count_properties(prop, depth + 1)
|
|
613
|
+
|
|
614
|
+
if "enum" in o:
|
|
615
|
+
counts["enums"] += len(o["enum"])
|
|
616
|
+
if isinstance(o["enum"], list):
|
|
617
|
+
for val in o["enum"]:
|
|
618
|
+
if isinstance(val, str):
|
|
619
|
+
counts["string_length"] += len(val)
|
|
620
|
+
|
|
621
|
+
# Count property names
|
|
622
|
+
if "properties" in o:
|
|
623
|
+
for name in o["properties"].keys():
|
|
624
|
+
counts["string_length"] += len(name)
|
|
625
|
+
|
|
626
|
+
# Process nested structures
|
|
627
|
+
for key in ["items", "allOf", "oneOf", "anyOf"]:
|
|
628
|
+
if key in o:
|
|
629
|
+
if isinstance(o[key], dict):
|
|
630
|
+
_count_properties(o[key], depth)
|
|
631
|
+
elif isinstance(o[key], list):
|
|
632
|
+
for item in o[key]:
|
|
633
|
+
_count_properties(item, depth)
|
|
634
|
+
|
|
635
|
+
_count_properties(obj)
|
|
636
|
+
|
|
637
|
+
# Check limits, reference: https://platform.openai.com/docs/guides/structured-outputs?api-mode=responses#objects-have-limitations-on-nesting-depth-and-size # noqa: E501
|
|
638
|
+
if counts["properties"] > 5000:
|
|
639
|
+
raise ValueError(
|
|
640
|
+
"Schema exceeds maximum of 5000 properties"
|
|
641
|
+
)
|
|
642
|
+
if counts["enums"] > 1000:
|
|
643
|
+
raise ValueError(
|
|
644
|
+
"Schema exceeds maximum of 1000 enum values"
|
|
645
|
+
)
|
|
646
|
+
if counts["string_length"] > 120000:
|
|
647
|
+
raise ValueError(
|
|
648
|
+
"Schema exceeds maximum total string length of 120000"
|
|
649
|
+
)
|
|
488
650
|
|
|
489
|
-
|
|
490
|
-
|
|
651
|
+
return True
|
|
652
|
+
|
|
653
|
+
# Check if schema has any issues that prevent strict mode
|
|
654
|
+
def _has_strict_mode_issues(obj):
|
|
655
|
+
r"""Check for any issues that would prevent strict mode."""
|
|
656
|
+
issues = []
|
|
657
|
+
|
|
658
|
+
def _check_issues(o, path=""):
|
|
659
|
+
if isinstance(o, dict):
|
|
660
|
+
# Check for additionalProperties: true
|
|
661
|
+
if o.get("additionalProperties") is True:
|
|
662
|
+
issues.append(
|
|
663
|
+
f"additionalProperties: true at {path}"
|
|
664
|
+
)
|
|
665
|
+
|
|
666
|
+
# Check for unsupported keywords
|
|
667
|
+
unsupported = [
|
|
668
|
+
"not",
|
|
669
|
+
"dependentRequired",
|
|
670
|
+
"dependentSchemas",
|
|
671
|
+
"if",
|
|
672
|
+
"then",
|
|
673
|
+
"else",
|
|
674
|
+
"patternProperties",
|
|
675
|
+
]
|
|
676
|
+
for keyword in unsupported:
|
|
677
|
+
if keyword in o:
|
|
678
|
+
issues.append(
|
|
679
|
+
f"Unsupported keyword '{keyword}' "
|
|
680
|
+
f"at {path}"
|
|
681
|
+
)
|
|
682
|
+
|
|
683
|
+
# Recursively check
|
|
684
|
+
for key, value in o.items():
|
|
685
|
+
if isinstance(value, (dict, list)):
|
|
686
|
+
_check_issues(value, f"{path}.{key}")
|
|
687
|
+
|
|
688
|
+
elif isinstance(o, list):
|
|
689
|
+
for i, item in enumerate(o):
|
|
690
|
+
_check_issues(item, f"{path}[{i}]")
|
|
691
|
+
|
|
692
|
+
_check_issues(obj)
|
|
693
|
+
return issues
|
|
694
|
+
|
|
695
|
+
# Check if already strict and compliant
|
|
491
696
|
if schema.get("function", {}).get("strict") is True:
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
697
|
+
# Validate it's actually compliant
|
|
698
|
+
try:
|
|
699
|
+
params = schema["function"].get("parameters", {})
|
|
700
|
+
if params:
|
|
701
|
+
_validate_and_fix_schema(params)
|
|
702
|
+
_check_schema_limits(params)
|
|
703
|
+
return tool
|
|
704
|
+
except Exception:
|
|
705
|
+
# Not actually compliant, continue to fix it
|
|
706
|
+
pass
|
|
707
|
+
|
|
708
|
+
# Apply sanitization first to handle optional fields properly
|
|
495
709
|
if "function" in schema:
|
|
710
|
+
# Apply the sanitization function first
|
|
711
|
+
from camel.toolkits.function_tool import (
|
|
712
|
+
sanitize_and_enforce_required,
|
|
713
|
+
)
|
|
714
|
+
|
|
715
|
+
schema = sanitize_and_enforce_required(schema)
|
|
716
|
+
|
|
717
|
+
# Special handling for schemas with additionalProperties that
|
|
718
|
+
# aren't false These can't use strict mode
|
|
719
|
+
def _has_open_props(obj, path=""):
|
|
720
|
+
"""Check if any object has additionalProperties that
|
|
721
|
+
isn't false."""
|
|
722
|
+
if isinstance(obj, dict):
|
|
723
|
+
if (
|
|
724
|
+
obj.get("type") == "object"
|
|
725
|
+
and "additionalProperties" in obj
|
|
726
|
+
):
|
|
727
|
+
if obj["additionalProperties"] is not False:
|
|
728
|
+
return True
|
|
729
|
+
|
|
730
|
+
# Recurse through the schema
|
|
731
|
+
for key, value in obj.items():
|
|
732
|
+
if key in [
|
|
733
|
+
"properties",
|
|
734
|
+
"items",
|
|
735
|
+
"allOf",
|
|
736
|
+
"oneOf",
|
|
737
|
+
"anyOf",
|
|
738
|
+
]:
|
|
739
|
+
if isinstance(value, dict):
|
|
740
|
+
if _has_open_props(value, f"{path}.{key}"):
|
|
741
|
+
return True
|
|
742
|
+
elif isinstance(value, list):
|
|
743
|
+
for i, item in enumerate(value):
|
|
744
|
+
if _has_open_props(
|
|
745
|
+
item,
|
|
746
|
+
f"{path}.{key}[{i}]",
|
|
747
|
+
):
|
|
748
|
+
return True
|
|
749
|
+
elif isinstance(value, dict) and key not in [
|
|
750
|
+
"description",
|
|
751
|
+
"type",
|
|
752
|
+
"enum",
|
|
753
|
+
]:
|
|
754
|
+
if _has_open_props(value, f"{path}.{key}"):
|
|
755
|
+
return True
|
|
756
|
+
return False
|
|
757
|
+
|
|
758
|
+
# Check if schema has dynamic additionalProperties
|
|
759
|
+
if _has_open_props(schema["function"].get("parameters", {})):
|
|
760
|
+
# Can't use strict mode with dynamic additionalProperties
|
|
761
|
+
schema["function"]["strict"] = False
|
|
762
|
+
tool.set_openai_tool_schema(schema)
|
|
763
|
+
logger.warning(
|
|
764
|
+
f"Tool '{tool.get_function_name()}' has "
|
|
765
|
+
f"dynamic additionalProperties and cannot use "
|
|
766
|
+
f"strict mode"
|
|
767
|
+
)
|
|
768
|
+
return tool
|
|
769
|
+
|
|
770
|
+
# Now check for blocking issues after sanitization
|
|
771
|
+
issues = _has_strict_mode_issues(schema)
|
|
772
|
+
if issues:
|
|
773
|
+
# Can't use strict mode
|
|
774
|
+
schema["function"]["strict"] = False
|
|
775
|
+
tool.set_openai_tool_schema(schema)
|
|
776
|
+
logger.warning(
|
|
777
|
+
f"Tool '{tool.get_function_name()}' has "
|
|
778
|
+
f"issues preventing strict mode: "
|
|
779
|
+
f"{'; '.join(issues[:3])}{'...' if len(issues) > 3 else ''}" # noqa: E501
|
|
780
|
+
)
|
|
781
|
+
return tool
|
|
782
|
+
|
|
783
|
+
# Enable strict mode
|
|
496
784
|
schema["function"]["strict"] = True
|
|
497
785
|
|
|
498
|
-
# Ensure parameters have proper strict mode configuration
|
|
499
786
|
parameters = schema["function"].get("parameters", {})
|
|
500
787
|
if parameters:
|
|
501
|
-
#
|
|
502
|
-
parameters
|
|
503
|
-
|
|
504
|
-
# Process properties to handle optional fields
|
|
505
|
-
properties = parameters.get("properties", {})
|
|
506
|
-
parameters["required"] = list(properties.keys())
|
|
507
|
-
|
|
508
|
-
# Apply the sanitization function from function_tool
|
|
509
|
-
from camel.toolkits.function_tool import (
|
|
510
|
-
sanitize_and_enforce_required,
|
|
511
|
-
)
|
|
788
|
+
# Validate and fix the parameters schema
|
|
789
|
+
_validate_and_fix_schema(parameters)
|
|
512
790
|
|
|
513
|
-
|
|
791
|
+
# Check schema limits
|
|
792
|
+
_check_schema_limits(parameters)
|
|
514
793
|
|
|
515
794
|
tool.set_openai_tool_schema(schema)
|
|
516
795
|
logger.debug(
|
|
@@ -518,7 +797,23 @@ class MCPToolkit(BaseToolkit):
|
|
|
518
797
|
)
|
|
519
798
|
|
|
520
799
|
except Exception as e:
|
|
521
|
-
|
|
800
|
+
# If we can't make it strict, disable strict mode
|
|
801
|
+
try:
|
|
802
|
+
if "function" in schema:
|
|
803
|
+
schema["function"]["strict"] = False
|
|
804
|
+
tool.set_openai_tool_schema(schema)
|
|
805
|
+
logger.warning(
|
|
806
|
+
f"Failed to ensure strict schema for "
|
|
807
|
+
f"tool '{tool.get_function_name()}': {str(e)[:100]}. "
|
|
808
|
+
f"Setting strict=False."
|
|
809
|
+
)
|
|
810
|
+
except Exception as inner_e:
|
|
811
|
+
# If even setting strict=False fails, log the error
|
|
812
|
+
logger.error(
|
|
813
|
+
f"Critical error processing "
|
|
814
|
+
f"tool '{tool.get_function_name()}': {inner_e}. "
|
|
815
|
+
f"Tool may not function correctly."
|
|
816
|
+
)
|
|
522
817
|
|
|
523
818
|
return tool
|
|
524
819
|
|
|
@@ -98,6 +98,7 @@ class TerminalToolkit(BaseToolkit):
|
|
|
98
98
|
self.is_macos = platform.system() == 'Darwin'
|
|
99
99
|
self.initial_env_path: Optional[str] = None
|
|
100
100
|
self.initial_env_prepared = False
|
|
101
|
+
self.uv_path: Optional[str] = None
|
|
101
102
|
|
|
102
103
|
atexit.register(self.__del__)
|
|
103
104
|
|
|
@@ -200,37 +201,111 @@ class TerminalToolkit(BaseToolkit):
|
|
|
200
201
|
f"Creating new Python environment at: {self.cloned_env_path}\n"
|
|
201
202
|
)
|
|
202
203
|
|
|
203
|
-
#
|
|
204
|
-
|
|
204
|
+
# Try to use uv if available
|
|
205
|
+
if self._ensure_uv_available():
|
|
206
|
+
# Use uv to create environment with current Python version
|
|
207
|
+
uv_command = self.uv_path if self.uv_path else "uv"
|
|
205
208
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
self.cloned_env_path, "Scripts", "python.exe"
|
|
209
|
+
# Get current Python version
|
|
210
|
+
current_version = (
|
|
211
|
+
f"{sys.version_info.major}.{sys.version_info.minor}"
|
|
210
212
|
)
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
213
|
+
|
|
214
|
+
subprocess.run(
|
|
215
|
+
[
|
|
216
|
+
uv_command,
|
|
217
|
+
"venv",
|
|
218
|
+
"--python",
|
|
219
|
+
current_version,
|
|
220
|
+
self.cloned_env_path,
|
|
221
|
+
],
|
|
222
|
+
check=True,
|
|
223
|
+
capture_output=True,
|
|
224
|
+
cwd=self.working_dir,
|
|
225
|
+
timeout=300,
|
|
214
226
|
)
|
|
215
227
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
228
|
+
# Get the python path from the new environment
|
|
229
|
+
if self.os_type == 'Windows':
|
|
230
|
+
python_path = os.path.join(
|
|
231
|
+
self.cloned_env_path, "Scripts", "python.exe"
|
|
232
|
+
)
|
|
233
|
+
else:
|
|
234
|
+
python_path = os.path.join(
|
|
235
|
+
self.cloned_env_path, "bin", "python"
|
|
236
|
+
)
|
|
237
|
+
|
|
238
|
+
# Install pip and setuptools using uv
|
|
219
239
|
subprocess.run(
|
|
220
|
-
[
|
|
240
|
+
[
|
|
241
|
+
uv_command,
|
|
242
|
+
"pip",
|
|
243
|
+
"install",
|
|
244
|
+
"--python",
|
|
245
|
+
python_path,
|
|
246
|
+
"pip",
|
|
247
|
+
"setuptools",
|
|
248
|
+
"wheel",
|
|
249
|
+
],
|
|
221
250
|
check=True,
|
|
222
251
|
capture_output=True,
|
|
223
252
|
cwd=self.working_dir,
|
|
224
|
-
timeout=
|
|
253
|
+
timeout=300,
|
|
225
254
|
)
|
|
255
|
+
|
|
226
256
|
self._update_terminal_output(
|
|
227
|
-
"
|
|
257
|
+
"[UV] Cloned Python environment created successfully!\n"
|
|
228
258
|
)
|
|
259
|
+
|
|
229
260
|
else:
|
|
261
|
+
# Fallback to standard venv
|
|
230
262
|
self._update_terminal_output(
|
|
231
|
-
|
|
263
|
+
"Falling back to standard venv for cloning environment\n"
|
|
232
264
|
)
|
|
233
265
|
|
|
266
|
+
# Create virtual environment with pip. On macOS, use
|
|
267
|
+
# symlinks=False to avoid dyld library loading issues
|
|
268
|
+
venv.create(
|
|
269
|
+
self.cloned_env_path, with_pip=True, symlinks=False
|
|
270
|
+
)
|
|
271
|
+
|
|
272
|
+
# Ensure pip is properly available by upgrading it
|
|
273
|
+
if self.os_type == 'Windows':
|
|
274
|
+
python_path = os.path.join(
|
|
275
|
+
self.cloned_env_path, "Scripts", "python.exe"
|
|
276
|
+
)
|
|
277
|
+
else:
|
|
278
|
+
python_path = os.path.join(
|
|
279
|
+
self.cloned_env_path, "bin", "python"
|
|
280
|
+
)
|
|
281
|
+
|
|
282
|
+
# Verify python executable exists
|
|
283
|
+
if os.path.exists(python_path):
|
|
284
|
+
# Use python -m pip to ensure pip is available
|
|
285
|
+
subprocess.run(
|
|
286
|
+
[
|
|
287
|
+
python_path,
|
|
288
|
+
"-m",
|
|
289
|
+
"pip",
|
|
290
|
+
"install",
|
|
291
|
+
"--upgrade",
|
|
292
|
+
"pip",
|
|
293
|
+
],
|
|
294
|
+
check=True,
|
|
295
|
+
capture_output=True,
|
|
296
|
+
cwd=self.working_dir,
|
|
297
|
+
timeout=60,
|
|
298
|
+
)
|
|
299
|
+
self._update_terminal_output(
|
|
300
|
+
"New Python environment created successfully "
|
|
301
|
+
"with pip!\n"
|
|
302
|
+
)
|
|
303
|
+
else:
|
|
304
|
+
self._update_terminal_output(
|
|
305
|
+
f"Warning: Python executable not found "
|
|
306
|
+
f"at {python_path}\n"
|
|
307
|
+
)
|
|
308
|
+
|
|
234
309
|
except subprocess.CalledProcessError as e:
|
|
235
310
|
error_msg = e.stderr.decode() if e.stderr else str(e)
|
|
236
311
|
self._update_terminal_output(
|
|
@@ -255,6 +330,97 @@ class TerminalToolkit(BaseToolkit):
|
|
|
255
330
|
or shutil.which("uv") is not None
|
|
256
331
|
)
|
|
257
332
|
|
|
333
|
+
def _ensure_uv_available(self) -> bool:
|
|
334
|
+
r"""Ensure uv is available, installing it if necessary.
|
|
335
|
+
|
|
336
|
+
Returns:
|
|
337
|
+
bool: True if uv is available (either already installed or
|
|
338
|
+
successfully installed), False otherwise.
|
|
339
|
+
"""
|
|
340
|
+
# Check if uv is already available
|
|
341
|
+
existing_uv = shutil.which("uv")
|
|
342
|
+
if existing_uv is not None:
|
|
343
|
+
self.uv_path = existing_uv
|
|
344
|
+
self._update_terminal_output(
|
|
345
|
+
f"uv is already available at: {self.uv_path}\n"
|
|
346
|
+
)
|
|
347
|
+
return True
|
|
348
|
+
|
|
349
|
+
try:
|
|
350
|
+
self._update_terminal_output("uv not found, installing...\n")
|
|
351
|
+
|
|
352
|
+
# Install uv using the official installer script
|
|
353
|
+
if self.os_type in ['Darwin', 'Linux']:
|
|
354
|
+
# Use curl to download and execute the installer
|
|
355
|
+
install_cmd = "curl -LsSf https://astral.sh/uv/install.sh | sh"
|
|
356
|
+
result = subprocess.run(
|
|
357
|
+
install_cmd,
|
|
358
|
+
shell=True,
|
|
359
|
+
capture_output=True,
|
|
360
|
+
text=True,
|
|
361
|
+
timeout=60,
|
|
362
|
+
)
|
|
363
|
+
|
|
364
|
+
if result.returncode != 0:
|
|
365
|
+
self._update_terminal_output(
|
|
366
|
+
f"Failed to install uv: {result.stderr}\n"
|
|
367
|
+
)
|
|
368
|
+
return False
|
|
369
|
+
|
|
370
|
+
# Check if uv was installed in the expected location
|
|
371
|
+
home = os.path.expanduser("~")
|
|
372
|
+
uv_bin_path = os.path.join(home, ".cargo", "bin")
|
|
373
|
+
uv_executable = os.path.join(uv_bin_path, "uv")
|
|
374
|
+
|
|
375
|
+
if os.path.exists(uv_executable):
|
|
376
|
+
# Store the full path to uv instead of modifying PATH
|
|
377
|
+
self.uv_path = uv_executable
|
|
378
|
+
self._update_terminal_output(
|
|
379
|
+
f"uv installed successfully at: {self.uv_path}\n"
|
|
380
|
+
)
|
|
381
|
+
return True
|
|
382
|
+
|
|
383
|
+
elif self.os_type == 'Windows':
|
|
384
|
+
# Use PowerShell to install uv on Windows
|
|
385
|
+
install_cmd = (
|
|
386
|
+
"powershell -ExecutionPolicy Bypass -c "
|
|
387
|
+
"\"irm https://astral.sh/uv/install.ps1 | iex\""
|
|
388
|
+
)
|
|
389
|
+
result = subprocess.run(
|
|
390
|
+
install_cmd,
|
|
391
|
+
shell=True,
|
|
392
|
+
capture_output=True,
|
|
393
|
+
text=True,
|
|
394
|
+
timeout=60,
|
|
395
|
+
)
|
|
396
|
+
|
|
397
|
+
if result.returncode != 0:
|
|
398
|
+
self._update_terminal_output(
|
|
399
|
+
f"Failed to install uv: {result.stderr}\n"
|
|
400
|
+
)
|
|
401
|
+
return False
|
|
402
|
+
|
|
403
|
+
# Check if uv was installed in the expected location on Windows
|
|
404
|
+
home = os.path.expanduser("~")
|
|
405
|
+
uv_bin_path = os.path.join(home, ".cargo", "bin")
|
|
406
|
+
uv_executable = os.path.join(uv_bin_path, "uv.exe")
|
|
407
|
+
|
|
408
|
+
if os.path.exists(uv_executable):
|
|
409
|
+
# Store the full path to uv instead of modifying PATH
|
|
410
|
+
self.uv_path = uv_executable
|
|
411
|
+
self._update_terminal_output(
|
|
412
|
+
f"uv installed successfully at: {self.uv_path}\n"
|
|
413
|
+
)
|
|
414
|
+
return True
|
|
415
|
+
|
|
416
|
+
self._update_terminal_output("Failed to verify uv installation\n")
|
|
417
|
+
return False
|
|
418
|
+
|
|
419
|
+
except Exception as e:
|
|
420
|
+
self._update_terminal_output(f"Error installing uv: {e!s}\n")
|
|
421
|
+
logger.error(f"Failed to install uv: {e}")
|
|
422
|
+
return False
|
|
423
|
+
|
|
258
424
|
def _prepare_initial_environment(self):
|
|
259
425
|
r"""Prepare initial environment with Python 3.10, pip, and other
|
|
260
426
|
essential tools.
|
|
@@ -279,10 +445,14 @@ class TerminalToolkit(BaseToolkit):
|
|
|
279
445
|
# Create the initial environment directory
|
|
280
446
|
os.makedirs(self.initial_env_path, exist_ok=True)
|
|
281
447
|
|
|
282
|
-
#
|
|
283
|
-
if self.
|
|
448
|
+
# Try to ensure uv is available and use it preferentially
|
|
449
|
+
if self._ensure_uv_available():
|
|
284
450
|
self._setup_initial_env_with_uv()
|
|
285
451
|
else:
|
|
452
|
+
# Fallback to venv if uv installation failed
|
|
453
|
+
self._update_terminal_output(
|
|
454
|
+
"Falling back to standard venv for environment setup\n"
|
|
455
|
+
)
|
|
286
456
|
self._setup_initial_env_with_venv()
|
|
287
457
|
|
|
288
458
|
self.initial_env_prepared = True
|
|
@@ -302,9 +472,18 @@ class TerminalToolkit(BaseToolkit):
|
|
|
302
472
|
raise Exception("Initial environment path not set")
|
|
303
473
|
|
|
304
474
|
try:
|
|
475
|
+
# Use the stored uv path if available, otherwise fall back to "uv"
|
|
476
|
+
uv_command = self.uv_path if self.uv_path else "uv"
|
|
477
|
+
|
|
305
478
|
# Create virtual environment with Python 3.10 using uv
|
|
306
479
|
subprocess.run(
|
|
307
|
-
[
|
|
480
|
+
[
|
|
481
|
+
uv_command,
|
|
482
|
+
"venv",
|
|
483
|
+
"--python",
|
|
484
|
+
"3.10",
|
|
485
|
+
self.initial_env_path,
|
|
486
|
+
],
|
|
308
487
|
check=True,
|
|
309
488
|
capture_output=True,
|
|
310
489
|
cwd=self.working_dir,
|
|
@@ -332,7 +511,7 @@ class TerminalToolkit(BaseToolkit):
|
|
|
332
511
|
]
|
|
333
512
|
subprocess.run(
|
|
334
513
|
[
|
|
335
|
-
|
|
514
|
+
uv_command,
|
|
336
515
|
"pip",
|
|
337
516
|
"install",
|
|
338
517
|
"--python",
|
|
@@ -366,10 +545,12 @@ class TerminalToolkit(BaseToolkit):
|
|
|
366
545
|
|
|
367
546
|
try:
|
|
368
547
|
# Create virtual environment with system Python
|
|
548
|
+
# On macOS, use symlinks=False to avoid dyld library loading issues
|
|
369
549
|
venv.create(
|
|
370
550
|
self.initial_env_path,
|
|
371
551
|
with_pip=True,
|
|
372
552
|
system_site_packages=False,
|
|
553
|
+
symlinks=False,
|
|
373
554
|
)
|
|
374
555
|
|
|
375
556
|
# Get pip path
|
camel/types/enums.py
CHANGED
|
@@ -245,6 +245,7 @@ class ModelType(UnifiedModelType, Enum):
|
|
|
245
245
|
QWEN_QWQ_32B = "qwq-32b-preview"
|
|
246
246
|
QWEN_QVQ_72B = "qvq-72b-preview"
|
|
247
247
|
QWEN_QWQ_PLUS = "qwq-plus"
|
|
248
|
+
QWEN_3_CODER_PLUS = "qwen3-coder-plus"
|
|
248
249
|
|
|
249
250
|
# Yi models (01-ai)
|
|
250
251
|
YI_LIGHTNING = "yi-lightning"
|
|
@@ -763,6 +764,7 @@ class ModelType(UnifiedModelType, Enum):
|
|
|
763
764
|
ModelType.QWEN_PLUS_2025_04_28,
|
|
764
765
|
ModelType.QWEN_TURBO_LATEST,
|
|
765
766
|
ModelType.QWEN_TURBO_2025_04_28,
|
|
767
|
+
ModelType.QWEN_3_CODER_PLUS,
|
|
766
768
|
}
|
|
767
769
|
|
|
768
770
|
@property
|
|
@@ -1306,6 +1308,10 @@ class ModelType(UnifiedModelType, Enum):
|
|
|
1306
1308
|
ModelType.NOVITA_LLAMA_4_MAVERICK_17B,
|
|
1307
1309
|
}:
|
|
1308
1310
|
return 1_048_576
|
|
1311
|
+
elif self in {
|
|
1312
|
+
ModelType.QWEN_3_CODER_PLUS,
|
|
1313
|
+
}:
|
|
1314
|
+
return 1_000_000
|
|
1309
1315
|
elif self in {
|
|
1310
1316
|
ModelType.QWEN_LONG,
|
|
1311
1317
|
ModelType.TOGETHER_LLAMA_4_SCOUT,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
camel/__init__.py,sha256=
|
|
1
|
+
camel/__init__.py,sha256=5x8F3f70sOTYS-YwvaLAyGdigu-jW_3Tncrt3bj-R-s,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
|
|
@@ -268,7 +268,7 @@ camel/schemas/base.py,sha256=x0H0oIwbQR6UGdEvR5v-srI25MJ8uTrEw8nnygvLwjw,1604
|
|
|
268
268
|
camel/schemas/openai_converter.py,sha256=SEnYsYcboZgVmjcC1YP5xke3c0MYPESPRmYQWsDGZ4Y,4362
|
|
269
269
|
camel/schemas/outlines_converter.py,sha256=OYKPR1fNyrYs9eh5RiXEAccMbnRc9WTwSVJYbh9HkKE,8738
|
|
270
270
|
camel/services/agent_openapi_server.py,sha256=NUCBLNZBvi4C-J1ESMyRHiRX1NDhPdPkXTMJTl0oUQo,14698
|
|
271
|
-
camel/societies/__init__.py,sha256=
|
|
271
|
+
camel/societies/__init__.py,sha256=8J_PBAGkFdL0692Mxx8dvcSRm57ibouXdIU_f1n9dJE,876
|
|
272
272
|
camel/societies/babyagi_playing.py,sha256=KbTdpHfZ2V8AripVck0bNTOyF-RSaMPCRARz3DvzWfQ,11855
|
|
273
273
|
camel/societies/role_playing.py,sha256=0XScr3WfxX1QOC71RhBLmrcS5y2c7DMQB_mAFOHU34M,31421
|
|
274
274
|
camel/societies/workforce/__init__.py,sha256=bkTI-PE-MSK9AQ2V2gR6cR2WY-R7Jqy_NmXRtAoqo8o,920
|
|
@@ -292,7 +292,7 @@ camel/storages/key_value_storages/__init__.py,sha256=qBNx5QwKGa2wydavFYpM5MLVPkq
|
|
|
292
292
|
camel/storages/key_value_storages/base.py,sha256=FSfxeLuG7SPvn-Mg-OQxtRKPtQBnRkB7lYeDaFOefpk,2177
|
|
293
293
|
camel/storages/key_value_storages/in_memory.py,sha256=k04Nx53lYxD5MoqDtBEgZrQYkAQ-zIuU6tqnoNqiHws,1949
|
|
294
294
|
camel/storages/key_value_storages/json.py,sha256=Jn7-fh2MjSMaVSCCMF_Hu-mAIj6JJ86iwKaSgI-5Uf0,3483
|
|
295
|
-
camel/storages/key_value_storages/mem0_cloud.py,sha256=
|
|
295
|
+
camel/storages/key_value_storages/mem0_cloud.py,sha256=kO6HL__8AwosPY0APv_JaiiOv1jf_Xa2VyZfDlzmOdo,8213
|
|
296
296
|
camel/storages/key_value_storages/redis.py,sha256=Suo7wxxBXFc0fkJ8qSX2xQ26Ik_YhoKWfTOVQKUl5vA,5720
|
|
297
297
|
camel/storages/object_storages/__init__.py,sha256=26yATVTD9yVH-p9KueD30JakstTGiDh89GcFtUNNe4U,915
|
|
298
298
|
camel/storages/object_storages/amazon_s3.py,sha256=9Yvyyyb1LGHxr8REEza7oGopbVtLEfOyXWJc18ZwgqA,7418
|
|
@@ -333,7 +333,7 @@ camel/toolkits/dappier_toolkit.py,sha256=OEHOYXX_oXhgbVtWYAy13nO9uXf9i5qEXSwY4Pe
|
|
|
333
333
|
camel/toolkits/data_commons_toolkit.py,sha256=aHZUSL1ACpnYGaf1rE2csVKTmXTmN8lMGRUBYhZ_YEk,14168
|
|
334
334
|
camel/toolkits/edgeone_pages_mcp_toolkit.py,sha256=1TFpAGHUNLggFQeN1OEw7P5laijwnlrCkfxBtgxFuUY,2331
|
|
335
335
|
camel/toolkits/excel_toolkit.py,sha256=tQaonygk0yDTPZHWWQKG5osTN-R_EawR0bJIKLsLg08,35768
|
|
336
|
-
camel/toolkits/file_write_toolkit.py,sha256=
|
|
336
|
+
camel/toolkits/file_write_toolkit.py,sha256=BIN4c_Tw_24iBu7vDFxVV401UTNqKZkP5p_eOOL_Hmk,39389
|
|
337
337
|
camel/toolkits/function_tool.py,sha256=3_hE-Khqf556CeebchsPpjIDCynC6vKmUJLdh1EO_js,34295
|
|
338
338
|
camel/toolkits/github_toolkit.py,sha256=iUyRrjWGAW_iljZVfNyfkm1Vi55wJxK6PsDAQs9pOag,13099
|
|
339
339
|
camel/toolkits/google_calendar_toolkit.py,sha256=E-sdgdbtNBs_CXbhht9t1dsVr4DsTr5NguHkx4fvSmc,15410
|
|
@@ -347,7 +347,7 @@ camel/toolkits/klavis_toolkit.py,sha256=ZKerhgz5e-AV-iv0ftf07HgWikknIHjB3EOQswfu
|
|
|
347
347
|
camel/toolkits/linkedin_toolkit.py,sha256=wn4eXwYYlVA7doTna7k7WYhUqTBF83W79S-UJs_IQr0,8065
|
|
348
348
|
camel/toolkits/markitdown_toolkit.py,sha256=Cwga4sOTT1HO51CjmXubD6ieRMhumtqEN6jlsgL1nq0,2867
|
|
349
349
|
camel/toolkits/math_toolkit.py,sha256=KdI8AJ9Dbq5cfWboAYJUYgSkmADMCO5eZ6yqYkWuiIQ,3686
|
|
350
|
-
camel/toolkits/mcp_toolkit.py,sha256=
|
|
350
|
+
camel/toolkits/mcp_toolkit.py,sha256=orWwKwCCL7jiPPkuoydGcM97iDRZG3udabY1VyoyPNo,40542
|
|
351
351
|
camel/toolkits/memory_toolkit.py,sha256=TeKYd5UMwgjVpuS2orb-ocFL13eUNKujvrFOruDCpm8,4436
|
|
352
352
|
camel/toolkits/meshy_toolkit.py,sha256=NbgdOBD3FYLtZf-AfonIv6-Q8-8DW129jsaP1PqI2rs,7126
|
|
353
353
|
camel/toolkits/message_agent_toolkit.py,sha256=yWvAaxoxAvDEtD7NH7IkkHIyfWIYK47WZhn5E_RaxKo,22661
|
|
@@ -378,7 +378,7 @@ camel/toolkits/slack_toolkit.py,sha256=ZnK_fRdrQiaAUpjkgHSv1iXdv1HKEgXMlKevu3Qiv
|
|
|
378
378
|
camel/toolkits/stripe_toolkit.py,sha256=07swo5znGTnorafC1uYLKB4NRcJIOPOx19J7tkpLYWk,10102
|
|
379
379
|
camel/toolkits/sympy_toolkit.py,sha256=BAQnI8EFJydNUpKQWXBdleQ1Cm-srDBhFlqp9V9pbPQ,33757
|
|
380
380
|
camel/toolkits/task_planning_toolkit.py,sha256=Ttw9fHae4omGC1SA-6uaeXVHJ1YkwiVloz_hO-fm1gw,4855
|
|
381
|
-
camel/toolkits/terminal_toolkit.py,sha256=
|
|
381
|
+
camel/toolkits/terminal_toolkit.py,sha256=7LdcG0hqZaPiaJPagXVXi87Ncm-MJIIbFUTZRtrIXes,68194
|
|
382
382
|
camel/toolkits/thinking_toolkit.py,sha256=nZYLvKWIx2BM1DYu69I9B5EISAG7aYcLYXKv9663BVk,8000
|
|
383
383
|
camel/toolkits/twitter_toolkit.py,sha256=Px4N8aUxUzy01LhGSWkdrC2JgwKkrY3cvxgMeJ2XYfU,15939
|
|
384
384
|
camel/toolkits/video_analysis_toolkit.py,sha256=h6D7b1MAAzaHn222n_YKtwG-EGEGgMt7mBrNNVipYZc,23361
|
|
@@ -438,7 +438,7 @@ camel/toolkits/open_api_specs/web_scraper/openapi.yaml,sha256=u_WalQ01e8W1D27VnZ
|
|
|
438
438
|
camel/toolkits/open_api_specs/web_scraper/paths/__init__.py,sha256=OKCZrQCDwaWtXIN_2rA9FSqEvgpQRieRoHh7Ek6N16A,702
|
|
439
439
|
camel/toolkits/open_api_specs/web_scraper/paths/scraper.py,sha256=aWy1_ppV4NVVEZfnbN3tu9XA9yAPAC9bRStJ5JuXMRU,1117
|
|
440
440
|
camel/types/__init__.py,sha256=pFTg3CWGSCfwFdoxPDTf4dKV8DdJS1x-bBPuEOmtdf0,2549
|
|
441
|
-
camel/types/enums.py,sha256=
|
|
441
|
+
camel/types/enums.py,sha256=JolxBxgOfAGXAD-Z6DzMLiQ51I8H-6GrAO__1dEB_MQ,63239
|
|
442
442
|
camel/types/mcp_registries.py,sha256=dl4LgYtSaUhsqAKpz28k_SA9La11qxqBvDLaEuyzrFE,4971
|
|
443
443
|
camel/types/openai_types.py,sha256=8ZFzLe-zGmKNPfuVZFzxlxAX98lGf18gtrPhOgMmzus,2104
|
|
444
444
|
camel/types/unified_model_type.py,sha256=U3NUZux7QuMIxPW2H0qDp9BOyDJFHAx6jUmDNw5_9KM,5912
|
|
@@ -467,7 +467,7 @@ camel/verifiers/math_verifier.py,sha256=tA1D4S0sm8nsWISevxSN0hvSVtIUpqmJhzqfbuMo
|
|
|
467
467
|
camel/verifiers/models.py,sha256=GdxYPr7UxNrR1577yW4kyroRcLGfd-H1GXgv8potDWU,2471
|
|
468
468
|
camel/verifiers/physics_verifier.py,sha256=c1grrRddcrVN7szkxhv2QirwY9viIRSITWeWFF5HmLs,30187
|
|
469
469
|
camel/verifiers/python_verifier.py,sha256=ogTz77wODfEcDN4tMVtiSkRQyoiZbHPY2fKybn59lHw,20558
|
|
470
|
-
camel_ai-0.2.
|
|
471
|
-
camel_ai-0.2.
|
|
472
|
-
camel_ai-0.2.
|
|
473
|
-
camel_ai-0.2.
|
|
470
|
+
camel_ai-0.2.73a9.dist-info/METADATA,sha256=DX7cvC3menqY-BKlqULVDdurx20QNDEuUDiMQtrxhM0,50434
|
|
471
|
+
camel_ai-0.2.73a9.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
472
|
+
camel_ai-0.2.73a9.dist-info/licenses/LICENSE,sha256=id0nB2my5kG0xXeimIu5zZrbHLS6EQvxvkKkzIHaT2k,11343
|
|
473
|
+
camel_ai-0.2.73a9.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|