glaip-sdk 0.7.14__py3-none-any.whl → 0.7.15__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.
- glaip_sdk/agents/base.py +46 -1
- glaip_sdk/runner/langgraph.py +107 -16
- {glaip_sdk-0.7.14.dist-info → glaip_sdk-0.7.15.dist-info}/METADATA +1 -1
- {glaip_sdk-0.7.14.dist-info → glaip_sdk-0.7.15.dist-info}/RECORD +7 -7
- {glaip_sdk-0.7.14.dist-info → glaip_sdk-0.7.15.dist-info}/WHEEL +0 -0
- {glaip_sdk-0.7.14.dist-info → glaip_sdk-0.7.15.dist-info}/entry_points.txt +0 -0
- {glaip_sdk-0.7.14.dist-info → glaip_sdk-0.7.15.dist-info}/top_level.txt +0 -0
glaip_sdk/agents/base.py
CHANGED
|
@@ -202,7 +202,11 @@ class Agent:
|
|
|
202
202
|
|
|
203
203
|
self._agent_config = kwargs.pop("agent_config", Agent._UNSET) # type: ignore[assignment]
|
|
204
204
|
self._tool_configs = kwargs.pop("tool_configs", Agent._UNSET) # type: ignore[assignment]
|
|
205
|
-
|
|
205
|
+
mcp_configs = kwargs.pop("mcp_configs", Agent._UNSET)
|
|
206
|
+
if mcp_configs is not Agent._UNSET and isinstance(mcp_configs, dict):
|
|
207
|
+
self._mcp_configs = self._normalize_mcp_configs(mcp_configs)
|
|
208
|
+
else:
|
|
209
|
+
self._mcp_configs = mcp_configs # type: ignore[assignment]
|
|
206
210
|
self._a2a_profile = kwargs.pop("a2a_profile", Agent._UNSET) # type: ignore[assignment]
|
|
207
211
|
|
|
208
212
|
# Warn about unexpected kwargs
|
|
@@ -783,6 +787,47 @@ class Agent:
|
|
|
783
787
|
|
|
784
788
|
return resolved
|
|
785
789
|
|
|
790
|
+
def _normalize_mcp_configs(self, mcp_configs: dict[Any, Any]) -> dict[Any, Any]:
|
|
791
|
+
"""Normalize mcp_configs by wrapping misplaced transport keys in 'config'.
|
|
792
|
+
|
|
793
|
+
This ensures that flat transport settings (e.g. {'url': '...'}) provided
|
|
794
|
+
by the user are correctly moved into the 'config' block required by the
|
|
795
|
+
Platform, ensuring parity between local and remote execution.
|
|
796
|
+
|
|
797
|
+
Args:
|
|
798
|
+
mcp_configs: The raw mcp_configs dictionary.
|
|
799
|
+
|
|
800
|
+
Returns:
|
|
801
|
+
Normalized mcp_configs dictionary.
|
|
802
|
+
"""
|
|
803
|
+
from glaip_sdk.runner.langgraph import _MCP_TRANSPORT_KEYS # noqa: PLC0415
|
|
804
|
+
|
|
805
|
+
normalized = {}
|
|
806
|
+
for mcp_key, override in mcp_configs.items():
|
|
807
|
+
if not isinstance(override, dict):
|
|
808
|
+
normalized[mcp_key] = override
|
|
809
|
+
continue
|
|
810
|
+
|
|
811
|
+
misplaced = {k: v for k, v in override.items() if k in _MCP_TRANSPORT_KEYS}
|
|
812
|
+
|
|
813
|
+
if misplaced:
|
|
814
|
+
new_override = override.copy()
|
|
815
|
+
config_block = new_override.get("config", {})
|
|
816
|
+
if not isinstance(config_block, dict):
|
|
817
|
+
config_block = {}
|
|
818
|
+
|
|
819
|
+
config_block.update(misplaced)
|
|
820
|
+
new_override["config"] = config_block
|
|
821
|
+
|
|
822
|
+
for k in misplaced:
|
|
823
|
+
new_override.pop(k, None)
|
|
824
|
+
|
|
825
|
+
normalized[mcp_key] = new_override
|
|
826
|
+
else:
|
|
827
|
+
normalized[mcp_key] = override
|
|
828
|
+
|
|
829
|
+
return normalized
|
|
830
|
+
|
|
786
831
|
def _resolve_agents(self, registry: AgentRegistry) -> list[str]:
|
|
787
832
|
"""Resolve sub-agent references using AgentRegistry.
|
|
788
833
|
|
glaip_sdk/runner/langgraph.py
CHANGED
|
@@ -70,6 +70,10 @@ def _swallow_aip_logs(level: int = logging.ERROR) -> None:
|
|
|
70
70
|
logger = LoggerManager().get_logger(__name__)
|
|
71
71
|
|
|
72
72
|
|
|
73
|
+
# Constants for MCP configuration validation
|
|
74
|
+
_MCP_TRANSPORT_KEYS = {"url", "command", "args", "env", "timeout", "headers"}
|
|
75
|
+
|
|
76
|
+
|
|
73
77
|
def _convert_chat_history_to_messages(
|
|
74
78
|
chat_history: list[dict[str, str]] | None,
|
|
75
79
|
) -> list[BaseMessage]:
|
|
@@ -870,39 +874,126 @@ class LangGraphRunner(BaseRunner):
|
|
|
870
874
|
base_config: dict[str, Any],
|
|
871
875
|
override: dict[str, Any] | None,
|
|
872
876
|
) -> dict[str, Any]:
|
|
873
|
-
"""Merge a single MCP config with runtime override.
|
|
877
|
+
"""Merge a single MCP config with a runtime override, handling normalization and parity fixes.
|
|
878
|
+
|
|
879
|
+
This method orchestrates the merging of base MCP settings (from the object definition)
|
|
880
|
+
with runtime overrides. It enforces Platform parity by prioritizing the nested 'config'
|
|
881
|
+
block while maintaining robustness for local development by auto-fixing flat transport keys.
|
|
882
|
+
|
|
883
|
+
The merge follows these priority rules (highest to lowest):
|
|
884
|
+
1. Misplaced flat keys in the override (e.g., 'url' at top level) - Auto-fixed with warning.
|
|
885
|
+
2. Nested 'config' block in the override (Matches Platform/Constructor schema).
|
|
886
|
+
3. Authentication objects in the override (Converted to HTTP headers).
|
|
887
|
+
4. Structural settings in the override (e.g., 'allowed_tools').
|
|
888
|
+
5. Base configuration from the MCP object definition.
|
|
889
|
+
|
|
890
|
+
Examples:
|
|
891
|
+
>>> # 1. Strict Nested Style (Recommended)
|
|
892
|
+
>>> override = {"config": {"url": "https://new.api"}, "allowed_tools": ["t1"]}
|
|
893
|
+
>>> self._merge_single_mcp_config("mcp", base, override)
|
|
894
|
+
>>> # Result: {"url": "https://new.api", "allowed_tools": ["t1"], ...}
|
|
895
|
+
|
|
896
|
+
>>> # 2. Flat Legacy Style (Auto-fixed with warning)
|
|
897
|
+
>>> override = {"url": "https://new.api"}
|
|
898
|
+
>>> self._merge_single_mcp_config("mcp", base, override)
|
|
899
|
+
>>> # Result: {"url": "https://new.api", ...}
|
|
900
|
+
|
|
901
|
+
>>> # 3. Header Merging (Preserves Auth)
|
|
902
|
+
>>> base = {"headers": {"Authorization": "Bearer token"}}
|
|
903
|
+
>>> override = {"headers": {"X-Custom": "val"}}
|
|
904
|
+
>>> self._merge_single_mcp_config("mcp", base, override)
|
|
905
|
+
>>> # Result: {"headers": {"Authorization": "Bearer token", "X-Custom": "val"}, ...}
|
|
874
906
|
|
|
875
907
|
Args:
|
|
876
|
-
server_name: Name of the MCP server.
|
|
877
|
-
base_config: Base
|
|
878
|
-
override: Optional runtime
|
|
908
|
+
server_name: Name of the MCP server being configured.
|
|
909
|
+
base_config: Base configuration dictionary derived from the MCP object.
|
|
910
|
+
override: Optional dictionary of runtime overrides.
|
|
879
911
|
|
|
880
912
|
Returns:
|
|
881
|
-
|
|
913
|
+
A fully merged and normalized configuration dictionary ready for the local runner.
|
|
882
914
|
"""
|
|
883
915
|
merged = base_config.copy()
|
|
884
916
|
|
|
885
917
|
if not override:
|
|
886
918
|
return merged
|
|
887
919
|
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
920
|
+
# 1. Check for misplaced keys and warn (DX/Parity guidance)
|
|
921
|
+
self._warn_if_mcp_override_misplaced(server_name, override)
|
|
922
|
+
|
|
923
|
+
# 2. Apply Authentication (Converted to headers)
|
|
924
|
+
self._apply_mcp_auth_override(server_name, merged, override)
|
|
925
|
+
|
|
926
|
+
# 3. Apply Transport Settings (Nested 'config')
|
|
927
|
+
if "config" in override and isinstance(override["config"], dict):
|
|
928
|
+
merged.update(override["config"])
|
|
891
929
|
|
|
892
|
-
#
|
|
893
|
-
if "
|
|
894
|
-
|
|
895
|
-
if headers:
|
|
896
|
-
merged["headers"] = headers
|
|
897
|
-
logger.debug("Applied runtime authentication headers for MCP '%s'", server_name)
|
|
930
|
+
# 4. Apply Structural Settings (e.g., allowed_tools)
|
|
931
|
+
if "allowed_tools" in override:
|
|
932
|
+
merged["allowed_tools"] = override["allowed_tools"]
|
|
898
933
|
|
|
899
|
-
#
|
|
934
|
+
# 5. Preserve unknown top-level keys (backward compatibility)
|
|
935
|
+
known_keys = _MCP_TRANSPORT_KEYS | {"config", "authentication", "allowed_tools"}
|
|
900
936
|
for key, value in override.items():
|
|
901
|
-
if key
|
|
937
|
+
if key not in known_keys:
|
|
902
938
|
merged[key] = value
|
|
903
939
|
|
|
940
|
+
# 6. Apply Auto-fix for misplaced keys (Local Success)
|
|
941
|
+
for key in [k for k in override if k in _MCP_TRANSPORT_KEYS]:
|
|
942
|
+
val = override[key]
|
|
943
|
+
# Special case: Merge headers instead of overwriting to preserve auth
|
|
944
|
+
if key == "headers" and isinstance(val, dict) and isinstance(merged.get("headers"), dict):
|
|
945
|
+
merged["headers"].update(val)
|
|
946
|
+
else:
|
|
947
|
+
merged[key] = val
|
|
948
|
+
|
|
904
949
|
return merged
|
|
905
950
|
|
|
951
|
+
def _warn_if_mcp_override_misplaced(self, server_name: str, override: dict[str, Any]) -> None:
|
|
952
|
+
"""Log a warning if transport keys are found at the top level of an override.
|
|
953
|
+
|
|
954
|
+
Args:
|
|
955
|
+
server_name: Name of the MCP server.
|
|
956
|
+
override: The raw override dictionary.
|
|
957
|
+
"""
|
|
958
|
+
misplaced = [k for k in override if k in _MCP_TRANSPORT_KEYS]
|
|
959
|
+
if misplaced:
|
|
960
|
+
logger.warning(
|
|
961
|
+
"MCP '%s' override contains transport keys at the top level: %s. "
|
|
962
|
+
"This structure is inconsistent with the Platform and MCP constructor. "
|
|
963
|
+
"Transport settings should be nested within a 'config' dictionary. "
|
|
964
|
+
"Example: mcp_configs={'%s': {'config': {'%s': '...'}}}. "
|
|
965
|
+
"Automatically merging top-level keys for local execution parity.",
|
|
966
|
+
server_name,
|
|
967
|
+
misplaced,
|
|
968
|
+
server_name,
|
|
969
|
+
misplaced[0],
|
|
970
|
+
)
|
|
971
|
+
|
|
972
|
+
def _apply_mcp_auth_override(
|
|
973
|
+
self,
|
|
974
|
+
server_name: str,
|
|
975
|
+
merged_config: dict[str, Any],
|
|
976
|
+
override: dict[str, Any],
|
|
977
|
+
) -> None:
|
|
978
|
+
"""Convert authentication override to headers and apply to config.
|
|
979
|
+
|
|
980
|
+
Args:
|
|
981
|
+
server_name: Name of the MCP server.
|
|
982
|
+
merged_config: The configuration being built (mutated in place).
|
|
983
|
+
override: The raw override dictionary.
|
|
984
|
+
"""
|
|
985
|
+
if "authentication" not in override:
|
|
986
|
+
return
|
|
987
|
+
|
|
988
|
+
from glaip_sdk.runner.mcp_adapter.mcp_config_builder import ( # noqa: PLC0415
|
|
989
|
+
MCPConfigBuilder,
|
|
990
|
+
)
|
|
991
|
+
|
|
992
|
+
headers = MCPConfigBuilder.build_headers_from_auth(override["authentication"])
|
|
993
|
+
if headers:
|
|
994
|
+
merged_config["headers"] = headers
|
|
995
|
+
logger.debug("Applied runtime authentication headers for MCP '%s'", server_name)
|
|
996
|
+
|
|
906
997
|
def _validate_sub_agent_for_local_mode(self, sub_agent: Any) -> None:
|
|
907
998
|
"""Validate that a sub-agent reference is supported for local execution.
|
|
908
999
|
|
|
@@ -5,7 +5,7 @@ glaip_sdk/exceptions.py,sha256=iAChFClkytXRBLP0vZq1_YjoZxA9i4m4bW1gDLiGR1g,2321
|
|
|
5
5
|
glaip_sdk/icons.py,sha256=J5THz0ReAmDwIiIooh1_G3Le-mwTJyEjhJDdJ13KRxM,524
|
|
6
6
|
glaip_sdk/rich_components.py,sha256=44Z0V1ZQleVh9gUDGwRR5mriiYFnVGOhm7fFxZYbP8c,4052
|
|
7
7
|
glaip_sdk/agents/__init__.py,sha256=VfYov56edbWuySXFEbWJ_jLXgwnFzPk1KB-9-mfsUCc,776
|
|
8
|
-
glaip_sdk/agents/base.py,sha256=
|
|
8
|
+
glaip_sdk/agents/base.py,sha256=OCJP2yBOo1rYqUAzpwdcEb2ZjIGHj9-ivDvldzfQX48,50813
|
|
9
9
|
glaip_sdk/cli/__init__.py,sha256=xCCfuF1Yc7mpCDcfhHZTX0vizvtrDSLeT8MJ3V7m5A0,156
|
|
10
10
|
glaip_sdk/cli/account_store.py,sha256=u_memecwEQssustZs2wYBrHbEmKUlDfmmL-zO1F3n3A,19034
|
|
11
11
|
glaip_sdk/cli/agent_config.py,sha256=YAbFKrTNTRqNA6b0i0Q3pH-01rhHDRi5v8dxSFwGSwM,2401
|
|
@@ -151,7 +151,7 @@ glaip_sdk/registry/tool.py,sha256=c0Ja4rFYMOKs_1yjDLDZxCId4IjQzprwXzX0iIL8Fio,14
|
|
|
151
151
|
glaip_sdk/runner/__init__.py,sha256=orJ3nLR9P-n1qMaAMWZ_xRS4368YnDpdltg-bX5BlUk,2210
|
|
152
152
|
glaip_sdk/runner/base.py,sha256=KIjcSAyDCP9_mn2H4rXR5gu1FZlwD9pe0gkTBmr6Yi4,2663
|
|
153
153
|
glaip_sdk/runner/deps.py,sha256=Du3hr2R5RHOYCRAv7RVmx661x-ayVXIeZ8JD7ODirTA,3884
|
|
154
|
-
glaip_sdk/runner/langgraph.py,sha256=
|
|
154
|
+
glaip_sdk/runner/langgraph.py,sha256=HB1n6w44LdyE7OSB2iSEtwhm_IeD7fGi_20erCZurX4,40869
|
|
155
155
|
glaip_sdk/runner/logging_config.py,sha256=OrQgW23t42qQRqEXKH8U4bFg4JG5EEkUJTlbvtU65iE,2528
|
|
156
156
|
glaip_sdk/runner/mcp_adapter/__init__.py,sha256=Rdttfg3N6kg3-DaTCKqaGXKByZyBt0Mwf6FV8s_5kI8,462
|
|
157
157
|
glaip_sdk/runner/mcp_adapter/base_mcp_adapter.py,sha256=ic56fKgb3zgVZZQm3ClWUZi7pE1t4EVq8mOg6AM6hdA,1374
|
|
@@ -216,8 +216,8 @@ glaip_sdk/utils/rendering/steps/format.py,sha256=Chnq7OBaj8XMeBntSBxrX5zSmrYeGcO
|
|
|
216
216
|
glaip_sdk/utils/rendering/steps/manager.py,sha256=BiBmTeQMQhjRMykgICXsXNYh1hGsss-fH9BIGVMWFi0,13194
|
|
217
217
|
glaip_sdk/utils/rendering/viewer/__init__.py,sha256=XrxmE2cMAozqrzo1jtDFm8HqNtvDcYi2mAhXLXn5CjI,457
|
|
218
218
|
glaip_sdk/utils/rendering/viewer/presenter.py,sha256=mlLMTjnyeyPVtsyrAbz1BJu9lFGQSlS-voZ-_Cuugv0,5725
|
|
219
|
-
glaip_sdk-0.7.
|
|
220
|
-
glaip_sdk-0.7.
|
|
221
|
-
glaip_sdk-0.7.
|
|
222
|
-
glaip_sdk-0.7.
|
|
223
|
-
glaip_sdk-0.7.
|
|
219
|
+
glaip_sdk-0.7.15.dist-info/METADATA,sha256=L7wF6kfY6yiNHvUsl6gGSVhFjMGllD9K3ZHA3UmIbkA,8528
|
|
220
|
+
glaip_sdk-0.7.15.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
221
|
+
glaip_sdk-0.7.15.dist-info/entry_points.txt,sha256=NkhO6FfgX9Zrjn63GuKphf-dLw7KNJvucAcXc7P3aMk,54
|
|
222
|
+
glaip_sdk-0.7.15.dist-info/top_level.txt,sha256=td7yXttiYX2s94-4wFhv-5KdT0rSZ-pnJRSire341hw,10
|
|
223
|
+
glaip_sdk-0.7.15.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|