PraisonAI 0.0.66__cp312-cp312-manylinux_2_35_x86_64.whl → 0.0.68__cp312-cp312-manylinux_2_35_x86_64.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 PraisonAI might be problematic. Click here for more details.

praisonai/deploy.py CHANGED
@@ -56,7 +56,7 @@ class CloudDeployer:
56
56
  file.write("FROM python:3.11-slim\n")
57
57
  file.write("WORKDIR /app\n")
58
58
  file.write("COPY . .\n")
59
- file.write("RUN pip install flask praisonai==0.0.66 gunicorn markdown\n")
59
+ file.write("RUN pip install flask praisonai==0.0.68 gunicorn markdown\n")
60
60
  file.write("EXPOSE 8080\n")
61
61
  file.write('CMD ["gunicorn", "-b", "0.0.0.0:8080", "api:app"]\n')
62
62
 
@@ -0,0 +1 @@
1
+
praisonai/ui/code.py CHANGED
@@ -281,7 +281,7 @@ async def send_count():
281
281
  ).send()
282
282
 
283
283
  @cl.on_chat_resume
284
- async def on_chat_resume(thread: cl_data.ThreadDict):
284
+ async def on_chat_resume(thread: ThreadDict):
285
285
  logger.info(f"Resuming chat: {thread['id']}")
286
286
  model_name = load_setting("model_name") or os.getenv("MODEL_NAME") or "gpt-4o-mini"
287
287
  logger.debug(f"Model name: {model_name}")
@@ -7,8 +7,9 @@ from typing import TYPE_CHECKING, Any, Dict, List, Optional, Union
7
7
 
8
8
  import aiofiles
9
9
  import aiohttp
10
- from chainlit.context import context
11
- from chainlit.data import BaseDataLayer, BaseStorageClient, queue_until_user_message
10
+
11
+ from chainlit.data.base import BaseDataLayer, BaseStorageClient
12
+ from chainlit.data.utils import queue_until_user_message
12
13
  from chainlit.element import ElementDict
13
14
  from chainlit.logger import logger
14
15
  from chainlit.step import StepDict
@@ -26,9 +27,6 @@ from sqlalchemy import text
26
27
  from sqlalchemy.exc import SQLAlchemyError
27
28
  from sqlalchemy.ext.asyncio import AsyncEngine, AsyncSession, create_async_engine
28
29
  from sqlalchemy.orm import sessionmaker
29
- import chainlit as cl
30
- from literalai.helper import utc_now
31
- now = utc_now()
32
30
 
33
31
  if TYPE_CHECKING:
34
32
  from chainlit.element import Element, ElementDict
@@ -57,7 +55,9 @@ class SQLAlchemyDataLayer(BaseDataLayer):
57
55
  self.engine: AsyncEngine = create_async_engine(
58
56
  self._conninfo, connect_args=ssl_args
59
57
  )
60
- self.async_session = sessionmaker(bind=self.engine, expire_on_commit=False, class_=AsyncSession) # type: ignore
58
+ self.async_session = sessionmaker(
59
+ bind=self.engine, expire_on_commit=False, class_=AsyncSession
60
+ ) # type: ignore
61
61
  if storage_provider:
62
62
  self.storage_provider: Optional[BaseStorageClient] = storage_provider
63
63
  if self.show_logger:
@@ -84,6 +84,9 @@ class SQLAlchemyDataLayer(BaseDataLayer):
84
84
  if result.returns_rows:
85
85
  json_result = [dict(row._mapping) for row in result.fetchall()]
86
86
  clean_json_result = self.clean_result(json_result)
87
+ assert isinstance(clean_json_result, list) or isinstance(
88
+ clean_json_result, int
89
+ )
87
90
  return clean_json_result
88
91
  else:
89
92
  return result.rowcount
@@ -111,8 +114,6 @@ class SQLAlchemyDataLayer(BaseDataLayer):
111
114
 
112
115
  ###### User ######
113
116
  async def get_user(self, identifier: str) -> Optional[PersistedUser]:
114
- logger.debug(f"Getting user: {identifier}")
115
- return cl.PersistedUser(id="test", createdAt=now, identifier=identifier)
116
117
  if self.show_logger:
117
118
  logger.info(f"SQLAlchemy: get_user, identifier={identifier}")
118
119
  query = "SELECT * FROM users WHERE identifier = :identifier"
