camel-ai 0.2.68__py3-none-any.whl → 0.2.69a1__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 (36) hide show
  1. camel/__init__.py +1 -1
  2. camel/agents/chat_agent.py +170 -11
  3. camel/configs/vllm_config.py +2 -0
  4. camel/datagen/self_improving_cot.py +1 -1
  5. camel/memories/context_creators/score_based.py +129 -87
  6. camel/runtimes/configs.py +11 -11
  7. camel/runtimes/daytona_runtime.py +4 -4
  8. camel/runtimes/docker_runtime.py +6 -6
  9. camel/runtimes/remote_http_runtime.py +5 -5
  10. camel/societies/workforce/prompts.py +13 -12
  11. camel/societies/workforce/single_agent_worker.py +252 -22
  12. camel/societies/workforce/utils.py +10 -2
  13. camel/societies/workforce/worker.py +21 -45
  14. camel/societies/workforce/workforce.py +36 -15
  15. camel/tasks/task.py +18 -12
  16. camel/toolkits/__init__.py +2 -0
  17. camel/toolkits/aci_toolkit.py +19 -19
  18. camel/toolkits/arxiv_toolkit.py +6 -6
  19. camel/toolkits/dappier_toolkit.py +5 -5
  20. camel/toolkits/file_write_toolkit.py +10 -10
  21. camel/toolkits/github_toolkit.py +3 -3
  22. camel/toolkits/non_visual_browser_toolkit/__init__.py +18 -0
  23. camel/toolkits/non_visual_browser_toolkit/actions.py +196 -0
  24. camel/toolkits/non_visual_browser_toolkit/agent.py +278 -0
  25. camel/toolkits/non_visual_browser_toolkit/browser_non_visual_toolkit.py +363 -0
  26. camel/toolkits/non_visual_browser_toolkit/nv_browser_session.py +175 -0
  27. camel/toolkits/non_visual_browser_toolkit/snapshot.js +188 -0
  28. camel/toolkits/non_visual_browser_toolkit/snapshot.py +164 -0
  29. camel/toolkits/pptx_toolkit.py +4 -4
  30. camel/toolkits/sympy_toolkit.py +1 -1
  31. camel/toolkits/task_planning_toolkit.py +3 -3
  32. camel/toolkits/thinking_toolkit.py +1 -1
  33. {camel_ai-0.2.68.dist-info → camel_ai-0.2.69a1.dist-info}/METADATA +1 -1
  34. {camel_ai-0.2.68.dist-info → camel_ai-0.2.69a1.dist-info}/RECORD +36 -29
  35. {camel_ai-0.2.68.dist-info → camel_ai-0.2.69a1.dist-info}/WHEEL +0 -0
  36. {camel_ai-0.2.68.dist-info → camel_ai-0.2.69a1.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,175 @@
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
+ from __future__ import annotations
15
+
16
+ from pathlib import Path
17
+ from typing import TYPE_CHECKING, Any, Optional
18
+
19
+ from .actions import ActionExecutor
20
+ from .snapshot import PageSnapshot
21
+
22
+ if TYPE_CHECKING:
23
+ from playwright.async_api import (
24
+ Browser,
25
+ BrowserContext,
26
+ Page,
27
+ Playwright,
28
+ )
29
+
30
+
31
+ class NVBrowserSession:
32
+ """Lightweight wrapper around Playwright for non-visual (headless)
33
+ browsing.
34
+
35
+ It provides a single *Page* instance plus helper utilities (snapshot &
36
+ executor). Multiple toolkits or agents can reuse this class without
37
+ duplicating Playwright setup code.
38
+ """
39
+
40
+ # Configuration constants
41
+ DEFAULT_NAVIGATION_TIMEOUT = 10000 # 10 seconds
42
+ NETWORK_IDLE_TIMEOUT = 5000 # 5 seconds
43
+
44
+ def __init__(
45
+ self, *, headless: bool = True, user_data_dir: Optional[str] = None
46
+ ):
47
+ self._headless = headless
48
+ self._user_data_dir = user_data_dir
49
+
50
+ self._playwright: Optional[Playwright] = None
51
+ self._browser: Optional[Browser] = None
52
+ self._context: Optional[BrowserContext] = None
53
+ self._page: Optional[Page] = None
54
+
55
+ self.snapshot: Optional[PageSnapshot] = None
56
+ self.executor: Optional[ActionExecutor] = None
57
+
58
+ # ------------------------------------------------------------------
59
+ # Browser lifecycle helpers
60
+ # ------------------------------------------------------------------
61
+ async def ensure_browser(self) -> None:
62
+ from playwright.async_api import async_playwright
63
+
64
+ if self._page is not None:
65
+ return
66
+
67
+ self._playwright = await async_playwright().start()
68
+ if self._user_data_dir:
69
+ Path(self._user_data_dir).mkdir(parents=True, exist_ok=True)
70
+ pl = self._playwright
71
+ assert pl is not None
72
+ self._context = await pl.chromium.launch_persistent_context(
73
+ user_data_dir=self._user_data_dir,
74
+ headless=self._headless,
75
+ )
76
+ self._browser = self._context.browser
77
+ else:
78
+ pl = self._playwright
79
+ assert pl is not None
80
+ self._browser = await pl.chromium.launch(headless=self._headless)
81
+ self._context = await self._browser.new_context()
82
+
83
+ # Reuse an already open page (persistent context may restore last
84
+ # session)
85
+ if self._context.pages:
86
+ self._page = self._context.pages[0]
87
+ else:
88
+ self._page = await self._context.new_page()
89
+ # helpers
90
+ self.snapshot = PageSnapshot(self._page)
91
+ self.executor = ActionExecutor(self._page)
92
+
93
+ async def close(self) -> None:
94
+ r"""Close all browser resources, ensuring cleanup even if some
95
+ operations fail.
96
+ """
97
+ errors: list[str] = []
98
+
99
+ # Close context first (which closes pages)
100
+ if self._context is not None:
101
+ try:
102
+ await self._context.close()
103
+ except Exception as e:
104
+ errors.append(f"Context close error: {e}")
105
+
106
+ # Close browser
107
+ if self._browser is not None:
108
+ try:
109
+ await self._browser.close()
110
+ except Exception as e:
111
+ errors.append(f"Browser close error: {e}")
112
+
113
+ # Stop playwright
114
+ if self._playwright is not None:
115
+ try:
116
+ await self._playwright.stop()
117
+ except Exception as e:
118
+ errors.append(f"Playwright stop error: {e}")
119
+
120
+ # Reset all references
121
+ self._playwright = self._browser = self._context = self._page = None
122
+ self.snapshot = self.executor = None
123
+
124
+ # Log errors if any occurred during cleanup
125
+ if errors:
126
+ from camel.logger import get_logger
127
+
128
+ logger = get_logger(__name__)
129
+ logger.warning(
130
+ "Errors during browser session cleanup: %s", "; ".join(errors)
131
+ )
132
+
133
+ # ------------------------------------------------------------------
134
+ # Convenience wrappers around common actions
135
+ # ------------------------------------------------------------------
136
+ async def visit(self, url: str) -> str:
137
+ await self.ensure_browser()
138
+ assert self._page is not None
139
+
140
+ try:
141
+ await self._page.goto(
142
+ url,
143
+ wait_until="domcontentloaded",
144
+ timeout=self.DEFAULT_NAVIGATION_TIMEOUT,
145
+ )
146
+ # Try to wait for network idle, but don't fail if it times out
147
+ try:
148
+ await self._page.wait_for_load_state(
149
+ "networkidle", timeout=self.NETWORK_IDLE_TIMEOUT
150
+ )
151
+ except Exception:
152
+ pass # Network idle timeout is not critical
153
+ return f"Visited {url}"
154
+ except Exception as e:
155
+ return f"Error visiting {url}: {e}"
156
+
157
+ async def get_snapshot(
158
+ self, *, force_refresh: bool = False, diff_only: bool = False
159
+ ) -> str:
160
+ await self.ensure_browser()
161
+ assert self.snapshot is not None
162
+ return await self.snapshot.capture(
163
+ force_refresh=force_refresh, diff_only=diff_only
164
+ )
165
+
166
+ async def exec_action(self, action: dict[str, Any]) -> str:
167
+ await self.ensure_browser()
168
+ assert self.executor is not None
169
+ return await self.executor.execute(action)
170
+
171
+ # Low-level accessors -------------------------------------------------
172
+ async def get_page(self) -> "Page":
173
+ await self.ensure_browser()
174
+ assert self._page is not None
175
+ return self._page
@@ -0,0 +1,188 @@
1
+ (() => {
2
+ // Store each element as {text, priority, depth}
3
+ const elements = [];
4
+
5
+ // Maximum lines allowed before we start dropping lower-priority nodes
6
+ const MAX_LINES = 400;
7
+
8
+ // Priority helper – lower number = higher priority
9
+ function getPriority(tag, role, text) {
10
+ // 1. Interactive elements
11
+ if (["input", "button", "a", "select", "textarea"].includes(tag)) return 1;
12
+ if (["checkbox", "radio"].includes(role)) return 1;
13
+
14
+ // 2. Labels / descriptive adjacent text (label elements)
15
+ if (tag === "label") return 2;
16
+
17
+ // 3. General visible text
18
+ if (text) return 3;
19
+
20
+ // 4. Low-value structural nodes
21
+ return 4;
22
+ }
23
+
24
+ function isVisible(node) {
25
+ const rect = node.getBoundingClientRect();
26
+ if (rect.width === 0 || rect.height === 0) return false;
27
+
28
+ const style = window.getComputedStyle(node);
29
+ if (style.display === 'none' || style.visibility === 'hidden') return false;
30
+
31
+ return true;
32
+ }
33
+
34
+ function getRole(node) {
35
+ const tag = node.tagName.toLowerCase();
36
+ const type = node.getAttribute('type');
37
+
38
+ if (node.getAttribute('role')) return node.getAttribute('role');
39
+
40
+ if (tag === 'input') {
41
+ if (type === 'checkbox') return 'checkbox';
42
+ if (type === 'radio') return 'radio';
43
+ return 'input';
44
+ }
45
+
46
+ if (tag === 'button') return 'button';
47
+ if (tag === 'a') return 'link';
48
+ if (tag === 'select') return 'select';
49
+ if (tag === 'textarea') return 'textarea';
50
+ if (tag === 'p') return 'paragraph';
51
+ if (tag === 'span') return 'text';
52
+
53
+ return 'generic';
54
+ }
55
+
56
+ function getAccessibleName(node) {
57
+ if (node.hasAttribute('aria-label')) {
58
+ return node.getAttribute('aria-label');
59
+ }
60
+ if (node.hasAttribute('aria-labelledby')) {
61
+ const id = node.getAttribute('aria-labelledby');
62
+ const labelEl = document.getElementById(id);
63
+ if (labelEl) return labelEl.textContent.trim();
64
+ }
65
+ if (node.hasAttribute('title')) {
66
+ return node.getAttribute('title');
67
+ }
68
+
69
+ const tagName = node.tagName?.toLowerCase();
70
+ if (['style', 'script', 'meta', 'noscript', 'svg'].includes(tagName)) {
71
+ return '';
72
+ }
73
+
74
+ const text = node.textContent?.trim() || '';
75
+
76
+ // Ignore styles, tokens, or long CSS-like expressions
77
+ if (/^[.#]?[a-zA-Z0-9\-_]+\s*\{[^}]*\}/.test(text)) return '';
78
+ if ((text.match(/[;:{}]/g)?.length || 0) > 2) return '';
79
+
80
+ return text.replace(/[^\w\u4e00-\u9fa5\s\-.,?!'"()()]/g, '').trim();
81
+ }
82
+
83
+ let refCounter = 1;
84
+
85
+ function traverse(node, depth) {
86
+ if (node.nodeType !== Node.ELEMENT_NODE) return;
87
+ if (!isVisible(node)) return;
88
+
89
+ const tagName = node.tagName.toLowerCase();
90
+ const text = getAccessibleName(node).slice(0, 50);
91
+
92
+ // Skip unlabeled links (anchors without any accessible name)
93
+ if (tagName === 'a' && !text) {
94
+ // Skip unlabeled links; process children if any
95
+ for (const child of node.children) {
96
+ traverse(child, depth + 1);
97
+ }
98
+ return;
99
+ }
100
+
101
+ const hasRoleOrText = ['button', 'a', 'input', 'select', 'textarea', 'p', 'span'].includes(tagName) ||
102
+ node.getAttribute('role') || text;
103
+
104
+ if (hasRoleOrText) {
105
+ const role = getRole(node);
106
+ const ref = `e${refCounter++}`;
107
+ const label = text ? `"${text}"` : '';
108
+
109
+ // Raw line (without indent) – we will apply indentation later once we know
110
+ // which ancestor lines survive filtering so that indentation always reflects
111
+ // the visible hierarchy.
112
+ const lineText = `- ${role}${label ? ` ${label}` : ''} [ref=${ref}]`;
113
+ const priority = getPriority(tagName, role, text);
114
+
115
+ elements.push({ text: lineText, priority, depth });
116
+
117
+ // Always inject ref so Playwright can still locate the element even if line is later filtered out.
118
+ node.setAttribute('aria-ref', ref);
119
+ }
120
+
121
+ for (const child of node.children) {
122
+ traverse(child, depth + 1);
123
+ }
124
+ }
125
+
126
+ function processDocument(doc, depth = 0) {
127
+ try {
128
+ traverse(doc.body, depth);
129
+ } catch (e) {
130
+ // Handle docs without body (e.g., about:blank)
131
+ }
132
+
133
+ const frames = doc.querySelectorAll('iframe');
134
+ for (const frame of frames) {
135
+ try {
136
+ if (frame.contentDocument) {
137
+ processDocument(frame.contentDocument, depth + 1);
138
+ }
139
+ } catch (e) {
140
+ // Skip cross-origin iframes
141
+ }
142
+ }
143
+ }
144
+
145
+ processDocument(document);
146
+
147
+ // Always drop priority-4 nodes (low-value structural or invisible)
148
+ let finalElements = elements.filter(el => el.priority <= 3);
149
+
150
+ // Additional size condensation when still exceeding MAX_LINES
151
+ if (finalElements.length > MAX_LINES) {
152
+ const filterBy = (maxPriority) => finalElements.filter(el => el.priority <= maxPriority);
153
+
154
+ // Progressively tighten: keep 1-3, then 1-2, finally only 1
155
+ for (const limit of [3, 2, 1]) {
156
+ const candidate = filterBy(limit);
157
+ if (candidate.length <= MAX_LINES || limit === 1) {
158
+ finalElements = candidate;
159
+ break;
160
+ }
161
+ }
162
+ }
163
+
164
+ // ------------------------------------------------------------------
165
+ // Re-apply indentation so that it matches the *visible* hierarchy only.
166
+ // Whenever an ancestor element is removed due to priority rules, its
167
+ // children will be re-indented one level up so the structure remains
168
+ // intuitive.
169
+ // ------------------------------------------------------------------
170
+ const outputLines = [];
171
+ const depthStack = []; // keeps track of kept original depths
172
+
173
+ for (const el of finalElements) {
174
+ // Pop depths that are not ancestors of current element
175
+ while (depthStack.length && depthStack[depthStack.length - 1] >= el.depth) {
176
+ depthStack.pop();
177
+ }
178
+
179
+ // Push the current depth so future descendants know their ancestor chain
180
+ depthStack.push(el.depth);
181
+
182
+ const compressedDepth = depthStack.length - 1; // root level has zero indent
183
+ const indent = '\t'.repeat(compressedDepth);
184
+ outputLines.push(indent + el.text);
185
+ }
186
+
187
+ return outputLines.join('\n');
188
+ })();
@@ -0,0 +1,164 @@
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
+ from pathlib import Path
15
+ from typing import TYPE_CHECKING, Dict, List, Optional
16
+
17
+ if TYPE_CHECKING:
18
+ from playwright.async_api import Page
19
+
20
+ # Logging support
21
+ from camel.logger import get_logger
22
+
23
+ logger = get_logger(__name__)
24
+
25
+
26
+ class PageSnapshot:
27
+ """Utility for capturing YAML-like page snapshots and diff-only
28
+ variants."""
29
+
30
+ MAX_TIMEOUT_MS = 5000 # wait_for_load_state timeout
31
+
32
+ def __init__(self, page: "Page"):
33
+ self.page = page
34
+ self.snapshot_data: Optional[str] = None # last full snapshot
35
+ self._last_url: Optional[str] = None
36
+ self.last_info: Dict[str, List[int] | bool] = {
37
+ "is_diff": False,
38
+ "priorities": [1, 2, 3],
39
+ }
40
+
41
+ # ---------------------------------------------------------------------
42
+ # Public API
43
+ # ---------------------------------------------------------------------
44
+ async def capture(
45
+ self, *, force_refresh: bool = False, diff_only: bool = False
46
+ ) -> str:
47
+ """Return current snapshot or just the diff to previous one."""
48
+ try:
49
+ current_url = self.page.url
50
+
51
+ # Serve cached copy (unless diff requested)
52
+ if (
53
+ not force_refresh
54
+ and current_url == self._last_url
55
+ and self.snapshot_data
56
+ and not diff_only
57
+ ):
58
+ return self.snapshot_data
59
+
60
+ # ensure DOM stability
61
+ await self.page.wait_for_load_state(
62
+ 'domcontentloaded', timeout=self.MAX_TIMEOUT_MS
63
+ )
64
+
65
+ logger.debug("Capturing page snapshot …")
66
+ snapshot_text = await self._get_snapshot_direct()
67
+ formatted = self._format_snapshot(snapshot_text or "<empty>")
68
+
69
+ output = formatted
70
+ if diff_only and self.snapshot_data:
71
+ output = self._compute_diff(self.snapshot_data, formatted)
72
+
73
+ # update cache with *full* snapshot (not diff)
74
+ self._last_url = current_url
75
+ self.snapshot_data = formatted
76
+
77
+ # analyse priorities present (only for non-diff)
78
+ priorities_included = self._detect_priorities(
79
+ formatted if not diff_only else self.snapshot_data or formatted
80
+ )
81
+ self.last_info = {
82
+ "is_diff": diff_only and self.snapshot_data is not None,
83
+ "priorities": priorities_included,
84
+ }
85
+
86
+ logger.debug(
87
+ "Snapshot captured. Diff_only=%s, priorities=%s",
88
+ diff_only,
89
+ self.last_info["priorities"],
90
+ )
91
+ return output
92
+ except Exception as exc:
93
+ logger.error("Snapshot capture failed: %s", exc)
94
+ return f"Error: Could not capture page snapshot {exc}"
95
+
96
+ # ------------------------------------------------------------------
97
+ # Internal helpers
98
+ # ------------------------------------------------------------------
99
+ _snapshot_js_cache: Optional[str] = None # class-level cache
100
+
101
+ async def _get_snapshot_direct(self) -> Optional[str]:
102
+ try:
103
+ if PageSnapshot._snapshot_js_cache is None:
104
+ js_path = Path(__file__).parent / "snapshot.js"
105
+ PageSnapshot._snapshot_js_cache = js_path.read_text(
106
+ encoding="utf-8"
107
+ )
108
+ return await self.page.evaluate(PageSnapshot._snapshot_js_cache)
109
+ except Exception as e:
110
+ logger.warning("Failed to execute snapshot JavaScript: %s", e)
111
+ return None
112
+
113
+ @staticmethod
114
+ def _format_snapshot(text: str) -> str:
115
+ return "\n".join(["- Page Snapshot", "```yaml", text, "```"])
116
+
117
+ @staticmethod
118
+ def _compute_diff(old: str, new: str) -> str:
119
+ if not old or not new:
120
+ return "- Page Snapshot (error: missing data for diff)"
121
+
122
+ import difflib
123
+
124
+ diff = list(
125
+ difflib.unified_diff(
126
+ old.splitlines(False),
127
+ new.splitlines(False),
128
+ fromfile='prev',
129
+ tofile='curr',
130
+ lineterm='',
131
+ )
132
+ )
133
+ if not diff:
134
+ return "- Page Snapshot (no structural changes)"
135
+ return "\n".join(["- Page Snapshot (diff)", "```diff", *diff, "```"])
136
+
137
+ # ------------------------------------------------------------------
138
+ def _detect_priorities(self, snapshot_yaml: str) -> List[int]:
139
+ """Return sorted list of priorities present (1,2,3)."""
140
+ priorities = set()
141
+ for line in snapshot_yaml.splitlines():
142
+ if '[ref=' not in line:
143
+ continue
144
+ lower_line = line.lower()
145
+ if any(
146
+ r in lower_line
147
+ for r in (
148
+ "input",
149
+ "button",
150
+ "select",
151
+ "textarea",
152
+ "checkbox",
153
+ "radio",
154
+ "link",
155
+ )
156
+ ):
157
+ priorities.add(1)
158
+ elif 'label' in lower_line:
159
+ priorities.add(2)
160
+ else:
161
+ priorities.add(3)
162
+ if not priorities:
163
+ priorities.add(3)
164
+ return sorted(priorities)
@@ -62,7 +62,7 @@ class PPTXToolkit(BaseToolkit):
62
62
  output_dir (str): The default directory for output files.
63
63
  Defaults to the current working directory.
64
64
  timeout (Optional[float]): The timeout for the toolkit.
65
- (default: :obj: `None`)
65
+ (default: :obj:`None`)
66
66
  """
67
67
  super().__init__(timeout=timeout)
68
68
  self.output_dir = Path(output_dir).resolve()
@@ -120,7 +120,7 @@ class PPTXToolkit(BaseToolkit):
120
120
  frame_paragraph: The paragraph to format.
121
121
  text (str): The text to format.
122
122
  set_color_to_white (bool): Whether to set the color to white.
123
- (default: :obj: `False`)
123
+ (default: :obj:`False`)
124
124
  """
125
125
  from pptx.dml.color import RGBColor
126
126
 
@@ -170,7 +170,7 @@ class PPTXToolkit(BaseToolkit):
170
170
  flat_items_list (List[Tuple[str, int]]): The list of items to be
171
171
  displayed.
172
172
  set_color_to_white (bool): Whether to set the font color to white.
173
- (default: :obj: `False`)
173
+ (default: :obj:`False`)
174
174
  """
175
175
  if not flat_items_list:
176
176
  logger.warning("Empty bullet point list provided")
@@ -368,7 +368,7 @@ class PPTXToolkit(BaseToolkit):
368
368
  supplied, it is resolved to self.output_dir.
369
369
  template (Optional[str]): The path to the template PPTX file.
370
370
  Initializes a presentation from a given template file Or PPTX
371
- file. (default: :obj: `None`)
371
+ file. (default: :obj:`None`)
372
372
 
373
373
  Returns:
374
374
  str: A success message indicating the file was created.
@@ -39,7 +39,7 @@ class SymPyToolkit(BaseToolkit):
39
39
 
40
40
  Args:
41
41
  default_variable (str): The default variable for
42
- operations (default: :obj: `x`)
42
+ operations (default: :obj:`x`)
43
43
  """
44
44
  super().__init__(timeout=timeout)
45
45
  self.default_variable = default_variable
@@ -32,7 +32,7 @@ class TaskPlanningToolkit(BaseToolkit):
32
32
 
33
33
  Args:
34
34
  timeout (Optional[float]): The timeout for the toolkit.
35
- (default: :obj: `None`)
35
+ (default: :obj:`None`)
36
36
  """
37
37
  super().__init__(timeout=timeout)
38
38
 
@@ -53,7 +53,7 @@ class TaskPlanningToolkit(BaseToolkit):
53
53
  string is the content for a new sub-task.
54
54
  original_task_id (Optional[str]): The id of the task to be
55
55
  decomposed. If not provided, a new id will be generated.
56
- (default: :obj: `None`)
56
+ (default: :obj:`None`)
57
57
 
58
58
  Returns:
59
59
  List[Task]: A list of newly created sub-task objects.
@@ -99,7 +99,7 @@ class TaskPlanningToolkit(BaseToolkit):
99
99
  sub_task_contents (List[str]): A list of strings, where each
100
100
  string is the content for a new sub-task.
101
101
  original_task_id (Optional[str]): The id of the task to be
102
- decomposed. (default: :obj: `None`)
102
+ decomposed. (default: :obj:`None`)
103
103
 
104
104
  Returns:
105
105
  List[Task]: Reordered or modified tasks.
@@ -32,7 +32,7 @@ class ThinkingToolkit(BaseToolkit):
32
32
 
33
33
  Args:
34
34
  timeout (Optional[float]): The timeout for the toolkit.
35
- (default: :obj: `None`)
35
+ (default: :obj:`None`)
36
36
  """
37
37
  super().__init__(timeout=timeout)
38
38
  self.plans: List[str] = []
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: camel-ai
3
- Version: 0.2.68
3
+ Version: 0.2.69a1
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