разделение workspace и system файлов, использование CompositeBackend
This commit is contained in:
parent
74e884179a
commit
7907f57971
7 changed files with 85 additions and 32 deletions
|
|
@ -2,23 +2,49 @@ import os
|
|||
import pwd
|
||||
import subprocess
|
||||
from typing import Any
|
||||
|
||||
from deepagents.backends.local_shell import LocalShellBackend
|
||||
import uuid
|
||||
from pathlib import Path
|
||||
from deepagents.backends.local_shell import DEFAULT_EXECUTE_TIMEOUT
|
||||
from deepagents.backends.protocol import SandboxBackendProtocol
|
||||
|
||||
|
||||
class IsolatedShellBackend(LocalShellBackend):
|
||||
class IsolatedShellBackend(SandboxBackendProtocol):
|
||||
"""LocalShellBackend с изоляцией shell-команд через отдельного пользователя."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
user: str,
|
||||
**kwargs: Any,
|
||||
root_dir: str,
|
||||
timeout: int = DEFAULT_EXECUTE_TIMEOUT,
|
||||
max_output_bytes: int = 100_000,
|
||||
env: dict[str, str] | None = None,
|
||||
inherit_env: bool = False,
|
||||
):
|
||||
super().__init__(**kwargs)
|
||||
|
||||
self._user = user
|
||||
self._uid = pwd.getpwnam(user).pw_uid # type: ignore[attr-defined]
|
||||
self._gid = pwd.getpwnam(user).pw_gid # type: ignore[attr-defined]
|
||||
|
||||
if timeout <= 0:
|
||||
msg = f"timeout must be positive, got {timeout}"
|
||||
raise ValueError(msg)
|
||||
|
||||
# Store execution parameters
|
||||
self._default_timeout = timeout
|
||||
self._max_output_bytes = max_output_bytes
|
||||
self.cwd = Path(root_dir).resolve() if root_dir else Path.cwd()
|
||||
|
||||
# Build environment based on inherit_env setting
|
||||
if inherit_env:
|
||||
self._env = os.environ.copy()
|
||||
if env is not None:
|
||||
self._env.update(env)
|
||||
else:
|
||||
self._env = env if env is not None else {}
|
||||
|
||||
# Generate unique sandbox ID
|
||||
self._sandbox_id = f"local-{uuid.uuid4().hex[:8]}"
|
||||
|
||||
def execute(
|
||||
self,
|
||||
command: str,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import os
|
||||
from deepagents import create_deep_agent
|
||||
from deepagents import create_deep_agent, FilesystemPermission
|
||||
from deepagents.backends import CompositeBackend, FilesystemBackend
|
||||
from langchain_openai import ChatOpenAI
|
||||
from langgraph.checkpoint.memory import MemorySaver
|
||||
from langgraph.graph.state import CompiledStateGraph
|
||||
|
|
@ -14,7 +15,7 @@ class Agent(CompiledStateGraph):
|
|||
"""
|
||||
Временный (надеюсь) костыль, чтобы дать доступ сервису к файловой системе агента.
|
||||
"""
|
||||
backend: IsolatedShellBackend
|
||||
backend: CompositeBackend
|
||||
|
||||
|
||||
def create_agent() -> Agent:
|
||||
|
|
@ -32,10 +33,10 @@ def create_agent() -> Agent:
|
|||
workspace_dir = os.environ["WORKSPACE_DIR"]
|
||||
agent_user = os.environ.get("AGENT_USER", "agent")
|
||||
|
||||
backend = IsolatedShellBackend(
|
||||
user=agent_user,
|
||||
root_dir=workspace_dir,
|
||||
virtual_mode=True,
|
||||
backend = CompositeBackend(
|
||||
routes={
|
||||
workspace_dir: FilesystemBackend(workspace_dir, virtual_mode=True),
|
||||
}
|
||||
)
|
||||
|
||||
# noinspection PyTypeChecker
|
||||
|
|
@ -46,6 +47,18 @@ def create_agent() -> Agent:
|
|||
checkpointer=MemorySaver(),
|
||||
tools=tools + [send_file],
|
||||
backend=backend,
|
||||
permissions=[
|
||||
FilesystemPermission(
|
||||
operations=["read", "write"],
|
||||
paths=["/workspace/**"],
|
||||
mode="allow",
|
||||
),
|
||||
FilesystemPermission(
|
||||
operations=["read", "write"],
|
||||
paths=["/**"],
|
||||
mode="deny"
|
||||
)
|
||||
]
|
||||
)
|
||||
agent.backend = backend
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue