Repository navigation
fix(eve): keep a turn's principal fixed for typed ctx.ask answers - #4925
Conversation
Bundle + Package Summary:
|
| Area | Metric | Baseline | Current | Delta |
|---|---|---|---|---|
| Package | Packed tarball | 7.90 MB | 7.90 MB | +925 B |
| Package | Unpacked publish size | 27.57 MB | 27.58 MB | +3.5 kB |
| Package | Installed footprint | 76.02 MB | 76.02 MB | +3.5 kB |
| Package | Published files | 4366 | 4366 | 0 |
| Package | Installed files | 8363 | 8363 | 0 |
| Package | Installed package instances | 34 | 34 | 0 |
| Package | Distinct installed package names | 32 | 32 | 0 |
| Package | Installed dependency edges | 51 | 51 | 0 |
| Package | Installed optional peer edges | 17 | 17 | 0 |
| Runtime | Unique function payloads | 2 | 2 | 0 |
| Runtime | Total function bytes | 21.86 MB | 21.87 MB | +7.8 kB |
| Runtime | Public routes | 18 | 18 | 0 |
Changed function payloads vs triage/issue-4923-repro (7deee87) (2)
| Function | Status | Baseline | Current | Delta | Route changes |
|---|---|---|---|---|---|
functions/__server.func |
changed | 10.93 MB | 10.94 MB | +3.9 kB |
none |
functions/.well-known/workflow/v1/flow.func |
changed | 10.93 MB | 10.94 MB | +3.9 kB |
none |
eve init install
| Metric | Baseline | Current | Delta |
|---|---|---|---|
| Installed footprint | 114.40 MB | 114.40 MB | +3.5 kB |
| Installed packages | 97 | 97 | 0 |
| dependencies | 4 | 4 | 0 |
| devDependencies | 2 | 2 | 0 |
| Dependency package bytes | 46.10 MB | 46.11 MB | +3.5 kB |
| devDependency package bytes | 5.11 MB | 5.11 MB | 0 B ➖ |
Build Metadata
- Preset:
vercel - Nitro:
nitro@3.0.260903-beta - Output directory:
apps/fixtures/weather-agent/.vercel/output - Build metadata timestamp: 2026-10-27T04:18:08.889Z
- Route aliases: 18 public, 1 internal (19 total aliases)
- Vercel routes in config: 21
- Severity legend: 🔴 dominant/large, 🟠 notable, 🟡 watch, ⚪ small
Package Drill-Down
Package Details
- Package:
eve@0.84.0 - Package directory:
packages/eve - Tarball: 7.90 MB (
eve-0.84.0.tgz) - Unpacked payload: 27.58 MB across 4366 published files
- Installed footprint: 76.02 MB across 8363 installed files
- Installed root package: 27.58 MB
- Installed dependencies: 48.44 MB
- Installed package instances: 34
- Distinct installed package names: 32
- Installed dependency edges: 51
- Installed optional peer edges: 17
- Runtime dependencies: 2
- Peer dependencies: 15 (14 optional)
Installed footprint is measured from an isolated temporary npm install of the packed tarball.
Graph metrics read only package.json files in package directories directly beneath a node_modules boundary, including nested boundaries. Each directory is one package instance; distinct names come from those manifests. Dependency edges count each unique name in dependencies or optionalDependencies per instance; optional peer edges count peerDependencies marked optional.
Heavy installed dependencies
eve: 27.58 MB (36.3%)@rolldown/binding-linux-x64-gnu: 19.89 MB (26.2%)ai: 8.50 MB (11.2%)zod: 6.15 MB (8.1%)undici: 3.58 MB (4.7%)
Publish payload breakdown
Published file size
🟠 dist/src/compiled/shadcn-registry/index.js [#####...................] 3.85 MB 14.0%
🟠 dist/src/compiled/@photon-ai/chat-adapter-ime... [###.....................] 2.29 MB 8.3%
🟠 dist/src/compiled/run/index.js [#.......................] 1.00 MB 3.6%
🟡 dist/src/compiled/@vercel/blob/index.js [#.......................] 604.9 kB 2.2%
🟡 dist/src/compiled/_chunks/workflow/undici-D-I... [#.......................] 521.9 kB 1.9%
🔴 Other published files [########################] 19.31 MB 70.0%
Installed footprint breakdown
Installed package size
🔴 eve [########################] 27.58 MB 36.3%
🔴 @rolldown/binding-linux-x64-gnu [#################.......] 19.89 MB 26.2%
🔴 ai [#######.................] 8.50 MB 11.2%
🔴 zod [#####...................] 6.15 MB 8.1%
🟠 undici [###.....................] 3.58 MB 4.7%
🟠 nitro [##......................] 1.89 MB 2.5%
🔴 Other installed packages [#######.................] 8.44 MB 11.1%
Runtime dependencies (2)
| Package | Range | Notes |
|---|---|---|
nitro |
3.0.260903-beta |
|
undici |
8.10.2 |
Peer dependencies (15)
| Package | Range | Notes |
|---|---|---|
@linqapp/sdk |
^0.47.1 |
optional peer |
@nuxt/kit |
^4.0.0 |
optional peer |
@nuxt/schema |
^4.0.0 |
optional peer |
@opentelemetry/api |
^1.0.0 |
optional peer |
@vercel/connect |
^2.5.2 |
optional peer |
ai |
catalog: |
|
braintrust |
^3.0.0 |
optional peer |
chat |
^4.42.0 |
optional peer |
dd-trace |
^6.13.0 |
optional peer |
just-bash |
^3.6.0 |
optional peer |
next |
^16.0.0 |
optional peer |
react |
^19.0.0 |
optional peer |
svelte |
^5.0.0 |
optional peer |
vite |
^8.3.1 |
optional peer |
vue |
^3.5.0 |
optional peer |
eve init install drill-down
eve init install details
- Command:
eve init my-agent - Package manager:
npm - Installed footprint: 114.40 MB across 10280 installed files
- Installed packages: 97 total (91 transitive-only)
- dependencies: 4 direct packages totaling 46.11 MB
- devDependencies: 2 direct packages totaling 5.11 MB
- Other transitive package files: 63.19 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 (24.4%)eve: 27.58 MB (24.1%)@rolldown/binding-linux-x64-gnu: 19.89 MB (17.4%)zod: 9.76 MB (8.5%)ai: 8.50 MB (7.4%)
Installed footprint breakdown
Installed package size
🔴 @typescript/typescript-linux-x64 [########################] 27.95 MB 24.4%
🔴 eve [########################] 27.58 MB 24.1%
🔴 @rolldown/binding-linux-x64-gnu [#################.......] 19.89 MB 17.4%
🔴 zod [########................] 9.76 MB 8.5%
🔴 ai [#######.................] 8.50 MB 7.4%
🟠 undici [###.....................] 3.58 MB 3.1%
🔴 Other installed packages [###############.........] 17.16 MB 15.0%
dependencies (4)
| Package | Range | Installed size | Share |
|---|---|---|---|
@vercel/connect |
2.5.2 |
276.3 kB | 0.2% |
ai |
^7.0.137 |
8.50 MB | 7.4% |
eve |
file:eve-0.84.0.tgz |
27.58 MB | 24.1% |
zod |
4.5.4 |
9.76 MB | 8.5% |
devDependencies (2)
| Package | Range | Installed size | Share |
|---|---|---|---|
@types/node |
24.x |
2.61 MB | 2.3% |
typescript |
7.0.2 |
2.50 MB | 2.2% |
Function Drill-Down
Payload Size Graph
Unique function payload size and share of total
🔴 functions/.well-known/workflow/v1/flow.func [########################] 10.94 MB 50.0%
🔴 functions/__server.func [########################] 10.94 MB 50.0%
Top Function Payloads
🟠 functions/.well-known/workflow/v1/flow.func • 1 public route • 10.94 MB
| Metric | Value |
|---|---|
| Public routes | /.well-known/workflow/v1/flow |
| Runtime | nodejs24.x |
| Handler | index.mjs |
| Payload | 10.94 MB |
| Function files | 10.94 MB across 124 files |
| Traced dependencies | 0 B |
| Signal | 🟠 Bundled file _chunks/vercel.web.mjs is 2.61 MB (23.8%) |
🟠 🔎 Dependency Analysis
📦 Bundled files:
Bundled file size
🟠 _chunks/vercel.web.mjs [#############...........] 2.61 MB 23.8%
🟡 _libs/undici.mjs [#####...................] 994.5 kB 9.1%
🟡 _chunks/sandbox2.mjs [#####...................] 937.1 kB 8.6%
🟡 _chunks/compiled-artifacts-instrumentation.mjs [####....................] 730.7 kB 6.7%
🟡 _chunks/token-util-Bla5Z0G9.mjs [###.....................] 704.5 kB 6.4%
🔴 Other bundled files [########################] 4.96 MB 45.4%
🧾 Vercel Config
{
"handler": "index.mjs",
"launcherType": "Nodejs",
"shouldAddHelpers": false,
"supportsResponseStreaming": true,
"runtime": "nodejs24.x",
"maxDuration": "max",
"experimentalTriggers": [
{
"type": "queue/v2beta",
"topic": "__eve776561746865722d6167656e74_wkf_workflow_*",
"consumer": "default",
"retryAfterSeconds": 5,
"initialDelaySeconds": 0
}
],
"environment": {
"WORKFLOW_PRECONDITION_GUARD": "1"
}
}🟠 functions/__server.func • 17 public routes, 1 internal alias • 10.94 MB
| Metric | Value |
|---|---|
| Public routes | //.well-known/workflow/v1/webhook/[token]/eve/v1/callback/[token]/eve/v1/connections/[name]/callback/[attemptId]/[token]/eve/v1/connections/[name]/callback/[token]/eve/v1/health/eve/v1/info/eve/v1/session/eve/v1/session/[parentSessionId]/subagents/[callId]/[childSessionId]/stream/eve/v1/session/[sessionId]/eve/v1/session/[sessionId]/cancel/eve/v1/session/[sessionId]/clear/eve/v1/session/[sessionId]/compact/eve/v1/session/[sessionId]/descendants/stream/eve/v1/session/[sessionId]/reset/eve/v1/session/[sessionId]/stream/eve/v1/session/[sessionId]/stubs |
| Internal aliases | /__server |
| Runtime | nodejs24.x |
| Handler | index.mjs |
| Payload | 10.94 MB |
| Function files | 10.94 MB across 124 files |
| Traced dependencies | 0 B |
| Signal | 🟠 Bundled file _chunks/vercel.web.mjs is 2.61 MB (23.8%) |
🟠 🔎 Dependency Analysis
📦 Bundled files:
Bundled file size
🟠 _chunks/vercel.web.mjs [#############...........] 2.61 MB 23.8%
🟡 _libs/undici.mjs [#####...................] 994.5 kB 9.1%
🟡 _chunks/sandbox2.mjs [#####...................] 937.1 kB 8.6%
🟡 _chunks/compiled-artifacts-instrumentation.mjs [####....................] 730.7 kB 6.7%
🟡 _chunks/token-util-Bla5Z0G9.mjs [###.....................] 704.5 kB 6.4%
🔴 Other bundled files [########################] 4.96 MB 45.4%
🧾 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: 3.74 s -> 4.10 s (+358.2 ms) vs
triage/issue-4923-repro (7deee87). - Timing is informational: shared GitHub runners are too variable for a hard timing budget.
Detailed phase timings vs `triage/issue-4923-repro (7deee87)`
| Phase | Baseline | Current | Delta |
|---|---|---|---|
extension.check |
7.0 ms | 0.5 ms | -6.5 ms |
project.resolve |
0.4 ms | 0.4 ms | 0.0 ms |
workspace.create |
0.6 ms | 0.6 ms | 0.0 ms |
host.prepare |
604.6 ms | 620.0 ms | +15.4 ms |
vercel.service-prefix.resolve |
1.9 ms | 2.1 ms | +0.2 ms |
nitro.create |
435.6 ms | 447.5 ms | +11.9 ms |
sandbox.prewarm |
474.9 ms | 564.7 ms | +89.8 ms |
nitro.cache.prepare |
0.3 ms | 0.4 ms | +0.1 ms |
nitro.prepare |
0.8 ms | 1.0 ms | +0.2 ms |
nitro.public-assets |
0.8 ms | 0.9 ms | +0.1 ms |
nitro.prerender |
0.5 ms | 0.5 ms | 0.0 ms |
nitro.bundle |
2.06 s | 2.31 s | +247.0 ms |
nitro.cache.write |
0.4 ms | 0.3 ms | -0.1 ms |
vercel.workflow-function.materialize |
56.7 ms | 56.1 ms | -0.6 ms |
agent-summary.emit |
0.6 ms | 0.7 ms | +0.1 ms |
connect-manifest.emit |
0.3 ms | 0.3 ms | 0.0 ms |
nitro.close |
0.1 ms | 0.1 ms | 0.0 ms |
output.publish |
3.3 ms | 3.6 ms | +0.3 ms |
workspace.remove |
3.1 ms | 2.8 ms | -0.3 ms |
807cb98 to
637ca94
Compare
637ca94 to
e6fb2c7
Compare
e6fb2c7 to
33ad90d
Compare
33ad90d to
db92a17
Compare
db92a17 to
e22c690
Compare
|
This session could not recover from an error (SerializationError: Failed to serialize stream chunk Start a new comment to continue. Error id: 6c9cc615-20fb-40df-a6b1-ff2278f9c1a5 |
|
CI on e2efed0 failed on two tests the rebase onto main left stale, not on the fix itself:
Repairs: 422cdc6 on #4924 switches the test to Run locally on 3525086: |
3525086 to
21aacc6
Compare
|
The only failure on 21aacc6 was in |
|
Attempt 2 of run 40359632606 failed again, still only in This isn't from this PR: I'm not rerunning again, because it has already been retried and also fails on |
21aacc6 to
d5b5de1
Compare
|
Run 40369187484 on This PR doesn't touch tracing or content capture, so I'm treating it as transient trace-export timing and re-ran the failed job once. |
|
CI run 40369187435 on |
|
Attempt 2 of run 40369187435 failed again in That test passed on this same head in attempt 1 on Windows and in both Linux integration runs. That points to Windows timing flakiness rather than a deterministic regression, but I haven't proven it: this PR does touch turn joining, so a race in turn ordering is possible. The job has already been retried, so I'm not rerunning it again. The cheapest check is to run |
Another principal's typed text could answer a running turn's ctx.ask, ask_question or relayed child prompt and drive the turn under its auth, and a mixed delivery's stale answer let that sender stand in as the turn's caller. Only the turn's own principal now joins its turn by text, with refreshed claims; another principal's text waits for its own turn, each answer to an open approval carries its responder, and another principal's answer to a request that is no longer open is dropped. Signed-off-by: ruiconti <1834568+ruiconti@users.noreply.github.com>
d5b5de1 to
3eaca67
Compare
|
E2E (Vercel) run 40444125995 on That eval runs a single mock-model subagent call with no |
|
Both CI runs on
Recent |
…e session A typed answer whose payload also carried channel state or client context left a remainder for the parent, so the answer never joined the turn's auth and the turn kept the asking request's claims. The claims now update whenever the owner's text is consumed as an answer. Refs #4923 Signed-off-by: ruiconti <1834568+ruiconti@users.noreply.github.com>
Refs #4923
Within a turn the principal is now fixed, and only its claims may update. Only the turn's own principal can answer a pending
ctx.ask()orask_questionby typing; anyone else's text waits and runs as its own turn. A typed answer from the turn's principal updatesctx.session.auth.current, so itsdelivery.consumedhooks and the rest of the turn see the request that sent it, also when its payload carries channel state or client context besides the text. Stacked on the repro in #4924; this PR removes itsit.failsmarkers.Why
Text-answer routing did not check who sent the text. While a turn waits on a question, every admitted delivery is offered to its open prompts, so another person's text could answer it. On
mainthe turn then continued on the asker's auth; a fix that only movedauth.currentto the answer's sender would have switched the turn to that other person mid-turn. Steering already enforces the rule this needs: only the turn's own principal joins a running turn.Approach
isSteeringDeliveryagainst the turn's principal) for every relay route: a workflow tool'sctx.ask(), a subagent and a remote agent. Text from anyone else stays in the parent's queue as an ordinary message.continueTurnAuth(execution/session/principal.ts): the typed-answer join inproxied-deliver-step.ts(joinAnswerToTurn) and the turn step's join inturn-step.ts. It updates the claims of the turn's own principal and throws if another principal's message gets past a gate, so a future path that forgets the gate fails loudly instead of running someone's text under someone else's auth.continue). The resumed turn takes its owner from the persisted session auth, not from the answer's sender, so alice's text keeps steering it and bob's text waits instead of failing the session.attributeAnswersgets the open turn's owner. Each answer to an open approval carries its responder, and another principal's answer to a request that is no longer open is dropped instead of becoming text the open turn reads or making that sender the caller.Docs
docs/concepts/security-model.mdgets a short section on the rule, and the "What reachesctx.session.auth" section of the auth guide and the hooks guide state it.Validation
approved: false,answer: "eu-west", relayed1forwarded to the child), and the same-principal test sees"asking request".hook-cancellationandedge-casesintegration files, all four repros included.edge-cases.integration.test.tsadds a regression test where bob types while alice's turn is parked on its session-limit prompt and alice declines. Bob's text runs as his ownturn_2. This already holds on currentmain, so the earlierSessionInputQueue.takeNextchange is no longer part of this PR.hook-cancellation.integration.test.tsruns the same-principal typed answer with only text, with channelstate, and with client context. The last two kept the asking request's claims before this fix (turn.settledsaw"asking request") because the extra fields left a remainder for the parent session, which skipped the claims update.edge-cases.integration.test.tsadds a test where bob types while alice's turn waits on her approval. Alice approves, her turn completes, and bob's text runs as his ownturn_1.parkedwait only runs between turns. An instrumented run of theexecution,harness,runtime,channel,client,eve-channel,reactions,internalandpublicintegration tiers never parked with an open turn.approval-caller.integration.test.ts, new: bob's delivery carries a stale answer with text plus a live approve on alice's requester-only approval. Alice stays the caller and turn auth throughout, nothing settles, and bob's text never reaches the model. Red onmain(callers[bob, alice]).turn.test.ts: bob'scontinueanswer resumes alice's parked turn; while it runs, alice's pumped text signals steering and bob's does not.principal.test.tscoverscontinueTurnAuth: claims update, input without auth, and refusal for another principal id, another issuer, and an anonymous caller.8229 passed | 1 skipped. Integration tier, run per directory (execution228,public834,runtime90,harness95, pluschannel,client,eve-channel,reactions,internal) → all pass.tsc --noEmit,oxlintandoxfmtpass.