ship grants, a2a_client, discovery, sandbox SDK + tests
This commit is contained in:
@@ -199,6 +199,42 @@ class WorkspaceClient(ABC):
|
||||
@abstractmethod
|
||||
async def list_grants(self) -> list[WorkspaceGrant]: ...
|
||||
|
||||
async def delegate(
|
||||
self,
|
||||
*,
|
||||
audience: str,
|
||||
allow_patterns: Sequence[str] = ("**",),
|
||||
deny_patterns: Sequence[str] = (),
|
||||
mode: WorkspaceMode = WorkspaceMode.READ_ONLY,
|
||||
outputs_prefix: str | None = None,
|
||||
ttl_seconds: int = 300,
|
||||
) -> str:
|
||||
"""Mint a signed grant token the caller can hand to ``ctx.call``.
|
||||
|
||||
The default implementation requires the workspace to expose
|
||||
``self.bucket`` and ``self.issuer`` — override in concrete clients
|
||||
that don't fit that shape.
|
||||
"""
|
||||
from .grants import mint_grant
|
||||
|
||||
bucket = getattr(self, "bucket", None) or getattr(self, "_bucket", None)
|
||||
if bucket is None:
|
||||
raise NotImplementedError(
|
||||
"this WorkspaceClient does not expose a bucket; override delegate()"
|
||||
)
|
||||
issuer = getattr(self, "issuer", "self")
|
||||
_, token = mint_grant(
|
||||
issuer=issuer,
|
||||
audience=audience,
|
||||
bucket=bucket,
|
||||
mode=mode,
|
||||
allow_patterns=tuple(allow_patterns),
|
||||
deny_patterns=tuple(deny_patterns),
|
||||
outputs_prefix=outputs_prefix,
|
||||
ttl_seconds=ttl_seconds,
|
||||
)
|
||||
return token
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Local in-memory implementation, for dev/tests.
|
||||
@@ -288,11 +324,16 @@ class LocalWorkspaceClient(WorkspaceClient):
|
||||
files: dict[str, bytes],
|
||||
*,
|
||||
access: WorkspaceAccess,
|
||||
bucket: str = "local",
|
||||
issuer: str = "local",
|
||||
) -> None:
|
||||
self._files: dict[str, bytes] = dict(files)
|
||||
self._access = access
|
||||
self._grants: dict[str, WorkspaceGrant] = {}
|
||||
self._counter = 0
|
||||
# Expose bucket+issuer so the default WorkspaceClient.delegate() works.
|
||||
self.bucket = bucket
|
||||
self.issuer = issuer
|
||||
|
||||
def _detect(self, path: str) -> FileType:
|
||||
for ext, ft in self._EXT_TO_TYPE.items():
|
||||
|
||||
Reference in New Issue
Block a user