siada-cli 1.5.3__tar.gz → 1.5.6__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 (299) hide show
  1. {siada_cli-1.5.3 → siada_cli-1.5.6}/PKG-INFO +3 -2
  2. {siada_cli-1.5.3 → siada_cli-1.5.6}/README.md +1 -1
  3. {siada_cli-1.5.3 → siada_cli-1.5.6}/agent_config.yaml +1 -1
  4. {siada_cli-1.5.3 → siada_cli-1.5.6}/pyproject.toml +3 -2
  5. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/agent_hub/coder/prompt/base/prompt_builder.py +13 -2
  6. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/agent_hub/coder/prompt/base/rules.py +2 -1
  7. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/agent_hub/coder/prompt/code_gen_prompt.py +1 -1
  8. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/agent_hub/context_filter/api_message_transfer_filter.py +7 -0
  9. siada_cli-1.5.6/siada/agent_hub/hooks/processors/llm_spinner_processor.py +153 -0
  10. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/agent_hub/hooks/siada_agent_hooks.py +3 -1
  11. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/entrypoint/interaction/controller.py +28 -5
  12. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/entrypoint/interaction/running_config.py +2 -1
  13. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/entrypoint/interaction/turn/conversation_turn.py +99 -73
  14. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/entrypoint/siadahub.py +3 -2
  15. siada_cli-1.5.6/siada/io/banner.py +457 -0
  16. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/io/color_settings.py +38 -11
  17. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/io/components/mdstream.py +4 -3
  18. siada_cli-1.5.6/siada/io/custom_prompt_session.py +653 -0
  19. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/io/io.py +124 -4
  20. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/io/key_bindings.py +35 -7
  21. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/provider/client_factory.py +6 -2
  22. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/provider/default/default_provider.py +10 -19
  23. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/provider/llm_client.py +2 -2
  24. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/provider/openrouter/openroute_provider.py +3 -2
  25. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/support/slash_commands.py +2 -1
  26. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/support/spinner.py +8 -3
  27. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/tools/coder/tool_docs.py +3 -1
  28. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/tools/tool_call_format/formatters.py +3 -3
  29. siada_cli-1.5.3/siada/io/banner.py +0 -148
  30. {siada_cli-1.5.3 → siada_cli-1.5.6}/LICENSE +0 -0
  31. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/__init__.py +0 -0
  32. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/agent_hub/__init__.py +0 -0
  33. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/agent_hub/coder/browser_agent.py +0 -0
  34. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/agent_hub/coder/bug_fix_agent.py +0 -0
  35. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/agent_hub/coder/card_agent.py +0 -0
  36. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/agent_hub/coder/code_gen_agent.py +0 -0
  37. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/agent_hub/coder/fe_gen_agent.py +0 -0
  38. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/agent_hub/coder/issue_review_agent.py +0 -0
  39. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/agent_hub/coder/prompt/__init__.py +0 -0
  40. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/agent_hub/coder/prompt/base/__init__.py +0 -0
  41. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/agent_hub/coder/prompt/base/capabilities.py +0 -0
  42. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/agent_hub/coder/prompt/base/non_interactive.py +0 -0
  43. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/agent_hub/coder/prompt/base/tool_use.py +0 -0
  44. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/agent_hub/coder/prompt/bug_prompt/bug_fix_prompt.py +0 -0
  45. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/agent_hub/coder/prompt/bug_prompt/rules.py +0 -0
  46. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/agent_hub/coder/prompt/card_prompt/__init__.py +0 -0
  47. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/agent_hub/coder/prompt/card_prompt/card_prompt.py +0 -0
  48. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/agent_hub/coder/prompt/card_prompt/rules.py +0 -0
  49. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/agent_hub/coder/prompt/card_prompt.py +0 -0
  50. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/agent_hub/coder/prompt/compact_prompt.py +0 -0
  51. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/agent_hub/coder/prompt/fe_gen_prompt.py +0 -0
  52. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/agent_hub/coder/prompt/issue_review_prompt.py +0 -0
  53. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/agent_hub/coder/select_agent.py +0 -0
  54. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/agent_hub/coder/tracing/__init__.py +0 -0
  55. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/agent_hub/coder/tracing/bug_fix_trace_collector.py +0 -0
  56. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/agent_hub/coder/tracing/logger_tracing_processor.py +0 -0
  57. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/agent_hub/context_filter/__init__.py +0 -0
  58. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/agent_hub/context_filter/base_filter.py +0 -0
  59. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/agent_hub/context_filter/context_capture_filter.py +0 -0
  60. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/agent_hub/context_filter/message_history_capture_filter.py +0 -0
  61. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/agent_hub/context_filter/utils.py +0 -0
  62. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/agent_hub/hooks/__init__.py +0 -0
  63. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/agent_hub/hooks/agent_processors/__init__.py +0 -0
  64. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/agent_hub/hooks/agent_processors/context_track_processor.py +0 -0
  65. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/agent_hub/hooks/context_capture_filter.py +0 -0
  66. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/agent_hub/hooks/io_hooks.py +0 -0
  67. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/agent_hub/hooks/processors/__init__.py +0 -0
  68. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/agent_hub/hooks/processors/checkpointing_processor.py +0 -0
  69. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/agent_hub/hooks/siada_run_hooks.py +0 -0
  70. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/agent_hub/siada_agent.py +0 -0
  71. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/config/__init__.py +0 -0
  72. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/config/agent_config_loader.py +0 -0
  73. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/config/config_loader.py +0 -0
  74. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/config/language_config.py +0 -0
  75. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/config/mcp_config.py +0 -0
  76. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/config/mcp_config_loader.py +0 -0
  77. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/config/model_config.py +0 -0
  78. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/entrypoint/__init__.py +0 -0
  79. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/entrypoint/args_parser/__init__.py +0 -0
  80. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/entrypoint/args_parser/args.py +0 -0
  81. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/entrypoint/interaction/__init__.py +0 -0
  82. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/entrypoint/interaction/base_turn.py +0 -0
  83. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/entrypoint/interaction/config.py +0 -0
  84. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/entrypoint/interaction/nointeractive_controller.py +0 -0
  85. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/entrypoint/interaction/turn/__init__.py +0 -0
  86. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/entrypoint/interaction/turn/command_turn.py +0 -0
  87. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/entrypoint/interaction/turn/interface.py +0 -0
  88. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/entrypoint/interaction/turn/models.py +0 -0
  89. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/entrypoint/interaction/turn/run_turn.py +0 -0
  90. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/entrypoint/interaction/turn/turn_factory.py +0 -0
  91. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/entrypoint/interaction/turn_factory.py +0 -0
  92. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/entrypoint/interaction/turn_models.py +0 -0
  93. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/foundation/__init__.py +0 -0
  94. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/foundation/code_agent_context.py +0 -0
  95. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/foundation/config.py +0 -0
  96. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/foundation/constants.py +0 -0
  97. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/foundation/context.py +0 -0
  98. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/foundation/log_category.py +0 -0
  99. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/foundation/logging.py +0 -0
  100. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/foundation/setting.py +0 -0
  101. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/foundation/siadaignore_controller.py +0 -0
  102. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/foundation/telemetry.py +0 -0
  103. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/foundation/tools/__init__.py +0 -0
  104. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/foundation/tools/fix_result_checker_validator.py +0 -0
  105. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/foundation/tools/get_git_diff.py +0 -0
  106. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/foundation/tools/issue_type_checker_validator.py +0 -0
  107. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/foundation/tools/json_util.py +0 -0
  108. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/foundation/tools/swebench_extractor.py +0 -0
  109. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/io/__init__.py +0 -0
  110. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/io/color_utils.py +0 -0
  111. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/io/components/__init__.py +0 -0
  112. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/io/console_printer.py +0 -0
  113. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/io/notification_command.py +0 -0
  114. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/io/test_banner.py +0 -0
  115. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/models/__init__.py +0 -0
  116. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/models/agent.py +0 -0
  117. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/models/coder/__init__.py +0 -0
  118. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/models/converter.py +0 -0
  119. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/models/model_base_config.py +0 -0
  120. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/models/model_run_config.py +0 -0
  121. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/models/model_setting_converter.py +0 -0
  122. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/provider/__init__.py +0 -0
  123. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/provider/default/coverter.py +0 -0
  124. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/provider/openrouter/__init__.py +0 -0
  125. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/provider/openrouter/coverter.py +0 -0
  126. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/provider/provider_factory.py +0 -0
  127. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/queries/tree-sitter-language-pack/README.md +0 -0
  128. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/queries/tree-sitter-language-pack/arduino-tags.scm +0 -0
  129. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/queries/tree-sitter-language-pack/c-tags.scm +0 -0
  130. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/queries/tree-sitter-language-pack/chatito-tags.scm +0 -0
  131. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/queries/tree-sitter-language-pack/commonlisp-tags.scm +0 -0
  132. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/queries/tree-sitter-language-pack/cpp-tags.scm +0 -0
  133. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/queries/tree-sitter-language-pack/csharp-tags.scm +0 -0
  134. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/queries/tree-sitter-language-pack/d-tags.scm +0 -0
  135. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/queries/tree-sitter-language-pack/dart-tags.scm +0 -0
  136. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/queries/tree-sitter-language-pack/elisp-tags.scm +0 -0
  137. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/queries/tree-sitter-language-pack/elixir-tags.scm +0 -0
  138. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/queries/tree-sitter-language-pack/elm-tags.scm +0 -0
  139. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/queries/tree-sitter-language-pack/gleam-tags.scm +0 -0
  140. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/queries/tree-sitter-language-pack/go-tags.scm +0 -0
  141. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/queries/tree-sitter-language-pack/java-tags.scm +0 -0
  142. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/queries/tree-sitter-language-pack/javascript-tags.scm +0 -0
  143. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/queries/tree-sitter-language-pack/lua-tags.scm +0 -0
  144. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/queries/tree-sitter-language-pack/ocaml-tags.scm +0 -0
  145. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/queries/tree-sitter-language-pack/ocaml_interface-tags.scm +0 -0
  146. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/queries/tree-sitter-language-pack/pony-tags.scm +0 -0
  147. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/queries/tree-sitter-language-pack/properties-tags.scm +0 -0
  148. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/queries/tree-sitter-language-pack/python-tags.scm +0 -0
  149. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/queries/tree-sitter-language-pack/r-tags.scm +0 -0
  150. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/queries/tree-sitter-language-pack/racket-tags.scm +0 -0
  151. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/queries/tree-sitter-language-pack/ruby-tags.scm +0 -0
  152. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/queries/tree-sitter-language-pack/rust-tags.scm +0 -0
  153. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/queries/tree-sitter-language-pack/solidity-tags.scm +0 -0
  154. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/queries/tree-sitter-language-pack/swift-tags.scm +0 -0
  155. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/queries/tree-sitter-language-pack/udev-tags.scm +0 -0
  156. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/queries/tree-sitter-languages/README.md +0 -0
  157. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/queries/tree-sitter-languages/c-tags.scm +0 -0
  158. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/queries/tree-sitter-languages/c_sharp-tags.scm +0 -0
  159. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/queries/tree-sitter-languages/cpp-tags.scm +0 -0
  160. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/queries/tree-sitter-languages/dart-tags.scm +0 -0
  161. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/queries/tree-sitter-languages/elisp-tags.scm +0 -0
  162. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/queries/tree-sitter-languages/elixir-tags.scm +0 -0
  163. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/queries/tree-sitter-languages/elm-tags.scm +0 -0
  164. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/queries/tree-sitter-languages/go-tags.scm +0 -0
  165. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/queries/tree-sitter-languages/hcl-tags.scm +0 -0
  166. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/queries/tree-sitter-languages/java-tags.scm +0 -0
  167. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/queries/tree-sitter-languages/javascript-tags.scm +0 -0
  168. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/queries/tree-sitter-languages/kotlin-tags.scm +0 -0
  169. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/queries/tree-sitter-languages/ocaml-tags.scm +0 -0
  170. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/queries/tree-sitter-languages/ocaml_interface-tags.scm +0 -0
  171. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/queries/tree-sitter-languages/php-tags.scm +0 -0
  172. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/queries/tree-sitter-languages/python-tags.scm +0 -0
  173. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/queries/tree-sitter-languages/ql-tags.scm +0 -0
  174. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/queries/tree-sitter-languages/ruby-tags.scm +0 -0
  175. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/queries/tree-sitter-languages/rust-tags.scm +0 -0
  176. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/queries/tree-sitter-languages/scala-tags.scm +0 -0
  177. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/queries/tree-sitter-languages/typescript-tags.scm +0 -0
  178. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/services/__init__.py +0 -0
  179. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/services/agent_loader.py +0 -0
  180. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/services/anomaly_checker.py +0 -0
  181. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/services/anomaly_detection/anomaly_detector_text_only.py +0 -0
  182. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/services/anomaly_detection/text_anomaly_model.pkl +0 -0
  183. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/services/at_file_recommendation_design_document.md +0 -0
  184. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/services/bug_desc_optimizer.py +0 -0
  185. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/services/checkpointer_recommendation/__init__.py +0 -0
  186. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/services/checkpointer_recommendation/checkpoint_recommend.py +0 -0
  187. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/services/code_context_manager.py +0 -0
  188. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/services/enhanced_fix_result_check.py +0 -0
  189. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/services/execution_trace_collector.py +0 -0
  190. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/services/file_recommendation/__init__.py +0 -0
  191. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/services/file_recommendation/core/__init__.py +0 -0
  192. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/services/file_recommendation/core/completion_engine.py +0 -0
  193. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/services/file_recommendation/core/config.py +0 -0
  194. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/services/file_recommendation/core/file_discovery.py +0 -0
  195. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/services/file_recommendation/core/suggestion.py +0 -0
  196. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/services/file_recommendation/utils/__init__.py +0 -0
  197. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/services/file_recommendation/utils/path_utils.py +0 -0
  198. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/services/file_recommendation/utils/text_utils.py +0 -0
  199. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/services/file_session.py +0 -0
  200. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/services/fix_result_check.py +0 -0
  201. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/services/git_service.py +0 -0
  202. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/services/handle_at_command/README.md +0 -0
  203. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/services/handle_at_command/__init__.py +0 -0
  204. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/services/handle_at_command/exceptions.py +0 -0
  205. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/services/handle_at_command/models.py +0 -0
  206. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/services/handle_at_command/parser.py +0 -0
  207. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/services/handle_at_command/processor.py +0 -0
  208. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/services/handle_at_command/resolver.py +0 -0
  209. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/services/handle_at_command/utils.py +0 -0
  210. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/services/input_processor.py +0 -0
  211. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/services/issue_type_checker.py +0 -0
  212. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/services/mcp_service.py +0 -0
  213. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/services/model_info_service.py +0 -0
  214. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/services/model_wrapper.py +0 -0
  215. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/services/ps_fr_comparator.py +0 -0
  216. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/services/siada_memory.py +0 -0
  217. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/services/siada_runner.py +0 -0
  218. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/services/strict_fix_result_check.py +0 -0
  219. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/services/version_checker/__init__.py +0 -0
  220. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/services/version_checker/base.py +0 -0
  221. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/services/version_checker/handlers/external_handler.py +0 -0
  222. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/services/version_checker/version_checker.py +0 -0
  223. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/session/__init__.py +0 -0
  224. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/session/session_manager.py +0 -0
  225. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/session/session_models.py +0 -0
  226. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/session/task_message_state.py +0 -0
  227. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/support/__init__.py +0 -0
  228. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/support/checkpoint_tracker.py +0 -0
  229. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/support/completer.py +0 -0
  230. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/support/editor.py +0 -0
  231. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/support/envprocessor.py +0 -0
  232. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/support/message_classifier.py +0 -0
  233. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/support/repo.py +0 -0
  234. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/support/usage_utils.py +0 -0
  235. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/tools/__init__.py +0 -0
  236. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/tools/ast/README.md +0 -0
  237. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/tools/ast/ast_tool.py +0 -0
  238. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/tools/ast/models.py +0 -0
  239. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/tools/browser/__init__.py +0 -0
  240. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/tools/browser/browser_action_tool.py +0 -0
  241. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/tools/browser/browsergym_action_tool.py +0 -0
  242. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/tools/browser/browsergym_env.py +0 -0
  243. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/tools/browser/browsergym_utils.py +0 -0
  244. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/tools/browser/chromium_installer.py +0 -0
  245. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/tools/browser/local_server_tool.py +0 -0
  246. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/tools/browser/models.py +0 -0
  247. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/tools/cca/__init__.py +0 -0
  248. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/tools/cca/card_gen.py +0 -0
  249. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/tools/cca/compile_card.py +0 -0
  250. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/tools/cca/get_cca_resource.py +0 -0
  251. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/tools/cca/zip_project.py +0 -0
  252. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/tools/coder/__init__.py +0 -0
  253. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/tools/coder/ask_followup_question.py +0 -0
  254. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/tools/coder/cmd_runner.py +0 -0
  255. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/tools/coder/file_operator.py +0 -0
  256. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/tools/coder/file_search/README.md +0 -0
  257. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/tools/coder/file_search/__init__.py +0 -0
  258. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/tools/coder/file_search/bin/rg-linux-arm64 +0 -0
  259. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/tools/coder/file_search/bin/rg-linux-x64 +0 -0
  260. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/tools/coder/file_search/bin/rg-macos-arm64 +0 -0
  261. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/tools/coder/file_search/bin/rg-macos-x64 +0 -0
  262. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/tools/coder/file_search/bin/rg.exe +0 -0
  263. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/tools/coder/file_search/search.py +0 -0
  264. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/tools/coder/file_search/setup_package.py +0 -0
  265. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/tools/coder/file_search/test_search.py +0 -0
  266. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/tools/coder/files.py +0 -0
  267. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/tools/coder/fix_attempt_completion.py +0 -0
  268. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/tools/coder/issue_review_completion.py +0 -0
  269. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/tools/coder/observation/__init__.py +0 -0
  270. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/tools/coder/observation/error.py +0 -0
  271. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/tools/coder/observation/file_observation.py +0 -0
  272. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/tools/coder/observation/observation.py +0 -0
  273. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/tools/coder/patch_selection_completion.py +0 -0
  274. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/tools/coder/repo_map/__init__.py +0 -0
  275. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/tools/coder/repo_map/dump.py +0 -0
  276. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/tools/coder/repo_map/io.py +0 -0
  277. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/tools/coder/repo_map/repo_map.py +0 -0
  278. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/tools/coder/repo_map/special.py +0 -0
  279. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/tools/coder/repo_map/token_counter.py +0 -0
  280. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/tools/coder/repo_map/waiting.py +0 -0
  281. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/tools/coder/reproduce_completion.py +0 -0
  282. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/tools/coder/run_cmd.py +0 -0
  283. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/tools/coder/test_completion.py +0 -0
  284. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/tools/compression_tool.py +0 -0
  285. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/tools/read_many_files/README.md +0 -0
  286. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/tools/read_many_files/__init__.py +0 -0
  287. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/tools/read_many_files/file_processor.py +0 -0
  288. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/tools/read_many_files/filters.py +0 -0
  289. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/tools/read_many_files/formatters.py +0 -0
  290. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/tools/read_many_files/models.py +0 -0
  291. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/tools/read_many_files_tool.py +0 -0
  292. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/tools/test_failure_analyzer.py +0 -0
  293. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/tools/tool_call_format/__init__.py +0 -0
  294. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/tools/tool_call_format/file_to_language.py +0 -0
  295. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/tools/tool_call_format/formatter_factory.py +0 -0
  296. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/tools/tool_call_format/tool_call_formatter.py +0 -0
  297. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/tools/web/__init__.py +0 -0
  298. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/tools/web/web_crawl.py +0 -0
  299. {siada_cli-1.5.3 → siada_cli-1.5.6}/siada/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: siada-cli
