praisonaiagents 0.0.18__tar.gz → 0.0.20__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
Files changed (27) hide show
  1. {praisonaiagents-0.0.18 → praisonaiagents-0.0.20}/PKG-INFO +1 -1
  2. {praisonaiagents-0.0.18 → praisonaiagents-0.0.20}/praisonaiagents/__init__.py +4 -2
  3. praisonaiagents-0.0.20/praisonaiagents/main.py +349 -0
  4. {praisonaiagents-0.0.18 → praisonaiagents-0.0.20}/praisonaiagents.egg-info/PKG-INFO +1 -1
  5. {praisonaiagents-0.0.18 → praisonaiagents-0.0.20}/pyproject.toml +1 -1
  6. praisonaiagents-0.0.18/praisonaiagents/main.py +0 -206
  7. {praisonaiagents-0.0.18 → praisonaiagents-0.0.20}/praisonaiagents/agent/__init__.py +0 -0
  8. {praisonaiagents-0.0.18 → praisonaiagents-0.0.20}/praisonaiagents/agent/agent.py +0 -0
  9. {praisonaiagents-0.0.18 → praisonaiagents-0.0.20}/praisonaiagents/agents/__init__.py +0 -0
  10. {praisonaiagents-0.0.18 → praisonaiagents-0.0.20}/praisonaiagents/agents/agents.py +0 -0
  11. {praisonaiagents-0.0.18 → praisonaiagents-0.0.20}/praisonaiagents/build/lib/praisonaiagents/__init__.py +0 -0
  12. {praisonaiagents-0.0.18 → praisonaiagents-0.0.20}/praisonaiagents/build/lib/praisonaiagents/agent/__init__.py +0 -0
  13. {praisonaiagents-0.0.18 → praisonaiagents-0.0.20}/praisonaiagents/build/lib/praisonaiagents/agent/agent.py +0 -0
  14. {praisonaiagents-0.0.18 → praisonaiagents-0.0.20}/praisonaiagents/build/lib/praisonaiagents/agents/__init__.py +0 -0
  15. {praisonaiagents-0.0.18 → praisonaiagents-0.0.20}/praisonaiagents/build/lib/praisonaiagents/agents/agents.py +0 -0
  16. {praisonaiagents-0.0.18 → praisonaiagents-0.0.20}/praisonaiagents/build/lib/praisonaiagents/main.py +0 -0
  17. {praisonaiagents-0.0.18 → praisonaiagents-0.0.20}/praisonaiagents/build/lib/praisonaiagents/task/__init__.py +0 -0
  18. {praisonaiagents-0.0.18 → praisonaiagents-0.0.20}/praisonaiagents/build/lib/praisonaiagents/task/task.py +0 -0
  19. {praisonaiagents-0.0.18 → praisonaiagents-0.0.20}/praisonaiagents/process/__init__.py +0 -0
  20. {praisonaiagents-0.0.18 → praisonaiagents-0.0.20}/praisonaiagents/process/process.py +0 -0
  21. {praisonaiagents-0.0.18 → praisonaiagents-0.0.20}/praisonaiagents/task/__init__.py +0 -0
  22. {praisonaiagents-0.0.18 → praisonaiagents-0.0.20}/praisonaiagents/task/task.py +0 -0
  23. {praisonaiagents-0.0.18 → praisonaiagents-0.0.20}/praisonaiagents.egg-info/SOURCES.txt +0 -0
  24. {praisonaiagents-0.0.18 → praisonaiagents-0.0.20}/praisonaiagents.egg-info/dependency_links.txt +0 -0
  25. {praisonaiagents-0.0.18 → praisonaiagents-0.0.20}/praisonaiagents.egg-info/requires.txt +0 -0
  26. {praisonaiagents-0.0.18 → praisonaiagents-0.0.20}/praisonaiagents.egg-info/top_level.txt +0 -0
  27. {praisonaiagents-0.0.18 → praisonaiagents-0.0.20}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: praisonaiagents
3
- Version: 0.0.18
3
+ Version: 0.0.20
4
4
  Summary: Praison AI agents for completing complex tasks with Self Reflection Agents
5
5
  Author: Mervin Praison
6
6
  Requires-Dist: pydantic
@@ -17,7 +17,8 @@ from .main import (
17
17
  clean_triple_backticks,
18
18
  error_logs,
19
19
  register_display_callback,
20
- display_callbacks,
20
+ sync_display_callbacks,
21
+ async_display_callbacks,
21
22
  )
