acp-sdk 0.12.0__py3-none-any.whl → 0.12.1__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/models/models.py CHANGED
@@ -9,7 +9,7 @@ from pydantic import AnyUrl, BaseModel, ConfigDict, Field
9
9
 
10
10
  from acp_sdk.models.errors import ACPError, Error
11
11
  from acp_sdk.models.platform import PlatformUIAnnotation
12
- from acp_sdk.models.types import AgentName, ResourceId, ResourceUrl, RunId, SessionId
12
+ from acp_sdk.models.types import AgentName, ResourceUrl, RunId, SessionId
13
13
  from acp_sdk.shared import ResourceLoader, ResourceStore
14
14
 
15
15
 
@@ -357,6 +357,6 @@ class Session(BaseModel):
357
357
  if not store:
358
358
  raise ValueError("Store must be specified")
359
359
 
360
- id = ResourceId()
360
+ id = uuid.uuid4()
361
361
  await store.store(id, data)
362
362
  return await store.url(id)
acp_sdk/server/app.py CHANGED
@@ -51,6 +51,7 @@ from acp_sdk.server.errors import (
51
51
  validation_exception_handler,
52
52
  )
53
53
  from acp_sdk.server.executor import CancelData, Executor, RunData
54
+ from acp_sdk.server.resources import ServerResourceLoader
54
55
  from acp_sdk.server.store import MemoryStore, Store
55
56
  from acp_sdk.server.utils import stream_sse, wait_util_stop
56
57
  from acp_sdk.shared import ResourceLoader, ResourceStore