3
- Version: 1.5.3
3
+ Version: 1.5.6
4
4
  Summary: Siada CLI is a Ai Pair Programming Tool in terminal
5
5
  License: Apache-2.0
6
6
  License-File: LICENSE
@@ -20,6 +20,7 @@ Requires-Dist: browsergym (>=0.14.2,<0.15.0)
20
20
  Requires-Dist: click (>=8.2.1,<9.0.0)
21
21
  Requires-Dist: configargparse (>=1.7,<2.0.0)
22
22
  Requires-Dist: diskcache (==5.6.3)
23
+ Requires-Dist: drawille (>=0.1.0,<1.0.0)
23
24
  Requires-Dist: fastapi (>=0.110.0,<1.0.0)
24
25
  Requires-Dist: gitpython (>=3.1.0,<4.0.0)
25
26
  Requires-Dist: grep-ast (>=0.9.0,<1.0.0)
@@ -82,7 +83,7 @@ With Siada CLI you can:
82
83
  ```
83
84
  2. Install siada-cli
84
85
  ```bash
85
- uv tool install --force --python python3.12 --with pip siada-cli@latest --no-build-package pyarrow
86
+ uv tool install --force --python python3.12 --compile --with pip siada-cli@latest
86
87
  ```
87
88
  If the siada-cli directory is not present on the PATH, run the follow command to update the shell
88
89
  ```bash
@@ -29,7 +29,7 @@ With Siada CLI you can:
29
29
  ```
30
30
  2. Install siada-cli
31
31
  ```bash
32
- uv tool install --force --python python3.12 --with pip siada-cli@latest --no-build-package pyarrow
32
+ uv tool install --force --python python3.12 --compile --with pip siada-cli@latest
33
33
  ```
34
34
  If the siada-cli directory is not present on the PATH, run the follow command to update the shell
35
35
  ```bash
@@ -50,7 +50,7 @@ agents:
50
50
 
51
51
  # LLM Configuration
52
52
  llm_config:
53
- provider: "li" # Optional: "li" , "openrouter", "default"
53
+ provider: "openrouter" # Optional: "li" , "openrouter", "default"
54
54
  model_name: "claude-sonnet-4.5"
55
55
  repo_map_tokens: 8192 # repo map max token
56
56
  repo_map_mul_no_files: 16 # Multiple without chat files
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "siada-cli"
3
- version = "1.5.3"
3
+ version = "1.5.6"
4
4
  description = "Siada CLI is a Ai Pair Programming Tool in terminal"
5
5
  packages = [{include = "siada"}, {include = "agent_config.yaml"}]
6
6
  include = ["agent_config.yaml"]
@@ -17,7 +17,7 @@ classifiers = [
17
17
  ]
18
18
 
19
19
  [tool.poetry.scripts]
20
- siada-cli = "siada.entrypoint.siadahub:main"
20
+ siada-cli = "siada.entrypoint.siadahub:main"
21
21
  [tool.poetry.dependencies]
22
22
  python = "^3.12"
23
23
  fastapi = ">=0.110.0,<1.0.0"
@@ -55,6 +55,7 @@ pandas = ">=2.0.0,<3.0.0"
55
55
  scikit-learn = ">=1.3.0,<2.0.0"
56
56
  browsergym = "^0.14.2"
57
57
  gymnasium = "^1.2.0"
58
+ drawille = ">=0.1.0,<1.0.0"
58
59
 
59
60
 
60
61
  [tool.poetry.group.dev.dependencies]
@@ -1,3 +1,4 @@
1
+
1
2
  def build_system_prompt(intro: str, tool_use: str, capabilities: str, rules: str, objective: str, user_memory: str = None, preferred_language: str = "en", agent_name: str = None) -> str:
2
3
  """
3
4
  Common function for building system prompts
@@ -39,7 +40,7 @@ def build_system_prompt(intro: str, tool_use: str, capabilities: str, rules: str
39
40
  return base_prompt
40
41
 
41
42
 
42
- def _get_language_instruction(preferred_language: str, agent_name: str = None) -> str:
43
+ def _get_language_instruction(preferred_language: str='en', agent_name: str = None) -> str:
43
44
  """
44
45
  Get language preference instruction based on user's choice.
45
46
  Only returns instruction if the preferred language differs from the agent's default language.
@@ -54,8 +55,18 @@ def _get_language_instruction(preferred_language: str, agent_name: str = None) -
54
55
  from siada.config.language_config import get_agent_default_language
55
56
 
56
57
  # Get the default language for this agent
57
- default_language = get_agent_default_language(agent_name) if agent_name else "en"
58
+ from siada.config.language_config import DEFAULT_LANGUAGE
59
+ default_language = get_agent_default_language(agent_name) if agent_name else DEFAULT_LANGUAGE
58
60
 
61
+ # if preferred_language == None:
62
+ # return f"""====
63
+
64
+ # PREFERRED LANGUAGE
65
+
66
+ # Use the same language as the user to speak.
67
+
68
+ # """
69
+
59
70
  # Only return instruction if preferred language differs from default
60
71
  if preferred_language != default_language:
61
72
  return f"""====
@@ -23,7 +23,8 @@ def get_rules_section(cwd: str, os_name: str, home_dir: str, interactive_mode: b
23
23
  - When using the regex_search_files tool, craft your regex patterns carefully to balance specificity and flexibility. Based on the user's task you may use it to find code patterns, TODO comments, function definitions, or any text-based information across the project. The results include context, so analyze the surrounding code to better understand the matches. Leverage the regex_search_files tool in combination with other tools for more comprehensive analysis. For example, use it to find specific code patterns, then use the view command of the edit_file tool to examine the full context of interesting matches before using replace_in_file to make informed changes.
24
24
  - When making changes to code, always consider the context in which the code is being used. Ensure that your changes are compatible with the existing codebase and that they follow the project's coding standards and best practices.
25
25
  - When you want to modify a file, use the str_replace or insert command of the edit_file tool directly with the desired changes. You do not need to display the changes before using the tool.
26
- - When executing commands, if you don't see the expected output, assume the terminal executed the command successfully and proceed with the task.
26
+ - NEVER create files unless they're absolutely necessary for achieving your goal. ALWAYS prefer editing an existing file to creating a new one. This includes markdown files.
27
+ - When executing commands, if you don't see the expected output, assume the terminal executed the command successfully and proceed with the task.
27
28
  - The user may provide a file's contents directly in their message, in which case you shouldn't use the tool to get the file contents again since you already have it.
28
29
  - Your goal is to try to accomplish the user's task, NOT engage in a back and forth conversation.
29
30
  - You are STRICTLY FORBIDDEN from starting your messages with "Great", "Certainly", "Okay", "Sure". You should NOT be conversational in your responses, but rather direct and to the point. For example you should NOT say "Great, I've updated the CSS" but instead something like "I've updated the CSS". It is important you be clear and technical in your messages.
@@ -6,7 +6,7 @@ from .base.rules import get_rules_section
6
6
  from .base.prompt_builder import build_system_prompt
7
7
 
8
8
 
9
- def get_system_prompt(cwd: str = "/default/path", interactive_mode: bool = True, user_memory: str = None, preferred_language: str = "en", agent_name: str = None) -> str:
9
+ def get_system_prompt(cwd: str = "/default/path", interactive_mode: bool = True, user_memory: str = None, preferred_language: str = None, agent_name: str = None) -> str:
10
10
  """
11
11
  生成系统提示词
12
12
 
@@ -496,6 +496,13 @@ class ApiMessageTransferFilter:
496
496
  "model": model,
497
497
  "messages": _build_compact_messages(history_to_compact=history_to_compact),
498
498
  }
499
+
500
+ # Only add empty tools list for Anthropic/Claude models with default provider to avoid litellm error
501
+ if provider == "default" and (
502
+ "anthropic" in model.lower() or "claude" in model.lower()
503
+ ):
504
+ complete_kwargs["tools"] = []
505
+
499
506
  response = await llm_client.completion(**complete_kwargs)
500
507
 
501
508
  if response and response.choices and response.choices[0].message:
@@ -0,0 +1,153 @@
1
+ """
2
+ LLM Spinner Processor
3
+
4
+ Provides visual feedback during LLM calls by displaying a waiting spinner.
5
+ """
6
+
7
+ from typing import Optional
8
+ from agents import Agent, ModelResponse, AgentHooks, TContext, TResponseInputItem, RunContextWrapper
9
+ from siada.foundation.code_agent_context import CodeAgentContext
10
+ from siada.support.spinner import WaitingSpinner
11
+
12
+
13
+ class LLMSpinnerProcessor(AgentHooks):
14
+ """
15
+ Processor that displays a waiting spinner during LLM calls.
16
+
17
+ This processor:
18
+ - Starts a spinner when LLM call begins (on_llm_start)
19
+ - Stops the spinner when LLM call completes (on_llm_end)
20
+ """
21
+
22
+ def __init__(self, spinner_text: str = "Waiting for LLM...", text_color: str = "#79B8FF"):
23
+ """
24
+ Initialize the LLM spinner processor.
25
+
26
+ Args:
27
+ spinner_text: Text to display with the spinner
28
+ text_color: Color of the spinner text (hex or color name)
29
+ """
30
+ self.spinner_text = spinner_text
31
+ self.text_color = text_color
32
+ self.spinner: Optional[WaitingSpinner] = None
33
+
34
+ async def on_llm_start(
35
+ self,
36
+ context: RunContextWrapper[CodeAgentContext],
37
+ agent: Agent[TContext],
38
+ system_prompt: Optional[str],
39
+ input_items: list[TResponseInputItem],
40
+ ) -> None:
41
+ """
42
+ Called just before invoking the LLM.
43
+ Starts the waiting spinner and injects it into session for external access.
44
+ Only starts spinner in interactive mode.
45
+ """
46
+ # Only start spinner if we're in interactive mode
47
+ if hasattr(context.context, 'session') and context.context.session and context.context.session.siada_config:
48
+ running_config = getattr(context.context.session, 'siada_config', None)
49
+
50
+ # Check if we're in interactive mode
51
+ if not running_config or not getattr(running_config, 'interactive', True):
52
+ # Non-interactive mode, skip spinner
53
+ return
54
+
55
+ # Get agent name for personalized message
56
+ agent_name = getattr(context.context.session.siada_config, 'agent_name', 'Agent')
57
+ spinner_text = f"Thinking ..."
58
+
59
+ # Get IO instance to pass to spinner for panel status checking
60
+ io_instance = getattr(running_config, 'io', None) if running_config else None
61
+
62
+ # Create and start spinner with IO instance
63
+ self.spinner = WaitingSpinner(spinner_text, text_color=self.text_color, io_instance=io_instance)
64
+ self.spinner.start()
65
+
66
+ # Inject spinner into session state for external access
67
+ # This allows _stop_waiting_spinner() in conversation_turn.py to stop it
68
+ # when the first stream data arrives
69
+ context.context.session.state.spinner = self.spinner
70
+
71
+ async def on_llm_end(
72
+ self,
73
+ context: RunContextWrapper[CodeAgentContext],
74
+ agent: Agent[TContext],
75
+ response: ModelResponse,
76
+ ) -> None:
77
+ """
78
+ Called immediately after the LLM call returns.
79
+ Stops the waiting spinner with fallback cleanup.
80
+
81
+ This method ensures spinner is stopped in all cases:
82
+ 1. Stops self.spinner (processor's own reference)
83
+ 2. Stops session.state.spinner (external reference used by conversation_turn)
84
+ 3. Stops session.spinner (legacy reference if exists)
85
+ """
86
+ # Stop processor's own spinner reference
87
+ if self.spinner is not None:
88
+ try:
89
+ self.spinner.stop()
90
+ except Exception:
91
+ pass # Ignore stop errors
92
+ finally:
93
+ self.spinner = None
94
+
95
+ # Fallback: Also stop spinner in session.state (used by conversation_turn._stop_waiting_spinner)
96
+ if hasattr(context.context, 'session') and context.context.session:
97
+ session = context.context.session
98
+
99
+ # Stop session.state.spinner
100
+ if hasattr(session, 'state') and hasattr(session.state, 'spinner'):
101
+ spinner = session.state.spinner
102
+ if spinner:
103
+ try:
104
+ spinner.stop()
105
+ except Exception:
106
+ pass # Ignore stop errors
107
+ finally:
108
+ session.state.spinner = None
109
+
110
+ # Stop session.spinner (legacy reference)
111
+ if hasattr(session, 'spinner') and session.spinner:
112
+ try:
113
+ session.spinner.stop()
114
+ except Exception:
115
+ pass # Ignore stop errors
116
+ finally:
117
+ session.spinner = None
118
+
119
+ async def on_agent_start(
120
+ self,
121
+ context: RunContextWrapper[CodeAgentContext],
122
+ agent: Agent[TContext],
123
+ ) -> None:
124
+ """Called when an agent starts execution."""
125
+ pass
126
+
127
+ async def on_agent_end(
128
+ self,
129
+ context: RunContextWrapper[CodeAgentContext],
130
+ agent: Agent[TContext],
131
+ output: any,
132
+ ) -> None:
133
+ """Called when an agent completes execution."""
134
+ pass
135
+
136
+ async def on_tool_start(
137
+ self,
138
+ context: RunContextWrapper[CodeAgentContext],
139
+ agent: Agent[TContext],
140
+ tool: any,
141
+ ) -> None:
142
+ """Called before a tool is executed."""
143
+ pass
144
+
145
+ async def on_tool_end(
146
+ self,
147
+ context: RunContextWrapper[CodeAgentContext],
148
+ agent: Agent[TContext],
149
+ tool: any,
150
+ result: str,
151
+ ) -> None:
152
+ """Called after a tool completes execution."""
153
+ pass
@@ -2,6 +2,7 @@ from typing import Optional, List, Any
2
2
  from agents import Agent, ModelResponse, AgentHooks, TContext, TResponseInputItem, RunContextWrapper, Tool
