diff --git a/robosystems_client/clients/ledger_client.py b/robosystems_client/clients/ledger_client.py index e065476..ffed5e7 100644 --- a/robosystems_client/clients/ledger_client.py +++ b/robosystems_client/clients/ledger_client.py @@ -327,7 +327,11 @@ # Map the wire flavor strings the facade accepts to the GraphQL # ``ReportDownloadFormat`` enum names used as query variables. -_DOWNLOAD_FORMAT_ALIASES = {"jsonld": "JSONLD", "xbrl-2.1": "XBRL_2_1"} +_DOWNLOAD_FORMAT_ALIASES = { + "jsonld": "JSONLD", + "holon-jsonld": "HOLON_JSONLD", + "xbrl-2.1": "XBRL_2_1", +} def _parse_filename(content_disposition: str) -> str | None: @@ -1824,9 +1828,11 @@ def download_report_bundle( Args: graph_id: Graph identifier owning the Report. report_id: Report identifier (``rpt_``-prefixed ULID). - format: Serialization flavor — ``"jsonld"`` (default) or - ``"xbrl-2.1"``. The enum names ``"JSONLD"`` / ``"XBRL_2_1"`` - are also accepted. + format: Serialization flavor — ``"jsonld"`` (default, the flat + canonical bundle), ``"holon-jsonld"`` (the dataset-form + scene/boundary/projection holon), or ``"xbrl-2.1"``. The enum + names ``"JSONLD"`` / ``"HOLON_JSONLD"`` / ``"XBRL_2_1"`` are + also accepted. to: Optional file path to write the bytes to. When set, the returned ``ReportBundleDownload.path`` points at the written file. @@ -1870,7 +1876,9 @@ def download_report_bundle( ) generation_count = info.get("generation_count") - default_ext = "zip" if gql_format == "XBRL_2_1" else "jsonld" + default_ext = {"XBRL_2_1": "zip", "HOLON_JSONLD": "holon.jsonld"}.get( + gql_format, "jsonld" + ) filename = ( _parse_filename(artifact.headers.get("content-disposition", "")) or f"{report_id}-g{generation_count or 1}.{default_ext}" diff --git a/robosystems_client/models/mcp_tools_response.py b/robosystems_client/models/mcp_tools_response.py index bd00e41..7d255c9 100644 --- a/robosystems_client/models/mcp_tools_response.py +++ b/robosystems_client/models/mcp_tools_response.py @@ -1,11 +1,13 @@ from __future__ import annotations from collections.abc import Mapping -from typing import TYPE_CHECKING, Any, TypeVar +from typing import TYPE_CHECKING, Any, TypeVar, cast from attrs import define as _attrs_define from attrs import field as _attrs_field +from ..types import UNSET, Unset + if TYPE_CHECKING: from ..models.mcp_tools_response_tools_item import MCPToolsResponseToolsItem @@ -19,9 +21,13 @@ class MCPToolsResponse: Attributes: tools (list[MCPToolsResponseToolsItem]): List of available MCP tools with their schemas + instructions (None | str | Unset): Per-graph routing guidance for MCP clients, tailored to the graph's category + and live tool set. Clients should pass this to the MCP server's `instructions` handshake field so it is always + in the agent's context. """ tools: list[MCPToolsResponseToolsItem] + instructions: None | str | Unset = UNSET additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) def to_dict(self) -> dict[str, Any]: @@ -30,6 +36,12 @@ def to_dict(self) -> dict[str, Any]: tools_item = tools_item_data.to_dict() tools.append(tools_item) + instructions: None | str | Unset + if isinstance(self.instructions, Unset): + instructions = UNSET + else: + instructions = self.instructions + field_dict: dict[str, Any] = {} field_dict.update(self.additional_properties) field_dict.update( @@ -37,6 +49,8 @@ def to_dict(self) -> dict[str, Any]: "tools": tools, } ) + if instructions is not UNSET: + field_dict["instructions"] = instructions return field_dict @@ -52,8 +66,18 @@ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: tools.append(tools_item) + def _parse_instructions(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + instructions = _parse_instructions(d.pop("instructions", UNSET)) + mcp_tools_response = cls( tools=tools, + instructions=instructions, ) mcp_tools_response.additional_properties = d