From b050a93fb799b13d967d7fc5be722beb8274ae21 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 1 Dec 2025 14:36:26 +0000 Subject: [PATCH 1/2] Initial plan From 7d9614a7a97990d3e61030ba95d277c9ecaaa0a0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 1 Dec 2025 14:43:32 +0000 Subject: [PATCH 2/2] Address all code review suggestions in a single commit Co-authored-by: 0xba1a <2942888+0xba1a@users.noreply.github.com> --- src/microbots/MicroBot.py | 6 +++--- src/microbots/llm/ollama_local.py | 12 ++++++------ test/llm/conftest.py | 2 +- test/llm/test_llm.py | 4 ++-- test/llm/test_ollama_local.py | 5 ++--- test/llm/test_openai_api.py | 4 ++-- 6 files changed, 16 insertions(+), 17 deletions(-) diff --git a/src/microbots/MicroBot.py b/src/microbots/MicroBot.py index 0cf566c..5b9ead6 100644 --- a/src/microbots/MicroBot.py +++ b/src/microbots/MicroBot.py @@ -28,11 +28,11 @@ Don't add any chat or extra messages outside the json format. Because the system will parse only the json response. The properties ( task_done, thoughts, command ) are mandatory on each response. -after each command, the system will execute the command respond you the output. -ensure to run only one command at a time. +after each command, the system will execute the command and respond to you with the output. +Ensure to run only one command at a time. NEVER use 'ls -R', 'tree', or 'find' without -maxdepth on large repos - use targeted paths like 'ls drivers/block/' to avoid exceeding context limits. Use specific patterns: 'find -name "*.c" -maxdepth 2' instead of recursive exploration. -No human in involved in the task. So, don't seek human intervention. +No human is involved in the task. So, don't seek human intervention. """ diff --git a/src/microbots/llm/ollama_local.py b/src/microbots/llm/ollama_local.py index 86214eb..e2fbcec 100644 --- a/src/microbots/llm/ollama_local.py +++ b/src/microbots/llm/ollama_local.py @@ -20,7 +20,7 @@ # LOCAL_MODEL_PORT=11434 # ``` # -# To use with Microbot, define you Microbot as following +# To use with Microbot, define your Microbot as following # ```python # bot = Microbot( # model="ollama-local/codellama:latest", @@ -53,14 +53,14 @@ def __init__(self, system_prompt, model_name=LOCAL_MODEL_NAME, model_port=LOCAL_ self.messages = [{"role": "system", "content": system_prompt}] if not self.model_name or not self.model_port: - raise ValueError("LOCAL_MODEL_NAME and LOCAL_MODEL_PORT environment variables must be set for or passed as arguments OllamaLocal.") + raise ValueError("LOCAL_MODEL_NAME and LOCAL_MODEL_PORT environment variables must be set or passed as arguments to OllamaLocal.") # Set these values here. This logic will be handled in the parent class. self.max_retries = max_retries self.retries = 0 def ask(self, message) -> LLMAskResponse: - self.retries = 0 # reset retries for each ask. Handled in parent class. + self.retries = 0 # reset retries for each ask. Handled in parent class. self.messages.append({"role": "user", "content": message}) @@ -99,11 +99,11 @@ def _send_request_to_local_model(self, messages): if response.status_code == 200: response_json = response.json() logger.debug(f"\nResponse JSON: {response_json}") - response_back = response_json.get("response", {}) + response_back = response_json.get("response", "") # However, as instructed, Ollama is not providing the response only in JSON. - # It adds some extra text above or below the json sometimes. - # So, this hack to extract the json part from the response. + # It adds some extra text above or below the JSON sometimes. + # So, this hack extracts the JSON part from the response. try: response_back = response_back.split("{", 1)[1] response_back = "{" + response_back.rsplit("}", 1)[0] + "}" diff --git a/test/llm/conftest.py b/test/llm/conftest.py index 9473a94..5b9d8ce 100644 --- a/test/llm/conftest.py +++ b/test/llm/conftest.py @@ -7,7 +7,6 @@ import time import requests import shutil -from pathlib import Path @pytest.fixture(scope="session") @@ -128,6 +127,7 @@ def ollama_server(check_ollama_installed, ensure_ollama_model_pulled, ollama_mod server_already_running = True print(f"\nOllama server already running on port {ollama_model_port}") except requests.exceptions.RequestException: + # If the request fails, assume the server is not running and proceed to start it. pass process = None diff --git a/test/llm/test_llm.py b/test/llm/test_llm.py index b863b61..cb88c94 100644 --- a/test/llm/test_llm.py +++ b/test/llm/test_llm.py @@ -38,7 +38,7 @@ def test_default_values(self): response = LLMAskResponse() assert response.task_done is False assert response.command == "" - assert response.thoughts is None or response.thoughts == "" + assert response.thoughts == "" def test_custom_values(self): """Test creating response with custom values""" @@ -56,7 +56,7 @@ def test_partial_initialization(self): response = LLMAskResponse(command="ls -la") assert response.task_done is False assert response.command == "ls -la" - assert response.thoughts is None or response.thoughts == "" + assert response.thoughts == "" @pytest.mark.integration class TestValidateLlmResponse: diff --git a/test/llm/test_ollama_local.py b/test/llm/test_ollama_local.py index a1c1339..90505f1 100644 --- a/test/llm/test_ollama_local.py +++ b/test/llm/test_ollama_local.py @@ -7,8 +7,7 @@ import pytest import sys import os -from unittest.mock import Mock, patch, MagicMock -import json +from unittest.mock import Mock, patch # Add src to path for imports sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "../../src"))) @@ -313,7 +312,7 @@ def test_ask_resets_retries(self, mock_post): } mock_post.return_value = mock_response - result = ollama.ask("List files") + ollama.ask("List files") assert ollama.retries == 0 diff --git a/test/llm/test_openai_api.py b/test/llm/test_openai_api.py index 4f19cdb..d5db11c 100644 --- a/test/llm/test_openai_api.py +++ b/test/llm/test_openai_api.py @@ -93,7 +93,7 @@ def test_ask_successful_response(self): mock_response.output_text = json.dumps({ "task_done": False, "command": "echo 'hello'", - "thoughts": None + "thoughts": "" }) api.ai_client.responses.create = Mock(return_value=mock_response) @@ -105,7 +105,7 @@ def test_ask_successful_response(self): assert isinstance(result, LLMAskResponse) assert result.task_done is False assert result.command == "echo 'hello'" - assert result.thoughts is None or result.thoughts == "" + assert result.thoughts == "" # Verify retries was reset assert api.retries == 0