attp-client 0.0.1__py3-none-any.whl → 0.0.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
attp_client/catalog.py CHANGED
@@ -1,11 +1,21 @@
1
+ import asyncio
1
2
  from typing import Any, Callable, MutableMapping
3
+
4
+ from attp_client.errors.attp_exception import AttpException
2
5
  from attp_client.errors.not_found import NotFoundError
6
+ from attp_client.interfaces.catalogs.tools.envelope import IEnvelope
7
+ from attp_client.interfaces.error import IErr
3
8
  from attp_client.tools import ToolsManager
4
9
 
10
+ from reactivex import operators as ops
11
+ from reactivex.scheduler.eventloop import AsyncIOScheduler
12
+
13
+ from attp_core.rs_api import PyAttpMessage
14
+
5
15
 
6
16
  class AttpCatalog:
7
- attached_tools: MutableMapping[str, Callable[..., Any]]
8
- tool_name_to_id_symlink: MutableMapping[str, str]
17
+ attached_tools: MutableMapping[str, Callable[..., Any]] # id, callback
18
+ tool_name_to_id_symlink: MutableMapping[str, str] # name, id
9
19
 
10
20
  def __init__(
11
21
  self,
@@ -18,12 +28,51 @@ class AttpCatalog:
18
28
  self.tool_manager = manager
19
29
  self.attached_tools = {}
20
30
  self.tool_name_to_id_symlink = {}
31
+
32
+ self.responder = self.tool_manager.router.responder
33
+
34
+ async def start_tool_listener(self):
35
+ scheduler = AsyncIOScheduler(asyncio.get_event_loop())
36
+
37
+ def handle_call(item: IEnvelope):
38
+ asyncio.create_task(self.handle_call(item))
39
+
40
+ def send_err(err: AttpException):
41
+ asyncio.create_task(self.tool_manager.router.session.send_error(err=err.to_ierr(), correlation_id=None, route=1))
42
+
43
+ def envelopize(item: PyAttpMessage):
44
+ if not item.payload:
45
+ raise AttpException("EmptyPayload", detail={"message": "Payload was empty."})
46
+ try:
47
+ return IEnvelope.mps(item.payload)
48
+ except Exception as e:
49
+ raise AttpException("InvalidPayload", detail={"message": f"Payload was invalid: {str(e)}"})
50
+
51
+ def catch_handler(err: Any, _: Any):
52
+ # Convert any exception to AttpException if needed
53
+ if not isinstance(err, AttpException):
54
+ attp_err = AttpException("UnhandledException", detail={"message": str(err)})
55
+ else:
56
+ attp_err = err
57
+ send_err(attp_err)
58
+ # Return an empty observable to terminate the stream after error
59
+ from reactivex import empty
60
+ return empty()
61
+
62
+ self.responder.pipe(
63
+ ops.filter(lambda item: item.payload is not None and item.correlation_id == 1),
64
+ ops.map(lambda item: envelopize(item)),
65
+ ops.catch(catch_handler),
66
+ ops.filter(lambda item: item.catalog == self.catalog_name and item.tool_id in self.attached_tools),
67
+ ops.observe_on(scheduler),
68
+ ).subscribe(lambda item: handle_call(item))
21
69
 
22
70
  async def attach_tool(
23
71
  self,
24
- callback: Callable[..., Any],
72
+ callback: Callable[[IEnvelope], Any],
25
73
  name: str,
26
74
  description: str | None = None,
75
+ schema: dict | None = None,
27
76
  schema_id: str | None = None,
28
77
  *,
29
78
  return_direct: bool = False,
@@ -37,6 +86,7 @@ class AttpCatalog:
37
86
  description=description,
38
87
  schema_id=schema_id,
39
88
  return_direct=return_direct,
89
+ schema=schema,
40
90
  schema_ver=schema_ver,
41
91
  timeout_ms=timeout_ms,
42
92
  idempotent=idempotent
@@ -56,4 +106,12 @@ class AttpCatalog:
56
106
  raise NotFoundError(f"Tool {name} not marked as registered and wasn't found in the catalog {self.catalog_name}.")
57
107
 
58
108
  await self.tool_manager.unregister(self.catalog_name, tool_id)
59
- return tool_id
109
+ return tool_id
110
+
111
+ async def handle_call(self, envelope: IEnvelope) -> Any:
112
+ tool = self.attached_tools.get(envelope.tool_id)
113
+
114
+ if not tool:
115
+ raise NotFoundError(f"Tool {envelope.tool_id} not marked as registered and wasn't found in the catalog {self.catalog_name}.")
116
+
117
+ return await tool(envelope)
@@ -0,0 +1,13 @@
1
+ from typing import Annotated, Any, Mapping
2
+ from pydantic import Field
3
+ from typing_extensions import Doc
4
+ from attp_client.misc.fixed_basemodel import FixedBaseModel
5
+
6
+
7
+ class IEnvelope(FixedBaseModel):
8
+ """Uniform tool output"""
9
+ type: Annotated[str, Doc("Envelop discriminator; For tools only 'tool-call'")] = Field("tool-call")
10
+ catalog: Annotated[str, Doc("Tool catalog name where tool is registered and being called from")]
11
+ tool_id: Annotated[str, Doc("Tool ID being called")]
12
+ metadata: Annotated[Mapping[str, Any], Doc("AgentHub/trace metadata")] = Field(default_factory=dict)
13
+ data: Annotated[Mapping[str, Any], Doc("Tool output JSON matching provided tool arg schema")]
attp_client/tools.py CHANGED
@@ -15,6 +15,7 @@ class ToolsManager:
15
15
  name: str,
16
16
  description: str | None = None,
17
17
  schema_id: str | None = None,
18
+ schema: dict | None = None,
18
19
  *,
19
20
  return_direct: bool = False,
20
21
  schema_ver: str = "1.0",
@@ -31,6 +32,7 @@ class ToolsManager:
31
32
  "schema_id": schema_id,
32
33
  "return_direct": return_direct,
33
34
  "schema_ver": schema_ver,
35
+ "schema": schema,
34
36
  "timeout_ms": timeout_ms,
35
37
  "idempotent": idempotent
36
38
  }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: attp-client
3
- Version: 0.0.1
3
+ Version: 0.0.2
4
4
  Summary: A python-sdk client for interacting with AgentHub's ATTP protocol (Agent Tool Transport Protocol)
5
5
  License: MIT
6
6
  Author: Ascender Team
@@ -1,4 +1,4 @@
1
- attp_client/catalog.py,sha256=rStW3wveo09hiQOpq7XGlZtqd7dEjc96yowh1VCN78c,1799
1
+ attp_client/catalog.py,sha256=trWLiE_nDXnhlygr4yewti9JLGwanokDdMhHYffMNKs,4296
2
2
  attp_client/client.py,sha256=aSjDaH1pHkmPsVZBwIrSIMX8QXDtbDfGpVBXR5KgnF4,3989
3
3
  attp_client/consts.py,sha256=6UZyqWddycOp-TKW5yvb0JW2fdfcS-J2xFVVNfuJQbU,18
4
4
  attp_client/errors/attp_exception.py,sha256=HePYyYMknS4t6tMrwU-p9L_LPdj1i7chntrlM53ueK4,347
@@ -9,6 +9,7 @@ attp_client/errors/serialization_error.py,sha256=Pa8PRzFJrrikA1Ikj0q-0euvXVUMb_q
9
9
  attp_client/errors/unauthenticated_error.py,sha256=F0V1FjO0qVLMl6Y120y3AXKZnwb5iDD17c4GEMbL5aI,46
10
10
  attp_client/inference.py,sha256=wZ-iF-O8eWDn_YosW234ClnXFa7Gw7I73eD2ugmXvfU,4626
11
11
  attp_client/interfaces/catalogs/catalog.py,sha256=3PxlRwR3y2tbQVfXAkhDIv07AJPraMfH0c_pyi7Y6z8,146
12
+ attp_client/interfaces/catalogs/tools/envelope.py,sha256=6aUx06ou9If9OYv4BODKiBybrgBL2YWfSHZ6ukIR1K0,693
12
13
  attp_client/interfaces/error.py,sha256=fIrk5XlAhMs6mbYQ5PzgwS0v-LIbtne3OlQue4CjWXs,139
13
14
  attp_client/interfaces/handshake/auth.py,sha256=lCbu4Mz50N7-XC5szQKht6xnw-d8pPQMeBviSPfRB2U,337
14
15
  attp_client/interfaces/handshake/hello.py,sha256=hlwWcvSpRebtnbS3lLBYmBm7AfHE4n6dp0ILgfqMUFU,680
@@ -23,11 +24,11 @@ attp_client/misc/fixed_basemodel.py,sha256=0MTVmlTrA75Oxv0pVfLdXFTSp5AmBzgiNwvDi
23
24
  attp_client/misc/serializable.py,sha256=tU08TsjiLiafAhU1jKd5BxajlHdEDcdKeEiKPqhMSTI,2102
24
25
  attp_client/router.py,sha256=UDHU2xsvTjgSIzMtV0jkPvOYK9R7GFjKfIrjjBHws-Q,4575
25
26
  attp_client/session.py,sha256=YDrd1KYmwKsZW6Xdkt6UprXZzGz6pFFSkk6O7XS6ZsA,11409
26
- attp_client/tools.py,sha256=stKrT8cAIIdIpiE8LhH3YPSGa7OsDux-mTeNsT294ng,1765
27
+ attp_client/tools.py,sha256=8GppeVYtnWNqc8M6a-s-S43QYpZROU4aYk67R9388yc,1839
27
28
  attp_client/types/route_mapping.py,sha256=Kb9ZX88lqihRZr8IryfH1Vg_YAobW699Yjl6Raz1rdg,375
28
29
  attp_client/utils/context_awaiter.py,sha256=oCptu5g8mY43j5cr-W4fOe85OCCaqQI9r_Pn92NgZSY,1035
29
30
  attp_client/utils/route_mapper.py,sha256=uJNhKp6ipCSUxoiZS0Liix2lHOgUAnJM0kfgXWAh9RQ,554
30
31
  attp_client/utils/serializer.py,sha256=O1tWYbQS9jC9aus-ISKtliKCgGmOEIb9hxykVrmMKGY,636
31
- attp_client-0.0.1.dist-info/METADATA,sha256=3b74iG5sWjaUpDqeJwjrjJ-8meMF0YOcWGJpEhOiEOI,7137
32
- attp_client-0.0.1.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
33
- attp_client-0.0.1.dist-info/RECORD,,
32
+ attp_client-0.0.2.dist-info/METADATA,sha256=HbejbdD7QR0-oSgJOnW5YfmS5qWwBSrU3UfA2zw_25U,7137
33
+ attp_client-0.0.2.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
34
+ attp_client-0.0.2.dist-info/RECORD,,