22
23
 
23
24
  __all__ = [
@@ -35,5 +36,6 @@ __all__ = [
35
36
  'clean_triple_backticks',
36
37
  'error_logs',
37
38
  'register_display_callback',
38
- 'display_callbacks',
39
+ 'sync_display_callbacks',
40
+ 'async_display_callbacks',
39
41
  ]
@@ -0,0 +1,349 @@
1
+ import os
2
+ import time
3
+ import json
4
+ import logging
5
+ from typing import List, Optional, Dict, Any, Union, Literal, Type
6
+ from openai import OpenAI
7
+ from pydantic import BaseModel
8
+ from rich import print
9
+ from rich.console import Console
10
+ from rich.panel import Panel
11
+ from rich.text import Text
12
+ from rich.markdown import Markdown
13
+ from rich.logging import RichHandler
14
+ from rich.live import Live
15
+ import asyncio
16
+
17
+ LOGLEVEL = os.environ.get('LOGLEVEL', 'INFO').upper()
18
+
19
+ logging.basicConfig(
20
+ level=getattr(logging, LOGLEVEL, logging.INFO),
21
+ format="%(asctime)s %(filename)s:%(lineno)d %(levelname)s %(message)s",
22
+ datefmt="[%X]",
23
+ handlers=[RichHandler(rich_tracebacks=True)]
24
+ )
25
+
26
+ # Global list to store error logs
27
+ error_logs = []
28
+
29
+ # Separate registries for sync and async callbacks
30
+ sync_display_callbacks = {}
31
+ async_display_callbacks = {}
32
+
33
+ # At the top of the file, add display_callbacks to __all__
34
+ __all__ = [
35
+ 'error_logs',
36
+ 'register_display_callback',
37
+ 'sync_display_callbacks',
38
+ 'async_display_callbacks',
39
+ # ... other exports
40
+ ]
41
+
42
+ def register_display_callback(display_type: str, callback_fn, is_async: bool = False):
43
+ """Register a synchronous or asynchronous callback function for a specific display type.
44
+
45
+ Args:
46
+ display_type (str): Type of display event ('interaction', 'self_reflection', etc.)
47
+ callback_fn: The callback function to register
48
+ is_async (bool): Whether the callback is asynchronous
49
+ """
50
+ if is_async:
51
+ async_display_callbacks[display_type] = callback_fn
52
+ else:
53
+ sync_display_callbacks[display_type] = callback_fn
54
+
55
+ async def execute_callback(display_type: str, **kwargs):
56
+ """Execute both sync and async callbacks for a given display type.
57
+
58
+ Args:
59
+ display_type (str): Type of display event
60
+ **kwargs: Arguments to pass to the callback functions
61
+ """
62
+ # Execute synchronous callback if registered
63
+ if display_type in sync_display_callbacks:
64
+ callback = sync_display_callbacks[display_type]
65
+ loop = asyncio.get_event_loop()
66
+ await loop.run_in_executor(None, lambda: callback(**kwargs))
67
+
68
+ # Execute asynchronous callback if registered
69
+ if display_type in async_display_callbacks:
70
+ callback = async_display_callbacks[display_type]
71
+ await callback(**kwargs)
72
+
73
+ def _clean_display_content(content: str, max_length: int = 20000) -> str:
74
+ """Helper function to clean and truncate content for display."""
75
+ if not content or not str(content).strip():
76
+ return ""
77
+
78
+ content = str(content)
79
+ # Handle base64 content
80
+ if "base64" in content:
81
+ content_parts = []
82
+ for line in content.split('\n'):
83
+ if "base64" not in line:
84
+ content_parts.append(line)
85
+ content = '\n'.join(content_parts)
86
+
87
+ # Truncate if too long
88
+ if len(content) > max_length:
89
+ content = content[:max_length] + "..."
90
+
91
+ return content.strip()
92
+
93
+ def display_interaction(message, response, markdown=True, generation_time=None, console=None):
94
+ """Synchronous version of display_interaction."""
95
+ if console is None:
96
+ console = Console()
97
+
98
+ if isinstance(message, list):
99
+ text_content = next((item["text"] for item in message if item["type"] == "text"), "")
100
+ message = text_content
101
+
102
+ message = _clean_display_content(str(message))
103
+ response = _clean_display_content(str(response))
104
+
105
+ # Execute synchronous callback if registered
106
+ if 'interaction' in sync_display_callbacks:
107
+ sync_display_callbacks['interaction'](
108
+ message=message,
109
+ response=response,
110
+ markdown=markdown,
111
+ generation_time=generation_time
112
+ )
113
+
114
+ # Rest of the display logic...
115
+ if generation_time:
116
+ console.print(Text(f"Response generated in {generation_time:.1f}s", style="dim"))
117
+
118
+ if markdown:
119
+ console.print(Panel.fit(Markdown(message), title="Message", border_style="cyan"))
120
+ console.print(Panel.fit(Markdown(response), title="Response", border_style="cyan"))
121
+ else:
122
+ console.print(Panel.fit(Text(message, style="bold green"), title="Message", border_style="cyan"))
123
+ console.print(Panel.fit(Text(response, style="bold blue"), title="Response", border_style="cyan"))
124
+
125
+ def display_self_reflection(message: str, console=None):
126
+ if not message or not message.strip():
127
+ return
128
+ if console is None:
129
+ console = Console()
130
+ message = _clean_display_content(str(message))
131
+
132
+ # Execute callback if registered
133
+ if 'self_reflection' in sync_display_callbacks:
134
+ sync_display_callbacks['self_reflection'](message=message)
135
+
136
+ console.print(Panel.fit(Text(message, style="bold yellow"), title="Self Reflection", border_style="magenta"))
137
+
138
+ def display_instruction(message: str, console=None):
139
+ if not message or not message.strip():
140
+ return
141
+ if console is None:
142
+ console = Console()
143
+ message = _clean_display_content(str(message))
144
+
145
+ # Execute callback if registered
146
+ if 'instruction' in sync_display_callbacks:
147
+ sync_display_callbacks['instruction'](message=message)
148
+
149
+ console.print(Panel.fit(Text(message, style="bold blue"), title="Instruction", border_style="cyan"))
150
+
151
+ def display_tool_call(message: str, console=None):
152
+ if not message or not message.strip():
153
+ return
154
+ if console is None:
155
+ console = Console()
156
+ message = _clean_display_content(str(message))
157
+
158
+ # Execute callback if registered
159
+ if 'tool_call' in sync_display_callbacks:
160
+ sync_display_callbacks['tool_call'](message=message)
161
+
162
+ console.print(Panel.fit(Text(message, style="bold cyan"), title="Tool Call", border_style="green"))
163
+
164
+ def display_error(message: str, console=None):
165
+ if not message or not message.strip():
166
+ return
167
+ if console is None:
168
+ console = Console()
169
+ message = _clean_display_content(str(message))
170
+
171
+ # Execute callback if registered
172
+ if 'error' in sync_display_callbacks:
173
+ sync_display_callbacks['error'](message=message)
174
+
175
+ console.print(Panel.fit(Text(message, style="bold red"), title="Error", border_style="red"))
176
+ error_logs.append(message)
177
+
178
+ def display_generating(content: str = "", start_time: Optional[float] = None):
179
+ if not content or not str(content).strip():
180
+ return Panel("", title="", border_style="green")
181
+
182
+ elapsed_str = ""
183
+ if start_time is not None:
184
+ elapsed = time.time() - start_time
185
+ elapsed_str = f" {elapsed:.1f}s"
186
+
187
+ content = _clean_display_content(str(content))
188
+
189
+ # Execute callback if registered
190
+ if 'generating' in sync_display_callbacks:
191
+ sync_display_callbacks['generating'](
192
+ content=content,
193
+ elapsed_time=elapsed_str.strip() if elapsed_str else None
194
+ )
195
+
196
+ return Panel(Markdown(content), title=f"Generating...{elapsed_str}", border_style="green")
197
+
198
+ # Async versions with 'a' prefix
199
+ async def adisplay_interaction(message, response, markdown=True, generation_time=None, console=None):
200
+ """Async version of display_interaction."""
201
+ if console is None:
202
+ console = Console()
203
+
204
+ if isinstance(message, list):
205
+ text_content = next((item["text"] for item in message if item["type"] == "text"), "")
206
+ message = text_content
207
+
208
+ message = _clean_display_content(str(message))
209
+ response = _clean_display_content(str(response))
210
+
211
+ # Execute callbacks
212
+ await execute_callback(
213
+ 'interaction',
214
+ message=message,
215
+ response=response,
216
+ markdown=markdown,
217
+ generation_time=generation_time
218
+ )
219
+
220
+ # Rest of the display logic...
221
+ if generation_time:
222
+ console.print(Text(f"Response generated in {generation_time:.1f}s", style="dim"))
223
+
224
+ if markdown:
225
+ console.print(Panel.fit(Markdown(message), title="Message", border_style="cyan"))
226
+ console.print(Panel.fit(Markdown(response), title="Response", border_style="cyan"))
227
+ else:
228
+ console.print(Panel.fit(Text(message, style="bold green"), title="Message", border_style="cyan"))
229
+ console.print(Panel.fit(Text(response, style="bold blue"), title="Response", border_style="cyan"))
230
+
231
+ async def adisplay_self_reflection(message: str, console=None):
232
+ """Async version of display_self_reflection."""
233
+ if not message or not message.strip():
234
+ return
235
+ if console is None:
236
+ console = Console()
237
+ message = _clean_display_content(str(message))
238
+
239
+ if 'self_reflection' in async_display_callbacks:
240
+ await async_display_callbacks['self_reflection'](message=message)
241
+
242
+ console.print(Panel.fit(Text(message, style="bold yellow"), title="Self Reflection", border_style="magenta"))
243
+
244
+ async def adisplay_instruction(message: str, console=None):
245
+ """Async version of display_instruction."""
246
+ if not message or not message.strip():
247
+ return
248
+ if console is None:
249
+ console = Console()
250
+ message = _clean_display_content(str(message))
251
+
252
+ if 'instruction' in async_display_callbacks:
253
+ await async_display_callbacks['instruction'](message=message)
254
+
255
+ console.print(Panel.fit(Text(message, style="bold blue"), title="Instruction", border_style="cyan"))
256
+
257
+ async def adisplay_tool_call(message: str, console=None):
258
+ """Async version of display_tool_call."""
259
+ if not message or not message.strip():
260
+ return
261
+ if console is None:
262
+ console = Console()
263
+ message = _clean_display_content(str(message))
264
+
265
+ if 'tool_call' in async_display_callbacks:
266
+ await async_display_callbacks['tool_call'](message=message)
267
+
268
+ console.print(Panel.fit(Text(message, style="bold cyan"), title="Tool Call", border_style="green"))
269
+
270
+ async def adisplay_error(message: str, console=None):
271
+ """Async version of display_error."""
272
+ if not message or not message.strip():
273
+ return
274
+ if console is None:
275
+ console = Console()
276
+ message = _clean_display_content(str(message))
277
+
278
+ if 'error' in async_display_callbacks:
279
+ await async_display_callbacks['error'](message=message)
280
+
281
+ console.print(Panel.fit(Text(message, style="bold red"), title="Error", border_style="red"))
282
+ error_logs.append(message)
283
+
284
+ async def adisplay_generating(content: str = "", start_time: Optional[float] = None):
285
+ """Async version of display_generating."""
286
+ if not content or not str(content).strip():
287
+ return Panel("", title="", border_style="green")
288
+
289
+ elapsed_str = ""
290
+ if start_time is not None:
291
+ elapsed = time.time() - start_time
292
+ elapsed_str = f" {elapsed:.1f}s"
293
+
294
+ content = _clean_display_content(str(content))
295
+
296
+ if 'generating' in async_display_callbacks:
297
+ await async_display_callbacks['generating'](
298
+ content=content,
299
+ elapsed_time=elapsed_str.strip() if elapsed_str else None
300
+ )
301
+
302
+ return Panel(Markdown(content), title=f"Generating...{elapsed_str}", border_style="green")
303
+
304
+ def clean_triple_backticks(text: str) -> str:
305
+ """Remove triple backticks and surrounding json fences from a string."""
306
+ cleaned = text.strip()
307
+ if cleaned.startswith("```json"):
308
+ cleaned = cleaned[len("```json"):].strip()
309
+ if cleaned.startswith("```"):
310
+ cleaned = cleaned[len("```"):].strip()
311
+ if cleaned.endswith("```"):
312
+ cleaned = cleaned[:-3].strip()
313
+ return cleaned
314
+
315
+ class ReflectionOutput(BaseModel):
316
+ reflection: str
317
+ satisfactory: Literal["yes", "no"]
318
+
319
+ client = OpenAI(api_key=os.environ.get("OPENAI_API_KEY"))
320
+
321
+ class TaskOutput(BaseModel):
322
+ description: str
323
+ summary: Optional[str] = None
324
+ raw: str
325
+ pydantic: Optional[BaseModel] = None
326
+ json_dict: Optional[Dict[str, Any]] = None
327
+ agent: str
328
+ output_format: Literal["RAW", "JSON", "Pydantic"] = "RAW"
329
+
330
+ def json(self) -> Optional[str]:
331
+ if self.output_format == "JSON" and self.json_dict:
332
+ return json.dumps(self.json_dict)
333
+ return None
334
+
335
+ def to_dict(self) -> dict:
336
+ output_dict = {}
337
+ if self.json_dict:
338
+ output_dict.update(self.json_dict)
339
+ if self.pydantic:
340
+ output_dict.update(self.pydantic.model_dump())
341
+ return output_dict
342
+
343
+ def __str__(self):
344
+ if self.pydantic:
345
+ return str(self.pydantic)
346
+ elif self.json_dict:
347
+ return json.dumps(self.json_dict)
348
+ else:
349
+ return self.raw
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: praisonaiagents
3
- Version: 0.0.18
3
+ Version: 0.0.20
4
4
  Summary: Praison AI agents for completing complex tasks with Self Reflection Agents
5
5
  Author: Mervin Praison
6
6
  Requires-Dist: pydantic
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "praisonaiagents"
7
- version = "0.0.18"
7
+ version = "0.0.20"
8
8
  description = "Praison AI agents for completing complex tasks with Self Reflection Agents"
9
9
  authors = [
10
10
  { name="Mervin Praison" }
@@ -1,206 +0,0 @@
1
- import os
2
- import time
3
- import json
4
- import logging
5
- from typing import List, Optional, Dict, Any, Union, Literal, Type
6
- from openai import OpenAI
7
- from pydantic import BaseModel
8
- from rich import print
9
- from rich.console import Console
10
- from rich.panel import Panel
11
- from rich.text import Text
12
- from rich.markdown import Markdown
13
- from rich.logging import RichHandler
14
- from rich.live import Live
15
-
16
- LOGLEVEL = os.environ.get('LOGLEVEL', 'INFO').upper()
17
-
18
- logging.basicConfig(
19
- level=getattr(logging, LOGLEVEL, logging.INFO),
20
- format="%(asctime)s %(filename)s:%(lineno)d %(levelname)s %(message)s",
21
- datefmt="[%X]",
22
- handlers=[RichHandler(rich_tracebacks=True)]
23
- )
24
-
25
- # Global list to store error logs
26
- error_logs = []
27
-
28
- # Global callback registry
29
- display_callbacks = {}
30
-
31
- def register_display_callback(display_type: str, callback_fn):
32
- """Register a callback function for a specific display type."""
33
- display_callbacks[display_type] = callback_fn
34
-
35
- def _clean_display_content(content: str, max_length: int = 20000) -> str:
36
- """Helper function to clean and truncate content for display."""
37
- if not content or not str(content).strip():
38
- return ""
39
-
40
- content = str(content)
41
- # Handle base64 content
42
- if "base64" in content:
43
- content_parts = []
44
- for line in content.split('\n'):
45
- if "base64" not in line:
46
- content_parts.append(line)
47
- content = '\n'.join(content_parts)
48
-
49
- # Truncate if too long
50
- if len(content) > max_length:
51
- content = content[:max_length] + "..."
52
-
53
- return content.strip()
54
-
55
- def display_interaction(message, response, markdown=True, generation_time=None, console=None):
56
- """Display the interaction between user and assistant."""
57
- if console is None:
58
- console = Console()
59
-
60
- # Handle multimodal content (list)
61
- if isinstance(message, list):
62
- text_content = next((item["text"] for item in message if item["type"] == "text"), "")
63
- message = text_content
64
-
65
- message = _clean_display_content(str(message))
66
- response = _clean_display_content(str(response))
67
-
68
- # Execute callback if registered
69
- if 'interaction' in display_callbacks:
70
- display_callbacks['interaction'](
71
- message=message,
72
- response=response,
73
- markdown=markdown,
74
- generation_time=generation_time
75
- )
76
-
77
- # Existing display logic...
78
- if generation_time:
79
- console.print(Text(f"Response generated in {generation_time:.1f}s", style="dim"))
80
-
81
- if markdown:
82
- console.print(Panel.fit(Markdown(message), title="Message", border_style="cyan"))
83
- console.print(Panel.fit(Markdown(response), title="Response", border_style="cyan"))
84
- else:
85
- console.print(Panel.fit(Text(message, style="bold green"), title="Message", border_style="cyan"))
86
- console.print(Panel.fit(Text(response, style="bold blue"), title="Response", border_style="cyan"))
87
-
88
- def display_self_reflection(message: str, console=None):
89
- if not message or not message.strip():
90
- return
91
- if console is None:
92
- console = Console()
93
- message = _clean_display_content(str(message))
94
-
95
- # Execute callback if registered
96
- if 'self_reflection' in display_callbacks:
97
- display_callbacks['self_reflection'](message=message)
98
-
99
- console.print(Panel.fit(Text(message, style="bold yellow"), title="Self Reflection", border_style="magenta"))
100
-
101
- def display_instruction(message: str, console=None):
102
- if not message or not message.strip():
103
- return
104
- if console is None:
105
- console = Console()
106
- message = _clean_display_content(str(message))
107
-
108
- # Execute callback if registered
109
- if 'instruction' in display_callbacks:
110
- display_callbacks['instruction'](message=message)
111
-
112
- console.print(Panel.fit(Text(message, style="bold blue"), title="Instruction", border_style="cyan"))
113
-
114
- def display_tool_call(message: str, console=None):
115
- if not message or not message.strip():
116
- return
117
- if console is None:
118
- console = Console()
119
- message = _clean_display_content(str(message))
120
-
121
- # Execute callback if registered
122
- if 'tool_call' in display_callbacks:
123
- display_callbacks['tool_call'](message=message)
124
-
125
- console.print(Panel.fit(Text(message, style="bold cyan"), title="Tool Call", border_style="green"))
126
-
127
- def display_error(message: str, console=None):
128
- if not message or not message.strip():
129
- return
130
- if console is None:
131
- console = Console()
132
- message = _clean_display_content(str(message))
133
-
134
- # Execute callback if registered
135
- if 'error' in display_callbacks:
136
- display_callbacks['error'](message=message)
137
-
138
- console.print(Panel.fit(Text(message, style="bold red"), title="Error", border_style="red"))
139
- error_logs.append(message)
140
-
141
- def display_generating(content: str = "", start_time: Optional[float] = None):
142
- if not content or not str(content).strip():
143
- return Panel("", title="", border_style="green")
144
-
145
- elapsed_str = ""
146
- if start_time is not None:
147
- elapsed = time.time() - start_time
148
- elapsed_str = f" {elapsed:.1f}s"
149
-
150
- content = _clean_display_content(str(content))
151
-
152
- # Execute callback if registered
153
- if 'generating' in display_callbacks:
154
- display_callbacks['generating'](
155
- content=content,
156
- elapsed_time=elapsed_str.strip() if elapsed_str else None
157
- )
158
-
159
- return Panel(Markdown(content), title=f"Generating...{elapsed_str}", border_style="green")
160
-
161
- def clean_triple_backticks(text: str) -> str:
162
- """Remove triple backticks and surrounding json fences from a string."""
163
- cleaned = text.strip()
164
- if cleaned.startswith("```json"):
165
- cleaned = cleaned[len("```json"):].strip()
166
- if cleaned.startswith("```"):
167
- cleaned = cleaned[len("```"):].strip()
168
- if cleaned.endswith("```"):
169
- cleaned = cleaned[:-3].strip()
170
- return cleaned
171
-
172
- class ReflectionOutput(BaseModel):
173
- reflection: str
174
- satisfactory: Literal["yes", "no"]
175
-
176
- client = OpenAI(api_key=os.environ.get("OPENAI_API_KEY"))
177
-
178
- class TaskOutput(BaseModel):
179
- description: str
180
- summary: Optional[str] = None
181
- raw: str
182
- pydantic: Optional[BaseModel] = None
183
- json_dict: Optional[Dict[str, Any]] = None
184
- agent: str
185
- output_format: Literal["RAW", "JSON", "Pydantic"] = "RAW"
186
-
187
- def json(self) -> Optional[str]:
188
- if self.output_format == "JSON" and self.json_dict:
189
- return json.dumps(self.json_dict)
190
- return None
191
-
192
- def to_dict(self) -> dict:
193
- output_dict = {}
194
- if self.json_dict:
195
- output_dict.update(self.json_dict)
196
- if self.pydantic:
197
- output_dict.update(self.pydantic.model_dump())
198
- return output_dict
199
-
200
- def __str__(self):
201
- if self.pydantic:
202
- return str(self.pydantic)
203
- elif self.json_dict:
204
- return json.dumps(self.json_dict)
205
- else:
206
- return self.raw