ayder-cli 1.6.9__tar.gz → 1.8.3__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 (232) hide show
  1. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/PKG-INFO +31 -66
  2. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/README.md +29 -64
  3. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/docs/PROJECT_STRUCTURE.md +4 -4
  4. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/pyproject.toml +2 -2
  5. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/agents/callbacks.py +6 -0
  6. ayder_cli-1.8.3/src/ayder_cli/agents/config.py +74 -0
  7. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/agents/registry.py +46 -21
  8. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/agents/runner.py +17 -0
  9. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/agents/tool.py +33 -7
  10. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/application/runtime_factory.py +28 -11
  11. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/cli_runner.py +18 -3
  12. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/parser.py +8 -0
  13. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/prompts.py +13 -63
  14. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/providers/impl/ollama_drivers/matrix.py +22 -2
  15. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/providers/impl/ollama_drivers/minimax.py +9 -5
  16. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/themes/claude.py +40 -0
  17. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/themes/original.py +39 -0
  18. ayder_cli-1.8.3/src/ayder_cli/tools/builtins/context.py +344 -0
  19. ayder_cli-1.8.3/src/ayder_cli/tools/builtins/context_definitions.py +54 -0
  20. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tools/execution.py +9 -1
  21. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tools/registry.py +21 -3
  22. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tui/app.py +85 -10
  23. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tui/commands.py +121 -61
  24. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tui/screens.py +178 -0
  25. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/agents/test_integration.py +7 -2
  26. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/agents/test_registry.py +99 -15
  27. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/agents/test_runner.py +32 -0
  28. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/agents/test_tool.py +43 -1
  29. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/application/test_message_contract.py +1 -2
  30. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/application/test_runtime_factory.py +2 -0
  31. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/core/test_parser.py +41 -0
  32. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/providers/ollama_drivers/test_matrix.py +2 -1
  33. ayder_cli-1.8.3/tests/providers/ollama_drivers/test_minimax.py +76 -0
  34. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/providers/test_ollama_xml_autoroute.py +1 -1
  35. ayder_cli-1.8.3/tests/test_context.py +453 -0
  36. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/tools/test_definition_discovery.py +2 -4
  37. ayder_cli-1.8.3/tests/tools/test_di_injection.py +50 -0
  38. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/tools/test_schemas.py +2 -2
  39. ayder_cli-1.8.3/tests/tui/__init__.py +1 -0
  40. ayder_cli-1.8.3/tests/tui/test_agent_list_screen.py +115 -0
  41. ayder_cli-1.8.3/tests/tui/test_do_clear_coordination.py +93 -0
  42. ayder_cli-1.8.3/tests/tui/test_pending_compact_consumer.py +148 -0
  43. ayder_cli-1.8.3/tests/ui/test_tui_commands_agent.py +108 -0
  44. ayder_cli-1.8.3/tests/ui/test_tui_widgets.py +28 -0
  45. ayder_cli-1.6.9/src/ayder_cli/agents/config.py +0 -14
  46. ayder_cli-1.6.9/src/ayder_cli/tools/builtins/memory.py +0 -155
  47. ayder_cli-1.6.9/src/ayder_cli/tools/builtins/memory_definitions.py +0 -105
  48. ayder_cli-1.6.9/tests/providers/ollama_drivers/test_minimax.py +0 -49
  49. ayder_cli-1.6.9/tests/test_memory.py +0 -123
  50. ayder_cli-1.6.9/tests/ui/test_tui_widgets.py +0 -28
  51. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/.github/workflows/ci.yml +0 -0
  52. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/.github/workflows/python-package.yml +0 -0
  53. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/.gitignore +0 -0
  54. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/.python-version +0 -0
  55. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/AGENTS.md +0 -0
  56. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/LICENSE +0 -0
  57. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/docs/README_OLLAMA.md +0 -0
  58. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/docs/cc.png +0 -0
  59. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/docs/config.toml.example +0 -0
  60. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/__init__.py +0 -0
  61. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/__main__.py +0 -0
  62. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/agents/__init__.py +0 -0
  63. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/agents/summary.py +0 -0
  64. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/application/README.md +0 -0
  65. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/application/__init__.py +0 -0
  66. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/application/execution_policy.py +0 -0
  67. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/application/message_contract.py +0 -0
  68. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/application/validation.py +0 -0
  69. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/cli.py +0 -0
  70. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/cli_callbacks.py +0 -0
  71. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/console.py +0 -0
  72. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/core/cache_monitor.py +0 -0
  73. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/core/config.py +0 -0
  74. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/core/config_migration.py +0 -0
  75. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/core/context.py +0 -0
  76. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/core/context_manager.py +0 -0
  77. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/core/context_manager_factory.py +0 -0
  78. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/core/default_context_manager.py +0 -0
  79. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/core/ollama_context_manager.py +0 -0
  80. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/core/result.py +0 -0
  81. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/logging_config.py +0 -0
  82. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/loops/__init__.py +0 -0
  83. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/loops/chat_loop.py +0 -0
  84. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/process_manager.py +0 -0
  85. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/providers/__init__.py +0 -0
  86. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/providers/base.py +0 -0
  87. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/providers/impl/claude.py +0 -0
  88. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/providers/impl/deepseek.py +0 -0
  89. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/providers/impl/gemini.py +0 -0
  90. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/providers/impl/glm.py +0 -0
  91. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/providers/impl/ollama.py +0 -0
  92. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/providers/impl/ollama_drivers/__init__.py +0 -0
  93. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/providers/impl/ollama_drivers/_errors.py +0 -0
  94. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/providers/impl/ollama_drivers/base.py +0 -0
  95. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/providers/impl/ollama_drivers/deepseek.py +0 -0
  96. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/providers/impl/ollama_drivers/generic_native.py +0 -0
  97. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/providers/impl/ollama_drivers/generic_xml.py +0 -0
  98. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/providers/impl/ollama_drivers/qwen3.py +0 -0
  99. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/providers/impl/ollama_drivers/registry.py +0 -0
  100. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/providers/impl/ollama_inspector.py +0 -0
  101. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/providers/impl/openai.py +0 -0
  102. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/providers/impl/qwen.py +0 -0
  103. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/providers/orchestrator.py +0 -0
  104. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/providers/retry.py +0 -0
  105. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/services/__init__.py +0 -0
  106. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/services/interactions.py +0 -0
  107. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/themes/__init__.py +0 -0
  108. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tools/__init__.py +0 -0
  109. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tools/builtins/__init__.py +0 -0
  110. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tools/builtins/filesystem.py +0 -0
  111. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tools/builtins/filesystem_definitions.py +0 -0
  112. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tools/builtins/notes.py +0 -0
  113. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tools/builtins/notes_definitions.py +0 -0
  114. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tools/builtins/process_manager_definitions.py +0 -0
  115. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tools/builtins/search.py +0 -0
  116. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tools/builtins/search_definitions.py +0 -0
  117. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tools/builtins/shell.py +0 -0
  118. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tools/builtins/shell_definitions.py +0 -0
  119. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tools/builtins/tasks.py +0 -0
  120. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tools/builtins/tasks_definitions.py +0 -0
  121. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tools/builtins/utils_tools.py +0 -0
  122. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tools/builtins/utils_tools_definitions.py +0 -0
  123. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tools/builtins/web.py +0 -0
  124. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tools/builtins/web_definitions.py +0 -0
  125. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tools/definition.py +0 -0
  126. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tools/hooks.py +0 -0
  127. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tools/normalization.py +0 -0
  128. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tools/plugin_api.py +0 -0
  129. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tools/plugin_github.py +0 -0
  130. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tools/plugin_manager.py +0 -0
  131. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tools/schemas.py +0 -0
  132. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tools/utils.py +0 -0
  133. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tui/__init__.py +0 -0
  134. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tui/adapter.py +0 -0
  135. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tui/helpers.py +0 -0
  136. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tui/keybindings.py +0 -0
  137. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tui/parser.py +0 -0
  138. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tui/theme_manager.py +0 -0
  139. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tui/types.py +0 -0
  140. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/tui/widgets.py +0 -0
  141. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/ui.py +0 -0
  142. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/src/ayder_cli/version.py +0 -0
  143. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/COVERAGE.md +0 -0
  144. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/__init__.py +0 -0
  145. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/agents/__init__.py +0 -0
  146. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/agents/test_callbacks.py +0 -0
  147. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/agents/test_config.py +0 -0
  148. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/agents/test_summary.py +0 -0
  149. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/client/test_main.py +0 -0
  150. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/convergence/__init__.py +0 -0
  151. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/convergence/test_execution_policy_parity.py +0 -0
  152. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/convergence/test_runtime_wiring.py +0 -0
  153. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/convergence/test_validation_path.py +0 -0
  154. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/core/test_cache_monitor.py +0 -0
  155. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/core/test_config.py +0 -0
  156. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/core/test_config_coverage.py +0 -0
  157. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/core/test_config_migration.py +0 -0
  158. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/core/test_config_retry.py +0 -0
  159. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/core/test_config_v2.py +0 -0
  160. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/core/test_context_manager_factory.py +0 -0
  161. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/core/test_default_context_manager.py +0 -0
  162. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/core/test_default_context_manager_should_compact.py +0 -0
  163. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/core/test_ollama_context_manager.py +0 -0
  164. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/core/test_ollama_context_manager_cache_monitor.py +0 -0
  165. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/core/test_ollama_context_manager_max_history.py +0 -0
  166. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/core/test_parameter_aliasing.py +0 -0
  167. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/loops/__init__.py +0 -0
  168. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/loops/test_base.py +0 -0
  169. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/loops/test_chat_loop_hook.py +0 -0
  170. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/loops/test_chat_loop_tool_truncation.py +0 -0
  171. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/manual_test_verbose.py +0 -0
  172. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/providers/__init__.py +0 -0
  173. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/providers/ollama_drivers/__init__.py +0 -0
  174. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/providers/ollama_drivers/test_base.py +0 -0
  175. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/providers/ollama_drivers/test_deepseek.py +0 -0
  176. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/providers/ollama_drivers/test_errors.py +0 -0
  177. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/providers/ollama_drivers/test_fallback.py +0 -0
  178. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/providers/ollama_drivers/test_generic_native.py +0 -0
  179. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/providers/ollama_drivers/test_generic_xml.py +0 -0
  180. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/providers/ollama_drivers/test_provider_integration.py +0 -0
  181. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/providers/ollama_drivers/test_qwen3.py +0 -0
  182. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/providers/ollama_drivers/test_registry.py +0 -0
  183. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/providers/test_glm_async.py +0 -0
  184. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/providers/test_ollama_inspector.py +0 -0
  185. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/providers/test_ollama_native.py +0 -0
  186. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/providers/test_ollama_xml.py +0 -0
  187. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/providers/test_ollama_xml_usage.py +0 -0
  188. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/providers/test_qwen_async.py +0 -0
  189. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/providers/test_retry_classifier.py +0 -0
  190. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/providers/test_retry_integration.py +0 -0
  191. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/providers/test_retrying_provider.py +0 -0
  192. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/services/test_boundary.py +0 -0
  193. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/services/test_interaction_sink.py +0 -0
  194. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/test_cli.py +0 -0
  195. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/test_cli_callbacks.py +0 -0
  196. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/test_env_manager.py +0 -0
  197. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/test_logging_config.py +0 -0
  198. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/test_notes.py +0 -0
  199. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/test_process_manager.py +0 -0
  200. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/test_tasks.py +0 -0
  201. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/tools/__init__.py +0 -0
  202. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/tools/test_impl.py +0 -0
  203. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/tools/test_impl_coverage.py +0 -0
  204. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/tools/test_path_security.py +0 -0
  205. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/tools/test_plugin_api.py +0 -0
  206. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/tools/test_plugin_github.py +0 -0
  207. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/tools/test_plugin_loading.py +0 -0
  208. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/tools/test_plugin_manager.py +0 -0
  209. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/tools/test_registry.py +0 -0
  210. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/tools/test_registry_coverage.py +0 -0
  211. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/tools/test_result.py +0 -0
  212. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/tools/test_search_codebase.py +0 -0
  213. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/tools/test_utils.py +0 -0
  214. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/tools/test_web.py +0 -0
  215. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/tui/test_follow_mode.py +0 -0
  216. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/tui/test_help_screen.py +0 -0
  217. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/tui/test_keybindings.py +0 -0
  218. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/tui/test_multi_select_screen.py +0 -0
  219. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/tui/test_multiline_input.py +0 -0
  220. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/tui/test_paste.py +0 -0
  221. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/tui/test_widgets.py +0 -0
  222. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/ui/test_confirm_screen.py +0 -0
  223. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/ui/test_diff_preview.py +0 -0
  224. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/ui/test_tui_assistant_sanitization.py +0 -0
  225. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/ui/test_tui_chat_loop.py +0 -0
  226. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/ui/test_tui_commands_logging.py +0 -0
  227. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/ui/test_tui_commands_provider.py +0 -0
  228. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/ui/test_tui_helpers.py +0 -0
  229. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/ui/test_tui_temporal_command.py +0 -0
  230. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/ui/test_ui.py +0 -0
  231. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/ui/test_ui_coverage.py +0 -0
  232. {ayder_cli-1.6.9 → ayder_cli-1.8.3}/tests/ui/test_ui_verbose.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ayder-cli
