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,384 @@
1
+ """
2
+ Image Handler for CLI.
3
+
4
+ Provides two distinct image capabilities:
5
+ 1. Image Description (Vision) - Analyze existing images using vision-capable LLMs
6
+ Usage: praisonai "Describe this image" --image path/to/image.png
7
+
8
+ 2. Image Generation - Generate new images from text prompts
9
+ Usage: praisonai "A sunset over mountains" --image-generate
10
+ """
11
+
12
+ import os
13
+ import base64
14
+ import logging
15
+ from typing import Any, Dict, Tuple, List, Optional
16
+ from .base import FlagHandler
17
+
18
+ logger = logging.getLogger(__name__)
19
+
20
+ # Supported image extensions for vision/description
21
+ SUPPORTED_EXTENSIONS = {'.png', '.jpg', '.jpeg', '.gif', '.webp', '.bmp', '.svg', '.tiff'}
22
+
23
+ # Default vision-capable models (gpt-4o has better vision support than gpt-4o-mini)
24
+ DEFAULT_VISION_MODEL = "gpt-4o"
25
+
26
+ # Default image generation models
27
+ DEFAULT_IMAGE_GEN_MODEL = "dall-e-3"
28
+ SUPPORTED_IMAGE_GEN_MODELS = [
29
+ 'gpt-image-1', 'gpt-image-1-mini', 'gpt-image-1.5',
30
+ 'chatgpt-image-latest', 'dall-e-2', 'dall-e-3'
31
+ ]
32
+
33
+
34
+ class ImageHandler(FlagHandler):
35
+ """
36
+ Handler for --image flag (Image Description/Vision).
37
+
38
+ Describes/analyzes existing images using vision-capable LLMs like GPT-4o.
39
+ This is for understanding what's IN an image, not generating new images.
40
+
41
+ Example:
42
+ praisonai "Describe this image" --image photo.png
43
+ praisonai "What's in this image?" --image /path/to/image.jpg
44
+ praisonai "Count the objects" --image image1.png,image2.png
45
+ """
46
+
47
+ @property
48
+ def feature_name(self) -> str:
49
+ return "image"
50
+
51
+ @property
52
+ def flag_name(self) -> str:
53
+ return "image"
54
+
55
+ @property
56
+ def flag_help(self) -> str:
57
+ return "Path to image file for vision-based description/analysis"
58
+
59
+ def check_dependencies(self) -> Tuple[bool, str]:
60
+ """Check if litellm is available for vision."""
61
+ try:
62
+ import litellm
63
+ return True, ""
64
+ except ImportError:
65
+ return False, "litellm not installed. Install with: pip install litellm"
66
+
67
+ def validate_image_path(self, path: str) -> Tuple[bool, str]:
68
+ """
69
+ Validate that the image path is valid.
70
+
71
+ Args:
72
+ path: Path to the image file
73
+
74
+ Returns:
75
+ Tuple of (is_valid, error_message)
76
+ """
77
+ if not path:
78
+ return False, "No image path provided"
79
+
80
+ # Check extension
81
+ ext = os.path.splitext(path)[1].lower()
82
+ if ext not in SUPPORTED_EXTENSIONS:
83
+ return False, f"Unsupported image format: {ext}. Supported: {', '.join(SUPPORTED_EXTENSIONS)}"
84
+
85
+ # Check if file exists (for local files)
86
+ if not path.startswith(('http://', 'https://')):
87
+ if not os.path.exists(path):
88
+ return False, f"Image file not found: {path}"
89
+
90
+ return True, ""
91
+
92
+ def _encode_image_to_base64(self, image_path: str) -> str:
93
+ """Encode a local image file to base64."""
94
+ with open(image_path, 'rb') as f:
95
+ return base64.b64encode(f.read()).decode('utf-8')
96
+
97
+ def _get_image_mime_type(self, image_path: str) -> str:
98
+ """Get MIME type based on file extension."""
99
+ ext = os.path.splitext(image_path)[1].lower()
100
+ mime_types = {
101
+ '.png': 'image/png',
102
+ '.jpg': 'image/jpeg',
103
+ '.jpeg': 'image/jpeg',
104
+ '.gif': 'image/gif',
105
+ '.webp': 'image/webp',
106
+ '.bmp': 'image/bmp',
107
+ '.svg': 'image/svg+xml',
108
+ '.tiff': 'image/tiff',
109
+ }
110
+ return mime_types.get(ext, 'image/png')
111
+
112
+ def _build_image_content(self, image_path: str) -> Dict[str, Any]:
113
+ """Build image content for vision API."""
114
+ if image_path.startswith(('http://', 'https://')):
115
+ return {
116
+ "type": "image_url",
117
+ "image_url": {"url": image_path}
118
+ }
119
+ else:
120
+ mime_type = self._get_image_mime_type(image_path)
121
+ base64_data = self._encode_image_to_base64(image_path)
122
+ return {
123
+ "type": "image_url",
124
+ "image_url": {"url": f"data:{mime_type};base64,{base64_data}"}
125
+ }
126
+
127
+ def apply_to_agent_config(self, config: Dict[str, Any], flag_value: Any) -> Dict[str, Any]:
128
+ """Apply image configuration to agent config."""
129
+ if flag_value:
130
+ if isinstance(flag_value, str):
131
+ config["images"] = [flag_value]
132
+ elif isinstance(flag_value, list):
133
+ config["images"] = flag_value
134
+ config["use_vision"] = True
135
+ return config
136
+
137
+ def describe_image(self, prompt: str, image_path: str, llm = None) -> str:
138
+ """
139
+ Describe an image using vision-capable LLM.
140
+
141
+ Args:
142
+ prompt: The prompt/question about the image
143
+ image_path: Path to the image file
144
+ llm: Optional LLM model name (must be vision-capable), can be string or dict
145
+
146
+ Returns:
147
+ Description of the image
148
+ """
149
+ valid, msg = self.validate_image_path(image_path)
150
+ if not valid:
151
+ return f"Error: {msg}"
152
+
153
+ available, dep_msg = self.check_dependencies()
154
+ if not available:
155
+ return f"Error: {dep_msg}"
156
+
157
+ import litellm
158
+
159
+ # Handle llm being a dict (from agent_config) or string
160
+ if isinstance(llm, dict):
161
+ model = llm.get('model', DEFAULT_VISION_MODEL)
162
+ else:
163
+ model = llm or DEFAULT_VISION_MODEL
164
+
165
+ try:
166
+ # Build message with image
167
+ content = [
168
+ {"type": "text", "text": prompt},
169
+ self._build_image_content(image_path)
170
+ ]
171
+
172
+ response = litellm.completion(
173
+ model=model,
174
+ messages=[{"role": "user", "content": content}]
175
+ )
176
+
177
+ return response.choices[0].message.content
178
+
179
+ except Exception as e:
180
+ logger.error(f"Error describing image: {e}")
181
+ return f"Error describing image: {e}"
182
+
183
+ def describe_multiple_images(self, prompt: str, image_paths: List[str], llm = None) -> str:
184
+ """
185
+ Describe multiple images using vision-capable LLM.
186
+
187
+ Args:
188
+ prompt: The prompt/question about the images
189
+ image_paths: List of paths to image files
190
+ llm: Optional LLM model name, can be string or dict
191
+
192
+ Returns:
193
+ Description of the images
194
+ """
195
+ for path in image_paths:
196
+ valid, msg = self.validate_image_path(path)
197
+ if not valid:
198
+ return f"Error: {msg}"
199
+
200
+ available, dep_msg = self.check_dependencies()
201
+ if not available:
202
+ return f"Error: {dep_msg}"
203
+
204
+ import litellm
205
+
206
+ # Handle llm being a dict (from agent_config) or string
207
+ if isinstance(llm, dict):
208
+ model = llm.get('model', DEFAULT_VISION_MODEL)
209
+ else:
210
+ model = llm or DEFAULT_VISION_MODEL
211
+
212
+ try:
213
+ # Build message with all images
214
+ content = [{"type": "text", "text": prompt}]
215
+ for path in image_paths:
216
+ content.append(self._build_image_content(path))
217
+
218
+ response = litellm.completion(
219
+ model=model,
220
+ messages=[{"role": "user", "content": content}]
221
+ )
222
+
223
+ return response.choices[0].message.content
224
+
225
+ except Exception as e:
226
+ logger.error(f"Error describing images: {e}")
227
+ return f"Error describing images: {e}"
228
+
229
+ def execute(self, prompt: str = None, image_path: str = None, llm: str = None, **kwargs) -> str:
230
+ """
231
+ Execute image description (vision).
232
+
233
+ Args:
234
+ prompt: The prompt/question about the image
235
+ image_path: Path to the image file (or comma-separated paths)
236
+ llm: Optional vision-capable LLM model name
237
+
238
+ Returns:
239
+ Description of the image(s)
240
+ """
241
+ if not prompt:
242
+ return "Error: No prompt provided"
243
+
244
+ if not image_path:
245
+ return "Error: No image path provided"
246
+
247
+ # Handle multiple images (comma-separated)
248
+ if ',' in image_path:
249
+ paths = [p.strip() for p in image_path.split(',')]
250
+ return self.describe_multiple_images(prompt, paths, llm)
251
+
252
+ return self.describe_image(prompt, image_path, llm)
253
+
254
+
255
+ class ImageGenerateHandler(FlagHandler):
256
+ """
257
+ Handler for --image-generate flag (Image Generation).
258
+
259
+ Generates NEW images from text prompts using DALL-E or similar models.
260
+ This is for CREATING images, not analyzing existing ones.
261
+
262
+ Example:
263
+ praisonai "A sunset over mountains" --image-generate
264
+ praisonai "A cat wearing a hat" --image-generate --llm dall-e-3
265
+ """
266
+
267
+ @property
268
+ def feature_name(self) -> str:
269
+ return "image_generate"
270
+
271
+ @property
272
+ def flag_name(self) -> str:
273
+ return "image_generate"
274
+
275
+ @property
276
+ def flag_help(self) -> str:
277
+ return "Generate an image from the text prompt"
278
+
279
+ def check_dependencies(self) -> Tuple[bool, str]:
280
+ """Check if ImageAgent is available."""
281
+ try:
282
+ import importlib.util
283
+ if importlib.util.find_spec("praisonaiagents") is not None:
284
+ return True, ""
285
+ return False, "praisonaiagents not installed. Install with: pip install praisonaiagents"
286
+ except ImportError:
287
+ return False, "praisonaiagents not installed. Install with: pip install praisonaiagents"
288
+
289
+ def apply_to_agent_config(self, config: Dict[str, Any], flag_value: Any) -> Dict[str, Any]:
290
+ """Apply image generation configuration."""
291
+ if flag_value:
292
+ config["use_image_generation"] = True
293
+ return config
294
+
295
+ def generate_image(self, prompt: str, llm: str = None, output_path: str = None) -> Dict[str, Any]:
296
+ """
297
+ Generate an image from a text prompt.
298
+
299
+ Args:
300
+ prompt: Text description of the image to generate
301
+ llm: Image generation model (dall-e-3, dall-e-2, etc.)
302
+ output_path: Optional path to save the generated image
303
+
304
+ Returns:
305
+ Dict with image URL or path, or error message
306
+ """
307
+ available, msg = self.check_dependencies()
308
+ if not available:
309
+ return {"error": msg}
310
+
311
+ from praisonaiagents import ImageAgent
312
+
313
+ # Use provided model or default
314
+ model = llm or DEFAULT_IMAGE_GEN_MODEL
315
+
316
+ # Validate model is supported for generation
317
+ if model not in SUPPORTED_IMAGE_GEN_MODELS:
318
+ return {
319
+ "error": f"Invalid model: '{model}'. Supported image generation models: {', '.join(SUPPORTED_IMAGE_GEN_MODELS)}"
320
+ }
321
+
322
+ try:
323
+ agent = ImageAgent(
324
+ name="ImageGenerator",
325
+ role="Image Generation Assistant",
326
+ goal="Generate high-quality images from text descriptions",
327
+ llm=model
328
+ )
329
+
330
+ result = agent.chat(prompt)
331
+
332
+ # Save image if output path provided
333
+ if output_path and isinstance(result, dict) and 'data' in result:
334
+ self._save_image(result, output_path)
335
+ result['saved_to'] = output_path
336
+
337
+ return result
338
+
339
+ except Exception as e:
340
+ logger.error(f"Error generating image: {e}")
341
+ return {"error": str(e)}
342
+
343
+ def _save_image(self, result: Dict[str, Any], output_path: str) -> bool:
344
+ """Save generated image to file."""
345
+ try:
346
+ import requests
347
+
348
+ if 'data' in result and len(result['data']) > 0:
349
+ image_data = result['data'][0]
350
+
351
+ if 'url' in image_data:
352
+ # Download from URL
353
+ response = requests.get(image_data['url'])
354
+ with open(output_path, 'wb') as f:
355
+ f.write(response.content)
356
+ return True
357
+ elif 'b64_json' in image_data:
358
+ # Decode base64
359
+ import base64
360
+ img_bytes = base64.b64decode(image_data['b64_json'])
361
+ with open(output_path, 'wb') as f:
362
+ f.write(img_bytes)
363
+ return True
364
+ return False
365
+ except Exception as e:
366
+ logger.error(f"Error saving image: {e}")
367
+ return False
368
+
369
+ def execute(self, prompt: str = None, llm: str = None, output_path: str = None, **kwargs) -> Dict[str, Any]:
370
+ """
371
+ Execute image generation.
372
+
373
+ Args:
374
+ prompt: Text description of the image to generate
375
+ llm: Image generation model name
376
+ output_path: Optional path to save the image
377
+
378
+ Returns:
379
+ Dict with generated image info or error
380
+ """
381
+ if not prompt:
382
+ return {"error": "No prompt provided for image generation"}
383
+
384
+ return self.generate_image(prompt, llm, output_path)