ayder-cli 1.0__tar.gz → 1.6.1__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.
- {ayder_cli-1.0 → ayder_cli-1.6.1}/.gitignore +3 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/AGENTS.md +27 -13
- {ayder_cli-1.0 → ayder_cli-1.6.1}/PKG-INFO +176 -12
- {ayder_cli-1.0 → ayder_cli-1.6.1}/README.md +174 -8
- {ayder_cli-1.0 → ayder_cli-1.6.1}/docs/PROJECT_STRUCTURE.md +59 -45
- ayder_cli-1.6.1/docs/config.toml.example +313 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/pyproject.toml +4 -7
- ayder_cli-1.6.1/src/ayder_cli/agents/__init__.py +8 -0
- ayder_cli-1.6.1/src/ayder_cli/agents/callbacks.py +100 -0
- ayder_cli-1.6.1/src/ayder_cli/agents/config.py +14 -0
- ayder_cli-1.6.1/src/ayder_cli/agents/registry.py +226 -0
- ayder_cli-1.6.1/src/ayder_cli/agents/runner.py +165 -0
- ayder_cli-1.6.1/src/ayder_cli/agents/summary.py +24 -0
- ayder_cli-1.6.1/src/ayder_cli/agents/tool.py +66 -0
- ayder_cli-1.6.1/src/ayder_cli/application/__init__.py +3 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/src/ayder_cli/application/execution_policy.py +3 -27
- ayder_cli-1.6.1/src/ayder_cli/application/runtime_factory.py +162 -0
- ayder_cli-1.6.1/src/ayder_cli/cli.py +382 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/src/ayder_cli/cli_callbacks.py +4 -4
- {ayder_cli-1.0 → ayder_cli-1.6.1}/src/ayder_cli/cli_runner.py +46 -34
- ayder_cli-1.6.1/src/ayder_cli/core/cache_monitor.py +91 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/src/ayder_cli/core/config.py +27 -31
- {ayder_cli-1.0 → ayder_cli-1.6.1}/src/ayder_cli/core/config_migration.py +2 -1
- ayder_cli-1.6.1/src/ayder_cli/core/context_manager.py +134 -0
- ayder_cli-1.6.1/src/ayder_cli/core/context_manager_factory.py +36 -0
- ayder_cli-1.0/src/ayder_cli/core/context_manager.py → ayder_cli-1.6.1/src/ayder_cli/core/default_context_manager.py +234 -188
- ayder_cli-1.6.1/src/ayder_cli/core/ollama_context_manager.py +402 -0
- ayder_cli-1.6.1/src/ayder_cli/loops/__init__.py +9 -0
- {ayder_cli-1.0/src/ayder_cli/tui → ayder_cli-1.6.1/src/ayder_cli/loops}/chat_loop.py +124 -38
- {ayder_cli-1.0 → ayder_cli-1.6.1}/src/ayder_cli/parser.py +0 -27
- {ayder_cli-1.0 → ayder_cli-1.6.1}/src/ayder_cli/prompts.py +0 -61
- {ayder_cli-1.0 → ayder_cli-1.6.1}/src/ayder_cli/providers/impl/glm.py +5 -2
- {ayder_cli-1.0 → ayder_cli-1.6.1}/src/ayder_cli/providers/impl/ollama.py +224 -136
- ayder_cli-1.6.1/src/ayder_cli/providers/impl/ollama_inspector.py +74 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/src/ayder_cli/providers/impl/qwen.py +7 -4
- ayder_cli-1.6.1/src/ayder_cli/services/__init__.py +5 -0
- ayder_cli-1.6.1/src/ayder_cli/services/interactions.py +24 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/src/ayder_cli/themes/claude.py +92 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/src/ayder_cli/themes/original.py +39 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/src/ayder_cli/tools/__init__.py +0 -2
- ayder_cli-1.6.1/src/ayder_cli/tools/builtins/memory.py +155 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/src/ayder_cli/tools/builtins/memory_definitions.py +43 -2
- {ayder_cli-1.0 → ayder_cli-1.6.1}/src/ayder_cli/tools/builtins/notes_definitions.py +1 -1
- {ayder_cli-1.0 → ayder_cli-1.6.1}/src/ayder_cli/tools/builtins/tasks_definitions.py +2 -2
- {ayder_cli-1.0 → ayder_cli-1.6.1}/src/ayder_cli/tools/definition.py +25 -1
- {ayder_cli-1.0 → ayder_cli-1.6.1}/src/ayder_cli/tools/normalization.py +0 -4
- ayder_cli-1.6.1/src/ayder_cli/tools/plugin_api.py +22 -0
- ayder_cli-1.6.1/src/ayder_cli/tools/plugin_github.py +146 -0
- ayder_cli-1.6.1/src/ayder_cli/tools/plugin_manager.py +435 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/src/ayder_cli/tools/registry.py +83 -8
- ayder_cli-1.6.1/src/ayder_cli/tui/adapter.py +32 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/src/ayder_cli/tui/app.py +138 -16
- {ayder_cli-1.0 → ayder_cli-1.6.1}/src/ayder_cli/tui/commands.py +137 -34
- {ayder_cli-1.0 → ayder_cli-1.6.1}/src/ayder_cli/tui/screens.py +102 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/src/ayder_cli/tui/widgets.py +194 -22
- {ayder_cli-1.0 → ayder_cli-1.6.1}/src/ayder_cli/ui.py +0 -95
- ayder_cli-1.6.1/tests/agents/test_callbacks.py +76 -0
- ayder_cli-1.6.1/tests/agents/test_config.py +96 -0
- ayder_cli-1.6.1/tests/agents/test_integration.py +241 -0
- ayder_cli-1.6.1/tests/agents/test_registry.py +294 -0
- ayder_cli-1.6.1/tests/agents/test_runner.py +111 -0
- ayder_cli-1.6.1/tests/agents/test_summary.py +59 -0
- ayder_cli-1.6.1/tests/agents/test_tool.py +74 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/tests/application/test_runtime_factory.py +5 -49
- ayder_cli-1.6.1/tests/application/test_service_ui_decoupling.py +129 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/tests/convergence/test_runtime_wiring.py +3 -36
- {ayder_cli-1.0 → ayder_cli-1.6.1}/tests/convergence/test_validation_path.py +1 -1
- ayder_cli-1.6.1/tests/core/test_cache_monitor.py +58 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/tests/core/test_config_coverage.py +18 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/tests/core/test_config_migration.py +30 -0
- ayder_cli-1.6.1/tests/core/test_context_manager_factory.py +54 -0
- ayder_cli-1.6.1/tests/core/test_default_context_manager.py +192 -0
- ayder_cli-1.6.1/tests/core/test_ollama_context_manager.py +339 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/tests/core/test_parameter_aliasing.py +12 -12
- {ayder_cli-1.0 → ayder_cli-1.6.1}/tests/core/test_parser.py +23 -111
- ayder_cli-1.6.1/tests/loops/__init__.py +0 -0
- ayder_cli-1.6.1/tests/loops/test_base.py +33 -0
- ayder_cli-1.6.1/tests/loops/test_chat_loop_hook.py +79 -0
- ayder_cli-1.6.1/tests/providers/__init__.py +0 -0
- ayder_cli-1.6.1/tests/providers/test_glm_async.py +70 -0
- ayder_cli-1.6.1/tests/providers/test_ollama_inspector.py +117 -0
- ayder_cli-1.6.1/tests/providers/test_ollama_native.py +386 -0
- ayder_cli-1.6.1/tests/providers/test_ollama_xml.py +109 -0
- ayder_cli-1.6.1/tests/providers/test_qwen_async.py +77 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/tests/services/test_boundary.py +3 -3
- ayder_cli-1.6.1/tests/services/test_interaction_sink.py +82 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/tests/test_cli.py +22 -175
- {ayder_cli-1.0 → ayder_cli-1.6.1}/tests/test_cli_callbacks.py +2 -2
- {ayder_cli-1.0 → ayder_cli-1.6.1}/tests/test_env_manager.py +3 -3
- ayder_cli-1.6.1/tests/test_memory.py +123 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/tests/test_notes.py +1 -1
- ayder_cli-1.6.1/tests/test_runtime_factory.py +174 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/tests/test_tasks.py +1 -30
- {ayder_cli-1.0 → ayder_cli-1.6.1}/tests/tools/test_definition_discovery.py +2 -20
- {ayder_cli-1.0 → ayder_cli-1.6.1}/tests/tools/test_impl.py +1 -7
- {ayder_cli-1.0 → ayder_cli-1.6.1}/tests/tools/test_impl_coverage.py +1 -7
- ayder_cli-1.6.1/tests/tools/test_plugin_api.py +40 -0
- ayder_cli-1.6.1/tests/tools/test_plugin_github.py +72 -0
- ayder_cli-1.6.1/tests/tools/test_plugin_loading.py +115 -0
- ayder_cli-1.6.1/tests/tools/test_plugin_manager.py +232 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/tests/tools/test_registry.py +7 -6
- {ayder_cli-1.0 → ayder_cli-1.6.1}/tests/tools/test_registry_coverage.py +7 -7
- {ayder_cli-1.0 → ayder_cli-1.6.1}/tests/tools/test_schemas.py +8 -9
- ayder_cli-1.6.1/tests/tui/test_multi_select_screen.py +28 -0
- ayder_cli-1.6.1/tests/tui/test_widgets.py +115 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/tests/ui/test_confirm_screen.py +9 -9
- {ayder_cli-1.0 → ayder_cli-1.6.1}/tests/ui/test_diff_preview.py +1 -66
- {ayder_cli-1.0 → ayder_cli-1.6.1}/tests/ui/test_tui_chat_loop.py +4 -6
- {ayder_cli-1.0 → ayder_cli-1.6.1}/tests/ui/test_tui_helpers.py +0 -4
- ayder_cli-1.6.1/tests/ui/test_tui_temporal_command.py +115 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/tests/ui/test_ui.py +0 -47
- {ayder_cli-1.0 → ayder_cli-1.6.1}/tests/ui/test_ui_coverage.py +0 -76
- ayder_cli-1.0/docs/temporal/CONTRACT_TEMPLATE.md +0 -84
- ayder_cli-1.0/docs/temporal/PRD.md +0 -510
- ayder_cli-1.0/docs/temporal/prompts.md +0 -109
- ayder_cli-1.0/src/ayder_cli/application/__init__.py +0 -11
- ayder_cli-1.0/src/ayder_cli/application/runtime_factory.py +0 -100
- ayder_cli-1.0/src/ayder_cli/application/temporal_contract.py +0 -112
- ayder_cli-1.0/src/ayder_cli/application/temporal_metadata.py +0 -41
- ayder_cli-1.0/src/ayder_cli/cli.py +0 -208
- ayder_cli-1.0/src/ayder_cli/client.py +0 -27
- ayder_cli-1.0/src/ayder_cli/loops/__init__.py +0 -6
- ayder_cli-1.0/src/ayder_cli/loops/base.py +0 -63
- ayder_cli-1.0/src/ayder_cli/loops/config.py +0 -20
- ayder_cli-1.0/src/ayder_cli/memory.py +0 -352
- ayder_cli-1.0/src/ayder_cli/services/__init__.py +0 -12
- ayder_cli-1.0/src/ayder_cli/services/interactions.py +0 -106
- ayder_cli-1.0/src/ayder_cli/services/temporal_client.py +0 -89
- ayder_cli-1.0/src/ayder_cli/services/temporal_worker.py +0 -69
- ayder_cli-1.0/src/ayder_cli/services/temporal_workflow_service.py +0 -98
- ayder_cli-1.0/src/ayder_cli/services/tools/executor.py +0 -220
- ayder_cli-1.0/src/ayder_cli/tools/builtins/dbs_tool.py +0 -160
- ayder_cli-1.0/src/ayder_cli/tools/builtins/dbs_tool_definitions.py +0 -60
- ayder_cli-1.0/src/ayder_cli/tools/builtins/python_editor.py +0 -495
- ayder_cli-1.0/src/ayder_cli/tools/builtins/python_editor_definitions.py +0 -69
- ayder_cli-1.0/src/ayder_cli/tools/builtins/temporal.py +0 -23
- ayder_cli-1.0/src/ayder_cli/tools/builtins/temporal_definitions.py +0 -52
- ayder_cli-1.0/src/ayder_cli/tools/builtins/venv.py +0 -365
- ayder_cli-1.0/src/ayder_cli/tools/builtins/venv_definitions.py +0 -134
- ayder_cli-1.0/src/ayder_cli/tui/adapter.py +0 -87
- ayder_cli-1.0/src/ayder_cli/ui/cli_adapter.py +0 -63
- ayder_cli-1.0/tests/application/test_service_ui_decoupling.py +0 -453
- ayder_cli-1.0/tests/application/test_temporal_contract.py +0 -98
- ayder_cli-1.0/tests/convergence/test_temporal_runtime_wiring.py +0 -70
- ayder_cli-1.0/tests/core/test_context_manager.py +0 -86
- ayder_cli-1.0/tests/loops/test_base.py +0 -132
- ayder_cli-1.0/tests/services/test_confirmation_policy.py +0 -303
- ayder_cli-1.0/tests/services/test_executor_integration.py +0 -419
- ayder_cli-1.0/tests/services/test_interaction_sink.py +0 -339
- ayder_cli-1.0/tests/services/test_temporal_client.py +0 -122
- ayder_cli-1.0/tests/services/test_temporal_worker.py +0 -65
- ayder_cli-1.0/tests/services/test_temporal_workflow_service.py +0 -112
- ayder_cli-1.0/tests/services/tools/test_executor.py +0 -365
- ayder_cli-1.0/tests/test_memory.py +0 -332
- ayder_cli-1.0/tests/test_runtime_factory.py +0 -87
- ayder_cli-1.0/tests/tools/test_dbs_tool.py +0 -153
- ayder_cli-1.0/tests/tools/test_python_editor.py +0 -384
- ayder_cli-1.0/tests/tools/test_temporal_tool.py +0 -120
- ayder_cli-1.0/tests/tools/test_virtualenv.py +0 -521
- ayder_cli-1.0/tests/ui/test_tui_temporal_command.py +0 -82
- {ayder_cli-1.0 → ayder_cli-1.6.1}/.github/workflows/ci.yml +0 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/.github/workflows/python-package.yml +0 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/.python-version +0 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/LICENSE +0 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/docs/cc.png +0 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/src/ayder_cli/__init__.py +0 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/src/ayder_cli/__main__.py +0 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/src/ayder_cli/application/README.md +0 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/src/ayder_cli/application/message_contract.py +0 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/src/ayder_cli/application/validation.py +0 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/src/ayder_cli/console.py +0 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/src/ayder_cli/core/context.py +0 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/src/ayder_cli/core/result.py +0 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/src/ayder_cli/logging_config.py +0 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/src/ayder_cli/process_manager.py +0 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/src/ayder_cli/providers/__init__.py +0 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/src/ayder_cli/providers/base.py +0 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/src/ayder_cli/providers/impl/claude.py +0 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/src/ayder_cli/providers/impl/deepseek.py +0 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/src/ayder_cli/providers/impl/gemini.py +0 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/src/ayder_cli/providers/impl/openai.py +0 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/src/ayder_cli/providers/orchestrator.py +0 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/src/ayder_cli/themes/__init__.py +0 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/src/ayder_cli/tools/builtins/__init__.py +0 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/src/ayder_cli/tools/builtins/filesystem.py +0 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/src/ayder_cli/tools/builtins/filesystem_definitions.py +0 -0
- {ayder_cli-1.0/src/ayder_cli → ayder_cli-1.6.1/src/ayder_cli/tools/builtins}/notes.py +0 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/src/ayder_cli/tools/builtins/process_manager_definitions.py +0 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/src/ayder_cli/tools/builtins/search.py +0 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/src/ayder_cli/tools/builtins/search_definitions.py +0 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/src/ayder_cli/tools/builtins/shell.py +0 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/src/ayder_cli/tools/builtins/shell_definitions.py +0 -0
- {ayder_cli-1.0/src/ayder_cli → ayder_cli-1.6.1/src/ayder_cli/tools/builtins}/tasks.py +0 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/src/ayder_cli/tools/builtins/utils_tools.py +0 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/src/ayder_cli/tools/builtins/utils_tools_definitions.py +0 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/src/ayder_cli/tools/builtins/web.py +0 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/src/ayder_cli/tools/builtins/web_definitions.py +0 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/src/ayder_cli/tools/execution.py +0 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/src/ayder_cli/tools/hooks.py +0 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/src/ayder_cli/tools/schemas.py +0 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/src/ayder_cli/tools/utils.py +0 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/src/ayder_cli/tui/__init__.py +0 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/src/ayder_cli/tui/helpers.py +0 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/src/ayder_cli/tui/parser.py +0 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/src/ayder_cli/tui/theme_manager.py +0 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/src/ayder_cli/tui/types.py +0 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/src/ayder_cli/version.py +0 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/tests/COVERAGE.md +0 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/tests/__init__.py +0 -0
- {ayder_cli-1.0/tests/convergence → ayder_cli-1.6.1/tests/agents}/__init__.py +0 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/tests/application/test_message_contract.py +0 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/tests/client/test_main.py +0 -0
- {ayder_cli-1.0/tests/loops → ayder_cli-1.6.1/tests/convergence}/__init__.py +0 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/tests/convergence/test_execution_policy_parity.py +0 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/tests/core/test_config.py +3 -3
- {ayder_cli-1.0 → ayder_cli-1.6.1}/tests/core/test_config_v2.py +0 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/tests/manual_test_verbose.py +0 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/tests/test_logging_config.py +0 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/tests/test_message_contract.py +0 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/tests/test_process_manager.py +0 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/tests/tools/__init__.py +0 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/tests/tools/test_path_security.py +0 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/tests/tools/test_result.py +0 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/tests/tools/test_search_codebase.py +0 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/tests/tools/test_utils.py +0 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/tests/tools/test_web.py +0 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/tests/ui/test_tui_commands_logging.py +0 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/tests/ui/test_tui_commands_provider.py +0 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/tests/ui/test_tui_widgets.py +0 -0
- {ayder_cli-1.0 → ayder_cli-1.6.1}/tests/ui/test_ui_verbose.py +0 -0
|
@@ -35,6 +35,7 @@ This document provides coding standards, tool configurations, and workflows for
|
|
|
35
35
|
| **pytest-cov** | Code coverage | >=7.0.0 |
|
|
36
36
|
| **ruff** | Fast Python linter | latest |
|
|
37
37
|
| **mypy** | Static type checker | latest |
|
|
38
|
+
| **pyright** | Static type checker (Microsoft) | >=1.1.0 |
|
|
38
39
|
| **uv** | Fast Python package manager | >=0.10.0 |
|
|
39
40
|
| **poethepoet** | Task runner | >=0.24.0 |
|
|
40
41
|
|
|
@@ -61,21 +62,31 @@ ayder-cli/
|
|
|
61
62
|
│ │ ├── context.py # ProjectContext (path sandboxing)
|
|
62
63
|
│ │ └── result.py # ToolSuccess/ToolError types
|
|
63
64
|
│ │
|
|
65
|
+
│ ├── agents/ # Multi-agent system
|
|
66
|
+
│ │ ├── __init__.py # Package exports
|
|
67
|
+
│ │ ├── callbacks.py # AgentCallbacks (ChatCallbacks for agents)
|
|
68
|
+
│ │ ├── config.py # AgentConfig (Pydantic model)
|
|
69
|
+
│ │ ├── registry.py # AgentRegistry (lifecycle management)
|
|
70
|
+
│ │ ├── runner.py # AgentRunner (isolated ChatLoop execution)
|
|
71
|
+
│ │ ├── summary.py # AgentSummary (structured result)
|
|
72
|
+
│ │ └── tool.py # call_agent tool definition + handler
|
|
73
|
+
│ │
|
|
64
74
|
│ ├── application/ # Shared application layer (CLI + TUI)
|
|
65
75
|
│ │ ├── execution_policy.py # ExecutionPolicy, PermissionDeniedError
|
|
66
76
|
│ │ ├── message_contract.py # LLM message format contracts
|
|
67
|
-
│ │ ├── runtime_factory.py # create_runtime()
|
|
77
|
+
│ │ ├── runtime_factory.py # create_runtime() + create_agent_runtime()
|
|
68
78
|
│ │ ├── temporal_contract.py # Temporal workflow contracts
|
|
69
79
|
│ │ ├── temporal_metadata.py # Temporal metadata types
|
|
70
80
|
│ │ └── validation.py # ValidationAuthority, SchemaValidator
|
|
71
81
|
│ │
|
|
72
|
-
│ ├── loops/ # Shared agent loop base
|
|
82
|
+
│ ├── loops/ # Shared agent loop + base classes
|
|
73
83
|
│ │ ├── base.py # AgentLoopBase (iteration, checkpoint, routing)
|
|
84
|
+
│ │ ├── chat_loop.py # ChatLoop (async LLM + tool execution loop)
|
|
74
85
|
│ │ └── config.py # Shared LoopConfig dataclass
|
|
75
86
|
│ │
|
|
76
87
|
│ ├── providers/ # LLM provider implementations
|
|
77
88
|
│ │ ├── base.py # AIProvider protocol, NormalizedStreamChunk
|
|
78
|
-
│ │ ├──
|
|
89
|
+
│ │ ├── orchestrator.py # Factory: create(config) → provider
|
|
79
90
|
│ │ └── impl/ # Individual provider drivers
|
|
80
91
|
│ │ ├── openai.py # OpenAIProvider (base for most drivers)
|
|
81
92
|
│ │ ├── ollama.py # OllamaProvider (native + XML fallback)
|
|
@@ -86,9 +97,7 @@ ayder-cli/
|
|
|
86
97
|
│ │ └── glm.py # GLMNativeProvider (ZhipuAI SDK)
|
|
87
98
|
│ │
|
|
88
99
|
│ ├── services/ # Service layer
|
|
89
|
-
│ │
|
|
90
|
-
│ │ └── tools/
|
|
91
|
-
│ │ └── executor.py # ToolExecutor (CLI confirmation + diff preview)
|
|
100
|
+
│ │ └── interactions.py # InteractionSink protocol (LLM debug events)
|
|
92
101
|
│ │
|
|
93
102
|
│ ├── tools/ # Tool framework + implementations (25 tools)
|
|
94
103
|
│ │ ├── definition.py # ToolDefinition dataclass + auto-discovery
|
|
@@ -108,12 +117,15 @@ ayder-cli/
|
|
|
108
117
|
│ │ ├── utils_tools.py # manage_environment_vars
|
|
109
118
|
│ │ ├── web.py # fetch_web
|
|
110
119
|
│ │ ├── dbs_tool.py # DBS RAG API tool
|
|
111
|
-
│ │
|
|
120
|
+
│ │ ├── temporal.py # Temporal workflow tool
|
|
121
|
+
│ │ ├── tasks.py # Task management (.ayder/tasks/)
|
|
122
|
+
│ │ ├── notes.py # Note management (.ayder/notes/)
|
|
123
|
+
│ │ └── memory.py # Cross-session memory storage
|
|
112
124
|
│ │
|
|
113
125
|
│ ├── tui/ # Textual TUI (main interface)
|
|
114
126
|
│ │ ├── __init__.py # run_tui() entry point
|
|
115
127
|
│ │ ├── app.py # AyderApp main application
|
|
116
|
-
│ │ ├── chat_loop.py #
|
|
128
|
+
│ │ ├── chat_loop.py # Backward-compat re-exports → loops/chat_loop.py
|
|
117
129
|
│ │ ├── commands.py # Slash command handlers (19 commands)
|
|
118
130
|
│ │ ├── helpers.py # TUI helper functions
|
|
119
131
|
│ │ ├── adapter.py # TUIInteractionSink (verbose debug)
|
|
@@ -128,12 +140,9 @@ ayder-cli/
|
|
|
128
140
|
│ │ ├── claude.py # Claude theme CSS
|
|
129
141
|
│ │ └── original.py # Original theme CSS
|
|
130
142
|
│ │
|
|
131
|
-
│ ├── memory.py # Cross-session memory storage
|
|
132
|
-
│ ├── notes.py # Note management (.ayder/notes/)
|
|
133
143
|
│ ├── parser.py # XML/JSON tool call parser
|
|
134
144
|
│ ├── process_manager.py # Background process management
|
|
135
145
|
│ ├── prompts.py # System prompt templates
|
|
136
|
-
│ ├── tasks.py # Task management (.ayder/tasks/)
|
|
137
146
|
│ └── ui.py # Rich terminal UI helpers
|
|
138
147
|
│
|
|
139
148
|
├── tests/ # Test suite (998+ tests)
|
|
@@ -158,7 +167,8 @@ ayder-cli/
|
|
|
158
167
|
| `cli.py` | Entry point, argument parsing |
|
|
159
168
|
| `tui/app.py` | Main TUI application (AyderApp) |
|
|
160
169
|
| `tui/commands.py` | Slash command handlers (19 commands) |
|
|
161
|
-
| `
|
|
170
|
+
| `loops/chat_loop.py` | Async LLM + tool execution loop (ChatLoop + ChatCallbacks protocol) |
|
|
171
|
+
| `tui/chat_loop.py` | Backward-compat re-exports (TuiChatLoop → ChatLoop aliases) |
|
|
162
172
|
| `cli_runner.py` | CLI command execution + sync agent loop |
|
|
163
173
|
| `application/runtime_factory.py` | `create_runtime()` — single composition root for CLI + TUI |
|
|
164
174
|
| `application/execution_policy.py` | Shared permission + tool execution policy |
|
|
@@ -168,7 +178,7 @@ ayder-cli/
|
|
|
168
178
|
| `tools/registry.py` | ToolRegistry: schemas, execution, system prompts, tag filtering |
|
|
169
179
|
| `core/config.py` | Configuration with Pydantic validation |
|
|
170
180
|
| `core/context.py` | ProjectContext for path sandboxing |
|
|
171
|
-
| `providers/
|
|
181
|
+
| `providers/orchestrator.py` | Factory dispatching to correct driver |
|
|
172
182
|
|
|
173
183
|
## Environment Setup
|
|
174
184
|
|
|
@@ -338,6 +348,10 @@ uv run poe typecheck
|
|
|
338
348
|
uv run mypy src/
|
|
339
349
|
```
|
|
340
350
|
|
|
351
|
+
## Type Checking with Pyright
|
|
352
|
+
|
|
353
|
+
Use the **pyright-lsp LSP server** for Pyright diagnostics — do not run `pyright` as a CLI command. The LSP tool provides real-time type errors directly from the language server.
|
|
354
|
+
|
|
341
355
|
### Type Annotation Standards
|
|
342
356
|
|
|
343
357
|
```python
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ayder-cli
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.6.1
|
|
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,14 +19,12 @@ 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.
|
|
22
|
+
Requires-Dist: ollama>=0.6.1
|
|
23
23
|
Requires-Dist: openai
|
|
24
24
|
Requires-Dist: python-dotenv>=1.0.0
|
|
25
25
|
Requires-Dist: rich>=13.0.0
|
|
26
26
|
Requires-Dist: textual>=0.50.0
|
|
27
27
|
Requires-Dist: tiktoken>=0.7.0
|
|
28
|
-
Provides-Extra: temporal
|
|
29
|
-
Requires-Dist: temporalio<1.23.0,>=1.22.0; (python_version < '3.13') and extra == 'temporal'
|
|
30
28
|
Description-Content-Type: text/markdown
|
|
31
29
|
|
|
32
30
|
# ayder-cli
|
|
@@ -54,6 +52,7 @@ Most AI coding assistants require cloud APIs, subscriptions, or heavy IDE plugin
|
|
|
54
52
|
- **7 native drivers** -- Ollama, OpenAI, Anthropic, Gemini, DeepSeek, Qwen (DashScope), and GLM (ZhipuAI). Each driver guarantees native tool calling and streaming support.
|
|
55
53
|
- **Fully local or cloud** -- run locally with Ollama, or connect to any cloud provider.
|
|
56
54
|
- **Agentic workflow** -- the LLM reads files, edits code, runs shell commands, and iterates autonomously with configurable iteration limits per message.
|
|
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.
|
|
57
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.
|
|
58
57
|
- **Minimal dependencies** -- OpenAI SDK, Rich, and Textual. Other provider SDKs are optional.
|
|
59
58
|
|
|
@@ -210,6 +209,7 @@ max_output_tokens = 4096 # Max tokens in LLM response
|
|
|
210
209
|
max_history_messages = 30 # Messages kept in history
|
|
211
210
|
prompt = "STANDARD" # System prompt tier: MINIMAL, STANDARD, EXTENDED
|
|
212
211
|
tool_tags = ["core", "metadata"] # Enabled tool tags (see /plugin)
|
|
212
|
+
agent_timeout = 300 # Seconds before a background agent is cancelled
|
|
213
213
|
|
|
214
214
|
[logging]
|
|
215
215
|
file_enabled = true
|
|
@@ -343,22 +343,34 @@ echo "fix the bug" | ayder -r -w -x
|
|
|
343
343
|
|
|
344
344
|
### Context Management
|
|
345
345
|
|
|
346
|
-
|
|
346
|
+
ayder-cli includes a context manager that automatically keeps your conversation within the model's token budget. The implementation is **driver-aware** — Ollama gets a specialized KV-cache-optimized manager, while cloud providers (Anthropic, OpenAI, Gemini) use a general-purpose tiered manager.
|
|
347
347
|
|
|
348
|
-
|
|
348
|
+
**Ollama-specific optimizations** (automatic when `driver = "ollama"`):
|
|
349
|
+
|
|
350
|
+
- **KV-cache-aware**: Messages are append-only and never reordered. The system prompt is frozen at session start. This preserves Ollama's KV-cache prefix between calls — subsequent prompts process only new tokens instead of recomputing everything.
|
|
351
|
+
- **Real token counts**: Uses Ollama's `prompt_eval_count` and `eval_count` from native API responses instead of estimates. Compaction decisions are based on actual usage, not heuristics.
|
|
352
|
+
- **Cache monitoring**: Tracks `prompt_eval_duration / prompt_eval_count` ratio to detect KV-cache hits (hot/warm/miss). When the cache is hot, compaction is delayed (threshold raised from 70% to 90%) to avoid invalidating it.
|
|
353
|
+
- **Auto-detected context length**: On startup, queries `/api/show` to get the model's real context length instead of relying on `num_ctx`. Falls back to `num_ctx` if detection fails.
|
|
354
|
+
- **Heuristic compaction**: When the context fills up, oldest message units are replaced with a text summary — no LLM call needed.
|
|
355
|
+
- **Native SDK**: Uses `ollama.AsyncClient` directly (not the OpenAI compatibility layer) for full timing data, native thinking support, and `keep_alive=-1` to prevent model unloading.
|
|
356
|
+
|
|
357
|
+
**General-purpose manager** (Anthropic, OpenAI, Gemini, and other drivers):
|
|
358
|
+
|
|
359
|
+
Every message is assigned an importance tier (system > recent user > recent assistant > tool results > old history). When the conversation approaches the token budget, old tool results are compressed (JSON structurally summarized, large text head/tail truncated) and the lowest-priority messages are pruned. Tool call + result pairs are kept as atomic units.
|
|
360
|
+
|
|
361
|
+
The context manager is configured under `[context_manager]` in `config.toml`:
|
|
349
362
|
|
|
350
363
|
| Setting | Default | Description |
|
|
351
364
|
|---------|---------|-------------|
|
|
352
|
-
| `enabled` | `true` | Master switch.
|
|
353
|
-
| `max_context_tokens` | `8192` |
|
|
354
|
-
| `reserve_ratio` | `0.30` | Fraction
|
|
355
|
-
| `
|
|
356
|
-
| `compression_threshold` | `0.50` | When utilization exceeds this ratio, old tool results are compressed. |
|
|
365
|
+
| `enabled` | `true` | Master switch. |
|
|
366
|
+
| `max_context_tokens` | `8192` | Fallback token budget (Ollama auto-detects from model). |
|
|
367
|
+
| `reserve_ratio` | `0.30` | Fraction reserved for the LLM response. |
|
|
368
|
+
| `compaction_threshold` | `0.70` | Utilization ratio that triggers compaction. |
|
|
357
369
|
| `tool_result_compress_age` | `5` | Tool results older than N messages are eligible for compression. |
|
|
358
370
|
| `max_tool_result_length` | `2048` | Maximum character length for a compressed tool result. |
|
|
359
371
|
| `compress_tool_results` | `true` | Enable automatic tool result compression. |
|
|
360
372
|
|
|
361
|
-
|
|
373
|
+
You can also manually manage context with `/save-memory`, `/load-memory`, and `/compact`.
|
|
362
374
|
|
|
363
375
|
### Slash Commands
|
|
364
376
|
|
|
@@ -383,6 +395,9 @@ For small local models (7B-14B), lower `max_context_tokens` to match the model's
|
|
|
383
395
|
| `/load-memory` | Load memory and restore context |
|
|
384
396
|
| `/archive-completed-tasks` | Move completed tasks to `.ayder/task_archive/` |
|
|
385
397
|
| `/temporal` | Start/status Temporal queue worker |
|
|
398
|
+
| `/agent list` | List configured agents and their current status |
|
|
399
|
+
| `/agent <name> <task>` | Dispatch an agent to run a task in the background |
|
|
400
|
+
| `/agent cancel <name>` | Cancel a running agent |
|
|
386
401
|
|
|
387
402
|
### Logging
|
|
388
403
|
|
|
@@ -488,6 +503,155 @@ The tool system:
|
|
|
488
503
|
| **Web** | `fetch_web` |
|
|
489
504
|
| **DBS** | `dbs_tool` (RAG API for DBS-related queries) |
|
|
490
505
|
| **Workflow** | `temporal_workflow` |
|
|
506
|
+
| **Agents** | `call_agent` (dispatch a named agent to run a task in the background) |
|
|
507
|
+
|
|
508
|
+
## Multi-Agent System
|
|
509
|
+
|
|
510
|
+
ayder-cli supports user-defined **specialized agents**: each agent is an independent AI loop with its own LLM provider, model, system prompt, and context window. Agents run as background tasks — they never block the main conversation and their results are automatically injected back when they complete.
|
|
511
|
+
|
|
512
|
+
### How Agents Work
|
|
513
|
+
|
|
514
|
+
```
|
|
515
|
+
Main LLM (your conversation)
|
|
516
|
+
│
|
|
517
|
+
├─ calls `call_agent` tool ─────────────────────────────────┐
|
|
518
|
+
│ OR you type `/agent <name> <task>` │
|
|
519
|
+
│ ▼
|
|
520
|
+
│ AgentRunner (background asyncio task)
|
|
521
|
+
│ ┌─────────────────────────────────┐
|
|
522
|
+
│ │ Isolated ChatLoop │
|
|
523
|
+
│ │ • own LLM provider + model │
|
|
524
|
+
│ │ • own context window │
|
|
525
|
+
│ │ • own ToolRegistry │
|
|
526
|
+
│ │ • auto-approves all tools │
|
|
527
|
+
│ │ • produces <agent-summary> │
|
|
528
|
+
│ └────────────────┬────────────────┘
|
|
529
|
+
│ │ completes
|
|
530
|
+
│ ▼
|
|
531
|
+
│ AgentSummary → _summary_queue
|
|
532
|
+
│
|
|
533
|
+
▼ (next main LLM turn)
|
|
534
|
+
pre_iteration_hook drains queue
|
|
535
|
+
└─ injects AgentSummary as system message into main context
|
|
536
|
+
└─ main LLM sees: "[Agent 'reviewer' completed] FINDINGS: ..."
|
|
537
|
+
```
|
|
538
|
+
|
|
539
|
+
Key properties:
|
|
540
|
+
- **Separate context** — agents have no access to the main conversation history. They receive only their system prompt and the task description.
|
|
541
|
+
- **Non-blocking** — dispatching an agent returns immediately. Both `/agent` and `call_agent` are fire-and-forget.
|
|
542
|
+
- **Concurrent** — multiple agents can run simultaneously, each in its own async task.
|
|
543
|
+
- **Summary injection** — when an agent finishes, its structured `<agent-summary>` block is injected as a system message into the main LLM's context at the start of the next turn.
|
|
544
|
+
- **Timeout** — agents are automatically cancelled after `agent_timeout` seconds (default: 300).
|
|
545
|
+
|
|
546
|
+
### Configuring Agents
|
|
547
|
+
|
|
548
|
+
Add `[agents.<name>]` sections to your `~/.ayder/config.toml`:
|
|
549
|
+
|
|
550
|
+
```toml
|
|
551
|
+
[app]
|
|
552
|
+
provider = "ollama"
|
|
553
|
+
agent_timeout = 300 # Global timeout for all agents (seconds)
|
|
554
|
+
|
|
555
|
+
[llm.ollama]
|
|
556
|
+
driver = "ollama"
|
|
557
|
+
model = "qwen3-coder:latest"
|
|
558
|
+
num_ctx = 65536
|
|
559
|
+
|
|
560
|
+
[llm.anthropic]
|
|
561
|
+
driver = "anthropic"
|
|
562
|
+
api_key = "sk-ant-..."
|
|
563
|
+
model = "claude-sonnet-4-5-20250929"
|
|
564
|
+
num_ctx = 200000
|
|
565
|
+
|
|
566
|
+
# --- Agents ---
|
|
567
|
+
|
|
568
|
+
[agents.code-reviewer]
|
|
569
|
+
system_prompt = """You are a senior code reviewer. Review the code for bugs,
|
|
570
|
+
security issues, and style violations. Be concise and actionable."""
|
|
571
|
+
provider = "anthropic" # Optional: use a different provider than main
|
|
572
|
+
model = "claude-sonnet-4-5-20250929" # Optional: use a different model
|
|
573
|
+
|
|
574
|
+
[agents.test-writer]
|
|
575
|
+
system_prompt = """You are a test engineer. Write comprehensive pytest tests
|
|
576
|
+
for the code provided. Follow existing test patterns in the codebase."""
|
|
577
|
+
# No provider/model → inherits from [app] provider
|
|
578
|
+
|
|
579
|
+
[agents.doc-writer]
|
|
580
|
+
system_prompt = """You are a technical writer. Write clear, concise docstrings
|
|
581
|
+
and inline comments for the code provided."""
|
|
582
|
+
```
|
|
583
|
+
|
|
584
|
+
Each agent field:
|
|
585
|
+
|
|
586
|
+
| Field | Required | Description |
|
|
587
|
+
|-------|----------|-------------|
|
|
588
|
+
| `system_prompt` | Yes | The agent's role and instructions |
|
|
589
|
+
| `provider` | No | LLM provider profile name (inherits from `[app]` if omitted) |
|
|
590
|
+
| `model` | No | Model name override (inherits from provider profile if omitted) |
|
|
591
|
+
|
|
592
|
+
### Using Agents
|
|
593
|
+
|
|
594
|
+
**From the TUI (slash commands):**
|
|
595
|
+
|
|
596
|
+
```
|
|
597
|
+
# List configured agents and their status
|
|
598
|
+
/agent list
|
|
599
|
+
|
|
600
|
+
# Dispatch an agent to review your authentication module
|
|
601
|
+
/agent code-reviewer Review src/auth.py for security issues
|
|
602
|
+
|
|
603
|
+
# Dispatch the test writer for a specific module
|
|
604
|
+
/agent test-writer Write tests for src/api/users.py
|
|
605
|
+
|
|
606
|
+
# Cancel a running agent
|
|
607
|
+
/agent cancel code-reviewer
|
|
608
|
+
```
|
|
609
|
+
|
|
610
|
+
**Via the main LLM (automatic):**
|
|
611
|
+
|
|
612
|
+
When agents are configured, the main LLM is told about them via its system prompt and can call `call_agent` autonomously:
|
|
613
|
+
|
|
614
|
+
```
|
|
615
|
+
You: Review the authentication module and write tests for it.
|
|
616
|
+
|
|
617
|
+
LLM: I'll dispatch two agents to handle this in parallel.
|
|
618
|
+
[calls call_agent: name="code-reviewer", task="Review src/auth.py..."]
|
|
619
|
+
[calls call_agent: name="test-writer", task="Write tests for src/auth.py..."]
|
|
620
|
+
|
|
621
|
+
Both agents are running in the background. I'll incorporate
|
|
622
|
+
their findings when they complete.
|
|
623
|
+
|
|
624
|
+
... (agents run independently) ...
|
|
625
|
+
|
|
626
|
+
LLM: [next turn, after agents complete]
|
|
627
|
+
The code-reviewer found 2 issues: ...
|
|
628
|
+
The test-writer produced 8 new tests: ...
|
|
629
|
+
```
|
|
630
|
+
|
|
631
|
+
**Agent summary format:**
|
|
632
|
+
|
|
633
|
+
Agents end their final response with a structured block that ayder-cli parses:
|
|
634
|
+
|
|
635
|
+
```
|
|
636
|
+
<agent-summary>
|
|
637
|
+
FINDINGS: Found a SQL injection vulnerability in login() and missing input validation in register()
|
|
638
|
+
FILES_CHANGED: none
|
|
639
|
+
RECOMMENDATIONS: Parameterize all DB queries; add Pydantic validators to all endpoints
|
|
640
|
+
</agent-summary>
|
|
641
|
+
```
|
|
642
|
+
|
|
643
|
+
This summary is injected into the main LLM's context as a system message so the main agent can act on it, summarize it for you, or chain it to further work.
|
|
644
|
+
|
|
645
|
+
## Plugins
|
|
646
|
+
|
|
647
|
+
Official plugins (venv, python, dbs, mcp, temporal) are maintained in the **[ayder/ayder-plugins](https://github.com/ayder/ayder-plugins)** repository. Install any plugin directly from GitHub:
|
|
648
|
+
|
|
649
|
+
```bash
|
|
650
|
+
ayder install-plugin https://github.com/ayder/ayder-plugins/tree/main/venv-tools
|
|
651
|
+
ayder install-plugin https://github.com/ayder/ayder-plugins/tree/main/python-tools
|
|
652
|
+
```
|
|
653
|
+
|
|
654
|
+
Plugins can also be hosted in any public GitHub repository — point `install-plugin` at any repo or subdirectory containing a `plugin.toml`.
|
|
491
655
|
|
|
492
656
|
## License
|
|
493
657
|
|
|
@@ -23,6 +23,7 @@ Most AI coding assistants require cloud APIs, subscriptions, or heavy IDE plugin
|
|
|
23
23
|
- **7 native drivers** -- Ollama, OpenAI, Anthropic, Gemini, DeepSeek, Qwen (DashScope), and GLM (ZhipuAI). Each driver guarantees native tool calling and streaming support.
|
|
24
24
|
- **Fully local or cloud** -- run locally with Ollama, or connect to any cloud provider.
|
|
25
25
|
- **Agentic workflow** -- the LLM reads files, edits code, runs shell commands, and iterates autonomously with configurable iteration limits per message.
|
|
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.
|
|
26
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.
|
|
27
28
|
- **Minimal dependencies** -- OpenAI SDK, Rich, and Textual. Other provider SDKs are optional.
|
|
28
29
|
|
|
@@ -179,6 +180,7 @@ max_output_tokens = 4096 # Max tokens in LLM response
|
|
|
179
180
|
max_history_messages = 30 # Messages kept in history
|
|
180
181
|
prompt = "STANDARD" # System prompt tier: MINIMAL, STANDARD, EXTENDED
|
|
181
182
|
tool_tags = ["core", "metadata"] # Enabled tool tags (see /plugin)
|
|
183
|
+
agent_timeout = 300 # Seconds before a background agent is cancelled
|
|
182
184
|
|
|
183
185
|
[logging]
|
|
184
186
|
file_enabled = true
|
|
@@ -312,22 +314,34 @@ echo "fix the bug" | ayder -r -w -x
|
|
|
312
314
|
|
|
313
315
|
### Context Management
|
|
314
316
|
|
|
315
|
-
|
|
317
|
+
ayder-cli includes a context manager that automatically keeps your conversation within the model's token budget. The implementation is **driver-aware** — Ollama gets a specialized KV-cache-optimized manager, while cloud providers (Anthropic, OpenAI, Gemini) use a general-purpose tiered manager.
|
|
316
318
|
|
|
317
|
-
|
|
319
|
+
**Ollama-specific optimizations** (automatic when `driver = "ollama"`):
|
|
320
|
+
|
|
321
|
+
- **KV-cache-aware**: Messages are append-only and never reordered. The system prompt is frozen at session start. This preserves Ollama's KV-cache prefix between calls — subsequent prompts process only new tokens instead of recomputing everything.
|
|
322
|
+
- **Real token counts**: Uses Ollama's `prompt_eval_count` and `eval_count` from native API responses instead of estimates. Compaction decisions are based on actual usage, not heuristics.
|
|
323
|
+
- **Cache monitoring**: Tracks `prompt_eval_duration / prompt_eval_count` ratio to detect KV-cache hits (hot/warm/miss). When the cache is hot, compaction is delayed (threshold raised from 70% to 90%) to avoid invalidating it.
|
|
324
|
+
- **Auto-detected context length**: On startup, queries `/api/show` to get the model's real context length instead of relying on `num_ctx`. Falls back to `num_ctx` if detection fails.
|
|
325
|
+
- **Heuristic compaction**: When the context fills up, oldest message units are replaced with a text summary — no LLM call needed.
|
|
326
|
+
- **Native SDK**: Uses `ollama.AsyncClient` directly (not the OpenAI compatibility layer) for full timing data, native thinking support, and `keep_alive=-1` to prevent model unloading.
|
|
327
|
+
|
|
328
|
+
**General-purpose manager** (Anthropic, OpenAI, Gemini, and other drivers):
|
|
329
|
+
|
|
330
|
+
Every message is assigned an importance tier (system > recent user > recent assistant > tool results > old history). When the conversation approaches the token budget, old tool results are compressed (JSON structurally summarized, large text head/tail truncated) and the lowest-priority messages are pruned. Tool call + result pairs are kept as atomic units.
|
|
331
|
+
|
|
332
|
+
The context manager is configured under `[context_manager]` in `config.toml`:
|
|
318
333
|
|
|
319
334
|
| Setting | Default | Description |
|
|
320
335
|
|---------|---------|-------------|
|
|
321
|
-
| `enabled` | `true` | Master switch.
|
|
322
|
-
| `max_context_tokens` | `8192` |
|
|
323
|
-
| `reserve_ratio` | `0.30` | Fraction
|
|
324
|
-
| `
|
|
325
|
-
| `compression_threshold` | `0.50` | When utilization exceeds this ratio, old tool results are compressed. |
|
|
336
|
+
| `enabled` | `true` | Master switch. |
|
|
337
|
+
| `max_context_tokens` | `8192` | Fallback token budget (Ollama auto-detects from model). |
|
|
338
|
+
| `reserve_ratio` | `0.30` | Fraction reserved for the LLM response. |
|
|
339
|
+
| `compaction_threshold` | `0.70` | Utilization ratio that triggers compaction. |
|
|
326
340
|
| `tool_result_compress_age` | `5` | Tool results older than N messages are eligible for compression. |
|
|
327
341
|
| `max_tool_result_length` | `2048` | Maximum character length for a compressed tool result. |
|
|
328
342
|
| `compress_tool_results` | `true` | Enable automatic tool result compression. |
|
|
329
343
|
|
|
330
|
-
|
|
344
|
+
You can also manually manage context with `/save-memory`, `/load-memory`, and `/compact`.
|
|
331
345
|
|
|
332
346
|
### Slash Commands
|
|
333
347
|
|
|
@@ -352,6 +366,9 @@ For small local models (7B-14B), lower `max_context_tokens` to match the model's
|
|
|
352
366
|
| `/load-memory` | Load memory and restore context |
|
|
353
367
|
| `/archive-completed-tasks` | Move completed tasks to `.ayder/task_archive/` |
|
|
354
368
|
| `/temporal` | Start/status Temporal queue worker |
|
|
369
|
+
| `/agent list` | List configured agents and their current status |
|
|
370
|
+
| `/agent <name> <task>` | Dispatch an agent to run a task in the background |
|
|
371
|
+
| `/agent cancel <name>` | Cancel a running agent |
|
|
355
372
|
|
|
356
373
|
### Logging
|
|
357
374
|
|
|
@@ -457,6 +474,155 @@ The tool system:
|
|
|
457
474
|
| **Web** | `fetch_web` |
|
|
458
475
|
| **DBS** | `dbs_tool` (RAG API for DBS-related queries) |
|
|
459
476
|
| **Workflow** | `temporal_workflow` |
|
|
477
|
+
| **Agents** | `call_agent` (dispatch a named agent to run a task in the background) |
|
|
478
|
+
|
|
479
|
+
## Multi-Agent System
|
|
480
|
+
|
|
481
|
+
ayder-cli supports user-defined **specialized agents**: each agent is an independent AI loop with its own LLM provider, model, system prompt, and context window. Agents run as background tasks — they never block the main conversation and their results are automatically injected back when they complete.
|
|
482
|
+
|
|
483
|
+
### How Agents Work
|
|
484
|
+
|
|
485
|
+
```
|
|
486
|
+
Main LLM (your conversation)
|
|
487
|
+
│
|
|
488
|
+
├─ calls `call_agent` tool ─────────────────────────────────┐
|
|
489
|
+
│ OR you type `/agent <name> <task>` │
|
|
490
|
+
│ ▼
|
|
491
|
+
│ AgentRunner (background asyncio task)
|
|
492
|
+
│ ┌─────────────────────────────────┐
|
|
493
|
+
│ │ Isolated ChatLoop │
|
|
494
|
+
│ │ • own LLM provider + model │
|
|
495
|
+
│ │ • own context window │
|
|
496
|
+
│ │ • own ToolRegistry │
|
|
497
|
+
│ │ • auto-approves all tools │
|
|
498
|
+
│ │ • produces <agent-summary> │
|
|
499
|
+
│ └────────────────┬────────────────┘
|
|
500
|
+
│ │ completes
|
|
501
|
+
│ ▼
|
|
502
|
+
│ AgentSummary → _summary_queue
|
|
503
|
+
│
|
|
504
|
+
▼ (next main LLM turn)
|
|
505
|
+
pre_iteration_hook drains queue
|
|
506
|
+
└─ injects AgentSummary as system message into main context
|
|
507
|
+
└─ main LLM sees: "[Agent 'reviewer' completed] FINDINGS: ..."
|
|
508
|
+
```
|
|
509
|
+
|
|
510
|
+
Key properties:
|
|
511
|
+
- **Separate context** — agents have no access to the main conversation history. They receive only their system prompt and the task description.
|
|
512
|
+
- **Non-blocking** — dispatching an agent returns immediately. Both `/agent` and `call_agent` are fire-and-forget.
|
|
513
|
+
- **Concurrent** — multiple agents can run simultaneously, each in its own async task.
|
|
514
|
+
- **Summary injection** — when an agent finishes, its structured `<agent-summary>` block is injected as a system message into the main LLM's context at the start of the next turn.
|
|
515
|
+
- **Timeout** — agents are automatically cancelled after `agent_timeout` seconds (default: 300).
|
|
516
|
+
|
|
517
|
+
### Configuring Agents
|
|
518
|
+
|
|
519
|
+
Add `[agents.<name>]` sections to your `~/.ayder/config.toml`:
|
|
520
|
+
|
|
521
|
+
```toml
|
|
522
|
+
[app]
|
|
523
|
+
provider = "ollama"
|
|
524
|
+
agent_timeout = 300 # Global timeout for all agents (seconds)
|
|
525
|
+
|
|
526
|
+
[llm.ollama]
|
|
527
|
+
driver = "ollama"
|
|
528
|
+
model = "qwen3-coder:latest"
|
|
529
|
+
num_ctx = 65536
|
|
530
|
+
|
|
531
|
+
[llm.anthropic]
|
|
532
|
+
driver = "anthropic"
|
|
533
|
+
api_key = "sk-ant-..."
|
|
534
|
+
model = "claude-sonnet-4-5-20250929"
|
|
535
|
+
num_ctx = 200000
|
|
536
|
+
|
|
537
|
+
# --- Agents ---
|
|
538
|
+
|
|
539
|
+
[agents.code-reviewer]
|
|
540
|
+
system_prompt = """You are a senior code reviewer. Review the code for bugs,
|
|
541
|
+
security issues, and style violations. Be concise and actionable."""
|
|
542
|
+
provider = "anthropic" # Optional: use a different provider than main
|
|
543
|
+
model = "claude-sonnet-4-5-20250929" # Optional: use a different model
|
|
544
|
+
|
|
545
|
+
[agents.test-writer]
|
|
546
|
+
system_prompt = """You are a test engineer. Write comprehensive pytest tests
|
|
547
|
+
for the code provided. Follow existing test patterns in the codebase."""
|
|
548
|
+
# No provider/model → inherits from [app] provider
|
|
549
|
+
|
|
550
|
+
[agents.doc-writer]
|
|
551
|
+
system_prompt = """You are a technical writer. Write clear, concise docstrings
|
|
552
|
+
and inline comments for the code provided."""
|
|
553
|
+
```
|
|
554
|
+
|
|
555
|
+
Each agent field:
|
|
556
|
+
|
|
557
|
+
| Field | Required | Description |
|
|
558
|
+
|-------|----------|-------------|
|
|
559
|
+
| `system_prompt` | Yes | The agent's role and instructions |
|
|
560
|
+
| `provider` | No | LLM provider profile name (inherits from `[app]` if omitted) |
|
|
561
|
+
| `model` | No | Model name override (inherits from provider profile if omitted) |
|
|
562
|
+
|
|
563
|
+
### Using Agents
|
|
564
|
+
|
|
565
|
+
**From the TUI (slash commands):**
|
|
566
|
+
|
|
567
|
+
```
|
|
568
|
+
# List configured agents and their status
|
|
569
|
+
/agent list
|
|
570
|
+
|
|
571
|
+
# Dispatch an agent to review your authentication module
|
|
572
|
+
/agent code-reviewer Review src/auth.py for security issues
|
|
573
|
+
|
|
574
|
+
# Dispatch the test writer for a specific module
|
|
575
|
+
/agent test-writer Write tests for src/api/users.py
|
|
576
|
+
|
|
577
|
+
# Cancel a running agent
|
|
578
|
+
/agent cancel code-reviewer
|
|
579
|
+
```
|
|
580
|
+
|
|
581
|
+
**Via the main LLM (automatic):**
|
|
582
|
+
|
|
583
|
+
When agents are configured, the main LLM is told about them via its system prompt and can call `call_agent` autonomously:
|
|
584
|
+
|
|
585
|
+
```
|
|
586
|
+
You: Review the authentication module and write tests for it.
|
|
587
|
+
|
|
588
|
+
LLM: I'll dispatch two agents to handle this in parallel.
|
|
589
|
+
[calls call_agent: name="code-reviewer", task="Review src/auth.py..."]
|
|
590
|
+
[calls call_agent: name="test-writer", task="Write tests for src/auth.py..."]
|
|
591
|
+
|
|
592
|
+
Both agents are running in the background. I'll incorporate
|
|
593
|
+
their findings when they complete.
|
|
594
|
+
|
|
595
|
+
... (agents run independently) ...
|
|
596
|
+
|
|
597
|
+
LLM: [next turn, after agents complete]
|
|
598
|
+
The code-reviewer found 2 issues: ...
|
|
599
|
+
The test-writer produced 8 new tests: ...
|
|
600
|
+
```
|
|
601
|
+
|
|
602
|
+
**Agent summary format:**
|
|
603
|
+
|
|
604
|
+
Agents end their final response with a structured block that ayder-cli parses:
|
|
605
|
+
|
|
606
|
+
```
|
|
607
|
+
<agent-summary>
|
|
608
|
+
FINDINGS: Found a SQL injection vulnerability in login() and missing input validation in register()
|
|
609
|
+
FILES_CHANGED: none
|
|
610
|
+
RECOMMENDATIONS: Parameterize all DB queries; add Pydantic validators to all endpoints
|
|
611
|
+
</agent-summary>
|
|
612
|
+
```
|
|
613
|
+
|
|
614
|
+
This summary is injected into the main LLM's context as a system message so the main agent can act on it, summarize it for you, or chain it to further work.
|
|
615
|
+
|
|
616
|
+
## Plugins
|
|
617
|
+
|
|
618
|
+
Official plugins (venv, python, dbs, mcp, temporal) are maintained in the **[ayder/ayder-plugins](https://github.com/ayder/ayder-plugins)** repository. Install any plugin directly from GitHub:
|
|
619
|
+
|
|
620
|
+
```bash
|
|
621
|
+
ayder install-plugin https://github.com/ayder/ayder-plugins/tree/main/venv-tools
|
|
622
|
+
ayder install-plugin https://github.com/ayder/ayder-plugins/tree/main/python-tools
|
|
623
|
+
```
|
|
624
|
+
|
|
625
|
+
Plugins can also be hosted in any public GitHub repository — point `install-plugin` at any repo or subdirectory containing a `plugin.toml`.
|
|
460
626
|
|
|
461
627
|
## License
|
|
462
628
|
|