3
- Version: 1.6.9
3
+ Version: 1.8.3
4
4
  Summary: AI agent for any LLMs
5
5
  Project-URL: Homepage, https://github.com/ayder/ayder-cli
6
6
  Project-URL: Repository, https://github.com/ayder/ayder-cli.git
@@ -19,7 +19,7 @@ Requires-Dist: google-genai
19
19
  Requires-Dist: httpx
20
20
  Requires-Dist: libcst>=1.0.0
21
21
  Requires-Dist: loguru
22
- Requires-Dist: ollama>=0.6.1
22
+ Requires-Dist: ollama>=0.6.2
23
23
  Requires-Dist: openai
24
24
  Requires-Dist: python-dotenv>=1.0.0
25
25
  Requires-Dist: rich>=13.0.0
@@ -54,39 +54,11 @@ Most AI coding assistants require cloud APIs, subscriptions, or heavy IDE plugin
54
54
  - **Agentic workflow** -- the LLM reads files, edits code, runs shell commands, and iterates autonomously with configurable iteration limits per message.
55
55
  - **Multi-agent** -- define specialized sub-agents in `config.toml`. Each agent runs independently with its own LLM, model, and context. Results are injected back into the main conversation when complete.
56
56
  - **Textual TUI** -- an inline terminal interface with chat view, tool panel, thinking block toggle, slash command auto-completion, permission toggles, and tool confirmation modals with diff previews.
