Skip to content

feat(cli): attribute CLI traffic via the e2b-cli integration tag#1525

Closed
mishushakov wants to merge 6 commits into
mainfrom
cli-integration-attribution
Closed

feat(cli): attribute CLI traffic via the e2b-cli integration tag#1525
mishushakov wants to merge 6 commits into
mainfrom
cli-integration-attribution

Conversation

@mishushakov

@mishushakov mishushakov commented Jul 3, 2026

Copy link
Copy Markdown
Member

Stacked on #1524.

Sets the CLI integration string introduced there: ConnectionConfig.setIntegration('e2b-cli/<version>') runs at the top of src/api.ts, before the shared connection config is constructed at import time, so every CLI request carries the tag in the User-Agent header:

User-Agent: e2b-js-sdk/2.31.0 e2b-cli/2.13.0

No dependency changes needed: the CLI typechecks and bundles the workspace js-sdk source (packages/cli/tsconfig.json maps e2b../js-sdk/src, and esbuild follows the same mapping when bundling via noExternal), so the setter is available as soon as #1524 merges — no published e2b release required.

⚠️ Blocked on a backend User-Agent parsing fix

The API currently parses the SDK version from the User-Agent by taking everything after e2b-js-sdk/, so any integration tag appended after the SDK token breaks template builds (verified against production):

❌ Template build failed.
Error: 400: Error when parsing user agent: parsing JS SDK version: invalid current version format: v2.31.0 e2b-cli/2.13.0

This affects every integration using #1524's setter, not just the CLI. The parser needs to be fixed on the backend (stop at the first whitespace after the SDK token) before this — or any integration tagging — ships. Prepending the tag instead (e2b-cli/2.13.0 e2b-js-sdk/2.31.0) passes against today's backend, if a client-side ordering workaround is preferred in #1524.

Merge order

Verified

  • New packages/cli/tests/attribution.test.ts covers the import-time shared config and configs constructed later at runtime (auth commands, Sandbox calls).
  • Full CLI suite (96 tests) passes locally.
  • Ran the built binary against a local HTTP server and observed User-Agent: e2b-js-sdk/2.31.0 e2b-cli/2.13.0, confirming the call survives esbuild bundling (sideEffects: false makes a bare side-effect import unsafe, hence placement in api.ts) and that the bundle carries the workspace SDK regardless of the npm e2b version installed.

🤖 Generated with Claude Code

mishushakov and others added 5 commits July 3, 2026 15:46
…ntegration

Replace the per-call `integration` connection option with a process-wide,
set-once setter: `ConnectionConfig.setIntegration()` (JS) and
`ConnectionConfig.set_integration()` (Python). Integrations wrapping the
SDK tag themselves once at startup and every request carries the identifier
in the User-Agent header — no more threading the option through individual
SDK calls, and the knob is kept out of the public, documented API surface.

The `integration` option is removed from `ConnectionConfigOpts` (now a
deprecated alias of `ConnectionOpts`) and from the Python constructor.
The CLI uses the new setter to tag all its traffic as `e2b-cli/<version>`.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… rpc headers test

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Cover the two behaviors the setter contract implies but nothing asserted:
custom User-Agent headers are preserved (Python) or overridden by an
integration, and setIntegration does not retro-tag configs constructed
before it was called (JS).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ration

After ConnectionConfig.set_integration(None), configs built while an
integration was set kept the stale tagged User-Agent through
get_api_params rebuilds: the header was only recomputed when the classvar
was non-None, and __init__ preserves an existing User-Agent. Track whether
the User-Agent was SDK-built and recompute it from the current integration
on every get_api_params call, while still preserving user-supplied
User-Agents (construction-time and per-call).

Reported by Cursor BugBot on #1524.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Unify the two precedence rules ConnectionConfig grew (construction-time
custom User-Agent lost to the integration, per-call won over it) into a
single one — an explicitly provided User-Agent always wins, otherwise the
SDK-built one tagged with the current integration — and extract it into
_apply_user_agent, shared by __init__ and get_api_params. _build_user_agent
and the JS buildUserAgent now read the integration themselves instead of
taking it as a parameter.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@cla-bot cla-bot Bot added the cla-signed label Jul 3, 2026
@cursor

cursor Bot commented Jul 3, 2026

Copy link
Copy Markdown

PR Summary

Medium Risk
Low local CLI risk, but appended integration tokens can break production template builds until the backend User-Agent parser is fixed and the CLI ships against an e2b release that exposes setIntegration.

Overview
The CLI calls ConnectionConfig.setIntegration('e2b-cli/<version>') at the start of api.ts before the shared connectionConfig is created so outbound requests include e2b-cli/<version> in User-Agent. A patch changeset and attribution.test.ts assert the import-time config and later ConnectionConfig instances carry that tag.

This depends on SDK support from the stacked integration-tag work and on the API parsing User-Agent without treating text after e2b-js-sdk/<version> as part of the SDK version; otherwise template builds can fail with a 400 parse error.

Reviewed by Cursor Bugbot for commit 777010b. Bugbot is set up for automated code reviews on this repo. Configure here.

@changeset-bot

changeset-bot Bot commented Jul 3, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 777010b

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@e2b/cli Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@mishushakov mishushakov force-pushed the cli-integration-attribution branch 2 times, most recently from ad0d704 to f471903 Compare July 3, 2026 15:11
@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Package Artifacts

Built from edeb74f. Download artifacts from this workflow run.

JS SDK (e2b@2.31.1-cli-integration-attribution.0):

npm install ./e2b-2.31.1-cli-integration-attribution.0.tgz

CLI (@e2b/cli@2.13.1-cli-integration-attribution.0):

npm install ./e2b-cli-2.13.1-cli-integration-attribution.0.tgz

Python SDK (e2b==2.30.0+cli-integration-attribution):

pip install ./e2b-2.30.0+cli.integration.attribution-py3-none-any.whl

Set ConnectionConfig.setIntegration('e2b-cli/<version>') before the
shared connection config is built at import time so every CLI request
carries the tag in the User-Agent header. The CLI typechecks and
bundles the workspace js-sdk source (tsconfig paths maps 'e2b' to
../js-sdk/src), so no published e2b release is required.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@mishushakov mishushakov force-pushed the cli-integration-attribution branch from f471903 to 777010b Compare July 3, 2026 15:15
@OndrejDrapalik OndrejDrapalik self-requested a review July 3, 2026 16:07
Base automatically changed from streamline-sdk-attribution to main July 11, 2026 13:52
@linear-code

linear-code Bot commented Jul 11, 2026

Copy link
Copy Markdown

SDK-215

@mishushakov

Copy link
Copy Markdown
Member Author

will reopen a fresh one, since this one drifted too far

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant