Skip to content

feat(eve): identify eve on AI Gateway, Workflow, and Sandbox requests - #939

Merged
AndrewBarba merged 11 commits into
mainfrom
rui/eve-service-identification
Jul 21, 2026
Merged

feat(eve): identify eve on AI Gateway, Workflow, and Sandbox requests#939
AndrewBarba merged 11 commits into
mainfrom
rui/eve-service-identification

Conversation

@ruiconti

@ruicontiruiconti commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

Vercel services can't tell eve traffic from any other AI SDK app today. This appends an eve/<installed version> User-Agent product token to every service request eve makes, so receivers can attribute traffic to eve and its version — segmenting by framework during incidents and, later, controlling traffic keyed on the same token.

What

  • internal/user-agent.ts: builds the eve/<version> product token, appends it to a Headers without touching existing products (idempotent, space-joined per the RFC 9110 UA grammar — not Headers.append(), whose comma-combination breaks whitespace-delimited parsers), and exposes withPackageUserAgent(fetch), the generic UA-decorating fetch wrapper both the Gateway and Sandbox transports build on.
  • internal/gateway.ts owns the Gateway transport surface: the /v1/models and /v1/models/catalog URLs, getVercelGatewayFetch() (a UA-decorated fetch, mirroring the Sandbox binding's getVercelSandboxFetch), and resolveProviderHeaders(model) — headers for Gateway-routed models (bare ids and gateway.* instances), undefined for direct providers.
  • AI Gateway call sites: tool-loop generation and compaction, autoeval judge calls, model catalog, setup catalog, CLI model lookup, API-key validation — all through the two helpers above; no call site does header plumbing or URL assembly.
  • Workflow: generated world-vercel startup code passes the token via createWorld({ headers }), with the per-world wiring dispatched in one place (resolveWorkflowWorldWiring).
  • Sandbox: the SDK fetch decoration reuses withPackageUserAgent. A separate commit fixes a real gap here: Sandbox.get() lost the custom fetch on the credential-discovery failure path.

Wire format

Captured against a local server through the real ai/@ai-sdk/gateway packages — existing products stay intact:

eve/0.24.6 ai/7.0.26 ai-sdk/provider-utils/5.0.9 runtime/node.js/26

The Workflow leg is inert until a vendored bump

The vendored @workflow/world-vercel@5.0.0-beta.31 overwrites caller User-Agents, so the header this PR passes is dropped on the wire today (requests degrade to current behavior — nothing fails). vercel/workflow#2998 fixes the append; a follow-up bump of the vendored package lights this leg up.

Compaction attribution fix

Gateway attribution headers for compaction were previously computed from the main model; they now derive from the compaction model itself, since the two can differ.

…ery fails
getVercelSandboxGetOptions only attached the fetch override in the
credential-discovery success branch, so on the catch path Sandbox.get()
fell back to the SDK's bare global fetch. Move the fetch into the shared
base options so both branches use it.
Signed-off-by: Rui Conti <ruiconti@gmail.com>
Append an eve/<installed version> User-Agent product token to every
Vercel-service request eve makes, so receiving services can attribute
traffic to eve and its version without new headers or protocols:
- AI Gateway: model generation and compaction (tool-loop), autoeval
judge calls, the model catalog and setup catalog fetches, CLI model
lookup, and API-key validation. Gateway-routed models are detected via
isGatewayModel (bare ids and gateway.* instances).
- Workflow: generated world-vercel startup code passes the token via
createWorld({ headers }). Inert until the vendored @workflow/world-vercel
ships the caller User-Agent append (currently 5.0.0-beta.31, which
discards caller UA) — requests degrade to today's behavior, no failure.
- Sandbox: the SDK fetch decoration is generalized from the eve-specific
helper to appendPackageUserAgent.
The token is appended per the RFC 9110 User-Agent grammar (whitespace-
delimited products), never replacing existing products, idempotent on
re-append. Receivers parse it with whitespace-token scanners, so joining
uses spaces, not Headers.append() comma-combination.
Signed-off-by: Rui Conti <ruiconti@gmail.com>
@vercel

vercelBot commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

ProjectDeploymentActionsUpdated (UTC)
eve-docsReadyReadyPreview, CommentJul 20, 2026 11:50pm
eve-docs-1644ReadyReadyPreview, Comment, Open in v0Jul 20, 2026 11:50pm
eve-docs-4759ReadyReadyPreview, Comment, Open in v0Jul 20, 2026 11:50pm

Request Review

@github-actions

github-actionsBot commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

Bundle + Package Summary: apps/fixtures/weather-agent

Key takeaways

  • No notable deltas vs main (d034e01).

Delta vs main (d034e01)

AreaMetricBaselineCurrentDelta
PackagePacked tarball3.80 MB3.81 MB+636 B ⚠️
PackageUnpacked publish size13.77 MB13.78 MB+3.6 kB ⚠️
PackageInstalled footprint52.88 MB52.89 MB+3.6 kB ⚠️
PackagePublished files27222724+2
PackageInstalled files59625964+2
RuntimeUnique function payloads220
RuntimeTotal function bytes9.75 MB9.75 MB+3 B ⚠️
RuntimePublic routes10100
Changed function payloads vs main (d034e01) (2)
FunctionStatusBaselineCurrentDeltaRoute changes
functions/.well-known/workflow/v1/flow.funcchanged6.28 MB6.28 MB+191 B ⚠️none
functions/__server.funcchanged3.47 MB3.47 MB-188 B ✅none

eve init install

MetricBaselineCurrentDelta
Installed footprint91.29 MB91.29 MB+3.6 kB ⚠️
Installed packages1221220
dependencies440
devDependencies220
Dependency package bytes28.02 MB28.03 MB+3.6 kB ⚠️
devDependency package bytes5.04 MB5.04 MB0 B ➖
Build Metadata
  • Preset: vercel
  • Nitro: nitro@3.0.260610-beta
  • Output directory: apps/fixtures/weather-agent/.vercel/output
  • Build metadata timestamp: 2026-07-20T23:51:17.985Z
  • Route aliases: 10 public, 1 internal (11 total aliases)
  • Vercel routes in config: 11
  • Severity legend: 🔴 dominant/large, 🟠 notable, 🟡 watch, ⚪ small
Package Drill-Down

Package Details

  • Package: eve@0.26.1
  • Package directory: packages/eve
  • Tarball: 3.81 MB (eve-0.26.1.tgz)
  • Unpacked payload: 13.78 MB across 2724 published files
  • Installed footprint: 52.89 MB across 5964 installed files
  • Installed root package: 12.50 MB
  • Installed dependencies: 40.39 MB
  • Runtime dependencies: 1
  • Peer dependencies: 5 (4 optional)

Installed footprint is measured from an isolated temporary npm install of the packed tarball.

Heavy installed dependencies

  • @rolldown/binding-linux-x64-gnu: 18.96 MB (35.8%)
  • eve: 12.50 MB (23.6%)
  • ai: 6.39 MB (12.1%)
  • zod: 5.04 MB (9.5%)
  • nitro: 2.41 MB (4.6%)
Publish payload breakdown
Published file size
🟠 dist/src/compiled/experimental-ai-sdk-code-mo... [###.....................] 1.51 MB 10.9%
🟡 dist/src/compiled/@vercel/sandbox/index.js [#.......................] 622.2 kB 4.5%
🟡 dist/src/compiled/_chunks/workflow/undici-fb5... [#.......................] 502.4 kB 3.6%
🟡 dist/src/compiled/@chat-adapter/slack/index.js [#.......................] 433.3 kB 3.1%
🟡 dist/src/compiled/_chunks/workflow/dist-CSfKN... [#.......................] 277.8 kB 2.0%
🔴 Other published files [########################] 10.44 MB 75.7%
Installed footprint breakdown
Installed package size
🔴 @rolldown/binding-linux-x64-gnu [########################] 18.96 MB 35.8%
🔴 eve [################........] 12.50 MB 23.6%
🔴 ai [########................] 6.39 MB 12.1%
🔴 zod [######..................] 5.04 MB 9.5%
🟠 nitro [###.....................] 2.41 MB 4.6%
🟡 @ai-sdk/provider-utils [#.......................] 847.6 kB 1.6%
🔴 Other installed packages [#########...............] 6.74 MB 12.7%
Runtime dependencies (1)
PackageRangeNotes
nitro3.0.260610-beta
Peer dependencies (5)
PackageRangeNotes
@opentelemetry/api^1.0.0optional peer
aicatalog:
braintrust^3.0.0optional peer
just-bash^3.0.0optional peer
microsandbox^0.5.0optional peer
eve init install drill-down

eve init install details

  • Command: eve init my-agent
  • Package manager: npm
  • Installed footprint: 91.29 MB across 7832 installed files
  • Installed packages: 122 total (116 transitive-only)
  • dependencies: 4 direct packages totaling 28.03 MB
  • devDependencies: 2 direct packages totaling 5.04 MB
  • Other transitive package files: 58.22 MB

Installed footprint is measured from an isolated temporary eve init my-agent using the current packed eve tarball.

Heavy installed dependencies

  • @typescript/typescript-linux-x64: 27.95 MB (30.6%)
  • @rolldown/binding-linux-x64-gnu: 18.96 MB (20.8%)
  • eve: 12.50 MB (13.7%)
  • zod: 9.00 MB (9.9%)
  • ai: 6.39 MB (7.0%)
Installed footprint breakdown
Installed package size
🔴 @typescript/typescript-linux-x64 [########################] 27.95 MB 30.6%
🔴 @rolldown/binding-linux-x64-gnu [################........] 18.96 MB 20.8%
🔴 eve [###########.............] 12.50 MB 13.7%
🔴 zod [########................] 9.00 MB 9.9%
🔴 ai [#####...................] 6.39 MB 7.0%
🟠 @types/node [##......................] 2.54 MB 2.8%
🔴 Other installed packages [############............] 13.95 MB 15.3%
dependencies (4)
PackageRangeInstalled sizeShare
@vercel/connect0.4.0135.4 kB0.1%
ai^7.0.266.39 MB7.0%
evefile:eve-0.26.1.tgz12.50 MB13.7%
zod4.4.39.00 MB9.9%
devDependencies (2)
PackageRangeInstalled sizeShare
@types/node24.x2.54 MB2.8%
typescript7.0.22.50 MB2.7%
Function Drill-Down

Payload Size Graph

Unique function payload size and share of total
🔴 functions/.well-known/workflow/v1/flow.func [########################] 6.28 MB 64.4%
🟠 functions/__server.func [#############...........] 3.47 MB 35.6%

Top Function Payloads

🟠 functions/.well-known/workflow/v1/flow.func • 1 public route • 6.28 MB
MetricValue
Public routes/.well-known/workflow/v1/flow
Runtimenodejs24.x
Handlerindex.mjs
Payload6.28 MB
Function files6.28 MB across 37 files
Traced dependencies0 B
Signal🟠 Bundled file __eve_nitro_handler__.mjs is 2.21 MB (35.2%)

🟠 🔎 Dependency Analysis

📦 Bundled files:

Bundled file size
🟠 __eve_nitro_handler__.mjs [########################] 2.21 MB 35.2%
🟡 _chunks/world-vercel.mjs [#########...............] 826.3 kB 13.2%
🟡 _chunks/sandbox.mjs [########................] 754.9 kB 12.0%
🟡 _libs/@ai-sdk/gateway+[...].mjs [#####...................] 430.4 kB 6.9%
🟡 _libs/zod.mjs [####....................] 376.1 kB 6.0%
🟠 Other bundled files [##################......] 1.68 MB 26.8%

🧾 Vercel Config

{
"handler": "index.mjs",
"launcherType": "Nodejs",
"shouldAddHelpers": false,
"supportsResponseStreaming": true,
"runtime": "nodejs24.x",
"environment": {
"NODE_OPTIONS": "--experimental-require-module"
},
"maxDuration": "max",
"experimentalTriggers": [
{
"type": "queue/v2beta",
"topic": "__eve776561746865722d6167656e74_wkf_workflow_*",
"consumer": "default",
"retryAfterSeconds": 5,
"initialDelaySeconds": 0
}
]
}

🟠 functions/__server.func • 9 public routes, 1 internal alias • 3.47 MB
MetricValue
Public routes/
/eve/v1/callback/[token]
/eve/v1/connections/[name]/callback/[token]
/eve/v1/health
/eve/v1/info
/eve/v1/session
/eve/v1/session/[sessionId]
/eve/v1/session/[sessionId]/cancel
/eve/v1/session/[sessionId]/stream
Internal aliases/__server
Runtimenodejs24.x
Handlerindex.mjs
Payload3.47 MB
Function files3.47 MB across 28 files
Traced dependencies0 B
Signal🟠 Bundled file _chunks/runtime-artifacts.mjs is 949.0 kB (27.3%)

🟠 🔎 Dependency Analysis

📦 Bundled files:

Bundled file size
🟠 _chunks/runtime-artifacts.mjs [########################] 949.0 kB 27.3%
🟠 _chunks/world-vercel.mjs [#####################...] 823.4 kB 23.7%
🟠 _chunks/sandbox.mjs [###################.....] 754.9 kB 21.8%
🟡 _chunks/dist-CSfKNxQW.mjs [#########...............] 348.5 kB 10.0%
⚪ _libs/zod.mjs [###.....................] 114.2 kB 3.3%
🟡 Other bundled files [############............] 480.2 kB 13.8%

🧾 Vercel Config

{
"handler": "index.mjs",
"launcherType": "Nodejs",
"shouldAddHelpers": false,
"supportsResponseStreaming": true,
"runtime": "nodejs24.x"
}

Build Timing: e2e/fixtures/agent-tools-sandbox

This is an informational timing measurement inside eve build, from preflight through publication. Output-size measurement and profile writing are excluded.

Build mode: deployable Vercel build with sandbox template prewarm included.

  • Build pipeline: 2.41 s -> 2.38 s (-36.9 ms) vs main (d034e01).
  • Timing is informational: shared GitHub runners are too variable for a hard timing budget.
Detailed phase timings vs `main (d034e01)`
PhaseBaselineCurrentDelta
extension.check1.1 ms0.9 ms-0.2 ms
project.resolve0.7 ms0.6 ms-0.1 ms
workspace.create0.9 ms0.7 ms-0.2 ms
host.prepare230.6 ms230.3 ms-0.3 ms
vercel.service-prefix.resolve2.1 ms2.1 ms0.0 ms
nitro.app.create24.3 ms24.2 ms-0.1 ms
nitro.app.cache.prepare0.2 ms0.2 ms0.0 ms
nitro.app.prepare0.9 ms0.8 ms-0.1 ms
nitro.app.public-assets0.7 ms0.7 ms0.0 ms
nitro.app.prerender0.5 ms0.5 ms0.0 ms
nitro.app.bundle547.7 ms554.9 ms+7.2 ms
nitro.app.cache.write0.5 ms0.4 ms-0.1 ms
sandbox.prewarm278.3 ms260.6 ms-17.7 ms
nitro.flow.create185.2 ms178.8 ms-6.4 ms
nitro.flow.cache.prepare0.2 ms0.2 ms0.0 ms
nitro.flow.prepare0.9 ms0.9 ms0.0 ms
nitro.flow.public-assets0.2 ms0.2 ms0.0 ms
nitro.flow.prerender0.0 ms0.0 ms0.0 ms
nitro.flow.bundle952.2 ms935.9 ms-16.3 ms
nitro.flow.cache.write0.3 ms0.3 ms0.0 ms
nitro.flow.close0.2 ms0.2 ms0.0 ms
workflow.emit173.9 ms170.9 ms-3.0 ms
agent-summary.emit0.6 ms0.5 ms-0.1 ms
nitro.app.close0.0 ms0.0 ms0.0 ms
output.publish3.7 ms3.7 ms0.0 ms
workspace.remove5.7 ms5.8 ms+0.1 ms

createWorkflowWorldPluginSource encoded the world selection three times: a
nested ternary for the createWorld statement, a repeated condition for the
runtime imports, and another for the vendored module specifier. The pieces
co-vary — a world constructed through an explicit createWorld(config) call
must not import createWorldFromModule — so hiding that invariant across
three expressions made every new world branch risky to add.
resolveWorkflowWorldWiring now owns all four facts per world; the caller is
pure assembly. Generated output is byte-identical for the world-local,
world-vercel, and passthrough branches (verified by rendering both versions
and comparing).
Signed-off-by: Rui Conti <ruiconti@gmail.com>
gateway.ts exported its internals — buildGatewayURL, addGatewayUA,
buildGatewayUA, isGatewayModel — and every call site reassembled them:
URLs were rebuilt locally, and model-conditional header logic leaked as
isGatewayModel(...) ? Object.fromEntries(addGatewayUA(...)) : undefined.
The module now owns the decisions instead of the parts:
- AI_GATEWAY_MODELS_URL / AI_GATEWAY_MODELS_CATALOG_URL live in gateway.ts.
- getVercelGatewayFetch() returns a UA-decorated fetch, mirroring the
Sandbox binding's getVercelSandboxFetch — call sites get a transport,
not header plumbing. validate-gateway-key routes its provider fetch
through it instead of construction headers.
- resolveProviderHeaders(model) answers "which headers does this model's
provider need" directly; isGatewayModel is private again.
The generic fetch decoration moves from the sandbox-named
withSandboxUserAgent to withPackageUserAgent in internal/user-agent.ts
(the sandbox binding and the gateway both wrap it). Its default now
resolves globalThis.fetch per request instead of capturing it at wrap
time, so globally installed fetch instrumentation still applies.
Signed-off-by: Rui Conti <ruiconti@gmail.com>
The world-wiring branches built their return values from inline
expressions and join("\n") arrays. Name the intermediates and write the
generated snippets as leading-newline template literals (trimStart keeps
the emitted text starting at the statement), so each branch reads as: the
specifiers, the code it emits, the wiring object.
Generated output is byte-identical for all three branches (verified by
rendering the HEAD version and this one against the same inputs).
Signed-off-by: Rui Conti <ruiconti@gmail.com>
withPackageUserAgent resolves globalThis.fetch per request when no inner
fetch is given, so later-installed global fetch instrumentation still
applies. Passing globalThis.fetch explicitly here captured it at
options-build time, quietly opting the sandbox path out of that contract
while the gateway path honored it.
Signed-off-by: Rui Conti <ruiconti@gmail.com>
…ever casts
ai/test's mock satisfies the LanguageModel contract, so the
resolveProviderHeaders tests no longer need to cast partial objects.
Same pattern tool-loop.test.ts already uses.
Signed-off-by: Rui Conti <ruiconti@gmail.com>
@vercel
vercelBottemporarily deployed to Preview – eve-docs-1644 July 20, 2026 06:51 Inactive
@vercel
vercelBottemporarily deployed to Preview – eve-docs-4759 July 20, 2026 06:51 Inactive
@ruiconti
ruiconti marked this pull request as ready for review July 20, 2026 15:20
Comment threadpackages/eve/src/compiler/model-catalog.ts Outdated
Comment on lines +5 to +6
const { name, version } = resolveInstalledPackageInfo();
return `${name}/${version}`;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we include agent name as well?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can infer project via deploymentId which is already part of User-Agent. Unless you were thinking of some other use for it

getVercelGatewayFetch() mirrored the Sandbox binding's factory shape, but
unlike getVercelSandboxFetch(createOptions) it had nothing to construct —
call sites read getVercelGatewayFetch()(url). withPackageUserAgent
late-binds globalThis.fetch per request, so a module-level const is safe
and the call sites become plain vercelGatewayFetch(url).
Signed-off-by: Rui Conti <ruiconti@gmail.com>
…ification
Signed-off-by: Rui Conti <ruiconti@gmail.com>
# Conflicts:
#	packages/eve/src/setup/boxes/select-model.test.ts
#	packages/eve/src/setup/boxes/select-model.ts
@AndrewBarba
AndrewBarba enabled auto-merge (squash) July 20, 2026 23:49
@AndrewBarba
AndrewBarba merged commit 938ef92 into mainJul 21, 2026
139 of 152 checks passed
@AndrewBarba
AndrewBarba deleted the rui/eve-service-identification branch July 21, 2026 00:03
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@ruiconti@AndrewBarba@ctgowrie
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
feat(eve): identify eve on AI Gateway, Workflow, and Sandbox requests by ruiconti · Pull Request #939 · vercel/eve · GitHub
Skip to content

feat(eve): identify eve on AI Gateway, Workflow, and Sandbox requests - #939

Merged
AndrewBarba merged 11 commits into
mainfrom
rui/eve-service-identification
Jul 21, 2026
Merged

feat(eve): identify eve on AI Gateway, Workflow, and Sandbox requests#939
AndrewBarba merged 11 commits into
mainfrom
rui/eve-service-identification

Conversation

@ruiconti

@ruicontiruiconti commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

Vercel services can't tell eve traffic from any other AI SDK app today. This appends an eve/<installed version> User-Agent product token to every service request eve makes, so receivers can attribute traffic to eve and its version — segmenting by framework during incidents and, later, controlling traffic keyed on the same token.

What

  • internal/user-agent.ts: builds the eve/<version> product token, appends it to a Headers without touching existing products (idempotent, space-joined per the RFC 9110 UA grammar — not Headers.append(), whose comma-combination breaks whitespace-delimited parsers), and exposes withPackageUserAgent(fetch), the generic UA-decorating fetch wrapper both the Gateway and Sandbox transports build on.
  • internal/gateway.ts owns the Gateway transport surface: the /v1/models and /v1/models/catalog URLs, getVercelGatewayFetch() (a UA-decorated fetch, mirroring the Sandbox binding's getVercelSandboxFetch), and resolveProviderHeaders(model) — headers for Gateway-routed models (bare ids and gateway.* instances), undefined for direct providers.
  • AI Gateway call sites: tool-loop generation and compaction, autoeval judge calls, model catalog, setup catalog, CLI model lookup, API-key validation — all through the two helpers above; no call site does header plumbing or URL assembly.
  • Workflow: generated world-vercel startup code passes the token via createWorld({ headers }), with the per-world wiring dispatched in one place (resolveWorkflowWorldWiring).
  • Sandbox: the SDK fetch decoration reuses withPackageUserAgent. A separate commit fixes a real gap here: Sandbox.get() lost the custom fetch on the credential-discovery failure path.

Wire format

Captured against a local server through the real ai/@ai-sdk/gateway packages — existing products stay intact:

eve/0.24.6 ai/7.0.26 ai-sdk/provider-utils/5.0.9 runtime/node.js/26

The Workflow leg is inert until a vendored bump

The vendored @workflow/world-vercel@5.0.0-beta.31 overwrites caller User-Agents, so the header this PR passes is dropped on the wire today (requests degrade to current behavior — nothing fails). vercel/workflow#2998 fixes the append; a follow-up bump of the vendored package lights this leg up.

Compaction attribution fix

Gateway attribution headers for compaction were previously computed from the main model; they now derive from the compaction model itself, since the two can differ.

…ery fails
getVercelSandboxGetOptions only attached the fetch override in the
credential-discovery success branch, so on the catch path Sandbox.get()
fell back to the SDK's bare global fetch. Move the fetch into the shared
base options so both branches use it.
Signed-off-by: Rui Conti <ruiconti@gmail.com>
Append an eve/<installed version> User-Agent product token to every
Vercel-service request eve makes, so receiving services can attribute
traffic to eve and its version without new headers or protocols:
- AI Gateway: model generation and compaction (tool-loop), autoeval
judge calls, the model catalog and setup catalog fetches, CLI model
lookup, and API-key validation. Gateway-routed models are detected via
isGatewayModel (bare ids and gateway.* instances).
- Workflow: generated world-vercel startup code passes the token via
createWorld({ headers }). Inert until the vendored @workflow/world-vercel
ships the caller User-Agent append (currently 5.0.0-beta.31, which
discards caller UA) — requests degrade to today's behavior, no failure.
- Sandbox: the SDK fetch decoration is generalized from the eve-specific
helper to appendPackageUserAgent.
The token is appended per the RFC 9110 User-Agent grammar (whitespace-
delimited products), never replacing existing products, idempotent on
re-append. Receivers parse it with whitespace-token scanners, so joining
uses spaces, not Headers.append() comma-combination.
Signed-off-by: Rui Conti <ruiconti@gmail.com>
@vercel

vercelBot commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

ProjectDeploymentActionsUpdated (UTC)
eve-docsReadyReadyPreview, CommentJul 20, 2026 11:50pm
eve-docs-1644ReadyReadyPreview, Comment, Open in v0Jul 20, 2026 11:50pm
eve-docs-4759ReadyReadyPreview, Comment, Open in v0Jul 20, 2026 11:50pm

Request Review

@github-actions

github-actionsBot commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

Bundle + Package Summary: apps/fixtures/weather-agent

Key takeaways

  • No notable deltas vs main (d034e01).

Delta vs main (d034e01)

AreaMetricBaselineCurrentDelta
PackagePacked tarball3.80 MB3.81 MB+636 B ⚠️
PackageUnpacked publish size13.77 MB13.78 MB+3.6 kB ⚠️
PackageInstalled footprint52.88 MB52.89 MB+3.6 kB ⚠️
PackagePublished files27222724+2
PackageInstalled files59625964+2
RuntimeUnique function payloads220
RuntimeTotal function bytes9.75 MB9.75 MB+3 B ⚠️
RuntimePublic routes10100
Changed function payloads vs main (d034e01) (2)
FunctionStatusBaselineCurrentDeltaRoute changes
functions/.well-known/workflow/v1/flow.funcchanged6.28 MB6.28 MB+191 B ⚠️none
functions/__server.funcchanged3.47 MB3.47 MB-188 B ✅none

eve init install

MetricBaselineCurrentDelta
Installed footprint91.29 MB91.29 MB+3.6 kB ⚠️
Installed packages1221220
dependencies440
devDependencies220
Dependency package bytes28.02 MB28.03 MB+3.6 kB ⚠️
devDependency package bytes5.04 MB5.04 MB0 B ➖
Build Metadata
  • Preset: vercel
  • Nitro: nitro@3.0.260610-beta
  • Output directory: apps/fixtures/weather-agent/.vercel/output
  • Build metadata timestamp: 2026-07-20T23:51:17.985Z
  • Route aliases: 10 public, 1 internal (11 total aliases)
  • Vercel routes in config: 11
  • Severity legend: 🔴 dominant/large, 🟠 notable, 🟡 watch, ⚪ small
Package Drill-Down

Package Details

  • Package: eve@0.26.1
  • Package directory: packages/eve
  • Tarball: 3.81 MB (eve-0.26.1.tgz)
  • Unpacked payload: 13.78 MB across 2724 published files
  • Installed footprint: 52.89 MB across 5964 installed files
  • Installed root package: 12.50 MB
  • Installed dependencies: 40.39 MB
  • Runtime dependencies: 1
  • Peer dependencies: 5 (4 optional)

Installed footprint is measured from an isolated temporary npm install of the packed tarball.

Heavy installed dependencies

  • @rolldown/binding-linux-x64-gnu: 18.96 MB (35.8%)
  • eve: 12.50 MB (23.6%)
  • ai: 6.39 MB (12.1%)
  • zod: 5.04 MB (9.5%)
  • nitro: 2.41 MB (4.6%)
Publish payload breakdown
Published file size
🟠 dist/src/compiled/experimental-ai-sdk-code-mo... [###.....................] 1.51 MB 10.9%
🟡 dist/src/compiled/@vercel/sandbox/index.js [#.......................] 622.2 kB 4.5%
🟡 dist/src/compiled/_chunks/workflow/undici-fb5... [#.......................] 502.4 kB 3.6%
🟡 dist/src/compiled/@chat-adapter/slack/index.js [#.......................] 433.3 kB 3.1%
🟡 dist/src/compiled/_chunks/workflow/dist-CSfKN... [#.......................] 277.8 kB 2.0%
🔴 Other published files [########################] 10.44 MB 75.7%
Installed footprint breakdown
Installed package size
🔴 @rolldown/binding-linux-x64-gnu [########################] 18.96 MB 35.8%
🔴 eve [################........] 12.50 MB 23.6%
🔴 ai [########................] 6.39 MB 12.1%
🔴 zod [######..................] 5.04 MB 9.5%
🟠 nitro [###.....................] 2.41 MB 4.6%
🟡 @ai-sdk/provider-utils [#.......................] 847.6 kB 1.6%
🔴 Other installed packages [#########...............] 6.74 MB 12.7%
Runtime dependencies (1)
PackageRangeNotes
nitro3.0.260610-beta
Peer dependencies (5)
PackageRangeNotes
@opentelemetry/api^1.0.0optional peer
aicatalog:
braintrust^3.0.0optional peer
just-bash^3.0.0optional peer
microsandbox^0.5.0optional peer
eve init install drill-down

eve init install details

  • Command: eve init my-agent
  • Package manager: npm
  • Installed footprint: 91.29 MB across 7832 installed files
  • Installed packages: 122 total (116 transitive-only)
  • dependencies: 4 direct packages totaling 28.03 MB
  • devDependencies: 2 direct packages totaling 5.04 MB
  • Other transitive package files: 58.22 MB

Installed footprint is measured from an isolated temporary eve init my-agent using the current packed eve tarball.

Heavy installed dependencies

  • @typescript/typescript-linux-x64: 27.95 MB (30.6%)
  • @rolldown/binding-linux-x64-gnu: 18.96 MB (20.8%)
  • eve: 12.50 MB (13.7%)
  • zod: 9.00 MB (9.9%)
  • ai: 6.39 MB (7.0%)
Installed footprint breakdown
Installed package size
🔴 @typescript/typescript-linux-x64 [########################] 27.95 MB 30.6%
🔴 @rolldown/binding-linux-x64-gnu [################........] 18.96 MB 20.8%
🔴 eve [###########.............] 12.50 MB 13.7%
🔴 zod [########................] 9.00 MB 9.9%
🔴 ai [#####...................] 6.39 MB 7.0%
🟠 @types/node [##......................] 2.54 MB 2.8%
🔴 Other installed packages [############............] 13.95 MB 15.3%
dependencies (4)
PackageRangeInstalled sizeShare
@vercel/connect0.4.0135.4 kB0.1%
ai^7.0.266.39 MB7.0%
evefile:eve-0.26.1.tgz12.50 MB13.7%
zod4.4.39.00 MB9.9%
devDependencies (2)
PackageRangeInstalled sizeShare
@types/node24.x2.54 MB2.8%
typescript7.0.22.50 MB2.7%
Function Drill-Down

Payload Size Graph

Unique function payload size and share of total
🔴 functions/.well-known/workflow/v1/flow.func [########################] 6.28 MB 64.4%
🟠 functions/__server.func [#############...........] 3.47 MB 35.6%

Top Function Payloads

🟠 functions/.well-known/workflow/v1/flow.func • 1 public route • 6.28 MB
MetricValue
Public routes/.well-known/workflow/v1/flow
Runtimenodejs24.x
Handlerindex.mjs
Payload6.28 MB
Function files6.28 MB across 37 files
Traced dependencies0 B
Signal🟠 Bundled file __eve_nitro_handler__.mjs is 2.21 MB (35.2%)

🟠 🔎 Dependency Analysis

📦 Bundled files:

Bundled file size
🟠 __eve_nitro_handler__.mjs [########################] 2.21 MB 35.2%
🟡 _chunks/world-vercel.mjs [#########...............] 826.3 kB 13.2%
🟡 _chunks/sandbox.mjs [########................] 754.9 kB 12.0%
🟡 _libs/@ai-sdk/gateway+[...].mjs [#####...................] 430.4 kB 6.9%
🟡 _libs/zod.mjs [####....................] 376.1 kB 6.0%
🟠 Other bundled files [##################......] 1.68 MB 26.8%

🧾 Vercel Config

{
"handler": "index.mjs",
"launcherType": "Nodejs",
"shouldAddHelpers": false,
"supportsResponseStreaming": true,
"runtime": "nodejs24.x",
"environment": {
"NODE_OPTIONS": "--experimental-require-module"
},
"maxDuration": "max",
"experimentalTriggers": [
{
"type": "queue/v2beta",
"topic": "__eve776561746865722d6167656e74_wkf_workflow_*",
"consumer": "default",
"retryAfterSeconds": 5,
"initialDelaySeconds": 0
}
]
}

🟠 functions/__server.func • 9 public routes, 1 internal alias • 3.47 MB
MetricValue
Public routes/
/eve/v1/callback/[token]
/eve/v1/connections/[name]/callback/[token]
/eve/v1/health
/eve/v1/info
/eve/v1/session
/eve/v1/session/[sessionId]
/eve/v1/session/[sessionId]/cancel
/eve/v1/session/[sessionId]/stream
Internal aliases/__server
Runtimenodejs24.x
Handlerindex.mjs
Payload3.47 MB
Function files3.47 MB across 28 files
Traced dependencies0 B
Signal🟠 Bundled file _chunks/runtime-artifacts.mjs is 949.0 kB (27.3%)

🟠 🔎 Dependency Analysis

📦 Bundled files:

Bundled file size
🟠 _chunks/runtime-artifacts.mjs [########################] 949.0 kB 27.3%
🟠 _chunks/world-vercel.mjs [#####################...] 823.4 kB 23.7%
🟠 _chunks/sandbox.mjs [###################.....] 754.9 kB 21.8%
🟡 _chunks/dist-CSfKNxQW.mjs [#########...............] 348.5 kB 10.0%
⚪ _libs/zod.mjs [###.....................] 114.2 kB 3.3%
🟡 Other bundled files [############............] 480.2 kB 13.8%

🧾 Vercel Config

{
"handler": "index.mjs",
"launcherType": "Nodejs",
"shouldAddHelpers": false,
"supportsResponseStreaming": true,
"runtime": "nodejs24.x"
}

Build Timing: e2e/fixtures/agent-tools-sandbox

This is an informational timing measurement inside eve build, from preflight through publication. Output-size measurement and profile writing are excluded.

Build mode: deployable Vercel build with sandbox template prewarm included.

  • Build pipeline: 2.41 s -> 2.38 s (-36.9 ms) vs main (d034e01).
  • Timing is informational: shared GitHub runners are too variable for a hard timing budget.
Detailed phase timings vs `main (d034e01)`
PhaseBaselineCurrentDelta
extension.check1.1 ms0.9 ms-0.2 ms
project.resolve0.7 ms0.6 ms-0.1 ms
workspace.create0.9 ms0.7 ms-0.2 ms
host.prepare230.6 ms230.3 ms-0.3 ms
vercel.service-prefix.resolve2.1 ms2.1 ms0.0 ms
nitro.app.create24.3 ms24.2 ms-0.1 ms
nitro.app.cache.prepare0.2 ms0.2 ms0.0 ms
nitro.app.prepare0.9 ms0.8 ms-0.1 ms
nitro.app.public-assets0.7 ms0.7 ms0.0 ms
nitro.app.prerender0.5 ms0.5 ms0.0 ms
nitro.app.bundle547.7 ms554.9 ms+7.2 ms
nitro.app.cache.write0.5 ms0.4 ms-0.1 ms
sandbox.prewarm278.3 ms260.6 ms-17.7 ms
nitro.flow.create185.2 ms178.8 ms-6.4 ms
nitro.flow.cache.prepare0.2 ms0.2 ms0.0 ms
nitro.flow.prepare0.9 ms0.9 ms0.0 ms
nitro.flow.public-assets0.2 ms0.2 ms0.0 ms
nitro.flow.prerender0.0 ms0.0 ms0.0 ms
nitro.flow.bundle952.2 ms935.9 ms-16.3 ms
nitro.flow.cache.write0.3 ms0.3 ms0.0 ms
nitro.flow.close0.2 ms0.2 ms0.0 ms
workflow.emit173.9 ms170.9 ms-3.0 ms
agent-summary.emit0.6 ms0.5 ms-0.1 ms
nitro.app.close0.0 ms0.0 ms0.0 ms
output.publish3.7 ms3.7 ms0.0 ms
workspace.remove5.7 ms5.8 ms+0.1 ms

createWorkflowWorldPluginSource encoded the world selection three times: a
nested ternary for the createWorld statement, a repeated condition for the
runtime imports, and another for the vendored module specifier. The pieces
co-vary — a world constructed through an explicit createWorld(config) call
must not import createWorldFromModule — so hiding that invariant across
three expressions made every new world branch risky to add.
resolveWorkflowWorldWiring now owns all four facts per world; the caller is
pure assembly. Generated output is byte-identical for the world-local,
world-vercel, and passthrough branches (verified by rendering both versions
and comparing).
Signed-off-by: Rui Conti <ruiconti@gmail.com>
gateway.ts exported its internals — buildGatewayURL, addGatewayUA,
buildGatewayUA, isGatewayModel — and every call site reassembled them:
URLs were rebuilt locally, and model-conditional header logic leaked as
isGatewayModel(...) ? Object.fromEntries(addGatewayUA(...)) : undefined.
The module now owns the decisions instead of the parts:
- AI_GATEWAY_MODELS_URL / AI_GATEWAY_MODELS_CATALOG_URL live in gateway.ts.
- getVercelGatewayFetch() returns a UA-decorated fetch, mirroring the
Sandbox binding's getVercelSandboxFetch — call sites get a transport,
not header plumbing. validate-gateway-key routes its provider fetch
through it instead of construction headers.
- resolveProviderHeaders(model) answers "which headers does this model's
provider need" directly; isGatewayModel is private again.
The generic fetch decoration moves from the sandbox-named
withSandboxUserAgent to withPackageUserAgent in internal/user-agent.ts
(the sandbox binding and the gateway both wrap it). Its default now
resolves globalThis.fetch per request instead of capturing it at wrap
time, so globally installed fetch instrumentation still applies.
Signed-off-by: Rui Conti <ruiconti@gmail.com>
The world-wiring branches built their return values from inline
expressions and join("\n") arrays. Name the intermediates and write the
generated snippets as leading-newline template literals (trimStart keeps
the emitted text starting at the statement), so each branch reads as: the
specifiers, the code it emits, the wiring object.
Generated output is byte-identical for all three branches (verified by
rendering the HEAD version and this one against the same inputs).
Signed-off-by: Rui Conti <ruiconti@gmail.com>
withPackageUserAgent resolves globalThis.fetch per request when no inner
fetch is given, so later-installed global fetch instrumentation still
applies. Passing globalThis.fetch explicitly here captured it at
options-build time, quietly opting the sandbox path out of that contract
while the gateway path honored it.
Signed-off-by: Rui Conti <ruiconti@gmail.com>
…ever casts
ai/test's mock satisfies the LanguageModel contract, so the
resolveProviderHeaders tests no longer need to cast partial objects.
Same pattern tool-loop.test.ts already uses.
Signed-off-by: Rui Conti <ruiconti@gmail.com>
@vercel
vercelBottemporarily deployed to Preview – eve-docs-1644 July 20, 2026 06:51 Inactive
@vercel
vercelBottemporarily deployed to Preview – eve-docs-4759 July 20, 2026 06:51 Inactive
@ruiconti
ruiconti marked this pull request as ready for review July 20, 2026 15:20
Comment threadpackages/eve/src/compiler/model-catalog.ts Outdated
Comment on lines +5 to +6
const { name, version } = resolveInstalledPackageInfo();
return `${name}/${version}`;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we include agent name as well?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can infer project via deploymentId which is already part of User-Agent. Unless you were thinking of some other use for it

getVercelGatewayFetch() mirrored the Sandbox binding's factory shape, but
unlike getVercelSandboxFetch(createOptions) it had nothing to construct —
call sites read getVercelGatewayFetch()(url). withPackageUserAgent
late-binds globalThis.fetch per request, so a module-level const is safe
and the call sites become plain vercelGatewayFetch(url).
Signed-off-by: Rui Conti <ruiconti@gmail.com>
…ification
Signed-off-by: Rui Conti <ruiconti@gmail.com>
# Conflicts:
#	packages/eve/src/setup/boxes/select-model.test.ts
#	packages/eve/src/setup/boxes/select-model.ts
@AndrewBarba
AndrewBarba enabled auto-merge (squash) July 20, 2026 23:49
@AndrewBarba
AndrewBarba merged commit 938ef92 into mainJul 21, 2026
139 of 152 checks passed
@AndrewBarba
AndrewBarba deleted the rui/eve-service-identification branch July 21, 2026 00:03
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@ruiconti@AndrewBarba@ctgowrie
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' feat(eve): identify eve on AI Gateway, Workflow, and Sandbox requests by ruiconti · Pull Request #939 · vercel/eve · GitHub
Skip to content

feat(eve): identify eve on AI Gateway, Workflow, and Sandbox requests - #939

Merged
AndrewBarba merged 11 commits into
mainfrom
rui/eve-service-identification
Jul 21, 2026
Merged

feat(eve): identify eve on AI Gateway, Workflow, and Sandbox requests#939
AndrewBarba merged 11 commits into
mainfrom
rui/eve-service-identification

Conversation

@ruiconti

@ruicontiruiconti commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

Vercel services can't tell eve traffic from any other AI SDK app today. This appends an eve/<installed version> User-Agent product token to every service request eve makes, so receivers can attribute traffic to eve and its version — segmenting by framework during incidents and, later, controlling traffic keyed on the same token.

What

  • internal/user-agent.ts: builds the eve/<version> product token, appends it to a Headers without touching existing products (idempotent, space-joined per the RFC 9110 UA grammar — not Headers.append(), whose comma-combination breaks whitespace-delimited parsers), and exposes withPackageUserAgent(fetch), the generic UA-decorating fetch wrapper both the Gateway and Sandbox transports build on.
  • internal/gateway.ts owns the Gateway transport surface: the /v1/models and /v1/models/catalog URLs, getVercelGatewayFetch() (a UA-decorated fetch, mirroring the Sandbox binding's getVercelSandboxFetch), and resolveProviderHeaders(model) — headers for Gateway-routed models (bare ids and gateway.* instances), undefined for direct providers.
  • AI Gateway call sites: tool-loop generation and compaction, autoeval judge calls, model catalog, setup catalog, CLI model lookup, API-key validation — all through the two helpers above; no call site does header plumbing or URL assembly.
  • Workflow: generated world-vercel startup code passes the token via createWorld({ headers }), with the per-world wiring dispatched in one place (resolveWorkflowWorldWiring).
  • Sandbox: the SDK fetch decoration reuses withPackageUserAgent. A separate commit fixes a real gap here: Sandbox.get() lost the custom fetch on the credential-discovery failure path.

Wire format

Captured against a local server through the real ai/@ai-sdk/gateway packages — existing products stay intact:

eve/0.24.6 ai/7.0.26 ai-sdk/provider-utils/5.0.9 runtime/node.js/26

The Workflow leg is inert until a vendored bump

The vendored @workflow/world-vercel@5.0.0-beta.31 overwrites caller User-Agents, so the header this PR passes is dropped on the wire today (requests degrade to current behavior — nothing fails). vercel/workflow#2998 fixes the append; a follow-up bump of the vendored package lights this leg up.

Compaction attribution fix

Gateway attribution headers for compaction were previously computed from the main model; they now derive from the compaction model itself, since the two can differ.

…ery fails
getVercelSandboxGetOptions only attached the fetch override in the
credential-discovery success branch, so on the catch path Sandbox.get()
fell back to the SDK's bare global fetch. Move the fetch into the shared
base options so both branches use it.
Signed-off-by: Rui Conti <ruiconti@gmail.com>
Append an eve/<installed version> User-Agent product token to every
Vercel-service request eve makes, so receiving services can attribute
traffic to eve and its version without new headers or protocols:
- AI Gateway: model generation and compaction (tool-loop), autoeval
judge calls, the model catalog and setup catalog fetches, CLI model
lookup, and API-key validation. Gateway-routed models are detected via
isGatewayModel (bare ids and gateway.* instances).
- Workflow: generated world-vercel startup code passes the token via
createWorld({ headers }). Inert until the vendored @workflow/world-vercel
ships the caller User-Agent append (currently 5.0.0-beta.31, which
discards caller UA) — requests degrade to today's behavior, no failure.
- Sandbox: the SDK fetch decoration is generalized from the eve-specific
helper to appendPackageUserAgent.
The token is appended per the RFC 9110 User-Agent grammar (whitespace-
delimited products), never replacing existing products, idempotent on
re-append. Receivers parse it with whitespace-token scanners, so joining
uses spaces, not Headers.append() comma-combination.
Signed-off-by: Rui Conti <ruiconti@gmail.com>
@vercel

vercelBot commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

ProjectDeploymentActionsUpdated (UTC)
eve-docsReadyReadyPreview, CommentJul 20, 2026 11:50pm
eve-docs-1644ReadyReadyPreview, Comment, Open in v0Jul 20, 2026 11:50pm
eve-docs-4759ReadyReadyPreview, Comment, Open in v0Jul 20, 2026 11:50pm

Request Review

@github-actions

github-actionsBot commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

Bundle + Package Summary: apps/fixtures/weather-agent

Key takeaways

  • No notable deltas vs main (d034e01).

Delta vs main (d034e01)

AreaMetricBaselineCurrentDelta
PackagePacked tarball3.80 MB3.81 MB+636 B ⚠️
PackageUnpacked publish size13.77 MB13.78 MB+3.6 kB ⚠️
PackageInstalled footprint52.88 MB52.89 MB+3.6 kB ⚠️
PackagePublished files27222724+2
PackageInstalled files59625964+2
RuntimeUnique function payloads220
RuntimeTotal function bytes9.75 MB9.75 MB+3 B ⚠️
RuntimePublic routes10100
Changed function payloads vs main (d034e01) (2)
FunctionStatusBaselineCurrentDeltaRoute changes
functions/.well-known/workflow/v1/flow.funcchanged6.28 MB6.28 MB+191 B ⚠️none
functions/__server.funcchanged3.47 MB3.47 MB-188 B ✅none

eve init install

MetricBaselineCurrentDelta
Installed footprint91.29 MB91.29 MB+3.6 kB ⚠️
Installed packages1221220
dependencies440
devDependencies220
Dependency package bytes28.02 MB28.03 MB+3.6 kB ⚠️
devDependency package bytes5.04 MB5.04 MB0 B ➖
Build Metadata
  • Preset: vercel
  • Nitro: nitro@3.0.260610-beta
  • Output directory: apps/fixtures/weather-agent/.vercel/output
  • Build metadata timestamp: 2026-07-20T23:51:17.985Z
  • Route aliases: 10 public, 1 internal (11 total aliases)
  • Vercel routes in config: 11
  • Severity legend: 🔴 dominant/large, 🟠 notable, 🟡 watch, ⚪ small
Package Drill-Down

Package Details

  • Package: eve@0.26.1
  • Package directory: packages/eve
  • Tarball: 3.81 MB (eve-0.26.1.tgz)
  • Unpacked payload: 13.78 MB across 2724 published files
  • Installed footprint: 52.89 MB across 5964 installed files
  • Installed root package: 12.50 MB
  • Installed dependencies: 40.39 MB
  • Runtime dependencies: 1
  • Peer dependencies: 5 (4 optional)

Installed footprint is measured from an isolated temporary npm install of the packed tarball.

Heavy installed dependencies

  • @rolldown/binding-linux-x64-gnu: 18.96 MB (35.8%)
  • eve: 12.50 MB (23.6%)
  • ai: 6.39 MB (12.1%)
  • zod: 5.04 MB (9.5%)
  • nitro: 2.41 MB (4.6%)
Publish payload breakdown
Published file size
🟠 dist/src/compiled/experimental-ai-sdk-code-mo... [###.....................] 1.51 MB 10.9%
🟡 dist/src/compiled/@vercel/sandbox/index.js [#.......................] 622.2 kB 4.5%
🟡 dist/src/compiled/_chunks/workflow/undici-fb5... [#.......................] 502.4 kB 3.6%
🟡 dist/src/compiled/@chat-adapter/slack/index.js [#.......................] 433.3 kB 3.1%
🟡 dist/src/compiled/_chunks/workflow/dist-CSfKN... [#.......................] 277.8 kB 2.0%
🔴 Other published files [########################] 10.44 MB 75.7%
Installed footprint breakdown
Installed package size
🔴 @rolldown/binding-linux-x64-gnu [########################] 18.96 MB 35.8%
🔴 eve [################........] 12.50 MB 23.6%
🔴 ai [########................] 6.39 MB 12.1%
🔴 zod [######..................] 5.04 MB 9.5%
🟠 nitro [###.....................] 2.41 MB 4.6%
🟡 @ai-sdk/provider-utils [#.......................] 847.6 kB 1.6%
🔴 Other installed packages [#########...............] 6.74 MB 12.7%
Runtime dependencies (1)
PackageRangeNotes
nitro3.0.260610-beta
Peer dependencies (5)
PackageRangeNotes
@opentelemetry/api^1.0.0optional peer
aicatalog:
braintrust^3.0.0optional peer
just-bash^3.0.0optional peer
microsandbox^0.5.0optional peer
eve init install drill-down

eve init install details

  • Command: eve init my-agent
  • Package manager: npm
  • Installed footprint: 91.29 MB across 7832 installed files
  • Installed packages: 122 total (116 transitive-only)
  • dependencies: 4 direct packages totaling 28.03 MB
  • devDependencies: 2 direct packages totaling 5.04 MB
  • Other transitive package files: 58.22 MB

Installed footprint is measured from an isolated temporary eve init my-agent using the current packed eve tarball.

Heavy installed dependencies

  • @typescript/typescript-linux-x64: 27.95 MB (30.6%)
  • @rolldown/binding-linux-x64-gnu: 18.96 MB (20.8%)
  • eve: 12.50 MB (13.7%)
  • zod: 9.00 MB (9.9%)
  • ai: 6.39 MB (7.0%)
Installed footprint breakdown
Installed package size
🔴 @typescript/typescript-linux-x64 [########################] 27.95 MB 30.6%
🔴 @rolldown/binding-linux-x64-gnu [################........] 18.96 MB 20.8%
🔴 eve [###########.............] 12.50 MB 13.7%
🔴 zod [########................] 9.00 MB 9.9%
🔴 ai [#####...................] 6.39 MB 7.0%
🟠 @types/node [##......................] 2.54 MB 2.8%
🔴 Other installed packages [############............] 13.95 MB 15.3%
dependencies (4)
PackageRangeInstalled sizeShare
@vercel/connect0.4.0135.4 kB0.1%
ai^7.0.266.39 MB7.0%
evefile:eve-0.26.1.tgz12.50 MB13.7%
zod4.4.39.00 MB9.9%
devDependencies (2)
PackageRangeInstalled sizeShare
@types/node24.x2.54 MB2.8%
typescript7.0.22.50 MB2.7%
Function Drill-Down

Payload Size Graph

Unique function payload size and share of total
🔴 functions/.well-known/workflow/v1/flow.func [########################] 6.28 MB 64.4%
🟠 functions/__server.func [#############...........] 3.47 MB 35.6%

Top Function Payloads

🟠 functions/.well-known/workflow/v1/flow.func • 1 public route • 6.28 MB
MetricValue
Public routes/.well-known/workflow/v1/flow
Runtimenodejs24.x
Handlerindex.mjs
Payload6.28 MB
Function files6.28 MB across 37 files
Traced dependencies0 B
Signal🟠 Bundled file __eve_nitro_handler__.mjs is 2.21 MB (35.2%)

🟠 🔎 Dependency Analysis

📦 Bundled files:

Bundled file size
🟠 __eve_nitro_handler__.mjs [########################] 2.21 MB 35.2%
🟡 _chunks/world-vercel.mjs [#########...............] 826.3 kB 13.2%
🟡 _chunks/sandbox.mjs [########................] 754.9 kB 12.0%
🟡 _libs/@ai-sdk/gateway+[...].mjs [#####...................] 430.4 kB 6.9%
🟡 _libs/zod.mjs [####....................] 376.1 kB 6.0%
🟠 Other bundled files [##################......] 1.68 MB 26.8%

🧾 Vercel Config

{
"handler": "index.mjs",
"launcherType": "Nodejs",
"shouldAddHelpers": false,
"supportsResponseStreaming": true,
"runtime": "nodejs24.x",
"environment": {
"NODE_OPTIONS": "--experimental-require-module"
},
"maxDuration": "max",
"experimentalTriggers": [
{
"type": "queue/v2beta",
"topic": "__eve776561746865722d6167656e74_wkf_workflow_*",
"consumer": "default",
"retryAfterSeconds": 5,
"initialDelaySeconds": 0
}
]
}

🟠 functions/__server.func • 9 public routes, 1 internal alias • 3.47 MB
MetricValue
Public routes/
/eve/v1/callback/[token]
/eve/v1/connections/[name]/callback/[token]
/eve/v1/health
/eve/v1/info
/eve/v1/session
/eve/v1/session/[sessionId]
/eve/v1/session/[sessionId]/cancel
/eve/v1/session/[sessionId]/stream
Internal aliases/__server
Runtimenodejs24.x
Handlerindex.mjs
Payload3.47 MB
Function files3.47 MB across 28 files
Traced dependencies0 B
Signal🟠 Bundled file _chunks/runtime-artifacts.mjs is 949.0 kB (27.3%)

🟠 🔎 Dependency Analysis

📦 Bundled files:

Bundled file size
🟠 _chunks/runtime-artifacts.mjs [########################] 949.0 kB 27.3%
🟠 _chunks/world-vercel.mjs [#####################...] 823.4 kB 23.7%
🟠 _chunks/sandbox.mjs [###################.....] 754.9 kB 21.8%
🟡 _chunks/dist-CSfKNxQW.mjs [#########...............] 348.5 kB 10.0%
⚪ _libs/zod.mjs [###.....................] 114.2 kB 3.3%
🟡 Other bundled files [############............] 480.2 kB 13.8%

🧾 Vercel Config

{
"handler": "index.mjs",
"launcherType": "Nodejs",
"shouldAddHelpers": false,
"supportsResponseStreaming": true,
"runtime": "nodejs24.x"
}

Build Timing: e2e/fixtures/agent-tools-sandbox

This is an informational timing measurement inside eve build, from preflight through publication. Output-size measurement and profile writing are excluded.

Build mode: deployable Vercel build with sandbox template prewarm included.

  • Build pipeline: 2.41 s -> 2.38 s (-36.9 ms) vs main (d034e01).
  • Timing is informational: shared GitHub runners are too variable for a hard timing budget.
Detailed phase timings vs `main (d034e01)`
PhaseBaselineCurrentDelta
extension.check1.1 ms0.9 ms-0.2 ms
project.resolve0.7 ms0.6 ms-0.1 ms
workspace.create0.9 ms0.7 ms-0.2 ms
host.prepare230.6 ms230.3 ms-0.3 ms
vercel.service-prefix.resolve2.1 ms2.1 ms0.0 ms
nitro.app.create24.3 ms24.2 ms-0.1 ms
nitro.app.cache.prepare0.2 ms0.2 ms0.0 ms
nitro.app.prepare0.9 ms0.8 ms-0.1 ms
nitro.app.public-assets0.7 ms0.7 ms0.0 ms
nitro.app.prerender0.5 ms0.5 ms0.0 ms
nitro.app.bundle547.7 ms554.9 ms+7.2 ms
nitro.app.cache.write0.5 ms0.4 ms-0.1 ms
sandbox.prewarm278.3 ms260.6 ms-17.7 ms
nitro.flow.create185.2 ms178.8 ms-6.4 ms
nitro.flow.cache.prepare0.2 ms0.2 ms0.0 ms
nitro.flow.prepare0.9 ms0.9 ms0.0 ms
nitro.flow.public-assets0.2 ms0.2 ms0.0 ms
nitro.flow.prerender0.0 ms0.0 ms0.0 ms
nitro.flow.bundle952.2 ms935.9 ms-16.3 ms
nitro.flow.cache.write0.3 ms0.3 ms0.0 ms
nitro.flow.close0.2 ms0.2 ms0.0 ms
workflow.emit173.9 ms170.9 ms-3.0 ms
agent-summary.emit0.6 ms0.5 ms-0.1 ms
nitro.app.close0.0 ms0.0 ms0.0 ms
output.publish3.7 ms3.7 ms0.0 ms
workspace.remove5.7 ms5.8 ms+0.1 ms

createWorkflowWorldPluginSource encoded the world selection three times: a
nested ternary for the createWorld statement, a repeated condition for the
runtime imports, and another for the vendored module specifier. The pieces
co-vary — a world constructed through an explicit createWorld(config) call
must not import createWorldFromModule — so hiding that invariant across
three expressions made every new world branch risky to add.
resolveWorkflowWorldWiring now owns all four facts per world; the caller is
pure assembly. Generated output is byte-identical for the world-local,
world-vercel, and passthrough branches (verified by rendering both versions
and comparing).
Signed-off-by: Rui Conti <ruiconti@gmail.com>
gateway.ts exported its internals — buildGatewayURL, addGatewayUA,
buildGatewayUA, isGatewayModel — and every call site reassembled them:
URLs were rebuilt locally, and model-conditional header logic leaked as
isGatewayModel(...) ? Object.fromEntries(addGatewayUA(...)) : undefined.
The module now owns the decisions instead of the parts:
- AI_GATEWAY_MODELS_URL / AI_GATEWAY_MODELS_CATALOG_URL live in gateway.ts.
- getVercelGatewayFetch() returns a UA-decorated fetch, mirroring the
Sandbox binding's getVercelSandboxFetch — call sites get a transport,
not header plumbing. validate-gateway-key routes its provider fetch
through it instead of construction headers.
- resolveProviderHeaders(model) answers "which headers does this model's
provider need" directly; isGatewayModel is private again.
The generic fetch decoration moves from the sandbox-named
withSandboxUserAgent to withPackageUserAgent in internal/user-agent.ts
(the sandbox binding and the gateway both wrap it). Its default now
resolves globalThis.fetch per request instead of capturing it at wrap
time, so globally installed fetch instrumentation still applies.
Signed-off-by: Rui Conti <ruiconti@gmail.com>
The world-wiring branches built their return values from inline
expressions and join("\n") arrays. Name the intermediates and write the
generated snippets as leading-newline template literals (trimStart keeps
the emitted text starting at the statement), so each branch reads as: the
specifiers, the code it emits, the wiring object.
Generated output is byte-identical for all three branches (verified by
rendering the HEAD version and this one against the same inputs).
Signed-off-by: Rui Conti <ruiconti@gmail.com>
withPackageUserAgent resolves globalThis.fetch per request when no inner
fetch is given, so later-installed global fetch instrumentation still
applies. Passing globalThis.fetch explicitly here captured it at
options-build time, quietly opting the sandbox path out of that contract
while the gateway path honored it.
Signed-off-by: Rui Conti <ruiconti@gmail.com>
…ever casts
ai/test's mock satisfies the LanguageModel contract, so the
resolveProviderHeaders tests no longer need to cast partial objects.
Same pattern tool-loop.test.ts already uses.
Signed-off-by: Rui Conti <ruiconti@gmail.com>
@vercel
vercelBottemporarily deployed to Preview – eve-docs-1644 July 20, 2026 06:51 Inactive
@vercel
vercelBottemporarily deployed to Preview – eve-docs-4759 July 20, 2026 06:51 Inactive
@ruiconti
ruiconti marked this pull request as ready for review July 20, 2026 15:20
Comment threadpackages/eve/src/compiler/model-catalog.ts Outdated
Comment on lines +5 to +6
const { name, version } = resolveInstalledPackageInfo();
return `${name}/${version}`;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we include agent name as well?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can infer project via deploymentId which is already part of User-Agent. Unless you were thinking of some other use for it

getVercelGatewayFetch() mirrored the Sandbox binding's factory shape, but
unlike getVercelSandboxFetch(createOptions) it had nothing to construct —
call sites read getVercelGatewayFetch()(url). withPackageUserAgent
late-binds globalThis.fetch per request, so a module-level const is safe
and the call sites become plain vercelGatewayFetch(url).
Signed-off-by: Rui Conti <ruiconti@gmail.com>
…ification
Signed-off-by: Rui Conti <ruiconti@gmail.com>
# Conflicts:
#	packages/eve/src/setup/boxes/select-model.test.ts
#	packages/eve/src/setup/boxes/select-model.ts
@AndrewBarba
AndrewBarba enabled auto-merge (squash) July 20, 2026 23:49
@AndrewBarba
AndrewBarba merged commit 938ef92 into mainJul 21, 2026
139 of 152 checks passed
@AndrewBarba
AndrewBarba deleted the rui/eve-service-identification branch July 21, 2026 00:03
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@ruiconti@AndrewBarba@ctgowrie
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' feat(eve): identify eve on AI Gateway, Workflow, and Sandbox requests by ruiconti · Pull Request #939 · vercel/eve · GitHub
Skip to content

feat(eve): identify eve on AI Gateway, Workflow, and Sandbox requests - #939

Merged
AndrewBarba merged 11 commits into
mainfrom
rui/eve-service-identification
Jul 21, 2026
Merged

feat(eve): identify eve on AI Gateway, Workflow, and Sandbox requests#939
AndrewBarba merged 11 commits into
mainfrom
rui/eve-service-identification

Conversation

@ruiconti

@ruicontiruiconti commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

Vercel services can't tell eve traffic from any other AI SDK app today. This appends an eve/<installed version> User-Agent product token to every service request eve makes, so receivers can attribute traffic to eve and its version — segmenting by framework during incidents and, later, controlling traffic keyed on the same token.

What

  • internal/user-agent.ts: builds the eve/<version> product token, appends it to a Headers without touching existing products (idempotent, space-joined per the RFC 9110 UA grammar — not Headers.append(), whose comma-combination breaks whitespace-delimited parsers), and exposes withPackageUserAgent(fetch), the generic UA-decorating fetch wrapper both the Gateway and Sandbox transports build on.
  • internal/gateway.ts owns the Gateway transport surface: the /v1/models and /v1/models/catalog URLs, getVercelGatewayFetch() (a UA-decorated fetch, mirroring the Sandbox binding's getVercelSandboxFetch), and resolveProviderHeaders(model) — headers for Gateway-routed models (bare ids and gateway.* instances), undefined for direct providers.
  • AI Gateway call sites: tool-loop generation and compaction, autoeval judge calls, model catalog, setup catalog, CLI model lookup, API-key validation — all through the two helpers above; no call site does header plumbing or URL assembly.
  • Workflow: generated world-vercel startup code passes the token via createWorld({ headers }), with the per-world wiring dispatched in one place (resolveWorkflowWorldWiring).
  • Sandbox: the SDK fetch decoration reuses withPackageUserAgent. A separate commit fixes a real gap here: Sandbox.get() lost the custom fetch on the credential-discovery failure path.

Wire format

Captured against a local server through the real ai/@ai-sdk/gateway packages — existing products stay intact:

eve/0.24.6 ai/7.0.26 ai-sdk/provider-utils/5.0.9 runtime/node.js/26

The Workflow leg is inert until a vendored bump

The vendored @workflow/world-vercel@5.0.0-beta.31 overwrites caller User-Agents, so the header this PR passes is dropped on the wire today (requests degrade to current behavior — nothing fails). vercel/workflow#2998 fixes the append; a follow-up bump of the vendored package lights this leg up.

Compaction attribution fix

Gateway attribution headers for compaction were previously computed from the main model; they now derive from the compaction model itself, since the two can differ.

…ery fails
getVercelSandboxGetOptions only attached the fetch override in the
credential-discovery success branch, so on the catch path Sandbox.get()
fell back to the SDK's bare global fetch. Move the fetch into the shared
base options so both branches use it.
Signed-off-by: Rui Conti <ruiconti@gmail.com>
Append an eve/<installed version> User-Agent product token to every
Vercel-service request eve makes, so receiving services can attribute
traffic to eve and its version without new headers or protocols:
- AI Gateway: model generation and compaction (tool-loop), autoeval
judge calls, the model catalog and setup catalog fetches, CLI model
lookup, and API-key validation. Gateway-routed models are detected via
isGatewayModel (bare ids and gateway.* instances).
- Workflow: generated world-vercel startup code passes the token via
createWorld({ headers }). Inert until the vendored @workflow/world-vercel
ships the caller User-Agent append (currently 5.0.0-beta.31, which
discards caller UA) — requests degrade to today's behavior, no failure.
- Sandbox: the SDK fetch decoration is generalized from the eve-specific
helper to appendPackageUserAgent.
The token is appended per the RFC 9110 User-Agent grammar (whitespace-
delimited products), never replacing existing products, idempotent on
re-append. Receivers parse it with whitespace-token scanners, so joining
uses spaces, not Headers.append() comma-combination.
Signed-off-by: Rui Conti <ruiconti@gmail.com>
@vercel

vercelBot commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

ProjectDeploymentActionsUpdated (UTC)
eve-docsReadyReadyPreview, CommentJul 20, 2026 11:50pm
eve-docs-1644ReadyReadyPreview, Comment, Open in v0Jul 20, 2026 11:50pm
eve-docs-4759ReadyReadyPreview, Comment, Open in v0Jul 20, 2026 11:50pm

Request Review

@github-actions

github-actionsBot commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

Bundle + Package Summary: apps/fixtures/weather-agent

Key takeaways

  • No notable deltas vs main (d034e01).

Delta vs main (d034e01)

AreaMetricBaselineCurrentDelta
PackagePacked tarball3.80 MB3.81 MB+636 B ⚠️
PackageUnpacked publish size13.77 MB13.78 MB+3.6 kB ⚠️
PackageInstalled footprint52.88 MB52.89 MB+3.6 kB ⚠️
PackagePublished files27222724+2
PackageInstalled files59625964+2
RuntimeUnique function payloads220
RuntimeTotal function bytes9.75 MB9.75 MB+3 B ⚠️
RuntimePublic routes10100
Changed function payloads vs main (d034e01) (2)
FunctionStatusBaselineCurrentDeltaRoute changes
functions/.well-known/workflow/v1/flow.funcchanged6.28 MB6.28 MB+191 B ⚠️none
functions/__server.funcchanged3.47 MB3.47 MB-188 B ✅none

eve init install

MetricBaselineCurrentDelta
Installed footprint91.29 MB91.29 MB+3.6 kB ⚠️
Installed packages1221220
dependencies440
devDependencies220
Dependency package bytes28.02 MB28.03 MB+3.6 kB ⚠️
devDependency package bytes5.04 MB5.04 MB0 B ➖
Build Metadata
  • Preset: vercel
  • Nitro: nitro@3.0.260610-beta
  • Output directory: apps/fixtures/weather-agent/.vercel/output
  • Build metadata timestamp: 2026-07-20T23:51:17.985Z
  • Route aliases: 10 public, 1 internal (11 total aliases)
  • Vercel routes in config: 11
  • Severity legend: 🔴 dominant/large, 🟠 notable, 🟡 watch, ⚪ small
Package Drill-Down

Package Details

  • Package: eve@0.26.1
  • Package directory: packages/eve
  • Tarball: 3.81 MB (eve-0.26.1.tgz)
  • Unpacked payload: 13.78 MB across 2724 published files
  • Installed footprint: 52.89 MB across 5964 installed files
  • Installed root package: 12.50 MB
  • Installed dependencies: 40.39 MB
  • Runtime dependencies: 1
  • Peer dependencies: 5 (4 optional)

Installed footprint is measured from an isolated temporary npm install of the packed tarball.

Heavy installed dependencies

  • @rolldown/binding-linux-x64-gnu: 18.96 MB (35.8%)
  • eve: 12.50 MB (23.6%)
  • ai: 6.39 MB (12.1%)
  • zod: 5.04 MB (9.5%)
  • nitro: 2.41 MB (4.6%)
Publish payload breakdown
Published file size
🟠 dist/src/compiled/experimental-ai-sdk-code-mo... [###.....................] 1.51 MB 10.9%
🟡 dist/src/compiled/@vercel/sandbox/index.js [#.......................] 622.2 kB 4.5%
🟡 dist/src/compiled/_chunks/workflow/undici-fb5... [#.......................] 502.4 kB 3.6%
🟡 dist/src/compiled/@chat-adapter/slack/index.js [#.......................] 433.3 kB 3.1%
🟡 dist/src/compiled/_chunks/workflow/dist-CSfKN... [#.......................] 277.8 kB 2.0%
🔴 Other published files [########################] 10.44 MB 75.7%
Installed footprint breakdown
Installed package size
🔴 @rolldown/binding-linux-x64-gnu [########################] 18.96 MB 35.8%
🔴 eve [################........] 12.50 MB 23.6%
🔴 ai [########................] 6.39 MB 12.1%
🔴 zod [######..................] 5.04 MB 9.5%
🟠 nitro [###.....................] 2.41 MB 4.6%
🟡 @ai-sdk/provider-utils [#.......................] 847.6 kB 1.6%
🔴 Other installed packages [#########...............] 6.74 MB 12.7%
Runtime dependencies (1)
PackageRangeNotes
nitro3.0.260610-beta
Peer dependencies (5)
PackageRangeNotes
@opentelemetry/api^1.0.0optional peer
aicatalog:
braintrust^3.0.0optional peer
just-bash^3.0.0optional peer
microsandbox^0.5.0optional peer
eve init install drill-down

eve init install details

  • Command: eve init my-agent
  • Package manager: npm
  • Installed footprint: 91.29 MB across 7832 installed files
  • Installed packages: 122 total (116 transitive-only)
  • dependencies: 4 direct packages totaling 28.03 MB
  • devDependencies: 2 direct packages totaling 5.04 MB
  • Other transitive package files: 58.22 MB

Installed footprint is measured from an isolated temporary eve init my-agent using the current packed eve tarball.

Heavy installed dependencies

  • @typescript/typescript-linux-x64: 27.95 MB (30.6%)
  • @rolldown/binding-linux-x64-gnu: 18.96 MB (20.8%)
  • eve: 12.50 MB (13.7%)
  • zod: 9.00 MB (9.9%)
  • ai: 6.39 MB (7.0%)
Installed footprint breakdown
Installed package size
🔴 @typescript/typescript-linux-x64 [########################] 27.95 MB 30.6%
🔴 @rolldown/binding-linux-x64-gnu [################........] 18.96 MB 20.8%
🔴 eve [###########.............] 12.50 MB 13.7%
🔴 zod [########................] 9.00 MB 9.9%
🔴 ai [#####...................] 6.39 MB 7.0%
🟠 @types/node [##......................] 2.54 MB 2.8%
🔴 Other installed packages [############............] 13.95 MB 15.3%
dependencies (4)
PackageRangeInstalled sizeShare
@vercel/connect0.4.0135.4 kB0.1%
ai^7.0.266.39 MB7.0%
evefile:eve-0.26.1.tgz12.50 MB13.7%
zod4.4.39.00 MB9.9%
devDependencies (2)
PackageRangeInstalled sizeShare
@types/node24.x2.54 MB2.8%
typescript7.0.22.50 MB2.7%
Function Drill-Down

Payload Size Graph

Unique function payload size and share of total
🔴 functions/.well-known/workflow/v1/flow.func [########################] 6.28 MB 64.4%
🟠 functions/__server.func [#############...........] 3.47 MB 35.6%

Top Function Payloads

🟠 functions/.well-known/workflow/v1/flow.func • 1 public route • 6.28 MB
MetricValue
Public routes/.well-known/workflow/v1/flow
Runtimenodejs24.x
Handlerindex.mjs
Payload6.28 MB
Function files6.28 MB across 37 files
Traced dependencies0 B
Signal🟠 Bundled file __eve_nitro_handler__.mjs is 2.21 MB (35.2%)

🟠 🔎 Dependency Analysis

📦 Bundled files:

Bundled file size
🟠 __eve_nitro_handler__.mjs [########################] 2.21 MB 35.2%
🟡 _chunks/world-vercel.mjs [#########...............] 826.3 kB 13.2%
🟡 _chunks/sandbox.mjs [########................] 754.9 kB 12.0%
🟡 _libs/@ai-sdk/gateway+[...].mjs [#####...................] 430.4 kB 6.9%
🟡 _libs/zod.mjs [####....................] 376.1 kB 6.0%
🟠 Other bundled files [##################......] 1.68 MB 26.8%

🧾 Vercel Config

{
"handler": "index.mjs",
"launcherType": "Nodejs",
"shouldAddHelpers": false,
"supportsResponseStreaming": true,
"runtime": "nodejs24.x",
"environment": {
"NODE_OPTIONS": "--experimental-require-module"
},
"maxDuration": "max",
"experimentalTriggers": [
{
"type": "queue/v2beta",
"topic": "__eve776561746865722d6167656e74_wkf_workflow_*",
"consumer": "default",
"retryAfterSeconds": 5,
"initialDelaySeconds": 0
}
]
}

🟠 functions/__server.func • 9 public routes, 1 internal alias • 3.47 MB
MetricValue
Public routes/
/eve/v1/callback/[token]
/eve/v1/connections/[name]/callback/[token]
/eve/v1/health
/eve/v1/info
/eve/v1/session
/eve/v1/session/[sessionId]
/eve/v1/session/[sessionId]/cancel
/eve/v1/session/[sessionId]/stream
Internal aliases/__server
Runtimenodejs24.x
Handlerindex.mjs
Payload3.47 MB
Function files3.47 MB across 28 files
Traced dependencies0 B
Signal🟠 Bundled file _chunks/runtime-artifacts.mjs is 949.0 kB (27.3%)

🟠 🔎 Dependency Analysis

📦 Bundled files:

Bundled file size
🟠 _chunks/runtime-artifacts.mjs [########################] 949.0 kB 27.3%
🟠 _chunks/world-vercel.mjs [#####################...] 823.4 kB 23.7%
🟠 _chunks/sandbox.mjs [###################.....] 754.9 kB 21.8%
🟡 _chunks/dist-CSfKNxQW.mjs [#########...............] 348.5 kB 10.0%
⚪ _libs/zod.mjs [###.....................] 114.2 kB 3.3%
🟡 Other bundled files [############............] 480.2 kB 13.8%

🧾 Vercel Config

{
"handler": "index.mjs",
"launcherType": "Nodejs",
"shouldAddHelpers": false,
"supportsResponseStreaming": true,
"runtime": "nodejs24.x"
}

Build Timing: e2e/fixtures/agent-tools-sandbox

This is an informational timing measurement inside eve build, from preflight through publication. Output-size measurement and profile writing are excluded.

Build mode: deployable Vercel build with sandbox template prewarm included.

  • Build pipeline: 2.41 s -> 2.38 s (-36.9 ms) vs main (d034e01).
  • Timing is informational: shared GitHub runners are too variable for a hard timing budget.
Detailed phase timings vs `main (d034e01)`
PhaseBaselineCurrentDelta
extension.check1.1 ms0.9 ms-0.2 ms
project.resolve0.7 ms0.6 ms-0.1 ms
workspace.create0.9 ms0.7 ms-0.2 ms
host.prepare230.6 ms230.3 ms-0.3 ms
vercel.service-prefix.resolve2.1 ms2.1 ms0.0 ms
nitro.app.create24.3 ms24.2 ms-0.1 ms
nitro.app.cache.prepare0.2 ms0.2 ms0.0 ms
nitro.app.prepare0.9 ms0.8 ms-0.1 ms
nitro.app.public-assets0.7 ms0.7 ms0.0 ms
nitro.app.prerender0.5 ms0.5 ms0.0 ms
nitro.app.bundle547.7 ms554.9 ms+7.2 ms
nitro.app.cache.write0.5 ms0.4 ms-0.1 ms
sandbox.prewarm278.3 ms260.6 ms-17.7 ms
nitro.flow.create185.2 ms178.8 ms-6.4 ms
nitro.flow.cache.prepare0.2 ms0.2 ms0.0 ms
nitro.flow.prepare0.9 ms0.9 ms0.0 ms
nitro.flow.public-assets0.2 ms0.2 ms0.0 ms
nitro.flow.prerender0.0 ms0.0 ms0.0 ms
nitro.flow.bundle952.2 ms935.9 ms-16.3 ms
nitro.flow.cache.write0.3 ms0.3 ms0.0 ms
nitro.flow.close0.2 ms0.2 ms0.0 ms
workflow.emit173.9 ms170.9 ms-3.0 ms
agent-summary.emit0.6 ms0.5 ms-0.1 ms
nitro.app.close0.0 ms0.0 ms0.0 ms
output.publish3.7 ms3.7 ms0.0 ms
workspace.remove5.7 ms5.8 ms+0.1 ms

createWorkflowWorldPluginSource encoded the world selection three times: a
nested ternary for the createWorld statement, a repeated condition for the
runtime imports, and another for the vendored module specifier. The pieces
co-vary — a world constructed through an explicit createWorld(config) call
must not import createWorldFromModule — so hiding that invariant across
three expressions made every new world branch risky to add.
resolveWorkflowWorldWiring now owns all four facts per world; the caller is
pure assembly. Generated output is byte-identical for the world-local,
world-vercel, and passthrough branches (verified by rendering both versions
and comparing).
Signed-off-by: Rui Conti <ruiconti@gmail.com>
gateway.ts exported its internals — buildGatewayURL, addGatewayUA,
buildGatewayUA, isGatewayModel — and every call site reassembled them:
URLs were rebuilt locally, and model-conditional header logic leaked as
isGatewayModel(...) ? Object.fromEntries(addGatewayUA(...)) : undefined.
The module now owns the decisions instead of the parts:
- AI_GATEWAY_MODELS_URL / AI_GATEWAY_MODELS_CATALOG_URL live in gateway.ts.
- getVercelGatewayFetch() returns a UA-decorated fetch, mirroring the
Sandbox binding's getVercelSandboxFetch — call sites get a transport,
not header plumbing. validate-gateway-key routes its provider fetch
through it instead of construction headers.
- resolveProviderHeaders(model) answers "which headers does this model's
provider need" directly; isGatewayModel is private again.
The generic fetch decoration moves from the sandbox-named
withSandboxUserAgent to withPackageUserAgent in internal/user-agent.ts
(the sandbox binding and the gateway both wrap it). Its default now
resolves globalThis.fetch per request instead of capturing it at wrap
time, so globally installed fetch instrumentation still applies.
Signed-off-by: Rui Conti <ruiconti@gmail.com>
The world-wiring branches built their return values from inline
expressions and join("\n") arrays. Name the intermediates and write the
generated snippets as leading-newline template literals (trimStart keeps
the emitted text starting at the statement), so each branch reads as: the
specifiers, the code it emits, the wiring object.
Generated output is byte-identical for all three branches (verified by
rendering the HEAD version and this one against the same inputs).
Signed-off-by: Rui Conti <ruiconti@gmail.com>
withPackageUserAgent resolves globalThis.fetch per request when no inner
fetch is given, so later-installed global fetch instrumentation still
applies. Passing globalThis.fetch explicitly here captured it at
options-build time, quietly opting the sandbox path out of that contract
while the gateway path honored it.
Signed-off-by: Rui Conti <ruiconti@gmail.com>
…ever casts
ai/test's mock satisfies the LanguageModel contract, so the
resolveProviderHeaders tests no longer need to cast partial objects.
Same pattern tool-loop.test.ts already uses.
Signed-off-by: Rui Conti <ruiconti@gmail.com>
@vercel
vercelBottemporarily deployed to Preview – eve-docs-1644 July 20, 2026 06:51 Inactive
@vercel
vercelBottemporarily deployed to Preview – eve-docs-4759 July 20, 2026 06:51 Inactive
@ruiconti
ruiconti marked this pull request as ready for review July 20, 2026 15:20
Comment threadpackages/eve/src/compiler/model-catalog.ts Outdated
Comment on lines +5 to +6
const { name, version } = resolveInstalledPackageInfo();
return `${name}/${version}`;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we include agent name as well?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can infer project via deploymentId which is already part of User-Agent. Unless you were thinking of some other use for it

getVercelGatewayFetch() mirrored the Sandbox binding's factory shape, but
unlike getVercelSandboxFetch(createOptions) it had nothing to construct —
call sites read getVercelGatewayFetch()(url). withPackageUserAgent
late-binds globalThis.fetch per request, so a module-level const is safe
and the call sites become plain vercelGatewayFetch(url).
Signed-off-by: Rui Conti <ruiconti@gmail.com>
…ification
Signed-off-by: Rui Conti <ruiconti@gmail.com>
# Conflicts:
#	packages/eve/src/setup/boxes/select-model.test.ts
#	packages/eve/src/setup/boxes/select-model.ts
@AndrewBarba
AndrewBarba enabled auto-merge (squash) July 20, 2026 23:49
@AndrewBarba
AndrewBarba merged commit 938ef92 into mainJul 21, 2026
139 of 152 checks passed
@AndrewBarba
AndrewBarba deleted the rui/eve-service-identification branch July 21, 2026 00:03
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@ruiconti@AndrewBarba@ctgowrie
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' feat(eve): identify eve on AI Gateway, Workflow, and Sandbox requests by ruiconti · Pull Request #939 · vercel/eve · GitHub
Skip to content

feat(eve): identify eve on AI Gateway, Workflow, and Sandbox requests - #939

Merged
AndrewBarba merged 11 commits into
mainfrom
rui/eve-service-identification
Jul 21, 2026
Merged

feat(eve): identify eve on AI Gateway, Workflow, and Sandbox requests#939
AndrewBarba merged 11 commits into
mainfrom
rui/eve-service-identification

Conversation

@ruiconti

@ruicontiruiconti commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

Vercel services can't tell eve traffic from any other AI SDK app today. This appends an eve/<installed version> User-Agent product token to every service request eve makes, so receivers can attribute traffic to eve and its version — segmenting by framework during incidents and, later, controlling traffic keyed on the same token.

What

  • internal/user-agent.ts: builds the eve/<version> product token, appends it to a Headers without touching existing products (idempotent, space-joined per the RFC 9110 UA grammar — not Headers.append(), whose comma-combination breaks whitespace-delimited parsers), and exposes withPackageUserAgent(fetch), the generic UA-decorating fetch wrapper both the Gateway and Sandbox transports build on.
  • internal/gateway.ts owns the Gateway transport surface: the /v1/models and /v1/models/catalog URLs, getVercelGatewayFetch() (a UA-decorated fetch, mirroring the Sandbox binding's getVercelSandboxFetch), and resolveProviderHeaders(model) — headers for Gateway-routed models (bare ids and gateway.* instances), undefined for direct providers.
  • AI Gateway call sites: tool-loop generation and compaction, autoeval judge calls, model catalog, setup catalog, CLI model lookup, API-key validation — all through the two helpers above; no call site does header plumbing or URL assembly.
  • Workflow: generated world-vercel startup code passes the token via createWorld({ headers }), with the per-world wiring dispatched in one place (resolveWorkflowWorldWiring).
  • Sandbox: the SDK fetch decoration reuses withPackageUserAgent. A separate commit fixes a real gap here: Sandbox.get() lost the custom fetch on the credential-discovery failure path.

Wire format

Captured against a local server through the real ai/@ai-sdk/gateway packages — existing products stay intact:

eve/0.24.6 ai/7.0.26 ai-sdk/provider-utils/5.0.9 runtime/node.js/26

The Workflow leg is inert until a vendored bump

The vendored @workflow/world-vercel@5.0.0-beta.31 overwrites caller User-Agents, so the header this PR passes is dropped on the wire today (requests degrade to current behavior — nothing fails). vercel/workflow#2998 fixes the append; a follow-up bump of the vendored package lights this leg up.

Compaction attribution fix

Gateway attribution headers for compaction were previously computed from the main model; they now derive from the compaction model itself, since the two can differ.

…ery fails
getVercelSandboxGetOptions only attached the fetch override in the
credential-discovery success branch, so on the catch path Sandbox.get()
fell back to the SDK's bare global fetch. Move the fetch into the shared
base options so both branches use it.
Signed-off-by: Rui Conti <ruiconti@gmail.com>
Append an eve/<installed version> User-Agent product token to every
Vercel-service request eve makes, so receiving services can attribute
traffic to eve and its version without new headers or protocols:
- AI Gateway: model generation and compaction (tool-loop), autoeval
judge calls, the model catalog and setup catalog fetches, CLI model
lookup, and API-key validation. Gateway-routed models are detected via
isGatewayModel (bare ids and gateway.* instances).
- Workflow: generated world-vercel startup code passes the token via
createWorld({ headers }). Inert until the vendored @workflow/world-vercel
ships the caller User-Agent append (currently 5.0.0-beta.31, which
discards caller UA) — requests degrade to today's behavior, no failure.
- Sandbox: the SDK fetch decoration is generalized from the eve-specific
helper to appendPackageUserAgent.
The token is appended per the RFC 9110 User-Agent grammar (whitespace-
delimited products), never replacing existing products, idempotent on
re-append. Receivers parse it with whitespace-token scanners, so joining
uses spaces, not Headers.append() comma-combination.
Signed-off-by: Rui Conti <ruiconti@gmail.com>
@vercel

vercelBot commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

ProjectDeploymentActionsUpdated (UTC)
eve-docsReadyReadyPreview, CommentJul 20, 2026 11:50pm
eve-docs-1644ReadyReadyPreview, Comment, Open in v0Jul 20, 2026 11:50pm
eve-docs-4759ReadyReadyPreview, Comment, Open in v0Jul 20, 2026 11:50pm

Request Review

@github-actions

github-actionsBot commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

Bundle + Package Summary: apps/fixtures/weather-agent

Key takeaways

  • No notable deltas vs main (d034e01).

Delta vs main (d034e01)

AreaMetricBaselineCurrentDelta
PackagePacked tarball3.80 MB3.81 MB+636 B ⚠️
PackageUnpacked publish size13.77 MB13.78 MB+3.6 kB ⚠️
PackageInstalled footprint52.88 MB52.89 MB+3.6 kB ⚠️
PackagePublished files27222724+2
PackageInstalled files59625964+2
RuntimeUnique function payloads220
RuntimeTotal function bytes9.75 MB9.75 MB+3 B ⚠️
RuntimePublic routes10100
Changed function payloads vs main (d034e01) (2)
FunctionStatusBaselineCurrentDeltaRoute changes
functions/.well-known/workflow/v1/flow.funcchanged6.28 MB6.28 MB+191 B ⚠️none
functions/__server.funcchanged3.47 MB3.47 MB-188 B ✅none

eve init install

MetricBaselineCurrentDelta
Installed footprint91.29 MB91.29 MB+3.6 kB ⚠️
Installed packages1221220
dependencies440
devDependencies220
Dependency package bytes28.02 MB28.03 MB+3.6 kB ⚠️
devDependency package bytes5.04 MB5.04 MB0 B ➖
Build Metadata
  • Preset: vercel
  • Nitro: nitro@3.0.260610-beta
  • Output directory: apps/fixtures/weather-agent/.vercel/output
  • Build metadata timestamp: 2026-07-20T23:51:17.985Z
  • Route aliases: 10 public, 1 internal (11 total aliases)
  • Vercel routes in config: 11
  • Severity legend: 🔴 dominant/large, 🟠 notable, 🟡 watch, ⚪ small
Package Drill-Down

Package Details

  • Package: eve@0.26.1
  • Package directory: packages/eve
  • Tarball: 3.81 MB (eve-0.26.1.tgz)
  • Unpacked payload: 13.78 MB across 2724 published files
  • Installed footprint: 52.89 MB across 5964 installed files
  • Installed root package: 12.50 MB
  • Installed dependencies: 40.39 MB
  • Runtime dependencies: 1
  • Peer dependencies: 5 (4 optional)

Installed footprint is measured from an isolated temporary npm install of the packed tarball.

Heavy installed dependencies

  • @rolldown/binding-linux-x64-gnu: 18.96 MB (35.8%)
  • eve: 12.50 MB (23.6%)
  • ai: 6.39 MB (12.1%)
  • zod: 5.04 MB (9.5%)
  • nitro: 2.41 MB (4.6%)
Publish payload breakdown
Published file size
🟠 dist/src/compiled/experimental-ai-sdk-code-mo... [###.....................] 1.51 MB 10.9%
🟡 dist/src/compiled/@vercel/sandbox/index.js [#.......................] 622.2 kB 4.5%
🟡 dist/src/compiled/_chunks/workflow/undici-fb5... [#.......................] 502.4 kB 3.6%
🟡 dist/src/compiled/@chat-adapter/slack/index.js [#.......................] 433.3 kB 3.1%
🟡 dist/src/compiled/_chunks/workflow/dist-CSfKN... [#.......................] 277.8 kB 2.0%
🔴 Other published files [########################] 10.44 MB 75.7%
Installed footprint breakdown
Installed package size
🔴 @rolldown/binding-linux-x64-gnu [########################] 18.96 MB 35.8%
🔴 eve [################........] 12.50 MB 23.6%
🔴 ai [########................] 6.39 MB 12.1%
🔴 zod [######..................] 5.04 MB 9.5%
🟠 nitro [###.....................] 2.41 MB 4.6%
🟡 @ai-sdk/provider-utils [#.......................] 847.6 kB 1.6%
🔴 Other installed packages [#########...............] 6.74 MB 12.7%
Runtime dependencies (1)
PackageRangeNotes
nitro3.0.260610-beta
Peer dependencies (5)
PackageRangeNotes
@opentelemetry/api^1.0.0optional peer
aicatalog:
braintrust^3.0.0optional peer
just-bash^3.0.0optional peer
microsandbox^0.5.0optional peer
eve init install drill-down

eve init install details

  • Command: eve init my-agent
  • Package manager: npm
  • Installed footprint: 91.29 MB across 7832 installed files
  • Installed packages: 122 total (116 transitive-only)
  • dependencies: 4 direct packages totaling 28.03 MB
  • devDependencies: 2 direct packages totaling 5.04 MB
  • Other transitive package files: 58.22 MB

Installed footprint is measured from an isolated temporary eve init my-agent using the current packed eve tarball.

Heavy installed dependencies

  • @typescript/typescript-linux-x64: 27.95 MB (30.6%)
  • @rolldown/binding-linux-x64-gnu: 18.96 MB (20.8%)
  • eve: 12.50 MB (13.7%)
  • zod: 9.00 MB (9.9%)
  • ai: 6.39 MB (7.0%)
Installed footprint breakdown
Installed package size
🔴 @typescript/typescript-linux-x64 [########################] 27.95 MB 30.6%
🔴 @rolldown/binding-linux-x64-gnu [################........] 18.96 MB 20.8%
🔴 eve [###########.............] 12.50 MB 13.7%
🔴 zod [########................] 9.00 MB 9.9%
🔴 ai [#####...................] 6.39 MB 7.0%
🟠 @types/node [##......................] 2.54 MB 2.8%
🔴 Other installed packages [############............] 13.95 MB 15.3%
dependencies (4)
PackageRangeInstalled sizeShare
@vercel/connect0.4.0135.4 kB0.1%
ai^7.0.266.39 MB7.0%
evefile:eve-0.26.1.tgz12.50 MB13.7%
zod4.4.39.00 MB9.9%
devDependencies (2)
PackageRangeInstalled sizeShare
@types/node24.x2.54 MB2.8%
typescript7.0.22.50 MB2.7%
Function Drill-Down

Payload Size Graph

Unique function payload size and share of total
🔴 functions/.well-known/workflow/v1/flow.func [########################] 6.28 MB 64.4%
🟠 functions/__server.func [#############...........] 3.47 MB 35.6%

Top Function Payloads

🟠 functions/.well-known/workflow/v1/flow.func • 1 public route • 6.28 MB
MetricValue
Public routes/.well-known/workflow/v1/flow
Runtimenodejs24.x
Handlerindex.mjs
Payload6.28 MB
Function files6.28 MB across 37 files
Traced dependencies0 B
Signal🟠 Bundled file __eve_nitro_handler__.mjs is 2.21 MB (35.2%)

🟠 🔎 Dependency Analysis

📦 Bundled files:

Bundled file size
🟠 __eve_nitro_handler__.mjs [########################] 2.21 MB 35.2%
🟡 _chunks/world-vercel.mjs [#########...............] 826.3 kB 13.2%
🟡 _chunks/sandbox.mjs [########................] 754.9 kB 12.0%
🟡 _libs/@ai-sdk/gateway+[...].mjs [#####...................] 430.4 kB 6.9%
🟡 _libs/zod.mjs [####....................] 376.1 kB 6.0%
🟠 Other bundled files [##################......] 1.68 MB 26.8%

🧾 Vercel Config

{
"handler": "index.mjs",
"launcherType": "Nodejs",
"shouldAddHelpers": false,
"supportsResponseStreaming": true,
"runtime": "nodejs24.x",
"environment": {
"NODE_OPTIONS": "--experimental-require-module"
},
"maxDuration": "max",
"experimentalTriggers": [
{
"type": "queue/v2beta",
"topic": "__eve776561746865722d6167656e74_wkf_workflow_*",
"consumer": "default",
"retryAfterSeconds": 5,
"initialDelaySeconds": 0
}
]
}

🟠 functions/__server.func • 9 public routes, 1 internal alias • 3.47 MB
MetricValue
Public routes/
/eve/v1/callback/[token]
/eve/v1/connections/[name]/callback/[token]
/eve/v1/health
/eve/v1/info
/eve/v1/session
/eve/v1/session/[sessionId]
/eve/v1/session/[sessionId]/cancel
/eve/v1/session/[sessionId]/stream
Internal aliases/__server
Runtimenodejs24.x
Handlerindex.mjs
Payload3.47 MB
Function files3.47 MB across 28 files
Traced dependencies0 B
Signal🟠 Bundled file _chunks/runtime-artifacts.mjs is 949.0 kB (27.3%)

🟠 🔎 Dependency Analysis

📦 Bundled files:

Bundled file size
🟠 _chunks/runtime-artifacts.mjs [########################] 949.0 kB 27.3%
🟠 _chunks/world-vercel.mjs [#####################...] 823.4 kB 23.7%
🟠 _chunks/sandbox.mjs [###################.....] 754.9 kB 21.8%
🟡 _chunks/dist-CSfKNxQW.mjs [#########...............] 348.5 kB 10.0%
⚪ _libs/zod.mjs [###.....................] 114.2 kB 3.3%
🟡 Other bundled files [############............] 480.2 kB 13.8%

🧾 Vercel Config

{
"handler": "index.mjs",
"launcherType": "Nodejs",
"shouldAddHelpers": false,
"supportsResponseStreaming": true,
"runtime": "nodejs24.x"
}

Build Timing: e2e/fixtures/agent-tools-sandbox

This is an informational timing measurement inside eve build, from preflight through publication. Output-size measurement and profile writing are excluded.

Build mode: deployable Vercel build with sandbox template prewarm included.

  • Build pipeline: 2.41 s -> 2.38 s (-36.9 ms) vs main (d034e01).
  • Timing is informational: shared GitHub runners are too variable for a hard timing budget.
Detailed phase timings vs `main (d034e01)`
PhaseBaselineCurrentDelta
extension.check1.1 ms0.9 ms-0.2 ms
project.resolve0.7 ms0.6 ms-0.1 ms
workspace.create0.9 ms0.7 ms-0.2 ms
host.prepare230.6 ms230.3 ms-0.3 ms
vercel.service-prefix.resolve2.1 ms2.1 ms0.0 ms
nitro.app.create24.3 ms24.2 ms-0.1 ms
nitro.app.cache.prepare0.2 ms0.2 ms0.0 ms
nitro.app.prepare0.9 ms0.8 ms-0.1 ms
nitro.app.public-assets0.7 ms0.7 ms0.0 ms
nitro.app.prerender0.5 ms0.5 ms0.0 ms
nitro.app.bundle547.7 ms554.9 ms+7.2 ms
nitro.app.cache.write0.5 ms0.4 ms-0.1 ms
sandbox.prewarm278.3 ms260.6 ms-17.7 ms
nitro.flow.create185.2 ms178.8 ms-6.4 ms
nitro.flow.cache.prepare0.2 ms0.2 ms0.0 ms
nitro.flow.prepare0.9 ms0.9 ms0.0 ms
nitro.flow.public-assets0.2 ms0.2 ms0.0 ms
nitro.flow.prerender0.0 ms0.0 ms0.0 ms
nitro.flow.bundle952.2 ms935.9 ms-16.3 ms
nitro.flow.cache.write0.3 ms0.3 ms0.0 ms
nitro.flow.close0.2 ms0.2 ms0.0 ms
workflow.emit173.9 ms170.9 ms-3.0 ms
agent-summary.emit0.6 ms0.5 ms-0.1 ms
nitro.app.close0.0 ms0.0 ms0.0 ms
output.publish3.7 ms3.7 ms0.0 ms
workspace.remove5.7 ms5.8 ms+0.1 ms

createWorkflowWorldPluginSource encoded the world selection three times: a
nested ternary for the createWorld statement, a repeated condition for the
runtime imports, and another for the vendored module specifier. The pieces
co-vary — a world constructed through an explicit createWorld(config) call
must not import createWorldFromModule — so hiding that invariant across
three expressions made every new world branch risky to add.
resolveWorkflowWorldWiring now owns all four facts per world; the caller is
pure assembly. Generated output is byte-identical for the world-local,
world-vercel, and passthrough branches (verified by rendering both versions
and comparing).
Signed-off-by: Rui Conti <ruiconti@gmail.com>
gateway.ts exported its internals — buildGatewayURL, addGatewayUA,
buildGatewayUA, isGatewayModel — and every call site reassembled them:
URLs were rebuilt locally, and model-conditional header logic leaked as
isGatewayModel(...) ? Object.fromEntries(addGatewayUA(...)) : undefined.
The module now owns the decisions instead of the parts:
- AI_GATEWAY_MODELS_URL / AI_GATEWAY_MODELS_CATALOG_URL live in gateway.ts.
- getVercelGatewayFetch() returns a UA-decorated fetch, mirroring the
Sandbox binding's getVercelSandboxFetch — call sites get a transport,
not header plumbing. validate-gateway-key routes its provider fetch
through it instead of construction headers.
- resolveProviderHeaders(model) answers "which headers does this model's
provider need" directly; isGatewayModel is private again.
The generic fetch decoration moves from the sandbox-named
withSandboxUserAgent to withPackageUserAgent in internal/user-agent.ts
(the sandbox binding and the gateway both wrap it). Its default now
resolves globalThis.fetch per request instead of capturing it at wrap
time, so globally installed fetch instrumentation still applies.
Signed-off-by: Rui Conti <ruiconti@gmail.com>
The world-wiring branches built their return values from inline
expressions and join("\n") arrays. Name the intermediates and write the
generated snippets as leading-newline template literals (trimStart keeps
the emitted text starting at the statement), so each branch reads as: the
specifiers, the code it emits, the wiring object.
Generated output is byte-identical for all three branches (verified by
rendering the HEAD version and this one against the same inputs).
Signed-off-by: Rui Conti <ruiconti@gmail.com>
withPackageUserAgent resolves globalThis.fetch per request when no inner
fetch is given, so later-installed global fetch instrumentation still
applies. Passing globalThis.fetch explicitly here captured it at
options-build time, quietly opting the sandbox path out of that contract
while the gateway path honored it.
Signed-off-by: Rui Conti <ruiconti@gmail.com>
…ever casts
ai/test's mock satisfies the LanguageModel contract, so the
resolveProviderHeaders tests no longer need to cast partial objects.
Same pattern tool-loop.test.ts already uses.
Signed-off-by: Rui Conti <ruiconti@gmail.com>
@vercel
vercelBottemporarily deployed to Preview – eve-docs-1644 July 20, 2026 06:51 Inactive
@vercel
vercelBottemporarily deployed to Preview – eve-docs-4759 July 20, 2026 06:51 Inactive
@ruiconti
ruiconti marked this pull request as ready for review July 20, 2026 15:20
Comment threadpackages/eve/src/compiler/model-catalog.ts Outdated
Comment on lines +5 to +6
const { name, version } = resolveInstalledPackageInfo();
return `${name}/${version}`;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we include agent name as well?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can infer project via deploymentId which is already part of User-Agent. Unless you were thinking of some other use for it

getVercelGatewayFetch() mirrored the Sandbox binding's factory shape, but
unlike getVercelSandboxFetch(createOptions) it had nothing to construct —
call sites read getVercelGatewayFetch()(url). withPackageUserAgent
late-binds globalThis.fetch per request, so a module-level const is safe
and the call sites become plain vercelGatewayFetch(url).
Signed-off-by: Rui Conti <ruiconti@gmail.com>
…ification
Signed-off-by: Rui Conti <ruiconti@gmail.com>
# Conflicts:
#	packages/eve/src/setup/boxes/select-model.test.ts
#	packages/eve/src/setup/boxes/select-model.ts
@AndrewBarba
AndrewBarba enabled auto-merge (squash) July 20, 2026 23:49
@AndrewBarba
AndrewBarba merged commit 938ef92 into mainJul 21, 2026
139 of 152 checks passed
@AndrewBarba
AndrewBarba deleted the rui/eve-service-identification branch July 21, 2026 00:03
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@ruiconti@AndrewBarba@ctgowrie
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' feat(eve): identify eve on AI Gateway, Workflow, and Sandbox requests by ruiconti · Pull Request #939 · vercel/eve · GitHub
Skip to content

feat(eve): identify eve on AI Gateway, Workflow, and Sandbox requests - #939

Merged
AndrewBarba merged 11 commits into
mainfrom
rui/eve-service-identification
Jul 21, 2026
Merged

feat(eve): identify eve on AI Gateway, Workflow, and Sandbox requests#939
AndrewBarba merged 11 commits into
mainfrom
rui/eve-service-identification

Conversation

@ruiconti

@ruicontiruiconti commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

Vercel services can't tell eve traffic from any other AI SDK app today. This appends an eve/<installed version> User-Agent product token to every service request eve makes, so receivers can attribute traffic to eve and its version — segmenting by framework during incidents and, later, controlling traffic keyed on the same token.

What

  • internal/user-agent.ts: builds the eve/<version> product token, appends it to a Headers without touching existing products (idempotent, space-joined per the RFC 9110 UA grammar — not Headers.append(), whose comma-combination breaks whitespace-delimited parsers), and exposes withPackageUserAgent(fetch), the generic UA-decorating fetch wrapper both the Gateway and Sandbox transports build on.
  • internal/gateway.ts owns the Gateway transport surface: the /v1/models and /v1/models/catalog URLs, getVercelGatewayFetch() (a UA-decorated fetch, mirroring the Sandbox binding's getVercelSandboxFetch), and resolveProviderHeaders(model) — headers for Gateway-routed models (bare ids and gateway.* instances), undefined for direct providers.
  • AI Gateway call sites: tool-loop generation and compaction, autoeval judge calls, model catalog, setup catalog, CLI model lookup, API-key validation — all through the two helpers above; no call site does header plumbing or URL assembly.
  • Workflow: generated world-vercel startup code passes the token via createWorld({ headers }), with the per-world wiring dispatched in one place (resolveWorkflowWorldWiring).
  • Sandbox: the SDK fetch decoration reuses withPackageUserAgent. A separate commit fixes a real gap here: Sandbox.get() lost the custom fetch on the credential-discovery failure path.

Wire format

Captured against a local server through the real ai/@ai-sdk/gateway packages — existing products stay intact:

eve/0.24.6 ai/7.0.26 ai-sdk/provider-utils/5.0.9 runtime/node.js/26

The Workflow leg is inert until a vendored bump

The vendored @workflow/world-vercel@5.0.0-beta.31 overwrites caller User-Agents, so the header this PR passes is dropped on the wire today (requests degrade to current behavior — nothing fails). vercel/workflow#2998 fixes the append; a follow-up bump of the vendored package lights this leg up.

Compaction attribution fix

Gateway attribution headers for compaction were previously computed from the main model; they now derive from the compaction model itself, since the two can differ.

…ery fails
getVercelSandboxGetOptions only attached the fetch override in the
credential-discovery success branch, so on the catch path Sandbox.get()
fell back to the SDK's bare global fetch. Move the fetch into the shared
base options so both branches use it.
Signed-off-by: Rui Conti <ruiconti@gmail.com>
Append an eve/<installed version> User-Agent product token to every
Vercel-service request eve makes, so receiving services can attribute
traffic to eve and its version without new headers or protocols:
- AI Gateway: model generation and compaction (tool-loop), autoeval
judge calls, the model catalog and setup catalog fetches, CLI model
lookup, and API-key validation. Gateway-routed models are detected via
isGatewayModel (bare ids and gateway.* instances).
- Workflow: generated world-vercel startup code passes the token via
createWorld({ headers }). Inert until the vendored @workflow/world-vercel
ships the caller User-Agent append (currently 5.0.0-beta.31, which
discards caller UA) — requests degrade to today's behavior, no failure.
- Sandbox: the SDK fetch decoration is generalized from the eve-specific
helper to appendPackageUserAgent.
The token is appended per the RFC 9110 User-Agent grammar (whitespace-
delimited products), never replacing existing products, idempotent on
re-append. Receivers parse it with whitespace-token scanners, so joining
uses spaces, not Headers.append() comma-combination.
Signed-off-by: Rui Conti <ruiconti@gmail.com>
@vercel

vercelBot commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

ProjectDeploymentActionsUpdated (UTC)
eve-docsReadyReadyPreview, CommentJul 20, 2026 11:50pm
eve-docs-1644ReadyReadyPreview, Comment, Open in v0Jul 20, 2026 11:50pm
eve-docs-4759ReadyReadyPreview, Comment, Open in v0Jul 20, 2026 11:50pm

Request Review

@github-actions

github-actionsBot commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

Bundle + Package Summary: apps/fixtures/weather-agent

Key takeaways

  • No notable deltas vs main (d034e01).

Delta vs main (d034e01)

AreaMetricBaselineCurrentDelta
PackagePacked tarball3.80 MB3.81 MB+636 B ⚠️
PackageUnpacked publish size13.77 MB13.78 MB+3.6 kB ⚠️
PackageInstalled footprint52.88 MB52.89 MB+3.6 kB ⚠️
PackagePublished files27222724+2
PackageInstalled files59625964+2
RuntimeUnique function payloads220
RuntimeTotal function bytes9.75 MB9.75 MB+3 B ⚠️
RuntimePublic routes10100
Changed function payloads vs main (d034e01) (2)
FunctionStatusBaselineCurrentDeltaRoute changes
functions/.well-known/workflow/v1/flow.funcchanged6.28 MB6.28 MB+191 B ⚠️none
functions/__server.funcchanged3.47 MB3.47 MB-188 B ✅none

eve init install

MetricBaselineCurrentDelta
Installed footprint91.29 MB91.29 MB+3.6 kB ⚠️
Installed packages1221220
dependencies440
devDependencies220
Dependency package bytes28.02 MB28.03 MB+3.6 kB ⚠️
devDependency package bytes5.04 MB5.04 MB0 B ➖
Build Metadata
  • Preset: vercel
  • Nitro: nitro@3.0.260610-beta
  • Output directory: apps/fixtures/weather-agent/.vercel/output
  • Build metadata timestamp: 2026-07-20T23:51:17.985Z
  • Route aliases: 10 public, 1 internal (11 total aliases)
  • Vercel routes in config: 11
  • Severity legend: 🔴 dominant/large, 🟠 notable, 🟡 watch, ⚪ small
Package Drill-Down

Package Details

  • Package: eve@0.26.1
  • Package directory: packages/eve
  • Tarball: 3.81 MB (eve-0.26.1.tgz)
  • Unpacked payload: 13.78 MB across 2724 published files
  • Installed footprint: 52.89 MB across 5964 installed files
  • Installed root package: 12.50 MB
  • Installed dependencies: 40.39 MB
  • Runtime dependencies: 1
  • Peer dependencies: 5 (4 optional)

Installed footprint is measured from an isolated temporary npm install of the packed tarball.

Heavy installed dependencies

  • @rolldown/binding-linux-x64-gnu: 18.96 MB (35.8%)
  • eve: 12.50 MB (23.6%)
  • ai: 6.39 MB (12.1%)
  • zod: 5.04 MB (9.5%)
  • nitro: 2.41 MB (4.6%)
Publish payload breakdown
Published file size
🟠 dist/src/compiled/experimental-ai-sdk-code-mo... [###.....................] 1.51 MB 10.9%
🟡 dist/src/compiled/@vercel/sandbox/index.js [#.......................] 622.2 kB 4.5%
🟡 dist/src/compiled/_chunks/workflow/undici-fb5... [#.......................] 502.4 kB 3.6%
🟡 dist/src/compiled/@chat-adapter/slack/index.js [#.......................] 433.3 kB 3.1%
🟡 dist/src/compiled/_chunks/workflow/dist-CSfKN... [#.......................] 277.8 kB 2.0%
🔴 Other published files [########################] 10.44 MB 75.7%
Installed footprint breakdown
Installed package size
🔴 @rolldown/binding-linux-x64-gnu [########################] 18.96 MB 35.8%
🔴 eve [################........] 12.50 MB 23.6%
🔴 ai [########................] 6.39 MB 12.1%
🔴 zod [######..................] 5.04 MB 9.5%
🟠 nitro [###.....................] 2.41 MB 4.6%
🟡 @ai-sdk/provider-utils [#.......................] 847.6 kB 1.6%
🔴 Other installed packages [#########...............] 6.74 MB 12.7%
Runtime dependencies (1)
PackageRangeNotes
nitro3.0.260610-beta
Peer dependencies (5)
PackageRangeNotes
@opentelemetry/api^1.0.0optional peer
aicatalog:
braintrust^3.0.0optional peer
just-bash^3.0.0optional peer
microsandbox^0.5.0optional peer
eve init install drill-down

eve init install details

  • Command: eve init my-agent
  • Package manager: npm
  • Installed footprint: 91.29 MB across 7832 installed files
  • Installed packages: 122 total (116 transitive-only)
  • dependencies: 4 direct packages totaling 28.03 MB
  • devDependencies: 2 direct packages totaling 5.04 MB
  • Other transitive package files: 58.22 MB

Installed footprint is measured from an isolated temporary eve init my-agent using the current packed eve tarball.

Heavy installed dependencies

  • @typescript/typescript-linux-x64: 27.95 MB (30.6%)
  • @rolldown/binding-linux-x64-gnu: 18.96 MB (20.8%)
  • eve: 12.50 MB (13.7%)
  • zod: 9.00 MB (9.9%)
  • ai: 6.39 MB (7.0%)
Installed footprint breakdown
Installed package size
🔴 @typescript/typescript-linux-x64 [########################] 27.95 MB 30.6%
🔴 @rolldown/binding-linux-x64-gnu [################........] 18.96 MB 20.8%
🔴 eve [###########.............] 12.50 MB 13.7%
🔴 zod [########................] 9.00 MB 9.9%
🔴 ai [#####...................] 6.39 MB 7.0%
🟠 @types/node [##......................] 2.54 MB 2.8%
🔴 Other installed packages [############............] 13.95 MB 15.3%
dependencies (4)
PackageRangeInstalled sizeShare
@vercel/connect0.4.0135.4 kB0.1%
ai^7.0.266.39 MB7.0%
evefile:eve-0.26.1.tgz12.50 MB13.7%
zod4.4.39.00 MB9.9%
devDependencies (2)
PackageRangeInstalled sizeShare
@types/node24.x2.54 MB2.8%
typescript7.0.22.50 MB2.7%
Function Drill-Down

Payload Size Graph

Unique function payload size and share of total
🔴 functions/.well-known/workflow/v1/flow.func [########################] 6.28 MB 64.4%
🟠 functions/__server.func [#############...........] 3.47 MB 35.6%

Top Function Payloads

🟠 functions/.well-known/workflow/v1/flow.func • 1 public route • 6.28 MB
MetricValue
Public routes/.well-known/workflow/v1/flow
Runtimenodejs24.x
Handlerindex.mjs
Payload6.28 MB
Function files6.28 MB across 37 files
Traced dependencies0 B
Signal🟠 Bundled file __eve_nitro_handler__.mjs is 2.21 MB (35.2%)

🟠 🔎 Dependency Analysis

📦 Bundled files:

Bundled file size
🟠 __eve_nitro_handler__.mjs [########################] 2.21 MB 35.2%
🟡 _chunks/world-vercel.mjs [#########...............] 826.3 kB 13.2%
🟡 _chunks/sandbox.mjs [########................] 754.9 kB 12.0%
🟡 _libs/@ai-sdk/gateway+[...].mjs [#####...................] 430.4 kB 6.9%
🟡 _libs/zod.mjs [####....................] 376.1 kB 6.0%
🟠 Other bundled files [##################......] 1.68 MB 26.8%

🧾 Vercel Config

{
"handler": "index.mjs",
"launcherType": "Nodejs",
"shouldAddHelpers": false,
"supportsResponseStreaming": true,
"runtime": "nodejs24.x",
"environment": {
"NODE_OPTIONS": "--experimental-require-module"
},
"maxDuration": "max",
"experimentalTriggers": [
{
"type": "queue/v2beta",
"topic": "__eve776561746865722d6167656e74_wkf_workflow_*",
"consumer": "default",
"retryAfterSeconds": 5,
"initialDelaySeconds": 0
}
]
}

🟠 functions/__server.func • 9 public routes, 1 internal alias • 3.47 MB
MetricValue
Public routes/
/eve/v1/callback/[token]
/eve/v1/connections/[name]/callback/[token]
/eve/v1/health
/eve/v1/info
/eve/v1/session
/eve/v1/session/[sessionId]
/eve/v1/session/[sessionId]/cancel
/eve/v1/session/[sessionId]/stream
Internal aliases/__server
Runtimenodejs24.x
Handlerindex.mjs
Payload3.47 MB
Function files3.47 MB across 28 files
Traced dependencies0 B
Signal🟠 Bundled file _chunks/runtime-artifacts.mjs is 949.0 kB (27.3%)

🟠 🔎 Dependency Analysis

📦 Bundled files:

Bundled file size
🟠 _chunks/runtime-artifacts.mjs [########################] 949.0 kB 27.3%
🟠 _chunks/world-vercel.mjs [#####################...] 823.4 kB 23.7%
🟠 _chunks/sandbox.mjs [###################.....] 754.9 kB 21.8%
🟡 _chunks/dist-CSfKNxQW.mjs [#########...............] 348.5 kB 10.0%
⚪ _libs/zod.mjs [###.....................] 114.2 kB 3.3%
🟡 Other bundled files [############............] 480.2 kB 13.8%

🧾 Vercel Config

{
"handler": "index.mjs",
"launcherType": "Nodejs",
"shouldAddHelpers": false,
"supportsResponseStreaming": true,
"runtime": "nodejs24.x"
}

Build Timing: e2e/fixtures/agent-tools-sandbox

This is an informational timing measurement inside eve build, from preflight through publication. Output-size measurement and profile writing are excluded.

Build mode: deployable Vercel build with sandbox template prewarm included.

  • Build pipeline: 2.41 s -> 2.38 s (-36.9 ms) vs main (d034e01).
  • Timing is informational: shared GitHub runners are too variable for a hard timing budget.
Detailed phase timings vs `main (d034e01)`
PhaseBaselineCurrentDelta
extension.check1.1 ms0.9 ms-0.2 ms
project.resolve0.7 ms0.6 ms-0.1 ms
workspace.create0.9 ms0.7 ms-0.2 ms
host.prepare230.6 ms230.3 ms-0.3 ms
vercel.service-prefix.resolve2.1 ms2.1 ms0.0 ms
nitro.app.create24.3 ms24.2 ms-0.1 ms
nitro.app.cache.prepare0.2 ms0.2 ms0.0 ms
nitro.app.prepare0.9 ms0.8 ms-0.1 ms
nitro.app.public-assets0.7 ms0.7 ms0.0 ms
nitro.app.prerender0.5 ms0.5 ms0.0 ms
nitro.app.bundle547.7 ms554.9 ms+7.2 ms
nitro.app.cache.write0.5 ms0.4 ms-0.1 ms
sandbox.prewarm278.3 ms260.6 ms-17.7 ms
nitro.flow.create185.2 ms178.8 ms-6.4 ms
nitro.flow.cache.prepare0.2 ms0.2 ms0.0 ms
nitro.flow.prepare0.9 ms0.9 ms0.0 ms
nitro.flow.public-assets0.2 ms0.2 ms0.0 ms
nitro.flow.prerender0.0 ms0.0 ms0.0 ms
nitro.flow.bundle952.2 ms935.9 ms-16.3 ms
nitro.flow.cache.write0.3 ms0.3 ms0.0 ms
nitro.flow.close0.2 ms0.2 ms0.0 ms
workflow.emit173.9 ms170.9 ms-3.0 ms
agent-summary.emit0.6 ms0.5 ms-0.1 ms
nitro.app.close0.0 ms0.0 ms0.0 ms
output.publish3.7 ms3.7 ms0.0 ms
workspace.remove5.7 ms5.8 ms+0.1 ms

createWorkflowWorldPluginSource encoded the world selection three times: a
nested ternary for the createWorld statement, a repeated condition for the
runtime imports, and another for the vendored module specifier. The pieces
co-vary — a world constructed through an explicit createWorld(config) call
must not import createWorldFromModule — so hiding that invariant across
three expressions made every new world branch risky to add.
resolveWorkflowWorldWiring now owns all four facts per world; the caller is
pure assembly. Generated output is byte-identical for the world-local,
world-vercel, and passthrough branches (verified by rendering both versions
and comparing).
Signed-off-by: Rui Conti <ruiconti@gmail.com>
gateway.ts exported its internals — buildGatewayURL, addGatewayUA,
buildGatewayUA, isGatewayModel — and every call site reassembled them:
URLs were rebuilt locally, and model-conditional header logic leaked as
isGatewayModel(...) ? Object.fromEntries(addGatewayUA(...)) : undefined.
The module now owns the decisions instead of the parts:
- AI_GATEWAY_MODELS_URL / AI_GATEWAY_MODELS_CATALOG_URL live in gateway.ts.
- getVercelGatewayFetch() returns a UA-decorated fetch, mirroring the
Sandbox binding's getVercelSandboxFetch — call sites get a transport,
not header plumbing. validate-gateway-key routes its provider fetch
through it instead of construction headers.
- resolveProviderHeaders(model) answers "which headers does this model's
provider need" directly; isGatewayModel is private again.
The generic fetch decoration moves from the sandbox-named
withSandboxUserAgent to withPackageUserAgent in internal/user-agent.ts
(the sandbox binding and the gateway both wrap it). Its default now
resolves globalThis.fetch per request instead of capturing it at wrap
time, so globally installed fetch instrumentation still applies.
Signed-off-by: Rui Conti <ruiconti@gmail.com>
The world-wiring branches built their return values from inline
expressions and join("\n") arrays. Name the intermediates and write the
generated snippets as leading-newline template literals (trimStart keeps
the emitted text starting at the statement), so each branch reads as: the
specifiers, the code it emits, the wiring object.
Generated output is byte-identical for all three branches (verified by
rendering the HEAD version and this one against the same inputs).
Signed-off-by: Rui Conti <ruiconti@gmail.com>
withPackageUserAgent resolves globalThis.fetch per request when no inner
fetch is given, so later-installed global fetch instrumentation still
applies. Passing globalThis.fetch explicitly here captured it at
options-build time, quietly opting the sandbox path out of that contract
while the gateway path honored it.
Signed-off-by: Rui Conti <ruiconti@gmail.com>
…ever casts
ai/test's mock satisfies the LanguageModel contract, so the
resolveProviderHeaders tests no longer need to cast partial objects.
Same pattern tool-loop.test.ts already uses.
Signed-off-by: Rui Conti <ruiconti@gmail.com>
@vercel
vercelBottemporarily deployed to Preview – eve-docs-1644 July 20, 2026 06:51 Inactive
@vercel
vercelBottemporarily deployed to Preview – eve-docs-4759 July 20, 2026 06:51 Inactive
@ruiconti
ruiconti marked this pull request as ready for review July 20, 2026 15:20
Comment threadpackages/eve/src/compiler/model-catalog.ts Outdated
Comment on lines +5 to +6
const { name, version } = resolveInstalledPackageInfo();
return `${name}/${version}`;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we include agent name as well?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can infer project via deploymentId which is already part of User-Agent. Unless you were thinking of some other use for it

getVercelGatewayFetch() mirrored the Sandbox binding's factory shape, but
unlike getVercelSandboxFetch(createOptions) it had nothing to construct —
call sites read getVercelGatewayFetch()(url). withPackageUserAgent
late-binds globalThis.fetch per request, so a module-level const is safe
and the call sites become plain vercelGatewayFetch(url).
Signed-off-by: Rui Conti <ruiconti@gmail.com>
…ification
Signed-off-by: Rui Conti <ruiconti@gmail.com>
# Conflicts:
#	packages/eve/src/setup/boxes/select-model.test.ts
#	packages/eve/src/setup/boxes/select-model.ts
@AndrewBarba
AndrewBarba enabled auto-merge (squash) July 20, 2026 23:49
@AndrewBarba
AndrewBarba merged commit 938ef92 into mainJul 21, 2026
139 of 152 checks passed
@AndrewBarba
AndrewBarba deleted the rui/eve-service-identification branch July 21, 2026 00:03
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@ruiconti@AndrewBarba@ctgowrie
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' feat(eve): identify eve on AI Gateway, Workflow, and Sandbox requests by ruiconti · Pull Request #939 · vercel/eve · GitHub
Skip to content

feat(eve): identify eve on AI Gateway, Workflow, and Sandbox requests - #939

Merged
AndrewBarba merged 11 commits into
mainfrom
rui/eve-service-identification
Jul 21, 2026
Merged

feat(eve): identify eve on AI Gateway, Workflow, and Sandbox requests#939
AndrewBarba merged 11 commits into
mainfrom
rui/eve-service-identification

Conversation

@ruiconti

@ruicontiruiconti commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

Vercel services can't tell eve traffic from any other AI SDK app today. This appends an eve/<installed version> User-Agent product token to every service request eve makes, so receivers can attribute traffic to eve and its version — segmenting by framework during incidents and, later, controlling traffic keyed on the same token.

What

  • internal/user-agent.ts: builds the eve/<version> product token, appends it to a Headers without touching existing products (idempotent, space-joined per the RFC 9110 UA grammar — not Headers.append(), whose comma-combination breaks whitespace-delimited parsers), and exposes withPackageUserAgent(fetch), the generic UA-decorating fetch wrapper both the Gateway and Sandbox transports build on.
  • internal/gateway.ts owns the Gateway transport surface: the /v1/models and /v1/models/catalog URLs, getVercelGatewayFetch() (a UA-decorated fetch, mirroring the Sandbox binding's getVercelSandboxFetch), and resolveProviderHeaders(model) — headers for Gateway-routed models (bare ids and gateway.* instances), undefined for direct providers.
  • AI Gateway call sites: tool-loop generation and compaction, autoeval judge calls, model catalog, setup catalog, CLI model lookup, API-key validation — all through the two helpers above; no call site does header plumbing or URL assembly.
  • Workflow: generated world-vercel startup code passes the token via createWorld({ headers }), with the per-world wiring dispatched in one place (resolveWorkflowWorldWiring).
  • Sandbox: the SDK fetch decoration reuses withPackageUserAgent. A separate commit fixes a real gap here: Sandbox.get() lost the custom fetch on the credential-discovery failure path.

Wire format

Captured against a local server through the real ai/@ai-sdk/gateway packages — existing products stay intact:

eve/0.24.6 ai/7.0.26 ai-sdk/provider-utils/5.0.9 runtime/node.js/26

The Workflow leg is inert until a vendored bump

The vendored @workflow/world-vercel@5.0.0-beta.31 overwrites caller User-Agents, so the header this PR passes is dropped on the wire today (requests degrade to current behavior — nothing fails). vercel/workflow#2998 fixes the append; a follow-up bump of the vendored package lights this leg up.

Compaction attribution fix

Gateway attribution headers for compaction were previously computed from the main model; they now derive from the compaction model itself, since the two can differ.

…ery fails
getVercelSandboxGetOptions only attached the fetch override in the
credential-discovery success branch, so on the catch path Sandbox.get()
fell back to the SDK's bare global fetch. Move the fetch into the shared
base options so both branches use it.
Signed-off-by: Rui Conti <ruiconti@gmail.com>
Append an eve/<installed version> User-Agent product token to every
Vercel-service request eve makes, so receiving services can attribute
traffic to eve and its version without new headers or protocols:
- AI Gateway: model generation and compaction (tool-loop), autoeval
judge calls, the model catalog and setup catalog fetches, CLI model
lookup, and API-key validation. Gateway-routed models are detected via
isGatewayModel (bare ids and gateway.* instances).
- Workflow: generated world-vercel startup code passes the token via
createWorld({ headers }). Inert until the vendored @workflow/world-vercel
ships the caller User-Agent append (currently 5.0.0-beta.31, which
discards caller UA) — requests degrade to today's behavior, no failure.
- Sandbox: the SDK fetch decoration is generalized from the eve-specific
helper to appendPackageUserAgent.
The token is appended per the RFC 9110 User-Agent grammar (whitespace-
delimited products), never replacing existing products, idempotent on
re-append. Receivers parse it with whitespace-token scanners, so joining
uses spaces, not Headers.append() comma-combination.
Signed-off-by: Rui Conti <ruiconti@gmail.com>
@vercel

vercelBot commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

ProjectDeploymentActionsUpdated (UTC)
eve-docsReadyReadyPreview, CommentJul 20, 2026 11:50pm
eve-docs-1644ReadyReadyPreview, Comment, Open in v0Jul 20, 2026 11:50pm
eve-docs-4759ReadyReadyPreview, Comment, Open in v0Jul 20, 2026 11:50pm

Request Review

@github-actions

github-actionsBot commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

Bundle + Package Summary: apps/fixtures/weather-agent

Key takeaways

  • No notable deltas vs main (d034e01).

Delta vs main (d034e01)

AreaMetricBaselineCurrentDelta
PackagePacked tarball3.80 MB3.81 MB+636 B ⚠️
PackageUnpacked publish size13.77 MB13.78 MB+3.6 kB ⚠️
PackageInstalled footprint52.88 MB52.89 MB+3.6 kB ⚠️
PackagePublished files27222724+2
PackageInstalled files59625964+2
RuntimeUnique function payloads220
RuntimeTotal function bytes9.75 MB9.75 MB+3 B ⚠️
RuntimePublic routes10100
Changed function payloads vs main (d034e01) (2)
FunctionStatusBaselineCurrentDeltaRoute changes
functions/.well-known/workflow/v1/flow.funcchanged6.28 MB6.28 MB+191 B ⚠️none
functions/__server.funcchanged3.47 MB3.47 MB-188 B ✅none

eve init install

MetricBaselineCurrentDelta
Installed footprint91.29 MB91.29 MB+3.6 kB ⚠️
Installed packages1221220
dependencies440
devDependencies220
Dependency package bytes28.02 MB28.03 MB+3.6 kB ⚠️
devDependency package bytes5.04 MB5.04 MB0 B ➖
Build Metadata
  • Preset: vercel
  • Nitro: nitro@3.0.260610-beta
  • Output directory: apps/fixtures/weather-agent/.vercel/output
  • Build metadata timestamp: 2026-07-20T23:51:17.985Z
  • Route aliases: 10 public, 1 internal (11 total aliases)
  • Vercel routes in config: 11
  • Severity legend: 🔴 dominant/large, 🟠 notable, 🟡 watch, ⚪ small
Package Drill-Down

Package Details

  • Package: eve@0.26.1
  • Package directory: packages/eve
  • Tarball: 3.81 MB (eve-0.26.1.tgz)
  • Unpacked payload: 13.78 MB across 2724 published files
  • Installed footprint: 52.89 MB across 5964 installed files
  • Installed root package: 12.50 MB
  • Installed dependencies: 40.39 MB
  • Runtime dependencies: 1
  • Peer dependencies: 5 (4 optional)

Installed footprint is measured from an isolated temporary npm install of the packed tarball.

Heavy installed dependencies

  • @rolldown/binding-linux-x64-gnu: 18.96 MB (35.8%)
  • eve: 12.50 MB (23.6%)
  • ai: 6.39 MB (12.1%)
  • zod: 5.04 MB (9.5%)
  • nitro: 2.41 MB (4.6%)
Publish payload breakdown
Published file size
🟠 dist/src/compiled/experimental-ai-sdk-code-mo... [###.....................] 1.51 MB 10.9%
🟡 dist/src/compiled/@vercel/sandbox/index.js [#.......................] 622.2 kB 4.5%
🟡 dist/src/compiled/_chunks/workflow/undici-fb5... [#.......................] 502.4 kB 3.6%
🟡 dist/src/compiled/@chat-adapter/slack/index.js [#.......................] 433.3 kB 3.1%
🟡 dist/src/compiled/_chunks/workflow/dist-CSfKN... [#.......................] 277.8 kB 2.0%
🔴 Other published files [########################] 10.44 MB 75.7%
Installed footprint breakdown
Installed package size
🔴 @rolldown/binding-linux-x64-gnu [########################] 18.96 MB 35.8%
🔴 eve [################........] 12.50 MB 23.6%
🔴 ai [########................] 6.39 MB 12.1%
🔴 zod [######..................] 5.04 MB 9.5%
🟠 nitro [###.....................] 2.41 MB 4.6%
🟡 @ai-sdk/provider-utils [#.......................] 847.6 kB 1.6%
🔴 Other installed packages [#########...............] 6.74 MB 12.7%
Runtime dependencies (1)
PackageRangeNotes
nitro3.0.260610-beta
Peer dependencies (5)
PackageRangeNotes
@opentelemetry/api^1.0.0optional peer
aicatalog:
braintrust^3.0.0optional peer
just-bash^3.0.0optional peer
microsandbox^0.5.0optional peer
eve init install drill-down

eve init install details

  • Command: eve init my-agent
  • Package manager: npm
  • Installed footprint: 91.29 MB across 7832 installed files
  • Installed packages: 122 total (116 transitive-only)
  • dependencies: 4 direct packages totaling 28.03 MB
  • devDependencies: 2 direct packages totaling 5.04 MB
  • Other transitive package files: 58.22 MB

Installed footprint is measured from an isolated temporary eve init my-agent using the current packed eve tarball.

Heavy installed dependencies

  • @typescript/typescript-linux-x64: 27.95 MB (30.6%)
  • @rolldown/binding-linux-x64-gnu: 18.96 MB (20.8%)
  • eve: 12.50 MB (13.7%)
  • zod: 9.00 MB (9.9%)
  • ai: 6.39 MB (7.0%)
Installed footprint breakdown
Installed package size
🔴 @typescript/typescript-linux-x64 [########################] 27.95 MB 30.6%
🔴 @rolldown/binding-linux-x64-gnu [################........] 18.96 MB 20.8%
🔴 eve [###########.............] 12.50 MB 13.7%
🔴 zod [########................] 9.00 MB 9.9%
🔴 ai [#####...................] 6.39 MB 7.0%
🟠 @types/node [##......................] 2.54 MB 2.8%
🔴 Other installed packages [############............] 13.95 MB 15.3%
dependencies (4)
PackageRangeInstalled sizeShare
@vercel/connect0.4.0135.4 kB0.1%
ai^7.0.266.39 MB7.0%
evefile:eve-0.26.1.tgz12.50 MB13.7%
zod4.4.39.00 MB9.9%
devDependencies (2)
PackageRangeInstalled sizeShare
@types/node24.x2.54 MB2.8%
typescript7.0.22.50 MB2.7%
Function Drill-Down

Payload Size Graph

Unique function payload size and share of total
🔴 functions/.well-known/workflow/v1/flow.func [########################] 6.28 MB 64.4%
🟠 functions/__server.func [#############...........] 3.47 MB 35.6%

Top Function Payloads

🟠 functions/.well-known/workflow/v1/flow.func • 1 public route • 6.28 MB
MetricValue
Public routes/.well-known/workflow/v1/flow
Runtimenodejs24.x
Handlerindex.mjs
Payload6.28 MB
Function files6.28 MB across 37 files
Traced dependencies0 B
Signal🟠 Bundled file __eve_nitro_handler__.mjs is 2.21 MB (35.2%)

🟠 🔎 Dependency Analysis

📦 Bundled files:

Bundled file size
🟠 __eve_nitro_handler__.mjs [########################] 2.21 MB 35.2%
🟡 _chunks/world-vercel.mjs [#########...............] 826.3 kB 13.2%
🟡 _chunks/sandbox.mjs [########................] 754.9 kB 12.0%
🟡 _libs/@ai-sdk/gateway+[...].mjs [#####...................] 430.4 kB 6.9%
🟡 _libs/zod.mjs [####....................] 376.1 kB 6.0%
🟠 Other bundled files [##################......] 1.68 MB 26.8%

🧾 Vercel Config

{
"handler": "index.mjs",
"launcherType": "Nodejs",
"shouldAddHelpers": false,
"supportsResponseStreaming": true,
"runtime": "nodejs24.x",
"environment": {
"NODE_OPTIONS": "--experimental-require-module"
},
"maxDuration": "max",
"experimentalTriggers": [
{
"type": "queue/v2beta",
"topic": "__eve776561746865722d6167656e74_wkf_workflow_*",
"consumer": "default",
"retryAfterSeconds": 5,
"initialDelaySeconds": 0
}
]
}

🟠 functions/__server.func • 9 public routes, 1 internal alias • 3.47 MB
MetricValue
Public routes/
/eve/v1/callback/[token]
/eve/v1/connections/[name]/callback/[token]
/eve/v1/health
/eve/v1/info
/eve/v1/session
/eve/v1/session/[sessionId]
/eve/v1/session/[sessionId]/cancel
/eve/v1/session/[sessionId]/stream
Internal aliases/__server
Runtimenodejs24.x
Handlerindex.mjs
Payload3.47 MB
Function files3.47 MB across 28 files
Traced dependencies0 B
Signal🟠 Bundled file _chunks/runtime-artifacts.mjs is 949.0 kB (27.3%)

🟠 🔎 Dependency Analysis

📦 Bundled files:

Bundled file size
🟠 _chunks/runtime-artifacts.mjs [########################] 949.0 kB 27.3%
🟠 _chunks/world-vercel.mjs [#####################...] 823.4 kB 23.7%
🟠 _chunks/sandbox.mjs [###################.....] 754.9 kB 21.8%
🟡 _chunks/dist-CSfKNxQW.mjs [#########...............] 348.5 kB 10.0%
⚪ _libs/zod.mjs [###.....................] 114.2 kB 3.3%
🟡 Other bundled files [############............] 480.2 kB 13.8%

🧾 Vercel Config

{
"handler": "index.mjs",
"launcherType": "Nodejs",
"shouldAddHelpers": false,
"supportsResponseStreaming": true,
"runtime": "nodejs24.x"
}

Build Timing: e2e/fixtures/agent-tools-sandbox

This is an informational timing measurement inside eve build, from preflight through publication. Output-size measurement and profile writing are excluded.

Build mode: deployable Vercel build with sandbox template prewarm included.

  • Build pipeline: 2.41 s -> 2.38 s (-36.9 ms) vs main (d034e01).
  • Timing is informational: shared GitHub runners are too variable for a hard timing budget.
Detailed phase timings vs `main (d034e01)`
PhaseBaselineCurrentDelta
extension.check1.1 ms0.9 ms-0.2 ms
project.resolve0.7 ms0.6 ms-0.1 ms
workspace.create0.9 ms0.7 ms-0.2 ms
host.prepare230.6 ms230.3 ms-0.3 ms
vercel.service-prefix.resolve2.1 ms2.1 ms0.0 ms
nitro.app.create24.3 ms24.2 ms-0.1 ms
nitro.app.cache.prepare0.2 ms0.2 ms0.0 ms
nitro.app.prepare0.9 ms0.8 ms-0.1 ms
nitro.app.public-assets0.7 ms0.7 ms0.0 ms
nitro.app.prerender0.5 ms0.5 ms0.0 ms
nitro.app.bundle547.7 ms554.9 ms+7.2 ms
nitro.app.cache.write0.5 ms0.4 ms-0.1 ms
sandbox.prewarm278.3 ms260.6 ms-17.7 ms
nitro.flow.create185.2 ms178.8 ms-6.4 ms
nitro.flow.cache.prepare0.2 ms0.2 ms0.0 ms
nitro.flow.prepare0.9 ms0.9 ms0.0 ms
nitro.flow.public-assets0.2 ms0.2 ms0.0 ms
nitro.flow.prerender0.0 ms0.0 ms0.0 ms
nitro.flow.bundle952.2 ms935.9 ms-16.3 ms
nitro.flow.cache.write0.3 ms0.3 ms0.0 ms
nitro.flow.close0.2 ms0.2 ms0.0 ms
workflow.emit173.9 ms170.9 ms-3.0 ms
agent-summary.emit0.6 ms0.5 ms-0.1 ms
nitro.app.close0.0 ms0.0 ms0.0 ms
output.publish3.7 ms3.7 ms0.0 ms
workspace.remove5.7 ms5.8 ms+0.1 ms

createWorkflowWorldPluginSource encoded the world selection three times: a
nested ternary for the createWorld statement, a repeated condition for the
runtime imports, and another for the vendored module specifier. The pieces
co-vary — a world constructed through an explicit createWorld(config) call
must not import createWorldFromModule — so hiding that invariant across
three expressions made every new world branch risky to add.
resolveWorkflowWorldWiring now owns all four facts per world; the caller is
pure assembly. Generated output is byte-identical for the world-local,
world-vercel, and passthrough branches (verified by rendering both versions
and comparing).
Signed-off-by: Rui Conti <ruiconti@gmail.com>
gateway.ts exported its internals — buildGatewayURL, addGatewayUA,
buildGatewayUA, isGatewayModel — and every call site reassembled them:
URLs were rebuilt locally, and model-conditional header logic leaked as
isGatewayModel(...) ? Object.fromEntries(addGatewayUA(...)) : undefined.
The module now owns the decisions instead of the parts:
- AI_GATEWAY_MODELS_URL / AI_GATEWAY_MODELS_CATALOG_URL live in gateway.ts.
- getVercelGatewayFetch() returns a UA-decorated fetch, mirroring the
Sandbox binding's getVercelSandboxFetch — call sites get a transport,
not header plumbing. validate-gateway-key routes its provider fetch
through it instead of construction headers.
- resolveProviderHeaders(model) answers "which headers does this model's
provider need" directly; isGatewayModel is private again.
The generic fetch decoration moves from the sandbox-named
withSandboxUserAgent to withPackageUserAgent in internal/user-agent.ts
(the sandbox binding and the gateway both wrap it). Its default now
resolves globalThis.fetch per request instead of capturing it at wrap
time, so globally installed fetch instrumentation still applies.
Signed-off-by: Rui Conti <ruiconti@gmail.com>
The world-wiring branches built their return values from inline
expressions and join("\n") arrays. Name the intermediates and write the
generated snippets as leading-newline template literals (trimStart keeps
the emitted text starting at the statement), so each branch reads as: the
specifiers, the code it emits, the wiring object.
Generated output is byte-identical for all three branches (verified by
rendering the HEAD version and this one against the same inputs).
Signed-off-by: Rui Conti <ruiconti@gmail.com>
withPackageUserAgent resolves globalThis.fetch per request when no inner
fetch is given, so later-installed global fetch instrumentation still
applies. Passing globalThis.fetch explicitly here captured it at
options-build time, quietly opting the sandbox path out of that contract
while the gateway path honored it.
Signed-off-by: Rui Conti <ruiconti@gmail.com>
…ever casts
ai/test's mock satisfies the LanguageModel contract, so the
resolveProviderHeaders tests no longer need to cast partial objects.
Same pattern tool-loop.test.ts already uses.
Signed-off-by: Rui Conti <ruiconti@gmail.com>
@vercel
vercelBottemporarily deployed to Preview – eve-docs-1644 July 20, 2026 06:51 Inactive
@vercel
vercelBottemporarily deployed to Preview – eve-docs-4759 July 20, 2026 06:51 Inactive
@ruiconti
ruiconti marked this pull request as ready for review July 20, 2026 15:20
Comment threadpackages/eve/src/compiler/model-catalog.ts Outdated
Comment on lines +5 to +6
const { name, version } = resolveInstalledPackageInfo();
return `${name}/${version}`;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we include agent name as well?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can infer project via deploymentId which is already part of User-Agent. Unless you were thinking of some other use for it

getVercelGatewayFetch() mirrored the Sandbox binding's factory shape, but
unlike getVercelSandboxFetch(createOptions) it had nothing to construct —
call sites read getVercelGatewayFetch()(url). withPackageUserAgent
late-binds globalThis.fetch per request, so a module-level const is safe
and the call sites become plain vercelGatewayFetch(url).
Signed-off-by: Rui Conti <ruiconti@gmail.com>
…ification
Signed-off-by: Rui Conti <ruiconti@gmail.com>
# Conflicts:
#	packages/eve/src/setup/boxes/select-model.test.ts
#	packages/eve/src/setup/boxes/select-model.ts
@AndrewBarba
AndrewBarba enabled auto-merge (squash) July 20, 2026 23:49
@AndrewBarba
AndrewBarba merged commit 938ef92 into mainJul 21, 2026
139 of 152 checks passed
@AndrewBarba
AndrewBarba deleted the rui/eve-service-identification branch July 21, 2026 00:03
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@ruiconti@AndrewBarba@ctgowrie
, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); feat(eve): identify eve on AI Gateway, Workflow, and Sandbox requests by ruiconti · Pull Request #939 · vercel/eve · GitHub
Skip to content

feat(eve): identify eve on AI Gateway, Workflow, and Sandbox requests - #939

Merged
AndrewBarba merged 11 commits into
mainfrom
rui/eve-service-identification
Jul 21, 2026
Merged

feat(eve): identify eve on AI Gateway, Workflow, and Sandbox requests#939
AndrewBarba merged 11 commits into
mainfrom
rui/eve-service-identification

Conversation

@ruiconti

@ruicontiruiconti commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

Vercel services can't tell eve traffic from any other AI SDK app today. This appends an eve/<installed version> User-Agent product token to every service request eve makes, so receivers can attribute traffic to eve and its version — segmenting by framework during incidents and, later, controlling traffic keyed on the same token.

What

  • internal/user-agent.ts: builds the eve/<version> product token, appends it to a Headers without touching existing products (idempotent, space-joined per the RFC 9110 UA grammar — not Headers.append(), whose comma-combination breaks whitespace-delimited parsers), and exposes withPackageUserAgent(fetch), the generic UA-decorating fetch wrapper both the Gateway and Sandbox transports build on.
  • internal/gateway.ts owns the Gateway transport surface: the /v1/models and /v1/models/catalog URLs, getVercelGatewayFetch() (a UA-decorated fetch, mirroring the Sandbox binding's getVercelSandboxFetch), and resolveProviderHeaders(model) — headers for Gateway-routed models (bare ids and gateway.* instances), undefined for direct providers.
  • AI Gateway call sites: tool-loop generation and compaction, autoeval judge calls, model catalog, setup catalog, CLI model lookup, API-key validation — all through the two helpers above; no call site does header plumbing or URL assembly.
  • Workflow: generated world-vercel startup code passes the token via createWorld({ headers }), with the per-world wiring dispatched in one place (resolveWorkflowWorldWiring).
  • Sandbox: the SDK fetch decoration reuses withPackageUserAgent. A separate commit fixes a real gap here: Sandbox.get() lost the custom fetch on the credential-discovery failure path.

Wire format

Captured against a local server through the real ai/@ai-sdk/gateway packages — existing products stay intact:

eve/0.24.6 ai/7.0.26 ai-sdk/provider-utils/5.0.9 runtime/node.js/26

The Workflow leg is inert until a vendored bump

The vendored @workflow/world-vercel@5.0.0-beta.31 overwrites caller User-Agents, so the header this PR passes is dropped on the wire today (requests degrade to current behavior — nothing fails). vercel/workflow#2998 fixes the append; a follow-up bump of the vendored package lights this leg up.

Compaction attribution fix

Gateway attribution headers for compaction were previously computed from the main model; they now derive from the compaction model itself, since the two can differ.

…ery fails
getVercelSandboxGetOptions only attached the fetch override in the
credential-discovery success branch, so on the catch path Sandbox.get()
fell back to the SDK's bare global fetch. Move the fetch into the shared
base options so both branches use it.
Signed-off-by: Rui Conti <ruiconti@gmail.com>
Append an eve/<installed version> User-Agent product token to every
Vercel-service request eve makes, so receiving services can attribute
traffic to eve and its version without new headers or protocols:
- AI Gateway: model generation and compaction (tool-loop), autoeval
judge calls, the model catalog and setup catalog fetches, CLI model
lookup, and API-key validation. Gateway-routed models are detected via
isGatewayModel (bare ids and gateway.* instances).
- Workflow: generated world-vercel startup code passes the token via
createWorld({ headers }). Inert until the vendored @workflow/world-vercel
ships the caller User-Agent append (currently 5.0.0-beta.31, which
discards caller UA) — requests degrade to today's behavior, no failure.
- Sandbox: the SDK fetch decoration is generalized from the eve-specific
helper to appendPackageUserAgent.
The token is appended per the RFC 9110 User-Agent grammar (whitespace-
delimited products), never replacing existing products, idempotent on
re-append. Receivers parse it with whitespace-token scanners, so joining
uses spaces, not Headers.append() comma-combination.
Signed-off-by: Rui Conti <ruiconti@gmail.com>
@vercel

vercelBot commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

ProjectDeploymentActionsUpdated (UTC)
eve-docsReadyReadyPreview, CommentJul 20, 2026 11:50pm
eve-docs-1644ReadyReadyPreview, Comment, Open in v0Jul 20, 2026 11:50pm
eve-docs-4759ReadyReadyPreview, Comment, Open in v0Jul 20, 2026 11:50pm

Request Review

@github-actions

github-actionsBot commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

Bundle + Package Summary: apps/fixtures/weather-agent

Key takeaways

  • No notable deltas vs main (d034e01).

Delta vs main (d034e01)

AreaMetricBaselineCurrentDelta
PackagePacked tarball3.80 MB3.81 MB+636 B ⚠️
PackageUnpacked publish size13.77 MB13.78 MB+3.6 kB ⚠️
PackageInstalled footprint52.88 MB52.89 MB+3.6 kB ⚠️
PackagePublished files27222724+2
PackageInstalled files59625964+2
RuntimeUnique function payloads220
RuntimeTotal function bytes9.75 MB9.75 MB+3 B ⚠️
RuntimePublic routes10100
Changed function payloads vs main (d034e01) (2)
FunctionStatusBaselineCurrentDeltaRoute changes
functions/.well-known/workflow/v1/flow.funcchanged6.28 MB6.28 MB+191 B ⚠️none
functions/__server.funcchanged3.47 MB3.47 MB-188 B ✅none

eve init install

MetricBaselineCurrentDelta
Installed footprint91.29 MB91.29 MB+3.6 kB ⚠️
Installed packages1221220
dependencies440
devDependencies220
Dependency package bytes28.02 MB28.03 MB+3.6 kB ⚠️
devDependency package bytes5.04 MB5.04 MB0 B ➖
Build Metadata
  • Preset: vercel
  • Nitro: nitro@3.0.260610-beta
  • Output directory: apps/fixtures/weather-agent/.vercel/output
  • Build metadata timestamp: 2026-07-20T23:51:17.985Z
  • Route aliases: 10 public, 1 internal (11 total aliases)
  • Vercel routes in config: 11
  • Severity legend: 🔴 dominant/large, 🟠 notable, 🟡 watch, ⚪ small
Package Drill-Down

Package Details

  • Package: eve@0.26.1
  • Package directory: packages/eve
  • Tarball: 3.81 MB (eve-0.26.1.tgz)
  • Unpacked payload: 13.78 MB across 2724 published files
  • Installed footprint: 52.89 MB across 5964 installed files
  • Installed root package: 12.50 MB
  • Installed dependencies: 40.39 MB
  • Runtime dependencies: 1
  • Peer dependencies: 5 (4 optional)

Installed footprint is measured from an isolated temporary npm install of the packed tarball.

Heavy installed dependencies

  • @rolldown/binding-linux-x64-gnu: 18.96 MB (35.8%)
  • eve: 12.50 MB (23.6%)
  • ai: 6.39 MB (12.1%)
  • zod: 5.04 MB (9.5%)
  • nitro: 2.41 MB (4.6%)
Publish payload breakdown
Published file size
🟠 dist/src/compiled/experimental-ai-sdk-code-mo... [###.....................] 1.51 MB 10.9%
🟡 dist/src/compiled/@vercel/sandbox/index.js [#.......................] 622.2 kB 4.5%
🟡 dist/src/compiled/_chunks/workflow/undici-fb5... [#.......................] 502.4 kB 3.6%
🟡 dist/src/compiled/@chat-adapter/slack/index.js [#.......................] 433.3 kB 3.1%
🟡 dist/src/compiled/_chunks/workflow/dist-CSfKN... [#.......................] 277.8 kB 2.0%
🔴 Other published files [########################] 10.44 MB 75.7%
Installed footprint breakdown
Installed package size
🔴 @rolldown/binding-linux-x64-gnu [########################] 18.96 MB 35.8%
🔴 eve [################........] 12.50 MB 23.6%
🔴 ai [########................] 6.39 MB 12.1%
🔴 zod [######..................] 5.04 MB 9.5%
🟠 nitro [###.....................] 2.41 MB 4.6%
🟡 @ai-sdk/provider-utils [#.......................] 847.6 kB 1.6%
🔴 Other installed packages [#########...............] 6.74 MB 12.7%
Runtime dependencies (1)
PackageRangeNotes
nitro3.0.260610-beta
Peer dependencies (5)
PackageRangeNotes
@opentelemetry/api^1.0.0optional peer
aicatalog:
braintrust^3.0.0optional peer
just-bash^3.0.0optional peer
microsandbox^0.5.0optional peer
eve init install drill-down

eve init install details

  • Command: eve init my-agent
  • Package manager: npm
  • Installed footprint: 91.29 MB across 7832 installed files
  • Installed packages: 122 total (116 transitive-only)
  • dependencies: 4 direct packages totaling 28.03 MB
  • devDependencies: 2 direct packages totaling 5.04 MB
  • Other transitive package files: 58.22 MB

Installed footprint is measured from an isolated temporary eve init my-agent using the current packed eve tarball.

Heavy installed dependencies

  • @typescript/typescript-linux-x64: 27.95 MB (30.6%)
  • @rolldown/binding-linux-x64-gnu: 18.96 MB (20.8%)
  • eve: 12.50 MB (13.7%)
  • zod: 9.00 MB (9.9%)
  • ai: 6.39 MB (7.0%)
Installed footprint breakdown
Installed package size
🔴 @typescript/typescript-linux-x64 [########################] 27.95 MB 30.6%
🔴 @rolldown/binding-linux-x64-gnu [################........] 18.96 MB 20.8%
🔴 eve [###########.............] 12.50 MB 13.7%
🔴 zod [########................] 9.00 MB 9.9%
🔴 ai [#####...................] 6.39 MB 7.0%
🟠 @types/node [##......................] 2.54 MB 2.8%
🔴 Other installed packages [############............] 13.95 MB 15.3%
dependencies (4)
PackageRangeInstalled sizeShare
@vercel/connect0.4.0135.4 kB0.1%
ai^7.0.266.39 MB7.0%
evefile:eve-0.26.1.tgz12.50 MB13.7%
zod4.4.39.00 MB9.9%
devDependencies (2)
PackageRangeInstalled sizeShare
@types/node24.x2.54 MB2.8%
typescript7.0.22.50 MB2.7%
Function Drill-Down

Payload Size Graph

Unique function payload size and share of total
🔴 functions/.well-known/workflow/v1/flow.func [########################] 6.28 MB 64.4%
🟠 functions/__server.func [#############...........] 3.47 MB 35.6%

Top Function Payloads

🟠 functions/.well-known/workflow/v1/flow.func • 1 public route • 6.28 MB
MetricValue
Public routes/.well-known/workflow/v1/flow
Runtimenodejs24.x
Handlerindex.mjs
Payload6.28 MB
Function files6.28 MB across 37 files
Traced dependencies0 B
Signal🟠 Bundled file __eve_nitro_handler__.mjs is 2.21 MB (35.2%)

🟠 🔎 Dependency Analysis

📦 Bundled files:

Bundled file size
🟠 __eve_nitro_handler__.mjs [########################] 2.21 MB 35.2%
🟡 _chunks/world-vercel.mjs [#########...............] 826.3 kB 13.2%
🟡 _chunks/sandbox.mjs [########................] 754.9 kB 12.0%
🟡 _libs/@ai-sdk/gateway+[...].mjs [#####...................] 430.4 kB 6.9%
🟡 _libs/zod.mjs [####....................] 376.1 kB 6.0%
🟠 Other bundled files [##################......] 1.68 MB 26.8%

🧾 Vercel Config

{
"handler": "index.mjs",
"launcherType": "Nodejs",
"shouldAddHelpers": false,
"supportsResponseStreaming": true,
"runtime": "nodejs24.x",
"environment": {
"NODE_OPTIONS": "--experimental-require-module"
},
"maxDuration": "max",
"experimentalTriggers": [
{
"type": "queue/v2beta",
"topic": "__eve776561746865722d6167656e74_wkf_workflow_*",
"consumer": "default",
"retryAfterSeconds": 5,
"initialDelaySeconds": 0
}
]
}

🟠 functions/__server.func • 9 public routes, 1 internal alias • 3.47 MB
MetricValue
Public routes/
/eve/v1/callback/[token]
/eve/v1/connections/[name]/callback/[token]
/eve/v1/health
/eve/v1/info
/eve/v1/session
/eve/v1/session/[sessionId]
/eve/v1/session/[sessionId]/cancel
/eve/v1/session/[sessionId]/stream
Internal aliases/__server
Runtimenodejs24.x
Handlerindex.mjs
Payload3.47 MB
Function files3.47 MB across 28 files
Traced dependencies0 B
Signal🟠 Bundled file _chunks/runtime-artifacts.mjs is 949.0 kB (27.3%)

🟠 🔎 Dependency Analysis

📦 Bundled files:

Bundled file size
🟠 _chunks/runtime-artifacts.mjs [########################] 949.0 kB 27.3%
🟠 _chunks/world-vercel.mjs [#####################...] 823.4 kB 23.7%
🟠 _chunks/sandbox.mjs [###################.....] 754.9 kB 21.8%
🟡 _chunks/dist-CSfKNxQW.mjs [#########...............] 348.5 kB 10.0%
⚪ _libs/zod.mjs [###.....................] 114.2 kB 3.3%
🟡 Other bundled files [############............] 480.2 kB 13.8%

🧾 Vercel Config

{
"handler": "index.mjs",
"launcherType": "Nodejs",
"shouldAddHelpers": false,
"supportsResponseStreaming": true,
"runtime": "nodejs24.x"
}

Build Timing: e2e/fixtures/agent-tools-sandbox

This is an informational timing measurement inside eve build, from preflight through publication. Output-size measurement and profile writing are excluded.

Build mode: deployable Vercel build with sandbox template prewarm included.

  • Build pipeline: 2.41 s -> 2.38 s (-36.9 ms) vs main (d034e01).
  • Timing is informational: shared GitHub runners are too variable for a hard timing budget.
Detailed phase timings vs `main (d034e01)`
PhaseBaselineCurrentDelta
extension.check1.1 ms0.9 ms-0.2 ms
project.resolve0.7 ms0.6 ms-0.1 ms
workspace.create0.9 ms0.7 ms-0.2 ms
host.prepare230.6 ms230.3 ms-0.3 ms
vercel.service-prefix.resolve2.1 ms2.1 ms0.0 ms
nitro.app.create24.3 ms24.2 ms-0.1 ms
nitro.app.cache.prepare0.2 ms0.2 ms0.0 ms
nitro.app.prepare0.9 ms0.8 ms-0.1 ms
nitro.app.public-assets0.7 ms0.7 ms0.0 ms
nitro.app.prerender0.5 ms0.5 ms0.0 ms
nitro.app.bundle547.7 ms554.9 ms+7.2 ms
nitro.app.cache.write0.5 ms0.4 ms-0.1 ms
sandbox.prewarm278.3 ms260.6 ms-17.7 ms
nitro.flow.create185.2 ms178.8 ms-6.4 ms
nitro.flow.cache.prepare0.2 ms0.2 ms0.0 ms
nitro.flow.prepare0.9 ms0.9 ms0.0 ms
nitro.flow.public-assets0.2 ms0.2 ms0.0 ms
nitro.flow.prerender0.0 ms0.0 ms0.0 ms
nitro.flow.bundle952.2 ms935.9 ms-16.3 ms
nitro.flow.cache.write0.3 ms0.3 ms0.0 ms
nitro.flow.close0.2 ms0.2 ms0.0 ms
workflow.emit173.9 ms170.9 ms-3.0 ms
agent-summary.emit0.6 ms0.5 ms-0.1 ms
nitro.app.close0.0 ms0.0 ms0.0 ms
output.publish3.7 ms3.7 ms0.0 ms
workspace.remove5.7 ms5.8 ms+0.1 ms

createWorkflowWorldPluginSource encoded the world selection three times: a
nested ternary for the createWorld statement, a repeated condition for the
runtime imports, and another for the vendored module specifier. The pieces
co-vary — a world constructed through an explicit createWorld(config) call
must not import createWorldFromModule — so hiding that invariant across
three expressions made every new world branch risky to add.
resolveWorkflowWorldWiring now owns all four facts per world; the caller is
pure assembly. Generated output is byte-identical for the world-local,
world-vercel, and passthrough branches (verified by rendering both versions
and comparing).
Signed-off-by: Rui Conti <ruiconti@gmail.com>
gateway.ts exported its internals — buildGatewayURL, addGatewayUA,
buildGatewayUA, isGatewayModel — and every call site reassembled them:
URLs were rebuilt locally, and model-conditional header logic leaked as
isGatewayModel(...) ? Object.fromEntries(addGatewayUA(...)) : undefined.
The module now owns the decisions instead of the parts:
- AI_GATEWAY_MODELS_URL / AI_GATEWAY_MODELS_CATALOG_URL live in gateway.ts.
- getVercelGatewayFetch() returns a UA-decorated fetch, mirroring the
Sandbox binding's getVercelSandboxFetch — call sites get a transport,
not header plumbing. validate-gateway-key routes its provider fetch
through it instead of construction headers.
- resolveProviderHeaders(model) answers "which headers does this model's
provider need" directly; isGatewayModel is private again.
The generic fetch decoration moves from the sandbox-named
withSandboxUserAgent to withPackageUserAgent in internal/user-agent.ts
(the sandbox binding and the gateway both wrap it). Its default now
resolves globalThis.fetch per request instead of capturing it at wrap
time, so globally installed fetch instrumentation still applies.
Signed-off-by: Rui Conti <ruiconti@gmail.com>
The world-wiring branches built their return values from inline
expressions and join("\n") arrays. Name the intermediates and write the
generated snippets as leading-newline template literals (trimStart keeps
the emitted text starting at the statement), so each branch reads as: the
specifiers, the code it emits, the wiring object.
Generated output is byte-identical for all three branches (verified by
rendering the HEAD version and this one against the same inputs).
Signed-off-by: Rui Conti <ruiconti@gmail.com>
withPackageUserAgent resolves globalThis.fetch per request when no inner
fetch is given, so later-installed global fetch instrumentation still
applies. Passing globalThis.fetch explicitly here captured it at
options-build time, quietly opting the sandbox path out of that contract
while the gateway path honored it.
Signed-off-by: Rui Conti <ruiconti@gmail.com>
…ever casts
ai/test's mock satisfies the LanguageModel contract, so the
resolveProviderHeaders tests no longer need to cast partial objects.
Same pattern tool-loop.test.ts already uses.
Signed-off-by: Rui Conti <ruiconti@gmail.com>
@vercel
vercelBottemporarily deployed to Preview – eve-docs-1644 July 20, 2026 06:51 Inactive
@vercel
vercelBottemporarily deployed to Preview – eve-docs-4759 July 20, 2026 06:51 Inactive
@ruiconti
ruiconti marked this pull request as ready for review July 20, 2026 15:20
Comment threadpackages/eve/src/compiler/model-catalog.ts Outdated
Comment on lines +5 to +6
const { name, version } = resolveInstalledPackageInfo();
return `${name}/${version}`;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we include agent name as well?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can infer project via deploymentId which is already part of User-Agent. Unless you were thinking of some other use for it

getVercelGatewayFetch() mirrored the Sandbox binding's factory shape, but
unlike getVercelSandboxFetch(createOptions) it had nothing to construct —
call sites read getVercelGatewayFetch()(url). withPackageUserAgent
late-binds globalThis.fetch per request, so a module-level const is safe
and the call sites become plain vercelGatewayFetch(url).
Signed-off-by: Rui Conti <ruiconti@gmail.com>
…ification
Signed-off-by: Rui Conti <ruiconti@gmail.com>
# Conflicts:
#	packages/eve/src/setup/boxes/select-model.test.ts
#	packages/eve/src/setup/boxes/select-model.ts
@AndrewBarba
AndrewBarba enabled auto-merge (squash) July 20, 2026 23:49
@AndrewBarba
AndrewBarba merged commit 938ef92 into mainJul 21, 2026
139 of 152 checks passed
@AndrewBarba
AndrewBarba deleted the rui/eve-service-identification branch July 21, 2026 00:03
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@ruiconti@AndrewBarba@ctgowrie