diff --git a/gateway/config.py b/gateway/config.py index f7a4af8d6..1258e0899 100644 --- a/gateway/config.py +++ b/gateway/config.py @@ -312,7 +312,7 @@ class GatewayConfig: config.extra.get("client_id") or os.getenv("DINGTALK_CLIENT_ID") ) and ( config.extra.get("client_secret") or os.getenv("DINGTALK_CLIENT_SECRET") - ): + ): connected.append(platform) return connected diff --git a/hermes_cli/tools_config.py b/hermes_cli/tools_config.py index 8bfbc059f..8e4bde883 100644 --- a/hermes_cli/tools_config.py +++ b/hermes_cli/tools_config.py @@ -512,7 +512,7 @@ def _get_platform_tools( """Resolve which individual toolset names are enabled for a platform.""" from toolsets import resolve_toolset - platform_toolsets = config.get("platform_toolsets", {}) + platform_toolsets = config.get("platform_toolsets") or {} toolset_names = platform_toolsets.get(platform) if toolset_names is None or not isinstance(toolset_names, list): diff --git a/scripts/release.py b/scripts/release.py index 74063a635..61ebfb4ca 100755 --- a/scripts/release.py +++ b/scripts/release.py @@ -70,6 +70,7 @@ AUTHOR_MAP = { "27917469+nosleepcassette@users.noreply.github.com": "nosleepcassette", "241404605+MestreY0d4-Uninter@users.noreply.github.com": "MestreY0d4-Uninter", "109555139+davetist@users.noreply.github.com": "davetist", + "39405770+yyq4193@users.noreply.github.com": "yyq4193", "Asunfly@users.noreply.github.com": "Asunfly", # contributors (manual mapping from git names) "ahmedsherif95@gmail.com": "asheriif", @@ -181,6 +182,7 @@ AUTHOR_MAP = { "juan.ovalle@mistral.ai": "jjovalle99", "julien.talbot@ergonomia.re": "Julientalbot", "kagura.chen28@gmail.com": "kagura-agent", + "1342088860@qq.com": "youngDoo", "kamil@gwozdz.me": "kamil-gwozdz", "karamusti912@gmail.com": "MustafaKara7", "kira@ariaki.me": "kira-ariaki", diff --git a/tests/gateway/test_config.py b/tests/gateway/test_config.py index e60bf1e92..41a7a49fe 100644 --- a/tests/gateway/test_config.py +++ b/tests/gateway/test_config.py @@ -71,6 +71,51 @@ class TestGetConnectedPlatforms: config = GatewayConfig() assert config.get_connected_platforms() == [] + def test_dingtalk_recognised_via_extras(self): + config = GatewayConfig( + platforms={ + Platform.DINGTALK: PlatformConfig( + enabled=True, + extra={"client_id": "cid", "client_secret": "sec"}, + ), + }, + ) + assert Platform.DINGTALK in config.get_connected_platforms() + + def test_dingtalk_recognised_via_env_vars(self, monkeypatch): + """DingTalk configured via env vars (no extras) should still be + recognised as connected — covers the case where _apply_env_overrides + hasn't populated extras yet.""" + monkeypatch.setenv("DINGTALK_CLIENT_ID", "env_cid") + monkeypatch.setenv("DINGTALK_CLIENT_SECRET", "env_sec") + config = GatewayConfig( + platforms={ + Platform.DINGTALK: PlatformConfig(enabled=True, extra={}), + }, + ) + assert Platform.DINGTALK in config.get_connected_platforms() + + def test_dingtalk_missing_creds_not_connected(self, monkeypatch): + monkeypatch.delenv("DINGTALK_CLIENT_ID", raising=False) + monkeypatch.delenv("DINGTALK_CLIENT_SECRET", raising=False) + config = GatewayConfig( + platforms={ + Platform.DINGTALK: PlatformConfig(enabled=True, extra={}), + }, + ) + assert Platform.DINGTALK not in config.get_connected_platforms() + + def test_dingtalk_disabled_not_connected(self): + config = GatewayConfig( + platforms={ + Platform.DINGTALK: PlatformConfig( + enabled=False, + extra={"client_id": "cid", "client_secret": "sec"}, + ), + }, + ) + assert Platform.DINGTALK not in config.get_connected_platforms() + class TestSessionResetPolicy: def test_roundtrip(self): diff --git a/tests/hermes_cli/test_tools_config.py b/tests/hermes_cli/test_tools_config.py index 3a72490b4..8911d46dc 100644 --- a/tests/hermes_cli/test_tools_config.py +++ b/tests/hermes_cli/test_tools_config.py @@ -40,6 +40,19 @@ def test_get_platform_tools_preserves_explicit_empty_selection(): assert enabled == set() +def test_get_platform_tools_handles_null_platform_toolsets(): + """YAML `platform_toolsets:` with no value parses as None — the old + ``config.get("platform_toolsets", {})`` pattern would then crash with + ``NoneType has no attribute 'get'`` on the next line. Guard against that. + """ + config = {"platform_toolsets": None} + + enabled = _get_platform_tools(config, "cli") + + # Falls through to defaults instead of raising + assert enabled + + def test_platform_toolset_summary_uses_explicit_platform_list(): config = {}