@@ -120,12 +121,50 @@ class SQLAlchemyDataLayer(BaseDataLayer):
120
121
  result = await self.execute_sql(query=query, parameters=parameters)
121
122
  if result and isinstance(result, list):
122
123
  user_data = result[0]
123
- return PersistedUser(**user_data)
124
+
125
+ # SQLite returns JSON as string, we most convert it. (#1137)
126
+ metadata = user_data.get("metadata", {})
127
+ if isinstance(metadata, str):
128
+ metadata = json.loads(metadata)
129
+
130
+ assert isinstance(metadata, dict)
131
+ assert isinstance(user_data["id"], str)
132
+ assert isinstance(user_data["identifier"], str)
133
+ assert isinstance(user_data["createdAt"], str)
134
+
135
+ return PersistedUser(
136
+ id=user_data["id"],
137
+ identifier=user_data["identifier"],
138
+ createdAt=user_data["createdAt"],
139
+ metadata=metadata,
140
+ )
141
+ return None
142
+
143
+ async def _get_user_identifer_by_id(self, user_id: str) -> str:
144
+ if self.show_logger:
145
+ logger.info(f"SQLAlchemy: _get_user_identifer_by_id, user_id={user_id}")
146
+ query = "SELECT identifier FROM users WHERE id = :user_id"
147
+ parameters = {"user_id": user_id}
148
+ result = await self.execute_sql(query=query, parameters=parameters)
149
+
150
+ assert result
151
+ assert isinstance(result, list)
152
+
153
+ return result[0]["identifier"]
154
+
155
+ async def _get_user_id_by_thread(self, thread_id: str) -> Optional[str]:
156
+ if self.show_logger:
157
+ logger.info(f"SQLAlchemy: _get_user_id_by_thread, thread_id={thread_id}")
158
+ query = "SELECT userId FROM threads WHERE id = :thread_id"
159
+ parameters = {"thread_id": thread_id}
160
+ result = await self.execute_sql(query=query, parameters=parameters)
161
+ if result:
162
+ assert isinstance(result, list)
163
+ return result[0]["userId"]
164
+
124
165
  return None
125
166
 
126
167
  async def create_user(self, user: User) -> Optional[PersistedUser]:
127
- logger.debug(f"Creating user: {user.identifier}")
128
- return cl.PersistedUser(id="test", createdAt=now, identifier=user.identifier)
129
168
  if self.show_logger:
130
169
  logger.info(f"SQLAlchemy: create_user, user_identifier={user.identifier}")
131
170
  existing_user: Optional["PersistedUser"] = await self.get_user(user.identifier)
@@ -151,8 +190,6 @@ class SQLAlchemyDataLayer(BaseDataLayer):
151
190
 
152
191
  ###### Threads ######
153
192
  async def get_thread_author(self, thread_id: str) -> str:
154
- logger.debug(f"Getting thread author: {thread_id}")
155
- return "admin"
156
193
  if self.show_logger:
157
194
  logger.info(f"SQLAlchemy: get_thread_author, thread_id={thread_id}")
158
195
  query = """SELECT "userIdentifier" FROM threads WHERE "id" = :id"""
@@ -171,16 +208,7 @@ class SQLAlchemyDataLayer(BaseDataLayer):
171
208
  thread_id=thread_id
172
209
  )
173
210
  if user_threads:
174
- thread = user_threads[0]
175
- # Parse the metadata here
176
- if isinstance(thread['metadata'], str):
177
- try:
178
- thread['metadata'] = json.loads(thread['metadata'])
179
- except json.JSONDecodeError:
180
- thread['metadata'] = {}
181
- elif thread['metadata'] is None:
182
- thread['metadata'] = {}
183
- return thread
211
+ return user_threads[0]
184
212
  else:
185
213
  return None
186
214
 
@@ -194,10 +222,11 @@ class SQLAlchemyDataLayer(BaseDataLayer):
194
222
  ):
195
223
  if self.show_logger:
196
224
  logger.info(f"SQLAlchemy: update_thread, thread_id={thread_id}")
