Module ai_shell.demo_bots.pylint_bot

This bot will attempt to lint the issues in the fish_tank example.

You will need to reset the fish_tank folder to the original state after each run.

Expand source code
"""
This bot will attempt to lint the issues in the `fish_tank` example.

You will need to reset the fish_tank folder to the original state after each run.
"""

import asyncio
import logging
import logging.config
import os

from dotenv import load_dotenv

import ai_shell
import ai_shell.demo_bots.demo_setup as demo_setup
import ai_todo

ai_shell.ai_logs.log_to_bash.LOGGING_ENABLED = True

if __name__ == "__main__" and not os.path.exists("src"):
    demo_setup.initialize()


initial_pylint = None
if __name__ == "__main__":
    with ai_shell.change_directory("src"):
        initial_pylint = ai_shell.invoke_pylint("fish_tank", 8)

        if initial_pylint.return_code == 0:
            raise ValueError("The pylint score is already high enough. Bot won't have any work to do.")


async def main():
    load_dotenv()

    logger = logging.getLogger(__name__)
    logging.config.dictConfig(ai_shell.configure_logging())
    model = "gpt-3.5-turbo-1106"

    # The bot likes praise.
    bot_instructions = (
        "You are a persistent, excellent python developer. You think about your code and reason in steps."
    )
    # Too many tools will confuse the bot.
    tool_names = [
        "ls",
        "cat_markdown",
        "rewrite_file",
        "write_new_file",
        "report_text",
        "insert_text_after_context",
        "insert_text_after_multiline_context",
        "insert_text_at_start_or_end",
        "replace_all",
        "replace_line_by_line",
        "replace_with_regex",
    ]
    bot_name = "Pylint fixer bot"
    language = "python"  # hack so that blacken-docs doesn't try to reformat the string contents
    if not initial_pylint:
        raise ValueError("Pylint data must be initialized.")
    request = f"""You are in the './' folder. The base folder is './'. You do not need to guess the pwd, it is './'.

Here is a map.
fish_tank
├── __init__.py
├── __main__.py
tests
├── test_import_module.py
└── __init__.py

Do not start addressing pylint issues until you use cat_markdown tool to read the fish_tank code.

- Don't even think of modifying a file with running cat_markdown first.
- Do not attempt to address linting issues by adding arbitrary code.
- Do not add functions with empty bodies or `pass` 

If you use the rewrite_file tool, it will blow away any previous contents. Please don't accidentally delete code.

This is an example of google style doc strings.
```{language}
def create_fish(emoji: str, x: int, y: int) -> None:
    \"\"\"
    Create a fish.
    Args:
        emoji (str): The emoji to use for the fish.
        x (int): The starting x coordinate.
        y (int): The starting y coordinate.
    \"\"\"
```        

Now that is out of the way, use the rewrite tool (and/or other tool) to add google style docstrings to the fish_tank 
files. As you can see, pylint says they're missing. After each round of edits, you'll see the updated output of pylint.
    
```markdown
{initial_pylint.to_markdown()}
```"""

    root_folder = "src"
    if not os.path.exists(root_folder):
        raise ValueError("The demo requires that there be a src folder with some python code in it.")

    async def pylint_goal_checker(toolkit: ai_shell.ToolKit):
        # already in src!
        result = ai_shell.invoke_pylint("fish_tank", 8)
        if result.return_code == 0:
            return toolkit.conversation_over_marker
        return result.to_markdown() + "\n\nThe pylint score is too low. Please try again. You can do it!"

    config = ai_shell.Config()
    bot = ai_shell.TaskBot(
        config,
        bot_name,
        bot_instructions,
        model,
        ai_shell.DialogLoggerWithMarkdown("./tmp"),
        persist_bots=True,
        persist_threads=True,
    )
    if not config.get_list("todo_roles"):
        config.set_list("todo_roles", ["Developer", "Tester"])
    ai_todo.TaskManager("src", config.get_list("todo_roles"))
    with ai_shell.change_directory("src"):
        await bot.initialize()
        await bot.basic_tool_loop(
            request, ".", tool_names, pylint_goal_checker, stop_on_no_tool_use=True  # root_folder,
        )
        logger.info("Run completed.")


if __name__ == "__main__":
    asyncio.run(main())

Functions

async def main()
Expand source code
async def main():
    load_dotenv()

    logger = logging.getLogger(__name__)
    logging.config.dictConfig(ai_shell.configure_logging())
    model = "gpt-3.5-turbo-1106"

    # The bot likes praise.
    bot_instructions = (
        "You are a persistent, excellent python developer. You think about your code and reason in steps."
    )
    # Too many tools will confuse the bot.
    tool_names = [
        "ls",
        "cat_markdown",
        "rewrite_file",
        "write_new_file",
        "report_text",
        "insert_text_after_context",
        "insert_text_after_multiline_context",
        "insert_text_at_start_or_end",
        "replace_all",
        "replace_line_by_line",
        "replace_with_regex",
    ]
    bot_name = "Pylint fixer bot"
    language = "python"  # hack so that blacken-docs doesn't try to reformat the string contents
    if not initial_pylint:
        raise ValueError("Pylint data must be initialized.")
    request = f"""You are in the './' folder. The base folder is './'. You do not need to guess the pwd, it is './'.

Here is a map.
fish_tank
├── __init__.py
├── __main__.py
tests
├── test_import_module.py
└── __init__.py

Do not start addressing pylint issues until you use cat_markdown tool to read the fish_tank code.

- Don't even think of modifying a file with running cat_markdown first.
- Do not attempt to address linting issues by adding arbitrary code.
- Do not add functions with empty bodies or `pass` 

If you use the rewrite_file tool, it will blow away any previous contents. Please don't accidentally delete code.

This is an example of google style doc strings.
```{language}
def create_fish(emoji: str, x: int, y: int) -> None:
    \"\"\"
    Create a fish.
    Args:
        emoji (str): The emoji to use for the fish.
        x (int): The starting x coordinate.
        y (int): The starting y coordinate.
    \"\"\"
```        

Now that is out of the way, use the rewrite tool (and/or other tool) to add google style docstrings to the fish_tank 
files. As you can see, pylint says they're missing. After each round of edits, you'll see the updated output of pylint.
    
```markdown
{initial_pylint.to_markdown()}
```"""

    root_folder = "src"
    if not os.path.exists(root_folder):
        raise ValueError("The demo requires that there be a src folder with some python code in it.")

    async def pylint_goal_checker(toolkit: ai_shell.ToolKit):
        # already in src!
        result = ai_shell.invoke_pylint("fish_tank", 8)
        if result.return_code == 0:
            return toolkit.conversation_over_marker
        return result.to_markdown() + "\n\nThe pylint score is too low. Please try again. You can do it!"

    config = ai_shell.Config()
    bot = ai_shell.TaskBot(
        config,
        bot_name,
        bot_instructions,
        model,
        ai_shell.DialogLoggerWithMarkdown("./tmp"),
        persist_bots=True,
        persist_threads=True,
    )
    if not config.get_list("todo_roles"):
        config.set_list("todo_roles", ["Developer", "Tester"])
    ai_todo.TaskManager("src", config.get_list("todo_roles"))
    with ai_shell.change_directory("src"):
        await bot.initialize()
        await bot.basic_tool_loop(
            request, ".", tool_names, pylint_goal_checker, stop_on_no_tool_use=True  # root_folder,
        )
        logger.info("Run completed.")