Skip to content

refactor(client): share one conversation client across the store and hooks - #3879

Open
OwenKephart wants to merge 6 commits into
refactor/client-stable-part-idsfrom
refactor/shared-conversation-client
Open

OwenKephart wants to merge 6 commits into
refactor/client-stable-part-idsfrom
refactor/shared-conversation-client

Conversation

@OwenKephart

@OwenKephart OwenKephart commented Sep 27, 2026 •

Copy link
Copy Markdown
Contributor

Summary

EveAgentStore, the framework hooks, and the eve dev TUI each tracked session lifecycle on their own. Store decisions came from raw events, and subagent following existed only in the TUI. The store now delegates the root stream, deduplication, cursors, projections, and agent-session following to one ConversationClient. It keeps a canonical ConversationState (messages, root turns, input requests, tasks, and agent sessions) next to a custom reducer's data.

A turn held by working tasks stays streaming with turns[turnId].waiting set, and the store accepts answers while a turn runs. followSubagents: true follows each agent tool's session into conversation.agents; it is off by default. The store also gains a client option plus compact(), clear(), and retire(); retire() needs a store-owned session and rejects for a caller-supplied session.

Breaking: default hooks return ConversationState instead of EveMessageData.

On top of #3878; #3880 moves the TUI onto this store, and #3986 later backs ConversationState's lifecycle with the session projection #4044 adds. Stack: #3878 → #3879 → #3880 → #3965 → #4018 → #4044 → #3986, with #3977 on top. The client design is in #3922; the server design is in research/turn-state.md (#4018) and research/session-stream-contract.md (#4044).

Bugs fixed

  • Sending a second message while the first was still creating the session threw "A session is required before opening its stream."
  • When one model step asked to approve two tools, approving the first left the store busy, since the server sends no boundary until the batch completes. The store and web chat scaffold refused answers while busy, so the second approval could never be answered.
  • In that partial batch, the approval that was already approved became clickable again after an unrelated turn ended, because the scaffold only saw an answer once the whole batch resolved.
  • Answering a request the server had already settled left the store submitted forever. It now rejects locally with "already answered".
  • A steered message appeared below the reply it steered until the server confirmed it.
  • With a slow prepareSend, the user's message didn't appear until it resolved.
  • When two callback-backed authorizations for the same connection were pending, the first completion cleared both. The session looked idle while the second was still waiting.
  • MessageResponse.result().inputRequests listed requests that had already settled within the same response.
  • A steered message's send() resolved when its turn asked for a callback-backed sign-in, instead of waiting for the callback like an ordinary send.

Out of scope, on the server side:

  • A partially answered approval batch still sends no boundary, so the UI shows the agent as working until the batch completes.
  • When an agent tool starts two parallel subagents that each need approval, both approvals reach the root, but the answer to the first is dropped. That task never settles and the root turn stays held. The same two approvals directly under the root settle normally. fix(subagents): route answers to every batch a subagent has open #3941 fixes this on the server.

Validation

  • Rebased onto main at e9dd418: tsc passes, and the unit suite passes at this branch (8,783 passed, 1 skipped) apart from the sandbox OIDC fallback test that also fails on main.

Before the rebase:

  • pnpm typecheck, pnpm lint, pnpm fmt, pnpm guard:invariants, pnpm docs:check, git diff --check
  • pnpm --filter eve check:web-template
  • Unit suite: 799 files, 8,634 passed, 1 skipped, with the tasks stack's TUI running on this client
  • Integration suite: 128 files, 978 passed
  • After keeping kind on ConversationTask: tsc, pnpm guard:invariants, and unit tests for src/client and the framework hooks (22 files, 314 passed)
  • Before the split, EveAgentStore against mock-model eve dev servers:
    • A two-approval batch. The second approval was accepted while the first settled, and re-answering the first was rejected locally.
    • Parallel subagent approvals, under the agent tool and directly under the root. This reproduced the server stall above and showed that followSubagents follows the agent session.

Checklist

  • This change was requested or approved by a maintainer
  • I ran the relevant checks from CONTRIBUTING.md
  • I added tests and documentation where relevant
  • I added a changeset if this touches the published eve package
  • DCO sign-off passes for every commit (git commit --signoff)

@vercel

vercel Bot commented Sep 27, 2026 •

Copy link
Copy Markdown
Contributor

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

