praisonaiagents 0.0.14__py3-none-any.whl → 0.0.16__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.
@@ -10,9 +10,7 @@ from rich.console import Console
10
10
  from ..main import display_error, TaskOutput, error_logs, client
11
11
  from ..agent.agent import Agent
12
12
  from ..task.task import Task
13
-
14
- class LoopItems(BaseModel):
15
- items: List[Any]
13
+ from ..process.process import Process, LoopItems
16
14
 
17
15
  def encode_file_to_base64(file_path: str) -> str:
18
16
  """Base64-encode a file."""
@@ -256,254 +254,24 @@ Expected Output: {task.expected_output}.
256
254
 
257
255
  def run_all_tasks(self):
258
256
  """Execute tasks based on execution mode"""
257
+ process = Process(
258
+ tasks=self.tasks,
259
+ agents=self.agents,
260
+ manager_llm=self.manager_llm,
261
+ verbose=self.verbose
262
+ )
263
+
259
264
  if self.process == "workflow":
260
- # Build workflow relationships first
261
- for task in self.tasks.values():
262
- if task.next_tasks:
263
- for next_task_name in task.next_tasks:
264
- next_task = next((t for t in self.tasks.values() if t.name == next_task_name), None)
265
- if next_task:
266
- next_task.previous_tasks.append(task.name)
267
-
268
- # Find start task
269
- start_task = None
270
- for task_id, task in self.tasks.items():
271
- if task.is_start:
272
- start_task = task
273
- break
274
-
275
- if not start_task:
276
- start_task = list(self.tasks.values())[0]
277
- logging.info("No start task marked, using first task")
278
-
279
- current_task = start_task
280
- visited_tasks = set()
281
- loop_data = {} # Store loop-specific data
282
-
283
- while current_task and current_task.id not in visited_tasks:
284
- task_id = current_task.id
285
- logging.info(f"Executing workflow task: {current_task.name if current_task.name else task_id}")
286
-
287
- # Add context from previous tasks to description
288
- if current_task.previous_tasks or current_task.context:
289
- context = "\nInput data from previous tasks:"
290
-
291
- # Add data from previous tasks in workflow
292
- for prev_name in current_task.previous_tasks:
293
- prev_task = next((t for t in self.tasks.values() if t.name == prev_name), None)
294
- if prev_task and prev_task.result:
295
- # Handle loop data
296
- if current_task.task_type == "loop":
297
- # create a loop manager Agent
298
- loop_manager = Agent(
299
- name="Loop Manager",
300
- role="Loop data processor",
301
- goal="Process loop data and convert it to list format",
302
- backstory="Expert at handling loop data and converting it to proper format",
303
- llm=self.manager_llm,
304
- verbose=self.verbose,
305
- markdown=True
306
- )
307
-
308
- # get the loop data convert it to list using calling Agent class chat
309
- loop_prompt = f"""
310
- Process this data into a list format:
311
- {prev_task.result.raw}
312
-
313
- Return a JSON object with an 'items' array containing the items to process.
314
- """
315
- loop_data_str = loop_manager.chat(
316
- prompt=loop_prompt,
317
- output_json=LoopItems
318
- )
319
-
320
- try:
321
- # The response will already be parsed into LoopItems model
322
- loop_data[f"loop_{current_task.name}"] = {
323
- "items": loop_data_str.items,
324
- "index": 0,
325
- "remaining": len(loop_data_str.items)
326
- }
327
- context += f"\nCurrent loop item: {loop_data_str.items[0]}"
328
- except Exception as e:
329
- display_error(f"Failed to process loop data: {e}")
330
- context += f"\n{prev_name}: {prev_task.result.raw}"
331
- else:
332
- context += f"\n{prev_name}: {prev_task.result.raw}"
333
-
334
- # Add data from context tasks
335
- if current_task.context:
336
- for ctx_task in current_task.context:
337
- if ctx_task.result and ctx_task.name != current_task.name:
338
- context += f"\n{ctx_task.name}: {ctx_task.result.raw}"
339
-
340
- # Update task description with context
341
- current_task.description = current_task.description + context
342
-
343
- # Execute task using existing run_task method
265
+ for task_id in process.workflow():
344
266
  self.run_task(task_id)
