acp-sdk 0.12.0__tar.gz → 0.12.1__tar.gz

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.
Files changed (61) hide show
  1. {acp_sdk-0.12.0 → acp_sdk-0.12.1}/PKG-INFO +1 -1
  2. {acp_sdk-0.12.0 → acp_sdk-0.12.1}/pyproject.toml +1 -1
  3. {acp_sdk-0.12.0 → acp_sdk-0.12.1}/src/acp_sdk/models/models.py +2 -2
  4. {acp_sdk-0.12.0 → acp_sdk-0.12.1}/src/acp_sdk/server/app.py +23 -12
  5. acp_sdk-0.12.1/src/acp_sdk/server/resources.py +38 -0
  6. {acp_sdk-0.12.0 → acp_sdk-0.12.1}/.gitignore +0 -0
  7. {acp_sdk-0.12.0 → acp_sdk-0.12.1}/.python-version +0 -0
  8. {acp_sdk-0.12.0 → acp_sdk-0.12.1}/README.md +0 -0
  9. {acp_sdk-0.12.0 → acp_sdk-0.12.1}/docs/.gitignore +0 -0
  10. {acp_sdk-0.12.0 → acp_sdk-0.12.1}/docs/Makefile +0 -0
  11. {acp_sdk-0.12.0 → acp_sdk-0.12.1}/docs/conf.py +0 -0
  12. {acp_sdk-0.12.0 → acp_sdk-0.12.1}/docs/index.rst +0 -0
  13. {acp_sdk-0.12.0 → acp_sdk-0.12.1}/docs/make.bat +0 -0
  14. {acp_sdk-0.12.0 → acp_sdk-0.12.1}/pytest.ini +0 -0
  15. {acp_sdk-0.12.0 → acp_sdk-0.12.1}/src/acp_sdk/__init__.py +0 -0
  16. {acp_sdk-0.12.0 → acp_sdk-0.12.1}/src/acp_sdk/client/__init__.py +0 -0
  17. {acp_sdk-0.12.0 → acp_sdk-0.12.1}/src/acp_sdk/client/client.py +0 -0
  18. {acp_sdk-0.12.0 → acp_sdk-0.12.1}/src/acp_sdk/client/types.py +0 -0
  19. {acp_sdk-0.12.0 → acp_sdk-0.12.1}/src/acp_sdk/client/utils.py +0 -0
  20. {acp_sdk-0.12.0 → acp_sdk-0.12.1}/src/acp_sdk/instrumentation.py +0 -0
  21. {acp_sdk-0.12.0 → acp_sdk-0.12.1}/src/acp_sdk/models/__init__.py +0 -0
  22. {acp_sdk-0.12.0 → acp_sdk-0.12.1}/src/acp_sdk/models/errors.py +0 -0
  23. {acp_sdk-0.12.0 → acp_sdk-0.12.1}/src/acp_sdk/models/platform.py +0 -0
  24. {acp_sdk-0.12.0 → acp_sdk-0.12.1}/src/acp_sdk/models/schemas.py +0 -0
  25. {acp_sdk-0.12.0 → acp_sdk-0.12.1}/src/acp_sdk/models/types.py +0 -0
  26. {acp_sdk-0.12.0 → acp_sdk-0.12.1}/src/acp_sdk/py.typed +0 -0
  27. {acp_sdk-0.12.0 → acp_sdk-0.12.1}/src/acp_sdk/server/__init__.py +0 -0
  28. {acp_sdk-0.12.0 → acp_sdk-0.12.1}/src/acp_sdk/server/agent.py +0 -0
  29. {acp_sdk-0.12.0 → acp_sdk-0.12.1}/src/acp_sdk/server/context.py +0 -0
  30. {acp_sdk-0.12.0 → acp_sdk-0.12.1}/src/acp_sdk/server/errors.py +0 -0
  31. {acp_sdk-0.12.0 → acp_sdk-0.12.1}/src/acp_sdk/server/executor.py +0 -0
  32. {acp_sdk-0.12.0 → acp_sdk-0.12.1}/src/acp_sdk/server/logging.py +0 -0
  33. {acp_sdk-0.12.0 → acp_sdk-0.12.1}/src/acp_sdk/server/server.py +0 -0
  34. {acp_sdk-0.12.0 → acp_sdk-0.12.1}/src/acp_sdk/server/store/__init__.py +0 -0
  35. {acp_sdk-0.12.0 → acp_sdk-0.12.1}/src/acp_sdk/server/store/memory_store.py +0 -0
  36. {acp_sdk-0.12.0 → acp_sdk-0.12.1}/src/acp_sdk/server/store/postgresql_store.py +0 -0
  37. {acp_sdk-0.12.0 → acp_sdk-0.12.1}/src/acp_sdk/server/store/redis_store.py +0 -0
  38. {acp_sdk-0.12.0 → acp_sdk-0.12.1}/src/acp_sdk/server/store/store.py +0 -0
  39. {acp_sdk-0.12.0 → acp_sdk-0.12.1}/src/acp_sdk/server/store/utils.py +0 -0
  40. {acp_sdk-0.12.0 → acp_sdk-0.12.1}/src/acp_sdk/server/telemetry.py +0 -0
  41. {acp_sdk-0.12.0 → acp_sdk-0.12.1}/src/acp_sdk/server/types.py +0 -0
  42. {acp_sdk-0.12.0 → acp_sdk-0.12.1}/src/acp_sdk/server/utils.py +0 -0
  43. {acp_sdk-0.12.0 → acp_sdk-0.12.1}/src/acp_sdk/shared/__init__.py +0 -0
  44. {acp_sdk-0.12.0 → acp_sdk-0.12.1}/src/acp_sdk/shared/resources.py +0 -0
  45. {acp_sdk-0.12.0 → acp_sdk-0.12.1}/src/acp_sdk/version.py +0 -0
  46. {acp_sdk-0.12.0 → acp_sdk-0.12.1}/tests/conftest.py +0 -0
  47. {acp_sdk-0.12.0 → acp_sdk-0.12.1}/tests/e2e/__init__.py +0 -0
  48. {acp_sdk-0.12.0 → acp_sdk-0.12.1}/tests/e2e/config.py +0 -0
  49. {acp_sdk-0.12.0 → acp_sdk-0.12.1}/tests/e2e/fixtures/__init__.py +0 -0
  50. {acp_sdk-0.12.0 → acp_sdk-0.12.1}/tests/e2e/fixtures/client.py +0 -0
  51. {acp_sdk-0.12.0 → acp_sdk-0.12.1}/tests/e2e/fixtures/server.py +0 -0
  52. {acp_sdk-0.12.0 → acp_sdk-0.12.1}/tests/e2e/test_suites/__init__.py +0 -0
  53. {acp_sdk-0.12.0 → acp_sdk-0.12.1}/tests/e2e/test_suites/test_discovery.py +0 -0
  54. {acp_sdk-0.12.0 → acp_sdk-0.12.1}/tests/e2e/test_suites/test_runs.py +0 -0
  55. {acp_sdk-0.12.0 → acp_sdk-0.12.1}/tests/e2e/test_suites/test_sessions.py +0 -0
  56. {acp_sdk-0.12.0 → acp_sdk-0.12.1}/tests/unit/client/test_client.py +0 -0
  57. {acp_sdk-0.12.0 → acp_sdk-0.12.1}/tests/unit/client/test_utils.py +0 -0
  58. {acp_sdk-0.12.0 → acp_sdk-0.12.1}/tests/unit/models/__init__.py +0 -0
  59. {acp_sdk-0.12.0 → acp_sdk-0.12.1}/tests/unit/models/test_models.py +0 -0
  60. {acp_sdk-0.12.0 → acp_sdk-0.12.1}/tests/unit/server/__init__.py +0 -0
  61. {acp_sdk-0.12.0 → acp_sdk-0.12.1}/tests/unit/server/test_server.py +0 -0
@@ -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>
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "acp-sdk"
3
- version = "0.12.0"
3
+ version = "0.12.1"
4
4
  description = "Agent Communication Protocol SDK"
5
5
  license = "Apache-2.0"
6
6
  readme = "README.md"
@@ -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)
@@ -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)
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes