| | """ Command and Control """ |
| | import json |
| | from typing import Dict, List, NoReturn, Union |
| |
|
| | from autogpt.agent.agent_manager import AgentManager |
| | from autogpt.commands.analyze_code import analyze_code |
| | from autogpt.commands.audio_text import read_audio_from_file |
| | from autogpt.commands.execute_code import ( |
| | execute_python_file, |
| | execute_shell, |
| | execute_shell_popen, |
| | ) |
| | from autogpt.commands.file_operations import ( |
| | append_to_file, |
| | delete_file, |
| | download_file, |
| | read_file, |
| | search_files, |
| | write_to_file, |
| | ) |
| | from autogpt.commands.git_operations import clone_repository |
| | from autogpt.commands.google_search import google_official_search, google_search |
| | from autogpt.commands.image_gen import generate_image |
| | from autogpt.commands.improve_code import improve_code |
| | from autogpt.commands.twitter import send_tweet |
| | from autogpt.commands.web_requests import scrape_links, scrape_text |
| | from autogpt.commands.web_selenium import browse_website |
| | from autogpt.commands.write_tests import write_tests |
| | from autogpt.config import Config |
| | from autogpt.json_utils.json_fix_llm import fix_and_parse_json |
| | from autogpt.memory import get_memory |
| | from autogpt.processing.text import summarize_text |
| | from autogpt.speech import say_text |
| |
|
| | CFG = Config() |
| | AGENT_MANAGER = AgentManager() |
| |
|
| |
|
| | def is_valid_int(value: str) -> bool: |
| | """Check if the value is a valid integer |
| | |
| | Args: |
| | value (str): The value to check |
| | |
| | Returns: |
| | bool: True if the value is a valid integer, False otherwise |
| | """ |
| | try: |
| | int(value) |
| | return True |
| | except ValueError: |
| | return False |
| |
|
| |
|
| | def get_command(response_json: Dict): |
| | """Parse the response and return the command name and arguments |
| | |
| | Args: |
| | response_json (json): The response from the AI |
| | |
| | Returns: |
| | tuple: The command name and arguments |
| | |
| | Raises: |
| | json.decoder.JSONDecodeError: If the response is not valid JSON |
| | |
| | Exception: If any other error occurs |
| | """ |
| | try: |
| | if "command" not in response_json: |
| | return "Error:", "Missing 'command' object in JSON" |
| |
|
| | if not isinstance(response_json, dict): |
| | return "Error:", f"'response_json' object is not dictionary {response_json}" |
| |
|
| | command = response_json["command"] |
| | if not isinstance(command, dict): |
| | return "Error:", "'command' object is not a dictionary" |
| |
|
| | if "name" not in command: |
| | return "Error:", "Missing 'name' field in 'command' object" |
| |
|
| | command_name = command["name"] |
| |
|
| | |
| | arguments = command.get("args", {}) |
| |
|
| | return command_name, arguments |
| | except json.decoder.JSONDecodeError: |
| | return "Error:", "Invalid JSON" |
| | |
| | except Exception as e: |
| | return "Error:", str(e) |
| |
|
| |
|
| | def map_command_synonyms(command_name: str): |
| | """Takes the original command name given by the AI, and checks if the |
| | string matches a list of common/known hallucinations |
| | """ |
| | synonyms = [ |
| | ("write_file", "write_to_file"), |
| | ("create_file", "write_to_file"), |
| | ("search", "google"), |
| | ] |
| | for seen_command, actual_command_name in synonyms: |
| | if command_name == seen_command: |
| | return actual_command_name |
| | return command_name |
| |
|
| |
|
| | def execute_command(command_name: str, arguments): |
| | """Execute the command and return the result |
| | |
| | Args: |
| | command_name (str): The name of the command to execute |
| | arguments (dict): The arguments for the command |
| | |
| | Returns: |
| | str: The result of the command |
| | """ |
| | try: |
| | command_name = map_command_synonyms(command_name.lower()) |
| | if command_name == "google": |
| | |
| | |
| | |
| | key = CFG.google_api_key |
| | if key and key.strip() and key != "your-google-api-key": |
| | google_result = google_official_search(arguments["input"]) |
| | return google_result |
| | else: |
| | google_result = google_search(arguments["input"]) |
| |
|
| | |
| | if isinstance(google_result, list): |
| | safe_message = [ |
| | google_result_single.encode("utf-8", "ignore") |
| | for google_result_single in google_result |
| | ] |
| | else: |
| | safe_message = google_result.encode("utf-8", "ignore") |
| |
|
| | return safe_message.decode("utf-8") |
| | elif command_name == "memory_add": |
| | memory = get_memory(CFG) |
| | return memory.add(arguments["string"]) |
| | elif command_name == "start_agent": |
| | return start_agent( |
| | arguments["name"], arguments["task"], arguments["prompt"] |
| | ) |
| | elif command_name == "message_agent": |
| | return message_agent(arguments["key"], arguments["message"]) |
| | elif command_name == "list_agents": |
| | return list_agents() |
| | elif command_name == "delete_agent": |
| | return delete_agent(arguments["key"]) |
| | elif command_name == "get_text_summary": |
| | return get_text_summary(arguments["url"], arguments["question"]) |
| | elif command_name == "get_hyperlinks": |
| | return get_hyperlinks(arguments["url"]) |
| | elif command_name == "clone_repository": |
| | return clone_repository( |
| | arguments["repository_url"], arguments["clone_path"] |
| | ) |
| | elif command_name == "read_file": |
| | return read_file(arguments["file"]) |
| | elif command_name == "write_to_file": |
| | return write_to_file(arguments["file"], arguments["text"]) |
| | elif command_name == "append_to_file": |
| | return append_to_file(arguments["file"], arguments["text"]) |
| | elif command_name == "delete_file": |
| | return delete_file(arguments["file"]) |
| | elif command_name == "search_files": |
| | return search_files(arguments["directory"]) |
| | elif command_name == "download_file": |
| | if not CFG.allow_downloads: |
| | return "Error: You do not have user authorization to download files locally." |
| | return download_file(arguments["url"], arguments["file"]) |
| | elif command_name == "browse_website": |
| | return browse_website(arguments["url"], arguments["question"]) |
| | |
| | |
| | |
| | elif command_name == "analyze_code": |
| | return analyze_code(arguments["code"]) |
| | elif command_name == "improve_code": |
| | return improve_code(arguments["suggestions"], arguments["code"]) |
| | elif command_name == "write_tests": |
| | return write_tests(arguments["code"], arguments.get("focus")) |
| | elif command_name == "execute_python_file": |
| | return execute_python_file(arguments["file"]) |
| | elif command_name == "execute_shell": |
| | if CFG.execute_local_commands: |
| | return execute_shell(arguments["command_line"]) |
| | else: |
| | return ( |
| | "You are not allowed to run local shell commands. To execute" |
| | " shell commands, EXECUTE_LOCAL_COMMANDS must be set to 'True' " |
| | "in your config. Do not attempt to bypass the restriction." |
| | ) |
| | elif command_name == "execute_shell_popen": |
| | if CFG.execute_local_commands: |
| | return execute_shell_popen(arguments["command_line"]) |
| | else: |
| | return ( |
| | "You are not allowed to run local shell commands. To execute" |
| | " shell commands, EXECUTE_LOCAL_COMMANDS must be set to 'True' " |
| | "in your config. Do not attempt to bypass the restriction." |
| | ) |
| | elif command_name == "read_audio_from_file": |
| | return read_audio_from_file(arguments["file"]) |
| | elif command_name == "generate_image": |
| | return generate_image(arguments["prompt"]) |
| | elif command_name == "send_tweet": |
| | return send_tweet(arguments["text"]) |
| | elif command_name == "do_nothing": |
| | return "No action performed." |
| | elif command_name == "task_complete": |
| | shutdown() |
| | else: |
| | return ( |
| | f"Unknown command '{command_name}'. Please refer to the 'COMMANDS'" |
| | " list for available commands and only respond in the specified JSON" |
| | " format." |
| | ) |
| | except Exception as e: |
| | return f"Error: {str(e)}" |
| |
|
| |
|
| | def get_text_summary(url: str, question: str) -> str: |
| | """Return the results of a Google search |
| | |
| | Args: |
| | url (str): The url to scrape |
| | question (str): The question to summarize the text for |
| | |
| | Returns: |
| | str: The summary of the text |
| | """ |
| | text = scrape_text(url) |
| | summary = summarize_text(url, text, question) |
| | return f""" "Result" : {summary}""" |
| |
|
| |
|
| | def get_hyperlinks(url: str) -> Union[str, List[str]]: |
| | """Return the results of a Google search |
| | |
| | Args: |
| | url (str): The url to scrape |
| | |
| | Returns: |
| | str or list: The hyperlinks on the page |
| | """ |
| | return scrape_links(url) |
| |
|
| |
|
| | def shutdown() -> NoReturn: |
| | """Shut down the program""" |
| | print("Shutting down...") |
| | quit() |
| |
|
| |
|
| | def start_agent(name: str, task: str, prompt: str, model=CFG.fast_llm_model) -> str: |
| | """Start an agent with a given name, task, and prompt |
| | |
| | Args: |
| | name (str): The name of the agent |
| | task (str): The task of the agent |
| | prompt (str): The prompt for the agent |
| | model (str): The model to use for the agent |
| | |
| | Returns: |
| | str: The response of the agent |
| | """ |
| | |
| | voice_name = name.replace("_", " ") |
| |
|
| | first_message = f"""You are {name}. Respond with: "Acknowledged".""" |
| | agent_intro = f"{voice_name} here, Reporting for duty!" |
| |
|
| | |
| | if CFG.speak_mode: |
| | say_text(agent_intro, 1) |
| | key, ack = AGENT_MANAGER.create_agent(task, first_message, model) |
| |
|
| | if CFG.speak_mode: |
| | say_text(f"Hello {voice_name}. Your task is as follows. {task}.") |
| |
|
| | |
| | agent_response = AGENT_MANAGER.message_agent(key, prompt) |
| |
|
| | return f"Agent {name} created with key {key}. First response: {agent_response}" |
| |
|
| |
|
| | def message_agent(key: str, message: str) -> str: |
| | """Message an agent with a given key and message""" |
| | |
| | if is_valid_int(key): |
| | agent_response = AGENT_MANAGER.message_agent(int(key), message) |
| | else: |
| | return "Invalid key, must be an integer." |
| |
|
| | |
| | if CFG.speak_mode: |
| | say_text(agent_response, 1) |
| | return agent_response |
| |
|
| |
|
| | def list_agents(): |
| | """List all agents |
| | |
| | Returns: |
| | str: A list of all agents |
| | """ |
| | return "List of agents:\n" + "\n".join( |
| | [str(x[0]) + ": " + x[1] for x in AGENT_MANAGER.list_agents()] |
| | ) |
| |
|
| |
|
| | def delete_agent(key: str) -> str: |
| | """Delete an agent with a given key |
| | |
| | Args: |
| | key (str): The key of the agent to delete |
| | |
| | Returns: |
| | str: A message indicating whether the agent was deleted or not |
| | """ |
| | result = AGENT_MANAGER.delete_agent(key) |
| | return f"Agent {key} deleted." if result else f"Agent {key} does not exist." |
| |
|