3
3
  from siada.foundation.code_agent_context import CodeAgentContext
4
4
  from siada.agent_hub.hooks.agent_processors.context_track_processor import ContextTrackProcessor
5
+ from siada.agent_hub.hooks.processors.llm_spinner_processor import LLMSpinnerProcessor
5
6
 
6
7
 
7
8
  class SiadaAgentHooks(AgentHooks):
@@ -23,6 +24,7 @@ class SiadaAgentHooks(AgentHooks):
23
24
  # Default processors
24
25
  self.processors = [
25
26
  ContextTrackProcessor(),
27
+ LLMSpinnerProcessor(), # Add spinner for LLM calls
26
28
  # Add more processors here as needed
27
29
  ]
28
30
  else:
@@ -118,4 +120,4 @@ class SiadaAgentHooks(AgentHooks):
118
120
  processor: The AgentHooks processor to remove
119
121
  """
120
122
  if processor in self.processors:
121
- self.processors.remove(processor)
123
+ self.processors.remove(processor)
@@ -8,6 +8,7 @@ Separates core interaction logic from main entry point for better code organizat
8
8
  import time
9
9
  import asyncio
10
10
  import threading
11
+ from regex import T
11
12
  from siada.session.session_models import RunningSession
12
13
  from siada import __version__
13
14
  from siada.entrypoint.interaction.running_config import RunningConfig
@@ -44,6 +45,7 @@ class Controller:
44
45
  self._preload_success = False
45
46
  # Pre-load agent class asynchronously to optimize first-time execution
46
47
  self._start_preload_agent()
48
+ self.need_show_announcements_welcome_panel:bool = True
47
49
 
48
50
  def _start_preload_agent(self):
49
51
  """
@@ -98,7 +100,7 @@ class Controller:
98
100
  if show_spinner and not self._preload_complete.is_set():
99
101
  if self.config.io and self.config.io.pretty:
100
102
  message = f"Loading {self.config.agent_name} agent..."
101
- spinner = WaitingSpinner(message, text_color="cyan")
103
+ spinner = WaitingSpinner(message, text_color="#79B8FF")
102
104
  spinner.start()
103
105
 
104
106
  if self._preload_complete.wait(timeout=timeout):
@@ -151,7 +153,7 @@ class Controller:
151
153
 
152
154
  def run(self) -> int:
153
155
  session = self.session
154
- display_rule = True
156
+ display_rule = False
155
157
  pending_input = None # Pending input to process in next iteration
156
158
 
157
159
  while True:
@@ -235,8 +237,14 @@ class Controller:
235
237
  break
236
238
 
237
239
  def get_announcements(self):
240
+ import os
241
+
238
242
  lines = []
239
- lines.append(f"Siada CLI v{__version__} supported by Li Auto")
243
+ # lines.append(f"Siada CLI v{__version__} supported by Li Auto")
244
+
245
+ # Add current working directory
246
+ current_dir = os.getcwd()
247
+ lines.append(f"Working Directory: {current_dir}")
240
248
 
241
249
  output = f"Agent: {self.config.agent_name}, Provider: {self.config.llm_config.provider}, Model: {self.config.llm_config.model_name}"
242
250
 
@@ -259,8 +267,23 @@ class Controller:
259
267
  return lines
260
268
 
261
269
  def show_announcements(self):
