feat(eve): add direct Codex model auth#417
Draft
ruiconti wants to merge 12 commits into
Draft
Conversation
Add an experimental eve/codex adapter backed by the local Codex CLI app-server, including Codex model catalog lookup for compile/setup flows and /model source rewrites for experimental_codex. Warn during production builds when a compiled manifest uses Codex subscription models, since /info should stay a runtime inspection contract. Signed-off-by: Rui Conti <ruiconti@gmail.com>
Contributor
|
The latest updates on your projects. Learn more about Vercel for GitHub.
1 Skipped Deployment
|
Contributor
Bundle + Package Summary:
|
| Area | Metric | Baseline | Current | Delta |
|---|---|---|---|---|
| Package | Packed tarball | 3.48 MB | 3.50 MB | +11.2 kB |
| Package | Unpacked publish size | 12.66 MB | 12.71 MB | +46.7 kB |
| Package | Installed footprint | 52.68 MB | 52.72 MB | +46.7 kB |
| Package | Published files | 2378 | 2398 | +20 |
| Package | Installed files | 5587 | 5607 | +20 |
| Runtime | Unique function payloads | 2 | 2 | 0 |
| Runtime | Total function bytes | 9.20 MB | 9.20 MB | +2.6 kB |
| Runtime | Public routes | 9 | 9 | 0 |
Changed function payloads vs main (70ebe69) (2)
| Function | Status | Baseline | Current | Delta | Route changes |
|---|---|---|---|---|---|
functions/__server.func |
changed | 3.47 MB | 3.47 MB | +1.4 kB |
none |
functions/.well-known/workflow/v1/flow.func |
changed | 5.73 MB | 5.73 MB | +1.2 kB |
none |
Build Metadata
- Preset:
vercel - Nitro:
nitro@3.0.260610-beta - Output directory:
apps/fixtures/weather-agent/.vercel/output - Build metadata timestamp: 2026-06-30T00:53:25.361Z
- Route aliases: 9 public, 1 internal (10 total aliases)
- Vercel routes in config: 10
- Severity legend: 🔴 dominant/large, 🟠 notable, 🟡 watch, ⚪ small
Package Drill-Down
Package Details
- Package:
eve@0.17.1 - Package directory:
packages/eve - Tarball: 3.50 MB (
eve-0.17.1.tgz) - Unpacked payload: 12.71 MB across 2398 published files
- Installed footprint: 52.72 MB across 5607 installed files
- Installed root package: 11.44 MB
- Installed dependencies: 41.28 MB
- Runtime dependencies: 1
- Peer dependencies: 12 (11 optional)
Installed footprint is measured from an isolated temporary npm install of the packed tarball.
Heavy installed dependencies
@rolldown/binding-linux-x64-gnu: 20.26 MB (38.4%)eve: 11.44 MB (21.7%)ai: 6.28 MB (11.9%)zod: 5.04 MB (9.6%)nitro: 2.41 MB (4.6%)
Publish payload breakdown
Published file size
🟠 dist/src/compiled/experimental-ai-sdk-code-mo... [####....................] 1.51 MB 11.8%
🟡 dist/src/compiled/@workflow/core/runtime.js [##......................] 794.4 kB 6.3%
🟡 dist/src/compiled/@vercel/sandbox/index.js [##......................] 632.0 kB 5.0%
🟡 dist/src/compiled/@chat-adapter/slack/index.js [#.......................] 436.6 kB 3.4%
🟡 dist/src/compiled/_chunks/workflow/attribute-... [#.......................] 371.6 kB 2.9%
🔴 Other published files [########################] 8.97 MB 70.6%
Installed footprint breakdown
Installed package size
🔴 @rolldown/binding-linux-x64-gnu [########################] 20.26 MB 38.4%
🔴 eve [##############..........] 11.44 MB 21.7%
🔴 ai [#######.................] 6.28 MB 11.9%
🔴 zod [######..................] 5.04 MB 9.6%
🟠 nitro [###.....................] 2.41 MB 4.6%
🟡 rolldown [#.......................] 771.7 kB 1.5%
🔴 Other installed packages [########................] 6.53 MB 12.4%
Runtime dependencies (1)
| Package | Range | Notes |
|---|---|---|
nitro |
3.0.260610-beta |
Peer dependencies (12)
| Package | Range | Notes |
|---|---|---|
@opentelemetry/api |
^1.0.0 |
optional peer |
@sveltejs/kit |
^2.0.0 |
optional peer |
ai |
catalog: |
|
braintrust |
^3.0.0 |
optional peer |
just-bash |
^3.0.0 |
optional peer |
microsandbox |
^0.5.0 |
optional peer |
next |
^16.0.0 |
optional peer |
nuxt |
^4.0.0 |
optional peer |
react |
^19.0.0 |
optional peer |
svelte |
^5.0.0 |
optional peer |
vite |
^8.0.0 |
optional peer |
vue |
^3.5.0 |
optional peer |
Function Drill-Down
Payload Size Graph
Unique function payload size and share of total
🔴 functions/.well-known/workflow/v1/flow.func [########################] 5.73 MB 62.3%
🟠 functions/__server.func [###############.........] 3.47 MB 37.7%
Top Function Payloads
🟠 functions/.well-known/workflow/v1/flow.func • 1 public route • 5.73 MB
| Metric | Value |
|---|---|
| Public routes | /.well-known/workflow/v1/flow |
| Runtime | nodejs24.x |
| Handler | index.mjs |
| Payload | 5.73 MB |
| Function files | 5.73 MB across 26 files |
| Traced dependencies | 0 B |
| Signal | 🟠 Bundled file __eve_nitro_handler__.mjs is 1.96 MB (34.2%) |
🟠 🔎 Dependency Analysis
📦 Bundled files:
Bundled file size
🟠 __eve_nitro_handler__.mjs [########################] 1.96 MB 34.2%
🟠 _chunks/runtime.mjs [############............] 983.9 kB 17.2%
🟡 _chunks/sandbox.mjs [#########...............] 766.0 kB 13.4%
🟡 _chunks/attribute-changes-zAifvEhb.mjs [######..................] 473.4 kB 8.3%
🟡 _libs/@ai-sdk/gateway+[...].mjs [#####...................] 413.5 kB 7.2%
🟠 Other bundled files [##############..........] 1.14 MB 19.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 • 8 public routes, 1 internal alias • 3.47 MB
| Metric | Value |
|---|---|
| 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]/stream |
| Internal aliases | /__server |
| Runtime | nodejs24.x |
| Handler | index.mjs |
| Payload | 3.47 MB |
| Function files | 3.47 MB across 19 files |
| Traced dependencies | 0 B |
| Signal | 🟠 Bundled file index.mjs is 992.2 kB (28.6%) |
🟠 🔎 Dependency Analysis
📦 Bundled files:
Bundled file size
🟠 index.mjs [########################] 992.2 kB 28.6%
🟠 _chunks/runtime.mjs [######################..] 891.6 kB 25.7%
🟠 _chunks/sandbox.mjs [###################.....] 766.0 kB 22.1%
🟡 _chunks/attribute-changes-zAifvEhb.mjs [###########.............] 449.0 kB 12.9%
⚪ _libs/zod.mjs [###.....................] 114.2 kB 3.3%
🟡 Other bundled files [######..................] 255.4 kB 7.4%
🧾 Vercel Config
{
"handler": "index.mjs",
"launcherType": "Nodejs",
"shouldAddHelpers": false,
"supportsResponseStreaming": true,
"runtime": "nodejs24.x"
}Signed-off-by: Rui Conti <ruiconti@gmail.com>
Signed-off-by: Rui Conti <ruiconti@gmail.com>
42a5a67 to
b963f71
Compare
b963f71 to
95c732f
Compare
95c732f to
8d3de52
Compare
8d3de52 to
a49c5e0
Compare
Signed-off-by: Rui Conti <ruiconti@gmail.com>
a49c5e0 to
c937269
Compare
Move model-endpoint-auth/* and codex-model-catalog under
internal/model-auth/endpoint/ and rework the codex internals:
- auth.json parses once into a {state, credentials} snapshot; a single
selectCodexCredentials picks the active login (an explicit auth_mode
wins when its credential is usable, otherwise usable ChatGPT tokens
outrank an API key), so the status view and the transport can no
longer disagree over stale mode markers or residual tokens.
- resolveCodexEndpointStatus reads auth.json once per /info, not twice.
- the transport drops its whole-body store:false JSON rewrite; the
model wrapper owns that invariant, the transport owns credentials and
the endpoint rewrite.
- the model wrapper strips OpenAI itemIds copy-on-write instead of
structuredClone-ing the entire prompt on every call.
- JWT payloads decode via vendored jose decodeJwt, local isRecord
copies defer to shared guards, and the codex tests share one
unsigned-JWT fixture.
Signed-off-by: Rui Conti <ruiconti@gmail.com>
Codex auth is now an explicit opt-in: only the development-gated
experimental.useCodexSubscription flag produces auth {kind:"codex"}.
classifyModelAuth no longer maps a provider named "codex" to codex
auth, so an authored LanguageModel with that provider name keeps its
own baseURL and credentials instead of being silently rerouted through
the local Codex login (previously in production builds too). The
runtime codex resolver drops the parallel codex/<slug> id grammar the
authoring surface already rejected.
auth becomes required on InternalAgentModelDefinition — the compiled
manifest schema already required it — deleting the routing-derived
`auth ?? modelAuthForRouting(routing)` fallbacks, which would have
misclassified a codex model as gateway had they ever fired. The
codex-in-production-build warning is deleted as provably dead code:
`eve build` compiles in production mode, where the flag is off, so a
production manifest can never carry codex auth.
The leftover eve/codex export surface is removed and the changeset is
rewritten to describe the flag that actually shipped. The dev TUI
setup-issues/status-line surfaces and docs follow the same semantics.
Signed-off-by: Rui Conti <ruiconti@gmail.com>
Replacing the client's inline agent-info schemas with the shared .strict() ones made client.info() throw on any field a newer server adds to model.routing or model.endpoint — exactly the kind of addition this branch itself makes. The endpoint-status schema is client-only, so it simply drops .strict(); model routing keeps the strict variant for compiled-manifest validation (where unknown keys mean compiler drift) and gains a strip-mode client variant built from the same shape objects, so the two cannot diverge. Signed-off-by: Rui Conti <ruiconti@gmail.com>
changeAgentModel now runs the uneditable-model refusal itself and derives the slug-validation boundary from the compiled model's auth, so the stringly ModelChangeValidation union and the modelChangePreflight / modelChangeRefusalForUneditableModel exports disappear, and both callers — the /model menu flow and the TUI's `/model <slug>` handler — stop threading validation state across the module boundary. The codex-transport-id rejection message is built in one place, and the openai/ id formatter moves into the codex catalog next to the prefix it formats. apply-model-name also loses the vestiges of the removed multi-property editor: applyStringLiteralChange is back to (source, literal, to), and findProperty/stringLiteralFromProperty re-merge into their single composition. Signed-off-by: Rui Conti <ruiconti@gmail.com>
Direct (non-gateway) AI_APICallError failures — the codex transport's error shape — now summarize with the nested API message when the body carries one, or an HTTP-status + response-body fallback otherwise. Two guards keep the summaries honest: transient 408/429/5xx failures return to the generic retry-exhausted framing instead of "AI Gateway model request rejected", and bare param/status field values are no longer promoted to user-facing messages (a 400 with param "input" previously surfaced as "Model provider API error: input"); structured error.code objects still are. The AI Gateway provider-attempt (providerMetadata.gateway.routing. modelAttempts) mining that rode along here is dropped: codex requests bypass the gateway, nothing else consumed it, and it deserves its own change. Signed-off-by: Rui Conti <ruiconti@gmail.com>
The exact Sandbox.get assertions only passed on machines without Vercel credentials: with env vars cleared, getVercelSandboxCredentials still falls through to getVercelOidcToken, which refreshes a real token from the local CLI login (network I/O in a unit test) and injects credentials, fetch, and signal into the lookup options — which is why 6c1d67f loosened the assertions to objectContaining. Mock the vendored @vercel/oidc module to fail instead, so every machine exercises the deterministic credential-less path CI sees and the exact { name, resume } contract is pinned again. Signed-off-by: Rui Conti <ruiconti@gmail.com>
Signed-off-by: Rui Conti <ruiconti@gmail.com>
The stored ModelAuth union was almost entirely derivable — ai-gateway
and external mirrored the model's routing, and codex was the only real
bit of information. Storing that derived classification forced auth
onto every model reference (and into ~40 test fixtures) for one flag's
worth of signal.
The compiled model reference now carries an optional
`transport?: "codex"` literal instead, set by the compiler only when
experimental.useCodexSubscription applies; absent means the model is
served by whatever its routing implies. The ModelAuth type,
modelAuthSchema, classifyModelAuth/cloneModelAuth, and the classify
module are deleted; endpoint status resolves from {routing, transport};
the /model flow reads a plain codex boolean; and every fixture file the
required-auth change touched reverts to its merge-base content. The
provider-name hijack fix holds by construction: nothing but the flag
path can set the marker.
Signed-off-by: Rui Conti <ruiconti@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of #44 and #131.
What changed
eve/codexwithexperimentalCodex({ model }), backed by the local Codex CLI auth file.internal/model-endpoint-authprobes AI Gateway OIDC/API-key state and Codex local auth for/eve/v1/info./modelflows to understandcodex/<slug>ids from the local Codex model catalog.Codex model auth
experimentalCodexcreates an OpenAI Responses model under thecodexprovider namespace. It does not startcodex app-server.For API-key Codex login state, eve sends the request to the normal OpenAI Responses endpoint with the key from
~/.codex/auth.json.For ChatGPT Codex login state, eve reads
~/.codex/auth.json, reuses a fresh access token when it can, and refreshes throughhttps://auth.openai.com/oauth/tokenwhen it needs to. ChatGPT-authenticated model calls go tohttps://chatgpt.com/backend-api/codex/responses. Refreshed tokens are written back to the Codex auth file so the next request sees the updated local login state.eve does not implement
codex login. The user still signs in with the Codex CLI.Endpoint readiness
model-auth/classifyonly decides the compiled auth tag: AI Gateway, Codex, or external provider. It does not read env, OIDC, or~/.codex.model-endpoint-auth/ai-gatewayandmodel-endpoint-auth/codexown the live credential checks. AI Gateway checksAI_GATEWAY_API_KEYfirst, then Vercel OIDC. Codex checks local Codex auth state and reports whether it has an API key, a fresh ChatGPT access token, or a ChatGPT refresh token. External providers still report only that they are external, because eve cannot inspect arbitrary provider credentials.resolve-model-endpoint-statusis the dispatcher used by/eve/v1/info. That status is parsed by the client schema and rendered in the dev TUI status line. Missing or invalid Codex login state now shows as a Codex endpoint warning instead of looking ready until the first model call fails.Catalog, setup, and source edits
The model catalog loader now recognizes
codex/<slug>ids. It asks the local Codex CLI forcodex debug models, falling back to the bundled CLI catalog when needed./modelgets a Codex-specific picker when the authored model usesexperimentalCodex({ model }). It rewrites only the helper's inner model literal. It still refuses to write Codex ids into Gateway string models, or Gateway ids into the Codex helper.Production build warning
eve buildwarns when the primary or compaction model uses Codex auth. This is a build-time warning, not a runtime block. The warning keeps deployment policy at the point where the artifact is produced.