PraisonAI 3.0.0__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.
Files changed (393) hide show
  1. praisonai/__init__.py +54 -0
  2. praisonai/__main__.py +15 -0
  3. praisonai/acp/__init__.py +54 -0
  4. praisonai/acp/config.py +159 -0
  5. praisonai/acp/server.py +587 -0
  6. praisonai/acp/session.py +219 -0
  7. praisonai/adapters/__init__.py +50 -0
  8. praisonai/adapters/readers.py +395 -0
  9. praisonai/adapters/rerankers.py +315 -0
  10. praisonai/adapters/retrievers.py +394 -0
  11. praisonai/adapters/vector_stores.py +409 -0
  12. praisonai/agent_scheduler.py +337 -0
  13. praisonai/agents_generator.py +903 -0
  14. praisonai/api/call.py +292 -0
  15. praisonai/auto.py +1197 -0
  16. praisonai/capabilities/__init__.py +275 -0
  17. praisonai/capabilities/a2a.py +140 -0
  18. praisonai/capabilities/assistants.py +283 -0
  19. praisonai/capabilities/audio.py +320 -0
  20. praisonai/capabilities/batches.py +469 -0
  21. praisonai/capabilities/completions.py +336 -0
  22. praisonai/capabilities/container_files.py +155 -0
  23. praisonai/capabilities/containers.py +93 -0
  24. praisonai/capabilities/embeddings.py +158 -0
  25. praisonai/capabilities/files.py +467 -0
  26. praisonai/capabilities/fine_tuning.py +293 -0
  27. praisonai/capabilities/guardrails.py +182 -0
  28. praisonai/capabilities/images.py +330 -0
  29. praisonai/capabilities/mcp.py +190 -0
  30. praisonai/capabilities/messages.py +270 -0
  31. praisonai/capabilities/moderations.py +154 -0
  32. praisonai/capabilities/ocr.py +217 -0
  33. praisonai/capabilities/passthrough.py +204 -0
  34. praisonai/capabilities/rag.py +207 -0
  35. praisonai/capabilities/realtime.py +160 -0
  36. praisonai/capabilities/rerank.py +165 -0
  37. praisonai/capabilities/responses.py +266 -0
  38. praisonai/capabilities/search.py +109 -0
  39. praisonai/capabilities/skills.py +133 -0
  40. praisonai/capabilities/vector_store_files.py +334 -0
  41. praisonai/capabilities/vector_stores.py +304 -0
  42. praisonai/capabilities/videos.py +141 -0
  43. praisonai/chainlit_ui.py +304 -0
  44. praisonai/chat/__init__.py +106 -0
  45. praisonai/chat/app.py +125 -0
  46. praisonai/cli/__init__.py +26 -0
  47. praisonai/cli/app.py +213 -0
  48. praisonai/cli/commands/__init__.py +75 -0
  49. praisonai/cli/commands/acp.py +70 -0
  50. praisonai/cli/commands/completion.py +333 -0
  51. praisonai/cli/commands/config.py +166 -0
  52. praisonai/cli/commands/debug.py +142 -0
  53. praisonai/cli/commands/diag.py +55 -0
  54. praisonai/cli/commands/doctor.py +166 -0
  55. praisonai/cli/commands/environment.py +179 -0
  56. praisonai/cli/commands/lsp.py +112 -0
  57. praisonai/cli/commands/mcp.py +210 -0
  58. praisonai/cli/commands/profile.py +457 -0
  59. praisonai/cli/commands/run.py +228 -0
  60. praisonai/cli/commands/schedule.py +150 -0
  61. praisonai/cli/commands/serve.py +97 -0
  62. praisonai/cli/commands/session.py +212 -0
  63. praisonai/cli/commands/traces.py +145 -0
  64. praisonai/cli/commands/version.py +101 -0
  65. praisonai/cli/configuration/__init__.py +18 -0
  66. praisonai/cli/configuration/loader.py +353 -0
  67. praisonai/cli/configuration/paths.py +114 -0
  68. praisonai/cli/configuration/schema.py +164 -0
  69. praisonai/cli/features/__init__.py +268 -0
  70. praisonai/cli/features/acp.py +236 -0
  71. praisonai/cli/features/action_orchestrator.py +546 -0
  72. praisonai/cli/features/agent_scheduler.py +773 -0
  73. praisonai/cli/features/agent_tools.py +474 -0
  74. praisonai/cli/features/agents.py +375 -0
  75. praisonai/cli/features/at_mentions.py +471 -0
  76. praisonai/cli/features/auto_memory.py +182 -0
  77. praisonai/cli/features/autonomy_mode.py +490 -0
  78. praisonai/cli/features/background.py +356 -0
  79. praisonai/cli/features/base.py +168 -0
  80. praisonai/cli/features/capabilities.py +1326 -0
  81. praisonai/cli/features/checkpoints.py +338 -0
  82. praisonai/cli/features/code_intelligence.py +652 -0
  83. praisonai/cli/features/compaction.py +294 -0
  84. praisonai/cli/features/compare.py +534 -0
  85. praisonai/cli/features/cost_tracker.py +514 -0
  86. praisonai/cli/features/debug.py +810 -0
  87. praisonai/cli/features/deploy.py +517 -0
  88. praisonai/cli/features/diag.py +289 -0
  89. praisonai/cli/features/doctor/__init__.py +63 -0
  90. praisonai/cli/features/doctor/checks/__init__.py +24 -0
  91. praisonai/cli/features/doctor/checks/acp_checks.py +240 -0
  92. praisonai/cli/features/doctor/checks/config_checks.py +366 -0
  93. praisonai/cli/features/doctor/checks/db_checks.py +366 -0
  94. praisonai/cli/features/doctor/checks/env_checks.py +543 -0
  95. praisonai/cli/features/doctor/checks/lsp_checks.py +199 -0
  96. praisonai/cli/features/doctor/checks/mcp_checks.py +349 -0
  97. praisonai/cli/features/doctor/checks/memory_checks.py +268 -0
  98. praisonai/cli/features/doctor/checks/network_checks.py +251 -0
  99. praisonai/cli/features/doctor/checks/obs_checks.py +328 -0
  100. praisonai/cli/features/doctor/checks/performance_checks.py +235 -0
  101. praisonai/cli/features/doctor/checks/permissions_checks.py +259 -0
  102. praisonai/cli/features/doctor/checks/selftest_checks.py +322 -0
  103. praisonai/cli/features/doctor/checks/serve_checks.py +426 -0
  104. praisonai/cli/features/doctor/checks/skills_checks.py +231 -0
  105. praisonai/cli/features/doctor/checks/tools_checks.py +371 -0
  106. praisonai/cli/features/doctor/engine.py +266 -0
  107. praisonai/cli/features/doctor/formatters.py +310 -0
  108. praisonai/cli/features/doctor/handler.py +397 -0
  109. praisonai/cli/features/doctor/models.py +264 -0
  110. praisonai/cli/features/doctor/registry.py +239 -0
  111. praisonai/cli/features/endpoints.py +1019 -0
  112. praisonai/cli/features/eval.py +560 -0
  113. praisonai/cli/features/external_agents.py +231 -0
  114. praisonai/cli/features/fast_context.py +410 -0
  115. praisonai/cli/features/flow_display.py +566 -0
  116. praisonai/cli/features/git_integration.py +651 -0
  117. praisonai/cli/features/guardrail.py +171 -0
  118. praisonai/cli/features/handoff.py +185 -0
  119. praisonai/cli/features/hooks.py +583 -0
  120. praisonai/cli/features/image.py +384 -0
  121. praisonai/cli/features/interactive_runtime.py +585 -0
  122. praisonai/cli/features/interactive_tools.py +380 -0
  123. praisonai/cli/features/interactive_tui.py +603 -0
  124. praisonai/cli/features/jobs.py +632 -0
  125. praisonai/cli/features/knowledge.py +531 -0
  126. praisonai/cli/features/lite.py +244 -0
  127. praisonai/cli/features/lsp_cli.py +225 -0
  128. praisonai/cli/features/mcp.py +169 -0
  129. praisonai/cli/features/message_queue.py +587 -0
  130. praisonai/cli/features/metrics.py +211 -0
  131. praisonai/cli/features/n8n.py +673 -0
  132. praisonai/cli/features/observability.py +293 -0
  133. praisonai/cli/features/ollama.py +361 -0
  134. praisonai/cli/features/output_style.py +273 -0
  135. praisonai/cli/features/package.py +631 -0
  136. praisonai/cli/features/performance.py +308 -0
  137. praisonai/cli/features/persistence.py +636 -0
  138. praisonai/cli/features/profile.py +226 -0
  139. praisonai/cli/features/profiler/__init__.py +81 -0
  140. praisonai/cli/features/profiler/core.py +558 -0
  141. praisonai/cli/features/profiler/optimizations.py +652 -0
  142. praisonai/cli/features/profiler/suite.py +386 -0
  143. praisonai/cli/features/profiling.py +350 -0
  144. praisonai/cli/features/queue/__init__.py +73 -0
  145. praisonai/cli/features/queue/manager.py +395 -0
  146. praisonai/cli/features/queue/models.py +286 -0
  147. praisonai/cli/features/queue/persistence.py +564 -0
  148. praisonai/cli/features/queue/scheduler.py +484 -0
  149. praisonai/cli/features/queue/worker.py +372 -0
  150. praisonai/cli/features/recipe.py +1723 -0
  151. praisonai/cli/features/recipes.py +449 -0
  152. praisonai/cli/features/registry.py +229 -0
  153. praisonai/cli/features/repo_map.py +860 -0
  154. praisonai/cli/features/router.py +466 -0
  155. praisonai/cli/features/sandbox_executor.py +515 -0
  156. praisonai/cli/features/serve.py +829 -0
  157. praisonai/cli/features/session.py +222 -0
  158. praisonai/cli/features/skills.py +856 -0
  159. praisonai/cli/features/slash_commands.py +650 -0
  160. praisonai/cli/features/telemetry.py +179 -0
  161. praisonai/cli/features/templates.py +1384 -0
  162. praisonai/cli/features/thinking.py +305 -0
  163. praisonai/cli/features/todo.py +334 -0
  164. praisonai/cli/features/tools.py +680 -0
  165. praisonai/cli/features/tui/__init__.py +83 -0
  166. praisonai/cli/features/tui/app.py +580 -0
  167. praisonai/cli/features/tui/cli.py +566 -0
  168. praisonai/cli/features/tui/debug.py +511 -0
  169. praisonai/cli/features/tui/events.py +99 -0
  170. praisonai/cli/features/tui/mock_provider.py +328 -0
  171. praisonai/cli/features/tui/orchestrator.py +652 -0
  172. praisonai/cli/features/tui/screens/__init__.py +50 -0
  173. praisonai/cli/features/tui/screens/main.py +245 -0
  174. praisonai/cli/features/tui/screens/queue.py +174 -0
  175. praisonai/cli/features/tui/screens/session.py +124 -0
  176. praisonai/cli/features/tui/screens/settings.py +148 -0
  177. praisonai/cli/features/tui/widgets/__init__.py +56 -0
  178. praisonai/cli/features/tui/widgets/chat.py +261 -0
  179. praisonai/cli/features/tui/widgets/composer.py +224 -0
  180. praisonai/cli/features/tui/widgets/queue_panel.py +200 -0
  181. praisonai/cli/features/tui/widgets/status.py +167 -0
  182. praisonai/cli/features/tui/widgets/tool_panel.py +248 -0
  183. praisonai/cli/features/workflow.py +720 -0
  184. praisonai/cli/legacy.py +236 -0
  185. praisonai/cli/main.py +5559 -0
  186. praisonai/cli/schedule_cli.py +54 -0
  187. praisonai/cli/state/__init__.py +31 -0
  188. praisonai/cli/state/identifiers.py +161 -0
  189. praisonai/cli/state/sessions.py +313 -0
  190. praisonai/code/__init__.py +93 -0
  191. praisonai/code/agent_tools.py +344 -0
  192. praisonai/code/diff/__init__.py +21 -0
  193. praisonai/code/diff/diff_strategy.py +432 -0
  194. praisonai/code/tools/__init__.py +27 -0
  195. praisonai/code/tools/apply_diff.py +221 -0
  196. praisonai/code/tools/execute_command.py +275 -0
  197. praisonai/code/tools/list_files.py +274 -0
  198. praisonai/code/tools/read_file.py +206 -0
  199. praisonai/code/tools/search_replace.py +248 -0
  200. praisonai/code/tools/write_file.py +217 -0
  201. praisonai/code/utils/__init__.py +46 -0
  202. praisonai/code/utils/file_utils.py +307 -0
  203. praisonai/code/utils/ignore_utils.py +308 -0
  204. praisonai/code/utils/text_utils.py +276 -0
  205. praisonai/db/__init__.py +64 -0
  206. praisonai/db/adapter.py +531 -0
  207. praisonai/deploy/__init__.py +62 -0
  208. praisonai/deploy/api.py +231 -0
  209. praisonai/deploy/docker.py +454 -0
  210. praisonai/deploy/doctor.py +367 -0
  211. praisonai/deploy/main.py +327 -0
  212. praisonai/deploy/models.py +179 -0
  213. praisonai/deploy/providers/__init__.py +33 -0
  214. praisonai/deploy/providers/aws.py +331 -0
  215. praisonai/deploy/providers/azure.py +358 -0
  216. praisonai/deploy/providers/base.py +101 -0
  217. praisonai/deploy/providers/gcp.py +314 -0
  218. praisonai/deploy/schema.py +208 -0
  219. praisonai/deploy.py +185 -0
  220. praisonai/endpoints/__init__.py +53 -0
  221. praisonai/endpoints/a2u_server.py +410 -0
  222. praisonai/endpoints/discovery.py +165 -0
  223. praisonai/endpoints/providers/__init__.py +28 -0
  224. praisonai/endpoints/providers/a2a.py +253 -0
  225. praisonai/endpoints/providers/a2u.py +208 -0
  226. praisonai/endpoints/providers/agents_api.py +171 -0
  227. praisonai/endpoints/providers/base.py +231 -0
  228. praisonai/endpoints/providers/mcp.py +263 -0
  229. praisonai/endpoints/providers/recipe.py +206 -0
  230. praisonai/endpoints/providers/tools_mcp.py +150 -0
  231. praisonai/endpoints/registry.py +131 -0
  232. praisonai/endpoints/server.py +161 -0
  233. praisonai/inbuilt_tools/__init__.py +24 -0
  234. praisonai/inbuilt_tools/autogen_tools.py +117 -0
  235. praisonai/inc/__init__.py +2 -0
  236. praisonai/inc/config.py +96 -0
  237. praisonai/inc/models.py +155 -0
  238. praisonai/integrations/__init__.py +56 -0
  239. praisonai/integrations/base.py +303 -0
  240. praisonai/integrations/claude_code.py +270 -0
  241. praisonai/integrations/codex_cli.py +255 -0
  242. praisonai/integrations/cursor_cli.py +195 -0
  243. praisonai/integrations/gemini_cli.py +222 -0
  244. praisonai/jobs/__init__.py +67 -0
  245. praisonai/jobs/executor.py +425 -0
  246. praisonai/jobs/models.py +230 -0
  247. praisonai/jobs/router.py +314 -0
  248. praisonai/jobs/server.py +186 -0
  249. praisonai/jobs/store.py +203 -0
  250. praisonai/llm/__init__.py +66 -0
  251. praisonai/llm/registry.py +382 -0
  252. praisonai/mcp_server/__init__.py +152 -0
  253. praisonai/mcp_server/adapters/__init__.py +74 -0
  254. praisonai/mcp_server/adapters/agents.py +128 -0
  255. praisonai/mcp_server/adapters/capabilities.py +168 -0
  256. praisonai/mcp_server/adapters/cli_tools.py +568 -0
  257. praisonai/mcp_server/adapters/extended_capabilities.py +462 -0
  258. praisonai/mcp_server/adapters/knowledge.py +93 -0
  259. praisonai/mcp_server/adapters/memory.py +104 -0
  260. praisonai/mcp_server/adapters/prompts.py +306 -0
  261. praisonai/mcp_server/adapters/resources.py +124 -0
  262. praisonai/mcp_server/adapters/tools_bridge.py +280 -0
  263. praisonai/mcp_server/auth/__init__.py +48 -0
  264. praisonai/mcp_server/auth/api_key.py +291 -0
  265. praisonai/mcp_server/auth/oauth.py +460 -0
  266. praisonai/mcp_server/auth/oidc.py +289 -0
  267. praisonai/mcp_server/auth/scopes.py +260 -0
  268. praisonai/mcp_server/cli.py +852 -0
  269. praisonai/mcp_server/elicitation.py +445 -0
  270. praisonai/mcp_server/icons.py +302 -0
  271. praisonai/mcp_server/recipe_adapter.py +573 -0
  272. praisonai/mcp_server/recipe_cli.py +824 -0
  273. praisonai/mcp_server/registry.py +703 -0
  274. praisonai/mcp_server/sampling.py +422 -0
  275. praisonai/mcp_server/server.py +490 -0
  276. praisonai/mcp_server/tasks.py +443 -0
  277. praisonai/mcp_server/transports/__init__.py +18 -0
  278. praisonai/mcp_server/transports/http_stream.py +376 -0
  279. praisonai/mcp_server/transports/stdio.py +132 -0
  280. praisonai/persistence/__init__.py +84 -0
  281. praisonai/persistence/config.py +238 -0
  282. praisonai/persistence/conversation/__init__.py +25 -0
  283. praisonai/persistence/conversation/async_mysql.py +427 -0
  284. praisonai/persistence/conversation/async_postgres.py +410 -0
  285. praisonai/persistence/conversation/async_sqlite.py +371 -0
  286. praisonai/persistence/conversation/base.py +151 -0
  287. praisonai/persistence/conversation/json_store.py +250 -0
  288. praisonai/persistence/conversation/mysql.py +387 -0
  289. praisonai/persistence/conversation/postgres.py +401 -0
  290. praisonai/persistence/conversation/singlestore.py +240 -0
  291. praisonai/persistence/conversation/sqlite.py +341 -0
  292. praisonai/persistence/conversation/supabase.py +203 -0
  293. praisonai/persistence/conversation/surrealdb.py +287 -0
  294. praisonai/persistence/factory.py +301 -0
  295. praisonai/persistence/hooks/__init__.py +18 -0
  296. praisonai/persistence/hooks/agent_hooks.py +297 -0
  297. praisonai/persistence/knowledge/__init__.py +26 -0
  298. praisonai/persistence/knowledge/base.py +144 -0
  299. praisonai/persistence/knowledge/cassandra.py +232 -0
  300. praisonai/persistence/knowledge/chroma.py +295 -0
  301. praisonai/persistence/knowledge/clickhouse.py +242 -0
  302. praisonai/persistence/knowledge/cosmosdb_vector.py +438 -0
  303. praisonai/persistence/knowledge/couchbase.py +286 -0
  304. praisonai/persistence/knowledge/lancedb.py +216 -0
  305. praisonai/persistence/knowledge/langchain_adapter.py +291 -0
  306. praisonai/persistence/knowledge/lightrag_adapter.py +212 -0
  307. praisonai/persistence/knowledge/llamaindex_adapter.py +256 -0
  308. praisonai/persistence/knowledge/milvus.py +277 -0
  309. praisonai/persistence/knowledge/mongodb_vector.py +306 -0
  310. praisonai/persistence/knowledge/pgvector.py +335 -0
  311. praisonai/persistence/knowledge/pinecone.py +253 -0
  312. praisonai/persistence/knowledge/qdrant.py +301 -0
  313. praisonai/persistence/knowledge/redis_vector.py +291 -0
  314. praisonai/persistence/knowledge/singlestore_vector.py +299 -0
  315. praisonai/persistence/knowledge/surrealdb_vector.py +309 -0
  316. praisonai/persistence/knowledge/upstash_vector.py +266 -0
  317. praisonai/persistence/knowledge/weaviate.py +223 -0
  318. praisonai/persistence/migrations/__init__.py +10 -0
  319. praisonai/persistence/migrations/manager.py +251 -0
  320. praisonai/persistence/orchestrator.py +406 -0
  321. praisonai/persistence/state/__init__.py +21 -0
  322. praisonai/persistence/state/async_mongodb.py +200 -0
  323. praisonai/persistence/state/base.py +107 -0
  324. praisonai/persistence/state/dynamodb.py +226 -0
  325. praisonai/persistence/state/firestore.py +175 -0
  326. praisonai/persistence/state/gcs.py +155 -0
  327. praisonai/persistence/state/memory.py +245 -0
  328. praisonai/persistence/state/mongodb.py +158 -0
  329. praisonai/persistence/state/redis.py +190 -0
  330. praisonai/persistence/state/upstash.py +144 -0
  331. praisonai/persistence/tests/__init__.py +3 -0
  332. praisonai/persistence/tests/test_all_backends.py +633 -0
  333. praisonai/profiler.py +1214 -0
  334. praisonai/recipe/__init__.py +134 -0
  335. praisonai/recipe/bridge.py +278 -0
  336. praisonai/recipe/core.py +893 -0
  337. praisonai/recipe/exceptions.py +54 -0
  338. praisonai/recipe/history.py +402 -0
  339. praisonai/recipe/models.py +266 -0
  340. praisonai/recipe/operations.py +440 -0
  341. praisonai/recipe/policy.py +422 -0
  342. praisonai/recipe/registry.py +849 -0
  343. praisonai/recipe/runtime.py +214 -0
  344. praisonai/recipe/security.py +711 -0
  345. praisonai/recipe/serve.py +859 -0
  346. praisonai/recipe/server.py +613 -0
  347. praisonai/scheduler/__init__.py +45 -0
  348. praisonai/scheduler/agent_scheduler.py +552 -0
  349. praisonai/scheduler/base.py +124 -0
  350. praisonai/scheduler/daemon_manager.py +225 -0
  351. praisonai/scheduler/state_manager.py +155 -0
  352. praisonai/scheduler/yaml_loader.py +193 -0
  353. praisonai/scheduler.py +194 -0
  354. praisonai/setup/__init__.py +1 -0
  355. praisonai/setup/build.py +21 -0
  356. praisonai/setup/post_install.py +23 -0
  357. praisonai/setup/setup_conda_env.py +25 -0
  358. praisonai/setup.py +16 -0
  359. praisonai/templates/__init__.py +116 -0
  360. praisonai/templates/cache.py +364 -0
  361. praisonai/templates/dependency_checker.py +358 -0
  362. praisonai/templates/discovery.py +391 -0
  363. praisonai/templates/loader.py +564 -0
  364. praisonai/templates/registry.py +511 -0
  365. praisonai/templates/resolver.py +206 -0
  366. praisonai/templates/security.py +327 -0
  367. praisonai/templates/tool_override.py +498 -0
  368. praisonai/templates/tools_doctor.py +256 -0
  369. praisonai/test.py +105 -0
  370. praisonai/train.py +562 -0
  371. praisonai/train_vision.py +306 -0
  372. praisonai/ui/agents.py +824 -0
  373. praisonai/ui/callbacks.py +57 -0
  374. praisonai/ui/chainlit_compat.py +246 -0
  375. praisonai/ui/chat.py +532 -0
  376. praisonai/ui/code.py +717 -0
  377. praisonai/ui/colab.py +474 -0
  378. praisonai/ui/colab_chainlit.py +81 -0
  379. praisonai/ui/components/aicoder.py +284 -0
  380. praisonai/ui/context.py +283 -0
  381. praisonai/ui/database_config.py +56 -0
  382. praisonai/ui/db.py +294 -0
  383. praisonai/ui/realtime.py +488 -0
  384. praisonai/ui/realtimeclient/__init__.py +756 -0
  385. praisonai/ui/realtimeclient/tools.py +242 -0
  386. praisonai/ui/sql_alchemy.py +710 -0
  387. praisonai/upload_vision.py +140 -0
  388. praisonai/version.py +1 -0
  389. praisonai-3.0.0.dist-info/METADATA +3493 -0
  390. praisonai-3.0.0.dist-info/RECORD +393 -0
  391. praisonai-3.0.0.dist-info/WHEEL +5 -0
  392. praisonai-3.0.0.dist-info/entry_points.txt +4 -0
  393. praisonai-3.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,531 @@
