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,186 @@
1
+ """
2
+ Server for PraisonAI Async Jobs API.
3
+
4
+ Provides FastAPI application setup and server startup.
5
+ """
6
+
7
+ import logging
8
+ import os
9
+ from typing import Optional
10
+ from contextlib import asynccontextmanager
11
+
12
+ from fastapi import FastAPI
13
+ from fastapi.middleware.cors import CORSMiddleware
14
+
15
+ from .store import InMemoryJobStore, JobStore
16
+ from .executor import JobExecutor
17
+ from .router import create_router
18
+
19
+ logger = logging.getLogger(__name__)
20
+
21
+ # Global instances (for single-process deployment)
22
+ _store: Optional[JobStore] = None
23
+ _executor: Optional[JobExecutor] = None
24
+
25
+
26
+ def get_store() -> JobStore:
27
+ """Get or create the job store."""
28
+ global _store
29
+ if _store is None:
30
+ _store = InMemoryJobStore(max_jobs=1000)
31
+ return _store
32
+
33
+
34
+ def get_executor() -> JobExecutor:
35
+ """Get or create the job executor."""
36
+ global _executor
37
+ if _executor is None:
38
+ _executor = JobExecutor(
39
+ store=get_store(),
40
+ max_concurrent=int(os.environ.get("PRAISONAI_MAX_CONCURRENT_JOBS", "10")),
41
+ default_timeout=int(os.environ.get("PRAISONAI_JOB_TIMEOUT", "3600"))
42
+ )
43
+ return _executor
44
+
45
+
46
+ @asynccontextmanager
47
+ async def lifespan(app: FastAPI):
48
+ """Application lifespan manager."""
49
+ executor = get_executor()
50
+ await executor.start()
51
+ logger.info("Jobs API server started")
52
+
53
+ yield
54
+
55
+ await executor.stop()
56
+ logger.info("Jobs API server stopped")
57
+
58
+
59
+ def create_app(
60
+ store: Optional[JobStore] = None,
61
+ executor: Optional[JobExecutor] = None,
62
+ cors_origins: Optional[list] = None
63
+ ) -> FastAPI:
64
+ """
65
+ Create the FastAPI application.
66
+
67
+ Args:
68
+ store: Optional custom job store
69
+ executor: Optional custom executor
70
+ cors_origins: Optional list of allowed CORS origins
71
+
72
+ Returns:
73
+ FastAPI application
74
+ """
75
+ global _store, _executor
76
+
77
+ if store:
78
+ _store = store
79
+ if executor:
80
+ _executor = executor
81
+
82
+ app = FastAPI(
83
+ title="PraisonAI Jobs API",
84
+ description="Async Jobs API for long-running agent tasks",
85
+ version="1.0.0",
86
+ lifespan=lifespan
87
+ )
88
+
89
+ # Add CORS middleware
90
+ origins = cors_origins or ["*"]
91
+ app.add_middleware(
92
+ CORSMiddleware,
93
+ allow_origins=origins,
94
+ allow_credentials=True,
95
+ allow_methods=["*"],
96
+ allow_headers=["*"],
97
+ )
98
+
99
+ # Add jobs router
100
+ jobs_router = create_router(get_store(), get_executor())
101
+ app.include_router(jobs_router)
102
+
103
+ # Health check endpoint
104
+ @app.get("/health")
105
+ async def health_check():
106
+ """Health check endpoint."""
107
+ return {
108
+ "status": "healthy",
109
+ "store": get_store().__class__.__name__,
110
+ "executor_stats": get_executor().get_stats()
111
+ }
112
+
113
+ # Stats endpoint
114
+ @app.get("/stats")
115
+ async def get_stats():
116
+ """Get server statistics."""
117
+ store = get_store()
118
+ executor = get_executor()
119
+
120
+ stats = {
121
+ "executor": executor.get_stats()
122
+ }
123
+
124
+ if hasattr(store, "get_stats"):
125
+ stats["store"] = store.get_stats()
126
+
127
+ return stats
128
+
129
+ return app
130
+
131
+
132
+ def start_server(
133
+ host: str = "127.0.0.1",
134
+ port: int = 8005,
135
+ reload: bool = False,
136
+ workers: int = 1,
137
+ log_level: str = "info"
138
+ ):
139
+ """
140
+ Start the jobs API server.
141
+
142
+ Args:
143
+ host: Host to bind to
144
+ port: Port to bind to
145
+ reload: Enable auto-reload for development
146
+ workers: Number of worker processes
147
+ log_level: Logging level
148
+ """
149
+ try:
150
+ import uvicorn
151
+ except ImportError:
152
+ raise RuntimeError("uvicorn is required. Install with: pip install uvicorn")
153
+
154
+ logger.info(f"Starting PraisonAI Jobs API on {host}:{port}")
155
+
156
+ uvicorn.run(
157
+ "praisonai.jobs.server:create_app",
158
+ host=host,
159
+ port=port,
160
+ reload=reload,
161
+ workers=workers,
162
+ log_level=log_level,
163
+ factory=True
164
+ )
165
+
166
+
167
+ # For direct module execution
168
+ if __name__ == "__main__":
169
+ import argparse
170
+
171
+ parser = argparse.ArgumentParser(description="PraisonAI Jobs API Server")
172
+ parser.add_argument("--host", default="127.0.0.1", help="Host to bind to")
173
+ parser.add_argument("--port", type=int, default=8005, help="Port to bind to")
174
+ parser.add_argument("--reload", action="store_true", help="Enable auto-reload")
175
+ parser.add_argument("--workers", type=int, default=1, help="Number of workers")
176
+ parser.add_argument("--log-level", default="info", help="Log level")
177
+
178
+ args = parser.parse_args()
179
+
180
+ start_server(
181
+ host=args.host,
182
+ port=args.port,
183
+ reload=args.reload,
184
+ workers=args.workers,
185
+ log_level=args.log_level
186
+ )
@@ -0,0 +1,203 @@
1
+ """
2
+ Job Store for PraisonAI Async Jobs API.
3
+
4
+ Provides storage backends for job state persistence.
5
+ """
6
+
7
+ import asyncio
8
+ import logging
9
+ from abc import ABC, abstractmethod
10
+ from typing import Optional, List, Dict, Any
11
+ from datetime import datetime, timedelta
12
+
13
+ from .models import Job, JobStatus
14
+
15
+ logger = logging.getLogger(__name__)
16
+
17
+
18
+ class JobStore(ABC):
19
+ """Abstract base class for job storage backends."""
20
+
21
+ @abstractmethod
22
+ async def save(self, job: Job) -> None:
23
+ """Save or update a job."""
24
+ pass
25
+
26
+ @abstractmethod
27
+ async def get(self, job_id: str) -> Optional[Job]:
28
+ """Get a job by ID."""
29
+ pass
30
+
31
+ @abstractmethod
32
+ async def get_by_idempotency_key(self, key: str) -> Optional[Job]:
33
+ """Get a job by idempotency key."""
34
+ pass
35
+
36
+ @abstractmethod
37
+ async def list_jobs(
38
+ self,
39
+ status: Optional[JobStatus] = None,
40
+ session_id: Optional[str] = None,
41
+ limit: int = 20,
42
+ offset: int = 0
43
+ ) -> List[Job]:
44
+ """List jobs with optional filters."""
45
+ pass
46
+
47
+ @abstractmethod
48
+ async def count(
49
+ self,
50
+ status: Optional[JobStatus] = None,
51
+ session_id: Optional[str] = None
52
+ ) -> int:
53
+ """Count jobs matching filters."""
54
+ pass
55
+
56
+ @abstractmethod
57
+ async def delete(self, job_id: str) -> bool:
58
+ """Delete a job by ID."""
59
+ pass
60
+
61
+ @abstractmethod
62
+ async def cleanup_old_jobs(self, max_age_seconds: int = 86400) -> int:
63
+ """Remove jobs older than max_age_seconds. Returns count deleted."""
64
+ pass
65
+
66
+
67
+ class InMemoryJobStore(JobStore):
68
+ """
69
+ In-memory job store.
70
+
71
+ Suitable for development and single-process deployments.
72
+ Jobs are lost on restart.
73
+ """
74
+
75
+ def __init__(self, max_jobs: int = 1000):
76
+ self._jobs: Dict[str, Job] = {}
77
+ self._idempotency_keys: Dict[str, str] = {} # key -> job_id
78
+ self._max_jobs = max_jobs
79
+ self._lock = asyncio.Lock()
80
+
81
+ async def save(self, job: Job) -> None:
82
+ """Save or update a job."""
83
+ async with self._lock:
84
+ self._jobs[job.id] = job
85
+
86
+ # Track idempotency key
87
+ if job.idempotency_key:
88
+ self._idempotency_keys[job.idempotency_key] = job.id
89
+
90
+ # Enforce max jobs limit by removing oldest completed
91
+ if len(self._jobs) > self._max_jobs:
92
+ await self._evict_oldest_completed()
93
+
94
+ async def _evict_oldest_completed(self) -> None:
95
+ """Remove oldest completed jobs to stay under limit."""
96
+ completed = [
97
+ (job_id, job) for job_id, job in self._jobs.items()
98
+ if job.is_terminal
99
+ ]
100
+
101
+ if not completed:
102
+ return
103
+
104
+ # Sort by completed_at, oldest first
105
+ completed.sort(key=lambda x: x[1].completed_at or datetime.min)
106
+
107
+ # Remove oldest 10%
108
+ to_remove = max(1, len(completed) // 10)
109
+ for job_id, job in completed[:to_remove]:
110
+ del self._jobs[job_id]
111
+ if job.idempotency_key:
112
+ self._idempotency_keys.pop(job.idempotency_key, None)
113
+
114
+ async def get(self, job_id: str) -> Optional[Job]:
115
+ """Get a job by ID."""
116
+ return self._jobs.get(job_id)
117
+
118
+ async def get_by_idempotency_key(self, key: str) -> Optional[Job]:
119
+ """Get a job by idempotency key."""
120
+ job_id = self._idempotency_keys.get(key)
121
+ if job_id:
122
+ return self._jobs.get(job_id)
123
+ return None
124
+
125
+ async def list_jobs(
126
+ self,
127
+ status: Optional[JobStatus] = None,
128
+ session_id: Optional[str] = None,
129
+ limit: int = 20,
130
+ offset: int = 0
131
+ ) -> List[Job]:
132
+ """List jobs with optional filters."""
133
+ jobs = list(self._jobs.values())
134
+
135
+ # Apply filters
136
+ if status:
137
+ jobs = [j for j in jobs if j.status == status]
138
+ if session_id:
139
+ jobs = [j for j in jobs if j.session_id == session_id]
140
+
141
+ # Sort by created_at descending (newest first)
142
+ jobs.sort(key=lambda j: j.created_at, reverse=True)
143
+
144
+ # Apply pagination
145
+ return jobs[offset:offset + limit]
146
+
147
+ async def count(
148
+ self,
149
+ status: Optional[JobStatus] = None,
150
+ session_id: Optional[str] = None
151
+ ) -> int:
152
+ """Count jobs matching filters."""
153
+ jobs = list(self._jobs.values())
154
+
155
+ if status:
156
+ jobs = [j for j in jobs if j.status == status]
157
+ if session_id:
158
+ jobs = [j for j in jobs if j.session_id == session_id]
159
+
160
+ return len(jobs)
161
+
162
+ async def delete(self, job_id: str) -> bool:
163
+ """Delete a job by ID."""
164
+ async with self._lock:
165
+ job = self._jobs.pop(job_id, None)
166
+ if job:
167
+ if job.idempotency_key:
168
+ self._idempotency_keys.pop(job.idempotency_key, None)
169
+ return True
170
+ return False
171
+
172
+ async def cleanup_old_jobs(self, max_age_seconds: int = 86400) -> int:
173
+ """Remove jobs older than max_age_seconds."""
174
+ async with self._lock:
175
+ cutoff = datetime.utcnow() - timedelta(seconds=max_age_seconds)
176
+ to_remove = []
177
+
178
+ for job_id, job in self._jobs.items():
179
+ if job.is_terminal and job.completed_at and job.completed_at < cutoff:
180
+ to_remove.append(job_id)
181
+
182
+ for job_id in to_remove:
183
+ job = self._jobs.pop(job_id)
184
+ if job.idempotency_key:
185
+ self._idempotency_keys.pop(job.idempotency_key, None)
186
+
187
+ if to_remove:
188
+ logger.info(f"Cleaned up {len(to_remove)} old jobs")
189
+
190
+ return len(to_remove)
191
+
192
+ def get_stats(self) -> Dict[str, Any]:
193
+ """Get store statistics."""
194
+ status_counts = {}
195
+ for job in self._jobs.values():
196
+ status_counts[job.status.value] = status_counts.get(job.status.value, 0) + 1
197
+
198
+ return {
199
+ "total_jobs": len(self._jobs),
200
+ "idempotency_keys": len(self._idempotency_keys),
201
+ "max_jobs": self._max_jobs,
202
+ "status_counts": status_counts
203
+ }
@@ -0,0 +1,66 @@
1
+ """
2
+ LLM Module for PraisonAI CLI Wrapper.
3
+
4
+ This module provides LLM provider registry and utilities for the CLI wrapper.
5
+ The core LLM functionality is in praisonaiagents.llm.
6
+ """
7
+
8
+ # Lazy loading for performance
9
+ _lazy_cache = {}
10
+
11
+
12
+ def __getattr__(name):
13
+ """Lazy load LLM registry classes."""
14
+ if name in _lazy_cache:
15
+ return _lazy_cache[name]
16
+
17
+ if name == "LLMProviderRegistry":
18
+ from .registry import LLMProviderRegistry
19
+ _lazy_cache[name] = LLMProviderRegistry
20
+ return LLMProviderRegistry
21
+ elif name == "get_default_llm_registry":
22
+ from .registry import get_default_llm_registry
23
+ _lazy_cache[name] = get_default_llm_registry
24
+ return get_default_llm_registry
25
+ elif name == "register_llm_provider":
26
+ from .registry import register_llm_provider
27
+ _lazy_cache[name] = register_llm_provider
28
+ return register_llm_provider
29
+ elif name == "unregister_llm_provider":
30
+ from .registry import unregister_llm_provider
31
+ _lazy_cache[name] = unregister_llm_provider
32
+ return unregister_llm_provider
33
+ elif name == "has_llm_provider":
34
+ from .registry import has_llm_provider
35
+ _lazy_cache[name] = has_llm_provider
36
+ return has_llm_provider
37
+ elif name == "list_llm_providers":
38
+ from .registry import list_llm_providers
39
+ _lazy_cache[name] = list_llm_providers
40
+ return list_llm_providers
41
+ elif name == "create_llm_provider":
42
+ from .registry import create_llm_provider
43
+ _lazy_cache[name] = create_llm_provider
44
+ return create_llm_provider
45
+ elif name == "parse_model_string":
46
+ from .registry import parse_model_string
47
+ _lazy_cache[name] = parse_model_string
48
+ return parse_model_string
49
+ elif name == "_reset_default_registry":
50
+ from .registry import _reset_default_registry
51
+ _lazy_cache[name] = _reset_default_registry
52
+ return _reset_default_registry
53
+
54
+ raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
55
+
56
+
57
+ __all__ = [
58
+ "LLMProviderRegistry",
59
+ "get_default_llm_registry",
60
+ "register_llm_provider",
61
+ "unregister_llm_provider",
62
+ "has_llm_provider",
63
+ "list_llm_providers",
64
+ "create_llm_provider",
65
+ "parse_model_string",
66
+ ]