345
- visited_tasks.add(task_id)
346
-
347
- # Handle loop progression
348
- if current_task.task_type == "loop":
349
- loop_key = f"loop_{current_task.name}"
350
- if loop_key in loop_data:
351
- loop_info = loop_data[loop_key]
352
- loop_info["index"] += 1
353
- has_more = loop_info["remaining"] > 0
354
-
355
- # Update result to trigger correct condition
356
- if current_task.result:
357
- result = current_task.result.raw
358
- if has_more:
359
- result += "\nmore"
360
- else:
361
- result += "\ndone"
362
- current_task.result.raw = result
363
-
364
- # Determine next task based on result
365
- next_task = None
366
- if current_task.result:
367
- if current_task.task_type in ["decision", "loop"]:
368
- result = current_task.result.raw.lower()
369
- # Check conditions
370
- for condition, tasks in current_task.condition.items():
371
- if condition.lower() in result and tasks:
372
- next_task_name = tasks[0]
373
- next_task = next((t for t in self.tasks.values() if t.name == next_task_name), None)
374
- # For loops, allow revisiting the same task
375
- if next_task and next_task.id == current_task.id:
376
- visited_tasks.discard(current_task.id)
377
- break
378
-
379
- if not next_task and current_task.next_tasks:
380
- next_task_name = current_task.next_tasks[0]
381
- next_task = next((t for t in self.tasks.values() if t.name == next_task_name), None)
382
-
383
- current_task = next_task
384
- if not current_task:
385
- logging.info("Workflow execution completed")
386
- break
387
-
388
267
  elif self.process == "sequential":
389
- # Keep original sequential execution
390
- for task_id in self.tasks:
391
- if self.tasks[task_id].status != "completed":
392
- self.run_task(task_id)
393
-
268
+ for task_id in process.sequential():
269
+ self.run_task(task_id)
394
270
  elif self.process == "hierarchical":
395
- # Keep original hierarchical execution
396
- logging.debug(f"Starting hierarchical task execution with {len(self.tasks)} tasks")
397
- manager_agent = Agent(
398
- name="Manager",
399
- role="Project manager",
400
- goal="Manage the entire flow of tasks and delegate them to the right agent",
401
- backstory="Expert project manager to coordinate tasks among agents",
402
- llm=self.manager_llm,
403
- verbose=self.verbose,
404
- markdown=True,
405
- self_reflect=False
406
- )
407
-
408
- class ManagerInstructions(BaseModel):
409
- task_id: int
410
- agent_name: str
411
- action: str
412
-
413
- manager_task = Task(
414
- name="manager_task",
415
- description="Decide the order of tasks and which agent executes them",
416
- expected_output="All tasks completed successfully",
417
- agent=manager_agent
418
- )
419
- manager_task_id = self.add_task(manager_task)
420
- logging.info(f"Created manager task with ID {manager_task_id}")
421
-
422
- completed_count = 0
423
- total_tasks = len(self.tasks) - 1
424
- logging.info(f"Need to complete {total_tasks} tasks (excluding manager task)")
425
-
426
- while completed_count < total_tasks:
427
- tasks_summary = []
428
- for tid, tk in self.tasks.items():
429
- if tk.name == "manager_task":
430
- continue
431
- task_info = {
432
- "task_id": tid,
433
- "name": tk.name,
434
- "description": tk.description,
435
- "status": tk.status if tk.status else "not started",
436
- "agent": tk.agent.name if tk.agent else "No agent"
437
- }
438
- tasks_summary.append(task_info)
439
- logging.info(f"Task {tid} status: {task_info}")
440
-
441
- manager_prompt = f"""
442
- Here is the current status of all tasks except yours (manager_task):
443
- {tasks_summary}
444
-
445
- Provide a JSON with the structure:
446
- {{
447
- "task_id": <int>,
448
- "agent_name": "<string>",
449
- "action": "<execute or stop>"
450
- }}
451
- """
452
-
453
- try:
454
- logging.info("Requesting manager instructions...")
455
- manager_response = client.beta.chat.completions.parse(
456
- model=self.manager_llm,
457
- messages=[
458
- {"role": "system", "content": manager_task.description},
459
- {"role": "user", "content": manager_prompt}
460
- ],
461
- temperature=0.7,
462
- response_format=ManagerInstructions
463
- )
464
- parsed_instructions = manager_response.choices[0].message.parsed
465
- logging.info(f"Manager instructions: {parsed_instructions}")
466
- except Exception as e:
467
- display_error(f"Manager parse error: {e}")
468
- logging.error(f"Manager parse error: {str(e)}", exc_info=True)
469
- break
470
-
471
- selected_task_id = parsed_instructions.task_id
472
- selected_agent_name = parsed_instructions.agent_name
473
- action = parsed_instructions.action
474
-
475
- logging.info(f"Manager selected task_id={selected_task_id}, agent={selected_agent_name}, action={action}")
476
-
477
- if action.lower() == "stop":
478
- logging.info("Manager decided to stop task execution")
479
- break
480
-
481
- if selected_task_id not in self.tasks:
482
- error_msg = f"Manager selected invalid task id {selected_task_id}"
483
- display_error(error_msg)
484
- logging.error(error_msg)
485
- break
486
-
487
- original_agent = self.tasks[selected_task_id].agent.name if self.tasks[selected_task_id].agent else "None"
488
- for a in self.agents:
489
- if a.name == selected_agent_name:
490
- self.tasks[selected_task_id].agent = a
491
- logging.info(f"Changed agent for task {selected_task_id} from {original_agent} to {selected_agent_name}")
492
- break
493
-
494
- if self.tasks[selected_task_id].status != "completed":
495
- logging.info(f"Starting execution of task {selected_task_id}")
496
- self.run_task(selected_task_id)
497
- logging.info(f"Finished execution of task {selected_task_id}, status: {self.tasks[selected_task_id].status}")
498
-
499
- if self.tasks[selected_task_id].status == "completed":
500
- completed_count += 1
501
- logging.info(f"Task {selected_task_id} completed. Total completed: {completed_count}/{total_tasks}")
502
-
503
- self.tasks[manager_task.id].status = "completed"
504
- if self.verbose >= 1:
505
- logging.info("All tasks completed under manager supervision.")
506
- logging.info("Hierarchical task execution finished")
271
+ for task_id in process.hierarchical():
272
+ if isinstance(task_id, Task):
273
+ task_id = self.add_task(task_id)
274
+ self.run_task(task_id)
507
275
 
