praisonai-code 0.0.44__tar.gz → 0.0.45__tar.gz

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 (313) hide show
  1. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/PKG-INFO +1 -1
  2. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/__init__.py +1 -1
  3. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/app.py +22 -1
  4. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/commands/init.py +27 -0
  5. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/commands/run.py +99 -0
  6. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/commands/session.py +9 -2
  7. praisonai_code-0.0.45/praisonai_code/cli/commands/uninstall.py +73 -0
  8. praisonai_code-0.0.45/praisonai_code/cli/commands/upgrade.py +105 -0
  9. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/configuration/config.schema.json +36 -1
  10. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/configuration/resolver.py +366 -21
  11. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/custom_definitions.py +259 -4
  12. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/interactive_tools.py +147 -1
  13. praisonai_code-0.0.45/praisonai_code/cli/features/self_manage.py +310 -0
  14. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/help_categories.py +2 -0
  15. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/state/project_sessions.py +48 -2
  16. praisonai_code-0.0.45/praisonai_code/cli/utils/project.py +338 -0
  17. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/tool_resolver.py +32 -5
  18. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code.egg-info/PKG-INFO +1 -1
  19. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code.egg-info/SOURCES.txt +3 -0
  20. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/pyproject.toml +1 -1
  21. praisonai_code-0.0.44/praisonai_code/cli/utils/project.py +0 -131
  22. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/README.md +0 -0
  23. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/__main__.py +0 -0
  24. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/_bot_bridge.py +0 -0
  25. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/_framework_availability.py +0 -0
  26. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/_logging.py +0 -0
  27. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/_registry.py +0 -0
  28. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/_safe_loader.py +0 -0
  29. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/_version.py +0 -0
  30. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/_wrapper_bridge.py +0 -0
  31. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/__init__.py +0 -0
  32. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/_forward_shim.py +0 -0
  33. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/_paths.py +0 -0
  34. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/_warnings.py +0 -0
  35. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/_wrapper_reexport.py +0 -0
  36. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/approval_backend.py +0 -0
  37. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/branding.py +0 -0
  38. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/commands/__init__.py +0 -0
  39. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/commands/acp.py +0 -0
  40. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/commands/agent.py +0 -0
  41. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/commands/agents.py +0 -0
  42. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/commands/attach.py +0 -0
  43. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/commands/auth.py +0 -0
  44. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/commands/benchmark.py +0 -0
  45. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/commands/browser.py +0 -0
  46. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/commands/call.py +0 -0
  47. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/commands/chat.py +0 -0
  48. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/commands/checkpoint.py +0 -0
  49. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/commands/code.py +0 -0
  50. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/commands/command.py +0 -0
  51. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/commands/commit.py +0 -0
  52. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/commands/completion.py +0 -0
  53. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/commands/config.py +0 -0
  54. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/commands/daemon.py +0 -0
  55. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/commands/debug.py +0 -0
  56. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/commands/deploy.py +0 -0
  57. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/commands/diag.py +0 -0
  58. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/commands/doctor.py +0 -0
  59. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/commands/endpoints.py +0 -0
  60. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/commands/environment.py +0 -0
  61. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/commands/eval.py +0 -0
  62. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/commands/github.py +0 -0
  63. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/commands/hooks.py +0 -0
  64. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/commands/loop.py +0 -0
  65. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/commands/lsp.py +0 -0
  66. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/commands/memory.py +0 -0
  67. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/commands/models.py +0 -0
  68. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/commands/obs.py +0 -0
  69. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/commands/package.py +0 -0
  70. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/commands/paths.py +0 -0
  71. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/commands/permissions.py +0 -0
  72. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/commands/plugins.py +0 -0
  73. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/commands/port.py +0 -0
  74. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/commands/publish.py +0 -0
  75. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/commands/registry.py +0 -0
  76. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/commands/research.py +0 -0
  77. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/commands/retrieval.py +0 -0
  78. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/commands/rules.py +0 -0
  79. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/commands/sandbox.py +0 -0
  80. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/commands/serve.py +0 -0
  81. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/commands/setup.py +0 -0
  82. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/commands/skills.py +0 -0
  83. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/commands/templates.py +0 -0
  84. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/commands/test.py +0 -0
  85. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/commands/todo.py +0 -0
  86. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/commands/tools.py +0 -0
  87. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/commands/traces.py +0 -0
  88. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/commands/tracker.py +0 -0
  89. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/commands/ui.py +0 -0
  90. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/commands/up.py +0 -0
  91. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/commands/version.py +0 -0
  92. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/commands/workflow.py +0 -0
  93. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/config_loader.py +0 -0
  94. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/configuration/__init__.py +0 -0
  95. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/configuration/credentials.py +0 -0
  96. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/configuration/loader.py +0 -0
  97. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/configuration/model_resolver.py +0 -0
  98. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/configuration/oauth.py +0 -0
  99. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/configuration/paths.py +0 -0
  100. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/configuration/schema.py +0 -0
  101. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/execution/__init__.py +0 -0
  102. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/execution/core.py +0 -0
  103. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/execution/profiler.py +0 -0
  104. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/execution/request.py +0 -0
  105. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/execution/result.py +0 -0
  106. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/fallback_schema.py +0 -0
  107. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/__init__.py +0 -0
  108. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/_approval_bridge.py +0 -0
  109. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/_endpoint_registry.py +0 -0
  110. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/_search_registry.py +0 -0
  111. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/action_orchestrator.py +0 -0
  112. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/agents.py +0 -0
  113. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/at_mentions.py +0 -0
  114. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/audit_cli.py +0 -0
  115. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/auto_memory.py +0 -0
  116. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/auto_mode.py +0 -0
  117. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/autonomy_mode.py +0 -0
  118. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/base.py +0 -0
  119. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/benchmark.py +0 -0
  120. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/capabilities.py +0 -0
  121. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/checkpoints.py +0 -0
  122. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/cli_profiler.py +0 -0
  123. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/code_intelligence.py +0 -0
  124. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/compaction.py +0 -0
  125. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/compare.py +0 -0
  126. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/config_hierarchy.py +0 -0
  127. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/context_manager.py +0 -0
  128. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/cost_tracker.py +0 -0
  129. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/csv_test_runner.py +0 -0
  130. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/debug.py +0 -0
  131. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/diag.py +0 -0
  132. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/display_jsonl.py +0 -0
  133. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/doctor/__init__.py +0 -0
  134. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/doctor/checks/__init__.py +0 -0
  135. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/doctor/checks/_wrapper_checks.py +0 -0
  136. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/doctor/checks/acp_checks.py +0 -0
  137. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/doctor/checks/bot_checks.py +0 -0
  138. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/doctor/checks/config_checks.py +0 -0
  139. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/doctor/checks/db_checks.py +0 -0
  140. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/doctor/checks/env_checks.py +0 -0
  141. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/doctor/checks/gateway_checks.py +0 -0
  142. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/doctor/checks/lsp_checks.py +0 -0
  143. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/doctor/checks/mcp_checks.py +0 -0
  144. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/doctor/checks/memory_checks.py +0 -0
  145. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/doctor/checks/network_checks.py +0 -0
  146. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/doctor/checks/obs_checks.py +0 -0
  147. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/doctor/checks/packaging_checks.py +0 -0
  148. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/doctor/checks/performance_checks.py +0 -0
  149. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/doctor/checks/permissions_checks.py +0 -0
  150. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/doctor/checks/runtime_checks.py +0 -0
  151. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/doctor/checks/runtime_migration_checks.py +0 -0
  152. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/doctor/checks/selftest_checks.py +0 -0
  153. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/doctor/checks/serve_checks.py +0 -0
  154. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/doctor/checks/skills_checks.py +0 -0
  155. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/doctor/checks/tools_checks.py +0 -0
  156. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/doctor/engine.py +0 -0
  157. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/doctor/formatters.py +0 -0
  158. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/doctor/handler.py +0 -0
  159. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/doctor/models.py +0 -0
  160. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/doctor/registry.py +0 -0
  161. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/endpoints.py +0 -0
  162. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/examples.py +0 -0
  163. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/external_agents.py +0 -0
  164. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/fast_context.py +0 -0
  165. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/file_history.py +0 -0
  166. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/flow_display.py +0 -0
  167. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/git_attribution.py +0 -0
  168. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/git_integration.py +0 -0
  169. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/guardrail.py +0 -0
  170. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/handoff.py +0 -0
  171. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/hooks.py +0 -0
  172. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/hybrid_workflow.py +0 -0
  173. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/image.py +0 -0
  174. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/interactive_core_headless.py +0 -0
  175. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/interactive_runtime.py +0 -0
  176. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/interactive_test_harness.py +0 -0
  177. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/interactive_tui.py +0 -0
  178. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/job_workflow.py +0 -0
  179. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/jobs.py +0 -0
  180. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/knowledge.py +0 -0
  181. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/knowledge_cli.py +0 -0
  182. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/lite.py +0 -0
  183. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/logs.py +0 -0
  184. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/lsp_cli.py +0 -0
  185. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/lsp_diagnostics.py +0 -0
  186. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/mcp.py +0 -0
  187. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/message_queue.py +0 -0
  188. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/metrics.py +0 -0
  189. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/migrate.py +0 -0
  190. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/migration_flow.py +0 -0
  191. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/migration_spec.py +0 -0
  192. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/n8n.py +0 -0
  193. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/observability.py +0 -0
  194. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/output_modes.py +0 -0
  195. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/output_style.py +0 -0
  196. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/package.py +0 -0
  197. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/performance.py +0 -0
  198. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/profiler/__init__.py +0 -0
  199. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/profiler/core.py +0 -0
  200. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/profiler/optimizations.py +0 -0
  201. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/profiler/suite.py +0 -0
  202. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/queue/__init__.py +0 -0
  203. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/queue/manager.py +0 -0
  204. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/queue/models.py +0 -0
  205. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/queue/persistence.py +0 -0
  206. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/queue/scheduler.py +0 -0
  207. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/queue/worker.py +0 -0
  208. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/recipe_creator.py +0 -0
  209. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/recipe_prompts.py +0 -0
  210. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/registry.py +0 -0
  211. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/repo_map.py +0 -0
  212. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/router.py +0 -0
  213. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/safe_shell.py +0 -0
  214. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/sandbox_executor.py +0 -0
  215. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/sdk_knowledge.py +0 -0
  216. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/session.py +0 -0
  217. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/session_checkpoints.py +0 -0
  218. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/setup/__init__.py +0 -0
  219. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/setup/handler.py +0 -0
  220. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/setup/templates.py +0 -0
  221. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/skills.py +0 -0
  222. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/slash_commands.py +0 -0
  223. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/telemetry.py +0 -0
  224. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/thinking.py +0 -0
  225. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/todo.py +0 -0
  226. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/tools.py +0 -0
  227. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/tui/__init__.py +0 -0
  228. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/tui/cli.py +0 -0
  229. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/tui/config.py +0 -0
  230. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/tui/debug.py +0 -0
  231. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/tui/events.py +0 -0
  232. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/tui/mock_provider.py +0 -0
  233. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/tui/orchestrator.py +0 -0
  234. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/tui/screens/__init__.py +0 -0
  235. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/tui/screens/help.py +0 -0
  236. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/tui/screens/main.py +0 -0
  237. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/tui/screens/queue.py +0 -0
  238. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/tui/screens/session.py +0 -0
  239. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/tui/screens/settings.py +0 -0
  240. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/tui/session_store.py +0 -0
  241. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/tui/widgets/__init__.py +0 -0
  242. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/tui/widgets/chat.py +0 -0
  243. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/tui/widgets/command_popup.py +0 -0
  244. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/tui/widgets/composer.py +0 -0
  245. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/tui/widgets/file_popup.py +0 -0
  246. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/tui/widgets/queue_panel.py +0 -0
  247. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/tui/widgets/status.py +0 -0
  248. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/tui/widgets/tool_panel.py +0 -0
  249. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/wizard.py +0 -0
  250. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/workflow.py +0 -0
  251. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/features/yaml_utils.py +0 -0
  252. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/interactive/__init__.py +0 -0
  253. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/interactive/async_tui.py +0 -0
  254. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/interactive/command_registry.py +0 -0
  255. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/interactive/config.py +0 -0
  256. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/interactive/core.py +0 -0
  257. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/interactive/events.py +0 -0
  258. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/interactive/frontends/__init__.py +0 -0
  259. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/interactive/frontends/rich_frontend.py +0 -0
  260. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/interactive/frontends/textual_frontend.py +0 -0
  261. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/interactive/praison_io.py +0 -0
  262. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/interactive/repl.py +0 -0
  263. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/interactive/split_tui.py +0 -0
  264. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/interactive/tui_app.py +0 -0
  265. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/legacy/__init__.py +0 -0
  266. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/legacy/env_security.py +0 -0
  267. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/legacy/praison_ai.py +0 -0
  268. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/legacy/prompt_dispatch.py +0 -0
  269. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/main.py +0 -0
  270. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/output/__init__.py +0 -0
  271. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/output/console.py +0 -0
  272. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/output/event_bridge.py +0 -0
  273. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/schedule_cli.py +0 -0
  274. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/schema_provider.py +0 -0
  275. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/session/__init__.py +0 -0
  276. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/session/resume.py +0 -0
  277. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/session/unified.py +0 -0
  278. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/state/__init__.py +0 -0
  279. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/state/identifiers.py +0 -0
  280. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/state/sessions.py +0 -0
  281. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/ui/__init__.py +0 -0
  282. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/ui/config.py +0 -0
  283. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/ui/events.py +0 -0
  284. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/ui/mg_backend.py +0 -0
  285. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/ui/plain.py +0 -0
  286. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/ui/rich_backend.py +0 -0
  287. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/unified_schema.py +0 -0
  288. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/utils/env_utils.py +0 -0
  289. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli/utils/stdin.py +0 -0
  290. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli_backends/__init__.py +0 -0
  291. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli_backends/claude.py +0 -0
  292. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/cli_backends/registry.py +0 -0
  293. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/data/__init__.py +0 -0
  294. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/data/fixtures/interactive/multi_agent.csv +0 -0
  295. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/data/fixtures/interactive/refactor.csv +0 -0
  296. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/data/fixtures/interactive/smoke.csv +0 -0
  297. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/data/fixtures/interactive/tools.csv +0 -0
  298. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/llm/__init__.py +0 -0
  299. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/llm/catalogue.py +0 -0
  300. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/llm/config.py +0 -0
  301. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/llm/credentials.py +0 -0
  302. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/llm/env.py +0 -0
  303. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/runtime/__init__.py +0 -0
  304. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/runtime/__main__.py +0 -0
  305. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/runtime/client.py +0 -0
  306. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/runtime/descriptor.py +0 -0
  307. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/runtime/server.py +0 -0
  308. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code/tool_registry.py +0 -0
  309. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code.egg-info/dependency_links.txt +0 -0
  310. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code.egg-info/entry_points.txt +0 -0
  311. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code.egg-info/requires.txt +0 -0
  312. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/praisonai_code.egg-info/top_level.txt +0 -0
  313. {praisonai_code-0.0.44 → praisonai_code-0.0.45}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: praisonai-code
