@@ -671,7 +671,8 @@ def test_sets_default_http_client(self, mocker):
671671 # the newly created client is reused
672672 assert stripe .default_http_client == new_default_client
673673
674- def test_uses_app_info (self , requestor , http_client_mock ):
674+ def test_uses_app_info (self , requestor , mocker , http_client_mock ):
675+ mocker .patch .object (_APIRequestor , "_detect_ai_agent" , return_value = "" )
675676 try :
676677 old = stripe .app_info
677678 stripe .set_app_info (
@@ -707,6 +708,42 @@ def test_uses_app_info(self, requestor, http_client_mock):
707708 finally :
708709 stripe .app_info = old
709710
711+ def test_detect_ai_agent (self ):
712+ assert (
713+ _APIRequestor ._detect_ai_agent ({"CLAUDECODE" : "1" })
714+ == "claude_code"
715+ )
716+
717+ def test_detect_ai_agent_no_env_vars (self ):
718+ assert _APIRequestor ._detect_ai_agent ({}) == ""
719+
720+ def test_detect_ai_agent_first_match_wins (self ):
721+ assert (
722+ _APIRequestor ._detect_ai_agent (
723+ {"CURSOR_AGENT" : "1" , "OPENCODE" : "1" }
724+ )
725+ == "cursor"
726+ )
727+
728+ def test_ai_agent_included_in_request_headers (
729+ self , requestor , mocker , http_client_mock
730+ ):
731+ mocker .patch .object (
732+ _APIRequestor , "_detect_ai_agent" , return_value = "cursor"
733+ )
734+ http_client_mock .stub_request (
735+ "get" , path = self .v1_path , rbody = "{}" , rcode = 200
736+ )
737+ requestor .request ("get" , self .v1_path , {}, base_address = "api" )
738+
739+ last_call = http_client_mock .get_last_call ()
740+ ua = last_call .get_raw_header ("User-Agent" )
741+ assert ua .endswith (" AIAgent/cursor" )
742+ client_ua = json .loads (
743+ last_call .get_raw_header ("X-Stripe-Client-User-Agent" )
744+ )
745+ assert client_ua ["ai_agent" ] == "cursor"
746+
710747 def test_handles_failed_platform_call (
711748 self , requestor , mocker , http_client_mock
712749 ):
0 commit comments