mirror of
https://github.com/aljazceru/Auto-GPT.git
synced 2025-12-24 01:14:22 +01:00
Pass agent to commands instead of config (#4645)
* Add config as attribute to Agent, rename old config to ai_config * Code review: Pass ai_config * Pass agent to commands instead of config * Lint * Fix merge error * Fix memory challenge a --------- Co-authored-by: Nicholas Tindle <nick@ntindle.com> Co-authored-by: merwanehamadi <merwanehamadi@gmail.com>
This commit is contained in:
@@ -4,7 +4,6 @@ from datetime import datetime
|
|||||||
|
|
||||||
from colorama import Fore, Style
|
from colorama import Fore, Style
|
||||||
|
|
||||||
from autogpt.app import execute_command, get_command
|
|
||||||
from autogpt.commands.command import CommandRegistry
|
from autogpt.commands.command import CommandRegistry
|
||||||
from autogpt.config import Config
|
from autogpt.config import Config
|
||||||
from autogpt.config.ai_config import AIConfig
|
from autogpt.config.ai_config import AIConfig
|
||||||
@@ -89,6 +88,9 @@ class Agent:
|
|||||||
).max_tokens
|
).max_tokens
|
||||||
|
|
||||||
def start_interaction_loop(self):
|
def start_interaction_loop(self):
|
||||||
|
# Avoid circular imports
|
||||||
|
from autogpt.app import execute_command, get_command
|
||||||
|
|
||||||
# Interaction Loop
|
# Interaction Loop
|
||||||
self.cycle_count = 0
|
self.cycle_count = 0
|
||||||
command_name = None
|
command_name = None
|
||||||
@@ -287,8 +289,7 @@ class Agent:
|
|||||||
self.command_registry,
|
self.command_registry,
|
||||||
command_name,
|
command_name,
|
||||||
arguments,
|
arguments,
|
||||||
self.ai_config.prompt_generator,
|
agent=self,
|
||||||
config=self.config,
|
|
||||||
)
|
)
|
||||||
result = f"Command {command_name} returned: " f"{command_result}"
|
result = f"Command {command_name} returned: " f"{command_result}"
|
||||||
|
|
||||||
|
|||||||
@@ -2,12 +2,11 @@
|
|||||||
import json
|
import json
|
||||||
from typing import Dict, List, Union
|
from typing import Dict, List, Union
|
||||||
|
|
||||||
|
from autogpt.agent.agent import Agent
|
||||||
from autogpt.agent.agent_manager import AgentManager
|
from autogpt.agent.agent_manager import AgentManager
|
||||||
from autogpt.commands.command import CommandRegistry, command
|
from autogpt.commands.command import CommandRegistry, command
|
||||||
from autogpt.commands.web_requests import scrape_links, scrape_text
|
from autogpt.commands.web_requests import scrape_links, scrape_text
|
||||||
from autogpt.config import Config
|
|
||||||
from autogpt.processing.text import summarize_text
|
from autogpt.processing.text import summarize_text
|
||||||
from autogpt.prompts.generator import PromptGenerator
|
|
||||||
from autogpt.speech import say_text
|
from autogpt.speech import say_text
|
||||||
from autogpt.url_utils.validators import validate_url
|
from autogpt.url_utils.validators import validate_url
|
||||||
|
|
||||||
@@ -87,9 +86,8 @@ def map_command_synonyms(command_name: str):
|
|||||||
def execute_command(
|
def execute_command(
|
||||||
command_registry: CommandRegistry,
|
command_registry: CommandRegistry,
|
||||||
command_name: str,
|
command_name: str,
|
||||||
arguments,
|
arguments: dict[str, str],
|
||||||
prompt: PromptGenerator,
|
agent: Agent,
|
||||||
config: Config,
|
|
||||||
):
|
):
|
||||||
"""Execute the command and return the result
|
"""Execute the command and return the result
|
||||||
|
|
||||||
@@ -105,7 +103,7 @@ def execute_command(
|
|||||||
|
|
||||||
# If the command is found, call it with the provided arguments
|
# If the command is found, call it with the provided arguments
|
||||||
if cmd:
|
if cmd:
|
||||||
return cmd(**arguments, config=config)
|
return cmd(**arguments, agent=agent)
|
||||||
|
|
||||||
# TODO: Remove commands below after they are moved to the command registry.
|
# TODO: Remove commands below after they are moved to the command registry.
|
||||||
command_name = map_command_synonyms(command_name.lower())
|
command_name = map_command_synonyms(command_name.lower())
|
||||||
@@ -113,7 +111,7 @@ def execute_command(
|
|||||||
# TODO: Change these to take in a file rather than pasted code, if
|
# TODO: Change these to take in a file rather than pasted code, if
|
||||||
# non-file is given, return instructions "Input should be a python
|
# non-file is given, return instructions "Input should be a python
|
||||||
# filepath, write your code to file and try again
|
# filepath, write your code to file and try again
|
||||||
for command in prompt.commands:
|
for command in agent.prompt.commands:
|
||||||
if (
|
if (
|
||||||
command_name == command["label"].lower()
|
command_name == command["label"].lower()
|
||||||
or command_name == command["name"].lower()
|
or command_name == command["name"].lower()
|
||||||
@@ -132,7 +130,7 @@ def execute_command(
|
|||||||
"get_text_summary", "Get text summary", '"url": "<url>", "question": "<question>"'
|
"get_text_summary", "Get text summary", '"url": "<url>", "question": "<question>"'
|
||||||
)
|
)
|
||||||
@validate_url
|
@validate_url
|
||||||
def get_text_summary(url: str, question: str, config: Config) -> str:
|
def get_text_summary(url: str, question: str, agent: Agent) -> str:
|
||||||
"""Get the text summary of a webpage
|
"""Get the text summary of a webpage
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@@ -142,7 +140,7 @@ def get_text_summary(url: str, question: str, config: Config) -> str:
|
|||||||
Returns:
|
Returns:
|
||||||
str: The summary of the text
|
str: The summary of the text
|
||||||
"""
|
"""
|
||||||
text = scrape_text(url, config)
|
text = scrape_text(url, agent)
|
||||||
summary, _ = summarize_text(text, question=question)
|
summary, _ = summarize_text(text, question=question)
|
||||||
|
|
||||||
return f""" "Result" : {summary}"""
|
return f""" "Result" : {summary}"""
|
||||||
@@ -150,7 +148,7 @@ def get_text_summary(url: str, question: str, config: Config) -> str:
|
|||||||
|
|
||||||
@command("get_hyperlinks", "Get hyperlinks", '"url": "<url>"')
|
@command("get_hyperlinks", "Get hyperlinks", '"url": "<url>"')
|
||||||
@validate_url
|
@validate_url
|
||||||
def get_hyperlinks(url: str, config: Config) -> Union[str, List[str]]:
|
def get_hyperlinks(url: str, agent: Agent) -> Union[str, List[str]]:
|
||||||
"""Get all hyperlinks on a webpage
|
"""Get all hyperlinks on a webpage
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@@ -159,7 +157,7 @@ def get_hyperlinks(url: str, config: Config) -> Union[str, List[str]]:
|
|||||||
Returns:
|
Returns:
|
||||||
str or list: The hyperlinks on the page
|
str or list: The hyperlinks on the page
|
||||||
"""
|
"""
|
||||||
return scrape_links(url, config)
|
return scrape_links(url, agent)
|
||||||
|
|
||||||
|
|
||||||
@command(
|
@command(
|
||||||
@@ -167,7 +165,7 @@ def get_hyperlinks(url: str, config: Config) -> Union[str, List[str]]:
|
|||||||
"Start GPT Agent",
|
"Start GPT Agent",
|
||||||
'"name": "<name>", "task": "<short_task_desc>", "prompt": "<prompt>"',
|
'"name": "<name>", "task": "<short_task_desc>", "prompt": "<prompt>"',
|
||||||
)
|
)
|
||||||
def start_agent(name: str, task: str, prompt: str, config: Config, model=None) -> str:
|
def start_agent(name: str, task: str, prompt: str, agent: Agent, model=None) -> str:
|
||||||
"""Start an agent with a given name, task, and prompt
|
"""Start an agent with a given name, task, and prompt
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@@ -188,11 +186,11 @@ def start_agent(name: str, task: str, prompt: str, config: Config, model=None) -
|
|||||||
agent_intro = f"{voice_name} here, Reporting for duty!"
|
agent_intro = f"{voice_name} here, Reporting for duty!"
|
||||||
|
|
||||||
# Create agent
|
# Create agent
|
||||||
if config.speak_mode:
|
if agent.config.speak_mode:
|
||||||
say_text(agent_intro, 1)
|
say_text(agent_intro, 1)
|
||||||
key, ack = agent_manager.create_agent(task, first_message, model)
|
key, ack = agent_manager.create_agent(task, first_message, model)
|
||||||
|
|
||||||
if config.speak_mode:
|
if agent.config.speak_mode:
|
||||||
say_text(f"Hello {voice_name}. Your task is as follows. {task}.")
|
say_text(f"Hello {voice_name}. Your task is as follows. {task}.")
|
||||||
|
|
||||||
# Assign task (prompt), get response
|
# Assign task (prompt), get response
|
||||||
@@ -202,7 +200,7 @@ def start_agent(name: str, task: str, prompt: str, config: Config, model=None) -
|
|||||||
|
|
||||||
|
|
||||||
@command("message_agent", "Message GPT Agent", '"key": "<key>", "message": "<message>"')
|
@command("message_agent", "Message GPT Agent", '"key": "<key>", "message": "<message>"')
|
||||||
def message_agent(key: str, message: str, config: Config) -> str:
|
def message_agent(key: str, message: str, agent: Agent) -> str:
|
||||||
"""Message an agent with a given key and message"""
|
"""Message an agent with a given key and message"""
|
||||||
# Check if the key is a valid integer
|
# Check if the key is a valid integer
|
||||||
if is_valid_int(key):
|
if is_valid_int(key):
|
||||||
@@ -211,13 +209,13 @@ def message_agent(key: str, message: str, config: Config) -> str:
|
|||||||
return "Invalid key, must be an integer."
|
return "Invalid key, must be an integer."
|
||||||
|
|
||||||
# Speak response
|
# Speak response
|
||||||
if config.speak_mode:
|
if agent.config.speak_mode:
|
||||||
say_text(agent_response, 1)
|
say_text(agent_response, 1)
|
||||||
return agent_response
|
return agent_response
|
||||||
|
|
||||||
|
|
||||||
@command("list_agents", "List GPT Agents", "() -> str")
|
@command("list_agents", "List GPT Agents", "() -> str")
|
||||||
def list_agents(config: Config) -> str:
|
def list_agents(agent: Agent) -> str:
|
||||||
"""List all agents
|
"""List all agents
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
@@ -229,7 +227,7 @@ def list_agents(config: Config) -> str:
|
|||||||
|
|
||||||
|
|
||||||
@command("delete_agent", "Delete GPT Agent", '"key": "<key>"')
|
@command("delete_agent", "Delete GPT Agent", '"key": "<key>"')
|
||||||
def delete_agent(key: str, config: Config) -> str:
|
def delete_agent(key: str, agent: Agent) -> str:
|
||||||
"""Delete an agent with a given key
|
"""Delete an agent with a given key
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
|
|||||||
@@ -1,21 +1,17 @@
|
|||||||
"""Code evaluation module."""
|
"""Code evaluation module."""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
from autogpt.agent.agent import Agent
|
||||||
|
|
||||||
from autogpt.commands.command import command
|
from autogpt.commands.command import command
|
||||||
from autogpt.llm.utils import call_ai_function
|
from autogpt.llm.utils import call_ai_function
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from autogpt.config import Config
|
|
||||||
|
|
||||||
|
|
||||||
@command(
|
@command(
|
||||||
"analyze_code",
|
"analyze_code",
|
||||||
"Analyze Code",
|
"Analyze Code",
|
||||||
'"code": "<full_code_string>"',
|
'"code": "<full_code_string>"',
|
||||||
)
|
)
|
||||||
def analyze_code(code: str, config: Config) -> list[str]:
|
def analyze_code(code: str, agent: Agent) -> list[str]:
|
||||||
"""
|
"""
|
||||||
A function that takes in a string and returns a response from create chat
|
A function that takes in a string and returns a response from create chat
|
||||||
completion api call.
|
completion api call.
|
||||||
@@ -33,4 +29,6 @@ def analyze_code(code: str, config: Config) -> list[str]:
|
|||||||
"Analyzes the given code and returns a list of suggestions for improvements."
|
"Analyzes the given code and returns a list of suggestions for improvements."
|
||||||
)
|
)
|
||||||
|
|
||||||
return call_ai_function(function_string, args, description_string, config=config)
|
return call_ai_function(
|
||||||
|
function_string, args, description_string, config=agent.config
|
||||||
|
)
|
||||||
|
|||||||
@@ -1,14 +1,10 @@
|
|||||||
"""Commands for converting audio to text."""
|
"""Commands for converting audio to text."""
|
||||||
import json
|
import json
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
|
from autogpt.agent.agent import Agent
|
||||||
from autogpt.commands.command import command
|
from autogpt.commands.command import command
|
||||||
from autogpt.config import Config
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from autogpt.config import Config
|
|
||||||
|
|
||||||
|
|
||||||
@command(
|
@command(
|
||||||
@@ -19,7 +15,7 @@ if TYPE_CHECKING:
|
|||||||
and config.huggingface_api_token,
|
and config.huggingface_api_token,
|
||||||
"Configure huggingface_audio_to_text_model and Hugging Face api token.",
|
"Configure huggingface_audio_to_text_model and Hugging Face api token.",
|
||||||
)
|
)
|
||||||
def read_audio_from_file(filename: str, config: Config) -> str:
|
def read_audio_from_file(filename: str, agent: Agent) -> str:
|
||||||
"""
|
"""
|
||||||
Convert audio to text.
|
Convert audio to text.
|
||||||
|
|
||||||
@@ -31,10 +27,10 @@ def read_audio_from_file(filename: str, config: Config) -> str:
|
|||||||
"""
|
"""
|
||||||
with open(filename, "rb") as audio_file:
|
with open(filename, "rb") as audio_file:
|
||||||
audio = audio_file.read()
|
audio = audio_file.read()
|
||||||
return read_audio(audio, config)
|
return read_audio(audio, agent.config)
|
||||||
|
|
||||||
|
|
||||||
def read_audio(audio: bytes, config: Config) -> str:
|
def read_audio(audio: bytes, agent: Agent) -> str:
|
||||||
"""
|
"""
|
||||||
Convert audio to text.
|
Convert audio to text.
|
||||||
|
|
||||||
@@ -44,8 +40,8 @@ def read_audio(audio: bytes, config: Config) -> str:
|
|||||||
Returns:
|
Returns:
|
||||||
str: The text from the audio
|
str: The text from the audio
|
||||||
"""
|
"""
|
||||||
if config.audio_to_text_provider == "huggingface":
|
if agent.config.audio_to_text_provider == "huggingface":
|
||||||
text = read_huggingface_audio(audio, config)
|
text = read_huggingface_audio(audio, agent.config)
|
||||||
if text:
|
if text:
|
||||||
return f"The audio says: {text}"
|
return f"The audio says: {text}"
|
||||||
else:
|
else:
|
||||||
@@ -54,10 +50,10 @@ def read_audio(audio: bytes, config: Config) -> str:
|
|||||||
return "Error: No audio to text provider given"
|
return "Error: No audio to text provider given"
|
||||||
|
|
||||||
|
|
||||||
def read_huggingface_audio(audio: bytes, config: Config) -> str:
|
def read_huggingface_audio(audio: bytes, agent: Agent) -> str:
|
||||||
model = config.huggingface_audio_to_text_model
|
model = agent.config.huggingface_audio_to_text_model
|
||||||
api_url = f"https://api-inference.huggingface.co/models/{model}"
|
api_url = f"https://api-inference.huggingface.co/models/{model}"
|
||||||
api_token = config.huggingface_api_token
|
api_token = agent.config.huggingface_api_token
|
||||||
headers = {"Authorization": f"Bearer {api_token}"}
|
headers = {"Authorization": f"Bearer {api_token}"}
|
||||||
|
|
||||||
if api_token is None:
|
if api_token is None:
|
||||||
|
|||||||
@@ -4,11 +4,11 @@ import subprocess
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
import docker
|
import docker
|
||||||
|
from confection import Config
|
||||||
from docker.errors import ImageNotFound
|
from docker.errors import ImageNotFound
|
||||||
|
|
||||||
|
from autogpt.agent.agent import Agent
|
||||||
from autogpt.commands.command import command
|
from autogpt.commands.command import command
|
||||||
from autogpt.config import Config
|
|
||||||
from autogpt.config.ai_config import AIConfig
|
|
||||||
from autogpt.logs import logger
|
from autogpt.logs import logger
|
||||||
from autogpt.setup import CFG
|
from autogpt.setup import CFG
|
||||||
from autogpt.workspace.workspace import Workspace
|
from autogpt.workspace.workspace import Workspace
|
||||||
@@ -22,7 +22,7 @@ DENYLIST_CONTROL = "denylist"
|
|||||||
"Create a Python file and execute it",
|
"Create a Python file and execute it",
|
||||||
'"code": "<code>", "basename": "<basename>"',
|
'"code": "<code>", "basename": "<basename>"',
|
||||||
)
|
)
|
||||||
def execute_python_code(code: str, basename: str, config: Config) -> str:
|
def execute_python_code(code: str, basename: str, agent: Agent) -> str:
|
||||||
"""Create and execute a Python file in a Docker container and return the STDOUT of the
|
"""Create and execute a Python file in a Docker container and return the STDOUT of the
|
||||||
executed code. If there is any data that needs to be captured use a print statement
|
executed code. If there is any data that needs to be captured use a print statement
|
||||||
|
|
||||||
@@ -33,8 +33,8 @@ def execute_python_code(code: str, basename: str, config: Config) -> str:
|
|||||||
Returns:
|
Returns:
|
||||||
str: The STDOUT captured from the code when it ran
|
str: The STDOUT captured from the code when it ran
|
||||||
"""
|
"""
|
||||||
ai_name = AIConfig.load(config.ai_settings_file).ai_name
|
ai_name = agent.ai_name
|
||||||
directory = os.path.join(config.workspace_path, ai_name, "executed_code")
|
directory = os.path.join(agent.config.workspace_path, ai_name, "executed_code")
|
||||||
os.makedirs(directory, exist_ok=True)
|
os.makedirs(directory, exist_ok=True)
|
||||||
|
|
||||||
if not basename.endswith(".py"):
|
if not basename.endswith(".py"):
|
||||||
@@ -46,13 +46,13 @@ def execute_python_code(code: str, basename: str, config: Config) -> str:
|
|||||||
with open(path, "w+", encoding="utf-8") as f:
|
with open(path, "w+", encoding="utf-8") as f:
|
||||||
f.write(code)
|
f.write(code)
|
||||||
|
|
||||||
return execute_python_file(f.name, config)
|
return execute_python_file(f.name, agent)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return f"Error: {str(e)}"
|
return f"Error: {str(e)}"
|
||||||
|
|
||||||
|
|
||||||
@command("execute_python_file", "Execute Python File", '"filename": "<filename>"')
|
@command("execute_python_file", "Execute Python File", '"filename": "<filename>"')
|
||||||
def execute_python_file(filename: str, config: Config) -> str:
|
def execute_python_file(filename: str, agent: Agent) -> str:
|
||||||
"""Execute a Python file in a Docker container and return the output
|
"""Execute a Python file in a Docker container and return the output
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@@ -68,7 +68,9 @@ def execute_python_file(filename: str, config: Config) -> str:
|
|||||||
if not filename.endswith(".py"):
|
if not filename.endswith(".py"):
|
||||||
return "Error: Invalid file type. Only .py files are allowed."
|
return "Error: Invalid file type. Only .py files are allowed."
|
||||||
|
|
||||||
workspace = Workspace(config.workspace_path, config.restrict_to_workspace)
|
workspace = Workspace(
|
||||||
|
agent.config.workspace_path, agent.config.restrict_to_workspace
|
||||||
|
)
|
||||||
|
|
||||||
path = workspace.get_path(filename)
|
path = workspace.get_path(filename)
|
||||||
if not path.is_file():
|
if not path.is_file():
|
||||||
@@ -116,7 +118,7 @@ def execute_python_file(filename: str, config: Config) -> str:
|
|||||||
image_name,
|
image_name,
|
||||||
["python", str(path.relative_to(workspace.root))],
|
["python", str(path.relative_to(workspace.root))],
|
||||||
volumes={
|
volumes={
|
||||||
config.workspace_path: {
|
agent.config.workspace_path: {
|
||||||
"bind": "/workspace",
|
"bind": "/workspace",
|
||||||
"mode": "ro",
|
"mode": "ro",
|
||||||
}
|
}
|
||||||
@@ -175,7 +177,7 @@ def validate_command(command: str, config: Config) -> bool:
|
|||||||
" shell commands, EXECUTE_LOCAL_COMMANDS must be set to 'True' "
|
" shell commands, EXECUTE_LOCAL_COMMANDS must be set to 'True' "
|
||||||
"in your config file: .env - do not attempt to bypass the restriction.",
|
"in your config file: .env - do not attempt to bypass the restriction.",
|
||||||
)
|
)
|
||||||
def execute_shell(command_line: str, config: Config) -> str:
|
def execute_shell(command_line: str, agent: Agent) -> str:
|
||||||
"""Execute a shell command and return the output
|
"""Execute a shell command and return the output
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@@ -184,14 +186,14 @@ def execute_shell(command_line: str, config: Config) -> str:
|
|||||||
Returns:
|
Returns:
|
||||||
str: The output of the command
|
str: The output of the command
|
||||||
"""
|
"""
|
||||||
if not validate_command(command_line, config):
|
if not validate_command(command_line, agent.config):
|
||||||
logger.info(f"Command '{command_line}' not allowed")
|
logger.info(f"Command '{command_line}' not allowed")
|
||||||
return "Error: This Shell Command is not allowed."
|
return "Error: This Shell Command is not allowed."
|
||||||
|
|
||||||
current_dir = Path.cwd()
|
current_dir = Path.cwd()
|
||||||
# Change dir into workspace if necessary
|
# Change dir into workspace if necessary
|
||||||
if not current_dir.is_relative_to(config.workspace_path):
|
if not current_dir.is_relative_to(agent.config.workspace_path):
|
||||||
os.chdir(config.workspace_path)
|
os.chdir(agent.config.workspace_path)
|
||||||
|
|
||||||
logger.info(
|
logger.info(
|
||||||
f"Executing command '{command_line}' in working directory '{os.getcwd()}'"
|
f"Executing command '{command_line}' in working directory '{os.getcwd()}'"
|
||||||
@@ -215,7 +217,7 @@ def execute_shell(command_line: str, config: Config) -> str:
|
|||||||
" shell commands, EXECUTE_LOCAL_COMMANDS must be set to 'True' "
|
" shell commands, EXECUTE_LOCAL_COMMANDS must be set to 'True' "
|
||||||
"in your config. Do not attempt to bypass the restriction.",
|
"in your config. Do not attempt to bypass the restriction.",
|
||||||
)
|
)
|
||||||
def execute_shell_popen(command_line, config: Config) -> str:
|
def execute_shell_popen(command_line, agent: Agent) -> str:
|
||||||
"""Execute a shell command with Popen and returns an english description
|
"""Execute a shell command with Popen and returns an english description
|
||||||
of the event and the process id
|
of the event and the process id
|
||||||
|
|
||||||
@@ -225,14 +227,14 @@ def execute_shell_popen(command_line, config: Config) -> str:
|
|||||||
Returns:
|
Returns:
|
||||||
str: Description of the fact that the process started and its id
|
str: Description of the fact that the process started and its id
|
||||||
"""
|
"""
|
||||||
if not validate_command(command_line, config):
|
if not validate_command(command_line, agent.config):
|
||||||
logger.info(f"Command '{command_line}' not allowed")
|
logger.info(f"Command '{command_line}' not allowed")
|
||||||
return "Error: This Shell Command is not allowed."
|
return "Error: This Shell Command is not allowed."
|
||||||
|
|
||||||
current_dir = os.getcwd()
|
current_dir = os.getcwd()
|
||||||
# Change dir into workspace if necessary
|
# Change dir into workspace if necessary
|
||||||
if config.workspace_path not in current_dir:
|
if agent.config.workspace_path not in current_dir:
|
||||||
os.chdir(config.workspace_path)
|
os.chdir(agent.config.workspace_path)
|
||||||
|
|
||||||
logger.info(
|
logger.info(
|
||||||
f"Executing command '{command_line}' in working directory '{os.getcwd()}'"
|
f"Executing command '{command_line}' in working directory '{os.getcwd()}'"
|
||||||
|
|||||||
@@ -5,12 +5,14 @@ import hashlib
|
|||||||
import os
|
import os
|
||||||
import os.path
|
import os.path
|
||||||
import re
|
import re
|
||||||
from typing import TYPE_CHECKING, Generator, Literal
|
from typing import Generator, Literal
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
from colorama import Back, Fore
|
from colorama import Back, Fore
|
||||||
|
from confection import Config
|
||||||
from requests.adapters import HTTPAdapter, Retry
|
from requests.adapters import HTTPAdapter, Retry
|
||||||
|
|
||||||
|
from autogpt.agent.agent import Agent
|
||||||
from autogpt.commands.command import command
|
from autogpt.commands.command import command
|
||||||
from autogpt.commands.file_operations_utils import read_textual_file
|
from autogpt.commands.file_operations_utils import read_textual_file
|
||||||
from autogpt.logs import logger
|
from autogpt.logs import logger
|
||||||
@@ -18,10 +20,6 @@ from autogpt.memory.vector import MemoryItem, VectorMemory
|
|||||||
from autogpt.spinner import Spinner
|
from autogpt.spinner import Spinner
|
||||||
from autogpt.utils import readable_file_size
|
from autogpt.utils import readable_file_size
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from autogpt.config import Config
|
|
||||||
|
|
||||||
|
|
||||||
Operation = Literal["write", "append", "delete"]
|
Operation = Literal["write", "append", "delete"]
|
||||||
|
|
||||||
|
|
||||||
@@ -103,7 +101,7 @@ def is_duplicate_operation(
|
|||||||
|
|
||||||
|
|
||||||
def log_operation(
|
def log_operation(
|
||||||
operation: str, filename: str, config: Config, checksum: str | None = None
|
operation: str, filename: str, agent: Agent, checksum: str | None = None
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Log the file operation to the file_logger.txt
|
"""Log the file operation to the file_logger.txt
|
||||||
|
|
||||||
@@ -116,7 +114,9 @@ def log_operation(
|
|||||||
if checksum is not None:
|
if checksum is not None:
|
||||||
log_entry += f" #{checksum}"
|
log_entry += f" #{checksum}"
|
||||||
logger.debug(f"Logging file operation: {log_entry}")
|
logger.debug(f"Logging file operation: {log_entry}")
|
||||||
append_to_file(config.file_logger_path, f"{log_entry}\n", config, should_log=False)
|
append_to_file(
|
||||||
|
agent.config.file_logger_path, f"{log_entry}\n", agent, should_log=False
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def split_file(
|
def split_file(
|
||||||
@@ -152,7 +152,7 @@ def split_file(
|
|||||||
|
|
||||||
|
|
||||||
@command("read_file", "Read a file", '"filename": "<filename>"')
|
@command("read_file", "Read a file", '"filename": "<filename>"')
|
||||||
def read_file(filename: str, config: Config) -> str:
|
def read_file(filename: str, agent: Agent) -> str:
|
||||||
"""Read a file and return the contents
|
"""Read a file and return the contents
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@@ -201,7 +201,7 @@ def ingest_file(
|
|||||||
|
|
||||||
|
|
||||||
@command("write_to_file", "Write to file", '"filename": "<filename>", "text": "<text>"')
|
@command("write_to_file", "Write to file", '"filename": "<filename>", "text": "<text>"')
|
||||||
def write_to_file(filename: str, text: str, config: Config) -> str:
|
def write_to_file(filename: str, text: str, agent: Agent) -> str:
|
||||||
"""Write text to a file
|
"""Write text to a file
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@@ -212,14 +212,14 @@ def write_to_file(filename: str, text: str, config: Config) -> str:
|
|||||||
str: A message indicating success or failure
|
str: A message indicating success or failure
|
||||||
"""
|
"""
|
||||||
checksum = text_checksum(text)
|
checksum = text_checksum(text)
|
||||||
if is_duplicate_operation("write", filename, config, checksum):
|
if is_duplicate_operation("write", filename, agent.config, checksum):
|
||||||
return "Error: File has already been updated."
|
return "Error: File has already been updated."
|
||||||
try:
|
try:
|
||||||
directory = os.path.dirname(filename)
|
directory = os.path.dirname(filename)
|
||||||
os.makedirs(directory, exist_ok=True)
|
os.makedirs(directory, exist_ok=True)
|
||||||
with open(filename, "w", encoding="utf-8") as f:
|
with open(filename, "w", encoding="utf-8") as f:
|
||||||
f.write(text)
|
f.write(text)
|
||||||
log_operation("write", filename, config, checksum)
|
log_operation("write", filename, agent, checksum)
|
||||||
return "File written to successfully."
|
return "File written to successfully."
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
return f"Error: {err}"
|
return f"Error: {err}"
|
||||||
@@ -233,7 +233,7 @@ def write_to_file(filename: str, text: str, config: Config) -> str:
|
|||||||
'"occurrence_index": "<occurrence_index>"',
|
'"occurrence_index": "<occurrence_index>"',
|
||||||
)
|
)
|
||||||
def replace_in_file(
|
def replace_in_file(
|
||||||
filename: str, old_text: str, new_text: str, config: Config, occurrence_index=None
|
filename: str, old_text: str, new_text: str, agent: Agent, occurrence_index=None
|
||||||
):
|
):
|
||||||
"""Update a file by replacing one or all occurrences of old_text with new_text using Python's built-in string
|
"""Update a file by replacing one or all occurrences of old_text with new_text using Python's built-in string
|
||||||
manipulation and regular expression modules for cross-platform file editing similar to sed and awk.
|
manipulation and regular expression modules for cross-platform file editing similar to sed and awk.
|
||||||
@@ -280,7 +280,7 @@ def replace_in_file(
|
|||||||
|
|
||||||
with open(filename, "r", encoding="utf-8") as f:
|
with open(filename, "r", encoding="utf-8") as f:
|
||||||
checksum = text_checksum(f.read())
|
checksum = text_checksum(f.read())
|
||||||
log_operation("update", filename, config, checksum=checksum)
|
log_operation("update", filename, agent, checksum=checksum)
|
||||||
|
|
||||||
return f"File {filename} updated successfully."
|
return f"File {filename} updated successfully."
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -291,7 +291,7 @@ def replace_in_file(
|
|||||||
"append_to_file", "Append to file", '"filename": "<filename>", "text": "<text>"'
|
"append_to_file", "Append to file", '"filename": "<filename>", "text": "<text>"'
|
||||||
)
|
)
|
||||||
def append_to_file(
|
def append_to_file(
|
||||||
filename: str, text: str, config: Config, should_log: bool = True
|
filename: str, text: str, agent: Agent, should_log: bool = True
|
||||||
) -> str:
|
) -> str:
|
||||||
"""Append text to a file
|
"""Append text to a file
|
||||||
|
|
||||||
@@ -312,7 +312,7 @@ def append_to_file(
|
|||||||
if should_log:
|
if should_log:
|
||||||
with open(filename, "r", encoding="utf-8") as f:
|
with open(filename, "r", encoding="utf-8") as f:
|
||||||
checksum = text_checksum(f.read())
|
checksum = text_checksum(f.read())
|
||||||
log_operation("append", filename, config, checksum=checksum)
|
log_operation("append", filename, agent, checksum=checksum)
|
||||||
|
|
||||||
return "Text appended successfully."
|
return "Text appended successfully."
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
@@ -320,7 +320,7 @@ def append_to_file(
|
|||||||
|
|
||||||
|
|
||||||
@command("delete_file", "Delete file", '"filename": "<filename>"')
|
@command("delete_file", "Delete file", '"filename": "<filename>"')
|
||||||
def delete_file(filename: str, config: Config) -> str:
|
def delete_file(filename: str, agent: Agent) -> str:
|
||||||
"""Delete a file
|
"""Delete a file
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@@ -329,18 +329,18 @@ def delete_file(filename: str, config: Config) -> str:
|
|||||||
Returns:
|
Returns:
|
||||||
str: A message indicating success or failure
|
str: A message indicating success or failure
|
||||||
"""
|
"""
|
||||||
if is_duplicate_operation("delete", filename, config):
|
if is_duplicate_operation("delete", filename, agent.config):
|
||||||
return "Error: File has already been deleted."
|
return "Error: File has already been deleted."
|
||||||
try:
|
try:
|
||||||
os.remove(filename)
|
os.remove(filename)
|
||||||
log_operation("delete", filename, config)
|
log_operation("delete", filename, agent)
|
||||||
return "File deleted successfully."
|
return "File deleted successfully."
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
return f"Error: {err}"
|
return f"Error: {err}"
|
||||||
|
|
||||||
|
|
||||||
@command("list_files", "List Files in Directory", '"directory": "<directory>"')
|
@command("list_files", "List Files in Directory", '"directory": "<directory>"')
|
||||||
def list_files(directory: str, config: Config) -> list[str]:
|
def list_files(directory: str, agent: Agent) -> list[str]:
|
||||||
"""lists files in a directory recursively
|
"""lists files in a directory recursively
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@@ -356,7 +356,7 @@ def list_files(directory: str, config: Config) -> list[str]:
|
|||||||
if file.startswith("."):
|
if file.startswith("."):
|
||||||
continue
|
continue
|
||||||
relative_path = os.path.relpath(
|
relative_path = os.path.relpath(
|
||||||
os.path.join(root, file), config.workspace_path
|
os.path.join(root, file), agent.config.workspace_path
|
||||||
)
|
)
|
||||||
found_files.append(relative_path)
|
found_files.append(relative_path)
|
||||||
|
|
||||||
@@ -370,7 +370,7 @@ def list_files(directory: str, config: Config) -> list[str]:
|
|||||||
lambda config: config.allow_downloads,
|
lambda config: config.allow_downloads,
|
||||||
"Error: You do not have user authorization to download files locally.",
|
"Error: You do not have user authorization to download files locally.",
|
||||||
)
|
)
|
||||||
def download_file(url, filename, config: Config):
|
def download_file(url, filename, agent: Agent):
|
||||||
"""Downloads a file
|
"""Downloads a file
|
||||||
Args:
|
Args:
|
||||||
url (str): URL of the file to download
|
url (str): URL of the file to download
|
||||||
@@ -380,7 +380,7 @@ def download_file(url, filename, config: Config):
|
|||||||
directory = os.path.dirname(filename)
|
directory = os.path.dirname(filename)
|
||||||
os.makedirs(directory, exist_ok=True)
|
os.makedirs(directory, exist_ok=True)
|
||||||
message = f"{Fore.YELLOW}Downloading file from {Back.LIGHTBLUE_EX}{url}{Back.RESET}{Fore.RESET}"
|
message = f"{Fore.YELLOW}Downloading file from {Back.LIGHTBLUE_EX}{url}{Back.RESET}{Fore.RESET}"
|
||||||
with Spinner(message, plain_output=config.plain_output) as spinner:
|
with Spinner(message, plain_output=agent.config.plain_output) as spinner:
|
||||||
session = requests.Session()
|
session = requests.Session()
|
||||||
retry = Retry(total=3, backoff_factor=1, status_forcelist=[502, 503, 504])
|
retry = Retry(total=3, backoff_factor=1, status_forcelist=[502, 503, 504])
|
||||||
adapter = HTTPAdapter(max_retries=retry)
|
adapter = HTTPAdapter(max_retries=retry)
|
||||||
|
|||||||
@@ -1,15 +1,11 @@
|
|||||||
"""Git operations for autogpt"""
|
"""Git operations for autogpt"""
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
from git.repo import Repo
|
from git.repo import Repo
|
||||||
|
|
||||||
|
from autogpt.agent.agent import Agent
|
||||||
from autogpt.commands.command import command
|
from autogpt.commands.command import command
|
||||||
from autogpt.config import Config
|
|
||||||
from autogpt.url_utils.validators import validate_url
|
from autogpt.url_utils.validators import validate_url
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from autogpt.config import Config
|
|
||||||
|
|
||||||
|
|
||||||
@command(
|
@command(
|
||||||
"clone_repository",
|
"clone_repository",
|
||||||
@@ -19,7 +15,7 @@ if TYPE_CHECKING:
|
|||||||
"Configure github_username and github_api_key.",
|
"Configure github_username and github_api_key.",
|
||||||
)
|
)
|
||||||
@validate_url
|
@validate_url
|
||||||
def clone_repository(url: str, clone_path: str, config: Config) -> str:
|
def clone_repository(url: str, clone_path: str, agent: Agent) -> str:
|
||||||
"""Clone a GitHub repository locally.
|
"""Clone a GitHub repository locally.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@@ -30,8 +26,10 @@ def clone_repository(url: str, clone_path: str, config: Config) -> str:
|
|||||||
str: The result of the clone operation.
|
str: The result of the clone operation.
|
||||||
"""
|
"""
|
||||||
split_url = url.split("//")
|
split_url = url.split("//")
|
||||||
auth_repo_url = f"//{config.github_username}:{config.github_api_key}@".join(
|
auth_repo_url = (
|
||||||
split_url
|
f"//{agent.config.github_username}:{agent.config.github_api_key}@".join(
|
||||||
|
split_url
|
||||||
|
)
|
||||||
)
|
)
|
||||||
try:
|
try:
|
||||||
Repo.clone_from(url=auth_repo_url, to_path=clone_path)
|
Repo.clone_from(url=auth_repo_url, to_path=clone_path)
|
||||||
|
|||||||
@@ -4,15 +4,12 @@ from __future__ import annotations
|
|||||||
import json
|
import json
|
||||||
import time
|
import time
|
||||||
from itertools import islice
|
from itertools import islice
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
from duckduckgo_search import DDGS
|
from duckduckgo_search import DDGS
|
||||||
|
|
||||||
|
from autogpt.agent.agent import Agent
|
||||||
from autogpt.commands.command import command
|
from autogpt.commands.command import command
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from autogpt.config import Config
|
|
||||||
|
|
||||||
DUCKDUCKGO_MAX_ATTEMPTS = 3
|
DUCKDUCKGO_MAX_ATTEMPTS = 3
|
||||||
|
|
||||||
|
|
||||||
@@ -22,7 +19,7 @@ DUCKDUCKGO_MAX_ATTEMPTS = 3
|
|||||||
'"query": "<query>"',
|
'"query": "<query>"',
|
||||||
lambda config: not config.google_api_key,
|
lambda config: not config.google_api_key,
|
||||||
)
|
)
|
||||||
def google_search(query: str, config: Config, num_results: int = 8) -> str:
|
def google_search(query: str, agent: Agent, num_results: int = 8) -> str:
|
||||||
"""Return the results of a Google search
|
"""Return the results of a Google search
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@@ -61,7 +58,7 @@ def google_search(query: str, config: Config, num_results: int = 8) -> str:
|
|||||||
"Configure google_api_key and custom_search_engine_id.",
|
"Configure google_api_key and custom_search_engine_id.",
|
||||||
)
|
)
|
||||||
def google_official_search(
|
def google_official_search(
|
||||||
query: str, config: Config, num_results: int = 8
|
query: str, agent: Agent, num_results: int = 8
|
||||||
) -> str | list[str]:
|
) -> str | list[str]:
|
||||||
"""Return the results of a Google search using the official Google API
|
"""Return the results of a Google search using the official Google API
|
||||||
|
|
||||||
@@ -78,8 +75,8 @@ def google_official_search(
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
# Get the Google API key and Custom Search Engine ID from the config file
|
# Get the Google API key and Custom Search Engine ID from the config file
|
||||||
api_key = config.google_api_key
|
api_key = agent.config.google_api_key
|
||||||
custom_search_engine_id = config.google_custom_search_engine_id
|
custom_search_engine_id = agent.config.google_custom_search_engine_id
|
||||||
|
|
||||||
# Initialize the Custom Search API service
|
# Initialize the Custom Search API service
|
||||||
service = build("customsearch", "v1", developerKey=api_key)
|
service = build("customsearch", "v1", developerKey=api_key)
|
||||||
|
|||||||
@@ -4,19 +4,15 @@ import json
|
|||||||
import time
|
import time
|
||||||
import uuid
|
import uuid
|
||||||
from base64 import b64decode
|
from base64 import b64decode
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
import openai
|
import openai
|
||||||
import requests
|
import requests
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
|
|
||||||
|
from autogpt.agent.agent import Agent
|
||||||
from autogpt.commands.command import command
|
from autogpt.commands.command import command
|
||||||
from autogpt.config import Config
|
|
||||||
from autogpt.logs import logger
|
from autogpt.logs import logger
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from autogpt.config import Config
|
|
||||||
|
|
||||||
|
|
||||||
@command(
|
@command(
|
||||||
"generate_image",
|
"generate_image",
|
||||||
@@ -25,7 +21,7 @@ if TYPE_CHECKING:
|
|||||||
lambda config: config.image_provider,
|
lambda config: config.image_provider,
|
||||||
"Requires a image provider to be set.",
|
"Requires a image provider to be set.",
|
||||||
)
|
)
|
||||||
def generate_image(prompt: str, config: Config, size: int = 256) -> str:
|
def generate_image(prompt: str, agent: Agent, size: int = 256) -> str:
|
||||||
"""Generate an image from a prompt.
|
"""Generate an image from a prompt.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@@ -35,21 +31,21 @@ def generate_image(prompt: str, config: Config, size: int = 256) -> str:
|
|||||||
Returns:
|
Returns:
|
||||||
str: The filename of the image
|
str: The filename of the image
|
||||||
"""
|
"""
|
||||||
filename = f"{config.workspace_path}/{str(uuid.uuid4())}.jpg"
|
filename = f"{agent.config.workspace_path}/{str(uuid.uuid4())}.jpg"
|
||||||
|
|
||||||
# DALL-E
|
# DALL-E
|
||||||
if config.image_provider == "dalle":
|
if agent.config.image_provider == "dalle":
|
||||||
return generate_image_with_dalle(prompt, filename, size, config)
|
return generate_image_with_dalle(prompt, filename, size, agent)
|
||||||
# HuggingFace
|
# HuggingFace
|
||||||
elif config.image_provider == "huggingface":
|
elif agent.config.image_provider == "huggingface":
|
||||||
return generate_image_with_hf(prompt, filename, config)
|
return generate_image_with_hf(prompt, filename, agent)
|
||||||
# SD WebUI
|
# SD WebUI
|
||||||
elif config.image_provider == "sdwebui":
|
elif agent.config.image_provider == "sdwebui":
|
||||||
return generate_image_with_sd_webui(prompt, filename, config, size)
|
return generate_image_with_sd_webui(prompt, filename, agent, size)
|
||||||
return "No Image Provider Set"
|
return "No Image Provider Set"
|
||||||
|
|
||||||
|
|
||||||
def generate_image_with_hf(prompt: str, filename: str, config: Config) -> str:
|
def generate_image_with_hf(prompt: str, filename: str, agent: Agent) -> str:
|
||||||
"""Generate an image with HuggingFace's API.
|
"""Generate an image with HuggingFace's API.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@@ -59,15 +55,13 @@ def generate_image_with_hf(prompt: str, filename: str, config: Config) -> str:
|
|||||||
Returns:
|
Returns:
|
||||||
str: The filename of the image
|
str: The filename of the image
|
||||||
"""
|
"""
|
||||||
API_URL = (
|
API_URL = f"https://api-inference.huggingface.co/models/{agent.config.huggingface_image_model}"
|
||||||
f"https://api-inference.huggingface.co/models/{config.huggingface_image_model}"
|
if agent.config.huggingface_api_token is None:
|
||||||
)
|
|
||||||
if config.huggingface_api_token is None:
|
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
"You need to set your Hugging Face API token in the config file."
|
"You need to set your Hugging Face API token in the config file."
|
||||||
)
|
)
|
||||||
headers = {
|
headers = {
|
||||||
"Authorization": f"Bearer {config.huggingface_api_token}",
|
"Authorization": f"Bearer {agent.config.huggingface_api_token}",
|
||||||
"X-Use-Cache": "false",
|
"X-Use-Cache": "false",
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,7 +104,7 @@ def generate_image_with_hf(prompt: str, filename: str, config: Config) -> str:
|
|||||||
|
|
||||||
|
|
||||||
def generate_image_with_dalle(
|
def generate_image_with_dalle(
|
||||||
prompt: str, filename: str, size: int, config: Config
|
prompt: str, filename: str, size: int, agent: Agent
|
||||||
) -> str:
|
) -> str:
|
||||||
"""Generate an image with DALL-E.
|
"""Generate an image with DALL-E.
|
||||||
|
|
||||||
@@ -136,7 +130,7 @@ def generate_image_with_dalle(
|
|||||||
n=1,
|
n=1,
|
||||||
size=f"{size}x{size}",
|
size=f"{size}x{size}",
|
||||||
response_format="b64_json",
|
response_format="b64_json",
|
||||||
api_key=config.openai_api_key,
|
api_key=agent.config.openai_api_key,
|
||||||
)
|
)
|
||||||
|
|
||||||
logger.info(f"Image Generated for prompt:{prompt}")
|
logger.info(f"Image Generated for prompt:{prompt}")
|
||||||
@@ -152,7 +146,7 @@ def generate_image_with_dalle(
|
|||||||
def generate_image_with_sd_webui(
|
def generate_image_with_sd_webui(
|
||||||
prompt: str,
|
prompt: str,
|
||||||
filename: str,
|
filename: str,
|
||||||
config: Config,
|
agent: Agent,
|
||||||
size: int = 512,
|
size: int = 512,
|
||||||
negative_prompt: str = "",
|
negative_prompt: str = "",
|
||||||
extra: dict = {},
|
extra: dict = {},
|
||||||
@@ -169,13 +163,13 @@ def generate_image_with_sd_webui(
|
|||||||
"""
|
"""
|
||||||
# Create a session and set the basic auth if needed
|
# Create a session and set the basic auth if needed
|
||||||
s = requests.Session()
|
s = requests.Session()
|
||||||
if config.sd_webui_auth:
|
if agent.config.sd_webui_auth:
|
||||||
username, password = config.sd_webui_auth.split(":")
|
username, password = agent.config.sd_webui_auth.split(":")
|
||||||
s.auth = (username, password or "")
|
s.auth = (username, password or "")
|
||||||
|
|
||||||
# Generate the images
|
# Generate the images
|
||||||
response = requests.post(
|
response = requests.post(
|
||||||
f"{config.sd_webui_url}/sdapi/v1/txt2img",
|
f"{agent.config.sd_webui_url}/sdapi/v1/txt2img",
|
||||||
json={
|
json={
|
||||||
"prompt": prompt,
|
"prompt": prompt,
|
||||||
"negative_prompt": negative_prompt,
|
"negative_prompt": negative_prompt,
|
||||||
|
|||||||
@@ -1,21 +1,18 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import json
|
import json
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
|
from autogpt.agent.agent import Agent
|
||||||
from autogpt.commands.command import command
|
from autogpt.commands.command import command
|
||||||
from autogpt.llm.utils import call_ai_function
|
from autogpt.llm.utils import call_ai_function
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from autogpt.config import Config
|
|
||||||
|
|
||||||
|
|
||||||
@command(
|
@command(
|
||||||
"improve_code",
|
"improve_code",
|
||||||
"Get Improved Code",
|
"Get Improved Code",
|
||||||
'"suggestions": "<list_of_suggestions>", "code": "<full_code_string>"',
|
'"suggestions": "<list_of_suggestions>", "code": "<full_code_string>"',
|
||||||
)
|
)
|
||||||
def improve_code(suggestions: list[str], code: str, config: Config) -> str:
|
def improve_code(suggestions: list[str], code: str, agent: Agent) -> str:
|
||||||
"""
|
"""
|
||||||
A function that takes in code and suggestions and returns a response from create
|
A function that takes in code and suggestions and returns a response from create
|
||||||
chat completion api call.
|
chat completion api call.
|
||||||
@@ -36,4 +33,6 @@ def improve_code(suggestions: list[str], code: str, config: Config) -> str:
|
|||||||
" provided, making no other changes."
|
" provided, making no other changes."
|
||||||
)
|
)
|
||||||
|
|
||||||
return call_ai_function(function_string, args, description_string, config=config)
|
return call_ai_function(
|
||||||
|
function_string, args, description_string, config=agent.config
|
||||||
|
)
|
||||||
|
|||||||
@@ -1,21 +1,19 @@
|
|||||||
"""Task Statuses module."""
|
"""Task Statuses module."""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from typing import TYPE_CHECKING, NoReturn
|
from typing import NoReturn
|
||||||
|
|
||||||
|
from autogpt.agent.agent import Agent
|
||||||
from autogpt.commands.command import command
|
from autogpt.commands.command import command
|
||||||
from autogpt.logs import logger
|
from autogpt.logs import logger
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from autogpt.config import Config
|
|
||||||
|
|
||||||
|
|
||||||
@command(
|
@command(
|
||||||
"task_complete",
|
"task_complete",
|
||||||
"Task Complete (Shutdown)",
|
"Task Complete (Shutdown)",
|
||||||
'"reason": "<reason>"',
|
'"reason": "<reason>"',
|
||||||
)
|
)
|
||||||
def task_complete(reason: str, config: Config) -> NoReturn:
|
def task_complete(reason: str, agent: Agent) -> NoReturn:
|
||||||
"""
|
"""
|
||||||
A function that takes in a string and exits the program
|
A function that takes in a string and exits the program
|
||||||
|
|
||||||
|
|||||||
@@ -1,20 +1,24 @@
|
|||||||
"""Browse a webpage and summarize it using the LLM model"""
|
"""Browse a webpage and summarize it using the LLM model"""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
from bs4 import BeautifulSoup
|
from bs4 import BeautifulSoup
|
||||||
from requests import Response
|
from requests import Response
|
||||||
|
|
||||||
from autogpt.config import Config
|
|
||||||
from autogpt.processing.html import extract_hyperlinks, format_hyperlinks
|
from autogpt.processing.html import extract_hyperlinks, format_hyperlinks
|
||||||
from autogpt.url_utils.validators import validate_url
|
from autogpt.url_utils.validators import validate_url
|
||||||
|
|
||||||
session = requests.Session()
|
session = requests.Session()
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from autogpt.agent.agent import Agent
|
||||||
|
|
||||||
|
|
||||||
@validate_url
|
@validate_url
|
||||||
def get_response(
|
def get_response(
|
||||||
url: str, config: Config, timeout: int = 10
|
url: str, agent: Agent, timeout: int = 10
|
||||||
) -> tuple[None, str] | tuple[Response, None]:
|
) -> tuple[None, str] | tuple[Response, None]:
|
||||||
"""Get the response from a URL
|
"""Get the response from a URL
|
||||||
|
|
||||||
@@ -30,7 +34,7 @@ def get_response(
|
|||||||
requests.exceptions.RequestException: If the HTTP request fails
|
requests.exceptions.RequestException: If the HTTP request fails
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
session.headers.update({"User-Agent": config.user_agent})
|
session.headers.update({"User-Agent": agent.config.user_agent})
|
||||||
response = session.get(url, timeout=timeout)
|
response = session.get(url, timeout=timeout)
|
||||||
|
|
||||||
# Check if the response contains an HTTP error
|
# Check if the response contains an HTTP error
|
||||||
@@ -48,7 +52,7 @@ def get_response(
|
|||||||
return None, f"Error: {str(re)}"
|
return None, f"Error: {str(re)}"
|
||||||
|
|
||||||
|
|
||||||
def scrape_text(url: str, config: Config) -> str:
|
def scrape_text(url: str, agent: Agent) -> str:
|
||||||
"""Scrape text from a webpage
|
"""Scrape text from a webpage
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@@ -57,7 +61,7 @@ def scrape_text(url: str, config: Config) -> str:
|
|||||||
Returns:
|
Returns:
|
||||||
str: The scraped text
|
str: The scraped text
|
||||||
"""
|
"""
|
||||||
response, error_message = get_response(url, config)
|
response, error_message = get_response(url, agent)
|
||||||
if error_message:
|
if error_message:
|
||||||
return error_message
|
return error_message
|
||||||
if not response:
|
if not response:
|
||||||
@@ -76,7 +80,7 @@ def scrape_text(url: str, config: Config) -> str:
|
|||||||
return text
|
return text
|
||||||
|
|
||||||
|
|
||||||
def scrape_links(url: str, config: Config) -> str | list[str]:
|
def scrape_links(url: str, agent: Agent) -> str | list[str]:
|
||||||
"""Scrape links from a webpage
|
"""Scrape links from a webpage
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@@ -85,7 +89,7 @@ def scrape_links(url: str, config: Config) -> str | list[str]:
|
|||||||
Returns:
|
Returns:
|
||||||
str | list[str]: The scraped links
|
str | list[str]: The scraped links
|
||||||
"""
|
"""
|
||||||
response, error_message = get_response(url, config)
|
response, error_message = get_response(url, agent)
|
||||||
if error_message:
|
if error_message:
|
||||||
return error_message
|
return error_message
|
||||||
if not response:
|
if not response:
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ from __future__ import annotations
|
|||||||
import logging
|
import logging
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from sys import platform
|
from sys import platform
|
||||||
from typing import TYPE_CHECKING, Optional, Type
|
from typing import Optional, Type
|
||||||
|
|
||||||
from bs4 import BeautifulSoup
|
from bs4 import BeautifulSoup
|
||||||
from selenium.common.exceptions import WebDriverException
|
from selenium.common.exceptions import WebDriverException
|
||||||
@@ -27,15 +27,13 @@ from webdriver_manager.chrome import ChromeDriverManager
|
|||||||
from webdriver_manager.firefox import GeckoDriverManager
|
from webdriver_manager.firefox import GeckoDriverManager
|
||||||
from webdriver_manager.microsoft import EdgeChromiumDriverManager as EdgeDriverManager
|
from webdriver_manager.microsoft import EdgeChromiumDriverManager as EdgeDriverManager
|
||||||
|
|
||||||
|
from autogpt.agent.agent import Agent
|
||||||
from autogpt.commands.command import command
|
from autogpt.commands.command import command
|
||||||
from autogpt.logs import logger
|
from autogpt.logs import logger
|
||||||
from autogpt.memory.vector import MemoryItem, get_memory
|
from autogpt.memory.vector import MemoryItem, get_memory
|
||||||
from autogpt.processing.html import extract_hyperlinks, format_hyperlinks
|
from autogpt.processing.html import extract_hyperlinks, format_hyperlinks
|
||||||
from autogpt.url_utils.validators import validate_url
|
from autogpt.url_utils.validators import validate_url
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from autogpt.config import Config
|
|
||||||
|
|
||||||
BrowserOptions = ChromeOptions | EdgeOptions | FirefoxOptions | SafariOptions
|
BrowserOptions = ChromeOptions | EdgeOptions | FirefoxOptions | SafariOptions
|
||||||
|
|
||||||
FILE_DIR = Path(__file__).parent.parent
|
FILE_DIR = Path(__file__).parent.parent
|
||||||
@@ -47,7 +45,7 @@ FILE_DIR = Path(__file__).parent.parent
|
|||||||
'"url": "<url>", "question": "<what_you_want_to_find_on_website>"',
|
'"url": "<url>", "question": "<what_you_want_to_find_on_website>"',
|
||||||
)
|
)
|
||||||
@validate_url
|
@validate_url
|
||||||
def browse_website(url: str, question: str, config: Config) -> str:
|
def browse_website(url: str, question: str, agent: Agent) -> str:
|
||||||
"""Browse a website and return the answer and links to the user
|
"""Browse a website and return the answer and links to the user
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@@ -58,7 +56,7 @@ def browse_website(url: str, question: str, config: Config) -> str:
|
|||||||
Tuple[str, WebDriver]: The answer and links to the user and the webdriver
|
Tuple[str, WebDriver]: The answer and links to the user and the webdriver
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
driver, text = scrape_text_with_selenium(url, config)
|
driver, text = scrape_text_with_selenium(url, agent)
|
||||||
except WebDriverException as e:
|
except WebDriverException as e:
|
||||||
# These errors are often quite long and include lots of context.
|
# These errors are often quite long and include lots of context.
|
||||||
# Just grab the first line.
|
# Just grab the first line.
|
||||||
@@ -66,7 +64,7 @@ def browse_website(url: str, question: str, config: Config) -> str:
|
|||||||
return f"Error: {msg}"
|
return f"Error: {msg}"
|
||||||
|
|
||||||
add_header(driver)
|
add_header(driver)
|
||||||
summary = summarize_memorize_webpage(url, text, question, config, driver)
|
summary = summarize_memorize_webpage(url, text, question, agent, driver)
|
||||||
links = scrape_links_with_selenium(driver, url)
|
links = scrape_links_with_selenium(driver, url)
|
||||||
|
|
||||||
# Limit links to 5
|
# Limit links to 5
|
||||||
@@ -76,7 +74,7 @@ def browse_website(url: str, question: str, config: Config) -> str:
|
|||||||
return f"Answer gathered from website: {summary}\n\nLinks: {links}"
|
return f"Answer gathered from website: {summary}\n\nLinks: {links}"
|
||||||
|
|
||||||
|
|
||||||
def scrape_text_with_selenium(url: str, config: Config) -> tuple[WebDriver, str]:
|
def scrape_text_with_selenium(url: str, agent: Agent) -> tuple[WebDriver, str]:
|
||||||
"""Scrape text from a website using selenium
|
"""Scrape text from a website using selenium
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@@ -94,23 +92,23 @@ def scrape_text_with_selenium(url: str, config: Config) -> tuple[WebDriver, str]
|
|||||||
"safari": SafariOptions,
|
"safari": SafariOptions,
|
||||||
}
|
}
|
||||||
|
|
||||||
options: BrowserOptions = options_available[config.selenium_web_browser]()
|
options: BrowserOptions = options_available[agent.config.selenium_web_browser]()
|
||||||
options.add_argument(
|
options.add_argument(
|
||||||
"user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.5615.49 Safari/537.36"
|
"user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.5615.49 Safari/537.36"
|
||||||
)
|
)
|
||||||
|
|
||||||
if config.selenium_web_browser == "firefox":
|
if agent.config.selenium_web_browser == "firefox":
|
||||||
if config.selenium_headless:
|
if agent.config.selenium_headless:
|
||||||
options.headless = True
|
options.headless = True
|
||||||
options.add_argument("--disable-gpu")
|
options.add_argument("--disable-gpu")
|
||||||
driver = FirefoxDriver(
|
driver = FirefoxDriver(
|
||||||
service=GeckoDriverService(GeckoDriverManager().install()), options=options
|
service=GeckoDriverService(GeckoDriverManager().install()), options=options
|
||||||
)
|
)
|
||||||
elif config.selenium_web_browser == "edge":
|
elif agent.config.selenium_web_browser == "edge":
|
||||||
driver = EdgeDriver(
|
driver = EdgeDriver(
|
||||||
service=EdgeDriverService(EdgeDriverManager().install()), options=options
|
service=EdgeDriverService(EdgeDriverManager().install()), options=options
|
||||||
)
|
)
|
||||||
elif config.selenium_web_browser == "safari":
|
elif agent.config.selenium_web_browser == "safari":
|
||||||
# Requires a bit more setup on the users end
|
# Requires a bit more setup on the users end
|
||||||
# See https://developer.apple.com/documentation/webkit/testing_with_webdriver_in_safari
|
# See https://developer.apple.com/documentation/webkit/testing_with_webdriver_in_safari
|
||||||
driver = SafariDriver(options=options)
|
driver = SafariDriver(options=options)
|
||||||
@@ -120,7 +118,7 @@ def scrape_text_with_selenium(url: str, config: Config) -> tuple[WebDriver, str]
|
|||||||
options.add_argument("--remote-debugging-port=9222")
|
options.add_argument("--remote-debugging-port=9222")
|
||||||
|
|
||||||
options.add_argument("--no-sandbox")
|
options.add_argument("--no-sandbox")
|
||||||
if config.selenium_headless:
|
if agent.config.selenium_headless:
|
||||||
options.add_argument("--headless=new")
|
options.add_argument("--headless=new")
|
||||||
options.add_argument("--disable-gpu")
|
options.add_argument("--disable-gpu")
|
||||||
|
|
||||||
@@ -205,7 +203,7 @@ def summarize_memorize_webpage(
|
|||||||
url: str,
|
url: str,
|
||||||
text: str,
|
text: str,
|
||||||
question: str,
|
question: str,
|
||||||
config: Config,
|
agent: Agent,
|
||||||
driver: Optional[WebDriver] = None,
|
driver: Optional[WebDriver] = None,
|
||||||
) -> str:
|
) -> str:
|
||||||
"""Summarize text using the OpenAI API
|
"""Summarize text using the OpenAI API
|
||||||
@@ -225,7 +223,7 @@ def summarize_memorize_webpage(
|
|||||||
text_length = len(text)
|
text_length = len(text)
|
||||||
logger.info(f"Text length: {text_length} characters")
|
logger.info(f"Text length: {text_length} characters")
|
||||||
|
|
||||||
memory = get_memory(config)
|
memory = get_memory(agent.config)
|
||||||
|
|
||||||
new_memory = MemoryItem.from_webpage(text, url, question=question)
|
new_memory = MemoryItem.from_webpage(text, url, question=question)
|
||||||
memory.add(new_memory)
|
memory.add(new_memory)
|
||||||
|
|||||||
@@ -2,21 +2,18 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import json
|
import json
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
|
from autogpt.agent.agent import Agent
|
||||||
from autogpt.commands.command import command
|
from autogpt.commands.command import command
|
||||||
from autogpt.llm.utils import call_ai_function
|
from autogpt.llm.utils import call_ai_function
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from autogpt.config import Config
|
|
||||||
|
|
||||||
|
|
||||||
@command(
|
@command(
|
||||||
"write_tests",
|
"write_tests",
|
||||||
"Write Tests",
|
"Write Tests",
|
||||||
'"code": "<full_code_string>", "focus": "<list_of_focus_areas>"',
|
'"code": "<full_code_string>", "focus": "<list_of_focus_areas>"',
|
||||||
)
|
)
|
||||||
def write_tests(code: str, focus: list[str], config: Config) -> str:
|
def write_tests(code: str, focus: list[str], agent: Agent) -> str:
|
||||||
"""
|
"""
|
||||||
A function that takes in code and focus topics and returns a response from create
|
A function that takes in code and focus topics and returns a response from create
|
||||||
chat completion api call.
|
chat completion api call.
|
||||||
@@ -38,4 +35,6 @@ def write_tests(code: str, focus: list[str], config: Config) -> str:
|
|||||||
" specific areas if required."
|
" specific areas if required."
|
||||||
)
|
)
|
||||||
|
|
||||||
return call_ai_function(function_string, args, description_string, config=config)
|
return call_ai_function(
|
||||||
|
function_string, args, description_string, config=agent.config
|
||||||
|
)
|
||||||
|
|||||||
@@ -181,7 +181,7 @@ def chat_with_ai(
|
|||||||
logger.debug("")
|
logger.debug("")
|
||||||
logger.debug("----------- END OF CONTEXT ----------------")
|
logger.debug("----------- END OF CONTEXT ----------------")
|
||||||
agent.log_cycle_handler.log_cycle(
|
agent.log_cycle_handler.log_cycle(
|
||||||
agent.ai_config.ai_name,
|
agent.ai_name,
|
||||||
agent.created_at,
|
agent.created_at,
|
||||||
agent.cycle_count,
|
agent.cycle_count,
|
||||||
message_sequence.raw(),
|
message_sequence.raw(),
|
||||||
|
|||||||
@@ -184,7 +184,7 @@ Latest Development:
|
|||||||
|
|
||||||
prompt = ChatSequence.for_model(cfg.fast_llm_model, [Message("user", prompt)])
|
prompt = ChatSequence.for_model(cfg.fast_llm_model, [Message("user", prompt)])
|
||||||
self.agent.log_cycle_handler.log_cycle(
|
self.agent.log_cycle_handler.log_cycle(
|
||||||
self.agent.ai_config.ai_name,
|
self.agent.ai_name,
|
||||||
self.agent.created_at,
|
self.agent.created_at,
|
||||||
self.agent.cycle_count,
|
self.agent.cycle_count,
|
||||||
prompt.raw(),
|
prompt.raw(),
|
||||||
@@ -194,7 +194,7 @@ Latest Development:
|
|||||||
self.summary = create_chat_completion(prompt)
|
self.summary = create_chat_completion(prompt)
|
||||||
|
|
||||||
self.agent.log_cycle_handler.log_cycle(
|
self.agent.log_cycle_handler.log_cycle(
|
||||||
self.agent.ai_config.ai_name,
|
self.agent.ai_name,
|
||||||
self.agent.created_at,
|
self.agent.created_at,
|
||||||
self.agent.cycle_count,
|
self.agent.cycle_count,
|
||||||
self.summary,
|
self.summary,
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import pytest
|
|||||||
|
|
||||||
from autogpt.agent import Agent
|
from autogpt.agent import Agent
|
||||||
from autogpt.commands.file_operations import read_file
|
from autogpt.commands.file_operations import read_file
|
||||||
from autogpt.config import Config
|
|
||||||
from tests.challenges.challenge_decorator.challenge_decorator import challenge
|
from tests.challenges.challenge_decorator.challenge_decorator import challenge
|
||||||
from tests.challenges.utils import get_workspace_path, run_interaction_loop
|
from tests.challenges.utils import get_workspace_path, run_interaction_loop
|
||||||
from tests.utils import requires_api_key
|
from tests.utils import requires_api_key
|
||||||
@@ -23,7 +22,6 @@ def test_write_file(
|
|||||||
file_system_agents: List[Agent],
|
file_system_agents: List[Agent],
|
||||||
patched_api_requestor: None,
|
patched_api_requestor: None,
|
||||||
monkeypatch: pytest.MonkeyPatch,
|
monkeypatch: pytest.MonkeyPatch,
|
||||||
config: Config,
|
|
||||||
level_to_run: int,
|
level_to_run: int,
|
||||||
) -> None:
|
) -> None:
|
||||||
file_system_agent = file_system_agents[level_to_run - 1]
|
file_system_agent = file_system_agents[level_to_run - 1]
|
||||||
@@ -35,7 +33,7 @@ def test_write_file(
|
|||||||
|
|
||||||
for file_name, expected_lines in expected_outputs.items():
|
for file_name, expected_lines in expected_outputs.items():
|
||||||
file_path = get_workspace_path(file_system_agent, file_name)
|
file_path = get_workspace_path(file_system_agent, file_name)
|
||||||
content = read_file(file_path, config)
|
content = read_file(file_path, file_system_agent)
|
||||||
for expected_line in expected_lines:
|
for expected_line in expected_lines:
|
||||||
assert (
|
assert (
|
||||||
expected_line in content
|
expected_line in content
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ from pytest_mock import MockerFixture
|
|||||||
|
|
||||||
from autogpt.agent import Agent
|
from autogpt.agent import Agent
|
||||||
from autogpt.commands.execute_code import execute_python_file
|
from autogpt.commands.execute_code import execute_python_file
|
||||||
from autogpt.config import Config
|
|
||||||
from tests.challenges.challenge_decorator.challenge_decorator import challenge
|
from tests.challenges.challenge_decorator.challenge_decorator import challenge
|
||||||
from tests.challenges.utils import (
|
from tests.challenges.utils import (
|
||||||
copy_file_into_workspace,
|
copy_file_into_workspace,
|
||||||
@@ -28,7 +27,6 @@ def test_debug_code_challenge_a(
|
|||||||
debug_code_agents: Agent,
|
debug_code_agents: Agent,
|
||||||
monkeypatch: pytest.MonkeyPatch,
|
monkeypatch: pytest.MonkeyPatch,
|
||||||
patched_api_requestor: MockerFixture,
|
patched_api_requestor: MockerFixture,
|
||||||
config: Config,
|
|
||||||
level_to_run: int,
|
level_to_run: int,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""
|
"""
|
||||||
@@ -37,7 +35,6 @@ def test_debug_code_challenge_a(
|
|||||||
:param debug_code_agent: The agent to test.
|
:param debug_code_agent: The agent to test.
|
||||||
:param monkeypatch: pytest's monkeypatch utility for modifying builtins.
|
:param monkeypatch: pytest's monkeypatch utility for modifying builtins.
|
||||||
:patched_api_requestor: Sends api requests to our API CI pipeline
|
:patched_api_requestor: Sends api requests to our API CI pipeline
|
||||||
:config: The config object for the agent.
|
|
||||||
:level_to_run: The level to run.
|
:level_to_run: The level to run.
|
||||||
"""
|
"""
|
||||||
debug_code_agent = debug_code_agents[level_to_run - 1]
|
debug_code_agent = debug_code_agents[level_to_run - 1]
|
||||||
@@ -48,7 +45,7 @@ def test_debug_code_challenge_a(
|
|||||||
run_interaction_loop(monkeypatch, debug_code_agent, CYCLE_COUNT)
|
run_interaction_loop(monkeypatch, debug_code_agent, CYCLE_COUNT)
|
||||||
|
|
||||||
output = execute_python_file(
|
output = execute_python_file(
|
||||||
get_workspace_path(debug_code_agent, TEST_FILE_PATH), config
|
get_workspace_path(debug_code_agent, TEST_FILE_PATH), debug_code_agent
|
||||||
)
|
)
|
||||||
|
|
||||||
assert "error" not in output.lower(), f"Errors found in output: {output}!"
|
assert "error" not in output.lower(), f"Errors found in output: {output}!"
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import pytest
|
|||||||
from pytest_mock import MockerFixture
|
from pytest_mock import MockerFixture
|
||||||
|
|
||||||
from autogpt.commands.file_operations import read_file
|
from autogpt.commands.file_operations import read_file
|
||||||
from autogpt.config import Config
|
|
||||||
from tests.challenges.challenge_decorator.challenge_decorator import challenge
|
from tests.challenges.challenge_decorator.challenge_decorator import challenge
|
||||||
from tests.challenges.utils import get_workspace_path, run_interaction_loop
|
from tests.challenges.utils import get_workspace_path, run_interaction_loop
|
||||||
from tests.utils import requires_api_key
|
from tests.utils import requires_api_key
|
||||||
@@ -21,7 +20,6 @@ def test_information_retrieval_challenge_a(
|
|||||||
information_retrieval_agents: Agent,
|
information_retrieval_agents: Agent,
|
||||||
monkeypatch: pytest.MonkeyPatch,
|
monkeypatch: pytest.MonkeyPatch,
|
||||||
patched_api_requestor: MockerFixture,
|
patched_api_requestor: MockerFixture,
|
||||||
config: Config,
|
|
||||||
level_to_run: int,
|
level_to_run: int,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""
|
"""
|
||||||
@@ -34,7 +32,7 @@ def test_information_retrieval_challenge_a(
|
|||||||
run_interaction_loop(monkeypatch, information_retrieval_agent, CYCLE_COUNT)
|
run_interaction_loop(monkeypatch, information_retrieval_agent, CYCLE_COUNT)
|
||||||
|
|
||||||
file_path = get_workspace_path(information_retrieval_agent, OUTPUT_LOCATION)
|
file_path = get_workspace_path(information_retrieval_agent, OUTPUT_LOCATION)
|
||||||
content = read_file(file_path, config)
|
content = read_file(file_path, information_retrieval_agent)
|
||||||
expected_revenues = EXPECTED_REVENUES[level_to_run - 1]
|
expected_revenues = EXPECTED_REVENUES[level_to_run - 1]
|
||||||
for revenue in expected_revenues:
|
for revenue in expected_revenues:
|
||||||
assert (
|
assert (
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ from pytest_mock import MockerFixture
|
|||||||
|
|
||||||
from autogpt.agent import Agent
|
from autogpt.agent import Agent
|
||||||
from autogpt.commands.file_operations import read_file
|
from autogpt.commands.file_operations import read_file
|
||||||
from autogpt.config import Config
|
|
||||||
from tests.challenges.challenge_decorator.challenge_decorator import challenge
|
from tests.challenges.challenge_decorator.challenge_decorator import challenge
|
||||||
from tests.challenges.utils import get_workspace_path, run_interaction_loop
|
from tests.challenges.utils import get_workspace_path, run_interaction_loop
|
||||||
from tests.utils import requires_api_key
|
from tests.utils import requires_api_key
|
||||||
@@ -22,7 +21,6 @@ def test_information_retrieval_challenge_b(
|
|||||||
monkeypatch: pytest.MonkeyPatch,
|
monkeypatch: pytest.MonkeyPatch,
|
||||||
patched_api_requestor: MockerFixture,
|
patched_api_requestor: MockerFixture,
|
||||||
level_to_run: int,
|
level_to_run: int,
|
||||||
config: Config,
|
|
||||||
) -> None:
|
) -> None:
|
||||||
"""
|
"""
|
||||||
Test the challenge_b function in a given agent by mocking user inputs and checking the output file content.
|
Test the challenge_b function in a given agent by mocking user inputs and checking the output file content.
|
||||||
@@ -31,14 +29,13 @@ def test_information_retrieval_challenge_b(
|
|||||||
:param monkeypatch: pytest's monkeypatch utility for modifying builtins.
|
:param monkeypatch: pytest's monkeypatch utility for modifying builtins.
|
||||||
:param patched_api_requestor: APIRequestor Patch to override the openai.api_requestor module for testing.
|
:param patched_api_requestor: APIRequestor Patch to override the openai.api_requestor module for testing.
|
||||||
:param level_to_run: The level to run.
|
:param level_to_run: The level to run.
|
||||||
:param config: The config object.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
with contextlib.suppress(SystemExit):
|
with contextlib.suppress(SystemExit):
|
||||||
run_interaction_loop(monkeypatch, get_nobel_prize_agent, CYCLE_COUNT)
|
run_interaction_loop(monkeypatch, get_nobel_prize_agent, CYCLE_COUNT)
|
||||||
file_path = get_workspace_path(get_nobel_prize_agent, OUTPUT_LOCATION)
|
file_path = get_workspace_path(get_nobel_prize_agent, OUTPUT_LOCATION)
|
||||||
|
|
||||||
content = read_file(file_path, config)
|
content = read_file(file_path, get_nobel_prize_agent)
|
||||||
assert "Andre Geim" in content, "Expected the file to contain Andre Geim"
|
assert "Andre Geim" in content, "Expected the file to contain Andre Geim"
|
||||||
assert (
|
assert (
|
||||||
"Konstantin Novoselov" in content
|
"Konstantin Novoselov" in content
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ from pytest_mock import MockerFixture
|
|||||||
|
|
||||||
from autogpt.agent import Agent
|
from autogpt.agent import Agent
|
||||||
from autogpt.commands.file_operations import read_file
|
from autogpt.commands.file_operations import read_file
|
||||||
from autogpt.config import Config
|
|
||||||
from tests.challenges.challenge_decorator.challenge_decorator import challenge
|
from tests.challenges.challenge_decorator.challenge_decorator import challenge
|
||||||
from tests.challenges.utils import get_workspace_path, run_interaction_loop
|
from tests.challenges.utils import get_workspace_path, run_interaction_loop
|
||||||
from tests.utils import requires_api_key
|
from tests.utils import requires_api_key
|
||||||
@@ -20,7 +19,6 @@ def test_kubernetes_template_challenge_a(
|
|||||||
kubernetes_agent: Agent,
|
kubernetes_agent: Agent,
|
||||||
monkeypatch: pytest.MonkeyPatch,
|
monkeypatch: pytest.MonkeyPatch,
|
||||||
patched_api_requestor: MockerFixture,
|
patched_api_requestor: MockerFixture,
|
||||||
config: Config,
|
|
||||||
level_to_run: int,
|
level_to_run: int,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""
|
"""
|
||||||
@@ -30,13 +28,12 @@ def test_kubernetes_template_challenge_a(
|
|||||||
Args:
|
Args:
|
||||||
kubernetes_agent (Agent)
|
kubernetes_agent (Agent)
|
||||||
monkeypatch (pytest.MonkeyPatch)
|
monkeypatch (pytest.MonkeyPatch)
|
||||||
config (Config)
|
|
||||||
level_to_run (int)
|
level_to_run (int)
|
||||||
"""
|
"""
|
||||||
run_interaction_loop(monkeypatch, kubernetes_agent, CYCLE_COUNT)
|
run_interaction_loop(monkeypatch, kubernetes_agent, CYCLE_COUNT)
|
||||||
|
|
||||||
file_path = get_workspace_path(kubernetes_agent, OUTPUT_LOCATION)
|
file_path = get_workspace_path(kubernetes_agent, OUTPUT_LOCATION)
|
||||||
content = read_file(file_path, config)
|
content = read_file(file_path, kubernetes_agent)
|
||||||
|
|
||||||
for word in ["apiVersion", "kind", "metadata", "spec"]:
|
for word in ["apiVersion", "kind", "metadata", "spec"]:
|
||||||
assert word in content, f"Expected the file to contain {word}"
|
assert word in content, f"Expected the file to contain {word}"
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ from pytest_mock import MockerFixture
|
|||||||
|
|
||||||
from autogpt.agent import Agent
|
from autogpt.agent import Agent
|
||||||
from autogpt.commands.file_operations import read_file, write_to_file
|
from autogpt.commands.file_operations import read_file, write_to_file
|
||||||
from autogpt.config import Config
|
|
||||||
from tests.challenges.challenge_decorator.challenge_decorator import challenge
|
from tests.challenges.challenge_decorator.challenge_decorator import challenge
|
||||||
from tests.challenges.utils import get_workspace_path, run_interaction_loop
|
from tests.challenges.utils import get_workspace_path, run_interaction_loop
|
||||||
from tests.utils import requires_api_key
|
from tests.utils import requires_api_key
|
||||||
@@ -18,7 +17,6 @@ def test_memory_challenge_a(
|
|||||||
memory_management_agent: Agent,
|
memory_management_agent: Agent,
|
||||||
patched_api_requestor: MockerFixture,
|
patched_api_requestor: MockerFixture,
|
||||||
monkeypatch: pytest.MonkeyPatch,
|
monkeypatch: pytest.MonkeyPatch,
|
||||||
config: Config,
|
|
||||||
level_to_run: int,
|
level_to_run: int,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""
|
"""
|
||||||
@@ -28,17 +26,16 @@ def test_memory_challenge_a(
|
|||||||
memory_management_agent (Agent)
|
memory_management_agent (Agent)
|
||||||
patched_api_requestor (MockerFixture)
|
patched_api_requestor (MockerFixture)
|
||||||
monkeypatch (pytest.MonkeyPatch)
|
monkeypatch (pytest.MonkeyPatch)
|
||||||
config (Config)
|
|
||||||
level_to_run (int)
|
level_to_run (int)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
task_id = "2314"
|
task_id = "2314"
|
||||||
create_instructions_files(memory_management_agent, level_to_run, task_id, config)
|
create_instructions_files(memory_management_agent, level_to_run, task_id)
|
||||||
|
|
||||||
run_interaction_loop(monkeypatch, memory_management_agent, level_to_run + 2)
|
run_interaction_loop(monkeypatch, memory_management_agent, level_to_run + 2)
|
||||||
|
|
||||||
file_path = get_workspace_path(memory_management_agent, OUTPUT_LOCATION)
|
file_path = get_workspace_path(memory_management_agent, OUTPUT_LOCATION)
|
||||||
content = read_file(file_path, config)
|
content = read_file(file_path, memory_management_agent)
|
||||||
assert task_id in content, f"Expected the file to contain {task_id}"
|
assert task_id in content, f"Expected the file to contain {task_id}"
|
||||||
|
|
||||||
|
|
||||||
@@ -46,7 +43,6 @@ def create_instructions_files(
|
|||||||
memory_management_agent: Agent,
|
memory_management_agent: Agent,
|
||||||
num_files: int,
|
num_files: int,
|
||||||
task_id: str,
|
task_id: str,
|
||||||
config: Config,
|
|
||||||
base_filename: str = "instructions_",
|
base_filename: str = "instructions_",
|
||||||
) -> None:
|
) -> None:
|
||||||
"""
|
"""
|
||||||
@@ -61,7 +57,7 @@ def create_instructions_files(
|
|||||||
content = generate_content(i, task_id, base_filename, num_files)
|
content = generate_content(i, task_id, base_filename, num_files)
|
||||||
file_name = f"{base_filename}{i}.txt"
|
file_name = f"{base_filename}{i}.txt"
|
||||||
file_path = get_workspace_path(memory_management_agent, file_name)
|
file_path = get_workspace_path(memory_management_agent, file_name)
|
||||||
write_to_file(file_path, content, config)
|
write_to_file(file_path, content, memory_management_agent)
|
||||||
|
|
||||||
|
|
||||||
def generate_content(
|
def generate_content(
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ from pytest_mock import MockerFixture
|
|||||||
|
|
||||||
from autogpt.agent import Agent
|
from autogpt.agent import Agent
|
||||||
from autogpt.commands.file_operations import read_file, write_to_file
|
from autogpt.commands.file_operations import read_file, write_to_file
|
||||||
from autogpt.config import Config
|
|
||||||
from tests.challenges.challenge_decorator.challenge_decorator import challenge
|
from tests.challenges.challenge_decorator.challenge_decorator import challenge
|
||||||
from tests.challenges.utils import (
|
from tests.challenges.utils import (
|
||||||
generate_noise,
|
generate_noise,
|
||||||
@@ -23,7 +22,6 @@ def test_memory_challenge_b(
|
|||||||
memory_management_agent: Agent,
|
memory_management_agent: Agent,
|
||||||
patched_api_requestor: MockerFixture,
|
patched_api_requestor: MockerFixture,
|
||||||
monkeypatch: pytest.MonkeyPatch,
|
monkeypatch: pytest.MonkeyPatch,
|
||||||
config: Config,
|
|
||||||
level_to_run: int,
|
level_to_run: int,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""
|
"""
|
||||||
@@ -37,12 +35,12 @@ def test_memory_challenge_b(
|
|||||||
level_to_run (int)
|
level_to_run (int)
|
||||||
"""
|
"""
|
||||||
task_ids = [str(i * 1111) for i in range(1, level_to_run + 1)]
|
task_ids = [str(i * 1111) for i in range(1, level_to_run + 1)]
|
||||||
create_instructions_files(memory_management_agent, level_to_run, task_ids, config)
|
create_instructions_files(memory_management_agent, level_to_run, task_ids)
|
||||||
|
|
||||||
run_interaction_loop(monkeypatch, memory_management_agent, level_to_run + 2)
|
run_interaction_loop(monkeypatch, memory_management_agent, level_to_run + 2)
|
||||||
|
|
||||||
file_path = get_workspace_path(memory_management_agent, OUTPUT_LOCATION)
|
file_path = get_workspace_path(memory_management_agent, OUTPUT_LOCATION)
|
||||||
content = read_file(file_path, config)
|
content = read_file(file_path, memory_management_agent)
|
||||||
for task_id in task_ids:
|
for task_id in task_ids:
|
||||||
assert task_id in content, f"Expected the file to contain {task_id}"
|
assert task_id in content, f"Expected the file to contain {task_id}"
|
||||||
|
|
||||||
@@ -51,7 +49,6 @@ def create_instructions_files(
|
|||||||
memory_management_agent: Agent,
|
memory_management_agent: Agent,
|
||||||
level: int,
|
level: int,
|
||||||
task_ids: list,
|
task_ids: list,
|
||||||
config: Config,
|
|
||||||
base_filename: str = "instructions_",
|
base_filename: str = "instructions_",
|
||||||
) -> None:
|
) -> None:
|
||||||
"""
|
"""
|
||||||
@@ -68,7 +65,7 @@ def create_instructions_files(
|
|||||||
file_name = f"{base_filename}{i}.txt"
|
file_name = f"{base_filename}{i}.txt"
|
||||||
file_path = get_workspace_path(memory_management_agent, file_name)
|
file_path = get_workspace_path(memory_management_agent, file_name)
|
||||||
|
|
||||||
write_to_file(file_path, content, config)
|
write_to_file(file_path, content, memory_management_agent)
|
||||||
|
|
||||||
|
|
||||||
def generate_content(index: int, task_ids: list, base_filename: str, level: int) -> str:
|
def generate_content(index: int, task_ids: list, base_filename: str, level: int) -> str:
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ from pytest_mock import MockerFixture
|
|||||||
|
|
||||||
from autogpt.agent import Agent
|
from autogpt.agent import Agent
|
||||||
from autogpt.commands.file_operations import read_file, write_to_file
|
from autogpt.commands.file_operations import read_file, write_to_file
|
||||||
from autogpt.config import Config
|
|
||||||
from tests.challenges.challenge_decorator.challenge_decorator import challenge
|
from tests.challenges.challenge_decorator.challenge_decorator import challenge
|
||||||
from tests.challenges.utils import (
|
from tests.challenges.utils import (
|
||||||
generate_noise,
|
generate_noise,
|
||||||
@@ -24,7 +23,6 @@ def test_memory_challenge_c(
|
|||||||
memory_management_agent: Agent,
|
memory_management_agent: Agent,
|
||||||
patched_api_requestor: MockerFixture,
|
patched_api_requestor: MockerFixture,
|
||||||
monkeypatch: pytest.MonkeyPatch,
|
monkeypatch: pytest.MonkeyPatch,
|
||||||
config: Config,
|
|
||||||
level_to_run: int,
|
level_to_run: int,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""
|
"""
|
||||||
@@ -36,7 +34,6 @@ def test_memory_challenge_c(
|
|||||||
memory_management_agent (Agent)
|
memory_management_agent (Agent)
|
||||||
patched_api_requestor (MockerFixture)
|
patched_api_requestor (MockerFixture)
|
||||||
monkeypatch (pytest.MonkeyPatch)
|
monkeypatch (pytest.MonkeyPatch)
|
||||||
config (Config)
|
|
||||||
level_to_run (int)
|
level_to_run (int)
|
||||||
"""
|
"""
|
||||||
silly_phrases = [
|
silly_phrases = [
|
||||||
@@ -54,12 +51,14 @@ def test_memory_challenge_c(
|
|||||||
|
|
||||||
level_silly_phrases = silly_phrases[:level_to_run]
|
level_silly_phrases = silly_phrases[:level_to_run]
|
||||||
create_instructions_files(
|
create_instructions_files(
|
||||||
memory_management_agent, level_to_run, level_silly_phrases, config=config
|
memory_management_agent,
|
||||||
|
level_to_run,
|
||||||
|
level_silly_phrases,
|
||||||
)
|
)
|
||||||
|
|
||||||
run_interaction_loop(monkeypatch, memory_management_agent, level_to_run + 2)
|
run_interaction_loop(monkeypatch, memory_management_agent, level_to_run + 2)
|
||||||
file_path = get_workspace_path(memory_management_agent, OUTPUT_LOCATION)
|
file_path = get_workspace_path(memory_management_agent, OUTPUT_LOCATION)
|
||||||
content = read_file(file_path, config)
|
content = read_file(file_path, agent=memory_management_agent)
|
||||||
for phrase in level_silly_phrases:
|
for phrase in level_silly_phrases:
|
||||||
assert phrase in content, f"Expected the file to contain {phrase}"
|
assert phrase in content, f"Expected the file to contain {phrase}"
|
||||||
|
|
||||||
@@ -68,7 +67,6 @@ def create_instructions_files(
|
|||||||
memory_management_agent: Agent,
|
memory_management_agent: Agent,
|
||||||
level: int,
|
level: int,
|
||||||
task_ids: list,
|
task_ids: list,
|
||||||
config: Config,
|
|
||||||
base_filename: str = "instructions_",
|
base_filename: str = "instructions_",
|
||||||
) -> None:
|
) -> None:
|
||||||
"""
|
"""
|
||||||
@@ -84,7 +82,7 @@ def create_instructions_files(
|
|||||||
content = generate_content(i, task_ids, base_filename, level)
|
content = generate_content(i, task_ids, base_filename, level)
|
||||||
file_name = f"{base_filename}{i}.txt"
|
file_name = f"{base_filename}{i}.txt"
|
||||||
file_path = get_workspace_path(memory_management_agent, file_name)
|
file_path = get_workspace_path(memory_management_agent, file_name)
|
||||||
write_to_file(file_path, content, config)
|
write_to_file(file_path, content, memory_management_agent)
|
||||||
|
|
||||||
|
|
||||||
def generate_content(
|
def generate_content(
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ from pytest_mock import MockerFixture
|
|||||||
|
|
||||||
from autogpt.agent import Agent
|
from autogpt.agent import Agent
|
||||||
from autogpt.commands.file_operations import read_file, write_to_file
|
from autogpt.commands.file_operations import read_file, write_to_file
|
||||||
from autogpt.config import Config
|
|
||||||
from tests.challenges.challenge_decorator.challenge_decorator import challenge
|
from tests.challenges.challenge_decorator.challenge_decorator import challenge
|
||||||
from tests.challenges.utils import get_workspace_path, run_interaction_loop
|
from tests.challenges.utils import get_workspace_path, run_interaction_loop
|
||||||
from tests.utils import requires_api_key
|
from tests.utils import requires_api_key
|
||||||
@@ -23,7 +22,6 @@ def test_memory_challenge_d(
|
|||||||
memory_management_agent: Agent,
|
memory_management_agent: Agent,
|
||||||
patched_api_requestor: MockerFixture,
|
patched_api_requestor: MockerFixture,
|
||||||
monkeypatch: pytest.MonkeyPatch,
|
monkeypatch: pytest.MonkeyPatch,
|
||||||
config: Config,
|
|
||||||
level_to_run: int,
|
level_to_run: int,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""
|
"""
|
||||||
@@ -41,12 +39,12 @@ def test_memory_challenge_d(
|
|||||||
]
|
]
|
||||||
level_sally_anne_test_phrases = sally_anne_test_phrases[:level_to_run]
|
level_sally_anne_test_phrases = sally_anne_test_phrases[:level_to_run]
|
||||||
create_instructions_files(
|
create_instructions_files(
|
||||||
memory_management_agent, level_to_run, level_sally_anne_test_phrases, config
|
memory_management_agent, level_to_run, level_sally_anne_test_phrases
|
||||||
)
|
)
|
||||||
run_interaction_loop(monkeypatch, memory_management_agent, level_to_run + 2)
|
run_interaction_loop(monkeypatch, memory_management_agent, level_to_run + 2)
|
||||||
file_path = get_workspace_path(memory_management_agent, OUTPUT_LOCATION)
|
file_path = get_workspace_path(memory_management_agent, OUTPUT_LOCATION)
|
||||||
|
|
||||||
content = read_file(file_path, config)
|
content = read_file(file_path, memory_management_agent)
|
||||||
check_beliefs(content, level_to_run)
|
check_beliefs(content, level_to_run)
|
||||||
|
|
||||||
|
|
||||||
@@ -177,7 +175,6 @@ def create_instructions_files(
|
|||||||
memory_management_agent: Agent,
|
memory_management_agent: Agent,
|
||||||
level: int,
|
level: int,
|
||||||
test_phrases: list,
|
test_phrases: list,
|
||||||
config: Config,
|
|
||||||
base_filename: str = "instructions_",
|
base_filename: str = "instructions_",
|
||||||
) -> None:
|
) -> None:
|
||||||
"""
|
"""
|
||||||
@@ -186,14 +183,13 @@ def create_instructions_files(
|
|||||||
level:
|
level:
|
||||||
memory_management_agent (Agent)
|
memory_management_agent (Agent)
|
||||||
test_phrases (list)
|
test_phrases (list)
|
||||||
config (Config)
|
|
||||||
base_filename (str, optional)
|
base_filename (str, optional)
|
||||||
"""
|
"""
|
||||||
for i in range(1, level + 1):
|
for i in range(1, level + 1):
|
||||||
content = generate_content(i, test_phrases, base_filename, level)
|
content = generate_content(i, test_phrases, base_filename, level)
|
||||||
file_name = f"{base_filename}{i}.txt"
|
file_name = f"{base_filename}{i}.txt"
|
||||||
file_path = get_workspace_path(memory_management_agent, file_name)
|
file_path = get_workspace_path(memory_management_agent, file_name)
|
||||||
write_to_file(file_path, content, config)
|
write_to_file(file_path, content, memory_management_agent)
|
||||||
|
|
||||||
|
|
||||||
def generate_content(
|
def generate_content(
|
||||||
|
|||||||
@@ -4,9 +4,14 @@ from pathlib import Path
|
|||||||
import pytest
|
import pytest
|
||||||
from pytest_mock import MockerFixture
|
from pytest_mock import MockerFixture
|
||||||
|
|
||||||
|
from autogpt.agent.agent import Agent
|
||||||
|
from autogpt.commands.command import CommandRegistry
|
||||||
|
from autogpt.config.ai_config import AIConfig
|
||||||
from autogpt.config.config import Config
|
from autogpt.config.config import Config
|
||||||
from autogpt.llm.api_manager import ApiManager
|
from autogpt.llm.api_manager import ApiManager
|
||||||
from autogpt.logs import TypingConsoleHandler
|
from autogpt.logs import TypingConsoleHandler
|
||||||
|
from autogpt.memory.vector import get_memory
|
||||||
|
from autogpt.prompts.prompt import DEFAULT_TRIGGERING_PROMPT
|
||||||
from autogpt.workspace import Workspace
|
from autogpt.workspace import Workspace
|
||||||
|
|
||||||
pytest_plugins = [
|
pytest_plugins = [
|
||||||
@@ -57,3 +62,32 @@ def patch_emit(monkeypatch):
|
|||||||
print(self.format(record))
|
print(self.format(record))
|
||||||
|
|
||||||
monkeypatch.setattr(TypingConsoleHandler, "emit", quick_emit)
|
monkeypatch.setattr(TypingConsoleHandler, "emit", quick_emit)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def agent(config: Config, workspace: Workspace) -> Agent:
|
||||||
|
ai_config = AIConfig(
|
||||||
|
ai_name="Base",
|
||||||
|
ai_role="A base AI",
|
||||||
|
ai_goals=[],
|
||||||
|
)
|
||||||
|
|
||||||
|
command_registry = CommandRegistry()
|
||||||
|
ai_config.command_registry = command_registry
|
||||||
|
|
||||||
|
config.set_memory_backend("json_file")
|
||||||
|
memory_json_file = get_memory(config, init=True)
|
||||||
|
|
||||||
|
system_prompt = ai_config.construct_full_prompt()
|
||||||
|
|
||||||
|
return Agent(
|
||||||
|
ai_name=ai_config.ai_name,
|
||||||
|
memory=memory_json_file,
|
||||||
|
command_registry=command_registry,
|
||||||
|
ai_config=ai_config,
|
||||||
|
config=config,
|
||||||
|
next_action_count=0,
|
||||||
|
system_prompt=system_prompt,
|
||||||
|
triggering_prompt=DEFAULT_TRIGGERING_PROMPT,
|
||||||
|
workspace_directory=workspace.root,
|
||||||
|
)
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ from typing import Callable
|
|||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
import autogpt.commands.execute_code as sut # system under testing
|
import autogpt.commands.execute_code as sut # system under testing
|
||||||
|
from autogpt.agent.agent import Agent
|
||||||
from autogpt.config import Config
|
from autogpt.config import Config
|
||||||
from autogpt.config.ai_config import AIConfig
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
@@ -31,54 +31,54 @@ def random_string():
|
|||||||
return "".join(random.choice(string.ascii_lowercase) for _ in range(10))
|
return "".join(random.choice(string.ascii_lowercase) for _ in range(10))
|
||||||
|
|
||||||
|
|
||||||
def test_execute_python_file(python_test_file: str, random_string: str, config):
|
def test_execute_python_file(python_test_file: str, random_string: str, agent: Agent):
|
||||||
result: str = sut.execute_python_file(python_test_file, config)
|
result: str = sut.execute_python_file(python_test_file, agent=agent)
|
||||||
assert result.replace("\r", "") == f"Hello {random_string}!\n"
|
assert result.replace("\r", "") == f"Hello {random_string}!\n"
|
||||||
|
|
||||||
|
|
||||||
def test_execute_python_code(random_code: str, random_string: str, config: Config):
|
def test_execute_python_code(random_code: str, random_string: str, agent: Agent):
|
||||||
ai_name = AIConfig.load(config.ai_settings_file).ai_name
|
ai_name = agent.ai_name
|
||||||
|
|
||||||
result: str = sut.execute_python_code(random_code, "test_code", config)
|
result: str = sut.execute_python_code(random_code, "test_code", agent=agent)
|
||||||
assert result.replace("\r", "") == f"Hello {random_string}!\n"
|
assert result.replace("\r", "") == f"Hello {random_string}!\n"
|
||||||
|
|
||||||
# Check that the code is stored
|
# Check that the code is stored
|
||||||
destination = os.path.join(
|
destination = os.path.join(
|
||||||
config.workspace_path, ai_name, "executed_code", "test_code.py"
|
agent.config.workspace_path, ai_name, "executed_code", "test_code.py"
|
||||||
)
|
)
|
||||||
with open(destination) as f:
|
with open(destination) as f:
|
||||||
assert f.read() == random_code
|
assert f.read() == random_code
|
||||||
|
|
||||||
|
|
||||||
def test_execute_python_code_overwrites_file(
|
def test_execute_python_code_overwrites_file(
|
||||||
random_code: str, random_string: str, config: Config
|
random_code: str, random_string: str, agent: Agent
|
||||||
):
|
):
|
||||||
ai_name = AIConfig.load(config.ai_settings_file).ai_name
|
ai_name = agent.ai_name
|
||||||
destination = os.path.join(
|
destination = os.path.join(
|
||||||
config.workspace_path, ai_name, "executed_code", "test_code.py"
|
agent.config.workspace_path, ai_name, "executed_code", "test_code.py"
|
||||||
)
|
)
|
||||||
os.makedirs(os.path.dirname(destination), exist_ok=True)
|
os.makedirs(os.path.dirname(destination), exist_ok=True)
|
||||||
|
|
||||||
with open(destination, "w+") as f:
|
with open(destination, "w+") as f:
|
||||||
f.write("This will be overwritten")
|
f.write("This will be overwritten")
|
||||||
|
|
||||||
sut.execute_python_code(random_code, "test_code.py", config)
|
sut.execute_python_code(random_code, "test_code.py", agent=agent)
|
||||||
|
|
||||||
# Check that the file is updated with the new code
|
# Check that the file is updated with the new code
|
||||||
with open(destination) as f:
|
with open(destination) as f:
|
||||||
assert f.read() == random_code
|
assert f.read() == random_code
|
||||||
|
|
||||||
|
|
||||||
def test_execute_python_file_invalid(config: Config):
|
def test_execute_python_file_invalid(agent: Agent):
|
||||||
assert all(
|
assert all(
|
||||||
s in sut.execute_python_file("not_python", config).lower()
|
s in sut.execute_python_file("not_python", agent).lower()
|
||||||
for s in ["error:", "invalid", ".py"]
|
for s in ["error:", "invalid", ".py"]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_execute_python_file_not_found(config: Config):
|
def test_execute_python_file_not_found(agent: Agent):
|
||||||
assert all(
|
assert all(
|
||||||
s in sut.execute_python_file("notexist.py", config).lower()
|
s in sut.execute_python_file("notexist.py", agent).lower()
|
||||||
for s in [
|
for s in [
|
||||||
"python: can't open file 'notexist.py'",
|
"python: can't open file 'notexist.py'",
|
||||||
"[errno 2] no such file or directory",
|
"[errno 2] no such file or directory",
|
||||||
@@ -86,43 +86,43 @@ def test_execute_python_file_not_found(config: Config):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_execute_shell(random_string: str, config: Config):
|
def test_execute_shell(random_string: str, agent: Agent):
|
||||||
result = sut.execute_shell(f"echo 'Hello {random_string}!'", config)
|
result = sut.execute_shell(f"echo 'Hello {random_string}!'", agent)
|
||||||
assert f"Hello {random_string}!" in result
|
assert f"Hello {random_string}!" in result
|
||||||
|
|
||||||
|
|
||||||
def test_execute_shell_local_commands_not_allowed(random_string: str, config: Config):
|
def test_execute_shell_local_commands_not_allowed(random_string: str, agent: Agent):
|
||||||
result = sut.execute_shell(f"echo 'Hello {random_string}!'", config)
|
result = sut.execute_shell(f"echo 'Hello {random_string}!'", agent)
|
||||||
assert f"Hello {random_string}!" in result
|
assert f"Hello {random_string}!" in result
|
||||||
|
|
||||||
|
|
||||||
def test_execute_shell_denylist_should_deny(config: Config, random_string: str):
|
def test_execute_shell_denylist_should_deny(agent: Agent, random_string: str):
|
||||||
config.shell_denylist = ["echo"]
|
agent.config.shell_denylist = ["echo"]
|
||||||
|
|
||||||
result = sut.execute_shell(f"echo 'Hello {random_string}!'", config)
|
result = sut.execute_shell(f"echo 'Hello {random_string}!'", agent)
|
||||||
assert "Error:" in result and "not allowed" in result
|
assert "Error:" in result and "not allowed" in result
|
||||||
|
|
||||||
|
|
||||||
def test_execute_shell_denylist_should_allow(config: Config, random_string: str):
|
def test_execute_shell_denylist_should_allow(agent: Agent, random_string: str):
|
||||||
config.shell_denylist = ["cat"]
|
agent.config.shell_denylist = ["cat"]
|
||||||
|
|
||||||
result = sut.execute_shell(f"echo 'Hello {random_string}!'", config)
|
result = sut.execute_shell(f"echo 'Hello {random_string}!'", agent)
|
||||||
assert "Hello" in result and random_string in result
|
assert "Hello" in result and random_string in result
|
||||||
assert "Error" not in result
|
assert "Error" not in result
|
||||||
|
|
||||||
|
|
||||||
def test_execute_shell_allowlist_should_deny(config: Config, random_string: str):
|
def test_execute_shell_allowlist_should_deny(agent: Agent, random_string: str):
|
||||||
config.shell_command_control = sut.ALLOWLIST_CONTROL
|
agent.config.shell_command_control = sut.ALLOWLIST_CONTROL
|
||||||
config.shell_allowlist = ["cat"]
|
agent.config.shell_allowlist = ["cat"]
|
||||||
|
|
||||||
result = sut.execute_shell(f"echo 'Hello {random_string}!'", config)
|
result = sut.execute_shell(f"echo 'Hello {random_string}!'", agent)
|
||||||
assert "Error:" in result and "not allowed" in result
|
assert "Error:" in result and "not allowed" in result
|
||||||
|
|
||||||
|
|
||||||
def test_execute_shell_allowlist_should_allow(config: Config, random_string: str):
|
def test_execute_shell_allowlist_should_allow(agent: Agent, random_string: str):
|
||||||
config.shell_command_control = sut.ALLOWLIST_CONTROL
|
agent.config.shell_command_control = sut.ALLOWLIST_CONTROL
|
||||||
config.shell_allowlist = ["echo"]
|
agent.config.shell_allowlist = ["echo"]
|
||||||
|
|
||||||
result = sut.execute_shell(f"echo 'Hello {random_string}!'", config)
|
result = sut.execute_shell(f"echo 'Hello {random_string}!'", agent)
|
||||||
assert "Hello" in result and random_string in result
|
assert "Hello" in result and random_string in result
|
||||||
assert "Error" not in result
|
assert "Error" not in result
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ from unittest.mock import patch
|
|||||||
import pytest
|
import pytest
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
|
|
||||||
|
from autogpt.agent.agent import Agent
|
||||||
from autogpt.commands.image_gen import generate_image, generate_image_with_sd_webui
|
from autogpt.commands.image_gen import generate_image, generate_image_with_sd_webui
|
||||||
from tests.utils import requires_api_key
|
from tests.utils import requires_api_key
|
||||||
|
|
||||||
@@ -18,10 +19,10 @@ def image_size(request):
|
|||||||
|
|
||||||
@requires_api_key("OPENAI_API_KEY")
|
@requires_api_key("OPENAI_API_KEY")
|
||||||
@pytest.mark.vcr
|
@pytest.mark.vcr
|
||||||
def test_dalle(config, workspace, image_size, patched_api_requestor):
|
def test_dalle(agent: Agent, workspace, image_size, patched_api_requestor):
|
||||||
"""Test DALL-E image generation."""
|
"""Test DALL-E image generation."""
|
||||||
generate_and_validate(
|
generate_and_validate(
|
||||||
config,
|
agent,
|
||||||
workspace,
|
workspace,
|
||||||
image_provider="dalle",
|
image_provider="dalle",
|
||||||
image_size=image_size,
|
image_size=image_size,
|
||||||
@@ -36,10 +37,10 @@ def test_dalle(config, workspace, image_size, patched_api_requestor):
|
|||||||
"image_model",
|
"image_model",
|
||||||
["CompVis/stable-diffusion-v1-4", "stabilityai/stable-diffusion-2-1"],
|
["CompVis/stable-diffusion-v1-4", "stabilityai/stable-diffusion-2-1"],
|
||||||
)
|
)
|
||||||
def test_huggingface(config, workspace, image_size, image_model):
|
def test_huggingface(agent: Agent, workspace, image_size, image_model):
|
||||||
"""Test HuggingFace image generation."""
|
"""Test HuggingFace image generation."""
|
||||||
generate_and_validate(
|
generate_and_validate(
|
||||||
config,
|
agent,
|
||||||
workspace,
|
workspace,
|
||||||
image_provider="huggingface",
|
image_provider="huggingface",
|
||||||
image_size=image_size,
|
image_size=image_size,
|
||||||
@@ -48,10 +49,10 @@ def test_huggingface(config, workspace, image_size, image_model):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.xfail(reason="SD WebUI call does not work.")
|
@pytest.mark.xfail(reason="SD WebUI call does not work.")
|
||||||
def test_sd_webui(config, workspace, image_size):
|
def test_sd_webui(agent: Agent, workspace, image_size):
|
||||||
"""Test SD WebUI image generation."""
|
"""Test SD WebUI image generation."""
|
||||||
generate_and_validate(
|
generate_and_validate(
|
||||||
config,
|
agent,
|
||||||
workspace,
|
workspace,
|
||||||
image_provider="sd_webui",
|
image_provider="sd_webui",
|
||||||
image_size=image_size,
|
image_size=image_size,
|
||||||
@@ -59,11 +60,11 @@ def test_sd_webui(config, workspace, image_size):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.xfail(reason="SD WebUI call does not work.")
|
@pytest.mark.xfail(reason="SD WebUI call does not work.")
|
||||||
def test_sd_webui_negative_prompt(config, workspace, image_size):
|
def test_sd_webui_negative_prompt(agent: Agent, workspace, image_size):
|
||||||
gen_image = functools.partial(
|
gen_image = functools.partial(
|
||||||
generate_image_with_sd_webui,
|
generate_image_with_sd_webui,
|
||||||
prompt="astronaut riding a horse",
|
prompt="astronaut riding a horse",
|
||||||
config=config,
|
agent=agent,
|
||||||
size=image_size,
|
size=image_size,
|
||||||
extra={"seed": 123},
|
extra={"seed": 123},
|
||||||
)
|
)
|
||||||
@@ -87,7 +88,7 @@ def lst(txt):
|
|||||||
|
|
||||||
|
|
||||||
def generate_and_validate(
|
def generate_and_validate(
|
||||||
config,
|
agent: Agent,
|
||||||
workspace,
|
workspace,
|
||||||
image_size,
|
image_size,
|
||||||
image_provider,
|
image_provider,
|
||||||
@@ -95,11 +96,11 @@ def generate_and_validate(
|
|||||||
**kwargs,
|
**kwargs,
|
||||||
):
|
):
|
||||||
"""Generate an image and validate the output."""
|
"""Generate an image and validate the output."""
|
||||||
config.image_provider = image_provider
|
agent.config.image_provider = image_provider
|
||||||
config.huggingface_image_model = hugging_face_image_model
|
agent.config.huggingface_image_model = hugging_face_image_model
|
||||||
prompt = "astronaut riding a horse"
|
prompt = "astronaut riding a horse"
|
||||||
|
|
||||||
image_path = lst(generate_image(prompt, config, image_size, **kwargs))
|
image_path = lst(generate_image(prompt, agent, image_size, **kwargs))
|
||||||
assert image_path.exists()
|
assert image_path.exists()
|
||||||
with Image.open(image_path) as img:
|
with Image.open(image_path) as img:
|
||||||
assert img.size == (image_size, image_size)
|
assert img.size == (image_size, image_size)
|
||||||
@@ -120,7 +121,7 @@ def generate_and_validate(
|
|||||||
)
|
)
|
||||||
@pytest.mark.parametrize("delay", [10, 0])
|
@pytest.mark.parametrize("delay", [10, 0])
|
||||||
def test_huggingface_fail_request_with_delay(
|
def test_huggingface_fail_request_with_delay(
|
||||||
config, workspace, image_size, image_model, return_text, delay
|
agent: Agent, workspace, image_size, image_model, return_text, delay
|
||||||
):
|
):
|
||||||
return_text = return_text.replace("[model]", image_model).replace(
|
return_text = return_text.replace("[model]", image_model).replace(
|
||||||
"[delay]", str(delay)
|
"[delay]", str(delay)
|
||||||
@@ -138,13 +139,13 @@ def test_huggingface_fail_request_with_delay(
|
|||||||
mock_post.return_value.ok = False
|
mock_post.return_value.ok = False
|
||||||
mock_post.return_value.text = return_text
|
mock_post.return_value.text = return_text
|
||||||
|
|
||||||
config.image_provider = "huggingface"
|
agent.config.image_provider = "huggingface"
|
||||||
config.huggingface_image_model = image_model
|
agent.config.huggingface_image_model = image_model
|
||||||
prompt = "astronaut riding a horse"
|
prompt = "astronaut riding a horse"
|
||||||
|
|
||||||
with patch("time.sleep") as mock_sleep:
|
with patch("time.sleep") as mock_sleep:
|
||||||
# Verify request fails.
|
# Verify request fails.
|
||||||
result = generate_image(prompt, config, image_size)
|
result = generate_image(prompt, agent, image_size)
|
||||||
assert result == "Error creating image."
|
assert result == "Error creating image."
|
||||||
|
|
||||||
# Verify retry was called with delay if delay is in return_text
|
# Verify retry was called with delay if delay is in return_text
|
||||||
@@ -154,8 +155,8 @@ def test_huggingface_fail_request_with_delay(
|
|||||||
mock_sleep.assert_not_called()
|
mock_sleep.assert_not_called()
|
||||||
|
|
||||||
|
|
||||||
def test_huggingface_fail_request_with_delay(mocker, config):
|
def test_huggingface_fail_request_with_delay(mocker, agent: Agent):
|
||||||
config.huggingface_api_token = "1"
|
agent.config.huggingface_api_token = "1"
|
||||||
|
|
||||||
# Mock requests.post
|
# Mock requests.post
|
||||||
mock_post = mocker.patch("requests.post")
|
mock_post = mocker.patch("requests.post")
|
||||||
@@ -166,10 +167,10 @@ def test_huggingface_fail_request_with_delay(mocker, config):
|
|||||||
# Mock time.sleep
|
# Mock time.sleep
|
||||||
mock_sleep = mocker.patch("time.sleep")
|
mock_sleep = mocker.patch("time.sleep")
|
||||||
|
|
||||||
config.image_provider = "huggingface"
|
agent.config.image_provider = "huggingface"
|
||||||
config.huggingface_image_model = "CompVis/stable-diffusion-v1-4"
|
agent.config.huggingface_image_model = "CompVis/stable-diffusion-v1-4"
|
||||||
|
|
||||||
result = generate_image("astronaut riding a horse", config, 512)
|
result = generate_image("astronaut riding a horse", agent, 512)
|
||||||
|
|
||||||
assert result == "Error creating image."
|
assert result == "Error creating image."
|
||||||
|
|
||||||
@@ -177,8 +178,8 @@ def test_huggingface_fail_request_with_delay(mocker, config):
|
|||||||
mock_sleep.assert_called_with(0)
|
mock_sleep.assert_called_with(0)
|
||||||
|
|
||||||
|
|
||||||
def test_huggingface_fail_request_no_delay(mocker, config):
|
def test_huggingface_fail_request_no_delay(mocker, agent: Agent):
|
||||||
config.huggingface_api_token = "1"
|
agent.config.huggingface_api_token = "1"
|
||||||
|
|
||||||
# Mock requests.post
|
# Mock requests.post
|
||||||
mock_post = mocker.patch("requests.post")
|
mock_post = mocker.patch("requests.post")
|
||||||
@@ -191,10 +192,10 @@ def test_huggingface_fail_request_no_delay(mocker, config):
|
|||||||
# Mock time.sleep
|
# Mock time.sleep
|
||||||
mock_sleep = mocker.patch("time.sleep")
|
mock_sleep = mocker.patch("time.sleep")
|
||||||
|
|
||||||
config.image_provider = "huggingface"
|
agent.config.image_provider = "huggingface"
|
||||||
config.huggingface_image_model = "CompVis/stable-diffusion-v1-4"
|
agent.config.huggingface_image_model = "CompVis/stable-diffusion-v1-4"
|
||||||
|
|
||||||
result = generate_image("astronaut riding a horse", config, 512)
|
result = generate_image("astronaut riding a horse", agent, 512)
|
||||||
|
|
||||||
assert result == "Error creating image."
|
assert result == "Error creating image."
|
||||||
|
|
||||||
@@ -202,8 +203,8 @@ def test_huggingface_fail_request_no_delay(mocker, config):
|
|||||||
mock_sleep.assert_not_called()
|
mock_sleep.assert_not_called()
|
||||||
|
|
||||||
|
|
||||||
def test_huggingface_fail_request_bad_json(mocker, config):
|
def test_huggingface_fail_request_bad_json(mocker, agent: Agent):
|
||||||
config.huggingface_api_token = "1"
|
agent.config.huggingface_api_token = "1"
|
||||||
|
|
||||||
# Mock requests.post
|
# Mock requests.post
|
||||||
mock_post = mocker.patch("requests.post")
|
mock_post = mocker.patch("requests.post")
|
||||||
@@ -214,10 +215,10 @@ def test_huggingface_fail_request_bad_json(mocker, config):
|
|||||||
# Mock time.sleep
|
# Mock time.sleep
|
||||||
mock_sleep = mocker.patch("time.sleep")
|
mock_sleep = mocker.patch("time.sleep")
|
||||||
|
|
||||||
config.image_provider = "huggingface"
|
agent.config.image_provider = "huggingface"
|
||||||
config.huggingface_image_model = "CompVis/stable-diffusion-v1-4"
|
agent.config.huggingface_image_model = "CompVis/stable-diffusion-v1-4"
|
||||||
|
|
||||||
result = generate_image("astronaut riding a horse", config, 512)
|
result = generate_image("astronaut riding a horse", agent, 512)
|
||||||
|
|
||||||
assert result == "Error creating image."
|
assert result == "Error creating image."
|
||||||
|
|
||||||
@@ -225,28 +226,28 @@ def test_huggingface_fail_request_bad_json(mocker, config):
|
|||||||
mock_sleep.assert_not_called()
|
mock_sleep.assert_not_called()
|
||||||
|
|
||||||
|
|
||||||
def test_huggingface_fail_request_bad_image(mocker, config):
|
def test_huggingface_fail_request_bad_image(mocker, agent: Agent):
|
||||||
config.huggingface_api_token = "1"
|
agent.config.huggingface_api_token = "1"
|
||||||
|
|
||||||
# Mock requests.post
|
# Mock requests.post
|
||||||
mock_post = mocker.patch("requests.post")
|
mock_post = mocker.patch("requests.post")
|
||||||
mock_post.return_value.status_code = 200
|
mock_post.return_value.status_code = 200
|
||||||
|
|
||||||
config.image_provider = "huggingface"
|
agent.config.image_provider = "huggingface"
|
||||||
config.huggingface_image_model = "CompVis/stable-diffusion-v1-4"
|
agent.config.huggingface_image_model = "CompVis/stable-diffusion-v1-4"
|
||||||
|
|
||||||
result = generate_image("astronaut riding a horse", config, 512)
|
result = generate_image("astronaut riding a horse", agent, 512)
|
||||||
|
|
||||||
assert result == "Error creating image."
|
assert result == "Error creating image."
|
||||||
|
|
||||||
|
|
||||||
def test_huggingface_fail_missing_api_token(mocker, config):
|
def test_huggingface_fail_missing_api_token(mocker, agent: Agent):
|
||||||
config.image_provider = "huggingface"
|
agent.config.image_provider = "huggingface"
|
||||||
config.huggingface_image_model = "CompVis/stable-diffusion-v1-4"
|
agent.config.huggingface_image_model = "CompVis/stable-diffusion-v1-4"
|
||||||
|
|
||||||
# Mock requests.post to raise ValueError
|
# Mock requests.post to raise ValueError
|
||||||
mock_post = mocker.patch("requests.post", side_effect=ValueError)
|
mock_post = mocker.patch("requests.post", side_effect=ValueError)
|
||||||
|
|
||||||
# Verify request raises an error.
|
# Verify request raises an error.
|
||||||
with pytest.raises(ValueError):
|
with pytest.raises(ValueError):
|
||||||
generate_image("astronaut riding a horse", config, 512)
|
generate_image("astronaut riding a horse", agent, 512)
|
||||||
|
|||||||
@@ -1,18 +1,14 @@
|
|||||||
import pytest
|
|
||||||
from pytest_mock import MockerFixture
|
from pytest_mock import MockerFixture
|
||||||
|
|
||||||
|
from autogpt.agent.agent import Agent
|
||||||
from autogpt.commands.web_selenium import browse_website
|
from autogpt.commands.web_selenium import browse_website
|
||||||
from autogpt.config import Config
|
|
||||||
from tests.utils import requires_api_key
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.vcr
|
def test_browse_website(agent: Agent, patched_api_requestor: MockerFixture):
|
||||||
@requires_api_key("OPENAI_API_KEY")
|
|
||||||
def test_browse_website(config: Config, patched_api_requestor: MockerFixture):
|
|
||||||
url = "https://barrel-roll.com"
|
url = "https://barrel-roll.com"
|
||||||
question = "How to execute a barrel roll"
|
question = "How to execute a barrel roll"
|
||||||
|
|
||||||
response = browse_website(url, question, config)
|
response = browse_website(url, question, agent)
|
||||||
assert "Error" in response
|
assert "Error" in response
|
||||||
# Sanity check that the response is not too long
|
# Sanity check that the response is not too long
|
||||||
assert len(response) < 200
|
assert len(response) < 200
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
# Dependencies:
|
# Dependencies:
|
||||||
# pip install pytest-mock
|
# pip install pytest-mock
|
||||||
|
|
||||||
|
from autogpt.agent.agent import Agent
|
||||||
from autogpt.commands.web_requests import scrape_links
|
from autogpt.commands.web_requests import scrape_links
|
||||||
|
|
||||||
"""
|
"""
|
||||||
@@ -42,14 +43,14 @@ class TestScrapeLinks:
|
|||||||
provided with a valid url that returns a webpage with hyperlinks.
|
provided with a valid url that returns a webpage with hyperlinks.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def test_valid_url_with_hyperlinks(self, config):
|
def test_valid_url_with_hyperlinks(self, agent: Agent):
|
||||||
url = "https://www.google.com"
|
url = "https://www.google.com"
|
||||||
result = scrape_links(url, config=config)
|
result = scrape_links(url, agent=agent)
|
||||||
assert len(result) > 0
|
assert len(result) > 0
|
||||||
assert isinstance(result, list)
|
assert isinstance(result, list)
|
||||||
assert isinstance(result[0], str)
|
assert isinstance(result[0], str)
|
||||||
|
|
||||||
def test_valid_url(self, mocker, config):
|
def test_valid_url(self, mocker, agent: Agent):
|
||||||
"""Test that the function returns correctly formatted hyperlinks when given a valid url."""
|
"""Test that the function returns correctly formatted hyperlinks when given a valid url."""
|
||||||
# Mock the requests.get() function to return a response with sample HTML containing hyperlinks
|
# Mock the requests.get() function to return a response with sample HTML containing hyperlinks
|
||||||
mock_response = mocker.Mock()
|
mock_response = mocker.Mock()
|
||||||
@@ -60,12 +61,12 @@ class TestScrapeLinks:
|
|||||||
mocker.patch("requests.Session.get", return_value=mock_response)
|
mocker.patch("requests.Session.get", return_value=mock_response)
|
||||||
|
|
||||||
# Call the function with a valid URL
|
# Call the function with a valid URL
|
||||||
result = scrape_links("https://www.example.com", config)
|
result = scrape_links("https://www.example.com", agent)
|
||||||
|
|
||||||
# Assert that the function returns correctly formatted hyperlinks
|
# Assert that the function returns correctly formatted hyperlinks
|
||||||
assert result == ["Google (https://www.google.com)"]
|
assert result == ["Google (https://www.google.com)"]
|
||||||
|
|
||||||
def test_invalid_url(self, mocker, config):
|
def test_invalid_url(self, mocker, agent: Agent):
|
||||||
"""Test that the function returns "error" when given an invalid url."""
|
"""Test that the function returns "error" when given an invalid url."""
|
||||||
# Mock the requests.get() function to return an HTTP error response
|
# Mock the requests.get() function to return an HTTP error response
|
||||||
mock_response = mocker.Mock()
|
mock_response = mocker.Mock()
|
||||||
@@ -73,12 +74,12 @@ class TestScrapeLinks:
|
|||||||
mocker.patch("requests.Session.get", return_value=mock_response)
|
mocker.patch("requests.Session.get", return_value=mock_response)
|
||||||
|
|
||||||
# Call the function with an invalid URL
|
# Call the function with an invalid URL
|
||||||
result = scrape_links("https://www.invalidurl.com", config)
|
result = scrape_links("https://www.invalidurl.com", agent)
|
||||||
|
|
||||||
# Assert that the function returns "error"
|
# Assert that the function returns "error"
|
||||||
assert "Error:" in result
|
assert "Error:" in result
|
||||||
|
|
||||||
def test_no_hyperlinks(self, mocker, config):
|
def test_no_hyperlinks(self, mocker, agent: Agent):
|
||||||
"""Test that the function returns an empty list when the html contains no hyperlinks."""
|
"""Test that the function returns an empty list when the html contains no hyperlinks."""
|
||||||
# Mock the requests.get() function to return a response with sample HTML containing no hyperlinks
|
# Mock the requests.get() function to return a response with sample HTML containing no hyperlinks
|
||||||
mock_response = mocker.Mock()
|
mock_response = mocker.Mock()
|
||||||
@@ -87,12 +88,12 @@ class TestScrapeLinks:
|
|||||||
mocker.patch("requests.Session.get", return_value=mock_response)
|
mocker.patch("requests.Session.get", return_value=mock_response)
|
||||||
|
|
||||||
# Call the function with a URL containing no hyperlinks
|
# Call the function with a URL containing no hyperlinks
|
||||||
result = scrape_links("https://www.example.com", config)
|
result = scrape_links("https://www.example.com", agent)
|
||||||
|
|
||||||
# Assert that the function returns an empty list
|
# Assert that the function returns an empty list
|
||||||
assert result == []
|
assert result == []
|
||||||
|
|
||||||
def test_scrape_links_with_few_hyperlinks(self, mocker, config):
|
def test_scrape_links_with_few_hyperlinks(self, mocker, agent: Agent):
|
||||||
"""Test that scrape_links() correctly extracts and formats hyperlinks from a sample HTML containing a few hyperlinks."""
|
"""Test that scrape_links() correctly extracts and formats hyperlinks from a sample HTML containing a few hyperlinks."""
|
||||||
mock_response = mocker.Mock()
|
mock_response = mocker.Mock()
|
||||||
mock_response.status_code = 200
|
mock_response.status_code = 200
|
||||||
@@ -108,7 +109,7 @@ class TestScrapeLinks:
|
|||||||
mocker.patch("requests.Session.get", return_value=mock_response)
|
mocker.patch("requests.Session.get", return_value=mock_response)
|
||||||
|
|
||||||
# Call the function being tested
|
# Call the function being tested
|
||||||
result = scrape_links("https://www.example.com", config)
|
result = scrape_links("https://www.example.com", agent)
|
||||||
|
|
||||||
# Assert that the function returns a list of formatted hyperlinks
|
# Assert that the function returns a list of formatted hyperlinks
|
||||||
assert isinstance(result, list)
|
assert isinstance(result, list)
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
import pytest
|
import pytest
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
|
from autogpt.agent.agent import Agent
|
||||||
from autogpt.commands.web_requests import scrape_text
|
from autogpt.commands.web_requests import scrape_text
|
||||||
|
|
||||||
"""
|
"""
|
||||||
@@ -42,7 +43,7 @@ Additional aspects:
|
|||||||
|
|
||||||
|
|
||||||
class TestScrapeText:
|
class TestScrapeText:
|
||||||
def test_scrape_text_with_valid_url(self, mocker, config):
|
def test_scrape_text_with_valid_url(self, mocker, agent: Agent):
|
||||||
"""Tests that scrape_text() returns the expected text when given a valid URL."""
|
"""Tests that scrape_text() returns the expected text when given a valid URL."""
|
||||||
# Mock the requests.get() method to return a response with expected text
|
# Mock the requests.get() method to return a response with expected text
|
||||||
expected_text = "This is some sample text"
|
expected_text = "This is some sample text"
|
||||||
@@ -57,14 +58,14 @@ class TestScrapeText:
|
|||||||
# Call the function with a valid URL and assert that it returns the
|
# Call the function with a valid URL and assert that it returns the
|
||||||
# expected text
|
# expected text
|
||||||
url = "http://www.example.com"
|
url = "http://www.example.com"
|
||||||
assert scrape_text(url, config) == expected_text
|
assert scrape_text(url, agent) == expected_text
|
||||||
|
|
||||||
def test_invalid_url(self, config):
|
def test_invalid_url(self, agent: Agent):
|
||||||
"""Tests that an error is raised when an invalid url is provided."""
|
"""Tests that an error is raised when an invalid url is provided."""
|
||||||
url = "invalidurl.com"
|
url = "invalidurl.com"
|
||||||
pytest.raises(ValueError, scrape_text, url, config)
|
pytest.raises(ValueError, scrape_text, url, agent)
|
||||||
|
|
||||||
def test_unreachable_url(self, mocker, config):
|
def test_unreachable_url(self, mocker, agent: Agent):
|
||||||
"""Test that scrape_text returns an error message when an invalid or unreachable url is provided."""
|
"""Test that scrape_text returns an error message when an invalid or unreachable url is provided."""
|
||||||
# Mock the requests.get() method to raise an exception
|
# Mock the requests.get() method to raise an exception
|
||||||
mocker.patch(
|
mocker.patch(
|
||||||
@@ -74,10 +75,10 @@ class TestScrapeText:
|
|||||||
# Call the function with an invalid URL and assert that it returns an error
|
# Call the function with an invalid URL and assert that it returns an error
|
||||||
# message
|
# message
|
||||||
url = "http://thiswebsitedoesnotexist.net/"
|
url = "http://thiswebsitedoesnotexist.net/"
|
||||||
error_message = scrape_text(url, config)
|
error_message = scrape_text(url, agent)
|
||||||
assert "Error:" in error_message
|
assert "Error:" in error_message
|
||||||
|
|
||||||
def test_no_text(self, mocker, config):
|
def test_no_text(self, mocker, agent: Agent):
|
||||||
"""Test that scrape_text returns an empty string when the html page contains no text to be scraped."""
|
"""Test that scrape_text returns an empty string when the html page contains no text to be scraped."""
|
||||||
# Mock the requests.get() method to return a response with no text
|
# Mock the requests.get() method to return a response with no text
|
||||||
mock_response = mocker.Mock()
|
mock_response = mocker.Mock()
|
||||||
@@ -87,20 +88,20 @@ class TestScrapeText:
|
|||||||
|
|
||||||
# Call the function with a valid URL and assert that it returns an empty string
|
# Call the function with a valid URL and assert that it returns an empty string
|
||||||
url = "http://www.example.com"
|
url = "http://www.example.com"
|
||||||
assert scrape_text(url, config) == ""
|
assert scrape_text(url, agent) == ""
|
||||||
|
|
||||||
def test_http_error(self, mocker, config):
|
def test_http_error(self, mocker, agent: Agent):
|
||||||
"""Test that scrape_text returns an error message when the response status code is an http error (>=400)."""
|
"""Test that scrape_text returns an error message when the response status code is an http error (>=400)."""
|
||||||
# Mock the requests.get() method to return a response with a 404 status code
|
# Mock the requests.get() method to return a response with a 404 status code
|
||||||
mocker.patch("requests.Session.get", return_value=mocker.Mock(status_code=404))
|
mocker.patch("requests.Session.get", return_value=mocker.Mock(status_code=404))
|
||||||
|
|
||||||
# Call the function with a URL
|
# Call the function with a URL
|
||||||
result = scrape_text("https://www.example.com", config)
|
result = scrape_text("https://www.example.com", agent)
|
||||||
|
|
||||||
# Check that the function returns an error message
|
# Check that the function returns an error message
|
||||||
assert result == "Error: HTTP 404 error"
|
assert result == "Error: HTTP 404 error"
|
||||||
|
|
||||||
def test_scrape_text_with_html_tags(self, mocker, config):
|
def test_scrape_text_with_html_tags(self, mocker, agent: Agent):
|
||||||
"""Test that scrape_text() properly handles HTML tags."""
|
"""Test that scrape_text() properly handles HTML tags."""
|
||||||
# Create a mock response object with HTML containing tags
|
# Create a mock response object with HTML containing tags
|
||||||
html = "<html><body><p>This is <b>bold</b> text.</p></body></html>"
|
html = "<html><body><p>This is <b>bold</b> text.</p></body></html>"
|
||||||
@@ -110,7 +111,7 @@ class TestScrapeText:
|
|||||||
mocker.patch("requests.Session.get", return_value=mock_response)
|
mocker.patch("requests.Session.get", return_value=mock_response)
|
||||||
|
|
||||||
# Call the function with a URL
|
# Call the function with a URL
|
||||||
result = scrape_text("https://www.example.com", config)
|
result = scrape_text("https://www.example.com", agent)
|
||||||
|
|
||||||
# Check that the function properly handles HTML tags
|
# Check that the function properly handles HTML tags
|
||||||
assert result == "This is bold text."
|
assert result == "This is bold text."
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import pytest
|
|||||||
from pytest_mock import MockerFixture
|
from pytest_mock import MockerFixture
|
||||||
|
|
||||||
import autogpt.commands.file_operations as file_ops
|
import autogpt.commands.file_operations as file_ops
|
||||||
from autogpt.config import Config
|
from autogpt.agent.agent import Agent
|
||||||
from autogpt.memory.vector.memory_item import MemoryItem
|
from autogpt.memory.vector.memory_item import MemoryItem
|
||||||
from autogpt.memory.vector.utils import Embedding
|
from autogpt.memory.vector.utils import Embedding
|
||||||
from autogpt.utils import readable_file_size
|
from autogpt.utils import readable_file_size
|
||||||
@@ -42,7 +42,7 @@ def mock_MemoryItem_from_text(mocker: MockerFixture, mock_embedding: Embedding):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.fixture()
|
@pytest.fixture()
|
||||||
def test_file_path(config, workspace: Workspace):
|
def test_file_path(workspace: Workspace):
|
||||||
return workspace.get_path("test_file.txt")
|
return workspace.get_path("test_file.txt")
|
||||||
|
|
||||||
|
|
||||||
@@ -55,22 +55,22 @@ def test_file(test_file_path: Path):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.fixture()
|
@pytest.fixture()
|
||||||
def test_file_with_content_path(test_file: TextIOWrapper, file_content, config):
|
def test_file_with_content_path(test_file: TextIOWrapper, file_content, agent: Agent):
|
||||||
test_file.write(file_content)
|
test_file.write(file_content)
|
||||||
test_file.close()
|
test_file.close()
|
||||||
file_ops.log_operation(
|
file_ops.log_operation(
|
||||||
"write", test_file.name, config, file_ops.text_checksum(file_content)
|
"write", test_file.name, agent, file_ops.text_checksum(file_content)
|
||||||
)
|
)
|
||||||
return Path(test_file.name)
|
return Path(test_file.name)
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture()
|
@pytest.fixture()
|
||||||
def test_directory(config, workspace: Workspace):
|
def test_directory(workspace: Workspace):
|
||||||
return workspace.get_path("test_directory")
|
return workspace.get_path("test_directory")
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture()
|
@pytest.fixture()
|
||||||
def test_nested_file(config, workspace: Workspace):
|
def test_nested_file(workspace: Workspace):
|
||||||
return workspace.get_path("nested/test_file.txt")
|
return workspace.get_path("nested/test_file.txt")
|
||||||
|
|
||||||
|
|
||||||
@@ -117,7 +117,7 @@ def test_file_operations_state(test_file: TextIOWrapper):
|
|||||||
assert file_ops.file_operations_state(test_file.name) == expected_state
|
assert file_ops.file_operations_state(test_file.name) == expected_state
|
||||||
|
|
||||||
|
|
||||||
def test_is_duplicate_operation(config: Config, mocker: MockerFixture):
|
def test_is_duplicate_operation(agent: Agent, mocker: MockerFixture):
|
||||||
# Prepare a fake state dictionary for the function to use
|
# Prepare a fake state dictionary for the function to use
|
||||||
state = {
|
state = {
|
||||||
"path/to/file1.txt": "checksum1",
|
"path/to/file1.txt": "checksum1",
|
||||||
@@ -128,42 +128,48 @@ def test_is_duplicate_operation(config: Config, mocker: MockerFixture):
|
|||||||
# Test cases with write operations
|
# Test cases with write operations
|
||||||
assert (
|
assert (
|
||||||
file_ops.is_duplicate_operation(
|
file_ops.is_duplicate_operation(
|
||||||
"write", "path/to/file1.txt", config, "checksum1"
|
"write", "path/to/file1.txt", agent.config, "checksum1"
|
||||||
)
|
)
|
||||||
is True
|
is True
|
||||||
)
|
)
|
||||||
assert (
|
assert (
|
||||||
file_ops.is_duplicate_operation(
|
file_ops.is_duplicate_operation(
|
||||||
"write", "path/to/file1.txt", config, "checksum2"
|
"write", "path/to/file1.txt", agent.config, "checksum2"
|
||||||
)
|
)
|
||||||
is False
|
is False
|
||||||
)
|
)
|
||||||
assert (
|
assert (
|
||||||
file_ops.is_duplicate_operation(
|
file_ops.is_duplicate_operation(
|
||||||
"write", "path/to/file3.txt", config, "checksum3"
|
"write", "path/to/file3.txt", agent.config, "checksum3"
|
||||||
)
|
)
|
||||||
is False
|
is False
|
||||||
)
|
)
|
||||||
# Test cases with append operations
|
# Test cases with append operations
|
||||||
assert (
|
assert (
|
||||||
file_ops.is_duplicate_operation(
|
file_ops.is_duplicate_operation(
|
||||||
"append", "path/to/file1.txt", config, "checksum1"
|
"append", "path/to/file1.txt", agent.config, "checksum1"
|
||||||
)
|
)
|
||||||
is False
|
is False
|
||||||
)
|
)
|
||||||
# Test cases with delete operations
|
# Test cases with delete operations
|
||||||
assert (
|
assert (
|
||||||
file_ops.is_duplicate_operation("delete", "path/to/file1.txt", config) is False
|
file_ops.is_duplicate_operation(
|
||||||
|
"delete", "path/to/file1.txt", config=agent.config
|
||||||
|
)
|
||||||
|
is False
|
||||||
)
|
)
|
||||||
assert (
|
assert (
|
||||||
file_ops.is_duplicate_operation("delete", "path/to/file3.txt", config) is True
|
file_ops.is_duplicate_operation(
|
||||||
|
"delete", "path/to/file3.txt", config=agent.config
|
||||||
|
)
|
||||||
|
is True
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
# Test logging a file operation
|
# Test logging a file operation
|
||||||
def test_log_operation(config: Config):
|
def test_log_operation(agent: Agent):
|
||||||
file_ops.log_operation("log_test", "path/to/test", config)
|
file_ops.log_operation("log_test", "path/to/test", agent=agent)
|
||||||
with open(config.file_logger_path, "r", encoding="utf-8") as f:
|
with open(agent.config.file_logger_path, "r", encoding="utf-8") as f:
|
||||||
content = f.read()
|
content = f.read()
|
||||||
assert f"log_test: path/to/test\n" in content
|
assert f"log_test: path/to/test\n" in content
|
||||||
|
|
||||||
@@ -175,9 +181,9 @@ def test_text_checksum(file_content: str):
|
|||||||
assert checksum != different_checksum
|
assert checksum != different_checksum
|
||||||
|
|
||||||
|
|
||||||
def test_log_operation_with_checksum(config: Config):
|
def test_log_operation_with_checksum(agent: Agent):
|
||||||
file_ops.log_operation("log_test", "path/to/test", config, checksum="ABCDEF")
|
file_ops.log_operation("log_test", "path/to/test", agent=agent, checksum="ABCDEF")
|
||||||
with open(config.file_logger_path, "r", encoding="utf-8") as f:
|
with open(agent.config.file_logger_path, "r", encoding="utf-8") as f:
|
||||||
content = f.read()
|
content = f.read()
|
||||||
assert f"log_test: path/to/test #ABCDEF\n" in content
|
assert f"log_test: path/to/test #ABCDEF\n" in content
|
||||||
|
|
||||||
@@ -223,66 +229,66 @@ def test_read_file(
|
|||||||
mock_MemoryItem_from_text,
|
mock_MemoryItem_from_text,
|
||||||
test_file_with_content_path: Path,
|
test_file_with_content_path: Path,
|
||||||
file_content,
|
file_content,
|
||||||
config: Config,
|
agent: Agent,
|
||||||
):
|
):
|
||||||
content = file_ops.read_file(test_file_with_content_path, config)
|
content = file_ops.read_file(test_file_with_content_path, agent=agent)
|
||||||
assert content.replace("\r", "") == file_content
|
assert content.replace("\r", "") == file_content
|
||||||
|
|
||||||
|
|
||||||
def test_read_file_not_found(config: Config):
|
def test_read_file_not_found(agent: Agent):
|
||||||
filename = "does_not_exist.txt"
|
filename = "does_not_exist.txt"
|
||||||
content = file_ops.read_file(filename, config)
|
content = file_ops.read_file(filename, agent=agent)
|
||||||
assert "Error:" in content and filename in content and "no such file" in content
|
assert "Error:" in content and filename in content and "no such file" in content
|
||||||
|
|
||||||
|
|
||||||
def test_write_to_file(test_file_path: Path, config):
|
def test_write_to_file(test_file_path: Path, agent: Agent):
|
||||||
new_content = "This is new content.\n"
|
new_content = "This is new content.\n"
|
||||||
file_ops.write_to_file(str(test_file_path), new_content, config)
|
file_ops.write_to_file(str(test_file_path), new_content, agent=agent)
|
||||||
with open(test_file_path, "r", encoding="utf-8") as f:
|
with open(test_file_path, "r", encoding="utf-8") as f:
|
||||||
content = f.read()
|
content = f.read()
|
||||||
assert content == new_content
|
assert content == new_content
|
||||||
|
|
||||||
|
|
||||||
def test_write_file_logs_checksum(test_file_path: Path, config):
|
def test_write_file_logs_checksum(test_file_path: Path, agent: Agent):
|
||||||
new_content = "This is new content.\n"
|
new_content = "This is new content.\n"
|
||||||
new_checksum = file_ops.text_checksum(new_content)
|
new_checksum = file_ops.text_checksum(new_content)
|
||||||
file_ops.write_to_file(str(test_file_path), new_content, config)
|
file_ops.write_to_file(str(test_file_path), new_content, agent=agent)
|
||||||
with open(config.file_logger_path, "r", encoding="utf-8") as f:
|
with open(agent.config.file_logger_path, "r", encoding="utf-8") as f:
|
||||||
log_entry = f.read()
|
log_entry = f.read()
|
||||||
assert log_entry == f"write: {test_file_path} #{new_checksum}\n"
|
assert log_entry == f"write: {test_file_path} #{new_checksum}\n"
|
||||||
|
|
||||||
|
|
||||||
def test_write_file_fails_if_content_exists(test_file_path: Path, config):
|
def test_write_file_fails_if_content_exists(test_file_path: Path, agent: Agent):
|
||||||
new_content = "This is new content.\n"
|
new_content = "This is new content.\n"
|
||||||
file_ops.log_operation(
|
file_ops.log_operation(
|
||||||
"write",
|
"write",
|
||||||
str(test_file_path),
|
str(test_file_path),
|
||||||
config,
|
agent=agent,
|
||||||
checksum=file_ops.text_checksum(new_content),
|
checksum=file_ops.text_checksum(new_content),
|
||||||
)
|
)
|
||||||
result = file_ops.write_to_file(str(test_file_path), new_content, config)
|
result = file_ops.write_to_file(str(test_file_path), new_content, agent=agent)
|
||||||
assert result == "Error: File has already been updated."
|
assert result == "Error: File has already been updated."
|
||||||
|
|
||||||
|
|
||||||
def test_write_file_succeeds_if_content_different(
|
def test_write_file_succeeds_if_content_different(
|
||||||
test_file_with_content_path: Path, config
|
test_file_with_content_path: Path, agent: Agent
|
||||||
):
|
):
|
||||||
new_content = "This is different content.\n"
|
new_content = "This is different content.\n"
|
||||||
result = file_ops.write_to_file(
|
result = file_ops.write_to_file(
|
||||||
str(test_file_with_content_path), new_content, config
|
str(test_file_with_content_path), new_content, agent=agent
|
||||||
)
|
)
|
||||||
assert result == "File written to successfully."
|
assert result == "File written to successfully."
|
||||||
|
|
||||||
|
|
||||||
# Update file testing
|
# Update file testing
|
||||||
def test_replace_in_file_all_occurrences(test_file, test_file_path, config):
|
def test_replace_in_file_all_occurrences(test_file, test_file_path, agent: Agent):
|
||||||
old_content = "This is a test file.\n we test file here\na test is needed"
|
old_content = "This is a test file.\n we test file here\na test is needed"
|
||||||
expected_content = (
|
expected_content = (
|
||||||
"This is a update file.\n we update file here\na update is needed"
|
"This is a update file.\n we update file here\na update is needed"
|
||||||
)
|
)
|
||||||
test_file.write(old_content)
|
test_file.write(old_content)
|
||||||
test_file.close()
|
test_file.close()
|
||||||
file_ops.replace_in_file(test_file_path, "test", "update", config)
|
file_ops.replace_in_file(test_file_path, "test", "update", agent=agent)
|
||||||
with open(test_file_path) as f:
|
with open(test_file_path) as f:
|
||||||
new_content = f.read()
|
new_content = f.read()
|
||||||
print(new_content)
|
print(new_content)
|
||||||
@@ -290,13 +296,13 @@ def test_replace_in_file_all_occurrences(test_file, test_file_path, config):
|
|||||||
assert new_content == expected_content
|
assert new_content == expected_content
|
||||||
|
|
||||||
|
|
||||||
def test_replace_in_file_one_occurrence(test_file, test_file_path, config):
|
def test_replace_in_file_one_occurrence(test_file, test_file_path, agent: Agent):
|
||||||
old_content = "This is a test file.\n we test file here\na test is needed"
|
old_content = "This is a test file.\n we test file here\na test is needed"
|
||||||
expected_content = "This is a test file.\n we update file here\na test is needed"
|
expected_content = "This is a test file.\n we update file here\na test is needed"
|
||||||
test_file.write(old_content)
|
test_file.write(old_content)
|
||||||
test_file.close()
|
test_file.close()
|
||||||
file_ops.replace_in_file(
|
file_ops.replace_in_file(
|
||||||
test_file_path, "test", "update", config, occurrence_index=1
|
test_file_path, "test", "update", agent=agent, occurrence_index=1
|
||||||
)
|
)
|
||||||
with open(test_file_path) as f:
|
with open(test_file_path) as f:
|
||||||
new_content = f.read()
|
new_content = f.read()
|
||||||
@@ -304,7 +310,7 @@ def test_replace_in_file_one_occurrence(test_file, test_file_path, config):
|
|||||||
assert new_content == expected_content
|
assert new_content == expected_content
|
||||||
|
|
||||||
|
|
||||||
def test_replace_in_file_multiline_old_text(test_file, test_file_path, config):
|
def test_replace_in_file_multiline_old_text(test_file, test_file_path, agent: Agent):
|
||||||
old_content = "This is a multi_line\ntest for testing\nhow well this function\nworks when the input\nis multi-lined"
|
old_content = "This is a multi_line\ntest for testing\nhow well this function\nworks when the input\nis multi-lined"
|
||||||
expected_content = "This is a multi_line\nfile. succeeded test\nis multi-lined"
|
expected_content = "This is a multi_line\nfile. succeeded test\nis multi-lined"
|
||||||
test_file.write(old_content)
|
test_file.write(old_content)
|
||||||
@@ -313,7 +319,7 @@ def test_replace_in_file_multiline_old_text(test_file, test_file_path, config):
|
|||||||
test_file_path,
|
test_file_path,
|
||||||
"\ntest for testing\nhow well this function\nworks when the input\n",
|
"\ntest for testing\nhow well this function\nworks when the input\n",
|
||||||
"\nfile. succeeded test\n",
|
"\nfile. succeeded test\n",
|
||||||
config,
|
agent=agent,
|
||||||
)
|
)
|
||||||
with open(test_file_path) as f:
|
with open(test_file_path) as f:
|
||||||
new_content = f.read()
|
new_content = f.read()
|
||||||
@@ -321,11 +327,11 @@ def test_replace_in_file_multiline_old_text(test_file, test_file_path, config):
|
|||||||
assert new_content == expected_content
|
assert new_content == expected_content
|
||||||
|
|
||||||
|
|
||||||
def test_append_to_file(test_nested_file: Path, config):
|
def test_append_to_file(test_nested_file: Path, agent: Agent):
|
||||||
append_text = "This is appended text.\n"
|
append_text = "This is appended text.\n"
|
||||||
file_ops.write_to_file(test_nested_file, append_text, config)
|
file_ops.write_to_file(test_nested_file, append_text, agent=agent)
|
||||||
|
|
||||||
file_ops.append_to_file(test_nested_file, append_text, config)
|
file_ops.append_to_file(test_nested_file, append_text, agent=agent)
|
||||||
|
|
||||||
with open(test_nested_file, "r") as f:
|
with open(test_nested_file, "r") as f:
|
||||||
content_after = f.read()
|
content_after = f.read()
|
||||||
@@ -333,11 +339,13 @@ def test_append_to_file(test_nested_file: Path, config):
|
|||||||
assert content_after == append_text + append_text
|
assert content_after == append_text + append_text
|
||||||
|
|
||||||
|
|
||||||
def test_append_to_file_uses_checksum_from_appended_file(test_file_path: Path, config):
|
def test_append_to_file_uses_checksum_from_appended_file(
|
||||||
|
test_file_path: Path, agent: Agent
|
||||||
|
):
|
||||||
append_text = "This is appended text.\n"
|
append_text = "This is appended text.\n"
|
||||||
file_ops.append_to_file(test_file_path, append_text, config)
|
file_ops.append_to_file(test_file_path, append_text, agent=agent)
|
||||||
file_ops.append_to_file(test_file_path, append_text, config)
|
file_ops.append_to_file(test_file_path, append_text, agent=agent)
|
||||||
with open(config.file_logger_path, "r", encoding="utf-8") as f:
|
with open(agent.config.file_logger_path, "r", encoding="utf-8") as f:
|
||||||
log_contents = f.read()
|
log_contents = f.read()
|
||||||
|
|
||||||
digest = hashlib.md5()
|
digest = hashlib.md5()
|
||||||
@@ -351,25 +359,25 @@ def test_append_to_file_uses_checksum_from_appended_file(test_file_path: Path, c
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_delete_file(test_file_with_content_path: Path, config):
|
def test_delete_file(test_file_with_content_path: Path, agent: Agent):
|
||||||
result = file_ops.delete_file(str(test_file_with_content_path), config)
|
result = file_ops.delete_file(str(test_file_with_content_path), agent=agent)
|
||||||
assert result == "File deleted successfully."
|
assert result == "File deleted successfully."
|
||||||
assert os.path.exists(test_file_with_content_path) is False
|
assert os.path.exists(test_file_with_content_path) is False
|
||||||
|
|
||||||
|
|
||||||
def test_delete_missing_file(config):
|
def test_delete_missing_file(agent: Agent):
|
||||||
filename = "path/to/file/which/does/not/exist"
|
filename = "path/to/file/which/does/not/exist"
|
||||||
# confuse the log
|
# confuse the log
|
||||||
file_ops.log_operation("write", filename, config, checksum="fake")
|
file_ops.log_operation("write", filename, agent=agent, checksum="fake")
|
||||||
try:
|
try:
|
||||||
os.remove(filename)
|
os.remove(filename)
|
||||||
except FileNotFoundError as err:
|
except FileNotFoundError as err:
|
||||||
assert str(err) in file_ops.delete_file(filename, config)
|
assert str(err) in file_ops.delete_file(filename, agent=agent)
|
||||||
return
|
return
|
||||||
assert False, f"Failed to test delete_file; {filename} not expected to exist"
|
assert False, f"Failed to test delete_file; {filename} not expected to exist"
|
||||||
|
|
||||||
|
|
||||||
def test_list_files(workspace: Workspace, test_directory: Path, config):
|
def test_list_files(workspace: Workspace, test_directory: Path, agent: Agent):
|
||||||
# Case 1: Create files A and B, search for A, and ensure we don't return A and B
|
# Case 1: Create files A and B, search for A, and ensure we don't return A and B
|
||||||
file_a = workspace.get_path("file_a.txt")
|
file_a = workspace.get_path("file_a.txt")
|
||||||
file_b = workspace.get_path("file_b.txt")
|
file_b = workspace.get_path("file_b.txt")
|
||||||
@@ -387,7 +395,7 @@ def test_list_files(workspace: Workspace, test_directory: Path, config):
|
|||||||
with open(os.path.join(test_directory, file_a.name), "w") as f:
|
with open(os.path.join(test_directory, file_a.name), "w") as f:
|
||||||
f.write("This is file A in the subdirectory.")
|
f.write("This is file A in the subdirectory.")
|
||||||
|
|
||||||
files = file_ops.list_files(str(workspace.root), config)
|
files = file_ops.list_files(str(workspace.root), agent=agent)
|
||||||
assert file_a.name in files
|
assert file_a.name in files
|
||||||
assert file_b.name in files
|
assert file_b.name in files
|
||||||
assert os.path.join(Path(test_directory).name, file_a.name) in files
|
assert os.path.join(Path(test_directory).name, file_a.name) in files
|
||||||
@@ -400,17 +408,17 @@ def test_list_files(workspace: Workspace, test_directory: Path, config):
|
|||||||
|
|
||||||
# Case 2: Search for a file that does not exist and make sure we don't throw
|
# Case 2: Search for a file that does not exist and make sure we don't throw
|
||||||
non_existent_file = "non_existent_file.txt"
|
non_existent_file = "non_existent_file.txt"
|
||||||
files = file_ops.list_files("", config)
|
files = file_ops.list_files("", agent=agent)
|
||||||
assert non_existent_file not in files
|
assert non_existent_file not in files
|
||||||
|
|
||||||
|
|
||||||
def test_download_file(workspace: Workspace, config):
|
def test_download_file(workspace: Workspace, agent: Agent):
|
||||||
url = "https://github.com/Significant-Gravitas/Auto-GPT/archive/refs/tags/v0.2.2.tar.gz"
|
url = "https://github.com/Significant-Gravitas/Auto-GPT/archive/refs/tags/v0.2.2.tar.gz"
|
||||||
local_name = workspace.get_path("auto-gpt.tar.gz")
|
local_name = workspace.get_path("auto-gpt.tar.gz")
|
||||||
size = 365023
|
size = 365023
|
||||||
readable_size = readable_file_size(size)
|
readable_size = readable_file_size(size)
|
||||||
assert (
|
assert (
|
||||||
file_ops.download_file(url, local_name, config)
|
file_ops.download_file(url, local_name, agent=agent)
|
||||||
== f'Successfully downloaded and locally stored file: "{local_name}"! (Size: {readable_size})'
|
== f'Successfully downloaded and locally stored file: "{local_name}"! (Size: {readable_size})'
|
||||||
)
|
)
|
||||||
assert os.path.isfile(local_name) is True
|
assert os.path.isfile(local_name) is True
|
||||||
@@ -418,10 +426,10 @@ def test_download_file(workspace: Workspace, config):
|
|||||||
|
|
||||||
url = "https://github.com/Significant-Gravitas/Auto-GPT/archive/refs/tags/v0.0.0.tar.gz"
|
url = "https://github.com/Significant-Gravitas/Auto-GPT/archive/refs/tags/v0.0.0.tar.gz"
|
||||||
assert "Got an HTTP Error whilst trying to download file" in file_ops.download_file(
|
assert "Got an HTTP Error whilst trying to download file" in file_ops.download_file(
|
||||||
url, local_name, config
|
url, local_name, agent=agent
|
||||||
)
|
)
|
||||||
|
|
||||||
url = "https://thiswebsiteiswrong.hmm/v0.0.0.tar.gz"
|
url = "https://thiswebsiteiswrong.hmm/v0.0.0.tar.gz"
|
||||||
assert "Failed to establish a new connection:" in file_ops.download_file(
|
assert "Failed to establish a new connection:" in file_ops.download_file(
|
||||||
url, local_name, config
|
url, local_name, agent=agent
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import pytest
|
|||||||
from git.exc import GitCommandError
|
from git.exc import GitCommandError
|
||||||
from git.repo.base import Repo
|
from git.repo.base import Repo
|
||||||
|
|
||||||
|
from autogpt.agent.agent import Agent
|
||||||
from autogpt.commands.git_operations import clone_repository
|
from autogpt.commands.git_operations import clone_repository
|
||||||
|
|
||||||
|
|
||||||
@@ -10,7 +11,7 @@ def mock_clone_from(mocker):
|
|||||||
return mocker.patch.object(Repo, "clone_from")
|
return mocker.patch.object(Repo, "clone_from")
|
||||||
|
|
||||||
|
|
||||||
def test_clone_auto_gpt_repository(workspace, mock_clone_from, config):
|
def test_clone_auto_gpt_repository(workspace, mock_clone_from, agent: Agent):
|
||||||
mock_clone_from.return_value = None
|
mock_clone_from.return_value = None
|
||||||
|
|
||||||
repo = "github.com/Significant-Gravitas/Auto-GPT.git"
|
repo = "github.com/Significant-Gravitas/Auto-GPT.git"
|
||||||
@@ -20,16 +21,16 @@ def test_clone_auto_gpt_repository(workspace, mock_clone_from, config):
|
|||||||
|
|
||||||
expected_output = f"Cloned {url} to {clone_path}"
|
expected_output = f"Cloned {url} to {clone_path}"
|
||||||
|
|
||||||
clone_result = clone_repository(url=url, clone_path=clone_path, config=config)
|
clone_result = clone_repository(url=url, clone_path=clone_path, agent=agent)
|
||||||
|
|
||||||
assert clone_result == expected_output
|
assert clone_result == expected_output
|
||||||
mock_clone_from.assert_called_once_with(
|
mock_clone_from.assert_called_once_with(
|
||||||
url=f"{scheme}{config.github_username}:{config.github_api_key}@{repo}",
|
url=f"{scheme}{agent.config.github_username}:{agent.config.github_api_key}@{repo}",
|
||||||
to_path=clone_path,
|
to_path=clone_path,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_clone_repository_error(workspace, mock_clone_from, config):
|
def test_clone_repository_error(workspace, mock_clone_from, agent: Agent):
|
||||||
url = "https://github.com/this-repository/does-not-exist.git"
|
url = "https://github.com/this-repository/does-not-exist.git"
|
||||||
clone_path = str(workspace.get_path("does-not-exist"))
|
clone_path = str(workspace.get_path("does-not-exist"))
|
||||||
|
|
||||||
@@ -37,6 +38,6 @@ def test_clone_repository_error(workspace, mock_clone_from, config):
|
|||||||
"clone", "fatal: repository not found", ""
|
"clone", "fatal: repository not found", ""
|
||||||
)
|
)
|
||||||
|
|
||||||
result = clone_repository(url=url, clone_path=clone_path, config=config)
|
result = clone_repository(url=url, clone_path=clone_path, agent=agent)
|
||||||
|
|
||||||
assert "Error: " in result
|
assert "Error: " in result
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import json
|
|||||||
import pytest
|
import pytest
|
||||||
from googleapiclient.errors import HttpError
|
from googleapiclient.errors import HttpError
|
||||||
|
|
||||||
|
from autogpt.agent.agent import Agent
|
||||||
from autogpt.commands.google_search import (
|
from autogpt.commands.google_search import (
|
||||||
google_official_search,
|
google_official_search,
|
||||||
google_search,
|
google_search,
|
||||||
@@ -39,13 +40,13 @@ def test_safe_google_results_invalid_input():
|
|||||||
],
|
],
|
||||||
)
|
)
|
||||||
def test_google_search(
|
def test_google_search(
|
||||||
query, num_results, expected_output, return_value, mocker, config
|
query, num_results, expected_output, return_value, mocker, agent: Agent
|
||||||
):
|
):
|
||||||
mock_ddg = mocker.Mock()
|
mock_ddg = mocker.Mock()
|
||||||
mock_ddg.return_value = return_value
|
mock_ddg.return_value = return_value
|
||||||
|
|
||||||
mocker.patch("autogpt.commands.google_search.DDGS.text", mock_ddg)
|
mocker.patch("autogpt.commands.google_search.DDGS.text", mock_ddg)
|
||||||
actual_output = google_search(query, config, num_results=num_results)
|
actual_output = google_search(query, agent=agent, num_results=num_results)
|
||||||
expected_output = safe_google_results(expected_output)
|
expected_output = safe_google_results(expected_output)
|
||||||
assert actual_output == expected_output
|
assert actual_output == expected_output
|
||||||
|
|
||||||
@@ -79,10 +80,15 @@ def mock_googleapiclient(mocker):
|
|||||||
],
|
],
|
||||||
)
|
)
|
||||||
def test_google_official_search(
|
def test_google_official_search(
|
||||||
query, num_results, expected_output, search_results, mock_googleapiclient, config
|
query,
|
||||||
|
num_results,
|
||||||
|
expected_output,
|
||||||
|
search_results,
|
||||||
|
mock_googleapiclient,
|
||||||
|
agent: Agent,
|
||||||
):
|
):
|
||||||
mock_googleapiclient.return_value = search_results
|
mock_googleapiclient.return_value = search_results
|
||||||
actual_output = google_official_search(query, config, num_results=num_results)
|
actual_output = google_official_search(query, agent=agent, num_results=num_results)
|
||||||
assert actual_output == safe_google_results(expected_output)
|
assert actual_output == safe_google_results(expected_output)
|
||||||
|
|
||||||
|
|
||||||
@@ -113,7 +119,7 @@ def test_google_official_search_errors(
|
|||||||
mock_googleapiclient,
|
mock_googleapiclient,
|
||||||
http_code,
|
http_code,
|
||||||
error_msg,
|
error_msg,
|
||||||
config,
|
agent: Agent,
|
||||||
):
|
):
|
||||||
class resp:
|
class resp:
|
||||||
def __init__(self, _status, _reason):
|
def __init__(self, _status, _reason):
|
||||||
@@ -130,5 +136,5 @@ def test_google_official_search_errors(
|
|||||||
)
|
)
|
||||||
|
|
||||||
mock_googleapiclient.side_effect = error
|
mock_googleapiclient.side_effect = error
|
||||||
actual_output = google_official_search(query, config, num_results=num_results)
|
actual_output = google_official_search(query, agent=agent, num_results=num_results)
|
||||||
assert actual_output == safe_google_results(expected_output)
|
assert actual_output == safe_google_results(expected_output)
|
||||||
|
|||||||
@@ -2,11 +2,11 @@ from unittest.mock import MagicMock
|
|||||||
|
|
||||||
from pytest_mock import MockerFixture
|
from pytest_mock import MockerFixture
|
||||||
|
|
||||||
|
from autogpt.agent.agent import Agent
|
||||||
from autogpt.app import list_agents, start_agent
|
from autogpt.app import list_agents, start_agent
|
||||||
from autogpt.config import Config
|
|
||||||
|
|
||||||
|
|
||||||
def test_make_agent(config: Config, mocker: MockerFixture) -> None:
|
def test_make_agent(agent: Agent, mocker: MockerFixture) -> None:
|
||||||
"""Test that an agent can be created"""
|
"""Test that an agent can be created"""
|
||||||
mock = mocker.patch("openai.ChatCompletion.create")
|
mock = mocker.patch("openai.ChatCompletion.create")
|
||||||
|
|
||||||
@@ -16,9 +16,9 @@ def test_make_agent(config: Config, mocker: MockerFixture) -> None:
|
|||||||
response.usage.prompt_tokens = 1
|
response.usage.prompt_tokens = 1
|
||||||
response.usage.completion_tokens = 1
|
response.usage.completion_tokens = 1
|
||||||
mock.return_value = response
|
mock.return_value = response
|
||||||
start_agent("Test Agent", "chat", "Hello, how are you?", config, "gpt-3.5-turbo")
|
start_agent("Test Agent", "chat", "Hello, how are you?", agent, "gpt-3.5-turbo")
|
||||||
agents = list_agents(config)
|
agents = list_agents(agent)
|
||||||
assert "List of agents:\n0: chat" == agents
|
assert "List of agents:\n0: chat" == agents
|
||||||
start_agent("Test Agent 2", "write", "Hello, how are you?", config, "gpt-3.5-turbo")
|
start_agent("Test Agent 2", "write", "Hello, how are you?", agent, "gpt-3.5-turbo")
|
||||||
agents = list_agents(config)
|
agents = list_agents(agent.config)
|
||||||
assert "List of agents:\n0: chat\n1: write" == agents
|
assert "List of agents:\n0: chat\n1: write" == agents
|
||||||
|
|||||||
Reference in New Issue
Block a user