Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(core): add message endpoint for inspector #490

Merged
merged 33 commits into from
Aug 30, 2024
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
381cdb9
feat(core): add message endpoint for inspector
Alejandro-Morales Aug 7, 2024
4e6ffd2
fix: ruff check
Alejandro-Morales Aug 7, 2024
8f53362
fix: ruff check
Alejandro-Morales Aug 7, 2024
f4acd8c
Merge branch 'main' into feat/message-inspector
Alejandro-Morales Aug 15, 2024
bd8d4cc
feat: move file storage to memory storage
Alejandro-Morales Aug 15, 2024
f13f0c4
fix: ruff check
Alejandro-Morales Aug 16, 2024
c899ca5
Merge branch 'main' into feat/message-inspector
Alejandro-Morales Aug 16, 2024
2a1e27d
updates on Florians comments
Alejandro-Morales Aug 16, 2024
613c257
ruff format
Alejandro-Morales Aug 16, 2024
7a78622
Merge branch 'main' into feat/message-inspector
Alejandro-Morales Aug 16, 2024
7dd0098
feat: updates on florians comments and agent_info endpoint
Alejandro-Morales Aug 19, 2024
b40656a
fix: delete unused imports
Alejandro-Morales Aug 19, 2024
474d5bd
fix: ruff format check
Alejandro-Morales Aug 19, 2024
d244919
Merge branch 'main' into feat/message-inspector
Alejandro-Morales Aug 19, 2024
c6e5e62
feat: add retention mechanism
Alejandro-Morales Aug 19, 2024
5dc4996
Merge branch 'main' into feat/message-inspector
Alejandro-Morales Aug 21, 2024
f43ab1c
feat: Bureau integration
Alejandro-Morales Aug 22, 2024
46aea4c
try adding server headers
Archento Aug 22, 2024
e37ee6a
fix: format
Alejandro-Morales Aug 22, 2024
05f08e8
fix: model dump agent endpoint list
jrriehl Aug 23, 2024
0e3c4d1
loosen access control rules
Archento Aug 23, 2024
724ede6
Merge branch 'main' into feat/message-inspector
Alejandro-Morales Aug 28, 2024
e65f152
feat: Refactoring based on new REST updates
Alejandro-Morales Aug 28, 2024
39f87b5
fix: test and ruff check
Alejandro-Morales Aug 28, 2024
ead3242
minor corrections
Alejandro-Morales Aug 28, 2024
01b075f
fix rest example, make inspector opt-out, enforce reserved routes, wr…
Archento Aug 29, 2024
887c3f7
fix test
Archento Aug 29, 2024
2999472
simplify AgentEndpoint model
Archento Aug 29, 2024
bec7141
relocate cache ref to dispenser
Archento Aug 30, 2024
a593e94
update docs
Archento Aug 30, 2024
4bcf5e8
fix: small context inconsistency
Archento Aug 30, 2024
0c72136
another small revert in context
Archento Aug 30, 2024
a28162e
refactor retention mechanism
Archento Aug 30, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion python/src/uagents/agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,11 @@ def __init__(

if not self._use_mailbox:
self._server = ASGIServer(
self._port, self._loop, self._queries, logger=self._logger
self._port,
self._loop,
self._queries,
self._dispenser,
logger=self._logger,
)

# define default error message handler
Expand Down
34 changes: 31 additions & 3 deletions python/src/uagents/asgi.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@
import pydantic
import uvicorn
from requests.structures import CaseInsensitiveDict
from uagents.communication import enclose_response_raw
from uagents.communication import Dispenser, enclose_response_raw
from uagents.config import RESPONSE_TIME_HINT_SECONDS
from uagents.context import ERROR_MESSAGE_DIGEST
from uagents.crypto import is_user_address
from uagents.dispatch import dispatcher
from uagents.envelope import Envelope
from uagents.envelope import Envelope, EnvelopeHistory
from uagents.models import ErrorMessage
from uagents.utils import get_logger

Expand Down Expand Up @@ -44,6 +44,7 @@ def __init__(
port: int,
loop: asyncio.AbstractEventLoop,
queries: Dict[str, asyncio.Future],
dispenser: Dispenser,
logger: Optional[Logger] = None,
):
"""
Expand All @@ -58,6 +59,7 @@ def __init__(
self._port = int(port)
self._loop = loop
self._queries = queries
self._dispenser = dispenser
self._logger = logger or get_logger("server")
self._server = None

Expand Down Expand Up @@ -149,6 +151,26 @@ async def handle_missing_content_type(self, headers: CaseInsensitiveDict, send):
}
)

async def handle_get_messages(self, send):
"""
Handle retrieval of stored messages.
"""
response = EnvelopeHistory(
Alejandro-Morales marked this conversation as resolved.
Show resolved Hide resolved
envelopes=dispatcher.received_messages + self._dispenser.sent_messages
).model_dump_json()
await send(
{
"type": "http.response.start",
"status": 200,
"headers": [
[b"content-type", b"application/json"],
],
}
)
await send(
{"type": "http.response.body", "body": json.dumps(response).encode()}
Alejandro-Morales marked this conversation as resolved.
Show resolved Hide resolved
)

async def serve(self):
"""
Start the server.
Expand All @@ -173,6 +195,13 @@ async def __call__(self, scope, receive, send): # pylint: disable=too-many-bra

assert scope["type"] == "http"

request_method = scope["method"]
path = scope["path"]

if request_method == "GET" and path == "/messages":
await self.handle_get_messages(send)
return

if scope["path"] != "/submit":
await send(
{
Expand All @@ -190,7 +219,6 @@ async def __call__(self, scope, receive, send): # pylint: disable=too-many-bra

headers = CaseInsensitiveDict(scope.get("headers", {}))

request_method = scope["method"]
if request_method == "HEAD":
await self.handle_readiness_probe(headers, send)
return
Expand Down
8 changes: 7 additions & 1 deletion python/src/uagents/communication.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from uagents.config import DEFAULT_ENVELOPE_TIMEOUT_SECONDS
from uagents.crypto import Identity, is_user_address
from uagents.dispatch import JsonStr, dispatcher
from uagents.envelope import Envelope
from uagents.envelope import Envelope, EnvelopeHistory, EnvelopeHistoryEntry
from uagents.models import Model
from uagents.resolver import GlobalResolver, Resolver
from uagents.utils import get_logger
Expand Down Expand Up @@ -72,6 +72,7 @@ def __init__(self):
self._envelopes: asyncio.Queue[
Tuple[Envelope, List[str], asyncio.Future, bool]
] = asyncio.Queue()
self.sent_messages: EnvelopeHistory = []

def add_envelope(
self,
Expand Down Expand Up @@ -104,6 +105,11 @@ async def run(self):
sync=sync,
)
response_future.set_result(result)
env_dict = env.model_dump()
env_dict["payload"] = env.decode_payload()
env_dict["timestamp"] = int(time())
Alejandro-Morales marked this conversation as resolved.
Show resolved Hide resolved

self.sent_messages.append(EnvelopeHistoryEntry(**env_dict))
except Exception as err:
LOGGER.error(f"Failed to send envelope: {err}")

Expand Down
16 changes: 16 additions & 0 deletions python/src/uagents/dispatch.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import uuid
from abc import ABC, abstractmethod
from time import time
from typing import Dict, Set

from uagents.envelope import EnvelopeHistory, EnvelopeHistoryEntry

JsonStr = str


Expand All @@ -24,6 +27,7 @@ class Dispatcher:

def __init__(self):
self._sinks: Dict[str, Set[Sink]] = {}
self.received_messages: EnvelopeHistory = []

@property
def sinks(self) -> Dict[str, Set[Sink]]:
Expand Down Expand Up @@ -56,5 +60,17 @@ async def dispatch(
for handler in self._sinks.get(destination, set()):
await handler.handle_message(sender, schema_digest, message, session)

self.received_messages.append(
EnvelopeHistoryEntry(
timestamp=int(time()),
Alejandro-Morales marked this conversation as resolved.
Show resolved Hide resolved
version=1,
sender=sender,
target=destination,
session=session,
schema_digest=schema_digest,
payload=message,
)
)


dispatcher = Dispatcher()
33 changes: 30 additions & 3 deletions python/src/uagents/envelope.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@
import base64
import hashlib
import struct
from typing import Callable, Optional
import time
from typing import Callable, List, Optional

from pydantic import UUID4, BaseModel, ConfigDict
from pydantic import UUID4, BaseModel, ConfigDict, Field, field_serializer
from uagents.crypto import Identity
from uagents.dispatch import JsonStr

JsonStr = str


class Envelope(BaseModel):
Expand Down Expand Up @@ -109,3 +111,28 @@ def _digest(self) -> bytes:
if self.nonce is not None:
hasher.update(struct.pack(">Q", self.nonce))
return hasher.digest()


class EnvelopeHistoryEntry(BaseModel):
timestamp: int = Field(default_factory=lambda: int(time.time()))
version: int
sender: str
target: str
session: UUID4
schema_digest: str
protocol_digest: Optional[str] = None
payload: Optional[str] = None

@field_serializer("session")
def serialize_dt(self, session: UUID4, _info):
Alejandro-Morales marked this conversation as resolved.
Show resolved Hide resolved
return str(session)


class EnvelopeHistory(BaseModel):
envelopes: List[EnvelopeHistoryEntry]

@field_serializer("envelopes", when_used="json")
def serialize_envelopes_in_order(
self, envelopes: List[EnvelopeHistoryEntry], _info
):
return sorted(envelopes, key=lambda e: e.timestamp)
Loading