From 0cb5b816df2214ac3352ed67e0dc61628bda470d Mon Sep 17 00:00:00 2001 From: Reza Rahemtola Date: Tue, 5 Nov 2024 01:34:01 +0900 Subject: [PATCH] feat(backend): Public agent route started and utils package added --- backend/mypy.ini | 2 + backend/poetry.lock | 53 +++++++++++++++++++++++++- backend/pyproject.toml | 1 + backend/src/interfaces/agent.py | 19 +++++++-- backend/src/interfaces/subscription.py | 16 -------- backend/src/main.py | 36 ++++++++++++++++- 6 files changed, 104 insertions(+), 23 deletions(-) create mode 100644 backend/mypy.ini delete mode 100644 backend/src/interfaces/subscription.py diff --git a/backend/mypy.ini b/backend/mypy.ini new file mode 100644 index 0000000..fa36901 --- /dev/null +++ b/backend/mypy.ini @@ -0,0 +1,2 @@ +[mypy-libertai_utils.*] +ignore_missing_imports = True \ No newline at end of file diff --git a/backend/poetry.lock b/backend/poetry.lock index 2d024b7..e263e5f 100644 --- a/backend/poetry.lock +++ b/backend/poetry.lock @@ -1395,6 +1395,17 @@ MarkupSafe = ">=2.0" [package.extras] i18n = ["Babel (>=2.7)"] +[[package]] +name = "jsonalias" +version = "0.1.1" +description = "A microlibrary that defines a Json type alias for Python." +optional = false +python-versions = ">=3.7,<4.0" +files = [ + {file = "jsonalias-0.1.1-py3-none-any.whl", hash = "sha256:a56d2888e6397812c606156504e861e8ec00e188005af149f003c787db3d3f18"}, + {file = "jsonalias-0.1.1.tar.gz", hash = "sha256:64f04d935397d579fc94509e1fcb6212f2d081235d9d6395bd10baedf760a769"}, +] + [[package]] name = "jsonschema" version = "4.23.0" @@ -1445,6 +1456,24 @@ files = [ cryptography = ">=3.4" typing-extensions = ">=4.5.0" +[[package]] +name = "libertai-utils" +version = "0.0.2" +description = "LibertAI internal types and functions" +optional = false +python-versions = "<4.0,>=3.12" +files = [ + {file = "libertai_utils-0.0.2-py3-none-any.whl", hash = "sha256:2a6e8aa2e1cff5feca77ddf713bf2f8e2b22f5cd110083421b59a8e9b0f001bc"}, + {file = "libertai_utils-0.0.2.tar.gz", hash = "sha256:7376a2aa2e93866a537e32cc180cf46ac9167fba12a8057964cdbe3f9297c32b"}, +] + +[package.dependencies] +eciespy = ">=0.4.2,<0.5.0" +pydantic = ">=1.10.5,<2.0.0" +pynacl = ">=1.5.0,<2.0.0" +solders = ">=0.22.0,<0.23.0" +web3 = ">=6.3.0,<7.0.0" + [[package]] name = "lru-dict" version = "1.3.0" @@ -2573,6 +2602,28 @@ files = [ {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, ] +[[package]] +name = "solders" +version = "0.22.0" +description = "Python bindings for Solana Rust tools" +optional = false +python-versions = ">=3.7" +files = [ + {file = "solders-0.22.0-cp37-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:f03a49ee921b233c37c1ac54ed3764b935602ba95c543d5b0b81ce41ead0b8dd"}, + {file = "solders-0.22.0-cp37-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3b390d62847e8d0dda69f31b53bde8731a586a7f6670630aa30804cc0ab52016"}, + {file = "solders-0.22.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cef27fae7b9356ce19f96f58ed01235ddc15e3a276862fcf67902678f16c18e7"}, + {file = "solders-0.22.0-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:80e92568ec7e55045d97d201fe43b21d76ee92583810e1fec6e633f00cdb0df3"}, + {file = "solders-0.22.0-cp37-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:81bf7943e1b3a31a6375e8a2e788a0a35b36357197eef281cce740bd705265c2"}, + {file = "solders-0.22.0-cp37-abi3-musllinux_1_2_i686.whl", hash = "sha256:786eb2b39a5f894998a7a46d8d959175a0027a0c643d06b514a702730042d380"}, + {file = "solders-0.22.0-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:4ca64741a5a24c42813a89a0e75f7735a51bf56e01850a887f9428e33cd62ad0"}, + {file = "solders-0.22.0-cp37-abi3-win_amd64.whl", hash = "sha256:16732f4a43437121bdbb494e626db3737a33c6ba94b16016c35c34a23d5a2775"}, + {file = "solders-0.22.0.tar.gz", hash = "sha256:2ae6cf45a3dcb833f36c7e6197d8a975185f8ab00d5e2f4b2195611806c02312"}, +] + +[package.dependencies] +jsonalias = "0.1.1" +typing-extensions = ">=4.2.0" + [[package]] name = "starlette" version = "0.41.2" @@ -3044,4 +3095,4 @@ propcache = ">=0.2.0" [metadata] lock-version = "2.0" python-versions = "^3.12" -content-hash = "297c6c61912ac99824a326699d39176790558b315153f97616cd998b6125bc49" +content-hash = "0258eecb5c47c8d191c56ebbaa9de5c2cae64fae54b8a3212803513ce627fd08" diff --git a/backend/pyproject.toml b/backend/pyproject.toml index b2b61a2..02086dd 100644 --- a/backend/pyproject.toml +++ b/backend/pyproject.toml @@ -14,6 +14,7 @@ python = "^3.12" fastapi = { extras = ["standard"], version = "^0.115.2" } aleph-sdk-python = "^1.1.0" eciespy = "^0.4.2" +libertai-utils = "^0.0.2" [tool.poetry.group.dev.dependencies] mypy = "^1.12.0" diff --git a/backend/src/interfaces/agent.py b/backend/src/interfaces/agent.py index 6e61e41..76d1ac2 100644 --- a/backend/src/interfaces/agent.py +++ b/backend/src/interfaces/agent.py @@ -1,7 +1,7 @@ +from libertai_utils.interfaces.subscription import SubscriptionAccount from pydantic import BaseModel, validator from src.config import config -from src.interfaces.subscription import SubscriptionAccount class DeleteAgentBody(BaseModel): @@ -25,14 +25,25 @@ class UpdateAgentResponse(BaseModel): vm_hash: str -class Agent(BaseModel): +class PublicAgentData(BaseModel): id: str - subscription_id: str vm_hash: str | None - encrypted_secret: str last_update: int + + +class Agent(PublicAgentData): + subscription_id: str + encrypted_secret: str tags: list[str] class FetchedAgent(Agent): post_hash: str + + +class GetAgentResponse(PublicAgentData): + pass + + +class GetAgentSecretResponse(BaseModel): + secret: str diff --git a/backend/src/interfaces/subscription.py b/backend/src/interfaces/subscription.py deleted file mode 100644 index 5f1924d..0000000 --- a/backend/src/interfaces/subscription.py +++ /dev/null @@ -1,16 +0,0 @@ -# TODO: make a shared package for these types -from enum import Enum - -from pydantic import BaseModel - - -class SubscriptionChain(str, Enum): - base = "base" - - -class SubscriptionAccount(BaseModel): - address: str - chain: SubscriptionChain - - class Config: - schema_extra = {"example": {"address": "0x0000000000000000000000000000000000000000", "chain": "base"}} diff --git a/backend/src/main.py b/backend/src/main.py index c9eb4df..c7ef97d 100644 --- a/backend/src/main.py +++ b/backend/src/main.py @@ -16,6 +16,8 @@ SetupAgentBody, DeleteAgentBody, UpdateAgentResponse, + GetAgentResponse, + GetAgentSecretResponse, ) from src.interfaces.aleph import AlephVolume from src.utils.agent import fetch_agents, fetch_agent_program_message @@ -66,9 +68,39 @@ async def setup(body: SetupAgentBody) -> None: ) -@app.put("/agent", description="Deploy an agent or update it") +@app.get("/agent/{agent_id}", description="Get an agent public information") +async def get_agent_public_info(agent_id: str) -> GetAgentResponse: + agents = await fetch_agents([agent_id]) + + if len(agents) != 1: + raise HTTPException( + status_code=HTTPStatus.NOT_FOUND, + detail=f"Agent with ID {agent_id} not found.", + ) + agent = agents[0] + + return GetAgentResponse( + id=agent.id, vm_hash=agent.vm_hash, last_update=agent.last_update + ) + + +@app.get("/agent/{agent_id}/secret", description="Get an agent secret") +async def get_agent_secret(agent_id: str, signature: str) -> GetAgentSecretResponse: + agents = await fetch_agents([agent_id]) + + if len(agents) != 1: + raise HTTPException( + status_code=HTTPStatus.NOT_FOUND, + detail=f"Agent with ID {agent_id} not found.", + ) + agent = agents[0] + # TODO: real implementation + return GetAgentSecretResponse(secret="") + + +@app.put("/agent/{agent_id}", description="Deploy an agent or update it") async def update( - agent_id: str = Form(), + agent_id: str, secret: str = Form(), code: UploadFile = File(...), packages: UploadFile = File(...),