3
- Version: 0.0.44
3
+ Version: 0.0.45
4
4
  Summary: Agentic terminal CLI for PraisonAI — the terminal-native agent (run, chat, code, runtime, cli backends) extracted from the praisonai wrapper.
5
5
  Author: Mervin Praison
6
6
  License: MIT
@@ -12,6 +12,6 @@ the remaining terminal-agent modules, with PEP 562 shims left behind at the
12
12
  old ``praisonai.*`` paths for backward compatibility.
13
13
  """
14
14
 
15
- __version__ = "0.0.44"
15
+ __version__ = "0.0.45"
16
16
 
17
17
  __all__ = ["__version__"]
@@ -149,6 +149,8 @@ _LAZY_COMMANDS: Dict[str, Tuple[str, str, str]] = {
149
149
  "session": (".commands.session", "app", "Session management"),
150
150
  "completion": (".commands.completion", "app", "Shell completion scripts"),
151
151
  "version": (".commands.version", "app", "Version information"),
152
+ "upgrade": (".commands.upgrade", "app", "Update the managed PraisonAI CLI install"),
153
+ "uninstall": (".commands.uninstall", "app", "Remove the managed PraisonAI CLI install"),
152
154
  "debug": (".commands.debug", "app", "Debug and test interactive flows"),
153
155
  "lsp": (".commands.lsp", "app", "LSP service lifecycle"),
154
156
  "diag": (".commands.diag", "app", "Diagnostics export"),
@@ -787,7 +789,26 @@ def main_callback(
787
789
  trace_id=context.trace_id,
788
790
  )
789
791
  set_output_controller(state.output_controller)
790
-
792
+
793
+ # Non-blocking "update available" hint from the cached background check.
794
+ # Text-mode only, opt-out via PRAISONAI_NO_UPDATE_CHECK; never blocks or
795
+ # raises (only reads a time-boxed cache, never performs network I/O here).
796
+ if mode == OutputMode.TEXT and not state.quiet:
797
+ try:
798
+ from .features.self_manage import (
799
+ maybe_schedule_update_check,
800
+ read_cached_hint,
801
+ )
802
+
803
+ hint = read_cached_hint()
804
+ if hint:
805
+ typer.echo(hint, err=True)
806
+ # Warm the cache in a detached child for the next invocation. Never
807
+ # performs network I/O here and never blocks or raises.
808
+ maybe_schedule_update_check()
809
+ except Exception:
810
+ pass
811
+
791
812
  # If no command provided, start interactive mode
792
813
  if ctx.invoked_subcommand is None:
793
814
  # Check for credentials before starting TUI
@@ -8,9 +8,12 @@ Project scaffolding command for the `.praisonai/` convention.
8
8
  config.yaml # sensible defaults (model, output mode)
9
9
  agents/assistant.md # working starter agent (frontmatter + body)
10
10
  commands/review.md # working starter command using $ARGUMENTS / @file
11
+ tools/example.py # commented @tool example, auto-discovered on run
11
12
 
12
13
  The scaffolded files are immediately discoverable and runnable via
13
14
  `praisonai run --agent assistant ...` and `praisonai run --command review ...`.
15
+ Tools dropped in `.praisonai/tools/*.py` are auto-loaded on every `run`
16
+ (gated by PRAISONAI_ALLOW_LOCAL_TOOLS).
14
17
  """
