разделение workspace и system файлов, использование CompositeBackend
This commit is contained in:
parent
74e884179a
commit
7907f57971
7 changed files with 85 additions and 32 deletions
|
|
@ -7,4 +7,4 @@
|
|||
*.pyc
|
||||
__pycache__/
|
||||
.env
|
||||
workspace/
|
||||
/data/
|
||||
|
|
|
|||
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -1,4 +1,4 @@
|
|||
workspace/
|
||||
/data/
|
||||
|
||||
.idea/
|
||||
workspace/
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ services:
|
|||
volumes:
|
||||
- ./src:/app/src
|
||||
- ${AGENT_API_PATH}:/agent_api/
|
||||
- ./workspace:/workspace/
|
||||
- ./data/workspace:/workspace/
|
||||
ports:
|
||||
- "8000:8000"
|
||||
env_file:
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ requires-python = ">=3.14"
|
|||
dependencies = [
|
||||
"fastapi>=0.135.3",
|
||||
"uvicorn[standard]>=0.34.0",
|
||||
"deepagents>=0.1.0",
|
||||
"deepagents>=0.5.0",
|
||||
"langchain-openai>=1.1.12",
|
||||
"composio>=0.11.5",
|
||||
"composio-langchain>=0.11.5"
|
||||
"composio-langchain>=0.11.5",
|
||||
]
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
46
uv.lock
generated
46
uv.lock
generated
|
|
@ -19,7 +19,7 @@ dependencies = [
|
|||
requires-dist = [
|
||||
{ name = "composio", specifier = ">=0.11.5" },
|
||||
{ name = "composio-langchain", specifier = ">=0.11.5" },
|
||||
{ name = "deepagents", specifier = ">=0.1.0" },
|
||||
{ name = "deepagents", specifier = ">=0.5.0" },
|
||||
{ name = "fastapi", specifier = ">=0.135.3" },
|
||||
{ name = "langchain-openai", specifier = ">=1.1.12" },
|
||||
{ name = "uvicorn", extras = ["standard"], specifier = ">=0.34.0" },
|
||||
|
|
@ -289,18 +289,19 @@ wheels = [
|
|||
|
||||
[[package]]
|
||||
name = "deepagents"
|
||||
version = "0.4.12"
|
||||
version = "0.5.3"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "langchain" },
|
||||
{ name = "langchain-anthropic" },
|
||||
{ name = "langchain-core" },
|
||||
{ name = "langchain-google-genai" },
|
||||
{ name = "langsmith" },
|
||||
{ name = "wcmatch" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/5a/ef/0b2ccd5e4f40c1554145de17a7f3ee41994de1dda3ea36abe28600f1a3cf/deepagents-0.4.12.tar.gz", hash = "sha256:fc24a691e5cba00920ac4fa1d94f8147d6081fe513ed22bdba7da469288681c3", size = 91870, upload-time = "2026-03-20T14:54:29.904Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/bd/c5/fbf36ff707f7ad4ff2d1590ba8c3b44622370955c74f0c84e4bb1b101d7d/deepagents-0.5.3.tar.gz", hash = "sha256:cbe63bd482c37d3aef883326f5dde70effcd489e67fc91834ffe7a8769796a5f", size = 122654, upload-time = "2026-04-15T13:06:34.875Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/5e/77/63a5cb4e3a8871c4a52d600661a232c26b35f52931ee551c3adc38eeacf6/deepagents-0.4.12-py3-none-any.whl", hash = "sha256:76a272bac25607c5ef8c5adc876e391da945f1107b504686964dfdb6afdc1ebb", size = 104455, upload-time = "2026-03-20T14:54:28.786Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/30/8f/40c91a29e4f094e5a1375e33309a3d0ca2e5204816d1dcdcd41ac38410d8/deepagents-0.5.3-py3-none-any.whl", hash = "sha256:f1f1c968f17a5bfb0a6d588d00c2e83264cdac0faa91f7b522892d5a2bd303cb", size = 138475, upload-time = "2026-04-15T13:06:33.593Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -514,16 +515,16 @@ wheels = [
|
|||
|
||||
[[package]]
|
||||
name = "langchain"
|
||||
version = "1.2.14"
|
||||
version = "1.2.15"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "langchain-core" },
|
||||
{ name = "langgraph" },
|
||||
{ name = "pydantic" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/af/2b/0ca77ee988a9f1c1f1d923115d7c91221ab434067bc36f2f637201aeee81/langchain-1.2.14.tar.gz", hash = "sha256:fc5511e8f8af7efee9e5a144da4392d700d627b301d240470db97272940ad317", size = 574190, upload-time = "2026-03-31T13:50:37.398Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/98/3f/888a7099d2bd2917f8b0c3ffc7e347f1e664cf64267820b0b923c4f339fc/langchain-1.2.15.tar.gz", hash = "sha256:1717b6719daefae90b2728314a5e2a117ff916291e2862595b6c3d6fba33d652", size = 574732, upload-time = "2026-04-03T14:26:03.994Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/4c/87/324ae5fd9993f024339a452fc89e3fd808bccde87ef95c8dafab3de023c0/langchain-1.2.14-py3-none-any.whl", hash = "sha256:96da6d7338d5a6fc41eb4ec0db83f7ef5d03bb5efd17bb269f34ba4378ebdb4d", size = 112715, upload-time = "2026-03-31T13:50:35.997Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3f/e8/a3b8cb0005553f6a876865073c81ef93bd7c5b18381bcb9ba4013af96ebc/langchain-1.2.15-py3-none-any.whl", hash = "sha256:e349db349cb3e9550c4044077cf90a1717691756cc236438404b23500e615874", size = 112714, upload-time = "2026-04-03T14:26:02.557Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -542,10 +543,11 @@ wheels = [
|
|||
|
||||
[[package]]
|
||||
name = "langchain-core"
|
||||
version = "1.2.25"
|
||||
version = "1.3.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "jsonpatch" },
|
||||
{ name = "langchain-protocol" },
|
||||
{ name = "langsmith" },
|
||||
{ name = "packaging" },
|
||||
{ name = "pydantic" },
|
||||
|
|
@ -554,9 +556,9 @@ dependencies = [
|
|||
{ name = "typing-extensions" },
|
||||
{ name = "uuid-utils" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/86/2a/d65de24fc9b7989137253da8973f850f3e39b4ce3e0377bc8200d6b3c189/langchain_core-1.2.25.tar.gz", hash = "sha256:77e032b96509d0eb1f6875042fdf97b7e2334a815314700c6894d9d078909b9c", size = 842347, upload-time = "2026-04-02T22:39:11.528Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/a8/03/7219502e8ca728d65eb44d7a3eb60239230742a70dbfc9241b9bfd61c4ab/langchain_core-1.3.2.tar.gz", hash = "sha256:fd7a50b2f28ba561fd9d7f5d2760bc9e06cf00cdf820a3ccafe88a94ffa8d5b7", size = 911813, upload-time = "2026-04-24T15:49:23.699Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/3d/0e/7b31b0249f9b9b0fc7829d5b0ee484b8f8d43c78e376e9951e2ef3eac70c/langchain_core-1.2.25-py3-none-any.whl", hash = "sha256:0c05bf395aec6d2dfa14488fd006f7bcd0540e7e89287e04f92203532a82c828", size = 506866, upload-time = "2026-04-02T22:39:10.137Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7d/d5/8fa4431007cbb7cfed7590f4d6a5dea3ad724f4174d248f6642ef5ce7d05/langchain_core-1.3.2-py3-none-any.whl", hash = "sha256:d44a66127f9f8db735bdfd0ab9661bccb47a97113cfd3f2d89c74864422b7274", size = 542390, upload-time = "2026-04-24T15:49:21.991Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -588,9 +590,21 @@ wheels = [
|
|||
{ url = "https://files.pythonhosted.org/packages/6e/a6/68fb22e3604015e6f546fa1d3677d24378b482855ae74710cbf4aec44132/langchain_openai-1.1.12-py3-none-any.whl", hash = "sha256:da71ca3f2d18c16f7a2443cc306aa195ad2a07054335ac9b0626dcae02b6a0c5", size = 88487, upload-time = "2026-03-23T18:59:17.978Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "langchain-protocol"
|
||||
version = "0.0.12"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "typing-extensions" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/5c/51/1157009b6f94e6e58be58fa8b620187d657909a8b36a6bf5b0c52a2711f6/langchain_protocol-0.0.12.tar.gz", hash = "sha256:5e14c434290a705c9510fdb1a83ecf7561a5e6e0dfd053930ade80dba069269f", size = 6408, upload-time = "2026-04-25T01:05:01.489Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/95/82/3431e3061c917439589fa88a6b23c9bc0e154cba0f05d2e895a68c76ff74/langchain_protocol-0.0.12-py3-none-any.whl", hash = "sha256:402b61f42d4139692528cf37226c367bb6efc8ff8165b29380accb0abfece7b2", size = 6639, upload-time = "2026-04-25T01:05:00.487Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "langgraph"
|
||||
version = "1.1.4"
|
||||
version = "1.1.9"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "langchain-core" },
|
||||
|
|
@ -600,9 +614,9 @@ dependencies = [
|
|||
{ name = "pydantic" },
|
||||
{ name = "xxhash" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/c0/ba/8a8f48ca1248ecff4844cb27247d10a85f05b4ac6b903298d36b2ca090fd/langgraph-1.1.4.tar.gz", hash = "sha256:c951a859f68a021c69a27500db4eafc1900fc7ac32a54f7fc31d277165d04bed", size = 545440, upload-time = "2026-03-31T12:56:45.344Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/8c/d5/9d9c65d5500a1ca7ea63d6d65aecfb248037018a74d7d4ef52e276bb4e4b/langgraph-1.1.9.tar.gz", hash = "sha256:bc5a49d5a5e71fda1f9c53c06c62f4caec9a95545b739d130a58b6ab3269e274", size = 560717, upload-time = "2026-04-21T13:43:06.809Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/d0/74/22ea4734247b59e7c98e575e31a1f463366b084e0dc83cf63715b079ff28/langgraph-1.1.4-py3-none-any.whl", hash = "sha256:77ebe7ed44a2699f13696bf41f1dabe7b5fa8e6ad51e3597f2f175492e8f3656", size = 168190, upload-time = "2026-03-31T12:56:44.221Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/16/58/0380420e66619d12c992c1f8cfda0c7a04e8f0fe8a84752245b9e7b1cba7/langgraph-1.1.9-py3-none-any.whl", hash = "sha256:7db13ceecde4ea643df6c097dcc9e534895dcd9fcc6500eeff2f2cde0fab16b2", size = 173744, upload-time = "2026-04-21T13:43:05.513Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -620,15 +634,15 @@ wheels = [
|
|||
|
||||
[[package]]
|
||||
name = "langgraph-prebuilt"
|
||||
version = "1.0.8"
|
||||
version = "1.0.11"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "langchain-core" },
|
||||
{ name = "langgraph-checkpoint" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/0d/06/dd61a5c2dce009d1b03b1d56f2a85b3127659fdddf5b3be5d8f1d60820fb/langgraph_prebuilt-1.0.8.tar.gz", hash = "sha256:0cd3cf5473ced8a6cd687cc5294e08d3de57529d8dd14fdc6ae4899549efcf69", size = 164442, upload-time = "2026-02-19T18:14:39.083Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/8d/bb/0e0b3eb33b1f2f32f8810a49aa24b7d11a5b0ed45f679386095946a59557/langgraph_prebuilt-1.0.11.tar.gz", hash = "sha256:0e71545f706a134b6a80a2a56916562797b499e3e4ab6eed5ce89396ac03d322", size = 171759, upload-time = "2026-04-24T18:18:34.528Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/dc/41/ec966424ad3f2ed3996d24079d3342c8cd6c0bd0653c12b2a917a685ec6c/langgraph_prebuilt-1.0.8-py3-none-any.whl", hash = "sha256:d16a731e591ba4470f3e313a319c7eee7dbc40895bcf15c821f985a3522a7ce0", size = 35648, upload-time = "2026-02-19T18:14:37.611Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f6/8c/f4c574cb75ae9b8a474215d03a029ea723c919f65771ca1c82fe532d0297/langgraph_prebuilt-1.0.11-py3-none-any.whl", hash = "sha256:7afbaf5d64959e452976664c75bb8ec24098d3510cf9c205919baf443e7342ec", size = 36832, upload-time = "2026-04-24T18:18:33.586Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue