Spaces:
Running
Running
| """ | |
| RemoteTool. | |
| Wrapper around a connector that calls a remote tool. | |
| """ | |
| from typing import Optional | |
| from openspace.utils.logging import Logger | |
| from ..types import BackendType, ToolResult, ToolSchema, ToolStatus | |
| from .base import BaseTool | |
| from openspace.grounding.core.transport.connectors import BaseConnector | |
| logger = Logger.get_logger(__name__) | |
| class RemoteTool(BaseTool): | |
| backend_type = BackendType.NOT_SET | |
| def __init__( | |
| self, | |
| schema: ToolSchema | None = None, | |
| connector: Optional[BaseConnector] = None, | |
| remote_name: str = "", | |
| *, | |
| verbose: bool = False, | |
| backend: BackendType = BackendType.NOT_SET, | |
| ): | |
| self._conn = connector | |
| self._remote_name = remote_name or (schema.name if schema else "") | |
| self.backend_type = backend | |
| super().__init__(schema=schema, verbose=verbose) | |
| async def _arun(self, **kwargs): | |
| # If no connector, tool must be invoked via grounding_client (on-demand startup) | |
| if self._conn is None: | |
| raise RuntimeError( | |
| f"Tool '{self.name}' has no connector. " | |
| "Use grounding_client.invoke_tool() to execute it with on-demand server startup." | |
| ) | |
| raw = await self._conn.invoke(self._remote_name, kwargs) | |
| if hasattr(raw, 'content') and hasattr(raw, 'isError'): | |
| content_parts = [] | |
| for item in (raw.content or []): | |
| # Extract text from TextContent | |
| if hasattr(item, 'text') and item.text: | |
| content_parts.append(item.text) | |
| # Handle ImageContent (just note its presence) | |
| elif hasattr(item, 'data'): | |
| content_parts.append(f"[Image data: {len(item.data) if item.data else 0} bytes]") | |
| # Handle EmbeddedResource | |
| elif hasattr(item, 'resource'): | |
| content_parts.append(f"[Embedded resource: {getattr(item.resource, 'uri', 'unknown')}]") | |
| content = "\n".join(content_parts) if content_parts else "" | |
| is_error = getattr(raw, 'isError', False) | |
| return ToolResult( | |
| status=ToolStatus.ERROR if is_error else ToolStatus.SUCCESS, | |
| content=content, | |
| error=content if is_error else None, | |
| ) | |
| # Handle dict response | |
| if isinstance(raw, dict): | |
| import json | |
| try: | |
| content = json.dumps(raw, ensure_ascii=False, indent=2) | |
| except (TypeError, ValueError): | |
| content = str(raw) | |
| # Handle list/tuple response | |
| elif isinstance(raw, (list, tuple)): | |
| import json | |
| try: | |
| content = json.dumps(raw, ensure_ascii=False, indent=2) | |
| except (TypeError, ValueError): | |
| content = str(raw) | |
| # Handle primitive types | |
| elif isinstance(raw, (int, float, bool)): | |
| content = str(raw) | |
| elif isinstance(raw, str): | |
| content = raw | |
| # Fallback for unknown types | |
| else: | |
| content = str(raw) | |
| return ToolResult( | |
| status=ToolStatus.SUCCESS, | |
| content=content, | |
| ) |