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,179 @@
1
+ """
2
+ Deploy configuration models using Pydantic.
3
+ """
4
+ from enum import Enum
5
+ from typing import Optional, Dict, List, Any
6
+ from pydantic import BaseModel, Field, field_validator
7
+
8
+
9
+ class DeployType(str, Enum):
10
+ """Deployment type enum."""
11
+ API = "api"
12
+ DOCKER = "docker"
13
+ CLOUD = "cloud"
14
+
15
+
16
+ class CloudProvider(str, Enum):
17
+ """Cloud provider enum."""
18
+ AWS = "aws"
19
+ AZURE = "azure"
20
+ GCP = "gcp"
21
+
22
+
23
+ class APIConfig(BaseModel):
24
+ """Configuration for API server deployment."""
25
+ host: str = Field(default="127.0.0.1", description="Server host")
26
+ port: int = Field(default=8005, description="Server port")
27
+ workers: int = Field(default=1, description="Number of worker processes")
28
+ cors_enabled: bool = Field(default=True, description="Enable CORS")
29
+ auth_enabled: bool = Field(default=False, description="Enable authentication")
30
+ auth_token: Optional[str] = Field(default=None, description="Authentication token")
31
+ reload: bool = Field(default=False, description="Enable auto-reload for development")
32
+
33
+
34
+ class DockerConfig(BaseModel):
35
+ """Configuration for Docker deployment."""
36
+ image_name: str = Field(default="praisonai-app", description="Docker image name")
37
+ tag: str = Field(default="latest", description="Docker image tag")
38
+ base_image: str = Field(default="python:3.11-slim", description="Base Docker image")
39
+ expose: List[int] = Field(default=[8005], description="Ports to expose")
40
+ registry: Optional[str] = Field(default=None, description="Docker registry URL")
41
+ push: bool = Field(default=False, description="Push image to registry after build")
42
+ build_args: Optional[Dict[str, str]] = Field(default=None, description="Docker build arguments")
43
+
44
+
45
+ class CloudConfig(BaseModel):
46
+ """Configuration for cloud deployment."""
47
+ provider: CloudProvider = Field(..., description="Cloud provider")
48
+ region: str = Field(..., description="Deployment region")
49
+ service_name: str = Field(..., description="Service/application name")
50
+
51
+ # Common cloud config
52
+ image: Optional[str] = Field(default=None, description="Container image URL")
53
+ cpu: Optional[str] = Field(default="256", description="CPU allocation")
54
+ memory: Optional[str] = Field(default="512", description="Memory allocation (MB)")
55
+ min_instances: int = Field(default=1, description="Minimum instances")
56
+ max_instances: int = Field(default=10, description="Maximum instances")
57
+ env_vars: Optional[Dict[str, str]] = Field(default=None, description="Environment variables")
58
+
59
+ # AWS-specific
60
+ cluster_name: Optional[str] = Field(default=None, description="ECS cluster name (AWS)")
61
+ task_definition: Optional[str] = Field(default=None, description="Task definition (AWS)")
62
+
63
+ # Azure-specific
64
+ resource_group: Optional[str] = Field(default=None, description="Resource group (Azure)")
65
+ subscription_id: Optional[str] = Field(default=None, description="Subscription ID (Azure)")
66
+
67
+ # GCP-specific
68
+ project_id: Optional[str] = Field(default=None, description="Project ID (GCP)")
69
+
70
+
71
+ class AgentConfig(BaseModel):
72
+ """Configuration for an agent to deploy."""
73
+ name: str = Field(..., description="Agent name/identifier")
74
+ entrypoint: str = Field(..., description="Agent entrypoint file (e.g., agents.yaml)")
75
+ env: Dict[str, str] = Field(default_factory=dict, description="Environment variables")
76
+ secrets: Dict[str, str] = Field(default_factory=dict, description="Secret references")
77
+ ports: Optional[List[int]] = Field(default=None, description="Ports to expose")
78
+ resources: Optional[Dict[str, str]] = Field(default=None, description="Resource requirements")
79
+
80
+
81
+ class DeployConfig(BaseModel):
82
+ """Main deployment configuration."""
83
+ type: DeployType = Field(..., description="Deployment type")
84
+ api: Optional[APIConfig] = Field(default=None, description="API server configuration")
85
+ docker: Optional[DockerConfig] = Field(default=None, description="Docker configuration")
86
+ cloud: Optional[CloudConfig] = Field(default=None, description="Cloud configuration")
87
+ agents: Optional[List[AgentConfig]] = Field(default=None, description="Agent configurations")
88
+
89
+ @field_validator('api', 'docker', 'cloud')
90
+ @classmethod
91
+ def validate_config_for_type(cls, v, info):
92
+ """Validate that required config is present for the deployment type."""
93
+ if info.data.get('type') == DeployType.API and info.field_name == 'api':
94
+ return v or APIConfig()
95
+ elif info.data.get('type') == DeployType.DOCKER and info.field_name == 'docker':
96
+ return v or DockerConfig()
97
+ elif info.data.get('type') == DeployType.CLOUD and info.field_name == 'cloud':
98
+ if v is None:
99
+ raise ValueError("cloud config required for cloud deployment type")
100
+ return v
101
+ return v
102
+
103
+ def model_post_init(self, __context):
104
+ """Post-initialization validation."""
105
+ if self.type == DeployType.API and self.api is None:
106
+ self.api = APIConfig()
107
+ elif self.type == DeployType.DOCKER and self.docker is None:
108
+ self.docker = DockerConfig()
109
+ elif self.type == DeployType.CLOUD and self.cloud is None:
110
+ raise ValueError("cloud config required for cloud deployment type")
111
+
112
+
113
+ class DeployResult(BaseModel):
114
+ """Result of a deployment operation."""
115
+ success: bool = Field(..., description="Whether deployment succeeded")
116
+ message: str = Field(..., description="Result message")
117
+ url: Optional[str] = Field(default=None, description="Deployed service URL")
118
+ error: Optional[str] = Field(default=None, description="Error message if failed")
119
+ metadata: Dict[str, Any] = Field(default_factory=dict, description="Additional metadata")
120
+
121
+
122
+ class ServiceState(str, Enum):
123
+ """Service state enum."""
124
+ RUNNING = "running"
125
+ STOPPED = "stopped"
126
+ PENDING = "pending"
127
+ FAILED = "failed"
128
+ NOT_FOUND = "not_found"
129
+ UNKNOWN = "unknown"
130
+
131
+
132
+ class DeployStatus(BaseModel):
133
+ """Status of a deployed service."""
134
+ state: ServiceState = Field(..., description="Current service state")
135
+ url: Optional[str] = Field(default=None, description="Service URL/endpoint")
136
+ message: str = Field(default="", description="Status message")
137
+
138
+ # Resource identifiers
139
+ service_name: Optional[str] = Field(default=None, description="Service name")
140
+ provider: Optional[str] = Field(default=None, description="Provider (api/docker/aws/azure/gcp)")
141
+ region: Optional[str] = Field(default=None, description="Deployment region")
142
+
143
+ # Health info
144
+ healthy: bool = Field(default=False, description="Whether service is healthy")
145
+ instances_running: int = Field(default=0, description="Number of running instances")
146
+ instances_desired: int = Field(default=0, description="Desired number of instances")
147
+
148
+ # Timestamps
149
+ created_at: Optional[str] = Field(default=None, description="Creation timestamp")
150
+ updated_at: Optional[str] = Field(default=None, description="Last update timestamp")
151
+
152
+ # Provider-specific metadata
153
+ metadata: Dict[str, Any] = Field(default_factory=dict, description="Provider-specific metadata")
154
+
155
+ def to_dict(self) -> Dict[str, Any]:
156
+ """Convert to dictionary for JSON output."""
157
+ return {
158
+ "state": self.state.value,
159
+ "url": self.url,
160
+ "message": self.message,
161
+ "service_name": self.service_name,
162
+ "provider": self.provider,
163
+ "region": self.region,
164
+ "healthy": self.healthy,
165
+ "instances_running": self.instances_running,
166
+ "instances_desired": self.instances_desired,
167
+ "created_at": self.created_at,
168
+ "updated_at": self.updated_at,
169
+ "metadata": self.metadata
170
+ }
171
+
172
+
173
+ class DestroyResult(BaseModel):
174
+ """Result of a destroy operation."""
175
+ success: bool = Field(..., description="Whether destroy succeeded")
176
+ message: str = Field(..., description="Result message")
177
+ resources_deleted: List[str] = Field(default_factory=list, description="List of deleted resources")
178
+ error: Optional[str] = Field(default=None, description="Error message if failed")
179
+ metadata: Dict[str, Any] = Field(default_factory=dict, description="Additional metadata")
@@ -0,0 +1,33 @@
1
+ """
2
+ Cloud provider adapters for deployment.
3
+ """
4
+ from typing import TYPE_CHECKING
5
+
6
+ if TYPE_CHECKING:
7
+ from .base import BaseProvider
8
+ from .aws import AWSProvider
9
+ from .azure import AzureProvider
10
+ from .gcp import GCPProvider
11
+
12
+
13
+ def __getattr__(name):
14
+ """Lazy load provider modules."""
15
+ if name == 'BaseProvider':
16
+ from .base import BaseProvider
17
+ return BaseProvider
18
+ elif name == 'AWSProvider':
19
+ from .aws import AWSProvider
20
+ return AWSProvider
21
+ elif name == 'AzureProvider':
22
+ from .azure import AzureProvider
23
+ return AzureProvider
24
+ elif name == 'GCPProvider':
25
+ from .gcp import GCPProvider
26
+ return GCPProvider
27
+ elif name == 'get_provider':
28
+ from .base import get_provider
29
+ return get_provider
30
+ raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
31
+
32
+
33
+ __all__ = ['BaseProvider', 'AWSProvider', 'AzureProvider', 'GCPProvider', 'get_provider']
@@ -0,0 +1,331 @@
1
+ """
2
+ AWS provider for cloud deployment (ECS Fargate).
3
+ """
4
+ import subprocess
5
+ import json
6
+ from typing import Dict, Any
7
+ from .base import BaseProvider
8
+ from ..models import CloudConfig, DeployResult, DeployStatus, DestroyResult, ServiceState
9
+ from ..doctor import DoctorReport, DoctorCheckResult, check_aws_cli
10
+
11
+
12
+ class AWSProvider(BaseProvider):
13
+ """AWS deployment provider using ECS Fargate."""
14
+
15
+ def doctor(self) -> DoctorReport:
16
+ """Run AWS-specific health checks."""
17
+ checks = [check_aws_cli()]
18
+
19
+ # Check if region is configured
20
+ try:
21
+ result = subprocess.run(
22
+ ['aws', 'configure', 'get', 'region'],
23
+ capture_output=True,
24
+ text=True,
25
+ timeout=5
26
+ )
27
+
28
+ if result.returncode == 0 and result.stdout.strip():
29
+ checks.append(DoctorCheckResult(
30
+ name="AWS Region",
31
+ passed=True,
32
+ message=f"Region configured: {result.stdout.strip()}"
33
+ ))
34
+ else:
35
+ checks.append(DoctorCheckResult(
36
+ name="AWS Region",
37
+ passed=False,
38
+ message="No default region configured",
39
+ fix_suggestion="Run: aws configure set region us-east-1"
40
+ ))
41
+ except Exception as e:
42
+ checks.append(DoctorCheckResult(
43
+ name="AWS Region",
44
+ passed=False,
45
+ message=f"Failed to check region: {e}",
46
+ fix_suggestion="Run: aws configure"
47
+ ))
48
+
49
+ return DoctorReport(checks=checks)
50
+
51
+ def plan(self) -> Dict[str, Any]:
52
+ """Generate AWS deployment plan."""
53
+ cluster_name = self.config.cluster_name or f"{self.config.service_name}-cluster"
54
+
55
+ plan = {
56
+ "provider": "aws",
57
+ "service_name": self.config.service_name,
58
+ "region": self.config.region,
59
+ "cluster_name": cluster_name,
60
+ "launch_type": "FARGATE",
61
+ "cpu": self.config.cpu,
62
+ "memory": self.config.memory,
63
+ "desired_count": self.config.min_instances,
64
+ "image": self.config.image or f"{self.config.service_name}:latest",
65
+ "steps": [
66
+ "1. Create ECS cluster (if not exists)",
67
+ "2. Create task definition",
68
+ "3. Create or update ECS service",
69
+ "4. Wait for service to stabilize"
70
+ ]
71
+ }
72
+
73
+ return plan
74
+
75
+ def deploy(self) -> DeployResult:
76
+ """Deploy to AWS ECS Fargate."""
77
+ try:
78
+ cluster_name = self.config.cluster_name or f"{self.config.service_name}-cluster"
79
+
80
+ # Step 1: Create cluster if not exists
81
+ print(f"📦 Creating ECS cluster: {cluster_name}")
82
+ try:
83
+ subprocess.run(
84
+ ['aws', 'ecs', 'create-cluster',
85
+ '--cluster-name', cluster_name,
86
+ '--region', self.config.region],
87
+ capture_output=True,
88
+ timeout=30
89
+ )
90
+ except Exception:
91
+ pass # Cluster may already exist
92
+
93
+ # Step 2: Register task definition
94
+ print(f"📝 Registering task definition")
95
+
96
+ task_def = {
97
+ "family": self.config.service_name,
98
+ "networkMode": "awsvpc",
99
+ "requiresCompatibilities": ["FARGATE"],
100
+ "cpu": self.config.cpu,
101
+ "memory": self.config.memory,
102
+ "containerDefinitions": [
103
+ {
104
+ "name": self.config.service_name,
105
+ "image": self.config.image or f"{self.config.service_name}:latest",
106
+ "portMappings": [
107
+ {
108
+ "containerPort": 8005,
109
+ "protocol": "tcp"
110
+ }
111
+ ],
112
+ "environment": [
113
+ {"name": k, "value": v}
114
+ for k, v in (self.config.env_vars or {}).items()
115
+ ]
116
+ }
117
+ ]
118
+ }
119
+
120
+ result = subprocess.run(
121
+ ['aws', 'ecs', 'register-task-definition',
122
+ '--cli-input-json', json.dumps(task_def),
123
+ '--region', self.config.region],
124
+ capture_output=True,
125
+ text=True,
126
+ timeout=30
127
+ )
128
+
129
+ if result.returncode != 0:
130
+ return DeployResult(
131
+ success=False,
132
+ message="Failed to register task definition",
133
+ error=result.stderr
134
+ )
135
+
136
+ # Step 3: Create or update service
137
+ print(f"🚀 Deploying service: {self.config.service_name}")
138
+
139
+ # Try to update first, create if doesn't exist
140
+ update_result = subprocess.run(
141
+ ['aws', 'ecs', 'update-service',
142
+ '--cluster', cluster_name,
143
+ '--service', self.config.service_name,
144
+ '--task-definition', self.config.service_name,
145
+ '--desired-count', str(self.config.min_instances),
146
+ '--region', self.config.region],
147
+ capture_output=True,
148
+ text=True,
149
+ timeout=60
150
+ )
151
+
152
+ if update_result.returncode != 0:
153
+ # Service doesn't exist, create it
154
+ # Note: This is simplified - production would need VPC/subnet/security group config
155
+ return DeployResult(
156
+ success=False,
157
+ message="Service creation requires VPC configuration",
158
+ error="Please create the service manually with proper VPC/subnet/security group configuration, then use update"
159
+ )
160
+
161
+ return DeployResult(
162
+ success=True,
163
+ message=f"Service deployed successfully to AWS ECS",
164
+ url=f"https://console.aws.amazon.com/ecs/home?region={self.config.region}#/clusters/{cluster_name}/services/{self.config.service_name}",
165
+ metadata={
166
+ "cluster": cluster_name,
167
+ "service": self.config.service_name,
168
+ "region": self.config.region
169
+ }
170
+ )
171
+
172
+ except Exception as e:
173
+ return DeployResult(
174
+ success=False,
175
+ message="AWS deployment failed",
176
+ error=str(e)
177
+ )
178
+
179
+ def status(self) -> DeployStatus:
180
+ """Get current AWS ECS service status."""
181
+ try:
182
+ cluster_name = self.config.cluster_name or f"{self.config.service_name}-cluster"
183
+
184
+ result = subprocess.run(
185
+ ['aws', 'ecs', 'describe-services',
186
+ '--cluster', cluster_name,
187
+ '--services', self.config.service_name,
188
+ '--region', self.config.region,
189
+ '--output', 'json'],
190
+ capture_output=True,
191
+ text=True,
192
+ timeout=30
193
+ )
194
+
195
+ if result.returncode != 0:
196
+ return DeployStatus(
197
+ state=ServiceState.NOT_FOUND,
198
+ message=f"Service not found or error: {result.stderr}",
199
+ service_name=self.config.service_name,
200
+ provider="aws",
201
+ region=self.config.region
202
+ )
203
+
204
+ data = json.loads(result.stdout)
205
+ services = data.get('services', [])
206
+
207
+ if not services:
208
+ return DeployStatus(
209
+ state=ServiceState.NOT_FOUND,
210
+ message="Service not found",
211
+ service_name=self.config.service_name,
212
+ provider="aws",
213
+ region=self.config.region
214
+ )
215
+
216
+ service = services[0]
217
+ status_str = service.get('status', 'UNKNOWN')
218
+ running_count = service.get('runningCount', 0)
219
+ desired_count = service.get('desiredCount', 0)
220
+
221
+ # Map AWS status to ServiceState
222
+ if status_str == 'ACTIVE' and running_count > 0:
223
+ state = ServiceState.RUNNING
224
+ elif status_str == 'ACTIVE' and running_count == 0:
225
+ state = ServiceState.STOPPED
226
+ elif status_str == 'DRAINING':
227
+ state = ServiceState.PENDING
228
+ elif status_str == 'INACTIVE':
229
+ state = ServiceState.STOPPED
230
+ else:
231
+ state = ServiceState.UNKNOWN
232
+
233
+ return DeployStatus(
234
+ state=state,
235
+ url=f"https://console.aws.amazon.com/ecs/home?region={self.config.region}#/clusters/{cluster_name}/services/{self.config.service_name}",
236
+ message=f"Status: {status_str}",
237
+ service_name=self.config.service_name,
238
+ provider="aws",
239
+ region=self.config.region,
240
+ healthy=running_count >= desired_count and running_count > 0,
241
+ instances_running=running_count,
242
+ instances_desired=desired_count,
243
+ created_at=service.get('createdAt'),
244
+ metadata={
245
+ "cluster": cluster_name,
246
+ "task_definition": service.get('taskDefinition'),
247
+ "launch_type": service.get('launchType'),
248
+ "deployments": len(service.get('deployments', []))
249
+ }
250
+ )
251
+
252
+ except Exception as e:
253
+ return DeployStatus(
254
+ state=ServiceState.UNKNOWN,
255
+ message=f"Failed to get status: {e}",
256
+ service_name=self.config.service_name,
257
+ provider="aws",
258
+ region=self.config.region
259
+ )
260
+
261
+ def destroy(self, force: bool = False) -> DestroyResult:
262
+ """Destroy AWS ECS service and related resources."""
263
+ try:
264
+ cluster_name = self.config.cluster_name or f"{self.config.service_name}-cluster"
265
+ deleted_resources = []
266
+
267
+ # Step 1: Update service desired count to 0
268
+ print(f"🛑 Stopping service: {self.config.service_name}")
269
+ subprocess.run(
270
+ ['aws', 'ecs', 'update-service',
271
+ '--cluster', cluster_name,
272
+ '--service', self.config.service_name,
273
+ '--desired-count', '0',
274
+ '--region', self.config.region],
275
+ capture_output=True,
276
+ timeout=30
277
+ )
278
+
279
+ # Step 2: Delete the service
280
+ print(f"🗑️ Deleting service: {self.config.service_name}")
281
+ result = subprocess.run(
282
+ ['aws', 'ecs', 'delete-service',
283
+ '--cluster', cluster_name,
284
+ '--service', self.config.service_name,
285
+ '--force' if force else '--no-force',
286
+ '--region', self.config.region],
287
+ capture_output=True,
288
+ text=True,
289
+ timeout=60
290
+ )
291
+
292
+ if result.returncode == 0:
293
+ deleted_resources.append(f"ecs-service:{self.config.service_name}")
294
+ else:
295
+ return DestroyResult(
296
+ success=False,
297
+ message="Failed to delete service",
298
+ error=result.stderr,
299
+ resources_deleted=deleted_resources
300
+ )
301
+
302
+ # Step 3: Optionally delete cluster if empty
303
+ if force:
304
+ print(f"🗑️ Deleting cluster: {cluster_name}")
305
+ cluster_result = subprocess.run(
306
+ ['aws', 'ecs', 'delete-cluster',
307
+ '--cluster', cluster_name,
308
+ '--region', self.config.region],
309
+ capture_output=True,
310
+ text=True,
311
+ timeout=30
312
+ )
313
+ if cluster_result.returncode == 0:
314
+ deleted_resources.append(f"ecs-cluster:{cluster_name}")
315
+
316
+ return DestroyResult(
317
+ success=True,
318
+ message=f"Successfully destroyed AWS ECS service",
319
+ resources_deleted=deleted_resources,
320
+ metadata={
321
+ "cluster": cluster_name,
322
+ "region": self.config.region
323
+ }
324
+ )
325
+
326
+ except Exception as e:
327
+ return DestroyResult(
328
+ success=False,
329
+ message="Failed to destroy AWS resources",
330
+ error=str(e)
331
+ )