15
18
 
16
19
  from pathlib import Path
@@ -62,6 +65,29 @@ If a file path is provided, here are its contents:
62
65
  @$ARGUMENTS
63
66
  """
64
67
 
68
+ STARTER_TOOL_PY = '''\
69
+ """Project-local tools for this .praisonai/ project.
70
+
71
+ Every public callable in this directory is auto-discovered and made available
72
+ to the agent on `praisonai run` — no --tools flag required. Decorate a function
73
+ with @tool for a rich schema, or just define a plain function.
74
+
75
+ Loading executes this file, so it is gated by the PRAISONAI_ALLOW_LOCAL_TOOLS
76
+ opt-in (set PRAISONAI_ALLOW_LOCAL_TOOLS=true to enable local tool loading).
77
+ Uncomment the example below to try it:
78
+
79
+ praisonai run "use the greet tool to greet Ada"
80
+ """
81
+
82
+ # from praisonaiagents import tool
83
+ #
84
+ #
85
+ # @tool
86
+ # def greet(name: str) -> str:
87
+ # """Return a friendly greeting for the given name."""
88
+ # return f"Hello, {name}!"
89
+ '''
90
+
65
91
 
66
92
  def _any_provider_credential() -> bool:
67
93
  """Return True if any supported provider credential is present in env."""
@@ -136,6 +162,7 @@ def init(
136
162
  (base / "config.yaml", STARTER_CONFIG.format(model=scaffold_model)),
137
163
  (base / "agents" / "assistant.md", STARTER_AGENT_MD.format(model=scaffold_model)),
138
164
  (base / "commands" / "review.md", STARTER_COMMAND_MD),
165
+ (base / "tools" / "example.py", STARTER_TOOL_PY),
139
166
  ]
140
167
 
141
168
  written = []
@@ -333,6 +333,49 @@ def _resolve_tools_arg(value: Optional[str], verbose: bool = False) -> list:
333
333
  return resolved
334
334
 
335
335
 
336
+ def _auto_discover_project_tools(existing: list, verbose: bool = False) -> list:
337
+ """Return auto-discovered ``.praisonai/tools/*.py`` callables to append.
338
+
339
+ Mirrors the agents/commands convention: project-local tools are loaded from
340
+ ``.praisonai/tools/`` (user-global + project walk-up) with no ``--tools``
341
+ flag. Loading executes user code and is gated by the shared
342
+ ``PRAISONAI_ALLOW_LOCAL_TOOLS`` opt-in, so this returns an empty list when
343
+ the opt-in is not set.
344
+
345
+ Discovery is additive: explicit ``--tools`` items already in ``existing``
346
+ take precedence and are not re-added (dedup by callable identity).
347
+ """
348
+ try:
349
+ from praisonai_code.cli.features.custom_definitions import (
350
+ discover_project_tools,
351
+ )
352
+ except Exception:
353
+ return []
354
+
355
+ try:
356
+ discovered = discover_project_tools()
357
+ except Exception:
358
+ return []
359
+
360
+ if not discovered:
361
+ return []
362
+
363
+ seen = {id(t) for t in existing}
364
+ merged: list = []
365
+ for tool in discovered:
366
+ if id(tool) in seen:
367
+ continue
368
+ seen.add(id(tool))
369
+ merged.append(tool)
370
+
371
+ if merged and verbose:
372
+ from ..output import get_output_controller
373
+ get_output_controller().print_info(
374
+ f"Loaded {len(merged)} project tool(s) from .praisonai/tools/"
375
+ )
376
+ return merged
377
+
378
+
336
379
  def _permissions_from_config(config) -> Optional[dict]:
337
380
  """Convert a resolved ``permissions`` config section to a pattern->action dict.
338
381
 
@@ -613,6 +656,7 @@ def run_main(
613
656
  no_save: bool = typer.Option(False, "--no-save", help="Don't auto-save session after execution"),
614
657
  # Custom definitions
615
658
  agent: Optional[str] = typer.Option(None, "--agent", "-a", help="Use a named custom agent"),
659
+ subagents: Optional[str] = typer.Option(None, "--subagents", help="Comma-separated named agents (.praisonai/agents/*.md) the running agent may delegate to. Omit to expose agents marked 'mode: subagent'."),
616
660
  command: Optional[str] = typer.Option(None, "--command", help="Execute a named custom command"),
617
661
  # Reasoning effort
618
662
  thinking: Optional[str] = typer.Option(None, "--thinking", help="Reasoning effort (off, minimal, low, medium, high)"),
@@ -779,6 +823,7 @@ def run_main(
779
823
  fork=fork,
780
824
  no_save=no_save,
781
825
  thinking_budget=thinking_budget,
826
+ subagents=subagents,
782
827
  )
783
828
  return
784
829
 
@@ -1236,6 +1281,12 @@ def _run_prompt(
1236
1281
  toolset_names = [t.strip() for t in toolset.split(",") if t.strip()]
1237
1282
  if toolset_names:
1238
1283
  selected_tools.extend(_resolve_toolsets(toolset_names))
1284
+ # Auto-discover project-local .praisonai/tools/*.py (additive;
1285
+ # explicit --tools take precedence). Gated by the shared
1286
+ # PRAISONAI_ALLOW_LOCAL_TOOLS opt-in in the safe loader.
1287
+ selected_tools.extend(
1288
+ _auto_discover_project_tools(selected_tools, verbose=verbose)
1289
+ )
1239
1290
  if selected_tools:
1240
1291
  agent_config["tools"] = list(agent_config.get("tools", [])) + selected_tools
1241
1292
 
@@ -1482,6 +1533,46 @@ def _run_from_file_profiled(
1482
1533
  profiler.print_report()
1483
1534
 
1484
1535
 
1536
+ def _wire_subagent_delegation(
1537
+ agent_config: Dict[str, Any],
1538
+ subagents: Optional[str],
1539
+ ) -> None:
1540
+ """Attach a `spawn_subagent` tool that can delegate to named agents.
1541
+
1542
+ Resolves delegatable ``.praisonai/agents/*.md`` definitions into a
1543
+ core ``create_subagent_tool`` resolver and appends the tool to
1544
+ ``agent_config['tools']``. No-op when there are no delegatable agents so
1545
+ the default run is unchanged.
1546
+
1547
+ ``subagents`` is the raw ``--subagents`` string (comma-separated names);
1548
+ when None, agents marked ``mode: subagent`` are exposed instead.
1549
+ """
1550
+ allow_list = None
1551
+ if subagents:
1552
+ allow_list = [name.strip() for name in subagents.split(",") if name.strip()]
1553
+
1554
+ try:
1555
+ from praisonai_code.cli.features.custom_definitions import (
1556
+ build_subagent_resolver,
1557
+ )
1558
+
1559
+ resolver, descriptions = build_subagent_resolver(allow_list)
1560
+ except Exception:
1561
+ return
1562
+
1563
+ if resolver is None:
1564
+ return
1565
+
1566
+ from praisonaiagents.tools.subagent_tool import create_subagent_tool
1567
+
1568
+ tool = create_subagent_tool(
1569
+ agent_resolver=resolver,
1570
+ allowed_agents=list(descriptions.keys()),
1571
+ resolvable_agents=descriptions,
1572
+ )
1573
+ agent_config["tools"] = list(agent_config.get("tools") or []) + [tool]
1574
+
1575
+
1485
1576
  def _run_custom_agent(
1486
1577
  agent_config: Dict[str, Any],
1487
1578
  prompt: str,
@@ -1503,6 +1594,7 @@ def _run_custom_agent(
1503
1594
  fork: bool = False,
1504
1595
  no_save: bool = False,
1505
1596
  thinking_budget: Optional[int] = None,
1597
+ subagents: Optional[str] = None,
1506
1598
  ):
1507
1599
  """Run a custom agent definition."""
1508
1600
  output = get_output_controller()
@@ -1513,6 +1605,13 @@ def _run_custom_agent(
1513
1605
  # Override model if specified
1514
1606
  if model:
1515
1607
  agent_config["llm"] = model
1608
+
1609
+ # Offer discovered named agents as delegation targets. The primary
1610
+ # agent can then call spawn_subagent(agent_name="researcher", ...) to
1611
+ # hand a sub-task to a user-defined .praisonai/agents/*.md agent, which
1612
+ # runs under its own model/tools/permissions. An explicit --subagents
1613
+ # allow-list wins; otherwise agents marked `mode: subagent` are used.
1614
+ _wire_subagent_delegation(agent_config, subagents)
1516
1615
 
1517
1616
  # Add verbose flag
1518
1617
  if verbose:
@@ -76,7 +76,11 @@ def session_list(
76
76
  get_project_session_store,
77
77
  list_project_sessions,
78
78
  )
79
- from ..utils.project import get_project_id, get_project_name
79
+ from ..utils.project import (
80
+ get_project_id,
81
+ get_project_identity_source,
82
+ get_project_name,
83
+ )
80
84
 
81
85
  # List sessions for specific or current project. For the current
82
86
  # project, merge the project-scoped and global default stores so the
@@ -131,7 +135,10 @@ def session_list(
131
135
  if not project_id:
132
136
  current_project = get_project_name()
133
137
  current_id = get_project_id()
134
- output.print_info(f"Project: {current_project} (ID: {current_id})")
138
+ identity_source = get_project_identity_source()
139
+ output.print_info(
140
+ f"Project: {current_project} (ID: {current_id}, identity: {identity_source})"
141
+ )
135
142
 
136
143
  else:
137
144
  # Use global session manager
@@ -0,0 +1,73 @@
1
+ """``praisonai uninstall`` — cleanly remove the managed CLI install.
2
+
3
+ Removes the managed PraisonAI environment and global shim provisioned by the
4
+ one-line installer (``uv tool`` / ``pipx``), or uninstalls the ``pip`` package
5
+ for library installs. CLI self-management only; ``praisonaiagents`` is not
6
+ touched by this command.
7
+ """
8
+
9
+ import subprocess
10
+
11
+ import typer
12
+
13
+ from ..output.console import get_output_controller
14
+ from ..features.self_manage import detect_install, get_installed_version
15
+
16
+ app = typer.Typer(help="Remove the managed PraisonAI CLI install")
17
+
18
+
19
+ @app.callback(invoke_without_command=True)
20
+ def uninstall(
21
+ ctx: typer.Context,
22
+ yes: bool = typer.Option(
23
+ False,
24
+ "--yes",
25
+ "-y",
26
+ help="Skip the confirmation prompt (non-interactive/CI).",
27
+ ),
28
+ ):
29
+ """Remove the managed PraisonAI environment and global ``praisonai`` shim."""
30
+ if ctx.invoked_subcommand is not None:
31
+ return
32
+
33
+ output = get_output_controller()
34
+ info = detect_install()
35
+ current = get_installed_version()
36
+
37
+ if info.uninstall_cmd is None:
38
+ output.print_error(
39
+ f"Automatic uninstall is not supported for a '{info.manager}' install.\n"
40
+ "Remove manually with: pip uninstall praisonai"
41
+ )
42
+ raise typer.Exit(1)
43
+
44
+ if not yes and not output.is_json_mode:
45
+ confirmed = typer.confirm(
46
+ f"Remove PraisonAI {current} (installed via {info.manager})?"
47
+ )
48
+ if not confirmed:
49
+ output.print("Uninstall cancelled.")
50
+ raise typer.Exit(0)
51
+
52
+ if not output.is_json_mode:
53
+ output.print(
54
+ f"Uninstalling PraisonAI via {info.manager}: "
55
+ f"{' '.join(info.uninstall_cmd)}"
56
+ )
57
+
58
+ try:
59
+ result = subprocess.run(info.uninstall_cmd)
60
+ except Exception as e: # pragma: no cover - defensive
61
+ output.print_error(f"Uninstall failed: {e}")
62
+ raise typer.Exit(1)
63
+
64
+ if result.returncode != 0:
65
+ output.print_error(
66
+ f"Uninstall command exited with code {result.returncode}."
67
+ )
68
+ raise typer.Exit(result.returncode)
69
+
70
+ if output.is_json_mode:
71
+ output.print_json({"manager": info.manager, "removed": current})
72
+ else:
73
+ output.print_success(f"PraisonAI {current} removed.")
@@ -0,0 +1,105 @@
1
+ """``praisonai upgrade`` — self-update the managed CLI install.
2
+
3
+ Updates the PraisonAI CLI in place using whichever tool manager provisioned it
4
+ (``uv tool`` / ``pipx`` for the one-line installer, or ``pip`` for library
5
+ installs). ``--check`` reports whether a newer release exists without mutating
6
+ anything. This is CLI self-management only; ``praisonaiagents`` is untouched.
7
+ """
8
+
9
+ import subprocess
10
+
11
+ import typer
12
+
13
+ from ..output.console import get_output_controller
14
+ from ..features.self_manage import (
15
+ detect_install,
16
+ get_installed_version,
17
+ get_latest_version,
18
+ is_newer,
19
+ refresh_update_cache,
20
+ )
21
+
22
+ app = typer.Typer(help="Update the managed PraisonAI CLI install")
23
+
24
+
25
+ @app.callback(invoke_without_command=True)
26
+ def upgrade(
27
+ ctx: typer.Context,
28
+ check: bool = typer.Option(
29
+ False,
30
+ "--check",
31
+ help="Report whether a newer version exists without upgrading.",
32
+ ),
33
+ ):
34
+ """Update PraisonAI in place, or check for a newer release with ``--check``."""
35
+ if ctx.invoked_subcommand is not None:
36
+ return
37
+
38
+ output = get_output_controller()
39
+ current = get_installed_version()
40
+
41
+ if check:
42
+ latest = get_latest_version()
43
+ # Warm the background-hint cache so long-lived installs surface the
44
+ # notice on next start without their own network round-trip.
45
+ refresh_update_cache()
46
+ if latest is None:
47
+ if output.is_json_mode:
48
+ output.print_json(
49
+ {"current": current, "latest": None, "update_available": None,
50
+ "error": "Could not reach PyPI"}
51
+ )
52
+ else:
53
+ output.print_error("Could not check for updates (network error).")
54
+ output.print(f"Current version: {current}")
55
+ raise typer.Exit(1)
56
+
57
+ available = is_newer(latest, current)
58
+ if output.is_json_mode:
59
+ output.print_json(
60
+ {"current": current, "latest": latest, "update_available": available}
61
+ )
62
+ elif available:
63
+ output.print_warning(
64
+ f"Update available: {current} -> {latest}\nRun: praisonai upgrade"
65
+ )
66
+ else:
67
+ output.print_success(f"You are on the latest version ({current}).")
68
+ return
69
+
70
+ info = detect_install()
71
+ if info.upgrade_cmd is None:
72
+ output.print_error(
73
+ f"Automatic upgrade is not supported for a '{info.manager}' install.\n"
74
+ "Upgrade manually with: pip install --upgrade praisonai"
75
+ )
76
+ raise typer.Exit(1)
77
+
78
+ if not output.is_json_mode:
79
+ output.print(
80
+ f"Upgrading PraisonAI via {info.manager}: {' '.join(info.upgrade_cmd)}"
81
+ )
82
+
83
+ try:
84
+ result = subprocess.run(info.upgrade_cmd)
85
+ except Exception as e: # pragma: no cover - defensive
86
+ output.print_error(f"Upgrade failed: {e}")
87
+ raise typer.Exit(1)
88
+
89
+ if result.returncode != 0:
90
+ output.print_error(
91
+ f"Upgrade command exited with code {result.returncode}."
92
+ )
93
+ raise typer.Exit(result.returncode)
94
+
95
+ new_version = get_installed_version()
96
+ if output.is_json_mode:
97
+ output.print_json(
98
+ {"manager": info.manager, "previous": current, "current": new_version}
99
+ )
100
+ else:
101
+ output.print_success(
102
+ f"PraisonAI upgraded ({current} -> {new_version})."
103
+ if new_version != current
104
+ else f"PraisonAI is up to date ({new_version})."
105
+ )
@@ -52,6 +52,41 @@
52
52
  "quiet": { "type": "boolean" }
53
53
  }
54
54
  },
55
- "telemetry": { "type": "boolean" }
55
+ "telemetry": { "type": "boolean" },
56
+ "model_allowlist": {
57
+ "type": "array",
58
+ "description": "Allowed model identifiers. Enforceable when supplied by a managed source.",
59
+ "items": { "type": "string" }
60
+ },
61
+ "permissions": {
62
+ "type": "object",
63
+ "description": "Permission policy (rules for auto-running tools). Enforceable when supplied by a managed source.",
64
+ "additionalProperties": true
65
+ },
66
+ "managed": {
67
+ "type": "object",
68
+ "description": "Optional centrally-managed / remote config + policy source. Fully opt-in; when absent, resolution is local-only. Also configurable via PRAISONAI_MANAGED_CONFIG_URL / PRAISONAI_MANAGED_CONFIG_DIR.",
69
+ "additionalProperties": false,
70
+ "properties": {
71
+ "url": {
72
+ "type": "string",
73
+ "description": "Remote URL to fetch managed config from (short timeout, cached, fail-soft to last good copy or local-only when offline)."
74
+ },
75
+ "dir": {
76
+ "type": "string",
77
+ "description": "Managed/enterprise directory (populated by MDM/config-management) containing config.yaml|yml|json."
78
+ },
79
+ "timeout": {
80
+ "type": "number",
81
+ "description": "Fetch timeout in seconds (default 3). Never blocks a run on the network.",
82
+ "default": 3
83
+ },
84
+ "enforce": {
85
+ "type": "boolean",
86
+ "description": "When true (default), policy keys (permissions, model_allowlist) are enforced above local config; other keys remain overridable defaults below local config. When false, the whole managed source is advisory.",
87
+ "default": true
88
+ }
89
+ }
90
+ }
56
91
  }
57
92
  }