chore(web): upgrade eve from 0.53.1 to 0.74.0
Moves eve from 0.53.1 to 0.74.0 in apps/web and apps/web/eve, with the lockfile, and adapts the planning brain to what changed in between. Nothing is adopted: no sandbox, no code extension, no web_search. defaultTools: false, the tool set, the per-step model, and the "*" relay hook are as they were.
Breaking changes handled (Eve changelog 0.53.1 ā 0.74.0)
| Eve | Change | What this PR does |
|---|---|---|
| 0.54.1 | The task_update tool is removed. A disableTool() on a slot with no default fails the build. | Deletes eve/subagents/worker/tools/task_update.ts. |
| 0.66.0 | ctx.getSkill() is removed from ToolContext. | The three ToolContext fakes in tests drop it. |
| 0.69.0 | Background tasks are removed. Every subagent call is a task the turn waits on: a receipt at once, the result as a task.result message inside the same turn, turn.waiting while the turn parks, and no result ever opens a turn of its own. The subagent.* events are gone. | The relay no longer recognises a wake-up turn (RELAY_TURN.CHILD_COMPLETION, the delegated flag). A parked turn stays one turn on record: the park tells nothing, the steps after the worker's result add to it, and the answer holds the words before and after the wait. The eval and the relay test assert that shape. |
| 0.69.0 | task_wait and task_cancel are framework tools eve adds beside any agent tool; authored tools/task_cancel.ts is rejected. task_cancel takes { taskId }, not { taskIds }; a subagent call continues a child by taskId, not agentId. | Deletes the task_cancel re-export; the hosted tool set declares task_wait and the new input shapes; the planning prompt says taskId. |
| 0.69.0 | A subagent call is announced on the stream as a subagent-call action, not a tool-call. | The relay reads it as the call of the tool its result names, so the tool-worker part is kept as before. |
| 0.69.0 | session.cancel() loses its tasks option and always cancels every working task. The route answers 202 for accepted. | The cancel body no longer carries tasks: true. |
| 0.69.0 | ToolContext gains messages. | The fakes carry it. |
| 0.72.0 | Eve peers on ai@^7.0.128. | ai 7.0.97 ā 7.0.135 in the catalog and @ai-sdk/openai 4.0.65 ā 4.0.91, which keeps one @ai-sdk/provider in the tree. |
| 0.74 channel | A follow-up to a session whose inbox is still starting answers 409 session_not_ready; one eve no longer runs answers 409 session_not_active. Eve's client retries the first from 250 ms, doubling to 2 s, for up to 20 s, and treats the second as terminal at once. | eve-sessions.ts does the same (Schedule.exponential capped and bounded); the unused delayLadder helper goes. |
Not applicable to Luke, checked: the todo tool removal (0.65), the instrumentation split (0.62), the eval session API (0.59; the eval uses attachSession), durable schema factories (0.59; the hosted tools' JSON schemas are built at module scope), outputSchema on defineAgent (0.67; never set), run modes (0.67), the self-modification split (0.73), schedules (0.74).
The eve build --skip-sandbox-prewarm layout test and the pinned-state test are unchanged and pass: eve 0.74 still reads a session's durable state out of an AsyncLocalStorage on every access, so pinned-state.ts stays.
Where behaviour could not stay the same
Eve 0.69 removed the shape the worker relied on. Before, a worker call ended the planning turn at once and the result woke the session in a child_completion turn, which the voice picked up as a woken run. Now the planning turn stays open until the worker's reply reaches the model inside it. Two consequences, settled with Dean through the orchestrator:
-
The worker's findings land in the planning turn. The relay keeps the parked turn open and records one turn. The voice's woken-turn watcher (
watchWoken,turnsWokenIn) only ever read turns the relay no longer records, and its test drove the old shape through the relay, so the watcher, its store read, and that test are removed.TURN_ORIGIN.CHILD_COMPLETION,OBSERVATION_SOURCE.CHILD_COMPLETION, and the Mac-sideLIVE_BRAIN_RUN_EVENT.WOKENvocabulary stay for rows already on record; removing them is a follow-up. -
The planning channel's turn policy is now
steer. Underqueue, a spoken follow-up that arrives while the worker is still researching would wait for the whole research before Luke read it. The policy is one constant,BRAIN_HOST_TURN_POLICYinchannel.ts, eithersteerorqueue, documented there (the only place it is documented). To makesteersound, the relay now binds an ask whose delivery joins a turn under way the moment eve names it (eve stamps the steering delivery on the follow-up'smessage.receivedand every later event), carries a Stop it took while it waited, ties its spoken line to the turn, and gives a second received line of one turn an id of its own. Two relay tests cover it. A message steers only from the principal the turn runs under, so a typed ask during a spoken turn, and the reverse, still waits.
The scripted comparison behind the default
A temporary probe (not committed) ran the scripted planner under Eve 0.74 with a worker held for ten seconds and posted a follow-up the moment the turn parked. Times are from the session's first event.
steer | queue | |
|---|---|---|
Turn parks on the worker's task (turn.waiting) | +0.25 s | +0.37 s |
| Follow-up posted | +0.26 s | +0.38 s |
Follow-up read by the model (message.received, step.started) | +0.37 s, +0.38 s, in turn_0 | waits |
| Turn parks again | +0.43 s | |
Worker's task.settled | +10.56 s | +10.66 s |
turn_0 completes | +10.62 s, one turn | +10.71 s |
| Follow-up's turn | none needed | turn_1 starts +10.77 s, completes +10.81 s |
Eve 0.74 has no task form that leaves the turn open: task(), serve(), and every agent call hold it, and the docs state no result ever starts a turn on its own, so the old shape could not be kept.
What steer costs: a follow-up that arrives while the model is still generating cuts that call short, and the correction runs in the same turn (that step ends with finishReason: "other").
Known limitation, left as a follow-up
The voice follows a spoken ask for ten minutes (LIVE_BRAIN_FOLLOW_BOUNDS.FOLLOW). Under Eve 0.74 the planning turn is held, under either policy, until the worker settles, so a worker that researches for longer than that ends the ask's follow as failed and its findings, though on record, are not spoken. Before, the wake-up turn only started once the worker had finished. The fix is a follow bound that knows the turn is parked on a task, which belongs to the voice service rather than this upgrade.
Deploying
Eve 0.69 rejects session handoffs across this upgrade boundary in both directions. A planning session opened on the old deployment is not continued by the new one; Luke's follow-up reads it as retired and opens a new session seeded from the record, which is the rotation that already exists.
Verification
./scripts/check.shexits 0.pnpm --filter @luke/web test:storeandpnpm --filter @luke/web test:agentpass on a local PostgreSQL 17 (the same order CI runs them in).pnpm exec eve build --skip-sandbox-prewarmbuilds the agent underVERCEL=1.
š¤ Generated with Claude Code