508
276
  def get_task_status(self, task_id):
509
277
  if task_id in self.tasks:
@@ -0,0 +1,3 @@
1
+ from .process import Process
2
+
3
+ __all__ = ['Process']
@@ -0,0 +1,263 @@
1
+ import logging
2
+ from typing import Dict, Optional, List, Any
3
+ from pydantic import BaseModel
4
+ from ..agent.agent import Agent
5
+ from ..task.task import Task
6
+ from ..main import display_error, client
7
+
8
+ class LoopItems(BaseModel):
9
+ items: List[Any]
10
+
11
+ class Process:
12
+ def __init__(self, tasks: Dict[str, Task], agents: List[Agent], manager_llm: Optional[str] = None, verbose: bool = False):
13
+ self.tasks = tasks
14
+ self.agents = agents
15
+ self.manager_llm = manager_llm
16
+ self.verbose = verbose
17
+
18
+ def workflow(self):
19
+ # Build workflow relationships first
20
+ for task in self.tasks.values():
21
+ if task.next_tasks:
22
+ for next_task_name in task.next_tasks:
23
+ next_task = next((t for t in self.tasks.values() if t.name == next_task_name), None)
24
+ if next_task:
25
+ next_task.previous_tasks.append(task.name)
26
+
27
+ # Find start task
28
+ start_task = None
29
+ for task_id, task in self.tasks.items():
30
+ if task.is_start:
31
+ start_task = task
32
+ break
33
+
34
+ if not start_task:
35
+ start_task = list(self.tasks.values())[0]
36
+ logging.info("No start task marked, using first task")
37
+
38
+ current_task = start_task
39
+ visited_tasks = set()
40
+ loop_data = {} # Store loop-specific data
41
+
42
+ while current_task and current_task.id not in visited_tasks:
43
+ task_id = current_task.id
44
+ logging.info(f"Executing workflow task: {current_task.name if current_task.name else task_id}")
45
+
46
+ # Add context from previous tasks to description
47
+ if current_task.previous_tasks or current_task.context:
48
+ context = "\nInput data from previous tasks:"
49
+
50
+ # Add data from previous tasks in workflow
51
+ for prev_name in current_task.previous_tasks:
52
+ prev_task = next((t for t in self.tasks.values() if t.name == prev_name), None)
53
+ if prev_task and prev_task.result:
54
+ # Handle loop data
55
+ if current_task.task_type == "loop":
56
+ # create a loop manager Agent
57
+ loop_manager = Agent(
58
+ name="Loop Manager",
59
+ role="Loop data processor",
60
+ goal="Process loop data and convert it to list format",
61
+ backstory="Expert at handling loop data and converting it to proper format",
62
+ llm=self.manager_llm,
63
+ verbose=self.verbose,
64
+ markdown=True
65
+ )
66
+
67
+ # get the loop data convert it to list using calling Agent class chat
68
+ loop_prompt = f"""
69
+ Process this data into a list format:
70
+ {prev_task.result.raw}
71
+
72
+ Return a JSON object with an 'items' array containing the items to process.
73
+ """
74
+ loop_data_str = loop_manager.chat(
75
+ prompt=loop_prompt,
76
+ output_json=LoopItems
77
+ )
78
+
79
+ try:
80
+ # The response will already be parsed into LoopItems model
81
+ loop_data[f"loop_{current_task.name}"] = {
82
+ "items": loop_data_str.items,
83
+ "index": 0,
84
+ "remaining": len(loop_data_str.items)
85
+ }
86
+ context += f"\nCurrent loop item: {loop_data_str.items[0]}"
87
+ except Exception as e:
88
+ display_error(f"Failed to process loop data: {e}")
89
+ context += f"\n{prev_name}: {prev_task.result.raw}"
90
+ else:
91
+ context += f"\n{prev_name}: {prev_task.result.raw}"
92
+
93
+ # Add data from context tasks
94
+ if current_task.context:
95
+ for ctx_task in current_task.context:
96
+ if ctx_task.result and ctx_task.name != current_task.name:
97
+ context += f"\n{ctx_task.name}: {ctx_task.result.raw}"
98
+
99
+ # Update task description with context
100
+ current_task.description = current_task.description + context
101
+
102
+ # Execute task using existing run_task method
103
+ yield task_id
104
+ visited_tasks.add(task_id)
105
+
106
+ # Handle loop progression
107
+ if current_task.task_type == "loop":
108
+ loop_key = f"loop_{current_task.name}"
109
+ if loop_key in loop_data:
110
+ loop_info = loop_data[loop_key]
111
+ loop_info["index"] += 1
112
+ has_more = loop_info["remaining"] > 0
113
+
114
+ # Update result to trigger correct condition
115
+ if current_task.result:
116
+ result = current_task.result.raw
117
+ if has_more:
118
+ result += "\nmore"
119
+ else:
120
+ result += "\ndone"
121
+ current_task.result.raw = result
122
+
123
+ # Determine next task based on result
124
+ next_task = None
125
+ if current_task.result:
126
+ if current_task.task_type in ["decision", "loop"]:
127
+ result = current_task.result.raw.lower()
128
+ # Check conditions
129
+ for condition, tasks in current_task.condition.items():
130
+ if condition.lower() in result and tasks:
131
+ next_task_name = tasks[0]
132
+ next_task = next((t for t in self.tasks.values() if t.name == next_task_name), None)
133
+ # For loops, allow revisiting the same task
134
+ if next_task and next_task.id == current_task.id:
135
+ visited_tasks.discard(current_task.id)
136
+ break
137
+
138
+ if not next_task and current_task.next_tasks:
139
+ next_task_name = current_task.next_tasks[0]
140
+ next_task = next((t for t in self.tasks.values() if t.name == next_task_name), None)
141
+
142
+ current_task = next_task
143
+ if not current_task:
144
+ logging.info("Workflow execution completed")
145
+ break
146
+
147
+ def sequential(self):
148
+ for task_id in self.tasks:
149
+ if self.tasks[task_id].status != "completed":
150
+ yield task_id
151
+
152
+ def hierarchical(self):
153
+ logging.debug(f"Starting hierarchical task execution with {len(self.tasks)} tasks")
154
+ manager_agent = Agent(
155
+ name="Manager",
156
+ role="Project manager",
157
+ goal="Manage the entire flow of tasks and delegate them to the right agent",
158
+ backstory="Expert project manager to coordinate tasks among agents",
159
+ llm=self.manager_llm,
160
+ verbose=self.verbose,
161
+ markdown=True,
162
+ self_reflect=False
163
+ )
164
+
165
+ class ManagerInstructions(BaseModel):
166
+ task_id: int
167
+ agent_name: str
168
+ action: str
169
+
170
+ manager_task = Task(
171
+ name="manager_task",
172
+ description="Decide the order of tasks and which agent executes them",
173
+ expected_output="All tasks completed successfully",
174
+ agent=manager_agent
175
+ )
176
+ manager_task_id = yield manager_task
177
+ logging.info(f"Created manager task with ID {manager_task_id}")
178
+
179
+ completed_count = 0
180
+ total_tasks = len(self.tasks) - 1
181
+ logging.info(f"Need to complete {total_tasks} tasks (excluding manager task)")
182
+
183
+ while completed_count < total_tasks:
184
+ tasks_summary = []
185
+ for tid, tk in self.tasks.items():
186
+ if tk.name == "manager_task":
187
+ continue
188
+ task_info = {
189
+ "task_id": tid,
190
+ "name": tk.name,
191
+ "description": tk.description,
192
+ "status": tk.status if tk.status else "not started",
193
+ "agent": tk.agent.name if tk.agent else "No agent"
194
+ }
195
+ tasks_summary.append(task_info)
196
+ logging.info(f"Task {tid} status: {task_info}")
197
+
198
+ manager_prompt = f"""
199
+ Here is the current status of all tasks except yours (manager_task):
200
+ {tasks_summary}
201
+
202
+ Provide a JSON with the structure:
203
+ {{
204
+ "task_id": <int>,
205
+ "agent_name": "<string>",
206
+ "action": "<execute or stop>"
207
+ }}
208
+ """
209
+
210
+ try:
211
+ logging.info("Requesting manager instructions...")
212
+ manager_response = client.beta.chat.completions.parse(
213
+ model=self.manager_llm,
214
+ messages=[
215
+ {"role": "system", "content": manager_task.description},
216
+ {"role": "user", "content": manager_prompt}
217
+ ],
218
+ temperature=0.7,
219
+ response_format=ManagerInstructions
220
+ )
221
+ parsed_instructions = manager_response.choices[0].message.parsed
222
+ logging.info(f"Manager instructions: {parsed_instructions}")
223
+ except Exception as e:
224
+ display_error(f"Manager parse error: {e}")
225
+ logging.error(f"Manager parse error: {str(e)}", exc_info=True)
226
+ break
227
+
228
+ selected_task_id = parsed_instructions.task_id
229
+ selected_agent_name = parsed_instructions.agent_name
230
+ action = parsed_instructions.action
231
+
232
+ logging.info(f"Manager selected task_id={selected_task_id}, agent={selected_agent_name}, action={action}")
233
+
234
+ if action.lower() == "stop":
235
+ logging.info("Manager decided to stop task execution")
236
+ break
237
+
238
+ if selected_task_id not in self.tasks:
239
+ error_msg = f"Manager selected invalid task id {selected_task_id}"
240
+ display_error(error_msg)
241
+ logging.error(error_msg)
242
+ break
243
+
244
+ original_agent = self.tasks[selected_task_id].agent.name if self.tasks[selected_task_id].agent else "None"
245
+ for a in self.agents:
246
+ if a.name == selected_agent_name:
247
+ self.tasks[selected_task_id].agent = a
248
+ logging.info(f"Changed agent for task {selected_task_id} from {original_agent} to {selected_agent_name}")
249
+ break
250
+
251
+ if self.tasks[selected_task_id].status != "completed":
252
+ logging.info(f"Starting execution of task {selected_task_id}")
253
+ yield selected_task_id
254
+ logging.info(f"Finished execution of task {selected_task_id}, status: {self.tasks[selected_task_id].status}")
255
+
256
+ if self.tasks[selected_task_id].status == "completed":
257
+ completed_count += 1
258
+ logging.info(f"Task {selected_task_id} completed. Total completed: {completed_count}/{total_tasks}")
259
+
260
+ self.tasks[manager_task.id].status = "completed"
261
+ if self.verbose >= 1:
262
+ logging.info("All tasks completed under manager supervision.")
263
+ logging.info("Hierarchical task execution finished")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: praisonaiagents
3
- Version: 0.0.14
3
+ Version: 0.0.16
4
4
  Summary: Praison AI agents for completing complex tasks with Self Reflection Agents
