camel-ai 0.2.76a0__py3-none-any.whl → 0.2.76a2__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 (34) hide show
  1. camel/__init__.py +1 -1
  2. camel/agents/chat_agent.py +8 -1
  3. camel/environments/tic_tac_toe.py +1 -1
  4. camel/memories/__init__.py +2 -1
  5. camel/memories/agent_memories.py +3 -1
  6. camel/memories/blocks/chat_history_block.py +17 -2
  7. camel/models/base_model.py +30 -0
  8. camel/societies/workforce/single_agent_worker.py +44 -38
  9. camel/societies/workforce/workforce.py +10 -1
  10. camel/storages/object_storages/google_cloud.py +1 -1
  11. camel/toolkits/__init__.py +9 -2
  12. camel/toolkits/aci_toolkit.py +45 -0
  13. camel/toolkits/context_summarizer_toolkit.py +683 -0
  14. camel/toolkits/{file_write_toolkit.py → file_toolkit.py} +194 -34
  15. camel/toolkits/hybrid_browser_toolkit/config_loader.py +4 -0
  16. camel/toolkits/hybrid_browser_toolkit/hybrid_browser_toolkit.py +67 -2
  17. camel/toolkits/hybrid_browser_toolkit/hybrid_browser_toolkit_ts.py +62 -45
  18. camel/toolkits/hybrid_browser_toolkit/ts/src/browser-session.ts +489 -60
  19. camel/toolkits/hybrid_browser_toolkit/ts/src/config-loader.ts +5 -2
  20. camel/toolkits/hybrid_browser_toolkit/ts/src/hybrid-browser-toolkit.ts +72 -12
  21. camel/toolkits/hybrid_browser_toolkit/ts/src/snapshot-parser.ts +2 -14
  22. camel/toolkits/hybrid_browser_toolkit/ts/src/types.ts +1 -0
  23. camel/toolkits/hybrid_browser_toolkit/ws_wrapper.py +228 -62
  24. camel/toolkits/hybrid_browser_toolkit_py/hybrid_browser_toolkit.py +4 -4
  25. camel/toolkits/markitdown_toolkit.py +27 -1
  26. camel/toolkits/note_taking_toolkit.py +18 -8
  27. camel/toolkits/slack_toolkit.py +50 -1
  28. camel/toolkits/vertex_ai_veo_toolkit.py +590 -0
  29. camel/toolkits/wechat_official_toolkit.py +483 -0
  30. camel/utils/context_utils.py +395 -0
  31. {camel_ai-0.2.76a0.dist-info → camel_ai-0.2.76a2.dist-info}/METADATA +84 -6
  32. {camel_ai-0.2.76a0.dist-info → camel_ai-0.2.76a2.dist-info}/RECORD +34 -30
  33. {camel_ai-0.2.76a0.dist-info → camel_ai-0.2.76a2.dist-info}/WHEEL +0 -0
  34. {camel_ai-0.2.76a0.dist-info → camel_ai-0.2.76a2.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,395 @@
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
+ import os
16
+ from datetime import datetime
17
+ from pathlib import Path
18
+ from typing import TYPE_CHECKING, Any, Dict, List, Optional
19
+
20
+ from camel.logger import get_logger
21
+
22
+ if TYPE_CHECKING:
23
+ from camel.agents import ChatAgent
24
+ from camel.memories.records import MemoryRecord
25
+
26
+ logger = get_logger(__name__)
27
+
28
+
29
+ class ContextUtility:
30
+ r"""Utility class for context management and file operations.
31
+
32
+ This utility provides generic functionality for managing context files,
33
+ markdown generation, and session management that can be used by
34
+ context-related features.
35
+
36
+ Key features:
37
+ - Session-based directory management
38
+ - Generic markdown file operations
39
+ - Text-based search through files
40
+ - File metadata handling
41
+ - Agent memory record retrieval
42
+ """
43
+
44
+ def __init__(self, working_directory: Optional[str] = None):
45
+ r"""Initialize the ContextUtility.
46
+
47
+ Args:
48
+ working_directory (str, optional): The directory path where files
49
+ will be stored. If not provided, a default directory will be
50
+ used.
51
+ """
52
+ self.working_directory_param = working_directory
53
+ self._setup_storage(working_directory)
54
+
55
+ def _setup_storage(self, working_directory: Optional[str]) -> None:
56
+ r"""Initialize session-specific storage paths and create directory
57
+ structure for context file management."""
58
+ self.session_id = self._generate_session_id()
59
+
60
+ if working_directory:
61
+ self.working_directory = Path(working_directory).resolve()
62
+ else:
63
+ camel_workdir = os.environ.get("CAMEL_WORKDIR")
64
+ if camel_workdir:
65
+ self.working_directory = Path(camel_workdir) / "context_files"
66
+ else:
67
+ self.working_directory = Path("context_files")
68
+
69
+ # Create session-specific directory
70
+ self.working_directory = self.working_directory / self.session_id
71
+ self.working_directory.mkdir(parents=True, exist_ok=True)
72
+
73
+ def _generate_session_id(self) -> str:
74
+ r"""Create timestamp-based unique identifier for isolating
75
+ current session files from other sessions."""
76
+ timestamp = datetime.now().strftime('%Y%m%d_%H%M%S_%f')
77
+ return f"session_{timestamp}"
78
+
79
+ # ========= GENERIC FILE MANAGEMENT METHODS =========
80
+
81
+ def _create_or_update_note(self, note_name: str, content: str) -> str:
82
+ r"""Write content to markdown file, creating new file or
83
+ overwriting existing one with UTF-8 encoding.
84
+
85
+ Args:
86
+ note_name (str): Name of the note (without .md extension).
87
+ content (str): Content to write to the note.
88
+
89
+ Returns:
90
+ str: Success message.
91
+ """
92
+ try:
93
+ file_path = self.working_directory / f"{note_name}.md"
94
+ with open(file_path, 'w', encoding='utf-8') as f:
95
+ f.write(content)
96
+ return f"Note '{note_name}.md' created successfully"
97
+ except Exception as e:
98
+ logger.error(f"Error creating note {note_name}: {e}")
99
+ return f"Error creating note: {e}"
100
+
101
+ def save_markdown_file(
102
+ self,
103
+ filename: str,
104
+ content: str,
105
+ title: Optional[str] = None,
106
+ metadata: Optional[Dict[str, Any]] = None,
107
+ ) -> str:
108
+ r"""Generic method to save any markdown content to a file.
109
+
110
+ Args:
111
+ filename (str): Name without .md extension.
112
+ content (str): Main content to save.
113
+ title (str, optional): Title for the markdown file.
114
+ metadata (Dict, optional): Additional metadata to include.
115
+
116
+ Returns:
117
+ str: Success message or error message.
118
+ """
119
+ try:
120
+ markdown_content = ""
121
+
122
+ # Add title if provided
123
+ if title:
124
+ markdown_content += f"# {title}\n\n"
125
+
126
+ # Add metadata section if provided
127
+ if metadata:
128
+ markdown_content += "## Metadata\n\n"
129
+ for key, value in metadata.items():
130
+ markdown_content += f"- {key}: {value}\n"
131
+ markdown_content += "\n"
132
+
133
+ # Add main content
134
+ markdown_content += content
135
+
136
+ self._create_or_update_note(filename, markdown_content)
137
+ logger.info(
138
+ f"Markdown file saved to "
139
+ f"{self.working_directory / f'{filename}.md'}"
140
+ )
141
+ return f"Markdown file '{filename}.md' saved successfully"
142
+
143
+ except Exception as e:
144
+ logger.error(f"Error saving markdown file {filename}: {e}")
145
+ return f"Error saving markdown file: {e}"
146
+
147
+ def load_markdown_file(self, filename: str) -> str:
148
+ r"""Generic method to load any markdown file.
149
+
150
+ Args:
151
+ filename (str): Name without .md extension.
152
+
153
+ Returns:
154
+ str: File content or empty string if not found.
155
+ """
156
+ try:
157
+ file_path = self.working_directory / f"{filename}.md"
158
+ if file_path.exists():
159
+ return file_path.read_text(encoding="utf-8")
160
+ return ""
161
+ except Exception as e:
162
+ logger.error(f"Error loading markdown file {filename}: {e}")
163
+ return ""
164
+
165
+ def file_exists(self, filename: str) -> bool:
166
+ r"""Verify presence of markdown file in current session directory.
167
+
168
+ Args:
169
+ filename (str): Name without .md extension.
170
+
171
+ Returns:
172
+ bool: True if file exists, False otherwise.
173
+ """
174
+ file_path = self.working_directory / f"{filename}.md"
175
+ return file_path.exists()
176
+
177
+ def list_markdown_files(self) -> List[str]:
178
+ r"""Discover all markdown files in current session directory
179
+ and return their base names for reference.
180
+
181
+ Returns:
182
+ List[str]: List of filenames without .md extension.
183
+ """
184
+ try:
185
+ md_files = list(self.working_directory.glob("*.md"))
186
+ return [f.stem for f in md_files]
187
+ except Exception as e:
188
+ logger.error(f"Error listing markdown files: {e}")
189
+ return []
190
+
191
+ # ========= GENERIC AGENT MEMORY METHODS =========
192
+
193
+ def get_agent_memory_records(
194
+ self, agent: "ChatAgent"
195
+ ) -> List["MemoryRecord"]:
196
+ r"""Retrieve conversation history from agent's memory system.
197
+
198
+ Args:
199
+ agent (ChatAgent): The agent to extract memory records from.
200
+
201
+ Returns:
202
+ List[MemoryRecord]: List of memory records from the agent.
203
+ """
204
+ try:
205
+ context_records = agent.memory.retrieve()
206
+ return [cr.memory_record for cr in context_records]
207
+ except Exception as e:
208
+ logger.error(f"Error extracting memory records: {e}")
209
+ return []
210
+
211
+ def format_memory_as_conversation(
212
+ self, memory_records: List["MemoryRecord"]
213
+ ) -> str:
214
+ r"""Transform structured memory records into human-readable
215
+ conversation format with role labels and message content.
216
+
217
+ Args:
218
+ memory_records (List[MemoryRecord]): Memory records to format.
219
+
220
+ Returns:
221
+ str: Formatted conversation text.
222
+ """
223
+ conversation_lines = []
224
+
225
+ for record in memory_records:
226
+ role = (
227
+ record.role_at_backend.value
228
+ if hasattr(record.role_at_backend, 'value')
229
+ else str(record.role_at_backend)
230
+ )
231
+ content = record.message.content
232
+ conversation_lines.append(f"{role}: {content}")
233
+
234
+ return "\n".join(conversation_lines)
235
+
236
+ # ========= SESSION MANAGEMENT METHODS =========
237
+
238
+ def create_session_directory(
239
+ self, base_dir: Optional[str] = None, session_id: Optional[str] = None
240
+ ) -> Path:
241
+ r"""Create a session-specific directory.
242
+
243
+ Args:
244
+ base_dir (str, optional): Base directory. If None, uses current
245
+ working directory.
246
+ session_id (str, optional): Custom session ID. If None, generates
247
+ new one.
248
+
249
+ Returns:
250
+ Path: The created session directory path.
251
+ """
252
+ if session_id is None:
253
+ session_id = self._generate_session_id()
254
+
255
+ if base_dir:
256
+ base_path = Path(base_dir).resolve()
257
+ else:
258
+ base_path = self.working_directory.parent
259
+
260
+ session_dir = base_path / session_id
261
+ session_dir.mkdir(parents=True, exist_ok=True)
262
+ return session_dir
263
+
264
+ def get_session_metadata(self) -> Dict[str, Any]:
265
+ r"""Collect comprehensive session information including identifiers,
266
+ timestamps, and directory paths for tracking and reference.
267
+
268
+ Returns:
269
+ Dict[str, Any]: Session metadata including ID, timestamp,
270
+ directory.
271
+ """
272
+ return {
273
+ 'session_id': self.session_id,
274
+ 'working_directory': str(self.working_directory),
275
+ 'created_at': datetime.now().isoformat(),
276
+ 'base_directory': str(self.working_directory.parent),
277
+ }
278
+
279
+ def list_sessions(self, base_dir: Optional[str] = None) -> List[str]:
280
+ r"""Discover all available session directories for browsing
281
+ historical conversations and context files.
282
+
283
+ Args:
284
+ base_dir (str, optional): Base directory to search. If None, uses
285
+ parent of working directory.
286
+
287
+ Returns:
288
+ List[str]: List of session directory names.
289
+ """
290
+ try:
291
+ if base_dir:
292
+ search_dir = Path(base_dir)
293
+ else:
294
+ search_dir = self.working_directory.parent
295
+
296
+ session_dirs = [
297
+ d.name
298
+ for d in search_dir.iterdir()
299
+ if d.is_dir() and d.name.startswith('session_')
300
+ ]
301
+ return sorted(session_dirs)
302
+ except Exception as e:
303
+ logger.error(f"Error listing sessions: {e}")
304
+ return []
305
+
306
+ # ========= GENERIC SEARCH METHODS =========
307
+
308
+ def search_in_file(
309
+ self, file_path: Path, keywords: List[str], top_k: int = 4
310
+ ) -> str:
311
+ r"""Perform keyword-based search through file sections,
312
+ ranking results by keyword frequency and returning top matches.
313
+
314
+ Args:
315
+ file_path (Path): Path to the file to search.
316
+ keywords (List[str]): Keywords to search for.
317
+ top_k (int): Maximum number of results to return.
318
+
319
+ Returns:
320
+ str: Formatted search results.
321
+ """
322
+ results: List[Dict[str, Any]] = []
323
+ keyword_terms = [keyword.lower() for keyword in keywords]
324
+
325
+ try:
326
+ if not file_path.exists():
327
+ return ""
328
+
329
+ with open(file_path, 'r', encoding='utf-8') as f:
330
+ content = f.read()
331
+
332
+ # Split content into sections (assuming ### headers)
333
+ sections = content.split('### ')[1:] # Skip the header part
334
+
335
+ for i, section in enumerate(sections):
336
+ if not section.strip():
337
+ continue
338
+
339
+ section_lower = section.lower()
340
+
341
+ # count how many keywords appear in this section
342
+ keyword_matches = sum(
343
+ 1 for keyword in keyword_terms if keyword in section_lower
344
+ )
345
+
346
+ if keyword_matches > 0:
347
+ results.append(
348
+ {
349
+ 'content': f"### {section.strip()}",
350
+ 'keyword_count': keyword_matches,
351
+ 'section_num': i + 1,
352
+ }
353
+ )
354
+
355
+ except Exception as e:
356
+ logger.warning(f"Error reading file {file_path}: {e}")
357
+ return ""
358
+
359
+ # sort by keyword count and limit results
360
+ results.sort(key=lambda x: x['keyword_count'], reverse=True)
361
+ results = results[:top_k]
362
+
363
+ if not results:
364
+ return ""
365
+
366
+ # format results
367
+ formatted_sections = []
368
+ for result in results:
369
+ formatted_sections.append(
370
+ f"Section {result['section_num']} "
371
+ f"(keyword matches: {result['keyword_count']}):\n"
372
+ f"{result['content']}\n"
373
+ )
374
+
375
+ return "\n---\n".join(formatted_sections)
376
+
377
+ # ========= UTILITY METHODS =========
378
+
379
+ def get_working_directory(self) -> Path:
380
+ r"""Retrieve the session-specific directory path where
381
+ all context files are stored.
382
+
383
+ Returns:
384
+ Path: The working directory path.
385
+ """
386
+ return self.working_directory
387
+
388
+ def get_session_id(self) -> str:
389
+ r"""Retrieve the unique identifier for the current session
390
+ used for file organization and tracking.
391
+
392
+ Returns:
393
+ str: The session ID.
394
+ """
395
+ return self.session_id
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: camel-ai
3
- Version: 0.2.76a0
3
+ Version: 0.2.76a2
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
@@ -57,6 +57,7 @@ Requires-Dist: flask>=2.0; extra == 'all'
57
57
  Requires-Dist: google-api-python-client==2.166.0; extra == 'all'
58
58
  Requires-Dist: google-auth-httplib2==0.2.0; extra == 'all'
59
59
  Requires-Dist: google-auth-oauthlib==1.2.1; extra == 'all'
60
+ Requires-Dist: google-cloud-aiplatform>=1.111.0; extra == 'all'
60
61
  Requires-Dist: google-cloud-storage<3,>=2.18.0; extra == 'all'
61
62
  Requires-Dist: google-genai>=1.13.0; extra == 'all'
62
63
  Requires-Dist: googlemaps<5,>=4.10.0; extra == 'all'
@@ -447,12 +448,52 @@ Join us ([*Discord*](https://discord.camel-ai.org/) or [*WeChat*](https://ghli.o
447
448
  </div>
448
449
 
449
450
  <div align="center">
450
- <img src="docs/images/star.gif" alt="Star" width="186" height="60">
451
+ <img src="docs/images/stars.gif" alt="Star">
451
452
  </a>
452
453
  </div>
453
454
 
454
455
  <br>
455
456
 
457
+ <details>
458
+ <summary><kbd>Table of contents</kbd></summary>
459
+
460
+ <br/>
461
+
462
+ - [CAMEL Framework Design Principles](#camel-framework-design-principles)
463
+ - [Why Use CAMEL for Your Research?](#why-use-camel-for-your-research)
464
+ - [What Can You Build With CAMEL?](#what-can-you-build-with-camel)
465
+ - [Data Generation](#1-data-generation)
466
+ - [Task Automation](#2-task-automation)
467
+ - [World Simulation](#3-world-simulation)
468
+ - [Quick Start](#quick-start)
469
+ - [Starting with ChatAgent](#starting-with-chatagent)
470
+ - [Seeking Help](#seeking-help)
471
+ - [Tech Stack](#tech-stack)
472
+ - [Research](#research)
473
+ - [Synthetic Datasets](#synthetic-datasets)
474
+ - [Cookbooks (Usecases)](#cookbooks-usecases)
475
+ - [Basic Concepts](#1-basic-concepts)
476
+ - [Advanced Features](#2-advanced-features)
477
+ - [Model Training & Data Generation](#3-model-training--data-generation)
478
+ - [Multi-Agent Systems & Applications](#4-multi-agent-systems--applications)
479
+ - [Data Processing](#5-data-processing)
480
+ - [Real-World Usecases](#real-world-usecases)
481
+ - [🧱 Built with CAMEL (Real-world Producs & Research)](#-built-with-camel-real-world-producs--research)
482
+ - [Research Projects](#research-projects)
483
+ - [Product Projects](#product-projects)
484
+ - [🗓️ Events](#️-events)
485
+ - [Contributing to CAMEL](#contributing-to-camel)
486
+ - [Community & Contact](#community--contact)
487
+ - [Citation](#citation)
488
+ - [Acknowledgment](#acknowledgment)
489
+ - [License](#license)
490
+
491
+ ####
492
+
493
+ <br/>
494
+
495
+ </details>
496
+
456
497
 
457
498
  ## CAMEL Framework Design Principles
458
499
 
@@ -686,6 +727,18 @@ We believe that studying these agents on a large scale offers valuable insights
686
727
 
687
728
  **Explore our research projects:**
688
729
 
730
+ <div align="center">
731
+ <a href="https://github.com/camel-ai/owl">
732
+ <img src="docs/images/owl.png" alt="OWL">
733
+ </a>
734
+ </div>
735
+
736
+ <div align="center">
737
+ <a href="https://oasis.camel-ai.org/">
738
+ <img src="docs/images/oasis.png" alt="OASIS">
739
+ </a>
740
+ </div>
741
+
689
742
  <div align="center">
690
743
  <a href="https://crab.camel-ai.org/">
691
744
  <img src="docs/images/crab.png" alt="CRAB">
@@ -693,14 +746,14 @@ We believe that studying these agents on a large scale offers valuable insights
693
746
  </div>
694
747
 
695
748
  <div align="center">
696
- <a href="https://agent-trust.camel-ai.org/">
697
- <img src="docs/images/agent_trust.png" alt="Agent Trust">
749
+ <a href="https://github.com/camel-ai/loong">
750
+ <img src="docs/images/loong.png" alt="Loong">
698
751
  </a>
699
752
  </div>
700
753
 
701
754
  <div align="center">
702
- <a href="https://oasis.camel-ai.org/">
703
- <img src="docs/images/oasis.png" alt="OASIS">
755
+ <a href="https://agent-trust.camel-ai.org/">
756
+ <img src="docs/images/agent_trust.png" alt="Agent Trust">
704
757
  </a>
705
758
  </div>
706
759
 
@@ -834,6 +887,31 @@ Real-world usecases demonstrating how CAMEL’s multi-agent framework enables re
834
887
 
835
888
  <br>
836
889
 
890
+ ## 🧱 Built with CAMEL (Real-world Producs & Research)
891
+ <div align="left">
892
+ <a href="https://www.camel-ai.org/">
893
+ <img src="docs/images/built_with_CAMEL.png" alt="Built with CAMEL" height="40px">
894
+ </a>
895
+ </div>
896
+
897
+ ### Research Projects
898
+
899
+ | Name | Description |
900
+ |:---|:---|
901
+ | **[ChatDev](https://github.com/OpenBMB/ChatDev/tree/main/camel)** | Communicative Agents for software Development |
902
+ | **[Paper2Poster](https://github.com/Paper2Poster/Paper2Poster)** | Multimodal poster automation from scientific papers |
903
+
904
+ ### Product Projects
905
+
906
+ | Name | Description |
907
+ |:---|:---|
908
+ | **[Eigent](https://www.eigent.ai/)** | The World First Multi-agent Workforce |
909
+ | **[EigentBot](https://bot.eigent.ai/)** | One EigentBot,
910
+ Every Code Answer |
911
+ | **[Matrix](https://matrix.eigent.ai/)** | Social Media Simulation |
912
+ | **[AI Geometric](https://www.linkedin.com/posts/aigeometric_ai-interviewpreparation-careerdevelopment-activity-7261428422516555776-MtaK/?utm_source=share&utm_medium=member_desktop&rcm=ACoAAChHluEB9xRwkjiJ6VSAzqM2Y-U4NI2sKGY)** | AI-powered interview copilot |
913
+ | **[Log10](https://github.com/log10-io/log10/blob/main/src/log10/agents/camel.py)** | AI accuracy, delivered |
914
+
837
915
 
838
916
  ## 🗓️ Events
839
917