Project Deployment Actions Updated
eve-docs Ready Ready Preview, v0 Sep 30, 2026 6:12pm UTC
1 Skipped Deployment
Project Deployment Actions Updated
eve-pkg Skipped Skipped v0 Sep 30, 2026 6:12pm UTC

@github-actions

github-actions Bot commented Sep 27, 2026 •

Copy link
Copy Markdown
Contributor

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

Key takeaways

  • No notable deltas vs refactor/client-stable-part-ids (10b054a).

Delta vs refactor/client-stable-part-ids (10b054a)

Area Metric Baseline Current Delta
Package Packed tarball 8.44 MB 8.45 MB +18.7 kB ⚠️
Package Unpacked publish size 30.97 MB 31.04 MB +71.8 kB ⚠️
Package Installed footprint 77.78 MB 77.85 MB +71.8 kB ⚠️
Package Published files 3898 3908 +10
Package Installed files 7878 7888 +10
Package Installed package instances 33 33 0
Package Distinct installed package names 32 32 0
Package Installed dependency edges 51 51 0
Package Installed optional peer edges 9 9 0
Runtime Unique function payloads 2 2 0
Runtime Total function bytes 19.09 MB 19.09 MB -80 B ✅
Runtime Public routes 17 17 0
Changed function payloads vs refactor/client-stable-part-ids (10b054a) (2)
Function Status Baseline Current Delta Route changes
functions/__server.func changed 9.55 MB 9.55 MB -40 B ✅ none
functions/.well-known/workflow/v1/flow.func changed 9.55 MB 9.55 MB -40 B ✅ none

eve init install

Metric Baseline Current Delta
Installed footprint 116.07 MB 116.15 MB +71.8 kB ⚠️
Installed packages 97 97 0
dependencies 4 4 0
devDependencies 2 2 0
Dependency package bytes 48.41 MB 48.48 MB +71.8 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-09-30T18:12:07.633Z
  • Route aliases: 17 public, 1 internal (18 total aliases)
  • Vercel routes in config: 20
  • Severity legend: 🔴 dominant/large, 🟠 notable, 🟡 watch, ⚪ small
Package Drill-Down