1
+ """
2
+ PraisonDB adapter - implements the DbAdapter protocol from praisonaiagents.
3
+
4
+ This module provides the bridge between the core Agent's db interface
5
+ and the wrapper's persistence layer (PersistenceOrchestrator).
6
+ """
7
+
8
+ import time
9
+ import logging
10
+ from typing import Any, Dict, List, Optional
11
+
12
+ logger = logging.getLogger(__name__)
13
+
14
+
15
+ class PraisonDB:
16
+ """
17
+ Universal database adapter for PraisonAI agents.
18
+
19
+ Automatically selects backends based on URL or explicit configuration.
20
+ Implements the DbAdapter protocol expected by praisonaiagents.Agent.
21
+
22
+ Example:
23
+ from praisonaiagents import Agent
24
+ from praisonai.db import PraisonDB
25
+
26
+ # Simple usage with PostgreSQL
27
+ db = PraisonDB(database_url="postgresql://localhost/mydb")
28
+ agent = Agent(name="Assistant", db=db, session_id="my-session")
29
+ agent.chat("Hello!")
30
+
31
+ # With multiple backends
32
+ db = PraisonDB(
33
+ database_url="postgresql://localhost/mydb",
34
+ state_url="redis://localhost:6379"
35
+ )
36
+ """
37
+
38
+ def __init__(
39
+ self,
40
+ database_url: Optional[str] = None,
41
+ state_url: Optional[str] = None,
42
+ knowledge_url: Optional[str] = None,
43
+ **options
44
+ ):
45
+ """
46
+ Initialize PraisonDB adapter.
47
+
48
+ Args:
49
+ database_url: URL for conversation storage (postgres, mysql, sqlite)
50
+ state_url: URL for state storage (redis, etc.)
51
+ knowledge_url: URL for knowledge/vector storage (qdrant, etc.)
52
+ **options: Additional backend-specific options
53
+ """
54
+ self._database_url = database_url
55
+ self._state_url = state_url
56
+ self._knowledge_url = knowledge_url
57
+ self._options = options
58
+
59
+ # Lazy-loaded stores
60
+ self._conversation_store = None
61
+ self._state_store = None
62
+ self._knowledge_store = None
63
+ self._initialized = False
64
+
65
+ def _init_stores(self):
66
+ """Lazily initialize stores on first use."""
67
+ if self._initialized:
68
+ return
69
+
70
+ # Import persistence layer
71
+ from ..persistence.factory import (
72
+ create_conversation_store,
73
+ create_state_store,
74
+ create_knowledge_store,
75
+ )
76
+
77
+ # Initialize conversation store
78
+ if self._database_url:
79
+ backend = self._detect_backend(self._database_url)
80
+ self._conversation_store = create_conversation_store(
81
+ backend, url=self._database_url, **self._options
82
+ )
83
+
84
+ # Initialize state store
85
+ if self._state_url:
86
+ backend = self._detect_backend(self._state_url)
87
+ self._state_store = create_state_store(
88
+ backend, url=self._state_url, **self._options
89
+ )
90
+
91
+ # Initialize knowledge store
92
+ if self._knowledge_url:
93
+ backend = self._detect_backend(self._knowledge_url)
94
+ self._knowledge_store = create_knowledge_store(
95
+ backend, url=self._knowledge_url, **self._options
96
+ )
97
+
98
+ self._initialized = True
99
+
100
+ def _detect_backend(self, url: str) -> str:
101
+ """Detect backend type from URL."""
102
+ url_lower = url.lower()
103
+
104
+ if url_lower.startswith("postgresql://") or url_lower.startswith("postgres://"):
105
+ return "postgres"
106
+ elif url_lower.startswith("mysql://"):
107
+ return "mysql"
108
+ elif url_lower.startswith("sqlite://") or url_lower.endswith(".db"):
109
+ return "sqlite"
110
+ elif url_lower.startswith("redis://"):
111
+ return "redis"
112
+ elif url_lower.startswith("http://") or url_lower.startswith("https://"):
113
+ # Could be Qdrant, Weaviate, etc.
114
+ if "qdrant" in url_lower or ":6333" in url_lower:
115
+ return "qdrant"
116
+ elif "weaviate" in url_lower:
117
+ return "weaviate"
118
+
119
+ # Default fallback
120
+ return "sqlite"
121
+
122
+ def on_agent_start(
123
+ self,
124
+ agent_name: str,
125
+ session_id: str,
126
+ user_id: Optional[str] = None,
127
+ metadata: Optional[Dict[str, Any]] = None,
128
+ ) -> List:
129
+ """Called when agent starts - returns previous messages for resume."""
130
+ self._init_stores()
131
+
132
+ if not self._conversation_store:
133
+ return []
134
+
135
+ from ..persistence.conversation.base import ConversationSession
136
+
137
+ # Check if session exists
138
+ session = self._conversation_store.get_session(session_id)
139
+
140
+ if session is None:
141
+ # Create new session
142
+ session = ConversationSession(
143
+ session_id=session_id,
144
+ user_id=user_id or "default",
145
+ agent_id=agent_name,
146
+ name=f"Session {session_id}",
147
+ metadata=metadata or {}
148
+ )
149
+ self._conversation_store.create_session(session)
150
+ return []
151
+
152
+ # Resume existing session - get messages
153
+ messages = self._conversation_store.get_messages(session_id)
154
+
155
+ # Convert to DbMessage format
156
+ from praisonaiagents.db.protocol import DbMessage
157
+ return [
158
+ DbMessage(
159
+ role=msg.role,
160
+ content=msg.content,
161
+ metadata=msg.metadata or {},
162
+ timestamp=msg.created_at or time.time(),
163
+ id=msg.id
164
+ )
165
+ for msg in messages
166
+ ]
167
+
168
+ def on_user_message(
169
+ self,
170
+ session_id: str,
171
+ content: str,
172
+ metadata: Optional[Dict[str, Any]] = None,
173
+ ) -> None:
174
+ """Called when user sends a message."""
175
+ if not self._conversation_store:
176
+ return
177
+
178
+ from ..persistence.conversation.base import ConversationMessage
179
+ import uuid
180
+
181
+ msg = ConversationMessage(
182
+ id=f"msg-{uuid.uuid4().hex[:12]}",
183
+ session_id=session_id,
184
+ role="user",
185
+ content=content,
186
+ metadata=metadata or {},
187
+ created_at=time.time()
188
+ )
189
+ self._conversation_store.add_message(session_id, msg)
190
+
191
+ def on_agent_message(
192
+ self,
193
+ session_id: str,
194
+ content: str,
195
+ metadata: Optional[Dict[str, Any]] = None,
196
+ ) -> None:
197
+ """Called when agent produces a response."""
198
+ if not self._conversation_store:
199
+ return
200
+
201
+ from ..persistence.conversation.base import ConversationMessage
202
+ import uuid
203
+
204
+ msg = ConversationMessage(
205
+ id=f"msg-{uuid.uuid4().hex[:12]}",
206
+ session_id=session_id,
207
+ role="assistant",
208
+ content=content,
209
+ metadata=metadata or {},
210
+ created_at=time.time()
211
+ )
212
+ self._conversation_store.add_message(session_id, msg)
213
+
214
+ def on_tool_call(
215
+ self,
216
+ session_id: str,
217
+ tool_name: str,
218
+ args: Dict[str, Any],
219
+ result: Any,
220
+ metadata: Optional[Dict[str, Any]] = None,
221
+ ) -> None:
222
+ """Called when a tool is executed."""
223
+ if not self._conversation_store:
224
+ return
225
+
226
+ from ..persistence.conversation.base import ConversationMessage
227
+ import uuid
228
+ import json
229
+
230
+ # Store tool call as a special message
231
+ tool_content = json.dumps({
232
+ "tool": tool_name,
233
+ "args": args,
234
+ "result": str(result)[:1000] # Truncate large results
235
+ })
236
+
237
+ msg = ConversationMessage(
238
+ id=f"tool-{uuid.uuid4().hex[:12]}",
239
+ session_id=session_id,
240
+ role="tool",
241
+ content=tool_content,
242
+ metadata={"tool_name": tool_name, **(metadata or {})},
243
+ created_at=time.time()
244
+ )
245
+ self._conversation_store.add_message(session_id, msg)
246
+
247
+ def on_agent_end(
248
+ self,
249
+ session_id: str,
250
+ metadata: Optional[Dict[str, Any]] = None,
251
+ ) -> None:
252
+ """Called when agent session ends."""
253
+ if not self._conversation_store:
254
+ return
255
+
256
+ # Update session metadata
257
+ session = self._conversation_store.get_session(session_id)
258
+ if session:
259
+ session.metadata = {**(session.metadata or {}), "ended_at": time.time()}
260
+ self._conversation_store.update_session(session)
261
+
262
+ def on_run_start(
263
+ self,
264
+ session_id: str,
265
+ run_id: str,
266
+ input_content: Optional[str] = None,
267
+ metadata: Optional[Dict[str, Any]] = None,
268
+ ) -> None:
269
+ """Called when a new run (turn) starts."""
270
+ if not self._conversation_store:
271
+ return
272
+
273
+ # Store run start in state if available
274
+ if self._state_store:
275
+ run_key = f"run:{session_id}:{run_id}"
276
+ self._state_store.set(run_key, {
277
+ "run_id": run_id,
278
+ "session_id": session_id,
279
+ "started_at": time.time(),
280
+ "input_content": input_content,
281
+ "status": "running",
282
+ "metadata": metadata or {}
283
+ })
284
+
285
+ def on_run_end(
286
+ self,
287
+ session_id: str,
288
+ run_id: str,
289
+ output_content: Optional[str] = None,
290
+ status: str = "completed",
291
+ metrics: Optional[Dict[str, Any]] = None,
292
+ metadata: Optional[Dict[str, Any]] = None,
293
+ ) -> None:
294
+ """Called when a run (turn) ends."""
295
+ if self._state_store:
296
+ run_key = f"run:{session_id}:{run_id}"
297
+ run_data = self._state_store.get(run_key) or {}
298
+ run_data.update({
299
+ "ended_at": time.time(),
300
+ "output_content": output_content,
301
+ "status": status,
302
+ "metrics": metrics or {},
303
+ "metadata": {**run_data.get("metadata", {}), **(metadata or {})}
304
+ })
305
+ self._state_store.set(run_key, run_data)
306
+
307
+ def get_runs(
308
+ self,
309
+ session_id: str,
310
+ limit: Optional[int] = None,
311
+ ) -> List:
312
+ """Get runs for a session."""
313
+ # For now, runs are stored in state store
314
+ # Full implementation would query from conversation store
315
+ return []
316
+
317
+ def export_session(
318
+ self,
319
+ session_id: str,
320
+ ) -> Dict[str, Any]:
321
+ """Export a session as a dictionary."""
322
+ self._init_stores()
323
+
324
+ if not self._conversation_store:
325
+ return {}
326
+
327
+ session = self._conversation_store.get_session(session_id)
328
+ if not session:
329
+ return {}
330
+
331
+ messages = self._conversation_store.get_messages(session_id)
332
+
333
+ return {
334
+ "session_id": session.session_id,
335
+ "user_id": session.user_id,
336
+ "agent_id": session.agent_id,
337
+ "name": session.name,
338
+ "metadata": session.metadata,
339
+ "created_at": session.created_at,
340
+ "messages": [
341
+ {
342
+ "id": msg.id,
343
+ "role": msg.role,
344
+ "content": msg.content,
345
+ "metadata": msg.metadata,
346
+ "created_at": msg.created_at
347
+ }
348
+ for msg in messages
349
+ ]
350
+ }
351
+
352
+ def import_session(
353
+ self,
354
+ data: Dict[str, Any],
355
+ ) -> str:
356
+ """Import a session from a dictionary."""
357
+ self._init_stores()
358
+
359
+ if not self._conversation_store:
360
+ raise ValueError("No conversation store configured")
361
+
362
+ from ..persistence.conversation.base import ConversationSession, ConversationMessage
363
+ import uuid
364
+
365
+ session_id = data.get("session_id") or f"imported-{uuid.uuid4().hex[:8]}"
366
+
367
+ # Create session
368
+ session = ConversationSession(
369
+ session_id=session_id,
370
+ user_id=data.get("user_id", "default"),
371
+ agent_id=data.get("agent_id", "imported"),
372
+ name=data.get("name", f"Imported Session {session_id}"),
373
+ metadata=data.get("metadata", {})
374
+ )
375
+ self._conversation_store.create_session(session)
376
+
377
+ # Import messages with new IDs to avoid conflicts
378
+ for msg_data in data.get("messages", []):
379
+ msg = ConversationMessage(
380
+ id=f"msg-{uuid.uuid4().hex[:12]}", # Always generate new ID
381
+ session_id=session_id,
382
+ role=msg_data.get("role", "user"),
383
+ content=msg_data.get("content", ""),
384
+ metadata=msg_data.get("metadata", {}),
385
+ created_at=msg_data.get("created_at", time.time())
386
+ )
387
+ self._conversation_store.add_message(session_id, msg)
388
+
389
+ return session_id
390
+
391
+ # --- Tracing/Observability ---
392
+
393
+ def on_trace_start(
394
+ self,
395
+ trace_id: str,
396
+ session_id: Optional[str] = None,
397
+ run_id: Optional[str] = None,
398
+ agent_name: Optional[str] = None,
399
+ user_id: Optional[str] = None,
400
+ metadata: Optional[Dict[str, Any]] = None,
401
+ ) -> None:
402
+ """Called when a new trace starts."""
403
+ if self._state_store:
404
+ trace_key = f"trace:{trace_id}"
405
+ self._state_store.set(trace_key, {
406
+ "trace_id": trace_id,
407
+ "session_id": session_id,
408
+ "run_id": run_id,
409
+ "agent_name": agent_name,
410
+ "user_id": user_id,
411
+ "started_at": time.time(),
412
+ "status": "running",
413
+ "spans": [],
414
+ "metadata": metadata or {}
415
+ })
416
+
417
+ def on_trace_end(
418
+ self,
419
+ trace_id: str,
420
+ status: str = "ok",
421
+ metadata: Optional[Dict[str, Any]] = None,
422
+ ) -> None:
423
+ """Called when a trace ends."""
424
+ if self._state_store:
425
+ trace_key = f"trace:{trace_id}"
426
+ trace_data = self._state_store.get(trace_key) or {}
427
+ trace_data.update({
428
+ "ended_at": time.time(),
429
+ "status": status,
430
+ "metadata": {**trace_data.get("metadata", {}), **(metadata or {})}
431
+ })
432
+ self._state_store.set(trace_key, trace_data)
433
+
434
+ def on_span_start(
435
+ self,
436
+ span_id: str,
437
+ trace_id: str,
438
+ name: str,
439
+ parent_span_id: Optional[str] = None,
440
+ attributes: Optional[Dict[str, Any]] = None,
441
+ ) -> None:
442
+ """Called when a new span starts."""
443
+ if self._state_store:
444
+ span_key = f"span:{span_id}"
445
+ self._state_store.set(span_key, {
446
+ "span_id": span_id,
447
+ "trace_id": trace_id,
448
+ "name": name,
449
+ "parent_span_id": parent_span_id,
450
+ "started_at": time.time(),
451
+ "status": "running",
452
+ "attributes": attributes or {},
453
+ "events": []
454
+ })
455
+
456
+ def on_span_end(
457
+ self,
458
+ span_id: str,
459
+ status: str = "ok",
460
+ attributes: Optional[Dict[str, Any]] = None,
461
+ ) -> None:
462
+ """Called when a span ends."""
463
+ if self._state_store:
464
+ span_key = f"span:{span_id}"
465
+ span_data = self._state_store.get(span_key) or {}
466
+ span_data.update({
467
+ "ended_at": time.time(),
468
+ "status": status,
469
+ "attributes": {**span_data.get("attributes", {}), **(attributes or {})}
470
+ })
471
+ self._state_store.set(span_key, span_data)
472
+
473
+ def get_traces(
474
+ self,
475
+ session_id: Optional[str] = None,
476
+ user_id: Optional[str] = None,
477
+ limit: Optional[int] = None,
478
+ ) -> List:
479
+ """Get traces with optional filters."""
480
+ # For now, return empty list - full implementation would scan state store
481
+ return []
482
+
483
+ def close(self) -> None:
484
+ """Close all database connections."""
485
+ if self._conversation_store:
486
+ self._conversation_store.close()
487
+ if self._state_store:
488
+ self._state_store.close()
489
+ if self._knowledge_store:
490
+ self._knowledge_store.close()
491
+
492
+
493
+ class PostgresDB(PraisonDB):
494
+ """PostgreSQL-specific database adapter."""
495
+
496
+ def __init__(
497
+ self,
498
+ host: str = "localhost",
499
+ port: int = 5432,
500
+ database: str = "praisonai",
501
+ user: str = "postgres",
502
+ password: str = "",
503
+ **options
504
+ ):
505
+ url = f"postgresql://{user}:{password}@{host}:{port}/{database}"
506
+ super().__init__(database_url=url, **options)
507
+
508
+
509
+ class SQLiteDB(PraisonDB):
510
+ """SQLite-specific database adapter."""
511
+
512
+ def __init__(self, path: str = "praisonai.db", database_url: str = None, **options):
513
+ # Allow either path or database_url
514
+ url = database_url or path
515
+ super().__init__(database_url=url, **options)
516
+
517
+ def _detect_backend(self, url: str) -> str:
518
+ return "sqlite"
519
+
520
+
521
+ class RedisDB(PraisonDB):
522
+ """Redis-specific database adapter (for state only)."""
523
+
524
+ def __init__(
525
+ self,
526
+ host: str = "localhost",
527
+ port: int = 6379,
528
+ **options
529
+ ):
530
+ url = f"redis://{host}:{port}"
531
+ super().__init__(state_url=url, **options)
@@ -0,0 +1,62 @@
1
+ """
2
+ Deploy module for PraisonAI - API, Docker, and Cloud deployments.
3
+ """
4
+ from typing import TYPE_CHECKING, Optional, Dict, Any
5
+
6
+ if TYPE_CHECKING:
7
+ from .models import DeployConfig, DeployResult, DeployType, CloudProvider
8
+ from .schema import validate_agents_yaml, generate_sample_yaml
9
+ from .doctor import DoctorReport, run_all_checks
10
+
11
+
12
+ def __getattr__(name):
13
+ """Lazy load deploy modules."""
14
+ if name == 'Deploy':
15
+ from .main import Deploy
16
+ return Deploy
17
+ elif name == 'DeployConfig':
18
+ from .models import DeployConfig
19
+ return DeployConfig
20
+ elif name == 'DeployType':
21
+ from .models import DeployType
22
+ return DeployType
23
+ elif name == 'CloudProvider':
24
+ from .models import CloudProvider
25
+ return CloudProvider
26
+ elif name == 'DeployResult':
27
+ from .models import DeployResult
28
+ return DeployResult
29
+ elif name == 'DeployStatus':
30
+ from .models import DeployStatus
31
+ return DeployStatus
32
+ elif name == 'DestroyResult':
33
+ from .models import DestroyResult
34
+ return DestroyResult
35
+ elif name == 'ServiceState':
36
+ from .models import ServiceState
37
+ return ServiceState
38
+ elif name == 'validate_agents_yaml':
39
+ from .schema import validate_agents_yaml
40
+ return validate_agents_yaml
41
+ elif name == 'generate_sample_yaml':
42
+ from .schema import generate_sample_yaml
43
+ return generate_sample_yaml
44
+ elif name == 'run_all_checks':
45
+ from .doctor import run_all_checks
46
+ return run_all_checks
47
+ raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
48
+
49
+
50
+ __all__ = [
51
+ 'Deploy',
52
+ 'DeployConfig',
53
+ 'DeployType',
54
+ 'CloudProvider',
55
+ 'DeployResult',
56
+ 'DeployStatus',
57
+ 'DestroyResult',
58
+ 'ServiceState',
59
+ 'validate_agents_yaml',
60
+ 'generate_sample_yaml',
61
+ 'run_all_checks'
62
+ ]