5
5
  Author: Mervin Praison
6
6
  Requires-Dist: pydantic
@@ -3,7 +3,7 @@ praisonaiagents/main.py,sha256=K2OxVKPmo4dNJbSWIsXDi_hm9CRx5O4km_74UGcszhk,5744
3
3
  praisonaiagents/agent/__init__.py,sha256=sKO8wGEXvtCrvV1e834r1Okv0XAqAxqZCqz6hKLiTvA,79
4
4
  praisonaiagents/agent/agent.py,sha256=zTYcDpJ5DzzBnefwLvhrtBlGQoRI4ZZAioDu5nKTPSs,24042
5
5
  praisonaiagents/agents/__init__.py,sha256=7RDeQNSqZg5uBjD4M_0p_F6YgfWuDuxPFydPU50kDYc,120
6
- praisonaiagents/agents/agents.py,sha256=ITvH8Yq_OzhyMC_Aid4qlqQbEM9cCfp7SayXg0ASJ5k,24526
6
+ praisonaiagents/agents/agents.py,sha256=-1Z-jIN2fkLM9P6nAq-OtKPTF8HIjA-a_Zznv8TfpFY,12964
7
7
  praisonaiagents/build/lib/praisonaiagents/__init__.py,sha256=Nqnn8clbgv-5l0PgxcTOldg8mkMKrFn4TvPL-rYUUGg,1
