diff --git a/plugins/memory/honcho/oauth_flow.py b/plugins/memory/honcho/oauth_flow.py index e168364e1a33..b1268c02d441 100644 --- a/plugins/memory/honcho/oauth_flow.py +++ b/plugins/memory/honcho/oauth_flow.py @@ -465,7 +465,8 @@ def request_device_code( f"{verification_uri}?user_code={body['user_code']}", ), expires_in=int(body["expires_in"]), - interval=int(body["interval"]), + # RFC 8628 §3.2: interval is optional; clients default to 5s. + interval=int(body.get("interval", 5)), ) except (KeyError, TypeError, ValueError) as e: raise DeviceFlowError( diff --git a/tests/honcho_plugin/test_oauth_flow.py b/tests/honcho_plugin/test_oauth_flow.py index a52941a8e60d..5a63b8fcdd79 100644 --- a/tests/honcho_plugin/test_oauth_flow.py +++ b/tests/honcho_plugin/test_oauth_flow.py @@ -353,6 +353,24 @@ def test_request_device_code_parses_response_and_sends_identity(fake_as): assert _FakeAS.last_device_form["source"] == "hermes-cli" +def test_request_device_code_defaults_interval_when_omitted(monkeypatch): + # RFC 8628 §3.2: interval is optional; a compliant AS may omit it, and the + # client must fall back to 5s rather than treating the response as malformed. + endpoints = oauth_flow.resolve_endpoints(environment="local") + monkeypatch.setattr( + oauth, + "_http_post_form_status", + lambda *a, **k: (200, { + "device_code": "dev-code-1", + "user_code": "ABCD-EFGH", + "verification_uri": "http://localhost:3000/device", + "expires_in": 600, + }), + ) + device = oauth_flow.request_device_code(endpoints) + assert device.interval == 5 + + def test_full_device_flow_pending_then_approved(tmp_path, fake_as): _FakeAS.device_responses = ["authorization_pending", "authorization_pending", "ok"] config_path = tmp_path / "honcho.json"