262
- for line in self.get_announcements():
263
- self.config.io.print_info(line)
270
+ # Clear terminal using system clear command
271
+ import os
272
+ os.system('clear' if os.name != 'nt' else 'cls')
273
+ if self.need_show_announcements_welcome_panel:
274
+ # only once
275
+ self.need_show_announcements_welcome_panel = False
276
+ self.show_announcements_welcome_panel()
277
+ else:
278
+ for line in self.get_announcements():
279
+ self.config.io.print_info(line)
280
+
281
+ def show_announcements_welcome_panel(self, console: Console = None):
282
+ from siada.io.banner import BannerDisplay
283
+
284
+ announcements = self.get_announcements()
285
+ BannerDisplay.show_welcome_panel(announcements=announcements, console=console
286
+ , siada_version=f"Siada CLI v{__version__}")
264
287
 
265
288
  def keyboard_interrupt(self):
266
289
  # Ensure cursor is visible on exit
@@ -37,4 +37,5 @@ class RunningConfig:
37
37
  mcp_service = None # MCP service instance (will be initialized later)
38
38
  auto_compact: bool = True # Enable automatic context compression
39
39
  siadaignore_controller: Optional[SiadaIgnoreController] = None # SiadaIgnore controller for file access control
40
- preferred_language: str = "en" # Preferred language for AI responses: "en" (English) or "zh-CN" (Chinese)
40
+ preferred_language: str = None # Preferred language for AI responses: "en" (English) or "zh-CN" (Chinese)
41
+ startup_warning: Optional[str] = None # Warning message to display at startup (for Textual mode)
@@ -39,11 +39,11 @@ REASONING_TAG = "thinking-content-" + "7bbeb8e1441453ad999a0bbba8a46d4b"
39
39
  SPLIT_TAG = "\n--------------\n"
40
40
  # Output formatting
41
41
 
42
- REASONING_START = "► **THINKING**"
42
+ REASONING_START = "▶ **THINKING**" # ►
43
43
 
44
- REASONING_END = "► **ANSWER**"
44
+ REASONING_END = "▶ **ANSWER**"
45
45
 
46
- TOOL_CALL_START = "► **TOOL USE**"
46
+ TOOL_CALL_START = "▶ **TOOL USE**"
47
47
 
48
48
 
49
49
  class ConversationTurn(RunTurn):
@@ -267,7 +267,7 @@ class ConversationTurn(RunTurn):
267
267
  ):
268
268
  if not self.got_reasoning_part and stream_data.delta:
269
269
  self.got_reasoning_part = True
270
- self.print_split_line()
270
+ # self.print_split_line()
271
271
  delta_text = f"\n{REASONING_START}\n\n{stream_data.delta}"
272
272
  self.response_content += delta_text
273
273
  else:
@@ -289,8 +289,8 @@ class ConversationTurn(RunTurn):
289
289
  elif isinstance(stream_data, ResponseTextDeltaEvent):
290
290
  if not self.got_content_part and stream_data.delta:
291
291
  self.got_content_part = True
292
- if not self.got_reasoning_part:
293
- self.print_split_line()
292
+ # if not self.got_reasoning_part:
293
+ # self.print_split_line()
294
294
  delta_text = f"\n\n{REASONING_END}\n\n{stream_data.delta}"
295
295
  self.response_content += delta_text
296
296
  else:
@@ -368,10 +368,19 @@ class ConversationTurn(RunTurn):
368
368
  ]
369
369
 
370
370
  self.current_active_call_id = call_id
371
- self.print_split_line()
372
- self.config.io.print_tool_call(
373
- f"{TOOL_CALL_START}\n\nSiada wants to use the tool: {tool_name}\n"
371
+ # self.print_split_line()
372
+
373
+ # Stage 1: Print tool name (use append=False to avoid accumulating the header)
374
+ self.config.io.print_tool_call_all_stages(
375
+ f"Siada wants to use the tool: {tool_name}.\n",
376
+ final=False,
377
+ append=True
374
378
  )
379
+
380
+ # Original method (commented out for reference)
381
+ # self.config.io.print_tool_call(
382
+ # f"{TOOL_CALL_START}\n\nSiada wants to use the tool: {tool_name}\n"
383
+ # )
375
384
 
376
385
  elif isinstance(
377
386
  stream_data, ResponseFunctionCallArgumentsDeltaEvent
@@ -387,35 +396,35 @@ class ConversationTurn(RunTurn):
387
396
  )
388
397
 
389
398
  # if supports streaming, update the tool call mdstream
390
- if tool_call_formatter.supports_streaming():
391
- content, is_complete = tool_call_formatter.format_input(
392
- self.current_active_call_id,
393
- self.tool_calls[self.current_active_call_id]["name"],
394
- self.tool_calls[self.current_active_call_id][
395
- "arguments"
396
- ],
397
- )
398
-
399
- # compute the content_delta
400
- arguments_delta = content[
401
- len(
402
- self.tool_calls[self.current_active_call_id][
403
- "arguments_render"
404
- ]
405
- ) :
406
- ]
407
- self.tool_calls[self.current_active_call_id][
408
- "arguments_render"
409
- ] = content
410
-
411
- if self.current_active_call_id in self.tool_call_mdstreams:
412
- self.tool_call_mdstreams[
413
- self.current_active_call_id
414
- ].update(content, final=False)
415
- else:
416
- self.config.io.console.print(
417
- arguments_delta, sep="", end=""
418
- )
399
+ # if tool_call_formatter.supports_streaming():
400
+ # content, is_complete = tool_call_formatter.format_input(
401
+ # self.current_active_call_id,
402
+ # self.tool_calls[self.current_active_call_id]["name"],
403
+ # self.tool_calls[self.current_active_call_id][
404
+ # "arguments"
405
+ # ],
406
+ # )
407
+
408
+ # # compute the content_delta
409
+ # arguments_delta = content[
410
+ # len(
411
+ # self.tool_calls[self.current_active_call_id][
412
+ # "arguments_render"
413
+ # ]
414
+ # ) :
415
+ # ]
416
+ # self.tool_calls[self.current_active_call_id][
417
+ # "arguments_render"
418
+ # ] = content
419
+
420
+ # if self.current_active_call_id in self.tool_call_mdstreams:
421
+ # self.tool_call_mdstreams[
422
+ # self.current_active_call_id
423
+ # ].update(content, final=False)
424
+ # else:
425
+ # self.config.io.console.print(
426
+ # arguments_delta, sep="", end=""
427
+ # )
419
428
 
420
429
  elif isinstance(stream_data, ResponseOutputItemDoneEvent):
421
430
  if isinstance(stream_data.item, ResponseFunctionToolCall):
@@ -431,33 +440,48 @@ class ConversationTurn(RunTurn):
431
440
  call_id, tool_name, full_arguments
432
441
  )