57
- - **Minimal dependencies** -- OpenAI SDK, Rich, and Textual. Other provider SDKs are optional.
58
-
59
- ### Tested Providers with Models
60
-
61
- | Provider | Location | Model |
62
- | -------- | -------- | ----- |
63
- | ollama | Cloud | deepseek-v3.2:cloud |
64
- | ollama | Cloud | gemini-3-pro-preview:latest |
65
- | ollama | Local | glm-4.7-flash:latest |
66
- | ollama | Cloud | glm-4.7:cloud |
67
- | ollama | Cloud | glm-5:cloud |
68
- | ollama | Local | glm-ocr:latest |
69
- | ollama | Cloud | gpt-oss:120b-cloud |
70
- | ollama | Cloud | kimi-k2.5:cloud |
71
- | ollama | Cloud | minimax-m2.5:cloud |
72
- | ollama | Local | ministral-3:14b |
73
- | ollama | Cloud | qwen3-coder-next:cloud |
74
- | ollama | Cloud | qwen3-coder:480b-cloud |
75
- | ollama | Local | qwen3-coder:latest |
76
- | anthropic | Cloud | claude-opus-4-6 |
77
- | anthropic | Cloud | claude-sonnet-4-5-20250929 |
78
- | anthropic | Cloud | claude-haiku-4-5-20251001 |
79
- | openai | Cloud | GPT-5.3-Codex |
80
- | openai | Cloud | GPT-5.3-Codex-Spark |
81
- | openai | Cloud | GPT-5.2 |
82
- | openai | Cloud | GPT-5 |
83
- | gemini | Cloud | gemini-3-deep-think |
84
- | gemini | Cloud | gemini-3-pro |
85
- | gemini | Cloud | gemini-3-flash |
57
+ - **Batteries included** -- the OpenAI, Anthropic, Google, and Ollama SDKs all ship with ayder-cli, so every provider works out of the box. The terminal UI is built on Rich and Textual.
86
58
 
87
59
  ### Tools
88
60
 