@@ -161,14 +162,30 @@ def create_app(
161
162
  if request.session_id and request.session and request.session_id != request.session.id:
162
163
  raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Session ID mismatch")
163
164
 
165
+ def create_resource_url_forwarded(id: ResourceId) -> ResourceUrl:
166
+ if not forward_resources:
167
+ raise RuntimeError("Resource forwarding disabled")
168
+ return ResourceUrl(url=str(req.url_for("get_resource", resource_id=id)))
169
+
170
+ async def create_resource_url(id: ResourceId) -> ResourceUrl:
171
+ if forward_resources:
172
+ return create_resource_url_forwarded(id)
173
+ else:
174
+ return await resource_store.url(id)
175
+
176
+ server_resource_loader = ServerResourceLoader(
177
+ loader=resource_loader,
178
+ store=resource_store,
179
+ create_resource_url=create_resource_url_forwarded if forward_resources else None,
180
+ )
181
+
164
182
  session = request.session or (
165
- (
166
- await session_store.get(request.session_id)
167
- or Session(id=request.session_id, loader=resource_loader, store=resource_store)
168
- )
183
+ (await session_store.get(request.session_id) or Session(id=request.session_id))
169
184
  if request.session_id
170
- else Session(loader=resource_loader, store=resource_store)
185
+ else Session()
171
186
  )
187
+ session.loader = server_resource_loader
188
+ session.store = resource_store
172
189
 
173
190
  nonlocal executor
174
191
  run_data = RunData(
@@ -183,12 +200,6 @@ def create_app(
183
200
  headers = {Headers.RUN_ID: str(run_data.run.run_id)}
184
201
  ready = asyncio.Event()
185
202
 
186
- async def create_resource_url(id: ResourceId) -> ResourceUrl:
187
- if forward_resources:
188
- return ResourceUrl(url=str(req.url_for("get_resource", resource_id=id)))
189
- else:
190
- return await resource_store.url(id)
191
-
192
203
  Executor(
193
204
  agent=agent,
194
205
  run_data=run_data,
@@ -200,7 +211,7 @@ def create_app(
200
211
  executor=executor,
201
212
  request=req,
202
213
  resource_store=resource_store,
203
- resource_loader=resource_loader,
214
+ resource_loader=server_resource_loader,
204
215
  create_resource_url=create_resource_url,
205
216
  ).execute(request.input, wait=ready)
206
217
 
@@ -0,0 +1,38 @@
1
+ import re
2
+ import uuid
3
+ from typing import Callable
4
+
5
+ import cachetools
6
+
7
+ from acp_sdk.models import ResourceUrl
8
+ from acp_sdk.models.types import ResourceId
9
+ from acp_sdk.shared.resources import ResourceLoader, ResourceStore
10
+
11
+
12
+ class ServerResourceLoader(ResourceLoader):
13
+ def __init__(
14
+ self,
15
+ *,
16
+ loader: ResourceLoader,
17
+ store: ResourceStore,
18
+ create_resource_url: Callable[[ResourceId], ResourceUrl] | None,
19
+ ) -> None:
20
+ self._loader = loader
21
+ self._store = store
22
+
23
+ placeholder_id = uuid.uuid4()
24
+ self._url_pattern = (
25
+ re.escape(str(create_resource_url(placeholder_id))).replace(re.escape(str(placeholder_id)), r"([^/?&#]+)")
26
+ if create_resource_url
27
+ else None
28
+ )
29
+
30
+ @cachetools.func.lfu_cache
31
+ async def load(self, url: ResourceUrl) -> bytes:
32
+ if self._url_pattern:
33
+ match = re.match(self._url_pattern, str(url))
34
+ if match:
35
+ id = ResourceId(match.group(1))
36
+ result = await self._store.load(id)
37
+ return (await result.bytes_async()).to_bytes()
38
+ return await self._loader.load(url)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: acp-sdk
3
- Version: 0.12.0
3
+ Version: 0.12.1
4
4
  Summary: Agent Communication Protocol SDK
5
5
  Author: IBM Corp.
6
6
  Maintainer-email: Tomas Pilar <thomas7pilar@gmail.com>
@@ -8,17 +8,18 @@ acp_sdk/client/types.py,sha256=_H6zYt-2OHOOYRtssRnbDIiwmgsl2-KIXc9lb-mJLFA,133
8
8
  acp_sdk/client/utils.py,sha256=2jhJyrPJmVFRoDJh0q_JMqOMlC3IxCh-6HXed-PIZS8,924
9
9
  acp_sdk/models/__init__.py,sha256=_XDSvUwlHeRsqUayAxHusJ5s8Z1jWXV1ZcUKlJakOt4,200
10
10
  acp_sdk/models/errors.py,sha256=rEyaMVvQuBi7fwWe_d0PGGySYsD3FZTluQ-SkC0yhAs,444
11
- acp_sdk/models/models.py,sha256=OBpCsRq7vSkPN67MrT40LvfzitwjXK_darSFdj1G_zE,10821
11
+ acp_sdk/models/models.py,sha256=-ORIe32MOWVVh22njH596lKeQQQCRsXzKLvOk1dQJB8,10809
12
12
  acp_sdk/models/platform.py,sha256=qgQhBZZNPG9XLlytEZmuv1LTkejbklmlj7YpnpUV_DE,497
13
13
  acp_sdk/models/schemas.py,sha256=Vu3aO-6M0IW71I9thxAiphLGXXMvyZXFMJCdj7euUmc,915
14
14
  acp_sdk/models/types.py,sha256=tH79qqpW3DrPJggZD1KFlLtGE_ZKT6eLtwiR3p3x2QM,145
15
15
  acp_sdk/server/__init__.py,sha256=TfTOOI7G2nejjOB6RZB5ujynyh3bFeH51pfDIMzv3N4,627
16
16
  acp_sdk/server/agent.py,sha256=tzdk9bXb4aKBKD3F1-QfI7zrjMZYEg6qm3gGRWJGC1E,3739
17
- acp_sdk/server/app.py,sha256=KKjZcVxJxQvxAEP_cQna4f9ed1O5mN9Ldo1X_tXfFfI,11107
17
+ acp_sdk/server/app.py,sha256=dugceYPELl6N1_OQQ6JP5VCfVSm0rcanFtjDpscOy6o,11586
18
18
  acp_sdk/server/context.py,sha256=Xz1am_HLNTgEvG0IPtS0tRJcPk-rEhLtNyTQGUAvLQw,1271
19
19
  acp_sdk/server/errors.py,sha256=GSO8yYIqEeX8Y4Lz86ks35dMTHiQiXuOrLYYx0eXsbI,2110
20
20
  acp_sdk/server/executor.py,sha256=ktM1FCwixtbjsU60VM7PHxwF_Saz15M_9fNXN4mItrU,12607
21
21
  acp_sdk/server/logging.py,sha256=Oc8yZigCsuDnHHPsarRzu0RX3NKaLEgpELM2yovGKDI,411
22
+ acp_sdk/server/resources.py,sha256=g9C2Xr_SyvAFsV1uHQLEe1H7CgLIjfQZ51Nj3n-w0f4,1174
22
23
  acp_sdk/server/server.py,sha256=HJOub1ynHiJTQrfKq_bq0r9aqgL1kQeboZH_ArZcuh0,14651
23
24
  acp_sdk/server/telemetry.py,sha256=lbB2ppijUcqbHUOn0e-15LGcVvT_qrMguq8qBokICac,2016
24
25
  acp_sdk/server/types.py,sha256=gLb5wCkMYhmu2laj_ymK-TPfN9LSjRgKOP1H_893UzA,304
@@ -31,6 +32,6 @@ acp_sdk/server/store/store.py,sha256=jGmYy9oiuVjhYYJY8QRo4g2J2Qyt1HLTmq_eHy4aI7c
31
32
  acp_sdk/server/store/utils.py,sha256=JumEOMs1h1uGlnHnUGeguee-srGzT7_Y2NVEYt01QuY,92
32
33
  acp_sdk/shared/__init__.py,sha256=vZuhdQ6lrWVdyYPmIyXpPvs5eMnzemhNek3gfYPA3Bc,138
33
34
  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,,
35
+ acp_sdk-0.12.1.dist-info/METADATA,sha256=MRAqSfZU7kiGP1mmHqXMcPVxfDVhsQBUbPJVOhaIxYw,1713
36
+ acp_sdk-0.12.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
37
+ acp_sdk-0.12.1.dist-info/RECORD,,