camel-ai 0.2.71a6__py3-none-any.whl → 0.2.71a7__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/workforce/single_agent_worker.py +2 -0
- camel/societies/workforce/worker.py +2 -0
- camel/societies/workforce/workforce.py +3 -17
- camel/toolkits/file_write_toolkit.py +179 -124
- {camel_ai-0.2.71a6.dist-info → camel_ai-0.2.71a7.dist-info}/METADATA +1 -1
- {camel_ai-0.2.71a6.dist-info → camel_ai-0.2.71a7.dist-info}/RECORD +9 -9
- {camel_ai-0.2.71a6.dist-info → camel_ai-0.2.71a7.dist-info}/WHEEL +0 -0
- {camel_ai-0.2.71a6.dist-info → camel_ai-0.2.71a7.dist-info}/licenses/LICENSE +0 -0
camel/__init__.py
CHANGED
|
@@ -344,6 +344,8 @@ class SingleAgentWorker(Worker):
|
|
|
344
344
|
f"{Fore.RED}Error processing task {task.id}: "
|
|
345
345
|
f"{type(e).__name__}: {e}{Fore.RESET}"
|
|
346
346
|
)
|
|
347
|
+
# Store error information in task result
|
|
348
|
+
task.result = f"{type(e).__name__}: {e!s}"
|
|
347
349
|
return TaskState.FAILED
|
|
348
350
|
finally:
|
|
349
351
|
# Return agent to pool or let it be garbage collected
|
|
@@ -103,6 +103,8 @@ class Worker(BaseNode, ABC):
|
|
|
103
103
|
await self._channel.return_task(task.id)
|
|
104
104
|
except Exception as e:
|
|
105
105
|
logger.error(f"Error processing task {task.id}: {e}")
|
|
106
|
+
# Store error information in task result
|
|
107
|
+
task.result = f"{type(e).__name__}: {e!s}"
|
|
106
108
|
task.set_state(TaskState.FAILED)
|
|
107
109
|
await self._channel.return_task(task.id)
|
|
108
110
|
finally:
|
|
@@ -2145,17 +2145,7 @@ class Workforce(BaseNode):
|
|
|
2145
2145
|
f"Current pending tasks: {len(self._pending_tasks)}, "
|
|
2146
2146
|
f"In-flight tasks: {self._in_flight_tasks}"
|
|
2147
2147
|
)
|
|
2148
|
-
logger.
|
|
2149
|
-
|
|
2150
|
-
if self._pending_tasks and self._assignees:
|
|
2151
|
-
for task in self._pending_tasks:
|
|
2152
|
-
if task.id in self._assignees:
|
|
2153
|
-
# Mark task as failed and decrement counter
|
|
2154
|
-
task.set_state(TaskState.FAILED)
|
|
2155
|
-
self._decrement_in_flight_tasks(
|
|
2156
|
-
task.id, "timeout/error in _get_returned_task"
|
|
2157
|
-
)
|
|
2158
|
-
return task
|
|
2148
|
+
logger.error(error_msg, exc_info=True)
|
|
2159
2149
|
return None
|
|
2160
2150
|
|
|
2161
2151
|
async def _post_ready_tasks(self) -> None:
|
|
@@ -2231,12 +2221,8 @@ class Workforce(BaseNode):
|
|
|
2231
2221
|
task.failure_count += 1
|
|
2232
2222
|
|
|
2233
2223
|
# Determine detailed failure information
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
f"response: {task.result[:100] if task.result else ''}..."
|
|
2237
|
-
else:
|
|
2238
|
-
failure_reason = "Task marked as failed despite "
|
|
2239
|
-
f"having result: {(task.result or '')[:100]}..."
|
|
2224
|
+
# Use the actual error/result stored in task.result
|
|
2225
|
+
failure_reason = task.result or "Unknown error"
|
|
2240
2226
|
|
|
2241
2227
|
# Add context about the worker and task
|
|
2242
2228
|
worker_id = task.assigned_worker_id or "unknown"
|
|
@@ -14,10 +14,7 @@
|
|
|
14
14
|
import re
|
|
15
15
|
from datetime import datetime
|
|
16
16
|
from pathlib import Path
|
|
17
|
-
from typing import
|
|
18
|
-
|
|
19
|
-
if TYPE_CHECKING:
|
|
20
|
-
from reportlab.platypus import Table
|
|
17
|
+
from typing import List, Optional, Tuple, Union
|
|
21
18
|
|
|
22
19
|
from camel.logger import get_logger
|
|
23
20
|
from camel.toolkits.base import BaseToolkit
|
|
@@ -26,9 +23,6 @@ from camel.utils import MCPServer, dependencies_required
|
|
|
26
23
|
|
|
27
24
|
logger = get_logger(__name__)
|
|
28
25
|
|
|
29
|
-
# Default format when no extension is provided
|
|
30
|
-
DEFAULT_FORMAT = '.md'
|
|
31
|
-
|
|
32
26
|
|
|
33
27
|
@MCPServer()
|
|
34
28
|
class FileWriteToolkit(BaseToolkit):
|
|
@@ -92,6 +86,22 @@ class FileWriteToolkit(BaseToolkit):
|
|
|
92
86
|
path_obj = path_obj.parent / sanitized_filename
|
|
93
87
|
return path_obj.resolve()
|
|
94
88
|
|
|
89
|
+
def _sanitize_filename(self, filename: str) -> str:
|
|
90
|
+
r"""Sanitize a filename by replacing any character that is not
|
|
91
|
+
alphanumeric, a dot (.), hyphen (-), or underscore (_) with an
|
|
92
|
+
underscore (_).
|
|
93
|
+
|
|
94
|
+
Args:
|
|
95
|
+
filename (str): The original filename which may contain spaces or
|
|
96
|
+
special characters.
|
|
97
|
+
|
|
98
|
+
Returns:
|
|
99
|
+
str: The sanitized filename with disallowed characters replaced by
|
|
100
|
+
underscores.
|
|
101
|
+
"""
|
|
102
|
+
safe = re.sub(r'[^\w\-.]', '_', filename)
|
|
103
|
+
return safe
|
|
104
|
+
|
|
95
105
|
def _write_text_file(
|
|
96
106
|
self, file_path: Path, content: str, encoding: str = "utf-8"
|
|
97
107
|
) -> None:
|
|
@@ -104,7 +114,6 @@ class FileWriteToolkit(BaseToolkit):
|
|
|
104
114
|
"""
|
|
105
115
|
with file_path.open("w", encoding=encoding) as f:
|
|
106
116
|
f.write(content)
|
|
107
|
-
logger.debug(f"Wrote text to {file_path} with {encoding} encoding")
|
|
108
117
|
|
|
109
118
|
def _generate_unique_filename(self, file_path: Path) -> Path:
|
|
110
119
|
r"""Generate a unique filename if the target file already exists.
|
|
@@ -163,7 +172,6 @@ class FileWriteToolkit(BaseToolkit):
|
|
|
163
172
|
para.style = style
|
|
164
173
|
|
|
165
174
|
document.save(str(file_path))
|
|
166
|
-
logger.debug(f"Wrote DOCX to {file_path} with default formatting")
|
|
167
175
|
|
|
168
176
|
@dependencies_required('reportlab')
|
|
169
177
|
def _write_pdf_file(
|
|
@@ -331,9 +339,6 @@ class FileWriteToolkit(BaseToolkit):
|
|
|
331
339
|
isinstance(row, list) for row in content
|
|
332
340
|
):
|
|
333
341
|
# Content is a table (List[List[str]])
|
|
334
|
-
logger.debug(
|
|
335
|
-
f"Processing content as table with {len(content)} rows"
|
|
336
|
-
)
|
|
337
342
|
if content:
|
|
338
343
|
table = self._create_pdf_table(content)
|
|
339
344
|
story.append(table)
|
|
@@ -364,7 +369,6 @@ class FileWriteToolkit(BaseToolkit):
|
|
|
364
369
|
|
|
365
370
|
# Process content
|
|
366
371
|
lines = content.split('\n')
|
|
367
|
-
logger.debug(f"Processing {len(lines)} lines of content")
|
|
368
372
|
|
|
369
373
|
# Parse all tables from the content first
|
|
370
374
|
tables = self._parse_markdown_table(lines)
|
|
@@ -396,8 +400,6 @@ class FileWriteToolkit(BaseToolkit):
|
|
|
396
400
|
)
|
|
397
401
|
|
|
398
402
|
if current_table_idx < len(tables):
|
|
399
|
-
table_row_count = len(tables[current_table_idx])
|
|
400
|
-
logger.debug(f"Adding table with {table_row_count} rows")
|
|
401
403
|
try:
|
|
402
404
|
table = self._create_pdf_table(
|
|
403
405
|
tables[current_table_idx]
|
|
@@ -530,10 +532,8 @@ class FileWriteToolkit(BaseToolkit):
|
|
|
530
532
|
addMapping(font_name, 0, 1, font_name) # italic
|
|
531
533
|
addMapping(font_name, 1, 0, font_name) # bold
|
|
532
534
|
addMapping(font_name, 1, 1, font_name) # bold italic
|
|
533
|
-
logger.debug(f"Registered Chinese font: {font_path}")
|
|
534
535
|
return font_name
|
|
535
|
-
except Exception
|
|
536
|
-
logger.debug(f"Failed to register font {font_path}: {e}")
|
|
536
|
+
except Exception:
|
|
537
537
|
continue
|
|
538
538
|
|
|
539
539
|
# Fallback to Helvetica if no Chinese font found
|
|
@@ -559,38 +559,29 @@ class FileWriteToolkit(BaseToolkit):
|
|
|
559
559
|
|
|
560
560
|
# Check for table (Markdown-style)
|
|
561
561
|
if self._is_table_row(line):
|
|
562
|
-
logger.debug(f"Found table line: {line}")
|
|
563
|
-
|
|
564
562
|
if not in_table:
|
|
565
563
|
in_table = True
|
|
566
564
|
current_table_data = []
|
|
567
|
-
logger.debug("Starting new table")
|
|
568
565
|
|
|
569
566
|
# Skip separator lines (e.g., |---|---|)
|
|
570
567
|
if self._is_table_separator(line):
|
|
571
|
-
logger.debug("Skipping separator line")
|
|
572
568
|
continue
|
|
573
569
|
|
|
574
570
|
# Parse table row
|
|
575
571
|
cells = self._parse_table_row(line)
|
|
576
572
|
if cells:
|
|
577
573
|
current_table_data.append(cells)
|
|
578
|
-
logger.debug(f"Added table row: {cells}")
|
|
579
574
|
continue
|
|
580
575
|
|
|
581
576
|
# If we were in a table and now we're not, finalize the table
|
|
582
577
|
if in_table:
|
|
583
578
|
if current_table_data:
|
|
584
|
-
row_count = len(current_table_data)
|
|
585
|
-
logger.debug(f"Finalizing table with {row_count} rows")
|
|
586
579
|
tables.append(current_table_data)
|
|
587
580
|
current_table_data = []
|
|
588
581
|
in_table = False
|
|
589
582
|
|
|
590
583
|
# Add any remaining table
|
|
591
584
|
if in_table and current_table_data:
|
|
592
|
-
row_count = len(current_table_data)
|
|
593
|
-
logger.debug(f"Adding final table with {row_count} rows")
|
|
594
585
|
tables.append(current_table_data)
|
|
595
586
|
|
|
596
587
|
return tables
|
|
@@ -646,7 +637,7 @@ class FileWriteToolkit(BaseToolkit):
|
|
|
646
637
|
|
|
647
638
|
return cells
|
|
648
639
|
|
|
649
|
-
def _create_pdf_table(self, table_data: List[List[str]])
|
|
640
|
+
def _create_pdf_table(self, table_data: List[List[str]]):
|
|
650
641
|
r"""Create a formatted table for PDF.
|
|
651
642
|
|
|
652
643
|
Args:
|
|
@@ -656,40 +647,153 @@ class FileWriteToolkit(BaseToolkit):
|
|
|
656
647
|
Table: A formatted reportlab Table object.
|
|
657
648
|
"""
|
|
658
649
|
from reportlab.lib import colors
|
|
659
|
-
from reportlab.
|
|
650
|
+
from reportlab.lib.pagesizes import A4
|
|
651
|
+
from reportlab.lib.styles import ParagraphStyle
|
|
652
|
+
from reportlab.platypus import Paragraph, Table, TableStyle
|
|
660
653
|
|
|
661
654
|
try:
|
|
662
655
|
# Get Chinese font for table
|
|
663
656
|
chinese_font = self._register_chinese_font()
|
|
664
657
|
|
|
665
|
-
#
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
658
|
+
# Calculate available width (A4 width minus margins)
|
|
659
|
+
page_width = A4[0] # A4 width in points
|
|
660
|
+
margins = 144 # left + right margins (72 each)
|
|
661
|
+
available_width = page_width - margins
|
|
662
|
+
|
|
663
|
+
# Calculate column widths and font size based on content
|
|
664
|
+
if table_data:
|
|
665
|
+
num_columns = len(table_data[0])
|
|
666
|
+
|
|
667
|
+
# Calculate max content length for each column
|
|
668
|
+
max_lengths = [0] * num_columns
|
|
669
|
+
max_cell_length = 0
|
|
670
|
+
for row in table_data:
|
|
671
|
+
for i, cell in enumerate(row):
|
|
672
|
+
if i < len(max_lengths):
|
|
673
|
+
cell_length = len(str(cell))
|
|
674
|
+
max_lengths[i] = max(max_lengths[i], cell_length)
|
|
675
|
+
max_cell_length = max(max_cell_length, cell_length)
|
|
676
|
+
|
|
677
|
+
# Dynamic font size calculation based on columns and content
|
|
678
|
+
# Base font sizes
|
|
679
|
+
base_header_font = 9
|
|
680
|
+
base_body_font = 8
|
|
681
|
+
|
|
682
|
+
# Calculate font size factor based on columns and content
|
|
683
|
+
column_factors = {10: 0.6, 8: 0.7, 6: 0.8, 4: 0.9}
|
|
684
|
+
font_size_factor = next(
|
|
685
|
+
(
|
|
686
|
+
factor
|
|
687
|
+
for cols, factor in column_factors.items()
|
|
688
|
+
if num_columns > cols
|
|
689
|
+
),
|
|
690
|
+
1.0,
|
|
691
|
+
)
|
|
692
|
+
|
|
693
|
+
# Further adjust if max cell content is very long
|
|
694
|
+
if max_cell_length > 30:
|
|
695
|
+
font_size_factor *= 0.8
|
|
696
|
+
elif max_cell_length > 20:
|
|
697
|
+
font_size_factor *= 0.9
|
|
698
|
+
|
|
699
|
+
header_font_size = max(
|
|
700
|
+
5, int(base_header_font * font_size_factor)
|
|
701
|
+
)
|
|
702
|
+
body_font_size = max(5, int(base_body_font * font_size_factor))
|
|
703
|
+
|
|
704
|
+
# Calculate minimum column width based on font size
|
|
705
|
+
min_col_width = max(30, 40 * font_size_factor)
|
|
706
|
+
|
|
707
|
+
# Distribute width proportionally with minimum width
|
|
708
|
+
total_length = sum(max_lengths)
|
|
709
|
+
if total_length > 0:
|
|
710
|
+
# Calculate proportional widths
|
|
711
|
+
proportional_widths = [
|
|
712
|
+
(length / total_length) * available_width
|
|
713
|
+
for length in max_lengths
|
|
714
|
+
]
|
|
715
|
+
|
|
716
|
+
# Ensure minimum width and adjust if necessary
|
|
717
|
+
col_widths = []
|
|
718
|
+
total_width = 0
|
|
719
|
+
for width in proportional_widths:
|
|
720
|
+
adjusted_width = max(min_col_width, width)
|
|
721
|
+
col_widths.append(adjusted_width)
|
|
722
|
+
total_width += adjusted_width
|
|
723
|
+
|
|
724
|
+
# Scale down if total exceeds available width
|
|
725
|
+
if total_width > available_width:
|
|
726
|
+
scale_factor = available_width / total_width
|
|
727
|
+
col_widths = [w * scale_factor for w in col_widths]
|
|
728
|
+
else:
|
|
729
|
+
col_widths = [available_width / num_columns] * num_columns
|
|
730
|
+
|
|
731
|
+
# Adjust padding based on font size
|
|
732
|
+
h_padding = max(2, int(6 * font_size_factor))
|
|
733
|
+
v_padding = max(2, int(4 * font_size_factor))
|
|
734
|
+
else:
|
|
735
|
+
col_widths = None
|
|
736
|
+
header_font_size = 9
|
|
737
|
+
body_font_size = 8
|
|
738
|
+
h_padding = 6
|
|
739
|
+
v_padding = 4
|
|
740
|
+
|
|
741
|
+
# Create paragraph styles for wrapping text
|
|
742
|
+
header_style = ParagraphStyle(
|
|
743
|
+
'TableHeader',
|
|
744
|
+
fontName=chinese_font,
|
|
745
|
+
fontSize=header_font_size,
|
|
746
|
+
textColor=colors.whitesmoke,
|
|
747
|
+
alignment=0, # LEFT alignment
|
|
748
|
+
leading=header_font_size * 1.2,
|
|
749
|
+
)
|
|
669
750
|
|
|
670
|
-
|
|
671
|
-
|
|
751
|
+
body_style = ParagraphStyle(
|
|
752
|
+
'TableBody',
|
|
753
|
+
fontName=chinese_font,
|
|
754
|
+
fontSize=body_font_size,
|
|
755
|
+
textColor=colors.black,
|
|
756
|
+
alignment=0, # LEFT alignment
|
|
757
|
+
leading=body_font_size * 1.2,
|
|
758
|
+
)
|
|
759
|
+
|
|
760
|
+
# Convert table data to Paragraph objects for text wrapping
|
|
761
|
+
wrapped_data = []
|
|
762
|
+
for row_idx, row in enumerate(table_data):
|
|
763
|
+
wrapped_row = []
|
|
764
|
+
for cell in row:
|
|
765
|
+
cell_text = str(cell)
|
|
766
|
+
# Use header style for first row, body style for others
|
|
767
|
+
style = header_style if row_idx == 0 else body_style
|
|
768
|
+
# Escape special characters for XML
|
|
769
|
+
cell_text = (
|
|
770
|
+
cell_text.replace('&', '&')
|
|
771
|
+
.replace('<', '<')
|
|
772
|
+
.replace('>', '>')
|
|
773
|
+
)
|
|
774
|
+
para = Paragraph(cell_text, style)
|
|
775
|
+
wrapped_row.append(para)
|
|
776
|
+
wrapped_data.append(wrapped_row)
|
|
672
777
|
|
|
673
|
-
#
|
|
778
|
+
# Create table with wrapped data
|
|
779
|
+
table = Table(wrapped_data, colWidths=col_widths, repeatRows=1)
|
|
780
|
+
|
|
781
|
+
# Style the table with dynamic formatting
|
|
674
782
|
table.setStyle(
|
|
675
783
|
TableStyle(
|
|
676
784
|
[
|
|
677
785
|
('BACKGROUND', (0, 0), (-1, 0), colors.grey),
|
|
678
|
-
('
|
|
679
|
-
('
|
|
680
|
-
('
|
|
681
|
-
('
|
|
682
|
-
('
|
|
683
|
-
('
|
|
684
|
-
('
|
|
685
|
-
('FONTSIZE', (0, 1), (-1, -1), 9),
|
|
686
|
-
('GRID', (0, 0), (-1, -1), 1, colors.black),
|
|
687
|
-
('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),
|
|
786
|
+
('BACKGROUND', (0, 1), (-1, -1), colors.white),
|
|
787
|
+
('GRID', (0, 0), (-1, -1), 0.5, colors.black),
|
|
788
|
+
('VALIGN', (0, 0), (-1, -1), 'TOP'),
|
|
789
|
+
('LEFTPADDING', (0, 0), (-1, -1), h_padding),
|
|
790
|
+
('RIGHTPADDING', (0, 0), (-1, -1), h_padding),
|
|
791
|
+
('TOPPADDING', (0, 0), (-1, -1), v_padding),
|
|
792
|
+
('BOTTOMPADDING', (0, 0), (-1, -1), v_padding),
|
|
688
793
|
]
|
|
689
794
|
)
|
|
690
795
|
)
|
|
691
796
|
|
|
692
|
-
logger.debug("Table created successfully")
|
|
693
797
|
return table
|
|
694
798
|
|
|
695
799
|
except Exception as e:
|
|
@@ -708,18 +812,20 @@ class FileWriteToolkit(BaseToolkit):
|
|
|
708
812
|
Returns:
|
|
709
813
|
str: Text with HTML formatting.
|
|
710
814
|
"""
|
|
711
|
-
#
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
815
|
+
# Define conversion patterns
|
|
816
|
+
conversions = [
|
|
817
|
+
(r'\*\*(.*?)\*\*', r'<b>\1</b>'), # Bold with **
|
|
818
|
+
(r'__(.*?)__', r'<b>\1</b>'), # Bold with __
|
|
819
|
+
(
|
|
820
|
+
r'(?<!\*)\*(?!\*)(.*?)(?<!\*)\*(?!\*)',
|
|
821
|
+
r'<i>\1</i>',
|
|
822
|
+
), # Italic with *
|
|
823
|
+
(r'(?<!_)_(?!_)(.*?)(?<!_)_(?!_)', r'<i>\1</i>'), # Italic with _
|
|
824
|
+
(r'`(.*?)`', r'<font name="Courier">\1</font>'), # Inline code
|
|
825
|
+
]
|
|
720
826
|
|
|
721
|
-
|
|
722
|
-
|
|
827
|
+
for pattern, replacement in conversions:
|
|
828
|
+
text = re.sub(pattern, replacement, text)
|
|
723
829
|
|
|
724
830
|
return text
|
|
725
831
|
|
|
@@ -745,7 +851,6 @@ class FileWriteToolkit(BaseToolkit):
|
|
|
745
851
|
else:
|
|
746
852
|
writer = csv.writer(f)
|
|
747
853
|
writer.writerows(content)
|
|
748
|
-
logger.debug(f"Wrote CSV to {file_path} with {encoding} encoding")
|
|
749
854
|
|
|
750
855
|
def _write_json_file(
|
|
751
856
|
self,
|
|
@@ -774,52 +879,19 @@ class FileWriteToolkit(BaseToolkit):
|
|
|
774
879
|
else:
|
|
775
880
|
# If not string, dump as JSON
|
|
776
881
|
json.dump(content, f, ensure_ascii=False)
|
|
777
|
-
logger.debug(f"Wrote JSON to {file_path} with {encoding} encoding")
|
|
778
|
-
|
|
779
|
-
def _write_yaml_file(
|
|
780
|
-
self,
|
|
781
|
-
file_path: Path,
|
|
782
|
-
content: str,
|
|
783
|
-
encoding: str = "utf-8",
|
|
784
|
-
) -> None:
|
|
785
|
-
r"""Write YAML content to a file.
|
|
786
|
-
|
|
787
|
-
Args:
|
|
788
|
-
file_path (Path): The target file path.
|
|
789
|
-
content (str): The YAML content as a string.
|
|
790
|
-
encoding (str): Character encoding to use. (default: :obj:`utf-8`)
|
|
791
|
-
"""
|
|
792
|
-
with file_path.open("w", encoding=encoding) as f:
|
|
793
|
-
f.write(content)
|
|
794
|
-
logger.debug(f"Wrote YAML to {file_path} with {encoding} encoding")
|
|
795
|
-
|
|
796
|
-
def _write_html_file(
|
|
797
|
-
self, file_path: Path, content: str, encoding: str = "utf-8"
|
|
798
|
-
) -> None:
|
|
799
|
-
r"""Write text content to an HTML file.
|
|
800
|
-
|
|
801
|
-
Args:
|
|
802
|
-
file_path (Path): The target file path.
|
|
803
|
-
content (str): The HTML content to write.
|
|
804
|
-
encoding (str): Character encoding to use. (default: :obj:`utf-8`)
|
|
805
|
-
"""
|
|
806
|
-
with file_path.open("w", encoding=encoding) as f:
|
|
807
|
-
f.write(content)
|
|
808
|
-
logger.debug(f"Wrote HTML to {file_path} with {encoding} encoding")
|
|
809
882
|
|
|
810
|
-
def
|
|
883
|
+
def _write_simple_text_file(
|
|
811
884
|
self, file_path: Path, content: str, encoding: str = "utf-8"
|
|
812
885
|
) -> None:
|
|
813
|
-
r"""Write text content to a Markdown
|
|
886
|
+
r"""Write text content to a file (used for HTML, Markdown, YAML, etc.).
|
|
814
887
|
|
|
815
888
|
Args:
|
|
816
889
|
file_path (Path): The target file path.
|
|
817
|
-
content (str): The
|
|
890
|
+
content (str): The content to write.
|
|
818
891
|
encoding (str): Character encoding to use. (default: :obj:`utf-8`)
|
|
819
892
|
"""
|
|
820
893
|
with file_path.open("w", encoding=encoding) as f:
|
|
821
894
|
f.write(content)
|
|
822
|
-
logger.debug(f"Wrote Markdown to {file_path} with {encoding} encoding")
|
|
823
895
|
|
|
824
896
|
def write_to_file(
|
|
825
897
|
self,
|
|
@@ -861,10 +933,10 @@ class FileWriteToolkit(BaseToolkit):
|
|
|
861
933
|
|
|
862
934
|
extension = file_path.suffix.lower()
|
|
863
935
|
|
|
864
|
-
# If no extension is provided, use
|
|
936
|
+
# If no extension is provided, use markdown as default
|
|
865
937
|
if extension == "":
|
|
866
|
-
file_path = file_path.with_suffix(
|
|
867
|
-
extension =
|
|
938
|
+
file_path = file_path.with_suffix('.md')
|
|
939
|
+
extension = '.md'
|
|
868
940
|
|
|
869
941
|
try:
|
|
870
942
|
# Get encoding or use default
|
|
@@ -884,16 +956,15 @@ class FileWriteToolkit(BaseToolkit):
|
|
|
884
956
|
content, # type: ignore[arg-type]
|
|
885
957
|
encoding=file_encoding,
|
|
886
958
|
)
|
|
887
|
-
elif extension in [
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
self._write_markdown_file(
|
|
959
|
+
elif extension in [
|
|
960
|
+
".yml",
|
|
961
|
+
".yaml",
|
|
962
|
+
".html",
|
|
963
|
+
".htm",
|
|
964
|
+
".md",
|
|
965
|
+
".markdown",
|
|
966
|
+
]:
|
|
967
|
+
self._write_simple_text_file(
|
|
897
968
|
file_path, str(content), encoding=file_encoding
|
|
898
969
|
)
|
|
899
970
|
else:
|
|
@@ -924,19 +995,3 @@ class FileWriteToolkit(BaseToolkit):
|
|
|
924
995
|
return [
|
|
925
996
|
FunctionTool(self.write_to_file),
|
|
926
997
|
]
|
|
927
|
-
|
|
928
|
-
def _sanitize_filename(self, filename: str) -> str:
|
|
929
|
-
r"""Sanitize a filename by replacing any character that is not
|
|
930
|
-
alphanumeric, a dot (.), hyphen (-), or underscore (_) with an
|
|
931
|
-
underscore (_).
|
|
932
|
-
|
|
933
|
-
Args:
|
|
934
|
-
filename (str): The original filename which may contain spaces or
|
|
935
|
-
special characters.
|
|
936
|
-
|
|
937
|
-
Returns:
|
|
938
|
-
str: The sanitized filename with disallowed characters replaced by
|
|
939
|
-
underscores.
|
|
940
|
-
"""
|
|
941
|
-
safe = re.sub(r'[^\w\-.]', '_', filename)
|
|
942
|
-
return safe
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
camel/__init__.py,sha256=
|
|
1
|
+
camel/__init__.py,sha256=C4KnIug_Cb0qJb805wzvImeQ7B3j-R9vyXl1apOfuXk,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
|
|
@@ -275,12 +275,12 @@ camel/societies/workforce/__init__.py,sha256=bkTI-PE-MSK9AQ2V2gR6cR2WY-R7Jqy_NmX
|
|
|
275
275
|
camel/societies/workforce/base.py,sha256=z2DmbTP5LL5-aCAAqglznQqCLfPmnyM5zD3w6jjtsb8,2175
|
|
276
276
|
camel/societies/workforce/prompts.py,sha256=gobVelz7rRdReogFG2QCfFy21GfhaQJyoiNnKWo4EHE,14391
|
|
277
277
|
camel/societies/workforce/role_playing_worker.py,sha256=z5-OcNiaNEaoC206_3HD7xeonuUkD-XTxYbD3AqoNC8,10319
|
|
278
|
-
camel/societies/workforce/single_agent_worker.py,sha256=
|
|
278
|
+
camel/societies/workforce/single_agent_worker.py,sha256=seWeFR-scpaTSS0yXwqJSJkUWaNuiYyuxDTfbpebRN8,17314
|
|
279
279
|
camel/societies/workforce/structured_output_handler.py,sha256=xr8szFN86hg3jQ825aEkJTjkSFQnTlbinVg4j1vZJVI,17870
|
|
280
280
|
camel/societies/workforce/task_channel.py,sha256=uqQQI67Tr4awbR4bjZXdx8_4gL6-ON5IjQk_H_ryqT4,7431
|
|
281
281
|
camel/societies/workforce/utils.py,sha256=THgNHSeZsNVnjTzQTur3qCJhi72MrDS8X2gPET174cI,8434
|
|
282
|
-
camel/societies/workforce/worker.py,sha256=
|
|
283
|
-
camel/societies/workforce/workforce.py,sha256=
|
|
282
|
+
camel/societies/workforce/worker.py,sha256=k_AokiF-HAfq6Cd5SQYb0uaoJsA_kSwV_n5o1fxvzmo,6522
|
|
283
|
+
camel/societies/workforce/workforce.py,sha256=FnBRW0sWBY3RyIBOAXw4BtOBYRS16LSM64pN0jr3B4c,133316
|
|
284
284
|
camel/societies/workforce/workforce_logger.py,sha256=0YT__ys48Bgn0IICKIZBmSWhON-eA1KShebjCdn5ppE,24525
|
|
285
285
|
camel/storages/__init__.py,sha256=RwpEyvxpMbJzVDZJJygeBg4AzyYMkTjjkfB53hTuqGo,2141
|
|
286
286
|
camel/storages/graph_storages/__init__.py,sha256=G29BNn651C0WTOpjCl4QnVM-4B9tcNh8DdmsCiONH8Y,948
|
|
@@ -332,7 +332,7 @@ camel/toolkits/dappier_toolkit.py,sha256=OEHOYXX_oXhgbVtWYAy13nO9uXf9i5qEXSwY4Pe
|
|
|
332
332
|
camel/toolkits/data_commons_toolkit.py,sha256=aHZUSL1ACpnYGaf1rE2csVKTmXTmN8lMGRUBYhZ_YEk,14168
|
|
333
333
|
camel/toolkits/edgeone_pages_mcp_toolkit.py,sha256=1TFpAGHUNLggFQeN1OEw7P5laijwnlrCkfxBtgxFuUY,2331
|
|
334
334
|
camel/toolkits/excel_toolkit.py,sha256=9Uk5GLWl719c4W-NcGPJTNMtodAbEE5gUgLsFkIInbk,32564
|
|
335
|
-
camel/toolkits/file_write_toolkit.py,sha256=
|
|
335
|
+
camel/toolkits/file_write_toolkit.py,sha256=_vQLjcM134-u6F0DmmTjUIgkcwMyFhVGtlwQlwmvhnU,36478
|
|
336
336
|
camel/toolkits/function_tool.py,sha256=xCDzjxTRCVj_kmbnMFBuwK-3NuzM4JNe_kv9HLtjnIA,33644
|
|
337
337
|
camel/toolkits/github_toolkit.py,sha256=iUyRrjWGAW_iljZVfNyfkm1Vi55wJxK6PsDAQs9pOag,13099
|
|
338
338
|
camel/toolkits/google_calendar_toolkit.py,sha256=E-sdgdbtNBs_CXbhht9t1dsVr4DsTr5NguHkx4fvSmc,15410
|
|
@@ -446,7 +446,7 @@ camel/verifiers/math_verifier.py,sha256=tA1D4S0sm8nsWISevxSN0hvSVtIUpqmJhzqfbuMo
|
|
|
446
446
|
camel/verifiers/models.py,sha256=GdxYPr7UxNrR1577yW4kyroRcLGfd-H1GXgv8potDWU,2471
|
|
447
447
|
camel/verifiers/physics_verifier.py,sha256=c1grrRddcrVN7szkxhv2QirwY9viIRSITWeWFF5HmLs,30187
|
|
448
448
|
camel/verifiers/python_verifier.py,sha256=ogTz77wODfEcDN4tMVtiSkRQyoiZbHPY2fKybn59lHw,20558
|
|
449
|
-
camel_ai-0.2.
|
|
450
|
-
camel_ai-0.2.
|
|
451
|
-
camel_ai-0.2.
|
|
452
|
-
camel_ai-0.2.
|
|
449
|
+
camel_ai-0.2.71a7.dist-info/METADATA,sha256=7RntrU6DFsIklapB4M50ShludXNyfdjpDEfIYBCnvi8,50002
|
|
450
|
+
camel_ai-0.2.71a7.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
451
|
+
camel_ai-0.2.71a7.dist-info/licenses/LICENSE,sha256=id0nB2my5kG0xXeimIu5zZrbHLS6EQvxvkKkzIHaT2k,11343
|
|
452
|
+
camel_ai-0.2.71a7.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|