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,145 @@
1
+ """
2
+ Traces command group for PraisonAI CLI.
3
+
4
+ Provides trace collection management:
5
+ - traces enable: Enable trace collection
6
+ - traces disable: Disable trace collection
7
+ - traces status: Show current status
8
+ - traces list: List recent traces
9
+ """
10
+
11
+ from typing import Optional
12
+
13
+ import typer
14
+
15
+ from ..configuration.loader import get_config_loader
16
+ from ..output.console import get_output_controller
17
+
18
+ app = typer.Typer(help="Trace collection management")
19
+
20
+
21
+ @app.command("enable")
22
+ def traces_enable(
23
+ endpoint: Optional[str] = typer.Option(
24
+ None,
25
+ "--endpoint",
26
+ "-e",
27
+ help="Trace endpoint URL",
28
+ ),
29
+ sample_rate: float = typer.Option(
30
+ 1.0,
31
+ "--sample-rate",
32
+ "-r",
33
+ help="Sample rate (0.0 to 1.0)",
34
+ ),
35
+ ):
36
+ """Enable trace collection."""
37
+ output = get_output_controller()
38
+ loader = get_config_loader()
39
+
40
+ loader.set("traces.enabled", True)
41
+ if endpoint:
42
+ loader.set("traces.endpoint", endpoint)
43
+ if sample_rate != 1.0:
44
+ loader.set("traces.sample_rate", sample_rate)
45
+
46
+ if output.is_json_mode:
47
+ output.print_json({
48
+ "traces_enabled": True,
49
+ "endpoint": endpoint,
50
+ "sample_rate": sample_rate,
51
+ })
52
+ else:
53
+ output.print_success("Trace collection enabled")
54
+ if endpoint:
55
+ output.print(f" Endpoint: {endpoint}")
56
+ output.print(f" Sample rate: {sample_rate}")
57
+
58
+
59
+ @app.command("disable")
60
+ def traces_disable():
61
+ """Disable trace collection."""
62
+ output = get_output_controller()
63
+ loader = get_config_loader()
64
+
65
+ loader.set("traces.enabled", False)
66
+
67
+ if output.is_json_mode:
68
+ output.print_json({"traces_enabled": False})
69
+ else:
70
+ output.print_success("Trace collection disabled")
71
+
72
+
73
+ @app.command("status")
74
+ def traces_status():
75
+ """Show trace collection status."""
76
+ output = get_output_controller()
77
+ loader = get_config_loader()
78
+
79
+ enabled = loader.get("traces.enabled", False)
80
+ endpoint = loader.get("traces.endpoint")
81
+ sample_rate = loader.get("traces.sample_rate", 1.0)
82
+
83
+ if output.is_json_mode:
84
+ output.print_json({
85
+ "enabled": enabled,
86
+ "endpoint": endpoint,
87
+ "sample_rate": sample_rate,
88
+ })
89
+ else:
90
+ status = "✅ Enabled" if enabled else "❌ Disabled"
91
+ output.print_panel(
92
+ f"Status: {status}\n"
93
+ f"Endpoint: {endpoint or 'Not configured'}\n"
94
+ f"Sample Rate: {sample_rate}",
95
+ title="Trace Collection Status"
96
+ )
97
+
98
+
99
+ @app.command("list")
100
+ def traces_list(
101
+ limit: int = typer.Option(
102
+ 20,
103
+ "--limit",
104
+ "-n",
105
+ help="Maximum number of traces to show",
106
+ ),
107
+ ):
108
+ """List recent traces."""
109
+ output = get_output_controller()
110
+
111
+ from ..configuration.paths import get_traces_dir
112
+
113
+ traces_dir = get_traces_dir()
114
+
115
+ if not traces_dir.exists():
116
+ if output.is_json_mode:
117
+ output.print_json({"traces": []})
118
+ else:
119
+ output.print_info("No traces found")
120
+ return
121
+
122
+ traces = []
123
+ for trace_file in sorted(traces_dir.iterdir(), reverse=True)[:limit]:
124
+ if trace_file.is_file() and trace_file.suffix == ".json":
125
+ traces.append({
126
+ "name": trace_file.stem,
127
+ "size": trace_file.stat().st_size,
128
+ "modified": trace_file.stat().st_mtime,
129
+ })
130
+
131
+ if output.is_json_mode:
132
+ output.print_json({"traces": traces})
133
+ else:
134
+ if not traces:
135
+ output.print_info("No traces found")
136
+ return
137
+
138
+ headers = ["Name", "Size", "Modified"]
139
+ rows = []
140
+ for t in traces:
141
+ from datetime import datetime
142
+ modified = datetime.fromtimestamp(t["modified"]).strftime("%Y-%m-%d %H:%M")
143
+ rows.append([t["name"], f"{t['size']} bytes", modified])
144
+
145
+ output.print_table(headers, rows, title="Recent Traces")
@@ -0,0 +1,101 @@
1
+ """
2
+ Version command group for PraisonAI CLI.
3
+
4
+ Provides version information:
5
+ - version show: Show version
6
+ - version check: Check for updates
7
+ """
8
+
9
+ import typer
10
+
11
+ from ..output.console import get_output_controller
12
+
13
+ app = typer.Typer(help="Version information")
14
+
15
+
16
+ @app.command("show")
17
+ def version_show():
18
+ """Show version information."""
19
+ output = get_output_controller()
20
+
21
+ from praisonai.version import __version__
22
+
23
+ # Try to get additional version info
24
+ versions = {
25
+ "praisonai": __version__,
26
+ }
27
+
28
+ # Check praisonaiagents version
29
+ try:
30
+ import praisonaiagents
31
+ versions["praisonaiagents"] = getattr(praisonaiagents, "__version__", "unknown")
32
+ except ImportError:
33
+ versions["praisonaiagents"] = "not installed"
34
+
35
+ # Check Python version
36
+ import sys
37
+ versions["python"] = f"{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}"
38
+
39
+ if output.is_json_mode:
40
+ output.print_json(versions)
41
+ return
42
+
43
+ output.print_panel(
44
+ f"PraisonAI: {versions['praisonai']}\n"
45
+ f"PraisonAI Agents: {versions['praisonaiagents']}\n"
46
+ f"Python: {versions['python']}",
47
+ title="Version Information"
48
+ )
49
+
50
+
51
+ @app.command("check")
52
+ def version_check():
53
+ """Check for updates."""
54
+ output = get_output_controller()
55
+
56
+ from praisonai.version import __version__
57
+
58
+ output.print_info("Checking for updates...")
59
+
60
+ try:
61
+ import urllib.request
62
+ import json
63
+
64
+ url = "https://pypi.org/pypi/praisonai/json"
65
+ with urllib.request.urlopen(url, timeout=5) as response:
66
+ data = json.loads(response.read().decode())
67
+ latest = data["info"]["version"]
68
+
69
+ if output.is_json_mode:
70
+ output.print_json({
71
+ "current": __version__,
72
+ "latest": latest,
73
+ "update_available": latest != __version__,
74
+ })
75
+ return
76
+
77
+ if latest != __version__:
78
+ output.print_warning(
79
+ f"Update available: {__version__} → {latest}\n"
80
+ f"Run: pip install --upgrade praisonai"
81
+ )
82
+ else:
83
+ output.print_success(f"You are using the latest version ({__version__})")
84
+
85
+ except Exception as e:
86
+ if output.is_json_mode:
87
+ output.print_json({
88
+ "current": __version__,
89
+ "latest": None,
90
+ "error": str(e),
91
+ })
92
+ else:
93
+ output.print_error(f"Failed to check for updates: {e}")
94
+ output.print(f"Current version: {__version__}")
95
+
96
+
97
+ @app.callback(invoke_without_command=True)
98
+ def version_callback(ctx: typer.Context):
99
+ """Show version (default behavior)."""
100
+ if ctx.invoked_subcommand is None:
101
+ version_show()
@@ -0,0 +1,18 @@
1
+ """
2
+ PraisonAI CLI Configuration Module.
3
+
4
+ Provides configuration management with TOML support and precedence handling.
5
+ """
6
+
7
+ from .loader import ConfigLoader, get_config
8
+ from .schema import ConfigSchema
9
+ from .paths import get_config_paths, get_user_config_path, get_project_config_path
10
+
11
+ __all__ = [
12
+ 'ConfigLoader',
13
+ 'ConfigSchema',
14
+ 'get_config',
15
+ 'get_config_paths',
16
+ 'get_user_config_path',
17
+ 'get_project_config_path',
18
+ ]
@@ -0,0 +1,353 @@
1
+ """
2
+ Configuration loader for PraisonAI CLI.
3
+
4
+ Handles loading, merging, and saving configuration with precedence.
5
+ """
6
+
7
+ import os
8
+ import threading
9
+ from pathlib import Path
10
+ from typing import Any, Dict, Optional
11
+
12
+ from .paths import (
13
+ get_config_paths,
14
+ get_user_config_path,
15
+ get_project_config_path,
16
+ get_env_prefix,
17
+ ensure_config_dirs,
18
+ )
19
+ from .schema import ConfigSchema, DEFAULT_CONFIG
20
+
21
+
22
+ # Thread-safe config cache
23
+ _config_lock = threading.Lock()
24
+ _config_cache: Optional[ConfigSchema] = None
25
+
26
+
27
+ def _load_toml(path: Path) -> Dict[str, Any]:
28
+ """Load a TOML file."""
29
+ try:
30
+ # Try tomllib (Python 3.11+) first
31
+ import tomllib
32
+ with open(path, "rb") as f:
33
+ return tomllib.load(f)
34
+ except ImportError:
35
+ pass
36
+
37
+ try:
38
+ # Fall back to tomli
39
+ import tomli
40
+ with open(path, "rb") as f:
41
+ return tomli.load(f)
42
+ except ImportError:
43
+ pass
44
+
45
+ # Last resort: basic TOML parsing
46
+ return _basic_toml_parse(path)
47
+
48
+
49
+ def _basic_toml_parse(path: Path) -> Dict[str, Any]:
50
+ """Basic TOML parser for simple configs."""
51
+ result: Dict[str, Any] = {}
52
+ current_section: Optional[str] = None
53
+
54
+ with open(path, "r", encoding="utf-8") as f:
55
+ for line in f:
56
+ line = line.strip()
57
+ if not line or line.startswith("#"):
58
+ continue
59
+
60
+ if line.startswith("[") and line.endswith("]"):
61
+ current_section = line[1:-1]
62
+ if current_section not in result:
63
+ result[current_section] = {}
64
+ elif "=" in line:
65
+ key, value = line.split("=", 1)
66
+ key = key.strip()
67
+ value = value.strip()
68
+
69
+ # Parse value
70
+ if value.lower() == "true":
71
+ parsed_value = True
72
+ elif value.lower() == "false":
73
+ parsed_value = False
74
+ elif value.startswith('"') and value.endswith('"'):
75
+ parsed_value = value[1:-1]
76
+ elif value.startswith("'") and value.endswith("'"):
77
+ parsed_value = value[1:-1]
78
+ else:
79
+ try:
80
+ parsed_value = int(value)
81
+ except ValueError:
82
+ try:
83
+ parsed_value = float(value)
84
+ except ValueError:
85
+ parsed_value = value
86
+
87
+ if current_section:
88
+ result[current_section][key] = parsed_value
89
+ else:
90
+ result[key] = parsed_value
91
+
92
+ return result
93
+
94
+
95
+ def _save_toml(path: Path, data: Dict[str, Any]) -> None:
96
+ """Save data to a TOML file."""
97
+ try:
98
+ import tomli_w
99
+ with open(path, "wb") as f:
100
+ tomli_w.dump(data, f)
101
+ return
102
+ except ImportError:
103
+ pass
104
+
105
+ # Fall back to basic TOML writing
106
+ _basic_toml_write(path, data)
107
+
108
+
109
+ def _basic_toml_write(path: Path, data: Dict[str, Any]) -> None:
110
+ """Basic TOML writer."""
111
+ lines = []
112
+
113
+ # Write top-level keys first
114
+ for key, value in data.items():
115
+ if not isinstance(value, dict):
116
+ lines.append(f"{key} = {_format_toml_value(value)}")
117
+
118
+ # Write sections
119
+ for key, value in data.items():
120
+ if isinstance(value, dict):
121
+ lines.append(f"\n[{key}]")
122
+ for sub_key, sub_value in value.items():
123
+ if not isinstance(sub_value, dict):
124
+ lines.append(f"{sub_key} = {_format_toml_value(sub_value)}")
125
+ else:
126
+ # Nested section
127
+ lines.append(f"\n[{key}.{sub_key}]")
128
+ for nested_key, nested_value in sub_value.items():
129
+ lines.append(f"{nested_key} = {_format_toml_value(nested_value)}")
130
+
131
+ path.parent.mkdir(parents=True, exist_ok=True)
132
+ with open(path, "w", encoding="utf-8") as f:
133
+ f.write("\n".join(lines) + "\n")
134
+
135
+
136
+ def _format_toml_value(value: Any) -> str:
137
+ """Format a value for TOML."""
138
+ if isinstance(value, bool):
139
+ return "true" if value else "false"
140
+ elif isinstance(value, str):
141
+ return f'"{value}"'
142
+ elif isinstance(value, (int, float)):
143
+ return str(value)
144
+ elif isinstance(value, list):
145
+ items = ", ".join(_format_toml_value(v) for v in value)
146
+ return f"[{items}]"
147
+ else:
148
+ return f'"{value}"'
149
+
150
+
151
+ def _merge_dicts(base: Dict[str, Any], override: Dict[str, Any]) -> Dict[str, Any]:
152
+ """Deep merge two dictionaries."""
153
+ result = base.copy()
154
+ for key, value in override.items():
155
+ if key in result and isinstance(result[key], dict) and isinstance(value, dict):
156
+ result[key] = _merge_dicts(result[key], value)
157
+ else:
158
+ result[key] = value
159
+ return result
160
+
161
+
162
+ def _get_env_overrides() -> Dict[str, Any]:
163
+ """Get configuration overrides from environment variables."""
164
+ prefix = get_env_prefix()
165
+ overrides: Dict[str, Any] = {}
166
+
167
+ for key, value in os.environ.items():
168
+ if not key.startswith(prefix):
169
+ continue
170
+
171
+ # Convert PRAISONAI_OUTPUT_FORMAT to output.format
172
+ config_key = key[len(prefix):].lower()
173
+ parts = config_key.split("_")
174
+
175
+ # Parse value
176
+ if value.lower() == "true":
177
+ parsed_value = True
178
+ elif value.lower() == "false":
179
+ parsed_value = False
180
+ else:
181
+ try:
182
+ parsed_value = int(value)
183
+ except ValueError:
184
+ try:
185
+ parsed_value = float(value)
186
+ except ValueError:
187
+ parsed_value = value
188
+
189
+ # Build nested dict
190
+ if len(parts) >= 2:
191
+ section = parts[0]
192
+ sub_key = "_".join(parts[1:])
193
+ if section not in overrides:
194
+ overrides[section] = {}
195
+ overrides[section][sub_key] = parsed_value
196
+ else:
197
+ overrides[config_key] = parsed_value
198
+
199
+ return overrides
200
+
201
+
202
+ def _get_dotted_value(data: Dict[str, Any], key: str) -> Any:
203
+ """Get a value using dotted key notation."""
204
+ parts = key.split(".")
205
+ current = data
206
+ for part in parts:
207
+ if isinstance(current, dict) and part in current:
208
+ current = current[part]
209
+ else:
210
+ return None
211
+ return current
212
+
213
+
214
+ def _set_dotted_value(data: Dict[str, Any], key: str, value: Any) -> None:
215
+ """Set a value using dotted key notation."""
216
+ parts = key.split(".")
217
+ current = data
218
+ for part in parts[:-1]:
219
+ if part not in current:
220
+ current[part] = {}
221
+ current = current[part]
222
+ current[parts[-1]] = value
223
+
224
+
225
+ class ConfigLoader:
226
+ """
227
+ Configuration loader with precedence handling.
228
+
229
+ Precedence (highest to lowest):
230
+ 1. CLI flags (not handled here)
231
+ 2. Environment variables (PRAISONAI_*)
232
+ 3. Project config (.praison/config.toml)
233
+ 4. User config (~/.praison/config.toml)
234
+ 5. Defaults
235
+ """
236
+
237
+ def __init__(self, project_root: Optional[Path] = None):
238
+ self.project_root = project_root or Path.cwd()
239
+ self._config: Optional[ConfigSchema] = None
240
+ self._raw_config: Dict[str, Any] = {}
241
+
242
+ def load(self, force_reload: bool = False) -> ConfigSchema:
243
+ """Load configuration with precedence."""
244
+ if self._config is not None and not force_reload:
245
+ return self._config
246
+
247
+ # Start with defaults
248
+ merged = DEFAULT_CONFIG.to_dict()
249
+
250
+ # Load config files in reverse precedence order
251
+ config_paths = get_config_paths(self.project_root)
252
+ for path in reversed(config_paths):
253
+ try:
254
+ file_config = _load_toml(path)
255
+ merged = _merge_dicts(merged, file_config)
256
+ except Exception:
257
+ pass # Skip invalid files
258
+
259
+ # Apply environment overrides
260
+ env_overrides = _get_env_overrides()
261
+ merged = _merge_dicts(merged, env_overrides)
262
+
263
+ self._raw_config = merged
264
+ self._config = ConfigSchema.from_dict(merged)
265
+ return self._config
266
+
267
+ def get(self, key: str, default: Any = None) -> Any:
268
+ """Get a configuration value using dotted key notation."""
269
+ self.load()
270
+ value = _get_dotted_value(self._raw_config, key)
271
+ return value if value is not None else default
272
+
273
+ def set(self, key: str, value: Any, scope: str = "user") -> None:
274
+ """
275
+ Set a configuration value.
276
+
277
+ Args:
278
+ key: Dotted key notation (e.g., "output.format")
279
+ value: Value to set
280
+ scope: "user" or "project"
281
+ """
282
+ if scope == "project":
283
+ config_path = get_project_config_path(self.project_root)
284
+ else:
285
+ config_path = get_user_config_path()
286
+
287
+ # Load existing config or create empty
288
+ if config_path.exists():
289
+ try:
290
+ existing = _load_toml(config_path)
291
+ except Exception:
292
+ existing = {}
293
+ else:
294
+ existing = {}
295
+
296
+ # Set the value
297
+ _set_dotted_value(existing, key, value)
298
+
299
+ # Ensure directory exists
300
+ ensure_config_dirs()
301
+ if scope == "project":
302
+ config_path.parent.mkdir(parents=True, exist_ok=True)
303
+
304
+ # Save
305
+ _save_toml(config_path, existing)
306
+
307
+ # Reload
308
+ self.load(force_reload=True)
309
+
310
+ def reset(self, scope: str = "user") -> None:
311
+ """Reset configuration to defaults."""
312
+ if scope == "project":
313
+ config_path = get_project_config_path(self.project_root)
314
+ else:
315
+ config_path = get_user_config_path()
316
+
317
+ if config_path.exists():
318
+ config_path.unlink()
319
+
320
+ self.load(force_reload=True)
321
+
322
+ def list_all(self) -> Dict[str, Any]:
323
+ """List all configuration values."""
324
+ self.load()
325
+ return self._raw_config.copy()
326
+
327
+
328
+ # Global config loader
329
+ _global_loader: Optional[ConfigLoader] = None
330
+
331
+
332
+ def get_config(project_root: Optional[Path] = None) -> ConfigSchema:
333
+ """Get the global configuration."""
334
+ global _global_loader, _config_cache
335
+
336
+ with _config_lock:
337
+ if _global_loader is None or project_root is not None:
338
+ _global_loader = ConfigLoader(project_root)
339
+
340
+ if _config_cache is None:
341
+ _config_cache = _global_loader.load()
342
+
343
+ return _config_cache
344
+
345
+
346
+ def get_config_loader(project_root: Optional[Path] = None) -> ConfigLoader:
347
+ """Get the global config loader."""
348
+ global _global_loader
349
+
350
+ with _config_lock:
351
+ if _global_loader is None or project_root is not None:
352
+ _global_loader = ConfigLoader(project_root)
353
+ return _global_loader