1313import java .util .Optional ;
1414import java .util .Properties ;
1515import java .util .concurrent .ThreadLocalRandom ;
16+ import java .util .function .Function ;
1617
1718/** Base abstract class for HTTP clients used to send requests to Stripe's API. */
1819public abstract class HttpClient {
@@ -137,12 +138,39 @@ public StripeResponseStream requestStreamWithRetries(StripeRequest request)
137138 return sendWithRetries (request , (r ) -> this .requestStream (r ));
138139 }
139140
141+ static String detectAIAgent () {
142+ return detectAIAgent (System ::getenv );
143+ }
144+
145+ static String detectAIAgent (Function <String , String > getEnv ) {
146+ String [][] agents = {
147+ {"ANTIGRAVITY_CLI_ALIAS" , "antigravity" },
148+ {"CLAUDECODE" , "claude_code" },
149+ {"CLINE_ACTIVE" , "cline" },
150+ {"CODEX_SANDBOX" , "codex_cli" },
151+ {"CURSOR_AGENT" , "cursor" },
152+ {"GEMINI_CLI" , "gemini_cli" },
153+ {"OPENCODE" , "open_code" },
154+ };
155+ for (String [] agent : agents ) {
156+ String val = getEnv .apply (agent [0 ]);
157+ if (val != null && !val .isEmpty ()) {
158+ return agent [1 ];
159+ }
160+ }
161+ return "" ;
162+ }
163+
140164 /**
141165 * Builds the value of the {@code User-Agent} header.
142166 *
143167 * @return a string containing the value of the {@code User-Agent} header
144168 */
145169 protected static String buildUserAgentString (StripeRequest request ) {
170+ return buildUserAgentString (request , detectAIAgent ());
171+ }
172+
173+ static String buildUserAgentString (StripeRequest request , String aiAgent ) {
146174 String apiMode = request .apiMode () == ApiMode .V2 ? "v2" : "v1" ;
147175
148176 String userAgent = String .format ("Stripe/%s JavaBindings/%s" , apiMode , Stripe .VERSION );
@@ -151,6 +179,10 @@ protected static String buildUserAgentString(StripeRequest request) {
151179 userAgent += " " + formatAppInfo (Stripe .getAppInfo ());
152180 }
153181
182+ if (!aiAgent .isEmpty ()) {
183+ userAgent += " AIAgent/" + aiAgent ;
184+ }
185+
154186 return userAgent ;
155187 }
156188
@@ -160,6 +192,10 @@ protected static String buildUserAgentString(StripeRequest request) {
160192 * @return a string containing the value of the {@code X-Stripe-Client-User-Agent} header
161193 */
162194 protected static String buildXStripeClientUserAgentString () {
195+ return buildXStripeClientUserAgentString (detectAIAgent ());
196+ }
197+
198+ static String buildXStripeClientUserAgentString (String aiAgent ) {
163199 String [] propertyNames = {
164200 "os.name" ,
165201 "os.version" ,
@@ -182,6 +218,10 @@ protected static String buildXStripeClientUserAgentString() {
182218 }
183219 getGsonVersion ().ifPresent (ver -> propertyMap .put ("gson.version" , ver ));
184220
221+ if (!aiAgent .isEmpty ()) {
222+ propertyMap .put ("ai_agent" , aiAgent );
223+ }
224+
185225 return ApiResource .INTERNAL_GSON .toJson (propertyMap );
186226 }
187227
0 commit comments