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,636 @@
1
+ """
2
+ Persistence CLI feature for PraisonAI.
3
+
4
+ Provides commands for database persistence configuration and management:
5
+ - praisonai persistence doctor - Validate DB connectivity
6
+ - praisonai persistence run - Run agent with persistence
7
+ - praisonai persistence resume - Resume a session
8
+ """
9
+
10
+ import os
11
+ import sys
12
+ import logging
13
+ from typing import Optional
14
+
15
+ logger = logging.getLogger(__name__)
16
+
17
+
18
+ def handle_persistence_command(args: list) -> bool:
19
+ """
20
+ Handle persistence subcommands.
21
+
22
+ Args:
23
+ args: Command line arguments after 'persistence'
24
+
25
+ Returns:
26
+ True if command was handled, False otherwise
27
+ """
28
+ if not args:
29
+ print_persistence_help()
30
+ return True
31
+
32
+ subcommand = args[0].lower()
33
+ sub_args = args[1:]
34
+
35
+ if subcommand == "doctor":
36
+ return handle_doctor(sub_args)
37
+ elif subcommand == "run":
38
+ return handle_run(sub_args)
39
+ elif subcommand == "resume":
40
+ return handle_resume(sub_args)
41
+ elif subcommand == "export":
42
+ return handle_export(sub_args)
43
+ elif subcommand == "import":
44
+ return handle_import(sub_args)
45
+ elif subcommand == "migrate":
46
+ return handle_migrate(sub_args)
47
+ elif subcommand == "status":
48
+ return handle_status(sub_args)
49
+ elif subcommand in ("--help", "-h", "help"):
50
+ print_persistence_help()
51
+ return True
52
+ else:
53
+ print(f"Unknown persistence subcommand: {subcommand}")
54
+ print_persistence_help()
55
+ return True
56
+
57
+
58
+ def print_persistence_help():
59
+ """Print persistence command help."""
60
+ help_text = """
61
+ PraisonAI Persistence Commands
62
+ ==============================
63
+
64
+ Usage: praisonai persistence <command> [options]
65
+
66
+ Commands:
67
+ doctor Validate database connectivity and configuration
68
+ run Run an agent with persistence enabled
69
+ resume Resume an existing session
70
+
71
+ Doctor Command:
72
+ praisonai persistence doctor [options]
73
+
74
+ Options:
75
+ --conversation-url URL Conversation store URL (postgres/mysql/sqlite)
76
+ --knowledge-url URL Knowledge store URL (qdrant/chroma/pinecone)
77
+ --state-url URL State store URL (redis/memory)
78
+ --all Test all configured stores
79
+
80
+ Environment Variables:
81
+ PRAISON_CONVERSATION_URL Default conversation store URL
82
+ PRAISON_KNOWLEDGE_URL Default knowledge store URL
83
+ PRAISON_STATE_URL Default state store URL
84
+
85
+ Run Command:
86
+ praisonai persistence run [options] "prompt"
87
+
88
+ Options:
89
+ --session-id ID Session identifier (auto-generated if not provided)
90
+ --user-id ID User identifier (default: "default")
91
+ --conversation-url URL Conversation store URL
92
+ --knowledge-url URL Knowledge store URL
93
+ --state-url URL State store URL
94
+ --agent-name NAME Agent name (default: "Assistant")
95
+ --agent-instructions TEXT Agent instructions
96
+ --dry-run Show configuration without running
97
+
98
+ Resume Command:
99
+ praisonai persistence resume --session-id ID [options]
100
+
101
+ Options:
102
+ --session-id ID Session to resume (required)
103
+ --conversation-url URL Conversation store URL
104
+ --show-history Display conversation history
105
+ --continue "prompt" Continue with a new prompt
106
+
107
+ Export/Import Commands:
108
+ praisonai persistence export --session-id ID [options]
109
+ praisonai persistence import --file FILE [options]
110
+
111
+ Options:
112
+ --session-id ID Session to export (required for export)
113
+ --conversation-url URL Conversation store URL
114
+ --file FILE File path for export/import (JSONL format)
115
+ --output FILE Output file path (default: session-{id}.jsonl)
116
+
117
+ Examples:
118
+ # Check PostgreSQL connectivity
119
+ praisonai persistence doctor --conversation-url "postgresql://localhost/mydb"
120
+
121
+ # Run agent with persistence
122
+ praisonai persistence run --session-id "my-session" "Hello, remember my name is Alice"
123
+
124
+ # Resume a session
125
+ praisonai persistence resume --session-id "my-session" --show-history
126
+
127
+ # Continue a session
128
+ praisonai persistence resume --session-id "my-session" --continue "What's my name?"
129
+
130
+ # Export a session
131
+ praisonai persistence export --session-id "my-session" --output session.jsonl
132
+
133
+ # Import a session
134
+ praisonai persistence import --file session.jsonl
135
+ """
136
+ print(help_text)
137
+
138
+
139
+ def parse_persistence_args(args: list) -> dict:
140
+ """Parse persistence command arguments."""
141
+ config = {
142
+ "session_id": None,
143
+ "user_id": "default",
144
+ "conversation_url": os.getenv("PRAISON_CONVERSATION_URL"),
145
+ "knowledge_url": os.getenv("PRAISON_KNOWLEDGE_URL"),
146
+ "state_url": os.getenv("PRAISON_STATE_URL"),
147
+ "agent_name": "Assistant",
148
+ "agent_instructions": "You are a helpful assistant.",
149
+ "dry_run": False,
150
+ "show_history": False,
151
+ "all_stores": False,
152
+ "prompt": None,
153
+ "continue_prompt": None,
154
+ "output_file": None,
155
+ "input_file": None,
156
+ }
157
+
158
+ i = 0
159
+ while i < len(args):
160
+ arg = args[i]
161
+
162
+ if arg == "--session-id" and i + 1 < len(args):
163
+ config["session_id"] = args[i + 1]
164
+ i += 2
165
+ elif arg == "--user-id" and i + 1 < len(args):
166
+ config["user_id"] = args[i + 1]
167
+ i += 2
168
+ elif arg == "--conversation-url" and i + 1 < len(args):
169
+ config["conversation_url"] = args[i + 1]
170
+ i += 2
171
+ elif arg == "--knowledge-url" and i + 1 < len(args):
172
+ config["knowledge_url"] = args[i + 1]
173
+ i += 2
174
+ elif arg == "--state-url" and i + 1 < len(args):
175
+ config["state_url"] = args[i + 1]
176
+ i += 2
177
+ elif arg == "--agent-name" and i + 1 < len(args):
178
+ config["agent_name"] = args[i + 1]
179
+ i += 2
180
+ elif arg == "--agent-instructions" and i + 1 < len(args):
181
+ config["agent_instructions"] = args[i + 1]
182
+ i += 2
183
+ elif arg == "--dry-run":
184
+ config["dry_run"] = True
185
+ i += 1
186
+ elif arg == "--show-history":
187
+ config["show_history"] = True
188
+ i += 1
189
+ elif arg == "--all":
190
+ config["all_stores"] = True
191
+ i += 1
192
+ elif arg == "--continue" and i + 1 < len(args):
193
+ config["continue_prompt"] = args[i + 1]
194
+ i += 2
195
+ elif arg == "--output" and i + 1 < len(args):
196
+ config["output_file"] = args[i + 1]
197
+ i += 2
198
+ elif arg == "--file" and i + 1 < len(args):
199
+ config["input_file"] = args[i + 1]
200
+ i += 2
201
+ elif not arg.startswith("-"):
202
+ config["prompt"] = arg
203
+ i += 1
204
+ else:
205
+ i += 1
206
+
207
+ return config
208
+
209
+
210
+ def handle_doctor(args: list) -> bool:
211
+ """Handle persistence doctor command."""
212
+ config = parse_persistence_args(args)
213
+
214
+ print("=" * 50)
215
+ print("PraisonAI Persistence Doctor")
216
+ print("=" * 50)
217
+
218
+ results = []
219
+
220
+ # Test conversation store
221
+ if config["conversation_url"] or config["all_stores"]:
222
+ url = config["conversation_url"]
223
+ if url:
224
+ print(f"\n[Conversation Store] Testing: {_mask_url(url)}")
225
+ success, msg = _test_conversation_store(url)
226
+ results.append(("Conversation", success, msg))
227
+ print(f" {'✅' if success else '❌'} {msg}")
228
+ else:
229
+ print("\n[Conversation Store] Not configured (set --conversation-url or PRAISON_CONVERSATION_URL)")
230
+
231
+ # Test knowledge store
232
+ if config["knowledge_url"] or config["all_stores"]:
233
+ url = config["knowledge_url"]
234
+ if url:
235
+ print(f"\n[Knowledge Store] Testing: {_mask_url(url)}")
236
+ success, msg = _test_knowledge_store(url)
237
+ results.append(("Knowledge", success, msg))
238
+ print(f" {'✅' if success else '❌'} {msg}")
239
+ else:
240
+ print("\n[Knowledge Store] Not configured (set --knowledge-url or PRAISON_KNOWLEDGE_URL)")
241
+
242
+ # Test state store
243
+ if config["state_url"] or config["all_stores"]:
244
+ url = config["state_url"]
245
+ if url:
246
+ print(f"\n[State Store] Testing: {_mask_url(url)}")
247
+ success, msg = _test_state_store(url)
248
+ results.append(("State", success, msg))
249
+ print(f" {'✅' if success else '❌'} {msg}")
250
+ else:
251
+ print("\n[State Store] Not configured (set --state-url or PRAISON_STATE_URL)")
252
+
253
+ # Summary
254
+ print("\n" + "=" * 50)
255
+ if results:
256
+ passed = sum(1 for _, s, _ in results if s)
257
+ total = len(results)
258
+ print(f"Results: {passed}/{total} stores connected successfully")
259
+ else:
260
+ print("No stores configured. Use --conversation-url, --knowledge-url, or --state-url")
261
+ print("=" * 50)
262
+
263
+ return True
264
+
265
+
266
+ def handle_run(args: list) -> bool:
267
+ """Handle persistence run command."""
268
+ config = parse_persistence_args(args)
269
+
270
+ if not config["prompt"]:
271
+ print("Error: No prompt provided")
272
+ print("Usage: praisonai persistence run [options] \"your prompt\"")
273
+ return True
274
+
275
+ if not config["conversation_url"]:
276
+ print("Error: No conversation URL configured")
277
+ print("Set --conversation-url or PRAISON_CONVERSATION_URL")
278
+ return True
279
+
280
+ if config["dry_run"]:
281
+ print("=" * 50)
282
+ print("Dry Run - Configuration")
283
+ print("=" * 50)
284
+ print(f"Session ID: {config['session_id'] or '(auto-generated)'}")
285
+ print(f"User ID: {config['user_id']}")
286
+ print(f"Conversation URL: {_mask_url(config['conversation_url'])}")
287
+ print(f"Agent Name: {config['agent_name']}")
288
+ print(f"Prompt: {config['prompt'][:50]}...")
289
+ return True
290
+
291
+ # Run agent with persistence
292
+ try:
293
+ from praisonaiagents import Agent, db
294
+
295
+ db_instance = db(
296
+ database_url=config["conversation_url"],
297
+ state_url=config["state_url"],
298
+ knowledge_url=config["knowledge_url"],
299
+ )
300
+
301
+ agent = Agent(
302
+ name=config["agent_name"],
303
+ instructions=config["agent_instructions"],
304
+ db=db_instance,
305
+ session_id=config["session_id"],
306
+ verbose=True
307
+ )
308
+
309
+ print(f"\n[Session: {agent.session_id}]")
310
+ response = agent.chat(config["prompt"])
311
+ print(f"\nAgent: {response}")
312
+
313
+ db_instance.close()
314
+
315
+ except Exception as e:
316
+ print(f"Error: {e}")
317
+ return True
318
+
319
+ return True
320
+
321
+
322
+ def handle_resume(args: list) -> bool:
323
+ """Handle persistence resume command."""
324
+ config = parse_persistence_args(args)
325
+
326
+ if not config["session_id"]:
327
+ print("Error: --session-id is required for resume")
328
+ return True
329
+
330
+ if not config["conversation_url"]:
331
+ print("Error: No conversation URL configured")
332
+ print("Set --conversation-url or PRAISON_CONVERSATION_URL")
333
+ return True
334
+
335
+ try:
336
+ from praisonaiagents import db
337
+
338
+ db_instance = db(database_url=config["conversation_url"])
339
+
340
+ # Get session history
341
+ history = db_instance.on_agent_start(
342
+ agent_name="Resume",
343
+ session_id=config["session_id"],
344
+ user_id=config["user_id"]
345
+ )
346
+
347
+ print(f"\n[Session: {config['session_id']}]")
348
+ print(f"Messages in history: {len(history)}")
349
+
350
+ if config["show_history"]:
351
+ print("\n--- Conversation History ---")
352
+ for msg in history:
353
+ role = msg.role.upper()
354
+ content = msg.content[:100] + "..." if len(msg.content) > 100 else msg.content
355
+ print(f"[{role}] {content}")
356
+ print("--- End History ---\n")
357
+
358
+ if config["continue_prompt"]:
359
+ from praisonaiagents import Agent
360
+
361
+ agent = Agent(
362
+ name=config["agent_name"],
363
+ instructions=config["agent_instructions"],
364
+ db=db_instance,
365
+ session_id=config["session_id"],
366
+ verbose=True
367
+ )
368
+
369
+ response = agent.chat(config["continue_prompt"])
370
+ print(f"\nAgent: {response}")
371
+
372
+ db_instance.close()
373
+
374
+ except Exception as e:
375
+ print(f"Error: {e}")
376
+ return True
377
+
378
+ return True
379
+
380
+
381
+ def handle_export(args: list) -> bool:
382
+ """Handle persistence export command."""
383
+ config = parse_persistence_args(args)
384
+
385
+ if not config["session_id"]:
386
+ print("Error: --session-id is required for export")
387
+ return True
388
+
389
+ if not config["conversation_url"]:
390
+ print("Error: No conversation URL configured")
391
+ return True
392
+
393
+ try:
394
+ from praisonaiagents import db
395
+ import json
396
+
397
+ db_instance = db(database_url=config["conversation_url"])
398
+
399
+ # Export session
400
+ data = db_instance.export_session(config["session_id"])
401
+
402
+ if not data:
403
+ print(f"Error: Session {config['session_id']} not found")
404
+ db_instance.close()
405
+ return True
406
+
407
+ # Determine output file
408
+ output_file = config.get("output_file") or f"session-{config['session_id']}.jsonl"
409
+
410
+ with open(output_file, 'w') as f:
411
+ f.write(json.dumps(data, default=str) + '\n')
412
+
413
+ print(f"Exported session to: {output_file}")
414
+ print(f"Messages: {len(data.get('messages', []))}")
415
+
416
+ db_instance.close()
417
+
418
+ except Exception as e:
419
+ print(f"Error: {e}")
420
+ return True
421
+
422
+ return True
423
+
424
+
425
+ def handle_import(args: list) -> bool:
426
+ """Handle persistence import command."""
427
+ config = parse_persistence_args(args)
428
+
429
+ input_file = config.get("input_file")
430
+ if not input_file:
431
+ print("Error: --file is required for import")
432
+ return True
433
+
434
+ if not config["conversation_url"]:
435
+ print("Error: No conversation URL configured")
436
+ return True
437
+
438
+ try:
439
+ from praisonaiagents import db
440
+ import json
441
+
442
+ db_instance = db(database_url=config["conversation_url"])
443
+
444
+ with open(input_file, 'r') as f:
445
+ data = json.loads(f.readline())
446
+
447
+ session_id = db_instance.import_session(data)
448
+
449
+ print(f"Imported session: {session_id}")
450
+ print(f"Messages: {len(data.get('messages', []))}")
451
+
452
+ db_instance.close()
453
+
454
+ except Exception as e:
455
+ print(f"Error: {e}")
456
+ return True
457
+
458
+ return True
459
+
460
+
461
+ def handle_migrate(args: list) -> bool:
462
+ """Handle persistence migrate command."""
463
+ config = parse_persistence_args(args)
464
+
465
+ if not config["conversation_url"] and not config["state_url"]:
466
+ print("Error: No database URL configured")
467
+ print("Set --conversation-url or --state-url")
468
+ return True
469
+
470
+ try:
471
+ from praisonaiagents import db
472
+ from praisonai.persistence.migrations import MigrationManager
473
+
474
+ db_instance = db(
475
+ database_url=config["conversation_url"],
476
+ state_url=config["state_url"]
477
+ )
478
+
479
+ manager = MigrationManager(db_instance)
480
+
481
+ # Check for --up or --down flags
482
+ direction = "up"
483
+ target = None
484
+ for i, arg in enumerate(args):
485
+ if arg == "--down":
486
+ direction = "down"
487
+ elif arg == "--target" and i + 1 < len(args):
488
+ target = args[i + 1]
489
+
490
+ if direction == "up":
491
+ print("Applying pending migrations...")
492
+ applied = manager.migrate_up(target)
493
+ if applied:
494
+ print(f"Applied migrations: {', '.join(applied)}")
495
+ else:
496
+ print("No pending migrations")
497
+ else:
498
+ if not target:
499
+ print("Error: --target required for --down migration")
500
+ return True
501
+ print(f"Rolling back to version {target}...")
502
+ rolled_back = manager.migrate_down(target)
503
+ if rolled_back:
504
+ print(f"Rolled back: {', '.join(rolled_back)}")
505
+ else:
506
+ print("No migrations to rollback")
507
+
508
+ db_instance.close()
509
+
510
+ except Exception as e:
511
+ print(f"Error: {e}")
512
+ return True
513
+
514
+ return True
515
+
516
+
517
+ def handle_status(args: list) -> bool:
518
+ """Handle persistence status command."""
519
+ config = parse_persistence_args(args)
520
+
521
+ if not config["conversation_url"] and not config["state_url"]:
522
+ print("Error: No database URL configured")
523
+ return True
524
+
525
+ try:
526
+ from praisonaiagents import db
527
+ from praisonai.persistence.migrations import MigrationManager
528
+
529
+ db_instance = db(
530
+ database_url=config["conversation_url"],
531
+ state_url=config["state_url"]
532
+ )
533
+
534
+ manager = MigrationManager(db_instance)
535
+ status = manager.get_migration_status()
536
+
537
+ print("\n=== Schema Status ===")
538
+ print(f"Current version: {status['current_version'] or '(not set)'}")
539
+ print(f"Latest version: {status['latest_version']}")
540
+ print(f"Pending: {status['pending_count']} migration(s)")
541
+
542
+ if status['pending_versions']:
543
+ print(f"Pending versions: {', '.join(status['pending_versions'])}")
544
+
545
+ db_instance.close()
546
+
547
+ except Exception as e:
548
+ print(f"Error: {e}")
549
+ return True
550
+
551
+ return True
552
+
553
+
554
+ def _mask_url(url: str) -> str:
555
+ """Mask sensitive parts of URL."""
556
+ if not url:
557
+ return "(not set)"
558
+
559
+ # Mask password in URLs
560
+ import re
561
+ masked = re.sub(r'://([^:]+):([^@]+)@', r'://\1:****@', url)
562
+ return masked
563
+
564
+
565
+ def _test_conversation_store(url: str) -> tuple:
566
+ """Test conversation store connectivity."""
567
+ try:
568
+ from praisonai.persistence.factory import create_conversation_store
569
+
570
+ # Detect backend
571
+ if "postgresql" in url or "postgres" in url:
572
+ backend = "postgres"
573
+ elif "mysql" in url:
574
+ backend = "mysql"
575
+ elif url.endswith(".db") or "sqlite" in url:
576
+ backend = "sqlite"
577
+ else:
578
+ backend = "sqlite"
579
+
580
+ store = create_conversation_store(backend, url=url)
581
+
582
+ # Try a simple operation
583
+ sessions = store.list_sessions(limit=1)
584
+ store.close()
585
+
586
+ return True, f"Connected ({backend})"
587
+ except Exception as e:
588
+ return False, str(e)
589
+
590
+
591
+ def _test_knowledge_store(url: str) -> tuple:
592
+ """Test knowledge store connectivity."""
593
+ try:
594
+ from praisonai.persistence.factory import create_knowledge_store
595
+
596
+ # Detect backend
597
+ if "qdrant" in url or ":6333" in url:
598
+ backend = "qdrant"
599
+ elif "chroma" in url:
600
+ backend = "chroma"
601
+ else:
602
+ backend = "qdrant"
603
+
604
+ store = create_knowledge_store(backend, url=url)
605
+
606
+ # Try a simple operation
607
+ exists = store.collection_exists("test_doctor")
608
+ store.close()
609
+
610
+ return True, f"Connected ({backend})"
611
+ except Exception as e:
612
+ return False, str(e)
613
+
614
+
615
+ def _test_state_store(url: str) -> tuple:
616
+ """Test state store connectivity."""
617
+ try:
618
+ from praisonai.persistence.factory import create_state_store
619
+
620
+ # Detect backend
621
+ if "redis" in url:
622
+ backend = "redis"
623
+ else:
624
+ backend = "memory"
625
+
626
+ store = create_state_store(backend, url=url)
627
+
628
+ # Try a simple operation
629
+ store.set("_doctor_test", "ok", ttl=5)
630
+ value = store.get("_doctor_test")
631
+ store.delete("_doctor_test")
632
+ store.close()
633
+
634
+ return True, f"Connected ({backend})"
635
+ except Exception as e:
636
+ return False, str(e)