Skip to content

Commit 6272a60

Browse files
committed
dynamic load of agent runners
1 parent 869fb02 commit 6272a60

File tree

2 files changed

+119
-9
lines changed

2 files changed

+119
-9
lines changed

operate/services/agent_runner.py

+105
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
import stat
2+
import os
3+
from pathlib import Path
4+
import platform
5+
import shutil
6+
from tempfile import TemporaryDirectory
7+
from aea.configurations.data_types import PublicId
8+
from regex import A
9+
import requests
10+
11+
AGENTS_SUPPORTED = {
12+
"valory": {
13+
"trader": "https://github.com/valory-xyz/trader-test/",
14+
"optimus": "https://github.com/valory-xyz/optimus-testing/",
15+
},
16+
"dvilela": {"memeooorr": "https://github.com/valory-xyz/meme-ooorr-test/"},
17+
}
18+
19+
20+
def get_agent_runner_executable_name():
21+
22+
if platform.system() == "Darwin":
23+
os_name = "macos"
24+
elif platform.system() == "Windows":
25+
os_name = "windows"
26+
else:
27+
raise ValueError("Platform not supported!")
28+
29+
if platform.machine().lower() in ("x86_64", "amd64"):
30+
arch = "x64"
31+
elif platform.machine().lower() == "arm64":
32+
arch = "arm64"
33+
if os_name == "windows":
34+
raise ValueError("Windows arm64 is not supported!")
35+
else:
36+
raise ValueError(f"unsupported arch: {platform.machine()}")
37+
38+
exec_name = f"agent_runner_{os_name}_{arch}"
39+
if platform.system() == "Windows":
40+
exec_name += ".exe"
41+
return exec_name
42+
43+
44+
def parse_agent(public_id_str):
45+
public_id = PublicId.from_str(public_id_string=public_id_str)
46+
return (public_id.author, public_id.name)
47+
48+
49+
def download_file(url, save_path):
50+
try:
51+
# Send a GET request to the URL
52+
response = requests.get(url, stream=True)
53+
response.raise_for_status() # Raise an error for bad status codes (4xx or 5xx)
54+
55+
# Open the file in binary write mode and save the content
56+
with open(save_path, "wb") as file:
57+
for chunk in response.iter_content(chunk_size=8192):
58+
file.write(chunk)
59+
60+
print(f"File downloaded and saved to {save_path}")
61+
except requests.exceptions.RequestException as e:
62+
print(f"Error downloading file: {e}")
63+
raise
64+
65+
66+
def download_agent_runner(
67+
target_path: Path, agent_runner_name: str, agent_public_id_str: str
68+
):
69+
agent_author, agent_name = parse_agent(public_id_str=agent_public_id_str)
70+
if not agent_author in AGENTS_SUPPORTED:
71+
raise ValueError(f"No agents supported for author {agent_author}")
72+
if not agent_name in AGENTS_SUPPORTED[agent_author]:
73+
raise ValueError(
74+
f"No agent named {agent_name} supported for author {agent_author}"
75+
)
76+
repo_url = AGENTS_SUPPORTED[agent_author][agent_name]
77+
download_url = f"{repo_url}/releases/latest/download/{agent_runner_name}"
78+
try:
79+
with TemporaryDirectory() as tmp_dir:
80+
tmp_file = Path(tmp_dir) / "agent_runner"
81+
download_file(download_url, tmp_file)
82+
shutil.copy2(tmp_file, target_path)
83+
if os.name == "posix":
84+
target_path.chmod(target_path.stat().st_mode | stat.S_IEXEC)
85+
except:
86+
# remove in cae of errors
87+
if target_path.exists():
88+
target_path.unlink(missing_ok=True)
89+
raise
90+
91+
92+
def get_agent_runner_path(service_dir: Path, agent_public_id_str: str) -> str:
93+
agent_runner_name = get_agent_runner_executable_name()
94+
agent_runner_path: Path = service_dir / agent_runner_name
95+
96+
if agent_runner_path.exists():
97+
print(f"agent runner {agent_runner_path} already exists. dont download it.")
98+
else:
99+
print(f"agent runner {agent_runner_path} does not exists. downloading it.")
100+
download_agent_runner(
101+
target_path=agent_runner_path,
102+
agent_runner_name=agent_runner_name,
103+
agent_public_id_str=agent_public_id_str,
104+
)
105+
return str(agent_runner_path)

operate/services/deployment_runner.py

+14-9
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@
4040

4141
from operate import constants
4242

43+
from .agent_runner import get_agent_runner_path
44+
4345

4446
class AbstractDeploymentRunner(ABC):
4547
"""Abstract deployment runner."""
@@ -194,7 +196,7 @@ def _setup_agent(self) -> None:
194196
)
195197

196198
self._run_aea_command(
197-
"fetch", env["AEA_AGENT"], "--alias", "agent", cwd=working_dir
199+
"-s", "fetch", env["AEA_AGENT"], "--alias", "agent", cwd=working_dir
198200
)
199201

200202
# Add keys
@@ -264,8 +266,17 @@ class PyInstallerHostDeploymentRunner(BaseDeploymentRunner):
264266
@property
265267
def _agent_runner_bin(self) -> str:
266268
"""Return aea_bin path."""
267-
abin = str(Path(os.path.dirname(sys.executable)) / "aea_bin") # type: ignore # pylint: disable=protected-access
268-
return abin
269+
env = json.loads(
270+
(self._work_directory / "agent.json").read_text(encoding="utf-8")
271+
)
272+
273+
agent_publicid_str = env["AEA_AGENT"]
274+
service_dir = self._work_directory.parent
275+
276+
agent_runner_bin = get_agent_runner_path(
277+
service_dir=service_dir, agent_public_id_str=agent_publicid_str
278+
)
279+
return str(agent_runner_bin)
269280

270281
@property
271282
def _tendermint_bin(self) -> str:
@@ -340,12 +351,6 @@ class PyInstallerHostDeploymentRunnerMac(PyInstallerHostDeploymentRunner):
340351
class PyInstallerHostDeploymentRunnerWindows(PyInstallerHostDeploymentRunner):
341352
"""Windows deployment runner."""
342353

343-
@property
344-
def _agent_runner_bin(self) -> str:
345-
"""Return aea_bin path."""
346-
abin = str(Path(os.path.dirname(sys.executable)) / "aea_win.exe") # type: ignore # pylint: disable=protected-access
347-
return abin
348-
349354
@property
350355
def _tendermint_bin(self) -> str:
351356
"""Return tendermint path."""

0 commit comments

Comments
 (0)