acp-sdk 0.10.1__py3-none-any.whl → 0.12.0__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.
acp_sdk/server/server.py CHANGED
@@ -11,7 +11,7 @@ import uvicorn.config
11
11
  from fastapi import FastAPI
12
12
 
13
13
  from acp_sdk.models import Metadata
14
- from acp_sdk.server.agent import Agent
14
+ from acp_sdk.server.agent import AgentManifest
15
15
  from acp_sdk.server.agent import agent as agent_decorator
16
16
  from acp_sdk.server.app import create_app
17
17
  from acp_sdk.server.logging import configure_logger as configure_logger_func
@@ -19,11 +19,12 @@ from acp_sdk.server.logging import logger
19
19
  from acp_sdk.server.store import Store
20
20
  from acp_sdk.server.telemetry import configure_telemetry as configure_telemetry_func
21
21
  from acp_sdk.server.utils import async_request_with_retry
22
+ from acp_sdk.shared.resources import ResourceLoader, ResourceStore
22
23
 
23
24
 
24
25
  class Server:
25
26
  def __init__(self) -> None:
26
- self.agents: list[Agent] = []
27
+ self.agents: list[AgentManifest] = []
27
28
  self.server: uvicorn.Server | None = None
28
29
 
29
30
  def agent(
@@ -42,7 +43,7 @@ class Server:
42
43
 
43
44
  return decorator
44
45
 
45
- def register(self, *agents: Agent) -> None:
46
+ def register(self, *agents: AgentManifest) -> None:
46
47
  self.agents.extend(agents)
47
48
 
48
49
  @asynccontextmanager
@@ -56,6 +57,8 @@ class Server:
56
57
  configure_telemetry: bool = False,
57
58
  self_registration: bool = True,
58
59
  store: Store | None = None,
60
+ resource_store: ResourceStore | None = None,
61
+ resource_loader: ResourceLoader | None = None,
59
62
  host: str = "127.0.0.1",
60
63
  port: int = 8000,
61
64
  uds: str | None = None,
@@ -118,7 +121,13 @@ class Server:
118
121
 
119
122
  import uvicorn
120
123
 
121
- app = create_app(*self.agents, lifespan=self.lifespan, store=store)
124
+ app = create_app(
125
+ *self.agents,
126
+ lifespan=self.lifespan,
127
+ store=store,
128
+ resource_loader=resource_loader,
129
+ resource_store=resource_store,
130
+ )
122
131
 
123
132
  if configure_logger:
124
133
  configure_logger_func()
@@ -185,6 +194,8 @@ class Server:
185
194
  configure_telemetry: bool = False,
186
195
  self_registration: bool = True,
187
196
  store: Store | None = None,
197
+ resource_store: ResourceStore | None = None,
198
+ resource_loader: ResourceLoader | None = None,
188
199
  host: str = "127.0.0.1",
189
200
  port: int = 8000,
190
201
  uds: str | None = None,
@@ -243,6 +254,8 @@ class Server:
243
254
  configure_telemetry=configure_telemetry,
244
255
  self_registration=self_registration,
245
256
  store=store,
257
+ resource_store=resource_store,
258
+ resource_loader=resource_loader,
246
259
  host=host,
247
260
  port=port,
248
261
  uds=uds,
@@ -5,25 +5,25 @@ from typing import Generic
5
5
 
6
6
  from cachetools import TTLCache
7
7
 
8
- from acp_sdk.server.store.store import Store, T
8
+ from acp_sdk.server.store.store import Store, StoreModel, T
9
9
  from acp_sdk.server.store.utils import Stringable
10
10
 
11
11
 
12
12
  class MemoryStore(Store[T], Generic[T]):
13
13
  def __init__(self, *, limit: int, ttl: int | None = None) -> None:
14
14
  super().__init__()
15
- self._cache: TTLCache[str, T] = TTLCache(maxsize=limit, ttl=ttl, timer=datetime.now)
15
+ self._cache: TTLCache[str, str] = TTLCache(maxsize=limit, ttl=ttl, timer=datetime.now)
16
16
  self._event = asyncio.Event()
17
17
 
18
18
  async def get(self, key: Stringable) -> T | None:
19
19
  value = self._cache.get(str(key))
20
- return value.model_copy(deep=True) if value else value
20
+ return StoreModel.model_validate_json(value) if value else value
21
21
 
22
22
  async def set(self, key: Stringable, value: T | None) -> None:
23
23
  if value is None:
24
24
  del self._cache[str(key)]
25
25
  else:
26
- self._cache[str(key)] = value.model_copy(deep=True)
26
+ self._cache[str(key)] = value.model_dump_json()
27
27
  self._event.set()
28
28
 
29
29
  async def watch(self, key: Stringable, *, ready: asyncio.Event | None = None) -> AsyncIterator[T | None]:
acp_sdk/server/utils.py CHANGED
@@ -9,7 +9,7 @@ from pydantic import BaseModel
9
9
  from acp_sdk.models import RunStatus
10
10
  from acp_sdk.server.executor import RunData
11
11
  from acp_sdk.server.logging import logger
12
- from acp_sdk.server.store.store import Store
12
+ from acp_sdk.server.store import Store
13
13
 
14
14
 
15
15
  def encode_sse(model: BaseModel) -> str:
@@ -0,0 +1,2 @@
1
+ from acp_sdk.shared.resources import ResourceLoader as ResourceLoader
2
+ from acp_sdk.shared.resources import ResourceStore as ResourceStore
@@ -0,0 +1,46 @@
1
+ from datetime import timedelta
2
+
3
+ import cachetools
4
+ import cachetools.func
5
+ import httpx
6
+ import obstore
7
+ from obstore.store import AzureStore, GCSStore, HTTPStore, ObjectStore, S3Store
8
+
9
+ from acp_sdk.models.types import ResourceId, ResourceUrl
10
+
11
+
12
+ class ResourceLoader:
13
+ def __init__(self, *, client: httpx.AsyncClient | None = None) -> None:
14
+ self._client = client or httpx.AsyncClient(follow_redirects=False)
15
+
16
+ @cachetools.func.lfu_cache
17
+ async def load(self, url: ResourceUrl) -> bytes:
18
+ response = await self._client.get(str(url))
19
+ response.raise_for_status()
20
+ return await response.aread()
21
+
22
+
23
+ class ResourceStore:
24
+ def __init__(self, *, store: ObjectStore, presigned_url_expiration: timedelta = timedelta(days=7)) -> None:
25
+ self._store = store
26
+ self._presigned_url_expiration = presigned_url_expiration
27
+
28
+ async def load(self, id: ResourceId): # noqa: ANN201
29
+ result = await self._store.get_async(str(id))
30
+ return result
31
+
32
+ async def store(
33
+ self,
34
+ id: ResourceId,
35
+ data: bytes,
36
+ ) -> None:
37
+ await self._store.put_async(str(id), data)
38
+
39
+ async def url(self, id: ResourceId) -> ResourceUrl:
40
+ if isinstance(self._store, (AzureStore, GCSStore, S3Store)):
41
+ url = await obstore.sign_async(self._store, "GET", str(id), self._presigned_url_expiration)
42
+ return ResourceUrl(url=url)
43
+ elif isinstance(self._store, HTTPStore):
44
+ return ResourceUrl(url=f"{self._store.url}/{id!s}")
45
+ else:
46
+ raise NotImplementedError("Unsupported store")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: acp-sdk
3
- Version: 0.10.1
3
+ Version: 0.12.0
4
4
  Summary: Agent Communication Protocol SDK
5
5
  Author: IBM Corp.
6
6
  Maintainer-email: Tomas Pilar <thomas7pilar@gmail.com>
@@ -11,6 +11,7 @@ Requires-Dist: fastapi[standard]>=0.115
11
11
  Requires-Dist: httpx-sse>=0.4
12
12
  Requires-Dist: httpx>=0.26
13
13
  Requires-Dist: janus>=2.0
14
+ Requires-Dist: obstore>=0.6
14
15
  Requires-Dist: opentelemetry-api>=1.31
15
16
  Requires-Dist: opentelemetry-exporter-otlp-proto-http>=1.31
16
17
  Requires-Dist: opentelemetry-instrumentation-fastapi>=0.52b1
@@ -0,0 +1,36 @@
1
+ acp_sdk/__init__.py,sha256=tXdAUM9zcmdSKCAkVrOCrGcXcuVS-yuvQUoQwTe9pek,98
2
+ acp_sdk/instrumentation.py,sha256=JqSyvILN3sGAfOZrmckQq4-M_4_5alyPn95DK0o5lfA,161
3
+ acp_sdk/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
+ acp_sdk/version.py,sha256=Niy83rgvigB4hL_rR-O4ySvI7dj6xnqkyOe_JTymi9s,73
5
+ acp_sdk/client/__init__.py,sha256=Bca1DORrswxzZsrR2aUFpATuNG2xNSmYvF1Z2WJaVbc,51
6
+ acp_sdk/client/client.py,sha256=p6e5zmH9-hdx0t0zoQOCSkgSUgmH-YCTD5_1idcwTEQ,12763
7
+ acp_sdk/client/types.py,sha256=_H6zYt-2OHOOYRtssRnbDIiwmgsl2-KIXc9lb-mJLFA,133
8
+ acp_sdk/client/utils.py,sha256=2jhJyrPJmVFRoDJh0q_JMqOMlC3IxCh-6HXed-PIZS8,924
9
+ acp_sdk/models/__init__.py,sha256=_XDSvUwlHeRsqUayAxHusJ5s8Z1jWXV1ZcUKlJakOt4,200
10
+ acp_sdk/models/errors.py,sha256=rEyaMVvQuBi7fwWe_d0PGGySYsD3FZTluQ-SkC0yhAs,444
11
+ acp_sdk/models/models.py,sha256=OBpCsRq7vSkPN67MrT40LvfzitwjXK_darSFdj1G_zE,10821
12
+ acp_sdk/models/platform.py,sha256=qgQhBZZNPG9XLlytEZmuv1LTkejbklmlj7YpnpUV_DE,497
13
+ acp_sdk/models/schemas.py,sha256=Vu3aO-6M0IW71I9thxAiphLGXXMvyZXFMJCdj7euUmc,915
14
+ acp_sdk/models/types.py,sha256=tH79qqpW3DrPJggZD1KFlLtGE_ZKT6eLtwiR3p3x2QM,145
15
+ acp_sdk/server/__init__.py,sha256=TfTOOI7G2nejjOB6RZB5ujynyh3bFeH51pfDIMzv3N4,627
16
+ acp_sdk/server/agent.py,sha256=tzdk9bXb4aKBKD3F1-QfI7zrjMZYEg6qm3gGRWJGC1E,3739
17
+ acp_sdk/server/app.py,sha256=KKjZcVxJxQvxAEP_cQna4f9ed1O5mN9Ldo1X_tXfFfI,11107
18
+ acp_sdk/server/context.py,sha256=Xz1am_HLNTgEvG0IPtS0tRJcPk-rEhLtNyTQGUAvLQw,1271
19
+ acp_sdk/server/errors.py,sha256=GSO8yYIqEeX8Y4Lz86ks35dMTHiQiXuOrLYYx0eXsbI,2110
20
+ acp_sdk/server/executor.py,sha256=ktM1FCwixtbjsU60VM7PHxwF_Saz15M_9fNXN4mItrU,12607
21
+ acp_sdk/server/logging.py,sha256=Oc8yZigCsuDnHHPsarRzu0RX3NKaLEgpELM2yovGKDI,411
22
+ acp_sdk/server/server.py,sha256=HJOub1ynHiJTQrfKq_bq0r9aqgL1kQeboZH_ArZcuh0,14651
23
+ acp_sdk/server/telemetry.py,sha256=lbB2ppijUcqbHUOn0e-15LGcVvT_qrMguq8qBokICac,2016
24
+ acp_sdk/server/types.py,sha256=gLb5wCkMYhmu2laj_ymK-TPfN9LSjRgKOP1H_893UzA,304
25
+ acp_sdk/server/utils.py,sha256=O9GUZ8SKqk8P5Vo-N4BD7hXS3XuE7l8wifOhvKMX3ws,2715
26
+ acp_sdk/server/store/__init__.py,sha256=zzKic0byQTM86cyC2whwZeNP4prfy_HZrbSriTaV5j8,282
27
+ acp_sdk/server/store/memory_store.py,sha256=ykGskORGJUhQNMxTmXuNB8tX8xCgukr5502PSZr14nk,1214
28
+ acp_sdk/server/store/postgresql_store.py,sha256=bHyAgf4vSn_07wGXXq6juFwm3JldYNOjU9RARcDSYQo,2717
29
+ acp_sdk/server/store/redis_store.py,sha256=IKXvDseOFMcoGjVYPOkOBhPnJAchy_RyeMayKLoVCGA,1378
30
+ acp_sdk/server/store/store.py,sha256=jGmYy9oiuVjhYYJY8QRo4g2J2Qyt1HLTmq_eHy4aI7c,1806
31
+ acp_sdk/server/store/utils.py,sha256=JumEOMs1h1uGlnHnUGeguee-srGzT7_Y2NVEYt01QuY,92
32
+ acp_sdk/shared/__init__.py,sha256=vZuhdQ6lrWVdyYPmIyXpPvs5eMnzemhNek3gfYPA3Bc,138
33
+ acp_sdk/shared/resources.py,sha256=3oPvevYv2B1YaHyoMH85B7fcHVyhgZDUaDCBVEflTlA,1592
34
+ acp_sdk-0.12.0.dist-info/METADATA,sha256=AFY7mxImu6UwA0LZlc0ItpdmhLzw8Tw59AJXBjeWq2Q,1713
35
+ acp_sdk-0.12.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
36
+ acp_sdk-0.12.0.dist-info/RECORD,,
acp_sdk/server/session.py DELETED
@@ -1,24 +0,0 @@
1
- import uuid
2
-
3
- from pydantic import BaseModel, Field
4
-
5
- from acp_sdk.models import Message, RunId, RunStatus, SessionId
6
- from acp_sdk.server.executor import RunData
7
- from acp_sdk.server.store import Store
8
-
9
-
10
- class Session(BaseModel):
11
- id: SessionId = Field(default_factory=uuid.uuid4)
12
- runs: list[RunId] = []
13
-
14
- def append(self, run_id: RunId) -> None:
15
- self.runs.append(run_id)
16
-
17
- async def history(self, store: Store[RunData]) -> list[Message]:
18
- history = []
19
- for run_id in self.runs:
20
- run_data = await store.get(run_id)
21
- if run_data is not None and run_data.run.status == RunStatus.COMPLETED:
22
- history.extend(run_data.input)
23
- history.extend(run_data.run.output)
24
- return history
@@ -1,33 +0,0 @@
1
- acp_sdk/__init__.py,sha256=tXdAUM9zcmdSKCAkVrOCrGcXcuVS-yuvQUoQwTe9pek,98
2
- acp_sdk/instrumentation.py,sha256=JqSyvILN3sGAfOZrmckQq4-M_4_5alyPn95DK0o5lfA,161
3
- acp_sdk/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
- acp_sdk/version.py,sha256=Niy83rgvigB4hL_rR-O4ySvI7dj6xnqkyOe_JTymi9s,73
5
- acp_sdk/client/__init__.py,sha256=Bca1DORrswxzZsrR2aUFpATuNG2xNSmYvF1Z2WJaVbc,51
6
- acp_sdk/client/client.py,sha256=7GVD7eVlaSU78O3puMlyoOTqKjTwZYaBKLHyYvbvr3I,8504
7
- acp_sdk/client/types.py,sha256=_H6zYt-2OHOOYRtssRnbDIiwmgsl2-KIXc9lb-mJLFA,133
8
- acp_sdk/client/utils.py,sha256=2jhJyrPJmVFRoDJh0q_JMqOMlC3IxCh-6HXed-PIZS8,924
9
- acp_sdk/models/__init__.py,sha256=numSDBDT1QHx7n_Y3Deb5VOvKWcUBxbOEaMwQBSRHxc,151
10
- acp_sdk/models/errors.py,sha256=rEyaMVvQuBi7fwWe_d0PGGySYsD3FZTluQ-SkC0yhAs,444
11
- acp_sdk/models/models.py,sha256=So5D9VjJxX2jdOF8BGc3f9D2ssbAyFEO2Rgr1KykI-M,7730
12
- acp_sdk/models/schemas.py,sha256=_ah7_zHsQJGxDXvnzsBvASdRsQHVphFQ7Sum6A04iRw,759
13
- acp_sdk/server/__init__.py,sha256=mxBBBFaZuMEUENRMLwp1XZkuLeT9QghcFmNvjnqvAAU,377
14
- acp_sdk/server/agent.py,sha256=6VBKn_qVXqUl79G8T7grwhnuLMwr67d4UGagMGX1hMs,6586
15
- acp_sdk/server/app.py,sha256=XeMn8hfU2J2O2QxSvsH5q6lowxCfwS1-DTWz-gUVotA,8733
16
- acp_sdk/server/context.py,sha256=MgnLV6qcDIhc_0BjW7r4Jj1tHts4ZuwpdTGIBnz2Mgo,1036
17
- acp_sdk/server/errors.py,sha256=GSO8yYIqEeX8Y4Lz86ks35dMTHiQiXuOrLYYx0eXsbI,2110
18
- acp_sdk/server/executor.py,sha256=YL0J9cVY1QZtdTeqwjJaKDpB_T6_sByHlHc52kgNAJo,7742
19
- acp_sdk/server/logging.py,sha256=Oc8yZigCsuDnHHPsarRzu0RX3NKaLEgpELM2yovGKDI,411
20
- acp_sdk/server/server.py,sha256=slePybTpocXD8k9HxOvxCiyvigiDUdZmkz3kiI-dCFU,14113
21
- acp_sdk/server/session.py,sha256=vGUVpKzUGefI1c7LeK08Bvd8zvJIRfsdJEt2KhYoEg0,764
22
- acp_sdk/server/telemetry.py,sha256=lbB2ppijUcqbHUOn0e-15LGcVvT_qrMguq8qBokICac,2016
23
- acp_sdk/server/types.py,sha256=gLb5wCkMYhmu2laj_ymK-TPfN9LSjRgKOP1H_893UzA,304
24
- acp_sdk/server/utils.py,sha256=BYSn4Bd95Bn-oEH1W1yE_pWpYUOdtYPh-vMnou4nsdk,2721
25
- acp_sdk/server/store/__init__.py,sha256=zzKic0byQTM86cyC2whwZeNP4prfy_HZrbSriTaV5j8,282
26
- acp_sdk/server/store/memory_store.py,sha256=9hOoJiHdaDz-0hNHWhO_qZpp-I_pnTqYBIhQnlWilu4,1194
27
- acp_sdk/server/store/postgresql_store.py,sha256=bHyAgf4vSn_07wGXXq6juFwm3JldYNOjU9RARcDSYQo,2717
28
- acp_sdk/server/store/redis_store.py,sha256=IKXvDseOFMcoGjVYPOkOBhPnJAchy_RyeMayKLoVCGA,1378
29
- acp_sdk/server/store/store.py,sha256=jGmYy9oiuVjhYYJY8QRo4g2J2Qyt1HLTmq_eHy4aI7c,1806
30
- acp_sdk/server/store/utils.py,sha256=JumEOMs1h1uGlnHnUGeguee-srGzT7_Y2NVEYt01QuY,92
31
- acp_sdk-0.10.1.dist-info/METADATA,sha256=2CkcWAS4e-6bIeoFsv2eyxLcbeTSgy15gq3VCP1dxbE,1685
32
- acp_sdk-0.10.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
33
- acp_sdk-0.10.1.dist-info/RECORD,,