Package Details

  • Package: eve@0.68.0
  • Package directory: packages/eve
  • Tarball: 8.45 MB (eve-0.68.0.tgz)
  • Unpacked payload: 31.04 MB across 3908 published files
  • Installed footprint: 77.85 MB across 7888 installed files
  • Installed root package: 30.75 MB
  • Installed dependencies: 47.10 MB
  • Installed package instances: 33
  • Distinct installed package names: 32
  • Installed dependency edges: 51
  • Installed optional peer edges: 9
  • Runtime dependencies: 2
  • Peer dependencies: 7 (6 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: 30.75 MB (39.5%)
  • @rolldown/binding-linux-x64-gnu: 19.47 MB (25.0%)
  • ai: 7.78 MB (10.0%)
  • zod: 6.14 MB (7.9%)
  • undici: 3.52 MB (4.5%)
Publish payload breakdown
Published file size
🔴 dist/src/compiled/shadcn-registry/index.js       [##############..........] 9.70 MB 31.3%
🟠 dist/src/compiled/@photon-ai/chat-adapter-ime... [###.....................] 2.29 MB 7.4%
🟠 dist/src/compiled/@ai-sdk/code-mode/index.js     [#.......................] 1.03 MB 3.3%
🟡 dist/src/compiled/@vercel/blob/index.js          [#.......................] 604.9 kB 1.9%
🟡 dist/src/compiled/_chunks/workflow/signal-exi... [#.......................] 514.5 kB 1.7%
🔴 Other published files                            [########################] 16.90 MB 54.5%
Installed footprint breakdown
Installed package size
🔴 eve                             [########################] 30.75 MB 39.5%
🔴 @rolldown/binding-linux-x64-gnu [###############.........] 19.47 MB 25.0%
🔴 ai                              [######..................] 7.78 MB 10.0%
🔴 zod                             [#####...................] 6.14 MB 7.9%
🟠 undici                          [###.....................] 3.52 MB 4.5%
🟠 nitro                           [#.......................] 1.89 MB 2.4%
🔴 Other installed packages        [######..................] 8.30 MB 10.7%
Runtime dependencies (2)
Package Range Notes
nitro 3.0.260903-beta
undici 8.9.0
Peer dependencies (7)
Package Range Notes
@opentelemetry/api ^1.0.0 optional peer
ai catalog:
braintrust ^3.0.0 optional peer
chat ^4.41.0 optional peer
dd-trace ^6.13.0 optional peer
just-bash ^3.1.0 optional peer
microsandbox ^0.5.0 optional peer
eve init install drill-down

eve init install details

  • Command: eve init my-agent
  • Package manager: npm
  • Installed footprint: 116.15 MB across 9783 installed files
  • Installed packages: 97 total (91 transitive-only)
  • dependencies: 4 direct packages totaling 48.48 MB
  • devDependencies: 2 direct packages totaling 5.11 MB
  • Other transitive package files: 62.55 MB

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

Heavy installed dependencies

  • eve: 30.75 MB (26.5%)
  • @typescript/typescript-linux-x64: 27.95 MB (24.1%)
  • @rolldown/binding-linux-x64-gnu: 19.47 MB (16.8%)
  • zod: 9.76 MB (8.4%)
  • ai: 7.78 MB (6.7%)
Installed footprint breakdown
Installed package size
🔴 eve                              [########################] 30.75 MB 26.5%
🔴 @typescript/typescript-linux-x64 [######################..] 27.95 MB 24.1%
🔴 @rolldown/binding-linux-x64-gnu  [###############.........] 19.47 MB 16.8%
🔴 zod                              [########................] 9.76 MB 8.4%
🔴 ai                               [######..................] 7.78 MB 6.7%
🟠 undici                           [###.....................] 3.52 MB 3.0%
🔴 Other installed packages         [#############...........] 16.93 MB 14.6%
dependencies (4)
Package Range Installed size Share
@vercel/connect 2.2.0 194.7 kB 0.2%
ai ^7.0.105 7.78 MB 6.7%
eve file:eve-0.68.0.tgz 30.75 MB 26.5%
zod 4.5.4 9.76 MB 8.4%
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     [########################] 9.55 MB 50.0%
🔴 functions/__server.func                         [########################] 9.55 MB 50.0%

Top Function Payloads

🟠 functions/.well-known/workflow/v1/flow.func • 1 public route • 9.55 MB
Metric Value
Public routes /.well-known/workflow/v1/flow
Runtime nodejs24.x
Handler index.mjs
Payload 9.55 MB
Function files 9.55 MB across 111 files
Traced dependencies 0 B
Signal 🟠 Bundled file _chunks/vercel.web.mjs is 2.16 MB (22.6%)

🟠 🔎 Dependency Analysis

📦 Bundled files:

Bundled file size
🟠 _chunks/vercel.web.mjs                         [############............] 2.16 MB 22.6%
🟡 _libs/undici.mjs                               [######..................] 980.8 kB 10.3%
🟡 _chunks/sandbox.mjs                            [#####...................] 811.4 kB 8.5%
🟡 _chunks/compiled-artifacts-instrumentation.mjs [####....................] 756.3 kB 7.9%
🟡 _chunks/signal-exit-DZKTacNU.mjs               [###.....................] 616.2 kB 6.5%
🔴 Other bundled files                            [########################] 4.23 MB 44.3%

🧾 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 • 16 public routes, 1 internal alias • 9.55 MB
Metric Value
Public routes /
/.well-known/workflow/v1/webhook/[token]
/eve/v1/activity/[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]/reset
/eve/v1/session/[sessionId]/stream
Internal aliases /__server
Runtime nodejs24.x
Handler index.mjs
Payload 9.55 MB
Function files 9.55 MB across 111 files
Traced dependencies 0 B
Signal 🟠 Bundled file _chunks/vercel.web.mjs is 2.16 MB (22.6%)

🟠 🔎 Dependency Analysis

📦 Bundled files:

Bundled file size
🟠 _chunks/vercel.web.mjs                         [############............] 2.16 MB 22.6%
🟡 _libs/undici.mjs                               [######..................] 980.8 kB 10.3%
🟡 _chunks/sandbox.mjs                            [#####...................] 811.4 kB 8.5%
🟡 _chunks/compiled-artifacts-instrumentation.mjs [####....................] 756.3 kB 7.9%
🟡 _chunks/signal-exit-DZKTacNU.mjs               [###.....................] 616.2 kB 6.5%
🔴 Other bundled files                            [########################] 4.23 MB 44.3%

🧾 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.22 s -> 3.21 s (-10.0 ms) vs refactor/client-stable-part-ids (10b054a).
  • Timing is informational: shared GitHub runners are too variable for a hard timing budget.
Detailed phase timings vs `refactor/client-stable-part-ids (10b054a)`
Phase Baseline Current Delta
extension.check 12.4 ms 12.8 ms +0.4 ms
project.resolve 3.1 ms 5.3 ms +2.2 ms
workspace.create 0.6 ms 3.1 ms +2.5 ms
host.prepare 608.4 ms 543.0 ms -65.4 ms
vercel.service-prefix.resolve 1.1 ms 1.2 ms +0.1 ms
nitro.create 415.7 ms 402.2 ms -13.5 ms
sandbox.prewarm 323.8 ms 326.6 ms +2.8 ms
nitro.cache.prepare 0.2 ms 0.2 ms 0.0 ms
nitro.prepare 0.8 ms 0.6 ms -0.2 ms
nitro.public-assets 0.5 ms 0.5 ms 0.0 ms
nitro.prerender 0.4 ms 0.3 ms -0.1 ms
nitro.bundle 1.72 s 1.78 s +62.5 ms
nitro.cache.write 0.2 ms 0.2 ms 0.0 ms
vercel.workflow-function.materialize 60.9 ms 60.5 ms -0.4 ms
agent-summary.emit 0.6 ms 0.6 ms 0.0 ms
connect-manifest.emit 0.2 ms 0.2 ms 0.0 ms
nitro.close 0.1 ms 0.1 ms 0.0 ms
output.publish 3.8 ms 4.5 ms +0.7 ms
workspace.remove 2.3 ms 2.4 ms +0.1 ms

Comment thread packages/eve/src/client/eve-agent-store.ts
Comment thread packages/eve/src/client/conversation-reducer.ts Outdated
Comment thread packages/eve/src/client/eve-agent-store.ts
Comment thread packages/eve/src/client/conversation-client.ts
Comment thread packages/eve/src/client/child-stream-follower.ts Outdated
Comment thread docs/guides/frontend/overview.mdx
Comment thread .changeset/shared-conversation-client.md Outdated
Comment thread packages/eve/src/client/eve-agent-store.ts
Comment thread packages/eve/src/client/eve-agent-store.ts
Comment thread packages/eve/src/client/conversation-reducer.ts
…hooks

Signed-off-by: owenkephart <owen.kephart@vercel.com>
…s internal

Signed-off-by: owenkephart <owen.kephart@vercel.com>
Six readers decided where a read of session events stops, each with its own
copy of the bookkeeping: the session's response reader, collectTurnEvents,
summarizeTurnEvents, the evals session, the test stream helper, and the
store's steered-turn follower. The copies had drifted. Only the response
reader read past a session.waiting while a sign-in callback was outstanding,
and summarizeTurnEvents settled requests on approval.settled for the list it
returned but not for the boundary it reported.

endsTurnSegment now holds the rule, and TurnSegment tracks what a segment
leaves open for the SDK readers. Readers that follow a turn to its end, the
response reader and the steered-turn follower, read past a parked callback
sign-in; eve invoke and evals still stop there to report it. The store's
catch-up and idle checks apply the same rule to ConversationState, since they
have no response to scope a segment to.

A steered follow-up now settles after its sign-in callback resumes the turn,
as the first message's response already did.

Signed-off-by: owenkephart <owen.kephart@vercel.com>
ConversationClient repeated the same check, whether the canonical conversation shares data's projection, before each append and reset. It now writes through the projections list it already exposes, so the shared-projection case lives in one getter.

Signed-off-by: owenkephart <owen.kephart@vercel.com>
`ConversationTask` now keeps the `kind` that `task.started` carries. Following decided whether a session was an agent tool's own by comparing the task's tool name with the agent's name, in two places. One `agentToolTask` check now reads `kind === "agent"` instead, which is how the protocol says a client tells an agent call from an authored tool that opens sessions with `ctx.agent`.

The task-start test fixtures now pass the `kind` the event requires.

Signed-off-by: owenkephart <owen.kephart@vercel.com>
Signed-off-by: owenkephart <owen.kephart@vercel.com>

This branch was successfully deployed

1 active and 1 inactive deployments
Preview – eve-docs — 1d347bb4 Deployed Sep 30, 2026 by vercel[bot]
Preview – eve-pkg — 1d347bb4 Deployed Sep 30, 2026 by vercel[bot]
Sign up for free to 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.

2 participants