Set a base User-Agent and append agent/<id> when a coding agent is detected#509
Draft
ctufts wants to merge 1 commit into
Draft
Set a base User-Agent and append agent/<id> when a coding agent is detected#509ctufts wants to merge 1 commit into
ctufts wants to merge 1 commit into
Conversation
…tected The Node SDK sends no User-Agent today, so requests fall back to got's default. Establish mapbox-sdk-js/<version> as the base UA on every request, and append " agent/<id>" when a coding-agent env indicator is present (Node only; the allowlist + precedence mirrors mapbox/tilesets-cli's agent_detect.py). The browser client explicitly filters the user-agent header back out, since browsers forbid script-set UA via XHR.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The Node SDK currently sends no
User-Agentof its own — requests fall back togot's default (got/11.8.5 ...). This PR establishes a first-party base UA,mapbox-sdk-js/<version>, on every request, and appendsagent/<id>when the process environment indicates it's being driven by a coding agent (Claude Code, Codex, Cursor, etc.).This is a behavior change on every Node request this SDK makes (previously an unset/
got-default UA, now alwaysmapbox-sdk-js/<version>[ agent/<id>]) — flagging explicitly for reviewer sign-off before merge, since it's visible in server-side logs for every consumer.Changes
lib/helpers/agent-detect.js— Node-onlydetectAgent(), checking a hardcoded allowlist of ~24 known coding-agent environment indicators (by presence or exact value) in priority order, then falling back toAI_AGENT/AGENTif set. Fallback values are validated against a safe charset (/^[\w.-]{1,64}$/) before use, since an arbitrary env var value must never reach an HTTP header unsanitized (a stray newline would otherwise crash every request). Returnsnulloutside Node (e.g. the browser bundle) or on any unexpected error readingprocess.env.lib/helpers/sdk-version.js— resolvesmapbox-sdk-js/<version>frompackage.jsonat runtime, so the UA can never drift from the published version.lib/classes/mapi-request.js—defaultHeadersnow always setsuser-agent, appendingagent/<id>when detected. A caller-suppliedUser-Agentheader still overrides it (existing lowercase-dedup behavior), with no duplicate header.lib/browser/browser-layer.js— filters theuser-agentheader key out before callingxhr.setRequestHeader, since browsers forbid script-set User-Agent via XHR (this SDK's new default would otherwise be a no-op there at best, and throws in some stricter XHR implementations at worst — this is exactly what broke while developing this change, see Testing). Browser agent-tagging is intentionally out of scope here; it's expected to ride a separate mechanism.rollup.config.js/package.json— addedrollup-plugin-jsonso the UMD browser bundle can inlinepackage.json's version forsdk-version.js.Testing
npm test— full suite passing (490/490), including new coverage for: all ~24 allowlist entries individually, table-order precedence, theAI_AGENT/AGENTfallback and its charset validation (including a header-injection attempt with an embedded newline, unicode, and other unsafe characters), the Node-vs-browser guard, a throwingprocess.env(permission-gated environments), the browser UA-filter, and the header-merge/override/dedup path inmapi-request.js.npm run lintclean.npm run bundlesucceeds; confirmed the version string is correctly inlined intoumd/mapbox-sdk.js.MapiRequest:CLAUDECODE=1→user-agent: mapbox-sdk-js/0.16.3 agent/claude-codeuser-agent: mapbox-sdk-js/0.16.3(negative control, no suffix)AI_AGENTset to a value containing an embedded newline → safely rejected, base UA only, no crashprocess.enverror-handling gap above, and the missing browser-layer regression test).Downstream impact
Every Node consumer's outbound requests to
api.mapbox.comwill show a new User-Agent string going forward — relevant to anyone with UA-based logging, analytics, or allowlisting on their own systems. No behavior change for browser consumers (the UA header is filtered out before it would ever reach the network, same as today'sgot-default-only browser behavior). No change to auth, response handling, retries, or any other request semantics.Operational considerations
None — pure client-side header change, no deploy/migration/feature flag required. Takes effect on the next version bump.