mirror of
https://github.com/Significant-Gravitas/AutoGPT.git
synced 2026-01-10 23:58:06 -05:00
Complete context integration & add close_context_item command
This commit is contained in:
@@ -177,14 +177,11 @@ class Agent(ContextMixin, WorkspaceMixin, BaseAgent):
|
||||
return_value[1], ContextItem
|
||||
):
|
||||
context_item = return_value[1]
|
||||
# return_value = return_value[0]
|
||||
return_value = return_value[0]
|
||||
logger.debug(
|
||||
f"Command {command_name} returned a ContextItem: {context_item}"
|
||||
)
|
||||
# self.context.add(context_item)
|
||||
|
||||
# HACK: use content of ContextItem as return value, for legacy support
|
||||
return_value = context_item.content
|
||||
self.context.add(context_item)
|
||||
|
||||
result = ActionSuccessResult(return_value)
|
||||
except AgentException as e:
|
||||
|
||||
@@ -102,7 +102,7 @@ class BaseAgent(metaclass=ABCMeta):
|
||||
super(BaseAgent, self).__init__()
|
||||
|
||||
@property
|
||||
def system_prompt(self):
|
||||
def system_prompt(self) -> str:
|
||||
"""
|
||||
The system prompt sets up the AI's personality and explains its goals,
|
||||
available resources, and restrictions.
|
||||
@@ -297,7 +297,7 @@ class BaseAgent(metaclass=ABCMeta):
|
||||
return (
|
||||
f"Respond strictly with JSON{', and also specify a command to use through a function_call' if use_functions else ''}. "
|
||||
"The JSON should be compatible with the TypeScript type `Response` from the following:\n"
|
||||
f"{response_format}\n"
|
||||
f"{response_format}"
|
||||
)
|
||||
|
||||
def on_before_think(
|
||||
|
||||
@@ -23,7 +23,7 @@ from autogpt.models.context_item import FileContextItem, FolderContextItem
|
||||
from .decorators import sanitize_path_arg
|
||||
|
||||
|
||||
def compatible_with_agent(agent: BaseAgent) -> bool:
|
||||
def agent_implements_context(agent: BaseAgent) -> bool:
|
||||
return isinstance(agent, ContextMixin)
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ def compatible_with_agent(agent: BaseAgent) -> bool:
|
||||
"required": True,
|
||||
}
|
||||
},
|
||||
available=compatible_with_agent,
|
||||
available=agent_implements_context,
|
||||
)
|
||||
@sanitize_path_arg("file_path")
|
||||
def open_file(file_path: Path, agent: Agent) -> tuple[str, FileContextItem]:
|
||||
@@ -51,8 +51,9 @@ def open_file(file_path: Path, agent: Agent) -> tuple[str, FileContextItem]:
|
||||
FileContextItem: A ContextItem representing the opened file
|
||||
"""
|
||||
# Try to make the file path relative
|
||||
relative_file_path = None
|
||||
with contextlib.suppress(ValueError):
|
||||
file_path = file_path.relative_to(agent.workspace.root)
|
||||
relative_file_path = file_path.relative_to(agent.workspace.root)
|
||||
|
||||
assert (agent_context := get_agent_context(agent)) is not None
|
||||
|
||||
@@ -63,12 +64,14 @@ def open_file(file_path: Path, agent: Agent) -> tuple[str, FileContextItem]:
|
||||
elif not file_path.is_file():
|
||||
raise CommandExecutionError(f"{file_path} exists but is not a file")
|
||||
|
||||
file = FileContextItem(file_path)
|
||||
file_path = relative_file_path or file_path
|
||||
|
||||
file = FileContextItem(file_path, agent.workspace.root)
|
||||
if file in agent_context:
|
||||
raise DuplicateOperationError(f"The file {file_path} is already open")
|
||||
|
||||
return (
|
||||
f"File {file}{' created,' if created else ''} opened and added to context ✅",
|
||||
f"File {file_path}{' created,' if created else ''} opened and added to context ✅",
|
||||
file,
|
||||
)
|
||||
|
||||
@@ -83,7 +86,7 @@ def open_file(file_path: Path, agent: Agent) -> tuple[str, FileContextItem]:
|
||||
"required": True,
|
||||
}
|
||||
},
|
||||
available=compatible_with_agent,
|
||||
available=agent_implements_context,
|
||||
)
|
||||
@sanitize_path_arg("path")
|
||||
def open_folder(path: Path, agent: Agent) -> tuple[str, FolderContextItem]:
|
||||
@@ -97,8 +100,9 @@ def open_folder(path: Path, agent: Agent) -> tuple[str, FolderContextItem]:
|
||||
FolderContextItem: A ContextItem representing the opened folder
|
||||
"""
|
||||
# Try to make the path relative
|
||||
relative_path = None
|
||||
with contextlib.suppress(ValueError):
|
||||
path = path.relative_to(agent.workspace.root)
|
||||
relative_path = path.relative_to(agent.workspace.root)
|
||||
|
||||
assert (agent_context := get_agent_context(agent)) is not None
|
||||
|
||||
@@ -107,8 +111,10 @@ def open_folder(path: Path, agent: Agent) -> tuple[str, FolderContextItem]:
|
||||
elif not path.is_dir():
|
||||
raise CommandExecutionError(f"{path} exists but is not a folder")
|
||||
|
||||
folder = FolderContextItem(path)
|
||||
path = relative_path or path
|
||||
|
||||
folder = FolderContextItem(path, agent.workspace.root)
|
||||
if folder in agent_context:
|
||||
raise DuplicateOperationError(f"The folder {path} is already open")
|
||||
|
||||
return f"Folder {folder} opened and added to context ✅", folder
|
||||
return f"Folder {path} opened and added to context ✅", folder
|
||||
|
||||
@@ -6,8 +6,13 @@ COMMAND_CATEGORY = "system"
|
||||
COMMAND_CATEGORY_TITLE = "System"
|
||||
|
||||
import logging
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from autogpt.agents.agent import Agent
|
||||
if TYPE_CHECKING:
|
||||
from autogpt.agents.agent import Agent
|
||||
|
||||
from autogpt.agents.features.context import get_agent_context
|
||||
from autogpt.agents.utils.exceptions import InvalidArgumentError
|
||||
from autogpt.command_decorator import command
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -36,3 +41,25 @@ def task_complete(reason: str, agent: Agent) -> None:
|
||||
"""
|
||||
logger.info(reason, extra={"title": "Shutting down...\n"})
|
||||
quit()
|
||||
|
||||
|
||||
@command(
|
||||
"close_context_item",
|
||||
"Close an open file, folder or other context item",
|
||||
{
|
||||
"index": {
|
||||
"type": "integer",
|
||||
"description": "The 1-based index of the context item to close",
|
||||
"required": True,
|
||||
}
|
||||
},
|
||||
available=lambda a: get_agent_context(a) is not None,
|
||||
)
|
||||
def close_context_item(index: int, agent: Agent) -> str:
|
||||
assert (context := get_agent_context(agent)) is not None
|
||||
|
||||
if index > len(context.items) or index == 0:
|
||||
raise InvalidArgumentError(f"Index {index} out of range")
|
||||
|
||||
context.close(index)
|
||||
return f"Context item {index} closed ✅"
|
||||
|
||||
@@ -39,15 +39,20 @@ class ContextItem(ABC):
|
||||
|
||||
@dataclass
|
||||
class FileContextItem(ContextItem):
|
||||
file_path: Path
|
||||
file_path_in_workspace: Path
|
||||
workspace_path: Path
|
||||
|
||||
@property
|
||||
def file_path(self) -> Path:
|
||||
return self.workspace_path / self.file_path_in_workspace
|
||||
|
||||
@property
|
||||
def description(self) -> str:
|
||||
return f"The current content of the file '{self.file_path}'"
|
||||
return f"The current content of the file '{self.file_path_in_workspace}'"
|
||||
|
||||
@property
|
||||
def source(self) -> str:
|
||||
return str(self.file_path)
|
||||
return str(self.file_path_in_workspace)
|
||||
|
||||
@property
|
||||
def content(self) -> str:
|
||||
@@ -56,7 +61,12 @@ class FileContextItem(ContextItem):
|
||||
|
||||
@dataclass
|
||||
class FolderContextItem(ContextItem):
|
||||
path: Path
|
||||
path_in_workspace: Path
|
||||
workspace_path: Path
|
||||
|
||||
@property
|
||||
def path(self) -> Path:
|
||||
return self.workspace_path / self.path_in_workspace
|
||||
|
||||
def __post_init__(self) -> None:
|
||||
assert self.path.exists(), "Selected path does not exist"
|
||||
@@ -64,11 +74,11 @@ class FolderContextItem(ContextItem):
|
||||
|
||||
@property
|
||||
def description(self) -> str:
|
||||
return f"The contents of the folder '{self.path}' in the workspace"
|
||||
return f"The contents of the folder '{self.path_in_workspace}' in the workspace"
|
||||
|
||||
@property
|
||||
def source(self) -> str:
|
||||
return str(self.path)
|
||||
return str(self.path_in_workspace)
|
||||
|
||||
@property
|
||||
def content(self) -> str:
|
||||
|
||||
Reference in New Issue
Block a user