8
8
  praisonaiagents/build/lib/praisonaiagents/main.py,sha256=zDhN5KKtKbfruolDNxlyJkcFlkSt4KQkQTDRfQVAhxc,3960
9
9
  praisonaiagents/build/lib/praisonaiagents/agent/__init__.py,sha256=sKO8wGEXvtCrvV1e834r1Okv0XAqAxqZCqz6hKLiTvA,79
@@ -12,9 +12,11 @@ praisonaiagents/build/lib/praisonaiagents/agents/__init__.py,sha256=cgCLFLFcLp9S
12
12
  praisonaiagents/build/lib/praisonaiagents/agents/agents.py,sha256=P2FAtlfD3kPib5a1oLVYanxlU6e4-GhBMQ0YDY5MHY4,13473
13
13
  praisonaiagents/build/lib/praisonaiagents/task/__init__.py,sha256=VL5hXVmyGjINb34AalxpBMl-YW9m5EDcRkMTKkSSl7c,80
14
14
  praisonaiagents/build/lib/praisonaiagents/task/task.py,sha256=4Y1qX8OeEFcid2yhAiPYylvHpuDmWORsyNL16_BiVvI,1831
15
+ praisonaiagents/process/__init__.py,sha256=lkYbL7Hn5a0ldvJtkdH23vfIIZLIcanK-65C0MwaorY,52
16
+ praisonaiagents/process/process.py,sha256=HN_xNeG02T5QwcvcuSw8OiABVYbKIYJ-J--3H8Hd89Q,11722
15
17
  praisonaiagents/task/__init__.py,sha256=VL5hXVmyGjINb34AalxpBMl-YW9m5EDcRkMTKkSSl7c,80
16
18
  praisonaiagents/task/task.py,sha256=oMC5Zz1dMj0Ceice69aBS1KQQXMLqphc8wNOQ9zcu0Q,2570
17
- praisonaiagents-0.0.14.dist-info/METADATA,sha256=-pdlX7m7Sr2IovIrRt9QyBfkiwgK81rEd3_VklcmHNs,233
18
- praisonaiagents-0.0.14.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
19
- praisonaiagents-0.0.14.dist-info/top_level.txt,sha256=_HsRddrJ23iDx5TTqVUVvXG2HeHBL5voshncAMDGjtA,16
20
- praisonaiagents-0.0.14.dist-info/RECORD,,
19
+ praisonaiagents-0.0.16.dist-info/METADATA,sha256=Nb_ZUqzMHYl2CzLFiDFAclzAAx4G0LWN6IWADmYu0LY,233
20
+ praisonaiagents-0.0.16.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
21
+ praisonaiagents-0.0.16.dist-info/top_level.txt,sha256=_HsRddrJ23iDx5TTqVUVvXG2HeHBL5voshncAMDGjtA,16
22
+ praisonaiagents-0.0.16.dist-info/RECORD,,