433
442
  style = tool_call_formatter.get_style()
443
+
444
+ # Stage 2: Print tool description/parameters
445
+ self.config.io.advance_tool_call_stage()
446
+ self.config.io.print_tool_call_all_stages(
447
+ content,
448
+ final=True
449
+ )
450
+
451
+ # Original streaming/non-streaming handling (commented out)
434
452
  # if not streaming, only create the mdstream and update the final content
435
- if tool_call_formatter.supports_streaming():
436
- # process the last tool call stream, stop the live
437
- if call_id in self.tool_call_mdstreams:
438
- self.tool_call_mdstreams[call_id].update(
439
- content,
440
- final=True,
441
- )
442
- if call_id in self.tool_call_mdstreams:
443
- del self.tool_call_mdstreams[call_id]
444
- else:
445
- if style == "markdown" and self.config.io.pretty:
446
- self.tool_call_mdstreams[call_id] = (
447
- self.get_response_mdstream()
448
- )
449
- self.tool_call_mdstreams[call_id].update(
450
- content, final=True
451
- )
452
- if call_id in self.tool_call_mdstreams:
453
- del self.tool_call_mdstreams[call_id]
454
- else:
455
- self.config.io.print_tool_call(content)
453
+ # if tool_call_formatter.supports_streaming():
454
+ # # process the last tool call stream, stop the live
455
+ # if call_id in self.tool_call_mdstreams:
456
+ # self.tool_call_mdstreams[call_id].update(
457
+ # content,
458
+ # final=True,
459
+ # )
460
+ # if call_id in self.tool_call_mdstreams:
461
+ # del self.tool_call_mdstreams[call_id]
462
+ # else:
463
+ # if style == "markdown" and self.config.io.pretty:
464
+ # self.tool_call_mdstreams[call_id] = (
465
+ # self.get_response_mdstream()
466
+ # )
467
+ # self.tool_call_mdstreams[call_id].update(
468
+ # content, final=True
469
+ # )
470
+ # if call_id in self.tool_call_mdstreams:
471
+ # del self.tool_call_mdstreams[call_id]
472
+ # else:
473
+ # self.config.io.print_tool_call(content)
456
474
 
457
475
  elif isinstance(stream_data, ResponseCompletedEvent):
458
- # Print context usage after each model response
459
- # Get usage from the event if available
476
+ # Stage 3: Close the Live+Panel display without adding token info
460
477
  usage = stream_data.response.usage if hasattr(stream_data, 'response') and stream_data.response else None
478
+
479
+ # Close the Live+Panel display (don't add token info to panel)
480
+ if hasattr(self.config.io, '_tool_call_stages') and self.config.io._tool_call_stages:
481
+ # Just close the panel without adding token info
482
+ self.config.io.print_tool_call_all_stages("", final=True, append=False)
483
+
484
+ # Print context usage using original method (outside the panel)
461
485
  self._print_context_usage(usage=usage)
462
486
 
463
487
  elif isinstance(event, RunItemStreamEvent):
@@ -467,7 +491,7 @@ class ConversationTurn(RunTurn):
467
491
  if call_id:
468
492
  if call_id in self.tool_calls:
469
493
  tool_name = self.tool_calls[call_id]["name"]
470
- self.print_split_line()
494
+ # self.print_split_line()
471
495
  output = stream_data.output
472
496
  if isinstance(output, FunctionCallResult):
473
497
  self.config.io.print_tool_result(
@@ -510,9 +534,11 @@ class ConversationTurn(RunTurn):
510
534
  )
511
535
 
512
536
  if should_render or final:
513
- self.mdstream.update(
514
- processed_content if processed_content else "", final
515
- )
537
+ content_to_update = processed_content if processed_content else ""
538
+ # When final is True, ensure content ends with newline
539
+ if final and content_to_update and not content_to_update.endswith('\n'):
540
+ content_to_update += '\n'
541
+ self.mdstream.update(content_to_update, final)
516
542
  # If should_render is False, pause mdstream.update temporarily
517
543
  else:
518
544
  if not self.config.io.pretty:
@@ -534,12 +560,12 @@ class ConversationTurn(RunTurn):
534
560
  self.start_time = self._get_timestamp()
535
561
 
536
562
  # Initialize spinner and inject into session for external access
537
- if self.config.io.pretty:
538
- spinner = WaitingSpinner(
539
- f"Waiting for Agent {self.config.agent_name}..."
540
- )
541
- # Inject spinner into session state for external access (e.g., stop from outside)
542
- self.session.state.spinner = spinner
563
+ # if self.config.io.pretty:
564
+ # spinner = WaitingSpinner(
565
+ # f"Waiting for Agent {self.config.agent_name}...", text_color="#79B8FF"
566
+ # )
567
+ # # Inject spinner into session state for external access (e.g., stop from outside)
568
+ # self.session.state.spinner = spinner
543
569
 
544
570
  # Reset event flags at the beginning of each execution
545
571
  self._cleanup_done.clear()
@@ -659,7 +685,7 @@ class ConversationTurn(RunTurn):
659
685
 
660
686
  def get_response_mdstream(self):
661
687
  mdargs = dict(
662
- style=self.config.running_color_settings.assistant_output_color,
688
+ style=self.config.running_color_settings.assistant_output_color,
663
689
  code_theme=self.config.running_color_settings.code_theme,
664
690
  inline_code_lexer="text",
665
691
  )
@@ -694,7 +720,7 @@ class ConversationTurn(RunTurn):
694
720
  from rich.text import Text
695
721
 
696
722
  # Create styled text with a dim style for subtle display
697
- text = Text(message, style="dim cyan")
723
+ text = Text(message, style="dim #5B9BD5") # rule
698
724
  aligned_text = Align.right(text)
699
725
 
700
726
  self.config.io.console.print(aligned_text)