197
- if context.session.user is not None:
198
- user_identifier = context.session.user.identifier
199
- else:
200
- raise ValueError("User not found in session context")
225
+
226
+ user_identifier = None
227
+ if user_id:
228
+ user_identifier = await self._get_user_identifer_by_id(user_id)
229
+
201
230
  data = {
202
231
  "id": thread_id,
203
232
  "createdAt": (
@@ -309,8 +338,7 @@ class SQLAlchemyDataLayer(BaseDataLayer):
309
338
  async def create_step(self, step_dict: "StepDict"):
310
339
  if self.show_logger:
311
340
  logger.info(f"SQLAlchemy: create_step, step_id={step_dict.get('id')}")
312
- if not getattr(context.session.user, "id", None):
313
- raise ValueError("No authenticated user in context")
341
+
314
342
  step_dict["showInput"] = (
315
343
  str(step_dict.get("showInput", "")).lower()
316
344
  if "showInput" in step_dict
@@ -388,15 +416,48 @@ class SQLAlchemyDataLayer(BaseDataLayer):
388
416
  return True
389
417
 
390
418
  ###### Elements ######
419
+ async def get_element(
420
+ self, thread_id: str, element_id: str
421
+ ) -> Optional["ElementDict"]:
422
+ if self.show_logger:
423
+ logger.info(
424
+ f"SQLAlchemy: get_element, thread_id={thread_id}, element_id={element_id}"
425
+ )
426
+ query = """SELECT * FROM elements WHERE "threadId" = :thread_id AND "id" = :element_id"""
427
+ parameters = {"thread_id": thread_id, "element_id": element_id}
428
+ element: Union[List[Dict[str, Any]], int, None] = await self.execute_sql(
429
+ query=query, parameters=parameters
430
+ )
431
+ if isinstance(element, list) and element:
432
+ element_dict: Dict[str, Any] = element[0]
433
+ return ElementDict(
434
+ id=element_dict["id"],
435
+ threadId=element_dict.get("threadId"),
436
+ type=element_dict["type"],
437
+ chainlitKey=element_dict.get("chainlitKey"),
438
+ url=element_dict.get("url"),
439
+ objectKey=element_dict.get("objectKey"),
440
+ name=element_dict["name"],
441
+ display=element_dict["display"],
442
+ size=element_dict.get("size"),
443
+ language=element_dict.get("language"),
444
+ page=element_dict.get("page"),
445
+ autoPlay=element_dict.get("autoPlay"),
446
+ playerConfig=element_dict.get("playerConfig"),
447
+ forId=element_dict.get("forId"),
448
+ mime=element_dict.get("mime"),
449
+ )
450
+ else:
451
+ return None
452
+
391
453
  @queue_until_user_message()
392
454
  async def create_element(self, element: "Element"):
393
455
  if self.show_logger:
394
456
  logger.info(f"SQLAlchemy: create_element, element_id = {element.id}")
395
- if not getattr(context.session.user, "id", None):
396
- raise ValueError("No authenticated user in context")
457
+
397
458
  if not self.storage_provider:
398
459
  logger.warn(
399
- f"SQLAlchemy: create_element error. No blob_storage_client is configured!"
460
+ "SQLAlchemy: create_element error. No blob_storage_client is configured!"
400
461
  )
401
462
  return
402
463
  if not element.for_id:
@@ -421,10 +482,8 @@ class SQLAlchemyDataLayer(BaseDataLayer):
421
482
  if content is None:
422
483
  raise ValueError("Content is None, cannot upload file")
423
484
 
424
- context_user = context.session.user
425
-
426
- user_folder = getattr(context_user, "id", "unknown")
427
- file_object_key = f"{user_folder}/{element.id}" + (
485
+ user_id: str = await self._get_user_id_by_thread(element.thread_id) or "unknown"
486
+ file_object_key = f"{user_id}/{element.id}" + (
428
487
  f"/{element.name}" if element.name else ""
429
488
  )
430
489
 
@@ -458,15 +517,12 @@ class SQLAlchemyDataLayer(BaseDataLayer):
458
517
  parameters = {"id": element_id}
459
518
  await self.execute_sql(query=query, parameters=parameters)
460
519
 
461
- async def delete_user_session(self, id: str) -> bool:
462
- return False # Not sure why documentation wants this
463
-
464
520
  async def get_all_user_threads(
465
521
  self, user_id: Optional[str] = None, thread_id: Optional[str] = None
466
522
  ) -> Optional[List[ThreadDict]]:
467
523
  """Fetch all user threads up to self.user_thread_limit, or one thread by id if thread_id is provided."""
468
524
  if self.show_logger:
469
- logger.info(f"SQLAlchemy: get_all_user_threads")
525
+ logger.info("SQLAlchemy: get_all_user_threads")
470
526
  user_threads_query = """
471
527
  SELECT
472
528
  "id" AS thread_id,
@@ -522,7 +578,8 @@ class SQLAlchemyDataLayer(BaseDataLayer):
522
578
  s."language" AS step_language,
523
579
  s."indent" AS step_indent,
524
580
  f."value" AS feedback_value,
525
- f."comment" AS feedback_comment
581
+ f."comment" AS feedback_comment,
582
+ f."id" AS feedback_id
526
583
  FROM steps s LEFT JOIN feedbacks f ON s."id" = f."forId"
527
584
  WHERE s."threadId" IN {thread_ids}
528
585
  ORDER BY s."createdAt" ASC
@@ -596,8 +653,9 @@ class SQLAlchemyDataLayer(BaseDataLayer):
596
653
  tags=step_feedback.get("step_tags"),
597
654
  input=(
598
655
  step_feedback.get("step_input", "")
599
- if step_feedback["step_showinput"] == "true"
600
- else None
656
+ if step_feedback.get("step_showinput")
657
+ not in [None, "false"]
658
+ else ""
601
659
  ),
602
660
  output=step_feedback.get("step_output", ""),
603
661
  createdAt=step_feedback.get("step_createdat"),
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: PraisonAI
3
- Version: 0.0.66
3
+ Version: 0.0.68
4
4
  Summary: PraisonAI application combines AutoGen and CrewAI or similar frameworks into a low-code solution for building and managing multi-agent LLM systems, focusing on simplicity, customization, and efficient human-agent collaboration.
5
5
  Author: Mervin Praison
6
6
  Requires-Python: >=3.10,<3.13
@@ -4,7 +4,7 @@ praisonai/agents_generator.py,sha256=8d1WRbubvEkBrW1HZ7_xnGyqgJi0yxmXa3MgTIqef1c
4
4
  praisonai/auto.py,sha256=9spTXqj47Hmmqv5QHRYE_RzSVHH_KoPbaZjskUj2UcE,7895
5
5
  praisonai/chainlit_ui.py,sha256=bNR7s509lp0I9JlJNvwCZRUZosC64qdvlFCt8NmFamQ,12216
6
6
  praisonai/cli.py,sha256=M23MbUUzNS7z9ZHz3cGawUrGWzXM-FzhMyiRWQPZSEk,18485
7
- praisonai/deploy.py,sha256=XjrgXuYb8otkQ4Y1fYah0Xo4S0wAQUcofBszCMbL5OE,6028
7
+ praisonai/deploy.py,sha256=HBBlpkKwaI7tANVanHejKi7qYkZ21Yu1Fj3jwgZ6cz0,6028
8
8
  praisonai/inbuilt_tools/__init__.py,sha256=mUKnbL6Gram9c9f2m8wJwEzURBLmPEOcHzwySBH89YA,74
9
9
  praisonai/inbuilt_tools/autogen_tools.py,sha256=svYkM2N7DVFvbiwgoAS7U_MqTOD8rHf8VD3BaFUV5_Y,14907
10
10
  praisonai/inc/__init__.py,sha256=sPDlYBBwdk0VlWzaaM_lG0_LD07lS2HRGvPdxXJFiYg,62
@@ -22,7 +22,7 @@ praisonai/public/logo_dark.png,sha256=frHz1zkrnivGssJgk9iy1cabojkVgm8B4MllFwL_Cn
22
22
  praisonai/public/logo_light.png,sha256=8cQRti_Ysa30O3_7C3ku2w40LnVUUlUok47H-3ZZHSU,19656
23
23
  praisonai/public/movie.svg,sha256=aJ2EQ8vXZusVsF2SeuAVxP4RFJzQ14T26ejrGYdBgzk,1289
24
24
  praisonai/public/thriller.svg,sha256=2dYY72EcgbEyTxS4QzjAm37Y4srtPWEW4vCMFki98ZI,3163
25
- praisonai/setup/__init__.py ,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
25
+ praisonai/setup/__init__.py,sha256=frcCV1k9oG9oKj3dpUqdJg1PxRT2RSN_XKdLCPjaYaY,2
26
26
  praisonai/setup/build.py,sha256=NyTAXQ_UZ8vKo_KwCINp8ctmauZyCMDkw1rys3ay0ec,646
27
27
  praisonai/setup/config.yaml,sha256=sr_D1RIvv3LQ_eueOMZV0rAUiWTR-n2xuE1RhKK6b34,1211
28
28
  praisonai/setup/post_install.py,sha256=hXukn_7bL64vE582SZcS-9MiZGeJj6hN7upoR1oJ-Bo,576
@@ -31,7 +31,7 @@ praisonai/setup/setup_conda_env.sh,sha256=te7s0KHsTi7XM-vkNvE0dKC1HeU2tXxqE-sPUS
31
31
  praisonai/test.py,sha256=OL-wesjA5JTohr8rtr6kWoaS4ImkJg2l0GXJ-dUUfRU,4090
32
32
  praisonai/train.py,sha256=DvORlrwKOD-2v4r_z84eV3LsfzpNs-WnPKb5cQB3_t4,11071
33
33
  praisonai/ui/chat.py,sha256=V4kG2jog8FK0zHbcG_gTS58JzeriG_ZTorCjEnjJz38,9383
34
- praisonai/ui/code.py,sha256=MaegqaKknkPup1AVoVIkVLa7YUp25kytqq_udm0xtIg,10157
34
+ praisonai/ui/code.py,sha256=aVIxnMd-4qeA8ZjoOM7XfBt05SWHgwFoJWW3sNIWYzE,10149
35
35
  praisonai/ui/context.py,sha256=oWO2I_WBZb7kZnuXItf18EJX0ZQv-1nAd8rxhwhuuDU,11871
36
36
  praisonai/ui/public/fantasy.svg,sha256=4Gs3kIOux-pjGtw6ogI_rv5_viVJxnE5gRwGilsSg0o,1553
37
37
  praisonai/ui/public/game.svg,sha256=y2QMaA01m8XzuDjTOBWzupOC3-TpnUl9ah89mIhviUw,2406
@@ -39,10 +39,10 @@ praisonai/ui/public/logo_dark.png,sha256=frHz1zkrnivGssJgk9iy1cabojkVgm8B4MllFwL
39
39
  praisonai/ui/public/logo_light.png,sha256=8cQRti_Ysa30O3_7C3ku2w40LnVUUlUok47H-3ZZHSU,19656
40
40
  praisonai/ui/public/movie.svg,sha256=aJ2EQ8vXZusVsF2SeuAVxP4RFJzQ14T26ejrGYdBgzk,1289
41
41
  praisonai/ui/public/thriller.svg,sha256=2dYY72EcgbEyTxS4QzjAm37Y4srtPWEW4vCMFki98ZI,3163
42
- praisonai/ui/sql_alchemy.py,sha256=HsyeRq-G9qbQobHWpTJHHKQiT4FvYw_7iuv-2PNh0IU,27419
42
+ praisonai/ui/sql_alchemy.py,sha256=CABakQ2WVZbZcUnfRv_9THAcMz4Mp9BIukw8ZN4kMXk,29510
43
43
  praisonai/version.py,sha256=ugyuFliEqtAwQmH4sTlc16YXKYbFWDmfyk87fErB8-8,21
44
- praisonai-0.0.66.dist-info/LICENSE,sha256=kqvFysVlnFxYOu0HxCe2HlmZmJtdmNGOxWRRkT9TsWc,1035
45
- praisonai-0.0.66.dist-info/METADATA,sha256=AXsHQUxTKnza0LBXTskOP33g-XlAxCvYcFqUPGcUZKE,11406
46
- praisonai-0.0.66.dist-info/WHEEL,sha256=HBsDV7Hj4OTiS1GX6ua7iQXUQTB9UHftbBxr7Q8Xm9c,110
47
- praisonai-0.0.66.dist-info/entry_points.txt,sha256=jB078LEGLY3Ky_indhclomRIVVpXrPSksHjJ-tcBZ-o,133
48
- praisonai-0.0.66.dist-info/RECORD,,
44
+ praisonai-0.0.68.dist-info/LICENSE,sha256=kqvFysVlnFxYOu0HxCe2HlmZmJtdmNGOxWRRkT9TsWc,1035
45
+ praisonai-0.0.68.dist-info/METADATA,sha256=B2ADo7iPbkiCGaMsnctG0o3F9uHcrSFkVeaY77xKtoU,11406
46
+ praisonai-0.0.68.dist-info/WHEEL,sha256=HBsDV7Hj4OTiS1GX6ua7iQXUQTB9UHftbBxr7Q8Xm9c,110
47
+ praisonai-0.0.68.dist-info/entry_points.txt,sha256=jB078LEGLY3Ky_indhclomRIVVpXrPSksHjJ-tcBZ-o,133
48
+ praisonai-0.0.68.dist-info/RECORD,,
File without changes