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,305 @@
1
+ """
2
+ Thinking Budgets CLI Feature for PraisonAI.
3
+
4
+ Provides CLI commands for managing thinking budgets.
5
+
6
+ Commands:
7
+ - praisonai thinking status # Show current budget
8
+ - praisonai thinking set <level> # Set budget level
9
+ - praisonai thinking stats # Show usage statistics
10
+ """
11
+
12
+ import os
13
+ import json
14
+ from typing import Dict, Any
15
+
16
+
17
+ class ThinkingHandler:
18
+ """
19
+ Handler for thinking CLI commands.
20
+
21
+ Provides functionality to:
22
+ - Show current thinking budget settings
23
+ - Set budget levels (minimal, low, medium, high, maximum)
24
+ - Display usage statistics
25
+ """
26
+
27
+ CONFIG_FILE = ".praison/thinking.json"
28
+
29
+ def __init__(self, verbose: bool = False):
30
+ self.verbose = verbose
31
+ self._budget = None
32
+ self._tracker = None
33
+
34
+ @property
35
+ def feature_name(self) -> str:
36
+ return "thinking"
37
+
38
+ def _get_config_path(self) -> str:
39
+ """Get path to config file."""
40
+ return os.path.join(os.getcwd(), self.CONFIG_FILE)
41
+
42
+ def _load_config(self) -> Dict[str, Any]:
43
+ """Load config from file."""
44
+ config_path = self._get_config_path()
45
+ if os.path.exists(config_path):
46
+ try:
47
+ with open(config_path, 'r') as f:
48
+ return json.load(f)
49
+ except (json.JSONDecodeError, IOError):
50
+ pass
51
+ return {}
52
+
53
+ def _save_config(self, config: Dict[str, Any]):
54
+ """Save config to file."""
55
+ config_path = self._get_config_path()
56
+ os.makedirs(os.path.dirname(config_path), exist_ok=True)
57
+ with open(config_path, 'w') as f:
58
+ json.dump(config, f, indent=2)
59
+
60
+ def status(self) -> Dict[str, Any]:
61
+ """
62
+ Show current thinking budget status.
63
+
64
+ Returns:
65
+ Current budget configuration
66
+ """
67
+ config = self._load_config()
68
+
69
+ # Get current budget settings
70
+ level = config.get("level", "medium")
71
+ max_tokens = config.get("max_tokens", 8000)
72
+ adaptive = config.get("adaptive", True)
73
+
74
+ result = {
75
+ "level": level,
76
+ "max_tokens": max_tokens,
77
+ "adaptive": adaptive,
78
+ "config_file": self._get_config_path()
79
+ }
80
+
81
+ self._print_status(result)
82
+ return result
83
+
84
+ def _print_status(self, status: Dict[str, Any]):
85
+ """Print status in formatted output."""
86
+ try:
87
+ from rich.console import Console
88
+ from rich.table import Table
89
+ from rich.panel import Panel
90
+
91
+ console = Console()
92
+
93
+ table = Table(show_header=False, box=None)
94
+ table.add_column("Setting", style="cyan")
95
+ table.add_column("Value", style="green")
96
+
97
+ table.add_row("Level", status["level"])
98
+ table.add_row("Max Tokens", str(status["max_tokens"]))
99
+ table.add_row("Adaptive", "āœ“" if status["adaptive"] else "āœ—")
100
+ table.add_row("Config File", status["config_file"])
101
+
102
+ console.print(Panel(table, title="Thinking Budget Status", border_style="blue"))
103
+
104
+ except ImportError:
105
+ print("Thinking Budget Status:")
106
+ print(f" Level: {status['level']}")
107
+ print(f" Max Tokens: {status['max_tokens']}")
108
+ print(f" Adaptive: {status['adaptive']}")
109
+ print(f" Config File: {status['config_file']}")
110
+
111
+ def set_level(self, level: str) -> Dict[str, Any]:
112
+ """
113
+ Set thinking budget level.
114
+
115
+ Args:
116
+ level: Budget level (minimal, low, medium, high, maximum)
117
+
118
+ Returns:
119
+ Updated configuration
120
+ """
121
+ valid_levels = ["minimal", "low", "medium", "high", "maximum"]
122
+ level = level.lower()
123
+
124
+ if level not in valid_levels:
125
+ self._print_error(f"Invalid level: {level}. Valid levels: {', '.join(valid_levels)}")
126
+ return {"error": f"Invalid level: {level}"}
127
+
128
+ # Get token allocation for level
129
+ token_map = {
130
+ "minimal": 2000,
131
+ "low": 4000,
132
+ "medium": 8000,
133
+ "high": 16000,
134
+ "maximum": 32000
135
+ }
136
+
137
+ config = self._load_config()
138
+ config["level"] = level
139
+ config["max_tokens"] = token_map[level]
140
+ self._save_config(config)
141
+
142
+ result = {
143
+ "level": level,
144
+ "max_tokens": token_map[level],
145
+ "message": f"Thinking budget set to {level} ({token_map[level]} tokens)"
146
+ }
147
+
148
+ self._print_success(result["message"])
149
+ return result
150
+
151
+ def _print_error(self, message: str):
152
+ """Print error message."""
153
+ try:
154
+ from rich.console import Console
155
+ Console().print(f"[red]Error: {message}[/red]")
156
+ except ImportError:
157
+ print(f"Error: {message}")
158
+
159
+ def _print_success(self, message: str):
160
+ """Print success message."""
161
+ try:
162
+ from rich.console import Console
163
+ Console().print(f"[green]āœ“ {message}[/green]")
164
+ except ImportError:
165
+ print(f"āœ“ {message}")
166
+
167
+ def stats(self) -> Dict[str, Any]:
168
+ """
169
+ Show thinking usage statistics.
170
+
171
+ Returns:
172
+ Usage statistics
173
+ """
174
+ config = self._load_config()
175
+ stats = config.get("stats", {})
176
+
177
+ result = {
178
+ "session_count": stats.get("session_count", 0),
179
+ "total_tokens_used": stats.get("total_tokens_used", 0),
180
+ "total_time_seconds": stats.get("total_time_seconds", 0.0),
181
+ "average_tokens_per_session": stats.get("average_tokens_per_session", 0.0),
182
+ "average_utilization": stats.get("average_utilization", 0.0),
183
+ "over_budget_count": stats.get("over_budget_count", 0)
184
+ }
185
+
186
+ self._print_stats(result)
187
+ return result
188
+
189
+ def _print_stats(self, stats: Dict[str, Any]):
190
+ """Print statistics in formatted output."""
191
+ try:
192
+ from rich.console import Console
193
+ from rich.table import Table
194
+ from rich.panel import Panel
195
+
196
+ console = Console()
197
+
198
+ if stats["session_count"] == 0:
199
+ console.print("[yellow]No thinking sessions recorded yet.[/yellow]")
200
+ return
201
+
202
+ table = Table(show_header=False, box=None)
203
+ table.add_column("Metric", style="cyan")
204
+ table.add_column("Value", style="green")
205
+
206
+ table.add_row("Sessions", str(stats["session_count"]))
207
+ table.add_row("Total Tokens Used", f"{stats['total_tokens_used']:,}")
208
+ table.add_row("Total Time", f"{stats['total_time_seconds']:.1f}s")
209
+ table.add_row("Avg Tokens/Session", f"{stats['average_tokens_per_session']:.0f}")
210
+ table.add_row("Avg Utilization", f"{stats['average_utilization']:.1%}")
211
+ table.add_row("Over Budget", str(stats["over_budget_count"]))
212
+
213
+ console.print(Panel(table, title="Thinking Usage Statistics", border_style="blue"))
214
+
215
+ except ImportError:
216
+ print("Thinking Usage Statistics:")
217
+ print(f" Sessions: {stats['session_count']}")
218
+ print(f" Total Tokens Used: {stats['total_tokens_used']:,}")
219
+ print(f" Total Time: {stats['total_time_seconds']:.1f}s")
220
+ print(f" Avg Tokens/Session: {stats['average_tokens_per_session']:.0f}")
221
+ print(f" Avg Utilization: {stats['average_utilization']:.1%}")
222
+ print(f" Over Budget: {stats['over_budget_count']}")
223
+
224
+
225
+ def handle_thinking_command(args: list) -> int:
226
+ """
227
+ Handle thinking CLI commands.
228
+
229
+ Args:
230
+ args: Command arguments
231
+
232
+ Returns:
233
+ Exit code (0 for success)
234
+ """
235
+ if not args:
236
+ args = ["status"]
237
+
238
+ command = args[0].lower()
239
+ handler = ThinkingHandler()
240
+
241
+ if command == "status":
242
+ handler.status()
243
+ return 0
244
+
245
+ elif command == "set":
246
+ if len(args) < 2:
247
+ handler._print_error("Usage: praisonai thinking set <level>")
248
+ print("Levels: minimal, low, medium, high, maximum")
249
+ return 1
250
+ result = handler.set_level(args[1])
251
+ return 0 if "error" not in result else 1
252
+
253
+ elif command == "stats":
254
+ handler.stats()
255
+ return 0
256
+
257
+ elif command == "help":
258
+ _print_help()
259
+ return 0
260
+
261
+ else:
262
+ handler._print_error(f"Unknown command: {command}")
263
+ _print_help()
264
+ return 1
265
+
266
+
267
+ def _print_help():
268
+ """Print help message."""
269
+ try:
270
+ from rich.console import Console
271
+ from rich.panel import Panel
272
+
273
+ console = Console()
274
+ help_text = """
275
+ [bold]Thinking Budget Commands[/bold]
276
+
277
+ [cyan]praisonai thinking status[/cyan]
278
+ Show current thinking budget settings
279
+
280
+ [cyan]praisonai thinking set <level>[/cyan]
281
+ Set budget level (minimal, low, medium, high, maximum)
282
+
283
+ Levels:
284
+ • minimal - 2,000 tokens
285
+ • low - 4,000 tokens
286
+ • medium - 8,000 tokens (default)
287
+ • high - 16,000 tokens
288
+ • maximum - 32,000 tokens
289
+
290
+ [cyan]praisonai thinking stats[/cyan]
291
+ Show usage statistics
292
+
293
+ [cyan]praisonai thinking help[/cyan]
294
+ Show this help message
295
+ """
296
+ console.print(Panel(help_text, title="Thinking Budget Help", border_style="blue"))
297
+
298
+ except ImportError:
299
+ print("Thinking Budget Commands:")
300
+ print(" praisonai thinking status - Show current settings")
301
+ print(" praisonai thinking set <level> - Set budget level")
302
+ print(" praisonai thinking stats - Show usage statistics")
303
+ print(" praisonai thinking help - Show this help")
304
+ print("")
305
+ print("Levels: minimal (2K), low (4K), medium (8K), high (16K), maximum (32K)")
@@ -0,0 +1,334 @@
1
+ """
2
+ Todo Handler for CLI.
3
+
4
+ Provides todo list management.
5
+ Usage: praisonai todo list
6
+ praisonai todo add "New task"
7
+ praisonai "Plan project" --todo
8
+ """
9
+
10
+ import os
11
+ import json
12
+ from typing import Any, Dict, List
13
+ from .base import CommandHandler, FlagHandler
14
+
15
+
16
+ class TodoHandler(CommandHandler, FlagHandler):
17
+ """
18
+ Handler for todo command and --todo flag.
19
+
20
+ Manages todo lists for task planning.
21
+
22
+ Example:
23
+ praisonai todo list
24
+ praisonai todo add "Implement feature X"
25
+ praisonai todo complete 1
26
+ praisonai "Plan project" --todo
27
+ """
28
+
29
+ def __init__(self, verbose: bool = False, workspace: str = None):
30
+ CommandHandler.__init__(self, verbose)
31
+ self.workspace = workspace or os.path.join(os.path.expanduser("~"), ".praison")
32
+ self.todo_file = os.path.join(self.workspace, "todos.json")
33
+ os.makedirs(self.workspace, exist_ok=True)
34
+ self._todos = None
35
+
36
+ @property
37
+ def feature_name(self) -> str:
38
+ return "todo"
39
+
40
+ @property
41
+ def flag_name(self) -> str:
42
+ return "todo"
43
+
44
+ @property
45
+ def flag_help(self) -> str:
46
+ return "Generate todo list from task"
47
+
48
+ def get_actions(self) -> List[str]:
49
+ return ["list", "add", "complete", "delete", "clear", "help"]
50
+
51
+ def get_help_text(self) -> str:
52
+ return """
53
+ Todo Commands:
54
+ praisonai todo list - List all todos
55
+ praisonai todo add <task> - Add a new todo
56
+ praisonai todo complete <id> - Mark todo as complete
57
+ praisonai todo delete <id> - Delete a todo
58
+ praisonai todo clear - Clear all todos
59
+
60
+ Flag Usage:
61
+ praisonai "Plan project" --todo - Generate todos from task
62
+ """
63
+
64
+ def _load_todos(self) -> List[Dict[str, Any]]:
65
+ """Load todos from file."""
66
+ if self._todos is not None:
67
+ return self._todos
68
+
69
+ if os.path.exists(self.todo_file):
70
+ try:
71
+ with open(self.todo_file, 'r') as f:
72
+ self._todos = json.load(f)
73
+ except Exception:
74
+ self._todos = []
75
+ else:
76
+ self._todos = []
77
+
78
+ return self._todos
79
+
80
+ def _save_todos(self):
81
+ """Save todos to file."""
82
+ try:
83
+ with open(self.todo_file, 'w') as f:
84
+ json.dump(self._todos or [], f, indent=2)
85
+ except Exception as e:
86
+ self.log(f"Failed to save todos: {e}", "error")
87
+
88
+ def action_list(self, args: List[str], **kwargs) -> List[Dict[str, Any]]:
89
+ """
90
+ List all todos.
91
+
92
+ Returns:
93
+ List of todo items
94
+ """
95
+ todos = self._load_todos()
96
+
97
+ if not todos:
98
+ self.print_status("šŸ“‹ No todos found", "info")
99
+ return []
100
+
101
+ self.print_status("\nšŸ“‹ Todo List:", "info")
102
+ self.print_status("-" * 50, "info")
103
+
104
+ for i, todo in enumerate(todos, 1):
105
+ status = "āœ…" if todo.get('completed') else "⬜"
106
+ task = todo.get('task', 'Unknown')
107
+ priority = todo.get('priority', 'medium')
108
+
109
+ priority_color = {
110
+ 'high': 'šŸ”“',
111
+ 'medium': '🟔',
112
+ 'low': '🟢'
113
+ }.get(priority, '⚪')
114
+
115
+ self.print_status(f" {i}. {status} {priority_color} {task}", "info")
116
+
117
+ self.print_status("-" * 50, "info")
118
+ completed = sum(1 for t in todos if t.get('completed'))
119
+ self.print_status(f" {completed}/{len(todos)} completed", "info")
120
+
121
+ return todos
122
+
123
+ def action_add(self, args: List[str], **kwargs) -> Dict[str, Any]:
124
+ """
125
+ Add a new todo.
126
+
127
+ Args:
128
+ args: List containing task description
129
+
130
+ Returns:
131
+ Created todo item
132
+ """
133
+ if not args:
134
+ self.print_status("Usage: praisonai todo add <task>", "error")
135
+ return {}
136
+
137
+ task = ' '.join(args)
138
+ priority = kwargs.get('priority', 'medium')
139
+
140
+ todos = self._load_todos()
141
+
142
+ todo = {
143
+ 'id': len(todos) + 1,
144
+ 'task': task,
145
+ 'completed': False,
146
+ 'priority': priority,
147
+ 'created_at': self._get_timestamp()
148
+ }
149
+
150
+ todos.append(todo)
151
+ self._todos = todos
152
+ self._save_todos()
153
+
154
+ self.print_status(f"āœ… Added: {task}", "success")
155
+ return todo
156
+
157
+ def action_complete(self, args: List[str], **kwargs) -> bool:
158
+ """
159
+ Mark a todo as complete.
160
+
161
+ Args:
162
+ args: List containing todo ID
163
+
164
+ Returns:
165
+ True if successful
166
+ """
167
+ if not args:
168
+ self.print_status("Usage: praisonai todo complete <id>", "error")
169
+ return False
170
+
171
+ try:
172
+ todo_id = int(args[0])
173
+ except ValueError:
174
+ self.print_status("Invalid todo ID", "error")
175
+ return False
176
+
177
+ todos = self._load_todos()
178
+
179
+ if todo_id < 1 or todo_id > len(todos):
180
+ self.print_status(f"Todo {todo_id} not found", "error")
181
+ return False
182
+
183
+ todos[todo_id - 1]['completed'] = True
184
+ todos[todo_id - 1]['completed_at'] = self._get_timestamp()
185
+ self._todos = todos
186
+ self._save_todos()
187
+
188
+ self.print_status(f"āœ… Completed: {todos[todo_id - 1]['task']}", "success")
189
+ return True
190
+
191
+ def action_delete(self, args: List[str], **kwargs) -> bool:
192
+ """
193
+ Delete a todo.
194
+
195
+ Args:
196
+ args: List containing todo ID
197
+
198
+ Returns:
199
+ True if successful
200
+ """
201
+ if not args:
202
+ self.print_status("Usage: praisonai todo delete <id>", "error")
203
+ return False
204
+
205
+ try:
206
+ todo_id = int(args[0])
207
+ except ValueError:
208
+ self.print_status("Invalid todo ID", "error")
209
+ return False
210
+
211
+ todos = self._load_todos()
212
+
213
+ if todo_id < 1 or todo_id > len(todos):
214
+ self.print_status(f"Todo {todo_id} not found", "error")
215
+ return False
216
+
217
+ deleted = todos.pop(todo_id - 1)
218
+ self._todos = todos
219
+ self._save_todos()
220
+
221
+ self.print_status(f"šŸ—‘ļø Deleted: {deleted['task']}", "success")
222
+ return True
223
+
224
+ def action_clear(self, args: List[str], **kwargs) -> bool:
225
+ """
226
+ Clear all todos.
227
+
228
+ Returns:
229
+ True if successful
230
+ """
231
+ self._todos = []
232
+ self._save_todos()
233
+ self.print_status("šŸ—‘ļø All todos cleared", "success")
234
+ return True
235
+
236
+ def _get_timestamp(self) -> str:
237
+ """Get current timestamp."""
238
+ from datetime import datetime
239
+ return datetime.now().isoformat()
240
+
241
+ def apply_to_agent_config(self, config: Dict[str, Any], flag_value: Any) -> Dict[str, Any]:
242
+ """
243
+ Apply todo configuration.
244
+
245
+ Args:
246
+ config: Agent configuration dictionary
247
+ flag_value: Boolean indicating todo generation
248
+
249
+ Returns:
250
+ Modified configuration
251
+ """
252
+ if flag_value:
253
+ config['generate_todos'] = True
254
+ return config
255
+
256
+ def generate_todos_from_response(self, response: str) -> List[Dict[str, Any]]:
257
+ """
258
+ Extract todos from agent response.
259
+
260
+ Args:
261
+ response: Agent response text
262
+
263
+ Returns:
264
+ List of extracted todos
265
+ """
266
+ # Simple extraction - look for numbered lists or bullet points
267
+ import re
268
+
269
+ todos = []
270
+ lines = response.split('\n')
271
+
272
+ for line in lines:
273
+ line = line.strip()
274
+ # Match numbered lists (1. Task, 1) Task)
275
+ match = re.match(r'^[\d]+[\.\)]\s*(.+)$', line)
276
+ if match:
277
+ task = match.group(1).strip()
278
+ if task and len(task) > 3:
279
+ todos.append({
280
+ 'task': task,
281
+ 'completed': False,
282
+ 'priority': 'medium'
283
+ })
284
+ # Match bullet points (- Task, * Task, • Task)
285
+ elif line.startswith(('-', '*', '•', '→')):
286
+ task = line[1:].strip()
287
+ if task and len(task) > 3:
288
+ todos.append({
289
+ 'task': task,
290
+ 'completed': False,
291
+ 'priority': 'medium'
292
+ })
293
+
294
+ return todos
295
+
296
+ def post_process_result(self, result: Any, flag_value: Any) -> Any:
297
+ """
298
+ Post-process result to extract todos.
299
+
300
+ Args:
301
+ result: Agent output
302
+ flag_value: Boolean indicating todo generation
303
+
304
+ Returns:
305
+ Original result (todos are saved)
306
+ """
307
+ if not flag_value:
308
+ return result
309
+
310
+ extracted = self.generate_todos_from_response(str(result))
311
+
312
+ if extracted:
313
+ todos = self._load_todos()
314
+ for todo in extracted:
315
+ todo['id'] = len(todos) + 1
316
+ todo['created_at'] = self._get_timestamp()
317
+ todos.append(todo)
318
+
319
+ self._todos = todos
320
+ self._save_todos()
321
+
322
+ self.print_status(f"\nšŸ“‹ Generated {len(extracted)} todos:", "success")
323
+ for todo in extracted:
324
+ self.print_status(f" • {todo['task']}", "info")
325
+
326
+ return result
327
+
328
+ def execute(self, action: str = None, action_args: List[str] = None, **kwargs) -> Any:
329
+ """Execute todo command action."""
330
+ if action is None:
331
+ action = "list"
332
+ if action_args is None:
333
+ action_args = []
334
+ return CommandHandler.execute(self, action, action_args, **kwargs)