89
- LLMs on their own can only generate text. To be a useful coding assistant, the model needs to *act* on your codebase. ayder-cli provides 25 tools across 10 categories that the model can call:
61
+ LLMs on their own can only generate text. To be a useful coding assistant, the model needs to *act* on your codebase. ayder-cli ships 16 built-in tools that the model can call, plus optional plugin toolsets (see [Plugins](#plugins)):
90
62
 
91
63
  Each tool has an OpenAI-compatible JSON schema so models that support function calling can use them natively. For models that don't, ayder-cli also parses a custom XML-like syntax (`<function=name><parameter=key>value</parameter></function>`) as a fallback.
92
64
 
@@ -134,26 +106,16 @@ export OLLAMA_FLASH_ATTENTION=true
134
106
  export OLLAMA_MAX_LOADED_MODELS=1
135
107
  ```
136
108
 
137
- ### Anthropic setup (optional)
109
+ ### Cloud providers (Anthropic, OpenAI, Gemini)
138
110
 
139
- ```bash
140
- # Install the Anthropic SDK
141
- pip install anthropic
142
-
143
- # Set your API key in ~/.ayder/config.toml (see Configuration below)
144
- # Then switch provider:
145
- # /provider anthropic
146
- ```
147
-
148
- ### Gemini setup (optional)
111
+ The Anthropic, OpenAI, and Google SDKs ship with ayder-cli — no extra installs.
112
+ Just add an API key to a profile in `~/.ayder/config.toml` (see Configuration
113
+ below) and switch provider in the TUI:
149
114
 
150
115
  ```bash
151
- # Install the Google Generative AI SDK
152
- pip install google-generativeai
116
+ /provider anthropic # or: openai, gemini
153
117
  ```
154
118
 
155
- Set your API key in `~/.ayder/config.toml`, then switch provider: `/provider gemini`
156
-
157
119
  ### Configuration: Profiles and Drivers
158
120
 
159
121
  ayder-cli uses a flexible profile-based configuration system. On the first run, it creates a config file at `~/.ayder/config.toml`.
@@ -218,7 +180,7 @@ rotation = "10 MB"
218
180
  retention = "7 days"
219
181
 
220
182
  [context_manager]
221
- enabled = false
183
+ enabled = true
222
184
  max_context_tokens = 8192
223
185
 
224
186
  [temporal]
@@ -316,12 +278,14 @@ ayder --implement-all
316
278
 
317
279
  By default, every tool call requires user confirmation. Use permission flags to auto-approve tool categories:
318
280
 
319
- | Flag | Category | Tools |
320
- | ---- | -------- | ----- |
321
- | `-r` | Read | `file_explorer`, `read_file`, `search_codebase`, `get_project_structure`, `load_memory`, `get_background_output`, `list_background_processes`, `list_tasks`, `show_task`, `list_virtualenvs`, `activate_virtualenv` |
322
- | `-w` | Write | `file_editor`, `create_note`, `save_memory`, `manage_environment_vars`, `python_editor`, `temporal_workflow` |
323
- | `-x` | Execute | `run_shell_command`, `run_background_process`, `kill_background_process`, `create_virtualenv`, `install_requirements`, `remove_virtualenv` |
324
- | `--http` | Web/Network | `fetch_web`, `dbs_tool` |
281
+ | Flag | Category | Built-in tools |
282
+ | ---- | -------- | -------------- |
283
+ | `-r` | Read | `file_explorer`, `read_file`, `search_codebase`, `get_project_structure`, `get_background_output`, `list_background_processes`, `list_tasks`, `show_task` |
284
+ | `-w` | Write | `file_editor`, `context`, `create_note`, `manage_environment_vars` |
285
+ | `-x` | Execute | `run_shell_command`, `run_background_process`, `kill_background_process` |
286
+ | `--http` | Web/Network | `fetch_web` |
287
+
288
+ Installed plugins extend these categories (e.g. `python_editor` → write, virtualenv tools → execute, `dbs_tool` → web).
325
289
 
326
290
  ```bash
327
291
  # Auto-approve read-only tools
@@ -370,7 +334,7 @@ The context manager is configured under `[context_manager]` in `config.toml`:
370
334
  | `max_tool_result_length` | `2048` | Maximum character length for a compressed tool result. |
371
335
  | `compress_tool_results` | `true` | Enable automatic tool result compression. |
372
336
 
373
- You can also manually manage context with `/save-memory`, `/load-memory`, and `/compact`.
337
+ You can also manually manage context with the `context` tool and its slash-command shortcuts: `/save-context`, `/load-context`, `/list-contexts`, `/context-stats`, and `/compact`.
374
338
 
375
339
  ### Slash Commands
376
340
 
@@ -390,9 +354,11 @@ You can also manually manage context with `/save-memory`, `/load-memory`, and `/
390
354
  | `/skill` | Activate a domain skill from `.ayder/skills/` |
391
355
  | `/verbose` | Toggle verbose mode |
392
356
  | `/logging` | Set log level for current session (NONE, ERROR, WARNING, INFO, DEBUG) |
393
- | `/compact` | Summarize conversation, save to memory, clear, and reload context |
394
- | `/save-memory` | Summarize conversation and save to memory (no clear) |
395
- | `/load-memory` | Load memory and restore context |
357
+ | `/compact` | Summarize conversation, save a context snapshot, clear, and reload |
358
+ | `/save-context` | Summarize conversation and save it to a named context slot (no clear) |
359
+ | `/load-context` | Load a saved context slot and restore it |
360
+ | `/list-contexts` | List saved context slots |
361
+ | `/context-stats` | Show current token and KV-cache usage |
396
362
  | `/archive-completed-tasks` | Move completed tasks to `.ayder/task_archive/` |
397
363
  | `/temporal` | Start/status Temporal queue worker |
398
364
  | `/agent list` | List configured agents and their current status |
@@ -436,7 +402,7 @@ The standard mode for general coding and chat. Uses the system prompt.
436
402
  > create a fibonacci function
437
403
  ```
438
404
 
439
- Available tools: File read/write, shell commands, search, memory, notes, tasks.
405
+ Available tools: file read/write, shell commands, search, context, notes, tasks.
440
406
 
441
407
  ### Planning Mode (`/plan`)
442
408
 
@@ -486,24 +452,23 @@ The tool system:
486
452
  - Supports tag-based filtering for dynamic enable/disable
487
453
  - Injects tool-specific system prompts when enabled
488
454
 
489
- **Current tool categories (25 tools):**
455
+ **Built-in tools (16):**
490
456
 
491
457
  | Category | Tools |
492
458
  |----------|-------|
493
459
  | **Filesystem** | `file_explorer`, `read_file`, `file_editor` |
494
460
  | **Search** | `search_codebase`, `get_project_structure` |
495
461
  | **Shell** | `run_shell_command` |
496
- | **Python Editor** | `python_editor` (CST-based structural code manipulation) |
497
- | **Memory** | `save_memory`, `load_memory` |
462
+ | **Context** | `context` (save / load / list / stats / clear session context slots) |
498
463
  | **Notes** | `create_note` |
499
464
  | **Background Processes** | `run_background_process`, `get_background_output`, `kill_background_process`, `list_background_processes` |
500
465
  | **Tasks** | `list_tasks`, `show_task` |
501
466
  | **Environment** | `manage_environment_vars` |
502
- | **Virtual Environments** | `create_virtualenv`, `install_requirements`, `list_virtualenvs`, `activate_virtualenv`, `remove_virtualenv` |
503
467
  | **Web** | `fetch_web` |
504
- | **DBS** | `dbs_tool` (RAG API for DBS-related queries) |
505
- | **Workflow** | `temporal_workflow` |
506
- | **Agents** | `call_agent` (dispatch a named agent to run a task in the background) |
468
+
469
+ When agents are configured, the `call_agent` tool is also registered so the main LLM can dispatch them (see [Multi-Agent System](#multi-agent-system)).
470
+
471
+ **Plugin tools** — `python_editor`, `dbs_tool`, `temporal_workflow`, virtualenv tools, and MCP integrations ship as optional plugins in the [ayder/ayder-plugins](https://github.com/ayder/ayder-plugins) repo (see [Plugins](#plugins)). Once installed they are auto-discovered exactly like built-ins.
507
472
 
508
473
  ## Multi-Agent System
509
474
 
@@ -25,39 +25,11 @@ Most AI coding assistants require cloud APIs, subscriptions, or heavy IDE plugin
25
25
  - **Agentic workflow** -- the LLM reads files, edits code, runs shell commands, and iterates autonomously with configurable iteration limits per message.
26
26
  - **Multi-agent** -- define specialized sub-agents in `config.toml`. Each agent runs independently with its own LLM, model, and context. Results are injected back into the main conversation when complete.
27
27
  - **Textual TUI** -- an inline terminal interface with chat view, tool panel, thinking block toggle, slash command auto-completion, permission toggles, and tool confirmation modals with diff previews.
28
- - **Minimal dependencies** -- OpenAI SDK, Rich, and Textual. Other provider SDKs are optional.
29
-
30
- ### Tested Providers with Models
31
-
32
- | Provider | Location | Model |
33
- | -------- | -------- | ----- |
34
- | ollama | Cloud | deepseek-v3.2:cloud |
35
- | ollama | Cloud | gemini-3-pro-preview:latest |
36
- | ollama | Local | glm-4.7-flash:latest |
37
- | ollama | Cloud | glm-4.7:cloud |
38
- | ollama | Cloud | glm-5:cloud |
39
- | ollama | Local | glm-ocr:latest |
40
- | ollama | Cloud | gpt-oss:120b-cloud |
41
- | ollama | Cloud | kimi-k2.5:cloud |
42
- | ollama | Cloud | minimax-m2.5:cloud |
43
- | ollama | Local | ministral-3:14b |
44
- | ollama | Cloud | qwen3-coder-next:cloud |
45
- | ollama | Cloud | qwen3-coder:480b-cloud |
46
- | ollama | Local | qwen3-coder:latest |
47
- | anthropic | Cloud | claude-opus-4-6 |
48
- | anthropic | Cloud | claude-sonnet-4-5-20250929 |
49
- | anthropic | Cloud | claude-haiku-4-5-20251001 |
50
- | openai | Cloud | GPT-5.3-Codex |
51
- | openai | Cloud | GPT-5.3-Codex-Spark |
52
- | openai | Cloud | GPT-5.2 |
53
- | openai | Cloud | GPT-5 |
54
- | gemini | Cloud | gemini-3-deep-think |
55
- | gemini | Cloud | gemini-3-pro |
56
- | gemini | Cloud | gemini-3-flash |
28
+ - **Batteries included** -- the OpenAI, Anthropic, Google, and Ollama SDKs all ship with ayder-cli, so every provider works out of the box. The terminal UI is built on Rich and Textual.
57
29
 
58
30
  ### Tools
59
31
 
60
- LLMs on their own can only generate text. To be a useful coding assistant, the model needs to *act* on your codebase. ayder-cli provides 25 tools across 10 categories that the model can call:
32
+ LLMs on their own can only generate text. To be a useful coding assistant, the model needs to *act* on your codebase. ayder-cli ships 16 built-in tools that the model can call, plus optional plugin toolsets (see [Plugins](#plugins)):
61
33
 
62
34
  Each tool has an OpenAI-compatible JSON schema so models that support function calling can use them natively. For models that don't, ayder-cli also parses a custom XML-like syntax (`<function=name><parameter=key>value</parameter></function>`) as a fallback.
63
35
 
@@ -105,26 +77,16 @@ export OLLAMA_FLASH_ATTENTION=true
105
77
  export OLLAMA_MAX_LOADED_MODELS=1
106
78
  ```
107
79
 
108
- ### Anthropic setup (optional)
80
+ ### Cloud providers (Anthropic, OpenAI, Gemini)
109
81
 
110
- ```bash
111
- # Install the Anthropic SDK
112
- pip install anthropic
113
-
114
- # Set your API key in ~/.ayder/config.toml (see Configuration below)
115
- # Then switch provider:
116
- # /provider anthropic
117
- ```
118
-
119
- ### Gemini setup (optional)
82
+ The Anthropic, OpenAI, and Google SDKs ship with ayder-cli — no extra installs.
83
+ Just add an API key to a profile in `~/.ayder/config.toml` (see Configuration
84
+ below) and switch provider in the TUI:
120
85
 
121
86
  ```bash
122
- # Install the Google Generative AI SDK
123
- pip install google-generativeai
87
+ /provider anthropic # or: openai, gemini
124
88
  ```
125
89
 
126
- Set your API key in `~/.ayder/config.toml`, then switch provider: `/provider gemini`
127
-
128
90
  ### Configuration: Profiles and Drivers
129
91
 
130
92
  ayder-cli uses a flexible profile-based configuration system. On the first run, it creates a config file at `~/.ayder/config.toml`.
@@ -189,7 +151,7 @@ rotation = "10 MB"
189
151
  retention = "7 days"
190
152
 
191
153
  [context_manager]
192
- enabled = false
154
+ enabled = true
193
155
  max_context_tokens = 8192
194
156
 
195
157
  [temporal]
@@ -287,12 +249,14 @@ ayder --implement-all
287
249
 
288
250
  By default, every tool call requires user confirmation. Use permission flags to auto-approve tool categories:
289
251
 
290
- | Flag | Category | Tools |
291
- | ---- | -------- | ----- |
292
- | `-r` | Read | `file_explorer`, `read_file`, `search_codebase`, `get_project_structure`, `load_memory`, `get_background_output`, `list_background_processes`, `list_tasks`, `show_task`, `list_virtualenvs`, `activate_virtualenv` |
293
- | `-w` | Write | `file_editor`, `create_note`, `save_memory`, `manage_environment_vars`, `python_editor`, `temporal_workflow` |
294
- | `-x` | Execute | `run_shell_command`, `run_background_process`, `kill_background_process`, `create_virtualenv`, `install_requirements`, `remove_virtualenv` |
295
- | `--http` | Web/Network | `fetch_web`, `dbs_tool` |
252
+ | Flag | Category | Built-in tools |
253
+ | ---- | -------- | -------------- |
254
+ | `-r` | Read | `file_explorer`, `read_file`, `search_codebase`, `get_project_structure`, `get_background_output`, `list_background_processes`, `list_tasks`, `show_task` |
255
+ | `-w` | Write | `file_editor`, `context`, `create_note`, `manage_environment_vars` |
256
+ | `-x` | Execute | `run_shell_command`, `run_background_process`, `kill_background_process` |
257
+ | `--http` | Web/Network | `fetch_web` |
258
+
259
+ Installed plugins extend these categories (e.g. `python_editor` → write, virtualenv tools → execute, `dbs_tool` → web).
296
260
 
297
261
  ```bash
298
262
  # Auto-approve read-only tools
@@ -341,7 +305,7 @@ The context manager is configured under `[context_manager]` in `config.toml`:
341
305
  | `max_tool_result_length` | `2048` | Maximum character length for a compressed tool result. |
342
306
  | `compress_tool_results` | `true` | Enable automatic tool result compression. |
343
307
 
344
- You can also manually manage context with `/save-memory`, `/load-memory`, and `/compact`.
308
+ You can also manually manage context with the `context` tool and its slash-command shortcuts: `/save-context`, `/load-context`, `/list-contexts`, `/context-stats`, and `/compact`.
345
309
 
346
310
  ### Slash Commands
347
311
 
@@ -361,9 +325,11 @@ You can also manually manage context with `/save-memory`, `/load-memory`, and `/
361
325
  | `/skill` | Activate a domain skill from `.ayder/skills/` |
362
326
  | `/verbose` | Toggle verbose mode |
363
327
  | `/logging` | Set log level for current session (NONE, ERROR, WARNING, INFO, DEBUG) |
364
- | `/compact` | Summarize conversation, save to memory, clear, and reload context |
365
- | `/save-memory` | Summarize conversation and save to memory (no clear) |
366
- | `/load-memory` | Load memory and restore context |
328
+ | `/compact` | Summarize conversation, save a context snapshot, clear, and reload |
329
+ | `/save-context` | Summarize conversation and save it to a named context slot (no clear) |
330
+ | `/load-context` | Load a saved context slot and restore it |
331
+ | `/list-contexts` | List saved context slots |
332
+ | `/context-stats` | Show current token and KV-cache usage |
367
333
  | `/archive-completed-tasks` | Move completed tasks to `.ayder/task_archive/` |
368
334
  | `/temporal` | Start/status Temporal queue worker |
369
335
  | `/agent list` | List configured agents and their current status |
@@ -407,7 +373,7 @@ The standard mode for general coding and chat. Uses the system prompt.
407
373
  > create a fibonacci function
408
374
  ```
409
375
 
410
- Available tools: File read/write, shell commands, search, memory, notes, tasks.
376
+ Available tools: file read/write, shell commands, search, context, notes, tasks.
411
377
 
412
378
  ### Planning Mode (`/plan`)
413
379
 
@@ -457,24 +423,23 @@ The tool system:
457
423
  - Supports tag-based filtering for dynamic enable/disable
458
424
  - Injects tool-specific system prompts when enabled
459
425
 
460
- **Current tool categories (25 tools):**
426
+ **Built-in tools (16):**
461
427
 
462
428
  | Category | Tools |
463
429
  |----------|-------|
464
430
  | **Filesystem** | `file_explorer`, `read_file`, `file_editor` |
465
431
  | **Search** | `search_codebase`, `get_project_structure` |
466
432
  | **Shell** | `run_shell_command` |
467
- | **Python Editor** | `python_editor` (CST-based structural code manipulation) |
468
- | **Memory** | `save_memory`, `load_memory` |
433
+ | **Context** | `context` (save / load / list / stats / clear session context slots) |
469
434
  | **Notes** | `create_note` |
470
435
  | **Background Processes** | `run_background_process`, `get_background_output`, `kill_background_process`, `list_background_processes` |
471
436
  | **Tasks** | `list_tasks`, `show_task` |
472
437
  | **Environment** | `manage_environment_vars` |
473
- | **Virtual Environments** | `create_virtualenv`, `install_requirements`, `list_virtualenvs`, `activate_virtualenv`, `remove_virtualenv` |
474
438
  | **Web** | `fetch_web` |
475
- | **DBS** | `dbs_tool` (RAG API for DBS-related queries) |
476
- | **Workflow** | `temporal_workflow` |
477
- | **Agents** | `call_agent` (dispatch a named agent to run a task in the background) |
439
+
440
+ When agents are configured, the `call_agent` tool is also registered so the main LLM can dispatch them (see [Multi-Agent System](#multi-agent-system)).
441
+
442
+ **Plugin tools** — `python_editor`, `dbs_tool`, `temporal_workflow`, virtualenv tools, and MCP integrations ship as optional plugins in the [ayder/ayder-plugins](https://github.com/ayder/ayder-plugins) repo (see [Plugins](#plugins)). Once installed they are auto-discovered exactly like built-ins.
478
443
 
479
444
  ## Multi-Agent System
480
445
 
@@ -219,7 +219,7 @@ cli.py:main()
219
219
  | `tui/adapter.py` | Adapter glue between `AyderApp` and `ChatLoop` | callback wiring helpers |
220
220
  | `tui/commands.py` | Slash command handlers | `COMMAND_MAP`, `handle_*()` |
221
221
  | `tui/widgets.py` | Custom widgets | `ChatView`, `ToolPanel`, `CLIInputBar`, `StatusBar`, `AutoCompleteInput` |
222
- | `tui/screens.py` | Modal screens | `CLIConfirmScreen`, `CLIHelpScreen`, `CLIPermissionScreen`, `CLISafeModeScreen`, `CLISelectScreen`, `TaskEditScreen` |
222
+ | `tui/screens.py` | Modal screens | `AgentListScreen`, `CLIConfirmScreen`, `CLIHelpScreen`, `CLIMultiSelectScreen`, `CLIPermissionScreen`, `CLISafeModeScreen`, `CLISelectScreen`, `TaskEditScreen` |
223
223
  | `tui/parser.py` | TUI-specific parsing | `content_processor()` |
224
224
  | `tui/helpers.py` | UI helpers | `create_tui_banner()` |
225
225
  | `tui/keybindings.py` | Keybinding declarations | `BINDINGS` |
@@ -289,7 +289,7 @@ the design rationale.
289
289
  | `tools/builtins/filesystem.py` | File system tool impls | `file_explorer()`, `read_file()`, `file_editor()` |
290
290
  | `tools/builtins/search.py` | Search tool impls | `search_codebase()`, `get_project_structure()` |
291
291
  | `tools/builtins/shell.py` | Shell execution impl | `run_shell_command()` |
292
- | `tools/builtins/memory.py` | Long-term memory tools | `save_memory`, `load_memory`, `save_context_memory`, `load_context_memory` |
292
+ | `tools/builtins/context.py` | Session context snapshots | `context` |
293
293
  | `tools/builtins/notes.py` | Note-taking tool | `create_note()` |
294
294
  | `tools/builtins/tasks.py` | Task-management tools | `list_tasks()`, `show_task()` |
295
295
  | `tools/builtins/web.py` | HTTP fetch tool | `fetch_web()` |
@@ -642,11 +642,11 @@ Schema-driven tool definitions with auto-discovery:
642
642
  - **Schema generation**: `to_openai_schema()` returns the OpenAI function-calling dict
643
643
  - **Plugin loading**: `tools/plugin_manager.py` can augment `TOOL_DEFINITIONS` at runtime from local or GitHub-sourced plugins
644
644
 
645
- 19 built-in tools across 9 definition files:
645
+ 16 built-in tools across 9 definition files:
646
646
  - Filesystem (3): `file_explorer`, `read_file`, `file_editor`
647
647
  - Search (2): `search_codebase`, `get_project_structure`
648
648
  - Shell (1): `run_shell_command`
649
- - Memory (4): `save_memory`, `load_memory`, `save_context_memory`, `load_context_memory`
649
+ - Context (1): `context`
650
650
  - Notes (1): `create_note`
651
651
  - Background Processes (4): `run_background_process`, `get_background_output`, `kill_background_process`, `list_background_processes`
652
652
  - Tasks (2): `list_tasks`, `show_task`
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "ayder-cli"
7
- version = "1.6.9"
7
+ version = "1.8.3"
8
8
  description = "AI agent for any LLMs"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.12"
@@ -23,7 +23,7 @@ dependencies = [
23
23
  "openai",
24
24
  "anthropic",
25
25
  "google-genai",
26
- "ollama>=0.6.1",
26
+ "ollama>=0.6.2",
27
27
  "loguru",
28
28
  "httpx",
29
29
  "rich>=13.0.0",
@@ -41,6 +41,7 @@ class AgentCallbacks:
41
41
  self._cancel_event = cancel_event
42
42
  self._on_progress = on_progress
43
43
  self.last_content: str = ""
44
+ self.last_system_error: str | None = None
44
45
 
45
46
  def _emit(self, event: str, data: Any = None) -> None:
46
47
  if self._on_progress:
@@ -87,6 +88,11 @@ class AgentCallbacks:
87
88
  self._emit("tools_cleanup")
88
89
 
89
90
  def on_system_message(self, text: str) -> None:
91
+ # ChatLoop reports stream/tool failures here. Capture them so the
92
+ # runner can promote them into AgentSummary.error instead of returning
93
+ # a misleading "completed" status with no content.
94
+ if isinstance(text, str) and text.lstrip().lower().startswith("error"):
95
+ self.last_system_error = text
90
96
  self._emit("system_message", text)
91
97
 
92
98
  async def request_confirmation(
@@ -0,0 +1,74 @@
1
+ """AgentConfig — Pydantic model for agent definitions."""
2
+
3
+ from typing import Any
4
+
5
+ from pydantic import BaseModel, ConfigDict, model_validator
6
+
7
+
8
+ class AgentConfig(BaseModel):
9
+ """Configuration for a single agent, parsed from [agents.<name>] TOML sections.
10
+
11
+ Connection-level fields (base_url, api_key, num_ctx, temperature, think,
12
+ driver) are optional; when set they override the values pulled from the
13
+ parent provider profile. This lets one agent target an entirely different
14
+ endpoint than the main session without needing a separate [llm.<name>]
15
+ profile.
16
+ """
17
+
18
+ model_config = ConfigDict(frozen=True, extra="forbid")
19
+
20
+ name: str
21
+ provider: str | None = None
22
+ model: str | None = None
23
+ system_prompt: str = ""
24
+
25
+ base_url: str | None = None
26
+ api_key: str | None = None
27
+ driver: str | None = None
28
+ num_ctx: int | None = None
29
+ temperature: float | None = None
30
+ max_output_tokens: int | None = None
31
+ think: str | None = None
32
+
33
+ @model_validator(mode="before")
34
+ @classmethod
35
+ def _coerce_aliases(cls, data: Any) -> Any:
36
+ """Accept ``thinking`` as an alias for ``think`` and coerce numeric strings."""
37
+ if not isinstance(data, dict):
38
+ return data
39
+ new_data = dict(data)
40
+ if "thinking" in new_data and "think" not in new_data:
41
+ new_data["think"] = new_data.pop("thinking")
42
+ for key in ("temperature",):
43
+ val = new_data.get(key)
44
+ if isinstance(val, str) and val.strip():
45
+ try:
46
+ new_data[key] = float(val)
47
+ except ValueError:
48
+ pass
49
+ for key in ("num_ctx", "max_output_tokens"):
50
+ val = new_data.get(key)
51
+ if isinstance(val, str) and val.strip():
52
+ try:
53
+ new_data[key] = int(val)
54
+ except ValueError:
55
+ pass
56
+ return new_data
57
+
58
+ def overrides(self) -> dict[str, Any]:
59
+ """Return non-None connection-level fields suitable for cfg.model_copy()."""
60
+ out: dict[str, Any] = {}
61
+ for field in (
62
+ "model",
63
+ "base_url",
64
+ "api_key",
65
+ "driver",
66
+ "num_ctx",
67
+ "temperature",
68
+ "max_output_tokens",
69
+ "think",
70
+ ):
71
+ value = getattr(self, field)
72
+ if value is not None:
73
+ out[field] = value
74
+ return out
@@ -79,39 +79,42 @@ class AgentRegistry:
79
79
  """Count of currently active instances of the named agent."""
80
80
  return sum(1 for r in self._active.values() if r.agent_name == name)
81
81
 
82
+ def list_agents(self) -> list[dict[str, Any]]:
83
+ """Return configured agents with live status information."""
84
+ parent_model = getattr(self._parent_config, "model", None)
85
+ agents: list[dict[str, Any]] = []
86
+ for name, cfg in self.agents.items():
87
+ description = cfg.system_prompt[:200] if cfg.system_prompt else ""
88
+ resolved_model = cfg.model or parent_model
89
+ model = resolved_model if isinstance(resolved_model, str) else ""
90
+ agents.append({
91
+ "name": name,
92
+ "description": description,
93
+ "model": model,
94
+ "status": self.get_status(name) or "unknown",
95
+ "running_count": self.get_running_count(name),
96
+ })
97
+ return agents
98
+
82
99
  def get_capability_prompts(self) -> str:
83
- """Generate capability prompt text for the main LLM's system prompt."""
100
+ """Generate generic agent capability guidance for the system prompt."""
84
101
  if not self.agents:
85
102
  return ""
86
103
 
87
- agent_names = list(self.agents.keys())
88
-
89
104
  lines = [
90
- "\n## Registered Agents",
91
- "",
92
- "You have specialized agents available. To use them, call the `call_agent` tool",
93
- f"with the `name` parameter set to one of: {', '.join(repr(n) for n in agent_names)}.",
105
+ "\n## Agent Delegation",
94
106
  "",
107
+ "Configured specialized agents may be available.",
108
+ "Use the `list_agents` tool to discover exact names and descriptions before `call_agent`.",
95
109
  "Each agent runs in the background with its own LLM and tools.",
96
110
  "You will receive the agent's summary when it completes.",
97
- "",
98
- "When asked to list agents, list the names below — do NOT search the codebase.",
99
- "",
100
- ]
101
- for name, cfg in self.agents.items():
102
- provider = cfg.provider or "(inherited)"
103
- model = cfg.model or "(inherited)"
104
- desc = cfg.system_prompt[:150] if cfg.system_prompt else "(no description)"
105
- lines.append(f"- **{name}** (provider: {provider}, model: {model}): {desc}")
106
-
107
- lines.extend([
108
111
  "",
109
112
  "**Usage rules:**",
110
113
  "- You CAN dispatch the same agent multiple times with different tasks.",
111
114
  "- Only use the agent whose specialty matches the task. Do NOT use unrelated agents.",
112
115
  "- Batch behavior: you will receive all agent summaries after all agents complete.",
113
116
  "- On agent failure, handle the task yourself. Do NOT re-dispatch failed agents.",
114
- ])
117
+ ]
115
118
 
116
119
  return "\n".join(lines)
117
120
 
@@ -122,7 +125,17 @@ class AgentRegistry:
122
125
  """
123
126
  if name not in self.agents:
124
127
  logger.debug("dispatch rejected: agent '%s' not found", name)
125
- return f"Error: Agent '{name}' not found in configured agents"
128
+ available = ", ".join(sorted(self.agents))
129
+ if available:
130
+ return (
131
+ f"Error: Agent '{name}' not found. "
132
+ f"Available agents: {available}. "
133
+ f"Call list_agents for descriptions."
134
+ )
135
+ return (
136
+ f"Error: Agent '{name}' not found. "
137
+ f"No agents are configured. Call list_agents to verify availability."
138
+ )
126
139
  # Re-dispatch guard: block agents that failed in this cycle
127
140
  if name in self._settled and self._settled[name] in ("error", "timeout"):
128
141
  logger.debug(
@@ -185,7 +198,19 @@ class AgentRegistry:
185
198
  if self._loop is None:
186
199
  self._active.pop(run_id, None)
187
200
  return "Error: Agent registry not initialized (event loop not set)"
188
- asyncio.run_coroutine_threadsafe(_run_and_queue(), self._loop)
201
+
202
+ coro = _run_and_queue()
203
+ try:
204
+ asyncio.run_coroutine_threadsafe(coro, self._loop)
205
+ except Exception as exc:
206
+ # If scheduling fails (for example because the loop was closed),
207
+ # the coroutine object will never be awaited unless explicitly
208
+ # closed. Also remove the runner from active state so status does
209
+ # not remain stuck on "running".
210
+ coro.close()
211
+ self._active.pop(run_id, None)
212
+ logger.exception("failed to schedule agent run: agent='%s' run_id=%d", name, run_id)
213
+ return f"Error: Failed to schedule agent '{name}': {exc}"
189
214
 
190
215
  return run_id
191
216
 
@@ -139,6 +139,23 @@ class AgentRunner:
139
139
  error=f"Agent exceeded {self._timeout}s timeout",
140
140
  )
141
141
 
142
+ # ChatLoop swallows stream/tool failures via on_system_message
143
+ # and returns normally. Promote any captured error into a real
144
+ # error AgentSummary so callers see the cause instead of a
145
+ # placeholder "completed with no summary".
146
+ if callbacks.last_system_error and not callbacks.last_content.strip():
147
+ self.status = "error"
148
+ logger.debug(
149
+ "run failed (captured via on_system_message): agent='%s' run_id=%d error='%s'",
150
+ self.agent_name, self.run_id, callbacks.last_system_error[:200],
151
+ )
152
+ return AgentSummary(
153
+ agent_name=self.agent_name,
154
+ status="error",
155
+ summary="Agent failed before producing output.",
156
+ error=callbacks.last_system_error,
157
+ )
158
+
142
159
  # Completed successfully
143
160
  self.status = "completed"
144
161
  summary_text = self._parse_summary(callbacks.last_content)